Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

license-plate, validator, regex, europe, anpr, vehicle, car, nodejs, typescript, php, italy, germany, france, spain, uk, poland, netherlands, belgium, scandinavia, balkans, ukraine

License

Notifications You must be signed in to change notification settings

CodeCornTech/euro-plate-validator

Repository files navigation

๐ŸŒ @codecorn/euro-plate-validator

๐Ÿš— European license plate validator (Russia excluded). Multi-country, regex-based validation for EU/EEA license plates. Works in Node.js, TypeScript, and the browser (with a lightweight UI client).

Lang: IT Demo


@codecorn/euro-plate-validator npm downloads jsDelivr GitHub stars

CI Tests issues min minzip Types module cdn License


โœจ Features

  • โœ… Multi-country support (25+ EU/EEA)
  • ๐Ÿšซ Russia excluded by design
  • ๐Ÿ”  Normalizes input (spaces, hyphens, case)
  • ๐Ÿง  Smart regex engine per-country (car/motorcycle aware)
  • ๐Ÿงฉ Lightweight client SDK with UI, flags, dropdown, and Inputmask integration
  • โ†•๏ธ Accepts lowercase input, auto-coerced to UPPERCASE by mask token L
  • ๐ŸŒ Built-in i18n: IT and EN
  • ๐Ÿงฏ Safe dependency autoload via CDN with configurable overrides

๐Ÿ“ฆ Installation

npm install @codecorn/euro-plate-validator

๐Ÿ”— CDN (v1.0.15)

Use versioned URLs to avoid stale CDN caches.

Core module

  • ESM (browser) https://cdn.jsdelivr.net/npm/@codecorn/euro-plate-validator@1.0.15/dist/browser/index.esm.js

  • IIFE (global window.EuroPlateValidator) https://cdn.jsdelivr.net/npm/@codecorn/euro-plate-validator@1.0.15/dist/browser/index.iife.min.js

Client SDK (UI)

  • ESM https://cdn.jsdelivr.net/npm/@codecorn/euro-plate-validator@1.0.15/dist/client/index.mjs

  • CJS (Node) https://cdn.jsdelivr.net/npm/@codecorn/euro-plate-validator@1.0.15/dist/client/europlate.client.cjs

Assets (CSS)

  • https://cdn.jsdelivr.net/npm/@codecorn/euro-plate-validator@1.0.15/dist/assets/css/styles.css
  • (compat alias) .../assets/css/styles.css

๐Ÿง  Core API

Node.js / TypeScript

import { validatePlate } from "@codecorn/euro-plate-validator";
// Italy (car)
validatePlate("AB 123 CD", ["IT"], { vehicleType: "car" });
// โ†’ { isValid: true, matches: [{country:"IT", name:"Italy"}], checked:["IT"] }
// UK vs IE
validatePlate("AB12 CDE", ["UK", "IE"]);

๐Ÿงฉ Browser Client SDK โ€” createEuroPlate()

The browser client auto-generates a full UI (flag + input + dropdown + status) or attaches to an existing <input>. ecco la versione EN tradotta 1 : 1 . Ho lasciato il codice invariato , e ho applicato lo spazio prima / dopo la punteggiatura solo al testo in prosa .


๐Ÿง  Core API ( Node / TS )

import { validatePlate } from "@codecorn/euro-plate-validator";
// IT (car)
validatePlate("AB 123 CD", ["IT"], { vehicleType: "car" });
// โ†’ { isValid: true, matches:[{country:"IT", name:"Italy"}], checked:["IT"] }
// UK vs IE
validatePlate("AB12 CDE", ["UK", "IE"]);

๐Ÿงฉ Client SDK ( UI ) โ€” createEuroPlate

The client either generates the markup ( flag + input + country dropdown + status ) or attaches to an existing input .

Main options ( including new ones )

