@yellowsakura/js-pii-mask 0.8.93 → 0.9.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.md CHANGED
@@ -1,4 +1,4 @@
1
- # js-pii-mask
1
+ # JS PII Mask
2
2
 
3
3
  [![License: MIT](https://img.shields.io/badge/License-MIT-blue)](https://opensource.org/licenses/MIT)
4
4
  [![TypeScript](https://shields.io/badge/TypeScript-3178C6?logo=TypeScript&logoColor=FFF&style=flat-square)](https://www.typescriptlang.org)
@@ -8,9 +8,9 @@
8
8
 
9
9
  Simple lightweight PII (Personally Identifiable Information) masking library for **TypeScript / JavaScript**.
10
10
 
11
- It provides **regex-based detection and masking** of common PII patterns, inspired by [OpenAI's guardrails-js](https://github.com/openai/openai-guardrails-js), with a strong focus on **simplicity, predictability, and extensibility**.
11
+ It provides **regex-based detection and masking** of common PII patterns, inspired by [OpenAI's guardrails-js](https://github.com/openai/openai-guardrails-js), with **basic NLP capabilities** to enhance its detection power, and a strong focus on simplicity, predictability, and extensibility.
12
12
 
13
- > ⚠️ Heuristic-based detection: useful in practice, **not a compliance guarantee**.
13
+ > Heuristic-based detection: useful in practice, **not a compliance guarantee**.
14
14
 
15
15
  ## Contents
16
16
 
@@ -19,14 +19,14 @@ It provides **regex-based detection and masking** of common PII patterns, inspir
19
19
  3. [Supported PII entities](#supported-pii-entities)
20
20
  4. [API reference](#api-reference)
21
21
  5. [How it works and recommended use cases](#how-it-works-and-recommended-use-cases)
22
- 6. [Licences](#licences)
22
+ 6. [License](#license)
23
23
 
24
24
  ## Features
25
25
 
26
- - 🔎 Detects **35+ common PII types** (global + regional)
26
+ - 🔎 Detects **40+ common PII types** (global + regional)
27
27
  - 🧩 **Custom rules** for managing specific domains
28
- - ⚡ Fast, dependency-free, sequential processing
29
- - **Cannot**: Understand semantic context or perform deep NLP analysis
28
+ - ⚡ Fast, sequential processing
29
+ - 🧠 **Optional lightweight NLP** for dynamic named entities (names, places, orgs)
30
30
  - 🔍 **Trade-offs**: Balanced for minimal false positives, but may miss some edge cases
31
31
 
32
32
  This library is **pattern-based**.
@@ -37,7 +37,7 @@ This library is **pattern-based**.
37
37
  **Does NOT**:
38
38
  - Understand semantic context
39
39
  - Detect unstructured personal data
40
- - Perform NER or NLP
40
+ - Perform deep NER or NLP
41
41
  - Guarantee 100% accuracy
42
42
 
43
43
  **Expect**:
@@ -83,16 +83,16 @@ mask('Email: admin@example.com, SSN: 123-45-6789')
83
83
  import { mask, FixedPIIEntity } from '@yellowsakura/js-pii-mask'
84
84
 
85
85
  // Mask only specific entity types
86
- mask("Email: test@example.com, SSN: 123-45-6789", {
86
+ mask('Email: test@example.com, SSN: 123-45-6789', {
87
87
  fixedPiiEntities: [FixedPIIEntity.EMAIL_ADDRESS]
88
88
  })
89
- // Output: "Email: <EMAIL_ADDRESS>, SSN: 123-45-6789"
89
+ // "Email: <EMAIL_ADDRESS>, SSN: 123-45-6789"
90
90
 
91
91
  // Mask only financial information
92
- mask("Card: 1234-5678-9012-3456, Email: test@example.com", {
92
+ mask('Card: 1234-5678-9012-3456, Email: test@example.com', {
93
93
  fixedPiiEntities: [FixedPIIEntity.CREDIT_CARD, FixedPIIEntity.US_BANK_NUMBER]
94
94
  })
95
- // Output: "Card: <CREDIT_CARD>, Email: test@example.com"
95
+ // "Card: <CREDIT_CARD>, Email: test@example.com"
96
96
  ```
97
97
 
98
98
  ### Custom rules
@@ -126,12 +126,39 @@ mask('Employee EMP-12345 (email: john@company.com) submitted ticket', {
126
126
  ],
127
127
  fixedPiiEntities: [FixedPIIEntity.EMAIL_ADDRESS]
128
128
  })
129
- // Output: "Employee <EMPLOYEE_ID> (email: <EMAIL_ADDRESS>) submitted ticket"
129
+ // "Employee <EMPLOYEE_ID> (email: <EMAIL_ADDRESS>) submitted ticket"
130
130
  ```
131
131
 
132
+ ### Using NLP (Lightweight)
133
+
134
+ You can enable **N**atural **L**anguage **P**rocessing to detect dynamic entities like names, places, and organizations.
135
+ This uses the [compromise](https://www.npmjs.com/package/compromise) library.
136
+
137
+ ```ts
138
+ import { mask, NlpEntity } from '@yellowsakura/js-pii-mask'
139
+
140
+ // Enable default NLP entities (People, Places, Orgs, etc.)
141
+ mask('John Smith visited Paris', { nlp: true })
142
+ // → "<PEOPLE> visited <PLACES>"
143
+
144
+ // Selective NLP entities
145
+ mask('Google bought Fitbit for $2.1 billion', {
146
+ nlpRules: [NlpEntity.ORGS, NlpEntity.MONEY]
147
+ })
148
+ // → "<ORGS> bought <ORGS> for <MONEY>"
149
+ ```
150
+
151
+ > **⚠️ NLP Limitations & Best Practices**
152
+ >
153
+ > The NLP feature is powered by `compromise`, a lightweight library designed to be fast rather than perfect.
154
+ >
155
+ > - **Language Support**: Optimized primarily for **English**. Accuracy in other languages is limited.
156
+ > - **Accuracy**: Expect higher false positives/negatives than deep-learning based NER models.
157
+ > - **Performance**: Little slower than pure regex regex-based masking.
158
+
132
159
  ## Supported PII entities
133
160
 
134
- The library includes **35+ predefined patterns**, including:
161
+ The library includes **40+ predefined patterns**, including:
135
162
 
136
163
  ### Global
137
164
  - EMAIL_ADDRESS
@@ -142,6 +169,13 @@ The library includes **35+ predefined patterns**, including:
142
169
  - URL
143
170
  - DATE_TIME
144
171
 
172
+ ### NLP Entities (Dynamic)
173
+ - PEOPLE (Names)
174
+ - PLACES (Locations, Cities, Countries)
175
+ - ORGS (Organizations, Companies)
176
+ - MONEY (Currency amounts)
177
+ - ACRONYMS
178
+
145
179
  ### Country-specific (examples)
146
180
  - US: SSN, Passport, Bank Number, ITIN
147
181
  - UK: NHS, NINO
@@ -150,7 +184,7 @@ The library includes **35+ predefined patterns**, including:
150
184
 
151
185
  Some entities require **context keywords** (e.g. `CVV`, `BIC_SWIFT`) to reduce false positives.
152
186
 
153
- For overlapping patterns, explicitly specify `fixedPiiEntities`, see [`src/pii-fixed-rules.ts`](./src/pii-fixed-rules.ts) for an exhaustive list.
187
+ See [`src/pii-nlp.ts`](./src/pii-nlp.ts) and [`src/pii-fixed-rules.ts`](./src/pii-fixed-rules.ts) for an exhaustive list.
154
188
 
155
189
  ## API reference
156
190
 
@@ -169,12 +203,24 @@ type MaskOptions = {
169
203
  // Array of custom masking rules (always applied FIRST)
170
204
  customRules?: CustomRule[]
171
205
 
206
+ // Enable NLP processing (default: false)
207
+ nlp?: boolean
208
+
209
+ // Specific NLP entities to detect (default: all if nlp=true)
210
+ nlpRules?: NlpEntity[]
211
+
172
212
  // Array of specific fixed PII entities to detect (always applied AFTER custom rules)
173
213
  // If empty or undefined, ALL fixed entities are checked
174
214
  fixedPiiEntities?: FixedPIIEntity[]
175
215
  }
176
216
  ```
177
217
 
218
+ **Order of execution:**
219
+ 1. **NLP Rules** (if enabled)
220
+ 2. **Custom Rules** (if defined)
221
+ 3. **Fixed PII Rules**
222
+ ```
223
+
178
224
  **Returns:**
179
225
  - `string` - The masked text with PII replaced by `<REPLACED>` placeholders
180
226
 
@@ -198,12 +244,6 @@ interface CustomRule {
198
244
 
199
245
  **Examples:**
200
246
  ```ts
201
- // Good: Specific pattern with word boundaries
202
- {
203
- pattern: /\bEMP-\d{5}\b/g,
204
- replacement: 'EMPLOYEE_ID'
205
- }
206
-
207
247
  // Good: Case-insensitive matching
208
248
  {
209
249
  pattern: /ticket-[a-z0-9]{8}/gi,
@@ -216,10 +256,27 @@ interface CustomRule {
216
256
  replacement: 'NUMBER'
217
257
  }
218
258
  ```
259
+ ### `NlpEntity` Enum
260
+
261
+ Enumeration of all predefined NLP entity types, import to specify which entities to detect:
262
+
263
+ ```ts
264
+ import { NlpEntity } from '@yellowsakura/js-pii-mask'
265
+
266
+ mask(text, {
267
+ nlpRules: [
268
+ NlpEntity.ACRONYMS,
269
+ NlpEntity.MONEY,
270
+ NlpEntity.ORGS,
271
+ NlpEntity.PEOPLE,
272
+ NlpEntity.PLACES
273
+ ]
274
+ })
275
+ ```
219
276
 
220
277
  ### `FixedPIIEntity` Enum
221
278
 
222
- Enumeration of all predefined PII entity types. Import to specify which entities to detect:
279
+ Enumeration of all predefined PII entity types, import to specify which entities to detect:
223
280
 
224
281
  ```ts
225
282
  import { FixedPIIEntity } from '@yellowsakura/js-pii-mask'
@@ -228,7 +285,8 @@ mask(text, {
228
285
  fixedPiiEntities: [
229
286
  FixedPIIEntity.EMAIL_ADDRESS,
230
287
  FixedPIIEntity.PHONE_NUMBER,
231
- FixedPIIEntity.US_SSN
288
+ FixedPIIEntity.US_SSN,
289
+ ...
232
290
  ]
233
291
  })
234
292
  ```
@@ -236,28 +294,27 @@ mask(text, {
236
294
  ## How it works and recommended use cases:
237
295
 
238
296
  1. Unicode normalization (NFKC, zero-width removal)
239
- 2. Apply custom rules (in order)
240
- 3. Apply fixed PII rules (all or selected)
241
- 4. Replace matches inline
297
+ 2. Apply NLP Rules
298
+ 3. Apply custom rules (in order)
299
+ 4. Apply fixed PII rules (all or selected)
242
300
 
243
301
  Deterministic, sequential, and predictable.
244
302
 
245
- ## Use cases
303
+ ### Use cases
246
304
 
247
- ✅ Test / staging data anonymization
248
- ✅ API response redaction
249
- ✅ Preprocessing before third-party services (e.g. LLM)
305
+ ✅ Test / staging data anonymization
306
+ ✅ API response redaction
307
+ ✅ Preprocessing before third-party services (e.g. LLM)
250
308
  ✅ Masking internal identifiers
251
309
 
252
310
  ⚠️ Use with caution for:
253
- - Legal, medical, or financial documents
311
+ - Legal, medical, or financial documents
254
312
  - Automated compliance enforcement
255
313
 
256
314
  ❌ Not suitable as a standalone compliance solution.
257
315
 
258
- # License
316
+ ## License
259
317
 
260
318
  The code is licensed under the [MIT](https://opensource.org/licenses/MIT) by [Yellow Sakura](https://www.yellowsakura.com), [support@yellowsakura.com](mailto:support@yellowsakura.com), see the LICENSE file.
261
- For more details, please refer to the [project page](https://www.yellowsakura.com/en/projects/js-pii-mask).
262
319
 
263
320
  This library is adapted from [OpenAI's guardrails-js](https://github.com/openai/openai-guardrails-js) PII detection patterns.
package/dist/index.cjs ADDED
@@ -0,0 +1 @@
1
+ var e=Object.create,t=Object.defineProperty,n=Object.getOwnPropertyDescriptor,r=Object.getOwnPropertyNames,i=Object.getPrototypeOf,a=Object.prototype.hasOwnProperty,o=(e,i,o,s)=>{if(i&&typeof i==`object`||typeof i==`function`)for(var c=r(i),l=0,u=c.length,d;l<u;l++)d=c[l],!a.call(e,d)&&d!==o&&t(e,d,{get:(e=>i[e]).bind(null,d),enumerable:!(s=n(i,d))||s.enumerable});return e},s=(n,r,a)=>(a=n==null?{}:e(i(n)),o(r||!n||!n.__esModule?t(a,`default`,{value:n,enumerable:!0}):a,n));const c=s(require(`compromise`));let l=function(e){return e.ACRONYMS=`acronyms`,e.MONEY=`money`,e.ORGS=`organizations`,e.PEOPLE=`people`,e.PLACES=`places`,e}({});function u(e,t=Object.values(l)){if(!e||t.length===0)return e;let n=(0,c.default)(e);return t.forEach(t=>{let r=n[t]().out(`array`);r.forEach(n=>{e=e.replaceAll(n,`<${t.toUpperCase()}>`)})}),e}function d(e,t){if(!e||!t||t.length===0)return e;for(let n of t){if(!n.pattern||n.replacement===void 0)continue;e=e.replace(n.pattern,`<${n.replacement}>`)}return e}let f=function(e){return e.CREDIT_CARD=`CREDIT_CARD`,e.CRYPTO=`CRYPTO`,e.DATE_TIME=`DATE_TIME`,e.EMAIL_ADDRESS=`EMAIL_ADDRESS`,e.IBAN_CODE=`IBAN_CODE`,e.IP_ADDRESS=`IP_ADDRESS`,e.PHONE_NUMBER=`PHONE_NUMBER`,e.URL=`URL`,e.CVV=`CVV`,e.BIC_SWIFT=`BIC_SWIFT`,e.US_BANK_NUMBER=`US_BANK_NUMBER`,e.US_DRIVER_LICENSE=`US_DRIVER_LICENSE`,e.US_ITIN=`US_ITIN`,e.US_PASSPORT=`US_PASSPORT`,e.US_SSN=`US_SSN`,e.UK_NHS=`UK_NHS`,e.UK_NINO=`UK_NINO`,e.ES_NIF=`ES_NIF`,e.ES_NIE=`ES_NIE`,e.IT_FISCAL_CODE=`IT_FISCAL_CODE`,e.IT_DOCUMENT=`IT_DOCUMENT`,e.IT_VAT_CODE=`IT_VAT_CODE`,e.PL_PESEL=`PL_PESEL`,e.FI_PERSONAL_IDENTITY_CODE=`FI_PERSONAL_IDENTITY_CODE`,e.SG_NRIC_FIN=`SG_NRIC_FIN`,e.SG_UEN=`SG_UEN`,e.AU_ABN=`AU_ABN`,e.AU_ACN=`AU_ACN`,e.AU_TFN=`AU_TFN`,e.AU_MEDICARE=`AU_MEDICARE`,e.IN_PAN=`IN_PAN`,e.IN_AADHAAR=`IN_AADHAAR`,e.IN_VEHICLE_REGISTRATION=`IN_VEHICLE_REGISTRATION`,e.IN_VOTER=`IN_VOTER`,e.IN_PASSPORT=`IN_PASSPORT`,e.KR_RRN=`KR_RRN`,e}({});const p=[`(?:[sS][wW][iI][fF][tT])`,`(?:[bB][iI][cC])`,`(?:[bB][aA][nN][kK][\\s-]?[cC][oO][dD][eE])`,`(?:[sS][wW][iI][fF][tT][\\s-]?[cC][oO][dD][eE])`,`(?:[bB][iI][cC][\\s-]?[cC][oO][dD][eE])`].join(`|`),m=RegExp(`(?:${p})[:\\s=]+([A-Z]{4}[A-Z]{2}[A-Z0-9]{2}(?:[A-Z0-9]{3})?)\\b`,`g`),h={[f.CREDIT_CARD]:[/\b\d{4}[-\s]?\d{4}[-\s]?\d{4}[-\s]?\d{4}\b/g],[f.CRYPTO]:[/\b[13][a-km-zA-HJ-NP-Z1-9]{25,34}\b/g],[f.DATE_TIME]:[/\b(0[1-9]|1[0-2])[/-](0[1-9]|[12]\d|3[01])[/-](19|20)\d{2}\b/g],[f.EMAIL_ADDRESS]:[/\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}\b/g,RegExp(`(?<=[?&=/])[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,}`,`g`)],[f.IBAN_CODE]:[/\b[A-Z]{2}[0-9]{2}[A-Z0-9]{4}[0-9]{7}([A-Z0-9]?){0,16}\b/g],[f.IP_ADDRESS]:[/\b(?:[0-9]{1,3}\.){3}[0-9]{1,3}\b/g,/\b(?:[0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}\b/g,/\b(?:[0-9a-fA-F]{1,4}:){1,7}:|:(?::[0-9a-fA-F]{1,4}){1,7}\b/g],[f.PHONE_NUMBER]:[/\b(\+\d{1,3}[-.\s]?)?\(?\d{3}\)?[-.\s]?\d{3}[-.\s]?\d{4}\b/g],[f.URL]:[/\bhttps?:\/\/(?:[-\w.])+(?::[0-9]+)?(?:\/(?:[\w/_.])*(?:\?(?:[\w&=%.])*)?(?:#(?:[\w.])*)?)?/g],[f.CVV]:[/\b(?:cvv|cvc|security\s*code|card\s*code)[\s:=]*[0-9]{3,4}\b/gi],[f.BIC_SWIFT]:[m],[f.US_BANK_NUMBER]:[/\b\d{8,17}\b/g],[f.US_DRIVER_LICENSE]:[/\b[A-Z]\d{7}\b/g],[f.US_ITIN]:[/\b9\d{2}-\d{2}-\d{4}\b/g],[f.US_PASSPORT]:[/\b[A-Z]\d{8}\b/g],[f.US_SSN]:[/\b\d{3}-\d{2}-\d{4}\b|\b\d{9}\b/g],[f.UK_NHS]:[/\b\d{3} \d{3} \d{4}\b/g],[f.UK_NINO]:[/\b[A-Z]{2}\d{6}[A-Z]\b/g],[f.ES_NIF]:[/\b\d{8}[A-Z]\b/g],[f.ES_NIE]:[/\b[XYZ]\d{7}[A-Z]\b/g],[f.IT_FISCAL_CODE]:[/\b[A-Z]{6}\d{2}[A-Z]\d{2}[A-Z]\d{3}[A-Z]\b/g],[f.IT_DOCUMENT]:[/\b[A-Z]{2}\d{7}\b/g],[f.IT_VAT_CODE]:[/\bIT\d{11}\b/g],[f.PL_PESEL]:[/\b\d{11}\b/g],[f.FI_PERSONAL_IDENTITY_CODE]:[/\b\d{6}[+-A]\d{3}[A-Z0-9]\b/g],[f.SG_NRIC_FIN]:[/\b[A-Z]\d{7}[A-Z]\b/g],[f.SG_UEN]:[/\b\d{8}[A-Z]\b|\b\d{9}[A-Z]\b/g],[f.AU_ABN]:[/\b\d{2} \d{3} \d{3} \d{3}\b/g],[f.AU_ACN]:[/\b\d{3} \d{3} \d{3}\b/g],[f.AU_TFN]:[/\b\d{9}\b/g],[f.AU_MEDICARE]:[/\b\d{4} \d{5} \d{1}\b/g],[f.IN_PAN]:[/\b[A-Z]{5}\d{4}[A-Z]\b/g],[f.IN_AADHAAR]:[/\b\d{4} \d{4} \d{4}\b/g],[f.IN_VEHICLE_REGISTRATION]:[/\b[A-Z]{2}\d{2}[A-Z]{2}\d{4}\b/g],[f.IN_VOTER]:[/\b[A-Z]{3}\d{7}\b/g],[f.IN_PASSPORT]:[/\b[A-Z]\d{7}\b/g],[f.KR_RRN]:[/\b\d{2}(0[1-9]|1[0-2])(0[1-9]|[12]\d|3[01])-[1-4]\d{6}\b/g]};function g(e,t=Object.values(f)){if(!e)return e;for(let n of t){let t=h[n];if(!t||!t.length)continue;for(let r of t)e=e.replace(r,`<${n}>`)}return e}function _(e){if(!e)return e;let t=/(?:\u200B|\u200C|\u200D|\u2060|\uFEFF)/g;try{return e.normalize(`NFKC`).replace(t,``)}catch{return e.replace(t,``)}}function v(e,t){let{nlp:n=!1,nlpRules:r=[],customRules:i=[],fixedPiiEntities:a=[]}=t||{},o=_(e);return(n||r.length>0)&&(o=r.length==0?u(o):u(o,r)),i.length>0&&(o=d(o,i)),a.length>0?g(o,a):g(o)}exports.FixedPIIEntity=f,exports.NlpEntity=l,exports.mask=v;
@@ -1,7 +1,9 @@
1
+ import { NlpEntity } from './pii-nlp';
1
2
  import { CustomRule } from './pii-custom-rules';
2
3
  import { FixedPIIEntity } from './pii-fixed-rules';
3
4
  export type { CustomRule } from './pii-custom-rules';
4
5
  export { FixedPIIEntity } from './pii-fixed-rules';
6
+ export { NlpEntity } from './pii-nlp';
5
7
  /**
6
8
  * Configuration options for the `mask` function.
7
9
  *
@@ -13,6 +15,8 @@ export { FixedPIIEntity } from './pii-fixed-rules';
13
15
  * Both properties are optional.
14
16
  */
15
17
  type MaskOptions = {
18
+ nlp?: boolean;
19
+ nlpRules?: NlpEntity[];
16
20
  customRules?: CustomRule[];
17
21
  fixedPiiEntities?: FixedPIIEntity[];
18
22
  };
package/dist/index.d.ts CHANGED
@@ -1,7 +1,9 @@
1
+ import { NlpEntity } from './pii-nlp';
1
2
  import { CustomRule } from './pii-custom-rules';
2
3
  import { FixedPIIEntity } from './pii-fixed-rules';
3
4
  export type { CustomRule } from './pii-custom-rules';
4
5
  export { FixedPIIEntity } from './pii-fixed-rules';
6
+ export { NlpEntity } from './pii-nlp';
5
7
  /**
6
8
  * Configuration options for the `mask` function.
7
9
  *
@@ -13,6 +15,8 @@ export { FixedPIIEntity } from './pii-fixed-rules';
13
15
  * Both properties are optional.
14
16
  */
15
17
  type MaskOptions = {
18
+ nlp?: boolean;
19
+ nlpRules?: NlpEntity[];
16
20
  customRules?: CustomRule[];
17
21
  fixedPiiEntities?: FixedPIIEntity[];
18
22
  };
package/dist/index.js CHANGED
@@ -1 +1 @@
1
- function e(e,t){if(!e||!t||t.length===0)return e;for(let n of t){if(!n.pattern||n.replacement===void 0)continue;e=e.replace(n.pattern,`<${n.replacement}>`)}return e}let t=function(e){return e.CREDIT_CARD=`CREDIT_CARD`,e.CRYPTO=`CRYPTO`,e.DATE_TIME=`DATE_TIME`,e.EMAIL_ADDRESS=`EMAIL_ADDRESS`,e.IBAN_CODE=`IBAN_CODE`,e.IP_ADDRESS=`IP_ADDRESS`,e.PHONE_NUMBER=`PHONE_NUMBER`,e.URL=`URL`,e.CVV=`CVV`,e.BIC_SWIFT=`BIC_SWIFT`,e.US_BANK_NUMBER=`US_BANK_NUMBER`,e.US_DRIVER_LICENSE=`US_DRIVER_LICENSE`,e.US_ITIN=`US_ITIN`,e.US_PASSPORT=`US_PASSPORT`,e.US_SSN=`US_SSN`,e.UK_NHS=`UK_NHS`,e.UK_NINO=`UK_NINO`,e.ES_NIF=`ES_NIF`,e.ES_NIE=`ES_NIE`,e.IT_FISCAL_CODE=`IT_FISCAL_CODE`,e.IT_DOCUMENT=`IT_DOCUMENT`,e.IT_VAT_CODE=`IT_VAT_CODE`,e.PL_PESEL=`PL_PESEL`,e.FI_PERSONAL_IDENTITY_CODE=`FI_PERSONAL_IDENTITY_CODE`,e.SG_NRIC_FIN=`SG_NRIC_FIN`,e.SG_UEN=`SG_UEN`,e.AU_ABN=`AU_ABN`,e.AU_ACN=`AU_ACN`,e.AU_TFN=`AU_TFN`,e.AU_MEDICARE=`AU_MEDICARE`,e.IN_PAN=`IN_PAN`,e.IN_AADHAAR=`IN_AADHAAR`,e.IN_VEHICLE_REGISTRATION=`IN_VEHICLE_REGISTRATION`,e.IN_VOTER=`IN_VOTER`,e.IN_PASSPORT=`IN_PASSPORT`,e.KR_RRN=`KR_RRN`,e}({});const n=[`(?:[sS][wW][iI][fF][tT])`,`(?:[bB][iI][cC])`,`(?:[bB][aA][nN][kK][\\s-]?[cC][oO][dD][eE])`,`(?:[sS][wW][iI][fF][tT][\\s-]?[cC][oO][dD][eE])`,`(?:[bB][iI][cC][\\s-]?[cC][oO][dD][eE])`].join(`|`),r=RegExp(`(?:${n})[:\\s=]+([A-Z]{4}[A-Z]{2}[A-Z0-9]{2}(?:[A-Z0-9]{3})?)\\b`,`g`),i={[t.CREDIT_CARD]:[/\b\d{4}[-\s]?\d{4}[-\s]?\d{4}[-\s]?\d{4}\b/g],[t.CRYPTO]:[/\b[13][a-km-zA-HJ-NP-Z1-9]{25,34}\b/g],[t.DATE_TIME]:[/\b(0[1-9]|1[0-2])[/-](0[1-9]|[12]\d|3[01])[/-](19|20)\d{2}\b/g],[t.EMAIL_ADDRESS]:[/\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}\b/g,RegExp(`(?<=[?&=/])[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,}`,`g`)],[t.IBAN_CODE]:[/\b[A-Z]{2}[0-9]{2}[A-Z0-9]{4}[0-9]{7}([A-Z0-9]?){0,16}\b/g],[t.IP_ADDRESS]:[/\b(?:[0-9]{1,3}\.){3}[0-9]{1,3}\b/g,/\b(?:[0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}\b/g,/\b(?:[0-9a-fA-F]{1,4}:){1,7}:|:(?::[0-9a-fA-F]{1,4}){1,7}\b/g],[t.PHONE_NUMBER]:[/\b(\+\d{1,3}[-.\s]?)?\(?\d{3}\)?[-.\s]?\d{3}[-.\s]?\d{4}\b/g],[t.URL]:[/\bhttps?:\/\/(?:[-\w.])+(?::[0-9]+)?(?:\/(?:[\w/_.])*(?:\?(?:[\w&=%.])*)?(?:#(?:[\w.])*)?)?/g],[t.CVV]:[/\b(?:cvv|cvc|security\s*code|card\s*code)[\s:=]*[0-9]{3,4}\b/gi],[t.BIC_SWIFT]:[r],[t.US_BANK_NUMBER]:[/\b\d{8,17}\b/g],[t.US_DRIVER_LICENSE]:[/\b[A-Z]\d{7}\b/g],[t.US_ITIN]:[/\b9\d{2}-\d{2}-\d{4}\b/g],[t.US_PASSPORT]:[/\b[A-Z]\d{8}\b/g],[t.US_SSN]:[/\b\d{3}-\d{2}-\d{4}\b|\b\d{9}\b/g],[t.UK_NHS]:[/\b\d{3} \d{3} \d{4}\b/g],[t.UK_NINO]:[/\b[A-Z]{2}\d{6}[A-Z]\b/g],[t.ES_NIF]:[/\b\d{8}[A-Z]\b/g],[t.ES_NIE]:[/\b[XYZ]\d{7}[A-Z]\b/g],[t.IT_FISCAL_CODE]:[/\b[A-Z]{6}\d{2}[A-Z]\d{2}[A-Z]\d{3}[A-Z]\b/g],[t.IT_DOCUMENT]:[/\b[A-Z]{2}\d{7}\b/g],[t.IT_VAT_CODE]:[/\bIT\d{11}\b/g],[t.PL_PESEL]:[/\b\d{11}\b/g],[t.FI_PERSONAL_IDENTITY_CODE]:[/\b\d{6}[+-A]\d{3}[A-Z0-9]\b/g],[t.SG_NRIC_FIN]:[/\b[A-Z]\d{7}[A-Z]\b/g],[t.SG_UEN]:[/\b\d{8}[A-Z]\b|\b\d{9}[A-Z]\b/g],[t.AU_ABN]:[/\b\d{2} \d{3} \d{3} \d{3}\b/g],[t.AU_ACN]:[/\b\d{3} \d{3} \d{3}\b/g],[t.AU_TFN]:[/\b\d{9}\b/g],[t.AU_MEDICARE]:[/\b\d{4} \d{5} \d{1}\b/g],[t.IN_PAN]:[/\b[A-Z]{5}\d{4}[A-Z]\b/g],[t.IN_AADHAAR]:[/\b\d{4} \d{4} \d{4}\b/g],[t.IN_VEHICLE_REGISTRATION]:[/\b[A-Z]{2}\d{2}[A-Z]{2}\d{4}\b/g],[t.IN_VOTER]:[/\b[A-Z]{3}\d{7}\b/g],[t.IN_PASSPORT]:[/\b[A-Z]\d{7}\b/g],[t.KR_RRN]:[/\b\d{2}(0[1-9]|1[0-2])(0[1-9]|[12]\d|3[01])-[1-4]\d{6}\b/g]};function a(e,n=Object.values(t)){if(!e)return e;for(let t of n){let n=i[t];if(!n||!n.length)continue;for(let r of n)e=e.replace(r,`<${t}>`)}return e}function o(e){if(!e)return e;let t=/(?:\u200B|\u200C|\u200D|\u2060|\uFEFF)/g;try{return e.normalize(`NFKC`).replace(t,``)}catch{return e.replace(t,``)}}function s(t,n){let{customRules:r=[],fixedPiiEntities:i=[]}=n||{},s=o(t);return r.length>0&&(s=e(s,r)),i.length>0?a(s,i):a(s)}exports.FixedPIIEntity=t,exports.mask=s;
1
+ import e from"compromise";let t=function(e){return e.ACRONYMS=`acronyms`,e.MONEY=`money`,e.ORGS=`organizations`,e.PEOPLE=`people`,e.PLACES=`places`,e}({});function n(n,r=Object.values(t)){if(!n||r.length===0)return n;let i=e(n);return r.forEach(e=>{let t=i[e]().out(`array`);t.forEach(t=>{n=n.replaceAll(t,`<${e.toUpperCase()}>`)})}),n}function r(e,t){if(!e||!t||t.length===0)return e;for(let n of t){if(!n.pattern||n.replacement===void 0)continue;e=e.replace(n.pattern,`<${n.replacement}>`)}return e}let i=function(e){return e.CREDIT_CARD=`CREDIT_CARD`,e.CRYPTO=`CRYPTO`,e.DATE_TIME=`DATE_TIME`,e.EMAIL_ADDRESS=`EMAIL_ADDRESS`,e.IBAN_CODE=`IBAN_CODE`,e.IP_ADDRESS=`IP_ADDRESS`,e.PHONE_NUMBER=`PHONE_NUMBER`,e.URL=`URL`,e.CVV=`CVV`,e.BIC_SWIFT=`BIC_SWIFT`,e.US_BANK_NUMBER=`US_BANK_NUMBER`,e.US_DRIVER_LICENSE=`US_DRIVER_LICENSE`,e.US_ITIN=`US_ITIN`,e.US_PASSPORT=`US_PASSPORT`,e.US_SSN=`US_SSN`,e.UK_NHS=`UK_NHS`,e.UK_NINO=`UK_NINO`,e.ES_NIF=`ES_NIF`,e.ES_NIE=`ES_NIE`,e.IT_FISCAL_CODE=`IT_FISCAL_CODE`,e.IT_DOCUMENT=`IT_DOCUMENT`,e.IT_VAT_CODE=`IT_VAT_CODE`,e.PL_PESEL=`PL_PESEL`,e.FI_PERSONAL_IDENTITY_CODE=`FI_PERSONAL_IDENTITY_CODE`,e.SG_NRIC_FIN=`SG_NRIC_FIN`,e.SG_UEN=`SG_UEN`,e.AU_ABN=`AU_ABN`,e.AU_ACN=`AU_ACN`,e.AU_TFN=`AU_TFN`,e.AU_MEDICARE=`AU_MEDICARE`,e.IN_PAN=`IN_PAN`,e.IN_AADHAAR=`IN_AADHAAR`,e.IN_VEHICLE_REGISTRATION=`IN_VEHICLE_REGISTRATION`,e.IN_VOTER=`IN_VOTER`,e.IN_PASSPORT=`IN_PASSPORT`,e.KR_RRN=`KR_RRN`,e}({});const a=[`(?:[sS][wW][iI][fF][tT])`,`(?:[bB][iI][cC])`,`(?:[bB][aA][nN][kK][\\s-]?[cC][oO][dD][eE])`,`(?:[sS][wW][iI][fF][tT][\\s-]?[cC][oO][dD][eE])`,`(?:[bB][iI][cC][\\s-]?[cC][oO][dD][eE])`].join(`|`),o=RegExp(`(?:${a})[:\\s=]+([A-Z]{4}[A-Z]{2}[A-Z0-9]{2}(?:[A-Z0-9]{3})?)\\b`,`g`),s={[i.CREDIT_CARD]:[/\b\d{4}[-\s]?\d{4}[-\s]?\d{4}[-\s]?\d{4}\b/g],[i.CRYPTO]:[/\b[13][a-km-zA-HJ-NP-Z1-9]{25,34}\b/g],[i.DATE_TIME]:[/\b(0[1-9]|1[0-2])[/-](0[1-9]|[12]\d|3[01])[/-](19|20)\d{2}\b/g],[i.EMAIL_ADDRESS]:[/\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}\b/g,RegExp(`(?<=[?&=/])[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,}`,`g`)],[i.IBAN_CODE]:[/\b[A-Z]{2}[0-9]{2}[A-Z0-9]{4}[0-9]{7}([A-Z0-9]?){0,16}\b/g],[i.IP_ADDRESS]:[/\b(?:[0-9]{1,3}\.){3}[0-9]{1,3}\b/g,/\b(?:[0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}\b/g,/\b(?:[0-9a-fA-F]{1,4}:){1,7}:|:(?::[0-9a-fA-F]{1,4}){1,7}\b/g],[i.PHONE_NUMBER]:[/\b(\+\d{1,3}[-.\s]?)?\(?\d{3}\)?[-.\s]?\d{3}[-.\s]?\d{4}\b/g],[i.URL]:[/\bhttps?:\/\/(?:[-\w.])+(?::[0-9]+)?(?:\/(?:[\w/_.])*(?:\?(?:[\w&=%.])*)?(?:#(?:[\w.])*)?)?/g],[i.CVV]:[/\b(?:cvv|cvc|security\s*code|card\s*code)[\s:=]*[0-9]{3,4}\b/gi],[i.BIC_SWIFT]:[o],[i.US_BANK_NUMBER]:[/\b\d{8,17}\b/g],[i.US_DRIVER_LICENSE]:[/\b[A-Z]\d{7}\b/g],[i.US_ITIN]:[/\b9\d{2}-\d{2}-\d{4}\b/g],[i.US_PASSPORT]:[/\b[A-Z]\d{8}\b/g],[i.US_SSN]:[/\b\d{3}-\d{2}-\d{4}\b|\b\d{9}\b/g],[i.UK_NHS]:[/\b\d{3} \d{3} \d{4}\b/g],[i.UK_NINO]:[/\b[A-Z]{2}\d{6}[A-Z]\b/g],[i.ES_NIF]:[/\b\d{8}[A-Z]\b/g],[i.ES_NIE]:[/\b[XYZ]\d{7}[A-Z]\b/g],[i.IT_FISCAL_CODE]:[/\b[A-Z]{6}\d{2}[A-Z]\d{2}[A-Z]\d{3}[A-Z]\b/g],[i.IT_DOCUMENT]:[/\b[A-Z]{2}\d{7}\b/g],[i.IT_VAT_CODE]:[/\bIT\d{11}\b/g],[i.PL_PESEL]:[/\b\d{11}\b/g],[i.FI_PERSONAL_IDENTITY_CODE]:[/\b\d{6}[+-A]\d{3}[A-Z0-9]\b/g],[i.SG_NRIC_FIN]:[/\b[A-Z]\d{7}[A-Z]\b/g],[i.SG_UEN]:[/\b\d{8}[A-Z]\b|\b\d{9}[A-Z]\b/g],[i.AU_ABN]:[/\b\d{2} \d{3} \d{3} \d{3}\b/g],[i.AU_ACN]:[/\b\d{3} \d{3} \d{3}\b/g],[i.AU_TFN]:[/\b\d{9}\b/g],[i.AU_MEDICARE]:[/\b\d{4} \d{5} \d{1}\b/g],[i.IN_PAN]:[/\b[A-Z]{5}\d{4}[A-Z]\b/g],[i.IN_AADHAAR]:[/\b\d{4} \d{4} \d{4}\b/g],[i.IN_VEHICLE_REGISTRATION]:[/\b[A-Z]{2}\d{2}[A-Z]{2}\d{4}\b/g],[i.IN_VOTER]:[/\b[A-Z]{3}\d{7}\b/g],[i.IN_PASSPORT]:[/\b[A-Z]\d{7}\b/g],[i.KR_RRN]:[/\b\d{2}(0[1-9]|1[0-2])(0[1-9]|[12]\d|3[01])-[1-4]\d{6}\b/g]};function c(e,t=Object.values(i)){if(!e)return e;for(let n of t){let t=s[n];if(!t||!t.length)continue;for(let r of t)e=e.replace(r,`<${n}>`)}return e}function l(e){if(!e)return e;let t=/(?:\u200B|\u200C|\u200D|\u2060|\uFEFF)/g;try{return e.normalize(`NFKC`).replace(t,``)}catch{return e.replace(t,``)}}function u(e,t){let{nlp:i=!1,nlpRules:a=[],customRules:o=[],fixedPiiEntities:s=[]}=t||{},u=l(e);return(i||a.length>0)&&(u=a.length==0?n(u):n(u,a)),o.length>0&&(u=r(u,o)),s.length>0?c(u,s):c(u)}export{i as FixedPIIEntity,t as NlpEntity,u as mask};
@@ -0,0 +1,43 @@
1
+ /**
2
+ * Supported NLP entity types.
3
+ *
4
+ * These map directly to `compromise` library methods for entity extraction.
5
+ * Useful for detecting dynamic PII that lacks a fixed structure.
6
+ */
7
+ export declare enum NlpEntity {
8
+ ACRONYMS = "acronyms",
9
+ MONEY = "money",
10
+ ORGS = "organizations",
11
+ PEOPLE = "people",
12
+ PLACES = "places"
13
+ }
14
+ /**
15
+ * Apply NLP-based masking rules to text.
16
+ *
17
+ * Uses the `compromise` library to identify and mask dynamic entities.
18
+ * This function handles the entities sequentially.
19
+ *
20
+ * Use Cases:
21
+ * - Masking names in free text
22
+ * - Masking cities or organizations
23
+ *
24
+ * Limitations:
25
+ * - Performance: Slower than `applyFixedRules`. Use only when necessary.
26
+ * - Accuracy: Depends on `compromise` heuristics. Best suited for complete sentences in English.
27
+ *
28
+ * @param text - The text to scan and mask
29
+ * @param entities - List of NLP entity types to detect (defaults to ALL)
30
+ *
31
+ * @returns The text with detected entities replaced by placeholders (e.g. <PEOPLE>)
32
+ *
33
+ * @example
34
+ * // Default usage (masks all supported NLP entities)
35
+ * applyNlpRules("John Smith visited Paris")
36
+ * // Returns: "<PEOPLE> visited <PLACES>"
37
+ *
38
+ * @example
39
+ * // Selective masking
40
+ * applyNlpRules("Google bought Fitbit for $2.1 billion", [NlpEntity.ORGS])
41
+ * // Returns: "<ORGS> bought <ORGS> for $2.1 billion"
42
+ */
43
+ export declare function applyNlpRules(text: string, entities?: NlpEntity[]): string;
@@ -0,0 +1,43 @@
1
+ /**
2
+ * Supported NLP entity types.
3
+ *
4
+ * These map directly to `compromise` library methods for entity extraction.
5
+ * Useful for detecting dynamic PII that lacks a fixed structure.
6
+ */
7
+ export declare enum NlpEntity {
8
+ ACRONYMS = "acronyms",
9
+ MONEY = "money",
10
+ ORGS = "organizations",
11
+ PEOPLE = "people",
12
+ PLACES = "places"
13
+ }
14
+ /**
15
+ * Apply NLP-based masking rules to text.
16
+ *
17
+ * Uses the `compromise` library to identify and mask dynamic entities.
18
+ * This function handles the entities sequentially.
19
+ *
20
+ * Use Cases:
21
+ * - Masking names in free text
22
+ * - Masking cities or organizations
23
+ *
24
+ * Limitations:
25
+ * - Performance: Slower than `applyFixedRules`. Use only when necessary.
26
+ * - Accuracy: Depends on `compromise` heuristics. Best suited for complete sentences in English.
27
+ *
28
+ * @param text - The text to scan and mask
29
+ * @param entities - List of NLP entity types to detect (defaults to ALL)
30
+ *
31
+ * @returns The text with detected entities replaced by placeholders (e.g. <PEOPLE>)
32
+ *
33
+ * @example
34
+ * // Default usage (masks all supported NLP entities)
35
+ * applyNlpRules("John Smith visited Paris")
36
+ * // Returns: "<PEOPLE> visited <PLACES>"
37
+ *
38
+ * @example
39
+ * // Selective masking
40
+ * applyNlpRules("Google bought Fitbit for $2.1 billion", [NlpEntity.ORGS])
41
+ * // Returns: "<ORGS> bought <ORGS> for $2.1 billion"
42
+ */
43
+ export declare function applyNlpRules(text: string, entities?: NlpEntity[]): string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yellowsakura/js-pii-mask",
3
- "version": "0.8.93",
3
+ "version": "0.9.0",
4
4
  "description": "Simple and effective PII data masking library for TypeScript/JavaScript",
5
5
  "keywords": [
6
6
  "pii",
@@ -8,12 +8,8 @@
8
8
  "masking",
9
9
  "data-privacy",
10
10
  "privacy",
11
- "gdpr",
12
- "ccpa",
13
11
  "anonymization",
14
- "typescript",
15
- "personal-data",
16
- "sensitive-data"
12
+ "personal-data"
17
13
  ],
18
14
  "homepage": "https://github.com/YellowSakura/js-pii-mask#readme",
19
15
  "bugs": {
@@ -25,7 +21,8 @@
25
21
  },
26
22
  "license": "MIT",
27
23
  "author": "Yellow Sakura",
28
- "main": "./dist/index.js",
24
+ "main": "./dist/index.cjs",
25
+ "type": "module",
29
26
  "types": "./dist/index.d.ts",
30
27
  "directories": {
31
28
  "doc": "docs",
@@ -56,5 +53,8 @@
56
53
  "engines": {
57
54
  "node": ">=24.12.0"
58
55
  },
59
- "module": "./dist/index.mjs"
56
+ "module": "./dist/index.js",
57
+ "dependencies": {
58
+ "compromise": "^14.14.5"
59
+ }
60
60
  }
package/dist/index.mjs DELETED
@@ -1 +0,0 @@
1
- function e(e,t){if(!e||!t||t.length===0)return e;for(let n of t){if(!n.pattern||n.replacement===void 0)continue;e=e.replace(n.pattern,`<${n.replacement}>`)}return e}let t=function(e){return e.CREDIT_CARD=`CREDIT_CARD`,e.CRYPTO=`CRYPTO`,e.DATE_TIME=`DATE_TIME`,e.EMAIL_ADDRESS=`EMAIL_ADDRESS`,e.IBAN_CODE=`IBAN_CODE`,e.IP_ADDRESS=`IP_ADDRESS`,e.PHONE_NUMBER=`PHONE_NUMBER`,e.URL=`URL`,e.CVV=`CVV`,e.BIC_SWIFT=`BIC_SWIFT`,e.US_BANK_NUMBER=`US_BANK_NUMBER`,e.US_DRIVER_LICENSE=`US_DRIVER_LICENSE`,e.US_ITIN=`US_ITIN`,e.US_PASSPORT=`US_PASSPORT`,e.US_SSN=`US_SSN`,e.UK_NHS=`UK_NHS`,e.UK_NINO=`UK_NINO`,e.ES_NIF=`ES_NIF`,e.ES_NIE=`ES_NIE`,e.IT_FISCAL_CODE=`IT_FISCAL_CODE`,e.IT_DOCUMENT=`IT_DOCUMENT`,e.IT_VAT_CODE=`IT_VAT_CODE`,e.PL_PESEL=`PL_PESEL`,e.FI_PERSONAL_IDENTITY_CODE=`FI_PERSONAL_IDENTITY_CODE`,e.SG_NRIC_FIN=`SG_NRIC_FIN`,e.SG_UEN=`SG_UEN`,e.AU_ABN=`AU_ABN`,e.AU_ACN=`AU_ACN`,e.AU_TFN=`AU_TFN`,e.AU_MEDICARE=`AU_MEDICARE`,e.IN_PAN=`IN_PAN`,e.IN_AADHAAR=`IN_AADHAAR`,e.IN_VEHICLE_REGISTRATION=`IN_VEHICLE_REGISTRATION`,e.IN_VOTER=`IN_VOTER`,e.IN_PASSPORT=`IN_PASSPORT`,e.KR_RRN=`KR_RRN`,e}({});const n=[`(?:[sS][wW][iI][fF][tT])`,`(?:[bB][iI][cC])`,`(?:[bB][aA][nN][kK][\\s-]?[cC][oO][dD][eE])`,`(?:[sS][wW][iI][fF][tT][\\s-]?[cC][oO][dD][eE])`,`(?:[bB][iI][cC][\\s-]?[cC][oO][dD][eE])`].join(`|`),r=RegExp(`(?:${n})[:\\s=]+([A-Z]{4}[A-Z]{2}[A-Z0-9]{2}(?:[A-Z0-9]{3})?)\\b`,`g`),i={[t.CREDIT_CARD]:[/\b\d{4}[-\s]?\d{4}[-\s]?\d{4}[-\s]?\d{4}\b/g],[t.CRYPTO]:[/\b[13][a-km-zA-HJ-NP-Z1-9]{25,34}\b/g],[t.DATE_TIME]:[/\b(0[1-9]|1[0-2])[/-](0[1-9]|[12]\d|3[01])[/-](19|20)\d{2}\b/g],[t.EMAIL_ADDRESS]:[/\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}\b/g,RegExp(`(?<=[?&=/])[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,}`,`g`)],[t.IBAN_CODE]:[/\b[A-Z]{2}[0-9]{2}[A-Z0-9]{4}[0-9]{7}([A-Z0-9]?){0,16}\b/g],[t.IP_ADDRESS]:[/\b(?:[0-9]{1,3}\.){3}[0-9]{1,3}\b/g,/\b(?:[0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}\b/g,/\b(?:[0-9a-fA-F]{1,4}:){1,7}:|:(?::[0-9a-fA-F]{1,4}){1,7}\b/g],[t.PHONE_NUMBER]:[/\b(\+\d{1,3}[-.\s]?)?\(?\d{3}\)?[-.\s]?\d{3}[-.\s]?\d{4}\b/g],[t.URL]:[/\bhttps?:\/\/(?:[-\w.])+(?::[0-9]+)?(?:\/(?:[\w/_.])*(?:\?(?:[\w&=%.])*)?(?:#(?:[\w.])*)?)?/g],[t.CVV]:[/\b(?:cvv|cvc|security\s*code|card\s*code)[\s:=]*[0-9]{3,4}\b/gi],[t.BIC_SWIFT]:[r],[t.US_BANK_NUMBER]:[/\b\d{8,17}\b/g],[t.US_DRIVER_LICENSE]:[/\b[A-Z]\d{7}\b/g],[t.US_ITIN]:[/\b9\d{2}-\d{2}-\d{4}\b/g],[t.US_PASSPORT]:[/\b[A-Z]\d{8}\b/g],[t.US_SSN]:[/\b\d{3}-\d{2}-\d{4}\b|\b\d{9}\b/g],[t.UK_NHS]:[/\b\d{3} \d{3} \d{4}\b/g],[t.UK_NINO]:[/\b[A-Z]{2}\d{6}[A-Z]\b/g],[t.ES_NIF]:[/\b\d{8}[A-Z]\b/g],[t.ES_NIE]:[/\b[XYZ]\d{7}[A-Z]\b/g],[t.IT_FISCAL_CODE]:[/\b[A-Z]{6}\d{2}[A-Z]\d{2}[A-Z]\d{3}[A-Z]\b/g],[t.IT_DOCUMENT]:[/\b[A-Z]{2}\d{7}\b/g],[t.IT_VAT_CODE]:[/\bIT\d{11}\b/g],[t.PL_PESEL]:[/\b\d{11}\b/g],[t.FI_PERSONAL_IDENTITY_CODE]:[/\b\d{6}[+-A]\d{3}[A-Z0-9]\b/g],[t.SG_NRIC_FIN]:[/\b[A-Z]\d{7}[A-Z]\b/g],[t.SG_UEN]:[/\b\d{8}[A-Z]\b|\b\d{9}[A-Z]\b/g],[t.AU_ABN]:[/\b\d{2} \d{3} \d{3} \d{3}\b/g],[t.AU_ACN]:[/\b\d{3} \d{3} \d{3}\b/g],[t.AU_TFN]:[/\b\d{9}\b/g],[t.AU_MEDICARE]:[/\b\d{4} \d{5} \d{1}\b/g],[t.IN_PAN]:[/\b[A-Z]{5}\d{4}[A-Z]\b/g],[t.IN_AADHAAR]:[/\b\d{4} \d{4} \d{4}\b/g],[t.IN_VEHICLE_REGISTRATION]:[/\b[A-Z]{2}\d{2}[A-Z]{2}\d{4}\b/g],[t.IN_VOTER]:[/\b[A-Z]{3}\d{7}\b/g],[t.IN_PASSPORT]:[/\b[A-Z]\d{7}\b/g],[t.KR_RRN]:[/\b\d{2}(0[1-9]|1[0-2])(0[1-9]|[12]\d|3[01])-[1-4]\d{6}\b/g]};function a(e,n=Object.values(t)){if(!e)return e;for(let t of n){let n=i[t];if(!n||!n.length)continue;for(let r of n)e=e.replace(r,`<${t}>`)}return e}function o(e){if(!e)return e;let t=/(?:\u200B|\u200C|\u200D|\u2060|\uFEFF)/g;try{return e.normalize(`NFKC`).replace(t,``)}catch{return e.replace(t,``)}}function s(t,n){let{customRules:r=[],fixedPiiEntities:i=[]}=n||{},s=o(t);return r.length>0&&(s=e(s,r)),i.length>0?a(s,i):a(s)}export{t as FixedPIIEntity,s as mask};