taiwan-validator 1.0.0 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.en.md CHANGED
@@ -1,8 +1,9 @@
1
1
  # Taiwan Validator
2
2
 
3
- A comprehensive TypeScript validator for Taiwan identification numbers and codes.
3
+ A comprehensive TypeScript validator for Taiwan, supporting identification numbers, business codes, license plates, and more.
4
4
 
5
5
  [![CI](https://github.com/imgarylai/taiwan-validator/actions/workflows/test.yml/badge.svg)](https://github.com/imgarylai/taiwan-validator/actions/workflows/test.yml)
6
+ [![codecov](https://codecov.io/gh/imgarylai/taiwan-validator/branch/main/graph/badge.svg)](https://codecov.io/gh/imgarylai/taiwan-validator)
6
7
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
7
8
 
8
9
  [繁體中文](README.md)
@@ -16,6 +17,7 @@ A comprehensive TypeScript validator for Taiwan identification numbers and codes
16
17
  - ✅ Citizen Digital Certificate validation (自然人憑證)
17
18
  - ✅ e-Invoice Mobile Barcode validation (電子發票手機條碼)
18
19
  - ✅ e-Invoice Donation Code validation (電子發票捐贈碼)
20
+ - ✅ License Plate Number validation (車牌號碼) - Supports cars, motorcycles, electric vehicles, and more
19
21
  - 📘 Full TypeScript support with type definitions
20
22
  - 🧪 Thoroughly tested with 100% coverage
21
23
  - 📦 Tree-shakeable ESM and CommonJS support
@@ -38,6 +40,7 @@ import {
38
40
  validateCitizenCertificate,
39
41
  validateEInvoiceMobileBarcode,
40
42
  validateEInvoiceDonationCode,
43
+ validateLicensePlate,
41
44
  } from "taiwan-validator";
42
45
 
43
46
  // National ID (身分證字號)
@@ -63,6 +66,11 @@ validateEInvoiceMobileBarcode("/ABCD123"); // { isValid: true }
63
66
 
64
67
  // e-Invoice Donation Code (電子發票捐贈碼)
65
68
  validateEInvoiceDonationCode("12345"); // { isValid: true }
69
+
70
+ // License Plate Number (車牌號碼)
71
+ validateLicensePlate("ABC-1235"); // { isValid: true, plateType: 'car' }
72
+ validateLicensePlate("EAB-1235"); // { isValid: true, plateType: 'electric-car' }
73
+ validateLicensePlate("AB1-234"); // { isValid: true, plateType: 'motorcycle' }
66
74
  ```
67
75
 
68
76
  ## API Documentation
@@ -144,6 +152,60 @@ Validates Taiwan e-Invoice Donation Code (電子發票捐贈碼).
144
152
  validateEInvoiceDonationCode("12345");
145
153
  ```
146
154
 
155
+ ### `validateLicensePlate(plate: string, options?: { type?: LicensePlateType, detectType?: boolean }): LicensePlateValidationResult`
156
+
157
+ Validates Taiwan license plate numbers, supporting multiple vehicle types.
158
+
159
+ - **Supported Formats**:
160
+ - **New car** (`car`): 3 letters - 4 digits (e.g., `ABC-1235`)
161
+ - Letters I and O are not used
162
+ - Digit 4 is not used
163
+ - **Old car** (`car-old`): 1 digit + 1 letter - 4 digits (e.g., `1A-2345`)
164
+ - **Electric car** (`electric-car`): E + 2 letters - 4 digits (e.g., `EAB-1235`)
165
+ - Letters I and O are not used
166
+ - Digit 4 is not used
167
+ - **Small motorcycle** (`motorcycle-small`):
168
+ - 3 digits - 3 letters (e.g., `123-ABC`)
169
+ - 3 letters - 3 digits (e.g., `ABC-123`)
170
+ - **Regular motorcycle** (`motorcycle`): 2 letters + 1 digit - 3 digits (e.g., `AB1-234`)
171
+
172
+ ```typescript
173
+ // Basic validation (auto-detect plate type)
174
+ validateLicensePlate("ABC-1235");
175
+ // { isValid: true, plateType: 'car' }
176
+
177
+ // Electric car
178
+ validateLicensePlate("EAB-1235");
179
+ // { isValid: true, plateType: 'electric-car' }
180
+
181
+ // Old car format
182
+ validateLicensePlate("1A-2345");
183
+ // { isValid: true, plateType: 'car-old' }
184
+
185
+ // Small motorcycle
186
+ validateLicensePlate("123-ABC");
187
+ // { isValid: true, plateType: 'motorcycle-small' }
188
+
189
+ validateLicensePlate("ABC-123");
190
+ // { isValid: true, plateType: 'motorcycle-small' }
191
+
192
+ // Regular motorcycle
193
+ validateLicensePlate("AB1-234");
194
+ // { isValid: true, plateType: 'motorcycle' }
195
+
196
+ // Validate specific plate type
197
+ validateLicensePlate("ABC-1235", { type: "car" });
198
+ // { isValid: true, plateType: 'car' }
199
+
200
+ // Disable type detection
201
+ validateLicensePlate("ABC-1235", { detectType: false });
202
+ // { isValid: true }
203
+
204
+ // Handles lowercase and whitespace
205
+ validateLicensePlate(" abc-1235 ");
206
+ // { isValid: true, plateType: 'car' }
207
+ ```
208
+
147
209
  ### Return Type
148
210
 
149
211
  All validation functions return a `ValidationResult` object:
@@ -155,6 +217,19 @@ interface ValidationResult {
155
217
  }
156
218
  ```
157
219
 
220
+ License plate validation returns a `LicensePlateValidationResult` with additional plate type information:
221
+
222
+ ```typescript
223
+ interface LicensePlateValidationResult extends ValidationResult {
224
+ plateType?:
225
+ | "car"
226
+ | "car-old"
227
+ | "electric-car"
228
+ | "motorcycle-small"
229
+ | "motorcycle";
230
+ }
231
+ ```
232
+
158
233
  ## Development
159
234
 
160
235
  ### Setup
package/README.md CHANGED
@@ -1,8 +1,9 @@
1
1
  # Taiwan Validator
2
2
 
3
- 一個完整的台灣身分證件與代碼驗證 TypeScript 套件。
3
+ 一個完整的台灣身分驗證 TypeScript 套件,支援身分證件、營業代碼、車牌號碼等多種格式驗證。
4
4
 
5
5
  [![CI](https://github.com/imgarylai/taiwan-validator/actions/workflows/test.yml/badge.svg)](https://github.com/imgarylai/taiwan-validator/actions/workflows/test.yml)
6
+ [![codecov](https://codecov.io/gh/imgarylai/taiwan-validator/branch/main/graph/badge.svg)](https://codecov.io/gh/imgarylai/taiwan-validator)
6
7
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
7
8
 
8
9
  [English](README.en.md)
@@ -16,6 +17,7 @@
16
17
  - ✅ 自然人憑證驗證
17
18
  - ✅ 電子發票手機條碼驗證
18
19
  - ✅ 電子發票捐贈碼驗證
20
+ - ✅ 車牌號碼驗證 - 支援汽車、機車、電動車等多種格式
19
21
  - 📘 完整的 TypeScript 型別定義
20
22
  - 🧪 完整測試覆蓋率
21
23
  - 📦 支援 ESM 和 CommonJS 且可 Tree-shaking
@@ -38,6 +40,7 @@ import {
38
40
  validateCitizenCertificate,
39
41
  validateEInvoiceMobileBarcode,
40
42
  validateEInvoiceDonationCode,
43
+ validateLicensePlate,
41
44
  } from "taiwan-validator";
42
45
 
43
46
  // 身分證字號
@@ -63,6 +66,11 @@ validateEInvoiceMobileBarcode("/ABCD123"); // { isValid: true }
63
66
 
64
67
  // 電子發票捐贈碼
65
68
  validateEInvoiceDonationCode("12345"); // { isValid: true }
69
+
70
+ // 車牌號碼
71
+ validateLicensePlate("ABC-1235"); // { isValid: true, plateType: 'car' }
72
+ validateLicensePlate("EAB-1235"); // { isValid: true, plateType: 'electric-car' }
73
+ validateLicensePlate("AB1-234"); // { isValid: true, plateType: 'motorcycle' }
66
74
  ```
67
75
 
68
76
  ## API 文件
@@ -144,6 +152,60 @@ validateEInvoiceMobileBarcode("/ABCD123");
144
152
  validateEInvoiceDonationCode("12345");
145
153
  ```
146
154
 
155
+ ### `validateLicensePlate(plate: string, options?: { type?: LicensePlateType, detectType?: boolean }): LicensePlateValidationResult`
156
+
157
+ 驗證台灣車牌號碼,支援多種車輛類型。
158
+
159
+ - **支援格式**:
160
+ - **新制汽車** (`car`):3個英文字母 - 4個數字(例如:`ABC-1235`)
161
+ - 不使用字母 I、O
162
+ - 不使用數字 4
163
+ - **舊制汽車** (`car-old`):1個數字 + 1個英文字母 - 4個數字(例如:`1A-2345`)
164
+ - **電動汽車** (`electric-car`):E + 2個英文字母 - 4個數字(例如:`EAB-1235`)
165
+ - 不使用字母 I、O
166
+ - 不使用數字 4
167
+ - **小型機車** (`motorcycle-small`):
168
+ - 3個數字 - 3個英文字母(例如:`123-ABC`)
169
+ - 3個英文字母 - 3個數字(例如:`ABC-123`)
170
+ - **一般機車** (`motorcycle`):2個英文字母 + 1個數字 - 3個數字(例如:`AB1-234`)
171
+
172
+ ```typescript
173
+ // 基本驗證(自動偵測車牌類型)
174
+ validateLicensePlate("ABC-1235");
175
+ // { isValid: true, plateType: 'car' }
176
+
177
+ // 電動汽車
178
+ validateLicensePlate("EAB-1235");
179
+ // { isValid: true, plateType: 'electric-car' }
180
+
181
+ // 舊制汽車
182
+ validateLicensePlate("1A-2345");
183
+ // { isValid: true, plateType: 'car-old' }
184
+
185
+ // 小型機車
186
+ validateLicensePlate("123-ABC");
187
+ // { isValid: true, plateType: 'motorcycle-small' }
188
+
189
+ validateLicensePlate("ABC-123");
190
+ // { isValid: true, plateType: 'motorcycle-small' }
191
+
192
+ // 一般機車
193
+ validateLicensePlate("AB1-234");
194
+ // { isValid: true, plateType: 'motorcycle' }
195
+
196
+ // 指定車牌類型驗證
197
+ validateLicensePlate("ABC-1235", { type: "car" });
198
+ // { isValid: true, plateType: 'car' }
199
+
200
+ // 不偵測車牌類型
201
+ validateLicensePlate("ABC-1235", { detectType: false });
202
+ // { isValid: true }
203
+
204
+ // 處理小寫和空格
205
+ validateLicensePlate(" abc-1235 ");
206
+ // { isValid: true, plateType: 'car' }
207
+ ```
208
+
147
209
  ### 回傳型別
148
210
 
149
211
  所有驗證函式都會回傳 `ValidationResult` 物件:
@@ -155,6 +217,19 @@ interface ValidationResult {
155
217
  }
156
218
  ```
157
219
 
220
+ 車牌驗證函式會回傳 `LicensePlateValidationResult`,包含額外的車牌類型資訊:
221
+
222
+ ```typescript
223
+ interface LicensePlateValidationResult extends ValidationResult {
224
+ plateType?:
225
+ | "car"
226
+ | "car-old"
227
+ | "electric-car"
228
+ | "motorcycle-small"
229
+ | "motorcycle";
230
+ }
231
+ ```
232
+
158
233
  ## 開發
159
234
 
160
235
  ### 設定
package/dist/index.cjs CHANGED
@@ -1,2 +1,2 @@
1
- 'use strict';var V={A:10,B:11,C:12,D:13,E:14,F:15,G:16,H:17,I:34,J:18,K:19,L:20,M:21,N:22,O:35,P:23,Q:24,R:25,S:26,T:27,U:28,V:29,W:32,X:30,Y:31,Z:33};function R(t){if(!/^[A-Z][12]\d{8}$/.test(t))return false;let s=t[0],i=t.slice(1),r=V[s],e=Math.floor(r/10),a=r%10,o=[1,9,8,7,6,5,4,3,2,1,1];return [e,a,...i.split("").map(Number)].reduce((d,u,f)=>d+u*o[f],0)%10===0}function v(t){if(!/^[A-Z]{2}\d{8}$/.test(t))return false;let s=t[0],i=t[1],r=t.slice(2),e=V[s],a=V[i],o=Math.floor(e/10),l=e%10,c=Math.floor(a/10),d=a%10,u=[1,9,8,7,6,5,4,3,2,1,1,1];return [o,l,c,d,...r.split("").map(Number)].reduce((m,p,g)=>m+p*u[g],0)%10===0}function I(t){return /^[A-Z][12]\d{8}$/.test(t)?"old":/^[A-Z]{2}\d{8}$/.test(t)?"new":null}function x(t,n){if(!t||typeof t!="string")return {isValid:false,message:"\u8EAB\u5206\u8B49\u5B57\u865F\u5FC5\u9808\u70BA\u975E\u7A7A\u5B57\u4E32"};let s=t.trim().toUpperCase();if(n==="old"){let e=R(s);return {isValid:e,message:e?void 0:"\u7121\u6548\u7684\u820A\u5F0F\u8EAB\u5206\u8B49\u5B57\u865F"}}if(n==="new"){let e=v(s);return {isValid:e,message:e?void 0:"\u7121\u6548\u7684\u65B0\u5F0F\u8EAB\u5206\u8B49\u5B57\u865F"}}let i=I(s);if(!i)return {isValid:false,message:"\u7121\u6548\u7684\u8EAB\u5206\u8B49\u5B57\u865F\u683C\u5F0F"};let r=i==="old"?R(s):v(s);return {isValid:r,message:r?void 0:`\u7121\u6548\u7684${i==="old"?"\u820A\u5F0F":"\u65B0\u5F0F"}\u8EAB\u5206\u8B49\u5B57\u865F`}}function A(t){if(!t||typeof t!="string")return {isValid:false,message:"\u7D71\u4E00\u7DE8\u865F\u5FC5\u9808\u70BA\u975E\u7A7A\u5B57\u4E32"};let n=t.trim();if(!/^\d{8}$/.test(n))return {isValid:false,message:"\u7D71\u4E00\u7DE8\u865F\u5FC5\u9808\u70BA8\u4F4D\u6578\u5B57"};let i=n.split("").map(Number),r=[1,2,1,2,1,2,4,1],e=0;for(let o=0;o<8;o++){let l=i[o]*r[o];l>=10&&(l=Math.floor(l/10)+l%10),e+=l;}let a=e%10===0||i[6]===7&&e%10===1;return {isValid:a,message:a?void 0:"\u7D71\u4E00\u7DE8\u865F\u6AA2\u67E5\u78BC\u932F\u8AA4"}}var y={A:10,B:11,C:12,D:13,E:14,F:15,G:16,H:17,I:34,J:18,K:19,L:20,M:21,N:22,O:35,P:23,Q:24,R:25,S:26,T:27,U:28,V:29,W:32,X:30,Y:31,Z:33};function b(t){if(!/^[A-D][89]\d{8}$/.test(t))return false;let s=t[0],i=t.slice(1),r=y[s],e=Math.floor(r/10),a=r%10,o=[1,9,8,7,6,5,4,3,2,1,1];return [e,a,...i.split("").map(Number)].reduce((d,u,f)=>d+u*o[f],0)%10===0}function C(t){if(!/^[A-Z]{2}\d{8}$/.test(t))return false;let s=t[0],i=t[1],r=t.slice(2),e=y[s],a=y[i],o=Math.floor(e/10),l=e%10,c=Math.floor(a/10),d=a%10,u=[1,9,8,7,6,5,4,3,2,1,1,1];return [o,l,c,d,...r.split("").map(Number)].reduce((m,p,g)=>m+p*u[g],0)%10===0}function M(t){return /^[A-D][89]\d{8}$/.test(t)?"old":/^[A-Z]{2}\d{8}$/.test(t)?"new":null}function $(t,n){if(!t||typeof t!="string")return {isValid:false,message:"\u5C45\u7559\u8B49\u865F\u5FC5\u9808\u70BA\u975E\u7A7A\u5B57\u4E32"};let s=t.trim().toUpperCase();if(n==="old"){let e=b(s);return {isValid:e,message:e?void 0:"\u7121\u6548\u7684\u820A\u5F0F\u5C45\u7559\u8B49\u865F"}}if(n==="new"){let e=C(s);return {isValid:e,message:e?void 0:"\u7121\u6548\u7684\u65B0\u5F0F\u5C45\u7559\u8B49\u865F"}}let i=M(s);if(!i)return {isValid:false,message:"\u7121\u6548\u7684\u5C45\u7559\u8B49\u865F\u683C\u5F0F"};let r=i==="old"?b(s):C(s);return {isValid:r,message:r?void 0:`\u7121\u6548\u7684${i==="old"?"\u820A\u5F0F":"\u65B0\u5F0F"}\u5C45\u7559\u8B49\u865F`}}function T(t){if(!t||typeof t!="string")return {isValid:false,message:"\u624B\u6A5F\u865F\u78BC\u5FC5\u9808\u70BA\u975E\u7A7A\u5B57\u4E32"};let n=t.trim().replace(/[\s\-()]/g,"");return /^09\d{8}$/.test(n)?{isValid:true}:{isValid:false,message:"\u624B\u6A5F\u865F\u78BC\u5FC5\u9808\u4EE509\u958B\u982D\u4E14\u70BA10\u4F4D\u6578\u5B57"}}function h(t){if(!t||typeof t!="string")return {isValid:false,message:"\u81EA\u7136\u4EBA\u6191\u8B49\u7DE8\u865F\u5FC5\u9808\u70BA\u975E\u7A7A\u5B57\u4E32"};let n=t.trim().toUpperCase();return /^[A-Z]{2}\d{14}$/.test(n)?{isValid:true}:{isValid:false,message:"\u81EA\u7136\u4EBA\u6191\u8B49\u7DE8\u865F\u5FC5\u9808\u70BA2\u500B\u82F1\u6587\u5B57\u6BCD\u52A0\u4E0A14\u4F4D\u6578\u5B57"}}function L(t){if(!t||typeof t!="string")return {isValid:false,message:"\u624B\u6A5F\u689D\u78BC\u5FC5\u9808\u70BA\u975E\u7A7A\u5B57\u4E32"};let n=t.trim().toUpperCase();return /^\/[A-Z0-9+.-]{7}$/.test(n)?{isValid:true}:{isValid:false,message:"\u624B\u6A5F\u689D\u78BC\u5FC5\u9808\u4EE5 / \u958B\u982D\uFF0C\u5F8C\u63A57\u500B\u6709\u6548\u5B57\u5143\uFF08A-Z\u30010-9\u3001+\u3001-\u3001.\uFF09"}}function w(t){if(!t||typeof t!="string")return {isValid:false,message:"\u6350\u8D08\u78BC\u5FC5\u9808\u70BA\u975E\u7A7A\u5B57\u4E32"};let n=t.trim();return /^\d{3,7}$/.test(n)?{isValid:true}:{isValid:false,message:"\u6350\u8D08\u78BC\u5FC5\u9808\u70BA3\u81F37\u4F4D\u6578\u5B57"}}exports.validateBusinessNumber=A;exports.validateCitizenCertificate=h;exports.validateEInvoiceDonationCode=w;exports.validateEInvoiceMobileBarcode=L;exports.validateMobilePhone=T;exports.validateNationalId=x;exports.validateResidentCertificate=$;//# sourceMappingURL=index.cjs.map
1
+ 'use strict';var d={A:10,B:11,C:12,D:13,E:14,F:15,G:16,H:17,I:34,J:18,K:19,L:20,M:21,N:22,O:35,P:23,Q:24,R:25,S:26,T:27,U:28,V:29,W:32,X:30,Y:31,Z:33},p={A:"\u81FA\u5317\u5E02",B:"\u81FA\u4E2D\u5E02",C:"\u57FA\u9686\u5E02",D:"\u81FA\u5357\u5E02",E:"\u9AD8\u96C4\u5E02",F:"\u65B0\u5317\u5E02",G:"\u5B9C\u862D\u7E23",H:"\u6843\u5712\u5E02",I:"\u5609\u7FA9\u5E02",J:"\u65B0\u7AF9\u7E23",K:"\u82D7\u6817\u7E23",L:"\u81FA\u4E2D\u7E23",M:"\u5357\u6295\u7E23",N:"\u5F70\u5316\u7E23",O:"\u65B0\u7AF9\u5E02",P:"\u96F2\u6797\u7E23",Q:"\u5609\u7FA9\u7E23",R:"\u81FA\u5357\u7E23",S:"\u9AD8\u96C4\u7E23",T:"\u5C4F\u6771\u7E23",U:"\u82B1\u84EE\u7E23",V:"\u81FA\u6771\u7E23",W:"\u91D1\u9580\u7E23",X:"\u6F8E\u6E56\u7E23",Y:"\u967D\u660E\u5C71\u7BA1\u7406\u5C40",Z:"\u9023\u6C5F\u7E23"};function y(t){if(!/^[A-Z][12]\d{8}$/.test(t))return false;let i=t[0],s=t.slice(1),r=d[i],n=Math.floor(r/10),a=r%10,o=[1,9,8,7,6,5,4,3,2,1,1];return [n,a,...s.split("").map(Number)].reduce((c,f,u)=>c+f*o[u],0)%10===0}function A(t,e){if(!t||typeof t!="string")return {isValid:false,message:"\u8EAB\u5206\u8B49\u5B57\u865F\u5FC5\u9808\u70BA\u975E\u7A7A\u5B57\u4E32"};let i=t.trim().toUpperCase(),s=y(i);return {isValid:s,message:s?void 0:"\u7121\u6548\u7684\u8EAB\u5206\u8B49\u5B57\u865F"}}function b(t){if(!t||typeof t!="string")return {isValid:false,message:"\u8EAB\u5206\u8B49\u5B57\u865F\u5FC5\u9808\u70BA\u975E\u7A7A\u5B57\u4E32"};let e=t.trim().toUpperCase();if(!y(e))return {isValid:false,message:"\u7121\u6548\u7684\u8EAB\u5206\u8B49\u5B57\u865F"};let s=e[0],n=e[1]==="1"?"male":"female",a=p[s];return {isValid:true,gender:n,region:a}}function h(t){if(!t||typeof t!="string")return {isValid:false,message:"\u7D71\u4E00\u7DE8\u865F\u5FC5\u9808\u70BA\u975E\u7A7A\u5B57\u4E32"};let e=t.trim();if(!/^\d{8}$/.test(e))return {isValid:false,message:"\u7D71\u4E00\u7DE8\u865F\u5FC5\u9808\u70BA8\u4F4D\u6578\u5B57"};let s=e.split("").map(Number),r=[1,2,1,2,1,2,4,1],n=0;for(let o=0;o<8;o++){let l=s[o]*r[o];l>=10&&(l=Math.floor(l/10)+l%10),n+=l;}let a=n%10===0||s[6]===7&&n%10===1;return {isValid:a,message:a?void 0:"\u7D71\u4E00\u7DE8\u865F\u6AA2\u67E5\u78BC\u932F\u8AA4"}}function $(t){if(!t||typeof t!="string")return {isValid:false,message:"\u767C\u7968\u865F\u78BC\u5FC5\u9808\u70BA\u975E\u7A7A\u5B57\u4E32"};let e=t.replace(/[-\s]/g,"").toUpperCase();return /^[A-Z]{2}\d{8}$/.test(e)?{isValid:true}:{isValid:false,message:"\u767C\u7968\u865F\u78BC\u683C\u5F0F\u5FC5\u9808\u70BA2\u78BC\u82F1\u6587\u82078\u78BC\u6578\u5B57"}}function g(t){if(!/^[A-Z][A-D]\d{8}$/.test(t))return false;let i=t[0],s=t[1],r=t.slice(2),n=d[i],a=d[s],o=Math.floor(n/10),l=n%10,m=a%10,c=[1,9,8,7,6,5,4,3,2,1,1];return [o,l,m,...r.split("").map(Number)].reduce((x,N,T)=>x+N*c[T],0)%10===0}function V(t){if(!/^[A-Z][89]\d{8}$/.test(t))return false;let i=t[0],s=t.slice(1),r=d[i],n=Math.floor(r/10),a=r%10,o=[1,9,8,7,6,5,4,3,2,1,1];return [n,a,...s.split("").map(Number)].reduce((c,f,u)=>c+f*o[u],0)%10===0}function R(t){return /^[A-Z][A-D]\d{8}$/.test(t)?"old":/^[A-Z][89]\d{8}$/.test(t)?"new":null}function E(t,e){if(!t||typeof t!="string")return {isValid:false,message:"\u5C45\u7559\u8B49\u865F\u5FC5\u9808\u70BA\u975E\u7A7A\u5B57\u4E32"};let i=t.trim().toUpperCase();if(e==="old"){let n=g(i);return {isValid:n,message:n?void 0:"\u7121\u6548\u7684\u820A\u5F0F\u5C45\u7559\u8B49\u865F"}}if(e==="new"){let n=V(i);return {isValid:n,message:n?void 0:"\u7121\u6548\u7684\u65B0\u5F0F\u5C45\u7559\u8B49\u865F"}}let s=R(i);if(!s)return {isValid:false,message:"\u7121\u6548\u7684\u5C45\u7559\u8B49\u865F\u683C\u5F0F"};let r=s==="old"?g(i):V(i);return {isValid:r,message:r?void 0:`\u7121\u6548\u7684${s==="old"?"\u820A\u5F0F":"\u65B0\u5F0F"}\u5C45\u7559\u8B49\u865F`}}function z(t){if(!t||typeof t!="string")return {isValid:false,message:"\u5C45\u7559\u8B49\u865F\u5FC5\u9808\u70BA\u975E\u7A7A\u5B57\u4E32"};let e=t.trim().toUpperCase(),i=R(e);if(!i)return {isValid:false,message:"\u7121\u6548\u7684\u5C45\u7559\u8B49\u865F\u683C\u5F0F"};if(!(i==="old"?g(e):V(e)))return {isValid:false,message:`\u7121\u6548\u7684${i==="old"?"\u820A\u5F0F":"\u65B0\u5F0F"}\u5C45\u7559\u8B49\u865F`};let r=e[0],n=e[1],a=p[r],o,l;return i==="new"?(o=n==="8"?"male":"female",l="foreigner"):(o=n==="A"||n==="C"?"male":"female",l=n==="A"||n==="B"?"non-citizen":"foreigner"),{isValid:true,format:i,gender:o,region:a,identityType:l}}function M(t){if(!t||typeof t!="string")return {isValid:false,message:"\u624B\u6A5F\u865F\u78BC\u5FC5\u9808\u70BA\u975E\u7A7A\u5B57\u4E32"};let e=t.trim().replace(/[\s\-()]/g,"");return /^09\d{8}$/.test(e)?{isValid:true}:{isValid:false,message:"\u624B\u6A5F\u865F\u78BC\u5FC5\u9808\u4EE509\u958B\u982D\u4E14\u70BA10\u4F4D\u6578\u5B57"}}var Z=[{code:"0826",totalLength:9},{code:"0836",totalLength:9},{code:"037",totalLength:9},{code:"049",totalLength:9},{code:"082",totalLength:9},{code:"089",totalLength:9},{code:"02",totalLength:10},{code:"03",totalLength:9},{code:"04",totalLength:10},{code:"05",totalLength:9},{code:"06",totalLength:9},{code:"07",totalLength:9},{code:"08",totalLength:9}];function G(t){if(!t||typeof t!="string")return {isValid:false,message:"\u96FB\u8A71\u865F\u78BC\u5FC5\u9808\u70BA\u975E\u7A7A\u5B57\u4E32"};let e=t.replace(/[^\d]/g,""),i=Z.find(s=>e.startsWith(s.code));return i?e.length!==i.totalLength?{isValid:false,message:`\u8A72\u5340\u78BC\u7684\u96FB\u8A71\u865F\u78BC\u9577\u5EA6\u61C9\u70BA ${i.totalLength} \u78BC`}:{isValid:true}:{isValid:false,message:"\u7121\u6548\u7684\u53F0\u7063\u5E02\u8A71\u5340\u78BC"}}function U(t){if(t==null)return {isValid:false,message:"\u90F5\u905E\u5340\u865F\u5FC5\u9808\u70BA\u975E\u7A7A\u5B57\u4E32\u6216\u6578\u5B57"};let e=String(t).trim().replace(/[-\s]/g,"");return /^[1-9]\d{2}$|^[1-9]\d{4}$|^[1-9]\d{5}$/.test(e)?{isValid:true}:{isValid:false,message:"\u90F5\u905E\u5340\u865F\u683C\u5F0F\u5FC5\u9808\u70BA\u9996\u78BC\u975E0\u76843\u78BC\u30015\u78BC\u62166\u78BC\u6578\u5B57"}}function w(t){if(!t||typeof t!="string")return {isValid:false,message:"\u81EA\u7136\u4EBA\u6191\u8B49\u7DE8\u865F\u5FC5\u9808\u70BA\u975E\u7A7A\u5B57\u4E32"};let e=t.trim().toUpperCase();return /^[A-Z]{2}\d{14}$/.test(e)?{isValid:true}:{isValid:false,message:"\u81EA\u7136\u4EBA\u6191\u8B49\u7DE8\u865F\u5FC5\u9808\u70BA2\u500B\u82F1\u6587\u5B57\u6BCD\u52A0\u4E0A14\u4F4D\u6578\u5B57"}}function D(t){if(!t||typeof t!="string")return {isValid:false,message:"\u5065\u4FDD\u5361\u865F\u5FC5\u9808\u70BA\u975E\u7A7A\u5B57\u4E32"};let e=t.replace(/[-\s]/g,"");return /^\d{12}$/.test(e)?{isValid:true}:{isValid:false,message:"\u5065\u4FDD\u5361\u865F\u683C\u5F0F\u5FC5\u9808\u70BA12\u78BC\u6578\u5B57"}}function O(t){if(!t||typeof t!="string")return {isValid:false,message:"\u8B77\u7167\u865F\u78BC\u5FC5\u9808\u70BA\u975E\u7A7A\u5B57\u4E32"};let e=t.trim();return /^\d{9}$/.test(e)?{isValid:true}:{isValid:false,message:"\u8B77\u7167\u865F\u78BC\u683C\u5F0F\u5FC5\u9808\u70BA9\u4F4D\u6578\u5B57"}}function _(t){if(!t||typeof t!="string")return {isValid:false,message:"\u624B\u6A5F\u689D\u78BC\u5FC5\u9808\u70BA\u975E\u7A7A\u5B57\u4E32"};let e=t.trim().toUpperCase();return /^\/[A-Z0-9+.-]{7}$/.test(e)?{isValid:true}:{isValid:false,message:"\u624B\u6A5F\u689D\u78BC\u5FC5\u9808\u4EE5 / \u958B\u982D\uFF0C\u5F8C\u63A57\u500B\u6709\u6548\u5B57\u5143\uFF08A-Z\u30010-9\u3001+\u3001-\u3001.\uFF09"}}function B(t){if(!t||typeof t!="string")return {isValid:false,message:"\u6350\u8D08\u78BC\u5FC5\u9808\u70BA\u975E\u7A7A\u5B57\u4E32"};let e=t.trim();return /^\d{3,7}$/.test(e)?{isValid:true}:{isValid:false,message:"\u6350\u8D08\u78BC\u5FC5\u9808\u70BA3\u81F37\u4F4D\u6578\u5B57"}}function P(t){return /^[A-HJ-NP-Z]{3}-\d{4}$/.test(t)?!t.split("-")[1].includes("4"):false}function L(t){return /^\d[A-Z]-\d{4}$/.test(t)}function C(t){return /^E[A-HJ-NP-Z]{2}-\d{4}$/.test(t)?!t.split("-")[1].includes("4"):false}function I(t){let e=/^\d{3}-[A-Z]{3}$/,i=/^[A-Z]{3}-\d{3}$/;return e.test(t)||i.test(t)}function v(t){return /^[A-Z]{2}\d-\d{3}$/.test(t)}function F(t){return C(t)?"electric-car":P(t)?"car":L(t)?"car-old":I(t)?"motorcycle-small":v(t)?"motorcycle":null}function k(t,e={}){let{type:i,detectType:s=true}=e;if(!t||typeof t!="string")return {isValid:false,message:"\u8ECA\u724C\u865F\u78BC\u5FC5\u9808\u70BA\u975E\u7A7A\u5B57\u4E32"};let r=t.trim().toUpperCase();if(i){let a=false;switch(i){case "car":a=P(r);break;case "car-old":a=L(r);break;case "electric-car":a=C(r);break;case "motorcycle-small":a=I(r);break;case "motorcycle":a=v(r);break}return {isValid:a,message:a?void 0:`\u7121\u6548\u7684${H(i)}\u8ECA\u724C\u865F\u78BC`,plateType:a&&s?i:void 0}}let n=F(r);return n?{isValid:true,plateType:s?n:void 0}:{isValid:false,message:"\u7121\u6548\u7684\u8ECA\u724C\u865F\u78BC\u683C\u5F0F"}}function H(t){return {car:"\u6C7D\u8ECA","car-old":"\u6C7D\u8ECA\uFF08\u820A\u5236\uFF09","electric-car":"\u96FB\u52D5\u6C7D\u8ECA","motorcycle-small":"\u5C0F\u578B\u6A5F\u8ECA",motorcycle:"\u6A5F\u8ECA"}[t]}exports.parseNationalId=b;exports.parseResidentCertificate=z;exports.validateBusinessNumber=h;exports.validateCitizenCertificate=w;exports.validateEInvoiceDonationCode=B;exports.validateEInvoiceMobileBarcode=_;exports.validateLandlinePhone=G;exports.validateLicensePlate=k;exports.validateMobilePhone=M;exports.validateNHICard=D;exports.validateNationalId=A;exports.validatePassport=O;exports.validatePostalCode=U;exports.validateResidentCertificate=E;exports.validateUniformInvoice=$;//# sourceMappingURL=index.cjs.map
2
2
  //# sourceMappingURL=index.cjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/validators/national-id.ts","../src/validators/business-number.ts","../src/validators/resident-certificate.ts","../src/validators/mobile-phone.ts","../src/validators/citizen-certificate.ts","../src/validators/einvoice-mobile-barcode.ts","../src/validators/einvoice-donation-code.ts"],"names":["LETTER_MAPPING","validateOldFormat","id","letter","numbers","letterValue","d1","d2","weights","acc","digit","index","validateNewFormat","firstLetter","secondLetter","firstLetterValue","secondLetterValue","d3","d4","detectFormat","validateNationalId","format","normalizedId","isValid","detectedFormat","validateBusinessNumber","number","normalized","digits","sum","i","product","validateResidentCertificate","validateMobilePhone","phone","validateCitizenCertificate","certNumber","validateEInvoiceMobileBarcode","barcode","validateEInvoiceDonationCode","code"],"mappings":"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","file":"index.cjs","sourcesContent":["import type { ValidationResult, NationalIdType } from \"../types\";\n\n/**\n * 字母對應數字表(用於身分證字號驗證)\n */\nconst LETTER_MAPPING: Record<string, number> = {\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/**\n * 驗證舊式身分證字號格式(1個字母 + 9個數字)\n * 格式:A123456789\n * - 第一個字元:地區代碼(字母)\n * - 第二個字元:性別(1 = 男性,2 = 女性)\n * - 最後一個字元:檢查碼\n */\nfunction validateOldFormat(id: string): boolean {\n const pattern = /^[A-Z][12]\\d{8}$/;\n if (!pattern.test(id)) {\n return false;\n }\n\n const letter = id[0] as string;\n const numbers = id.slice(1);\n\n const letterValue = LETTER_MAPPING[letter] as number;\n\n // 計算檢查碼\n const d1 = Math.floor(letterValue / 10);\n const d2 = letterValue % 10;\n\n const weights = [1, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1];\n const digits = [d1, d2, ...numbers.split(\"\").map(Number)];\n\n const sum = digits.reduce(\n (acc, digit, index) => acc + digit * weights[index]!,\n 0,\n );\n\n return sum % 10 === 0;\n}\n\n/**\n * 驗證新式身分證字號格式(2個字母 + 8個數字)\n * 格式:AA12345678\n * - 第一個字元:地區代碼(字母)\n * - 第二個字元:性別(8 = 男性,9 = 女性)以字母表示\n * - 最後一個字元:檢查碼\n */\nfunction validateNewFormat(id: string): boolean {\n const pattern = /^[A-Z]{2}\\d{8}$/;\n if (!pattern.test(id)) {\n return false;\n }\n\n const firstLetter = id[0] as string;\n const secondLetter = id[1] as string;\n const numbers = id.slice(2);\n\n const firstLetterValue = LETTER_MAPPING[firstLetter] as number;\n const secondLetterValue = LETTER_MAPPING[secondLetter] as number;\n\n // 計算新式格式的檢查碼\n const d1 = Math.floor(firstLetterValue / 10);\n const d2 = firstLetterValue % 10;\n const d3 = Math.floor(secondLetterValue / 10);\n const d4 = secondLetterValue % 10;\n\n const weights = [1, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1];\n const digits = [d1, d2, d3, d4, ...numbers.split(\"\").map(Number)];\n\n const sum = digits.reduce(\n (acc, digit, index) => acc + digit * weights[index]!,\n 0,\n );\n\n return sum % 10 === 0;\n}\n\n/**\n * 偵測身分證字號格式類型\n */\nfunction detectFormat(id: string): NationalIdType | null {\n if (/^[A-Z][12]\\d{8}$/.test(id)) {\n return \"old\";\n }\n if (/^[A-Z]{2}\\d{8}$/.test(id)) {\n return \"new\";\n }\n return null;\n}\n\n/**\n * 驗證台灣身分證字號(支援新舊格式)\n * @param id - 要驗證的身分證字號\n * @param format - 可選:指定格式類型('old' 或 'new')\n * @returns 驗證結果\n *\n * @example\n * ```typescript\n * validateNationalId('A123456789'); // 舊式格式\n * validateNationalId('AA12345678'); // 新式格式\n * ```\n */\nexport function validateNationalId(\n id: string,\n format?: NationalIdType,\n): ValidationResult {\n if (!id || typeof id !== \"string\") {\n return {\n isValid: false,\n message: \"身分證字號必須為非空字串\",\n };\n }\n\n const normalizedId = id.trim().toUpperCase();\n\n // 如果指定了格式,只驗證該格式\n if (format === \"old\") {\n const isValid = validateOldFormat(normalizedId);\n return {\n isValid,\n message: isValid ? undefined : \"無效的舊式身分證字號\",\n };\n }\n\n if (format === \"new\") {\n const isValid = validateNewFormat(normalizedId);\n return {\n isValid,\n message: isValid ? undefined : \"無效的新式身分證字號\",\n };\n }\n\n // 自動偵測格式\n const detectedFormat = detectFormat(normalizedId);\n\n if (!detectedFormat) {\n return {\n isValid: false,\n message: \"無效的身分證字號格式\",\n };\n }\n\n const isValid =\n detectedFormat === \"old\"\n ? validateOldFormat(normalizedId)\n : validateNewFormat(normalizedId);\n\n return {\n isValid,\n message: isValid\n ? undefined\n : `無效的${detectedFormat === \"old\" ? \"舊式\" : \"新式\"}身分證字號`,\n };\n}\n","import type { ValidationResult } from \"../types\";\n\n/**\n * 驗證台灣營利事業統一編號\n * 格式:8位數字\n * 使用加權檢查碼演算法\n *\n * @param number - 要驗證的統一編號\n * @returns 驗證結果\n *\n * @example\n * ```typescript\n * validateBusinessNumber('12345678');\n * ```\n */\nexport function validateBusinessNumber(number: string): ValidationResult {\n if (!number || typeof number !== \"string\") {\n return {\n isValid: false,\n message: \"統一編號必須為非空字串\",\n };\n }\n\n const normalized = number.trim();\n\n // 檢查是否為8位數字\n const pattern = /^\\d{8}$/;\n if (!pattern.test(normalized)) {\n return {\n isValid: false,\n message: \"統一編號必須為8位數字\",\n };\n }\n\n const digits = normalized.split(\"\").map(Number);\n const weights = [1, 2, 1, 2, 1, 2, 4, 1];\n\n // 計算加權總和\n let sum = 0;\n for (let i = 0; i < 8; i++) {\n let product = digits[i]! * weights[i]!;\n\n // 如果乘積為兩位數,將十位數和個位數相加\n if (product >= 10) {\n product = Math.floor(product / 10) + (product % 10);\n }\n\n sum += product;\n }\n\n // 特殊情況:第7位數字為7時\n // 如果第7位數字為7且總和除以10的餘數為1,也視為有效\n const isValid = sum % 10 === 0 || (digits[6]! === 7 && sum % 10 === 1);\n\n return {\n isValid,\n message: isValid ? undefined : \"統一編號檢查碼錯誤\",\n };\n}\n","import type { ValidationResult, ResidentCertificateType } from \"../types\";\n\n/**\n * 字母對應數字表(用於居留證號驗證)\n */\nconst LETTER_MAPPING: Record<string, number> = {\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/**\n * 驗證舊式居留證號格式(1個字母 + 9個數字)\n * 格式:A800000000\n * - 第一個字元:地區代碼(A、B、C 或 D 表示外國人士)\n * - 第二個字元:性別/類型(8 = 男性,9 = 女性)\n * - 最後一個字元:檢查碼\n */\nfunction validateOldFormat(id: string): boolean {\n const pattern = /^[A-D][89]\\d{8}$/;\n if (!pattern.test(id)) {\n return false;\n }\n\n const letter = id[0] as string;\n const numbers = id.slice(1);\n\n const letterValue = LETTER_MAPPING[letter] as number;\n\n // 計算檢查碼(與身分證字號相同的演算法)\n const d1 = Math.floor(letterValue / 10);\n const d2 = letterValue % 10;\n\n const weights = [1, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1];\n const digits = [d1, d2, ...numbers.split(\"\").map(Number)];\n\n const sum = digits.reduce(\n (acc, digit, index) => acc + digit * weights[index]!,\n 0,\n );\n\n return sum % 10 === 0;\n}\n\n/**\n * 驗證新式居留證號格式(2個字母 + 8個數字)\n * 格式:AA12345678\n * - 第一個字元:地區代碼(字母)\n * - 第二個字元:性別(8 = 男性,9 = 女性)以字母表示\n * - 最後一個字元:檢查碼\n */\nfunction validateNewFormat(id: string): boolean {\n const pattern = /^[A-Z]{2}\\d{8}$/;\n if (!pattern.test(id)) {\n return false;\n }\n\n const firstLetter = id[0] as string;\n const secondLetter = id[1] as string;\n const numbers = id.slice(2);\n\n const firstLetterValue = LETTER_MAPPING[firstLetter] as number;\n const secondLetterValue = LETTER_MAPPING[secondLetter] as number;\n\n // 計算新式格式的檢查碼\n const d1 = Math.floor(firstLetterValue / 10);\n const d2 = firstLetterValue % 10;\n const d3 = Math.floor(secondLetterValue / 10);\n const d4 = secondLetterValue % 10;\n\n const weights = [1, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1];\n const digits = [d1, d2, d3, d4, ...numbers.split(\"\").map(Number)];\n\n const sum = digits.reduce(\n (acc, digit, index) => acc + digit * weights[index]!,\n 0,\n );\n\n return sum % 10 === 0;\n}\n\n/**\n * 偵測居留證號格式類型\n */\nfunction detectFormat(id: string): ResidentCertificateType | null {\n if (/^[A-D][89]\\d{8}$/.test(id)) {\n return \"old\";\n }\n if (/^[A-Z]{2}\\d{8}$/.test(id)) {\n return \"new\";\n }\n return null;\n}\n\n/**\n * 驗證台灣居留證號(支援新舊格式)\n * @param id - 要驗證的居留證號\n * @param format - 可選:指定格式類型('old' 或 'new')\n * @returns 驗證結果\n *\n * @example\n * ```typescript\n * validateResidentCertificate('A800000000'); // 舊式格式\n * validateResidentCertificate('AA12345678'); // 新式格式\n * ```\n */\nexport function validateResidentCertificate(\n id: string,\n format?: ResidentCertificateType,\n): ValidationResult {\n if (!id || typeof id !== \"string\") {\n return {\n isValid: false,\n message: \"居留證號必須為非空字串\",\n };\n }\n\n const normalizedId = id.trim().toUpperCase();\n\n // 如果指定了格式,只驗證該格式\n if (format === \"old\") {\n const isValid = validateOldFormat(normalizedId);\n return {\n isValid,\n message: isValid ? undefined : \"無效的舊式居留證號\",\n };\n }\n\n if (format === \"new\") {\n const isValid = validateNewFormat(normalizedId);\n return {\n isValid,\n message: isValid ? undefined : \"無效的新式居留證號\",\n };\n }\n\n // 自動偵測格式\n const detectedFormat = detectFormat(normalizedId);\n\n if (!detectedFormat) {\n return {\n isValid: false,\n message: \"無效的居留證號格式\",\n };\n }\n\n const isValid =\n detectedFormat === \"old\"\n ? validateOldFormat(normalizedId)\n : validateNewFormat(normalizedId);\n\n return {\n isValid,\n message: isValid\n ? undefined\n : `無效的${detectedFormat === \"old\" ? \"舊式\" : \"新式\"}居留證號`,\n };\n}\n","import type { ValidationResult } from \"../types\";\n\n/**\n * 驗證台灣手機號碼\n * 格式:09XXXXXXXX(10位數字,以09開頭)\n *\n * @param phone - 要驗證的手機號碼\n * @returns 驗證結果\n *\n * @example\n * ```typescript\n * validateMobilePhone('0912345678');\n * validateMobilePhone('0912-345-678'); // 含分隔符號\n * ```\n */\nexport function validateMobilePhone(phone: string): ValidationResult {\n if (!phone || typeof phone !== \"string\") {\n return {\n isValid: false,\n message: \"手機號碼必須為非空字串\",\n };\n }\n\n // 移除常見的分隔符號(空格、破折號、括號)\n const normalized = phone.trim().replace(/[\\s\\-()]/g, \"\");\n\n // 檢查是否符合台灣手機號碼格式\n // 以09開頭且總共10位數字\n const pattern = /^09\\d{8}$/;\n\n if (!pattern.test(normalized)) {\n return {\n isValid: false,\n message: \"手機號碼必須以09開頭且為10位數字\",\n };\n }\n\n return {\n isValid: true,\n };\n}\n","import type { ValidationResult } from \"../types\";\n\n/**\n * 驗證台灣自然人憑證編號\n * 格式:2個大寫英文字母 + 14位數字\n * 範例:AB12345678901234\n *\n * @param certNumber - 要驗證的自然人憑證編號\n * @returns 驗證結果\n *\n * @example\n * ```typescript\n * validateCitizenCertificate('AB12345678901234');\n * ```\n */\nexport function validateCitizenCertificate(\n certNumber: string,\n): ValidationResult {\n if (!certNumber || typeof certNumber !== \"string\") {\n return {\n isValid: false,\n message: \"自然人憑證編號必須為非空字串\",\n };\n }\n\n const normalized = certNumber.trim().toUpperCase();\n\n // 檢查格式:2個字母 + 14位數字\n const pattern = /^[A-Z]{2}\\d{14}$/;\n\n if (!pattern.test(normalized)) {\n return {\n isValid: false,\n message: \"自然人憑證編號必須為2個英文字母加上14位數字\",\n };\n }\n\n return {\n isValid: true,\n };\n}\n","import type { ValidationResult } from \"../types\";\n\n/**\n * 驗證台灣電子發票手機條碼\n * 格式:/ + 7個字元(大寫英文字母、數字、+、-、.)\n * 範例:/ABCD123\n *\n * 手機條碼用於將電子發票儲存在手機載具中\n *\n * @param barcode - 要驗證的手機條碼\n * @returns 驗證結果\n *\n * @example\n * ```typescript\n * validateEInvoiceMobileBarcode('/ABCD123');\n * validateEInvoiceMobileBarcode('/1234567');\n * ```\n */\nexport function validateEInvoiceMobileBarcode(\n barcode: string,\n): ValidationResult {\n if (!barcode || typeof barcode !== \"string\") {\n return {\n isValid: false,\n message: \"手機條碼必須為非空字串\",\n };\n }\n\n const normalized = barcode.trim().toUpperCase();\n\n // 檢查格式:以 / 開頭,後接7個字元\n // 有效字元:A-Z、0-9、+、-、.\n const pattern = /^\\/[A-Z0-9+.-]{7}$/;\n\n if (!pattern.test(normalized)) {\n return {\n isValid: false,\n message: \"手機條碼必須以 / 開頭,後接7個有效字元(A-Z、0-9、+、-、.)\",\n };\n }\n\n return {\n isValid: true,\n };\n}\n","import type { ValidationResult } from \"../types\";\n\n/**\n * 驗證台灣電子發票捐贈碼\n * 格式:3-7位數字\n * 範例:123、12345、1234567\n *\n * 捐贈碼用於將電子發票捐贈給已註冊的慈善機構\n *\n * @param code - 要驗證的捐贈碼\n * @returns 驗證結果\n *\n * @example\n * ```typescript\n * validateEInvoiceDonationCode('123');\n * validateEInvoiceDonationCode('12345');\n * ```\n */\nexport function validateEInvoiceDonationCode(code: string): ValidationResult {\n if (!code || typeof code !== \"string\") {\n return {\n isValid: false,\n message: \"捐贈碼必須為非空字串\",\n };\n }\n\n const normalized = code.trim();\n\n // 檢查格式:3-7位數字\n const pattern = /^\\d{3,7}$/;\n\n if (!pattern.test(normalized)) {\n return {\n isValid: false,\n message: \"捐贈碼必須為3至7位數字\",\n };\n }\n\n return {\n isValid: true,\n };\n}\n"]}
1
+ {"version":3,"sources":["../src/validators/shared.ts","../src/validators/national-id.ts","../src/validators/business-number.ts","../src/validators/uniform-invoice.ts","../src/validators/resident-certificate.ts","../src/validators/mobile-phone.ts","../src/validators/landline-phone.ts","../src/validators/postal-code.ts","../src/validators/citizen-certificate.ts","../src/validators/nhi-card.ts","../src/validators/passport.ts","../src/validators/einvoice-mobile-barcode.ts","../src/validators/einvoice-donation-code.ts","../src/validators/license-plate.ts"],"names":["LETTER_MAPPING","REGION_MAPPING","validateFormatAndChecksum","id","letter","numbers","letterValue","d1","d2","weights","acc","digit","index","validateNationalId","_format","normalizedId","isValid","parseNationalId","firstLetter","gender","region","validateBusinessNumber","number","normalized","digits","sum","i","product","validateUniformInvoice","invoice","validateOldFormat","secondLetter","firstLetterValue","secondLetterValue","d3","validateNewFormat","detectFormat","validateResidentCertificate","format","detectedFormat","parseResidentCertificate","secondChar","identityType","validateMobilePhone","phone","AREA_CODES","validateLandlinePhone","match","entry","validatePostalCode","code","strCode","validateCitizenCertificate","certNumber","validateNHICard","cardNumber","validatePassport","passport","validateEInvoiceMobileBarcode","barcode","validateEInvoiceDonationCode","validateNewCarPlate","plate","validateOldCarPlate","validateElectricCarPlate","validateSmallMotorcyclePlate","pattern1","pattern2","validateMotorcyclePlate","detectPlateType","validateLicensePlate","options","type","detectType","getPlateTypeName","detectedType"],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * 字母對應數字表(用於身分證字號與居留證號驗證)\n */\nexport const LETTER_MAPPING: Record<string, number> = {\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/**\n * 字母對應地區名稱表\n */\nexport const REGION_MAPPING: Record<string, string> = {\n A: \"臺北市\",\n B: \"臺中市\",\n C: \"基隆市\",\n D: \"臺南市\",\n E: \"高雄市\",\n F: \"新北市\",\n G: \"宜蘭縣\",\n H: \"桃園市\",\n I: \"嘉義市\",\n J: \"新竹縣\",\n K: \"苗栗縣\",\n L: \"臺中縣\",\n M: \"南投縣\",\n N: \"彰化縣\",\n O: \"新竹市\",\n P: \"雲林縣\",\n Q: \"嘉義縣\",\n R: \"臺南縣\",\n S: \"高雄縣\",\n T: \"屏東縣\",\n U: \"花蓮縣\",\n V: \"臺東縣\",\n W: \"金門縣\",\n X: \"澎湖縣\",\n Y: \"陽明山管理局\",\n Z: \"連江縣\",\n};\n","import type { ValidationResult, NationalIdType, NationalIdInfo } from \"../types\";\nimport { LETTER_MAPPING, REGION_MAPPING } from \"./shared\";\n\n/**\n * 驗證台灣身分證字號格式與檢查碼(1個字母 + 9個數字)\n * 格式:A123456789\n * - 第一個字元:地區代碼(字母)\n * - 第二個字元:性別(1 = 男性,2 = 女性)\n * - 最後一個字元:檢查碼\n */\nfunction validateFormatAndChecksum(id: string): boolean {\n const pattern = /^[A-Z][12]\\d{8}$/;\n if (!pattern.test(id)) {\n return false;\n }\n\n const letter = id[0] as string;\n const numbers = id.slice(1);\n\n const letterValue = LETTER_MAPPING[letter] as number;\n\n const d1 = Math.floor(letterValue / 10);\n const d2 = letterValue % 10;\n\n const weights = [1, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1];\n const digits = [d1, d2, ...numbers.split(\"\").map(Number)];\n\n const sum = digits.reduce(\n (acc, digit, index) => acc + digit * weights[index]!,\n 0,\n );\n\n return sum % 10 === 0;\n}\n\n/**\n * 驗證台灣身分證字號(身分證字號皆為「1個字母 + 9個數字」格式)\n * @param id - 要驗證的身分證字號\n * @param format - 可選(為維持相容性保留):指定格式類型\n * @returns 驗證結果\n *\n * @example\n * ```typescript\n * validateNationalId('A123456789');\n * ```\n */\nexport function validateNationalId(\n id: string,\n _format?: NationalIdType,\n): ValidationResult {\n if (!id || typeof id !== \"string\") {\n return {\n isValid: false,\n message: \"身分證字號必須為非空字串\",\n };\n }\n\n const normalizedId = id.trim().toUpperCase();\n\n const isValid = validateFormatAndChecksum(normalizedId);\n\n return {\n isValid,\n message: isValid ? undefined : \"無效的身分證字號\",\n };\n}\n\n/**\n * 解析台灣身分證字號資訊(性別、發證地區)\n * @param id - 要解析的身分證字號\n * @returns 解析結果,包含驗證狀態及相關欄位\n *\n * @example\n * ```typescript\n * parseNationalId('A123456789');\n * // 輸出: { isValid: true, gender: 'male', region: '臺北市' }\n * ```\n */\nexport function parseNationalId(id: string): NationalIdInfo {\n if (!id || typeof id !== \"string\") {\n return {\n isValid: false,\n message: \"身分證字號必須為非空字串\",\n };\n }\n\n const normalizedId = id.trim().toUpperCase();\n\n const isValid = validateFormatAndChecksum(normalizedId);\n if (!isValid) {\n return {\n isValid: false,\n message: \"無效的身分證字號\",\n };\n }\n\n const firstLetter = normalizedId[0] as string;\n const genderDigit = normalizedId[1] as string;\n\n const gender = genderDigit === \"1\" ? \"male\" : \"female\";\n const region = REGION_MAPPING[firstLetter] as string;\n\n return {\n isValid: true,\n gender,\n region,\n };\n}\n","import type { ValidationResult } from \"../types\";\n\n/**\n * 驗證台灣營利事業統一編號\n * 格式:8位數字\n * 使用加權檢查碼演算法\n *\n * @param number - 要驗證的統一編號\n * @returns 驗證結果\n *\n * @example\n * ```typescript\n * validateBusinessNumber('12345678');\n * ```\n */\nexport function validateBusinessNumber(number: string): ValidationResult {\n if (!number || typeof number !== \"string\") {\n return {\n isValid: false,\n message: \"統一編號必須為非空字串\",\n };\n }\n\n const normalized = number.trim();\n\n // 檢查是否為8位數字\n const pattern = /^\\d{8}$/;\n if (!pattern.test(normalized)) {\n return {\n isValid: false,\n message: \"統一編號必須為8位數字\",\n };\n }\n\n const digits = normalized.split(\"\").map(Number);\n const weights = [1, 2, 1, 2, 1, 2, 4, 1];\n\n // 計算加權總和\n let sum = 0;\n for (let i = 0; i < 8; i++) {\n let product = digits[i]! * weights[i]!;\n\n // 如果乘積為兩位數,將十位數和個位數相加\n if (product >= 10) {\n product = Math.floor(product / 10) + (product % 10);\n }\n\n sum += product;\n }\n\n // 特殊情況:第7位數字為7時\n // 如果第7位數字為7且總和除以10的餘數為1,也視為有效\n const isValid = sum % 10 === 0 || (digits[6]! === 7 && sum % 10 === 1);\n\n return {\n isValid,\n message: isValid ? undefined : \"統一編號檢查碼錯誤\",\n };\n}\n","import type { ValidationResult } from \"../types\";\n\n/**\n * 驗證台灣統一發票號碼格式\n * 格式為 2 碼英文開頭 + 8 碼數字(可包含減號或空格,如 AB-12345678 或 AB 12345678)\n *\n * @param invoice - 要驗證的發票號碼\n * @returns 驗證結果\n *\n * @example\n * ```typescript\n * validateUniformInvoice('AB-12345678'); // { isValid: true }\n * validateUniformInvoice('AB12345678'); // { isValid: true }\n * ```\n */\nexport function validateUniformInvoice(invoice: string): ValidationResult {\n if (!invoice || typeof invoice !== \"string\") {\n return {\n isValid: false,\n message: \"發票號碼必須為非空字串\",\n };\n }\n\n // 去除空格與減號並轉大寫\n const normalized = invoice.replace(/[-\\s]/g, \"\").toUpperCase();\n\n const pattern = /^[A-Z]{2}\\d{8}$/;\n\n if (!pattern.test(normalized)) {\n return {\n isValid: false,\n message: \"發票號碼格式必須為2碼英文與8碼數字\",\n };\n }\n\n return {\n isValid: true,\n };\n}\n","import type { ValidationResult, ResidentCertificateType, ResidentCertificateInfo } from \"../types\";\nimport { LETTER_MAPPING, REGION_MAPPING } from \"./shared\";\n\n/**\n * 驗證舊式居留證號格式與檢查碼(2個字母 + 8個數字)\n * 格式:AA12345678\n * - 第一個字元:地區代碼(字母)\n * - 第二個字元:身分與性別碼(A = 男性無戶籍國民/港澳陸居民,B = 女性無戶籍國民/港澳陸居民,C = 男性外國人,D = 女性外國人)\n * - 最後一個字元:檢查碼\n */\nfunction validateOldFormat(id: string): boolean {\n const pattern = /^[A-Z][A-D]\\d{8}$/;\n if (!pattern.test(id)) {\n return false;\n }\n\n const firstLetter = id[0] as string;\n const secondLetter = id[1] as string;\n const numbers = id.slice(2);\n\n const firstLetterValue = LETTER_MAPPING[firstLetter] as number;\n const secondLetterValue = LETTER_MAPPING[secondLetter] as number;\n\n const d1 = Math.floor(firstLetterValue / 10);\n const d2 = firstLetterValue % 10;\n const d3 = secondLetterValue % 10; // 取第二個字母對應數字的個位數\n\n const weights = [1, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1];\n const digits = [d1, d2, d3, ...numbers.split(\"\").map(Number)];\n\n const sum = digits.reduce(\n (acc, digit, index) => acc + digit * weights[index]!,\n 0,\n );\n\n return sum % 10 === 0;\n}\n\n/**\n * 驗證新式居留證號格式與檢查碼(1個字母 + 9個數字,其中第二碼為8或9)\n * 格式:A800000001\n * - 第一個字元:地區代碼(字母)\n * - 第二個字元:性別(8 = 男性,9 = 女性)\n * - 最後一個字元:檢查碼\n */\nfunction validateNewFormat(id: string): boolean {\n const pattern = /^[A-Z][89]\\d{8}$/;\n if (!pattern.test(id)) {\n return false;\n }\n\n const letter = id[0] as string;\n const numbers = id.slice(1);\n\n const letterValue = LETTER_MAPPING[letter] as number;\n\n const d1 = Math.floor(letterValue / 10);\n const d2 = letterValue % 10;\n\n const weights = [1, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1];\n const digits = [d1, d2, ...numbers.split(\"\").map(Number)];\n\n const sum = digits.reduce(\n (acc, digit, index) => acc + digit * weights[index]!,\n 0,\n );\n\n return sum % 10 === 0;\n}\n\n/**\n * 偵測居留證號格式類型\n */\nfunction detectFormat(id: string): ResidentCertificateType | null {\n if (/^[A-Z][A-D]\\d{8}$/.test(id)) {\n return \"old\";\n }\n if (/^[A-Z][89]\\d{8}$/.test(id)) {\n return \"new\";\n }\n return null;\n}\n\n/**\n * 驗證台灣居留證號(支援新舊格式,舊版為2字母+8數字,新版為1字母+9數字)\n * @param id - 要驗證的居留證號\n * @param format - 可選:指定格式類型('old' 或 'new')\n * @returns 驗證結果\n *\n * @example\n * ```typescript\n * validateResidentCertificate('AD00000001', 'old'); // 舊式格式\n * validateResidentCertificate('A800000001', 'new'); // 新式格式\n * ```\n */\nexport function validateResidentCertificate(\n id: string,\n format?: ResidentCertificateType,\n): ValidationResult {\n if (!id || typeof id !== \"string\") {\n return {\n isValid: false,\n message: \"居留證號必須為非空字串\",\n };\n }\n\n const normalizedId = id.trim().toUpperCase();\n\n if (format === \"old\") {\n const isValid = validateOldFormat(normalizedId);\n return {\n isValid,\n message: isValid ? undefined : \"無效的舊式居留證號\",\n };\n }\n\n if (format === \"new\") {\n const isValid = validateNewFormat(normalizedId);\n return {\n isValid,\n message: isValid ? undefined : \"無效的新式居留證號\",\n };\n }\n\n const detectedFormat = detectFormat(normalizedId);\n\n if (!detectedFormat) {\n return {\n isValid: false,\n message: \"無效的居留證號格式\",\n };\n }\n\n const isValid =\n detectedFormat === \"old\"\n ? validateOldFormat(normalizedId)\n : validateNewFormat(normalizedId);\n\n return {\n isValid,\n message: isValid\n ? undefined\n : `無效的${detectedFormat === \"old\" ? \"舊式\" : \"新式\"}居留證號`,\n };\n}\n\n/**\n * 解析台灣居留證號資訊(格式版本、性別、發證地區、身分類型)\n * @param id - 要解析的居留證號\n * @returns 解析結果,包含驗證狀態及相關欄位\n *\n * @example\n * ```typescript\n * parseResidentCertificate('A800000001');\n * // 輸出: { isValid: true, format: 'new', gender: 'male', region: '臺北市' }\n * ```\n */\nexport function parseResidentCertificate(id: string): ResidentCertificateInfo {\n if (!id || typeof id !== \"string\") {\n return {\n isValid: false,\n message: \"居留證號必須為非空字串\",\n };\n }\n\n const normalizedId = id.trim().toUpperCase();\n\n const format = detectFormat(normalizedId);\n if (!format) {\n return {\n isValid: false,\n message: \"無效的居留證號格式\",\n };\n }\n\n const isValid =\n format === \"old\"\n ? validateOldFormat(normalizedId)\n : validateNewFormat(normalizedId);\n\n if (!isValid) {\n return {\n isValid: false,\n message: `無效的${format === \"old\" ? \"舊式\" : \"新式\"}居留證號`,\n };\n }\n\n const firstLetter = normalizedId[0] as string;\n const secondChar = normalizedId[1] as string;\n\n const region = REGION_MAPPING[firstLetter] as string;\n let gender: \"male\" | \"female\";\n let identityType: \"non-citizen\" | \"foreigner\" | undefined;\n\n if (format === \"new\") {\n gender = secondChar === \"8\" ? \"male\" : \"female\";\n identityType = \"foreigner\"; // 新式格式下通常統稱為外來人口\n } else {\n // 舊式格式: A, B, C, D\n gender = (secondChar === \"A\" || secondChar === \"C\") ? \"male\" : \"female\";\n identityType = (secondChar === \"A\" || secondChar === \"B\") ? \"non-citizen\" : \"foreigner\";\n }\n\n return {\n isValid: true,\n format,\n gender,\n region,\n identityType,\n };\n}\n","import type { ValidationResult } from \"../types\";\n\n/**\n * 驗證台灣手機號碼\n * 格式:09XXXXXXXX(10位數字,以09開頭)\n *\n * @param phone - 要驗證的手機號碼\n * @returns 驗證結果\n *\n * @example\n * ```typescript\n * validateMobilePhone('0912345678');\n * validateMobilePhone('0912-345-678'); // 含分隔符號\n * ```\n */\nexport function validateMobilePhone(phone: string): ValidationResult {\n if (!phone || typeof phone !== \"string\") {\n return {\n isValid: false,\n message: \"手機號碼必須為非空字串\",\n };\n }\n\n // 移除常見的分隔符號(空格、破折號、括號)\n const normalized = phone.trim().replace(/[\\s\\-()]/g, \"\");\n\n // 檢查是否符合台灣手機號碼格式\n // 以09開頭且總共10位數字\n const pattern = /^09\\d{8}$/;\n\n if (!pattern.test(normalized)) {\n return {\n isValid: false,\n message: \"手機號碼必須以09開頭且為10位數字\",\n };\n }\n\n return {\n isValid: true,\n };\n}\n","import type { ValidationResult } from \"../types\";\n\n// 台灣市話區碼與對應的總長度(含區碼)\nconst AREA_CODES = [\n { code: \"0826\", totalLength: 9 }, // 烏坵\n { code: \"0836\", totalLength: 9 }, // 馬祖\n { code: \"037\", totalLength: 9 }, // 苗栗\n { code: \"049\", totalLength: 9 }, // 南投\n { code: \"082\", totalLength: 9 }, // 金門\n { code: \"089\", totalLength: 9 }, // 台東\n { code: \"02\", totalLength: 10 }, // 雙北、基隆\n { code: \"03\", totalLength: 9 }, // 桃園、新竹、宜蘭、花蓮\n { code: \"04\", totalLength: 10 }, // 台中、彰化\n { code: \"05\", totalLength: 9 }, // 雲林、嘉義\n { code: \"06\", totalLength: 9 }, // 台南、澎湖\n { code: \"07\", totalLength: 9 }, // 高雄\n { code: \"08\", totalLength: 9 }, // 屏東\n];\n\n/**\n * 驗證台灣市內電話號碼格式\n * 支援帶有括號、減號或空格的格式(例如 (02) 1234-5678, 02-12345678, 03-1234567)\n *\n * @param phone - 要驗證的市話號碼\n * @returns 驗證結果\n *\n * @example\n * ```typescript\n * validateLandlinePhone('(02) 1234-5678'); // { isValid: true }\n * validateLandlinePhone('03-1234567'); // { isValid: true }\n * ```\n */\nexport function validateLandlinePhone(phone: string): ValidationResult {\n if (!phone || typeof phone !== \"string\") {\n return {\n isValid: false,\n message: \"電話號碼必須為非空字串\",\n };\n }\n\n // 移除非數字的字元\n const normalized = phone.replace(/[^\\d]/g, \"\");\n\n // 尋找匹配的區碼\n const match = AREA_CODES.find((entry) => normalized.startsWith(entry.code));\n\n if (!match) {\n return {\n isValid: false,\n message: \"無效的台灣市話區碼\",\n };\n }\n\n if (normalized.length !== match.totalLength) {\n return {\n isValid: false,\n message: `該區碼的電話號碼長度應為 ${match.totalLength} 碼`,\n };\n }\n\n return {\n isValid: true,\n };\n}\n","import type { ValidationResult } from \"../types\";\n\n/**\n * 驗證台灣郵遞區號格式\n * 支援 3 碼、5 碼 (3+2) 及新式 6 碼 (3+3) 格式(可包含減號,如 100-001 或 100001)\n * 第一碼必須為 1-9\n *\n * @param code - 要驗證的郵遞區號\n * @returns 驗證結果\n *\n * @example\n * ```typescript\n * validatePostalCode('100'); // { isValid: true }\n * validatePostalCode('100-01'); // { isValid: true }\n * validatePostalCode('100001'); // { isValid: true }\n * ```\n */\nexport function validatePostalCode(code: string | number): ValidationResult {\n if (code === null || code === undefined) {\n return {\n isValid: false,\n message: \"郵遞區號必須為非空字串或數字\",\n };\n }\n\n const strCode = String(code).trim().replace(/[-\\s]/g, \"\");\n\n // 驗證格式:3 碼、5 碼或 6 碼,且首碼為 1-9\n const pattern = /^[1-9]\\d{2}$|^[1-9]\\d{4}$|^[1-9]\\d{5}$/;\n\n if (!pattern.test(strCode)) {\n return {\n isValid: false,\n message: \"郵遞區號格式必須為首碼非0的3碼、5碼或6碼數字\",\n };\n }\n\n return {\n isValid: true,\n };\n}\n","import type { ValidationResult } from \"../types\";\n\n/**\n * 驗證台灣自然人憑證編號\n * 格式:2個大寫英文字母 + 14位數字\n * 範例:AB12345678901234\n *\n * @param certNumber - 要驗證的自然人憑證編號\n * @returns 驗證結果\n *\n * @example\n * ```typescript\n * validateCitizenCertificate('AB12345678901234');\n * ```\n */\nexport function validateCitizenCertificate(\n certNumber: string,\n): ValidationResult {\n if (!certNumber || typeof certNumber !== \"string\") {\n return {\n isValid: false,\n message: \"自然人憑證編號必須為非空字串\",\n };\n }\n\n const normalized = certNumber.trim().toUpperCase();\n\n // 檢查格式:2個字母 + 14位數字\n const pattern = /^[A-Z]{2}\\d{14}$/;\n\n if (!pattern.test(normalized)) {\n return {\n isValid: false,\n message: \"自然人憑證編號必須為2個英文字母加上14位數字\",\n };\n }\n\n return {\n isValid: true,\n };\n}\n","import type { ValidationResult } from \"../types\";\n\n/**\n * 驗證台灣國民健康保險卡(健保卡)卡號格式\n * 格式為 12 碼數字(可包含減號或空格,如 0000 1234 5678)\n *\n * @param cardNumber - 要驗證的健保卡卡號\n * @returns 驗證結果\n *\n * @example\n * ```typescript\n * validateNHICard('0000 1234 5678'); // { isValid: true }\n * validateNHICard('000012345678'); // { isValid: true }\n * ```\n */\nexport function validateNHICard(cardNumber: string): ValidationResult {\n if (!cardNumber || typeof cardNumber !== \"string\") {\n return {\n isValid: false,\n message: \"健保卡號必須為非空字串\",\n };\n }\n\n // 去除空格與減號\n const normalized = cardNumber.replace(/[-\\s]/g, \"\");\n\n const pattern = /^\\d{12}$/;\n\n if (!pattern.test(normalized)) {\n return {\n isValid: false,\n message: \"健保卡號格式必須為12碼數字\",\n };\n }\n\n return {\n isValid: true,\n };\n}\n","import type { ValidationResult } from \"../types\";\n\n/**\n * 驗證中華民國(台灣)護照號碼格式\n * 晶片護照與一般護照為 9 碼數字格式(晶片護照通常以 3 開頭)\n *\n * @param passport - 要驗證的護照號碼\n * @returns 驗證結果\n *\n * @example\n * ```typescript\n * validatePassport('312345678'); // { isValid: true }\n * ```\n */\nexport function validatePassport(passport: string): ValidationResult {\n if (!passport || typeof passport !== \"string\") {\n return {\n isValid: false,\n message: \"護照號碼必須為非空字串\",\n };\n }\n\n const normalized = passport.trim();\n\n // 驗證 9 碼數字\n const pattern = /^\\d{9}$/;\n\n if (!pattern.test(normalized)) {\n return {\n isValid: false,\n message: \"護照號碼格式必須為9位數字\",\n };\n }\n\n return {\n isValid: true,\n };\n}\n","import type { ValidationResult } from \"../types\";\n\n/**\n * 驗證台灣電子發票手機條碼\n * 格式:/ + 7個字元(大寫英文字母、數字、+、-、.)\n * 範例:/ABCD123\n *\n * 手機條碼用於將電子發票儲存在手機載具中\n *\n * @param barcode - 要驗證的手機條碼\n * @returns 驗證結果\n *\n * @example\n * ```typescript\n * validateEInvoiceMobileBarcode('/ABCD123');\n * validateEInvoiceMobileBarcode('/1234567');\n * ```\n */\nexport function validateEInvoiceMobileBarcode(\n barcode: string,\n): ValidationResult {\n if (!barcode || typeof barcode !== \"string\") {\n return {\n isValid: false,\n message: \"手機條碼必須為非空字串\",\n };\n }\n\n const normalized = barcode.trim().toUpperCase();\n\n // 檢查格式:以 / 開頭,後接7個字元\n // 有效字元:A-Z、0-9、+、-、.\n const pattern = /^\\/[A-Z0-9+.-]{7}$/;\n\n if (!pattern.test(normalized)) {\n return {\n isValid: false,\n message: \"手機條碼必須以 / 開頭,後接7個有效字元(A-Z、0-9、+、-、.)\",\n };\n }\n\n return {\n isValid: true,\n };\n}\n","import type { ValidationResult } from \"../types\";\n\n/**\n * 驗證台灣電子發票捐贈碼\n * 格式:3-7位數字\n * 範例:123、12345、1234567\n *\n * 捐贈碼用於將電子發票捐贈給已註冊的慈善機構\n *\n * @param code - 要驗證的捐贈碼\n * @returns 驗證結果\n *\n * @example\n * ```typescript\n * validateEInvoiceDonationCode('123');\n * validateEInvoiceDonationCode('12345');\n * ```\n */\nexport function validateEInvoiceDonationCode(code: string): ValidationResult {\n if (!code || typeof code !== \"string\") {\n return {\n isValid: false,\n message: \"捐贈碼必須為非空字串\",\n };\n }\n\n const normalized = code.trim();\n\n // 檢查格式:3-7位數字\n const pattern = /^\\d{3,7}$/;\n\n if (!pattern.test(normalized)) {\n return {\n isValid: false,\n message: \"捐贈碼必須為3至7位數字\",\n };\n }\n\n return {\n isValid: true,\n };\n}\n","import type { ValidationResult } from \"../types\";\n\n/**\n * 車牌類型\n */\nexport type LicensePlateType =\n | \"car\" // 汽車(新制)\n | \"car-old\" // 汽車(舊制)\n | \"electric-car\" // 電動汽車\n | \"motorcycle-small\" // 小型機車(50cc以下)\n | \"motorcycle\"; // 一般機車\n\n/**\n * 車牌驗證結果(含車牌類型資訊)\n */\nexport interface LicensePlateValidationResult extends ValidationResult {\n plateType?: LicensePlateType | undefined;\n}\n\n/**\n * 驗證新制汽車車牌(2012年12月後)\n * 格式:3個英文字母 - 4個數字\n * 不使用字母 I、O\n * 不使用數字 4\n */\nfunction validateNewCarPlate(plate: string): boolean {\n // 格式:3個英文字母-4個數字(例如:ABC-1234)\n const pattern = /^[A-HJ-NP-Z]{3}-\\d{4}$/;\n if (!pattern.test(plate)) {\n return false;\n }\n\n // 檢查數字部分不包含 4\n const numbers = plate.split(\"-\")[1] as string;\n return !numbers.includes(\"4\");\n}\n\n/**\n * 驗證舊制汽車車牌(1992-2012)\n * 格式:1個數字 + 1個英文字母 - 4個數字\n */\nfunction validateOldCarPlate(plate: string): boolean {\n // 格式:1個數字+1個英文字母-4個數字(例如:1A-2345)\n const pattern = /^\\d[A-Z]-\\d{4}$/;\n return pattern.test(plate);\n}\n\n/**\n * 驗證電動汽車車牌\n * 格式:E + 2個英文字母 - 4個數字\n * 不使用字母 I、O\n * 不使用數字 4\n */\nfunction validateElectricCarPlate(plate: string): boolean {\n // 格式:E + 2個英文字母-4個數字(例如:EAB-1234)\n const pattern = /^E[A-HJ-NP-Z]{2}-\\d{4}$/;\n if (!pattern.test(plate)) {\n return false;\n }\n\n // 檢查數字部分不包含 4\n const numbers = plate.split(\"-\")[1] as string;\n return !numbers.includes(\"4\");\n}\n\n/**\n * 驗證小型機車車牌(50cc以下)\n * 格式:3個數字-3個英文字母 或 3個英文字母-3個數字\n */\nfunction validateSmallMotorcyclePlate(plate: string): boolean {\n // 格式1:3個數字-3個英文字母(例如:123-ABC)\n // 格式2:3個英文字母-3個數字(例如:ABC-123)\n const pattern1 = /^\\d{3}-[A-Z]{3}$/;\n const pattern2 = /^[A-Z]{3}-\\d{3}$/;\n return pattern1.test(plate) || pattern2.test(plate);\n}\n\n/**\n * 驗證一般機車車牌(舊制,50-250cc)\n * 格式:2個英文字母 + 1個數字 - 3個數字\n */\nfunction validateMotorcyclePlate(plate: string): boolean {\n // 格式:2個英文字母+1個數字-3個數字(例如:AB1-234)\n const pattern = /^[A-Z]{2}\\d-\\d{3}$/;\n return pattern.test(plate);\n}\n\n/**\n * 偵測車牌類型\n */\nfunction detectPlateType(plate: string): LicensePlateType | null {\n if (validateElectricCarPlate(plate)) {\n return \"electric-car\";\n }\n if (validateNewCarPlate(plate)) {\n return \"car\";\n }\n if (validateOldCarPlate(plate)) {\n return \"car-old\";\n }\n if (validateSmallMotorcyclePlate(plate)) {\n return \"motorcycle-small\";\n }\n if (validateMotorcyclePlate(plate)) {\n return \"motorcycle\";\n }\n return null;\n}\n\n/**\n * 驗證台灣車牌號碼\n * @param plate - 要驗證的車牌號碼\n * @param options - 驗證選項\n * @param options.type - 可選:指定車牌類型\n * @param options.detectType - 是否偵測車牌類型(預設:true)\n * @returns 驗證結果\n *\n * @example\n * ```typescript\n * // 新制汽車\n * validateLicensePlate('ABC-1235');\n *\n * // 電動汽車\n * validateLicensePlate('EAB-1235');\n *\n * // 舊制汽車\n * validateLicensePlate('1A-2345');\n *\n * // 小型機車\n * validateLicensePlate('123-ABC');\n * validateLicensePlate('ABC-123');\n *\n * // 一般機車\n * validateLicensePlate('AB1-234');\n *\n * // 指定類型驗證\n * validateLicensePlate('ABC-1235', { type: 'car' });\n *\n * // 不偵測類型\n * validateLicensePlate('ABC-1235', { detectType: false });\n * ```\n */\nexport function validateLicensePlate(\n plate: string,\n options: { type?: LicensePlateType; detectType?: boolean } = {},\n): LicensePlateValidationResult {\n const { type, detectType = true } = options;\n\n if (!plate || typeof plate !== \"string\") {\n return {\n isValid: false,\n message: \"車牌號碼必須為非空字串\",\n };\n }\n\n // 移除空格並轉換為大寫\n const normalized = plate.trim().toUpperCase();\n\n // 如果指定了類型,只驗證該類型\n if (type) {\n let isValid = false;\n switch (type) {\n case \"car\":\n isValid = validateNewCarPlate(normalized);\n break;\n case \"car-old\":\n isValid = validateOldCarPlate(normalized);\n break;\n case \"electric-car\":\n isValid = validateElectricCarPlate(normalized);\n break;\n case \"motorcycle-small\":\n isValid = validateSmallMotorcyclePlate(normalized);\n break;\n case \"motorcycle\":\n isValid = validateMotorcyclePlate(normalized);\n break;\n }\n\n return {\n isValid,\n message: isValid ? undefined : `無效的${getPlateTypeName(type)}車牌號碼`,\n plateType: isValid && detectType ? type : undefined,\n };\n }\n\n // 自動偵測類型\n const detectedType = detectPlateType(normalized);\n\n if (!detectedType) {\n return {\n isValid: false,\n message: \"無效的車牌號碼格式\",\n };\n }\n\n return {\n isValid: true,\n plateType: detectType ? detectedType : undefined,\n };\n}\n\n/**\n * 取得車牌類型的中文名稱\n */\nfunction getPlateTypeName(type: LicensePlateType): string {\n const typeNames: Record<LicensePlateType, string> = {\n car: \"汽車\",\n \"car-old\": \"汽車(舊制)\",\n \"electric-car\": \"電動汽車\",\n \"motorcycle-small\": \"小型機車\",\n motorcycle: \"機車\",\n };\n return typeNames[type];\n}\n"]}
package/dist/index.d.cts CHANGED
@@ -5,19 +5,54 @@ interface ValidationResult {
5
5
  type Gender = "male" | "female";
6
6
  type ResidentCertificateType = "old" | "new";
7
7
  type NationalIdType = "old" | "new";
8
+ interface NationalIdInfo {
9
+ isValid: boolean;
10
+ gender?: Gender;
11
+ region?: string;
12
+ message?: string;
13
+ }
14
+ interface ResidentCertificateInfo {
15
+ isValid: boolean;
16
+ format?: ResidentCertificateType;
17
+ gender?: Gender;
18
+ region?: string;
19
+ identityType?: "non-citizen" | "foreigner";
20
+ message?: string;
21
+ }
8
22
 
9
- declare function validateNationalId(id: string, format?: NationalIdType): ValidationResult;
23
+ declare function validateNationalId(id: string, _format?: NationalIdType): ValidationResult;
24
+ declare function parseNationalId(id: string): NationalIdInfo;
10
25
 
11
26
  declare function validateBusinessNumber(number: string): ValidationResult;
12
27
 
28
+ declare function validateUniformInvoice(invoice: string): ValidationResult;
29
+
13
30
  declare function validateResidentCertificate(id: string, format?: ResidentCertificateType): ValidationResult;
31
+ declare function parseResidentCertificate(id: string): ResidentCertificateInfo;
14
32
 
15
33
  declare function validateMobilePhone(phone: string): ValidationResult;
16
34
 
35
+ declare function validateLandlinePhone(phone: string): ValidationResult;
36
+
37
+ declare function validatePostalCode(code: string | number): ValidationResult;
38
+
17
39
  declare function validateCitizenCertificate(certNumber: string): ValidationResult;
18
40
 
41
+ declare function validateNHICard(cardNumber: string): ValidationResult;
42
+
43
+ declare function validatePassport(passport: string): ValidationResult;
44
+
19
45
  declare function validateEInvoiceMobileBarcode(barcode: string): ValidationResult;
20
46
 
21
47
  declare function validateEInvoiceDonationCode(code: string): ValidationResult;
22
48
 
23
- export { type Gender, type NationalIdType, type ResidentCertificateType, type ValidationResult, validateBusinessNumber, validateCitizenCertificate, validateEInvoiceDonationCode, validateEInvoiceMobileBarcode, validateMobilePhone, validateNationalId, validateResidentCertificate };
49
+ type LicensePlateType = "car" | "car-old" | "electric-car" | "motorcycle-small" | "motorcycle";
50
+ interface LicensePlateValidationResult extends ValidationResult {
51
+ plateType?: LicensePlateType | undefined;
52
+ }
53
+ declare function validateLicensePlate(plate: string, options?: {
54
+ type?: LicensePlateType;
55
+ detectType?: boolean;
56
+ }): LicensePlateValidationResult;
57
+
58
+ export { type Gender, type LicensePlateType, type LicensePlateValidationResult, type NationalIdInfo, type NationalIdType, type ResidentCertificateInfo, type ResidentCertificateType, type ValidationResult, parseNationalId, parseResidentCertificate, validateBusinessNumber, validateCitizenCertificate, validateEInvoiceDonationCode, validateEInvoiceMobileBarcode, validateLandlinePhone, validateLicensePlate, validateMobilePhone, validateNHICard, validateNationalId, validatePassport, validatePostalCode, validateResidentCertificate, validateUniformInvoice };
package/dist/index.d.ts CHANGED
@@ -5,19 +5,54 @@ interface ValidationResult {
5
5
  type Gender = "male" | "female";
6
6
  type ResidentCertificateType = "old" | "new";
7
7
  type NationalIdType = "old" | "new";
8
+ interface NationalIdInfo {
9
+ isValid: boolean;
10
+ gender?: Gender;
11
+ region?: string;
12
+ message?: string;
13
+ }
14
+ interface ResidentCertificateInfo {
15
+ isValid: boolean;
16
+ format?: ResidentCertificateType;
17
+ gender?: Gender;
18
+ region?: string;
19
+ identityType?: "non-citizen" | "foreigner";
20
+ message?: string;
21
+ }
8
22
 
9
- declare function validateNationalId(id: string, format?: NationalIdType): ValidationResult;
23
+ declare function validateNationalId(id: string, _format?: NationalIdType): ValidationResult;
24
+ declare function parseNationalId(id: string): NationalIdInfo;
10
25
 
11
26
  declare function validateBusinessNumber(number: string): ValidationResult;
12
27
 
28
+ declare function validateUniformInvoice(invoice: string): ValidationResult;
29
+
13
30
  declare function validateResidentCertificate(id: string, format?: ResidentCertificateType): ValidationResult;
31
+ declare function parseResidentCertificate(id: string): ResidentCertificateInfo;
14
32
 
15
33
  declare function validateMobilePhone(phone: string): ValidationResult;
16
34
 
35
+ declare function validateLandlinePhone(phone: string): ValidationResult;
36
+
37
+ declare function validatePostalCode(code: string | number): ValidationResult;
38
+
17
39
  declare function validateCitizenCertificate(certNumber: string): ValidationResult;
18
40
 
41
+ declare function validateNHICard(cardNumber: string): ValidationResult;
42
+
43
+ declare function validatePassport(passport: string): ValidationResult;
44
+
19
45
  declare function validateEInvoiceMobileBarcode(barcode: string): ValidationResult;
20
46
 
21
47
  declare function validateEInvoiceDonationCode(code: string): ValidationResult;
22
48
 
23
- export { type Gender, type NationalIdType, type ResidentCertificateType, type ValidationResult, validateBusinessNumber, validateCitizenCertificate, validateEInvoiceDonationCode, validateEInvoiceMobileBarcode, validateMobilePhone, validateNationalId, validateResidentCertificate };
49
+ type LicensePlateType = "car" | "car-old" | "electric-car" | "motorcycle-small" | "motorcycle";
50
+ interface LicensePlateValidationResult extends ValidationResult {
51
+ plateType?: LicensePlateType | undefined;
52
+ }
53
+ declare function validateLicensePlate(plate: string, options?: {
54
+ type?: LicensePlateType;
55
+ detectType?: boolean;
56
+ }): LicensePlateValidationResult;
57
+
58
+ export { type Gender, type LicensePlateType, type LicensePlateValidationResult, type NationalIdInfo, type NationalIdType, type ResidentCertificateInfo, type ResidentCertificateType, type ValidationResult, parseNationalId, parseResidentCertificate, validateBusinessNumber, validateCitizenCertificate, validateEInvoiceDonationCode, validateEInvoiceMobileBarcode, validateLandlinePhone, validateLicensePlate, validateMobilePhone, validateNHICard, validateNationalId, validatePassport, validatePostalCode, validateResidentCertificate, validateUniformInvoice };
package/dist/index.mjs CHANGED
@@ -1,2 +1,2 @@
1
- var V={A:10,B:11,C:12,D:13,E:14,F:15,G:16,H:17,I:34,J:18,K:19,L:20,M:21,N:22,O:35,P:23,Q:24,R:25,S:26,T:27,U:28,V:29,W:32,X:30,Y:31,Z:33};function R(t){if(!/^[A-Z][12]\d{8}$/.test(t))return false;let s=t[0],i=t.slice(1),r=V[s],e=Math.floor(r/10),a=r%10,o=[1,9,8,7,6,5,4,3,2,1,1];return [e,a,...i.split("").map(Number)].reduce((d,u,f)=>d+u*o[f],0)%10===0}function v(t){if(!/^[A-Z]{2}\d{8}$/.test(t))return false;let s=t[0],i=t[1],r=t.slice(2),e=V[s],a=V[i],o=Math.floor(e/10),l=e%10,c=Math.floor(a/10),d=a%10,u=[1,9,8,7,6,5,4,3,2,1,1,1];return [o,l,c,d,...r.split("").map(Number)].reduce((m,p,g)=>m+p*u[g],0)%10===0}function I(t){return /^[A-Z][12]\d{8}$/.test(t)?"old":/^[A-Z]{2}\d{8}$/.test(t)?"new":null}function x(t,n){if(!t||typeof t!="string")return {isValid:false,message:"\u8EAB\u5206\u8B49\u5B57\u865F\u5FC5\u9808\u70BA\u975E\u7A7A\u5B57\u4E32"};let s=t.trim().toUpperCase();if(n==="old"){let e=R(s);return {isValid:e,message:e?void 0:"\u7121\u6548\u7684\u820A\u5F0F\u8EAB\u5206\u8B49\u5B57\u865F"}}if(n==="new"){let e=v(s);return {isValid:e,message:e?void 0:"\u7121\u6548\u7684\u65B0\u5F0F\u8EAB\u5206\u8B49\u5B57\u865F"}}let i=I(s);if(!i)return {isValid:false,message:"\u7121\u6548\u7684\u8EAB\u5206\u8B49\u5B57\u865F\u683C\u5F0F"};let r=i==="old"?R(s):v(s);return {isValid:r,message:r?void 0:`\u7121\u6548\u7684${i==="old"?"\u820A\u5F0F":"\u65B0\u5F0F"}\u8EAB\u5206\u8B49\u5B57\u865F`}}function A(t){if(!t||typeof t!="string")return {isValid:false,message:"\u7D71\u4E00\u7DE8\u865F\u5FC5\u9808\u70BA\u975E\u7A7A\u5B57\u4E32"};let n=t.trim();if(!/^\d{8}$/.test(n))return {isValid:false,message:"\u7D71\u4E00\u7DE8\u865F\u5FC5\u9808\u70BA8\u4F4D\u6578\u5B57"};let i=n.split("").map(Number),r=[1,2,1,2,1,2,4,1],e=0;for(let o=0;o<8;o++){let l=i[o]*r[o];l>=10&&(l=Math.floor(l/10)+l%10),e+=l;}let a=e%10===0||i[6]===7&&e%10===1;return {isValid:a,message:a?void 0:"\u7D71\u4E00\u7DE8\u865F\u6AA2\u67E5\u78BC\u932F\u8AA4"}}var y={A:10,B:11,C:12,D:13,E:14,F:15,G:16,H:17,I:34,J:18,K:19,L:20,M:21,N:22,O:35,P:23,Q:24,R:25,S:26,T:27,U:28,V:29,W:32,X:30,Y:31,Z:33};function b(t){if(!/^[A-D][89]\d{8}$/.test(t))return false;let s=t[0],i=t.slice(1),r=y[s],e=Math.floor(r/10),a=r%10,o=[1,9,8,7,6,5,4,3,2,1,1];return [e,a,...i.split("").map(Number)].reduce((d,u,f)=>d+u*o[f],0)%10===0}function C(t){if(!/^[A-Z]{2}\d{8}$/.test(t))return false;let s=t[0],i=t[1],r=t.slice(2),e=y[s],a=y[i],o=Math.floor(e/10),l=e%10,c=Math.floor(a/10),d=a%10,u=[1,9,8,7,6,5,4,3,2,1,1,1];return [o,l,c,d,...r.split("").map(Number)].reduce((m,p,g)=>m+p*u[g],0)%10===0}function M(t){return /^[A-D][89]\d{8}$/.test(t)?"old":/^[A-Z]{2}\d{8}$/.test(t)?"new":null}function $(t,n){if(!t||typeof t!="string")return {isValid:false,message:"\u5C45\u7559\u8B49\u865F\u5FC5\u9808\u70BA\u975E\u7A7A\u5B57\u4E32"};let s=t.trim().toUpperCase();if(n==="old"){let e=b(s);return {isValid:e,message:e?void 0:"\u7121\u6548\u7684\u820A\u5F0F\u5C45\u7559\u8B49\u865F"}}if(n==="new"){let e=C(s);return {isValid:e,message:e?void 0:"\u7121\u6548\u7684\u65B0\u5F0F\u5C45\u7559\u8B49\u865F"}}let i=M(s);if(!i)return {isValid:false,message:"\u7121\u6548\u7684\u5C45\u7559\u8B49\u865F\u683C\u5F0F"};let r=i==="old"?b(s):C(s);return {isValid:r,message:r?void 0:`\u7121\u6548\u7684${i==="old"?"\u820A\u5F0F":"\u65B0\u5F0F"}\u5C45\u7559\u8B49\u865F`}}function T(t){if(!t||typeof t!="string")return {isValid:false,message:"\u624B\u6A5F\u865F\u78BC\u5FC5\u9808\u70BA\u975E\u7A7A\u5B57\u4E32"};let n=t.trim().replace(/[\s\-()]/g,"");return /^09\d{8}$/.test(n)?{isValid:true}:{isValid:false,message:"\u624B\u6A5F\u865F\u78BC\u5FC5\u9808\u4EE509\u958B\u982D\u4E14\u70BA10\u4F4D\u6578\u5B57"}}function h(t){if(!t||typeof t!="string")return {isValid:false,message:"\u81EA\u7136\u4EBA\u6191\u8B49\u7DE8\u865F\u5FC5\u9808\u70BA\u975E\u7A7A\u5B57\u4E32"};let n=t.trim().toUpperCase();return /^[A-Z]{2}\d{14}$/.test(n)?{isValid:true}:{isValid:false,message:"\u81EA\u7136\u4EBA\u6191\u8B49\u7DE8\u865F\u5FC5\u9808\u70BA2\u500B\u82F1\u6587\u5B57\u6BCD\u52A0\u4E0A14\u4F4D\u6578\u5B57"}}function L(t){if(!t||typeof t!="string")return {isValid:false,message:"\u624B\u6A5F\u689D\u78BC\u5FC5\u9808\u70BA\u975E\u7A7A\u5B57\u4E32"};let n=t.trim().toUpperCase();return /^\/[A-Z0-9+.-]{7}$/.test(n)?{isValid:true}:{isValid:false,message:"\u624B\u6A5F\u689D\u78BC\u5FC5\u9808\u4EE5 / \u958B\u982D\uFF0C\u5F8C\u63A57\u500B\u6709\u6548\u5B57\u5143\uFF08A-Z\u30010-9\u3001+\u3001-\u3001.\uFF09"}}function w(t){if(!t||typeof t!="string")return {isValid:false,message:"\u6350\u8D08\u78BC\u5FC5\u9808\u70BA\u975E\u7A7A\u5B57\u4E32"};let n=t.trim();return /^\d{3,7}$/.test(n)?{isValid:true}:{isValid:false,message:"\u6350\u8D08\u78BC\u5FC5\u9808\u70BA3\u81F37\u4F4D\u6578\u5B57"}}export{A as validateBusinessNumber,h as validateCitizenCertificate,w as validateEInvoiceDonationCode,L as validateEInvoiceMobileBarcode,T as validateMobilePhone,x as validateNationalId,$ as validateResidentCertificate};//# sourceMappingURL=index.mjs.map
1
+ var d={A:10,B:11,C:12,D:13,E:14,F:15,G:16,H:17,I:34,J:18,K:19,L:20,M:21,N:22,O:35,P:23,Q:24,R:25,S:26,T:27,U:28,V:29,W:32,X:30,Y:31,Z:33},p={A:"\u81FA\u5317\u5E02",B:"\u81FA\u4E2D\u5E02",C:"\u57FA\u9686\u5E02",D:"\u81FA\u5357\u5E02",E:"\u9AD8\u96C4\u5E02",F:"\u65B0\u5317\u5E02",G:"\u5B9C\u862D\u7E23",H:"\u6843\u5712\u5E02",I:"\u5609\u7FA9\u5E02",J:"\u65B0\u7AF9\u7E23",K:"\u82D7\u6817\u7E23",L:"\u81FA\u4E2D\u7E23",M:"\u5357\u6295\u7E23",N:"\u5F70\u5316\u7E23",O:"\u65B0\u7AF9\u5E02",P:"\u96F2\u6797\u7E23",Q:"\u5609\u7FA9\u7E23",R:"\u81FA\u5357\u7E23",S:"\u9AD8\u96C4\u7E23",T:"\u5C4F\u6771\u7E23",U:"\u82B1\u84EE\u7E23",V:"\u81FA\u6771\u7E23",W:"\u91D1\u9580\u7E23",X:"\u6F8E\u6E56\u7E23",Y:"\u967D\u660E\u5C71\u7BA1\u7406\u5C40",Z:"\u9023\u6C5F\u7E23"};function y(t){if(!/^[A-Z][12]\d{8}$/.test(t))return false;let i=t[0],s=t.slice(1),r=d[i],n=Math.floor(r/10),a=r%10,o=[1,9,8,7,6,5,4,3,2,1,1];return [n,a,...s.split("").map(Number)].reduce((c,f,u)=>c+f*o[u],0)%10===0}function A(t,e){if(!t||typeof t!="string")return {isValid:false,message:"\u8EAB\u5206\u8B49\u5B57\u865F\u5FC5\u9808\u70BA\u975E\u7A7A\u5B57\u4E32"};let i=t.trim().toUpperCase(),s=y(i);return {isValid:s,message:s?void 0:"\u7121\u6548\u7684\u8EAB\u5206\u8B49\u5B57\u865F"}}function b(t){if(!t||typeof t!="string")return {isValid:false,message:"\u8EAB\u5206\u8B49\u5B57\u865F\u5FC5\u9808\u70BA\u975E\u7A7A\u5B57\u4E32"};let e=t.trim().toUpperCase();if(!y(e))return {isValid:false,message:"\u7121\u6548\u7684\u8EAB\u5206\u8B49\u5B57\u865F"};let s=e[0],n=e[1]==="1"?"male":"female",a=p[s];return {isValid:true,gender:n,region:a}}function h(t){if(!t||typeof t!="string")return {isValid:false,message:"\u7D71\u4E00\u7DE8\u865F\u5FC5\u9808\u70BA\u975E\u7A7A\u5B57\u4E32"};let e=t.trim();if(!/^\d{8}$/.test(e))return {isValid:false,message:"\u7D71\u4E00\u7DE8\u865F\u5FC5\u9808\u70BA8\u4F4D\u6578\u5B57"};let s=e.split("").map(Number),r=[1,2,1,2,1,2,4,1],n=0;for(let o=0;o<8;o++){let l=s[o]*r[o];l>=10&&(l=Math.floor(l/10)+l%10),n+=l;}let a=n%10===0||s[6]===7&&n%10===1;return {isValid:a,message:a?void 0:"\u7D71\u4E00\u7DE8\u865F\u6AA2\u67E5\u78BC\u932F\u8AA4"}}function $(t){if(!t||typeof t!="string")return {isValid:false,message:"\u767C\u7968\u865F\u78BC\u5FC5\u9808\u70BA\u975E\u7A7A\u5B57\u4E32"};let e=t.replace(/[-\s]/g,"").toUpperCase();return /^[A-Z]{2}\d{8}$/.test(e)?{isValid:true}:{isValid:false,message:"\u767C\u7968\u865F\u78BC\u683C\u5F0F\u5FC5\u9808\u70BA2\u78BC\u82F1\u6587\u82078\u78BC\u6578\u5B57"}}function g(t){if(!/^[A-Z][A-D]\d{8}$/.test(t))return false;let i=t[0],s=t[1],r=t.slice(2),n=d[i],a=d[s],o=Math.floor(n/10),l=n%10,m=a%10,c=[1,9,8,7,6,5,4,3,2,1,1];return [o,l,m,...r.split("").map(Number)].reduce((x,N,T)=>x+N*c[T],0)%10===0}function V(t){if(!/^[A-Z][89]\d{8}$/.test(t))return false;let i=t[0],s=t.slice(1),r=d[i],n=Math.floor(r/10),a=r%10,o=[1,9,8,7,6,5,4,3,2,1,1];return [n,a,...s.split("").map(Number)].reduce((c,f,u)=>c+f*o[u],0)%10===0}function R(t){return /^[A-Z][A-D]\d{8}$/.test(t)?"old":/^[A-Z][89]\d{8}$/.test(t)?"new":null}function E(t,e){if(!t||typeof t!="string")return {isValid:false,message:"\u5C45\u7559\u8B49\u865F\u5FC5\u9808\u70BA\u975E\u7A7A\u5B57\u4E32"};let i=t.trim().toUpperCase();if(e==="old"){let n=g(i);return {isValid:n,message:n?void 0:"\u7121\u6548\u7684\u820A\u5F0F\u5C45\u7559\u8B49\u865F"}}if(e==="new"){let n=V(i);return {isValid:n,message:n?void 0:"\u7121\u6548\u7684\u65B0\u5F0F\u5C45\u7559\u8B49\u865F"}}let s=R(i);if(!s)return {isValid:false,message:"\u7121\u6548\u7684\u5C45\u7559\u8B49\u865F\u683C\u5F0F"};let r=s==="old"?g(i):V(i);return {isValid:r,message:r?void 0:`\u7121\u6548\u7684${s==="old"?"\u820A\u5F0F":"\u65B0\u5F0F"}\u5C45\u7559\u8B49\u865F`}}function z(t){if(!t||typeof t!="string")return {isValid:false,message:"\u5C45\u7559\u8B49\u865F\u5FC5\u9808\u70BA\u975E\u7A7A\u5B57\u4E32"};let e=t.trim().toUpperCase(),i=R(e);if(!i)return {isValid:false,message:"\u7121\u6548\u7684\u5C45\u7559\u8B49\u865F\u683C\u5F0F"};if(!(i==="old"?g(e):V(e)))return {isValid:false,message:`\u7121\u6548\u7684${i==="old"?"\u820A\u5F0F":"\u65B0\u5F0F"}\u5C45\u7559\u8B49\u865F`};let r=e[0],n=e[1],a=p[r],o,l;return i==="new"?(o=n==="8"?"male":"female",l="foreigner"):(o=n==="A"||n==="C"?"male":"female",l=n==="A"||n==="B"?"non-citizen":"foreigner"),{isValid:true,format:i,gender:o,region:a,identityType:l}}function M(t){if(!t||typeof t!="string")return {isValid:false,message:"\u624B\u6A5F\u865F\u78BC\u5FC5\u9808\u70BA\u975E\u7A7A\u5B57\u4E32"};let e=t.trim().replace(/[\s\-()]/g,"");return /^09\d{8}$/.test(e)?{isValid:true}:{isValid:false,message:"\u624B\u6A5F\u865F\u78BC\u5FC5\u9808\u4EE509\u958B\u982D\u4E14\u70BA10\u4F4D\u6578\u5B57"}}var Z=[{code:"0826",totalLength:9},{code:"0836",totalLength:9},{code:"037",totalLength:9},{code:"049",totalLength:9},{code:"082",totalLength:9},{code:"089",totalLength:9},{code:"02",totalLength:10},{code:"03",totalLength:9},{code:"04",totalLength:10},{code:"05",totalLength:9},{code:"06",totalLength:9},{code:"07",totalLength:9},{code:"08",totalLength:9}];function G(t){if(!t||typeof t!="string")return {isValid:false,message:"\u96FB\u8A71\u865F\u78BC\u5FC5\u9808\u70BA\u975E\u7A7A\u5B57\u4E32"};let e=t.replace(/[^\d]/g,""),i=Z.find(s=>e.startsWith(s.code));return i?e.length!==i.totalLength?{isValid:false,message:`\u8A72\u5340\u78BC\u7684\u96FB\u8A71\u865F\u78BC\u9577\u5EA6\u61C9\u70BA ${i.totalLength} \u78BC`}:{isValid:true}:{isValid:false,message:"\u7121\u6548\u7684\u53F0\u7063\u5E02\u8A71\u5340\u78BC"}}function U(t){if(t==null)return {isValid:false,message:"\u90F5\u905E\u5340\u865F\u5FC5\u9808\u70BA\u975E\u7A7A\u5B57\u4E32\u6216\u6578\u5B57"};let e=String(t).trim().replace(/[-\s]/g,"");return /^[1-9]\d{2}$|^[1-9]\d{4}$|^[1-9]\d{5}$/.test(e)?{isValid:true}:{isValid:false,message:"\u90F5\u905E\u5340\u865F\u683C\u5F0F\u5FC5\u9808\u70BA\u9996\u78BC\u975E0\u76843\u78BC\u30015\u78BC\u62166\u78BC\u6578\u5B57"}}function w(t){if(!t||typeof t!="string")return {isValid:false,message:"\u81EA\u7136\u4EBA\u6191\u8B49\u7DE8\u865F\u5FC5\u9808\u70BA\u975E\u7A7A\u5B57\u4E32"};let e=t.trim().toUpperCase();return /^[A-Z]{2}\d{14}$/.test(e)?{isValid:true}:{isValid:false,message:"\u81EA\u7136\u4EBA\u6191\u8B49\u7DE8\u865F\u5FC5\u9808\u70BA2\u500B\u82F1\u6587\u5B57\u6BCD\u52A0\u4E0A14\u4F4D\u6578\u5B57"}}function D(t){if(!t||typeof t!="string")return {isValid:false,message:"\u5065\u4FDD\u5361\u865F\u5FC5\u9808\u70BA\u975E\u7A7A\u5B57\u4E32"};let e=t.replace(/[-\s]/g,"");return /^\d{12}$/.test(e)?{isValid:true}:{isValid:false,message:"\u5065\u4FDD\u5361\u865F\u683C\u5F0F\u5FC5\u9808\u70BA12\u78BC\u6578\u5B57"}}function O(t){if(!t||typeof t!="string")return {isValid:false,message:"\u8B77\u7167\u865F\u78BC\u5FC5\u9808\u70BA\u975E\u7A7A\u5B57\u4E32"};let e=t.trim();return /^\d{9}$/.test(e)?{isValid:true}:{isValid:false,message:"\u8B77\u7167\u865F\u78BC\u683C\u5F0F\u5FC5\u9808\u70BA9\u4F4D\u6578\u5B57"}}function _(t){if(!t||typeof t!="string")return {isValid:false,message:"\u624B\u6A5F\u689D\u78BC\u5FC5\u9808\u70BA\u975E\u7A7A\u5B57\u4E32"};let e=t.trim().toUpperCase();return /^\/[A-Z0-9+.-]{7}$/.test(e)?{isValid:true}:{isValid:false,message:"\u624B\u6A5F\u689D\u78BC\u5FC5\u9808\u4EE5 / \u958B\u982D\uFF0C\u5F8C\u63A57\u500B\u6709\u6548\u5B57\u5143\uFF08A-Z\u30010-9\u3001+\u3001-\u3001.\uFF09"}}function B(t){if(!t||typeof t!="string")return {isValid:false,message:"\u6350\u8D08\u78BC\u5FC5\u9808\u70BA\u975E\u7A7A\u5B57\u4E32"};let e=t.trim();return /^\d{3,7}$/.test(e)?{isValid:true}:{isValid:false,message:"\u6350\u8D08\u78BC\u5FC5\u9808\u70BA3\u81F37\u4F4D\u6578\u5B57"}}function P(t){return /^[A-HJ-NP-Z]{3}-\d{4}$/.test(t)?!t.split("-")[1].includes("4"):false}function L(t){return /^\d[A-Z]-\d{4}$/.test(t)}function C(t){return /^E[A-HJ-NP-Z]{2}-\d{4}$/.test(t)?!t.split("-")[1].includes("4"):false}function I(t){let e=/^\d{3}-[A-Z]{3}$/,i=/^[A-Z]{3}-\d{3}$/;return e.test(t)||i.test(t)}function v(t){return /^[A-Z]{2}\d-\d{3}$/.test(t)}function F(t){return C(t)?"electric-car":P(t)?"car":L(t)?"car-old":I(t)?"motorcycle-small":v(t)?"motorcycle":null}function k(t,e={}){let{type:i,detectType:s=true}=e;if(!t||typeof t!="string")return {isValid:false,message:"\u8ECA\u724C\u865F\u78BC\u5FC5\u9808\u70BA\u975E\u7A7A\u5B57\u4E32"};let r=t.trim().toUpperCase();if(i){let a=false;switch(i){case "car":a=P(r);break;case "car-old":a=L(r);break;case "electric-car":a=C(r);break;case "motorcycle-small":a=I(r);break;case "motorcycle":a=v(r);break}return {isValid:a,message:a?void 0:`\u7121\u6548\u7684${H(i)}\u8ECA\u724C\u865F\u78BC`,plateType:a&&s?i:void 0}}let n=F(r);return n?{isValid:true,plateType:s?n:void 0}:{isValid:false,message:"\u7121\u6548\u7684\u8ECA\u724C\u865F\u78BC\u683C\u5F0F"}}function H(t){return {car:"\u6C7D\u8ECA","car-old":"\u6C7D\u8ECA\uFF08\u820A\u5236\uFF09","electric-car":"\u96FB\u52D5\u6C7D\u8ECA","motorcycle-small":"\u5C0F\u578B\u6A5F\u8ECA",motorcycle:"\u6A5F\u8ECA"}[t]}export{b as parseNationalId,z as parseResidentCertificate,h as validateBusinessNumber,w as validateCitizenCertificate,B as validateEInvoiceDonationCode,_ as validateEInvoiceMobileBarcode,G as validateLandlinePhone,k as validateLicensePlate,M as validateMobilePhone,D as validateNHICard,A as validateNationalId,O as validatePassport,U as validatePostalCode,E as validateResidentCertificate,$ as validateUniformInvoice};//# sourceMappingURL=index.mjs.map
2
2
  //# sourceMappingURL=index.mjs.map