type EuroPlateOptions = {
 // DOM
 input?: HTMLInputElement; // external input
 wrapper?: string | HTMLElement | false; // if provided โ†’ auto-build UI
 inputId?: string; // default: derived ( e.g., "epv-xxxx-plate" )
 inputName?: string; // default: same
 preserveInputAttrs?: boolean; // NEW: if true, does NOT overwrite existing id/name
 autoFocusOnInit?: boolean; // NEW: default false ( no focus on init )
 // โš™๏ธ UI configuration ( new: EVERYTHING under "ui" )
 ui?: {
 /**
 * Where to show the status :
 * - "block" โ†’ uses <div class="status"> under the input ( back-compat , default )
 * - "inline" โ†’ overlays inside the input , does not change height
 * - "off" โ†’ hides status text / icon
 */
 statusMode?: "block" | "inline" | "off"; // default: "block"
 /** Icon type for inline status ( ignored in "block" and "off" ) */
 statusIcon?: "none" | "icon" | "pill"; // default: "none"
 /** Whether to show status text */
 showStatusText?: boolean; // default: blockโ†’true , inlineโ†’false
 /** Inline icon position */
 iconPosition?: "right" | "left"; // default: "right"
 // Optional references to existing nodes ( when NOT using wrapper )
 flagIcon?: HTMLElement;
 flagLabel?: HTMLElement;
 dropdown?: HTMLElement;
 button?: HTMLElement;
 status?: HTMLElement;
 };
 // UX / i18n
 mode?: "AUTO" | string; // fixed country or AUTO ( default )
 i18n?: "AUTO" | "IT" | "EN"; // default AUTO โ†’ navigator it / en
 allowedCountries?: string[]; // whitelist ; default : all
 vehicleType?: "any" | "car" | "bike"; // default : any
 placeholders?: { auto?: string }; // placeholder for AUTO
 // Normalization / formatting
 normalize?: (code: string) => string; // default GBโ†’UK
 formatters?: Record<string, (s: string) => string>; // per country code
 // Timings
 timings?: { debounce?: number; clear?: number };
 // Dependencies / logging
 deps?: { inputmask?: any }; // manual inject ( e.g., window.Inputmask )
 autoLoadDeps?: { inputmask?: boolean }; // default : true ( autoload UMD )
 cdn?: { inputmask?: string }; // override Inputmask CDN URL
 logger?: Logger;
 debug?: boolean;
};

Values and defaults ( UI )

Key Type Values Default Notes
ui.statusMode "block" | "inline" | "off" block / inline / off "block" block uses <div class="status"> , inline overlays inside the input , off hides UI
ui.statusIcon "none" | "icon" | "pill" none / icon / pill "none" used only when statusMode is inline
ui.showStatusText boolean true / false blockโ†’true , inlineโ†’false short text in inline ; full text in block
ui.iconPosition "right" | "left" right / left "right" icon position for inline
ui.status HTMLElement ( optional ) โ€” auto created / derived existing host for status when you do not use wrapper
ui.button / dropdown / flagIcon / flagLabel HTMLElement ( optional ) โ€” auto created if wrapper for re-using external DOM

Instance methods

type EuroPlateInstance = {
 setCountry(code: "AUTO" | string): void; // alias of setMode
 setMode(m: "AUTO" | string): void; // set fixed country or AUTO
 setAllowed(codes: string[]): void; // dynamic whitelist
 setVehicleType(t: "any" | "car" | "bike"): void;
 setI18n(code: "AUTO" | "IT" | "EN"): void;
 setDebug(on: boolean): void;
 validate(): { ok: boolean; country?: string; value: string };
 destroy(): void;
 getI18n(): "it" | "en";
};

๐Ÿ–ผ๏ธ Usage examples

A ) Quick start with a shared common config + autoload deps ( Inputmask , jQuery , Toastr )

<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@codecorn/euro-plate-validator@1.0.15/dist/assets/css/styles.css" />
<div id="plateBox"></div>
<script type="module">
 import * as EuroMod from "https://cdn.jsdelivr.net/npm/@codecorn/euro-plate-validator@1.0.15/dist/browser/index.esm.js";
 import { createEuroPlate } from "https://cdn.jsdelivr.net/npm/@codecorn/euro-plate-validator@1.0.15/dist/client/index.mjs";
 // Common options used across examples
 const common = {
 mode: "AUTO",
 i18n: "IT",
 allowedCountries: ["IT", "FR", "DE", "ES"],
 vehicleType: "any",
 autoFocusOnInit: false,
 ui: {
 statusMode: "inline",
 statusIcon: "icon",
 showStatusText: true, // | false
 iconPosition: "right",
 },
 // Autoload deps (UMD) from CDN
 autoLoadDeps: { inputmask: true, jquery: true, toastr: true },
 // Optional : route logs to Toastr if available
 useToastrLogger: true,
 debug: true,
 };
 createEuroPlate(EuroMod, {
 wrapper: "#plateBox", // optional
 ...common,
 });
</script>

Notes :

  • With autoLoadDeps.jquery: true and autoLoadDeps.toastr: true the client will fetch UMD builds from CDN when missing .
  • useToastrLogger: true sends SDK logs and validation notices to Toastr if it is present ( either auto-loaded or injected ) .
  • jQuery is not required by the core validator ; it is only pulled if your page / widgets rely on it .

B ) You provide Inputmask manually ( UMD โ†’ window.Inputmask )

