@mailwoman/codex 8.6.0 → 9.0.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.
Files changed (44) hide show
  1. package/README.md +1 -1
  2. package/ca/province.ts +2 -12
  3. package/country/subdivision.ts +1 -12
  4. package/fr/region.ts +2 -12
  5. package/gb/postcode-area.ts +10 -0
  6. package/index.ts +1 -0
  7. package/normalize.ts +53 -0
  8. package/nz/delivery-service.ts +17 -17
  9. package/nz/postcode.ts +4 -4
  10. package/out/ca/province.d.ts.map +1 -1
  11. package/out/ca/province.js +1 -11
  12. package/out/ca/province.js.map +1 -1
  13. package/out/country/subdivision.d.ts.map +1 -1
  14. package/out/country/subdivision.js +1 -11
  15. package/out/country/subdivision.js.map +1 -1
  16. package/out/fr/region.d.ts.map +1 -1
  17. package/out/fr/region.js +1 -11
  18. package/out/fr/region.js.map +1 -1
  19. package/out/gb/postcode-area.d.ts +9 -0
  20. package/out/gb/postcode-area.d.ts.map +1 -1
  21. package/out/gb/postcode-area.js +9 -0
  22. package/out/gb/postcode-area.js.map +1 -1
  23. package/out/index.d.ts +1 -0
  24. package/out/index.d.ts.map +1 -1
  25. package/out/index.js +1 -0
  26. package/out/index.js.map +1 -1
  27. package/out/normalize.d.ts +36 -0
  28. package/out/normalize.d.ts.map +1 -0
  29. package/out/normalize.js +51 -0
  30. package/out/normalize.js.map +1 -0
  31. package/out/nz/delivery-service.d.ts +10 -10
  32. package/out/nz/delivery-service.js +5 -5
  33. package/out/nz/postcode.d.ts +3 -3
  34. package/out/nz/postcode.js +2 -2
  35. package/out/postcode-systems.js +2 -2
  36. package/out/tools/build-country-surface-lexicon.js +2 -7
  37. package/out/tools/build-country-surface-lexicon.js.map +1 -1
  38. package/out/tools/generate-official-languages.d.ts.map +1 -1
  39. package/out/tools/generate-official-languages.js +4 -2
  40. package/out/tools/generate-official-languages.js.map +1 -1
  41. package/package.json +2 -2
  42. package/postcode-systems.ts +2 -2
  43. package/tools/build-country-surface-lexicon.ts +2 -10
  44. package/tools/generate-official-languages.ts +6 -1
package/README.md CHANGED
@@ -92,7 +92,7 @@ questions, different tables.
92
92
 
93
93
  - [`@mailwoman/core`](../core) — `ComponentTag` schema, pipeline infrastructure
94
94
  - [`@mailwoman/address-id`](../address-id) — uses codex for stable address primary keys
