@treeviz/gedcom-parser 2.0.8 → 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.
Files changed (27) hide show
  1. package/dist/classes/index.js +382 -158
  2. package/dist/classes/indi.d.ts.map +1 -1
  3. package/dist/cli/index.js +382 -158
  4. package/dist/constants/index.js +381 -157
  5. package/dist/factories/index.js +381 -157
  6. package/dist/index.js +383 -159
  7. package/dist/kinship-translator/index.js +381 -157
  8. package/dist/kinship-translator/kinship-translator.basic.d.ts +11 -0
  9. package/dist/kinship-translator/kinship-translator.basic.d.ts.map +1 -1
  10. package/dist/kinship-translator/kinship-translator.d.ts.map +1 -1
  11. package/dist/kinship-translator/kinship-translator.de.d.ts +2 -1
  12. package/dist/kinship-translator/kinship-translator.de.d.ts.map +1 -1
  13. package/dist/kinship-translator/kinship-translator.en.d.ts +2 -1
  14. package/dist/kinship-translator/kinship-translator.en.d.ts.map +1 -1
  15. package/dist/kinship-translator/kinship-translator.es.d.ts +2 -1
  16. package/dist/kinship-translator/kinship-translator.es.d.ts.map +1 -1
  17. package/dist/kinship-translator/kinship-translator.fr.d.ts +2 -1
  18. package/dist/kinship-translator/kinship-translator.fr.d.ts.map +1 -1
  19. package/dist/kinship-translator/kinship-translator.hu.d.ts +8 -1
  20. package/dist/kinship-translator/kinship-translator.hu.d.ts.map +1 -1
  21. package/dist/kinship-translator/kinship-translator.interface.d.ts +1 -0
  22. package/dist/kinship-translator/kinship-translator.interface.d.ts.map +1 -1
  23. package/dist/kinship-translator/patterns.es.d.ts.map +1 -1
  24. package/dist/utils/cache.d.ts +14 -1
  25. package/dist/utils/cache.d.ts.map +1 -1
  26. package/dist/utils/index.js +383 -159
  27. 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 `${prefix}brother`;
753
+ return "brother";
700
754
  }
701
755
  if (this.personN?.isFemale()) {
702
- return `${prefix}sister`;
756
+ return "sister";
703
757
  }
704
- return `${prefix}sibling`;
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 `${prefix}fr\xE8re`;
950
+ return "fr\xE8re";
895
951
  }
896
952
  if (this.personN?.isFemale()) {
897
- return `${prefix}s\u0153ur`;
953
+ return "s\u0153ur";
954
+ }
955
+ return "fr\xE8re/s\u0153ur";
956
+ }
957
+ halfBlood(relation) {
958
+ if (!relation || !this.isHalfBlood) {
959
+ return relation ?? "";
898
960
  }
899
- return `${prefix}fr\xE8re/s\u0153ur`;
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 `${prefix}hermano`;
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 `${prefix}hermana`;
1156
+ return `media ${relation}`;
1093
1157
  }
1094
- return `${prefix}hermano/hermana`;
1158
+ if (this.personN?.isMale()) {
1159
+ return `medio ${relation}`;
1160
+ }
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);
@@ -3090,6 +3158,135 @@ var profilePictureCache = (gedcom, key, value) => {
3090
3158
  const cached = caches.profilePictureCache?.[fullKey];
3091
3159
  return cached;
3092
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
+ };
3093
3290
 
3094
3291
  // src/utils/get-places.ts
