ezmedicationinput 0.1.17 → 0.1.19
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/parser.js +143 -19
- package/package.json +1 -1
package/dist/parser.js
CHANGED
|
@@ -1445,6 +1445,7 @@ function parseInternal(input, options) {
|
|
|
1445
1445
|
}
|
|
1446
1446
|
// PRN detection
|
|
1447
1447
|
let prnReasonStart;
|
|
1448
|
+
const prnSiteSuffixIndices = new Set();
|
|
1448
1449
|
for (let i = 0; i < tokens.length; i++) {
|
|
1449
1450
|
const token = tokens[i];
|
|
1450
1451
|
if (token.lower === "prn") {
|
|
@@ -1529,6 +1530,9 @@ function parseInternal(input, options) {
|
|
|
1529
1530
|
};
|
|
1530
1531
|
// Process tokens sequentially
|
|
1531
1532
|
const tryRouteSynonym = (startIndex) => {
|
|
1533
|
+
if (prnReasonStart !== undefined && startIndex >= prnReasonStart) {
|
|
1534
|
+
return false;
|
|
1535
|
+
}
|
|
1532
1536
|
const maxSpan = Math.min(24, tokens.length - startIndex);
|
|
1533
1537
|
for (let span = maxSpan; span >= 1; span--) {
|
|
1534
1538
|
const slice = tokens.slice(startIndex, startIndex + span);
|
|
@@ -1901,7 +1905,7 @@ function parseInternal(input, options) {
|
|
|
1901
1905
|
for (let i = prnReasonStart; i < tokens.length; i++) {
|
|
1902
1906
|
const token = tokens[i];
|
|
1903
1907
|
if (internal.consumed.has(token.index)) {
|
|
1904
|
-
|
|
1908
|
+
internal.consumed.delete(token.index);
|
|
1905
1909
|
}
|
|
1906
1910
|
reasonTokens.push(token.original);
|
|
1907
1911
|
reasonIndices.push(token.index);
|
|
@@ -1948,6 +1952,14 @@ function parseInternal(input, options) {
|
|
|
1948
1952
|
}
|
|
1949
1953
|
}
|
|
1950
1954
|
}
|
|
1955
|
+
if (reasonTokens.length > 0) {
|
|
1956
|
+
const suffixTokens = findTrailingPrnSiteSuffix(reasonObjects, internal, options);
|
|
1957
|
+
if (suffixTokens === null || suffixTokens === void 0 ? void 0 : suffixTokens.length) {
|
|
1958
|
+
for (const token of suffixTokens) {
|
|
1959
|
+
prnSiteSuffixIndices.add(token.index);
|
|
1960
|
+
}
|
|
1961
|
+
}
|
|
1962
|
+
}
|
|
1951
1963
|
if (reasonTokens.length > 0) {
|
|
1952
1964
|
const joined = reasonTokens.join(" ").trim();
|
|
1953
1965
|
if (joined) {
|
|
@@ -1983,21 +1995,31 @@ function parseInternal(input, options) {
|
|
|
1983
1995
|
// Determine site text from leftover tokens (excluding PRN reason tokens)
|
|
1984
1996
|
const leftoverTokens = tokens.filter((t) => !internal.consumed.has(t.index));
|
|
1985
1997
|
const siteCandidateIndices = new Set();
|
|
1998
|
+
const leftoverSiteIndices = new Set();
|
|
1986
1999
|
for (const token of leftoverTokens) {
|
|
2000
|
+
if (prnSiteSuffixIndices.has(token.index)) {
|
|
2001
|
+
continue;
|
|
2002
|
+
}
|
|
1987
2003
|
const normalized = normalizeTokenLower(token);
|
|
1988
2004
|
if (isBodySiteHint(normalized, internal.customSiteHints)) {
|
|
1989
2005
|
siteCandidateIndices.add(token.index);
|
|
2006
|
+
leftoverSiteIndices.add(token.index);
|
|
1990
2007
|
continue;
|
|
1991
2008
|
}
|
|
1992
2009
|
if (SITE_CONNECTORS.has(normalized)) {
|
|
1993
2010
|
const next = tokens[token.index + 1];
|
|
1994
|
-
if (next && !internal.consumed.has(next.index)) {
|
|
2011
|
+
if (next && !internal.consumed.has(next.index) && !prnSiteSuffixIndices.has(next.index)) {
|
|
1995
2012
|
siteCandidateIndices.add(next.index);
|
|
1996
2013
|
}
|
|
1997
2014
|
}
|
|
1998
2015
|
}
|
|
1999
|
-
|
|
2000
|
-
|
|
2016
|
+
if (leftoverSiteIndices.size === 0) {
|
|
2017
|
+
for (const idx of internal.siteTokenIndices) {
|
|
2018
|
+
if (prnSiteSuffixIndices.has(idx)) {
|
|
2019
|
+
continue;
|
|
2020
|
+
}
|
|
2021
|
+
siteCandidateIndices.add(idx);
|
|
2022
|
+
}
|
|
2001
2023
|
}
|
|
2002
2024
|
if (siteCandidateIndices.size > 0) {
|
|
2003
2025
|
const indicesToInclude = new Set(siteCandidateIndices);
|
|
@@ -2492,18 +2514,52 @@ function normalizeSiteDisplayText(text, customSiteMap) {
|
|
|
2492
2514
|
return trimmed;
|
|
2493
2515
|
}
|
|
2494
2516
|
const canonicalInput = (0, maps_1.normalizeBodySiteKey)(trimmed);
|
|
2495
|
-
if (!canonicalInput
|
|
2496
|
-
return trimmed;
|
|
2497
|
-
}
|
|
2498
|
-
const definition = (_a = lookupBodySiteDefinition(customSiteMap, canonicalInput)) !== null && _a !== void 0 ? _a : maps_1.DEFAULT_BODY_SITE_SNOMED[canonicalInput];
|
|
2499
|
-
if (!definition) {
|
|
2517
|
+
if (!canonicalInput) {
|
|
2500
2518
|
return trimmed;
|
|
2501
2519
|
}
|
|
2502
|
-
const
|
|
2503
|
-
|
|
2504
|
-
|
|
2520
|
+
const resolvePreferred = (canonical) => {
|
|
2521
|
+
var _a;
|
|
2522
|
+
const definition = (_a = lookupBodySiteDefinition(customSiteMap, canonical)) !== null && _a !== void 0 ? _a : maps_1.DEFAULT_BODY_SITE_SNOMED[canonical];
|
|
2523
|
+
if (!definition) {
|
|
2524
|
+
return undefined;
|
|
2525
|
+
}
|
|
2526
|
+
const preferred = pickPreferredBodySitePhrase(canonical, definition, customSiteMap);
|
|
2527
|
+
const textValue = preferred !== null && preferred !== void 0 ? preferred : canonical;
|
|
2528
|
+
const normalized = (0, maps_1.normalizeBodySiteKey)(textValue);
|
|
2529
|
+
if (!normalized) {
|
|
2530
|
+
return undefined;
|
|
2531
|
+
}
|
|
2532
|
+
return { text: textValue, canonical: normalized };
|
|
2533
|
+
};
|
|
2534
|
+
if (isAdjectivalSitePhrase(canonicalInput)) {
|
|
2535
|
+
const direct = resolvePreferred(canonicalInput);
|
|
2536
|
+
return (_a = direct === null || direct === void 0 ? void 0 : direct.text) !== null && _a !== void 0 ? _a : trimmed;
|
|
2537
|
+
}
|
|
2538
|
+
const words = canonicalInput.split(/\s+/).filter((word) => word.length > 0);
|
|
2539
|
+
for (let i = 1; i < words.length; i++) {
|
|
2540
|
+
const prefix = words.slice(0, i);
|
|
2541
|
+
if (!prefix.every((word) => isAdjectivalSitePhrase(word))) {
|
|
2542
|
+
continue;
|
|
2543
|
+
}
|
|
2544
|
+
const candidateCanonical = words.slice(i).join(" ");
|
|
2545
|
+
if (!candidateCanonical) {
|
|
2546
|
+
continue;
|
|
2547
|
+
}
|
|
2548
|
+
const candidatePreferred = resolvePreferred(candidateCanonical);
|
|
2549
|
+
if (!candidatePreferred) {
|
|
2550
|
+
continue;
|
|
2551
|
+
}
|
|
2552
|
+
const prefixMatches = prefix.every((word) => {
|
|
2553
|
+
const normalizedPrefix = resolvePreferred(word);
|
|
2554
|
+
return (normalizedPrefix !== undefined &&
|
|
2555
|
+
normalizedPrefix.canonical === candidatePreferred.canonical);
|
|
2556
|
+
});
|
|
2557
|
+
if (!prefixMatches) {
|
|
2558
|
+
continue;
|
|
2559
|
+
}
|
|
2560
|
+
return candidatePreferred.text;
|
|
2505
2561
|
}
|
|
2506
|
-
return
|
|
2562
|
+
return trimmed;
|
|
2507
2563
|
}
|
|
2508
2564
|
function pickPreferredBodySitePhrase(canonical, definition, customSiteMap) {
|
|
2509
2565
|
const synonyms = new Set();
|
|
@@ -2532,12 +2588,12 @@ function pickPreferredBodySitePhrase(canonical, definition, customSiteMap) {
|
|
|
2532
2588
|
if (normalizedKey) {
|
|
2533
2589
|
synonyms.add(normalizedKey);
|
|
2534
2590
|
}
|
|
2535
|
-
|
|
2536
|
-
|
|
2537
|
-
|
|
2538
|
-
|
|
2539
|
-
|
|
2540
|
-
|
|
2591
|
+
if (candidate.aliases) {
|
|
2592
|
+
for (const alias of candidate.aliases) {
|
|
2593
|
+
const normalizedAlias = (0, maps_1.normalizeBodySiteKey)(alias);
|
|
2594
|
+
if (normalizedAlias) {
|
|
2595
|
+
synonyms.add(normalizedAlias);
|
|
2596
|
+
}
|
|
2541
2597
|
}
|
|
2542
2598
|
}
|
|
2543
2599
|
}
|
|
@@ -2810,6 +2866,74 @@ function findPrnReasonSeparator(sourceText) {
|
|
|
2810
2866
|
}
|
|
2811
2867
|
return undefined;
|
|
2812
2868
|
}
|
|
2869
|
+
function findTrailingPrnSiteSuffix(tokens, internal, options) {
|
|
2870
|
+
var _a;
|
|
2871
|
+
let suffixStart;
|
|
2872
|
+
let hasSiteHint = false;
|
|
2873
|
+
let hasConnector = false;
|
|
2874
|
+
for (let i = tokens.length - 1; i >= 0; i--) {
|
|
2875
|
+
const token = tokens[i];
|
|
2876
|
+
const lower = normalizeTokenLower(token);
|
|
2877
|
+
if (!lower) {
|
|
2878
|
+
if (suffixStart !== undefined && token.original.trim()) {
|
|
2879
|
+
break;
|
|
2880
|
+
}
|
|
2881
|
+
continue;
|
|
2882
|
+
}
|
|
2883
|
+
if (isBodySiteHint(lower, internal.customSiteHints)) {
|
|
2884
|
+
hasSiteHint = true;
|
|
2885
|
+
suffixStart = i;
|
|
2886
|
+
continue;
|
|
2887
|
+
}
|
|
2888
|
+
if (suffixStart !== undefined) {
|
|
2889
|
+
if (SITE_CONNECTORS.has(lower)) {
|
|
2890
|
+
hasConnector = true;
|
|
2891
|
+
suffixStart = i;
|
|
2892
|
+
continue;
|
|
2893
|
+
}
|
|
2894
|
+
if (SITE_FILLER_WORDS.has(lower) || ROUTE_DESCRIPTOR_FILLER_WORDS.has(lower)) {
|
|
2895
|
+
suffixStart = i;
|
|
2896
|
+
continue;
|
|
2897
|
+
}
|
|
2898
|
+
}
|
|
2899
|
+
if (suffixStart !== undefined) {
|
|
2900
|
+
break;
|
|
2901
|
+
}
|
|
2902
|
+
}
|
|
2903
|
+
if (!hasSiteHint || !hasConnector || suffixStart === undefined || suffixStart === 0) {
|
|
2904
|
+
return undefined;
|
|
2905
|
+
}
|
|
2906
|
+
const suffixTokens = tokens.slice(suffixStart);
|
|
2907
|
+
const siteWords = [];
|
|
2908
|
+
const siteHintTokens = [];
|
|
2909
|
+
for (const token of suffixTokens) {
|
|
2910
|
+
const trimmed = token.original.trim();
|
|
2911
|
+
if (!trimmed) {
|
|
2912
|
+
continue;
|
|
2913
|
+
}
|
|
2914
|
+
const lower = normalizeTokenLower(token);
|
|
2915
|
+
if (SITE_CONNECTORS.has(lower) ||
|
|
2916
|
+
SITE_FILLER_WORDS.has(lower) ||
|
|
2917
|
+
ROUTE_DESCRIPTOR_FILLER_WORDS.has(lower)) {
|
|
2918
|
+
continue;
|
|
2919
|
+
}
|
|
2920
|
+
siteHintTokens.push(token);
|
|
2921
|
+
siteWords.push(trimmed);
|
|
2922
|
+
}
|
|
2923
|
+
if (!siteWords.length) {
|
|
2924
|
+
return undefined;
|
|
2925
|
+
}
|
|
2926
|
+
const sitePhrase = siteWords.join(" ");
|
|
2927
|
+
const canonical = (0, maps_1.normalizeBodySiteKey)(sitePhrase);
|
|
2928
|
+
if (!canonical) {
|
|
2929
|
+
return undefined;
|
|
2930
|
+
}
|
|
2931
|
+
const definition = (_a = lookupBodySiteDefinition(options === null || options === void 0 ? void 0 : options.siteCodeMap, canonical)) !== null && _a !== void 0 ? _a : maps_1.DEFAULT_BODY_SITE_SNOMED[canonical];
|
|
2932
|
+
if (!definition) {
|
|
2933
|
+
return undefined;
|
|
2934
|
+
}
|
|
2935
|
+
return siteHintTokens;
|
|
2936
|
+
}
|
|
2813
2937
|
function lookupPrnReasonDefinition(map, canonical) {
|
|
2814
2938
|
if (!map) {
|
|
2815
2939
|
return undefined;
|