@treeviz/gedcom-parser 2.0.10 → 2.0.12
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 +6 -1
- package/dist/classes/common.d.ts.map +1 -1
- package/dist/classes/fam.d.ts +9 -1
- package/dist/classes/fam.d.ts.map +1 -1
- package/dist/classes/gedcom.d.ts +6 -2
- package/dist/classes/gedcom.d.ts.map +1 -1
- package/dist/classes/index.js +495 -50
- package/dist/classes/indi.d.ts +6 -0
- package/dist/classes/indi.d.ts.map +1 -1
- package/dist/cli/index.js +3383 -2932
- package/dist/constants/constants.d.ts +7 -0
- package/dist/constants/constants.d.ts.map +1 -1
- package/dist/constants/index.js +1287 -916
- package/dist/factories/index.js +409 -39
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5327 -4777
- package/dist/interfaces/fam.d.ts +7 -1
- package/dist/interfaces/fam.d.ts.map +1 -1
- package/dist/interfaces/gedcom.d.ts +4 -0
- package/dist/interfaces/gedcom.d.ts.map +1 -1
- package/dist/interfaces/indi.d.ts +5 -1
- package/dist/interfaces/indi.d.ts.map +1 -1
- package/dist/kinship-translator/index.js +409 -39
- package/dist/structures/gedcom.d.ts +1 -0
- package/dist/structures/gedcom.d.ts.map +1 -1
- package/dist/types/types.d.ts +10 -0
- package/dist/types/types.d.ts.map +1 -1
- package/dist/utils/fact-edit.d.ts +22 -0
- package/dist/utils/fact-edit.d.ts.map +1 -0
- package/dist/utils/family-edit.d.ts +23 -0
- package/dist/utils/family-edit.d.ts.map +1 -0
- package/dist/utils/gedcom-trailer.d.ts +6 -0
- package/dist/utils/gedcom-trailer.d.ts.map +1 -0
- package/dist/utils/index.d.ts +4 -1
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/index.js +605 -55
- package/dist/utils/parser.d.ts +3 -0
- package/dist/utils/parser.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/constants/index.js
CHANGED
|
@@ -8,11 +8,13 @@ var __export = (target, all) => {
|
|
|
8
8
|
};
|
|
9
9
|
|
|
10
10
|
// src/constants/constants.ts
|
|
11
|
+
var APP_BRANDING = "TreeViz - The Family Tree Visualiser & Editor";
|
|
11
12
|
var REF_LINE_REG = /^0 (?:(@[_a-zA-Z0-9]*@) )?(?<type>_[_A-Z][_a-zA-Z]{2,}|_?[A-Z][a-zA-Z]{2,}) ?(?<value>.*)/gm;
|
|
12
13
|
var LINE_REG = /(?<indent>^[0-9]) (?:(@[_a-zA-Z0-9]*@) )?(?<type>_[_A-Z][_a-zA-Z]{2,}|_?[A-Z][a-zA-Z]{2,}) ?(?<value>.*)/;
|
|
13
14
|
var ID_REG = /^@[_a-zA-Z0-9]+@/;
|
|
14
15
|
var ID_GETTER_REG = /^(?<at>@)?(?<letter>[A-Z])?/i;
|
|
15
16
|
var ID_SPLIT_REG = /^@[_a-zA-Z0-9]+@:/;
|
|
17
|
+
var ORIG_HEAD_TAG = "_ORIGHEAD";
|
|
16
18
|
var MAX_FILE_SIZE_TO_SYNC = 1024 * 1024 * 20;
|
|
17
19
|
|
|
18
20
|
// src/constants/filters.ts
|
|
@@ -543,1050 +545,1317 @@ var dateFormatter = (indi, showMarriages = false, showDays = false, showPlaces =
|
|
|
543
545
|
} : {}
|
|
544
546
|
};
|
|
545
547
|
};
|
|
546
|
-
|
|
547
|
-
|
|
548
|
+
|
|
549
|
+
// src/utils/gedcom-trailer.ts
|
|
550
|
+
var GEDCOM_TRAILER_TAG = "TRLR";
|
|
551
|
+
var isGedcomTrailerTag = (tag) => tag === GEDCOM_TRAILER_TAG;
|
|
552
|
+
var List = class _List {
|
|
553
|
+
// length = 0;
|
|
554
|
+
constructor(items) {
|
|
555
|
+
this.items = {};
|
|
548
556
|
this.isListable = true;
|
|
549
|
-
this.
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
this.initUniqueId();
|
|
553
|
-
if (id) {
|
|
554
|
-
this._id = id;
|
|
555
|
-
} else {
|
|
556
|
-
delete this._id;
|
|
557
|
+
this.marker = void 0;
|
|
558
|
+
if (items) {
|
|
559
|
+
this.concat(items);
|
|
557
560
|
}
|
|
558
561
|
}
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
this.uniqueId = this.uniqueId?.replace(/^[^:]+/, `~${type}`);
|
|
562
|
-
}
|
|
563
|
-
this._type = type;
|
|
562
|
+
get length() {
|
|
563
|
+
return this.values().length;
|
|
564
564
|
}
|
|
565
|
-
|
|
566
|
-
return this.
|
|
565
|
+
has(indi) {
|
|
566
|
+
return !!this.item(
|
|
567
|
+
typeof indi === "string" ? indi : indi?.id ?? ""
|
|
568
|
+
);
|
|
567
569
|
}
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
570
|
+
get(name) {
|
|
571
|
+
const propList = new _List();
|
|
572
|
+
this.entries().forEach(([key, item]) => {
|
|
573
|
+
propList.item(key, item.get(name));
|
|
574
|
+
});
|
|
575
|
+
return propList;
|
|
572
576
|
}
|
|
573
|
-
|
|
574
|
-
const
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
if (
|
|
578
|
-
|
|
577
|
+
getIf(name, condition, name2) {
|
|
578
|
+
const propList = new _List();
|
|
579
|
+
this.entries().forEach(([key, item]) => {
|
|
580
|
+
const passedItem = item.getIf(name, condition, name2);
|
|
581
|
+
if (passedItem) {
|
|
582
|
+
propList.item(key, passedItem);
|
|
579
583
|
}
|
|
580
|
-
|
|
581
|
-
|
|
584
|
+
});
|
|
585
|
+
return propList;
|
|
582
586
|
}
|
|
583
|
-
|
|
584
|
-
return this.
|
|
587
|
+
keys() {
|
|
588
|
+
return Object.keys(this.items);
|
|
585
589
|
}
|
|
586
|
-
|
|
587
|
-
this.
|
|
590
|
+
values() {
|
|
591
|
+
return Object.values(this.items);
|
|
588
592
|
}
|
|
589
|
-
|
|
590
|
-
return
|
|
593
|
+
entries() {
|
|
594
|
+
return Object.entries(this.items);
|
|
591
595
|
}
|
|
592
|
-
|
|
593
|
-
this._value = value;
|
|
596
|
+
setLength(_type) {
|
|
594
597
|
}
|
|
595
|
-
|
|
596
|
-
return this.
|
|
598
|
+
first() {
|
|
599
|
+
return this.index(0);
|
|
597
600
|
}
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
* @param gedcom - The GedComType to set as the gedcom reference
|
|
601
|
-
*/
|
|
602
|
-
setGedcom(gedcom) {
|
|
603
|
-
this._gedcom = gedcom;
|
|
601
|
+
last() {
|
|
602
|
+
return this.index(this.keys().length - 1);
|
|
604
603
|
}
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
604
|
+
index(index) {
|
|
605
|
+
const keys = this.keys();
|
|
606
|
+
const key = keys[index];
|
|
607
|
+
return key && this.items[key];
|
|
608
608
|
}
|
|
609
|
-
|
|
610
|
-
if (
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
this.value
|
|
614
|
-
);
|
|
609
|
+
item(name, value) {
|
|
610
|
+
if (arguments.length > 1) {
|
|
611
|
+
set(this.items, name, value);
|
|
612
|
+
this.setLength();
|
|
615
613
|
}
|
|
616
|
-
return this;
|
|
614
|
+
return get(this.items, name);
|
|
617
615
|
}
|
|
618
|
-
|
|
619
|
-
|
|
616
|
+
removeItem(name) {
|
|
617
|
+
unset(this.items, name);
|
|
618
|
+
this.setLength();
|
|
620
619
|
}
|
|
621
|
-
|
|
622
|
-
|
|
620
|
+
exclude(excludedList) {
|
|
621
|
+
excludedList.keys().forEach((itemId) => {
|
|
622
|
+
delete this.items[itemId];
|
|
623
|
+
});
|
|
624
|
+
this.setLength();
|
|
625
|
+
return this;
|
|
623
626
|
}
|
|
624
|
-
|
|
625
|
-
if (
|
|
626
|
-
|
|
627
|
-
this.
|
|
628
|
-
}
|
|
629
|
-
|
|
627
|
+
concat(items) {
|
|
628
|
+
if (Array.isArray(items)) {
|
|
629
|
+
items.forEach((item) => {
|
|
630
|
+
this.append(item);
|
|
631
|
+
});
|
|
632
|
+
} else {
|
|
633
|
+
Object.assign(this.items, items ?? {});
|
|
630
634
|
}
|
|
635
|
+
this.setLength();
|
|
636
|
+
return this;
|
|
631
637
|
}
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
exportValue() {
|
|
636
|
-
return this.value;
|
|
638
|
+
merge(mergedList) {
|
|
639
|
+
this.concat(mergedList?.items);
|
|
640
|
+
return this;
|
|
637
641
|
}
|
|
638
|
-
|
|
639
|
-
|
|
642
|
+
intersection(mergedList) {
|
|
643
|
+
const inter = intersectionBy(
|
|
644
|
+
this.values(),
|
|
645
|
+
mergedList?.values() ?? [],
|
|
646
|
+
"id"
|
|
647
|
+
);
|
|
648
|
+
return new _List(inter);
|
|
640
649
|
}
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
}
|
|
649
|
-
return get(this, name);
|
|
650
|
+
difference(mergedList) {
|
|
651
|
+
const inter = differenceBy(
|
|
652
|
+
this.values(),
|
|
653
|
+
mergedList?.values() ?? [],
|
|
654
|
+
"id"
|
|
655
|
+
);
|
|
656
|
+
return new _List(inter);
|
|
650
657
|
}
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
if (
|
|
655
|
-
|
|
656
|
-
|
|
658
|
+
prepend(item) {
|
|
659
|
+
if (item.id) {
|
|
660
|
+
let increase = true;
|
|
661
|
+
if (this.items[item.id]) {
|
|
662
|
+
delete this.items[item.id];
|
|
663
|
+
increase = false;
|
|
664
|
+
}
|
|
665
|
+
this.items = Object.assign(
|
|
666
|
+
{
|
|
667
|
+
[item.id]: item
|
|
668
|
+
},
|
|
669
|
+
this.items
|
|
670
|
+
);
|
|
671
|
+
if (increase) {
|
|
672
|
+
this.setLength("increase");
|
|
657
673
|
}
|
|
658
|
-
const values = [
|
|
659
|
-
...curValue.values(),
|
|
660
|
-
...value instanceof List ? value.values() : [value]
|
|
661
|
-
];
|
|
662
|
-
curValue.concat({
|
|
663
|
-
...!unique ? values : uniqBy(
|
|
664
|
-
values,
|
|
665
|
-
(value2) => value2 instanceof _Common ? value2?.value : void 0
|
|
666
|
-
)
|
|
667
|
-
});
|
|
668
|
-
} else {
|
|
669
|
-
this.set(name, value);
|
|
670
674
|
}
|
|
671
|
-
return
|
|
675
|
+
return this;
|
|
672
676
|
}
|
|
673
|
-
|
|
674
|
-
if (
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
for (const part of nameParts) {
|
|
680
|
-
const indexPart = Number(part);
|
|
681
|
-
const itemIndex = part.match(/items\[(?<itemIndex>\d+)\]/)?.groups?.itemIndex;
|
|
682
|
-
const itemId = part.match(/items\[(?<itemId>@[A-Z]+\d+@)\]/)?.groups?.itemId;
|
|
683
|
-
const usedPart = itemId || itemIndex;
|
|
684
|
-
if (last instanceof List) {
|
|
685
|
-
if (!isNaN(indexPart)) {
|
|
686
|
-
last = last.index(indexPart);
|
|
687
|
-
} else {
|
|
688
|
-
if (usedPart) {
|
|
689
|
-
last = last.item(usedPart);
|
|
690
|
-
} else {
|
|
691
|
-
last = last?.index(0)?.get(part);
|
|
692
|
-
}
|
|
693
|
-
}
|
|
694
|
-
} else {
|
|
695
|
-
const usedIndex = Number(itemIndex ?? indexPart);
|
|
696
|
-
if (!isNaN(usedIndex)) {
|
|
697
|
-
last = last?.toList().index(usedIndex);
|
|
698
|
-
} else {
|
|
699
|
-
last = last?.get(itemId ?? part);
|
|
700
|
-
}
|
|
677
|
+
append(item) {
|
|
678
|
+
if (item.id) {
|
|
679
|
+
let increase = true;
|
|
680
|
+
if (this.items[item.id]) {
|
|
681
|
+
delete this.items[item.id];
|
|
682
|
+
increase = false;
|
|
701
683
|
}
|
|
702
|
-
|
|
703
|
-
|
|
684
|
+
this.items[item.id] = item;
|
|
685
|
+
if (increase) {
|
|
686
|
+
this.setLength("increase");
|
|
704
687
|
}
|
|
705
688
|
}
|
|
706
|
-
return
|
|
689
|
+
return this;
|
|
707
690
|
}
|
|
708
|
-
|
|
709
|
-
|
|
691
|
+
delete(item) {
|
|
692
|
+
if (item.id && this.items[item.id]) {
|
|
693
|
+
delete this.items[item.id];
|
|
694
|
+
this.setLength("decrease");
|
|
695
|
+
}
|
|
696
|
+
return this;
|
|
710
697
|
}
|
|
711
|
-
|
|
712
|
-
|
|
698
|
+
copy(ClassName = _List) {
|
|
699
|
+
const newList = new ClassName();
|
|
700
|
+
Object.assign(newList.items, this.items);
|
|
701
|
+
newList.setLength();
|
|
702
|
+
return newList;
|
|
713
703
|
}
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
const name2Parts = name2.split(".");
|
|
717
|
-
if (nameParts.length !== name2Parts.length) {
|
|
718
|
-
throw new Error("Tag pathes must be of the same depth");
|
|
719
|
-
}
|
|
720
|
-
if (nameParts.length > 1 && nameParts[0] !== name2Parts[0]) {
|
|
721
|
-
throw new Error("Final tags must be siblings");
|
|
722
|
-
}
|
|
723
|
-
const valueCommon = this.get(name);
|
|
724
|
-
if (valueCommon instanceof _Common) {
|
|
725
|
-
return valueCommon?.toValue() !== condition ? void 0 : this.get(name2);
|
|
726
|
-
}
|
|
727
|
-
const valueCommon2 = this.get(name2)?.toList();
|
|
728
|
-
const ifList = new List();
|
|
729
|
-
valueCommon?.forEach((item, key) => {
|
|
730
|
-
const pair = valueCommon2?.item(key);
|
|
731
|
-
ifList.item(key, item?.toValue() !== condition ? void 0 : pair);
|
|
732
|
-
});
|
|
733
|
-
return ifList;
|
|
734
|
-
}
|
|
735
|
-
toString() {
|
|
736
|
-
return this.value?.toString() || "";
|
|
737
|
-
}
|
|
738
|
-
toValue() {
|
|
739
|
-
return this.value;
|
|
740
|
-
}
|
|
741
|
-
toProp(tag) {
|
|
742
|
-
const prop = this.get(tag);
|
|
743
|
-
return prop;
|
|
744
|
-
}
|
|
745
|
-
toList() {
|
|
746
|
-
return new List().concat(
|
|
747
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
748
|
-
this.id ? { [this.id]: this } : { ...[this] }
|
|
749
|
-
);
|
|
750
|
-
}
|
|
751
|
-
index(i) {
|
|
752
|
-
return this.toList()?.index(i);
|
|
704
|
+
except(item, ClassName = _List) {
|
|
705
|
+
return this.copy(ClassName).delete(item);
|
|
753
706
|
}
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
{ ...[this] }
|
|
759
|
-
)
|
|
760
|
-
);
|
|
707
|
+
forEach(iterate) {
|
|
708
|
+
this.entries().forEach(([key, item], index) => {
|
|
709
|
+
iterate(item, key, index);
|
|
710
|
+
});
|
|
761
711
|
}
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
this,
|
|
767
|
-
options.obje.namespace,
|
|
768
|
-
options.obje.override
|
|
769
|
-
);
|
|
770
|
-
}
|
|
712
|
+
map(iterate) {
|
|
713
|
+
return this.entries().map(([key, item], index) => {
|
|
714
|
+
return iterate(item, key, index);
|
|
715
|
+
});
|
|
771
716
|
}
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
717
|
+
reduce(iterate, initialValue) {
|
|
718
|
+
return this.entries().reduce((acc, [key, item], index) => {
|
|
719
|
+
return iterate(acc, item, key, index);
|
|
720
|
+
}, initialValue);
|
|
775
721
|
}
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
const
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
}
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
if (prop instanceof _Common) {
|
|
794
|
-
json[validKey] = prop.toObject(validKey, options);
|
|
795
|
-
} else {
|
|
796
|
-
json = {
|
|
797
|
-
...json,
|
|
798
|
-
...prop.toObject(validKey, options)
|
|
799
|
-
};
|
|
800
|
-
}
|
|
722
|
+
filter(filters, ClassName = _List) {
|
|
723
|
+
const newList = new ClassName();
|
|
724
|
+
const isIterator = typeof filters === "function";
|
|
725
|
+
this.entries().forEach(([itemId, item], index) => {
|
|
726
|
+
if (isIterator) {
|
|
727
|
+
filters(item, itemId, index) && newList.item(itemId, item);
|
|
728
|
+
return;
|
|
729
|
+
}
|
|
730
|
+
if (!Object.keys(filters).length || Object.entries(filters).every(([key, value]) => {
|
|
731
|
+
let itemValue;
|
|
732
|
+
if (key === "id") {
|
|
733
|
+
itemValue = item.toProp("id");
|
|
734
|
+
} else {
|
|
735
|
+
itemValue = item.toProp(key)?.toValue();
|
|
736
|
+
}
|
|
737
|
+
if (Array.isArray(value)) {
|
|
738
|
+
return value.includes(itemValue);
|
|
801
739
|
}
|
|
740
|
+
return itemValue === value;
|
|
741
|
+
})) {
|
|
742
|
+
newList.item(itemId, item);
|
|
802
743
|
}
|
|
803
744
|
});
|
|
804
|
-
return
|
|
745
|
+
return newList;
|
|
805
746
|
}
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
747
|
+
find(filters, _ClassName = _List) {
|
|
748
|
+
let foundItem;
|
|
749
|
+
const isIterator = typeof filters === "function";
|
|
750
|
+
this.entries().find(([itemId, item], index) => {
|
|
751
|
+
if (isIterator) {
|
|
752
|
+
if (filters(item, itemId, index)) {
|
|
753
|
+
foundItem = item;
|
|
754
|
+
return true;
|
|
755
|
+
}
|
|
756
|
+
return false;
|
|
814
757
|
}
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
758
|
+
if (!Object.keys(filters).length || Object.entries(filters).every(([key, value]) => {
|
|
759
|
+
let itemValue;
|
|
760
|
+
if (key === "id") {
|
|
761
|
+
itemValue = item.toProp("id");
|
|
762
|
+
} else {
|
|
763
|
+
itemValue = item.toProp(key)?.toValue();
|
|
764
|
+
}
|
|
765
|
+
if (Array.isArray(value)) {
|
|
766
|
+
return value.includes(itemValue);
|
|
822
767
|
}
|
|
768
|
+
return itemValue === value;
|
|
769
|
+
})) {
|
|
770
|
+
foundItem = item;
|
|
771
|
+
return true;
|
|
823
772
|
}
|
|
773
|
+
return false;
|
|
824
774
|
});
|
|
825
|
-
return
|
|
775
|
+
return foundItem;
|
|
826
776
|
}
|
|
827
|
-
|
|
828
|
-
const
|
|
829
|
-
const
|
|
830
|
-
|
|
831
|
-
this
|
|
832
|
-
this._main,
|
|
833
|
-
this._parent
|
|
834
|
-
);
|
|
835
|
-
if (newId && this._id) {
|
|
836
|
-
instance.id = `IFT${this._id.replace(/[^0-9]/g, "")}`;
|
|
777
|
+
orderBy(orders, ClassName = _List) {
|
|
778
|
+
const newList = new ClassName();
|
|
779
|
+
const isIterator = typeof orders === "function";
|
|
780
|
+
if (!isIterator && (!orders || !Object.keys(orders).length)) {
|
|
781
|
+
return newList.merge(this);
|
|
837
782
|
}
|
|
838
|
-
const
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
if (
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
} else {
|
|
866
|
-
gedcom.push(
|
|
867
|
-
...prop.toGedcomLines(validKey, level, options)
|
|
868
|
-
);
|
|
783
|
+
const sortedItems = this.entries().toSorted(
|
|
784
|
+
([itemAId, itemA], [itemBId, itemB]) => {
|
|
785
|
+
if (isIterator) {
|
|
786
|
+
return orders(itemA, itemAId, itemB, itemBId);
|
|
787
|
+
}
|
|
788
|
+
const [key, { direction, getter }] = Object.entries(
|
|
789
|
+
typeof orders === "string" ? { [orders]: { direction: "ASC" } } : orders
|
|
790
|
+
)[0];
|
|
791
|
+
const rawA = itemA.get(key);
|
|
792
|
+
const rawB = itemB.get(key);
|
|
793
|
+
let valueA = rawA?.toValue();
|
|
794
|
+
let valueB = rawB?.toValue();
|
|
795
|
+
if (getter && typeof getter === "function") {
|
|
796
|
+
valueA = getter(valueA, rawA);
|
|
797
|
+
valueB = getter(valueB, rawB);
|
|
798
|
+
}
|
|
799
|
+
let sortValue2 = 0;
|
|
800
|
+
if (!valueA && valueA !== 0 && !valueB && valueB !== 0) {
|
|
801
|
+
sortValue2 = 0;
|
|
802
|
+
} else if (!valueB && valueB !== 0) {
|
|
803
|
+
sortValue2 = 1;
|
|
804
|
+
} else if (!valueA && valueA !== 0) {
|
|
805
|
+
sortValue2 = -1;
|
|
806
|
+
} else if (valueA < valueB) {
|
|
807
|
+
sortValue2 = -1;
|
|
808
|
+
} else if (valueA > valueB) {
|
|
809
|
+
sortValue2 = 1;
|
|
869
810
|
}
|
|
811
|
+
return sortValue2 * (direction === "DESC" ? -1 : 1);
|
|
870
812
|
}
|
|
813
|
+
);
|
|
814
|
+
sortedItems.forEach(([key, value]) => {
|
|
815
|
+
newList.item(key, value);
|
|
871
816
|
});
|
|
872
|
-
return
|
|
873
|
-
}
|
|
874
|
-
isGenoPro() {
|
|
875
|
-
const head = get(this, "HEAD") || get(this.getGedcom(), "HEAD");
|
|
876
|
-
const sour = get(head, "SOUR.value");
|
|
877
|
-
return !!sour?.toLowerCase()?.startsWith("genopro");
|
|
878
|
-
}
|
|
879
|
-
isAhnenblatt() {
|
|
880
|
-
const head = get(this, "HEAD") || get(this.getGedcom(), "HEAD");
|
|
881
|
-
const sour = get(head, "SOUR.value");
|
|
882
|
-
return !!sour?.toLowerCase()?.startsWith("ahnenblatt");
|
|
883
|
-
}
|
|
884
|
-
isGeni() {
|
|
885
|
-
const head = get(this, "HEAD") || get(this.getGedcom(), "HEAD");
|
|
886
|
-
const sour = get(head, "SOUR.value");
|
|
887
|
-
return !!sour?.toLowerCase()?.startsWith("geni");
|
|
888
|
-
}
|
|
889
|
-
isAncestry() {
|
|
890
|
-
const head = get(this, "HEAD") || get(this.getGedcom(), "HEAD");
|
|
891
|
-
const sour = get(head, "SOUR.value");
|
|
892
|
-
return !!sour?.toLowerCase()?.startsWith("ancestry");
|
|
893
|
-
}
|
|
894
|
-
isMyHeritage() {
|
|
895
|
-
const head = get(this, "HEAD") || get(this.getGedcom(), "HEAD");
|
|
896
|
-
const sour = get(head, "SOUR.value");
|
|
897
|
-
return !!sour?.toLowerCase()?.startsWith("myheritage");
|
|
817
|
+
return newList;
|
|
898
818
|
}
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
819
|
+
groupBy(groups, sort, minOccurance = -1, lessOccuranceLabel = "Appearing less than 5 times", ClassName = _List) {
|
|
820
|
+
const groupped = {};
|
|
821
|
+
const isIterator = typeof groups === "function";
|
|
822
|
+
if (!isIterator && (!groups || !Object.keys(groups).length)) {
|
|
823
|
+
groupped.Unknown = new ClassName().merge(this);
|
|
824
|
+
groupped.Unknown.marker = "Unknown";
|
|
825
|
+
return groupped;
|
|
826
|
+
}
|
|
827
|
+
this.forEach((item, itemId) => {
|
|
828
|
+
const group = [];
|
|
829
|
+
if (isIterator) {
|
|
830
|
+
const newGroups = groups(item, itemId);
|
|
831
|
+
group.push(
|
|
832
|
+
...Array.isArray(newGroups) ? newGroups : [newGroups]
|
|
833
|
+
);
|
|
834
|
+
} else {
|
|
835
|
+
const [key, { getter }] = Object.entries(
|
|
836
|
+
typeof groups === "string" ? { [groups]: {} } : groups
|
|
837
|
+
)[0];
|
|
838
|
+
const raw = item.get(key)?.index(0);
|
|
839
|
+
let value = raw?.toValue();
|
|
840
|
+
if (getter && typeof getter === "function") {
|
|
841
|
+
value = getter(value, raw);
|
|
842
|
+
}
|
|
843
|
+
if (value) {
|
|
844
|
+
group.push(value);
|
|
845
|
+
}
|
|
846
|
+
}
|
|
847
|
+
if (!group.length) {
|
|
848
|
+
group.push("Unknown");
|
|
849
|
+
}
|
|
850
|
+
group.forEach((g) => {
|
|
851
|
+
const newGroup = typeof g === "string" ? { group: g } : g;
|
|
852
|
+
if (!groupped[newGroup.group]) {
|
|
853
|
+
groupped[newGroup.group] = new ClassName();
|
|
854
|
+
groupped[newGroup.group].marker = newGroup.marker ?? newGroup.group;
|
|
855
|
+
}
|
|
856
|
+
groupped[newGroup.group]?.append(item);
|
|
857
|
+
});
|
|
858
|
+
});
|
|
859
|
+
if (sort) {
|
|
860
|
+
return Object.entries(groupped).toSorted(([ak, a], [bk, b]) => {
|
|
861
|
+
if (typeof sort === "function") {
|
|
862
|
+
return sort(a, ak, b, bk);
|
|
863
|
+
}
|
|
864
|
+
if (ak === "Unknown") {
|
|
865
|
+
return 1;
|
|
866
|
+
}
|
|
867
|
+
if (bk === "Unknown") {
|
|
868
|
+
return -1;
|
|
869
|
+
}
|
|
870
|
+
if (sort === "group") {
|
|
871
|
+
return ak.localeCompare(bk);
|
|
872
|
+
}
|
|
873
|
+
return (b?.length ?? 0) - (a?.length ?? 0);
|
|
874
|
+
}).reduce((acc, [key, value]) => {
|
|
875
|
+
if (minOccurance > -1 && (value?.length ?? 0) < minOccurance) {
|
|
876
|
+
const otherKey = lessOccuranceLabel;
|
|
877
|
+
acc[otherKey] = acc[otherKey] && value ? acc[otherKey].merge(value) : value;
|
|
878
|
+
} else {
|
|
879
|
+
acc[key] = value;
|
|
880
|
+
}
|
|
881
|
+
return acc;
|
|
882
|
+
}, {});
|
|
883
|
+
}
|
|
884
|
+
return groupped;
|
|
912
885
|
}
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
886
|
+
findIndex(item) {
|
|
887
|
+
if (!item?.id) {
|
|
888
|
+
return -1;
|
|
889
|
+
}
|
|
890
|
+
return this.keys().findIndex((key) => key === item.id);
|
|
917
891
|
}
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
const sour = get(head, "SOUR.value");
|
|
921
|
-
return sour === "GNO2GED";
|
|
892
|
+
getItems() {
|
|
893
|
+
return this.items;
|
|
922
894
|
}
|
|
923
|
-
|
|
924
|
-
const
|
|
925
|
-
return
|
|
895
|
+
toJson(tag, options) {
|
|
896
|
+
const json = this.toObject(tag, options);
|
|
897
|
+
return JSON.stringify(json);
|
|
926
898
|
}
|
|
927
|
-
|
|
928
|
-
const
|
|
929
|
-
|
|
899
|
+
toObject(tag, options) {
|
|
900
|
+
const json = {};
|
|
901
|
+
this.entries().forEach(([_, item]) => {
|
|
902
|
+
const validTag = getValidTag(tag);
|
|
903
|
+
if (json[validTag]) {
|
|
904
|
+
if (!Array.isArray(json[validTag])) {
|
|
905
|
+
json[validTag] = [json[validTag]];
|
|
906
|
+
}
|
|
907
|
+
json[validTag].push(
|
|
908
|
+
item.toObject(validTag, options)
|
|
909
|
+
);
|
|
910
|
+
} else {
|
|
911
|
+
json[validTag] = item.toObject(
|
|
912
|
+
validTag,
|
|
913
|
+
options
|
|
914
|
+
);
|
|
915
|
+
}
|
|
916
|
+
});
|
|
917
|
+
return json;
|
|
930
918
|
}
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
if (id !== void 0) return id;
|
|
935
|
-
}
|
|
936
|
-
if (this?.isMyHeritage()) {
|
|
937
|
-
const id = this.getMyHeritageTreeId();
|
|
938
|
-
if (id !== void 0) return id;
|
|
939
|
-
}
|
|
940
|
-
if (this?.isFamilySearch()) {
|
|
941
|
-
const id = this.getFamilySearchTreeId();
|
|
942
|
-
if (id !== void 0) return id;
|
|
943
|
-
}
|
|
944
|
-
if (this?.isGNO2GED()) {
|
|
945
|
-
const id = this.getGNO2GEDTreeId();
|
|
946
|
-
if (id !== void 0) return id;
|
|
947
|
-
}
|
|
948
|
-
if (this?.isAhnenblatt()) {
|
|
949
|
-
const id = this.getAhnenblattTreeId();
|
|
950
|
-
if (id !== void 0) return id;
|
|
951
|
-
}
|
|
952
|
-
if (this?.isGeni()) {
|
|
953
|
-
const id = this.getGeniTreeId();
|
|
954
|
-
if (id !== void 0) return id;
|
|
955
|
-
}
|
|
956
|
-
if (this?.isGenoPro()) {
|
|
957
|
-
const id = this.getGenoProTreeId();
|
|
958
|
-
if (id !== void 0) return id;
|
|
959
|
-
}
|
|
960
|
-
return this.getUniversalTreeId();
|
|
919
|
+
toGedcom(tag, level = 0, options) {
|
|
920
|
+
const gedcom = this.toGedcomLines(tag, level, options);
|
|
921
|
+
return gedcom.join("\n");
|
|
961
922
|
}
|
|
962
|
-
|
|
963
|
-
const
|
|
964
|
-
|
|
923
|
+
toGedcomLines(tag, level = 0, options) {
|
|
924
|
+
const gedcom = [];
|
|
925
|
+
this.entries().forEach(([_, item]) => {
|
|
926
|
+
const validTag = getValidTag(tag);
|
|
927
|
+
const validKey = item.id;
|
|
928
|
+
const validValue = validKey ? validTag : item.exportValue();
|
|
929
|
+
gedcom.push(
|
|
930
|
+
`${level} ${validKey || validTag}${validValue ? ` ${validValue}` : ""}`
|
|
931
|
+
);
|
|
932
|
+
gedcom.push(
|
|
933
|
+
...item.toGedcomLines(
|
|
934
|
+
validTag,
|
|
935
|
+
level + 1,
|
|
936
|
+
options
|
|
937
|
+
)
|
|
938
|
+
);
|
|
939
|
+
});
|
|
940
|
+
return gedcom;
|
|
965
941
|
}
|
|
966
|
-
|
|
967
|
-
const
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
942
|
+
toValue() {
|
|
943
|
+
const propList = new _List();
|
|
944
|
+
this.entries().forEach(([key, item]) => {
|
|
945
|
+
propList.item(key, item?.toValue());
|
|
946
|
+
});
|
|
947
|
+
return propList;
|
|
972
948
|
}
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
return rin;
|
|
977
|
-
}
|
|
978
|
-
return "familysearch";
|
|
949
|
+
// @deprecated use get instead
|
|
950
|
+
toProp(tag) {
|
|
951
|
+
return this.get(tag);
|
|
979
952
|
}
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
953
|
+
toList() {
|
|
954
|
+
return new _List().concat(this.items);
|
|
955
|
+
}
|
|
956
|
+
toValueList() {
|
|
957
|
+
const newList = new _List();
|
|
958
|
+
this.values().forEach((value) => {
|
|
959
|
+
value.value && newList.item(value.value, value);
|
|
960
|
+
});
|
|
961
|
+
return newList;
|
|
962
|
+
}
|
|
963
|
+
};
|
|
964
|
+
|
|
965
|
+
// src/classes/common.ts
|
|
966
|
+
var Common = class _Common {
|
|
967
|
+
constructor(gedcom, id, main, parent) {
|
|
968
|
+
this.isListable = true;
|
|
969
|
+
this._gedcom = gedcom;
|
|
970
|
+
this._main = main;
|
|
971
|
+
this._parent = parent;
|
|
972
|
+
this.initUniqueId();
|
|
973
|
+
if (id) {
|
|
974
|
+
this._id = id;
|
|
975
|
+
} else {
|
|
976
|
+
delete this._id;
|
|
984
977
|
}
|
|
985
|
-
const fileName = get(this, "HEAD.FILE.value") || get(this.getGedcom(), "HEAD.FILE.value");
|
|
986
|
-
return fileName || "FamilySearch Import";
|
|
987
978
|
}
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
const idMatch = fileName.match(/_(\d+)/);
|
|
992
|
-
if (idMatch) {
|
|
993
|
-
return idMatch[1];
|
|
994
|
-
}
|
|
979
|
+
set type(type) {
|
|
980
|
+
if (type) {
|
|
981
|
+
this.uniqueId = this.uniqueId?.replace(/^[^:]+/, `~${type}`);
|
|
995
982
|
}
|
|
996
|
-
|
|
983
|
+
this._type = type;
|
|
997
984
|
}
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
return fileName?.replace(/\.ged$/i, "").replace(/_/g, " ");
|
|
985
|
+
get type() {
|
|
986
|
+
return this._type;
|
|
1001
987
|
}
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
const idMatch = fileName.match(/_(\d+)/);
|
|
1006
|
-
if (idMatch) {
|
|
1007
|
-
return idMatch[1];
|
|
1008
|
-
}
|
|
988
|
+
initUniqueId() {
|
|
989
|
+
if (this._gedcom) {
|
|
990
|
+
this.uniqueId = `~Common:${this._gedcom.refcount++}`;
|
|
1009
991
|
}
|
|
1010
|
-
return void 0;
|
|
1011
992
|
}
|
|
1012
|
-
|
|
1013
|
-
const
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
if (fileName) {
|
|
1019
|
-
const idMatch = fileName.match(/_(\d+)/);
|
|
1020
|
-
if (idMatch) {
|
|
1021
|
-
return idMatch[1];
|
|
993
|
+
set uniqueId(id) {
|
|
994
|
+
const currentId = this._uniqueId;
|
|
995
|
+
if (this._gedcom?.reflist && id) {
|
|
996
|
+
this._uniqueId = id;
|
|
997
|
+
if (currentId && this._gedcom.reflist[currentId]) {
|
|
998
|
+
delete this._gedcom.reflist[currentId];
|
|
1022
999
|
}
|
|
1000
|
+
this._gedcom.reflist[id] = this;
|
|
1023
1001
|
}
|
|
1024
|
-
return void 0;
|
|
1025
1002
|
}
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
return fileName?.replace(/\.ged$/i, "").replace(/_/g, " ");
|
|
1003
|
+
get uniqueId() {
|
|
1004
|
+
return this._uniqueId;
|
|
1029
1005
|
}
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
if (rin) {
|
|
1033
|
-
return rin;
|
|
1034
|
-
}
|
|
1035
|
-
return `gno_${this._gedcom?.refcount || "unknown"}`;
|
|
1006
|
+
set id(id) {
|
|
1007
|
+
this._id = idGetter(id);
|
|
1036
1008
|
}
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
if (treeName) {
|
|
1040
|
-
return treeName;
|
|
1041
|
-
}
|
|
1042
|
-
const fileName = get(this, "HEAD.FILE.value") || get(this.getGedcom(), "HEAD.FILE.value");
|
|
1043
|
-
return fileName || "GNO2GED Export";
|
|
1009
|
+
get id() {
|
|
1010
|
+
return idGetter(this._id);
|
|
1044
1011
|
}
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
const sourceType = this.getSourceType();
|
|
1051
|
-
const prefix = sourceType ? sourceType.toLowerCase() : "tree";
|
|
1052
|
-
const fileName = get(this, "HEAD.FILE.value") || get(this.getGedcom(), "HEAD.FILE.value");
|
|
1053
|
-
if (fileName) {
|
|
1054
|
-
const idMatch = fileName.match(/_(\d+)/);
|
|
1055
|
-
if (idMatch) {
|
|
1056
|
-
return `${prefix}_${idMatch[1]}`;
|
|
1057
|
-
}
|
|
1058
|
-
}
|
|
1059
|
-
return `${prefix}_${this._gedcom?.refcount || "unknown"}`;
|
|
1012
|
+
set value(value) {
|
|
1013
|
+
this._value = value;
|
|
1014
|
+
}
|
|
1015
|
+
get value() {
|
|
1016
|
+
return this._value;
|
|
1060
1017
|
}
|
|
1061
1018
|
/**
|
|
1062
|
-
*
|
|
1063
|
-
*
|
|
1019
|
+
* Set the gedcom reference for this object
|
|
1020
|
+
* @param gedcom - The GedComType to set as the gedcom reference
|
|
1064
1021
|
*/
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
const prefix = sourceType ? `${sourceType}-` : "";
|
|
1068
|
-
const fileName = get(this, "HEAD.FILE.value") || get(this.getGedcom(), "HEAD.FILE.value");
|
|
1069
|
-
if (fileName) {
|
|
1070
|
-
const cleanName = fileName.replace(/\.ged$/i, "").replace(/_/g, " ");
|
|
1071
|
-
return `${prefix}${cleanName}`;
|
|
1072
|
-
}
|
|
1073
|
-
const sourName = get(this, "HEAD.SOUR.NAME.value") || get(this.getGedcom(), "HEAD.SOUR.NAME.value");
|
|
1074
|
-
if (sourName) {
|
|
1075
|
-
return `${prefix}${sourName}`;
|
|
1076
|
-
}
|
|
1077
|
-
const sourValue = get(this, "HEAD.SOUR.value") || get(this.getGedcom(), "HEAD.SOUR.value");
|
|
1078
|
-
if (sourValue) {
|
|
1079
|
-
return `${prefix}${sourValue}`;
|
|
1080
|
-
}
|
|
1081
|
-
return `${prefix}Unknown Tree`;
|
|
1022
|
+
setGedcom(gedcom) {
|
|
1023
|
+
this._gedcom = gedcom;
|
|
1082
1024
|
}
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
if (this
|
|
1089
|
-
|
|
1090
|
-
|
|
1025
|
+
// avoid to override
|
|
1026
|
+
get originalValue() {
|
|
1027
|
+
return this._value;
|
|
1028
|
+
}
|
|
1029
|
+
get ref() {
|
|
1030
|
+
if (typeof this.value === "string" && isId(this.value) && this.refType) {
|
|
1031
|
+
return this._gedcom?.[getListTag(this.refType)]?.item(
|
|
1032
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
1033
|
+
this.value
|
|
1034
|
+
);
|
|
1091
1035
|
}
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1036
|
+
return this;
|
|
1037
|
+
}
|
|
1038
|
+
get main() {
|
|
1039
|
+
return this._main;
|
|
1040
|
+
}
|
|
1041
|
+
get parent() {
|
|
1042
|
+
return this._parent;
|
|
1043
|
+
}
|
|
1044
|
+
addRef(refNode) {
|
|
1045
|
+
if (typeof refNode.value === "string" && isId(refNode.value) && refNode.refType) {
|
|
1046
|
+
if (!this._refs) {
|
|
1047
|
+
this._refs = new List();
|
|
1048
|
+
}
|
|
1049
|
+
this._refs.item(refNode.value, refNode);
|
|
1095
1050
|
}
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1051
|
+
}
|
|
1052
|
+
getRefs() {
|
|
1053
|
+
return this._refs;
|
|
1054
|
+
}
|
|
1055
|
+
exportValue() {
|
|
1056
|
+
return this.value;
|
|
1057
|
+
}
|
|
1058
|
+
removeValue() {
|
|
1059
|
+
delete this._value;
|
|
1060
|
+
}
|
|
1061
|
+
set(name, value) {
|
|
1062
|
+
if (isGedcomTrailerTag(name)) {
|
|
1063
|
+
return void 0;
|
|
1099
1064
|
}
|
|
1100
|
-
if (
|
|
1101
|
-
const
|
|
1102
|
-
|
|
1065
|
+
if (typeof value === "string") {
|
|
1066
|
+
const usedValue = createCommon(this._gedcom, void 0, this.main);
|
|
1067
|
+
usedValue.value = value;
|
|
1068
|
+
set(this, name, usedValue);
|
|
1069
|
+
} else {
|
|
1070
|
+
set(this, name, value);
|
|
1103
1071
|
}
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1072
|
+
return get(this, name);
|
|
1073
|
+
}
|
|
1074
|
+
assign(name, value, unique = false) {
|
|
1075
|
+
if (isGedcomTrailerTag(name)) {
|
|
1076
|
+
return void 0;
|
|
1107
1077
|
}
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
if (
|
|
1078
|
+
let curValue = this.get(name);
|
|
1079
|
+
if (curValue?.isListable) {
|
|
1080
|
+
if (curValue instanceof _Common) {
|
|
1081
|
+
curValue = new List().concat({ ...[curValue] });
|
|
1082
|
+
this.set(name, curValue);
|
|
1083
|
+
}
|
|
1084
|
+
const values = [
|
|
1085
|
+
...curValue.values(),
|
|
1086
|
+
...value instanceof List ? value.values() : [value]
|
|
1087
|
+
];
|
|
1088
|
+
curValue.concat({
|
|
1089
|
+
...!unique ? values : uniqBy(
|
|
1090
|
+
values,
|
|
1091
|
+
(value2) => value2 instanceof _Common ? value2?.value : void 0
|
|
1092
|
+
)
|
|
1093
|
+
});
|
|
1094
|
+
} else {
|
|
1095
|
+
this.set(name, value);
|
|
1111
1096
|
}
|
|
1112
|
-
return this
|
|
1097
|
+
return get(this, name);
|
|
1113
1098
|
}
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
if (
|
|
1127
|
-
|
|
1099
|
+
get(name) {
|
|
1100
|
+
if (!name.includes(".")) {
|
|
1101
|
+
return get(this, name);
|
|
1102
|
+
}
|
|
1103
|
+
const nameParts = name.split(".");
|
|
1104
|
+
let last = this;
|
|
1105
|
+
for (const part of nameParts) {
|
|
1106
|
+
const indexPart = Number(part);
|
|
1107
|
+
const itemIndex = part.match(/items\[(?<itemIndex>\d+)\]/)?.groups?.itemIndex;
|
|
1108
|
+
const itemId = part.match(/items\[(?<itemId>@[A-Z]+\d+@)\]/)?.groups?.itemId;
|
|
1109
|
+
const usedPart = itemId || itemIndex;
|
|
1110
|
+
if (last instanceof List) {
|
|
1111
|
+
if (!isNaN(indexPart)) {
|
|
1112
|
+
last = last.index(indexPart);
|
|
1113
|
+
} else {
|
|
1114
|
+
if (usedPart) {
|
|
1115
|
+
last = last.item(usedPart);
|
|
1116
|
+
} else {
|
|
1117
|
+
last = last?.index(0)?.get(part);
|
|
1118
|
+
}
|
|
1119
|
+
}
|
|
1120
|
+
} else {
|
|
1121
|
+
const usedIndex = Number(itemIndex ?? indexPart);
|
|
1122
|
+
if (!isNaN(usedIndex)) {
|
|
1123
|
+
last = last?.toList().index(usedIndex);
|
|
1124
|
+
} else {
|
|
1125
|
+
last = last?.get(itemId ?? part);
|
|
1128
1126
|
}
|
|
1129
1127
|
}
|
|
1128
|
+
if (!last) {
|
|
1129
|
+
break;
|
|
1130
|
+
}
|
|
1130
1131
|
}
|
|
1131
|
-
|
|
1132
|
-
};
|
|
1133
|
-
var createCommon = (gedcom, id, main, parent) => {
|
|
1134
|
-
return createProxy(
|
|
1135
|
-
new Common(gedcom, id, main, parent)
|
|
1136
|
-
);
|
|
1137
|
-
};
|
|
1138
|
-
var isOnlyMainProp = (key) => {
|
|
1139
|
-
return key === "_gedcom" || key === "_main" || key === "_parent" || key === "_uniqueId" || key === "_type" || key === "_refs" || key === "id" || key === "_id";
|
|
1140
|
-
};
|
|
1141
|
-
var isValidKey = (common, key) => {
|
|
1142
|
-
const prop = get(common, key);
|
|
1143
|
-
return key !== "_gedcom" && key !== "_main" && key !== "_parent" && key !== "_uniqueId" && key !== "_refs" && key !== "_type" && (key === "id" || key === "_id" || key === "value" || key === "_value" || prop instanceof Common || prop instanceof List);
|
|
1144
|
-
};
|
|
1145
|
-
var getValidKeys = (common) => {
|
|
1146
|
-
return Object.keys(common).filter((key) => {
|
|
1147
|
-
return isValidKey(common, key);
|
|
1148
|
-
});
|
|
1149
|
-
};
|
|
1150
|
-
var getValidTag = (tag) => {
|
|
1151
|
-
return tag.replace(/^@@/, "");
|
|
1152
|
-
};
|
|
1153
|
-
var getListTag = (tag) => {
|
|
1154
|
-
return `@@${tag}`;
|
|
1155
|
-
};
|
|
1156
|
-
var isId = (string) => {
|
|
1157
|
-
return ID_REG.test(string);
|
|
1158
|
-
};
|
|
1159
|
-
var idGetter = (id) => {
|
|
1160
|
-
if (id === void 0) {
|
|
1161
|
-
return void 0;
|
|
1132
|
+
return last;
|
|
1162
1133
|
}
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
if (!parts?.at && !parts?.letter) {
|
|
1166
|
-
newId = `@U${newId}`;
|
|
1167
|
-
} else if (!parts.at) {
|
|
1168
|
-
newId = `@${newId}`;
|
|
1169
|
-
} else if (!parts.letter) {
|
|
1170
|
-
newId = newId.replace(/^@/, "@U");
|
|
1134
|
+
remove(name) {
|
|
1135
|
+
unset(this, name);
|
|
1171
1136
|
}
|
|
1172
|
-
|
|
1173
|
-
|
|
1137
|
+
getGedcom() {
|
|
1138
|
+
return this._gedcom;
|
|
1174
1139
|
}
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
// length = 0;
|
|
1181
|
-
constructor(items) {
|
|
1182
|
-
this.items = {};
|
|
1183
|
-
this.isListable = true;
|
|
1184
|
-
this.marker = void 0;
|
|
1185
|
-
if (items) {
|
|
1186
|
-
this.concat(items);
|
|
1140
|
+
getIf(name, condition, name2) {
|
|
1141
|
+
const nameParts = name.split(".");
|
|
1142
|
+
const name2Parts = name2.split(".");
|
|
1143
|
+
if (nameParts.length !== name2Parts.length) {
|
|
1144
|
+
throw new Error("Tag pathes must be of the same depth");
|
|
1187
1145
|
}
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
);
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
propList.item(key, item.get(name));
|
|
1201
|
-
});
|
|
1202
|
-
return propList;
|
|
1203
|
-
}
|
|
1204
|
-
getIf(name, condition, name2) {
|
|
1205
|
-
const propList = new _List();
|
|
1206
|
-
this.entries().forEach(([key, item]) => {
|
|
1207
|
-
const passedItem = item.getIf(name, condition, name2);
|
|
1208
|
-
if (passedItem) {
|
|
1209
|
-
propList.item(key, passedItem);
|
|
1210
|
-
}
|
|
1146
|
+
if (nameParts.length > 1 && nameParts[0] !== name2Parts[0]) {
|
|
1147
|
+
throw new Error("Final tags must be siblings");
|
|
1148
|
+
}
|
|
1149
|
+
const valueCommon = this.get(name);
|
|
1150
|
+
if (valueCommon instanceof _Common) {
|
|
1151
|
+
return valueCommon?.toValue() !== condition ? void 0 : this.get(name2);
|
|
1152
|
+
}
|
|
1153
|
+
const valueCommon2 = this.get(name2)?.toList();
|
|
1154
|
+
const ifList = new List();
|
|
1155
|
+
valueCommon?.forEach((item, key) => {
|
|
1156
|
+
const pair = valueCommon2?.item(key);
|
|
1157
|
+
ifList.item(key, item?.toValue() !== condition ? void 0 : pair);
|
|
1211
1158
|
});
|
|
1212
|
-
return
|
|
1213
|
-
}
|
|
1214
|
-
keys() {
|
|
1215
|
-
return Object.keys(this.items);
|
|
1159
|
+
return ifList;
|
|
1216
1160
|
}
|
|
1217
|
-
|
|
1218
|
-
return
|
|
1161
|
+
toString() {
|
|
1162
|
+
return this.value?.toString() || "";
|
|
1219
1163
|
}
|
|
1220
|
-
|
|
1221
|
-
return
|
|
1164
|
+
toValue() {
|
|
1165
|
+
return this.value;
|
|
1222
1166
|
}
|
|
1223
|
-
|
|
1167
|
+
toProp(tag) {
|
|
1168
|
+
const prop = this.get(tag);
|
|
1169
|
+
return prop;
|
|
1224
1170
|
}
|
|
1225
|
-
|
|
1226
|
-
return
|
|
1171
|
+
toList() {
|
|
1172
|
+
return new List().concat(
|
|
1173
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
1174
|
+
this.id ? { [this.id]: this } : { ...[this] }
|
|
1175
|
+
);
|
|
1227
1176
|
}
|
|
1228
|
-
|
|
1229
|
-
return this.index(
|
|
1177
|
+
index(i) {
|
|
1178
|
+
return this.toList()?.index(i);
|
|
1230
1179
|
}
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1180
|
+
toValueList() {
|
|
1181
|
+
return new List().concat(
|
|
1182
|
+
this.value ? { [this.value]: this } : (
|
|
1183
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
1184
|
+
{ ...[this] }
|
|
1185
|
+
)
|
|
1186
|
+
);
|
|
1235
1187
|
}
|
|
1236
|
-
|
|
1237
|
-
if (
|
|
1238
|
-
|
|
1239
|
-
|
|
1188
|
+
standardizeObject(tag, options) {
|
|
1189
|
+
if (tag === "OBJE" && !options?.original && options?.obje?.standardize && options?.obje?.namespace && "standardizeMedia" in this) {
|
|
1190
|
+
const standardize = this.standardizeMedia;
|
|
1191
|
+
return standardize.call(
|
|
1192
|
+
this,
|
|
1193
|
+
options.obje.namespace,
|
|
1194
|
+
options.obje.override
|
|
1195
|
+
);
|
|
1240
1196
|
}
|
|
1241
|
-
return get(this.items, name);
|
|
1242
1197
|
}
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1198
|
+
toJson(tag, options) {
|
|
1199
|
+
const json = this.toObject(tag, options);
|
|
1200
|
+
return JSON.stringify(json);
|
|
1246
1201
|
}
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
1202
|
+
toObject(tag, options) {
|
|
1203
|
+
this.standardizeObject(tag, options);
|
|
1204
|
+
const validKeys = getValidKeys(this);
|
|
1205
|
+
let json = {};
|
|
1206
|
+
validKeys.forEach((key) => {
|
|
1207
|
+
if (key === "id" && this.id !== void 0) {
|
|
1208
|
+
json.id = this.id;
|
|
1209
|
+
} else if (key === "_id" && this._id !== void 0) {
|
|
1210
|
+
json.id = this._id;
|
|
1211
|
+
} else if (key === "value" && this.value !== void 0) {
|
|
1212
|
+
json.value = this.value;
|
|
1213
|
+
} else if (key === "_value" && this._value !== void 0) {
|
|
1214
|
+
json.value = this._value;
|
|
1215
|
+
} else {
|
|
1216
|
+
const validKey = key;
|
|
1217
|
+
const prop = this.get(validKey);
|
|
1218
|
+
if (typeof prop?.toObject === "function") {
|
|
1219
|
+
if (prop instanceof _Common) {
|
|
1220
|
+
json[validKey] = prop.toObject(validKey, options);
|
|
1221
|
+
} else {
|
|
1222
|
+
json = {
|
|
1223
|
+
...json,
|
|
1224
|
+
...prop.toObject(validKey, options)
|
|
1225
|
+
};
|
|
1226
|
+
}
|
|
1227
|
+
}
|
|
1228
|
+
}
|
|
1250
1229
|
});
|
|
1251
|
-
|
|
1252
|
-
return this;
|
|
1230
|
+
return json;
|
|
1253
1231
|
}
|
|
1254
|
-
|
|
1255
|
-
if (
|
|
1256
|
-
|
|
1257
|
-
this.append(item);
|
|
1258
|
-
});
|
|
1259
|
-
} else {
|
|
1260
|
-
Object.assign(this.items, items ?? {});
|
|
1232
|
+
merge(other, override = false, avoidKeys = []) {
|
|
1233
|
+
if (!other) {
|
|
1234
|
+
return this;
|
|
1261
1235
|
}
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1236
|
+
const validKeys = getValidKeys(other);
|
|
1237
|
+
validKeys.forEach((validKey) => {
|
|
1238
|
+
if (avoidKeys.includes(validKey)) {
|
|
1239
|
+
return;
|
|
1240
|
+
}
|
|
1241
|
+
const current = this.get(validKey);
|
|
1242
|
+
const mergeValue = other.get(validKey);
|
|
1243
|
+
if (mergeValue) {
|
|
1244
|
+
if (current instanceof _Common || current instanceof List) {
|
|
1245
|
+
this.assign(validKey, mergeValue, true);
|
|
1246
|
+
} else if (!current || override && validKey !== "id" && validKey !== "_id") {
|
|
1247
|
+
this.set(validKey, mergeValue);
|
|
1248
|
+
}
|
|
1249
|
+
}
|
|
1250
|
+
});
|
|
1267
1251
|
return this;
|
|
1268
1252
|
}
|
|
1269
|
-
|
|
1270
|
-
const
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1253
|
+
clone(newId = false, avoidKeys = []) {
|
|
1254
|
+
const ctor = this.constructor;
|
|
1255
|
+
const instance = new ctor(
|
|
1256
|
+
this._gedcom,
|
|
1257
|
+
this._id,
|
|
1258
|
+
this._main,
|
|
1259
|
+
this._parent
|
|
1274
1260
|
);
|
|
1275
|
-
|
|
1261
|
+
if (newId && this._id) {
|
|
1262
|
+
instance.id = `IFT${this._id.replace(/[^0-9]/g, "")}`;
|
|
1263
|
+
}
|
|
1264
|
+
const cloned = createProxy(instance);
|
|
1265
|
+
cloned.merge(this, true, avoidKeys);
|
|
1266
|
+
return cloned;
|
|
1276
1267
|
}
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
this.values(),
|
|
1280
|
-
mergedList?.values() ?? [],
|
|
1281
|
-
"id"
|
|
1282
|
-
);
|
|
1283
|
-
return new _List(inter);
|
|
1268
|
+
// fromGedcom<T = typeof this>(value: string) {
|
|
1269
|
+
fromGedcom(_value) {
|
|
1284
1270
|
}
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
if (this.items[item.id]) {
|
|
1289
|
-
delete this.items[item.id];
|
|
1290
|
-
increase = false;
|
|
1291
|
-
}
|
|
1292
|
-
this.items = Object.assign(
|
|
1293
|
-
{
|
|
1294
|
-
[item.id]: item
|
|
1295
|
-
},
|
|
1296
|
-
this.items
|
|
1297
|
-
);
|
|
1298
|
-
if (increase) {
|
|
1299
|
-
this.setLength("increase");
|
|
1300
|
-
}
|
|
1301
|
-
}
|
|
1302
|
-
return this;
|
|
1271
|
+
toGedcom(tag, level = 0, options) {
|
|
1272
|
+
const gedcom = this.toGedcomLines(tag, level, options);
|
|
1273
|
+
return gedcom.join("\n");
|
|
1303
1274
|
}
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1275
|
+
toGedcomLines(tag, level = 0, options) {
|
|
1276
|
+
this.standardizeObject(tag, options);
|
|
1277
|
+
const validKeys = getValidKeys(this);
|
|
1278
|
+
const gedcom = [];
|
|
1279
|
+
validKeys.forEach((key) => {
|
|
1280
|
+
const validKey = key;
|
|
1281
|
+
const prop = this.get(validKey);
|
|
1282
|
+
if (typeof prop?.toGedcomLines === "function") {
|
|
1283
|
+
if (prop instanceof _Common) {
|
|
1284
|
+
const value = prop.exportValue();
|
|
1285
|
+
gedcom.push(
|
|
1286
|
+
`${level} ${validKey}${value ? ` ${value}` : ""}`
|
|
1287
|
+
);
|
|
1288
|
+
gedcom.push(
|
|
1289
|
+
...prop.toGedcomLines(validKey, level + 1, options)
|
|
1290
|
+
);
|
|
1291
|
+
} else {
|
|
1292
|
+
gedcom.push(
|
|
1293
|
+
...prop.toGedcomLines(validKey, level, options)
|
|
1294
|
+
);
|
|
1295
|
+
}
|
|
1314
1296
|
}
|
|
1315
|
-
}
|
|
1316
|
-
return
|
|
1297
|
+
});
|
|
1298
|
+
return gedcom;
|
|
1317
1299
|
}
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
delete this.items[item.id];
|
|
1321
|
-
this.setLength("decrease");
|
|
1322
|
-
}
|
|
1323
|
-
return this;
|
|
1300
|
+
getHeadRecord() {
|
|
1301
|
+
return get(this, "HEAD") || get(this.getGedcom(), "HEAD");
|
|
1324
1302
|
}
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
Object.assign(newList.items, this.items);
|
|
1328
|
-
newList.setLength();
|
|
1329
|
-
return newList;
|
|
1303
|
+
getOriginalHeadRecord() {
|
|
1304
|
+
return get(this, ORIG_HEAD_TAG) || get(this.getGedcom(), ORIG_HEAD_TAG) || get(this.getHeadRecord(), ORIG_HEAD_TAG);
|
|
1330
1305
|
}
|
|
1331
|
-
|
|
1332
|
-
|
|
1306
|
+
getSourceHeads() {
|
|
1307
|
+
const heads = [this.getOriginalHeadRecord(), this.getHeadRecord()];
|
|
1308
|
+
return heads.filter((head, index) => {
|
|
1309
|
+
return Boolean(head && heads.indexOf(head) === index);
|
|
1310
|
+
});
|
|
1333
1311
|
}
|
|
1334
|
-
|
|
1335
|
-
this.
|
|
1336
|
-
|
|
1312
|
+
getFromSourceHeads(path) {
|
|
1313
|
+
for (const head of this.getSourceHeads()) {
|
|
1314
|
+
const value = get(head, path);
|
|
1315
|
+
if (value !== void 0 && value !== null && value !== "") {
|
|
1316
|
+
return value;
|
|
1317
|
+
}
|
|
1318
|
+
}
|
|
1319
|
+
return void 0;
|
|
1320
|
+
}
|
|
1321
|
+
sourStartsWith(prefix) {
|
|
1322
|
+
return this.getSourceHeads().some((head) => {
|
|
1323
|
+
const sour = get(head, "SOUR.value");
|
|
1324
|
+
return !!sour?.toLowerCase()?.startsWith(prefix);
|
|
1337
1325
|
});
|
|
1338
1326
|
}
|
|
1339
|
-
|
|
1340
|
-
return this.
|
|
1341
|
-
return iterate(item, key, index);
|
|
1342
|
-
});
|
|
1327
|
+
isGenoPro() {
|
|
1328
|
+
return this.sourStartsWith("genopro");
|
|
1343
1329
|
}
|
|
1344
|
-
|
|
1345
|
-
return this.
|
|
1346
|
-
return iterate(acc, item, key, index);
|
|
1347
|
-
}, initialValue);
|
|
1330
|
+
isAhnenblatt() {
|
|
1331
|
+
return this.sourStartsWith("ahnenblatt");
|
|
1348
1332
|
}
|
|
1349
|
-
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
|
|
1353
|
-
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
|
|
1358
|
-
|
|
1359
|
-
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
|
|
1333
|
+
isGeni() {
|
|
1334
|
+
return this.sourStartsWith("geni");
|
|
1335
|
+
}
|
|
1336
|
+
isAncestry() {
|
|
1337
|
+
return this.sourStartsWith("ancestry");
|
|
1338
|
+
}
|
|
1339
|
+
isMyHeritage() {
|
|
1340
|
+
return this.sourStartsWith("myheritage");
|
|
1341
|
+
}
|
|
1342
|
+
/**
|
|
1343
|
+
* Get the source type as a string (for prefixing tree IDs and names)
|
|
1344
|
+
* Returns the detected source type or undefined if unknown
|
|
1345
|
+
*/
|
|
1346
|
+
getSourceType() {
|
|
1347
|
+
if (this.isAncestry()) return "Ancestry";
|
|
1348
|
+
if (this.isMyHeritage()) return "MyHeritage";
|
|
1349
|
+
if (this.isFamilySearch()) return "FamilySearch";
|
|
1350
|
+
if (this.isGNO2GED()) return "GNO2GED";
|
|
1351
|
+
if (this.isGenoPro()) return "GenoPro";
|
|
1352
|
+
if (this.isAhnenblatt()) return "Ahnenblatt";
|
|
1353
|
+
if (this.isGeni()) return "Geni";
|
|
1354
|
+
return void 0;
|
|
1355
|
+
}
|
|
1356
|
+
isFamilySearch() {
|
|
1357
|
+
return this.getSourceHeads().some((head) => {
|
|
1358
|
+
const sourName = get(head, "SOUR.NAME.value");
|
|
1359
|
+
return sourName === "FamilySearch API";
|
|
1371
1360
|
});
|
|
1372
|
-
return newList;
|
|
1373
1361
|
}
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
if (isIterator) {
|
|
1379
|
-
if (filters(item, itemId, index)) {
|
|
1380
|
-
foundItem = item;
|
|
1381
|
-
return true;
|
|
1382
|
-
}
|
|
1383
|
-
return false;
|
|
1384
|
-
}
|
|
1385
|
-
if (!Object.keys(filters).length || Object.entries(filters).every(([key, value]) => {
|
|
1386
|
-
let itemValue;
|
|
1387
|
-
if (key === "id") {
|
|
1388
|
-
itemValue = item.toProp("id");
|
|
1389
|
-
} else {
|
|
1390
|
-
itemValue = item.toProp(key)?.toValue();
|
|
1391
|
-
}
|
|
1392
|
-
if (Array.isArray(value)) {
|
|
1393
|
-
return value.includes(itemValue);
|
|
1394
|
-
}
|
|
1395
|
-
return itemValue === value;
|
|
1396
|
-
})) {
|
|
1397
|
-
foundItem = item;
|
|
1398
|
-
return true;
|
|
1399
|
-
}
|
|
1400
|
-
return false;
|
|
1362
|
+
isGNO2GED() {
|
|
1363
|
+
return this.getSourceHeads().some((head) => {
|
|
1364
|
+
const sour = get(head, "SOUR.value");
|
|
1365
|
+
return sour === "GNO2GED";
|
|
1401
1366
|
});
|
|
1402
|
-
return foundItem;
|
|
1403
1367
|
}
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
|
|
1368
|
+
getAncestryTreeId() {
|
|
1369
|
+
return this.getFromSourceHeads("SOUR._TREE.RIN.value") || (get(this, "HEAD.SOUR._TREE.RIN.value") || get(this.getGedcom(), "HEAD.SOUR._TREE.RIN.value"));
|
|
1370
|
+
}
|
|
1371
|
+
getMyHeritageTreeId() {
|
|
1372
|
+
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"));
|
|
1373
|
+
}
|
|
1374
|
+
getTreeId() {
|
|
1375
|
+
if (this?.isAncestry()) {
|
|
1376
|
+
const id = this.getAncestryTreeId();
|
|
1377
|
+
if (id !== void 0) return id;
|
|
1409
1378
|
}
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
|
|
1420
|
-
|
|
1421
|
-
|
|
1422
|
-
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
|
|
1379
|
+
if (this?.isMyHeritage()) {
|
|
1380
|
+
const id = this.getMyHeritageTreeId();
|
|
1381
|
+
if (id !== void 0) return id;
|
|
1382
|
+
}
|
|
1383
|
+
if (this?.isFamilySearch()) {
|
|
1384
|
+
const id = this.getFamilySearchTreeId();
|
|
1385
|
+
if (id !== void 0) return id;
|
|
1386
|
+
}
|
|
1387
|
+
if (this?.isGNO2GED()) {
|
|
1388
|
+
const id = this.getGNO2GEDTreeId();
|
|
1389
|
+
if (id !== void 0) return id;
|
|
1390
|
+
}
|
|
1391
|
+
if (this?.isAhnenblatt()) {
|
|
1392
|
+
const id = this.getAhnenblattTreeId();
|
|
1393
|
+
if (id !== void 0) return id;
|
|
1394
|
+
}
|
|
1395
|
+
if (this?.isGeni()) {
|
|
1396
|
+
const id = this.getGeniTreeId();
|
|
1397
|
+
if (id !== void 0) return id;
|
|
1398
|
+
}
|
|
1399
|
+
if (this?.isGenoPro()) {
|
|
1400
|
+
const id = this.getGenoProTreeId();
|
|
1401
|
+
if (id !== void 0) return id;
|
|
1402
|
+
}
|
|
1403
|
+
return this.getUniversalTreeId();
|
|
1404
|
+
}
|
|
1405
|
+
getAncestryTreeName() {
|
|
1406
|
+
return this.getFromSourceHeads("SOUR._TREE.value") || (get(this, "HEAD.SOUR._TREE.value") || get(this.getGedcom(), "HEAD.SOUR._TREE.value"));
|
|
1407
|
+
}
|
|
1408
|
+
getMyHeritageTreeName() {
|
|
1409
|
+
const path = "HEAD.FILE.value";
|
|
1410
|
+
const treeDetails = get(this, path) || get(this.getGedcom(), path);
|
|
1411
|
+
return treeDetails?.match(
|
|
1412
|
+
/Exported by MyHeritage.com from (?<tree>.+) in.+$/
|
|
1413
|
+
)?.groups?.tree;
|
|
1414
|
+
}
|
|
1415
|
+
getFamilySearchTreeId() {
|
|
1416
|
+
const rin = this.getFromSourceHeads("SOUR._TREE.RIN.value") || get(this, "HEAD.SOUR._TREE.RIN.value") || get(this.getGedcom(), "HEAD.SOUR._TREE.RIN.value");
|
|
1417
|
+
if (rin) {
|
|
1418
|
+
return rin;
|
|
1419
|
+
}
|
|
1420
|
+
return "familysearch";
|
|
1421
|
+
}
|
|
1422
|
+
getFamilySearchTreeName() {
|
|
1423
|
+
const treeName = this.getFromSourceHeads("SOUR._TREE.value") || get(this, "HEAD.SOUR._TREE.value") || get(this.getGedcom(), "HEAD.SOUR._TREE.value");
|
|
1424
|
+
if (treeName) {
|
|
1425
|
+
return treeName;
|
|
1426
|
+
}
|
|
1427
|
+
const fileName = get(this, "HEAD.FILE.value") || get(this.getGedcom(), "HEAD.FILE.value");
|
|
1428
|
+
return fileName || "FamilySearch Import";
|
|
1429
|
+
}
|
|
1430
|
+
getAhnenblattTreeId() {
|
|
1431
|
+
const fileName = get(this, "HEAD.FILE.value") || get(this.getGedcom(), "HEAD.FILE.value");
|
|
1432
|
+
if (fileName) {
|
|
1433
|
+
const idMatch = fileName.match(/_(\d+)/);
|
|
1434
|
+
if (idMatch) {
|
|
1435
|
+
return idMatch[1];
|
|
1439
1436
|
}
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
newList.item(key, value);
|
|
1443
|
-
});
|
|
1444
|
-
return newList;
|
|
1437
|
+
}
|
|
1438
|
+
return void 0;
|
|
1445
1439
|
}
|
|
1446
|
-
|
|
1447
|
-
const
|
|
1448
|
-
|
|
1449
|
-
|
|
1450
|
-
|
|
1451
|
-
|
|
1452
|
-
|
|
1440
|
+
getAhnenblattTreeName() {
|
|
1441
|
+
const fileName = get(this, "HEAD.FILE.value") || get(this.getGedcom(), "HEAD.FILE.value");
|
|
1442
|
+
return fileName?.replace(/\.ged$/i, "").replace(/_/g, " ");
|
|
1443
|
+
}
|
|
1444
|
+
getGeniTreeId() {
|
|
1445
|
+
const fileName = get(this, "HEAD.FILE.value") || get(this.getGedcom(), "HEAD.FILE.value");
|
|
1446
|
+
if (fileName) {
|
|
1447
|
+
const idMatch = fileName.match(/_(\d+)/);
|
|
1448
|
+
if (idMatch) {
|
|
1449
|
+
return idMatch[1];
|
|
1450
|
+
}
|
|
1453
1451
|
}
|
|
1454
|
-
|
|
1455
|
-
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
let value = raw?.toValue();
|
|
1467
|
-
if (getter && typeof getter === "function") {
|
|
1468
|
-
value = getter(value, raw);
|
|
1469
|
-
}
|
|
1470
|
-
if (value) {
|
|
1471
|
-
group.push(value);
|
|
1472
|
-
}
|
|
1452
|
+
return void 0;
|
|
1453
|
+
}
|
|
1454
|
+
getGeniTreeName() {
|
|
1455
|
+
const fileName = get(this, "HEAD.FILE.value") || get(this.getGedcom(), "HEAD.FILE.value");
|
|
1456
|
+
return fileName?.replace(/\.ged$/i, "").replace(/_/g, " ");
|
|
1457
|
+
}
|
|
1458
|
+
getGenoProTreeId() {
|
|
1459
|
+
const fileName = get(this, "HEAD.FILE.value") || get(this.getGedcom(), "HEAD.FILE.value");
|
|
1460
|
+
if (fileName) {
|
|
1461
|
+
const idMatch = fileName.match(/_(\d+)/);
|
|
1462
|
+
if (idMatch) {
|
|
1463
|
+
return idMatch[1];
|
|
1473
1464
|
}
|
|
1474
|
-
|
|
1475
|
-
|
|
1465
|
+
}
|
|
1466
|
+
return void 0;
|
|
1467
|
+
}
|
|
1468
|
+
getGenoProTreeName() {
|
|
1469
|
+
const fileName = get(this, "HEAD.FILE.value") || get(this.getGedcom(), "HEAD.FILE.value");
|
|
1470
|
+
return fileName?.replace(/\.ged$/i, "").replace(/_/g, " ");
|
|
1471
|
+
}
|
|
1472
|
+
getGNO2GEDTreeId() {
|
|
1473
|
+
const rin = get(this, "HEAD._TREE.RIN.value") || get(this.getGedcom(), "HEAD._TREE.RIN.value");
|
|
1474
|
+
if (rin) {
|
|
1475
|
+
return rin;
|
|
1476
|
+
}
|
|
1477
|
+
return `gno_${this._gedcom?.refcount || "unknown"}`;
|
|
1478
|
+
}
|
|
1479
|
+
getGNO2GEDTreeName() {
|
|
1480
|
+
const treeName = get(this, "HEAD._TREE.value") || get(this.getGedcom(), "HEAD._TREE.value");
|
|
1481
|
+
if (treeName) {
|
|
1482
|
+
return treeName;
|
|
1483
|
+
}
|
|
1484
|
+
const fileName = get(this, "HEAD.FILE.value") || get(this.getGedcom(), "HEAD.FILE.value");
|
|
1485
|
+
return fileName || "GNO2GED Export";
|
|
1486
|
+
}
|
|
1487
|
+
/**
|
|
1488
|
+
* Universal tree ID getter for unknown/unrecognized GEDCOM sources
|
|
1489
|
+
* Tries to extract an ID from various common locations
|
|
1490
|
+
*/
|
|
1491
|
+
getUniversalTreeId() {
|
|
1492
|
+
const sourceType = this.getSourceType();
|
|
1493
|
+
const prefix = sourceType ? sourceType.toLowerCase() : "tree";
|
|
1494
|
+
const fileName = get(this, "HEAD.FILE.value") || get(this.getGedcom(), "HEAD.FILE.value");
|
|
1495
|
+
if (fileName) {
|
|
1496
|
+
const idMatch = fileName.match(/_(\d+)/);
|
|
1497
|
+
if (idMatch) {
|
|
1498
|
+
return `${prefix}_${idMatch[1]}`;
|
|
1476
1499
|
}
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
|
|
1493
|
-
|
|
1494
|
-
|
|
1495
|
-
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
|
|
1505
|
-
|
|
1506
|
-
|
|
1500
|
+
}
|
|
1501
|
+
return `${prefix}_${this._gedcom?.refcount || "unknown"}`;
|
|
1502
|
+
}
|
|
1503
|
+
/**
|
|
1504
|
+
* Universal tree name getter for unknown/unrecognized GEDCOM sources
|
|
1505
|
+
* Tries to extract a name from various common locations
|
|
1506
|
+
*/
|
|
1507
|
+
getUniversalTreeName() {
|
|
1508
|
+
const sourceType = this.getSourceType();
|
|
1509
|
+
const prefix = sourceType ? `${sourceType}-` : "";
|
|
1510
|
+
const fileName = get(this, "HEAD.FILE.value") || get(this.getGedcom(), "HEAD.FILE.value");
|
|
1511
|
+
if (fileName) {
|
|
1512
|
+
const cleanName = fileName.replace(/\.ged$/i, "").replace(/_/g, " ");
|
|
1513
|
+
return `${prefix}${cleanName}`;
|
|
1514
|
+
}
|
|
1515
|
+
const sourName = this.getFromSourceHeads("SOUR.NAME.value") || get(this, "HEAD.SOUR.NAME.value") || get(this.getGedcom(), "HEAD.SOUR.NAME.value");
|
|
1516
|
+
if (sourName) {
|
|
1517
|
+
return `${prefix}${sourName}`;
|
|
1518
|
+
}
|
|
1519
|
+
const sourValue = this.getFromSourceHeads("SOUR.value") || get(this, "HEAD.SOUR.value") || get(this.getGedcom(), "HEAD.SOUR.value");
|
|
1520
|
+
if (sourValue) {
|
|
1521
|
+
return `${prefix}${sourValue}`;
|
|
1522
|
+
}
|
|
1523
|
+
return `${prefix}Unknown Tree`;
|
|
1524
|
+
}
|
|
1525
|
+
getTreeName() {
|
|
1526
|
+
if (this?.isAncestry()) {
|
|
1527
|
+
const name = this.getAncestryTreeName();
|
|
1528
|
+
if (name) return name;
|
|
1529
|
+
}
|
|
1530
|
+
if (this?.isMyHeritage()) {
|
|
1531
|
+
const name = this.getMyHeritageTreeName();
|
|
1532
|
+
if (name) return name;
|
|
1533
|
+
}
|
|
1534
|
+
if (this?.isFamilySearch()) {
|
|
1535
|
+
const name = this.getFamilySearchTreeName();
|
|
1536
|
+
if (name) return name;
|
|
1537
|
+
}
|
|
1538
|
+
if (this?.isGNO2GED()) {
|
|
1539
|
+
const name = this.getGNO2GEDTreeName();
|
|
1540
|
+
if (name) return name;
|
|
1541
|
+
}
|
|
1542
|
+
if (this?.isAhnenblatt()) {
|
|
1543
|
+
const name = this.getAhnenblattTreeName();
|
|
1544
|
+
if (name) return name;
|
|
1545
|
+
}
|
|
1546
|
+
if (this?.isGeni()) {
|
|
1547
|
+
const name = this.getGeniTreeName();
|
|
1548
|
+
if (name) return name;
|
|
1549
|
+
}
|
|
1550
|
+
if (this?.isGenoPro()) {
|
|
1551
|
+
const name = this.getGenoProTreeName();
|
|
1552
|
+
if (name) return name;
|
|
1553
|
+
}
|
|
1554
|
+
return this.getUniversalTreeName();
|
|
1555
|
+
}
|
|
1556
|
+
};
|
|
1557
|
+
var createProxy = (target) => {
|
|
1558
|
+
return new Proxy(target, {
|
|
1559
|
+
get(t, prop, receiver) {
|
|
1560
|
+
if (prop === "unwrapped") {
|
|
1561
|
+
return target;
|
|
1562
|
+
}
|
|
1563
|
+
if (prop in t) {
|
|
1564
|
+
return Reflect.get(t, prop, receiver);
|
|
1565
|
+
}
|
|
1566
|
+
if (!isOnlyMainProp(prop)) {
|
|
1567
|
+
const ref = t.ref;
|
|
1568
|
+
if (ref && prop in ref) {
|
|
1569
|
+
return Reflect.get(ref, prop, receiver);
|
|
1507
1570
|
}
|
|
1508
|
-
|
|
1509
|
-
}, {});
|
|
1571
|
+
}
|
|
1510
1572
|
}
|
|
1511
|
-
|
|
1573
|
+
});
|
|
1574
|
+
};
|
|
1575
|
+
var createCommon = (gedcom, id, main, parent) => {
|
|
1576
|
+
return createProxy(
|
|
1577
|
+
new Common(gedcom, id, main, parent)
|
|
1578
|
+
);
|
|
1579
|
+
};
|
|
1580
|
+
var isOnlyMainProp = (key) => {
|
|
1581
|
+
return key === "_gedcom" || key === "_main" || key === "_parent" || key === "_uniqueId" || key === "_type" || key === "_refs" || key === "id" || key === "_id";
|
|
1582
|
+
};
|
|
1583
|
+
var isValidKey = (common, key) => {
|
|
1584
|
+
const prop = get(common, key);
|
|
1585
|
+
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);
|
|
1586
|
+
};
|
|
1587
|
+
var getValidKeys = (common) => {
|
|
1588
|
+
return Object.keys(common).filter((key) => {
|
|
1589
|
+
return isValidKey(common, key);
|
|
1590
|
+
});
|
|
1591
|
+
};
|
|
1592
|
+
var getValidTag = (tag) => {
|
|
1593
|
+
return tag.replace(/^@@/, "");
|
|
1594
|
+
};
|
|
1595
|
+
var getListTag = (tag) => {
|
|
1596
|
+
return `@@${tag}`;
|
|
1597
|
+
};
|
|
1598
|
+
var isId = (string) => {
|
|
1599
|
+
return ID_REG.test(string);
|
|
1600
|
+
};
|
|
1601
|
+
var idGetter = (id) => {
|
|
1602
|
+
if (id === void 0) {
|
|
1603
|
+
return void 0;
|
|
1512
1604
|
}
|
|
1513
|
-
|
|
1514
|
-
|
|
1515
|
-
|
|
1605
|
+
let newId = `${id}`;
|
|
1606
|
+
const parts = newId?.match(ID_GETTER_REG)?.groups;
|
|
1607
|
+
if (!parts?.at && !parts?.letter) {
|
|
1608
|
+
newId = `@U${newId}`;
|
|
1609
|
+
} else if (!parts.at) {
|
|
1610
|
+
newId = `@${newId}`;
|
|
1611
|
+
} else if (!parts.letter) {
|
|
1612
|
+
newId = newId.replace(/^@/, "@U");
|
|
1613
|
+
}
|
|
1614
|
+
if (!newId.endsWith("@")) {
|
|
1615
|
+
newId = `${newId}@`;
|
|
1616
|
+
}
|
|
1617
|
+
return newId;
|
|
1618
|
+
};
|
|
1619
|
+
|
|
1620
|
+
// src/utils/fact-edit.ts
|
|
1621
|
+
var SINGLETON_TAGS = /* @__PURE__ */ new Set(["BIRT", "DEAT", "SSN", "SEX", "DSCR"]);
|
|
1622
|
+
var firstRecord = (node) => {
|
|
1623
|
+
if (!node) {
|
|
1624
|
+
return void 0;
|
|
1625
|
+
}
|
|
1626
|
+
if (node instanceof List) {
|
|
1627
|
+
return node.index(0);
|
|
1628
|
+
}
|
|
1629
|
+
return node.index(0) ?? node;
|
|
1630
|
+
};
|
|
1631
|
+
var setDateOn = (gedcom, owner, parent, date) => {
|
|
1632
|
+
const trimmed = date.trim();
|
|
1633
|
+
if (!trimmed) {
|
|
1634
|
+
return;
|
|
1635
|
+
}
|
|
1636
|
+
let dateNode = parent.get("DATE");
|
|
1637
|
+
if (!dateNode || dateNode instanceof List) {
|
|
1638
|
+
dateNode = createCommonDate(gedcom, void 0, owner, parent);
|
|
1639
|
+
dateNode.type = "DATE";
|
|
1640
|
+
parent.set("DATE", dateNode);
|
|
1641
|
+
}
|
|
1642
|
+
dateNode.value = trimmed;
|
|
1643
|
+
};
|
|
1644
|
+
var fillFact = (gedcom, owner, event, input) => {
|
|
1645
|
+
if (input.value?.trim()) {
|
|
1646
|
+
event.value = input.value.trim();
|
|
1647
|
+
}
|
|
1648
|
+
if (input.type?.trim()) {
|
|
1649
|
+
event.set("TYPE", input.type.trim());
|
|
1650
|
+
}
|
|
1651
|
+
if (input.date) {
|
|
1652
|
+
setDateOn(gedcom, owner, event, input.date);
|
|
1653
|
+
}
|
|
1654
|
+
if (input.place?.trim()) {
|
|
1655
|
+
event.set("PLAC", input.place.trim());
|
|
1656
|
+
}
|
|
1657
|
+
if (input.note?.trim()) {
|
|
1658
|
+
event.set("NOTE", input.note.trim());
|
|
1659
|
+
}
|
|
1660
|
+
};
|
|
1661
|
+
var addIndividualFact = (indi, input) => {
|
|
1662
|
+
const gedcom = indi.getGedcom();
|
|
1663
|
+
if (!gedcom) {
|
|
1664
|
+
return void 0;
|
|
1665
|
+
}
|
|
1666
|
+
const tag = input.tag;
|
|
1667
|
+
let event = SINGLETON_TAGS.has(tag) ? firstRecord(indi.get(tag)) : void 0;
|
|
1668
|
+
if (!event) {
|
|
1669
|
+
event = createCommon(gedcom, void 0, indi);
|
|
1670
|
+
event.type = tag;
|
|
1671
|
+
if (SINGLETON_TAGS.has(tag)) {
|
|
1672
|
+
indi.set(tag, event);
|
|
1673
|
+
} else {
|
|
1674
|
+
indi.assign(tag, event);
|
|
1516
1675
|
}
|
|
1517
|
-
return this.keys().findIndex((key) => key === item.id);
|
|
1518
1676
|
}
|
|
1519
|
-
|
|
1520
|
-
|
|
1677
|
+
fillFact(gedcom, indi, event, input);
|
|
1678
|
+
return event;
|
|
1679
|
+
};
|
|
1680
|
+
var addFamilyFact = (fam, input) => {
|
|
1681
|
+
const gedcom = fam.getGedcom();
|
|
1682
|
+
if (!gedcom) {
|
|
1683
|
+
return void 0;
|
|
1521
1684
|
}
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
|
|
1685
|
+
const event = createCommon(gedcom, void 0, fam);
|
|
1686
|
+
event.type = input.tag;
|
|
1687
|
+
fam.assign(input.tag, event);
|
|
1688
|
+
fillFact(gedcom, fam, event, input);
|
|
1689
|
+
return event;
|
|
1690
|
+
};
|
|
1691
|
+
|
|
1692
|
+
// src/utils/family-edit.ts
|
|
1693
|
+
var PEDIGREE_VALUES = [
|
|
1694
|
+
"birth" /* BIRTH */,
|
|
1695
|
+
"adopted" /* ADOPTED */,
|
|
1696
|
+
"foster" /* FOSTER */,
|
|
1697
|
+
"step" /* STEP */,
|
|
1698
|
+
"sealing" /* SEALING */
|
|
1699
|
+
];
|
|
1700
|
+
var toGedcomPedigree = (value) => {
|
|
1701
|
+
const normalized = String(value || "birth" /* BIRTH */).toLowerCase();
|
|
1702
|
+
if (normalized === "biological" /* BIOLOGICAL */ || normalized === "birth" /* BIRTH */) {
|
|
1703
|
+
return "birth" /* BIRTH */;
|
|
1525
1704
|
}
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
|
|
1529
|
-
|
|
1530
|
-
|
|
1531
|
-
|
|
1532
|
-
json[validTag] = [json[validTag]];
|
|
1533
|
-
}
|
|
1534
|
-
json[validTag].push(
|
|
1535
|
-
item.toObject(validTag, options)
|
|
1536
|
-
);
|
|
1537
|
-
} else {
|
|
1538
|
-
json[validTag] = item.toObject(
|
|
1539
|
-
validTag,
|
|
1540
|
-
options
|
|
1541
|
-
);
|
|
1542
|
-
}
|
|
1543
|
-
});
|
|
1544
|
-
return json;
|
|
1705
|
+
const match = PEDIGREE_VALUES.find((item) => item === normalized);
|
|
1706
|
+
return match ?? "birth" /* BIRTH */;
|
|
1707
|
+
};
|
|
1708
|
+
var pointerIds = (tag) => {
|
|
1709
|
+
if (!tag) {
|
|
1710
|
+
return [];
|
|
1545
1711
|
}
|
|
1546
|
-
|
|
1547
|
-
|
|
1548
|
-
return gedcom.join("\n");
|
|
1712
|
+
if (tag instanceof List) {
|
|
1713
|
+
return tag.values().map((item) => item?.toValue?.()).filter((value2) => !!value2);
|
|
1549
1714
|
}
|
|
1550
|
-
|
|
1551
|
-
|
|
1552
|
-
|
|
1553
|
-
|
|
1554
|
-
|
|
1555
|
-
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
return gedcom;
|
|
1715
|
+
const value = tag.toValue?.();
|
|
1716
|
+
return value ? [String(value)] : [];
|
|
1717
|
+
};
|
|
1718
|
+
var firstPointerId = (tag) => pointerIds(tag)[0];
|
|
1719
|
+
var makePointer = (gedcom, parent, value, refType) => {
|
|
1720
|
+
const pointer = createCommon(gedcom, void 0, parent);
|
|
1721
|
+
pointer.value = value;
|
|
1722
|
+
pointer.refType = refType;
|
|
1723
|
+
return pointer;
|
|
1724
|
+
};
|
|
1725
|
+
var familyHasParent = (fam, indiId) => pointerIds(fam.get("HUSB")).includes(indiId) || pointerIds(fam.get("WIFE")).includes(indiId);
|
|
1726
|
+
var familyHasChild = (fam, indiId) => pointerIds(fam.get("CHIL")).includes(indiId);
|
|
1727
|
+
var spouseTagFor = (indi, fam) => {
|
|
1728
|
+
const husbId = firstPointerId(fam.get("HUSB"));
|
|
1729
|
+
const wifeId = firstPointerId(fam.get("WIFE"));
|
|
1730
|
+
if (husbId === indi.id) {
|
|
1731
|
+
return "HUSB";
|
|
1568
1732
|
}
|
|
1569
|
-
|
|
1570
|
-
|
|
1571
|
-
this.entries().forEach(([key, item]) => {
|
|
1572
|
-
propList.item(key, item?.toValue());
|
|
1573
|
-
});
|
|
1574
|
-
return propList;
|
|
1733
|
+
if (wifeId === indi.id) {
|
|
1734
|
+
return "WIFE";
|
|
1575
1735
|
}
|
|
1576
|
-
|
|
1577
|
-
|
|
1578
|
-
return this.get(tag);
|
|
1736
|
+
if (indi.isFemale()) {
|
|
1737
|
+
return wifeId && wifeId !== indi.id ? "HUSB" : "WIFE";
|
|
1579
1738
|
}
|
|
1580
|
-
|
|
1581
|
-
return
|
|
1739
|
+
if (indi.isMale()) {
|
|
1740
|
+
return husbId && husbId !== indi.id ? "WIFE" : "HUSB";
|
|
1582
1741
|
}
|
|
1583
|
-
|
|
1584
|
-
|
|
1585
|
-
|
|
1586
|
-
|
|
1587
|
-
|
|
1588
|
-
|
|
1742
|
+
return husbId ? "WIFE" : "HUSB";
|
|
1743
|
+
};
|
|
1744
|
+
var canAttachAsSpouse = (fam, indi) => {
|
|
1745
|
+
if (!indi.id) {
|
|
1746
|
+
return false;
|
|
1747
|
+
}
|
|
1748
|
+
if (familyHasParent(fam, indi.id)) {
|
|
1749
|
+
return true;
|
|
1750
|
+
}
|
|
1751
|
+
const tag = spouseTagFor(indi, fam);
|
|
1752
|
+
const occupied = firstPointerId(fam.get(tag));
|
|
1753
|
+
return !occupied || occupied === indi.id;
|
|
1754
|
+
};
|
|
1755
|
+
var pointerByValue = (tag, id) => {
|
|
1756
|
+
if (!tag) {
|
|
1757
|
+
return void 0;
|
|
1758
|
+
}
|
|
1759
|
+
const fromValues = tag.toValueList?.().item(id);
|
|
1760
|
+
if (fromValues) {
|
|
1761
|
+
return fromValues;
|
|
1762
|
+
}
|
|
1763
|
+
return tag.toList()?.values().find((item) => item?.toValue?.() === id);
|
|
1764
|
+
};
|
|
1765
|
+
var setChildPedigree = (fam, child, pedigree, parent) => {
|
|
1766
|
+
if (!fam.id || !child.id) {
|
|
1767
|
+
return;
|
|
1768
|
+
}
|
|
1769
|
+
const pedi = toGedcomPedigree(pedigree);
|
|
1770
|
+
const famc = pointerByValue(child.get("FAMC"), fam.id);
|
|
1771
|
+
if (famc) {
|
|
1772
|
+
famc.set("PEDI", pedi);
|
|
1773
|
+
}
|
|
1774
|
+
const chil = pointerByValue(fam.get("CHIL"), child.id);
|
|
1775
|
+
if (!chil) {
|
|
1776
|
+
return;
|
|
1777
|
+
}
|
|
1778
|
+
const setFather = !parent || parent.isMale() || parent.isUnknownSex();
|
|
1779
|
+
const setMother = !parent || parent.isFemale() || parent.isUnknownSex();
|
|
1780
|
+
if (setFather) {
|
|
1781
|
+
chil.set("_FREL", pedi);
|
|
1782
|
+
}
|
|
1783
|
+
if (setMother) {
|
|
1784
|
+
chil.set("_MREL", pedi);
|
|
1785
|
+
}
|
|
1786
|
+
};
|
|
1787
|
+
var attachSpouseToFamily = (fam, indi) => {
|
|
1788
|
+
const gedcom = fam.getGedcom() ?? indi.getGedcom();
|
|
1789
|
+
if (!indi.id || !fam.id || !gedcom) {
|
|
1790
|
+
return false;
|
|
1791
|
+
}
|
|
1792
|
+
if (!canAttachAsSpouse(fam, indi)) {
|
|
1793
|
+
return false;
|
|
1794
|
+
}
|
|
1795
|
+
const tag = spouseTagFor(indi, fam);
|
|
1796
|
+
if (firstPointerId(fam.get(tag)) !== indi.id) {
|
|
1797
|
+
fam.set(tag, makePointer(gedcom, fam, indi.id, "INDI"));
|
|
1798
|
+
}
|
|
1799
|
+
indi.assign("FAMS", makePointer(gedcom, indi, fam.id, "FAM"), true);
|
|
1800
|
+
return true;
|
|
1801
|
+
};
|
|
1802
|
+
var attachChildToFamily = (fam, child, pedigree, parent) => {
|
|
1803
|
+
const gedcom = fam.getGedcom() ?? child.getGedcom();
|
|
1804
|
+
if (!child.id || !fam.id || !gedcom) {
|
|
1805
|
+
return false;
|
|
1806
|
+
}
|
|
1807
|
+
if (!familyHasChild(fam, child.id)) {
|
|
1808
|
+
fam.assign("CHIL", makePointer(gedcom, fam, child.id, "INDI"), true);
|
|
1809
|
+
}
|
|
1810
|
+
const existingFamc = pointerByValue(child.get("FAMC"), fam.id);
|
|
1811
|
+
if (!existingFamc) {
|
|
1812
|
+
child.assign("FAMC", makePointer(gedcom, child, fam.id, "FAM"), true);
|
|
1813
|
+
}
|
|
1814
|
+
setChildPedigree(fam, child, pedigree, parent);
|
|
1815
|
+
return true;
|
|
1816
|
+
};
|
|
1817
|
+
var findReusableParentChildFamily = (parent, child) => {
|
|
1818
|
+
if (!parent.id || !child.id) {
|
|
1819
|
+
return void 0;
|
|
1820
|
+
}
|
|
1821
|
+
let reusableFamc;
|
|
1822
|
+
let already = false;
|
|
1823
|
+
child.getFamilies("FAMC")?.forEach((fam) => {
|
|
1824
|
+
if (!fam) {
|
|
1825
|
+
return;
|
|
1826
|
+
}
|
|
1827
|
+
if (familyHasParent(fam, parent.id) && familyHasChild(fam, child.id)) {
|
|
1828
|
+
already = true;
|
|
1829
|
+
return;
|
|
1830
|
+
}
|
|
1831
|
+
if (!reusableFamc && canAttachAsSpouse(fam, parent)) {
|
|
1832
|
+
reusableFamc = fam;
|
|
1833
|
+
}
|
|
1834
|
+
});
|
|
1835
|
+
if (already) {
|
|
1836
|
+
return "already";
|
|
1837
|
+
}
|
|
1838
|
+
if (reusableFamc) {
|
|
1839
|
+
return reusableFamc;
|
|
1840
|
+
}
|
|
1841
|
+
const parentFams = [];
|
|
1842
|
+
parent.getFamilies("FAMS")?.forEach((fam) => {
|
|
1843
|
+
if (fam) {
|
|
1844
|
+
parentFams.push(fam);
|
|
1845
|
+
}
|
|
1846
|
+
});
|
|
1847
|
+
if (parentFams.length === 1) {
|
|
1848
|
+
return parentFams[0];
|
|
1589
1849
|
}
|
|
1850
|
+
return void 0;
|
|
1851
|
+
};
|
|
1852
|
+
|
|
1853
|
+
// src/utils/get-family-with.ts
|
|
1854
|
+
var getFamilyWith = (person1, person2, famType = "FAMS") => {
|
|
1855
|
+
return person1?.get(famType)?.toValueList().find((fam) => {
|
|
1856
|
+
const family = fam;
|
|
1857
|
+
return famType === "FAMC" || family?.HUSB?.value === person2 || family?.WIFE?.value === person2;
|
|
1858
|
+
});
|
|
1590
1859
|
};
|
|
1591
1860
|
|
|
1592
1861
|
// src/utils/get-places.ts
|
|
@@ -2219,6 +2488,31 @@ var Fam = class extends Common {
|
|
|
2219
2488
|
getParents() {
|
|
2220
2489
|
return this.getHusband().copy().merge(this.getWife());
|
|
2221
2490
|
}
|
|
2491
|
+
hasParent(indi) {
|
|
2492
|
+
const indiId = typeof indi === "string" ? indi : indi?.id;
|
|
2493
|
+
return !!indiId && familyHasParent(this, indiId);
|
|
2494
|
+
}
|
|
2495
|
+
hasChild(indi) {
|
|
2496
|
+
const indiId = typeof indi === "string" ? indi : indi?.id;
|
|
2497
|
+
return !!indiId && familyHasChild(this, indiId);
|
|
2498
|
+
}
|
|
2499
|
+
canAddSpouse(indi) {
|
|
2500
|
+
return canAttachAsSpouse(this, indi);
|
|
2501
|
+
}
|
|
2502
|
+
addSpouse(indi) {
|
|
2503
|
+
return attachSpouseToFamily(this, indi);
|
|
2504
|
+
}
|
|
2505
|
+
addChild(child, pedigree, parent) {
|
|
2506
|
+
return attachChildToFamily(
|
|
2507
|
+
this,
|
|
2508
|
+
child,
|
|
2509
|
+
pedigree,
|
|
2510
|
+
parent
|
|
2511
|
+
);
|
|
2512
|
+
}
|
|
2513
|
+
addFact(input) {
|
|
2514
|
+
return addFamilyFact(this, input);
|
|
2515
|
+
}
|
|
2222
2516
|
toList() {
|
|
2223
2517
|
return new Families().concat(
|
|
2224
2518
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
@@ -2319,19 +2613,51 @@ var ALLOWED_FACTS = [
|
|
|
2319
2613
|
"OCCU",
|
|
2320
2614
|
"OCCUPATIONS",
|
|
2321
2615
|
"RESI",
|
|
2616
|
+
"BIRT",
|
|
2617
|
+
"DEAT",
|
|
2322
2618
|
"BAPT",
|
|
2619
|
+
"BAPM",
|
|
2323
2620
|
"CHRI",
|
|
2324
2621
|
"CHR",
|
|
2622
|
+
"CHRA",
|
|
2325
2623
|
"BURI",
|
|
2326
|
-
"
|
|
2624
|
+
"CREM",
|
|
2625
|
+
"ADOP",
|
|
2626
|
+
"BARM",
|
|
2627
|
+
"BASM",
|
|
2628
|
+
"BLES",
|
|
2629
|
+
"CONF",
|
|
2630
|
+
"FCOM",
|
|
2631
|
+
"ORDN",
|
|
2632
|
+
"NATU",
|
|
2633
|
+
"EMIG",
|
|
2634
|
+
"IMMI",
|
|
2635
|
+
"CENS",
|
|
2636
|
+
"PROB",
|
|
2637
|
+
"WILL",
|
|
2327
2638
|
"GRAD",
|
|
2639
|
+
"RETI",
|
|
2640
|
+
"EDUC",
|
|
2328
2641
|
"DIV",
|
|
2329
|
-
"IMMI",
|
|
2330
2642
|
"RELI",
|
|
2643
|
+
"CAST",
|
|
2644
|
+
"DSCR",
|
|
2645
|
+
"NATI",
|
|
2646
|
+
"PROP",
|
|
2647
|
+
"SSN",
|
|
2648
|
+
"TITL",
|
|
2649
|
+
"ADDR",
|
|
2650
|
+
"BAPL",
|
|
2651
|
+
"CONL",
|
|
2652
|
+
"ENDL",
|
|
2653
|
+
"SLGC",
|
|
2331
2654
|
"_MILT",
|
|
2332
2655
|
"_MILTID",
|
|
2333
2656
|
"FACT",
|
|
2334
|
-
"_ORIG"
|
|
2657
|
+
"_ORIG",
|
|
2658
|
+
"_WLNK",
|
|
2659
|
+
"WWW",
|
|
2660
|
+
"URL"
|
|
2335
2661
|
];
|
|
2336
2662
|
var DISALLOWED_CUSTOM_FACTS = ["DNA Test", "Newspaper"];
|
|
2337
2663
|
var CustomFactRenderers = {
|
|
@@ -2875,7 +3201,7 @@ var Indi = class extends Common {
|
|
|
2875
3201
|
return result;
|
|
2876
3202
|
}
|
|
2877
3203
|
ancestryLink() {
|
|
2878
|
-
const www = this._gedcom?.HEAD?.SOUR?.CORP?.WWW?.value;
|
|
3204
|
+
const www = this.getFromSourceHeads("SOUR.CORP.WWW.value") || this._gedcom?.HEAD?.SOUR?.CORP?.WWW?.value;
|
|
2879
3205
|
const tree = this.getAncestryTreeId();
|
|
2880
3206
|
if (this.id) {
|
|
2881
3207
|
return `https://${www}/family-tree/person/tree/${tree}/person/${this.id.replace(
|
|
@@ -2887,7 +3213,7 @@ var Indi = class extends Common {
|
|
|
2887
3213
|
async ancestryMedia(namespace) {
|
|
2888
3214
|
const list = {};
|
|
2889
3215
|
const objeList = this.get("OBJE")?.toList().copy();
|
|
2890
|
-
const www = this._gedcom?.HEAD?.SOUR?.CORP?.WWW?.value;
|
|
3216
|
+
const www = this.getFromSourceHeads("SOUR.CORP.WWW.value") || this._gedcom?.HEAD?.SOUR?.CORP?.WWW?.value;
|
|
2891
3217
|
const tree = this.getAncestryTreeId();
|
|
2892
3218
|
if (objeList) {
|
|
2893
3219
|
await Promise.all(
|
|
@@ -2947,7 +3273,7 @@ var Indi = class extends Common {
|
|
|
2947
3273
|
return list;
|
|
2948
3274
|
}
|
|
2949
3275
|
myheritageLink(poolId = 0) {
|
|
2950
|
-
const www = this._gedcom?.HEAD?.SOUR?.CORP?.value?.toLowerCase().replace(/^www\./gi, "");
|
|
3276
|
+
const www = (this.getFromSourceHeads("SOUR.CORP.value") || this._gedcom?.HEAD?.SOUR?.CORP?.value)?.toLowerCase().replace(/^www\./gi, "");
|
|
2951
3277
|
const site = this.getMyHeritageTreeId();
|
|
2952
3278
|
const file = this._gedcom?.HEAD?.get("FILE")?.toValue()?.match(/Exported by MyHeritage.com from .+ in (?<site>.+) on .+$/)?.groups?.site;
|
|
2953
3279
|
const normalizedFile = file?.normalize("NFD").replace(/[\u0300-\u036f]/g, "").toLowerCase().replace(/[^a-z0-9]+/g, "-");
|
|
@@ -3468,6 +3794,57 @@ var Indi = class extends Common {
|
|
|
3468
3794
|
isUnknownSex() {
|
|
3469
3795
|
return !this.isMale() && !this.isFemale();
|
|
3470
3796
|
}
|
|
3797
|
+
addSpouse(other) {
|
|
3798
|
+
if (!this.id || !other?.id || this.id === other.id || !this._gedcom) {
|
|
3799
|
+
return void 0;
|
|
3800
|
+
}
|
|
3801
|
+
const existing = getFamilyWith(this, other.id);
|
|
3802
|
+
if (existing) {
|
|
3803
|
+
return existing;
|
|
3804
|
+
}
|
|
3805
|
+
const fam = this._gedcom.createFamily();
|
|
3806
|
+
if (!fam.addSpouse(this) || !fam.addSpouse(other)) {
|
|
3807
|
+
return void 0;
|
|
3808
|
+
}
|
|
3809
|
+
return fam;
|
|
3810
|
+
}
|
|
3811
|
+
addChild(child, pedigree) {
|
|
3812
|
+
if (!this.id || !child?.id || this.id === child.id || !this._gedcom) {
|
|
3813
|
+
return void 0;
|
|
3814
|
+
}
|
|
3815
|
+
const existing = findReusableParentChildFamily(
|
|
3816
|
+
this,
|
|
3817
|
+
child
|
|
3818
|
+
);
|
|
3819
|
+
if (existing === "already") {
|
|
3820
|
+
const fam2 = child.getFamilies("FAMC")?.find(
|
|
3821
|
+
(item) => !!item && item.hasParent(this.id) && item.hasChild(child.id)
|
|
3822
|
+
);
|
|
3823
|
+
if (fam2) {
|
|
3824
|
+
setChildPedigree(
|
|
3825
|
+
fam2,
|
|
3826
|
+
child,
|
|
3827
|
+
pedigree,
|
|
3828
|
+
this
|
|
3829
|
+
);
|
|
3830
|
+
}
|
|
3831
|
+
return fam2;
|
|
3832
|
+
}
|
|
3833
|
+
const fam = existing ?? this._gedcom.createFamily();
|
|
3834
|
+
if (!fam.addSpouse(this)) {
|
|
3835
|
+
return void 0;
|
|
3836
|
+
}
|
|
3837
|
+
if (!fam.addChild(child, pedigree, this)) {
|
|
3838
|
+
return void 0;
|
|
3839
|
+
}
|
|
3840
|
+
return fam;
|
|
3841
|
+
}
|
|
3842
|
+
addParent(parent, pedigree) {
|
|
3843
|
+
return parent.addChild(this, pedigree);
|
|
3844
|
+
}
|
|
3845
|
+
addFact(input) {
|
|
3846
|
+
return addIndividualFact(this, input);
|
|
3847
|
+
}
|
|
3471
3848
|
getParentType(id) {
|
|
3472
3849
|
let indi;
|
|
3473
3850
|
if (typeof id === "string" || typeof id === "number") {
|
|
@@ -3668,7 +4045,9 @@ var Indi = class extends Common {
|
|
|
3668
4045
|
}
|
|
3669
4046
|
}
|
|
3670
4047
|
if (kinship !== "child" || !breakAfterSpouse) {
|
|
3671
|
-
indi.getBiologicalFathers().copy().merge(indi.getBiologicalMothers()).merge(
|
|
4048
|
+
indi.getBiologicalFathers().copy().merge(indi.getBiologicalMothers()).merge(
|
|
4049
|
+
indi.getFathers().copy().merge(indi.getMothers())
|
|
4050
|
+
).forEach((relative) => {
|
|
3672
4051
|
if (!visited.has(relative)) {
|
|
3673
4052
|
const currentRelation = indi.getParentType(relative);
|
|
3674
4053
|
const isNonBiological = !!currentRelation && currentRelation !== "biological" /* BIOLOGICAL */;
|
|
@@ -6562,14 +6941,6 @@ var isCommonDate = (value) => {
|
|
|
6562
6941
|
return !!value && value !== null && typeof value === "object" && "_date" in value;
|
|
6563
6942
|
};
|
|
6564
6943
|
|
|
6565
|
-
// src/utils/get-family-with.ts
|
|
6566
|
-
var getFamilyWith = (person1, person2, famType = "FAMS") => {
|
|
6567
|
-
return person1?.get(famType)?.toValueList().find((fam) => {
|
|
6568
|
-
const family = fam;
|
|
6569
|
-
return famType === "FAMC" || family?.HUSB?.value === person2 || family?.WIFE?.value === person2;
|
|
6570
|
-
});
|
|
6571
|
-
};
|
|
6572
|
-
|
|
6573
6944
|
// src/constants/orders.ts
|
|
6574
6945
|
var DEFAULT = {};
|
|
6575
6946
|
var BIRTH_ASC = {
|
|
@@ -6809,4 +7180,4 @@ var getMarriageAscAndBirth = (person) => (itemA, keyA, itemB, keyB) => {
|
|
|
6809
7180
|
return getBirthAsc(itemA, keyA, itemB);
|
|
6810
7181
|
};
|
|
6811
7182
|
|
|
6812
|
-
export { ADOPTED, BIOLOGICAL, BIRTH, BIRTH_ASC, BIRTH_DESC, DATE_ASC, DATE_DESC, DEATH_ASC, DEATH_DESC, DEFAULT, EVERY, FEMALE, FOSTER, FRIEND, ID_GETTER_REG, ID_REG, ID_SPLIT_REG, LINE_REG, MALE, MAX_FILE_SIZE_TO_SYNC, OTHER, PARTNER, REF_LINE_REG, SEALING, SINGLE, SPOUSE, STEP, UNKOWN, getBirthAsc, getMarriageAsc, getMarriageAscAndBirth, getMarriageAscAndChildBirth, getNameAsc, getNameAscAndBirth, getNameDesc };
|
|
7183
|
+
export { ADOPTED, APP_BRANDING, BIOLOGICAL, BIRTH, BIRTH_ASC, BIRTH_DESC, DATE_ASC, DATE_DESC, DEATH_ASC, DEATH_DESC, DEFAULT, EVERY, FEMALE, FOSTER, FRIEND, ID_GETTER_REG, ID_REG, ID_SPLIT_REG, LINE_REG, MALE, MAX_FILE_SIZE_TO_SYNC, ORIG_HEAD_TAG, OTHER, PARTNER, REF_LINE_REG, SEALING, SINGLE, SPOUSE, STEP, UNKOWN, getBirthAsc, getMarriageAsc, getMarriageAscAndBirth, getMarriageAscAndChildBirth, getNameAsc, getNameAscAndBirth, getNameDesc };
|