<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@codecorn/euro-plate-validator@1.0.15/dist/assets/css/styles.css" />
<script src="https://cdn.jsdelivr.net/npm/inputmask@5.0.9/dist/inputmask.min.js"></script>
<script type="module">
 import * as EuroMod from "https://cdn.jsdelivr.net/npm/@codecorn/euro-plate-validator@1.0.15/dist/browser/index.esm.js";
 import { createEuroPlate } from "https://cdn.jsdelivr.net/npm/@codecorn/euro-plate-validator@1.0.15/dist/client/index.mjs";
 createEuroPlate(EuroMod, {
 wrapper: "#plateBox",
 i18n: "AUTO",
 autoFocusOnInit: false,
 deps: { inputmask: window.Inputmask }, // manual inject
 });
</script>

C ) Autoload deps from CDN ( default , Inputmask only )

<script type="module">
 import * as EuroMod from "https://cdn.jsdelivr.net/npm/@codecorn/euro-plate-validator@1.0.15/dist/browser/index.esm.js";
 import { createEuroPlate } from "https://cdn.jsdelivr.net/npm/@codecorn/euro-plate-validator@1.0.15/dist/client/index.mjs";
 createEuroPlate(EuroMod, {
 wrapper: "#plateBox",
 i18n: "AUTO",
 autoFocusOnInit: false,
 // No deps object โ†’ will autoload Inputmask UMD from jsDelivr
 });
</script>

D ) Autoload ON with a custom CDN URL

createEuroPlate(EuroMod, {
 wrapper: "#plateBox",
 cdn: { inputmask: "https://unpkg.com/inputmask@5.0.9/dist/inputmask.min.js" },
});

E ) Disable autoload ( "no mask" fallback , no error )

createEuroPlate(EuroMod, {
 wrapper: "#plateBox",
 autoLoadDeps: { inputmask: false },
});

F ) Attach to an existing input ( no auto-build )

<input id="myPlate" />
<script type="module">
 import * as EuroMod from ".../index.esm.js";
 import { createEuroPlate } from ".../index.mjs";
 createEuroPlate(EuroMod, {
 input: document.getElementById("myPlate"),
 inputName: "plate_number",
 preserveInputAttrs: true, // do NOT overwrite existing id/name
 i18n: "EN",
 mode: "AUTO",
 autoFocusOnInit: false,
 });
</script>

๐Ÿงฉ WordPress ( WP ) / Elementor

1 ) Enqueue CSS + init helper ( type = "module" )

add_action('wp_enqueue_scripts', function () {
 wp_register_script('epv-init', '', [], null, true);
 wp_enqueue_style(
 'epv-styles',
 'https://cdn.jsdelivr.net/npm/@codecorn/euro-plate-validator@1.0.15/dist/assets/css/styles.css',
 [],
 '1.0.15'
 );
 add_filter('script_loader_tag', function ($tag, $handle) {
 if ($handle === 'epv-init') {
 return '<script type="module">' .
 'import * as EuroMod from "https://cdn.jsdelivr.net/npm/@codecorn/euro-plate-validator@1.0.15/dist/browser/index.esm.js";' .
 'import { createEuroPlate } from "https://cdn.jsdelivr.net/npm/@codecorn/euro-plate-validator@1.0.15/dist/client/index.mjs";' .
 'window.__epvInit=(id,opts)=>createEuroPlate(EuroMod,Object.assign({wrapper:"#"+id,mode:"AUTO",i18n:"IT",debug:true,autoFocusOnInit:false},opts||{}));' .
 '</script>';
 }
 return $tag;
 }, 10, 2);
 wp_enqueue_script('epv-init');
});

โš™๏ธ WordPress / Elementor integration

You can enqueue the CSS and auto-inject a window.__epvInit bootstrapper.

Then, create a shortcode to instantiate it dynamically inside Elementor.

Full example available in the Italian README โ†’ "WordPress (WP) / Elementor" section.


๐Ÿงช CLI Tool

npx @codecorn/euro-plate-validator "AB 123 CD" --countries IT,FR,DE --type car --pretty

Options:

  • --countries / -c โ†’ comma-separated list of country codes
  • --type / -t โ†’ car, motorcycle, or any
  • --pretty / -p โ†’ human-readable output

Exit codes:

  • 0 โ†’ valid
  • 1 โ†’ invalid
  • 2 โ†’ bad arguments

๐ŸŒ Supported Countries

๐Ÿ‡ฎ๐Ÿ‡น IT | ๐Ÿ‡ฌ๐Ÿ‡ง UK | ๐Ÿ‡ฉ๐Ÿ‡ช DE | ๐Ÿ‡ซ๐Ÿ‡ท FR | ๐Ÿ‡ช๐Ÿ‡ธ ES | ๐Ÿ‡ต๐Ÿ‡น PT | ๐Ÿ‡ณ๐Ÿ‡ฑ NL | ๐Ÿ‡ง๐Ÿ‡ช BE | ๐Ÿ‡จ๐Ÿ‡ญ CH | ๐Ÿ‡ฆ๐Ÿ‡น AT | ๐Ÿ‡ฎ๐Ÿ‡ช IE | ๐Ÿ‡ฑ๐Ÿ‡บ LU ๐Ÿ‡ฉ๐Ÿ‡ฐ DK | ๐Ÿ‡ธ๐Ÿ‡ช SE | ๐Ÿ‡ณ๐Ÿ‡ด NO | ๐Ÿ‡ซ๐Ÿ‡ฎ FI | ๐Ÿ‡ต๐Ÿ‡ฑ PL | ๐Ÿ‡จ๐Ÿ‡ฟ CZ | ๐Ÿ‡ธ๐Ÿ‡ฐ SK | ๐Ÿ‡ญ๐Ÿ‡บ HU | ๐Ÿ‡ท๐Ÿ‡ด RO | ๐Ÿ‡ง๐Ÿ‡ฌ BG | ๐Ÿ‡ธ๐Ÿ‡ฎ SI | ๐Ÿ‡ญ๐Ÿ‡ท HR | ๐Ÿ‡ฌ๐Ÿ‡ท GR ๐Ÿ‡ฑ๐Ÿ‡น LT | ๐Ÿ‡ฑ๐Ÿ‡ป LV | ๐Ÿ‡ช๐Ÿ‡ช EE | ๐Ÿ‡บ๐Ÿ‡ฆ UA


๐Ÿงพ Changelog (highlights)

1.0.15

  • Inputmask

    • Safe merge of definitions (no hard override of defaults).
    • New L token (letter) accepts lowercase and forces UPPERCASE (casing: "upper").
    • Avoid redefining A/9; use H (IT) / C (ES) only when needed.
    • applyMaskNow applied immediately on country change (no debounce race).
    • Finalized placeholders via finalizeInputMaskLayouts + scripts/test-placeholders.mjs.
  • Client SDK

    • Centralized logging (imLog, imPreLog, imMounted, imError) using BADGE/LOG when debug: true.
    • Lowercase input supported across layouts with L token.
    • Examples updated with autoLoadDeps: { inputmask: true, jquery: true, toastr: true } and useToastrLogger: true.
  • Docs

    • CDN bumped to 1.0.15.
    • Notes about lowercase acceptance and uppercase coercion.
    • Guidance to not override A/9 and define only custom tokens for restricted alphabets.

1.0.13

  • Status inline configurabile

    • statusMode: "inline" | "block" | "off"
    • statusIcon: "none" | "icon" | "pill"
    • showStatusText: boolean
    • iconPosition: "left" | "right"
  • Riserva spazio automatica via :has([data-state])

  • Nessuno stato su campo vuoto / parziale

  • Fix cambio paese (ITโ†”FR) e Inputmask merge (A/H/9)

  • Refactor UI status (setValidityUI unico writer)

  • Add clearStatusUI() per idle neutro


1.0.12

  • NEW โ†’ autoFocusOnInit (default: false) โ€” prevents autofocus on init.
  • NEW โ†’ preserveInputAttrs โ€” keeps external input id/name intact.
  • UX โ†’ renamed CSS classes from .iti__* โ†’ .epv__*.
  • Dependencies โ†’ auto-loads Inputmask UMD via CDN; supports manual injection and CDN override.
  • I18n โ†’ IT / EN / AUTO (auto-detect from browser locale).
  • UX stability โ†’ dynamic placeholder, country-based formatter, debounce system.

1.0.10โ€“11

  • CSS/Assets consolidation.
  • Added Client SDK + autoload fallback.
  • Updated README, docs, and npm package.

๐Ÿ“ License

MIT ยฉ CodeCornTM โ€” see LICENSE


๐Ÿ‘ค Maintainer

Federico Girolami Full-Stack Developer โ€ข System Integrator โ€ข Digital Solution Architect ๐Ÿš€ ๐ŸŒ codecorn.it ๐Ÿ“ง f.girolami@codecorn.it ๐Ÿ™ github.com/fgirolami29


๐Ÿค Contributing

Pull requests are welcome. For major changes, please open an issue first.

Powered by CodeCornTM ๐Ÿš€


AltStyle ใซใ‚ˆใฃใฆๅค‰ๆ›ใ•ใ‚ŒใŸใƒšใƒผใ‚ธ (->ใ‚ชใƒชใ‚ธใƒŠใƒซ) /