@stll/anonymize-wasm 1.4.10 → 1.5.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/dist/address-stopwords.mjs +2 -0
- package/dist/allow-list.mjs +1 -0
- package/dist/constants.mjs +1 -0
- package/dist/constants.mjs.map +1 -1
- package/dist/constants2.d.mts +1 -1
- package/dist/names-nw-ar.mjs +202 -0
- package/dist/names-nw-ar.mjs.map +1 -0
- package/dist/names-nw-fil.mjs +202 -0
- package/dist/names-nw-fil.mjs.map +1 -0
- package/dist/names-nw-id.mjs +210 -0
- package/dist/names-nw-id.mjs.map +1 -0
- package/dist/names-nw-in.mjs +526 -0
- package/dist/names-nw-in.mjs.map +1 -0
- package/dist/names-nw-ja-latn.mjs +260 -0
- package/dist/names-nw-ja-latn.mjs.map +1 -0
- package/dist/names-nw-ko.mjs +162 -0
- package/dist/names-nw-ko.mjs.map +1 -0
- package/dist/names-nw-th.mjs +188 -0
- package/dist/names-nw-th.mjs.map +1 -0
- package/dist/names-nw-vi.mjs +151 -0
- package/dist/names-nw-vi.mjs.map +1 -0
- package/dist/names-nw-zh-latn.mjs +197 -0
- package/dist/names-nw-zh-latn.mjs.map +1 -0
- package/dist/wasm.d.mts +43 -9
- package/dist/wasm.mjs +235 -36
- package/dist/wasm.mjs.map +1 -1
- package/package.json +2 -2
package/dist/wasm.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { DEFAULT_ENTITY_LABELS, DETECTION_SOURCES, DETECTOR_PRIORITY, OPERATOR_TYPES } from "./constants.mjs";
|
|
2
2
|
import { TextSearch } from "@stll/text-search-wasm";
|
|
3
|
-
import { at, au, be, bg, br, ch, cn, cy, cz, de, dk, ee, es, fi, fr, gb, gr, hr, hu, ie, it, lt, lu, lv, mt, nl, no, pl, pt, ro, se, si, sk, us } from "@stll/stdnum";
|
|
3
|
+
import { at, au, be, bg, br, ch, cn, crypto, cy, cz, de, dk, ee, es, fi, fr, gb, gr, hr, hu, ie, it, lt, lu, lv, mt, nl, no, pl, pt, ro, se, si, sk, us } from "@stll/stdnum";
|
|
4
4
|
import { toRegex } from "@stll/stdnum/patterns";
|
|
5
5
|
//#region \0rolldown/runtime.js
|
|
6
6
|
var __defProp = Object.defineProperty;
|
|
@@ -7959,6 +7959,15 @@ const processCountryMatches = (allMatches, sliceStart, sliceEnd, fullText, data)
|
|
|
7959
7959
|
return results;
|
|
7960
7960
|
};
|
|
7961
7961
|
//#endregion
|
|
7962
|
+
//#region src/util/entity-source.ts
|
|
7963
|
+
/**
|
|
7964
|
+
* True when the entity came from a caller-supplied detector — a
|
|
7965
|
+
* custom deny-list entry or a custom regex. These spans carry
|
|
7966
|
+
* caller-locked boundaries: the pipeline does not sanitise, trim,
|
|
7967
|
+
* or boundary-adjust them, since the caller chose the exact text.
|
|
7968
|
+
*/
|
|
7969
|
+
const isCallerOwnedEntity = (entity) => entity.sourceDetail === "custom-deny-list" || entity.sourceDetail === "custom-regex";
|
|
7970
|
+
//#endregion
|
|
7962
7971
|
//#region src/config/titles.ts
|
|
7963
7972
|
/**
|
|
7964
7973
|
* Academic and professional title prefixes.
|
|
@@ -8304,6 +8313,17 @@ const NONWESTERN_LOCALE_KEYS = [
|
|
|
8304
8313
|
"fil",
|
|
8305
8314
|
"id"
|
|
8306
8315
|
];
|
|
8316
|
+
const NONWESTERN_NAME_IMPORTS = {
|
|
8317
|
+
in: () => import("./names-nw-in.mjs"),
|
|
8318
|
+
ar: () => import("./names-nw-ar.mjs"),
|
|
8319
|
+
"ja-latn": () => import("./names-nw-ja-latn.mjs"),
|
|
8320
|
+
ko: () => import("./names-nw-ko.mjs"),
|
|
8321
|
+
"zh-latn": () => import("./names-nw-zh-latn.mjs"),
|
|
8322
|
+
th: () => import("./names-nw-th.mjs"),
|
|
8323
|
+
vi: () => import("./names-nw-vi.mjs"),
|
|
8324
|
+
fil: () => import("./names-nw-fil.mjs"),
|
|
8325
|
+
id: () => import("./names-nw-id.mjs")
|
|
8326
|
+
};
|
|
8307
8327
|
const normalizeCorpusLanguage = (language) => language.toLowerCase();
|
|
8308
8328
|
const getScopedNonWesternLocaleKeys = (languages) => {
|
|
8309
8329
|
if (languages === void 0) return NONWESTERN_LOCALE_KEYS;
|
|
@@ -8376,7 +8396,7 @@ const initNameCorpus = (ctx = defaultContext, dictionaries, languages) => {
|
|
|
8376
8396
|
for (const form of scopedNonWesternHonorifics) if (form.endsWith(".")) titleAbbrSet.add(form.replace(/[.-]+$/u, "").toLowerCase());
|
|
8377
8397
|
const exclusions = exclusionMod.default.words;
|
|
8378
8398
|
const nwLocaleKeys = getScopedNonWesternLocaleKeys(languages);
|
|
8379
|
-
const [nwNameMods, nwExcludedMod] = await Promise.all([Promise.all(nwLocaleKeys.map((locale) =>
|
|
8399
|
+
const [nwNameMods, nwExcludedMod] = await Promise.all([Promise.all(nwLocaleKeys.map((locale) => NONWESTERN_NAME_IMPORTS[locale]())), import("./names-nw-excluded-allcaps.mjs")]);
|
|
8380
8400
|
const nonWesternNames = [];
|
|
8381
8401
|
for (const mod of nwNameMods) for (const name of mod.default.names) nonWesternNames.push(name);
|
|
8382
8402
|
if (dictionaries?.nonWesternNames) {
|
|
@@ -8394,6 +8414,7 @@ const initNameCorpus = (ctx = defaultContext, dictionaries, languages) => {
|
|
|
8394
8414
|
titleTokens: Object.freeze(new Set(dedupTitles)),
|
|
8395
8415
|
titleAbbreviations: Object.freeze(titleAbbrSet),
|
|
8396
8416
|
excludedWords: Object.freeze(new Set(exclusions)),
|
|
8417
|
+
commonWords: Object.freeze(commonWords),
|
|
8397
8418
|
nonWesternNames: Object.freeze(new Set(dedupNonWestern)),
|
|
8398
8419
|
excludedAllCaps: Object.freeze(new Set(dedupExcludedAllCaps)),
|
|
8399
8420
|
firstNamesList: Object.freeze(dedupFirst),
|
|
@@ -9108,13 +9129,14 @@ const detectNameCorpus = (fullText, ctx = defaultContext, options = {}) => {
|
|
|
9108
9129
|
const corpusCount = chain.filter((t) => isCorpusMatch(t.type)).length;
|
|
9109
9130
|
const capitalizedCount = chain.filter((t) => t.type === TOKEN_TYPE.CAPITALIZED).length;
|
|
9110
9131
|
const nonWesternCount = chain.filter((t) => t.nonWestern).length;
|
|
9132
|
+
const chainAllCommonWords = chain.every((t) => corpus.commonWords.has(t.text.toLowerCase()));
|
|
9111
9133
|
let score;
|
|
9112
9134
|
if (hasNonWestern) {
|
|
9113
9135
|
if (hasTitle && (nonWesternCount > 0 || capitalizedCount > 0)) score = .95;
|
|
9114
9136
|
else if (hasJaSuffix && (capitalizedCount > 0 || nonWesternCount > 0)) score = .9;
|
|
9115
9137
|
else if (hasArabicConnector && nonWesternCount > 0) score = .9;
|
|
9116
9138
|
else if (nonWesternCount >= 2) score = .9;
|
|
9117
|
-
else if (nonWesternCount > 0 && (capitalizedCount > 0 || hasAbbreviation)) score = .9;
|
|
9139
|
+
else if (nonWesternCount > 0 && (capitalizedCount > 0 || hasAbbreviation) && !chainAllCommonWords) score = .9;
|
|
9118
9140
|
else if (nonWesternCount === 1 && chain.length === 1 && !isSentenceStart(fullText, token.start)) score = .5;
|
|
9119
9141
|
else continue;
|
|
9120
9142
|
if (supplementalMode && score < .9) continue;
|
|
@@ -9743,6 +9765,7 @@ var amount_words_default = {
|
|
|
9743
9765
|
//#region src/detectors/regex.ts
|
|
9744
9766
|
const MIN_PHONE_LENGTH = 7;
|
|
9745
9767
|
const MIN_MONTH_NAME_LENGTH = 3;
|
|
9768
|
+
const US_STATE_CODE = "(?:(?i:A[KLZR]|C[AOT]|D[CE]|FL|GA|HI|I[ADL]|K[SY]|LA|M[ADEHINOPST]|N[CDEHJMVY]|O[HK]|PA|RI|S[CD]|T[NX]|UT|V[AIT]|W[AIVY])|I[Nn]|iN|O[Rr]|oR)";
|
|
9746
9769
|
const escapeTitle = (title) => title.replace(/[.*+?^${}()|[\]\\]/g, "\\$&").replace(/\s+/g, "\\s*");
|
|
9747
9770
|
/** Escape for use inside a regex alternation. */
|
|
9748
9771
|
const escapeRegex$2 = (s) => s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
@@ -9980,6 +10003,58 @@ const ES_CIF = {
|
|
|
9980
10003
|
score: .95,
|
|
9981
10004
|
validator: es.cif
|
|
9982
10005
|
};
|
|
10006
|
+
const NHS_NUMBER_CONTEXT = {
|
|
10007
|
+
pattern: "\\b(?:(?i:NHS)(?:[^\\S\\n]+(?:(?i:number)|(?i:no\\.?)|#))?|(?i:National)[^\\S\\n]+(?i:Health)[^\\S\\n]+(?i:Service)[^\\S\\n]+(?:(?i:number)|(?i:no\\.?)|#))[^\\S\\n]{0,4}:?[^\\S\\n]{0,4}\\d{3}[^\\S\\n]?\\d{3}[^\\S\\n]?\\d{4}\\b",
|
|
10008
|
+
label: "national identification number",
|
|
10009
|
+
score: .95,
|
|
10010
|
+
validator: gb.nhs,
|
|
10011
|
+
validatorInput: (text) => text.replace(/\D/g, "")
|
|
10012
|
+
};
|
|
10013
|
+
const PASSPORT_CONTEXT = {
|
|
10014
|
+
pattern: "\\b(?:(?:(?i:U\\.?S\\.?)|(?i:USA)|(?i:United)[^\\S\\n]+(?i:States)|(?i:UK)|(?i:U\\.?K\\.?)|(?i:GBR)|(?i:British)|(?i:EU)|(?i:European)|(?i:France)|(?i:French))[^\\S\\n]{1,4})?(?i:passports?)(?:[^\\S\\n]+(?:(?i:number)|(?i:no\\.?)|#))?[^\\S\\n]{0,4}:?[^\\S\\n]{0,4}(?:[A-Za-z]{1,2}\\d{6,8}|\\d{2}[A-Za-z]{2}\\d{5}|\\d{7,9})\\b",
|
|
10015
|
+
label: "passport number",
|
|
10016
|
+
score: .96
|
|
10017
|
+
};
|
|
10018
|
+
const FR_CNI_CONTEXT = {
|
|
10019
|
+
pattern: "\\b(?:(?i:CNI)|(?i:carte)[^\\S\\n]+(?i:nationale)[^\\S\\n]+(?i:d)[’'](?i:identit[ée])|(?i:French)[^\\S\\n]+(?i:national)[^\\S\\n]+(?i:identity)[^\\S\\n]+(?i:card))(?:[^\\S\\n]+(?:(?i:number)|(?i:no\\.?)|(?i:n[°ºo]\\.?))[^\\S\\n]{0,4}:?[^\\S\\n]{0,4}[A-Za-z0-9]{9,12}|[^\\S\\n]{0,4}:?[^\\S\\n]{0,4}(?=[A-Za-z0-9]{0,11}\\d)[A-Za-z0-9]{9,12})\\b",
|
|
10020
|
+
label: "identity card number",
|
|
10021
|
+
score: .96
|
|
10022
|
+
};
|
|
10023
|
+
const CY_TIC_CONTEXT = {
|
|
10024
|
+
pattern: "\\b(?:(?:(?i:Cyprus)|(?i:Cypriot))[^\\S\\n]{1,4})?(?:(?i:TIC)|(?i:tax)[^\\S\\n]+(?i:identification)[^\\S\\n]+(?i:code))(?:[^\\S\\n]+(?:(?i:number)|(?i:no\\.?)|#))?[^\\S\\n]{0,4}:?[^\\S\\n]{0,4}\\d{8}[A-Za-z]\\b",
|
|
10025
|
+
label: "tax identification number",
|
|
10026
|
+
score: .96
|
|
10027
|
+
};
|
|
10028
|
+
const CY_ID_CARD_CONTEXT = {
|
|
10029
|
+
pattern: "\\b(?:(?i:Cyprus)|(?i:Cypriot))[^\\S\\n]+(?:(?i:identity)[^\\S\\n]+(?i:card)|(?i:ID)[^\\S\\n]+(?i:card))(?:[^\\S\\n]+(?:(?i:number)|(?i:no\\.?)|#))?[^\\S\\n]{0,4}:?[^\\S\\n]{0,4}\\d{6,8}\\b",
|
|
10030
|
+
label: "identity card number",
|
|
10031
|
+
score: .96
|
|
10032
|
+
};
|
|
10033
|
+
const UK_DRIVING_LICENCE_CONTEXT = {
|
|
10034
|
+
pattern: "\\b(?:(?:(?i:UK)|(?i:U\\.?K\\.?)|(?i:British))[^\\S\\n]{1,4})?(?i:driving)[^\\S\\n]+(?i:licen[cs]e)(?:[^\\S\\n]+(?:(?i:number)|(?i:no\\.?)|#))?[^\\S\\n]{0,4}:?[^\\S\\n]{0,4}[A-Za-z9]{5}\\d{6}[A-Za-z0-9]{2}\\d[A-Za-z]{2}\\b",
|
|
10035
|
+
label: "identity card number",
|
|
10036
|
+
score: .96
|
|
10037
|
+
};
|
|
10038
|
+
const US_DRIVER_LICENSE_CONTEXT = {
|
|
10039
|
+
pattern: `\\b(?:(?:(?i:U\\.?S\\.?)|(?i:USA)|(?i:United)[^\\S\\n]+(?i:States)|${US_STATE_CODE})[^\\S\\n]{1,4})?(?:(?i:driver['’]?s?)|(?i:driving))[^\\S\\n]+(?i:licen[cs]e)(?:[^\\S\\n]+(?:(?i:number)|(?i:no\\.?)|#)[^\\S\\n]{0,4}:?[^\\S\\n]{0,4}[A-Za-z0-9]{5,15}|[^\\S\\n]{0,4}:?[^\\S\\n]{0,4}(?=[A-Za-z0-9]{0,14}\\d)[A-Za-z0-9]{5,15})\\b`,
|
|
10040
|
+
label: "identity card number",
|
|
10041
|
+
score: .8
|
|
10042
|
+
};
|
|
10043
|
+
const MEDICAL_LICENSE_CONTEXT = {
|
|
10044
|
+
pattern: "\\b(?:(?:(?i:GMC)|(?i:NMC))(?:[^\\S\\n]+(?:(?i:licen[cs]e)|(?i:registration)|(?i:reg\\.?)|(?i:pin)|(?i:number)|(?i:no\\.?)))*|(?:(?i:medical)|(?i:physician)|(?i:doctor)|(?i:surgeon)|(?i:nursing)|(?i:nurse))(?:[^\\S\\n]+(?:(?i:licen[cs]e)|(?i:registration)|(?i:reg\\.?)|(?i:pin)|(?i:number)|(?i:no\\.?)))+)[^\\S\\n]{0,4}:?[^\\S\\n]{0,4}(?:[A-Za-z]{0,3}\\d{5,8}|\\d{2}[A-Za-z]\\d{4}[A-Za-z])\\b",
|
|
10045
|
+
label: "registration number",
|
|
10046
|
+
score: .85
|
|
10047
|
+
};
|
|
10048
|
+
const CRYPTO_WALLET_CANDIDATE = crypto.wallet.candidatePattern ?? "(?!)";
|
|
10049
|
+
const CRYPTO_WALLET_CANDIDATE_REGEX = new RegExp(CRYPTO_WALLET_CANDIDATE);
|
|
10050
|
+
const getCryptoWalletCandidate = (text) => CRYPTO_WALLET_CANDIDATE_REGEX.exec(text)?.[0] ?? text;
|
|
10051
|
+
const CRYPTO_WALLET_ADDRESS = {
|
|
10052
|
+
pattern: "\\b(?:0x[0-9A-Fa-f]{40}|bc1[ac-hj-np-z02-9]{11,71}|BC1[AC-HJ-NP-Z02-9]{11,71})\\b|\\b(?:(?i:BTC|Bitcoin|crypto|wallet|address)[^\\S\\n]{0,4}:?[^\\S\\n]{1,8}){1,4}[13][a-km-zA-HJ-NP-Z1-9]{25,34}\\b",
|
|
10053
|
+
label: "crypto",
|
|
10054
|
+
score: .85,
|
|
10055
|
+
validator: crypto.wallet,
|
|
10056
|
+
validatorInput: getCryptoWalletCandidate
|
|
10057
|
+
};
|
|
9983
10058
|
const AU_ABN_FORMATTED = {
|
|
9984
10059
|
pattern: `\\b\\d{2}[^\\S\\n]\\d{3}[^\\S\\n]\\d{3}[^\\S\\n]\\d{3}\\b`,
|
|
9985
10060
|
label: "tax identification number",
|
|
@@ -10126,6 +10201,15 @@ const ALL_REGEX_DEFS = [
|
|
|
10126
10201
|
ES_DNI,
|
|
10127
10202
|
ES_NIE,
|
|
10128
10203
|
ES_CIF,
|
|
10204
|
+
NHS_NUMBER_CONTEXT,
|
|
10205
|
+
PASSPORT_CONTEXT,
|
|
10206
|
+
FR_CNI_CONTEXT,
|
|
10207
|
+
CY_TIC_CONTEXT,
|
|
10208
|
+
CY_ID_CARD_CONTEXT,
|
|
10209
|
+
UK_DRIVING_LICENCE_CONTEXT,
|
|
10210
|
+
US_DRIVER_LICENSE_CONTEXT,
|
|
10211
|
+
MEDICAL_LICENSE_CONTEXT,
|
|
10212
|
+
CRYPTO_WALLET_ADDRESS,
|
|
10129
10213
|
AU_ABN_FORMATTED,
|
|
10130
10214
|
NO_ORGNR_FORMATTED,
|
|
10131
10215
|
NO_MVA_FORMATTED,
|
|
@@ -10157,6 +10241,7 @@ const REGEX_META = ALL_REGEX_DEFS.map((d) => {
|
|
|
10157
10241
|
score: d.score
|
|
10158
10242
|
};
|
|
10159
10243
|
if (d.validator) meta.validator = d.validator;
|
|
10244
|
+
if (d.validatorInput) meta.validatorInput = d.validatorInput;
|
|
10160
10245
|
return meta;
|
|
10161
10246
|
});
|
|
10162
10247
|
/**
|
|
@@ -10428,7 +10513,8 @@ const processRegexMatches = (allMatches, sliceStart, sliceEnd, meta_) => {
|
|
|
10428
10513
|
if (!meta) continue;
|
|
10429
10514
|
if (meta.sourceDetail !== "custom-regex" && meta.label === "phone number" && match.text.length < MIN_PHONE_LENGTH) continue;
|
|
10430
10515
|
if (meta.validator) {
|
|
10431
|
-
const
|
|
10516
|
+
const validatorText = meta.validatorInput ? meta.validatorInput(match.text) : match.text;
|
|
10517
|
+
const compacted = meta.validator.compact(validatorText);
|
|
10432
10518
|
if (!meta.validator.validate(compacted).valid) continue;
|
|
10433
10519
|
}
|
|
10434
10520
|
const entity = {
|
|
@@ -11884,7 +11970,40 @@ const trimTrailingAddressProse = (text) => {
|
|
|
11884
11970
|
}
|
|
11885
11971
|
return text;
|
|
11886
11972
|
};
|
|
11887
|
-
const
|
|
11973
|
+
const collapseEntityWhitespace = (text) => text.replace(/\s*\n\s*/g, " ").replace(/\s{2,}/g, " ");
|
|
11974
|
+
const normalizeEntityFromRaw = (entity, fullText) => {
|
|
11975
|
+
let start = entity.start;
|
|
11976
|
+
let end = entity.end;
|
|
11977
|
+
let text = fullText.slice(start, end);
|
|
11978
|
+
const trimLeading = (re) => {
|
|
11979
|
+
const match = re.exec(text);
|
|
11980
|
+
if (!match) return;
|
|
11981
|
+
start += match[0].length;
|
|
11982
|
+
text = text.slice(match[0].length);
|
|
11983
|
+
};
|
|
11984
|
+
trimLeading(LEADING_ARTIFACT_RE);
|
|
11985
|
+
trimLeading(/^\s+/u);
|
|
11986
|
+
if (entity.label === "address") {
|
|
11987
|
+
trimLeading(ADDRESS_ROLE_PREFIX_RE);
|
|
11988
|
+
const beforeTrim = text;
|
|
11989
|
+
text = trimTrailingAddressProse(text);
|
|
11990
|
+
end -= beforeTrim.length - text.length;
|
|
11991
|
+
}
|
|
11992
|
+
const trailingMatch = /[,\s]+$/u.exec(text);
|
|
11993
|
+
if (trailingMatch) {
|
|
11994
|
+
end -= trailingMatch[0].length;
|
|
11995
|
+
text = text.slice(0, text.length - trailingMatch[0].length);
|
|
11996
|
+
}
|
|
11997
|
+
if (text.length === 0) return null;
|
|
11998
|
+
return {
|
|
11999
|
+
...entity,
|
|
12000
|
+
start,
|
|
12001
|
+
end,
|
|
12002
|
+
text: collapseEntityWhitespace(text)
|
|
12003
|
+
};
|
|
12004
|
+
};
|
|
12005
|
+
const normalizeEntity = (entity, fullText) => {
|
|
12006
|
+
if (fullText !== void 0) return normalizeEntityFromRaw(entity, fullText);
|
|
11888
12007
|
let start = entity.start;
|
|
11889
12008
|
let text = entity.text;
|
|
11890
12009
|
const trimLeading = (re) => {
|
|
@@ -11902,10 +12021,13 @@ const normalizeEntity = (entity) => {
|
|
|
11902
12021
|
const trailingMatch = /[,\s]+$/u.exec(text);
|
|
11903
12022
|
if (trailingMatch) text = text.slice(0, text.length - trailingMatch[0].length);
|
|
11904
12023
|
if (text.length === 0) return null;
|
|
12024
|
+
const removedFromFront = start - entity.start;
|
|
12025
|
+
const removedFromBack = entity.text.length - removedFromFront - text.length;
|
|
12026
|
+
const end = entity.end - removedFromBack;
|
|
11905
12027
|
return {
|
|
11906
12028
|
...entity,
|
|
11907
12029
|
start,
|
|
11908
|
-
end
|
|
12030
|
+
end,
|
|
11909
12031
|
text
|
|
11910
12032
|
};
|
|
11911
12033
|
};
|
|
@@ -12010,7 +12132,6 @@ const initAddressComponents = () => {
|
|
|
12010
12132
|
* Czech house number form.
|
|
12011
12133
|
*/
|
|
12012
12134
|
const hasAddressComponent = (text) => _streetTypesRe.test(text) || ADDRESS_COMPONENT_EXTRA_RE.test(text);
|
|
12013
|
-
const isCallerOwnedEntity$3 = (entity) => entity.sourceDetail === "custom-deny-list" || entity.sourceDetail === "custom-regex";
|
|
12014
12135
|
/**
|
|
12015
12136
|
* Filter out entities that are likely false positives:
|
|
12016
12137
|
* template placeholders, clause/section numbers,
|
|
@@ -12023,14 +12144,14 @@ const filterFalsePositives = (entities, ctx = defaultContext, fullText) => {
|
|
|
12023
12144
|
const filtered = [];
|
|
12024
12145
|
const roles = getGenericRoles(ctx);
|
|
12025
12146
|
for (const entity of entities) {
|
|
12026
|
-
if (isCallerOwnedEntity
|
|
12147
|
+
if (isCallerOwnedEntity(entity)) {
|
|
12027
12148
|
filtered.push(entity);
|
|
12028
12149
|
continue;
|
|
12029
12150
|
}
|
|
12030
|
-
const normalized = normalizeEntity(entity);
|
|
12151
|
+
const normalized = normalizeEntity(entity, fullText);
|
|
12031
12152
|
if (!normalized) continue;
|
|
12032
12153
|
const trimmed = normalized.text;
|
|
12033
|
-
if (isCallerOwnedEntity
|
|
12154
|
+
if (isCallerOwnedEntity(normalized)) {
|
|
12034
12155
|
filtered.push(normalized);
|
|
12035
12156
|
continue;
|
|
12036
12157
|
}
|
|
@@ -12109,6 +12230,32 @@ const loadCommonWords = () => {
|
|
|
12109
12230
|
})();
|
|
12110
12231
|
return commonWordsPromise;
|
|
12111
12232
|
};
|
|
12233
|
+
let monthNamesPromise = null;
|
|
12234
|
+
let monthNamesCache = null;
|
|
12235
|
+
/**
|
|
12236
|
+
* English month names, lowercased. City gazetteers carry a
|
|
12237
|
+
* handful of entries that collide with month words (e.g. a
|
|
12238
|
+
* place named "August"); in prose these surface as address
|
|
12239
|
+
* false positives where the token is plainly a date, so they
|
|
12240
|
+
* are dropped from address patterns at build time.
|
|
12241
|
+
*/
|
|
12242
|
+
const loadMonthNames = () => {
|
|
12243
|
+
if (monthNamesCache) return Promise.resolve(monthNamesCache);
|
|
12244
|
+
if (monthNamesPromise) return monthNamesPromise;
|
|
12245
|
+
monthNamesPromise = (async () => {
|
|
12246
|
+
try {
|
|
12247
|
+
const mod = await import("./date-months.mjs");
|
|
12248
|
+
const set = new Set((mod.default?.en ?? []).map((month) => month.toLowerCase()));
|
|
12249
|
+
monthNamesCache = set;
|
|
12250
|
+
return set;
|
|
12251
|
+
} catch {
|
|
12252
|
+
const empty = /* @__PURE__ */ new Set();
|
|
12253
|
+
monthNamesCache = empty;
|
|
12254
|
+
return empty;
|
|
12255
|
+
}
|
|
12256
|
+
})();
|
|
12257
|
+
return monthNamesPromise;
|
|
12258
|
+
};
|
|
12112
12259
|
/**
|
|
12113
12260
|
* Curated dictionary entries that are pure dotted
|
|
12114
12261
|
* single-letter acronyms (e.g. `S.C.`, `D.N.J.`, `C.E.C.`)
|
|
@@ -12422,10 +12569,12 @@ const buildDenyList = async (config, ctx = defaultContext) => {
|
|
|
12422
12569
|
loadPersonStopwords(ctx),
|
|
12423
12570
|
loadAddressStopwords(ctx),
|
|
12424
12571
|
loadCommonWords(),
|
|
12572
|
+
loadMonthNames(),
|
|
12425
12573
|
loadStreetTypeRe(),
|
|
12426
12574
|
loadGenericRoles(ctx)
|
|
12427
12575
|
]);
|
|
12428
12576
|
const commonWords = await loadCommonWords();
|
|
12577
|
+
const monthNames = await loadMonthNames();
|
|
12429
12578
|
const dictionaries = config.dictionaries;
|
|
12430
12579
|
const hasDenyList = dictionaries?.denyList && dictionaries?.denyListMeta;
|
|
12431
12580
|
const hasCustomDenyList = config.customDenyList !== void 0 && config.customDenyList.length > 0;
|
|
@@ -12444,9 +12593,11 @@ const buildDenyList = async (config, ctx = defaultContext) => {
|
|
|
12444
12593
|
const normalized = source === "custom-deny-list" ? normalizeForSearch(entry) : stripCuratedPatternSyntax(normalizeForSearch(entry));
|
|
12445
12594
|
if (normalized.length === 0) return;
|
|
12446
12595
|
const lower = normalized.toLowerCase();
|
|
12447
|
-
if (source !== "custom-deny-list"
|
|
12448
|
-
if (
|
|
12449
|
-
|
|
12596
|
+
if (source !== "custom-deny-list") {
|
|
12597
|
+
if (label !== "address") {
|
|
12598
|
+
if (SINGLE_WORD_RE.test(normalized) && commonWords.has(lower)) return;
|
|
12599
|
+
if (isShortCuratedNoiseAcronym(normalized)) return;
|
|
12600
|
+
} else if (monthNames.has(lower)) return;
|
|
12450
12601
|
}
|
|
12451
12602
|
const existing = patternIndex.get(lower);
|
|
12452
12603
|
if (existing !== void 0) {
|
|
@@ -13325,7 +13476,6 @@ const TRAILING_SEP = /[,\s]+$/;
|
|
|
13325
13476
|
const WORD_CHAR_RE = /[\p{L}\p{N}]/u;
|
|
13326
13477
|
const ORG_PROPAGATION_SCORE = .9;
|
|
13327
13478
|
const ORG_DETERMINER_RE = /(?<![\p{L}\p{N}])(společnost(?:i|í|em|u)?|spolecnost(?:i|em|u)?|the\s+(?:company|corporation|firm)|die\s+(?:gesellschaft|firma)|la\s+(?:société|empresa|sociedad)|el\s+(?:empresa|sociedad))\s+$/iu;
|
|
13328
|
-
const isCallerOwnedEntity$2 = (entity) => entity.sourceDetail === "custom-deny-list" || entity.sourceDetail === "custom-regex";
|
|
13329
13479
|
/**
|
|
13330
13480
|
* After the main detection pass, collect organization
|
|
13331
13481
|
* entities with a legal form suffix, strip the suffix
|
|
@@ -13343,7 +13493,7 @@ const propagateOrgNames = (entities, fullText) => {
|
|
|
13343
13493
|
const seedByBase = /* @__PURE__ */ new Map();
|
|
13344
13494
|
for (const e of entities) {
|
|
13345
13495
|
if (e.label !== "organization") continue;
|
|
13346
|
-
if (isCallerOwnedEntity
|
|
13496
|
+
if (isCallerOwnedEntity(e)) continue;
|
|
13347
13497
|
for (const suffix of LEGAL_SUFFIXES) if (e.text.endsWith(suffix)) {
|
|
13348
13498
|
const base = e.text.slice(0, -suffix.length).replace(TRAILING_SEP, "").trim();
|
|
13349
13499
|
if (base.length >= 3) {
|
|
@@ -13713,7 +13863,6 @@ const NEAR_MISS_BAND = .15;
|
|
|
13713
13863
|
const BOOST_PER_NEIGHBOUR = .05;
|
|
13714
13864
|
const CONTEXT_WINDOW_CHARS = 150;
|
|
13715
13865
|
const HIGH_CONFIDENCE_FLOOR = .9;
|
|
13716
|
-
const isCallerOwnedEntity$1 = (entity) => entity.sourceDetail === "custom-deny-list" || entity.sourceDetail === "custom-regex";
|
|
13717
13866
|
/**
|
|
13718
13867
|
* Boost confidence of near-miss NER entities that appear
|
|
13719
13868
|
* near high-confidence detections (regex, trigger phrase).
|
|
@@ -13745,7 +13894,7 @@ const boostNearMissEntities = (entities, threshold) => {
|
|
|
13745
13894
|
const boostedScore = entity.score + neighbourCount * BOOST_PER_NEIGHBOUR;
|
|
13746
13895
|
if (boostedScore >= threshold) boosted.push({
|
|
13747
13896
|
...entity,
|
|
13748
|
-
score: boostedScore
|
|
13897
|
+
score: Math.min(1, boostedScore)
|
|
13749
13898
|
});
|
|
13750
13899
|
}
|
|
13751
13900
|
return boosted;
|
|
@@ -13824,7 +13973,7 @@ const getStreetAbbrevs = () => _streetAbbrevs ?? /* @__PURE__ */ new Set();
|
|
|
13824
13973
|
*/
|
|
13825
13974
|
const detectStreetPatternsNearAddresses = (fullText, existingEntities) => {
|
|
13826
13975
|
const results = [];
|
|
13827
|
-
const addressEntities = existingEntities.filter((entity) => !(entity.label === "address" && isCallerOwnedEntity
|
|
13976
|
+
const addressEntities = existingEntities.filter((entity) => !(entity.label === "address" && isCallerOwnedEntity(entity))).filter((e) => e.label === "address");
|
|
13828
13977
|
const headerEnd = Math.floor(fullText.length * HEADER_ZONE_FRACTION);
|
|
13829
13978
|
const houseNumRe = /\b(?:\d{1,4}\/\d+[a-zA-Z]\b|\d{3,4}\/\d+\b|(?:1[3-9]|[2-9]\d)\/\d{3,}\b)/g;
|
|
13830
13979
|
houseNumRe.lastIndex = 0;
|
|
@@ -13923,7 +14072,7 @@ const ORPHAN_STREET_RE = /^[^\S\n]*(\p{Lu}[\p{Ll}\p{Lu}]+(?:[^\S\n]+[\p{Lu}\p{Ll
|
|
|
13923
14072
|
*/
|
|
13924
14073
|
const detectOrphanStreetLines = (fullText, existingEntities) => {
|
|
13925
14074
|
const headerEnd = Math.floor(fullText.length * HEADER_ZONE_FRACTION);
|
|
13926
|
-
const contextEntities = existingEntities.filter((entity) => !(entity.label === "address" && isCallerOwnedEntity
|
|
14075
|
+
const contextEntities = existingEntities.filter((entity) => !(entity.label === "address" && isCallerOwnedEntity(entity)));
|
|
13927
14076
|
const results = [];
|
|
13928
14077
|
ORPHAN_STREET_RE.lastIndex = 0;
|
|
13929
14078
|
for (let m = ORPHAN_STREET_RE.exec(fullText); m !== null; m = ORPHAN_STREET_RE.exec(fullText)) {
|
|
@@ -14281,7 +14430,7 @@ const applyHotwordRules = (entities, fullText) => {
|
|
|
14281
14430
|
//#region src/filters/boundary-consistency.ts
|
|
14282
14431
|
/** Max gap (in chars) between entities to merge. */
|
|
14283
14432
|
const MAX_GAP = 3;
|
|
14284
|
-
const hasLockedBoundary$1 = (entity) => entity
|
|
14433
|
+
const hasLockedBoundary$1 = (entity) => isCallerOwnedEntity(entity);
|
|
14285
14434
|
const hasDetectorLockedBoundary = (entity) => entity.label === "phone number" && entity.source === DETECTION_SOURCES.TRIGGER;
|
|
14286
14435
|
/**
|
|
14287
14436
|
* Characters allowed in the gap between two adjacent
|
|
@@ -14864,7 +15013,6 @@ const unmaskNerEntities = (nerEntities, maskResult, fullText) => {
|
|
|
14864
15013
|
* so the containment rule trusts their length.
|
|
14865
15014
|
*/
|
|
14866
15015
|
const LITERAL_SOURCES = new Set(["deny-list", "gazetteer"]);
|
|
14867
|
-
const isCallerOwnedEntity = (entity) => entity.sourceDetail === "custom-deny-list" || entity.sourceDetail === "custom-regex";
|
|
14868
15016
|
const hasLockedBoundary = (entity) => isCallerOwnedEntity(entity);
|
|
14869
15017
|
const isCoveredByDenyListEntity = (entity, denyListEntity) => entity.label === denyListEntity.label && denyListEntity.start <= entity.start && denyListEntity.end >= entity.end;
|
|
14870
15018
|
const filterNameCorpusCoveredByDenyList = (nameCorpusEntities, denyListEntities) => nameCorpusEntities.filter((entity) => !denyListEntities.some((denyListEntity) => isCoveredByDenyListEntity(entity, denyListEntity)));
|
|
@@ -15088,7 +15236,7 @@ const sanitizeEntities = (entities) => entities.flatMap((e) => {
|
|
|
15088
15236
|
return [{
|
|
15089
15237
|
...e,
|
|
15090
15238
|
start: e.start + lead,
|
|
15091
|
-
end: e.start + lead +
|
|
15239
|
+
end: e.start + lead + cleaned.length,
|
|
15092
15240
|
text: collapsed
|
|
15093
15241
|
}];
|
|
15094
15242
|
});
|
|
@@ -15204,7 +15352,7 @@ const filterAllowedLabels = (entities, allowedLabels) => {
|
|
|
15204
15352
|
return entities.filter((e) => allowedLabels.has(e.label));
|
|
15205
15353
|
};
|
|
15206
15354
|
const labelIsAllowed = (label, allowedLabels) => !allowedLabels || allowedLabels.has(label);
|
|
15207
|
-
const NON_NER_LABELS = new Set(["misc"]);
|
|
15355
|
+
const NON_NER_LABELS = new Set(["crypto", "misc"]);
|
|
15208
15356
|
const getRequestedNerLabels = (config, expandForHotwords = false) => {
|
|
15209
15357
|
const labels = config.labels.length > 0 ? config.labels : DEFAULT_ENTITY_LABELS;
|
|
15210
15358
|
return (expandForHotwords ? expandLabelsForHotwordRules(labels) : labels).filter((label) => !NON_NER_LABELS.has(label));
|
|
@@ -15534,7 +15682,23 @@ const resolveOperator = (config, label) => config.operators[label] ?? "replace";
|
|
|
15534
15682
|
//#region src/redact.ts
|
|
15535
15683
|
const WHITESPACE_RE = /\s+/g;
|
|
15536
15684
|
const PHONE_NOISE_RE = /[()\s-]/g;
|
|
15685
|
+
const ETHEREUM_ADDRESS_RE = /0x[0-9A-Fa-f]{40}/;
|
|
15686
|
+
const BECH32_ADDRESS_RE = /\bbc1[ac-hj-np-z02-9]{11,71}\b/i;
|
|
15687
|
+
const BASE58_ADDRESS_RE = /\b[13][a-km-zA-HJ-NP-Z1-9]{25,34}\b/;
|
|
15688
|
+
const NHS_NUMBER_CUE_RE = /\b(?:NHS|National\s+Health\s+Service)\b/i;
|
|
15689
|
+
const PASSPORT_IDENTIFIER_RE = /\b(?:[A-Za-z]{1,2}\d{6,8}|\d{2}[A-Za-z]{2}\d{5}|\d{7,9})\b/;
|
|
15537
15690
|
const ID_SEPARATOR_RE = /[\s\-/.]/g;
|
|
15691
|
+
const normalizeCryptoText = (text) => {
|
|
15692
|
+
const trimmed = text.trim();
|
|
15693
|
+
const ethereumAddress = ETHEREUM_ADDRESS_RE.exec(trimmed)?.[0];
|
|
15694
|
+
if (ethereumAddress) return ethereumAddress.toLowerCase();
|
|
15695
|
+
const bech32Address = BECH32_ADDRESS_RE.exec(trimmed)?.[0];
|
|
15696
|
+
if (bech32Address) return bech32Address.toLowerCase();
|
|
15697
|
+
return BASE58_ADDRESS_RE.exec(trimmed)?.[0] ?? trimmed;
|
|
15698
|
+
};
|
|
15699
|
+
const normalizePassportText = (text) => {
|
|
15700
|
+
return (PASSPORT_IDENTIFIER_RE.exec(text)?.[0] ?? text).replace(ID_SEPARATOR_RE, "").toUpperCase();
|
|
15701
|
+
};
|
|
15538
15702
|
/**
|
|
15539
15703
|
* Normalize entity text so that surface-form variations
|
|
15540
15704
|
* of the same real-world value map to a single canonical
|
|
@@ -15544,7 +15708,10 @@ const normalizeEntityText = (label, text) => {
|
|
|
15544
15708
|
const upper = label.toUpperCase().replace(WHITESPACE_RE, "_");
|
|
15545
15709
|
if (upper === "EMAIL_ADDRESS" || upper === "EMAIL") return text.toLowerCase().trim();
|
|
15546
15710
|
if (upper === "PHONE_NUMBER" || upper === "PHONE") return text.replace(PHONE_NOISE_RE, "");
|
|
15547
|
-
if (upper === "
|
|
15711
|
+
if (upper === "CRYPTO") return normalizeCryptoText(text);
|
|
15712
|
+
if (upper === "NATIONAL_IDENTIFICATION_NUMBER" && NHS_NUMBER_CUE_RE.test(text)) return text.replace(/\D/g, "");
|
|
15713
|
+
if (upper === "IBAN" || upper === "BANK_ACCOUNT_NUMBER" || upper === "TAX_IDENTIFICATION_NUMBER" || upper === "REGISTRATION_NUMBER" || upper === "NATIONAL_IDENTIFICATION_NUMBER" || upper === "SOCIAL_SECURITY_NUMBER" || upper === "BIRTH_NUMBER" || upper === "IDENTITY_CARD_NUMBER" || upper === "CREDIT_CARD_NUMBER") return text.replace(ID_SEPARATOR_RE, "").toUpperCase();
|
|
15714
|
+
if (upper === "PASSPORT_NUMBER") return normalizePassportText(text);
|
|
15548
15715
|
if (upper === "PERSON" || upper === "ORGANIZATION" || upper === "ADDRESS" || upper === "LAND_PARCEL" || upper === "MISC") return text.replace(WHITESPACE_RE, " ").toLowerCase().trim();
|
|
15549
15716
|
return text.trim();
|
|
15550
15717
|
};
|
|
@@ -15677,7 +15844,7 @@ const hasOverlapping = (a, b, multiLabel) => {
|
|
|
15677
15844
|
const b0 = b[0] ?? 0;
|
|
15678
15845
|
const b1 = b[1] ?? 0;
|
|
15679
15846
|
if (a0 === b0 && a1 === b1) return !multiLabel;
|
|
15680
|
-
return
|
|
15847
|
+
return a0 < b1 && b0 < a1;
|
|
15681
15848
|
};
|
|
15682
15849
|
/**
|
|
15683
15850
|
* Greedy non-overlapping span selection.
|
|
@@ -15889,7 +16056,12 @@ const encodeInputs = (tokenizer, texts, promptLengths) => {
|
|
|
15889
16056
|
allWordsMasks
|
|
15890
16057
|
];
|
|
15891
16058
|
};
|
|
15892
|
-
/**
|
|
16059
|
+
/**
|
|
16060
|
+
* Build span index pairs and masks for the model.
|
|
16061
|
+
*
|
|
16062
|
+
* Exported for unit testing the span-mask invariant; not part
|
|
16063
|
+
* of the public package barrel.
|
|
16064
|
+
*/
|
|
15893
16065
|
const prepareSpans = (batchTokens, maxWidth) => {
|
|
15894
16066
|
const spanIdxs = [];
|
|
15895
16067
|
const spanMasks = [];
|
|
@@ -15900,7 +16072,7 @@ const prepareSpans = (batchTokens, maxWidth) => {
|
|
|
15900
16072
|
for (let i = 0; i < len; i++) for (let j = 0; j < maxWidth; j++) {
|
|
15901
16073
|
const endIdx = Math.min(i + j, len - 1);
|
|
15902
16074
|
idx.push([i, endIdx]);
|
|
15903
|
-
mask.push(
|
|
16075
|
+
mask.push(i + j < len);
|
|
15904
16076
|
}
|
|
15905
16077
|
spanIdxs.push(idx);
|
|
15906
16078
|
spanMasks.push(mask);
|
|
@@ -15966,13 +16138,20 @@ const MAX_CHUNK_CHARS = 1500;
|
|
|
15966
16138
|
const OVERLAP_CHARS = 50;
|
|
15967
16139
|
const MIN_CHUNK_LENGTH = 10;
|
|
15968
16140
|
/**
|
|
15969
|
-
* Split text into overlapping chunks
|
|
15970
|
-
*
|
|
15971
|
-
* (rough approximation of token limits).
|
|
16141
|
+
* Split text into overlapping chunks, each paired with its
|
|
16142
|
+
* exact start offset in the source text.
|
|
15972
16143
|
*
|
|
15973
|
-
*
|
|
16144
|
+
* Carrying the offset out of the splitter is the robust way to
|
|
16145
|
+
* map chunk-local entity offsets back to document offsets:
|
|
16146
|
+
* downstream code never has to re-locate a chunk by content
|
|
16147
|
+
* search (which mis-locates when boilerplate repeats; see
|
|
16148
|
+
* computeChunkOffsets).
|
|
16149
|
+
*
|
|
16150
|
+
* Character-based splitting (rough token approximation for
|
|
16151
|
+
* GLiNER's ~512 token window); breaks at sentence boundaries
|
|
16152
|
+
* when possible.
|
|
15974
16153
|
*/
|
|
15975
|
-
const
|
|
16154
|
+
const chunkTextWithOffsets = (text) => {
|
|
15976
16155
|
const chunks = [];
|
|
15977
16156
|
let offset = 0;
|
|
15978
16157
|
while (offset < text.length) {
|
|
@@ -15982,14 +16161,34 @@ const chunkText = (text) => {
|
|
|
15982
16161
|
if (lastPeriod > MAX_CHUNK_CHARS * .5) end = offset + lastPeriod + 2;
|
|
15983
16162
|
}
|
|
15984
16163
|
const chunk = text.slice(offset, end);
|
|
15985
|
-
if (chunk.trim().length > MIN_CHUNK_LENGTH) chunks.push(
|
|
16164
|
+
if (chunk.trim().length > MIN_CHUNK_LENGTH) chunks.push({
|
|
16165
|
+
text: chunk,
|
|
16166
|
+
offset
|
|
16167
|
+
});
|
|
16168
|
+
if (end === text.length) break;
|
|
15986
16169
|
offset = Math.max(offset + 1, end - OVERLAP_CHARS);
|
|
15987
16170
|
}
|
|
15988
16171
|
return chunks;
|
|
15989
16172
|
};
|
|
15990
16173
|
/**
|
|
15991
|
-
*
|
|
15992
|
-
*
|
|
16174
|
+
* Split text into overlapping chunks for GLiNER's ~512 token
|
|
16175
|
+
* context window. Character-based splitting (rough token
|
|
16176
|
+
* approximation); breaks at sentence boundaries when possible.
|
|
16177
|
+
*
|
|
16178
|
+
* Prefer chunkTextWithOffsets when you also need each chunk's
|
|
16179
|
+
* document offset.
|
|
16180
|
+
*/
|
|
16181
|
+
const chunkText = (text) => chunkTextWithOffsets(text).map((chunk) => chunk.text);
|
|
16182
|
+
/**
|
|
16183
|
+
* Compute the start offset of each chunk within the original
|
|
16184
|
+
* document text by content search.
|
|
16185
|
+
*
|
|
16186
|
+
* @deprecated Re-locates each chunk with `indexOf`, which can
|
|
16187
|
+
* match the wrong position when identical content repeats in
|
|
16188
|
+
* the document (common in boilerplate-heavy legal text) and
|
|
16189
|
+
* then desyncs every subsequent offset. Use
|
|
16190
|
+
* `chunkTextWithOffsets`, which carries exact offsets out of
|
|
16191
|
+
* the splitter.
|
|
15993
16192
|
*/
|
|
15994
16193
|
const computeChunkOffsets = (fullText, chunks) => {
|
|
15995
16194
|
const offsets = [];
|
|
@@ -16090,6 +16289,6 @@ const levenshtein = (rawA, rawB) => {
|
|
|
16090
16289
|
//#region src/wasm.ts
|
|
16091
16290
|
initTextSearch(TextSearch);
|
|
16092
16291
|
//#endregion
|
|
16093
|
-
export { CURRENCY_PATTERN_META, DATE_PATTERN_META, DEFAULT_ENTITY_LABELS, DEFAULT_OPERATOR_CONFIG, DETECTION_SOURCES, DETECTOR_PRIORITY, OPERATOR_REGISTRY, OPERATOR_TYPES, REGEX_META, REGEX_PATTERNS, REGIONS, ZONE_SCORE_ADJUSTMENTS, applyHotwordRules, applyZoneAdjustments, boostNearMissEntities, buildDenyList, buildGazetteerPatterns, buildLegalFormPatterns, buildPlaceholderMap, buildStreetTypePatterns, buildTriggerPatterns, buildUnifiedSearch, chunkText, classifyZones, computeChunkOffsets, corefKey, createPipelineContext, deanonymise, decodeSpans, decodeTokenSpans, detectNameCorpus, ensureDenyListData, exportRedactionKey, extractDefinedTerms, filterFalsePositives, findCoreferenceSpans, getCurrencyPatterns, getDatePatterns, getNameCorpusNonWesternNames, initAddressComponents, initHotwordRules, initNameCorpus, initZoneClassifier, levenshtein, mergeAndDedup, mergeChunkEntities, normalizeForSearch, prepareBatch, preparePipelineSearch, processAddressSeeds, processDenyListMatches, processGazetteerMatches, processLegalFormMatches, processRegexMatches, processTriggerMatches, propagateOrgNames, redactText, resolveCountries, resolveOperator, runPipeline, runUnifiedSearch, sanitizeEntities, tokenizeText, warmLegalRoleHeads };
|
|
16292
|
+
export { CURRENCY_PATTERN_META, DATE_PATTERN_META, DEFAULT_ENTITY_LABELS, DEFAULT_OPERATOR_CONFIG, DETECTION_SOURCES, DETECTOR_PRIORITY, OPERATOR_REGISTRY, OPERATOR_TYPES, REGEX_META, REGEX_PATTERNS, REGIONS, ZONE_SCORE_ADJUSTMENTS, applyHotwordRules, applyZoneAdjustments, boostNearMissEntities, buildDenyList, buildGazetteerPatterns, buildLegalFormPatterns, buildPlaceholderMap, buildStreetTypePatterns, buildTriggerPatterns, buildUnifiedSearch, chunkText, chunkTextWithOffsets, classifyZones, computeChunkOffsets, corefKey, createPipelineContext, deanonymise, decodeSpans, decodeTokenSpans, detectNameCorpus, ensureDenyListData, exportRedactionKey, extractDefinedTerms, filterFalsePositives, findCoreferenceSpans, getCurrencyPatterns, getDatePatterns, getNameCorpusNonWesternNames, initAddressComponents, initHotwordRules, initNameCorpus, initZoneClassifier, levenshtein, mergeAndDedup, mergeChunkEntities, normalizeForSearch, prepareBatch, preparePipelineSearch, processAddressSeeds, processDenyListMatches, processGazetteerMatches, processLegalFormMatches, processRegexMatches, processTriggerMatches, propagateOrgNames, redactText, resolveCountries, resolveOperator, runPipeline, runUnifiedSearch, sanitizeEntities, tokenizeText, warmLegalRoleHeads };
|
|
16094
16293
|
|
|
16095
16294
|
//# sourceMappingURL=wasm.mjs.map
|