@stll/anonymize-wasm 1.0.9 → 1.1.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/wasm.d.mts +75 -11
- package/dist/wasm.mjs +89 -136
- package/dist/wasm.mjs.map +1 -1
- package/package.json +1 -1
- package/dist/AT.mjs +0 -282
- package/dist/AT.mjs.map +0 -1
- package/dist/AT2.mjs +0 -343
- package/dist/AT2.mjs.map +0 -1
- package/dist/AU.mjs +0 -122
- package/dist/AU.mjs.map +0 -1
- package/dist/AU2.mjs +0 -90
- package/dist/AU2.mjs.map +0 -1
- package/dist/BE.mjs +0 -144
- package/dist/BE.mjs.map +0 -1
- package/dist/BE2.mjs +0 -107
- package/dist/BE2.mjs.map +0 -1
- package/dist/BG.mjs +0 -73
- package/dist/BG.mjs.map +0 -1
- package/dist/BG2.mjs +0 -42
- package/dist/BG2.mjs.map +0 -1
- package/dist/BR.mjs +0 -226
- package/dist/BR.mjs.map +0 -1
- package/dist/BR2.mjs +0 -339
- package/dist/BR2.mjs.map +0 -1
- package/dist/CA.mjs +0 -275
- package/dist/CA.mjs.map +0 -1
- package/dist/CA2.mjs +0 -222
- package/dist/CA2.mjs.map +0 -1
- package/dist/CZ.mjs +0 -212
- package/dist/CZ.mjs.map +0 -1
- package/dist/CZ2.mjs +0 -619
- package/dist/CZ2.mjs.map +0 -1
- package/dist/CZ3.mjs +0 -127
- package/dist/CZ3.mjs.map +0 -1
- package/dist/DE.mjs +0 -1652
- package/dist/DE.mjs.map +0 -1
- package/dist/DE2.mjs +0 -3885
- package/dist/DE2.mjs.map +0 -1
- package/dist/DE3.mjs +0 -669
- package/dist/DE3.mjs.map +0 -1
- package/dist/DK.mjs +0 -218
- package/dist/DK.mjs.map +0 -1
- package/dist/DK2.mjs +0 -162
- package/dist/DK2.mjs.map +0 -1
- package/dist/ES.mjs +0 -522
- package/dist/ES.mjs.map +0 -1
- package/dist/ES2.mjs +0 -352
- package/dist/ES2.mjs.map +0 -1
- package/dist/FI.mjs +0 -267
- package/dist/FI.mjs.map +0 -1
- package/dist/FI2.mjs +0 -107
- package/dist/FI2.mjs.map +0 -1
- package/dist/FR.mjs +0 -224
- package/dist/FR.mjs.map +0 -1
- package/dist/FR2.mjs +0 -1823
- package/dist/FR2.mjs.map +0 -1
- package/dist/GB.mjs +0 -298
- package/dist/GB.mjs.map +0 -1
- package/dist/GB2.mjs +0 -208
- package/dist/GB2.mjs.map +0 -1
- package/dist/HR.mjs +0 -37
- package/dist/HR.mjs.map +0 -1
- package/dist/HR2.mjs +0 -16
- package/dist/HR2.mjs.map +0 -1
- package/dist/HU.mjs +0 -59
- package/dist/HU.mjs.map +0 -1
- package/dist/HU2.mjs +0 -29
- package/dist/HU2.mjs.map +0 -1
- package/dist/IE.mjs +0 -35
- package/dist/IE.mjs.map +0 -1
- package/dist/IE2.mjs +0 -19
- package/dist/IE2.mjs.map +0 -1
- package/dist/IT.mjs +0 -341
- package/dist/IT.mjs.map +0 -1
- package/dist/IT2.mjs +0 -46
- package/dist/IT2.mjs.map +0 -1
- package/dist/NL.mjs +0 -298
- package/dist/NL.mjs.map +0 -1
- package/dist/NL2.mjs +0 -305
- package/dist/NL2.mjs.map +0 -1
- package/dist/NO.mjs +0 -178
- package/dist/NO.mjs.map +0 -1
- package/dist/NO2.mjs +0 -346
- package/dist/NO2.mjs.map +0 -1
- package/dist/PL.mjs +0 -175
- package/dist/PL.mjs.map +0 -1
- package/dist/PL2.mjs +0 -107
- package/dist/PL2.mjs.map +0 -1
- package/dist/PT.mjs +0 -78
- package/dist/PT.mjs.map +0 -1
- package/dist/PT2.mjs +0 -657
- package/dist/PT2.mjs.map +0 -1
- package/dist/RO.mjs +0 -181
- package/dist/RO.mjs.map +0 -1
- package/dist/RO2.mjs +0 -46
- package/dist/RO2.mjs.map +0 -1
- package/dist/SE.mjs +0 -270
- package/dist/SE.mjs.map +0 -1
- package/dist/SE2.mjs +0 -369
- package/dist/SE2.mjs.map +0 -1
- package/dist/SI.mjs +0 -27
- package/dist/SI.mjs.map +0 -1
- package/dist/SI2.mjs +0 -88
- package/dist/SI2.mjs.map +0 -1
- package/dist/SK.mjs +0 -61
- package/dist/SK.mjs.map +0 -1
- package/dist/SK2.mjs +0 -26
- package/dist/SK2.mjs.map +0 -1
- package/dist/US.mjs +0 -1061
- package/dist/US.mjs.map +0 -1
- package/dist/US2.mjs +0 -518
- package/dist/US2.mjs.map +0 -1
- package/dist/cs.mjs +0 -5080
- package/dist/cs.mjs.map +0 -1
- package/dist/cs2.mjs +0 -17609
- package/dist/cs2.mjs.map +0 -1
- package/dist/de4.mjs +0 -8214
- package/dist/de4.mjs.map +0 -1
- package/dist/de5.mjs +0 -8197
- package/dist/de5.mjs.map +0 -1
- package/dist/dist.mjs +0 -619
- package/dist/dist.mjs.map +0 -1
- package/dist/en.mjs +0 -9977
- package/dist/en.mjs.map +0 -1
- package/dist/en2.mjs +0 -5014
- package/dist/en2.mjs.map +0 -1
- package/dist/es3.mjs +0 -9059
- package/dist/es3.mjs.map +0 -1
- package/dist/es4.mjs +0 -8254
- package/dist/es4.mjs.map +0 -1
- package/dist/eu-institutions.mjs +0 -518
- package/dist/eu-institutions.mjs.map +0 -1
- package/dist/fr3.mjs +0 -9999
- package/dist/fr3.mjs.map +0 -1
- package/dist/fr4.mjs +0 -9975
- package/dist/fr4.mjs.map +0 -1
- package/dist/global.mjs +0 -195368
- package/dist/global.mjs.map +0 -1
- package/dist/hospitals-CZ.mjs +0 -747
- package/dist/hospitals-CZ.mjs.map +0 -1
- package/dist/hospitals-DE.mjs +0 -3356
- package/dist/hospitals-DE.mjs.map +0 -1
- package/dist/hu3.mjs +0 -9964
- package/dist/hu3.mjs.map +0 -1
- package/dist/hu4.mjs +0 -5031
- package/dist/hu4.mjs.map +0 -1
- package/dist/it3.mjs +0 -5037
- package/dist/it3.mjs.map +0 -1
- package/dist/it4.mjs +0 -9989
- package/dist/it4.mjs.map +0 -1
- package/dist/ministries-AT.mjs +0 -180
- package/dist/ministries-AT.mjs.map +0 -1
- package/dist/ministries-CZ.mjs +0 -201
- package/dist/ministries-CZ.mjs.map +0 -1
- package/dist/ministries-DE.mjs +0 -859
- package/dist/ministries-DE.mjs.map +0 -1
- package/dist/ministries-SK.mjs +0 -174
- package/dist/ministries-SK.mjs.map +0 -1
- package/dist/pl3.mjs +0 -5059
- package/dist/pl3.mjs.map +0 -1
- package/dist/pl4.mjs +0 -9991
- package/dist/pl4.mjs.map +0 -1
- package/dist/ro3.mjs +0 -10000
- package/dist/ro3.mjs.map +0 -1
- package/dist/ro4.mjs +0 -5037
- package/dist/ro4.mjs.map +0 -1
- package/dist/sk3.mjs +0 -9205
- package/dist/sk3.mjs.map +0 -1
- package/dist/sk4.mjs +0 -15242
- package/dist/sk4.mjs.map +0 -1
- package/dist/sv.mjs +0 -8312
- package/dist/sv.mjs.map +0 -1
- package/dist/sv2.mjs +0 -8439
- package/dist/sv2.mjs.map +0 -1
- package/dist/translations.mjs +0 -603
- package/dist/translations.mjs.map +0 -1
- package/dist/universities-AT.mjs +0 -410
- package/dist/universities-AT.mjs.map +0 -1
- package/dist/universities-CZ.mjs +0 -427
- package/dist/universities-CZ.mjs.map +0 -1
- package/dist/universities-DE.mjs +0 -3393
- package/dist/universities-DE.mjs.map +0 -1
- package/dist/universities-SK.mjs +0 -215
- package/dist/universities-SK.mjs.map +0 -1
package/dist/wasm.d.mts
CHANGED
|
@@ -174,6 +174,59 @@ type RedactionResult = {
|
|
|
174
174
|
* Configuration for the detection pipeline.
|
|
175
175
|
*/
|
|
176
176
|
type DenyListCategory = "Names" | "Places" | "Addresses" | "Courts" | "Financial" | "Government" | "Healthcare" | "Education" | "Political" | "Organizations" | "International";
|
|
177
|
+
/**
|
|
178
|
+
* Metadata for a single dictionary entry in the
|
|
179
|
+
* deny-list system. Mirrors the shape from
|
|
180
|
+
* `@stll/anonymize-data` so consumers can pass
|
|
181
|
+
* pre-loaded data without the runtime dependency.
|
|
182
|
+
*/
|
|
183
|
+
type DictionaryMeta = {
|
|
184
|
+
label: string;
|
|
185
|
+
category: DenyListCategory;
|
|
186
|
+
country: string | null;
|
|
187
|
+
};
|
|
188
|
+
/**
|
|
189
|
+
* Pre-loaded dictionary data for dependency injection.
|
|
190
|
+
* Consumers that want name/city/deny-list detection
|
|
191
|
+
* import from `@stll/anonymize-data` themselves and
|
|
192
|
+
* pass the data here; the anonymize package itself
|
|
193
|
+
* has zero cross-package imports.
|
|
194
|
+
*
|
|
195
|
+
* All fields are optional. When a field is absent,
|
|
196
|
+
* the corresponding detection path is skipped (same
|
|
197
|
+
* behavior as when `@stll/anonymize-data` was not
|
|
198
|
+
* installed).
|
|
199
|
+
*/
|
|
200
|
+
type Dictionaries = {
|
|
201
|
+
/**
|
|
202
|
+
* First names per language code (e.g., "cs", "de").
|
|
203
|
+
* Merged with legacy config names at init time.
|
|
204
|
+
*/
|
|
205
|
+
firstNames?: Readonly<Record<string, readonly string[]>>;
|
|
206
|
+
/**
|
|
207
|
+
* Surnames per language code.
|
|
208
|
+
* Merged with legacy config names at init time.
|
|
209
|
+
*/
|
|
210
|
+
surnames?: Readonly<Record<string, readonly string[]>>;
|
|
211
|
+
/**
|
|
212
|
+
* Pre-loaded deny-list dictionaries keyed by
|
|
213
|
+
* dictionary ID (e.g., "courts/CZ", "banks/DE").
|
|
214
|
+
* Each value is the array of terms for that
|
|
215
|
+
* dictionary.
|
|
216
|
+
*/
|
|
217
|
+
denyList?: Readonly<Record<string, readonly string[]>>;
|
|
218
|
+
/**
|
|
219
|
+
* Metadata per dictionary ID. Required when
|
|
220
|
+
* `denyList` is provided so the pipeline knows
|
|
221
|
+
* labels, categories, and country filters.
|
|
222
|
+
*/
|
|
223
|
+
denyListMeta?: Readonly<Record<string, DictionaryMeta>>;
|
|
224
|
+
/**
|
|
225
|
+
* Pre-loaded city names, already merged across
|
|
226
|
+
* all desired countries.
|
|
227
|
+
*/
|
|
228
|
+
cities?: readonly string[];
|
|
229
|
+
};
|
|
177
230
|
type PipelineConfig = {
|
|
178
231
|
threshold: number;
|
|
179
232
|
enableTriggerPhrases: boolean;
|
|
@@ -209,6 +262,13 @@ type PipelineConfig = {
|
|
|
209
262
|
*/
|
|
210
263
|
labels: string[];
|
|
211
264
|
workspaceId: string;
|
|
265
|
+
/**
|
|
266
|
+
* Pre-loaded dictionary data for name, deny-list,
|
|
267
|
+
* and city detection. When omitted, dictionary-based
|
|
268
|
+
* detection paths are skipped. Consumers load from
|
|
269
|
+
* `@stll/anonymize-data` and pass the data here.
|
|
270
|
+
*/
|
|
271
|
+
dictionaries?: Dictionaries;
|
|
212
272
|
};
|
|
213
273
|
/**
|
|
214
274
|
* Canonical entity labels used across the pipeline.
|
|
@@ -261,7 +321,7 @@ declare const CURRENCY_PATTERN_META: Readonly<RegexMeta>;
|
|
|
261
321
|
declare const processRegexMatches: (allMatches: Match[], sliceStart: number, sliceEnd: number, meta_: readonly RegexMeta[]) => Entity[];
|
|
262
322
|
//#endregion
|
|
263
323
|
//#region src/detectors/deny-list.d.ts
|
|
264
|
-
type DenyListConfig = Pick<PipelineConfig, "enableDenyList" | "enableNameCorpus" | "denyListCountries" | "denyListRegions" | "denyListExcludeCategories">;
|
|
324
|
+
type DenyListConfig = Pick<PipelineConfig, "enableDenyList" | "enableNameCorpus" | "denyListCountries" | "denyListRegions" | "denyListExcludeCategories" | "dictionaries">;
|
|
265
325
|
/**
|
|
266
326
|
* Source tag for each pattern in the automaton.
|
|
267
327
|
* "deny-list" = standard deny list entry
|
|
@@ -289,13 +349,13 @@ type DenyListData = {
|
|
|
289
349
|
};
|
|
290
350
|
/**
|
|
291
351
|
* Resolve which dictionaries to load based on country
|
|
292
|
-
* and category filters,
|
|
293
|
-
*
|
|
294
|
-
*
|
|
352
|
+
* and category filters, then build the deny list data.
|
|
353
|
+
* The returned data provides PatternEntry[] for the
|
|
354
|
+
* unified builder and parallel arrays for
|
|
295
355
|
* post-processing.
|
|
296
356
|
*
|
|
297
|
-
*
|
|
298
|
-
* Returns null if
|
|
357
|
+
* Dictionary data is injected via `config.dictionaries`.
|
|
358
|
+
* Returns null if no dictionaries are provided.
|
|
299
359
|
*/
|
|
300
360
|
declare const buildDenyList: (config: DenyListConfig, ctx?: PipelineContext) => Promise<DenyListData | null>;
|
|
301
361
|
/**
|
|
@@ -306,7 +366,7 @@ declare const buildDenyList: (config: DenyListConfig, ctx?: PipelineContext) =>
|
|
|
306
366
|
* the search instance was built on a different context
|
|
307
367
|
* (e.g. cachedSearch).
|
|
308
368
|
*/
|
|
309
|
-
declare const ensureDenyListData: (ctx?: PipelineContext) => Promise<void>;
|
|
369
|
+
declare const ensureDenyListData: (ctx?: PipelineContext, dictionaries?: Dictionaries) => Promise<void>;
|
|
310
370
|
/**
|
|
311
371
|
* Process deny list matches from the unified search.
|
|
312
372
|
* Receives all matches; filters to the deny list slice
|
|
@@ -647,14 +707,18 @@ declare const propagateOrgNames: (entities: Entity[], fullText: string) => Entit
|
|
|
647
707
|
//#endregion
|
|
648
708
|
//#region src/detectors/names.d.ts
|
|
649
709
|
/**
|
|
650
|
-
* Load name corpus data from
|
|
651
|
-
*
|
|
710
|
+
* Load name corpus data from injected dictionaries
|
|
711
|
+
* and legacy config files. Merges all sources.
|
|
652
712
|
*
|
|
653
713
|
* Safe to call multiple times; only loads once per
|
|
654
714
|
* context. Must be called before detectNameCorpus or
|
|
655
715
|
* the getNameCorpus*() accessors are used.
|
|
716
|
+
*
|
|
717
|
+
* @param dictionaries Optional pre-loaded dictionaries
|
|
718
|
+
* with per-language first names and surnames. When
|
|
719
|
+
* omitted, only legacy config files are used.
|
|
656
720
|
*/
|
|
657
|
-
declare const initNameCorpus: (ctx?: PipelineContext) => Promise<void>;
|
|
721
|
+
declare const initNameCorpus: (ctx?: PipelineContext, dictionaries?: Dictionaries) => Promise<void>;
|
|
658
722
|
/**
|
|
659
723
|
* Detect person names by looking up tokens against the
|
|
660
724
|
* name corpus, then chaining adjacent name-like tokens.
|
|
@@ -933,5 +997,5 @@ declare const levenshtein: (rawA: string, rawB: string) => number;
|
|
|
933
997
|
*/
|
|
934
998
|
declare const normalizeForSearch: (text: string) => string;
|
|
935
999
|
//#endregion
|
|
936
|
-
export { type AnonymisationOperator, CURRENCY_PATTERN_META, type CountryCode, DATE_PATTERN_META, DEFAULT_ENTITY_LABELS, DEFAULT_OPERATOR_CONFIG, DETECTION_SOURCES, DETECTOR_PRIORITY, type DefinitionPattern, type DenyListCategory, type DenyListData, type DetectionSource, type DocumentZone, type Entity, type EntityResult, type GazetteerData, type GazetteerEntry, type HotwordRule, type NameCorpusData, type NerInferenceFn, OPERATOR_REGISTRY, OPERATOR_TYPES, type OperatorConfig, type OperatorType, type PipelineConfig, type PipelineContext, type PipelineOptions, REGEX_META, REGEX_PATTERNS, REGIONS, type RawInferenceResult, type RedactionResult, type RegexMeta, type RegionId, type ReviewDecision, type ReviewedEntity, type TriggerExtension, type TriggerGroupConfig, type TriggerRule, type TriggerStrategy, type TriggerValidation, type UnifiedResult, type UnifiedSearchInstance, ZONE_SCORE_ADJUSTMENTS, type ZoneSpan, 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, initHotwordRules, initNameCorpus, initZoneClassifier, levenshtein, mergeAndDedup, mergeChunkEntities, normalizeForSearch, prepareBatch, processAddressSeeds, processDenyListMatches, processGazetteerMatches, processLegalFormMatches, processRegexMatches, processTriggerMatches, propagateOrgNames, redactText, resolveCountries, resolveOperator, runPipeline, runUnifiedSearch, sanitizeEntities, tokenizeText };
|
|
1000
|
+
export { type AnonymisationOperator, CURRENCY_PATTERN_META, type CountryCode, DATE_PATTERN_META, DEFAULT_ENTITY_LABELS, DEFAULT_OPERATOR_CONFIG, DETECTION_SOURCES, DETECTOR_PRIORITY, type DefinitionPattern, type DenyListCategory, type DenyListData, type DetectionSource, type Dictionaries, type DictionaryMeta, type DocumentZone, type Entity, type EntityResult, type GazetteerData, type GazetteerEntry, type HotwordRule, type NameCorpusData, type NerInferenceFn, OPERATOR_REGISTRY, OPERATOR_TYPES, type OperatorConfig, type OperatorType, type PipelineConfig, type PipelineContext, type PipelineOptions, REGEX_META, REGEX_PATTERNS, REGIONS, type RawInferenceResult, type RedactionResult, type RegexMeta, type RegionId, type ReviewDecision, type ReviewedEntity, type TriggerExtension, type TriggerGroupConfig, type TriggerRule, type TriggerStrategy, type TriggerValidation, type UnifiedResult, type UnifiedSearchInstance, ZONE_SCORE_ADJUSTMENTS, type ZoneSpan, 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, initHotwordRules, initNameCorpus, initZoneClassifier, levenshtein, mergeAndDedup, mergeChunkEntities, normalizeForSearch, prepareBatch, processAddressSeeds, processDenyListMatches, processGazetteerMatches, processLegalFormMatches, processRegexMatches, processTriggerMatches, propagateOrgNames, redactText, resolveCountries, resolveOperator, runPipeline, runUnifiedSearch, sanitizeEntities, tokenizeText };
|
|
937
1001
|
//# sourceMappingURL=wasm.d.mts.map
|
package/dist/wasm.mjs
CHANGED
|
@@ -606,42 +606,18 @@ const getNameCorpusFirstNames = (ctx = defaultContext) => ctx.nameCorpus?.firstN
|
|
|
606
606
|
const getNameCorpusSurnames = (ctx = defaultContext) => ctx.nameCorpus?.surnamesList ?? [];
|
|
607
607
|
const getNameCorpusTitles = (ctx = defaultContext) => ctx.nameCorpus?.titlesList ?? [];
|
|
608
608
|
/**
|
|
609
|
-
*
|
|
610
|
-
*
|
|
611
|
-
*/
|
|
612
|
-
const NAME_LANGUAGES = [
|
|
613
|
-
"cs",
|
|
614
|
-
"sk",
|
|
615
|
-
"de",
|
|
616
|
-
"pl",
|
|
617
|
-
"hu",
|
|
618
|
-
"ro",
|
|
619
|
-
"fr",
|
|
620
|
-
"es",
|
|
621
|
-
"it",
|
|
622
|
-
"en",
|
|
623
|
-
"sv"
|
|
624
|
-
];
|
|
625
|
-
/**
|
|
626
|
-
* Try importing a JSON module; return empty array
|
|
627
|
-
* if not found.
|
|
628
|
-
*/
|
|
629
|
-
const tryImportArray = async (path) => {
|
|
630
|
-
try {
|
|
631
|
-
return (await import(path)).default;
|
|
632
|
-
} catch {
|
|
633
|
-
return [];
|
|
634
|
-
}
|
|
635
|
-
};
|
|
636
|
-
/**
|
|
637
|
-
* Load name corpus data from per-language dictionary
|
|
638
|
-
* files and legacy config files. Merges all sources.
|
|
609
|
+
* Load name corpus data from injected dictionaries
|
|
610
|
+
* and legacy config files. Merges all sources.
|
|
639
611
|
*
|
|
640
612
|
* Safe to call multiple times; only loads once per
|
|
641
613
|
* context. Must be called before detectNameCorpus or
|
|
642
614
|
* the getNameCorpus*() accessors are used.
|
|
615
|
+
*
|
|
616
|
+
* @param dictionaries Optional pre-loaded dictionaries
|
|
617
|
+
* with per-language first names and surnames. When
|
|
618
|
+
* omitted, only legacy config files are used.
|
|
643
619
|
*/
|
|
644
|
-
const initNameCorpus = (ctx = defaultContext) => {
|
|
620
|
+
const initNameCorpus = (ctx = defaultContext, dictionaries) => {
|
|
645
621
|
if (ctx.nameCorpusPromise) return ctx.nameCorpusPromise;
|
|
646
622
|
const promise = (async () => {
|
|
647
623
|
try {
|
|
@@ -651,13 +627,10 @@ const initNameCorpus = (ctx = defaultContext) => {
|
|
|
651
627
|
import("./names-title-tokens.mjs"),
|
|
652
628
|
import("./names-exclusions.mjs")
|
|
653
629
|
]);
|
|
654
|
-
const firstImports = NAME_LANGUAGES.map((lang) => tryImportArray(`@stll/anonymize-data/dictionaries/names/first/${lang}.json`));
|
|
655
|
-
const surnameImports = NAME_LANGUAGES.map((lang) => tryImportArray(`@stll/anonymize-data/dictionaries/names/surnames/${lang}.json`));
|
|
656
|
-
const [firstResults, surnameResults] = await Promise.all([Promise.all(firstImports), Promise.all(surnameImports)]);
|
|
657
630
|
const firstNames = [...legacyFirstMod.default.names];
|
|
658
|
-
for (const names of
|
|
631
|
+
if (dictionaries?.firstNames) for (const names of Object.values(dictionaries.firstNames)) for (const name of names) firstNames.push(name);
|
|
659
632
|
const surnames = [...legacySurnameMod.default.names];
|
|
660
|
-
for (const names of
|
|
633
|
+
if (dictionaries?.surnames) for (const names of Object.values(dictionaries.surnames)) for (const name of names) surnames.push(name);
|
|
661
634
|
const dedup = (arr) => {
|
|
662
635
|
const seen = /* @__PURE__ */ new Set();
|
|
663
636
|
const result = [];
|
|
@@ -3156,17 +3129,6 @@ const normalizeForSearch = (text) => {
|
|
|
3156
3129
|
};
|
|
3157
3130
|
//#endregion
|
|
3158
3131
|
//#region src/detectors/deny-list.ts
|
|
3159
|
-
/**
|
|
3160
|
-
* Try to load the optional @stll/anonymize-data package.
|
|
3161
|
-
* Returns null if not installed.
|
|
3162
|
-
*/
|
|
3163
|
-
const loadDataModule = async () => {
|
|
3164
|
-
try {
|
|
3165
|
-
return await import("./dist.mjs");
|
|
3166
|
-
} catch {
|
|
3167
|
-
return null;
|
|
3168
|
-
}
|
|
3169
|
-
};
|
|
3170
3132
|
const loadAllowList = (ctx) => {
|
|
3171
3133
|
if (ctx.allowListPromise) return ctx.allowListPromise;
|
|
3172
3134
|
ctx.allowListPromise = (async () => {
|
|
@@ -3285,46 +3247,33 @@ const PERSON_CHAIN_BREAK_RE = /[!?;:]|,/u;
|
|
|
3285
3247
|
const isInitialContinuationGap = (text, gap) => /^\p{Lu}$/u.test(text) && /^\.[^\S\n]{1,2}$/u.test(gap) || /^[^\S\n]{1,2}(?:\p{Lu}\.[^\S\n]{1,2})+$/u.test(gap);
|
|
3286
3248
|
/**
|
|
3287
3249
|
* Resolve which dictionaries to load based on country
|
|
3288
|
-
* and category filters,
|
|
3289
|
-
*
|
|
3290
|
-
*
|
|
3250
|
+
* and category filters, then build the deny list data.
|
|
3251
|
+
* The returned data provides PatternEntry[] for the
|
|
3252
|
+
* unified builder and parallel arrays for
|
|
3291
3253
|
* post-processing.
|
|
3292
3254
|
*
|
|
3293
|
-
*
|
|
3294
|
-
* Returns null if
|
|
3255
|
+
* Dictionary data is injected via `config.dictionaries`.
|
|
3256
|
+
* Returns null if no dictionaries are provided.
|
|
3295
3257
|
*/
|
|
3296
3258
|
const buildDenyList = async (config, ctx = defaultContext) => {
|
|
3297
|
-
await initNameCorpus(ctx);
|
|
3259
|
+
await initNameCorpus(ctx, config.dictionaries);
|
|
3298
3260
|
await Promise.all([
|
|
3299
3261
|
loadStopwords(ctx),
|
|
3300
3262
|
loadAllowList(ctx),
|
|
3301
3263
|
loadPersonStopwords(ctx),
|
|
3302
3264
|
loadGenericRoles(ctx)
|
|
3303
3265
|
]);
|
|
3304
|
-
const
|
|
3305
|
-
|
|
3266
|
+
const dictionaries = config.dictionaries;
|
|
3267
|
+
const hasDenyList = dictionaries?.denyList && dictionaries?.denyListMeta;
|
|
3268
|
+
const hasCities = dictionaries?.cities && dictionaries.cities.length > 0;
|
|
3269
|
+
if (!hasDenyList && !hasCities) return buildNameCorpusOnly(config, ctx);
|
|
3306
3270
|
const allowedCountries = resolveCountries(config.denyListRegions, config.denyListCountries);
|
|
3307
3271
|
const excluded = config.denyListExcludeCategories;
|
|
3308
3272
|
const excludeCategories = excluded ? new Set(excluded) : /* @__PURE__ */ new Set();
|
|
3309
|
-
const ids = [...dataModule.ALL_DICTIONARY_IDS].filter((id) => {
|
|
3310
|
-
const meta = dataModule.DICTIONARY_META[id];
|
|
3311
|
-
if (!meta) return false;
|
|
3312
|
-
if (!config.enableNameCorpus && meta.category === "Names") return false;
|
|
3313
|
-
if (excludeCategories.has(meta.category)) return false;
|
|
3314
|
-
if (allowedCountries === null) return true;
|
|
3315
|
-
if (meta.country === null) return true;
|
|
3316
|
-
return allowedCountries.has(meta.country);
|
|
3317
|
-
});
|
|
3318
3273
|
const patternList = [];
|
|
3319
3274
|
const labelList = [];
|
|
3320
3275
|
const sourceList = [];
|
|
3321
3276
|
const patternIndex = /* @__PURE__ */ new Map();
|
|
3322
|
-
const results = await Promise.all(ids.map(async (id) => {
|
|
3323
|
-
return {
|
|
3324
|
-
id,
|
|
3325
|
-
entries: await dataModule.loadDictionary(id)
|
|
3326
|
-
};
|
|
3327
|
-
}));
|
|
3328
3277
|
const addDenyListEntry = (entry, label) => {
|
|
3329
3278
|
const normalized = normalizeForSearch(entry).replace(/[|\\]/g, "");
|
|
3330
3279
|
if (normalized.length === 0) return;
|
|
@@ -3340,47 +3289,59 @@ const buildDenyList = async (config, ctx = defaultContext) => {
|
|
|
3340
3289
|
sourceList.push(["deny-list"]);
|
|
3341
3290
|
}
|
|
3342
3291
|
};
|
|
3343
|
-
|
|
3344
|
-
const
|
|
3345
|
-
|
|
3346
|
-
for (const
|
|
3347
|
-
|
|
3348
|
-
|
|
3349
|
-
|
|
3350
|
-
|
|
3351
|
-
|
|
3352
|
-
|
|
3353
|
-
|
|
3354
|
-
|
|
3355
|
-
|
|
3356
|
-
"CH",
|
|
3357
|
-
"CZ",
|
|
3358
|
-
"DE",
|
|
3359
|
-
"DK",
|
|
3360
|
-
"ES",
|
|
3361
|
-
"FI",
|
|
3362
|
-
"FR",
|
|
3363
|
-
"GB",
|
|
3364
|
-
"GR",
|
|
3365
|
-
"HR",
|
|
3366
|
-
"HU",
|
|
3367
|
-
"IE",
|
|
3368
|
-
"IT",
|
|
3369
|
-
"LU",
|
|
3370
|
-
"NL",
|
|
3371
|
-
"NO",
|
|
3372
|
-
"NZ",
|
|
3373
|
-
"PL",
|
|
3374
|
-
"PT",
|
|
3375
|
-
"RO",
|
|
3376
|
-
"SE",
|
|
3377
|
-
"SI",
|
|
3378
|
-
"SK",
|
|
3379
|
-
"US"
|
|
3380
|
-
];
|
|
3381
|
-
const cityEntries = await dataModule.loadCityDictionaries(cityCountries);
|
|
3382
|
-
for (const entry of cityEntries) addDenyListEntry(entry, "address");
|
|
3292
|
+
if (hasDenyList) {
|
|
3293
|
+
const denyListData = dictionaries.denyList;
|
|
3294
|
+
const metaData = dictionaries.denyListMeta;
|
|
3295
|
+
for (const [id, entries] of Object.entries(denyListData)) {
|
|
3296
|
+
const meta = metaData[id];
|
|
3297
|
+
if (!meta) continue;
|
|
3298
|
+
if (!config.enableNameCorpus && meta.category === "Names") continue;
|
|
3299
|
+
if (excludeCategories.has(meta.category)) continue;
|
|
3300
|
+
if (allowedCountries !== null && meta.country !== null) {
|
|
3301
|
+
if (!allowedCountries.has(meta.country)) continue;
|
|
3302
|
+
}
|
|
3303
|
+
for (const entry of entries) addDenyListEntry(entry, meta.label);
|
|
3304
|
+
}
|
|
3383
3305
|
}
|
|
3306
|
+
if (hasCities && !excludeCategories.has("Places")) for (const entry of dictionaries.cities) addDenyListEntry(entry, "address");
|
|
3307
|
+
appendNameCorpusEntries(config, ctx, patternList, labelList, sourceList, patternIndex);
|
|
3308
|
+
if (patternList.length === 0) return null;
|
|
3309
|
+
return {
|
|
3310
|
+
labels: labelList,
|
|
3311
|
+
originals: patternList,
|
|
3312
|
+
sources: sourceList
|
|
3313
|
+
};
|
|
3314
|
+
};
|
|
3315
|
+
/**
|
|
3316
|
+
* Build deny-list data containing only name corpus
|
|
3317
|
+
* entries (no external dictionaries). Used when no
|
|
3318
|
+
* dictionary data is injected but name corpus is
|
|
3319
|
+
* enabled.
|
|
3320
|
+
*/
|
|
3321
|
+
const buildNameCorpusOnly = (config, ctx) => {
|
|
3322
|
+
if (!config.enableNameCorpus) return null;
|
|
3323
|
+
const excluded = config.denyListExcludeCategories;
|
|
3324
|
+
if ((excluded ? new Set(excluded) : /* @__PURE__ */ new Set()).has("Names")) return null;
|
|
3325
|
+
const patternList = [];
|
|
3326
|
+
const labelList = [];
|
|
3327
|
+
const sourceList = [];
|
|
3328
|
+
appendNameCorpusEntries(config, ctx, patternList, labelList, sourceList, /* @__PURE__ */ new Map());
|
|
3329
|
+
if (patternList.length === 0) return null;
|
|
3330
|
+
return {
|
|
3331
|
+
labels: labelList,
|
|
3332
|
+
originals: patternList,
|
|
3333
|
+
sources: sourceList
|
|
3334
|
+
};
|
|
3335
|
+
};
|
|
3336
|
+
/**
|
|
3337
|
+
* Append name corpus entries (first names, surnames,
|
|
3338
|
+
* titles) to the pattern arrays. Shared between
|
|
3339
|
+
* buildDenyList and buildNameCorpusOnly.
|
|
3340
|
+
*/
|
|
3341
|
+
const appendNameCorpusEntries = (config, ctx, patternList, labelList, sourceList, patternIndex) => {
|
|
3342
|
+
const excluded = config.denyListExcludeCategories;
|
|
3343
|
+
const excludeCategories = excluded ? new Set(excluded) : /* @__PURE__ */ new Set();
|
|
3344
|
+
if (!config.enableNameCorpus || excludeCategories.has("Names")) return;
|
|
3384
3345
|
const addNameEntry = (name, source) => {
|
|
3385
3346
|
const normalized = normalizeForSearch(name).replace(/[|\\]/g, "");
|
|
3386
3347
|
if (normalized.length === 0) return;
|
|
@@ -3396,30 +3357,22 @@ const buildDenyList = async (config, ctx = defaultContext) => {
|
|
|
3396
3357
|
sourceList.push([source]);
|
|
3397
3358
|
}
|
|
3398
3359
|
};
|
|
3399
|
-
|
|
3400
|
-
|
|
3401
|
-
|
|
3402
|
-
|
|
3403
|
-
|
|
3404
|
-
|
|
3405
|
-
|
|
3406
|
-
|
|
3407
|
-
if (existing
|
|
3408
|
-
|
|
3409
|
-
|
|
3410
|
-
|
|
3411
|
-
|
|
3412
|
-
|
|
3413
|
-
sourceList.push(["title"]);
|
|
3414
|
-
}
|
|
3360
|
+
for (const name of getNameCorpusFirstNames(ctx)) addNameEntry(name, "first-name");
|
|
3361
|
+
for (const name of getNameCorpusSurnames(ctx)) addNameEntry(name, "surname");
|
|
3362
|
+
for (const title of getNameCorpusTitles(ctx)) {
|
|
3363
|
+
const norm = normalizeForSearch(title).replace(/[|\\]/g, "");
|
|
3364
|
+
if (norm.length === 0) continue;
|
|
3365
|
+
const lower = norm.toLowerCase();
|
|
3366
|
+
const existing = patternIndex.get(lower);
|
|
3367
|
+
if (existing !== void 0) {
|
|
3368
|
+
if (!sourceList[existing].includes("title")) sourceList[existing].push("title");
|
|
3369
|
+
} else {
|
|
3370
|
+
patternIndex.set(lower, patternList.length);
|
|
3371
|
+
patternList.push(norm);
|
|
3372
|
+
labelList.push(["person"]);
|
|
3373
|
+
sourceList.push(["title"]);
|
|
3415
3374
|
}
|
|
3416
3375
|
}
|
|
3417
|
-
if (patternList.length === 0) return null;
|
|
3418
|
-
return {
|
|
3419
|
-
labels: labelList,
|
|
3420
|
-
originals: patternList,
|
|
3421
|
-
sources: sourceList
|
|
3422
|
-
};
|
|
3423
3376
|
};
|
|
3424
3377
|
/**
|
|
3425
3378
|
* Ensure all deny-list support data (stopwords, allow
|
|
@@ -3429,8 +3382,8 @@ const buildDenyList = async (config, ctx = defaultContext) => {
|
|
|
3429
3382
|
* the search instance was built on a different context
|
|
3430
3383
|
* (e.g. cachedSearch).
|
|
3431
3384
|
*/
|
|
3432
|
-
const ensureDenyListData = async (ctx = defaultContext) => {
|
|
3433
|
-
await initNameCorpus(ctx);
|
|
3385
|
+
const ensureDenyListData = async (ctx = defaultContext, dictionaries) => {
|
|
3386
|
+
await initNameCorpus(ctx, dictionaries);
|
|
3434
3387
|
await Promise.all([
|
|
3435
3388
|
loadStopwords(ctx),
|
|
3436
3389
|
loadAllowList(ctx),
|
|
@@ -5186,7 +5139,7 @@ const runPipeline = async (options) => {
|
|
|
5186
5139
|
initStreetAbbrevs(),
|
|
5187
5140
|
hotwordInit
|
|
5188
5141
|
]);
|
|
5189
|
-
if (cachedSearch && config.enableDenyList) await ensureDenyListData(ctx);
|
|
5142
|
+
if (cachedSearch && config.enableDenyList) await ensureDenyListData(ctx, config.dictionaries);
|
|
5190
5143
|
let zones = [];
|
|
5191
5144
|
if (config.enableZoneClassification && zoneInitOk) {
|
|
5192
5145
|
zones = classifyZones(fullText, ctx);
|
|
@@ -5212,7 +5165,7 @@ const runPipeline = async (options) => {
|
|
|
5212
5165
|
let rawNameCorpusEntities = [];
|
|
5213
5166
|
let nameCorpusEntities = [];
|
|
5214
5167
|
if (config.enableNameCorpus && !config.enableDenyList) {
|
|
5215
|
-
await initNameCorpus(ctx);
|
|
5168
|
+
await initNameCorpus(ctx, config.dictionaries);
|
|
5216
5169
|
checkAbort(signal);
|
|
5217
5170
|
rawNameCorpusEntities = detectNameCorpus(fullText, ctx);
|
|
5218
5171
|
nameCorpusEntities = filterAllowedLabels(rawNameCorpusEntities, preHotwordAllowedLabels);
|