strom-research 1.18.0-beta.13 → 1.18.0-beta.14
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/CHANGELOG.cs.md +4 -4
- package/CHANGELOG.de.md +5 -4
- package/CHANGELOG.md +4 -3
- package/dist/core/document.js +143 -24
- package/dist/core/tree.js +1 -1
- package/package.json +1 -1
package/CHANGELOG.cs.md
CHANGED
|
@@ -7,7 +7,7 @@ Změny každé verze ve zkratce. Úplné poznámky a instalační řádky jsou n
|
|
|
7
7
|
|
|
8
8
|
## 1.18.0
|
|
9
9
|
|
|
10
|
-
*Připravuje se: bety do 1.18.0-beta.
|
|
10
|
+
*Připravuje se: bety do 1.18.0-beta.14. Oddíl bude úplný s vydáním.*
|
|
11
11
|
|
|
12
12
|
- **Fotky z telefonu nastojato.** Fotka otočená podle údaje EXIF se čte tak, jak se má dívat, nastojato; místa na ní
|
|
13
13
|
vyznačená (výřezy, poloviny dvoustrany, uložená část) jsou místa obrázku, jak se ukazuje. Fotka sama zůstává, jak
|
|
@@ -20,9 +20,9 @@ Změny každé verze ve zkratce. Úplné poznámky a instalační řádky jsou n
|
|
|
20
20
|
matriky, dopis, listinu, náhrobek, rub fotky: přepis slovo od slova, překlad, význam starých slov a zkratek a osoby,
|
|
21
21
|
které jmenuje, i s tím, kdo ze stromu to může být. Nic se nedomýšlí: jméno, které v dokumentu není, vypadne — i
|
|
22
22
|
příjmení, nikdy se nebere od otce ani z jiné rodiny —, co nejde přečíst, je označené; druhý čtenář může číst naslepo.
|
|
23
|
-
Dokument na úředním formuláři, jako rodný list, si své osoby ponechá — dítě i oba rodiče s jejich podílem
|
|
24
|
-
|
|
25
|
-
stojí, takže aplikace Strom ukáže výřez každé z nich.
|
|
23
|
+
Dokument na úředním formuláři, jako rodný list, si své osoby ponechá — dítě i oba rodiče s jejich podílem, i jméno a
|
|
24
|
+
příjmení psané proloženě a rodné příjmení po „roz.“ —, a dokument přečtený dřív je po aktualizaci ukáže, aniž by se
|
|
25
|
+
četl znovu. U každé osoby a události je i místo na stránce, kde stojí, takže aplikace Strom ukáže výřez každé z nich.
|
|
26
26
|
Do stromu se z toho nic nezapíše samo. Dokument už přečtený to o sobě řekne, takže se omylem nečte podruhé. Dokument
|
|
27
27
|
čtený znovu se ukazuje pod názvem svého souboru, nikdy pod kódem. Dokument poslaný z aplikace Strom najde agenta
|
|
28
28
|
stejně jako terminál — i nainstalovaného do vlastní složky, přes npm nebo Homebrew — místo hlášení, že agent není
|
package/CHANGELOG.de.md
CHANGED
|
@@ -7,7 +7,7 @@ Die Änderungen jeder Version in Kürze. Die vollständigen Hinweise und die Ins
|
|
|
7
7
|
|
|
8
8
|
## 1.18.0
|
|
9
9
|
|
|
10
|
-
*In Vorbereitung: die Betas bis 1.18.0-beta.
|
|
10
|
+
*In Vorbereitung: die Betas bis 1.18.0-beta.14. Der Abschnitt ist mit dem Release vollständig.*
|
|
11
11
|
|
|
12
12
|
- **Handyfotos aufrecht.** Ein Foto, das nach seiner EXIF-Ausrichtung gedreht ist, wird gelesen, wie es gesehen
|
|
13
13
|
werden soll, aufrecht; die darauf markierten Stellen (Ausschnitte, die Hälften einer Doppelseite, ein gespeicherter
|
|
@@ -21,9 +21,10 @@ Die Änderungen jeder Version in Kürze. Die vollständigen Hinweise und die Ins
|
|
|
21
21
|
Wort, ihre Übersetzung, was alte Wörter und Abkürzungen bedeuten, und die genannten Personen, samt wem im Stammbaum
|
|
22
22
|
sie entsprechen können. Nichts wird ergänzt: ein Name, der nicht im Dokument steht, fällt weg — auch ein Nachname, nie
|
|
23
23
|
vom Vater oder aus einer anderen Familie genommen —, Unleserliches wird markiert; ein zweiter Leser kann blind lesen.
|
|
24
|
-
Ein Dokument auf einem amtlichen Formular, etwa eine Geburtsurkunde, behält seine Personen — das Kind und beide
|
|
25
|
-
|
|
26
|
-
|
|
24
|
+
Ein Dokument auf einem amtlichen Formular, etwa eine Geburtsurkunde, behält seine Personen — das Kind und beide Eltern
|
|
25
|
+
mit ihrem Anteil, auch ein gesperrt getippter Name und ein Geburtsname nach „geb.“ —, und ein früher gelesenes
|
|
26
|
+
Dokument zeigt sie nach dem Update, ohne erneut gelesen zu werden. Jede Person und jedes Ereignis kommt mit der Stelle
|
|
27
|
+
auf der Seite, an der es steht, so zeigt die Strom-App von jedem
|
|
27
28
|
einen eigenen Ausschnitt.
|
|
28
29
|
In den Stammbaum gelangt nichts von selbst. Ein schon gelesenes Dokument sagt es, so wird es nicht versehentlich ein
|
|
29
30
|
zweites Mal gelesen. Ein erneut gelesenes Dokument wird unter dem Namen seiner Datei gezeigt, nie unter einem Code.
|
package/CHANGELOG.md
CHANGED
|
@@ -7,7 +7,7 @@ The changes of each version in short. The full notes and the install lines are o
|
|
|
7
7
|
|
|
8
8
|
## 1.18.0
|
|
9
9
|
|
|
10
|
-
*In preparation: the betas up to 1.18.0-beta.
|
|
10
|
+
*In preparation: the betas up to 1.18.0-beta.14. The section is complete with the release.*
|
|
11
11
|
|
|
12
12
|
- **Phone photos upright.** A photo turned by its EXIF orientation is read as it is meant to be seen, upright; the
|
|
13
13
|
places marked on it (excerpts, the halves of a spread, a cut-out part) are of the picture as it is shown. The
|
|
@@ -22,8 +22,9 @@ The changes of each version in short. The full notes and the install lines are o
|
|
|
22
22
|
name the document does not have is left out — a surname too, never taken from a father or another family —, what
|
|
23
23
|
cannot be read is marked; a second reader can read it blind. A
|
|
24
24
|
document on a printed form, as a birth certificate, keeps its people — the child and both parents with their part in
|
|
25
|
-
it
|
|
26
|
-
|
|
25
|
+
it, their names typed letter-spaced and a mother's birth name after "née" or "roz." too —, and a document read before
|
|
26
|
+
shows them after the update with nothing read again. Each person and event it names comes with the place on the page
|
|
27
|
+
where it stands, so the Strom app shows each its own excerpt. Nothing of it enters the tree by itself. A document read
|
|
27
28
|
already says so, so it is not read a second time by mistake. A document read again is shown under the name of its
|
|
28
29
|
file, never a code. A document sent from the Strom app finds the agent as the terminal does — one installed in a
|
|
29
30
|
folder of its own, by npm or Homebrew too — instead of saying no agent is set up. Every agent the research works with
|
package/dist/core/document.js
CHANGED
|
@@ -114,6 +114,8 @@ term: <a word or abbreviation as written> = <what it means, in ${into}> (term |
|
|
|
114
114
|
given and surname only turn the written name into today's form ("Joannes" → "Jan"): never a name the transcript
|
|
115
115
|
does not have — no surname the entry does not write by the person (a child's is not taken from its father's);
|
|
116
116
|
on a form (a certificate) whose fields hold a name apart, written= the words of its fields as written there;
|
|
117
|
+
a name in letter-spaced type ("N o v á k") is one word: surname=Novák; a woman written with her birth name
|
|
118
|
+
("Marie Nováková roz. Dvořáková", geb., née, z domu): surname= the birth name;
|
|
117
119
|
a name you could not read stays out; leave out what the entry does not say; region: where the person's name
|
|
118
120
|
stands — its line, or its field on a form — as the entry's region, of the page's whole view (tight, not the entry)
|
|
119
121
|
event: <BIRT | BAPM | MARR | DEAT | BURI | RESI | EVEN> | date=<as on the record, in numbers: 3.4.1846, or a year> |
|
|
@@ -312,20 +314,113 @@ function kindOf(said) {
|
|
|
312
314
|
return "photo.back";
|
|
313
315
|
return "other";
|
|
314
316
|
}
|
|
315
|
-
|
|
317
|
+
/** One letter alone, as a typewriter spaces out a name (V í š e k); the last of them may have a stop or a "[?]". */
|
|
318
|
+
const SPACED = /^\p{L}\p{M}*$/u;
|
|
319
|
+
const SPACED_LAST = /^\p{L}\p{M}*(?:\[\?\]|[^\p{L}\p{M}\p{N}\[\]])*$/u;
|
|
320
|
+
const keyOf = (t) => foldText(t.replace(/\[\?\]/gu, "")).replace(/[^\p{L}\p{M}\p{N}]+/gu, "");
|
|
321
|
+
/** The keys of the words of names (a reader's given name and surname, the other reader's text) that join spaced letters. */
|
|
322
|
+
export function nameKeys(...names) {
|
|
323
|
+
return names.flatMap((n) => (n ? words(n).map((w) => w.key) : [])).filter((k) => k.length >= 2 && k !== "[...]");
|
|
324
|
+
}
|
|
325
|
+
/**
|
|
326
|
+
* The words of a text as they are compared: a word after a stop with no space ("roz.Nováková", "n.Labem") a word of
|
|
327
|
+
* its own, glued to the one before; letters standing alone (a name in letter-spaced type, "N o v á k") one word, as
|
|
328
|
+
* written — a run of them that spells one of `names` (the reader's given name or surname), the rest of a run that has
|
|
329
|
+
* one, and else three or more beginning with a capital; a gap of two spaces or more (a typewriter's between the words of
|
|
330
|
+
* a spaced name) or a line ends a run. Letters of running text ("šel a v k domu") stay words of their own.
|
|
331
|
+
*/
|
|
332
|
+
export function words(s, names = []) {
|
|
316
333
|
const src = s
|
|
317
334
|
.replace(/\s*\[\?\]/gu, "[?]")
|
|
318
335
|
.replace(/\[\s*(?:\.{2,}|…)\s*\]/gu, " [...] ")
|
|
319
|
-
.replace(/\|/gu, "
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
.
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
336
|
+
.replace(/\|/gu, " ");
|
|
337
|
+
const parts = [];
|
|
338
|
+
for (const m of src.matchAll(/(\s*)(\S+)/gu)) {
|
|
339
|
+
const wide = m[1].length > 1 || /[\n\r]/u.test(m[1]);
|
|
340
|
+
if (m[2] === "[...]")
|
|
341
|
+
parts.push({ t: m[2], glued: false, wide });
|
|
342
|
+
else
|
|
343
|
+
m[2].split(/(?<=\p{L}\p{M}*\.)(?=\p{L})/u).forEach((t, i) => parts.push({ t, glued: i > 0, wide: i === 0 && wide }));
|
|
344
|
+
}
|
|
345
|
+
const known = new Set(names);
|
|
346
|
+
const out = [];
|
|
347
|
+
const letters = (a, b) => {
|
|
348
|
+
const text = parts.slice(a, b).map((x) => x.t).join(" ");
|
|
349
|
+
out.push({ text, key: keyOf(text), unsure: text.includes("[?]"), illegible: false });
|
|
350
|
+
};
|
|
351
|
+
for (let i = 0; i < parts.length; i++) {
|
|
352
|
+
// a run of letters alone: no gap of two spaces within, the last may have a stop, the word after not glued to it
|
|
353
|
+
let j = i;
|
|
354
|
+
while (j < parts.length && !parts[j].glued && (j === i || !parts[j].wide) && SPACED.test(parts[j].t))
|
|
355
|
+
j++;
|
|
356
|
+
if (j < parts.length && j > i && !parts[j].glued && !parts[j].wide && SPACED_LAST.test(parts[j].t) && !SPACED.test(parts[j].t))
|
|
357
|
+
j++;
|
|
358
|
+
if (j - i >= 2 && (j === parts.length || !parts[j].glued)) {
|
|
359
|
+
// the names it spells, the longest first, and what stands between them
|
|
360
|
+
const named = [];
|
|
361
|
+
for (let a = i; a < j - 1;) {
|
|
362
|
+
let b = j;
|
|
363
|
+
while (b - a >= 2 && !known.has(keyOf(parts.slice(a, b).map((x) => x.t).join(""))))
|
|
364
|
+
b--;
|
|
365
|
+
if (b - a >= 2) {
|
|
366
|
+
named.push([a, b]);
|
|
367
|
+
a = b;
|
|
368
|
+
}
|
|
369
|
+
else
|
|
370
|
+
a++;
|
|
371
|
+
}
|
|
372
|
+
if (named.length) {
|
|
373
|
+
let a = i;
|
|
374
|
+
for (const [x, y] of [...named, [j, j]]) {
|
|
375
|
+
if (x - a >= 2)
|
|
376
|
+
letters(a, x);
|
|
377
|
+
else
|
|
378
|
+
for (let k = a; k < x; k++)
|
|
379
|
+
letters(k, k + 1);
|
|
380
|
+
if (y > x)
|
|
381
|
+
letters(x, y);
|
|
382
|
+
a = y;
|
|
383
|
+
}
|
|
384
|
+
i = j - 1;
|
|
385
|
+
continue;
|
|
386
|
+
}
|
|
387
|
+
if (j - i >= 3 && /^\p{Lu}/u.test(parts[i].t)) {
|
|
388
|
+
letters(i, j);
|
|
389
|
+
i = j - 1;
|
|
390
|
+
continue;
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
const { t, glued } = parts[i];
|
|
394
|
+
if (t === "[...]") {
|
|
395
|
+
out.push({ text: t, key: "[...]", unsure: false, illegible: true });
|
|
396
|
+
continue;
|
|
397
|
+
}
|
|
398
|
+
const key = keyOf(t);
|
|
399
|
+
if (key)
|
|
400
|
+
out.push({ text: t, key, unsure: t.includes("[?]"), illegible: false, ...(glued ? { glued } : {}) });
|
|
401
|
+
}
|
|
402
|
+
return out;
|
|
403
|
+
}
|
|
404
|
+
/** Words that stand in a row as they were written: one space between, none before a word glued to the one before. */
|
|
405
|
+
function asWritten(span) {
|
|
406
|
+
return span.map((x, i) => (i && !x.glued ? ` ${x.text}` : x.text)).join("");
|
|
407
|
+
}
|
|
408
|
+
/**
|
|
409
|
+
* The words of a birth name's mark, folded: in full — rozená, geborene, née, nata, urodzona, урождённая, z domu — or
|
|
410
|
+
* shortened with its stop — roz., geb., urodz., ur., урожд. —: the name after one is the person's birth surname.
|
|
411
|
+
*/
|
|
412
|
+
const BIRTH_WORDS = new Set(["rozena", "rozeny", "geborene", "geborener", "nee", "nata", "urodzona", "урожденная", "урожденный", "szuletett"]);
|
|
413
|
+
const BIRTH_SHORT = new Set(["roz", "geb", "urodz", "ur", "урожд", "szul"]);
|
|
414
|
+
/** A birth name's mark at `i`; a short one only with its stop, "ur." only before the reader's surname (Ur is a name too). */
|
|
415
|
+
function birthMarkAt(span, i, surnameAt) {
|
|
416
|
+
const x = span[i];
|
|
417
|
+
if (x.key === "domu")
|
|
418
|
+
return span[i - 1]?.key === "z";
|
|
419
|
+
if (BIRTH_WORDS.has(x.key))
|
|
420
|
+
return true;
|
|
421
|
+
if (!BIRTH_SHORT.has(x.key) || !/\.$/u.test(x.text.replace(/\[\?\]/gu, "")))
|
|
422
|
+
return false;
|
|
423
|
+
return x.key !== "ur" || i + 1 === surnameAt;
|
|
329
424
|
}
|
|
330
425
|
/** Where the words of `part` stand in `whole`, in a row (its first place), else -1. */
|
|
331
426
|
function find(whole, part) {
|
|
@@ -512,17 +607,20 @@ export function checkEntry(raw, id, blind = false, form = false) {
|
|
|
512
607
|
checks.push({ entry: id, ref: p.ref, what: [p.fields.given, p.fields.surname].filter(Boolean).join(" ") || p.role, why: "no-name" });
|
|
513
608
|
continue;
|
|
514
609
|
}
|
|
515
|
-
|
|
516
|
-
const
|
|
610
|
+
// letters spaced out (a name typed letter-spaced) joined as the reader's given name and surname spell them
|
|
611
|
+
const names = nameKeys(p.fields.given, p.fields.surname);
|
|
612
|
+
const own = words(raw.transcript, names);
|
|
613
|
+
const w = words(written, names);
|
|
614
|
+
const at = find(own, w);
|
|
517
615
|
// a form (a certificate) holds a name in its fields apart — the surname in one, the given names in another —:
|
|
518
616
|
// its words each written there are the name; elsewhere a name stands in a row as written
|
|
519
|
-
const span = at >= 0 ?
|
|
617
|
+
const span = at >= 0 ? own.slice(at, at + w.length) : form ? findApart(own, w) : undefined;
|
|
520
618
|
if (!span) {
|
|
521
619
|
checks.push({ entry: id, ref: p.ref, what: written, why: "not-in-transcript" });
|
|
522
620
|
continue;
|
|
523
621
|
}
|
|
524
622
|
const role = (ROLES.includes(p.role) ? p.role : "other");
|
|
525
|
-
const person = { ref: p.ref, role, written: span.map((x) => x.text).join(" ") };
|
|
623
|
+
const person = { ref: p.ref, role, written: at >= 0 ? asWritten(span) : span.map((x) => x.text).join(" ") };
|
|
526
624
|
if (p.roleText && !blind)
|
|
527
625
|
person.roleText = p.roleText;
|
|
528
626
|
const uncertain = new Set();
|
|
@@ -548,7 +646,13 @@ export function checkEntry(raw, id, blind = false, form = false) {
|
|
|
548
646
|
}
|
|
549
647
|
// the given name: the other words; a word of today's form must be one of them in its letters (Josephi → Josef,
|
|
550
648
|
// Joannes → Jan), else the name is as written and the reader's form only a lead (today)
|
|
551
|
-
|
|
649
|
+
// (not a birth name's mark, roz. or geb., nor the birth name after it)
|
|
650
|
+
const marked = new Set();
|
|
651
|
+
span.forEach((x, i) => {
|
|
652
|
+
if (birthMarkAt(span, i, surnameAt))
|
|
653
|
+
[i, i + 1, ...(x.key === "domu" ? [i - 1] : [])].forEach((k) => marked.add(k));
|
|
654
|
+
});
|
|
655
|
+
const givenWords = span.filter((_, i) => i !== surnameAt && !marked.has(i));
|
|
552
656
|
const given = p.fields.given?.replace(/\[\?\]/gu, "").trim();
|
|
553
657
|
if (given) {
|
|
554
658
|
const legible = givenWords.filter((x) => !x.illegible);
|
|
@@ -559,7 +663,7 @@ export function checkEntry(raw, id, blind = false, form = false) {
|
|
|
559
663
|
if (fits)
|
|
560
664
|
person.given = given;
|
|
561
665
|
else {
|
|
562
|
-
person.given = legible.map((x) => x.text.replace(/\[\?\]
|
|
666
|
+
person.given = legible.map((x) => x.text.replace(/\[\?\]|\s+/gu, "").replace(/^[^\p{L}\p{M}\p{N}]+|[^\p{L}\p{M}\p{N}]+$/gu, "")).join(" ");
|
|
563
667
|
person.today = given;
|
|
564
668
|
uncertain.add("given");
|
|
565
669
|
checks.push({ entry: id, ref: p.ref, what: `given "${given}" for "${person.given}"`, why: "not-of-its-letters" });
|
|
@@ -658,8 +762,9 @@ function partOf(r, entry) {
|
|
|
658
762
|
// ── two readers ───────────────────────────────────────────────────────────────────────────────────────────────────
|
|
659
763
|
/** The hunks where two transcripts differ, word by word (their keys; the marks [?] are no difference). */
|
|
660
764
|
export function wordDiff(a, b) {
|
|
661
|
-
|
|
662
|
-
const
|
|
765
|
+
// letters one reader spaced out joined as the other wrote the word
|
|
766
|
+
const x = words(a, nameKeys(b));
|
|
767
|
+
const y = words(b, nameKeys(a));
|
|
663
768
|
const n = x.length;
|
|
664
769
|
const m = y.length;
|
|
665
770
|
const lcs = Array.from({ length: n + 1 }, () => new Array(m + 1).fill(0));
|
|
@@ -699,7 +804,7 @@ const same = (a, b) => foldText(a ?? "") === foldText(b ?? "");
|
|
|
699
804
|
* one's. Index in `mine` → index in `theirs`.
|
|
700
805
|
*/
|
|
701
806
|
function pairByName(mine, theirs) {
|
|
702
|
-
const keys = (p) => words(p.written).filter((x) => !x.illegible).map((x) => x.key);
|
|
807
|
+
const keys = (p) => words(p.written, nameKeys(p.given, p.surname)).filter((x) => !x.illegible).map((x) => x.key);
|
|
703
808
|
const surname = (p) => words(p.surname ?? "").map((x) => x.key);
|
|
704
809
|
const WHOLE = 1000;
|
|
705
810
|
const score = (p, q) => {
|
|
@@ -859,7 +964,7 @@ function bornRange(role, year, age) {
|
|
|
859
964
|
* and a surname of the same family (Novák/Nováková) are needed; the same sex, a birth year that fits the role and the
|
|
860
965
|
* record's year, and a place of theirs add to it. A suggestion, never a decision: the person chooses.
|
|
861
966
|
*/
|
|
862
|
-
export function matchPerson(tree, p, year, place) {
|
|
967
|
+
export function matchPerson(tree, p, year, place, own, child) {
|
|
863
968
|
if (!p.given || !p.surname)
|
|
864
969
|
return [];
|
|
865
970
|
const firstOf = (s) => foldText(s).split(" ")[0];
|
|
@@ -888,8 +993,16 @@ export function matchPerson(tree, p, year, place) {
|
|
|
888
993
|
score += 0.1;
|
|
889
994
|
}
|
|
890
995
|
const born = dateYears(birthEvent(o)?.date ?? "")[0];
|
|
891
|
-
|
|
892
|
-
|
|
996
|
+
// a parent of one the document says was born then (a certificate's grandparents) as a parent of that year
|
|
997
|
+
const range = child !== undefined ? bornRange("father", child) : year !== undefined ? bornRange(p.role, year, p.age) : undefined;
|
|
998
|
+
// the year the document says the person was born (a certificate's parents): the tree's, a year apart at most
|
|
999
|
+
if (own !== undefined && born !== undefined) {
|
|
1000
|
+
if (Math.abs(born - own) > 1)
|
|
1001
|
+
continue;
|
|
1002
|
+
why.push("years");
|
|
1003
|
+
score += 0.15;
|
|
1004
|
+
}
|
|
1005
|
+
else if (range && born !== undefined) {
|
|
893
1006
|
if (born < range[0] - 2 || born > range[1] + 2)
|
|
894
1007
|
continue;
|
|
895
1008
|
why.push("years");
|
|
@@ -923,8 +1036,14 @@ export function withTree(tree, entries) {
|
|
|
923
1036
|
const known = knownPlace(tree, x.place.text);
|
|
924
1037
|
return known ? { ...x, place: { ...x.place, known } } : x;
|
|
925
1038
|
});
|
|
1039
|
+
// the year each person was born, where the document says so
|
|
1040
|
+
const bornOf = (ref) => {
|
|
1041
|
+
const birth = e.events.find((x) => ["BIRT", "BAPM", "CHR"].includes(x.type) && x.date?.gedcom && x.persons.some((r) => r.ref === ref && r.role === "principal"));
|
|
1042
|
+
return birth?.date?.gedcom ? dateYears(birth.date.gedcom)[0] : undefined;
|
|
1043
|
+
};
|
|
926
1044
|
const persons = e.persons.map((p) => {
|
|
927
|
-
const
|
|
1045
|
+
const child = e.relations.flatMap((r) => (r.type === "parent" && r.parent === p.ref ? [bornOf(r.child)] : [])).find((y) => y !== undefined);
|
|
1046
|
+
const match = matchPerson(tree, p, year, place, bornOf(p.ref), child);
|
|
928
1047
|
return match.length ? { ...p, match } : p;
|
|
929
1048
|
});
|
|
930
1049
|
return { ...e, persons, events };
|
package/dist/core/tree.js
CHANGED
|
@@ -27,7 +27,7 @@ import { lastBackup } from "./backup.js";
|
|
|
27
27
|
export const TREE_FILE = "strom.json";
|
|
28
28
|
// between releases the candidate being made (a bridge run from the sources says what it is: the Strom app goes by it);
|
|
29
29
|
// at a release the release's own (package.json)
|
|
30
|
-
export const VERSION = "1.18.0-beta.
|
|
30
|
+
export const VERSION = "1.18.0-beta.14";
|
|
31
31
|
const GITIGNORE = `# Strom Research — local state and large files are not versioned
|
|
32
32
|
.strom/
|
|
33
33
|
/media/
|