euredact 0.5.1 → 0.7.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/NOTICE +11 -0
- package/README.md +658 -45
- package/dist/cjs/cache.js +2 -8
- package/dist/cjs/cloud/account.js +180 -0
- package/dist/cjs/cloud/batches.js +469 -0
- package/dist/cjs/cloud/client.js +131 -18
- package/dist/cjs/cloud/config.js +28 -2
- package/dist/cjs/cloud/errors.js +39 -2
- package/dist/cjs/cloud/index.js +16 -1
- package/dist/cjs/index.js +9 -1
- package/dist/cjs/platform.browser.js +98 -0
- package/dist/cjs/platform.js +140 -0
- package/dist/cjs/rules/bicGleif.js +57 -0
- package/dist/cjs/rules/bicRegistry.js +37 -11
- package/dist/cjs/rules/countries/index.js +138 -48
- package/dist/cjs/rules/cues.js +29 -9
- package/dist/cjs/rules/engine.js +14 -6
- package/dist/cjs/rules/suppressors.js +418 -23
- package/dist/cjs/rules/validators.js +103 -0
- package/dist/cjs/sdk.js +150 -44
- package/dist/cjs/types.js +4 -1
- package/dist/esm/cache.js +2 -8
- package/dist/esm/cloud/account.d.ts +155 -0
- package/dist/esm/cloud/account.js +175 -0
- package/dist/esm/cloud/batches.d.ts +166 -0
- package/dist/esm/cloud/batches.js +464 -0
- package/dist/esm/cloud/client.d.ts +90 -5
- package/dist/esm/cloud/client.js +126 -26
- package/dist/esm/cloud/config.d.ts +6 -0
- package/dist/esm/cloud/config.js +27 -2
- package/dist/esm/cloud/errors.d.ts +26 -1
- package/dist/esm/cloud/errors.js +35 -1
- package/dist/esm/cloud/index.d.ts +4 -2
- package/dist/esm/cloud/index.js +4 -2
- package/dist/esm/index.d.ts +2 -2
- package/dist/esm/index.js +1 -1
- package/dist/esm/platform.browser.d.ts +27 -0
- package/dist/esm/platform.browser.js +92 -0
- package/dist/esm/platform.d.ts +20 -0
- package/dist/esm/platform.js +101 -0
- package/dist/esm/rules/bicGleif.d.ts +4 -0
- package/dist/esm/rules/bicGleif.js +53 -0
- package/dist/esm/rules/bicRegistry.d.ts +25 -11
- package/dist/esm/rules/bicRegistry.js +36 -11
- package/dist/esm/rules/countries/index.js +138 -48
- package/dist/esm/rules/cues.d.ts +1 -1
- package/dist/esm/rules/cues.js +29 -9
- package/dist/esm/rules/engine.js +14 -6
- package/dist/esm/rules/suppressors.d.ts +1 -0
- package/dist/esm/rules/suppressors.js +417 -22
- package/dist/esm/rules/validators.d.ts +14 -0
- package/dist/esm/rules/validators.js +100 -0
- package/dist/esm/sdk.d.ts +63 -19
- package/dist/esm/sdk.js +148 -44
- package/dist/esm/types.d.ts +58 -2
- package/dist/esm/types.js +4 -1
- package/package.json +12 -4
|
@@ -1,5 +1,14 @@
|
|
|
1
1
|
import { EntityType } from "../../types.js";
|
|
2
2
|
import { IBAN_LENGTHS } from "../validators.js";
|
|
3
|
+
import { MONTH_NAMES } from "../suppressors.js";
|
|
4
|
+
/** Day, month as a word, year ("4. März 1948"), behind a date label (rules-engine#115). */
|
|
5
|
+
function writtenDatePattern() {
|
|
6
|
+
const names = new Set(MONTH_NAMES.split("|").filter(Boolean));
|
|
7
|
+
for (const m of [...names])
|
|
8
|
+
names.add(m.charAt(0).toUpperCase() + m.slice(1));
|
|
9
|
+
const months = [...names].sort((a, b) => b.length - a.length || (a < b ? -1 : a > b ? 1 : 0)).join("|");
|
|
10
|
+
return String.raw `\b(?:0?[1-9]|[12][0-9]|3[01])\.?\s+(?:` + months + String.raw `)\.?\s+(?:19|20)\d{2}\b`;
|
|
11
|
+
}
|
|
3
12
|
/**
|
|
4
13
|
* Build a country-independent IBAN pattern from the ISO 13616 length table.
|
|
5
14
|
*
|
|
@@ -102,23 +111,56 @@ const SECRET_CONTEXT = [
|
|
|
102
111
|
// ---------------------------------------------------------------------------
|
|
103
112
|
// DOB context keywords (reused across SHARED patterns)
|
|
104
113
|
// ---------------------------------------------------------------------------
|
|
114
|
+
// Every way the documents this engine sees introduce a date of birth.
|
|
115
|
+
//
|
|
116
|
+
// DOB recall was 62.8% -- 33,441 unmasked birth dates -- because this covered
|
|
117
|
+
// seven languages of thirty-one. Eleven countries scored exactly 100% (the
|
|
118
|
+
// listed languages) while twenty sat at 42-51%, which is what proved it was
|
|
119
|
+
// coverage rather than capability (rules-engine#38).
|
|
120
|
+
//
|
|
121
|
+
// Matching is substring, not word-boundary, so every entry was screened against
|
|
122
|
+
// the 29.2-million-character corpus for occurrences inside a longer word. Two
|
|
123
|
+
// were rejected: `fædd` lives inside `fæddur`, and `born` was found inside
|
|
124
|
+
// `gabornagy` and `gabornemeth` -- Hungarian names as e-mail local parts -- so
|
|
125
|
+
// `"born "` with the trailing space is listed instead.
|
|
126
|
+
//
|
|
127
|
+
// DOB_CONTEXT is gone: it was a second, shorter copy missing `nato il`,
|
|
128
|
+
// `nascido`, `geburtstag` and more, so ISO dates were gated on fewer keywords
|
|
129
|
+
// than DD/MM/YYYY ones for no stated reason.
|
|
105
130
|
const DOB_CONTEXT = [
|
|
131
|
+
// Germanic / Romance -- the original set, kept verbatim.
|
|
106
132
|
"geboren", "geboortedatum", "date de naissance", "né le", "née le",
|
|
107
133
|
"né(e) le", "nee le", "nee(e) le", "date of birth", "DOB",
|
|
108
134
|
"Geburtsdatum", "geboren am", "geboren op", "nascido", "nacido",
|
|
109
135
|
"data di nascita", "nato il", "nata il", "geb.", "geb.datum", "geb ",
|
|
110
136
|
"birth date", "birthday", "naissance", "geboorte", "geburtstag",
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
"
|
|
115
|
-
"
|
|
116
|
-
|
|
137
|
+
// English and Italian forms the list was missing.
|
|
138
|
+
"born ", "d.o.b", "nato/a il",
|
|
139
|
+
// Nordic.
|
|
140
|
+
"født", "fødselsdato", "född", "födelsedatum",
|
|
141
|
+
"syntynyt", "syntymäaika", "fæddur", "fæðingardagur",
|
|
142
|
+
// Greek -- Greece and Cyprus.
|
|
143
|
+
"γεννηθείς", "γεννήθηκε", "ημερομηνία γέννησης",
|
|
144
|
+
// West Slavic.
|
|
145
|
+
"urodzony", "urodzona", "data urodzenia",
|
|
146
|
+
"narozen", "datum narození", "narodený", "dátum narodenia",
|
|
147
|
+
// Hungarian, Romanian, Bulgarian.
|
|
148
|
+
"született", "születési", "născut", "născută", "data nașterii",
|
|
149
|
+
"роден", "родена", "дата на раждане",
|
|
150
|
+
// South Slavic.
|
|
151
|
+
"rođen", "rođena", "datum rođenja", "rojen", "rojena", "datum rojstva",
|
|
152
|
+
// Baltic.
|
|
153
|
+
"sündinud", "sünniaeg", "dzimis", "dzimusi", "dzimšanas datums",
|
|
154
|
+
"gimęs", "gimusi", "gimimo data",
|
|
155
|
+
// Maltese, Irish, Turkish (Cyprus).
|
|
156
|
+
"twieled", "twieldet", "data tat-twelid",
|
|
157
|
+
"rugadh", "dáta breithe", "doğum tarihi",
|
|
117
158
|
];
|
|
118
159
|
const DATE_OF_DEATH_CONTEXT = [
|
|
119
160
|
"overleden", "overlijdensdatum", "date de décès", "décédé le",
|
|
120
161
|
"date of death", "Sterbedatum", "verstorben am", "gestorven",
|
|
121
162
|
"death date", "died on", "mort le", "décès",
|
|
163
|
+
"datum van overlijden", "décédée le", "Sterbetag",
|
|
122
164
|
];
|
|
123
165
|
// ---------------------------------------------------------------------------
|
|
124
166
|
// Country configurations
|
|
@@ -173,6 +215,9 @@ const SHARED = {
|
|
|
173
215
|
p(EntityType.BIC, String.raw `\b[A-Z]{4} [A-Z]{2} [A-Z0-9]{2}(?: [A-Z0-9]{3})?\b`, "bic", "BIC/SWIFT code (space-separated groups)"),
|
|
174
216
|
p(EntityType.CREDIT_CARD, String.raw `\b(?:4[0-9]{3}[\s\-]?[0-9]{4}[\s\-]?[0-9]{4}[\s\-]?[0-9]{4}|5[1-5][0-9]{2}[\s\-]?[0-9]{4}[\s\-]?[0-9]{4}[\s\-]?[0-9]{4}|3[47][0-9]{2}[\s\-]?[0-9]{6}[\s\-]?[0-9]{5})\b`, "luhn"),
|
|
175
217
|
p(EntityType.VIN, String.raw `\b[A-HJ-NPR-Z0-9]{17}\b`, "vin"),
|
|
218
|
+
// Behind its label: any case, or in its three sections 3-6-8 (rules-engine#110).
|
|
219
|
+
p(EntityType.VIN, String.raw `\b[A-HJ-NPR-Za-hj-npr-z0-9]{13}\d{4}\b`, "vin", "VIN — any case, behind its label", ["VIN", "FIN:", "FIN-Nr", "FIN-Nummer", "Fahrgestellnummer", "Fahrzeug-Identifizierungsnummer", "Fahrzeugidentifizierungsnummer", "châssis", "chassis", "chassisnummer", "chasisnummer", "numéro de série", "vehicle identification", "numero di telaio", "telaio", "bastidor", "número de bastidor", "VIN-code", "VIN-kod"], true),
|
|
220
|
+
p(EntityType.VIN, String.raw `\b[A-HJ-NPR-Za-hj-npr-z0-9]{3}[\s\-][A-HJ-NPR-Za-hj-npr-z0-9]{6}[\s\-][A-HJ-NPR-Za-hj-npr-z0-9]{4}\d{4}\b`, "vin", "VIN — in sections, behind its label", ["VIN", "FIN:", "FIN-Nr", "FIN-Nummer", "Fahrgestellnummer", "Fahrzeug-Identifizierungsnummer", "Fahrzeugidentifizierungsnummer", "châssis", "chassis", "chassisnummer", "chasisnummer", "numéro de série", "vehicle identification", "numero di telaio", "telaio", "bastidor", "número de bastidor", "VIN-code", "VIN-kod"], true),
|
|
176
221
|
p(EntityType.IP_ADDRESS, String.raw `\b(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\b`),
|
|
177
222
|
// Branch order is load-bearing: alternation is leftmost-first, not
|
|
178
223
|
// longest-match, so the form that consumes most is tried first, and the
|
|
@@ -187,6 +232,8 @@ const SHARED = {
|
|
|
187
232
|
p(EntityType.MAC_ADDRESS, String.raw `\b[0-9a-fA-F]{4}\.[0-9a-fA-F]{4}\.[0-9a-fA-F]{4}\b`, null, "Cisco"),
|
|
188
233
|
p(EntityType.IMEI, String.raw `\b\d{15}\b`, "imei"),
|
|
189
234
|
p(EntityType.IMEI, String.raw `\b\d{2}[\-\s]\d{6}[\-\s]\d{6}[\-\s]\d\b`, "imei", "formatted"),
|
|
235
|
+
// Behind "IMEI": 14 digits, the 16-digit IMEISV, or 15 with a failed check (rules-engine#110).
|
|
236
|
+
p(EntityType.IMEI, String.raw `\b\d{14,16}\b`, null, "IMEI / IMEISV — behind its label", ["IMEI"], true),
|
|
190
237
|
p(EntityType.GPS_COORDINATES, String.raw `-?(?:[1-8]?\d(?:\.\d{4,})|90(?:\.0{4,}))\s*[,;/]\s*-?(?:1[0-7]\d(?:\.\d{4,})|180(?:\.0{4,})|\d{1,2}(?:\.\d{4,}))`),
|
|
191
238
|
p(EntityType.UUID, String.raw `\b[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}\b`),
|
|
192
239
|
p(EntityType.SOCIAL_HANDLE, String.raw `(?<![\p{L}\p{N}_])@\p{L}[\p{L}\p{N}_.]{1,29}\b`),
|
|
@@ -220,7 +267,12 @@ const SHARED = {
|
|
|
220
267
|
// --- Secret / API Key (connection strings with embedded credentials) ---
|
|
221
268
|
p(EntityType.SECRET, String.raw `(?:mongodb|mysql|postgres(?:ql)?|redis|amqp|rabbitmq):\/\/[^\s:]{1,256}:[^\s@]{1,256}@[^\s]+`, null, "Connection string with credentials"),
|
|
222
269
|
// --- Secret / API Key (assignment-based: KEY=value or KEY: value) ---
|
|
223
|
-
|
|
270
|
+
// The final character may not be sentence punctuation. `\S` does not stop
|
|
271
|
+
// at a full stop, so "Reisepass: CA1234567." was claimed as the
|
|
272
|
+
// ten-character span "CA1234567." -- a passport number plus the sentence's
|
|
273
|
+
// period, masked as a credential because a "credentials" word sat within
|
|
274
|
+
// the context window (rules-engine#35).
|
|
275
|
+
p(EntityType.SECRET, String.raw `(?<=[:=] )\S{7,}[^\s.,;:!?)'"]|(?<=[:=])\S{7,}[^\s.,;:!?)'"]`, "high_entropy", "Assigned secret value", SECRET_CONTEXT, true),
|
|
224
276
|
// --- Secret / API Key (entropy-based fallback for longer tokens) ---
|
|
225
277
|
// Only the *trailing* \b is replaced. It could not match when the token run
|
|
226
278
|
// ended on "-", "+" or "/", so the engine backtracked across two
|
|
@@ -238,19 +290,24 @@ const SHARED = {
|
|
|
238
290
|
p(EntityType.SECRET, String.raw `\b[A-Za-z0-9_\-+/]{24,}[A-Za-z0-9_\-+/=]*(?![A-Za-z0-9_\-+/=])`, "high_entropy", "High-entropy token", SECRET_CONTEXT, true),
|
|
239
291
|
p(EntityType.DOB, String.raw `\b(?:0[1-9]|[12][0-9]|3[01])[/.\-](?:0[1-9]|1[0-2])[/.\-](?:19|20)\d{2}\b`, null, "DD/MM/YYYY", DOB_CONTEXT, true),
|
|
240
292
|
p(EntityType.DATE_OF_DEATH, String.raw `\b(?:0[1-9]|[12][0-9]|3[01])[/.\-](?:0[1-9]|1[0-2])[/.\-](?:19|20)\d{2}\b`, null, "", DATE_OF_DEATH_CONTEXT, true),
|
|
241
|
-
|
|
293
|
+
// Written-month dates, behind the same labels (rules-engine#115).
|
|
294
|
+
p(EntityType.DOB, writtenDatePattern(), null, "Date with a written month", DOB_CONTEXT, true),
|
|
295
|
+
p(EntityType.DATE_OF_DEATH, writtenDatePattern(), null, "Date of death with a written month", DATE_OF_DEATH_CONTEXT, true),
|
|
296
|
+
p(EntityType.DOB, String.raw `\b(?:19|20)\d{2}[/.\-](?:0[1-9]|1[0-2])[/.\-](?:0[1-9]|[12][0-9]|3[01])\b`, null, "ISO YYYY-MM-DD", DOB_CONTEXT, true),
|
|
242
297
|
],
|
|
243
298
|
};
|
|
244
299
|
const NL = {
|
|
245
300
|
code: "NL",
|
|
246
301
|
name: "Netherlands",
|
|
247
302
|
patterns: [
|
|
303
|
+
// Healthcare-provider numbers, behind their label: no shape of their own, so without a pattern nothing claimed them, or a phone or a foreign checksum did (canon HEALTHCARE_PROVIDER; rules-engine#111).
|
|
304
|
+
p(EntityType.HEALTHCARE_PROVIDER, String.raw `\b\d{8,11}\b`, null, "Dutch BIG-registratienummer — 8-11 digits", ["BIG-nummer", "BIG nummer", "BIG-registratie", "BIG registratie", "BIG-nr", "BIG nr", "BIG:"], true),
|
|
248
305
|
p(EntityType.NATIONAL_ID, String.raw `\b[0-9]{9}\b`, "bsn"),
|
|
249
306
|
p(EntityType.NATIONAL_ID, String.raw `\b[0-9]{2,4}\.[0-9]{2,4}\.[0-9]{2,4}\b`, "bsn"),
|
|
250
307
|
p(EntityType.IBAN, String.raw `\bNL\d{2}\s?[A-Z]{4}\s?\d{4}\s?\d{4}\s?\d{2}\b`, "iban"),
|
|
251
|
-
p(EntityType.VAT, String.raw `\bNL\d{9}B\d{2}\b`, "vat_nl"),
|
|
308
|
+
p(EntityType.VAT, String.raw `\bNL[\s.]?\d{9}B\d{2}\b`, "vat_nl"),
|
|
252
309
|
p(EntityType.CHAMBER_OF_COMMERCE, String.raw `\b\d{8}\b`, "kvk", "", ["KvK", "Kamer van Koophandel", "kvk-nummer", "KVK-nummer", "handelsregister", "chamber of commerce"], true),
|
|
253
|
-
p(EntityType.PHONE, String.raw `\b0[1-9]\d[\s\-]?\d{3}[\s\-]?\d{4}\b`),
|
|
310
|
+
p(EntityType.PHONE, String.raw `\b0[1-9]\d(?:\s-\s|[\s\-])?\d{3}[\s\-]?\d{4}\b`),
|
|
254
311
|
p(EntityType.PHONE, String.raw `\b0[1-9]\d{2}[\s\-]?\d{6,7}\b`),
|
|
255
312
|
p(EntityType.PHONE, String.raw `\b06[\s\-]?\d{4}[\s\-]?\d{4}\b`),
|
|
256
313
|
p(EntityType.PHONE, String.raw `\b06\d{8}\b`),
|
|
@@ -275,7 +332,7 @@ const BE = {
|
|
|
275
332
|
p(EntityType.PASSPORT, String.raw `\b[A-Z]{2}\d{6}\b`, null, "", PASSPORT_CONTEXT, true),
|
|
276
333
|
p(EntityType.DRIVERS_LICENSE, String.raw `\b\d{10}\b`, null, "", ["rijbewijs", "permis de conduire", "driving licence", "driving license", "rijbewijsnummer"], true),
|
|
277
334
|
p(EntityType.LICENSE_PLATE, String.raw `\b[12][\-\s]?[A-Z]{3}[\-\s]?\d{3}\b`),
|
|
278
|
-
p(EntityType.POSTAL_CODE, String.raw `\b[1-9]\d{3}\b`, null, "", ["postcode", "code postal", "postnummer", "postal code", "zip", "B-", "adres", "adresse", "wonende", "woonplaats", "rue", "straat", "laan", "avenue", "boulevard", "plein", "steenweg", "chaussée", "domicilié", "gedomicilieerd", "Levering:", "siège"], true),
|
|
335
|
+
p(EntityType.POSTAL_CODE, String.raw `\b[1-9]\d{3}\b`, null, "", ["postcode", "code postal", "postnummer", "postal code", "zip", "B-", "adres", "adresse", "wonende", "woonplaats", "domicile", "rue", "straat", "laan", "avenue", "boulevard", "plein", "steenweg", "chaussée", "domicilié", "gedomicilieerd", "Levering:", "siège"], true),
|
|
279
336
|
p(EntityType.POSTAL_CODE, String.raw `(?<=, )[1-9]\d{3}(?= [A-Z])`),
|
|
280
337
|
p(EntityType.HEALTHCARE_PROVIDER, String.raw `\b\d{1}[\-.]?\d{5}[\-.]?\d{2}[\-.]?\d{3}\b`, null, "", ["RIZIV", "INAMI", "arts", "médecin", "zorgverlener", "prestataire", "dokter", "doctor"], true),
|
|
281
338
|
],
|
|
@@ -284,13 +341,17 @@ const DE = {
|
|
|
284
341
|
code: "DE",
|
|
285
342
|
name: "Germany",
|
|
286
343
|
patterns: [
|
|
344
|
+
// Healthcare-provider numbers, behind their label: no shape of their own, so without a pattern nothing claimed them, or a phone or a foreign checksum did (canon HEALTHCARE_PROVIDER; rules-engine#111).
|
|
345
|
+
p(EntityType.HEALTHCARE_PROVIDER, String.raw `\b\d{9}\b`, null, "German LANR — 9 digits", ["LANR", "Lebenslange Arztnummer", "Arztnummer"], true),
|
|
346
|
+
p(EntityType.HEALTHCARE_PROVIDER, String.raw `\b\d{9}\b`, null, "German BSNR — 9 digits", ["BSNR", "Betriebsstättennummer", "Betriebsstätten-Nr"], true),
|
|
287
347
|
p(EntityType.TAX_ID, String.raw `\b[1-9]\d{10}\b`, "german_tax_id"),
|
|
288
348
|
p(EntityType.TAX_ID, String.raw `\b[1-9]\d[\s.]?\d{3}[\s.]?\d{3}[\s.]?\d{3}\b`, "german_tax_id"),
|
|
289
349
|
p(EntityType.NATIONAL_ID, String.raw `\b[CFGHJKLMNPRTVWXYZ][0-9CFGHJKLMNPRTVWXYZ]{8}\d?\b`, null, "", ["Personalausweis", "Personalausweisnummer", "Ausweis", "Ausweisnummer", "Ausweis-Nr", "identity card", "Identitätskarte", "Perso", "PA-Nummer"], true),
|
|
290
350
|
p(EntityType.IBAN, String.raw `\bDE\d{2}\s?\d{4}\s?\d{4}\s?\d{4}\s?\d{4}\s?\d{2}\b`, "iban"),
|
|
291
351
|
p(EntityType.VAT, String.raw `\bDE\s?\d{9}\b`, "vat_de"),
|
|
292
|
-
|
|
293
|
-
p(EntityType.PHONE, String.raw
|
|
352
|
+
// Prefix may be set off by " / "; up to three trailing two-digit groups (rules-engine#51).
|
|
353
|
+
p(EntityType.PHONE, String.raw `\b0[1-9]\d{1,4}(?:\s?[/\-]\s?|\s)?\d{3,8}\b(?:[ \-]\d{2}\b(?![.,/:\-]\d)){0,3}`),
|
|
354
|
+
p(EntityType.PHONE, String.raw `\+49\s?\d{2,5}(?:\s?[/\-]\s?|\s)?\d{3,8}\b(?:[ \-]\d{2}\b(?![.,/:\-]\d)){0,3}`),
|
|
294
355
|
p(EntityType.PASSPORT, String.raw `\b[CFGHJK][0-9CFGHJKLMNPRTVWXYZ]{8}\d?\b`, null, "", PASSPORT_CONTEXT, true),
|
|
295
356
|
// The separator after the city code is mandatory. When it was optional, a
|
|
296
357
|
// contiguous letter run split across both groups and the hyphen was
|
|
@@ -300,7 +361,7 @@ const DE = {
|
|
|
300
361
|
// separates the city code: "B-AB 1234", "M-XY 99".
|
|
301
362
|
p(EntityType.LICENSE_PLATE, String.raw `\b[A-ZÄÖÜ]{1,3}[\s\-][A-Z]{1,2}[\s\-]?\d{1,4}[EH]?\b`),
|
|
302
363
|
p(EntityType.POSTAL_CODE, String.raw `\b\d{5}\b`, null, "", ["PLZ", "Postleitzahl", "postal code", "postcode", "Anschrift", "Adresse", "Wohnort", "Ort", "Stadt", "wohnt", "wohnhaft", "Straße", "Str.", "Weg", "Platz", "Allee", "Ring"], true),
|
|
303
|
-
p(EntityType.CHAMBER_OF_COMMERCE, String.raw `\bHR[AB]\s?\d{4,6}\b
|
|
364
|
+
p(EntityType.CHAMBER_OF_COMMERCE, String.raw `\bHR[AB]\s?\d{4,6}(?:\s[A-Z]\b)?`),
|
|
304
365
|
p(EntityType.SSN, String.raw `\b\d{2}[\s]?\d{6}[\s]?[A-Z][\s]?\d{3}\b`, null, "", ["Rentenversicherung", "RV-Nummer", "Sozialversicherung", "SV-Nummer", "Versicherungsnummer", "Rentenversicherungsnummer", "Sozialversicherungsnummer", "SVNR", "SV-Nr", "RVNR"], true),
|
|
305
366
|
p(EntityType.TAX_ID, String.raw `\b\d{2,3}/\d{3,4}/\d{4,5}\b`, null, "", ["Steuernummer", "St.-Nr", "StNr", "Finanzamt", "Steuer"], true),
|
|
306
367
|
p(EntityType.TAX_ID, String.raw `\b\d{13}\b`, null, "", ["Steuernummer", "St.-Nr", "StNr", "Finanzamt", "Steuer"], true),
|
|
@@ -311,15 +372,16 @@ const AT = {
|
|
|
311
372
|
code: "AT",
|
|
312
373
|
name: "Austria",
|
|
313
374
|
patterns: [
|
|
314
|
-
|
|
375
|
+
// SSN: Austria has no national ID; the SVNr is its separate social-insurance number (rules-engine#111).
|
|
376
|
+
p(EntityType.SSN, String.raw `\b\d{4}\s?\d{6}\b`, "austrian_svnr"),
|
|
315
377
|
p(EntityType.IBAN, String.raw `\bAT\d{2}\s?\d{4}\s?\d{4}\s?\d{4}\s?\d{4}\b`, "iban"),
|
|
316
|
-
p(EntityType.VAT, String.raw `\bATU\d{8}\b`),
|
|
378
|
+
p(EntityType.VAT, String.raw `\bATU[\s.]?\d{8}\b`),
|
|
317
379
|
p(EntityType.PHONE, String.raw `\b0\d{3,4}[\s\-]?\d{5,8}\b`),
|
|
318
380
|
// Short area codes (Vienna is "01") split across three groups:
|
|
319
381
|
// "01 53460 2215". The pattern above requires 3-4 digits after the trunk
|
|
320
382
|
// 0, so it never matched these. Both separators are mandatory here, which
|
|
321
383
|
// keeps "01 2025" (a date fragment) out.
|
|
322
|
-
p(EntityType.PHONE, String.raw `\b0\d{1,4}[\s\-/]\d{3,7}[\s\-/]\d{2,6}\b`, null, "Austrian national phone — short area code, grouped"),
|
|
384
|
+
p(EntityType.PHONE, String.raw `\b0\d{1,4}[\s\-/]\d{3,7}[\s\-/]\d{2,6}\b(?![.,/:]\d)`, null, "Austrian national phone — short area code, grouped"),
|
|
323
385
|
p(EntityType.PHONE, String.raw `\+43\s?\d{3,4}[\s\-]?\d{5,8}`),
|
|
324
386
|
p(EntityType.LICENSE_PLATE, String.raw `\b[A-ZÄÖÜ]{1,2}\s?\d{1,5}\s?[A-Z]{1,2}\b`, null, "", ["Kennzeichen", "Nummernschild", "Kfz-Kennzeichen"], true),
|
|
325
387
|
p(EntityType.POSTAL_CODE, String.raw `\b[1-9]\d{3}\b`, null, "", ["PLZ", "Postleitzahl", "Adresse", "Anschrift", "Straße", "Str.", "Gasse", "Weg", "Platz", "Postal:", "Wohnort"], true),
|
|
@@ -331,6 +393,8 @@ const CH = {
|
|
|
331
393
|
name: "Switzerland",
|
|
332
394
|
patterns: [
|
|
333
395
|
p(EntityType.NATIONAL_ID, String.raw `\b756\.\d{4}\.\d{4}\.\d{2}\b`, "swiss_ahv"),
|
|
396
|
+
// Dotted, check digit not required when the document names it nearby (rules-engine#82).
|
|
397
|
+
p(EntityType.NATIONAL_ID, String.raw `\b756\.\d{4}\.\d{4}\.\d{2}\b`, null, "Swiss AHV number — dotted, beside AVS/AHV", ["AVS", "AHV"], true),
|
|
334
398
|
p(EntityType.NATIONAL_ID, String.raw `\b756\d{10}\b`, "swiss_ahv"),
|
|
335
399
|
p(EntityType.CHAMBER_OF_COMMERCE, String.raw `\bCHE[\-\s]?\d{3}\.?\d{3}\.?\d{3}\b`),
|
|
336
400
|
p(EntityType.VAT, String.raw `\bCHE[\-\s]?\d{3}\.?\d{3}\.?\d{3}\s?(?:MWST|TVA|IVA)\b`),
|
|
@@ -339,13 +403,16 @@ const CH = {
|
|
|
339
403
|
p(EntityType.PHONE, String.raw `\+41\s?\d{2}\s?\d{3}\s?\d{2}\s?\d{2}`),
|
|
340
404
|
p(EntityType.LICENSE_PLATE, String.raw `\b[A-Z]{2}\s?\d{1,6}\b`, null, "", ["Kontrollschild", "Nummernschild", "plaque", "immatriculation", "Kennzeichen"], true),
|
|
341
405
|
p(EntityType.POSTAL_CODE, String.raw `\b[1-9]\d{3}\b`, null, "", ["PLZ", "Postleitzahl", "code postal", "NPA", "Adresse", "Anschrift", "adresse", "rue", "Straße", "Str.", "Gasse", "chemin", "Postal:", "Wohnort"], true),
|
|
342
|
-
p(EntityType.POSTAL_CODE, String.raw `(?<=, )[1-9]\d{3}(?= [A-Z])`),
|
|
406
|
+
p(EntityType.POSTAL_CODE, String.raw `(?:(?<=, )|(?<=, CH-)|(?<=^CH-)|(?<=\nCH-))[1-9]\d{3}(?= [A-Z])`), // also "…, CH-8004 Zürich" and a "CH-8004 Zürich" line (rules-engine#58)
|
|
343
407
|
],
|
|
344
408
|
};
|
|
345
409
|
const FR = {
|
|
346
410
|
code: "FR",
|
|
347
411
|
name: "France",
|
|
348
412
|
patterns: [
|
|
413
|
+
// Healthcare-provider numbers, behind their label: no shape of their own, so without a pattern nothing claimed them, or a phone or a foreign checksum did (canon HEALTHCARE_PROVIDER; rules-engine#111).
|
|
414
|
+
p(EntityType.HEALTHCARE_PROVIDER, String.raw `\b\d{11}\b`, null, "French RPPS — 11 digits", ["RPPS", "Répertoire Partagé des Professionnels"], true),
|
|
415
|
+
p(EntityType.HEALTHCARE_PROVIDER, String.raw `\b\d{9}\b`, null, "French ADELI — 9 digits", ["ADELI"], true),
|
|
349
416
|
p(EntityType.NATIONAL_ID, String.raw `\b[12]\s?\d{2}\s?(?:0[1-9]|1[0-2]|[2-9]\d)\s?\d{2}[0-9AB]?\s?\d{3}\s?\d{3}\s?\d{2}\b`, "french_nir"),
|
|
350
417
|
p(EntityType.NATIONAL_ID, String.raw `\b\d{12}\b`, null, "", ["carte d'identité", "CNI", "carte nationale", "identity card", "pièce d'identité"], true),
|
|
351
418
|
p(EntityType.IBAN, String.raw `\bFR\d{2}\s?\d{4}\s?\d{4}\s?\d{4}\s?\d{4}\s?\d{4}\s?\d{3}\b`, "iban"),
|
|
@@ -354,7 +421,7 @@ const FR = {
|
|
|
354
421
|
p(EntityType.PHONE, String.raw `\+33\s?[1-9][\s.\-]?\d{2}[\s.\-]?\d{2}[\s.\-]?\d{2}[\s.\-]?\d{2}`),
|
|
355
422
|
p(EntityType.PASSPORT, String.raw `\b\d{2}[A-Z]{2}\d{5}\b`, null, "", PASSPORT_CONTEXT, true),
|
|
356
423
|
p(EntityType.LICENSE_PLATE, String.raw `\b[A-Z]{2}[\-\s]?\d{3}[\-\s]?[A-Z]{2}\b`),
|
|
357
|
-
p(EntityType.POSTAL_CODE, String.raw `\b(?:0[1-9]|[1-8]\d|9[0-5]|97[1-6])\d{3}\b`, null, "", ["code postal", "CP", "postal code", "postcode", "adresse", "domicilié", "résidant", "rue", "avenue", "boulevard", "place", "chemin", "allée", "impasse", "ville"], true),
|
|
424
|
+
p(EntityType.POSTAL_CODE, String.raw `\b(?:0[1-9]|[1-8]\d|9[0-5]|97[1-6])\d{3}\b`, null, "", ["code postal", "CP", "postal code", "postcode", "adresse", "domicile", "domicilié", "résidant", "rue", "avenue", "boulevard", "place", "chemin", "allée", "impasse", "ville"], true),
|
|
358
425
|
p(EntityType.CHAMBER_OF_COMMERCE, String.raw `\b\d{3}\s?\d{3}\s?\d{3}\b`, null, "", ["SIREN", "siren", "RCS", "entreprise", "immatricul", "numéro d'entreprise", "registre du commerce"], true),
|
|
359
426
|
p(EntityType.CHAMBER_OF_COMMERCE, String.raw `\b\d{3}\s?\d{3}\s?\d{3}\s?\d{5}\b`, null, "", ["SIRET", "siret", "établissement", "immatricul"], true),
|
|
360
427
|
p(EntityType.TAX_ID, String.raw `\b\d{13}\b`, null, "", ["numéro fiscal", "SPI", "référence fiscale", "avis d'impôt", "impôt sur le revenu", "déclaration fiscale", "fiscal"], true),
|
|
@@ -387,9 +454,9 @@ const SE = {
|
|
|
387
454
|
p(EntityType.PHONE, String.raw `\b0\d{1,3}[\-\s]?\d{2,3}[\s]?\d{2,3}[\s]?\d{2}\b`),
|
|
388
455
|
p(EntityType.PHONE, String.raw `\+46\s?\d{1,3}[\s\-]?\d{2,3}[\s\-]?\d{2,3}[\s\-]?\d{2}`),
|
|
389
456
|
p(EntityType.LICENSE_PLATE, String.raw `\b[A-Z]{3}\s?\d{2}[A-Z0-9]\b`),
|
|
390
|
-
p(EntityType.POSTAL_CODE, String.raw `\b\d{3}\s?\d{2}\b`, null, "", ["postnummer", "postort", "postkod", "adress", "bostadsadress", "gatuadress", "boende", "gatan", "vägen", "gata", "väg", "allé", "plats", "torg", "stigen", "Bostadsadress"], true),
|
|
391
|
-
p(EntityType.POSTAL_CODE, String.raw `\b\d{4}\s\d{2}\b`, null, "", ["postnummer", "postort", "postkod", "adress", "bostadsadress", "gatuadress", "boende", "gatan", "vägen", "gata", "väg", "allé"], true),
|
|
392
|
-
p(EntityType.POSTAL_CODE, String.raw `\b\d{6}\b`, null, "", ["postnummer", "postort", "postkod", "adress", "bostadsadress", "gatuadress", "boende", "gatan", "vägen", "gata", "väg", "allé"], true),
|
|
457
|
+
p(EntityType.POSTAL_CODE, String.raw `\b\d{3}\s?\d{2}\b`, null, "", ["postnummer", "postort", "postkod", "adress", "Postal:", "Address:", "bostadsadress", "gatuadress", "boende", "gatan", "vägen", "gata", "väg", "allé", "plats", "torg", "stigen", "Bostadsadress"], true),
|
|
458
|
+
p(EntityType.POSTAL_CODE, String.raw `\b\d{4}\s\d{2}\b`, null, "", ["postnummer", "postort", "postkod", "adress", "Postal:", "Address:", "bostadsadress", "gatuadress", "boende", "gatan", "vägen", "gata", "väg", "allé"], true),
|
|
459
|
+
p(EntityType.POSTAL_CODE, String.raw `\b\d{6}\b`, null, "", ["postnummer", "postort", "postkod", "adress", "Postal:", "Address:", "bostadsadress", "gatuadress", "boende", "gatan", "vägen", "gata", "väg", "allé"], true),
|
|
393
460
|
p(EntityType.CHAMBER_OF_COMMERCE, String.raw `\b\d{6}-?\d{4}\b`, null, "", ["organisationsnummer", "org.nr", "org nr", "Bolagsverket", "registreringsnummer"], true),
|
|
394
461
|
],
|
|
395
462
|
};
|
|
@@ -405,7 +472,7 @@ const NO = {
|
|
|
405
472
|
p(EntityType.PHONE, String.raw `\b[2-9]\d\s?\d{2}\s?\d{2}\s?\d{2}\b`),
|
|
406
473
|
p(EntityType.PHONE, String.raw `\+47\s?\d{2}\s?\d{2}\s?\d{2}\s?\d{2}`),
|
|
407
474
|
p(EntityType.LICENSE_PLATE, String.raw `\b[A-Z]{2}\s?\d{5}\b`),
|
|
408
|
-
p(EntityType.POSTAL_CODE, String.raw `\b\d{4}\b`, null, "", ["postnummer", "poststed", "postnr", "adresse", "bostedsadresse", "gate", "vei", "veien", "gata", "plass", "stien", "allé"], true),
|
|
475
|
+
p(EntityType.POSTAL_CODE, String.raw `\b\d{4}\b`, null, "", ["postnummer", "poststed", "postnr", "adresse", "bostedsadresse", "gate", "vei", "veien", "gata", "plass", "stien", "allé", "Postal:", "Address:"], true),
|
|
409
476
|
],
|
|
410
477
|
};
|
|
411
478
|
const FI = {
|
|
@@ -414,7 +481,7 @@ const FI = {
|
|
|
414
481
|
patterns: [
|
|
415
482
|
p(EntityType.NATIONAL_ID, String.raw `\b\d{6}[-+ABCDEFYXWVU]\d{3}[0-9A-FHJK-NPR-Y]\b`, "finnish_hetu"),
|
|
416
483
|
p(EntityType.IBAN, String.raw `\bFI\d{2}\s?\d{4}\s?\d{4}\s?\d{4}\s?\d{2}\b`, "iban"),
|
|
417
|
-
p(EntityType.VAT, String.raw `\bFI\d{8}\b`),
|
|
484
|
+
p(EntityType.VAT, String.raw `\bFI[\s.]?\d{8}\b`),
|
|
418
485
|
p(EntityType.CHAMBER_OF_COMMERCE, String.raw `\b\d{7}-\d\b`, "finnish_business_id"),
|
|
419
486
|
p(EntityType.PHONE, String.raw `\b0\d{1,2}\s?\d{3,4}\s?\d{3,4}\b`),
|
|
420
487
|
p(EntityType.PHONE, String.raw `\+358\s?\d{1,3}[\s\-]?\d{3,4}[\s\-]?\d{3,4}`),
|
|
@@ -432,7 +499,7 @@ const IS = {
|
|
|
432
499
|
p(EntityType.PHONE, String.raw `\b[3-9]\d{6}\b`, null, "", ["sími", "símanúmer", "farsími", "gsm", "phone", "tel", "hringja", "hringdu", "ná í", "nás á", "nás", "SMS", "sent to"], true),
|
|
433
500
|
p(EntityType.PHONE, String.raw `\+354\s?\d{3}\s?\d{4}`),
|
|
434
501
|
p(EntityType.LICENSE_PLATE, String.raw `\b[A-Z]{2}\s?\d{3}\b`, null, "", ["skráningarnúmer", "bílnúmer", "ökutæki", "bifreið", "plata"], true),
|
|
435
|
-
p(EntityType.POSTAL_CODE, String.raw `\b[1-9]\d{2}\b`, null, "", ["póstnúmer", "póstfang", "staður", "heimilisfang"], true),
|
|
502
|
+
p(EntityType.POSTAL_CODE, String.raw `\b[1-9]\d{2}\b`, null, "", ["póstnúmer", "póstfang", "staður", "heimilisfang", "Postal:", "Address:"], true),
|
|
436
503
|
],
|
|
437
504
|
};
|
|
438
505
|
const IT = {
|
|
@@ -442,7 +509,7 @@ const IT = {
|
|
|
442
509
|
p(EntityType.NATIONAL_ID, String.raw `\b[A-Z]{6}\d{2}[ABCDEHLMPRST]\d{2}[A-Z]\d{3}[A-Z]\b`, "italian_cf"),
|
|
443
510
|
p(EntityType.IBAN, String.raw `\bIT\d{2}\s?[A-Z]\d{3}\s?\d{4}\s?\d{4}\s?\d{4}\s?\d{4}\s?\d{3}\b`, "iban"),
|
|
444
511
|
p(EntityType.IBAN, String.raw `\bIT\d{2}[A-Z]\d{22}\b`, "iban"),
|
|
445
|
-
p(EntityType.VAT, String.raw `\bIT\d{11}\b`),
|
|
512
|
+
p(EntityType.VAT, String.raw `\bIT[\s.]?\d{11}\b`),
|
|
446
513
|
p(EntityType.PHONE, String.raw `\b3\d{2}[\s\-]?\d{3}[\s\-]?\d{4}\b`),
|
|
447
514
|
p(EntityType.PHONE, String.raw `\b0\d{1,3}[\s\-]?\d{6,8}\b`),
|
|
448
515
|
p(EntityType.PHONE, String.raw `\b0\d{1,2}[\s\-]\d{3}[\s\-]\d{4}\b`),
|
|
@@ -458,7 +525,7 @@ const ES = {
|
|
|
458
525
|
p(EntityType.NATIONAL_ID, String.raw `\b\d{8}[A-Z]\b`, "spanish_dni"),
|
|
459
526
|
p(EntityType.NATIONAL_ID, String.raw `\b[XYZ]\d{7}[A-Z]\b`, "spanish_nie"),
|
|
460
527
|
p(EntityType.IBAN, String.raw `\bES\d{2}\s?\d{4}\s?\d{4}\s?\d{4}\s?\d{4}\s?\d{4}\b`, "iban"),
|
|
461
|
-
p(EntityType.VAT, String.raw `\bES[A-Z0-9]\d{7}[A-Z0-9]\b`),
|
|
528
|
+
p(EntityType.VAT, String.raw `\bES[\s.]?[A-Z0-9]\d{7}[A-Z0-9]\b`),
|
|
462
529
|
p(EntityType.PHONE, String.raw `\b[679]\d{2}[\s\-]?\d{3}[\s\-]?\d{3}\b`),
|
|
463
530
|
p(EntityType.PHONE, String.raw `\b[679]\d{8}\b`),
|
|
464
531
|
p(EntityType.PHONE, String.raw `\b[679]\d[\s\-]?\d{3}[\s\-]?\d{2}[\s\-]?\d{2}\b`),
|
|
@@ -481,7 +548,7 @@ const PT = {
|
|
|
481
548
|
p(EntityType.NATIONAL_ID, String.raw `\b[1-35-9]\d{8}\b`, "portuguese_nif"),
|
|
482
549
|
p(EntityType.NATIONAL_ID, String.raw `\b[1-35-9]\d{2}[\s.]\d{3}[\s.]\d{3}\b`, "portuguese_nif"),
|
|
483
550
|
p(EntityType.IBAN, String.raw `\bPT\d{2}\s?\d{4}\s?\d{4}\s?\d{4}\s?\d{4}\s?\d{5}\b`, "iban"),
|
|
484
|
-
p(EntityType.VAT, String.raw `\bPT\d{9}\b`),
|
|
551
|
+
p(EntityType.VAT, String.raw `\bPT[\s.]?\d{9}\b`),
|
|
485
552
|
p(EntityType.PHONE, String.raw `\b[29]\d{2}[\s\-]?\d{3}[\s\-]?\d{3}\b`),
|
|
486
553
|
p(EntityType.PHONE, String.raw `\b[29]\d{8}\b`),
|
|
487
554
|
p(EntityType.PHONE, String.raw `\+351\s?[29]\d{2}[\s\-]?\d{3}[\s\-]?\d{3}`),
|
|
@@ -493,7 +560,8 @@ const LU = {
|
|
|
493
560
|
code: "LU",
|
|
494
561
|
name: "Luxembourg",
|
|
495
562
|
patterns: [
|
|
496
|
-
|
|
563
|
+
// Grouped: one horizontal space is optional at each boundary of YYYY MM DD XXX XX (rules-engine#49).
|
|
564
|
+
p(EntityType.NATIONAL_ID, String.raw `\b(?:19|20)\d{2}[^\S\r\n]?(?:0[1-9]|1[0-2])[^\S\r\n]?(?:0[1-9]|[12]\d|3[01])[^\S\r\n]?\d{3}[^\S\r\n]?\d{2}\b`),
|
|
497
565
|
p(EntityType.NATIONAL_ID, String.raw `\b(?:19|20)\d{2}(?:0[1-9]|1[0-2])(?:0[1-9]|[12]\d|3[01])\d{5}\b`),
|
|
498
566
|
p(EntityType.IBAN, String.raw `\bLU\d{2}\s?[A-Z0-9]{4}\s?[A-Z0-9]{4}\s?[A-Z0-9]{4}\s?[A-Z0-9]{4}\b`, "iban"),
|
|
499
567
|
p(EntityType.VAT, String.raw `\bLU\s?\d{8}\b`, "vat_lu"),
|
|
@@ -510,14 +578,32 @@ const PL = {
|
|
|
510
578
|
code: "PL",
|
|
511
579
|
name: "Poland",
|
|
512
580
|
patterns: [
|
|
581
|
+
// Healthcare-provider numbers, behind their label: no shape of their own, so without a pattern nothing claimed them, or a phone or a foreign checksum did (canon HEALTHCARE_PROVIDER; rules-engine#111).
|
|
582
|
+
p(EntityType.HEALTHCARE_PROVIDER, String.raw `\b\d{7}\b`, null, "Polish PWZ — 7 digits", ["PWZ", "prawa wykonywania zawodu", "prawo wykonywania zawodu"], true),
|
|
513
583
|
p(EntityType.NATIONAL_ID, String.raw `\b\d{11}\b`, "polish_pesel"),
|
|
514
|
-
|
|
584
|
+
// NIP in the company (3-3-2-2) or the personal (3-2-2-3) grouping (rules-engine#94).
|
|
585
|
+
p(EntityType.TAX_ID, String.raw `\b(?:\d{3}-?\d{3}-?\d{2}-?\d{2}|\d{3}-\d{2}-\d{2}-\d{3})\b`, "polish_nip"),
|
|
515
586
|
p(EntityType.IBAN, String.raw `\bPL\d{2}\s?\d{4}\s?\d{4}\s?\d{4}\s?\d{4}\s?\d{4}\s?\d{4}\b`, "iban"),
|
|
516
587
|
p(EntityType.IBAN, String.raw `\bPL\d{26}\b`, "iban"),
|
|
517
|
-
|
|
588
|
+
// NRB, the domestic account number: the IBAN without "PL" (rules-engine#93).
|
|
589
|
+
p(EntityType.BANK_ACCOUNT, String.raw `\b\d{2}(?: ?\d{4}){6}\b`, "polish_nrb", "Polish NRB"),
|
|
590
|
+
p(EntityType.VAT, String.raw `\bPL[\s.]?\d{10}\b`),
|
|
518
591
|
p(EntityType.PHONE, String.raw `\b[5-8]\d{2}[\s\-]?\d{3}[\s\-]?\d{3}\b`),
|
|
519
592
|
p(EntityType.PHONE, String.raw `\b[5-8]\d{8}\b`),
|
|
520
593
|
p(EntityType.PHONE, String.raw `\+48\s?[5-8]\d{2}[\s\-]?\d{3}[\s\-]?\d{3}`),
|
|
594
|
+
// Identity card, REGON, driving licence: each behind its own label (rules-engine#75, #76, #77).
|
|
595
|
+
p(EntityType.NATIONAL_ID, String.raw `\b[A-Z]{3}\s?\d{6}\b`, "polish_id_card", "Polish identity card", ["dowód osobisty", "dowodu osobistego", "dowodem osobistym", "dowód", "dowodu", "nr dowodu", "identity card", "ID card"], true),
|
|
596
|
+
p(EntityType.CHAMBER_OF_COMMERCE, String.raw `\b\d{9}(?:\d{5})?\b`, "polish_regon", "Polish REGON", ["REGON"], true),
|
|
597
|
+
// KRS: ten digits with the leading zeros, so it begins "00", which no dialled number does (rules-engine#90).
|
|
598
|
+
p(EntityType.CHAMBER_OF_COMMERCE, String.raw `\b00\d{8}\b`, null, "Polish KRS", ["KRS"], true),
|
|
599
|
+
p(EntityType.DRIVERS_LICENSE, String.raw `\b\d{3,6}/\d{2}/\d{3,7}\b`, null, "Polish driving licence number — field 5", ["prawo jazdy", "prawa jazdy", "prawem jazdy", "driving licence", "driving license"], true),
|
|
600
|
+
p(EntityType.DRIVERS_LICENSE, String.raw `\b[A-Z]{2}\s?\d{6,7}\b`, null, "Polish driving licence document number", ["prawo jazdy", "prawa jazdy", "prawem jazdy", "driving licence", "driving license"], true),
|
|
601
|
+
// Military booklet: a 2- or 3-letter series + 7 digits, one identifier, also "seria MS nr 6620419" (rules-engine#102).
|
|
602
|
+
p(EntityType.INTERNAL_ID, String.raw `\b[A-Z]{2,3}(?:\s?|\s+nr\.?\s+)\d{7}\b`, null, "Polish military booklet", ["książeczka wojskowa", "książeczki wojskowej", "książeczkę wojskową", "książeczką wojskową", "książeczce wojskowej", "military booklet", "military record book"], true),
|
|
603
|
+
// Residence card and national-visa sticker: 2 letters + 7 digits (rules-engine#103).
|
|
604
|
+
p(EntityType.RESIDENCE_PERMIT, String.raw `\b[A-Z]{2}\s?\d{7}\b`, null, "Polish residence card or visa sticker", ["karta pobytu", "karty pobytu", "kartę pobytu", "kartą pobytu", "CUKR", "naklejka wizowa", "naklejki wizowej", "naklejkę wizową", "naklejką wizową", "residence card", "visa sticker"], true),
|
|
605
|
+
// Case reference (znak sprawy): prefix.class.number.year, one INTERNAL_ID (rules-engine#105).
|
|
606
|
+
p(EntityType.INTERNAL_ID, String.raw `\b[A-ZĄĆĘŁŃÓŚŹŻ]{2,}(?:-[A-Z0-9]{1,6})*(?:\.[A-Z0-9]{1,6})*\.\d{3,4}(?:\.\d{1,6})+\.(?:19|20)\d{2}\b`, null, "Polish case reference", ["znak sprawy", "znak pisma", "znak:", "sygnatura", "sygn.", "sprawa nr", "sprawy nr", "nr sprawy", "decyzj", "postanowieni", "pismo nr"], true),
|
|
521
607
|
p(EntityType.POSTAL_CODE, String.raw `\b\d{2}-\d{3}\b`, null, "", ["kod pocztowy", "adres", "ulica", "Postal:", "Address:"]),
|
|
522
608
|
],
|
|
523
609
|
};
|
|
@@ -525,10 +611,11 @@ const IE = {
|
|
|
525
611
|
code: "IE",
|
|
526
612
|
name: "Ireland",
|
|
527
613
|
patterns: [
|
|
528
|
-
|
|
614
|
+
// The PPSN is SSN, never NATIONAL_ID: Ireland has no national ID (canon SSN; rules-engine#111).
|
|
615
|
+
p(EntityType.SSN, String.raw `\b\d{7}[A-W][ABWTXZ]?\b`, "irish_pps"),
|
|
529
616
|
p(EntityType.IBAN, String.raw `\bIE\d{2}\s?[A-Z]{4}\s?\d{4}\s?\d{4}\s?\d{4}\s?\d{2}\b`, "iban"),
|
|
530
617
|
p(EntityType.IBAN, String.raw `\bIE\d{2}[A-Z]{4}\d{14}\b`, "iban"),
|
|
531
|
-
p(EntityType.VAT, String.raw `\bIE\d{7}[A-Z]\b`),
|
|
618
|
+
p(EntityType.VAT, String.raw `\bIE[\s.]?\d{7}[A-Z]\b`),
|
|
532
619
|
p(EntityType.PHONE, String.raw `\b0[89]\d[\s\-]?\d{3}[\s\-]?\d{4}\b`),
|
|
533
620
|
p(EntityType.PHONE, String.raw `\b0[89]\d{8}\b`),
|
|
534
621
|
p(EntityType.PHONE, String.raw `\b0[1-9]\d{0,2}[\s\-]?\d{5,8}\b`),
|
|
@@ -540,11 +627,14 @@ const UK = {
|
|
|
540
627
|
code: "UK",
|
|
541
628
|
name: "United Kingdom",
|
|
542
629
|
patterns: [
|
|
543
|
-
|
|
630
|
+
// Healthcare-provider numbers, behind their label: no shape of their own, so without a pattern nothing claimed them, or a phone or a foreign checksum did (canon HEALTHCARE_PROVIDER; rules-engine#111).
|
|
631
|
+
p(EntityType.HEALTHCARE_PROVIDER, String.raw `\b\d{7}\b`, null, "UK GMC number — 7 digits", ["GMC number", "GMC no", "GMC reference", "GMC reg", "GMC:", "GMC-Nr", "General Medical Council"], true),
|
|
632
|
+
// UK NINO: a social-security number, so SSN, as the canon defaults it (rules-engine#47).
|
|
633
|
+
p(EntityType.SSN, String.raw `\b[A-CEGHJ-PR-TW-Z][A-CEGHJ-NPR-TW-Z]\s?\d{2}\s?\d{2}\s?\d{2}\s?[ABCD]\b`),
|
|
544
634
|
p(EntityType.HEALTH_INSURANCE, String.raw `\b\d{3}\s?\d{3}\s?\d{4}\b`, "uk_nhs", "", ["NHS", "NHS number", "health number", "NHS no"], true),
|
|
545
635
|
p(EntityType.IBAN, String.raw `\bGB\d{2}\s?[A-Z]{4}\s?\d{4}\s?\d{4}\s?\d{4}\s?\d{2}\b`, "iban"),
|
|
546
636
|
p(EntityType.IBAN, String.raw `\bGB\d{2}[A-Z]{4}\d{14}\b`, "iban"),
|
|
547
|
-
p(EntityType.VAT, String.raw `\bGB\d{
|
|
637
|
+
p(EntityType.VAT, String.raw `\bGB[\s.]?\d{3}[\s.]?\d{4}[\s.]?\d{2}\b`),
|
|
548
638
|
p(EntityType.PHONE, String.raw `\b07[4-9]\d{2}[\s\-]?\d{3}[\s\-]?\d{3}\b`),
|
|
549
639
|
p(EntityType.PHONE, String.raw `\b07[4-9]\d{8}\b`),
|
|
550
640
|
p(EntityType.PHONE, String.raw `\b0[12]\d{2}[\s\-]?\d{3}[\s\-]?\d{4}\b`),
|
|
@@ -560,7 +650,7 @@ const BG = {
|
|
|
560
650
|
patterns: [
|
|
561
651
|
p(EntityType.NATIONAL_ID, String.raw `\b\d{10}\b`, "bulgarian_egn"),
|
|
562
652
|
p(EntityType.IBAN, String.raw `\bBG\d{2}\s?[A-Z]{4}\s?\d{4}\s?\d{4}\s?\d{4}\s?\d{2}\b`, "iban"),
|
|
563
|
-
p(EntityType.VAT, String.raw `\bBG\d{9,10}\b`),
|
|
653
|
+
p(EntityType.VAT, String.raw `\bBG[\s.]?\d{9,10}\b`),
|
|
564
654
|
p(EntityType.PHONE, String.raw `\b0?[89][789][\s\-]?\d{3}[\s\-]?\d{3,4}\b`),
|
|
565
655
|
p(EntityType.PHONE, String.raw `\b0?[89][789]\d{7,8}\b`),
|
|
566
656
|
p(EntityType.PHONE, String.raw `\+359\s?[89][789][\s\-]?\d{3}[\s\-]?\d{3,4}`),
|
|
@@ -575,7 +665,7 @@ const CY = {
|
|
|
575
665
|
p(EntityType.NATIONAL_ID, String.raw `\b\d{8}[A-Z]\b`),
|
|
576
666
|
p(EntityType.IBAN, String.raw `\bCY\d{2}\s?\d{4}\s?\d{4}\s?\d{4}\s?\d{4}\s?\d{4}\s?\d{4}\b`, "iban"),
|
|
577
667
|
p(EntityType.IBAN, String.raw `\bCY\d{26}\b`, "iban"),
|
|
578
|
-
p(EntityType.VAT, String.raw `\bCY\d{8}[A-Z]\b`),
|
|
668
|
+
p(EntityType.VAT, String.raw `\bCY[\s.]?\d{8}[A-Z]\b`),
|
|
579
669
|
p(EntityType.PHONE, String.raw `\b[29]\d{3}[\s\-]?\d{4}\b`),
|
|
580
670
|
p(EntityType.PHONE, String.raw `\b[29]\d[\s\-]?\d{3}[\s\-]?\d{3}\b`),
|
|
581
671
|
p(EntityType.PHONE, String.raw `\b[29]\d{7}\b`),
|
|
@@ -591,7 +681,7 @@ const CZ = {
|
|
|
591
681
|
p(EntityType.NATIONAL_ID, String.raw `\b\d{6}/?\d{3,4}\b`, "czech_birth_number"),
|
|
592
682
|
p(EntityType.IBAN, String.raw `\bCZ\d{2}\s?\d{4}\s?\d{4}\s?\d{4}\s?\d{4}\s?\d{4}\b`, "iban"),
|
|
593
683
|
p(EntityType.IBAN, String.raw `\bCZ\d{22}\b`, "iban"),
|
|
594
|
-
p(EntityType.VAT, String.raw `\bCZ\d{8,10}\b`),
|
|
684
|
+
p(EntityType.VAT, String.raw `\bCZ[\s.]?\d{8,10}\b`),
|
|
595
685
|
p(EntityType.PHONE, String.raw `\b[67]\d{2}[\s\-]?\d{3}[\s\-]?\d{3}\b`),
|
|
596
686
|
p(EntityType.PHONE, String.raw `\b[67]\d{8}\b`),
|
|
597
687
|
p(EntityType.PHONE, String.raw `\+420\s?[67]\d{2}[\s\-]?\d{3}[\s\-]?\d{3}`),
|
|
@@ -605,7 +695,7 @@ const SK = {
|
|
|
605
695
|
p(EntityType.NATIONAL_ID, String.raw `\b\d{6}/?\d{3,4}\b`, "czech_birth_number"),
|
|
606
696
|
p(EntityType.IBAN, String.raw `\bSK\d{2}\s?\d{4}\s?\d{4}\s?\d{4}\s?\d{4}\s?\d{4}\b`, "iban"),
|
|
607
697
|
p(EntityType.IBAN, String.raw `\bSK\d{22}\b`, "iban"),
|
|
608
|
-
p(EntityType.VAT, String.raw `\bSK\d{10}\b`),
|
|
698
|
+
p(EntityType.VAT, String.raw `\bSK[\s.]?\d{10}\b`),
|
|
609
699
|
p(EntityType.PHONE, String.raw `\b0?9\d{2}[\s\-]?\d{3}[\s\-]?\d{3}\b`),
|
|
610
700
|
p(EntityType.PHONE, String.raw `\+421\s?9\d{2}[\s\-]?\d{3}[\s\-]?\d{3}`),
|
|
611
701
|
p(EntityType.POSTAL_CODE, String.raw `\b\d{3}\s?\d{2}\b`, null, "", ["PSČ", "poštové", "adresa", "ulica", "Postal:", "Address:"], true),
|
|
@@ -618,7 +708,7 @@ const EE = {
|
|
|
618
708
|
p(EntityType.NATIONAL_ID, String.raw `\b[1-6]\d{10}\b`, "estonian_id"),
|
|
619
709
|
p(EntityType.IBAN, String.raw `\bEE\d{2}\s?\d{4}\s?\d{4}\s?\d{4}\s?\d{4}\b`, "iban"),
|
|
620
710
|
p(EntityType.IBAN, String.raw `\bEE\d{18}\b`, "iban"),
|
|
621
|
-
p(EntityType.VAT, String.raw `\bEE\d{9}\b`),
|
|
711
|
+
p(EntityType.VAT, String.raw `\bEE[\s.]?\d{9}\b`),
|
|
622
712
|
p(EntityType.PHONE, String.raw `\b5\d{3}[\s\-]?\d{4}\b`),
|
|
623
713
|
p(EntityType.PHONE, String.raw `\b5\d{7}\b`),
|
|
624
714
|
p(EntityType.PHONE, String.raw `\+372\s?5\d{3}[\s\-]?\d{3,4}`),
|
|
@@ -632,7 +722,7 @@ const LT = {
|
|
|
632
722
|
p(EntityType.NATIONAL_ID, String.raw `\b[1-6]\d{10}\b`, "estonian_id"),
|
|
633
723
|
p(EntityType.IBAN, String.raw `\bLT\d{2}\s?\d{4}\s?\d{4}\s?\d{4}\s?\d{4}\b`, "iban"),
|
|
634
724
|
p(EntityType.IBAN, String.raw `\bLT\d{18}\b`, "iban"),
|
|
635
|
-
p(EntityType.VAT, String.raw `\bLT\d{9,12}\b`),
|
|
725
|
+
p(EntityType.VAT, String.raw `\bLT[\s.]?\d{9,12}\b`),
|
|
636
726
|
p(EntityType.PHONE, String.raw `\b6\d{2}[\s\-]?\d{2}[\s\-]?\d{3}\b`),
|
|
637
727
|
p(EntityType.PHONE, String.raw `\b6\d{7}\b`),
|
|
638
728
|
p(EntityType.PHONE, String.raw `\b8[\s\-]?6\d{2}[\s\-]?\d{2}[\s\-]?\d{3}\b`),
|
|
@@ -648,7 +738,7 @@ const LV = {
|
|
|
648
738
|
p(EntityType.NATIONAL_ID, String.raw `\b(?:0[1-9]|[12]\d|3[01])(?:0[1-9]|1[0-2])\d{7}\b`, null, "", ["personas kods", "PK", "identifikācijas"], true),
|
|
649
739
|
p(EntityType.IBAN, String.raw `\bLV\d{2}\s?[A-Z]{4}\s?\d{4}\s?\d{4}\s?\d{4}\s?\d\b`, "iban"),
|
|
650
740
|
p(EntityType.IBAN, String.raw `\bLV\d{2}[A-Z]{4}\d{13}\b`, "iban"),
|
|
651
|
-
p(EntityType.VAT, String.raw `\bLV\d{11}\b`),
|
|
741
|
+
p(EntityType.VAT, String.raw `\bLV[\s.]?\d{11}\b`),
|
|
652
742
|
p(EntityType.PHONE, String.raw `\b[2]\d{3}[\s\-]?\d{4}\b`),
|
|
653
743
|
p(EntityType.PHONE, String.raw `\b[2]\d{7}\b`),
|
|
654
744
|
p(EntityType.PHONE, String.raw `\+371\s?[2]\d{3}[\s\-]?\d{3,4}`),
|
|
@@ -663,7 +753,7 @@ const HR = {
|
|
|
663
753
|
p(EntityType.IBAN, String.raw `\bHR\d{2}\s?\d{4}\s?\d{4}\s?\d{4}\s?\d{4}\s?\d{3}\b`, "iban"),
|
|
664
754
|
p(EntityType.IBAN, String.raw `\bHR\d{2}\s\d{4}\s\d{4}\s\d{4}\s\d{5}\b`, "iban"),
|
|
665
755
|
p(EntityType.IBAN, String.raw `\bHR\d{19}\b`, "iban"),
|
|
666
|
-
p(EntityType.VAT, String.raw `\bHR\d{11}\b`),
|
|
756
|
+
p(EntityType.VAT, String.raw `\bHR[\s.]?\d{11}\b`),
|
|
667
757
|
p(EntityType.PHONE, String.raw `\b0?9[12579][\s\-]?\d{3}[\s\-]?\d{3,4}\b`),
|
|
668
758
|
p(EntityType.PHONE, String.raw `\b0?9[12579]\d{7,8}\b`),
|
|
669
759
|
p(EntityType.PHONE, String.raw `\+385\s?9[12579][\s\-]?\d{3}[\s\-]?\d{3,4}`),
|
|
@@ -677,7 +767,7 @@ const HU = {
|
|
|
677
767
|
p(EntityType.NATIONAL_ID, String.raw `\b\d{9}\b`, "hungarian_taj"),
|
|
678
768
|
p(EntityType.NATIONAL_ID, String.raw `\b\d{3}\s\d{3}\s\d{3}\b`, "hungarian_taj"),
|
|
679
769
|
p(EntityType.TAX_ID, String.raw `\b8\d{9}\b`, null, "", ["adóazonosító", "adószám", "adóazonosító jel"], true),
|
|
680
|
-
p(EntityType.VAT, String.raw `\bHU\d{8,11}\b`, null, "", ["adószám", "ÁFA"]),
|
|
770
|
+
p(EntityType.VAT, String.raw `\bHU[\s.]?\d{8,11}\b`, null, "", ["adószám", "ÁFA"]),
|
|
681
771
|
p(EntityType.IBAN, String.raw `\bHU\d{2}\s?\d{4}\s?\d{4}\s?\d{4}\s?\d{4}\s?\d{4}\s?\d{4}\b`, "iban"),
|
|
682
772
|
p(EntityType.IBAN, String.raw `\bHU\d{26}\b`, "iban"),
|
|
683
773
|
p(EntityType.PHONE, String.raw `\b06\s?\d{1,2}[\s\-]?\d{3}[\s\-]?\d{3,4}\b`),
|
|
@@ -692,7 +782,7 @@ const RO = {
|
|
|
692
782
|
patterns: [
|
|
693
783
|
p(EntityType.NATIONAL_ID, String.raw `\b[1-8]\d{12}\b`, "romanian_cnp"),
|
|
694
784
|
p(EntityType.IBAN, String.raw `\bRO\d{2}[A-Z]{4}\d{16}\b`, "iban"),
|
|
695
|
-
p(EntityType.VAT, String.raw `\bRO\d{2,10}\b`),
|
|
785
|
+
p(EntityType.VAT, String.raw `\bRO[\s.]?\d{2,10}\b`),
|
|
696
786
|
p(EntityType.PHONE, String.raw `\b0?7[2-9]\d{1}[\s\-]?\d{3}[\s\-]?\d{3,4}\b`),
|
|
697
787
|
p(EntityType.PHONE, String.raw `\b0?7[2-9]\d{7,8}\b`),
|
|
698
788
|
p(EntityType.PHONE, String.raw `\+40\s?7[2-9]\d{1}[\s\-]?\d{3}[\s\-]?\d{3,4}`),
|
|
@@ -707,7 +797,7 @@ const EL = {
|
|
|
707
797
|
p(EntityType.NATIONAL_ID, String.raw `\b\d{11}\b`, "greek_amka"),
|
|
708
798
|
p(EntityType.IBAN, String.raw `\bGR\d{2}\s?\d{4}\s?\d{4}\s?\d{4}\s?\d{4}\s?\d{4}\s?\d{3}\b`, "iban"),
|
|
709
799
|
p(EntityType.IBAN, String.raw `\bGR\d{25}\b`, "iban"),
|
|
710
|
-
p(EntityType.VAT, String.raw `\bEL\d{9}\b`),
|
|
800
|
+
p(EntityType.VAT, String.raw `\bEL[\s.]?\d{9}\b`),
|
|
711
801
|
p(EntityType.PHONE, String.raw `\b69\d[\s\-]?\d{3,4}[\s\-]?\d{4}\b`),
|
|
712
802
|
p(EntityType.PHONE, String.raw `\b69\d{8}\b`),
|
|
713
803
|
p(EntityType.PHONE, String.raw `\b2\d{1,3}[\s\-]?\d{3,4}[\s\-]?\d{3,4}\b`),
|
|
@@ -722,7 +812,7 @@ const SI = {
|
|
|
722
812
|
p(EntityType.NATIONAL_ID, String.raw `\b\d{13}\b`, "slovenian_emso"),
|
|
723
813
|
p(EntityType.IBAN, String.raw `\bSI\d{2}\s?\d{4}\s?\d{4}\s?\d{4}\s?\d{3}\b`, "iban"),
|
|
724
814
|
p(EntityType.IBAN, String.raw `\bSI\d{17}\b`, "iban"),
|
|
725
|
-
p(EntityType.VAT, String.raw `\bSI\d{8}\b`),
|
|
815
|
+
p(EntityType.VAT, String.raw `\bSI[\s.]?\d{8}\b`),
|
|
726
816
|
p(EntityType.PHONE, String.raw `\b0?[34567]\d{1}[\s\-]?\d{3}[\s\-]?\d{3}\b`),
|
|
727
817
|
p(EntityType.PHONE, String.raw `\b0?[34567]\d{7}\b`),
|
|
728
818
|
p(EntityType.PHONE, String.raw `\+386\s?[34567]\d{1}[\s\-]?\d{3}[\s\-]?\d{3}`),
|
|
@@ -737,7 +827,7 @@ const MT = {
|
|
|
737
827
|
p(EntityType.NATIONAL_ID, String.raw `\b\d{5,7}[MGAPLHBZ]\b`),
|
|
738
828
|
p(EntityType.IBAN, String.raw `\bMT\d{2}\s?[A-Z]{4}\s?\d{4}\s?\d{4}\s?[A-Z0-9]{4}\s?[A-Z0-9]{4}\s?[A-Z0-9]{4}\s?[A-Z0-9]{3}\b`, "iban"),
|
|
739
829
|
p(EntityType.IBAN, String.raw `\bMT\d{2}[A-Z]{4}\d{5}[A-Z0-9]{18}\b`, "iban"),
|
|
740
|
-
p(EntityType.VAT, String.raw `\bMT\d{8}\b`),
|
|
830
|
+
p(EntityType.VAT, String.raw `\bMT[\s.]?\d{8}\b`),
|
|
741
831
|
p(EntityType.PHONE, String.raw `\b[79]\d{3}[\s\-]?\d{4}\b`),
|
|
742
832
|
p(EntityType.PHONE, String.raw `\b[79]\d{7}\b`),
|
|
743
833
|
p(EntityType.PHONE, String.raw `\+356\s?[79]\d{3}[\s\-]?\d{3,4}`),
|
package/dist/esm/rules/cues.d.ts
CHANGED
|
@@ -130,4 +130,4 @@ export declare const RESCUE_TARGETS: Set<string>;
|
|
|
130
130
|
* `countryScore` is the document's support for the country the winning pattern
|
|
131
131
|
* came from; see RETYPABLE_UNCORROBORATED.
|
|
132
132
|
*/
|
|
133
|
-
export declare function retypedBy(text: string, start: number, entityType: EntityType | string, countryScore: number): EntityType | null;
|
|
133
|
+
export declare function retypedBy(text: string, start: number, entityType: EntityType | string, countryScore: number, country?: string | null): EntityType | null;
|
package/dist/esm/rules/cues.js
CHANGED
|
@@ -90,7 +90,7 @@ export const CUES = [
|
|
|
90
90
|
/(?<![A-Za-z0-9_])(?:phone|tel|telephone|téléphone|telefoon|telefon|telefono|teléfono|tlf|mobil|mobile|gsm|handy|sími|puh|móvil|cell|tālrunis|τηλέφωνο|τηλ)(?:(?:[A-Za-z0-9_]|[^\x00-\x7F])*|\s+[^\s:.\-\d,;()\/]{2,20})\s*\)?\s*[:.\-]*\s*$/i],
|
|
91
91
|
// National identity number.
|
|
92
92
|
[EntityType.NATIONAL_ID,
|
|
93
|
-
/(?<![A-Za-z0-9_])(?:bsn|burgerservicenummer(?:\s*\(bsn\))?|personnummer|rijksregisternummer|nationaal\s*nummer|numéro\s*national|national\s*(?:id|number)|identiteitsnummer|henkilötunnus|kennitala|cpr(?:-?nummer)?|nif|nie|
|
|
93
|
+
/(?<![A-Za-z0-9_])(?:bsn(?!r)|burgerservicenummer(?:\s*\(bsn\))?|personnummer|rijksregisternummer|nationaal\s*nummer|numéro\s*national|national\s*(?:id|number)|identiteitsnummer|henkilötunnus|kennitala|cpr(?:-?nummer)?|nif|nie|dnie?(?![A-Za-z]|[^\x00-\x7F])|rr|nn|nir|insz|niss|nis|matricule|id\s*card(?:\s*(?:no|nr|number))?|ausweisnummer|personalausweis|osobní\s*číslo|ЕГН|EGN|dow[óo]d(?:u|em)?\s*osobist(?:y|ego|ym)|nr\s*dowodu|ahv(?:-?(?:nr|nummer))?|avs)(?:(?:[A-Za-z0-9_]|[^\x00-\x7F])*|\s+[^\s:.\-\d,;()\/]{2,20})\s*\)?\s*[:.\-]*\s*$/i],
|
|
94
94
|
// Cyprus: "ID number" in both official languages, plus the Greek abbreviation
|
|
95
95
|
// ΑΔΤ (Αστυνομική Ταυτότητα). Neither has a phone reading.
|
|
96
96
|
[EntityType.NATIONAL_ID,
|
|
@@ -111,16 +111,16 @@ export const CUES = [
|
|
|
111
111
|
/(?<![A-Za-z0-9_])(?:αφμ|α\.φ\.μ\.|steuerliche\s*identifikations-?nummer|steuer-?identifikations-?nummer|steuer-?id-?nr\.?|steuer-?id|steuernummer|st\.?-?nr|stnr|tin|finanzamt\s+ist|tax\s*(?:id|no|number)|daňové\s*číslo|numer\s*podatkowy)(?:(?:[A-Za-z0-9_]|[^\x00-\x7F])*|\s+[^\s:.\-\d,;()\/]{2,20})\s*\)?\s*[:.\-]*\s*$/i],
|
|
112
112
|
// Health insurance: the insured person.
|
|
113
113
|
[EntityType.HEALTH_INSURANCE,
|
|
114
|
-
/(?<![A-Za-z0-9_])(?:versichertennummer|krankenversicherung|kvnr|kv-?nr|mutualité|ziekenfonds|aansluitingsnummer|medical\s*card(?:\s*(?:no|number))?)(?:(?:[A-Za-z0-9_]|[^\x00-\x7F])*|\s+[^\s:.\-\d,;()\/]{2,20})\s*\)?\s*[:.\-]*\s*$/i],
|
|
114
|
+
/(?<![A-Za-z0-9_])(?:versichertennummer|krankenversicherung|kvnr|kv-?nr|mutualité|ziekenfonds|aansluitingsnummer|medical\s*card(?:\s*(?:no|number))?|nhs(?:\s*(?:no|number))?)(?:(?:[A-Za-z0-9_]|[^\x00-\x7F])*|\s+[^\s:.\-\d,;()\/]{2,20})\s*\)?\s*[:.\-]*\s*$/i],
|
|
115
115
|
// Healthcare provider: the clinician or practice, not the patient — the Dutch
|
|
116
116
|
// AGB-code, the German LANR, the UK GMC number.
|
|
117
117
|
[EntityType.HEALTHCARE_PROVIDER,
|
|
118
|
-
/(?<![A-Za-z0-9_])(?:agb-?code|lanr|bsnr|gmc(?:\s*(?:no|number|reg))?|big
|
|
118
|
+
/(?<![A-Za-z0-9_])(?:agb-?code|lanr|bsnr|gmc(?:\s*(?:no|number|reg))?|big(?:-?registratie)?-?(?:nummer|nr)|zorgverlener(?:snummer)?|lebenslange\s*arztnummer|betriebsst[äa]ttennummer|rpps|adeli|pwz)(?:(?:[A-Za-z0-9_]|[^\x00-\x7F])*|\s+[^\s:.\-\d,;()\/]{2,20})\s*\)?\s*[:.\-]*\s*$/i],
|
|
119
119
|
// Company / trade register. "Companies House" and "Company Registration
|
|
120
120
|
// Number" are written out: the tail allows a run-on *or* one qualifier word,
|
|
121
121
|
// never a second word, so a three-word label needs to be spelled.
|
|
122
122
|
[EntityType.CHAMBER_OF_COMMERCE,
|
|
123
|
-
/(?<![A-Za-z0-9_])(?:siren|siret|kbo|bce|kvk|ondernemingsnummer|ondernemingen\s+onder\s+nummer|kruispuntbank|numéro\s*d'entreprise|enterprise\s*number|handelsregister|companies\s*house(?:\s*(?:registration|reg|no|number))?|company\s*registration(?:\s*(?:number|no))?|company\s*(?:no|number|reg)|organisationsnummer|orgnr|i[čc]o|identifikační\s*číslo|ЕИК|eik|bulstat|cvr(?:-?nummer)?|virksomhedsnummer)(?:(?:[A-Za-z0-9_]|[^\x00-\x7F])*|\s+[^\s:.\-\d,;()\/]{2,20})\s*\)?\s*[:.\-]*\s*$/i],
|
|
123
|
+
/(?<![A-Za-z0-9_])(?:siren|siret|kbo|bce|kvk|ondernemingsnummer|ondernemingen\s+onder\s+nummer|kruispuntbank|numéro\s*d'entreprise|enterprise\s*number|handelsregister|companies\s*house(?:\s*(?:registration|reg|no|number))?|company\s*registration(?:\s*(?:number|no))?|company\s*(?:no|number|reg)|organisationsnummer|orgnr|i[čc]o|identifikační\s*číslo|ЕИК|eik|bulstat|cvr(?:-?nummer)?|virksomhedsnummer|regon|krs)(?:(?:[A-Za-z0-9_]|[^\x00-\x7F])*|\s+[^\s:.\-\d,;()\/]{2,20})\s*\)?\s*[:.\-]*\s*$/i],
|
|
124
124
|
// VAT.
|
|
125
125
|
[EntityType.VAT,
|
|
126
126
|
/(?<![A-Za-z0-9_])(?:vat|btw|tva|ust|iva|moms|alv|mwst|dič|vsk)(?:(?:[A-Za-z0-9_.\-]|[^\x00-\x7F])*|\s+[^\s:.\-\d,;()\/]{2,20})\s*\)?\s*[:.\-]*\s*$/i],
|
|
@@ -130,6 +130,15 @@ export const CUES = [
|
|
|
130
130
|
[EntityType.BANK_ACCOUNT,
|
|
131
131
|
/(?<![A-Za-z0-9_])(?:sort\s*code|account\s*(?:no|number)|rekeningnummer|kontonummer|numéro\s*de\s*compte|sort-?code)(?:(?:[A-Za-z0-9_]|[^\x00-\x7F])*|\s+[^\s:.\-\d,;()\/]{2,20})\s*\)?\s*[:.\-]*\s*$/i],
|
|
132
132
|
// Passport.
|
|
133
|
+
// Residence permit. No permit patterns exist, so a permit number was filed
|
|
134
|
+
// under whichever ID, passport or phone pattern fitted it (rules-engine#53).
|
|
135
|
+
// The tail admits the Belgian card category ("nr. B 565992336"), unmasked.
|
|
136
|
+
[EntityType.RESIDENCE_PERMIT,
|
|
137
|
+
/(?<![A-Za-z0-9_])(?:aufenthalts(?:titel|erlaubnis|karte|gestattung)|niederlassungs(?:erlaubnis|bewilligung)|verblijfs(?:vergunning|kaart|document|titel)|titre\s*de\s*s[ée]jour|carte\s*de\s*s[ée]jour|permis\s*de\s*s[ée]jour|carte\s*de\s*r[ée]sident|residence\s*(?:permit|card|document)|biometric\s*residence\s*permit|permesso\s*di\s*soggiorno|carta\s*di\s*soggiorno|kart(?:a|y|ę|ą)\s*pobytu(?:\s*cukr)?|naklejk(?:a|i|ę|ą)\s*wizow(?:a|ej|ą)|uppehållstillstånd|opholdstilladelse|oppholdstillatelse|oleskelulupa)(?:(?:[A-Za-z0-9_]|[^\x00-\x7F])*|\s+[^\s:.\-\d,;()\/]{2,20})\s*\)?\s*[:.\-]*\s*(?:[A-Z]\s+)?$/i],
|
|
138
|
+
// Driving licence: Polish labels; the document number has the passport
|
|
139
|
+
// shape, so without this cue it lost the span to the passport rule (rules-engine#77).
|
|
140
|
+
[EntityType.DRIVERS_LICENSE,
|
|
141
|
+
/(?<![A-Za-z0-9_])(?:(?:nr\s*dokumentu\s*)?(?:prawo|prawa|prawem)\s*jazdy|numer\s*blankietu\s*prawa\s*jazdy)(?:(?:[A-Za-z0-9_]|[^\x00-\x7F])*|\s+[^\s:.\-\d,;()\/]{2,20})\s*\)?\s*[:.\-]*\s*$/i],
|
|
133
142
|
[EntityType.PASSPORT,
|
|
134
143
|
/(?<![A-Za-z0-9_])(?:passport(?:\s*(?:no|number))?|paspoort(?:nummer)?|reisepass(?:nummer)?|passeport|passnummer)(?:(?:[A-Za-z0-9_]|[^\x00-\x7F])*|\s+[^\s:.\-\d,;()\/]{2,20})\s*\)?\s*[:.\-]*\s*$/i],
|
|
135
144
|
// BIC / SWIFT.
|
|
@@ -146,7 +155,7 @@ export const CUES = [
|
|
|
146
155
|
// only thing that identifies one, which is why the engine emits this type
|
|
147
156
|
// from here and nowhere else.
|
|
148
157
|
[EntityType.INTERNAL_ID,
|
|
149
|
-
/(?<![A-Za-z0-9_])(?:medarbejdernummer|ansattnummer|anställningsnummer|personalnummer|personeelsnummer|matricule\s*salarié|employee\s*(?:no|number|id)|badge(?:\s*(?:no|number))?|betriebsstätten(?:nr|nummer)|grundstücks(?:nr|nummer)|dossier-?(?:nr|nummer)|aktenzeichen|osobní\s*(?:číslo\s*)?zaměstnance)(?:(?:[A-Za-z0-9_]|[^\x00-\x7F])*|\s+[^\s:.\-\d,;()\/]{2,20})\s*\)?\s*[:.\-]*\s*$/i],
|
|
158
|
+
/(?<![A-Za-z0-9_])(?:medarbejdernummer|ansattnummer|anställningsnummer|personalnummer|personeelsnummer|matricule\s*salarié|employee\s*(?:no|number|id)|badge(?:\s*(?:no|number))?|betriebsstätten(?:nr|nummer)|grundstücks(?:nr|nummer)|dossier-?(?:nr|nummer)|aktenzeichen|schade(?:claim|nummer|dossier)|schadens?-?(?:nummer|nr)|num[ée]ro\s*de\s*sinistre|numero\s*(?:di\s*)?sinistro|n[úu]mero\s*de\s*siniestro|skade(?:nummer|sag)|claim\s*(?:no|number|id)|collar|osobní\s*(?:číslo\s*)?zaměstnance)(?:(?:[A-Za-z0-9_]|[^\x00-\x7F])*|\s+[^\s:.\-\d,;()\/]{2,20})\s*\)?\s*[:.\-]*\s*$/i],
|
|
150
159
|
// Credential. Typed SECRET because that is the type this SDK has; the
|
|
151
160
|
// training pipeline's report asks for CREDENTIAL, which does not exist here.
|
|
152
161
|
[EntityType.SECRET,
|
|
@@ -192,6 +201,13 @@ const RETYPABLE = new Set([
|
|
|
192
201
|
* "Betriebsstättennr. 260326822" both landed, each reported as Czech.
|
|
193
202
|
*/
|
|
194
203
|
const RETYPABLE_UNCORROBORATED = new Set([EntityType.NATIONAL_ID]);
|
|
204
|
+
/**
|
|
205
|
+
* Retypable to RESIDENCE_PERMIT by a permit label touching the span, whatever
|
|
206
|
+
* the country support: a German eAT number fits the identity-card pattern and a
|
|
207
|
+
* Dutch permit number the passport pattern (rules-engine#53). Not a Spanish
|
|
208
|
+
* NIE, which the canon keeps NATIONAL_ID.
|
|
209
|
+
*/
|
|
210
|
+
const RETYPABLE_BY_PERMIT_LABEL = new Set([EntityType.NATIONAL_ID, EntityType.PASSPORT]);
|
|
195
211
|
/**
|
|
196
212
|
* Types a label can assert on its own.
|
|
197
213
|
*
|
|
@@ -205,7 +221,7 @@ export const CUE_TARGETS = new Set([
|
|
|
205
221
|
EntityType.HEALTH_INSURANCE, EntityType.HEALTHCARE_PROVIDER,
|
|
206
222
|
EntityType.CHAMBER_OF_COMMERCE, EntityType.VAT, EntityType.POSTAL_CODE,
|
|
207
223
|
EntityType.PASSPORT, EntityType.INTERNAL_ID, EntityType.BANK_ACCOUNT,
|
|
208
|
-
EntityType.SECRET,
|
|
224
|
+
EntityType.SECRET, EntityType.RESIDENCE_PERMIT,
|
|
209
225
|
]);
|
|
210
226
|
/**
|
|
211
227
|
* Which of those a label may also *rescue* — re-admit after its checksum
|
|
@@ -242,13 +258,17 @@ export const RESCUE_TARGETS = new Set([
|
|
|
242
258
|
* `countryScore` is the document's support for the country the winning pattern
|
|
243
259
|
* came from; see RETYPABLE_UNCORROBORATED.
|
|
244
260
|
*/
|
|
245
|
-
export function retypedBy(text, start, entityType, countryScore) {
|
|
261
|
+
export function retypedBy(text, start, entityType, countryScore, country = null) {
|
|
246
262
|
const type = String(entityType);
|
|
247
|
-
|
|
248
|
-
|
|
263
|
+
const general = RETYPABLE.has(type)
|
|
264
|
+
|| (RETYPABLE_UNCORROBORATED.has(type) && countryScore === 0);
|
|
265
|
+
const byPermit = RETYPABLE_BY_PERMIT_LABEL.has(type) && country !== "ES";
|
|
266
|
+
if (!general && !byPermit)
|
|
249
267
|
return null;
|
|
250
268
|
const cued = cuedType(text, start);
|
|
251
269
|
if (cued === null || cued === entityType || !CUE_TARGETS.has(String(cued)))
|
|
252
270
|
return null;
|
|
271
|
+
if (!general && cued !== EntityType.RESIDENCE_PERMIT)
|
|
272
|
+
return null;
|
|
253
273
|
return cued;
|
|
254
274
|
}
|