3095
3292
  var getPlaces = (common, type = ["ALL" /* All */], maxLevel = 1, level = 0, mainKey) => {
@@ -5110,7 +5307,6 @@ var Indi = class extends Common {
5110
5307
  if (cache) {
5111
5308
  return cache;
5112
5309
  }
5113
- const visited = new Individuals().append(this);
5114
5310
  const mainItem = {
5115
5311
  indi: this,
5116
5312
  level: 0,
@@ -5119,129 +5315,155 @@ var Indi = class extends Common {
5119
5315
  degree: 0,
5120
5316
  kinship: "self"
5121
5317
  };
5122
- const path = [mainItem];
5318
+ const mainPath = [mainItem];
5123
5319
  if (this.id === usedIndi.id) {
5124
- return path;
5320
+ return mainPath;
5125
5321
  }
5126
- const queue = [
5127
- {
5128
- ...mainItem,
5129
- path
5130
- }
5131
- ];
5132
- let helper = 0;
5133
- while (queue.length > 0) {
5134
- if (helper++ > 1e6) {
5135
- break;
5136
- }
5137
- const {
5138
- indi,
5139
- path: path2,
5140
- kinship,
5141
- relation,
5142
- level,
5143
- levelUp,
5144
- levelDown,
5145
- degree,
5146
- breakOnNext,
5147
- breakAfterNext,
5148
- inLaw
5149
- } = queue.shift();
5150
- if (usedIndi.id === indi.id) {
5151
- if (breakOnNext) {
5152
- return void 0;
5322
+ const bfs = (biologicalOnly) => {
5323
+ const visited = new Individuals().append(this);
5324
+ const queue = [
5325
+ {
5326
+ ...mainItem,
5327
+ path: mainPath
5153
5328
  }
5154
- pathCache(this._gedcom, cacheKey, path2);
5155
- return path2;
5156
- }
5157
- visited.append(indi);
5158
- const additional = {};
5159
- if (breakOnNext || breakAfterNext) {
5160
- additional.breakOnNext = breakOnNext || breakAfterNext;
5161
- }
5162
- if (inLaw) {
5163
- additional.inLaw = inLaw;
5164
- }
5165
- if (kinship === "spouse" && breakAfterSpouse) {
5166
- if (path2.length <= 2) {
5167
- additional.inLaw = true;
5168
- } else {
5169
- additional.breakOnNext = true;
5329
+ ];
5330
+ let helper = 0;
5331
+ while (queue.length > 0) {
5332
+ if (helper++ > 1e6) {
5333
+ break;
5170
5334
  }
5171
- }
5172
- if (kinship !== "child" || !breakAfterSpouse) {
5173
- indi.getBiologicalFathers().copy().merge(indi.getBiologicalMothers()).merge(indi.getFathers().copy().merge(indi.getMothers())).forEach((relative) => {
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) => {
5174
5398
  if (!visited.has(relative)) {
5175
- const currentRelation = indi.getParentType(relative);
5176
- if (breakAfterNonBiological && currentRelation !== "biological" /* BIOLOGICAL */) {
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) {
5177
5405
  additional.breakAfterNext = true;
5178
5406
  }
5179
5407
  const newItem = {
5180
5408
  indi: relative,
5181
- kinship: "parent",
5182
- relation: currentRelation && currentRelation !== "biological" /* BIOLOGICAL */ ? currentRelation : relation,
5183
- level: level + 1,
5184
- levelUp: levelUp + 1,
5185
- levelDown,
5186
- 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,
5187
5415
  ...additional
5188
5416
  };
5189
5417
  queue.push({
5190
5418
  ...newItem,
5191
- path: [...path2, newItem]
5419
+ path: [...path, newItem]
5192
5420
  });
5193
5421
  }
5194
5422
  });
5195
- }
5196
- indi.getChildren().forEach((relative) => {
5197
- if (!visited.has(relative)) {
5198
- const currentRelation = relative.getParentType(indi);
5199
- if (breakAfterNonBiological && currentRelation !== "biological" /* BIOLOGICAL */) {
5200
- additional.breakAfterNext = true;
5201
- }
5202
- const newItem = {
5203
- indi: relative,
5204
- kinship: "child",
5205
- relation: currentRelation && currentRelation !== "biological" /* BIOLOGICAL */ ? currentRelation : relation,
5206
- level: level - 1,
5207
- levelUp,
5208
- levelDown: levelDown + 1,
5209
- degree: levelUp ? level > 0 ? levelUp - level + 1 : levelDown - Math.abs(level) : 0,
5210
- ...additional
5211
- };
5212
- queue.push({
5213
- ...newItem,
5214
- path: [...path2, newItem]
5215
- });
5423
+ if (biologicalOnly) {
5424
+ continue;
5216
5425
  }
5217
- });
5218
- indi.getCoParents().forEach((relative) => {
5219
- if (!visited.has(relative)) {
5220
- const currentAddition = {};
5221
- if (relation && relation !== "biological" /* BIOLOGICAL */) {
5222
- currentAddition.relation = relation;
5223
- }
5224
- if (inLaw) {
5225
- currentAddition.breakOnNext = true;
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
+ });
5226
5449
  }
5227
- const newItem = {
5228
- indi: relative,
5229
- kinship: "spouse",
5230
- level,
5231
- levelUp,
5232
- levelDown,
5233
- degree,
5234
- ...additional,
5235
- ...currentAddition
5236
- };
5237
- queue.push({
5238
- ...newItem,
5239
- path: [...path2, newItem]
5240
- });
5241
- }
5242
- });
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
+ }
5243
5462
  }
5244
- return void 0;
5463
+ if (foundPath) {
5464
+ cacheDiscoveredPath(this._gedcom, foundPath);
5465
+ }
5466
+ return foundPath;
5245
5467
  }
5246
5468
  kinship(other, showMainPerson, lang = "en", entirePath, displayName = "givenname") {
5247
5469
  const KinshipTranslatorClass2 = getKinshipTranslatorClass();
@@ -6169,20 +6391,22 @@ var KinshipTranslatorDe = class extends KinshipTranslatorBasic {
6169
6391
  return `${prefix}kind`;
6170
6392
  }
6171
6393
  sibling() {
6172
- const parents1 = this.person1?.getBiologicalParents();
6173
- const parentsN = this.personN?.getBiologicalParents();
6174
- const inter = parents1?.intersection(parentsN);
6175
- let prefix = "";
6176
- if (!inter || inter.length < 2) {
6177
- prefix = "Halb";
6178
- }
6179
6394
  if (this.personN?.isMale()) {
6180
- return `${prefix}bruder`;
6395
+ return "bruder";
6181
6396
  }
6182
6397
  if (this.personN?.isFemale()) {
6183
- return `${prefix}schwester`;
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}`;
6184
6408
  }
6185
- return `${prefix}geschwister`;
6409
+ return `Halb${relation}`;
6186
6410
  }
6187
6411
  spouse() {
6188
6412
  if (this.personN?.isMale()) {
@@ -15,6 +15,16 @@ export default class KinshipTranslatorBasic implements IKinshipTranslator {
15
15
  get person2(): import("..").IndiType | undefined;
16
16
  get personM(): import("..").IndiType | undefined;
17
17
  get personN(): import("..").IndiType | undefined;
18
+ /**
19
+ * True when the path goes through a common ancestor whose two children
20
+ * (the person we came from and the person we go to) share fewer than two
21
+ * biological parents — i.e. they are half-siblings, so every collateral
22
+ * relative on this path is a half-aunt/half-cousin/... too.
23
+ *
24
+ * Direct ancestors/descendants and paths that already use a
25
+ * step/adopted/foster edge are never half-blood.
26
+ */
27
+ protected get isHalfBlood(): boolean;
18
28
  indirect(): string;
19
29
  removal(): string;
20
30
  parent(): string;
@@ -24,6 +34,7 @@ export default class KinshipTranslatorBasic implements IKinshipTranslator {
24
34
  ofSpouse(relation?: string | undefined): string;
25
35
  spouseOf(relation?: string | undefined): string;
26
36
  relationType(relation?: string | undefined): string;
37
+ halfBlood(relation?: string | undefined): string;
27
38
  of(relation?: string | undefined): string;
28
39
  inLaw(relation?: string | undefined): string;
29
40
  }
@@ -1 +1 @@
1
- {"version":3,"file":"kinship-translator.basic.d.ts","sourceRoot":"","sources":["../../src/kinship-translator/kinship-translator.basic.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,IAAI,EAAC,MAAM,iBAAiB,CAAC;AAE1C,OAAO,KAAK,kBAAkB,MAAM,gCAAgC,CAAC;AAErE,MAAM,CAAC,OAAO,OAAO,sBAAuB,YAAW,kBAAkB;IACxE,UAAU,UAAS;IACnB,UAAU,UAAS;IACnB,WAAW,EAAE,MAAM,GAAG,WAAW,GAAG,SAAS,GAAG,KAAK,CAAC;IAEtD,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAO;gBAE7B,IAAI,EAAE,IAAI,EACV,WAAW,GAAE,MAAM,GAAG,WAAW,GAAG,SAAS,GAAG,KAAmB;IAMpE,SAAS,KAAK,IAAI,qBAEjB;IAED,IAAI,KAAK,sCAER;IAED,IAAI,KAAK,sCAER;IAED,IAAI,KAAK,sCAER;IAED,IAAI,KAAK,sCAER;IAED,IAAI,OAAO,sCAMV;IAED,IAAI,OAAO,sCAEV;IAED,IAAI,OAAO,sCAEV;IAED,IAAI,OAAO,sCAMV;IAED,QAAQ;IAIR,OAAO;IAIP,MAAM;IAIN,KAAK;IAIL,OAAO;IAIP,MAAM;IAIN,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS;IAItC,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS;IAItC,YAAY,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS;IAI1C,EAAE,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS;IAIhC,KAAK,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS;CAGnC"}
1
+ {"version":3,"file":"kinship-translator.basic.d.ts","sourceRoot":"","sources":["../../src/kinship-translator/kinship-translator.basic.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,IAAI,EAAC,MAAM,iBAAiB,CAAC;AAG1C,OAAO,KAAK,kBAAkB,MAAM,gCAAgC,CAAC;AAErE,MAAM,CAAC,OAAO,OAAO,sBAAuB,YAAW,kBAAkB;IACxE,UAAU,UAAS;IACnB,UAAU,UAAS;IACnB,WAAW,EAAE,MAAM,GAAG,WAAW,GAAG,SAAS,GAAG,KAAK,CAAC;IAEtD,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAO;gBAE7B,IAAI,EAAE,IAAI,EACV,WAAW,GAAE,MAAM,GAAG,WAAW,GAAG,SAAS,GAAG,KAAmB;IAMpE,SAAS,KAAK,IAAI,qBAEjB;IAED,IAAI,KAAK,sCAER;IAED,IAAI,KAAK,sCAER;IAED,IAAI,KAAK,sCAER;IAED,IAAI,KAAK,sCAER;IAED,IAAI,OAAO,sCAMV;IAED,IAAI,OAAO,sCAEV;IAED,IAAI,OAAO,sCAEV;IAED,IAAI,OAAO,sCAMV;IAED;;;;;;;;OAQG;IACH,SAAS,KAAK,WAAW,IAAI,OAAO,CA0CnC;IAED,QAAQ;IAIR,OAAO;IAIP,MAAM;IAIN,KAAK;IAIL,OAAO;IAIP,MAAM;IAIN,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS;IAItC,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS;IAItC,YAAY,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS;IAI1C,SAAS,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS;IAIvC,EAAE,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS;IAIhC,KAAK,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS;CAGnC"}
@@ -1 +1 @@
1
- {"version":3,"file":"kinship-translator.d.ts","sourceRoot":"","sources":["../../src/kinship-translator/kinship-translator.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAO,QAAQ,EAAC,MAAM,iBAAiB,CAAC;AACpD,OAAO,KAAK,EAAC,OAAO,EAAC,MAAM,gBAAgB,CAAC;AAI5C,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAExC,MAAM,CAAC,OAAO,OAAO,iBAAiB,CAAC,CAAC,SAAS,OAAO,GAAG,SAAS;IACnE,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAqB;IACjD,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAW;IACnC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAW;IACpC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAO;IAC7B,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAI;IAChC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAW;IAChC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAA2C;gBAEtE,OAAO,EAAE,QAAQ,EACjB,OAAO,CAAC,EAAE,QAAQ,GAAG,OAAO,EAC5B,IAAI,GAAE,QAAe,EACrB,UAAU,CAAC,EAAE,CAAC,EACd,WAAW,GAAE,MAAM,GAAG,WAAW,GAAG,SAAS,GAAG,KAAmB;IA2BpE,IAAI,KAAK,sCAER;IAED,IAAI,KAAK,sCAER;IAED,IAAI,KAAK,sCAER;IAED,IAAI,KAAK,sCAER;IAED,MAAM;IAkBN,QAAQ;IAIR,OAAO;IAIP,SAAS,CAAC,cAAc,CAAC,EAAE,OAAO;aAoBhB,OAAO;mBAAa,MAAM;mBAAa,MAAM;;CAsD/D"}
1
+ {"version":3,"file":"kinship-translator.d.ts","sourceRoot":"","sources":["../../src/kinship-translator/kinship-translator.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAO,QAAQ,EAAC,MAAM,iBAAiB,CAAC;AACpD,OAAO,KAAK,EAAC,OAAO,EAAC,MAAM,gBAAgB,CAAC;AAI5C,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAExC,MAAM,CAAC,OAAO,OAAO,iBAAiB,CAAC,CAAC,SAAS,OAAO,GAAG,SAAS;IACnE,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAqB;IACjD,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAW;IACnC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAW;IACpC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAO;IAC7B,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAI;IAChC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAW;IAChC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAA2C;gBAEtE,OAAO,EAAE,QAAQ,EACjB,OAAO,CAAC,EAAE,QAAQ,GAAG,OAAO,EAC5B,IAAI,GAAE,QAAe,EACrB,UAAU,CAAC,EAAE,CAAC,EACd,WAAW,GAAE,MAAM,GAAG,WAAW,GAAG,SAAS,GAAG,KAAmB;IA2BpE,IAAI,KAAK,sCAER;IAED,IAAI,KAAK,sCAER;IAED,IAAI,KAAK,sCAER;IAED,IAAI,KAAK,sCAER;IAED,MAAM;IAkBN,QAAQ;IAIR,OAAO;IAIP,SAAS,CAAC,cAAc,CAAC,EAAE,OAAO;aAoBhB,OAAO;mBAAa,MAAM;mBAAa,MAAM;;CAwD/D"}