thaizip 0.6.0 → 0.7.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +90 -265
- package/dist/data.cjs +53 -4
- package/dist/data.d.cts +16 -0
- package/dist/data.d.ts +16 -0
- package/dist/data.js +53 -4
- package/dist/index.cjs +293 -21
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +156 -2
- package/dist/index.d.ts +156 -2
- package/dist/index.js +288 -22
- package/dist/index.js.map +1 -1
- package/dist/react.cjs +228 -42
- package/dist/react.cjs.map +1 -1
- package/dist/react.d.cts +40 -1
- package/dist/react.d.ts +40 -1
- package/dist/react.js +229 -43
- package/dist/react.js.map +1 -1
- package/package.json +4 -4
package/dist/index.d.cts
CHANGED
|
@@ -14,10 +14,37 @@ type TrigramIndex = {
|
|
|
14
14
|
map: Map<string, Set<number>>;
|
|
15
15
|
records: ThaiAddressRecord[];
|
|
16
16
|
zipIndex: Map<string, number[]>;
|
|
17
|
+
/**
|
|
18
|
+
* Normalized Thai tambon names, parallel to `records` (same index).
|
|
19
|
+
* Used by the search ranker for exact/prefix match detection without
|
|
20
|
+
* re-normalizing on every query.
|
|
21
|
+
*/
|
|
22
|
+
normTambon: string[];
|
|
23
|
+
/**
|
|
24
|
+
* Normalized English (RTGS) tambon names, parallel to `records`. Needed so
|
|
25
|
+
* romanized queries get the same own-name-beats-parent-name ranking that
|
|
26
|
+
* Thai queries get.
|
|
27
|
+
*/
|
|
28
|
+
normTambonEn: string[];
|
|
29
|
+
/** Record indices grouped by `provinceId`, in insertion order. */
|
|
30
|
+
byProvince: Map<number, number[]>;
|
|
31
|
+
/** Record indices grouped by `amphureId`, in insertion order. */
|
|
32
|
+
byAmphure: Map<number, number[]>;
|
|
33
|
+
};
|
|
34
|
+
/** Which language a formatted label should be rendered in. */
|
|
35
|
+
type AddressLocale = 'th' | 'en';
|
|
36
|
+
type FormatSuggestionOptions = {
|
|
37
|
+
/** Language for the `label` field. Defaults to `'th'`. */
|
|
38
|
+
locale?: AddressLocale;
|
|
17
39
|
};
|
|
18
40
|
type ThaiAddressSuggestion = {
|
|
19
41
|
id: string;
|
|
42
|
+
/** Human-readable label in the requested locale (Thai by default). */
|
|
20
43
|
label: string;
|
|
44
|
+
/** Human-readable label in Thai, regardless of the requested locale. */
|
|
45
|
+
labelTh: string;
|
|
46
|
+
/** Human-readable label in English, regardless of the requested locale. */
|
|
47
|
+
labelEn: string;
|
|
21
48
|
tambon: string;
|
|
22
49
|
tambonEn: string;
|
|
23
50
|
amphure: string;
|
|
@@ -26,6 +53,27 @@ type ThaiAddressSuggestion = {
|
|
|
26
53
|
provinceEn: string;
|
|
27
54
|
zipCode: string;
|
|
28
55
|
};
|
|
56
|
+
/** A province entry returned by the enumeration API. */
|
|
57
|
+
type ProvinceSummary = {
|
|
58
|
+
id: number;
|
|
59
|
+
nameTh: string;
|
|
60
|
+
nameEn: string;
|
|
61
|
+
};
|
|
62
|
+
/** An amphure (district) entry returned by the enumeration API. */
|
|
63
|
+
type AmphureSummary = {
|
|
64
|
+
id: number;
|
|
65
|
+
nameTh: string;
|
|
66
|
+
nameEn: string;
|
|
67
|
+
provinceId: number;
|
|
68
|
+
};
|
|
69
|
+
/** A tambon (subdistrict) entry returned by the enumeration API. */
|
|
70
|
+
type TambonSummary = {
|
|
71
|
+
id: number;
|
|
72
|
+
nameTh: string;
|
|
73
|
+
nameEn: string;
|
|
74
|
+
amphureId: number;
|
|
75
|
+
zipCode: string;
|
|
76
|
+
};
|
|
29
77
|
type ResolvedThaiAddress = {
|
|
30
78
|
tambon: string;
|
|
31
79
|
tambonEn: string;
|
|
@@ -43,6 +91,17 @@ type ResolvedThaiAddress = {
|
|
|
43
91
|
type SearchOptions = {
|
|
44
92
|
limit?: number;
|
|
45
93
|
threshold?: number;
|
|
94
|
+
/**
|
|
95
|
+
* Maximum results for all-digit (zip code) queries. A zip code maps to at most
|
|
96
|
+
* a few dozen tambons, so this defaults to `Infinity` — capping zip results at
|
|
97
|
+
* the text-autocomplete `limit` silently hides valid subdistricts.
|
|
98
|
+
*/
|
|
99
|
+
zipLimit?: number;
|
|
100
|
+
/**
|
|
101
|
+
* Expand common romanization variants (e.g. `lardprao` → `lat phrao`) before
|
|
102
|
+
* searching. Only affects Latin-script queries. Defaults to `true`.
|
|
103
|
+
*/
|
|
104
|
+
romanizationAliases?: boolean;
|
|
46
105
|
};
|
|
47
106
|
type RawGeography = {
|
|
48
107
|
id: number;
|
|
@@ -73,6 +132,12 @@ type RawTambon = {
|
|
|
73
132
|
};
|
|
74
133
|
type BuildIndexOptions = {
|
|
75
134
|
onSkip?: (tambon: RawTambon) => void;
|
|
135
|
+
/**
|
|
136
|
+
* Validate that every consumed field has the expected runtime type and throw a
|
|
137
|
+
* descriptive `TypeError` if not. Defaults to `true`; set to `false` to skip
|
|
138
|
+
* the checks when the data source is already trusted (e.g. the bundled index).
|
|
139
|
+
*/
|
|
140
|
+
validate?: boolean;
|
|
76
141
|
};
|
|
77
142
|
type RawData = {
|
|
78
143
|
geographies?: RawGeography[];
|
|
@@ -81,14 +146,103 @@ type RawData = {
|
|
|
81
146
|
tambons: RawTambon[];
|
|
82
147
|
};
|
|
83
148
|
|
|
149
|
+
/**
|
|
150
|
+
* Validate that a `RawData` payload has the runtime shapes `buildThaiAddressIndex`
|
|
151
|
+
* expects. Intended for consumers building an index from their own data (CSV, CMS,
|
|
152
|
+
* private datasets) who want to fail fast with a descriptive error instead of an
|
|
153
|
+
* opaque crash deep inside the normalizer, or silent `"undefined"` labels.
|
|
154
|
+
*
|
|
155
|
+
* Throws a `TypeError` (message prefixed `[thaizip]`) naming the table, the
|
|
156
|
+
* offending record's `id`, the field, and the actual `typeof` on the first bad
|
|
157
|
+
* field found. Does not filter soft-deleted rows first — validates every row as
|
|
158
|
+
* provided.
|
|
159
|
+
*/
|
|
160
|
+
declare function validateRawData(data: RawData): void;
|
|
84
161
|
declare function buildThaiAddressIndex(data: RawData, options?: BuildIndexOptions): TrigramIndex;
|
|
85
162
|
|
|
163
|
+
/**
|
|
164
|
+
* Look up records by zip code (exact or prefix match). Exact matches are
|
|
165
|
+
* returned before prefix matches; ties are ordered by ascending zip code.
|
|
166
|
+
*
|
|
167
|
+
* Unlike `searchThaiAddress`, results are NOT capped by `options.limit` —
|
|
168
|
+
* only by `options.zipLimit` (defaults to `Infinity`), since a zip code can
|
|
169
|
+
* legitimately map to dozens of tambons (e.g. `45000` → 33 records).
|
|
170
|
+
*/
|
|
171
|
+
declare function lookupByZipCode(index: TrigramIndex, zip: string, options?: SearchOptions): ThaiAddressRecord[];
|
|
86
172
|
declare function searchThaiAddress(index: TrigramIndex, query: string, options?: SearchOptions): ThaiAddressRecord[];
|
|
87
173
|
|
|
88
|
-
|
|
174
|
+
/**
|
|
175
|
+
* All provinces present in the index, deduplicated and sorted by Thai name.
|
|
176
|
+
* Backed by `index.byProvince` (O(unique provinces)); falls back to scanning
|
|
177
|
+
* `index.records` if an older-shaped index lacks that map.
|
|
178
|
+
*/
|
|
179
|
+
declare function listProvinces(index: TrigramIndex): ProvinceSummary[];
|
|
180
|
+
/**
|
|
181
|
+
* Amphures (districts) within a given province, deduplicated and sorted by
|
|
182
|
+
* Thai name. Unknown `provinceId` returns `[]`. Backed by `index.byProvince`;
|
|
183
|
+
* falls back to scanning `index.records` if an older-shaped index lacks it.
|
|
184
|
+
*/
|
|
185
|
+
declare function listAmphures(index: TrigramIndex, provinceId: number): AmphureSummary[];
|
|
186
|
+
/**
|
|
187
|
+
* Tambons (subdistricts) within a given amphure, sorted by Thai name.
|
|
188
|
+
* Unknown `amphureId` returns `[]`. Backed by `index.byAmphure`; falls back
|
|
189
|
+
* to scanning `index.records` if an older-shaped index lacks it. Each
|
|
190
|
+
* `byAmphure` entry already maps to exactly one tambon record, so no
|
|
191
|
+
* deduplication is needed here.
|
|
192
|
+
*/
|
|
193
|
+
declare function listTambons(index: TrigramIndex, amphureId: number): TambonSummary[];
|
|
194
|
+
|
|
195
|
+
declare function formatThaiAddressSuggestion(record: ThaiAddressRecord, options?: FormatSuggestionOptions): ThaiAddressSuggestion;
|
|
89
196
|
|
|
90
197
|
declare function resolveThaiAddress(record: ThaiAddressRecord): ResolvedThaiAddress;
|
|
91
198
|
|
|
92
199
|
declare function normalizeThaiAddressText(input: string): string;
|
|
93
200
|
|
|
94
|
-
|
|
201
|
+
/**
|
|
202
|
+
* Romanization alias expansion for Latin-script queries.
|
|
203
|
+
*
|
|
204
|
+
* The bundled dataset indexes only the official RTGS transliteration of each
|
|
205
|
+
* name (`name_en`), so common but non-RTGS spellings a user actually types
|
|
206
|
+
* ("lardprao", "krungthep", "sukumvit") miss the index entirely. This module
|
|
207
|
+
* rewrites such a query into its RTGS form before trigram extraction.
|
|
208
|
+
*
|
|
209
|
+
* Contract:
|
|
210
|
+
* - Input is an ALREADY-NORMALIZED query (lowercased, prefixes and tone marks
|
|
211
|
+
* stripped) as produced by `normalizeThaiAddressText`.
|
|
212
|
+
* - Output is a normalized query too — safe to hand straight to
|
|
213
|
+
* `extractTrigramsNormalized`.
|
|
214
|
+
* - Thai-script input must be returned unchanged.
|
|
215
|
+
* - Must be a pure function; it runs on every keystroke.
|
|
216
|
+
*
|
|
217
|
+
* Design (two layers, cheapest/most-reliable first):
|
|
218
|
+
*
|
|
219
|
+
* 1. A curated dictionary of non-RTGS spelling -> exact RTGS string, as it
|
|
220
|
+
* literally appears in a `name_en` field of the bundled dataset. Targets
|
|
221
|
+
* were read off the real generated index (see the romanize benchmark
|
|
222
|
+
* harness used to build this list), not guessed — a couple of entries
|
|
223
|
+
* intentionally map onto data typos already baked into the dataset
|
|
224
|
+
* (`loburi`, `buogkan`) because that is what is actually indexed.
|
|
225
|
+
*
|
|
226
|
+
* 2. A tiny, conservative cleanup pass used only when the dictionary misses:
|
|
227
|
+
* collapse runs of whitespace, and strip a few English administrative
|
|
228
|
+
* words (`district`, `province`, ...) that never occur inside a real
|
|
229
|
+
* `name_en` value. Both were verified against the full dataset before
|
|
230
|
+
* being added — see the "rejected rules" note below for transformations
|
|
231
|
+
* that were tried and thrown out because they collide with real names.
|
|
232
|
+
*
|
|
233
|
+
* Rejected systematic rules (measured against the real dataset, not
|
|
234
|
+
* hypothetical): a blanket `klong` -> `khlong` rewrite would break the real
|
|
235
|
+
* tambons "Mae Klong" and "Ho Klong"; `muang` -> `mueang` would break ~122
|
|
236
|
+
* real tambons that legitimately contain "Muang" as a name component (e.g.
|
|
237
|
+
* "Bang Muang", "Khok Muang"); `huay` -> `huai` would break the real tambon
|
|
238
|
+
* "Huay Lueg"; a blanket hyphen -> space rewrite would break the ~70 real
|
|
239
|
+
* names that use a hyphen on purpose (e.g. "Bang Pa-in", the Ayutthaya
|
|
240
|
+
* palace town). None of the classic AUA-vs-RTGS letter swaps (`oo` -> `u`,
|
|
241
|
+
* trailing `-rd` -> `-t`, `dt` -> `t`, `bp` -> `p`, doubled consonants) had
|
|
242
|
+
* any real occurrence in the traffic-prioritized query set used to validate
|
|
243
|
+
* this module, so none were added — see the harness report for the
|
|
244
|
+
* before/after numbers this file was tuned against.
|
|
245
|
+
*/
|
|
246
|
+
declare function applyRomanizationAliases(normalized: string): string;
|
|
247
|
+
|
|
248
|
+
export { type AddressLocale, type AmphureSummary, type BuildIndexOptions, type FormatSuggestionOptions, type ProvinceSummary, type RawAmphure, type RawData, type RawGeography, type RawProvince, type RawTambon, type ResolvedThaiAddress, type SearchOptions, type TambonSummary, type ThaiAddressRecord, type ThaiAddressSuggestion, type TrigramIndex, applyRomanizationAliases, buildThaiAddressIndex, formatThaiAddressSuggestion, listAmphures, listProvinces, listTambons, lookupByZipCode, normalizeThaiAddressText, resolveThaiAddress, searchThaiAddress, validateRawData };
|
package/dist/index.d.ts
CHANGED
|
@@ -14,10 +14,37 @@ type TrigramIndex = {
|
|
|
14
14
|
map: Map<string, Set<number>>;
|
|
15
15
|
records: ThaiAddressRecord[];
|
|
16
16
|
zipIndex: Map<string, number[]>;
|
|
17
|
+
/**
|
|
18
|
+
* Normalized Thai tambon names, parallel to `records` (same index).
|
|
19
|
+
* Used by the search ranker for exact/prefix match detection without
|
|
20
|
+
* re-normalizing on every query.
|
|
21
|
+
*/
|
|
22
|
+
normTambon: string[];
|
|
23
|
+
/**
|
|
24
|
+
* Normalized English (RTGS) tambon names, parallel to `records`. Needed so
|
|
25
|
+
* romanized queries get the same own-name-beats-parent-name ranking that
|
|
26
|
+
* Thai queries get.
|
|
27
|
+
*/
|
|
28
|
+
normTambonEn: string[];
|
|
29
|
+
/** Record indices grouped by `provinceId`, in insertion order. */
|
|
30
|
+
byProvince: Map<number, number[]>;
|
|
31
|
+
/** Record indices grouped by `amphureId`, in insertion order. */
|
|
32
|
+
byAmphure: Map<number, number[]>;
|
|
33
|
+
};
|
|
34
|
+
/** Which language a formatted label should be rendered in. */
|
|
35
|
+
type AddressLocale = 'th' | 'en';
|
|
36
|
+
type FormatSuggestionOptions = {
|
|
37
|
+
/** Language for the `label` field. Defaults to `'th'`. */
|
|
38
|
+
locale?: AddressLocale;
|
|
17
39
|
};
|
|
18
40
|
type ThaiAddressSuggestion = {
|
|
19
41
|
id: string;
|
|
42
|
+
/** Human-readable label in the requested locale (Thai by default). */
|
|
20
43
|
label: string;
|
|
44
|
+
/** Human-readable label in Thai, regardless of the requested locale. */
|
|
45
|
+
labelTh: string;
|
|
46
|
+
/** Human-readable label in English, regardless of the requested locale. */
|
|
47
|
+
labelEn: string;
|
|
21
48
|
tambon: string;
|
|
22
49
|
tambonEn: string;
|
|
23
50
|
amphure: string;
|
|
@@ -26,6 +53,27 @@ type ThaiAddressSuggestion = {
|
|
|
26
53
|
provinceEn: string;
|
|
27
54
|
zipCode: string;
|
|
28
55
|
};
|
|
56
|
+
/** A province entry returned by the enumeration API. */
|
|
57
|
+
type ProvinceSummary = {
|
|
58
|
+
id: number;
|
|
59
|
+
nameTh: string;
|
|
60
|
+
nameEn: string;
|
|
61
|
+
};
|
|
62
|
+
/** An amphure (district) entry returned by the enumeration API. */
|
|
63
|
+
type AmphureSummary = {
|
|
64
|
+
id: number;
|
|
65
|
+
nameTh: string;
|
|
66
|
+
nameEn: string;
|
|
67
|
+
provinceId: number;
|
|
68
|
+
};
|
|
69
|
+
/** A tambon (subdistrict) entry returned by the enumeration API. */
|
|
70
|
+
type TambonSummary = {
|
|
71
|
+
id: number;
|
|
72
|
+
nameTh: string;
|
|
73
|
+
nameEn: string;
|
|
74
|
+
amphureId: number;
|
|
75
|
+
zipCode: string;
|
|
76
|
+
};
|
|
29
77
|
type ResolvedThaiAddress = {
|
|
30
78
|
tambon: string;
|
|
31
79
|
tambonEn: string;
|
|
@@ -43,6 +91,17 @@ type ResolvedThaiAddress = {
|
|
|
43
91
|
type SearchOptions = {
|
|
44
92
|
limit?: number;
|
|
45
93
|
threshold?: number;
|
|
94
|
+
/**
|
|
95
|
+
* Maximum results for all-digit (zip code) queries. A zip code maps to at most
|
|
96
|
+
* a few dozen tambons, so this defaults to `Infinity` — capping zip results at
|
|
97
|
+
* the text-autocomplete `limit` silently hides valid subdistricts.
|
|
98
|
+
*/
|
|
99
|
+
zipLimit?: number;
|
|
100
|
+
/**
|
|
101
|
+
* Expand common romanization variants (e.g. `lardprao` → `lat phrao`) before
|
|
102
|
+
* searching. Only affects Latin-script queries. Defaults to `true`.
|
|
103
|
+
*/
|
|
104
|
+
romanizationAliases?: boolean;
|
|
46
105
|
};
|
|
47
106
|
type RawGeography = {
|
|
48
107
|
id: number;
|
|
@@ -73,6 +132,12 @@ type RawTambon = {
|
|
|
73
132
|
};
|
|
74
133
|
type BuildIndexOptions = {
|
|
75
134
|
onSkip?: (tambon: RawTambon) => void;
|
|
135
|
+
/**
|
|
136
|
+
* Validate that every consumed field has the expected runtime type and throw a
|
|
137
|
+
* descriptive `TypeError` if not. Defaults to `true`; set to `false` to skip
|
|
138
|
+
* the checks when the data source is already trusted (e.g. the bundled index).
|
|
139
|
+
*/
|
|
140
|
+
validate?: boolean;
|
|
76
141
|
};
|
|
77
142
|
type RawData = {
|
|
78
143
|
geographies?: RawGeography[];
|
|
@@ -81,14 +146,103 @@ type RawData = {
|
|
|
81
146
|
tambons: RawTambon[];
|
|
82
147
|
};
|
|
83
148
|
|
|
149
|
+
/**
|
|
150
|
+
* Validate that a `RawData` payload has the runtime shapes `buildThaiAddressIndex`
|
|
151
|
+
* expects. Intended for consumers building an index from their own data (CSV, CMS,
|
|
152
|
+
* private datasets) who want to fail fast with a descriptive error instead of an
|
|
153
|
+
* opaque crash deep inside the normalizer, or silent `"undefined"` labels.
|
|
154
|
+
*
|
|
155
|
+
* Throws a `TypeError` (message prefixed `[thaizip]`) naming the table, the
|
|
156
|
+
* offending record's `id`, the field, and the actual `typeof` on the first bad
|
|
157
|
+
* field found. Does not filter soft-deleted rows first — validates every row as
|
|
158
|
+
* provided.
|
|
159
|
+
*/
|
|
160
|
+
declare function validateRawData(data: RawData): void;
|
|
84
161
|
declare function buildThaiAddressIndex(data: RawData, options?: BuildIndexOptions): TrigramIndex;
|
|
85
162
|
|
|
163
|
+
/**
|
|
164
|
+
* Look up records by zip code (exact or prefix match). Exact matches are
|
|
165
|
+
* returned before prefix matches; ties are ordered by ascending zip code.
|
|
166
|
+
*
|
|
167
|
+
* Unlike `searchThaiAddress`, results are NOT capped by `options.limit` —
|
|
168
|
+
* only by `options.zipLimit` (defaults to `Infinity`), since a zip code can
|
|
169
|
+
* legitimately map to dozens of tambons (e.g. `45000` → 33 records).
|
|
170
|
+
*/
|
|
171
|
+
declare function lookupByZipCode(index: TrigramIndex, zip: string, options?: SearchOptions): ThaiAddressRecord[];
|
|
86
172
|
declare function searchThaiAddress(index: TrigramIndex, query: string, options?: SearchOptions): ThaiAddressRecord[];
|
|
87
173
|
|
|
88
|
-
|
|
174
|
+
/**
|
|
175
|
+
* All provinces present in the index, deduplicated and sorted by Thai name.
|
|
176
|
+
* Backed by `index.byProvince` (O(unique provinces)); falls back to scanning
|
|
177
|
+
* `index.records` if an older-shaped index lacks that map.
|
|
178
|
+
*/
|
|
179
|
+
declare function listProvinces(index: TrigramIndex): ProvinceSummary[];
|
|
180
|
+
/**
|
|
181
|
+
* Amphures (districts) within a given province, deduplicated and sorted by
|
|
182
|
+
* Thai name. Unknown `provinceId` returns `[]`. Backed by `index.byProvince`;
|
|
183
|
+
* falls back to scanning `index.records` if an older-shaped index lacks it.
|
|
184
|
+
*/
|
|
185
|
+
declare function listAmphures(index: TrigramIndex, provinceId: number): AmphureSummary[];
|
|
186
|
+
/**
|
|
187
|
+
* Tambons (subdistricts) within a given amphure, sorted by Thai name.
|
|
188
|
+
* Unknown `amphureId` returns `[]`. Backed by `index.byAmphure`; falls back
|
|
189
|
+
* to scanning `index.records` if an older-shaped index lacks it. Each
|
|
190
|
+
* `byAmphure` entry already maps to exactly one tambon record, so no
|
|
191
|
+
* deduplication is needed here.
|
|
192
|
+
*/
|
|
193
|
+
declare function listTambons(index: TrigramIndex, amphureId: number): TambonSummary[];
|
|
194
|
+
|
|
195
|
+
declare function formatThaiAddressSuggestion(record: ThaiAddressRecord, options?: FormatSuggestionOptions): ThaiAddressSuggestion;
|
|
89
196
|
|
|
90
197
|
declare function resolveThaiAddress(record: ThaiAddressRecord): ResolvedThaiAddress;
|
|
91
198
|
|
|
92
199
|
declare function normalizeThaiAddressText(input: string): string;
|
|
93
200
|
|
|
94
|
-
|
|
201
|
+
/**
|
|
202
|
+
* Romanization alias expansion for Latin-script queries.
|
|
203
|
+
*
|
|
204
|
+
* The bundled dataset indexes only the official RTGS transliteration of each
|
|
205
|
+
* name (`name_en`), so common but non-RTGS spellings a user actually types
|
|
206
|
+
* ("lardprao", "krungthep", "sukumvit") miss the index entirely. This module
|
|
207
|
+
* rewrites such a query into its RTGS form before trigram extraction.
|
|
208
|
+
*
|
|
209
|
+
* Contract:
|
|
210
|
+
* - Input is an ALREADY-NORMALIZED query (lowercased, prefixes and tone marks
|
|
211
|
+
* stripped) as produced by `normalizeThaiAddressText`.
|
|
212
|
+
* - Output is a normalized query too — safe to hand straight to
|
|
213
|
+
* `extractTrigramsNormalized`.
|
|
214
|
+
* - Thai-script input must be returned unchanged.
|
|
215
|
+
* - Must be a pure function; it runs on every keystroke.
|
|
216
|
+
*
|
|
217
|
+
* Design (two layers, cheapest/most-reliable first):
|
|
218
|
+
*
|
|
219
|
+
* 1. A curated dictionary of non-RTGS spelling -> exact RTGS string, as it
|
|
220
|
+
* literally appears in a `name_en` field of the bundled dataset. Targets
|
|
221
|
+
* were read off the real generated index (see the romanize benchmark
|
|
222
|
+
* harness used to build this list), not guessed — a couple of entries
|
|
223
|
+
* intentionally map onto data typos already baked into the dataset
|
|
224
|
+
* (`loburi`, `buogkan`) because that is what is actually indexed.
|
|
225
|
+
*
|
|
226
|
+
* 2. A tiny, conservative cleanup pass used only when the dictionary misses:
|
|
227
|
+
* collapse runs of whitespace, and strip a few English administrative
|
|
228
|
+
* words (`district`, `province`, ...) that never occur inside a real
|
|
229
|
+
* `name_en` value. Both were verified against the full dataset before
|
|
230
|
+
* being added — see the "rejected rules" note below for transformations
|
|
231
|
+
* that were tried and thrown out because they collide with real names.
|
|
232
|
+
*
|
|
233
|
+
* Rejected systematic rules (measured against the real dataset, not
|
|
234
|
+
* hypothetical): a blanket `klong` -> `khlong` rewrite would break the real
|
|
235
|
+
* tambons "Mae Klong" and "Ho Klong"; `muang` -> `mueang` would break ~122
|
|
236
|
+
* real tambons that legitimately contain "Muang" as a name component (e.g.
|
|
237
|
+
* "Bang Muang", "Khok Muang"); `huay` -> `huai` would break the real tambon
|
|
238
|
+
* "Huay Lueg"; a blanket hyphen -> space rewrite would break the ~70 real
|
|
239
|
+
* names that use a hyphen on purpose (e.g. "Bang Pa-in", the Ayutthaya
|
|
240
|
+
* palace town). None of the classic AUA-vs-RTGS letter swaps (`oo` -> `u`,
|
|
241
|
+
* trailing `-rd` -> `-t`, `dt` -> `t`, `bp` -> `p`, doubled consonants) had
|
|
242
|
+
* any real occurrence in the traffic-prioritized query set used to validate
|
|
243
|
+
* this module, so none were added — see the harness report for the
|
|
244
|
+
* before/after numbers this file was tuned against.
|
|
245
|
+
*/
|
|
246
|
+
declare function applyRomanizationAliases(normalized: string): string;
|
|
247
|
+
|
|
248
|
+
export { type AddressLocale, type AmphureSummary, type BuildIndexOptions, type FormatSuggestionOptions, type ProvinceSummary, type RawAmphure, type RawData, type RawGeography, type RawProvince, type RawTambon, type ResolvedThaiAddress, type SearchOptions, type TambonSummary, type ThaiAddressRecord, type ThaiAddressSuggestion, type TrigramIndex, applyRomanizationAliases, buildThaiAddressIndex, formatThaiAddressSuggestion, listAmphures, listProvinces, listTambons, lookupByZipCode, normalizeThaiAddressText, resolveThaiAddress, searchThaiAddress, validateRawData };
|