@whiteslove/parsing-lexicon 0.2.0 → 0.2.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.
Files changed (94) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +137 -137
  3. package/index.d.ts +374 -374
  4. package/package.json +77 -75
  5. package/src/central-asia-locations.js +211 -211
  6. package/src/central-asia.js +233 -233
  7. package/src/contact.d.ts +44 -44
  8. package/src/contact.js +159 -159
  9. package/src/countries.js +175 -175
  10. package/src/country-context.d.ts +10 -10
  11. package/src/country-context.js +22 -22
  12. package/src/currency.d.ts +14 -14
  13. package/src/currency.js +66 -66
  14. package/src/geo.js +169 -169
  15. package/src/geography-central-asia.js +42 -42
  16. package/src/geography-detection.d.ts +14 -14
  17. package/src/geography-detection.js +64 -64
  18. package/src/geography-display.d.ts +13 -13
  19. package/src/geography-display.js +113 -113
  20. package/src/geography.js +210 -210
  21. package/src/hiring-advanced.js +147 -147
  22. package/src/hiring-candidate-fields.d.ts +9 -9
  23. package/src/hiring-candidate-fields.js +92 -92
  24. package/src/hiring-context.d.ts +64 -64
  25. package/src/hiring-context.js +412 -412
  26. package/src/hiring-language-extensions.d.ts +19 -19
  27. package/src/hiring-language-extensions.js +139 -139
  28. package/src/hiring-languages.js +135 -135
  29. package/src/hiring-location-fields.d.ts +3 -3
  30. package/src/hiring-location-fields.js +53 -53
  31. package/src/hiring-professions-ro.js +191 -191
  32. package/src/hiring-professions.js +437 -437
  33. package/src/hiring-requirements.d.ts +16 -16
  34. package/src/hiring-requirements.js +170 -170
  35. package/src/hiring-salary-context.d.ts +27 -27
  36. package/src/hiring-salary-context.js +76 -76
  37. package/src/hiring-semantics.d.ts +29 -29
  38. package/src/hiring-semantics.js +218 -218
  39. package/src/hiring-skills.d.ts +21 -21
  40. package/src/hiring-skills.js +315 -315
  41. package/src/hiring-source-aliases.d.ts +32 -32
  42. package/src/hiring-source-aliases.js +185 -185
  43. package/src/hiring-source-semantics.d.ts +31 -31
  44. package/src/hiring-source-semantics.js +293 -293
  45. package/src/hiring-temporal.d.ts +15 -15
  46. package/src/hiring-temporal.js +67 -67
  47. package/src/hiring-vacancy-fields.d.ts +5 -5
  48. package/src/hiring-vacancy-fields.js +23 -23
  49. package/src/hiring-work-semantics.d.ts +34 -34
  50. package/src/hiring-work-semantics.js +72 -72
  51. package/src/hiring.js +180 -180
  52. package/src/housing-address.d.ts +18 -18
  53. package/src/housing-address.js +217 -210
  54. package/src/housing-commercial.d.ts +1 -0
  55. package/src/housing-commercial.js +9 -0
  56. package/src/housing-context.d.ts +36 -36
  57. package/src/housing-context.js +183 -183
  58. package/src/housing-features.js +30 -30
  59. package/src/housing-intent.d.ts +9 -9
  60. package/src/housing-intent.js +132 -132
  61. package/src/housing-listing-fields.js +131 -131
  62. package/src/housing-money.d.ts +7 -7
  63. package/src/housing-money.js +102 -102
  64. package/src/housing-source-aliases.d.ts +8 -8
  65. package/src/housing-source-aliases.js +51 -51
  66. package/src/housing-structured.d.ts +55 -55
  67. package/src/housing-structured.js +219 -219
  68. package/src/housing.js +200 -200
  69. package/src/index.js +45 -44
  70. package/src/kz-location-extensions.js +307 -307
  71. package/src/landmarks.js +21 -21
  72. package/src/lexicon-core.js +58 -58
  73. package/src/location-merge.js +106 -106
  74. package/src/locations.js +456 -456
  75. package/src/money-core.d.ts +10 -10
  76. package/src/money-core.js +81 -81
  77. package/src/money-lexicon.d.ts +5 -5
  78. package/src/money-lexicon.js +79 -79
  79. package/src/money.js +154 -154
  80. package/src/normalization.js +384 -384
  81. package/src/odesa-metropolitan.js +144 -144
  82. package/src/romania-geography.js +47 -47
  83. package/src/tashkent-colloquial.js +80 -72
  84. package/src/tashkent-housing-geography.d.ts +38 -38
  85. package/src/tashkent-housing-geography.js +211 -211
  86. package/src/tashkent-pois.js +215 -215
  87. package/src/tashkent-residential-complexes.js +272 -272
  88. package/src/ua-location-extensions-major.js +118 -118
  89. package/src/ua-location-extensions-metro.js +9 -9
  90. package/src/ua-location-extensions-regional.js +246 -246
  91. package/src/ua-secondary-cities.d.ts +2 -2
  92. package/src/ua-secondary-cities.js +57 -57
  93. package/src/ukraine.js +75 -75
  94. package/src/uz-location-extensions.js +259 -259
