[
  {
    "path": ".babelrc",
    "content": "{\n    \"env\": {\n        \"es\": {\n            \"presets\": [\n                [\"@babel/preset-env\", {\n                    \"modules\": false\n                }]\n            ]\n        },\n        \"development\": {\n            \"presets\": [\n                [\"@babel/preset-env\", { \"targets\": { \"node\": \"0.10\" } }]\n            ],\n            \"plugins\": [\n                [\n                    \"add-module-exports\",\n                    {\n                        \"addDefaultProperty\": true\n                    }\n                ]\n            ]\n        }\n    }\n}"
  },
  {
    "path": ".eslintrc.json",
    "content": "{\n  \"extends\": \"airbnb-base\",\n  \"parser\": \"babel-eslint\",\n  \"parserOptions\": {\n    \"ecmaVersion\": 6,\n    \"sourceType\": \"module\"\n  },\n  \"env\": {\n    \"es6\": true,\n    \"browser\": true,\n    \"node\": true,\n    \"mocha\": true\n  },\n  \"rules\": {\n    \"camelcase\": 0,\n    \"no-param-reassign\": 0,\n    \"one-var\": 0,\n    \"one-var-declaration-per-line\": 0,\n    \"func-names\": 0,\n    \"no-console\": 0,\n    \"newline-per-chained-call\": 0,\n    \"prefer-const\": 0,\n    \"linebreak-style\": 0,\n    \"no-restricted-syntax\": [2, \"DebuggerStatement\", \"LabeledStatement\", \"WithStatement\"],\n    \"no-restricted-globals\": 0,\n    \"prefer-destructuring\": 0,\n    \"comma-dangle\": [2, {\n      \"arrays\": \"always-multiline\",\n      \"objects\": \"always-multiline\",\n      \"imports\": \"always-multiline\",\n      \"exports\": \"always-multiline\",\n      \"functions\": \"never\"\n    }],\n    \"no-plusplus\": [2, {\n      \"allowForLoopAfterthoughts\": true\n    }],\n    \"no-prototype-builtins\": 0,\n    \"no-useless-escape\": 0\n  }\n}\n"
  },
  {
    "path": ".github/FUNDING.yml",
    "content": "open_collective: validatorjs\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/bug_report.md",
    "content": "---\nname: Bug report\nabout: Create a report to help us improve\ntitle: ''\nlabels: \"\\U0001F41B bug\"\nassignees: ''\n\n---\n\n**Describe the bug**\nA clear and concise description of what the bug is.\n\n\n**Examples**\nIf applicable, add screenshots to help explain your problem.\n\n**Reproductions**\nIf applicable, provide a reproduction on platforms like [runkit](npm.runkit.com/validator)\n\n**Additional context**\nValidator.js version:\nNode.js version:\nOS platform: [windows, linux, macOS, etc]\n"
  },
  {
    "path": ".github/pull_request_template.md",
    "content": "<!--\nAdd a descriptive title textbox above, e.g.\nfeat(validatorName): brief title of what has been done\n-->\n\n<!--- briefly describe what you have done in this PR --->\n\n<!--- provide some (credible) references showing the structure of the data to be validated, if applicable --->\n\n## Checklist\n\n- [ ] PR contains only changes related; no stray files, etc.\n- [ ] README updated (where applicable)\n- [ ] Tests written (where applicable)\n- [ ] References provided in PR (where applicable)\n"
  },
  {
    "path": ".github/workflows/ci.yml",
    "content": "name: CI\non:\n  push:\n    branches: [master]\n  pull_request:\n    branches: [master]\njobs:\n  test:\n    runs-on: ubuntu-latest\n    strategy:\n      matrix:\n        node-version: [22, 20, 18, 16, 14, 12, 10, 8]\n    name: Run tests on Node.js ${{ matrix.node-version }}\n    steps:\n    - name: Setup Node.js ${{ matrix.node-version }}\n      uses: actions/setup-node@v4\n      with:\n        node-version: ${{ matrix.node-version }}\n    - name: Checkout repository\n      uses: actions/checkout@v4\n    - name: Install dependencies\n      run: npm install --legacy-peer-deps\n    - name: Run tests\n      run: npm test\n    - if: matrix.node-version == 22\n      name: Send coverage info to Codecov\n      uses: codecov/codecov-action@v5\n      with:\n        token: ${{ secrets.CODECOV_TOKEN }}\n"
  },
  {
    "path": ".github/workflows/codeql-analysis.yml",
    "content": "# For most projects, this workflow file will not need changing; you simply need\n# to commit it to your repository.\n#\n# You may wish to alter this file to override the set of languages analyzed,\n# or to provide custom queries or build logic.\n#\n# ******** NOTE ********\n# We have attempted to detect the languages in your repository. Please check\n# the `language` matrix defined below to confirm you have the correct set of\n# supported CodeQL languages.\n#\nname: \"CodeQL\"\n\non:\n  push:\n    branches: [ master ]\n  pull_request:\n    # The branches below must be a subset of the branches above\n    branches: [ master ]\n  schedule:\n    - cron: '38 10 * * 4'\n\njobs:\n  analyze:\n    name: Analyze\n    runs-on: ubuntu-latest\n    permissions:\n      actions: read\n      contents: read\n      security-events: write\n\n    strategy:\n      fail-fast: false\n      matrix:\n        language: [ 'javascript' ]\n        # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ]\n        # Learn more about CodeQL language support at https://git.io/codeql-language-support\n\n    steps:\n    - name: Checkout repository\n      uses: actions/checkout@v4\n\n    # Initializes the CodeQL tools for scanning.\n    - name: Initialize CodeQL\n      uses: github/codeql-action/init@v3\n      with:\n        languages: ${{ matrix.language }}\n        # If you wish to specify custom queries, you can do so here or in a config file.\n        # By default, queries listed here will override any specified in a config file.\n        # Prefix the list here with \"+\" to use these queries and those in the config file.\n        # queries: ./path/to/local/query, your-org/your-repo/queries@main\n\n    # Autobuild attempts to build any compiled languages  (C/C++, C#, or Java).\n    # If this step fails, then you should remove it and run the build manually (see below)\n    - name: Autobuild\n      uses: github/codeql-action/autobuild@v3\n\n    # ℹ️ Command-line programs to run using the OS shell.\n    # 📚 https://git.io/JvXDl\n\n    # ✏️ If the Autobuild fails above, remove it and uncomment the following three lines\n    #    and modify them (or add more) to build your code if your project\n    #    uses a compiled language\n\n    #- run: |\n    #   make bootstrap\n    #   make release\n\n    - name: Perform CodeQL Analysis\n      uses: github/codeql-action/analyze@v3\n"
  },
  {
    "path": ".github/workflows/npm-publish.yml",
    "content": "name: NPM Publish\non:\n  release:\n    types: [created]\njobs:\n  publish:\n    runs-on: ubuntu-latest\n    permissions:\n      contents: read\n      id-token: write\n    steps:\n    - name: Setup Node.js 24\n      uses: actions/setup-node@v5\n      with:\n        node-version: 24\n        registry-url: https://registry.npmjs.org/\n    - name: Checkout Repository\n      uses: actions/checkout@v4\n    - name: Install Dependencies\n      run: npm install --legacy-peer-deps\n    - name: Run Tests\n      run: npm test\n    - name: Publish Package to NPM Registry\n      run: npm publish\n"
  },
  {
    "path": ".gitignore",
    "content": ".DS_Store\nnode_modules\ncoverage\ncoverage.lcov\n.nyc_output\npackage-lock.json\nyarn.lock\n/es\n/lib\n/index.js\nvalidator.js\nvalidator.min.js\n\n"
  },
  {
    "path": ".nycrc",
    "content": "{\n  \"reporter\": [\n    \"html\",\n    \"text-summary\"\n  ],\n  \"include\": [\n    \"src/**/*.js\"\n  ]\n}\n"
  },
  {
    "path": "CHANGELOG.md",
    "content": "# 13.15.26\n\n### Fixes, New Locales and Enhancements\n\n- [#2535](https://github.com/validatorjs/validator.js/pull/2535) `isHexColor`: add `require_hashtag` option @Numbers0689\n- [#2633](https://github.com/validatorjs/validator.js/pull/2633) `isURL`: handle possible bypass with URL-encoded content @WikiRik\n- [#2634](https://github.com/validatorjs/validator.js/pull/2634) `isIBAN`: improve `IR` locale @ds1371dani\n- **Doc fixes and others:**\n  - [#2640](https://github.com/validatorjs/validator.js/pull/2640) @WikiRik\n\n# 13.15.23\n\n### Fixes, New Locales and Enhancements\n\n- **Doc fixes and others:**\n  - [#2631](https://github.com/validatorjs/validator.js/pull/2631) @WikiRik\n\n# 13.15.22\n\n### Fixes, New Locales and Enhancements\n\n- [#2622](https://github.com/validatorjs/validator.js/pull/2622) `isURL`: fix regression with hostnames with ports @mbtools\n- [#2616](https://github.com/validatorjs/validator.js/pull/2616) `isLength`: improve handling Unicode variation selectors @koral--\n- **Doc fixes and others:**\n  - [#2621](https://github.com/validatorjs/validator.js/pull/2621) @mbtools\n\n# 13.15.20\n\n### Fixes, New Locales and Enhancements\n\n- [#2556](https://github.com/validatorjs/validator.js/pull/2556) `isMobilePhone`: add `ar-QA` locale @WardKhaddour\n- [#2576](https://github.com/validatorjs/validator.js/pull/2576) `isAlpha`/`isAlphanuneric`: add Indic locales (`ta-IN`, `te-IN`, `kn-IN`, `ml-IN`, `gu-IN`, `pa-IN`, `or-IN`) @avadootharajesh\n- [#2574](https://github.com/validatorjs/validator.js/pull/2574) `isBase64`: improve padding regex @KrayzeeKev\n- [#2584](https://github.com/validatorjs/validator.js/pull/2584) `isVAT`: improve `FR` locale @iamAmer\n- [#2608](https://github.com/validatorjs/validator.js/pull/2608) `isURL`: improve protocol detection. Resolves CVE-2025-56200 @theofidry\n- **Doc fixes and others:**\n  - [#2563](https://github.com/validatorjs/validator.js/pull/2563) @stoneLeaf\n  - [#2581](https://github.com/validatorjs/validator.js/pull/2581) @camillobruni\n\n# 13.15.15\n\n### Fixes, New Locales and Enhancements\n\n- `isMobilePhone`\n  - [#2514](https://github.com/validatorjs/validator.js/pull/2514) improve `el-CY` locale @rezk2ll\n  - [#2512](https://github.com/validatorjs/validator.js/pull/2512) improve `pt-AO` locale @renaldodev\n  - [#2502](https://github.com/validatorjs/validator.js/pull/2502) improve `ar-OM` locale @tomcastro\n- [#2089](https://github.com/validatorjs/validator.js/pull/2089) `isIP`: allow usage of option object @pixelbucket-dev\n- [#2526](https://github.com/validatorjs/validator.js/pull/2526) `isPassportNumber`: improve `CA` locale @evanbechtol\n- [#2491](https://github.com/validatorjs/validator.js/pull/2491) `isBase64`: improve validation based on RFC4648 @aseyfpour\n- [#2479](https://github.com/validatorjs/validator.js/pull/2479) `isPostalCode`: improve `FR` locale @Rajput-Balram\n- [#2088](https://github.com/validatorjs/validator.js/pull/2088) `isBefore`: allow usage of option object @pixelbucket-dev\n- [#2346](https://github.com/validatorjs/validator.js/pull/2346) `isRgbColor`: allow second digit in rgba alpha value @controlol\n- [#2453](https://github.com/validatorjs/validator.js/pull/2453) `isIP`: improve IPv6 regex @ShreySinha02\n- [#2052](https://github.com/validatorjs/validator.js/pull/2052) `isPostalCode`: add `PK` locale @mateeni-dev\n- [#2529](https://github.com/validatorjs/validator.js/pull/2529) `isPostalCode`: improve `TW` locale @Crocsx\n- [#2550](https://github.com/validatorjs/validator.js/pull/2550) `isPassportNumber`: improve `US` locale @yitzchak-schechter\n- [#2553](https://github.com/validatorjs/validator.js/pull/2553) `isUUID`: add `loose` option @bc-m\n- [#2551](https://github.com/validatorjs/validator.js/pull/2551) `isPostalCode`: add `BD` locale @tanvirrb\n- [#2555](https://github.com/validatorjs/validator.js/pull/2555) `isLicensePlate`: improve `pt-PT` locale @castrosu\n- **Doc fixes and others:**\n  - [#2372](https://github.com/validatorjs/validator.js/pull/2372) @EmersonRabelo\n  - [#2538](https://github.com/validatorjs/validator.js/pull/2538) @WikiRik\n  - [#2539](https://github.com/validatorjs/validator.js/pull/2539) @WikiRik\n  - [#2540](https://github.com/validatorjs/validator.js/pull/2540) @WikiRik\n  - [#2549](https://github.com/validatorjs/validator.js/pull/2549) @WikiRik\n  - [#2537](https://github.com/validatorjs/validator.js/pull/2537) @sgress454\n\n# 13.15.0\n\n### New Features / Validators\n\n- [#2399](https://github.com/validatorjs/validator.js/pull/2399) `isISO31661Numeric` @RobinvanderVliet\n- [#2294](https://github.com/validatorjs/validator.js/pull/2294) `isULID` @arafatkn\n- [#2215](https://github.com/validatorjs/validator.js/pull/2215) `isISO15924` @xDivisionByZerox\n\n### Fixes, New Locales and Enhancements\n\n- `isMobilePhone`\n  - [#2395](https://github.com/validatorjs/validator.js/pull/2395) add `es-GT` locale @ignaciosuarezquilis\n  - [#1971](https://github.com/validatorjs/validator.js/pull/1971) improve `en-GB` locale @ihmpavel\n  - [#2359](https://github.com/validatorjs/validator.js/pull/2359) improve `uk-UA` locale @arttiger\n  - [#2350](https://github.com/validatorjs/validator.js/pull/2350) improve `ky-KG` locale @sadraliev\n  - [#2482](https://github.com/validatorjs/validator.js/pull/2482) improve `en-ZM` locale @sonikishan\n  - [#2362](https://github.com/validatorjs/validator.js/pull/2362) improve `en-GH` locale @NanaAb-116\n  - [#2500](https://github.com/validatorjs/validator.js/pull/2500) add `mk-MK` locale @eshward95\n  - [#2534](https://github.com/validatorjs/validator.js/pull/2534) improve `sq-AL` locale @nichoola\n- [#2406](https://github.com/validatorjs/validator.js/pull/2406) `isBtcAddress` support all address formats and testnets @madoke\n- [#2339](https://github.com/validatorjs/validator.js/pull/2339) `isIBAN` improve `VG` regex @ST-DDT\n- [#2332](https://github.com/validatorjs/validator.js/pull/2332) `isISO4217` update currency codes @cbodtorf\n- [#2291](https://github.com/validatorjs/validator.js/pull/2291) `isIdentityCard` add `PK` locale @Daniyal-Qureshi\n- [#2414](https://github.com/validatorjs/validator.js/pull/2414) `isEmail` fix blacklist_chars @keshavlingala\n- [#2416](https://github.com/validatorjs/validator.js/pull/2416) `isInt`/`isFloat` handle undefined and null values @Daniyal-Qureshi\n- [#2415](https://github.com/validatorjs/validator.js/pull/2415) `isPostalCode` add `CO` locale @jorgevrgs\n- [#2404](https://github.com/validatorjs/validator.js/pull/2404) `isPassportNumber` export `passportNumberLocales` @derekparnell\n- [#2029](https://github.com/validatorjs/validator.js/pull/2029) `isRgbColor` add `allowSpaces` option @a-h-i\n- [#2421](https://github.com/validatorjs/validator.js/pull/2421) `isUUID` require valid variant field and require RFC9562 UUID in version `all` @broofa\n- [#2439](https://github.com/validatorjs/validator.js/pull/2439) `isURL` add `max_allowed_length` option @pinkiesky\n- [#2437](https://github.com/validatorjs/validator.js/pull/2437) `isEmail` reject starting with double quotes @code0emperor\n- [#2333](https://github.com/validatorjs/validator.js/pull/2333) `isLicensePlate` add `en-SG` locale @Sabarinathan07\n- [#2441](https://github.com/validatorjs/validator.js/pull/2441) `normalizeEmail` add `yandex_convert_yandexru` option @AayushGH\n- [#2443](https://github.com/validatorjs/validator.js/pull/2443) `isDate` return false instead of Error in certain cases @pano9000\n- [#2474](https://github.com/validatorjs/validator.js/pull/2474) `isLength` add `discreteLengths` option @Suven-p\n- [#2481](https://github.com/validatorjs/validator.js/pull/2481) `isDate` disallow mismatching length in `strictMode` @sonikishan\n- [#2492](https://github.com/validatorjs/validator.js/pull/2492) `isISO6346` set check digit to 0 if remainder is 10 @joelcuy\n- [#2493](https://github.com/validatorjs/validator.js/pull/2493) `isPostalCode` improve `BR` locale @ticmaisdev\n- [#2494](https://github.com/validatorjs/validator.js/pull/2494) `isEmail` allow regexp in `host_whitelist` and `host_blacklist` @weikangchia\n- [#2518](https://github.com/validatorjs/validator.js/pull/2518) `isIBAN` improve `IE`/`PS` regex @Tarasz57\n- **Doc fixes and others:**\n  - [#2402](https://github.com/validatorjs/validator.js/pull/2402) @BibhushanKarki\n  - [#2394](https://github.com/validatorjs/validator.js/pull/2394) @RobinvanderVliet\n  - [#1732](https://github.com/validatorjs/validator.js/pull/1732) @alguerocode\n  - [#2413](https://github.com/validatorjs/validator.js/pull/2413) @rubiin\n  - [#2408](https://github.com/validatorjs/validator.js/pull/2408) @profnandaa\n  - [#2411](https://github.com/validatorjs/validator.js/pull/2411) @rubiin\n  - [#2325](https://github.com/validatorjs/validator.js/pull/2325) @ovarn\n  - [#2418](https://github.com/validatorjs/validator.js/pull/2418) @ihmpavel\n  - [#2323](https://github.com/validatorjs/validator.js/pull/2323) @ovarn\n  - [#2423](https://github.com/validatorjs/validator.js/pull/2423) @rubiin\n  - [#2409](https://github.com/validatorjs/validator.js/pull/2409) @profnandaa\n  - [#2442](https://github.com/validatorjs/validator.js/pull/2442) @pano9000\n\n# 13.12.0\n\n### New Features / Validators\n\n- [#2143](https://github.com/validatorjs/validator.js/pull/2143) `isAbaRouting` @songyuew\n\n### Fixes, New Locales and Enhancements\n\n- [#2207](https://github.com/validatorjs/validator.js/pull/2207) `isLicensePlate` add Pakistani `en-PK` locale @anasshakil\n- [#2208](https://github.com/validatorjs/validator.js/issues/2208) `isPort` fix invalid leading zeros @anasshakil\n- [#2224](https://github.com/validatorjs/validator.js/pull/2224) `isTaxID` added Argentina `es-AR` locale @estefrare\n- [#2257](https://github.com/validatorjs/validator.js/pull/2257) `isDate` timezone offset fix @tomaspanek\n- [#2265](https://github.com/validatorjs/validator.js/pull/2265) `isPassportNumber` added `ZA` locale @GMorris-professional\n- `isMobilePhone`:\n  - [#2267](https://github.com/validatorjs/validator.js/pull/2267) added `en-MW` locale @SimranSiddiqui\n  - [#2140](https://github.com/validatorjs/validator.js/pull/2140) fix `am-AM` locale @AlexKrupko\n- [#2271](https://github.com/validatorjs/validator.js/pull/2271) `isPostalAddress` fix `NL` locale @RobinvanderVliet\n- [#2273](https://github.com/validatorjs/validator.js/pull/2273) `isISO4217` add `SLE` currency @urg\n- [#2278](https://github.com/validatorjs/validator.js/pull/2278) `isStrongPassword` fix symbolRegex to include `\\` @nandavikas\n- [#2279](https://github.com/validatorjs/validator.js/pull/2279) `isVAT` fixed `KZ` locale @MatthieuLemoine\n- [#2285](https://github.com/validatorjs/validator.js/pull/2285) `isAlpha`, `isAlphanumeric` added `eo` locale @RobinvanderVliet\n- [#2320](https://github.com/validatorjs/validator.js/pull/2320) `isIBAN` add Algeria `DZ` locale @thibault-lr\n- [#2343](https://github.com/validatorjs/validator.js/pull/2343) `isVAT`improve `AU` locale @matthewberryman\n- [#2345](https://github.com/validatorjs/validator.js/pull/2345) `isUUID` add support for v7 @ruscon\n- [#2358](https://github.com/validatorjs/validator.js/pull/2358) `isTaxID` add Ukraine `uk-UA` locale @arttiger\n- [#2381](https://github.com/validatorjs/validator.js/pull/2381) `isDate` disallow hiphen before year @Sumit-tech-joshi\n- **Doc fixes and others:**\n  - [#2276](https://github.com/validatorjs/validator.js/pull/2276) @meyfa\n  - [#2341](https://github.com/validatorjs/validator.js/pull/2341) @WikiRik\n  - [#2364](https://github.com/validatorjs/validator.js/pull/2364) @rubiin\n  - [#2368](https://github.com/validatorjs/validator.js/pull/2368) @ZhulinskiiDanil\n  - [#2371](https://github.com/validatorjs/validator.js/pull/2371) @devmanbud\n  - [#2386](https://github.com/validatorjs/validator.js/pull/2386) @alinaghale88\n\n# 13.11.0\n\n### New Features / Validators\n\n- [#2144](https://github.com/validatorjs/validator.js/pull/2144) `isFreightContainerID`: for shipping containers IDs @songyuew\n- [#2188](https://github.com/validatorjs/validator.js/pull/2188) `isMailtoURI` @uksarkar\n\n### Fixes, New Locales and Enhancements\n\n- [#2025](https://github.com/validatorjs/validator.js/pull/2025) `isIBAN` add `MA` locale @lroudge\n- [#2117](https://github.com/validatorjs/validator.js/pull/2117) `isCreditCard` refactor @pano9000\n- [#2189](https://github.com/validatorjs/validator.js/pull/2189) `isLocale` add support for more language tags @kwahome\n- [#2203](https://github.com/validatorjs/validator.js/pull/2203) `isVAT` for `CU` @jimmyorpheus\n- [#2217](https://github.com/validatorjs/validator.js/pull/2217) `isJWT` @Prathamesh061\n- [#2222](https://github.com/validatorjs/validator.js/pull/2222) `IsFQDN` test enhancements @aalekhpatel07\n- [#2226](https://github.com/validatorjs/validator.js/pull/2226) `isAlpha`, `isAlphanumeric` for `kk-KZ` @BekStar7\n- [#2229](https://github.com/validatorjs/validator.js/pull/2229) `isEmail` support `allow_underscores` @guspower\n- [#2231](https://github.com/validatorjs/validator.js/pull/2231) `isDate` enhance Date declaration compatibility across multiple environments @CiprianS\n- [#2235](https://github.com/validatorjs/validator.js/pull/2235) `isIBAN` add white and blacklist options to the isIBAN validator @edilson\n- [#2237](https://github.com/validatorjs/validator.js/pull/2237) `isEmail` do not allow non-breaking space in user part @jeremy21212121\n- `isMobilePhone`:\n  - [#2175](https://github.com/validatorjs/validator.js/pull/2175) `so-SO` @ohersi\n  - [#2176](https://github.com/validatorjs/validator.js/pull/2176) `fr-CF` @cheboi\n  - [#2197](https://github.com/validatorjs/validator.js/pull/2197) `es-CU` @klaframboise\n  - [#2202](https://github.com/validatorjs/validator.js/pull/2202) `pl-PL` @czerwony03\n  - [#2209](https://github.com/validatorjs/validator.js/pull/2209) `fr-WF` @aidos42\n  - [#2246](https://github.com/validatorjs/validator.js/pull/2246) `ar-SD` @Hussienma\n\n# 13.9.0\n\n### New Features / Validators\n\n- [#1892](https://github.com/validatorjs/validator.js/pull/1892) `isISO6391`: add ISO 639-1 validator @braaar\n- [#1974](https://github.com/validatorjs/validator.js/pull/1974) `isLuhnNumber` @ST-DDT\n\n### Fixes and Enhancements\n\n- [#1865](https://github.com/validatorjs/validator.js/pull/1865) `isMACAddress`: add EUI-validation @WikiRik @tux-tn\n- [#1888](https://github.com/validatorjs/validator.js/pull/1888) `isBase32`: add option for Crockford's base32 alternative @BigOsvaap\n- [#1916](https://github.com/validatorjs/validator.js/pull/1916) `isDataURI`: fix mediaType format @temoffey\n- [#1920](https://github.com/validatorjs/validator.js/pull/1920) `isEmail`: add `host_whitelist` option @poor-coder\n- [#1939](https://github.com/validatorjs/validator.js/pull/1939) `isFQDN`: fix `allow_numeric_tld` option @BigOsvaap\n- [#1962](https://github.com/validatorjs/validator.js/pull/1962) `isIP`: refactor @UnKnoWn-Consortium\n- [#1967](https://github.com/validatorjs/validator.js/pull/1967) `isLength` @ikkyu-3\n- [#1992](https://github.com/validatorjs/validator.js/pull/1992) `isMagnetURI` @Rhilip @tux-tn\n- [#1995](https://github.com/validatorjs/validator.js/pull/1995) `isURL`: fix check for host @mortbauer\n- [#2008](https://github.com/validatorjs/validator.js/pull/2008) `isCreditCard` @brianwhaley\n- [#2075](https://github.com/validatorjs/validator.js/pull/2075) `isAfter`: allow usage of option object @WikiRik\n- [#2114](https://github.com/validatorjs/validator.js/pull/2114) `isRgbColor` @pano9000\n- [#2122](https://github.com/validatorjs/validator.js/pull/2122) `isDataURI`: fix MIME types with underscores @pano9000\n- [#2148](https://github.com/validatorjs/validator.js/pull/2148) `isStrongPassword` @sandmule\n- [#2157](https://github.com/validatorjs/validator.js/pull/2157) `isISBN`: allow usage of option object @WikiRik\n- [#2170](https://github.com/validatorjs/validator.js/pull/2170) `isEmail`: fix `ignore_max_length` for FQDN @sakhmedbayev\n- [#2020](https://github.com/validatorjs/validator.js/pull/2170) `isFloat`: fix comma(,) passing as float @frederike-ramin\n\n- Documentation fixes:\n\n  - [#1860](https://github.com/validatorjs/validator.js/pull/1860) @leonardovillela\n  - [#1861](https://github.com/validatorjs/validator.js/pull/1860) @tux-tn\n  - [#1957](https://github.com/validatorjs/validator.js/pull/1957) @tfilo\n  - [#2010](https://github.com/validatorjs/validator.js/pull/2010) @marcelozarate\n  - [#2107](https://github.com/validatorjs/validator.js/pull/2107) @pano9000\n  - [#2160](https://github.com/validatorjs/validator.js/pull/2160) @WikiRik\n\n- Code Refactors:\n  - [#1942](https://github.com/validatorjs/validator.js/pull/1942) @CommanderRoot\n  - [#1975](https://github.com/validatorjs/validator.js/pull/1975) @fedeci\n  - [#2137](https://github.com/validatorjs/validator.js/pull/2137) [#2132](https://github.com/validatorjs/validator.js/pull/2132) @pano9000\n\n### New and Improved Locales\n\n- `isAlpha`, `isAlphanumeric`:\n\n  - [#1678](https://github.com/validatorjs/validator.js/pull/1678) `bn-BD` @rak810\n  - [#1996](https://github.com/validatorjs/validator.js/pull/1996) `si-LK` @melkorCBA\n  - [#2014](https://github.com/validatorjs/validator.js/pull/2014) `ja-JP` @starcharles\n  - [#1995](https://github.com/validatorjs/validator.js/pull/1995) `ko-KR` @Dongkyuuuu\n\n- `isBIC`:\n\n  - [#2046](https://github.com/validatorjs/validator.js/pull/2046) `XK` @import-brain\n\n- `isIdentityCard`:\n\n  - [#2142](https://github.com/validatorjs/validator.js/pull/2142) `hk-HK` @Dongkyuuuu\n\n- `isMobilePhone`:\n\n  - [#1813](https://github.com/validatorjs/validator.js/pull/1813) `my-MM`, @ferdousulhaque\n  - [#1868](https://github.com/validatorjs/validator.js/pull/1868) `de-DE`, @thomaschaaf\n  - [#1896](https://github.com/validatorjs/validator.js/pull/1896) `en-LS`, @DevilsAutumn\n  - [#1897](https://github.com/validatorjs/validator.js/pull/1897) `el-CY`, @ikerasiotis\n  - [#1909](https://github.com/validatorjs/validator.js/pull/1909) `es-NI`, @ajGingrich\n  - [#1910](https://github.com/validatorjs/validator.js/pull/1910) `az-AZ`, @shaanaliyev\n  - [#1922](https://github.com/validatorjs/validator.js/pull/1922) `ir-IR`, @ArashST79\n  - [#1924](https://github.com/validatorjs/validator.js/pull/1924) `ky-KG`, @arsalanfiroozi\n  - [#1925](https://github.com/validatorjs/validator.js/pull/1925) `ar-YE`, `ar-EH`, `fa-AF`, @Mustafiz04\n  - [#1932](https://github.com/validatorjs/validator.js/pull/1932) `ro-MD`, @mik7up\n  - [#1940](https://github.com/validatorjs/validator.js/pull/1940) `ar-YE`, `en-BS`, @savannahvaith\n  - [#1952](https://github.com/validatorjs/validator.js/pull/1952) `ka-GE`, @avkvak\n  - [#1964](https://github.com/validatorjs/validator.js/pull/1964) [#1951](https://github.com/validatorjs/validator.js/pull/1951) `pt-BR`, @jhcaiafa @matheusnascgomes\n  - [#1983](https://github.com/validatorjs/validator.js/pull/1983) `es-HN`, @ademyan05\n  - [#1985](https://github.com/validatorjs/validator.js/pull/1985) `nl-AW`, @adida948\n  - [#1986](https://github.com/validatorjs/validator.js/pull/1986) `en-JM`, @ademyan05\n  - [#1993](https://github.com/validatorjs/validator.js/pull/1993) `mn-MN`, @rksp25\n  - [#1997](https://github.com/validatorjs/validator.js/pull/1997) `fr-BJ`, @rkuma552 @rksp25\n  - [#2001](https://github.com/validatorjs/validator.js/pull/2001) `mg-MG`, @ShivangiRai1310\n  - [#2002](https://github.com/validatorjs/validator.js/pull/2002) `en-PG`, @kai2128\n  - [#2004](https://github.com/validatorjs/validator.js/pull/2004) `en-AG`, @jiaweilow\n  - [#2007](https://github.com/validatorjs/validator.js/pull/2007) `en-AI`, @elaine1129\n  - [#2011](https://github.com/validatorjs/validator.js/pull/2011) `en-KN`, @Eelyneee\n  - [#2041](https://github.com/validatorjs/validator.js/pull/2041) `fr-CD`, @coolbeatz71\n  - [#2084](https://github.com/validatorjs/validator.js/pull/2084) `en-SS`, @cheboi\n  - [#2109](https://github.com/validatorjs/validator.js/pull/2109) `dv-MV`, @pano9000\n  - [#2129](https://github.com/validatorjs/validator.js/pull/2129) `en-HN`, @WikiRik\n  - [#2148](https://github.com/validatorjs/validator.js/pull/2148) `ar-KW`, @Yazan-KE @WikiRik\n  - [#2112](https://github.com/validatorjs/validator.js/pull/2112) `el-GR`, @pano9000\n  - [#2116](https://github.com/validatorjs/validator.js/pull/2116) `en-BM`, @pano9000\n  - [#2155](https://github.com/validatorjs/validator.js/pull/2155) `ms-MY`, @pano9000\n  - [#2156](https://github.com/validatorjs/validator.js/pull/2156) `ro-RO`, @pano9000\n\n- `isLicensePlate`:\n\n  - [#1665](https://github.com/validatorjs/validator.js/pull/1665) `sv-SE`, @elmaxe\n  - [#1895](https://github.com/validatorjs/validator.js/pull/1895) `hu-HU`, @szabolcstarnai\n  - [#1944](https://github.com/validatorjs/validator.js/pull/1944) `en-NI`, @NishantJS\n  - [#1945](https://github.com/validatorjs/validator.js/pull/1945) `de-DE`, @bennetfabian\n  - [#1945](https://github.com/validatorjs/validator.js/pull/1945) `de-DE`, @bennetfabian\n  - [#2103](https://github.com/validatorjs/validator.js/pull/2103) `es-AR`, @alvarocastro\n\n- `isPassportNumber`:\n\n  - [#1515](https://github.com/validatorjs/validator.js/pull/1515) `JM`,`KZ`,`LI`,`NZ` @JuanFML\n  - [#1814](https://github.com/validatorjs/validator.js/pull/1814) `TH` @TonPC64 @braaar\n  - [#2061](https://github.com/validatorjs/validator.js/pull/2061) `AZ` @djeks922\n  - [#2073](https://github.com/validatorjs/validator.js/pull/2073) `PH`,`PK` @digambar-t7\n\n- `isPostalCode`:\n\n  - [#1951](https://github.com/validatorjs/validator.js/pull/1951) `BA`, @matheusnascgomes\n  - [#2134](https://github.com/validatorjs/validator.js/pull/2134) `BY`, @pano9000\n  - [#2136](https://github.com/validatorjs/validator.js/pull/2136) `IR`, @pano9000\n\n- `isTaxID`:\n  - [#1867](https://github.com/validatorjs/validator.js/pull/1867) `en-CA`, @boonya\n  - [#1989](https://github.com/validatorjs/validator.js/pull/1989) `'AT', 'BE', 'BG', 'HR', 'CY', 'CZ', 'DK', 'EE', 'FI', 'FR', 'DE', 'EL', 'HU', 'IE', 'LV', 'LT', 'LU', 'MT', 'PL', 'PT', 'RO', 'SK', 'SI', 'ES', 'SE', 'AL', 'MK', 'AU', 'BY', 'CA', 'IS', 'IN', 'ID', 'IL', 'KZ', 'NZ', 'NG', 'NO', 'PH', 'RU', 'SM', 'SA', 'RS', 'CH', 'TR', 'UA', 'UZ', 'AR', 'BO', 'BR', 'CL', 'CO', 'CR', 'EC', 'SV', 'GT', 'HN', 'MX', 'NI', 'PA', 'PY', 'PE', 'DO', 'UY', 'VE'` @Dev1lDragon\n\n## 13.7.0\n\n### New Features\n\n- [#1706](https://github.com/validatorjs/validator.js/pull/1706) `isISO4217`, currency code validator @jpaya17\n\n### Fixes and Enhancements\n\n- [#1647](https://github.com/validatorjs/validator.js/pull/1647) `isFQDN`: add `allow_wildcard` option @fasenderos\n- [#1654](https://github.com/validatorjs/validator.js/pull/1654) `isRFC3339`: Disallow prepended and appended strings to RFC 3339 date-time @jmacmahon\n- [#1658](https://github.com/validatorjs/validator.js/pull/1658) maintenance: increase code coverage @tux-tn\n- [#1669](https://github.com/validatorjs/validator.js/pull/1669) `IBAN` export list of country codes that implement IBAN @dror-heller @fedeci\n- [#1676](https://github.com/validatorjs/validator.js/pull/1676) `isBoolean`: add `loose` option @brybrophy\n- [#1697](https://github.com/validatorjs/validator.js/pull/1697) maintenance: fix npm installation error @rubiin\n- [#1708](https://github.com/validatorjs/validator.js/pull/1708) `isISO31661Alpha3`: perf @jpaya17\n- [#1711](https://github.com/validatorjs/validator.js/pull/1711) `isDate`: allow users to strictly validate dates with `.` as delimiter @flymans\n- [#1715](https://github.com/validatorjs/validator.js/pull/1715) `isCreditCard`: fix for Union Pay cards @shreyassai123\n- [#1718](https://github.com/validatorjs/validator.js/pull/1718) `isEmail`: replace all dots in GMail length validation @DasDingGehtNicht\n- [#1721](https://github.com/validatorjs/validator.js/pull/1721) `isURL`: add `allow_fragments` and `allow_query_components` @cowboy-bebug\n- [#1724](https://github.com/validatorjs/validator.js/pull/1724) `isISO31661Alpha2`: perf @jpaya17\n- [#1730](https://github.com/validatorjs/validator.js/pull/1730) `isMagnetURI` @tux-tn\n- [#1738](https://github.com/validatorjs/validator.js/pull/1738) `rtrim`: remove regex to prevent ReDOS attack @tux-tn\n- [#1747](https://github.com/validatorjs/validator.js/pull/1747) maintenance: run scripts in parallel for build and clean @sachinraja\n- [#1748](https://github.com/validatorjs/validator.js/pull/1748) `isURL`: higher priority to `whitelist` @deepanshu2506\n- [#1751](https://github.com/validatorjs/validator.js/pull/1751) `isURL`: allow url with colon and no port @MatteoPierro\n- [#1777](https://github.com/validatorjs/validator.js/pull/1777) `isUUID`: fix for `null` version argument @theteladras\n- [#1799](https://github.com/validatorjs/validator.js/pull/1799) `isFQDN`: check more special chars @MatteoPierro\n- [#1833](https://github.com/validatorjs/validator.js/pull/1833) `isURL`: allow URL with an empty user @MiguelSavignano\n- [#1835](https://github.com/validatorjs/validator.js/pull/1835) `unescape`: fixed bug where intermediate string contains escaped @Marcholio\n- [#1836](https://github.com/validatorjs/validator.js/pull/1836) `contains`: can check that string contains seed multiple times @Marcholio\n- [#1844](https://github.com/validatorjs/validator.js/pull/1844) docs: add CDN instructions @luiscobits\n- [#1848](https://github.com/validatorjs/validator.js/pull/1848) `isUUID`: add support for validation of `v1` and `v2` @theteladras\n- [#1941](https://github.com/validatorjs/validator.js/pull/1641) `isEmail`: add `host_blacklist` option @fedeci\n\n### New and Improved Locales\n\n- `isAlpha`, `isAlphanumeric`:\n\n  - [#1716](https://github.com/validatorjs/validator.js/pull/1716) `hi-IN` @MiKr13\n  - [#1837](https://github.com/validatorjs/validator.js/pull/1837) `fi-FI` @Marcholio\n\n- `isPassportNumber`:\n\n  - [#1656](https://github.com/validatorjs/validator.js/pull/1656) `ID` @rubiin\n  - [#1714](https://github.com/validatorjs/validator.js/pull/1714) `CN` @anirudhgiri\n  - [#1809](https://github.com/validatorjs/validator.js/pull/1809) `PL` @Ronqn\n  - [#1810](https://github.com/validatorjs/validator.js/pull/1810) `RU` @Theta-Dev\n\n- `isPostalCode`:\n\n  - [#1788](https://github.com/validatorjs/validator.js/pull/1788) `LK` @nimanthadilz\n\n- `isIdentityCard`:\n\n  - [#1657](https://github.com/validatorjs/validator.js/pull/1657) `TH` @tithanayut\n  - [#1745](https://github.com/validatorjs/validator.js/pull/1745) `PL` @wiktorwojcik112 @fedeci @tux-tn\n  - [#1786](https://github.com/validatorjs/validator.js/pull/1786) `LK` @nimanthadilz @tux-tn\n  - [#1838](https://github.com/validatorjs/validator.js/pull/1838) `FI` @Marcholio\n\n- `isMobilePhone`:\n\n  - [#1679](https://github.com/validatorjs/validator.js/pull/1679) `de-DE` @AnnaMariaJansen\n  - [#1689](https://github.com/validatorjs/validator.js/pull/1689) `vi-VN` @luisrivas\n  - [#1695](https://github.com/validatorjs/validator.js/pull/1695) [#1682](https://github.com/validatorjs/validator.js/pull/1682) `zh-CN` @laulujan @yisibl\n  - [#1734](https://github.com/validatorjs/validator.js/pull/1734) `es-VE` @islasjuanp\n  - [#1746](https://github.com/validatorjs/validator.js/pull/1746) `nl-BE` @divikshrivastava\n  - [#1765](https://github.com/validatorjs/validator.js/pull/1765) `es-CU` @pasagedev\n  - [#1766](https://github.com/validatorjs/validator.js/pull/1766) `es-SV`, @hereje\n  - [#1767](https://github.com/validatorjs/validator.js/pull/1767) `ar-PS`, @brendan-c\n  - [#1769](https://github.com/validatorjs/validator.js/pull/1769) `en-BM` @HackProAIT\n  - [#1770](https://github.com/validatorjs/validator.js/pull/1770) `dz-BT` @lakshayr003\n  - [#1771](https://github.com/validatorjs/validator.js/pull/1771) `en-BW`, @mgndolan\n  - [#1772](https://github.com/validatorjs/validator.js/pull/1772) `fr-CM` @beckettnormington\n  - [#1778](https://github.com/validatorjs/validator.js/pull/1778) `en-PK` @ammad20120 @tux-tn\n  - [#1780](https://github.com/validatorjs/validator.js/pull/1780) `tk-TM`, @Husan-Eshonqulov\n  - [#1784](https://github.com/validatorjs/validator.js/pull/1784) `en-GY`, @mfkrause\n  - [#1785](https://github.com/validatorjs/validator.js/pull/1785) `si-LK` @Madhavi96\n  - [#1797](https://github.com/validatorjs/validator.js/pull/1797) `fr-PF`, @hereje\n  - [#1820](https://github.com/validatorjs/validator.js/pull/1820) `en-KI`, @c-tanner\n  - [#1826](https://github.com/validatorjs/validator.js/pull/1826) `hu-HU` @danielTiringer\n  - [#1834](https://github.com/validatorjs/validator.js/pull/1834) `fr-BF`, `en-NA` @lakshayr003\n  - [#1846](https://github.com/validatorjs/validator.js/pull/1846) `tg-TJ` @mgnss\n\n- `isLicensePlate`:\n\n  - [#1565](https://github.com/validatorjs/validator.js/pull/1565) `cs-CZ` @filiptronicek\n  - [#1790](https://github.com/validatorjs/validator.js/pull/1790) `fi-FI` @Marcholio\n\n- `isVAT`:\n  - [#1825](https://github.com/validatorjs/validator.js/pull/1825) `NL` @zeno4ever\n\n#### 13.6.1\n\n- **New features**:\n\n  - [#1495](https://github.com/validatorjs/validator.js/pull/1495) `isLicensePlate` @firlus\n\n- **Fixes and Enhancements**:\n\n  - [#1651](https://github.com/validatorjs/validator.js/pull/1651) fix ReDOS vulnerabilities in `isHSL` and `isEmail` @tux-tn\n  - [#1644](https://github.com/validatorjs/validator.js/pull/1644) `isURL`: Allow URLs to have only a username in the userinfo subcomponent @jbuchmann-coosto\n  - [#1633](https://github.com/validatorjs/validator.js/pull/1633) `isISIN`: optimization @bmacnaughton\n  - [#1632](https://github.com/validatorjs/validator.js/pull/1632) `isIP`: improved pattern for IPv4 and IPv6 @ognjenjevremovic\n  - [#1625](https://github.com/validatorjs/validator.js/pull/1625) fix `[A-z]` regex range on some validators @bmacnaughton\n  - [#1620](https://github.com/validatorjs/validator.js/pull/1620) fix docs @prahaladbelavadi\n  - [#1616](https://github.com/validatorjs/validator.js/pull/1616) `isMacAddress`: improve regexes and options @fedeci\n  - [#1603](https://github.com/validatorjs/validator.js/pull/1603) fix ReDOS vulnerabilities in `isSlug` and `rtrim` @fedeci\n  - [#1594](https://github.com/validatorjs/validator.js/pull/1594) `isIPRange`: add support for IPv6 @neilime\n  - [#1577](https://github.com/validatorjs/validator.js/pull/1577) `isEAN`: add support for EAN-14 @varsubham @tux-tn\n  - [#1566](https://github.com/validatorjs/validator.js/pull/1566) `isStrongPassword`: add `@` as a valid symbol @stingalleman\n  - [#1548](https://github.com/validatorjs/validator.js/pull/1548) `isBtcAddress`: add base58 @ezkemboi\n  - [#1546](https://github.com/validatorjs/validator.js/pull/1546) `isFQDN`: numeric domain names @tux-tn\n\n- **New and Improved locales**:\n  - `isIdentityCard`, `isPassportNumber`:\n    - [#1595](https://github.com/validatorjs/validator.js/pull/1595) `IR` @mhf-ir @fedeci\n    - [#1583](https://github.com/validatorjs/validator.js/pull/1583) `ar-LY` @asghaier76 @tux-tn\n    - [#1574](https://github.com/validatorjs/validator.js/pull/1574) `MY` @stranger26 @tux-tn\n  - `isMobilePhone`:\n    - [#1642](https://github.com/validatorjs/validator.js/pull/1642) `zh-CN` @Akira0705\n    - [#1638](https://github.com/validatorjs/validator.js/pull/1638) `lv-LV` @AntonLukichev\n    - [#1635](https://github.com/validatorjs/validator.js/pull/1635) `en-GH` @ankorGH\n    - [#1604](https://github.com/validatorjs/validator.js/pull/1604) `mz-MZ` @salmento @tux-tn\n    - [#1575](https://github.com/validatorjs/validator.js/pull/1575) `vi-VN` @kyled7\n    - [#1573](https://github.com/validatorjs/validator.js/pull/1573) `en-SG` @liliwei25\n    - [#1554](https://github.com/validatorjs/validator.js/pull/1554) `de-CH`, `fr-CH`, `it-CH` @dinfekted\n    - [#1541](https://github.com/validatorjs/validator.js/pull/1541) [#1623](https://github.com/validatorjs/validator.js/pull/1623) `es-CO` @ezkemboi @tux-tn\n    - [#1506](https://github.com/validatorjs/validator.js/pull/1506) `ar-OM` @dev-sna\n    - [#1505](https://github.com/validatorjs/validator.js/pull/1505) `pt-AO` @AdilsonFuxe\n  - `isPostalCode`:\n    - [#1628](https://github.com/validatorjs/validator.js/pull/1628) `KR` @greatSumini\n  - `isTaxID`:\n    - [#1613](https://github.com/validatorjs/validator.js/pull/1613) `pt-BR` @mschunke\n    - [#1529](https://github.com/validatorjs/validator.js/pull/1529) `el-GR` @dspinellis\n  - `isVAT`:\n    - [#1536](https://github.com/validatorjs/validator.js/pull/1536) `IT` @fedeci\n\n#### ~~13.5.0~~ 13.5.1\n\n- **New features**:\n\n  - `isVAT` [#1463](https://github.com/validatorjs/validator.js/pull/1463) @ CodingNagger\n  - `isTaxID` [#1446](https://github.com/validatorjs/validator.js/pull/1446) @tplessas\n  - `isBase58` [#1445](https://github.com/validatorjs/validator.js/pull/1445) @ezkemboi\n  - `isStrongPassword` [#1348](https://github.com/validatorjs/validator.js/pull/1348) @door-bell\n\n- **Fixes and Enhancements**:\n\n  - [#1486](https://github.com/validatorjs/validator.js/pull/1486) `isISO8601`: add `strictSeparator` @brostone51\n  - [#1474](https://github.com/validatorjs/validator.js/pull/1474) `isFQDN`: make more strict @CristhianMotoche\n  - [#1469](https://github.com/validatorjs/validator.js/pull/1469) `isFQDN`: `allow_underscore` option @gibson042\n  - [#1449](https://github.com/validatorjs/validator.js/pull/1449) `isEmail`: character blacklisting @rubiin\n  - [#1436](https://github.com/validatorjs/validator.js/pull/1436) `isURL`: added `require_port` option @yshanli\n  - [#1435](https://github.com/validatorjs/validator.js/pull/1435) `isEmail`: respect `ignore_max_length` option @evantahler\n  - [#1402](https://github.com/validatorjs/validator.js/pull/1402) `isDate`: add strictMode and prevent mixed delimiters @tux-tn\n  - [#1286](https://github.com/validatorjs/validator.js/pull/1286) `isAlpha`: support `ignore` option @mum-never-proud\n\n- **New and Improved locales**:\n  - `isAlpha`, `isAlphanumeric`:\n    - [#1528](https://github.com/validatorjs/validator.js/pull/1528) multiple fixes @tux-tn @purell\n    - [#1513](https://github.com/validatorjs/validator.js/pull/1513) `id-ID` and docs update @bekicot\n    - [#1484](https://github.com/validatorjs/validator.js/pull/1484) [#1481](https://github.com/validatorjs/validator.js/pull/1481) `th-TH` @ipiranhaa\n    - [#1455](https://github.com/validatorjs/validator.js/pull/1455) `fa-IR` @fakhrip\n    - [#1447](https://github.com/validatorjs/validator.js/pull/1447) `az-AZ` @saidfagan\n  - `isMobilePhone`:\n    - [#1521](https://github.com/validatorjs/validator.js/pull/1521) `ar-MA` @artpumpkin\n    - [#1492](https://github.com/validatorjs/validator.js/pull/1492) `de-LU`,`it-SM`, `sq-AL` and `ga-IE` @firlus\n    - [#1487](https://github.com/validatorjs/validator.js/pull/1487) `en-HN` @jehielmartinez\n    - [#1473](https://github.com/validatorjs/validator.js/pull/1473) `ar-LB`, `es-PE`, `ka-GE` @rubiin\n    - [#1470](https://github.com/validatorjs/validator.js/pull/1444) `es-DO` @devrasec\n    - [#1460](https://github.com/validatorjs/validator.js/pull/1444) `es-BO` @rubiin\n    - [#1444](https://github.com/validatorjs/validator.js/pull/1444) `es-AR` @csrgt\n    - [#1407](https://github.com/validatorjs/validator.js/pull/1407) `pt-BR` @viniciushvsilva\n  - `isPostalCode`:\n    - [#1534](https://github.com/validatorjs/validator.js/pull/1534) `CN` @httpsbao\n    - [#1515](https://github.com/validatorjs/validator.js/pull/1515) `IR` @masoudDaliriyan\n    - [#1502](https://github.com/validatorjs/validator.js/pull/1502) `SG`, `MY` @stranger26\n    - [#1480](https://github.com/validatorjs/validator.js/pull/1480) `TH` @ipiranhaa\n    - [#1459](https://github.com/validatorjs/validator.js/pull/1456) `BY` @rubiin\n    - [#1456](https://github.com/validatorjs/validator.js/pull/1456) `DO` and `HT` @yomed\n  - `isPassportNumber`:\n    - [#1468](https://github.com/validatorjs/validator.js/pull/1468) `BY` @zenby\n    - [#1467](https://github.com/validatorjs/validator.js/pull/1467) `RU` @dkochetkov\n\n<sub>&mdash; this release is dedicated to @dbnandaa 🧒</sub>\n\n#### 13.1.17\n\n- **New features**:\n  - None\n- **Fixes and chores**:\n\n  - [#1425](https://github.com/validatorjs/validator.js/pull/1425) fix validation for _userinfo_ part for `isURL` @heanzyzabala\n  - [#1419](https://github.com/validatorjs/validator.js/pull/1419) fix `isBase32` and `isBase64` to validate empty strings properly @AberDerBart\n  - [#1408](https://github.com/validatorjs/validator.js/pull/1408) tests for `isTaxId` @dspinellis\n  - [#1397](https://github.com/validatorjs/validator.js/pull/1397) added `validate_length` option for `isURL` @tomgrossman\n  - [#1383](https://github.com/validatorjs/validator.js/pull/1383) [#1428](https://github.com/validatorjs/validator.js/pull/1428) doc typos @0xflotus @timgates42\n  - [#1376](https://github.com/validatorjs/validator.js/pull/1376) add missing tests and switch to Coverall @tux-tn\n  - [#1373](https://github.com/validatorjs/validator.js/pull/1373) improve code coverage @ezkemboi\n  - [#1357](https://github.com/validatorjs/validator.js/pull/1357) add Node v6 on build pipeline @profnandaa\n\n- **New and Improved locales**:\n  - `isMobilePhone`:\n    - [#1439](https://github.com/validatorjs/validator.js/pull/1439) `az-AZ` @saidfagan\n    - [#1420](https://github.com/validatorjs/validator.js/pull/1420) `uz-Uz` @icyice0217\n    - [#1391](https://github.com/validatorjs/validator.js/pull/1391) `de-DE` @heanzyzabala\n    - [#1388](https://github.com/validatorjs/validator.js/pull/1388) `en-PH` @stinkymonkeyph\n    - [#1370](https://github.com/validatorjs/validator.js/pull/1370) `es-ES` @rubiin\n    - [#1356](https://github.com/validatorjs/validator.js/pull/1356) `bs-BA` @MladenZeljic\n    - [#1303](https://github.com/validatorjs/validator.js/pull/1301) `zh-CN` @heathcliff-hu\n  - `isPostalCode`:\n    - [#1439](https://github.com/validatorjs/validator.js/pull/1439) `AZ` @saidfagan\n    - [#1370](https://github.com/validatorjs/validator.js/pull/1370) `ES` @rubiin\n    - [#1367](https://github.com/validatorjs/validator.js/pull/1367) `IL` @rubiin\n  - `isAlpha`, `isAlphanumeric`:\n    - [#1411](https://github.com/validatorjs/validator.js/pull/1411) `fa-AF`, `fa-IR` @stinkymonkeyph\n    - [#1371](https://github.com/validatorjs/validator.js/pull/1371) `vi-VN` @rubiin\n  - `isBAN`:\n    - [#1394](https://github.com/validatorjs/validator.js/pull/1394) `EG`, `SV` @heanzyzabala\n  - `isIdentityCard`:\n    - [#1384](https://github.com/validatorjs/validator.js/pull/1384) `IT` @lorenzodb1\n\n#### 13.1.1\n\n- Hotfix for a regex incompatibility in some browsers\n  ([#1355](https://github.com/validatorjs/validator.js/pull/1355)\n\n#### 13.1.0\n\n- Added an `isIMEI()` validator\n  ([#1346](https://github.com/validatorjs/validator.js/pull/1346))\n- Added an `isDate()` validator\n  ([#1270](https://github.com/validatorjs/validator.js/pull/1270))\n- Added an `isTaxID()` validator\n  ([#1336](https://github.com/validatorjs/validator.js/pull/1336))\n- Added DMS support to `isLatLong()`\n  ([#1340](https://github.com/validatorjs/validator.js/pull/1340))\n- Added support for URL-safe base64 validation\n  ([#1277](https://github.com/validatorjs/validator.js/pull/1277))\n- Added support for primitives in `isJSON()`\n  ([#1328](https://github.com/validatorjs/validator.js/pull/1328))\n- Added support for case-insensitive matching to `contains()`\n  ([#1334](https://github.com/validatorjs/validator.js/pull/1334))\n- Support additional cards in `isCreditCard()`\n  ([#1177](https://github.com/validatorjs/validator.js/pull/1177))\n- Support additional currencies in `isCurrency()`\n  ([#1306](https://github.com/validatorjs/validator.js/pull/1306))\n- Fixed `isFQDN()` handling of certain special chars\n  ([#1091](https://github.com/validatorjs/validator.js/pull/1091))\n- Fixed a bug in `isSlug()`\n  ([#1338](https://github.com/validatorjs/validator.js/pull/1338))\n- New and improved locales\n  ([#1112](https://github.com/validatorjs/validator.js/pull/1112),\n  [#1167](https://github.com/validatorjs/validator.js/pull/1167),\n  [#1198](https://github.com/validatorjs/validator.js/pull/1198),\n  [#1199](https://github.com/validatorjs/validator.js/pull/1199),\n  [#1273](https://github.com/validatorjs/validator.js/pull/1273),\n  [#1279](https://github.com/validatorjs/validator.js/pull/1279),\n  [#1281](https://github.com/validatorjs/validator.js/pull/1281),\n  [#1293](https://github.com/validatorjs/validator.js/pull/1293),\n  [#1294](https://github.com/validatorjs/validator.js/pull/1294),\n  [#1311](https://github.com/validatorjs/validator.js/pull/1311),\n  [#1312](https://github.com/validatorjs/validator.js/pull/1312),\n  [#1313](https://github.com/validatorjs/validator.js/pull/1313),\n  [#1314](https://github.com/validatorjs/validator.js/pull/1314),\n  [#1315](https://github.com/validatorjs/validator.js/pull/1315),\n  [#1317](https://github.com/validatorjs/validator.js/pull/1317),\n  [#1322](https://github.com/validatorjs/validator.js/pull/1322),\n  [#1324](https://github.com/validatorjs/validator.js/pull/1324),\n  [#1330](https://github.com/validatorjs/validator.js/pull/1330),\n  [#1337](https://github.com/validatorjs/validator.js/pull/1337))\n\n#### 13.0.0\n\n- Added `isEthereumAddress()` validator\n  to validate [Ethereum addresses](https://en.wikipedia.org/wiki/Ethereum#Addresses)\n  ([#1117](https://github.com/validatorjs/validator.js/pull/1117))\n- Added `isBtcAddress()` validator\n  to validate [Bitcoin addresses](https://en.bitcoin.it/wiki/Address)\n  ([#1163](https://github.com/validatorjs/validator.js/pull/1163))\n- Added `isIBAN()` validator\n  to validate [International Bank Account Numbers](https://en.wikipedia.org/wiki/International_Bank_Account_Number)\n  ([#1243](https://github.com/validatorjs/validator.js/pull/1243))\n- Added `isEAN()` validator\n  to validate [International Article Numbers](https://en.wikipedia.org/wiki/International_Article_Number)\n  ([#1244](https://github.com/validatorjs/validator.js/pull/1244))\n- Added `isSemVer()` validator\n  to validate [Semantic Version Numbers](https://semver.org)\n  ([#1246](https://github.com/validatorjs/validator.js/pull/1246))\n- Added `isPassportNumber()` validator\n  ([#1250](https://github.com/validatorjs/validator.js/pull/1250))\n- Added `isRgbColor()` validator\n  ([#1141](https://github.com/validatorjs/validator.js/pull/1141))\n- Added `isHSL()` validator\n  ([#1159](https://github.com/validatorjs/validator.js/pull/1159))\n- Added `isLocale()` validator\n  ([#1072](https://github.com/validatorjs/validator.js/pull/1072))\n- Improved the `isIP()` validator\n  ([#1211](https://github.com/validatorjs/validator.js/pull/1211))\n- Improved the `isMACAddress()` validator\n  ([#1267](https://github.com/validatorjs/validator.js/pull/1267))\n- New and improved locales\n  ([#1238](https://github.com/validatorjs/validator.js/pull/1238),\n  [#1265](https://github.com/validatorjs/validator.js/pull/1265))\n\n#### 12.2.0\n\n- Support CSS Colors Level 4 spec\n  ([#1233](https://github.com/validatorjs/validator.js/pull/1233))\n- Improve the `toFloat()` sanitizer\n  ([#1227](https://github.com/validatorjs/validator.js/pull/1227))\n- New and improved locales\n  ([#1200](https://github.com/validatorjs/validator.js/pull/1200),\n  [#1207](https://github.com/validatorjs/validator.js/pull/1207),\n  [#1213](https://github.com/validatorjs/validator.js/pull/1213),\n  [#1217](https://github.com/validatorjs/validator.js/pull/1217),\n  [#1234](https://github.com/validatorjs/validator.js/pull/1234))\n\n#### 12.1.0\n\n- ES module for webpack tree shaking\n  ([#1015](https://github.com/validatorjs/validator.js/pull/1015))\n- Updated `isIP()` to accept scoped IPv6 addresses\n  ([#1160](https://github.com/validatorjs/validator.js/pull/1160))\n- New and improved locales\n  ([#1162](https://github.com/validatorjs/validator.js/pull/1162),\n  [#1183](https://github.com/validatorjs/validator.js/pull/1183),\n  [#1187](https://github.com/validatorjs/validator.js/pull/1187),\n  [#1191](https://github.com/validatorjs/validator.js/pull/1191))\n\n#### 12.0.0\n\n- Added `isOctal()` validator\n  ([#1153](https://github.com/validatorjs/validator.js/pull/1153))\n- Added `isSlug()` validator\n  ([#1096](https://github.com/validatorjs/validator.js/pull/1096))\n- Added `isBIC()` validator for bank identification codes\n  ([#1071](https://github.com/validatorjs/validator.js/pull/1071))\n- Allow uppercase chars in `isHash()`\n  ([#1062](https://github.com/validatorjs/validator.js/pull/1062))\n- Allow additional prefixes in `isHexadecimal()`\n  ([#1147](https://github.com/validatorjs/validator.js/pull/1147))\n- Allow additional separators in `isMACAddress()`\n  ([#1065](https://github.com/validatorjs/validator.js/pull/1065))\n- Better defaults for `isLength()`\n  ([#1070](https://github.com/validatorjs/validator.js/pull/1070))\n- Bug fixes\n  ([#1074](https://github.com/validatorjs/validator.js/pull/1074))\n- New and improved locales\n  ([#1059](https://github.com/validatorjs/validator.js/pull/1059),\n  [#1060](https://github.com/validatorjs/validator.js/pull/1060),\n  [#1069](https://github.com/validatorjs/validator.js/pull/1069),\n  [#1073](https://github.com/validatorjs/validator.js/pull/1073),\n  [#1082](https://github.com/validatorjs/validator.js/pull/1082),\n  [#1092](https://github.com/validatorjs/validator.js/pull/1092),\n  [#1121](https://github.com/validatorjs/validator.js/pull/1121),\n  [#1125](https://github.com/validatorjs/validator.js/pull/1125),\n  [#1132](https://github.com/validatorjs/validator.js/pull/1132),\n  [#1152](https://github.com/validatorjs/validator.js/pull/1152),\n  [#1165](https://github.com/validatorjs/validator.js/pull/1165),\n  [#1166](https://github.com/validatorjs/validator.js/pull/1166),\n  [#1174](https://github.com/validatorjs/validator.js/pull/1174))\n\n#### 11.1.0\n\n- Code coverage improvements\n  ([#1024](https://github.com/validatorjs/validator.js/pull/1024))\n- New and improved locales\n  ([#1035](https://github.com/validatorjs/validator.js/pull/1035),\n  [#1040](https://github.com/validatorjs/validator.js/pull/1040),\n  [#1041](https://github.com/validatorjs/validator.js/pull/1041),\n  [#1048](https://github.com/validatorjs/validator.js/pull/1048),\n  [#1049](https://github.com/validatorjs/validator.js/pull/1049),\n  [#1052](https://github.com/validatorjs/validator.js/pull/1052),\n  [#1054](https://github.com/validatorjs/validator.js/pull/1054),\n  [#1055](https://github.com/validatorjs/validator.js/pull/1055),\n  [#1056](https://github.com/validatorjs/validator.js/pull/1056),\n  [#1057](https://github.com/validatorjs/validator.js/pull/1057))\n\n#### 11.0.0\n\n- Added a `isBase32()` validator\n  ([#1023](https://github.com/validatorjs/validator.js/pull/1023))\n- Updated `isEmail()` to validate display names according to RFC2822\n  ([#1004](https://github.com/validatorjs/validator.js/pull/1004))\n- Updated `isEmail()` to check total email length\n  ([#1007](https://github.com/validatorjs/validator.js/pull/1007))\n- The internal `toString()` util is no longer exported\n  ([0277eb](https://github.com/validatorjs/validator.js/commit/0277eb00d245a3479af52adf7d927d4036895650))\n- New and improved locales\n  ([#999](https://github.com/validatorjs/validator.js/pull/999),\n  [#1010](https://github.com/validatorjs/validator.js/pull/1010),\n  [#1017](https://github.com/validatorjs/validator.js/pull/1017),\n  [#1022](https://github.com/validatorjs/validator.js/pull/1022),\n  [#1031](https://github.com/validatorjs/validator.js/pull/1031),\n  [#1032](https://github.com/validatorjs/validator.js/pull/1032))\n\n#### 10.11.0\n\n- Fix imports like `import .. from \"validator/lib/..\"`\n  ([#961](https://github.com/validatorjs/validator.js/pull/961))\n- New locale\n  ([#958](https://github.com/validatorjs/validator.js/pull/958))\n\n#### 10.10.0\n\n- `isISO8601()` strict mode now works in the browser\n  ([#932](https://github.com/validatorjs/validator.js/pull/932))\n- New and improved locales\n  ([#931](https://github.com/validatorjs/validator.js/pull/931),\n  [#933](https://github.com/validatorjs/validator.js/pull/933),\n  [#947](https://github.com/validatorjs/validator.js/pull/947),\n  [#950](https://github.com/validatorjs/validator.js/pull/950))\n\n#### 10.9.0\n\n- Added an option to `isURL()` to reject email-like URLs\n  ([#901](https://github.com/validatorjs/validator.js/pull/901))\n- Added a `strict` option to `isISO8601()`\n  ([#910](https://github.com/validatorjs/validator.js/pull/910))\n- Relaxed `isJWT()` signature requirements\n  ([#906](https://github.com/validatorjs/validator.js/pull/906))\n- New and improved locales\n  ([#899](https://github.com/validatorjs/validator.js/pull/899),\n  [#904](https://github.com/validatorjs/validator.js/pull/904),\n  [#913](https://github.com/validatorjs/validator.js/pull/913),\n  [#916](https://github.com/validatorjs/validator.js/pull/916),\n  [#925](https://github.com/validatorjs/validator.js/pull/925),\n  [#928](https://github.com/validatorjs/validator.js/pull/928))\n\n#### 10.8.0\n\n- Added `isIdentityCard()`\n  ([#846](https://github.com/validatorjs/validator.js/pull/846))\n- Better error when validators are passed an invalid type\n  ([#895](https://github.com/validatorjs/validator.js/pull/895))\n- Locales are now exported\n  ([#890](https://github.com/validatorjs/validator.js/pull/890),\n  [#892](https://github.com/validatorjs/validator.js/pull/892))\n- New locale\n  ([#896](https://github.com/validatorjs/validator.js/pull/896))\n\n#### 10.7.1\n\n- Ignore case when checking URL protocol\n  ([#887](https://github.com/validatorjs/validator.js/issues/887))\n- Locale fix\n  ([#889](https://github.com/validatorjs/validator.js/pull/889))\n\n#### 10.7.0\n\n- Added `isMagnetURI()` to validate [magnet URIs](https://en.wikipedia.org/wiki/Magnet_URI_scheme)\n  ([#884](https://github.com/validatorjs/validator.js/pull/884))\n- Added `isJWT()` to validate [JSON web tokens](https://en.wikipedia.org/wiki/JSON_Web_Token)\n  ([#885](https://github.com/validatorjs/validator.js/pull/885))\n\n#### 10.6.0\n\n- Updated `isMobilePhone()` to match any locale's pattern by default\n  ([#874](https://github.com/validatorjs/validator.js/pull/874))\n- Added an option to ignore whitespace in `isEmpty()`\n  ([#880](https://github.com/validatorjs/validator.js/pull/880))\n- New and improved locales\n  ([#878](https://github.com/validatorjs/validator.js/pull/878),\n  [#879](https://github.com/validatorjs/validator.js/pull/879))\n\n#### 10.5.0\n\n- Disabled domain-specific email validation\n  ([#873](https://github.com/validatorjs/validator.js/pull/873))\n- Added support for IP hostnames in `isEmail()`\n  ([#845](https://github.com/validatorjs/validator.js/pull/845))\n- Added a `no_symbols` option to `isNumeric()`\n  ([#848](https://github.com/validatorjs/validator.js/pull/848))\n- Added a `no_colons` option to `isMACAddress()`\n  ([#849](https://github.com/validatorjs/validator.js/pull/849))\n- Updated `isURL()` to reject protocol relative URLs unless a flag is set\n  ([#860](https://github.com/validatorjs/validator.js/issues/860))\n- New and improved locales\n  ([#801](https://github.com/validatorjs/validator.js/pull/801),\n  [#856](https://github.com/validatorjs/validator.js/pull/856),\n  [#859](https://github.com/validatorjs/validator.js/issues/859),\n  [#861](https://github.com/validatorjs/validator.js/pull/861),\n  [#862](https://github.com/validatorjs/validator.js/pull/862),\n  [#863](https://github.com/validatorjs/validator.js/pull/863),\n  [#864](https://github.com/validatorjs/validator.js/pull/864),\n  [#870](https://github.com/validatorjs/validator.js/pull/870),\n  [#872](https://github.com/validatorjs/validator.js/pull/872))\n\n#### 10.4.0\n\n- Added an `isIPRange()` validator\n  ([#842](https://github.com/validatorjs/validator.js/pull/842))\n- Accept an array of locales in `isMobilePhone()`\n  ([#742](https://github.com/validatorjs/validator.js/pull/742))\n- New locale\n  ([#843](https://github.com/validatorjs/validator.js/pull/843))\n\n#### 10.3.0\n\n- Strict Gmail validation in `isEmail()`\n  ([#832](https://github.com/validatorjs/validator.js/pull/832))\n- New locales\n  ([#831](https://github.com/validatorjs/validator.js/pull/831),\n  [#835](https://github.com/validatorjs/validator.js/pull/835),\n  [#836](https://github.com/validatorjs/validator.js/pull/836))\n\n#### 10.2.0\n\n- Export the list of supported locales in `isPostalCode()`\n  ([#830](https://github.com/validatorjs/validator.js/pull/830))\n\n#### 10.1.0\n\n- Added an `isISO31661Alpha3()` validator\n  ([#809](https://github.com/validatorjs/validator.js/pull/809))\n\n#### 10.0.0\n\n- Allow floating points in `isNumeric()`\n  ([#810](https://github.com/validatorjs/validator.js/pull/810))\n- Disallow GMail addresses with multiple consecutive dots, or leading/trailing dots\n  ([#820](https://github.com/validatorjs/validator.js/pull/820))\n- Added an `isRFC3339()` validator\n  ([#816](https://github.com/validatorjs/validator.js/pull/816))\n- Reject domain parts longer than 63 octets in `isFQDN()`, `isURL()` and `isEmail()`\n  ([bb3e542](https://github.com/validatorjs/validator.js/commit/bb3e542))\n- Added a new Amex prefix to `isCreditCard()`\n  ([#805](https://github.com/validatorjs/validator.js/pull/805))\n- Fixed `isFloat()` min/max/gt/lt filters when a locale with a comma decimal is used\n  ([2b70821](https://github.com/validatorjs/validator.js/commit/2b70821))\n- Normalize Yandex emails\n  ([#807](https://github.com/validatorjs/validator.js/pull/807))\n- New locales\n  ([#803](https://github.com/validatorjs/validator.js/pull/803))\n\n#### 9.4.1\n\n- Patched a [REDOS](https://en.wikipedia.org/wiki/ReDoS) vulnerability in `isDataURI`\n- New and improved locales\n  ([#788](https://github.com/validatorjs/validator.js/pull/788))\n\n#### 9.4.0\n\n- Added an option to `isMobilePhone` to require a country code\n  ([#769](https://github.com/validatorjs/validator.js/pull/769))\n- New and improved locales\n  ([#785](https://github.com/validatorjs/validator.js/pull/785))\n\n#### 9.3.0\n\n- New and improved locales\n  ([#763](https://github.com/validatorjs/validator.js/pull/763),\n  [#768](https://github.com/validatorjs/validator.js/pull/768),\n  [#774](https://github.com/validatorjs/validator.js/pull/774),\n  [#777](https://github.com/validatorjs/validator.js/pull/777),\n  [#779](https://github.com/validatorjs/validator.js/pull/779))\n\n#### 9.2.0\n\n- Added an `isMimeType()` validator\n  ([#760](https://github.com/validatorjs/validator.js/pull/760))\n- New and improved locales\n  ([#753](https://github.com/validatorjs/validator.js/pull/753),\n  [#755](https://github.com/validatorjs/validator.js/pull/755),\n  [#764](https://github.com/validatorjs/validator.js/pull/764))\n\n#### 9.1.2\n\n- Fixed a bug with the `isFloat` validator\n  ([#752](https://github.com/validatorjs/validator.js/pull/752))\n\n#### 9.1.1\n\n- Locale fixes\n  ([#738](https://github.com/validatorjs/validator.js/pull/738),\n  [#739](https://github.com/validatorjs/validator.js/pull/739))\n\n#### 9.1.0\n\n- Added an `isISO31661Alpha2()` validator\n  ([#734](https://github.com/validatorjs/validator.js/pull/734))\n- New locales\n  ([#735](https://github.com/validatorjs/validator.js/pull/735),\n  [#737](https://github.com/validatorjs/validator.js/pull/737))\n\n#### 9.0.0\n\n- `normalizeEmail()` no longer validates the email address\n  ([#725](https://github.com/validatorjs/validator.js/pull/725))\n- Added locale-aware validation to `isFloat()` and `isDecimal()`\n  ([#721](https://github.com/validatorjs/validator.js/pull/721))\n- Added an `isPort()` validator\n  ([#733](https://github.com/validatorjs/validator.js/pull/733))\n- New locales\n  ([#731](https://github.com/validatorjs/validator.js/pull/731))\n\n#### 8.2.0\n\n- Added an `isHash()` validator\n  ([#711](https://github.com/validatorjs/validator.js/pull/711))\n- Control decimal places in `isCurrency()`\n  ([#713](https://github.com/validatorjs/validator.js/pull/713))\n- New and improved locales\n  ([#700](https://github.com/validatorjs/validator.js/pull/700),\n  [#701](https://github.com/validatorjs/validator.js/pull/701),\n  [#714](https://github.com/validatorjs/validator.js/pull/714),\n  [#715](https://github.com/validatorjs/validator.js/pull/715),\n  [#718](https://github.com/validatorjs/validator.js/pull/718))\n\n#### 8.1.0\n\n- Fix `require('validator/lib/isIS8601')` calls\n  ([#688](https://github.com/validatorjs/validator.js/issues/688))\n- Added an `isLatLong()` and `isPostalCode()` validator\n  ([#684](https://github.com/validatorjs/validator.js/pull/684))\n- Allow comma in email display names\n  ([#692](https://github.com/validatorjs/validator.js/pull/692))\n- Add missing string to `unescape()`\n  ([#690](https://github.com/validatorjs/validator.js/pull/690))\n- Fix `isMobilePhone()` with Node <= 6.x\n  ([#681](https://github.com/validatorjs/validator.js/issues/681))\n- New locales\n  ([#695](https://github.com/validatorjs/validator.js/pull/695))\n\n#### 8.0.0\n\n- `isURL()` now requires the `require_tld: false` option to validate `localhost`\n  ([#675](https://github.com/validatorjs/validator.js/issues/675))\n- `isURL()` now rejects URLs that are protocol only\n  ([#642](https://github.com/validatorjs/validator.js/issues/642))\n- Fixed a bug where `isMobilePhone()` would silently return false if the locale was invalid or unsupported\n  ([#657](https://github.com/validatorjs/validator.js/issues/657))\n\n#### 7.2.0\n\n- Added an option to validate any phone locale\n  ([#663](https://github.com/validatorjs/validator.js/pull/663))\n- Fixed a bug in credit card validation\n  ([#672](https://github.com/validatorjs/validator.js/pull/672))\n- Disallow whitespace, including unicode whitespace, in TLDs\n  ([#677](https://github.com/validatorjs/validator.js/pull/677))\n- New locales\n  ([#673](https://github.com/validatorjs/validator.js/pull/673),\n  [#676](https://github.com/validatorjs/validator.js/pull/676))\n\n#### 7.1.0\n\n- Added an `isISRC()` validator for [ISRC](https://en.wikipedia.org/wiki/International_Standard_Recording_Code)\n  ([#660](https://github.com/validatorjs/validator.js/pull/660))\n- Fixed a bug in credit card validation\n  ([#670](https://github.com/validatorjs/validator.js/pull/670))\n- Reduced the maximum allowed address in `isEmail()` based on\n  [RFC3696 errata](http://www.rfc-editor.org/errata_search.php?rfc=3696&eid=1690)\n  ([#655](https://github.com/validatorjs/validator.js/issues/655))\n- New locales\n  ([#647](https://github.com/validatorjs/validator.js/pull/647),\n  [#667](https://github.com/validatorjs/validator.js/pull/667),\n  [#667](https://github.com/validatorjs/validator.js/pull/667),\n  [#671](https://github.com/validatorjs/validator.js/pull/671))\n\n#### 7.0.0\n\n- Remove `isDate()`\n\n#### 6.3.0\n\n- Allow values like `-.01` in `isFloat()`\n  ([#618](https://github.com/validatorjs/validator.js/issues/618))\n- New locales\n  ([#616](https://github.com/validatorjs/validator.js/pull/616),\n  [#622](https://github.com/validatorjs/validator.js/pull/622),\n  [#627](https://github.com/validatorjs/validator.js/pull/627),\n  [#630](https://github.com/validatorjs/validator.js/pull/630))\n\n#### 6.2.1\n\n- Disallow `<` and `>` in URLs\n  ([#613](https://github.com/validatorjs/validator.js/issues/613))\n- New locales\n  ([#610](https://github.com/validatorjs/validator.js/pull/610))\n\n#### 6.2.0\n\n- Added an option to require an email display name\n  ([#607](https://github.com/validatorjs/validator.js/pull/607))\n- Added support for `lt` and `gt` to `isInt()`\n  ([#588](https://github.com/validatorjs/validator.js/pull/588))\n- New locales\n  ([#601](https://github.com/validatorjs/validator.js/pull/601))\n\n#### 6.1.0\n\n- Added support for greater or less than in `isFloat()`\n  ([#544](https://github.com/validatorjs/validator.js/issues/544))\n- Added support for ISSN validation via `isISSN()`\n  ([#593](https://github.com/validatorjs/validator.js/pull/593))\n- Fixed a bug in `normalizeEmail()`\n  ([#594](https://github.com/validatorjs/validator.js/issues/594))\n- New locales\n  ([#585](https://github.com/validatorjs/validator.js/pull/585))\n\n#### 6.0.0\n\n- Renamed `isNull()` to `isEmpty()`\n  ([#574](https://github.com/validatorjs/validator.js/issues/574))\n- Backslash is now escaped in `escape()`\n  ([#516](https://github.com/validatorjs/validator.js/issues/516))\n- Improved `normalizeEmail()`\n  ([#583](https://github.com/validatorjs/validator.js/pull/583))\n- Allow leading zeroes by default in `isInt()`\n  ([#532](https://github.com/validatorjs/validator.js/pull/532))\n\n#### 5.7.0\n\n- Added support for IPv6 in `isURL()`\n  ([#564](https://github.com/validatorjs/validator.js/issues/564))\n- Added support for urls without a host (e.g. `file:///foo.txt`) in `isURL()`\n  ([#563](https://github.com/validatorjs/validator.js/issues/563))\n- Added support for regular expressions in the `isURL()` host whitelist and blacklist\n  ([#562](https://github.com/validatorjs/validator.js/issues/562))\n- Added support for MasterCard 2-Series BIN\n  ([#576](https://github.com/validatorjs/validator.js/pull/576))\n- New locales\n  ([#575](https://github.com/validatorjs/validator.js/pull/575),\n  [#552](https://github.com/validatorjs/validator.js/issues/552))\n\n#### 5.6.0\n\n- Added an `isMD5()` validator\n  ([#557](https://github.com/validatorjs/validator.js/pull/557))\n- Fixed an exceptional case in `isDate()`\n  ([#566](https://github.com/validatorjs/validator.js/pull/566))\n- New locales\n  ([#559](https://github.com/validatorjs/validator.js/pull/559),\n  [#568](https://github.com/validatorjs/validator.js/pull/568),\n  [#571](https://github.com/validatorjs/validator.js/pull/571),\n  [#573](https://github.com/validatorjs/validator.js/pull/573))\n\n#### 5.5.0\n\n- Fixed a regex denial of service in `trim()` and `rtrim()`\n  ([#556](https://github.com/validatorjs/validator.js/pull/556))\n- Added an Algerian locale to `isMobilePhone()`\n  ([#540](https://github.com/validatorjs/validator.js/pull/540))\n- Fixed the Hungarian locale in `isAlpha()` and `isAlphanumeric()`\n  ([#541](https://github.com/validatorjs/validator.js/pull/541))\n- Added a Polish locale to `isMobilePhone()`\n  ([#545](https://github.com/validatorjs/validator.js/pull/545))\n\n#### 5.4.0\n\n- Accept Union Pay credit cards in `isCreditCard()`\n  ([#539](https://github.com/validatorjs/validator.js/pull/539))\n- Added Danish locale to `isMobilePhone()`\n  ([#538](https://github.com/validatorjs/validator.js/pull/538))\n- Added Hungarian locales to `isAlpha()`, `isAlphanumeric()` and `isMobilePhone()`\n  ([#537](https://github.com/validatorjs/validator.js/pull/537))\n\n#### 5.3.0\n\n- Added an `allow_leading_zeroes` option to `isInt()`\n  ([#532](https://github.com/validatorjs/validator.js/pull/532))\n- Adjust Chinese mobile phone validation\n  ([#523](https://github.com/validatorjs/validator.js/pull/523))\n- Added a Canadian locale to `isMobilePhone()`\n  ([#524](https://github.com/validatorjs/validator.js/issues/524))\n\n#### 5.2.0\n\n- Added a `isDataURI()` validator\n  ([#521](https://github.com/validatorjs/validator.js/pull/521))\n- Added Czech locales\n  ([#522](https://github.com/validatorjs/validator.js/pull/522))\n- Fixed a bug with `isURL()` when protocol was missing and \"://\" appeared in the query\n  ([#518](https://github.com/validatorjs/validator.js/issues/518))\n\n#### 5.1.0\n\n- Added a `unescape()` HTML function\n  ([#509](https://github.com/validatorjs/validator.js/pull/509))\n- Added a Malaysian locale to `isMobilePhone()`\n  ([#507](https://github.com/validatorjs/validator.js/pull/507))\n- Added Polish locales to `isAlpha()` and `isAlphanumeric()`\n  ([#506](https://github.com/validatorjs/validator.js/pull/506))\n- Added Turkish locales to `isAlpha()`, `isAlphanumeric()` and `isMobilePhone()`\n  ([#512](https://github.com/validatorjs/validator.js/pull/512))\n- Allow >1 underscore in hostnames when using `allow_underscores`\n  ([#510](https://github.com/validatorjs/validator.js/issues/510))\n\n#### 5.0.0\n\n- Migrate to ES6\n  ([#496](https://github.com/validatorjs/validator.js/pull/496))\n- Break the library up so that individual functions can be imported\n  ([#496](https://github.com/validatorjs/validator.js/pull/496))\n- Remove auto-coercion of input to a string\n  ([#496](https://github.com/validatorjs/validator.js/pull/496))\n- Remove the `extend()` function\n  ([#496](https://github.com/validatorjs/validator.js/pull/496))\n- Added Arabic locales to `isAlpha()` and `isAlphanumeric()`\n  ([#496](https://github.com/validatorjs/validator.js/pull/496#issuecomment-184781730))\n- Fix validation of very large base64 strings\n  ([#503](https://github.com/validatorjs/validator.js/pull/503))\n\n#### 4.9.0\n\n- Added a Russian locale to `isAlpha()` and `isAlphanumeric()`\n  ([#499](https://github.com/validatorjs/validator.js/pull/499))\n- Remove the restriction on adjacent hyphens in hostnames\n  ([#500](https://github.com/validatorjs/validator.js/issues/500))\n\n#### 4.8.0\n\n- Added Spanish, French, Portuguese and Dutch support for `isAlpha()` and `isAlphanumeric()`\n  ([#492](https://github.com/validatorjs/validator.js/pull/492))\n- Added a Brazilian locale to `isMobilePhone()`\n  ([#489](https://github.com/validatorjs/validator.js/pull/489))\n- Reject IPv4 addresses with invalid zero padding\n  ([#490](https://github.com/validatorjs/validator.js/pull/490))\n- Fix the client-side version when used with RequireJS\n  ([#494](https://github.com/validatorjs/validator.js/issues/494))\n\n#### 4.7.1\n\n- Use [node-depd](https://github.com/dougwilson/nodejs-depd) to print deprecation notices\n  ([#487](https://github.com/validatorjs/validator.js/issues/487))\n\n#### 4.7.0\n\n- Print a deprecation warning if validator input is not a string\n  ([1f67e1e](https://github.com/validatorjs/validator.js/commit/1f67e1e15198c0ae735151290dc8dc2bf14da254)).\n  Note that this will be an error in v5.\n- Added a German locale to `isMobilePhone()`, `isAlpha()` and `isAlphanumeric()`\n  ([#477](https://github.com/validatorjs/validator.js/pull/477))\n- Added a Finnish locale to `isMobilePhone()`\n  ([#455](https://github.com/validatorjs/validator.js/pull/455))\n\n#### 4.6.1\n\n- Fix coercion of objects: `Object.toString()` is `[object Object]` not `\"\"`\n  ([a57f3c8](https://github.com/validatorjs/validator.js/commit/a57f3c843c715fba2664ee22ec80e9e28e88e0a6))\n\n#### 4.6.0\n\n- Added a Spanish locale to `isMobilePhone()`\n  ([#481](https://github.com/validatorjs/validator.js/pull/481))\n- Fix string coercion of objects created with `Object.create(null)`\n  ([#484](https://github.com/validatorjs/validator.js/issues/484))\n\n#### 4.5.2\n\n- Fix a timezone issue with short-form ISO 8601 dates, e.g.\n  `validator.isDate('2011-12-21')`\n  ([#480](https://github.com/validatorjs/validator.js/issues/480))\n\n#### 4.5.1\n\n- Make `isLength()` / `isByteLength()` accept `{min, max}` as options object.\n  ([#474](https://github.com/validatorjs/validator.js/issues/474))\n\n#### 4.5.0\n\n- Add validation for Indian mobile phone numbers\n  ([#471](https://github.com/validatorjs/validator.js/pull/471))\n- Tweak Greek and Chinese mobile phone validation\n  ([#467](https://github.com/validatorjs/validator.js/pull/467),\n  [#468](https://github.com/validatorjs/validator.js/pull/468))\n- Fixed a bug in `isDate()` when validating ISO 8601 dates without a timezone\n  ([#472](https://github.com/validatorjs/validator.js/issues/472))\n\n#### 4.4.1\n\n- Allow triple hyphens in IDNA hostnames\n  ([#466](https://github.com/validatorjs/validator.js/issues/466))\n\n#### 4.4.0\n\n- Added `isMACAddress()` validator\n  ([#458](https://github.com/validatorjs/validator.js/pull/458))\n- Added `isWhitelisted()` validator\n  ([#462](https://github.com/validatorjs/validator.js/pull/462))\n- Added a New Zealand locale to `isMobilePhone()`\n  ([#452](https://github.com/validatorjs/validator.js/pull/452))\n- Added options to control GMail address normalization\n  ([#460](https://github.com/validatorjs/validator.js/pull/460))\n\n#### 4.3.0\n\n- Support Ember CLI module definitions\n  ([#448](https://github.com/validatorjs/validator.js/pull/448))\n- Added a Vietnam locale to `isMobilePhone()`\n  ([#451](https://github.com/validatorjs/validator.js/pull/451))\n\n#### 4.2.1\n\n- Fix `isDate()` handling of RFC2822 timezones\n  ([#447](https://github.com/validatorjs/validator.js/pull/447))\n\n#### 4.2.0\n\n- Fix `isDate()` handling of ISO8601 timezones\n  ([#444](https://github.com/validatorjs/validator.js/pull/444))\n- Fix the incorrect `isFloat('.') === true`\n  ([#443](https://github.com/validatorjs/validator.js/pull/443))\n- Added a Norwegian locale to `isMobilePhone()`\n  ([#439](https://github.com/validatorjs/validator.js/pull/439))\n\n#### 4.1.0\n\n- General `isDate()` improvements\n  ([#431](https://github.com/validatorjs/validator.js/pull/431))\n- Tests now require node 4.0+\n  ([#438](https://github.com/validatorjs/validator.js/pull/438))\n\n#### 4.0.6\n\n- Added a Taiwan locale to `isMobilePhone()`\n  ([#432](https://github.com/validatorjs/validator.js/pull/432))\n- Fixed a bug in `isBefore()` where it would return `null`\n  ([#436](https://github.com/validatorjs/validator.js/pull/436))\n\n#### 4.0.5\n\n- Fixed a denial of service vulnerability in the `isEmail()` regex\n  ([#152](https://github.com/validatorjs/validator.js/issues/152#issuecomment-131874928))\n\n#### 4.0.4\n\n- Reverted the leap year validation in `isDate()` as it introduced some regressions\n  ([#422](https://github.com/validatorjs/validator.js/issues/422), [#423](https://github.com/validatorjs/validator.js/issues/423))\n\n#### 4.0.3\n\n- Added leap year validation to `isDate()`\n  ([#418](https://github.com/validatorjs/validator.js/pull/418))\n\n#### 4.0.2\n\n- Fixed `isDecimal()` with an empty string\n  ([#419](https://github.com/validatorjs/validator.js/issues/419))\n\n#### 4.0.1\n\n- Fixed `isByteLength()` with certain strings\n  ([09f0c6d](https://github.com/validatorjs/validator.js/commit/09f0c6d2321f0c78af6a7de42e91b63955e4c01e))\n- Put length restrictions on email parts\n  ([#258](https://github.com/validatorjs/validator.js/issues/258#issuecomment-127173612))\n\n#### 4.0.0\n\n- Simplified the `isEmail()` regex and fixed some edge cases\n  ([#258](https://github.com/validatorjs/validator.js/issues/258#issuecomment-127173612))\n- Added ISO 8601 date validation via `isISO8601()`\n  ([#373](https://github.com/validatorjs/validator.js/issues/373))\n"
  },
  {
    "path": "CONTRIBUTING.md",
    "content": "# Contributing to validator.js\nWelcome to validator.js repository!! We appreciate your interest in contributing to this open library and for helping our community grow. \n\n## How to Contribute\n### Code Contribution\nIn general, we follow the \"fork-and-pull\" Git workflow.\n\n1. [Fork](https://docs.github.com/en/get-started/exploring-projects-on-github/contributing-to-a-project) the repository on GitHub\n2. Clone the project to your local machine\n3. Work on your fork\n    * Install the project using `npm install --legacy-peer-deps` (see [issue](https://github.com/validatorjs/validator.js/issues/2123))\n    * Make your changes and additions\n        - Most of your changes should be focused on src/ and test/ folders and/or [README.md](https://github.com/validatorjs/validator.js/blob/master/README.md).\n        - Files such as validator.js, validator.min.js and files in lib/ folder are autogenerated when running tests (npm test) and need not to be changed **manually**.\n    * Change or add tests if needed\n    * Run tests and make sure they pass\n    * Add changes to README.md if needed\n4. Commit changes to your own branch\n5. **Make sure** you merge the latest from \"upstream\" and resolve conflicts if there is any\n6. Repeat step 3(3) above\n7. Push your work back up to your fork\n8. Submit a Pull request so that we can review your changes\n\n#### Run Tests\nTests are using mocha. To run the tests use:\n\n```sh\n$ npm test\n```\n\n### Financial Contribution\nWe welcome financial contributions on our [open collective](https://opencollective.com/validatorjs).\n\nYou can opt to become a [backer](https://opencollective.com/validatorjs#backer) or a [sponsor](https://opencollective.com/validatorjs#sponsor) and help our project sustain over time.\n\nThank you to the people who have already contributed:\n\n<a href=\"https://github.com/validatorjs/validator.js/graphs/contributors\"><img src=\"https://opencollective.com/validatorjs/contributors.svg?width=890\" /></a>"
  },
  {
    "path": "LICENSE",
    "content": "Copyright (c) 2018 Chris O'Hara <cohara87@gmail.com>\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n\"Software\"), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE\nLIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\nOF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\nWITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n"
  },
  {
    "path": "README.md",
    "content": "# validator.js\n[![NPM version][npm-image]][npm-url]\n[![CI][ci-image]][ci-url]\n[![Coverage][codecov-image]][codecov-url]\n[![Downloads][downloads-image]][npm-url]\n[![Backers on Open Collective](https://opencollective.com/validatorjs/backers/badge.svg)](#backers)\n[![Sponsors on Open Collective](https://opencollective.com/validatorjs/sponsors/badge.svg)](#sponsors)\n[![License](https://img.shields.io/badge/License-MIT-red.svg)](https://github.com/alguerocode/validator.js/blob/master/LICENSE)\n[![Gitter][gitter-image]][gitter-url]\n\nA library of string validators and sanitizers.\n\n## Strings only\n\n**This library validates and sanitizes strings only.**\n\nIf you're not sure if your input is a string, coerce it using `input + ''`.\nPassing anything other than a string will result in an error.\n\n## Installation and Usage\n\n### Server-side usage\n\nInstall the `validator` package as:\n\n```sh\nnpm i validator\nyarn add validator\npnpm i validator\n```\n\n#### No ES6\n\n```javascript\nvar validator = require('validator');\n\nvalidator.isEmail('foo@bar.com'); //=> true\n```\n\n#### ES6\n\n```javascript\nimport validator from 'validator';\n```\n\nOr, import only a subset of the library:\n\n```javascript\nimport isEmail from 'validator/lib/isEmail';\n```\n\n#### Tree-shakeable ES imports\n\n```javascript\nimport isEmail from 'validator/es/lib/isEmail';\n```\n\n### Client-side usage\n\nThe library can be loaded either as a standalone script, or through an [AMD][amd]-compatible loader\n\n```html\n<script type=\"text/javascript\" src=\"validator.min.js\"></script>\n<script type=\"text/javascript\">\n  validator.isEmail('foo@bar.com'); //=> true\n</script>\n```\n\nThe library can also be installed through [bower][bower]\n\n```bash\n$ bower install validator-js\n```\n\nCDN\n\n```html\n<script src=\"https://unpkg.com/validator@latest/validator.min.js\"></script>\n```\n\n## Validators\n\nHere is a list of the validators currently available.\n\nValidator                               | Description\n--------------------------------------- | --------------------------------------\n**contains(str, seed [, options])**    | check if the string contains the seed.<br/><br/>`options` is an object that defaults to `{ ignoreCase: false, minOccurrences: 1 }`.<br />Options: <br/> `ignoreCase`: Ignore case when doing comparison, default false.<br/>`minOccurrences`: Minimum number of occurrences for the seed in the string. Defaults to 1.\n**equals(str, comparison)**             | check if the string matches the comparison.\n**isAbaRouting(str)**               | check if the string is an ABA routing number for US bank account / cheque.\n**isAfter(str [, options])**            | check if the string is a date that is after the specified date.<br/><br/>`options` is an object that defaults to `{ comparisonDate: Date().toString() }`.<br/>**Options:**<br/>`comparisonDate`: Date to compare to. Defaults to `Date().toString()` (now).\n**isAlpha(str [, locale, options])**    | check if the string contains only letters (a-zA-Z).<br/><br/>`locale` is one of `['ar', 'ar-AE', 'ar-BH', 'ar-DZ', 'ar-EG', 'ar-IQ', 'ar-JO', 'ar-KW', 'ar-LB', 'ar-LY', 'ar-MA', 'ar-QA', 'ar-QM', 'ar-SA', 'ar-SD', 'ar-SY', 'ar-TN', 'ar-YE', 'bg-BG', 'bn', 'bn-IN', 'cs-CZ', 'da-DK', 'de-DE', 'el-GR', 'en-AU', 'en-GB', 'en-HK', 'en-IN', 'en-NZ', 'en-US', 'en-ZA', 'en-ZM', 'eo', 'es-ES', 'fa-IR', 'fi-FI', 'fr-CA', 'fr-FR', 'gu-IN', 'he', 'hi-IN', 'hu-HU', 'it-IT', 'ja-JP', 'kk-KZ', 'kn-IN', 'ko-KR', 'ku-IQ', 'ml-IN', 'nb-NO', 'nl-NL', 'nn-NO', 'or-IN', 'pa-IN', 'pl-PL', 'pt-BR', 'pt-PT', 'ru-RU', 'si-LK', 'sk-SK', 'sl-SI', 'sr-RS', 'sr-RS@latin', 'sv-SE', 'ta-IN', 'te-IN', 'th-TH', 'tr-TR', 'uk-UA']` and defaults to `en-US`. Locale list is `validator.isAlphaLocales`. `options` is an optional object that can be supplied with the following key(s): `ignore` which can either be a String or RegExp of characters to be ignored e.g. \" -\" will ignore spaces and -'s.\n**isAlphanumeric(str [, locale, options])**      | check if the string contains only letters and numbers (a-zA-Z0-9).<br/><br/>`locale` is one of `['ar', 'ar-AE', 'ar-BH', 'ar-DZ', 'ar-EG', 'ar-IQ', 'ar-JO', 'ar-KW', 'ar-LB', 'ar-LY', 'ar-MA', 'ar-QA', 'ar-QM', 'ar-SA', 'ar-SD', 'ar-SY', 'ar-TN', 'ar-YE', 'bg-BG', 'bn', 'bn-IN', 'cs-CZ', 'da-DK', 'de-DE', 'el-GR', 'en-AU', 'en-GB', 'en-HK', 'en-IN', 'en-NZ', 'en-US', 'en-ZA', 'en-ZM', 'eo', 'es-ES', 'fa-IR', 'fi-FI', 'fr-CA', 'fr-FR', 'gu-IN', 'he', 'hi-IN', 'hu-HU', 'it-IT', 'ja-JP', 'kk-KZ', 'kn-IN', 'ko-KR', 'ku-IQ', 'ml-IN', 'nb-NO', 'nl-NL', 'nn-NO', 'or-IN', 'pa-IN', 'pl-PL', 'pt-BR', 'pt-PT', 'ru-RU', 'si-LK', 'sk-SK', 'sl-SI', 'sr-RS', 'sr-RS@latin', 'sv-SE', 'ta-IN', 'te-IN', 'th-TH', 'tr-TR', 'uk-UA']`) and defaults to `en-US`. Locale list is `validator.isAlphanumericLocales`. `options` is an optional object that can be supplied with the following key(s): `ignore` which can either be a String or RegExp of characters to be ignored e.g. \" -\" will ignore spaces and -'s.\n**isAscii(str)**                        | check if the string contains ASCII chars only.\n**isBase32(str [, options])**           | check if the string is base32 encoded. `options` is optional and defaults to `{ crockford: false }`.<br/> When `crockford` is true it tests the given base32 encoded string using [Crockford's base32 alternative][Crockford Base32].\n**isBase58(str)**                       | check if the string is base58 encoded.\n**isBase64(str [, options])**          | check if the string is base64 encoded. `options` is optional and defaults to `{ urlSafe: false, padding: true }`<br/> when `urlSafe` is true default value for `padding` is false and it tests the given base64 encoded string is [url safe][Base64 URL Safe].\n**isBefore(str [, options])**              | check if the string is a date that is before the specified date.<br/><br/>`options` is an object that defaults to `{ comparisonDate: Date().toString() }`.<br/><br/>**Options:**<br/>`comparisonDate`: Date to compare to. Defaults to `Date().toString()` (now).\n**isBIC(str)**                          | check if the string is a BIC (Bank Identification Code) or SWIFT code.\n**isBoolean(str [, options])**          | check if the string is a boolean.<br/>`options` is an object which defaults to `{ loose: false }`. If `loose` is set to false, the validator will strictly match ['true', 'false', '0', '1']. If `loose` is set to true, the validator will also match 'yes', 'no', and will match a valid boolean string of any case. (e.g.: ['true', 'True', 'TRUE']).\n**isBtcAddress(str)**            | check if the string is a valid BTC address.\n**isByteLength(str [, options])**          | check if the string's length (in UTF-8 bytes) falls in a range.<br/><br/>`options` is an object which defaults to `{ min: 0, max: undefined }`.\n**isCreditCard(str [, options])**                   | check if the string is a credit card number.<br/><br/> `options` is an optional object that can be supplied with the following key(s): `provider` is an optional key whose value should be a string, and defines the company issuing the credit card. Valid values include `['amex', 'dinersclub', 'discover', 'jcb', 'mastercard', 'unionpay', 'visa']` or blank will check for any provider.\n**isCurrency(str [, options])**            | check if the string is a valid currency amount.<br/><br/>`options` is an object which defaults to `{ symbol: '$', require_symbol: false, allow_space_after_symbol: false, symbol_after_digits: false, allow_negatives: true, parens_for_negatives: false, negative_sign_before_digits: false, negative_sign_after_digits: false, allow_negative_sign_placeholder: false, thousands_separator: ',', decimal_separator: '.', allow_decimal: true, require_decimal: false, digits_after_decimal: [2], allow_space_after_digits: false }`.<br/>**Note:** The array `digits_after_decimal` is filled with the exact number of digits allowed not a range, for example a range 1 to 3 will be given as [1, 2, 3].\n**isDataURI(str)**                      | check if the string is a [data uri format][Data URI Format].\n**isDate(str [, options])**          | check if the string is a valid date. e.g. [`2002-07-15`, new Date()].<br/><br/> `options` is an object which can contain the keys `format`, `strictMode` and/or `delimiters`.<br/><br/>`format` is a string and defaults to `YYYY/MM/DD`.<br/><br/>`strictMode` is a boolean and defaults to `false`. If `strictMode` is set to true, the validator will reject strings different from `format`.<br/><br/> `delimiters` is an array of allowed date delimiters and defaults to `['/', '-']`.\n**isDecimal(str [, options])**             | check if the string represents a decimal number, such as 0.1, .3, 1.1, 1.00003, 4.0, etc.<br/><br/>`options` is an object which defaults to `{force_decimal: false, decimal_digits: '1,', locale: 'en-US'}`.<br/><br/>`locale` determines the decimal separator and is one of `['ar', 'ar-AE', 'ar-BH', 'ar-DZ', 'ar-EG', 'ar-IQ', 'ar-JO', 'ar-KW', 'ar-LB', 'ar-LY', 'ar-MA', 'ar-QA', 'ar-QM', 'ar-SA', 'ar-SD', 'ar-SY', 'ar-TN', 'ar-YE', 'bg-BG', 'cs-CZ', 'da-DK', 'de-DE', 'el-GR', 'en-AU', 'en-GB', 'en-HK', 'en-IN', 'en-NZ', 'en-US', 'en-ZA', 'en-ZM', 'eo', 'es-ES', 'fa', 'fa-AF', 'fa-IR', 'fr-FR', 'fr-CA', 'hu-HU', 'id-ID', 'it-IT', 'ku-IQ', 'nb-NO', 'nl-NL', 'nn-NO', 'pl-PL', 'pl-Pl', 'pt-BR', 'pt-PT', 'ru-RU', 'sl-SI', 'sr-RS', 'sr-RS@latin', 'sv-SE', 'tr-TR', 'uk-UA', 'vi-VN']`.<br/>**Note:** `decimal_digits` is given as a range like '1,3', a specific value like '3' or min like '1,'.\n**isDivisibleBy(str, number)**          | check if the string is a number that is divisible by another.\n**isEAN(str)**                          | check if the string is an [EAN (European Article Number)][European Article Number].\n**isEmail(str [, options])**            | check if the string is an email.<br/><br/>`options` is an object which defaults to `{ allow_display_name: false, require_display_name: false, allow_utf8_local_part: true, require_tld: true, allow_ip_domain: false, allow_underscores: false, domain_specific_validation: false, blacklisted_chars: '', host_blacklist: [] }`. If `allow_display_name` is set to true, the validator will also match `Display Name <email-address>`. If `require_display_name` is set to true, the validator will reject strings without the format `Display Name <email-address>`. If `allow_utf8_local_part` is set to false, the validator will not allow any non-English UTF8 character in email address' local part. If `require_tld` is set to false, email addresses without a TLD in their domain will also be matched. If `ignore_max_length` is set to true, the validator will not check for the standard max length of an email. If `allow_ip_domain` is set to true, the validator will allow IP addresses in the host part. If `domain_specific_validation` is true, some additional validation will be enabled, e.g. disallowing certain syntactically valid email addresses that are rejected by Gmail. If `blacklisted_chars` receives a string, then the validator will reject emails that include any of the characters in the string, in the name part. If `host_blacklist` is set to an array of strings or regexp, and the part of the email after the `@` symbol matches one of the strings defined in it, the validation fails. If `host_whitelist` is set to an array of strings or regexp, and the part of the email after the `@` symbol matches none of the strings defined in it, the validation fails.\n**isEmpty(str [, options])**            | check if the string has a length of zero.<br/><br/>`options` is an object which defaults to `{ ignore_whitespace: false }`.\n**isEthereumAddress(str)**              | check if the string is an [Ethereum][Ethereum] address. Does not validate address checksums.\n**isFloat(str [, options])**            | check if the string is a float.<br/><br/>`options` is an object which can contain the keys `min`, `max`, `gt`, and/or `lt` to validate the float is within boundaries (e.g. `{ min: 7.22, max: 9.55 }`) it also has `locale` as an option.<br/><br/>`min` and `max` are equivalent to 'greater or equal' and 'less or equal', respectively while `gt` and `lt` are their strict counterparts.<br/><br/>`locale` determines the decimal separator and is one of `['ar', 'ar-AE', 'ar-BH', 'ar-DZ', 'ar-EG', 'ar-IQ', 'ar-JO', 'ar-KW', 'ar-LB', 'ar-LY', 'ar-MA', 'ar-QA', 'ar-QM', 'ar-SA', 'ar-SD', 'ar-SY', 'ar-TN', 'ar-YE', 'bg-BG', 'cs-CZ', 'da-DK', 'de-DE', 'en-AU', 'en-GB', 'en-HK', 'en-IN', 'en-NZ', 'en-US', 'en-ZA', 'en-ZM', 'eo', 'es-ES', 'fr-CA', 'fr-FR', 'hu-HU', 'it-IT', 'nb-NO', 'nl-NL', 'nn-NO', 'pl-PL', 'pt-BR', 'pt-PT', 'ru-RU', 'sl-SI', 'sr-RS', 'sr-RS@latin', 'sv-SE', 'tr-TR', 'uk-UA']`. Locale list is `validator.isFloatLocales`.\n**isFQDN(str [, options])**             | check if the string is a fully qualified domain name (e.g. domain.com).<br/><br/>`options` is an object which defaults to `{ require_tld: true, allow_underscores: false, allow_trailing_dot: false, allow_numeric_tld: false, allow_wildcard: false, ignore_max_length: false }`.<br/><br/>`require_tld` - If set to false the validator will not check if the domain includes a TLD.<br/>`allow_underscores` - if set to true, the validator will allow underscores in the domain.<br/>`allow_trailing_dot` - if set to true, the validator will allow the domain to end with a `.` character.<br/>`allow_numeric_tld` - if set to true, the validator will allow the TLD of the domain to be made up solely of numbers.<br />`allow_wildcard` - if set to true, the validator will allow domains starting with `*.` (e.g. `*.example.com` or `*.shop.example.com`).<br/>`ignore_max_length` - if set to true, the validator will not check for the standard max length of a domain.<br/>\n**isFreightContainerID(str)**           | alias for `isISO6346`, check if the string is a valid [ISO 6346](https://en.wikipedia.org/wiki/ISO_6346) shipping container identification.\n**isFullWidth(str)**                    | check if the string contains any full-width chars.\n**isHalfWidth(str)**                    | check if the string contains any half-width chars.\n**isHash(str, algorithm)**              | check if the string is a hash of type algorithm.<br/><br/>Algorithm is one of `['crc32', 'crc32b', 'md4', 'md5', 'ripemd128', 'ripemd160', 'sha1', 'sha256', 'sha384', 'sha512', 'tiger128', 'tiger160', 'tiger192']`.\n**isHexadecimal(str)**                  | check if the string is a hexadecimal number.\n**isHexColor(str [, options])**         | check if the string is a hexadecimal color. <br/><br/>`options` is an object that defaults to `{ require_hashtag: false }`.<br />Options: <br/> `require_hashtag`: Enforce # prefix, default false.\n**isHSL(str)**                          | check if the string is an HSL (hue, saturation, lightness, optional alpha) color based on [CSS Colors Level 4 specification][CSS Colors Level 4 Specification].<br/><br/>Comma-separated format supported. Space-separated format supported with the exception of a few edge cases (ex: `hsl(200grad+.1%62%/1)`).\n**isIBAN(str, [, options])**            | check if the string is an IBAN (International Bank Account Number).<br/><br/>`options` is an object which accepts two attributes: `whitelist`: where you can restrict IBAN codes you want to receive data from and `blacklist`: where you can remove some of the countries from the current list. For both you can use an array with the following values `['AD','AE','AL','AT','AZ','BA','BE','BG','BH','BR','BY','CH','CR','CY','CZ','DE','DK','DO','EE','EG','ES','FI','FO','FR','GB','GE','GI','GL','GR','GT','HR','HU','IE','IL','IQ','IR','IS','IT','JO','KW','KZ','LB','LC','LI','LT','LU','LV','MC','MD','ME','MK','MR','MT','MU','MZ','NL','NO','PK','PL','PS','PT','QA','RO','RS','SA','SC','SE','SI','SK','SM','SV','TL','TN','TR','UA','VA','VG','XK']`.\n**isIdentityCard(str [, locale])**      | check if the string is a valid identity card code.<br/><br/>`locale` is one of `['LK', 'PL', 'ES', 'FI', 'IN', 'IT', 'IR', 'MZ', 'NO', 'TH', 'zh-TW', 'he-IL', 'ar-LY', 'ar-TN', 'zh-CN', 'zh-HK', 'PK']` OR `'any'`. If 'any' is used, function will check if any of the locales match.<br/><br/>Defaults to 'any'.\n**isIMEI(str [, options]))**            | check if the string is a valid [IMEI number][IMEI]. IMEI should be of format `###############` or `##-######-######-#`.<br/><br/>`options` is an object which can contain the keys `allow_hyphens`. Defaults to first format. If `allow_hyphens` is set to true, the validator will validate the second format.\n**isIn(str, values)**                   | check if the string is in an array of allowed values.\n**isInt(str [, options])**              | check if the string is an integer.<br/><br/>`options` is an object which can contain the keys `min` and/or `max` to check the integer is within boundaries (e.g. `{ min: 10, max: 99 }`). `options` can also contain the key `allow_leading_zeroes`, which when set to false will disallow integer values with leading zeroes (e.g. `{ allow_leading_zeroes: false }`). Finally, `options` can contain the keys `gt` and/or `lt` which will enforce integers being greater than or less than, respectively, the value provided (e.g. `{gt: 1, lt: 4}` for a number between 1 and 4).\n**isIP(str [, options])**               | check if the string is an IP address (version 4 or 6).<br/><br/>`options` is an object that defaults to `{ version: '' }`.<br/><br/>**Options:**<br/>`version`: defines which IP version to compare to. Accepted values: `4`, `6`, `'4'`, `'6'`.\n**isIPRange(str [, version])**          | check if the string is an IP Range (version 4 or 6).\n**isISBN(str [, options])**             | check if the string is an [ISBN][ISBN].<br/><br/>`options` is an object that has no default.<br/>**Options:**<br/>`version`: ISBN version to compare to. Accepted values are '10' and '13'. If none provided, both will be tested.\n**isISIN(str)**                         | check if the string is an [ISIN][ISIN] (stock/security identifier).\n**isISO6346(str)**                      | check if the string is a valid [ISO 6346](https://en.wikipedia.org/wiki/ISO_6346) shipping container identification.\n**isISO6391(str)**                      | check if the string is a valid [ISO 639-1][ISO 639-1] language code.\n**isISO8601(str [, options])**          | check if the string is a valid [ISO 8601][ISO 8601] date. <br/>`options` is an object which defaults to `{ strict: false, strictSeparator: false }`. If `strict` is true, date strings with invalid dates like `2009-02-29` will be invalid. If `strictSeparator` is true, date strings with date and time separated by anything other than a T will be invalid.\n**isISO15924(str)**                     | check if the string is a valid [ISO 15924][ISO 15924] officially assigned script code.\n**isISO31661Alpha2(str [, options])**   | check if the string is a valid [ISO 3166-1 alpha-2][ISO 3166-1 alpha-2] officially assigned country code. <br/>`options` is an object which can contain the key `userAssignedCodes`: an array of custom codes that are not officially assigned (e.g. `['XK']`).\n**isISO31661Alpha3(str [, options])**   | check if the string is a valid [ISO 3166-1 alpha-3][ISO 3166-1 alpha-3] officially assigned country code. <br/>`options` is an object which can contain the key `userAssignedCodes`: an array of custom codes that are not officially assigned (e.g. `['XXK']`).\n**isISO31661Numeric(str)**              | check if the string is a valid [ISO 3166-1 numeric][ISO 3166-1 numeric] officially assigned country code.\n**isISO4217(str)**                      | check if the string is a valid [ISO 4217][ISO 4217] officially assigned currency code.\n**isISRC(str)**                         | check if the string is an [ISRC][ISRC].\n**isISSN(str [, options])**             | check if the string is an [ISSN][ISSN].<br/><br/>`options` is an object which defaults to `{ case_sensitive: false, require_hyphen: false }`. If `case_sensitive` is true, ISSNs with a lowercase `'x'` as the check digit are rejected.\n**isJSON(str [, options])**             | check if the string is valid JSON (note: uses JSON.parse).<br/><br/>`options` is an object which defaults to `{ allow_primitives: false }`. If `allow_primitives` is true, the primitives 'true', 'false' and 'null' are accepted as valid JSON values.\n**isJWT(str)**                          | check if the string is valid JWT token.\n**isLatLong(str [, options])**          | check if the string is a valid latitude-longitude coordinate in the format `lat,long` or `lat, long`.<br/><br/>`options` is an object that defaults to `{ checkDMS: false }`. Pass `checkDMS` as `true` to validate DMS(degrees, minutes, and seconds) latitude-longitude format.\n**isLength(str [, options])**           | check if the string's length falls in a range and equal to any of the integers of the `discreteLengths` array if provided.<br/><br/>`options` is an object which defaults to `{ min: 0, max: undefined, discreteLengths: undefined }`. Note: this function takes into account surrogate pairs.\n**isLicensePlate(str, locale)**         | check if the string matches the format of a country's license plate.<br/><br/>`locale` is one of `['cs-CZ', 'de-DE', 'de-LI', 'en-IN', 'en-SG', 'en-PK', 'es-AR', 'hu-HU', 'pt-BR', 'pt-PT', 'sq-AL', 'sv-SE']` or `'any'`.\n**isLocale(str)**                       | check if the string is a locale.\n**isLowercase(str)**                    | check if the string is lowercase.\n**isLuhnNumber(str)**                    | check if the string passes the [Luhn algorithm check](https://en.wikipedia.org/wiki/Luhn_algorithm).\n**isMACAddress(str [, options])**                   | check if the string is a MAC address.<br/><br/>`options` is an object which defaults to `{ no_separators: false }`. It allows the use of hyphens, spaces or dots e.g. '01 02 03 04 05 ab', '01-02-03-04-05-ab' or '0102.0304.05ab'. If `no_separators` is true, the validator will then only check MAC addresses without separators. The options also allow a `eui` property to specify if it needs to be validated against EUI-48 or EUI-64. The accepted values of `eui` are: 48, 64.\n**isMagnetURI(str)**                      | check if the string is a [Magnet URI format][Magnet URI Format].\n**isMailtoURI(str, [, options])**                      | check if the string is a [Mailto URI format][Mailto URI Format].<br/><br/>`options` is an object of validating emails inside the URI (check `isEmail`s options for details).\n**isMD5(str)**                          | check if the string is a MD5 hash.<br/><br/>Please note that you can also use the `isHash(str, 'md5')` function. Keep in mind that MD5 has some collision weaknesses compared to other algorithms (e.g., SHA).\n**isMimeType(str)**                     | check if the string matches to a valid [MIME type][MIME Type] format.\n**isMobilePhone(str [, locale [, options]])**          | check if the string is a mobile phone number,<br/><br/>`locale` is either an array of locales (e.g. `['sk-SK', 'sr-RS']`) OR one of `['am-Am', 'ar-AE', 'ar-BH', 'ar-DZ', 'ar-EG', 'ar-EH', 'ar-IQ', 'ar-JO', 'ar-KW', 'ar-PS', 'ar-SA', 'ar-SD', 'ar-SY', 'ar-TN', 'ar-YE', 'az-AZ', 'az-LB', 'az-LY', 'be-BY', 'bg-BG', 'bn-BD', 'bs-BA', 'ca-AD', 'cs-CZ', 'da-DK', 'de-AT', 'de-CH', 'de-DE', 'de-LU', 'dv-MV', 'dz-BT', 'el-CY', 'el-GR', 'en-AG', 'en-AI', 'en-AU', 'en-BM', 'en-BS', 'en-BW', 'en-CA', 'en-GB', 'en-GG', 'en-GH', 'en-GY', 'en-HK', 'en-IE', 'en-IN', 'en-JM', 'en-KE', 'en-KI', 'en-KN', 'en-LS', 'en-MO', 'en-MT', 'en-MU', 'en-MW', 'en-NG', 'en-NZ', 'en-PG', 'en-PH', 'en-PK', 'en-RW', 'en-SG', 'en-SL', 'en-SS', 'en-TZ', 'en-UG', 'en-US', 'en-ZA', 'en-ZM', 'en-ZW', 'es-AR', 'es-BO', 'es-CL', 'es-CO', 'es-CR', 'es-CU', 'es-DO', 'es-EC', 'es-ES', 'es-GT','es-HN', 'es-MX', 'es-NI', 'es-PA', 'es-PE', 'es-PY', 'es-SV', 'es-UY', 'es-VE', 'et-EE', 'fa-AF', 'fa-IR', 'fi-FI', 'fj-FJ', 'fo-FO', 'fr-BE', 'fr-BF', 'fr-BJ', 'fr-CD', 'fr-CF', 'fr-DJ', 'fr-FR', 'fr-GF', 'fr-GP', 'fr-MQ', 'fr-PF', 'fr-RE', 'fr-WF', 'ga-IE', 'he-IL', 'hu-HU', 'id-ID', 'ir-IR', 'it-IT', 'it-SM', 'ja-JP', 'ka-GE', 'kk-KZ', 'kl-GL', 'ko-KR', 'ky-KG', 'lt-LT', 'mg-MG', 'mn-MN', 'mk-MK', 'ms-MY', 'my-MM', 'mz-MZ', 'nb-NO', 'ne-NP', 'nl-AW', 'nl-BE', 'nl-NL', 'nn-NO', 'pl-PL', 'pt-AO', 'pt-BR', 'pt-PT', 'ro-Md', 'ro-RO', 'ru-RU', 'si-LK', 'sk-SK', 'sl-SI', 'so-SO', 'sq-AL', 'sr-RS', 'sv-SE', 'tg-TJ', 'th-TH', 'tk-TM', 'tr-TR', 'uk-UA', 'uz-UZ', 'vi-VN', 'zh-CN', 'zh-HK', 'zh-MO', 'zh-TW']` OR defaults to `'any'`. If 'any' or a falsey value is used, function will check if any of the locales match).<br/><br/>`options` is an optional object that can be supplied with the following keys: `strictMode`, if this is set to `true`, the mobile phone number must be supplied with the country code and therefore must start with `+`. Locale list is `validator.isMobilePhoneLocales`.\n**isMongoId(str)**                      | check if the string is a valid hex-encoded representation of a [MongoDB ObjectId][mongoid].\n**isMultibyte(str)**                    | check if the string contains one or more multibyte chars.\n**isNumeric(str [, options])**                      | check if the string contains only numbers.<br/><br/>`options` is an object which defaults to `{ no_symbols: false }` it also has `locale` as an option. If `no_symbols` is true, the validator will reject numeric strings that feature a symbol (e.g. `+`, `-`, or `.`).<br/><br/>`locale` determines the decimal separator and is one of `['ar', 'ar-AE', 'ar-BH', 'ar-DZ', 'ar-EG', 'ar-IQ', 'ar-JO', 'ar-KW', 'ar-LB', 'ar-LY', 'ar-MA', 'ar-QA', 'ar-QM', 'ar-SA', 'ar-SD', 'ar-SY', 'ar-TN', 'ar-YE', 'bg-BG', 'cs-CZ', 'da-DK', 'de-DE', 'en-AU', 'en-GB', 'en-HK', 'en-IN', 'en-NZ', 'en-US', 'en-ZA', 'en-ZM', 'eo', 'es-ES', 'fr-FR', 'fr-CA', 'hu-HU', 'it-IT', 'nb-NO', 'nl-NL', 'nn-NO', 'pl-PL', 'pt-BR', 'pt-PT', 'ru-RU', 'sl-SI', 'sr-RS', 'sr-RS@latin', 'sv-SE', 'tr-TR', 'uk-UA']`.\n**isOctal(str)**                        | check if the string is a valid octal number.\n**isPassportNumber(str, countryCode)**    | check if the string is a valid passport number.<br/><br/>`countryCode` is one of `['AM', 'AR', 'AT', 'AU', 'AZ', 'BE', 'BG', 'BY', 'BR', 'CA', 'CH', 'CN', 'CY', 'CZ', 'DE', 'DK', 'DZ', 'EE', 'ES', 'FI', 'FR', 'GB', 'GR', 'HR', 'HU', 'IE', 'IN', 'IR', 'ID', 'IS', 'IT', 'JM', 'JP', 'KR', 'KZ', 'LI', 'LT', 'LU', 'LV', 'LY', 'MT', 'MX', 'MY', 'MZ', 'NL', 'NZ', 'PH', 'PK', 'PL', 'PT', 'RO', 'RU', 'SE', 'SL', 'SK', 'TH', 'TR', 'UA', 'US', 'ZA']`.  Locale list is `validator.passportNumberLocales`.\n**isPort(str)**                         | check if the string is a valid port number.\n**isPostalCode(str, locale)**           | check if the string is a postal code.<br/><br/>`locale` is one of `['AD', 'AT', 'AU', 'AZ', 'BA', 'BD', 'BE', 'BG', 'BR', 'BY', 'CA', 'CH', 'CN', 'CO', 'CZ', 'DE', 'DK', 'DO', 'DZ', 'EE', 'ES', 'FI', 'FR', 'GB', 'GR', 'HR', 'HT', 'HU', 'ID', 'IE', 'IL', 'IN', 'IR', 'IS', 'IT', 'JP', 'KE', 'KR', 'LI', 'LK', 'LT', 'LU', 'LV', 'MC', 'MG', 'MT', 'MX', 'MY', 'NL', 'NO', 'NP', 'NZ', 'PK', 'PL', 'PR', 'PT', 'RO', 'RU', 'SA', 'SE', 'SG', 'SI', 'SK', 'TH', 'TN', 'TW', 'UA', 'US', 'ZA', 'ZM']` OR `'any'`. If 'any' is used, function will check if any of the locales match. Locale list is `validator.isPostalCodeLocales`.\n**isRFC3339(str)**                      | check if the string is a valid [RFC 3339][RFC 3339] date.\n**isRgbColor(str [,options])**                     | check if the string is a rgb or rgba color.<br/></br>`options` is an object with the following properties<br/><br/>`includePercentValues` defaults to `true`. If you don't want to allow to set `rgb` or `rgba` values with percents, like `rgb(5%,5%,5%)`, or `rgba(90%,90%,90%,.3)`, then set it to false.<br/><br/>`allowSpaces` defaults to `true`, which prohibits whitespace. If set to false, whitespace between color values is allowed, such as `rgb(255, 255, 255)` or even `rgba(255,       128,        0,      0.7)`.\n**isSemVer(str)**                       | check if the string is a Semantic Versioning Specification (SemVer).\n**isSurrogatePair(str)**                | check if the string contains any surrogate pairs chars.\n**isUppercase(str)**                    | check if the string is uppercase.\n**isSlug(str)**                         | check if the string is of type slug.\n**isStrongPassword(str [, options])**   | check if the string can be considered a strong password or not. Allows for custom requirements or scoring rules. If `returnScore` is true, then the function returns an integer score for the password rather than a boolean.<br/>Default options: <br/>`{ minLength: 8, minLowercase: 1, minUppercase: 1, minNumbers: 1, minSymbols: 1, returnScore: false, pointsPerUnique: 1, pointsPerRepeat: 0.5, pointsForContainingLower: 10, pointsForContainingUpper: 10, pointsForContainingNumber: 10, pointsForContainingSymbol: 10 }`\n**isTime(str [, options])**             | check if the string is a valid time e.g. [`23:01:59`, new Date().toLocaleTimeString()].<br/><br/> `options` is an object which can contain the keys `hourFormat` or `mode`.<br/><br/>`hourFormat` is a key and defaults to `'hour24'`.<br/><br/>`mode` is a key and defaults to `'default'`. <br/><br/>`hourFormat` can contain the values `'hour12'` or `'hour24'`, `'hour24'` will validate hours in 24 format and `'hour12'` will validate hours in 12 format. <br/><br/>`mode` can contain the values `'default', 'withSeconds', withOptionalSeconds`, `'default'` will validate `HH:MM` format, `'withSeconds'` will validate the `HH:MM:SS` format, `'withOptionalSeconds'` will validate `'HH:MM'` and `'HH:MM:SS'` formats.\n**isTaxID(str, locale)**                | check if the string is a valid Tax Identification Number. Default locale is `en-US`.<br/><br/>More info about exact TIN support can be found in `src/lib/isTaxID.js`.<br/><br/>Supported locales: `[ 'bg-BG', 'cs-CZ', 'de-AT', 'de-DE', 'dk-DK', 'el-CY', 'el-GR', 'en-CA', 'en-GB', 'en-IE', 'en-US', 'es-AR', 'es-ES', 'et-EE', 'fi-FI', 'fr-BE', 'fr-CA', 'fr-FR', 'fr-LU', 'hr-HR', 'hu-HU', 'it-IT', 'lb-LU', 'lt-LT', 'lv-LV', 'mt-MT', 'nl-BE', 'nl-NL', 'pl-PL', 'pt-BR', 'pt-PT', 'ro-RO', 'sk-SK', 'sl-SI', 'sv-SE', 'uk-UA']`.\n**isURL(str [, options])**              | check if the string is a URL.<br/><br/>`options` is an object which defaults to `{ protocols: ['http','https','ftp'], require_tld: true, require_protocol: false, require_host: true, require_port: false, require_valid_protocol: true, allow_underscores: false, host_whitelist: false, host_blacklist: false, allow_trailing_dot: false, allow_protocol_relative_urls: false, allow_fragments: true, allow_query_components: true, disallow_auth: false, validate_length: true }`.<br/><br/>`protocols` - valid protocols can be modified with this option.<br/>`require_tld` - If set to false isURL will not check if the URL's host includes a top-level domain.<br/>`require_protocol` - **RECOMMENDED** if set to true isURL will return false if protocol is not present in the URL. Without this setting, some malicious URLs cannot be distinguishable from a valid URL with authentication information.<br/>`require_host` - if set to false isURL will not check if host is present in the URL.<br/>`require_port` - if set to true isURL will check if port is present in the URL.<br/>`require_valid_protocol` - isURL will check if the URL's protocol is present in the protocols option.<br/>`allow_underscores` - if set to true, the validator will allow underscores in the URL.<br/>`host_whitelist` - if set to an array of strings or regexp, and the domain matches none of the strings defined in it, the validation fails.<br/>`host_blacklist` - if set to an array of strings or regexp, and the domain matches any of the strings defined in it, the validation fails.<br/>`allow_trailing_dot` - if set to true, the validator will allow the domain to end with a `.` character.<br/>`allow_protocol_relative_urls` - if set to true protocol relative URLs will be allowed.<br/>`allow_fragments` - if set to false isURL will return false if fragments are present.<br/>`allow_query_components` - if set to false isURL will return false if query components are present.<br/>`disallow_auth` - if set to true, the validator will fail if the URL contains an authentication component, e.g. `http://username:password@example.com`.<br/>`validate_length` - if set to false isURL will skip string length validation. `max_allowed_length` will be ignored if this is set as `false`.<br/>`max_allowed_length` - if set, isURL will not allow URLs longer than the specified value (default is 2084 that IE maximum URL length).<br/>\n**isULID(str)**                         | check if the string is a [ULID](https://github.com/ulid/spec).\n**isUUID(str [, version])**             | check if the string is an RFC9562 UUID.<br/>`version` is one of `'1'`-`'8'`, `'nil'`, `'max'`, `'all'` or `'loose'`. The `'loose'` option checks if the string is a UUID-like string with hexadecimal values, ignoring RFC9565.\n**isVariableWidth(str)**                | check if the string contains a mixture of full and half-width chars.\n**isVAT(str, countryCode)**             | check if the string is a [valid VAT number][VAT Number] if validation is available for the given country code matching [ISO 3166-1 alpha-2][ISO 3166-1 alpha-2]. <br/><br/>`countryCode` is one of `['AL', 'AR', 'AT', 'AU', 'BE', 'BG', 'BO', 'BR', 'BY', 'CA', 'CH', 'CL', 'CO', 'CR', 'CY', 'CZ', 'DE', 'DK', 'DO', 'EC', 'EE', 'EL', 'ES', 'FI', 'FR', 'GB', 'GT', 'HN', 'HR', 'HU', 'ID', 'IE', 'IL', 'IN', 'IS', 'IT', 'KZ', 'LT', 'LU', 'LV', 'MK', 'MT', 'MX', 'NG', 'NI', 'NL', 'NO', 'NZ', 'PA', 'PE', 'PH', 'PL', 'PT', 'PY', 'RO', 'RS', 'RU', 'SA', 'SE', 'SI', 'SK', 'SM', 'SV', 'TR', 'UA', 'UY', 'UZ', 'VE']`.\n**isWhitelisted(str, chars)**           | check if the string consists only of characters that appear in the whitelist `chars`.\n**matches(str, pattern [, modifiers])** | check if the string matches the pattern.<br/><br/>Either `matches('foo', /foo/i)` or `matches('foo', 'foo', 'i')`.<br/>**Note:** The pattern is not checked for possible ReDoS attacks. We do not recommend that the user can provide their own pattern.\n\n## Sanitizers\n\nHere is a list of the sanitizers currently available.\n\nSanitizer                              | Description\n-------------------------------------- | -------------------------------\n**blacklist(input, chars)**            | remove characters that appear in the blacklist. The characters are used in a RegExp and so you will need to escape some chars, e.g. `blacklist(input, '\\\\[\\\\]')`.\n**escape(input)**                      | replace `<`, `>`, `&`, `'`, `\"`, `` ` ``, `\\` and `/` with HTML entities.\n**ltrim(input [, chars])**             | trim characters from the left-side of the input.\n**normalizeEmail(email [, options])**  | canonicalize an email address. (This doesn't validate that the input is an email, if you want to validate the email use isEmail beforehand).<br/><br/>`options` is an object with the following keys and default values:<br/><ul><li>*all_lowercase: true* - Transforms the local part (before the @ symbol) of all email addresses to lowercase. Please note that this may violate RFC 5321, which gives providers the possibility to treat the local part of email addresses in a case sensitive way (although in practice most - yet not all - providers don't). The domain part of the email address is always lowercased, as it is case insensitive per RFC 1035.</li><li>*gmail_lowercase: true* - Gmail addresses are known to be case-insensitive, so this switch allows lowercasing them even when *all_lowercase* is set to false. Please note that when *all_lowercase* is true, Gmail addresses are lowercased regardless of the value of this setting.</li><li>*gmail_remove_dots: true*: Removes dots from the local part of the email address, as Gmail ignores them (e.g. \"john.doe\" and \"johndoe\" are considered equal).</li><li>*gmail_remove_subaddress: true*: Normalizes addresses by removing \"sub-addresses\", which is the part following a \"+\" sign (e.g. \"foo+bar@gmail.com\" becomes \"foo@gmail.com\").</li><li>*gmail_convert_googlemaildotcom: true*: Converts addresses with domain @googlemail.com to @gmail.com, as they're equivalent.</li><li>*outlookdotcom_lowercase: true* - Outlook.com addresses (including Windows Live and Hotmail) are known to be case-insensitive, so this switch allows lowercasing them even when *all_lowercase* is set to false. Please note that when *all_lowercase* is true, Outlook.com addresses are lowercased regardless of the value of this setting.</li><li>*outlookdotcom_remove_subaddress: true*: Normalizes addresses by removing \"sub-addresses\", which is the part following a \"+\" sign (e.g. \"foo+bar@outlook.com\" becomes \"foo@outlook.com\").</li><li>*yahoo_lowercase: true* - Yahoo Mail addresses are known to be case-insensitive, so this switch allows lowercasing them even when *all_lowercase* is set to false. Please note that when *all_lowercase* is true, Yahoo Mail addresses are lowercased regardless of the value of this setting.</li><li>*yahoo_remove_subaddress: true*: Normalizes addresses by removing \"sub-addresses\", which is the part following a \"-\" sign (e.g. \"foo-bar@yahoo.com\" becomes \"foo@yahoo.com\").</li><li>*icloud_lowercase: true* - iCloud addresses (including MobileMe) are known to be case-insensitive, so this switch allows lowercasing them even when *all_lowercase* is set to false. Please note that when *all_lowercase* is true, iCloud addresses are lowercased regardless of the value of this setting.</li><li>*icloud_remove_subaddress: true*: Normalizes addresses by removing \"sub-addresses\", which is the part following a \"+\" sign (e.g. \"foo+bar@icloud.com\" becomes \"foo@icloud.com\").</li></ul>\n**rtrim(input [, chars])**             | trim characters from the right-side of the input.\n**stripLow(input [, keep_new_lines])** | remove characters with a numerical value < 32 and 127, mostly control characters. If `keep_new_lines` is `true`, newline characters are preserved (`\\n` and `\\r`, hex `0xA` and `0xD`). Unicode-safe in JavaScript.\n**toBoolean(input [, strict])**        | convert the input string to a boolean. Everything except for `'0'`, `'false'` and `''` returns `true`. In strict mode only `'1'` and `'true'` return `true`.\n**toDate(input)**                      | convert the input string to a date, or `null` if the input is not a date.\n**toFloat(input)**                     | convert the input string to a float, or `NaN` if the input is not a float.\n**toInt(input [, radix])**             | convert the input string to an integer, or `NaN` if the input is not an integer.\n**trim(input [, chars])**              | trim characters (whitespace by default) from both sides of the input.\n**unescape(input)**                    | replace HTML encoded entities with `<`, `>`, `&`, `'`, `\"`, `` ` ``, `\\` and `/`.\n**whitelist(input, chars)**            | remove characters that do not appear in the whitelist. The characters are used in a RegExp and so you will need to escape some chars, e.g. `whitelist(input, '\\\\[\\\\]')`.\n\n### XSS Sanitization\n\nXSS sanitization was removed from the library in [2d5d6999](https://github.com/validatorjs/validator.js/commit/2d5d6999541add350fb396ef02dc42ca3215049e).\n\nFor an alternative, have a look at Yahoo's [xss-filters library](https://github.com/yahoo/xss-filters) or at [DOMPurify](https://github.com/cure53/DOMPurify).\n\n## Maintainers\n\n- [chriso](https://github.com/chriso) - **Chris O'Hara** (author)\n- [profnandaa](https://github.com/profnandaa) - **Anthony Nandaa**\n- [rubiin](https://github.com/rubiin) - **Rubin Bhandari**\n- [wikirik](https://github.com/wikirik) - **Rik Smale**\n- [ezkemboi](https://github.com/ezkemboi) - **Ezrqn Kemboi**\n- [tux-tn](https://github.com/tux-tn) - **Sarhan Aissi**\n\n## Reading\n\nRemember, validating can be troublesome sometimes. See [A list of articles about programming assumptions commonly made that aren't true](https://github.com/jameslk/awesome-falsehoods).\n\n## Contributing\n\nWe welcome contributions from the community! If you're interested in contributing to this project, please read our [Contribution Guide](CONTRIBUTING.md) to get started.\n\n## License\n\nThis project is licensed under the [MIT](LICENSE). See the [LICENSE](LICENSE) file for details.\n\n[downloads-image]: http://img.shields.io/npm/dm/validator.svg\n\n[npm-url]: https://npmjs.org/package/validator\n[npm-image]: http://img.shields.io/npm/v/validator.svg\n\n[codecov-url]: https://codecov.io/gh/validatorjs/validator.js\n[codecov-image]: https://codecov.io/gh/validatorjs/validator.js/branch/master/graph/badge.svg\n\n[ci-url]: https://github.com/validatorjs/validator.js/actions?query=workflow%3ACI\n[ci-image]: https://github.com/validatorjs/validator.js/workflows/CI/badge.svg?branch=master\n\n[gitter-url]: https://gitter.im/validatorjs/community\n[gitter-image]: https://badges.gitter.im/validatorjs/community.svg\n\n[huntr-url]: https://huntr.dev/bounties/disclose/?target=https://github.com/validatorjs/validator.js\n[huntr-image]: https://cdn.huntr.dev/huntr_security_badge_mono.svg\n\n[amd]: http://requirejs.org/docs/whyamd.html\n[bower]: http://bower.io/\n\n[Crockford Base32]: http://www.crockford.com/base32.html\n[Base64 URL Safe]: https://base64.guru/standards/base64url\n[Data URI Format]: https://developer.mozilla.org/en-US/docs/Web/HTTP/data_URIs\n[European Article Number]: https://en.wikipedia.org/wiki/International_Article_Number\n[Ethereum]: https://ethereum.org/\n[CSS Colors Level 4 Specification]: https://developer.mozilla.org/en-US/docs/Web/CSS/color_value\n[IMEI]: https://en.wikipedia.org/wiki/International_Mobile_Equipment_Identity\n[ISBN]: https://en.wikipedia.org/wiki/ISBN\n[ISIN]: https://en.wikipedia.org/wiki/International_Securities_Identification_Number\n[ISO 639-1]: https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes\n[ISO 8601]: https://en.wikipedia.org/wiki/ISO_8601\n[ISO 15924]: https://en.wikipedia.org/wiki/ISO_15924\n[ISO 3166-1 alpha-2]: https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2\n[ISO 3166-1 alpha-3]: https://en.wikipedia.org/wiki/ISO_3166-1_alpha-3\n[ISO 3166-1 numeric]: https://en.wikipedia.org/wiki/ISO_3166-1_numeric\n[ISO 4217]: https://en.wikipedia.org/wiki/ISO_4217\n[ISRC]: https://en.wikipedia.org/wiki/International_Standard_Recording_Code\n[ISSN]: https://en.wikipedia.org/wiki/International_Standard_Serial_Number\n[Luhn Check]: https://en.wikipedia.org/wiki/Luhn_algorithm\n[Magnet URI Format]: https://en.wikipedia.org/wiki/Magnet_URI_scheme\n[Mailto URI Format]: https://en.wikipedia.org/wiki/Mailto\n[MIME Type]: https://en.wikipedia.org/wiki/Media_type\n[mongoid]: http://docs.mongodb.org/manual/reference/object-id/\n[RFC 3339]: https://tools.ietf.org/html/rfc3339\n[VAT Number]: https://en.wikipedia.org/wiki/VAT_identification_number\n"
  },
  {
    "path": "SECURITY.md",
    "content": "# Security Policy\n\n## Supported Versions\n\nIn the case of a confirmed security issue, only the current version of validator is guaranteed to be patched.\n\n## Reporting a Vulnerability\n\n**Please don't disclose security-related issues publicly.**\n\nReport the security issue to the Node.js Security Working Group through the [HackerOne program](https://hackerone.com/nodejs-ecosystem) for ecosystem modules on npm, or to [Snyk Security Team](https://snyk.io/vulnerability-disclosure). They will help triage the security issue and work with all involved parties to remediate and release a fix.\n"
  },
  {
    "path": "bower.json",
    "content": "{\n  \"name\": \"validator-js\",\n  \"main\": \"validator.js\",\n  \"homepage\": \"https://github.com/validatorjs/validator.js\",\n  \"authors\": [\n    \"Chris O'Hara <cohara87+gh@gmail.com>\"\n  ],\n  \"description\": \"String validation and sanitization\",\n  \"license\": \"MIT\",\n  \"ignore\": [\n    \"**/.*\",\n    \"index.js\",\n    \"build*.js\",\n    \"package.json\",\n    \"node_modules\",\n    \"bower_components\",\n    \"test\"\n  ]\n}\n"
  },
  {
    "path": "build-browser.js",
    "content": "/* eslint import/no-extraneous-dependencies: 0 */\nimport fs from \"fs\";\nimport { rollup } from \"rollup\";\nimport babel from \"rollup-plugin-babel\";\nimport babelPresetEnv from \"@babel/preset-env\";\nimport pkg from \"./package.json\";\n\nrollup({\n  entry: \"src/index.js\",\n  plugins: [\n    babel({\n      presets: [[babelPresetEnv, { modules: false }]],\n      babelrc: false,\n    }),\n  ],\n})\n  .then((bundle) =>\n    bundle.write({\n      dest: \"validator.js\",\n      format: \"umd\",\n      moduleName: pkg.name,\n      banner: `/*!\\n${String(fs.readFileSync(\"./LICENSE\"))\n        .trim()\n        .split(\"\\n\")\n        .map((l) => ` * ${l}`)\n        .join(\"\\n\")}\\n */`,\n    })\n  )\n  .catch((e) => {\n    process.stderr.write(`${e.message}\\n`);\n    process.exit(1);\n  });\n"
  },
  {
    "path": "jsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"module\": \"system\",\n    \"target\": \"ES6\"\n  }\n}"
  },
  {
    "path": "package.json",
    "content": "{\n  \"name\": \"validator\",\n  \"description\": \"String validation and sanitization\",\n  \"version\": \"13.15.26\",\n  \"sideEffects\": false,\n  \"homepage\": \"https://github.com/validatorjs/validator.js\",\n  \"files\": [\n    \"index.js\",\n    \"es\",\n    \"lib\",\n    \"README.md\",\n    \"LICENSE\",\n    \"validator.js\",\n    \"validator.min.js\"\n  ],\n  \"keywords\": [\n    \"validator\",\n    \"validation\",\n    \"validate\",\n    \"sanitization\",\n    \"sanitize\",\n    \"sanitisation\",\n    \"sanitise\",\n    \"assert\"\n  ],\n  \"author\": \"Chris O'Hara <cohara87@gmail.com>\",\n  \"contributors\": [\n    \"Anthony Nandaa (https://github.com/profnandaa)\"\n  ],\n  \"main\": \"index.js\",\n  \"bugs\": {\n    \"url\": \"https://github.com/validatorjs/validator.js/issues\"\n  },\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"git+https://github.com/validatorjs/validator.js.git\"\n  },\n  \"devDependencies\": {\n    \"@babel/cli\": \"^7.0.0\",\n    \"@babel/core\": \"^7.0.0\",\n    \"@babel/preset-env\": \"^7.0.0\",\n    \"@babel/register\": \"^7.0.0\",\n    \"babel-eslint\": \"^10.0.1\",\n    \"babel-plugin-add-module-exports\": \"^1.0.0\",\n    \"eslint\": \"^4.19.1\",\n    \"eslint-config-airbnb-base\": \"^12.1.0\",\n    \"eslint-plugin-import\": \"^2.11.0\",\n    \"mocha\": \"^6.2.3\",\n    \"npm-run-all\": \"^4.1.5\",\n    \"nyc\": \"^14.1.0\",\n    \"rimraf\": \"^3.0.0\",\n    \"rollup\": \"^0.47.0\",\n    \"rollup-plugin-babel\": \"^4.0.1\",\n    \"timezone-mock\": \"^1.3.6\",\n    \"uglify-js\": \"^3.0.19\"\n  },\n  \"scripts\": {\n    \"lint\": \"eslint src test\",\n    \"lint:fix\": \"eslint --fix src test\",\n    \"clean:node\": \"rimraf index.js lib\",\n    \"clean:es\": \"rimraf es\",\n    \"clean:browser\": \"rimraf validator*.js\",\n    \"clean\": \"run-p clean:*\",\n    \"minify\": \"uglifyjs validator.js -o validator.min.js  --compress --mangle --comments /Copyright/\",\n    \"build:browser\": \"node --require @babel/register build-browser && npm run minify\",\n    \"build:es\": \"babel src -d es --env-name=es\",\n    \"build:node\": \"babel src -d .\",\n    \"build\": \"run-p build:*\",\n    \"pretest\": \"npm run build && npm run lint\",\n    \"test\": \"nyc --reporter=cobertura --reporter=text-summary mocha --require @babel/register --reporter dot --recursive\"\n  },\n  \"engines\": {\n    \"node\": \">= 0.10\"\n  },\n  \"license\": \"MIT\"\n}\n"
  },
  {
    "path": "src/index.js",
    "content": "import toDate from './lib/toDate';\nimport toFloat from './lib/toFloat';\nimport toInt from './lib/toInt';\nimport toBoolean from './lib/toBoolean';\nimport equals from './lib/equals';\nimport contains from './lib/contains';\nimport matches from './lib/matches';\n\nimport isEmail from './lib/isEmail';\nimport isURL from './lib/isURL';\nimport isMACAddress from './lib/isMACAddress';\nimport isIP from './lib/isIP';\nimport isIPRange from './lib/isIPRange';\nimport isFQDN from './lib/isFQDN';\nimport isDate from './lib/isDate';\nimport isTime from './lib/isTime';\n\nimport isBoolean from './lib/isBoolean';\nimport isLocale from './lib/isLocale';\n\nimport isAbaRouting from './lib/isAbaRouting';\nimport isAlpha, { locales as isAlphaLocales } from './lib/isAlpha';\nimport isAlphanumeric, { locales as isAlphanumericLocales } from './lib/isAlphanumeric';\nimport isNumeric from './lib/isNumeric';\nimport isPassportNumber, { locales as passportNumberLocales } from './lib/isPassportNumber';\nimport isPort from './lib/isPort';\nimport isLowercase from './lib/isLowercase';\nimport isUppercase from './lib/isUppercase';\n\nimport isIMEI from './lib/isIMEI';\n\nimport isAscii from './lib/isAscii';\nimport isFullWidth from './lib/isFullWidth';\nimport isHalfWidth from './lib/isHalfWidth';\nimport isVariableWidth from './lib/isVariableWidth';\nimport isMultibyte from './lib/isMultibyte';\nimport isSemVer from './lib/isSemVer';\nimport isSurrogatePair from './lib/isSurrogatePair';\n\nimport isInt from './lib/isInt';\nimport isFloat, { locales as isFloatLocales } from './lib/isFloat';\nimport isDecimal from './lib/isDecimal';\nimport isHexadecimal from './lib/isHexadecimal';\nimport isOctal from './lib/isOctal';\nimport isDivisibleBy from './lib/isDivisibleBy';\n\nimport isHexColor from './lib/isHexColor';\nimport isRgbColor from './lib/isRgbColor';\nimport isHSL from './lib/isHSL';\n\nimport isISRC from './lib/isISRC';\n\nimport isIBAN, { locales as ibanLocales } from './lib/isIBAN';\nimport isBIC from './lib/isBIC';\n\nimport isMD5 from './lib/isMD5';\nimport isHash from './lib/isHash';\nimport isJWT from './lib/isJWT';\n\nimport isJSON from './lib/isJSON';\nimport isEmpty from './lib/isEmpty';\n\nimport isLength from './lib/isLength';\nimport isByteLength from './lib/isByteLength';\n\nimport isULID from './lib/isULID';\nimport isUUID from './lib/isUUID';\nimport isMongoId from './lib/isMongoId';\n\nimport isAfter from './lib/isAfter';\nimport isBefore from './lib/isBefore';\n\nimport isIn from './lib/isIn';\n\nimport isLuhnNumber from './lib/isLuhnNumber';\nimport isCreditCard from './lib/isCreditCard';\nimport isIdentityCard from './lib/isIdentityCard';\n\nimport isEAN from './lib/isEAN';\nimport isISIN from './lib/isISIN';\nimport isISBN from './lib/isISBN';\nimport isISSN from './lib/isISSN';\nimport isTaxID from './lib/isTaxID';\n\nimport isMobilePhone, { locales as isMobilePhoneLocales } from './lib/isMobilePhone';\n\nimport isEthereumAddress from './lib/isEthereumAddress';\n\nimport isCurrency from './lib/isCurrency';\n\nimport isBtcAddress from './lib/isBtcAddress';\n\nimport { isISO6346, isFreightContainerID } from './lib/isISO6346';\nimport isISO6391 from './lib/isISO6391';\nimport isISO8601 from './lib/isISO8601';\nimport isRFC3339 from './lib/isRFC3339';\nimport isISO15924 from './lib/isISO15924';\nimport isISO31661Alpha2 from './lib/isISO31661Alpha2';\nimport isISO31661Alpha3 from './lib/isISO31661Alpha3';\nimport isISO31661Numeric from './lib/isISO31661Numeric';\nimport isISO4217 from './lib/isISO4217';\n\nimport isBase32 from './lib/isBase32';\nimport isBase58 from './lib/isBase58';\nimport isBase64 from './lib/isBase64';\nimport isDataURI from './lib/isDataURI';\nimport isMagnetURI from './lib/isMagnetURI';\nimport isMailtoURI from './lib/isMailtoURI';\n\nimport isMimeType from './lib/isMimeType';\n\nimport isLatLong from './lib/isLatLong';\nimport isPostalCode, { locales as isPostalCodeLocales } from './lib/isPostalCode';\n\nimport ltrim from './lib/ltrim';\nimport rtrim from './lib/rtrim';\nimport trim from './lib/trim';\nimport escape from './lib/escape';\nimport unescape from './lib/unescape';\nimport stripLow from './lib/stripLow';\nimport whitelist from './lib/whitelist';\nimport blacklist from './lib/blacklist';\nimport isWhitelisted from './lib/isWhitelisted';\n\nimport normalizeEmail from './lib/normalizeEmail';\n\nimport isSlug from './lib/isSlug';\nimport isLicensePlate from './lib/isLicensePlate';\nimport isStrongPassword from './lib/isStrongPassword';\n\nimport isVAT from './lib/isVAT';\n\nconst version = '13.15.26';\n\nconst validator = {\n  version,\n  toDate,\n  toFloat,\n  toInt,\n  toBoolean,\n  equals,\n  contains,\n  matches,\n  isEmail,\n  isURL,\n  isMACAddress,\n  isIP,\n  isIPRange,\n  isFQDN,\n  isBoolean,\n  isIBAN,\n  isBIC,\n  isAbaRouting,\n  isAlpha,\n  isAlphaLocales,\n  isAlphanumeric,\n  isAlphanumericLocales,\n  isNumeric,\n  isPassportNumber,\n  passportNumberLocales,\n  isPort,\n  isLowercase,\n  isUppercase,\n  isAscii,\n  isFullWidth,\n  isHalfWidth,\n  isVariableWidth,\n  isMultibyte,\n  isSemVer,\n  isSurrogatePair,\n  isInt,\n  isIMEI,\n  isFloat,\n  isFloatLocales,\n  isDecimal,\n  isHexadecimal,\n  isOctal,\n  isDivisibleBy,\n  isHexColor,\n  isRgbColor,\n  isHSL,\n  isISRC,\n  isMD5,\n  isHash,\n  isJWT,\n  isJSON,\n  isEmpty,\n  isLength,\n  isLocale,\n  isByteLength,\n  isULID,\n  isUUID,\n  isMongoId,\n  isAfter,\n  isBefore,\n  isIn,\n  isLuhnNumber,\n  isCreditCard,\n  isIdentityCard,\n  isEAN,\n  isISIN,\n  isISBN,\n  isISSN,\n  isMobilePhone,\n  isMobilePhoneLocales,\n  isPostalCode,\n  isPostalCodeLocales,\n  isEthereumAddress,\n  isCurrency,\n  isBtcAddress,\n  isISO6346,\n  isFreightContainerID,\n  isISO6391,\n  isISO8601,\n  isISO15924,\n  isRFC3339,\n  isISO31661Alpha2,\n  isISO31661Alpha3,\n  isISO31661Numeric,\n  isISO4217,\n  isBase32,\n  isBase58,\n  isBase64,\n  isDataURI,\n  isMagnetURI,\n  isMailtoURI,\n  isMimeType,\n  isLatLong,\n  ltrim,\n  rtrim,\n  trim,\n  escape,\n  unescape,\n  stripLow,\n  whitelist,\n  blacklist,\n  isWhitelisted,\n  normalizeEmail,\n  toString,\n  isSlug,\n  isStrongPassword,\n  isTaxID,\n  isDate,\n  isTime,\n  isLicensePlate,\n  isVAT,\n  ibanLocales,\n};\n\nexport default validator;\n"
  },
  {
    "path": "src/lib/alpha.js",
    "content": "export const alpha = {\n  'en-US': /^[A-Z]+$/i,\n  'az-AZ': /^[A-VXYZÇƏĞİıÖŞÜ]+$/i,\n  'bg-BG': /^[А-Я]+$/i,\n  'cs-CZ': /^[A-ZÁČĎÉĚÍŇÓŘŠŤÚŮÝŽ]+$/i,\n  'da-DK': /^[A-ZÆØÅ]+$/i,\n  'de-DE': /^[A-ZÄÖÜß]+$/i,\n  'el-GR': /^[Α-ώ]+$/i,\n  'es-ES': /^[A-ZÁÉÍÑÓÚÜ]+$/i,\n  'fa-IR': /^[ابپتثجچحخدذرزژسشصضطظعغفقکگلمنوهی]+$/i,\n  'fi-FI': /^[A-ZÅÄÖ]+$/i,\n  'fr-FR': /^[A-ZÀÂÆÇÉÈÊËÏÎÔŒÙÛÜŸ]+$/i,\n  'it-IT': /^[A-ZÀÉÈÌÎÓÒÙ]+$/i,\n  'ja-JP': /^[ぁ-んァ-ヶｦ-ﾟ一-龠ー・。、]+$/i,\n  'nb-NO': /^[A-ZÆØÅ]+$/i,\n  'nl-NL': /^[A-ZÁÉËÏÓÖÜÚ]+$/i,\n  'nn-NO': /^[A-ZÆØÅ]+$/i,\n  'hu-HU': /^[A-ZÁÉÍÓÖŐÚÜŰ]+$/i,\n  'pl-PL': /^[A-ZĄĆĘŚŁŃÓŻŹ]+$/i,\n  'pt-PT': /^[A-ZÃÁÀÂÄÇÉÊËÍÏÕÓÔÖÚÜ]+$/i,\n  'ru-RU': /^[А-ЯЁ]+$/i,\n  'kk-KZ': /^[А-ЯЁ\\u04D8\\u04B0\\u0406\\u04A2\\u0492\\u04AE\\u049A\\u04E8\\u04BA]+$/i,\n  'sl-SI': /^[A-ZČĆĐŠŽ]+$/i,\n  'sk-SK': /^[A-ZÁČĎÉÍŇÓŠŤÚÝŽĹŔĽÄÔ]+$/i,\n  'sr-RS@latin': /^[A-ZČĆŽŠĐ]+$/i,\n  'sr-RS': /^[А-ЯЂЈЉЊЋЏ]+$/i,\n  'sv-SE': /^[A-ZÅÄÖ]+$/i,\n  'th-TH': /^[ก-๐\\s]+$/i,\n  'tr-TR': /^[A-ZÇĞİıÖŞÜ]+$/i,\n  'uk-UA': /^[А-ЩЬЮЯЄIЇҐі]+$/i,\n  'vi-VN': /^[A-ZÀÁẠẢÃÂẦẤẬẨẪĂẰẮẶẲẴĐÈÉẸẺẼÊỀẾỆỂỄÌÍỊỈĨÒÓỌỎÕÔỒỐỘỔỖƠỜỚỢỞỠÙÚỤỦŨƯỪỨỰỬỮỲÝỴỶỸ]+$/i,\n  'ko-KR': /^[ㄱ-ㅎㅏ-ㅣ가-힣]*$/,\n  'ku-IQ': /^[ئابپتجچحخدرڕزژسشعغفڤقکگلڵمنوۆھەیێيطؤثآإأكضصةظذ]+$/i,\n  ar: /^[ءآأؤإئابةتثجحخدذرزسشصضطظعغفقكلمنهوىيًٌٍَُِّْٰ]+$/,\n  he: /^[א-ת]+$/,\n  fa: /^['آاءأؤئبپتثجچحخدذرزژسشصضطظعغفقکگلمنوهةی']+$/i,\n  bn: /^['ঀঁংঃঅআইঈউঊঋঌএঐওঔকখগঘঙচছজঝঞটঠডঢণতথদধনপফবভমযরলশষসহ়ঽািীুূৃৄেৈোৌ্ৎৗড়ঢ়য়ৠৡৢৣৰৱ৲৳৴৵৶৷৸৹৺৻']+$/,\n  eo: /^[ABCĈD-GĜHĤIJĴK-PRSŜTUŬVZ]+$/i,\n  'hi-IN': /^[\\u0900-\\u0961]+[\\u0972-\\u097F]*$/i,\n  'si-LK': /^[\\u0D80-\\u0DFF]+$/,\n  'ta-IN': /^[\\u0B80-\\u0BFF]+$/i,\n  'te-IN': /^[\\u0C00-\\u0C7F]+$/i,\n  'kn-IN': /^[\\u0C80-\\u0CFF]+$/i,\n  'ml-IN': /^[\\u0D00-\\u0D7F]+$/i,\n  'gu-IN': /^[\\u0A80-\\u0AFF]+$/i,\n  'pa-IN': /^[\\u0A00-\\u0A7F]+$/i,\n  'or-IN': /^[\\u0B00-\\u0B7F]+$/i,\n};\n\nexport const alphanumeric = {\n  'en-US': /^[0-9A-Z]+$/i,\n  'az-AZ': /^[0-9A-VXYZÇƏĞİıÖŞÜ]+$/i,\n  'bg-BG': /^[0-9А-Я]+$/i,\n  'cs-CZ': /^[0-9A-ZÁČĎÉĚÍŇÓŘŠŤÚŮÝŽ]+$/i,\n  'da-DK': /^[0-9A-ZÆØÅ]+$/i,\n  'de-DE': /^[0-9A-ZÄÖÜß]+$/i,\n  'el-GR': /^[0-9Α-ω]+$/i,\n  'es-ES': /^[0-9A-ZÁÉÍÑÓÚÜ]+$/i,\n  'fi-FI': /^[0-9A-ZÅÄÖ]+$/i,\n  'fr-FR': /^[0-9A-ZÀÂÆÇÉÈÊËÏÎÔŒÙÛÜŸ]+$/i,\n  'it-IT': /^[0-9A-ZÀÉÈÌÎÓÒÙ]+$/i,\n  'ja-JP': /^[0-9０-９ぁ-んァ-ヶｦ-ﾟ一-龠ー・。、]+$/i,\n  'hu-HU': /^[0-9A-ZÁÉÍÓÖŐÚÜŰ]+$/i,\n  'nb-NO': /^[0-9A-ZÆØÅ]+$/i,\n  'nl-NL': /^[0-9A-ZÁÉËÏÓÖÜÚ]+$/i,\n  'nn-NO': /^[0-9A-ZÆØÅ]+$/i,\n  'pl-PL': /^[0-9A-ZĄĆĘŚŁŃÓŻŹ]+$/i,\n  'pt-PT': /^[0-9A-ZÃÁÀÂÄÇÉÊËÍÏÕÓÔÖÚÜ]+$/i,\n  'ru-RU': /^[0-9А-ЯЁ]+$/i,\n  'kk-KZ': /^[0-9А-ЯЁ\\u04D8\\u04B0\\u0406\\u04A2\\u0492\\u04AE\\u049A\\u04E8\\u04BA]+$/i,\n  'sl-SI': /^[0-9A-ZČĆĐŠŽ]+$/i,\n  'sk-SK': /^[0-9A-ZÁČĎÉÍŇÓŠŤÚÝŽĹŔĽÄÔ]+$/i,\n  'sr-RS@latin': /^[0-9A-ZČĆŽŠĐ]+$/i,\n  'sr-RS': /^[0-9А-ЯЂЈЉЊЋЏ]+$/i,\n  'sv-SE': /^[0-9A-ZÅÄÖ]+$/i,\n  'th-TH': /^[ก-๙\\s]+$/i,\n  'tr-TR': /^[0-9A-ZÇĞİıÖŞÜ]+$/i,\n  'uk-UA': /^[0-9А-ЩЬЮЯЄIЇҐі]+$/i,\n  'ko-KR': /^[0-9ㄱ-ㅎㅏ-ㅣ가-힣]*$/,\n  'ku-IQ': /^[٠١٢٣٤٥٦٧٨٩0-9ئابپتجچحخدرڕزژسشعغفڤقکگلڵمنوۆھەیێيطؤثآإأكضصةظذ]+$/i,\n  'vi-VN': /^[0-9A-ZÀÁẠẢÃÂẦẤẬẨẪĂẰẮẶẲẴĐÈÉẸẺẼÊỀẾỆỂỄÌÍỊỈĨÒÓỌỎÕÔỒỐỘỔỖƠỜỚỢỞỠÙÚỤỦŨƯỪỨỰỬỮỲÝỴỶỸ]+$/i,\n  ar: /^[٠١٢٣٤٥٦٧٨٩0-9ءآأؤإئابةتثجحخدذرزسشصضطظعغفقكلمنهوىيًٌٍَُِّْٰ]+$/,\n  he: /^[0-9א-ת]+$/,\n  fa: /^['0-9آاءأؤئبپتثجچحخدذرزژسشصضطظعغفقکگلمنوهةی۱۲۳۴۵۶۷۸۹۰']+$/i,\n  bn: /^['ঀঁংঃঅআইঈউঊঋঌএঐওঔকখগঘঙচছজঝঞটঠডঢণতথদধনপফবভমযরলশষসহ়ঽািীুূৃৄেৈোৌ্ৎৗড়ঢ়য়ৠৡৢৣ০১২৩৪৫৬৭৮৯ৰৱ৲৳৴৵৶৷৸৹৺৻']+$/,\n  eo: /^[0-9ABCĈD-GĜHĤIJĴK-PRSŜTUŬVZ]+$/i,\n  'hi-IN': /^[\\u0900-\\u0963]+[\\u0966-\\u097F]*$/i,\n  'si-LK': /^[0-9\\u0D80-\\u0DFF]+$/,\n  'ta-IN': /^[0-9\\u0B80-\\u0BFF.]+$/i,\n  'te-IN': /^[0-9\\u0C00-\\u0C7F.]+$/i,\n  'kn-IN': /^[0-9\\u0C80-\\u0CFF.]+$/i,\n  'ml-IN': /^[0-9\\u0D00-\\u0D7F.]+$/i,\n  'gu-IN': /^[0-9\\u0A80-\\u0AFF.]+$/i,\n  'pa-IN': /^[0-9\\u0A00-\\u0A7F.]+$/i,\n  'or-IN': /^[0-9\\u0B00-\\u0B7F.]+$/i,\n};\n\nexport const decimal = {\n  'en-US': '.',\n  ar: '٫',\n};\n\n\nexport const englishLocales = ['AU', 'GB', 'HK', 'IN', 'NZ', 'ZA', 'ZM'];\n\nfor (let locale, i = 0; i < englishLocales.length; i++) {\n  locale = `en-${englishLocales[i]}`;\n  alpha[locale] = alpha['en-US'];\n  alphanumeric[locale] = alphanumeric['en-US'];\n  decimal[locale] = decimal['en-US'];\n}\n\n// Source: http://www.localeplanet.com/java/\nexport const arabicLocales = ['AE', 'BH', 'DZ', 'EG', 'IQ', 'JO', 'KW', 'LB', 'LY',\n  'MA', 'QM', 'QA', 'SA', 'SD', 'SY', 'TN', 'YE'];\n\nfor (let locale, i = 0; i < arabicLocales.length; i++) {\n  locale = `ar-${arabicLocales[i]}`;\n  alpha[locale] = alpha.ar;\n  alphanumeric[locale] = alphanumeric.ar;\n  decimal[locale] = decimal.ar;\n}\n\nexport const farsiLocales = ['IR', 'AF'];\n\nfor (let locale, i = 0; i < farsiLocales.length; i++) {\n  locale = `fa-${farsiLocales[i]}`;\n  alphanumeric[locale] = alphanumeric.fa;\n  decimal[locale] = decimal.ar;\n}\n\nexport const bengaliLocales = ['BD', 'IN'];\n\nfor (let locale, i = 0; i < bengaliLocales.length; i++) {\n  locale = `bn-${bengaliLocales[i]}`;\n  alpha[locale] = alpha.bn;\n  alphanumeric[locale] = alphanumeric.bn;\n  decimal[locale] = decimal['en-US'];\n}\n\n// Source: https://en.wikipedia.org/wiki/Decimal_mark\nexport const dotDecimal = ['ar-EG', 'ar-LB', 'ar-LY'];\nexport const commaDecimal = [\n  'bg-BG', 'cs-CZ', 'da-DK', 'de-DE', 'el-GR', 'en-ZM', 'eo', 'es-ES', 'fr-CA', 'fr-FR',\n  'gu-IN', 'hi-IN', 'hu-HU', 'id-ID', 'it-IT', 'kk-KZ', 'kn-IN', 'ku-IQ', 'ml-IN', 'nb-NO',\n  'nl-NL', 'nn-NO', 'or-IN', 'pa-IN', 'pl-PL', 'pt-PT', 'ru-RU', 'si-LK', 'sl-SI', 'sr-RS',\n  'sr-RS@latin', 'sv-SE', 'ta-IN', 'te-IN', 'tr-TR', 'uk-UA', 'vi-VN',\n];\n\nfor (let i = 0; i < dotDecimal.length; i++) {\n  decimal[dotDecimal[i]] = decimal['en-US'];\n}\n\nfor (let i = 0; i < commaDecimal.length; i++) {\n  decimal[commaDecimal[i]] = ',';\n}\n\nalpha['fr-CA'] = alpha['fr-FR'];\nalphanumeric['fr-CA'] = alphanumeric['fr-FR'];\n\nalpha['pt-BR'] = alpha['pt-PT'];\nalphanumeric['pt-BR'] = alphanumeric['pt-PT'];\ndecimal['pt-BR'] = decimal['pt-PT'];\n\n// see #862\nalpha['pl-Pl'] = alpha['pl-PL'];\nalphanumeric['pl-Pl'] = alphanumeric['pl-PL'];\ndecimal['pl-Pl'] = decimal['pl-PL'];\n\n// see #1455\nalpha['fa-AF'] = alpha.fa;\n"
  },
  {
    "path": "src/lib/blacklist.js",
    "content": "import assertString from './util/assertString';\n\nexport default function blacklist(str, chars) {\n  assertString(str);\n  return str.replace(new RegExp(`[${chars}]+`, 'g'), '');\n}\n"
  },
  {
    "path": "src/lib/contains.js",
    "content": "import assertString from './util/assertString';\nimport toString from './util/toString';\nimport merge from './util/merge';\n\nconst defaultContainsOptions = {\n  ignoreCase: false,\n  minOccurrences: 1,\n};\n\nexport default function contains(str, elem, options) {\n  assertString(str);\n  options = merge(options, defaultContainsOptions);\n\n  if (options.ignoreCase) {\n    return str.toLowerCase().split(toString(elem).toLowerCase()).length > options.minOccurrences;\n  }\n\n  return str.split(toString(elem)).length > options.minOccurrences;\n}\n"
  },
  {
    "path": "src/lib/equals.js",
    "content": "import assertString from './util/assertString';\n\nexport default function equals(str, comparison) {\n  assertString(str);\n  return str === comparison;\n}\n"
  },
  {
    "path": "src/lib/escape.js",
    "content": "import assertString from './util/assertString';\n\nexport default function escape(str) {\n  assertString(str);\n  return (str.replace(/&/g, '&amp;')\n    .replace(/\"/g, '&quot;')\n    .replace(/'/g, '&#x27;')\n    .replace(/</g, '&lt;')\n    .replace(/>/g, '&gt;')\n    .replace(/\\//g, '&#x2F;')\n    .replace(/\\\\/g, '&#x5C;')\n    .replace(/`/g, '&#96;'));\n}\n"
  },
  {
    "path": "src/lib/isAbaRouting.js",
    "content": "import assertString from './util/assertString';\n\n// http://www.brainjar.com/js/validation/\n// https://www.aba.com/news-research/research-analysis/routing-number-policy-procedures\n// series reserved for future use are excluded\nconst isRoutingReg = /^(?!(1[3-9])|(20)|(3[3-9])|(4[0-9])|(5[0-9])|(60)|(7[3-9])|(8[1-9])|(9[0-2])|(9[3-9]))[0-9]{9}$/;\n\nexport default function isAbaRouting(str) {\n  assertString(str);\n\n  if (!isRoutingReg.test(str)) return false;\n\n  let checkSumVal = 0;\n  for (let i = 0; i < str.length; i++) {\n    if (i % 3 === 0) checkSumVal += str[i] * 3;\n    else if (i % 3 === 1) checkSumVal += str[i] * 7;\n    else checkSumVal += str[i] * 1;\n  }\n  return (checkSumVal % 10 === 0);\n}\n"
  },
  {
    "path": "src/lib/isAfter.js",
    "content": "import toDate from './toDate';\n\nexport default function isAfter(date, options) {\n  // For backwards compatibility:\n  // isAfter(str [, date]), i.e. `options` could be used as argument for the legacy `date`\n  const comparisonDate = (typeof options === 'object' ? options.comparisonDate : options) || Date().toString();\n\n  const comparison = toDate(comparisonDate);\n  const original = toDate(date);\n\n  return !!(original && comparison && original > comparison);\n}\n"
  },
  {
    "path": "src/lib/isAlpha.js",
    "content": "import assertString from './util/assertString';\nimport { alpha } from './alpha';\n\nexport default function isAlpha(_str, locale = 'en-US', options = {}) {\n  assertString(_str);\n\n  let str = _str;\n  const { ignore } = options;\n\n  if (ignore) {\n    if (ignore instanceof RegExp) {\n      str = str.replace(ignore, '');\n    } else if (typeof ignore === 'string') {\n      str = str.replace(new RegExp(`[${ignore.replace(/[-[\\]{}()*+?.,\\\\^$|#\\\\s]/g, '\\\\$&')}]`, 'g'), ''); // escape regex for ignore\n    } else {\n      throw new Error('ignore should be instance of a String or RegExp');\n    }\n  }\n\n  if (locale in alpha) {\n    return alpha[locale].test(str);\n  }\n  throw new Error(`Invalid locale '${locale}'`);\n}\n\nexport const locales = Object.keys(alpha);\n"
  },
  {
    "path": "src/lib/isAlphanumeric.js",
    "content": "import assertString from './util/assertString';\nimport { alphanumeric } from './alpha';\n\nexport default function isAlphanumeric(_str, locale = 'en-US', options = {}) {\n  assertString(_str);\n\n  let str = _str;\n  const { ignore } = options;\n\n  if (ignore) {\n    if (ignore instanceof RegExp) {\n      str = str.replace(ignore, '');\n    } else if (typeof ignore === 'string') {\n      str = str.replace(new RegExp(`[${ignore.replace(/[-[\\]{}()*+?.,\\\\^$|#\\\\s]/g, '\\\\$&')}]`, 'g'), ''); // escape regex for ignore\n    } else {\n      throw new Error('ignore should be instance of a String or RegExp');\n    }\n  }\n\n  if (locale in alphanumeric) {\n    return alphanumeric[locale].test(str);\n  }\n  throw new Error(`Invalid locale '${locale}'`);\n}\n\nexport const locales = Object.keys(alphanumeric);\n"
  },
  {
    "path": "src/lib/isAscii.js",
    "content": "import assertString from './util/assertString';\n\n/* eslint-disable no-control-regex */\nconst ascii = /^[\\x00-\\x7F]+$/;\n/* eslint-enable no-control-regex */\n\nexport default function isAscii(str) {\n  assertString(str);\n  return ascii.test(str);\n}\n"
  },
  {
    "path": "src/lib/isBIC.js",
    "content": "import assertString from './util/assertString';\nimport { CountryCodes } from './isISO31661Alpha2';\n\n// https://en.wikipedia.org/wiki/ISO_9362\nconst isBICReg = /^[A-Za-z]{6}[A-Za-z0-9]{2}([A-Za-z0-9]{3})?$/;\n\nexport default function isBIC(str) {\n  assertString(str);\n\n  // toUpperCase() should be removed when a new major version goes out that changes\n  // the regex to [A-Z] (per the spec).\n  const countryCode = str.slice(4, 6).toUpperCase();\n\n  if (!CountryCodes.has(countryCode) && countryCode !== 'XK') {\n    return false;\n  }\n\n  return isBICReg.test(str);\n}\n"
  },
  {
    "path": "src/lib/isBase32.js",
    "content": "import assertString from './util/assertString';\nimport merge from './util/merge';\n\nconst base32 = /^[A-Z2-7]+=*$/;\nconst crockfordBase32 = /^[A-HJKMNP-TV-Z0-9]+$/;\n\nconst defaultBase32Options = {\n  crockford: false,\n};\n\nexport default function isBase32(str, options) {\n  assertString(str);\n  options = merge(options, defaultBase32Options);\n\n  if (options.crockford) {\n    return crockfordBase32.test(str);\n  }\n\n  const len = str.length;\n  if (len % 8 === 0 && base32.test(str)) {\n    return true;\n  }\n  return false;\n}\n"
  },
  {
    "path": "src/lib/isBase58.js",
    "content": "import assertString from './util/assertString';\n\n// Accepted chars - 123456789ABCDEFGH JKLMN PQRSTUVWXYZabcdefghijk mnopqrstuvwxyz\nconst base58Reg = /^[A-HJ-NP-Za-km-z1-9]*$/;\n\nexport default function isBase58(str) {\n  assertString(str);\n  if (base58Reg.test(str)) {\n    return true;\n  }\n  return false;\n}\n"
  },
  {
    "path": "src/lib/isBase64.js",
    "content": "import assertString from './util/assertString';\nimport merge from './util/merge';\n\nconst base64WithPadding = /^[A-Za-z0-9+/]+={0,2}$/;\nconst base64WithoutPadding = /^[A-Za-z0-9+/]+$/;\nconst base64UrlWithPadding = /^[A-Za-z0-9_-]+={0,2}$/;\nconst base64UrlWithoutPadding = /^[A-Za-z0-9_-]+$/;\n\nexport default function isBase64(str, options) {\n  assertString(str);\n  options = merge(options, { urlSafe: false, padding: !options?.urlSafe });\n\n  if (str === '') return true;\n\n  if (options.padding && str.length % 4 !== 0) return false;\n\n  let regex;\n  if (options.urlSafe) {\n    regex = options.padding ? base64UrlWithPadding : base64UrlWithoutPadding;\n  } else {\n    regex = options.padding ? base64WithPadding : base64WithoutPadding;\n  }\n\n  return (!options.padding || str.length % 4 === 0) && regex.test(str);\n}\n"
  },
  {
    "path": "src/lib/isBefore.js",
    "content": "import toDate from './toDate';\n\nexport default function isBefore(date, options) {\n  // For backwards compatibility:\n  // isBefore(str [, date]), i.e. `options` could be used as argument for the legacy `date`\n  const comparisonDate = (typeof options === 'object' ? options.comparisonDate : options) || Date().toString();\n\n  const comparison = toDate(comparisonDate);\n  const original = toDate(date);\n\n  return !!(original && comparison && original < comparison);\n}\n"
  },
  {
    "path": "src/lib/isBoolean.js",
    "content": "import assertString from './util/assertString';\nimport includes from './util/includesArray';\n\nconst defaultOptions = { loose: false };\nconst strictBooleans = ['true', 'false', '1', '0'];\nconst looseBooleans = [...strictBooleans, 'yes', 'no'];\n\nexport default function isBoolean(str, options = defaultOptions) {\n  assertString(str);\n\n  if (options.loose) {\n    return includes(looseBooleans, str.toLowerCase());\n  }\n\n  return includes(strictBooleans, str);\n}\n"
  },
  {
    "path": "src/lib/isBtcAddress.js",
    "content": "import assertString from './util/assertString';\n\nconst bech32 = /^(bc1|tb1|bc1p|tb1p)[ac-hj-np-z02-9]{39,58}$/;\nconst base58 = /^(1|2|3|m)[A-HJ-NP-Za-km-z1-9]{25,39}$/;\n\nexport default function isBtcAddress(str) {\n  assertString(str);\n  return bech32.test(str) || base58.test(str);\n}\n"
  },
  {
    "path": "src/lib/isByteLength.js",
    "content": "import assertString from './util/assertString';\n\n/* eslint-disable prefer-rest-params */\nexport default function isByteLength(str, options) {\n  assertString(str);\n  let min;\n  let max;\n  if (typeof (options) === 'object') {\n    min = options.min || 0;\n    max = options.max;\n  } else { // backwards compatibility: isByteLength(str, min [, max])\n    min = arguments[1];\n    max = arguments[2];\n  }\n  const len = encodeURI(str).split(/%..|./).length - 1;\n  return len >= min && (typeof max === 'undefined' || len <= max);\n}\n"
  },
  {
    "path": "src/lib/isCreditCard.js",
    "content": "import assertString from './util/assertString';\nimport isLuhnValid from './isLuhnNumber';\n\nconst cards = {\n  amex: /^3[47][0-9]{13}$/,\n  dinersclub: /^3(?:0[0-5]|[68][0-9])[0-9]{11}$/,\n  discover: /^6(?:011|5[0-9][0-9])[0-9]{12,15}$/,\n  jcb: /^(?:2131|1800|35\\d{3})\\d{11}$/,\n  mastercard: /^5[1-5][0-9]{2}|(222[1-9]|22[3-9][0-9]|2[3-6][0-9]{2}|27[01][0-9]|2720)[0-9]{12}$/, // /^[25][1-7][0-9]{14}$/;\n  unionpay: /^(6[27][0-9]{14}|^(81[0-9]{14,17}))$/,\n  visa: /^(?:4[0-9]{12})(?:[0-9]{3,6})?$/,\n};\n\nconst allCards = (() => {\n  const tmpCardsArray = [];\n  for (const cardProvider in cards) {\n    // istanbul ignore else\n    if (cards.hasOwnProperty(cardProvider)) {\n      tmpCardsArray.push(cards[cardProvider]);\n    }\n  }\n  return tmpCardsArray;\n})();\n\nexport default function isCreditCard(card, options = {}) {\n  assertString(card);\n  const { provider } = options;\n  const sanitized = card.replace(/[- ]+/g, '');\n  if (provider && provider.toLowerCase() in cards) {\n    // specific provider in the list\n    if (!(cards[provider.toLowerCase()].test(sanitized))) {\n      return false;\n    }\n  } else if (provider && !(provider.toLowerCase() in cards)) {\n    /* specific provider not in the list */\n    throw new Error(`${provider} is not a valid credit card provider.`);\n  } else if (!allCards.some(cardProvider => cardProvider.test(sanitized))) {\n    // no specific provider\n    return false;\n  }\n  return isLuhnValid(card);\n}\n"
  },
  {
    "path": "src/lib/isCurrency.js",
    "content": "import merge from './util/merge';\nimport assertString from './util/assertString';\n\nfunction currencyRegex(options) {\n  let decimal_digits = `\\\\d{${options.digits_after_decimal[0]}}`;\n  options.digits_after_decimal.forEach((digit, index) => { if (index !== 0) decimal_digits = `${decimal_digits}|\\\\d{${digit}}`; });\n\n  const symbol =\n    `(${options.symbol.replace(/\\W/, m => `\\\\${m}`)})${(options.require_symbol ? '' : '?')}`,\n    negative = '-?',\n    whole_dollar_amount_without_sep = '[1-9]\\\\d*',\n    whole_dollar_amount_with_sep = `[1-9]\\\\d{0,2}(\\\\${options.thousands_separator}\\\\d{3})*`,\n    valid_whole_dollar_amounts = [\n      '0', whole_dollar_amount_without_sep, whole_dollar_amount_with_sep],\n    whole_dollar_amount = `(${valid_whole_dollar_amounts.join('|')})?`,\n    decimal_amount = `(\\\\${options.decimal_separator}(${decimal_digits}))${options.require_decimal ? '' : '?'}`;\n  let pattern = whole_dollar_amount + (options.allow_decimal || options.require_decimal ? decimal_amount : '');\n\n  // default is negative sign before symbol, but there are two other options (besides parens)\n  if (options.allow_negatives && !options.parens_for_negatives) {\n    if (options.negative_sign_after_digits) {\n      pattern += negative;\n    } else if (options.negative_sign_before_digits) {\n      pattern = negative + pattern;\n    }\n  }\n\n  // South African Rand, for example, uses R 123 (space) and R-123 (no space)\n  if (options.allow_negative_sign_placeholder) {\n    pattern = `( (?!\\\\-))?${pattern}`;\n  } else if (options.allow_space_after_symbol) {\n    pattern = ` ?${pattern}`;\n  } else if (options.allow_space_after_digits) {\n    pattern += '( (?!$))?';\n  }\n\n  if (options.symbol_after_digits) {\n    pattern += symbol;\n  } else {\n    pattern = symbol + pattern;\n  }\n\n  if (options.allow_negatives) {\n    if (options.parens_for_negatives) {\n      pattern = `(\\\\(${pattern}\\\\)|${pattern})`;\n    } else if (!(options.negative_sign_before_digits || options.negative_sign_after_digits)) {\n      pattern = negative + pattern;\n    }\n  }\n\n  // ensure there's a dollar and/or decimal amount, and that\n  // it doesn't start with a space or a negative sign followed by a space\n  return new RegExp(`^(?!-? )(?=.*\\\\d)${pattern}$`);\n}\n\n\nconst default_currency_options = {\n  symbol: '$',\n  require_symbol: false,\n  allow_space_after_symbol: false,\n  symbol_after_digits: false,\n  allow_negatives: true,\n  parens_for_negatives: false,\n  negative_sign_before_digits: false,\n  negative_sign_after_digits: false,\n  allow_negative_sign_placeholder: false,\n  thousands_separator: ',',\n  decimal_separator: '.',\n  allow_decimal: true,\n  require_decimal: false,\n  digits_after_decimal: [2],\n  allow_space_after_digits: false,\n};\n\nexport default function isCurrency(str, options) {\n  assertString(str);\n  options = merge(options, default_currency_options);\n  return currencyRegex(options).test(str);\n}\n"
  },
  {
    "path": "src/lib/isDataURI.js",
    "content": "import assertString from './util/assertString';\n\nconst validMediaType = /^[a-z]+\\/[a-z0-9\\-\\+\\._]+$/i;\n\nconst validAttribute = /^[a-z\\-]+=[a-z0-9\\-]+$/i;\n\nconst validData = /^[a-z0-9!\\$&'\\(\\)\\*\\+,;=\\-\\._~:@\\/\\?%\\s]*$/i;\n\nexport default function isDataURI(str) {\n  assertString(str);\n  let data = str.split(',');\n  if (data.length < 2) {\n    return false;\n  }\n  const attributes = data.shift().trim().split(';');\n  const schemeAndMediaType = attributes.shift();\n  if (schemeAndMediaType.slice(0, 5) !== 'data:') {\n    return false;\n  }\n  const mediaType = schemeAndMediaType.slice(5);\n  if (mediaType !== '' && !validMediaType.test(mediaType)) {\n    return false;\n  }\n  for (let i = 0; i < attributes.length; i++) {\n    if (\n      !(i === attributes.length - 1 && attributes[i].toLowerCase() === 'base64') &&\n      !validAttribute.test(attributes[i])\n    ) {\n      return false;\n    }\n  }\n  for (let i = 0; i < data.length; i++) {\n    if (!validData.test(data[i])) {\n      return false;\n    }\n  }\n  return true;\n}\n"
  },
  {
    "path": "src/lib/isDate.js",
    "content": "import merge from './util/merge';\n\nconst default_date_options = {\n  format: 'YYYY/MM/DD',\n  delimiters: ['/', '-'],\n  strictMode: false,\n};\n\nfunction isValidFormat(format) {\n  return /(^(y{4}|y{2})[.\\/-](m{1,2})[.\\/-](d{1,2})$)|(^(m{1,2})[.\\/-](d{1,2})[.\\/-]((y{4}|y{2})$))|(^(d{1,2})[.\\/-](m{1,2})[.\\/-]((y{4}|y{2})$))/gi.test(format);\n}\n\nfunction zip(date, format) {\n  const zippedArr = [],\n    len = Math.max(date.length, format.length);\n\n  for (let i = 0; i < len; i++) {\n    zippedArr.push([date[i], format[i]]);\n  }\n\n  return zippedArr;\n}\n\nexport default function isDate(input, options) {\n  if (typeof options === 'string') { // Allow backward compatibility for old format isDate(input [, format])\n    options = merge({ format: options }, default_date_options);\n  } else {\n    options = merge(options, default_date_options);\n  }\n  if (typeof input === 'string' && isValidFormat(options.format)) {\n    if (options.strictMode && input.length !== options.format.length) return false;\n    const formatDelimiter = options.delimiters\n      .find(delimiter => options.format.indexOf(delimiter) !== -1);\n    const dateDelimiter = options.strictMode\n      ? formatDelimiter\n      : options.delimiters.find(delimiter => input.indexOf(delimiter) !== -1);\n    const dateAndFormat = zip(\n      input.split(dateDelimiter),\n      options.format.toLowerCase().split(formatDelimiter)\n    );\n    const dateObj = {};\n\n    for (const [dateWord, formatWord] of dateAndFormat) {\n      if (!dateWord || !formatWord || dateWord.length !== formatWord.length) {\n        return false;\n      }\n\n      dateObj[formatWord.charAt(0)] = dateWord;\n    }\n\n    let fullYear = dateObj.y;\n\n    // Check if the year starts with a hyphen\n    if (fullYear.startsWith('-')) {\n      return false; // Hyphen before year is not allowed\n    }\n\n    if (dateObj.y.length === 2) {\n      const parsedYear = parseInt(dateObj.y, 10);\n\n      if (isNaN(parsedYear)) {\n        return false;\n      }\n\n      const currentYearLastTwoDigits = new Date().getFullYear() % 100;\n\n      if (parsedYear < currentYearLastTwoDigits) {\n        fullYear = `20${dateObj.y}`;\n      } else {\n        fullYear = `19${dateObj.y}`;\n      }\n    }\n\n    let month = dateObj.m;\n\n    if (dateObj.m.length === 1) {\n      month = `0${dateObj.m}`;\n    }\n\n    let day = dateObj.d;\n\n    if (dateObj.d.length === 1) {\n      day = `0${dateObj.d}`;\n    }\n\n    return new Date(`${fullYear}-${month}-${day}T00:00:00.000Z`).getUTCDate() === +dateObj.d;\n  }\n\n  if (!options.strictMode) {\n    return Object.prototype.toString.call(input) === '[object Date]' && isFinite(input);\n  }\n\n  return false;\n}\n"
  },
  {
    "path": "src/lib/isDecimal.js",
    "content": "import merge from './util/merge';\nimport assertString from './util/assertString';\nimport includes from './util/includesArray';\nimport { decimal } from './alpha';\n\nfunction decimalRegExp(options) {\n  const regExp = new RegExp(`^[-+]?([0-9]+)?(\\\\${decimal[options.locale]}[0-9]{${options.decimal_digits}})${options.force_decimal ? '' : '?'}$`);\n  return regExp;\n}\n\nconst default_decimal_options = {\n  force_decimal: false,\n  decimal_digits: '1,',\n  locale: 'en-US',\n};\n\nconst blacklist = ['', '-', '+'];\n\nexport default function isDecimal(str, options) {\n  assertString(str);\n  options = merge(options, default_decimal_options);\n  if (options.locale in decimal) {\n    return !includes(blacklist, str.replace(/ /g, '')) && decimalRegExp(options).test(str);\n  }\n  throw new Error(`Invalid locale '${options.locale}'`);\n}\n"
  },
  {
    "path": "src/lib/isDivisibleBy.js",
    "content": "import assertString from './util/assertString';\nimport toFloat from './toFloat';\n\nexport default function isDivisibleBy(str, num) {\n  assertString(str);\n  return toFloat(str) % parseInt(num, 10) === 0;\n}\n"
  },
  {
    "path": "src/lib/isEAN.js",
    "content": "/**\n * The most commonly used EAN standard is\n * the thirteen-digit EAN-13, while the\n * less commonly used 8-digit EAN-8 barcode was\n * introduced for use on small packages.\n * Also EAN/UCC-14 is used for Grouping of individual\n * trade items above unit level(Intermediate, Carton or Pallet).\n * For more info about EAN-14 checkout: https://www.gtin.info/itf-14-barcodes/\n * EAN consists of:\n * GS1 prefix, manufacturer code, product code and check digit\n * Reference: https://en.wikipedia.org/wiki/International_Article_Number\n * Reference: https://www.gtin.info/\n */\n\nimport assertString from './util/assertString';\n\n/**\n * Define EAN Lengths; 8 for EAN-8; 13 for EAN-13; 14 for EAN-14\n * and Regular Expression for valid EANs (EAN-8, EAN-13, EAN-14),\n * with exact numeric matching of 8 or 13 or 14 digits [0-9]\n */\nconst LENGTH_EAN_8 = 8;\nconst LENGTH_EAN_14 = 14;\nconst validEanRegex = /^(\\d{8}|\\d{13}|\\d{14})$/;\n\n\n/**\n * Get position weight given:\n * EAN length and digit index/position\n *\n * @param {number} length\n * @param {number} index\n * @return {number}\n */\nfunction getPositionWeightThroughLengthAndIndex(length, index) {\n  if (length === LENGTH_EAN_8 || length === LENGTH_EAN_14) {\n    return (index % 2 === 0) ? 3 : 1;\n  }\n\n  return (index % 2 === 0) ? 1 : 3;\n}\n\n/**\n * Calculate EAN Check Digit\n * Reference: https://en.wikipedia.org/wiki/International_Article_Number#Calculation_of_checksum_digit\n *\n * @param {string} ean\n * @return {number}\n */\nfunction calculateCheckDigit(ean) {\n  const checksum = ean\n    .slice(0, -1)\n    .split('')\n    .map((char, index) => Number(char) * getPositionWeightThroughLengthAndIndex(ean.length, index))\n    .reduce((acc, partialSum) => acc + partialSum, 0);\n\n  const remainder = 10 - (checksum % 10);\n\n  return remainder < 10 ? remainder : 0;\n}\n\n/**\n * Check if string is valid EAN:\n * Matches EAN-8/EAN-13/EAN-14 regex\n * Has valid check digit.\n *\n * @param {string} str\n * @return {boolean}\n */\nexport default function isEAN(str) {\n  assertString(str);\n  const actualCheckDigit = Number(str.slice(-1));\n\n  return validEanRegex.test(str) && actualCheckDigit === calculateCheckDigit(str);\n}\n"
  },
  {
    "path": "src/lib/isEmail.js",
    "content": "import assertString from './util/assertString';\nimport checkHost from './util/checkHost';\n\nimport isByteLength from './isByteLength';\nimport isFQDN from './isFQDN';\nimport isIP from './isIP';\nimport merge from './util/merge';\n\nconst default_email_options = {\n  allow_display_name: false,\n  allow_underscores: false,\n  require_display_name: false,\n  allow_utf8_local_part: true,\n  require_tld: true,\n  blacklisted_chars: '',\n  ignore_max_length: false,\n  host_blacklist: [],\n  host_whitelist: [],\n};\n\n/* eslint-disable max-len */\n/* eslint-disable no-control-regex */\nconst splitNameAddress = /^([^\\x00-\\x1F\\x7F-\\x9F\\cX]+)</i;\nconst emailUserPart = /^[a-z\\d!#\\$%&'\\*\\+\\-\\/=\\?\\^_`{\\|}~]+$/i;\nconst gmailUserPart = /^[a-z\\d]+$/;\nconst quotedEmailUser = /^([\\s\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x7f\\x21\\x23-\\x5b\\x5d-\\x7e]|(\\\\[\\x01-\\x09\\x0b\\x0c\\x0d-\\x7f]))*$/i;\nconst emailUserUtf8Part = /^[a-z\\d!#\\$%&'\\*\\+\\-\\/=\\?\\^_`{\\|}~\\u00A1-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF]+$/i;\nconst quotedEmailUserUtf8 = /^([\\s\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x7f\\x21\\x23-\\x5b\\x5d-\\x7e\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF]|(\\\\[\\x01-\\x09\\x0b\\x0c\\x0d-\\x7f\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF]))*$/i;\nconst defaultMaxEmailLength = 254;\n/* eslint-enable max-len */\n/* eslint-enable no-control-regex */\n\n/**\n * Validate display name according to the RFC2822: https://tools.ietf.org/html/rfc2822#appendix-A.1.2\n * @param {String} display_name\n */\nfunction validateDisplayName(display_name) {\n  const display_name_without_quotes = display_name.replace(/^\"(.+)\"$/, '$1');\n  // display name with only spaces is not valid\n  if (!display_name_without_quotes.trim()) {\n    return false;\n  }\n\n  // check whether display name contains illegal character\n  const contains_illegal = /[\\.\";<>]/.test(display_name_without_quotes);\n  if (contains_illegal) {\n    // if contains illegal characters,\n    // must to be enclosed in double-quotes, otherwise it's not a valid display name\n    if (display_name_without_quotes === display_name) {\n      return false;\n    }\n\n    // the quotes in display name must start with character symbol \\\n    const all_start_with_back_slash =\n      display_name_without_quotes.split('\"').length === display_name_without_quotes.split('\\\\\"').length;\n    if (!all_start_with_back_slash) {\n      return false;\n    }\n  }\n\n  return true;\n}\n\nexport default function isEmail(str, options) {\n  assertString(str);\n  options = merge(options, default_email_options);\n\n  if (options.require_display_name || options.allow_display_name) {\n    const display_email = str.match(splitNameAddress);\n    if (display_email) {\n      let display_name = display_email[1];\n\n      // Remove display name and angle brackets to get email address\n      // Can be done in the regex but will introduce a ReDOS (See  #1597 for more info)\n      str = str.replace(display_name, '').replace(/(^<|>$)/g, '');\n\n      // sometimes need to trim the last space to get the display name\n      // because there may be a space between display name and email address\n      // eg. myname <address@gmail.com>\n      // the display name is `myname` instead of `myname `, so need to trim the last space\n      if (display_name.endsWith(' ')) {\n        display_name = display_name.slice(0, -1);\n      }\n\n      if (!validateDisplayName(display_name)) {\n        return false;\n      }\n    } else if (options.require_display_name) {\n      return false;\n    }\n  }\n  if (!options.ignore_max_length && str.length > defaultMaxEmailLength) {\n    return false;\n  }\n\n  const parts = str.split('@');\n  const domain = parts.pop();\n  const lower_domain = domain.toLowerCase();\n\n  if (options.host_blacklist.length > 0 && checkHost(lower_domain, options.host_blacklist)) {\n    return false;\n  }\n\n  if (options.host_whitelist.length > 0 && !checkHost(lower_domain, options.host_whitelist)) {\n    return false;\n  }\n\n  let user = parts.join('@');\n\n  if (options.domain_specific_validation && (lower_domain === 'gmail.com' || lower_domain === 'googlemail.com')) {\n    /*\n    Previously we removed dots for gmail addresses before validating.\n    This was removed because it allows `multiple..dots@gmail.com`\n    to be reported as valid, but it is not.\n    Gmail only normalizes single dots, removing them from here is pointless,\n    should be done in normalizeEmail\n    */\n    user = user.toLowerCase();\n\n    // Removing sub-address from username before gmail validation\n    const username = user.split('+')[0];\n\n    // Dots are not included in gmail length restriction\n    if (!isByteLength(username.replace(/\\./g, ''), { min: 6, max: 30 })) {\n      return false;\n    }\n\n    const user_parts = username.split('.');\n    for (let i = 0; i < user_parts.length; i++) {\n      if (!gmailUserPart.test(user_parts[i])) {\n        return false;\n      }\n    }\n  }\n\n  if (options.ignore_max_length === false && (\n    !isByteLength(user, { max: 64 }) ||\n    !isByteLength(domain, { max: 254 }))\n  ) {\n    return false;\n  }\n\n  if (!isFQDN(domain, {\n    require_tld: options.require_tld,\n    ignore_max_length: options.ignore_max_length,\n    allow_underscores: options.allow_underscores,\n  })) {\n    if (!options.allow_ip_domain) {\n      return false;\n    }\n\n    if (!isIP(domain)) {\n      if (!domain.startsWith('[') || !domain.endsWith(']')) {\n        return false;\n      }\n\n      let noBracketdomain = domain.slice(1, -1);\n\n      if (noBracketdomain.length === 0 || !isIP(noBracketdomain)) {\n        return false;\n      }\n    }\n  }\n\n  if (options.blacklisted_chars) {\n    if (user.search(new RegExp(`[${options.blacklisted_chars}]+`, 'g')) !== -1) return false;\n  }\n\n  if (user[0] === '\"' && user[user.length - 1] === '\"') {\n    user = user.slice(1, user.length - 1);\n    return options.allow_utf8_local_part ?\n      quotedEmailUserUtf8.test(user) :\n      quotedEmailUser.test(user);\n  }\n\n  const pattern = options.allow_utf8_local_part ?\n    emailUserUtf8Part : emailUserPart;\n\n  const user_parts = user.split('.');\n  for (let i = 0; i < user_parts.length; i++) {\n    if (!pattern.test(user_parts[i])) {\n      return false;\n    }\n  }\n\n  return true;\n}\n"
  },
  {
    "path": "src/lib/isEmpty.js",
    "content": "import assertString from './util/assertString';\nimport merge from './util/merge';\n\nconst default_is_empty_options = {\n  ignore_whitespace: false,\n};\n\nexport default function isEmpty(str, options) {\n  assertString(str);\n  options = merge(options, default_is_empty_options);\n\n  return (options.ignore_whitespace ? str.trim().length : str.length) === 0;\n}\n"
  },
  {
    "path": "src/lib/isEthereumAddress.js",
    "content": "import assertString from './util/assertString';\n\nconst eth = /^(0x)[0-9a-f]{40}$/i;\n\nexport default function isEthereumAddress(str) {\n  assertString(str);\n  return eth.test(str);\n}\n"
  },
  {
    "path": "src/lib/isFQDN.js",
    "content": "import assertString from './util/assertString';\nimport merge from './util/merge';\n\nconst default_fqdn_options = {\n  require_tld: true,\n  allow_underscores: false,\n  allow_trailing_dot: false,\n  allow_numeric_tld: false,\n  allow_wildcard: false,\n  ignore_max_length: false,\n};\n\nexport default function isFQDN(str, options) {\n  assertString(str);\n  options = merge(options, default_fqdn_options);\n\n  /* Remove the optional trailing dot before checking validity */\n  if (options.allow_trailing_dot && str[str.length - 1] === '.') {\n    str = str.substring(0, str.length - 1);\n  }\n\n  /* Remove the optional wildcard before checking validity */\n  if (options.allow_wildcard === true && str.indexOf('*.') === 0) {\n    str = str.substring(2);\n  }\n\n  const parts = str.split('.');\n  const tld = parts[parts.length - 1];\n\n  if (options.require_tld) {\n    // disallow fqdns without tld\n    if (parts.length < 2) {\n      return false;\n    }\n\n    if (!options.allow_numeric_tld && !/^([a-z\\u00A1-\\u00A8\\u00AA-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF]{2,}|xn[a-z0-9-]{2,})$/i.test(tld)) {\n      return false;\n    }\n\n    // disallow spaces\n    if (/\\s/.test(tld)) {\n      return false;\n    }\n  }\n\n  // reject numeric TLDs\n  if (!options.allow_numeric_tld && /^\\d+$/.test(tld)) {\n    return false;\n  }\n\n  return parts.every((part) => {\n    if (part.length > 63 && !options.ignore_max_length) {\n      return false;\n    }\n\n    if (!/^[a-z_\\u00a1-\\uffff0-9-]+$/i.test(part)) {\n      return false;\n    }\n\n    // disallow full-width chars\n    if (/[\\uff01-\\uff5e]/.test(part)) {\n      return false;\n    }\n\n    // disallow parts starting or ending with hyphen\n    if (/^-|-$/.test(part)) {\n      return false;\n    }\n\n    if (!options.allow_underscores && /_/.test(part)) {\n      return false;\n    }\n\n    return true;\n  });\n}\n"
  },
  {
    "path": "src/lib/isFloat.js",
    "content": "import assertString from './util/assertString';\nimport isNullOrUndefined from './util/nullUndefinedCheck';\nimport { decimal } from './alpha';\n\nexport default function isFloat(str, options) {\n  assertString(str);\n  options = options || {};\n  const float = new RegExp(`^(?:[-+])?(?:[0-9]+)?(?:\\\\${options.locale ? decimal[options.locale] : '.'}[0-9]*)?(?:[eE][\\\\+\\\\-]?(?:[0-9]+))?$`);\n  if (str === '' || str === '.' || str === ',' || str === '-' || str === '+') {\n    return false;\n  }\n  const value = parseFloat(str.replace(',', '.'));\n  return float.test(str) &&\n    (!options.hasOwnProperty('min') || isNullOrUndefined(options.min) || value >= options.min) &&\n    (!options.hasOwnProperty('max') || isNullOrUndefined(options.max) || value <= options.max) &&\n    (!options.hasOwnProperty('lt') || isNullOrUndefined(options.lt) || value < options.lt) &&\n    (!options.hasOwnProperty('gt') || isNullOrUndefined(options.gt) || value > options.gt);\n}\n\nexport const locales = Object.keys(decimal);\n"
  },
  {
    "path": "src/lib/isFullWidth.js",
    "content": "import assertString from './util/assertString';\n\nexport const fullWidth = /[^\\u0020-\\u007E\\uFF61-\\uFF9F\\uFFA0-\\uFFDC\\uFFE8-\\uFFEE0-9a-zA-Z]/;\n\nexport default function isFullWidth(str) {\n  assertString(str);\n  return fullWidth.test(str);\n}\n"
  },
  {
    "path": "src/lib/isHSL.js",
    "content": "import assertString from './util/assertString';\n\n\nconst hslComma = /^hsla?\\(((\\+|\\-)?([0-9]+(\\.[0-9]+)?(e(\\+|\\-)?[0-9]+)?|\\.[0-9]+(e(\\+|\\-)?[0-9]+)?))(deg|grad|rad|turn)?(,(\\+|\\-)?([0-9]+(\\.[0-9]+)?(e(\\+|\\-)?[0-9]+)?|\\.[0-9]+(e(\\+|\\-)?[0-9]+)?)%){2}(,((\\+|\\-)?([0-9]+(\\.[0-9]+)?(e(\\+|\\-)?[0-9]+)?|\\.[0-9]+(e(\\+|\\-)?[0-9]+)?)%?))?\\)$/i;\nconst hslSpace = /^hsla?\\(((\\+|\\-)?([0-9]+(\\.[0-9]+)?(e(\\+|\\-)?[0-9]+)?|\\.[0-9]+(e(\\+|\\-)?[0-9]+)?))(deg|grad|rad|turn)?(\\s(\\+|\\-)?([0-9]+(\\.[0-9]+)?(e(\\+|\\-)?[0-9]+)?|\\.[0-9]+(e(\\+|\\-)?[0-9]+)?)%){2}\\s?(\\/\\s((\\+|\\-)?([0-9]+(\\.[0-9]+)?(e(\\+|\\-)?[0-9]+)?|\\.[0-9]+(e(\\+|\\-)?[0-9]+)?)%?)\\s?)?\\)$/i;\n\n\nexport default function isHSL(str) {\n  assertString(str);\n\n  // Strip duplicate spaces before calling the validation regex (See  #1598 for more info)\n  const strippedStr = str.replace(/\\s+/g, ' ').replace(/\\s?(hsla?\\(|\\)|,)\\s?/ig, '$1');\n\n  if (strippedStr.indexOf(',') !== -1) {\n    return hslComma.test(strippedStr);\n  }\n\n  return hslSpace.test(strippedStr);\n}\n"
  },
  {
    "path": "src/lib/isHalfWidth.js",
    "content": "import assertString from './util/assertString';\n\nexport const halfWidth = /[\\u0020-\\u007E\\uFF61-\\uFF9F\\uFFA0-\\uFFDC\\uFFE8-\\uFFEE0-9a-zA-Z]/;\n\nexport default function isHalfWidth(str) {\n  assertString(str);\n  return halfWidth.test(str);\n}\n"
  },
  {
    "path": "src/lib/isHash.js",
    "content": "import assertString from './util/assertString';\n\nconst lengths = {\n  md5: 32,\n  md4: 32,\n  sha1: 40,\n  sha256: 64,\n  sha384: 96,\n  sha512: 128,\n  ripemd128: 32,\n  ripemd160: 40,\n  tiger128: 32,\n  tiger160: 40,\n  tiger192: 48,\n  crc32: 8,\n  crc32b: 8,\n};\n\nexport default function isHash(str, algorithm) {\n  assertString(str);\n  const hash = new RegExp(`^[a-fA-F0-9]{${lengths[algorithm]}}$`);\n  return hash.test(str);\n}\n"
  },
  {
    "path": "src/lib/isHexColor.js",
    "content": "import assertString from './util/assertString';\nimport merge from './util/merge';\n\nconst hexcolor = /^#?([0-9A-F]{3}|[0-9A-F]{4}|[0-9A-F]{6}|[0-9A-F]{8})$/i;\nconst hexcolor_with_prefix = /^#([0-9A-F]{3}|[0-9A-F]{4}|[0-9A-F]{6}|[0-9A-F]{8})$/i;\n\nconst default_is_hexcolor_options = {\n  require_hashtag: false,\n};\n\nexport default function isHexColor(str, options) {\n  assertString(str);\n  options = merge(options, default_is_hexcolor_options);\n\n  const hexcolor_regex = options.require_hashtag\n    ? hexcolor_with_prefix\n    : hexcolor;\n  return hexcolor_regex.test(str);\n}\n"
  },
  {
    "path": "src/lib/isHexadecimal.js",
    "content": "import assertString from './util/assertString';\n\nconst hexadecimal = /^(0x|0h)?[0-9A-F]+$/i;\n\nexport default function isHexadecimal(str) {\n  assertString(str);\n  return hexadecimal.test(str);\n}\n"
  },
  {
    "path": "src/lib/isIBAN.js",
    "content": "import assertString from './util/assertString';\nimport includes from './util/includesArray';\n\n/**\n * List of country codes with\n * corresponding IBAN regular expression\n * Reference: https://en.wikipedia.org/wiki/International_Bank_Account_Number\n */\nconst ibanRegexThroughCountryCode = {\n  AD: /^(AD[0-9]{2})\\d{8}[A-Z0-9]{12}$/,\n  AE: /^(AE[0-9]{2})\\d{3}\\d{16}$/,\n  AL: /^(AL[0-9]{2})\\d{8}[A-Z0-9]{16}$/,\n  AT: /^(AT[0-9]{2})\\d{16}$/,\n  AZ: /^(AZ[0-9]{2})[A-Z0-9]{4}\\d{20}$/,\n  BA: /^(BA[0-9]{2})\\d{16}$/,\n  BE: /^(BE[0-9]{2})\\d{12}$/,\n  BG: /^(BG[0-9]{2})[A-Z]{4}\\d{6}[A-Z0-9]{8}$/,\n  BH: /^(BH[0-9]{2})[A-Z]{4}[A-Z0-9]{14}$/,\n  BR: /^(BR[0-9]{2})\\d{23}[A-Z]{1}[A-Z0-9]{1}$/,\n  BY: /^(BY[0-9]{2})[A-Z0-9]{4}\\d{20}$/,\n  CH: /^(CH[0-9]{2})\\d{5}[A-Z0-9]{12}$/,\n  CR: /^(CR[0-9]{2})\\d{18}$/,\n  CY: /^(CY[0-9]{2})\\d{8}[A-Z0-9]{16}$/,\n  CZ: /^(CZ[0-9]{2})\\d{20}$/,\n  DE: /^(DE[0-9]{2})\\d{18}$/,\n  DK: /^(DK[0-9]{2})\\d{14}$/,\n  DO: /^(DO[0-9]{2})[A-Z]{4}\\d{20}$/,\n  DZ: /^(DZ\\d{24})$/,\n  EE: /^(EE[0-9]{2})\\d{16}$/,\n  EG: /^(EG[0-9]{2})\\d{25}$/,\n  ES: /^(ES[0-9]{2})\\d{20}$/,\n  FI: /^(FI[0-9]{2})\\d{14}$/,\n  FO: /^(FO[0-9]{2})\\d{14}$/,\n  FR: /^(FR[0-9]{2})\\d{10}[A-Z0-9]{11}\\d{2}$/,\n  GB: /^(GB[0-9]{2})[A-Z]{4}\\d{14}$/,\n  GE: /^(GE[0-9]{2})[A-Z0-9]{2}\\d{16}$/,\n  GI: /^(GI[0-9]{2})[A-Z]{4}[A-Z0-9]{15}$/,\n  GL: /^(GL[0-9]{2})\\d{14}$/,\n  GR: /^(GR[0-9]{2})\\d{7}[A-Z0-9]{16}$/,\n  GT: /^(GT[0-9]{2})[A-Z0-9]{4}[A-Z0-9]{20}$/,\n  HR: /^(HR[0-9]{2})\\d{17}$/,\n  HU: /^(HU[0-9]{2})\\d{24}$/,\n  IE: /^(IE[0-9]{2})[A-Z]{4}\\d{14}$/,\n  IL: /^(IL[0-9]{2})\\d{19}$/,\n  IQ: /^(IQ[0-9]{2})[A-Z]{4}\\d{15}$/,\n  IR: /^(IR[0-9]{2})\\d{22}$/,\n  IS: /^(IS[0-9]{2})\\d{22}$/,\n  IT: /^(IT[0-9]{2})[A-Z]{1}\\d{10}[A-Z0-9]{12}$/,\n  JO: /^(JO[0-9]{2})[A-Z]{4}\\d{22}$/,\n  KW: /^(KW[0-9]{2})[A-Z]{4}[A-Z0-9]{22}$/,\n  KZ: /^(KZ[0-9]{2})\\d{3}[A-Z0-9]{13}$/,\n  LB: /^(LB[0-9]{2})\\d{4}[A-Z0-9]{20}$/,\n  LC: /^(LC[0-9]{2})[A-Z]{4}[A-Z0-9]{24}$/,\n  LI: /^(LI[0-9]{2})\\d{5}[A-Z0-9]{12}$/,\n  LT: /^(LT[0-9]{2})\\d{16}$/,\n  LU: /^(LU[0-9]{2})\\d{3}[A-Z0-9]{13}$/,\n  LV: /^(LV[0-9]{2})[A-Z]{4}[A-Z0-9]{13}$/,\n  MA: /^(MA[0-9]{26})$/,\n  MC: /^(MC[0-9]{2})\\d{10}[A-Z0-9]{11}\\d{2}$/,\n  MD: /^(MD[0-9]{2})[A-Z0-9]{20}$/,\n  ME: /^(ME[0-9]{2})\\d{18}$/,\n  MK: /^(MK[0-9]{2})\\d{3}[A-Z0-9]{10}\\d{2}$/,\n  MR: /^(MR[0-9]{2})\\d{23}$/,\n  MT: /^(MT[0-9]{2})[A-Z]{4}\\d{5}[A-Z0-9]{18}$/,\n  MU: /^(MU[0-9]{2})[A-Z]{4}\\d{19}[A-Z]{3}$/,\n  MZ: /^(MZ[0-9]{2})\\d{21}$/,\n  NL: /^(NL[0-9]{2})[A-Z]{4}\\d{10}$/,\n  NO: /^(NO[0-9]{2})\\d{11}$/,\n  PK: /^(PK[0-9]{2})[A-Z0-9]{4}\\d{16}$/,\n  PL: /^(PL[0-9]{2})\\d{24}$/,\n  PS: /^(PS[0-9]{2})[A-Z]{4}[A-Z0-9]{21}$/,\n  PT: /^(PT[0-9]{2})\\d{21}$/,\n  QA: /^(QA[0-9]{2})[A-Z]{4}[A-Z0-9]{21}$/,\n  RO: /^(RO[0-9]{2})[A-Z]{4}[A-Z0-9]{16}$/,\n  RS: /^(RS[0-9]{2})\\d{18}$/,\n  SA: /^(SA[0-9]{2})\\d{2}[A-Z0-9]{18}$/,\n  SC: /^(SC[0-9]{2})[A-Z]{4}\\d{20}[A-Z]{3}$/,\n  SE: /^(SE[0-9]{2})\\d{20}$/,\n  SI: /^(SI[0-9]{2})\\d{15}$/,\n  SK: /^(SK[0-9]{2})\\d{20}$/,\n  SM: /^(SM[0-9]{2})[A-Z]{1}\\d{10}[A-Z0-9]{12}$/,\n  SV: /^(SV[0-9]{2})[A-Z0-9]{4}\\d{20}$/,\n  TL: /^(TL[0-9]{2})\\d{19}$/,\n  TN: /^(TN[0-9]{2})\\d{20}$/,\n  TR: /^(TR[0-9]{2})\\d{5}[A-Z0-9]{17}$/,\n  UA: /^(UA[0-9]{2})\\d{6}[A-Z0-9]{19}$/,\n  VA: /^(VA[0-9]{2})\\d{18}$/,\n  VG: /^(VG[0-9]{2})[A-Z]{4}\\d{16}$/,\n  XK: /^(XK[0-9]{2})\\d{16}$/,\n};\n\n/**\n * Check if the country codes passed are valid using the\n * ibanRegexThroughCountryCode as a reference\n *\n * @param {array} countryCodeArray\n * @return {boolean}\n */\n\nfunction hasOnlyValidCountryCodes(countryCodeArray) {\n  const countryCodeArrayFilteredWithObjectIbanCode = countryCodeArray\n    .filter(countryCode => !(countryCode in ibanRegexThroughCountryCode));\n\n  if (countryCodeArrayFilteredWithObjectIbanCode.length > 0) {\n    return false;\n  }\n\n  return true;\n}\n\n/**\n * Check whether string has correct universal IBAN format\n * The IBAN consists of up to 34 alphanumeric characters, as follows:\n * Country Code using ISO 3166-1 alpha-2, two letters\n * check digits, two digits and\n * Basic Bank Account Number (BBAN), up to 30 alphanumeric characters.\n * NOTE: Permitted IBAN characters are: digits [0-9] and the 26 latin alphabetic [A-Z]\n *\n * @param {string} str - string under validation\n * @param {object} options - object to pass the countries to be either whitelisted or blacklisted\n * @return {boolean}\n */\nfunction hasValidIbanFormat(str, options) {\n  // Strip white spaces and hyphens\n  const strippedStr = str.replace(/[\\s\\-]+/gi, '').toUpperCase();\n  const isoCountryCode = strippedStr.slice(0, 2).toUpperCase();\n\n  const isoCountryCodeInIbanRegexCodeObject = isoCountryCode in ibanRegexThroughCountryCode;\n\n  if (options.whitelist) {\n    if (!hasOnlyValidCountryCodes(options.whitelist)) {\n      return false;\n    }\n\n    const isoCountryCodeInWhiteList = includes(options.whitelist, isoCountryCode);\n\n    if (!isoCountryCodeInWhiteList) {\n      return false;\n    }\n  }\n\n  if (options.blacklist) {\n    const isoCountryCodeInBlackList = includes(options.blacklist, isoCountryCode);\n\n    if (isoCountryCodeInBlackList) {\n      return false;\n    }\n  }\n\n  return (isoCountryCodeInIbanRegexCodeObject) &&\n    ibanRegexThroughCountryCode[isoCountryCode].test(strippedStr);\n}\n\n/**\n   * Check whether string has valid IBAN Checksum\n   * by performing basic mod-97 operation and\n   * the remainder should equal 1\n   * -- Start by rearranging the IBAN by moving the four initial characters to the end of the string\n   * -- Replace each letter in the string with two digits, A -> 10, B = 11, Z = 35\n   * -- Interpret the string as a decimal integer and\n   * -- compute the remainder on division by 97 (mod 97)\n   * Reference: https://en.wikipedia.org/wiki/International_Bank_Account_Number\n   *\n   * @param {string} str\n   * @return {boolean}\n   */\nfunction hasValidIbanChecksum(str) {\n  const strippedStr = str.replace(/[^A-Z0-9]+/gi, '').toUpperCase(); // Keep only digits and A-Z latin alphabetic\n  const rearranged = strippedStr.slice(4) + strippedStr.slice(0, 4);\n  const alphaCapsReplacedWithDigits = rearranged.replace(/[A-Z]/g, char => char.charCodeAt(0) - 55);\n\n  const remainder = alphaCapsReplacedWithDigits.match(/\\d{1,7}/g)\n    .reduce((acc, value) => Number(acc + value) % 97, '');\n\n  return remainder === 1;\n}\n\nexport default function isIBAN(str, options = {}) {\n  assertString(str);\n\n  return hasValidIbanFormat(str, options) && hasValidIbanChecksum(str);\n}\n\nexport const locales = Object.keys(ibanRegexThroughCountryCode);\n"
  },
  {
    "path": "src/lib/isIMEI.js",
    "content": "import assertString from './util/assertString';\n\n\nlet imeiRegexWithoutHyphens = /^[0-9]{15}$/;\nlet imeiRegexWithHyphens = /^\\d{2}-\\d{6}-\\d{6}-\\d{1}$/;\n\n\nexport default function isIMEI(str, options) {\n  assertString(str);\n  options = options || {};\n\n  // default regex for checking imei is the one without hyphens\n\n  let imeiRegex = imeiRegexWithoutHyphens;\n\n  if (options.allow_hyphens) {\n    imeiRegex = imeiRegexWithHyphens;\n  }\n\n\n  if (!imeiRegex.test(str)) {\n    return false;\n  }\n\n  str = str.replace(/-/g, '');\n\n  let sum = 0,\n    mul = 2,\n    l = 14;\n\n  for (let i = 0; i < l; i++) {\n    const digit = str.substring(l - i - 1, l - i);\n    const tp = parseInt(digit, 10) * mul;\n    if (tp >= 10) {\n      sum += (tp % 10) + 1;\n    } else {\n      sum += tp;\n    }\n    if (mul === 1) {\n      mul += 1;\n    } else {\n      mul -= 1;\n    }\n  }\n  const chk = ((10 - (sum % 10)) % 10);\n  if (chk !== parseInt(str.substring(14, 15), 10)) {\n    return false;\n  }\n  return true;\n}\n"
  },
  {
    "path": "src/lib/isIP.js",
    "content": "import assertString from './util/assertString';\n/**\n11.3.  Examples\n\n   The following addresses\n\n             fe80::1234 (on the 1st link of the node)\n             ff02::5678 (on the 5th link of the node)\n             ff08::9abc (on the 10th organization of the node)\n\n   would be represented as follows:\n\n             fe80::1234%1\n             ff02::5678%5\n             ff08::9abc%10\n\n   (Here we assume a natural translation from a zone index to the\n   <zone_id> part, where the Nth zone of any scope is translated into\n   \"N\".)\n\n   If we use interface names as <zone_id>, those addresses could also be\n   represented as follows:\n\n            fe80::1234%ne0\n            ff02::5678%pvc1.3\n            ff08::9abc%interface10\n\n   where the interface \"ne0\" belongs to the 1st link, \"pvc1.3\" belongs\n   to the 5th link, and \"interface10\" belongs to the 10th organization.\n * * */\nconst IPv4SegmentFormat = '(?:[0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])';\nconst IPv4AddressFormat = `(${IPv4SegmentFormat}[.]){3}${IPv4SegmentFormat}`;\nconst IPv4AddressRegExp = new RegExp(`^${IPv4AddressFormat}$`);\n\nconst IPv6SegmentFormat = '(?:[0-9a-fA-F]{1,4})';\nconst IPv6AddressRegExp = new RegExp('^(' +\n  `(?:${IPv6SegmentFormat}:){7}(?:${IPv6SegmentFormat}|:)|` +\n  `(?:${IPv6SegmentFormat}:){6}(?:${IPv4AddressFormat}|:${IPv6SegmentFormat}|:)|` +\n  `(?:${IPv6SegmentFormat}:){5}(?::${IPv4AddressFormat}|(:${IPv6SegmentFormat}){1,2}|:)|` +\n  `(?:${IPv6SegmentFormat}:){4}(?:(:${IPv6SegmentFormat}){0,1}:${IPv4AddressFormat}|(:${IPv6SegmentFormat}){1,3}|:)|` +\n  `(?:${IPv6SegmentFormat}:){3}(?:(:${IPv6SegmentFormat}){0,2}:${IPv4AddressFormat}|(:${IPv6SegmentFormat}){1,4}|:)|` +\n  `(?:${IPv6SegmentFormat}:){2}(?:(:${IPv6SegmentFormat}){0,3}:${IPv4AddressFormat}|(:${IPv6SegmentFormat}){1,5}|:)|` +\n  `(?:${IPv6SegmentFormat}:){1}(?:(:${IPv6SegmentFormat}){0,4}:${IPv4AddressFormat}|(:${IPv6SegmentFormat}){1,6}|:)|` +\n  `(?::((?::${IPv6SegmentFormat}){0,5}:${IPv4AddressFormat}|(?::${IPv6SegmentFormat}){1,7}|:))` +\n  ')(%[0-9a-zA-Z.]{1,})?$');\n\nexport default function isIP(ipAddress, options = {}) {\n  assertString(ipAddress);\n\n  // accessing 'arguments' for backwards compatibility: isIP(ipAddress [, version])\n  // eslint-disable-next-line prefer-rest-params\n  const version = (typeof options === 'object' ? options.version : arguments[1]) || '';\n\n  if (!version) {\n    return isIP(ipAddress, { version: 4 }) || isIP(ipAddress, { version: 6 });\n  }\n\n  if (version.toString() === '4') {\n    return IPv4AddressRegExp.test(ipAddress);\n  }\n\n  if (version.toString() === '6') {\n    return IPv6AddressRegExp.test(ipAddress);\n  }\n\n  return false;\n}\n"
  },
  {
    "path": "src/lib/isIPRange.js",
    "content": "import assertString from './util/assertString';\nimport isIP from './isIP';\n\nconst subnetMaybe = /^\\d{1,3}$/;\nconst v4Subnet = 32;\nconst v6Subnet = 128;\n\nexport default function isIPRange(str, version = '') {\n  assertString(str);\n  const parts = str.split('/');\n\n  // parts[0] -> ip, parts[1] -> subnet\n  if (parts.length !== 2) {\n    return false;\n  }\n\n  if (!subnetMaybe.test(parts[1])) {\n    return false;\n  }\n\n  // Disallow preceding 0 i.e. 01, 02, ...\n  if (parts[1].length > 1 && parts[1].startsWith('0')) {\n    return false;\n  }\n\n  const isValidIP = isIP(parts[0], version);\n  if (!isValidIP) {\n    return false;\n  }\n\n  // Define valid subnet according to IP's version\n  let expectedSubnet = null;\n  switch (String(version)) {\n    case '4':\n      expectedSubnet = v4Subnet;\n      break;\n\n    case '6':\n      expectedSubnet = v6Subnet;\n      break;\n\n    default:\n      expectedSubnet = isIP(parts[0], '6') ? v6Subnet : v4Subnet;\n  }\n\n  return parts[1] <= expectedSubnet && parts[1] >= 0;\n}\n"
  },
  {
    "path": "src/lib/isISBN.js",
    "content": "import assertString from './util/assertString';\n\nconst possibleIsbn10 = /^(?:[0-9]{9}X|[0-9]{10})$/;\nconst possibleIsbn13 = /^(?:[0-9]{13})$/;\nconst factor = [1, 3];\n\nexport default function isISBN(isbn, options) {\n  assertString(isbn);\n\n  // For backwards compatibility:\n  // isISBN(str [, version]), i.e. `options` could be used as argument for the legacy `version`\n  const version = String(options?.version || options);\n\n  if (!(options?.version || options)) {\n    return isISBN(isbn, { version: 10 }) || isISBN(isbn, { version: 13 });\n  }\n\n  const sanitizedIsbn = isbn.replace(/[\\s-]+/g, '');\n\n  let checksum = 0;\n\n  if (version === '10') {\n    if (!possibleIsbn10.test(sanitizedIsbn)) {\n      return false;\n    }\n\n    for (let i = 0; i < version - 1; i++) {\n      checksum += (i + 1) * sanitizedIsbn.charAt(i);\n    }\n\n    if (sanitizedIsbn.charAt(9) === 'X') {\n      checksum += 10 * 10;\n    } else {\n      checksum += 10 * sanitizedIsbn.charAt(9);\n    }\n\n    if ((checksum % 11) === 0) {\n      return true;\n    }\n  } else if (version === '13') {\n    if (!possibleIsbn13.test(sanitizedIsbn)) {\n      return false;\n    }\n\n    for (let i = 0; i < 12; i++) {\n      checksum += factor[i % 2] * sanitizedIsbn.charAt(i);\n    }\n\n    if (sanitizedIsbn.charAt(12) - ((10 - (checksum % 10)) % 10) === 0) {\n      return true;\n    }\n  }\n\n  return false;\n}\n"
  },
  {
    "path": "src/lib/isISIN.js",
    "content": "import assertString from './util/assertString';\n\nconst isin = /^[A-Z]{2}[0-9A-Z]{9}[0-9]$/;\n\n// this link details how the check digit is calculated:\n// https://www.isin.org/isin-format/. it is a little bit\n// odd in that it works with digits, not numbers. in order\n// to make only one pass through the ISIN characters, the\n// each alpha character is handled as 2 characters within\n// the loop.\n\nexport default function isISIN(str) {\n  assertString(str);\n  if (!isin.test(str)) {\n    return false;\n  }\n\n  let double = true;\n  let sum = 0;\n  // convert values\n  for (let i = str.length - 2; i >= 0; i--) {\n    if (str[i] >= 'A' && str[i] <= 'Z') {\n      const value = str[i].charCodeAt(0) - 55;\n      const lo = value % 10;\n      const hi = Math.trunc(value / 10);\n      // letters have two digits, so handle the low order\n      // and high order digits separately.\n      for (const digit of [lo, hi]) {\n        if (double) {\n          if (digit >= 5) {\n            sum += 1 + ((digit - 5) * 2);\n          } else {\n            sum += digit * 2;\n          }\n        } else {\n          sum += digit;\n        }\n        double = !double;\n      }\n    } else {\n      const digit = str[i].charCodeAt(0) - '0'.charCodeAt(0);\n      if (double) {\n        if (digit >= 5) {\n          sum += 1 + ((digit - 5) * 2);\n        } else {\n          sum += digit * 2;\n        }\n      } else {\n        sum += digit;\n      }\n      double = !double;\n    }\n  }\n\n  const check = (Math.trunc(((sum + 9) / 10)) * 10) - sum;\n\n  return +str[str.length - 1] === check;\n}\n"
  },
  {
    "path": "src/lib/isISO15924.js",
    "content": "import assertString from './util/assertString';\n\n// from https://www.unicode.org/iso15924/iso15924-codes.html\nconst validISO15924Codes = new Set([\n  'Adlm', 'Afak', 'Aghb', 'Ahom', 'Arab', 'Aran', 'Armi', 'Armn', 'Avst',\n  'Bali', 'Bamu', 'Bass', 'Batk', 'Beng', 'Bhks', 'Blis', 'Bopo', 'Brah', 'Brai', 'Bugi', 'Buhd',\n  'Cakm', 'Cans', 'Cari', 'Cham', 'Cher', 'Chis', 'Chrs', 'Cirt', 'Copt', 'Cpmn', 'Cprt', 'Cyrl', 'Cyrs',\n  'Deva', 'Diak', 'Dogr', 'Dsrt', 'Dupl',\n  'Egyd', 'Egyh', 'Egyp', 'Elba', 'Elym', 'Ethi',\n  'Gara', 'Geok', 'Geor', 'Glag', 'Gong', 'Gonm', 'Goth', 'Gran', 'Grek', 'Gujr', 'Gukh', 'Guru',\n  'Hanb', 'Hang', 'Hani', 'Hano', 'Hans', 'Hant', 'Hatr', 'Hebr', 'Hira', 'Hluw', 'Hmng', 'Hmnp', 'Hrkt', 'Hung',\n  'Inds', 'Ital',\n  'Jamo', 'Java', 'Jpan', 'Jurc',\n  'Kali', 'Kana', 'Kawi', 'Khar', 'Khmr', 'Khoj', 'Kitl', 'Kits', 'Knda', 'Kore', 'Kpel', 'Krai', 'Kthi',\n  'Lana', 'Laoo', 'Latf', 'Latg', 'Latn', 'Leke', 'Lepc', 'Limb', 'Lina', 'Linb', 'Lisu', 'Loma', 'Lyci', 'Lydi',\n  'Mahj', 'Maka', 'Mand', 'Mani', 'Marc', 'Maya', 'Medf', 'Mend', 'Merc', 'Mero', 'Mlym', 'Modi', 'Mong', 'Moon', 'Mroo', 'Mtei', 'Mult', 'Mymr',\n  'Nagm', 'Nand', 'Narb', 'Nbat', 'Newa', 'Nkdb', 'Nkgb', 'Nkoo', 'Nshu',\n  'Ogam', 'Olck', 'Onao', 'Orkh', 'Orya', 'Osge', 'Osma', 'Ougr',\n  'Palm', 'Pauc', 'Pcun', 'Pelm', 'Perm', 'Phag', 'Phli', 'Phlp', 'Phlv', 'Phnx', 'Plrd', 'Piqd', 'Prti', 'Psin',\n  'Qaaa', 'Qaab', 'Qaac', 'Qaad', 'Qaae', 'Qaaf', 'Qaag', 'Qaah', 'Qaai', 'Qaaj', 'Qaak', 'Qaal', 'Qaam', 'Qaan', 'Qaao', 'Qaap', 'Qaaq', 'Qaar', 'Qaas', 'Qaat', 'Qaau', 'Qaav', 'Qaaw', 'Qaax', 'Qaay', 'Qaaz', 'Qaba', 'Qabb', 'Qabc', 'Qabd', 'Qabe', 'Qabf', 'Qabg', 'Qabh', 'Qabi', 'Qabj', 'Qabk', 'Qabl', 'Qabm', 'Qabn', 'Qabo', 'Qabp', 'Qabq', 'Qabr', 'Qabs', 'Qabt', 'Qabu', 'Qabv', 'Qabw', 'Qabx',\n  'Ranj', 'Rjng', 'Rohg', 'Roro', 'Runr',\n  'Samr', 'Sara', 'Sarb', 'Saur', 'Sgnw', 'Shaw', 'Shrd', 'Shui', 'Sidd', 'Sidt', 'Sind', 'Sinh', 'Sogd', 'Sogo', 'Sora', 'Soyo', 'Sund', 'Sunu', 'Sylo', 'Syrc', 'Syre', 'Syrj', 'Syrn',\n  'Tagb', 'Takr', 'Tale', 'Talu', 'Taml', 'Tang', 'Tavt', 'Tayo', 'Telu', 'Teng', 'Tfng', 'Tglg', 'Thaa', 'Thai', 'Tibt', 'Tirh', 'Tnsa', 'Todr', 'Tols', 'Toto', 'Tutg',\n  'Ugar',\n  'Vaii', 'Visp', 'Vith',\n  'Wara', 'Wcho', 'Wole',\n  'Xpeo', 'Xsux',\n  'Yezi', 'Yiii',\n  'Zanb', 'Zinh', 'Zmth', 'Zsye', 'Zsym', 'Zxxx', 'Zyyy', 'Zzzz',\n]);\n\nexport default function isISO15924(str) {\n  assertString(str);\n  return validISO15924Codes.has(str);\n}\n\nexport const ScriptCodes = validISO15924Codes;\n"
  },
  {
    "path": "src/lib/isISO31661Alpha2.js",
    "content": "import assertString from './util/assertString';\n\n// from https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2\nconst validISO31661Alpha2CountriesCodes = new Set([\n  'AD', 'AE', 'AF', 'AG', 'AI', 'AL', 'AM', 'AO', 'AQ', 'AR', 'AS', 'AT', 'AU', 'AW', 'AX', 'AZ',\n  'BA', 'BB', 'BD', 'BE', 'BF', 'BG', 'BH', 'BI', 'BJ', 'BL', 'BM', 'BN', 'BO', 'BQ', 'BR', 'BS', 'BT', 'BV', 'BW', 'BY', 'BZ',\n  'CA', 'CC', 'CD', 'CF', 'CG', 'CH', 'CI', 'CK', 'CL', 'CM', 'CN', 'CO', 'CR', 'CU', 'CV', 'CW', 'CX', 'CY', 'CZ',\n  'DE', 'DJ', 'DK', 'DM', 'DO', 'DZ',\n  'EC', 'EE', 'EG', 'EH', 'ER', 'ES', 'ET',\n  'FI', 'FJ', 'FK', 'FM', 'FO', 'FR',\n  'GA', 'GB', 'GD', 'GE', 'GF', 'GG', 'GH', 'GI', 'GL', 'GM', 'GN', 'GP', 'GQ', 'GR', 'GS', 'GT', 'GU', 'GW', 'GY',\n  'HK', 'HM', 'HN', 'HR', 'HT', 'HU',\n  'ID', 'IE', 'IL', 'IM', 'IN', 'IO', 'IQ', 'IR', 'IS', 'IT',\n  'JE', 'JM', 'JO', 'JP',\n  'KE', 'KG', 'KH', 'KI', 'KM', 'KN', 'KP', 'KR', 'KW', 'KY', 'KZ',\n  'LA', 'LB', 'LC', 'LI', 'LK', 'LR', 'LS', 'LT', 'LU', 'LV', 'LY',\n  'MA', 'MC', 'MD', 'ME', 'MF', 'MG', 'MH', 'MK', 'ML', 'MM', 'MN', 'MO', 'MP', 'MQ', 'MR', 'MS', 'MT', 'MU', 'MV', 'MW', 'MX', 'MY', 'MZ',\n  'NA', 'NC', 'NE', 'NF', 'NG', 'NI', 'NL', 'NO', 'NP', 'NR', 'NU', 'NZ',\n  'OM',\n  'PA', 'PE', 'PF', 'PG', 'PH', 'PK', 'PL', 'PM', 'PN', 'PR', 'PS', 'PT', 'PW', 'PY',\n  'QA',\n  'RE', 'RO', 'RS', 'RU', 'RW',\n  'SA', 'SB', 'SC', 'SD', 'SE', 'SG', 'SH', 'SI', 'SJ', 'SK', 'SL', 'SM', 'SN', 'SO', 'SR', 'SS', 'ST', 'SV', 'SX', 'SY', 'SZ',\n  'TC', 'TD', 'TF', 'TG', 'TH', 'TJ', 'TK', 'TL', 'TM', 'TN', 'TO', 'TR', 'TT', 'TV', 'TW', 'TZ',\n  'UA', 'UG', 'UM', 'US', 'UY', 'UZ',\n  'VA', 'VC', 'VE', 'VG', 'VI', 'VN', 'VU',\n  'WF', 'WS',\n  'YE', 'YT',\n  'ZA', 'ZM', 'ZW',\n]);\n\nconst alpha2CountryCode = /^[a-zA-Z]{2}$/;\n\nexport default function isISO31661Alpha2(str, options = {}) {\n  assertString(str);\n\n  const { userAssignedCodes } = options;\n  const validUserAssignedCodes = (userAssignedCodes || [])\n    .reduce((accumulator, userAssignedCode) => {\n      if (alpha2CountryCode.test(userAssignedCode)) {\n        accumulator.push(userAssignedCode.toUpperCase());\n      }\n      return accumulator;\n    }, []);\n\n  if (validUserAssignedCodes.includes(str.toUpperCase())) {\n    return true;\n  }\n\n  return validISO31661Alpha2CountriesCodes.has(str.toUpperCase());\n}\n\nexport const CountryCodes = validISO31661Alpha2CountriesCodes;\n"
  },
  {
    "path": "src/lib/isISO31661Alpha3.js",
    "content": "import assertString from './util/assertString';\n\n// from https://en.wikipedia.org/wiki/ISO_3166-1_alpha-3\nconst validISO31661Alpha3CountriesCodes = new Set([\n  'AFG', 'ALA', 'ALB', 'DZA', 'ASM', 'AND', 'AGO', 'AIA', 'ATA', 'ATG', 'ARG', 'ARM', 'ABW', 'AUS', 'AUT', 'AZE',\n  'BHS', 'BHR', 'BGD', 'BRB', 'BLR', 'BEL', 'BLZ', 'BEN', 'BMU', 'BTN', 'BOL', 'BES', 'BIH', 'BWA', 'BVT', 'BRA',\n  'IOT', 'BRN', 'BGR', 'BFA', 'BDI', 'KHM', 'CMR', 'CAN', 'CPV', 'CYM', 'CAF', 'TCD', 'CHL', 'CHN', 'CXR', 'CCK',\n  'COL', 'COM', 'COG', 'COD', 'COK', 'CRI', 'CIV', 'HRV', 'CUB', 'CUW', 'CYP', 'CZE', 'DNK', 'DJI', 'DMA', 'DOM',\n  'ECU', 'EGY', 'SLV', 'GNQ', 'ERI', 'EST', 'ETH', 'FLK', 'FRO', 'FJI', 'FIN', 'FRA', 'GUF', 'PYF', 'ATF', 'GAB',\n  'GMB', 'GEO', 'DEU', 'GHA', 'GIB', 'GRC', 'GRL', 'GRD', 'GLP', 'GUM', 'GTM', 'GGY', 'GIN', 'GNB', 'GUY', 'HTI',\n  'HMD', 'VAT', 'HND', 'HKG', 'HUN', 'ISL', 'IND', 'IDN', 'IRN', 'IRQ', 'IRL', 'IMN', 'ISR', 'ITA', 'JAM', 'JPN',\n  'JEY', 'JOR', 'KAZ', 'KEN', 'KIR', 'PRK', 'KOR', 'KWT', 'KGZ', 'LAO', 'LVA', 'LBN', 'LSO', 'LBR', 'LBY', 'LIE',\n  'LTU', 'LUX', 'MAC', 'MKD', 'MDG', 'MWI', 'MYS', 'MDV', 'MLI', 'MLT', 'MHL', 'MTQ', 'MRT', 'MUS', 'MYT', 'MEX',\n  'FSM', 'MDA', 'MCO', 'MNG', 'MNE', 'MSR', 'MAR', 'MOZ', 'MMR', 'NAM', 'NRU', 'NPL', 'NLD', 'NCL', 'NZL', 'NIC',\n  'NER', 'NGA', 'NIU', 'NFK', 'MNP', 'NOR', 'OMN', 'PAK', 'PLW', 'PSE', 'PAN', 'PNG', 'PRY', 'PER', 'PHL', 'PCN',\n  'POL', 'PRT', 'PRI', 'QAT', 'REU', 'ROU', 'RUS', 'RWA', 'BLM', 'SHN', 'KNA', 'LCA', 'MAF', 'SPM', 'VCT', 'WSM',\n  'SMR', 'STP', 'SAU', 'SEN', 'SRB', 'SYC', 'SLE', 'SGP', 'SXM', 'SVK', 'SVN', 'SLB', 'SOM', 'ZAF', 'SGS', 'SSD',\n  'ESP', 'LKA', 'SDN', 'SUR', 'SJM', 'SWZ', 'SWE', 'CHE', 'SYR', 'TWN', 'TJK', 'TZA', 'THA', 'TLS', 'TGO', 'TKL',\n  'TON', 'TTO', 'TUN', 'TUR', 'TKM', 'TCA', 'TUV', 'UGA', 'UKR', 'ARE', 'GBR', 'USA', 'UMI', 'URY', 'UZB', 'VUT',\n  'VEN', 'VNM', 'VGB', 'VIR', 'WLF', 'ESH', 'YEM', 'ZMB', 'ZWE',\n]);\n\nconst alpha3CountryCode = /^[a-zA-Z]{3}$/;\n\nexport default function isISO31661Alpha3(str, options = {}) {\n  assertString(str);\n\n  const { userAssignedCodes } = options;\n  const validUserAssignedCodes = (userAssignedCodes || [])\n    .reduce((accumulator, userAssignedCode) => {\n      if (alpha3CountryCode.test(userAssignedCode)) {\n        accumulator.push(userAssignedCode.toUpperCase());\n      }\n      return accumulator;\n    }, []);\n\n  if (validUserAssignedCodes.includes(str.toUpperCase())) {\n    return true;\n  }\n\n  return validISO31661Alpha3CountriesCodes.has(str.toUpperCase());\n}\n"
  },
  {
    "path": "src/lib/isISO31661Numeric.js",
    "content": "import assertString from './util/assertString';\n\n// from https://en.wikipedia.org/wiki/ISO_3166-1_numeric\nconst validISO31661NumericCountriesCodes = new Set([\n  '004', '008', '010', '012', '016', '020', '024', '028', '031', '032', '036', '040', '044', '048', '050', '051',\n  '052', '056', '060', '064', '068', '070', '072', '074', '076', '084', '086', '090', '092', '096', '100', '104',\n  '108', '112', '116', '120', '124', '132', '136', '140', '144', '148', '152', '156', '158', '162', '166', '170',\n  '174', '175', '178', '180', '184', '188', '191', '192', '196', '203', '204', '208', '212', '214', '218', '222',\n  '226', '231', '232', '233', '234', '238', '239', '242', '246', '248', '250', '254', '258', '260', '262', '266',\n  '268', '270', '275', '276', '288', '292', '296', '300', '304', '308', '312', '316', '320', '324', '328', '332',\n  '334', '336', '340', '344', '348', '352', '356', '360', '364', '368', '372', '376', '380', '384', '388', '392',\n  '398', '400', '404', '408', '410', '414', '417', '418', '422', '426', '428', '430', '434', '438', '440', '442',\n  '446', '450', '454', '458', '462', '466', '470', '474', '478', '480', '484', '492', '496', '498', '499', '500',\n  '504', '508', '512', '516', '520', '524', '528', '531', '533', '534', '535', '540', '548', '554', '558', '562',\n  '566', '570', '574', '578', '580', '581', '583', '584', '585', '586', '591', '598', '600', '604', '608', '612',\n  '616', '620', '624', '626', '630', '634', '638', '642', '643', '646', '652', '654', '659', '660', '662', '663',\n  '666', '670', '674', '678', '682', '686', '688', '690', '694', '702', '703', '704', '705', '706', '710', '716',\n  '724', '728', '729', '732', '740', '744', '748', '752', '756', '760', '762', '764', '768', '772', '776', '780',\n  '784', '788', '792', '795', '796', '798', '800', '804', '807', '818', '826', '831', '832', '833', '834', '840',\n  '850', '854', '858', '860', '862', '876', '882', '887', '894',\n]);\n\nexport default function isISO31661Numeric(str) {\n  assertString(str);\n  return validISO31661NumericCountriesCodes.has(str);\n}\n"
  },
  {
    "path": "src/lib/isISO4217.js",
    "content": "import assertString from './util/assertString';\n\n// from https://en.wikipedia.org/wiki/ISO_4217\nconst validISO4217CurrencyCodes = new Set([\n  'AED', 'AFN', 'ALL', 'AMD', 'ANG', 'AOA', 'ARS', 'AUD', 'AWG', 'AZN',\n  'BAM', 'BBD', 'BDT', 'BGN', 'BHD', 'BIF', 'BMD', 'BND', 'BOB', 'BOV', 'BRL', 'BSD', 'BTN', 'BWP', 'BYN', 'BZD',\n  'CAD', 'CDF', 'CHE', 'CHF', 'CHW', 'CLF', 'CLP', 'CNY', 'COP', 'COU', 'CRC', 'CUP', 'CVE', 'CZK',\n  'DJF', 'DKK', 'DOP', 'DZD',\n  'EGP', 'ERN', 'ETB', 'EUR',\n  'FJD', 'FKP',\n  'GBP', 'GEL', 'GHS', 'GIP', 'GMD', 'GNF', 'GTQ', 'GYD',\n  'HKD', 'HNL', 'HTG', 'HUF',\n  'IDR', 'ILS', 'INR', 'IQD', 'IRR', 'ISK',\n  'JMD', 'JOD', 'JPY',\n  'KES', 'KGS', 'KHR', 'KMF', 'KPW', 'KRW', 'KWD', 'KYD', 'KZT',\n  'LAK', 'LBP', 'LKR', 'LRD', 'LSL', 'LYD',\n  'MAD', 'MDL', 'MGA', 'MKD', 'MMK', 'MNT', 'MOP', 'MRU', 'MUR', 'MVR', 'MWK', 'MXN', 'MXV', 'MYR', 'MZN',\n  'NAD', 'NGN', 'NIO', 'NOK', 'NPR', 'NZD',\n  'OMR',\n  'PAB', 'PEN', 'PGK', 'PHP', 'PKR', 'PLN', 'PYG',\n  'QAR',\n  'RON', 'RSD', 'RUB', 'RWF',\n  'SAR', 'SBD', 'SCR', 'SDG', 'SEK', 'SGD', 'SHP', 'SLE', 'SLL', 'SOS', 'SRD', 'SSP', 'STN', 'SVC', 'SYP', 'SZL',\n  'THB', 'TJS', 'TMT', 'TND', 'TOP', 'TRY', 'TTD', 'TWD', 'TZS',\n  'UAH', 'UGX', 'USD', 'USN', 'UYI', 'UYU', 'UYW', 'UZS',\n  'VED', 'VES', 'VND', 'VUV',\n  'WST',\n  'XAF', 'XAG', 'XAU', 'XBA', 'XBB', 'XBC', 'XBD', 'XCD', 'XDR', 'XOF', 'XPD', 'XPF', 'XPT', 'XSU', 'XTS', 'XUA', 'XXX',\n  'YER',\n  'ZAR', 'ZMW', 'ZWL',\n]);\n\nexport default function isISO4217(str) {\n  assertString(str);\n  return validISO4217CurrencyCodes.has(str.toUpperCase());\n}\n\nexport const CurrencyCodes = validISO4217CurrencyCodes;\n"
  },
  {
    "path": "src/lib/isISO6346.js",
    "content": "import assertString from './util/assertString';\n\n// https://en.wikipedia.org/wiki/ISO_6346\n// according to ISO6346 standard, checksum digit is mandatory for freight container but recommended\n// for other container types (J and Z)\nconst isISO6346Str = /^[A-Z]{3}(U[0-9]{7})|([J,Z][0-9]{6,7})$/;\nconst isDigit = /^[0-9]$/;\n\nexport function isISO6346(str) {\n  assertString(str);\n\n  str = str.toUpperCase();\n\n  if (!isISO6346Str.test(str)) return false;\n\n  if (str.length === 11) {\n    let sum = 0;\n    for (let i = 0; i < str.length - 1; i++) {\n      if (!isDigit.test(str[i])) {\n        let convertedCode;\n        const letterCode = str.charCodeAt(i) - 55;\n        if (letterCode < 11) convertedCode = letterCode;\n        else if (letterCode >= 11 && letterCode <= 20) convertedCode = 12 + (letterCode % 11);\n        else if (letterCode >= 21 && letterCode <= 30) convertedCode = 23 + (letterCode % 21);\n        else convertedCode = 34 + (letterCode % 31);\n        sum += convertedCode * (2 ** i);\n      } else sum += str[i] * (2 ** i);\n    }\n\n    let checkSumDigit = sum % 11;\n    if (checkSumDigit === 10) checkSumDigit = 0;\n    return Number(str[str.length - 1]) === checkSumDigit;\n  }\n\n  return true;\n}\n\nexport const isFreightContainerID = isISO6346;\n"
  },
  {
    "path": "src/lib/isISO6391.js",
    "content": "import assertString from './util/assertString';\n\nconst isISO6391Set = new Set([\n  'aa', 'ab', 'ae', 'af', 'ak', 'am', 'an', 'ar', 'as', 'av', 'ay', 'az', 'az',\n  'ba', 'be', 'bg', 'bh', 'bi', 'bm', 'bn', 'bo', 'br', 'bs',\n  'ca', 'ce', 'ch', 'co', 'cr', 'cs', 'cu', 'cv', 'cy',\n  'da', 'de', 'dv', 'dz',\n  'ee', 'el', 'en', 'eo', 'es', 'et', 'eu',\n  'fa', 'ff', 'fi', 'fj', 'fo', 'fr', 'fy',\n  'ga', 'gd', 'gl', 'gn', 'gu', 'gv',\n  'ha', 'he', 'hi', 'ho', 'hr', 'ht', 'hu', 'hy', 'hz',\n  'ia', 'id', 'ie', 'ig', 'ii', 'ik', 'io', 'is', 'it', 'iu',\n  'ja', 'jv',\n  'ka', 'kg', 'ki', 'kj', 'kk', 'kl', 'km', 'kn', 'ko', 'kr', 'ks', 'ku', 'kv', 'kw', 'ky',\n  'la', 'lb', 'lg', 'li', 'ln', 'lo', 'lt', 'lu', 'lv',\n  'mg', 'mh', 'mi', 'mk', 'ml', 'mn', 'mr', 'ms', 'mt', 'my',\n  'na', 'nb', 'nd', 'ne', 'ng', 'nl', 'nn', 'no', 'nr', 'nv', 'ny',\n  'oc', 'oj', 'om', 'or', 'os',\n  'pa', 'pi', 'pl', 'ps', 'pt',\n  'qu',\n  'rm', 'rn', 'ro', 'ru', 'rw',\n  'sa', 'sc', 'sd', 'se', 'sg', 'si', 'sk', 'sl', 'sm', 'sn', 'so', 'sq', 'sr', 'ss', 'st', 'su', 'sv', 'sw',\n  'ta', 'te', 'tg', 'th', 'ti', 'tk', 'tl', 'tn', 'to', 'tr', 'ts', 'tt', 'tw', 'ty',\n  'ug', 'uk', 'ur', 'uz',\n  've', 'vi', 'vo',\n  'wa', 'wo',\n  'xh',\n  'yi', 'yo',\n  'za', 'zh', 'zu',\n]);\n\nexport default function isISO6391(str) {\n  assertString(str);\n  return isISO6391Set.has(str);\n}\n"
  },
  {
    "path": "src/lib/isISO8601.js",
    "content": "import assertString from './util/assertString';\n\n/* eslint-disable max-len */\n// from http://goo.gl/0ejHHW\nconst iso8601 = /^([\\+-]?\\d{4}(?!\\d{2}\\b))((-?)((0[1-9]|1[0-2])(\\3([12]\\d|0[1-9]|3[01]))?|W([0-4]\\d|5[0-3])(-?[1-7])?|(00[1-9]|0[1-9]\\d|[12]\\d{2}|3([0-5]\\d|6[1-6])))([T\\s]((([01]\\d|2[0-3])((:?)[0-5]\\d)?|24:?00)([\\.,]\\d+(?!:))?)?(\\17[0-5]\\d([\\.,]\\d+)?)?([zZ]|([\\+-])([01]\\d|2[0-3]):?([0-5]\\d)?)?)?)?$/;\n// same as above, except with a strict 'T' separator between date and time\nconst iso8601StrictSeparator = /^([\\+-]?\\d{4}(?!\\d{2}\\b))((-?)((0[1-9]|1[0-2])(\\3([12]\\d|0[1-9]|3[01]))?|W([0-4]\\d|5[0-3])(-?[1-7])?|(00[1-9]|0[1-9]\\d|[12]\\d{2}|3([0-5]\\d|6[1-6])))([T]((([01]\\d|2[0-3])((:?)[0-5]\\d)?|24:?00)([\\.,]\\d+(?!:))?)?(\\17[0-5]\\d([\\.,]\\d+)?)?([zZ]|([\\+-])([01]\\d|2[0-3]):?([0-5]\\d)?)?)?)?$/;\n/* eslint-enable max-len */\nconst isValidDate = (str) => {\n  // str must have passed the ISO8601 check\n  // this check is meant to catch invalid dates\n  // like 2009-02-31\n  // first check for ordinal dates\n  const ordinalMatch = str.match(/^(\\d{4})-?(\\d{3})([ T]{1}\\.*|$)/);\n  if (ordinalMatch) {\n    const oYear = Number(ordinalMatch[1]);\n    const oDay = Number(ordinalMatch[2]);\n    // if is leap year\n    if ((oYear % 4 === 0 && oYear % 100 !== 0) || oYear % 400 === 0) return oDay <= 366;\n    return oDay <= 365;\n  }\n  const match = str.match(/(\\d{4})-?(\\d{0,2})-?(\\d*)/).map(Number);\n  const year = match[1];\n  const month = match[2];\n  const day = match[3];\n  const monthString = month ? `0${month}`.slice(-2) : month;\n  const dayString = day ? `0${day}`.slice(-2) : day;\n\n  // create a date object and compare\n  const d = new Date(`${year}-${monthString || '01'}-${dayString || '01'}`);\n  if (month && day) {\n    return d.getUTCFullYear() === year\n      && (d.getUTCMonth() + 1) === month\n      && d.getUTCDate() === day;\n  }\n  return true;\n};\n\nexport default function isISO8601(str, options = {}) {\n  assertString(str);\n  const check = options.strictSeparator ? iso8601StrictSeparator.test(str) : iso8601.test(str);\n  if (check && options.strict) return isValidDate(str);\n  return check;\n}\n"
  },
  {
    "path": "src/lib/isISRC.js",
    "content": "import assertString from './util/assertString';\n\n// see http://isrc.ifpi.org/en/isrc-standard/code-syntax\nconst isrc = /^[A-Z]{2}[0-9A-Z]{3}\\d{2}\\d{5}$/;\n\nexport default function isISRC(str) {\n  assertString(str);\n  return isrc.test(str);\n}\n"
  },
  {
    "path": "src/lib/isISSN.js",
    "content": "import assertString from './util/assertString';\n\nconst issn = '^\\\\d{4}-?\\\\d{3}[\\\\dX]$';\n\nexport default function isISSN(str, options = {}) {\n  assertString(str);\n  let testIssn = issn;\n  testIssn = options.require_hyphen ? testIssn.replace('?', '') : testIssn;\n  testIssn = options.case_sensitive ? new RegExp(testIssn) : new RegExp(testIssn, 'i');\n  if (!testIssn.test(str)) {\n    return false;\n  }\n  const digits = str.replace('-', '').toUpperCase();\n  let checksum = 0;\n  for (let i = 0; i < digits.length; i++) {\n    const digit = digits[i];\n    checksum += (digit === 'X' ? 10 : +digit) * (8 - i);\n  }\n  return checksum % 11 === 0;\n}\n"
  },
  {
    "path": "src/lib/isIdentityCard.js",
    "content": "import assertString from './util/assertString';\nimport includes from './util/includesArray';\nimport isInt from './isInt';\n\nconst validators = {\n  PL: (str) => {\n    assertString(str);\n\n    const weightOfDigits = {\n      1: 1,\n      2: 3,\n      3: 7,\n      4: 9,\n      5: 1,\n      6: 3,\n      7: 7,\n      8: 9,\n      9: 1,\n      10: 3,\n      11: 0,\n    };\n\n    if (str != null && str.length === 11 && isInt(str, { allow_leading_zeroes: true })) {\n      const digits = str.split('').slice(0, -1);\n      const sum = digits.reduce((acc, digit, index) =>\n        acc + (Number(digit) * weightOfDigits[index + 1]), 0);\n\n      const modulo = sum % 10;\n      const lastDigit = Number(str.charAt(str.length - 1));\n\n      if ((modulo === 0 && lastDigit === 0) || lastDigit === 10 - modulo) {\n        return true;\n      }\n    }\n\n    return false;\n  },\n  ES: (str) => {\n    assertString(str);\n\n    const DNI = /^[0-9X-Z][0-9]{7}[TRWAGMYFPDXBNJZSQVHLCKE]$/;\n\n    const charsValue = {\n      X: 0,\n      Y: 1,\n      Z: 2,\n    };\n\n    const controlDigits = [\n      'T', 'R', 'W', 'A', 'G', 'M', 'Y', 'F', 'P', 'D', 'X', 'B',\n      'N', 'J', 'Z', 'S', 'Q', 'V', 'H', 'L', 'C', 'K', 'E',\n    ];\n\n    // sanitize user input\n    const sanitized = str.trim().toUpperCase();\n\n    // validate the data structure\n    if (!DNI.test(sanitized)) {\n      return false;\n    }\n\n    // validate the control digit\n    const number = sanitized.slice(0, -1).replace(/[X,Y,Z]/g, char => charsValue[char]);\n\n    return sanitized.endsWith(controlDigits[number % 23]);\n  },\n  FI: (str) => {\n    // https://dvv.fi/en/personal-identity-code#:~:text=control%20character%20for%20a-,personal,-identity%20code%20calculated\n    assertString(str);\n\n    if (str.length !== 11) {\n      return false;\n    }\n\n    if (!str.match(/^\\d{6}[\\-A\\+]\\d{3}[0-9ABCDEFHJKLMNPRSTUVWXY]{1}$/)) {\n      return false;\n    }\n\n    const checkDigits = '0123456789ABCDEFHJKLMNPRSTUVWXY';\n\n    const idAsNumber = (parseInt(str.slice(0, 6), 10) * 1000) + parseInt(str.slice(7, 10), 10);\n    const remainder = idAsNumber % 31;\n    const checkDigit = checkDigits[remainder];\n\n    return checkDigit === str.slice(10, 11);\n  },\n  IN: (str) => {\n    const DNI = /^[1-9]\\d{3}\\s?\\d{4}\\s?\\d{4}$/;\n\n    // multiplication table\n    const d = [\n      [0, 1, 2, 3, 4, 5, 6, 7, 8, 9],\n      [1, 2, 3, 4, 0, 6, 7, 8, 9, 5],\n      [2, 3, 4, 0, 1, 7, 8, 9, 5, 6],\n      [3, 4, 0, 1, 2, 8, 9, 5, 6, 7],\n      [4, 0, 1, 2, 3, 9, 5, 6, 7, 8],\n      [5, 9, 8, 7, 6, 0, 4, 3, 2, 1],\n      [6, 5, 9, 8, 7, 1, 0, 4, 3, 2],\n      [7, 6, 5, 9, 8, 2, 1, 0, 4, 3],\n      [8, 7, 6, 5, 9, 3, 2, 1, 0, 4],\n      [9, 8, 7, 6, 5, 4, 3, 2, 1, 0],\n    ];\n\n    // permutation table\n    const p = [\n      [0, 1, 2, 3, 4, 5, 6, 7, 8, 9],\n      [1, 5, 7, 6, 2, 8, 3, 0, 9, 4],\n      [5, 8, 0, 3, 7, 9, 6, 1, 4, 2],\n      [8, 9, 1, 6, 0, 4, 3, 5, 2, 7],\n      [9, 4, 5, 3, 1, 2, 6, 8, 7, 0],\n      [4, 2, 8, 6, 5, 7, 3, 9, 0, 1],\n      [2, 7, 9, 3, 8, 0, 6, 4, 1, 5],\n      [7, 0, 4, 6, 9, 1, 3, 2, 5, 8],\n    ];\n\n    // sanitize user input\n    const sanitized = str.trim();\n\n    // validate the data structure\n    if (!DNI.test(sanitized)) {\n      return false;\n    }\n    let c = 0;\n    let invertedArray = sanitized.replace(/\\s/g, '').split('').map(Number).reverse();\n\n    invertedArray.forEach((val, i) => {\n      c = d[c][p[(i % 8)][val]];\n    });\n\n    return c === 0;\n  },\n  IR: (str) => {\n    if (!str.match(/^\\d{10}$/)) return false;\n    str = (`0000${str}`).slice(str.length - 6);\n\n    if (parseInt(str.slice(3, 9), 10) === 0) return false;\n\n    const lastNumber = parseInt(str.slice(9, 10), 10);\n    let sum = 0;\n\n    for (let i = 0; i < 9; i++) {\n      sum += parseInt(str.slice(i, i + 1), 10) * (10 - i);\n    }\n\n    sum %= 11;\n\n    return (\n      (sum < 2 && lastNumber === sum) || (sum >= 2 && lastNumber === 11 - sum)\n    );\n  },\n  IT: function IT(str) {\n    if (str.length !== 9) return false;\n    if (str === 'CA00000AA') return false; // https://it.wikipedia.org/wiki/Carta_d%27identit%C3%A0_elettronica_italiana\n    return str.search(/C[A-Z]\\d{5}[A-Z]{2}/is) > -1;\n  },\n  NO: (str) => {\n    const sanitized = str.trim();\n    if (isNaN(Number(sanitized))) return false;\n    if (sanitized.length !== 11) return false;\n    if (sanitized === '00000000000') return false;\n\n    // https://no.wikipedia.org/wiki/F%C3%B8dselsnummer\n    const f = sanitized.split('').map(Number);\n    let k1 = (11 - (((3 * f[0]) + (7 * f[1]) + (6 * f[2])\n      + (1 * f[3]) + (8 * f[4]) + (9 * f[5]) + (4 * f[6])\n      + (5 * f[7]) + (2 * f[8])) % 11)) % 11;\n    let k2 = (11 - (((5 * f[0]) + (4 * f[1]) + (3 * f[2])\n      + (2 * f[3]) + (7 * f[4]) + (6 * f[5]) + (5 * f[6])\n      + (4 * f[7]) + (3 * f[8]) + (2 * k1)) % 11)) % 11;\n\n    if (k1 !== f[9] || k2 !== f[10]) return false;\n    return true;\n  },\n  TH: (str) => {\n    if (!str.match(/^[1-8]\\d{12}$/)) return false;\n\n    // validate check digit\n    let sum = 0;\n    for (let i = 0; i < 12; i++) {\n      sum += parseInt(str[i], 10) * (13 - i);\n    }\n    return str[12] === ((11 - (sum % 11)) % 10).toString();\n  },\n  LK: (str) => {\n    const old_nic = /^[1-9]\\d{8}[vx]$/i;\n    const new_nic = /^[1-9]\\d{11}$/i;\n\n    if (str.length === 10 && old_nic.test(str)) return true;\n    else if (str.length === 12 && new_nic.test(str)) return true;\n    return false;\n  },\n  'he-IL': (str) => {\n    const DNI = /^\\d{9}$/;\n\n    // sanitize user input\n    const sanitized = str.trim();\n\n    // validate the data structure\n    if (!DNI.test(sanitized)) {\n      return false;\n    }\n\n    const id = sanitized;\n\n    let sum = 0,\n      incNum;\n    for (let i = 0; i < id.length; i++) {\n      incNum = Number(id[i]) * ((i % 2) + 1); // Multiply number by 1 or 2\n      sum += incNum > 9 ? incNum - 9 : incNum; // Sum the digits up and add to total\n    }\n    return sum % 10 === 0;\n  },\n  'ar-LY': (str) => {\n    // Libya National Identity Number NIN is 12 digits, the first digit is either 1 or 2\n    const NIN = /^(1|2)\\d{11}$/;\n\n    // sanitize user input\n    const sanitized = str.trim();\n\n    // validate the data structure\n    if (!NIN.test(sanitized)) {\n      return false;\n    }\n    return true;\n  },\n  'ar-TN': (str) => {\n    const DNI = /^\\d{8}$/;\n\n    // sanitize user input\n    const sanitized = str.trim();\n\n    // validate the data structure\n    if (!DNI.test(sanitized)) {\n      return false;\n    }\n    return true;\n  },\n  'zh-CN': (str) => {\n    const provincesAndCities = [\n      '11', // 北京\n      '12', // 天津\n      '13', // 河北\n      '14', // 山西\n      '15', // 内蒙古\n      '21', // 辽宁\n      '22', // 吉林\n      '23', // 黑龙江\n      '31', // 上海\n      '32', // 江苏\n      '33', // 浙江\n      '34', // 安徽\n      '35', // 福建\n      '36', // 江西\n      '37', // 山东\n      '41', // 河南\n      '42', // 湖北\n      '43', // 湖南\n      '44', // 广东\n      '45', // 广西\n      '46', // 海南\n      '50', // 重庆\n      '51', // 四川\n      '52', // 贵州\n      '53', // 云南\n      '54', // 西藏\n      '61', // 陕西\n      '62', // 甘肃\n      '63', // 青海\n      '64', // 宁夏\n      '65', // 新疆\n      '71', // 台湾\n      '81', // 香港\n      '82', // 澳门\n      '91', // 国外\n    ];\n\n    const powers = ['7', '9', '10', '5', '8', '4', '2', '1', '6', '3', '7', '9', '10', '5', '8', '4', '2'];\n\n    const parityBit = ['1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2'];\n\n    const checkAddressCode = addressCode => includes(provincesAndCities, addressCode);\n\n    const checkBirthDayCode = (birDayCode) => {\n      const yyyy = parseInt(birDayCode.substring(0, 4), 10);\n      const mm = parseInt(birDayCode.substring(4, 6), 10);\n      const dd = parseInt(birDayCode.substring(6), 10);\n      const xdata = new Date(yyyy, mm - 1, dd);\n      if (xdata > new Date()) {\n        return false;\n        // eslint-disable-next-line max-len\n      } else if ((xdata.getFullYear() === yyyy) && (xdata.getMonth() === mm - 1) && (xdata.getDate() === dd)) {\n        return true;\n      }\n      return false;\n    };\n\n    const getParityBit = (idCardNo) => {\n      let id17 = idCardNo.substring(0, 17);\n\n      let power = 0;\n      for (let i = 0; i < 17; i++) {\n        power += parseInt(id17.charAt(i), 10) * parseInt(powers[i], 10);\n      }\n\n      let mod = power % 11;\n      return parityBit[mod];\n    };\n\n    const checkParityBit = idCardNo => getParityBit(idCardNo) === idCardNo.charAt(17).toUpperCase();\n\n\n    const check15IdCardNo = (idCardNo) => {\n      let check = /^[1-9]\\d{7}((0[1-9])|(1[0-2]))((0[1-9])|([1-2][0-9])|(3[0-1]))\\d{3}$/.test(idCardNo);\n      if (!check) return false;\n      let addressCode = idCardNo.substring(0, 2);\n      check = checkAddressCode(addressCode);\n      if (!check) return false;\n      let birDayCode = `19${idCardNo.substring(6, 12)}`;\n      check = checkBirthDayCode(birDayCode);\n      if (!check) return false;\n      return true;\n    };\n\n    const check18IdCardNo = (idCardNo) => {\n      let check = /^[1-9]\\d{5}[1-9]\\d{3}((0[1-9])|(1[0-2]))((0[1-9])|([1-2][0-9])|(3[0-1]))\\d{3}(\\d|x|X)$/.test(idCardNo);\n      if (!check) return false;\n      let addressCode = idCardNo.substring(0, 2);\n      check = checkAddressCode(addressCode);\n      if (!check) return false;\n      let birDayCode = idCardNo.substring(6, 14);\n      check = checkBirthDayCode(birDayCode);\n      if (!check) return false;\n      return checkParityBit(idCardNo);\n    };\n\n    const checkIdCardNo = (idCardNo) => {\n      let check = /^\\d{15}|(\\d{17}(\\d|x|X))$/.test(idCardNo);\n      if (!check) return false;\n      if (idCardNo.length === 15) {\n        return check15IdCardNo(idCardNo);\n      }\n      return check18IdCardNo(idCardNo);\n    };\n    return checkIdCardNo(str);\n  },\n  'zh-HK': (str) => {\n    // sanitize user input\n    str = str.trim();\n\n    // HKID number starts with 1 or 2 letters, followed by 6 digits,\n    // then a checksum contained in square / round brackets or nothing\n    const regexHKID = /^[A-Z]{1,2}[0-9]{6}((\\([0-9A]\\))|(\\[[0-9A]\\])|([0-9A]))$/;\n    const regexIsDigit = /^[0-9]$/;\n\n    // convert the user input to all uppercase and apply regex\n    str = str.toUpperCase();\n    if (!regexHKID.test(str)) return false;\n    str = str.replace(/\\[|\\]|\\(|\\)/g, '');\n\n    if (str.length === 8) str = `3${str}`;\n    let checkSumVal = 0;\n    for (let i = 0; i <= 7; i++) {\n      let convertedChar;\n      if (!regexIsDigit.test(str[i])) convertedChar = (str[i].charCodeAt(0) - 55) % 11;\n      else convertedChar = str[i];\n      checkSumVal += (convertedChar * (9 - i));\n    }\n    checkSumVal %= 11;\n\n    let checkSumConverted;\n    if (checkSumVal === 0) checkSumConverted = '0';\n    else if (checkSumVal === 1) checkSumConverted = 'A';\n    else checkSumConverted = String(11 - checkSumVal);\n    if (checkSumConverted === str[str.length - 1]) return true;\n    return false;\n  },\n  'zh-TW': (str) => {\n    const ALPHABET_CODES = {\n      A: 10,\n      B: 11,\n      C: 12,\n      D: 13,\n      E: 14,\n      F: 15,\n      G: 16,\n      H: 17,\n      I: 34,\n      J: 18,\n      K: 19,\n      L: 20,\n      M: 21,\n      N: 22,\n      O: 35,\n      P: 23,\n      Q: 24,\n      R: 25,\n      S: 26,\n      T: 27,\n      U: 28,\n      V: 29,\n      W: 32,\n      X: 30,\n      Y: 31,\n      Z: 33,\n    };\n\n    const sanitized = str.trim().toUpperCase();\n\n    if (!/^[A-Z][0-9]{9}$/.test(sanitized)) return false;\n\n    return Array.from(sanitized).reduce((sum, number, index) => {\n      if (index === 0) {\n        const code = ALPHABET_CODES[number];\n\n        return ((code % 10) * 9) + Math.floor(code / 10);\n      }\n\n      if (index === 9) {\n        return ((10 - (sum % 10)) - Number(number)) % 10 === 0;\n      }\n\n      return sum + (Number(number) * (9 - index));\n    }, 0);\n  },\n  PK: (str) => {\n    // Pakistani National Identity Number CNIC is 13 digits\n    const CNIC = /^[1-7][0-9]{4}-[0-9]{7}-[1-9]$/;\n\n    // sanitize user input\n    const sanitized = str.trim();\n\n    // validate the data structure\n    return CNIC.test(sanitized);\n  },\n};\n\nexport default function isIdentityCard(str, locale) {\n  assertString(str);\n  if (locale in validators) {\n    return validators[locale](str);\n  } else if (locale === 'any') {\n    for (const key in validators) {\n      // https://github.com/gotwarlost/istanbul/blob/master/ignoring-code-for-coverage.md#ignoring-code-for-coverage-purposes\n      // istanbul ignore else\n      if (validators.hasOwnProperty(key)) {\n        const validator = validators[key];\n        if (validator(str)) {\n          return true;\n        }\n      }\n    }\n    return false;\n  }\n  throw new Error(`Invalid locale '${locale}'`);\n}\n"
  },
  {
    "path": "src/lib/isIn.js",
    "content": "import assertString from './util/assertString';\nimport toString from './util/toString';\n\nexport default function isIn(str, options) {\n  assertString(str);\n  let i;\n  if (Object.prototype.toString.call(options) === '[object Array]') {\n    const array = [];\n    for (i in options) {\n      // https://github.com/gotwarlost/istanbul/blob/master/ignoring-code-for-coverage.md#ignoring-code-for-coverage-purposes\n      // istanbul ignore else\n      if ({}.hasOwnProperty.call(options, i)) {\n        array[i] = toString(options[i]);\n      }\n    }\n    return array.indexOf(str) >= 0;\n  } else if (typeof options === 'object') {\n    return options.hasOwnProperty(str);\n  } else if (options && typeof options.indexOf === 'function') {\n    return options.indexOf(str) >= 0;\n  }\n  return false;\n}\n"
  },
  {
    "path": "src/lib/isInt.js",
    "content": "import assertString from './util/assertString';\nimport isNullOrUndefined from './util/nullUndefinedCheck';\n\nconst int = /^(?:[-+]?(?:0|[1-9][0-9]*))$/;\nconst intLeadingZeroes = /^[-+]?[0-9]+$/;\n\nexport default function isInt(str, options) {\n  assertString(str);\n  options = options || {};\n\n  // Get the regex to use for testing, based on whether\n  // leading zeroes are allowed or not.\n  const regex = options.allow_leading_zeroes === false ? int : intLeadingZeroes;\n\n  // Check min/max/lt/gt\n  let minCheckPassed = (!options.hasOwnProperty('min') || isNullOrUndefined(options.min) || str >= options.min);\n  let maxCheckPassed = (!options.hasOwnProperty('max') || isNullOrUndefined(options.max) || str <= options.max);\n  let ltCheckPassed = (!options.hasOwnProperty('lt') || isNullOrUndefined(options.lt) || str < options.lt);\n  let gtCheckPassed = (!options.hasOwnProperty('gt') || isNullOrUndefined(options.gt) || str > options.gt);\n\n  return regex.test(str) && minCheckPassed && maxCheckPassed && ltCheckPassed && gtCheckPassed;\n}\n"
  },
  {
    "path": "src/lib/isJSON.js",
    "content": "import assertString from './util/assertString';\nimport includes from './util/includesArray';\nimport merge from './util/merge';\n\nconst default_json_options = {\n  allow_primitives: false,\n};\n\nexport default function isJSON(str, options) {\n  assertString(str);\n  try {\n    options = merge(options, default_json_options);\n    let primitives = [];\n    if (options.allow_primitives) {\n      primitives = [null, false, true];\n    }\n\n    const obj = JSON.parse(str);\n    return includes(primitives, obj) || (!!obj && typeof obj === 'object');\n  } catch (e) { /* ignore */ }\n  return false;\n}\n"
  },
  {
    "path": "src/lib/isJWT.js",
    "content": "import assertString from './util/assertString';\nimport isBase64 from './isBase64';\n\nexport default function isJWT(str) {\n  assertString(str);\n\n  const dotSplit = str.split('.');\n  const len = dotSplit.length;\n\n  if (len !== 3) {\n    return false;\n  }\n\n  return dotSplit.reduce((acc, currElem) => acc && isBase64(currElem, { urlSafe: true }), true);\n}\n"
  },
  {
    "path": "src/lib/isLatLong.js",
    "content": "import assertString from './util/assertString';\nimport merge from './util/merge';\nimport includes from './util/includesString';\n\nconst lat = /^\\(?[+-]?(90(\\.0+)?|[1-8]?\\d(\\.\\d+)?)$/;\nconst long = /^\\s?[+-]?(180(\\.0+)?|1[0-7]\\d(\\.\\d+)?|\\d{1,2}(\\.\\d+)?)\\)?$/;\n\nconst latDMS = /^(([1-8]?\\d)\\D+([1-5]?\\d|60)\\D+([1-5]?\\d|60)(\\.\\d+)?|90\\D+0\\D+0)\\D+[NSns]?$/i;\nconst longDMS = /^\\s*([1-7]?\\d{1,2}\\D+([1-5]?\\d|60)\\D+([1-5]?\\d|60)(\\.\\d+)?|180\\D+0\\D+0)\\D+[EWew]?$/i;\n\nconst defaultLatLongOptions = {\n  checkDMS: false,\n};\n\nexport default function isLatLong(str, options) {\n  assertString(str);\n  options = merge(options, defaultLatLongOptions);\n\n  if (!includes(str, ',')) return false;\n  const pair = str.split(',');\n  if ((pair[0].startsWith('(') && !pair[1].endsWith(')'))\n    || (pair[1].endsWith(')') && !pair[0].startsWith('('))) return false;\n\n  if (options.checkDMS) {\n    return latDMS.test(pair[0]) && longDMS.test(pair[1]);\n  }\n  return lat.test(pair[0]) && long.test(pair[1]);\n}\n"
  },
  {
    "path": "src/lib/isLength.js",
    "content": "import assertString from './util/assertString';\n\n/* eslint-disable prefer-rest-params */\nexport default function isLength(str, options) {\n  assertString(str);\n  let min;\n  let max;\n\n  if (typeof (options) === 'object') {\n    min = options.min || 0;\n    max = options.max;\n  } else { // backwards compatibility: isLength(str, min [, max])\n    min = arguments[1] || 0;\n    max = arguments[2];\n  }\n\n  const presentationSequences = str.match(/[^\\uFE0F\\uFE0E][\\uFE0F\\uFE0E]/g) || [];\n  const surrogatePairs = str.match(/[\\uD800-\\uDBFF][\\uDC00-\\uDFFF]/g) || [];\n  const len = str.length - presentationSequences.length - surrogatePairs.length;\n  const isInsideRange = len >= min && (typeof max === 'undefined' || len <= max);\n\n  if (isInsideRange && Array.isArray(options?.discreteLengths)) {\n    return options.discreteLengths.some(discreteLen => discreteLen === len);\n  }\n\n  return isInsideRange;\n}\n"
  },
  {
    "path": "src/lib/isLicensePlate.js",
    "content": "import assertString from './util/assertString';\r\n\r\nconst validators = {\r\n  'cs-CZ': str =>\r\n    /^(([ABCDEFHIJKLMNPRSTUVXYZ]|[0-9])-?){5,8}$/.test(str),\r\n  'de-DE': str =>\r\n    /^((A|AA|AB|AC|AE|AH|AK|AM|AN|AÖ|AP|AS|AT|AU|AW|AZ|B|BA|BB|BC|BE|BF|BH|BI|BK|BL|BM|BN|BO|BÖ|BS|BT|BZ|C|CA|CB|CE|CO|CR|CW|D|DA|DD|DE|DH|DI|DL|DM|DN|DO|DU|DW|DZ|E|EA|EB|ED|EE|EF|EG|EH|EI|EL|EM|EN|ER|ES|EU|EW|F|FB|FD|FF|FG|FI|FL|FN|FO|FR|FS|FT|FÜ|FW|FZ|G|GA|GC|GD|GE|GF|GG|GI|GK|GL|GM|GN|GÖ|GP|GR|GS|GT|GÜ|GV|GW|GZ|H|HA|HB|HC|HD|HE|HF|HG|HH|HI|HK|HL|HM|HN|HO|HP|HR|HS|HU|HV|HX|HY|HZ|IK|IL|IN|IZ|J|JE|JL|K|KA|KB|KC|KE|KF|KG|KH|KI|KK|KL|KM|KN|KO|KR|KS|KT|KU|KW|KY|L|LA|LB|LC|LD|LF|LG|LH|LI|LL|LM|LN|LÖ|LP|LR|LU|M|MA|MB|MC|MD|ME|MG|MH|MI|MK|ML|MM|MN|MO|MQ|MR|MS|MÜ|MW|MY|MZ|N|NB|ND|NE|NF|NH|NI|NK|NM|NÖ|NP|NR|NT|NU|NW|NY|NZ|OA|OB|OC|OD|OE|OF|OG|OH|OK|OL|OP|OS|OZ|P|PA|PB|PE|PF|PI|PL|PM|PN|PR|PS|PW|PZ|R|RA|RC|RD|RE|RG|RH|RI|RL|RM|RN|RO|RP|RS|RT|RU|RV|RW|RZ|S|SB|SC|SE|SG|SI|SK|SL|SM|SN|SO|SP|SR|ST|SU|SW|SY|SZ|TE|TF|TG|TO|TP|TR|TS|TT|TÜ|ÜB|UE|UH|UL|UM|UN|V|VB|VG|VK|VR|VS|W|WA|WB|WE|WF|WI|WK|WL|WM|WN|WO|WR|WS|WT|WÜ|WW|WZ|Z|ZE|ZI|ZP|ZR|ZW|ZZ)[- ]?[A-Z]{1,2}[- ]?\\d{1,4}|(ABG|ABI|AIB|AIC|ALF|ALZ|ANA|ANG|ANK|APD|ARN|ART|ASL|ASZ|AUR|AZE|BAD|BAR|BBG|BCH|BED|BER|BGD|BGL|BID|BIN|BIR|BIT|BIW|BKS|BLB|BLK|BNA|BOG|BOH|BOR|BOT|BRA|BRB|BRG|BRK|BRL|BRV|BSB|BSK|BTF|BÜD|BUL|BÜR|BÜS|BÜZ|CAS|CHA|CLP|CLZ|COC|COE|CUX|DAH|DAN|DAU|DBR|DEG|DEL|DGF|DIL|DIN|DIZ|DKB|DLG|DON|DUD|DÜW|EBE|EBN|EBS|ECK|EIC|EIL|EIN|EIS|EMD|EMS|ERB|ERH|ERK|ERZ|ESB|ESW|FDB|FDS|FEU|FFB|FKB|FLÖ|FOR|FRG|FRI|FRW|FTL|FÜS|GAN|GAP|GDB|GEL|GEO|GER|GHA|GHC|GLA|GMN|GNT|GOA|GOH|GRA|GRH|GRI|GRM|GRZ|GTH|GUB|GUN|GVM|HAB|HAL|HAM|HAS|HBN|HBS|HCH|HDH|HDL|HEB|HEF|HEI|HER|HET|HGN|HGW|HHM|HIG|HIP|HMÜ|HOG|HOH|HOL|HOM|HOR|HÖS|HOT|HRO|HSK|HST|HVL|HWI|IGB|ILL|JÜL|KEH|KEL|KEM|KIB|KLE|KLZ|KÖN|KÖT|KÖZ|KRU|KÜN|KUS|KYF|LAN|LAU|LBS|LBZ|LDK|LDS|LEO|LER|LEV|LIB|LIF|LIP|LÖB|LOS|LRO|LSZ|LÜN|LUP|LWL|MAB|MAI|MAK|MAL|MED|MEG|MEI|MEK|MEL|MER|MET|MGH|MGN|MHL|MIL|MKK|MOD|MOL|MON|MOS|MSE|MSH|MSP|MST|MTK|MTL|MÜB|MÜR|MYK|MZG|NAB|NAI|NAU|NDH|NEA|NEB|NEC|NEN|NES|NEW|NMB|NMS|NOH|NOL|NOM|NOR|NVP|NWM|OAL|OBB|OBG|OCH|OHA|ÖHR|OHV|OHZ|OPR|OSL|OVI|OVL|OVP|PAF|PAN|PAR|PCH|PEG|PIR|PLÖ|PRÜ|QFT|QLB|RDG|REG|REH|REI|RID|RIE|ROD|ROF|ROK|ROL|ROS|ROT|ROW|RSL|RÜD|RÜG|SAB|SAD|SAN|SAW|SBG|SBK|SCZ|SDH|SDL|SDT|SEB|SEE|SEF|SEL|SFB|SFT|SGH|SHA|SHG|SHK|SHL|SIG|SIM|SLE|SLF|SLK|SLN|SLS|SLÜ|SLZ|SMÜ|SOB|SOG|SOK|SÖM|SON|SPB|SPN|SRB|SRO|STA|STB|STD|STE|STL|SUL|SÜW|SWA|SZB|TBB|TDO|TET|TIR|TÖL|TUT|UEM|UER|UFF|USI|VAI|VEC|VER|VIB|VIE|VIT|VOH|WAF|WAK|WAN|WAR|WAT|WBS|WDA|WEL|WEN|WER|WES|WHV|WIL|WIS|WIT|WIZ|WLG|WMS|WND|WOB|WOH|WOL|WOR|WOS|WRN|WSF|WST|WSW|WTL|WTM|WUG|WÜM|WUN|WUR|WZL|ZEL|ZIG)[- ]?(([A-Z][- ]?\\d{1,4})|([A-Z]{2}[- ]?\\d{1,3})))[- ]?(E|H)?$/.test(str),\r\n  'de-LI': str => /^FL[- ]?\\d{1,5}[UZ]?$/.test(str),\r\n  'en-IN': str => /^[A-Z]{2}[ -]?[0-9]{1,2}(?:[ -]?[A-Z])(?:[ -]?[A-Z]*)?[ -]?[0-9]{4}$/.test(str),\r\n  'en-SG': str => /^[A-Z]{3}[ -]?[\\d]{4}[ -]?[A-Z]{1}$/.test(str),\r\n  'es-AR': str => /^(([A-Z]{2} ?[0-9]{3} ?[A-Z]{2})|([A-Z]{3} ?[0-9]{3}))$/.test(str),\r\n  'fi-FI': str => /^(?=.{4,7})(([A-Z]{1,3}|[0-9]{1,3})[\\s-]?([A-Z]{1,3}|[0-9]{1,5}))$/.test(str),\r\n  'hu-HU': str => /^((((?!AAA)(([A-NPRSTVZWXY]{1})([A-PR-Z]{1})([A-HJ-NPR-Z]))|(A[ABC]I)|A[ABC]O|A[A-W]Q|BPI|BPO|UCO|UDO|XAO)-(?!000)\\d{3})|(M\\d{6})|((CK|DT|CD|HC|H[ABEFIKLMNPRSTVX]|MA|OT|R[A-Z]) \\d{2}-\\d{2})|(CD \\d{3}-\\d{3})|(C-(C|X) \\d{4})|(X-(A|B|C) \\d{4})|(([EPVZ]-\\d{5}))|(S A[A-Z]{2} \\d{2})|(SP \\d{2}-\\d{2}))$/.test(str),\r\n  'pt-BR': str =>\r\n    /^[A-Z]{3}[ -]?[0-9][A-Z][0-9]{2}|[A-Z]{3}[ -]?[0-9]{4}$/.test(str),\r\n  'pt-PT': str =>\r\n    /^(([A-Z]{2}[ -·]?[0-9]{2}[ -·]?[0-9]{2})|([0-9]{2}[ -·]?[A-Z]{2}[ -·]?[0-9]{2})|([0-9]{2}[ -·]?[0-9]{2}[ -·]?[A-Z]{2})|([A-Z]{2}[ -·]?[0-9]{2}[ -·]?[A-Z]{2}))$/.test(str),\r\n  'sq-AL': str =>\r\n    /^[A-Z]{2}[- ]?((\\d{3}[- ]?(([A-Z]{2})|T))|(R[- ]?\\d{3}))$/.test(str),\r\n  'sv-SE': str =>\r\n    /^[A-HJ-PR-UW-Z]{3} ?[\\d]{2}[A-HJ-PR-UW-Z1-9]$|(^[A-ZÅÄÖ ]{2,7}$)/.test(str.trim()),\r\n  'en-PK': str => /(^[A-Z]{2}((\\s|-){0,1})[0-9]{3,4}((\\s|-)[0-9]{2}){0,1}$)|(^[A-Z]{3}((\\s|-){0,1})[0-9]{3,4}((\\s|-)[0-9]{2}){0,1}$)|(^[A-Z]{4}((\\s|-){0,1})[0-9]{3,4}((\\s|-)[0-9]{2}){0,1}$)|(^[A-Z]((\\s|-){0,1})[0-9]{4}((\\s|-)[0-9]{2}){0,1}$)/.test(str.trim()),\r\n};\r\n\r\nexport default function isLicensePlate(str, locale) {\r\n  assertString(str);\r\n  if (locale in validators) {\r\n    return validators[locale](str);\r\n  } else if (locale === 'any') {\r\n    for (const key in validators) {\r\n      /* eslint guard-for-in: 0 */\r\n      const validator = validators[key];\r\n      if (validator(str)) {\r\n        return true;\r\n      }\r\n    }\r\n    return false;\r\n  }\r\n  throw new Error(`Invalid locale '${locale}'`);\r\n}\r\n"
  },
  {
    "path": "src/lib/isLocale.js",
    "content": "import assertString from './util/assertString';\n\n/*\n  = 3ALPHA              ; selected ISO 639 codes\n    *2(\"-\" 3ALPHA)      ; permanently reserved\n */\nconst extlang = '([A-Za-z]{3}(-[A-Za-z]{3}){0,2})';\n\n/*\n  = 2*3ALPHA            ; shortest ISO 639 code\n    [\"-\" extlang]       ; sometimes followed by\n                        ; extended language subtags\n  / 4ALPHA              ; or reserved for future use\n  / 5*8ALPHA            ; or registered language subtag\n */\nconst language = `(([a-zA-Z]{2,3}(-${extlang})?)|([a-zA-Z]{5,8}))`;\n\n/*\n  = 4ALPHA              ; ISO 15924 code\n */\nconst script = '([A-Za-z]{4})';\n\n/*\n  = 2ALPHA              ; ISO 3166-1 code\n  / 3DIGIT              ; UN M.49 code\n */\nconst region = '([A-Za-z]{2}|\\\\d{3})';\n\n/*\n  = 5*8alphanum         ; registered variants\n  / (DIGIT 3alphanum)\n */\nconst variant = '([A-Za-z0-9]{5,8}|(\\\\d[A-Z-a-z0-9]{3}))';\n\n/*\n  = DIGIT               ; 0 - 9\n  / %x41-57             ; A - W\n  / %x59-5A             ; Y - Z\n  / %x61-77             ; a - w\n  / %x79-7A             ; y - z\n */\nconst singleton = '(\\\\d|[A-W]|[Y-Z]|[a-w]|[y-z])';\n\n/*\n  = singleton 1*(\"-\" (2*8alphanum))\n                        ; Single alphanumerics\n                        ; \"x\" reserved for private use\n */\nconst extension = `(${singleton}(-[A-Za-z0-9]{2,8})+)`;\n\n/*\n  = \"x\" 1*(\"-\" (1*8alphanum))\n */\nconst privateuse = '(x(-[A-Za-z0-9]{1,8})+)';\n\n// irregular tags do not match the 'langtag' production and would not\n// otherwise be considered 'well-formed'. These tags are all valid, but\n// most are deprecated in favor of more modern subtags or subtag combination\n\nconst irregular = '((en-GB-oed)|(i-ami)|(i-bnn)|(i-default)|(i-enochian)|' +\n    '(i-hak)|(i-klingon)|(i-lux)|(i-mingo)|(i-navajo)|(i-pwn)|(i-tao)|' +\n    '(i-tay)|(i-tsu)|(sgn-BE-FR)|(sgn-BE-NL)|(sgn-CH-DE))';\n\n// regular tags match the 'langtag' production, but their subtags are not\n// extended language or variant subtags: their meaning is defined by\n// their registration and all of these are deprecated in favor of a more\n// modern subtag or sequence of subtags\n\nconst regular = '((art-lojban)|(cel-gaulish)|(no-bok)|(no-nyn)|(zh-guoyu)|' +\n    '(zh-hakka)|(zh-min)|(zh-min-nan)|(zh-xiang))';\n\n/*\n  = irregular           ; non-redundant tags registered\n  / regular             ; during the RFC 3066 era\n\n */\nconst grandfathered = `(${irregular}|${regular})`;\n\n/*\n  RFC 5646 defines delimitation of subtags via a hyphen:\n\n      \"Subtag\" refers to a specific section of a tag, delimited by a\n      hyphen, such as the subtags 'zh', 'Hant', and 'CN' in the tag \"zh-\n      Hant-CN\".  Examples of subtags in this document are enclosed in\n      single quotes ('Hant')\n\n  However, we need to add \"_\" to maintain the existing behaviour.\n */\nconst delimiter = '(-|_)';\n\n/*\n  = language\n    [\"-\" script]\n    [\"-\" region]\n    *(\"-\" variant)\n    *(\"-\" extension)\n    [\"-\" privateuse]\n */\nconst langtag = `${language}(${delimiter}${script})?(${delimiter}${region})?(${delimiter}${variant})*(${delimiter}${extension})*(${delimiter}${privateuse})?`;\n\n/*\n  Regex implementation based on BCP RFC 5646\n  Tags for Identifying Languages\n  https://www.rfc-editor.org/rfc/rfc5646.html\n */\nconst languageTagRegex = new RegExp(`(^${privateuse}$)|(^${grandfathered}$)|(^${langtag}$)`);\n\nexport default function isLocale(str) {\n  assertString(str);\n  return languageTagRegex.test(str);\n}\n"
  },
  {
    "path": "src/lib/isLowercase.js",
    "content": "import assertString from './util/assertString';\n\nexport default function isLowercase(str) {\n  assertString(str);\n  return str === str.toLowerCase();\n}\n"
  },
  {
    "path": "src/lib/isLuhnNumber.js",
    "content": "import assertString from './util/assertString';\n\nexport default function isLuhnNumber(str) {\n  assertString(str);\n  const sanitized = str.replace(/[- ]+/g, '');\n  let sum = 0;\n  let digit;\n  let tmpNum;\n  let shouldDouble;\n  for (let i = sanitized.length - 1; i >= 0; i--) {\n    digit = sanitized.substring(i, (i + 1));\n    tmpNum = parseInt(digit, 10);\n    if (shouldDouble) {\n      tmpNum *= 2;\n      if (tmpNum >= 10) {\n        sum += ((tmpNum % 10) + 1);\n      } else {\n        sum += tmpNum;\n      }\n    } else {\n      sum += tmpNum;\n    }\n    shouldDouble = !shouldDouble;\n  }\n  return !!((sum % 10) === 0 ? sanitized : false);\n}\n"
  },
  {
    "path": "src/lib/isMACAddress.js",
    "content": "import assertString from './util/assertString';\n\nconst macAddress48 = /^(?:[0-9a-fA-F]{2}([-:\\s]))([0-9a-fA-F]{2}\\1){4}([0-9a-fA-F]{2})$/;\nconst macAddress48NoSeparators = /^([0-9a-fA-F]){12}$/;\nconst macAddress48WithDots = /^([0-9a-fA-F]{4}\\.){2}([0-9a-fA-F]{4})$/;\nconst macAddress64 = /^(?:[0-9a-fA-F]{2}([-:\\s]))([0-9a-fA-F]{2}\\1){6}([0-9a-fA-F]{2})$/;\nconst macAddress64NoSeparators = /^([0-9a-fA-F]){16}$/;\nconst macAddress64WithDots = /^([0-9a-fA-F]{4}\\.){3}([0-9a-fA-F]{4})$/;\n\nexport default function isMACAddress(str, options) {\n  assertString(str);\n  if (options?.eui) {\n    options.eui = String(options.eui);\n  }\n  /**\n   * @deprecated `no_colons` TODO: remove it in the next major\n  */\n  if (options?.no_colons || options?.no_separators) {\n    if (options.eui === '48') {\n      return macAddress48NoSeparators.test(str);\n    }\n    if (options.eui === '64') {\n      return macAddress64NoSeparators.test(str);\n    }\n    return macAddress48NoSeparators.test(str) || macAddress64NoSeparators.test(str);\n  }\n  if (options?.eui === '48') {\n    return macAddress48.test(str) || macAddress48WithDots.test(str);\n  }\n  if (options?.eui === '64') {\n    return macAddress64.test(str) || macAddress64WithDots.test(str);\n  }\n  return isMACAddress(str, { eui: '48' }) || isMACAddress(str, { eui: '64' });\n}\n"
  },
  {
    "path": "src/lib/isMD5.js",
    "content": "import assertString from './util/assertString';\n\nconst md5 = /^[a-f0-9]{32}$/;\n\nexport default function isMD5(str) {\n  assertString(str);\n  return md5.test(str);\n}\n"
  },
  {
    "path": "src/lib/isMagnetURI.js",
    "content": "import assertString from './util/assertString';\n\nconst magnetURIComponent = /(?:^magnet:\\?|[^?&]&)xt(?:\\.1)?=urn:(?:(?:aich|bitprint|btih|ed2k|ed2khash|kzhash|md5|sha1|tree:tiger):[a-z0-9]{32}(?:[a-z0-9]{8})?|btmh:1220[a-z0-9]{64})(?:$|&)/i;\n\nexport default function isMagnetURI(url) {\n  assertString(url);\n\n  if (url.indexOf('magnet:?') !== 0) {\n    return false;\n  }\n\n  return magnetURIComponent.test(url);\n}\n"
  },
  {
    "path": "src/lib/isMailtoURI.js",
    "content": "import trim from './trim';\nimport isEmail from './isEmail';\nimport assertString from './util/assertString';\n\nfunction parseMailtoQueryString(queryString) {\n  const allowedParams = new Set(['subject', 'body', 'cc', 'bcc']),\n    query = { cc: '', bcc: '' };\n  let isParseFailed = false;\n\n  const queryParams = queryString.split('&');\n\n  if (queryParams.length > 4) {\n    return false;\n  }\n\n  for (const q of queryParams) {\n    const [key, value] = q.split('=');\n\n    // checked for invalid and duplicated query params\n    if (key && !allowedParams.has(key)) {\n      isParseFailed = true;\n      break;\n    }\n\n    if (value && (key === 'cc' || key === 'bcc')) {\n      query[key] = value;\n    }\n\n    if (key) {\n      allowedParams.delete(key);\n    }\n  }\n\n  return isParseFailed ? false : query;\n}\n\nexport default function isMailtoURI(url, options) {\n  assertString(url);\n\n  if (url.indexOf('mailto:') !== 0) {\n    return false;\n  }\n\n  const [to, queryString = ''] = url.replace('mailto:', '').split('?');\n\n  if (!to && !queryString) {\n    return true;\n  }\n\n  const query = parseMailtoQueryString(queryString);\n\n  if (!query) {\n    return false;\n  }\n\n  return `${to},${query.cc},${query.bcc}`\n    .split(',')\n    .every((email) => {\n      email = trim(email, ' ');\n\n      if (email) {\n        return isEmail(email, options);\n      }\n\n      return true;\n    });\n}\n"
  },
  {
    "path": "src/lib/isMimeType.js",
    "content": "import assertString from './util/assertString';\n\n/*\n  Checks if the provided string matches to a correct Media type format (MIME type)\n\n  This function only checks is the string format follows the\n  established rules by the according RFC specifications.\n  This function supports 'charset' in textual media types\n  (https://tools.ietf.org/html/rfc6657).\n\n  This function does not check against all the media types listed\n  by the IANA (https://www.iana.org/assignments/media-types/media-types.xhtml)\n  because of lightness purposes : it would require to include\n  all these MIME types in this library, which would weigh it\n  significantly. This kind of effort maybe is not worth for the use that\n  this function has in this entire library.\n\n  More information in the RFC specifications :\n  - https://tools.ietf.org/html/rfc2045\n  - https://tools.ietf.org/html/rfc2046\n  - https://tools.ietf.org/html/rfc7231#section-3.1.1.1\n  - https://tools.ietf.org/html/rfc7231#section-3.1.1.5\n*/\n\n// Match simple MIME types\n// NB :\n//   Subtype length must not exceed 100 characters.\n//   This rule does not comply to the RFC specs (what is the max length ?).\nconst mimeTypeSimple = /^(application|audio|font|image|message|model|multipart|text|video)\\/[a-zA-Z0-9\\.\\-\\+_]{1,100}$/i; // eslint-disable-line max-len\n\n// Handle \"charset\" in \"text/*\"\nconst mimeTypeText = /^text\\/[a-zA-Z0-9\\.\\-\\+]{1,100};\\s?charset=(\"[a-zA-Z0-9\\.\\-\\+\\s]{0,70}\"|[a-zA-Z0-9\\.\\-\\+]{0,70})(\\s?\\([a-zA-Z0-9\\.\\-\\+\\s]{1,20}\\))?$/i; // eslint-disable-line max-len\n\n// Handle \"boundary\" in \"multipart/*\"\nconst mimeTypeMultipart = /^multipart\\/[a-zA-Z0-9\\.\\-\\+]{1,100}(;\\s?(boundary|charset)=(\"[a-zA-Z0-9\\.\\-\\+\\s]{0,70}\"|[a-zA-Z0-9\\.\\-\\+]{0,70})(\\s?\\([a-zA-Z0-9\\.\\-\\+\\s]{1,20}\\))?){0,2}$/i; // eslint-disable-line max-len\n\nexport default function isMimeType(str) {\n  assertString(str);\n  return mimeTypeSimple.test(str) || mimeTypeText.test(str) || mimeTypeMultipart.test(str);\n}\n"
  },
  {
    "path": "src/lib/isMobilePhone.js",
    "content": "import assertString from './util/assertString';\n\n/* eslint-disable max-len */\nconst phones = {\n  'am-AM': /^(\\+?374|0)(33|4[134]|55|77|88|9[13-689])\\d{6}$/,\n  'ar-AE': /^((\\+?971)|0)?5[024568]\\d{7}$/,\n  'ar-BH': /^(\\+?973)?(3|6)\\d{7}$/,\n  'ar-DZ': /^(\\+?213|0)(5|6|7)\\d{8}$/,\n  'ar-LB': /^(\\+?961)?((3|81)\\d{6}|7\\d{7})$/,\n  'ar-EG': /^((\\+?20)|0)?1[0125]\\d{8}$/,\n  'ar-IQ': /^(\\+?964|0)?7[0-9]\\d{8}$/,\n  'ar-JO': /^(\\+?962|0)?7[789]\\d{7}$/,\n  'ar-KW': /^(\\+?965)([569]\\d{7}|41\\d{6})$/,\n  'ar-LY': /^((\\+?218)|0)?(9[1-6]\\d{7}|[1-8]\\d{7,9})$/,\n  'ar-MA': /^(?:(?:\\+|00)212|0)[5-7]\\d{8}$/,\n  'ar-OM': /^((\\+|00)968)?([79][1-9])\\d{6}$/,\n  'ar-PS': /^(\\+?970|0)5[6|9](\\d{7})$/,\n  'ar-SA': /^(!?(\\+?966)|0)?5\\d{8}$/,\n  'ar-SD': /^((\\+?249)|0)?(9[012369]|1[012])\\d{7}$/,\n  'ar-SY': /^(!?(\\+?963)|0)?9\\d{8}$/,\n  'ar-TN': /^(\\+?216)?[2459]\\d{7}$/,\n  'az-AZ': /^(\\+994|0)(10|5[015]|7[07]|99)\\d{7}$/,\n  'ar-QA': /^(\\+?974|0)?([3567]\\d{7})$/,\n  'bs-BA': /^((((\\+|00)3876)|06))((([0-3]|[5-6])\\d{6})|(4\\d{7}))$/,\n  'be-BY': /^(\\+?375)?(24|25|29|33|44)\\d{7}$/,\n  'bg-BG': /^(\\+?359|0)?8[789]\\d{7}$/,\n  'bn-BD': /^(\\+?880|0)1[13456789][0-9]{8}$/,\n  'ca-AD': /^(\\+376)?[346]\\d{5}$/,\n  'cs-CZ': /^(\\+?420)? ?[1-9][0-9]{2} ?[0-9]{3} ?[0-9]{3}$/,\n  'da-DK': /^(\\+?45)?\\s?\\d{2}\\s?\\d{2}\\s?\\d{2}\\s?\\d{2}$/,\n  'de-DE': /^((\\+49|0)1)(5[0-25-9]\\d|6([23]|0\\d?)|7([0-57-9]|6\\d))\\d{7,9}$/,\n  'de-AT': /^(\\+43|0)\\d{1,4}\\d{3,12}$/,\n  'de-CH': /^(\\+41|0)([1-9])\\d{1,9}$/,\n  'de-LU': /^(\\+352)?((6\\d1)\\d{6})$/,\n  'dv-MV': /^(\\+?960)?(7[2-9]|9[1-9])\\d{5}$/,\n  'el-GR': /^(\\+?30|0)?6(8[5-9]|9(?![26])[0-9])\\d{7}$/,\n  'el-CY': /^(\\+?357?)?(9(9|7|6|5|4)\\d{6})$/,\n  'en-AI': /^(\\+?1|0)264(?:2(35|92)|4(?:6[1-2]|76|97)|5(?:3[6-9]|8[1-4])|7(?:2(4|9)|72))\\d{4}$/,\n  'en-AU': /^(\\+?61|0)4\\d{8}$/,\n  'en-AG': /^(?:\\+1|1)268(?:464|7(?:1[3-9]|[28]\\d|3[0246]|64|7[0-689]))\\d{4}$/,\n  'en-BM': /^(\\+?1)?441(((3|7)\\d{6}$)|(5[0-3][0-9]\\d{4}$)|(59\\d{5}$))/,\n  'en-BS': /^(\\+?1[-\\s]?|0)?\\(?242\\)?[-\\s]?\\d{3}[-\\s]?\\d{4}$/,\n  'en-GB': /^(\\+?44|0)7[1-9]\\d{8}$/,\n  'en-GG': /^(\\+?44|0)1481\\d{6}$/,\n  'en-GH': /^(\\+233|0)(20|50|24|54|27|57|26|56|23|53|28|55|59)\\d{7}$/,\n  'en-GY': /^(\\+592|0)6\\d{6}$/,\n  'en-HK': /^(\\+?852[-\\s]?)?[456789]\\d{3}[-\\s]?\\d{4}$/,\n  'en-MO': /^(\\+?853[-\\s]?)?[6]\\d{3}[-\\s]?\\d{4}$/,\n  'en-IE': /^(\\+?353|0)8[356789]\\d{7}$/,\n  'en-IN': /^(\\+?91|0)?[6789]\\d{9}$/,\n  'en-JM': /^(\\+?876)?\\d{7}$/,\n  'en-KE': /^(\\+?254|0)(7|1)\\d{8}$/,\n  'fr-CF': /^(\\+?236| ?)(70|75|77|72|21|22)\\d{6}$/,\n  'en-SS': /^(\\+?211|0)(9[1257])\\d{7}$/,\n  'en-KI': /^((\\+686|686)?)?( )?((6|7)(2|3|8)[0-9]{6})$/,\n  'en-KN': /^(?:\\+1|1)869(?:46\\d|48[89]|55[6-8]|66\\d|76[02-7])\\d{4}$/,\n  'en-LS': /^(\\+?266)(22|28|57|58|59|27|52)\\d{6}$/,\n  'en-MT': /^(\\+?356|0)?(99|79|77|21|27|22|25)[0-9]{6}$/,\n  'en-MU': /^(\\+?230|0)?\\d{8}$/,\n  'en-MW': /^(\\+?265|0)(((77|88|31|99|98|21)\\d{7})|(((111)|1)\\d{6})|(32000\\d{4}))$/,\n  'en-NA': /^(\\+?264|0)(6|8)\\d{7}$/,\n  'en-NG': /^(\\+?234|0)?[789]\\d{9}$/,\n  'en-NZ': /^(\\+?64|0)[28]\\d{7,9}$/,\n  'en-PG': /^(\\+?675|0)?(7\\d|8[18])\\d{6}$/,\n  'en-PK': /^((00|\\+)?92|0)3[0-6]\\d{8}$/,\n  'en-PH': /^(09|\\+639)\\d{9}$/,\n  'en-RW': /^(\\+?250|0)?[7]\\d{8}$/,\n  'en-SG': /^(\\+65)?[3689]\\d{7}$/,\n  'en-SL': /^(\\+?232|0)\\d{8}$/,\n  'en-TZ': /^(\\+?255|0)?[67]\\d{8}$/,\n  'en-UG': /^(\\+?256|0)?[7]\\d{8}$/,\n  'en-US': /^((\\+1|1)?( |-)?)?(\\([2-9][0-9]{2}\\)|[2-9][0-9]{2})( |-)?([2-9][0-9]{2}( |-)?[0-9]{4})$/,\n  'en-ZA': /^(\\+?27|0)\\d{9}$/,\n  'en-ZM': /^(\\+?26)?0[79][567]\\d{7}$/,\n  'en-ZW': /^(\\+263)[0-9]{9}$/,\n  'en-BW': /^(\\+?267)?(7[1-8]{1})\\d{6}$/,\n  'es-AR': /^\\+?549(11|[2368]\\d)\\d{8}$/,\n  'es-BO': /^(\\+?591)?(6|7)\\d{7}$/,\n  'es-CO': /^(\\+?57)?3(0(0|1|2|4|5)|1\\d|2[0-4]|5(0|1))\\d{7}$/,\n  'es-CL': /^(\\+?56|0)[2-9]\\d{1}\\d{7}$/,\n  'es-CR': /^(\\+506)?[2-8]\\d{7}$/,\n  'es-CU': /^(\\+53|0053)?5\\d{7}$/,\n  'es-DO': /^(\\+?1)?8[024]9\\d{7}$/,\n  'es-HN': /^(\\+?504)?[9|8|3|2]\\d{7}$/,\n  'es-EC': /^(\\+?593|0)([2-7]|9[2-9])\\d{7}$/,\n  'es-ES': /^(\\+?34)?[6|7]\\d{8}$/,\n  'es-GT': /^(\\+?502)?[2|6|7]\\d{7}$/,\n  'es-PE': /^(\\+?51)?9\\d{8}$/,\n  'es-MX': /^(\\+?52)?(1|01)?\\d{10,11}$/,\n  'es-NI': /^(\\+?505)\\d{7,8}$/,\n  'es-PA': /^(\\+?507)\\d{7,8}$/,\n  'es-PY': /^(\\+?595|0)9[9876]\\d{7}$/,\n  'es-SV': /^(\\+?503)?[67]\\d{7}$/,\n  'es-UY': /^(\\+598|0)9[1-9][\\d]{6}$/,\n  'es-VE': /^(\\+?58)?(2|4)\\d{9}$/,\n  'et-EE': /^(\\+?372)?\\s?(5|8[1-4])\\s?([0-9]\\s?){6,7}$/,\n  'fa-IR': /^(\\+?98[\\-\\s]?|0)9[0-39]\\d[\\-\\s]?\\d{3}[\\-\\s]?\\d{4}$/,\n  'fi-FI': /^(\\+?358|0)\\s?(4[0-6]|50)\\s?(\\d\\s?){4,8}$/,\n  'fj-FJ': /^(\\+?679)?\\s?\\d{3}\\s?\\d{4}$/,\n  'fo-FO': /^(\\+?298)?\\s?\\d{2}\\s?\\d{2}\\s?\\d{2}$/,\n  'fr-BF': /^(\\+226|0)[67]\\d{7}$/,\n  'fr-BJ': /^(\\+229)\\d{8}$/,\n  'fr-CD': /^(\\+?243|0)?(8|9)\\d{8}$/,\n  'fr-CM': /^(\\+?237)6[0-9]{8}$/,\n  'fr-DJ': /^(?:\\+253)?77[6-8]\\d{5}$/,\n  'fr-FR': /^(\\+?33|0)[67]\\d{8}$/,\n  'fr-GF': /^(\\+?594|0|00594)[67]\\d{8}$/,\n  'fr-GP': /^(\\+?590|0|00590)[67]\\d{8}$/,\n  'fr-MQ': /^(\\+?596|0|00596)[67]\\d{8}$/,\n  'fr-PF': /^(\\+?689)?8[789]\\d{6}$/,\n  'fr-RE': /^(\\+?262|0|00262)[67]\\d{8}$/,\n  'fr-WF': /^(\\+681)?\\d{6}$/,\n  'he-IL': /^(\\+972|0)([23489]|5[012345689]|77)[1-9]\\d{6}$/,\n  'hu-HU': /^(\\+?36|06)(20|30|31|50|70)\\d{7}$/,\n  'id-ID': /^(\\+?62|0)8(1[123456789]|2[1238]|3[1238]|5[12356789]|7[78]|9[56789]|8[123456789])([\\s?|\\d]{5,11})$/,\n  'ir-IR': /^(\\+98|0)?9\\d{9}$/,\n  'it-IT': /^(\\+?39)?\\s?3\\d{2} ?\\d{6,7}$/,\n  'it-SM': /^((\\+378)|(0549)|(\\+390549)|(\\+3780549))?6\\d{5,9}$/,\n  'ja-JP': /^(\\+81[ \\-]?(\\(0\\))?|0)[6789]0[ \\-]?\\d{4}[ \\-]?\\d{4}$/,\n  'ka-GE': /^(\\+?995)?(79\\d{7}|5\\d{8})$/,\n  'kk-KZ': /^(\\+?7|8)?7\\d{9}$/,\n  'kl-GL': /^(\\+?299)?\\s?\\d{2}\\s?\\d{2}\\s?\\d{2}$/,\n  'ko-KR': /^((\\+?82)[ \\-]?)?0?1([0|1|6|7|8|9]{1})[ \\-]?\\d{3,4}[ \\-]?\\d{4}$/,\n  'ky-KG': /^(\\+996\\s?)?(22[0-9]|50[0-9]|55[0-9]|70[0-9]|75[0-9]|77[0-9]|880|990|995|996|997|998)\\s?\\d{3}\\s?\\d{3}$/,\n  'lt-LT': /^(\\+370|8)\\d{8}$/,\n  'lv-LV': /^(\\+?371)2\\d{7}$/,\n  'mg-MG': /^((\\+?261|0)(2|3)\\d)?\\d{7}$/,\n  'mn-MN': /^(\\+|00|011)?976(77|81|88|91|94|95|96|99)\\d{6}$/,\n  'my-MM': /^(\\+?959|09|9)(2[5-7]|3[1-2]|4[0-5]|6[6-9]|7[5-9]|9[6-9])[0-9]{7}$/,\n  'ms-MY': /^(\\+?60|0)1(([0145](-|\\s)?\\d{7,8})|([236-9](-|\\s)?\\d{7}))$/,\n  'mz-MZ': /^(\\+?258)?8[234567]\\d{7}$/,\n  'nb-NO': /^(\\+?47)?[49]\\d{7}$/,\n  'ne-NP': /^(\\+?977)?9[78]\\d{8}$/,\n  'nl-BE': /^(\\+?32|0)4\\d{8}$/,\n  'nl-NL': /^(((\\+|00)?31\\(0\\))|((\\+|00)?31)|0)6{1}\\d{8}$/,\n  'nl-AW': /^(\\+)?297(56|59|64|73|74|99)\\d{5}$/,\n  'nn-NO': /^(\\+?47)?[49]\\d{7}$/,\n  'pl-PL': /^(\\+?48)? ?([5-8]\\d|45) ?\\d{3} ?\\d{2} ?\\d{2}$/,\n  'pt-BR': /^((\\+?55\\ ?[1-9]{2}\\ ?)|(\\+?55\\ ?\\([1-9]{2}\\)\\ ?)|(0[1-9]{2}\\ ?)|(\\([1-9]{2}\\)\\ ?)|([1-9]{2}\\ ?))((\\d{4}\\-?\\d{4})|(9[1-9]{1}\\d{3}\\-?\\d{4}))$/,\n  'pt-PT': /^(\\+?351)?9[1236]\\d{7}$/,\n  'pt-AO': /^(\\+?244)?9\\d{8}$/,\n  'ro-MD': /^(\\+?373|0)((6(0|1|2|6|7|8|9))|(7(6|7|8|9)))\\d{6}$/,\n  'ro-RO': /^(\\+?40|0)\\s?7\\d{2}(\\/|\\s|\\.|-)?\\d{3}(\\s|\\.|-)?\\d{3}$/,\n  'ru-RU': /^(\\+?7|8)?9\\d{9}$/,\n  'si-LK': /^(?:0|94|\\+94)?(7(0|1|2|4|5|6|7|8)( |-)?)\\d{7}$/,\n  'sl-SI': /^(\\+386\\s?|0)(\\d{1}\\s?\\d{3}\\s?\\d{2}\\s?\\d{2}|\\d{2}\\s?\\d{3}\\s?\\d{3})$/,\n  'sk-SK': /^(\\+?421)? ?[1-9][0-9]{2} ?[0-9]{3} ?[0-9]{3}$/,\n  'so-SO': /^(\\+?252|0)((6[0-9])\\d{7}|(7[1-9])\\d{7})$/,\n  'sq-AL': /^(\\+355|0)6[2-9]\\d{7}$/,\n  'sr-RS': /^(\\+3816|06)[- \\d]{5,9}$/,\n  'sv-SE': /^(\\+?46|0)[\\s\\-]?7[\\s\\-]?[02369]([\\s\\-]?\\d){7}$/,\n  'tg-TJ': /^(\\+?992)?[5][5]\\d{7}$/,\n  'th-TH': /^(\\+66|66|0)\\d{9}$/,\n  'tr-TR': /^(\\+?90|0)?5\\d{9}$/,\n  'tk-TM': /^(\\+993|993|8)\\d{8}$/,\n  'uk-UA': /^(\\+?38)?0(50|6[36-8]|7[357]|9[1-9])\\d{7}$/,\n  'uz-UZ': /^(\\+?998)?(6[125-79]|7[1-69]|88|9\\d)\\d{7}$/,\n  'vi-VN': /^((\\+?84)|0)((3([2-9]))|(5([25689]))|(7([0|6-9]))|(8([1-9]))|(9([0-9])))([0-9]{7})$/,\n  'zh-CN': /^((\\+|00)86)?(1[3-9]|9[28])\\d{9}$/,\n  'zh-TW': /^(\\+?886\\-?|0)?9\\d{8}$/,\n  'dz-BT': /^(\\+?975|0)?(17|16|77|02)\\d{6}$/,\n  'ar-YE': /^(((\\+|00)9677|0?7)[0137]\\d{7}|((\\+|00)967|0)[1-7]\\d{6})$/,\n  'ar-EH': /^(\\+?212|0)[\\s\\-]?(5288|5289)[\\s\\-]?\\d{5}$/,\n  'fa-AF': /^(\\+93|0)?(2{1}[0-8]{1}|[3-5]{1}[0-4]{1})(\\d{7})$/,\n  'mk-MK': /^(\\+?389|0)?((?:2[2-9]\\d{6}|(?:3[1-4]|4[2-8])\\d{6}|500\\d{5}|5[2-9]\\d{6}|7[0-9][2-9]\\d{5}|8[1-9]\\d{6}|800\\d{5}|8009\\d{4}))$/,\n};\n/* eslint-enable max-len */\n\n// aliases\nphones['en-CA'] = phones['en-US'];\nphones['fr-CA'] = phones['en-CA'];\nphones['fr-BE'] = phones['nl-BE'];\nphones['zh-HK'] = phones['en-HK'];\nphones['zh-MO'] = phones['en-MO'];\nphones['ga-IE'] = phones['en-IE'];\nphones['fr-CH'] = phones['de-CH'];\nphones['it-CH'] = phones['fr-CH'];\n\nexport default function isMobilePhone(str, locale, options) {\n  assertString(str);\n  if (options && options.strictMode && !str.startsWith('+')) {\n    return false;\n  }\n  if (Array.isArray(locale)) {\n    return locale.some((key) => {\n      // https://github.com/gotwarlost/istanbul/blob/master/ignoring-code-for-coverage.md#ignoring-code-for-coverage-purposes\n      // istanbul ignore else\n      if (phones.hasOwnProperty(key)) {\n        const phone = phones[key];\n        if (phone.test(str)) {\n          return true;\n        }\n      }\n      return false;\n    });\n  } else if (locale in phones) {\n    return phones[locale].test(str);\n    // alias falsey locale as 'any'\n  } else if (!locale || locale === 'any') {\n    for (const key in phones) {\n      // istanbul ignore else\n      if (phones.hasOwnProperty(key)) {\n        const phone = phones[key];\n        if (phone.test(str)) {\n          return true;\n        }\n      }\n    }\n    return false;\n  }\n  throw new Error(`Invalid locale '${locale}'`);\n}\n\nexport const locales = Object.keys(phones);\n"
  },
  {
    "path": "src/lib/isMongoId.js",
    "content": "import assertString from './util/assertString';\n\nimport isHexadecimal from './isHexadecimal';\n\nexport default function isMongoId(str) {\n  assertString(str);\n  return isHexadecimal(str) && str.length === 24;\n}\n"
  },
  {
    "path": "src/lib/isMultibyte.js",
    "content": "import assertString from './util/assertString';\n\n/* eslint-disable no-control-regex */\nconst multibyte = /[^\\x00-\\x7F]/;\n/* eslint-enable no-control-regex */\n\nexport default function isMultibyte(str) {\n  assertString(str);\n  return multibyte.test(str);\n}\n"
  },
  {
    "path": "src/lib/isNumeric.js",
    "content": "import assertString from './util/assertString';\nimport { decimal } from './alpha';\n\nconst numericNoSymbols = /^[0-9]+$/;\n\nexport default function isNumeric(str, options) {\n  assertString(str);\n  if (options && options.no_symbols) {\n    return numericNoSymbols.test(str);\n  }\n  return (new RegExp(`^[+-]?([0-9]*[${(options || {}).locale ? decimal[options.locale] : '.'}])?[0-9]+$`)).test(str);\n}\n"
  },
  {
    "path": "src/lib/isOctal.js",
    "content": "import assertString from './util/assertString';\n\nconst octal = /^(0o)?[0-7]+$/i;\n\nexport default function isOctal(str) {\n  assertString(str);\n  return octal.test(str);\n}\n"
  },
  {
    "path": "src/lib/isPassportNumber.js",
    "content": "import assertString from './util/assertString';\n\n/**\n * Reference:\n * https://en.wikipedia.org/ -- Wikipedia\n * https://docs.microsoft.com/en-us/microsoft-365/compliance/eu-passport-number -- EU Passport Number\n * https://countrycode.org/ -- Country Codes\n */\nconst passportRegexByCountryCode = {\n  AM: /^[A-Z]{2}\\d{7}$/, // ARMENIA\n  AR: /^[A-Z]{3}\\d{6}$/, // ARGENTINA\n  AT: /^[A-Z]\\d{7}$/, // AUSTRIA\n  AU: /^[A-Z]\\d{7}$/, // AUSTRALIA\n  AZ: /^[A-Z]{1}\\d{8}$/, // AZERBAIJAN\n  BE: /^[A-Z]{2}\\d{6}$/, // BELGIUM\n  BG: /^\\d{9}$/, // BULGARIA\n  BR: /^[A-Z]{2}\\d{6}$/, // BRAZIL\n  BY: /^[A-Z]{2}\\d{7}$/, // BELARUS\n  CA: /^[A-Z]{2}\\d{6}$|^[A-Z]\\d{6}[A-Z]{2}$/, // CANADA\n  CH: /^[A-Z]\\d{7}$/, // SWITZERLAND\n  CN: /^G\\d{8}$|^E(?![IO])[A-Z0-9]\\d{7}$/, // CHINA [G=Ordinary, E=Electronic] followed by 8-digits, or E followed by any UPPERCASE letter (except I and O) followed by 7 digits\n  CY: /^[A-Z](\\d{6}|\\d{8})$/, // CYPRUS\n  CZ: /^\\d{8}$/, // CZECH REPUBLIC\n  DE: /^[CFGHJKLMNPRTVWXYZ0-9]{9}$/, // GERMANY\n  DK: /^\\d{9}$/, // DENMARK\n  DZ: /^\\d{9}$/, // ALGERIA\n  EE: /^([A-Z]\\d{7}|[A-Z]{2}\\d{7})$/, // ESTONIA (K followed by 7-digits), e-passports have 2 UPPERCASE followed by 7 digits\n  ES: /^[A-Z0-9]{2}([A-Z0-9]?)\\d{6}$/, // SPAIN\n  FI: /^[A-Z]{2}\\d{7}$/, // FINLAND\n  FR: /^\\d{2}[A-Z]{2}\\d{5}$/, // FRANCE\n  GB: /^\\d{9}$/, // UNITED KINGDOM\n  GR: /^[A-Z]{2}\\d{7}$/, // GREECE\n  HR: /^\\d{9}$/, // CROATIA\n  HU: /^[A-Z]{2}(\\d{6}|\\d{7})$/, // HUNGARY\n  IE: /^[A-Z0-9]{2}\\d{7}$/, // IRELAND\n  IN: /^[A-Z]{1}-?\\d{7}$/, // INDIA\n  ID: /^[A-C]\\d{7}$/, // INDONESIA\n  IR: /^[A-Z]\\d{8}$/, // IRAN\n  IS: /^(A)\\d{7}$/, // ICELAND\n  IT: /^[A-Z0-9]{2}\\d{7}$/, // ITALY\n  JM: /^[Aa]\\d{7}$/, // JAMAICA\n  JP: /^[A-Z]{2}\\d{7}$/, // JAPAN\n  KR: /^[MS]\\d{8}$/, // SOUTH KOREA, REPUBLIC OF KOREA, [S=PS Passports, M=PM Passports]\n  KZ: /^[a-zA-Z]\\d{7}$/, // KAZAKHSTAN\n  LI: /^[a-zA-Z]\\d{5}$/, // LIECHTENSTEIN\n  LT: /^[A-Z0-9]{8}$/, // LITHUANIA\n  LU: /^[A-Z0-9]{8}$/, // LUXEMBURG\n  LV: /^[A-Z0-9]{2}\\d{7}$/, // LATVIA\n  LY: /^[A-Z0-9]{8}$/, // LIBYA\n  MT: /^\\d{7}$/, // MALTA\n  MZ: /^([A-Z]{2}\\d{7})|(\\d{2}[A-Z]{2}\\d{5})$/, // MOZAMBIQUE\n  MY: /^[AHK]\\d{8}$/, // MALAYSIA\n  MX: /^[A-Z]\\d{8}$/, // MEXICO\n  NL: /^[A-Z]{2}[A-Z0-9]{6}\\d$/, // NETHERLANDS\n  NZ: /^([Ll]([Aa]|[Dd]|[Ff]|[Hh])|[Ee]([Aa]|[Pp])|[Nn])\\d{6}$/, // NEW ZEALAND\n  PH: /^([A-Z](\\d{6}|\\d{7}[A-Z]))|([A-Z]{2}(\\d{6}|\\d{7}))$/, // PHILIPPINES\n  PK: /^[A-Z]{2}\\d{7}$/, // PAKISTAN\n  PL: /^[A-Z]{2}\\d{7}$/, // POLAND\n  PT: /^[A-Z]\\d{6}$/, // PORTUGAL\n  RO: /^\\d{8,9}$/, // ROMANIA\n  RU: /^\\d{9}$/, // RUSSIAN FEDERATION\n  SE: /^\\d{8}$/, // SWEDEN\n  SL: /^(P)[A-Z]\\d{7}$/, // SLOVENIA\n  SK: /^[0-9A-Z]\\d{7}$/, // SLOVAKIA\n  TH: /^[A-Z]{1,2}\\d{6,7}$/, // THAILAND\n  TR: /^[A-Z]\\d{8}$/, // TURKEY\n  UA: /^[A-Z]{2}\\d{6}$/, // UKRAINE\n  US: /^\\d{9}$|^[A-Z]\\d{8}$/, // UNITED STATES\n  ZA: /^[TAMD]\\d{8}$/, // SOUTH AFRICA\n};\n\nexport const locales = Object.keys(passportRegexByCountryCode);\n\n/**\n * Check if str is a valid passport number\n * relative to provided ISO Country Code.\n *\n * @param {string} str\n * @param {string} countryCode\n * @return {boolean}\n */\nexport default function isPassportNumber(str, countryCode) {\n  assertString(str);\n  /** Remove All Whitespaces, Convert to UPPERCASE */\n  const normalizedStr = str.replace(/\\s/g, '').toUpperCase();\n\n  return (countryCode.toUpperCase() in passportRegexByCountryCode) &&\n    passportRegexByCountryCode[countryCode].test(normalizedStr);\n}\n"
  },
  {
    "path": "src/lib/isPort.js",
    "content": "import isInt from './isInt';\n\nexport default function isPort(str) {\n  return isInt(str, { allow_leading_zeroes: false, min: 0, max: 65535 });\n}\n"
  },
  {
    "path": "src/lib/isPostalCode.js",
    "content": "import assertString from './util/assertString';\n\n// common patterns\nconst threeDigit = /^\\d{3}$/;\nconst fourDigit = /^\\d{4}$/;\nconst fiveDigit = /^\\d{5}$/;\nconst sixDigit = /^\\d{6}$/;\n\nconst patterns = {\n  AD: /^AD\\d{3}$/,\n  AT: fourDigit,\n  AU: fourDigit,\n  AZ: /^AZ\\d{4}$/,\n  BA: /^([7-8]\\d{4}$)/,\n  BD: /^([1-8][0-9]{3}|9[0-4][0-9]{2})$/,\n  BE: fourDigit,\n  BG: fourDigit,\n  BR: /^\\d{5}-?\\d{3}$/,\n  BY: /^2[1-4]\\d{4}$/,\n  CA: /^[ABCEGHJKLMNPRSTVXY]\\d[ABCEGHJ-NPRSTV-Z][\\s\\-]?\\d[ABCEGHJ-NPRSTV-Z]\\d$/i,\n  CH: fourDigit,\n  CN: /^(0[1-7]|1[012356]|2[0-7]|3[0-6]|4[0-7]|5[1-7]|6[1-7]|7[1-5]|8[1345]|9[09])\\d{4}$/,\n  CO: /^(05|08|11|13|15|17|18|19|20|23|25|27|41|44|47|50|52|54|63|66|68|70|73|76|81|85|86|88|91|94|95|97|99)(\\d{4})$/,\n  CZ: /^\\d{3}\\s?\\d{2}$/,\n  DE: fiveDigit,\n  DK: fourDigit,\n  DO: fiveDigit,\n  DZ: fiveDigit,\n  EE: fiveDigit,\n  ES: /^(5[0-2]{1}|[0-4]{1}\\d{1})\\d{3}$/,\n  FI: fiveDigit,\n  FR: /^(?:(?:0[1-9]|[1-8]\\d|9[0-5])\\d{3}|97[1-46]\\d{2})$/,\n  GB: /^(gir\\s?0aa|[a-z]{1,2}\\d[\\da-z]?\\s?(\\d[a-z]{2})?)$/i,\n  GR: /^\\d{3}\\s?\\d{2}$/,\n  HR: /^([1-5]\\d{4}$)/,\n  HT: /^HT\\d{4}$/,\n  HU: fourDigit,\n  ID: fiveDigit,\n  IE: /^(?!.*(?:o))[A-Za-z]\\d[\\dw]\\s\\w{4}$/i,\n  IL: /^(\\d{5}|\\d{7})$/,\n  IN: /^((?!10|29|35|54|55|65|66|86|87|88|89)[1-9][0-9]{5})$/,\n  IR: /^(?!(\\d)\\1{3})[13-9]{4}[1346-9][013-9]{5}$/,\n  IS: threeDigit,\n  IT: fiveDigit,\n  JP: /^\\d{3}\\-\\d{4}$/,\n  KE: fiveDigit,\n  KR: /^(\\d{5}|\\d{6})$/,\n  LI: /^(948[5-9]|949[0-7])$/,\n  LT: /^LT\\-\\d{5}$/,\n  LU: fourDigit,\n  LV: /^LV\\-\\d{4}$/,\n  LK: fiveDigit,\n  MC: /^980\\d{2}$/,\n  MG: threeDigit,\n  MX: fiveDigit,\n  MT: /^[A-Za-z]{3}\\s{0,1}\\d{4}$/,\n  MY: fiveDigit,\n  NL: /^[1-9]\\d{3}\\s?(?!sa|sd|ss)[a-z]{2}$/i,\n  NO: fourDigit,\n  NP: /^(10|21|22|32|33|34|44|45|56|57)\\d{3}$|^(977)$/i,\n  NZ: fourDigit,\n  // https://www.pakpost.gov.pk/postcodes.php\n  PK: fiveDigit,\n  PL: /^\\d{2}\\-\\d{3}$/,\n  PR: /^00[679]\\d{2}([ -]\\d{4})?$/,\n  PT: /^\\d{4}\\-\\d{3}?$/,\n  RO: sixDigit,\n  RU: sixDigit,\n  SA: fiveDigit,\n  SE: /^[1-9]\\d{2}\\s?\\d{2}$/,\n  SG: sixDigit,\n  SI: fourDigit,\n  SK: /^\\d{3}\\s?\\d{2}$/,\n  TH: fiveDigit,\n  TN: fourDigit,\n  TW: /^\\d{3}(\\d{2,3})?$/,\n  UA: fiveDigit,\n  US: /^\\d{5}(-\\d{4})?$/,\n  ZA: fourDigit,\n  ZM: fiveDigit,\n};\n\nexport const locales = Object.keys(patterns);\n\nexport default function isPostalCode(str, locale) {\n  assertString(str);\n  if (locale in patterns) {\n    return patterns[locale].test(str);\n  } else if (locale === 'any') {\n    for (const key in patterns) {\n      // https://github.com/gotwarlost/istanbul/blob/master/ignoring-code-for-coverage.md#ignoring-code-for-coverage-purposes\n      // istanbul ignore else\n      if (patterns.hasOwnProperty(key)) {\n        const pattern = patterns[key];\n        if (pattern.test(str)) {\n          return true;\n        }\n      }\n    }\n    return false;\n  }\n  throw new Error(`Invalid locale '${locale}'`);\n}\n"
  },
  {
    "path": "src/lib/isRFC3339.js",
    "content": "import assertString from './util/assertString';\n\n/* Based on https://tools.ietf.org/html/rfc3339#section-5.6 */\n\nconst dateFullYear = /[0-9]{4}/;\nconst dateMonth = /(0[1-9]|1[0-2])/;\nconst dateMDay = /([12]\\d|0[1-9]|3[01])/;\n\nconst timeHour = /([01][0-9]|2[0-3])/;\nconst timeMinute = /[0-5][0-9]/;\nconst timeSecond = /([0-5][0-9]|60)/;\n\nconst timeSecFrac = /(\\.[0-9]+)?/;\nconst timeNumOffset = new RegExp(`[-+]${timeHour.source}:${timeMinute.source}`);\nconst timeOffset = new RegExp(`([zZ]|${timeNumOffset.source})`);\n\nconst partialTime = new RegExp(`${timeHour.source}:${timeMinute.source}:${timeSecond.source}${timeSecFrac.source}`);\n\nconst fullDate = new RegExp(`${dateFullYear.source}-${dateMonth.source}-${dateMDay.source}`);\nconst fullTime = new RegExp(`${partialTime.source}${timeOffset.source}`);\n\nconst rfc3339 = new RegExp(`^${fullDate.source}[ tT]${fullTime.source}$`);\n\nexport default function isRFC3339(str) {\n  assertString(str);\n  return rfc3339.test(str);\n}\n"
  },
  {
    "path": "src/lib/isRgbColor.js",
    "content": "/* eslint-disable prefer-rest-params */\nimport assertString from './util/assertString';\n\nconst rgbColor = /^rgb\\((([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5]),){2}([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\\)$/;\nconst rgbaColor = /^rgba\\((([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5]),){3}(0?\\.\\d\\d?|1(\\.0)?|0(\\.0)?)\\)$/;\nconst rgbColorPercent = /^rgb\\((([0-9]%|[1-9][0-9]%|100%),){2}([0-9]%|[1-9][0-9]%|100%)\\)$/;\nconst rgbaColorPercent = /^rgba\\((([0-9]%|[1-9][0-9]%|100%),){3}(0?\\.\\d\\d?|1(\\.0)?|0(\\.0)?)\\)$/;\nconst startsWithRgb = /^rgba?/;\n\nexport default function isRgbColor(str, options) {\n  assertString(str);\n  // default options to true for percent and false for spaces\n  let allowSpaces = false;\n  let includePercentValues = true;\n  if (typeof options !== 'object') {\n    if (arguments.length >= 2) {\n      includePercentValues = arguments[1];\n    }\n  } else {\n    allowSpaces = options.allowSpaces !== undefined ? options.allowSpaces : allowSpaces;\n    includePercentValues = options.includePercentValues !== undefined ?\n      options.includePercentValues : includePercentValues;\n  }\n\n  if (allowSpaces) {\n    // make sure it starts with continous rgba? without spaces before stripping\n    if (!startsWithRgb.test(str)) {\n      return false;\n    }\n    // strip all whitespace\n    str = str.replace(/\\s/g, '');\n  }\n\n  if (!includePercentValues) {\n    return rgbColor.test(str) || rgbaColor.test(str);\n  }\n\n  return rgbColor.test(str) ||\n    rgbaColor.test(str) ||\n    rgbColorPercent.test(str) ||\n    rgbaColorPercent.test(str);\n}\n"
  },
  {
    "path": "src/lib/isSemVer.js",
    "content": "import assertString from './util/assertString';\nimport multilineRegexp from './util/multilineRegex';\n\n/**\n * Regular Expression to match\n * semantic versioning (SemVer)\n * built from multi-line, multi-parts regexp\n * Reference: https://semver.org/\n */\nconst semanticVersioningRegex = multilineRegexp([\n  '^(0|[1-9]\\\\d*)\\\\.(0|[1-9]\\\\d*)\\\\.(0|[1-9]\\\\d*)',\n  '(?:-((?:0|[1-9]\\\\d*|\\\\d*[a-z-][0-9a-z-]*)(?:\\\\.(?:0|[1-9]\\\\d*|\\\\d*[a-z-][0-9a-z-]*))*))',\n  '?(?:\\\\+([0-9a-z-]+(?:\\\\.[0-9a-z-]+)*))?$',\n], 'i');\n\nexport default function isSemVer(str) {\n  assertString(str);\n\n  return semanticVersioningRegex.test(str);\n}\n"
  },
  {
    "path": "src/lib/isSlug.js",
    "content": "import assertString from './util/assertString';\n\nlet charsetRegex = /^[^\\s-_](?!.*?[-_]{2,})[a-z0-9-\\\\][^\\s]*[^-_\\s]$/;\n\nexport default function isSlug(str) {\n  assertString(str);\n  return (charsetRegex.test(str));\n}\n"
  },
  {
    "path": "src/lib/isStrongPassword.js",
    "content": "import merge from './util/merge';\nimport assertString from './util/assertString';\n\nconst upperCaseRegex = /^[A-Z]$/;\nconst lowerCaseRegex = /^[a-z]$/;\nconst numberRegex = /^[0-9]$/;\nconst symbolRegex = /^[-#!$@£%^&*()_+|~=`{}\\[\\]:\";'<>?,.\\/\\\\ ]$/;\n\nconst defaultOptions = {\n  minLength: 8,\n  minLowercase: 1,\n  minUppercase: 1,\n  minNumbers: 1,\n  minSymbols: 1,\n  returnScore: false,\n  pointsPerUnique: 1,\n  pointsPerRepeat: 0.5,\n  pointsForContainingLower: 10,\n  pointsForContainingUpper: 10,\n  pointsForContainingNumber: 10,\n  pointsForContainingSymbol: 10,\n};\n\n/* Counts number of occurrences of each char in a string\n * could be moved to util/ ?\n*/\nfunction countChars(str) {\n  let result = {};\n  Array.from(str).forEach((char) => {\n    let curVal = result[char];\n    if (curVal) {\n      result[char] += 1;\n    } else {\n      result[char] = 1;\n    }\n  });\n  return result;\n}\n\n/* Return information about a password */\nfunction analyzePassword(password) {\n  let charMap = countChars(password);\n  let analysis = {\n    length: password.length,\n    uniqueChars: Object.keys(charMap).length,\n    uppercaseCount: 0,\n    lowercaseCount: 0,\n    numberCount: 0,\n    symbolCount: 0,\n  };\n  Object.keys(charMap).forEach((char) => {\n    /* istanbul ignore else */\n    if (upperCaseRegex.test(char)) {\n      analysis.uppercaseCount += charMap[char];\n    } else if (lowerCaseRegex.test(char)) {\n      analysis.lowercaseCount += charMap[char];\n    } else if (numberRegex.test(char)) {\n      analysis.numberCount += charMap[char];\n    } else if (symbolRegex.test(char)) {\n      analysis.symbolCount += charMap[char];\n    }\n  });\n  return analysis;\n}\n\nfunction scorePassword(analysis, scoringOptions) {\n  let points = 0;\n  points += analysis.uniqueChars * scoringOptions.pointsPerUnique;\n  points += (analysis.length - analysis.uniqueChars) * scoringOptions.pointsPerRepeat;\n  if (analysis.lowercaseCount > 0) {\n    points += scoringOptions.pointsForContainingLower;\n  }\n  if (analysis.uppercaseCount > 0) {\n    points += scoringOptions.pointsForContainingUpper;\n  }\n  if (analysis.numberCount > 0) {\n    points += scoringOptions.pointsForContainingNumber;\n  }\n  if (analysis.symbolCount > 0) {\n    points += scoringOptions.pointsForContainingSymbol;\n  }\n  return points;\n}\n\nexport default function isStrongPassword(str, options = null) {\n  assertString(str);\n  const analysis = analyzePassword(str);\n  options = merge(options || {}, defaultOptions);\n  if (options.returnScore) {\n    return scorePassword(analysis, options);\n  }\n  return analysis.length >= options.minLength\n        && analysis.lowercaseCount >= options.minLowercase\n        && analysis.uppercaseCount >= options.minUppercase\n        && analysis.numberCount >= options.minNumbers\n        && analysis.symbolCount >= options.minSymbols;\n}\n"
  },
  {
    "path": "src/lib/isSurrogatePair.js",
    "content": "import assertString from './util/assertString';\n\nconst surrogatePair = /[\\uD800-\\uDBFF][\\uDC00-\\uDFFF]/;\n\nexport default function isSurrogatePair(str) {\n  assertString(str);\n  return surrogatePair.test(str);\n}\n"
  },
  {
    "path": "src/lib/isTaxID.js",
    "content": "import assertString from './util/assertString';\nimport * as algorithms from './util/algorithms';\nimport isDate from './isDate';\n\n/**\n * TIN Validation\n * Validates Tax Identification Numbers (TINs) from the US, EU member states and the United Kingdom.\n *\n * EU-UK:\n * National TIN validity is calculated using public algorithms as made available by DG TAXUD.\n *\n * See `https://ec.europa.eu/taxation_customs/tin/specs/FS-TIN%20Algorithms-Public.docx` for more information.\n *\n * US:\n * An Employer Identification Number (EIN), also known as a Federal Tax Identification Number,\n *  is used to identify a business entity.\n *\n * NOTES:\n *  - Prefix 47 is being reserved for future use\n *  - Prefixes 26, 27, 45, 46 and 47 were previously assigned by the Philadelphia campus.\n *\n * See `http://www.irs.gov/Businesses/Small-Businesses-&-Self-Employed/How-EINs-are-Assigned-and-Valid-EIN-Prefixes`\n * for more information.\n */\n\n// Locale functions\n\n/*\n * bg-BG validation function\n * (Edinen graždanski nomer (EGN/ЕГН), persons only)\n * Checks if birth date (first six digits) is valid and calculates check (last) digit\n */\nfunction bgBgCheck(tin) {\n  // Extract full year, normalize month and check birth date validity\n  let century_year = tin.slice(0, 2);\n  let month = parseInt(tin.slice(2, 4), 10);\n  if (month > 40) {\n    month -= 40;\n    century_year = `20${century_year}`;\n  } else if (month > 20) {\n    month -= 20;\n    century_year = `18${century_year}`;\n  } else {\n    century_year = `19${century_year}`;\n  }\n  if (month < 10) { month = `0${month}`; }\n  const date = `${century_year}/${month}/${tin.slice(4, 6)}`;\n  if (!isDate(date, 'YYYY/MM/DD')) { return false; }\n\n  // split digits into an array for further processing\n  const digits = tin.split('').map(a => parseInt(a, 10));\n\n  // Calculate checksum by multiplying digits with fixed values\n  const multip_lookup = [2, 4, 8, 5, 10, 9, 7, 3, 6];\n  let checksum = 0;\n  for (let i = 0; i < multip_lookup.length; i++) {\n    checksum += digits[i] * multip_lookup[i];\n  }\n  checksum = checksum % 11 === 10 ? 0 : checksum % 11;\n  return checksum === digits[9];\n}\n\n/**\n * Check if an input is a valid Canadian SIN (Social Insurance Number)\n *\n * The Social Insurance Number (SIN) is a 9 digit number that\n * you need to work in Canada or to have access to government programs and benefits.\n *\n * https://en.wikipedia.org/wiki/Social_Insurance_Number\n * https://www.canada.ca/en/employment-social-development/services/sin.html\n * https://www.codercrunch.com/challenge/819302488/sin-validator\n *\n * @param {string} input\n * @return {boolean}\n */\nfunction isCanadianSIN(input) {\n  const digitsArray = input.split('');\n  const even = digitsArray\n    .filter((_, idx) => idx % 2)\n    .map(i => Number(i) * 2)\n    .join('')\n    .split('');\n\n  const total = digitsArray\n    .filter((_, idx) => !(idx % 2))\n    .concat(even)\n    .map(i => Number(i))\n    .reduce((acc, cur) => acc + cur);\n\n  return (total % 10 === 0);\n}\n\n/*\n * cs-CZ validation function\n * (Rodné číslo (RČ), persons only)\n * Checks if birth date (first six digits) is valid and divisibility by 11\n * Material not in DG TAXUD document sourced from:\n * -`https://lorenc.info/3MA381/overeni-spravnosti-rodneho-cisla.htm`\n * -`https://www.mvcr.cz/clanek/rady-a-sluzby-dokumenty-rodne-cislo.aspx`\n */\nfunction csCzCheck(tin) {\n  tin = tin.replace(/\\W/, '');\n\n  // Extract full year from TIN length\n  let full_year = parseInt(tin.slice(0, 2), 10);\n  if (tin.length === 10) {\n    if (full_year < 54) {\n      full_year = `20${full_year}`;\n    } else {\n      full_year = `19${full_year}`;\n    }\n  } else {\n    if (tin.slice(6) === '000') { return false; } // Three-zero serial not assigned before 1954\n    if (full_year < 54) {\n      full_year = `19${full_year}`;\n    } else {\n      return false; // No 18XX years seen in any of the resources\n    }\n  }\n  // Add missing zero if needed\n  if (full_year.length === 3) {\n    full_year = [full_year.slice(0, 2), '0', full_year.slice(2)].join('');\n  }\n\n  // Extract month from TIN and normalize\n  let month = parseInt(tin.slice(2, 4), 10);\n  if (month > 50) {\n    month -= 50;\n  }\n  if (month > 20) {\n    // Month-plus-twenty was only introduced in 2004\n    if (parseInt(full_year, 10) < 2004) { return false; }\n    month -= 20;\n  }\n  if (month < 10) { month = `0${month}`; }\n\n  // Check date validity\n  const date = `${full_year}/${month}/${tin.slice(4, 6)}`;\n  if (!isDate(date, 'YYYY/MM/DD')) { return false; }\n\n  // Verify divisibility by 11\n  if (tin.length === 10) {\n    if (parseInt(tin, 10) % 11 !== 0) {\n      // Some numbers up to and including 1985 are still valid if\n      // check (last) digit equals 0 and modulo of first 9 digits equals 10\n      const checkdigit = parseInt(tin.slice(0, 9), 10) % 11;\n      if (parseInt(full_year, 10) < 1986 && checkdigit === 10) {\n        if (parseInt(tin.slice(9), 10) !== 0) { return false; }\n      } else {\n        return false;\n      }\n    }\n  }\n  return true;\n}\n\n/*\n * de-AT validation function\n * (Abgabenkontonummer, persons/entities)\n * Verify TIN validity by calling luhnCheck()\n */\nfunction deAtCheck(tin) {\n  return algorithms.luhnCheck(tin);\n}\n\n/*\n * de-DE validation function\n * (Steueridentifikationsnummer (Steuer-IdNr.), persons only)\n * Tests for single duplicate/triplicate value, then calculates ISO 7064 check (last) digit\n * Partial implementation of spec (same result with both algorithms always)\n */\nfunction deDeCheck(tin) {\n  // Split digits into an array for further processing\n  const digits = tin.split('').map(a => parseInt(a, 10));\n\n  // Fill array with strings of number positions\n  let occurrences = [];\n  for (let i = 0; i < digits.length - 1; i++) {\n    occurrences.push('');\n    for (let j = 0; j < digits.length - 1; j++) {\n      if (digits[i] === digits[j]) {\n        occurrences[i] += j;\n      }\n    }\n  }\n\n  // Remove digits with one occurrence and test for only one duplicate/triplicate\n  occurrences = occurrences.filter(a => a.length > 1);\n  if (occurrences.length !== 2 && occurrences.length !== 3) { return false; }\n\n  // In case of triplicate value only two digits are allowed next to each other\n  if (occurrences[0].length === 3) {\n    const trip_locations = occurrences[0].split('').map(a => parseInt(a, 10));\n    let recurrent = 0; // Amount of neighbor occurrences\n    for (let i = 0; i < trip_locations.length - 1; i++) {\n      if (trip_locations[i] + 1 === trip_locations[i + 1]) {\n        recurrent += 1;\n      }\n    }\n    if (recurrent === 2) {\n      return false;\n    }\n  }\n  return algorithms.iso7064Check(tin);\n}\n\n/*\n * dk-DK validation function\n * (CPR-nummer (personnummer), persons only)\n * Checks if birth date (first six digits) is valid and assigned to century (seventh) digit,\n * and calculates check (last) digit\n */\nfunction dkDkCheck(tin) {\n  tin = tin.replace(/\\W/, '');\n\n  // Extract year, check if valid for given century digit and add century\n  let year = parseInt(tin.slice(4, 6), 10);\n  const century_digit = tin.slice(6, 7);\n  switch (century_digit) {\n    case '0':\n    case '1':\n    case '2':\n    case '3':\n      year = `19${year}`;\n      break;\n    case '4':\n    case '9':\n      if (year < 37) {\n        year = `20${year}`;\n      } else {\n        year = `19${year}`;\n      }\n      break;\n    default:\n      if (year < 37) {\n        year = `20${year}`;\n      } else if (year > 58) {\n        year = `18${year}`;\n      } else {\n        return false;\n      }\n      break;\n  }\n  // Add missing zero if needed\n  if (year.length === 3) {\n    year = [year.slice(0, 2), '0', year.slice(2)].join('');\n  }\n  // Check date validity\n  const date = `${year}/${tin.slice(2, 4)}/${tin.slice(0, 2)}`;\n  if (!isDate(date, 'YYYY/MM/DD')) { return false; }\n\n  // Split digits into an array for further processing\n  const digits = tin.split('').map(a => parseInt(a, 10));\n  let checksum = 0;\n  let weight = 4;\n  // Multiply by weight and add to checksum\n  for (let i = 0; i < 9; i++) {\n    checksum += digits[i] * weight;\n    weight -= 1;\n    if (weight === 1) {\n      weight = 7;\n    }\n  }\n  checksum %= 11;\n  if (checksum === 1) { return false; }\n  return checksum === 0 ? digits[9] === 0 : digits[9] === 11 - checksum;\n}\n\n/*\n * el-CY validation function\n * (Arithmos Forologikou Mitroou (AFM/ΑΦΜ), persons only)\n * Verify TIN validity by calculating ASCII value of check (last) character\n */\nfunction elCyCheck(tin) {\n  // split digits into an array for further processing\n  const digits = tin.slice(0, 8).split('').map(a => parseInt(a, 10));\n\n  let checksum = 0;\n  // add digits in even places\n  for (let i = 1; i < digits.length; i += 2) {\n    checksum += digits[i];\n  }\n\n  // add digits in odd places\n  for (let i = 0; i < digits.length; i += 2) {\n    if (digits[i] < 2) {\n      checksum += 1 - digits[i];\n    } else {\n      checksum += (2 * (digits[i] - 2)) + 5;\n      if (digits[i] > 4) {\n        checksum += 2;\n      }\n    }\n  }\n  return String.fromCharCode((checksum % 26) + 65) === tin.charAt(8);\n}\n\n/*\n * el-GR validation function\n * (Arithmos Forologikou Mitroou (AFM/ΑΦΜ), persons/entities)\n * Verify TIN validity by calculating check (last) digit\n * Algorithm not in DG TAXUD document- sourced from:\n * - `http://epixeirisi.gr/%CE%9A%CE%A1%CE%99%CE%A3%CE%99%CE%9C%CE%91-%CE%98%CE%95%CE%9C%CE%91%CE%A4%CE%91-%CE%A6%CE%9F%CE%A1%CE%9F%CE%9B%CE%9F%CE%93%CE%99%CE%91%CE%A3-%CE%9A%CE%91%CE%99-%CE%9B%CE%9F%CE%93%CE%99%CE%A3%CE%A4%CE%99%CE%9A%CE%97%CE%A3/23791/%CE%91%CF%81%CE%B9%CE%B8%CE%BC%CF%8C%CF%82-%CE%A6%CE%BF%CF%81%CE%BF%CE%BB%CE%BF%CE%B3%CE%B9%CE%BA%CE%BF%CF%8D-%CE%9C%CE%B7%CF%84%CF%81%CF%8E%CE%BF%CF%85`\n */\nfunction elGrCheck(tin) {\n  // split digits into an array for further processing\n  const digits = tin.split('').map(a => parseInt(a, 10));\n\n  let checksum = 0;\n  for (let i = 0; i < 8; i++) {\n    checksum += digits[i] * (2 ** (8 - i));\n  }\n  return ((checksum % 11) % 10) === digits[8];\n}\n\n/*\n * en-GB validation function (should go here if needed)\n * (National Insurance Number (NINO) or Unique Taxpayer Reference (UTR),\n * persons/entities respectively)\n */\n\n/*\n * en-IE validation function\n * (Personal Public Service Number (PPS No), persons only)\n * Verify TIN validity by calculating check (second to last) character\n */\nfunction enIeCheck(tin) {\n  let checksum = algorithms.reverseMultiplyAndSum(tin.split('').slice(0, 7).map(a => parseInt(a, 10)), 8);\n  if (tin.length === 9 && tin[8] !== 'W') {\n    checksum += (tin[8].charCodeAt(0) - 64) * 9;\n  }\n\n  checksum %= 23;\n  if (checksum === 0) {\n    return tin[7].toUpperCase() === 'W';\n  }\n  return tin[7].toUpperCase() === String.fromCharCode(64 + checksum);\n}\n\n// Valid US IRS campus prefixes\nconst enUsCampusPrefix = {\n  andover: ['10', '12'],\n  atlanta: ['60', '67'],\n  austin: ['50', '53'],\n  brookhaven: ['01', '02', '03', '04', '05', '06', '11', '13', '14', '16', '21', '22', '23', '25', '34', '51', '52', '54', '55', '56', '57', '58', '59', '65'],\n  cincinnati: ['30', '32', '35', '36', '37', '38', '61'],\n  fresno: ['15', '24'],\n  internet: ['20', '26', '27', '45', '46', '47'],\n  kansas: ['40', '44'],\n  memphis: ['94', '95'],\n  ogden: ['80', '90'],\n  philadelphia: ['33', '39', '41', '42', '43', '46', '48', '62', '63', '64', '66', '68', '71', '72', '73', '74', '75', '76', '77', '81', '82', '83', '84', '85', '86', '87', '88', '91', '92', '93', '98', '99'],\n  sba: ['31'],\n};\n\n// Return an array of all US IRS campus prefixes\nfunction enUsGetPrefixes() {\n  const prefixes = [];\n\n  for (const location in enUsCampusPrefix) {\n    // https://github.com/gotwarlost/istanbul/blob/master/ignoring-code-for-coverage.md#ignoring-code-for-coverage-purposes\n    // istanbul ignore else\n    if (enUsCampusPrefix.hasOwnProperty(location)) {\n      prefixes.push(...enUsCampusPrefix[location]);\n    }\n  }\n\n  return prefixes;\n}\n\n/*\n * en-US validation function\n * Verify that the TIN starts with a valid IRS campus prefix\n */\nfunction enUsCheck(tin) {\n  return enUsGetPrefixes().indexOf(tin.slice(0, 2)) !== -1;\n}\n\n/*\n * es-AR validation function\n * Clave Única de Identificación Tributaria (CUIT/CUIL)\n * Sourced from:\n * - https://servicioscf.afip.gob.ar/publico/abc/ABCpaso2.aspx?id_nivel1=3036&id_nivel2=3040&p=Conceptos%20b%C3%A1sicos\n * - https://es.wikipedia.org/wiki/Clave_%C3%9Anica_de_Identificaci%C3%B3n_Tributaria\n */\n\nfunction esArCheck(tin) {\n  let accum = 0;\n  let digits = tin.split('');\n  let digit = parseInt(digits.pop(), 10);\n  for (let i = 0; i < digits.length; i++) {\n    accum += digits[9 - i] * (2 + (i % 6));\n  }\n  let verif = 11 - (accum % 11);\n  if (verif === 11) {\n    verif = 0;\n  } else if (verif === 10) {\n    verif = 9;\n  }\n  return digit === verif;\n}\n\n/*\n * es-ES validation function\n * (Documento Nacional de Identidad (DNI)\n * or Número de Identificación de Extranjero (NIE), persons only)\n * Verify TIN validity by calculating check (last) character\n */\nfunction esEsCheck(tin) {\n  // Split characters into an array for further processing\n  let chars = tin.toUpperCase().split('');\n\n  // Replace initial letter if needed\n  if (isNaN(parseInt(chars[0], 10)) && chars.length > 1) {\n    let lead_replace = 0;\n    switch (chars[0]) {\n      case 'Y':\n        lead_replace = 1;\n        break;\n      case 'Z':\n        lead_replace = 2;\n        break;\n      default:\n    }\n    chars.splice(0, 1, lead_replace);\n  // Fill with zeros if smaller than proper\n  } else {\n    while (chars.length < 9) {\n      chars.unshift(0);\n    }\n  }\n\n  // Calculate checksum and check according to lookup\n  const lookup = ['T', 'R', 'W', 'A', 'G', 'M', 'Y', 'F', 'P', 'D', 'X', 'B', 'N', 'J', 'Z', 'S', 'Q', 'V', 'H', 'L', 'C', 'K', 'E'];\n  chars = chars.join('');\n  let checksum = (parseInt(chars.slice(0, 8), 10) % 23);\n  return chars[8] === lookup[checksum];\n}\n\n/*\n * et-EE validation function\n * (Isikukood (IK), persons only)\n * Checks if birth date (century digit and six following) is valid and calculates check (last) digit\n * Material not in DG TAXUD document sourced from:\n * - `https://www.oecd.org/tax/automatic-exchange/crs-implementation-and-assistance/tax-identification-numbers/Estonia-TIN.pdf`\n */\nfunction etEeCheck(tin) {\n  // Extract year and add century\n  let full_year = tin.slice(1, 3);\n  const century_digit = tin.slice(0, 1);\n  switch (century_digit) {\n    case '1':\n    case '2':\n      full_year = `18${full_year}`;\n      break;\n    case '3':\n    case '4':\n      full_year = `19${full_year}`;\n      break;\n    default:\n      full_year = `20${full_year}`;\n      break;\n  }\n  // Check date validity\n  const date = `${full_year}/${tin.slice(3, 5)}/${tin.slice(5, 7)}`;\n  if (!isDate(date, 'YYYY/MM/DD')) { return false; }\n\n  // Split digits into an array for further processing\n  const digits = tin.split('').map(a => parseInt(a, 10));\n  let checksum = 0;\n  let weight = 1;\n  // Multiply by weight and add to checksum\n  for (let i = 0; i < 10; i++) {\n    checksum += digits[i] * weight;\n    weight += 1;\n    if (weight === 10) {\n      weight = 1;\n    }\n  }\n  // Do again if modulo 11 of checksum is 10\n  if (checksum % 11 === 10) {\n    checksum = 0;\n    weight = 3;\n    for (let i = 0; i < 10; i++) {\n      checksum += digits[i] * weight;\n      weight += 1;\n      if (weight === 10) {\n        weight = 1;\n      }\n    }\n    if (checksum % 11 === 10) { return digits[10] === 0; }\n  }\n\n  return checksum % 11 === digits[10];\n}\n\n/*\n * fi-FI validation function\n * (Henkilötunnus (HETU), persons only)\n * Checks if birth date (first six digits plus century symbol) is valid\n * and calculates check (last) digit\n */\nfunction fiFiCheck(tin) {\n  // Extract year and add century\n  let full_year = tin.slice(4, 6);\n  const century_symbol = tin.slice(6, 7);\n  switch (century_symbol) {\n    case '+':\n      full_year = `18${full_year}`;\n      break;\n    case '-':\n      full_year = `19${full_year}`;\n      break;\n    default:\n      full_year = `20${full_year}`;\n      break;\n  }\n  // Check date validity\n  const date = `${full_year}/${tin.slice(2, 4)}/${tin.slice(0, 2)}`;\n  if (!isDate(date, 'YYYY/MM/DD')) { return false; }\n\n  // Calculate check character\n  let checksum = parseInt((tin.slice(0, 6) + tin.slice(7, 10)), 10) % 31;\n  if (checksum < 10) { return checksum === parseInt(tin.slice(10), 10); }\n\n  checksum -= 10;\n  const letters_lookup = ['A', 'B', 'C', 'D', 'E', 'F', 'H', 'J', 'K', 'L', 'M', 'N', 'P', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y'];\n  return letters_lookup[checksum] === tin.slice(10);\n}\n\n/*\n * fr/nl-BE validation function\n * (Numéro national (N.N.), persons only)\n * Checks if birth date (first six digits) is valid and calculates check (last two) digits\n */\nfunction frBeCheck(tin) {\n  // Zero month/day value is acceptable\n  if (tin.slice(2, 4) !== '00' || tin.slice(4, 6) !== '00') {\n    // Extract date from first six digits of TIN\n    const date = `${tin.slice(0, 2)}/${tin.slice(2, 4)}/${tin.slice(4, 6)}`;\n    if (!isDate(date, 'YY/MM/DD')) { return false; }\n  }\n\n  let checksum = 97 - (parseInt(tin.slice(0, 9), 10) % 97);\n  const checkdigits = parseInt(tin.slice(9, 11), 10);\n  if (checksum !== checkdigits) {\n    checksum = 97 - (parseInt(`2${tin.slice(0, 9)}`, 10) % 97);\n    if (checksum !== checkdigits) {\n      return false;\n    }\n  }\n  return true;\n}\n\n/*\n * fr-FR validation function\n * (Numéro fiscal de référence (numéro SPI), persons only)\n * Verify TIN validity by calculating check (last three) digits\n */\nfunction frFrCheck(tin) {\n  tin = tin.replace(/\\s/g, '');\n  const checksum = parseInt(tin.slice(0, 10), 10) % 511;\n  const checkdigits = parseInt(tin.slice(10, 13), 10);\n  return checksum === checkdigits;\n}\n\n/*\n * fr/lb-LU validation function\n * (numéro d’identification personnelle, persons only)\n * Verify birth date validity and run Luhn and Verhoeff checks\n */\nfunction frLuCheck(tin) {\n  // Extract date and check validity\n  const date = `${tin.slice(0, 4)}/${tin.slice(4, 6)}/${tin.slice(6, 8)}`;\n  if (!isDate(date, 'YYYY/MM/DD')) { return false; }\n\n  // Run Luhn check\n  if (!algorithms.luhnCheck(tin.slice(0, 12))) { return false; }\n  // Remove Luhn check digit and run Verhoeff check\n  return algorithms.verhoeffCheck(`${tin.slice(0, 11)}${tin[12]}`);\n}\n\n/*\n * hr-HR validation function\n * (Osobni identifikacijski broj (OIB), persons/entities)\n * Verify TIN validity by calling iso7064Check(digits)\n */\nfunction hrHrCheck(tin) {\n  return algorithms.iso7064Check(tin);\n}\n\n/*\n * hu-HU validation function\n * (Adóazonosító jel, persons only)\n * Verify TIN validity by calculating check (last) digit\n */\nfunction huHuCheck(tin) {\n  // split digits into an array for further processing\n  const digits = tin.split('').map(a => parseInt(a, 10));\n\n  let checksum = 8;\n  for (let i = 1; i < 9; i++) {\n    checksum += digits[i] * (i + 1);\n  }\n  return checksum % 11 === digits[9];\n}\n\n/*\n * lt-LT validation function (should go here if needed)\n * (Asmens kodas, persons/entities respectively)\n * Current validation check is alias of etEeCheck- same format applies\n */\n\n/*\n * it-IT first/last name validity check\n * Accepts it-IT TIN-encoded names as a three-element character array and checks their validity\n * Due to lack of clarity between resources (\"Are only Italian consonants used?\n * What happens if a person has X in their name?\" etc.) only two test conditions\n * have been implemented:\n * Vowels may only be followed by other vowels or an X character\n * and X characters after vowels may only be followed by other X characters.\n */\nfunction itItNameCheck(name) {\n  // true at the first occurrence of a vowel\n  let vowelflag = false;\n\n  // true at the first occurrence of an X AFTER vowel\n  // (to properly handle last names with X as consonant)\n  let xflag = false;\n\n  for (let i = 0; i < 3; i++) {\n    if (!vowelflag && /[AEIOU]/.test(name[i])) {\n      vowelflag = true;\n    } else if (!xflag && vowelflag && (name[i] === 'X')) {\n      xflag = true;\n    } else if (i > 0) {\n      if (vowelflag && !xflag) {\n        if (!/[AEIOU]/.test(name[i])) { return false; }\n      }\n      if (xflag) {\n        if (!/X/.test(name[i])) { return false; }\n      }\n    }\n  }\n  return true;\n}\n\n/*\n * it-IT validation function\n * (Codice fiscale (TIN-IT), persons only)\n * Verify name, birth date and codice catastale validity\n * and calculate check character.\n * Material not in DG-TAXUD document sourced from:\n * `https://en.wikipedia.org/wiki/Italian_fiscal_code`\n */\nfunction itItCheck(tin) {\n  // Capitalize and split characters into an array for further processing\n  const chars = tin.toUpperCase().split('');\n\n  // Check first and last name validity calling itItNameCheck()\n  if (!itItNameCheck(chars.slice(0, 3))) { return false; }\n  if (!itItNameCheck(chars.slice(3, 6))) { return false; }\n\n  // Convert letters in number spaces back to numbers if any\n  const number_locations = [6, 7, 9, 10, 12, 13, 14];\n  const number_replace = {\n    L: '0',\n    M: '1',\n    N: '2',\n    P: '3',\n    Q: '4',\n    R: '5',\n    S: '6',\n    T: '7',\n    U: '8',\n    V: '9',\n  };\n  for (const i of number_locations) {\n    if (chars[i] in number_replace) {\n      chars.splice(i, 1, number_replace[chars[i]]);\n    }\n  }\n\n  // Extract month and day, and check date validity\n  const month_replace = {\n    A: '01',\n    B: '02',\n    C: '03',\n    D: '04',\n    E: '05',\n    H: '06',\n    L: '07',\n    M: '08',\n    P: '09',\n    R: '10',\n    S: '11',\n    T: '12',\n  };\n  let month = month_replace[chars[8]];\n\n  let day = parseInt(chars[9] + chars[10], 10);\n  if (day > 40) { day -= 40; }\n  if (day < 10) { day = `0${day}`; }\n\n  const date = `${chars[6]}${chars[7]}/${month}/${day}`;\n  if (!isDate(date, 'YY/MM/DD')) { return false; }\n\n  // Calculate check character by adding up even and odd characters as numbers\n  let checksum = 0;\n  for (let i = 1; i < chars.length - 1; i += 2) {\n    let char_to_int = parseInt(chars[i], 10);\n    if (isNaN(char_to_int)) {\n      char_to_int = chars[i].charCodeAt(0) - 65;\n    }\n    checksum += char_to_int;\n  }\n\n  const odd_convert = { // Maps of characters at odd places\n    A: 1,\n    B: 0,\n    C: 5,\n    D: 7,\n    E: 9,\n    F: 13,\n    G: 15,\n    H: 17,\n    I: 19,\n    J: 21,\n    K: 2,\n    L: 4,\n    M: 18,\n    N: 20,\n    O: 11,\n    P: 3,\n    Q: 6,\n    R: 8,\n    S: 12,\n    T: 14,\n    U: 16,\n    V: 10,\n    W: 22,\n    X: 25,\n    Y: 24,\n    Z: 23,\n    0: 1,\n    1: 0,\n  };\n  for (let i = 0; i < chars.length - 1; i += 2) {\n    let char_to_int = 0;\n    if (chars[i] in odd_convert) {\n      char_to_int = odd_convert[chars[i]];\n    } else {\n      let multiplier = parseInt(chars[i], 10);\n      char_to_int = (2 * multiplier) + 1;\n      if (multiplier > 4) {\n        char_to_int += 2;\n      }\n    }\n    checksum += char_to_int;\n  }\n\n  if (String.fromCharCode(65 + (checksum % 26)) !== chars[15]) { return false; }\n  return true;\n}\n\n/*\n * lv-LV validation function\n * (Personas kods (PK), persons only)\n * Check validity of birth date and calculate check (last) digit\n * Support only for old format numbers (not starting with '32', issued before 2017/07/01)\n * Material not in DG TAXUD document sourced from:\n * `https://boot.ritakafija.lv/forums/index.php?/topic/88314-personas-koda-algoritms-%C4%8Deksumma/`\n */\nfunction lvLvCheck(tin) {\n  tin = tin.replace(/\\W/, '');\n  // Extract date from TIN\n  const day = tin.slice(0, 2);\n  if (day !== '32') { // No date/checksum check if new format\n    const month = tin.slice(2, 4);\n    if (month !== '00') { // No date check if unknown month\n      let full_year = tin.slice(4, 6);\n      switch (tin[6]) {\n        case '0':\n          full_year = `18${full_year}`;\n          break;\n        case '1':\n          full_year = `19${full_year}`;\n          break;\n        default:\n          full_year = `20${full_year}`;\n          break;\n      }\n      // Check date validity\n      const date = `${full_year}/${tin.slice(2, 4)}/${day}`;\n      if (!isDate(date, 'YYYY/MM/DD')) { return false; }\n    }\n\n    // Calculate check digit\n    let checksum = 1101;\n    const multip_lookup = [1, 6, 3, 7, 9, 10, 5, 8, 4, 2];\n    for (let i = 0; i < tin.length - 1; i++) {\n      checksum -= parseInt(tin[i], 10) * multip_lookup[i];\n    }\n    return (parseInt(tin[10], 10) === checksum % 11);\n  }\n  return true;\n}\n\n/*\n * mt-MT validation function\n * (Identity Card Number or Unique Taxpayer Reference, persons/entities)\n * Verify Identity Card Number structure (no other tests found)\n */\nfunction mtMtCheck(tin) {\n  if (tin.length !== 9) { // No tests for UTR\n    let chars = tin.toUpperCase().split('');\n    // Fill with zeros if smaller than proper\n    while (chars.length < 8) {\n      chars.unshift(0);\n    }\n    // Validate format according to last character\n    switch (tin[7]) {\n      case 'A':\n      case 'P':\n        if (parseInt(chars[6], 10) === 0) { return false; }\n        break;\n      default: {\n        const first_part = parseInt(chars.join('').slice(0, 5), 10);\n        if (first_part > 32000) { return false; }\n        const second_part = parseInt(chars.join('').slice(5, 7), 10);\n        if (first_part === second_part) { return false; }\n      }\n    }\n  }\n  return true;\n}\n\n/*\n * nl-NL validation function\n * (Burgerservicenummer (BSN) or Rechtspersonen Samenwerkingsverbanden Informatie Nummer (RSIN),\n * persons/entities respectively)\n * Verify TIN validity by calculating check (last) digit (variant of MOD 11)\n */\nfunction nlNlCheck(tin) {\n  return algorithms.reverseMultiplyAndSum(tin.split('').slice(0, 8).map(a => parseInt(a, 10)), 9) % 11 === parseInt(tin[8], 10);\n}\n\n/*\n * pl-PL validation function\n * (Powszechny Elektroniczny System Ewidencji Ludności (PESEL)\n * or Numer identyfikacji podatkowej (NIP), persons/entities)\n * Verify TIN validity by validating birth date (PESEL) and calculating check (last) digit\n */\nfunction plPlCheck(tin) {\n  // NIP\n  if (tin.length === 10) {\n    // Calculate last digit by multiplying with lookup\n    const lookup = [6, 5, 7, 2, 3, 4, 5, 6, 7];\n    let checksum = 0;\n    for (let i = 0; i < lookup.length; i++) {\n      checksum += parseInt(tin[i], 10) * lookup[i];\n    }\n    checksum %= 11;\n    if (checksum === 10) { return false; }\n    return (checksum === parseInt(tin[9], 10));\n  }\n\n  // PESEL\n  // Extract full year using month\n  let full_year = tin.slice(0, 2);\n  let month = parseInt(tin.slice(2, 4), 10);\n  if (month > 80) {\n    full_year = `18${full_year}`;\n    month -= 80;\n  } else if (month > 60) {\n    full_year = `22${full_year}`;\n    month -= 60;\n  } else if (month > 40) {\n    full_year = `21${full_year}`;\n    month -= 40;\n  } else if (month > 20) {\n    full_year = `20${full_year}`;\n    month -= 20;\n  } else {\n    full_year = `19${full_year}`;\n  }\n  // Add leading zero to month if needed\n  if (month < 10) { month = `0${month}`; }\n  // Check date validity\n  const date = `${full_year}/${month}/${tin.slice(4, 6)}`;\n  if (!isDate(date, 'YYYY/MM/DD')) { return false; }\n\n  // Calculate last digit by multiplying with odd one-digit numbers except 5\n  let checksum = 0;\n  let multiplier = 1;\n  for (let i = 0; i < tin.length - 1; i++) {\n    checksum += (parseInt(tin[i], 10) * multiplier) % 10;\n    multiplier += 2;\n    if (multiplier > 10) {\n      multiplier = 1;\n    } else if (multiplier === 5) {\n      multiplier += 2;\n    }\n  }\n  checksum = 10 - (checksum % 10);\n  return checksum === parseInt(tin[10], 10);\n}\n\n/*\n * pt-BR validation function\n * (Cadastro de Pessoas Físicas (CPF, persons)\n * Cadastro Nacional de Pessoas Jurídicas (CNPJ, entities)\n * Both inputs will be validated.\n * CPF accepts formatted (XXX.XXX.XXX-XX) and unformatted input;\n * formatting is stripped before validation.\n * CNPJ supports both numeric (legacy) and alphanumeric format (starting July 2026).\n */\n\n/**\n * Convert a CNPJ character to its numeric value for check digit calculation.\n * Numbers 0-9 map to values 0-9, letters A-Z map to values 17-42.\n * This is done by subtracting 48 from the ASCII code.\n */\nfunction cnpjCharToValue(char) {\n  return char.charCodeAt(0) - 48;\n}\n\n/**\n * Validate CNPJ (both numeric and alphanumeric formats).\n * Algorithm: module 11 with weights 2-9 from right to left.\n */\nfunction validateCnpj(cnpj) {\n  // Get the 12 identifier characters and 2 check digits\n  const identifiers = cnpj.substring(0, 12).toUpperCase();\n  const checkDigits = cnpj.substring(12);\n\n  // Reject CNPJs with all same characters (e.g., '00000000000000', 'AAAAAAAAAAAAAA')\n  if (/^(.)\\1+$/.test(cnpj.toUpperCase())) {\n    return false;\n  }\n\n  // Calculate first check digit\n  let sum = 0;\n  let weight = 5;\n  for (let i = 0; i < 12; i++) {\n    sum += cnpjCharToValue(identifiers.charAt(i)) * weight;\n    weight = weight === 2 ? 9 : weight - 1;\n  }\n  let remainder = sum % 11;\n  let firstDV = remainder < 2 ? 0 : 11 - remainder;\n\n  if (firstDV !== parseInt(checkDigits.charAt(0), 10)) {\n    return false;\n  }\n\n  // Calculate second check digit (includes first check digit)\n  sum = 0;\n  weight = 6;\n  for (let i = 0; i < 12; i++) {\n    sum += cnpjCharToValue(identifiers.charAt(i)) * weight;\n    weight = weight === 2 ? 9 : weight - 1;\n  }\n  sum += firstDV * 2;\n  remainder = sum % 11;\n  let secondDV = remainder < 2 ? 0 : 11 - remainder;\n\n  return secondDV === parseInt(checkDigits.charAt(1), 10);\n}\n\nfunction ptBrCheck(tin) {\n  // Strip CPF formatting (XXX.XXX.XXX-XX)\n  tin = tin.replace(/[.\\-/]/g, '');\n\n  if (tin.length === 11) {\n    let sum;\n    let remainder;\n    sum = 0;\n\n    if ( // Reject known invalid CPFs\n      tin === '11111111111' ||\n      tin === '22222222222' ||\n      tin === '33333333333' ||\n      tin === '44444444444' ||\n      tin === '55555555555' ||\n      tin === '66666666666' ||\n      tin === '77777777777' ||\n      tin === '88888888888' ||\n      tin === '99999999999' ||\n      tin === '00000000000'\n    ) return false;\n\n    for (let i = 1; i <= 9; i++) sum += parseInt(tin.substring(i - 1, i), 10) * (11 - i);\n    remainder = (sum * 10) % 11;\n    if (remainder === 10) remainder = 0;\n    if (remainder !== parseInt(tin.substring(9, 10), 10)) return false;\n    sum = 0;\n\n    for (let i = 1; i <= 10; i++) sum += parseInt(tin.substring(i - 1, i), 10) * (12 - i);\n    remainder = (sum * 10) % 11;\n    if (remainder === 10) remainder = 0;\n    if (remainder !== parseInt(tin.substring(10, 11), 10)) return false;\n\n    return true;\n  }\n\n  // CNPJ validation (supports both numeric and alphanumeric formats)\n  return validateCnpj(tin);\n}\n\n/*\n * pt-PT validation function\n * (Número de identificação fiscal (NIF), persons/entities)\n * Verify TIN validity by calculating check (last) digit (variant of MOD 11)\n */\nfunction ptPtCheck(tin) {\n  let checksum = 11 - (algorithms.reverseMultiplyAndSum(tin.split('').slice(0, 8).map(a => parseInt(a, 10)), 9) % 11);\n  if (checksum > 9) { return parseInt(tin[8], 10) === 0; }\n  return checksum === parseInt(tin[8], 10);\n}\n\n/*\n * ro-RO validation function\n * (Cod Numeric Personal (CNP) or Cod de înregistrare fiscală (CIF),\n * persons only)\n * Verify CNP validity by calculating check (last) digit (test not found for CIF)\n * Material not in DG TAXUD document sourced from:\n * `https://en.wikipedia.org/wiki/National_identification_number#Romania`\n */\nfunction roRoCheck(tin) {\n  if (tin.slice(0, 4) !== '9000') { // No test found for this format\n    // Extract full year using century digit if possible\n    let full_year = tin.slice(1, 3);\n    switch (tin[0]) {\n      case '1':\n      case '2':\n        full_year = `19${full_year}`;\n        break;\n      case '3':\n      case '4':\n        full_year = `18${full_year}`;\n        break;\n      case '5':\n      case '6':\n        full_year = `20${full_year}`;\n        break;\n      default:\n    }\n\n    // Check date validity\n    const date = `${full_year}/${tin.slice(3, 5)}/${tin.slice(5, 7)}`;\n    if (date.length === 8) {\n      if (!isDate(date, 'YY/MM/DD')) { return false; }\n    } else if (!isDate(date, 'YYYY/MM/DD')) { return false; }\n\n    // Calculate check digit\n    const digits = tin.split('').map(a => parseInt(a, 10));\n    const multipliers = [2, 7, 9, 1, 4, 6, 3, 5, 8, 2, 7, 9];\n    let checksum = 0;\n    for (let i = 0; i < multipliers.length; i++) {\n      checksum += digits[i] * multipliers[i];\n    }\n    if (checksum % 11 === 10) { return digits[12] === 1; }\n    return digits[12] === checksum % 11;\n  }\n  return true;\n}\n\n/*\n * sk-SK validation function\n * (Rodné číslo (RČ) or bezvýznamové identifikačné číslo (BIČ), persons only)\n * Checks validity of pre-1954 birth numbers (rodné číslo) only\n * Due to the introduction of the pseudo-random BIČ it is not possible to test\n * post-1954 birth numbers without knowing whether they are BIČ or RČ beforehand\n */\nfunction skSkCheck(tin) {\n  if (tin.length === 9) {\n    tin = tin.replace(/\\W/, '');\n    if (tin.slice(6) === '000') { return false; } // Three-zero serial not assigned before 1954\n\n    // Extract full year from TIN length\n    let full_year = parseInt(tin.slice(0, 2), 10);\n    if (full_year > 53) { return false; }\n    if (full_year < 10) {\n      full_year = `190${full_year}`;\n    } else {\n      full_year = `19${full_year}`;\n    }\n\n    // Extract month from TIN and normalize\n    let month = parseInt(tin.slice(2, 4), 10);\n    if (month > 50) {\n      month -= 50;\n    }\n    if (month < 10) { month = `0${month}`; }\n\n    // Check date validity\n    const date = `${full_year}/${month}/${tin.slice(4, 6)}`;\n    if (!isDate(date, 'YYYY/MM/DD')) { return false; }\n  }\n  return true;\n}\n\n/*\n * sl-SI validation function\n * (Davčna številka, persons/entities)\n * Verify TIN validity by calculating check (last) digit (variant of MOD 11)\n */\nfunction slSiCheck(tin) {\n  let checksum = 11 - (algorithms.reverseMultiplyAndSum(tin.split('').slice(0, 7).map(a => parseInt(a, 10)), 8) % 11);\n  if (checksum === 10) { return parseInt(tin[7], 10) === 0; }\n  return checksum === parseInt(tin[7], 10);\n}\n\n/*\n * sv-SE validation function\n * (Personnummer or samordningsnummer, persons only)\n * Checks validity of birth date and calls luhnCheck() to validate check (last) digit\n */\nfunction svSeCheck(tin) {\n  // Make copy of TIN and normalize to two-digit year form\n  let tin_copy = tin.slice(0);\n  if (tin.length > 11) {\n    tin_copy = tin_copy.slice(2);\n  }\n\n  // Extract date of birth\n  let full_year = '';\n  const month = tin_copy.slice(2, 4);\n  let day = parseInt(tin_copy.slice(4, 6), 10);\n  if (tin.length > 11) {\n    full_year = tin.slice(0, 4);\n  } else {\n    full_year = tin.slice(0, 2);\n    if (tin.length === 11 && day < 60) {\n      // Extract full year from centenarian symbol\n      // Should work just fine until year 10000 or so\n      let current_year = new Date().getFullYear().toString();\n      const current_century = parseInt(current_year.slice(0, 2), 10);\n      current_year = parseInt(current_year, 10);\n      if (tin[6] === '-') {\n        if (parseInt(`${current_century}${full_year}`, 10) > current_year) {\n          full_year = `${current_century - 1}${full_year}`;\n        } else {\n          full_year = `${current_century}${full_year}`;\n        }\n      } else {\n        full_year = `${current_century - 1}${full_year}`;\n        if (current_year - parseInt(full_year, 10) < 100) { return false; }\n      }\n    }\n  }\n\n  // Normalize day and check date validity\n  if (day > 60) { day -= 60; }\n  if (day < 10) { day = `0${day}`; }\n  const date = `${full_year}/${month}/${day}`;\n  if (date.length === 8) {\n    if (!isDate(date, 'YY/MM/DD')) { return false; }\n  } else if (!isDate(date, 'YYYY/MM/DD')) { return false; }\n\n  return algorithms.luhnCheck(tin.replace(/\\W/, ''));\n}\n\n/**\n * uk-UA validation function\n * Verify TIN validity by calculating check (last) digit (variant of MOD 11)\n */\nfunction ukUaCheck(tin) {\n  // Calculate check digit\n  const digits = tin.split('').map(a => parseInt(a, 10));\n  const multipliers = [-1, 5, 7, 9, 4, 6, 10, 5, 7];\n  let checksum = 0;\n  for (let i = 0; i < multipliers.length; i++) {\n    checksum += digits[i] * multipliers[i];\n  }\n  return checksum % 11 === 10 ? digits[9] === 0 : digits[9] === checksum % 11;\n}\n\n// Locale lookup objects\n\n/*\n * Tax id regex formats for various locales\n *\n * Where not explicitly specified in DG-TAXUD document both\n * uppercase and lowercase letters are acceptable.\n */\nconst taxIdFormat = {\n  'bg-BG': /^\\d{10}$/,\n  'cs-CZ': /^\\d{6}\\/{0,1}\\d{3,4}$/,\n  'de-AT': /^\\d{9}$/,\n  'de-DE': /^[1-9]\\d{10}$/,\n  'dk-DK': /^\\d{6}-{0,1}\\d{4}$/,\n  'el-CY': /^[09]\\d{7}[A-Z]$/,\n  'el-GR': /^([0-4]|[7-9])\\d{8}$/,\n  'en-CA': /^\\d{9}$/,\n  'en-GB': /^\\d{10}$|^(?!GB|NK|TN|ZZ)(?![DFIQUV])[A-Z](?![DFIQUVO])[A-Z]\\d{6}[ABCD ]$/i,\n  'en-IE': /^\\d{7}[A-W][A-IW]{0,1}$/i,\n  'en-US': /^\\d{2}[- ]{0,1}\\d{7}$/,\n  'es-AR': /(20|23|24|27|30|33|34)[0-9]{8}[0-9]/,\n  'es-ES': /^(\\d{0,8}|[XYZKLM]\\d{7})[A-HJ-NP-TV-Z]$/i,\n  'et-EE': /^[1-6]\\d{6}(00[1-9]|0[1-9][0-9]|[1-6][0-9]{2}|70[0-9]|710)\\d$/,\n  'fi-FI': /^\\d{6}[-+A]\\d{3}[0-9A-FHJ-NPR-Y]$/i,\n  'fr-BE': /^\\d{11}$/,\n  'fr-FR': /^[0-3]\\d{12}$|^[0-3]\\d\\s\\d{2}(\\s\\d{3}){3}$/, // Conforms both to official spec and provided example\n  'fr-LU': /^\\d{13}$/,\n  'hr-HR': /^\\d{11}$/,\n  'hu-HU': /^8\\d{9}$/,\n  'it-IT': /^[A-Z]{6}[L-NP-V0-9]{2}[A-EHLMPRST][L-NP-V0-9]{2}[A-ILMZ][L-NP-V0-9]{3}[A-Z]$/i,\n  'lv-LV': /^\\d{6}-{0,1}\\d{5}$/, // Conforms both to DG TAXUD spec and original research\n  'mt-MT': /^\\d{3,7}[APMGLHBZ]$|^([1-8])\\1\\d{7}$/i,\n  'nl-NL': /^\\d{9}$/,\n  'pl-PL': /^\\d{10,11}$/,\n  'pt-BR': /(?:^\\d{3}\\.\\d{3}\\.\\d{3}-\\d{2}$)|(?:^\\d{11}$)|(?:^[A-Z0-9]{12}\\d{2}$)/i,\n  'pt-PT': /^\\d{9}$/,\n  'ro-RO': /^\\d{13}$/,\n  'sk-SK': /^\\d{6}\\/{0,1}\\d{3,4}$/,\n  'sl-SI': /^[1-9]\\d{7}$/,\n  'sv-SE': /^(\\d{6}[-+]{0,1}\\d{4}|(18|19|20)\\d{6}[-+]{0,1}\\d{4})$/,\n  'uk-UA': /^\\d{10}$/,\n};\n// taxIdFormat locale aliases\ntaxIdFormat['lb-LU'] = taxIdFormat['fr-LU'];\ntaxIdFormat['lt-LT'] = taxIdFormat['et-EE'];\ntaxIdFormat['nl-BE'] = taxIdFormat['fr-BE'];\ntaxIdFormat['fr-CA'] = taxIdFormat['en-CA'];\n\n// Algorithmic tax id check functions for various locales\nconst taxIdCheck = {\n  'bg-BG': bgBgCheck,\n  'cs-CZ': csCzCheck,\n  'de-AT': deAtCheck,\n  'de-DE': deDeCheck,\n  'dk-DK': dkDkCheck,\n  'el-CY': elCyCheck,\n  'el-GR': elGrCheck,\n  'en-CA': isCanadianSIN,\n  'en-IE': enIeCheck,\n  'en-US': enUsCheck,\n  'es-AR': esArCheck,\n  'es-ES': esEsCheck,\n  'et-EE': etEeCheck,\n  'fi-FI': fiFiCheck,\n  'fr-BE': frBeCheck,\n  'fr-FR': frFrCheck,\n  'fr-LU': frLuCheck,\n  'hr-HR': hrHrCheck,\n  'hu-HU': huHuCheck,\n  'it-IT': itItCheck,\n  'lv-LV': lvLvCheck,\n  'mt-MT': mtMtCheck,\n  'nl-NL': nlNlCheck,\n  'pl-PL': plPlCheck,\n  'pt-BR': ptBrCheck,\n  'pt-PT': ptPtCheck,\n  'ro-RO': roRoCheck,\n  'sk-SK': skSkCheck,\n  'sl-SI': slSiCheck,\n  'sv-SE': svSeCheck,\n  'uk-UA': ukUaCheck,\n};\n// taxIdCheck locale aliases\ntaxIdCheck['lb-LU'] = taxIdCheck['fr-LU'];\ntaxIdCheck['lt-LT'] = taxIdCheck['et-EE'];\ntaxIdCheck['nl-BE'] = taxIdCheck['fr-BE'];\ntaxIdCheck['fr-CA'] = taxIdCheck['en-CA'];\n\n// Regexes for locales where characters should be omitted before checking format\nconst allsymbols = /[-\\\\\\/!@#$%\\^&\\*\\(\\)\\+\\=\\[\\]]+/g;\nconst sanitizeRegexes = {\n  'de-AT': allsymbols,\n  'de-DE': /[\\/\\\\]/g,\n  'fr-BE': allsymbols,\n};\n// sanitizeRegexes locale aliases\nsanitizeRegexes['nl-BE'] = sanitizeRegexes['fr-BE'];\n\n/*\n * Validator function\n * Return true if the passed string is a valid tax identification number\n * for the specified locale.\n * Throw an error exception if the locale is not supported.\n */\nexport default function isTaxID(str, locale = 'en-US') {\n  assertString(str);\n  // Copy TIN to avoid replacement if sanitized\n  let strcopy = str.slice(0);\n\n  if (locale in taxIdFormat) {\n    if (locale in sanitizeRegexes) {\n      strcopy = strcopy.replace(sanitizeRegexes[locale], '');\n    }\n    if (!taxIdFormat[locale].test(strcopy)) {\n      return false;\n    }\n\n    if (locale in taxIdCheck) {\n      return taxIdCheck[locale](strcopy);\n    }\n    // Fallthrough; not all locales have algorithmic checks\n    return true;\n  }\n  throw new Error(`Invalid locale '${locale}'`);\n}\n"
  },
  {
    "path": "src/lib/isTime.js",
    "content": "import merge from './util/merge';\n\nconst default_time_options = {\n  hourFormat: 'hour24',\n  mode: 'default',\n};\n\nconst formats = {\n  hour24: {\n    default: /^([01]?[0-9]|2[0-3]):([0-5][0-9])$/,\n    withSeconds: /^([01]?[0-9]|2[0-3]):([0-5][0-9]):([0-5][0-9])$/,\n    withOptionalSeconds: /^([01]?[0-9]|2[0-3]):([0-5][0-9])(?::([0-5][0-9]))?$/,\n  },\n  hour12: {\n    default: /^(0?[1-9]|1[0-2]):([0-5][0-9]) (A|P)M$/,\n    withSeconds: /^(0?[1-9]|1[0-2]):([0-5][0-9]):([0-5][0-9]) (A|P)M$/,\n    withOptionalSeconds: /^(0?[1-9]|1[0-2]):([0-5][0-9])(?::([0-5][0-9]))? (A|P)M$/,\n  },\n};\n\nexport default function isTime(input, options) {\n  options = merge(options, default_time_options);\n  if (typeof input !== 'string') return false;\n  return formats[options.hourFormat][options.mode].test(input);\n}\n"
  },
  {
    "path": "src/lib/isULID.js",
    "content": "import assertString from './util/assertString';\n\nexport default function isULID(str) {\n  assertString(str);\n  return /^[0-7][0-9A-HJKMNP-TV-Z]{25}$/i.test(str);\n}\n"
  },
  {
    "path": "src/lib/isURL.js",
    "content": "import assertString from './util/assertString';\nimport checkHost from './util/checkHost';\nimport includes from './util/includesString';\n\nimport isFQDN from './isFQDN';\nimport isIP from './isIP';\nimport merge from './util/merge';\n\n/*\noptions for isURL method\n\nprotocols - valid protocols can be modified with this option.\nrequire_tld - If set to false isURL will not check if the URL's host includes a top-level domain.\nrequire_protocol - if set to true isURL will return false if protocol is not present in the URL.\nrequire_host - if set to false isURL will not check if host is present in the URL.\nrequire_port - if set to true isURL will check if port is present in the URL.\nrequire_valid_protocol - isURL will check if the URL's protocol is present in the protocols option.\nallow_underscores - if set to true, the validator will allow underscores in the URL.\nhost_whitelist - if set to an array of strings or regexp, and the domain matches none of the strings\n                 defined in it, the validation fails.\nhost_blacklist - if set to an array of strings or regexp, and the domain matches any of the strings\n                 defined in it, the validation fails.\nallow_trailing_dot - if set to true, the validator will allow the domain to end with\n                     a `.` character.\nallow_protocol_relative_urls - if set to true protocol relative URLs will be allowed.\nallow_fragments - if set to false isURL will return false if fragments are present.\nallow_query_components - if set to false isURL will return false if query components are present.\ndisallow_auth - if set to true, the validator will fail if the URL contains an authentication\n                component, e.g. `http://username:password@example.com`\nvalidate_length - if set to false isURL will skip string length validation. `max_allowed_length`\n                  will be ignored if this is set as `false`.\nmax_allowed_length - if set, isURL will not allow URLs longer than the specified value (default is\n                     2084 that IE maximum URL length).\n\n*/\n\n\nconst default_url_options = {\n  protocols: ['http', 'https', 'ftp'],\n  require_tld: true,\n  require_protocol: false,\n  require_host: true,\n  require_port: false,\n  require_valid_protocol: true,\n  allow_underscores: false,\n  allow_trailing_dot: false,\n  allow_protocol_relative_urls: false,\n  allow_fragments: true,\n  allow_query_components: true,\n  validate_length: true,\n  max_allowed_length: 2084,\n};\n\nconst wrapped_ipv6 = /^\\[([^\\]]+)\\](?::([0-9]+))?$/;\n\nexport default function isURL(url, options) {\n  assertString(url);\n  if (!url || /[\\s<>]/.test(url)) {\n    return false;\n  }\n  if (url.indexOf('mailto:') === 0) {\n    return false;\n  }\n  options = merge(options, default_url_options);\n\n  if (options.validate_length && url.length > options.max_allowed_length) {\n    return false;\n  }\n\n  if (!options.allow_fragments && includes(url, '#')) {\n    return false;\n  }\n\n  if (!options.allow_query_components && (includes(url, '?') || includes(url, '&'))) {\n    return false;\n  }\n\n  let protocol, auth, host, hostname, port, port_str, split, ipv6;\n\n  split = url.split('#');\n  url = split.shift();\n\n  split = url.split('?');\n  url = split.shift();\n\n  // Replaced the 'split(\"://\")' logic with a regex to match the protocol.\n  // This correctly identifies schemes like `javascript:` which don't use `//`.\n  // However, we need to be careful not to confuse authentication credentials (user:password@host)\n  // with protocols. A colon before an @ symbol might be part of auth, not a protocol separator.\n  const protocol_match = url.match(/^([a-z][a-z0-9+\\-.]*):/i);\n  let had_explicit_protocol = false;\n\n  const cleanUpProtocol = (potential_protocol) => {\n    had_explicit_protocol = true;\n    protocol = potential_protocol.toLowerCase();\n\n    if (options.require_valid_protocol && options.protocols.indexOf(protocol) === -1) {\n      // The identified protocol is not in the allowed list.\n      return false;\n    }\n\n    // Remove the protocol from the URL string.\n    return url.substring(protocol_match[0].length);\n  };\n\n  if (protocol_match) {\n    const potential_protocol = protocol_match[1];\n    const after_colon = url.substring(protocol_match[0].length);\n\n    // Check if what follows looks like authentication credentials (user:password@host)\n    // rather than a protocol. This happens when:\n    // 1. There's no `//` after the colon (protocols like `http://` have this)\n    // 2. There's an `@` symbol before any `/`\n    // 3. The part before `@` contains only valid auth characters (alphanumeric, -, _, ., %, :)\n    const starts_with_slashes = after_colon.slice(0, 2) === '//';\n\n    if (!starts_with_slashes) {\n      const first_slash_position = after_colon.indexOf('/');\n      const before_slash = first_slash_position === -1\n        ? after_colon\n        : after_colon.substring(0, first_slash_position);\n      const at_position = before_slash.indexOf('@');\n\n      if (at_position !== -1) {\n        const before_at = before_slash.substring(0, at_position);\n        const valid_auth_regex = /^[a-zA-Z0-9\\-_.%:]*$/;\n        const is_valid_auth = valid_auth_regex.test(before_at);\n\n        // Check if this contains URL-encoded content that could be malicious\n        // For example: javascript:%61%6c%65%72%74%28%31%29@example.com\n        // The encoded part decodes to: alert(1)\n        const has_encoded_content = /%[0-9a-fA-F]{2}/.test(before_at);\n\n        if (is_valid_auth && !has_encoded_content) {\n          // This looks like authentication (e.g., user:password@host), not a protocol\n          if (options.require_protocol) {\n            return false;\n          }\n\n          // Don't consume the colon; let the auth parsing handle it later\n        } else {\n          // This looks like a malicious protocol (e.g., javascript:alert();@host)\n          // or URL-encoded protocol handler (e.g., javascript:%61%6c%65%72%74%28%31%29@host)\n          url = cleanUpProtocol(potential_protocol);\n\n          if (url === false) {\n            return false;\n          }\n        }\n      } else {\n        // No @ symbol found. Check if this could be a port number instead of a protocol.\n        // If what's after the colon is numeric (or starts with a digit and contains only\n        // valid port characters until a path separator), it's likely hostname:port, not a protocol.\n        const looks_like_port = /^[0-9]/.test(after_colon);\n\n        if (looks_like_port) {\n          // This looks like hostname:port, not a protocol\n          if (options.require_protocol) {\n            return false;\n          }\n          // Don't consume anything; let it be parsed as hostname:port\n        } else {\n          // This is definitely a protocol\n          url = cleanUpProtocol(potential_protocol);\n\n          if (url === false) {\n            return false;\n          }\n        }\n      }\n    } else {\n      // Starts with '//', this is definitely a protocol like http://\n      url = cleanUpProtocol(potential_protocol);\n\n      if (url === false) {\n        return false;\n      }\n    }\n  } else if (options.require_protocol) {\n    return false;\n  }\n\n  // Handle leading '//' only as protocol-relative when there was NO explicit protocol.\n  // If there was an explicit protocol, '//' is the normal separator\n  // and should be stripped unconditionally.\n  if (url.slice(0, 2) === '//') {\n    if (!had_explicit_protocol && !options.allow_protocol_relative_urls) {\n      return false;\n    }\n\n    url = url.slice(2);\n  }\n\n  if (url === '') {\n    return false;\n  }\n\n  split = url.split('/');\n  url = split.shift();\n\n  if (url === '' && !options.require_host) {\n    return true;\n  }\n\n  split = url.split('@');\n  if (split.length > 1) {\n    if (options.disallow_auth) {\n      return false;\n    }\n    if (split[0] === '') {\n      return false;\n    }\n    auth = split.shift();\n    if (auth.indexOf(':') >= 0 && auth.split(':').length > 2) {\n      return false;\n    }\n    const [user, password] = auth.split(':');\n    if (user === '' && password === '') {\n      return false;\n    }\n  }\n  hostname = split.join('@');\n\n  port_str = null;\n  ipv6 = null;\n  const ipv6_match = hostname.match(wrapped_ipv6);\n  if (ipv6_match) {\n    host = '';\n    ipv6 = ipv6_match[1];\n    port_str = ipv6_match[2] || null;\n  } else {\n    split = hostname.split(':');\n    host = split.shift();\n    if (split.length) {\n      port_str = split.join(':');\n    }\n  }\n\n  if (port_str !== null && port_str.length > 0) {\n    port = parseInt(port_str, 10);\n    if (!/^[0-9]+$/.test(port_str) || port <= 0 || port > 65535) {\n      return false;\n    }\n  } else if (options.require_port) {\n    return false;\n  }\n\n  if (options.host_whitelist) {\n    return checkHost(host, options.host_whitelist);\n  }\n\n  if (host === '' && !options.require_host) {\n    return true;\n  }\n\n  if (!isIP(host) && !isFQDN(host, options) && (!ipv6 || !isIP(ipv6, 6))) {\n    return false;\n  }\n\n  host = host || ipv6;\n\n  if (options.host_blacklist && checkHost(host, options.host_blacklist)) {\n    return false;\n  }\n\n  return true;\n}\n"
  },
  {
    "path": "src/lib/isUUID.js",
    "content": "import assertString from './util/assertString';\n\nconst uuid = {\n  1: /^[0-9A-F]{8}-[0-9A-F]{4}-1[0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}$/i,\n  2: /^[0-9A-F]{8}-[0-9A-F]{4}-2[0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}$/i,\n  3: /^[0-9A-F]{8}-[0-9A-F]{4}-3[0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}$/i,\n  4: /^[0-9A-F]{8}-[0-9A-F]{4}-4[0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}$/i,\n  5: /^[0-9A-F]{8}-[0-9A-F]{4}-5[0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}$/i,\n  6: /^[0-9A-F]{8}-[0-9A-F]{4}-6[0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}$/i,\n  7: /^[0-9A-F]{8}-[0-9A-F]{4}-7[0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}$/i,\n  8: /^[0-9A-F]{8}-[0-9A-F]{4}-8[0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}$/i,\n\n  nil: /^00000000-0000-0000-0000-000000000000$/i,\n  max: /^ffffffff-ffff-ffff-ffff-ffffffffffff$/i,\n  loose: /^[0-9A-F]{8}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{12}$/i,\n\n  // From https://github.com/uuidjs/uuid/blob/main/src/regex.js\n  all: /^(?:[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$/i,\n};\n\nexport default function isUUID(str, version) {\n  assertString(str);\n\n  if (version === undefined || version === null) {\n    version = 'all';\n  }\n\n  return version in uuid ? uuid[version].test(str) : false;\n}\n"
  },
  {
    "path": "src/lib/isUppercase.js",
    "content": "import assertString from './util/assertString';\n\nexport default function isUppercase(str) {\n  assertString(str);\n  return str === str.toUpperCase();\n}\n"
  },
  {
    "path": "src/lib/isVAT.js",
    "content": "import assertString from './util/assertString';\r\nimport * as algorithms from './util/algorithms';\r\n\r\nconst AU = (str) => {\r\n  const match = str.match(/^(AU)?(\\d{11})$/);\r\n  if (!match) {\r\n    return false;\r\n  }\r\n  // @see {@link https://abr.business.gov.au/Help/AbnFormat}\r\n  const weights = [10, 1, 3, 5, 7, 9, 11, 13, 15, 17, 19];\r\n  str = str.replace(/^AU/, '');\r\n  const ABN = (parseInt(str.slice(0, 1), 10) - 1).toString() + str.slice(1);\r\n  let total = 0;\r\n  for (let i = 0; i < 11; i++) {\r\n    total += weights[i] * ABN.charAt(i);\r\n  }\r\n  return (total !== 0 && total % 89 === 0);\r\n};\r\n\r\nconst CH = (str) => {\r\n  // @see {@link https://www.ech.ch/de/ech/ech-0097/5.2.0}\r\n  const hasValidCheckNumber = (digits) => {\r\n    const lastDigit = digits.pop(); // used as check number\r\n    const weights = [5, 4, 3, 2, 7, 6, 5, 4];\r\n    const calculatedCheckNumber = (11 - (digits.reduce((acc, el, idx) =>\r\n      acc + (el * weights[idx]), 0) % 11)) % 11;\r\n\r\n    return lastDigit === calculatedCheckNumber;\r\n  };\r\n\r\n  // @see {@link https://www.estv.admin.ch/estv/de/home/mehrwertsteuer/uid/mwst-uid-nummer.html}\r\n  return /^(CHE[- ]?)?(\\d{9}|(\\d{3}\\.\\d{3}\\.\\d{3})|(\\d{3} \\d{3} \\d{3})) ?(TVA|MWST|IVA)?$/.test(str) && hasValidCheckNumber((str.match(/\\d/g).map(el => +el)));\r\n};\r\n\r\nconst PT = (str) => {\r\n  const match = str.match(/^(PT)?(\\d{9})$/);\r\n  if (!match) {\r\n    return false;\r\n  }\r\n\r\n  const tin = match[2];\r\n\r\n  const checksum = 11 - (algorithms.reverseMultiplyAndSum(tin.split('').slice(0, 8).map(a => parseInt(a, 10)), 9) % 11);\r\n  if (checksum > 9) {\r\n    return parseInt(tin[8], 10) === 0;\r\n  }\r\n  return checksum === parseInt(tin[8], 10);\r\n};\r\n\r\nexport const vatMatchers = {\r\n  /**\r\n   * European Union VAT identification numbers\r\n   */\r\n  AT: str => /^(AT)?U\\d{8}$/.test(str),\r\n  BE: str => /^(BE)?\\d{10}$/.test(str),\r\n  BG: str => /^(BG)?\\d{9,10}$/.test(str),\r\n  HR: str => /^(HR)?\\d{11}$/.test(str),\r\n  CY: str => /^(CY)?\\w{9}$/.test(str),\r\n  CZ: str => /^(CZ)?\\d{8,10}$/.test(str),\r\n  DK: str => /^(DK)?\\d{8}$/.test(str),\r\n  EE: str => /^(EE)?\\d{9}$/.test(str),\r\n  FI: str => /^(FI)?\\d{8}$/.test(str),\r\n  FR: str => /^(FR)([A-Z0-9]{2}\\d{9})$/.test(str),\r\n  DE: str => /^(DE)?\\d{9}$/.test(str),\r\n  EL: str => /^(EL)?\\d{9}$/.test(str),\r\n  HU: str => /^(HU)?\\d{8}$/.test(str),\r\n  IE: str => /^(IE)?\\d{7}\\w{1}(W)?$/.test(str),\r\n  IT: str => /^(IT)?\\d{11}$/.test(str),\r\n  LV: str => /^(LV)?\\d{11}$/.test(str),\r\n  LT: str => /^(LT)?\\d{9,12}$/.test(str),\r\n  LU: str => /^(LU)?\\d{8}$/.test(str),\r\n  MT: str => /^(MT)?\\d{8}$/.test(str),\r\n  NL: str => /^(NL)?\\d{9}B\\d{2}$/.test(str),\r\n  PL: str => /^(PL)?(\\d{10}|(\\d{3}-\\d{3}-\\d{2}-\\d{2})|(\\d{3}-\\d{2}-\\d{2}-\\d{3}))$/.test(str),\r\n  PT,\r\n  RO: str => /^(RO)?\\d{2,10}$/.test(str),\r\n  SK: str => /^(SK)?\\d{10}$/.test(str),\r\n  SI: str => /^(SI)?\\d{8}$/.test(str),\r\n  ES: str => /^(ES)?\\w\\d{7}[A-Z]$/.test(str),\r\n  SE: str => /^(SE)?\\d{12}$/.test(str),\r\n\r\n  /**\r\n   * VAT numbers of non-EU countries\r\n   */\r\n  AL: str => /^(AL)?\\w{9}[A-Z]$/.test(str),\r\n  MK: str => /^(MK)?\\d{13}$/.test(str),\r\n  AU,\r\n  BY: str => /^(УНП )?\\d{9}$/.test(str),\r\n  CA: str => /^(CA)?\\d{9}$/.test(str),\r\n  IS: str => /^(IS)?\\d{5,6}$/.test(str),\r\n  IN: str => /^(IN)?\\d{15}$/.test(str),\r\n  ID: str => /^(ID)?(\\d{15}|(\\d{2}.\\d{3}.\\d{3}.\\d{1}-\\d{3}.\\d{3}))$/.test(str),\r\n  IL: str => /^(IL)?\\d{9}$/.test(str),\r\n  KZ: str => /^(KZ)?\\d{12}$/.test(str),\r\n  NZ: str => /^(NZ)?\\d{9}$/.test(str),\r\n  NG: str => /^(NG)?(\\d{12}|(\\d{8}-\\d{4}))$/.test(str),\r\n  NO: str => /^(NO)?\\d{9}MVA$/.test(str),\r\n  PH: str => /^(PH)?(\\d{12}|\\d{3} \\d{3} \\d{3} \\d{3})$/.test(str),\r\n  RU: str => /^(RU)?(\\d{10}|\\d{12})$/.test(str),\r\n  SM: str => /^(SM)?\\d{5}$/.test(str),\r\n  SA: str => /^(SA)?\\d{15}$/.test(str),\r\n  RS: str => /^(RS)?\\d{9}$/.test(str),\r\n  CH,\r\n  TR: str => /^(TR)?\\d{10}$/.test(str),\r\n  UA: str => /^(UA)?\\d{12}$/.test(str),\r\n  GB: str => /^GB((\\d{3} \\d{4} ([0-8][0-9]|9[0-6]))|(\\d{9} \\d{3})|(((GD[0-4])|(HA[5-9]))[0-9]{2}))$/.test(str),\r\n  UZ: str => /^(UZ)?\\d{9}$/.test(str),\r\n\r\n  /**\r\n   * VAT numbers of Latin American countries\r\n   */\r\n  AR: str => /^(AR)?\\d{11}$/.test(str),\r\n  BO: str => /^(BO)?\\d{7}$/.test(str),\r\n  BR: str => /^(BR)?((\\d{2}.\\d{3}.\\d{3}\\/\\d{4}-\\d{2})|(\\d{3}.\\d{3}.\\d{3}-\\d{2}))$/.test(str),\r\n  CL: str => /^(CL)?\\d{8}-\\d{1}$/.test(str),\r\n  CO: str => /^(CO)?\\d{10}$/.test(str),\r\n  CR: str => /^(CR)?\\d{9,12}$/.test(str),\r\n  EC: str => /^(EC)?\\d{13}$/.test(str),\r\n  SV: str => /^(SV)?\\d{4}-\\d{6}-\\d{3}-\\d{1}$/.test(str),\r\n  GT: str => /^(GT)?\\d{7}-\\d{1}$/.test(str),\r\n  HN: str => /^(HN)?$/.test(str),\r\n  MX: str => /^(MX)?\\w{3,4}\\d{6}\\w{3}$/.test(str),\r\n  NI: str => /^(NI)?\\d{3}-\\d{6}-\\d{4}\\w{1}$/.test(str),\r\n  PA: str => /^(PA)?$/.test(str),\r\n  PY: str => /^(PY)?\\d{6,8}-\\d{1}$/.test(str),\r\n  PE: str => /^(PE)?\\d{11}$/.test(str),\r\n  DO: str => /^(DO)?(\\d{11}|(\\d{3}-\\d{7}-\\d{1})|[1,4,5]{1}\\d{8}|([1,4,5]{1})-\\d{2}-\\d{5}-\\d{1})$/.test(str),\r\n  UY: str => /^(UY)?\\d{12}$/.test(str),\r\n  VE: str => /^(VE)?[J,G,V,E]{1}-(\\d{9}|(\\d{8}-\\d{1}))$/.test(str),\r\n};\r\n\r\nexport default function isVAT(str, countryCode) {\r\n  assertString(str);\r\n  assertString(countryCode);\r\n\r\n  if (countryCode in vatMatchers) {\r\n    return vatMatchers[countryCode](str);\r\n  }\r\n  throw new Error(`Invalid country code: '${countryCode}'`);\r\n}\r\n"
  },
  {
    "path": "src/lib/isVariableWidth.js",
    "content": "import assertString from './util/assertString';\n\nimport { fullWidth } from './isFullWidth';\nimport { halfWidth } from './isHalfWidth';\n\nexport default function isVariableWidth(str) {\n  assertString(str);\n  return fullWidth.test(str) && halfWidth.test(str);\n}\n"
  },
  {
    "path": "src/lib/isWhitelisted.js",
    "content": "import assertString from './util/assertString';\n\nexport default function isWhitelisted(str, chars) {\n  assertString(str);\n  for (let i = str.length - 1; i >= 0; i--) {\n    if (chars.indexOf(str[i]) === -1) {\n      return false;\n    }\n  }\n  return true;\n}\n"
  },
  {
    "path": "src/lib/ltrim.js",
    "content": "import assertString from './util/assertString';\n\nexport default function ltrim(str, chars) {\n  assertString(str);\n  // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions#Escaping\n  const pattern = chars ? new RegExp(`^[${chars.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&')}]+`, 'g') : /^\\s+/g;\n  return str.replace(pattern, '');\n}\n"
  },
  {
    "path": "src/lib/matches.js",
    "content": "import assertString from './util/assertString';\n\nexport default function matches(str, pattern, modifiers) {\n  assertString(str);\n  if (Object.prototype.toString.call(pattern) !== '[object RegExp]') {\n    pattern = new RegExp(pattern, modifiers);\n  }\n  return !!str.match(pattern);\n}\n"
  },
  {
    "path": "src/lib/normalizeEmail.js",
    "content": "import merge from './util/merge';\n\nconst default_normalize_email_options = {\n  // The following options apply to all email addresses\n  // Lowercases the local part of the email address.\n  // Please note this may violate RFC 5321 as per http://stackoverflow.com/a/9808332/192024).\n  // The domain is always lowercased, as per RFC 1035\n  all_lowercase: true,\n\n  // The following conversions are specific to GMail\n  // Lowercases the local part of the GMail address (known to be case-insensitive)\n  gmail_lowercase: true,\n  // Removes dots from the local part of the email address, as that's ignored by GMail\n  gmail_remove_dots: true,\n  // Removes the subaddress (e.g. \"+foo\") from the email address\n  gmail_remove_subaddress: true,\n  // Conversts the googlemail.com domain to gmail.com\n  gmail_convert_googlemaildotcom: true,\n\n  // The following conversions are specific to Outlook.com / Windows Live / Hotmail\n  // Lowercases the local part of the Outlook.com address (known to be case-insensitive)\n  outlookdotcom_lowercase: true,\n  // Removes the subaddress (e.g. \"+foo\") from the email address\n  outlookdotcom_remove_subaddress: true,\n\n  // The following conversions are specific to Yahoo\n  // Lowercases the local part of the Yahoo address (known to be case-insensitive)\n  yahoo_lowercase: true,\n  // Removes the subaddress (e.g. \"-foo\") from the email address\n  yahoo_remove_subaddress: true,\n\n  // The following conversions are specific to Yandex\n  // Lowercases the local part of the Yandex address (known to be case-insensitive)\n  yandex_lowercase: true,\n  // all yandex domains are equal, this explicitly sets the domain to 'yandex.ru'\n  yandex_convert_yandexru: true,\n\n  // The following conversions are specific to iCloud\n  // Lowercases the local part of the iCloud address (known to be case-insensitive)\n  icloud_lowercase: true,\n  // Removes the subaddress (e.g. \"+foo\") from the email address\n  icloud_remove_subaddress: true,\n};\n\n// List of domains used by iCloud\nconst icloud_domains = [\n  'icloud.com',\n  'me.com',\n];\n\n// List of domains used by Outlook.com and its predecessors\n// This list is likely incomplete.\n// Partial reference:\n// https://blogs.office.com/2013/04/17/outlook-com-gets-two-step-verification-sign-in-by-alias-and-new-international-domains/\nconst outlookdotcom_domains = [\n  'hotmail.at',\n  'hotmail.be',\n  'hotmail.ca',\n  'hotmail.cl',\n  'hotmail.co.il',\n  'hotmail.co.nz',\n  'hotmail.co.th',\n  'hotmail.co.uk',\n  'hotmail.com',\n  'hotmail.com.ar',\n  'hotmail.com.au',\n  'hotmail.com.br',\n  'hotmail.com.gr',\n  'hotmail.com.mx',\n  'hotmail.com.pe',\n  'hotmail.com.tr',\n  'hotmail.com.vn',\n  'hotmail.cz',\n  'hotmail.de',\n  'hotmail.dk',\n  'hotmail.es',\n  'hotmail.fr',\n  'hotmail.hu',\n  'hotmail.id',\n  'hotmail.ie',\n  'hotmail.in',\n  'hotmail.it',\n  'hotmail.jp',\n  'hotmail.kr',\n  'hotmail.lv',\n  'hotmail.my',\n  'hotmail.ph',\n  'hotmail.pt',\n  'hotmail.sa',\n  'hotmail.sg',\n  'hotmail.sk',\n  'live.be',\n  'live.co.uk',\n  'live.com',\n  'live.com.ar',\n  'live.com.mx',\n  'live.de',\n  'live.es',\n  'live.eu',\n  'live.fr',\n  'live.it',\n  'live.nl',\n  'msn.com',\n  'outlook.at',\n  'outlook.be',\n  'outlook.cl',\n  'outlook.co.il',\n  'outlook.co.nz',\n  'outlook.co.th',\n  'outlook.com',\n  'outlook.com.ar',\n  'outlook.com.au',\n  'outlook.com.br',\n  'outlook.com.gr',\n  'outlook.com.pe',\n  'outlook.com.tr',\n  'outlook.com.vn',\n  'outlook.cz',\n  'outlook.de',\n  'outlook.dk',\n  'outlook.es',\n  'outlook.fr',\n  'outlook.hu',\n  'outlook.id',\n  'outlook.ie',\n  'outlook.in',\n  'outlook.it',\n  'outlook.jp',\n  'outlook.kr',\n  'outlook.lv',\n  'outlook.my',\n  'outlook.ph',\n  'outlook.pt',\n  'outlook.sa',\n  'outlook.sg',\n  'outlook.sk',\n  'passport.com',\n];\n\n// List of domains used by Yahoo Mail\n// This list is likely incomplete\nconst yahoo_domains = [\n  'rocketmail.com',\n  'yahoo.ca',\n  'yahoo.co.uk',\n  'yahoo.com',\n  'yahoo.de',\n  'yahoo.fr',\n  'yahoo.in',\n  'yahoo.it',\n  'ymail.com',\n];\n\n// List of domains used by yandex.ru\nconst yandex_domains = [\n  'yandex.ru',\n  'yandex.ua',\n  'yandex.kz',\n  'yandex.com',\n  'yandex.by',\n  'ya.ru',\n];\n\n// replace single dots, but not multiple consecutive dots\nfunction dotsReplacer(match) {\n  if (match.length > 1) {\n    return match;\n  }\n  return '';\n}\n\nexport default function normalizeEmail(email, options) {\n  options = merge(options, default_normalize_email_options);\n\n  const raw_parts = email.split('@');\n  const domain = raw_parts.pop();\n  const user = raw_parts.join('@');\n  const parts = [user, domain];\n\n  // The domain is always lowercased, as it's case-insensitive per RFC 1035\n  parts[1] = parts[1].toLowerCase();\n\n  if (parts[1] === 'gmail.com' || parts[1] === 'googlemail.com') {\n    // Address is GMail\n    if (options.gmail_remove_subaddress) {\n      parts[0] = parts[0].split('+')[0];\n    }\n    if (options.gmail_remove_dots) {\n      // this does not replace consecutive dots like example..email@gmail.com\n      parts[0] = parts[0].replace(/\\.+/g, dotsReplacer);\n    }\n    if (!parts[0].length) {\n      return false;\n    }\n    if (options.all_lowercase || options.gmail_lowercase) {\n      parts[0] = parts[0].toLowerCase();\n    }\n    parts[1] = options.gmail_convert_googlemaildotcom ? 'gmail.com' : parts[1];\n  } else if (icloud_domains.indexOf(parts[1]) >= 0) {\n    // Address is iCloud\n    if (options.icloud_remove_subaddress) {\n      parts[0] = parts[0].split('+')[0];\n    }\n    if (!parts[0].length) {\n      return false;\n    }\n    if (options.all_lowercase || options.icloud_lowercase) {\n      parts[0] = parts[0].toLowerCase();\n    }\n  } else if (outlookdotcom_domains.indexOf(parts[1]) >= 0) {\n    // Address is Outlook.com\n    if (options.outlookdotcom_remove_subaddress) {\n      parts[0] = parts[0].split('+')[0];\n    }\n    if (!parts[0].length) {\n      return false;\n    }\n    if (options.all_lowercase || options.outlookdotcom_lowercase) {\n      parts[0] = parts[0].toLowerCase();\n    }\n  } else if (yahoo_domains.indexOf(parts[1]) >= 0) {\n    // Address is Yahoo\n    if (options.yahoo_remove_subaddress) {\n      let components = parts[0].split('-');\n      parts[0] = (components.length > 1) ? components.slice(0, -1).join('-') : components[0];\n    }\n    if (!parts[0].length) {\n      return false;\n    }\n    if (options.all_lowercase || options.yahoo_lowercase) {\n      parts[0] = parts[0].toLowerCase();\n    }\n  } else if (yandex_domains.indexOf(parts[1]) >= 0) {\n    if (options.all_lowercase || options.yandex_lowercase) {\n      parts[0] = parts[0].toLowerCase();\n    }\n    parts[1] = options.yandex_convert_yandexru ? 'yandex.ru' : parts[1];\n  } else if (options.all_lowercase) {\n    // Any other address\n    parts[0] = parts[0].toLowerCase();\n  }\n  return parts.join('@');\n}\n"
  },
  {
    "path": "src/lib/rtrim.js",
    "content": "import assertString from './util/assertString';\n\nexport default function rtrim(str, chars) {\n  assertString(str);\n  if (chars) {\n    // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions#Escaping\n    const pattern = new RegExp(`[${chars.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&')}]+$`, 'g');\n    return str.replace(pattern, '');\n  }\n  // Use a faster and more safe than regex trim method https://blog.stevenlevithan.com/archives/faster-trim-javascript\n  let strIndex = str.length - 1;\n  while (/\\s/.test(str.charAt(strIndex))) {\n    strIndex -= 1;\n  }\n\n  return str.slice(0, strIndex + 1);\n}\n"
  },
  {
    "path": "src/lib/stripLow.js",
    "content": "import assertString from './util/assertString';\n\nimport blacklist from './blacklist';\n\nexport default function stripLow(str, keep_new_lines) {\n  assertString(str);\n  const chars = keep_new_lines ? '\\\\x00-\\\\x09\\\\x0B\\\\x0C\\\\x0E-\\\\x1F\\\\x7F' : '\\\\x00-\\\\x1F\\\\x7F';\n  return blacklist(str, chars);\n}\n"
  },
  {
    "path": "src/lib/toBoolean.js",
    "content": "import assertString from './util/assertString';\n\nexport default function toBoolean(str, strict) {\n  assertString(str);\n  if (strict) {\n    return str === '1' || /^true$/i.test(str);\n  }\n  return str !== '0' && !/^false$/i.test(str) && str !== '';\n}\n"
  },
  {
    "path": "src/lib/toDate.js",
    "content": "import assertString from './util/assertString';\n\nexport default function toDate(date) {\n  assertString(date);\n\n  date = Date.parse(date);\n  return !isNaN(date) ? new Date(date) : null;\n}\n"
  },
  {
    "path": "src/lib/toFloat.js",
    "content": "import isFloat from './isFloat';\n\nexport default function toFloat(str) {\n  if (!isFloat(str)) return NaN;\n\n  return parseFloat(str);\n}\n"
  },
  {
    "path": "src/lib/toInt.js",
    "content": "import assertString from './util/assertString';\n\nexport default function toInt(str, radix) {\n  assertString(str);\n  return parseInt(str, radix || 10);\n}\n"
  },
  {
    "path": "src/lib/trim.js",
    "content": "import rtrim from './rtrim';\nimport ltrim from './ltrim';\n\nexport default function trim(str, chars) {\n  return rtrim(ltrim(str, chars), chars);\n}\n"
  },
  {
    "path": "src/lib/unescape.js",
    "content": "import assertString from './util/assertString';\n\nexport default function unescape(str) {\n  assertString(str);\n  return (str.replace(/&quot;/g, '\"')\n    .replace(/&#x27;/g, \"'\")\n    .replace(/&lt;/g, '<')\n    .replace(/&gt;/g, '>')\n    .replace(/&#x2F;/g, '/')\n    .replace(/&#x5C;/g, '\\\\')\n    .replace(/&#96;/g, '`')\n    .replace(/&amp;/g, '&'));\n  // &amp; replacement has to be the last one to prevent\n  // bugs with intermediate strings containing escape sequences\n  // See: https://github.com/validatorjs/validator.js/issues/1827\n}\n"
  },
  {
    "path": "src/lib/util/algorithms.js",
    "content": "/**\n * Algorithmic validation functions\n * May be used as is or implemented in the workflow of other validators.\n */\n\n/*\n * ISO 7064 validation function\n * Called with a string of numbers (incl. check digit)\n * to validate according to ISO 7064 (MOD 11, 10).\n */\nexport function iso7064Check(str) {\n  let checkvalue = 10;\n  for (let i = 0; i < str.length - 1; i++) {\n    checkvalue = (parseInt(str[i], 10) + checkvalue) % 10 === 0 ? (10 * 2) % 11 :\n      (((parseInt(str[i], 10) + checkvalue) % 10) * 2) % 11;\n  }\n  checkvalue = checkvalue === 1 ? 0 : 11 - checkvalue;\n  return checkvalue === parseInt(str[10], 10);\n}\n\n/*\n * Luhn (mod 10) validation function\n * Called with a string of numbers (incl. check digit)\n * to validate according to the Luhn algorithm.\n */\nexport function luhnCheck(str) {\n  let checksum = 0;\n  let second = false;\n  for (let i = str.length - 1; i >= 0; i--) {\n    if (second) {\n      const product = parseInt(str[i], 10) * 2;\n      if (product > 9) {\n        // sum digits of product and add to checksum\n        checksum += product.toString().split('').map(a => parseInt(a, 10)).reduce((a, b) => a + b, 0);\n      } else {\n        checksum += product;\n      }\n    } else {\n      checksum += parseInt(str[i], 10);\n    }\n    second = !second;\n  }\n  return checksum % 10 === 0;\n}\n\n/*\n * Reverse TIN multiplication and summation helper function\n * Called with an array of single-digit integers and a base multiplier\n * to calculate the sum of the digits multiplied in reverse.\n * Normally used in variations of MOD 11 algorithmic checks.\n */\nexport function reverseMultiplyAndSum(digits, base) {\n  let total = 0;\n  for (let i = 0; i < digits.length; i++) {\n    total += digits[i] * (base - i);\n  }\n  return total;\n}\n\n/*\n * Verhoeff validation helper function\n * Called with a string of numbers\n * to validate according to the Verhoeff algorithm.\n */\nexport function verhoeffCheck(str) {\n  const d_table = [\n    [0, 1, 2, 3, 4, 5, 6, 7, 8, 9],\n    [1, 2, 3, 4, 0, 6, 7, 8, 9, 5],\n    [2, 3, 4, 0, 1, 7, 8, 9, 5, 6],\n    [3, 4, 0, 1, 2, 8, 9, 5, 6, 7],\n    [4, 0, 1, 2, 3, 9, 5, 6, 7, 8],\n    [5, 9, 8, 7, 6, 0, 4, 3, 2, 1],\n    [6, 5, 9, 8, 7, 1, 0, 4, 3, 2],\n    [7, 6, 5, 9, 8, 2, 1, 0, 4, 3],\n    [8, 7, 6, 5, 9, 3, 2, 1, 0, 4],\n    [9, 8, 7, 6, 5, 4, 3, 2, 1, 0],\n  ];\n\n  const p_table = [\n    [0, 1, 2, 3, 4, 5, 6, 7, 8, 9],\n    [1, 5, 7, 6, 2, 8, 3, 0, 9, 4],\n    [5, 8, 0, 3, 7, 9, 6, 1, 4, 2],\n    [8, 9, 1, 6, 0, 4, 3, 5, 2, 7],\n    [9, 4, 5, 3, 1, 2, 6, 8, 7, 0],\n    [4, 2, 8, 6, 5, 7, 3, 9, 0, 1],\n    [2, 7, 9, 3, 8, 0, 6, 4, 1, 5],\n    [7, 0, 4, 6, 9, 1, 3, 2, 5, 8],\n  ];\n\n  // Copy (to prevent replacement) and reverse\n  const str_copy = str.split('').reverse().join('');\n  let checksum = 0;\n  for (let i = 0; i < str_copy.length; i++) {\n    checksum = d_table[checksum][p_table[i % 8][parseInt(str_copy[i], 10)]];\n  }\n  return checksum === 0;\n}\n"
  },
  {
    "path": "src/lib/util/assertString.js",
    "content": "export default function assertString(input) {\n  if (input === undefined || input === null) throw new TypeError(`Expected a string but received a ${input}`);\n  if (input.constructor.name !== 'String') throw new TypeError(`Expected a string but received a ${input.constructor.name}`);\n}\n"
  },
  {
    "path": "src/lib/util/checkHost.js",
    "content": "function isRegExp(obj) {\n  return Object.prototype.toString.call(obj) === '[object RegExp]';\n}\n\nexport default function checkHost(host, matches) {\n  for (let i = 0; i < matches.length; i++) {\n    let match = matches[i];\n    if (host === match || (isRegExp(match) && match.test(host))) {\n      return true;\n    }\n  }\n  return false;\n}\n"
  },
  {
    "path": "src/lib/util/includesArray.js",
    "content": "const includes = (arr, val) => arr.some(arrVal => val === arrVal);\n\nexport default includes;\n"
  },
  {
    "path": "src/lib/util/includesString.js",
    "content": "const includes = (str, val) => str.indexOf(val) !== -1;\n\nexport default includes;\n"
  },
  {
    "path": "src/lib/util/merge.js",
    "content": "export default function merge(obj = { }, defaults) {\n  if (typeof obj !== 'object' || obj === null) {\n    obj = {};\n  }\n  for (const key in defaults) {\n    if (typeof obj[key] === 'undefined') {\n      obj[key] = defaults[key];\n    }\n  }\n  return obj;\n}\n"
  },
  {
    "path": "src/lib/util/multilineRegex.js",
    "content": "/**\n * Build RegExp object from an array\n * of multiple/multi-line regexp parts\n *\n * @param {string[]} parts\n * @param {string} flags\n * @return {object} - RegExp object\n */\nexport default function multilineRegexp(parts, flags) {\n  const regexpAsStringLiteral = parts.join('');\n\n  return new RegExp(regexpAsStringLiteral, flags);\n}\n"
  },
  {
    "path": "src/lib/util/nullUndefinedCheck.js",
    "content": "export default function isNullOrUndefined(value) {\n  return value === null || value === undefined;\n}\n"
  },
  {
    "path": "src/lib/util/toString.js",
    "content": "export default function toString(input) {\n  if (typeof input === 'object' && input !== null) {\n    if (typeof input.toString === 'function') {\n      input = input.toString();\n    } else {\n      input = '[object Object]';\n    }\n  } else if (input === null || typeof input === 'undefined' || (isNaN(input) && !input.length)) {\n    input = '';\n  }\n  return String(input);\n}\n"
  },
  {
    "path": "src/lib/util/typeOf.js",
    "content": "/**\n * Better way to handle type checking\n * null, {}, array and date are objects, which confuses\n */\nexport default function typeOf(input) {\n  const rawObject = Object.prototype.toString.call(input).toLowerCase();\n  const typeOfRegex = /\\[object (.*)]/g;\n  const type = typeOfRegex.exec(rawObject)[1];\n  return type;\n}\n"
  },
  {
    "path": "src/lib/whitelist.js",
    "content": "import assertString from './util/assertString';\n\nexport default function whitelist(str, chars) {\n  assertString(str);\n  return str.replace(new RegExp(`[^${chars}]+`, 'g'), '');\n}\n"
  },
  {
    "path": "test/clientSide.test.js",
    "content": "import assert from 'assert';\nimport validator from '../validator';\nimport min from '../validator.min';\n\ndescribe('Minified version', () => {\n  it('should export the same things as the server-side version', () => {\n    for (let key in validator) {\n      if ({}.hasOwnProperty.call(validator, key)) {\n        assert.strictEqual(\n          typeof validator[key],\n          typeof min[key], `Minified version did not export ${key}`\n        );\n      }\n    }\n  });\n\n  it('should be up to date', () => {\n    assert.strictEqual(min.version, validator.version, 'Minified version mismatch. Run `make min`');\n  });\n\n  it('should validate strings', () => {\n    assert.strictEqual(min.isEmail('foo@bar.com'), true);\n    assert.strictEqual(min.isEmail('foo'), false);\n  });\n\n  it('should sanitize strings', () => {\n    assert.strictEqual(min.toBoolean('1'), true);\n  });\n});\n"
  },
  {
    "path": "test/exports.test.js",
    "content": "import assert from 'assert';\nimport validator from '../index';\nimport { locales as isPostalCodeLocales } from '../src/lib/isPostalCode';\nimport { locales as isAlphaLocales } from '../src/lib/isAlpha';\nimport { locales as isAlphanumericLocales } from '../src/lib/isAlphanumeric';\nimport { locales as isMobilePhoneLocales } from '../src/lib/isMobilePhone';\nimport { locales as isFloatLocales } from '../src/lib/isFloat';\nimport { locales as ibanCountryCodes } from '../src/lib/isIBAN';\nimport { locales as passportNumberLocales } from '../src/lib/isPassportNumber';\n\ndescribe('Exports', () => {\n  it('should export isPassportNumbers\\'s supported locales', () => {\n    assert.ok(passportNumberLocales instanceof Array);\n    assert.ok(validator.passportNumberLocales instanceof Array);\n  });\n\n  it('should export validators', () => {\n    assert.strictEqual(typeof validator.isEmail, 'function');\n    assert.strictEqual(typeof validator.isAlpha, 'function');\n  });\n\n  it('should export sanitizers', () => {\n    assert.strictEqual(typeof validator.toBoolean, 'function');\n    assert.strictEqual(typeof validator.toFloat, 'function');\n  });\n\n  it('should export the version number', () => {\n    /* eslint-disable global-require */\n    assert.strictEqual(\n      validator.version, require('../package.json').version,\n      'Version number mismatch in \"package.json\" vs. \"validator.js\"'\n    );\n    /* eslint-enable global-require */\n  });\n\n  it('should export isPostalCode\\'s supported locales', () => {\n    assert.ok(isPostalCodeLocales instanceof Array);\n    assert.ok(validator.isPostalCodeLocales instanceof Array);\n  });\n\n  it('should export isAlpha\\'s supported locales', () => {\n    assert.ok(isAlphaLocales instanceof Array);\n    assert.ok(validator.isAlphaLocales instanceof Array);\n  });\n\n  it('should export isAlphanumeric\\'s supported locales', () => {\n    assert.ok(isAlphanumericLocales instanceof Array);\n    assert.ok(validator.isAlphanumericLocales instanceof Array);\n  });\n\n  it('should export isMobilePhone\\'s supported locales', () => {\n    assert.ok(isMobilePhoneLocales instanceof Array);\n    assert.ok(validator.isMobilePhoneLocales instanceof Array);\n  });\n\n  it('should export isFloat\\'s supported locales', () => {\n    assert.ok(isFloatLocales instanceof Array);\n    assert.ok(validator.isFloatLocales instanceof Array);\n  });\n\n  it('should export a list of country codes that implement IBAN', () => {\n    assert.ok(ibanCountryCodes instanceof Array);\n    assert.ok(validator.ibanLocales instanceof Array);\n  });\n});\n"
  },
  {
    "path": "test/sanitizers.test.js",
    "content": "import { format } from 'util';\nimport validator from '../src/index';\n\nfunction test(options) {\n  let args = options.args || [];\n\n  args.unshift(null);\n\n  Object.keys(options.expect).forEach((input) => {\n    args[0] = input;\n    let result = validator[options.sanitizer](...args);\n    let expected = options.expect[input];\n    if (isNaN(result) && !result.length && isNaN(expected)) {\n      return;\n    }\n\n    if (result !== expected) {\n      let warning = format(\n        'validator.%s(%s) returned \"%s\" but should have returned \"%s\"',\n        options.sanitizer, args.join(', '), result, expected\n      );\n\n      throw new Error(warning);\n    }\n  });\n}\n\ndescribe('Sanitizers', () => {\n  it('should sanitize boolean strings', () => {\n    test({\n      sanitizer: 'toBoolean',\n      expect: {\n        0: false,\n        '': false,\n        1: true,\n        true: true,\n        True: true,\n        TRUE: true,\n        foobar: true,\n        '   ': true,\n        false: false,\n        False: false,\n        FALSE: false,\n      },\n    });\n    test({\n      sanitizer: 'toBoolean',\n      args: [true], // strict\n      expect: {\n        0: false,\n        '': false,\n        1: true,\n        true: true,\n        True: true,\n        TRUE: true,\n        foobar: false,\n        '   ': false,\n        false: false,\n        False: false,\n        FALSE: false,\n      },\n    });\n  });\n\n  it('should trim whitespace', () => {\n    test({\n      sanitizer: 'trim',\n      expect: {\n        '  \\r\\n\\tfoo  \\r\\n\\t   ': 'foo',\n        '      \\r': '',\n      },\n    });\n\n    test({\n      sanitizer: 'ltrim',\n      expect: {\n        '  \\r\\n\\tfoo  \\r\\n\\t   ': 'foo  \\r\\n\\t   ',\n        '   \\t  \\n': '',\n      },\n    });\n\n    test({\n      sanitizer: 'rtrim',\n      expect: {\n        '  \\r\\n\\tfoo  \\r\\n\\t   ': '  \\r\\n\\tfoo',\n        ' \\r\\n  \\t': '',\n      },\n    });\n  });\n\n  it('should trim custom characters', () => {\n    test({\n      sanitizer: 'trim',\n      args: ['01'],\n      expect: { '010100201000': '2' },\n    });\n\n    test({\n      sanitizer: 'ltrim',\n      args: ['01'],\n      expect: { '010100201000': '201000' },\n    });\n\n    test({\n      sanitizer: 'ltrim',\n      args: ['\\\\S'],\n      expect: { '\\\\S01010020100001': '01010020100001' },\n    });\n\n\n    test({\n      sanitizer: 'rtrim',\n      args: ['01'],\n      expect: { '010100201000': '0101002' },\n    });\n\n    test({\n      sanitizer: 'rtrim',\n      args: ['\\\\S'],\n      expect: { '01010020100001\\\\S': '01010020100001' },\n    });\n  });\n\n  it('should convert strings to integers', () => {\n    test({\n      sanitizer: 'toInt',\n      expect: {\n        3: 3,\n        ' 3 ': 3,\n        2.4: 2,\n        foo: NaN,\n      },\n    });\n\n    test({\n      sanitizer: 'toInt',\n      args: [16],\n      expect: { ff: 255 },\n    });\n  });\n\n  it('should convert strings to floats', () => {\n    test({\n      sanitizer: 'toFloat',\n      expect: {\n        2: 2.0,\n        '2.': 2.0,\n        '-2.5': -2.5,\n        '.5': 0.5,\n        '2020-01-06T14:31:00.135Z': NaN,\n        foo: NaN,\n      },\n    });\n  });\n\n  it('should escape HTML', () => {\n    test({\n      sanitizer: 'escape',\n      expect: {\n        '<script> alert(\"xss&fun\"); </script>':\n            '&lt;script&gt; alert(&quot;xss&amp;fun&quot;); &lt;&#x2F;script&gt;',\n\n        \"<script> alert('xss&fun'); </script>\":\n            '&lt;script&gt; alert(&#x27;xss&amp;fun&#x27;); &lt;&#x2F;script&gt;',\n\n        'Backtick: `':\n            'Backtick: &#96;',\n\n        'Backslash: \\\\':\n            'Backslash: &#x5C;',\n      },\n    });\n  });\n\n  it('should unescape HTML', () => {\n    test({\n      sanitizer: 'unescape',\n      expect: {\n        '&lt;script&gt; alert(&quot;xss&amp;fun&quot;); &lt;&#x2F;script&gt;':\n             '<script> alert(\"xss&fun\"); </script>',\n\n        '&lt;script&gt; alert(&#x27;xss&amp;fun&#x27;); &lt;&#x2F;script&gt;':\n            \"<script> alert('xss&fun'); </script>\",\n\n        'Backtick: &#96;':\n            'Backtick: `',\n\n        'Escaped string: &amp;lt;':\n            'Escaped string: &lt;',\n      },\n    });\n  });\n\n  it('should remove control characters (<32 and 127)', () => {\n    // Check basic functionality\n    test({\n      sanitizer: 'stripLow',\n      expect: {\n        'foo\\x00': 'foo',\n        '\\x7Ffoo\\x02': 'foo',\n        '\\x01\\x09': '',\n        'foo\\x0A\\x0D': 'foo',\n      },\n    });\n    // Unicode safety\n    test({\n      sanitizer: 'stripLow',\n      expect: {\n        perché: 'perch\\u00e9',\n        '\\u20ac': '\\u20ac',\n        '\\u2206\\x0A': '\\u2206',\n        '\\ud83d\\ude04': '\\ud83d\\ude04',\n      },\n    });\n    // Preserve newlines\n    test({\n      sanitizer: 'stripLow',\n      args: [true], // keep_new_lines\n      expect: {\n        'foo\\x0A\\x0D': 'foo\\x0A\\x0D',\n        '\\x03foo\\x0A\\x0D': 'foo\\x0A\\x0D',\n      },\n    });\n  });\n\n  it('should sanitize a string based on a whitelist', () => {\n    test({\n      sanitizer: 'whitelist',\n      args: ['abc'],\n      expect: {\n        abcdef: 'abc',\n        aaaaaaaaaabbbbbbbbbb: 'aaaaaaaaaabbbbbbbbbb',\n        a1b2c3: 'abc',\n        '   ': '',\n      },\n    });\n  });\n\n  it('should sanitize a string based on a blacklist', () => {\n    test({\n      sanitizer: 'blacklist',\n      args: ['abc'],\n      expect: {\n        abcdef: 'def',\n        aaaaaaaaaabbbbbbbbbb: '',\n        a1b2c3: '123',\n        '   ': '   ',\n      },\n    });\n  });\n\n  it('should score passwords', () => {\n    test({\n      sanitizer: 'isStrongPassword',\n      args: [{\n        returnScore: true,\n        pointsPerUnique: 1,\n        pointsPerRepeat: 0.5,\n        pointsForContainingLower: 10,\n        pointsForContainingUpper: 10,\n        pointsForContainingNumber: 10,\n        pointsForContainingSymbol: 10,\n      }],\n      expect: {\n        abc: 13,\n        abcc: 13.5,\n        aBc: 23,\n        'Abc123!': 47,\n        '!@#$%^&*()': 20,\n      },\n    });\n  });\n\n  it('should score passwords with default options', () => {\n    test({\n      sanitizer: 'isStrongPassword',\n      expect: {\n        abc: false,\n        abcc: false,\n        aBc: false,\n        'Abc123!': false,\n        '!@#$%^&*()': false,\n        'abc123!@f#rA': true,\n      },\n    });\n  });\n\n  it('should normalize an email based on domain', () => {\n    test({\n      sanitizer: 'normalizeEmail',\n      expect: {\n        'test@me.com': 'test@me.com',\n        'some.name@gmail.com': 'somename@gmail.com',\n        'some.name@googleMail.com': 'somename@gmail.com',\n        'some.name+extension@gmail.com': 'somename@gmail.com',\n        'some.Name+extension@GoogleMail.com': 'somename@gmail.com',\n        'some.name.middleName+extension@gmail.com': 'somenamemiddlename@gmail.com',\n        'some.name.middleName+extension@GoogleMail.com': 'somenamemiddlename@gmail.com',\n        'some.name.midd.leNa.me.+extension@gmail.com': 'somenamemiddlename@gmail.com',\n        'some.name.midd.leNa.me.+extension@GoogleMail.com': 'somenamemiddlename@gmail.com',\n        'some.name+extension@unknown.com': 'some.name+extension@unknown.com',\n        'hans@m端ller.com': 'hans@m端ller.com',\n        'some.name.midd..leNa...me...+extension@GoogleMail.com': 'somenamemidd..lena...me...@gmail.com',\n        'matthew..example@gmail.com': 'matthew..example@gmail.com',\n        '\"foo@bar\"@baz.com': '\"foo@bar\"@baz.com',\n        'test@ya.ru': 'test@yandex.ru',\n        'test@yandex.kz': 'test@yandex.ru',\n        'test@yandex.ru': 'test@yandex.ru',\n        'test@yandex.ua': 'test@yandex.ru',\n        'test@yandex.com': 'test@yandex.ru',\n        'test@yandex.by': 'test@yandex.ru',\n        '@gmail.com': false,\n        '@icloud.com': false,\n        '@outlook.com': false,\n        '@yahoo.com': false,\n      },\n    });\n\n    // Testing all_lowercase switch, should apply to domains not known to be case-insensitive\n    test({\n      sanitizer: 'normalizeEmail',\n      args: [{ all_lowercase: false }],\n      expect: {\n        'test@foo.com': 'test@foo.com',\n        'hans@m端ller.com': 'hans@m端ller.com',\n        'test@FOO.COM': 'test@foo.com', // Hostname is always lowercased\n        'blAH@x.com': 'blAH@x.com',\n        // In case of domains that are known to be case-insensitive, there's a separate switch\n        'TEST@me.com': 'test@me.com',\n        'TEST@ME.COM': 'test@me.com',\n        'SOME.name@GMAIL.com': 'somename@gmail.com',\n        'SOME.name.middleName+extension@GoogleMail.com': 'somenamemiddlename@gmail.com',\n        'SOME.name.midd.leNa.me.+extension@gmail.com': 'somenamemiddlename@gmail.com',\n        'SOME.name@gmail.com': 'somename@gmail.com',\n        'SOME.name@yahoo.ca': 'some.name@yahoo.ca',\n        'SOME.name@outlook.ie': 'some.name@outlook.ie',\n        'SOME.name@me.com': 'some.name@me.com',\n        'SOME.name@yandex.ru': 'some.name@yandex.ru',\n      },\n    });\n\n    // Testing *_lowercase\n    test({\n      sanitizer: 'normalizeEmail',\n      args: [{\n        all_lowercase: false,\n        gmail_lowercase: false,\n        icloud_lowercase: false,\n        outlookdotcom_lowercase: false,\n        yahoo_lowercase: false,\n        yandex_lowercase: false,\n      }],\n      expect: {\n        'TEST@FOO.COM': 'TEST@foo.com', // all_lowercase\n        'ME@gMAil.com': 'ME@gmail.com', // gmail_lowercase\n        'ME@me.COM': 'ME@me.com', // icloud_lowercase\n        'ME@icloud.COM': 'ME@icloud.com', // icloud_lowercase\n        'ME@outlook.COM': 'ME@outlook.com', // outlookdotcom_lowercase\n        'JOHN@live.CA': 'JOHN@live.ca', // outlookdotcom_lowercase\n        'ME@ymail.COM': 'ME@ymail.com', // yahoo_lowercase\n        'ME@yandex.RU': 'ME@yandex.ru', // yandex_lowercase\n      },\n    });\n\n    // Testing all_lowercase\n    // Should overwrite all the *_lowercase options\n    test({\n      sanitizer: 'normalizeEmail',\n      args: [{\n        all_lowercase: true,\n        gmail_lowercase: false, // Overruled\n        icloud_lowercase: false, // Overruled\n        outlookdotcom_lowercase: false, // Overruled\n        yahoo_lowercase: false, // Overruled\n      }],\n      expect: {\n        'TEST@FOO.COM': 'test@foo.com', // all_lowercase\n        'ME@gMAil.com': 'me@gmail.com', // gmail_lowercase\n        'ME@me.COM': 'me@me.com', // icloud_lowercase\n        'ME@icloud.COM': 'me@icloud.com', // icloud_lowercase\n        'ME@outlook.COM': 'me@outlook.com', // outlookdotcom_lowercase\n        'JOHN@live.CA': 'john@live.ca', // outlookdotcom_lowercase\n        'ME@ymail.COM': 'me@ymail.com', // yahoo_lowercase\n      },\n    });\n\n    // Testing *_remove_dots\n    test({\n      sanitizer: 'normalizeEmail',\n      args: [{\n        gmail_remove_dots: false,\n      }],\n      expect: {\n        'SOME.name@GMAIL.com': 'some.name@gmail.com',\n        'SOME.name+me@GMAIL.com': 'some.name@gmail.com',\n        'my.self@foo.com': 'my.self@foo.com',\n      },\n    });\n\n    test({\n      sanitizer: 'normalizeEmail',\n      args: [{\n        gmail_remove_dots: true,\n      }],\n      expect: {\n        'SOME.name@GMAIL.com': 'somename@gmail.com',\n        'SOME.name+me@GMAIL.com': 'somename@gmail.com',\n        'some.name..multiple@gmail.com': 'somename..multiple@gmail.com',\n        'my.self@foo.com': 'my.self@foo.com',\n      },\n    });\n\n    // Testing *_remove_subaddress\n    test({\n      sanitizer: 'normalizeEmail',\n      args: [{\n        gmail_remove_subaddress: false,\n        icloud_remove_subaddress: false,\n        outlookdotcom_remove_subaddress: false,\n        yahoo_remove_subaddress: false, // Note Yahoo uses \"-\"\n      }],\n      expect: {\n        'foo+bar@unknown.com': 'foo+bar@unknown.com',\n        'foo+bar@gmail.com': 'foo+bar@gmail.com', // gmail_remove_subaddress\n        'foo+bar@me.com': 'foo+bar@me.com', // icloud_remove_subaddress\n        'foo+bar@icloud.com': 'foo+bar@icloud.com', // icloud_remove_subaddress\n        'foo+bar@live.fr': 'foo+bar@live.fr', // outlookdotcom_remove_subaddress\n        'foo+bar@hotmail.co.uk': 'foo+bar@hotmail.co.uk', // outlookdotcom_remove_subaddress\n        'foo-bar@yahoo.com': 'foo-bar@yahoo.com', // yahoo_remove_subaddress\n        'foo+bar@yahoo.com': 'foo+bar@yahoo.com', // yahoo_remove_subaddress\n      },\n    });\n\n    test({\n      sanitizer: 'normalizeEmail',\n      args: [{\n        gmail_remove_subaddress: true,\n        icloud_remove_subaddress: true,\n        outlookdotcom_remove_subaddress: true,\n        yahoo_remove_subaddress: true, // Note Yahoo uses \"-\"\n      }],\n      expect: {\n        'foo+bar@unknown.com': 'foo+bar@unknown.com',\n        'foo+bar@gmail.com': 'foo@gmail.com', // gmail_remove_subaddress\n        'foo+bar@me.com': 'foo@me.com', // icloud_remove_subaddress\n        'foo+bar@icloud.com': 'foo@icloud.com', // icloud_remove_subaddress\n        'foo+bar@live.fr': 'foo@live.fr', // outlookdotcom_remove_subaddress\n        'foo+bar@hotmail.co.uk': 'foo@hotmail.co.uk', // outlookdotcom_remove_subaddress\n        'foo-bar@yahoo.com': 'foo@yahoo.com', // yahoo_remove_subaddress\n        'foo+bar@yahoo.com': 'foo+bar@yahoo.com', // yahoo_remove_subaddress\n      },\n    });\n\n    // Testing gmail_convert_googlemaildotcom\n    test({\n      sanitizer: 'normalizeEmail',\n      args: [{\n        gmail_convert_googlemaildotcom: false,\n      }],\n      expect: {\n        'SOME.name@GMAIL.com': 'somename@gmail.com',\n        'SOME.name+me@GMAIL.com': 'somename@gmail.com',\n        'SOME.name+me@googlemail.com': 'somename@googlemail.com',\n        'SOME.name+me@googlemail.COM': 'somename@googlemail.com',\n        'SOME.name+me@googlEmail.com': 'somename@googlemail.com',\n        'my.self@foo.com': 'my.self@foo.com',\n      },\n    });\n\n    test({\n      sanitizer: 'normalizeEmail',\n      args: [{\n        gmail_convert_googlemaildotcom: true,\n      }],\n      expect: {\n        'SOME.name@GMAIL.com': 'somename@gmail.com',\n        'SOME.name+me@GMAIL.com': 'somename@gmail.com',\n        'SOME.name+me@googlemail.com': 'somename@gmail.com',\n        'SOME.name+me@googlemail.COM': 'somename@gmail.com',\n        'SOME.name+me@googlEmail.com': 'somename@gmail.com',\n        'my.self@foo.com': 'my.self@foo.com',\n      },\n    });\n\n    // Testing yandex_convert_yandexru\n    test({\n      sanitizer: 'normalizeEmail',\n      args: [{\n        yandex_convert_yandexru: false,\n      }],\n      expect: {\n        'test@yandex.kz': 'test@yandex.kz',\n        'test@yandex.ru': 'test@yandex.ru',\n        'test@yandex.ua': 'test@yandex.ua',\n        'test@yandex.com': 'test@yandex.com',\n        'test@yandex.by': 'test@yandex.by',\n      },\n    });\n\n    test({\n      sanitizer: 'normalizeEmail',\n      args: [{\n        yandex_convert_yandexru: true,\n      }],\n      expect: {\n        'test@yandex.kz': 'test@yandex.ru',\n        'test@yandex.ru': 'test@yandex.ru',\n        'test@yandex.ua': 'test@yandex.ru',\n        'test@yandex.com': 'test@yandex.ru',\n        'test@yandex.by': 'test@yandex.ru',\n      },\n    });\n  });\n});\n"
  },
  {
    "path": "test/testFunctions.js",
    "content": "import assert from 'assert';\nimport { format } from 'util';\nimport validator from '../src/index';\n\nfunction stringifyArgs(argsArr) {\n  return argsArr.map(arg => JSON.stringify(arg)).join(', ');\n}\n\nexport default function test(options) {\n  const args = options.args || [];\n\n  args.unshift(null);\n\n  if (options.error) {\n    options.error.forEach((error) => {\n      args[0] = error;\n\n      try {\n        assert.throws(() => validator[options.validator](...args));\n      } catch (err) {\n        const warning = format(\n          'validator.%s(%s) passed but should error',\n          options.validator, stringifyArgs(args)\n        );\n\n        throw new Error(warning);\n      }\n    });\n  }\n\n  if (options.valid) {\n    options.valid.forEach((valid) => {\n      args[0] = valid;\n\n      if (validator[options.validator](...args) !== true) {\n        const warning = format(\n          'validator.%s(%s) failed but should have passed',\n          options.validator, stringifyArgs(args)\n        );\n\n        throw new Error(warning);\n      }\n    });\n  }\n\n  if (options.invalid) {\n    options.invalid.forEach((invalid) => {\n      args[0] = invalid;\n\n      if (validator[options.validator](...args) !== false) {\n        const warning = format(\n          'validator.%s(%s) passed but should have failed',\n          options.validator, stringifyArgs(args)\n        );\n\n        throw new Error(warning);\n      }\n    });\n  }\n}\n"
  },
  {
    "path": "test/util.test.js",
    "content": "/**\n * All tests that tests any utility.\n * Prevent any breaking of functionality\n */\nimport assert from 'assert';\nimport typeOf from '../src/lib/util/typeOf';\nimport assertString from '../src/lib/util/assertString';\n\n\ndescribe('Util', () => {\n  it('should validate different typeOf', () => {\n    assert.strictEqual(typeOf([]), 'array');\n    assert.strictEqual(typeOf(null), 'null');\n    assert.strictEqual(typeOf({}), 'object');\n    assert.strictEqual(typeOf(new Date()), 'date');\n    assert.strictEqual(typeOf('ezkemboi'), 'string');\n    assert.strictEqual(typeOf(String('kemboi')), 'string');\n    assert.strictEqual(typeOf(undefined), 'undefined');\n    assert.strictEqual(typeOf(2021), 'number');\n    assert.notStrictEqual(typeOf([]), 'object');\n  });\n});\n\ndescribe('assertString', () => {\n  it('Should throw an error if argument provided is an undefined', () => {\n    assert.throws(() => { assertString(); }, TypeError);\n  });\n\n  it('Should throw an error if argument provided is a null', () => {\n    assert.throws(() => { assertString(null); }, TypeError);\n  });\n\n  it('Should throw an error if argument provided is a Boolean', () => {\n    assert.throws(() => { assertString(true); }, TypeError);\n  });\n\n  it('Should throw an error if argument provided is a Date', () => {\n    assert.throws(() => { assertString(new Date()); }, TypeError);\n  });\n\n  it('Should throw an error if argument provided is a Number(NaN)', () => {\n    assert.throws(() => { assertString(NaN); }, TypeError);\n  });\n\n  it('Should throw an error if argument provided is a Number', () => {\n    assert.throws(() => { assertString(2024); }, TypeError);\n  });\n\n  it('Should throw an error if argument provided is an Object', () => {\n    assert.throws(() => { assertString({}); }, TypeError);\n  });\n\n  it('Should throw an error if argument provided is an Array', () => {\n    assert.throws(() => { assertString([]); }, TypeError);\n  });\n\n  it('Should not throw an error if the argument is an empty string', () => {\n    assert.doesNotThrow(() => { assertString(''); });\n  });\n\n  it('Should not throw an error if the argument is a String', () => {\n    assert.doesNotThrow(() => { assertString('antidisestablishmentarianism'); });\n  });\n});\n"
  },
  {
    "path": "test/validators/isAfter.test.js",
    "content": "import test from '../testFunctions';\n\ndescribe('isAfter', () => {\n  it('should validate dates against a start date', () => {\n    test({\n      validator: 'isAfter',\n      args: [{ comparisonDate: '2011-08-03' }],\n      valid: ['2011-08-04', new Date(2011, 8, 10).toString()],\n      invalid: ['2010-07-02', '2011-08-03', new Date(0).toString(), 'foo'],\n    });\n\n    test({\n      validator: 'isAfter',\n      valid: ['2100-08-04', new Date(Date.now() + 86400000).toString()],\n      invalid: ['2010-07-02', new Date(0).toString()],\n    });\n\n    test({\n      validator: 'isAfter',\n      args: [{ comparisonDate: '2011-08-03' }],\n      valid: ['2015-09-17'],\n      invalid: ['invalid date'],\n    });\n\n    test({\n      validator: 'isAfter',\n      args: [{ comparisonDate: 'invalid date' }],\n      invalid: ['invalid date', '2015-09-17'],\n    });\n    test({\n      validator: 'isAfter',\n      args: [], // will fall back to the current date\n      valid: ['2100-08-04', new Date(Date.now() + 86400000).toString()],\n    });\n    test({\n      validator: 'isAfter',\n      args: [undefined], // will fall back to the current date\n      valid: ['2100-08-04', new Date(Date.now() + 86400000).toString()],\n    });\n    test({\n      validator: 'isAfter',\n      args: [{ comparisonDate: undefined }], // will fall back to the current date\n      valid: ['2100-08-04', new Date(Date.now() + 86400000).toString()],\n    });\n  });\n\n  describe('(legacy syntax)', () => {\n    it('should validate dates against a start date', () => {\n      test({\n        validator: 'isAfter',\n        args: ['2011-08-03'],\n        valid: ['2011-08-04', new Date(2011, 8, 10).toString()],\n        invalid: ['2010-07-02', '2011-08-03', new Date(0).toString(), 'foo'],\n      });\n\n      test({\n        validator: 'isAfter',\n        valid: ['2100-08-04', new Date(Date.now() + 86400000).toString()],\n        invalid: ['2010-07-02', new Date(0).toString()],\n      });\n\n      test({\n        validator: 'isAfter',\n        args: ['2011-08-03'],\n        valid: ['2015-09-17'],\n        invalid: ['invalid date'],\n      });\n\n      test({\n        validator: 'isAfter',\n        args: ['invalid date'],\n        invalid: ['invalid date', '2015-09-17'],\n      });\n    });\n  });\n});\n"
  },
  {
    "path": "test/validators/isBase64.test.js",
    "content": "import { format } from 'util';\nimport test from '../testFunctions';\nimport validator from '../../src';\n\ndescribe('isBase64', () => {\n  it('should validate base64 strings with default options', () => {\n    test({\n      validator: 'isBase64',\n      valid: [\n        '',\n        'Zg==',\n        'Zm8=',\n        'Zm9v',\n        'Zm9vYg==',\n        'Zm9vYmE=',\n        'Zm9vYmFy',\n        'TG9yZW0gaXBzdW0gZG9sb3Igc2l0IGFtZXQsIGNvbnNlY3RldHVyIGFkaXBpc2NpbmcgZWxpdC4=',\n        'Vml2YW11cyBmZXJtZW50dW0gc2VtcGVyIHBvcnRhLg==',\n        'U3VzcGVuZGlzc2UgbGVjdHVzIGxlbw==',\n        'MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuMPNS1Ufof9EW/M98FNw' +\n        'UAKrwflsqVxaxQjBQnHQmiI7Vac40t8x7pIb8gLGV6wL7sBTJiPovJ0V7y7oc0Ye' +\n        'rhKh0Rm4skP2z/jHwwZICgGzBvA0rH8xlhUiTvcwDCJ0kc+fh35hNt8srZQM4619' +\n        'FTgB66Xmp4EtVyhpQV+t02g6NzK72oZI0vnAvqhpkxLeLiMCyrI416wHm5Tkukhx' +\n        'QmcL2a6hNOyu0ixX/x2kSFXApEnVrJ+/IxGyfyw8kf4N2IZpW5nEP847lpfj0SZZ' +\n        'Fwrd1mnfnDbYohX2zRptLy2ZUn06Qo9pkG5ntvFEPo9bfZeULtjYzIl6K8gJ2uGZ' +\n        'HQIDAQAB',\n      ],\n      invalid: [\n        '12345',\n        'Vml2YW11cyBmZXJtZtesting123',\n        'Zg=',\n        'Z===',\n        'Zm=8',\n        '=m9vYg==',\n        'Zm9vYmFy====',\n      ],\n    });\n\n    test({\n      validator: 'isBase64',\n      args: [{ urlSafe: true }],\n      valid: [\n        '',\n        'bGFkaWVzIGFuZCBnZW50bGVtZW4sIHdlIGFyZSBmbG9hdGluZyBpbiBzcGFjZQ',\n        '1234',\n        'bXVtLW5ldmVyLXByb3Vk',\n        'PDw_Pz8-Pg',\n        'VGhpcyBpcyBhbiBlbmNvZGVkIHN0cmluZw',\n      ],\n      invalid: [\n        ' AA',\n        '\\tAA',\n        '\\rAA',\n        '\\nAA',\n        'This+isa/bad+base64Url==',\n        '0K3RgtC+INC30LDQutC+0LTQuNGA0L7QstCw0L3QvdCw0Y8g0YHRgtGA0L7QutCw',\n      ],\n      error: [\n        null,\n        undefined,\n        {},\n        [],\n        42,\n      ],\n    });\n\n    for (let i = 0, str = '', encoded; i < 1000; i++) {\n      str += String.fromCharCode(Math.random() * 26 | 97); // eslint-disable-line no-bitwise\n      encoded = Buffer.from(str).toString('base64');\n      if (!validator.isBase64(encoded)) {\n        let msg = format('validator.isBase64() failed with \"%s\"', encoded);\n        throw new Error(msg);\n      }\n    }\n  });\n\n  it('should validate standard Base64 with padding', () => {\n    test({\n      validator: 'isBase64',\n      args: [{ urlSafe: false, padding: true }],\n      valid: [\n        '',\n        'TWFu',\n        'TWE=',\n        'TQ==',\n        'SGVsbG8=',\n        'U29mdHdhcmU=',\n        'YW55IGNhcm5hbCBwbGVhc3VyZS4=',\n      ],\n      invalid: [\n        'TWF',\n        'TWE===',\n        'SGVsbG8@',\n        'SGVsbG8===',\n        'SGVsb G8=',\n        '====',\n      ],\n    });\n  });\n\n  it('should validate standard Base64 without padding', () => {\n    test({\n      validator: 'isBase64',\n      args: [{ urlSafe: false, padding: false }],\n      valid: [\n        '',\n        'TWFu',\n        'TWE',\n        'TQ',\n        'SGVsbG8',\n        'U29mdHdhcmU',\n        'YW55IGNhcm5hbCBwbGVhc3VyZS4',\n      ],\n      invalid: [\n        'TWE=',\n        'TQ===',\n        'SGVsbG8@',\n        'SGVsbG8===',\n        'SGVsb G8',\n        '====',\n      ],\n    });\n  });\n\n  it('should validate Base64url with padding', () => {\n    test({\n      validator: 'isBase64',\n      args: [{ urlSafe: true, padding: true }],\n      valid: [\n        '',\n        'SGVsbG8=',\n        'U29mdHdhcmU=',\n        'YW55IGNhcm5hbCBwbGVhc3VyZS4=',\n        'SGVsbG8-',\n        'SGVsbG8_',\n      ],\n      invalid: [\n        'SGVsbG8===',\n        'SGVsbG8@',\n        'SGVsb G8=',\n        '====',\n      ],\n    });\n  });\n\n  it('should validate Base64url without padding', () => {\n    test({\n      validator: 'isBase64',\n      args: [{ urlSafe: true, padding: false }],\n      valid: [\n        '',\n        'SGVsbG8',\n        'U29mdHdhcmU',\n        'YW55IGNhcm5hbCBwbGVhc3VyZS4',\n        'SGVsbG8-',\n        'SGVsbG8_',\n      ],\n      invalid: [\n        'SGVsbG8=',\n        'SGVsbG8===',\n        'SGVsbG8@',\n        'SGVsb G8',\n        '====',\n      ],\n    });\n  });\n\n  it('should handle mixed cases correctly', () => {\n    test({\n      validator: 'isBase64',\n      args: [{ urlSafe: false, padding: true }],\n      valid: [\n        '',\n        'TWFu',\n        'TWE=',\n        'TQ==',\n      ],\n      invalid: [\n        'TWE',\n        'TQ=',\n        'TQ===',\n      ],\n    });\n\n    test({\n      validator: 'isBase64',\n      args: [{ urlSafe: true, padding: false }],\n      valid: [\n        '',\n        'SGVsbG8',\n        'SGVsbG8-',\n        'SGVsbG8_',\n      ],\n      invalid: [\n        'SGVsbG8=',\n        'SGVsbG8@',\n        'SGVsb G8',\n      ],\n    });\n  });\n});\n"
  },
  {
    "path": "test/validators/isBefore.test.js",
    "content": "import { describe } from 'mocha';\nimport test from '../testFunctions';\n\ndescribe('isBefore', () => {\n  describe('should validate dates a given end date', () => {\n    describe('new syntax', () => {\n      test({\n        validator: 'isBefore',\n        args: [{ comparisonDate: '08/04/2011' }],\n        valid: ['2010-07-02', '2010-08-04', new Date(0).toString()],\n        invalid: ['08/04/2011', new Date(2011, 9, 10).toString()],\n      });\n      test({\n        validator: 'isBefore',\n        args: [{ comparisonDate: new Date(2011, 7, 4).toString() }],\n        valid: ['2010-07-02', '2010-08-04', new Date(0).toString()],\n        invalid: ['08/04/2011', new Date(2011, 9, 10).toString()],\n      });\n      test({\n        validator: 'isBefore',\n        args: [{ comparisonDate: '2011-08-03' }],\n        valid: ['1999-12-31'],\n        invalid: ['invalid date'],\n      });\n      test({\n        validator: 'isBefore',\n        args: [{ comparisonDate: 'invalid date' }],\n        invalid: ['invalid date', '1999-12-31'],\n      });\n    });\n\n    describe('legacy syntax', () => {\n      test({\n        validator: 'isBefore',\n        args: ['08/04/2011'],\n        valid: ['2010-07-02', '2010-08-04', new Date(0).toString()],\n        invalid: ['08/04/2011', new Date(2011, 9, 10).toString()],\n      });\n      test({\n        validator: 'isBefore',\n        args: [new Date(2011, 7, 4).toString()],\n        valid: ['2010-07-02', '2010-08-04', new Date(0).toString()],\n        invalid: ['08/04/2011', new Date(2011, 9, 10).toString()],\n      });\n      test({\n        validator: 'isBefore',\n        args: ['2011-08-03'],\n        valid: ['1999-12-31'],\n        invalid: ['invalid date'],\n      });\n      test({\n        validator: 'isBefore',\n        args: ['invalid date'],\n        invalid: ['invalid date', '1999-12-31'],\n      });\n    });\n  });\n\n  describe('should validate dates a default end date', () => {\n    describe('new syntax', () => {\n      test({\n        validator: 'isBefore',\n        valid: [\n          '2000-08-04',\n          new Date(0).toString(),\n          new Date(Date.now() - 86400000).toString(),\n        ],\n        invalid: ['2100-07-02', new Date(2217, 10, 10).toString()],\n      });\n      test({\n        validator: 'isBefore',\n        args: undefined, // will fall back to the current date\n        valid: ['1999-06-07'],\n      });\n      test({\n        validator: 'isBefore',\n        args: [], // will fall back to the current date\n        valid: ['1999-06-07'],\n      });\n      test({\n        validator: 'isBefore',\n        args: [undefined], // will fall back to the current date\n        valid: ['1999-06-07'],\n      });\n      test({\n        validator: 'isBefore',\n        args: [{ comparisonDate: undefined }], // will fall back to the current date\n        valid: ['1999-06-07'],\n      });\n    });\n\n    describe('legacy syntax', () => {\n      test({\n        validator: 'isBefore',\n        valid: [\n          '2000-08-04',\n          new Date(0).toString(),\n          new Date(Date.now() - 86400000).toString(),\n        ],\n        invalid: ['2100-07-02', new Date(2217, 10, 10).toString()],\n      });\n      test({\n        validator: 'isBefore',\n        args: undefined, // will fall back to the current date\n        valid: ['1999-06-07'],\n      });\n      test({\n        validator: 'isBefore',\n        args: [], // will fall back to the current date\n        valid: ['1999-06-07'],\n      });\n      test({\n        validator: 'isBefore',\n        args: [undefined], // will fall back to the current date\n        valid: ['1999-06-07'],\n      });\n    });\n  });\n});\n"
  },
  {
    "path": "test/validators/isFQDN.test.js",
    "content": "import test from '../testFunctions';\n\ndescribe('isFQDN', () => {\n  it('should validate domain names.', () => {\n    test({\n      validator: 'isFQDN',\n      args: [],\n      valid: [\n        'google.com',\n      ],\n      invalid: [\n        'google.l33t',\n      ],\n    });\n    test({\n      validator: 'isFQDN',\n      args: [{ allow_numeric_tld: true }],\n      valid: [\n        'google.com',\n        'google.l33t',\n      ],\n      invalid: [\n      ],\n    });\n  });\n});\n"
  },
  {
    "path": "test/validators/isIP.test.js",
    "content": "import test from '../testFunctions';\n\ndescribe('isIP', () => {\n  it('should validate IP addresses', () => {\n    test({\n      validator: 'isIP',\n      valid: [\n        '127.0.0.1',\n        '0.0.0.0',\n        '255.255.255.255',\n        '1.2.3.4',\n        '::1',\n        '2001:db8:0000:1:1:1:1:1',\n        '2001:db8:3:4::192.0.2.33',\n        '2001:41d0:2:a141::1',\n        '::ffff:127.0.0.1',\n        '::0000',\n        '0000::',\n        '1::',\n        '1111:1:1:1:1:1:1:1',\n        'fe80::a6db:30ff:fe98:e946',\n        '::',\n        '::8',\n        '::ffff:127.0.0.1',\n        '::ffff:255.255.255.255',\n        '::ffff:0:255.255.255.255',\n        '::2:3:4:5:6:7:8',\n        '::255.255.255.255',\n        '0:0:0:0:0:ffff:127.0.0.1',\n        '1:2:3:4:5:6:7::',\n        '1:2:3:4:5:6::8',\n        '1::7:8',\n        '1:2:3:4:5::7:8',\n        '1:2:3:4:5::8',\n        '1::6:7:8',\n        '1:2:3:4::6:7:8',\n        '1:2:3:4::8',\n        '1::5:6:7:8',\n        '1:2:3::5:6:7:8',\n        '1:2:3::8',\n        '1::4:5:6:7:8',\n        '1:2::4:5:6:7:8',\n        '1:2::8',\n        '1::3:4:5:6:7:8',\n        '1::8',\n        'fe80::7:8%eth0',\n        'fe80::7:8%1',\n        '64:ff9b::192.0.2.33',\n        '0:0:0:0:0:0:10.0.0.1',\n      ],\n      invalid: [\n        'abc',\n        '256.0.0.0',\n        '0.0.0.256',\n        '26.0.0.256',\n        '0200.200.200.200',\n        '200.0200.200.200',\n        '200.200.0200.200',\n        '200.200.200.0200',\n        '::banana',\n        'banana::',\n        '::1banana',\n        '::1::',\n        '1:',\n        ':1',\n        ':1:1:1::2',\n        '1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1',\n        '::11111',\n        '11111:1:1:1:1:1:1:1',\n        '2001:db8:0000:1:1:1:1::1',\n        '0:0:0:0:0:0:ffff:127.0.0.1',\n        '0:0:0:0:ffff:127.0.0.1',\n        'BC:e4d5:c:e7b9::%40i0nccymtl9cwfKo.5vaeXLSGRMe:EDh2qs5wkhnPws5xQKqafjfAMm6wGFCJ.bVFsZfb',\n        '1dC:0DF8:62D:3AC::%KTatXocjaFVioS0RTNQl4mA.V151o0RSy.JIu-D-D8.d3171ZWsSJ7PK4YjkJCRN0F',\n      ],\n    });\n\n    test({\n      validator: 'isIP',\n      args: [{ version: 'invalid version' }],\n      valid: [],\n      invalid: [\n        '127.0.0.1',\n        '0.0.0.0',\n        '255.255.255.255',\n        '1.2.3.4',\n      ],\n    });\n\n    test({\n      validator: 'isIP',\n      args: [{ version: null }],\n      valid: [\n        '127.0.0.1',\n        '0.0.0.0',\n        '255.255.255.255',\n        '1.2.3.4',\n      ],\n    });\n\n    test({\n      validator: 'isIP',\n      args: [{ version: undefined }],\n      valid: [\n        '127.0.0.1',\n        '0.0.0.0',\n        '255.255.255.255',\n        '1.2.3.4',\n      ],\n    });\n\n    test({\n      validator: 'isIP',\n      args: [{ version: 4 }],\n      valid: [\n        '127.0.0.1',\n        '0.0.0.0',\n        '255.255.255.255',\n        '1.2.3.4',\n        '255.0.0.1',\n        '0.0.1.1',\n      ],\n      invalid: [\n        '::1',\n        '2001:db8:0000:1:1:1:1:1',\n        '::ffff:127.0.0.1',\n        '137.132.10.01',\n        '0.256.0.256',\n        '255.256.255.256',\n      ],\n    });\n\n    test({\n      validator: 'isIP',\n      args: [{ version: 6 }],\n      valid: [\n        '::1',\n        '2001:db8:0000:1:1:1:1:1',\n        '::ffff:127.0.0.1',\n        'fe80::1234%1',\n        'ff08::9abc%10',\n        'ff08::9abc%interface10',\n        'ff02::5678%pvc1.3',\n      ],\n      invalid: [\n        '127.0.0.1',\n        '0.0.0.0',\n        '255.255.255.255',\n        '1.2.3.4',\n        '::ffff:287.0.0.1',\n        '%',\n        'fe80::1234%',\n        'fe80::1234%1%3%4',\n        'fe80%fe80%',\n      ],\n    });\n\n    test({\n      validator: 'isIP',\n      args: [{ version: 10 }],\n      valid: [],\n      invalid: [\n        '127.0.0.1',\n        '0.0.0.0',\n        '255.255.255.255',\n        '1.2.3.4',\n        '::1',\n        '2001:db8:0000:1:1:1:1:1',\n      ],\n    });\n  });\n\n  describe('legacy syntax', () => {\n    it('should validate IP addresses', () => {\n      test({\n        validator: 'isIP',\n        valid: [\n          '127.0.0.1',\n          '0.0.0.0',\n          '255.255.255.255',\n          '1.2.3.4',\n          '::1',\n          '2001:db8:0000:1:1:1:1:1',\n          '2001:db8:3:4::192.0.2.33',\n          '2001:41d0:2:a141::1',\n          '::ffff:127.0.0.1',\n          '::0000',\n          '0000::',\n          '1::',\n          '1111:1:1:1:1:1:1:1',\n          'fe80::a6db:30ff:fe98:e946',\n          '::',\n          '::8',\n          '::ffff:127.0.0.1',\n          '::ffff:255.255.255.255',\n          '::ffff:0:255.255.255.255',\n          '::2:3:4:5:6:7:8',\n          '::255.255.255.255',\n          '0:0:0:0:0:ffff:127.0.0.1',\n          '1:2:3:4:5:6:7::',\n          '1:2:3:4:5:6::8',\n          '1::7:8',\n          '1:2:3:4:5::7:8',\n          '1:2:3:4:5::8',\n          '1::6:7:8',\n          '1:2:3:4::6:7:8',\n          '1:2:3:4::8',\n          '1::5:6:7:8',\n          '1:2:3::5:6:7:8',\n          '1:2:3::8',\n          '1::4:5:6:7:8',\n          '1:2::4:5:6:7:8',\n          '1:2::8',\n          '1::3:4:5:6:7:8',\n          '1::8',\n          'fe80::7:8%eth0',\n          'fe80::7:8%1',\n          '64:ff9b::192.0.2.33',\n          '0:0:0:0:0:0:10.0.0.1',\n        ],\n        invalid: [\n          'abc',\n          '256.0.0.0',\n          '0.0.0.256',\n          '26.0.0.256',\n          '0200.200.200.200',\n          '200.0200.200.200',\n          '200.200.0200.200',\n          '200.200.200.0200',\n          '::banana',\n          'banana::',\n          '::1banana',\n          '::1::',\n          '1:',\n          ':1',\n          ':1:1:1::2',\n          '1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1',\n          '::11111',\n          '11111:1:1:1:1:1:1:1',\n          '2001:db8:0000:1:1:1:1::1',\n          '0:0:0:0:0:0:ffff:127.0.0.1',\n          '0:0:0:0:ffff:127.0.0.1',\n        ],\n      });\n      test({\n        validator: 'isIP',\n        args: [4],\n        valid: [\n          '127.0.0.1',\n          '0.0.0.0',\n          '255.255.255.255',\n          '1.2.3.4',\n          '255.0.0.1',\n          '0.0.1.1',\n        ],\n        invalid: [\n          '::1',\n          '2001:db8:0000:1:1:1:1:1',\n          '::ffff:127.0.0.1',\n          '137.132.10.01',\n          '0.256.0.256',\n          '255.256.255.256',\n        ],\n      });\n      test({\n        validator: 'isIP',\n        args: [6],\n        valid: [\n          '::1',\n          '2001:db8:0000:1:1:1:1:1',\n          '::ffff:127.0.0.1',\n          'fe80::1234%1',\n          'ff08::9abc%10',\n          'ff08::9abc%interface10',\n          'ff02::5678%pvc1.3',\n        ],\n        invalid: [\n          '127.0.0.1',\n          '0.0.0.0',\n          '255.255.255.255',\n          '1.2.3.4',\n          '::ffff:287.0.0.1',\n          '%',\n          'fe80::1234%',\n          'fe80::1234%1%3%4',\n          'fe80%fe80%',\n        ],\n      });\n      test({\n        validator: 'isIP',\n        args: [10],\n        valid: [],\n        invalid: [\n          '127.0.0.1',\n          '0.0.0.0',\n          '255.255.255.255',\n          '1.2.3.4',\n          '::1',\n          '2001:db8:0000:1:1:1:1:1',\n        ],\n      });\n    });\n  });\n});\n"
  },
  {
    "path": "test/validators/isISBN.test.js",
    "content": "import test from '../testFunctions';\n\ndescribe('isISBN', () => {\n  it('should validate ISBNs', () => {\n    test({\n      validator: 'isISBN',\n      args: [{ version: 10 }],\n      valid: [\n        '3836221195', '3-8362-2119-5', '3 8362 2119 5',\n        '1617290858', '1-61729-085-8', '1 61729 085-8',\n        '0007269706', '0-00-726970-6', '0 00 726970 6',\n        '3423214120', '3-423-21412-0', '3 423 21412 0',\n        '340101319X', '3-401-01319-X', '3 401 01319 X',\n      ],\n      invalid: [\n        '3423214121', '3-423-21412-1', '3 423 21412 1',\n        '978-3836221191', '9783836221191',\n        '123456789a', 'foo', '',\n      ],\n    });\n    test({\n      validator: 'isISBN',\n      args: [{ version: 13 }],\n      valid: [\n        '9783836221191', '978-3-8362-2119-1', '978 3 8362 2119 1',\n        '9783401013190', '978-3401013190', '978 3401013190',\n        '9784873113685', '978-4-87311-368-5', '978 4 87311 368 5',\n      ],\n      invalid: [\n        '9783836221190', '978-3-8362-2119-0', '978 3 8362 2119 0',\n        '3836221195', '3-8362-2119-5', '3 8362 2119 5',\n        '01234567890ab', 'foo', '',\n      ],\n    });\n    test({\n      validator: 'isISBN',\n      valid: [\n        '340101319X',\n        '9784873113685',\n      ],\n      invalid: [\n        '3423214121',\n        '9783836221190',\n      ],\n    });\n    test({\n      validator: 'isISBN',\n      args: [{ version: 'foo' }],\n      invalid: [\n        '340101319X',\n        '9784873113685',\n      ],\n    });\n  });\n\n  describe('(legacy syntax)', () => {\n    it('should validate ISBNs', () => {\n      test({\n        validator: 'isISBN',\n        args: [10],\n        valid: [\n          '3836221195', '3-8362-2119-5', '3 8362 2119 5',\n          '1617290858', '1-61729-085-8', '1 61729 085-8',\n          '0007269706', '0-00-726970-6', '0 00 726970 6',\n          '3423214120', '3-423-21412-0', '3 423 21412 0',\n          '340101319X', '3-401-01319-X', '3 401 01319 X',\n        ],\n        invalid: [\n          '3423214121', '3-423-21412-1', '3 423 21412 1',\n          '978-3836221191', '9783836221191',\n          '123456789a', 'foo', '',\n        ],\n      });\n      test({\n        validator: 'isISBN',\n        args: [13],\n        valid: [\n          '9783836221191', '978-3-8362-2119-1', '978 3 8362 2119 1',\n          '9783401013190', '978-3401013190', '978 3401013190',\n          '9784873113685', '978-4-87311-368-5', '978 4 87311 368 5',\n        ],\n        invalid: [\n          '9783836221190', '978-3-8362-2119-0', '978 3 8362 2119 0',\n          '3836221195', '3-8362-2119-5', '3 8362 2119 5',\n          '01234567890ab', 'foo', '',\n        ],\n      });\n      test({\n        validator: 'isISBN',\n        valid: [\n          '340101319X',\n          '9784873113685',\n        ],\n        invalid: [\n          '3423214121',\n          '9783836221190',\n        ],\n      });\n      test({\n        validator: 'isISBN',\n        args: ['foo'],\n        invalid: [\n          '340101319X',\n          '9784873113685',\n        ],\n      });\n    });\n  });\n});\n"
  },
  {
    "path": "test/validators/isISO31661Alpha2.test.js",
    "content": "import test from '../testFunctions';\n\ndescribe('isISO31661Alpha2', () => {\n  it('should validate ISO 3166-1 alpha 2 country codes', () => {\n    // from https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2\n    test({\n      validator: 'isISO31661Alpha2',\n      valid: [\n        'FR',\n        'fR',\n        'GB',\n        'PT',\n        'CM',\n        'JP',\n        'PM',\n        'ZW',\n        'MM',\n        'cc',\n        'GG',\n      ],\n      invalid: [\n        '',\n        'FRA',\n        'AA',\n        'PI',\n        'RP',\n        'WV',\n        'WL',\n        'UK',\n        'ZZ',\n      ],\n    });\n  });\n\n  it('should validate user assigned alpha 2 code if provided', () => {\n    test({\n      validator: 'isISO31661Alpha2',\n      args: [{ userAssignedCodes: ['XK', 'xl', '', 'x'] }],\n      valid: ['BE', 'FR', 'GB', 'US', 'XK', 'XL'],\n      invalid: ['XA', 'XB'],\n    });\n  });\n\n  it('should not validate user assigned alpha 2 not valid code if provided', () => {\n    test({\n      validator: 'isISO31661Alpha2',\n      args: [{ userAssignedCodes: ['', 'x', 'XXX'] }],\n      valid: ['FR'],\n      invalid: ['XXX', 'X'],\n    });\n  });\n\n  it('should still validate ISO 3166-1 alpha 2 country codes if the options object is empty', () => {\n    test({\n      validator: 'isISO31661Alpha2',\n      args: [{}],\n      valid: ['FR', 'US'],\n      invalid: ['XK'],\n    });\n  });\n\n  it('should still validate ISO 3166-1 alpha 2 country codes if the userAssignedCodes option is empty', () => {\n    test({\n      validator: 'isISO31661Alpha2',\n      args: [{ userAssignedCodes: [] }],\n      valid: ['FR', 'US'],\n      invalid: ['XK'],\n    });\n  });\n});\n"
  },
  {
    "path": "test/validators/isISO31661Alpha3.test.js",
    "content": "import test from '../testFunctions';\n\ndescribe('isISO31661Alpha3', () => {\n  it('should validate ISO 3166-1 alpha 3 country codes', () => {\n    // from https://en.wikipedia.org/wiki/ISO_3166-1_alpha-3\n    test({\n      validator: 'isISO31661Alpha3',\n      valid: [\n        'ABW',\n        'HND',\n        'KHM',\n        'RWA',\n      ],\n      invalid: [\n        '',\n        'FR',\n        'fR',\n        'GB',\n        'PT',\n        'CM',\n        'JP',\n        'PM',\n        'ZW',\n        'XXK',\n      ],\n    });\n  });\n\n  it('should validate user assigned ISO 3166-1 alpha 3 code if provided', () => {\n    test({\n      validator: 'isISO31661Alpha3',\n      args: [{ userAssignedCodes: ['XXK', 'xxl'] }],\n      valid: ['BEL', 'FRA', 'GBR', 'USA', 'XXK', 'XXL'],\n      invalid: ['XXA', 'GGG'],\n    });\n  });\n\n  it('should not validate user assigned ISO 3166-1 alpha 3 not valid code if provided', () => {\n    test({\n      validator: 'isISO31661Alpha3',\n      args: [{ userAssignedCodes: ['', 'x', 'XX', 'XXXX'] }],\n      valid: ['FRA'],\n      invalid: ['XX', 'XXXX', 'X'],\n    });\n  });\n\n  it('should still validate ISO 3166-1 alpha 3 country codes if the options object is empty', () => {\n    test({\n      validator: 'isISO31661Alpha3',\n      args: [{}],\n      valid: ['FRA', 'USA'],\n      invalid: ['XXK'],\n    });\n  });\n\n  it('should still validate ISO 3166-1 alpha 3 country codes if the userAssignedCodes option is empty', () => {\n    test({\n      validator: 'isISO31661Alpha3',\n      args: [{ userAssignedCodes: [] }],\n      valid: ['FRA', 'USA'],\n      invalid: ['XXK'],\n    });\n  });\n});\n"
  },
  {
    "path": "test/validators/isLength.test.js",
    "content": "import test from '../testFunctions';\n\ndescribe('isLength', () => {\n  it('should return false for a string with length greater than the max', () => {\n    test({\n      validator: 'isLength',\n      args: [{ max: 3 }],\n      invalid: ['test'],\n    });\n  });\n\n  it('should return true for a string with length equal to the max', () => {\n    test({\n      validator: 'isLength',\n      args: [{ max: 4 }],\n      valid: ['test'],\n    });\n  });\n\n  it('should correctly calculate the length of a string with presentation sequences', () => {\n    test({\n      validator: 'isLength',\n      args: [{ max: 4 }],\n      valid: ['test\\uFE0F'],\n    });\n\n    test({\n      validator: 'isLength',\n      args: [{ min: 5, max: 5 }],\n      valid: ['test\\uFE0F\\uFE0F'],\n    });\n\n    test({\n      validator: 'isLength',\n      args: [{ min: 5, max: 5 }],\n      valid: ['\\uFE0Ftest'],\n    });\n\n    test({\n      validator: 'isLength',\n      args: [{ min: 9, max: 9 }],\n      valid: ['test\\uFE0F\\uFE0F\\uFE0F\\uFE0F\\uFE0F\\uFE0F'],\n    });\n  });\n\n  it('should validate strings by length (deprecated api)', () => {\n    test({\n      validator: 'isLength',\n      args: [2],\n      valid: ['abc', 'de', 'abcd'],\n      invalid: ['', 'a'],\n    });\n    test({\n      validator: 'isLength',\n      args: [2, 3],\n      valid: ['abc', 'de'],\n      invalid: ['', 'a', 'abcd'],\n    });\n    test({\n      validator: 'isLength',\n      args: [2, 3],\n      valid: ['干𩸽', '𠮷野家'],\n      invalid: ['', '𠀋', '千竈通り'],\n    });\n    test({\n      validator: 'isLength',\n      args: [0, 0],\n      valid: [''],\n      invalid: ['a', 'ab'],\n    });\n  });\n\n  it('should validate strings by length', () => {\n    test({\n      validator: 'isLength',\n      args: [{ min: 2 }],\n      valid: ['abc', 'de', 'abcd'],\n      invalid: ['', 'a'],\n    });\n    test({\n      validator: 'isLength',\n      args: [{ min: 2, max: 3 }],\n      valid: ['abc', 'de'],\n      invalid: ['', 'a', 'abcd'],\n    });\n    test({\n      validator: 'isLength',\n      args: [{ min: 2, max: 3 }],\n      valid: ['干𩸽', '𠮷野家'],\n      invalid: ['', '𠀋', '千竈通り'],\n    });\n    test({\n      validator: 'isLength',\n      args: [{ max: 3 }],\n      valid: ['abc', 'de', 'a', ''],\n      invalid: ['abcd'],\n    });\n    test({\n      validator: 'isLength',\n      args: [{ max: 6, discreteLengths: 5 }],\n      valid: ['abcd', 'vfd', 'ff', '', 'k'],\n      invalid: ['abcdefgh', 'hfjdksks'],\n    });\n    test({\n      validator: 'isLength',\n      args: [{ min: 2, max: 6, discreteLengths: 5 }],\n      valid: ['bsa', 'vfvd', 'ff'],\n      invalid: ['', ' ', 'hfskdunvc'],\n    });\n    test({\n      validator: 'isLength',\n      args: [{ min: 1, discreteLengths: 2 }],\n      valid: [' ', 'hello', 'bsa'],\n      invalid: [''],\n    });\n    test({\n      validator: 'isLength',\n      args: [{ max: 0 }],\n      valid: [''],\n      invalid: ['a', 'ab'],\n    });\n    test({\n      validator: 'isLength',\n      args: [{ min: 5, max: 10, discreteLengths: [2, 6, 8, 9] }],\n      valid: ['helloguy', 'shopping', 'validator', 'length'],\n      invalid: ['abcde', 'abcdefg'],\n    });\n    test({\n      validator: 'isLength',\n      args: [{ discreteLengths: '9' }],\n      valid: ['a', 'abcd', 'abcdefghijkl'],\n      invalid: [],\n    });\n    test({\n      validator: 'isLength',\n      valid: ['a', '', 'asds'],\n    });\n    test({\n      validator: 'isLength',\n      args: [{ max: 8 }],\n      valid: ['👩🦰👩👩👦👦🏳️🌈', '⏩︎⏩︎⏪︎⏪︎⏭︎⏭︎⏮︎⏮︎'],\n    });\n  });\n\n  it('should return true if string exactly match min/max bounds', () => {\n    test({\n      validator: 'isLength',\n      args: [{ min: 3, max: 3 }],\n      valid: ['abc', 'def'],\n      invalid: ['abcd', 'efgh'],\n    });\n  });\n\n  it('should count emojis as single character', () => {\n    test({\n      validator: 'isLength',\n      args: [{ min: 1, max: 1 }],\n      valid: ['🚀', '🍕', 'A'],\n      invalid: ['🚀🚀', ''],\n    });\n  });\n\n  it('should only allow strings with specific lengths from a list', () => {\n    test({\n      validator: 'isLength',\n      args: [{ discreteLengths: [2, 5] }],\n      valid: ['to', 'hello'],\n      invalid: ['a', 'cat', 'lengthy'],\n    });\n  });\n});\n"
  },
  {
    "path": "test/validators.test.js",
    "content": "import assert from 'assert';\nimport fs from 'fs';\nimport timezone_mock from 'timezone-mock';\nimport vm from 'vm';\nimport validator from '../index';\nimport test from './testFunctions';\n\nlet validator_js = fs.readFileSync(require.resolve('../validator.js')).toString();\n\ndescribe('Validators', () => {\n  it('should validate email addresses', () => {\n    test({\n      validator: 'isEmail',\n      valid: [\n        'foo@bar.com',\n        'x@x.au',\n        'foo@bar.com.au',\n        'foo+bar@bar.com',\n        'hans.m端ller@test.com',\n        'hans@m端ller.com',\n        'test|123@m端ller.com',\n        'test123+ext@gmail.com',\n        'some.name.midd.leNa.me.and.locality+extension@GoogleMail.com',\n        '\"foobar\"@example.com',\n        '\"  foo  m端ller \"@example.com',\n        '\"foo\\\\@bar\"@example.com',\n        `${'a'.repeat(64)}@${'a'.repeat(63)}.com`,\n        `${'a'.repeat(64)}@${'a'.repeat(63)}.com`,\n        `${'a'.repeat(31)}@gmail.com`,\n        'test@gmail.com',\n        'test.1@gmail.com',\n        'test@1337.com',\n      ],\n      invalid: [\n        'invalidemail@',\n        'invalid.com',\n        '@invalid.com',\n        'foo@bar.com.',\n        'foo@_bar.com',\n        'somename@ｇｍａｉｌ.com',\n        'foo@bar.co.uk.',\n        'z@co.c',\n        'ｇｍａｉｌｇｍａｉｌｇｍａｉｌｇｍａｉｌｇｍａｉｌ@gmail.com',\n        `${'a'.repeat(64)}@${'a'.repeat(251)}.com`,\n        `${'a'.repeat(65)}@${'a'.repeat(250)}.com`,\n        `${'a'.repeat(64)}@${'a'.repeat(64)}.com`,\n        `${'a'.repeat(64)}@${'a'.repeat(63)}.${'a'.repeat(63)}.${'a'.repeat(63)}.${'a'.repeat(58)}.com`,\n        'test1@invalid.co m',\n        'test2@invalid.co m',\n        'test3@invalid.co m',\n        'test4@invalid.co m',\n        'test5@invalid.co m',\n        'test6@invalid.co m',\n        'test7@invalid.co m',\n        'test8@invalid.co m',\n        'test9@invalid.co m',\n        'test10@invalid.co m',\n        'test11@invalid.co m',\n        'test12@invalid.co　m',\n        'test13@invalid.co　m',\n        'multiple..dots@stillinvalid.com',\n        'test123+invalid! sub_address@gmail.com',\n        'gmail...ignores...dots...@gmail.com',\n        'ends.with.dot.@gmail.com',\n        'multiple..dots@gmail.com',\n        'wrong()[]\",:;<>@@gmail.com',\n        '\"wrong()[]\",:;<>@@gmail.com',\n        'username@domain.com�',\n        'username@domain.com©',\n        'nbsp test@test.com',\n        'nbsp_test@te st.com',\n        'nbsp_test@test.co m',\n        '\"foobar@gmail.com',\n        '\"foo\"bar@gmail.com',\n        'foo\"bar\"@gmail.com',\n      ],\n    });\n  });\n\n  it('should validate email addresses with domain specific validation', () => {\n    test({\n      validator: 'isEmail',\n      args: [{ domain_specific_validation: true }],\n      valid: [\n        'foobar@gmail.com',\n        'foo.bar@gmail.com',\n        'foo.bar@googlemail.com',\n        `${'a'.repeat(30)}@gmail.com`,\n      ],\n      invalid: [\n        `${'a'.repeat(31)}@gmail.com`,\n        'test@gmail.com',\n        'test.1@gmail.com',\n        '.foobar@gmail.com',\n      ],\n    });\n  });\n\n  it('should validate email addresses with underscores in the domain', () => {\n    test({\n      validator: 'isEmail',\n      args: [{ allow_underscores: true }],\n      valid: [\n        'foobar@my_sarisari_store.typepad.com',\n      ],\n      invalid: [],\n    });\n  });\n\n  it('should validate email addresses without UTF8 characters in local part', () => {\n    test({\n      validator: 'isEmail',\n      args: [{ allow_utf8_local_part: false }],\n      valid: [\n        'foo@bar.com',\n        'x@x.au',\n        'foo@bar.com.au',\n        'foo+bar@bar.com',\n        'hans@m端ller.com',\n        'test|123@m端ller.com',\n        'test123+ext@gmail.com',\n        'some.name.midd.leNa.me+extension@GoogleMail.com',\n        '\"foobar\"@example.com',\n        '\"foo\\\\@bar\"@example.com',\n        '\"  foo  bar  \"@example.com',\n      ],\n      invalid: [\n        'invalidemail@',\n        'invalid.com',\n        '@invalid.com',\n        'foo@bar.com.',\n        'foo@bar.co.uk.',\n        'somename@ｇｍａｉｌ.com',\n        'hans.m端ller@test.com',\n        'z@co.c',\n        'tüst@invalid.com',\n        'nbsp test@test.com',\n      ],\n    });\n  });\n\n  it('should validate email addresses with display names', () => {\n    test({\n      validator: 'isEmail',\n      args: [{ allow_display_name: true }],\n      valid: [\n        'foo@bar.com',\n        'x@x.au',\n        'foo@bar.com.au',\n        'foo+bar@bar.com',\n        'hans.m端ller@test.com',\n        'hans@m端ller.com',\n        'test|123@m端ller.com',\n        'test123+ext@gmail.com',\n        'some.name.midd.leNa.me+extension@GoogleMail.com',\n        'Some Name <foo@bar.com>',\n        'Some Name <x@x.au>',\n        'Some Name <foo@bar.com.au>',\n        'Some Name <foo+bar@bar.com>',\n        'Some Name <hans.m端ller@test.com>',\n        'Some Name <hans@m端ller.com>',\n        'Some Name <test|123@m端ller.com>',\n        'Some Name <test123+ext@gmail.com>',\n        '\\'Foo Bar, Esq\\'<foo@bar.com>',\n        'Some Name <some.name.midd.leNa.me+extension@GoogleMail.com>',\n        'Some Middle Name <some.name.midd.leNa.me+extension@GoogleMail.com>',\n        'Name <some.name.midd.leNa.me+extension@GoogleMail.com>',\n        'Name<some.name.midd.leNa.me+extension@GoogleMail.com>',\n        'Some Name <foo@gmail.com>',\n        'Name🍓With🍑Emoji🚴‍♀️🏆<test@aftership.com>',\n        '🍇🍗🍑<only_emoji@aftership.com>',\n        '\"<displayNameInBrackets>\"<jh@gmail.com>',\n        '\"\\\\\"quotes\\\\\"\"<jh@gmail.com>',\n        '\"name;\"<jh@gmail.com>',\n        '\"name;\" <jh@gmail.com>',\n      ],\n      invalid: [\n        'invalidemail@',\n        'invalid.com',\n        '@invalid.com',\n        'foo@bar.com.',\n        'foo@bar.co.uk.',\n        'Some Name <invalidemail@>',\n        'Some Name <invalid.com>',\n        'Some Name <@invalid.com>',\n        'Some Name <foo@bar.com.>',\n        'Some Name <foo@bar.co.uk.>',\n        'Some Name foo@bar.co.uk.>',\n        'Some Name <foo@bar.co.uk.',\n        'Some Name < foo@bar.co.uk >',\n        'Name foo@bar.co.uk',\n        'Some Name <some..name@gmail.com>',\n        'Some Name<emoji_in_address🍈@aftership.com>',\n        'invisibleCharacter\\u001F<jh@gmail.com>',\n        '<displayNameInBrackets><jh@gmail.com>',\n        '\\\\\"quotes\\\\\"<jh@gmail.com>',\n        '\"\"quotes\"\"<jh@gmail.com>',\n        'name;<jh@gmail.com>',\n        '    <jh@gmail.com>',\n        '\"    \"<jh@gmail.com>',\n      ],\n    });\n  });\n\n  it('should validate email addresses with required display names', () => {\n    test({\n      validator: 'isEmail',\n      args: [{ require_display_name: true }],\n      valid: [\n        'Some Name <foo@bar.com>',\n        'Some Name <x@x.au>',\n        'Some Name <foo@bar.com.au>',\n        'Some Name <foo+bar@bar.com>',\n        'Some Name <hans.m端ller@test.com>',\n        'Some Name <hans@m端ller.com>',\n        'Some Name <test|123@m端ller.com>',\n        'Some Name <test123+ext@gmail.com>',\n        'Some Name <some.name.midd.leNa.me+extension@GoogleMail.com>',\n        'Some Middle Name <some.name.midd.leNa.me+extension@GoogleMail.com>',\n        'Name <some.name.midd.leNa.me+extension@GoogleMail.com>',\n        'Name<some.name.midd.leNa.me+extension@GoogleMail.com>',\n      ],\n      invalid: [\n        'some.name.midd.leNa.me+extension@GoogleMail.com',\n        'foo@bar.com',\n        'x@x.au',\n        'foo@bar.com.au',\n        'foo+bar@bar.com',\n        'hans.m端ller@test.com',\n        'hans@m端ller.com',\n        'test|123@m端ller.com',\n        'test123+ext@gmail.com',\n        'invalidemail@',\n        'invalid.com',\n        '@invalid.com',\n        'foo@bar.com.',\n        'foo@bar.co.uk.',\n        'Some Name <invalidemail@>',\n        'Some Name <invalid.com>',\n        'Some Name <@invalid.com>',\n        'Some Name <foo@bar.com.>',\n        'Some Name <foo@bar.co.uk.>',\n        'Some Name foo@bar.co.uk.>',\n        'Some Name <foo@bar.co.uk.',\n        'Some Name < foo@bar.co.uk >',\n        'Name foo@bar.co.uk',\n      ],\n    });\n  });\n\n  it('should validate email addresses with allowed IPs', () => {\n    test({\n      validator: 'isEmail',\n      args: [{ allow_ip_domain: true }],\n      valid: [\n        'email@[123.123.123.123]',\n        'email@255.255.255.255',\n      ],\n      invalid: [\n        'email@0.0.0.256',\n        'email@26.0.0.256',\n        'email@[266.266.266.266]',\n      ],\n    });\n  });\n\n  it('should not validate email addresses with blacklisted chars in the name', () => {\n    test({\n      validator: 'isEmail',\n      args: [{ blacklisted_chars: 'abc\"' }],\n      valid: [\n        'emil@gmail.com',\n      ],\n      invalid: [\n        'email@gmail.com',\n        '\"foobr\"@example.com',\n        '\" foo m端ller \"@example.com',\n        '\"foo\\@br\"@example.com',\n      ],\n    });\n  });\n\n\n  it('should validate really long emails if ignore_max_length is set', () => {\n    test({\n      validator: 'isEmail',\n      args: [{ ignore_max_length: false }],\n      valid: [],\n      invalid: [\n        'Deleted-user-id-19430-Team-5051deleted-user-id-19430-team-5051XXXXXX@example.com',\n      ],\n    });\n\n    test({\n      validator: 'isEmail',\n      args: [{ ignore_max_length: true }],\n      valid: [\n        'Deleted-user-id-19430-Team-5051deleted-user-id-19430-team-5051XXXXXX@example.com',\n      ],\n      invalid: [],\n    });\n\n    test({\n      validator: 'isEmail',\n      args: [{ ignore_max_length: true }],\n      valid: [\n        'Deleted-user-id-19430-Team-5051deleted-user-id-19430-team-5051XXXXXX@Deleted-user-id-19430-Team-5051deleted-user-id-19430-team-5051XXXXXX.com',\n      ],\n      invalid: [],\n    });\n  });\n\n  it('should not validate email addresses with denylisted domains', () => {\n    test({\n      validator: 'isEmail',\n      args: [{ host_blacklist: ['gmail.com', 'foo.bar.com'] }],\n      valid: [\n        'email@foo.gmail.com',\n      ],\n      invalid: [\n        'foo+bar@gmail.com',\n        'email@foo.bar.com',\n      ],\n    });\n  });\n\n  it('should allow regular expressions in the host blacklist of isEmail', () => {\n    test({\n      validator: 'isEmail',\n      args: [{\n        host_blacklist: ['bar.com', 'foo.com', /\\.foo\\.com$/],\n      }],\n      valid: [\n        'email@foobar.com',\n        'email@foo.bar.com',\n        'email@qux.com',\n      ],\n      invalid: [\n        'email@bar.com',\n        'email@foo.com',\n        'email@a.b.c.foo.com',\n      ],\n    });\n  });\n\n  it('should validate only email addresses with whitelisted domains', () => {\n    test({\n      validator: 'isEmail',\n      args: [{ host_whitelist: ['gmail.com', 'foo.bar.com'] }],\n      valid: [\n        'email@gmail.com',\n        'test@foo.bar.com',\n      ],\n      invalid: [\n        'foo+bar@test.com',\n        'email@foo.com',\n        'email@bar.com',\n      ],\n    });\n  });\n\n  it('should allow regular expressions in the host whitelist of isEmail', () => {\n    test({\n      validator: 'isEmail',\n      args: [{\n        host_whitelist: ['bar.com', 'foo.com', /\\.foo\\.com$/],\n      }],\n      valid: [\n        'email@bar.com',\n        'email@foo.com',\n        'email@a.b.c.foo.com',\n      ],\n      invalid: [\n        'email@foobar.com',\n        'email@foo.bar.com',\n        'email@qux.com',\n      ],\n    });\n  });\n\n  it('should validate URLs', () => {\n    test({\n      validator: 'isURL',\n      valid: [\n        'foobar.com',\n        'www.foobar.com',\n        'foobar.com/',\n        'valid.au',\n        'http://www.foobar.com/',\n        'HTTP://WWW.FOOBAR.COM/',\n        'https://www.foobar.com/',\n        'HTTPS://WWW.FOOBAR.COM/',\n        'http://www.foobar.com:23/',\n        'http://www.foobar.com:65535/',\n        'http://www.foobar.com:5/',\n        'https://www.foobar.com/',\n        'ftp://www.foobar.com/',\n        'http://www.foobar.com/~foobar',\n        'http://user:pass@www.foobar.com/',\n        'http://user:@www.foobar.com/',\n        'http://:pass@www.foobar.com/',\n        'http://user@www.foobar.com',\n        'http://127.0.0.1/',\n        'http://10.0.0.0/',\n        'http://189.123.14.13/',\n        'http://duckduckgo.com/?q=%2F',\n        'http://foobar.com/t$-_.+!*\\'(),',\n        'http://foobar.com/?foo=bar#baz=qux',\n        'http://foobar.com?foo=bar',\n        'http://foobar.com#baz=qux',\n        'http://www.xn--froschgrn-x9a.net/',\n        'http://xn--froschgrn-x9a.com/',\n        'http://foo--bar.com',\n        'http://høyfjellet.no',\n        'http://xn--j1aac5a4g.xn--j1amh',\n        'http://xn------eddceddeftq7bvv7c4ke4c.xn--p1ai',\n        'http://кулік.укр',\n        'test.com?ref=http://test2.com',\n        'http://[FEDC:BA98:7654:3210:FEDC:BA98:7654:3210]:80/index.html',\n        'http://[1080:0:0:0:8:800:200C:417A]/index.html',\n        'http://[3ffe:2a00:100:7031::1]',\n        'http://[1080::8:800:200C:417A]/foo',\n        'http://[::192.9.5.5]/ipng',\n        'http://[::FFFF:129.144.52.38]:80/index.html',\n        'http://[2010:836B:4179::836B:4179]',\n        'http://example.com/example.json#/foo/bar',\n        'http://1337.com',\n        // TODO: those probably should not be marked as valid URLs; CVE-2025-56200\n        /* eslint-disable no-script-url */\n        'http://evil-site.com@example.com/',\n        'ｊａｖａｓｃｒｉｐｔ:alert(1)@example.com',\n        /* eslint-enable no-script-url */\n      ],\n      invalid: [\n        'http://localhost:3000/',\n        '//foobar.com',\n        'xyz://foobar.com',\n        'invalid/',\n        'invalid.x',\n        'invalid.',\n        '.com',\n        'http://com/',\n        'http://300.0.0.1/',\n        'mailto:foo@bar.com',\n        'rtmp://foobar.com',\n        'http://www.xn--.com/',\n        'http://xn--.com/',\n        'http://www.foobar.com:0/',\n        'http://www.foobar.com:70000/',\n        'http://www.foobar.com:99999/',\n        'http://www.-foobar.com/',\n        'http://www.foobar-.com/',\n        'http://foobar/# lol',\n        'http://foobar/? lol',\n        'http://foobar/ lol/',\n        'http://lol @foobar.com/',\n        'http://lol:lol @foobar.com/',\n        'http://lol:lol:lol@foobar.com/',\n        'http://lol: @foobar.com/',\n        'http://www.foo_bar.com/',\n        'http://www.foobar.com/\\t',\n        'http://@foobar.com',\n        'http://:@foobar.com',\n        'http://\\n@www.foobar.com/',\n        '',\n        `http://foobar.com/${new Array(2083).join('f')}`,\n        'http://*.foo.com',\n        '*.foo.com',\n        '!.foo.com',\n        'http://example.com.',\n        'http://localhost:61500this is an invalid url!!!!',\n        '////foobar.com',\n        'http:////foobar.com',\n        'https://example.com/foo/<script>alert(\\'XSS\\')</script>/',\n        // the following tests are because of CVE-2025-56200\n        /* eslint-disable no-script-url */\n        \"javascript:alert(1);a=';@example.com/alert(1)'\",\n        'JaVaScRiPt:alert(1)@example.com',\n        'javascript:/* comment */alert(1)@example.com',\n        'javascript:var a=1; alert(a);@example.com',\n        'javascript:alert(1)@user@example.com',\n        'javascript:alert(1)@example.com?q=safe',\n        'javascript:%61%6c%65%72%74%28%31%29@example.com',\n        'javascript:%22@a.com#\";alert(origin)//',\n        'data:text/html,<script>alert(1)</script>@example.com',\n        'vbscript:msgbox(\"XSS\")@example.com',\n        '//evil-site.com/path@example.com',\n        /* eslint-enable no-script-url */\n      ],\n    });\n  });\n\n  it('should validate URLs without protocol', () => {\n    test({\n      validator: 'isURL',\n      args: [{\n        require_tld: false,\n        require_valid_protocol: false,\n      }],\n      valid: [\n        'localhost',\n        'localhost:3000',\n        'service-name:8080',\n        'https://localhost',\n        'http://localhost:3000',\n        'http://service-name:8080',\n        'user:password@localhost',\n        'user:pass@service-name:8080',\n      ],\n      invalid: [],\n    });\n\n    // Test with require_protocol: true - should reject hostnames with ports but no protocol\n    test({\n      validator: 'isURL',\n      args: [{\n        require_tld: false,\n        require_protocol: true,\n        require_valid_protocol: false,\n      }],\n      valid: [\n        'http://localhost:3000',\n        'https://service-name:8080',\n        'custom://localhost',\n      ],\n      invalid: [\n        'localhost:3000',\n        'service-name:8080',\n        'user:password@localhost',\n      ],\n    });\n\n    // Test non-numeric patterns after colon (should be treated as protocols)\n    test({\n      validator: 'isURL',\n      args: [{\n        require_tld: false,\n        require_valid_protocol: false,\n        protocols: ['custom', 'myscheme'],\n      }],\n      valid: [\n        'custom:something',\n        'myscheme:data',\n      ],\n      invalid: [],\n    });\n  });\n\n  it('should validate URLs with custom protocols', () => {\n    test({\n      validator: 'isURL',\n      args: [{\n        protocols: ['rtmp'],\n      }],\n      valid: [\n        'rtmp://foobar.com',\n        'rtmp:foobar.com',\n      ],\n      invalid: [\n        'http://foobar.com',\n        'tel:+15551234567',\n      ],\n    });\n  });\n\n  it('should validate file URLs without a host', () => {\n    test({\n      validator: 'isURL',\n      args: [{\n        protocols: ['file'],\n        require_host: false,\n        require_tld: false,\n      }],\n      valid: [\n        'file://localhost/foo.txt',\n        'file:///foo.txt',\n        'file:///',\n      ],\n      invalid: [\n        'http://foobar.com',\n        'file://',\n      ],\n    });\n  });\n\n  it('should validate postgres URLs without a host', () => {\n    test({\n      validator: 'isURL',\n      args: [{\n        protocols: ['postgres'],\n        require_host: false,\n      }],\n      valid: [\n        'postgres://user:pw@/test',\n      ],\n      invalid: [\n        'http://foobar.com',\n        'postgres://',\n      ],\n    });\n  });\n\n\n  it('should validate URLs with any protocol', () => {\n    test({\n      validator: 'isURL',\n      args: [{\n        require_valid_protocol: false,\n      }],\n      valid: [\n        'rtmp://foobar.com',\n        'http://foobar.com',\n        'test://foobar.com',\n        // Dangerous! This allows to mark malicious URLs as a valid URL (CVE-2025-56200)\n        // eslint-disable-next-line no-script-url\n        'javascript:alert(1);@example.com',\n      ],\n      invalid: [\n        'mailto:test@example.com',\n      ],\n    });\n  });\n\n  it('should validate URLs with underscores', () => {\n    test({\n      validator: 'isURL',\n      args: [{\n        allow_underscores: true,\n      }],\n      valid: [\n        'http://foo_bar.com',\n        'http://pr.example_com.294.example.com/',\n        'http://foo__bar.com',\n        'http://_.example.com',\n      ],\n      invalid: [],\n    });\n  });\n\n  it('should validate URLs that do not have a TLD', () => {\n    test({\n      validator: 'isURL',\n      args: [{\n        require_tld: false,\n      }],\n      valid: [\n        'http://foobar.com/',\n        'http://foobar/',\n        'http://localhost/',\n        'foobar/',\n        'foobar',\n      ],\n      invalid: [],\n    });\n  });\n\n  it('should validate URLs with a trailing dot option', () => {\n    test({\n      validator: 'isURL',\n      args: [{\n        allow_trailing_dot: true,\n        require_tld: false,\n      }],\n      valid: [\n        'http://example.com.',\n        'foobar.',\n      ],\n    });\n  });\n\n  it('should validate URLs with column and no port', () => {\n    test({\n      validator: 'isURL',\n      valid: [\n        'http://example.com:',\n        'ftp://example.com:',\n      ],\n      invalid: [\n        'https://example.com:abc',\n      ],\n    });\n  });\n\n  it('should validate sftp protocol URL containing column and no port', () => {\n    test({\n      validator: 'isURL',\n      args: [{\n        protocols: ['sftp'],\n      }],\n      valid: [\n        'sftp://user:pass@terminal.aws.test.nl:/incoming/things.csv',\n      ],\n    });\n  });\n\n  it('should validate protocol relative URLs', () => {\n    test({\n      validator: 'isURL',\n      args: [{\n        allow_protocol_relative_urls: true,\n      }],\n      valid: [\n        '//foobar.com',\n        'http://foobar.com',\n        'foobar.com',\n      ],\n      invalid: [\n        '://foobar.com',\n        '/foobar.com',\n        '////foobar.com',\n        'http:////foobar.com',\n      ],\n    });\n  });\n\n  it('should not validate URLs with fragments when allow fragments is false', () => {\n    test({\n      validator: 'isURL',\n      args: [{\n        allow_fragments: false,\n      }],\n      valid: [\n        'http://foobar.com',\n        'foobar.com',\n      ],\n      invalid: [\n        'http://foobar.com#part',\n        'foobar.com#part',\n      ],\n    });\n  });\n\n  it('should not validate URLs with query components when allow query components is false', () => {\n    test({\n      validator: 'isURL',\n      args: [{\n        allow_query_components: false,\n      }],\n      valid: [\n        'http://foobar.com',\n        'foobar.com',\n      ],\n      invalid: [\n        'http://foobar.com?foo=bar',\n        'http://foobar.com?foo=bar&bar=foo',\n        'foobar.com?foo=bar',\n        'foobar.com?foo=bar&bar=foo',\n      ],\n    });\n  });\n\n  it('should not validate protocol relative URLs when require protocol is true', () => {\n    test({\n      validator: 'isURL',\n      args: [{\n        allow_protocol_relative_urls: true,\n        require_protocol: true,\n      }],\n      valid: [\n        'http://foobar.com',\n      ],\n      invalid: [\n        '//foobar.com',\n        '://foobar.com',\n        '/foobar.com',\n        'foobar.com',\n      ],\n    });\n  });\n\n  it('should let users specify whether URLs require a protocol', () => {\n    test({\n      validator: 'isURL',\n      args: [{\n        require_protocol: true,\n      }],\n      valid: [\n        'http://foobar.com/',\n      ],\n      invalid: [\n        'http://localhost/',\n        'foobar.com',\n        'foobar',\n      ],\n    });\n  });\n\n  it('should validate authentication strings if a protocol is not required', () => {\n    test({\n      validator: 'isURL',\n      args: [{\n        require_protocol: false,\n      }],\n      valid: [\n        'user:pw@foobar.com/',\n      ],\n      invalid: [\n        'user:pw,@foobar.com/',\n      ],\n    });\n  });\n\n  it('should reject authentication strings if a protocol is required', () => {\n    test({\n      validator: 'isURL',\n      args: [{\n        require_protocol: true,\n      }],\n      valid: [\n        'http://user:pw@foobar.com/',\n        'https://user:password@example.com',\n        'ftp://admin:pass@ftp.example.com/',\n      ],\n      invalid: [\n        'user:pw@foobar.com/',\n        'user:password@example.com',\n        'admin:pass@ftp.example.com/',\n      ],\n    });\n  });\n\n  it('should reject invalid protocols when require_valid_protocol is enabled', () => {\n    test({\n      validator: 'isURL',\n      args: [{\n        require_valid_protocol: true,\n        protocols: ['http', 'https', 'ftp'],\n      }],\n      valid: [\n        'http://example.com',\n        'https://example.com',\n        'ftp://example.com',\n      ],\n      invalid: [\n        // eslint-disable-next-line no-script-url\n        'javascript:alert(1);@example.com',\n        'data:text/html,<script>alert(1)</script>@example.com',\n        'file:///etc/passwd@example.com',\n      ],\n    });\n  });\n\n  it('should let users specify a host whitelist', () => {\n    test({\n      validator: 'isURL',\n      args: [{\n        host_whitelist: ['foo.com', 'bar.com'],\n      }],\n      valid: [\n        'http://bar.com/',\n        'http://foo.com/',\n      ],\n      invalid: [\n        'http://foobar.com',\n        'http://foo.bar.com/',\n        'http://qux.com',\n      ],\n    });\n  });\n\n  it('should allow regular expressions in the host whitelist', () => {\n    test({\n      validator: 'isURL',\n      args: [{\n        host_whitelist: ['bar.com', 'foo.com', /\\.foo\\.com$/],\n      }],\n      valid: [\n        'http://bar.com/',\n        'http://foo.com/',\n        'http://images.foo.com/',\n        'http://cdn.foo.com/',\n        'http://a.b.c.foo.com/',\n      ],\n      invalid: [\n        'http://foobar.com',\n        'http://foo.bar.com/',\n        'http://qux.com',\n      ],\n    });\n  });\n\n  it('should let users specify a host blacklist', () => {\n    test({\n      validator: 'isURL',\n      args: [{\n        host_blacklist: ['foo.com', 'bar.com'],\n      }],\n      valid: [\n        'http://foobar.com',\n        'http://foo.bar.com/',\n        'http://qux.com',\n      ],\n      invalid: [\n        'http://bar.com/',\n        'http://foo.com/',\n      ],\n    });\n  });\n\n  it('should allow regular expressions in the host blacklist', () => {\n    test({\n      validator: 'isURL',\n      args: [{\n        host_blacklist: ['bar.com', 'foo.com', /\\.foo\\.com$/],\n      }],\n      valid: [\n        'http://foobar.com',\n        'http://foo.bar.com/',\n        'http://qux.com',\n      ],\n      invalid: [\n        'http://bar.com/',\n        'http://foo.com/',\n        'http://images.foo.com/',\n        'http://cdn.foo.com/',\n        'http://a.b.c.foo.com/',\n      ],\n    });\n  });\n\n  it('GHSA-9965-vmph-33xx vulnerability - protocol delimiter parsing difference', () => {\n    const DOMAIN_WHITELIST = ['example.com'];\n\n    test({\n      validator: 'isURL',\n      args: [{\n        protocols: ['https'],\n        host_whitelist: DOMAIN_WHITELIST,\n        require_host: false,\n      }],\n      valid: [],\n      invalid: [\n        // eslint-disable-next-line no-script-url\n        \"javascript:alert(1);a=';@example.com/alert(1)\",\n      ],\n    });\n  });\n\n  it('should allow rejecting urls containing authentication information', () => {\n    test({\n      validator: 'isURL',\n      args: [{ disallow_auth: true }],\n      valid: [\n        'doe.com',\n      ],\n      invalid: [\n        'john@doe.com',\n        'john:john@doe.com',\n      ],\n    });\n  });\n\n  it('should accept urls containing authentication information', () => {\n    test({\n      validator: 'isURL',\n      args: [{ disallow_auth: false }],\n      valid: [\n        'user@example.com',\n        'user:@example.com',\n        'user:password@example.com',\n      ],\n      invalid: [\n        'user:user:password@example.com',\n        '@example.com',\n        ':@example.com',\n        ':example.com',\n      ],\n    });\n  });\n\n  it('should allow user to skip URL length validation', () => {\n    test({\n      validator: 'isURL',\n      args: [{ validate_length: false }],\n      valid: [\n        'http://foobar.com/f',\n        `http://foobar.com/${new Array(2083).join('f')}`,\n      ],\n      invalid: [],\n    });\n  });\n\n  it('should allow user to configure the maximum URL length', () => {\n    test({\n      validator: 'isURL',\n      args: [{ max_allowed_length: 20 }],\n      valid: [\n        'http://foobar.com/12', // 20 characters\n        'http://foobar.com/',\n      ],\n      invalid: [\n        'http://foobar.com/123', // 21 characters\n        'http://foobar.com/1234567890',\n      ],\n    });\n  });\n\n  it('should validate URLs with port present', () => {\n    test({\n      validator: 'isURL',\n      args: [{ require_port: true }],\n      valid: [\n        'http://user:pass@www.foobar.com:1',\n        'http://user:@www.foobar.com:65535',\n        'http://127.0.0.1:23',\n        'http://10.0.0.0:256',\n        'http://189.123.14.13:256',\n        'http://duckduckgo.com:65535?q=%2F',\n      ],\n      invalid: [\n        'http://user:pass@www.foobar.com/',\n        'http://user:@www.foobar.com/',\n        'http://127.0.0.1/',\n        'http://10.0.0.0/',\n        'http://189.123.14.13/',\n        'http://duckduckgo.com/?q=%2F',\n      ],\n    });\n  });\n\n  it('should validate MAC addresses', () => {\n    test({\n      validator: 'isMACAddress',\n      valid: [\n        'ab:ab:ab:ab:ab:ab',\n        'FF:FF:FF:FF:FF:FF',\n        '01:02:03:04:05:ab',\n        '01:AB:03:04:05:06',\n        'A9 C5 D4 9F EB D3',\n        '01 02 03 04 05 ab',\n        '01-02-03-04-05-ab',\n        '0102.0304.05ab',\n        'ab:ab:ab:ab:ab:ab:ab:ab',\n        'FF:FF:FF:FF:FF:FF:FF:FF',\n        '01:02:03:04:05:06:07:ab',\n        '01:AB:03:04:05:06:07:08',\n        'A9 C5 D4 9F EB D3 B6 65',\n        '01 02 03 04 05 06 07 ab',\n        '01-02-03-04-05-06-07-ab',\n        '0102.0304.0506.07ab',\n      ],\n      invalid: [\n        'abc',\n        '01:02:03:04:05',\n        '01:02:03:04:05:z0',\n        '01:02:03:04::ab',\n        '1:2:3:4:5:6',\n        'AB:CD:EF:GH:01:02',\n        'A9C5 D4 9F EB D3',\n        '01-02 03:04 05 ab',\n        '0102.03:04.05ab',\n        '900f/dffs/sdea',\n        '01:02:03:04:05:06:07',\n        '01:02:03:04:05:06:07:z0',\n        '01:02:03:04:05:06::ab',\n        '1:2:3:4:5:6:7:8',\n        'AB:CD:EF:GH:01:02:03:04',\n        'A9C5 D4 9F EB D3 B6 65',\n        '01-02 03:04 05 06 07 ab',\n        '0102.03:04.0506.07ab',\n        '900f/dffs/sdea/54gh',\n      ],\n    });\n    test({\n      validator: 'isMACAddress',\n      args: [{\n        eui: '48',\n      }],\n      valid: [\n        'ab:ab:ab:ab:ab:ab',\n        'FF:FF:FF:FF:FF:FF',\n        '01:02:03:04:05:ab',\n        '01:AB:03:04:05:06',\n        'A9 C5 D4 9F EB D3',\n        '01 02 03 04 05 ab',\n        '01-02-03-04-05-ab',\n        '0102.0304.05ab',\n      ],\n      invalid: [\n        'ab:ab:ab:ab:ab:ab:ab:ab',\n        'FF:FF:FF:FF:FF:FF:FF:FF',\n        '01:02:03:04:05:06:07:ab',\n        '01:AB:03:04:05:06:07:08',\n        'A9 C5 D4 9F EB D3 B6 65',\n        '01 02 03 04 05 06 07 ab',\n        '01-02-03-04-05-06-07-ab',\n        '0102.0304.0506.07ab',\n      ],\n    });\n    test({\n      validator: 'isMACAddress',\n      args: [{\n        eui: '64',\n      }],\n      valid: [\n        'ab:ab:ab:ab:ab:ab:ab:ab',\n        'FF:FF:FF:FF:FF:FF:FF:FF',\n        '01:02:03:04:05:06:07:ab',\n        '01:AB:03:04:05:06:07:08',\n        'A9 C5 D4 9F EB D3 B6 65',\n        '01 02 03 04 05 06 07 ab',\n        '01-02-03-04-05-06-07-ab',\n        '0102.0304.0506.07ab',\n      ],\n      invalid: [\n        'ab:ab:ab:ab:ab:ab',\n        'FF:FF:FF:FF:FF:FF',\n        '01:02:03:04:05:ab',\n        '01:AB:03:04:05:06',\n        'A9 C5 D4 9F EB D3',\n        '01 02 03 04 05 ab',\n        '01-02-03-04-05-ab',\n        '0102.0304.05ab',\n      ],\n    });\n  });\n\n  it('should validate MAC addresses without separator', () => {\n    test({\n      validator: 'isMACAddress',\n      args: [{\n        no_separators: true,\n      }],\n      valid: [\n        'abababababab',\n        'FFFFFFFFFFFF',\n        '0102030405ab',\n        '01AB03040506',\n        'abababababababab',\n        'FFFFFFFFFFFFFFFF',\n        '01020304050607ab',\n        '01AB030405060708',\n      ],\n      invalid: [\n        'abc',\n        '01:02:03:04:05',\n        '01:02:03:04::ab',\n        '1:2:3:4:5:6',\n        'AB:CD:EF:GH:01:02',\n        'ab:ab:ab:ab:ab:ab',\n        'FF:FF:FF:FF:FF:FF',\n        '01:02:03:04:05:ab',\n        '01:AB:03:04:05:06',\n        '0102030405',\n        '01020304ab',\n        '123456',\n        'ABCDEFGH0102',\n        '01:02:03:04:05:06:07',\n        '01:02:03:04:05:06::ab',\n        '1:2:3:4:5:6:7:8',\n        'AB:CD:EF:GH:01:02:03:04',\n        'ab:ab:ab:ab:ab:ab:ab:ab',\n        'FF:FF:FF:FF:FF:FF:FF:FF',\n        '01:02:03:04:05:06:07:ab',\n        '01:AB:03:04:05:06:07:08',\n        '01020304050607',\n        '010203040506ab',\n        '12345678',\n        'ABCDEFGH01020304',\n      ],\n    });\n    test({\n      validator: 'isMACAddress',\n      args: [{\n        no_separators: true,\n        eui: '48',\n      }],\n      valid: [\n        'abababababab',\n        'FFFFFFFFFFFF',\n        '0102030405ab',\n        '01AB03040506',\n      ],\n      invalid: [\n        'abababababababab',\n        'FFFFFFFFFFFFFFFF',\n        '01020304050607ab',\n        '01AB030405060708',\n      ],\n    });\n    test({\n      validator: 'isMACAddress',\n      args: [{\n        no_separators: true,\n        eui: '64',\n      }],\n      valid: [\n        'abababababababab',\n        'FFFFFFFFFFFFFFFF',\n        '01020304050607ab',\n        '01AB030405060708',\n      ],\n      invalid: [\n        'abababababab',\n        'FFFFFFFFFFFF',\n        '0102030405ab',\n        '01AB03040506',\n      ],\n    });\n  });\n\n  it('should validate isIPRange', () => {\n    test({\n      validator: 'isIPRange',\n      valid: [\n        '127.0.0.1/24',\n        '0.0.0.0/0',\n        '255.255.255.0/32',\n        '::/0',\n        '::/128',\n        '2001::/128',\n        '2001:800::/128',\n        '::ffff:127.0.0.1/128',\n      ],\n      invalid: [\n        'abc',\n        '127.200.230.1/35',\n        '127.200.230.1/-1',\n        '1.1.1.1/011',\n        '1.1.1/24.1',\n        '1.1.1.1/01',\n        '1.1.1.1/1.1',\n        '1.1.1.1/1.',\n        '1.1.1.1/1/1',\n        '1.1.1.1',\n        '::1',\n        '::1/164',\n        '2001::/240',\n        '2001::/-1',\n        '2001::/001',\n        '2001::/24.1',\n        '2001:db8:0000:1:1:1:1:1',\n        '::ffff:127.0.0.1',\n      ],\n    });\n    test({\n      validator: 'isIPRange',\n      args: [4],\n      valid: [\n        '127.0.0.1/1',\n        '0.0.0.0/1',\n        '255.255.255.255/1',\n        '1.2.3.4/1',\n        '255.0.0.1/1',\n        '0.0.1.1/1',\n      ],\n      invalid: [\n        'abc',\n        '::1',\n        '2001:db8:0000:1:1:1:1:1',\n        '::ffff:127.0.0.1',\n        '137.132.10.01',\n        '0.256.0.256',\n        '255.256.255.256',\n      ],\n    });\n    test({\n      validator: 'isIPRange',\n      args: [6],\n      valid: [\n        '::1/1',\n        '2001:db8:0000:1:1:1:1:1/1',\n        '::ffff:127.0.0.1/1',\n      ],\n      invalid: [\n        'abc',\n        '127.0.0.1',\n        '0.0.0.0',\n        '255.255.255.255',\n        '1.2.3.4',\n        '::ffff:287.0.0.1',\n        '::ffff:287.0.0.1/254',\n        '%',\n        'fe80::1234%',\n        'fe80::1234%1%3%4',\n        'fe80%fe80%',\n      ],\n    });\n    test({\n      validator: 'isIPRange',\n      args: [10],\n      valid: [],\n      invalid: [\n        'abc',\n        '127.0.0.1/1',\n        '0.0.0.0/1',\n        '255.255.255.255/1',\n        '1.2.3.4/1',\n        '::1/1',\n        '2001:db8:0000:1:1:1:1:1/1',\n      ],\n    });\n  });\n\n  it('should validate FQDN', () => {\n    test({\n      validator: 'isFQDN',\n      valid: [\n        'domain.com',\n        'dom.plato',\n        'a.domain.co',\n        'foo--bar.com',\n        'xn--froschgrn-x9a.com',\n        'rebecca.blackfriday',\n        '1337.com',\n      ],\n      invalid: [\n        'abc',\n        '256.0.0.0',\n        '_.com',\n        '*.some.com',\n        's!ome.com',\n        'domain.com/',\n        '/more.com',\n        'domain.com�',\n        'domain.co\\u00A0m',\n        'domain.co\\u1680m',\n        'domain.co\\u2006m',\n        'domain.co\\u2028m',\n        'domain.co\\u2029m',\n        'domain.co\\u202Fm',\n        'domain.co\\u205Fm',\n        'domain.co\\u3000m',\n        'domain.com\\uDC00',\n        'domain.co\\uEFFFm',\n        'domain.co\\uFDDAm',\n        'domain.co\\uFFF4m',\n        'domain.com©',\n        'example.0',\n        '192.168.0.9999',\n        '192.168.0',\n      ],\n    });\n  });\n  it('should validate FQDN with trailing dot option', () => {\n    test({\n      validator: 'isFQDN',\n      args: [\n        { allow_trailing_dot: true },\n      ],\n      valid: [\n        'example.com.',\n      ],\n    });\n  });\n  it('should invalidate FQDN when not require_tld', () => {\n    test({\n      validator: 'isFQDN',\n      args: [\n        { require_tld: false },\n      ],\n      invalid: [\n        'example.0',\n        '192.168.0',\n        '192.168.0.9999',\n      ],\n    });\n  });\n  it('should validate FQDN when not require_tld but allow_numeric_tld', () => {\n    test({\n      validator: 'isFQDN',\n      args: [\n        { allow_numeric_tld: true, require_tld: false },\n      ],\n      valid: [\n        'example.0',\n        '192.168.0',\n        '192.168.0.9999',\n      ],\n    });\n  });\n  it('should validate FQDN with wildcard option', () => {\n    test({\n      validator: 'isFQDN',\n      args: [\n        { allow_wildcard: true },\n      ],\n      valid: [\n        '*.example.com',\n        '*.shop.example.com',\n      ],\n    });\n  });\n  it('should validate FQDN with required allow_trailing_dot, allow_underscores and allow_numeric_tld options', () => {\n    test({\n      validator: 'isFQDN',\n      args: [\n        { allow_trailing_dot: true, allow_underscores: true, allow_numeric_tld: true },\n      ],\n      valid: [\n        'abc.efg.g1h.',\n        'as1s.sad3s.ssa2d.',\n      ],\n    });\n  });\n\n  it('should validate alpha strings', () => {\n    test({\n      validator: 'isAlpha',\n      valid: [\n        'abc',\n        'ABC',\n        'FoObar',\n      ],\n      invalid: [\n        'abc1',\n        '  foo  ',\n        '',\n        'ÄBC',\n        'FÜübar',\n        'Jön',\n        'Heiß',\n      ],\n    });\n  });\n\n  it('should validate alpha string with ignored characters', () => {\n    test({\n      validator: 'isAlpha',\n      args: ['en-US', { ignore: '- /' }], // ignore [space-/]\n      valid: [\n        'en-US',\n        'this is a valid alpha string',\n        'us/usa',\n      ],\n      invalid: [\n        '1. this is not a valid alpha string',\n        'this$is also not a valid.alpha string',\n        'this is also not a valid alpha string.',\n      ],\n    });\n\n    test({\n      validator: 'isAlpha',\n      args: ['en-US', { ignore: /[\\s/-]/g }], // ignore [space -]\n      valid: [\n        'en-US',\n        'this is a valid alpha string',\n      ],\n      invalid: [\n        '1. this is not a valid alpha string',\n        'this$is also not a valid.alpha string',\n        'this is also not a valid alpha string.',\n      ],\n    });\n\n    test({\n      validator: 'isAlpha',\n      args: ['en-US', { ignore: 1234 }], // invalid ignore matcher\n      error: [\n        'alpha',\n      ],\n    });\n  });\n\n  it('should validate Azerbaijani alpha strings', () => {\n    test({\n      validator: 'isAlpha',\n      args: ['az-AZ'],\n      valid: [\n        'Azərbaycan',\n        'Bakı',\n        'üöğıəçş',\n        'sizAzərbaycanlaşdırılmışlardansınızmı',\n        'dahaBirDüzgünString',\n        'abcçdeəfgğhxıijkqlmnoöprsştuüvyz',\n      ],\n      invalid: [\n        'rəqəm1',\n        '  foo  ',\n        '',\n        'ab(cd)',\n        'simvol@',\n        'wəkil',\n      ],\n    });\n  });\n\n  it('should validate bulgarian alpha strings', () => {\n    test({\n      validator: 'isAlpha',\n      args: ['bg-BG'],\n      valid: [\n        'абв',\n        'АБВ',\n        'жаба',\n        'яГоДа',\n      ],\n      invalid: [\n        'abc1',\n        '  foo  ',\n        '',\n        'ЁЧПС',\n        '_аз_обичам_обувки_',\n        'ехо!',\n      ],\n    });\n  });\n\n  it('should validate Bengali alpha strings', () => {\n    test({\n      validator: 'isAlpha',\n      args: ['bn-BD'],\n      valid: [\n        'অয়াওর',\n        'ফগফদ্রত',\n        'ফদ্ম্যতভ',\n        'বেরেওভচনভন',\n        'আমারবাসগা',\n      ],\n      invalid: [\n        'দাস২৩৪',\n        '  দ্গফহ্নভ  ',\n        '',\n        '(গফদ)',\n      ],\n    });\n  });\n\n  it('should validate czech alpha strings', () => {\n    test({\n      validator: 'isAlpha',\n      args: ['cs-CZ'],\n      valid: [\n        'žluťoučký',\n        'KŮŇ',\n        'Pěl',\n        'Ďábelské',\n        'ódy',\n      ],\n      invalid: [\n        'ábc1',\n        '  fůj  ',\n        '',\n      ],\n    });\n  });\n\n  it('should validate slovak alpha strings', () => {\n    test({\n      validator: 'isAlpha',\n      args: ['sk-SK'],\n      valid: [\n        'môj',\n        'ľúbím',\n        'mäkčeň',\n        'stĹp',\n        'vŕba',\n        'ňorimberk',\n        'ťava',\n        'žanéta',\n        'Ďábelské',\n        'ódy',\n      ],\n      invalid: [\n        '1moj',\n        '你好世界',\n        '  Привет мир  ',\n        'مرحبا العا ',\n      ],\n    });\n  });\n\n  it('should validate danish alpha strings', () => {\n    test({\n      validator: 'isAlpha',\n      args: ['da-DK'],\n      valid: [\n        'aøå',\n        'Ære',\n        'Øre',\n        'Åre',\n      ],\n      invalid: [\n        'äbc123',\n        'ÄBC11',\n        '',\n      ],\n    });\n  });\n\n  it('should validate dutch alpha strings', () => {\n    test({\n      validator: 'isAlpha',\n      args: ['nl-NL'],\n      valid: [\n        'Kán',\n        'één',\n        'vóór',\n        'nú',\n        'héél',\n      ],\n      invalid: [\n        'äca ',\n        'abcß',\n        'Øre',\n      ],\n    });\n  });\n\n  it('should validate german alpha strings', () => {\n    test({\n      validator: 'isAlpha',\n      args: ['de-DE'],\n      valid: [\n        'äbc',\n        'ÄBC',\n        'FöÖbär',\n        'Heiß',\n      ],\n      invalid: [\n        'äbc1',\n        '  föö  ',\n        '',\n      ],\n    });\n  });\n\n  it('should validate hungarian alpha strings', () => {\n    test({\n      validator: 'isAlpha',\n      args: ['hu-HU'],\n      valid: [\n        'árvíztűrőtükörfúrógép',\n        'ÁRVÍZTŰRŐTÜKÖRFÚRÓGÉP',\n      ],\n      invalid: [\n        'äbc1',\n        '  fäö  ',\n        'Heiß',\n        '',\n      ],\n    });\n  });\n\n  it('should validate portuguese alpha strings', () => {\n    test({\n      validator: 'isAlpha',\n      args: ['pt-PT'],\n      valid: [\n        'palíndromo',\n        'órgão',\n        'qwértyúão',\n        'àäãcëüïÄÏÜ',\n      ],\n      invalid: [\n        '12abc',\n        'Heiß',\n        'Øre',\n        'æøå',\n        '',\n      ],\n    });\n  });\n\n  it('should validate italian alpha strings', () => {\n    test({\n      validator: 'isAlpha',\n      args: ['it-IT'],\n      valid: [\n        'àéèìîóòù',\n        'correnti',\n        'DEFINIZIONE',\n        'compilazione',\n        'metró',\n        'pèsca',\n        'PÉSCA',\n        'genî',\n      ],\n      invalid: [\n        'äbc123',\n        'ÄBC11',\n        'æøå',\n        '',\n      ],\n    });\n  });\n\n  it('should validate Japanese alpha strings', () => {\n    test({\n      validator: 'isAlpha',\n      args: ['ja-JP'],\n      valid: [\n        'あいうえお',\n        'がぎぐげご',\n        'ぁぃぅぇぉ',\n        'アイウエオ',\n        'ァィゥェ',\n        'ｱｲｳｴｵ',\n        '吾輩は猫である',\n        '臥薪嘗胆',\n        '新世紀エヴァンゲリオン',\n        '天国と地獄',\n        '七人の侍',\n        'シン・ウルトラマン',\n      ],\n      invalid: [\n        'あいう123',\n        'abcあいう',\n        '１９８４',\n      ],\n    });\n  });\n\n  it('should validate kazakh alpha strings', () => {\n    test({\n      validator: 'isAlpha',\n      args: ['kk-KZ'],\n      valid: [\n        'Сәлем',\n        'қанағаттандырылмағандықтарыңыздан',\n        'Кешіріңіз',\n        'Өкінішке',\n        'Қайталаңызшы',\n        'ағылшынша',\n        'түсінбедім',\n      ],\n      invalid: [\n        'Кешіріңіз1',\n        '  Кет бар  ',\n        'مرحبا العا',\n      ],\n    });\n  });\n\n  it('should validate Vietnamese alpha strings', () => {\n    test({\n      validator: 'isAlpha',\n      args: ['vi-VN'],\n      valid: [\n        'thiến',\n        'nghiêng',\n        'xin',\n        'chào',\n        'thế',\n        'giới',\n      ],\n      invalid: [\n        'thầy3',\n        'Ba gà',\n        '',\n      ],\n    });\n  });\n\n  it('should validate arabic alpha strings', () => {\n    test({\n      validator: 'isAlpha',\n      args: ['ar'],\n      valid: [\n        'أبت',\n        'اَبِتَثّجً',\n      ],\n      invalid: [\n        '١٢٣أبت',\n        '١٢٣',\n        'abc1',\n        '  foo  ',\n        '',\n        'ÄBC',\n        'FÜübar',\n        'Jön',\n        'Heiß',\n      ],\n    });\n  });\n\n  it('should validate farsi alpha strings', () => {\n    test({\n      validator: 'isAlpha',\n      args: ['fa-IR'],\n      valid: [\n        'پدر',\n        'مادر',\n        'برادر',\n        'خواهر',\n      ],\n      invalid: [\n        'فارسی۱۲۳',\n        '۱۶۴',\n        'abc1',\n        '  foo  ',\n        '',\n        'ÄBC',\n        'FÜübar',\n        'Jön',\n        'Heiß',\n      ],\n    });\n  });\n\n  it('should validate finnish alpha strings', () => {\n    test({\n      validator: 'isAlpha',\n      args: ['fi-FI'],\n      valid: [\n        'äiti',\n        'Öljy',\n        'Åke',\n        'testÖ',\n      ],\n      invalid: [\n        'AİıÖöÇçŞşĞğÜüZ',\n        'äöå123',\n        '',\n      ],\n    });\n  });\n\n  it('should validate kurdish alpha strings', () => {\n    test({\n      validator: 'isAlpha',\n      args: ['ku-IQ'],\n      valid: [\n        'ئؤڤگێ',\n        'کوردستان',\n      ],\n      invalid: [\n        'ئؤڤگێ١٢٣',\n        '١٢٣',\n        'abc1',\n        '  foo  ',\n        '',\n        'ÄBC',\n        'FÜübar',\n        'Jön',\n        'Heiß',\n      ],\n    });\n  });\n\n  it('should validate norwegian alpha strings', () => {\n    test({\n      validator: 'isAlpha',\n      args: ['nb-NO'],\n      valid: [\n        'aøå',\n        'Ære',\n        'Øre',\n        'Åre',\n      ],\n      invalid: [\n        'äbc123',\n        'ÄBC11',\n        '',\n      ],\n    });\n  });\n\n  it('should validate polish alpha strings', () => {\n    test({\n      validator: 'isAlpha',\n      args: ['pl-PL'],\n      valid: [\n        'kreską',\n        'zamknięte',\n        'zwykłe',\n        'kropką',\n        'przyjęły',\n        'święty',\n        'Pozwól',\n      ],\n      invalid: [\n        '12řiď ',\n        'blé!!',\n        'föö!2!',\n      ],\n    });\n  });\n\n  it('should validate serbian cyrillic alpha strings', () => {\n    test({\n      validator: 'isAlpha',\n      args: ['sr-RS'],\n      valid: [\n        'ШћжЂљЕ',\n        'ЧПСТЋЏ',\n      ],\n      invalid: [\n        'řiď ',\n        'blé33!!',\n        'föö!!',\n      ],\n    });\n  });\n\n  it('should validate serbian latin alpha strings', () => {\n    test({\n      validator: 'isAlpha',\n      args: ['sr-RS@latin'],\n      valid: [\n        'ŠAabčšđćž',\n        'ŠATROĆčđš',\n      ],\n      invalid: [\n        '12řiď ',\n        'blé!!',\n        'föö!2!',\n      ],\n    });\n  });\n\n  it('should validate spanish alpha strings', () => {\n    test({\n      validator: 'isAlpha',\n      args: ['es-ES'],\n      valid: [\n        'ábcó',\n        'ÁBCÓ',\n        'dormís',\n        'volvés',\n        'español',\n      ],\n      invalid: [\n        'äca ',\n        'abcß',\n        'föö!!',\n      ],\n    });\n  });\n\n  it('should validate swedish alpha strings', () => {\n    test({\n      validator: 'isAlpha',\n      args: ['sv-SE'],\n      valid: [\n        'religiös',\n        'stjäla',\n        'västgöte',\n        'Åre',\n      ],\n      invalid: [\n        'AİıÖöÇçŞşĞğÜüZ',\n        'religiös23',\n        '',\n      ],\n    });\n  });\n\n  it('should validate defined arabic locales alpha strings', () => {\n    test({\n      validator: 'isAlpha',\n      args: ['ar-SY'],\n      valid: [\n        'أبت',\n        'اَبِتَثّجً',\n      ],\n      invalid: [\n        '١٢٣أبت',\n        '١٢٣',\n        'abc1',\n        '  foo  ',\n        '',\n        'ÄBC',\n        'FÜübar',\n        'Jön',\n        'Heiß',\n      ],\n    });\n  });\n\n  it('should validate turkish alpha strings', () => {\n    test({\n      validator: 'isAlpha',\n      args: ['tr-TR'],\n      valid: [\n        'AİıÖöÇçŞşĞğÜüZ',\n      ],\n      invalid: [\n        '0AİıÖöÇçŞşĞğÜüZ1',\n        '  AİıÖöÇçŞşĞğÜüZ  ',\n        'abc1',\n        '  foo  ',\n        '',\n        'ÄBC',\n        'Heiß',\n      ],\n    });\n  });\n\n  it('should validate urkrainian alpha strings', () => {\n    test({\n      validator: 'isAlpha',\n      args: ['uk-UA'],\n      valid: [\n        'АБВГҐДЕЄЖЗИIЇЙКЛМНОПРСТУФХЦШЩЬЮЯ',\n      ],\n      invalid: [\n        '0AİıÖöÇçŞşĞğÜüZ1',\n        '  AİıÖöÇçŞşĞğÜüZ  ',\n        'abc1',\n        '  foo  ',\n        '',\n        'ÄBC',\n        'Heiß',\n        'ЫыЪъЭэ',\n      ],\n    });\n  });\n\n  it('should validate greek alpha strings', () => {\n    test({\n      validator: 'isAlpha',\n      args: ['el-GR'],\n      valid: [\n        'αβγδεζηθικλμνξοπρςστυφχψω',\n        'ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡΣΤΥΦΧΨΩ',\n        'άέήίΰϊϋόύώ',\n        'ΆΈΉΊΪΫΎΏ',\n      ],\n      invalid: [\n        '0AİıÖöÇçŞşĞğÜüZ1',\n        '  AİıÖöÇçŞşĞğÜüZ  ',\n        'ÄBC',\n        'Heiß',\n        'ЫыЪъЭэ',\n        '120',\n        'jαckγ',\n      ],\n    });\n  });\n\n  it('should validate Hebrew alpha strings', () => {\n    test({\n      validator: 'isAlpha',\n      args: ['he'],\n      valid: [\n        'בדיקה',\n        'שלום',\n      ],\n      invalid: [\n        'בדיקה123',\n        '  foo  ',\n        'abc1',\n        '',\n      ],\n    });\n  });\n\n  it('should validate Hindi alpha strings', () => {\n    test({\n      validator: 'isAlpha',\n      args: ['hi-IN'],\n      valid: [\n        'अतअपनाअपनीअपनेअभीअंदरआदिआपइत्यादिइनइनकाइन्हींइन्हेंइन्होंइसइसकाइसकीइसकेइसमेंइसीइसेउनउनकाउनकीउनकेउनकोउन्हींउन्हेंउन्होंउसउसकेउसीउसेएकएवंएसऐसेऔरकईकरकरताकरतेकरनाकरनेकरेंकहतेकहाकाकाफ़ीकिकितनाकिन्हेंकिन्होंकियाकिरकिसकिसीकिसेकीकुछकुलकेकोकोईकौनकौनसागयाघरजबजहाँजाजितनाजिनजिन्हेंजिन्होंजिसजिसेजीधरजैसाजैसेजोतकतबतरहतिनतिन्हेंतिन्होंतिसतिसेतोथाथीथेदबारादियादुसरादूसरेदोद्वाराननकेनहींनानिहायतनीचेनेपरपहलेपूरापेफिरबनीबहीबहुतबादबालाबिलकुलभीभीतरमगरमानोमेमेंयदियहयहाँयहीयायिहयेरखेंरहारहेऱ्वासालिएलियेलेकिनववग़ैरहवर्गवहवहाँवहींवालेवुहवेवोसकतासकतेसबसेसभीसाथसाबुतसाभसारासेसोसंगहीहुआहुईहुएहैहैंहोहोताहोतीहोतेहोनाहोने',\n        'इन्हें',\n      ],\n      invalid: [\n        'अत०२३४५६७८९',\n        'अत 12',\n        ' अत ',\n        'abc1',\n        'abc',\n        '',\n      ],\n    });\n  });\n\n  it('should validate Tamil alpha strings', () => {\n    test({\n      validator: 'isAlpha',\n      args: ['ta-IN'],\n      valid: [\n        'அஆஇஈஉஊஎஏஐஒஓஔகஙசஞடணதநபமயரலவழளறனஶஜஷஸஹ',\n        'தமிழ்',\n      ],\n      invalid: [\n        'தமிழ்123',\n        'தமிழ் ',\n        'தமிழ்.',\n        'abc',\n        '',\n      ],\n    });\n  });\n  it('should validate Telugu alpha strings', () => {\n    test({\n      validator: 'isAlpha',\n      args: ['te-IN'],\n      valid: [\n        'అఆఇఈఉఊఋఌఎఏఐఒఓఔకఖగఘఙచఛజఝఞటఠడఢణతథదధనపఫబభమయరలవశషసహ',\n        'తెలుగు',\n      ],\n      invalid: ['తెలుగు123', 'తెలుగు.', 'abc', ''],\n    });\n  });\n  it('should validate Kannada alpha strings', () => {\n    test({\n      validator: 'isAlpha',\n      args: ['kn-IN'],\n      valid: [\n        'ಅಆಇಈಉಊಋಎಏಐಒಓಔಕಖಗಘಙಚಛಜಝಞಟಠಡಢಣತಥದಧನಪಫಬಭಮಯರಲವಶಷಸಹಳ',\n        'ಕನ್ನಡ',\n      ],\n      invalid: ['ಕನ್ನಡ123', 'ಕನ್ನಡ.', 'abc', ''],\n    });\n  });\n  it('should validate Malayalam alpha strings', () => {\n    test({\n      validator: 'isAlpha',\n      args: ['ml-IN'],\n      valid: [\n        'അആഇഈഉഊഋഎഏഐഒഓഔകഖഗഘങചഛജഝഞടഠഡഢണതഥദധനപഫബഭമയരലവശഷസഹള',\n        'മലയാളം',\n      ],\n      invalid: ['മലയാളം123', 'മലയാളം.', 'abc', ''],\n    });\n  });\n  it('should validate Gujarati alpha strings', () => {\n    test({\n      validator: 'isAlpha',\n      args: ['gu-IN'],\n      valid: [\n        'અઆઇઈઉઊઋએઐઓઔકખગઘચછજઝટઠડઢણતથદધનપફબભમયરલવશષસહળ',\n        'ગુજરાતી',\n      ],\n      invalid: ['ગુજરાતી123', 'ગુજરાતી.', 'abc', ''],\n    });\n  });\n  it('should validate Punjabi alpha strings', () => {\n    test({\n      validator: 'isAlpha',\n      args: ['pa-IN'],\n      valid: [\n        'ਅਆਇਈਉਊਏਐਓਔਕਖਗਘਙਚਛਜਝਞਟਠਡਢਣਤਥਦਧਨਪਫਬਭਮਯਰਲਵਸ਼ਸਹ',\n        'ਪੰਜਾਬੀ',\n      ],\n      invalid: ['ਪੰਜਾਬੀ123', 'ਪੰਜਾਬੀ.', 'abc', ''],\n    });\n  });\n  it('should validate Odia alpha strings', () => {\n    test({\n      validator: 'isAlpha',\n      args: ['or-IN'],\n      valid: [\n        'ଅଆଇଈଉଊଋଌଏଐଓଔକଖଗଘଙଚଛଜଝଞଟଠଡଢଣତଥଦଧନପଫବଭମଯରଲଶଷସହଳ',\n        'ଓଡ଼ିଆ',\n      ],\n      invalid: ['ଓଡ଼ିଆ123', 'ଓଡ଼ିଆ.', 'abc', ''],\n    });\n  });\n  it('should validate Bengali alpha strings', () => {\n    test({\n      validator: 'isAlpha',\n      args: ['bn-IN'],\n      valid: [\n        'অআইঈউঊঋএঐওঔকখগঘঙচছজঝঞটঠডঢণতথদধনপফবভমযরলশষসহ',\n        'বাংলা',\n      ],\n      invalid: ['বাংলা123', 'বাংলা.', 'abc', ''],\n    });\n  });\n  it('should validate persian alpha strings', () => {\n    test({\n      validator: 'isAlpha',\n      args: ['fa-IR'],\n      valid: [\n        'تست',\n        'عزیزم',\n        'ح',\n      ],\n      invalid: [\n        'تست 1',\n        '  عزیزم  ',\n        '',\n      ],\n    });\n  });\n\n  it('should validate Thai alpha strings', () => {\n    test({\n      validator: 'isAlpha',\n      args: ['th-TH'],\n      valid: [\n        'สวัสดี',\n        'ยินดีต้อนรับ เทสเคส',\n      ],\n      invalid: [\n        'สวัสดีHi',\n        '123 ยินดีต้อนรับ',\n        'ยินดีต้อนรับ-๑๒๓',\n      ],\n    });\n  });\n\n  it('should validate Korea alpha strings', () => {\n    test({\n      validator: 'isAlpha',\n      args: ['ko-KR'],\n      valid: [\n        'ㄱ',\n        'ㅑ',\n        'ㄱㄴㄷㅏㅕ',\n        '세종대왕',\n        '나랏말싸미듕귁에달아문자와로서르사맛디아니할쎄',\n      ],\n      invalid: [\n        'abc',\n        '123',\n        '흥선대원군 문호개방',\n        '1592년임진왜란',\n        '대한민국!',\n      ],\n    });\n  });\n\n  it('should validate Sinhala alpha strings', () => {\n    test({\n      validator: 'isAlpha',\n      args: ['si-LK'],\n      valid: [\n        'චතුර',\n        'කචටදබ',\n        'ඎඏදාෛපසුගො',\n      ],\n      invalid: [\n        'ஆஐअतක',\n        'කචට 12',\n        ' ඎ ',\n        'abc1',\n        'abc',\n        '',\n      ],\n    });\n  });\n\n  it('should validate Esperanto alpha strings', () => {\n    test({\n      validator: 'isAlpha',\n      args: ['eo'],\n      valid: [\n        'saluton',\n        'eĥoŝanĝoĉiuĵaŭde',\n        'EĤOŜANĜOĈIUĴAŬDE',\n        'Esperanto',\n        'LaŭLudovikoZamenhofBongustasFreŝaĈeĥaManĝaĵoKunSpicoj',\n      ],\n      invalid: [\n        'qwxyz',\n        '1887',\n        'qwxyz 1887',\n      ],\n    });\n  });\n\n  it('should error on invalid locale', () => {\n    test({\n      validator: 'isAlpha',\n      args: ['is-NOT'],\n      error: [\n        'abc',\n        'ABC',\n      ],\n    });\n  });\n\n  it('should validate alphanumeric strings', () => {\n    test({\n      validator: 'isAlphanumeric',\n      valid: [\n        'abc123',\n        'ABC11',\n      ],\n      invalid: [\n        'abc ',\n        'foo!!',\n        'ÄBC',\n        'FÜübar',\n        'Jön',\n      ],\n    });\n  });\n\n  it('should validate alphanumeric string with ignored characters', () => {\n    test({\n      validator: 'isAlphanumeric',\n      args: ['en-US', { ignore: '@_- ' }], // ignore [@ space _ -]\n      valid: [\n        'Hello@123',\n        'this is a valid alphaNumeric string',\n        'En-US @ alpha_numeric',\n      ],\n      invalid: [\n        'In*Valid',\n        'hello$123',\n        '{invalid}',\n      ],\n    });\n\n    test({\n      validator: 'isAlphanumeric',\n      args: ['en-US', { ignore: /[\\s/-]/g }], // ignore [space -]\n      valid: [\n        'en-US',\n        'this is a valid alphaNumeric string',\n      ],\n      invalid: [\n        'INVALID$ AlphaNum Str',\n        'hello@123',\n        'abc*123',\n      ],\n    });\n\n    test({\n      validator: 'isAlphanumeric',\n      args: ['en-US', { ignore: 1234 }], // invalid ignore matcher (ignore should be instance of a String or RegExp)\n      error: [\n        'alpha',\n      ],\n    });\n  });\n\n  it('should validate defined english aliases', () => {\n    test({\n      validator: 'isAlphanumeric',\n      args: ['en-GB'],\n      valid: [\n        'abc123',\n        'ABC11',\n      ],\n      invalid: [\n        'abc ',\n        'foo!!',\n        'ÄBC',\n        'FÜübar',\n        'Jön',\n      ],\n    });\n  });\n\n  it('should validate Azerbaijani alphanumeric strings', () => {\n    test({\n      validator: 'isAlphanumeric',\n      args: ['az-AZ'],\n      valid: [\n        'Azərbaycan',\n        'Bakı',\n        'abc1',\n        'abcç2',\n        '3kərə4kərə',\n      ],\n      invalid: [\n        '  foo1  ',\n        '',\n        'ab(cd)',\n        'simvol@',\n        'wəkil',\n      ],\n    });\n  });\n\n  it('should validate bulgarian alphanumeric strings', () => {\n    test({\n      validator: 'isAlphanumeric',\n      args: ['bg-BG'],\n      valid: [\n        'абв1',\n        '4АБ5В6',\n        'жаба',\n        'яГоДа2',\n        'йЮя',\n        '123',\n      ],\n      invalid: [\n        ' ',\n        '789  ',\n        'hello000',\n      ],\n    });\n  });\n\n  it('should validate Bengali alphanumeric strings', () => {\n    test({\n      validator: 'isAlphanumeric',\n      args: ['bn-BD'],\n      valid: [\n        'দ্গজ্ঞহ্রত্য১২৩',\n        'দ্গগফ৮৯০',\n        'চব৩৬৫ভবচ',\n        '১২৩৪',\n        '৩৪২৩৪দফজ্ঞদফ',\n      ],\n      invalid: [\n        ' ',\n        '১২৩  ',\n        'hel৩২0',\n      ],\n    });\n  });\n\n  it('should validate czech alphanumeric strings', () => {\n    test({\n      validator: 'isAlphanumeric',\n      args: ['cs-CZ'],\n      valid: [\n        'řiť123',\n        'KŮŇ11',\n      ],\n      invalid: [\n        'řiď ',\n        'blé!!',\n      ],\n    });\n  });\n\n  it('should validate slovak alphanumeric strings', () => {\n    test({\n      validator: 'isAlphanumeric',\n      args: ['sk-SK'],\n      valid: [\n        '1môj',\n        '2ľúbím',\n        '3mäkčeň',\n        '4stĹp',\n        '5vŕba',\n        '6ňorimberk',\n        '7ťava',\n        '8žanéta',\n        '9Ďábelské',\n        '10ódy',\n      ],\n      invalid: [\n        '1moj!',\n        '你好世界',\n        '  Привет мир  ',\n      ],\n    });\n  });\n\n  it('should validate danish alphanumeric strings', () => {\n    test({\n      validator: 'isAlphanumeric',\n      args: ['da-DK'],\n      valid: [\n        'ÆØÅ123',\n        'Ære321',\n        '321Øre',\n        '123Åre',\n      ],\n      invalid: [\n        'äbc123',\n        'ÄBC11',\n        '',\n      ],\n    });\n  });\n\n  it('should validate dutch alphanumeric strings', () => {\n    test({\n      validator: 'isAlphanumeric',\n      args: ['nl-NL'],\n      valid: [\n        'Kán123',\n        'één354',\n        'v4óór',\n        'nú234',\n        'hé54él',\n      ],\n      invalid: [\n        '1äca ',\n        'ab3cß',\n        'Øre',\n      ],\n    });\n  });\n\n  it('should validate finnish alphanumeric strings', () => {\n    test({\n      validator: 'isAlphanumeric',\n      args: ['fi-FI'],\n      valid: [\n        'äiti124',\n        'ÖLJY1234',\n        '123Åke',\n        '451åå23',\n      ],\n      invalid: [\n        'AİıÖöÇçŞşĞğÜüZ',\n        'foo!!',\n        '',\n      ],\n    });\n  });\n\n  it('should validate german alphanumeric strings', () => {\n    test({\n      validator: 'isAlphanumeric',\n      args: ['de-DE'],\n      valid: [\n        'äbc123',\n        'ÄBC11',\n      ],\n      invalid: [\n        'äca ',\n        'föö!!',\n      ],\n    });\n  });\n\n  it('should validate hungarian alphanumeric strings', () => {\n    test({\n      validator: 'isAlphanumeric',\n      args: ['hu-HU'],\n      valid: [\n        '0árvíztűrőtükörfúrógép123',\n        '0ÁRVÍZTŰRŐTÜKÖRFÚRÓGÉP123',\n      ],\n      invalid: [\n        '1időúr!',\n        'äbc1',\n        '  fäö  ',\n        'Heiß!',\n        '',\n      ],\n    });\n  });\n\n  it('should validate portuguese alphanumeric strings', () => {\n    test({\n      validator: 'isAlphanumeric',\n      args: ['pt-PT'],\n      valid: [\n        'palíndromo',\n        '2órgão',\n        'qwértyúão9',\n        'àäãcë4üïÄÏÜ',\n      ],\n      invalid: [\n        '!abc',\n        'Heiß',\n        'Øre',\n        'æøå',\n        '',\n      ],\n    });\n  });\n\n  it('should validate italian alphanumeric strings', () => {\n    test({\n      validator: 'isAlphanumeric',\n      args: ['it-IT'],\n      valid: [\n        '123àéèìîóòù',\n        '123correnti',\n        'DEFINIZIONE321',\n        'compil123azione',\n        'met23ró',\n        'pès56ca',\n        'PÉS45CA',\n        'gen45î',\n      ],\n      invalid: [\n        'äbc123',\n        'ÄBC11',\n        'æøå',\n        '',\n      ],\n    });\n  });\n\n  it('should validate spanish alphanumeric strings', () => {\n    test({\n      validator: 'isAlphanumeric',\n      args: ['es-ES'],\n      valid: [\n        'ábcó123',\n        'ÁBCÓ11',\n      ],\n      invalid: [\n        'äca ',\n        'abcß',\n        'föö!!',\n      ],\n    });\n  });\n\n  it('should validate Vietnamese alphanumeric strings', () => {\n    test({\n      validator: 'isAlphanumeric',\n      args: ['vi-VN'],\n      valid: [\n        'Thầy3',\n        '3Gà',\n      ],\n      invalid: [\n        'toang!',\n        'Cậu Vàng',\n      ],\n    });\n  });\n\n  it('should validate arabic alphanumeric strings', () => {\n    test({\n      validator: 'isAlphanumeric',\n      args: ['ar'],\n      valid: [\n        'أبت123',\n        'أبتَُِ١٢٣',\n      ],\n      invalid: [\n        'äca ',\n        'abcß',\n        'föö!!',\n      ],\n    });\n  });\n\n  it('should validate Hindi alphanumeric strings', () => {\n    test({\n      validator: 'isAlphanumeric',\n      args: ['hi-IN'],\n      valid: [\n        'अतअपनाअपनीअपनेअभीअंदरआदिआपइत्यादिइनइनकाइन्हींइन्हेंइन्होंइसइसकाइसकीइसकेइसमेंइसीइसेउनउनकाउनकीउनकेउनकोउन्हींउन्हेंउन्होंउसउसकेउसीउसेएकएवंएसऐसेऔरकईकरकरताकरतेकरनाकरनेकरेंकहतेकहाकाकाफ़ीकिकितनाकिन्हेंकिन्होंकियाकिरकिसकिसीकिसेकीकुछकुलकेकोकोईकौनकौनसागयाघरजबजहाँजाजितनाजिनजिन्हेंजिन्होंजिसजिसेजीधरजैसाजैसेजोतकतबतरहतिनतिन्हेंतिन्होंतिसतिसेतोथाथीथेदबारादियादुसरादूसरेदोद्वाराननकेनहींनानिहायतनीचेनेपरपहलेपूरापेफिरबनीबहीबहुतबादबालाबिलकुलभीभीतरमगरमानोमेमेंयदियहयहाँयहीयायिहयेरखेंरहारहेऱ्वासालिएलियेलेकिनववग़ैरहवर्गवहवहाँवहींवालेवुहवेवोसकतासकतेसबसेसभीसाथसाबुतसाभसारासेसोसंगहीहुआहुईहुएहैहैंहोहोताहोतीहोतेहोनाहोने०२३४५६७८९',\n        'इन्हें४५६७८९',\n      ],\n      invalid: [\n        'अत ०२३४५६७८९',\n        ' ३४५६७८९',\n        '12 ',\n        ' अत ',\n        'abc1',\n        'abc',\n        '',\n      ],\n    });\n  });\n\n  it('should validate farsi alphanumeric strings', () => {\n    test({\n      validator: 'isAlphanumeric',\n      args: ['fa-IR'],\n      valid: [\n        'پارسی۱۲۳',\n        '۱۴۵۶',\n        'مژگان9',\n      ],\n      invalid: [\n        'äca ',\n        'abcßة',\n        'föö!!',\n        '٤٥٦',\n      ],\n    });\n  });\n\n  it('should validate Japanese alphanumeric strings', () => {\n    test({\n      validator: 'isAlphanumeric',\n      args: ['ja-JP'],\n      valid: [\n        'あいうえお123',\n        '123がぎぐげご',\n        'ぁぃぅぇぉ',\n        'アイウエオ',\n        'ァィゥェ',\n        'ｱｲｳｴｵ',\n        '２０世紀少年',\n        '華氏４５１度',\n      ],\n      invalid: [\n        ' あいう123 ',\n        'abcあいう',\n        '生きろ!!',\n      ],\n    });\n  });\n\n  it('should validate kazakh alphanumeric strings', () => {\n    test({\n      validator: 'isAlphanumeric',\n      args: ['kk-KZ'],\n      valid: [\n        'Сәлем777',\n        '123Бәсе',\n        'солай',\n        'Жиенсу',\n        '90тоқсан',\n        'жалғыз',\n        '570бердім',\n      ],\n      invalid: [\n        ' кешіріңіз ',\n        'abcағылшынша',\n        'мүмкін!!',\n      ],\n    });\n  });\n\n  it('should validate kurdish alphanumeric strings', () => {\n    test({\n      validator: 'isAlphanumeric',\n      args: ['ku-IQ'],\n      valid: [\n        'ئؤڤگێ١٢٣',\n      ],\n      invalid: [\n        'äca ',\n        'abcß',\n        'föö!!',\n      ],\n    });\n  });\n\n  it('should validate defined arabic aliases', () => {\n    test({\n      validator: 'isAlphanumeric',\n      args: ['ar-SY'],\n      valid: [\n        'أبت123',\n        'أبتَُِ١٢٣',\n      ],\n      invalid: [\n        'abc ',\n        'foo!!',\n        'ÄBC',\n        'FÜübar',\n        'Jön',\n      ],\n    });\n  });\n\n  it('should validate norwegian alphanumeric strings', () => {\n    test({\n      validator: 'isAlphanumeric',\n      args: ['nb-NO'],\n      valid: [\n        'ÆØÅ123',\n        'Ære321',\n        '321Øre',\n        '123Åre',\n      ],\n      invalid: [\n        'äbc123',\n        'ÄBC11',\n        '',\n      ],\n    });\n  });\n\n  it('should validate polish alphanumeric strings', () => {\n    test({\n      validator: 'isAlphanumeric',\n      args: ['pl-PL'],\n      valid: [\n        'kre123ską',\n        'zam21knięte',\n        'zw23ykłe',\n        '123',\n        'prz23yjęły',\n        'świ23ęty',\n        'Poz1322wól',\n      ],\n      invalid: [\n        '12řiď ',\n        'blé!!',\n        'föö!2!',\n      ],\n    });\n  });\n\n  it('should validate serbian cyrillic alphanumeric strings', () => {\n    test({\n      validator: 'isAlphanumeric',\n      args: ['sr-RS'],\n      valid: [\n        'ШћжЂљЕ123',\n        'ЧПСТ132ЋЏ',\n      ],\n      invalid: [\n        'řiď ',\n        'blé!!',\n        'föö!!',\n      ],\n    });\n  });\n\n  it('should validate serbian latin alphanumeric strings', () => {\n    test({\n      validator: 'isAlphanumeric',\n      args: ['sr-RS@latin'],\n      valid: [\n        'ŠAabčšđćž123',\n        'ŠATRO11Ćčđš',\n      ],\n      invalid: [\n        'řiď ',\n        'blé!!',\n        'föö!!',\n      ],\n    });\n  });\n\n  it('should validate swedish alphanumeric strings', () => {\n    test({\n      validator: 'isAlphanumeric',\n      args: ['sv-SE'],\n      valid: [\n        'religiös13',\n        'st23jäla',\n        'västgöte123',\n        '123Åre',\n      ],\n      invalid: [\n        'AİıÖöÇçŞşĞğÜüZ',\n        'foo!!',\n        '',\n      ],\n    });\n  });\n\n  it('should validate turkish alphanumeric strings', () => {\n    test({\n      validator: 'isAlphanumeric',\n      args: ['tr-TR'],\n      valid: [\n        'AİıÖöÇçŞşĞğÜüZ123',\n      ],\n      invalid: [\n        'AİıÖöÇçŞşĞğÜüZ ',\n        'foo!!',\n        'ÄBC',\n      ],\n    });\n  });\n\n  it('should validate urkrainian alphanumeric strings', () => {\n    test({\n      validator: 'isAlphanumeric',\n      args: ['uk-UA'],\n      valid: [\n        'АБВГҐДЕЄЖЗИIЇЙКЛМНОПРСТУФХЦШЩЬЮЯ123',\n      ],\n      invalid: [\n        'éeoc ',\n        'foo!!',\n        'ÄBC',\n        'ЫыЪъЭэ',\n      ],\n    });\n  });\n\n  it('should validate greek alphanumeric strings', () => {\n    test({\n      validator: 'isAlphanumeric',\n      args: ['el-GR'],\n      valid: [\n        'αβγδεζηθικλμνξοπρςστυφχψω',\n        'ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡΣΤΥΦΧΨΩ',\n        '20θ',\n        '1234568960',\n      ],\n      invalid: [\n        '0AİıÖöÇçŞşĞğÜüZ1',\n        '  AİıÖöÇçŞşĞğÜüZ  ',\n        'ÄBC',\n        'Heiß',\n        'ЫыЪъЭэ',\n        'jαckγ',\n      ],\n    });\n  });\n\n  it('should validate Hebrew alphanumeric strings', () => {\n    test({\n      validator: 'isAlphanumeric',\n      args: ['he'],\n      valid: [\n        'אבג123',\n        'שלום11',\n      ],\n      invalid: [\n        'אבג ',\n        'לא!!',\n        'abc',\n        '  foo  ',\n      ],\n    });\n  });\n\n  it('should validate Thai alphanumeric strings', () => {\n    test({\n      validator: 'isAlphanumeric',\n      args: ['th-TH'],\n      valid: [\n        'สวัสดี ๑๒๓',\n        'ยินดีต้อนรับทั้ง ๒ คน',\n      ],\n      invalid: [\n        '1.สวัสดี',\n        'ยินดีต้อนรับทั้ง 2 คน',\n      ],\n    });\n  });\n\n  it('should validate Korea alphanumeric strings', () => {\n    test({\n      validator: 'isAlphanumeric',\n      args: ['ko-KR'],\n      valid: [\n        '2002',\n        '훈민정음',\n        '1446년훈민정음반포',\n      ],\n      invalid: [\n        '2022!',\n        '2019 코로나시작',\n        '1.로렘입숨',\n      ],\n    });\n  });\n\n  it('should validate Sinhala alphanumeric strings', () => {\n    test({\n      validator: 'isAlphanumeric',\n      args: ['si-LK'],\n      valid: [\n        'චතුර',\n        'කචට12',\n        'ඎඏදාෛපසුගො2',\n        '1234',\n      ],\n      invalid: [\n        'ஆஐअतක',\n        'කචට 12',\n        ' ඎ ',\n        'a1234',\n        'abc',\n        '',\n      ],\n    });\n  });\n\n  it('should validate Esperanto alphanumeric strings', () => {\n    test({\n      validator: 'isAlphanumeric',\n      args: ['eo'],\n      valid: [\n        'saluton',\n        'eĥoŝanĝoĉiuĵaŭde0123456789',\n        'EĤOŜANĜOĈIUĴAŬDE0123456789',\n        'Esperanto1887',\n        'LaŭLudovikoZamenhofBongustasFreŝaĈeĥaManĝaĵoKunSpicoj',\n      ],\n      invalid: [\n        'qwxyz',\n        'qwxyz 1887',\n      ],\n    });\n  });\n  it('should validate Tamil alphanumeric strings', () => {\n    test({\n      validator: 'isAlphanumeric',\n      args: ['ta-IN'],\n      valid: [\n        'தமிழ்',\n        'தமிழ்123',\n        'அஆஇஈ123',\n        'தமிழ்123.45',\n        '123.45',\n        'தமிழ்.',\n      ],\n      invalid: [\n        'தமிழ் ',\n        'abc',\n        '',\n      ],\n    });\n  });\n\n  it('should validate Telugu alphanumeric strings', () => {\n    test({\n      validator: 'isAlphanumeric',\n      args: ['te-IN'],\n      valid: [\n        'తెలుగు',\n        'తెలుగు123',\n        'అఆఇఈ123',\n        'తెలుగు123.45',\n        '123.45',\n        'తెలుగు.',\n      ],\n      invalid: [\n        'abc',\n        '',\n      ],\n    });\n  });\n\n  it('should validate Kannada alphanumeric strings', () => {\n    test({\n      validator: 'isAlphanumeric',\n      args: ['kn-IN'],\n      valid: [\n        'ಕನ್ನಡ',\n        'ಕನ್ನಡ123',\n        'ಅಆಇಈ123',\n        'ಕನ್ನಡ123.45',\n        '123.45',\n        'ಕನ್ನಡ.',\n      ],\n      invalid: [\n        'abc',\n        '',\n      ],\n    });\n  });\n\n  it('should validate Malayalam alphanumeric strings', () => {\n    test({\n      validator: 'isAlphanumeric',\n      args: ['ml-IN'],\n      valid: [\n        'മലയാളം',\n        'മലയാളം123',\n        'അആഇഈ123',\n        'മലയാളം123.45',\n        '123.45',\n        'മലയാളം.',\n      ],\n      invalid: [\n        'abc',\n        '',\n      ],\n    });\n  });\n\n  it('should validate Gujarati alphanumeric strings', () => {\n    test({\n      validator: 'isAlphanumeric',\n      args: ['gu-IN'],\n      valid: [\n        'ગુજરાતી',\n        'ગુજરાતી123',\n        'અઆઇઈ123',\n        'ગુજરાતી123.45',\n        '123.45',\n        'ગુજરાતી.',\n      ],\n      invalid: [\n        'abc',\n        '',\n      ],\n    });\n  });\n\n  it('should validate Punjabi alphanumeric strings', () => {\n    test({\n      validator: 'isAlphanumeric',\n      args: ['pa-IN'],\n      valid: [\n        'ਪੰਜਾਬੀ',\n        'ਪੰਜਾਬੀ123',\n        'ਅਆਇਈ123',\n        'ਪੰਜਾਬੀ123.45',\n        '123.45',\n        'ਪੰਜਾਬੀ.',\n      ],\n      invalid: [\n        'abc',\n        '',\n      ],\n    });\n  });\n\n  it('should validate Odia alphanumeric strings', () => {\n    test({\n      validator: 'isAlphanumeric',\n      args: ['or-IN'],\n      valid: [\n        'ଓଡ଼ିଆ',\n        'ଓଡ଼ିଆ123',\n        'ଅଆଇଈ123',\n        'ଓଡ଼ିଆ123.45',\n        '123.45',\n        'ଓଡ଼ିଆ.',\n      ],\n      invalid: [\n        'abc',\n        '',\n      ],\n    });\n  });\n\n  it('should validate Bengali alphanumeric strings', () => {\n    test({\n      validator: 'isAlphanumeric',\n      args: ['bn-IN'],\n      valid: [\n        'বাংলা',\n        'বাংলা১২৩',\n        'অআইঈ১২৩',\n        '১২৩৪৫৬৭৮৯০',\n        'বাংলা১২৩',\n        '১২৩৪৫',\n        'বাংলা',\n      ],\n      invalid: [\n        'abc',\n        'বাংলা123',\n        '123',\n        'বাংলা ১২৩',\n        'বাংলা,১২৩',\n        '১২৩٫৪৫',\n        '',\n      ],\n    });\n  });\n\n  it('should error on invalid locale', () => {\n    test({\n      validator: 'isAlphanumeric',\n      args: ['is-NOT'],\n      error: [\n        '1234568960',\n        'abc123',\n      ],\n    });\n  });\n\n  it('should validate numeric strings', () => {\n    test({\n      validator: 'isNumeric',\n      valid: [\n        '123',\n        '00123',\n        '-00123',\n        '0',\n        '-0',\n        '+123',\n        '123.123',\n        '+000000',\n      ],\n      invalid: [\n        ' ',\n        '',\n        '.',\n      ],\n    });\n  });\n\n  it('should validate numeric strings without symbols', () => {\n    test({\n      validator: 'isNumeric',\n      args: [{\n        no_symbols: true,\n      }],\n      valid: [\n        '123',\n        '00123',\n        '0',\n      ],\n      invalid: [\n        '-0',\n        '+000000',\n        '',\n        '+123',\n        '123.123',\n        '-00123',\n        ' ',\n        '.',\n      ],\n    });\n  });\n\n  it('should validate numeric strings with locale', () => {\n    test({\n      validator: 'isNumeric',\n      args: [{\n        locale: 'fr-FR',\n      }],\n      valid: [\n        '123',\n        '00123',\n        '-00123',\n        '0',\n        '-0',\n        '+123',\n        '123,123',\n        '+000000',\n      ],\n      invalid: [\n        ' ',\n        '',\n        ',',\n      ],\n    });\n  });\n\n  it('should validate numeric strings with locale', () => {\n    test({\n      validator: 'isNumeric',\n      args: [{\n        locale: 'fr-CA',\n      }],\n      valid: [\n        '123',\n        '00123',\n        '-00123',\n        '0',\n        '-0',\n        '+123',\n        '123,123',\n        '+000000',\n      ],\n      invalid: [\n        ' ',\n        '',\n        '.',\n      ],\n    });\n  });\n\n  it('should validate ports', () => {\n    test({\n      validator: 'isPort',\n      valid: [\n        '0',\n        '22',\n        '80',\n        '443',\n        '3000',\n        '8080',\n        '65535',\n      ],\n      invalid: [\n        '',\n        '-1',\n        '65536',\n        '0080',\n      ],\n    });\n  });\n\n  it('should validate passport number', () => {\n    test({\n      validator: 'isPassportNumber',\n      args: ['AM'],\n      valid: [\n        'AF0549358',\n      ],\n      invalid: [\n        'A1054935',\n      ],\n    });\n\n\n    test({\n      validator: 'isPassportNumber',\n      args: ['ID'],\n      valid: [\n        'C1253473',\n        'B5948378',\n        'A4859472',\n      ],\n      invalid: [\n        'D39481728',\n        'A-3847362',\n        '324132132',\n      ],\n    });\n\n    test({\n      validator: 'isPassportNumber',\n      args: ['AR'],\n      valid: [\n        'AAC811035',\n      ],\n      invalid: [\n        'A11811035',\n      ],\n    });\n\n    test({\n      validator: 'isPassportNumber',\n      args: ['AT'],\n      valid: [\n        'P 1630837',\n        'P 4366918',\n      ],\n      invalid: [\n        '0 1630837',\n      ],\n    });\n\n    test({\n      validator: 'isPassportNumber',\n      args: ['AU'],\n      valid: [\n        'N0995852',\n        'L4819236',\n      ],\n      invalid: [\n        '1A012345',\n      ],\n    });\n\n    test({\n      validator: 'isPassportNumber',\n      args: ['AZ'],\n      valid: [\n        'A16175905',\n        'A16175958',\n      ],\n      invalid: [\n        'AZ1234584',\n      ],\n    });\n\n    test({\n      validator: 'isPassportNumber',\n      args: ['BE'],\n      valid: [\n        'EM000000',\n        'LA080402',\n      ],\n      invalid: [\n        '00123456',\n      ],\n    });\n\n    test({\n      validator: 'isPassportNumber',\n      args: ['BG'],\n      valid: [\n        '346395366',\n        '039903356',\n      ],\n      invalid: [\n        'ABC123456',\n      ],\n    });\n\n    test({\n      validator: 'isPassportNumber',\n      args: ['BR'],\n      valid: [\n        'FZ973689',\n        'GH231233',\n      ],\n      invalid: [\n        'ABX29332',\n      ],\n    });\n\n    test({\n      validator: 'isPassportNumber',\n      args: ['BY'],\n      valid: [\n        'MP3899901',\n      ],\n      invalid: [\n        '345333454',\n        'FG53334542',\n      ],\n    });\n\n    test({\n      validator: 'isPassportNumber',\n      args: ['CA'],\n      valid: [\n        'GA302922',\n        'ZE000509',\n        'A123456AB',\n        'Z556378HG',\n      ],\n      invalid: [\n        'AB0123456',\n        'AZ556378H',\n        '556378HCX',\n        '556378432',\n        '5563784',\n        '#B12345FD',\n        'A43F12354',\n      ],\n    });\n\n    test({\n      validator: 'isPassportNumber',\n      args: ['CH'],\n      valid: [\n        'S1100409',\n        'S5200073',\n        'X4028791',\n      ],\n      invalid: [\n        'AB123456',\n      ],\n    });\n\n    test({\n      validator: 'isPassportNumber',\n      args: ['CN'],\n      valid: [\n        'G25352389',\n        'E00160027',\n        'EA1234567',\n      ],\n      invalid: [\n        'K0123456',\n        'E-1234567',\n        'G.1234567',\n        'GA1234567',\n        'EI1234567',\n        'GO1234567',\n      ],\n    });\n\n    test({\n      validator: 'isPassportNumber',\n      args: ['CY'],\n      valid: [\n        'K00000413',\n      ],\n      invalid: [\n        'K10100',\n      ],\n    });\n\n    test({\n      validator: 'isPassportNumber',\n      args: ['CZ'],\n      valid: [\n        '99003853',\n        '42747260',\n      ],\n      invalid: [\n        '012345678',\n        'AB123456',\n      ],\n    });\n\n    test({\n      validator: 'isPassportNumber',\n      args: ['DE'],\n      valid: [\n        'C01X00T47',\n        'C26VMVVC3',\n      ],\n      invalid: [\n        'AS0123456',\n        'A012345678',\n      ],\n    });\n\n    test({\n      validator: 'isPassportNumber',\n      args: ['DK'],\n      valid: [\n        '900010172',\n      ],\n      invalid: [\n        '01234567',\n        'K01234567',\n      ],\n    });\n\n    test({\n      validator: 'isPassportNumber',\n      args: ['DZ'],\n      valid: [\n        '855609385',\n        '154472412',\n        '197025599',\n      ],\n      invalid: [\n        'AS0123456',\n        'A012345678',\n        '0123456789',\n        '12345678',\n        '98KK54321',\n      ],\n    });\n\n    test({\n      validator: 'isPassportNumber',\n      args: ['EE'],\n      valid: [\n        'K4218285',\n        'K3295867',\n        'KB0167630',\n        'VD0023777',\n      ],\n      invalid: [\n        'K01234567',\n        'KB00112233',\n      ],\n    });\n\n    test({\n      validator: 'isPassportNumber',\n      args: ['ES'],\n      valid: [\n        'AF238143',\n        'ZAB000254',\n      ],\n      invalid: [\n        'AF01234567',\n      ],\n    });\n\n    test({\n      validator: 'isPassportNumber',\n      args: ['FI'],\n      valid: [\n        'XP8271602',\n        'XD8500003',\n      ],\n      invalid: [\n        'A01234567',\n        'ABC012345',\n      ],\n    });\n\n    test({\n      validator: 'isPassportNumber',\n      args: ['FR'],\n      valid: [\n        '10CV28144',\n        '60RF19342',\n        '05RP34083',\n      ],\n      invalid: [\n        '012345678',\n        'AB0123456',\n        '01C234567',\n      ],\n    });\n\n    test({\n      validator: 'isPassportNumber',\n      args: ['GB'],\n      valid: [\n        '925076473',\n        '107182890',\n        '104121156',\n      ],\n      invalid: [\n        'A012345678',\n        'K000000000',\n        '0123456789',\n      ],\n    });\n\n    test({\n      validator: 'isPassportNumber',\n      args: ['GR'],\n      valid: [\n        'AE0000005',\n        'AK0219304',\n      ],\n      invalid: [\n        'A01234567',\n        '012345678',\n      ],\n    });\n\n    test({\n      validator: 'isPassportNumber',\n      args: ['HR'],\n      valid: [\n        '007007007',\n        '138463188',\n      ],\n      invalid: [\n        'A01234567',\n        '00112233',\n      ],\n    });\n\n    test({\n      validator: 'isPassportNumber',\n      args: ['HU'],\n      valid: [\n        'ZA084505',\n        'BA0006902',\n      ],\n      invalid: [\n        'A01234567',\n        '012345678',\n      ],\n    });\n\n    test({\n      validator: 'isPassportNumber',\n      args: ['IE'],\n      valid: [\n        'D23145890',\n        'X65097105',\n        'XN0019390',\n      ],\n      invalid: [\n        'XND012345',\n        '0123456789',\n      ],\n    });\n\n    test({\n      validator: 'isPassportNumber',\n      args: ['IN'],\n      valid: [\n        'A-1234567',\n        'A1234567',\n        'X0019390',\n      ],\n      invalid: [\n        'AB-1234567',\n        '0123456789',\n      ],\n    });\n\n    test({\n      validator: 'isPassportNumber',\n      args: ['IR'],\n      valid: [\n        'J97634522',\n        'A01234567',\n        'Z11977831',\n      ],\n      invalid: [\n        'A0123456',\n        'A0123456Z',\n        '012345678',\n      ],\n    });\n\n    test({\n      validator: 'isPassportNumber',\n      args: ['IS'],\n      valid: [\n        'A2040611',\n        'A1197783',\n      ],\n      invalid: [\n        'K0000000',\n        '01234567',\n      ],\n    });\n\n    test({\n      validator: 'isPassportNumber',\n      args: ['IT'],\n      valid: [\n        'YA8335453',\n        'KK0000000',\n      ],\n      invalid: [\n        '01234567',\n        'KAK001122',\n      ],\n    });\n\n    test({\n      validator: 'isPassportNumber',\n      args: ['JM'],\n      valid: [\n        'A0123456',\n      ],\n      invalid: [\n        's0123456',\n        'a01234567',\n      ],\n    });\n\n    test({\n      validator: 'isPassportNumber',\n      args: ['JP'],\n      valid: [\n        'NH1106002',\n        'TE3180251',\n        'XS1234567',\n      ],\n      invalid: [\n        'X12345678',\n        '012345678',\n      ],\n    });\n\n    test({\n      validator: 'isPassportNumber',\n      args: ['KR'],\n      valid: [\n        'M35772699',\n        'M70689098',\n      ],\n      invalid: [\n        'X12345678',\n        '012345678',\n      ],\n    });\n\n    test({\n      validator: 'isPassportNumber',\n      args: ['KZ'],\n      valid: [\n        'A0123456',\n        'b0123456',\n      ],\n      invalid: [\n        '01234567',\n        'bb0123456',\n      ],\n    });\n\n    test({\n      validator: 'isPassportNumber',\n      args: ['LI'],\n      valid: [\n        'a01234',\n        'f01234',\n      ],\n      invalid: [\n        '012345',\n      ],\n    });\n\n    test({\n      validator: 'isPassportNumber',\n      args: ['LT'],\n      valid: [\n        '20200997',\n        'LB311756',\n      ],\n      invalid: [\n        'LB01234567',\n      ],\n    });\n\n    test({\n      validator: 'isPassportNumber',\n      args: ['LU'],\n      valid: [\n        'JCU9J4T2',\n        'JC4E7L2H',\n      ],\n      invalid: [\n        'JCU9J4T',\n        'JC4E7L2H0',\n      ],\n    });\n\n    test({\n      validator: 'isPassportNumber',\n      args: ['LV'],\n      valid: [\n        'LV9000339',\n        'LV4017173',\n      ],\n      invalid: [\n        'LV01234567',\n        '4017173LV',\n      ],\n    });\n    test({\n      validator: 'isPassportNumber',\n      args: ['LY'],\n      valid: [\n        'P79JF34X',\n        'RJ45H4V2',\n      ],\n      invalid: [\n        'P79JF34',\n        'RJ45H4V2C',\n        'RJ4-H4V2',\n      ],\n    });\n\n    test({\n      validator: 'isPassportNumber',\n      args: ['MT'],\n      valid: [\n        '1026564',\n      ],\n      invalid: [\n        '01234567',\n        'MT01234',\n      ],\n    });\n    test({\n      validator: 'isPassportNumber',\n      args: ['MZ'],\n      valid: [\n        'AB0808212',\n        '08AB12123',\n      ],\n      invalid: [\n        '1AB011241',\n        '1AB01121',\n        'ABAB01121',\n      ],\n    });\n    test({\n      validator: 'isPassportNumber',\n      args: ['MY'],\n      valid: [\n        'A00000000',\n        'H12345678',\n        'K43143233',\n      ],\n      invalid: [\n        'A1234567',\n        'C01234567',\n      ],\n    });\n\n    test({\n      validator: 'isPassportNumber',\n      args: ['MX'],\n      valid: [\n        'G98639222',\n        'N23457890',\n      ],\n      invalid: [\n        'ABC34567890',\n        '43986369222',\n        'N234578909',\n        '34567890',\n      ],\n    });\n\n    test({\n      validator: 'isPassportNumber',\n      args: ['NL'],\n      valid: [\n        'XTR110131',\n        'XR1001R58',\n      ],\n      invalid: [\n        'XTR11013R',\n        'XR1001R58A',\n      ],\n    });\n    test({\n      validator: 'isPassportNumber',\n      args: ['PK'],\n      valid: [\n        'QZ1791293',\n        'XR1001458',\n      ],\n      invalid: [\n        'XTR11013R',\n        'XR1001R58A',\n      ],\n    });\n\n    test({\n      validator: 'isPassportNumber',\n      args: ['PH'],\n      valid: [\n        'X123456',\n        'XY123456',\n        'XY1234567',\n        'X1234567Y',\n      ],\n      invalid: [\n        'XY12345',\n        'X12345Z',\n        'XY12345Z',\n      ],\n    });\n\n    test({\n      validator: 'isPassportNumber',\n      args: ['NZ'],\n      valid: [\n        'Lf012345',\n        'La012345',\n        'Ld012345',\n        'Lh012345',\n        'ea012345',\n        'ep012345',\n        'n012345',\n      ],\n      invalid: [\n        'Lp012345',\n        'nd012345',\n        'ed012345',\n        'eh012345',\n        'ef012345',\n      ],\n    });\n\n    test({\n      validator: 'isPassportNumber',\n      args: ['PL'],\n      valid: [\n        'ZS 0000177',\n        'AN 3000011',\n      ],\n      invalid: [\n        'A1 0000177',\n        '012345678',\n      ],\n    });\n\n    test({\n      validator: 'isPassportNumber',\n      args: ['PT'],\n      valid: [\n        'I700044',\n        'K453286',\n      ],\n      invalid: [\n        '0700044',\n        'K4532861',\n      ],\n    });\n\n    test({\n      validator: 'isPassportNumber',\n      args: ['RO'],\n      valid: [\n        '05485968',\n        '040005646',\n      ],\n      invalid: [\n        'R05485968',\n        '0511060461',\n      ],\n    });\n\n    test({\n      validator: 'isPassportNumber',\n      args: ['RU'],\n      valid: [\n        '2 32 636829',\n        '012 345321',\n        '439863692',\n      ],\n      invalid: [\n        'A 2R YU46J0',\n        '01A 3D5321',\n        'SF233D53T',\n        '12345678',\n        '1234567890',\n      ],\n    });\n\n    test({\n      validator: 'isPassportNumber',\n      args: ['SE'],\n      valid: [\n        '59000001',\n        '56702928',\n      ],\n      invalid: [\n        'SE012345',\n        '012345678',\n      ],\n    });\n\n    test({\n      validator: 'isPassportNumber',\n      args: ['SL'],\n      valid: [\n        'PB0036440',\n        'PB1390281',\n      ],\n      invalid: [\n        'SL0123456',\n        'P01234567',\n      ],\n    });\n\n    test({\n      validator: 'isPassportNumber',\n      args: ['SK'],\n      valid: [\n        'P0000000',\n      ],\n      invalid: [\n        'SK012345',\n        '012345678',\n      ],\n    });\n\n    test({\n      validator: 'isPassportNumber',\n      args: ['TH'],\n      valid: [\n        'A123456',\n        'B1234567',\n        'CD123456',\n        'EF1234567',\n      ],\n      invalid: [\n        '123456',\n        '1234567',\n        '010485371AA',\n      ],\n    });\n\n    test({\n      validator: 'isPassportNumber',\n      args: ['TR'],\n      valid: [\n        'U 06764100',\n        'U 01048537',\n      ],\n      invalid: [\n        '06764100U',\n        '010485371',\n      ],\n    });\n\n    test({\n      validator: 'isPassportNumber',\n      args: ['UA'],\n      valid: [\n        'EH345655',\n        'EK000001',\n        'AP841503',\n      ],\n      invalid: [\n        '01234567',\n        '012345EH',\n        'A012345P',\n      ],\n    });\n\n    test({\n      validator: 'isPassportNumber',\n      args: ['US'],\n      valid: [\n        '790369937',\n        '340007237',\n        'A90583942',\n        'E00007734',\n      ],\n      invalid: [\n        'US0123456',\n        '0123456US',\n        '7903699371',\n        '90583942',\n        'E000077341',\n      ],\n    });\n\n    test({\n      validator: 'isPassportNumber',\n      args: ['ZA'],\n      valid: [\n        'T12345678',\n        'A12345678',\n        'M12345678',\n        'D12345678',\n      ],\n      invalid: [\n        '123456789',\n        'Z12345678',\n      ],\n    });\n  });\n\n  it('should validate decimal numbers', () => {\n    test({\n      validator: 'isDecimal',\n      valid: [\n        '123',\n        '00123',\n        '-00123',\n        '0',\n        '-0',\n        '+123',\n        '0.01',\n        '.1',\n        '1.0',\n        '-.25',\n        '-0',\n        '0.0000000000001',\n      ],\n      invalid: [\n        '0,01',\n        ',1',\n        '1,0',\n        '-,25',\n        '0,0000000000001',\n        '0٫01',\n        '٫1',\n        '1٫0',\n        '-٫25',\n        '0٫0000000000001',\n        '....',\n        ' ',\n        '',\n        '-',\n        '+',\n        '.',\n        '0.1a',\n        'a',\n        '\\n',\n      ],\n    });\n\n    test({\n      validator: 'isDecimal',\n      args: [{ locale: 'en-AU' }],\n      valid: [\n        '123',\n        '00123',\n        '-00123',\n        '0',\n        '-0',\n        '+123',\n        '0.01',\n        '.1',\n        '1.0',\n        '-.25',\n        '-0',\n        '0.0000000000001',\n      ],\n      invalid: [\n        '0,01',\n        ',1',\n        '1,0',\n        '-,25',\n        '0,0000000000001',\n        '0٫01',\n        '٫1',\n        '1٫0',\n        '-٫25',\n        '0٫0000000000001',\n        '....',\n        ' ',\n        '',\n        '-',\n        '+',\n        '.',\n        '0.1a',\n        'a',\n        '\\n',\n      ],\n    });\n\n    test({\n      validator: 'isDecimal',\n      args: [{ locale: ['bg-BG'] }],\n      valid: [\n        '123',\n        '00123',\n        '-00123',\n        '0',\n        '-0',\n        '+123',\n        '0,01',\n        ',1',\n        '1,0',\n        '-,25',\n        '-0',\n        '0,0000000000001',\n      ],\n      invalid: [\n        '0.0000000000001',\n        '0.01',\n        '.1',\n        '1.0',\n        '-.25',\n        '0٫01',\n        '٫1',\n        '1٫0',\n        '-٫25',\n        '0٫0000000000001',\n        '....',\n        ' ',\n        '',\n        '-',\n        '+',\n        '.',\n        '0.1a',\n        'a',\n        '\\n',\n      ],\n    });\n\n    test({\n      validator: 'isDecimal',\n      args: [{ locale: ['cs-CZ'] }],\n      valid: [\n        '123',\n        '00123',\n        '-00123',\n        '0',\n        '-0',\n        '+123',\n        '0,01',\n        ',1',\n        '1,0',\n        '-,25',\n        '-0',\n        '0,0000000000001',\n      ],\n      invalid: [\n        '0.0000000000001',\n        '0.01',\n        '.1',\n        '1.0',\n        '-.25',\n        '0٫01',\n        '٫1',\n        '1٫0',\n        '-٫25',\n        '0٫0000000000001',\n        '....',\n        ' ',\n        '',\n        '-',\n        '+',\n        '.',\n        '0.1a',\n        'a',\n        '\\n',\n      ],\n    });\n\n    test({\n      validator: 'isDecimal',\n      args: [{ locale: ['ar-JO'] }],\n      valid: [\n        '123',\n        '00123',\n        '-00123',\n        '0',\n        '-0',\n        '+123',\n        '0٫01',\n        '٫1',\n        '1٫0',\n        '-٫25',\n        '-0',\n        '0٫0000000000001',\n      ],\n      invalid: [\n        '0,0000000000001',\n        '0,01',\n        ',1',\n        '1,0',\n        '-,25',\n        '0.0000000000001',\n        '0.01',\n        '.1',\n        '1.0',\n        '-.25',\n        '....',\n        ' ',\n        '',\n        '-',\n        '+',\n        '.',\n        '0.1a',\n        'a',\n        '\\n',\n      ],\n    });\n\n    test({\n      validator: 'isDecimal',\n      args: [{ locale: ['ar-EG'] }],\n      valid: [\n        '0.01',\n      ],\n      invalid: [\n        '0,01',\n      ],\n    });\n\n    test({\n      validator: 'isDecimal',\n      args: [{ locale: ['en-ZM'] }],\n      valid: [\n        '0,01',\n      ],\n      invalid: [\n        '0.01',\n      ],\n    });\n\n    test({\n      validator: 'isDecimal',\n      args: [{ force_decimal: true }],\n      valid: [\n        '0.01',\n        '.1',\n        '1.0',\n        '-.25',\n        '0.0000000000001',\n      ],\n      invalid: [\n        '-0',\n        '123',\n        '00123',\n        '-00123',\n        '0',\n        '-0',\n        '+123',\n        '0,0000000000001',\n        '0,01',\n        ',1',\n        '1,0',\n        '-,25',\n        '....',\n        ' ',\n        '',\n        '-',\n        '+',\n        '.',\n        '0.1a',\n        'a',\n        '\\n',\n      ],\n    });\n\n    test({\n      validator: 'isDecimal',\n      args: [{ decimal_digits: '2,3' }],\n      valid: [\n        '123',\n        '00123',\n        '-00123',\n        '0',\n        '-0',\n        '+123',\n        '0.01',\n        '1.043',\n        '.15',\n        '-.255',\n        '-0',\n      ],\n      invalid: [\n        '0.0000000000001',\n        '0.0',\n        '.1',\n        '1.0',\n        '-.2564',\n        '0.0',\n        '٫1',\n        '1٫0',\n        '-٫25',\n        '0٫0000000000001',\n        '....',\n        ' ',\n        '',\n        '-',\n        '+',\n        '.',\n        '0.1a',\n        'a',\n        '\\n',\n      ],\n    });\n  });\n\n  it('should error on invalid locale', () => {\n    test({\n      validator: 'isDecimal',\n      args: [{ locale: ['is-NOT'] }],\n      error: [\n        '123',\n        '0.01',\n        '0,01',\n      ],\n    });\n  });\n\n  it('should validate lowercase strings', () => {\n    test({\n      validator: 'isLowercase',\n      valid: [\n        'abc',\n        'abc123',\n        'this is lowercase.',\n        'tr竪s 端ber',\n      ],\n      invalid: [\n        'fooBar',\n        '123A',\n      ],\n    });\n  });\n\n\n  it('should validate imei strings', () => {\n    test({\n      validator: 'isIMEI',\n      valid: [\n        '352099001761481',\n        '868932036356090',\n        '490154203237518',\n        '546918475942169',\n        '998227667144730',\n        '532729766805999',\n      ],\n      invalid: [\n        '490154203237517',\n        '3568680000414120',\n        '3520990017614823',\n      ],\n    });\n  });\n\n\n  it('should validate imei strings with hyphens', () => {\n    test({\n      validator: 'isIMEI',\n      args: [{ allow_hyphens: true }],\n      valid: [\n        '35-209900-176148-1',\n        '86-893203-635609-0',\n        '49-015420-323751-8',\n        '54-691847-594216-9',\n        '99-822766-714473-0',\n        '53-272976-680599-9',\n      ],\n      invalid: [\n        '49-015420-323751-7',\n        '35-686800-0041412-0',\n        '35-209900-1761482-3',\n      ],\n    });\n  });\n\n\n  it('should validate uppercase strings', () => {\n    test({\n      validator: 'isUppercase',\n      valid: [\n        'ABC',\n        'ABC123',\n        'ALL CAPS IS FUN.',\n        '   .',\n      ],\n      invalid: [\n        'fooBar',\n        '123abc',\n      ],\n    });\n  });\n\n  it('should validate integers', () => {\n    test({\n      validator: 'isInt',\n      valid: [\n        '13',\n        '123',\n        '0',\n        '123',\n        '-0',\n        '+1',\n        '01',\n        '-01',\n        '000',\n      ],\n      invalid: [\n        '100e10',\n        '123.123',\n        '   ',\n        '',\n      ],\n    });\n    test({\n      validator: 'isInt',\n      args: [{ allow_leading_zeroes: false }],\n      valid: [\n        '13',\n        '123',\n        '0',\n        '123',\n        '-0',\n        '+1',\n      ],\n      invalid: [\n        '01',\n        '-01',\n        '000',\n        '100e10',\n        '123.123',\n        '   ',\n        '',\n      ],\n    });\n    test({\n      validator: 'isInt',\n      args: [{ allow_leading_zeroes: true }],\n      valid: [\n        '13',\n        '123',\n        '0',\n        '123',\n        '-0',\n        '+1',\n        '01',\n        '-01',\n        '000',\n        '-000',\n        '+000',\n      ],\n      invalid: [\n        '100e10',\n        '123.123',\n        '   ',\n        '',\n      ],\n    });\n    test({\n      validator: 'isInt',\n      args: [{\n        min: 10,\n      }],\n      valid: [\n        '15',\n        '80',\n        '99',\n      ],\n      invalid: [\n        '9',\n        '6',\n        '3.2',\n        'a',\n      ],\n    });\n    test({\n      validator: 'isInt',\n      args: [{\n        min: 10,\n        max: 15,\n      }],\n      valid: [\n        '15',\n        '11',\n        '13',\n      ],\n      invalid: [\n        '9',\n        '2',\n        '17',\n        '3.2',\n        '33',\n        'a',\n      ],\n    });\n    test({\n      validator: 'isInt',\n      args: [{\n        gt: 10,\n        lt: 15,\n      }],\n      valid: [\n        '14',\n        '11',\n        '13',\n      ],\n      invalid: [\n        '10',\n        '15',\n        '17',\n        '3.2',\n        '33',\n        'a',\n      ],\n    });\n    test({\n      validator: 'isInt',\n      args: [{\n        min: undefined,\n        max: undefined,\n      }],\n      valid: [\n        '143',\n        '15',\n        '767777575',\n      ],\n      invalid: [\n        '10.4',\n        'bar',\n        '10a',\n        'c44',\n      ],\n    });\n    test({\n      validator: 'isInt',\n      args: [{\n        gt: undefined,\n        lt: undefined,\n      }],\n      valid: [\n        '289373466',\n        '55',\n        '989',\n      ],\n      invalid: [\n        '10.4',\n        'baz',\n        '66a',\n        'c21',\n      ],\n    });\n    test({\n      validator: 'isInt',\n      args: [{\n        gt: null,\n        max: null,\n      }],\n      valid: [\n        '1',\n        '886',\n        '84512345',\n      ],\n      invalid: [\n        '10.4',\n        'h',\n        '1.2',\n        '+',\n      ],\n    });\n    test({\n      validator: 'isInt',\n      args: [{\n        lt: null,\n        min: null,\n      }],\n      valid: [\n        '289373466',\n        '55',\n        '989',\n      ],\n      invalid: [\n        ',',\n        '+11212+',\n        'fail',\n        '111987234i',\n      ],\n    });\n  });\n\n  it('should validate floats', () => {\n    test({\n      validator: 'isFloat',\n      valid: [\n        '123',\n        '123.',\n        '123.123',\n        '-123.123',\n        '-0.123',\n        '+0.123',\n        '0.123',\n        '.0',\n        '-.123',\n        '+.123',\n        '01.123',\n        '-0.22250738585072011e-307',\n      ],\n      invalid: [\n        '+',\n        '-',\n        '  ',\n        '',\n        '.',\n        ',',\n        'foo',\n        '20.foo',\n        '2020-01-06T14:31:00.135Z',\n      ],\n    });\n\n    test({\n      validator: 'isFloat',\n      args: [{ locale: 'en-AU' }],\n      valid: [\n        '123',\n        '123.',\n        '123.123',\n        '-123.123',\n        '-0.123',\n        '+0.123',\n        '0.123',\n        '.0',\n        '-.123',\n        '+.123',\n        '01.123',\n        '-0.22250738585072011e-307',\n      ],\n      invalid: [\n        '123٫123',\n        '123,123',\n        '  ',\n        '',\n        '.',\n        'foo',\n      ],\n    });\n\n    test({\n      validator: 'isFloat',\n      args: [{ locale: 'de-DE' }],\n      valid: [\n        '123',\n        '123,',\n        '123,123',\n        '-123,123',\n        '-0,123',\n        '+0,123',\n        '0,123',\n        ',0',\n        '-,123',\n        '+,123',\n        '01,123',\n        '-0,22250738585072011e-307',\n      ],\n      invalid: [\n        '123.123',\n        '123٫123',\n        '  ',\n        '',\n        '.',\n        'foo',\n      ],\n    });\n\n    test({\n      validator: 'isFloat',\n      args: [{ locale: 'ar-JO' }],\n      valid: [\n        '123',\n        '123٫',\n        '123٫123',\n        '-123٫123',\n        '-0٫123',\n        '+0٫123',\n        '0٫123',\n        '٫0',\n        '-٫123',\n        '+٫123',\n        '01٫123',\n        '-0٫22250738585072011e-307',\n      ],\n      invalid: [\n        '123,123',\n        '123.123',\n        '  ',\n        '',\n        '.',\n        'foo',\n      ],\n    });\n\n    test({\n      validator: 'isFloat',\n      args: [{\n        min: 3.7,\n      }],\n      valid: [\n        '3.888',\n        '3.92',\n        '4.5',\n        '50',\n        '3.7',\n        '3.71',\n      ],\n      invalid: [\n        '3.6',\n        '3.69',\n        '3',\n        '1.5',\n        'a',\n      ],\n    });\n    test({\n      validator: 'isFloat',\n      args: [{\n        min: 0.1,\n        max: 1.0,\n      }],\n      valid: [\n        '0.1',\n        '1.0',\n        '0.15',\n        '0.33',\n        '0.57',\n        '0.7',\n      ],\n      invalid: [\n        '0',\n        '0.0',\n        'a',\n        '1.3',\n        '0.05',\n        '5',\n      ],\n    });\n    test({\n      validator: 'isFloat',\n      args: [{\n        gt: -5.5,\n        lt: 10,\n      }],\n      valid: [\n        '9.9',\n        '1.0',\n        '0',\n        '-1',\n        '7',\n        '-5.4',\n      ],\n      invalid: [\n        '10',\n        '-5.5',\n        'a',\n        '-20.3',\n        '20e3',\n        '10.00001',\n      ],\n    });\n    test({\n      validator: 'isFloat',\n      args: [{\n        min: -5.5,\n        max: 10,\n        gt: -5.5,\n        lt: 10,\n      }],\n      valid: [\n        '9.99999',\n        '-5.499999',\n      ],\n      invalid: [\n        '10',\n        '-5.5',\n      ],\n    });\n    test({\n      validator: 'isFloat',\n      args: [{\n        locale: 'de-DE',\n        min: 3.1,\n      }],\n      valid: [\n        '123',\n        '123,',\n        '123,123',\n        '3,1',\n        '3,100001',\n      ],\n      invalid: [\n        '3,09',\n        '-,123',\n        '+,123',\n        '01,123',\n        '-0,22250738585072011e-307',\n        '-123,123',\n        '-0,123',\n        '+0,123',\n        '0,123',\n        ',0',\n        '123.123',\n        '123٫123',\n        '  ',\n        '',\n        '.',\n        'foo',\n      ],\n    });\n    test({\n      validator: 'isFloat',\n      args: [{\n        min: undefined,\n        max: undefined,\n      }],\n      valid: [\n        '123',\n        '123.',\n        '123.123',\n        '-767.767',\n        '+111.111',\n      ],\n      invalid: [\n        'ab565',\n        '-,123',\n        '+,123',\n        '7866.t',\n        '123,123',\n        '123,',\n      ],\n    });\n    test({\n      validator: 'isFloat',\n      args: [{\n        gt: undefined,\n        lt: undefined,\n      }],\n      valid: [\n        '14.34343',\n        '11.1',\n        '456',\n      ],\n      invalid: [\n        'ab565',\n        '-,123',\n        '+,123',\n        '7866.t',\n      ],\n    });\n    test({\n      validator: 'isFloat',\n      args: [{\n        locale: 'ar',\n        gt: null,\n        max: null,\n      }],\n      valid: [\n        '13324٫',\n        '12321',\n        '444٫83874',\n      ],\n      invalid: [\n        '55.55.55',\n        '1;23',\n        '+-123',\n        '1111111l1',\n        '3.3',\n      ],\n    });\n    test({\n      validator: 'isFloat',\n      args: [{\n        locale: 'ru-RU',\n        lt: null,\n        min: null,\n      }],\n      valid: [\n        '11231554,34343',\n        '11,1',\n        '456',\n        ',311',\n      ],\n      invalid: [\n        'ab565',\n        '-.123',\n        '+.123',\n        '7866.t',\n        '22.3',\n      ],\n    });\n  });\n\n  it('should validate hexadecimal strings', () => {\n    test({\n      validator: 'isHexadecimal',\n      valid: [\n        'deadBEEF',\n        'ff0044',\n        '0xff0044',\n        '0XfF0044',\n        '0x0123456789abcDEF',\n        '0X0123456789abcDEF',\n        '0hfedCBA9876543210',\n        '0HfedCBA9876543210',\n        '0123456789abcDEF',\n      ],\n      invalid: [\n        'abcdefg',\n        '',\n        '..',\n        '0xa2h',\n        '0xa20x',\n        '0x0123456789abcDEFq',\n        '0hfedCBA9876543210q',\n        '01234q56789abcDEF',\n      ],\n    });\n  });\n\n  it('should validate octal strings', () => {\n    test({\n      validator: 'isOctal',\n      valid: [\n        '076543210',\n        '0o01234567',\n      ],\n      invalid: [\n        'abcdefg',\n        '012345678',\n        '012345670c',\n        '00c12345670c',\n        '',\n        '..',\n      ],\n    });\n  });\n\n  it('should validate hexadecimal color strings', () => {\n    test({\n      validator: 'isHexColor',\n      valid: [\n        '#ff0000ff',\n        '#ff0034',\n        '#CCCCCC',\n        '0f38',\n        'fff',\n        '#f00',\n      ],\n      invalid: [\n        '#ff',\n        'fff0a',\n        '#ff12FG',\n        '#######',\n        '',\n      ],\n    });\n    test({\n      validator: 'isHexColor',\n      args: [{ require_hashtag: false }],\n      valid: [\n        '#ff0000ff',\n        '#ff0034',\n        '#CCCCCC',\n        '0f38',\n        'fff',\n        '#f00',\n      ],\n      invalid: [\n        '#ff',\n        'fff0a',\n        '#ff12FG',\n        '#######',\n        '',\n      ],\n    });\n    test({\n      validator: 'isHexColor',\n      args: [{ require_hashtag: true }],\n      valid: [\n        '#ff0000ff',\n        '#ff0034',\n        '#CCCCCC',\n        '#0f38',\n        '#fff',\n        '#f00',\n      ],\n      invalid: [\n        '#ff',\n        'fff0a',\n        '#ff12FG',\n        '0f38',\n        'fff',\n        '#######',\n        '',\n      ],\n    });\n    test({\n      validator: 'isHexColor',\n      args: [null],\n      valid: ['#fff', '#000000', '123'],\n      invalid: ['not-a-color'],\n    });\n    test({\n      validator: 'isHexColor',\n      args: [123],\n      valid: ['#fff', '#000000', '123', 'abc'],\n      invalid: ['gray', 'not-a-color'],\n    });\n    const validColors = ['#ff0034', '#CCCCCC'].filter(validator.isHexColor);\n    assert.strictEqual(validColors.length, 2);\n  });\n\n  it('should validate HSL color strings', () => {\n    test({\n      validator: 'isHSL',\n      valid: [\n        'hsl(360,0000000000100%,000000100%)',\n        'hsl(000010, 00000000001%, 00000040%)',\n        'HSL(00000,0000000000100%,000000100%)',\n        'hsL(0, 0%, 0%)',\n        'hSl(  360  , 100%  , 100%   )',\n        'Hsl(  00150  , 000099%  , 01%   )',\n        'hsl(01080, 03%, 4%)',\n        'hsl(-540, 03%, 4%)',\n        'hsla(+540, 03%, 4%)',\n        'hsla(+540, 03%, 4%, 500)',\n        'hsl(+540deg, 03%, 4%, 500)',\n        'hsl(+540gRaD, 03%, 4%, 500)',\n        'hsl(+540.01e-98rad, 03%, 4%, 500)',\n        'hsl(-540.5turn, 03%, 4%, 500)',\n        'hsl(+540, 03%, 4%, 500e-01)',\n        'hsl(+540, 03%, 4%, 500e+80)',\n        'hsl(4.71239rad, 60%, 70%)',\n        'hsl(270deg, 60%, 70%)',\n        'hsl(200, +.1%, 62%, 1)',\n        'hsl(270 60% 70%)',\n        'hsl(200, +.1e-9%, 62e10%, 1)',\n        'hsl(.75turn, 60%, 70%)',\n        // 'hsl(200grad+.1%62%/1)', //supposed to pass, but need to handle delimiters\n        'hsl(200grad +.1% 62% / 1)',\n        'hsl(270, 60%, 50%, .15)',\n        'hsl(270, 60%, 50%, 15%)',\n        'hsl(270 60% 50% / .15)',\n        'hsl(270 60% 50% / 15%)',\n      ],\n      invalid: [\n        'hsl (360,0000000000100%,000000100%)',\n        'hsl(0260, 100 %, 100%)',\n        'hsl(0160, 100%, 100%, 100 %)',\n        'hsl(-0160, 100%, 100a)',\n        'hsl(-0160, 100%, 100)',\n        'hsl(-0160 100%, 100%, )',\n        'hsl(270 deg, 60%, 70%)',\n        'hsl( deg, 60%, 70%)',\n        'hsl(, 60%, 70%)',\n        'hsl(3000deg, 70%)',\n      ],\n    });\n  });\n\n  it('should validate rgb color strings', () => {\n    test({\n      validator: 'isRgbColor',\n      valid: [\n        'rgb(0,0,0)',\n        'rgb(255,255,255)',\n        'rgba(0,0,0,0)',\n        'rgba(255,255,255,1)',\n        'rgba(255,255,255,.1)',\n        'rgba(255,255,255,0.1)',\n        'rgba(255,255,255,.12)',\n        'rgb(5%,5%,5%)',\n        'rgba(5%,5%,5%,.3)',\n        'rgba(5%,5%,5%,.32)',\n      ],\n      invalid: [\n        'rgb(0,0,0,)',\n        'rgb(0,0,)',\n        'rgb(0,0,256)',\n        'rgb()',\n        'rgba(0,0,0)',\n        'rgba(255,255,255,2)',\n        'rgba(255,255,255,.123)',\n        'rgba(255,255,256,0.1)',\n        'rgb(4,4,5%)',\n        'rgba(5%,5%,5%)',\n        'rgba(3,3,3%,.3)',\n        'rgba(5%,5%,5%,.321)',\n        'rgb(101%,101%,101%)',\n        'rgba(3%,3%,101%,0.3)',\n        'rgb(101%,101%,101%) additional invalid string part',\n        'rgba(3%,3%,101%,0.3) additional invalid string part',\n        'r         g    b(   0,         251,       222     )',\n        'r         g    ba(   0,         251,       222     )',\n        'rg ba(0, 251, 22, 0.5)',\n        'rgb( 255,255 ,255)',\n        'rgba(255, 255, 255, 0.5)',\n        'rgba(255, 255, 255, 0.5)',\n        'rgb(5%, 5%, 5%)',\n      ],\n    });\n\n    // test empty options object\n    test({\n      validator: 'isRgbColor',\n      args: [{}],\n      valid: [\n        'rgb(0,0,0)',\n        'rgb(255,255,255)',\n        'rgba(0,0,0,0)',\n        'rgba(255,255,255,1)',\n        'rgba(255,255,255,.1)',\n        'rgba(255,255,255,.12)',\n        'rgba(255,255,255,0.1)',\n        'rgb(5%,5%,5%)',\n        'rgba(5%,5%,5%,.3)',\n      ],\n      invalid: [\n        'rgb(0,0,0,)',\n        'rgb(0,0,)',\n        'rgb(0,0,256)',\n        'rgb()',\n        'rgba(0,0,0)',\n        'rgba(255,255,255,2)',\n        'rgba(255,255,256,0.1)',\n        'rgb(4,4,5%)',\n        'rgba(5%,5%,5%)',\n        'rgba(3,3,3%,.3)',\n        'rgb(101%,101%,101%)',\n        'rgba(3%,3%,101%,0.3)',\n        'r         g    b(   0,         251,       222     )',\n        'r         g    ba(   0,         251,       222     )',\n        'rg ba(0, 251, 22, 0.5)',\n        'rgb( 255,255 ,255)',\n        'rgba(255, 255, 255, 0.5)',\n        'rgba(255, 255, 255, 0.5)',\n        'rgb(5%, 5%, 5%)',\n      ],\n    });\n    // test where includePercentValues is given as false\n    test({\n      validator: 'isRgbColor',\n      args: [false],\n      valid: [\n        'rgb(5,5,5)',\n        'rgba(5,5,5,.3)',\n      ],\n      invalid: [\n        'rgb(4,4,5%)',\n        'rgba(5%,5%,5%)',\n        'r         g    b(   0,         251,       222     )',\n        'r         g    ba(   0,         251,       222     )',\n      ],\n    });\n\n    // test where includePercentValues is given as false as part of options object\n    test({\n      validator: 'isRgbColor',\n      args: [{ includePercentValues: false }],\n      valid: [\n        'rgb(5,5,5)',\n        'rgba(5,5,5,.3)',\n      ],\n      invalid: [\n        'rgb(4,4,5%)',\n        'rgba(5%,5%,5%)',\n        'r         g    b(   0,         251,       222     )',\n        'rgba(255, 255, 255 ,0.2)',\n        'r         g    ba(   0,         251,       222     )',\n      ],\n    });\n\n    // test where include percent is true explciitly\n    test({\n      validator: 'isRgbColor',\n      args: [true],\n      valid: [\n        'rgb(5,5,5)',\n        'rgba(5,5,5,.3)',\n        'rgb(0,0,0)',\n        'rgb(255,255,255)',\n        'rgba(0,0,0,0)',\n        'rgba(255,255,255,1)',\n        'rgba(255,255,255,.1)',\n        'rgba(255,255,255,.12)',\n        'rgba(255,255,255,0.1)',\n        'rgb(5%,5%,5%)',\n        'rgba(5%,5%,5%,.3)',\n        'rgb(5%,5%,5%)',\n        'rgba(255,255,255,0.5)',\n      ],\n      invalid: [\n        'rgba(255, 255, 255, 0.5)',\n        'rgb(5%, 5%, 5%)',\n        'rgb(4,4,5%)',\n        'rgba(5%,5%,5%)',\n        'r         g    b(   0,         251,       222     )',\n        'r         g    ba(   0,         251,       222     )',\n        'rgb(0,0,0,)',\n        'rgb(0,0,)',\n        'rgb(0,0,256)',\n        'rgb()',\n        'rgba(0,0,0)',\n        'rgba(255,255,255,2)',\n        'rgba(255,255,256,0.1)',\n        'rgb(4,4,5%)',\n        'rgba(5%,5%,5%)',\n        'rgba(3,3,3%,.3)',\n        'rgb(101%,101%,101%)',\n        'rgba(3%,3%,101%,0.3)',\n      ],\n    });\n\n    // test where percent value is false and allowSpaces is true as part of options object\n    test({\n      validator: 'isRgbColor',\n      args: [{ includePercentValues: false, allowSpaces: true }],\n      valid: [\n        'rgb(5,5,5)',\n        'rgba(5,5,5,.3)',\n        'rgba(255,255,255,0.2)',\n        'rgba(255, 255, 255 ,0.2)',\n      ],\n      invalid: [\n        'rgb(4,4,5%)',\n        'rgba(5%,5%,5%)',\n        'rgba(5% ,5%, 5%)',\n        'r         g    b(   0,         251,       222     )',\n        'r         g    ba(   0,         251,       222     )',\n        'rgb(0,0,)',\n        'rgb()',\n        'rgb(4,4,5%)',\n        'rgb(5%,5%,5%)',\n        'rgba(3,3,3%,.3)',\n        'rgb(101%, 101%, 101%)',\n        'rgba(3%,3%,101%,0.3)',\n      ],\n\n    });\n\n    // test where both are true as part of options object\n    test({\n      validator: 'isRgbColor',\n      args: [{ includePercentValues: true, allowSpaces: true }],\n      valid: [\n        'rgb(  5, 5, 5)',\n        'rgba(5, 5, 5, .3)',\n        'rgb(0, 0, 0)',\n        'rgb(255, 255, 255)',\n        'rgba(0, 0, 0, 0)',\n        'rgba(255, 255, 255, 1)',\n        'rgba(255, 255, 255, .1)',\n        'rgba(255, 255, 255, 0.1)',\n        'rgb(5% ,5% ,5%)',\n        'rgba(5%,5%,5%, .3)',\n      ],\n      invalid: [\n        'r         g    b(   0,         251,       222     )',\n        'rgb(4,4,5%)',\n        'rgb(101%,101%,101%)',\n\n      ],\n    });\n\n    // test where allowSpaces is false as part of options object\n    test({\n      validator: 'isRgbColor',\n      args: [{ includePercentValues: true, allowSpaces: false }],\n      valid: [\n        'rgb(5,5,5)',\n        'rgba(5,5,5,.3)',\n        'rgb(0,0,0)',\n        'rgb(255,255,255)',\n        'rgba(0,0,0,0)',\n        'rgba(255,255,255,1)',\n        'rgba(255,255,255,.1)',\n        'rgba(255,255,255,.12)',\n        'rgba(255,255,255,0.1)',\n        'rgb(5%,5%,5%)',\n        'rgba(5%,5%,5%,.3)',\n\n      ],\n      invalid: [\n        'rgb( 255,255 ,255)',\n        'rgba(255, 255, 255, 0.5)',\n        'rgb(5%, 5%, 5%)',\n        'rgba(255, 255, 255, 0.5)',\n        'rgb(4,4,5%)',\n        'rgba(5%,5%,5%)',\n        'r         g    b(   0,         251,       222     )',\n        'r         g    ba(   0,         251,       222     )',\n        'rgb(0,0,0,)',\n        'rgb(0,0,)',\n        'rgb(0,0,256)',\n        'rgb()',\n        'rgba(0,0,0)',\n        'rgba(255,255,255,2)',\n        'rgba(255,255,256,0.1)',\n        'rgb(4,4,5%)',\n        'rgba(5%,5%,5%)',\n        'rgba(3,3,3%,.3)',\n        'rgb(101%,101%,101%)',\n        'rgba(3%,3%,101%,0.3)',\n      ],\n    });\n  });\n\n  it('should validate ISRC code strings', () => {\n    test({\n      validator: 'isISRC',\n      valid: [\n        'USAT29900609',\n        'GBAYE6800011',\n        'USRC15705223',\n        'USCA29500702',\n      ],\n      invalid: [\n        'USAT2990060',\n        'SRC15705223',\n        'US-CA29500702',\n        'USARC15705223',\n      ],\n    });\n  });\n\n  it('should validate md5 strings', () => {\n    test({\n      validator: 'isMD5',\n      valid: [\n        'd94f3f016ae679c3008de268209132f2',\n        '751adbc511ccbe8edf23d486fa4581cd',\n        '88dae00e614d8f24cfd5a8b3f8002e93',\n        '0bf1c35032a71a14c2f719e5a14c1e96',\n      ],\n      invalid: [\n        'KYT0bf1c35032a71a14c2f719e5a14c1',\n        'q94375dj93458w34',\n        '39485729348',\n        '%&FHKJFvk',\n      ],\n    });\n  });\n\n  it('should validate hash strings', () => {\n    ['md5', 'md4', 'ripemd128', 'tiger128'].forEach((algorithm) => {\n      test({\n        validator: 'isHash',\n        args: [algorithm],\n        valid: [\n          'd94f3f016ae679c3008de268209132f2',\n          '751adbc511ccbe8edf23d486fa4581cd',\n          '88dae00e614d8f24cfd5a8b3f8002e93',\n          '0bf1c35032a71a14c2f719e5a14c1e96',\n          'd94f3F016Ae679C3008de268209132F2',\n          '88DAE00e614d8f24cfd5a8b3f8002E93',\n        ],\n        invalid: [\n          'q94375dj93458w34',\n          '39485729348',\n          '%&FHKJFvk',\n          'KYT0bf1c35032a71a14c2f719e5a1',\n        ],\n      });\n    });\n\n    ['crc32', 'crc32b'].forEach((algorithm) => {\n      test({\n        validator: 'isHash',\n        args: [algorithm],\n        valid: [\n          'd94f3f01',\n          '751adbc5',\n          '88dae00e',\n          '0bf1c350',\n          '88DAE00e',\n          '751aDBc5',\n        ],\n        invalid: [\n          'KYT0bf1c35032a71a14c2f719e5a14c1',\n          'q94375dj93458w34',\n          'q943',\n          '39485729348',\n          '%&FHKJFvk',\n        ],\n      });\n    });\n\n    ['sha1', 'tiger160', 'ripemd160'].forEach((algorithm) => {\n      test({\n        validator: 'isHash',\n        args: [algorithm],\n        valid: [\n          '3ca25ae354e192b26879f651a51d92aa8a34d8d3',\n          'aaf4c61ddcc5e8a2dabede0f3b482cd9aea9434d',\n          'beb8c3f30da46be179b8df5f5ecb5e4b10508230',\n          'efd5d3b190e893ed317f38da2420d63b7ae0d5ed',\n          'AAF4c61ddCC5e8a2dabede0f3b482cd9AEA9434D',\n          '3ca25AE354e192b26879f651A51d92aa8a34d8D3',\n        ],\n        invalid: [\n          'KYT0bf1c35032a71a14c2f719e5a14c1',\n          'KYT0bf1c35032a71a14c2f719e5a14c1dsjkjkjkjkkjk',\n          'q94375dj93458w34',\n          '39485729348',\n          '%&FHKJFvk',\n        ],\n      });\n    });\n\n    test({\n      validator: 'isHash',\n      args: ['sha256'],\n      valid: [\n        '2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824',\n        '1d996e033d612d9af2b44b70061ee0e868bfd14c2dd90b129e1edeb7953e7985',\n        '80f70bfeaed5886e33536bcfa8c05c60afef5a0e48f699a7912d5e399cdcc441',\n        '579282cfb65ca1f109b78536effaf621b853c9f7079664a3fbe2b519f435898c',\n        '2CF24dba5FB0a30e26E83b2AC5b9E29E1b161e5C1fa7425E73043362938b9824',\n        '80F70bFEAed5886e33536bcfa8c05c60aFEF5a0e48f699a7912d5e399cdCC441',\n      ],\n      invalid: [\n        'KYT0bf1c35032a71a14c2f719e5a14c1',\n        'KYT0bf1c35032a71a14c2f719e5a14c1dsjkjkjkjkkjk',\n        'q94375dj93458w34',\n        '39485729348',\n        '%&FHKJFvk',\n      ],\n    });\n    test({\n      validator: 'isHash',\n      args: ['sha384'],\n      valid: [\n        '3fed1f814d28dc5d63e313f8a601ecc4836d1662a19365cbdcf6870f6b56388850b58043f7ebf2418abb8f39c3a42e31',\n        'b330f4e575db6e73500bd3b805db1a84b5a034e5d21f0041d91eec85af1dfcb13e40bb1c4d36a72487e048ac6af74b58',\n        'bf547c3fc5841a377eb1519c2890344dbab15c40ae4150b4b34443d2212e5b04aa9d58865bf03d8ae27840fef430b891',\n        'fc09a3d11368386530f985dacddd026ae1e44e0e297c805c3429d50744e6237eb4417c20ffca8807b071823af13a3f65',\n        '3fed1f814d28dc5d63e313f8A601ecc4836d1662a19365CBDCf6870f6b56388850b58043f7ebf2418abb8f39c3a42e31',\n        'b330f4E575db6e73500bd3b805db1a84b5a034e5d21f0041d91EEC85af1dfcb13e40bb1c4d36a72487e048ac6af74b58',\n      ],\n      invalid: [\n        'KYT0bf1c35032a71a14c2f719e5a14c1',\n        'KYT0bf1c35032a71a14c2f719e5a14c1dsjkjkjkjkkjk',\n        'q94375dj93458w34',\n        '39485729348',\n        '%&FHKJFvk',\n      ],\n    });\n    test({\n      validator: 'isHash',\n      args: ['sha512'],\n      valid: [\n        '9b71d224bd62f3785d96d46ad3ea3d73319bfbc2890caadae2dff72519673ca72323c3d99ba5c11d7c7acc6e14b8c5da0c4663475c2e5c3adef46f73bcdec043',\n        '83c586381bf5ba94c8d9ba8b6b92beb0997d76c257708742a6c26d1b7cbb9269af92d527419d5b8475f2bb6686d2f92a6649b7f174c1d8306eb335e585ab5049',\n        '45bc5fa8cb45ee408c04b6269e9f1e1c17090c5ce26ffeeda2af097735b29953ce547e40ff3ad0d120e5361cc5f9cee35ea91ecd4077f3f589b4d439168f91b9',\n        '432ac3d29e4f18c7f604f7c3c96369a6c5c61fc09bf77880548239baffd61636d42ed374f41c261e424d20d98e320e812a6d52865be059745fdb2cb20acff0ab',\n        '9B71D224bd62f3785D96d46ad3ea3d73319bFBC2890CAAdae2dff72519673CA72323C3d99ba5c11d7c7ACC6e14b8c5DA0c4663475c2E5c3adef46f73bcDEC043',\n        '432AC3d29E4f18c7F604f7c3c96369A6C5c61fC09Bf77880548239baffd61636d42ed374f41c261e424d20d98e320e812a6d52865be059745fdb2cb20acff0ab',\n      ],\n      invalid: [\n        'KYT0bf1c35032a71a14c2f719e5a14c1',\n        'KYT0bf1c35032a71a14c2f719e5a14c1dsjkjkjkjkkjk',\n        'q94375dj93458w34',\n        '39485729348',\n        '%&FHKJFvk',\n      ],\n    });\n    test({\n      validator: 'isHash',\n      args: ['tiger192'],\n      valid: [\n        '6281a1f098c5e7290927ed09150d43ff3990a0fe1a48267c',\n        '56268f7bc269cf1bc83d3ce42e07a85632394737918f4760',\n        '46fc0125a148788a3ac1d649566fc04eb84a746f1a6e4fa7',\n        '7731ea1621ae99ea3197b94583d034fdbaa4dce31a67404a',\n        '6281A1f098c5e7290927ed09150d43ff3990a0fe1a48267C',\n        '46FC0125a148788a3AC1d649566fc04eb84A746f1a6E4fa7',\n      ],\n      invalid: [\n        'KYT0bf1c35032a71a14c2f719e5a14c1',\n        'KYT0bf1c35032a71a14c2f719e5a14c1dsjkjkjkjkkjk',\n        'q94375dj93458w34',\n        '39485729348',\n        '%&FHKJFvk',\n      ],\n    });\n  });\n  it('should validate JWT tokens', () => {\n    test({\n      validator: 'isJWT',\n      valid: [\n        'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJsb2dnZWRJbkFzIjoiYWRtaW4iLCJpYXQiOjE0MjI3Nzk2Mzh9.gzSraSYS8EXBxLN_oWnFSRgCzcmJmMjLiuyu5CSpyHI',\n        'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJsb3JlbSI6Imlwc3VtIn0.ymiJSsMJXR6tMSr8G9usjQ15_8hKPDv_CArLhxw28MI',\n        'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJkb2xvciI6InNpdCIsImFtZXQiOlsibG9yZW0iLCJpcHN1bSJdfQ.rRpe04zbWbbJjwM43VnHzAboDzszJtGrNsUxaqQ-GQ8',\n        'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqb2huIjp7ImFnZSI6MjUsImhlaWdodCI6MTg1fSwiamFrZSI6eyJhZ2UiOjMwLCJoZWlnaHQiOjI3MH19.YRLPARDmhGMC3BBk_OhtwwK21PIkVCqQe8ncIRPKo-E',\n      ],\n      invalid: [\n        'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9',\n        'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NSIsIm5hbWUiOiJKb2huIERvZSIsImlhdCI6MTUxNjIzOTAyMn0',\n        'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NSIsIm5hbWUiOiJKb2huIERvZSIsImlhdCI6MTYxNjY1Mzg3Mn0.eyJpc3MiOiJodHRwczovL2V4YW1wbGUuY29tIiwiaWF0IjoxNjE2NjUzODcyLCJleHAiOjE2MTY2NTM4ODJ9.a1jLRQkO5TV5y5ERcaPAiM9Xm2gBdRjKrrCpHkGr_8M',\n        '$Zs.ewu.su84',\n        'ks64$S/9.dy$§kz.3sd73b',\n      ],\n      error: [\n        [],\n        {},\n        null,\n        undefined,\n      ],\n    });\n  });\n\n  it('should validate null strings', () => {\n    test({\n      validator: 'isEmpty',\n      valid: [\n        '',\n      ],\n      invalid: [\n        ' ',\n        'foo',\n        '3',\n      ],\n    });\n    test({\n      validator: 'isEmpty',\n      args: [{ ignore_whitespace: false }],\n      valid: [\n        '',\n      ],\n      invalid: [\n        ' ',\n        'foo',\n        '3',\n      ],\n    });\n    test({\n      validator: 'isEmpty',\n      args: [{ ignore_whitespace: true }],\n      valid: [\n        '',\n        ' ',\n      ],\n      invalid: [\n        'foo',\n        '3',\n      ],\n    });\n  });\n\n  it('should validate strings against an expected value', () => {\n    test({\n      validator: 'equals', args: ['abc'], valid: ['abc'], invalid: ['Abc', '123'],\n    });\n  });\n\n  it('should validate strings contain another string', () => {\n    test({\n      validator: 'contains',\n      args: ['foo'],\n      valid: ['foo', 'foobar', 'bazfoo'],\n      invalid: ['bar', 'fobar'],\n    });\n\n    test({\n      validator: 'contains',\n      args: ['foo', {\n        ignoreCase: true,\n      }],\n      valid: ['Foo', 'FOObar', 'BAZfoo'],\n      invalid: ['bar', 'fobar', 'baxoof'],\n    });\n\n    test({\n      validator: 'contains',\n      args: ['foo', {\n        minOccurrences: 2,\n      }],\n      valid: ['foofoofoo', '12foo124foo', 'fofooofoooofoooo', 'foo1foo'],\n      invalid: ['foo', 'foobar', 'Fooofoo', 'foofo'],\n    });\n  });\n\n  it('should validate strings against a pattern', () => {\n    test({\n      validator: 'matches',\n      args: [/abc/],\n      valid: ['abc', 'abcdef', '123abc'],\n      invalid: ['acb', 'Abc'],\n    });\n    test({\n      validator: 'matches',\n      args: ['abc'],\n      valid: ['abc', 'abcdef', '123abc'],\n      invalid: ['acb', 'Abc'],\n    });\n    test({\n      validator: 'matches',\n      args: ['abc', 'i'],\n      valid: ['abc', 'abcdef', '123abc', 'AbC'],\n      invalid: ['acb'],\n    });\n  });\n\n\n  it('should validate isLocale codes', () => {\n    test({\n      validator: 'isLocale',\n      valid: [\n        'uz_Latn_UZ',\n        'en',\n        'gsw',\n        'en-US',\n        'es_ES',\n        'es-419',\n        'sw_KE',\n        'am_ET',\n        'zh-CHS',\n        'ca_ES_VALENCIA',\n        'en_US_POSIX',\n        'hak-CN',\n        'zh-Hant',\n        'zh-Hans',\n        'sr-Cyrl',\n        'sr-Latn',\n        'zh-cmn-Hans-CN',\n        'cmn-Hans-CN',\n        'zh-yue-HK',\n        'yue-HK',\n        'zh-Hans-CN',\n        'sr-Latn-RS',\n        'sl-rozaj',\n        'sl-rozaj-biske',\n        'sl-nedis',\n        'de-CH-1901',\n        'sl-IT-nedis',\n        'hy-Latn-IT-arevela',\n        'i-enochian',\n        'en-scotland-fonipa',\n        'sl-IT-rozaj-biske-1994',\n        'de-CH-x-phonebk',\n        'az-Arab-x-AZE-derbend',\n        'x-whatever',\n        'qaa-Qaaa-QM-x-southern',\n        'de-Qaaa',\n        'sr-Latn-QM',\n        'sr-Qaaa-RS',\n        'en-US-u-islamcal',\n        'zh-CN-a-myext-x-private',\n        'en-a-myext-b-another',\n      ],\n      invalid: [\n        'lo_POP',\n        '12',\n        '12_DD',\n        'de-419-DE',\n        'a-DE',\n      ],\n    });\n  });\n\n  it('should validate strings by byte length (deprecated api)', () => {\n    test({\n      validator: 'isByteLength',\n      args: [2],\n      valid: ['abc', 'de', 'abcd', 'ｇｍａｉｌ'],\n      invalid: ['', 'a'],\n    });\n    test({\n      validator: 'isByteLength',\n      args: [2, 3],\n      valid: ['abc', 'de', 'ｇ'],\n      invalid: ['', 'a', 'abcd', 'ｇｍ'],\n    });\n    test({\n      validator: 'isByteLength',\n      args: [0, 0],\n      valid: [''],\n      invalid: ['ｇ', 'a'],\n    });\n  });\n\n\n  it('should validate strings by byte length', () => {\n    test({\n      validator: 'isByteLength',\n      args: [{ min: 2 }],\n      valid: ['abc', 'de', 'abcd', 'ｇｍａｉｌ'],\n      invalid: ['', 'a'],\n    });\n    test({\n      validator: 'isByteLength',\n      args: [{ min: 2, max: 3 }],\n      valid: ['abc', 'de', 'ｇ'],\n      invalid: ['', 'a', 'abcd', 'ｇｍ'],\n    });\n    test({\n      validator: 'isByteLength',\n      args: [{ max: 3 }],\n      valid: ['abc', 'de', 'ｇ', 'a', ''],\n      invalid: ['abcd', 'ｇｍ'],\n    });\n    test({\n      validator: 'isByteLength',\n      args: [{ max: 0 }],\n      valid: [''],\n      invalid: ['ｇ', 'a'],\n    });\n  });\n\n  it('should validate ULIDs', () => {\n    test({\n      validator: 'isULID',\n      valid: [\n        '01HBGW8CWQ5Q6DTT7XP89VV4KT',\n        '01HBGW8CWR8MZQMBG6FA2QHMDD',\n        '01HBGW8CWS3MEEK12Y9G7SVW4V',\n        '01hbgw8cws1tq2njavy9amb0wx',\n        '01HBGW8cwS43H4jkQ0A4ZRJ7QV',\n      ],\n      invalid: [\n        '',\n        '01HBGW-CWS3MEEK1#Y9G7SVW4V',\n        '91HBGW8CWS3MEEK12Y9G7SVW4V',\n        '81HBGW8CWS3MEEK12Y9G7SVW4V',\n        '934859',\n        '01HBGW8CWS3MEEK12Y9G7SVW4VXXX',\n        '01UBGW8IWS3MOEK12Y9G7SVW4V',\n        '01HBGW8CuS43H4JKQ0A4ZRJ7QV',\n      ],\n    });\n  });\n\n  it('should validate UUIDs', () => {\n    test({\n      validator: 'isUUID',\n      valid: [\n        '9deb20fe-a6e0-355c-81ea-288b009e4f6d',\n        'A987FBC9-4BED-4078-8F07-9141BA07C9F3',\n        'A987FBC9-4BED-5078-AF07-9141BA07C9F3',\n        'A987FBC9-4BED-6078-AF07-9141BA07C9F3',\n        '018C544A-D384-7000-BB74-3B1738ABE43C',\n        'A987FBC9-4BED-8078-AF07-9141BA07C9F3',\n      ],\n      invalid: [\n        '',\n        'xxxA987FBC9-4BED-3078-CF07-9141BA07C9F3',\n        'A987FBC9-4BED-3078-CF07-9141BA07C9F3',\n        'A987FBC9-4BED-3078-CF07-9141BA07C9F3xxx',\n        'A987FBC94BED3078CF079141BA07C9F3',\n        '934859',\n        '987FBC9-4BED-3078-CF07A-9141BA07C9F3',\n        'AAAAAAAA-1111-1111-AAAG-111111111111',\n      ],\n    });\n    test({\n      validator: 'isUUID',\n      args: [undefined],\n      valid: [\n        '9deb20fe-a6e0-355c-81ea-288b009e4f6d',\n        'A117FBC9-4BED-5078-AF07-9141BA07C9F3',\n        '018C544A-D384-7000-BB74-3B1738ABE43C',\n      ],\n      invalid: [\n        '',\n        'A117FBC9-4BED-3078-CF07-9141BA07C9F3',\n        'xxxA987FBC9-4BED-3078-CF07-9141BA07C9F3',\n        'A987FBC94BED3078CF079141BA07C9F3',\n        'A11AAAAA-1111-1111-AAAG-111111111111',\n      ],\n    });\n    test({\n      validator: 'isUUID',\n      args: [null],\n      valid: [\n        'A127FBC9-4BED-3078-AF07-9141BA07C9F3',\n        '018C544A-D384-7000-BB74-3B1738ABE43C',\n      ],\n      invalid: [\n        '',\n        'xxxA987FBC9-4BED-3078-CF07-9141BA07C9F3',\n        'A127FBC9-4BED-3078-CF07-9141BA07C9F3',\n        'A127FBC9-4BED-3078-CF07-9141BA07C9F3xxx',\n        '912859',\n        'A12AAAAA-1111-1111-AAAG-111111111111',\n      ],\n    });\n    test({\n      validator: 'isUUID',\n      args: [1],\n      valid: [\n        'E034B584-7D89-11E9-9669-1AECF481A97B',\n      ],\n      invalid: [\n        'xxxA987FBC9-4BED-3078-CF07-9141BA07C9F3',\n        'AAAAAAAA-1111-2222-AAAG',\n        'AAAAAAAA-1111-2222-AAAG-111111111111',\n        'A987FBC9-4BED-4078-8F07-9141BA07C9F3',\n        'A987FBC9-4BED-5078-AF07-9141BA07C9F3',\n        '018C544A-D384-7000-BB74-3B1738ABE43C',\n      ],\n    });\n    test({\n      validator: 'isUUID',\n      args: [2],\n      valid: [\n        'A987FBC9-4BED-2078-AF07-9141BA07C9F3',\n      ],\n      invalid: [\n        '',\n        'xxxA987FBC9-4BED-3078-CF07-9141BA07C9F3',\n        '11111',\n        'AAAAAAAA-1111-1111-AAAG-111111111111',\n        'A987FBC9-4BED-2078-CF07-9141BA07C9F3',\n        'A987FBC9-4BED-4078-8F07-9141BA07C9F3',\n        'A987FBC9-4BED-5078-AF07-9141BA07C9F3',\n        '018C544A-D384-7000-BB74-3B1738ABE43C',\n      ],\n    });\n    test({\n      validator: 'isUUID',\n      args: [3],\n      valid: [\n        '9deb20fe-a6e0-355c-81ea-288b009e4f6d',\n      ],\n      invalid: [\n        '',\n        'A987FBC9-4BED-3078-CF07-9141BA07C9F3',\n        'xxxA987FBC9-4BED-3078-CF07-9141BA07C9F3',\n        '934859',\n        'AAAAAAAA-1111-1111-AAAG-111111111111',\n        'A987FBC9-4BED-4078-8F07-9141BA07C9F3',\n        'A987FBC9-4BED-5078-AF07-9141BA07C9F3',\n        '018C544A-D384-7000-BB74-3B1738ABE43C',\n      ],\n    });\n    test({\n      validator: 'isUUID',\n      args: [4],\n      valid: [\n        '713ae7e3-cb32-45f9-adcb-7c4fa86b90c1',\n        '625e63f3-58f5-40b7-83a1-a72ad31acffb',\n        '57b73598-8764-4ad0-a76a-679bb6640eb1',\n        '9c858901-8a57-4791-81fe-4c455b099bc9',\n      ],\n      invalid: [\n        '',\n        'xxxA987FBC9-4BED-3078-CF07-9141BA07C9F3',\n        '934859',\n        'AAAAAAAA-1111-1111-AAAG-111111111111',\n        'A987FBC9-4BED-5078-AF07-9141BA07C9F3',\n        'A987FBC9-4BED-3078-CF07-9141BA07C9F3',\n        '018C544A-D384-7000-BB74-3B1738ABE43C',\n      ],\n    });\n    test({\n      validator: 'isUUID',\n      args: [5],\n      valid: [\n        '987FBC97-4BED-5078-AF07-9141BA07C9F3',\n        '987FBC97-4BED-5078-BF07-9141BA07C9F3',\n        '987FBC97-4BED-5078-8F07-9141BA07C9F3',\n        '987FBC97-4BED-5078-9F07-9141BA07C9F3',\n      ],\n      invalid: [\n        '',\n        'xxxA987FBC9-4BED-3078-CF07-9141BA07C9F3',\n        '934859',\n        'AAAAAAAA-1111-1111-AAAG-111111111111',\n        '9c858901-8a57-4791-81fe-4c455b099bc9',\n        'A987FBC9-4BED-3078-CF07-9141BA07C9F3',\n        '018C544A-D384-7000-BB74-3B1738ABE43C',\n      ],\n    });\n    test({\n      validator: 'isUUID',\n      args: [6],\n      valid: [\n        '1ef29908-cde1-69d0-be16-bfc8518a95f0',\n      ],\n      invalid: [\n        '987FBC97-4BED-1078-AF07-9141BA07C9F3',\n        '987FBC97-4BED-2078-AF07-9141BA07C9F3',\n        '987FBC97-4BED-3078-AF07-9141BA07C9F3',\n        '987FBC97-4BED-4078-AF07-9141BA07C9F3',\n        '987FBC97-4BED-5078-AF07-9141BA07C9F3',\n        '018C544A-D384-7000-BB74-3B1738ABE43C',\n        '987FBC97-4BED-8078-AF07-9141BA07C9F3',\n      ],\n    });\n    test({\n      validator: 'isUUID',\n      args: [7],\n      valid: [\n        '018C544A-D384-7000-BB74-3B1738ABE43C',\n      ],\n      invalid: [\n        '',\n        'xxxA987FBC9-4BED-3078-CF07-9141BA07C9F3',\n        '934859',\n        'AAAAAAAA-1111-1111-AAAG-111111111111',\n        'A987FBC9-4BED-5078-AF07-9141BA07C9F3',\n        'A987FBC9-4BED-3078-CF07-9141BA07C9F3',\n        'A987FBC9-4BED-6078-AF07-9141BA07C9F3',\n        'A987FBC9-4BED-8078-AF07-9141BA07C9F3',\n        '713ae7e3-cb32-45f9-adcb-7c4fa86b90c1',\n        '625e63f3-58f5-40b7-83a1-a72ad31acffb',\n        '57b73598-8764-4ad0-a76a-679bb6640eb1',\n        '9c858901-8a57-4791-81fe-4c455b099bc9',\n      ],\n    });\n    test({\n      validator: 'isUUID',\n      args: [8],\n      valid: [\n        '018C544A-D384-8000-BB74-3B1738ABE43C',\n      ],\n      invalid: [\n        '',\n        'xxxA987FBC9-4BED-3078-CF07-9141BA07C9F3',\n        '934859',\n        'AAAAAAAA-1111-1111-AAAG-111111111111',\n        'A987FBC9-4BED-5078-AF07-9141BA07C9F3',\n        'A987FBC9-4BED-3078-CF07-9141BA07C9F3',\n        'A987FBC9-4BED-6078-AF07-9141BA07C9F3',\n        'A987FBC9-4BED-7078-AF07-9141BA07C9F3',\n        '713ae7e3-cb32-45f9-adcb-7c4fa86b90c1',\n        '625e63f3-58f5-40b7-83a1-a72ad31acffb',\n        '57b73598-8764-4ad0-a76a-679bb6640eb1',\n        '9c858901-8a57-4791-81fe-4c455b099bc9',\n      ],\n    });\n    test({\n      validator: 'isUUID',\n      args: ['nil'],\n      valid: [\n        '00000000-0000-0000-0000-000000000000',\n      ],\n      invalid: [\n        '',\n        'xxxA987FBC9-4BED-3078-CF07-9141BA07C9F3',\n        'A987FBC9-4BED-3078-CF07-9141BA07C9F3',\n        'A987FBC9-4BED-3078-CF07-9141BA07C9F3xxx',\n        'A987FBC94BED3078CF079141BA07C9F3',\n        '934859',\n        '987FBC9-4BED-3078-CF07A-9141BA07C9F3',\n        'AAAAAAAA-1111-1111-AAAG-111111111111',\n        '9deb20fe-a6e0-355c-81ea-288b009e4f6d',\n        'A987FBC9-4BED-4078-8F07-9141BA07C9F3',\n        'A987FBC9-4BED-5078-AF07-9141BA07C9F3',\n        'A987FBC9-4BED-6078-AF07-9141BA07C9F3',\n        '018C544A-D384-7000-BB74-3B1738ABE43C',\n        'A987FBC9-4BED-8078-AF07-9141BA07C9F3',\n        'ffffffff-ffff-ffff-ffff-ffffffffffff',\n        'FFFFFFFF-FFFF-FFFF-FFFF-FFFFFFFFFFFF',\n      ],\n    });\n    test({\n      validator: 'isUUID',\n      args: ['max'],\n      valid: [\n        'ffffffff-ffff-ffff-ffff-ffffffffffff',\n        'FFFFFFFF-FFFF-FFFF-FFFF-FFFFFFFFFFFF',\n      ],\n      invalid: [\n        '',\n        'xxxA987FBC9-4BED-3078-CF07-9141BA07C9F3',\n        'A987FBC9-4BED-3078-CF07-9141BA07C9F3',\n        'A987FBC9-4BED-3078-CF07-9141BA07C9F3xxx',\n        'A987FBC94BED3078CF079141BA07C9F3',\n        '934859',\n        '987FBC9-4BED-3078-CF07A-9141BA07C9F3',\n        'AAAAAAAA-1111-1111-AAAG-111111111111',\n        '9deb20fe-a6e0-355c-81ea-288b009e4f6d',\n        'A987FBC9-4BED-4078-8F07-9141BA07C9F3',\n        'A987FBC9-4BED-5078-AF07-9141BA07C9F3',\n        'A987FBC9-4BED-6078-AF07-9141BA07C9F3',\n        '018C544A-D384-7000-BB74-3B1738ABE43C',\n        'A987FBC9-4BED-8078-AF07-9141BA07C9F3',\n        '00000000-0000-0000-0000-000000000000',\n      ],\n    });\n    test({\n      validator: 'isUUID',\n      args: ['loose'],\n      valid: [\n        '9deb20fe-a6e0-355c-81ea-288b009e4f6d',\n        'A987FBC9-4BED-3078-CF07-9141BA07C9F3',\n        'A987FBC9-4BED-4078-8F07-9141BA07C9F3',\n        'A987FBC9-4BED-5078-AF07-9141BA07C9F3',\n        'A987FBC9-4BED-6078-AF07-9141BA07C9F3',\n        '018C544A-D384-7000-BB74-3B1738ABE43C',\n        'A987FBC9-4BED-8078-AF07-9141BA07C9F3',\n        'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa',\n        'AAAAAAAA-AAAA-AAAA-AAAA-AAAAAAAAAAAA',\n        'eeeeeeee-eeee-eeee-eeee-eeeeeeeeeeee',\n        'EEEEEEEE-EEEE-EEEE-EEEE-EEEEEEEEEEEE',\n        '99999999-9999-9999-9999-999999999999',\n      ],\n      invalid: [\n        '',\n        'xxxA987FBC9-4BED-3078-CF07-9141BA07C9F3',\n        'A987FBC9-4BED-3078-CF07-9141BA07C9F3xxx',\n        'A987FBC94BED3078CF079141BA07C9F3',\n        '987FBC9-4BED-3078-CF07A-9141BA07C9F3',\n        '934859',\n        'AAAAAAAA-1111-1111-AAAG-111111111111',\n      ],\n    });\n    test({\n      validator: 'isUUID',\n      args: ['all'],\n      valid: [\n        '9deb20fe-a6e0-355c-81ea-288b009e4f6d',\n        'A987FBC9-4BED-4078-8F07-9141BA07C9F3',\n        'A987FBC9-4BED-5078-AF07-9141BA07C9F3',\n        'A987FBC9-4BED-6078-AF07-9141BA07C9F3',\n        '018C544A-D384-7000-BB74-3B1738ABE43C',\n        'A987FBC9-4BED-8078-AF07-9141BA07C9F3',\n        '00000000-0000-0000-0000-000000000000',\n        'ffffffff-ffff-ffff-ffff-ffffffffffff',\n        'FFFFFFFF-FFFF-FFFF-FFFF-FFFFFFFFFFFF',\n      ],\n      invalid: [\n        '',\n        'xxxA987FBC9-4BED-3078-CF07-9141BA07C9F3',\n        'A987FBC9-4BED-3078-CF07-9141BA07C9F3',\n        'A987FBC9-4BED-3078-CF07-9141BA07C9F3xxx',\n        'A987FBC94BED3078CF079141BA07C9F3',\n        '934859',\n        '987FBC9-4BED-3078-CF07A-9141BA07C9F3',\n        'AAAAAAAA-1111-1111-AAAG-111111111111',\n      ],\n    });\n    test({\n      validator: 'isUUID',\n      args: ['invalid'],\n      valid: [],\n      invalid: [\n        '',\n        'xxxA987FBC9-4BED-3078-CF07-9141BA07C9F3',\n        'A987FBC9-4BED-3078-CF07-9141BA07C9F3',\n        'A987FBC9-4BED-3078-CF07-9141BA07C9F3xxx',\n        'A987FBC94BED3078CF079141BA07C9F3',\n        '934859',\n        '987FBC9-4BED-3078-CF07A-9141BA07C9F3',\n        'AAAAAAAA-1111-1111-AAAG-111111111111',\n        '9deb20fe-a6e0-355c-81ea-288b009e4f6d',\n        'A987FBC9-4BED-4078-8F07-9141BA07C9F3',\n        'A987FBC9-4BED-5078-AF07-9141BA07C9F3',\n        'A987FBC9-4BED-6078-AF07-9141BA07C9F3',\n        '018C544A-D384-7000-BB74-3B1738ABE43C',\n        'A987FBC9-4BED-8078-AF07-9141BA07C9F3',\n        '00000000-0000-0000-0000-000000000000',\n        'ffffffff-ffff-ffff-ffff-ffffffffffff',\n        'FFFFFFFF-FFFF-FFFF-FFFF-FFFFFFFFFFFF',\n      ],\n    });\n  });\n\n  it('should validate a string that is in another string or array', () => {\n    test({\n      validator: 'isIn',\n      args: ['foobar'],\n      valid: ['foo', 'bar', 'foobar', ''],\n      invalid: ['foobarbaz', 'barfoo'],\n    });\n    test({\n      validator: 'isIn',\n      args: [['foo', 'bar']],\n      valid: ['foo', 'bar'],\n      invalid: ['foobar', 'barfoo', ''],\n    });\n    test({\n      validator: 'isIn',\n      args: [['1', '2', '3']],\n      valid: ['1', '2', '3'],\n      invalid: ['4', ''],\n    });\n    test({\n      validator: 'isIn',\n      args: [['1', '2', '3', { foo: 'bar' }, () => 5, { toString: 'test' }]],\n      valid: ['1', '2', '3', ''],\n      invalid: ['4'],\n    });\n    test({ validator: 'isIn', invalid: ['foo', ''] });\n  });\n\n  it('should validate a string that is in another object', () => {\n    test({\n      validator: 'isIn',\n      args: [{ foo: 1, bar: 2, foobar: 3 }],\n      valid: ['foo', 'bar', 'foobar'],\n      invalid: ['foobarbaz', 'barfoo', ''],\n    });\n    test({\n      validator: 'isIn',\n      args: [{ 1: 3, 2: 0, 3: 1 }],\n      valid: ['1', '2', '3'],\n      invalid: ['4', ''],\n    });\n  });\n\n  it('should validate ABA routing number', () => {\n    test({\n      validator: 'isAbaRouting',\n      valid: [\n        '322070381',\n        '011103093',\n        '263170175',\n        '124303065',\n      ],\n      invalid: [\n        '426317017',\n        '789456124',\n        '603558459',\n        'qwerty',\n        '12430306',\n        '382070381',\n      ],\n    });\n  });\n\n  it('should validate IBAN', () => {\n    test({\n      validator: 'isIBAN',\n      valid: [\n        'SC52BAHL01031234567890123456USD',\n        'LC14BOSL123456789012345678901234',\n        'MT31MALT01100000000000000000123',\n        'SV43ACAT00000000000000123123',\n        'EG800002000156789012345180002',\n        'BE71 0961 2345 6769',\n        'FR76 3000 6000 0112 3456 7890 189',\n        'DE91 1000 0000 0123 4567 89',\n        'GR96 0810 0010 0000 0123 4567 890',\n        'RO09 BCYP 0000 0012 3456 7890',\n        'SA44 2000 0001 2345 6789 1234',\n        'ES79 2100 0813 6101 2345 6789',\n        'CH56 0483 5012 3456 7800 9',\n        'GB98 MIDL 0700 9312 3456 78',\n        'IL170108000000012612345',\n        'IT60X0542811101000000123456',\n        'JO71CBJO0000000000001234567890',\n        'TR320010009999901234567890',\n        'BR1500000000000010932840814P2',\n        'LB92000700000000123123456123',\n        'IR200170000000339545727003',\n        'MZ97123412341234123412341',\n        'MA64011519000001205000534921',\n        'VG96VPVG0000012345678901',\n        'DZ580002100001113000000570',\n        'IE29AIBK93115212345678',\n        'PS92PALS000000000400123456702',\n        'PS92PALS00000000040012345670O',\n        'IR576406610070915600106898',\n      ],\n      invalid: [\n        'XX22YYY1234567890123',\n        'FR14 2004 1010 0505 0001 3',\n        'FR7630006000011234567890189@',\n        'FR7630006000011234567890189😅',\n        'FR763000600001123456!!🤨7890189@',\n        'VG46H07Y0223060094359858',\n        'IE95TE8270900834048660',\n        'PS072435171802145240705922007',\n      ],\n    });\n    test({\n      validator: 'isIBAN',\n      args: [{ whitelist: ['DK', 'GB'] }],\n      valid: [\n        'DK5000400440116243',\n        'GB29NWBK60161331926819',\n      ],\n      invalid: [\n        'BE71 0961 2345 6769',\n        'FR76 3000 6000 0112 3456 7890 189',\n        'DE91 1000 0000 0123 4567 89',\n        'GR96 0810 0010 0000 0123 4567 890',\n        'RO09 BCYP 0000 0012 3456 7890',\n        'SA44 2000 0001 2345 6789 1234',\n        'ES79 2100 0813 6101 2345 6789',\n        'XX22YYY1234567890123',\n        'FR14 2004 1010 0505 0001 3',\n        'FR7630006000011234567890189@',\n        'FR7630006000011234567890189😅',\n        'FR763000600001123456!!🤨7890189@',\n      ],\n    });\n    test({\n      validator: 'isIBAN',\n      args: [{ whitelist: ['XX', 'AA'] }],\n      invalid: [\n        'DK5000400440116243',\n        'GB29NWBK60161331926819',\n        'BE71 0961 2345 6769',\n        'FR76 3000 6000 0112 3456 7890 189',\n        'DE91 1000 0000 0123 4567 89',\n        'GR96 0810 0010 0000 0123 4567 890',\n        'RO09 BCYP 0000 0012 3456 7890',\n        'SA44 2000 0001 2345 6789 1234',\n        'ES79 2100 0813 6101 2345 6789',\n        'XX22YYY1234567890123',\n        'FR14 2004 1010 0505 0001 3',\n        'FR7630006000011234567890189@',\n        'FR7630006000011234567890189😅',\n        'FR763000600001123456!!🤨7890189@',\n      ],\n    });\n    test({\n      validator: 'isIBAN',\n      args: [{ blacklist: ['IT'] }],\n      valid: [\n        'SC52BAHL01031234567890123456USD',\n        'LC14BOSL123456789012345678901234',\n        'MT31MALT01100000000000000000123',\n        'SV43ACAT00000000000000123123',\n        'EG800002000156789012345180002',\n        'BE71 0961 2345 6769',\n        'FR76 3000 6000 0112 3456 7890 189',\n        'DE91 1000 0000 0123 4567 89',\n        'GR96 0810 0010 0000 0123 4567 890',\n        'RO09 BCYP 0000 0012 3456 7890',\n        'SA44 2000 0001 2345 6789 1234',\n        'ES79 2100 0813 6101 2345 6789',\n        'CH56 0483 5012 3456 7800 9',\n        'GB98 MIDL 0700 9312 3456 78',\n        'IL170108000000012612345',\n        'JO71CBJO0000000000001234567890',\n        'TR320010009999901234567890',\n        'BR1500000000000010932840814P2',\n        'LB92000700000000123123456123',\n        'IR200170000000339545727003',\n        'MZ97123412341234123412341',\n      ],\n      invalid: [\n        'XX22YYY1234567890123',\n        'FR14 2004 1010 0505 0001 3',\n        'FR7630006000011234567890189@',\n        'FR7630006000011234567890189😅',\n        'FR763000600001123456!!🤨7890189@',\n        'IT60X0542811101000000123456',\n      ],\n    });\n  });\n\n  it('should validate BIC codes', () => {\n    test({\n      validator: 'isBIC',\n      valid: [\n        'SBICKEN1345',\n        'SBICKEN1',\n        'SBICKENY',\n        'SBICKEN1YYP',\n        'SBICXKN1YYP',\n      ],\n      invalid: [\n        'SBIC23NXXX',\n        'S23CKENXXXX',\n        'SBICKENXX',\n        'SBICKENXX9',\n        'SBICKEN13458',\n        'SBICKEN',\n        'SBICXK',\n      ],\n    });\n  });\n\n  it('should validate that integer strings are divisible by a number', () => {\n    test({\n      validator: 'isDivisibleBy',\n      args: [2],\n      valid: ['2', '4', '100', '1000'],\n      invalid: [\n        '1',\n        '2.5',\n        '101',\n        'foo',\n        '',\n        '2020-01-06T14:31:00.135Z',\n      ],\n    });\n  });\n\n  it('should validate luhn numbers', () => {\n    test({\n      validator: 'isLuhnNumber',\n      valid: [\n        '0',\n        '5421',\n        '01234567897',\n        '0123456789012345678906',\n        '0123456789012345678901234567891',\n        '123456789012345678906',\n        '375556917985515',\n        '36050234196908',\n        '4716461583322103',\n        '4716-2210-5188-5662',\n        '4929 7226 5379 7141',\n      ],\n      invalid: [\n        '',\n        '1',\n        '5422',\n        'foo',\n        'prefix6234917882863855',\n        '623491788middle2863855',\n        '6234917882863855suffix',\n      ],\n    });\n  });\n\n  it('should validate credit cards', () => {\n    test({\n      validator: 'isCreditCard',\n      valid: [\n        '375556917985515',\n        '36050234196908',\n        '4716461583322103',\n        '4716-2210-5188-5662',\n        '4929 7226 5379 7141',\n        '5398228707871527',\n        '6283875070985593',\n        '6263892624162870',\n        '6234917882863855',\n        '6234698580215388',\n        '6226050967750613',\n        '6246281879460688',\n        '2222155765072228',\n        '2225855203075256',\n        '2720428011723762',\n        '2718760626256570',\n        '6765780016990268',\n        '4716989580001715211',\n        '8171999927660000',\n        '8171999900000000021',\n      ],\n      invalid: [\n        'foo',\n        'foo',\n        '5398228707871528',\n        '2718760626256571',\n        '2721465526338453',\n        '2220175103860763',\n        '375556917985515999999993',\n        '899999996234917882863855',\n        'prefix6234917882863855',\n        '623491788middle2863855',\n        '6234917882863855suffix',\n        '4716989580001715213',\n      ],\n    });\n  });\n\n\n  it('should validate credit cards without a proper provider', () => {\n    test({\n      validator: 'isCreditCard',\n      args: [{ provider: 'Plorf' }],\n      error: [\n        'foo',\n        // valid cc #\n        '375556917985515',\n        '4716-2210-5188-5662',\n        '375556917985515999999993',\n        '6234917882863855suffix',\n      ],\n    });\n  });\n\n\n  it('should validate AmEx provided credit cards', () => {\n    test({\n      validator: 'isCreditCard',\n      args: [{ provider: 'AmEx' }],\n      valid: [\n        '375556917985515',\n      ],\n      invalid: [\n        'foo',\n        '2222155765072228',\n        '2225855203075256',\n        '2720428011723762',\n        '2718760626256570',\n        '36050234196908',\n        '375556917985515999999993',\n        '4716461583322103',\n        '4716-2210-5188-5662',\n        '4716989580001715211',\n        '4929 7226 5379 7141',\n        '5398228707871527',\n        '6234917882863855suffix',\n        '6283875070985593',\n        '6263892624162870',\n        '6234917882863855',\n        '6234698580215388',\n        '6226050967750613',\n        '6246281879460688',\n        '6283875070985593',\n        '6765780016990268',\n        '8171999927660000',\n        '8171999900000000021',\n      ],\n    });\n  });\n\n\n  it('should validate Diners Club provided credit cards', () => {\n    test({\n      validator: 'isCreditCard',\n      args: [{ provider: 'DinersClub' }],\n      valid: [\n        '36050234196908',\n      ],\n      invalid: [\n        'foo',\n        '2222155765072228',\n        '2225855203075256',\n        '2720428011723762',\n        '2718760626256570',\n        '375556917985515',\n        '375556917985515999999993',\n        '4716461583322103',\n        '4716-2210-5188-5662',\n        '4716989580001715211',\n        '4929 7226 5379 7141',\n        '5398228707871527',\n        '6234917882863855suffix',\n        '6283875070985593',\n        '6263892624162870',\n        '6234917882863855',\n        '6234698580215388',\n        '6226050967750613',\n        '6246281879460688',\n        '6283875070985593',\n        '6765780016990268',\n        '8171999927660000',\n        '8171999900000000021',\n      ],\n    });\n  });\n\n  it('should validate Discover provided credit cards', () => {\n    test({\n      validator: 'isCreditCard',\n      args: [{ provider: 'Discover' }],\n      valid: [\n        '6011111111111117',\n        '6011000990139424',\n      ],\n      invalid: [\n        'foo',\n        '2222155765072228',\n        '2225855203075256',\n        '2720428011723762',\n        '2718760626256570',\n        '36050234196908',\n        '375556917985515',\n        '375556917985515999999993',\n        '4716461583322103',\n        '4716-2210-5188-5662',\n        '4716989580001715211',\n        '4929 7226 5379 7141',\n        '5398228707871527',\n        '6234917882863855suffix',\n        '6283875070985593',\n        '6263892624162870',\n        '6234917882863855',\n        '6234698580215388',\n        '6226050967750613',\n        '6246281879460688',\n        '6283875070985593',\n        '6765780016990268',\n        '8171999927660000',\n        '8171999900000000021',\n      ],\n    });\n  });\n\n  it('should validate JCB provided credit cards', () => {\n    test({\n      validator: 'isCreditCard',\n      args: [{ provider: 'JCB' }],\n      valid: [\n        '3530111333300000',\n        '3566002020360505',\n      ],\n      invalid: [\n        'foo',\n        '2222155765072228',\n        '2225855203075256',\n        '2720428011723762',\n        '2718760626256570',\n        '36050234196908',\n        '375556917985515',\n        '375556917985515999999993',\n        '4716461583322103',\n        '4716-2210-5188-5662',\n        '4716989580001715211',\n        '4929 7226 5379 7141',\n        '5398228707871527',\n        '6234917882863855suffix',\n        '6283875070985593',\n        '6263892624162870',\n        '6234917882863855',\n        '6234698580215388',\n        '6226050967750613',\n        '6246281879460688',\n        '6283875070985593',\n        '6765780016990268',\n        '8171999927660000',\n        '8171999900000000021',\n      ],\n    });\n  });\n\n\n  it('should validate Mastercard provided credit cards', () => {\n    test({\n      validator: 'isCreditCard',\n      args: [{ provider: 'Mastercard' }],\n      valid: [\n        '2222155765072228',\n        '2225855203075256',\n        '2718760626256570',\n        '2720428011723762',\n        '5398228707871527',\n      ],\n      invalid: [\n        'foo',\n        '36050234196908',\n        '375556917985515',\n        '375556917985515999999993',\n        '4716461583322103',\n        '4716-2210-5188-5662',\n        '4716989580001715211',\n        '4929 7226 5379 7141',\n        '6234917882863855suffix',\n        '6283875070985593',\n        '6263892624162870',\n        '6234917882863855',\n        '6234698580215388',\n        '6226050967750613',\n        '6246281879460688',\n        '6283875070985593',\n        '6765780016990268',\n        '8171999927660000',\n        '8171999900000000021',\n      ],\n    });\n  });\n\n\n  it('should validate Union Pay provided credit cards', () => {\n    test({\n      validator: 'isCreditCard',\n      args: [{ provider: 'UnionPay' }],\n      valid: [\n        '6226050967750613',\n        '6234917882863855',\n        '6234698580215388',\n        '6246281879460688',\n        '6263892624162870',\n        '6283875070985593',\n        '6765780016990268',\n        '8171999927660000',\n        '8171999900000000021',\n      ],\n      invalid: [\n        'foo',\n        '2222155765072228',\n        '2225855203075256',\n        '2720428011723762',\n        '2718760626256570',\n        '36050234196908',\n        '375556917985515',\n        '375556917985515999999993',\n        '4716461583322103',\n        '4716-2210-5188-5662',\n        '4716989580001715211',\n        '4929 7226 5379 7141',\n        '5398228707871527',\n        '6234917882863855suffix',\n      ],\n    });\n  });\n\n\n  it('should validate Visa provided credit cards', () => {\n    test({\n      validator: 'isCreditCard',\n      args: [{ provider: 'Visa' }],\n      valid: [\n        '4716-2210-5188-5662',\n        '4716461583322103',\n        '4716989580001715211',\n        '4929 7226 5379 7141',\n      ],\n      invalid: [\n        'foo',\n        '2222155765072228',\n        '2225855203075256',\n        '2720428011723762',\n        '2718760626256570',\n        '36050234196908',\n        '375556917985515',\n        '375556917985515999999993',\n        '5398228707871527',\n        '6234917882863855suffix',\n        '6283875070985593',\n        '6263892624162870',\n        '6234917882863855',\n        '6234698580215388',\n        '6226050967750613',\n        '6246281879460688',\n        '6283875070985593',\n        '6765780016990268',\n        '8171999927660000',\n        '8171999900000000021',\n      ],\n    });\n  });\n\n\n  it('should validate identity cards', () => {\n    const fixtures = [\n      {\n        locale: 'PK',\n        valid: [\n          '45504-4185771-3',\n          '39915-6182971-9',\n          '21143-6182971-2',\n          '34543-2323471-1',\n          '72345-2345678-7',\n          '63456-8765432-8',\n          '55672-1234567-5',\n          '21234-9876543-6',\n        ],\n        invalid: [\n          '08000-1234567-5',\n          '74321-87654321-1',\n          '51234-98765-2',\n          '00000-0000000-0',\n          '88888-88888888-0',\n          '99999-9999999-9',\n          '11111',\n        ],\n      },\n      {\n        locale: 'zh-HK',\n        valid: [\n          'OV290326[A]',\n          'Q803337[0]',\n          'Z0977986',\n          'W520128(7)',\n          'A494866[4]',\n          'A494866(4)',\n          'Z867821A',\n          'ag293013(9)',\n          'k348609(5)',\n        ],\n        invalid: [\n          'A1234567890',\n          '98765432',\n          'O962472(9)',\n          'M4578601',\n          'X731324[8]',\n          'C503134(5)',\n          'RH265886(3)',\n        ],\n      },\n      {\n        locale: 'LK',\n        valid: [\n          '722222222v',\n          '722222222V',\n          '993151225x',\n          '993151225X',\n          '188888388x',\n          '935632124V',\n          '199931512253',\n          '200023125632',\n        ],\n        invalid: [\n          '023125648V',\n          '023345621v',\n          '021354211X',\n          '055321231x',\n          '02135465462',\n          '199931512253X',\n        ],\n      },\n      {\n        locale: 'PL',\n        valid: [\n          '99012229019',\n          '09210215408',\n          '20313034701',\n          '86051575214',\n          '77334586883',\n          '54007481320',\n          '06566860643',\n          '77552478861',\n        ],\n        invalid: [\n          'aa',\n          '5',\n          '195',\n          '',\n          ' ',\n          '12345678901',\n          '99212229019',\n          '09210215402',\n          '20313534701',\n          '86241579214',\n        ],\n      },\n      {\n        locale: 'ES',\n        valid: [\n          '99999999R',\n          '12345678Z',\n          '01234567L',\n          '01234567l',\n          'X1234567l',\n          'x1234567l',\n          'X1234567L',\n          'Y1234567X',\n          'Z1234567R',\n        ],\n        invalid: [\n          '123456789',\n          '12345678A',\n          '12345 678Z',\n          '12345678-Z',\n          '1234*6789',\n          '1234*678Z',\n          '12345678!',\n          '1234567L',\n          'A1234567L',\n          'X1234567A',\n          'Y1234567B',\n          'Z1234567C',\n        ],\n      },\n      {\n        locale: 'FI',\n        valid: [\n          '131052-308T', // People born in 1900s\n          '131052A308T', // People born in 2000s\n          '131052+308T', // People born in 1800s\n          '131052-313Y',\n        ],\n        invalid: [\n          '131052308T',\n          '131052-308T ',\n          '131052-308A',\n        ],\n      },\n      {\n        locale: 'IN',\n        valid: [\n          '298448863364',\n          '2984 4886 3364',\n        ],\n        invalid: [\n          '99999999R',\n          '12345678Z',\n          '01234567L',\n          '01234567l',\n          'X1234567l',\n          'x1234567l',\n          'X1234567L',\n        ],\n      },\n      {\n        locale: 'IR',\n        valid: [\n          '0499370899',\n          '0790419904',\n          '0084575948',\n          '0963695398',\n          '0684159414',\n          '0067749828',\n          '0650451252',\n          '1583250689',\n          '4032152314',\n          '0076229645',\n          '4271467685',\n          '0200203241',\n        ],\n        invalid: [\n          '1260293040',\n          '0000000001',\n          '1999999999',\n          '9999999991',\n          'AAAAAAAAAA',\n          '0684159415',\n        ],\n      },\n      {\n        locale: 'IT',\n        valid: [\n          'CR43675TM',\n          'CA79382RA',\n        ],\n        invalid: [\n          'CA00000AA',\n          'CB2342TG',\n          'CS123456A',\n          'C1236EC',\n        ],\n      },\n      {\n        locale: 'NO',\n        valid: [\n          '09053426694',\n          '26028338723',\n          '08031470790',\n          '12051539514',\n          '02077448074',\n          '14035638319',\n          '13031379673',\n          '29126214926',\n        ],\n        invalid: [\n          '09053426699',\n          '00000000000',\n          '26028338724',\n          '92031470790',\n        ],\n      },\n      {\n        locale: 'TH',\n        valid: [\n          '1101230000001',\n          '1101230000060',\n        ],\n        invalid: [\n          'abc',\n          '1101230',\n          '11012300000011',\n          'aaaaaaaaaaaaa',\n          '110123abcd001',\n          '1101230000007',\n          '0101123450000',\n          '0101123450004',\n          '9101123450008',\n        ],\n      },\n      {\n        locale: 'he-IL',\n        valid: [\n          '219472156',\n          '219486610',\n          '219488962',\n          '219566726',\n          '219640216',\n          '219645041',\n          '334795465',\n          '335211686',\n          '335240479',\n          '335472171',\n          '336999842',\n          '337090443',\n        ],\n        invalid: [\n          '123456789',\n          '12345678A',\n          '12345 678Z',\n          '12345678-Z',\n          '1234*6789',\n          '1234*678Z',\n          '12345678!',\n          '1234567L',\n          'A1234567L',\n          'X1234567A',\n          'Y1234567B',\n          'Z1234567C',\n          '219772156',\n          '219487710',\n          '334705465',\n          '336000842',\n        ],\n      },\n      {\n        locale: 'ar-LY',\n        valid: [\n          '119803455876',\n          '120024679875',\n          '219624876201',\n          '220103480657',\n        ],\n        invalid: [\n          '987654320123',\n          '123-456-7890',\n          '012345678912',\n          '1234567890',\n          'AFJBHUYTREWR',\n          'C4V6B1X0M5T6',\n          '9876543210123',\n        ],\n      },\n      {\n        locale: 'ar-TN',\n        valid: [\n          '09958092',\n          '09151092',\n          '65126506',\n          '79378815',\n          '58994407',\n          '73089789',\n          '73260311',\n        ],\n        invalid: [\n          '123456789546',\n          '123456789',\n          '023456789',\n          '12345678A',\n          '12345',\n          '1234578A',\n          '123 578A',\n          '12345 678Z',\n          '12345678-Z',\n          '1234*6789',\n          '1234*678Z',\n          'GE9800as98',\n          'X231071922',\n          '1234*678Z',\n          '12345678!',\n        ],\n      },\n      {\n        locale: 'zh-CN',\n        valid: [\n          '235407195106112745',\n          '210203197503102721',\n          '520323197806058856',\n          '110101491001001',\n        ],\n        invalid: [\n          '160323197806058856',\n          '010203197503102721',\n          '520323297806058856',\n          '520323197802318856',\n          '235407195106112742',\n          '010101491001001',\n          '110101491041001',\n          '160101491001001',\n          '110101940231001',\n          'xx1234567',\n          '135407195106112742',\n          '123456789546',\n          '123456789',\n          '023456789',\n          '12345678A',\n          '12345',\n          '1234578A',\n          '123 578A',\n          '12345 678Z',\n          '12345678-Z',\n          '1234*6789',\n          '1234*678Z',\n          'GE9800as98',\n          'X231071922',\n          '1234*678Z',\n          '12345678!',\n          '235407207006112742',\n        ],\n      },\n      {\n        locale: 'zh-TW',\n        valid: [\n          'B176944193',\n          'K101189797',\n          'F112866121',\n          'A219758834',\n          'A244144802',\n          'A146047171',\n          'Q170219004',\n          'Z277018381',\n          'X231071923',\n        ],\n        invalid: [\n          '123456789',\n          'A185034995',\n          'X431071923',\n          'GE9800as98',\n          'X231071922',\n          '1234*678Z',\n          '12345678!',\n          '1234567L',\n          'A1234567L',\n          'X1234567A',\n          'Y1234567B',\n          'Z1234567C',\n          '219772156',\n          '219487710',\n          '334705465',\n          '336000842',\n        ],\n      },\n    ];\n\n    let allValid = [];\n\n    // Test fixtures\n    fixtures.forEach((fixture) => {\n      if (fixture.valid) allValid = allValid.concat(fixture.valid);\n      test({\n        validator: 'isIdentityCard',\n        valid: fixture.valid,\n        invalid: fixture.invalid,\n        args: [fixture.locale],\n      });\n    });\n\n    // Test generics\n    test({\n      validator: 'isIdentityCard',\n      valid: [\n        ...allValid,\n      ],\n      invalid: [\n        'foo',\n      ],\n      args: ['any'],\n    });\n  });\n\n  it('should error on invalid locale', () => {\n    test({\n      validator: 'isIdentityCard',\n      args: ['is-NOT'],\n      error: [\n        '99999999R',\n        '12345678Z',\n      ],\n    });\n  });\n\n  it('should validate ISINs', () => {\n    test({\n      validator: 'isISIN',\n      valid: [\n        'AU0000XVGZA3',\n        'DE000BAY0017',\n        'BE0003796134',\n        'SG1G55870362',\n        'GB0001411924',\n        'DE000WCH8881',\n        'PLLWBGD00016',\n        'US0378331005',\n      ],\n      invalid: [\n        'DE000BAY0018',\n        'PLLWBGD00019',\n        'foo',\n        '5398228707871528',\n      ],\n    });\n  });\n\n  it('should validate EANs', () => {\n    test({\n      validator: 'isEAN',\n      valid: [\n        '9421023610112',\n        '1234567890128',\n        '4012345678901',\n        '9771234567003',\n        '9783161484100',\n        '73513537',\n        '00012345600012',\n        '10012345678902',\n        '20012345678909',\n      ],\n      invalid: [\n        '5901234123451',\n        '079777681629',\n        '0705632085948',\n      ],\n    });\n  });\n\n  it('should validate ISSNs', () => {\n    test({\n      validator: 'isISSN',\n      valid: [\n        '0378-5955',\n        '0000-0000',\n        '2434-561X',\n        '2434-561x',\n        '01896016',\n        '20905076',\n      ],\n      invalid: [\n        '0378-5954',\n        '0000-0001',\n        '0378-123',\n        '037-1234',\n        '0',\n        '2434-561c',\n        '1684-5370',\n        '19960791',\n        '',\n      ],\n    });\n    test({\n      validator: 'isISSN',\n      args: [{ case_sensitive: true }],\n      valid: [\n        '2434-561X',\n        '2434561X',\n        '0378-5955',\n        '03785955',\n      ],\n      invalid: [\n        '2434-561x',\n        '2434561x',\n      ],\n    });\n    test({\n      validator: 'isISSN',\n      args: [{ require_hyphen: true }],\n      valid: [\n        '2434-561X',\n        '2434-561x',\n        '0378-5955',\n      ],\n      invalid: [\n        '2434561X',\n        '2434561x',\n        '03785955',\n      ],\n    });\n    test({\n      validator: 'isISSN',\n      args: [{ case_sensitive: true, require_hyphen: true }],\n      valid: [\n        '2434-561X',\n        '0378-5955',\n      ],\n      invalid: [\n        '2434-561x',\n        '2434561X',\n        '2434561x',\n        '03785955',\n      ],\n    });\n  });\n\n  it('should validate JSON', () => {\n    test({\n      validator: 'isJSON',\n      valid: [\n        '{ \"key\": \"value\" }',\n        '{}',\n      ],\n      invalid: [\n        '{ key: \"value\" }',\n        '{ \\'key\\': \\'value\\' }',\n        'null',\n        '1234',\n        '\"nope\"',\n      ],\n    });\n  });\n\n  it('should validate JSON with primitives', () => {\n    test({\n      validator: 'isJSON',\n      args: [{ allow_primitives: true }],\n      valid: [\n        '{ \"key\": \"value\" }',\n        '{}',\n        'null',\n        'false',\n        'true',\n      ],\n      invalid: [\n        '{ key: \"value\" }',\n        '{ \\'key\\': \\'value\\' }',\n        '{ \"key\": value }',\n        '1234',\n        '\"nope\"',\n      ],\n    });\n  });\n\n  it('should validate multibyte strings', () => {\n    test({\n      validator: 'isMultibyte',\n      valid: [\n        'ひらがな・カタカナ、．漢字',\n        'あいうえお foobar',\n        'test＠example.com',\n        '1234abcDEｘｙｚ',\n        'ｶﾀｶﾅ',\n        '中文',\n      ],\n      invalid: [\n        'abc',\n        'abc123',\n        '<>@\" *.',\n      ],\n    });\n  });\n\n  it('should validate ascii strings', () => {\n    test({\n      validator: 'isAscii',\n      valid: [\n        'foobar',\n        '0987654321',\n        'test@example.com',\n        '1234abcDEF',\n      ],\n      invalid: [\n        'ｆｏｏbar',\n        'ｘｙｚ０９８',\n        '１２３456',\n        'ｶﾀｶﾅ',\n      ],\n    });\n  });\n\n  it('should validate full-width strings', () => {\n    test({\n      validator: 'isFullWidth',\n      valid: [\n        'ひらがな・カタカナ、．漢字',\n        '３ー０　ａ＠ｃｏｍ',\n        'Ｆｶﾀｶﾅﾞﾬ',\n        'Good＝Parts',\n      ],\n      invalid: [\n        'abc',\n        'abc123',\n        '!\"#$%&()<>/+=-_? ~^|.,@`{}[]',\n      ],\n    });\n  });\n\n  it('should validate half-width strings', () => {\n    test({\n      validator: 'isHalfWidth',\n      valid: [\n        '!\"#$%&()<>/+=-_? ~^|.,@`{}[]',\n        'l-btn_02--active',\n        'abc123い',\n        'ｶﾀｶﾅﾞﾬ￩',\n      ],\n      invalid: [\n        'あいうえお',\n        '００１１',\n      ],\n    });\n  });\n\n  it('should validate variable-width strings', () => {\n    test({\n      validator: 'isVariableWidth',\n      valid: [\n        'ひらがなカタカナ漢字ABCDE',\n        '３ー０123',\n        'Ｆｶﾀｶﾅﾞﾬ',\n        'Good＝Parts',\n      ],\n      invalid: [\n        'abc',\n        'abc123',\n        '!\"#$%&()<>/+=-_? ~^|.,@`{}[]',\n        'ひらがな・カタカナ、．漢字',\n        '１２３４５６',\n        'ｶﾀｶﾅﾞﾬ',\n      ],\n    });\n  });\n\n  it('should validate surrogate pair strings', () => {\n    test({\n      validator: 'isSurrogatePair',\n      valid: [\n        '𠮷野𠮷',\n        '𩸽',\n        'ABC千𥧄1-2-3',\n      ],\n      invalid: [\n        '吉野竈',\n        '鮪',\n        'ABC1-2-3',\n      ],\n    });\n  });\n\n  it('should validate Semantic Versioning Specification (SemVer) strings', () => {\n    test({\n      validator: 'isSemVer',\n      valid: [\n        '0.0.4',\n        '1.2.3',\n        '10.20.30',\n        '1.1.2-prerelease+meta',\n        '1.1.2+meta',\n        '1.1.2+meta-valid',\n        '1.0.0-alpha',\n        '1.0.0-beta',\n        '1.0.0-alpha.beta',\n        '1.0.0-alpha.beta.1',\n        '1.0.0-alpha.1',\n        '1.0.0-alpha0.valid',\n        '1.0.0-alpha.0valid',\n        '1.0.0-alpha-a.b-c-somethinglong+build.1-aef.1-its-okay',\n        '1.0.0-rc.1+build.1',\n        '2.0.0-rc.1+build.123',\n        '1.2.3-beta',\n        '10.2.3-DEV-SNAPSHOT',\n        '1.2.3-SNAPSHOT-123',\n        '1.0.0',\n        '2.0.0',\n        '1.1.7',\n        '2.0.0+build.1848',\n        '2.0.1-alpha.1227',\n        '1.0.0-alpha+beta',\n        '1.2.3----RC-SNAPSHOT.12.9.1--.12+788',\n        '1.2.3----R-S.12.9.1--.12+meta',\n        '1.2.3----RC-SNAPSHOT.12.9.1--.12',\n        '1.0.0+0.build.1-rc.10000aaa-kk-0.1',\n        '99999999999999999999999.999999999999999999.99999999999999999',\n        '1.0.0-0A.is.legal',\n      ],\n      invalid: [\n        '-invalid+invalid',\n        '-invalid.01',\n        'alpha',\n        'alpha.beta',\n        'alpha.beta.1',\n        'alpha.1',\n        'alpha+beta',\n        'alpha_beta',\n        'alpha.',\n        'alpha..',\n        'beta',\n        '1.0.0-alpha_beta',\n        '-alpha.',\n        '1.0.0-alpha..',\n        '1.0.0-alpha..1',\n        '1.0.0-alpha...1',\n        '1.0.0-alpha....1',\n        '1.0.0-alpha.....1',\n        '1.0.0-alpha......1',\n        '1.0.0-alpha.......1',\n        '01.1.1',\n        '1.01.1',\n        '1.1.01',\n        '1.2',\n        '1.2.3.DEV',\n        '1.2-SNAPSHOT',\n        '1.2.31.2.3----RC-SNAPSHOT.12.09.1--..12+788',\n        '1.2-RC-SNAPSHOT',\n        '-1.0.3-gamma+b7718',\n        '+justmeta',\n        '9.8.7+meta+meta',\n        '9.8.7-whatever+meta+meta',\n        '99999999999999999999999.999999999999999999.99999999999999999-',\n        '---RC-SNAPSHOT.12.09.1--------------------------------..12',\n      ],\n    });\n  });\n\n  it('should validate base32 strings', () => {\n    test({\n      validator: 'isBase32',\n      valid: [\n        'ZG======',\n        'JBSQ====',\n        'JBSWY===',\n        'JBSWY3A=',\n        'JBSWY3DP',\n        'JBSWY3DPEA======',\n        'K5SWYY3PNVSSA5DPEBXG6ZA=',\n        'K5SWYY3PNVSSA5DPEBXG6===',\n      ],\n      invalid: [\n        '12345',\n        '',\n        'JBSWY3DPtesting123',\n        'ZG=====',\n        'Z======',\n        'Zm=8JBSWY3DP',\n        '=m9vYg==',\n        'Zm9vYm/y====',\n      ],\n    });\n  });\n\n  it('should validate base32 strings with crockford alternative', () => {\n    test({\n      validator: 'isBase32',\n      args: [{ crockford: true }],\n      valid: [\n        '91JPRV3F41BPYWKCCGGG',\n        '60',\n        '64',\n        'B5QQA833C5Q20S3F41MQ8',\n      ],\n      invalid: [\n        '91JPRV3F41BUPYWKCCGGG',\n        'B5QQA833C5Q20S3F41MQ8L',\n        '60I',\n        'B5QQA833OULIC5Q20S3F41MQ8',\n      ],\n    });\n  });\n\n  it('should validate base58 strings', () => {\n    test({\n      validator: 'isBase58',\n      valid: [\n        'BukQL',\n        '3KMUV89zab',\n        '91GHkLMNtyo98',\n        'YyjKm3H',\n        'Mkhss145TRFg',\n        '7678765677',\n        'abcodpq',\n        'AAVHJKLPY',\n      ],\n      invalid: [\n        '0OPLJH',\n        'IMKLP23',\n        'KLMOmk986',\n        'LL1l1985hG',\n        '*MP9K',\n        'Zm=8JBSWY3DP',\n        ')()(=9292929MKL',\n      ],\n    });\n  });\n\n\n  it('should validate hex-encoded MongoDB ObjectId', () => {\n    test({\n      validator: 'isMongoId',\n      valid: [\n        '507f1f77bcf86cd799439011',\n      ],\n      invalid: [\n        '507f1f77bcf86cd7994390',\n        '507f1f77bcf86cd79943901z',\n        '',\n        '507f1f77bcf86cd799439011 ',\n      ],\n    });\n  });\n\n  it('should define the module using an AMD-compatible loader', () => {\n    let window = {\n      validator: null,\n      define(module) {\n        window.validator = module();\n      },\n    };\n    window.define.amd = true;\n\n    let sandbox = vm.createContext(window);\n    vm.runInContext(validator_js, sandbox);\n    assert.strictEqual(window.validator.trim('  foobar '), 'foobar');\n  });\n\n  it('should bind validator to the window if no module loaders are available', () => {\n    let window = {};\n    let sandbox = vm.createContext(window);\n    vm.runInContext(validator_js, sandbox);\n    assert.strictEqual(window.validator.trim('  foobar '), 'foobar');\n  });\n\n  it('should validate mobile phone number', () => {\n    let fixtures = [\n      {\n        locale: 'am-AM',\n        valid: [\n          '+37433123456',\n          '+37441123456',\n          '+37443123456',\n          '+37444123456',\n          '+37455123456',\n          '+37477123456',\n          '+37488123456',\n          '+37491123456',\n          '+37493123456',\n          '+37494123456',\n          '+37495123456',\n          '+37496123456',\n          '+37498123456',\n          '+37499123456',\n          '055123456',\n          '37455123456',\n        ],\n        invalid: [\n          '12345',\n          '+37403498855',\n          '+37416498123',\n          '05614988556',\n          '',\n          '37456789000',\n          '37486789000',\n          '+37431312345',\n          '+37430312345',\n          '+37460123456',\n          '+37410324123',\n          '+37422298765',\n          '+37431276521',\n          '022698763',\n          '+37492123456',\n        ],\n      },\n      {\n        locale: 'ar-AE',\n        valid: [\n          '+971502674453',\n          '+971521247658',\n          '+971541255684',\n          '+971555454458',\n          '+971561498855',\n          '+971585215778',\n          '971585215778',\n          '0585215778',\n          '585215778',\n        ],\n        invalid: [\n          '12345',\n          '+971511498855',\n          '+9715614988556',\n          '+9745614988556',\n          '',\n          '+9639626626262',\n          '+963332210972',\n          '0114152198',\n          '962796477263',\n        ],\n      },\n      {\n        locale: 'ar-BH',\n        valid: [\n          '+97335078110',\n          '+97339534385',\n          '+97366331055',\n          '+97333146000',\n          '97335078110',\n          '35078110',\n          '66331055',\n        ],\n        invalid: [\n          '12345',\n          '+973350781101',\n          '+97379534385',\n          '+973035078110',\n          '',\n          '+9639626626262',\n          '+963332210972',\n          '0114152198',\n          '962796477263',\n          '035078110',\n          '16331055',\n          'hello',\n          '+9733507811a',\n        ],\n      },\n      {\n        locale: 'ar-EG',\n        valid: [\n          '+201004513789',\n          '+201111453489',\n          '+201221204610',\n          '+201144621154',\n          '+201200124304',\n          '+201011201564',\n          '+201124679001',\n          '+201064790156',\n          '+201274652177',\n          '+201280134679',\n          '+201090124576',\n          '+201583728900',\n          '201599495596',\n          '201090124576',\n          '01090124576',\n          '01538920744',\n          '1593075993',\n          '1090124576',\n        ],\n        invalid: [\n          '+221004513789',\n          '+201404513789',\n          '12345',\n          '',\n          '+9639626626262',\n          '+963332210972',\n          '0114152198',\n          '962796477263',\n        ],\n      },\n      {\n        locale: 'ar-JO',\n        valid: [\n          '0796477263',\n          '0777866254',\n          '0786725261',\n          '+962796477263',\n          '+962777866254',\n          '+962786725261',\n          '962796477263',\n          '962777866254',\n          '962786725261',\n        ],\n        invalid: [\n          '00962786725261',\n          '00962796477263',\n          '12345',\n          '',\n          '+9639626626262',\n          '+963332210972',\n          '0114152198',\n        ],\n      },\n      {\n        locale: 'ar-KW',\n        valid: [\n          '96550000000',\n          '96560000000',\n          '96590000000',\n          '96541000000',\n          '+96550000000',\n          '+96550000220',\n          '+96551111220',\n          '+96541000000',\n        ],\n        invalid: [\n          '+96570000220',\n          '00962786725261',\n          '00962796477263',\n          '12345',\n          '',\n          '+9639626626262',\n          '+963332210972',\n          '0114152198',\n          '+96540000000',\n        ],\n      },\n      {\n        locale: 'ar-LB',\n        valid: [\n          '+96171234568',\n          '+9613123456',\n          '3456123',\n          '3123456',\n          '81978468',\n          '77675798',\n        ],\n        invalid: [\n          '+961712345688888',\n          '00912220000',\n          '7767579888',\n          '+0921110000',\n          '+3123456888',\n          '021222200000',\n          '213333444444',\n          '',\n          '+212234',\n          '+21',\n          '02122333',\n        ],\n      },\n      {\n        locale: 'ar-LY',\n        valid: [\n          '912220000',\n          '0923330000',\n          '218945550000',\n          '+218958880000',\n          '212220000',\n          '0212220000',\n          '+218212220000',\n        ],\n        invalid: [\n          '9122220000',\n          '00912220000',\n          '09211110000',\n          '+0921110000',\n          '+2180921110000',\n          '021222200000',\n          '213333444444',\n          '',\n          '+212234',\n          '+21',\n          '02122333',\n        ],\n      },\n      {\n        locale: 'ar-MA',\n        valid: [\n          '0522714782',\n          '0690851123',\n          '0708186135',\n          '+212522714782',\n          '+212690851123',\n          '+212708186135',\n          '00212522714782',\n          '00212690851123',\n          '00212708186135',\n        ],\n        invalid: [\n          '522714782',\n          '690851123',\n          '708186135',\n          '212522714782',\n          '212690851123',\n          '212708186135',\n          '0212522714782',\n          '0212690851123',\n          '0212708186135',\n          '',\n          '12345',\n          '0922714782',\n          '+212190851123',\n          '00212408186135',\n        ],\n      },\n      {\n        locale: 'dz-BT',\n        valid: [\n          '+97517374354',\n          '+97517454971',\n          '77324646',\n          '016329712',\n          '97517265559',\n        ],\n        invalid: [\n          '',\n          '9898347255',\n          '+96326626262',\n          '963372',\n          '0114152198',\n        ],\n      },\n      {\n        locale: 'ar-OM',\n        valid: [\n          '+96891212121',\n          '+96871212121',\n          '0096899999999',\n          '93112211',\n          '99099009',\n        ],\n        invalid: [\n          '+96890212121',\n          '0096890999999',\n          '0090999999',\n          '+9689021212',\n          '',\n          '+212234',\n          '+21',\n          '02122333',\n        ],\n      },\n      {\n        locale: 'ar-PS',\n        valid: [\n          '+970563459876',\n          '970592334218',\n          '0566372345',\n          '0598273583',\n        ],\n        invalid: [\n          '+9759029487',\n          '97059123456789',\n          '598372348',\n          '97058aaaafjd',\n          '',\n          '05609123484',\n          '+97059',\n          '+970',\n          '97056',\n        ],\n      },\n      {\n        locale: 'ar-SY',\n        valid: [\n          '0944549710',\n          '+963944549710',\n          '956654379',\n          '0944549710',\n          '0962655597',\n        ],\n        invalid: [\n          '12345',\n          '',\n          '+9639626626262',\n          '+963332210972',\n          '0114152198',\n        ],\n      },\n      {\n        locale: 'ar-SA',\n        valid: [\n          '0556578654',\n          '+966556578654',\n          '966556578654',\n          '596578654',\n          '572655597',\n        ],\n        invalid: [\n          '12345',\n          '',\n          '+9665626626262',\n          '+96633221097',\n          '0114152198',\n        ],\n      },\n      {\n        locale: 'ar-SD',\n        valid: [\n          '0128652312',\n          '+249919425113',\n          '249123212345',\n          '0993212345',\n        ],\n        invalid: [\n          '12345',\n          '',\n          '+249972662622',\n          '+24946266262',\n          '+24933221097',\n          '0614152198',\n          '096554',\n        ],\n      },\n      {\n        locale: 'ar-TN',\n        valid: [\n          '23456789',\n          '+21623456789',\n          '21623456789',\n        ],\n        invalid: [\n          '12345',\n          '75200123',\n          '+216512345678',\n          '13520459',\n          '85479520',\n        ],\n      },\n      {\n        locale: 'bg-BG',\n        valid: [\n          '+359897123456',\n          '+359898888888',\n          '0897123123',\n        ],\n        invalid: [\n          '',\n          '0898123',\n          '+359212555666',\n          '18001234567',\n          '12125559999',\n        ],\n      },\n      {\n        locale: 'bn-BD',\n        valid: [\n          '+8801794626846',\n          '01399098893',\n          '8801671163269',\n          '01717112029',\n          '8801898765432',\n          '+8801312345678',\n          '01494676946',\n        ],\n        invalid: [\n          '',\n          '0174626346',\n          '017943563469',\n          '18001234567',\n          '0131234567',\n        ],\n      },\n      {\n        locale: 'bs-BA',\n        valid: [\n          '060123456',\n          '061123456',\n          '062123456',\n          '063123456',\n          '0641234567',\n          '065123456',\n          '066123456',\n          '+38760123456',\n          '+38761123456',\n          '+38762123456',\n          '+38763123456',\n          '+387641234567',\n          '+38765123456',\n          '+38766123456',\n          '0038760123456',\n          '0038761123456',\n          '0038762123456',\n          '0038763123456',\n          '00387641234567',\n          '0038765123456',\n          '0038766123456',\n        ],\n        invalid: [\n          '0601234567',\n          '0611234567',\n          '06212345',\n          '06312345',\n          '064123456',\n          '0651234567',\n          '06612345',\n          '+3866123456',\n          '+3856123456',\n          '00038760123456',\n          '038761123456',\n        ],\n      },\n      {\n        locale: 'cs-CZ',\n        valid: [\n          '+420 123 456 789',\n          '+420 123456789',\n          '+420123456789',\n          '123 456 789',\n          '123456789',\n        ],\n        invalid: [\n          '',\n          '+42012345678',\n          '+421 123 456 789',\n          '+420 023456789',\n          '+4201234567892',\n        ],\n      },\n      {\n        locale: 'sk-SK',\n        valid: [\n          '+421 123 456 789',\n          '+421 123456789',\n          '+421123456789',\n          '123 456 789',\n          '123456789',\n        ],\n        invalid: [\n          '',\n          '+42112345678',\n          '+422 123 456 789',\n          '+421 023456789',\n          '+4211234567892',\n        ],\n      },\n      {\n        locale: 'de-DE',\n        valid: [\n          '+4915123456789',\n          '015123456789',\n          '015123456789',\n          '015623456789',\n          '015623456789',\n          '01601234567',\n          '016012345678',\n          '01621234567',\n          '01631234567',\n          '01701234567',\n          '017612345678',\n        ],\n        invalid: [\n          '+4930405044550',\n          '34412345678',\n          '14412345678',\n          '16212345678',\n          '1761234567',\n          '16412345678',\n          '17012345678',\n          '+4912345678910',\n          '+49015123456789',\n          '015345678910',\n          '015412345678',\n        ],\n      },\n      {\n        locale: 'de-AT',\n        valid: [\n          '+436761234567',\n          '06761234567',\n          '00436123456789',\n          '+436123456789',\n          '01999',\n          '+4372876',\n          '06434908989562345',\n        ],\n        invalid: [\n          '167612345678',\n          '1234',\n          '064349089895623459',\n        ],\n      },\n      {\n        locale: 'hu-HU',\n        valid: [\n          '06301234567',\n          '+36201234567',\n          '06701234567',\n        ],\n        invalid: [\n          '1234',\n          '06211234567',\n          '+3620123456',\n        ],\n      },\n      {\n        locale: 'mz-MZ',\n        valid: [\n          '+258849229754',\n          '258849229754',\n          '849229754',\n          '829229754',\n          '839229754',\n          '869229754',\n          '859229754',\n          '869229754',\n          '879229754',\n          '+258829229754',\n          '+258839229754',\n          '+258869229754',\n          '+258859229754',\n          '+258869229754',\n          '+258879229754',\n          '258829229754',\n          '258839229754',\n          '258869229754',\n          '258859229754',\n          '258869229754',\n          '258879229754',\n        ],\n        invalid: [\n          '+248849229754',\n          '158849229754',\n          '249229754',\n          '819229754',\n          '899229754',\n          '889229754',\n          '89229754',\n          '8619229754',\n          '87922975411',\n          '257829229754',\n          '+255839229754',\n          '+2258869229754',\n          '+1258859229754',\n          '+2588692297541',\n          '+2588792519754',\n          '25882922975411',\n        ],\n      },\n      {\n        locale: 'pt-BR',\n        valid: [\n          '+55 12 996551215',\n          '+55 15 97661234',\n          '+55 (12) 996551215',\n          '+55 (15) 97661234',\n          '55 (17) 96332-2155',\n          '55 (17) 6332-2155',\n          '55 15 976612345',\n          '55 15 75661234',\n          '+5512984567890',\n          '+551283456789',\n          '5512984567890',\n          '551283456789',\n          '015994569878',\n          '01593456987',\n          '022995678947',\n          '02299567894',\n          '(22)99567894',\n          '(22)9956-7894',\n          '(22) 99567894',\n          '(22) 9956-7894',\n          '(22)999567894',\n          '(22)99956-7894',\n          '(22) 999567894',\n          '(22) 99956-7894',\n          '(11) 94123-4567',\n          '(11) 91431-4567',\n          '+55 (11) 91431-4567',\n          '+55 11 91431-4567',\n          '+551191431-4567',\n          '5511914314567',\n          '5511912345678',\n        ],\n        invalid: [\n          '0819876543',\n          '+55 15 7566123',\n          '+017 123456789',\n          '5501599623874',\n          '+55012962308',\n          '+55 015 1234-3214',\n          '+55 11 90431-4567',\n          '+55 (11) 90431-4567',\n          '+551190431-4567',\n          '5511904314567',\n          '5511902345678',\n          '(11) 90431-4567',\n        ],\n      },\n      {\n        locale: 'zh-CN',\n        valid: [\n          '13523333233',\n          '13838389438',\n          '14899230918',\n          '14999230918',\n          '15323456787',\n          '15052052020',\n          '16237108167',\n          '008616238234822',\n          '+8616238234822',\n          '16565600001',\n          '17269427292',\n          '17469427292',\n          '18199617480',\n          '19151751717',\n          '19651751717',\n          '+8613238234822',\n          '+8613487234567',\n          '+8617823492338',\n          '+8617823492338',\n          '+8616637108167',\n          '+8616637108167',\n          '+8616712341234',\n          '+8619912341234',\n          '+8619812341234',\n          '+8619712341234',\n          '+8619612341234',\n          '+8619512341234',\n          '+8619312341234',\n          '+8619212341234',\n          '+8619112341234',\n          '+8617269427292',\n          '008618812341234',\n          '008618812341234',\n          '008617269427292',\n          // Reserve number segments in the future.\n          '92138389438',\n          '+8692138389438',\n          '008692138389438',\n          '98199649964',\n          '+8698099649964',\n          '008698099649964',\n        ],\n        invalid: [\n          '12345',\n          '',\n          '12038389438',\n          '12838389438',\n          '013838389438',\n          '+86-13838389438',\n          '+08613811211114',\n          '+008613811211114',\n          '08613811211114',\n          '0086-13811211114',\n          '0086-138-1121-1114',\n          'Vml2YW11cyBmZXJtZtesting123',\n          '010-38238383',\n        ],\n      },\n      {\n        locale: 'zh-TW',\n        valid: [\n          '0987123456',\n          '+886987123456',\n          '886987123456',\n          '+886-987123456',\n          '886-987123456',\n        ],\n        invalid: [\n          '12345',\n          '',\n          'Vml2YW11cyBmZXJtZtesting123',\n          '0-987123456',\n        ],\n      },\n      {\n        locale: 'en-LS',\n        valid: [\n          '+26622123456',\n          '+26628123456',\n          '+26657123456',\n          '+26658123456',\n          '+26659123456',\n          '+26627123456',\n          '+26652123456',\n        ],\n        invalid: [\n          '+26612345678',\n          '',\n          '2664512-21',\n          '+2662212345678',\n          'someString',\n        ],\n      },\n      {\n        locale: 'en-BM',\n        valid: [\n          '+14417974653',\n          '14413986653',\n          '4415370973',\n          '+14415005489',\n        ],\n        invalid: [\n          '85763287',\n          '+14412020436',\n          '+14412236546',\n          '+14418245567',\n          '+14416546789',\n          '44087635627',\n          '+4418970973',\n          '',\n          '+1441897465',\n          '+1441897465 additional invalid string part',\n        ],\n      },\n      {\n        locale: 'en-BS',\n        valid: [\n          '+12421231234',\n          '2421231234',\n          '+1-2421231234',\n          '+1-242-123-1234',\n          '(242)-123-1234',\n          '+1 (242)-123-1234',\n          '242 123-1234',\n          '(242) 123 1234',\n        ],\n        invalid: [\n          '85763287',\n          '+1 242 12 12 12 12',\n          '+1424123123',\n          '+14418245567',\n          '+14416546789',\n          'not a number',\n          '',\n        ],\n      },\n      {\n        locale: 'en-ZA',\n        valid: [\n          '0821231234',\n          '+27821231234',\n          '27821231234',\n        ],\n        invalid: [\n          '082123',\n          '08212312345',\n          '21821231234',\n          '+21821231234',\n          '+0821231234',\n        ],\n      },\n      {\n        locale: 'en-AU',\n        valid: [\n          '61404111222',\n          '+61411222333',\n          '0417123456',\n        ],\n        invalid: [\n          '082123',\n          '08212312345',\n          '21821231234',\n          '+21821231234',\n          '+0821231234',\n          '04123456789',\n        ],\n      },\n      {\n        locale: 'es-BO',\n        valid: [\n          '+59175553635',\n          '+59162223685',\n          '+59179783890',\n          '+59160081890',\n          '79783890',\n          '60081890',\n        ],\n        invalid: [\n          '082123',\n          '08212312345',\n          '21821231234',\n          '+21821231234',\n          '+59199783890',\n        ],\n      },\n      {\n        locale: 'en-GG',\n        valid: [\n          '+441481123456',\n          '+441481789123',\n          '441481123456',\n          '441481789123',\n        ],\n        invalid: [\n          '999',\n          '+441481123456789',\n          '+447123456789',\n        ],\n      },\n      {\n        locale: 'en-GH',\n        valid: [\n          '0202345671',\n          '0502345671',\n          '0242345671',\n          '0542345671',\n          '0532345671',\n          '0272345671',\n          '0572345671',\n          '0262345671',\n          '0562345671',\n          '0232345671',\n          '0282345671',\n          '+233202345671',\n          '+233502345671',\n          '+233242345671',\n          '+233542345671',\n          '+233532345671',\n          '+233272345671',\n          '+233572345671',\n          '+233262345671',\n          '+233562345671',\n          '+233232345671',\n          '+233282345671',\n          '+233592349493',\n          '0550298219',\n        ],\n        invalid: [\n          '082123',\n          '232345671',\n          '0292345671',\n          '+233292345671',\n        ],\n      },\n      {\n        locale: 'en-GY',\n        valid: [\n          '+5926121234',\n          '06121234',\n          '06726381',\n          '+5926726381',\n        ],\n        invalid: [\n          '5926121234',\n          '6121234',\n          '+592 6121234',\n          '05926121234',\n          '+592-6121234',\n        ],\n      },\n      {\n        locale: 'en-HK',\n        valid: [\n          '91234567',\n          '9123-4567',\n          '61234567',\n          '51234567',\n          '+85291234567',\n          '+852-91234567',\n          '+852-9123-4567',\n          '+852 9123 4567',\n          '9123 4567',\n          '852-91234567',\n        ],\n        invalid: [\n          '999',\n          '+852-912345678',\n          '123456789',\n          '+852-1234-56789',\n        ],\n      },\n      {\n        locale: 'en-MO',\n        valid: [\n          '61234567',\n          '+85361234567',\n          '+853-61234567',\n          '+853-6123-4567',\n          '+853 6123 4567',\n          '6123 4567',\n          '853-61234567',\n        ],\n        invalid: [\n          '999',\n          '12345678',\n          '612345678',\n          '+853-12345678',\n          '+853-22345678',\n          '+853-82345678',\n          '+853-612345678',\n          '+853-1234-5678',\n          '+853 1234 5678',\n          '+853-6123-45678',\n        ],\n      },\n      {\n        locale: 'en-IE',\n        valid: [\n          '+353871234567',\n          '353831234567',\n          '353851234567',\n          '353861234567',\n          '353871234567',\n          '353881234567',\n          '353891234567',\n          '0871234567',\n          '0851234567',\n        ],\n        invalid: [\n          '999',\n          '+353341234567',\n          '+33589484858',\n          '353841234567',\n          '353811234567',\n        ],\n      },\n      {\n        locale: 'en-JM',\n        valid: [\n          '+8761021234',\n          '8761211234',\n          '8763511274',\n          '+8764511274',\n        ],\n        invalid: [\n          '999',\n          '+876102123422',\n          '+8861021234',\n          '8761021212213',\n          '876102123',\n        ],\n      },\n      {\n        locale: 'en-KE',\n        valid: [\n          '+254728590432',\n          '+254733875610',\n          '254728590234',\n          '0733346543',\n          '0700459022',\n          '0110934567',\n          '+254110456794',\n          '254198452389',\n        ],\n        invalid: [\n          '999',\n          '+25489032',\n          '123456789',\n          '+254800723845',\n        ],\n      },\n      {\n        locale: 'fr-CF',\n        valid: [\n          '+23670850000',\n          '+23675038756',\n          '+23677859002',\n          '+23672854202',\n          '+23621854052',\n          '+23622854072',\n          '72234650',\n          '70045902',\n          '77934567',\n          '21456794',\n          '22452389',\n        ],\n        invalid: [\n          '+23689032',\n          '123456789',\n          '+236723845987',\n          '022452389',\n          '+236772345678',\n          '+236700456794',\n\n        ],\n      },\n      {\n        locale: 'en-KI',\n        valid: [\n          '+68673140000',\n          '68673059999',\n          '+68663000000',\n          '68663019999',\n        ],\n        invalid: [\n          '+68653000000',\n          '68664019999',\n          '+68619019999',\n          '686123456789',\n          '+686733445',\n        ],\n      },\n      {\n        locale: 'en-MT',\n        valid: [\n          '+35699000000',\n          '+35679000000',\n          '99000000',\n        ],\n        invalid: [\n          '356',\n          '+35699000',\n          '+35610000000',\n        ],\n      },\n      {\n        locale: 'en-PH',\n        valid: [\n          '+639275149120',\n          '+639275142327',\n          '+639003002023',\n          '09275149116',\n          '09194877624',\n        ],\n        invalid: [\n          '12112-13-345',\n          '12345678901',\n          'sx23YW11cyBmZxxXJt123123',\n          '010-38238383',\n          '966684123123-2590',\n        ],\n      },\n      {\n        locale: 'en-UG',\n        valid: [\n          '+256728590432',\n          '+256733875610',\n          '256728590234',\n          '0773346543',\n          '0700459022',\n        ],\n        invalid: [\n          '999',\n          '+254728590432',\n          '+25489032',\n          '123456789',\n          '+254800723845',\n        ],\n      },\n      {\n        locale: 'en-RW',\n        valid: [\n          '+250728590432',\n          '+250733875610',\n          '250738590234',\n          '0753346543',\n          '0780459022',\n        ],\n        invalid: [\n          '999',\n          '+254728590432',\n          '+25089032',\n          '123456789',\n          '+250800723845',\n        ],\n      },\n      {\n        locale: 'en-TZ',\n        valid: [\n          '+255728590432',\n          '+255733875610',\n          '255628590234',\n          '0673346543',\n          '0600459022',\n        ],\n        invalid: [\n          '999',\n          '+254728590432',\n          '+25589032',\n          '123456789',\n          '+255800723845',\n        ],\n      },\n      {\n        locale: 'en-MW',\n        valid: [\n          '+265994563785',\n          '+265111785436',\n          '+265318596857',\n          '0320008744',\n          '01256258',\n          '0882541896',\n          '+265984563214',\n        ],\n        invalid: [\n          '58563',\n          '+2658256258',\n          '0896328741',\n          '0708574896',\n          '+26570857489635',\n        ],\n      },\n      {\n        locale: 'es-PE',\n        valid: [\n          '+51912232764',\n          '+51923464567',\n          '+51968267382',\n          '+51908792973',\n          '974980472',\n          '908792973',\n          '+51974980472',\n        ],\n        invalid: [\n          '999',\n          '+51812232764',\n          '+5181223276499',\n          '+25589032',\n          '123456789',\n        ],\n      },\n      {\n        locale: 'fr-FR',\n        valid: [\n          '0612457898',\n          '+33612457898',\n          '33612457898',\n          '0712457898',\n          '+33712457898',\n          '33712457898',\n        ],\n        invalid: [\n          '061245789',\n          '06124578980',\n          '0112457898',\n          '0212457898',\n          '0312457898',\n          '0412457898',\n          '0512457898',\n          '0812457898',\n          '0912457898',\n          '+34612457898',\n          '+336124578980',\n          '+3361245789',\n        ],\n      },\n      {\n        locale: 'fr-BF',\n        valid: [\n          '+22661245789',\n          '+22665903092',\n          '+22672457898',\n          '+22673572346',\n          '061245789',\n          '071245783',\n        ],\n        invalid: [\n          '0612457892',\n          '06124578980',\n          '0112457898',\n          '0212457898',\n          '0312457898',\n          '0412457898',\n          '0512457898',\n          '0812457898',\n          '0912457898',\n          '+22762457898',\n          '+226724578980',\n          '+22634523',\n        ],\n      },\n      {\n        locale: 'fr-BJ',\n        valid: [\n          '+22920215789',\n          '+22920293092',\n          '+22921307898',\n          '+22921736346',\n          '+22922416346',\n          '+22923836346',\n        ],\n        invalid: [\n          '0612457892',\n          '01122921737346',\n          '+22762457898',\n          '+226724578980',\n          '+22634523',\n        ],\n      },\n      {\n        locale: 'fr-CA',\n        valid: ['19876543210', '8005552222', '+15673628910'],\n        invalid: [\n          '564785',\n          '0123456789',\n          '1437439210',\n          '+10345672645',\n          '11435213543',\n        ],\n      },\n      {\n        locale: 'fr-CD',\n        valid: [\n          '+243818590432',\n          '+243893875610',\n          '243978590234',\n          '0813346543',\n          '0820459022',\n          '+243902590221',\n        ],\n        invalid: [\n          '243',\n          '+254818590432',\n          '+24389032',\n          '123456789',\n          '+243700723845',\n        ],\n      },\n      {\n        locale: 'fr-GF',\n        valid: [\n          '0612457898',\n          '+594612457898',\n          '594612457898',\n          '0712457898',\n          '+594712457898',\n          '594712457898',\n        ],\n        invalid: [\n          '061245789',\n          '06124578980',\n          '0112457898',\n          '0212457898',\n          '0312457898',\n          '0412457898',\n          '0512457898',\n          '0812457898',\n          '0912457898',\n          '+54612457898',\n          '+5946124578980',\n          '+59461245789',\n        ],\n      },\n      {\n        locale: 'fr-GP',\n        valid: [\n          '0612457898',\n          '+590612457898',\n          '590612457898',\n          '0712457898',\n          '+590712457898',\n          '590712457898',\n        ],\n        invalid: [\n          '061245789',\n          '06124578980',\n          '0112457898',\n          '0212457898',\n          '0312457898',\n          '0412457898',\n          '0512457898',\n          '0812457898',\n          '0912457898',\n          '+594612457898',\n          '+5906124578980',\n          '+59061245789',\n        ],\n      },\n      {\n        locale: 'fr-MQ',\n        valid: [\n          '0612457898',\n          '+596612457898',\n          '596612457898',\n          '0712457898',\n          '+596712457898',\n          '596712457898',\n        ],\n        invalid: [\n          '061245789',\n          '06124578980',\n          '0112457898',\n          '0212457898',\n          '0312457898',\n          '0412457898',\n          '0512457898',\n          '0812457898',\n          '0912457898',\n          '+594612457898',\n          '+5966124578980',\n          '+59661245789',\n        ],\n      },\n      {\n        locale: 'fr-RE',\n        valid: [\n          '0612457898',\n          '+262612457898',\n          '262612457898',\n          '0712457898',\n          '+262712457898',\n          '262712457898',\n        ],\n        invalid: [\n          '061245789',\n          '06124578980',\n          '0112457898',\n          '0212457898',\n          '0312457898',\n          '0412457898',\n          '0512457898',\n          '0812457898',\n          '0912457898',\n          '+264612457898',\n          '+2626124578980',\n          '+26261245789',\n        ],\n      },\n      {\n        locale: 'fr-PF',\n        valid: [\n          '87123456',\n          '88123456',\n          '89123456',\n          '+68987123456',\n          '+68988123456',\n          '+68989123456',\n          '68987123456',\n          '68988123456',\n          '68989123456',\n        ],\n        invalid: [\n          '7123456',\n          '86123456',\n          '87 12 34 56',\n          'definitely not a number',\n          '01+68988123456',\n          '6898912345',\n        ],\n      },\n      {\n        locale: 'fr-WF',\n        valid: [\n          '+681408500',\n          '+681499387',\n          '+681728590',\n          '+681808542',\n          '+681828540',\n          '+681832014',\n          '408500',\n          '499387',\n          '728590',\n          '808542',\n          '828540',\n          '832014',\n        ],\n        invalid: [\n          '+68189032',\n          '123456789',\n          '+681723845987',\n          '022452389',\n          '+681772345678',\n          '+681700456794',\n\n        ],\n      },\n      {\n        locale: 'ka-GE',\n        valid: [\n          '+995500011111',\n          '+995515352134',\n          '+995798526662',\n          '798526662',\n          '500011119',\n          '798526662',\n          '+995799766525',\n        ],\n        invalid: [\n          '+99550001111',\n          '+9957997665250',\n          '+9959997665251',\n          '+995780011111',\n          '20000000000',\n          '68129485729',\n          '6589394827',\n          '298RI89572',\n        ],\n      },\n      {\n        locale: 'el-GR',\n        valid: [\n          '+306944848966',\n          '306944848966',\n          '06904567890',\n          '6944848966',\n          '6904567890',\n          '6914567890',\n          '6934567890',\n          '6944567890',\n          '6954567890',\n          '6974567890',\n          '6984567890',\n          '6994567890',\n          '6854567890',\n          '6864567890',\n          '6874567890',\n          '6884567890',\n          '6894567890',\n        ],\n        invalid: [\n          '2102323234',\n          '+302646041461',\n          '120000000',\n          '20000000000',\n          '68129485729',\n          '6589394827',\n          '298RI89572',\n          '6924567890',\n          '6964567890',\n          '6844567890',\n          '690456789',\n          '00690456789',\n          'not a number',\n        ],\n      },\n      {\n        locale: 'el-CY',\n        valid: [\n          '96546247',\n          '96978927',\n          '+35799837145',\n          '+35799646792',\n          '96056927',\n          '99629593',\n          '99849980',\n          '3599701619',\n          '+3599148725',\n          '96537247',\n          '3596676533',\n          '+35795123455',\n          '+35797012204',\n          '35799123456',\n          '+35794123456',\n          '+35796123456',\n        ],\n        invalid: [\n          '',\n          'somechars',\n          '9697892',\n          '998499803',\n          '33799837145',\n          '+3799646792',\n          '93056927',\n        ],\n      },\n      {\n        locale: 'en-GB',\n        valid: [\n          '447789345856',\n          '+447861235675',\n          '07888814488',\n        ],\n        invalid: [\n          '67699567',\n          '0773894868',\n          '077389f8688',\n          '+07888814488',\n          '0152456999',\n          '442073456754',\n          '+443003434751',\n          '05073456754',\n          '08001123123',\n          '07043425232',\n          '01273884231',\n          '03332654034',\n        ],\n      },\n      {\n        locale: 'en-SG',\n        valid: [\n          '32891278',\n          '87654321',\n          '98765432',\n          '+6587654321',\n          '+6598765432',\n          '+6565241234',\n        ],\n        invalid: [\n          '332891231',\n          '987654321',\n          '876543219',\n          '8765432',\n          '9876543',\n          '12345678',\n          '+98765432',\n          '+9876543212',\n          '+15673628910',\n          '19876543210',\n          '8005552222',\n        ],\n      },\n      {\n        locale: 'en-US',\n        valid: [\n          '19876543210',\n          '8005552222',\n          '+15673628910',\n          '+1(567)3628910',\n          '+1(567)362-8910',\n          '+1(567) 362-8910',\n          '1(567)362-8910',\n          '1(567)362 8910',\n          '223-456-7890',\n        ],\n        invalid: [\n          '564785',\n          '0123456789',\n          '1437439210',\n          '+10345672645',\n          '11435213543',\n          '1(067)362-8910',\n          '1(167)362-8910',\n          '+2(267)362-8910',\n          '+3365520145',\n        ],\n      },\n      {\n        locale: 'en-CA',\n        valid: ['19876543210', '8005552222', '+15673628910'],\n        invalid: [\n          '564785',\n          '0123456789',\n          '1437439210',\n          '+10345672645',\n          '11435213543',\n        ],\n      },\n      {\n        locale: 'en-ZM',\n        valid: [\n          '0956684590',\n          '0966684590',\n          '0976684590',\n          '+260956684590',\n          '+260966684590',\n          '+260976684590',\n          '260976684590',\n          '+260779493521',\n          '+260760010936',\n        ],\n        invalid: [\n          '12345',\n          '',\n          'Vml2YW11cyBmZXJtZtesting123',\n          '010-38238383',\n          '966684590',\n          '760010936',\n        ],\n      },\n      {\n        locale: ['en-ZW'],\n        valid: [\n          '+263561890123',\n          '+263715558041',\n          '+263775551112',\n          '+263775551695',\n          '+263715556633',\n        ],\n        invalid: [\n          '12345',\n          '',\n          'Vml2YW11cyBmZXJtZtesting123',\n          '+2631234567890',\n          '+2641234567',\n          '+263981234',\n          '4736338855',\n          '66338855',\n        ],\n      },\n      {\n        locale: ['en-NA'],\n        valid: [\n          '+26466189012',\n          '+26461555804',\n          '+26461434221',\n          '+26487555169',\n          '+26481555663',\n        ],\n        invalid: [\n          '12345',\n          '',\n          'Vml2YW11cyBmZXJtZtesting123',\n          '+2641234567890',\n          '+2641234567',\n          '+2648143422',\n          '+264981234',\n          '4736338855',\n          '66338855',\n        ],\n      },\n      {\n        locale: 'ru-RU',\n        valid: [\n          '+79676338855',\n          '79676338855',\n          '89676338855',\n          '9676338855',\n        ],\n        invalid: [\n          '12345',\n          '',\n          'Vml2YW11cyBmZXJtZtesting123',\n          '010-38238383',\n          '+9676338855',\n          '19676338855',\n          '6676338855',\n          '+99676338855',\n        ],\n      },\n      {\n        locale: 'si-LK',\n        valid: [\n          '+94766661206',\n          '94713114340',\n          '0786642116',\n          '078 7642116',\n          '078-7642116',\n          '0749994567',\n        ],\n        invalid: [\n          '9912349956789',\n          '12345',\n          '1678123456',\n          '0731234567',\n          '0797878674',\n        ],\n      },\n      {\n        locale: 'sr-RS',\n        valid: [\n          '0640133338',\n          '063333133',\n          '0668888878',\n          '+381645678912',\n          '+381611314000',\n          '0655885010',\n        ],\n        invalid: [\n          '12345',\n          '',\n          'Vml2YW11cyBmZXJtZtesting123',\n          '010-38238383',\n          '+9676338855',\n          '19676338855',\n          '6676338855',\n          '+99676338855',\n        ],\n      },\n      {\n        locale: 'en-NZ',\n        valid: [\n          '+6427987035',\n          '642240512347',\n          '0293981646',\n          '029968425',\n        ],\n        invalid: [\n          '12345',\n          '',\n          'Vml2YW11cyBmZXJtZtesting123',\n          '+642956696123566',\n          '+02119620856',\n          '+9676338855',\n          '19676338855',\n          '6676338855',\n          '+99676338855',\n        ],\n      },\n      {\n        locale: 'en-MU',\n        valid: [\n          '+23012341234',\n          '12341234',\n          '012341234',\n        ],\n        invalid: [\n          '41234',\n          '',\n          '+230',\n          '+2301',\n          '+23012',\n          '+230123',\n          '+2301234',\n          '+23012341',\n          '+230123412',\n          '+2301234123',\n          '+230123412341',\n          '+2301234123412',\n          '+23012341234123',\n        ],\n      },\n      {\n        locale: ['nb-NO', 'nn-NO'], // for multiple locales\n        valid: [\n          '+4796338855',\n          '+4746338855',\n          '4796338855',\n          '4746338855',\n          '46338855',\n          '96338855',\n        ],\n        invalid: [\n          '12345',\n          '',\n          'Vml2YW11cyBmZXJtZtesting123',\n          '+4676338855',\n          '19676338855',\n          '+4726338855',\n          '4736338855',\n          '66338855',\n        ],\n      },\n      {\n        locale: ['ne-NP'],\n        valid: [\n          '+9779817385479',\n          '+9779717385478',\n          '+9779862002615',\n          '+9779853660020',\n        ],\n        invalid: [\n          '12345',\n          '',\n          'Vml2YW11cyBmZXJtZtesting123',\n          '+97796123456789',\n          '+9771234567',\n          '+977981234',\n          '4736338855',\n          '66338855',\n        ],\n      },\n      {\n        locale: 'vi-VN',\n        valid: [\n          '0336012403',\n          '+84586012403',\n          '84981577798',\n          '0708001240',\n          '84813601243',\n          '0523803765',\n          '0863803732',\n          '0883805866',\n          '0892405867',\n          '+84888696413',\n          '0878123456',\n          '84781234567',\n          '0553803765',\n        ],\n        invalid: [\n          '12345',\n          '',\n          'Vml2YW11cyBmZXJtZtesting123',\n          '010-38238383',\n          '260976684590',\n          '01678912345',\n          '+841698765432',\n          '841626543219',\n          '0533803765',\n          '08712345678',\n          '+0321234567',\n        ],\n      },\n      {\n        locale: 'es-AR',\n        valid: [\n          '5491143214321',\n          '+5491143214321',\n          '+5492414321432',\n          '5498418432143',\n        ],\n        invalid: [\n          '1143214321',\n          '91143214321',\n          '+91143214321',\n          '549841004321432',\n          '549 11 43214321',\n          '549111543214321',\n          '5714003425432',\n          '549114a214321',\n          '54 9 11 4321-4321',\n        ],\n      },\n      {\n        locale: 'es-CO',\n        valid: [\n          '+573003321235',\n          '573003321235',\n          '3003321235',\n          '3213321235',\n          '3103321235',\n          '3243321235',\n          '573011140876',\n        ],\n        invalid: [\n          '1234',\n          '+57443875615',\n          '57309875615',\n          '57109834567',\n          '5792434567',\n          '5702345689',\n          '5714003425432',\n          '5703013347567',\n          '069834567',\n          '969834567',\n          '579871235',\n          '574321235',\n          '5784321235',\n          '5784321235',\n          '9821235',\n          '0698345',\n          '3321235',\n        ],\n      },\n      {\n        locale: 'es-CL',\n        valid: [\n          '+56733875615',\n          '56928590234',\n          '0928590294',\n          '0208590294',\n        ],\n        invalid: [\n          '1234',\n          '+5633875615',\n          '563875615',\n          '56109834567',\n          '56069834567',\n        ],\n      },\n      {\n        locale: 'es-EC',\n        valid: [\n          '+593987654321',\n          '593987654321',\n          '0987654321',\n          '027332615',\n          '+59323456789',\n        ],\n        invalid: [\n          '03321321',\n          '+593387561',\n          '59312345677',\n          '02344635',\n          '593123456789',\n          '081234567',\n          '+593912345678',\n          '+593902345678',\n          '+593287654321',\n          '593287654321',\n        ],\n      },\n      {\n        locale: 'es-CR',\n        valid: [\n          '+50688888888',\n          '+50665408090',\n          '+50640895069',\n          '25789563',\n          '85789563',\n        ],\n        invalid: [\n          '+5081',\n          '+5067777777',\n          '+50188888888',\n          '+50e987643254',\n          '+506e4t4',\n          '-50688888888',\n          '50688888888',\n          '12345678',\n          '98765432',\n          '01234567',\n        ],\n      },\n      {\n        locale: 'es-CU',\n        valid: [\n          '+5351234567',\n          '005353216547',\n          '51234567',\n          '53214567',\n        ],\n        invalid: [\n          '1234',\n          '+5341234567',\n          '0041234567',\n          '41234567',\n          '11234567',\n          '21234567',\n          '31234567',\n          '60303456',\n          '71234567',\n          '81234567',\n          '91234567',\n          '+5343216547',\n          '+5332165498',\n          '+53121234567',\n          '',\n          'abc',\n          '+535123457',\n          '56043029304',\n        ],\n      },\n      {\n        locale: 'es-DO',\n        valid: [\n          '+18096622563',\n          '+18295614488',\n          '+18495259567',\n          '8492283478',\n          '8092324576',\n          '8292387713',\n        ],\n        invalid: [\n          '+18091',\n          '+1849777777',\n          '-18296643245',\n          '+18086643245',\n          '+18396643245',\n          '8196643245',\n          '+38492283478',\n          '6492283478',\n          '8192283478',\n        ],\n      },\n      {\n        locale: 'es-HN',\n        valid: [\n          '+50495551876',\n          '+50488908787',\n          '+50493456789',\n          '+50489234567',\n          '+50488987896',\n          '+50497567389',\n          '+50427367389',\n          '+50422357389',\n          '+50431257389',\n          '+50430157389',\n        ],\n        invalid: [\n          '12345',\n          '',\n          'Vml2YW11cyBmZXJtZtesting123',\n          '+34683456543',\n          '65478932',\n          '+50298787654',\n          '+504989874',\n        ],\n      },\n      {\n        locale: 'es-ES',\n        valid: [\n          '+34654789321',\n          '654789321',\n          '+34714789321',\n          '714789321',\n          '+34744789321',\n          '744789321',\n        ],\n        invalid: [\n          '12345',\n          '',\n          'Vml2YW11cyBmZXJtZtesting123',\n          '+3465478932',\n          '65478932',\n          '+346547893210',\n          '6547893210',\n          '+3470478932',\n          '7047893210',\n          '+34854789321',\n          '7547893219',\n        ],\n      },\n      {\n        locale: 'es-MX',\n        valid: [\n          '+52019654789321',\n          '+52199654789321',\n          '+5201965478932',\n          '+5219654789321',\n          '52019654789321',\n          '52199654789321',\n          '5201965478932',\n          '5219654789321',\n          '87654789321',\n          '8654789321',\n          '0187654789321',\n          '18654789321',\n        ],\n        invalid: [\n          '12345',\n          '',\n          'Vml2YW11cyBmZXJtZtesting123',\n          '+3465478932',\n          '65478932',\n          '+346547893210',\n          '+34704789321',\n          '704789321',\n          '+34754789321',\n        ],\n      },\n      {\n        locale: 'es-NI',\n        valid: [\n          '+5051234567',\n          '+50512345678',\n          '5051234567',\n          '50512345678',\n          '+50555555555',\n        ],\n        invalid: [\n          '1234',\n          '',\n          '1234567',\n          '12345678',\n          '+12345678',\n          '+505123456789',\n          '+50612345678',\n          '+50712345678',\n          '-50512345678',\n        ],\n      },\n      {\n        locale: 'es-PA',\n        valid: [\n          '+5076784565',\n          '+5074321557',\n          '5073331112',\n          '+50723431212',\n        ],\n        invalid: [\n          '+50755555',\n          '+207123456',\n          '2001236542',\n          '+507987643254',\n          '+507jjjghtf',\n        ],\n      },\n      {\n        locale: 'es-PY',\n        valid: [\n          '+595991372649',\n          '+595992847352',\n          '+595993847593',\n          '+595994857473',\n          '+595995348532',\n          '+595996435231',\n          '+595981847362',\n          '+595982435452',\n          '+595983948502',\n          '+595984342351',\n          '+595985403481',\n          '+595986384012',\n          '+595971435231',\n          '+595972103924',\n          '+595973438542',\n          '+595974425864',\n          '+595975425843',\n          '+595976342546',\n          '+595961435234',\n          '+595963425043',\n        ],\n        invalid: [\n          '12345',\n          '',\n          'Vml2YW11cyBmZXJtZtesting123',\n          '65478932',\n          '+59599384712',\n          '+5959938471234',\n          '+595547893218',\n          '+591993546843',\n        ],\n      },\n      {\n        locale: 'es-SV',\n        valid: [\n          '62136634',\n          '50361366631',\n          '+50361366634',\n          '+50361367217',\n          '+50361367460',\n          '+50371367632',\n          '+50371367767',\n          '+50371368314',\n        ],\n        invalid: [\n          '+5032136663',\n          '21346663',\n          '+50321366663',\n          '12345',\n          'El salvador',\n          'this should fail',\n          '+5032222',\n          '+503 1111 1111',\n          '00 +503 1234 5678',\n        ],\n      },\n      {\n        locale: 'es-UY',\n        valid: [\n          '+59899123456',\n          '099123456',\n          '+59894654321',\n          '091111111',\n        ],\n        invalid: [\n          '54321',\n          'montevideo',\n          '',\n          '+598099123456',\n          '090883338',\n          '099 999 999',\n        ],\n      },\n      {\n        locale: 'es-VE',\n        valid: [\n          '+582125457765',\n          '+582125458053',\n          '+584125458053',\n        ],\n        invalid: [\n          '+585129934395',\n          '+58212993439',\n          '',\n        ],\n      },\n      {\n        locale: 'et-EE',\n        valid: [\n          '+372 512 34 567',\n          '372 512 34 567',\n          '+37251234567',\n          '51234567',\n          '81234567',\n          '+372842345678',\n        ],\n        invalid: [\n          '12345',\n          '',\n          'NotANumber',\n          '+333 51234567',\n          '61234567',\n          '+51234567',\n          '+372 539 57 4',\n          '+372 900 1234',\n          '12345678',\n        ],\n      },\n      {\n        locale: 'pl-PL',\n        valid: [\n          '+48512689767',\n          '+48 56 376 87 47',\n          '56 566 78 46',\n          '657562855',\n          '+48657562855',\n          '+48 887472765',\n          '+48 56 6572724',\n          '+48 67 621 5461',\n          '48 67 621 5461',\n          '+48 45 621 5461',\n        ],\n        invalid: [\n          '+48  67 621 5461',\n          '+55657562855',\n          '3454535',\n          'teststring',\n          '',\n          '1800-88-8687',\n          '+6019-5830837',\n          '357562855',\n          '+48 44 621 5461',\n        ],\n      },\n      {\n        locale: 'fa-IR',\n        valid: [\n          '+989123456789',\n          '989223456789',\n          '09323456789',\n          '09021456789',\n          '+98-990-345-6789',\n          '+98 938 345 6789',\n          '0938 345 6789',\n        ],\n        invalid: [\n          '',\n          '+989623456789',\n          '+981123456789',\n          '01234567890',\n          '09423456789',\n          '09823456789',\n          '9123456789',\n          '091234567890',\n          '0912345678',\n          '+98 912 3456 6789',\n          '0912 345 678',\n        ],\n      },\n      {\n        locale: 'fi-FI',\n        valid: [\n          '+358505557171',\n          '0455571',\n          '0505557171',\n          '358505557171',\n          '04412345',\n          '0457 123 45 67',\n          '+358457 123 45 67',\n          '+358 50 555 7171',\n          '0501234',\n          '+358501234',\n          '050 1234',\n        ],\n        invalid: [\n          '12345',\n          '',\n          '045557',\n          '045555717112312332423423421',\n          'Vml2YW11cyBmZXJtZtesting123',\n          '010-38238383',\n          '+3-585-0555-7171',\n          '+9676338855',\n          '19676338855',\n          '6676338855',\n          '+99676338855',\n          '044123',\n          '019123456789012345678901',\n        ],\n      },\n      {\n        locale: 'fj-FJ',\n        valid: [\n          '+6799898679',\n          '6793788679',\n          '+679 989 8679',\n          '679 989 8679',\n          '679 3456799',\n          '679908 8909',\n        ],\n        invalid: [\n          '12345',\n          '',\n          '04555792',\n          '902w99900030900000000099',\n          '8uiuiuhhyy&GUU88d',\n          '010-38238383',\n          '19676338855',\n          '679 9 89 8679',\n          '6793 45679',\n        ],\n      },\n      {\n        locale: 'ms-MY',\n        valid: [\n          '+60128228789',\n          '+60195830837',\n          '+6019-5830837',\n          '+6019-5830837',\n          '+6010-4357675',\n          '+60172012370',\n          '0128737867',\n          '0172012370',\n          '01468987837',\n          '01112347345',\n          '016-2838768',\n          '016 2838768',\n        ],\n        invalid: [\n          '12345',\n          '601238788657',\n          '088387675',\n          '16-2838768',\n          '032551433',\n          '6088-387888',\n          '088-261987',\n          '1800-88-8687',\n          '088-320000',\n          '+01112353576',\n          '+0111419752',\n        ],\n      },\n      {\n        locale: 'fr-CM',\n        valid: [\n          '+237677936141',\n          '237623456789',\n          '+237698124842',\n          '237693029202',\n        ],\n        invalid: [\n          'NotANumber',\n          '+(703)-572-2920',\n          '+237 623 45 67 890',\n          '+2379981247429',\n        ],\n      },\n      {\n        locale: 'fr-DJ',\n        valid: [\n          '77600000',\n          '77699999',\n          '77700000',\n          '77799999',\n          '77800000',\n          '77899999',\n          '77654321',\n          '77765432',\n          '77876543',\n          '+25377600000',\n          '+25377699999',\n          '+25377700000',\n          '+25377799999',\n          '+25377800000',\n          '+25377899999',\n        ],\n        invalid: [\n          '21600000',\n          '27600000',\n          '70600000',\n          '71600000',\n          '72600000',\n          '73600000',\n          '74600000',\n          '75600000',\n          '76600000',\n          '78600000',\n          '79600000',\n          '77500000',\n          '77900000',\n          '77000000',\n          '77100000',\n          '77599999',\n          '77999999',\n          '7760000',\n          '776000000',\n          '+2537760000',\n          '+253776000000',\n          '+25477600000',\n          '+25177600000',\n          '77 600000',\n          '77-600000',\n          '+253 77600000',\n          '',\n          '+253',\n          '00000000',\n          'abcdefgh',\n          '77600000x',\n        ],\n      },\n      {\n        locale: 'ko-KR',\n        valid: [\n          '+82-010-1234-5678',\n          '+82-10-1234-5678',\n          '82-010-1234-5678',\n          '82-10-1234-5678',\n          '+82 10 1234 5678',\n          '010-123-5678',\n          '10-1234-5678',\n          '+82 10 1234 5678',\n          '011 1234 5678',\n          '+820112345678',\n          '01012345678',\n          '+82 016 1234 5678',\n          '82 19 1234 5678',\n          '+82 010 12345678',\n        ],\n        invalid: [\n          'abcdefghi',\n          '+82 10 1234 567',\n          '+82 10o 1234 1234',\n          '+82 101 1234 5678',\n          '+82 10 12 5678',\n          '+011 7766 1234',\n          '011_7766_1234',\n          '+820 11 7766 1234',\n        ],\n      },\n      {\n        locale: 'ky-KG',\n        valid: [\n          '+996553033300',\n          '+996 222 123456',\n          '+996 500 987654',\n          '+996 555 111222',\n          '+996 700 333444',\n          '+996 770 555666',\n          '+996 880 777888',\n          '+996 990 999000',\n          '+996 995 555666',\n          '+996 996 555666',\n          '+996 997 555666',\n          '+996 998 555666',\n        ],\n        invalid: [\n          '+996 201 123456',\n          '+996 312 123456',\n          '+996 3960 12345',\n          '+996 3961 12345',\n          '+996 3962 12345',\n          '+996 3963 12345',\n          '+996 3964 12345',\n          '+996 3965 12345',\n          '+996 3966 12345',\n          '+996 3967 12345',\n          '+996 3968 12345',\n          '+996 511 123456',\n          '+996 522 123456',\n          '+996 561 123456',\n          '+996 571 123456',\n          '+996 624 123456',\n          '+996 623 123456',\n          '+996 622 123456',\n          '+996 609 123456',\n          '+996 100 12345',\n          '+996 100 1234567',\n          '996 100 123456',\n          '0 100 123456',\n          '0 100 123abc',\n        ],\n      },\n      {\n        locale: 'ja-JP',\n        valid: [\n          '09012345678',\n          '08012345678',\n          '07012345678',\n          '06012345678',\n          '090 1234 5678',\n          '+8190-1234-5678',\n          '+81 (0)90-1234-5678',\n          '+819012345678',\n          '+81-(0)90-1234-5678',\n          '+81 90 1234 5678',\n        ],\n        invalid: [\n          '12345',\n          '',\n          '045555717112312332423423421',\n          'Vml2YW11cyBmZXJtZtesting123',\n          '+3-585-0555-7171',\n          '0 1234 5689',\n          '16 1234 5689',\n          '03_1234_5689',\n          '0312345678',\n          '0721234567',\n          '06 1234 5678',\n          '072 123 4567',\n          '0729 12 3456',\n          '07296 1 2345',\n          '072961 2345',\n          '03-1234-5678',\n          '+81312345678',\n          '+816-1234-5678',\n          '+81 090 1234 5678',\n          '+8109012345678',\n          '+81-090-1234-5678',\n          '90 1234 5678',\n        ],\n      },\n      {\n        locale: 'ir-IR',\n        valid: [\n          '09023818688',\n          '09123809999',\n          '+989023818688',\n          '+989103923523',\n        ],\n        invalid: [\n          '19023818688',\n          '323254',\n          '+903232323257',\n          '++3567868',\n          '0902381888832',\n        ],\n      },\n      {\n        locale: 'it-IT',\n        valid: [\n          '370 3175423',\n          '333202925',\n          '+39 310 7688449',\n          '+39 3339847632',\n        ],\n        invalid: [\n          '011 7387545',\n          '12345',\n          '+45 345 6782395',\n        ],\n      },\n      {\n        locale: 'fr-BE',\n        valid: [\n          '0470123456',\n          '+32470123456',\n          '32470123456',\n          '0421234567',\n          '+32421234567',\n          '32421234567',\n        ],\n        invalid: [\n          '12345',\n          '+3212345',\n          '3212345',\n          '04701234567',\n          '+3204701234567',\n          '3204701234567',\n          '0212345678',\n          '+320212345678',\n          '320212345678',\n          '021234567',\n          '+3221234567',\n          '3221234567',\n        ],\n      },\n      {\n        locale: 'nl-BE',\n        valid: [\n          '0470123456',\n          '+32470123456',\n          '32470123456',\n          '0421234567',\n          '+32421234567',\n          '32421234567',\n        ],\n        invalid: [\n          '12345',\n          '+3212345',\n          '3212345',\n          '04701234567',\n          '+3204701234567',\n          '3204701234567',\n          '0212345678',\n          '+320212345678',\n          '320212345678',\n          '021234567',\n          '+3221234567',\n          '3221234567',\n        ],\n      },\n      {\n        locale: 'nl-NL',\n        valid: [\n          '0670123456',\n          '0612345678',\n          '31612345678',\n          '31670123456',\n          '+31612345678',\n          '+31670123456',\n          '+31(0)612345678',\n          '0031612345678',\n          '0031(0)612345678',\n        ],\n        invalid: [\n          '12345',\n          '+3112345',\n          '3112345',\n          '06701234567',\n          '012345678',\n          '+3104701234567',\n          '3104701234567',\n          '0212345678',\n          '021234567',\n          '+3121234567',\n          '3121234567',\n          '+310212345678',\n          '310212345678',\n        ],\n      },\n      {\n        locale: 'nl-AW',\n        valid: [\n          '2975612345',\n          '2976412345',\n          '+2975612345',\n          '+2975912345',\n          '+2976412345',\n          '+2977312345',\n          '+2977412345',\n          '+2979912345',\n        ],\n        invalid: [\n          '12345',\n          '+2972345',\n          '2972345',\n          '06701234567',\n          '012345678',\n          '+2974701234567',\n          '2974701234567',\n          '0297345678',\n          '029734567',\n          '+2971234567',\n          '2971234567',\n          '+297212345678',\n          '297212345678',\n          'number',\n        ],\n      },\n      {\n        locale: 'ro-MD',\n        valid: [\n          '+37360375781',\n          '+37361945673',\n          '+37362387563',\n          '+37368447788',\n          '+37369000101',\n          '+37367568910',\n          '+37376758294',\n          '+37378457892',\n          '+37379067436',\n          '37362387563',\n          '37368447788',\n          '37369000101',\n          '37367568910',\n        ],\n        invalid: [\n          '',\n          '+37363373381',\n          '+37364310581',\n          '+37365578199',\n          '+37371088636',\n          'Vml2YW11cyBmZXJtZtesting123',\n          '123456',\n          '740123456',\n          '+40640123456',\n          '+40210123456',\n        ],\n      },\n      {\n        locale: 'ro-RO',\n        valid: [\n          '+40740123456',\n          '+40 740123456',\n          '+40740 123 456',\n          '+40740.123.456',\n          '+40740-123-456',\n          '40740123456',\n          '40 740123456',\n          '40740 123 456',\n          '40740.123.456',\n          '40740-123-456',\n          '0740123456',\n          '0740/123456',\n          '0740 123 456',\n          '0740.123.456',\n          '0740-123-456',\n        ],\n        invalid: [\n          '',\n          'Vml2YW11cyBmZXJtZtesting123',\n          '123456',\n          '740123456',\n          '+40640123456',\n          '+40210123456',\n          '+0765351689',\n          '+0711419752',\n        ],\n      },\n      {\n        locale: 'id-ID',\n        valid: [\n          '0811 778 998',\n          '0811 7785 9983',\n          '0812 7784 9984',\n          '0813 7782 9982',\n          '0821 1234 1234',\n          '0822 1234 1234',\n          '0823 1234 1234',\n          '0852 1234 6764',\n          '0853 1234 6764',\n          '0851 1234 6764',\n          '0814 7782 9982',\n          '0815 7782 9982',\n          '0816 7782 9982',\n          '0855 7782 9982',\n          '0856 7782 9982',\n          '0857 7782 9982',\n          '0858 7782 9982',\n          '0817 7785 9983',\n          '0818 7784 9984',\n          '0819 7782 9982',\n          '0859 1234 1234',\n          '0877 1234 1234',\n          '0878 1234 1234',\n          '0895 7785 9983',\n          '0896 7784 9984',\n          '0897 7782 9982',\n          '0898 1234 1234',\n          '0899 1234 1234',\n          '0881 7785 9983',\n          '0882 7784 9984',\n          '0883 7782 9982',\n          '0884 1234 1234',\n          '0886 1234 1234',\n          '0887 1234 1234',\n          '0888 7785 9983',\n          '0889 7784 9984',\n          '0828 7784 9984',\n          '0838 7784 9984',\n          '0831 7784 9984',\n          '0832 7784 9984',\n          '0833 7784 9984',\n          '089931236181900',\n          '62811 778 998',\n          '62811778998',\n          '628993123618190',\n          '62898 740123456',\n          '62899 7401 2346',\n          '+62811 778 998',\n          '+62811778998',\n          '+62812 9650 3508',\n          '08197231819',\n          '085361008008',\n          '+62811787391',\n        ],\n        invalid: [\n          '0899312361819001',\n          '0217123456',\n          '622178878890',\n          '6221 740123456',\n          '0341 8123456',\n          '0778 89800910',\n          '0741 123456',\n          '+6221740123456',\n          '+65740 123 456',\n          '',\n          'ASDFGJKLmZXJtZtesting123',\n          '123456',\n          '740123456',\n          '+65640123456',\n          '+64210123456',\n        ],\n      },\n      {\n        locale: 'lt-LT',\n        valid: [\n          '+37051234567',\n          '851234567',\n        ],\n        invalid: [\n          '+65740 123 456',\n          '',\n          'ASDFGJKLmZXJtZtesting123',\n          '123456',\n          '740123456',\n          '+65640123456',\n          '+64210123456',\n        ],\n      },\n      {\n        locale: 'uk-UA',\n        valid: [\n          '+380501234567',\n          '+380631234567',\n          '+380661234567',\n          '+380671234567',\n          '+380681234567',\n          '+380731234567',\n          '+380751234567',\n          '+380771234567',\n          '+380911234567',\n          '+380921234567',\n          '+380931234567',\n          '+380941234567',\n          '+380951234567',\n          '+380961234567',\n          '+380971234567',\n          '+380981234567',\n          '+380991234567',\n          '380501234567',\n          '380631234567',\n          '380661234567',\n          '380671234567',\n          '380681234567',\n          '380731234567',\n          '380751234567',\n          '380771234567',\n          '380911234567',\n          '380921234567',\n          '380931234567',\n          '380941234567',\n          '380951234567',\n          '380961234567',\n          '380971234567',\n          '380981234567',\n          '380991234567',\n          '0501234567',\n          '0631234567',\n          '0661234567',\n          '0671234567',\n          '0681234567',\n          '0731234567',\n          '0751234567',\n          '0771234567',\n          '0911234567',\n          '0921234567',\n          '0931234567',\n          '0941234567',\n          '0951234567',\n          '0961234567',\n          '0971234567',\n          '0981234567',\n          '0991234567',\n        ],\n        invalid: [\n          '+30982345679',\n          '+380321234567',\n          '+380441234567',\n          '982345679',\n          '80982345679',\n          '+380 98 234 5679',\n          '+380-98-234-5679',\n          '+380 (98) 234-56-79',\n          '',\n          'ASDFGJKLmZXJtZtesting123',\n          '123456',\n          '740123456',\n        ],\n      },\n      {\n        locale: 'uz-UZ',\n        valid: [\n          '+998664835244',\n          '998664835244',\n          '664835244',\n          '+998957124555',\n          '998957124555',\n          '957124555',\n        ],\n        invalid: [\n          '+998644835244',\n          '998644835244',\n          '644835244',\n          '+99664835244',\n          'ASDFGJKLmZXJtZtesting123',\n          '123456789',\n          '870123456',\n          '',\n          '+998',\n          '998',\n        ],\n      },\n      {\n        locale: 'da-DK',\n        valid: [\n          '12345678',\n          '12 34 56 78',\n          '45 12345678',\n          '4512345678',\n          '45 12 34 56 78',\n          '+45 12 34 56 78',\n        ],\n        invalid: [\n          '',\n          '+45010203',\n          'ASDFGJKLmZXJtZtesting123',\n          '123456',\n          '12 34 56',\n          '123 123 12',\n        ],\n      },\n      {\n        locale: 'sv-SE',\n        valid: [\n          '+46701234567',\n          '46701234567',\n          '0721234567',\n          '073-1234567',\n          '0761-234567',\n          '079-123 45 67',\n        ],\n        invalid: [\n          '12345',\n          '+4670123456',\n          '+46301234567',\n          '+0731234567',\n          '0731234 56',\n          '+7312345678',\n          '',\n        ],\n      },\n      {\n        locale: 'fo-FO',\n        valid: [\n          '123456',\n          '12 34 56',\n          '298 123456',\n          '298123456',\n          '298 12 34 56',\n          '+298 12 34 56',\n        ],\n        invalid: [\n          '',\n          '+4501020304',\n          'ASDFGJKLmZXJtZtesting123',\n          '12345678',\n          '12 34 56 78',\n        ],\n      },\n      {\n        locale: 'kl-GL',\n        valid: [\n          '123456',\n          '12 34 56',\n          '299 123456',\n          '299123456',\n          '299 12 34 56',\n          '+299 12 34 56',\n        ],\n        invalid: [\n          '',\n          '+4501020304',\n          'ASDFGJKLmZXJtZtesting123',\n          '12345678',\n          '12 34 56 78',\n        ],\n      },\n      {\n        locale: 'kk-KZ',\n        valid: [\n          '+77254716212',\n          '77254716212',\n          '87254716212',\n          '7254716212',\n        ],\n        invalid: [\n          '12345',\n          '',\n          'ASDFGJKLmZXJtZtesting123',\n          '010-38238383',\n          '+9676338855',\n          '19676338855',\n          '6676338855',\n          '+99676338855',\n        ],\n      },\n      {\n        locale: 'be-BY',\n        valid: [\n          '+375241234567',\n          '+375251234567',\n          '+375291234567',\n          '+375331234567',\n          '+375441234567',\n          '375331234567',\n        ],\n        invalid: [\n          '12345',\n          '',\n          'ASDFGJKLmZXJtZtesting123',\n          '010-38238383',\n          '+9676338855',\n          '19676338855',\n          '6676338855',\n          '+99676338855',\n        ],\n      },\n      {\n        locale: 'th-TH',\n        valid: [\n          '0912345678',\n          '+66912345678',\n          '66912345678',\n        ],\n        invalid: [\n          '99123456789',\n          '12345',\n          '67812345623',\n          '081234567891',\n        ],\n      },\n      {\n        locale: 'tk-TM',\n        valid: [\n          '+99312495154',\n          '99312130136',\n          '+99312918407',\n          '99312183399',\n          '812391717',\n        ],\n        invalid: [\n          '12345',\n          '+99412495154',\n          '99412495154',\n          '998900066506',\n        ],\n      },\n      {\n        locale: 'en-SL',\n        valid: [\n          '+23274560591',\n          '23274560591',\n          '074560591',\n        ],\n        invalid: [\n          '0745605912',\n          '12345',\n          '232745605917',\n          '0797878674',\n          '23274560591 ',\n        ],\n      },\n      {\n        locale: 'en-BW',\n        valid: [\n          '+26772868545',\n          '+26776368790',\n          '+26774560512',\n          '26774560591',\n          '26778560512',\n          '74560512',\n          '76710284',\n        ],\n        invalid: [\n          '0799375902',\n          '12345',\n          '+2670745605448',\n          '2670745605482',\n          '+26779685451',\n          '+26770685451',\n          '267074560',\n          '2670ab5608',\n          '+267074560',\n          '70560512',\n          '79710284',\n        ],\n      },\n      {\n        locale: 'az-AZ',\n        valid: [\n          '+994707007070',\n          '0707007070',\n          '+994502111111',\n          '0505436743',\n          '0554328772',\n          '0104328772',\n          '0993301022',\n          '+994776007139',\n          '+994106007139',\n        ],\n        invalid: [\n          'wrong-number',\n          '',\n          '994707007070',\n          '++9945005050',\n          '556007070',\n          '1234566',\n          '+994778008080a',\n        ],\n      },\n      {\n        locale: 'de-LU',\n        valid: [\n          '601123456',\n          '+352601123456',\n        ],\n        invalid: [\n          'NaN',\n          '791234',\n          '+352791234',\n          '26791234',\n          '+35226791234',\n          '+112039812',\n          '+352703123456',\n          '1234',\n        ],\n      },\n      {\n        locale: 'it-SM',\n        valid: [\n          '612345',\n          '05496123456',\n          '+37861234567',\n          '+390549612345678',\n          '+37805496123456789',\n        ],\n        invalid: [\n          '61234567890',\n          '6123',\n          '1234567',\n          '+49123456',\n          'NotANumber',\n        ],\n      },\n      {\n        locale: 'so-SO',\n        valid: [\n          '+252601234567',\n          '+252650101010',\n          '+252794567120',\n          '252650647388',\n          '252751234567',\n          '0601234567',\n          '0609876543',\n        ],\n        invalid: [\n          '',\n          'not a number',\n          '+2526012345678',\n          '25260123456',\n          '+252705555555',\n          '+0601234567',\n          '06945454545',\n        ],\n      },\n      {\n        locale: 'sq-AL',\n        valid: [\n          '0621234567',\n          '0661234567',\n          '0671234567',\n          '0681234567',\n          '0691234567',\n          '+355621234567',\n          '+355651234567',\n          '+355661234567',\n          '+355671234567',\n          '+355681234567',\n          '+355691234567',\n        ],\n        invalid: [\n          '67123456',\n          '06712345',\n          '067123456',\n          '06712345678',\n          '0571234567',\n          '+3556712345',\n          '+35565123456',\n          '+35157123456',\n          'NotANumber',\n        ],\n      },\n      {\n        locale: 'ca-AD',\n        valid: [\n          '+376312345',\n          '312345',\n        ],\n        invalid: [\n          '31234',\n          '31234567',\n          '512345',\n          'NotANumber',\n        ],\n      },\n      {\n        locale: 'pt-AO',\n        valid: [\n          '+244911123432',\n          '911123432',\n          '244911123432',\n        ],\n        invalid: [\n          '+2449111234321',\n          '+244811123432',\n          '31234',\n          '31234567',\n          '512345',\n          'NotANumber',\n        ],\n      },\n      {\n        locale: 'lv-LV',\n        valid: [\n          '+37121234567',\n          '37121234567',\n        ],\n        invalid: [\n          '+37201234567',\n          '+3754321',\n          '3712123456',\n          '+371212345678',\n          'NotANumber',\n        ],\n      },\n      {\n        locale: 'mg-MG',\n        valid: [\n          '+261204269174',\n          '261204269174',\n          '0204269174',\n          '0209269174',\n          '0374269174',\n          '4269174',\n        ],\n        invalid: [\n          '0261204269174',\n          '+261 20 4 269174',\n          '+261 20 4269174',\n          '020 4269174',\n          '204269174',\n          '0404269174',\n          'NotANumber',\n        ],\n      },\n      {\n        locale: 'mn-MN',\n        valid: [\n          '+97699112222',\n          '97696112222',\n          '97695112222',\n          '01197691112222',\n          '0097688112222',\n          '+97677112222',\n          '+97694112222',\n          '+97681112222',\n        ],\n        invalid: [\n          '+97888112222',\n          '+97977112222',\n          '+97094112222',\n          '+97281112222',\n          '02297681112222',\n        ],\n      },\n      {\n        locale: 'my-MM',\n        valid: [\n          '+959750202595',\n          '09750202595',\n          '9750202595',\n          '+959260000966',\n          '09256000323',\n          '09276000323',\n          '09426000323',\n          '09456000323',\n          '09761234567',\n          '09791234567',\n          '09961234567',\n          '09771234567',\n          '09660000234',\n        ],\n        invalid: [\n          '59750202595',\n          '+9597502025',\n          '08943234524',\n          '09950000966',\n          '959240000966',\n          '09246000323',\n          '09466000323',\n          '09951234567',\n          '09801234567',\n          '09650000234',\n        ],\n      },\n      {\n        locale: 'en-PG',\n        valid: [\n          '+67570123456',\n          '67570123456',\n          '+67571123456',\n          '+67572123456',\n          '+67573123456',\n          '+67574123456',\n          '+67575123456',\n          '+67576123456',\n          '+67577123456',\n          '+67578123456',\n          '+67579123456',\n          '+67581123456',\n          '+67588123456',\n        ],\n        invalid: [\n          '',\n          'not a number',\n          '12345',\n          '+675123456789',\n          '+67580123456',\n          '+67569123456',\n          '+67582123456',\n          '+6757012345',\n        ],\n      },\n      {\n        locale: 'en-AG',\n        valid: [\n          '12687151234',\n          '+12687151234',\n          '+12684641234',\n          '12684641234',\n          '+12687211234',\n          '+12687302468',\n          '+12687642456',\n          '+12687763333',\n        ],\n        invalid: [\n          '2687151234',\n          '+12687773333',\n          '+126846412333',\n          '+12684641',\n          '+12687123456',\n          '+12687633456',\n        ],\n      },\n      {\n        locale: 'en-AI',\n        valid: [\n          '+12642351234',\n          '12642351234',\n          '+12644612222',\n          '+12645366326',\n          '+12645376326',\n          '+12647246326',\n          '+12647726326',\n        ],\n        invalid: [\n          '',\n          'not a number',\n          '+22642351234',\n          '+12902351234',\n          '+12642331234',\n          '+1264235',\n          '22642353456',\n          '+12352643456',\n        ],\n      },\n      {\n        locale: 'en-KN',\n        valid: [\n          '+18694699040',\n          '18694699040',\n          '+18697652917',\n          '18697652917',\n          '18694658472',\n          '+18696622969',\n          '+18694882224',\n        ],\n        invalid: [\n          '',\n          '+18694238545',\n          '+1 8694882224',\n          '8694658472',\n          '+186946990',\n          '+1869469904',\n          '1869469904',\n        ],\n      },\n      {\n        locale: 'en-PK',\n        valid: [\n          '+923412877421',\n          '+923001234567',\n          '00923001234567',\n          '923001234567',\n          '03001234567',\n        ],\n        invalid: [\n          '+3001234567',\n          '+933001234567',\n          '+924001234567',\n          '+92300123456720',\n          '030012345672',\n          '30012345673',\n          '0030012345673',\n          '3001234567',\n        ],\n      },\n      {\n        locale: ['tg-TJ'],\n        valid: [\n          '+992553388551',\n          '+992553322551',\n          '992553388551',\n          '992553322551',\n        ],\n        invalid: [\n          '12345',\n          '',\n          'Vml2YW11cyBmZXJtZtesting123',\n          '+995563388559',\n          '+9955633559',\n          '19676338855',\n          '+992263388505',\n          '9923633885',\n          '99255363885',\n          '66338855',\n        ],\n      },\n      {\n        locale: 'dv-MV',\n        valid: [\n          '+9609112345',\n          '+9609958973',\n          '+9607258963',\n          '+9607958463',\n          '9609112345',\n          '9609958973',\n          '9607212963',\n          '9607986963',\n          '9112345',\n          '9958973',\n          '7258963',\n          '7958963',\n        ],\n        invalid: [\n          '+96059234567',\n          '+96045789',\n          '7812463784',\n          'NotANumber',\n          '+9607112345',\n          '+9609012345',\n          '+609012345',\n          '+96071123456',\n          '3412345',\n          '9603412345',\n        ],\n      },\n      {\n        locale: 'ar-YE',\n        valid: [\n          '737198225',\n          '733111355',\n          '+967700990270',\n        ],\n        invalid: [\n          '+5032136663',\n          '21346663',\n          '+50321366663',\n          '12345',\n          'Yemen',\n          'this should fail',\n          '+5032222',\n          '+503 1111 1111',\n          '00 +503 1234 5678',\n        ],\n      },\n      {\n        locale: 'ar-EH',\n        valid: [\n          '+212-5288-12312',\n          '+212-5288 12312',\n          '+212 5288 12312',\n          '212528912312',\n          '+212528912312',\n          '+212528812312',\n        ],\n        invalid: [\n          '212528812312123',\n          '+212-5290-12312',\n          '++212528812312',\n          '12345',\n          'Wester Sahara',\n          'this should fail',\n          '212  5288---12312',\n          '+503 1111 1111',\n          '00 +503 1234 5678',\n        ],\n      },\n      {\n        locale: 'fa-AF',\n        valid: [\n          '0511231231',\n          '+93511231231',\n          '+93281234567',\n        ],\n        invalid: [\n          '212528812312123',\n          '+212-5290-12312',\n          '++212528812312',\n          '12345',\n          'Afghanistan',\n          'this should fail',\n          '212  5288---12312',\n          '+503 1111 1111',\n          '00 +503 1234 5678',\n        ],\n      },\n      {\n        locale: 'en-SS',\n        valid: [\n          '+211928530422',\n          '+211913384561',\n          '+211972879174',\n          '+211952379334',\n          '0923346543',\n          '0950459022',\n          '0970934567',\n          '211979841238',\n          '211929843238',\n          '211959840238',\n        ],\n        invalid: [\n          '911',\n          '+211999',\n          '123456789909',\n          'South Sudan',\n          '21195 840 238',\n          '+211981234567',\n          '+211931234567',\n          '+211901234567',\n          '+211991234567',\n\n        ],\n      },\n      {\n        locale: 'es-GT',\n        valid: [\n          '+50221234567',\n          '+50277654321',\n          '50226753421',\n          '50272332468',\n          '50278984455',\n          '+50273472492',\n          '71234567',\n          '21132398',\n        ],\n        invalid: [\n          '44',\n          '+5022712345678',\n          '1234567899',\n          '502712345678',\n          'This should fail',\n          '5021931234567',\n          '+50281234567',\n        ],\n      },\n      {\n        locale: 'mk-MK',\n        valid: [\n          '+38923234567',\n          '38931234567',\n          '022123456',\n          '22234567',\n          '71234567',\n          '31234567',\n          '+38923091500',\n          '80091234',\n          '81123456',\n          '54123456',\n        ],\n        invalid: [\n          '38912345678',\n          '+389123456789',\n          '21234567',\n          '123456789',\n          '+3891234567',\n          '700012345',\n          '510123456',\n          'This should fail',\n          '+389123456',\n          '389123456',\n          '80912345',\n        ],\n      },\n      {\n        locale: 'ar-QA',\n        valid: ['+97435551234', '+97455551234', '+97465551234', '+97475551234', '35551234', '55551234', '65551234', '75551234'],\n        invalid: ['+97445551234', '+97405551234', '+9745555123', '+974555512345', '+97355551234', '+9125551234', '25551234', '+13005551234', '45551234', '95551234', '+9745555abcd', '', '+974'],\n      },\n    ];\n\n    let allValid = [];\n\n    fixtures.forEach((fixture) => {\n      // to be used later on for validating 'any' locale\n      if (fixture.valid) allValid = allValid.concat(fixture.valid);\n\n      if (Array.isArray(fixture.locale)) {\n        test({\n          validator: 'isMobilePhone',\n          valid: fixture.valid,\n          invalid: fixture.invalid,\n          args: [fixture.locale],\n        });\n      } else {\n        test({\n          validator: 'isMobilePhone',\n          valid: fixture.valid,\n          invalid: fixture.invalid,\n          args: [fixture.locale],\n        });\n      }\n    });\n\n    test({\n      validator: 'isMobilePhone',\n      valid: allValid,\n      invalid: [\n        '',\n        'asdf',\n        '1',\n        'ASDFGJKLmZXJtZtesting123',\n        'Vml2YW11cyBmZXJtZtesting123',\n      ],\n      args: ['any'],\n    });\n\n    // strict mode\n    test({\n      validator: 'isMobilePhone',\n      valid: [\n        '+254728530234',\n        '+299 12 34 56',\n        '+94766660206',\n      ],\n      invalid: [\n        '254728530234',\n        '0728530234',\n        '+728530234',\n        '766667206',\n        '0766670206',\n      ],\n      args: ['any', { strictMode: true }],\n    });\n\n    // falsey locale defaults to 'any'\n    test({\n      validator: 'isMobilePhone',\n      valid: allValid,\n      invalid: [\n        '',\n        'asdf',\n        '1',\n        'ASDFGJKLmZXJtZtesting123',\n        'Vml2YW11cyBmZXJtZtesting123',\n      ],\n      args: [],\n    });\n  });\n\n  // de-CH, fr-CH, it-CH\n  test({\n    validator: 'isMobilePhone',\n    valid: [\n      '+41751112233',\n      '+41761112233',\n      '+41771112233',\n      '+41781112233',\n      '+41791112233',\n      '+411122112211',\n    ],\n    invalid: [\n      '+41041112233',\n    ],\n    args: [],\n  });\n\n\n  it('should error on invalid locale', () => {\n    test({\n      validator: 'isMobilePhone',\n      args: [{ locale: ['is-NOT'] }],\n      error: [\n        '+123456789',\n        '012345',\n      ],\n    });\n  });\n\n  it('should validate currency', () => {\n    // -$##,###.## (en-US, en-CA, en-AU, en-NZ, en-HK)\n    test({\n      validator: 'isCurrency',\n      valid: [\n        '-$10,123.45',\n        '$10,123.45',\n        '$10123.45',\n        '10,123.45',\n        '10123.45',\n        '10,123',\n        '1,123,456',\n        '1123456',\n        '1.39',\n        '.03',\n        '0.10',\n        '$0.10',\n        '-$0.01',\n        '-$.99',\n        '$100,234,567.89',\n        '$10,123',\n        '10,123',\n        '-10123',\n      ],\n      invalid: [\n        '1.234',\n        '$1.1',\n        '$ 32.50',\n        '500$',\n        '.0001',\n        '$.001',\n        '$0.001',\n        '12,34.56',\n        '123456,123,123456',\n        '123,4',\n        ',123',\n        '$-,123',\n        '$',\n        '.',\n        ',',\n        '00',\n        '$-',\n        '$-,.',\n        '-',\n        '-$',\n        '',\n        '- $',\n      ],\n    });\n\n    // -$##,###.## (en-US, en-CA, en-AU, en-NZ, en-HK)\n    test({\n      validator: 'isCurrency',\n      args: [\n        {\n          allow_decimal: false,\n        },\n      ],\n      valid: [\n        '-$10,123',\n        '$10,123',\n        '$10123',\n        '10,123',\n        '10123',\n        '10,123',\n        '1,123,456',\n        '1123456',\n        '1',\n        '0',\n        '$0',\n        '-$0',\n        '$100,234,567',\n        '$10,123',\n        '10,123',\n        '-10123',\n      ],\n      invalid: [\n        '-$10,123.45',\n        '$10,123.45',\n        '$10123.45',\n        '10,123.45',\n        '10123.45',\n        '1.39',\n        '.03',\n        '0.10',\n        '$0.10',\n        '-$0.01',\n        '-$.99',\n        '$100,234,567.89',\n        '1.234',\n        '$1.1',\n        '$ 32.50',\n        '.0001',\n        '$.001',\n        '$0.001',\n        '12,34.56',\n        '123,4',\n        ',123',\n        '$-,123',\n        '$',\n        '.',\n        ',',\n        '00',\n        '$-',\n        '$-,.',\n        '-',\n        '-$',\n        '',\n        '- $',\n      ],\n    });\n\n    // -$##,###.## (en-US, en-CA, en-AU, en-NZ, en-HK)\n    test({\n      validator: 'isCurrency',\n      args: [\n        {\n          require_decimal: true,\n        },\n      ],\n      valid: [\n        '-$10,123.45',\n        '$10,123.45',\n        '$10123.45',\n        '10,123.45',\n        '10123.45',\n        '10,123.00',\n        '1.39',\n        '.03',\n        '0.10',\n        '$0.10',\n        '-$0.01',\n        '-$.99',\n        '$100,234,567.89',\n      ],\n      invalid: [\n        '$10,123',\n        '10,123',\n        '-10123',\n        '1,123,456',\n        '1123456',\n        '1.234',\n        '$1.1',\n        '$ 32.50',\n        '500$',\n        '.0001',\n        '$.001',\n        '$0.001',\n        '12,34.56',\n        '123456,123,123456',\n        '123,4',\n        ',123',\n        '$-,123',\n        '$',\n        '.',\n        ',',\n        '00',\n        '$-',\n        '$-,.',\n        '-',\n        '-$',\n        '',\n        '- $',\n      ],\n    });\n\n    // -$##,###.## (en-US, en-CA, en-AU, en-NZ, en-HK)\n    test({\n      validator: 'isCurrency',\n      args: [\n        {\n          digits_after_decimal: [1, 3],\n        },\n      ],\n      valid: [\n        '-$10,123.4',\n        '$10,123.454',\n        '$10123.452',\n        '10,123.453',\n        '10123.450',\n        '10,123',\n        '1,123,456',\n        '1123456',\n        '1.3',\n        '.030',\n        '0.100',\n        '$0.1',\n        '-$0.0',\n        '-$.9',\n        '$100,234,567.893',\n        '$10,123',\n        '10,123.123',\n        '-10123.1',\n      ],\n      invalid: [\n        '1.23',\n        '$1.13322',\n        '$ 32.50',\n        '500$',\n        '.0001',\n        '$.01',\n        '$0.01',\n        '12,34.56',\n        '123456,123,123456',\n        '123,4',\n        ',123',\n        '$-,123',\n        '$',\n        '.',\n        ',',\n        '00',\n        '$-',\n        '$-,.',\n        '-',\n        '-$',\n        '',\n        '- $',\n      ],\n    });\n\n    // -$##,###.## with $ required (en-US, en-CA, en-AU, en-NZ, en-HK)\n    test({\n      validator: 'isCurrency',\n      args: [\n        {\n          require_symbol: true,\n        },\n      ],\n      valid: [\n        '-$10,123.45',\n        '$10,123.45',\n        '$10123.45',\n        '$10,123.45',\n        '$10,123',\n        '$1,123,456',\n        '$1123456',\n        '$1.39',\n        '$.03',\n        '$0.10',\n        '$0.10',\n        '-$0.01',\n        '-$.99',\n        '$100,234,567.89',\n        '$10,123',\n        '-$10123',\n      ],\n      invalid: [\n        '1.234',\n        '$1.234',\n        '1.1',\n        '$1.1',\n        '$ 32.50',\n        ' 32.50',\n        '500',\n        '10,123,456',\n        '.0001',\n        '$.001',\n        '$0.001',\n        '1,234.56',\n        '123456,123,123456',\n        '$123456,123,123456',\n        '123.4',\n        '$123.4',\n        ',123',\n        '$,123',\n        '$-,123',\n        '$',\n        '.',\n        '$.',\n        ',',\n        '$,',\n        '00',\n        '$00',\n        '$-',\n        '$-,.',\n        '-',\n        '-$',\n        '',\n        '$ ',\n        '- $',\n      ],\n    });\n\n    // ¥-##,###.## (zh-CN)\n    test({\n      validator: 'isCurrency',\n      args: [\n        {\n          symbol: '¥',\n          negative_sign_before_digits: true,\n        },\n      ],\n      valid: [\n        '123,456.78',\n        '-123,456.78',\n        '¥6,954,231',\n        '¥-6,954,231',\n        '¥10.03',\n        '¥-10.03',\n        '10.03',\n        '1.39',\n        '.03',\n        '0.10',\n        '¥-10567.01',\n        '¥0.01',\n        '¥1,234,567.89',\n        '¥10,123',\n        '¥-10,123',\n        '¥-10,123.45',\n        '10,123',\n        '10123',\n        '¥-100',\n      ],\n      invalid: [\n        '1.234',\n        '¥1.1',\n        '5,00',\n        '.0001',\n        '¥.001',\n        '¥0.001',\n        '12,34.56',\n        '123456,123,123456',\n        '123 456',\n        ',123',\n        '¥-,123',\n        '',\n        ' ',\n        '¥',\n        '¥-',\n        '¥-,.',\n        '-',\n        '- ¥',\n        '-¥',\n      ],\n    });\n\n    test({\n      validator: 'isCurrency',\n      args: [\n        {\n          negative_sign_after_digits: true,\n        },\n      ],\n      valid: [\n        '$10,123.45-',\n        '$10,123.45',\n        '$10123.45',\n        '10,123.45',\n        '10123.45',\n        '10,123',\n        '1,123,456',\n        '1123456',\n        '1.39',\n        '.03',\n        '0.10',\n        '$0.10',\n        '$0.01-',\n        '$.99-',\n        '$100,234,567.89',\n        '$10,123',\n        '10,123',\n        '10123-',\n      ],\n      invalid: [\n        '-123',\n        '1.234',\n        '$1.1',\n        '$ 32.50',\n        '500$',\n        '.0001',\n        '$.001',\n        '$0.001',\n        '12,34.56',\n        '123456,123,123456',\n        '123,4',\n        ',123',\n        '$-,123',\n        '$',\n        '.',\n        ',',\n        '00',\n        '$-',\n        '$-,.',\n        '-',\n        '-$',\n        '',\n        '- $',\n      ],\n    });\n\n    // ¥##,###.## with no negatives (zh-CN)\n    test({\n      validator: 'isCurrency',\n      args: [\n        {\n          symbol: '¥',\n          allow_negatives: false,\n        },\n      ],\n      valid: [\n        '123,456.78',\n        '¥6,954,231',\n        '¥10.03',\n        '10.03',\n        '1.39',\n        '.03',\n        '0.10',\n        '¥0.01',\n        '¥1,234,567.89',\n        '¥10,123',\n        '10,123',\n        '10123',\n        '¥100',\n      ],\n      invalid: [\n        '1.234',\n        '-123,456.78',\n        '¥-6,954,231',\n        '¥-10.03',\n        '¥-10567.01',\n        '¥1.1',\n        '¥-10,123',\n        '¥-10,123.45',\n        '5,00',\n        '¥-100',\n        '.0001',\n        '¥.001',\n        '¥-.001',\n        '¥0.001',\n        '12,34.56',\n        '123456,123,123456',\n        '123 456',\n        ',123',\n        '¥-,123',\n        '',\n        ' ',\n        '¥',\n        '¥-',\n        '¥-,.',\n        '-',\n        '- ¥',\n        '-¥',\n      ],\n    });\n\n    // R ## ###,## and R-10 123,25 (el-ZA)\n    test({\n      validator: 'isCurrency',\n      args: [\n        {\n          symbol: 'R',\n          negative_sign_before_digits: true,\n          thousands_separator: ' ',\n          decimal_separator: ',',\n          allow_negative_sign_placeholder: true,\n        },\n      ],\n      valid: [\n        '123 456,78',\n        '-10 123',\n        'R-10 123',\n        'R 6 954 231',\n        'R10,03',\n        '10,03',\n        '1,39',\n        ',03',\n        '0,10',\n        'R10567,01',\n        'R0,01',\n        'R1 234 567,89',\n        'R10 123',\n        'R 10 123',\n        'R 10123',\n        'R-10123',\n        '10 123',\n        '10123',\n      ],\n      invalid: [\n        '1,234',\n        'R -10123',\n        'R- 10123',\n        'R,1',\n        ',0001',\n        'R,001',\n        'R0,001',\n        '12 34,56',\n        '123456 123 123456',\n        ' 123',\n        '- 123',\n        '123 ',\n        '',\n        ' ',\n        'R',\n        'R- .1',\n        'R-',\n        '-',\n        '-R 10123',\n        'R00',\n        'R -',\n        '-R',\n      ],\n    });\n\n    // -€ ##.###,## (it-IT)\n    test({\n      validator: 'isCurrency',\n      args: [\n        {\n          symbol: '€',\n          thousands_separator: '.',\n          decimal_separator: ',',\n          allow_space_after_symbol: true,\n        },\n      ],\n      valid: [\n        '123.456,78',\n        '-123.456,78',\n        '€6.954.231',\n        '-€6.954.231',\n        '€ 896.954.231',\n        '-€ 896.954.231',\n        '16.954.231',\n        '-16.954.231',\n        '€10,03',\n        '-€10,03',\n        '10,03',\n        '-10,03',\n        '-1,39',\n        ',03',\n        '0,10',\n        '-€10567,01',\n        '-€ 10567,01',\n        '€ 0,01',\n        '€1.234.567,89',\n        '€10.123',\n        '10.123',\n        '-€10.123',\n        '€ 10.123',\n        '€10.123',\n        '€ 10123',\n        '10.123',\n        '-10123',\n      ],\n      invalid: [\n        '1,234',\n        '€ 1,1',\n        '50#,50',\n        '123,@€ ',\n        '€€500',\n        ',0001',\n        '€ ,001',\n        '€0,001',\n        '12.34,56',\n        '123456.123.123456',\n        '€123€',\n        '',\n        ' ',\n        '€',\n        ' €',\n        '€ ',\n        '€€',\n        ' 123',\n        '- 123',\n        '.123',\n        '-€.123',\n        '123 ',\n        '€-',\n        '- €',\n        '€ - ',\n        '-',\n        '- ',\n        '-€',\n      ],\n    });\n\n    // -##.###,## € (el-GR)\n    test({\n      validator: 'isCurrency',\n      args: [\n        {\n          symbol: '€',\n          thousands_separator: '.',\n          symbol_after_digits: true,\n          decimal_separator: ',',\n          allow_space_after_digits: true,\n        },\n      ],\n      valid: [\n        '123.456,78',\n        '-123.456,78',\n        '6.954.231 €',\n        '-6.954.231 €',\n        '896.954.231',\n        '-896.954.231',\n        '16.954.231',\n        '-16.954.231',\n        '10,03€',\n        '-10,03€',\n        '10,03',\n        '-10,03',\n        '1,39',\n        ',03',\n        '-,03',\n        '-,03 €',\n        '-,03€',\n        '0,10',\n        '10567,01€',\n        '0,01 €',\n        '1.234.567,89€',\n        '10.123€',\n        '10.123',\n        '10.123€',\n        '10.123 €',\n        '10123 €',\n        '10.123',\n        '10123',\n      ],\n      invalid: [\n        '1,234',\n        '1,1 €',\n        ',0001',\n        ',001 €',\n        '0,001€',\n        '12.34,56',\n        '123456.123.123456',\n        '€123€',\n        '',\n        ' ',\n        '€',\n        ' €',\n        '€ ',\n        ' 123',\n        '- 123',\n        '.123',\n        '-.123€',\n        '-.123 €',\n        '123 ',\n        '-€',\n        '- €',\n        '-',\n        '- ',\n      ],\n    });\n\n    // kr. -##.###,## (da-DK)\n    test({\n      validator: 'isCurrency',\n      args: [\n        {\n          symbol: 'kr.',\n          negative_sign_before_digits: true,\n          thousands_separator: '.',\n          decimal_separator: ',',\n          allow_space_after_symbol: true,\n        },\n      ],\n      valid: [\n        '123.456,78',\n        '-10.123',\n        'kr. -10.123',\n        'kr.-10.123',\n        'kr. 6.954.231',\n        'kr.10,03',\n        'kr. -10,03',\n        '10,03',\n        '1,39',\n        ',03',\n        '0,10',\n        'kr. 10567,01',\n        'kr. 0,01',\n        'kr. 1.234.567,89',\n        'kr. -1.234.567,89',\n        '10.123',\n        'kr. 10.123',\n        'kr.10.123',\n        '10123',\n        '10.123',\n        'kr.-10123',\n      ],\n      invalid: [\n        '1,234',\n        'kr.  -10123',\n        'kr.,1',\n        ',0001',\n        'kr. ,001',\n        'kr.0,001',\n        '12.34,56',\n        '123456.123.123456',\n        '.123',\n        'kr.-.123',\n        'kr. -.123',\n        '- 123',\n        '123 ',\n        '',\n        ' ',\n        'kr.',\n        ' kr.',\n        'kr. ',\n        'kr.-',\n        'kr. -',\n        'kr. - ',\n        ' - ',\n        '-',\n        '- kr.',\n        '-kr.',\n      ],\n    });\n\n    // kr. ##.###,## with no negatives (da-DK)\n    test({\n      validator: 'isCurrency',\n      args: [\n        {\n          symbol: 'kr.',\n          allow_negatives: false,\n          negative_sign_before_digits: true,\n          thousands_separator: '.',\n          decimal_separator: ',',\n          allow_space_after_symbol: true,\n        },\n      ],\n      valid: [\n        '123.456,78',\n        '10.123',\n        'kr. 10.123',\n        'kr.10.123',\n        'kr. 6.954.231',\n        'kr.10,03',\n        'kr. 10,03',\n        '10,03',\n        '1,39',\n        ',03',\n        '0,10',\n        'kr. 10567,01',\n        'kr. 0,01',\n        'kr. 1.234.567,89',\n        'kr.1.234.567,89',\n        '10.123',\n        'kr. 10.123',\n        'kr.10.123',\n        '10123',\n        '10.123',\n        'kr.10123',\n      ],\n      invalid: [\n        '1,234',\n        '-10.123',\n        'kr. -10.123',\n        'kr. -1.234.567,89',\n        'kr.-10123',\n        'kr.  -10123',\n        'kr.-10.123',\n        'kr. -10,03',\n        'kr.,1',\n        ',0001',\n        'kr. ,001',\n        'kr.0,001',\n        '12.34,56',\n        '123456.123.123456',\n        '.123',\n        'kr.-.123',\n        'kr. -.123',\n        '- 123',\n        '123 ',\n        '',\n        ' ',\n        'kr.',\n        ' kr.',\n        'kr. ',\n        'kr.-',\n        'kr. -',\n        'kr. - ',\n        ' - ',\n        '-',\n        '- kr.',\n        '-kr.',\n      ],\n    });\n\n    // ($##,###.##) (en-US, en-HK)\n    test({\n      validator: 'isCurrency',\n      args: [\n        {\n          parens_for_negatives: true,\n        },\n      ],\n      valid: [\n        '1,234',\n        '(1,234)',\n        '($6,954,231)',\n        '$10.03',\n        '(10.03)',\n        '($10.03)',\n        '1.39',\n        '.03',\n        '(.03)',\n        '($.03)',\n        '0.10',\n        '$10567.01',\n        '($0.01)',\n        '$1,234,567.89',\n        '$10,123',\n        '(10,123)',\n        '10123',\n      ],\n      invalid: [\n        '1.234',\n        '($1.1)',\n        '-$1.10',\n        '$ 32.50',\n        '500$',\n        '.0001',\n        '$.001',\n        '($0.001)',\n        '12,34.56',\n        '123456,123,123456',\n        '( 123)',\n        ',123',\n        '$-,123',\n        '',\n        ' ',\n        '  ',\n        '   ',\n        '$',\n        '$ ',\n        ' $',\n        ' 123',\n        '(123) ',\n        '.',\n        ',',\n        '00',\n        '$-',\n        '$ - ',\n        '$- ',\n        ' - ',\n        '-',\n        '- $',\n        '-$',\n        '()',\n        '( )',\n        '(  -)',\n        '(  - )',\n        '(  -  )',\n        '(-)',\n        '(-$)',\n      ],\n    });\n    // $##,###.## with no negatives (en-US, en-CA, en-AU, en-HK)\n    test({\n      validator: 'isCurrency',\n      args: [\n        { allow_negatives: false },\n      ],\n      valid: [\n        '$10,123.45',\n        '$10123.45',\n        '10,123.45',\n        '10123.45',\n        '10,123',\n        '1,123,456',\n        '1123456',\n        '1.39',\n        '.03',\n        '0.10',\n        '$0.10',\n        '$100,234,567.89',\n        '$10,123',\n        '10,123',\n      ],\n      invalid: [\n        '1.234',\n        '-1.234',\n        '-10123',\n        '-$0.01',\n        '-$.99',\n        '$1.1',\n        '-$1.1',\n        '$ 32.50',\n        '500$',\n        '.0001',\n        '$.001',\n        '$0.001',\n        '12,34.56',\n        '123456,123,123456',\n        '-123456,123,123456',\n        '123,4',\n        ',123',\n        '$-,123',\n        '$',\n        '.',\n        ',',\n        '00',\n        '$-',\n        '$-,.',\n        '-',\n        '-$',\n        '',\n        '- $',\n        '-$10,123.45',\n      ],\n    });\n\n    //  R$ ##,###.## (pt_BR)\n    test({\n      validator: 'isCurrency',\n      args: [\n        {\n          symbol: 'R$',\n          require_symbol: true,\n          allow_space_after_symbol: true,\n          symbol_after_digits: false,\n          thousands_separator: '.',\n          decimal_separator: ',',\n        },\n      ],\n      valid: [\n        'R$ 1.400,00',\n        'R$ 400,00',\n      ],\n      invalid: [\n        '$ 1.400,00',\n        '$R 1.400,00',\n      ],\n    });\n  });\n\n  it('should validate Ethereum addresses', () => {\n    test({\n      validator: 'isEthereumAddress',\n      valid: [\n        '0x0000000000000000000000000000000000000001',\n        '0x683E07492fBDfDA84457C16546ac3f433BFaa128',\n        '0x88dA6B6a8D3590e88E0FcadD5CEC56A7C9478319',\n        '0x8a718a84ee7B1621E63E680371e0C03C417cCaF6',\n        '0xFCb5AFB808b5679b4911230Aa41FfCD0cd335b42',\n      ],\n      invalid: [\n        '0xGHIJK05pwm37asdf5555QWERZCXV2345AoEuIdHt',\n        '0xFCb5AFB808b5679b4911230Aa41FfCD0cd335b422222',\n        '0xFCb5AFB808b5679b4911230Aa41FfCD0cd33',\n        '0b0110100001100101011011000110110001101111',\n        '683E07492fBDfDA84457C16546ac3f433BFaa128',\n        '1C6o5CDkLxjsVpnLSuqRs1UBFozXLEwYvU',\n      ],\n    });\n  });\n\n  it('should validate Bitcoin addresses', () => {\n    test({\n      validator: 'isBtcAddress',\n      valid: [\n        '1MUz4VMYui5qY1mxUiG8BQ1Luv6tqkvaiL',\n        'mucFNhKMYoBQYUAEsrFVscQ1YaFQPekBpg',\n        '3J98t1WpEZ73CNmQviecrnyiWrnqRhWNLy',\n        '2NFUBBRcTJbYc1D4HSCbJhKZp6YCV4PQFpQ',\n        'bc1qar0srrr7xfkvy5l643lydnw9re59gtzzwf5mdq',\n        '14qViLJfdGaP4EeHnDyJbEGQysnCpwk3gd',\n        '35bSzXvRKLpHsHMrzb82f617cV4Srnt7hS',\n        '17VZNX1SN5NtKa8UQFxwQbFeFc3iqRYhemt',\n        'bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4',\n        'tb1qxhkl607frtvjsy9nlyeg03lf6fsq947pl2pe82',\n        'bc1p5d7rjq7g6rdk2yhzks9smlaqtedr4dekq08ge8ztwac72sfr9rusxg3297',\n        'tb1pzpelffrdh9ptpaqnurwx30dlewqv57rcxfeetp86hsssk30p4cws38tr9y',\n      ],\n      invalid: [\n        '3J98t1WpEZ73CNmQviecrnyiWrnqh0WNL0',\n        '3J98t1WpEZ73CNmQviecrnyiWrnqh0WNLo',\n        '3J98t1WpEZ73CNmQviecrnyiWrnqh0WNLI',\n        '3J98t1WpEZ73CNmQviecrnyiWrnqh0WNLl',\n        '4J98t1WpEZ73CNmQviecrnyiWrnqRhWNLy',\n        '0x56F0B8A998425c53c75C4A303D4eF987533c5597',\n        'pp8skudq3x5hzw8ew7vzsw8tn4k8wxsqsv0lt0mf3g',\n        '17VZNX1SN5NlKa8UQFxwQbFeFc3iqRYhem',\n        'BC1QW508D6QEJXTDG4Y5R3ZARVAYR0C5XW7KV8F3T4',\n        'bc1p5d7rjq7g6rdk2yhzks9smlaqtedr4dekq08ge8ztwac72sfr9rusxg3291',\n        'bc1p5d7rjq7g6rdk2yhzks9smlaqtedr4dekq08ge8ztwac72sfr9rusxg329b',\n        'bc1p5d7rjq7g6rdk2yhzks9smlaqtedr4dekq08ge8ztwac72sfr9rusxg329i',\n        'bc1p5d7rjq7g6rdk2yhzks9smlaqtedr4dekq08ge8ztwac72sfr9rusxg329o',\n        'BC1P5D7RJQ7G6RDK2YHZKS9SMLAQTEDR4DEKQ08GE8ZTWAC72SFR9RUSXG3297',\n        'TB1PZPELFFRDH9PTPAQNURWX30DLEWQV57RCXFEETP86HSSSK30P4CWS38TR9Y',\n      ],\n    });\n  });\n\n  it('should validate booleans', () => {\n    test({\n      validator: 'isBoolean',\n      valid: [\n        'true',\n        'false',\n        '0',\n        '1',\n      ],\n      invalid: [\n        '1.0',\n        '0.0',\n        'true ',\n        'False',\n        'True',\n        'yes',\n      ],\n    });\n  });\n\n  it('should validate booleans with option loose set to true', () => {\n    test({\n      validator: 'isBoolean',\n      args: [\n        { loose: true },\n      ],\n      valid: [\n        'true',\n        'True',\n        'TRUE',\n        'false',\n        'False',\n        'FALSE',\n        '0',\n        '1',\n        'yes',\n        'Yes',\n        'YES',\n        'no',\n        'No',\n        'NO',\n      ],\n      invalid: [\n        '1.0',\n        '0.0',\n        'true ',\n        ' false',\n      ],\n    });\n  });\n\n  it('should validate ISO 639-1 language codes', () => {\n    test({\n      validator: 'isISO6391',\n      valid: ['ay', 'az', 'ba', 'be', 'bg'],\n      invalid: ['aj', 'al', 'pe', 'pf', 'abc', '123', ''],\n    });\n  });\n\n  const validISO8601 = [\n    '2009-12T12:34',\n    '2009',\n    '2009-05-19',\n    '2009-05-19',\n    '20090519',\n    '2009123',\n    '2009-05',\n    '2009-123',\n    '2009-222',\n    '2009-001',\n    '2009-W01-1',\n    '2009-W51-1',\n    '2009-W511',\n    '2009-W33',\n    '2009W511',\n    '2009-05-19',\n    '2009-05-19 00:00',\n    '2009-05-19 14',\n    '2009-05-19 14:31',\n    '2009-05-19 14:39:22',\n    '2009-05-19T14:39Z',\n    '2009-W21-2',\n    '2009-W21-2T01:22',\n    '2009-139',\n    '2009-05-19 14:39:22-06:00',\n    '2009-05-19 14:39:22+0600',\n    '2009-05-19 14:39:22-01',\n    '20090621T0545Z',\n    '2007-04-06T00:00',\n    '2007-04-05T24:00',\n    '2010-02-18T16:23:48.5',\n    '2010-02-18T16:23:48,444',\n    '2010-02-18T16:23:48,3-06:00',\n    '2010-02-18T16:23.4',\n    '2010-02-18T16:23,25',\n    '2010-02-18T16:23.33+0600',\n    '2010-02-18T16.23334444',\n    '2010-02-18T16,2283',\n    '2009-05-19 143922.500',\n    '2009-05-19 1439,55',\n    '2009-10-10',\n    '2020-366',\n    '2000-366',\n  ];\n\n  const invalidISO8601 = [\n    '200905',\n    '2009367',\n    '2009-',\n    '2007-04-05T24:50',\n    '2009-000',\n    '2009-M511',\n    '2009M511',\n    '2009-05-19T14a39r',\n    '2009-05-19T14:3924',\n    '2009-0519',\n    '2009-05-1914:39',\n    '2009-05-19 14:',\n    '2009-05-19r14:39',\n    '2009-05-19 14a39a22',\n    '200912-01',\n    '2009-05-19 14:39:22+06a00',\n    '2009-05-19 146922.500',\n    '2010-02-18T16.5:23.35:48',\n    '2010-02-18T16:23.35:48',\n    '2010-02-18T16:23.35:48.45',\n    '2009-05-19 14.5.44',\n    '2010-02-18T16:23.33.600',\n    '2010-02-18T16,25:23:48,444',\n    '2010-13-1',\n    'nonsense2021-01-01T00:00:00Z',\n    '2021-01-01T00:00:00Znonsense',\n  ];\n\n  it('should validate ISO 8601 dates', () => {\n    // from http://www.pelagodesign.com/blog/2009/05/20/iso-8601-date-validation-that-doesnt-suck/\n    test({\n      validator: 'isISO8601',\n      valid: validISO8601,\n      invalid: invalidISO8601,\n    });\n  });\n\n  it('should validate ISO 8601 dates, with strict = true (regression)', () => {\n    test({\n      validator: 'isISO8601',\n      args: [\n        { strict: true },\n      ],\n      valid: validISO8601,\n      invalid: invalidISO8601,\n    });\n  });\n\n  it('should validate ISO 8601 dates, with strict = true', () => {\n    test({\n      validator: 'isISO8601',\n      args: [\n        { strict: true },\n      ],\n      valid: [\n        '2000-02-29',\n        '2009-123',\n        '2009-222',\n        '2020-366',\n        '2400-366',\n      ],\n      invalid: [\n        '2010-02-30',\n        '2009-02-29',\n        '2009-366',\n        '2019-02-31',\n      ],\n    });\n  });\n\n  it('should validate ISO 8601 dates, with strictSeparator = true', () => {\n    test({\n      validator: 'isISO8601',\n      args: [\n        { strictSeparator: true },\n      ],\n      valid: [\n        '2009-12T12:34',\n        '2009',\n        '2009-05-19',\n        '2009-05-19',\n        '20090519',\n        '2009123',\n        '2009-05',\n        '2009-123',\n        '2009-222',\n        '2009-001',\n        '2009-W01-1',\n        '2009-W51-1',\n        '2009-W511',\n        '2009-W33',\n        '2009W511',\n        '2009-05-19',\n        '2009-05-19T14:39Z',\n        '2009-W21-2',\n        '2009-W21-2T01:22',\n        '2009-139',\n        '20090621T0545Z',\n        '2007-04-06T00:00',\n        '2007-04-05T24:00',\n        '2010-02-18T16:23:48.5',\n        '2010-02-18T16:23:48,444',\n        '2010-02-18T16:23:48,3-06:00',\n        '2010-02-18T16:23.4',\n        '2010-02-18T16:23,25',\n        '2010-02-18T16:23.33+0600',\n        '2010-02-18T16.23334444',\n        '2010-02-18T16,2283',\n        '2009-10-10',\n        '2020-366',\n        '2000-366',\n      ],\n      invalid: [\n        '200905',\n        '2009367',\n        '2009-',\n        '2007-04-05T24:50',\n        '2009-000',\n        '2009-M511',\n        '2009M511',\n        '2009-05-19T14a39r',\n        '2009-05-19T14:3924',\n        '2009-0519',\n        '2009-05-1914:39',\n        '2009-05-19 14:',\n        '2009-05-19r14:39',\n        '2009-05-19 14a39a22',\n        '200912-01',\n        '2009-05-19 14:39:22+06a00',\n        '2009-05-19 146922.500',\n        '2010-02-18T16.5:23.35:48',\n        '2010-02-18T16:23.35:48',\n        '2010-02-18T16:23.35:48.45',\n        '2009-05-19 14.5.44',\n        '2010-02-18T16:23.33.600',\n        '2010-02-18T16,25:23:48,444',\n        '2010-13-1',\n        '2009-05-19 00:00',\n        // Previously valid cases\n        '2009-05-19 14',\n        '2009-05-19 14:31',\n        '2009-05-19 14:39:22',\n        '2009-05-19 14:39:22-06:00',\n        '2009-05-19 14:39:22+0600',\n        '2009-05-19 14:39:22-01',\n      ],\n    });\n  });\n\n  it('should validate ISO 8601 dates, with strict = true and strictSeparator = true (regression)', () => {\n    test({\n      validator: 'isISO8601',\n      args: [\n        { strict: true, strictSeparator: true },\n      ],\n      valid: [\n        '2000-02-29',\n        '2009-123',\n        '2009-222',\n        '2020-366',\n        '2400-366',\n      ],\n      invalid: [\n        '2010-02-30',\n        '2009-02-29',\n        '2009-366',\n        '2019-02-31',\n        '2009-05-19 14',\n        '2009-05-19 14:31',\n        '2009-05-19 14:39:22',\n        '2009-05-19 14:39:22-06:00',\n        '2009-05-19 14:39:22+0600',\n        '2009-05-19 14:39:22-01',\n      ],\n    });\n  });\n\n  it('should validate ISO 15924 script codes', () => {\n    test({\n      validator: 'isISO15924',\n      valid: [\n        'Adlm',\n        'Bass',\n        'Copt',\n        'Dsrt',\n        'Egyd',\n        'Latn',\n        'Zzzz',\n      ],\n      invalid: [\n        '',\n        'arab',\n        'zzzz',\n        'Qaby',\n        'Lati',\n      ],\n    });\n  });\n\n  it('should validate RFC 3339 dates', () => {\n    test({\n      validator: 'isRFC3339',\n      valid: [\n        '2009-05-19 14:39:22-06:00',\n        '2009-05-19 14:39:22+06:00',\n        '2009-05-19 14:39:22Z',\n        '2009-05-19T14:39:22-06:00',\n        '2009-05-19T14:39:22Z',\n        '2010-02-18T16:23:48.3-06:00',\n        '2010-02-18t16:23:33+06:00',\n        '2010-02-18t16:23:33+06:00',\n        '2010-02-18t16:12:23.23334444z',\n        '2010-02-18T16:23:55.2283Z',\n        '2009-05-19 14:39:22.500Z',\n        '2009-05-19 14:39:55Z',\n        '2009-05-31 14:39:55Z',\n        '2009-05-31 14:53:60Z',\n        '2010-02-18t00:23:23.33+06:00',\n        '2010-02-18t00:23:32.33+00:00',\n        '2010-02-18t00:23:32.33+23:00',\n      ],\n      invalid: [\n        '2010-02-18t00:23:32.33+24:00',\n        '2009-05-31 14:60:55Z',\n        '2010-02-18t24:23.33+0600',\n        '2009-05-00 1439,55Z',\n        '2009-13-19 14:39:22-06:00',\n        '2009-05-00 14:39:22+0600',\n        '2009-00-1 14:39:22Z',\n        '2009-05-19T14:39:22',\n        'nonsense2021-01-01T00:00:00Z',\n        '2021-01-01T00:00:00Znonsense',\n      ],\n    });\n  });\n\n  it('should validate ISO 3166-1 numeric country codes', () => {\n    // from https://en.wikipedia.org/wiki/ISO_3166-1_numeric\n    test({\n      validator: 'isISO31661Numeric',\n      valid: [\n        '076',\n        '208',\n        '276',\n        '348',\n        '380',\n        '410',\n        '440',\n        '528',\n        '554',\n        '826',\n      ],\n      invalid: [\n        '',\n        'NL',\n        'NLD',\n        '002',\n        '197',\n        '249',\n        '569',\n        '810',\n        '900',\n        '999',\n      ],\n    });\n  });\n\n  it('should validate ISO 4217 corrency codes', () => {\n    // from https://en.wikipedia.org/wiki/ISO_4217\n    test({\n      validator: 'isISO4217',\n      valid: [\n        'AED',\n        'aed',\n        'AUD',\n        'CUP',\n        'EUR',\n        'GBP',\n        'LYD',\n        'MYR',\n        'SGD',\n        'SLE',\n        'USD',\n        'VED',\n        'SLE',\n      ],\n      invalid: [\n        '',\n        '$',\n        'US',\n        'us',\n        'AAA',\n        'aaa',\n        'RWA',\n        'EURO',\n        'euro',\n        'HRK',\n        'CUC',\n      ],\n    });\n  });\n\n  it('should validate whitelisted characters', () => {\n    test({\n      validator: 'isWhitelisted',\n      args: ['abcdefghijklmnopqrstuvwxyz-'],\n      valid: ['foo', 'foobar', 'baz-foo'],\n      invalid: ['foo bar', 'fo.bar', 'türkçe'],\n    });\n  });\n\n  it('should error on non-string input', () => {\n    test({\n      validator: 'isEmpty',\n      error: [undefined, null, [], NaN],\n    });\n  });\n\n  it('should validate dataURI', () => {\n    /* eslint-disable max-len */\n    test({\n      validator: 'isDataURI',\n      valid: [\n        'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQAQMAAAAlPW0iAAAABlBMVEUAAAD///+l2Z/dAAAAM0lEQVR4nGP4/5/h/1+G/58ZDrAz3D/McH8yw83NDDeNGe4Ug9C9zwz3gVLMDA/A6P9/AFGGFyjOXZtQAAAAAElFTkSuQmCC',\n        'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAIBAMAAAA2IaO4AAAAFVBMVEXk5OTn5+ft7e319fX29vb5+fn///++GUmVAAAALUlEQVQIHWNICnYLZnALTgpmMGYIFWYIZTA2ZFAzTTFlSDFVMwVyQhmAwsYMAKDaBy0axX/iAAAAAElFTkSuQmCC',\n        'data:application/media_control+xml;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAIBAMAAAA2IaO4AAAAFVBMVEXk5OTn5+ft7e319fX29vb5+fn///++GUmVAAAALUlEQVQIHWNICnYLZnALTgpmMGYIFWYIZTA2ZFAzTTFlSDFVMwVyQhmAwsYMAKDaBy0axX/iAAAAAElFTkSuQmCC',\n        '   data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAIBAMAAAA2IaO4AAAAFVBMVEXk5OTn5+ft7e319fX29vb5+fn///++GUmVAAAALUlEQVQIHWNICnYLZnALTgpmMGYIFWYIZTA2ZFAzTTFlSDFVMwVyQhmAwsYMAKDaBy0axX/iAAAAAElFTkSuQmCC   ',\n        'data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%22100%22%20height%3D%22100%22%3E%3Crect%20fill%3D%22%2300B1FF%22%20width%3D%22100%22%20height%3D%22100%22%2F%3E%3C%2Fsvg%3E',\n        'data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxMDAiIGhlaWdodD0iMTAwIj48cmVjdCBmaWxsPSIjMDBCMUZGIiB3aWR0aD0iMTAwIiBoZWlnaHQ9IjEwMCIvPjwvc3ZnPg==',\n        ' data:,Hello%2C%20World!',\n        ' data:,Hello World!',\n        ' data:text/plain;base64,SGVsbG8sIFdvcmxkIQ%3D%3D',\n        ' data:text/html,%3Ch1%3EHello%2C%20World!%3C%2Fh1%3E',\n        'data:,A%20brief%20note',\n        'data:text/html;charset=US-ASCII,%3Ch1%3EHello!%3C%2Fh1%3E',\n        'data:application/vnd.openxmlformats-officedocument.wordprocessingml.document;base64,dGVzdC5kb2N4',\n      ],\n      invalid: [\n        'dataxbase64',\n        'data:HelloWorld',\n        'data:,A%20brief%20invalid%20[note',\n        'file:text/plain;base64,SGVsbG8sIFdvcmxkIQ%3D%3D',\n        'data:text/html;charset=,%3Ch1%3EHello!%3C%2Fh1%3E',\n        'data:text/html;charset,%3Ch1%3EHello!%3C%2Fh1%3E', 'data:base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQAQMAAAAlPW0iAAAABlBMVEUAAAD///+l2Z/dAAAAM0lEQVR4nGP4/5/h/1+G/58ZDrAz3D/McH8yw83NDDeNGe4Ug9C9zwz3gVLMDA/A6P9/AFGGFyjOXZtQAAAAAElFTkSuQmCC',\n        '',\n        'http://wikipedia.org',\n        'base64',\n        'iVBORw0KGgoAAAANSUhEUgAAABAAAAAQAQMAAAAlPW0iAAAABlBMVEUAAAD///+l2Z/dAAAAM0lEQVR4nGP4/5/h/1+G/58ZDrAz3D/McH8yw83NDDeNGe4Ug9C9zwz3gVLMDA/A6P9/AFGGFyjOXZtQAAAAAElFTkSuQmCC',\n      ],\n    });\n    /* eslint-enable max-len */\n  });\n\n\n  it('should validate magnetURI', () => {\n    /* eslint-disable max-len */\n    test({\n      validator: 'isMagnetURI',\n      valid: [\n        'magnet:?xt.1=urn:sha1:ABCDEFGHIJKLMNOPQRSTUVWXYZ123456&xt.2=urn:sha1:ABCDEFGHIJKLMNOPQRSTUVWXYZ123456',\n        'magnet:?xt=urn:btih:ABCDEFGHIJKLMNOPQRSTUVWXYZ12345678901234&dn=helloword2000&tr=udp://helloworld:1337/announce',\n        'magnet:?xt=urn:btih:ABCDEFGHIJKLMNOPQRSTUVWXYZ12345678901234&dn=foo',\n        'magnet:?xt=urn:btih:ABCDEFGHIJKLMNOPQRSTUVWXYZ12345678901234&dn=&tr=&nonexisting=hello world',\n        'magnet:?xt=urn:md5:ABCDEFGHIJKLMNOPQRSTUVWXYZ123456',\n        'magnet:?xt=urn:tree:tiger:ABCDEFGHIJKLMNOPQRSTUVWXYZ123456',\n        'magnet:?xt=urn:ed2k:ABCDEFGHIJKLMNOPQRSTUVWXYZ12345678901234',\n        'magnet:?tr=udp://helloworld:1337/announce&xt=urn:btih:ABCDEFGHIJKLMNOPQRSTUVWXYZ12345678901234',\n        'magnet:?xt=urn:btmh:1220caf1e1c30e81cb361b9ee167c4aa64228a7fa4fa9f6105232b28ad099f3a302e',\n      ],\n      invalid: [\n        ':?xt=urn:btih:ABCDEFGHIJKLMNOPQRSTUVWXYZ12345678901234',\n        'xt=urn:btih:ABCDEFGHIJKLMNOPQRSTUVWXYZ12345678901234',\n        'magneta:?xt=urn:btih:ABCDEFGHIJKLMNOPQRSTUVWXYZ12345678901234',\n        'magnet:?xt=uarn:btih:ABCDEFGHIJKLMNOPQRSTUVWXYZ12345678901234',\n        'magnet:?xt=urn:btihz',\n        'magnet::?xt=urn:btih:UHWY2892JNEJ2GTEYOMDNU67E8ICGICYE92JDUGH',\n        'magnet:?xt:btih:ABCDEFGHIJKLMNOPQRSTUVWXYZ',\n        'magnet:?xt:urn:nonexisting:ABCDEFGHIJKLMNOPQRSTUVWXYZ12345678901234',\n        'magnet:?xt.2=urn:btih:ABCDEFGHIJKLMNOPQRSTUVWXYZ12345678901234',\n        'magnet:?xt=urn:ed2k:ABCDEFGHIJKLMNOPQRSTUVWXYZ12345678901234567890123456789ABCD',\n        'magnet:?xt=urn:btmh:1120caf1e1c30e81cb361b9ee167c4aa64228a7fa4fa9f6105232b28ad099f3a302e',\n        'magnet:?ttxt=urn:btmh:1220caf1e1c30e81cb361b9ee167c4aa64228a7fa4fa9f6105232b28ad099f3a302e',\n      ],\n    });\n    /* eslint-enable max-len */\n  });\n\n\n  it('should validate LatLong', () => {\n    test({\n      validator: 'isLatLong',\n      valid: [\n        '(-17.738223, 85.605469)',\n        '(-12.3456789, +12.3456789)',\n        '(-60.978437, -0.175781)',\n        '(77.719772, -37.529297)',\n        '(7.264394, 165.058594)',\n        '0.955766, -19.863281',\n        '(31.269161,164.355469)',\n        '+12.3456789, -12.3456789',\n        '-15.379543, -137.285156',\n        '(11.770570, -162.949219)',\n        '-55.034319, 113.027344',\n        '58.025555, 36.738281',\n        '55.720923,-28.652344',\n        '-90.00000,-180.00000',\n        '(-71, -146)',\n        '(-71.616864, -146.616864)',\n        '-0.55, +0.22',\n        '90, 180',\n        '+90, -180',\n        '-90,+180',\n        '90,180',\n        '0, 0',\n      ],\n      invalid: [\n        '(020.000000, 010.000000000)',\n        '89.9999999989, 360.0000000',\n        '90.1000000, 180.000000',\n        '+90.000000, -180.00001',\n        '090.0000, 0180.0000',\n        '126, -158',\n        '(-126.400010, -158.400010)',\n        '-95, -96',\n        '-95.738043, -96.738043',\n        '137, -148',\n        '(-137.5942, -148.5942)',\n        '(-120, -203)',\n        '(-119, -196)',\n        '+119.821728, -196.821728',\n        '(-110, -223)',\n        '-110.369532, 223.369532',\n        '(-120.969949, +203.969949)',\n        '-116, -126',\n        '-116.894222, -126.894222',\n        '-112, -160',\n        '-112.96381, -160.96381',\n        '-90., -180.',\n        '+90.1, -180.1',\n        '(-17.738223, 85.605469',\n        '0.955766, -19.863281)',\n        '+,-',\n        '(,)',\n        ',',\n        ' ',\n      ],\n    });\n\n    test({\n      validator: 'isLatLong',\n      args: [{\n        checkDMS: true,\n      }],\n      valid: [\n        '40° 26′ 46″ N, 79° 58′ 56″ W',\n        '40° 26′ 46″ S, 79° 58′ 56″ E',\n        '90° 0′ 0″ S, 180° 0′ 0″ E',\n        '40° 26′ 45.9996″ N, 79° 58′ 55.2″ E',\n        '40° 26′ 46″ n, 79° 58′ 56″ w',\n        '40°26′46″s, 79°58′56″e',\n        '11° 0′ 0.005″ S, 180° 0′ 0″ E',\n        '40°26′45.9996″N, 79°58′55.2″E',\n\n      ],\n      invalid: [\n        '100° 26′ 46″ N, 79° 70′ 56″ W',\n        '40° 89′ 46″ S, 79° 58′ 100″ E',\n        '40° 26.445′ 45″ N, 79° 58′ 55.2″ E',\n        '40° 46″ N, 79° 58′ 56″ W',\n      ],\n    });\n  });\n\n  it('should validate postal code', () => {\n    const fixtures = [\n      {\n        locale: 'AU',\n        valid: [\n          '4000',\n          '2620',\n          '3000',\n          '2017',\n          '0800',\n        ],\n      },\n      {\n        locale: 'BD',\n        valid: [\n          '1000',\n          '1200',\n          '1300',\n          '1400',\n          '1500',\n          '2000',\n          '3000',\n          '4000',\n          '5000',\n          '6000',\n          '7000',\n          '8000',\n          '9000',\n          '9400',\n          '9499',\n        ],\n        invalid: [\n          '0999',\n          '9500',\n          '10000',\n          '12345',\n          '123',\n          '123456',\n          'abcd',\n          '123a',\n          'a123',\n          '12 34',\n          '12-34',\n        ],\n      },\n      {\n        locale: 'BY',\n        valid: [\n          '225320',\n          '211120',\n          '247710',\n          '231960',\n        ],\n        invalid: [\n          'test 225320',\n          '211120 test',\n          '317543',\n          '267946',\n        ],\n      },\n      {\n        locale: 'CA',\n        valid: [\n          'L4T 0A5',\n          'G1A-0A2',\n          'A1A 1A1',\n          'X0A-0H0',\n          'V5K 0A1',\n          'A1C 3S4',\n          'A1C3S4',\n          'a1c 3s4',\n          'V9A 7N2',\n          'B3K 5X5',\n          'K8N 5W6',\n          'K1A 0B1',\n          'B1Z 0B9',\n        ],\n        invalid: [\n          '        ',\n          'invalid value',\n          'a1a1a',\n          'A1A  1A1',\n          'K1A 0D1',\n          'W1A 0B1',\n          'Z1A 0B1',\n        ],\n      },\n      {\n        locale: 'CO',\n        valid: [\n          '050034',\n          '110221',\n          '441029',\n          '910001',\n        ],\n        invalid: [\n          '11001',\n          '000000',\n          '109999',\n          '329999',\n        ],\n      },\n      {\n        locale: 'ES',\n        valid: [\n          '01001',\n          '52999',\n          '27880',\n        ],\n        invalid: [\n          '123',\n          '1234',\n          '53000',\n          '052999',\n          '0123',\n          'abcde',\n        ],\n      },\n      {\n        locale: 'JP',\n        valid: [\n          '135-0000',\n          '874-8577',\n          '669-1161',\n          '470-0156',\n          '672-8031',\n        ],\n      },\n      {\n        locale: 'GR',\n        valid: [\n          '022 93',\n          '29934',\n          '90293',\n          '299 42',\n          '94944',\n        ],\n      },\n      {\n        locale: 'GB',\n        valid: [\n          'TW8 9GS',\n          'BS98 1TL',\n          'DE99 3GG',\n          'DE55 4SW',\n          'DH98 1BT',\n          'DH99 1NS',\n          'GIR0aa',\n          'SA99',\n          'W1N 4DJ',\n          'AA9A 9AA',\n          'AA99 9AA',\n          'BS98 1TL',\n          'DE993GG',\n        ],\n      },\n      {\n        locale: 'FR',\n        valid: [\n          '75008',\n          '44522',\n          '38499',\n          '39940',\n          '01000',\n        ],\n        invalid: [\n          '44 522',\n          '38 499',\n          '96000',\n          '98025',\n        ],\n      },\n      {\n        locale: 'ID',\n        valid: [\n          '10210',\n          '40181',\n          '55161',\n          '60233',\n        ],\n      },\n      {\n        locale: 'IE',\n        valid: [\n          'A65 TF12',\n          'A6W U9U9',\n        ],\n        invalid: [\n          '123',\n          '75690HG',\n          'AW5  TF12',\n          'AW5 TF12',\n          '756  90HG',\n          'A65T F12',\n          'O62 O1O2',\n        ],\n      },\n      {\n        locale: 'IN',\n        valid: [\n          '364240',\n          '360005',\n        ],\n        invalid: [\n          '123',\n          '012345',\n          '011111',\n          '101123',\n          '291123',\n          '351123',\n          '541123',\n          '551123',\n          '651123',\n          '661123',\n          '861123',\n          '871123',\n          '881123',\n          '891123',\n        ],\n      },\n      {\n        locale: 'IL',\n        valid: [\n          '10200',\n          '10292',\n          '10300',\n          '10329',\n          '3885500',\n          '4290500',\n          '4286000',\n          '7080000',\n        ],\n        invalid: [\n          '123',\n          '012345',\n          '011111',\n          '101123',\n          '291123',\n          '351123',\n          '541123',\n          '551123',\n          '651123',\n          '661123',\n          '861123',\n          '871123',\n          '881123',\n          '891123',\n        ],\n      },\n      {\n        locale: 'BG',\n        valid: [\n          '1000',\n        ],\n      },\n      {\n        locale: 'IR',\n        valid: [\n          '4351666456',\n          '5614736867',\n        ],\n        invalid: [\n          '43516 6456',\n          '123443516 6456',\n          '891123',\n          'test 4351666456',\n          '4351666456 test',\n          'test 4351666456 test',\n        ],\n      },\n      {\n        locale: 'CZ',\n        valid: [\n          '20134',\n          '392 90',\n          '39919',\n          '938 29',\n          '39949',\n        ],\n      },\n      {\n        locale: 'NL',\n        valid: [\n          '1012 SZ',\n          '3432FE',\n          '1118 BH',\n          '3950IO',\n          '3997 GH',\n        ],\n        invalid: [\n          '1234',\n          '0603 JV',\n          '5194SA',\n          '9164 SD',\n          '1841SS',\n        ],\n      },\n      {\n        locale: 'NP',\n        valid: [\n          '10811',\n          '32600',\n          '56806',\n          '977',\n        ],\n        invalid: [\n          '11977',\n          'asds',\n          '13 32',\n          '-977',\n          '97765',\n        ],\n      },\n      {\n        locale: 'PL',\n        valid: [\n          '47-260',\n          '12-930',\n          '78-399',\n          '39-490',\n          '38-483',\n          '05-800',\n          '54-060',\n        ],\n      },\n      {\n        locale: 'TW',\n        valid: [\n          '360',\n          '90312',\n          '399',\n          '935',\n          '38842',\n          '546023',\n        ],\n      },\n      {\n        locale: 'LI',\n        valid: [\n          '9485',\n          '9497',\n          '9491',\n          '9489',\n          '9496',\n        ],\n      },\n      {\n        locale: 'PT',\n        valid: [\n          '4829-489',\n          '0294-348',\n          '8156-392',\n        ],\n      },\n      {\n        locale: 'SE',\n        valid: [\n          '12994',\n          '284 39',\n          '39556',\n          '489 39',\n          '499 49',\n        ],\n      },\n      {\n        locale: 'AD',\n        valid: [\n          'AD100',\n          'AD200',\n          'AD300',\n          'AD400',\n          'AD500',\n          'AD600',\n          'AD700',\n        ],\n      },\n      {\n        locale: 'UA',\n        valid: [\n          '65000',\n          '65080',\n          '01000',\n          '51901',\n          '51909',\n          '49125',\n        ],\n      },\n      {\n        locale: 'BR',\n        valid: [\n          '39100-000',\n          '22040-020',\n          '39400-152',\n          '39100000',\n          '22040020',\n          '39400152',\n        ],\n        invalid: [\n          '79800A12',\n          '13165-00',\n          '38175-abc',\n          '81470-2763',\n          '78908',\n          '13010|111',\n        ],\n      },\n      {\n        locale: 'NZ',\n        valid: [\n          '7843',\n          '3581',\n          '0449',\n          '0984',\n          '4144',\n        ],\n      },\n      {\n        locale: 'PK',\n        valid: [\n          '25000',\n          '44000',\n          '54810',\n          '74200',\n        ],\n        invalid: [\n          '5400',\n          '540000',\n          'NY540',\n          '540CA',\n          '540-0',\n        ],\n      },\n      {\n        locale: 'MG',\n        valid: [\n          '101',\n          '303',\n          '407',\n          '512',\n        ],\n      },\n      {\n        locale: 'MT',\n        valid: [\n          'VLT2345',\n          'VLT 2345',\n          'ATD1234',\n          'MSK8723',\n        ],\n      },\n      {\n        locale: 'MY',\n        valid: [\n          '56000',\n          '12000',\n          '79502',\n        ],\n      },\n      {\n        locale: 'PR',\n        valid: [\n          '00979',\n          '00631',\n          '00786',\n          '00987',\n        ],\n      },\n      {\n        locale: 'AZ',\n        valid: [\n          'AZ0100',\n          'AZ0121',\n          'AZ3500',\n        ],\n        invalid: [\n          '',\n          ' AZ0100',\n          'AZ100',\n          'AZ34340',\n          'EN2020',\n          'AY3030',\n        ],\n      },\n      {\n        locale: 'DO',\n        valid: [\n          '12345',\n        ],\n        invalid: [\n          'A1234',\n          '123',\n          '123456',\n        ],\n      },\n      {\n        locale: 'HT',\n        valid: [\n          'HT1234',\n        ],\n        invalid: [\n          'HT123',\n          'HT12345',\n          'AA1234',\n        ],\n      },\n      {\n        locale: 'TH',\n        valid: [\n          '10250',\n          '72170',\n          '12140',\n        ],\n        invalid: [\n          'T1025',\n          'T72170',\n          '12140TH',\n        ],\n      },\n      {\n        locale: 'SG',\n        valid: [\n          '308215',\n          '546080',\n        ],\n      },\n      {\n        locale: 'CN',\n        valid: [\n          '150237',\n          '100000',\n        ],\n        invalid: [\n          '141234',\n          '386789',\n          'ab1234',\n        ],\n      },\n      {\n        locale: 'KR',\n        valid: [\n          '17008',\n          '339012',\n        ],\n        invalid: [\n          '1412347',\n          'ab1234',\n        ],\n      },\n      {\n        locale: 'LK',\n        valid: [\n          '11500',\n          '22200',\n          '10370',\n          '43000',\n        ],\n        invalid: [\n          '1234',\n          '789389',\n          '982',\n        ],\n      },\n      {\n        locale: 'BA',\n        valid: [\n          '76300',\n          '71000',\n          '75412',\n          '76100',\n          '88202',\n          '88313',\n        ],\n        invalid: [\n          '1234',\n          '789389',\n          '98212',\n          '11000',\n        ],\n      },\n      {\n        locale: 'MC',\n        valid: [\n          '98000',\n          '98025',\n        ],\n        invalid: [\n          '123412',\n          'ab1234',\n        ],\n      },\n    ];\n\n    let allValid = [];\n\n    // Test fixtures\n    fixtures.forEach((fixture) => {\n      if (fixture.valid) allValid = allValid.concat(fixture.valid);\n      test({\n        validator: 'isPostalCode',\n        valid: fixture.valid,\n        invalid: fixture.invalid,\n        args: [fixture.locale],\n      });\n    });\n\n    // Test generics\n    test({\n      validator: 'isPostalCode',\n      valid: [\n        ...allValid,\n        '1234',\n        '6900',\n        '1292',\n        '9400',\n        '27616',\n        '90210',\n        '10001',\n        '21201',\n        '33142',\n        '060623',\n        '123456',\n        '293940',\n        '002920',\n      ],\n      invalid: [\n        'asdf',\n        '1',\n        'ASDFGJKLmZXJtZtesting123',\n        'Vml2YW11cyBmZXJtZtesting123',\n        '48380480343',\n        '29923-329393-2324',\n        '4294924224',\n        '13',\n      ],\n      args: ['any'],\n    });\n  });\n\n  it('should error on invalid locale', () => {\n    test({\n      validator: 'isPostalCode',\n      args: ['is-NOT'],\n      error: [\n        '293940',\n        '1234',\n      ],\n    });\n  });\n\n  it('should validate MIME types', () => {\n    test({\n      validator: 'isMimeType',\n      valid: [\n        'application/json',\n        'application/xhtml+xml',\n        'audio/mp4',\n        'image/bmp',\n        'font/woff2',\n        'message/http',\n        'model/vnd.gtw',\n        'application/media_control+xml',\n        'multipart/form-data',\n        'multipart/form-data; boundary=something',\n        'multipart/form-data; charset=utf-8; boundary=something',\n        'multipart/form-data; boundary=something; charset=utf-8',\n        'multipart/form-data; boundary=something; charset=\"utf-8\"',\n        'multipart/form-data; boundary=\"something\"; charset=utf-8',\n        'multipart/form-data; boundary=\"something\"; charset=\"utf-8\"',\n        'text/css',\n        'text/plain; charset=utf8',\n        'Text/HTML;Charset=\"utf-8\"',\n        'text/html;charset=UTF-8',\n        'Text/html;charset=UTF-8',\n        'text/html; charset=us-ascii',\n        'text/html; charset=us-ascii (Plain text)',\n        'text/html; charset=\"us-ascii\"',\n        'video/mp4',\n      ],\n      invalid: [\n        '',\n        ' ',\n        '/',\n        'f/b',\n        'application',\n        'application\\\\json',\n        'application/json/text',\n        'application/json; charset=utf-8',\n        'audio/mp4; charset=utf-8',\n        'image/bmp; charset=utf-8',\n        'font/woff2; charset=utf-8',\n        'message/http; charset=utf-8',\n        'model/vnd.gtw; charset=utf-8',\n        'video/mp4; charset=utf-8',\n      ],\n    });\n  });\n\n\n  it('should validate ISO6346 shipping containerID', () => {\n    test({\n      validator: 'isISO6346',\n      valid: [\n        'HLXU2008419',\n        'TGHU7599330',\n        'ECMU4657496',\n        'MEDU6246078',\n        'YMLU2809976',\n        'MRKU0046221',\n        'EMCU3811879',\n        'OOLU8643084',\n        'HJCU1922713',\n        'QJRZ123456',\n      ],\n      invalid: [\n        'OOLU1922713',\n        'HJCU1922413',\n        'FCUI985619',\n        'ECMJ4657496',\n        'TBJA7176445',\n        'AFFU5962593',\n      ],\n    });\n  });\n  it('should validate ISO6346 shipping containerID', () => {\n    test({\n      validator: 'isFreightContainerID',\n      valid: [\n        'HLXU2008419',\n        'TGHU7599330',\n        'ECMU4657496',\n        'MEDU6246078',\n        'YMLU2809976',\n        'MRKU0046221',\n        'EMCU3811879',\n        'OOLU8643084',\n        'HJCU1922713',\n        'QJRZ123456',\n      ],\n      invalid: [\n        'OOLU1922713',\n        'HJCU1922413',\n        'FCUI985619',\n        'ECMJ4657496',\n        'TBJA7176445',\n        'AFFU5962593',\n      ],\n    });\n  });\n\n  it('should validate ISO6346 shipping container IDs with checksum digit 10 represented as 0', () => {\n    test({\n      validator: 'isISO6346',\n      valid: [\n        'APZU3789870',\n        'TEMU1002030',\n        'DFSU1704420',\n        'CMAU2221480',\n        'SEGU5060260',\n        'FCIU8939320',\n        'TRHU3495670',\n        'MEDU3871410',\n        'CMAU2184010',\n        'TCLU2265970',\n      ],\n      invalid: [\n        'APZU3789871', // Incorrect check digit\n        'TEMU1002031',\n        'DFSU1704421',\n        'CMAU2221481',\n        'SEGU5060261',\n      ],\n    });\n  });\n  it('should validate ISO6346 shipping container IDs with checksum digit 10 represented as 0', () => {\n    test({\n      validator: 'isFreightContainerID',\n      valid: [\n        'APZU3789870',\n        'TEMU1002030',\n        'DFSU1704420',\n        'CMAU2221480',\n        'SEGU5060260',\n        'FCIU8939320',\n        'TRHU3495670',\n        'MEDU3871410',\n        'CMAU2184010',\n        'TCLU2265970',\n      ],\n      invalid: [\n        'APZU3789871', // Incorrect check digit\n        'TEMU1002031',\n        'DFSU1704421',\n        'CMAU2221481',\n        'SEGU5060261',\n      ],\n    });\n  });\n\n  // EU-UK valid numbers sourced from https://ec.europa.eu/taxation_customs/tin/specs/FS-TIN%20Algorithms-Public.docx or constructed by @tplessas.\n  it('should validate taxID', () => {\n    test({\n      validator: 'isTaxID',\n      args: ['bg-BG'],\n      valid: [\n        '7501010010',\n        '0101010012',\n        '0111010010',\n        '7521010014',\n        '7541010019'],\n      invalid: [\n        '750101001',\n        '75010100101',\n        '75-01010/01 0',\n        '7521320010',\n        '7501010019'],\n    });\n    test({\n      validator: 'isTaxID',\n      args: ['cs-CZ'],\n      valid: [\n        '530121999',\n        '530121/999',\n        '530121/9990',\n        '5301219990',\n        '1602295134',\n        '5451219994',\n        '0424175466',\n        '0532175468',\n        '7159079940'],\n      invalid: [\n        '53-0121 999',\n        '530121000',\n        '960121999',\n        '0124175466',\n        '0472301754',\n        '1975116400',\n        '7159079945'],\n    });\n    test({\n      validator: 'isTaxID',\n      args: ['de-AT'],\n      valid: [\n        '931736581',\n        '93-173/6581',\n        '93--173/6581'],\n      invalid: [\n        '999999999',\n        '93 173 6581',\n        '93-173/65811',\n        '93-173/658'],\n    });\n    test({\n      validator: 'isTaxID',\n      args: ['de-DE'],\n      valid: [\n        '26954371827',\n        '86095742719',\n        '65929970489',\n        '79608434120',\n        '659/299/7048/9'],\n      invalid: [\n        '26954371828',\n        '86095752719',\n        '8609575271',\n        '860957527190',\n        '65299970489',\n        '65999970489',\n        '6592997048-9'],\n    });\n    test({\n      validator: 'isTaxID',\n      args: ['dk-DK'],\n      valid: [\n        '010111-1113',\n        '0101110117',\n        '2110084008',\n        '2110489008',\n        '2110595002',\n        '2110197007',\n        '0101110117',\n        '0101110230'],\n      invalid: [\n        '010111/1113',\n        '010111111',\n        '01011111133',\n        '2110485008',\n        '2902034000',\n        '0101110630'],\n    });\n    test({\n      validator: 'isTaxID',\n      args: ['el-CY'],\n      valid: [\n        '00123123T',\n        '99652156X'],\n      invalid: [\n        '99652156A',\n        '00124123T',\n        '00123123',\n        '001123123T',\n        '00 12-3123/T'],\n    });\n    test({\n      validator: 'isTaxID',\n      args: ['el-GR'],\n      valid: [\n        '758426713',\n        '032792320',\n        '054100004'],\n      invalid: [\n        '054100005',\n        '05410000',\n        '0541000055',\n        '05 4100005',\n        '05-410/0005',\n        '658426713',\n        '558426713'],\n    });\n    test({\n      validator: 'isTaxID',\n      args: ['en-CA'],\n      valid: [\n        '000000000',\n        '521719666',\n        '469317481',\n        '120217450',\n        '480534858',\n        '325268597',\n        '336475660',\n        '744797853',\n        '130692544',\n        '046454286',\n      ],\n      invalid: [\n        '        ',\n        'any value',\n        '012345678',\n        '111111111',\n        '999999999',\n        '657449110',\n        '74 47 978 53',\n        '744 797 853',\n        '744-797-853',\n        '981062432',\n        '267500713',\n        '2675o0713',\n        '70597312',\n        '7058973122',\n        '069437151',\n        '046454281',\n        '146452286',\n        '30x92544',\n        '30692544',\n      ],\n    });\n    test({\n      validator: 'isTaxID',\n      args: ['en-GB'],\n      valid: [\n        '1234567890',\n        'AA123456A',\n        'AA123456 '],\n      invalid: [\n        'GB123456A',\n        '123456789',\n        '12345678901',\n        'NK123456A',\n        'TN123456A',\n        'ZZ123456A',\n        'GB123456Z',\n        'DM123456A',\n        'AO123456A',\n        'GB-123456A',\n        'GB 123456 A',\n        'GB123456  '],\n    });\n    test({\n      validator: 'isTaxID',\n      args: ['en-IE'],\n      valid: [\n        '1234567T',\n        '1234567TW',\n        '1234577W',\n        '1234577WW',\n        '1234577IA'],\n      invalid: [\n        '1234567',\n        '1234577WWW',\n        '1234577A',\n        '1234577JA'],\n    });\n    test({\n      validator: 'isTaxID',\n      args: ['en-US'],\n      valid: [\n        '01-1234567',\n        '01 1234567',\n        '011234567',\n        '10-1234567',\n        '02-1234567',\n        '67-1234567',\n        '15-1234567',\n        '31-1234567',\n        '99-1234567'],\n      invalid: [\n        '0-11234567',\n        '01#1234567',\n        '01  1234567',\n        '01 1234 567',\n        '07-1234567',\n        '28-1234567',\n        '96-1234567'],\n    });\n    test({\n      validator: 'isTaxID',\n      args: ['es-AR'],\n      valid: [\n        '20271633638',\n        '23274986069',\n        '27333234519',\n        '30678561165',\n        '33693450239',\n        '30534868460',\n        '23111111129',\n        '34557619099'],\n      invalid: [\n        '20-27163363-8',\n        '20.27163363.8',\n        '33693450231',\n        '69345023',\n        '693450233123123',\n        '3369ew50231',\n        '34557619095'],\n    });\n    test({\n      validator: 'isTaxID',\n      args: ['es-ES'],\n      valid: [\n        '00054237A',\n        '54237A',\n        'X1234567L',\n        'Z1234567R',\n        'M2812345C',\n        'Y2812345B'],\n      invalid: [\n        'M2812345CR',\n        'A2812345C',\n        '0/005 423-7A',\n        '00054237U'],\n    });\n    test({\n      validator: 'isTaxID',\n      args: ['et-EE'],\n      valid: [\n        '10001010080',\n        '46304280206',\n        '37102250382',\n        '32708101201'],\n      invalid: [\n        '46304280205',\n        '61002293333',\n        '4-6304 28/0206',\n        '4630428020',\n        '463042802066'],\n    });\n    test({\n      validator: 'isTaxID',\n      args: ['fi-FI'],\n      valid: [\n        '131052-308T',\n        '131002+308W',\n        '131019A3089'],\n      invalid: [\n        '131052308T',\n        '131052-308TT',\n        '131052S308T',\n        '13 1052-308/T',\n        '290219A1111'],\n    });\n    test({\n      validator: 'isTaxID',\n      args: ['fr-BE'],\n      valid: [\n        '00012511119'],\n    });\n    test({\n      validator: 'isTaxID',\n      args: ['fr-FR'],\n      valid: [\n        '30 23 217 600 053',\n        '3023217600053'],\n      invalid: [\n        '30 2 3 217 600 053',\n        '3 023217-600/053',\n        '3023217600052',\n        '3023217500053',\n        '30232176000534',\n        '302321760005'],\n    });\n    test({\n      validator: 'isTaxID',\n      args: ['nl-BE'],\n      valid: [\n        '00012511148',\n        '00/0125-11148',\n        '00000011115'],\n      invalid: [\n        '00 01 2511148',\n        '01022911148',\n        '00013211148',\n        '0001251114',\n        '000125111480',\n        '00012511149'],\n    });\n    test({\n      validator: 'isTaxID',\n      args: ['fr-LU'],\n      valid: [\n        '1893120105732'],\n      invalid: [\n        '189312010573',\n        '18931201057322',\n        '1893 12-01057/32',\n        '1893120105742',\n        '1893120105733'],\n    });\n    test({\n      validator: 'isTaxID',\n      args: ['lb-LU'],\n      invalid: [\n        '2016023005732'],\n    });\n    test({\n      validator: 'isTaxID',\n      args: ['hr-HR'],\n      valid: [\n        '94577403194'],\n      invalid: [\n        '94 57-7403/194',\n        '9457740319',\n        '945774031945',\n        '94577403197',\n        '94587403194'],\n    });\n    test({\n      validator: 'isTaxID',\n      args: ['hu-HU'],\n      valid: [\n        '8071592153'],\n      invalid: [\n        '80 71-592/153',\n        '80715921534',\n        '807159215',\n        '8071592152',\n        '8071582153'],\n    });\n    test({\n      validator: 'isTaxID',\n      args: ['lt-LT'],\n      valid: [\n        '33309240064'],\n    });\n    test({\n      validator: 'isTaxID',\n      args: ['it-IT'],\n      valid: [\n        'DMLPRY77D15H501F',\n        'AXXFAXTTD41H501D'],\n      invalid: [\n        'DML PRY/77D15H501-F',\n        'DMLPRY77D15H501',\n        'DMLPRY77D15H501FF',\n        'AAPPRY77D15H501F',\n        'DMLAXA77D15H501F',\n        'AXXFAX90A01Z001F',\n        'DMLPRY77B29H501F',\n        'AXXFAX3TD41H501E'],\n    });\n    test({\n      validator: 'isTaxID',\n      args: ['lv-LV'],\n      valid: [\n        '01011012344',\n        '32579461005',\n        '01019902341',\n        '325794-61005'],\n      invalid: [\n        '010110123444',\n        '0101101234',\n        '01001612345',\n        '290217-22343'],\n    });\n    test({\n      validator: 'isTaxID',\n      args: ['mt-MT'],\n      valid: [\n        '1234567A',\n        '882345608',\n        '34581M',\n        '199Z'],\n      invalid: [\n        '812345608',\n        '88234560',\n        '8823456088',\n        '11234567A',\n        '12/34-567 A',\n        '88 23-456/08',\n        '1234560A',\n        '0000000M',\n        '3200100G'],\n    });\n    test({\n      validator: 'isTaxID',\n      args: ['nl-NL'],\n      valid: [\n        '174559434'],\n      invalid: [\n        '17455943',\n        '1745594344',\n        '17 455-94/34'],\n    });\n    test({\n      validator: 'isTaxID',\n      args: ['pl-PL'],\n      valid: [\n        '2234567895',\n        '02070803628',\n        '02870803622',\n        '02670803626',\n        '01510813623'],\n      invalid: [\n        '020708036285',\n        '223456789',\n        '22 345-678/95',\n        '02 070-8036/28',\n        '2234567855',\n        '02223013623'],\n    });\n    test({\n      validator: 'isTaxID',\n      args: ['pt-BR'],\n      valid: [\n        // CPF (persons)\n        '35161990910',\n        '74407265027',\n        '12345678909',\n        '11144477735',\n        '52998224725',\n        // CPF formatted (XXX.XXX.XXX-XX)\n        '123.456.789-09',\n        '111.444.777-35',\n        '529.982.247-25',\n        // CNPJ numeric (legacy format)\n        '05423994000172',\n        '11867044000130',\n        // CNPJ alphanumeric (new format starting July 2026)\n        '12ABC34501DE35', // Example from official SERPRO documentation\n        '12abc34501de35', // Lowercase should also work\n      ],\n      invalid: [\n        'ABCDEFGH',\n        '170.691.440-72',\n        '000.000.000-00',\n        '111.111.111-11',\n        '123.456.789-00',\n        '12345678900',\n        '123',\n        '123456789012',\n        '11494282142',\n        '74405265037',\n        '11111111111',\n        '48469799384',\n        '94.592.973/0001-82',\n        '28592361000192',\n        '11111111111111',\n        '111111111111112',\n        '61938188550993',\n        '82168365502729',\n        // Invalid alphanumeric CNPJs\n        '12ABC34501DE00', // Wrong check digits\n        '12ABC34501DE99', // Wrong check digits\n        'AAAAAAAAAAAAAA', // All same characters\n        '00000000000000', // All zeros\n        '12.ABC.345/01DE-35', // Formatted (not accepted)\n      ],\n    });\n    test({\n      validator: 'isTaxID',\n      args: ['pt-PT'],\n      valid: [\n        '299999998',\n        '299992020'],\n      invalid: [\n        '2999999988',\n        '29999999',\n        '29 999-999/8'],\n    });\n    test({\n      validator: 'isTaxID',\n      args: ['ro-RO'],\n      valid: [\n        '8001011234563',\n        '9000123456789',\n        '1001011234560',\n        '3001011234564',\n        '5001011234568'],\n      invalid: [\n        '5001011234569',\n        '500 1011-234/568',\n        '500101123456',\n        '50010112345688',\n        '5001011504568',\n        '8000230234563',\n        '6000230234563'],\n    });\n    test({\n      validator: 'isTaxID',\n      args: ['sk-SK'],\n      valid: [\n        '530121999',\n        '536221/999',\n        '031121999',\n        '520229999',\n        '1234567890'],\n      invalid: [\n        '53012199999',\n        '990101999',\n        '530121000',\n        '53012199',\n        '53-0121 999',\n        '535229999'],\n    });\n    test({\n      validator: 'isTaxID',\n      args: ['sl-SI'],\n      valid: [\n        '15012557',\n        '15012590'],\n      invalid: [\n        '150125577',\n        '1501255',\n        '15 01-255/7'],\n    });\n    test({\n      validator: 'isTaxID',\n      args: ['sv-SE'],\n      valid: [\n        '640823-3234',\n        '640883-3231',\n        '6408833231',\n        '19640823-3233',\n        '196408233233',\n        '19640883-3230',\n        '200228+5266',\n        '20180101-5581'],\n      invalid: [\n        '640823+3234',\n        '160230-3231',\n        '160260-3231',\n        '160260-323',\n        '160260323',\n        '640823+323',\n        '640823323',\n        '640823+32344',\n        '64082332344',\n        '19640823-32333',\n        '1964082332333'],\n    });\n    test({\n      validator: 'isTaxID',\n      args: ['uk-UA'],\n      valid: [\n        '3006321856',\n        '3003102490',\n        '2164212906'],\n      invalid: [\n        '2565975632',\n        '256597563287',\n        'КС00123456',\n        '2896235845'],\n    });\n    test({\n      validator: 'isTaxID',\n      valid: [\n        '01-1234567'],\n    });\n    test({\n      validator: 'isTaxID',\n      args: ['is-NOT'],\n      error: [\n        '01-1234567',\n        '01 1234567',\n        '011234567',\n        '0-11234567',\n        '01#1234567',\n        '01  1234567',\n        '01 1234 567',\n        '07-1234567',\n        '28-1234567',\n        '96-1234567',\n      ],\n    });\n  });\n\n\n  it('should validate slug', () => {\n    test({\n      validator: 'isSlug',\n      valid: [\n        'foo',\n        'foo-bar',\n        'foo_bar',\n        'foo-bar-foo',\n        'foo-bar_foo',\n        'foo-bar_foo*75-b4r-**_foo',\n        'foo-bar_foo*75-b4r-**_foo-&&',\n      ],\n      invalid: [\n        'not-----------slug',\n        '@#_$@',\n        '-not-slug',\n        'not-slug-',\n        '_not-slug',\n        'not-slug_',\n        'not slug',\n      ],\n    });\n  });\n\n  it('should validate strong passwords', () => {\n    test({\n      validator: 'isStrongPassword',\n      args: [{\n        minLength: 8,\n        minLowercase: 1,\n        minUppercase: 1,\n        minNumbers: 1,\n        minSymbols: 1,\n      }],\n      valid: [\n        '%2%k{7BsL\"M%Kd6e',\n        'EXAMPLE of very long_password123!',\n        'mxH_+2vs&54_+H3P',\n        '+&DxJ=X7-4L8jRCD',\n        'etV*p%Nr6w&H%FeF',\n        '£3.ndSau_7',\n        'VaLIDWith\\\\Symb0l',\n      ],\n      invalid: [\n        '',\n        'password',\n        'hunter2',\n        'hello world',\n        'passw0rd',\n        'password!',\n        'PASSWORD!',\n      ],\n    });\n  });\n\n  it('should validate date', () => {\n    test({\n      validator: 'isDate',\n      valid: [\n        new Date(),\n        new Date([2014, 2, 15]),\n        new Date('2014-03-15'),\n        '2020/02/29',\n        '2020-02-19',\n      ],\n      invalid: [\n        '',\n        '15072002',\n        null,\n        undefined,\n        { year: 2002, month: 7, day: 15 },\n        42,\n        { toString() { return '[object Date]'; } }, // faking\n        '2020-02-30', // invalid date\n        '2019-02-29', // non-leap year\n        '2020-04-31', // invalid date\n        '2020/03-15', // mixed delimiter\n        '-2020-04-19',\n        '-2023/05/24',\n        'abc-2023/05/24',\n        '2024',\n        '2024-',\n        '2024-05',\n        '2024-05-',\n        '2024-05-01-',\n        '2024-05-01-abc',\n        '2024/',\n        '2024/05',\n        '2024/05/',\n        '2024/05/01/',\n        '2024/05/01/abc',\n      ],\n    });\n    test({\n      validator: 'isDate',\n      args: ['DD/MM/YYYY'], // old format for backward compatibility\n      valid: [\n        '15-07-2002',\n        '15/07/2002',\n      ],\n      invalid: [\n        '15/7/2002',\n        '15-7-2002',\n        '15/7/02',\n        '15-7-02',\n        '15-07/2002',\n        '2024',\n        '2024-',\n        '2024-05',\n        '2024-05-',\n        '2024-05-01-',\n        '2024-05-01-abc',\n        '2024/',\n        '2024/05',\n        '2024/05/',\n        '2024/05/01/',\n        '2024/05/01/abc',\n        '15/',\n        '15/07',\n        '15/07/',\n        '15/07/2024/',\n      ],\n    });\n    test({\n      validator: 'isDate',\n      args: [{ format: 'DD/MM/YYYY' }],\n      valid: [\n        '15-07-2002',\n        '15/07/2002',\n      ],\n      invalid: [\n        '15/7/2002',\n        '15-7-2002',\n        '15/7/02',\n        '15-7-02',\n        '15-07/2002',\n        '2024',\n        '2024-',\n        '2024-05',\n        '2024-05-',\n        '2024-05-01-',\n        '2024-05-01-abc',\n        '2024/',\n        '2024/05',\n        '2024/05/',\n        '2024/05/01/',\n        '2024/05/01/abc',\n        '15/',\n        '15/07',\n        '15/07/',\n        '15/07/2024/',\n      ],\n    });\n    test({\n      validator: 'isDate',\n      args: [{ format: 'DD/MM/YY' }],\n      valid: [\n        '15-07-02',\n        '15/07/02',\n      ],\n      invalid: [\n        '15/7/2002',\n        '15-7-2002',\n        '15/07-02',\n        '30/04/--',\n        '2024',\n        '2024-',\n        '2024-05',\n        '2024-05-',\n        '2024-05-01-',\n        '2024-05-01-abc',\n        '2024/',\n        '2024/05',\n        '2024/05/',\n        '2024/05/01/',\n        '2024/05/01/abc',\n        '15/',\n        '15/07',\n        '15/07/',\n        '15/07/2024/',\n        '15/07/24/',\n      ],\n    });\n    test({\n      validator: 'isDate',\n      args: [{ format: 'D/M/YY' }],\n      valid: [\n        '5-7-02',\n        '5/7/02',\n      ],\n      invalid: [\n        '5/07/02',\n        '15/7/02',\n        '15-7-02',\n        '5/7-02',\n        '3/4/aa',\n        '2024/',\n        '2024/05',\n        '2024/05/',\n        '2024/05/01/',\n        '2024/05/01/abc',\n        '15/',\n        '15/07',\n        '15/07/',\n        '15/07/2024/',\n        '15/07/24/',\n      ],\n    });\n    test({\n      validator: 'isDate',\n      args: [{ format: 'DD/MM/YYYY', strictMode: true }],\n      valid: [\n        '15/07/2002',\n      ],\n      invalid: [\n        '15-07-2002',\n        '15/7/2002',\n        '15-7-2002',\n        '15/7/02',\n        '15-7-02',\n        '15-07/2002',\n        '2024/',\n        '2024/05',\n        '2024/05/',\n        '2024/05/01/',\n        '2024/05/01/abc',\n        '15/',\n        '15/07',\n        '15/07/',\n        '15/07/2024/',\n        '15/07/24/',\n      ],\n    });\n    test({\n      validator: 'isDate',\n      args: [{ strictMode: true }],\n      valid: [\n        '2020/01/15',\n        '2014/02/15',\n        '2014/03/15',\n        '2020/02/29',\n      ],\n      invalid: [\n        '2014-02-15',\n        '2020-02-29',\n        '15-07/2002',\n        new Date(),\n        new Date([2014, 2, 15]),\n        new Date('2014-03-15'),\n        '-2020-04-19',\n        '-2023/05/24',\n        'abc-2023/05/24',\n        '2024',\n        '2024-',\n        '2024-05',\n        '2024-05-',\n        '2024-05-01-',\n        '2024-05-01-abc',\n        '2024/',\n        '2024/05',\n        '2024/05/',\n        '2024/05/01/',\n        '2024/05/01/abc',\n      ],\n    });\n    test({\n      validator: 'isDate',\n      args: [{ delimiters: ['/', ' '] }],\n      valid: [\n        new Date(),\n        new Date([2014, 2, 15]),\n        new Date('2014-03-15'),\n        '2020/02/29',\n        '2020 02 29',\n      ],\n      invalid: [\n        '2020-02-29',\n        '',\n        '15072002',\n        null,\n        undefined,\n        { year: 2002, month: 7, day: 15 },\n        42,\n        { toString() { return '[object Date]'; } },\n        '2020/02/30',\n        '2019/02/29',\n        '2020/04/31',\n        '2020/03-15',\n        '-2020-04-19',\n        '-2023/05/24',\n        'abc-2023/05/24',\n        '2024',\n        '2024-',\n        '2024-05',\n        '2024-05-',\n        '2024-05-01-',\n        '2024-05-01-abc',\n        '2024/',\n        '2024/05',\n        '2024/05/',\n        '2024/05/01/',\n        '2024/05/01/abc',\n        '2024 05 01 abc',\n      ],\n    });\n    test({\n      validator: 'isDate',\n      args: [{ format: 'MM.DD.YYYY', delimiters: ['.'], strictMode: true }],\n      valid: [\n        '01.15.2020',\n        '02.15.2014',\n        '03.15.2014',\n        '02.29.2020',\n      ],\n      invalid: [\n        '2014-02-15',\n        '2020-02-29',\n        '15-07/2002',\n        new Date(),\n        new Date([2014, 2, 15]),\n        new Date('2014-03-15'),\n        '29.02.2020',\n        '02.29.2020.20',\n        '2024-',\n        '2024-05',\n        '2024-05-',\n        '2024-05-01',\n        '-2020-04-19',\n        '-2023/05/24',\n        'abc-2023/05/24',\n        '04.05.2024.',\n        '04.05.2024.abc',\n        'abc.04.05.2024',\n      ],\n    });\n    // emulating Pacific time zone offset & time\n    // which could potentially result in UTC conversion issues\n    timezone_mock.register('US/Pacific');\n    test({\n      validator: 'isDate',\n      valid: [\n        new Date(2016, 2, 29),\n        '2017-08-04',\n      ],\n    });\n    timezone_mock.unregister();\n  });\n  it('should validate time', () => {\n    test({\n      validator: 'isTime',\n      valid: [\n        '00:00',\n        '23:59',\n        '9:00',\n      ],\n      invalid: [\n        '',\n        null,\n        undefined,\n        0,\n        '07:00 PM',\n        '23',\n        '00:60',\n        '00:',\n        '01:0 ',\n        '001:01',\n      ],\n    });\n    test({\n      validator: 'isTime',\n      args: [{ hourFormat: 'hour24', mode: 'withSeconds' }],\n      valid: [\n        '23:59:59',\n        '00:00:00',\n        '9:50:01',\n      ],\n      invalid: [\n        '',\n        null,\n        undefined,\n        23,\n        '01:00:01 PM',\n        '13:00:',\n        '00',\n        '26',\n        '00;01',\n        '0 :09',\n        '59:59:59',\n        '24:00:00',\n        '00:59:60',\n        '99:99:99',\n        '009:50:01',\n      ],\n    });\n    test({\n      validator: 'isTime',\n      args: [{ hourFormat: 'hour24', mode: 'withOptionalSeconds' }],\n      valid: [\n        '23:59:59',\n        '00:00:00',\n        '9:50:01',\n        '00:00',\n        '23:59',\n        '9:00',\n      ],\n      invalid: [\n        '',\n        null,\n        undefined,\n        23,\n        '01:00:01 PM',\n        '13:00:',\n        '00',\n        '26',\n        '00;01',\n        '0 :09',\n        '59:59:59',\n        '24:00:00',\n        '00:59:60',\n        '99:99:99',\n        '009:50:01',\n      ],\n    });\n    test({\n      validator: 'isTime',\n      args: [{ hourFormat: 'hour12' }],\n      valid: [\n        '12:59 PM',\n        '12:59 AM',\n        '01:00 PM',\n        '01:00 AM',\n        '7:00 AM',\n      ],\n      invalid: [\n        '',\n        null,\n        undefined,\n        0,\n        '12:59 MM',\n        '12:59 MA',\n        '12:59 PA',\n        '12:59 A M',\n        '13:00 PM',\n        '23',\n        '00:60',\n        '00:',\n        '9:00',\n        '01:0 ',\n        '001:01',\n        '12:59:00 PM',\n        '12:59:00 A M',\n        '12:59:00 ',\n      ],\n    });\n    test({\n      validator: 'isTime',\n      args: [{ hourFormat: 'hour12', mode: 'withSeconds' }],\n      valid: [\n        '12:59:59 PM',\n        '2:34:45 AM',\n        '7:00:00 AM',\n      ],\n      invalid: [\n        '',\n        null,\n        undefined,\n        23,\n        '01:00: 1 PM',\n        '13:00:',\n        '13:00:00 PM',\n        '00',\n        '26',\n        '00;01',\n        '0 :09',\n        '59:59:59',\n        '24:00:00',\n        '00:59:60',\n        '99:99:99',\n        '9:50:01',\n        '009:50:01',\n      ],\n    });\n    test({\n      validator: 'isTime',\n      args: [{ hourFormat: 'hour12', mode: 'withOptionalSeconds' }],\n      valid: [\n        '12:59:59 PM',\n        '2:34:45 AM',\n        '7:00:00 AM',\n        '12:59 PM',\n        '12:59 AM',\n        '01:00 PM',\n        '01:00 AM',\n        '7:00 AM',\n      ],\n      invalid: [\n        '',\n        null,\n        undefined,\n        23,\n        '01:00: 1 PM',\n        '13:00:',\n        '00',\n        '26',\n        '00;01',\n        '0 :09',\n        '59:59:59',\n        '24:00:00',\n        '00:59:60',\n        '99:99:99',\n        '9:50:01',\n        '009:50:01',\n      ],\n    });\n  });\n  it('should be valid license plate', () => {\n    test({\n      validator: 'isLicensePlate',\n      args: ['es-AR'],\n      valid: [\n        'AB 123 CD',\n        'AB123CD',\n        'ABC 123',\n        'ABC123',\n      ],\n      invalid: [\n        '',\n        'notalicenseplate',\n        'AB-123-CD',\n        'ABC-123',\n        'AABC 123',\n        'AB CDE FG',\n        'ABC DEF',\n        '12 ABC 34',\n      ],\n    });\n    test({\n      validator: 'isLicensePlate',\n      args: ['pt-PT'],\n      valid: [\n        'AA-12-34',\n        '12-AA-34',\n        '12-34-AA',\n        'AA-12-AA',\n        'AA·12·34',\n        '12·AB·34',\n        '12·34·AB',\n        'AB·34·AB',\n        'AA 12 34',\n        '12 AA 34',\n        '12 34 AA',\n        'AB 12 CD',\n        'AA1234',\n        '12AA34',\n        '1234AA',\n        'AB12CD',\n      ],\n      invalid: [\n        '',\n        'notalicenseplate',\n        'AA-AA-00',\n        '00-AA-AA',\n        'AA-AA-AA',\n        '00-00-00',\n        'AA·AA·00',\n        '00·AA·AA',\n        'AA·AA·AA',\n        '00·00·00',\n        'AA AA 00',\n        '00 AA AA',\n        'AA AA AA',\n        '00 00 00',\n        'A1-B2-C3',\n        '1A-2B-3C',\n        'ABC-1-EF',\n        'AB-C1D-EF',\n        'AB-C1-DEF',\n      ],\n    });\n    test({\n      validator: 'isLicensePlate',\n      args: ['de-LI'],\n      valid: [\n        'FL 1',\n        'FL 99999',\n        'FL 1337',\n      ],\n      invalid: [\n        '',\n        'FL 999999',\n        'AB 12345',\n        'FL -1',\n      ],\n    });\n    test({\n      validator: 'isLicensePlate',\n      args: ['de-DE'],\n      valid: [\n        'M A 1',\n        'M A 12',\n        'M A 123',\n        'M A 1234',\n        'M AB 1',\n        'M AB 12',\n        'M AB 123',\n        'M AB 1234',\n        'FS A 1',\n        'FS A 12',\n        'FS A 123',\n        'FS A 1234',\n        'FS AB 1',\n        'FS AB 12',\n        'FS AB 123',\n        'FS AB 1234',\n        'FSAB1234',\n        'FS-AB-1234',\n        'FS AB 1234 H',\n        'FS AB 1234 E',\n        'FSAB1234E',\n        'FS-AB-1234-E',\n        'FS AB-1234-E',\n        'FSAB1234 E',\n        'FS AB1234E',\n        'LRO AB 123',\n        'LRO-AB-123-E',\n        'LRO-AB-123E',\n        'LRO-AB-123 E',\n        'LRO-AB-123-H',\n        'LRO-AB-123H',\n        'LRO-AB-123 H',\n      ],\n      invalid: [\n        'YY AB 123',\n        'PAF AB 1234',\n        'M ABC 123',\n        'M AB 12345',\n        'FS AB 1234 A',\n        'LRO-AB-1234',\n        'HRO ABC 123',\n        'HRO ABC 1234',\n        'LDK-AB-1234-E',\n        'ÖHR FA 123D',\n        'MZG-AB-123X',\n        'OBG-ABD-123',\n        'PAF-AB2-123',\n      ],\n    });\n    test({\n      validator: 'isLicensePlate',\n      args: ['fi-FI'],\n      valid: [\n        'ABC-123',\n        'ABC 123',\n        'ABC123',\n        'A100',\n        'A 100',\n        'A-100',\n        'C10001',\n        'C 10001',\n        'C-10001',\n        '123-ABC',\n        '123 ABC',\n        '123ABC',\n        '123-A',\n        '123 A',\n        '123A',\n        '199AA',\n        '199 AA',\n        '199-AA',\n      ],\n      invalid: [\n        ' ',\n        'A-1',\n        'A1A-100',\n        '1-A-2',\n        'C1234567',\n        'A B C 1 2 3',\n        'abc-123',\n      ],\n    });\n    test({\n      validator: 'isLicensePlate',\n      args: ['sq-AL'],\n      valid: [\n        'AA 000 AA',\n        'ZZ 999 ZZ',\n      ],\n      invalid: [\n        '',\n        'AA 0 A',\n        'AAA 00 AAA',\n      ],\n    });\n    test({\n      validator: 'isLicensePlate',\n      args: ['cs-CZ'],\n      valid: [\n        'ALA4011',\n        '4A23000',\n        'DICTAT0R',\n        'VETERAN',\n        'AZKVIZ8',\n        '2A45876',\n        'DIC-TAT0R',\n      ],\n      invalid: [\n        '',\n        'invalidlicenseplate',\n        'LN5758898',\n        'X-|$|-X',\n        'AE0F-OP4',\n        'GO0MER',\n        '2AAAAAAAA',\n        'FS AB 1234 E',\n        'GB999 9999 00',\n      ],\n    });\n\n    test({\n      validator: 'isLicensePlate',\n      args: ['pt-BR'],\n      valid: [\n        'ABC1234',\n        'ABC 1234',\n        'ABC-1234',\n        'ABC1D23',\n        'ABC1K23',\n        'ABC1Z23',\n        'ABC 1D23',\n        'ABC-1D23',\n      ],\n      invalid: [\n        '',\n        'AA 0 A',\n        'AAA 00 AAA',\n        'ABCD123',\n        'AB12345',\n        'AB123DC',\n      ],\n    });\n    test({\n      validator: 'isLicensePlate',\n      args: ['hu-HU'],\n      valid: [\n        'AAB-001',\n        'AVC-987',\n        'KOC-124',\n        'JCM-871',\n        'AWQ-777',\n        'BPO-001',\n        'BPI-002',\n        'UCO-342',\n        'UDO-385',\n        'XAO-987',\n        'AAI-789',\n        'ABI-789',\n        'ACI-789',\n        'AAO-789',\n        'ABO-789',\n        'ACO-789',\n        'YAA-123',\n        'XAA-123',\n        'WAA-258',\n        'XZZ-784',\n        'M123456',\n        'CK 12-34',\n        'DT 12-34',\n        'CD 12-34',\n        'HC 12-34',\n        'HB 12-34',\n        'HK 12-34',\n        'MA 12-34',\n        'OT 12-34',\n        'RR 17-87',\n        'CD 124-348',\n        'C-C 2021',\n        'C-X 2458',\n        'X-A 7842',\n        'E-72345',\n        'Z-07458',\n        'S ACF 83',\n        'SP 04-68',\n      ],\n      invalid: [\n        'AAA-547',\n        'aab-001',\n        'AAB 001',\n        'AB34',\n        '789-LKJ',\n        'BBO-987',\n        'BBI-987',\n        'BWQ-777',\n        'BQW-987',\n        'BAI-789',\n        'BBI-789',\n        'BCI-789',\n        'BAO-789',\n        'BBO-789',\n        'BCO-789',\n        'ADI-789',\n        'ADO-789',\n        'KOC-1234',\n        'M1234567',\n        'W-12345',\n        'S BCF 83',\n        'X-D 1234',\n        'C-D 1234',\n        'HU 12-34',\n      ],\n    });\n    test({\n      validator: 'isLicensePlate',\n      args: ['any'],\n      valid: [\n        'FL 1',\n        'FS AB 123',\n      ],\n      invalid: [\n        '',\n        'FL 999999',\n        'FS AB 1234 A',\n      ],\n    });\n    test({\n      validator: 'isLicensePlate',\n      args: ['asdfasdf'],\n      error: [\n        'FL 1',\n        'FS AB 123',\n        'FL 999999',\n        'FS AB 1234 A',\n      ],\n    });\n    test({\n      validator: 'isLicensePlate',\n      args: ['sv-SE'],\n      valid: [\n        'ABC 123',\n        'ABC 12A',\n        'ABC123',\n        'ABC12A',\n        'A WORD',\n        'WORD',\n        'ÅSNA',\n        'EN VARG',\n        'CERISE',\n        'AA',\n        'ABCDEFG',\n        'ÅÄÖ',\n        'ÅÄÖ ÅÄÖ',\n      ],\n      invalid: [\n        '',\n        '    ',\n        'IQV 123',\n        'IQV123',\n        'ABI 12Q',\n        'ÅÄÖ 123',\n        'ÅÄÖ 12A',\n        'AB1 A23',\n        'AB1 12A',\n        'lower',\n        'abc 123',\n        'abc 12A',\n        'abc 12a',\n        'AbC 12a',\n        'WORDLONGERTHANSEVENCHARACTERS',\n        'A',\n        'ABC-123',\n      ],\n    });\n    test({\n      validator: 'isLicensePlate',\n      args: ['en-IN'],\n      valid: [\n        'MH 04 AD 0001',\n        'HR26DQ0001',\n        'WB-04-ZU-2001',\n        'KL 18 X 5800',\n        'DL 4 CAF 4856',\n        'KA-41CE-5289',\n        'GJ 04-AD 5822',\n      ],\n      invalid: ['mh04ad0045', 'invalidlicenseplate', '4578', '', 'GJ054GH4785'],\n    });\n    test({\n      validator: 'isLicensePlate',\n      args: ['en-SG'],\n      valid: [\n        'SGX 1234 A',\n        'SGX-1234-A',\n        'SGB1234Z',\n      ],\n      invalid: [\n        'sg1234a',\n        'invalidlicenseplate',\n        '4578',\n        '',\n        'GJ054GH4785',\n      ],\n    });\n  });\n  it('should validate VAT numbers', () => {\n    test({\n      validator: 'isVAT',\n      args: ['AT'],\n      valid: [\n        'ATU12345678',\n        'U12345678',\n      ],\n      invalid: [\n        'AT 12345678',\n        '12345678',\n      ],\n    });\n    test({\n      validator: 'isVAT',\n      args: ['BE'],\n      valid: [\n        'BE1234567890',\n        '1234567890',\n      ],\n      invalid: [\n        'BE 1234567890',\n        '123456789',\n      ],\n    });\n    test({\n      validator: 'isVAT',\n      args: ['BG'],\n      valid: [\n        'BG1234567890',\n        '1234567890',\n        'BG123456789',\n        '123456789',\n      ],\n      invalid: [\n        'BG 1234567890',\n        '12345678',\n      ],\n    });\n    test({\n      validator: 'isVAT',\n      args: ['HR'],\n      valid: [\n        'HR12345678901',\n        '12345678901',\n      ],\n      invalid: [\n        'HR 12345678901',\n        '1234567890',\n      ],\n    });\n    test({\n      validator: 'isVAT',\n      args: ['CY'],\n      valid: [\n        'CY123456789',\n        '123456789',\n      ],\n      invalid: [\n        'CY 123456789',\n        '12345678',\n      ],\n    });\n    test({\n      validator: 'isVAT',\n      args: ['CZ'],\n      valid: [\n        'CZ1234567890',\n        'CZ123456789',\n        'CZ12345678',\n        '1234567890',\n        '123456789',\n        '12345678',\n      ],\n      invalid: [\n        'CZ 123456789',\n        '1234567',\n      ],\n    });\n    test({\n      validator: 'isVAT',\n      args: ['DK'],\n      valid: [\n        'DK12345678',\n        '12345678',\n      ],\n      invalid: [\n        'DK 12345678',\n        '1234567',\n      ],\n    });\n    test({\n      validator: 'isVAT',\n      args: ['EE'],\n      valid: [\n        'EE123456789',\n        '123456789',\n      ],\n      invalid: [\n        'EE 123456789',\n        '12345678',\n      ],\n    });\n    test({\n      validator: 'isVAT',\n      args: ['FI'],\n      valid: [\n        'FI12345678',\n        '12345678',\n      ],\n      invalid: [\n        'FI 12345678',\n        '1234567',\n      ],\n    });\n    test({\n      validator: 'isVAT',\n      args: ['FR'],\n      valid: [\n        'FRAA123456789',\n        'FR83404833048',\n        'FR40123456789',\n        'FRA1123456789',\n        'FR1A123456789',\n      ],\n      invalid: [\n        'FR AA123456789',\n        '123456789',\n        'FRAA123456789A',\n        'FR123456789',\n        'FR 83404833048',\n        'FRaa123456789',\n      ],\n    });\n    test({\n      validator: 'isVAT',\n      args: ['DE'],\n      valid: [\n        'DE123456789',\n        '123456789',\n      ],\n      invalid: [\n        'DE 123456789',\n        '12345678',\n      ],\n    });\n    test({\n      validator: 'isVAT',\n      args: ['EL'],\n      valid: [\n        'EL123456789',\n        '123456789',\n      ],\n      invalid: [\n        'EL 123456789',\n        '12345678',\n      ],\n    });\n    test({\n      validator: 'isVAT',\n      args: ['HU'],\n      valid: [\n        'HU12345678',\n        '12345678',\n      ],\n      invalid: [\n        'HU 12345678',\n        '1234567',\n      ],\n    });\n    test({\n      validator: 'isVAT',\n      args: ['IE'],\n      valid: [\n        'IE1234567AW',\n        '1234567AW',\n      ],\n      invalid: [\n        'IE 1234567',\n        '1234567',\n      ],\n    });\n    test({\n      validator: 'isVAT',\n      args: ['IT'],\n      valid: [\n        'IT12345678910',\n        '12345678910',\n      ],\n      invalid: [\n        'IT12345678 910',\n        'IT 123456789101',\n        'IT123456789101',\n        'GB12345678910',\n        'IT123456789',\n      ],\n    });\n    test({\n      validator: 'isVAT',\n      args: ['LV'],\n      valid: [\n        'LV12345678901',\n        '12345678901',\n      ],\n      invalid: [\n        'LV 12345678901',\n        '1234567890',\n      ],\n    });\n    test({\n      validator: 'isVAT',\n      args: ['LT'],\n      valid: [\n        'LT123456789012',\n        '123456789012',\n        'LT12345678901',\n        '12345678901',\n        'LT1234567890',\n        '1234567890',\n        'LT123456789',\n        '123456789',\n      ],\n      invalid: [\n        'LT 123456789012',\n        '12345678',\n      ],\n    });\n    test({\n      validator: 'isVAT',\n      args: ['LU'],\n      valid: [\n        'LU12345678',\n        '12345678',\n      ],\n      invalid: [\n        'LU 12345678',\n        '1234567',\n      ],\n    });\n    test({\n      validator: 'isVAT',\n      args: ['MT'],\n      valid: [\n        'MT12345678',\n        '12345678',\n      ],\n      invalid: [\n        'MT 12345678',\n        '1234567',\n      ],\n    });\n    test({\n      validator: 'isVAT',\n      args: ['NL'],\n      valid: [\n        'NL123456789B10',\n        '123456789B10',\n      ],\n      invalid: [\n        'NL12345678 910',\n        'NL 123456789101',\n        'NL123456789B1',\n        'GB12345678910',\n        'NL123456789',\n      ],\n    });\n    test({\n      validator: 'isVAT',\n      args: ['PL'],\n      valid: [\n        'PL1234567890',\n        '1234567890',\n        'PL123-456-78-90',\n        '123-456-78-90',\n        'PL123-45-67-890',\n        '123-45-67-890',\n      ],\n      invalid: [\n        'PL 1234567890',\n        '123456789',\n      ],\n    });\n    test({\n      validator: 'isVAT',\n      args: ['PT'],\n      valid: [\n        'PT123456789',\n        '123456789',\n      ],\n      invalid: [\n        'PT 123456789',\n        '000000001',\n      ],\n    });\n    test({\n      validator: 'isVAT',\n      args: ['RO'],\n      valid: [\n        'RO1234567890',\n        '1234567890',\n        'RO12',\n        '12',\n      ],\n      invalid: [\n        'RO 12',\n        '1',\n      ],\n    });\n    test({\n      validator: 'isVAT',\n      args: ['SK'],\n      valid: [\n        'SK1234567890',\n        '1234567890',\n      ],\n      invalid: [\n        'SK 1234567890',\n        '123456789',\n      ],\n    });\n    test({\n      validator: 'isVAT',\n      args: ['SI'],\n      valid: [\n        'SI12345678',\n        '12345678',\n      ],\n      invalid: [\n        'SI 12345678',\n        '1234567',\n      ],\n    });\n    test({\n      validator: 'isVAT',\n      args: ['ES'],\n      valid: [\n        'ESA1234567A',\n        'A1234567A',\n      ],\n      invalid: [\n        'ES 1234567A',\n        '123456789',\n      ],\n    });\n    test({\n      validator: 'isVAT',\n      args: ['SE'],\n      valid: [\n        'SE123456789012',\n        '123456789012',\n      ],\n      invalid: [\n        'SE 123456789012',\n        '12345678901',\n      ],\n    });\n    test({\n      validator: 'isVAT',\n      args: ['AL'],\n      valid: [\n        'AL123456789A',\n        '123456789A',\n      ],\n      invalid: [\n        'AL 123456789A',\n        '123456789',\n      ],\n    });\n    test({\n      validator: 'isVAT',\n      args: ['MK'],\n      valid: [\n        'MK1234567890123',\n        '1234567890123',\n      ],\n      invalid: [\n        'MK 1234567890123',\n        '123456789012',\n      ],\n    });\n    test({\n      validator: 'isVAT',\n      args: ['AU'],\n      valid: [\n        'AU53004085616',\n        '53004085616',\n        'AU65613309809',\n        '65613309809',\n        'AU34118972998',\n        '34118972998',\n      ],\n      invalid: [\n        'AU65613309808',\n        '65613309808',\n        'AU55613309809',\n        '55613309809',\n        'AU65613319809',\n        '65613319809',\n        'AU34117972998',\n        '34117972998',\n        'AU12345678901',\n        '12345678901',\n        'AU 12345678901',\n        '1234567890',\n      ],\n    });\n    test({\n      validator: 'isVAT',\n      args: ['BY'],\n      valid: [\n        'УНП 123456789',\n        '123456789',\n      ],\n      invalid: [\n        'BY 123456789',\n        '12345678',\n      ],\n    });\n    test({\n      validator: 'isVAT',\n      args: ['CA'],\n      valid: [\n        'CA123456789',\n        '123456789',\n      ],\n      invalid: [\n        'CA 123456789',\n        '12345678',\n      ],\n    });\n    test({\n      validator: 'isVAT',\n      args: ['IS'],\n      valid: [\n        'IS123456',\n        '12345',\n      ],\n      invalid: [\n        'IS 12345',\n        '1234',\n      ],\n    });\n    test({\n      validator: 'isVAT',\n      args: ['IN'],\n      valid: [\n        'IN123456789012345',\n        '123456789012345',\n      ],\n      invalid: [\n        'IN 123456789012345',\n        '12345678901234',\n      ],\n    });\n    test({\n      validator: 'isVAT',\n      args: ['ID'],\n      valid: [\n        'ID123456789012345',\n        '123456789012345',\n        'ID12.345.678.9-012.345',\n        '12.345.678.9-012.345',\n      ],\n      invalid: [\n        'ID 123456789012345',\n        '12345678901234',\n      ],\n    });\n    test({\n      validator: 'isVAT',\n      args: ['IL'],\n      valid: [\n        'IL123456789',\n        '123456789',\n      ],\n      invalid: [\n        'IL 123456789',\n        '12345678',\n      ],\n    });\n    test({\n      validator: 'isVAT',\n      args: ['KZ'],\n      valid: [\n        'KZ123456789012',\n        '123456789012',\n      ],\n      invalid: [\n        'KZ 123456789012',\n        '12345678',\n      ],\n    });\n    test({\n      validator: 'isVAT',\n      args: ['NZ'],\n      valid: [\n        'NZ123456789',\n        '123456789',\n      ],\n      invalid: [\n        'NZ 123456789',\n        '12345678',\n      ],\n    });\n    test({\n      validator: 'isVAT',\n      args: ['NG'],\n      valid: [\n        'NG123456789012',\n        '123456789012',\n        'NG12345678-9012',\n        '12345678-9012',\n      ],\n      invalid: [\n        'NG 123456789012',\n        '12345678901',\n      ],\n    });\n    test({\n      validator: 'isVAT',\n      args: ['NO'],\n      valid: [\n        'NO123456789MVA',\n        '123456789MVA',\n      ],\n      invalid: [\n        'NO 123456789MVA',\n        '123456789',\n      ],\n    });\n    test({\n      validator: 'isVAT',\n      args: ['PH'],\n      valid: [\n        'PH123456789012',\n        '123456789012',\n        'PH123 456 789 012',\n        '123 456 789 012',\n      ],\n      invalid: [\n        'PH 123456789012',\n        '12345678901',\n      ],\n    });\n    test({\n      validator: 'isVAT',\n      args: ['RU'],\n      valid: [\n        'RU1234567890',\n        '1234567890',\n        'RU123456789012',\n        '123456789012',\n      ],\n      invalid: [\n        'RU 123456789012',\n        '12345678901',\n      ],\n    });\n    test({\n      validator: 'isVAT',\n      args: ['SM'],\n      valid: [\n        'SM12345',\n        '12345',\n      ],\n      invalid: [\n        'SM 12345',\n        '1234',\n      ],\n    });\n    test({\n      validator: 'isVAT',\n      args: ['SA'],\n      valid: [\n        'SA123456789012345',\n        '123456789012345',\n      ],\n      invalid: [\n        'SA 123456789012345',\n        '12345678901234',\n      ],\n    });\n    test({\n      validator: 'isVAT',\n      args: ['RS'],\n      valid: [\n        'RS123456789',\n        '123456789',\n      ],\n      invalid: [\n        'RS 123456789',\n        '12345678',\n      ],\n    });\n    test({\n      validator: 'isVAT',\n      args: ['CH'],\n      valid: [\n        // strictly valid\n        'CHE-116.281.710 MWST',\n        'CHE-116.281.710 IVA',\n        'CHE-116.281.710 TVA',\n        // loosely valid presentation variants\n        'CHE 116 281 710 IVA', // all separators are spaces\n        'CHE-191.398.369MWST', // no space before suffix\n        'CHE-116281710 MWST', // no number separators\n        'CHE-116281710MWST', // no number separators and no space before suffix\n        'CHE105854263MWST', // no separators\n        'CHE-116.285.524', // no suffix (vat abbreviation)\n        'CHE116281710', // no suffix and separators\n        '116.281.710 TVA', // no prefix (CHE, ISO-3166-1 Alpha-3)\n        '116281710MWST', // no prefix and separators\n        '100.218.485', // no prefix and suffix\n        '123456788', // no prefix, separators and suffix\n      ],\n      invalid: [\n        'CH-116.281.710 MWST', // invalid prefix (should be CHE)\n        'CHE-116.281 MWST', // invalid number of digits (should be 9)\n        'CHE-123.456.789 MWST', // invalid last digit (should match the calculated check-number 8)\n        'CHE-123.356.780 MWST', // invalid check-number (there are no swiss UIDs with the calculated check number 10)\n        'CH-116.281.710 VAT', // invalid suffix (should be MWST, IVA or TVA)\n        'CHE-116/281/710 IVA', // invalid number separators (should be all dots or all spaces)\n      ],\n    });\n    test({\n      validator: 'isVAT',\n      args: ['TR'],\n      valid: [\n        'TR1234567890',\n        '1234567890',\n      ],\n      invalid: [\n        'TR 1234567890',\n        '123456789',\n      ],\n    });\n    test({\n      validator: 'isVAT',\n      args: ['UA'],\n      valid: [\n        'UA123456789012',\n        '123456789012',\n      ],\n      invalid: [\n        'UA 123456789012',\n        '12345678901',\n      ],\n    });\n    test({\n      validator: 'isVAT',\n      args: ['GB'],\n      valid: [\n        'GB999 9999 00',\n        'GB999 9999 96',\n        'GB999999999 999',\n        'GBGD000',\n        'GBGD499',\n        'GBHA500',\n        'GBHA999',\n      ],\n      invalid: [\n        'GB999999900',\n        'GB999999996',\n        'GB999 9999 97',\n        'GB999999999999',\n        'GB999999999 9999',\n        'GB9999999999 999',\n        'GBGD 000',\n        'GBGD 499',\n        'GBHA 500',\n        'GBHA 999',\n        'GBGD500',\n        'GBGD999',\n        'GBHA000',\n        'GBHA499',\n      ],\n    });\n    test({\n      validator: 'isVAT',\n      args: ['UZ'],\n      valid: [\n        'UZ123456789',\n        '123456789',\n      ],\n      invalid: [\n        'UZ 123456789',\n        '12345678',\n      ],\n    });\n    test({\n      validator: 'isVAT',\n      args: ['AR'],\n      valid: [\n        'AR12345678901',\n        '12345678901',\n      ],\n      invalid: [\n        'AR 12345678901',\n        '1234567890',\n      ],\n    });\n    test({\n      validator: 'isVAT',\n      args: ['BO'],\n      valid: [\n        'BO1234567',\n        '1234567',\n      ],\n      invalid: [\n        'BO 1234567',\n        '123456',\n      ],\n    });\n    test({\n      validator: 'isVAT',\n      args: ['BR'],\n      valid: [\n        'BR12.345.678/9012-34',\n        '12.345.678/9012-34',\n        'BR123.456.789-01',\n        '123.456.789-01',\n      ],\n      invalid: [\n        'BR 12.345.678/9012-34',\n        '12345678901234',\n      ],\n    });\n    test({\n      validator: 'isVAT',\n      args: ['CL'],\n      valid: [\n        'CL12345678-9',\n        '12345678-9',\n      ],\n      invalid: [\n        'CL 12345678-9',\n        '12345678',\n      ],\n    });\n    test({\n      validator: 'isVAT',\n      args: ['CO'],\n      valid: [\n        'CO1234567890',\n        '1234567890',\n      ],\n      invalid: [\n        'CO 1234567890',\n        '123456789',\n      ],\n    });\n    test({\n      validator: 'isVAT',\n      args: ['CR'],\n      valid: [\n        'CR123456789012',\n        '123456789012',\n        'CR123456789',\n        '123456789',\n      ],\n      invalid: [\n        'CR 123456789',\n        '12345678',\n      ],\n    });\n    test({\n      validator: 'isVAT',\n      args: ['EC'],\n      valid: [\n        'EC1234567890123',\n        '1234567890123',\n      ],\n      invalid: [\n        'EC 1234567890123',\n        '123456789012',\n      ],\n    });\n    test({\n      validator: 'isVAT',\n      args: ['SV'],\n      valid: [\n        'SV1234-567890-123-1',\n        '1234-567890-123-1',\n      ],\n      invalid: [\n        'SV 1234-567890-123-1',\n        '1234567890123',\n      ],\n    });\n    test({\n      validator: 'isVAT',\n      args: ['GT'],\n      valid: [\n        'GT1234567-8',\n        '1234567-8',\n      ],\n      invalid: [\n        'GT 1234567-8',\n        '1234567',\n      ],\n    });\n    test({\n      validator: 'isVAT',\n      args: ['HN'],\n      valid: [\n        'HN',\n      ],\n      invalid: [\n        'HN ',\n      ],\n    });\n    test({\n      validator: 'isVAT',\n      args: ['MX'],\n      valid: [\n        'MXABCD123456EFG',\n        'ABCD123456EFG',\n        'MXABC123456DEF',\n        'ABC123456DEF',\n      ],\n      invalid: [\n        'MX ABC123456EFG',\n        '123456',\n      ],\n    });\n    test({\n      validator: 'isVAT',\n      args: ['NI'],\n      valid: [\n        'NI123-456789-0123A',\n        '123-456789-0123A',\n      ],\n      invalid: [\n        'NI 123-456789-0123A',\n        '1234567890123',\n      ],\n    });\n    test({\n      validator: 'isVAT',\n      args: ['PA'],\n      valid: [\n        'PA',\n      ],\n      invalid: [\n        'PA ',\n      ],\n    });\n    test({\n      validator: 'isVAT',\n      args: ['PY'],\n      valid: [\n        'PY12345678-9',\n        '12345678-9',\n        'PY123456-7',\n        '123456-7',\n      ],\n      invalid: [\n        'PY 123456-7',\n        '123456',\n      ],\n    });\n    test({\n      validator: 'isVAT',\n      args: ['PE'],\n      valid: [\n        'PE12345678901',\n        '12345678901',\n      ],\n      invalid: [\n        'PE 12345678901',\n        '1234567890',\n      ],\n    });\n    test({\n      validator: 'isVAT',\n      args: ['DO'],\n      valid: [\n        'DO12345678901',\n        '12345678901',\n        'DO123-4567890-1',\n        '123-4567890-1',\n        'DO123456789',\n        '123456789',\n        'DO1-23-45678-9',\n        '1-23-45678-9',\n      ],\n      invalid: [\n        'DO 12345678901',\n        '1234567890',\n      ],\n    });\n    test({\n      validator: 'isVAT',\n      args: ['UY'],\n      valid: [\n        'UY123456789012',\n        '123456789012',\n      ],\n      invalid: [\n        'UY 123456789012',\n        '12345678901',\n      ],\n    });\n    test({\n      validator: 'isVAT',\n      args: ['VE'],\n      valid: [\n        'VEJ-123456789',\n        'J-123456789',\n        'VEJ-12345678-9',\n        'J-12345678-9',\n      ],\n      invalid: [\n        'VE J-123456789',\n        '12345678',\n      ],\n    });\n    test({\n      validator: 'isVAT',\n      args: ['invalidCountryCode'],\n      error: [\n        'GB999 9999 00',\n      ],\n    });\n  });\n  it('should validate mailto URI', () => {\n    test({\n      validator: 'isMailtoURI',\n      valid: [\n        'mailto:?subject=something&cc=valid@mail.com',\n        'mailto:?subject=something&cc=valid@mail.com,another@mail.com,',\n        'mailto:?subject=something&bcc=valid@mail.com',\n        'mailto:?subject=something&bcc=valid@mail.com,another@mail.com',\n        'mailto:?bcc=valid@mail.com,another@mail.com',\n        'mailto:?cc=valid@mail.com,another@mail.com',\n        'mailto:?cc=valid@mail.com',\n        'mailto:?bcc=valid@mail.com',\n        'mailto:?subject=something&body=something else',\n        'mailto:?subject=something&body=something else&cc=hello@mail.com,another@mail.com',\n        'mailto:?subject=something&body=something else&bcc=hello@mail.com,another@mail.com',\n        'mailto:?subject=something&body=something else&cc=something@mail.com&bcc=hello@mail.com,another@mail.com',\n        'mailto:hello@mail.com',\n        'mailto:info@mail.com?',\n        'mailto:hey@mail.com?subject=something',\n        'mailto:info@mail.com?subject=something&cc=valid@mail.com',\n        'mailto:info@mail.com?subject=something&cc=valid@mail.com,another@mail.com,',\n        'mailto:info@mail.com?subject=something&bcc=valid@mail.com',\n        'mailto:info@mail.com?subject=something&bcc=valid@mail.com,another@mail.com',\n        'mailto:info@mail.com?bcc=valid@mail.com,another@mail.com',\n        'mailto:info@mail.com?cc=valid@mail.com,another@mail.com',\n        'mailto:info@mail.com?cc=valid@mail.com',\n        'mailto:info@mail.com?bcc=valid@mail.com&',\n        'mailto:info@mail.com?subject=something&body=something else',\n        'mailto:info@mail.com?subject=something&body=something else&cc=hello@mail.com,another@mail.com',\n        'mailto:info@mail.com?subject=something&body=something else&bcc=hello@mail.com,another@mail.com',\n        'mailto:info@mail.com?subject=something&body=something else&cc=something@mail.com&bcc=hello@mail.com,another@mail.com',\n        'mailto:',\n      ],\n      invalid: [\n        '',\n        'something',\n        'valid@gmail.com',\n        'mailto:?subject=okay&subject=444',\n        'mailto:?subject=something&wrong=888',\n        'mailto:somename@ｇｍａｉｌ.com',\n        'mailto:hello@world.com?cc=somename@ｇｍａｉｌ.com',\n        'mailto:hello@world.com?bcc=somename@ｇｍａｉｌ.com',\n        'mailto:hello@world.com?bcc=somename@ｇｍａｉｌ.com&bcc',\n        'mailto:valid@gmail.com?subject=anything&body=nothing&cc=&bcc=&key=',\n        'mailto:hello@world.com?cc=somename',\n        'mailto:somename',\n        'mailto:info@mail.com?subject=something&body=something else&cc=something@mail.com&bcc=hello@mail.com,another@mail.com&',\n        'mailto:?subject=something&body=something else&cc=something@mail.com&bcc=hello@mail.com,another@mail.com&',\n      ],\n    });\n  });\n});\n"
  }
]