Skip to content

About

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

Topics

Resources

Stars

4 stars

Watchers

1 watching

Forks

Latest commit

 

History

87 Commits

Folders and files

Repository files navigation

🌍 @codecorn/euro-plate-validator

🚗 Syntax-only license plate validator for European and nearby countries, including Moldova and Ukraine (Russia excluded). Supports Node.js, TypeScript, browser and PHP.

Lang: IT Demo


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

CI Tests issues min minzip Types module cdn License


✨ Features

  • ✅ 30 supported countries, including Moldova (MD) — automatic or fixed-country mode
  • 🚫 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.16 — after npm publication)

v1.0.16 CDN assets will be available after npm publishing. Use versioned URLs to avoid stale caches.

Core module

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

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

Client SDK (UI)

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

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

Assets (CSS)

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

🧠 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.16/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.16/dist/browser/index.esm.js";
  import { createEuroPlate } from "https://cdn.jsdelivr.net/npm/@codecorn/euro-plate-validator@1.0.16/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.16/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.16/dist/browser/index.esm.js";
  import { createEuroPlate } from "https://cdn.jsdelivr.net/npm/@codecorn/euro-plate-validator@1.0.16/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.16/dist/browser/index.esm.js";
  import { createEuroPlate } from "https://cdn.jsdelivr.net/npm/@codecorn/euro-plate-validator@1.0.16/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.16/dist/assets/css/styles.css',
    [],
    '1.0.16'
  );

  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.16/dist/browser/index.esm.js";' .
        'import { createEuroPlate } from "https://cdn.jsdelivr.net/npm/@codecorn/euro-plate-validator@1.0.16/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

The package supports 30 countries, including Moldova (MD).

🇮🇹 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 | 🇲🇩 MD

🇲🇩 Moldova (MD)

Category Example
Current standard ABC 123
Four-letter legacy AB CD 123
Chișinău C C AB 123
Chișinău K K AB 123
Diplomatic CD 123 AB
Police / MAI MAI 1234
Transnistria T 123 AB
import { validatePlate, getInputMask } from "@codecorn/euro-plate-validator";
validatePlate("ABC 123", ["MD"], { vehicleType: "car" }).isValid; // true
validatePlate("MAI 1234", ["MD"]).isValid; // true
validatePlate("ABC-123", ["MD"]).isValid; // false
getInputMask("MD"); // seven mask variants

Lowercase and compact unspaced forms are supported, but hyphens are not. Validation checks syntax only, not actual registration or legal recognition. AUTO mode may report multiple countries for overlapping patterns. See issue #2.


🧾 Changelog (highlights)

1.0.16

  • Moldova (MD) support: seven plate formats, metadata, flag and IT/EN country labels.
  • PHP validator updated alongside the TypeScript core.
  • Inputmask now preserves arrays of alternative masks.
  • Dedicated positive/negative tests and CI regression coverage.

Upcoming: GitHub release and npm publish after merge. See CHANGELOG.md.

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"
  • Automatic layout space reservation via :has([data-state])

  • No status shown for empty or partial input

  • Fixed country switching (IT↔FR) and Inputmask definitions merging (A/H/9)

  • Refactored status rendering with setValidityUI as the single writer

  • Added clearStatusUI() for a neutral idle state


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 © CodeCorn™ — 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 CodeCorn™ 🚀


About

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

Topics

Resources

Stars

4 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages