{"version":3,"file":"index.min.js","mappings":"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","sources":["webpack://taiwanIdValidator/webpack/universalModuleDefinition","webpack://taiwanIdValidator/webpack/bootstrap","webpack://taiwanIdValidator/webpack/runtime/define property getters","webpack://taiwanIdValidator/webpack/runtime/hasOwnProperty shorthand","webpack://taiwanIdValidator/webpack/runtime/make namespace object","webpack://taiwanIdValidator/./src/citizen-digital-certificate-number.ts","webpack://taiwanIdValidator/./src/e-invoice-mobile-barcode.ts","webpack://taiwanIdValidator/./src/e-invoice-donate-code.ts","webpack://taiwanIdValidator/./src/helper.ts","webpack://taiwanIdValidator/./src/business-administration-number.ts","webpack://taiwanIdValidator/./src/id-card-number.ts"],"sourcesContent":["(function webpackUniversalModuleDefinition(root, factory) {\n\tif(typeof exports === 'object' && typeof module === 'object')\n\t\tmodule.exports = factory();\n\telse if(typeof define === 'function' && define.amd)\n\t\tdefine([], factory);\n\telse if(typeof exports === 'object')\n\t\texports[\"taiwanIdValidator\"] = factory();\n\telse\n\t\troot[\"taiwanIdValidator\"] = factory();\n})(this, function() {\nreturn ","// The require scope\nvar __webpack_require__ = {};\n\n","// define getter functions for harmony exports\n__webpack_require__.d = function(exports, definition) {\n\tfor(var key in definition) {\n\t\tif(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n\t\t\tObject.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n\t\t}\n\t}\n};","__webpack_require__.o = function(obj, prop) { return Object.prototype.hasOwnProperty.call(obj, prop); }","// define __esModule on exports\n__webpack_require__.r = function(exports) {\n\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n\t}\n\tObject.defineProperty(exports, '__esModule', { value: true });\n};","/**\n * Verify the input is a valid Citizen Digital Certificate Number (自然人憑證)\n *\n * @param { string } input - Citizen Digital Certificate Number\n * @returns { boolean } is `input` a valid Citizen Digital Certificate Number\n * @example\n * isCdcNumber('AB12345678901234') // true\n * isCdcNumber('A12345678901234') // false\n */\nexport function isCdcNumber(input: string): boolean {\n if (typeof input !== 'string') return false\n\n const n = input.toString()\n\n // 驗證規則為兩碼英文 + 14 碼數字\n const regex = /^[A-Z]{2}\\d{14}$/\n\n return regex.test(n)\n}\n","/**\n * Verify the input is a valid E-Invoice Mobile Barcode (電子發票手機條碼)\n *\n * @param { string } input - E-Invoice Mobile Barcode\n * @returns { boolean } is `input` a valid E-Invoice Mobile Barcode\n * @example\n * isMobileBarcode('/+.-++..') // true\n * isMobileBarcode('/12345678') // false\n */\nexport function isMobileBarcode(input: string): boolean {\n if (typeof input !== 'string') return false\n\n const n = input.toString()\n\n /**\n * 總長度為 8 碼\n * 第 1 碼為 /\n * 第 2-8 碼由 0-9 (數字), A-Z (大寫英文字母), .(period), -(hyphen), +(plus) 組成\n */\n const regex = /^\\/[\\dA-Z.\\-+]{7}$/\n\n return regex.test(n)\n}\n","/**\n * Verify the input is a valid E-Invoice Donate Code (電子發票捐贈碼)\n *\n * @param { string | number } input - E-Invoice Donate Code\n * @returns { boolean } is `input` a valid E-Invoice Donate Code\n * @example\n * isDonateCode('123') // true\n * isDonateCode('abc123') // false\n */\nexport function isDonateCode(input: string | number): boolean {\n if (typeof input !== 'string' && typeof input !== 'number') return false\n\n const n = input.toString()\n\n // 總長度為 3-7 碼 0-9 的數字\n const regex = /^[\\d]{3,7}$/\n\n return regex.test(n)\n}\n","export function zipWith<T, R>(a1: T[], a2: T[], f: (v1: T, v2: T) => R): R[] {\n const length = Math.min(a1.length, a2.length)\n const result: R[] = []\n\n for (let i = 0; i < length; i++) result[i] = f(a1[i], a2[i])\n\n return result\n}\n\nexport function add(a: number, b: number) {\n return a + b\n}\n\nexport function multiply(a: number, b: number) {\n return a * b\n}\n\nexport const objectKeys: <T extends Record<string, unknown>>(\n obj: T\n) => (keyof T)[] = Object.keys\n","import { zipWith, multiply, add } from './helper'\n\nexport type BanValidationOptions = {\n /**\n * validate `input` with old format only: https://www.fia.gov.tw/singlehtml/3?cntId=c4d9cff38c8642ef8872774ee9987283\n */\n applyOldRules?: boolean\n}\n\n/**\n * Verify the input is a valid Business Administration Number (營利事業統一編號)\n *\n * @param { string | number } input - Business Administration Number\n * @param { BanValidationOptions } [banValidationOptions] - Business Administration Number validation options\n * @returns { boolean } is `input` a valid Business Administration Number\n * @example\n * isBan('12345675') // true\n * isBan('12345675', { applyOldRules: true }) // true\n * isBan('12345678') // false\n */\nexport function isBan(\n input: string | number,\n options: BanValidationOptions = {}\n): boolean {\n const { applyOldRules = false } = options\n\n if (typeof input !== 'string' && typeof input !== 'number') return false\n\n /**\n * Example: 12345675\n * Step 1:\n * 1 * 1 = 1\n * 2 * 2 = 4\n * 3 * 1 = 3\n * 4 * 2 = 8\n * 5 * 1 = 5\n * 6 * 2 = 12\n * 7 * 4 = 28\n * 5 * 1 = 5\n *\n * Step 2:\n * 1 -> 1\n * 4 -> 4\n * 3 -> 3\n * 8 -> 8\n * 5 -> 5\n * 12 -> 1 + 2 = 3\n * 28 -> 2 + 8 = 10\n * 5 -> 5\n *\n * Step 3:\n * (1 + 4 + 3 + 8 + 5 + 3 + 10 + 5) % 10 = 9\n */\n\n const BAN_COEFFICIENTS = [1, 2, 1, 2, 1, 2, 4, 1]\n\n const n = input.toString()\n const regex = /^\\d{8}$/\n\n if (!regex.test(n)) return false\n\n /**\n * Step 1: 先把統一編號的每個數字分別乘上對應的係數 (1, 2, 1, 2, 1, 2, 4, 1)\n * Step 2: 再把個別乘積的十位數與個位數相加,得出八個小於 10 的數字\n */\n\n const intRadix = 10\n const checksum = zipWith(\n BAN_COEFFICIENTS,\n n.split('').map(c => parseInt(c, intRadix)),\n multiply\n )\n .map(n => (n % 10) + Math.floor(n / 10))\n .reduce(add, 0)\n\n /**\n * Step 3: 檢查把這 8 個數字相加之後計算此和除以 5 or 10 的餘數\n * Step 4:\n * 4-1: 若是餘數為 0,則為正確的統一編號\n * 4-2: 若是餘數為 9,且原統一編號的第七位是 7,則也為正確的統一編號\n */\n\n const divisor = applyOldRules ? 10 : 5\n\n return (\n checksum % divisor === 0 ||\n (parseInt(n.charAt(6), intRadix) === 7 && (checksum + 1) % divisor === 0)\n )\n}\n","import { zipWith, multiply, add, objectKeys } from './helper'\n\nexport type NewUiValidationOptions =\n | Partial<{\n /**\n * Foreigners or stateless persons (外國人或無國籍人士)\n */\n foreignOrStateless: boolean\n /**\n * Stateless residents (無戶籍國民)\n */\n statelessResident: boolean\n /**\n * Hong Kong or Macao residents (香港澳門居民)\n */\n hkMacaoResident: boolean\n /**\n * Mainland China residents (大陸地區居民)\n */\n mainlandChinaResident: boolean\n }>\n | boolean\n\nexport type UiNumberValidationOptions =\n | Partial<{\n /**\n * Old format UI number (舊版統一證號)\n */\n oldFormat: boolean\n /**\n * New format UI number (新版統一證號)\n */\n newFormat: NewUiValidationOptions\n }>\n | boolean\n\nexport type IdCardValidationOptions = Partial<{\n /**\n * National identification number (身分證字號)\n */\n nationalId: boolean\n /**\n * UI number (統一證號)\n */\n uiNumber: UiNumberValidationOptions\n}>\n\ntype Tree<T> = {\n [key: string]: T | Tree<T>\n}\n\n/**\n * Tree structure containing RegExp patterns for identification numbers\n */\nconst idCardRegExps: Tree<RegExp> = {\n nationalId: /[A-Z][1,2]\\d{8}/,\n uiNumber: {\n oldFormat: /[A-Z][A-D]\\d{8}/,\n newFormat: {\n foreignOrStateless: /[A-Z][89][0-6]\\d{7}/,\n statelessResident: /[A-Z][89][7]\\d{7}/,\n hkMacaoResident: /[A-Z][89][8]\\d{7}/,\n mainlandChinaResident: /[A-Z][89][9]\\d{7}/\n }\n }\n}\n\n/**\n * Collect all the RegExp patterns from a tree structure.\n * If the validation options are specified, only the patterns with the corresponding options will be collected.\n * If the validation options are not specified, all patterns will be collected.\n * Default options are `true` if not specified.\n *\n * @param { Tree<RegExp> } regexTree - The tree structure containing RegExp patterns\n * @param { Tree<boolean> | boolean } validationOptions - The tree structure containing validation options\n * @returns { RegExp[] } An array of RegExp patterns to be used for validation\n */\nconst collectPatterns: (\n regexTree: Tree<RegExp>,\n validationOptions: Tree<boolean> | boolean\n) => RegExp[] = (regexTree, validationOptions) =>\n objectKeys(regexTree).reduce((patterns, key) => {\n const currentRegex = regexTree[key]\n\n const currentOptions =\n typeof validationOptions === 'boolean'\n ? validationOptions\n : validationOptions[key] ?? true // default to true if not specified\n\n return currentRegex instanceof RegExp\n ? currentOptions\n ? patterns.concat(currentRegex)\n : patterns\n : patterns.concat(collectPatterns(currentRegex, currentOptions))\n }, [] as RegExp[])\n\n/**\n * Verify the input is a valid identification number based on provided options.\n *\n * @param { string } input - The identification number to verify\n * @param { IdCardValidationOptions } [options] - Options specifying which types of identification numbers to check\n * @returns `true` if the input is a valid identification number according to the specified options, otherwise `false`\n * @example\n * isIdCardNumber('A123456789') // true\n * isIdCardNumber('A123456789', { nationalId: false }) // false\n */\nexport function isIdCardNumber(\n input: string,\n options: IdCardValidationOptions = {\n nationalId: true,\n uiNumber: true\n }\n): boolean {\n if (typeof input !== 'string') return false\n\n // collect all the patterns based on the options\n const patterns: RegExp[] = collectPatterns(idCardRegExps, options)\n\n // create a regex that matches any of the patterns\n const joinedRegexString = patterns.map(r => r.source).join('|')\n const regex = new RegExp(`^(${joinedRegexString})$`)\n\n return regex.test(input) && verifyTaiwanIdIntermediateString(input)\n}\n\n/**\n * Verify the intermediate string for isNationalIdentificationNumber and isResidentCertificateNumber\n *\n * @param { string } input - String to verify\n * @returns { boolean } is `input` a valid Taiwan ID intermediate string\n * @example\n * verifyTaiwanIdIntermediateString('A123456789') // true\n * verifyTaiwanIdIntermediateString('A123456788') // false\n */\nfunction verifyTaiwanIdIntermediateString(input: string): boolean {\n const intRadix = 10\n\n /**\n * A=10 台北市 J=18 新竹縣 S=26 高雄縣\n * B=11 台中市 K=19 苗栗縣 T=27 屏東縣\n * C=12 基隆市 L=20 台中縣 U=28 花蓮縣\n * D=13 台南市 M=21 南投縣 V=29 台東縣\n * E=14 高雄市 N=22 彰化縣 W=32 金門縣*\n * F=15 台北縣 O=35 新竹市* X=30 澎湖縣\n * G=16 宜蘭縣 P=23 雲林縣 Y=31 陽明山\n * H=17 桃園縣 Q=24 嘉義縣 Z=33 連江縣*\n * I=34 嘉義市* R=25 台南縣\n *\n * Step 1: 英文字母按照上表轉換為數字之後,十位數 * 1 + 個位數 * 9 相加\n */\n const TAIWAN_ID_LOCALE_CODE_LIST = [\n 1, // A -> 10 -> 1 * 1 + 9 * 0 = 1\n 10, // B -> 11 -> 1 * 1 + 9 * 1 = 10\n 19, // C -> 12 -> 1 * 1 + 9 * 2 = 19\n 28, // D\n 37, // E\n 46, // F\n 55, // G\n 64, // H\n 39, // I -> 34 -> 1 * 3 + 9 * 4 = 39\n 73, // J\n 82, // K\n 2, // L\n 11, // M\n 20, // N\n 48, // O -> 35 -> 1 * 3 + 9 * 5 = 48\n 29, // P\n 38, // Q\n 47, // R\n 56, // S\n 65, // T\n 74, // U\n 83, // V\n 21, // W -> 32 -> 1 * 3 + 9 * 2 = 21\n 3, // X\n 12, // Y\n 30 // Z -> 33 -> 1 * 3 + 9 * 3 = 30\n ]\n\n const RESIDENT_CERTIFICATE_NUMBER_LIST = [\n 0, // A\n 1, // B\n 2, // C\n 3, // D\n 4, // E\n 5, // F\n 6, // G\n 7, // H\n 4, // I\n 8, // J\n 9, // K\n 0, // L\n 1, // M\n 2, // N\n 5, // O\n 3, // P\n 4, // Q\n 5, // R\n 6, // S\n 7, // T\n 8, // U\n 9, // V\n 2, // W\n 0, // X\n 1, // Y\n 3 // Z\n ]\n\n const getCharOrder = (s: string, i: number) =>\n s.charCodeAt(i) - 'A'.charCodeAt(0)\n\n const firstDigit = TAIWAN_ID_LOCALE_CODE_LIST[getCharOrder(input, 0)]\n\n const secondDigit = isNaN(parseInt(input[1], intRadix)) // if is not a number (舊版居留證編號)\n ? RESIDENT_CERTIFICATE_NUMBER_LIST[getCharOrder(input, 1)]\n : parseInt(input[1], intRadix)\n\n const rest = input\n .substring(2)\n .split('')\n .map(n => parseInt(n, intRadix))\n\n const idInDigits = [firstDigit, secondDigit, ...rest]\n\n // Step 2: 第 1 位數字 (只能為 1 or 2) 至第 8 位數字分別乘上 8, 7, 6, 5, 4, 3, 2, 1 後相加,再加上第 9 位數字\n\n const ID_COEFFICIENTS = [1, 8, 7, 6, 5, 4, 3, 2, 1, 1]\n const sum = zipWith(idInDigits, ID_COEFFICIENTS, multiply).reduce(add, 0)\n\n // Step 3: 如果該數字為 10 的倍數,則為正確身分證字號\n\n return sum % 10 === 0\n}\n"],"names":["root","factory","exports","module","define","amd","this","__webpack_require__","definition","key","o","Object","defineProperty","enumerable","get","obj","prop","prototype","hasOwnProperty","call","Symbol","toStringTag","value","isCdcNumber","input","n","toString","test","isMobileBarcode","isDonateCode","zipWith","a1","a2","f","length","Math","min","result","i","add","a","b","multiply","objectKeys","keys","isBan","options","applyOldRules","checksum","split","map","c","parseInt","floor","reduce","divisor","charAt","idCardRegExps","nationalId","uiNumber","oldFormat","newFormat","foreignOrStateless","statelessResident","hkMacaoResident","mainlandChinaResident","collectPatterns","regexTree","validationOptions","patterns","currentRegex","currentOptions","RegExp","concat","isIdCardNumber","joinedRegexString","r","source","join","intRadix","RESIDENT_CERTIFICATE_NUMBER_LIST","getCharOrder","s","charCodeAt","firstDigit","secondDigit","isNaN","rest","substring","verifyTaiwanIdIntermediateString"],"sourceRoot":""}