@@ -1,215 +1,215 @@
1
- import { aliasesToRegex } from './normalization.js';
2
-
3
- function poi(name, category, aliases = [], options = {}) {
4
- const all = [...new Set([name, ...aliases].filter(Boolean))];
5
- return Object.freeze({
6
- canonical: name,
7
- name,
8
- category,
9
- categories: Object.freeze([...new Set([category, ...(options.categories || [])])]),
10
- aliases: Object.freeze(all),
11
- re: aliasesToRegex(all),
12
- contextRequired: Boolean(options.contextRequired),
13
- contextRe: options.context ? new RegExp(options.context, 'iu') : null,
14
- });
15
- }
16
-
17
- const MALL_CONTEXT = '(?:mall|молл|трц|тц|торгов(?:ый|ого)\\s+центр|savdo\\s+markazi|shopping\\s+(?:center|centre))';
18
-
19
- export const TASHKENT_PARKS = Object.freeze([
20
- poi('Tashkent City Park', 'park', ['Ташкент Сити парк', 'Парк Tashkent City']),
21
- poi('Magic City', 'park', ['Magic City Park', 'Magic Park', 'Мэджик Сити']),
22
- poi('Ecopark', 'park', ['Eco Park', 'Экопарк', 'Центральный экопарк']),
23
- poi('Central Park Mirzo Ulugbek', 'park', ['Центральный парк имени Мирзо Улугбека', 'Центральный парк', 'Central Park', 'Парк Мирзо Улугбека']),
24
- poi('Japanese Garden', 'park', ['Японский сад', "Yapon bog'i", 'Yapon bog‘i', 'Yapon bogʻI']),
25
- poi('Milliy Bog Park', 'park', ['Миллий бог', "Milliy Bog'", 'Milliy Bog‘', 'Milliy Bogʻ', 'Национальный парк'], { contextRequired: true, context: '(?:парк|bog|боғ|park|national)' }),
26
- poi('Alisher Navoi National Park', 'park', ['Парк имени Алишера Навои']),
27
- poi('Dream Park', 'park', ['Dream Park имени Гафура Гуляма', 'Парк имени Гафура Гуляма', 'Парк Гафура Гуляма']),
28
- poi('Anhor Park', 'park', ['Anhor', 'Анхор']),
29
- poi('Lokomotiv Park', 'park', ['Anhor Lokomotiv', 'Анхор Локомотив', 'Парк Локомотив']),
30
- poi('Tashkentland', 'park', ['Ташкентленд']),
31
- poi('Victory Park', 'park', ['Парк Победы', "G'alaba Bog'i", 'G‘alaba Bog‘i', 'Gʻalaba Bogʻi']),
32
- poi('Ashgabat Park', 'park', ['Ашхабад парк', 'Ashxobod Park']),
33
- poi('Dostlik Park', 'park', ['Парк Дустлик', "Do'stlik Park", 'Do‘stlik Park', 'Doʻstlik Park']),
34
- poi('Navruz Park', 'park', ['Парк Навруз']),
35
- poi('Bobur Park', 'park', ['Парк Бабура', 'Парк Бобура', "Bobur bog'i", 'Bobur bog‘i']),
36
- poi('Furqat Park', 'park', ['Парк Фурката']),
37
- poi('Yakub Kolas Park', 'park', ['Парк Якуба Коласа', 'Парк имени Якуба Коласа']),
38
- poi('Friendship of Peoples Park', 'park', ['Парк Дружбы народов']),
39
- poi('Yangi Ozbekiston Park', 'park', ["Yangi O'zbekiston Bog'i", 'Yangi O‘zbekiston Bog‘i', 'Парк Новый Узбекистан', 'Новый Узбекистан', "Yangi O'zbekiston Park"]),
40
- ]);
41
-
42
- export const TASHKENT_SQUARES = Object.freeze([
43
- poi('Amir Timur Square', 'square', ['Площадь Амира Темура', 'Amir Temur Square', 'Сквер Амира Темура', 'Сквер']),
44
- poi('Independence Square', 'square', ['Площадь Независимости', 'Mustaqillik Maydoni', 'Mustaqillik Square', 'Площадь Мустакиллик', 'Мустақиллик майдони']),
45
- poi('Friendship of Peoples Square', 'square', ['Площадь Дружбы народов']),
46
- poi('Khadra', 'square', ['Хадра', 'Xadra']),
47
- poi('Broadway Sayilgoh', 'square', ['Broadway', 'Бродвей', 'Сайилгох', 'Sayilgoh']),
48
- ]);
49
-
50
- export const TASHKENT_MARKETS = Object.freeze([
51
- poi('Chorsu Bazaar', 'market', ['Чорсу', 'Chorsu Bazaar', 'Chorsu bozori', 'базар Чорсу', 'Чорсу бозори']),
52
- poi('Eski Juva Bazaar', 'market', ['Эски Жува', 'Eski Juva']),
53
- poi('Alay Bazaar', 'market', ['Алайский рынок', 'Алайский базар', 'Oloy bozori', 'Олой бозори']),
54
- poi('Qoyliq Bazaar', 'market', ['Куйлюк базар', 'Куйлик базар', "Qo'yliq bozori", 'Qo‘yliq bozori', 'Qoʻyliq bozori']),
55
- poi('Yunusobod Bazaar', 'market', ['Юнусабадский рынок', 'Yunusobod bozori']),
56
- poi('Farhod Bazaar', 'market', ['Фархадский рынок', 'Фархадский базар', 'Farhod bozori']),
57
- poi('Uch Qahramon Bazaar', 'market', ['Уч Кахрамон', 'Уч Кахрамон базар']),
58
- poi('Katartal Bazaar', 'market', ['Катартал', 'Катартал базар']),
59
- poi('Karakamysh Bazaar', 'market', ['Каракамышский рынок']),
60
- poi('Parkent Bazaar', 'market', ['Паркентский рынок', 'Parkent bozori']),
61
- poi('Mirobod Bazaar', 'market', ['Мирабадский рынок', 'Госпитальный рынок', 'Mirobod bozori']),
62
- poi('Sergeli Bazaar', 'market', ['Сергели рынок', 'Сергели базар']),
63
- poi('Bek Baraka', 'market', ['Бек Барака']),
64
- poi('Ippodrom Bazaar', 'market', ['Ипподром']),
65
- poi('Abu Sahiy', 'market', ['Абу Сахий']),
66
- poi('Orikzor Bazaar', 'market', ['Урикзор', "O'rikzor", 'O‘rikzor', 'Oʻrikzor']),
67
- poi('Kadysheva Bazaar', 'market', ['Кадышева рынок', 'Кадышева базар']),
68
- poi('Yangiobod Bazaar', 'market', ['Янгиабадский рынок', 'Янгиабад', 'Yangiobod bozori']),
69
- ]);
70
-
71
- export const TASHKENT_MALLS = Object.freeze([
72
- poi('Tashkent City Mall', 'mall', ['Ташкент Сити Молл']),
73
- poi('Samarqand Darvoza', 'mall', ['Самарканд Дарвоза']),
74
- poi('Compass Mall', 'mall', ['Compass'], { contextRequired: true, context: MALL_CONTEXT }),
75
- poi('Mega Planet', 'mall', ['MegaPlanet']),
76
- poi('Riviera Mall', 'mall', ['Riviera'], { contextRequired: true, context: MALL_CONTEXT }),
77
- poi('NEXT Mall', 'mall', ['Next', 'NEXT'], { contextRequired: true, context: MALL_CONTEXT }),
78
- poi('Atlas Mall', 'mall', ['Atlas'], { contextRequired: true, context: MALL_CONTEXT }),
79
- poi('Parus Mall', 'mall', ['Parus'], { contextRequired: true, context: MALL_CONTEXT }),
80
- poi('Depo Mall', 'mall', ['Depo'], { contextRequired: true, context: MALL_CONTEXT }),
81
- poi('Vega Centre', 'mall', ['Vega Center']),
82
- poi('Yunusabad Gallery', 'mall'),
83
- poi('Poytaxt Mall', 'mall', ['Poytaxt'], { contextRequired: true, context: MALL_CONTEXT }),
84
- poi('Alfraganus Mall', 'mall', ['Alfraganus'], { contextRequired: true, context: MALL_CONTEXT }),
85
- poi('HT Mall', 'mall'),
86
- poi('Seoul Mun Mall', 'mall', ['Seoul Mun'], { contextRequired: true, context: MALL_CONTEXT }),
87
- poi('Ecobozor', 'mall', ['Eco Bozor']),
88
- ]);
89
-
90
- export const TASHKENT_ATTRACTIONS = Object.freeze([
91
- poi('Tashkent TV Tower', 'attraction', ['Телебашня', 'Ташкентская телебашня']),
92
- poi('Minor Mosque', 'religious', ['Мечеть Минор', 'Minor masjidi', 'Минор'], { contextRequired: true, context: '(?:мечет|mosque|masjid|масжид)' }),
93
- poi('Hazrati Imam', 'attraction', ['Хазрати Имам', 'Хаст Имам', 'Hast Imam', 'Khazrati Imam Complex']),
94
- poi('Kaffal Shashi Mausoleum', 'religious', ['Мавзолей Каффаля Шаши']),
95
- poi('Barak-Khan Madrasa', 'religious', ['Медресе Баракхан', 'Barak Khan Madrasa']),
96
- poi('Kukeldash Madrasa', 'religious', ['Медресе Кукельдаш']),
97
- poi('Khoja Ahrar Vali Mosque', 'religious', ['Мечеть Ходжа Ахрар Вали']),
98
- poi('Sacred Heart Cathedral', 'religious', ['Собор Святейшего Сердца Иисуса', 'Католический костёл']),
99
- poi('Holy Assumption Cathedral', 'religious', ['Успенский собор']),
100
- poi('Sheikh Zayniddin Mosque', 'religious', ['Мечеть Шейха Зайниддина']),
101
- poi('Suzuk Ota', 'attraction', ['Сузук Ота', 'Комплекс Сузук Ота']),
102
- poi('Ming Urik Archaeological Site', 'attraction', ['Минг Урик', "Ming O'rik archaeological site", 'Ming Urik'], { contextRequired: true, context: '(?:археолог|archaeolog|site|городищ|комплекс)' }),
103
- ]);
104
-
105
- export const TASHKENT_CULTURAL_POIS = Object.freeze([
106
- poi('Amir Timur Museum', 'museum', ['Государственный музей истории Тимуридов', 'Музей Амира Темура', 'Museum of the Temurids']),
107
- poi('State Museum of History of Uzbekistan', 'museum', ['Государственный музей истории Узбекистана']),
108
- poi('Museum of Arts of Uzbekistan', 'museum', ['Государственный музей искусств Узбекистана']),
109
- poi('Museum of Applied Arts', 'museum', ['Музей прикладного искусства']),
110
- poi('Railway Museum', 'museum', ['Музей железнодорожной техники']),
111
- poi('Museum of Olympic Glory', 'museum', ['Музей Олимпийской славы']),
112
- poi('Tamara Khanum Museum', 'museum', ['Дом-музей Тамары Ханум']),
113
- poi('Alisher Navoi Museum of Literature', 'museum', ['Музей литературы Алишера Навои']),
114
- poi('Art Gallery of Uzbekistan', 'museum', ['Государственная галерея искусств']),
115
- poi('Alisher Navoi Theatre', 'culture', ['Театр имени Алишера Навои', 'Большой театр Навои']),
116
- poi('Xalqlar Dostligi Palace', 'culture', ['Дворец Дружбы народов', "Xalqlar Do'stligi Palace", 'Xalqlar Do‘stligi Palace']),
117
- poi('Istiqlol Palace', 'culture', ['Дворец искусств Истиклол']),
118
- poi('Dom Kino', 'culture', ['Дом кино']),
119
- poi('Panoramic Cinema', 'culture', ['Панорамный кинотеатр']),
120
- poi('Alley of Writers', 'culture', ['Аллея литераторов']),
121
- poi('Tashkent Chimes', 'culture', ['Куранты', 'Ташкентские куранты']),
122
- ]);
123
-
124
- export const TASHKENT_TRANSPORT_POIS = Object.freeze([
125
- poi('Tashkent International Airport', 'airport', ['Международный аэропорт Ташкент', 'Аэропорт имени Ислама Каримова', 'Международный аэропорт имени Ислама Каримова', 'Tashkent Airport', 'Toshkent aeroporti']),
126
- poi('Tashkent Domestic Airport', 'airport', ['Аэропорт местных авиалиний', 'Аэропорт внутренних рейсов']),
127
- poi('Tashkent Central Railway Station', 'railway', ['Северный вокзал', 'Ташкент Северный', 'Toshkent Markaziy', 'Центральный вокзал', 'Ташкент Северный вокзал']),
128
- poi('Tashkent South Railway Station', 'railway', ['Южный вокзал', 'Ташкент Южный', 'Toshkent Janubiy', 'Ташкент Южный вокзал']),
129
- poi('Tashkent Bus Station', 'bus', ['Автовокзал Ташкент']),
130
- ]);
131
-
132
- const TASHKENT_MEDICAL_ACADEMY = poi('Tashkent Medical Academy', 'university', ['ТМА', 'Ташкентская медицинская академия'], { categories: ['medical'] });
133
-
134
- export const TASHKENT_UNIVERSITIES = Object.freeze([
135
- poi('National University of Uzbekistan', 'university', ['Национальный университет Узбекистана', 'NUUz', "O'zMU", 'O‘zMU', 'OʻzMU']),
136
- poi('University of World Economy and Diplomacy', 'university', ['Университет мировой экономики и дипломатии', 'UWED']),
137
- poi('Westminster International University in Tashkent', 'university', ['WIUT', 'Вестминстер']),
138
- poi('Turin Polytechnic University in Tashkent', 'university', ['Turin Polytechnic University', 'Туринский политех']),
139
- poi('INHA University in Tashkent', 'university', ['INHA', 'Университет Инха']),
140
- poi('Tashkent State Technical University', 'university', ['ТашГТУ', 'ТГТУ']),
141
- poi('Tashkent State University of Economics', 'university', ['ТГЭУ', 'Ташкентский государственный экономический университет']),
142
- poi('Tashkent State University of Law', 'university', ['ТГЮУ', 'Ташкентский государственный юридический университет']),
143
- TASHKENT_MEDICAL_ACADEMY,
144
- poi('Tashkent University of Information Technologies', 'university', ['TUIT', 'ТУИТ']),
145
- poi('Webster University Tashkent', 'university', ['Webster']),
146
- poi('TEAM University', 'university'),
147
- poi('Kimyo International University', 'university', ['Yeoju']),
148
- poi('MDIS Tashkent', 'university'),
149
- poi('Ajou University in Tashkent', 'university', ['ADJU']),
150
- poi('New Uzbekistan University', 'university', ['Новый университет Узбекистана']),
151
- ]);
152
-
153
- export const TASHKENT_MEDICAL_POIS = Object.freeze([
154
- TASHKENT_MEDICAL_ACADEMY,
155
- poi('Tashkent City Hospital No. 1', 'medical', ['1-я городская больница']),
156
- poi('Tashkent City Hospital No. 4', 'medical', ['4-я городская больница']),
157
- poi('Tashkent City Hospital No. 5', 'medical', ['5-я городская больница']),
158
- poi('Tashkent City Hospital No. 7', 'medical', ['7-я городская больница']),
159
- poi('Tashkent City Hospital No. 16', 'medical', ['16-я городская больница', '16-я больница']),
160
- poi('Republican Oncology Center', 'medical', ['Республиканский онкоцентр', 'Онкология']),
161
- poi('Republican Cardiology Center', 'medical', ['Республиканский кардиоцентр', 'Кардиоцентр']),
162
- poi('Republican Emergency Medical Center', 'medical', ['Республиканский центр экстренной медицинской помощи']),
163
- poi('Republican Perinatal Center', 'medical', ['Республиканский перинатальный центр', 'Перинатальный центр']),
164
- poi('Institute of Obstetrics and Gynecology', 'medical', ['Институт акушерства и гинекологии']),
165
- ]);
166
-
167
- export const TASHKENT_LEGACY_LANDMARKS = Object.freeze([
168
- poi('TSUM', 'legacy', ['ЦУМ']),
169
- poi('Main Post Office', 'legacy', ['Главпочтамт']),
170
- poi('GUM', 'legacy', ['ГУМ']),
171
- ]);
172
-
173
- export const TASHKENT_POI_GROUPS = Object.freeze({
174
- parks: TASHKENT_PARKS,
175
- squares: TASHKENT_SQUARES,
176
- markets: TASHKENT_MARKETS,
177
- malls: TASHKENT_MALLS,
178
- attractions: TASHKENT_ATTRACTIONS,
179
- culture: TASHKENT_CULTURAL_POIS,
180
- transport: TASHKENT_TRANSPORT_POIS,
181
- universities: TASHKENT_UNIVERSITIES,
182
- medical: TASHKENT_MEDICAL_POIS,
183
- legacy: TASHKENT_LEGACY_LANDMARKS,
184
- });
185
-
186
- const seen = new Set();
187
- export const TASHKENT_LANDMARKS = Object.freeze(Object.values(TASHKENT_POI_GROUPS).flat().filter((entry) => {
188
- const key = entry.name;
189
- if (seen.has(key)) return false;
190
- seen.add(key);
191
- return true;
192
- }));
193
-
194
- function hasRequiredContext(entry, text, start, end) {
195
- if (!entry.contextRequired) return true;
196
- const around = text.slice(Math.max(0, start - 48), Math.min(text.length, end + 48));
197
- return entry.contextRe?.test(around) ?? false;
198
- }
199
-
200
- export function matchTashkentPoi(value, category = null) {
201
- const text = String(value ?? '');
202
- if (!text) return null;
203
- const catalog = category ? (TASHKENT_POI_GROUPS[category] || []) : TASHKENT_LANDMARKS;
204
- const matches = [];
205
- for (const entry of catalog) {
206
- const match = text.match(entry.re);
207
- if (!match) continue;
208
- const start = match.index ?? 0;
209
- const end = start + match[0].length;
210
- if (!hasRequiredContext(entry, text, start, end)) continue;
211
- matches.push({ entry, start, length: match[0].trim().length });
212
- }
213
- matches.sort((a, b) => b.length - a.length || a.start - b.start);
214
- return matches[0]?.entry ?? null;
215
- }
1
+ import { aliasesToRegex } from './normalization.js';
2
+
3
+ function poi(name, category, aliases = [], options = {}) {
4
+ const all = [...new Set([name, ...aliases].filter(Boolean))];
5
+ return Object.freeze({
6
+ canonical: name,
7
+ name,
8
+ category,
9
+ categories: Object.freeze([...new Set([category, ...(options.categories || [])])]),
10
+ aliases: Object.freeze(all),
11
+ re: aliasesToRegex(all),
12
+ contextRequired: Boolean(options.contextRequired),
13
+ contextRe: options.context ? new RegExp(options.context, 'iu') : null,
14
+ });
15
+ }
16
+
17
+ const MALL_CONTEXT = '(?:mall|молл|трц|тц|торгов(?:ый|ого)\\s+центр|savdo\\s+markazi|shopping\\s+(?:center|centre))';
18
+
19
+ export const TASHKENT_PARKS = Object.freeze([
20
+ poi('Tashkent City Park', 'park', ['Ташкент Сити парк', 'Парк Tashkent City']),
21
+ poi('Magic City', 'park', ['Magic City Park', 'Magic Park', 'Мэджик Сити']),
22
+ poi('Ecopark', 'park', ['Eco Park', 'Экопарк', 'Центральный экопарк']),
23
+ poi('Central Park Mirzo Ulugbek', 'park', ['Центральный парк имени Мирзо Улугбека', 'Центральный парк', 'Central Park', 'Парк Мирзо Улугбека']),
24
+ poi('Japanese Garden', 'park', ['Японский сад', "Yapon bog'i", 'Yapon bog‘i', 'Yapon bogʻI']),
25
+ poi('Milliy Bog Park', 'park', ['Миллий бог', "Milliy Bog'", 'Milliy Bog‘', 'Milliy Bogʻ', 'Национальный парк'], { contextRequired: true, context: '(?:парк|bog|боғ|park|national)' }),
26
+ poi('Alisher Navoi National Park', 'park', ['Парк имени Алишера Навои']),
27
+ poi('Dream Park', 'park', ['Dream Park имени Гафура Гуляма', 'Парк имени Гафура Гуляма', 'Парк Гафура Гуляма']),
28
+ poi('Anhor Park', 'park', ['Anhor', 'Анхор']),
29
+ poi('Lokomotiv Park', 'park', ['Anhor Lokomotiv', 'Анхор Локомотив', 'Парк Локомотив']),
30
+ poi('Tashkentland', 'park', ['Ташкентленд']),
31
+ poi('Victory Park', 'park', ['Парк Победы', "G'alaba Bog'i", 'G‘alaba Bog‘i', 'Gʻalaba Bogʻi']),
32
+ poi('Ashgabat Park', 'park', ['Ашхабад парк', 'Ashxobod Park']),
33
+ poi('Dostlik Park', 'park', ['Парк Дустлик', "Do'stlik Park", 'Do‘stlik Park', 'Doʻstlik Park']),
34
+ poi('Navruz Park', 'park', ['Парк Навруз']),
35
+ poi('Bobur Park', 'park', ['Парк Бабура', 'Парк Бобура', "Bobur bog'i", 'Bobur bog‘i']),
36
+ poi('Furqat Park', 'park', ['Парк Фурката']),
37
+ poi('Yakub Kolas Park', 'park', ['Парк Якуба Коласа', 'Парк имени Якуба Коласа']),
38
+ poi('Friendship of Peoples Park', 'park', ['Парк Дружбы народов']),
39
+ poi('Yangi Ozbekiston Park', 'park', ["Yangi O'zbekiston Bog'i", 'Yangi O‘zbekiston Bog‘i', 'Парк Новый Узбекистан', 'Новый Узбекистан', "Yangi O'zbekiston Park"]),
40
+ ]);
41
+
42
+ export const TASHKENT_SQUARES = Object.freeze([
43
+ poi('Amir Timur Square', 'square', ['Площадь Амира Темура', 'Amir Temur Square', 'Сквер Амира Темура', 'Сквер']),
44
+ poi('Independence Square', 'square', ['Площадь Независимости', 'Mustaqillik Maydoni', 'Mustaqillik Square', 'Площадь Мустакиллик', 'Мустақиллик майдони']),
45
+ poi('Friendship of Peoples Square', 'square', ['Площадь Дружбы народов']),
46
+ poi('Khadra', 'square', ['Хадра', 'Xadra']),
47
+ poi('Broadway Sayilgoh', 'square', ['Broadway', 'Бродвей', 'Сайилгох', 'Sayilgoh']),
48
+ ]);
49
+
50
+ export const TASHKENT_MARKETS = Object.freeze([
51
+ poi('Chorsu Bazaar', 'market', ['Чорсу', 'Chorsu Bazaar', 'Chorsu bozori', 'базар Чорсу', 'Чорсу бозори']),
52
+ poi('Eski Juva Bazaar', 'market', ['Эски Жува', 'Eski Juva']),
53
+ poi('Alay Bazaar', 'market', ['Алайский рынок', 'Алайский базар', 'Oloy bozori', 'Олой бозори']),
54
+ poi('Qoyliq Bazaar', 'market', ['Куйлюк базар', 'Куйлик базар', "Qo'yliq bozori", 'Qo‘yliq bozori', 'Qoʻyliq bozori']),
55
+ poi('Yunusobod Bazaar', 'market', ['Юнусабадский рынок', 'Yunusobod bozori']),
56
+ poi('Farhod Bazaar', 'market', ['Фархадский рынок', 'Фархадский базар', 'Farhod bozori']),
57
+ poi('Uch Qahramon Bazaar', 'market', ['Уч Кахрамон', 'Уч Кахрамон базар']),
58
+ poi('Katartal Bazaar', 'market', ['Катартал', 'Катартал базар']),
59
+ poi('Karakamysh Bazaar', 'market', ['Каракамышский рынок']),
60
+ poi('Parkent Bazaar', 'market', ['Паркентский рынок', 'Parkent bozori']),
61
+ poi('Mirobod Bazaar', 'market', ['Мирабадский рынок', 'Госпитальный рынок', 'Mirobod bozori']),
62
+ poi('Sergeli Bazaar', 'market', ['Сергели рынок', 'Сергели базар']),
63
+ poi('Bek Baraka', 'market', ['Бек Барака']),
64
+ poi('Ippodrom Bazaar', 'market', ['Ипподром']),
65
+ poi('Abu Sahiy', 'market', ['Абу Сахий']),
66
+ poi('Orikzor Bazaar', 'market', ['Урикзор', "O'rikzor", 'O‘rikzor', 'Oʻrikzor']),
67
+ poi('Kadysheva Bazaar', 'market', ['Кадышева рынок', 'Кадышева базар']),
68
+ poi('Yangiobod Bazaar', 'market', ['Янгиабадский рынок', 'Янгиабад', 'Yangiobod bozori']),
69
+ ]);
70
+
71
+ export const TASHKENT_MALLS = Object.freeze([
72
+ poi('Tashkent City Mall', 'mall', ['Ташкент Сити Молл']),
73
+ poi('Samarqand Darvoza', 'mall', ['Самарканд Дарвоза']),
74
+ poi('Compass Mall', 'mall', ['Compass'], { contextRequired: true, context: MALL_CONTEXT }),
75
+ poi('Mega Planet', 'mall', ['MegaPlanet']),
76
+ poi('Riviera Mall', 'mall', ['Riviera'], { contextRequired: true, context: MALL_CONTEXT }),
77
+ poi('NEXT Mall', 'mall', ['Next', 'NEXT'], { contextRequired: true, context: MALL_CONTEXT }),
78
+ poi('Atlas Mall', 'mall', ['Atlas'], { contextRequired: true, context: MALL_CONTEXT }),
79
+ poi('Parus Mall', 'mall', ['Parus'], { contextRequired: true, context: MALL_CONTEXT }),
80
+ poi('Depo Mall', 'mall', ['Depo'], { contextRequired: true, context: MALL_CONTEXT }),
81
+ poi('Vega Centre', 'mall', ['Vega Center']),
82
+ poi('Yunusabad Gallery', 'mall'),
83
+ poi('Poytaxt Mall', 'mall', ['Poytaxt'], { contextRequired: true, context: MALL_CONTEXT }),
84
+ poi('Alfraganus Mall', 'mall', ['Alfraganus'], { contextRequired: true, context: MALL_CONTEXT }),
85
+ poi('HT Mall', 'mall'),
86
+ poi('Seoul Mun Mall', 'mall', ['Seoul Mun'], { contextRequired: true, context: MALL_CONTEXT }),
87
+ poi('Ecobozor', 'mall', ['Eco Bozor']),
88
+ ]);
89
+
90
+ export const TASHKENT_ATTRACTIONS = Object.freeze([
91
+ poi('Tashkent TV Tower', 'attraction', ['Телебашня', 'Ташкентская телебашня']),
92
+ poi('Minor Mosque', 'religious', ['Мечеть Минор', 'Minor masjidi', 'Минор'], { contextRequired: true, context: '(?:мечет|mosque|masjid|масжид)' }),
93
+ poi('Hazrati Imam', 'attraction', ['Хазрати Имам', 'Хаст Имам', 'Hast Imam', 'Khazrati Imam Complex']),
94
+ poi('Kaffal Shashi Mausoleum', 'religious', ['Мавзолей Каффаля Шаши']),
95
+ poi('Barak-Khan Madrasa', 'religious', ['Медресе Баракхан', 'Barak Khan Madrasa']),
96
+ poi('Kukeldash Madrasa', 'religious', ['Медресе Кукельдаш']),
97
+ poi('Khoja Ahrar Vali Mosque', 'religious', ['Мечеть Ходжа Ахрар Вали']),
98
+ poi('Sacred Heart Cathedral', 'religious', ['Собор Святейшего Сердца Иисуса', 'Католический костёл']),
99
+ poi('Holy Assumption Cathedral', 'religious', ['Успенский собор']),
100
+ poi('Sheikh Zayniddin Mosque', 'religious', ['Мечеть Шейха Зайниддина']),
101
+ poi('Suzuk Ota', 'attraction', ['Сузук Ота', 'Комплекс Сузук Ота']),
102
+ poi('Ming Urik Archaeological Site', 'attraction', ['Минг Урик', "Ming O'rik archaeological site", 'Ming Urik'], { contextRequired: true, context: '(?:археолог|archaeolog|site|городищ|комплекс)' }),
103
+ ]);
104
+
105
+ export const TASHKENT_CULTURAL_POIS = Object.freeze([
106
+ poi('Amir Timur Museum', 'museum', ['Государственный музей истории Тимуридов', 'Музей Амира Темура', 'Museum of the Temurids']),
107
+ poi('State Museum of History of Uzbekistan', 'museum', ['Государственный музей истории Узбекистана']),
108
+ poi('Museum of Arts of Uzbekistan', 'museum', ['Государственный музей искусств Узбекистана']),
109
+ poi('Museum of Applied Arts', 'museum', ['Музей прикладного искусства']),
110
+ poi('Railway Museum', 'museum', ['Музей железнодорожной техники']),
111
+ poi('Museum of Olympic Glory', 'museum', ['Музей Олимпийской славы']),
112
+ poi('Tamara Khanum Museum', 'museum', ['Дом-музей Тамары Ханум']),
113
+ poi('Alisher Navoi Museum of Literature', 'museum', ['Музей литературы Алишера Навои']),
114
+ poi('Art Gallery of Uzbekistan', 'museum', ['Государственная галерея искусств']),
115
+ poi('Alisher Navoi Theatre', 'culture', ['Театр имени Алишера Навои', 'Большой театр Навои']),
116
+ poi('Xalqlar Dostligi Palace', 'culture', ['Дворец Дружбы народов', "Xalqlar Do'stligi Palace", 'Xalqlar Do‘stligi Palace']),
117
+ poi('Istiqlol Palace', 'culture', ['Дворец искусств Истиклол']),
118
+ poi('Dom Kino', 'culture', ['Дом кино']),
119
+ poi('Panoramic Cinema', 'culture', ['Панорамный кинотеатр']),
120
+ poi('Alley of Writers', 'culture', ['Аллея литераторов']),
121
+ poi('Tashkent Chimes', 'culture', ['Куранты', 'Ташкентские куранты']),
122
+ ]);
123
+
124
+ export const TASHKENT_TRANSPORT_POIS = Object.freeze([
125
+ poi('Tashkent International Airport', 'airport', ['Международный аэропорт Ташкент', 'Аэропорт имени Ислама Каримова', 'Международный аэропорт имени Ислама Каримова', 'Tashkent Airport', 'Toshkent aeroporti']),
126
+ poi('Tashkent Domestic Airport', 'airport', ['Аэропорт местных авиалиний', 'Аэропорт внутренних рейсов']),
127
+ poi('Tashkent Central Railway Station', 'railway', ['Северный вокзал', 'Ташкент Северный', 'Toshkent Markaziy', 'Центральный вокзал', 'Ташкент Северный вокзал']),
128
+ poi('Tashkent South Railway Station', 'railway', ['Южный вокзал', 'Ташкент Южный', 'Toshkent Janubiy', 'Ташкент Южный вокзал']),
129
+ poi('Tashkent Bus Station', 'bus', ['Автовокзал Ташкент']),
130
+ ]);
131
+
132
+ const TASHKENT_MEDICAL_ACADEMY = poi('Tashkent Medical Academy', 'university', ['ТМА', 'Ташкентская медицинская академия'], { categories: ['medical'] });
133
+
134
+ export const TASHKENT_UNIVERSITIES = Object.freeze([
135
+ poi('National University of Uzbekistan', 'university', ['Национальный университет Узбекистана', 'NUUz', "O'zMU", 'O‘zMU', 'OʻzMU']),
136
+ poi('University of World Economy and Diplomacy', 'university', ['Университет мировой экономики и дипломатии', 'UWED']),
137
+ poi('Westminster International University in Tashkent', 'university', ['WIUT', 'Вестминстер']),
138
+ poi('Turin Polytechnic University in Tashkent', 'university', ['Turin Polytechnic University', 'Туринский политех']),
139
+ poi('INHA University in Tashkent', 'university', ['INHA', 'Университет Инха']),
140
+ poi('Tashkent State Technical University', 'university', ['ТашГТУ', 'ТГТУ']),
141
+ poi('Tashkent State University of Economics', 'university', ['ТГЭУ', 'Ташкентский государственный экономический университет']),
142
+ poi('Tashkent State University of Law', 'university', ['ТГЮУ', 'Ташкентский государственный юридический университет']),
143
+ TASHKENT_MEDICAL_ACADEMY,
144
+ poi('Tashkent University of Information Technologies', 'university', ['TUIT', 'ТУИТ']),
145
+ poi('Webster University Tashkent', 'university', ['Webster']),
146
+ poi('TEAM University', 'university'),
147
+ poi('Kimyo International University', 'university', ['Yeoju']),
148
+ poi('MDIS Tashkent', 'university'),
149
+ poi('Ajou University in Tashkent', 'university', ['ADJU']),
150
+ poi('New Uzbekistan University', 'university', ['Новый университет Узбекистана']),
151
+ ]);
152
+
153
+ export const TASHKENT_MEDICAL_POIS = Object.freeze([
154
+ TASHKENT_MEDICAL_ACADEMY,
155
+ poi('Tashkent City Hospital No. 1', 'medical', ['1-я городская больница']),
156
+ poi('Tashkent City Hospital No. 4', 'medical', ['4-я городская больница']),
157
+ poi('Tashkent City Hospital No. 5', 'medical', ['5-я городская больница']),
158
+ poi('Tashkent City Hospital No. 7', 'medical', ['7-я городская больница']),
159
+ poi('Tashkent City Hospital No. 16', 'medical', ['16-я городская больница', '16-я больница']),
160
+ poi('Republican Oncology Center', 'medical', ['Республиканский онкоцентр', 'Онкология']),
161
+ poi('Republican Cardiology Center', 'medical', ['Республиканский кардиоцентр', 'Кардиоцентр']),
162
+ poi('Republican Emergency Medical Center', 'medical', ['Республиканский центр экстренной медицинской помощи']),
163
+ poi('Republican Perinatal Center', 'medical', ['Республиканский перинатальный центр', 'Перинатальный центр']),
164
+ poi('Institute of Obstetrics and Gynecology', 'medical', ['Институт акушерства и гинекологии']),
165
+ ]);
166
+
167
+ export const TASHKENT_LEGACY_LANDMARKS = Object.freeze([
168
+ poi('TSUM', 'legacy', ['ЦУМ']),
169
+ poi('Main Post Office', 'legacy', ['Главпочтамт']),
170
+ poi('GUM', 'legacy', ['ГУМ']),
171
+ ]);
172
+
173
+ export const TASHKENT_POI_GROUPS = Object.freeze({
174
+ parks: TASHKENT_PARKS,
175
+ squares: TASHKENT_SQUARES,
176
+ markets: TASHKENT_MARKETS,
177
+ malls: TASHKENT_MALLS,
178
+ attractions: TASHKENT_ATTRACTIONS,
179
+ culture: TASHKENT_CULTURAL_POIS,
180
+ transport: TASHKENT_TRANSPORT_POIS,
181
+ universities: TASHKENT_UNIVERSITIES,
182
+ medical: TASHKENT_MEDICAL_POIS,
183
+ legacy: TASHKENT_LEGACY_LANDMARKS,
184
+ });
185
+
186
+ const seen = new Set();
187
+ export const TASHKENT_LANDMARKS = Object.freeze(Object.values(TASHKENT_POI_GROUPS).flat().filter((entry) => {
188
+ const key = entry.name;
189
+ if (seen.has(key)) return false;
190
+ seen.add(key);
191
+ return true;
192
+ }));
193
+
194
+ function hasRequiredContext(entry, text, start, end) {
195
+ if (!entry.contextRequired) return true;
196
+ const around = text.slice(Math.max(0, start - 48), Math.min(text.length, end + 48));
197
+ return entry.contextRe?.test(around) ?? false;
198
+ }
199
+
200
+ export function matchTashkentPoi(value, category = null) {
201
+ const text = String(value ?? '');
202
+ if (!text) return null;
203
+ const catalog = category ? (TASHKENT_POI_GROUPS[category] || []) : TASHKENT_LANDMARKS;
204
+ const matches = [];
205
+ for (const entry of catalog) {
206
+ const match = text.match(entry.re);
207
+ if (!match) continue;
208
+ const start = match.index ?? 0;
209
+ const end = start + match[0].length;
210
+ if (!hasRequiredContext(entry, text, start, end)) continue;
211
+ matches.push({ entry, start, length: match[0].trim().length });
212
+ }
213
+ matches.sort((a, b) => b.length - a.length || a.start - b.start);
214
+ return matches[0]?.entry ?? null;
215
+ }