@treeviz/gedcom-parser 2.0.7 → 2.0.9
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/dist/classes/date.d.ts +2 -0
- package/dist/classes/date.d.ts.map +1 -1
- package/dist/classes/index.js +424 -159
- package/dist/classes/indi.d.ts.map +1 -1
- package/dist/cli/index.js +424 -159
- package/dist/constants/index.js +423 -158
- package/dist/factories/index.js +423 -158
- package/dist/index.js +425 -160
- package/dist/kinship-translator/index.js +423 -158
- package/dist/kinship-translator/kinship-translator.basic.d.ts +11 -0
- package/dist/kinship-translator/kinship-translator.basic.d.ts.map +1 -1
- package/dist/kinship-translator/kinship-translator.d.ts.map +1 -1
- package/dist/kinship-translator/kinship-translator.de.d.ts +2 -1
- package/dist/kinship-translator/kinship-translator.de.d.ts.map +1 -1
- package/dist/kinship-translator/kinship-translator.en.d.ts +2 -1
- package/dist/kinship-translator/kinship-translator.en.d.ts.map +1 -1
- package/dist/kinship-translator/kinship-translator.es.d.ts +2 -1
- package/dist/kinship-translator/kinship-translator.es.d.ts.map +1 -1
- package/dist/kinship-translator/kinship-translator.fr.d.ts +2 -1
- package/dist/kinship-translator/kinship-translator.fr.d.ts.map +1 -1
- package/dist/kinship-translator/kinship-translator.hu.d.ts +8 -1
- package/dist/kinship-translator/kinship-translator.hu.d.ts.map +1 -1
- package/dist/kinship-translator/kinship-translator.interface.d.ts +1 -0
- package/dist/kinship-translator/kinship-translator.interface.d.ts.map +1 -1
- package/dist/kinship-translator/patterns.es.d.ts.map +1 -1
- package/dist/utils/cache.d.ts +14 -1
- package/dist/utils/cache.d.ts.map +1 -1
- package/dist/utils/index.js +425 -160
- package/package.json +1 -1
|
@@ -48,6 +48,44 @@ var KinshipTranslatorBasic = class {
|
|
|
48
48
|
}
|
|
49
49
|
return this.pathN?.indi;
|
|
50
50
|
}
|
|
51
|
+
/**
|
|
52
|
+
* True when the path goes through a common ancestor whose two children
|
|
53
|
+
* (the person we came from and the person we go to) share fewer than two
|
|
54
|
+
* biological parents — i.e. they are half-siblings, so every collateral
|
|
55
|
+
* relative on this path is a half-aunt/half-cousin/... too.
|
|
56
|
+
*
|
|
57
|
+
* Direct ancestors/descendants and paths that already use a
|
|
58
|
+
* step/adopted/foster edge are never half-blood.
|
|
59
|
+
*/
|
|
60
|
+
get isHalfBlood() {
|
|
61
|
+
const path = this.path;
|
|
62
|
+
if (!path || path.length < 3) {
|
|
63
|
+
return false;
|
|
64
|
+
}
|
|
65
|
+
if (path.some(
|
|
66
|
+
(item) => item.relation && item.relation !== "biological" /* BIOLOGICAL */
|
|
67
|
+
)) {
|
|
68
|
+
return false;
|
|
69
|
+
}
|
|
70
|
+
let peakIndex = -1;
|
|
71
|
+
for (let i = 1; i < path.length; i++) {
|
|
72
|
+
if (path[i].kinship === "parent") {
|
|
73
|
+
peakIndex = i;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
if (peakIndex <= 0 || peakIndex >= path.length - 1) {
|
|
77
|
+
return false;
|
|
78
|
+
}
|
|
79
|
+
if (path[peakIndex + 1].kinship !== "child") {
|
|
80
|
+
return false;
|
|
81
|
+
}
|
|
82
|
+
const siblingA = path[peakIndex - 1].indi;
|
|
83
|
+
const siblingB = path[peakIndex + 1].indi;
|
|
84
|
+
const parentsA = siblingA.getBiologicalParents();
|
|
85
|
+
const parentsB = siblingB.getBiologicalParents();
|
|
86
|
+
const inter = parentsA.intersection(parentsB);
|
|
87
|
+
return inter.length === 1 && (parentsA.length > 1 || parentsB.length > 1);
|
|
88
|
+
}
|
|
51
89
|
indirect() {
|
|
52
90
|
return "";
|
|
53
91
|
}
|
|
@@ -75,6 +113,9 @@ var KinshipTranslatorBasic = class {
|
|
|
75
113
|
relationType(relation) {
|
|
76
114
|
return relation ?? "";
|
|
77
115
|
}
|
|
116
|
+
halfBlood(relation) {
|
|
117
|
+
return relation ?? "";
|
|
118
|
+
}
|
|
78
119
|
of(relation) {
|
|
79
120
|
return relation ?? "";
|
|
80
121
|
}
|
|
@@ -482,14 +523,34 @@ var KinshipTranslatorHU = class extends KinshipTranslatorBasic {
|
|
|
482
523
|
return `${prefix.replace(/nagy$/, "")}unoka`;
|
|
483
524
|
}
|
|
484
525
|
sibling() {
|
|
485
|
-
const parents1 = this.person1?.getBiologicalParents();
|
|
486
|
-
const parentsN = this.personN?.getBiologicalParents();
|
|
487
|
-
const inter = parents1?.intersection(parentsN);
|
|
488
|
-
if (!inter || inter.length < 2) {
|
|
489
|
-
return "f\xE9ltestv\xE9r";
|
|
490
|
-
}
|
|
491
526
|
return "testv\xE9r";
|
|
492
527
|
}
|
|
528
|
+
halfBlood(relation) {
|
|
529
|
+
if (!relation || !this.isHalfBlood) {
|
|
530
|
+
return relation ?? "";
|
|
531
|
+
}
|
|
532
|
+
const [head, ...rest] = relation.split(" ");
|
|
533
|
+
if (!head) {
|
|
534
|
+
return relation;
|
|
535
|
+
}
|
|
536
|
+
const prefixed = this.prefixHalf(head);
|
|
537
|
+
return [prefixed, ...rest].join(" ");
|
|
538
|
+
}
|
|
539
|
+
/**
|
|
540
|
+
* AkH. 139: compounds of more than two members stay closed up to 6
|
|
541
|
+
* syllables; longer ones are hyphenated at the main boundary. A head
|
|
542
|
+
* that is already hyphenated also takes a hyphenated half- prefix.
|
|
543
|
+
*/
|
|
544
|
+
prefixHalf(head) {
|
|
545
|
+
if (head.includes("-") || !/[aáeéiíoóöőuúüű]/i.test(head)) {
|
|
546
|
+
return `f\xE9l-${head}`;
|
|
547
|
+
}
|
|
548
|
+
const syllables = (head.match(/[aáeéiíoóöőuúüű]/gi) ?? []).length + 1;
|
|
549
|
+
if (syllables > 6) {
|
|
550
|
+
return `f\xE9l-${head}`;
|
|
551
|
+
}
|
|
552
|
+
return `f\xE9l${head}`;
|
|
553
|
+
}
|
|
493
554
|
spouse() {
|
|
494
555
|
if (this.personN?.isMale()) {
|
|
495
556
|
return "f\xE9rj";
|
|
@@ -688,20 +749,22 @@ var KinshipTranslatorEn = class extends KinshipTranslatorBasic {
|
|
|
688
749
|
return `${prefix}child`;
|
|
689
750
|
}
|
|
690
751
|
sibling() {
|
|
691
|
-
const parents1 = this.person1?.getBiologicalParents();
|
|
692
|
-
const parentsN = this.personN?.getBiologicalParents();
|
|
693
|
-
const inter = parents1?.intersection(parentsN);
|
|
694
|
-
let prefix = "";
|
|
695
|
-
if (!inter || inter.length < 2) {
|
|
696
|
-
prefix = "half-";
|
|
697
|
-
}
|
|
698
752
|
if (this.personN?.isMale()) {
|
|
699
|
-
return
|
|
753
|
+
return "brother";
|
|
700
754
|
}
|
|
701
755
|
if (this.personN?.isFemale()) {
|
|
702
|
-
return
|
|
756
|
+
return "sister";
|
|
703
757
|
}
|
|
704
|
-
return
|
|
758
|
+
return "sibling";
|
|
759
|
+
}
|
|
760
|
+
halfBlood(relation) {
|
|
761
|
+
if (!relation || !this.isHalfBlood) {
|
|
762
|
+
return relation ?? "";
|
|
763
|
+
}
|
|
764
|
+
if (relation.includes(" ")) {
|
|
765
|
+
return `half ${relation}`;
|
|
766
|
+
}
|
|
767
|
+
return `half-${relation}`;
|
|
705
768
|
}
|
|
706
769
|
spouse() {
|
|
707
770
|
if (this.personN?.isMale()) {
|
|
@@ -883,20 +946,19 @@ var KinshipTranslatorFr = class extends KinshipTranslatorBasic {
|
|
|
883
946
|
return `${prefix}enfant`;
|
|
884
947
|
}
|
|
885
948
|
sibling() {
|
|
886
|
-
const parents1 = this.person1?.getBiologicalParents();
|
|
887
|
-
const parentsN = this.personN?.getBiologicalParents();
|
|
888
|
-
const inter = parents1?.intersection(parentsN);
|
|
889
|
-
let prefix = "";
|
|
890
|
-
if (!inter || inter.length < 2) {
|
|
891
|
-
prefix = "demi-";
|
|
892
|
-
}
|
|
893
949
|
if (this.personN?.isMale()) {
|
|
894
|
-
return
|
|
950
|
+
return "fr\xE8re";
|
|
895
951
|
}
|
|
896
952
|
if (this.personN?.isFemale()) {
|
|
897
|
-
return
|
|
953
|
+
return "s\u0153ur";
|
|
898
954
|
}
|
|
899
|
-
return
|
|
955
|
+
return "fr\xE8re/s\u0153ur";
|
|
956
|
+
}
|
|
957
|
+
halfBlood(relation) {
|
|
958
|
+
if (!relation || !this.isHalfBlood) {
|
|
959
|
+
return relation ?? "";
|
|
960
|
+
}
|
|
961
|
+
return `demi-${relation}`;
|
|
900
962
|
}
|
|
901
963
|
spouse() {
|
|
902
964
|
if (this.personN?.isMale()) {
|
|
@@ -993,12 +1055,12 @@ var InLawsEs = {
|
|
|
993
1055
|
"madre del (c\xF3nyuge|esposa|esposo)": "suegra",
|
|
994
1056
|
"padre del (c\xF3nyuge|esposa|esposo)": "suegro",
|
|
995
1057
|
"padre/madre del (c\xF3nyuge|esposa|esposo)": "suegro/suegra",
|
|
996
|
-
"esposa de (medio )?(hermano/hermana|hermana|hermano)": "cu\xF1ada",
|
|
997
|
-
"esposo de (medio )?(hermano/hermana|hermana|hermano)": "cu\xF1ado",
|
|
998
|
-
"c\xF3nyuge de (medio )?(hermano/hermana|hermana|hermano)": "cu\xF1ado/cu\xF1ada",
|
|
999
|
-
"(medio )?hermana del (c\xF3nyuge|esposa|esposo)": "cu\xF1ada",
|
|
1000
|
-
"(medio )?hermano del (c\xF3nyuge|esposa|esposo)": "cu\xF1ado",
|
|
1001
|
-
"(medio )?hermano/hermana del (c\xF3nyuge|esposa|esposo)": "cu\xF1ado/cu\xF1ada"
|
|
1058
|
+
"esposa de (medio |media |medio/a )?(hermano/hermana|hermana|hermano)": "cu\xF1ada",
|
|
1059
|
+
"esposo de (medio |media |medio/a )?(hermano/hermana|hermana|hermano)": "cu\xF1ado",
|
|
1060
|
+
"c\xF3nyuge de (medio |media |medio/a )?(hermano/hermana|hermana|hermano)": "cu\xF1ado/cu\xF1ada",
|
|
1061
|
+
"(medio |media |medio/a )?hermana del (c\xF3nyuge|esposa|esposo)": "cu\xF1ada",
|
|
1062
|
+
"(medio |media |medio/a )?hermano del (c\xF3nyuge|esposa|esposo)": "cu\xF1ado",
|
|
1063
|
+
"(medio |media |medio/a )?hermano/hermana del (c\xF3nyuge|esposa|esposo)": "cu\xF1ado/cu\xF1ada"
|
|
1002
1064
|
};
|
|
1003
1065
|
|
|
1004
1066
|
// src/kinship-translator/kinship-translator.es.ts
|
|
@@ -1078,20 +1140,25 @@ var KinshipTranslatorEs = class extends KinshipTranslatorBasic {
|
|
|
1078
1140
|
return `${prefix}hijo/hija`;
|
|
1079
1141
|
}
|
|
1080
1142
|
sibling() {
|
|
1081
|
-
const parents1 = this.person1?.getBiologicalParents();
|
|
1082
|
-
const parentsN = this.personN?.getBiologicalParents();
|
|
1083
|
-
const inter = parents1?.intersection(parentsN);
|
|
1084
|
-
let prefix = "";
|
|
1085
|
-
if (!inter || inter.length < 2) {
|
|
1086
|
-
prefix = "medio ";
|
|
1087
|
-
}
|
|
1088
1143
|
if (this.personN?.isMale()) {
|
|
1089
|
-
return
|
|
1144
|
+
return "hermano";
|
|
1145
|
+
}
|
|
1146
|
+
if (this.personN?.isFemale()) {
|
|
1147
|
+
return "hermana";
|
|
1148
|
+
}
|
|
1149
|
+
return "hermano/hermana";
|
|
1150
|
+
}
|
|
1151
|
+
halfBlood(relation) {
|
|
1152
|
+
if (!relation || !this.isHalfBlood) {
|
|
1153
|
+
return relation ?? "";
|
|
1090
1154
|
}
|
|
1091
1155
|
if (this.personN?.isFemale()) {
|
|
1092
|
-
return
|
|
1156
|
+
return `media ${relation}`;
|
|
1157
|
+
}
|
|
1158
|
+
if (this.personN?.isMale()) {
|
|
1159
|
+
return `medio ${relation}`;
|
|
1093
1160
|
}
|
|
1094
|
-
return
|
|
1161
|
+
return `medio/a ${relation}`;
|
|
1095
1162
|
}
|
|
1096
1163
|
spouse() {
|
|
1097
1164
|
if (this.personN?.isMale()) {
|
|
@@ -1273,6 +1340,7 @@ var KinshipTranslator = class {
|
|
|
1273
1340
|
} else if (personN.level !== 0) {
|
|
1274
1341
|
relation = this.removal();
|
|
1275
1342
|
}
|
|
1343
|
+
relation = this.translator?.halfBlood(relation);
|
|
1276
1344
|
relation = this.translator?.relationType(relation);
|
|
1277
1345
|
if (this.translator?.isOfSpouse) {
|
|
1278
1346
|
relation = this.translator?.ofSpouse(relation);
|
|
@@ -2586,6 +2654,20 @@ var LONG_NOTES = {
|
|
|
2586
2654
|
"Bef.": "Before",
|
|
2587
2655
|
"Aft.": "After"
|
|
2588
2656
|
};
|
|
2657
|
+
var STANDARD_QUALIFIERS = {
|
|
2658
|
+
ABT: "Abt.",
|
|
2659
|
+
ABOUT: "Abt.",
|
|
2660
|
+
BEF: "Bef.",
|
|
2661
|
+
BEFORE: "Bef.",
|
|
2662
|
+
AFT: "Aft.",
|
|
2663
|
+
AFTER: "Aft."
|
|
2664
|
+
};
|
|
2665
|
+
var EXPORT_QUALIFIERS = {
|
|
2666
|
+
"Abt.": "ABT",
|
|
2667
|
+
"Bef.": "BEF",
|
|
2668
|
+
"Aft.": "AFT"
|
|
2669
|
+
};
|
|
2670
|
+
var GEDCOM_MONTHS = /\b(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)\b/g;
|
|
2589
2671
|
var NOTE_MARKER = "####";
|
|
2590
2672
|
var formatDateWithComponents = (date, hasDay, hasMonth, hasYear, noteValue, baseFormat = "dd MMM yyyy", locale) => {
|
|
2591
2673
|
const hasNote = baseFormat.includes("NOTE");
|
|
@@ -2619,6 +2701,17 @@ var CommonDate = class extends Common {
|
|
|
2619
2701
|
this.NOTE = this.NOTE || createCommon(this._gedcom, void 0, this.main);
|
|
2620
2702
|
this.NOTE.value = noteMatch?.note;
|
|
2621
2703
|
validValue = value.replace(noteRegExp, "");
|
|
2704
|
+
} else {
|
|
2705
|
+
const qualifierMatch = value.match(
|
|
2706
|
+
/^(?<qualifier>ABT|ABOUT|BEF|BEFORE|AFT|AFTER)\b\s*/i
|
|
2707
|
+
);
|
|
2708
|
+
const qualifier = qualifierMatch?.groups?.qualifier?.toUpperCase();
|
|
2709
|
+
const note = qualifier ? STANDARD_QUALIFIERS[qualifier] : void 0;
|
|
2710
|
+
if (note) {
|
|
2711
|
+
this.NOTE = this.NOTE || createCommon(this._gedcom, void 0, this.main);
|
|
2712
|
+
this.NOTE.value = note;
|
|
2713
|
+
validValue = value.slice(qualifierMatch[0].length);
|
|
2714
|
+
}
|
|
2622
2715
|
}
|
|
2623
2716
|
const acceptedDate = this.isValidDateFormat(validValue);
|
|
2624
2717
|
if (acceptedDate) {
|
|
@@ -2724,7 +2817,23 @@ var CommonDate = class extends Common {
|
|
|
2724
2817
|
);
|
|
2725
2818
|
}
|
|
2726
2819
|
exportValue() {
|
|
2727
|
-
|
|
2820
|
+
const formatted = this.toValue("NOTE dd MMM yyyy", null);
|
|
2821
|
+
if (!formatted) {
|
|
2822
|
+
return formatted;
|
|
2823
|
+
}
|
|
2824
|
+
const note = this.NOTE?.value?.trim();
|
|
2825
|
+
const qualifier = note ? EXPORT_QUALIFIERS[note] : void 0;
|
|
2826
|
+
const standardized = qualifier ? formatted.replace(note, qualifier) : formatted;
|
|
2827
|
+
return standardized.replace(
|
|
2828
|
+
GEDCOM_MONTHS,
|
|
2829
|
+
(month) => month.toUpperCase()
|
|
2830
|
+
);
|
|
2831
|
+
}
|
|
2832
|
+
toGedcomLines(tag, level = 0, options) {
|
|
2833
|
+
const internal = new RegExp(
|
|
2834
|
+
`^${level} (DAY|MONTH|YEAR)( |$)|^${level} NOTE (Abt\\.|Bef\\.|Aft\\.)$`
|
|
2835
|
+
);
|
|
2836
|
+
return super.toGedcomLines(tag, level, options).filter((line) => !internal.test(line));
|
|
2728
2837
|
}
|
|
2729
2838
|
inRange(range, trueIfNoYear = false) {
|
|
2730
2839
|
return inRange(this.YEAR?.value, range, trueIfNoYear);
|
|
@@ -3049,6 +3158,135 @@ var profilePictureCache = (gedcom, key, value) => {
|
|
|
3049
3158
|
const cached = caches.profilePictureCache?.[fullKey];
|
|
3050
3159
|
return cached;
|
|
3051
3160
|
};
|
|
3161
|
+
var isNonBiologicalPath = (path) => path.some(
|
|
3162
|
+
(item) => item.relation && item.relation !== "biological" /* BIOLOGICAL */
|
|
3163
|
+
);
|
|
3164
|
+
var invertHop = (kinship) => {
|
|
3165
|
+
if (kinship === "parent") {
|
|
3166
|
+
return "child";
|
|
3167
|
+
}
|
|
3168
|
+
if (kinship === "child") {
|
|
3169
|
+
return "parent";
|
|
3170
|
+
}
|
|
3171
|
+
return kinship;
|
|
3172
|
+
};
|
|
3173
|
+
var hopRelation = (from, toIndi, kinship, inherited) => {
|
|
3174
|
+
if (kinship === "parent" || kinship === "child") {
|
|
3175
|
+
const parent = kinship === "parent" ? toIndi : from.indi;
|
|
3176
|
+
const child = kinship === "parent" ? from.indi : toIndi;
|
|
3177
|
+
const currentRelation = child.getParentType(parent);
|
|
3178
|
+
if (currentRelation && currentRelation !== "biological" /* BIOLOGICAL */) {
|
|
3179
|
+
return currentRelation;
|
|
3180
|
+
}
|
|
3181
|
+
}
|
|
3182
|
+
if (inherited && inherited !== "biological" /* BIOLOGICAL */) {
|
|
3183
|
+
return inherited;
|
|
3184
|
+
}
|
|
3185
|
+
return void 0;
|
|
3186
|
+
};
|
|
3187
|
+
var rebuildPathFromHops = (hops, skipRelation = false) => {
|
|
3188
|
+
if (hops.length === 0) {
|
|
3189
|
+
return [];
|
|
3190
|
+
}
|
|
3191
|
+
const path = [
|
|
3192
|
+
{
|
|
3193
|
+
indi: hops[0].indi,
|
|
3194
|
+
kinship: "self",
|
|
3195
|
+
level: 0,
|
|
3196
|
+
levelUp: 0,
|
|
3197
|
+
levelDown: 0,
|
|
3198
|
+
degree: 0
|
|
3199
|
+
}
|
|
3200
|
+
];
|
|
3201
|
+
for (let i = 1; i < hops.length; i++) {
|
|
3202
|
+
const prev = path[i - 1];
|
|
3203
|
+
const { indi, kinship } = hops[i];
|
|
3204
|
+
const relation = skipRelation ? void 0 : hopRelation(prev, indi, kinship, prev.relation);
|
|
3205
|
+
if (kinship === "parent") {
|
|
3206
|
+
path.push({
|
|
3207
|
+
indi,
|
|
3208
|
+
kinship,
|
|
3209
|
+
relation,
|
|
3210
|
+
level: prev.level + 1,
|
|
3211
|
+
levelUp: prev.levelUp + 1,
|
|
3212
|
+
levelDown: prev.levelDown,
|
|
3213
|
+
degree: prev.degree
|
|
3214
|
+
});
|
|
3215
|
+
continue;
|
|
3216
|
+
}
|
|
3217
|
+
if (kinship === "child") {
|
|
3218
|
+
path.push({
|
|
3219
|
+
indi,
|
|
3220
|
+
kinship,
|
|
3221
|
+
relation,
|
|
3222
|
+
level: prev.level - 1,
|
|
3223
|
+
levelUp: prev.levelUp,
|
|
3224
|
+
levelDown: prev.levelDown + 1,
|
|
3225
|
+
degree: prev.levelUp ? prev.level > 0 ? prev.levelUp - prev.level + 1 : prev.levelDown - Math.abs(prev.level) : 0
|
|
3226
|
+
});
|
|
3227
|
+
continue;
|
|
3228
|
+
}
|
|
3229
|
+
path.push({
|
|
3230
|
+
indi,
|
|
3231
|
+
kinship,
|
|
3232
|
+
relation,
|
|
3233
|
+
level: prev.level,
|
|
3234
|
+
levelUp: prev.levelUp,
|
|
3235
|
+
levelDown: prev.levelDown,
|
|
3236
|
+
degree: prev.degree
|
|
3237
|
+
});
|
|
3238
|
+
}
|
|
3239
|
+
return path;
|
|
3240
|
+
};
|
|
3241
|
+
var storePathIfBetter = (gedcom, fromId, toId, path) => {
|
|
3242
|
+
const key = `${fromId}|${toId}`;
|
|
3243
|
+
const existing = pathCache(gedcom, key);
|
|
3244
|
+
if (existing && (!isNonBiologicalPath(existing) || isNonBiologicalPath(path))) {
|
|
3245
|
+
return;
|
|
3246
|
+
}
|
|
3247
|
+
pathCache(gedcom, key, path);
|
|
3248
|
+
};
|
|
3249
|
+
var cacheDiscoveredPath = (gedcom, path) => {
|
|
3250
|
+
const n = path.length;
|
|
3251
|
+
if (n < 2) {
|
|
3252
|
+
return;
|
|
3253
|
+
}
|
|
3254
|
+
for (let i = 0; i < n; i++) {
|
|
3255
|
+
const fromId = path[i].indi.id;
|
|
3256
|
+
if (!fromId) {
|
|
3257
|
+
continue;
|
|
3258
|
+
}
|
|
3259
|
+
for (let j = i + 1; j < n; j++) {
|
|
3260
|
+
const toId = path[j].indi.id;
|
|
3261
|
+
if (!toId) {
|
|
3262
|
+
continue;
|
|
3263
|
+
}
|
|
3264
|
+
const isOriginalPair = i === 0 && j === n - 1;
|
|
3265
|
+
const isDirectHop = j === i + 1;
|
|
3266
|
+
const slice = path.slice(i, j + 1);
|
|
3267
|
+
const sliceMixed = isNonBiologicalPath(slice);
|
|
3268
|
+
if (!isOriginalPair && !isDirectHop && sliceMixed) {
|
|
3269
|
+
continue;
|
|
3270
|
+
}
|
|
3271
|
+
const forward = i === 0 ? slice : rebuildPathFromHops(slice, !sliceMixed);
|
|
3272
|
+
const reverseHops = [
|
|
3273
|
+
{
|
|
3274
|
+
indi: slice[slice.length - 1].indi,
|
|
3275
|
+
kinship: "self"
|
|
3276
|
+
}
|
|
3277
|
+
];
|
|
3278
|
+
for (let k = slice.length - 2; k >= 0; k--) {
|
|
3279
|
+
reverseHops.push({
|
|
3280
|
+
indi: slice[k].indi,
|
|
3281
|
+
kinship: invertHop(slice[k + 1].kinship)
|
|
3282
|
+
});
|
|
3283
|
+
}
|
|
3284
|
+
const reverse = rebuildPathFromHops(reverseHops, !sliceMixed);
|
|
3285
|
+
storePathIfBetter(gedcom, fromId, toId, forward);
|
|
3286
|
+
storePathIfBetter(gedcom, toId, fromId, reverse);
|
|
3287
|
+
}
|
|
3288
|
+
}
|
|
3289
|
+
};
|
|
3052
3290
|
|
|
3053
3291
|
// src/utils/get-places.ts
|
|
3054
3292
|
var getPlaces = (common, type = ["ALL" /* All */], maxLevel = 1, level = 0, mainKey) => {
|
|
@@ -5069,7 +5307,6 @@ var Indi = class extends Common {
|
|
|
5069
5307
|
if (cache) {
|
|
5070
5308
|
return cache;
|
|
5071
5309
|
}
|
|
5072
|
-
const visited = new Individuals().append(this);
|
|
5073
5310
|
const mainItem = {
|
|
5074
5311
|
indi: this,
|
|
5075
5312
|
level: 0,
|
|
@@ -5078,129 +5315,155 @@ var Indi = class extends Common {
|
|
|
5078
5315
|
degree: 0,
|
|
5079
5316
|
kinship: "self"
|
|
5080
5317
|
};
|
|
5081
|
-
const
|
|
5318
|
+
const mainPath = [mainItem];
|
|
5082
5319
|
if (this.id === usedIndi.id) {
|
|
5083
|
-
return
|
|
5320
|
+
return mainPath;
|
|
5084
5321
|
}
|
|
5085
|
-
const
|
|
5086
|
-
|
|
5087
|
-
|
|
5088
|
-
|
|
5089
|
-
|
|
5090
|
-
|
|
5091
|
-
let helper = 0;
|
|
5092
|
-
while (queue.length > 0) {
|
|
5093
|
-
if (helper++ > 1e6) {
|
|
5094
|
-
break;
|
|
5095
|
-
}
|
|
5096
|
-
const {
|
|
5097
|
-
indi,
|
|
5098
|
-
path: path2,
|
|
5099
|
-
kinship,
|
|
5100
|
-
relation,
|
|
5101
|
-
level,
|
|
5102
|
-
levelUp,
|
|
5103
|
-
levelDown,
|
|
5104
|
-
degree,
|
|
5105
|
-
breakOnNext,
|
|
5106
|
-
breakAfterNext,
|
|
5107
|
-
inLaw
|
|
5108
|
-
} = queue.shift();
|
|
5109
|
-
if (usedIndi.id === indi.id) {
|
|
5110
|
-
if (breakOnNext) {
|
|
5111
|
-
return void 0;
|
|
5322
|
+
const bfs = (biologicalOnly) => {
|
|
5323
|
+
const visited = new Individuals().append(this);
|
|
5324
|
+
const queue = [
|
|
5325
|
+
{
|
|
5326
|
+
...mainItem,
|
|
5327
|
+
path: mainPath
|
|
5112
5328
|
}
|
|
5113
|
-
|
|
5114
|
-
|
|
5115
|
-
|
|
5116
|
-
|
|
5117
|
-
|
|
5118
|
-
if (breakOnNext || breakAfterNext) {
|
|
5119
|
-
additional.breakOnNext = breakOnNext || breakAfterNext;
|
|
5120
|
-
}
|
|
5121
|
-
if (inLaw) {
|
|
5122
|
-
additional.inLaw = inLaw;
|
|
5123
|
-
}
|
|
5124
|
-
if (kinship === "spouse" && breakAfterSpouse) {
|
|
5125
|
-
if (path2.length <= 2) {
|
|
5126
|
-
additional.inLaw = true;
|
|
5127
|
-
} else {
|
|
5128
|
-
additional.breakOnNext = true;
|
|
5329
|
+
];
|
|
5330
|
+
let helper = 0;
|
|
5331
|
+
while (queue.length > 0) {
|
|
5332
|
+
if (helper++ > 1e6) {
|
|
5333
|
+
break;
|
|
5129
5334
|
}
|
|
5130
|
-
|
|
5131
|
-
|
|
5132
|
-
|
|
5335
|
+
const {
|
|
5336
|
+
indi,
|
|
5337
|
+
path,
|
|
5338
|
+
kinship,
|
|
5339
|
+
relation,
|
|
5340
|
+
level,
|
|
5341
|
+
levelUp,
|
|
5342
|
+
levelDown,
|
|
5343
|
+
degree,
|
|
5344
|
+
breakOnNext,
|
|
5345
|
+
breakAfterNext,
|
|
5346
|
+
inLaw
|
|
5347
|
+
} = queue.shift();
|
|
5348
|
+
if (usedIndi.id === indi.id) {
|
|
5349
|
+
if (breakOnNext) {
|
|
5350
|
+
return void 0;
|
|
5351
|
+
}
|
|
5352
|
+
return path;
|
|
5353
|
+
}
|
|
5354
|
+
visited.append(indi);
|
|
5355
|
+
const additional = {};
|
|
5356
|
+
if (breakOnNext || breakAfterNext) {
|
|
5357
|
+
additional.breakOnNext = breakOnNext || breakAfterNext;
|
|
5358
|
+
}
|
|
5359
|
+
if (inLaw) {
|
|
5360
|
+
additional.inLaw = inLaw;
|
|
5361
|
+
}
|
|
5362
|
+
if (!biologicalOnly && kinship === "spouse" && breakAfterSpouse) {
|
|
5363
|
+
if (path.length <= 2) {
|
|
5364
|
+
additional.inLaw = true;
|
|
5365
|
+
} else {
|
|
5366
|
+
additional.breakOnNext = true;
|
|
5367
|
+
}
|
|
5368
|
+
}
|
|
5369
|
+
if (kinship !== "child" || !breakAfterSpouse) {
|
|
5370
|
+
indi.getBiologicalFathers().copy().merge(indi.getBiologicalMothers()).merge(indi.getFathers().copy().merge(indi.getMothers())).forEach((relative) => {
|
|
5371
|
+
if (!visited.has(relative)) {
|
|
5372
|
+
const currentRelation = indi.getParentType(relative);
|
|
5373
|
+
const isNonBiological = !!currentRelation && currentRelation !== "biological" /* BIOLOGICAL */;
|
|
5374
|
+
if (biologicalOnly && isNonBiological) {
|
|
5375
|
+
return;
|
|
5376
|
+
}
|
|
5377
|
+
if (!biologicalOnly && breakAfterNonBiological && isNonBiological) {
|
|
5378
|
+
additional.breakAfterNext = true;
|
|
5379
|
+
}
|
|
5380
|
+
const newItem = {
|
|
5381
|
+
indi: relative,
|
|
5382
|
+
kinship: "parent",
|
|
5383
|
+
relation: isNonBiological ? currentRelation : relation,
|
|
5384
|
+
level: level + 1,
|
|
5385
|
+
levelUp: levelUp + 1,
|
|
5386
|
+
levelDown,
|
|
5387
|
+
degree,
|
|
5388
|
+
...additional
|
|
5389
|
+
};
|
|
5390
|
+
queue.push({
|
|
5391
|
+
...newItem,
|
|
5392
|
+
path: [...path, newItem]
|
|
5393
|
+
});
|
|
5394
|
+
}
|
|
5395
|
+
});
|
|
5396
|
+
}
|
|
5397
|
+
indi.getChildren().forEach((relative) => {
|
|
5133
5398
|
if (!visited.has(relative)) {
|
|
5134
|
-
const currentRelation =
|
|
5135
|
-
|
|
5399
|
+
const currentRelation = relative.getParentType(indi);
|
|
5400
|
+
const isNonBiological = !!currentRelation && currentRelation !== "biological" /* BIOLOGICAL */;
|
|
5401
|
+
if (biologicalOnly && isNonBiological) {
|
|
5402
|
+
return;
|
|
5403
|
+
}
|
|
5404
|
+
if (!biologicalOnly && breakAfterNonBiological && isNonBiological) {
|
|
5136
5405
|
additional.breakAfterNext = true;
|
|
5137
5406
|
}
|
|
5138
5407
|
const newItem = {
|
|
5139
5408
|
indi: relative,
|
|
5140
|
-
kinship: "
|
|
5141
|
-
relation:
|
|
5142
|
-
level: level
|
|
5143
|
-
levelUp
|
|
5144
|
-
levelDown,
|
|
5145
|
-
degree,
|
|
5409
|
+
kinship: "child",
|
|
5410
|
+
relation: isNonBiological ? currentRelation : relation,
|
|
5411
|
+
level: level - 1,
|
|
5412
|
+
levelUp,
|
|
5413
|
+
levelDown: levelDown + 1,
|
|
5414
|
+
degree: levelUp ? level > 0 ? levelUp - level + 1 : levelDown - Math.abs(level) : 0,
|
|
5146
5415
|
...additional
|
|
5147
5416
|
};
|
|
5148
5417
|
queue.push({
|
|
5149
5418
|
...newItem,
|
|
5150
|
-
path: [...
|
|
5419
|
+
path: [...path, newItem]
|
|
5151
5420
|
});
|
|
5152
5421
|
}
|
|
5153
5422
|
});
|
|
5154
|
-
|
|
5155
|
-
|
|
5156
|
-
if (!visited.has(relative)) {
|
|
5157
|
-
const currentRelation = relative.getParentType(indi);
|
|
5158
|
-
if (breakAfterNonBiological && currentRelation !== "biological" /* BIOLOGICAL */) {
|
|
5159
|
-
additional.breakAfterNext = true;
|
|
5160
|
-
}
|
|
5161
|
-
const newItem = {
|
|
5162
|
-
indi: relative,
|
|
5163
|
-
kinship: "child",
|
|
5164
|
-
relation: currentRelation && currentRelation !== "biological" /* BIOLOGICAL */ ? currentRelation : relation,
|
|
5165
|
-
level: level - 1,
|
|
5166
|
-
levelUp,
|
|
5167
|
-
levelDown: levelDown + 1,
|
|
5168
|
-
degree: levelUp ? level > 0 ? levelUp - level + 1 : levelDown - Math.abs(level) : 0,
|
|
5169
|
-
...additional
|
|
5170
|
-
};
|
|
5171
|
-
queue.push({
|
|
5172
|
-
...newItem,
|
|
5173
|
-
path: [...path2, newItem]
|
|
5174
|
-
});
|
|
5423
|
+
if (biologicalOnly) {
|
|
5424
|
+
continue;
|
|
5175
5425
|
}
|
|
5176
|
-
|
|
5177
|
-
|
|
5178
|
-
|
|
5179
|
-
|
|
5180
|
-
|
|
5181
|
-
|
|
5182
|
-
|
|
5183
|
-
|
|
5184
|
-
|
|
5426
|
+
indi.getCoParents().forEach((relative) => {
|
|
5427
|
+
if (!visited.has(relative)) {
|
|
5428
|
+
const currentAddition = {};
|
|
5429
|
+
if (relation && relation !== "biological" /* BIOLOGICAL */) {
|
|
5430
|
+
currentAddition.relation = relation;
|
|
5431
|
+
}
|
|
5432
|
+
if (inLaw) {
|
|
5433
|
+
currentAddition.breakOnNext = true;
|
|
5434
|
+
}
|
|
5435
|
+
const newItem = {
|
|
5436
|
+
indi: relative,
|
|
5437
|
+
kinship: "spouse",
|
|
5438
|
+
level,
|
|
5439
|
+
levelUp,
|
|
5440
|
+
levelDown,
|
|
5441
|
+
degree,
|
|
5442
|
+
...additional,
|
|
5443
|
+
...currentAddition
|
|
5444
|
+
};
|
|
5445
|
+
queue.push({
|
|
5446
|
+
...newItem,
|
|
5447
|
+
path: [...path, newItem]
|
|
5448
|
+
});
|
|
5185
5449
|
}
|
|
5186
|
-
|
|
5187
|
-
|
|
5188
|
-
|
|
5189
|
-
|
|
5190
|
-
|
|
5191
|
-
|
|
5192
|
-
|
|
5193
|
-
|
|
5194
|
-
|
|
5195
|
-
|
|
5196
|
-
|
|
5197
|
-
|
|
5198
|
-
path: [...path2, newItem]
|
|
5199
|
-
});
|
|
5200
|
-
}
|
|
5201
|
-
});
|
|
5450
|
+
});
|
|
5451
|
+
}
|
|
5452
|
+
return void 0;
|
|
5453
|
+
};
|
|
5454
|
+
const foundPath = bfs(false);
|
|
5455
|
+
const lastItem = foundPath?.[foundPath.length - 1];
|
|
5456
|
+
if (lastItem?.relation && lastItem.relation !== "biological" /* BIOLOGICAL */) {
|
|
5457
|
+
const biologicalPath = bfs(true);
|
|
5458
|
+
if (biologicalPath) {
|
|
5459
|
+
cacheDiscoveredPath(this._gedcom, biologicalPath);
|
|
5460
|
+
return biologicalPath;
|
|
5461
|
+
}
|
|
5202
5462
|
}
|
|
5203
|
-
|
|
5463
|
+
if (foundPath) {
|
|
5464
|
+
cacheDiscoveredPath(this._gedcom, foundPath);
|
|
5465
|
+
}
|
|
5466
|
+
return foundPath;
|
|
5204
5467
|
}
|
|
5205
5468
|
kinship(other, showMainPerson, lang = "en", entirePath, displayName = "givenname") {
|
|
5206
5469
|
const KinshipTranslatorClass2 = getKinshipTranslatorClass();
|
|
@@ -6128,20 +6391,22 @@ var KinshipTranslatorDe = class extends KinshipTranslatorBasic {
|
|
|
6128
6391
|
return `${prefix}kind`;
|
|
6129
6392
|
}
|
|
6130
6393
|
sibling() {
|
|
6131
|
-
const parents1 = this.person1?.getBiologicalParents();
|
|
6132
|
-
const parentsN = this.personN?.getBiologicalParents();
|
|
6133
|
-
const inter = parents1?.intersection(parentsN);
|
|
6134
|
-
let prefix = "";
|
|
6135
|
-
if (!inter || inter.length < 2) {
|
|
6136
|
-
prefix = "Halb";
|
|
6137
|
-
}
|
|
6138
6394
|
if (this.personN?.isMale()) {
|
|
6139
|
-
return
|
|
6395
|
+
return "bruder";
|
|
6140
6396
|
}
|
|
6141
6397
|
if (this.personN?.isFemale()) {
|
|
6142
|
-
return
|
|
6398
|
+
return "schwester";
|
|
6399
|
+
}
|
|
6400
|
+
return "geschwister";
|
|
6401
|
+
}
|
|
6402
|
+
halfBlood(relation) {
|
|
6403
|
+
if (!relation || !this.isHalfBlood) {
|
|
6404
|
+
return relation ?? "";
|
|
6405
|
+
}
|
|
6406
|
+
if (/^[A-ZÄÖÜ]/.test(relation) || /[-\s]/.test(relation)) {
|
|
6407
|
+
return `Halb-${relation}`;
|
|
6143
6408
|
}
|
|
6144
|
-
return
|
|
6409
|
+
return `Halb${relation}`;
|
|
6145
6410
|
}
|
|
6146
6411
|
spouse() {
|
|
6147
6412
|
if (this.personN?.isMale()) {
|