@whiteslove/parsing-lexicon 0.4.1 → 0.4.4
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,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@whiteslove/parsing-lexicon",
|
|
3
|
-
"version": "0.4.
|
|
4
|
-
"description": "Shared deterministic multilingual parsing lexicon for
|
|
3
|
+
"version": "0.4.4",
|
|
4
|
+
"description": "Shared deterministic multilingual parsing lexicon for WhitesLove housing and hiring services",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
7
7
|
"url": "git+https://github.com/AmoneMisa/parsing-lexicon.git"
|
package/src/geography-display.js
CHANGED
|
@@ -67,6 +67,12 @@ export const GEOGRAPHY_DISPLAY_NAMES = Object.freeze({
|
|
|
67
67
|
}),
|
|
68
68
|
microdistrict: Object.freeze({
|
|
69
69
|
Tsukrovyi: 'Сахарный',
|
|
70
|
+
Karakamysh: 'Каракамыш', Sebzar: 'Себзар', Tashselmash: 'Ташсельмаш', Aviasozlar: 'Авиасозлар',
|
|
71
|
+
Kuylyuk: 'Куйлюк', Sergeli: 'Сергели массив', Sputnik: 'Спутник', 'Yangi Choshtepa': 'Янги Чоштепа',
|
|
72
|
+
// Same places as Choshtepa/Takhtapul above, but under the spelling the
|
|
73
|
+
// mahalla registry (uz-location-extensions.js) actually uses as its
|
|
74
|
+
// canonical name -- exact-key lookup means both spellings must be here.
|
|
75
|
+
Chashtepa: 'Чаштепа', Taxtapul: 'Тахтапул',
|
|
70
76
|
}),
|
|
71
77
|
metro: Object.freeze({
|
|
72
78
|
'Buyuk Ipak Yoli': 'Буюк Ипак Йули', Pushkin: 'Пушкин', 'Hamid Olimjon': 'Хамид Алимджан',
|
package/src/housing-address.js
CHANGED
|
@@ -33,7 +33,11 @@ function escapeRegExp(value) {
|
|
|
33
33
|
|
|
34
34
|
function compactStreet(value) {
|
|
35
35
|
return clean(value)
|
|
36
|
-
|
|
36
|
+
// The bare abbreviations in PREFIX_STREET_MARKER (e.g. "пр" for "пр-т")
|
|
37
|
+
// must not be followed by a letter, or this would strip a false-positive
|
|
38
|
+
// prefix off an unrelated word that merely starts the same way (e.g.
|
|
39
|
+
// "проживания" -> "оживания").
|
|
40
|
+
.replace(new RegExp(`^${PREFIX_STREET_MARKER}(?!\\p{L})\\s*`, 'iu'), '')
|
|
37
41
|
.replace(new RegExp(`\\s+${POSTFIX_STREET_MARKER}$`, 'iu'), '')
|
|
38
42
|
.replace(/[\s,;:.\-–—]+$/gu, '')
|
|
39
43
|
.trim() || null;
|
|
@@ -167,7 +171,7 @@ function explicitStreetAddress(text) {
|
|
|
167
171
|
if (prefixTyped) return prefixTyped;
|
|
168
172
|
|
|
169
173
|
const boundedPrefix = line.match(new RegExp(
|
|
170
|
-
`(?:^|[\\s,;])${PREFIX_STREET_MARKER}\\s*((?:${STREET_WORD}\\s+){0,3}${STREET_WORD})(?=$|[,;])`,
|
|
174
|
+
`(?:^|[\\s,;])${PREFIX_STREET_MARKER}(?!\\p{L})\\s*((?:${STREET_WORD}\\s+){0,3}${STREET_WORD})(?=$|[,;])`,
|
|
171
175
|
'iu',
|
|
172
176
|
));
|
|
173
177
|
if (boundedPrefix) return result(boundedPrefix[0], boundedPrefix[1], null, null, 0.9);
|
package/src/housing-display.js
CHANGED
|
@@ -12,6 +12,7 @@ const DISPLAY = Object.freeze({
|
|
|
12
12
|
Market: 'Market', Cafe: 'Cafe', Restaurant: 'Restaurant', Playground: 'Playground', Pharmacy: 'Pharmacy',
|
|
13
13
|
Mosque: 'Mosque', Church: 'Church', 'Railway station': 'Railway station', Airport: 'Airport',
|
|
14
14
|
'Bobur Park': 'Bobur Park', 'Independence Square': 'Independence Square', 'Mega Planet': 'Mega Planet',
|
|
15
|
+
'Bek Baraka': 'Bek Baraka', Khadra: 'Khadra',
|
|
15
16
|
}),
|
|
16
17
|
ru: Object.freeze({
|
|
17
18
|
Park: 'Парк', Metro: 'Метро', 'Bus stop': 'Автобусная остановка', 'Public transport': 'Общественный транспорт',
|
|
@@ -21,6 +22,7 @@ const DISPLAY = Object.freeze({
|
|
|
21
22
|
Market: 'Рынок', Cafe: 'Кафе', Restaurant: 'Ресторан', Playground: 'Детская площадка', Pharmacy: 'Аптека',
|
|
22
23
|
Mosque: 'Мечеть', Church: 'Церковь', 'Railway station': 'Железнодорожный вокзал', Airport: 'Аэропорт',
|
|
23
24
|
'Bobur Park': 'Парк Бобура', 'Independence Square': 'Площадь Независимости', 'Mega Planet': 'Mega Planet',
|
|
25
|
+
'Bek Baraka': 'Бек-Барака', Khadra: 'Хадра',
|
|
24
26
|
}),
|
|
25
27
|
});
|
|
26
28
|
|
|
@@ -51,15 +53,28 @@ export function housingSemanticCanonical(value) {
|
|
|
51
53
|
return exactPoi(text)?.name || text;
|
|
52
54
|
}
|
|
53
55
|
|
|
56
|
+
function cyrillicPoiAlias(poiEntry) {
|
|
57
|
+
return (poiEntry?.aliases || []).find((alias) => /[а-яёіїґ]/iu.test(alias)) || null;
|
|
58
|
+
}
|
|
59
|
+
|
|
54
60
|
export function housingSemanticDisplayName(value, locale = 'en') {
|
|
55
61
|
const text = String(value || '').trim();
|
|
56
62
|
if (!text) return '';
|
|
57
63
|
const language = languageKey(locale);
|
|
58
64
|
const extension = extensionEntity(text);
|
|
59
65
|
if (extension?.display?.[language]) return extension.display[language];
|
|
66
|
+
const poiEntry = exactPoi(text);
|
|
60
67
|
const canonical = extension?.canonical
|
|
61
68
|
|| findCanonical(text, GENERIC_LANDMARK_TERMS)?.canonical
|
|
62
|
-
||
|
|
69
|
+
|| poiEntry?.name
|
|
63
70
|
|| text;
|
|
71
|
+
// Named landmarks (markets, squares, parks) are added one at a time in
|
|
72
|
+
// tashkent-pois.js and often only carry a Russian alias, no dedicated
|
|
73
|
+
// DISPLAY entry. Fall back to that alias for ru rather than leaking the
|
|
74
|
+
// Latin canonical name, instead of requiring every POI to be re-listed here.
|
|
75
|
+
if (language === 'ru' && !DISPLAY.ru[canonical]) {
|
|
76
|
+
const fallback = cyrillicPoiAlias(poiEntry);
|
|
77
|
+
if (fallback) return fallback;
|
|
78
|
+
}
|
|
64
79
|
return DISPLAY[language]?.[canonical] || canonical;
|
|
65
80
|
}
|
package/src/locations.js
CHANGED
|
@@ -172,11 +172,21 @@ export function matchDictionaryLocation(text, countryCode, city = null) {
|
|
|
172
172
|
const country = locationCities(countryCode);
|
|
173
173
|
const cities = city && country[city] ? [[city, country[city]]] : Object.entries(country);
|
|
174
174
|
const value = String(text || '');
|
|
175
|
+
let best = null;
|
|
175
176
|
for (const [cityName, data] of cities) {
|
|
176
177
|
for (const type of LOCATION_LIST_KEYS) {
|
|
177
|
-
const
|
|
178
|
-
|
|
178
|
+
for (const entry of data[type] || []) {
|
|
179
|
+
const match = entry?.re?.exec(value);
|
|
180
|
+
if (!match) continue;
|
|
181
|
+
const start = match.index;
|
|
182
|
+
const end = start + match[0].length;
|
|
183
|
+
const containsBest = best && start <= best.start && end >= best.end && end - start > best.end - best.start;
|
|
184
|
+
if (best && !containsBest) continue;
|
|
185
|
+
best = { city: cityName, type, name: entry.name, aliases: entry.aliases, start, end };
|
|
186
|
+
}
|
|
179
187
|
}
|
|
180
188
|
}
|
|
181
|
-
return null;
|
|
189
|
+
if (!best) return null;
|
|
190
|
+
const { start: _start, end: _end, ...result } = best;
|
|
191
|
+
return result;
|
|
182
192
|
}
|
|
@@ -210,6 +210,8 @@ export const UZ_LOCATION_EXTENSIONS = Object.freeze({
|
|
|
210
210
|
['Tashkent City', 'Ташкент Сити', 'Toshkent City', 'Tashkent City IBC'],
|
|
211
211
|
],
|
|
212
212
|
streets: [
|
|
213
|
+
{ name: 'Gulobod Street', aliases: ['Gulobod ko‘chasi', "Gulobod ko'chasi", 'улица Гулобод', 'ул. Гулобод'], parent: 'Shaykhantahur' },
|
|
214
|
+
{ name: 'Sebzor Street', aliases: ['Sebzor ko‘chasi', "Sebzor ko'chasi", 'улица Себзор', 'ул. Себзор'], parent: 'Almazar' },
|
|
213
215
|
{ name: 'Lolazor Street', aliases: ['Lolazor ko‘chasi', "Lolazor ko'chasi", 'улица Лолазор', 'ул. Лолазор'], parent: 'Uchtepa' },
|
|
214
216
|
{ name: 'Shohimardon Street', aliases: ['Shohimardon ko‘chasi', "Shohimardon ko'chasi", 'улица Шохимардон', 'ул. Шохимардон'], parent: 'Yashnobod' },
|
|
215
217
|
{ name: 'Shohimardon Passage 1', aliases: ['Shohimardon 1-tor ko‘chasi', "Shohimardon 1-tor ko'chasi", '1-й проезд Шохимардон', '1 проезд Шохимардон'], parent: 'Yashnobod' },
|