@mailwoman/codex 5.10.1 → 6.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/out/index.d.ts CHANGED
@@ -15,7 +15,10 @@
15
15
  * Systems are exposed as namespaces (`import { us } from "@mailwoman/codex"`) and as subpaths
16
16
  * (`import { lookupStreetSuffix } from "@mailwoman/codex/us"`). The cross-system
17
17
  * `candidateSystemsForPostcode` (the inverse of the per-slice postcode patterns) is a top-level
18
- * export.
18
+ * export. `levels` is the per-locale LEVEL/floor ordinal-semantics table (#1100) — like
19
+ * `candidateSystemsForPostcode`, it's inherently multi-locale, so it lives at the codex root
20
+ * (`./level-semantics.ts`) and is namespaced rather than given its own `@mailwoman/codex/<x>`
21
+ * subpath.
19
22
  */
20
23
  export { ADDRESS_SYSTEM_CONVENTIONS, conventionsForSystem, type AddressSystemConventions, } from "./address-system-conventions.ts";
21
24
  export * as au from "./au/index.ts";
@@ -24,6 +27,7 @@ export * as de from "./de/index.ts";
24
27
  export * as fr from "./fr/index.ts";
25
28
  export * as gb from "./gb/index.ts";
26
29
  export * as jp from "./jp/index.ts";
30
+ export * as levels from "./level-semantics.ts";
27
31
  export * as nz from "./nz/index.ts";
28
32
  export { candidateSystemsForPostcode, type SystemCode } from "./postcode-systems.ts";
29
33
  export * as us from "./us/index.ts";
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,EACN,0BAA0B,EAC1B,oBAAoB,EACpB,KAAK,wBAAwB,GAC7B,MAAM,iCAAiC,CAAA;AACxC,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,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;AACxC,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
@@ -15,7 +15,10 @@
15
15
  * Systems are exposed as namespaces (`import { us } from "@mailwoman/codex"`) and as subpaths
16
16
  * (`import { lookupStreetSuffix } from "@mailwoman/codex/us"`). The cross-system
17
17
  * `candidateSystemsForPostcode` (the inverse of the per-slice postcode patterns) is a top-level
18
- * export.
18
+ * export. `levels` is the per-locale LEVEL/floor ordinal-semantics table (#1100) — like
19
+ * `candidateSystemsForPostcode`, it's inherently multi-locale, so it lives at the codex root
20
+ * (`./level-semantics.ts`) and is namespaced rather than given its own `@mailwoman/codex/<x>`
21
+ * subpath.
19
22
  */
20
23
  export { ADDRESS_SYSTEM_CONVENTIONS, conventionsForSystem, } from "./address-system-conventions.js";
21
24
  export * as au from "./au/index.js";
@@ -24,6 +27,7 @@ export * as de from "./de/index.js";
24
27
  export * as fr from "./fr/index.js";
25
28
  export * as gb from "./gb/index.js";
26
29
  export * as jp from "./jp/index.js";
30
+ export * as levels from "./level-semantics.js";
27
31
  export * as nz from "./nz/index.js";
28
32
  export { candidateSystemsForPostcode } from "./postcode-systems.js";
29
33
  export * as us from "./us/index.js";
package/out/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,EACN,0BAA0B,EAC1B,oBAAoB,GAEpB,MAAM,iCAAiC,CAAA;AACxC,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,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;AACxC,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,465 @@
1
+ /**
2
+ * @copyright Sister Software
3
+ * @license AGPL-3.0
4
+ * @author Teffen Ellis, et al.
5
+ *
6
+ * Per-locale LEVEL semantics — the fix for "Flr 1 means something different depending on where you
7
+ * are" (#1100, the secondary-address epic's second data deliverable). {@link "./us/unit-designator.ts"},
8
+ * {@link "./us/floor-designator.ts"}, and {@link "./au/level-designator.ts"} each standardize ONE
9
+ * address system's floor/level VOCABULARY — which surface tokens exist ("FL", "L 3", "Ground
10
+ * Floor"). This module standardizes the cross-locale ORDINAL SEMANTICS those tokens carry: the fact
11
+ * that "1st floor" names the SAME physical storey as "ground floor" in the United States
12
+ * (`firstNumberedIsGround: true`) but ONE STOREY ABOVE it in France, Germany, and most of
13
+ * continental Europe (`firstNumberedIsGround: false`), where ground already has its own name (RDC,
14
+ * EG, PLANTA BAJA, …) and claims ordinal 0 on its own.
15
+ *
16
+ * This is inherently a MULTI-LOCALE module — unlike `us/`, `au/`, `fr/`, … it doesn't belong to one
17
+ * address system, so it lives at the codex root and is exported only from the root barrel
18
+ * (mirroring `address-system-conventions.ts` and `postcode-systems.ts`, the other cross-system root
19
+ * modules). It does not get its own `@mailwoman/codex/<x>` subpath.
20
+ *
21
+ * Two tables do the work:
22
+ *
23
+ * 1. {@link LEVEL_DESIGNATORS_BY_FAMILY} — the designator LEXICON per LANGUAGE family (the surface
24
+ * vocabulary: FL/FLOOR/LVL/LEVEL, ÉTAGE/ÉT, OG/OBERGESCHOSS, …). Keyed by a bare language tag
25
+ * ("en", "fr", "de", …) because the WORDS don't vary by country — American and British English
26
+ * both say "floor", "basement", "penthouse".
27
+ * 2. {@link LEVEL_ORDINAL_CONVENTIONS} — the ORDINAL CONVENTION per full locale ("en-US", "en-GB",
28
+ * …), because the NUMBERING varies by country even within one language: American and Canadian
29
+ * buildings both call the ground floor "the 1st floor"; British buildings, like the rest of the
30
+ * IMDF/continental-European convention locales, do not.
31
+ *
32
+ * {@link levelToOrdinal} composes both: look up the designator's KIND in the locale's language
33
+ * family (ground / basement / numbered / fractional / special / fixed), then — for numbered
34
+ * designators only — apply the locale's numbering convention. IMDF (Apple's Indoor Mapping Data
35
+ * Format) is the schema precedent for encoding a level as a signed integer `ordinal` where ground is
36
+ * always 0; this table supplies the locale-aware mapping from a raw (designator, number) pair into
37
+ * that same ordinal space.
38
+ *
39
+ * Data is convention encoded from common postal/building usage, not a single postal authority
40
+ * publication — level-numbering conventions are cultural, not regulatory, so no Pub-28-style single
41
+ * source exists for most of these locales. Retrieved/encoded 2026-07-13, epic #1100.
42
+ *
43
+ * Deliberately-excluded ambiguities (handled by an explicit, documented rounding rule below, never a
44
+ * silent guess):
45
+ *
46
+ * - **Spanish PRINCIPAL / ENTRESUELO**: pre-metric Spanish buildings run BAJO (0) → ENTRESUELO
47
+ * (~0.5) → PRINCIPAL (1) → PISO 1/2 (2), but the exact offset varies by city and building age.
48
+ * ENTRESUELO's true position (0.5) isn't representable as an integer ordinal; it floors to 0
49
+ * (grouped with ground) — a documented approximation, not an empirical claim. PRINCIPAL is a
50
+ * fixed, always-ordinal-1 designator (it names a specific floor by convention, not by a number the
51
+ * caller supplies).
52
+ * - **English LOWER GROUND / UPPER GROUND** (UK mixed-use buildings): sit at roughly -0.5 and +0.5
53
+ * relative to ground. Both round DOWN (floor): LOWER GROUND → -1 (grouped with the first basement
54
+ * level), UPPER GROUND → 0 (grouped with ground). Convention choices, not measurements.
55
+ * - **PENTHOUSE / ROOF / ATTIC / DACHGESCHOSS / ÁTICO / ATTICO**: named by relationship to the TOP of
56
+ * a SPECIFIC building, not by a fixed distance from ground — there is no locale-independent integer
57
+ * to assign. {@link levelToOrdinal} returns `undefined` for this designator kind rather than
58
+ * guessing.
59
+ * - **Nordic ground-floor vocabulary**: Danish STUEN/STUEETAGE is a well-attested standard term
60
+ * (the "st." you see on Danish addresses). Norwegian has no equally standard, universally-agreed
61
+ * single word for "ground floor" distinct from "1. etasje" in everyday use; GATEPLAN is included
62
+ * here for structural parity with the other Nordic tables but is a lower-confidence, regional
63
+ * inclusion — flagged in-line, not asserted as authoritative.
64
+ *
65
+ * @see {@link https://register.apple.com/resources/imdf/Level/ IMDF Level — `ordinal` (Apple Indoor Mapping Data Format)}
66
+ */
67
+ /**
68
+ * How a level designator's ordinal is derived. See the module header for the rationale behind each non-obvious kind.
69
+ *
70
+ * - `"ground"` — always ordinal 0 (RDC, EG, PLANTA BAJA, …).
71
+ * - `"basement"` — ordinal is the negation of the trailing number, defaulting to 1 when the designator appears bare
72
+ * ("Basement" alone → -1, same as "B1").
73
+ * - `"numbered"` — ordinal depends on the locale's {@link LevelOrdinalConvention} (US/CA/JP-style vs
74
+ * continental-European/IMDF-style); requires a number.
75
+ * - `"fractionalAboveGround"` — conceptually between ground and the first numbered level (mezzanine, entresol/entresuelo,
76
+ * upper ground, German Zwischengeschoss); floors to ordinal 0.
77
+ * - `"fractionalBelowGround"` — conceptually between the first basement level and ground (UK lower ground, Italian
78
+ * seminterrato); floors to ordinal -1.
79
+ * - `"special"` — named by relationship to a SPECIFIC building's top (penthouse, roof, attic); no locale-independent
80
+ * ordinal exists. {@link levelToOrdinal} returns `undefined`.
81
+ * - `"fixedOrdinal"` — a specific named floor with its own fixed ordinal, independent of any number the caller supplies
82
+ * (Spanish PRINCIPAL is always ordinal 1).
83
+ */
84
+ export type LevelDesignatorKind = "ground" | "basement" | "numbered" | "fractionalAboveGround" | "fractionalBelowGround" | "special" | "fixedOrdinal";
85
+ /** One row of a per-language-family level-designator lexicon. */
86
+ export interface LevelDesignatorRow {
87
+ /** Canonical designator key (the language's native canonical spelling, uppercase). */
88
+ code: string;
89
+ /** Human-readable name — the native word plus an English gloss in parentheses. */
90
+ name: string;
91
+ /** Recognized surface variants, including the canonical code itself and common ASCII-folded / abbreviated spellings. */
92
+ variants: readonly string[];
93
+ /** How this designator maps to an ordinal — see {@link LevelDesignatorKind}. */
94
+ kind: LevelDesignatorKind;
95
+ /** True when a secondary number typically follows ("FL 3", "B 2"); false for standalone designators ("EG", "RDC"). */
96
+ requiresNumber: boolean;
97
+ /**
98
+ * Only present when `kind` is `"fixedOrdinal"` — the designator's own fixed ordinal, independent of any passed
99
+ * number.
100
+ */
101
+ fixedOrdinal?: number;
102
+ }
103
+ /**
104
+ * English (American, British, Canadian, Australian, …) floor/level vocabulary. This is the GENERIC English lexicon for
105
+ * the ordinal-semantics table; it doesn't replace the more detailed per-system lexicons in
106
+ * {@link "./us/floor-designator.ts"} (USPS Pub-28 C2) or {@link "./au/level-designator.ts"} (AS 4590.1 / AMAS) — those
107
+ * drive span-proposer/synthesis vocabulary for their own address system. This table exists to answer a narrower
108
+ * question for ANY English-speaking locale: given a designator + number, what ordinal does it name.
109
+ */
110
+ export declare const EN_LEVEL_DESIGNATORS: readonly [{
111
+ readonly code: "FLOOR";
112
+ readonly name: "Floor";
113
+ readonly variants: readonly ["FLOOR", "FL", "FLR", "LEVEL", "LVL"];
114
+ readonly kind: "numbered";
115
+ readonly requiresNumber: true;
116
+ }, {
117
+ readonly code: "BASEMENT";
118
+ readonly name: "Basement";
119
+ readonly variants: readonly ["BASEMENT", "BSMT", "B"];
120
+ readonly kind: "basement";
121
+ readonly requiresNumber: true;
122
+ }, {
123
+ readonly code: "PENTHOUSE";
124
+ readonly name: "Penthouse";
125
+ readonly variants: readonly ["PENTHOUSE", "PH"];
126
+ readonly kind: "special";
127
+ readonly requiresNumber: false;
128
+ }, {
129
+ readonly code: "GROUND";
130
+ readonly name: "Ground";
131
+ readonly variants: readonly ["GROUND", "G", "GROUND FLOOR", "GF"];
132
+ readonly kind: "ground";
133
+ readonly requiresNumber: false;
134
+ }, {
135
+ readonly code: "LOWER GROUND";
136
+ readonly name: "Lower Ground";
137
+ readonly variants: readonly ["LOWER GROUND", "LG"];
138
+ readonly kind: "fractionalBelowGround";
139
+ readonly requiresNumber: false;
140
+ }, {
141
+ readonly code: "UPPER GROUND";
142
+ readonly name: "Upper Ground";
143
+ readonly variants: readonly ["UPPER GROUND", "UG"];
144
+ readonly kind: "fractionalAboveGround";
145
+ readonly requiresNumber: false;
146
+ }, {
147
+ readonly code: "MEZZANINE";
148
+ readonly name: "Mezzanine";
149
+ readonly variants: readonly ["MEZZANINE", "MEZZ", "M"];
150
+ readonly kind: "fractionalAboveGround";
151
+ readonly requiresNumber: false;
152
+ }, {
153
+ readonly code: "ROOF";
154
+ readonly name: "Roof";
155
+ readonly variants: readonly ["ROOF", "RF"];
156
+ readonly kind: "special";
157
+ readonly requiresNumber: false;
158
+ }];
159
+ /** French (France, and — for the vocabulary, not the numbering convention — Francophone Canada) floor/level vocabulary. */
160
+ export declare const FR_LEVEL_DESIGNATORS: readonly [{
161
+ readonly code: "ÉTAGE";
162
+ readonly name: "Étage (Floor)";
163
+ readonly variants: readonly ["ÉTAGE", "ETAGE", "ÉT", "ET"];
164
+ readonly kind: "numbered";
165
+ readonly requiresNumber: true;
166
+ }, {
167
+ readonly code: "RDC";
168
+ readonly name: "Rez-de-chaussée (Ground floor)";
169
+ readonly variants: readonly ["RDC", "REZ-DE-CHAUSSÉE", "REZ-DE-CHAUSSEE", "REZ DE CHAUSSEE"];
170
+ readonly kind: "ground";
171
+ readonly requiresNumber: false;
172
+ }, {
173
+ readonly code: "SOUS-SOL";
174
+ readonly name: "Sous-sol (Basement)";
175
+ readonly variants: readonly ["SOUS-SOL", "SOUS SOL", "SS"];
176
+ readonly kind: "basement";
177
+ readonly requiresNumber: true;
178
+ }, {
179
+ readonly code: "ENTRESOL";
180
+ readonly name: "Entresol (Mezzanine)";
181
+ readonly variants: readonly ["ENTRESOL"];
182
+ readonly kind: "fractionalAboveGround";
183
+ readonly requiresNumber: false;
184
+ }];
185
+ /** German floor/level vocabulary (the -geschoss family). */
186
+ export declare const DE_LEVEL_DESIGNATORS: readonly [{
187
+ readonly code: "OBERGESCHOSS";
188
+ readonly name: "Obergeschoss (Upper floor)";
189
+ readonly variants: readonly ["OBERGESCHOSS", "OG"];
190
+ readonly kind: "numbered";
191
+ readonly requiresNumber: true;
192
+ }, {
193
+ readonly code: "ERDGESCHOSS";
194
+ readonly name: "Erdgeschoss (Ground floor)";
195
+ readonly variants: readonly ["ERDGESCHOSS", "EG"];
196
+ readonly kind: "ground";
197
+ readonly requiresNumber: false;
198
+ }, {
199
+ readonly code: "UNTERGESCHOSS";
200
+ readonly name: "Untergeschoss (Basement)";
201
+ readonly variants: readonly ["UNTERGESCHOSS", "UG"];
202
+ readonly kind: "basement";
203
+ readonly requiresNumber: true;
204
+ }, {
205
+ readonly code: "DACHGESCHOSS";
206
+ readonly name: "Dachgeschoss (Attic/roof floor)";
207
+ readonly variants: readonly ["DACHGESCHOSS", "DG"];
208
+ readonly kind: "special";
209
+ readonly requiresNumber: false;
210
+ }, {
211
+ readonly code: "ZWISCHENGESCHOSS";
212
+ readonly name: "Zwischengeschoss (Mezzanine)";
213
+ readonly variants: readonly ["ZWISCHENGESCHOSS", "ZG"];
214
+ readonly kind: "fractionalAboveGround";
215
+ readonly requiresNumber: false;
216
+ }];
217
+ /**
218
+ * Spanish floor/level vocabulary. PRINCIPAL and ENTRESUELO offsets vary by city and building age (see the module
219
+ * header) — encoded here as a single convention, not an empirical universal.
220
+ */
221
+ export declare const ES_LEVEL_DESIGNATORS: readonly [{
222
+ readonly code: "PLANTA";
223
+ readonly name: "Planta/Piso (Floor)";
224
+ readonly variants: readonly ["PLANTA", "PISO"];
225
+ readonly kind: "numbered";
226
+ readonly requiresNumber: true;
227
+ }, {
228
+ readonly code: "PLANTA BAJA";
229
+ readonly name: "Planta Baja (Ground floor)";
230
+ readonly variants: readonly ["PLANTA BAJA", "BAJO", "PB"];
231
+ readonly kind: "ground";
232
+ readonly requiresNumber: false;
233
+ }, {
234
+ readonly code: "ENTRESUELO";
235
+ readonly name: "Entresuelo (Mezzanine)";
236
+ readonly variants: readonly ["ENTRESUELO"];
237
+ readonly kind: "fractionalAboveGround";
238
+ readonly requiresNumber: false;
239
+ }, {
240
+ readonly code: "PRINCIPAL";
241
+ readonly name: "Principal";
242
+ readonly variants: readonly ["PRINCIPAL"];
243
+ readonly kind: "fixedOrdinal";
244
+ readonly requiresNumber: false;
245
+ readonly fixedOrdinal: 1;
246
+ }, {
247
+ readonly code: "SÓTANO";
248
+ readonly name: "Sótano (Basement)";
249
+ readonly variants: readonly ["SÓTANO", "SOTANO"];
250
+ readonly kind: "basement";
251
+ readonly requiresNumber: true;
252
+ }, {
253
+ readonly code: "ÁTICO";
254
+ readonly name: "Ático (Attic/penthouse)";
255
+ readonly variants: readonly ["ÁTICO", "ATICO"];
256
+ readonly kind: "special";
257
+ readonly requiresNumber: false;
258
+ }];
259
+ /** Italian floor/level vocabulary. */
260
+ export declare const IT_LEVEL_DESIGNATORS: readonly [{
261
+ readonly code: "PIANO";
262
+ readonly name: "Piano (Floor)";
263
+ readonly variants: readonly ["PIANO"];
264
+ readonly kind: "numbered";
265
+ readonly requiresNumber: true;
266
+ }, {
267
+ readonly code: "PIANO TERRA";
268
+ readonly name: "Piano Terra (Ground floor)";
269
+ readonly variants: readonly ["PIANO TERRA", "PT"];
270
+ readonly kind: "ground";
271
+ readonly requiresNumber: false;
272
+ }, {
273
+ readonly code: "SEMINTERRATO";
274
+ readonly name: "Seminterrato (Semi-basement)";
275
+ readonly variants: readonly ["SEMINTERRATO"];
276
+ readonly kind: "fractionalBelowGround";
277
+ readonly requiresNumber: false;
278
+ }, {
279
+ readonly code: "ATTICO";
280
+ readonly name: "Attico (Attic/penthouse)";
281
+ readonly variants: readonly ["ATTICO"];
282
+ readonly kind: "special";
283
+ readonly requiresNumber: false;
284
+ }];
285
+ /** Portuguese floor/level vocabulary. */
286
+ export declare const PT_LEVEL_DESIGNATORS: readonly [{
287
+ readonly code: "ANDAR";
288
+ readonly name: "Andar (Floor)";
289
+ readonly variants: readonly ["ANDAR"];
290
+ readonly kind: "numbered";
291
+ readonly requiresNumber: true;
292
+ }, {
293
+ readonly code: "RÉS-DO-CHÃO";
294
+ readonly name: "Rés-do-chão (Ground floor)";
295
+ readonly variants: readonly ["RÉS-DO-CHÃO", "RES-DO-CHAO", "RC"];
296
+ readonly kind: "ground";
297
+ readonly requiresNumber: false;
298
+ }, {
299
+ readonly code: "CAVE";
300
+ readonly name: "Cave (Basement)";
301
+ readonly variants: readonly ["CAVE"];
302
+ readonly kind: "basement";
303
+ readonly requiresNumber: true;
304
+ }];
305
+ /** Dutch floor/level vocabulary. */
306
+ export declare const NL_LEVEL_DESIGNATORS: readonly [{
307
+ readonly code: "VERDIEPING";
308
+ readonly name: "Verdieping (Floor)";
309
+ readonly variants: readonly ["VERDIEPING", "VERD"];
310
+ readonly kind: "numbered";
311
+ readonly requiresNumber: true;
312
+ }, {
313
+ readonly code: "BEGANE GROND";
314
+ readonly name: "Begane Grond (Ground floor)";
315
+ readonly variants: readonly ["BEGANE GROND", "BG"];
316
+ readonly kind: "ground";
317
+ readonly requiresNumber: false;
318
+ }, {
319
+ readonly code: "KELDER";
320
+ readonly name: "Kelder (Basement)";
321
+ readonly variants: readonly ["KELDER"];
322
+ readonly kind: "basement";
323
+ readonly requiresNumber: true;
324
+ }];
325
+ /**
326
+ * Japanese (and generic CJK numeral+letter) floor/level vocabulary. Japanese addresses write the numbered floor as a
327
+ * trailing "F" suffix on the number ("2F", "地下1F"/"B1F") or the kanji "階" ("2階"); there is no distinct bare word for
328
+ * "ground floor" the way RDC/EG/PLANTA BAJA exist in Europe — "1F"/"1階" already IS ground (handled by the `"numbered"`
329
+ * kind + the ja-JP `firstNumberedIsGround: true` convention, not a separate `"ground"` row). "B" (and "地下", literally
330
+ * "underground") name the basement count the same way English "B1" does.
331
+ */
332
+ export declare const JA_LEVEL_DESIGNATORS: readonly [{
333
+ readonly code: "F";
334
+ readonly name: "階 (Floor)";
335
+ readonly variants: readonly ["F", "階"];
336
+ readonly kind: "numbered";
337
+ readonly requiresNumber: true;
338
+ }, {
339
+ readonly code: "B";
340
+ readonly name: "地下 (Basement)";
341
+ readonly variants: readonly ["B", "地下"];
342
+ readonly kind: "basement";
343
+ readonly requiresNumber: true;
344
+ }, {
345
+ readonly code: "RF";
346
+ readonly name: "屋上 (Rooftop)";
347
+ readonly variants: readonly ["RF", "屋上", "ROOFTOP"];
348
+ readonly kind: "special";
349
+ readonly requiresNumber: false;
350
+ }];
351
+ /** Swedish floor/level vocabulary. */
352
+ export declare const SV_LEVEL_DESIGNATORS: readonly [{
353
+ readonly code: "VÅNING";
354
+ readonly name: "Våning (Floor)";
355
+ readonly variants: readonly ["VÅNING", "VANING"];
356
+ readonly kind: "numbered";
357
+ readonly requiresNumber: true;
358
+ }, {
359
+ readonly code: "BOTTENVÅNING";
360
+ readonly name: "Bottenvåning (Ground floor)";
361
+ readonly variants: readonly ["BOTTENVÅNING", "BOTTENVANING", "BV"];
362
+ readonly kind: "ground";
363
+ readonly requiresNumber: false;
364
+ }, {
365
+ readonly code: "KÄLLARE";
366
+ readonly name: "Källare (Basement)";
367
+ readonly variants: readonly ["KÄLLARE", "KALLARE"];
368
+ readonly kind: "basement";
369
+ readonly requiresNumber: true;
370
+ }];
371
+ /**
372
+ * Norwegian floor/level vocabulary. GATEPLAN ("street level") is a lower-confidence, regional inclusion for the
373
+ * ground-floor row — see the module header's Nordic-vocabulary caveat.
374
+ */
375
+ export declare const NO_LEVEL_DESIGNATORS: readonly [{
376
+ readonly code: "ETASJE";
377
+ readonly name: "Etasje (Floor)";
378
+ readonly variants: readonly ["ETASJE"];
379
+ readonly kind: "numbered";
380
+ readonly requiresNumber: true;
381
+ }, {
382
+ readonly code: "GATEPLAN";
383
+ readonly name: "Gateplan (Street/ground level)";
384
+ readonly variants: readonly ["GATEPLAN"];
385
+ readonly kind: "ground";
386
+ readonly requiresNumber: false;
387
+ }, {
388
+ readonly code: "KJELLER";
389
+ readonly name: "Kjeller (Basement)";
390
+ readonly variants: readonly ["KJELLER"];
391
+ readonly kind: "basement";
392
+ readonly requiresNumber: true;
393
+ }];
394
+ /** Danish floor/level vocabulary. STUEN/STUEETAGE ("st.") is the standard ground-floor term seen on Danish addresses. */
395
+ export declare const DA_LEVEL_DESIGNATORS: readonly [{
396
+ readonly code: "ETAGE";
397
+ readonly name: "Etage (Floor)";
398
+ readonly variants: readonly ["ETAGE"];
399
+ readonly kind: "numbered";
400
+ readonly requiresNumber: true;
401
+ }, {
402
+ readonly code: "STUEN";
403
+ readonly name: "Stuen/Stueetage (Ground floor)";
404
+ readonly variants: readonly ["STUEN", "STUEETAGE", "ST"];
405
+ readonly kind: "ground";
406
+ readonly requiresNumber: false;
407
+ }, {
408
+ readonly code: "KÆLDER";
409
+ readonly name: "Kælder (Basement)";
410
+ readonly variants: readonly ["KÆLDER", "KAELDER"];
411
+ readonly kind: "basement";
412
+ readonly requiresNumber: true;
413
+ }];
414
+ /** A bare language-family tag — the key into {@link LEVEL_DESIGNATORS_BY_FAMILY}. */
415
+ export type LevelLocaleFamily = "en" | "fr" | "de" | "es" | "it" | "pt" | "nl" | "ja" | "sv" | "no" | "da";
416
+ /** Every language family's level-designator lexicon, keyed by bare language tag. */
417
+ export declare const LEVEL_DESIGNATORS_BY_FAMILY: Readonly<Record<LevelLocaleFamily, readonly LevelDesignatorRow[]>>;
418
+ /**
419
+ * The locale's level-numbering convention: does the FIRST numbered level ("1st floor", "1F", "étage 1", …) coincide
420
+ * with ground (ordinal 0), or sit one storey above it?
421
+ */
422
+ export interface LevelOrdinalConvention {
423
+ /**
424
+ * True for the US/Canada/Japan-style convention, where the first numbered level IS ground ("1st floor" = ground floor
425
+ * = ordinal 0, so ordinal = number - 1). False for the continental-European / IMDF-style convention, where ground has
426
+ * its own designator (RDC, EG, PLANTA BAJA, …) and the first NUMBERED level sits one storey above it (ordinal =
427
+ * number) — also the convention in the UK.
428
+ */
429
+ readonly firstNumberedIsGround: boolean;
430
+ }
431
+ /**
432
+ * Per-FULL-LOCALE ordinal convention overrides. Keyed by full locale (not bare language family) because English splits
433
+ * by country even though the vocabulary doesn't: American and Canadian buildings number the ground floor "1"; British
434
+ * buildings do not. "CA" (English or French) buckets with the US/Japan convention per real-world North American
435
+ * building-code practice, though individual Quebec buildings can and do vary.
436
+ */
437
+ export declare const LEVEL_ORDINAL_CONVENTIONS: Readonly<Record<string, LevelOrdinalConvention>>;
438
+ /**
439
+ * Look up a level designator (by canonical code, abbreviation, or any recognized variant) within a locale's language
440
+ * family. Case-insensitive. Returns `undefined` when the locale's family is unknown to this module, or the token isn't
441
+ * a recognized designator in that family.
442
+ */
443
+ export declare function lookupLevelDesignator(designator: string, locale: string): LevelDesignatorRow | undefined;
444
+ /** True when `input` is a recognized level designator (case-insensitive) in `locale`'s language family. */
445
+ export declare function isLevelDesignatorToken(input: unknown, locale: string): boolean;
446
+ /**
447
+ * Map a (designator, number) pair to an IMDF-style signed integer ordinal, given the semantics of `locale`. Ground is
448
+ * always 0. Returns `undefined` when:
449
+ *
450
+ * - `locale`'s language family has no lexicon in this module,
451
+ * - `designator` isn't a recognized token in that family,
452
+ * - The designator is `"special"` (penthouse/roof/attic — no locale-independent ordinal exists), or
453
+ * - The designator is `"numbered"` but either `number` is missing or the locale has no resolvable ordinal convention (a
454
+ * bare "en" locale, for example).
455
+ *
456
+ * @example
457
+ * levelToOrdinal("FL", 1, "en-US") // → 0 (US: 1st floor IS ground)
458
+ * levelToOrdinal("étage", 1, "fr-FR") // → 1 (FR: 1st étage is one storey above ground)
459
+ * levelToOrdinal("EG", undefined, "de-DE") // → 0 (ground, number ignored)
460
+ * levelToOrdinal("B", 1, "en-US") // → -1 (basement 1)
461
+ * levelToOrdinal("F", 1, "ja-JP") // → 0 (JP: 1F IS ground)
462
+ * levelToOrdinal("B", 1, "ja-JP") // → -1 (JP: B1F)
463
+ */
464
+ export declare function levelToOrdinal(designator: string, number: number | undefined, locale: string): number | undefined;
465
+ //# sourceMappingURL=level-semantics.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"level-semantics.d.ts","sourceRoot":"","sources":["../level-semantics.ts"],"names":[],"mappings":"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"}