@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.
Files changed (29) hide show
  1. package/dist/classes/date.d.ts +2 -0
  2. package/dist/classes/date.d.ts.map +1 -1
  3. package/dist/classes/index.js +424 -159
  4. package/dist/classes/indi.d.ts.map +1 -1
  5. package/dist/cli/index.js +424 -159
  6. package/dist/constants/index.js +423 -158
  7. package/dist/factories/index.js +423 -158
  8. package/dist/index.js +425 -160
  9. package/dist/kinship-translator/index.js +423 -158
  10. package/dist/kinship-translator/kinship-translator.basic.d.ts +11 -0
  11. package/dist/kinship-translator/kinship-translator.basic.d.ts.map +1 -1
  12. package/dist/kinship-translator/kinship-translator.d.ts.map +1 -1
  13. package/dist/kinship-translator/kinship-translator.de.d.ts +2 -1
  14. package/dist/kinship-translator/kinship-translator.de.d.ts.map +1 -1
  15. package/dist/kinship-translator/kinship-translator.en.d.ts +2 -1
  16. package/dist/kinship-translator/kinship-translator.en.d.ts.map +1 -1
  17. package/dist/kinship-translator/kinship-translator.es.d.ts +2 -1
  18. package/dist/kinship-translator/kinship-translator.es.d.ts.map +1 -1
  19. package/dist/kinship-translator/kinship-translator.fr.d.ts +2 -1
  20. package/dist/kinship-translator/kinship-translator.fr.d.ts.map +1 -1
  21. package/dist/kinship-translator/kinship-translator.hu.d.ts +8 -1
  22. package/dist/kinship-translator/kinship-translator.hu.d.ts.map +1 -1
  23. package/dist/kinship-translator/kinship-translator.interface.d.ts +1 -0
  24. package/dist/kinship-translator/kinship-translator.interface.d.ts.map +1 -1
  25. package/dist/kinship-translator/patterns.es.d.ts.map +1 -1
  26. package/dist/utils/cache.d.ts +14 -1
  27. package/dist/utils/cache.d.ts.map +1 -1
  28. package/dist/utils/index.js +425 -160
  29. package/package.json +1 -1
@@ -1347,6 +1347,44 @@ var KinshipTranslatorBasic = class {
1347
1347
  }
1348
1348
  return this.pathN?.indi;
1349
1349
  }
1350
+ /**
1351
+ * True when the path goes through a common ancestor whose two children
1352
+ * (the person we came from and the person we go to) share fewer than two
1353
+ * biological parents — i.e. they are half-siblings, so every collateral
1354
+ * relative on this path is a half-aunt/half-cousin/... too.
1355
+ *
1356
+ * Direct ancestors/descendants and paths that already use a
1357
+ * step/adopted/foster edge are never half-blood.
1358
+ */
1359
+ get isHalfBlood() {
1360
+ const path = this.path;
1361
+ if (!path || path.length < 3) {
1362
+ return false;
1363
+ }
1364
+ if (path.some(
1365
+ (item) => item.relation && item.relation !== "biological" /* BIOLOGICAL */
1366
+ )) {
1367
+ return false;
1368
+ }
1369
+ let peakIndex = -1;
1370
+ for (let i = 1; i < path.length; i++) {
1371
+ if (path[i].kinship === "parent") {
1372
+ peakIndex = i;
1373
+ }
1374
+ }
1375
+ if (peakIndex <= 0 || peakIndex >= path.length - 1) {
1376
+ return false;
1377
+ }
1378
+ if (path[peakIndex + 1].kinship !== "child") {
1379
+ return false;
1380
+ }
1381
+ const siblingA = path[peakIndex - 1].indi;
1382
+ const siblingB = path[peakIndex + 1].indi;
1383
+ const parentsA = siblingA.getBiologicalParents();
1384
+ const parentsB = siblingB.getBiologicalParents();
1385
+ const inter = parentsA.intersection(parentsB);
1386
+ return inter.length === 1 && (parentsA.length > 1 || parentsB.length > 1);
1387
+ }
1350
1388
  indirect() {
1351
1389
  return "";
1352
1390
  }
