@mailwoman/kind-classifier 9.1.0 → 9.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/{classify.ts → lib/classify.ts} +5 -5
- package/{index.ts → lib/index.ts} +10 -10
- package/{intent-markers.ts → lib/intent-markers.ts} +9 -7
- package/{intent-rules.ts → lib/intent-rules.ts} +7 -14
- package/{poi.ts → lib/poi.ts} +126 -15
- package/{rules.ts → lib/rules.ts} +28 -31
- package/lib/types.ts +17 -0
- package/out/classify.d.ts +2 -2
- package/out/classify.d.ts.map +1 -1
- package/out/classify.js +4 -4
- package/out/classify.js.map +1 -1
- package/out/index.d.ts +10 -10
- package/out/index.d.ts.map +1 -1
- package/out/index.js +6 -6
- package/out/index.js.map +1 -1
- package/out/intent-markers.d.ts +3 -3
- package/out/intent-markers.d.ts.map +1 -1
- package/out/intent-markers.js +8 -6
- package/out/intent-markers.js.map +1 -1
- package/out/intent-rules.d.ts +1 -1
- package/out/intent-rules.d.ts.map +1 -1
- package/out/intent-rules.js +6 -12
- package/out/intent-rules.js.map +1 -1
- package/out/poi.d.ts +65 -7
- package/out/poi.d.ts.map +1 -1
- package/out/poi.js +61 -10
- package/out/poi.js.map +1 -1
- package/out/rules.d.ts +12 -4
- package/out/rules.d.ts.map +1 -1
- package/out/rules.js +24 -30
- package/out/rules.js.map +1 -1
- package/out/types.d.ts +3 -25
- package/out/types.d.ts.map +1 -1
- package/out/types.js.map +1 -1
- package/package.json +74 -7
- package/types.ts +0 -34
package/out/intent-markers.d.ts
CHANGED
|
@@ -9,13 +9,13 @@
|
|
|
9
9
|
* Three of the four intent kinds can raise their marker here, from the string alone. The fourth —
|
|
10
10
|
* `bare_toponym`'s `declared_ambiguity` — cannot: its trigger is the dominance margin of the
|
|
11
11
|
* RESOLVED candidate list, which does not exist yet at Stage 2.5. That one is raised by
|
|
12
|
-
* `mailwoman/query-intent.ts` after the resolve, against the measured 0.5-log10
|
|
12
|
+
* `mailwoman/query-intent.ts` after the resolve, against the measured 0.5-log10 threshold. The split is
|
|
13
13
|
* deliberate and it is why this module never emits `declared_ambiguity`: a marker that asserted
|
|
14
14
|
* ambiguity from the string alone would be declaring that every bare city name is ambiguous, which
|
|
15
15
|
* is false 89.1% of the time (the measured table behind `DECISIVE_MARGIN_LOG10`).
|
|
16
16
|
*/
|
|
17
|
-
import { type POIPhraseLookup } from "
|
|
18
|
-
import type { NormalizedInputLite, QueryIntentMarker, QueryKind } from "
|
|
17
|
+
import { type POIPhraseLookup } from "#poi";
|
|
18
|
+
import type { NormalizedInputLite, QueryIntentMarker, QueryKind } from "#types";
|
|
19
19
|
/**
|
|
20
20
|
* Context the marker builder needs beyond the scored kinds.
|
|
21
21
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"intent-markers.d.ts","sourceRoot":"","sources":["../intent-markers.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAGH,OAAO,EAAoB,KAAK,eAAe,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"intent-markers.d.ts","sourceRoot":"","sources":["../lib/intent-markers.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAGH,OAAO,EAAoB,KAAK,eAAe,EAAE,MAAM,MAAM,CAAA;AAC7D,OAAO,KAAK,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAA;AAE/E;;GAEG;AACH,MAAM,WAAW,mBAAmB;IACnC,KAAK,EAAE,mBAAmB,CAAA;IAC1B;;;OAGG;IACH,UAAU,CAAC,EAAE,eAAe,CAAA;IAC5B,MAAM,CAAC,EAAE,MAAM,CAAA;CACf;AAED;;;;;;;;;GASG;AACH,wBAAgB,mBAAmB,CAClC,KAAK,EAAE,aAAa,CAAC;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,CAAC,EAC7D,GAAG,EAAE,mBAAmB,GACtB,iBAAiB,EAAE,CAgErB"}
|
package/out/intent-markers.js
CHANGED
|
@@ -9,13 +9,13 @@
|
|
|
9
9
|
* Three of the four intent kinds can raise their marker here, from the string alone. The fourth —
|
|
10
10
|
* `bare_toponym`'s `declared_ambiguity` — cannot: its trigger is the dominance margin of the
|
|
11
11
|
* RESOLVED candidate list, which does not exist yet at Stage 2.5. That one is raised by
|
|
12
|
-
* `mailwoman/query-intent.ts` after the resolve, against the measured 0.5-log10
|
|
12
|
+
* `mailwoman/query-intent.ts` after the resolve, against the measured 0.5-log10 threshold. The split is
|
|
13
13
|
* deliberate and it is why this module never emits `declared_ambiguity`: a marker that asserted
|
|
14
14
|
* ambiguity from the string alone would be declaring that every bare city name is ambiguous, which
|
|
15
15
|
* is false 89.1% of the time (the measured table behind `DECISIVE_MARGIN_LOG10`).
|
|
16
16
|
*/
|
|
17
|
-
import { nearMeSubject } from "
|
|
18
|
-
import { matchPOICategory } from "
|
|
17
|
+
import { nearMeSubject } from "#intent-rules";
|
|
18
|
+
import { matchPOICategory } from "#poi";
|
|
19
19
|
/**
|
|
20
20
|
* Build the advisories for one classified query.
|
|
21
21
|
*
|
|
@@ -30,6 +30,8 @@ export function deriveIntentMarkers(kinds, ctx) {
|
|
|
30
30
|
const fired = new Set(kinds.map((k) => k.kind));
|
|
31
31
|
const markers = [];
|
|
32
32
|
if (fired.has("route_pair")) {
|
|
33
|
+
// Whitespace-only split, not `wordsOf`: `route_pair` inputs are comma-free by construction (a comma
|
|
34
|
+
// disqualifies the kind), and the tokens are re-joined verbatim into the message.
|
|
33
35
|
const tokens = ctx.input.normalized.trim().split(/\s+/);
|
|
34
36
|
markers.push({
|
|
35
37
|
kind: "route_pair",
|
|
@@ -56,9 +58,9 @@ export function deriveIntentMarkers(kinds, ctx) {
|
|
|
56
58
|
evidence: {
|
|
57
59
|
subject,
|
|
58
60
|
/**
|
|
59
|
-
*
|
|
60
|
-
* `lat`/`lon` location-bias params — `photon/` is the eventual consumer of this marker, and this string
|
|
61
|
-
* note that says where it plugs in.
|
|
61
|
+
* THE PLUG POINT, named but not wired (ROAD_TO_V9 §4.4 scopes v9 to classification). Photon's `/api` already
|
|
62
|
+
* accepts `lat`/`lon` location-bias params — `photon/` is the eventual consumer of this marker, and this string
|
|
63
|
+
* is the note that says where it plugs in.
|
|
62
64
|
*/
|
|
63
65
|
focusParameter: "photon:lat/lon",
|
|
64
66
|
},
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"intent-markers.js","sourceRoot":"","sources":["../intent-markers.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,EAAE,aAAa,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"intent-markers.js","sourceRoot":"","sources":["../lib/intent-markers.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAA;AAC7C,OAAO,EAAE,gBAAgB,EAAwB,MAAM,MAAM,CAAA;AAgB7D;;;;;;;;;GASG;AACH,MAAM,UAAU,mBAAmB,CAClC,KAA6D,EAC7D,GAAwB;IAExB,MAAM,KAAK,GAAG,IAAI,GAAG,CAAY,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAA;IAC1D,MAAM,OAAO,GAAwB,EAAE,CAAA;IAEvC,IAAI,KAAK,CAAC,GAAG,CAAC,YAAY,CAAC,EAAE,CAAC;QAC7B,oGAAoG;QACpG,kFAAkF;QAClF,MAAM,MAAM,GAAG,GAAG,CAAC,KAAK,CAAC,UAAU,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,CAAA;QAEvD,OAAO,CAAC,IAAI,CAAC;YACZ,IAAI,EAAE,YAAY;YAClB,IAAI,EAAE,eAAe;YACrB,SAAS,EAAE,iBAAiB;YAC5B,OAAO,EAAE,IAAI,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,2HAA2H;YACxJ,QAAQ,EAAE;gBACT,MAAM;gBACN;;;mBAGG;gBACH,eAAe,EAAE,CAAC,cAAc,EAAE,6BAA6B,CAAC;aAChE;SACD,CAAC,CAAA;IACH,CAAC;IAED,IAAI,KAAK,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,CAAC;QAC1B,MAAM,OAAO,GAAG,aAAa,CAAC,GAAG,CAAC,KAAK,CAAC,CAAA;QAExC,OAAO,CAAC,IAAI,CAAC;YACZ,IAAI,EAAE,SAAS;YACf,IAAI,EAAE,sBAAsB;YAC5B,SAAS,EAAE,cAAc;YACzB,OAAO,EAAE,IAAI,OAAO,yEAAyE;YAC7F,QAAQ,EAAE;gBACT,OAAO;gBACP;;;;mBAIG;gBACH,cAAc,EAAE,gBAAgB;aAChC;SACD,CAAC,CAAA;IACH,CAAC;IAED,IAAI,KAAK,CAAC,GAAG,CAAC,cAAc,CAAC,IAAI,GAAG,CAAC,UAAU,EAAE,CAAC;QACjD,MAAM,KAAK,GAAG,gBAAgB,CAAC,GAAG,CAAC,KAAK,CAAC,UAAU,EAAE,GAAG,CAAC,MAAM,IAAI,GAAG,CAAC,KAAK,CAAC,aAAa,EAAE,GAAG,CAAC,UAAU,CAAC,CAAA;QAE3G,IAAI,KAAK,EAAE,CAAC;YACX,OAAO,CAAC,IAAI,CAAC;gBACZ,IAAI,EAAE,cAAc;gBACpB,IAAI,EAAE,cAAc;gBACpB,SAAS,EAAE,sBAAsB;gBACjC,OAAO,EAAE,IAAI,KAAK,CAAC,aAAa,yFAAyF;gBACzH,QAAQ,EAAE;oBACT,UAAU,EAAE,KAAK,CAAC,UAAU;oBAC5B,aAAa,EAAE,KAAK,CAAC,aAAa;oBAClC,GAAG,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,KAAK,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;iBACvD;aACD,CAAC,CAAA;QACH,CAAC;IACF,CAAC;IAED,OAAO,OAAO,CAAA;AACf,CAAC"}
|
package/out/intent-rules.d.ts
CHANGED
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
* `near_me` DOES win its top slot (0.91), because there is no incumbent worth preserving: a query
|
|
23
23
|
* ending "near me" is not a locality and answering it as one is the bug.
|
|
24
24
|
*/
|
|
25
|
-
import type { NormalizedInputLite, QueryShapeLike } from "
|
|
25
|
+
import type { NormalizedInputLite, QueryShapeLike } from "#types";
|
|
26
26
|
/**
|
|
27
27
|
* `bare_toponym` rule: a single coherent place-name carrying no address grammar.
|
|
28
28
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"intent-rules.d.ts","sourceRoot":"","sources":["../intent-rules.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAGH,OAAO,KAAK,EAAE,mBAAmB,EAAE,cAAc,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"intent-rules.d.ts","sourceRoot":"","sources":["../lib/intent-rules.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAGH,OAAO,KAAK,EAAE,mBAAmB,EAAE,cAAc,EAAE,MAAM,QAAQ,CAAA;AA+MjE;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,mBAAmB,EAAE,KAAK,EAAE,cAAc,GAAG,MAAM,CAE1F;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,mBAAmB,EAAE,KAAK,EAAE,cAAc,GAAG,MAAM,CAgBxF;AAED;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,mBAAmB,EAAE,MAAM,EAAE,cAAc,GAAG,MAAM,CAYtF;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,mBAAmB,GAAG,MAAM,CAQhE"}
|
package/out/intent-rules.js
CHANGED
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
* `near_me` DOES win its top slot (0.91), because there is no incumbent worth preserving: a query
|
|
23
23
|
* ending "near me" is not a locality and answering it as one is the bug.
|
|
24
24
|
*/
|
|
25
|
-
import { MAX_LOCALITY_ONLY_LENGTH,
|
|
25
|
+
import { isDisqualifyingStreetSuffix, MAX_LOCALITY_ONLY_LENGTH, wordsOf } from "#rules";
|
|
26
26
|
/**
|
|
27
27
|
* `locality_only` scores 0.85. Both refinement kinds sit under it by a whole confidence step so no float-comparison
|
|
28
28
|
* accident can flip the top slot, and so the gap reads as deliberate to the next person.
|
|
@@ -173,12 +173,6 @@ const DEICTIC_LOCATOR_TAIL = /\b(?:near|close\s+to|next\s+to|around|by|closest\s
|
|
|
173
173
|
* The adverbial half of the same class — no preposition, the deixis is baked into the word.
|
|
174
174
|
*/
|
|
175
175
|
const DEICTIC_ADVERB_TAIL = /\b(?:nearby|near\s?by|close\s+by|around\s+here|in\s+my\s+(?:area|neighborhood|neighbourhood))\s*$/;
|
|
176
|
-
/**
|
|
177
|
-
* Split on whitespace + commas, the way the other rules in this package do.
|
|
178
|
-
*/
|
|
179
|
-
function wordsOf(text) {
|
|
180
|
-
return text.split(/[\s,]+/).filter(Boolean);
|
|
181
|
-
}
|
|
182
176
|
/**
|
|
183
177
|
* True when the input carries a deictic locator tail in EITHER form.
|
|
184
178
|
*/
|
|
@@ -186,12 +180,12 @@ function hasDeicticTail(lowercased) {
|
|
|
186
180
|
return DEICTIC_LOCATOR_TAIL.test(lowercased) || DEICTIC_ADVERB_TAIL.test(lowercased);
|
|
187
181
|
}
|
|
188
182
|
/**
|
|
189
|
-
* The
|
|
183
|
+
* The conditions `bare_toponym` and `route_pair` share: no address grammar of any kind, one segment, alpha throughout.
|
|
190
184
|
*
|
|
191
185
|
* Returns the word list when the input clears them, `null` when it does not. Deliberately a SUPERSET of
|
|
192
|
-
* `scoreLocalityOnly`'s
|
|
193
|
-
* and can never fire where `locality_only` did not — the property `intent-rules.test.ts` asserts and
|
|
194
|
-
* ranking discipline above is enough to keep the top kind pinned.
|
|
186
|
+
* `scoreLocalityOnly`'s conditions (which admit two segments), so `bare_toponym` is a strict refinement of
|
|
187
|
+
* `locality_only` and can never fire where `locality_only` did not — the property `intent-rules.test.ts` asserts and
|
|
188
|
+
* the reason the ranking discipline above is enough to keep the top kind pinned.
|
|
195
189
|
*/
|
|
196
190
|
function bareNameWords(input, shape) {
|
|
197
191
|
const text = input.normalized.trim();
|
|
@@ -214,7 +208,7 @@ function bareNameWords(input, shape) {
|
|
|
214
208
|
if (!words.length || words.length > MAX_BARE_TOPONYM_WORDS)
|
|
215
209
|
return null;
|
|
216
210
|
for (const word of words) {
|
|
217
|
-
if (
|
|
211
|
+
if (isDisqualifyingStreetSuffix(word))
|
|
218
212
|
return null;
|
|
219
213
|
}
|
|
220
214
|
return words;
|
package/out/intent-rules.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"intent-rules.js","sourceRoot":"","sources":["../intent-rules.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,OAAO,EAAE,wBAAwB,EAAE,
|
|
1
|
+
{"version":3,"file":"intent-rules.js","sourceRoot":"","sources":["../lib/intent-rules.ts"],"names":[],"mappings":"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"}
|
package/out/poi.d.ts
CHANGED
|
@@ -8,52 +8,110 @@
|
|
|
8
8
|
* lives in `@mailwoman/poi-taxonomy` and is wired in by `createRuntimePipeline` behind the
|
|
9
9
|
* `poiQueryKind` flag (default-ON since 2026-07-20). Spec §3.1.
|
|
10
10
|
*/
|
|
11
|
-
import type { NormalizedInputLite, QueryShapeLike } from "
|
|
11
|
+
import type { NormalizedInputLite, QueryShapeLike } from "#types";
|
|
12
12
|
/**
|
|
13
13
|
* One lexicon hit for a candidate subject phrase.
|
|
14
14
|
*/
|
|
15
15
|
export interface POIPhraseMatch {
|
|
16
16
|
/**
|
|
17
|
-
* The matched subject's identifier string. For `kind: "category"`, a `@mailwoman/poi-taxonomy` category id
|
|
18
|
-
* `kind: "brand"`, the
|
|
19
|
-
*
|
|
17
|
+
* The matched subject's identifier string. For `kind: "category"`, a `@mailwoman/poi-taxonomy` category id; for
|
|
18
|
+
* `kind: "brand"` or `kind: "name"`, the canonical display name. `matchPOISubject` treats it opaquely; the caller
|
|
19
|
+
* (`mailwoman`'s `poi-intent.ts`) interprets it per `kind`.
|
|
20
20
|
*/
|
|
21
21
|
categoryID: string;
|
|
22
22
|
matchedPhrase: string;
|
|
23
23
|
confidence: number;
|
|
24
|
+
mechanism?: "exact" | "locale_normalized" | "typo";
|
|
25
|
+
inputPhrase?: string;
|
|
24
26
|
/**
|
|
25
27
|
* Absent = "category" (the pre-brand shape) — optional so pre-7.3 POIPhraseLookup implementors stay
|
|
26
28
|
* source-compatible.
|
|
27
29
|
*/
|
|
28
|
-
kind?: "category" | "brand";
|
|
30
|
+
kind?: "category" | "brand" | "name";
|
|
29
31
|
/**
|
|
30
32
|
* Wikidata QID, when known. `kind: "brand"` only — absent when a brand resolved by name alone (no QID match).
|
|
31
33
|
*/
|
|
32
34
|
wikidata?: string;
|
|
35
|
+
/**
|
|
36
|
+
* Whether this hit is one member of a set the caller must search TOGETHER, rather than one candidate in a preference
|
|
37
|
+
* list.
|
|
38
|
+
*
|
|
39
|
+
* A lookup returning several hits means two different things, and the difference decides whether narrowing to the
|
|
40
|
+
* first is an answer or an invented ordering. A phrase index returns the categories one typed phrase could name, the
|
|
41
|
+
* curated reading first (`credit union` → the `bank` rollup its synonym redirects to, then the standalone
|
|
42
|
+
* `credit_union` category), and the first entry IS the subject. An affordance rung returns every entity kind that
|
|
43
|
+
* affords ONE activity, in a stable enumeration that is not a preference, and taking the first picks a winner nobody
|
|
44
|
+
* authored.
|
|
45
|
+
*
|
|
46
|
+
* Set on every member of such a set. {@link matchPOISubject} then carries them all, the POI branch searches their
|
|
47
|
+
* union, and the candidate ordering the resolver already owns decides the answer. Absent — the committed lexicon's
|
|
48
|
+
* shape — keeps the first-hit reading unchanged.
|
|
49
|
+
*/
|
|
50
|
+
searchAsSet?: boolean;
|
|
51
|
+
/**
|
|
52
|
+
* ISO 3166-1 alpha-2 countries the authority behind this hit scopes its claim to. Absent = the claim holds
|
|
53
|
+
* everywhere.
|
|
54
|
+
*
|
|
55
|
+
* A scope is a statement about ESTABLISHMENTS, so it is judged against the country of the place being searched, not
|
|
56
|
+
* the caller's locale: the locale is the lens the phrase is read through, and it says nothing about where the claim
|
|
57
|
+
* holds. `matchPOISubject` carries the value untouched; the POI intent stage binds it once the anchor has resolved.
|
|
58
|
+
*/
|
|
59
|
+
countryScope?: readonly string[];
|
|
33
60
|
}
|
|
34
61
|
/**
|
|
35
62
|
* Injected phrase→category lookup. Exact-phrase, locale-aware; returns [] on miss.
|
|
36
63
|
*/
|
|
37
64
|
export type POIPhraseLookup = (phrase: string, locale?: string) => ReadonlyArray<POIPhraseMatch>;
|
|
65
|
+
export type POISpatialRelation = "comma" | "near" | "in" | "at" | "around" | "to";
|
|
66
|
+
export interface POIQuerySpan {
|
|
67
|
+
text: string;
|
|
68
|
+
/**
|
|
69
|
+
* Half-open character offsets into the normalized input.
|
|
70
|
+
*/
|
|
71
|
+
start: number;
|
|
72
|
+
end: number;
|
|
73
|
+
}
|
|
38
74
|
/**
|
|
39
75
|
* Which lexicon this hit came from. Existing category lookups set `"category"` (backward-compatible default).
|
|
40
76
|
*/
|
|
41
77
|
export interface POISubjectMatch {
|
|
78
|
+
/**
|
|
79
|
+
* The hit the subject SCORES under — its kind and its confidence. Always `matches[0]`; the two are built together in
|
|
80
|
+
* one place so they cannot disagree.
|
|
81
|
+
*/
|
|
42
82
|
match: POIPhraseMatch;
|
|
83
|
+
/**
|
|
84
|
+
* Every category the subject reaches, `match` first.
|
|
85
|
+
*
|
|
86
|
+
* One entry unless the lookup returned a {@link POIPhraseMatch.searchAsSet} set, in which case it holds the whole set
|
|
87
|
+
* and the POI branch searches their union. The order is the order the lookup returned and states no preference:
|
|
88
|
+
* nothing downstream may read position as rank.
|
|
89
|
+
*/
|
|
90
|
+
matches: POIPhraseMatch[];
|
|
43
91
|
/**
|
|
44
92
|
* The matched subject text as it appeared in the query.
|
|
45
93
|
*/
|
|
46
94
|
subject: string;
|
|
95
|
+
subjectSpan: POIQuerySpan;
|
|
96
|
+
/**
|
|
97
|
+
* The relation crossing from the subject span to the anchor span.
|
|
98
|
+
*/
|
|
99
|
+
relation?: POISpatialRelation;
|
|
100
|
+
relationSpan?: POIQuerySpan;
|
|
47
101
|
/**
|
|
48
102
|
* The anchor remainder after the separator; `""` when the whole input matched.
|
|
49
103
|
*/
|
|
50
104
|
remainder: string;
|
|
105
|
+
anchorSpan?: POIQuerySpan;
|
|
51
106
|
}
|
|
52
107
|
/**
|
|
53
108
|
* Match a POI subject: the whole input, or the text before the FIRST anchor separator WHOSE PREFIX HITS THE LEXICON (≤
|
|
54
|
-
*
|
|
109
|
+
* 8 tokens). Scans separator occurrences left-to-right — a lexicon phrase may itself contain a bare separator word
|
|
55
110
|
* (e.g. "walk in clinic"), so the first separator isn't necessarily the right split point. Returns null when the
|
|
56
111
|
* lexicon never fires — including comma-ridden full addresses whose leading segment isn't a lexicon phrase.
|
|
112
|
+
*
|
|
113
|
+
* The winning candidate's hits are carried per {@link reachedMatches}: the first hit, or the whole set when the lookup
|
|
114
|
+
* declared one.
|
|
57
115
|
*/
|
|
58
116
|
export declare function matchPOISubject(text: string, locale: string | undefined, lookup: POIPhraseLookup): POISubjectMatch | null;
|
|
59
117
|
/**
|
|
@@ -75,7 +133,7 @@ export declare function createScorePOIQuery(lookup: POIPhraseLookup, locale?: st
|
|
|
75
133
|
export declare function createScorePOICategory(lookup: POIPhraseLookup, locale?: string): (input: NormalizedInputLite, shape: QueryShapeLike) => number;
|
|
76
134
|
/**
|
|
77
135
|
* The whole-input category hit behind a `poi_category` verdict, for the marker's evidence. `null` when the input is not
|
|
78
|
-
* a bare category — same
|
|
136
|
+
* a bare category — same conditions as {@link createScorePOICategory}, so the two cannot disagree.
|
|
79
137
|
*/
|
|
80
138
|
export declare function matchPOICategory(text: string, locale: string | undefined, lookup: POIPhraseLookup): POIPhraseMatch | null;
|
|
81
139
|
//# sourceMappingURL=poi.d.ts.map
|
package/out/poi.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"poi.d.ts","sourceRoot":"","sources":["../poi.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,mBAAmB,EAAE,cAAc,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"poi.d.ts","sourceRoot":"","sources":["../lib/poi.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,mBAAmB,EAAE,cAAc,EAAE,MAAM,QAAQ,CAAA;AAQjE;;GAEG;AACH,MAAM,WAAW,cAAc;IAC9B;;;;OAIG;IACH,UAAU,EAAE,MAAM,CAAA;IAClB,aAAa,EAAE,MAAM,CAAA;IACrB,UAAU,EAAE,MAAM,CAAA;IAClB,SAAS,CAAC,EAAE,OAAO,GAAG,mBAAmB,GAAG,MAAM,CAAA;IAClD,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB;;;OAGG;IACH,IAAI,CAAC,EAAE,UAAU,GAAG,OAAO,GAAG,MAAM,CAAA;IACpC;;OAEG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB;;;;;;;;;;;;;;OAcG;IACH,WAAW,CAAC,EAAE,OAAO,CAAA;IACrB;;;;;;;OAOG;IACH,YAAY,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;CAChC;AAED;;GAEG;AACH,MAAM,MAAM,eAAe,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,KAAK,aAAa,CAAC,cAAc,CAAC,CAAA;AAEhG,MAAM,MAAM,kBAAkB,GAAG,OAAO,GAAG,MAAM,GAAG,IAAI,GAAG,IAAI,GAAG,QAAQ,GAAG,IAAI,CAAA;AAEjF,MAAM,WAAW,YAAY;IAC5B,IAAI,EAAE,MAAM,CAAA;IACZ;;OAEG;IACH,KAAK,EAAE,MAAM,CAAA;IACb,GAAG,EAAE,MAAM,CAAA;CACX;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC/B;;;OAGG;IACH,KAAK,EAAE,cAAc,CAAA;IACrB;;;;;;OAMG;IACH,OAAO,EAAE,cAAc,EAAE,CAAA;IACzB;;OAEG;IACH,OAAO,EAAE,MAAM,CAAA;IACf,WAAW,EAAE,YAAY,CAAA;IACzB;;OAEG;IACH,QAAQ,CAAC,EAAE,kBAAkB,CAAA;IAC7B,YAAY,CAAC,EAAE,YAAY,CAAA;IAC3B;;OAEG;IACH,SAAS,EAAE,MAAM,CAAA;IACjB,UAAU,CAAC,EAAE,YAAY,CAAA;CACzB;AAuCD;;;;;;;;GAQG;AACH,wBAAgB,eAAe,CAC9B,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM,GAAG,SAAS,EAC1B,MAAM,EAAE,eAAe,GACrB,eAAe,GAAG,IAAI,CAoExB;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAClC,MAAM,EAAE,eAAe,EACvB,MAAM,CAAC,EAAE,MAAM,GACb,CAAC,KAAK,EAAE,mBAAmB,EAAE,KAAK,EAAE,cAAc,KAAK,MAAM,CAiB/D;AAUD;;;;;;;;GAQG;AACH,wBAAgB,sBAAsB,CACrC,MAAM,EAAE,eAAe,EACvB,MAAM,CAAC,EAAE,MAAM,GACb,CAAC,KAAK,EAAE,mBAAmB,EAAE,KAAK,EAAE,cAAc,KAAK,MAAM,CAU/D;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAC/B,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM,GAAG,SAAS,EAC1B,MAAM,EAAE,eAAe,GACrB,cAAc,GAAG,IAAI,CAQvB"}
|
package/out/poi.js
CHANGED
|
@@ -14,8 +14,8 @@
|
|
|
14
14
|
*/
|
|
15
15
|
const MAX_POI_SEGMENTS = 3;
|
|
16
16
|
/**
|
|
17
|
-
* Anchor separator between subject and place: comma, or near/in/at/around — scanned left-to-right until a prefix
|
|
18
|
-
* the lexicon.
|
|
17
|
+
* Anchor separator between subject and place: comma, or near/in/at/around/to — scanned left-to-right until a prefix
|
|
18
|
+
* hits the lexicon.
|
|
19
19
|
*
|
|
20
20
|
* Linear by construction (no polynomial ReDoS): neither alternative places an unbounded whitespace quantifier _before_
|
|
21
21
|
* its required literal — the classic `\s*`/`\s+`-then-literal backtracking shape that CodeQL's `js/polynomial-redos`
|
|
@@ -31,37 +31,88 @@ const MAX_POI_SEGMENTS = 3;
|
|
|
31
31
|
* lastIndex) identical, preserving the exact subsequent-match sequence. Verified: 0 divergences across 22.7k inputs
|
|
32
32
|
* (systematic + fuzzed adversarial whitespace + shared-whitespace anchor/comma chains).
|
|
33
33
|
*/
|
|
34
|
-
const ANCHOR_SEPARATOR = /,\s*|\s(
|
|
34
|
+
const ANCHOR_SEPARATOR = /,\s*|\s(near|in|at|around|to)\s+/gi;
|
|
35
35
|
/**
|
|
36
|
-
* Longest subject we accept, in tokens.
|
|
36
|
+
* Longest subject we accept, in tokens. Eight covers compound taxonomy phrases while bounding lexicon probes.
|
|
37
37
|
*/
|
|
38
|
-
const MAX_SUBJECT_TOKENS =
|
|
38
|
+
const MAX_SUBJECT_TOKENS = 8;
|
|
39
|
+
/**
|
|
40
|
+
* The categories one candidate subject reaches, from the hits the lookup returned for it.
|
|
41
|
+
*
|
|
42
|
+
* The whole array when the first hit declares {@link POIPhraseMatch.searchAsSet} — carried as the lookup returned it,
|
|
43
|
+
* never filtered, so a rung that flagged only some of its members loses nothing here and the inconsistency stays
|
|
44
|
+
* visible to whoever reads the set. Otherwise the first hit alone, which is the preference-list reading the committed
|
|
45
|
+
* phrase index has always had.
|
|
46
|
+
*/
|
|
47
|
+
function reachedMatches(hits) {
|
|
48
|
+
return hits[0].searchAsSet ? [...hits] : [hits[0]];
|
|
49
|
+
}
|
|
39
50
|
/**
|
|
40
51
|
* Match a POI subject: the whole input, or the text before the FIRST anchor separator WHOSE PREFIX HITS THE LEXICON (≤
|
|
41
|
-
*
|
|
52
|
+
* 8 tokens). Scans separator occurrences left-to-right — a lexicon phrase may itself contain a bare separator word
|
|
42
53
|
* (e.g. "walk in clinic"), so the first separator isn't necessarily the right split point. Returns null when the
|
|
43
54
|
* lexicon never fires — including comma-ridden full addresses whose leading segment isn't a lexicon phrase.
|
|
55
|
+
*
|
|
56
|
+
* The winning candidate's hits are carried per {@link reachedMatches}: the first hit, or the whole set when the lookup
|
|
57
|
+
* declared one.
|
|
44
58
|
*/
|
|
45
59
|
export function matchPOISubject(text, locale, lookup) {
|
|
46
60
|
const trimmed = text.trim();
|
|
61
|
+
const inputStart = text.indexOf(trimmed);
|
|
47
62
|
if (!trimmed)
|
|
48
63
|
return null;
|
|
49
64
|
const whole = lookup(trimmed, locale);
|
|
50
65
|
if (whole.length) {
|
|
51
|
-
|
|
66
|
+
const matches = reachedMatches(whole);
|
|
67
|
+
return {
|
|
68
|
+
match: matches[0],
|
|
69
|
+
matches,
|
|
70
|
+
subject: trimmed,
|
|
71
|
+
subjectSpan: { text: trimmed, start: inputStart, end: inputStart + trimmed.length },
|
|
72
|
+
remainder: "",
|
|
73
|
+
};
|
|
52
74
|
}
|
|
53
75
|
for (const separator of trimmed.matchAll(ANCHOR_SEPARATOR)) {
|
|
54
76
|
if (separator.index === 0)
|
|
55
77
|
continue;
|
|
56
78
|
const subject = trimmed.slice(0, separator.index).trim();
|
|
57
|
-
// Subjects only grow as the scan moves right — once over budget, later splits are too.
|
|
79
|
+
// Subjects only grow as the scan moves right — once over budget, later splits are too. Whitespace-only
|
|
80
|
+
// split, not `wordsOf`: a comma inside a subject is real content here, not a separator to erase.
|
|
58
81
|
if (subject.split(/\s+/).length > MAX_SUBJECT_TOKENS)
|
|
59
82
|
break;
|
|
60
83
|
const hits = lookup(subject, locale);
|
|
61
84
|
if (!hits.length)
|
|
62
85
|
continue;
|
|
63
86
|
const remainder = trimmed.slice(separator.index + separator[0].length).trim();
|
|
64
|
-
|
|
87
|
+
if (!remainder)
|
|
88
|
+
continue;
|
|
89
|
+
const subjectOffset = trimmed.slice(0, separator.index).indexOf(subject);
|
|
90
|
+
const anchorOffset = trimmed.indexOf(remainder, separator.index + separator[0].length);
|
|
91
|
+
const relationText = separator[1] ?? ",";
|
|
92
|
+
const relationOffset = separator[1] ? separator.index + separator[0].indexOf(separator[1]) : separator.index;
|
|
93
|
+
const matches = reachedMatches(hits);
|
|
94
|
+
return {
|
|
95
|
+
match: matches[0],
|
|
96
|
+
matches,
|
|
97
|
+
subject,
|
|
98
|
+
subjectSpan: {
|
|
99
|
+
text: subject,
|
|
100
|
+
start: inputStart + subjectOffset,
|
|
101
|
+
end: inputStart + subjectOffset + subject.length,
|
|
102
|
+
},
|
|
103
|
+
relation: relationText === "," ? "comma" : relationText.toLowerCase(),
|
|
104
|
+
relationSpan: {
|
|
105
|
+
text: relationText,
|
|
106
|
+
start: inputStart + relationOffset,
|
|
107
|
+
end: inputStart + relationOffset + relationText.length,
|
|
108
|
+
},
|
|
109
|
+
remainder,
|
|
110
|
+
anchorSpan: {
|
|
111
|
+
text: remainder,
|
|
112
|
+
start: inputStart + anchorOffset,
|
|
113
|
+
end: inputStart + anchorOffset + remainder.length,
|
|
114
|
+
},
|
|
115
|
+
};
|
|
65
116
|
}
|
|
66
117
|
return null;
|
|
67
118
|
}
|
|
@@ -115,7 +166,7 @@ export function createScorePOICategory(lookup, locale) {
|
|
|
115
166
|
}
|
|
116
167
|
/**
|
|
117
168
|
* The whole-input category hit behind a `poi_category` verdict, for the marker's evidence. `null` when the input is not
|
|
118
|
-
* a bare category — same
|
|
169
|
+
* a bare category — same conditions as {@link createScorePOICategory}, so the two cannot disagree.
|
|
119
170
|
*/
|
|
120
171
|
export function matchPOICategory(text, locale, lookup) {
|
|
121
172
|
const matched = matchPOISubject(text, locale, lookup);
|
package/out/poi.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"poi.js","sourceRoot":"","sources":["../poi.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAIH;;;GAGG;AACH,MAAM,gBAAgB,GAAG,CAAC,CAAA;
|
|
1
|
+
{"version":3,"file":"poi.js","sourceRoot":"","sources":["../lib/poi.ts"],"names":[],"mappings":"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"}
|
package/out/rules.d.ts
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
* Bitter-lesson-safe: only universal structural patterns — no place-name dictionaries. ~1 small
|
|
10
10
|
* regex set per new locale, not 50K dictionary entries.
|
|
11
11
|
*/
|
|
12
|
-
import type { NormalizedInputLite, QueryShapeLike } from "
|
|
12
|
+
import type { NormalizedInputLite, QueryShapeLike } from "#types";
|
|
13
13
|
/**
|
|
14
14
|
* Longest input still plausible as a bare locality name, including a trailing region code.
|
|
15
15
|
*
|
|
@@ -33,10 +33,18 @@ export declare function scoreIntersection(input: NormalizedInputLite, _shape: Qu
|
|
|
33
33
|
*/
|
|
34
34
|
export declare function scoreLandmark(input: NormalizedInputLite, _shape: QueryShapeLike): number;
|
|
35
35
|
/**
|
|
36
|
-
*
|
|
37
|
-
*
|
|
36
|
+
* Split on whitespace + commas and drop empty words — the word grammar shared with `intent-rules.ts`. Dropping empties
|
|
37
|
+
* matters: a trailing comma or doubled separator otherwise yields an empty string that inflates the word count and
|
|
38
|
+
* falsifies every-word predicates like the proper-case check below.
|
|
38
39
|
*/
|
|
39
|
-
export declare
|
|
40
|
+
export declare function wordsOf(text: string): string[];
|
|
41
|
+
/**
|
|
42
|
+
* True when a word is USPS street-suffix vocabulary that unambiguously signals an address — the full Pub-28 table via
|
|
43
|
+
* `@mailwoman/codex`, minus its curated name-prone canonicals (PARK, FIELD, HILL, LAKE, …). Those double as ordinary
|
|
44
|
+
* proper-name heads ("Wrigley Field", "Menlo Park"), and disqualifying on them would reject the very venue and place
|
|
45
|
+
* names the rules below exist to capture. Shared with `intent-rules.ts` so both rule sets read one definition.
|
|
46
|
+
*/
|
|
47
|
+
export declare function isDisqualifyingStreetSuffix(word: string): boolean;
|
|
40
48
|
/**
|
|
41
49
|
* `landmark` rule (venue/named-place variant): short capitalized input with no street suffixes, no postcode hits, and
|
|
42
50
|
* no region abbreviations. Captures "Pier 39", "Empire State Building", "Wrigley Field", "Grand Central Terminal".
|
package/out/rules.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rules.d.ts","sourceRoot":"","sources":["../rules.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;
|
|
1
|
+
{"version":3,"file":"rules.d.ts","sourceRoot":"","sources":["../lib/rules.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAIH,OAAO,KAAK,EAAE,mBAAmB,EAAE,cAAc,EAAE,MAAM,QAAQ,CAAA;AAmBjE;;;;;;GAMG;AACH,eAAO,MAAM,wBAAwB,KAAK,CAAA;AAkD1C;;;GAGG;AACH,wBAAgB,UAAU,CAAC,MAAM,EAAE,mBAAmB,EAAE,KAAK,EAAE,cAAc,GAAG,MAAM,CAQrF;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,mBAAmB,EAAE,MAAM,EAAE,cAAc,GAAG,MAAM,CAQ5F;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,mBAAmB,EAAE,MAAM,EAAE,cAAc,GAAG,MAAM,CAQxF;AAED;;;;GAIG;AACH,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAE9C;AAED;;;;;GAKG;AACH,wBAAgB,2BAA2B,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAIjE;AAED;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,mBAAmB,EAAE,KAAK,EAAE,cAAc,GAAG,MAAM,CAkD5F;AAoBD;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAExD;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,mBAAmB,EAAE,KAAK,EAAE,cAAc,GAAG,MAAM,CAc3F;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,mBAAmB,EAAE,KAAK,EAAE,cAAc,GAAG,MAAM,CAe3F;AAED;;;GAGG;AACH,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,mBAAmB,EAAE,KAAK,EAAE,cAAc,GAAG,MAAM,CAmBhG;AAED;;;;;GAKG;AACH,wBAAgB,UAAU,CAAC,MAAM,EAAE,mBAAmB,EAAE,MAAM,EAAE,cAAc,GAAG,MAAM,CAEtF"}
|
package/out/rules.js
CHANGED
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
* Bitter-lesson-safe: only universal structural patterns — no place-name dictionaries. ~1 small
|
|
10
10
|
* regex set per new locale, not 50K dictionary entries.
|
|
11
11
|
*/
|
|
12
|
+
import { NAME_PRONE_US_SUFFIXES, US_STREET_SUFFIX_LOOKUP } from "@mailwoman/codex/us/street-suffix";
|
|
12
13
|
/**
|
|
13
14
|
* Longest input still plausible as a bare venue or landmark name. Beyond it the query is carrying an address as well,
|
|
14
15
|
* and belongs to the structured-address scorer.
|
|
@@ -109,34 +110,23 @@ export function scoreLandmark(input, _shape) {
|
|
|
109
110
|
return 0;
|
|
110
111
|
}
|
|
111
112
|
/**
|
|
112
|
-
*
|
|
113
|
-
*
|
|
113
|
+
* Split on whitespace + commas and drop empty words — the word grammar shared with `intent-rules.ts`. Dropping empties
|
|
114
|
+
* matters: a trailing comma or doubled separator otherwise yields an empty string that inflates the word count and
|
|
115
|
+
* falsifies every-word predicates like the proper-case check below.
|
|
114
116
|
*/
|
|
115
|
-
export
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
"ct",
|
|
129
|
-
"court",
|
|
130
|
-
"pl",
|
|
131
|
-
"place",
|
|
132
|
-
"way",
|
|
133
|
-
"pkwy",
|
|
134
|
-
"parkway",
|
|
135
|
-
"hwy",
|
|
136
|
-
"highway",
|
|
137
|
-
"cir",
|
|
138
|
-
"circle",
|
|
139
|
-
]);
|
|
117
|
+
export function wordsOf(text) {
|
|
118
|
+
return text.split(/[\s,]+/).filter((word) => word.length > 0);
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* True when a word is USPS street-suffix vocabulary that unambiguously signals an address — the full Pub-28 table via
|
|
122
|
+
* `@mailwoman/codex`, minus its curated name-prone canonicals (PARK, FIELD, HILL, LAKE, …). Those double as ordinary
|
|
123
|
+
* proper-name heads ("Wrigley Field", "Menlo Park"), and disqualifying on them would reject the very venue and place
|
|
124
|
+
* names the rules below exist to capture. Shared with `intent-rules.ts` so both rule sets read one definition.
|
|
125
|
+
*/
|
|
126
|
+
export function isDisqualifyingStreetSuffix(word) {
|
|
127
|
+
const canonical = US_STREET_SUFFIX_LOOKUP.get(word.trim().toLowerCase());
|
|
128
|
+
return canonical !== undefined && !NAME_PRONE_US_SUFFIXES.has(canonical);
|
|
129
|
+
}
|
|
140
130
|
/**
|
|
141
131
|
* `landmark` rule (venue/named-place variant): short capitalized input with no street suffixes, no postcode hits, and
|
|
142
132
|
* no region abbreviations. Captures "Pier 39", "Empire State Building", "Wrigley Field", "Grand Central Terminal".
|
|
@@ -159,10 +149,10 @@ export function scoreVenueLandmark(input, shape) {
|
|
|
159
149
|
const segCount = shape.segments?.length ?? 1;
|
|
160
150
|
if (segCount > 2)
|
|
161
151
|
return 0;
|
|
162
|
-
// Reject if any word is
|
|
163
|
-
const words = text
|
|
152
|
+
// Reject if any word is an unambiguous street suffix.
|
|
153
|
+
const words = wordsOf(text);
|
|
164
154
|
for (const w of words) {
|
|
165
|
-
if (
|
|
155
|
+
if (isDisqualifyingStreetSuffix(w))
|
|
166
156
|
return 0;
|
|
167
157
|
}
|
|
168
158
|
// Reject if the first token is a pure number (house-number-leading pattern).
|
|
@@ -199,6 +189,10 @@ const POSTCODE_FORMATS = new Set([
|
|
|
199
189
|
"ca_postcode",
|
|
200
190
|
"jp_postcode",
|
|
201
191
|
"nl_postcode",
|
|
192
|
+
"cz_postcode",
|
|
193
|
+
"sk_postcode",
|
|
194
|
+
"se_postcode",
|
|
195
|
+
"gr_postcode",
|
|
202
196
|
]);
|
|
203
197
|
/**
|
|
204
198
|
* Test whether a format string is a postcode variant. Use the set rather than ad-hoc string-matching to avoid the
|
package/out/rules.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rules.js","sourceRoot":"","sources":["../rules.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;
|
|
1
|
+
{"version":3,"file":"rules.js","sourceRoot":"","sources":["../lib/rules.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,sBAAsB,EAAE,uBAAuB,EAAE,MAAM,mCAAmC,CAAA;AAInG;;;GAGG;AACH,MAAM,mBAAmB,GAAG,EAAE,CAAA;AAE9B;;GAEG;AACH,MAAM,wBAAwB,GAAG,EAAE,CAAA;AAEnC;;;GAGG;AACH,MAAM,qBAAqB,GAAG,GAAG,CAAA;AAEjC;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,wBAAwB,GAAG,EAAE,CAAA;AAE1C;;;GAGG;AACH,MAAM,sBAAsB,GAAG,CAAC,CAAA;AAEhC;;GAEG;AACH,MAAM,sBAAsB,GAAG,CAAC,CAAA;AAEhC;;GAEG;AACH,MAAM,2BAA2B,GAAG,CAAC,CAAA;AAErC;;;GAGG;AACH,MAAM,gCAAgC,GAAG,EAAE,CAAA;AAE3C;;GAEG;AACH,MAAM,gBAAgB,GAAG;IACxB,QAAQ;IACR,MAAM;IACN,aAAa;IACb,UAAU;IACV,SAAS;IACT,QAAQ;IACR,aAAa;IACb,UAAU;IACV,QAAQ;CACR,CAAA;AAED;;GAEG;AACH,MAAM,qBAAqB,GAAG;IAC7B,gBAAgB;IAChB,sBAAsB;IACtB,uBAAuB;IACvB,oCAAoC;IACpC,6FAA6F;CAC7F,CAAA;AAED;;;GAGG;AACH,MAAM,UAAU,UAAU,CAAC,MAA2B,EAAE,KAAqB;IAC5E,MAAM,GAAG,GAAG,KAAK,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAA;IAEjE,IAAI,CAAC,GAAG;QAAE,OAAO,CAAC,CAAA;IAElB,+FAA+F;IAC/F,qCAAqC;IACrC,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,GAAG,CAAC,UAAU,GAAG,GAAG,CAAC,CAAA;AACzC,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,iBAAiB,CAAC,KAA0B,EAAE,MAAsB;IACnF,MAAM,IAAI,GAAG,KAAK,CAAC,UAAU,CAAA;IAE7B,KAAK,MAAM,OAAO,IAAI,qBAAqB,EAAE,CAAC;QAC7C,IAAI,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC;YAAE,OAAO,IAAI,CAAA;IACpC,CAAC;IAED,OAAO,CAAC,CAAA;AACT,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,aAAa,CAAC,KAA0B,EAAE,MAAsB;IAC/E,MAAM,EAAE,GAAG,KAAK,CAAC,UAAU,CAAC,WAAW,EAAE,CAAC,IAAI,EAAE,CAAA;IAEhD,KAAK,MAAM,MAAM,IAAI,gBAAgB,EAAE,CAAC;QACvC,IAAI,EAAE,CAAC,UAAU,CAAC,MAAM,GAAG,GAAG,CAAC,IAAI,EAAE,KAAK,MAAM;YAAE,OAAO,GAAG,CAAA;IAC7D,CAAC;IAED,OAAO,CAAC,CAAA;AACT,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,OAAO,CAAC,IAAY;IACnC,OAAO,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAA;AAC9D,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,2BAA2B,CAAC,IAAY;IACvD,MAAM,SAAS,GAAG,uBAAuB,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,CAAA;IAExE,OAAO,SAAS,KAAK,SAAS,IAAI,CAAC,sBAAsB,CAAC,GAAG,CAAC,SAAS,CAAC,CAAA;AACzE,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,kBAAkB,CAAC,KAA0B,EAAE,KAAqB;IACnF,MAAM,IAAI,GAAG,KAAK,CAAC,UAAU,CAAC,IAAI,EAAE,CAAA;IACpC,MAAM,GAAG,GAAG,IAAI,CAAC,MAAM,CAAA;IAEvB,IAAI,GAAG,KAAK,CAAC,IAAI,GAAG,GAAG,mBAAmB;QAAE,OAAO,CAAC,CAAA;IAEpD,2CAA2C;IAC3C,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC;QAAE,OAAO,CAAC,CAAA;IAEjC,kDAAkD;IAClD,IAAI,KAAK,CAAC,YAAY,CAAC,MAAM;QAAE,OAAO,CAAC,CAAA;IAEvC,6EAA6E;IAC7E,MAAM,QAAQ,GAAG,KAAK,CAAC,QAAQ,EAAE,MAAM,IAAI,CAAC,CAAA;IAE5C,IAAI,QAAQ,GAAG,CAAC;QAAE,OAAO,CAAC,CAAA;IAE1B,sDAAsD;IACtD,MAAM,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IAE3B,KAAK,MAAM,CAAC,IAAI,KAAK,EAAE,CAAC;QACvB,IAAI,2BAA2B,CAAC,CAAC,CAAC;YAAE,OAAO,CAAC,CAAA;IAC7C,CAAC;IAED,6EAA6E;IAC7E,IAAI,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC;QAAE,OAAO,CAAC,CAAA;IAEjC,2FAA2F;IAC3F,MAAM,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;IAEjE,mEAAmE;IACnE,MAAM,aAAa,GAAG,KAAK,CAAC,MAAM,GAAG,CAAC,IAAI,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAA;IAE9E,kEAAkE;IAClE,MAAM,SAAS,GAAG,KAAK,CAAC,MAAM,CAAA;IAE9B,IAAI,SAAS,IAAI,sBAAsB,IAAI,SAAS,IAAI,sBAAsB,IAAI,QAAQ,KAAK,CAAC,EAAE,CAAC;QAClG,IAAI,iBAAiB;YAAE,OAAO,IAAI,CAAA;QAElC,IAAI,aAAa;YAAE,OAAO,IAAI,CAAA;QAE9B,OAAO,IAAI,CAAA;IACZ,CAAC;IAED,qEAAqE;IACrE,IAAI,SAAS,IAAI,2BAA2B,IAAI,QAAQ,KAAK,CAAC,IAAI,aAAa,EAAE,CAAC;QACjF,OAAO,IAAI,CAAA;IACZ,CAAC;IAED,OAAO,CAAC,CAAA;AACT,CAAC;AAED;;GAEG;AACH,MAAM,gBAAgB,GAAwB,IAAI,GAAG,CAAC;IACrD,QAAQ;IACR,SAAS;IACT,aAAa;IACb,aAAa;IACb,aAAa;IACb,aAAa;IACb,aAAa;IACb,aAAa;IACb,aAAa;IACb,aAAa;IACb,aAAa;IACb,aAAa;CACb,CAAC,CAAA;AAEF;;;GAGG;AACH,MAAM,UAAU,gBAAgB,CAAC,MAAc;IAC9C,OAAO,gBAAgB,CAAC,GAAG,CAAC,MAAM,CAAC,CAAA;AACpC,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,iBAAiB,CAAC,KAA0B,EAAE,KAAqB;IAClF,MAAM,GAAG,GAAG,KAAK,CAAC,UAAU,CAAC,MAAM,CAAA;IAEnC,IAAI,GAAG,KAAK,CAAC,IAAI,GAAG,GAAG,wBAAwB;QAAE,OAAO,CAAC,CAAA;IACzD,MAAM,WAAW,GAAG,KAAK,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,gBAAgB,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAA;IAE9E,IAAI,CAAC,WAAW;QAAE,OAAO,CAAC,CAAA;IAC1B,MAAM,MAAM,GAAG,WAAW,CAAC,IAAI,CAAC,GAAG,GAAG,WAAW,CAAC,IAAI,CAAC,KAAK,CAAA;IAE5D,mFAAmF;IACnF,IAAI,MAAM,GAAG,GAAG,GAAG,qBAAqB;QAAE,OAAO,CAAC,CAAA;IAElD,qGAAqG;IACrG,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,WAAW,CAAC,UAAU,GAAG,CAAC,MAAM,GAAG,GAAG,CAAC,GAAG,GAAG,CAAC,CAAA;AAClE,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,iBAAiB,CAAC,KAA0B,EAAE,KAAqB;IAClF,MAAM,GAAG,GAAG,KAAK,CAAC,UAAU,CAAC,MAAM,CAAA;IAEnC,IAAI,GAAG,KAAK,CAAC,IAAI,GAAG,GAAG,wBAAwB;QAAE,OAAO,CAAC,CAAA;IAEzD,IAAI,KAAK,CAAC,cAAc,KAAK,OAAO;QAAE,OAAO,CAAC,CAAA;IAE9C,IAAI,KAAK,CAAC,YAAY,CAAC,MAAM;QAAE,OAAO,CAAC,CAAA;IACvC,qGAAqG;IACrG,6DAA6D;IAC7D,MAAM,QAAQ,GAAG,KAAK,CAAC,QAAQ,EAAE,MAAM,IAAI,CAAC,CAAA;IAE5C,IAAI,QAAQ,GAAG,CAAC;QAAE,OAAO,CAAC,CAAA;IAE1B,OAAO,IAAI,CAAA;AACZ,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,sBAAsB,CAAC,KAA0B,EAAE,KAAqB;IACvF,MAAM,GAAG,GAAG,KAAK,CAAC,UAAU,CAAC,MAAM,CAAA;IAEnC,IAAI,GAAG,KAAK,CAAC;QAAE,OAAO,CAAC,CAAA;IACvB,MAAM,QAAQ,GAAG,KAAK,CAAC,QAAQ,EAAE,MAAM,IAAI,CAAC,CAAA;IAE5C,+EAA+E;IAC/E,IAAI,QAAQ,IAAI,CAAC,IAAI,KAAK,CAAC,cAAc,KAAK,cAAc;QAAE,OAAO,GAAG,CAAA;IAExE,6EAA6E;IAC7E,IAAI,GAAG,IAAI,gCAAgC,IAAI,KAAK,CAAC,cAAc,KAAK,cAAc;QAAE,OAAO,IAAI,CAAA;IAEnG,4EAA4E;IAC5E,IAAI,QAAQ,IAAI,CAAC;QAAE,OAAO,GAAG,CAAA;IAE7B,wFAAwF;IACxF,IAAI,GAAG,GAAG,gCAAgC,IAAI,KAAK,CAAC,cAAc,KAAK,cAAc;QAAE,OAAO,GAAG,CAAA;IAEjG,OAAO,CAAC,CAAA;AACT,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,UAAU,CAAC,MAA2B,EAAE,MAAsB;IAC7E,OAAO,GAAG,CAAA;AACX,CAAC"}
|
package/out/types.d.ts
CHANGED
|
@@ -9,30 +9,8 @@
|
|
|
9
9
|
export type { LocaleHint, QueryIntentMarker, QueryKind, QueryKindResult } from "@mailwoman/core/pipeline";
|
|
10
10
|
export { QueryIntentCode } from "@mailwoman/core/pipeline";
|
|
11
11
|
/**
|
|
12
|
-
*
|
|
12
|
+
* The minimal input shapes consumed by `classifyKind` come from `@mailwoman/query-shape` — one declaration shared by
|
|
13
|
+
* every Stage-2.x consumer. `QueryShapeLike` stays this package's public name for its narrow read-only view.
|
|
13
14
|
*/
|
|
14
|
-
export
|
|
15
|
-
raw: string;
|
|
16
|
-
normalized: string;
|
|
17
|
-
appliedLocale?: string;
|
|
18
|
-
}
|
|
19
|
-
/**
|
|
20
|
-
* Minimal `QueryShape` shape consumed by `classifyKind`. Compatible with `@mailwoman/query-shape`'s output.
|
|
21
|
-
*/
|
|
22
|
-
export interface QueryShapeLike {
|
|
23
|
-
knownFormats: ReadonlyArray<{
|
|
24
|
-
format: string;
|
|
25
|
-
span: {
|
|
26
|
-
start: number;
|
|
27
|
-
end: number;
|
|
28
|
-
};
|
|
29
|
-
confidence: number;
|
|
30
|
-
}>;
|
|
31
|
-
segments?: ReadonlyArray<{
|
|
32
|
-
body: string;
|
|
33
|
-
index: number;
|
|
34
|
-
}>;
|
|
35
|
-
characterClass?: string;
|
|
36
|
-
totalLength?: number;
|
|
37
|
-
}
|
|
15
|
+
export type { NormalizedInputLite, QueryShapeSegmentsView as QueryShapeLike } from "@mailwoman/query-shape";
|
|
38
16
|
//# sourceMappingURL=types.d.ts.map
|