95
- - [Address system conventions](https://mailwoman.sister.software/articles/plan/reference/SCHEMA/)
95
+ - [Address system conventions](https://github.com/sister-software/mailwoman/blob/main/docs/engineering/reference/SCHEMA.mdx)
96
96
 
97
97
  ## License
98
98
 
package/ca/province.ts CHANGED
@@ -16,6 +16,8 @@
16
16
  * regions, the Canadian code IS a surface form, not just a resolver key.
17
17
  */
18
18
 
19
+ import { foldName } from "../normalize.ts"
20
+
19
21
  /**
20
22
  * Per-province record: ISO 3166-2:CA code, English name, and the co-official French name.
21
23
  */
@@ -68,18 +70,6 @@ export function isCanadianProvinceCode(input: unknown): input is CanadianProvinc
68
70
  return typeof input === "string" && PROVINCE_CODE_SET.has(input.toUpperCase())
69
71
  }
70
72
 
71
- /**
72
- * Strip diacritics + lowercase so `Québec`, `Quebec`, and `quebec` all key alike.
73
- */
74
- function foldName(s: string): string {
75
- return s
76
- .toLowerCase()
77
- .normalize("NFD")
78
- .replaceAll(/[\u0300-\u036F]/g, "")
79
- .replaceAll(/[^a-z0-9]+/g, " ")
80
- .trim()
81
- }
82
-
83
73
  /**
84
74
  * Folded province name (English or French) / code → ISO 3166-2:CA code. Built diacritic-insensitive so both co-official
85
75
  * names map regardless of accents: `Québec`, `Quebec`, and an unaccented `Nouvelle-Ecosse` all resolve. The two-name
@@ -27,6 +27,7 @@
27
27
  */
28
28
 
29
29
  import { CA_PROVINCES } from "../ca/province.ts"
30
+ import { foldName } from "../normalize.ts"
30
31
  import { US_STATE_BY_ABBREVIATION } from "../us/state.ts"
31
32
 
32
33
  /**
@@ -47,18 +48,6 @@ export interface SubdivisionMatch {
47
48
  country: string
48
49
  }
49
50
 
50
- /**
51
- * Strip diacritics + lowercase so `Québec`, `Quebec`, and `quebec` all key alike (mirrors `ca/province.ts`).
52
- */
53
- function foldName(s: string): string {
54
- return s
55
- .toLowerCase()
56
- .normalize("NFD")
57
- .replaceAll(/[\u0300-\u036F]/g, "")
58
- .replaceAll(/[^a-z0-9]+/g, " ")
59
- .trim()
60
- }
61
-
62
51
  /**
63
52
  * Folded surface form (ISO code, English name, or — for CA — co-official French name) → subdivision. Built once. US
64
53
  * states are inserted first and never overwritten, so on the (currently empty) event of a future code/name collision
package/fr/region.ts CHANGED
@@ -13,6 +13,8 @@
13
13
  * `code-postal.ts`).
14
14
  */
15
15
 
16
+ import { foldName } from "../normalize.ts"
17
+
16
18
  /**
17
19
  * Per-region record: ISO 3166-2:FR code (sans `FR-` prefix) + French name.
18
20
  */
@@ -65,18 +67,6 @@ export function isFrenchRegionCode(input: unknown): input is FrenchRegionCode {
65
67
  return typeof input === "string" && REGION_CODE_SET.has(input.toUpperCase())
66
68
  }
67
69
 
68
- /**
69
- * Strip diacritics + lowercase so `Île-de-France`, `ile-de-france`, `Ile de France` all key alike.
70
- */
71
- function foldName(s: string): string {
72
- return s
73
- .toLowerCase()
74
- .normalize("NFD")
75
- .replaceAll(/[\u0300-\u036F]/g, "")
76
- .replaceAll(/[^a-z0-9]+/g, " ")
77
- .trim()
78
- }
79
-
80
70
  /**
81
71
  * Folded region name / code → ISO 3166-2:FR code. Built diacritic-insensitive so the resolver's surface form
82
72
  * (`Île-de-France`, or an unaccented `Ile-de-France`) maps regardless of accents. Mirrors `de/bundesland.ts`'s
@@ -76,6 +76,16 @@ export const GB_POSTCODE_AREA_COUNTRY: Record<string, UkCountryCode> = {
76
76
  ...Object.fromEntries(WALES_AREAS.map((a) => [a, "WLS" as const])),
77
77
  }
78
78
 
79
+ /**
80
+ * The two postcode areas whose assignment in {@link GB_POSTCODE_AREA_COUNTRY} is a MAJORITY call rather than a fact —
81
+ * TD (Galashiels) straddles the Scotland/England border and SY (Shrewsbury) straddles the Wales/England border, and
82
+ * both carry real postcodes on the other side of the line. The header above documents them in prose; this is the same
83
+ * knowledge in a form a build can read, so an artifact that ASSERTS ancestry per postcode district can withhold the
84
+ * constituent country here instead of asserting a coin-flip. Consumers that only want the coarse majority answer keep
85
+ * using {@link countryOfPostcodeArea} and ignore this.
86
+ */
87
+ export const GB_BORDER_STRADDLING_AREAS: ReadonlySet<string> = new Set(["TD", "SY"])
88
+
79
89
  /**
80
90
  * True when `area` looks like a valid postcode-area string: one or two ASCII letters.
81
91
  */
package/index.ts CHANGED
@@ -27,6 +27,7 @@ export {
27
27
  type AddressSystemConventions,
28
28
  } from "./address-system-conventions.ts"
29
29
 
30
+ export * from "./normalize.ts"
30
31
  export * as au from "./au/index.ts"
31
32
  export * as ca from "./ca/index.ts"
32
33
  export * as de from "./de/index.ts"
package/normalize.ts ADDED
@@ -0,0 +1,53 @@
1
+ /**
2
+ * @copyright Sister Software
3
+ * @license AGPL-3.0
4
+ * @author Teffen Ellis, et al.
5
+ *
6
+ * Name-normalization primitives shared across the codex tables and the lexicon builders that read
7
+ * them.
8
+ *
9
+ * These live in `@mailwoman/codex` rather than in `core` or `normalize` for one reason: codex is
10
+ * the zero-runtime-dependency reference package, and everything that needs to match a name against
11
+ * a codex table already depends on it. Putting the folding rules next to the tables they fold
12
+ * means a lookup and its table can never disagree about what counts as the same name.
13
+ *
14
+ */
15
+
16
+ /**
17
+ * Fold a name to its ASCII match key: lower-cased, accents stripped, every run of non-alphanumerics collapsed to a
18
+ * single space.
19
+ *
20
+ * This is the aggressive fold used to match a user's surface form against a codex table — `"Québec"` and `"QUEBEC"` and
21
+ * `"quebec"` all become `"quebec"`. It is lossy by design and never used to render anything back to a user.
22
+ */
23
+ export function foldName(s: string): string {
24
+ return s
25
+ .toLowerCase()
26
+ .normalize("NFD")
27
+ .replaceAll(/[\u0300-\u036F]/g, "")
28
+ .replaceAll(/[^a-z0-9]+/g, " ")
29
+ .trim()
30
+ }
31
+
32
+ /**
33
+ * Strip leading and trailing punctuation from every whitespace-separated word, dropping words that were nothing but
34
+ * punctuation, and rejoin on single spaces.
35
+ *
36
+ * Unlike {@link foldName} this preserves case and non-Latin scripts — it works on Unicode letter and number classes, so
37
+ * `"Кыргызстан,"` and `"日本 。"` survive with their content intact. That is what makes it the right normalizer for
38
+ * building surface lexicons, where the entry has to remain renderable, and the wrong one for building a match key.
39
+ */
40
+ export function wordNorm(s: string): string {
41
+ return s
42
+ .split(/\s+/)
43
+ .map((w) => w.replaceAll(/^[^\p{L}\p{N}]+|[^\p{L}\p{N}]+$/gu, ""))
44
+ .filter(Boolean)
45
+ .join(" ")
46
+ }
47
+
48
+ /**
49
+ * {@link wordNorm}, lower-cased — the case-insensitive lexicon key.
50
+ */
51
+ export function wordNormLower(s: string): string {
52
+ return wordNorm(s).toLowerCase()
53
+ }
@@ -45,12 +45,12 @@
45
45
  /**
46
46
  * Identifier requirement per ADV358's Delivery Service Elements rules.
47
47
  */
48
- export type NzIdentifierRule = "required-if-allocated" | "optional" | "not-used"
48
+ export type NZIdentifierRule = "required-if-allocated" | "optional" | "not-used"
49
49
 
50
50
  /**
51
51
  * One Delivery Service Type row from ADV358.
52
52
  */
53
- export interface NzDeliveryServiceType {
53
+ export interface NZDeliveryServiceType {
54
54
  /**
55
55
  * The Delivery Service Type, verbatim casing per ADV358 ("PO Box", "Private Bag", "CMB").
56
56
  */
@@ -64,7 +64,7 @@ export interface NzDeliveryServiceType {
64
64
  * none ("not used … for Private Bags that do not have an identifier allocated by New Zealand Post"); Counter Delivery
65
65
  * and Poste Restante never carry one.
66
66
  */
67
- identifier: NzIdentifierRule
67
+ identifier: NZIdentifierRule
68
68
  }
69
69
 
70
70
  /**
@@ -89,12 +89,12 @@ export const NZ_DELIVERY_SERVICE_TYPES = [
89
89
  description: "Hold for Poste Restante collection - international mail",
90
90
  identifier: "not-used",
91
91
  },
92
- ] as const satisfies readonly NzDeliveryServiceType[]
92
+ ] as const satisfies readonly NZDeliveryServiceType[]
93
93
 
94
94
  /**
95
95
  * A canonical NZ Delivery Service Type.
96
96
  */
97
- export type NzDeliveryServiceTypeName = (typeof NZ_DELIVERY_SERVICE_TYPES)[number]["type"]
97
+ export type NZDeliveryServiceTypeName = (typeof NZ_DELIVERY_SERVICE_TYPES)[number]["type"]
98
98
 
99
99
  /**
100
100
  * Metadata for the colloquial "Private Box" alias (see the module header and operator ruling 2026-06-11). Kept separate
@@ -121,7 +121,7 @@ export const NZ_PRIVATE_BOX_ALIAS = {
121
121
  /**
122
122
  * Identifier rule mirrors PO Box: a number is expected when the alias is used with one.
123
123
  */
124
- identifier: "required-if-allocated" satisfies NzIdentifierRule,
124
+ identifier: "required-if-allocated" satisfies NZIdentifierRule,
125
125
  /**
126
126
  * True — this form is NOT valid per ADV358 or NZ Post's live standards pages (accessed 2026-06-11).
127
127
  */
@@ -136,7 +136,7 @@ export const NZ_PRIVATE_BOX_ALIAS = {
136
136
  * The colloquial "Private Box" alias is included for recognition (see {@link NZ_PRIVATE_BOX_ALIAS} and operator ruling
137
137
  * 2026-06-11); it maps to a distinct synthetic type string so callers can distinguish it from the ADV358 types.
138
138
  */
139
- const TYPE_PATTERNS: ReadonlyArray<readonly [NzDeliveryServiceTypeName | "Private Box", string]> = [
139
+ const TYPE_PATTERNS: ReadonlyArray<readonly [NZDeliveryServiceTypeName | "Private Box", string]> = [
140
140
  ["PO Box", String.raw`p\.?\s*o\.?\s*box|post\s+box`],
141
141
  ["Private Bag", String.raw`private\s+bag`],
142
142
  ["Private Box", String.raw`private\s+box`],
@@ -149,9 +149,9 @@ const TYPE_PATTERNS: ReadonlyArray<readonly [NzDeliveryServiceTypeName | "Privat
149
149
  /**
150
150
  * Extended type name union including the colloquial alias recognized for parsing.
151
151
  */
152
- export type NzDeliveryServiceMatchTypeName = NzDeliveryServiceTypeName | "Private Box"
152
+ export type NZDeliveryServiceMatchTypeName = NZDeliveryServiceTypeName | "Private Box"
153
153
 
154
- const IDENTIFIER_RULES = new Map<NzDeliveryServiceMatchTypeName, NzIdentifierRule>([
154
+ const IDENTIFIER_RULES = new Map<NZDeliveryServiceMatchTypeName, NZIdentifierRule>([
155
155
  ...NZ_DELIVERY_SERVICE_TYPES.map((t) => [t.type, t.identifier] as const),
156
156
  // "Private Box" mirrors PO Box identifier rules (required-if-allocated) per the alias metadata.
157
157
  ["Private Box", NZ_PRIVATE_BOX_ALIAS.identifier],
@@ -161,7 +161,7 @@ const IDENTIFIER_RULES = new Map<NzDeliveryServiceMatchTypeName, NzIdentifierRul
161
161
  * One anchored regex per type. The identifier shape follows ADV358 (alphanumeric, no spaces or separators — `24999`,
162
162
  * `B99`); the identifier-less counter services take no tail at all.
163
163
  */
164
- const MATCHERS: ReadonlyArray<{ type: NzDeliveryServiceMatchTypeName; re: RegExp }> = TYPE_PATTERNS.map(
164
+ const MATCHERS: ReadonlyArray<{ type: NZDeliveryServiceMatchTypeName; re: RegExp }> = TYPE_PATTERNS.map(
165
165
  ([type, src]) => {
166
166
  const rule = IDENTIFIER_RULES.get(type)!
167
167
  const tail = rule === "not-used" ? "" : String.raw`(?:\s+([\dA-Za-z]+))${rule === "optional" ? "?" : ""}`
@@ -173,7 +173,7 @@ const MATCHERS: ReadonlyArray<{ type: NzDeliveryServiceMatchTypeName; re: RegExp
173
173
  /**
174
174
  * Result of an NZ delivery-service parse.
175
175
  */
176
- export interface NzDeliveryServiceMatch {
176
+ export interface NZDeliveryServiceMatch {
177
177
  /**
178
178
  * The designator phrase as it appeared ("PO Box", "private bag", "Private Box").
179
179
  */
@@ -183,7 +183,7 @@ export interface NzDeliveryServiceMatch {
183
183
  * `type` is "Private Box", `colloquial` is true and `officiallyInvalid` is true — the form is not a valid ADV358
184
184
  * type.
185
185
  */
186
- type: NzDeliveryServiceMatchTypeName
186
+ type: NZDeliveryServiceMatchTypeName
187
187
  /**
188
188
  * The Delivery Service Identifier when present ("24999", "B99").
189
189
  */
@@ -204,7 +204,7 @@ export interface NzDeliveryServiceMatch {
204
204
  * Delivery Service Type; see {@link NZ_PRIVATE_BOX_ALIAS} and operator ruling 2026-06-11). Callers that want only
205
205
  * formally-valid ADV358 types should check `!result.colloquial`.
206
206
  */
207
- export function matchNzDeliveryService(input: unknown): NzDeliveryServiceMatch | null {
207
+ export function matchNZDeliveryService(input: unknown): NZDeliveryServiceMatch | null {
208
208
  if (typeof input !== "string") return null
209
209
 
210
210
  for (const { type, re } of MATCHERS) {
@@ -222,16 +222,16 @@ export function matchNzDeliveryService(input: unknown): NzDeliveryServiceMatch |
222
222
  /**
223
223
  * Type-predicate: does the input look like a standalone NZ delivery-service address line?
224
224
  */
225
- export function isNzDeliveryService(input: unknown): boolean {
226
- return matchNzDeliveryService(input) !== null
225
+ export function isNZDeliveryService(input: unknown): boolean {
226
+ return matchNZDeliveryService(input) !== null
227
227
  }
228
228
 
229
229
  /**
230
230
  * Normalize a recognized phrase to the ADV358 form (`"p.o. box 24999"` → `"PO Box 24999"`). Returns the input unchanged
231
231
  * if it isn't a delivery-service phrase.
232
232
  */
233
- export function normalizeNzDeliveryService(input: string): string {
234
- const m = matchNzDeliveryService(input)
233
+ export function normalizeNZDeliveryService(input: string): string {
234
+ const m = matchNZDeliveryService(input)
235
235
 
236
236
  if (!m) return input
237
237
 
package/nz/postcode.ts CHANGED
@@ -23,7 +23,7 @@ import type { Tagged } from "type-fest"
23
23
  * @title New Zealand postcode
24
24
  * @pattern ^\d{4}$
25
25
  */
26
- export type NzPostcode = Tagged<string, "NzPostcode">
26
+ export type NZPostcode = Tagged<string, "NZPostcode">
27
27
 
28
28
  /**
29
29
  * The NZ postcode shape: exactly four digits.
@@ -33,16 +33,16 @@ export const NZ_POSTCODE_PATTERN = /^\d{4}$/
33
33
  /**
34
34
  * Normalize a postcode surface form (trim only — NZ has no country-prefix courtesy form).
35
35
  */
36
- export function normalizeNzPostcode(raw: unknown): NzPostcode | null {
36
+ export function normalizeNZPostcode(raw: unknown): NZPostcode | null {
37
37
  if (typeof raw !== "string") return null
38
38
  const s = raw.trim()
39
39
 
40
- return NZ_POSTCODE_PATTERN.test(s) ? (s as NzPostcode) : null
40
+ return NZ_POSTCODE_PATTERN.test(s) ? (s as NZPostcode) : null
41
41
  }
42
42
 
43
43
  /**
44
44
  * Type-predicate for a (normalized) New Zealand postcode.
45
45
  */
46
- export function isNzPostcode(input: unknown): input is NzPostcode {
46
+ export function isNZPostcode(input: unknown): input is NZPostcode {
47
47
  return typeof input === "string" && NZ_POSTCODE_PATTERN.test(input)
48
48
  }
@@ -1 +1 @@
1
- {"version":3,"file":"province.d.ts","sourceRoot":"","sources":["../../ca/province.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACpC;;OAEG;IACH,IAAI,EAAE,MAAM,CAAA;IACZ;;OAEG;IACH,IAAI,EAAE,MAAM,CAAA;IACZ;;OAEG;IACH,MAAM,EAAE,MAAM,CAAA;CACd;AAED;;;GAGG;AACH,eAAO,MAAM,YAAY;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAcgC,CAAA;AAEzD;;GAEG;AACH,MAAM,MAAM,oBAAoB,GAAG,MAAM,OAAO,YAAY,CAAA;AAI5D;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,oBAAoB,CAEpF;AAcD;;;;;GAKG;AACH,eAAO,MAAM,wBAAwB,EAAE,WAAW,CAAC,MAAM,EAAE,oBAAoB,CAW3E,CAAA;AAEJ;;;GAGG;AACH,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,oBAAoB,GAAG,IAAI,CAOpG"}
1
+ {"version":3,"file":"province.d.ts","sourceRoot":"","sources":["../../ca/province.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAIH;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACpC;;OAEG;IACH,IAAI,EAAE,MAAM,CAAA;IACZ;;OAEG;IACH,IAAI,EAAE,MAAM,CAAA;IACZ;;OAEG;IACH,MAAM,EAAE,MAAM,CAAA;CACd;AAED;;;GAGG;AACH,eAAO,MAAM,YAAY;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAcgC,CAAA;AAEzD;;GAEG;AACH,MAAM,MAAM,oBAAoB,GAAG,MAAM,OAAO,YAAY,CAAA;AAI5D;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,oBAAoB,CAEpF;AAED;;;;;GAKG;AACH,eAAO,MAAM,wBAAwB,EAAE,WAAW,CAAC,MAAM,EAAE,oBAAoB,CAW3E,CAAA;AAEJ;;;GAGG;AACH,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,oBAAoB,GAAG,IAAI,CAOpG"}
@@ -15,6 +15,7 @@
15
15
  * is the abbreviation people actually write on the address line — so unlike German or French
16
16
  * regions, the Canadian code IS a surface form, not just a resolver key.
17
17
  */
18
+ import { foldName } from "../normalize.js";
18
19
  /**
19
20
  * ISO 3166-2:CA code → province/territory info, for all 13 subdivisions (10 provinces + 3 territories). Codes are the
20
21
  * official subdivision codes minus the `CA-` prefix.
@@ -41,17 +42,6 @@ const PROVINCE_CODE_SET = new Set(Object.keys(CA_PROVINCES));
41
42
  export function isCanadianProvinceCode(input) {
42
43
  return typeof input === "string" && PROVINCE_CODE_SET.has(input.toUpperCase());
43
44
  }
44
- /**
45
- * Strip diacritics + lowercase so `Québec`, `Quebec`, and `quebec` all key alike.
46
- */
47
- function foldName(s) {
48
- return s
49
- .toLowerCase()
50
- .normalize("NFD")
51
- .replaceAll(/[\u0300-\u036F]/g, "")
52
- .replaceAll(/[^a-z0-9]+/g, " ")
53
- .trim();
54
- }
55
45
  /**
56
46
  * Folded province name (English or French) / code → ISO 3166-2:CA code. Built diacritic-insensitive so both co-official
57
47
  * names map regardless of accents: `Québec`, `Quebec`, and an unaccented `Nouvelle-Ecosse` all resolve. The two-name
@@ -1 +1 @@
1
- {"version":3,"file":"province.js","sourceRoot":"","sources":["../../ca/province.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"province.js","sourceRoot":"","sources":["../../ca/province.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"subdivision.d.ts","sourceRoot":"","sources":["../../country/subdivision.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAKH;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAChC;;OAEG;IACH,IAAI,EAAE,MAAM,CAAA;IACZ;;OAEG;IACH,IAAI,EAAE,MAAM,CAAA;IACZ;;OAEG;IACH,OAAO,EAAE,MAAM,CAAA;CACf;AA8CD;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,gBAAgB,GAAG,IAAI,CAI1F"}
1
+ {"version":3,"file":"subdivision.d.ts","sourceRoot":"","sources":["../../country/subdivision.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAMH;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAChC;;OAEG;IACH,IAAI,EAAE,MAAM,CAAA;IACZ;;OAEG;IACH,IAAI,EAAE,MAAM,CAAA;IACZ;;OAEG;IACH,OAAO,EAAE,MAAM,CAAA;CACf;AAkCD;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,gBAAgB,GAAG,IAAI,CAI1F"}
@@ -26,18 +26,8 @@
26
26
  * re-keys those two existing tables into one subdivision→country view.
27
27
  */
28
28
  import { CA_PROVINCES } from "../ca/province.js";
29
+ import { foldName } from "../normalize.js";
29
30
  import { US_STATE_BY_ABBREVIATION } from "../us/state.js";
30
- /**
31
- * Strip diacritics + lowercase so `Québec`, `Quebec`, and `quebec` all key alike (mirrors `ca/province.ts`).
32
- */
33
- function foldName(s) {
34
- return s
35
- .toLowerCase()
36
- .normalize("NFD")
37
- .replaceAll(/[\u0300-\u036F]/g, "")
38
- .replaceAll(/[^a-z0-9]+/g, " ")
39
- .trim();
40
- }
41
31
  /**
42
32
  * Folded surface form (ISO code, English name, or — for CA — co-official French name) → subdivision. Built once. US
43
33
  * states are inserted first and never overwritten, so on the (currently empty) event of a future code/name collision
@@ -1 +1 @@
1
- {"version":3,"file":"subdivision.js","sourceRoot":"","sources":["../../country/subdivision.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAA;AAChD,OAAO,EAAE,wBAAwB,EAAE,MAAM,gBAAgB,CAAA;AAoBzD;;GAEG;AACH,SAAS,QAAQ,CAAC,CAAS;IAC1B,OAAO,CAAC;SACN,WAAW,EAAE;SACb,SAAS,CAAC,KAAK,CAAC;SAChB,UAAU,CAAC,kBAAkB,EAAE,EAAE,CAAC;SAClC,UAAU,CAAC,aAAa,EAAE,GAAG,CAAC;SAC9B,IAAI,EAAE,CAAA;AACT,CAAC;AAED;;;;GAIG;AACH,MAAM,kBAAkB,GAA0C,CAAC,GAAG,EAAE;IACvE,MAAM,GAAG,GAAG,IAAI,GAAG,EAA4B,CAAA;IAE/C,MAAM,GAAG,GAAG,CAAC,GAAW,EAAE,KAAuB,EAAQ,EAAE;QAC1D,MAAM,MAAM,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAA;QAE5B,IAAI,MAAM,CAAC,MAAM,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC;YACvC,GAAG,CAAC,GAAG,CAAC,MAAM,EAAE,KAAK,CAAC,CAAA;QACvB,CAAC;IACF,CAAC,CAAA;IAED,KAAK,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,wBAAwB,CAAC,EAAE,CAAC;QACrE,MAAM,KAAK,GAAqB,EAAE,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,CAAA;QAC7D,GAAG,CAAC,IAAI,EAAE,KAAK,CAAC,CAAA;QAChB,GAAG,CAAC,IAAI,EAAE,KAAK,CAAC,CAAA;IACjB,CAAC;IAED,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,MAAM,CAAC,YAAY,CAAC,EAAE,CAAC;QAChD,MAAM,KAAK,GAAqB,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,CAAA;QACnF,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,CAAC,CAAA;QACrB,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,CAAC,CAAA;QACrB,GAAG,CAAC,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC,CAAA;IACxB,CAAC;IAED,OAAO,GAAG,CAAA;AACX,CAAC,CAAC,EAAE,CAAA;AAEJ;;;;;GAKG;AACH,MAAM,UAAU,gBAAgB,CAAC,KAAgC;IAChE,IAAI,CAAC,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,IAAI,CAAA;IAEpD,OAAO,kBAAkB,CAAC,GAAG,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,IAAI,IAAI,CAAA;AACvD,CAAC"}
1
+ {"version":3,"file":"subdivision.js","sourceRoot":"","sources":["../../country/subdivision.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAA;AAChD,OAAO,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAA;AAC1C,OAAO,EAAE,wBAAwB,EAAE,MAAM,gBAAgB,CAAA;AAoBzD;;;;GAIG;AACH,MAAM,kBAAkB,GAA0C,CAAC,GAAG,EAAE;IACvE,MAAM,GAAG,GAAG,IAAI,GAAG,EAA4B,CAAA;IAE/C,MAAM,GAAG,GAAG,CAAC,GAAW,EAAE,KAAuB,EAAQ,EAAE;QAC1D,MAAM,MAAM,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAA;QAE5B,IAAI,MAAM,CAAC,MAAM,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC;YACvC,GAAG,CAAC,GAAG,CAAC,MAAM,EAAE,KAAK,CAAC,CAAA;QACvB,CAAC;IACF,CAAC,CAAA;IAED,KAAK,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,wBAAwB,CAAC,EAAE,CAAC;QACrE,MAAM,KAAK,GAAqB,EAAE,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,CAAA;QAC7D,GAAG,CAAC,IAAI,EAAE,KAAK,CAAC,CAAA;QAChB,GAAG,CAAC,IAAI,EAAE,KAAK,CAAC,CAAA;IACjB,CAAC;IAED,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,MAAM,CAAC,YAAY,CAAC,EAAE,CAAC;QAChD,MAAM,KAAK,GAAqB,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,CAAA;QACnF,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,CAAC,CAAA;QACrB,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,CAAC,CAAA;QACrB,GAAG,CAAC,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC,CAAA;IACxB,CAAC;IAED,OAAO,GAAG,CAAA;AACX,CAAC,CAAC,EAAE,CAAA;AAEJ;;;;;GAKG;AACH,MAAM,UAAU,gBAAgB,CAAC,KAAgC;IAChE,IAAI,CAAC,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,IAAI,CAAA;IAEpD,OAAO,kBAAkB,CAAC,GAAG,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,IAAI,IAAI,CAAA;AACvD,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"region.d.ts","sourceRoot":"","sources":["../../fr/region.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAChC;;OAEG;IACH,IAAI,EAAE,MAAM,CAAA;IACZ;;OAEG;IACH,IAAI,EAAE,MAAM,CAAA;CACZ;AAED;;GAEG;AACH,eAAO,MAAM,UAAU;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAmB8B,CAAA;AAErD;;GAEG;AACH,MAAM,MAAM,gBAAgB,GAAG,MAAM,OAAO,UAAU,CAAA;AAItD;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,gBAAgB,CAE5E;AAcD;;;;;GAKG;AACH,eAAO,MAAM,sBAAsB,EAAE,WAAW,CAAC,MAAM,EAAE,gBAAgB,CASrE,CAAA;AAEJ;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,gBAAgB,GAAG,IAAI,CAO5F"}
1
+ {"version":3,"file":"region.d.ts","sourceRoot":"","sources":["../../fr/region.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAIH;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAChC;;OAEG;IACH,IAAI,EAAE,MAAM,CAAA;IACZ;;OAEG;IACH,IAAI,EAAE,MAAM,CAAA;CACZ;AAED;;GAEG;AACH,eAAO,MAAM,UAAU;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAmB8B,CAAA;AAErD;;GAEG;AACH,MAAM,MAAM,gBAAgB,GAAG,MAAM,OAAO,UAAU,CAAA;AAItD;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,gBAAgB,CAE5E;AAED;;;;;GAKG;AACH,eAAO,MAAM,sBAAsB,EAAE,WAAW,CAAC,MAAM,EAAE,gBAAgB,CASrE,CAAA;AAEJ;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,gBAAgB,GAAG,IAAI,CAO5F"}
package/out/fr/region.js CHANGED
@@ -12,6 +12,7 @@
12
12
  * commune`. The region is inferred from the département, which is inferred from the postcode (see
13
13
  * `code-postal.ts`).
14
14
  */
15
+ import { foldName } from "../normalize.js";
15
16
  /**
16
17
  * ISO 3166-2:FR region code → info, for all 18 régions (13 metropolitan + 5 overseas).
17
18
  */
@@ -42,17 +43,6 @@ const REGION_CODE_SET = new Set(Object.keys(FR_REGIONS));
42
43
  export function isFrenchRegionCode(input) {
43
44
  return typeof input === "string" && REGION_CODE_SET.has(input.toUpperCase());
44
45
  }
45
- /**
46
- * Strip diacritics + lowercase so `Île-de-France`, `ile-de-france`, `Ile de France` all key alike.
47
- */
48
- function foldName(s) {
49
- return s
50
- .toLowerCase()
51
- .normalize("NFD")
52
- .replaceAll(/[\u0300-\u036F]/g, "")
53
- .replaceAll(/[^a-z0-9]+/g, " ")
54
- .trim();
55
- }
56
46
  /**
57
47
  * Folded region name / code → ISO 3166-2:FR code. Built diacritic-insensitive so the resolver's surface form
58
48
  * (`Île-de-France`, or an unaccented `Ile-de-France`) maps regardless of accents. Mirrors `de/bundesland.ts`'s
@@ -1 +1 @@
1
- {"version":3,"file":"region.js","sourceRoot":"","sources":["../../fr/region.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"region.js","sourceRoot":"","sources":["../../fr/region.ts"],"names":[],"mappings":"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"}
@@ -28,6 +28,15 @@ import type { UkCountryCode } from "./country.ts";
28
28
  * Keeping only the non-England set makes the default transparent — anything not named here is England.
29
29
  */
30
30
  export declare const GB_POSTCODE_AREA_COUNTRY: Record<string, UkCountryCode>;
31
+ /**
32
+ * The two postcode areas whose assignment in {@link GB_POSTCODE_AREA_COUNTRY} is a MAJORITY call rather than a fact —
33
+ * TD (Galashiels) straddles the Scotland/England border and SY (Shrewsbury) straddles the Wales/England border, and
34
+ * both carry real postcodes on the other side of the line. The header above documents them in prose; this is the same
35
+ * knowledge in a form a build can read, so an artifact that ASSERTS ancestry per postcode district can withhold the
36
+ * constituent country here instead of asserting a coin-flip. Consumers that only want the coarse majority answer keep
37
+ * using {@link countryOfPostcodeArea} and ignore this.
38
+ */
39
+ export declare const GB_BORDER_STRADDLING_AREAS: ReadonlySet<string>;
31
40
  /**
32
41
  * The constituent country a postcode AREA belongs to. Returns the explicit country for a known non-England area (e.g.
33
42
  * `BT` → `NIR`, `G` → `SCT`, `CF` → `WLS`), and `ENG` as the default for any other validly-shaped area — England is by
@@ -1 +1 @@
1
- {"version":3,"file":"postcode-area.d.ts","sourceRoot":"","sources":["../../gb/postcode-area.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAA;AA2CjD;;;;GAIG;AACH,eAAO,MAAM,wBAAwB,EAAE,MAAM,CAAC,MAAM,EAAE,aAAa,CAIlE,CAAA;AASD;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,OAAO,GAAG,aAAa,GAAG,IAAI,CAIzE;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,OAAO,GAAG,aAAa,GAAG,IAAI,CAQzE"}
1
+ {"version":3,"file":"postcode-area.d.ts","sourceRoot":"","sources":["../../gb/postcode-area.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAA;AA2CjD;;;;GAIG;AACH,eAAO,MAAM,wBAAwB,EAAE,MAAM,CAAC,MAAM,EAAE,aAAa,CAIlE,CAAA;AAED;;;;;;;GAOG;AACH,eAAO,MAAM,0BAA0B,EAAE,WAAW,CAAC,MAAM,CAAyB,CAAA;AASpF;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,OAAO,GAAG,aAAa,GAAG,IAAI,CAIzE;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,OAAO,GAAG,aAAa,GAAG,IAAI,CAQzE"}
@@ -69,6 +69,15 @@ export const GB_POSTCODE_AREA_COUNTRY = {
69
69
  ...Object.fromEntries(SCOTLAND_AREAS.map((a) => [a, "SCT"])),
70
70
  ...Object.fromEntries(WALES_AREAS.map((a) => [a, "WLS"])),
71
71
  };
72
+ /**
73
+ * The two postcode areas whose assignment in {@link GB_POSTCODE_AREA_COUNTRY} is a MAJORITY call rather than a fact —
74
+ * TD (Galashiels) straddles the Scotland/England border and SY (Shrewsbury) straddles the Wales/England border, and
75
+ * both carry real postcodes on the other side of the line. The header above documents them in prose; this is the same
76
+ * knowledge in a form a build can read, so an artifact that ASSERTS ancestry per postcode district can withhold the
77
+ * constituent country here instead of asserting a coin-flip. Consumers that only want the coarse majority answer keep
78
+ * using {@link countryOfPostcodeArea} and ignore this.
79
+ */
80
+ export const GB_BORDER_STRADDLING_AREAS = new Set(["TD", "SY"]);
72
81
  /**
73
82
  * True when `area` looks like a valid postcode-area string: one or two ASCII letters.
74
83
  */
@@ -1 +1 @@
1
- {"version":3,"file":"postcode-area.js","sourceRoot":"","sources":["../../gb/postcode-area.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAIH;;GAEG;AACH,MAAM,sBAAsB,GAAG,CAAC,IAAI,CAAU,CAAA;AAE9C;;;GAGG;AACH,MAAM,cAAc,GAAG;IACtB,IAAI,EAAE,WAAW;IACjB,IAAI,EAAE,SAAS;IACf,IAAI,EAAE,WAAW;IACjB,IAAI,EAAE,YAAY;IAClB,IAAI,EAAE,UAAU;IAChB,GAAG,EAAE,WAAW;IAChB,IAAI,EAAE,sCAAsC;IAC5C,IAAI,EAAE,YAAY;IAClB,IAAI,EAAE,aAAa;IACnB,IAAI,EAAE,gCAAgC;IACtC,IAAI,EAAE,mBAAmB;IACzB,IAAI,EAAE,aAAa;IACnB,IAAI,EAAE,UAAU;IAChB,IAAI,EAAE,QAAQ;IACd,IAAI,EAAE,kFAAkF;IACxF,IAAI,EAAE,qBAAqB;CAClB,CAAA;AAEV;;;GAGG;AACH,MAAM,WAAW,GAAG;IACnB,IAAI,EAAE,UAAU;IAChB,IAAI,EAAE,oBAAoB;IAC1B,IAAI,EAAE,YAAY;IAClB,IAAI,EAAE,UAAU;IAChB,IAAI,EAAE,UAAU;IAChB,IAAI,EAAE,kEAAkE;CAC/D,CAAA;AAEV;;;;GAIG;AACH,MAAM,CAAC,MAAM,wBAAwB,GAAkC;IACtE,GAAG,MAAM,CAAC,WAAW,CAAC,sBAAsB,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAc,CAAC,CAAC,CAAC;IAC7E,GAAG,MAAM,CAAC,WAAW,CAAC,cAAc,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAc,CAAC,CAAC,CAAC;IACrE,GAAG,MAAM,CAAC,WAAW,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAc,CAAC,CAAC,CAAC;CAClE,CAAA;AAED;;GAEG;AACH,SAAS,WAAW,CAAC,IAAa;IACjC,OAAO,OAAO,IAAI,KAAK,QAAQ,IAAI,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;AAC9D,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,qBAAqB,CAAC,IAAa;IAClD,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC;QAAE,OAAO,IAAI,CAAA;IAEnC,OAAO,wBAAwB,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,IAAI,KAAK,CAAA;AAC7D,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,iBAAiB,CAAC,QAAiB;IAClD,IAAI,OAAO,QAAQ,KAAK,QAAQ;QAAE,OAAO,IAAI,CAAA;IAC7C,kFAAkF;IAClF,MAAM,KAAK,GAAG,mBAAmB,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAA;IAEhD,IAAI,CAAC,KAAK;QAAE,OAAO,IAAI,CAAA;IAEvB,OAAO,qBAAqB,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAA;AACvC,CAAC"}
1
+ {"version":3,"file":"postcode-area.js","sourceRoot":"","sources":["../../gb/postcode-area.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAIH;;GAEG;AACH,MAAM,sBAAsB,GAAG,CAAC,IAAI,CAAU,CAAA;AAE9C;;;GAGG;AACH,MAAM,cAAc,GAAG;IACtB,IAAI,EAAE,WAAW;IACjB,IAAI,EAAE,SAAS;IACf,IAAI,EAAE,WAAW;IACjB,IAAI,EAAE,YAAY;IAClB,IAAI,EAAE,UAAU;IAChB,GAAG,EAAE,WAAW;IAChB,IAAI,EAAE,sCAAsC;IAC5C,IAAI,EAAE,YAAY;IAClB,IAAI,EAAE,aAAa;IACnB,IAAI,EAAE,gCAAgC;IACtC,IAAI,EAAE,mBAAmB;IACzB,IAAI,EAAE,aAAa;IACnB,IAAI,EAAE,UAAU;IAChB,IAAI,EAAE,QAAQ;IACd,IAAI,EAAE,kFAAkF;IACxF,IAAI,EAAE,qBAAqB;CAClB,CAAA;AAEV;;;GAGG;AACH,MAAM,WAAW,GAAG;IACnB,IAAI,EAAE,UAAU;IAChB,IAAI,EAAE,oBAAoB;IAC1B,IAAI,EAAE,YAAY;IAClB,IAAI,EAAE,UAAU;IAChB,IAAI,EAAE,UAAU;IAChB,IAAI,EAAE,kEAAkE;CAC/D,CAAA;AAEV;;;;GAIG;AACH,MAAM,CAAC,MAAM,wBAAwB,GAAkC;IACtE,GAAG,MAAM,CAAC,WAAW,CAAC,sBAAsB,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAc,CAAC,CAAC,CAAC;IAC7E,GAAG,MAAM,CAAC,WAAW,CAAC,cAAc,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAc,CAAC,CAAC,CAAC;IACrE,GAAG,MAAM,CAAC,WAAW,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAc,CAAC,CAAC,CAAC;CAClE,CAAA;AAED;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,0BAA0B,GAAwB,IAAI,GAAG,CAAC,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,CAAA;AAEpF;;GAEG;AACH,SAAS,WAAW,CAAC,IAAa;IACjC,OAAO,OAAO,IAAI,KAAK,QAAQ,IAAI,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;AAC9D,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,qBAAqB,CAAC,IAAa;IAClD,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC;QAAE,OAAO,IAAI,CAAA;IAEnC,OAAO,wBAAwB,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,IAAI,KAAK,CAAA;AAC7D,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,iBAAiB,CAAC,QAAiB;IAClD,IAAI,OAAO,QAAQ,KAAK,QAAQ;QAAE,OAAO,IAAI,CAAA;IAC7C,kFAAkF;IAClF,MAAM,KAAK,GAAG,mBAAmB,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAA;IAEhD,IAAI,CAAC,KAAK;QAAE,OAAO,IAAI,CAAA;IAEvB,OAAO,qBAAqB,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAA;AACvC,CAAC"}
package/out/index.d.ts CHANGED
@@ -21,6 +21,7 @@
21
21
  * subpath.
22
22
  */
23
23
  export { ADDRESS_SYSTEM_CONVENTIONS, conventionsForSystem, type AddressSystemConventions, } from "./address-system-conventions.ts";
24
+ export * from "./normalize.ts";
24
25
  export * as au from "./au/index.ts";
25
26
  export * as ca from "./ca/index.ts";
26
27
  export * as de from "./de/index.ts";
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,EACN,0BAA0B,EAC1B,oBAAoB,EACpB,KAAK,wBAAwB,GAC7B,MAAM,iCAAiC,CAAA;AAExC,OAAO,KAAK,EAAE,MAAM,eAAe,CAAA;AACnC,OAAO,KAAK,EAAE,MAAM,eAAe,CAAA;AACnC,OAAO,KAAK,EAAE,MAAM,eAAe,CAAA;AACnC,OAAO,KAAK,EAAE,MAAM,eAAe,CAAA;AACnC,OAAO,KAAK,EAAE,MAAM,eAAe,CAAA;AACnC,OAAO,KAAK,EAAE,MAAM,eAAe,CAAA;AACnC,OAAO,KAAK,MAAM,MAAM,sBAAsB,CAAA;AAC9C,OAAO,KAAK,EAAE,MAAM,eAAe,CAAA;AACnC,OAAO,EAAE,2BAA2B,EAAE,KAAK,UAAU,EAAE,MAAM,uBAAuB,CAAA;AACpF,OAAO,KAAK,EAAE,MAAM,eAAe,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,EACN,0BAA0B,EAC1B,oBAAoB,EACpB,KAAK,wBAAwB,GAC7B,MAAM,iCAAiC,CAAA;AAExC,cAAc,gBAAgB,CAAA;AAC9B,OAAO,KAAK,EAAE,MAAM,eAAe,CAAA;AACnC,OAAO,KAAK,EAAE,MAAM,eAAe,CAAA;AACnC,OAAO,KAAK,EAAE,MAAM,eAAe,CAAA;AACnC,OAAO,KAAK,EAAE,MAAM,eAAe,CAAA;AACnC,OAAO,KAAK,EAAE,MAAM,eAAe,CAAA;AACnC,OAAO,KAAK,EAAE,MAAM,eAAe,CAAA;AACnC,OAAO,KAAK,MAAM,MAAM,sBAAsB,CAAA;AAC9C,OAAO,KAAK,EAAE,MAAM,eAAe,CAAA;AACnC,OAAO,EAAE,2BAA2B,EAAE,KAAK,UAAU,EAAE,MAAM,uBAAuB,CAAA;AACpF,OAAO,KAAK,EAAE,MAAM,eAAe,CAAA"}
package/out/index.js CHANGED
@@ -21,6 +21,7 @@
21
21
  * subpath.
22
22
  */
23
23
  export { ADDRESS_SYSTEM_CONVENTIONS, conventionsForSystem, } from "./address-system-conventions.js";
24
+ export * from "./normalize.js";
24
25
  export * as au from "./au/index.js";
25
26
  export * as ca from "./ca/index.js";
26
27
  export * as de from "./de/index.js";
package/out/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,EACN,0BAA0B,EAC1B,oBAAoB,GAEpB,MAAM,iCAAiC,CAAA;AAExC,OAAO,KAAK,EAAE,MAAM,eAAe,CAAA;AACnC,OAAO,KAAK,EAAE,MAAM,eAAe,CAAA;AACnC,OAAO,KAAK,EAAE,MAAM,eAAe,CAAA;AACnC,OAAO,KAAK,EAAE,MAAM,eAAe,CAAA;AACnC,OAAO,KAAK,EAAE,MAAM,eAAe,CAAA;AACnC,OAAO,KAAK,EAAE,MAAM,eAAe,CAAA;AACnC,OAAO,KAAK,MAAM,MAAM,sBAAsB,CAAA;AAC9C,OAAO,KAAK,EAAE,MAAM,eAAe,CAAA;AACnC,OAAO,EAAE,2BAA2B,EAAmB,MAAM,uBAAuB,CAAA;AACpF,OAAO,KAAK,EAAE,MAAM,eAAe,CAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,EACN,0BAA0B,EAC1B,oBAAoB,GAEpB,MAAM,iCAAiC,CAAA;AAExC,cAAc,gBAAgB,CAAA;AAC9B,OAAO,KAAK,EAAE,MAAM,eAAe,CAAA;AACnC,OAAO,KAAK,EAAE,MAAM,eAAe,CAAA;AACnC,OAAO,KAAK,EAAE,MAAM,eAAe,CAAA;AACnC,OAAO,KAAK,EAAE,MAAM,eAAe,CAAA;AACnC,OAAO,KAAK,EAAE,MAAM,eAAe,CAAA;AACnC,OAAO,KAAK,EAAE,MAAM,eAAe,CAAA;AACnC,OAAO,KAAK,MAAM,MAAM,sBAAsB,CAAA;AAC9C,OAAO,KAAK,EAAE,MAAM,eAAe,CAAA;AACnC,OAAO,EAAE,2BAA2B,EAAmB,MAAM,uBAAuB,CAAA;AACpF,OAAO,KAAK,EAAE,MAAM,eAAe,CAAA"}
@@ -0,0 +1,36 @@
1
+ /**
2
+ * @copyright Sister Software
3
+ * @license AGPL-3.0
4
+ * @author Teffen Ellis, et al.
5
+ *
6
+ * Name-normalization primitives shared across the codex tables and the lexicon builders that read
7
+ * them.
8
+ *
9
+ * These live in `@mailwoman/codex` rather than in `core` or `normalize` for one reason: codex is
10
+ * the zero-runtime-dependency reference package, and everything that needs to match a name against
11
+ * a codex table already depends on it. Putting the folding rules next to the tables they fold
12
+ * means a lookup and its table can never disagree about what counts as the same name.
13
+ *
14
+ */
15
+ /**
16
+ * Fold a name to its ASCII match key: lower-cased, accents stripped, every run of non-alphanumerics collapsed to a
17
+ * single space.
18
+ *
19
+ * This is the aggressive fold used to match a user's surface form against a codex table — `"Québec"` and `"QUEBEC"` and
20
+ * `"quebec"` all become `"quebec"`. It is lossy by design and never used to render anything back to a user.
21
+ */
22
+ export declare function foldName(s: string): string;
23
+ /**
24
+ * Strip leading and trailing punctuation from every whitespace-separated word, dropping words that were nothing but
25
+ * punctuation, and rejoin on single spaces.
26
+ *
27
+ * Unlike {@link foldName} this preserves case and non-Latin scripts — it works on Unicode letter and number classes, so
28
+ * `"Кыргызстан,"` and `"日本 。"` survive with their content intact. That is what makes it the right normalizer for
29
+ * building surface lexicons, where the entry has to remain renderable, and the wrong one for building a match key.
30
+ */
31
+ export declare function wordNorm(s: string): string;
32
+ /**
33
+ * {@link wordNorm}, lower-cased — the case-insensitive lexicon key.
34
+ */
35
+ export declare function wordNormLower(s: string): string;
36
+ //# sourceMappingURL=normalize.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"normalize.d.ts","sourceRoot":"","sources":["../normalize.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH;;;;;;GAMG;AACH,wBAAgB,QAAQ,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAO1C;AAED;;;;;;;GAOG;AACH,wBAAgB,QAAQ,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAM1C;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAE/C"}
@@ -0,0 +1,51 @@
1
+ /**
2
+ * @copyright Sister Software
3
+ * @license AGPL-3.0
4
+ * @author Teffen Ellis, et al.
5
+ *
6
+ * Name-normalization primitives shared across the codex tables and the lexicon builders that read
7
+ * them.
8
+ *
9
+ * These live in `@mailwoman/codex` rather than in `core` or `normalize` for one reason: codex is
10
+ * the zero-runtime-dependency reference package, and everything that needs to match a name against
11
+ * a codex table already depends on it. Putting the folding rules next to the tables they fold
12
+ * means a lookup and its table can never disagree about what counts as the same name.
13
+ *
14
+ */
15
+ /**
16
+ * Fold a name to its ASCII match key: lower-cased, accents stripped, every run of non-alphanumerics collapsed to a
17
+ * single space.
18
+ *
19
+ * This is the aggressive fold used to match a user's surface form against a codex table — `"Québec"` and `"QUEBEC"` and
20
+ * `"quebec"` all become `"quebec"`. It is lossy by design and never used to render anything back to a user.
21
+ */
22
+ export function foldName(s) {
23
+ return s
24
+ .toLowerCase()
25
+ .normalize("NFD")
26
+ .replaceAll(/[\u0300-\u036F]/g, "")
27
+ .replaceAll(/[^a-z0-9]+/g, " ")
28
+ .trim();
29
+ }
30
+ /**
31
+ * Strip leading and trailing punctuation from every whitespace-separated word, dropping words that were nothing but
32
+ * punctuation, and rejoin on single spaces.
33
+ *
34
+ * Unlike {@link foldName} this preserves case and non-Latin scripts — it works on Unicode letter and number classes, so
35
+ * `"Кыргызстан,"` and `"日本 。"` survive with their content intact. That is what makes it the right normalizer for
36
+ * building surface lexicons, where the entry has to remain renderable, and the wrong one for building a match key.
37
+ */
38
+ export function wordNorm(s) {
39
+ return s
40
+ .split(/\s+/)
41
+ .map((w) => w.replaceAll(/^[^\p{L}\p{N}]+|[^\p{L}\p{N}]+$/gu, ""))
42
+ .filter(Boolean)
43
+ .join(" ");
44
+ }
45
+ /**
46
+ * {@link wordNorm}, lower-cased — the case-insensitive lexicon key.
47
+ */
48
+ export function wordNormLower(s) {
49
+ return wordNorm(s).toLowerCase();
50
+ }
51
+ //# sourceMappingURL=normalize.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"normalize.js","sourceRoot":"","sources":["../normalize.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH;;;;;;GAMG;AACH,MAAM,UAAU,QAAQ,CAAC,CAAS;IACjC,OAAO,CAAC;SACN,WAAW,EAAE;SACb,SAAS,CAAC,KAAK,CAAC;SAChB,UAAU,CAAC,kBAAkB,EAAE,EAAE,CAAC;SAClC,UAAU,CAAC,aAAa,EAAE,GAAG,CAAC;SAC9B,IAAI,EAAE,CAAA;AACT,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,QAAQ,CAAC,CAAS;IACjC,OAAO,CAAC;SACN,KAAK,CAAC,KAAK,CAAC;SACZ,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,mCAAmC,EAAE,EAAE,CAAC,CAAC;SACjE,MAAM,CAAC,OAAO,CAAC;SACf,IAAI,CAAC,GAAG,CAAC,CAAA;AACZ,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,aAAa,CAAC,CAAS;IACtC,OAAO,QAAQ,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,CAAA;AACjC,CAAC"}
@@ -44,11 +44,11 @@
44
44
  /**
45
45
  * Identifier requirement per ADV358's Delivery Service Elements rules.
46
46
  */
47
- export type NzIdentifierRule = "required-if-allocated" | "optional" | "not-used";
47
+ export type NZIdentifierRule = "required-if-allocated" | "optional" | "not-used";
48
48
  /**
49
49
  * One Delivery Service Type row from ADV358.
50
50
  */
51
- export interface NzDeliveryServiceType {
51
+ export interface NZDeliveryServiceType {
52
52
  /**
53
53
  * The Delivery Service Type, verbatim casing per ADV358 ("PO Box", "Private Bag", "CMB").
54
54
  */
@@ -62,7 +62,7 @@ export interface NzDeliveryServiceType {
62
62
  * none ("not used … for Private Bags that do not have an identifier allocated by New Zealand Post"); Counter Delivery
63
63
  * and Poste Restante never carry one.
64
64
  */
65
- identifier: NzIdentifierRule;
65
+ identifier: NZIdentifierRule;
66
66
  }
67
67
  /**
68
68
  * The six Delivery Service Types, verbatim from ADV358 (see the module header).
@@ -95,7 +95,7 @@ export declare const NZ_DELIVERY_SERVICE_TYPES: readonly [{
95
95
  /**
96
96
  * A canonical NZ Delivery Service Type.
97
97
  */
98
- export type NzDeliveryServiceTypeName = (typeof NZ_DELIVERY_SERVICE_TYPES)[number]["type"];
98
+ export type NZDeliveryServiceTypeName = (typeof NZ_DELIVERY_SERVICE_TYPES)[number]["type"];
99
99
  /**
100
100
  * Metadata for the colloquial "Private Box" alias (see the module header and operator ruling 2026-06-11). Kept separate
101
101
  * from {@link NZ_DELIVERY_SERVICE_TYPES} because it is NOT a valid ADV358 Delivery Service Type — recognition and
@@ -130,11 +130,11 @@ export declare const NZ_PRIVATE_BOX_ALIAS: {
130
130
  /**
131
131
  * Extended type name union including the colloquial alias recognized for parsing.
132
132
  */
133
- export type NzDeliveryServiceMatchTypeName = NzDeliveryServiceTypeName | "Private Box";
133
+ export type NZDeliveryServiceMatchTypeName = NZDeliveryServiceTypeName | "Private Box";
134
134
  /**
135
135
  * Result of an NZ delivery-service parse.
136
136
  */
137
- export interface NzDeliveryServiceMatch {
137
+ export interface NZDeliveryServiceMatch {
138
138
  /**
139
139
  * The designator phrase as it appeared ("PO Box", "private bag", "Private Box").
140
140
  */
@@ -144,7 +144,7 @@ export interface NzDeliveryServiceMatch {
144
144
  * `type` is "Private Box", `colloquial` is true and `officiallyInvalid` is true — the form is not a valid ADV358
145
145
  * type.
146
146
  */
147
- type: NzDeliveryServiceMatchTypeName;
147
+ type: NZDeliveryServiceMatchTypeName;
148
148
  /**
149
149
  * The Delivery Service Identifier when present ("24999", "B99").
150
150
  */
@@ -164,14 +164,14 @@ export interface NzDeliveryServiceMatch {
164
164
  * Delivery Service Type; see {@link NZ_PRIVATE_BOX_ALIAS} and operator ruling 2026-06-11). Callers that want only
165
165
  * formally-valid ADV358 types should check `!result.colloquial`.
166
166
  */
167
- export declare function matchNzDeliveryService(input: unknown): NzDeliveryServiceMatch | null;
167
+ export declare function matchNZDeliveryService(input: unknown): NZDeliveryServiceMatch | null;
168
168
  /**
169
169
  * Type-predicate: does the input look like a standalone NZ delivery-service address line?
170
170
  */
171
- export declare function isNzDeliveryService(input: unknown): boolean;
171
+ export declare function isNZDeliveryService(input: unknown): boolean;
172
172
  /**
173
173
  * Normalize a recognized phrase to the ADV358 form (`"p.o. box 24999"` → `"PO Box 24999"`). Returns the input unchanged
174
174
  * if it isn't a delivery-service phrase.
175
175
  */
176
- export declare function normalizeNzDeliveryService(input: string): string;
176
+ export declare function normalizeNZDeliveryService(input: string): string;
177
177
  //# sourceMappingURL=delivery-service.d.ts.map
@@ -135,7 +135,7 @@ const MATCHERS = TYPE_PATTERNS.map(([type, src]) => {
135
135
  * Delivery Service Type; see {@link NZ_PRIVATE_BOX_ALIAS} and operator ruling 2026-06-11). Callers that want only
136
136
  * formally-valid ADV358 types should check `!result.colloquial`.
137
137
  */
138
- export function matchNzDeliveryService(input) {
138
+ export function matchNZDeliveryService(input) {
139
139
  if (typeof input !== "string")
140
140
  return null;
141
141
  for (const { type, re } of MATCHERS) {
@@ -150,15 +150,15 @@ export function matchNzDeliveryService(input) {
150
150
  /**
151
151
  * Type-predicate: does the input look like a standalone NZ delivery-service address line?
152
152
  */
153
- export function isNzDeliveryService(input) {
154
- return matchNzDeliveryService(input) !== null;
153
+ export function isNZDeliveryService(input) {
154
+ return matchNZDeliveryService(input) !== null;
155
155
  }
156
156
  /**
157
157
  * Normalize a recognized phrase to the ADV358 form (`"p.o. box 24999"` → `"PO Box 24999"`). Returns the input unchanged
158
158
  * if it isn't a delivery-service phrase.
159
159
  */
160
- export function normalizeNzDeliveryService(input) {
161
- const m = matchNzDeliveryService(input);
160
+ export function normalizeNZDeliveryService(input) {
161
+ const m = matchNZDeliveryService(input);
162
162
  if (!m)
163
163
  return input;
164
164
  return m.id ? `${m.type} ${m.id.toUpperCase()}` : m.type;
@@ -21,7 +21,7 @@ import type { Tagged } from "type-fest";
21
21
  * @title New Zealand postcode
22
22
  * @pattern ^\d{4}$
23
23
  */
24
- export type NzPostcode = Tagged<string, "NzPostcode">;
24
+ export type NZPostcode = Tagged<string, "NZPostcode">;
25
25
  /**
26
26
  * The NZ postcode shape: exactly four digits.
27
27
  */
@@ -29,9 +29,9 @@ export declare const NZ_POSTCODE_PATTERN: RegExp;
29
29
  /**
30
30
  * Normalize a postcode surface form (trim only — NZ has no country-prefix courtesy form).
31
31
  */
32
- export declare function normalizeNzPostcode(raw: unknown): NzPostcode | null;
32
+ export declare function normalizeNZPostcode(raw: unknown): NZPostcode | null;
33
33
  /**
34
34
  * Type-predicate for a (normalized) New Zealand postcode.
35
35
  */
36
- export declare function isNzPostcode(input: unknown): input is NzPostcode;
36
+ export declare function isNZPostcode(input: unknown): input is NZPostcode;
37
37
  //# sourceMappingURL=postcode.d.ts.map
@@ -19,7 +19,7 @@ export const NZ_POSTCODE_PATTERN = /^\d{4}$/;
19
19
  /**
20
20
  * Normalize a postcode surface form (trim only — NZ has no country-prefix courtesy form).
21
21
  */
22
- export function normalizeNzPostcode(raw) {
22
+ export function normalizeNZPostcode(raw) {
23
23
  if (typeof raw !== "string")
24
24
  return null;
25
25
  const s = raw.trim();
@@ -28,7 +28,7 @@ export function normalizeNzPostcode(raw) {
28
28
  /**
29
29
  * Type-predicate for a (normalized) New Zealand postcode.
30
30
  */
31
- export function isNzPostcode(input) {
31
+ export function isNZPostcode(input) {
32
32
  return typeof input === "string" && NZ_POSTCODE_PATTERN.test(input);
33
33
  }
34
34
  //# sourceMappingURL=postcode.js.map
@@ -26,7 +26,7 @@ import { normalizePLZ } from "./de/index.js";
26
26
  import { normalizeCodePostal } from "./fr/index.js";
27
27
  import { normalizeUkPostcode } from "./gb/index.js";
28
28
  import { normalizeJpPostalCode } from "./jp/index.js";
29
- import { normalizeNzPostcode } from "./nz/index.js";
29
+ import { normalizeNZPostcode } from "./nz/index.js";
30
30
  import { isZipCode } from "./us/index.js";
31
31
  /**
32
32
  * Per-system membership test: each entry returns true when the string is accepted by that system's own postcode shape
@@ -41,7 +41,7 @@ const SYSTEM_ACCEPTS = [
41
41
  ["gb", (s) => normalizeUkPostcode(s) !== null],
42
42
  ["jp", (s) => normalizeJpPostalCode(s) !== null],
43
43
  ["au", (s) => normalizeAuPostcode(s) !== null],
44
- ["nz", (s) => normalizeNzPostcode(s) !== null],
44
+ ["nz", (s) => normalizeNZPostcode(s) !== null],
45
45
  ];
46
46
  /**
47
47
  * Every address system whose own postcode shape accepts `postcode`. Empty when no system recognizes the shape (e.g. a
@@ -42,6 +42,7 @@
42
42
  import { mkdirSync, writeFileSync } from "node:fs";
43
43
  import { dirname, resolve } from "node:path";
44
44
  import { COUNTRY_SURFACE_FORMS, ISO2_TO_NAME } from "../country/country.js";
45
+ import { wordNorm, wordNormLower } from "../normalize.js";
45
46
  import { US_STATE_ABBREVIATIONS, US_STATE_NAMES } from "../us/state.js";
46
47
  /**
47
48
  * Ambiguous entries printed before the list is truncated.
@@ -64,12 +65,6 @@ const OUTPUT = resolve(import.meta.dirname, "../../data/gazetteer/country-surfac
64
65
  * letters or digits (keep internal ones: "u.s.a", "timor-leste"), rejoin single-spaced. Entry keys and scanned tokens
65
66
  * both pass through it, so "U.S.A." ≡ "u.s.a".
66
67
  */
67
- const wordNorm = (s) => s
68
- .split(/\s+/)
69
- .map((w) => w.replaceAll(/^[^\p{L}\p{N}]+|[^\p{L}\p{N}]+$/gu, ""))
70
- .filter(Boolean)
71
- .join(" ");
72
- const norm = (s) => wordNorm(s).toLowerCase();
73
68
  /**
74
69
  * Short alphabetic code (≤3 letters once punctuation is dropped) → exact-uppercase matching.
75
70
  */
@@ -106,7 +101,7 @@ function add(surface) {
106
101
  codeEntries.set(key, (codeEntries.get(key) ?? 0) | bits);
107
102
  return;
108
103
  }
109
- const key = norm(s);
104
+ const key = wordNormLower(s);
110
105
  if (!key)
111
106
  return;
112
107
  const words = key.split(" ");
@@ -1 +1 @@
1
- {"version":3,"file":"build-country-surface-lexicon.js","sourceRoot":"","sources":["../../tools/build-country-surface-lexicon.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"build-country-surface-lexicon.js","sourceRoot":"","sources":["../../tools/build-country-surface-lexicon.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"generate-official-languages.d.ts","sourceRoot":"","sources":["../../tools/generate-official-languages.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAaH;;GAEG;AACH,MAAM,WAAW,gCAAgC;IAChD;;OAEG;IACH,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB;;OAEG;IACH,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB;;OAEG;IACH,GAAG,CAAC,EAAE,MAAM,CAAA;CACZ;AAED;;GAEG;AACH,MAAM,WAAW,gCAAgC;IAChD,WAAW,EAAE,MAAM,CAAA;IACnB,WAAW,EAAE,MAAM,CAAA;IACnB,OAAO,EAAE,MAAM,CAAA;CACf;AAgBD;;GAEG;AACH,wBAAsB,yBAAyB,CAC9C,OAAO,GAAE,gCAAqC,EAC9C,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,GAC7B,OAAO,CAAC,gCAAgC,CAAC,CA2H3C"}
1
+ {"version":3,"file":"generate-official-languages.d.ts","sourceRoot":"","sources":["../../tools/generate-official-languages.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAeH;;GAEG;AACH,MAAM,WAAW,gCAAgC;IAChD;;OAEG;IACH,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB;;OAEG;IACH,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB;;OAEG;IACH,GAAG,CAAC,EAAE,MAAM,CAAA;CACZ;AAED;;GAEG;AACH,MAAM,WAAW,gCAAgC;IAChD,WAAW,EAAE,MAAM,CAAA;IACnB,WAAW,EAAE,MAAM,CAAA;IACnB,OAAO,EAAE,MAAM,CAAA;CACf;AAmBD;;GAEG;AACH,wBAAsB,yBAAyB,CAC9C,OAAO,GAAE,gCAAqC,EAC9C,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,GAC7B,OAAO,CAAC,gCAAgC,CAAC,CA2H3C"}
@@ -21,6 +21,7 @@
21
21
  import { readFileSync, writeFileSync } from "node:fs";
22
22
  import { join } from "node:path";
23
23
  import { fileURLToPath } from "node:url";
24
+ import { parseJSONStrict } from "@mailwoman/core/objects";
24
25
  /**
25
26
  * The committed output path, resolved relative to this module (codex/tools/ → codex/country/). The codegen is
26
27
  * repo-only, and in the repo `@mailwoman/codex/tools` always loads from source via the `node` exports condition, so
@@ -28,8 +29,9 @@ import { fileURLToPath } from "node:url";
28
29
  */
29
30
  const DEFAULT_OUT = fileURLToPath(new URL("../country/official-languages.ts", import.meta.url));
30
31
  async function loadCLDR(file, cldrDir, cldrVersion) {
31
- if (cldrDir)
32
- return JSON.parse(readFileSync(join(cldrDir, `cldr-${file}.json`), "utf8"));
32
+ if (cldrDir) {
33
+ return parseJSONStrict(readFileSync(join(cldrDir, `cldr-${file}.json`), "utf8"));
34
+ }
33
35
  const url = `https://cdn.jsdelivr.net/npm/cldr-core@${cldrVersion}/supplemental/${file}.json`;
34
36
  const res = await fetch(url);
35
37
  if (!res.ok)
@@ -1 +1 @@
1
- {"version":3,"file":"generate-official-languages.js","sourceRoot":"","sources":["../../tools/generate-official-languages.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"generate-official-languages.js","sourceRoot":"","sources":["../../tools/generate-official-languages.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mailwoman/codex",
3
- "version": "8.6.0",
3
+ "version": "9.0.0",
4
4
  "description": "Per-address-system postal reference data + branded types (USPS street suffixes, US ZIP codes). Pure, zero-runtime-dep — the shared canonical home for postal-system primitives the parser, resolver, and synthesis layers all reach for.",
5
5
  "license": "AGPL-3.0-only OR LicenseRef-Commercial",
6
6
  "repository": {
@@ -140,6 +140,6 @@
140
140
  "type-fest": "^5.8.0"
141
141
  },
142
142
  "devDependencies": {
143
- "@mailwoman/annotations": "8.6.0"
143
+ "@mailwoman/annotations": "9.0.0"
144
144
  }
145
145
  }
@@ -27,7 +27,7 @@ import { normalizePLZ } from "./de/index.ts"
27
27
  import { normalizeCodePostal } from "./fr/index.ts"
28
28
  import { normalizeUkPostcode } from "./gb/index.ts"
29
29
  import { normalizeJpPostalCode } from "./jp/index.ts"
30
- import { normalizeNzPostcode } from "./nz/index.ts"
30
+ import { normalizeNZPostcode } from "./nz/index.ts"
31
31
  import { isZipCode } from "./us/index.ts"
32
32
 
33
33
  /**
@@ -48,7 +48,7 @@ const SYSTEM_ACCEPTS: ReadonlyArray<readonly [SystemCode, (s: string) => boolean
48
48
  ["gb", (s) => normalizeUkPostcode(s) !== null],
49
49
  ["jp", (s) => normalizeJpPostalCode(s) !== null],
50
50
  ["au", (s) => normalizeAuPostcode(s) !== null],
51
- ["nz", (s) => normalizeNzPostcode(s) !== null],
51
+ ["nz", (s) => normalizeNZPostcode(s) !== null],
52
52
  ]
53
53
 
54
54
  /**
@@ -44,6 +44,7 @@ import { mkdirSync, writeFileSync } from "node:fs"
44
44
  import { dirname, resolve } from "node:path"
45
45
 
46
46
  import { COUNTRY_SURFACE_FORMS, ISO2_TO_NAME } from "../country/country.ts"
47
+ import { wordNorm, wordNormLower } from "../normalize.ts"
47
48
  import { US_STATE_ABBREVIATIONS, US_STATE_NAMES } from "../us/state.ts"
48
49
 
49
50
  /**
@@ -71,15 +72,6 @@ const OUTPUT = resolve(import.meta.dirname, "../../data/gazetteer/country-surfac
71
72
  * letters or digits (keep internal ones: "u.s.a", "timor-leste"), rejoin single-spaced. Entry keys and scanned tokens
72
73
  * both pass through it, so "U.S.A." ≡ "u.s.a".
73
74
  */
74
- const wordNorm = (s: string): string =>
75
- s
76
- .split(/\s+/)
77
- .map((w) => w.replaceAll(/^[^\p{L}\p{N}]+|[^\p{L}\p{N}]+$/gu, ""))
78
- .filter(Boolean)
79
- .join(" ")
80
-
81
- const norm = (s: string): string => wordNorm(s).toLowerCase()
82
-
83
75
  /**
84
76
  * Short alphabetic code (≤3 letters once punctuation is dropped) → exact-uppercase matching.
85
77
  */
@@ -125,7 +117,7 @@ function add(surface: string): void {
125
117
  return
126
118
  }
127
119
 
128
- const key = norm(s)
120
+ const key = wordNormLower(s)
129
121
 
130
122
  if (!key) return
131
123
  const words = key.split(" ")
@@ -23,6 +23,8 @@ import { readFileSync, writeFileSync } from "node:fs"
23
23
  import { join } from "node:path"
24
24
  import { fileURLToPath } from "node:url"
25
25
 
26
+ import { parseJSONStrict } from "@mailwoman/core/objects"
27
+
26
28
  /**
27
29
  * The committed output path, resolved relative to this module (codex/tools/ → codex/country/). The codegen is
28
30
  * repo-only, and in the repo `@mailwoman/codex/tools` always loads from source via the `node` exports condition, so
@@ -62,7 +64,10 @@ interface LanguagePopulation {
62
64
  }
63
65
 
64
66
  async function loadCLDR(file: string, cldrDir: string | undefined, cldrVersion: string): Promise<unknown> {
65
- if (cldrDir) return JSON.parse(readFileSync(join(cldrDir, `cldr-${file}.json`), "utf8"))
67
+ if (cldrDir) {
68
+ return parseJSONStrict(readFileSync(join(cldrDir, `cldr-${file}.json`), "utf8"))
69
+ }
70
+
66
71
  const url = `https://cdn.jsdelivr.net/npm/cldr-core@${cldrVersion}/supplemental/${file}.json`
67
72
  const res = await fetch(url)
68
73