@@ -1374,6 +1412,9 @@ var KinshipTranslatorBasic = class {
1374
1412
  relationType(relation) {
1375
1413
  return relation ?? "";
1376
1414
  }
1415
+ halfBlood(relation) {
1416
+ return relation ?? "";
1417
+ }
1377
1418
  of(relation) {
1378
1419
  return relation ?? "";
1379
1420
  }
@@ -1612,14 +1653,34 @@ var KinshipTranslatorHU = class extends KinshipTranslatorBasic {
1612
1653
  return `${prefix.replace(/nagy$/, "")}unoka`;
1613
1654
  }
1614
1655
  sibling() {
1615
- const parents1 = this.person1?.getBiologicalParents();
1616
- const parentsN = this.personN?.getBiologicalParents();
1617
- const inter = parents1?.intersection(parentsN);
1618
- if (!inter || inter.length < 2) {
1619
- return "f\xE9ltestv\xE9r";
1620
- }
1621
1656
  return "testv\xE9r";
1622
1657
  }
1658
+ halfBlood(relation) {
1659
+ if (!relation || !this.isHalfBlood) {
1660
+ return relation ?? "";
1661
+ }
1662
+ const [head, ...rest] = relation.split(" ");
1663
+ if (!head) {
1664
+ return relation;
1665
+ }
1666
+ const prefixed = this.prefixHalf(head);
1667
+ return [prefixed, ...rest].join(" ");
1668
+ }
1669
+ /**
1670
+ * AkH. 139: compounds of more than two members stay closed up to 6
1671
+ * syllables; longer ones are hyphenated at the main boundary. A head
1672
+ * that is already hyphenated also takes a hyphenated half- prefix.
1673
+ */
1674
+ prefixHalf(head) {
1675
+ if (head.includes("-") || !/[aáeéiíoóöőuúüű]/i.test(head)) {
1676
+ return `f\xE9l-${head}`;
1677
+ }
1678
+ const syllables = (head.match(/[aáeéiíoóöőuúüű]/gi) ?? []).length + 1;
1679
+ if (syllables > 6) {
1680
+ return `f\xE9l-${head}`;
1681
+ }
1682
+ return `f\xE9l${head}`;
1683
+ }
1623
1684
  spouse() {
1624
1685
  if (this.personN?.isMale()) {
1625
1686
  return "f\xE9rj";
@@ -1818,20 +1879,22 @@ var KinshipTranslatorEn = class extends KinshipTranslatorBasic {
1818
1879
  return `${prefix}child`;
1819
1880
  }
1820
1881
  sibling() {
1821
- const parents1 = this.person1?.getBiologicalParents();
1822
- const parentsN = this.personN?.getBiologicalParents();
1823
- const inter = parents1?.intersection(parentsN);
1824
- let prefix = "";
1825
- if (!inter || inter.length < 2) {
1826
- prefix = "half-";
1827
- }
1828
1882
  if (this.personN?.isMale()) {
1829
- return `${prefix}brother`;
1883
+ return "brother";
1830
1884
  }
1831
1885
  if (this.personN?.isFemale()) {
1832
- return `${prefix}sister`;
1886
+ return "sister";
1833
1887
  }
1834
- return `${prefix}sibling`;
1888
+ return "sibling";
1889
+ }
1890
+ halfBlood(relation) {
1891
+ if (!relation || !this.isHalfBlood) {
1892
+ return relation ?? "";
1893
+ }
1894
+ if (relation.includes(" ")) {
1895
+ return `half ${relation}`;
1896
+ }
1897
+ return `half-${relation}`;
1835
1898
  }
1836
1899
  spouse() {
1837
1900
  if (this.personN?.isMale()) {
@@ -2013,20 +2076,22 @@ var KinshipTranslatorDe = class extends KinshipTranslatorBasic {
2013
2076
  return `${prefix}kind`;
2014
2077
  }
2015
2078
  sibling() {
2016
- const parents1 = this.person1?.getBiologicalParents();
2017
- const parentsN = this.personN?.getBiologicalParents();
2018
- const inter = parents1?.intersection(parentsN);
2019
- let prefix = "";
2020
- if (!inter || inter.length < 2) {
2021
- prefix = "Halb";
2022
- }
2023
2079
  if (this.personN?.isMale()) {
2024
- return `${prefix}bruder`;
2080
+ return "bruder";
2025
2081
  }
2026
2082
  if (this.personN?.isFemale()) {
2027
- return `${prefix}schwester`;
2083
+ return "schwester";
2028
2084
  }
2029
- return `${prefix}geschwister`;
2085
+ return "geschwister";
2086
+ }
2087
+ halfBlood(relation) {
2088
+ if (!relation || !this.isHalfBlood) {
2089
+ return relation ?? "";
2090
+ }
2091
+ if (/^[A-ZÄÖÜ]/.test(relation) || /[-\s]/.test(relation)) {
2092
+ return `Halb-${relation}`;
2093
+ }
2094
+ return `Halb${relation}`;
2030
2095
  }
2031
2096
  spouse() {
2032
2097
  if (this.personN?.isMale()) {
@@ -2208,20 +2273,19 @@ var KinshipTranslatorFr = class extends KinshipTranslatorBasic {
2208
2273
  return `${prefix}enfant`;
2209
2274
  }
2210
2275
  sibling() {
2211
- const parents1 = this.person1?.getBiologicalParents();
2212
- const parentsN = this.personN?.getBiologicalParents();
2213
- const inter = parents1?.intersection(parentsN);
2214
- let prefix = "";
2215
- if (!inter || inter.length < 2) {
2216
- prefix = "demi-";
2217
- }
2218
2276
  if (this.personN?.isMale()) {
2219
- return `${prefix}fr\xE8re`;
2277
+ return "fr\xE8re";
2220
2278
  }
2221
2279
  if (this.personN?.isFemale()) {
2222
- return `${prefix}s\u0153ur`;
2280
+ return "s\u0153ur";
2223
2281
  }
2224
- return `${prefix}fr\xE8re/s\u0153ur`;
2282
+ return "fr\xE8re/s\u0153ur";
2283
+ }
2284
+ halfBlood(relation) {
2285
+ if (!relation || !this.isHalfBlood) {
2286
+ return relation ?? "";
2287
+ }
2288
+ return `demi-${relation}`;
2225
2289
  }
2226
2290
  spouse() {
2227
2291
  if (this.personN?.isMale()) {
@@ -2318,12 +2382,12 @@ var InLawsEs = {
2318
2382
  "madre del (c\xF3nyuge|esposa|esposo)": "suegra",
2319
2383
  "padre del (c\xF3nyuge|esposa|esposo)": "suegro",
2320
2384
  "padre/madre del (c\xF3nyuge|esposa|esposo)": "suegro/suegra",
2321
- "esposa de (medio )?(hermano/hermana|hermana|hermano)": "cu\xF1ada",
2322
- "esposo de (medio )?(hermano/hermana|hermana|hermano)": "cu\xF1ado",
2323
- "c\xF3nyuge de (medio )?(hermano/hermana|hermana|hermano)": "cu\xF1ado/cu\xF1ada",
2324
- "(medio )?hermana del (c\xF3nyuge|esposa|esposo)": "cu\xF1ada",
2325
- "(medio )?hermano del (c\xF3nyuge|esposa|esposo)": "cu\xF1ado",
2326
- "(medio )?hermano/hermana del (c\xF3nyuge|esposa|esposo)": "cu\xF1ado/cu\xF1ada"
2385
+ "esposa de (medio |media |medio/a )?(hermano/hermana|hermana|hermano)": "cu\xF1ada",
2386
+ "esposo de (medio |media |medio/a )?(hermano/hermana|hermana|hermano)": "cu\xF1ado",
2387
+ "c\xF3nyuge de (medio |media |medio/a )?(hermano/hermana|hermana|hermano)": "cu\xF1ado/cu\xF1ada",
2388
+ "(medio |media |medio/a )?hermana del (c\xF3nyuge|esposa|esposo)": "cu\xF1ada",
2389
+ "(medio |media |medio/a )?hermano del (c\xF3nyuge|esposa|esposo)": "cu\xF1ado",
2390
+ "(medio |media |medio/a )?hermano/hermana del (c\xF3nyuge|esposa|esposo)": "cu\xF1ado/cu\xF1ada"
2327
2391
  };
2328
2392
 
2329
2393
  // src/kinship-translator/kinship-translator.es.ts
@@ -2403,20 +2467,25 @@ var KinshipTranslatorEs = class extends KinshipTranslatorBasic {
2403
2467
  return `${prefix}hijo/hija`;
2404
2468
  }
2405
2469
  sibling() {
2406
- const parents1 = this.person1?.getBiologicalParents();
2407
- const parentsN = this.personN?.getBiologicalParents();
2408
- const inter = parents1?.intersection(parentsN);
2409
- let prefix = "";
2410
- if (!inter || inter.length < 2) {
2411
- prefix = "medio ";
2412
- }
2413
2470
  if (this.personN?.isMale()) {
2414
- return `${prefix}hermano`;
2471
+ return "hermano";
2415
2472
  }
2416
2473
  if (this.personN?.isFemale()) {
2417
- return `${prefix}hermana`;
2474
+ return "hermana";
2418
2475
  }
2419
- return `${prefix}hermano/hermana`;
2476
+ return "hermano/hermana";
2477
+ }
2478
+ halfBlood(relation) {
2479
+ if (!relation || !this.isHalfBlood) {
2480
+ return relation ?? "";
2481
+ }
2482
+ if (this.personN?.isFemale()) {
2483
+ return `media ${relation}`;
2484
+ }
2485
+ if (this.personN?.isMale()) {
2486
+ return `medio ${relation}`;
2487
+ }
2488
+ return `medio/a ${relation}`;
2420
2489
  }
2421
2490
  spouse() {
2422
2491
  if (this.personN?.isMale()) {
@@ -2598,6 +2667,7 @@ var KinshipTranslator = class {
2598
2667
  } else if (personN.level !== 0) {
2599
2668
  relation = this.removal();
2600
2669
  }
2670
+ relation = this.translator?.halfBlood(relation);
2601
2671
  relation = this.translator?.relationType(relation);
2602
2672
  if (this.translator?.isOfSpouse) {
2603
2673
  relation = this.translator?.ofSpouse(relation);
@@ -2862,6 +2932,20 @@ var LONG_NOTES = {
2862
2932
  "Bef.": "Before",
2863
2933
  "Aft.": "After"
2864
2934
  };
2935
+ var STANDARD_QUALIFIERS = {
2936
+ ABT: "Abt.",
2937
+ ABOUT: "Abt.",
2938
+ BEF: "Bef.",
2939
+ BEFORE: "Bef.",
2940
+ AFT: "Aft.",
2941
+ AFTER: "Aft."
2942
+ };
2943
+ var EXPORT_QUALIFIERS = {
2944
+ "Abt.": "ABT",
2945
+ "Bef.": "BEF",
2946
+ "Aft.": "AFT"
2947
+ };
2948
+ var GEDCOM_MONTHS = /\b(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)\b/g;
2865
2949
  var NOTE_MARKER = "####";
2866
2950
  var formatDateWithComponents = (date, hasDay, hasMonth, hasYear, noteValue, baseFormat = "dd MMM yyyy", locale) => {
2867
2951
  const hasNote = baseFormat.includes("NOTE");
@@ -2895,6 +2979,17 @@ var CommonDate = class extends Common {
2895
2979
  this.NOTE = this.NOTE || createCommon(this._gedcom, void 0, this.main);
2896
2980
  this.NOTE.value = noteMatch?.note;
2897
2981
  validValue = value.replace(noteRegExp, "");
2982
+ } else {
2983
+ const qualifierMatch = value.match(
2984
+ /^(?<qualifier>ABT|ABOUT|BEF|BEFORE|AFT|AFTER)\b\s*/i
2985
+ );
2986
+ const qualifier = qualifierMatch?.groups?.qualifier?.toUpperCase();
2987
+ const note = qualifier ? STANDARD_QUALIFIERS[qualifier] : void 0;
2988
+ if (note) {
2989
+ this.NOTE = this.NOTE || createCommon(this._gedcom, void 0, this.main);
2990
+ this.NOTE.value = note;
2991
+ validValue = value.slice(qualifierMatch[0].length);
2992
+ }
2898
2993
  }
2899
2994
  const acceptedDate = this.isValidDateFormat(validValue);
2900
2995
  if (acceptedDate) {
@@ -3000,7 +3095,23 @@ var CommonDate = class extends Common {
3000
3095
  );
3001
3096
  }
3002
3097
  exportValue() {
3003
- return this.toValue("NOTE dd MMM yyyy", null);
3098
+ const formatted = this.toValue("NOTE dd MMM yyyy", null);
3099
+ if (!formatted) {
3100
+ return formatted;
3101
+ }
3102
+ const note = this.NOTE?.value?.trim();
3103
+ const qualifier = note ? EXPORT_QUALIFIERS[note] : void 0;
3104
+ const standardized = qualifier ? formatted.replace(note, qualifier) : formatted;
3105
+ return standardized.replace(
3106
+ GEDCOM_MONTHS,
3107
+ (month) => month.toUpperCase()
3108
+ );
3109
+ }
3110
+ toGedcomLines(tag, level = 0, options) {
3111
+ const internal = new RegExp(
3112
+ `^${level} (DAY|MONTH|YEAR)( |$)|^${level} NOTE (Abt\\.|Bef\\.|Aft\\.)$`
3113
+ );
3114
+ return super.toGedcomLines(tag, level, options).filter((line) => !internal.test(line));
3004
3115
  }
3005
3116
  inRange(range, trueIfNoYear = false) {
3006
3117
  return inRange(this.YEAR?.value, range, trueIfNoYear);
@@ -3325,6 +3436,135 @@ var profilePictureCache = (gedcom, key, value) => {
3325
3436
  const cached = caches.profilePictureCache?.[fullKey];
3326
3437
  return cached;
3327
3438
  };
3439
+ var isNonBiologicalPath = (path) => path.some(
3440
+ (item) => item.relation && item.relation !== "biological" /* BIOLOGICAL */
3441
+ );
3442
+ var invertHop = (kinship) => {
3443
+ if (kinship === "parent") {
3444
+ return "child";
3445
+ }
3446
+ if (kinship === "child") {
3447
+ return "parent";
3448
+ }
3449
+ return kinship;
3450
+ };
3451
+ var hopRelation = (from, toIndi, kinship, inherited) => {
3452
+ if (kinship === "parent" || kinship === "child") {
3453
+ const parent = kinship === "parent" ? toIndi : from.indi;
3454
+ const child = kinship === "parent" ? from.indi : toIndi;
3455
+ const currentRelation = child.getParentType(parent);
3456
+ if (currentRelation && currentRelation !== "biological" /* BIOLOGICAL */) {
3457
+ return currentRelation;
3458
+ }
3459
+ }
3460
+ if (inherited && inherited !== "biological" /* BIOLOGICAL */) {
3461
+ return inherited;
3462
+ }
3463
+ return void 0;
3464
+ };
3465
+ var rebuildPathFromHops = (hops, skipRelation = false) => {
3466
+ if (hops.length === 0) {
3467
+ return [];
3468
+ }
3469
+ const path = [
3470
+ {
3471
+ indi: hops[0].indi,
3472
+ kinship: "self",
3473
+ level: 0,
3474
+ levelUp: 0,
3475
+ levelDown: 0,
3476
+ degree: 0
3477
+ }
3478
+ ];
3479
+ for (let i = 1; i < hops.length; i++) {
3480
+ const prev = path[i - 1];
3481
+ const { indi, kinship } = hops[i];
3482
+ const relation = skipRelation ? void 0 : hopRelation(prev, indi, kinship, prev.relation);
3483
+ if (kinship === "parent") {
3484
+ path.push({
3485
+ indi,
3486
+ kinship,
3487
+ relation,
3488
+ level: prev.level + 1,
3489
+ levelUp: prev.levelUp + 1,
3490
+ levelDown: prev.levelDown,
3491
+ degree: prev.degree
3492
+ });
3493
+ continue;
3494
+ }
3495
+ if (kinship === "child") {
3496
+ path.push({
3497
+ indi,
3498
+ kinship,
3499
+ relation,
3500
+ level: prev.level - 1,
3501
+ levelUp: prev.levelUp,
3502
+ levelDown: prev.levelDown + 1,
3503
+ degree: prev.levelUp ? prev.level > 0 ? prev.levelUp - prev.level + 1 : prev.levelDown - Math.abs(prev.level) : 0
3504
+ });
3505
+ continue;
3506
+ }
3507
+ path.push({
3508
+ indi,
3509
+ kinship,
3510
+ relation,
3511
+ level: prev.level,
3512
+ levelUp: prev.levelUp,
3513
+ levelDown: prev.levelDown,
3514
+ degree: prev.degree
3515
+ });
3516
+ }
3517
+ return path;
3518
+ };
3519
+ var storePathIfBetter = (gedcom, fromId, toId, path) => {
3520
+ const key = `${fromId}|${toId}`;
3521
+ const existing = pathCache(gedcom, key);
3522
+ if (existing && (!isNonBiologicalPath(existing) || isNonBiologicalPath(path))) {
3523
+ return;
3524
+ }
3525
+ pathCache(gedcom, key, path);
3526
+ };
3527
+ var cacheDiscoveredPath = (gedcom, path) => {
3528
+ const n = path.length;
3529
+ if (n < 2) {
3530
+ return;
3531
+ }
3532
+ for (let i = 0; i < n; i++) {
3533
+ const fromId = path[i].indi.id;
3534
+ if (!fromId) {
3535
+ continue;
3536
+ }
3537
+ for (let j = i + 1; j < n; j++) {
3538
+ const toId = path[j].indi.id;
3539
+ if (!toId) {
3540
+ continue;
3541
+ }
3542
+ const isOriginalPair = i === 0 && j === n - 1;
3543
+ const isDirectHop = j === i + 1;
3544
+ const slice = path.slice(i, j + 1);
3545
+ const sliceMixed = isNonBiologicalPath(slice);
3546
+ if (!isOriginalPair && !isDirectHop && sliceMixed) {
3547
+ continue;
3548
+ }
3549
+ const forward = i === 0 ? slice : rebuildPathFromHops(slice, !sliceMixed);
3550
+ const reverseHops = [
3551
+ {
3552
+ indi: slice[slice.length - 1].indi,
3553
+ kinship: "self"
3554
+ }
3555
+ ];
3556
+ for (let k = slice.length - 2; k >= 0; k--) {
3557
+ reverseHops.push({
3558
+ indi: slice[k].indi,
3559
+ kinship: invertHop(slice[k + 1].kinship)
3560
+ });
3561
+ }
3562
+ const reverse = rebuildPathFromHops(reverseHops, !sliceMixed);
3563
+ storePathIfBetter(gedcom, fromId, toId, forward);
3564
+ storePathIfBetter(gedcom, toId, fromId, reverse);
3565
+ }
3566
+ }
3567
+ };
3328
3568
 
3329
3569
  // src/utils/get-places.ts
3330
3570
  var getPlaces = (common, type = ["ALL" /* All */], maxLevel = 1, level = 0, mainKey) => {
@@ -5317,7 +5557,6 @@ var Indi = class extends Common {
5317
5557
  if (cache) {
5318
5558
  return cache;
5319
5559
  }
5320
- const visited = new Individuals().append(this);
5321
5560
  const mainItem = {
5322
5561
  indi: this,
5323
5562
  level: 0,
@@ -5326,129 +5565,155 @@ var Indi = class extends Common {
5326
5565
  degree: 0,
5327
5566
  kinship: "self"
5328
5567
  };
5329
- const path = [mainItem];
5568
+ const mainPath = [mainItem];
5330
5569
  if (this.id === usedIndi.id) {
5331
- return path;
5570
+ return mainPath;
5332
5571
  }
5333
- const queue = [
5334
- {
5335
- ...mainItem,
5336
- path
5337
- }
5338
- ];
5339
- let helper = 0;
5340
- while (queue.length > 0) {
5341
- if (helper++ > 1e6) {
5342
- break;
5343
- }
5344
- const {
5345
- indi,
5346
- path: path2,
5347
- kinship,
5348
- relation,
5349
- level,
5350
- levelUp,
5351
- levelDown,
5352
- degree,
5353
- breakOnNext,
5354
- breakAfterNext,
5355
- inLaw
5356
- } = queue.shift();
5357
- if (usedIndi.id === indi.id) {
5358
- if (breakOnNext) {
5359
- return void 0;
5572
+ const bfs = (biologicalOnly) => {
5573
+ const visited = new Individuals().append(this);
5574
+ const queue = [
5575
+ {
5576
+ ...mainItem,
5577
+ path: mainPath
5360
5578
  }
5361
- pathCache(this._gedcom, cacheKey, path2);
5362
- return path2;
5363
- }
5364
- visited.append(indi);
5365
- const additional = {};
5366
- if (breakOnNext || breakAfterNext) {
5367
- additional.breakOnNext = breakOnNext || breakAfterNext;
5368
- }
5369
- if (inLaw) {
5370
- additional.inLaw = inLaw;
5371
- }
5372
- if (kinship === "spouse" && breakAfterSpouse) {
5373
- if (path2.length <= 2) {
5374
- additional.inLaw = true;
5375
- } else {
5376
- additional.breakOnNext = true;
5579
+ ];
5580
+ let helper = 0;
5581
+ while (queue.length > 0) {
5582
+ if (helper++ > 1e6) {
5583
+ break;
5377
5584
  }
5378
- }
5379
- if (kinship !== "child" || !breakAfterSpouse) {
5380
- indi.getBiologicalFathers().copy().merge(indi.getBiologicalMothers()).merge(indi.getFathers().copy().merge(indi.getMothers())).forEach((relative) => {
5585
+ const {
5586
+ indi,
5587
+ path,
5588
+ kinship,
5589
+ relation,
5590
+ level,
5591
+ levelUp,
5592
+ levelDown,
5593
+ degree,
5594
+ breakOnNext,
5595
+ breakAfterNext,
5596
+ inLaw
5597
+ } = queue.shift();
5598
+ if (usedIndi.id === indi.id) {
5599
+ if (breakOnNext) {
5600
+ return void 0;
5601
+ }
5602
+ return path;
5603
+ }
5604
+ visited.append(indi);
5605
+ const additional = {};
5606
+ if (breakOnNext || breakAfterNext) {
5607
+ additional.breakOnNext = breakOnNext || breakAfterNext;
5608
+ }
5609
+ if (inLaw) {
5610
+ additional.inLaw = inLaw;
5611
+ }
5612
+ if (!biologicalOnly && kinship === "spouse" && breakAfterSpouse) {
5613
+ if (path.length <= 2) {
5614
+ additional.inLaw = true;
5615
+ } else {
5616
+ additional.breakOnNext = true;
5617
+ }
5618
+ }
5619
+ if (kinship !== "child" || !breakAfterSpouse) {
5620
+ indi.getBiologicalFathers().copy().merge(indi.getBiologicalMothers()).merge(indi.getFathers().copy().merge(indi.getMothers())).forEach((relative) => {
5621
+ if (!visited.has(relative)) {
5622
+ const currentRelation = indi.getParentType(relative);
5623
+ const isNonBiological = !!currentRelation && currentRelation !== "biological" /* BIOLOGICAL */;
5624
+ if (biologicalOnly && isNonBiological) {
5625
+ return;
5626
+ }
5627
+ if (!biologicalOnly && breakAfterNonBiological && isNonBiological) {
5628
+ additional.breakAfterNext = true;
5629
+ }
5630
+ const newItem = {
5631
+ indi: relative,
5632
+ kinship: "parent",
5633
+ relation: isNonBiological ? currentRelation : relation,
5634
+ level: level + 1,
5635
+ levelUp: levelUp + 1,
5636
+ levelDown,
5637
+ degree,
5638
+ ...additional
5639
+ };
5640
+ queue.push({
5641
+ ...newItem,
5642
+ path: [...path, newItem]
5643
+ });
5644
+ }
5645
+ });
5646
+ }
5647
+ indi.getChildren().forEach((relative) => {
5381
5648
  if (!visited.has(relative)) {
5382
- const currentRelation = indi.getParentType(relative);
5383
- if (breakAfterNonBiological && currentRelation !== "biological" /* BIOLOGICAL */) {
5649
+ const currentRelation = relative.getParentType(indi);
5650
+ const isNonBiological = !!currentRelation && currentRelation !== "biological" /* BIOLOGICAL */;
5651
+ if (biologicalOnly && isNonBiological) {
5652
+ return;
5653
+ }
5654
+ if (!biologicalOnly && breakAfterNonBiological && isNonBiological) {
5384
5655
  additional.breakAfterNext = true;
5385
5656
  }
5386
5657
  const newItem = {
5387
5658
  indi: relative,
5388
- kinship: "parent",
5389
- relation: currentRelation && currentRelation !== "biological" /* BIOLOGICAL */ ? currentRelation : relation,
5390
- level: level + 1,
5391
- levelUp: levelUp + 1,
5392
- levelDown,
5393
- degree,
5659
+ kinship: "child",
5660
+ relation: isNonBiological ? currentRelation : relation,
5661
+ level: level - 1,
5662
+ levelUp,
5663
+ levelDown: levelDown + 1,
5664
+ degree: levelUp ? level > 0 ? levelUp - level + 1 : levelDown - Math.abs(level) : 0,
5394
5665
  ...additional
5395
5666
  };
5396
5667
  queue.push({
5397
5668
  ...newItem,
5398
- path: [...path2, newItem]
5669
+ path: [...path, newItem]
5399
5670
  });
5400
5671
  }
5401
5672
  });
5402
- }
5403
- indi.getChildren().forEach((relative) => {
5404
- if (!visited.has(relative)) {
5405
- const currentRelation = relative.getParentType(indi);
5406
- if (breakAfterNonBiological && currentRelation !== "biological" /* BIOLOGICAL */) {
5407
- additional.breakAfterNext = true;
5408
- }
5409
- const newItem = {
5410
- indi: relative,
5411
- kinship: "child",
5412
- relation: currentRelation && currentRelation !== "biological" /* BIOLOGICAL */ ? currentRelation : relation,
5413
- level: level - 1,
5414
- levelUp,
5415
- levelDown: levelDown + 1,
5416
- degree: levelUp ? level > 0 ? levelUp - level + 1 : levelDown - Math.abs(level) : 0,
5417
- ...additional
5418
- };
5419
- queue.push({
5420
- ...newItem,
5421
- path: [...path2, newItem]
5422
- });
5673
+ if (biologicalOnly) {
5674
+ continue;
5423
5675
  }
5424
- });
5425
- indi.getCoParents().forEach((relative) => {
5426
- if (!visited.has(relative)) {
5427
- const currentAddition = {};
5428
- if (relation && relation !== "biological" /* BIOLOGICAL */) {
5429
- currentAddition.relation = relation;
5430
- }
5431
- if (inLaw) {
5432
- currentAddition.breakOnNext = true;
5676
+ indi.getCoParents().forEach((relative) => {
5677
+ if (!visited.has(relative)) {
5678
+ const currentAddition = {};
5679
+ if (relation && relation !== "biological" /* BIOLOGICAL */) {
5680
+ currentAddition.relation = relation;
5681
+ }
5682
+ if (inLaw) {
5683
+ currentAddition.breakOnNext = true;
5684
+ }
5685
+ const newItem = {
5686
+ indi: relative,
5687
+ kinship: "spouse",
5688
+ level,
5689
+ levelUp,
5690
+ levelDown,
5691
+ degree,
5692
+ ...additional,
5693
+ ...currentAddition
5694
+ };
5695
+ queue.push({
5696
+ ...newItem,
5697
+ path: [...path, newItem]
5698
+ });
5433
5699
  }
5434
- const newItem = {
5435
- indi: relative,
5436
- kinship: "spouse",
5437
- level,
5438
- levelUp,
5439
- levelDown,
5440
- degree,
5441
- ...additional,
5442
- ...currentAddition
5443
- };
5444
- queue.push({
5445
- ...newItem,
5446
- path: [...path2, newItem]
5447
- });
5448
- }
5449
- });
5700
+ });
5701
+ }
5702
+ return void 0;
5703
+ };
5704
+ const foundPath = bfs(false);
5705
+ const lastItem = foundPath?.[foundPath.length - 1];
5706
+ if (lastItem?.relation && lastItem.relation !== "biological" /* BIOLOGICAL */) {
5707
+ const biologicalPath = bfs(true);
5708
+ if (biologicalPath) {
5709
+ cacheDiscoveredPath(this._gedcom, biologicalPath);
5710
+ return biologicalPath;
5711
+ }
5450
5712
  }
5451
- return void 0;
5713
+ if (foundPath) {
5714
+ cacheDiscoveredPath(this._gedcom, foundPath);
5715
+ }
5716
+ return foundPath;
5452
5717
  }
5453
5718
  kinship(other, showMainPerson, lang = "en", entirePath, displayName = "givenname") {
5454
5719
  const KinshipTranslatorClass2 = getKinshipTranslatorClass();
@@ -6253,7 +6518,7 @@ var createIndi = (gedcom, id, main, parent) => {
6253
6518
 
6254
6519
  // package.json
6255
6520
  var package_default = {
6256
- version: "2.0.7"};
6521
+ version: "2.0.9"};
6257
6522
 
6258
6523
  // src/utils/get-product-details.ts
6259
6524
  var getVersion = () => package_default.version;