@treeviz/gedcom-parser 2.1.15 → 2.1.17
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/common.d.ts.map +1 -1
- package/dist/classes/date.d.ts +2 -0
- package/dist/classes/date.d.ts.map +1 -1
- package/dist/classes/index.js +41 -10
- package/dist/cli/index.js +41 -10
- package/dist/constants/index.js +1149 -1117
- package/dist/factories/index.js +1192 -1160
- package/dist/index.js +41 -10
- package/dist/kinship-translator/index.js +1192 -1160
- package/dist/structures/individual.d.ts +1 -0
- package/dist/structures/individual.d.ts.map +1 -1
- package/dist/types/types.d.ts +1 -0
- package/dist/types/types.d.ts.map +1 -1
- package/dist/utils/date-formatter.d.ts.map +1 -1
- package/dist/utils/gedcom7-schema.d.ts.map +1 -1
- package/dist/utils/index.js +41 -10
- package/package.json +1 -1
package/dist/constants/index.js
CHANGED
|
@@ -353,202 +353,6 @@ var cacheDiscoveredPath = (gedcom, path) => {
|
|
|
353
353
|
}
|
|
354
354
|
};
|
|
355
355
|
|
|
356
|
-
// src/utils/get-all-prop.ts
|
|
357
|
-
var getAllProp = (indi, prop) => {
|
|
358
|
-
return prop && (indi?.get(prop)?.toList().values() ?? []).filter(Boolean) || [];
|
|
359
|
-
};
|
|
360
|
-
|
|
361
|
-
// src/utils/date-formatter.ts
|
|
362
|
-
var ACCEPTED_DATE_FORMATS = [
|
|
363
|
-
"yyyy.MM.dd.",
|
|
364
|
-
"yyyy-MM-dd",
|
|
365
|
-
"MM/dd/yyyy"
|
|
366
|
-
];
|
|
367
|
-
var ACCEPTED_DATE_FORMATS_REGEX = new RegExp(
|
|
368
|
-
`(${ACCEPTED_DATE_FORMATS.map(
|
|
369
|
-
(acceptedFormat) => acceptedFormat.replace(/[^.\-/]/g, "\\d")
|
|
370
|
-
).join("|")})`,
|
|
371
|
-
"gi"
|
|
372
|
-
);
|
|
373
|
-
var commonDateFormatter = (date, format2 = "yyyy", prefix = "") => {
|
|
374
|
-
const formattedDate = date?.toValue(format2);
|
|
375
|
-
if (!formattedDate) {
|
|
376
|
-
return void 0;
|
|
377
|
-
}
|
|
378
|
-
return `${prefix}${formattedDate}`.trim();
|
|
379
|
-
};
|
|
380
|
-
var noteDateFormatter = (date, format2 = "yyyy", prefix = "", shortNote = true, showNote = true) => {
|
|
381
|
-
const rawDate = commonDateFormatter(date, format2, "");
|
|
382
|
-
if (!rawDate) {
|
|
383
|
-
return void 0;
|
|
384
|
-
}
|
|
385
|
-
const note = date?.toNote(shortNote) ?? "";
|
|
386
|
-
return `${prefix}${note && showNote ? i18n.t(`${note} {{date}}`, { date: rawDate }) : rawDate}`;
|
|
387
|
-
};
|
|
388
|
-
var marriageDateFormatter = (fam, showDays = false, showPlaces = false, shortNote = true, showNote = true, showDisplayTextIfNoDate = true, showAllEvents = false, dateFormatPattern) => {
|
|
389
|
-
const fullDateFormat = i18n.t("dateFormat");
|
|
390
|
-
const marriageDates = [];
|
|
391
|
-
const marriagePlaces = [];
|
|
392
|
-
const marriages = (fam?.toValueList().values() ?? []).flatMap((fam2) => {
|
|
393
|
-
const family = fam2;
|
|
394
|
-
const marrEvents = (family?.MARR?.toList().values() ?? []).filter(
|
|
395
|
-
Boolean
|
|
396
|
-
);
|
|
397
|
-
if (marrEvents.length === 0) {
|
|
398
|
-
const displayText = family?.get("DISPLAYTEXT")?.toValue() ?? "";
|
|
399
|
-
if (showDisplayTextIfNoDate && displayText) {
|
|
400
|
-
const displayDate = displayText.match(
|
|
401
|
-
ACCEPTED_DATE_FORMATS_REGEX
|
|
402
|
-
)?.[0];
|
|
403
|
-
if (displayDate) {
|
|
404
|
-
marriagePlaces.push(displayText.replace(displayDate, ""));
|
|
405
|
-
const marriageDate = createCommonDate(
|
|
406
|
-
fam2?.getGedcom(),
|
|
407
|
-
void 0,
|
|
408
|
-
family
|
|
409
|
-
);
|
|
410
|
-
marriageDate.value = displayDate;
|
|
411
|
-
marriageDates.push(marriageDate);
|
|
412
|
-
} else {
|
|
413
|
-
marriagePlaces.push(displayText);
|
|
414
|
-
marriageDates.push(void 0);
|
|
415
|
-
return ["\u221E"];
|
|
416
|
-
}
|
|
417
|
-
}
|
|
418
|
-
return [];
|
|
419
|
-
}
|
|
420
|
-
const eventsToProcess = showAllEvents ? marrEvents : marrEvents.slice(0, 1);
|
|
421
|
-
return eventsToProcess.map((marrEvent) => {
|
|
422
|
-
const marriageEventDetail = marrEvent;
|
|
423
|
-
const marriageDate = marriageEventDetail?.DATE;
|
|
424
|
-
const marriagePlace = showPlaces ? marriageEventDetail?.PLAC?.value : void 0;
|
|
425
|
-
marriagePlaces.push(marriagePlace);
|
|
426
|
-
marriageDates.push(marriageDate);
|
|
427
|
-
const formattedDate = noteDateFormatter(
|
|
428
|
-
marriageDate,
|
|
429
|
-
showDays ? fullDateFormat : "yyyy",
|
|
430
|
-
"\u221E",
|
|
431
|
-
shortNote,
|
|
432
|
-
showNote
|
|
433
|
-
);
|
|
434
|
-
return formattedDate ? formattedDate : void 0;
|
|
435
|
-
});
|
|
436
|
-
});
|
|
437
|
-
const marriageArray = marriages.length ? marriages.filter(Boolean) : [];
|
|
438
|
-
const datesArray = marriageArray.filter(Boolean);
|
|
439
|
-
const placesArray = marriagePlaces.filter(Boolean);
|
|
440
|
-
const dates = datesArray.join(" ").trim();
|
|
441
|
-
return {
|
|
442
|
-
rawArray: marriageDates,
|
|
443
|
-
inArray: datesArray,
|
|
444
|
-
inOrder: dates,
|
|
445
|
-
places: placesArray,
|
|
446
|
-
marriage: marriageArray,
|
|
447
|
-
...showPlaces ? {
|
|
448
|
-
marriages,
|
|
449
|
-
marriagePlaces
|
|
450
|
-
} : {}
|
|
451
|
-
};
|
|
452
|
-
};
|
|
453
|
-
var dateFormatter = (indi, showMarriages = false, showDays = false, showPlaces = false, shortNote = true, showNote = true, isOnStage, showAllEvents = false, dateFormatPattern) => {
|
|
454
|
-
const fullDateFormat = i18n.t("dateFormat");
|
|
455
|
-
const birthEvents = getAllProp(indi, "BIRT");
|
|
456
|
-
const firstBirthValue = birthEvents[0];
|
|
457
|
-
const deathEvents = getAllProp(indi, "DEAT");
|
|
458
|
-
const firstDeathValue = deathEvents[0];
|
|
459
|
-
const birth = commonDateFormatter(
|
|
460
|
-
firstBirthValue?.DATE,
|
|
461
|
-
showDays ? fullDateFormat : "yyyy"
|
|
462
|
-
);
|
|
463
|
-
const birthPlace = showPlaces ? firstBirthValue?.PLAC?.value : void 0;
|
|
464
|
-
const death = commonDateFormatter(
|
|
465
|
-
firstDeathValue?.DATE,
|
|
466
|
-
showDays ? fullDateFormat : "yyyy"
|
|
467
|
-
);
|
|
468
|
-
const deathPlace = showPlaces ? firstDeathValue?.PLAC?.value : void 0;
|
|
469
|
-
const marriagePlaces = [];
|
|
470
|
-
const marriages = [];
|
|
471
|
-
if (showMarriages || isOnStage) {
|
|
472
|
-
(indi?.get("FAMS")?.toValueList().values() ?? []).forEach((fam) => {
|
|
473
|
-
const famRef = fam?.ref;
|
|
474
|
-
const marriageDates = marriageDateFormatter(
|
|
475
|
-
famRef,
|
|
476
|
-
showDays,
|
|
477
|
-
showPlaces,
|
|
478
|
-
shortNote,
|
|
479
|
-
showNote,
|
|
480
|
-
true,
|
|
481
|
-
showAllEvents);
|
|
482
|
-
marriages.push(...marriageDates?.marriage ?? []);
|
|
483
|
-
marriagePlaces.push(...marriageDates?.marriagePlaces ?? []);
|
|
484
|
-
});
|
|
485
|
-
}
|
|
486
|
-
const birthStrings = [];
|
|
487
|
-
const birthPlaces = [];
|
|
488
|
-
const eventsToProcess = showAllEvents ? birthEvents : birthEvents.slice(0, 1);
|
|
489
|
-
eventsToProcess.forEach((birthEvent) => {
|
|
490
|
-
const birthDate = commonDateFormatter(
|
|
491
|
-
birthEvent?.DATE,
|
|
492
|
-
showDays ? fullDateFormat : "yyyy"
|
|
493
|
-
);
|
|
494
|
-
const birthEventNote = birthEvent?.DATE?.toNote(shortNote) ?? "";
|
|
495
|
-
const birthEventPlace = showPlaces ? birthEvent?.PLAC?.value : void 0;
|
|
496
|
-
if (birthDate) {
|
|
497
|
-
birthStrings.push(
|
|
498
|
-
`*${birthEventNote && showNote ? i18n.t(`${birthEventNote} {{date}}`, {
|
|
499
|
-
date: birthDate
|
|
500
|
-
}) : birthDate}`
|
|
501
|
-
);
|
|
502
|
-
}
|
|
503
|
-
birthPlaces.push(birthEventPlace);
|
|
504
|
-
});
|
|
505
|
-
const deathStrings = [];
|
|
506
|
-
const deathPlaces = [];
|
|
507
|
-
const deathEventsToProcess = showAllEvents ? deathEvents : deathEvents.slice(0, 1);
|
|
508
|
-
deathEventsToProcess.forEach((deathEvent) => {
|
|
509
|
-
const deathDate = commonDateFormatter(
|
|
510
|
-
deathEvent?.DATE,
|
|
511
|
-
showDays ? fullDateFormat : "yyyy"
|
|
512
|
-
);
|
|
513
|
-
const deathEventNote = deathEvent?.DATE?.toNote(shortNote) ?? "";
|
|
514
|
-
const deathEventPlace = showPlaces ? deathEvent?.PLAC?.value : void 0;
|
|
515
|
-
if (deathDate) {
|
|
516
|
-
deathStrings.push(
|
|
517
|
-
`\u2020${deathEventNote && showNote ? i18n.t(`${deathEventNote} {{date}}`, {
|
|
518
|
-
date: deathDate
|
|
519
|
-
}) : deathDate}`
|
|
520
|
-
);
|
|
521
|
-
}
|
|
522
|
-
deathPlaces.push(deathEventPlace);
|
|
523
|
-
});
|
|
524
|
-
const birthString = birthStrings[0] ?? "";
|
|
525
|
-
const deathString = deathStrings[0] ?? "";
|
|
526
|
-
const marriageArray = marriages.length ? marriages.filter(Boolean) : [];
|
|
527
|
-
const datesArray = !birth && !death ? marriageArray : [...birthStrings, ...marriageArray, ...deathStrings];
|
|
528
|
-
const placesArray = !birth && !death ? marriagePlaces : [...birthPlaces, ...marriagePlaces, ...deathPlaces];
|
|
529
|
-
const nonNullDatesArray = datesArray.filter(Boolean);
|
|
530
|
-
const dates = nonNullDatesArray.join(" ").trim();
|
|
531
|
-
return {
|
|
532
|
-
inArray: nonNullDatesArray,
|
|
533
|
-
inOrder: dates,
|
|
534
|
-
places: placesArray,
|
|
535
|
-
birth: birthString,
|
|
536
|
-
marriage: marriageArray,
|
|
537
|
-
death: deathString,
|
|
538
|
-
...showPlaces ? {
|
|
539
|
-
birthPlace,
|
|
540
|
-
deathPlace,
|
|
541
|
-
...showMarriages ? { marriages, marriagePlaces } : {}
|
|
542
|
-
} : {},
|
|
543
|
-
...showAllEvents ? {
|
|
544
|
-
births: birthStrings,
|
|
545
|
-
birthPlaces,
|
|
546
|
-
deaths: deathStrings,
|
|
547
|
-
deathPlaces
|
|
548
|
-
} : {}
|
|
549
|
-
};
|
|
550
|
-
};
|
|
551
|
-
|
|
552
356
|
// src/utils/gedcom-trailer.ts
|
|
553
357
|
var GEDCOM_TRAILER_TAG = "TRLR";
|
|
554
358
|
var isGedcomTrailerTag = (tag) => tag === GEDCOM_TRAILER_TAG;
|
|
@@ -628,1087 +432,1313 @@ var objeXrefKey = (obje, fallback = 0) => {
|
|
|
628
432
|
return `@O${fallback}@`;
|
|
629
433
|
};
|
|
630
434
|
var objeNoteValue = (obje) => mediaIdValue(obje, "FILE.NOTE") || mediaIdValue(obje, "NOTE") || "";
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
435
|
+
|
|
436
|
+
// src/classes/common.ts
|
|
437
|
+
var Common = class _Common {
|
|
438
|
+
constructor(gedcom, id, main, parent) {
|
|
635
439
|
this.isListable = true;
|
|
636
|
-
this.
|
|
637
|
-
|
|
638
|
-
|
|
440
|
+
this._gedcom = gedcom;
|
|
441
|
+
this._main = main;
|
|
442
|
+
this._parent = parent;
|
|
443
|
+
this.initUniqueId();
|
|
444
|
+
if (id) {
|
|
445
|
+
this._id = id;
|
|
446
|
+
} else {
|
|
447
|
+
delete this._id;
|
|
639
448
|
}
|
|
640
449
|
}
|
|
641
|
-
|
|
642
|
-
|
|
450
|
+
set type(type) {
|
|
451
|
+
if (type) {
|
|
452
|
+
this.uniqueId = this.uniqueId?.replace(/^[^:]+/, `~${type}`);
|
|
453
|
+
}
|
|
454
|
+
this._type = type;
|
|
643
455
|
}
|
|
644
|
-
|
|
645
|
-
return
|
|
646
|
-
typeof indi === "string" ? indi : indi?.id ?? ""
|
|
647
|
-
);
|
|
456
|
+
get type() {
|
|
457
|
+
return this._type;
|
|
648
458
|
}
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
});
|
|
654
|
-
return propList;
|
|
459
|
+
initUniqueId() {
|
|
460
|
+
if (this._gedcom) {
|
|
461
|
+
this.uniqueId = `~Common:${this._gedcom.refcount++}`;
|
|
462
|
+
}
|
|
655
463
|
}
|
|
656
|
-
|
|
657
|
-
const
|
|
658
|
-
this.
|
|
659
|
-
|
|
660
|
-
if (
|
|
661
|
-
|
|
464
|
+
set uniqueId(id) {
|
|
465
|
+
const currentId = this._uniqueId;
|
|
466
|
+
if (this._gedcom?.reflist && id) {
|
|
467
|
+
this._uniqueId = id;
|
|
468
|
+
if (currentId && this._gedcom.reflist[currentId]) {
|
|
469
|
+
delete this._gedcom.reflist[currentId];
|
|
662
470
|
}
|
|
663
|
-
|
|
664
|
-
|
|
471
|
+
this._gedcom.reflist[id] = this;
|
|
472
|
+
}
|
|
665
473
|
}
|
|
666
|
-
|
|
667
|
-
return
|
|
474
|
+
get uniqueId() {
|
|
475
|
+
return this._uniqueId;
|
|
668
476
|
}
|
|
669
|
-
|
|
670
|
-
|
|
477
|
+
set id(id) {
|
|
478
|
+
this._id = idGetter(id);
|
|
671
479
|
}
|
|
672
|
-
|
|
673
|
-
return
|
|
480
|
+
get id() {
|
|
481
|
+
return idGetter(this._id);
|
|
674
482
|
}
|
|
675
|
-
|
|
483
|
+
set value(value) {
|
|
484
|
+
this._value = value;
|
|
676
485
|
}
|
|
677
|
-
|
|
678
|
-
return this.
|
|
486
|
+
get value() {
|
|
487
|
+
return this._value;
|
|
679
488
|
}
|
|
680
|
-
|
|
681
|
-
|
|
489
|
+
/**
|
|
490
|
+
* Set the gedcom reference for this object
|
|
491
|
+
* @param gedcom - The GedComType to set as the gedcom reference
|
|
492
|
+
*/
|
|
493
|
+
setGedcom(gedcom) {
|
|
494
|
+
this._gedcom = gedcom;
|
|
682
495
|
}
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
return key && this.items[key];
|
|
496
|
+
// avoid to override
|
|
497
|
+
get originalValue() {
|
|
498
|
+
return this._value;
|
|
687
499
|
}
|
|
688
|
-
|
|
689
|
-
if (
|
|
690
|
-
|
|
691
|
-
|
|
500
|
+
get ref() {
|
|
501
|
+
if (typeof this.value === "string" && isId(this.value) && this.refType) {
|
|
502
|
+
return this._gedcom?.[getListTag(this.refType)]?.item(
|
|
503
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
504
|
+
this.value
|
|
505
|
+
);
|
|
692
506
|
}
|
|
693
|
-
return
|
|
507
|
+
return this;
|
|
694
508
|
}
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
this.setLength();
|
|
509
|
+
get main() {
|
|
510
|
+
return this._main;
|
|
698
511
|
}
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
delete this.items[itemId];
|
|
702
|
-
});
|
|
703
|
-
this.setLength();
|
|
704
|
-
return this;
|
|
512
|
+
get parent() {
|
|
513
|
+
return this._parent;
|
|
705
514
|
}
|
|
706
|
-
|
|
707
|
-
if (
|
|
708
|
-
|
|
709
|
-
this.
|
|
710
|
-
}
|
|
711
|
-
|
|
712
|
-
Object.assign(this.items, items ?? {});
|
|
515
|
+
addRef(refNode) {
|
|
516
|
+
if (typeof refNode.value === "string" && isId(refNode.value) && refNode.refType) {
|
|
517
|
+
if (!this._refs) {
|
|
518
|
+
this._refs = new List();
|
|
519
|
+
}
|
|
520
|
+
this._refs.item(refNode.value, refNode);
|
|
713
521
|
}
|
|
714
|
-
this.setLength();
|
|
715
|
-
return this;
|
|
716
522
|
}
|
|
717
|
-
|
|
718
|
-
this.
|
|
719
|
-
return this;
|
|
523
|
+
getRefs() {
|
|
524
|
+
return this._refs;
|
|
720
525
|
}
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
this.values(),
|
|
724
|
-
mergedList?.values() ?? [],
|
|
725
|
-
"id"
|
|
726
|
-
);
|
|
727
|
-
return new _List(inter);
|
|
526
|
+
exportValue() {
|
|
527
|
+
return this.value;
|
|
728
528
|
}
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
this.values(),
|
|
732
|
-
mergedList?.values() ?? [],
|
|
733
|
-
"id"
|
|
734
|
-
);
|
|
735
|
-
return new _List(inter);
|
|
529
|
+
removeValue() {
|
|
530
|
+
delete this._value;
|
|
736
531
|
}
|
|
737
|
-
|
|
738
|
-
if (
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
this
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
532
|
+
set(name, value) {
|
|
533
|
+
if (isGedcomTrailerTag(name)) {
|
|
534
|
+
return void 0;
|
|
535
|
+
}
|
|
536
|
+
if (typeof value === "string") {
|
|
537
|
+
const usedValue = createCommon(this._gedcom, void 0, this.main);
|
|
538
|
+
usedValue.value = value;
|
|
539
|
+
set(this, name, usedValue);
|
|
540
|
+
} else {
|
|
541
|
+
set(this, name, value);
|
|
542
|
+
}
|
|
543
|
+
return get(this, name);
|
|
544
|
+
}
|
|
545
|
+
assign(name, value, unique = false) {
|
|
546
|
+
if (isGedcomTrailerTag(name)) {
|
|
547
|
+
return void 0;
|
|
548
|
+
}
|
|
549
|
+
let curValue = this.get(name);
|
|
550
|
+
if (curValue?.isListable) {
|
|
551
|
+
if (curValue instanceof _Common) {
|
|
552
|
+
curValue = new List().concat({ ...[curValue] });
|
|
553
|
+
this.set(name, curValue);
|
|
752
554
|
}
|
|
555
|
+
const values = [
|
|
556
|
+
...curValue.values(),
|
|
557
|
+
...value instanceof List ? value.values() : [value]
|
|
558
|
+
];
|
|
559
|
+
curValue.concat({
|
|
560
|
+
...!unique ? values : uniqBy(
|
|
561
|
+
values,
|
|
562
|
+
(value2) => value2 instanceof _Common ? value2?.value : void 0
|
|
563
|
+
)
|
|
564
|
+
});
|
|
565
|
+
} else {
|
|
566
|
+
this.set(name, value);
|
|
753
567
|
}
|
|
754
|
-
return this;
|
|
568
|
+
return get(this, name);
|
|
755
569
|
}
|
|
756
|
-
|
|
757
|
-
if (
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
570
|
+
get(name) {
|
|
571
|
+
if (!name.includes(".")) {
|
|
572
|
+
return get(this, name);
|
|
573
|
+
}
|
|
574
|
+
const nameParts = name.split(".");
|
|
575
|
+
let last = this;
|
|
576
|
+
for (const part of nameParts) {
|
|
577
|
+
const indexPart = Number(part);
|
|
578
|
+
const itemIndex = part.match(/items\[(?<itemIndex>\d+)\]/)?.groups?.itemIndex;
|
|
579
|
+
const itemId = part.match(/items\[(?<itemId>@[A-Z]+\d+@)\]/)?.groups?.itemId;
|
|
580
|
+
const usedPart = itemId || itemIndex;
|
|
581
|
+
if (last instanceof List) {
|
|
582
|
+
if (!isNaN(indexPart)) {
|
|
583
|
+
last = last.index(indexPart);
|
|
584
|
+
} else {
|
|
585
|
+
if (usedPart) {
|
|
586
|
+
last = last.item(usedPart);
|
|
587
|
+
} else {
|
|
588
|
+
last = last?.index(0)?.get(part);
|
|
589
|
+
}
|
|
590
|
+
}
|
|
591
|
+
} else {
|
|
592
|
+
const usedIndex = Number(itemIndex ?? indexPart);
|
|
593
|
+
if (!isNaN(usedIndex)) {
|
|
594
|
+
last = last?.toList().index(usedIndex);
|
|
595
|
+
} else {
|
|
596
|
+
last = last?.get(itemId ?? part);
|
|
597
|
+
}
|
|
762
598
|
}
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
this.setLength("increase");
|
|
599
|
+
if (!last) {
|
|
600
|
+
break;
|
|
766
601
|
}
|
|
767
602
|
}
|
|
768
|
-
return
|
|
603
|
+
return last;
|
|
769
604
|
}
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
605
|
+
remove(name) {
|
|
606
|
+
unset(this, name);
|
|
607
|
+
}
|
|
608
|
+
getGedcom() {
|
|
609
|
+
return this._gedcom;
|
|
610
|
+
}
|
|
611
|
+
getIf(name, condition, name2) {
|
|
612
|
+
const nameParts = name.split(".");
|
|
613
|
+
const name2Parts = name2.split(".");
|
|
614
|
+
if (nameParts.length !== name2Parts.length) {
|
|
615
|
+
throw new Error("Tag pathes must be of the same depth");
|
|
774
616
|
}
|
|
775
|
-
|
|
617
|
+
if (nameParts.length > 1 && nameParts[0] !== name2Parts[0]) {
|
|
618
|
+
throw new Error("Final tags must be siblings");
|
|
619
|
+
}
|
|
620
|
+
const valueCommon = this.get(name);
|
|
621
|
+
if (valueCommon instanceof _Common) {
|
|
622
|
+
return valueCommon?.toValue() !== condition ? void 0 : this.get(name2);
|
|
623
|
+
}
|
|
624
|
+
const valueCommon2 = this.get(name2)?.toList();
|
|
625
|
+
const ifList = new List();
|
|
626
|
+
valueCommon?.forEach((item, key) => {
|
|
627
|
+
const pair = valueCommon2?.item(key);
|
|
628
|
+
ifList.item(key, item?.toValue() !== condition ? void 0 : pair);
|
|
629
|
+
});
|
|
630
|
+
return ifList;
|
|
776
631
|
}
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
Object.assign(newList.items, this.items);
|
|
780
|
-
newList.setLength();
|
|
781
|
-
return newList;
|
|
632
|
+
toString() {
|
|
633
|
+
return this.value?.toString() || "";
|
|
782
634
|
}
|
|
783
|
-
|
|
784
|
-
return this.
|
|
635
|
+
toValue() {
|
|
636
|
+
return this.value;
|
|
785
637
|
}
|
|
786
|
-
|
|
787
|
-
this.
|
|
788
|
-
|
|
789
|
-
});
|
|
638
|
+
toProp(tag) {
|
|
639
|
+
const prop = this.get(tag);
|
|
640
|
+
return prop;
|
|
790
641
|
}
|
|
791
|
-
|
|
792
|
-
return
|
|
793
|
-
|
|
794
|
-
|
|
642
|
+
toList() {
|
|
643
|
+
return new List().concat(
|
|
644
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
645
|
+
this.id ? { [this.id]: this } : { ...[this] }
|
|
646
|
+
);
|
|
795
647
|
}
|
|
796
|
-
|
|
797
|
-
return this.
|
|
798
|
-
return iterate(acc, item, key, index);
|
|
799
|
-
}, initialValue);
|
|
648
|
+
index(i) {
|
|
649
|
+
return this.toList()?.index(i);
|
|
800
650
|
}
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
}
|
|
809
|
-
if (!Object.keys(filters).length || Object.entries(filters).every(([key, value]) => {
|
|
810
|
-
let itemValue;
|
|
811
|
-
if (key === "id") {
|
|
812
|
-
itemValue = item.toProp("id");
|
|
813
|
-
} else {
|
|
814
|
-
itemValue = item.toProp(key)?.toValue();
|
|
815
|
-
}
|
|
816
|
-
if (Array.isArray(value)) {
|
|
817
|
-
return value.includes(itemValue);
|
|
818
|
-
}
|
|
819
|
-
return itemValue === value;
|
|
820
|
-
})) {
|
|
821
|
-
newList.item(itemId, item);
|
|
822
|
-
}
|
|
823
|
-
});
|
|
824
|
-
return newList;
|
|
651
|
+
toValueList() {
|
|
652
|
+
return new List().concat(
|
|
653
|
+
this.value ? { [this.value]: this } : (
|
|
654
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
655
|
+
{ ...[this] }
|
|
656
|
+
)
|
|
657
|
+
);
|
|
825
658
|
}
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
659
|
+
standardizeObject(tag, options) {
|
|
660
|
+
if (tag === "OBJE" && options?.obje?.standardize && "standardizeMedia" in this) {
|
|
661
|
+
const standardize = this.standardizeMedia;
|
|
662
|
+
return standardize.call(
|
|
663
|
+
this,
|
|
664
|
+
options.obje.namespace,
|
|
665
|
+
options.obje.override,
|
|
666
|
+
this.isAncestry() ? ancestryMediaFileUrl : void 0,
|
|
667
|
+
options.gedcomVersion
|
|
668
|
+
);
|
|
669
|
+
}
|
|
670
|
+
}
|
|
671
|
+
toJson(tag, options) {
|
|
672
|
+
const json = this.toObject(tag, options);
|
|
673
|
+
return JSON.stringify(json);
|
|
674
|
+
}
|
|
675
|
+
toObject(tag, options) {
|
|
676
|
+
this.standardizeObject(tag, options);
|
|
677
|
+
const validKeys = getValidKeys(this);
|
|
678
|
+
let json = {};
|
|
679
|
+
validKeys.forEach((key) => {
|
|
680
|
+
if (options?.persist && (key === "DAY" || key === "MONTH" || key === "YEAR")) {
|
|
681
|
+
return;
|
|
836
682
|
}
|
|
837
|
-
if (
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
683
|
+
if (key === "id" && this.id !== void 0) {
|
|
684
|
+
json.id = this.id;
|
|
685
|
+
} else if (key === "_id" && this._id !== void 0) {
|
|
686
|
+
json.id = this._id;
|
|
687
|
+
} else if (key === "value" && this.value !== void 0) {
|
|
688
|
+
json.value = this.value;
|
|
689
|
+
} else if (key === "_value" && this._value !== void 0) {
|
|
690
|
+
json.value = this._value;
|
|
691
|
+
} else {
|
|
692
|
+
const validKey = key;
|
|
693
|
+
const prop = this.get(validKey);
|
|
694
|
+
if (typeof prop?.toObject === "function") {
|
|
695
|
+
if (prop instanceof _Common) {
|
|
696
|
+
json[validKey] = prop.toObject(validKey, options);
|
|
697
|
+
} else if (prop instanceof List) {
|
|
698
|
+
json = {
|
|
699
|
+
...json,
|
|
700
|
+
...prop.toObject(validKey, options)
|
|
701
|
+
};
|
|
702
|
+
}
|
|
846
703
|
}
|
|
847
|
-
return itemValue === value;
|
|
848
|
-
})) {
|
|
849
|
-
foundItem = item;
|
|
850
|
-
return true;
|
|
851
704
|
}
|
|
852
|
-
return false;
|
|
853
705
|
});
|
|
854
|
-
return
|
|
706
|
+
return json;
|
|
855
707
|
}
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
if (!isIterator && (!orders || !Object.keys(orders).length)) {
|
|
860
|
-
return newList.merge(this);
|
|
708
|
+
merge(other, override = false, avoidKeys = []) {
|
|
709
|
+
if (!other) {
|
|
710
|
+
return this;
|
|
861
711
|
}
|
|
862
|
-
const
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
}
|
|
867
|
-
const [key, { direction, getter }] = Object.entries(
|
|
868
|
-
typeof orders === "string" ? { [orders]: { direction: "ASC" } } : orders
|
|
869
|
-
)[0];
|
|
870
|
-
const rawA = itemA.get(key);
|
|
871
|
-
const rawB = itemB.get(key);
|
|
872
|
-
let valueA = rawA?.toValue();
|
|
873
|
-
let valueB = rawB?.toValue();
|
|
874
|
-
if (getter && typeof getter === "function") {
|
|
875
|
-
valueA = getter(valueA, rawA);
|
|
876
|
-
valueB = getter(valueB, rawB);
|
|
877
|
-
}
|
|
878
|
-
let sortValue2 = 0;
|
|
879
|
-
if (!valueA && valueA !== 0 && !valueB && valueB !== 0) {
|
|
880
|
-
sortValue2 = 0;
|
|
881
|
-
} else if (!valueB && valueB !== 0) {
|
|
882
|
-
sortValue2 = 1;
|
|
883
|
-
} else if (!valueA && valueA !== 0) {
|
|
884
|
-
sortValue2 = -1;
|
|
885
|
-
} else if (valueA < valueB) {
|
|
886
|
-
sortValue2 = -1;
|
|
887
|
-
} else if (valueA > valueB) {
|
|
888
|
-
sortValue2 = 1;
|
|
889
|
-
}
|
|
890
|
-
return sortValue2 * (direction === "DESC" ? -1 : 1);
|
|
712
|
+
const validKeys = getValidKeys(other);
|
|
713
|
+
validKeys.forEach((validKey) => {
|
|
714
|
+
if (avoidKeys.includes(validKey)) {
|
|
715
|
+
return;
|
|
891
716
|
}
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
groupped.Unknown.marker = "Unknown";
|
|
904
|
-
return groupped;
|
|
905
|
-
}
|
|
906
|
-
this.forEach((item, itemId) => {
|
|
907
|
-
const group = [];
|
|
908
|
-
if (isIterator) {
|
|
909
|
-
const newGroups = groups(item, itemId);
|
|
910
|
-
group.push(
|
|
911
|
-
...Array.isArray(newGroups) ? newGroups : [newGroups]
|
|
912
|
-
);
|
|
913
|
-
} else {
|
|
914
|
-
const [key, { getter }] = Object.entries(
|
|
915
|
-
typeof groups === "string" ? { [groups]: {} } : groups
|
|
916
|
-
)[0];
|
|
917
|
-
const raw = item.get(key)?.index(0);
|
|
918
|
-
let value = raw?.toValue();
|
|
919
|
-
if (getter && typeof getter === "function") {
|
|
920
|
-
value = getter(value, raw);
|
|
921
|
-
}
|
|
922
|
-
if (value) {
|
|
923
|
-
group.push(value);
|
|
717
|
+
const current = this.get(validKey);
|
|
718
|
+
const mergeValue = other.get(validKey);
|
|
719
|
+
if (mergeValue) {
|
|
720
|
+
if (current instanceof _Common && !current.isListable) {
|
|
721
|
+
if (override) {
|
|
722
|
+
this.set(validKey, mergeValue);
|
|
723
|
+
}
|
|
724
|
+
} else if (current instanceof _Common || current instanceof List) {
|
|
725
|
+
this.assign(validKey, mergeValue, true);
|
|
726
|
+
} else if (!current || override && validKey !== "id" && validKey !== "_id") {
|
|
727
|
+
this.set(validKey, mergeValue);
|
|
924
728
|
}
|
|
925
729
|
}
|
|
926
|
-
if (!group.length) {
|
|
927
|
-
group.push("Unknown");
|
|
928
|
-
}
|
|
929
|
-
group.forEach((g) => {
|
|
930
|
-
const newGroup = typeof g === "string" ? { group: g } : g;
|
|
931
|
-
if (!groupped[newGroup.group]) {
|
|
932
|
-
groupped[newGroup.group] = new ClassName();
|
|
933
|
-
groupped[newGroup.group].marker = newGroup.marker ?? newGroup.group;
|
|
934
|
-
}
|
|
935
|
-
groupped[newGroup.group]?.append(item);
|
|
936
|
-
});
|
|
937
730
|
});
|
|
938
|
-
|
|
939
|
-
return Object.entries(groupped).toSorted(([ak, a], [bk, b]) => {
|
|
940
|
-
if (typeof sort === "function") {
|
|
941
|
-
return sort(a, ak, b, bk);
|
|
942
|
-
}
|
|
943
|
-
if (ak === "Unknown") {
|
|
944
|
-
return 1;
|
|
945
|
-
}
|
|
946
|
-
if (bk === "Unknown") {
|
|
947
|
-
return -1;
|
|
948
|
-
}
|
|
949
|
-
if (sort === "group") {
|
|
950
|
-
return ak.localeCompare(bk);
|
|
951
|
-
}
|
|
952
|
-
return (b?.length ?? 0) - (a?.length ?? 0);
|
|
953
|
-
}).reduce((acc, [key, value]) => {
|
|
954
|
-
if (minOccurance > -1 && (value?.length ?? 0) < minOccurance) {
|
|
955
|
-
const otherKey = lessOccuranceLabel;
|
|
956
|
-
acc[otherKey] = acc[otherKey] && value ? acc[otherKey].merge(value) : value;
|
|
957
|
-
} else {
|
|
958
|
-
acc[key] = value;
|
|
959
|
-
}
|
|
960
|
-
return acc;
|
|
961
|
-
}, {});
|
|
962
|
-
}
|
|
963
|
-
return groupped;
|
|
731
|
+
return this;
|
|
964
732
|
}
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
733
|
+
clone(newId = false, avoidKeys = []) {
|
|
734
|
+
const ctor = this.constructor;
|
|
735
|
+
const instance = new ctor(
|
|
736
|
+
this._gedcom,
|
|
737
|
+
this._id,
|
|
738
|
+
this._main,
|
|
739
|
+
this._parent
|
|
740
|
+
);
|
|
741
|
+
if (newId && this._id) {
|
|
742
|
+
instance.id = `IFT${this._id.replace(/[^0-9]/g, "")}`;
|
|
968
743
|
}
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
return this.items;
|
|
973
|
-
}
|
|
974
|
-
toJson(tag, options) {
|
|
975
|
-
const json = this.toObject(tag, options);
|
|
976
|
-
return JSON.stringify(json);
|
|
744
|
+
const cloned = createProxy(instance);
|
|
745
|
+
cloned.merge(this, true, avoidKeys);
|
|
746
|
+
return cloned;
|
|
977
747
|
}
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
this.entries().forEach(([_, item]) => {
|
|
981
|
-
const validTag = getValidTag(tag);
|
|
982
|
-
if (json[validTag]) {
|
|
983
|
-
if (!Array.isArray(json[validTag])) {
|
|
984
|
-
json[validTag] = [json[validTag]];
|
|
985
|
-
}
|
|
986
|
-
json[validTag].push(
|
|
987
|
-
item.toObject(validTag, options)
|
|
988
|
-
);
|
|
989
|
-
} else {
|
|
990
|
-
json[validTag] = item.toObject(
|
|
991
|
-
validTag,
|
|
992
|
-
options
|
|
993
|
-
);
|
|
994
|
-
}
|
|
995
|
-
});
|
|
996
|
-
return json;
|
|
748
|
+
// fromGedcom<T = typeof this>(value: string) {
|
|
749
|
+
fromGedcom(_value) {
|
|
997
750
|
}
|
|
998
751
|
toGedcom(tag, level = 0, options) {
|
|
999
752
|
const gedcom = this.toGedcomLines(tag, level, options);
|
|
1000
753
|
return gedcom.join("\n");
|
|
1001
754
|
}
|
|
1002
755
|
toGedcomLines(tag, level = 0, options) {
|
|
756
|
+
this.standardizeObject(tag, options);
|
|
757
|
+
const validKeys = getValidKeys(this);
|
|
1003
758
|
const gedcom = [];
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
const
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
759
|
+
const isGedcom7Export = options?.gedcomVersion === "7.0";
|
|
760
|
+
validKeys.forEach((key) => {
|
|
761
|
+
const validKey = key;
|
|
762
|
+
if (isGedcom7Export && validKey === "CONC") {
|
|
763
|
+
return;
|
|
764
|
+
}
|
|
765
|
+
const prop = this.get(validKey);
|
|
766
|
+
if (typeof prop?.toGedcomLines === "function") {
|
|
767
|
+
if (prop instanceof _Common) {
|
|
768
|
+
const value = prop.exportValue();
|
|
769
|
+
gedcom.push(
|
|
770
|
+
`${level} ${validKey}${value ? ` ${value}` : ""}`
|
|
771
|
+
);
|
|
772
|
+
gedcom.push(
|
|
773
|
+
...prop.toGedcomLines(validKey, level + 1, options)
|
|
774
|
+
);
|
|
775
|
+
} else if (prop instanceof List) {
|
|
776
|
+
gedcom.push(
|
|
777
|
+
...prop.toGedcomLines(validKey, level, options)
|
|
778
|
+
);
|
|
779
|
+
}
|
|
1016
780
|
}
|
|
1017
|
-
gedcom.push(
|
|
1018
|
-
...item.toGedcomLines(
|
|
1019
|
-
validTag,
|
|
1020
|
-
level + 1,
|
|
1021
|
-
options
|
|
1022
|
-
)
|
|
1023
|
-
);
|
|
1024
781
|
});
|
|
1025
782
|
return gedcom;
|
|
1026
783
|
}
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
this.entries().forEach(([key, item]) => {
|
|
1030
|
-
propList.item(key, item?.toValue());
|
|
1031
|
-
});
|
|
1032
|
-
return propList;
|
|
1033
|
-
}
|
|
1034
|
-
// @deprecated use get instead
|
|
1035
|
-
toProp(tag) {
|
|
1036
|
-
return this.get(tag);
|
|
784
|
+
getHeadRecord() {
|
|
785
|
+
return get(this, "HEAD") || get(this.getGedcom(), "HEAD");
|
|
1037
786
|
}
|
|
1038
|
-
|
|
1039
|
-
return
|
|
787
|
+
getOriginalHeadRecord() {
|
|
788
|
+
return get(this, ORIG_HEAD_TAG) || get(this.getGedcom(), ORIG_HEAD_TAG) || get(this.getHeadRecord(), ORIG_HEAD_TAG);
|
|
1040
789
|
}
|
|
1041
|
-
|
|
1042
|
-
const
|
|
1043
|
-
|
|
1044
|
-
|
|
790
|
+
getSourceHeads() {
|
|
791
|
+
const heads = [this.getOriginalHeadRecord(), this.getHeadRecord()];
|
|
792
|
+
return heads.filter((head, index) => {
|
|
793
|
+
return Boolean(head && heads.indexOf(head) === index);
|
|
1045
794
|
});
|
|
1046
|
-
return newList;
|
|
1047
|
-
}
|
|
1048
|
-
};
|
|
1049
|
-
|
|
1050
|
-
// src/classes/common.ts
|
|
1051
|
-
var Common = class _Common {
|
|
1052
|
-
constructor(gedcom, id, main, parent) {
|
|
1053
|
-
this.isListable = true;
|
|
1054
|
-
this._gedcom = gedcom;
|
|
1055
|
-
this._main = main;
|
|
1056
|
-
this._parent = parent;
|
|
1057
|
-
this.initUniqueId();
|
|
1058
|
-
if (id) {
|
|
1059
|
-
this._id = id;
|
|
1060
|
-
} else {
|
|
1061
|
-
delete this._id;
|
|
1062
|
-
}
|
|
1063
|
-
}
|
|
1064
|
-
set type(type) {
|
|
1065
|
-
if (type) {
|
|
1066
|
-
this.uniqueId = this.uniqueId?.replace(/^[^:]+/, `~${type}`);
|
|
1067
|
-
}
|
|
1068
|
-
this._type = type;
|
|
1069
|
-
}
|
|
1070
|
-
get type() {
|
|
1071
|
-
return this._type;
|
|
1072
|
-
}
|
|
1073
|
-
initUniqueId() {
|
|
1074
|
-
if (this._gedcom) {
|
|
1075
|
-
this.uniqueId = `~Common:${this._gedcom.refcount++}`;
|
|
1076
|
-
}
|
|
1077
795
|
}
|
|
1078
|
-
|
|
1079
|
-
const
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
delete this._gedcom.reflist[currentId];
|
|
796
|
+
getFromSourceHeads(path) {
|
|
797
|
+
for (const head of this.getSourceHeads()) {
|
|
798
|
+
const value = get(head, path);
|
|
799
|
+
if (value !== void 0 && value !== null && value !== "") {
|
|
800
|
+
return value;
|
|
1084
801
|
}
|
|
1085
|
-
this._gedcom.reflist[id] = this;
|
|
1086
802
|
}
|
|
803
|
+
return void 0;
|
|
1087
804
|
}
|
|
1088
|
-
|
|
1089
|
-
return this.
|
|
805
|
+
sourStartsWith(prefix) {
|
|
806
|
+
return this.getSourceHeads().some((head) => {
|
|
807
|
+
const sour = get(head, "SOUR.value");
|
|
808
|
+
return !!sour?.toLowerCase()?.startsWith(prefix);
|
|
809
|
+
});
|
|
1090
810
|
}
|
|
1091
|
-
|
|
1092
|
-
this.
|
|
811
|
+
isGenoPro() {
|
|
812
|
+
return this.sourStartsWith("genopro");
|
|
1093
813
|
}
|
|
1094
|
-
|
|
1095
|
-
return
|
|
814
|
+
isAhnenblatt() {
|
|
815
|
+
return this.sourStartsWith("ahnenblatt");
|
|
1096
816
|
}
|
|
1097
|
-
|
|
1098
|
-
this.
|
|
817
|
+
isGeni() {
|
|
818
|
+
return this.sourStartsWith("geni");
|
|
1099
819
|
}
|
|
1100
|
-
|
|
1101
|
-
return this.
|
|
820
|
+
isAncestry() {
|
|
821
|
+
return this.sourStartsWith("ancestry");
|
|
822
|
+
}
|
|
823
|
+
isMyHeritage() {
|
|
824
|
+
return this.sourStartsWith("myheritage");
|
|
1102
825
|
}
|
|
1103
826
|
/**
|
|
1104
|
-
*
|
|
1105
|
-
*
|
|
827
|
+
* Get the source type as a string (for prefixing tree IDs and names)
|
|
828
|
+
* Returns the detected source type or undefined if unknown
|
|
1106
829
|
*/
|
|
1107
|
-
|
|
1108
|
-
this.
|
|
830
|
+
getSourceType() {
|
|
831
|
+
if (this.isAncestry()) return "Ancestry";
|
|
832
|
+
if (this.isMyHeritage()) return "MyHeritage";
|
|
833
|
+
if (this.isFamilySearch()) return "FamilySearch";
|
|
834
|
+
if (this.isGNO2GED()) return "GNO2GED";
|
|
835
|
+
if (this.isGenoPro()) return "GenoPro";
|
|
836
|
+
if (this.isAhnenblatt()) return "Ahnenblatt";
|
|
837
|
+
if (this.isGeni()) return "Geni";
|
|
838
|
+
return void 0;
|
|
1109
839
|
}
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
840
|
+
isFamilySearch() {
|
|
841
|
+
return this.getSourceHeads().some((head) => {
|
|
842
|
+
const sourName = get(head, "SOUR.NAME.value");
|
|
843
|
+
return sourName === "FamilySearch API";
|
|
844
|
+
});
|
|
1113
845
|
}
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
);
|
|
1120
|
-
}
|
|
1121
|
-
return this;
|
|
846
|
+
isGNO2GED() {
|
|
847
|
+
return this.getSourceHeads().some((head) => {
|
|
848
|
+
const sour = get(head, "SOUR.value");
|
|
849
|
+
return sour === "GNO2GED";
|
|
850
|
+
});
|
|
1122
851
|
}
|
|
1123
|
-
|
|
1124
|
-
return this.
|
|
852
|
+
getAncestryTreeId() {
|
|
853
|
+
return this.getFromSourceHeads("SOUR._TREE.RIN.value") || (get(this, "HEAD.SOUR._TREE.RIN.value") || get(this.getGedcom(), "HEAD.SOUR._TREE.RIN.value"));
|
|
1125
854
|
}
|
|
1126
|
-
|
|
1127
|
-
return this.
|
|
855
|
+
getMyHeritageTreeId() {
|
|
856
|
+
return this.getFromSourceHeads("_EXPORTED_FROM_SITE_ID.value") || (get(this, "HEAD._EXPORTED_FROM_SITE_ID.value") || get(this.getGedcom(), "HEAD._EXPORTED_FROM_SITE_ID.value"));
|
|
1128
857
|
}
|
|
1129
|
-
|
|
1130
|
-
if (
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
}
|
|
1134
|
-
this._refs.item(refNode.value, refNode);
|
|
858
|
+
getTreeId() {
|
|
859
|
+
if (this?.isAncestry()) {
|
|
860
|
+
const id = this.getAncestryTreeId();
|
|
861
|
+
if (id !== void 0) return id;
|
|
1135
862
|
}
|
|
863
|
+
if (this?.isMyHeritage()) {
|
|
864
|
+
const id = this.getMyHeritageTreeId();
|
|
865
|
+
if (id !== void 0) return id;
|
|
866
|
+
}
|
|
867
|
+
if (this?.isFamilySearch()) {
|
|
868
|
+
const id = this.getFamilySearchTreeId();
|
|
869
|
+
if (id !== void 0) return id;
|
|
870
|
+
}
|
|
871
|
+
if (this?.isGNO2GED()) {
|
|
872
|
+
const id = this.getGNO2GEDTreeId();
|
|
873
|
+
if (id !== void 0) return id;
|
|
874
|
+
}
|
|
875
|
+
if (this?.isAhnenblatt()) {
|
|
876
|
+
const id = this.getAhnenblattTreeId();
|
|
877
|
+
if (id !== void 0) return id;
|
|
878
|
+
}
|
|
879
|
+
if (this?.isGeni()) {
|
|
880
|
+
const id = this.getGeniTreeId();
|
|
881
|
+
if (id !== void 0) return id;
|
|
882
|
+
}
|
|
883
|
+
if (this?.isGenoPro()) {
|
|
884
|
+
const id = this.getGenoProTreeId();
|
|
885
|
+
if (id !== void 0) return id;
|
|
886
|
+
}
|
|
887
|
+
return this.getUniversalTreeId();
|
|
1136
888
|
}
|
|
1137
|
-
|
|
1138
|
-
return this.
|
|
1139
|
-
}
|
|
1140
|
-
exportValue() {
|
|
1141
|
-
return this.value;
|
|
889
|
+
getAncestryTreeName() {
|
|
890
|
+
return this.getFromSourceHeads("SOUR._TREE.value") || (get(this, "HEAD.SOUR._TREE.value") || get(this.getGedcom(), "HEAD.SOUR._TREE.value"));
|
|
1142
891
|
}
|
|
1143
|
-
|
|
1144
|
-
|
|
892
|
+
getMyHeritageTreeName() {
|
|
893
|
+
const path = "HEAD.FILE.value";
|
|
894
|
+
const treeDetails = get(this, path) || get(this.getGedcom(), path);
|
|
895
|
+
return treeDetails?.match(
|
|
896
|
+
/Exported by MyHeritage.com from (?<tree>.+) in.+$/
|
|
897
|
+
)?.groups?.tree;
|
|
1145
898
|
}
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
899
|
+
getFamilySearchTreeId() {
|
|
900
|
+
const rin = this.getFromSourceHeads("SOUR._TREE.RIN.value") || get(this, "HEAD.SOUR._TREE.RIN.value") || get(this.getGedcom(), "HEAD.SOUR._TREE.RIN.value");
|
|
901
|
+
if (rin) {
|
|
902
|
+
return rin;
|
|
1149
903
|
}
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
904
|
+
return "familysearch";
|
|
905
|
+
}
|
|
906
|
+
getFamilySearchTreeName() {
|
|
907
|
+
const treeName = this.getFromSourceHeads("SOUR._TREE.value") || get(this, "HEAD.SOUR._TREE.value") || get(this.getGedcom(), "HEAD.SOUR._TREE.value");
|
|
908
|
+
if (treeName) {
|
|
909
|
+
return treeName;
|
|
1156
910
|
}
|
|
1157
|
-
|
|
911
|
+
const fileName = get(this, "HEAD.FILE.value") || get(this.getGedcom(), "HEAD.FILE.value");
|
|
912
|
+
return fileName || "FamilySearch Import";
|
|
1158
913
|
}
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
914
|
+
getAhnenblattTreeId() {
|
|
915
|
+
const fileName = get(this, "HEAD.FILE.value") || get(this.getGedcom(), "HEAD.FILE.value");
|
|
916
|
+
if (fileName) {
|
|
917
|
+
const idMatch = fileName.match(/_(\d+)/);
|
|
918
|
+
if (idMatch) {
|
|
919
|
+
return idMatch[1];
|
|
920
|
+
}
|
|
1162
921
|
}
|
|
1163
|
-
|
|
1164
|
-
if (curValue?.isListable) {
|
|
1165
|
-
if (curValue instanceof _Common) {
|
|
1166
|
-
curValue = new List().concat({ ...[curValue] });
|
|
1167
|
-
this.set(name, curValue);
|
|
1168
|
-
}
|
|
1169
|
-
const values = [
|
|
1170
|
-
...curValue.values(),
|
|
1171
|
-
...value instanceof List ? value.values() : [value]
|
|
1172
|
-
];
|
|
1173
|
-
curValue.concat({
|
|
1174
|
-
...!unique ? values : uniqBy(
|
|
1175
|
-
values,
|
|
1176
|
-
(value2) => value2 instanceof _Common ? value2?.value : void 0
|
|
1177
|
-
)
|
|
1178
|
-
});
|
|
1179
|
-
} else {
|
|
1180
|
-
this.set(name, value);
|
|
1181
|
-
}
|
|
1182
|
-
return get(this, name);
|
|
922
|
+
return void 0;
|
|
1183
923
|
}
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
const
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
const usedPart = itemId || itemIndex;
|
|
1195
|
-
if (last instanceof List) {
|
|
1196
|
-
if (!isNaN(indexPart)) {
|
|
1197
|
-
last = last.index(indexPart);
|
|
1198
|
-
} else {
|
|
1199
|
-
if (usedPart) {
|
|
1200
|
-
last = last.item(usedPart);
|
|
1201
|
-
} else {
|
|
1202
|
-
last = last?.index(0)?.get(part);
|
|
1203
|
-
}
|
|
1204
|
-
}
|
|
1205
|
-
} else {
|
|
1206
|
-
const usedIndex = Number(itemIndex ?? indexPart);
|
|
1207
|
-
if (!isNaN(usedIndex)) {
|
|
1208
|
-
last = last?.toList().index(usedIndex);
|
|
1209
|
-
} else {
|
|
1210
|
-
last = last?.get(itemId ?? part);
|
|
1211
|
-
}
|
|
1212
|
-
}
|
|
1213
|
-
if (!last) {
|
|
1214
|
-
break;
|
|
924
|
+
getAhnenblattTreeName() {
|
|
925
|
+
const fileName = get(this, "HEAD.FILE.value") || get(this.getGedcom(), "HEAD.FILE.value");
|
|
926
|
+
return fileName?.replace(/\.ged$/i, "").replace(/_/g, " ");
|
|
927
|
+
}
|
|
928
|
+
getGeniTreeId() {
|
|
929
|
+
const fileName = get(this, "HEAD.FILE.value") || get(this.getGedcom(), "HEAD.FILE.value");
|
|
930
|
+
if (fileName) {
|
|
931
|
+
const idMatch = fileName.match(/_(\d+)/);
|
|
932
|
+
if (idMatch) {
|
|
933
|
+
return idMatch[1];
|
|
1215
934
|
}
|
|
1216
935
|
}
|
|
1217
|
-
return
|
|
1218
|
-
}
|
|
1219
|
-
remove(name) {
|
|
1220
|
-
unset(this, name);
|
|
936
|
+
return void 0;
|
|
1221
937
|
}
|
|
1222
|
-
|
|
1223
|
-
|
|
938
|
+
getGeniTreeName() {
|
|
939
|
+
const fileName = get(this, "HEAD.FILE.value") || get(this.getGedcom(), "HEAD.FILE.value");
|
|
940
|
+
return fileName?.replace(/\.ged$/i, "").replace(/_/g, " ");
|
|
1224
941
|
}
|
|
1225
|
-
|
|
1226
|
-
const
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
throw new Error("Final tags must be siblings");
|
|
1233
|
-
}
|
|
1234
|
-
const valueCommon = this.get(name);
|
|
1235
|
-
if (valueCommon instanceof _Common) {
|
|
1236
|
-
return valueCommon?.toValue() !== condition ? void 0 : this.get(name2);
|
|
942
|
+
getGenoProTreeId() {
|
|
943
|
+
const fileName = get(this, "HEAD.FILE.value") || get(this.getGedcom(), "HEAD.FILE.value");
|
|
944
|
+
if (fileName) {
|
|
945
|
+
const idMatch = fileName.match(/_(\d+)/);
|
|
946
|
+
if (idMatch) {
|
|
947
|
+
return idMatch[1];
|
|
948
|
+
}
|
|
1237
949
|
}
|
|
1238
|
-
|
|
1239
|
-
const ifList = new List();
|
|
1240
|
-
valueCommon?.forEach((item, key) => {
|
|
1241
|
-
const pair = valueCommon2?.item(key);
|
|
1242
|
-
ifList.item(key, item?.toValue() !== condition ? void 0 : pair);
|
|
1243
|
-
});
|
|
1244
|
-
return ifList;
|
|
1245
|
-
}
|
|
1246
|
-
toString() {
|
|
1247
|
-
return this.value?.toString() || "";
|
|
1248
|
-
}
|
|
1249
|
-
toValue() {
|
|
1250
|
-
return this.value;
|
|
950
|
+
return void 0;
|
|
1251
951
|
}
|
|
1252
|
-
|
|
1253
|
-
const
|
|
1254
|
-
return
|
|
952
|
+
getGenoProTreeName() {
|
|
953
|
+
const fileName = get(this, "HEAD.FILE.value") || get(this.getGedcom(), "HEAD.FILE.value");
|
|
954
|
+
return fileName?.replace(/\.ged$/i, "").replace(/_/g, " ");
|
|
1255
955
|
}
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
956
|
+
getGNO2GEDTreeId() {
|
|
957
|
+
const rin = get(this, "HEAD._TREE.RIN.value") || get(this.getGedcom(), "HEAD._TREE.RIN.value");
|
|
958
|
+
if (rin) {
|
|
959
|
+
return rin;
|
|
960
|
+
}
|
|
961
|
+
return `gno_${this._gedcom?.refcount || "unknown"}`;
|
|
1261
962
|
}
|
|
1262
|
-
|
|
1263
|
-
|
|
963
|
+
getGNO2GEDTreeName() {
|
|
964
|
+
const treeName = get(this, "HEAD._TREE.value") || get(this.getGedcom(), "HEAD._TREE.value");
|
|
965
|
+
if (treeName) {
|
|
966
|
+
return treeName;
|
|
967
|
+
}
|
|
968
|
+
const fileName = get(this, "HEAD.FILE.value") || get(this.getGedcom(), "HEAD.FILE.value");
|
|
969
|
+
return fileName || "GNO2GED Export";
|
|
1264
970
|
}
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
);
|
|
971
|
+
/**
|
|
972
|
+
* Universal tree ID getter for unknown/unrecognized GEDCOM sources
|
|
973
|
+
* Tries to extract an ID from various common locations
|
|
974
|
+
*/
|
|
975
|
+
getUniversalTreeId() {
|
|
976
|
+
const sourceType = this.getSourceType();
|
|
977
|
+
const prefix = sourceType ? sourceType.toLowerCase() : "tree";
|
|
978
|
+
const fileName = get(this, "HEAD.FILE.value") || get(this.getGedcom(), "HEAD.FILE.value");
|
|
979
|
+
if (fileName) {
|
|
980
|
+
const idMatch = fileName.match(/_(\d+)/);
|
|
981
|
+
if (idMatch) {
|
|
982
|
+
return `${prefix}_${idMatch[1]}`;
|
|
983
|
+
}
|
|
984
|
+
}
|
|
985
|
+
return `${prefix}_${this._gedcom?.refcount || "unknown"}`;
|
|
1272
986
|
}
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
);
|
|
987
|
+
/**
|
|
988
|
+
* Universal tree name getter for unknown/unrecognized GEDCOM sources
|
|
989
|
+
* Tries to extract a name from various common locations
|
|
990
|
+
*/
|
|
991
|
+
getUniversalTreeName() {
|
|
992
|
+
const sourceType = this.getSourceType();
|
|
993
|
+
const prefix = sourceType ? `${sourceType}-` : "";
|
|
994
|
+
const fileName = get(this, "HEAD.FILE.value") || get(this.getGedcom(), "HEAD.FILE.value");
|
|
995
|
+
if (fileName) {
|
|
996
|
+
const cleanName = fileName.replace(/\.ged$/i, "").replace(/_/g, " ");
|
|
997
|
+
return `${prefix}${cleanName}`;
|
|
998
|
+
}
|
|
999
|
+
const sourName = this.getFromSourceHeads("SOUR.NAME.value") || get(this, "HEAD.SOUR.NAME.value") || get(this.getGedcom(), "HEAD.SOUR.NAME.value");
|
|
1000
|
+
if (sourName) {
|
|
1001
|
+
return `${prefix}${sourName}`;
|
|
1002
|
+
}
|
|
1003
|
+
const sourValue = this.getFromSourceHeads("SOUR.value") || get(this, "HEAD.SOUR.value") || get(this.getGedcom(), "HEAD.SOUR.value");
|
|
1004
|
+
if (sourValue) {
|
|
1005
|
+
return `${prefix}${sourValue}`;
|
|
1283
1006
|
}
|
|
1007
|
+
return `${prefix}Unknown Tree`;
|
|
1284
1008
|
}
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1009
|
+
getTreeName() {
|
|
1010
|
+
if (this?.isAncestry()) {
|
|
1011
|
+
const name = this.getAncestryTreeName();
|
|
1012
|
+
if (name) return name;
|
|
1013
|
+
}
|
|
1014
|
+
if (this?.isMyHeritage()) {
|
|
1015
|
+
const name = this.getMyHeritageTreeName();
|
|
1016
|
+
if (name) return name;
|
|
1017
|
+
}
|
|
1018
|
+
if (this?.isFamilySearch()) {
|
|
1019
|
+
const name = this.getFamilySearchTreeName();
|
|
1020
|
+
if (name) return name;
|
|
1021
|
+
}
|
|
1022
|
+
if (this?.isGNO2GED()) {
|
|
1023
|
+
const name = this.getGNO2GEDTreeName();
|
|
1024
|
+
if (name) return name;
|
|
1025
|
+
}
|
|
1026
|
+
if (this?.isAhnenblatt()) {
|
|
1027
|
+
const name = this.getAhnenblattTreeName();
|
|
1028
|
+
if (name) return name;
|
|
1029
|
+
}
|
|
1030
|
+
if (this?.isGeni()) {
|
|
1031
|
+
const name = this.getGeniTreeName();
|
|
1032
|
+
if (name) return name;
|
|
1033
|
+
}
|
|
1034
|
+
if (this?.isGenoPro()) {
|
|
1035
|
+
const name = this.getGenoProTreeName();
|
|
1036
|
+
if (name) return name;
|
|
1037
|
+
}
|
|
1038
|
+
return this.getUniversalTreeName();
|
|
1288
1039
|
}
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
return;
|
|
1040
|
+
};
|
|
1041
|
+
var createProxy = (target) => {
|
|
1042
|
+
return new Proxy(target, {
|
|
1043
|
+
get(t, prop, receiver) {
|
|
1044
|
+
if (prop === "unwrapped") {
|
|
1045
|
+
return target;
|
|
1296
1046
|
}
|
|
1297
|
-
if (
|
|
1298
|
-
|
|
1299
|
-
}
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
json.value = this._value;
|
|
1305
|
-
} else {
|
|
1306
|
-
const validKey = key;
|
|
1307
|
-
const prop = this.get(validKey);
|
|
1308
|
-
if (typeof prop?.toObject === "function") {
|
|
1309
|
-
if (prop instanceof _Common) {
|
|
1310
|
-
json[validKey] = prop.toObject(validKey, options);
|
|
1311
|
-
} else if (prop instanceof List) {
|
|
1312
|
-
json = {
|
|
1313
|
-
...json,
|
|
1314
|
-
...prop.toObject(validKey, options)
|
|
1315
|
-
};
|
|
1316
|
-
}
|
|
1047
|
+
if (prop in t) {
|
|
1048
|
+
return Reflect.get(t, prop, receiver);
|
|
1049
|
+
}
|
|
1050
|
+
if (!isOnlyMainProp(prop)) {
|
|
1051
|
+
const ref = t.ref;
|
|
1052
|
+
if (ref && prop in ref) {
|
|
1053
|
+
return Reflect.get(ref, prop, receiver);
|
|
1317
1054
|
}
|
|
1318
1055
|
}
|
|
1319
|
-
});
|
|
1320
|
-
return json;
|
|
1321
|
-
}
|
|
1322
|
-
merge(other, override = false, avoidKeys = []) {
|
|
1323
|
-
if (!other) {
|
|
1324
|
-
return this;
|
|
1325
|
-
}
|
|
1326
|
-
const validKeys = getValidKeys(other);
|
|
1327
|
-
validKeys.forEach((validKey) => {
|
|
1328
|
-
if (avoidKeys.includes(validKey)) {
|
|
1329
|
-
return;
|
|
1330
|
-
}
|
|
1331
|
-
const current = this.get(validKey);
|
|
1332
|
-
const mergeValue = other.get(validKey);
|
|
1333
|
-
if (mergeValue) {
|
|
1334
|
-
if (current instanceof _Common || current instanceof List) {
|
|
1335
|
-
this.assign(validKey, mergeValue, true);
|
|
1336
|
-
} else if (!current || override && validKey !== "id" && validKey !== "_id") {
|
|
1337
|
-
this.set(validKey, mergeValue);
|
|
1338
|
-
}
|
|
1339
|
-
}
|
|
1340
|
-
});
|
|
1341
|
-
return this;
|
|
1342
|
-
}
|
|
1343
|
-
clone(newId = false, avoidKeys = []) {
|
|
1344
|
-
const ctor = this.constructor;
|
|
1345
|
-
const instance = new ctor(
|
|
1346
|
-
this._gedcom,
|
|
1347
|
-
this._id,
|
|
1348
|
-
this._main,
|
|
1349
|
-
this._parent
|
|
1350
|
-
);
|
|
1351
|
-
if (newId && this._id) {
|
|
1352
|
-
instance.id = `IFT${this._id.replace(/[^0-9]/g, "")}`;
|
|
1353
1056
|
}
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
|
|
1057
|
+
});
|
|
1058
|
+
};
|
|
1059
|
+
var createCommon = (gedcom, id, main, parent) => {
|
|
1060
|
+
return createProxy(
|
|
1061
|
+
new Common(gedcom, id, main, parent)
|
|
1062
|
+
);
|
|
1063
|
+
};
|
|
1064
|
+
var isOnlyMainProp = (key) => {
|
|
1065
|
+
return key === "_gedcom" || key === "_main" || key === "_parent" || key === "_uniqueId" || key === "_type" || key === "_refs" || key === "id" || key === "_id";
|
|
1066
|
+
};
|
|
1067
|
+
var isValidKey = (common, key) => {
|
|
1068
|
+
const prop = get(common, key);
|
|
1069
|
+
return key !== "_gedcom" && key !== "_main" && key !== "_parent" && key !== "_uniqueId" && key !== "_refs" && key !== "_type" && !(typeof key === "string" && isGedcomTrailerTag(key)) && (key === "id" || key === "_id" || key === "value" || key === "_value" || prop instanceof Common || prop instanceof List);
|
|
1070
|
+
};
|
|
1071
|
+
var getValidKeys = (common) => {
|
|
1072
|
+
return Object.keys(common).filter((key) => {
|
|
1073
|
+
return isValidKey(common, key);
|
|
1074
|
+
});
|
|
1075
|
+
};
|
|
1076
|
+
var getValidTag = (tag) => {
|
|
1077
|
+
return tag.replace(/^@@/, "");
|
|
1078
|
+
};
|
|
1079
|
+
var getListTag = (tag) => {
|
|
1080
|
+
return `@@${tag}`;
|
|
1081
|
+
};
|
|
1082
|
+
var isId = (string) => {
|
|
1083
|
+
return ID_REG.test(string);
|
|
1084
|
+
};
|
|
1085
|
+
var idGetter = (id) => {
|
|
1086
|
+
if (id === void 0) {
|
|
1087
|
+
return void 0;
|
|
1357
1088
|
}
|
|
1358
|
-
|
|
1359
|
-
|
|
1089
|
+
let newId = `${id}`;
|
|
1090
|
+
const parts = newId?.match(ID_GETTER_REG)?.groups;
|
|
1091
|
+
if (!parts?.at && !parts?.letter) {
|
|
1092
|
+
newId = `@U${newId}`;
|
|
1093
|
+
} else if (!parts.at) {
|
|
1094
|
+
newId = `@${newId}`;
|
|
1095
|
+
} else if (!parts.letter) {
|
|
1096
|
+
newId = newId.replace(/^@/, "@U");
|
|
1360
1097
|
}
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
return gedcom.join("\n");
|
|
1098
|
+
if (!newId.endsWith("@")) {
|
|
1099
|
+
newId = `${newId}@`;
|
|
1364
1100
|
}
|
|
1365
|
-
|
|
1366
|
-
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
const value = prop.exportValue();
|
|
1379
|
-
gedcom.push(
|
|
1380
|
-
`${level} ${validKey}${value ? ` ${value}` : ""}`
|
|
1381
|
-
);
|
|
1382
|
-
gedcom.push(
|
|
1383
|
-
...prop.toGedcomLines(validKey, level + 1, options)
|
|
1384
|
-
);
|
|
1385
|
-
} else if (prop instanceof List) {
|
|
1386
|
-
gedcom.push(
|
|
1387
|
-
...prop.toGedcomLines(validKey, level, options)
|
|
1388
|
-
);
|
|
1389
|
-
}
|
|
1390
|
-
}
|
|
1391
|
-
});
|
|
1392
|
-
return gedcom;
|
|
1101
|
+
return newId;
|
|
1102
|
+
};
|
|
1103
|
+
|
|
1104
|
+
// src/classes/list.ts
|
|
1105
|
+
var List = class _List {
|
|
1106
|
+
// length = 0;
|
|
1107
|
+
constructor(items) {
|
|
1108
|
+
this.items = {};
|
|
1109
|
+
this.isListable = true;
|
|
1110
|
+
this.marker = void 0;
|
|
1111
|
+
if (items) {
|
|
1112
|
+
this.concat(items);
|
|
1113
|
+
}
|
|
1393
1114
|
}
|
|
1394
|
-
|
|
1395
|
-
return
|
|
1115
|
+
get length() {
|
|
1116
|
+
return this.values().length;
|
|
1396
1117
|
}
|
|
1397
|
-
|
|
1398
|
-
return
|
|
1118
|
+
has(indi) {
|
|
1119
|
+
return !!this.item(
|
|
1120
|
+
typeof indi === "string" ? indi : indi?.id ?? ""
|
|
1121
|
+
);
|
|
1399
1122
|
}
|
|
1400
|
-
|
|
1401
|
-
const
|
|
1402
|
-
|
|
1403
|
-
|
|
1123
|
+
get(name) {
|
|
1124
|
+
const propList = new _List();
|
|
1125
|
+
this.entries().forEach(([key, item]) => {
|
|
1126
|
+
propList.item(key, item.get(name));
|
|
1404
1127
|
});
|
|
1128
|
+
return propList;
|
|
1405
1129
|
}
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
|
|
1130
|
+
getIf(name, condition, name2) {
|
|
1131
|
+
const propList = new _List();
|
|
1132
|
+
this.entries().forEach(([key, item]) => {
|
|
1133
|
+
const passedItem = item.getIf(name, condition, name2);
|
|
1134
|
+
if (passedItem) {
|
|
1135
|
+
propList.item(key, passedItem);
|
|
1411
1136
|
}
|
|
1412
|
-
}
|
|
1413
|
-
return void 0;
|
|
1414
|
-
}
|
|
1415
|
-
sourStartsWith(prefix) {
|
|
1416
|
-
return this.getSourceHeads().some((head) => {
|
|
1417
|
-
const sour = get(head, "SOUR.value");
|
|
1418
|
-
return !!sour?.toLowerCase()?.startsWith(prefix);
|
|
1419
1137
|
});
|
|
1138
|
+
return propList;
|
|
1420
1139
|
}
|
|
1421
|
-
|
|
1422
|
-
return this.
|
|
1140
|
+
keys() {
|
|
1141
|
+
return Object.keys(this.items);
|
|
1423
1142
|
}
|
|
1424
|
-
|
|
1425
|
-
return this.
|
|
1143
|
+
values() {
|
|
1144
|
+
return Object.values(this.items);
|
|
1426
1145
|
}
|
|
1427
|
-
|
|
1428
|
-
return this.
|
|
1146
|
+
entries() {
|
|
1147
|
+
return Object.entries(this.items);
|
|
1429
1148
|
}
|
|
1430
|
-
|
|
1431
|
-
return this.sourStartsWith("ancestry");
|
|
1149
|
+
setLength(_type) {
|
|
1432
1150
|
}
|
|
1433
|
-
|
|
1434
|
-
return this.
|
|
1151
|
+
first() {
|
|
1152
|
+
return this.index(0);
|
|
1435
1153
|
}
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
* Returns the detected source type or undefined if unknown
|
|
1439
|
-
*/
|
|
1440
|
-
getSourceType() {
|
|
1441
|
-
if (this.isAncestry()) return "Ancestry";
|
|
1442
|
-
if (this.isMyHeritage()) return "MyHeritage";
|
|
1443
|
-
if (this.isFamilySearch()) return "FamilySearch";
|
|
1444
|
-
if (this.isGNO2GED()) return "GNO2GED";
|
|
1445
|
-
if (this.isGenoPro()) return "GenoPro";
|
|
1446
|
-
if (this.isAhnenblatt()) return "Ahnenblatt";
|
|
1447
|
-
if (this.isGeni()) return "Geni";
|
|
1448
|
-
return void 0;
|
|
1154
|
+
last() {
|
|
1155
|
+
return this.index(this.keys().length - 1);
|
|
1449
1156
|
}
|
|
1450
|
-
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
});
|
|
1157
|
+
index(index) {
|
|
1158
|
+
const keys = this.keys();
|
|
1159
|
+
const key = keys[index];
|
|
1160
|
+
return key && this.items[key];
|
|
1455
1161
|
}
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
}
|
|
1162
|
+
item(name, value) {
|
|
1163
|
+
if (arguments.length > 1) {
|
|
1164
|
+
set(this.items, name, value);
|
|
1165
|
+
this.setLength();
|
|
1166
|
+
}
|
|
1167
|
+
return get(this.items, name);
|
|
1461
1168
|
}
|
|
1462
|
-
|
|
1463
|
-
|
|
1169
|
+
removeItem(name) {
|
|
1170
|
+
unset(this.items, name);
|
|
1171
|
+
this.setLength();
|
|
1464
1172
|
}
|
|
1465
|
-
|
|
1466
|
-
|
|
1173
|
+
exclude(excludedList) {
|
|
1174
|
+
excludedList.keys().forEach((itemId) => {
|
|
1175
|
+
delete this.items[itemId];
|
|
1176
|
+
});
|
|
1177
|
+
this.setLength();
|
|
1178
|
+
return this;
|
|
1467
1179
|
}
|
|
1468
|
-
|
|
1469
|
-
if (
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
|
|
1474
|
-
|
|
1475
|
-
if (id !== void 0) return id;
|
|
1476
|
-
}
|
|
1477
|
-
if (this?.isFamilySearch()) {
|
|
1478
|
-
const id = this.getFamilySearchTreeId();
|
|
1479
|
-
if (id !== void 0) return id;
|
|
1480
|
-
}
|
|
1481
|
-
if (this?.isGNO2GED()) {
|
|
1482
|
-
const id = this.getGNO2GEDTreeId();
|
|
1483
|
-
if (id !== void 0) return id;
|
|
1484
|
-
}
|
|
1485
|
-
if (this?.isAhnenblatt()) {
|
|
1486
|
-
const id = this.getAhnenblattTreeId();
|
|
1487
|
-
if (id !== void 0) return id;
|
|
1180
|
+
concat(items) {
|
|
1181
|
+
if (Array.isArray(items)) {
|
|
1182
|
+
items.forEach((item) => {
|
|
1183
|
+
this.append(item);
|
|
1184
|
+
});
|
|
1185
|
+
} else {
|
|
1186
|
+
Object.assign(this.items, items ?? {});
|
|
1488
1187
|
}
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
if (id !== void 0) return id;
|
|
1492
|
-
}
|
|
1493
|
-
if (this?.isGenoPro()) {
|
|
1494
|
-
const id = this.getGenoProTreeId();
|
|
1495
|
-
if (id !== void 0) return id;
|
|
1496
|
-
}
|
|
1497
|
-
return this.getUniversalTreeId();
|
|
1498
|
-
}
|
|
1499
|
-
getAncestryTreeName() {
|
|
1500
|
-
return this.getFromSourceHeads("SOUR._TREE.value") || (get(this, "HEAD.SOUR._TREE.value") || get(this.getGedcom(), "HEAD.SOUR._TREE.value"));
|
|
1188
|
+
this.setLength();
|
|
1189
|
+
return this;
|
|
1501
1190
|
}
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
|
|
1505
|
-
return treeDetails?.match(
|
|
1506
|
-
/Exported by MyHeritage.com from (?<tree>.+) in.+$/
|
|
1507
|
-
)?.groups?.tree;
|
|
1191
|
+
merge(mergedList) {
|
|
1192
|
+
this.concat(mergedList?.items);
|
|
1193
|
+
return this;
|
|
1508
1194
|
}
|
|
1509
|
-
|
|
1510
|
-
const
|
|
1511
|
-
|
|
1512
|
-
|
|
1513
|
-
|
|
1514
|
-
|
|
1195
|
+
intersection(mergedList) {
|
|
1196
|
+
const inter = intersectionBy(
|
|
1197
|
+
this.values(),
|
|
1198
|
+
mergedList?.values() ?? [],
|
|
1199
|
+
"id"
|
|
1200
|
+
);
|
|
1201
|
+
return new _List(inter);
|
|
1515
1202
|
}
|
|
1516
|
-
|
|
1517
|
-
const
|
|
1518
|
-
|
|
1519
|
-
|
|
1520
|
-
|
|
1521
|
-
|
|
1522
|
-
return
|
|
1203
|
+
difference(mergedList) {
|
|
1204
|
+
const inter = differenceBy(
|
|
1205
|
+
this.values(),
|
|
1206
|
+
mergedList?.values() ?? [],
|
|
1207
|
+
"id"
|
|
1208
|
+
);
|
|
1209
|
+
return new _List(inter);
|
|
1523
1210
|
}
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
|
|
1529
|
-
|
|
1211
|
+
prepend(item) {
|
|
1212
|
+
if (item.id) {
|
|
1213
|
+
let increase = true;
|
|
1214
|
+
if (this.items[item.id]) {
|
|
1215
|
+
delete this.items[item.id];
|
|
1216
|
+
increase = false;
|
|
1530
1217
|
}
|
|
1531
|
-
|
|
1532
|
-
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
|
|
1537
|
-
|
|
1538
|
-
|
|
1539
|
-
const fileName = get(this, "HEAD.FILE.value") || get(this.getGedcom(), "HEAD.FILE.value");
|
|
1540
|
-
if (fileName) {
|
|
1541
|
-
const idMatch = fileName.match(/_(\d+)/);
|
|
1542
|
-
if (idMatch) {
|
|
1543
|
-
return idMatch[1];
|
|
1218
|
+
this.items = Object.assign(
|
|
1219
|
+
{
|
|
1220
|
+
[item.id]: item
|
|
1221
|
+
},
|
|
1222
|
+
this.items
|
|
1223
|
+
);
|
|
1224
|
+
if (increase) {
|
|
1225
|
+
this.setLength("increase");
|
|
1544
1226
|
}
|
|
1545
1227
|
}
|
|
1546
|
-
return
|
|
1547
|
-
}
|
|
1548
|
-
getGeniTreeName() {
|
|
1549
|
-
const fileName = get(this, "HEAD.FILE.value") || get(this.getGedcom(), "HEAD.FILE.value");
|
|
1550
|
-
return fileName?.replace(/\.ged$/i, "").replace(/_/g, " ");
|
|
1228
|
+
return this;
|
|
1551
1229
|
}
|
|
1552
|
-
|
|
1553
|
-
|
|
1554
|
-
|
|
1555
|
-
|
|
1556
|
-
|
|
1557
|
-
|
|
1230
|
+
append(item) {
|
|
1231
|
+
if (item.id) {
|
|
1232
|
+
let increase = true;
|
|
1233
|
+
if (this.items[item.id]) {
|
|
1234
|
+
delete this.items[item.id];
|
|
1235
|
+
increase = false;
|
|
1236
|
+
}
|
|
1237
|
+
this.items[item.id] = item;
|
|
1238
|
+
if (increase) {
|
|
1239
|
+
this.setLength("increase");
|
|
1558
1240
|
}
|
|
1559
1241
|
}
|
|
1560
|
-
return
|
|
1561
|
-
}
|
|
1562
|
-
getGenoProTreeName() {
|
|
1563
|
-
const fileName = get(this, "HEAD.FILE.value") || get(this.getGedcom(), "HEAD.FILE.value");
|
|
1564
|
-
return fileName?.replace(/\.ged$/i, "").replace(/_/g, " ");
|
|
1242
|
+
return this;
|
|
1565
1243
|
}
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
|
|
1569
|
-
|
|
1244
|
+
delete(item) {
|
|
1245
|
+
if (item.id && this.items[item.id]) {
|
|
1246
|
+
delete this.items[item.id];
|
|
1247
|
+
this.setLength("decrease");
|
|
1570
1248
|
}
|
|
1571
|
-
return
|
|
1249
|
+
return this;
|
|
1572
1250
|
}
|
|
1573
|
-
|
|
1574
|
-
const
|
|
1575
|
-
|
|
1576
|
-
|
|
1577
|
-
|
|
1578
|
-
const fileName = get(this, "HEAD.FILE.value") || get(this.getGedcom(), "HEAD.FILE.value");
|
|
1579
|
-
return fileName || "GNO2GED Export";
|
|
1251
|
+
copy(ClassName = _List) {
|
|
1252
|
+
const newList = new ClassName();
|
|
1253
|
+
Object.assign(newList.items, this.items);
|
|
1254
|
+
newList.setLength();
|
|
1255
|
+
return newList;
|
|
1580
1256
|
}
|
|
1581
|
-
|
|
1582
|
-
|
|
1583
|
-
* Tries to extract an ID from various common locations
|
|
1584
|
-
*/
|
|
1585
|
-
getUniversalTreeId() {
|
|
1586
|
-
const sourceType = this.getSourceType();
|
|
1587
|
-
const prefix = sourceType ? sourceType.toLowerCase() : "tree";
|
|
1588
|
-
const fileName = get(this, "HEAD.FILE.value") || get(this.getGedcom(), "HEAD.FILE.value");
|
|
1589
|
-
if (fileName) {
|
|
1590
|
-
const idMatch = fileName.match(/_(\d+)/);
|
|
1591
|
-
if (idMatch) {
|
|
1592
|
-
return `${prefix}_${idMatch[1]}`;
|
|
1593
|
-
}
|
|
1594
|
-
}
|
|
1595
|
-
return `${prefix}_${this._gedcom?.refcount || "unknown"}`;
|
|
1257
|
+
except(item, ClassName = _List) {
|
|
1258
|
+
return this.copy(ClassName).delete(item);
|
|
1596
1259
|
}
|
|
1597
|
-
|
|
1598
|
-
|
|
1599
|
-
|
|
1600
|
-
|
|
1601
|
-
getUniversalTreeName() {
|
|
1602
|
-
const sourceType = this.getSourceType();
|
|
1603
|
-
const prefix = sourceType ? `${sourceType}-` : "";
|
|
1604
|
-
const fileName = get(this, "HEAD.FILE.value") || get(this.getGedcom(), "HEAD.FILE.value");
|
|
1605
|
-
if (fileName) {
|
|
1606
|
-
const cleanName = fileName.replace(/\.ged$/i, "").replace(/_/g, " ");
|
|
1607
|
-
return `${prefix}${cleanName}`;
|
|
1608
|
-
}
|
|
1609
|
-
const sourName = this.getFromSourceHeads("SOUR.NAME.value") || get(this, "HEAD.SOUR.NAME.value") || get(this.getGedcom(), "HEAD.SOUR.NAME.value");
|
|
1610
|
-
if (sourName) {
|
|
1611
|
-
return `${prefix}${sourName}`;
|
|
1612
|
-
}
|
|
1613
|
-
const sourValue = this.getFromSourceHeads("SOUR.value") || get(this, "HEAD.SOUR.value") || get(this.getGedcom(), "HEAD.SOUR.value");
|
|
1614
|
-
if (sourValue) {
|
|
1615
|
-
return `${prefix}${sourValue}`;
|
|
1616
|
-
}
|
|
1617
|
-
return `${prefix}Unknown Tree`;
|
|
1260
|
+
forEach(iterate) {
|
|
1261
|
+
this.entries().forEach(([key, item], index) => {
|
|
1262
|
+
iterate(item, key, index);
|
|
1263
|
+
});
|
|
1618
1264
|
}
|
|
1619
|
-
|
|
1620
|
-
|
|
1621
|
-
|
|
1622
|
-
|
|
1623
|
-
}
|
|
1624
|
-
if (this?.isMyHeritage()) {
|
|
1625
|
-
const name = this.getMyHeritageTreeName();
|
|
1626
|
-
if (name) return name;
|
|
1627
|
-
}
|
|
1628
|
-
if (this?.isFamilySearch()) {
|
|
1629
|
-
const name = this.getFamilySearchTreeName();
|
|
1630
|
-
if (name) return name;
|
|
1631
|
-
}
|
|
1632
|
-
if (this?.isGNO2GED()) {
|
|
1633
|
-
const name = this.getGNO2GEDTreeName();
|
|
1634
|
-
if (name) return name;
|
|
1635
|
-
}
|
|
1636
|
-
if (this?.isAhnenblatt()) {
|
|
1637
|
-
const name = this.getAhnenblattTreeName();
|
|
1638
|
-
if (name) return name;
|
|
1639
|
-
}
|
|
1640
|
-
if (this?.isGeni()) {
|
|
1641
|
-
const name = this.getGeniTreeName();
|
|
1642
|
-
if (name) return name;
|
|
1643
|
-
}
|
|
1644
|
-
if (this?.isGenoPro()) {
|
|
1645
|
-
const name = this.getGenoProTreeName();
|
|
1646
|
-
if (name) return name;
|
|
1647
|
-
}
|
|
1648
|
-
return this.getUniversalTreeName();
|
|
1265
|
+
map(iterate) {
|
|
1266
|
+
return this.entries().map(([key, item], index) => {
|
|
1267
|
+
return iterate(item, key, index);
|
|
1268
|
+
});
|
|
1649
1269
|
}
|
|
1650
|
-
|
|
1651
|
-
|
|
1652
|
-
|
|
1653
|
-
|
|
1654
|
-
|
|
1655
|
-
|
|
1270
|
+
reduce(iterate, initialValue) {
|
|
1271
|
+
return this.entries().reduce((acc, [key, item], index) => {
|
|
1272
|
+
return iterate(acc, item, key, index);
|
|
1273
|
+
}, initialValue);
|
|
1274
|
+
}
|
|
1275
|
+
filter(filters, ClassName = _List) {
|
|
1276
|
+
const newList = new ClassName();
|
|
1277
|
+
const isIterator = typeof filters === "function";
|
|
1278
|
+
this.entries().forEach(([itemId, item], index) => {
|
|
1279
|
+
if (isIterator) {
|
|
1280
|
+
filters(item, itemId, index) && newList.item(itemId, item);
|
|
1281
|
+
return;
|
|
1656
1282
|
}
|
|
1657
|
-
if (
|
|
1658
|
-
|
|
1283
|
+
if (!Object.keys(filters).length || Object.entries(filters).every(([key, value]) => {
|
|
1284
|
+
let itemValue;
|
|
1285
|
+
if (key === "id") {
|
|
1286
|
+
itemValue = item.toProp("id");
|
|
1287
|
+
} else {
|
|
1288
|
+
itemValue = item.toProp(key)?.toValue();
|
|
1289
|
+
}
|
|
1290
|
+
if (Array.isArray(value)) {
|
|
1291
|
+
return value.includes(itemValue);
|
|
1292
|
+
}
|
|
1293
|
+
return itemValue === value;
|
|
1294
|
+
})) {
|
|
1295
|
+
newList.item(itemId, item);
|
|
1659
1296
|
}
|
|
1660
|
-
|
|
1661
|
-
|
|
1662
|
-
|
|
1663
|
-
|
|
1297
|
+
});
|
|
1298
|
+
return newList;
|
|
1299
|
+
}
|
|
1300
|
+
find(filters, _ClassName = _List) {
|
|
1301
|
+
let foundItem;
|
|
1302
|
+
const isIterator = typeof filters === "function";
|
|
1303
|
+
this.entries().find(([itemId, item], index) => {
|
|
1304
|
+
if (isIterator) {
|
|
1305
|
+
if (filters(item, itemId, index)) {
|
|
1306
|
+
foundItem = item;
|
|
1307
|
+
return true;
|
|
1664
1308
|
}
|
|
1309
|
+
return false;
|
|
1665
1310
|
}
|
|
1311
|
+
if (!Object.keys(filters).length || Object.entries(filters).every(([key, value]) => {
|
|
1312
|
+
let itemValue;
|
|
1313
|
+
if (key === "id") {
|
|
1314
|
+
itemValue = item.toProp("id");
|
|
1315
|
+
} else {
|
|
1316
|
+
itemValue = item.toProp(key)?.toValue();
|
|
1317
|
+
}
|
|
1318
|
+
if (Array.isArray(value)) {
|
|
1319
|
+
return value.includes(itemValue);
|
|
1320
|
+
}
|
|
1321
|
+
return itemValue === value;
|
|
1322
|
+
})) {
|
|
1323
|
+
foundItem = item;
|
|
1324
|
+
return true;
|
|
1325
|
+
}
|
|
1326
|
+
return false;
|
|
1327
|
+
});
|
|
1328
|
+
return foundItem;
|
|
1329
|
+
}
|
|
1330
|
+
orderBy(orders, ClassName = _List) {
|
|
1331
|
+
const newList = new ClassName();
|
|
1332
|
+
const isIterator = typeof orders === "function";
|
|
1333
|
+
if (!isIterator && (!orders || !Object.keys(orders).length)) {
|
|
1334
|
+
return newList.merge(this);
|
|
1666
1335
|
}
|
|
1667
|
-
|
|
1668
|
-
|
|
1669
|
-
|
|
1670
|
-
|
|
1671
|
-
|
|
1672
|
-
|
|
1673
|
-
}
|
|
1674
|
-
|
|
1675
|
-
|
|
1676
|
-
|
|
1677
|
-
|
|
1678
|
-
|
|
1679
|
-
|
|
1680
|
-
|
|
1681
|
-
|
|
1682
|
-
|
|
1683
|
-
|
|
1684
|
-
|
|
1336
|
+
const sortedItems = this.entries().toSorted(
|
|
1337
|
+
([itemAId, itemA], [itemBId, itemB]) => {
|
|
1338
|
+
if (isIterator) {
|
|
1339
|
+
return orders(itemA, itemAId, itemB, itemBId);
|
|
1340
|
+
}
|
|
1341
|
+
const [key, { direction, getter }] = Object.entries(
|
|
1342
|
+
typeof orders === "string" ? { [orders]: { direction: "ASC" } } : orders
|
|
1343
|
+
)[0];
|
|
1344
|
+
const rawA = itemA.get(key);
|
|
1345
|
+
const rawB = itemB.get(key);
|
|
1346
|
+
let valueA = rawA?.toValue();
|
|
1347
|
+
let valueB = rawB?.toValue();
|
|
1348
|
+
if (getter && typeof getter === "function") {
|
|
1349
|
+
valueA = getter(valueA, rawA);
|
|
1350
|
+
valueB = getter(valueB, rawB);
|
|
1351
|
+
}
|
|
1352
|
+
let sortValue2 = 0;
|
|
1353
|
+
if (!valueA && valueA !== 0 && !valueB && valueB !== 0) {
|
|
1354
|
+
sortValue2 = 0;
|
|
1355
|
+
} else if (!valueB && valueB !== 0) {
|
|
1356
|
+
sortValue2 = 1;
|
|
1357
|
+
} else if (!valueA && valueA !== 0) {
|
|
1358
|
+
sortValue2 = -1;
|
|
1359
|
+
} else if (valueA < valueB) {
|
|
1360
|
+
sortValue2 = -1;
|
|
1361
|
+
} else if (valueA > valueB) {
|
|
1362
|
+
sortValue2 = 1;
|
|
1363
|
+
}
|
|
1364
|
+
return sortValue2 * (direction === "DESC" ? -1 : 1);
|
|
1365
|
+
}
|
|
1366
|
+
);
|
|
1367
|
+
sortedItems.forEach(([key, value]) => {
|
|
1368
|
+
newList.item(key, value);
|
|
1369
|
+
});
|
|
1370
|
+
return newList;
|
|
1371
|
+
}
|
|
1372
|
+
groupBy(groups, sort, minOccurance = -1, lessOccuranceLabel = "Appearing less than 5 times", ClassName = _List) {
|
|
1373
|
+
const groupped = {};
|
|
1374
|
+
const isIterator = typeof groups === "function";
|
|
1375
|
+
if (!isIterator && (!groups || !Object.keys(groups).length)) {
|
|
1376
|
+
groupped.Unknown = new ClassName().merge(this);
|
|
1377
|
+
groupped.Unknown.marker = "Unknown";
|
|
1378
|
+
return groupped;
|
|
1379
|
+
}
|
|
1380
|
+
this.forEach((item, itemId) => {
|
|
1381
|
+
const group = [];
|
|
1382
|
+
if (isIterator) {
|
|
1383
|
+
const newGroups = groups(item, itemId);
|
|
1384
|
+
group.push(
|
|
1385
|
+
...Array.isArray(newGroups) ? newGroups : [newGroups]
|
|
1386
|
+
);
|
|
1387
|
+
} else {
|
|
1388
|
+
const [key, { getter }] = Object.entries(
|
|
1389
|
+
typeof groups === "string" ? { [groups]: {} } : groups
|
|
1390
|
+
)[0];
|
|
1391
|
+
const raw = item.get(key)?.index(0);
|
|
1392
|
+
let value = raw?.toValue();
|
|
1393
|
+
if (getter && typeof getter === "function") {
|
|
1394
|
+
value = getter(value, raw);
|
|
1395
|
+
}
|
|
1396
|
+
if (value) {
|
|
1397
|
+
group.push(value);
|
|
1398
|
+
}
|
|
1399
|
+
}
|
|
1400
|
+
if (!group.length) {
|
|
1401
|
+
group.push("Unknown");
|
|
1402
|
+
}
|
|
1403
|
+
group.forEach((g) => {
|
|
1404
|
+
const newGroup = typeof g === "string" ? { group: g } : g;
|
|
1405
|
+
if (!groupped[newGroup.group]) {
|
|
1406
|
+
groupped[newGroup.group] = new ClassName();
|
|
1407
|
+
groupped[newGroup.group].marker = newGroup.marker ?? newGroup.group;
|
|
1408
|
+
}
|
|
1409
|
+
groupped[newGroup.group]?.append(item);
|
|
1410
|
+
});
|
|
1411
|
+
});
|
|
1412
|
+
if (sort) {
|
|
1413
|
+
return Object.entries(groupped).toSorted(([ak, a], [bk, b]) => {
|
|
1414
|
+
if (typeof sort === "function") {
|
|
1415
|
+
return sort(a, ak, b, bk);
|
|
1416
|
+
}
|
|
1417
|
+
if (ak === "Unknown") {
|
|
1418
|
+
return 1;
|
|
1419
|
+
}
|
|
1420
|
+
if (bk === "Unknown") {
|
|
1421
|
+
return -1;
|
|
1422
|
+
}
|
|
1423
|
+
if (sort === "group") {
|
|
1424
|
+
return ak.localeCompare(bk);
|
|
1425
|
+
}
|
|
1426
|
+
return (b?.length ?? 0) - (a?.length ?? 0);
|
|
1427
|
+
}).reduce((acc, [key, value]) => {
|
|
1428
|
+
if (minOccurance > -1 && (value?.length ?? 0) < minOccurance) {
|
|
1429
|
+
const otherKey = lessOccuranceLabel;
|
|
1430
|
+
acc[otherKey] = acc[otherKey] && value ? acc[otherKey].merge(value) : value;
|
|
1431
|
+
} else {
|
|
1432
|
+
acc[key] = value;
|
|
1433
|
+
}
|
|
1434
|
+
return acc;
|
|
1435
|
+
}, {});
|
|
1436
|
+
}
|
|
1437
|
+
return groupped;
|
|
1438
|
+
}
|
|
1439
|
+
findIndex(item) {
|
|
1440
|
+
if (!item?.id) {
|
|
1441
|
+
return -1;
|
|
1442
|
+
}
|
|
1443
|
+
return this.keys().findIndex((key) => key === item.id);
|
|
1444
|
+
}
|
|
1445
|
+
getItems() {
|
|
1446
|
+
return this.items;
|
|
1447
|
+
}
|
|
1448
|
+
toJson(tag, options) {
|
|
1449
|
+
const json = this.toObject(tag, options);
|
|
1450
|
+
return JSON.stringify(json);
|
|
1451
|
+
}
|
|
1452
|
+
toObject(tag, options) {
|
|
1453
|
+
const json = {};
|
|
1454
|
+
this.entries().forEach(([_, item]) => {
|
|
1455
|
+
const validTag = getValidTag(tag);
|
|
1456
|
+
if (json[validTag]) {
|
|
1457
|
+
if (!Array.isArray(json[validTag])) {
|
|
1458
|
+
json[validTag] = [json[validTag]];
|
|
1459
|
+
}
|
|
1460
|
+
json[validTag].push(
|
|
1461
|
+
item.toObject(validTag, options)
|
|
1462
|
+
);
|
|
1463
|
+
} else {
|
|
1464
|
+
json[validTag] = item.toObject(
|
|
1465
|
+
validTag,
|
|
1466
|
+
options
|
|
1467
|
+
);
|
|
1468
|
+
}
|
|
1469
|
+
});
|
|
1470
|
+
return json;
|
|
1471
|
+
}
|
|
1472
|
+
toGedcom(tag, level = 0, options) {
|
|
1473
|
+
const gedcom = this.toGedcomLines(tag, level, options);
|
|
1474
|
+
return gedcom.join("\n");
|
|
1475
|
+
}
|
|
1476
|
+
toGedcomLines(tag, level = 0, options) {
|
|
1477
|
+
const gedcom = [];
|
|
1478
|
+
this.entries().forEach(([_, item]) => {
|
|
1479
|
+
const validTag = getValidTag(tag);
|
|
1480
|
+
const xref = item.id;
|
|
1481
|
+
const payload = item.exportValue?.();
|
|
1482
|
+
if (xref) {
|
|
1483
|
+
gedcom.push(
|
|
1484
|
+
`${level} ${xref} ${validTag}${payload ? ` ${payload}` : ""}`
|
|
1485
|
+
);
|
|
1486
|
+
} else {
|
|
1487
|
+
gedcom.push(
|
|
1488
|
+
`${level} ${validTag}${payload ? ` ${payload}` : ""}`
|
|
1489
|
+
);
|
|
1490
|
+
}
|
|
1491
|
+
gedcom.push(
|
|
1492
|
+
...item.toGedcomLines(
|
|
1493
|
+
validTag,
|
|
1494
|
+
level + 1,
|
|
1495
|
+
options
|
|
1496
|
+
)
|
|
1497
|
+
);
|
|
1498
|
+
});
|
|
1499
|
+
return gedcom;
|
|
1500
|
+
}
|
|
1501
|
+
toValue() {
|
|
1502
|
+
const propList = new _List();
|
|
1503
|
+
this.entries().forEach(([key, item]) => {
|
|
1504
|
+
propList.item(key, item?.toValue());
|
|
1505
|
+
});
|
|
1506
|
+
return propList;
|
|
1507
|
+
}
|
|
1508
|
+
// @deprecated use get instead
|
|
1509
|
+
toProp(tag) {
|
|
1510
|
+
return this.get(tag);
|
|
1511
|
+
}
|
|
1512
|
+
toList() {
|
|
1513
|
+
return new _List().concat(this.items);
|
|
1514
|
+
}
|
|
1515
|
+
toValueList() {
|
|
1516
|
+
const newList = new _List();
|
|
1517
|
+
this.values().forEach((value) => {
|
|
1518
|
+
value.value && newList.item(value.value, value);
|
|
1519
|
+
});
|
|
1520
|
+
return newList;
|
|
1521
|
+
}
|
|
1685
1522
|
};
|
|
1686
|
-
|
|
1687
|
-
|
|
1523
|
+
|
|
1524
|
+
// src/utils/get-all-prop.ts
|
|
1525
|
+
var getAllProp = (indi, prop) => {
|
|
1526
|
+
return prop && (indi?.get(prop)?.toList().values() ?? []).filter(Boolean) || [];
|
|
1688
1527
|
};
|
|
1689
|
-
|
|
1690
|
-
|
|
1528
|
+
|
|
1529
|
+
// src/utils/date-formatter.ts
|
|
1530
|
+
var ACCEPTED_DATE_FORMATS = [
|
|
1531
|
+
"yyyy.MM.dd.",
|
|
1532
|
+
"yyyy-MM-dd",
|
|
1533
|
+
"MM/dd/yyyy"
|
|
1534
|
+
];
|
|
1535
|
+
var ACCEPTED_DATE_FORMATS_REGEX = new RegExp(
|
|
1536
|
+
`(${ACCEPTED_DATE_FORMATS.map(
|
|
1537
|
+
(acceptedFormat) => acceptedFormat.replace(/[^.\-/]/g, "\\d")
|
|
1538
|
+
).join("|")})`,
|
|
1539
|
+
"gi"
|
|
1540
|
+
);
|
|
1541
|
+
var firstDate = (date) => {
|
|
1542
|
+
if (!date) return void 0;
|
|
1543
|
+
if (isCommonDate(date)) return date;
|
|
1544
|
+
if (date instanceof List) {
|
|
1545
|
+
return firstDate(
|
|
1546
|
+
date.index(0)
|
|
1547
|
+
);
|
|
1548
|
+
}
|
|
1549
|
+
const node = date;
|
|
1550
|
+
if (typeof node.toValue === "function") {
|
|
1551
|
+
return node;
|
|
1552
|
+
}
|
|
1553
|
+
return void 0;
|
|
1691
1554
|
};
|
|
1692
|
-
var
|
|
1693
|
-
|
|
1555
|
+
var dateNote = (date, shortNote = true) => {
|
|
1556
|
+
if (date && typeof date.toNote === "function") {
|
|
1557
|
+
return date.toNote(shortNote) ?? "";
|
|
1558
|
+
}
|
|
1559
|
+
return "";
|
|
1694
1560
|
};
|
|
1695
|
-
var
|
|
1696
|
-
|
|
1561
|
+
var commonDateFormatter = (date, format2 = "yyyy", prefix = "") => {
|
|
1562
|
+
const used = firstDate(date);
|
|
1563
|
+
const formattedDate = used?.toValue(format2);
|
|
1564
|
+
if (!formattedDate) {
|
|
1697
1565
|
return void 0;
|
|
1698
1566
|
}
|
|
1699
|
-
|
|
1700
|
-
|
|
1701
|
-
|
|
1702
|
-
|
|
1703
|
-
|
|
1704
|
-
|
|
1705
|
-
|
|
1706
|
-
newId = newId.replace(/^@/, "@U");
|
|
1567
|
+
return `${prefix}${formattedDate}`.trim();
|
|
1568
|
+
};
|
|
1569
|
+
var noteDateFormatter = (date, format2 = "yyyy", prefix = "", shortNote = true, showNote = true) => {
|
|
1570
|
+
const used = firstDate(date);
|
|
1571
|
+
const rawDate = commonDateFormatter(used, format2, "");
|
|
1572
|
+
if (!rawDate) {
|
|
1573
|
+
return void 0;
|
|
1707
1574
|
}
|
|
1708
|
-
|
|
1709
|
-
|
|
1575
|
+
const note = dateNote(used, shortNote);
|
|
1576
|
+
return `${prefix}${note && showNote ? i18n.t(`${note} {{date}}`, { date: rawDate }) : rawDate}`;
|
|
1577
|
+
};
|
|
1578
|
+
var marriageDateFormatter = (fam, showDays = false, showPlaces = false, shortNote = true, showNote = true, showDisplayTextIfNoDate = true, showAllEvents = false, dateFormatPattern) => {
|
|
1579
|
+
const fullDateFormat = i18n.t("dateFormat");
|
|
1580
|
+
const marriageDates = [];
|
|
1581
|
+
const marriagePlaces = [];
|
|
1582
|
+
const marriages = (fam?.toValueList().values() ?? []).flatMap((fam2) => {
|
|
1583
|
+
const family = fam2;
|
|
1584
|
+
const marrEvents = (family?.MARR?.toList().values() ?? []).filter(
|
|
1585
|
+
Boolean
|
|
1586
|
+
);
|
|
1587
|
+
if (marrEvents.length === 0) {
|
|
1588
|
+
const displayText = family?.get("DISPLAYTEXT")?.toValue() ?? "";
|
|
1589
|
+
if (showDisplayTextIfNoDate && displayText) {
|
|
1590
|
+
const displayDate = displayText.match(
|
|
1591
|
+
ACCEPTED_DATE_FORMATS_REGEX
|
|
1592
|
+
)?.[0];
|
|
1593
|
+
if (displayDate) {
|
|
1594
|
+
marriagePlaces.push(displayText.replace(displayDate, ""));
|
|
1595
|
+
const marriageDate = createCommonDate(
|
|
1596
|
+
fam2?.getGedcom(),
|
|
1597
|
+
void 0,
|
|
1598
|
+
family
|
|
1599
|
+
);
|
|
1600
|
+
marriageDate.value = displayDate;
|
|
1601
|
+
marriageDates.push(marriageDate);
|
|
1602
|
+
} else {
|
|
1603
|
+
marriagePlaces.push(displayText);
|
|
1604
|
+
marriageDates.push(void 0);
|
|
1605
|
+
return ["\u221E"];
|
|
1606
|
+
}
|
|
1607
|
+
}
|
|
1608
|
+
return [];
|
|
1609
|
+
}
|
|
1610
|
+
const eventsToProcess = showAllEvents ? marrEvents : marrEvents.slice(0, 1);
|
|
1611
|
+
return eventsToProcess.map((marrEvent) => {
|
|
1612
|
+
const marriageEventDetail = marrEvent;
|
|
1613
|
+
const marriageDate = marriageEventDetail?.DATE;
|
|
1614
|
+
const marriagePlace = showPlaces ? marriageEventDetail?.PLAC?.value : void 0;
|
|
1615
|
+
marriagePlaces.push(marriagePlace);
|
|
1616
|
+
marriageDates.push(marriageDate);
|
|
1617
|
+
const formattedDate = noteDateFormatter(
|
|
1618
|
+
marriageDate,
|
|
1619
|
+
showDays ? fullDateFormat : "yyyy",
|
|
1620
|
+
"\u221E",
|
|
1621
|
+
shortNote,
|
|
1622
|
+
showNote
|
|
1623
|
+
);
|
|
1624
|
+
return formattedDate ? formattedDate : void 0;
|
|
1625
|
+
});
|
|
1626
|
+
});
|
|
1627
|
+
const marriageArray = marriages.length ? marriages.filter(Boolean) : [];
|
|
1628
|
+
const datesArray = marriageArray.filter(Boolean);
|
|
1629
|
+
const placesArray = marriagePlaces.filter(Boolean);
|
|
1630
|
+
const dates = datesArray.join(" ").trim();
|
|
1631
|
+
return {
|
|
1632
|
+
rawArray: marriageDates,
|
|
1633
|
+
inArray: datesArray,
|
|
1634
|
+
inOrder: dates,
|
|
1635
|
+
places: placesArray,
|
|
1636
|
+
marriage: marriageArray,
|
|
1637
|
+
...showPlaces ? {
|
|
1638
|
+
marriages,
|
|
1639
|
+
marriagePlaces
|
|
1640
|
+
} : {}
|
|
1641
|
+
};
|
|
1642
|
+
};
|
|
1643
|
+
var dateFormatter = (indi, showMarriages = false, showDays = false, showPlaces = false, shortNote = true, showNote = true, isOnStage, showAllEvents = false, dateFormatPattern) => {
|
|
1644
|
+
const fullDateFormat = i18n.t("dateFormat");
|
|
1645
|
+
const birthEvents = getAllProp(indi, "BIRT");
|
|
1646
|
+
const firstBirthValue = birthEvents[0];
|
|
1647
|
+
const deathEvents = getAllProp(indi, "DEAT");
|
|
1648
|
+
const firstDeathValue = deathEvents[0];
|
|
1649
|
+
const birth = commonDateFormatter(
|
|
1650
|
+
firstBirthValue?.DATE,
|
|
1651
|
+
showDays ? fullDateFormat : "yyyy"
|
|
1652
|
+
);
|
|
1653
|
+
const birthPlace = showPlaces ? firstBirthValue?.PLAC?.value : void 0;
|
|
1654
|
+
const death = commonDateFormatter(
|
|
1655
|
+
firstDeathValue?.DATE,
|
|
1656
|
+
showDays ? fullDateFormat : "yyyy"
|
|
1657
|
+
);
|
|
1658
|
+
const deathPlace = showPlaces ? firstDeathValue?.PLAC?.value : void 0;
|
|
1659
|
+
const marriagePlaces = [];
|
|
1660
|
+
const marriages = [];
|
|
1661
|
+
if (showMarriages || isOnStage) {
|
|
1662
|
+
(indi?.get("FAMS")?.toValueList().values() ?? []).forEach((fam) => {
|
|
1663
|
+
const famRef = fam?.ref;
|
|
1664
|
+
const marriageDates = marriageDateFormatter(
|
|
1665
|
+
famRef,
|
|
1666
|
+
showDays,
|
|
1667
|
+
showPlaces,
|
|
1668
|
+
shortNote,
|
|
1669
|
+
showNote,
|
|
1670
|
+
true,
|
|
1671
|
+
showAllEvents);
|
|
1672
|
+
marriages.push(...marriageDates?.marriage ?? []);
|
|
1673
|
+
marriagePlaces.push(...marriageDates?.marriagePlaces ?? []);
|
|
1674
|
+
});
|
|
1710
1675
|
}
|
|
1711
|
-
|
|
1676
|
+
const birthStrings = [];
|
|
1677
|
+
const birthPlaces = [];
|
|
1678
|
+
const eventsToProcess = showAllEvents ? birthEvents : birthEvents.slice(0, 1);
|
|
1679
|
+
eventsToProcess.forEach((birthEvent) => {
|
|
1680
|
+
const birthDateNode = firstDate(birthEvent?.DATE);
|
|
1681
|
+
const birthDate = commonDateFormatter(
|
|
1682
|
+
birthDateNode,
|
|
1683
|
+
showDays ? fullDateFormat : "yyyy"
|
|
1684
|
+
);
|
|
1685
|
+
const birthEventNote = dateNote(birthDateNode, shortNote);
|
|
1686
|
+
const birthEventPlace = showPlaces ? birthEvent?.PLAC?.value : void 0;
|
|
1687
|
+
if (birthDate) {
|
|
1688
|
+
birthStrings.push(
|
|
1689
|
+
`*${birthEventNote && showNote ? i18n.t(`${birthEventNote} {{date}}`, {
|
|
1690
|
+
date: birthDate
|
|
1691
|
+
}) : birthDate}`
|
|
1692
|
+
);
|
|
1693
|
+
}
|
|
1694
|
+
birthPlaces.push(birthEventPlace);
|
|
1695
|
+
});
|
|
1696
|
+
const deathStrings = [];
|
|
1697
|
+
const deathPlaces = [];
|
|
1698
|
+
const deathEventsToProcess = showAllEvents ? deathEvents : deathEvents.slice(0, 1);
|
|
1699
|
+
deathEventsToProcess.forEach((deathEvent) => {
|
|
1700
|
+
const deathDateNode = firstDate(deathEvent?.DATE);
|
|
1701
|
+
const deathDate = commonDateFormatter(
|
|
1702
|
+
deathDateNode,
|
|
1703
|
+
showDays ? fullDateFormat : "yyyy"
|
|
1704
|
+
);
|
|
1705
|
+
const deathEventNote = dateNote(deathDateNode, shortNote);
|
|
1706
|
+
const deathEventPlace = showPlaces ? deathEvent?.PLAC?.value : void 0;
|
|
1707
|
+
if (deathDate) {
|
|
1708
|
+
deathStrings.push(
|
|
1709
|
+
`\u2020${deathEventNote && showNote ? i18n.t(`${deathEventNote} {{date}}`, {
|
|
1710
|
+
date: deathDate
|
|
1711
|
+
}) : deathDate}`
|
|
1712
|
+
);
|
|
1713
|
+
}
|
|
1714
|
+
deathPlaces.push(deathEventPlace);
|
|
1715
|
+
});
|
|
1716
|
+
const birthString = birthStrings[0] ?? "";
|
|
1717
|
+
const deathString = deathStrings[0] ?? "";
|
|
1718
|
+
const marriageArray = marriages.length ? marriages.filter(Boolean) : [];
|
|
1719
|
+
const datesArray = !birth && !death ? marriageArray : [...birthStrings, ...marriageArray, ...deathStrings];
|
|
1720
|
+
const placesArray = !birth && !death ? marriagePlaces : [...birthPlaces, ...marriagePlaces, ...deathPlaces];
|
|
1721
|
+
const nonNullDatesArray = datesArray.filter(Boolean);
|
|
1722
|
+
const dates = nonNullDatesArray.join(" ").trim();
|
|
1723
|
+
return {
|
|
1724
|
+
inArray: nonNullDatesArray,
|
|
1725
|
+
inOrder: dates,
|
|
1726
|
+
places: placesArray,
|
|
1727
|
+
birth: birthString,
|
|
1728
|
+
marriage: marriageArray,
|
|
1729
|
+
death: deathString,
|
|
1730
|
+
...showPlaces ? {
|
|
1731
|
+
birthPlace,
|
|
1732
|
+
deathPlace,
|
|
1733
|
+
...showMarriages ? { marriages, marriagePlaces } : {}
|
|
1734
|
+
} : {},
|
|
1735
|
+
...showAllEvents ? {
|
|
1736
|
+
births: birthStrings,
|
|
1737
|
+
birthPlaces,
|
|
1738
|
+
deaths: deathStrings,
|
|
1739
|
+
deathPlaces
|
|
1740
|
+
} : {}
|
|
1741
|
+
};
|
|
1712
1742
|
};
|
|
1713
1743
|
|
|
1714
1744
|
// src/utils/fact-edit.ts
|
|
@@ -8033,6 +8063,8 @@ var formatDateWithComponents = (date, hasDay, hasMonth, hasYear, noteValue, base
|
|
|
8033
8063
|
var CommonDate = class extends Common {
|
|
8034
8064
|
constructor(gedcom, id, main, parent) {
|
|
8035
8065
|
super(gedcom, id, main, parent);
|
|
8066
|
+
/** One DATE per event — merge must not turn this into a List. */
|
|
8067
|
+
this.isListable = false;
|
|
8036
8068
|
delete this.id;
|
|
8037
8069
|
}
|
|
8038
8070
|
get calendar() {
|