@escape-game-over/atlas 0.1.73 → 0.1.74
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/package.json +1 -1
- package/src/address-formats.ts +669 -0
- package/src/contact.ts +53 -2
- package/src/index.ts +2 -0
- package/src/jsonld/place.ts +3 -1
package/package.json
CHANGED
|
@@ -0,0 +1,669 @@
|
|
|
1
|
+
import type { CountryCode } from "./countries.ts";
|
|
2
|
+
|
|
3
|
+
/** A part of `PostalAddress` an address layout can print. */
|
|
4
|
+
export type AddressField = "street" | "locality" | "region" | "postalCode";
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* One piece of a line: a field, or text the country always prints.
|
|
8
|
+
*
|
|
9
|
+
* A field brings its own punctuation, so a missing field takes it with it and
|
|
10
|
+
* nothing is left to clean up:
|
|
11
|
+
*
|
|
12
|
+
* - `separator` sits between this field and whatever the line already holds,
|
|
13
|
+
* and is dropped when the field opens the line: `, ` before a US state.
|
|
14
|
+
* - `prefix` belongs to the value itself and goes wherever it goes: the `CH-`
|
|
15
|
+
* of a Swiss postal code.
|
|
16
|
+
*/
|
|
17
|
+
export type AddressPart =
|
|
18
|
+
| {
|
|
19
|
+
readonly field: AddressField;
|
|
20
|
+
readonly separator?: string;
|
|
21
|
+
readonly prefix?: string;
|
|
22
|
+
}
|
|
23
|
+
| { readonly text: string };
|
|
24
|
+
|
|
25
|
+
/** A country's address, line by line. */
|
|
26
|
+
export type AddressLayout = readonly (readonly AddressPart[])[];
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* How a country lays out an address.
|
|
30
|
+
*
|
|
31
|
+
* Converted once from Google's address metadata, the dataset behind
|
|
32
|
+
* libaddressinput (Apache License 2.0), fetched 2026-10-02 one country at a
|
|
33
|
+
* time: <https://chromium-i18n.appspot.com/ssl-address/data/DE>, the `fmt`
|
|
34
|
+
* field. The bare `/data/` path answers `{}`. Google writes each layout as a
|
|
35
|
+
* format string, `%A%n%C, %S %Z`; this is the same layout as data, so nothing
|
|
36
|
+
* parses a string at run time.
|
|
37
|
+
*
|
|
38
|
+
* The conversion:
|
|
39
|
+
* - `%A` street
|
|
40
|
+
* - `%C` locality
|
|
41
|
+
* - `%S` region
|
|
42
|
+
* - `%Z` postal code
|
|
43
|
+
* became fields; text before a line's first field became that field's
|
|
44
|
+
* `prefix`, and text between two fields the second one's `separator`; a line of
|
|
45
|
+
* text alone became a `text` part. The recipient lines (`%N`, `%O`) and the
|
|
46
|
+
* fields `PostalAddress` does not carry — district, sorting code, India's
|
|
47
|
+
* extra lines — were dropped, with the punctuation that belonged to them.
|
|
48
|
+
*
|
|
49
|
+
* Countries that share a layout share a branch, in order of their first code.
|
|
50
|
+
* To update one, take its format from that address again and convert it the
|
|
51
|
+
* same way. A country listed twice is caught by Biome's `noDuplicateCase`.
|
|
52
|
+
*/
|
|
53
|
+
export function addressLayout(country: CountryCode): AddressLayout {
|
|
54
|
+
switch (country) {
|
|
55
|
+
case "AD":
|
|
56
|
+
case "AT":
|
|
57
|
+
case "BA":
|
|
58
|
+
case "BE":
|
|
59
|
+
case "BG":
|
|
60
|
+
case "BL":
|
|
61
|
+
case "CY":
|
|
62
|
+
case "CZ":
|
|
63
|
+
case "DE":
|
|
64
|
+
case "DK":
|
|
65
|
+
case "DO":
|
|
66
|
+
case "DZ":
|
|
67
|
+
case "EH":
|
|
68
|
+
case "ET":
|
|
69
|
+
case "FR":
|
|
70
|
+
case "GE":
|
|
71
|
+
case "GF":
|
|
72
|
+
case "GL":
|
|
73
|
+
case "GP":
|
|
74
|
+
case "GR":
|
|
75
|
+
case "GW":
|
|
76
|
+
case "IS":
|
|
77
|
+
case "KG":
|
|
78
|
+
case "KW":
|
|
79
|
+
case "LA":
|
|
80
|
+
case "LR":
|
|
81
|
+
case "MA":
|
|
82
|
+
case "ME":
|
|
83
|
+
case "MF":
|
|
84
|
+
case "MG":
|
|
85
|
+
case "MK":
|
|
86
|
+
case "MQ":
|
|
87
|
+
case "NC":
|
|
88
|
+
case "NE":
|
|
89
|
+
case "NL":
|
|
90
|
+
case "NO":
|
|
91
|
+
case "PL":
|
|
92
|
+
case "PM":
|
|
93
|
+
case "PT":
|
|
94
|
+
case "PY":
|
|
95
|
+
case "RE":
|
|
96
|
+
case "RS":
|
|
97
|
+
case "SJ":
|
|
98
|
+
case "SK":
|
|
99
|
+
case "SM":
|
|
100
|
+
case "SN":
|
|
101
|
+
case "TJ":
|
|
102
|
+
case "TM":
|
|
103
|
+
case "TN":
|
|
104
|
+
case "TZ":
|
|
105
|
+
case "VA":
|
|
106
|
+
case "WF":
|
|
107
|
+
case "XK":
|
|
108
|
+
case "YT":
|
|
109
|
+
case "ZM":
|
|
110
|
+
return [
|
|
111
|
+
[{ field: "street" }],
|
|
112
|
+
[
|
|
113
|
+
{ field: "postalCode" },
|
|
114
|
+
{ field: "locality", separator: " " },
|
|
115
|
+
],
|
|
116
|
+
];
|
|
117
|
+
case "AE":
|
|
118
|
+
case "NR":
|
|
119
|
+
return [[{ field: "street" }], [{ field: "region" }]];
|
|
120
|
+
case "AF":
|
|
121
|
+
case "AI":
|
|
122
|
+
case "FK":
|
|
123
|
+
case "GB":
|
|
124
|
+
case "GS":
|
|
125
|
+
case "IM":
|
|
126
|
+
case "IO":
|
|
127
|
+
case "KE":
|
|
128
|
+
case "LK":
|
|
129
|
+
case "NA":
|
|
130
|
+
case "PN":
|
|
131
|
+
case "SD":
|
|
132
|
+
case "SH":
|
|
133
|
+
case "SZ":
|
|
134
|
+
case "TC":
|
|
135
|
+
case "TT":
|
|
136
|
+
case "VG":
|
|
137
|
+
case "ZA":
|
|
138
|
+
return [
|
|
139
|
+
[{ field: "street" }],
|
|
140
|
+
[{ field: "locality" }],
|
|
141
|
+
[{ field: "postalCode" }],
|
|
142
|
+
];
|
|
143
|
+
case "AL":
|
|
144
|
+
case "EC":
|
|
145
|
+
case "MU":
|
|
146
|
+
case "OM":
|
|
147
|
+
return [
|
|
148
|
+
[{ field: "street" }],
|
|
149
|
+
[{ field: "postalCode" }],
|
|
150
|
+
[{ field: "locality" }],
|
|
151
|
+
];
|
|
152
|
+
case "AM":
|
|
153
|
+
return [
|
|
154
|
+
[{ field: "street" }],
|
|
155
|
+
[{ field: "postalCode" }],
|
|
156
|
+
[{ field: "locality" }],
|
|
157
|
+
[{ field: "region" }],
|
|
158
|
+
];
|
|
159
|
+
case "AR":
|
|
160
|
+
case "CL":
|
|
161
|
+
case "CV":
|
|
162
|
+
case "MY":
|
|
163
|
+
case "UZ":
|
|
164
|
+
return [
|
|
165
|
+
[{ field: "street" }],
|
|
166
|
+
[
|
|
167
|
+
{ field: "postalCode" },
|
|
168
|
+
{ field: "locality", separator: " " },
|
|
169
|
+
],
|
|
170
|
+
[{ field: "region" }],
|
|
171
|
+
];
|
|
172
|
+
case "AS":
|
|
173
|
+
case "AU":
|
|
174
|
+
case "CA":
|
|
175
|
+
case "CC":
|
|
176
|
+
case "CX":
|
|
177
|
+
case "FM":
|
|
178
|
+
case "HM":
|
|
179
|
+
case "MH":
|
|
180
|
+
case "MP":
|
|
181
|
+
case "NF":
|
|
182
|
+
case "PW":
|
|
183
|
+
case "UM":
|
|
184
|
+
case "VI":
|
|
185
|
+
return [
|
|
186
|
+
[{ field: "street" }],
|
|
187
|
+
[
|
|
188
|
+
{ field: "locality" },
|
|
189
|
+
{ field: "region", separator: " " },
|
|
190
|
+
{ field: "postalCode", separator: " " },
|
|
191
|
+
],
|
|
192
|
+
];
|
|
193
|
+
case "AX":
|
|
194
|
+
return [
|
|
195
|
+
[{ field: "street" }],
|
|
196
|
+
[
|
|
197
|
+
{ field: "postalCode", prefix: "AX-" },
|
|
198
|
+
{ field: "locality", separator: " " },
|
|
199
|
+
],
|
|
200
|
+
[{ text: "ÅLAND" }],
|
|
201
|
+
];
|
|
202
|
+
case "AZ":
|
|
203
|
+
return [
|
|
204
|
+
[{ field: "street" }],
|
|
205
|
+
[
|
|
206
|
+
{ field: "postalCode", prefix: "AZ " },
|
|
207
|
+
{ field: "locality", separator: " " },
|
|
208
|
+
],
|
|
209
|
+
];
|
|
210
|
+
case "BB":
|
|
211
|
+
case "SO":
|
|
212
|
+
case "US":
|
|
213
|
+
return [
|
|
214
|
+
[{ field: "street" }],
|
|
215
|
+
[
|
|
216
|
+
{ field: "locality" },
|
|
217
|
+
{ field: "region", separator: ", " },
|
|
218
|
+
{ field: "postalCode", separator: " " },
|
|
219
|
+
],
|
|
220
|
+
];
|
|
221
|
+
case "BD":
|
|
222
|
+
return [
|
|
223
|
+
[{ field: "street" }],
|
|
224
|
+
[
|
|
225
|
+
{ field: "locality" },
|
|
226
|
+
{ field: "postalCode", separator: " - " },
|
|
227
|
+
],
|
|
228
|
+
];
|
|
229
|
+
case "BH":
|
|
230
|
+
case "BM":
|
|
231
|
+
case "BN":
|
|
232
|
+
case "BT":
|
|
233
|
+
case "GU":
|
|
234
|
+
case "IL":
|
|
235
|
+
case "JO":
|
|
236
|
+
case "KH":
|
|
237
|
+
case "LB":
|
|
238
|
+
case "LS":
|
|
239
|
+
case "MT":
|
|
240
|
+
case "MV":
|
|
241
|
+
case "NP":
|
|
242
|
+
case "NZ":
|
|
243
|
+
case "SA":
|
|
244
|
+
case "VC":
|
|
245
|
+
return [
|
|
246
|
+
[{ field: "street" }],
|
|
247
|
+
[
|
|
248
|
+
{ field: "locality" },
|
|
249
|
+
{ field: "postalCode", separator: " " },
|
|
250
|
+
],
|
|
251
|
+
];
|
|
252
|
+
case "BR":
|
|
253
|
+
return [
|
|
254
|
+
[{ field: "street" }],
|
|
255
|
+
[{ field: "locality" }, { field: "region", separator: "-" }],
|
|
256
|
+
[{ field: "postalCode" }],
|
|
257
|
+
];
|
|
258
|
+
case "BS":
|
|
259
|
+
case "KN":
|
|
260
|
+
return [
|
|
261
|
+
[{ field: "street" }],
|
|
262
|
+
[{ field: "locality" }, { field: "region", separator: ", " }],
|
|
263
|
+
];
|
|
264
|
+
case "BY":
|
|
265
|
+
return [
|
|
266
|
+
[{ field: "street" }],
|
|
267
|
+
[
|
|
268
|
+
{ field: "postalCode" },
|
|
269
|
+
{ field: "locality", separator: ", " },
|
|
270
|
+
],
|
|
271
|
+
[{ field: "region" }],
|
|
272
|
+
];
|
|
273
|
+
case "CH":
|
|
274
|
+
return [
|
|
275
|
+
[{ field: "street" }],
|
|
276
|
+
[
|
|
277
|
+
{ field: "postalCode", prefix: "CH-" },
|
|
278
|
+
{ field: "locality", separator: " " },
|
|
279
|
+
],
|
|
280
|
+
];
|
|
281
|
+
case "CI":
|
|
282
|
+
return [
|
|
283
|
+
[{ field: "street" }, { field: "locality", separator: " " }],
|
|
284
|
+
];
|
|
285
|
+
// No space between region and town, as both write them.
|
|
286
|
+
case "CN":
|
|
287
|
+
case "TW":
|
|
288
|
+
return [
|
|
289
|
+
[{ field: "postalCode" }],
|
|
290
|
+
[{ field: "region" }, { field: "locality" }],
|
|
291
|
+
[{ field: "street" }],
|
|
292
|
+
];
|
|
293
|
+
case "CO":
|
|
294
|
+
return [
|
|
295
|
+
[{ field: "street" }],
|
|
296
|
+
[
|
|
297
|
+
{ field: "locality" },
|
|
298
|
+
{ field: "region", separator: ", " },
|
|
299
|
+
{ field: "postalCode", separator: ", " },
|
|
300
|
+
],
|
|
301
|
+
];
|
|
302
|
+
case "CR":
|
|
303
|
+
return [
|
|
304
|
+
[{ field: "street" }],
|
|
305
|
+
[{ field: "region" }, { field: "locality", separator: ", " }],
|
|
306
|
+
[{ field: "postalCode" }],
|
|
307
|
+
];
|
|
308
|
+
case "CU":
|
|
309
|
+
return [
|
|
310
|
+
[{ field: "street" }],
|
|
311
|
+
[{ field: "locality" }, { field: "region", separator: " " }],
|
|
312
|
+
[{ field: "postalCode" }],
|
|
313
|
+
];
|
|
314
|
+
case "EE":
|
|
315
|
+
case "ES":
|
|
316
|
+
case "IT":
|
|
317
|
+
case "PF":
|
|
318
|
+
case "UY":
|
|
319
|
+
return [
|
|
320
|
+
[{ field: "street" }],
|
|
321
|
+
[
|
|
322
|
+
{ field: "postalCode" },
|
|
323
|
+
{ field: "locality", separator: " " },
|
|
324
|
+
{ field: "region", separator: " " },
|
|
325
|
+
],
|
|
326
|
+
];
|
|
327
|
+
case "EG":
|
|
328
|
+
case "IE":
|
|
329
|
+
case "RU":
|
|
330
|
+
case "UA":
|
|
331
|
+
return [
|
|
332
|
+
[{ field: "street" }],
|
|
333
|
+
[{ field: "locality" }],
|
|
334
|
+
[{ field: "region" }],
|
|
335
|
+
[{ field: "postalCode" }],
|
|
336
|
+
];
|
|
337
|
+
case "FI":
|
|
338
|
+
return [
|
|
339
|
+
[{ field: "street" }],
|
|
340
|
+
[
|
|
341
|
+
{ field: "postalCode", prefix: "FI-" },
|
|
342
|
+
{ field: "locality", separator: " " },
|
|
343
|
+
],
|
|
344
|
+
];
|
|
345
|
+
case "FO":
|
|
346
|
+
return [
|
|
347
|
+
[{ field: "street" }],
|
|
348
|
+
[
|
|
349
|
+
{ field: "postalCode", prefix: "FO" },
|
|
350
|
+
{ field: "locality", separator: " " },
|
|
351
|
+
],
|
|
352
|
+
];
|
|
353
|
+
case "GG":
|
|
354
|
+
return [
|
|
355
|
+
[{ field: "street" }],
|
|
356
|
+
[{ field: "locality" }],
|
|
357
|
+
[{ text: "GUERNSEY" }],
|
|
358
|
+
[{ field: "postalCode" }],
|
|
359
|
+
];
|
|
360
|
+
case "GI":
|
|
361
|
+
return [
|
|
362
|
+
[{ field: "street" }],
|
|
363
|
+
[{ text: "GIBRALTAR" }],
|
|
364
|
+
[{ field: "postalCode" }],
|
|
365
|
+
];
|
|
366
|
+
case "GN":
|
|
367
|
+
return [
|
|
368
|
+
[
|
|
369
|
+
{ field: "postalCode" },
|
|
370
|
+
{ field: "street", separator: " " },
|
|
371
|
+
{ field: "locality", separator: " " },
|
|
372
|
+
],
|
|
373
|
+
];
|
|
374
|
+
case "GT":
|
|
375
|
+
return [
|
|
376
|
+
[{ field: "street" }],
|
|
377
|
+
[
|
|
378
|
+
{ field: "postalCode" },
|
|
379
|
+
{ field: "locality", separator: "- " },
|
|
380
|
+
],
|
|
381
|
+
];
|
|
382
|
+
case "HK":
|
|
383
|
+
return [
|
|
384
|
+
[{ field: "region" }],
|
|
385
|
+
[{ field: "locality" }],
|
|
386
|
+
[{ field: "street" }],
|
|
387
|
+
];
|
|
388
|
+
case "HN":
|
|
389
|
+
case "IQ":
|
|
390
|
+
return [
|
|
391
|
+
[{ field: "street" }],
|
|
392
|
+
[{ field: "locality" }, { field: "region", separator: ", " }],
|
|
393
|
+
[{ field: "postalCode" }],
|
|
394
|
+
];
|
|
395
|
+
case "HR":
|
|
396
|
+
return [
|
|
397
|
+
[{ field: "street" }],
|
|
398
|
+
[
|
|
399
|
+
{ field: "postalCode", prefix: "HR-" },
|
|
400
|
+
{ field: "locality", separator: " " },
|
|
401
|
+
],
|
|
402
|
+
];
|
|
403
|
+
case "HT":
|
|
404
|
+
return [
|
|
405
|
+
[{ field: "street" }],
|
|
406
|
+
[
|
|
407
|
+
{ field: "postalCode", prefix: "HT" },
|
|
408
|
+
{ field: "locality", separator: " " },
|
|
409
|
+
],
|
|
410
|
+
];
|
|
411
|
+
case "HU":
|
|
412
|
+
return [
|
|
413
|
+
[{ field: "locality" }],
|
|
414
|
+
[{ field: "street" }],
|
|
415
|
+
[{ field: "postalCode" }],
|
|
416
|
+
];
|
|
417
|
+
case "ID":
|
|
418
|
+
case "MN":
|
|
419
|
+
case "TH":
|
|
420
|
+
case "VN":
|
|
421
|
+
return [
|
|
422
|
+
[{ field: "street" }],
|
|
423
|
+
[{ field: "locality" }],
|
|
424
|
+
[{ field: "region" }, { field: "postalCode", separator: " " }],
|
|
425
|
+
];
|
|
426
|
+
case "IN":
|
|
427
|
+
case "NG":
|
|
428
|
+
case "PE":
|
|
429
|
+
return [
|
|
430
|
+
[{ field: "street" }],
|
|
431
|
+
[
|
|
432
|
+
{ field: "locality" },
|
|
433
|
+
{ field: "postalCode", separator: " " },
|
|
434
|
+
],
|
|
435
|
+
[{ field: "region" }],
|
|
436
|
+
];
|
|
437
|
+
case "IR":
|
|
438
|
+
return [
|
|
439
|
+
[{ field: "region" }],
|
|
440
|
+
[{ field: "locality" }],
|
|
441
|
+
[{ field: "street" }],
|
|
442
|
+
[{ field: "postalCode" }],
|
|
443
|
+
];
|
|
444
|
+
case "JE":
|
|
445
|
+
return [
|
|
446
|
+
[{ field: "street" }],
|
|
447
|
+
[{ field: "locality" }],
|
|
448
|
+
[{ text: "JERSEY" }],
|
|
449
|
+
[{ field: "postalCode" }],
|
|
450
|
+
];
|
|
451
|
+
case "JM":
|
|
452
|
+
case "PA":
|
|
453
|
+
case "SC":
|
|
454
|
+
case "SR":
|
|
455
|
+
case "TV":
|
|
456
|
+
return [
|
|
457
|
+
[{ field: "street" }],
|
|
458
|
+
[{ field: "locality" }],
|
|
459
|
+
[{ field: "region" }],
|
|
460
|
+
];
|
|
461
|
+
case "JP":
|
|
462
|
+
return [
|
|
463
|
+
[{ field: "postalCode", prefix: "〒" }],
|
|
464
|
+
[{ field: "region" }],
|
|
465
|
+
[{ field: "street" }],
|
|
466
|
+
];
|
|
467
|
+
case "KI":
|
|
468
|
+
return [
|
|
469
|
+
[{ field: "street" }],
|
|
470
|
+
[{ field: "region" }],
|
|
471
|
+
[{ field: "locality" }],
|
|
472
|
+
];
|
|
473
|
+
case "KP":
|
|
474
|
+
case "KZ":
|
|
475
|
+
return [
|
|
476
|
+
[{ field: "postalCode" }],
|
|
477
|
+
[{ field: "region" }],
|
|
478
|
+
[{ field: "locality" }],
|
|
479
|
+
[{ field: "street" }],
|
|
480
|
+
];
|
|
481
|
+
case "KR":
|
|
482
|
+
return [
|
|
483
|
+
[{ field: "region" }, { field: "locality", separator: " " }],
|
|
484
|
+
[{ field: "street" }],
|
|
485
|
+
[{ field: "postalCode" }],
|
|
486
|
+
];
|
|
487
|
+
case "KY":
|
|
488
|
+
return [
|
|
489
|
+
[{ field: "street" }],
|
|
490
|
+
[{ field: "region" }, { field: "postalCode", separator: " " }],
|
|
491
|
+
];
|
|
492
|
+
case "LI":
|
|
493
|
+
return [
|
|
494
|
+
[{ field: "street" }],
|
|
495
|
+
[
|
|
496
|
+
{ field: "postalCode", prefix: "FL-" },
|
|
497
|
+
{ field: "locality", separator: " " },
|
|
498
|
+
],
|
|
499
|
+
];
|
|
500
|
+
case "LT":
|
|
501
|
+
return [
|
|
502
|
+
[{ field: "street" }],
|
|
503
|
+
[
|
|
504
|
+
{ field: "postalCode", prefix: "LT-" },
|
|
505
|
+
{ field: "locality", separator: " " },
|
|
506
|
+
{ field: "region", separator: " " },
|
|
507
|
+
],
|
|
508
|
+
];
|
|
509
|
+
case "LU":
|
|
510
|
+
return [
|
|
511
|
+
[{ field: "street" }],
|
|
512
|
+
[
|
|
513
|
+
{ field: "postalCode", prefix: "L-" },
|
|
514
|
+
{ field: "locality", separator: " " },
|
|
515
|
+
],
|
|
516
|
+
];
|
|
517
|
+
case "LV":
|
|
518
|
+
return [
|
|
519
|
+
[{ field: "street" }],
|
|
520
|
+
[{ field: "region" }],
|
|
521
|
+
[
|
|
522
|
+
{ field: "locality" },
|
|
523
|
+
{ field: "postalCode", separator: ", " },
|
|
524
|
+
],
|
|
525
|
+
];
|
|
526
|
+
case "MC":
|
|
527
|
+
return [
|
|
528
|
+
[{ field: "street" }],
|
|
529
|
+
[
|
|
530
|
+
{ field: "postalCode", prefix: "MC-" },
|
|
531
|
+
{ field: "locality", separator: " " },
|
|
532
|
+
],
|
|
533
|
+
];
|
|
534
|
+
case "MD":
|
|
535
|
+
return [
|
|
536
|
+
[{ field: "street" }],
|
|
537
|
+
[
|
|
538
|
+
{ field: "postalCode", prefix: "MD-" },
|
|
539
|
+
{ field: "locality", separator: " " },
|
|
540
|
+
],
|
|
541
|
+
];
|
|
542
|
+
case "MM":
|
|
543
|
+
return [
|
|
544
|
+
[{ field: "street" }],
|
|
545
|
+
[
|
|
546
|
+
{ field: "locality" },
|
|
547
|
+
{ field: "postalCode", separator: ", " },
|
|
548
|
+
],
|
|
549
|
+
];
|
|
550
|
+
case "MO":
|
|
551
|
+
return [[{ field: "street" }]];
|
|
552
|
+
case "MX":
|
|
553
|
+
return [
|
|
554
|
+
[{ field: "street" }],
|
|
555
|
+
[
|
|
556
|
+
{ field: "postalCode" },
|
|
557
|
+
{ field: "locality", separator: " " },
|
|
558
|
+
{ field: "region", separator: ", " },
|
|
559
|
+
],
|
|
560
|
+
];
|
|
561
|
+
case "MZ":
|
|
562
|
+
return [
|
|
563
|
+
[{ field: "street" }],
|
|
564
|
+
[
|
|
565
|
+
{ field: "postalCode" },
|
|
566
|
+
{ field: "locality", separator: " " },
|
|
567
|
+
{ field: "region" },
|
|
568
|
+
],
|
|
569
|
+
];
|
|
570
|
+
case "NI":
|
|
571
|
+
return [
|
|
572
|
+
[{ field: "street" }],
|
|
573
|
+
[{ field: "postalCode" }],
|
|
574
|
+
[{ field: "locality" }, { field: "region", separator: ", " }],
|
|
575
|
+
];
|
|
576
|
+
case "PG":
|
|
577
|
+
return [
|
|
578
|
+
[{ field: "street" }],
|
|
579
|
+
[
|
|
580
|
+
{ field: "locality" },
|
|
581
|
+
{ field: "postalCode", separator: " " },
|
|
582
|
+
{ field: "region", separator: " " },
|
|
583
|
+
],
|
|
584
|
+
];
|
|
585
|
+
case "PH":
|
|
586
|
+
return [
|
|
587
|
+
[{ field: "street" }],
|
|
588
|
+
[{ field: "locality" }],
|
|
589
|
+
[{ field: "postalCode" }, { field: "region", separator: " " }],
|
|
590
|
+
];
|
|
591
|
+
case "PK":
|
|
592
|
+
return [
|
|
593
|
+
[{ field: "street" }],
|
|
594
|
+
[
|
|
595
|
+
{ field: "locality" },
|
|
596
|
+
{ field: "postalCode", separator: "-" },
|
|
597
|
+
],
|
|
598
|
+
];
|
|
599
|
+
case "PR":
|
|
600
|
+
return [
|
|
601
|
+
[{ field: "street" }],
|
|
602
|
+
[
|
|
603
|
+
{ field: "locality" },
|
|
604
|
+
{ field: "postalCode", separator: " PR " },
|
|
605
|
+
],
|
|
606
|
+
];
|
|
607
|
+
case "RO":
|
|
608
|
+
return [
|
|
609
|
+
[{ field: "street" }],
|
|
610
|
+
[
|
|
611
|
+
{ field: "postalCode" },
|
|
612
|
+
{ field: "region", separator: " " },
|
|
613
|
+
{ field: "locality", separator: " " },
|
|
614
|
+
],
|
|
615
|
+
];
|
|
616
|
+
case "SE":
|
|
617
|
+
return [
|
|
618
|
+
[{ field: "street" }],
|
|
619
|
+
[
|
|
620
|
+
{ field: "postalCode", prefix: "SE-" },
|
|
621
|
+
{ field: "locality", separator: " " },
|
|
622
|
+
],
|
|
623
|
+
];
|
|
624
|
+
case "SG":
|
|
625
|
+
return [
|
|
626
|
+
[{ field: "street" }],
|
|
627
|
+
[{ field: "postalCode", prefix: "SINGAPORE " }],
|
|
628
|
+
];
|
|
629
|
+
case "SI":
|
|
630
|
+
return [
|
|
631
|
+
[{ field: "street" }],
|
|
632
|
+
[
|
|
633
|
+
{ field: "postalCode", prefix: "SI-" },
|
|
634
|
+
{ field: "locality", separator: " " },
|
|
635
|
+
],
|
|
636
|
+
];
|
|
637
|
+
case "SV":
|
|
638
|
+
return [
|
|
639
|
+
[{ field: "street" }],
|
|
640
|
+
[
|
|
641
|
+
{ field: "postalCode" },
|
|
642
|
+
{ field: "locality", separator: "-" },
|
|
643
|
+
],
|
|
644
|
+
[{ field: "region" }],
|
|
645
|
+
];
|
|
646
|
+
case "TR":
|
|
647
|
+
return [
|
|
648
|
+
[{ field: "street" }],
|
|
649
|
+
[
|
|
650
|
+
{ field: "postalCode" },
|
|
651
|
+
{ field: "locality", separator: " " },
|
|
652
|
+
{ field: "region", separator: "/" },
|
|
653
|
+
],
|
|
654
|
+
];
|
|
655
|
+
case "VE":
|
|
656
|
+
return [
|
|
657
|
+
[{ field: "street" }],
|
|
658
|
+
[
|
|
659
|
+
{ field: "locality" },
|
|
660
|
+
{ field: "postalCode", separator: " " },
|
|
661
|
+
{ field: "region", separator: ", " },
|
|
662
|
+
],
|
|
663
|
+
];
|
|
664
|
+
// Google's default: BF and MW, and every country it gives no layout of
|
|
665
|
+
// its own.
|
|
666
|
+
default:
|
|
667
|
+
return [[{ field: "street" }], [{ field: "locality" }]];
|
|
668
|
+
}
|
|
669
|
+
}
|
package/src/contact.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { addressLayout } from "./address-formats.ts";
|
|
1
2
|
import type { CountryCode } from "./countries.ts";
|
|
2
3
|
import type { Digit } from "./types.ts";
|
|
3
4
|
import { warn } from "./warn.ts";
|
|
@@ -300,8 +301,12 @@ export interface PostalAddress {
|
|
|
300
301
|
readonly street: string;
|
|
301
302
|
/** Town or city, in its own language: `"Roma"`. */
|
|
302
303
|
readonly locality: string;
|
|
303
|
-
/**
|
|
304
|
-
|
|
304
|
+
/**
|
|
305
|
+
* Postal or ZIP code, as written locally. None where the country has no
|
|
306
|
+
* postal codes, as in the UAE: left out rather than sent empty, like
|
|
307
|
+
* `region`.
|
|
308
|
+
*/
|
|
309
|
+
readonly postalCode?: string;
|
|
305
310
|
/**
|
|
306
311
|
* The country, as its two-letter code: `"IT"`, not `"Italy"`.
|
|
307
312
|
*
|
|
@@ -313,3 +318,49 @@ export interface PostalAddress {
|
|
|
313
318
|
/** State, province or region, where the country uses one. */
|
|
314
319
|
readonly region?: string;
|
|
315
320
|
}
|
|
321
|
+
|
|
322
|
+
/**
|
|
323
|
+
* The record written out in its country's postal order, one string per line:
|
|
324
|
+
* `["Via Nazionale 100", "00184 Roma"]`, `["1 Example Ave", "Austin, TX
|
|
325
|
+
* 78701"]`.
|
|
326
|
+
*
|
|
327
|
+
* Still the canonical address — `Roma`, on every page — so it suits a list of
|
|
328
|
+
* venues or an envelope, not a sentence; a page that phrases the address for
|
|
329
|
+
* its reader writes it in the catalog, like the rest of its copy.
|
|
330
|
+
*
|
|
331
|
+
* The order is Google's address metadata, converted once into
|
|
332
|
+
* `addressLayout`, not a rule per country written here. A field the address does not have prints
|
|
333
|
+
* nothing, and its punctuation goes with it, because each field carries its
|
|
334
|
+
* own: no postal code, no `CH-`. Letter case is the caller's: some countries
|
|
335
|
+
* want the town in capitals on an envelope, which is not how a page should
|
|
336
|
+
* print it.
|
|
337
|
+
*/
|
|
338
|
+
export function addressLines(address: PostalAddress): readonly string[] {
|
|
339
|
+
const lines: string[] = [];
|
|
340
|
+
for (const parts of addressLayout(address.country)) {
|
|
341
|
+
let line = "";
|
|
342
|
+
for (const part of parts) {
|
|
343
|
+
if ("text" in part) {
|
|
344
|
+
line += part.text;
|
|
345
|
+
continue;
|
|
346
|
+
}
|
|
347
|
+
const value = address[part.field]?.trim();
|
|
348
|
+
if (!value) continue;
|
|
349
|
+
if (line !== "") line += part.separator ?? "";
|
|
350
|
+
line += (part.prefix ?? "") + value;
|
|
351
|
+
}
|
|
352
|
+
if (line !== "") lines.push(line);
|
|
353
|
+
}
|
|
354
|
+
return lines;
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
/**
|
|
358
|
+
* `addressLines` on one line, for where there is room for only one: a venue
|
|
359
|
+
* card, an `llms.txt` entry.
|
|
360
|
+
*/
|
|
361
|
+
export function addressLine(
|
|
362
|
+
address: PostalAddress,
|
|
363
|
+
separator: string = ", "
|
|
364
|
+
): string {
|
|
365
|
+
return addressLines(address).join(separator);
|
|
366
|
+
}
|
package/src/index.ts
CHANGED
package/src/jsonld/place.ts
CHANGED
|
@@ -37,7 +37,9 @@ export function postalAddress(address: PostalAddress): JsonLdNode {
|
|
|
37
37
|
"@type": "PostalAddress",
|
|
38
38
|
streetAddress: address.street,
|
|
39
39
|
addressLocality: address.locality,
|
|
40
|
-
|
|
40
|
+
...(address.postalCode === undefined
|
|
41
|
+
? {}
|
|
42
|
+
: { postalCode: address.postalCode }),
|
|
41
43
|
addressCountry: address.country,
|
|
42
44
|
...(address.region === undefined
|
|
43
45
|
? {}
|