@whiteslove/parsing-lexicon 0.5.6 → 0.5.8

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@whiteslove/parsing-lexicon",
3
- "version": "0.5.6",
3
+ "version": "0.5.8",
4
4
  "description": "Shared deterministic multilingual parsing lexicon for WhitesLove housing and hiring services",
5
5
  "repository": {
6
6
  "type": "git",
@@ -75,7 +75,7 @@ export const LOCATION_DICTIONARIES = Object.freeze({
75
75
  ]),
76
76
  landmarks: entries([
77
77
  ['Registan Square', 'площадь Регистан', 'Registon maydoni', 'Регистон майдони'], ['Gur-e-Amir', 'Гур Эмир', 'Go‘ri Amir', "Go'ri Amir"],
78
- ['Siab Bazaar', 'Сиабский базар', 'Siyob bozori'], ['Samarkand Railway Station', 'Самаркандский вокзал', 'Samarqand vokzali'],
78
+ ['Siyob Bazaar', 'Siab Bazaar', 'Сиабский базар', 'Siyob bozori'], ['Samarkand Railway Station', 'Самаркандский вокзал', 'Samarqand vokzali'],
79
79
  ]),
80
80
  }),
81
81
  }),
package/src/locations.js CHANGED
@@ -15,6 +15,7 @@ import { UA_REGIONAL_LOCATION_EXTENSIONS } from './ua-location-extensions-region
15
15
  import { UA_SECONDARY_LOCATION_EXTENSIONS } from './ua-secondary-cities.js';
16
16
  import { UA_METRO_LOCATION_EXTENSIONS } from './ua-location-extensions-metro.js';
17
17
  import { UA_KHARKIV_LOCATION_TRANSLATIONS } from './ua-kharkiv-location-translations.js';
18
+ import { UA_CITY_LOCATION_EXPANSIONS } from './ua-city-location-expansions.js';
18
19
 
