@finbheara/domain 0.13.1 → 0.19.0
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 +12 -5
- package/dist/age.js +53 -16
- package/dist/chunks/{place-sa6438qr.js → place-39zj2ymq.js} +370 -27
- package/dist/person.js +3 -3
- package/dist/place.js +1 -1
- package/dist/promotion.js +6 -0
- package/dist/school.js +48 -41
- package/dist/types/age-types.d.ts +1 -1
- package/dist/types/person.d.ts +3 -3
- package/dist/types/school-institution-vocabulary.d.ts +2 -0
- package/dist/types/school-tokens.d.ts +0 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -262,6 +262,7 @@ Age.fromTitle("Open Championship 15-16", { year: 2026 }).token; // "15-
|
|
|
262
262
|
Age.fromTitle("Competition 719OC - Open Championship (O18)").token; // "o18", not "o9"
|
|
263
263
|
Age.fromTitle("Treble Reel Special", { year: 2026 }).age.isEmpty(); // true
|
|
264
264
|
Age.fromTitle("Mixed Reel 7 & Under").token; // "u8": a 7-year-old dances in it
|
|
265
|
+
Age.fromTitle("Mixed Reel Under 08 / 2 yr").token; // "u8/2yr": the two ages under 8
|
|
265
266
|
Age.fromTitle("Girls 8 and under 9 years").token; // "8-9"
|
|
266
267
|
Age.fromTitle("Junior Boys 12 Years").token; // "u13"
|
|
267
268
|
Age.fromTitle("10-11 Single Jig").token; // "10-11", a band, not a number
|
|
@@ -271,7 +272,7 @@ Age.fromTitle("Beginner Adults Reel U40").token; // "adult u40": the adul
|
|
|
271
272
|
Age.fromTitle("Solo Championship - Adult O40").token; // "adult o40": adult, and 40 or over
|
|
272
273
|
Age.fromTitle("Adult Championship 18 - 29").token; // "adult 18-29": adult, and the range
|
|
273
274
|
Age.fromTitle("Adult / Child Reel Under 10").token; // "u10": no adult dances in it
|
|
274
|
-
Age.fromTitle("Senior Adult Ladies 19 & Over").token; // "
|
|
275
|
+
Age.fromTitle("Senior Adult Ladies 19 & Over").token; // "o19": TIDA's oldest youth championship
|
|
275
276
|
Age.fromTitle("Senior Adult Men 17 & Over").token; // "o17": it admits under-18s
|
|
276
277
|
Age.fromTitle("Championship (Adult) (A40U)").token; // "adult u40": a split adult code
|
|
277
278
|
Age.fromTitle("Traditional Set (A40O)").token; // "adult o40"
|
|
@@ -288,10 +289,10 @@ An adult word beside an and-over from 18 or a range from 18 reads both as well:
|
|
|
288
289
|
`adult 18-29` are adult (`isAdult()`), and their `kind`, interval and birth years are the ones the
|
|
289
290
|
band alone reads on the same ladder, a range floored at 18 where no rung sits below it. So
|
|
290
291
|
`Age.from("adult o40", { year: 2026 })` is born 1985 or earlier, as `o40` is. An and-over under
|
|
291
|
-
18 or a range opening under 18 (`Teen & Adult 13 & Over`) admits youth, and the band stands.
|
|
292
|
-
|
|
293
|
-
`Senior Adult Ladies 19 & Over` is `
|
|
294
|
-
`(A40U)` is `adult u40`, `(A40O)` and `(A40&O)` are `adult o40`.
|
|
292
|
+
18 or a range opening under 18 (`Teen & Adult 13 & Over`) admits youth, and the band stands. TIDA's
|
|
293
|
+
`Senior Adult` beside an and-over is its oldest youth championship, an open championship that
|
|
294
|
+
qualifies for the Worlds, so `Senior Adult Ladies 19 & Over` is `o19`. A closing split
|
|
295
|
+
adult code keeps its split: `(A40U)` is `adult u40`, `(A40O)` and `(A40&O)` are `adult o40`.
|
|
295
296
|
|
|
296
297
|
`adultBeside(band)` is that reading as one function, the band beside the adult word as one token,
|
|
297
298
|
or `undefined` where the band admits youth. A caller holding a band from another field asks it: a
|
|
@@ -300,6 +301,12 @@ platform's printed `18&O` beside a title that reads adult is `adult o18`.
|
|
|
300
301
|
An age group is the age on the first of January, so a title that admits the dancer who is
|
|
301
302
|
`N` (`7 & Under`, `7/U`, `7 Years`) is the `Under N+1` group.
|
|
302
303
|
|
|
304
|
+
An under band may print its stride, the number of ages it holds: `Under 08 / 2 yr` is the ages 6
|
|
305
|
+
and 7, and reads `u8/2yr`. `Age.from("u8/2yr")` is `[6, 8)` whatever the ladder offers, since the
|
|
306
|
+
page states the floor (`clauses` is `["under-stride"]`), where a plain `u8` takes the rung below
|
|
307
|
+
it. So `Age.from("u8/2yr", { year: 2026 })` is born 2018 or 2019. Beside the adult word the stride
|
|
308
|
+
never opens below 18: `adult u40/10yr` is `[30, 40)`.
|
|
309
|
+
|
|
303
310
|
A value the reader cannot stand behind is returned, not thrown. An `Age` is `Validated` (above):
|
|
304
311
|
an age group under `U3` admits nobody old enough to dance, and a year of birth outside 1901 to
|
|
305
312
|
2099 is not one, so the placeholders `1000` and `1900` are refused. An invalid `Age` has no
|
package/dist/age.js
CHANGED
|
@@ -4,14 +4,17 @@ import {
|
|
|
4
4
|
|
|
5
5
|
var LEAD_ID = /^\s*(?:comp(?:etition)?\.?\s*)?\d+[a-z]*(?:[/-]\d*[a-z]*)*\s*[-:.]?\s*/i;
|
|
6
6
|
var PAREN = /\(([^)]*)\)/g;
|
|
7
|
-
var AND_OVER = /(?<![a-z0-9])(\d{1,2})\s*(?:years?\s*)?(?:&|\+|\band\b)\s*(?:over|older|up|o)(?![a-z])/i;
|
|
8
|
-
var OVER_WORD = /(?:\bover\s*|\bos\s+cionn\s*|(?<![a-z0-9])o
|
|
7
|
+
var AND_OVER = /(?<![0-9])(?<![0-9][a-z]*)(?<!(?:^|[^a-z0-9])[a-z])(\d{1,2})\s*(?:years?\s*)?(?:&|\+|\band\b)\s*(?:over|older|up|o)(?![a-z])/i;
|
|
8
|
+
var OVER_WORD = /(?:\bover\s*|\bos\s+cionn\s*|(?<![a-z0-9])o[./]?\s*)(\d{1,2})(?![a-z0-9])/i;
|
|
9
9
|
var OVER_GLUED = /(?<![a-z0-9])(\d{1,2})\s*o(?![a-z'’])/i;
|
|
10
10
|
var OVER_PLUS = /(?<![a-z0-9])(\d{1,2})\s*\+/;
|
|
11
|
-
var UNDER = /(?:\bunder\s
|
|
11
|
+
var UNDER = /(?:\bunder\s*(?:age\s*)?|\bfaoi\s*|(?<![a-z0-9])u\.?\s*)(\d{1,2})(?![0-9])(?![a-z][a-z0-9])/i;
|
|
12
|
+
var UNDER_STRIDE = /^\s*\/\s*0*([1-9]\d?)\s*yrs?(?![a-z0-9])/i;
|
|
12
13
|
var AND_UNDER = /(?<![a-z0-9])(\d{1,2})\s*(?:years?\s*)?(?:&|\/|\band\b)\s*u(?:nder)?(?![a-z])(?!\s*\d)/i;
|
|
13
14
|
var AND_UNDER_RANGE = /(?<![a-z0-9])(\d{1,2})\s*(?:&|\band\b)\s*under\s*(\d{1,2})(?![a-z0-9])/i;
|
|
14
15
|
var AND_RANGE = /(?<![a-z0-9])(?<!\b(?:under|und|over|faoi|cionn|u|o)\.?\s*)(?<!\d\s*,\s*)(?<!\(\s*)(\d{1,2})\s*(?:&|\band\b)\s*(\d{1,2})(?![a-z0-9])(?!\s*-?\s*hand)(?!\s*(?:&|\+|\/|,|\)|\band\b|\bor\b))/i;
|
|
16
|
+
var SLASH_RANGE = /(?<![a-z0-9/])(\d{1,2})\s*\/\s*(\d{1,2})(?=\s*(?:years?|yrs?|boys?|girls?|ladies|men)\b)/i;
|
|
17
|
+
var AGE_N = /(?<!\b(?:under|over)\s*)\bage\s*(\d{1,2})(?![a-z0-9])(?!\s*-?\s*hand)/i;
|
|
15
18
|
var YEARS = /(?<![a-z0-9])(?<!\d\s*(?:&|\/|\band\b|[-\u0096–—]|\bto\b)\s*)(\d{1,2})\s*(?:years?|yrs?)(?![a-z0-9])(?!\s*(?:&|\+|\/|\band\b|\bor\b|old))/i;
|
|
16
19
|
var RANGE_DASH = String.raw`(?:\u00c2?[-\u0096–—]|\bto\b)`;
|
|
17
20
|
var RANGE = new RegExp(String.raw`(?<![0-9])(?<![0-9][a-z]*)(?<!(?:^|[^a-z0-9])[a-z])(?:u\s*)?(\d{1,2})\s*${RANGE_DASH}\s*(\d{1,2})(?![a-z0-9])`, "i");
|
|
@@ -28,6 +31,8 @@ function at(title, offset, start, end, token) {
|
|
|
28
31
|
return { token, span: { start: a, end: b, text: title.slice(a, b) } };
|
|
29
32
|
}
|
|
30
33
|
function inFence(a, b) {
|
|
34
|
+
if (a.startsWith("0") || b.startsWith("0"))
|
|
35
|
+
return false;
|
|
31
36
|
const lo = Number(a);
|
|
32
37
|
const hi = Number(b);
|
|
33
38
|
return lo >= TITLE_RANGE_MIN && hi <= TITLE_RANGE_MAX && lo < hi;
|
|
@@ -44,6 +49,9 @@ function readAnchored(title, s, offset, aside = false) {
|
|
|
44
49
|
const j = aside ? null : AND_RANGE.exec(s);
|
|
45
50
|
if (j?.[1] !== undefined && j[2] !== undefined && inFence(j[1], j[2]))
|
|
46
51
|
return at(title, offset, j.index, j.index + j[0].length, `${Number(j[1])}-${Number(j[2])}`);
|
|
52
|
+
const sl = aside ? null : SLASH_RANGE.exec(s);
|
|
53
|
+
if (sl?.[1] !== undefined && sl[2] !== undefined && inFence(sl[1], sl[2]) && Number(sl[2]) === Number(sl[1]) + 1)
|
|
54
|
+
return at(title, offset, sl.index, sl.index + sl[0].length, `${Number(sl[1])}-${Number(sl[2])}`);
|
|
47
55
|
const l = LEAD_RANGE.exec(s);
|
|
48
56
|
if (l?.[1] !== undefined && l[2] !== undefined && inFence(l[1], l[2])) {
|
|
49
57
|
const lead = l[0].length - l[0].trimStart().length;
|
|
@@ -58,9 +66,14 @@ function readAnchored(title, s, offset, aside = false) {
|
|
|
58
66
|
if (au?.[1] !== undefined)
|
|
59
67
|
return at(title, offset, au.index, au.index + au[0].length, `u${Number(au[1]) + 1}`);
|
|
60
68
|
const m = UNDER.exec(s);
|
|
61
|
-
if (m?.[1] !== undefined)
|
|
62
|
-
|
|
63
|
-
|
|
69
|
+
if (m?.[1] !== undefined) {
|
|
70
|
+
const end = m.index + m[0].length;
|
|
71
|
+
const k = UNDER_STRIDE.exec(s.slice(end));
|
|
72
|
+
if (k?.[1] !== undefined)
|
|
73
|
+
return at(title, offset, m.index, end + k[0].length, `u${Number(m[1])}/${Number(k[1])}yr`);
|
|
74
|
+
return at(title, offset, m.index, end, `u${Number(m[1])}`);
|
|
75
|
+
}
|
|
76
|
+
const y = YEARS.exec(s) ?? AGE_N.exec(s);
|
|
64
77
|
if (y?.[1] !== undefined)
|
|
65
78
|
return at(title, offset, y.index, y.index + y[0].length, `u${Number(y[1]) + 1}`);
|
|
66
79
|
const p = OVER_PLUS.exec(s);
|
|
@@ -111,15 +124,17 @@ function ageTitleToken(title) {
|
|
|
111
124
|
return adultAside !== null && (words.token === "" || words.token === "adult") ? adultAside : adultOverUnder(title, s, lead, words);
|
|
112
125
|
}
|
|
113
126
|
var ADULT_UNDER_MIN = 18;
|
|
127
|
+
var SENIOR_ADULT_OVER = /\bsenior\s+adult\b/i;
|
|
114
128
|
function adultBeside(band) {
|
|
115
129
|
const b = band.trim().toLowerCase();
|
|
116
130
|
if (b === "")
|
|
117
131
|
return "adult";
|
|
118
|
-
const
|
|
132
|
+
const u = /^u(\d+)(\/\d+yr)?$/.exec(b);
|
|
133
|
+
const n = u?.[1];
|
|
119
134
|
if (n !== undefined) {
|
|
120
135
|
if (Number(n) < ADULT_UNDER_MIN)
|
|
121
136
|
return;
|
|
122
|
-
return Number(n) > ADULT_UNDER_MIN ? `adult u${Number(n)}` : "adult";
|
|
137
|
+
return Number(n) > ADULT_UNDER_MIN ? `adult u${Number(n)}${u?.[2] ?? ""}` : "adult";
|
|
123
138
|
}
|
|
124
139
|
const floor = /^o(\d+)$/.exec(b)?.[1] ?? /^(\d+)-\d+$/.exec(b)?.[1];
|
|
125
140
|
if (floor === undefined)
|
|
@@ -132,10 +147,12 @@ function adultOverUnder(title, s, lead, t) {
|
|
|
132
147
|
const a = ADULT.exec(s);
|
|
133
148
|
if (a === null)
|
|
134
149
|
return t;
|
|
150
|
+
if (/^o\d+$/.test(t.token) && SENIOR_ADULT_OVER.test(s))
|
|
151
|
+
return t;
|
|
135
152
|
const token = adultBeside(t.token);
|
|
136
153
|
if (token === undefined || token === t.token)
|
|
137
154
|
return t;
|
|
138
|
-
if (/^u\d
|
|
155
|
+
if (/^u\d+(?:\/\d+yr)?$/.test(t.token))
|
|
139
156
|
return at(title, lead, a.index, a.index + a[0].length, token);
|
|
140
157
|
return { token, span: t.span };
|
|
141
158
|
}
|
|
@@ -153,12 +170,12 @@ var YOB_RANGE = Object.freeze({ first: 1901, last: 2099 });
|
|
|
153
170
|
var DANCE_UP_YEARS = 1;
|
|
154
171
|
var ageOnJanuary1 = (year, born) => year - born - 1;
|
|
155
172
|
var yearsSinceBirth = (year, born) => year - born;
|
|
156
|
-
var UNDER2 = /^(?:u|under\s*)(\d+)
|
|
173
|
+
var UNDER2 = /^(?:u|under\s*)(\d+)(?:\/([1-9]\d*)yr)?$/i;
|
|
157
174
|
var OVER = /^(?:o|over\s*)(\d+)$/i;
|
|
158
175
|
var AND_OVER2 = /^(\d+)\s*(?:&|and\b)\s*(?:over|o)$/i;
|
|
159
176
|
var RANGE2 = /^u?(\d+)\s*[-–]\s*(\d+)$/i;
|
|
160
177
|
var ADULT_WORD = /^(?:adults?|ad|advanced|masters?)$/i;
|
|
161
|
-
var ADULT_UNDER = /^(?:adults?|ad)[\s-]*(?:u|under\s*)(\d+)
|
|
178
|
+
var ADULT_UNDER = /^(?:adults?|ad)[\s-]*(?:u|under\s*)(\d+)(?:\/([1-9]\d*)yr)?$/i;
|
|
162
179
|
var ADULT_BAND = /^(?:adults?|ad)[\s-]+(\S.*)$/i;
|
|
163
180
|
var SENIOR_WORD = /^seniors?$/i;
|
|
164
181
|
var NO_LADDER = Object.freeze({ caps: [], overs: [], ranges: [] });
|
|
@@ -213,19 +230,28 @@ function readRange(a, b, ladder) {
|
|
|
213
230
|
parts: [a, b]
|
|
214
231
|
};
|
|
215
232
|
}
|
|
233
|
+
function strideOf(k) {
|
|
234
|
+
if (k === undefined)
|
|
235
|
+
return null;
|
|
236
|
+
const n = Number(k);
|
|
237
|
+
return Number.isInteger(n) && n >= 1 ? n : null;
|
|
238
|
+
}
|
|
216
239
|
function read(token, ladder, top) {
|
|
217
240
|
const r = RANGE2.exec(token);
|
|
218
241
|
if (r !== null)
|
|
219
242
|
return readRange(Number(r[1]), Number(r[2]), ladder);
|
|
220
243
|
const au = ADULT_UNDER.exec(token);
|
|
221
|
-
if (au !== null && Number(au[1]) > ADULT_FLOOR)
|
|
244
|
+
if (au !== null && Number(au[1]) > ADULT_FLOOR) {
|
|
245
|
+
const k = strideOf(au[2]);
|
|
246
|
+
const hi = Number(au[1]);
|
|
222
247
|
return {
|
|
223
248
|
kind: "adult",
|
|
224
|
-
interval: { lo: ADULT_FLOOR, hi
|
|
249
|
+
interval: { lo: k === null ? ADULT_FLOOR : Math.max(ADULT_FLOOR, hi - k), hi },
|
|
225
250
|
refusal: null,
|
|
226
|
-
clauses: ["adult-under-ceiling"],
|
|
227
|
-
parts: [
|
|
251
|
+
clauses: k === null ? ["adult-under-ceiling"] : ["adult-under-ceiling", "under-stride"],
|
|
252
|
+
parts: k === null ? [hi] : [hi, k]
|
|
228
253
|
};
|
|
254
|
+
}
|
|
229
255
|
const ab = au === null ? ADULT_BAND.exec(token) : null;
|
|
230
256
|
if (ab !== null) {
|
|
231
257
|
const inner = read(ab[1].trim(), { ...ladder, adult: true }, top);
|
|
@@ -253,6 +279,15 @@ function read(token, ladder, top) {
|
|
|
253
279
|
const u = UNDER2.exec(token);
|
|
254
280
|
if (u !== null) {
|
|
255
281
|
const n = Number(u[1]);
|
|
282
|
+
const k = strideOf(u[2]);
|
|
283
|
+
if (k !== null)
|
|
284
|
+
return {
|
|
285
|
+
kind: "under",
|
|
286
|
+
interval: { lo: Math.max(YOUNGEST_FLOOR, n - k), hi: n },
|
|
287
|
+
refusal: null,
|
|
288
|
+
clauses: ["under-stride"],
|
|
289
|
+
parts: [n, k]
|
|
290
|
+
};
|
|
256
291
|
const below = maxWhere(ladder.caps, (c) => c < n);
|
|
257
292
|
return {
|
|
258
293
|
kind: "under",
|
|
@@ -357,7 +392,7 @@ function fromPrint(print, context = {}) {
|
|
|
357
392
|
throw new Error(`Age.from(${JSON.stringify(print)}): birthYears needs a competition year`);
|
|
358
393
|
return birthYearsOfInterval(iv, at);
|
|
359
394
|
},
|
|
360
|
-
floorObserved: () => reading.kind !== "under" && reading.kind !== "range" || iv === null ? null : reading.clauses.includes("under-floored-on-rung") || reading.clauses.includes("range-adult-floor")
|
|
395
|
+
floorObserved: () => reading.kind !== "under" && reading.kind !== "range" || iv === null ? null : reading.clauses.includes("under-floored-on-rung") || reading.clauses.includes("range-adult-floor") || reading.clauses.includes("under-stride")
|
|
361
396
|
});
|
|
362
397
|
}
|
|
363
398
|
function fromYOB(from, to = from, context = {}) {
|
|
@@ -412,6 +447,8 @@ function sourceOf(r) {
|
|
|
412
447
|
switch (r.kind) {
|
|
413
448
|
case "range":
|
|
414
449
|
case "under":
|
|
450
|
+
if (r.clauses.includes("under-stride"))
|
|
451
|
+
return "printed-band";
|
|
415
452
|
return iv.lo > YOUNGEST_FLOOR ? "sibling-narrowed" : "printed-band";
|
|
416
453
|
case "over":
|
|
417
454
|
return iv.hi === Number.POSITIVE_INFINITY ? "printed-band" : "sibling-narrowed";
|
|
@@ -95,7 +95,7 @@ var PLACE_NODES = [
|
|
|
95
95
|
name: "Cúige Chonnacht / Connacht",
|
|
96
96
|
geo: "IRL",
|
|
97
97
|
admin: "world",
|
|
98
|
-
prints: ["chonnacht", "connacht", "connaght", "connaught", "cuige chonnacht"],
|
|
98
|
+
prints: ["chonnacht", "connacht", "connaght", "connaught", "cuige chonnacht", "cuige connacht"],
|
|
99
99
|
codes: ["CONNACHT"],
|
|
100
100
|
oireachtas: "CONNACHT"
|
|
101
101
|
},
|
|
@@ -381,7 +381,7 @@ var PLACE_NODES = [
|
|
|
381
381
|
name: "Cúige Uladh / Ulster",
|
|
382
382
|
geo: "IRL",
|
|
383
383
|
admin: "world",
|
|
384
|
-
prints: ["cuige uladh", "cuige uldah", "uladh", "ulster"],
|
|
384
|
+
prints: ["cuige uladh", "cuige uldah", "cuige ulster", "uladh", "ulster"],
|
|
385
385
|
codes: ["ULSTER"],
|
|
386
386
|
oireachtas: "ULSTER"
|
|
387
387
|
},
|
|
@@ -3575,6 +3575,276 @@ var PLACE_NODES = [
|
|
|
3575
3575
|
prints: ["warwickshire"],
|
|
3576
3576
|
codes: ["GB-WAR", "GBR-WAR"]
|
|
3577
3577
|
},
|
|
3578
|
+
{
|
|
3579
|
+
id: "GBR-BDF",
|
|
3580
|
+
kind: "subdivision",
|
|
3581
|
+
name: "Bedfordshire",
|
|
3582
|
+
geo: "GBR-ENG",
|
|
3583
|
+
admin: null,
|
|
3584
|
+
prints: ["bedfordshire"],
|
|
3585
|
+
codes: ["GB-BDF", "GBR-BDF"],
|
|
3586
|
+
listedCutsOnly: true
|
|
3587
|
+
},
|
|
3588
|
+
{
|
|
3589
|
+
id: "GBR-BKM",
|
|
3590
|
+
kind: "subdivision",
|
|
3591
|
+
name: "Buckinghamshire",
|
|
3592
|
+
geo: "GBR-ENG",
|
|
3593
|
+
admin: null,
|
|
3594
|
+
prints: ["buckinghamshire"],
|
|
3595
|
+
codes: ["GB-BKM", "GBR-BKM"],
|
|
3596
|
+
listedCutsOnly: true
|
|
3597
|
+
},
|
|
3598
|
+
{
|
|
3599
|
+
id: "GBR-BRK",
|
|
3600
|
+
kind: "subdivision",
|
|
3601
|
+
name: "Berkshire",
|
|
3602
|
+
geo: "GBR-ENG",
|
|
3603
|
+
admin: null,
|
|
3604
|
+
prints: ["berkshire"],
|
|
3605
|
+
codes: [],
|
|
3606
|
+
listedCutsOnly: true
|
|
3607
|
+
},
|
|
3608
|
+
{
|
|
3609
|
+
id: "GBR-CAM",
|
|
3610
|
+
kind: "subdivision",
|
|
3611
|
+
name: "Cambridgeshire",
|
|
3612
|
+
geo: "GBR-ENG",
|
|
3613
|
+
admin: null,
|
|
3614
|
+
prints: ["cambridgeshire"],
|
|
3615
|
+
codes: ["GB-CAM", "GBR-CAM"],
|
|
3616
|
+
listedCutsOnly: true
|
|
3617
|
+
},
|
|
3618
|
+
{
|
|
3619
|
+
id: "GBR-DUR",
|
|
3620
|
+
kind: "subdivision",
|
|
3621
|
+
name: "County Durham",
|
|
3622
|
+
geo: "GBR-ENG",
|
|
3623
|
+
admin: null,
|
|
3624
|
+
prints: ["co durham", "county durham", "durham"],
|
|
3625
|
+
codes: ["GB-DUR", "GBR-DUR"],
|
|
3626
|
+
listedCutsOnly: true
|
|
3627
|
+
},
|
|
3628
|
+
{
|
|
3629
|
+
id: "GBR-ERY",
|
|
3630
|
+
kind: "subdivision",
|
|
3631
|
+
name: "East Riding of Yorkshire",
|
|
3632
|
+
geo: "GBR-ENG",
|
|
3633
|
+
admin: null,
|
|
3634
|
+
prints: ["east riding", "east riding of yorkshire", "east riding yorkshire"],
|
|
3635
|
+
codes: ["GB-ERY", "GBR-ERY"],
|
|
3636
|
+
listedCutsOnly: true
|
|
3637
|
+
},
|
|
3638
|
+
{
|
|
3639
|
+
id: "GBR-ESX",
|
|
3640
|
+
kind: "subdivision",
|
|
3641
|
+
name: "East Sussex",
|
|
3642
|
+
geo: "GBR-ENG",
|
|
3643
|
+
admin: null,
|
|
3644
|
+
prints: ["east sussex"],
|
|
3645
|
+
codes: ["GB-ESX", "GBR-ESX"],
|
|
3646
|
+
listedCutsOnly: true
|
|
3647
|
+
},
|
|
3648
|
+
{
|
|
3649
|
+
id: "GBR-GTL",
|
|
3650
|
+
kind: "subdivision",
|
|
3651
|
+
name: "Greater London",
|
|
3652
|
+
geo: "GBR-ENG",
|
|
3653
|
+
admin: null,
|
|
3654
|
+
prints: ["greater london"],
|
|
3655
|
+
codes: [],
|
|
3656
|
+
listedCutsOnly: true
|
|
3657
|
+
},
|
|
3658
|
+
{
|
|
3659
|
+
id: "GBR-GTM",
|
|
3660
|
+
kind: "subdivision",
|
|
3661
|
+
name: "Greater Manchester",
|
|
3662
|
+
geo: "GBR-ENG",
|
|
3663
|
+
admin: null,
|
|
3664
|
+
prints: ["greater manchester"],
|
|
3665
|
+
codes: [],
|
|
3666
|
+
listedCutsOnly: true
|
|
3667
|
+
},
|
|
3668
|
+
{
|
|
3669
|
+
id: "GBR-HAM",
|
|
3670
|
+
kind: "subdivision",
|
|
3671
|
+
name: "Hampshire",
|
|
3672
|
+
geo: "GBR-ENG",
|
|
3673
|
+
admin: null,
|
|
3674
|
+
prints: ["hampshire"],
|
|
3675
|
+
codes: ["GB-HAM", "GBR-HAM"],
|
|
3676
|
+
listedCutsOnly: true
|
|
3677
|
+
},
|
|
3678
|
+
{
|
|
3679
|
+
id: "GBR-IOW",
|
|
3680
|
+
kind: "subdivision",
|
|
3681
|
+
name: "Isle of Wight",
|
|
3682
|
+
geo: "GBR-ENG",
|
|
3683
|
+
admin: null,
|
|
3684
|
+
prints: ["isle of wight"],
|
|
3685
|
+
codes: ["GB-IOW", "GBR-IOW"],
|
|
3686
|
+
listedCutsOnly: true
|
|
3687
|
+
},
|
|
3688
|
+
{
|
|
3689
|
+
id: "GBR-KEN",
|
|
3690
|
+
kind: "subdivision",
|
|
3691
|
+
name: "Kent",
|
|
3692
|
+
geo: "GBR-ENG",
|
|
3693
|
+
admin: null,
|
|
3694
|
+
prints: ["kent"],
|
|
3695
|
+
codes: ["GB-KEN", "GBR-KEN"],
|
|
3696
|
+
listedCutsOnly: true
|
|
3697
|
+
},
|
|
3698
|
+
{
|
|
3699
|
+
id: "GBR-LIN",
|
|
3700
|
+
kind: "subdivision",
|
|
3701
|
+
name: "Lincolnshire",
|
|
3702
|
+
geo: "GBR-ENG",
|
|
3703
|
+
admin: null,
|
|
3704
|
+
prints: ["lincolnshire"],
|
|
3705
|
+
codes: ["GB-LIN", "GBR-LIN"],
|
|
3706
|
+
listedCutsOnly: true
|
|
3707
|
+
},
|
|
3708
|
+
{
|
|
3709
|
+
id: "GBR-NBL",
|
|
3710
|
+
kind: "subdivision",
|
|
3711
|
+
name: "Northumberland",
|
|
3712
|
+
geo: "GBR-ENG",
|
|
3713
|
+
admin: null,
|
|
3714
|
+
prints: ["northumberland"],
|
|
3715
|
+
codes: ["GB-NBL", "GBR-NBL"],
|
|
3716
|
+
listedCutsOnly: true
|
|
3717
|
+
},
|
|
3718
|
+
{
|
|
3719
|
+
id: "GBR-NTH",
|
|
3720
|
+
kind: "subdivision",
|
|
3721
|
+
name: "Northamptonshire",
|
|
3722
|
+
geo: "GBR-ENG",
|
|
3723
|
+
admin: null,
|
|
3724
|
+
prints: ["northamptonshire", "northants"],
|
|
3725
|
+
codes: ["GB-NTH", "GBR-NTH"],
|
|
3726
|
+
listedCutsOnly: true
|
|
3727
|
+
},
|
|
3728
|
+
{
|
|
3729
|
+
id: "GBR-NTT",
|
|
3730
|
+
kind: "subdivision",
|
|
3731
|
+
name: "Nottinghamshire",
|
|
3732
|
+
geo: "GBR-ENG",
|
|
3733
|
+
admin: null,
|
|
3734
|
+
prints: ["nottinghamshire"],
|
|
3735
|
+
codes: ["GB-NTT", "GBR-NTT"],
|
|
3736
|
+
listedCutsOnly: true
|
|
3737
|
+
},
|
|
3738
|
+
{
|
|
3739
|
+
id: "GBR-NYK",
|
|
3740
|
+
kind: "subdivision",
|
|
3741
|
+
name: "North Yorkshire",
|
|
3742
|
+
geo: "GBR-ENG",
|
|
3743
|
+
admin: null,
|
|
3744
|
+
prints: ["n yorkshire", "north yorkshire"],
|
|
3745
|
+
codes: ["GB-NYK", "GBR-NYK"],
|
|
3746
|
+
listedCutsOnly: true
|
|
3747
|
+
},
|
|
3748
|
+
{
|
|
3749
|
+
id: "GBR-OXF",
|
|
3750
|
+
kind: "subdivision",
|
|
3751
|
+
name: "Oxfordshire",
|
|
3752
|
+
geo: "GBR-ENG",
|
|
3753
|
+
admin: null,
|
|
3754
|
+
prints: ["oxfordshire"],
|
|
3755
|
+
codes: ["GB-OXF", "GBR-OXF"],
|
|
3756
|
+
listedCutsOnly: true
|
|
3757
|
+
},
|
|
3758
|
+
{
|
|
3759
|
+
id: "GBR-RUT",
|
|
3760
|
+
kind: "subdivision",
|
|
3761
|
+
name: "Rutland",
|
|
3762
|
+
geo: "GBR-ENG",
|
|
3763
|
+
admin: null,
|
|
3764
|
+
prints: ["rutland"],
|
|
3765
|
+
codes: ["GB-RUT", "GBR-RUT"],
|
|
3766
|
+
listedCutsOnly: true
|
|
3767
|
+
},
|
|
3768
|
+
{
|
|
3769
|
+
id: "GBR-SOM",
|
|
3770
|
+
kind: "subdivision",
|
|
3771
|
+
name: "Somerset",
|
|
3772
|
+
geo: "GBR-ENG",
|
|
3773
|
+
admin: null,
|
|
3774
|
+
prints: ["somerset"],
|
|
3775
|
+
codes: ["GB-SOM", "GBR-SOM"],
|
|
3776
|
+
listedCutsOnly: true
|
|
3777
|
+
},
|
|
3778
|
+
{
|
|
3779
|
+
id: "GBR-SYK",
|
|
3780
|
+
kind: "subdivision",
|
|
3781
|
+
name: "South Yorkshire",
|
|
3782
|
+
geo: "GBR-ENG",
|
|
3783
|
+
admin: null,
|
|
3784
|
+
prints: ["s yorkshire", "south yorks", "south yorkshire"],
|
|
3785
|
+
codes: [],
|
|
3786
|
+
listedCutsOnly: true
|
|
3787
|
+
},
|
|
3788
|
+
{
|
|
3789
|
+
id: "GBR-TWR",
|
|
3790
|
+
kind: "subdivision",
|
|
3791
|
+
name: "Tyne and Wear",
|
|
3792
|
+
geo: "GBR-ENG",
|
|
3793
|
+
admin: null,
|
|
3794
|
+
prints: ["tyne and wear", "tyne wear"],
|
|
3795
|
+
codes: [],
|
|
3796
|
+
listedCutsOnly: true
|
|
3797
|
+
},
|
|
3798
|
+
{
|
|
3799
|
+
id: "GBR-WIL",
|
|
3800
|
+
kind: "subdivision",
|
|
3801
|
+
name: "Wiltshire",
|
|
3802
|
+
geo: "GBR-ENG",
|
|
3803
|
+
admin: null,
|
|
3804
|
+
prints: ["wiltshire"],
|
|
3805
|
+
codes: ["GB-WIL", "GBR-WIL"],
|
|
3806
|
+
listedCutsOnly: true
|
|
3807
|
+
},
|
|
3808
|
+
{
|
|
3809
|
+
id: "GBR-WMD",
|
|
3810
|
+
kind: "subdivision",
|
|
3811
|
+
name: "West Midlands",
|
|
3812
|
+
geo: "GBR-ENG",
|
|
3813
|
+
admin: null,
|
|
3814
|
+
prints: ["w midlands", "west midlands"],
|
|
3815
|
+
codes: [],
|
|
3816
|
+
listedCutsOnly: true
|
|
3817
|
+
},
|
|
3818
|
+
{
|
|
3819
|
+
id: "GBR-WOR",
|
|
3820
|
+
kind: "subdivision",
|
|
3821
|
+
name: "Worcestershire",
|
|
3822
|
+
geo: "GBR-ENG",
|
|
3823
|
+
admin: null,
|
|
3824
|
+
prints: ["worcestershire"],
|
|
3825
|
+
codes: ["GB-WOR", "GBR-WOR"],
|
|
3826
|
+
listedCutsOnly: true
|
|
3827
|
+
},
|
|
3828
|
+
{
|
|
3829
|
+
id: "GBR-WSX",
|
|
3830
|
+
kind: "subdivision",
|
|
3831
|
+
name: "West Sussex",
|
|
3832
|
+
geo: "GBR-ENG",
|
|
3833
|
+
admin: null,
|
|
3834
|
+
prints: ["west sussex"],
|
|
3835
|
+
codes: ["GB-WSX", "GBR-WSX"],
|
|
3836
|
+
listedCutsOnly: true
|
|
3837
|
+
},
|
|
3838
|
+
{
|
|
3839
|
+
id: "GBR-WYK",
|
|
3840
|
+
kind: "subdivision",
|
|
3841
|
+
name: "West Yorkshire",
|
|
3842
|
+
geo: "GBR-ENG",
|
|
3843
|
+
admin: null,
|
|
3844
|
+
prints: ["w yorkshire", "west yorkshire"],
|
|
3845
|
+
codes: [],
|
|
3846
|
+
listedCutsOnly: true
|
|
3847
|
+
},
|
|
3578
3848
|
{
|
|
3579
3849
|
id: "GBR-NIR",
|
|
3580
3850
|
kind: "subdivision",
|
|
@@ -6654,29 +6924,49 @@ var PLACE_NODES = [
|
|
|
6654
6924
|
];
|
|
6655
6925
|
|
|
6656
6926
|
var QUALIFIER_DELIMITER = /[,;:()[\]/–—-]/;
|
|
6657
|
-
var
|
|
6658
|
-
|
|
6659
|
-
|
|
6660
|
-
|
|
6661
|
-
|
|
6662
|
-
|
|
6663
|
-
|
|
6664
|
-
|
|
6665
|
-
|
|
6666
|
-
|
|
6667
|
-
|
|
6668
|
-
|
|
6669
|
-
|
|
6670
|
-
|
|
6671
|
-
|
|
6672
|
-
|
|
6673
|
-
|
|
6674
|
-
|
|
6675
|
-
|
|
6676
|
-
|
|
6677
|
-
|
|
6678
|
-
|
|
6679
|
-
|
|
6927
|
+
var SHORT_TOKEN_BARS = [
|
|
6928
|
+
{
|
|
6929
|
+
spelling: "de",
|
|
6930
|
+
place: true,
|
|
6931
|
+
name: true,
|
|
6932
|
+
why: "name particle: `De <Surname>`, and Spanish `de <Place>`"
|
|
6933
|
+
},
|
|
6934
|
+
{ spelling: "ni", place: true, name: true, why: "Irish patronymic particle: `Ní <Surname>`" },
|
|
6935
|
+
{ spelling: "ui", place: false, name: true, why: "Irish patronymic particle: `Uí <Surname>`" },
|
|
6936
|
+
{ spelling: "mo", place: true, name: true, why: "Irish possessive: `Mo <Word>`" },
|
|
6937
|
+
{ spelling: "na", place: true, name: true, why: "Irish article: `Rince na <Word>`" },
|
|
6938
|
+
{ spelling: "an", place: false, name: true, why: "Irish article: `<Word> an Rince`" },
|
|
6939
|
+
{
|
|
6940
|
+
spelling: "in",
|
|
6941
|
+
place: true,
|
|
6942
|
+
name: true,
|
|
6943
|
+
why: "Irish preposition: `<Word> In <Word>`, and `Inc` truncated to `In`"
|
|
6944
|
+
},
|
|
6945
|
+
{
|
|
6946
|
+
spelling: "co",
|
|
6947
|
+
place: true,
|
|
6948
|
+
name: true,
|
|
6949
|
+
why: "Company: `<Surname> & Co.`. Bracketed `(US-CO)` is still Colorado"
|
|
6950
|
+
},
|
|
6951
|
+
{
|
|
6952
|
+
spelling: "id",
|
|
6953
|
+
place: true,
|
|
6954
|
+
name: true,
|
|
6955
|
+
why: "Irish Dance: `<Surname> School of ID`, and `ID de <Place>` keys the place, as `Irish Dancing de <Place>` does"
|
|
6956
|
+
},
|
|
6957
|
+
{ spelling: "sd", place: true, name: true, why: "School of Dance: `<Surname> SD`" },
|
|
6958
|
+
{
|
|
6959
|
+
spelling: "da",
|
|
6960
|
+
place: false,
|
|
6961
|
+
name: true,
|
|
6962
|
+
why: "`Dance` truncated: `<Name> Academy of Irish Da` keys the name"
|
|
6963
|
+
}
|
|
6964
|
+
];
|
|
6965
|
+
function barred(flag) {
|
|
6966
|
+
return new Map(SHORT_TOKEN_BARS.filter((row) => row[flag]).map((row) => [row.spelling, row.why]));
|
|
6967
|
+
}
|
|
6968
|
+
var NEVER_PLACE = barred("place");
|
|
6969
|
+
var NEVER_NAME = barred("name");
|
|
6680
6970
|
var GENERIC_TLD = "com|net|org|edu|gov|mil|int|info|biz";
|
|
6681
6971
|
var WEB_SPAN = new RegExp([
|
|
6682
6972
|
"[A-Za-z][A-Za-z0-9+.-]*://\\S+",
|
|
@@ -7309,6 +7599,10 @@ function createPlaceReader2(options = {}) {
|
|
|
7309
7599
|
return false;
|
|
7310
7600
|
if (a.kind === b.kind)
|
|
7311
7601
|
return true;
|
|
7602
|
+
const sub = a.kind === "subdivision" ? a : b.kind === "subdivision" ? b : undefined;
|
|
7603
|
+
const town = a.kind === "city" ? a : b.kind === "city" ? b : undefined;
|
|
7604
|
+
if (sub !== undefined && town !== undefined && town.geo !== null && town.geo === sub.geo)
|
|
7605
|
+
return true;
|
|
7312
7606
|
const ca = countryOf(a);
|
|
7313
7607
|
const cb = countryOf(b);
|
|
7314
7608
|
return ca === undefined || cb === undefined || ca.id !== cb.id;
|
|
@@ -7343,7 +7637,9 @@ function createPlaceReader2(options = {}) {
|
|
|
7343
7637
|
break;
|
|
7344
7638
|
}
|
|
7345
7639
|
if (!plural) {
|
|
7346
|
-
const
|
|
7640
|
+
const tail = reads[reads.length - 1]?.heads ?? [];
|
|
7641
|
+
const closes = (m) => m.kind === "subdivision" && tail.length === 1 && tail[0]?.id === m.id && members.length > 2 && members.every((o) => onTheMap(m, o));
|
|
7642
|
+
const spent = members.filter((m) => m.kind === "country" && members.some((o) => o.id !== m.id && isAncestor(m, o)) || closes(m));
|
|
7347
7643
|
const inner = members.filter((m) => !spent.includes(m));
|
|
7348
7644
|
let apart = inner.length > 1 && spent.length > 0;
|
|
7349
7645
|
for (let a = 0;a < inner.length && apart; a++)
|
|
@@ -7515,6 +7811,19 @@ function createPlaceReader2(options = {}) {
|
|
|
7515
7811
|
});
|
|
7516
7812
|
return abroad ? right : undefined;
|
|
7517
7813
|
}
|
|
7814
|
+
function townInCounty(left, right) {
|
|
7815
|
+
if (left.length === 0 || right.length === 0)
|
|
7816
|
+
return;
|
|
7817
|
+
if (!left.every((l) => l.kind === "city") || !right.every((r) => r.kind === "subdivision"))
|
|
7818
|
+
return;
|
|
7819
|
+
if (left.some((l) => right.some((r) => relates(l, r))))
|
|
7820
|
+
return;
|
|
7821
|
+
const kept = left.filter((l) => {
|
|
7822
|
+
const parent = l.geo === null ? undefined : idx().byId.get(l.geo);
|
|
7823
|
+
return parent !== undefined && right.some((r) => r.id !== parent.id && onTheMap(parent, r));
|
|
7824
|
+
});
|
|
7825
|
+
return kept.length === 0 ? undefined : kept;
|
|
7826
|
+
}
|
|
7518
7827
|
function read(print, declared = false, smushed = true) {
|
|
7519
7828
|
const core = unbracket(repair(print));
|
|
7520
7829
|
if (fold(core) === "")
|
|
@@ -7577,13 +7886,14 @@ function createPlaceReader2(options = {}) {
|
|
|
7577
7886
|
};
|
|
7578
7887
|
}
|
|
7579
7888
|
const qualified = (k) => k === "comma" || k === "space";
|
|
7889
|
+
const listed = (k) => k === "amp" || k === "and" || k === "slash";
|
|
7580
7890
|
const settled = reads.map((r, n) => {
|
|
7581
7891
|
const prev = reads[n - 1];
|
|
7582
7892
|
if (prev === undefined || !qualified(before[n]) || r.truncated)
|
|
7583
7893
|
return;
|
|
7584
7894
|
if (n - 1 > 0 && (qualified(before[n - 1]) || !qualified(before[n - 2])))
|
|
7585
7895
|
return;
|
|
7586
|
-
return qualifierAlone(prev.heads, r.heads);
|
|
7896
|
+
return qualifierAlone(prev.heads, r.heads) ?? (prev.truncated || before[n] !== "comma" || listed(before[n + 1]) ? undefined : townInCounty(prev.heads, r.heads));
|
|
7587
7897
|
});
|
|
7588
7898
|
settled.forEach((heads, n) => {
|
|
7589
7899
|
if (heads === undefined)
|
|
@@ -7841,8 +8151,41 @@ function createPlaceReader2(options = {}) {
|
|
|
7841
8151
|
const base = hit ?? built(print, declared, key);
|
|
7842
8152
|
if (hit !== undefined)
|
|
7843
8153
|
hits++;
|
|
8154
|
+
if (declared && typeof ctx === "object" && base.arm === "unread" && base.refusal === null) {
|
|
8155
|
+
const q = unheldQualifier(print, ctx);
|
|
8156
|
+
if (q !== undefined)
|
|
8157
|
+
return q.refine(ctx);
|
|
8158
|
+
}
|
|
7844
8159
|
return ctx === undefined ? base : base.refine(ctx);
|
|
7845
8160
|
}
|
|
8161
|
+
function unheldQualifier(print, ctx) {
|
|
8162
|
+
const within = [ctx.country, ctx.near].filter((w) => w !== undefined && w.trim() !== "").flatMap((w) => headsOf(w));
|
|
8163
|
+
if (within.length === 0)
|
|
8164
|
+
return;
|
|
8165
|
+
const core = unbracket(repair(print));
|
|
8166
|
+
const pieces = core.split(SEP);
|
|
8167
|
+
for (let k = 0;k < pieces.length; k += 2)
|
|
8168
|
+
if (pieces[k] === "")
|
|
8169
|
+
return;
|
|
8170
|
+
let at = -1;
|
|
8171
|
+
for (let k = pieces.length - 2;k >= 1 && at === -1; k -= 2)
|
|
8172
|
+
if (kindOf(pieces[k]) === "comma")
|
|
8173
|
+
at = k;
|
|
8174
|
+
if (at === -1)
|
|
8175
|
+
return;
|
|
8176
|
+
const tail = read(pieces.slice(at + 1).join(""), true);
|
|
8177
|
+
if (tail.heads.length > 0 || tail.refusal !== null)
|
|
8178
|
+
return;
|
|
8179
|
+
const town = read(pieces.slice(0, at).join(""), true);
|
|
8180
|
+
if (town.refusal !== null || town.truncated || town.members !== undefined)
|
|
8181
|
+
return;
|
|
8182
|
+
if (town.heads.length === 0 || !town.heads.every((n) => n.kind === "city"))
|
|
8183
|
+
return;
|
|
8184
|
+
const kept = town.heads.filter((h) => within.some((w) => isAncestor(w, h)));
|
|
8185
|
+
if (kept.length === 0)
|
|
8186
|
+
return;
|
|
8187
|
+
return build(print, chainsFor(kept), { ...town, heads: kept }, []);
|
|
8188
|
+
}
|
|
7846
8189
|
function heading(print, ctx) {
|
|
7847
8190
|
const held = idx().byHeading.get(fold(repair(print)));
|
|
7848
8191
|
if (held === undefined)
|
package/dist/person.js
CHANGED
|
@@ -106,8 +106,8 @@ class RoleRefusedName {
|
|
|
106
106
|
return true;
|
|
107
107
|
}
|
|
108
108
|
}
|
|
109
|
-
function roleName(role, print, order) {
|
|
110
|
-
const read = personName(print, order);
|
|
109
|
+
function roleName(role, print, order, factory) {
|
|
110
|
+
const read = factory === undefined ? personName(print, order) : factory.parse(print, order);
|
|
111
111
|
const sentinel = MATCHERS[role](print);
|
|
112
112
|
return sentinel === undefined ? read : new RoleRefusedName(read, role, sentinel);
|
|
113
113
|
}
|
|
@@ -116,7 +116,7 @@ function rolePrintsNoName(role, print) {
|
|
|
116
116
|
}
|
|
117
117
|
var dancerPrintsNoName = (print) => rolePrintsNoName("dancer", print);
|
|
118
118
|
var seatName = (print) => roleName("adjudicator", print, "given-first");
|
|
119
|
-
var dancerName = (print, order) => roleName("dancer", print, order);
|
|
119
|
+
var dancerName = (print, order, factory) => roleName("dancer", print, order, factory);
|
|
120
120
|
var teacherName = (print, order) => roleName("teacher", print, order);
|
|
121
121
|
export {
|
|
122
122
|
ADJUDICATOR_SENTINELS,
|
package/dist/place.js
CHANGED
package/dist/promotion.js
CHANGED
|
@@ -122,6 +122,12 @@ function mojibakeRead(print) {
|
|
|
122
122
|
return out.replace(/\uFFFD/gu, "?");
|
|
123
123
|
}
|
|
124
124
|
function samePromotedName(was, now) {
|
|
125
|
+
if (samePromotedNameRead(was, now))
|
|
126
|
+
return true;
|
|
127
|
+
const soft = was.replace(/\u00c3\u00ad/gu, "?").replace(/\u00ad/gu, "-");
|
|
128
|
+
return soft !== was && samePromotedNameRead(soft, now);
|
|
129
|
+
}
|
|
130
|
+
function samePromotedNameRead(was, now) {
|
|
125
131
|
const read = questionMarksRead(was, now);
|
|
126
132
|
if (read === null)
|
|
127
133
|
return false;
|
package/dist/school.js
CHANGED
|
@@ -12,7 +12,7 @@ import {
|
|
|
12
12
|
areAllPlaceTokens2,
|
|
13
13
|
placeRelation2,
|
|
14
14
|
sameReading2
|
|
15
|
-
} from "./chunks/place-
|
|
15
|
+
} from "./chunks/place-39zj2ymq.js";
|
|
16
16
|
import {
|
|
17
17
|
validity
|
|
18
18
|
} from "./chunks/place-q9kwsmzd.js";
|
|
@@ -716,7 +716,8 @@ var SCHOOL_INSTITUTION_VOCABULARY = new Map([
|
|
|
716
716
|
kind: "word",
|
|
717
717
|
position: "suffix",
|
|
718
718
|
truncatable: true,
|
|
719
|
-
glued: true
|
|
719
|
+
glued: true,
|
|
720
|
+
matchKey: true
|
|
720
721
|
}
|
|
721
722
|
],
|
|
722
723
|
[
|
|
@@ -727,7 +728,8 @@ var SCHOOL_INSTITUTION_VOCABULARY = new Map([
|
|
|
727
728
|
kind: "word",
|
|
728
729
|
position: "suffix",
|
|
729
730
|
truncatable: false,
|
|
730
|
-
glued: false
|
|
731
|
+
glued: false,
|
|
732
|
+
matchKey: false
|
|
731
733
|
}
|
|
732
734
|
],
|
|
733
735
|
[
|
|
@@ -738,7 +740,8 @@ var SCHOOL_INSTITUTION_VOCABULARY = new Map([
|
|
|
738
740
|
kind: "word",
|
|
739
741
|
position: "suffix",
|
|
740
742
|
truncatable: false,
|
|
741
|
-
glued: false
|
|
743
|
+
glued: false,
|
|
744
|
+
matchKey: false
|
|
742
745
|
}
|
|
743
746
|
],
|
|
744
747
|
[
|
|
@@ -749,7 +752,8 @@ var SCHOOL_INSTITUTION_VOCABULARY = new Map([
|
|
|
749
752
|
kind: "word",
|
|
750
753
|
position: "suffix",
|
|
751
754
|
truncatable: false,
|
|
752
|
-
glued: false
|
|
755
|
+
glued: false,
|
|
756
|
+
matchKey: false
|
|
753
757
|
}
|
|
754
758
|
],
|
|
755
759
|
[
|
|
@@ -760,7 +764,8 @@ var SCHOOL_INSTITUTION_VOCABULARY = new Map([
|
|
|
760
764
|
kind: "word",
|
|
761
765
|
position: "suffix",
|
|
762
766
|
truncatable: true,
|
|
763
|
-
glued: true
|
|
767
|
+
glued: true,
|
|
768
|
+
matchKey: true
|
|
764
769
|
}
|
|
765
770
|
],
|
|
766
771
|
[
|
|
@@ -771,7 +776,8 @@ var SCHOOL_INSTITUTION_VOCABULARY = new Map([
|
|
|
771
776
|
kind: "word",
|
|
772
777
|
position: "suffix",
|
|
773
778
|
truncatable: false,
|
|
774
|
-
glued: false
|
|
779
|
+
glued: false,
|
|
780
|
+
matchKey: false
|
|
775
781
|
}
|
|
776
782
|
],
|
|
777
783
|
[
|
|
@@ -782,7 +788,8 @@ var SCHOOL_INSTITUTION_VOCABULARY = new Map([
|
|
|
782
788
|
kind: "word",
|
|
783
789
|
position: "suffix",
|
|
784
790
|
truncatable: false,
|
|
785
|
-
glued: false
|
|
791
|
+
glued: false,
|
|
792
|
+
matchKey: false
|
|
786
793
|
}
|
|
787
794
|
],
|
|
788
795
|
[
|
|
@@ -793,7 +800,8 @@ var SCHOOL_INSTITUTION_VOCABULARY = new Map([
|
|
|
793
800
|
kind: "word",
|
|
794
801
|
position: "prefix",
|
|
795
802
|
truncatable: false,
|
|
796
|
-
glued: false
|
|
803
|
+
glued: false,
|
|
804
|
+
matchKey: false
|
|
797
805
|
}
|
|
798
806
|
],
|
|
799
807
|
[
|
|
@@ -804,7 +812,8 @@ var SCHOOL_INSTITUTION_VOCABULARY = new Map([
|
|
|
804
812
|
kind: "word",
|
|
805
813
|
position: "prefix",
|
|
806
814
|
truncatable: false,
|
|
807
|
-
glued: false
|
|
815
|
+
glued: false,
|
|
816
|
+
matchKey: false
|
|
808
817
|
}
|
|
809
818
|
],
|
|
810
819
|
[
|
|
@@ -815,7 +824,8 @@ var SCHOOL_INSTITUTION_VOCABULARY = new Map([
|
|
|
815
824
|
kind: "word",
|
|
816
825
|
position: "prefix",
|
|
817
826
|
truncatable: false,
|
|
818
|
-
glued: false
|
|
827
|
+
glued: false,
|
|
828
|
+
matchKey: true
|
|
819
829
|
}
|
|
820
830
|
],
|
|
821
831
|
[
|
|
@@ -826,7 +836,8 @@ var SCHOOL_INSTITUTION_VOCABULARY = new Map([
|
|
|
826
836
|
kind: "phrase",
|
|
827
837
|
position: "prefix",
|
|
828
838
|
truncatable: false,
|
|
829
|
-
glued: false
|
|
839
|
+
glued: false,
|
|
840
|
+
matchKey: true
|
|
830
841
|
}
|
|
831
842
|
],
|
|
832
843
|
[
|
|
@@ -837,7 +848,8 @@ var SCHOOL_INSTITUTION_VOCABULARY = new Map([
|
|
|
837
848
|
kind: "phrase",
|
|
838
849
|
position: "prefix",
|
|
839
850
|
truncatable: false,
|
|
840
|
-
glued: false
|
|
851
|
+
glued: false,
|
|
852
|
+
matchKey: false
|
|
841
853
|
}
|
|
842
854
|
],
|
|
843
855
|
[
|
|
@@ -848,7 +860,8 @@ var SCHOOL_INSTITUTION_VOCABULARY = new Map([
|
|
|
848
860
|
kind: "word",
|
|
849
861
|
position: "prefix",
|
|
850
862
|
truncatable: false,
|
|
851
|
-
glued: false
|
|
863
|
+
glued: false,
|
|
864
|
+
matchKey: false
|
|
852
865
|
}
|
|
853
866
|
],
|
|
854
867
|
[
|
|
@@ -859,7 +872,8 @@ var SCHOOL_INSTITUTION_VOCABULARY = new Map([
|
|
|
859
872
|
kind: "word",
|
|
860
873
|
position: "suffix",
|
|
861
874
|
truncatable: true,
|
|
862
|
-
glued: false
|
|
875
|
+
glued: false,
|
|
876
|
+
matchKey: true
|
|
863
877
|
}
|
|
864
878
|
],
|
|
865
879
|
[
|
|
@@ -870,7 +884,8 @@ var SCHOOL_INSTITUTION_VOCABULARY = new Map([
|
|
|
870
884
|
kind: "word",
|
|
871
885
|
position: "suffix",
|
|
872
886
|
truncatable: false,
|
|
873
|
-
glued: false
|
|
887
|
+
glued: false,
|
|
888
|
+
matchKey: false
|
|
874
889
|
}
|
|
875
890
|
],
|
|
876
891
|
[
|
|
@@ -881,7 +896,8 @@ var SCHOOL_INSTITUTION_VOCABULARY = new Map([
|
|
|
881
896
|
kind: "word",
|
|
882
897
|
position: "suffix",
|
|
883
898
|
truncatable: true,
|
|
884
|
-
glued: false
|
|
899
|
+
glued: false,
|
|
900
|
+
matchKey: true
|
|
885
901
|
}
|
|
886
902
|
],
|
|
887
903
|
[
|
|
@@ -892,7 +908,8 @@ var SCHOOL_INSTITUTION_VOCABULARY = new Map([
|
|
|
892
908
|
kind: "word",
|
|
893
909
|
position: "suffix",
|
|
894
910
|
truncatable: true,
|
|
895
|
-
glued: false
|
|
911
|
+
glued: false,
|
|
912
|
+
matchKey: true
|
|
896
913
|
}
|
|
897
914
|
],
|
|
898
915
|
[
|
|
@@ -903,7 +920,8 @@ var SCHOOL_INSTITUTION_VOCABULARY = new Map([
|
|
|
903
920
|
kind: "word",
|
|
904
921
|
position: "suffix",
|
|
905
922
|
truncatable: true,
|
|
906
|
-
glued: false
|
|
923
|
+
glued: false,
|
|
924
|
+
matchKey: true
|
|
907
925
|
}
|
|
908
926
|
],
|
|
909
927
|
[
|
|
@@ -914,7 +932,8 @@ var SCHOOL_INSTITUTION_VOCABULARY = new Map([
|
|
|
914
932
|
kind: "word",
|
|
915
933
|
position: "suffix",
|
|
916
934
|
truncatable: false,
|
|
917
|
-
glued: false
|
|
935
|
+
glued: false,
|
|
936
|
+
matchKey: true
|
|
918
937
|
}
|
|
919
938
|
],
|
|
920
939
|
[
|
|
@@ -925,7 +944,8 @@ var SCHOOL_INSTITUTION_VOCABULARY = new Map([
|
|
|
925
944
|
kind: "word",
|
|
926
945
|
position: "suffix",
|
|
927
946
|
truncatable: false,
|
|
928
|
-
glued: false
|
|
947
|
+
glued: false,
|
|
948
|
+
matchKey: false
|
|
929
949
|
}
|
|
930
950
|
]
|
|
931
951
|
]);
|
|
@@ -958,28 +978,14 @@ function truncatedInstitution(tail) {
|
|
|
958
978
|
}
|
|
959
979
|
return found;
|
|
960
980
|
}
|
|
981
|
+
var MATCH_KEY_INSTITUTION_WORDS = [
|
|
982
|
+
...new Set([...SCHOOL_INSTITUTION_VOCABULARY].filter(([, v]) => v.matchKey).flatMap(([k]) => k.split(" ")))
|
|
983
|
+
].sort();
|
|
961
984
|
|
|
962
985
|
import { normalizeApostrophes } from "@finbheara/names/lexicon";
|
|
963
986
|
var SCHOOL_FLUFF_WORDS = new Set([
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
"dance",
|
|
967
|
-
"dancing",
|
|
968
|
-
"dancers",
|
|
969
|
-
"school",
|
|
970
|
-
"company",
|
|
971
|
-
"traditional",
|
|
972
|
-
"the",
|
|
973
|
-
"of",
|
|
974
|
-
"and",
|
|
975
|
-
"studio",
|
|
976
|
-
"center",
|
|
977
|
-
"centre",
|
|
978
|
-
"institute",
|
|
979
|
-
"scoil",
|
|
980
|
-
"rince",
|
|
981
|
-
"na",
|
|
982
|
-
"an"
|
|
987
|
+
...[...SCHOOL_FLUFF_VOCABULARY.values()].filter((entry) => entry.tokenFluff).map((entry) => entry.canonical),
|
|
988
|
+
...MATCH_KEY_INSTITUTION_WORDS
|
|
983
989
|
]);
|
|
984
990
|
var SCHOOL_GENERIC_NAME_PARTS = new Set(["celtic", "clann"]);
|
|
985
991
|
function hasSpecificToken(tokens) {
|
|
@@ -1142,8 +1148,9 @@ function createSchoolNameReader(options = {}) {
|
|
|
1142
1148
|
function readSpacingAcute(print) {
|
|
1143
1149
|
return print.replace(SPACING_ACUTE_AFTER_VOWEL, "$1́").replace(SPACING_ACUTE, "'");
|
|
1144
1150
|
}
|
|
1151
|
+
const INJECTED_LINK = /(?<=^|[\s([])(?:https?:\/\/|www\.)[^\s)\]]+/giu;
|
|
1145
1152
|
function renderSn1(print) {
|
|
1146
|
-
return normalizeApostrophes2(readSpacingAcute(repairMojibake(print)).normalize("NFKC")).replace(/\p{Cf}+/gu, "").replace(/\p{Cc}+/gu, " ").replace(/\s+/gu, " ").trim();
|
|
1153
|
+
return normalizeApostrophes2(readSpacingAcute(repairMojibake(print)).normalize("NFKC")).replace(/\p{Cf}+/gu, "").replace(/\p{Cc}+/gu, " ").replace(INJECTED_LINK, " ").replace(/\s+/gu, " ").trim();
|
|
1147
1154
|
}
|
|
1148
1155
|
const COMPOUND_OPENERS = new Set([
|
|
1149
1156
|
"hyphen",
|
|
@@ -25,7 +25,7 @@ export type AgeArm = "band" | "yob" | "open" | "empty";
|
|
|
25
25
|
export type AgeKind = "under" | "over" | "range" | "adult" | "senior" | "yob";
|
|
26
26
|
export type AgeRefusal = "not-a-band" | "backwards-range" | "overlapping-ranges" | "senior-without-ladder" | "below-youngest-band" | "year-out-of-range";
|
|
27
27
|
export type AgeSource = "sibling-narrowed" | "printed-band" | "printed-range" | "printed-yob" | "open";
|
|
28
|
-
export type AgeClause = "under-floored-on-rung" | "youngest-absorbs" | "over-ceiling-from-next-over" | "over-ceiling-refused-gap" | "and-over-no-ceiling" | "adult-under-ceiling" | "adult-band" | "range-overlapping" | "range-as-under" | "range-top-meets-over" | "range-adult-floor";
|
|
28
|
+
export type AgeClause = "under-floored-on-rung" | "under-stride" | "youngest-absorbs" | "over-ceiling-from-next-over" | "over-ceiling-refused-gap" | "and-over-no-ceiling" | "adult-under-ceiling" | "adult-band" | "range-overlapping" | "range-as-under" | "range-top-meets-over" | "range-adult-floor";
|
|
29
29
|
export type AgeRelation = "same" | "contains" | "overlaps" | "disjoint" | "silent";
|
|
30
30
|
export type AgeRelationReason = "equal" | "a-contains-b" | "b-contains-a" | "partial" | "a-older" | "a-younger" | "a-not-a-band" | "b-not-a-band";
|
|
31
31
|
export interface AgeComparison {
|
package/dist/types/person.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type ParseOrder, type PersonName } from "@finbheara/names/normalize";
|
|
1
|
+
import { type ParseOrder, type PersonName, type PersonNameFactory } from "@finbheara/names/normalize";
|
|
2
2
|
import { type RowSentinel } from "./row-sentinels.ts";
|
|
3
3
|
export { SHARED_ROW_SENTINELS, sentinelIn } from "./row-sentinels.ts";
|
|
4
4
|
export type { RowSentinel } from "./row-sentinels.ts";
|
|
@@ -8,9 +8,9 @@ export declare const DANCER_SENTINELS: readonly RowSentinel[];
|
|
|
8
8
|
export declare const TEACHER_SENTINELS: readonly RowSentinel[];
|
|
9
9
|
export declare const ROLE_SENTINELS: Readonly<Record<PersonRole, readonly RowSentinel[]>>;
|
|
10
10
|
export declare function roleSentinelOf(role: PersonRole, print: string): RowSentinel | undefined;
|
|
11
|
-
export declare function roleName(role: PersonRole, print: string, order?: ParseOrder): PersonName;
|
|
11
|
+
export declare function roleName(role: PersonRole, print: string, order?: ParseOrder, factory?: Pick<PersonNameFactory, "parse">): PersonName;
|
|
12
12
|
export declare function rolePrintsNoName(role: PersonRole, print: string): boolean;
|
|
13
13
|
export declare const dancerPrintsNoName: (print: string) => boolean;
|
|
14
14
|
export declare const seatName: (print: string) => PersonName;
|
|
15
|
-
export declare const dancerName: (print: string, order?: ParseOrder) => PersonName;
|
|
15
|
+
export declare const dancerName: (print: string, order?: ParseOrder, factory?: Pick<PersonNameFactory, "parse">) => PersonName;
|
|
16
16
|
export declare const teacherName: (print: string, order?: ParseOrder) => PersonName;
|
|
@@ -8,6 +8,7 @@ export interface SchoolInstitution {
|
|
|
8
8
|
position: InstitutionPosition;
|
|
9
9
|
truncatable: boolean;
|
|
10
10
|
glued: boolean;
|
|
11
|
+
matchKey: boolean;
|
|
11
12
|
}
|
|
12
13
|
export declare const SCHOOL_INSTITUTION_VOCABULARY: ReadonlyMap<string, SchoolInstitution>;
|
|
13
14
|
export declare function schoolInstitution(text: string): SchoolInstitution | undefined;
|
|
@@ -18,3 +19,4 @@ export declare const INSTITUTION_TYPES: readonly InstitutionType[];
|
|
|
18
19
|
export declare const INSTITUTION_PHRASES: readonly string[];
|
|
19
20
|
export declare const GLUED_INSTITUTION_SUFFIXES: readonly string[];
|
|
20
21
|
export declare function truncatedInstitution(tail: string): SchoolInstitution | undefined;
|
|
22
|
+
export declare const MATCH_KEY_INSTITUTION_WORDS: readonly string[];
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import type { InstitutionType as RegisterType } from "./school-institution-vocabulary.ts";
|
|
2
|
-
export declare const LEGACY_EXCEPTION_PHRASES: ReadonlySet<string>;
|
|
3
2
|
export type SchoolTokenClass = "NAME_PART" | "INSTITUTION_TYPE" | "FLUFF" | "LOCATION_HINT";
|
|
4
3
|
export interface SchoolToken {
|
|
5
4
|
text: string;
|
package/package.json
CHANGED