19
20
  export const UA_EXTRA_LOCATION_DICTIONARIES = Object.freeze({
20
21
  ...RAW_UA_EXTRA_LOCATION_DICTIONARIES,
@@ -37,6 +38,10 @@ const TASHKENT_UNSUPPORTED_SEED_MICRODISTRICTS = new Set([
37
38
  'Yunusabad-22',
38
39
  ]);
39
40
 
41
+ const LEGACY_SAMARKAND_SILK_ROAD_RESIDENCE = (
42
+ BASE_LOCATION_DICTIONARIES.UZ?.Samarkand?.residentialComplexes || []
43
+ ).find(({ name }) => name === 'Silk Road Residence');
44
+
40
45
  // The UZ seed is compatibility storage. In 0.3 semantic corrections are
41
46
  // applied before merging it with the canonical Uzbekistan extension layer.
42
47
  const UZ_BASE_LOCATION_DICTIONARIES = Object.freeze({
@@ -47,9 +52,17 @@ const UZ_BASE_LOCATION_DICTIONARIES = Object.freeze({
47
52
  (BASE_LOCATION_DICTIONARIES.UZ?.Tashkent?.microdistricts || [])
48
53
  .filter(({ name }) => !TASHKENT_UNSUPPORTED_SEED_MICRODISTRICTS.has(name)),
49
54
  ),
55
+ residentialComplexes: Object.freeze([
56
+ ...(BASE_LOCATION_DICTIONARIES.UZ?.Tashkent?.residentialComplexes || [])
57
+ .filter(({ name }) => name !== 'Tashkent City' && name !== 'Silk Road Residence'),
58
+ ...(LEGACY_SAMARKAND_SILK_ROAD_RESIDENCE ? [LEGACY_SAMARKAND_SILK_ROAD_RESIDENCE] : []),
59
+ ]),
60
+ }),
61
+ Samarkand: Object.freeze({
62
+ ...(BASE_LOCATION_DICTIONARIES.UZ?.Samarkand || {}),
50
63
  residentialComplexes: Object.freeze(
51
- (BASE_LOCATION_DICTIONARIES.UZ?.Tashkent?.residentialComplexes || [])
52
- .filter(({ name }) => name !== 'Tashkent City'),
64
+ (BASE_LOCATION_DICTIONARIES.UZ?.Samarkand?.residentialComplexes || [])
65
+ .filter(({ name }) => name !== 'Silk Road Residence'),
53
66
  ),
54
67
  }),
55
68
  });
@@ -125,6 +138,9 @@ function normalizeUzSemanticLocations(country) {
125
138
 
126
139
  const samarkand = normalized?.Samarkand;
127
140
  if (samarkand) {
141
+ const microdistricts = samarkand.microdistricts || [];
142
+ const mahallas = samarkand.mahallas || [];
143
+ const settlements = samarkand.settlements || [];
128
144
  const landmarks = samarkand.landmarks || [];
129
145
  const localAreas = samarkand.localAreas || [];
130
146
  const streets = samarkand.streets || [];
@@ -168,14 +184,150 @@ function normalizeUzSemanticLocations(country) {
168
184
  ? semanticEntry(canonicalUniversity, 'University Boulevard', universityAliases, 'street')
169
185
  : null;
170
186
 
187
+ const sogdianaMicrodistrict = microdistricts.find(({ name }) => name === 'Sogdiana');
188
+ const sogdianaLocalArea = localAreas.find(({ name }) => name === 'Sugdiyona');
189
+ const sogdianaMahalla = mahallas.find(({ name }) => name === 'Sogdiana');
190
+ const normalizedSogdiana = semanticEntry(
191
+ sogdianaMahalla || sogdianaLocalArea || sogdianaMicrodistrict || {},
192
+ 'Sogdiana',
193
+ [
194
+ ...(sogdianaMahalla?.aliases || []),
195
+ ...(sogdianaLocalArea?.aliases || []),
196
+ ...(sogdianaMicrodistrict?.aliases || []),
197
+ 'Sugdiyona',
198
+ "Sug'diyona",
199
+ 'Sug‘diyona',
200
+ "So'g'diyona",
201
+ 'So‘g‘diyona',
202
+ 'Согдиана',
203
+ 'Согдиёна',
204
+ 'Сўғдиёна',
205
+ ],
206
+ 'mahalla',
207
+ );
208
+
209
+ const kimyogarlarMicrodistrict = microdistricts.find(({ name }) => name === 'Kimyogarlar');
210
+ const kimyogarlarLocalArea = localAreas.find(({ name }) => name === 'Kimyogarlar');
211
+ const kimyogarlarSettlement = settlements.find(({ name }) => name === 'Kimyogarlar');
212
+ const normalizedKimyogarlar = semanticEntry(
213
+ kimyogarlarSettlement || kimyogarlarLocalArea || kimyogarlarMicrodistrict || {},
214
+ 'Kimyogarlar',
215
+ [
216
+ ...(kimyogarlarSettlement?.aliases || []),
217
+ ...(kimyogarlarLocalArea?.aliases || []),
218
+ ...(kimyogarlarMicrodistrict?.aliases || []),
219
+ 'Кимёгарлар',
220
+ 'Химики',
221
+ 'Химгородок',
222
+ 'посёлок Химиков',
223
+ 'поселок Химиков',
224
+ ],
225
+ 'settlement',
226
+ );
227
+
228
+ const chilquduqSource = mahallas.find(({ name }) => ['Chilquduq', 'Chilkuduq', 'Chilkuduk'].includes(name));
229
+ const navrozSource = mahallas.find(({ name }) => name === "Navro'z");
230
+ const shirinSource = mahallas.find(({ name }) => name === 'Shirin');
231
+ const choponOtaSource = mahallas.find(({ name }) => name === "Cho'pon ota");
232
+ const normalizedChilquduq = semanticEntry(
233
+ { ...(chilquduqSource || {}), parent: 'Xishrov' },
234
+ 'Chilquduq',
235
+ [
236
+ ...(chilquduqSource?.aliases || []),
237
+ 'Chilkuduq',
238
+ 'Chilkuduk',
239
+ 'Chilquduq MFY',
240
+ 'Chilquduq mahallasi',
241
+ 'Чилқудуқ',
242
+ 'Чилкудук',
243
+ ],
244
+ 'mahalla',
245
+ );
246
+ const normalizedNavroz = navrozSource
247
+ ? semanticEntry({ ...navrozSource, parent: 'Xishrov' }, "Navro'z", navrozSource.aliases || [], 'mahalla')
248
+ : null;
249
+ const normalizedShirin = shirinSource
250
+ ? semanticEntry({ ...shirinSource, parent: 'Farhod' }, 'Shirin', shirinSource.aliases || [], 'mahalla')
251
+ : null;
252
+ const normalizedChoponOta = choponOtaSource
253
+ ? semanticEntry({ ...choponOtaSource, parent: 'Farhod' }, "Cho'pon ota", choponOtaSource.aliases || [], 'mahalla')
254
+ : null;
255
+
256
+ const existingXishrov = settlements.find(({ name }) => ['Xishrov', 'Xishrav', 'Khishrav'].includes(name));
257
+ const normalizedXishrov = semanticEntry(
258
+ existingXishrov || {},
259
+ 'Xishrov',
260
+ [
261
+ ...(existingXishrov?.aliases || []),
262
+ 'Xishrav',
263
+ 'Khishrav',
264
+ 'Хишрав',
265
+ "So'lim shaharchasi",
266
+ 'So‘lim shaharchasi',
267
+ 'Solim shaharchasi',
268
+ 'Сўлим шаҳарчаси',
269
+ 'Сулим шахарчаси',
270
+ ],
271
+ 'settlement',
272
+ );
273
+ const existingFarhod = settlements.find(({ name }) => ['Farhod', 'Farxod'].includes(name));
274
+ const normalizedFarhod = semanticEntry(
275
+ existingFarhod || {},
276
+ 'Farhod',
277
+ [
278
+ ...(existingFarhod?.aliases || []),
279
+ 'Farhod shaharchasi',
280
+ 'Farxod shaharchasi',
281
+ 'Фарход шаҳарчаси',
282
+ 'Фарход шахарчаси',
283
+ ],
284
+ 'settlement',
285
+ );
286
+
287
+ const verifiedSamarkandStreetRows = Object.freeze([
288
+ ['Siyob Street', ['Siyob ko‘chasi', "Siyob ko'chasi", 'Сиёб кўчаси', 'Сиабская улица']],
289
+ ["Cho'pon-Ota Street", ["Cho'pon-Ota ko'chasi", 'Cho‘pon-Ota ko‘chasi', 'Чўпон Ота кўчаси', 'улица Чупон-Ота']],
290
+ ['Academician Vohid Abdullayev Street', ['Akademik Vohid Abdullayev ko‘chasi', "Akademik Vohid Abdullayev ko'chasi", 'Vohid Abdullayev ko‘chasi', 'улица Академика Вохида Абдуллаева']],
291
+ ]);
292
+ const verifiedSamarkandStreetNames = new Set(verifiedSamarkandStreetRows.map(([name]) => name));
293
+ const verifiedSamarkandStreets = verifiedSamarkandStreetRows.map(([name, aliases]) => semanticEntry({}, name, aliases, 'street'));
294
+
171
295
  normalized = Object.freeze({
172
296
  ...normalized,
173
297
  Samarkand: Object.freeze({
174
298
  ...samarkand,
175
- localAreas: Object.freeze(localAreas.filter(({ name }) => name !== 'University Boulevard')),
299
+ mahallas: Object.freeze([
300
+ ...mahallas.filter(({ name }) => ![
301
+ 'Sogdiana',
302
+ 'Chilquduq',
303
+ 'Chilkuduq',
304
+ 'Chilkuduk',
305
+ "Navro'z",
306
+ 'Shirin',
307
+ "Cho'pon ota",
308
+ ].includes(name)),
309
+ normalizedSogdiana,
310
+ normalizedChilquduq,
311
+ ...(normalizedNavroz ? [normalizedNavroz] : []),
312
+ ...(normalizedShirin ? [normalizedShirin] : []),
313
+ ...(normalizedChoponOta ? [normalizedChoponOta] : []),
314
+ ]),
315
+ microdistricts: Object.freeze(
316
+ microdistricts.filter(({ name }) => !['Sogdiana', 'Kimyogarlar'].includes(name)),
317
+ ),
318
+ localAreas: Object.freeze(
319
+ localAreas.filter(({ name }) => !['University Boulevard', 'Sugdiyona', 'Kimyogarlar'].includes(name)),
320
+ ),
321
+ settlements: Object.freeze([
322
+ ...settlements.filter(({ name }) => !['Kimyogarlar', 'Xishrov', 'Xishrav', 'Khishrav', 'Farhod', 'Farxod'].includes(name)),
323
+ normalizedKimyogarlar,
324
+ normalizedXishrov,
325
+ normalizedFarhod,
326
+ ]),
176
327
  streets: Object.freeze([
177
- ...streets.filter(({ name }) => name !== 'University Boulevard'),
328
+ ...streets.filter(({ name }) => name !== 'University Boulevard' && !verifiedSamarkandStreetNames.has(name)),
178
329
  ...(normalizedUniversity ? [normalizedUniversity] : []),
330
+ ...verifiedSamarkandStreets,
179
331
  ]),
180
332
  landmarks: Object.freeze([
181
333
  ...landmarks.filter(({ name }) => ![
@@ -359,6 +511,7 @@ const COUNTRY_LOCATION_DICTIONARIES = Object.freeze({
359
511
  UA_SECONDARY_LOCATION_EXTENSIONS,
360
512
  UA_METRO_LOCATION_EXTENSIONS,
361
513
  UA_KHARKIV_TRANSLATION_EXTENSIONS,
514
+ UA_CITY_LOCATION_EXPANSIONS,
362
515
  ),
363
516
  });
364
517
 
@@ -60,7 +60,7 @@ export const TASHKENT_RESIDENTIAL_COMPLEXES = Object.freeze([
60
60
  complex('Comfort House', ['Комфорт Хаус']),
61
61
  complex('Darhan', ['Darkhan Residence', 'Дархан Резиденс', 'Дархан', 'Darkhan']),
62
62
  complex('DARVOZA'),
63
- complex('Dostlar', ['Do‘stlar', 'Do\'stlar', 'Doʻstlar', 'Дустлар', 'Дўстлар', 'Дустлар ЖК']),
63
+ complex('Do‘stlar', ['Dostlar', 'Do\'stlar', 'Doʻstlar', 'Дустлар', 'Дўстлар', 'Дустлар ЖК']),
64
64
  complex('Dream House', ['Дрим-Хаус', 'Дрим Хаус']),
65
65
  complex('Dreamland Aeroport'),
66
66
  complex('Dreamland Do\'stlik'),
@@ -0,0 +1,76 @@
1
+ import { locationEntries } from './location-merge.js';
2
+
3
+ const microdistricts = (rows) => Object.freeze({ microdistricts: locationEntries(rows) });
4
+
5
+ // Listing-facing aliases that enrich the major Ukraine dictionaries without
6
+ // changing their established parser canonicals. Keep physical coordinates and
7
+ // source ownership in geo-catalog.
8
+ export const UA_CITY_LOCATION_EXPANSIONS = Object.freeze({
9
+ Kharkiv: microdistricts([
10
+ ['Zhukovskoho', 'Селище ім. Жуковського', 'селище Жуковського', 'Жуковського', 'посёлок Жуковского', 'поселок Жуковского', 'Жуковского', 'Zhukovskoho settlement'],
11
+ ['Kulynychi', 'Кулиничі', 'Кулиничи', 'селище Кулиничі', 'посёлок Кулиничи', 'поселок Кулиничи', 'Kulynichi'],
12
+ ['Saltivka', 'Saltovka', 'Салтовка'],
13
+ ['Pavlove Pole', 'Pavlovo Pole', 'Pavlovo Polye'],
14
+ ['Oleksiivka', 'Alekseevka', 'Alekseyevka'],
15
+ ['Kholodna Hora', 'Kholodnaya Gora', 'Holodnaya Gora'],
16
+ ['Novi Budynky', 'Novye Doma', 'Novyye Doma'],
17
+ ['Piatykhatky', 'Pyatikhatki', 'Pyatihatki'],
18
+ ['Zaliutyne', 'Zalyutino', 'Zalutino'],
19
+ ['Rohan', 'Rogan'],
20
+ ['Zhuravlivka', 'Zhuravlevka'],
21
+ ['Velyka Danylivka', 'Bolshaya Danilovka', 'Velika Danylivka'],
22
+ ['Sokolnyky', 'Sokolniki'],
23
+ ]),
24
+
25
+ Odesa: microdistricts([
26
+ ['Vuzivskyi', 'Вузівський', 'Вузовський', 'Вузовский', 'Vuzovskyi', 'Вузівський район', 'Вузовский район'],
27
+ ['Chubaivka', 'Чубаївка', 'Чубаевка', 'Chubayevka'],
28
+ ['Arkadia', 'Arcadia', 'район Аркадії', 'район Аркадии', 'Аркадія район', 'Аркадия район'],
29
+ ['Tairova', 'Tairovo', 'район Таїрова', 'район Таирова', 'ж/м Таїрова', 'ж/м Таирова', 'жилмассив Таирова'],
30
+ ['Cheryomushky', 'Cheremushki', 'Cheryomushki', 'Черемушки Одеса', 'Черёмушки Одесса', 'Черемушки Одесса', 'Черемушки район', 'Черёмушки район'],
31
+ ['Kotivskoho', 'Котовка', 'Поскот', 'ПосКот', 'ж/м Котовського', 'ж/м Котовского', 'жилмассив Котовского'],
32
+ ['Luzanivka', 'Luzanovka', 'Лузановский район', 'Лузанівський район', 'район Лузановки', 'район Лузанівки'],
33
+ ['Malyi Fontan', 'Maly Fontan', 'Малого Фонтана', 'Малого Фонтану', 'на Малом Фонтане', 'на Малому Фонтані'],
34
+ ['Moldavanka', 'Moldovanka', 'район Молдаванки', 'на Молдаванке', 'на Молдаванці'],
35
+ ['Peresyp', 'Peresip', 'район Пересыпи', 'район Пересипу', 'на Пересыпи', 'на Пересипі'],
36
+ ['Chornomorka', 'Chernomorka', 'Черноморка район', 'Чорноморка район', 'Люстдорф', 'Lustdorf'],
37
+ ['Dacha Kovalevskoho', 'Dacha Kovalevskogo', 'Дача Ковалевского район', 'район Дачи Ковалевского', 'район Дачі Ковалевського'],
38
+ ['Zastava-1', 'Zastava 1', 'Первая Застава', 'Перша Застава', 'Застава I'],
39
+ ['Zastava-2', 'Zastava 2', 'Вторая Застава', 'Друга Застава', 'Застава II'],
40
+ ]),
41
+
42
+ Kyiv: microdistricts([
43
+ ['Troyeshchyna', 'Troieshchyna', 'Троєщина масив', 'жилмассив Троещина', 'ж/м Троєщина', 'ж/м Троещина'],
44
+ ['Lipky', 'Lypky'],
45
+ ['Lukianivka', 'Lukyanivka'],
46
+ ['Zvirynets', 'Zverinets'],
47
+ ['Holosiiv', 'Holosiyiv', 'Goloseevo'],
48
+ ['Demiivka', 'Demiyivka', 'Demeevka'],
49
+ ['Shuliavka', 'Shulyavka'],
50
+ ['Solomianka', 'Solomyanka', 'Solomenka'],
51
+ ['Chokolivka', 'Chokolovka'],
52
+ ['Vidradnyi', 'Otradnyi', 'Otradny'],
53
+ ['Karavaievi Dachi', 'Karavayevi Dachi', 'Karavaevy Dachi'],
54
+ ['Kurenivka', 'Kurenevka'],
55
+ ['Rusanivka', 'Rusanovka'],
56
+ ['Berezniaky', 'Bereznyaky'],
57
+ ['Darnytsia', 'Darnitsa'],
58
+ ['Nova Darnytsia', 'Novaya Darnitsa'],
59
+ ['Stara Darnytsia', 'Staraya Darnitsa'],
60
+ ['Pozniaky', 'Poznyaki'],
61
+ ['Bortnychi', 'Bortnichi'],
62
+ ['Feofaniia', 'Feofaniya'],
63
+ ['Vydubychi', 'Vydubichi'],
64
+ ['Lisovyi Masyv', 'Lisovyi Massif', 'Lesnoy Massiv'],
65
+ ['Minskyi Masyv', 'Minskyi Massif', 'Minskiy Massiv'],
66
+ ['Kharkivskyi', 'Kharkivskyi Masyv', 'Kharkivskyi massif', 'Харківський житловий масив', 'Харьковский жилмассив'],
67
+ ['Borshchahivka', 'Borshchagivka', 'Borshchagovka'],
68
+ ['Pivdenna Borshchahivka', 'Yuzhnaya Borshchagovka'],
69
+ ['Mykilska Borshchahivka', 'Nikolskaya Borshchagovka'],
70
+ ['Sviatoshyn', 'Svyatoshyn'],
71
+ ['Akademmistechko', 'Akademhorodok', 'Akademgorodok'],
72
+ ['Pushcha-Vodytsia', 'Pushcha Vodytsia', 'Pushcha-Voditsa'],
73
+ ['Vynohradar', 'Vinogradar'],
74
+ ['Nyvky', 'Nivki'],
75
+ ]),
76
+ });
@@ -210,6 +210,7 @@ export const UZ_LOCATION_EXTENSIONS = Object.freeze({
210
210
  ['Tashkent City', 'Ташкент Сити', 'Toshkent City', 'Tashkent City IBC'],
211
211
  ],
212
212
  streets: [
213
+ { name: "Bog'bon Street", aliases: ['Bog‘bon ko‘chasi', "Bog'bon ko'chasi", 'Bogbon kochasi', 'улица Богбон', 'ул. Богбон'], parent: 'Yunusabad' },
213
214
  { name: 'Gulobod Street', aliases: ['Gulobod ko‘chasi', "Gulobod ko'chasi", 'улица Гулобод', 'ул. Гулобод'], parent: 'Shaykhantahur' },
214
215
  { name: 'Sebzor Street', aliases: ['Sebzor ko‘chasi', "Sebzor ko'chasi", 'улица Себзор', 'ул. Себзор'], parent: 'Almazar' },
215
216
  { name: 'Lolazor Street', aliases: ['Lolazor ko‘chasi', "Lolazor ko'chasi", 'улица Лолазор', 'ул. Лолазор'], parent: 'Uchtepa' },
@@ -241,7 +242,7 @@ export const UZ_LOCATION_EXTENSIONS = Object.freeze({
241
242
  ['Registan Square','Регистан','Registon','Площадь Регистан'],['Gur-e Amir','Гур-Эмир',"Go'ri Amir",'Гўри Амир'],['Shohi Zinda','Шахи-Зинда','Шоҳи Зинда'],['Bibi-Khanym','Биби-Ханым','Bibixonim','Бибихоним'],
242
243
  ['Siyob Bazaar','Сиабский базар','Siyob bozori','Сиёб бозори'],['Afrosiyob','Афросиаб','Афросиёб'],['Ulugbek Observatory','Обсерватория Улугбека',"Ulug'bek rasadxonasi"],['University Boulevard','Университетский бульвар','Universitet xiyoboni'],
243
244
  ['Eternal City','Вечный город','Boqiy shahar'],['Silk Road Samarkand'],['Samarkand City','Самарканд Сити'],['Samarkand International Airport','Международный аэропорт Самарканд','Samarqand xalqaro aeroporti','SKD'],
244
- ['Samarkand Railway Station','Самарканд вокзал','Samarqand vokzali'],['Central Park','Центральный парк',"Markaziy bog'"],['Alisher Navoiy Park','Парк Алишера Навои',"Alisher Navoiy bog'i"],['Youth Park','Парк Молодёжи',"Yoshlar bog'i"],
245
+ ['Samarkand Railway Station','Самарканд вокзал','Samarqand vokzali'],['Alisher Navoiy Park','Central Park','Центральный парк',"Markaziy bog'",'Парк Алишера Навои',"Alisher Navoiy bog'i"],['Youth Park','Парк Молодёжи',"Yoshlar bog'i"],
245
246
  ['Yangi Ozbekiston Park',"Yangi O'zbekiston bog'i",'Парк Новый Узбекистан'],['Family Park'],
246
247
  ],
247
248
  }),