@treeviz/gedcom-parser 2.0.10 → 2.1.0
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/README.md +236 -989
- package/dist/classes/common.d.ts +10 -5
- 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/fam.d.ts +10 -1
- package/dist/classes/fam.d.ts.map +1 -1
- package/dist/classes/fams.d.ts.map +1 -1
- package/dist/classes/gedcom.d.ts +45 -4
- package/dist/classes/gedcom.d.ts.map +1 -1
- package/dist/classes/index.js +1770 -279
- package/dist/classes/indi.d.ts +24 -1
- package/dist/classes/indi.d.ts.map +1 -1
- package/dist/classes/list.d.ts.map +1 -1
- package/dist/classes/note.d.ts.map +1 -1
- package/dist/classes/obje.d.ts +2 -1
- package/dist/classes/obje.d.ts.map +1 -1
- package/dist/cli/index.js +2802 -1296
- package/dist/constants/constants.d.ts +7 -0
- package/dist/constants/constants.d.ts.map +1 -1
- package/dist/constants/index.js +1599 -989
- package/dist/factories/index.js +719 -110
- package/dist/index.d.ts +12 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3837 -2028
- package/dist/interfaces/common.d.ts +6 -4
- package/dist/interfaces/common.d.ts.map +1 -1
- package/dist/interfaces/fam.d.ts +10 -1
- package/dist/interfaces/fam.d.ts.map +1 -1
- package/dist/interfaces/gedcom.d.ts +25 -1
- package/dist/interfaces/gedcom.d.ts.map +1 -1
- package/dist/interfaces/indi.d.ts +15 -1
- package/dist/interfaces/indi.d.ts.map +1 -1
- package/dist/kinship-translator/index.js +719 -110
- package/dist/structures/gedcom.d.ts +2 -0
- package/dist/structures/gedcom.d.ts.map +1 -1
- package/dist/types/types.d.ts +32 -4
- package/dist/types/types.d.ts.map +1 -1
- package/dist/utils/common-creator.d.ts.map +1 -1
- package/dist/utils/fact-edit.d.ts +34 -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/gedcom-version.d.ts +6 -0
- package/dist/utils/gedcom-version.d.ts.map +1 -0
- package/dist/utils/gedcom7-dates.d.ts +20 -0
- package/dist/utils/gedcom7-dates.d.ts.map +1 -0
- package/dist/utils/gedcom7-enumerations.d.ts +26 -0
- package/dist/utils/gedcom7-enumerations.d.ts.map +1 -0
- package/dist/utils/gedcom7-metadata.d.ts +19 -0
- package/dist/utils/gedcom7-metadata.d.ts.map +1 -0
- package/dist/utils/gedcom7-schema.d.ts +27 -0
- package/dist/utils/gedcom7-schema.d.ts.map +1 -0
- package/dist/utils/gedzip.d.ts +81 -0
- package/dist/utils/gedzip.d.ts.map +1 -0
- package/dist/utils/index.d.ts +13 -1
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/index.js +2225 -416
- package/dist/utils/local-media.d.ts +30 -0
- package/dist/utils/local-media.d.ts.map +1 -0
- package/dist/utils/media-utils.d.ts +10 -6
- package/dist/utils/media-utils.d.ts.map +1 -1
- package/dist/utils/multimedia.d.ts +38 -0
- package/dist/utils/multimedia.d.ts.map +1 -0
- package/dist/utils/parser.d.ts +3 -0
- package/dist/utils/parser.d.ts.map +1 -1
- package/dist/utils/uid.d.ts +6 -0
- package/dist/utils/uid.d.ts.map +1 -0
- package/package.json +2 -1
package/dist/cli/index.js
CHANGED
|
@@ -5,6 +5,7 @@ import { fileURLToPath } from 'url';
|
|
|
5
5
|
import { Command } from 'commander';
|
|
6
6
|
import { debounce, set, get, uniqBy, unset, difference, intersectionBy, differenceBy } from 'lodash-es';
|
|
7
7
|
import { format, isValid, parse } from 'date-fns';
|
|
8
|
+
import JSZip from 'jszip';
|
|
8
9
|
import chalk from 'chalk';
|
|
9
10
|
import * as readline from 'readline';
|
|
10
11
|
|
|
@@ -15,11 +16,31 @@ var __export = (target, all) => {
|
|
|
15
16
|
};
|
|
16
17
|
|
|
17
18
|
// src/constants/constants.ts
|
|
18
|
-
var
|
|
19
|
-
var
|
|
19
|
+
var APP_BRANDING = "TreeViz - The Family Tree Visualiser & Editor";
|
|
20
|
+
var REF_LINE_REG = /^0 (?:(@[_a-zA-Z0-9]*@) )?(?<type>_[_A-Z][_a-zA-Z0-9]{2,}|_?[A-Z][A-Za-z0-9]{2,}) ?(?<value>.*)/gm;
|
|
21
|
+
var LINE_REG = /(?<indent>^[0-9]{1,2}) (?:(@[_a-zA-Z0-9]*@) )?(?<type>_[_A-Z][_a-zA-Z0-9]{2,}|_?[A-Z][A-Za-z0-9]{2,}) ?(?<value>.*)/;
|
|
20
22
|
var ID_REG = /^@[_a-zA-Z0-9]+@/;
|
|
21
23
|
var ID_GETTER_REG = /^(?<at>@)?(?<letter>[A-Z])?/i;
|
|
24
|
+
var ORIG_HEAD_TAG = "_ORIGHEAD";
|
|
22
25
|
var MAX_FILE_SIZE_TO_SYNC = 1024 * 1024 * 20;
|
|
26
|
+
|
|
27
|
+
// src/utils/gedcom-trailer.ts
|
|
28
|
+
var TRAILER_LINE = /^0 TRLR\s*$/i;
|
|
29
|
+
var GEDCOM_TRAILER_TAG = "TRLR";
|
|
30
|
+
var isGedcomTrailerTag = (tag) => tag === GEDCOM_TRAILER_TAG;
|
|
31
|
+
var isGedcomTrailerLine = (line) => TRAILER_LINE.test(line);
|
|
32
|
+
var appendGedcomTrailer = (serialized) => {
|
|
33
|
+
const newline = serialized.includes("\r\n") ? "\r\n" : "\n";
|
|
34
|
+
const trimmed = serialized.replace(/(?:\r?\n)+$/, "");
|
|
35
|
+
if (!trimmed) {
|
|
36
|
+
return "0 TRLR";
|
|
37
|
+
}
|
|
38
|
+
const lastLine = trimmed.split(/\r?\n/).at(-1) ?? "";
|
|
39
|
+
if (isGedcomTrailerLine(lastLine)) {
|
|
40
|
+
return trimmed;
|
|
41
|
+
}
|
|
42
|
+
return `${trimmed}${newline}0 TRLR`;
|
|
43
|
+
};
|
|
23
44
|
var List = class _List {
|
|
24
45
|
// length = 0;
|
|
25
46
|
constructor(items) {
|
|
@@ -395,11 +416,17 @@ var List = class _List {
|
|
|
395
416
|
const gedcom = [];
|
|
396
417
|
this.entries().forEach(([_, item]) => {
|
|
397
418
|
const validTag = getValidTag(tag);
|
|
398
|
-
const
|
|
399
|
-
const
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
419
|
+
const xref = item.id;
|
|
420
|
+
const payload = item.exportValue?.();
|
|
421
|
+
if (xref) {
|
|
422
|
+
gedcom.push(
|
|
423
|
+
`${level} ${xref} ${validTag}${payload ? ` ${payload}` : ""}`
|
|
424
|
+
);
|
|
425
|
+
} else {
|
|
426
|
+
gedcom.push(
|
|
427
|
+
`${level} ${validTag}${payload ? ` ${payload}` : ""}`
|
|
428
|
+
);
|
|
429
|
+
}
|
|
403
430
|
gedcom.push(
|
|
404
431
|
...item.toGedcomLines(
|
|
405
432
|
validTag,
|
|
@@ -530,6 +557,9 @@ var Common = class _Common {
|
|
|
530
557
|
delete this._value;
|
|
531
558
|
}
|
|
532
559
|
set(name, value) {
|
|
560
|
+
if (isGedcomTrailerTag(name)) {
|
|
561
|
+
return void 0;
|
|
562
|
+
}
|
|
533
563
|
if (typeof value === "string") {
|
|
534
564
|
const usedValue = createCommon(this._gedcom, void 0, this.main);
|
|
535
565
|
usedValue.value = value;
|
|
@@ -540,6 +570,9 @@ var Common = class _Common {
|
|
|
540
570
|
return get(this, name);
|
|
541
571
|
}
|
|
542
572
|
assign(name, value, unique = false) {
|
|
573
|
+
if (isGedcomTrailerTag(name)) {
|
|
574
|
+
return void 0;
|
|
575
|
+
}
|
|
543
576
|
let curValue = this.get(name);
|
|
544
577
|
if (curValue?.isListable) {
|
|
545
578
|
if (curValue instanceof _Common) {
|
|
@@ -651,12 +684,14 @@ var Common = class _Common {
|
|
|
651
684
|
);
|
|
652
685
|
}
|
|
653
686
|
standardizeObject(tag, options) {
|
|
654
|
-
if (tag === "OBJE" &&
|
|
687
|
+
if (tag === "OBJE" && options?.obje?.standardize && "standardizeMedia" in this) {
|
|
655
688
|
const standardize = this.standardizeMedia;
|
|
656
689
|
return standardize.call(
|
|
657
690
|
this,
|
|
658
691
|
options.obje.namespace,
|
|
659
|
-
options.obje.override
|
|
692
|
+
options.obje.override,
|
|
693
|
+
void 0,
|
|
694
|
+
options.gedcomVersion
|
|
660
695
|
);
|
|
661
696
|
}
|
|
662
697
|
}
|
|
@@ -683,7 +718,7 @@ var Common = class _Common {
|
|
|
683
718
|
if (typeof prop?.toObject === "function") {
|
|
684
719
|
if (prop instanceof _Common) {
|
|
685
720
|
json[validKey] = prop.toObject(validKey, options);
|
|
686
|
-
} else {
|
|
721
|
+
} else if (prop instanceof List) {
|
|
687
722
|
json = {
|
|
688
723
|
...json,
|
|
689
724
|
...prop.toObject(validKey, options)
|
|
@@ -741,8 +776,12 @@ var Common = class _Common {
|
|
|
741
776
|
this.standardizeObject(tag, options);
|
|
742
777
|
const validKeys = getValidKeys(this);
|
|
743
778
|
const gedcom = [];
|
|
779
|
+
const isGedcom7Export = options?.gedcomVersion === "7.0";
|
|
744
780
|
validKeys.forEach((key) => {
|
|
745
781
|
const validKey = key;
|
|
782
|
+
if (isGedcom7Export && validKey === "CONC") {
|
|
783
|
+
return;
|
|
784
|
+
}
|
|
746
785
|
const prop = this.get(validKey);
|
|
747
786
|
if (typeof prop?.toGedcomLines === "function") {
|
|
748
787
|
if (prop instanceof _Common) {
|
|
@@ -753,7 +792,7 @@ var Common = class _Common {
|
|
|
753
792
|
gedcom.push(
|
|
754
793
|
...prop.toGedcomLines(validKey, level + 1, options)
|
|
755
794
|
);
|
|
756
|
-
} else {
|
|
795
|
+
} else if (prop instanceof List) {
|
|
757
796
|
gedcom.push(
|
|
758
797
|
...prop.toGedcomLines(validKey, level, options)
|
|
759
798
|
);
|
|
@@ -762,30 +801,47 @@ var Common = class _Common {
|
|
|
762
801
|
});
|
|
763
802
|
return gedcom;
|
|
764
803
|
}
|
|
804
|
+
getHeadRecord() {
|
|
805
|
+
return get(this, "HEAD") || get(this.getGedcom(), "HEAD");
|
|
806
|
+
}
|
|
807
|
+
getOriginalHeadRecord() {
|
|
808
|
+
return get(this, ORIG_HEAD_TAG) || get(this.getGedcom(), ORIG_HEAD_TAG) || get(this.getHeadRecord(), ORIG_HEAD_TAG);
|
|
809
|
+
}
|
|
810
|
+
getSourceHeads() {
|
|
811
|
+
const heads = [this.getOriginalHeadRecord(), this.getHeadRecord()];
|
|
812
|
+
return heads.filter((head, index) => {
|
|
813
|
+
return Boolean(head && heads.indexOf(head) === index);
|
|
814
|
+
});
|
|
815
|
+
}
|
|
816
|
+
getFromSourceHeads(path) {
|
|
817
|
+
for (const head of this.getSourceHeads()) {
|
|
818
|
+
const value = get(head, path);
|
|
819
|
+
if (value !== void 0 && value !== null && value !== "") {
|
|
820
|
+
return value;
|
|
821
|
+
}
|
|
822
|
+
}
|
|
823
|
+
return void 0;
|
|
824
|
+
}
|
|
825
|
+
sourStartsWith(prefix) {
|
|
826
|
+
return this.getSourceHeads().some((head) => {
|
|
827
|
+
const sour = get(head, "SOUR.value");
|
|
828
|
+
return !!sour?.toLowerCase()?.startsWith(prefix);
|
|
829
|
+
});
|
|
830
|
+
}
|
|
765
831
|
isGenoPro() {
|
|
766
|
-
|
|
767
|
-
const sour = get(head, "SOUR.value");
|
|
768
|
-
return !!sour?.toLowerCase()?.startsWith("genopro");
|
|
832
|
+
return this.sourStartsWith("genopro");
|
|
769
833
|
}
|
|
770
834
|
isAhnenblatt() {
|
|
771
|
-
|
|
772
|
-
const sour = get(head, "SOUR.value");
|
|
773
|
-
return !!sour?.toLowerCase()?.startsWith("ahnenblatt");
|
|
835
|
+
return this.sourStartsWith("ahnenblatt");
|
|
774
836
|
}
|
|
775
837
|
isGeni() {
|
|
776
|
-
|
|
777
|
-
const sour = get(head, "SOUR.value");
|
|
778
|
-
return !!sour?.toLowerCase()?.startsWith("geni");
|
|
838
|
+
return this.sourStartsWith("geni");
|
|
779
839
|
}
|
|
780
840
|
isAncestry() {
|
|
781
|
-
|
|
782
|
-
const sour = get(head, "SOUR.value");
|
|
783
|
-
return !!sour?.toLowerCase()?.startsWith("ancestry");
|
|
841
|
+
return this.sourStartsWith("ancestry");
|
|
784
842
|
}
|
|
785
843
|
isMyHeritage() {
|
|
786
|
-
|
|
787
|
-
const sour = get(head, "SOUR.value");
|
|
788
|
-
return !!sour?.toLowerCase()?.startsWith("myheritage");
|
|
844
|
+
return this.sourStartsWith("myheritage");
|
|
789
845
|
}
|
|
790
846
|
/**
|
|
791
847
|
* Get the source type as a string (for prefixing tree IDs and names)
|
|
@@ -802,22 +858,22 @@ var Common = class _Common {
|
|
|
802
858
|
return void 0;
|
|
803
859
|
}
|
|
804
860
|
isFamilySearch() {
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
861
|
+
return this.getSourceHeads().some((head) => {
|
|
862
|
+
const sourName = get(head, "SOUR.NAME.value");
|
|
863
|
+
return sourName === "FamilySearch API";
|
|
864
|
+
});
|
|
808
865
|
}
|
|
809
866
|
isGNO2GED() {
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
867
|
+
return this.getSourceHeads().some((head) => {
|
|
868
|
+
const sour = get(head, "SOUR.value");
|
|
869
|
+
return sour === "GNO2GED";
|
|
870
|
+
});
|
|
813
871
|
}
|
|
814
872
|
getAncestryTreeId() {
|
|
815
|
-
|
|
816
|
-
return get(this, path) || get(this.getGedcom(), path);
|
|
873
|
+
return this.getFromSourceHeads("SOUR._TREE.RIN.value") || (get(this, "HEAD.SOUR._TREE.RIN.value") || get(this.getGedcom(), "HEAD.SOUR._TREE.RIN.value"));
|
|
817
874
|
}
|
|
818
875
|
getMyHeritageTreeId() {
|
|
819
|
-
|
|
820
|
-
return get(this, path) || get(this.getGedcom(), path);
|
|
876
|
+
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"));
|
|
821
877
|
}
|
|
822
878
|
getTreeId() {
|
|
823
879
|
if (this?.isAncestry()) {
|
|
@@ -851,8 +907,7 @@ var Common = class _Common {
|
|
|
851
907
|
return this.getUniversalTreeId();
|
|
852
908
|
}
|
|
853
909
|
getAncestryTreeName() {
|
|
854
|
-
|
|
855
|
-
return get(this, path) || get(this.getGedcom(), path);
|
|
910
|
+
return this.getFromSourceHeads("SOUR._TREE.value") || (get(this, "HEAD.SOUR._TREE.value") || get(this.getGedcom(), "HEAD.SOUR._TREE.value"));
|
|
856
911
|
}
|
|
857
912
|
getMyHeritageTreeName() {
|
|
858
913
|
const path = "HEAD.FILE.value";
|
|
@@ -862,14 +917,14 @@ var Common = class _Common {
|
|
|
862
917
|
)?.groups?.tree;
|
|
863
918
|
}
|
|
864
919
|
getFamilySearchTreeId() {
|
|
865
|
-
const rin = get(this, "HEAD.SOUR._TREE.RIN.value") || get(this.getGedcom(), "HEAD.SOUR._TREE.RIN.value");
|
|
920
|
+
const rin = this.getFromSourceHeads("SOUR._TREE.RIN.value") || get(this, "HEAD.SOUR._TREE.RIN.value") || get(this.getGedcom(), "HEAD.SOUR._TREE.RIN.value");
|
|
866
921
|
if (rin) {
|
|
867
922
|
return rin;
|
|
868
923
|
}
|
|
869
924
|
return "familysearch";
|
|
870
925
|
}
|
|
871
926
|
getFamilySearchTreeName() {
|
|
872
|
-
const treeName = get(this, "HEAD.SOUR._TREE.value") || get(this.getGedcom(), "HEAD.SOUR._TREE.value");
|
|
927
|
+
const treeName = this.getFromSourceHeads("SOUR._TREE.value") || get(this, "HEAD.SOUR._TREE.value") || get(this.getGedcom(), "HEAD.SOUR._TREE.value");
|
|
873
928
|
if (treeName) {
|
|
874
929
|
return treeName;
|
|
875
930
|
}
|
|
@@ -961,11 +1016,11 @@ var Common = class _Common {
|
|
|
961
1016
|
const cleanName = fileName.replace(/\.ged$/i, "").replace(/_/g, " ");
|
|
962
1017
|
return `${prefix}${cleanName}`;
|
|
963
1018
|
}
|
|
964
|
-
const sourName = get(this, "HEAD.SOUR.NAME.value") || get(this.getGedcom(), "HEAD.SOUR.NAME.value");
|
|
1019
|
+
const sourName = this.getFromSourceHeads("SOUR.NAME.value") || get(this, "HEAD.SOUR.NAME.value") || get(this.getGedcom(), "HEAD.SOUR.NAME.value");
|
|
965
1020
|
if (sourName) {
|
|
966
1021
|
return `${prefix}${sourName}`;
|
|
967
1022
|
}
|
|
968
|
-
const sourValue = get(this, "HEAD.SOUR.value") || get(this.getGedcom(), "HEAD.SOUR.value");
|
|
1023
|
+
const sourValue = this.getFromSourceHeads("SOUR.value") || get(this, "HEAD.SOUR.value") || get(this.getGedcom(), "HEAD.SOUR.value");
|
|
969
1024
|
if (sourValue) {
|
|
970
1025
|
return `${prefix}${sourValue}`;
|
|
971
1026
|
}
|
|
@@ -1031,7 +1086,7 @@ var isOnlyMainProp = (key) => {
|
|
|
1031
1086
|
};
|
|
1032
1087
|
var isValidKey = (common, key) => {
|
|
1033
1088
|
const prop = get(common, key);
|
|
1034
|
-
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);
|
|
1089
|
+
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);
|
|
1035
1090
|
};
|
|
1036
1091
|
var getValidKeys = (common) => {
|
|
1037
1092
|
return Object.keys(common).filter((key) => {
|
|
@@ -1066,6 +1121,178 @@ var idGetter = (id) => {
|
|
|
1066
1121
|
return newId;
|
|
1067
1122
|
};
|
|
1068
1123
|
|
|
1124
|
+
// src/utils/family-edit.ts
|
|
1125
|
+
var PEDIGREE_VALUES = [
|
|
1126
|
+
"birth" /* BIRTH */,
|
|
1127
|
+
"adopted" /* ADOPTED */,
|
|
1128
|
+
"foster" /* FOSTER */,
|
|
1129
|
+
"step" /* STEP */,
|
|
1130
|
+
"sealing" /* SEALING */
|
|
1131
|
+
];
|
|
1132
|
+
var toGedcomPedigree = (value) => {
|
|
1133
|
+
const normalized = String(value || "birth" /* BIRTH */).toLowerCase();
|
|
1134
|
+
if (normalized === "biological" /* BIOLOGICAL */ || normalized === "birth" /* BIRTH */) {
|
|
1135
|
+
return "birth" /* BIRTH */;
|
|
1136
|
+
}
|
|
1137
|
+
const match = PEDIGREE_VALUES.find((item) => item === normalized);
|
|
1138
|
+
return match ?? "birth" /* BIRTH */;
|
|
1139
|
+
};
|
|
1140
|
+
var pointerIds = (tag) => {
|
|
1141
|
+
if (!tag) {
|
|
1142
|
+
return [];
|
|
1143
|
+
}
|
|
1144
|
+
if (tag instanceof List) {
|
|
1145
|
+
return tag.values().map((item) => item?.toValue?.()).filter((value2) => !!value2);
|
|
1146
|
+
}
|
|
1147
|
+
const value = tag.toValue?.();
|
|
1148
|
+
return value ? [String(value)] : [];
|
|
1149
|
+
};
|
|
1150
|
+
var firstPointerId = (tag) => pointerIds(tag)[0];
|
|
1151
|
+
var makePointer = (gedcom, parent, value, refType) => {
|
|
1152
|
+
const pointer = createCommon(gedcom, void 0, parent);
|
|
1153
|
+
pointer.value = value;
|
|
1154
|
+
pointer.refType = refType;
|
|
1155
|
+
return pointer;
|
|
1156
|
+
};
|
|
1157
|
+
var nextRecordId = (ids, prefix) => {
|
|
1158
|
+
let max = 0;
|
|
1159
|
+
ids.forEach((id) => {
|
|
1160
|
+
const match = String(id).match(/(\d+)/);
|
|
1161
|
+
const n = match ? Number.parseInt(match[1], 10) : 0;
|
|
1162
|
+
if (n > max) {
|
|
1163
|
+
max = n;
|
|
1164
|
+
}
|
|
1165
|
+
});
|
|
1166
|
+
return `@${prefix}${max + 1}@`;
|
|
1167
|
+
};
|
|
1168
|
+
var familyHasParent = (fam, indiId) => pointerIds(fam.get("HUSB")).includes(indiId) || pointerIds(fam.get("WIFE")).includes(indiId);
|
|
1169
|
+
var familyHasChild = (fam, indiId) => pointerIds(fam.get("CHIL")).includes(indiId);
|
|
1170
|
+
var spouseTagFor = (indi, fam) => {
|
|
1171
|
+
const husbId = firstPointerId(fam.get("HUSB"));
|
|
1172
|
+
const wifeId = firstPointerId(fam.get("WIFE"));
|
|
1173
|
+
if (husbId === indi.id) {
|
|
1174
|
+
return "HUSB";
|
|
1175
|
+
}
|
|
1176
|
+
if (wifeId === indi.id) {
|
|
1177
|
+
return "WIFE";
|
|
1178
|
+
}
|
|
1179
|
+
if (indi.isFemale()) {
|
|
1180
|
+
return wifeId && wifeId !== indi.id ? "HUSB" : "WIFE";
|
|
1181
|
+
}
|
|
1182
|
+
if (indi.isMale()) {
|
|
1183
|
+
return husbId && husbId !== indi.id ? "WIFE" : "HUSB";
|
|
1184
|
+
}
|
|
1185
|
+
return husbId ? "WIFE" : "HUSB";
|
|
1186
|
+
};
|
|
1187
|
+
var canAttachAsSpouse = (fam, indi) => {
|
|
1188
|
+
if (!indi.id) {
|
|
1189
|
+
return false;
|
|
1190
|
+
}
|
|
1191
|
+
if (familyHasParent(fam, indi.id)) {
|
|
1192
|
+
return true;
|
|
1193
|
+
}
|
|
1194
|
+
const tag = spouseTagFor(indi, fam);
|
|
1195
|
+
const occupied = firstPointerId(fam.get(tag));
|
|
1196
|
+
return !occupied || occupied === indi.id;
|
|
1197
|
+
};
|
|
1198
|
+
var pointerByValue = (tag, id) => {
|
|
1199
|
+
if (!tag) {
|
|
1200
|
+
return void 0;
|
|
1201
|
+
}
|
|
1202
|
+
const fromValues = tag.toValueList?.().item(id);
|
|
1203
|
+
if (fromValues) {
|
|
1204
|
+
return fromValues;
|
|
1205
|
+
}
|
|
1206
|
+
return tag.toList()?.values().find((item) => item?.toValue?.() === id);
|
|
1207
|
+
};
|
|
1208
|
+
var setChildPedigree = (fam, child, pedigree, parent) => {
|
|
1209
|
+
if (!fam.id || !child.id) {
|
|
1210
|
+
return;
|
|
1211
|
+
}
|
|
1212
|
+
const pedi = toGedcomPedigree(pedigree);
|
|
1213
|
+
const famc = pointerByValue(child.get("FAMC"), fam.id);
|
|
1214
|
+
if (famc) {
|
|
1215
|
+
famc.set("PEDI", pedi);
|
|
1216
|
+
}
|
|
1217
|
+
const chil = pointerByValue(fam.get("CHIL"), child.id);
|
|
1218
|
+
if (!chil) {
|
|
1219
|
+
return;
|
|
1220
|
+
}
|
|
1221
|
+
const setFather = !parent || parent.isMale() || parent.isUnknownSex();
|
|
1222
|
+
const setMother = !parent || parent.isFemale() || parent.isUnknownSex();
|
|
1223
|
+
if (setFather) {
|
|
1224
|
+
chil.set("_FREL", pedi);
|
|
1225
|
+
}
|
|
1226
|
+
if (setMother) {
|
|
1227
|
+
chil.set("_MREL", pedi);
|
|
1228
|
+
}
|
|
1229
|
+
};
|
|
1230
|
+
var attachSpouseToFamily = (fam, indi) => {
|
|
1231
|
+
const gedcom = fam.getGedcom() ?? indi.getGedcom();
|
|
1232
|
+
if (!indi.id || !fam.id || !gedcom) {
|
|
1233
|
+
return false;
|
|
1234
|
+
}
|
|
1235
|
+
if (!canAttachAsSpouse(fam, indi)) {
|
|
1236
|
+
return false;
|
|
1237
|
+
}
|
|
1238
|
+
const tag = spouseTagFor(indi, fam);
|
|
1239
|
+
if (firstPointerId(fam.get(tag)) !== indi.id) {
|
|
1240
|
+
fam.set(tag, makePointer(gedcom, fam, indi.id, "INDI"));
|
|
1241
|
+
}
|
|
1242
|
+
indi.assign("FAMS", makePointer(gedcom, indi, fam.id, "FAM"), true);
|
|
1243
|
+
return true;
|
|
1244
|
+
};
|
|
1245
|
+
var attachChildToFamily = (fam, child, pedigree, parent) => {
|
|
1246
|
+
const gedcom = fam.getGedcom() ?? child.getGedcom();
|
|
1247
|
+
if (!child.id || !fam.id || !gedcom) {
|
|
1248
|
+
return false;
|
|
1249
|
+
}
|
|
1250
|
+
if (!familyHasChild(fam, child.id)) {
|
|
1251
|
+
fam.assign("CHIL", makePointer(gedcom, fam, child.id, "INDI"), true);
|
|
1252
|
+
}
|
|
1253
|
+
const existingFamc = pointerByValue(child.get("FAMC"), fam.id);
|
|
1254
|
+
if (!existingFamc) {
|
|
1255
|
+
child.assign("FAMC", makePointer(gedcom, child, fam.id, "FAM"), true);
|
|
1256
|
+
}
|
|
1257
|
+
setChildPedigree(fam, child, pedigree, parent);
|
|
1258
|
+
return true;
|
|
1259
|
+
};
|
|
1260
|
+
var findReusableParentChildFamily = (parent, child) => {
|
|
1261
|
+
if (!parent.id || !child.id) {
|
|
1262
|
+
return void 0;
|
|
1263
|
+
}
|
|
1264
|
+
let reusableFamc;
|
|
1265
|
+
let already = false;
|
|
1266
|
+
child.getFamilies("FAMC")?.forEach((fam) => {
|
|
1267
|
+
if (!fam) {
|
|
1268
|
+
return;
|
|
1269
|
+
}
|
|
1270
|
+
if (familyHasParent(fam, parent.id) && familyHasChild(fam, child.id)) {
|
|
1271
|
+
already = true;
|
|
1272
|
+
return;
|
|
1273
|
+
}
|
|
1274
|
+
if (!reusableFamc && canAttachAsSpouse(fam, parent)) {
|
|
1275
|
+
reusableFamc = fam;
|
|
1276
|
+
}
|
|
1277
|
+
});
|
|
1278
|
+
if (already) {
|
|
1279
|
+
return "already";
|
|
1280
|
+
}
|
|
1281
|
+
if (reusableFamc) {
|
|
1282
|
+
return reusableFamc;
|
|
1283
|
+
}
|
|
1284
|
+
const parentFams = [];
|
|
1285
|
+
parent.getFamilies("FAMS")?.forEach((fam) => {
|
|
1286
|
+
if (fam) {
|
|
1287
|
+
parentFams.push(fam);
|
|
1288
|
+
}
|
|
1289
|
+
});
|
|
1290
|
+
if (parentFams.length === 1) {
|
|
1291
|
+
return parentFams[0];
|
|
1292
|
+
}
|
|
1293
|
+
return void 0;
|
|
1294
|
+
};
|
|
1295
|
+
|
|
1069
1296
|
// src/factories/cache-factory.ts
|
|
1070
1297
|
var defaultCacheFactory = () => {
|
|
1071
1298
|
let cache = null;
|
|
@@ -1139,131 +1366,322 @@ var PARTNER = {
|
|
|
1139
1366
|
var SPOUSE = {
|
|
1140
1367
|
PART: "spouse" /* SPOUSE */
|
|
1141
1368
|
};
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
if (treeId && sanitizedName) {
|
|
1150
|
-
return `${treeId}_${sanitizedName}`;
|
|
1151
|
-
} else if (treeId) {
|
|
1152
|
-
return treeId;
|
|
1153
|
-
} else if (sanitizedName) {
|
|
1154
|
-
return sanitizedName;
|
|
1155
|
-
}
|
|
1156
|
-
return `gedcom_${gedcom.refcount}`;
|
|
1157
|
-
};
|
|
1158
|
-
var caches = {
|
|
1159
|
-
pathCache: {},
|
|
1160
|
-
relativesOnDegreeCache: {},
|
|
1161
|
-
relativesOnLevelCache: {},
|
|
1162
|
-
profilePictureCache: {}
|
|
1369
|
+
|
|
1370
|
+
// src/utils/get-family-with.ts
|
|
1371
|
+
var getFamilyWith = (person1, person2, famType = "FAMS") => {
|
|
1372
|
+
return person1?.get(famType)?.toValueList().find((fam) => {
|
|
1373
|
+
const family = fam;
|
|
1374
|
+
return famType === "FAMC" || family?.HUSB?.value === person2 || family?.WIFE?.value === person2;
|
|
1375
|
+
});
|
|
1163
1376
|
};
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
relativesOnDegreeCache: getInstance("ftv", "Main", "path", true),
|
|
1176
|
-
relativesOnLevelCache: getInstance(
|
|
1177
|
-
"ftv",
|
|
1178
|
-
"Main",
|
|
1179
|
-
"path",
|
|
1180
|
-
true
|
|
1181
|
-
),
|
|
1182
|
-
profilePictureCache: getInstance(
|
|
1183
|
-
"ftv",
|
|
1184
|
-
"Main",
|
|
1185
|
-
"images",
|
|
1186
|
-
false
|
|
1187
|
-
)
|
|
1188
|
-
};
|
|
1377
|
+
|
|
1378
|
+
// src/constants/orders.ts
|
|
1379
|
+
var BIRTH_ASC = {
|
|
1380
|
+
"BIRT.DATE": {
|
|
1381
|
+
direction: "ASC",
|
|
1382
|
+
getter: (value, raw) => {
|
|
1383
|
+
if (isCommonDate(raw) && raw.rawValue) {
|
|
1384
|
+
return raw.rawValue.getTime();
|
|
1385
|
+
}
|
|
1386
|
+
return new Date(value).getTime();
|
|
1387
|
+
}
|
|
1189
1388
|
}
|
|
1190
|
-
return cacheDbs;
|
|
1191
1389
|
};
|
|
1192
|
-
var
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
}, 50),
|
|
1201
|
-
relativesOnLevelCache: debounce((value) => {
|
|
1202
|
-
if (value) {
|
|
1203
|
-
getCacheDbs().relativesOnLevelCache.setItem(value);
|
|
1204
|
-
}
|
|
1205
|
-
}, 50),
|
|
1206
|
-
relativesOnDegreeCache: debounce((value) => {
|
|
1207
|
-
if (value) {
|
|
1208
|
-
getCacheDbs().relativesOnDegreeCache.setItem(value);
|
|
1209
|
-
}
|
|
1210
|
-
}, 50),
|
|
1211
|
-
// profilePictureCache IS persisted to IndexedDB
|
|
1212
|
-
profilePictureCache: debounce((value) => {
|
|
1213
|
-
if (value) {
|
|
1214
|
-
getCacheDbs().profilePictureCache.setItem(value);
|
|
1390
|
+
var BIRTH_DESC = {
|
|
1391
|
+
"BIRT.DATE": {
|
|
1392
|
+
direction: "DESC",
|
|
1393
|
+
getter: (value, raw) => {
|
|
1394
|
+
if (isCommonDate(raw) && raw.rawValue) {
|
|
1395
|
+
return raw.rawValue.getTime();
|
|
1396
|
+
}
|
|
1397
|
+
return new Date(value).getTime();
|
|
1215
1398
|
}
|
|
1216
|
-
}, 100)
|
|
1217
|
-
};
|
|
1218
|
-
var relativesCache = (cacheKey) => (gedcom, key, subKey, value) => {
|
|
1219
|
-
const gedcomId = getGedcomId(gedcom);
|
|
1220
|
-
const fullKey = `${gedcomId}:${key}`;
|
|
1221
|
-
const cache = caches[cacheKey];
|
|
1222
|
-
if (!cache) {
|
|
1223
|
-
caches[cacheKey] = {};
|
|
1224
1399
|
}
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1400
|
+
};
|
|
1401
|
+
var DEATH_ASC = {
|
|
1402
|
+
"DEAT.DATE": {
|
|
1403
|
+
direction: "ASC",
|
|
1404
|
+
getter: (value, raw) => {
|
|
1405
|
+
if (isCommonDate(raw) && raw.rawValue) {
|
|
1406
|
+
return raw.rawValue.getTime();
|
|
1407
|
+
}
|
|
1408
|
+
return new Date(value).getTime();
|
|
1229
1409
|
}
|
|
1230
|
-
typedCache2[fullKey][subKey] = value;
|
|
1231
|
-
return typedCache2[fullKey][subKey];
|
|
1232
1410
|
}
|
|
1233
|
-
const typedCache = caches[cacheKey];
|
|
1234
|
-
return typedCache?.[fullKey]?.[subKey];
|
|
1235
1411
|
};
|
|
1236
|
-
var
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1412
|
+
var DEATH_DESC = {
|
|
1413
|
+
"DEAT.DATE": {
|
|
1414
|
+
direction: "DESC",
|
|
1415
|
+
getter: (value, raw) => {
|
|
1416
|
+
if (isCommonDate(raw) && raw.rawValue) {
|
|
1417
|
+
return raw.rawValue.getTime();
|
|
1418
|
+
}
|
|
1419
|
+
return new Date(value).getTime();
|
|
1420
|
+
}
|
|
1245
1421
|
}
|
|
1246
|
-
return caches.pathCache?.[fullKey];
|
|
1247
1422
|
};
|
|
1248
|
-
var
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
return caches.profilePictureCache[fullKey];
|
|
1423
|
+
var DATE_ASC = {
|
|
1424
|
+
DATE: {
|
|
1425
|
+
direction: "ASC",
|
|
1426
|
+
getter: (value, raw) => {
|
|
1427
|
+
if (isCommonDate(raw) && raw.rawValue) {
|
|
1428
|
+
return raw.rawValue.getTime();
|
|
1429
|
+
}
|
|
1430
|
+
return new Date(value).getTime();
|
|
1431
|
+
}
|
|
1258
1432
|
}
|
|
1259
|
-
const cached = caches.profilePictureCache?.[fullKey];
|
|
1260
|
-
return cached;
|
|
1261
1433
|
};
|
|
1262
|
-
var
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1434
|
+
var chars = [
|
|
1435
|
+
"a",
|
|
1436
|
+
"\xE0",
|
|
1437
|
+
"\xE1",
|
|
1438
|
+
"\xE2",
|
|
1439
|
+
"\xE4",
|
|
1440
|
+
"\xE6",
|
|
1441
|
+
"\xE3",
|
|
1442
|
+
"\xE5",
|
|
1443
|
+
"\u0101",
|
|
1444
|
+
"b",
|
|
1445
|
+
"c",
|
|
1446
|
+
"\xE7",
|
|
1447
|
+
"\u0107",
|
|
1448
|
+
"\u010D",
|
|
1449
|
+
"cs",
|
|
1450
|
+
"d",
|
|
1451
|
+
"dz",
|
|
1452
|
+
"dzs",
|
|
1453
|
+
"e",
|
|
1454
|
+
"\xE8",
|
|
1455
|
+
"\xE9",
|
|
1456
|
+
"\xEA",
|
|
1457
|
+
"\xEB",
|
|
1458
|
+
"\u0113",
|
|
1459
|
+
"\u0117",
|
|
1460
|
+
"\u0119",
|
|
1461
|
+
"f",
|
|
1462
|
+
"g",
|
|
1463
|
+
"gy",
|
|
1464
|
+
"h",
|
|
1465
|
+
"i",
|
|
1466
|
+
"\xEE",
|
|
1467
|
+
"\xEF",
|
|
1468
|
+
"\xED",
|
|
1469
|
+
"\u012B",
|
|
1470
|
+
"\u012F",
|
|
1471
|
+
"\xEC",
|
|
1472
|
+
"j",
|
|
1473
|
+
"k",
|
|
1474
|
+
"l",
|
|
1475
|
+
"\u0142",
|
|
1476
|
+
"ly",
|
|
1477
|
+
"m",
|
|
1478
|
+
"n",
|
|
1479
|
+
"\xF1",
|
|
1480
|
+
"\u0144",
|
|
1481
|
+
"ny",
|
|
1482
|
+
"o",
|
|
1483
|
+
"\xF3",
|
|
1484
|
+
"\xF6",
|
|
1485
|
+
"\u0151",
|
|
1486
|
+
"\xF4",
|
|
1487
|
+
"\xF2",
|
|
1488
|
+
"\xF5",
|
|
1489
|
+
"\u0153",
|
|
1490
|
+
"\xF8",
|
|
1491
|
+
"\u014D",
|
|
1492
|
+
"p",
|
|
1493
|
+
"q",
|
|
1494
|
+
"r",
|
|
1495
|
+
"s",
|
|
1496
|
+
"\u015B",
|
|
1497
|
+
"\u0161",
|
|
1498
|
+
"\xDF",
|
|
1499
|
+
"sz",
|
|
1500
|
+
"t",
|
|
1501
|
+
"ty",
|
|
1502
|
+
"u",
|
|
1503
|
+
"\xFA",
|
|
1504
|
+
"\xFC",
|
|
1505
|
+
"\u0171",
|
|
1506
|
+
"\xFB",
|
|
1507
|
+
"\xF9",
|
|
1508
|
+
"\u016B",
|
|
1509
|
+
"v",
|
|
1510
|
+
"w",
|
|
1511
|
+
"x",
|
|
1512
|
+
"y",
|
|
1513
|
+
"z",
|
|
1514
|
+
"zs"
|
|
1515
|
+
];
|
|
1516
|
+
chars.reduce((acc, curr, idx) => {
|
|
1517
|
+
acc[curr] = idx;
|
|
1518
|
+
return acc;
|
|
1519
|
+
}, {});
|
|
1520
|
+
var getBirthAsc = (itemA, _keyA, itemB, _keyB) => {
|
|
1521
|
+
const birthA = itemA?.BIRT?.index(0);
|
|
1522
|
+
const birthB = itemB?.BIRT?.index(0);
|
|
1523
|
+
const valueA = birthA?.DATE?.rawValue;
|
|
1524
|
+
const valueB = birthB?.DATE?.rawValue;
|
|
1525
|
+
if (valueA?.getTime() === valueB?.getTime()) {
|
|
1526
|
+
return 0;
|
|
1527
|
+
}
|
|
1528
|
+
if (!valueA || valueB && valueA > valueB) {
|
|
1529
|
+
return 1;
|
|
1530
|
+
}
|
|
1531
|
+
return -1;
|
|
1532
|
+
};
|
|
1533
|
+
var getMarriageAsc = (person, famType = "FAMS") => (itemA, _keyA, itemB, _keyB) => {
|
|
1534
|
+
if (!person && famType === "FAMS") {
|
|
1535
|
+
return 0;
|
|
1536
|
+
}
|
|
1537
|
+
const familyA = getFamilyWith(itemA, person);
|
|
1538
|
+
const familyB = getFamilyWith(itemB, person);
|
|
1539
|
+
const marriageA = familyA?.MARR?.DATE?.rawValue;
|
|
1540
|
+
const marriageB = familyB?.MARR?.DATE?.rawValue;
|
|
1541
|
+
if (marriageA?.getTime() === marriageB?.getTime()) {
|
|
1542
|
+
return 0;
|
|
1543
|
+
}
|
|
1544
|
+
if (!marriageA || marriageB && marriageA > marriageB) {
|
|
1545
|
+
return 1;
|
|
1546
|
+
}
|
|
1547
|
+
return -1;
|
|
1548
|
+
};
|
|
1549
|
+
var getMarriageAscAndChildBirth = (person) => (itemA, keyA, itemB, keyB) => {
|
|
1550
|
+
const marriageSort = getMarriageAsc(person)(itemA, keyA, itemB, keyB);
|
|
1551
|
+
if (marriageSort !== 0) {
|
|
1552
|
+
return marriageSort;
|
|
1553
|
+
}
|
|
1554
|
+
const familyA = getFamilyWith(itemA, person);
|
|
1555
|
+
const familyB = getFamilyWith(itemB, person);
|
|
1556
|
+
const childA = familyA?.getChildren().orderBy(BIRTH_ASC).index(0);
|
|
1557
|
+
const childB = familyB?.getChildren().orderBy(BIRTH_ASC).index(0);
|
|
1558
|
+
return getBirthAsc(childA, keyA, childB);
|
|
1559
|
+
};
|
|
1560
|
+
var getGedcomId = (gedcom) => {
|
|
1561
|
+
if (!gedcom) {
|
|
1562
|
+
return "unknown";
|
|
1563
|
+
}
|
|
1564
|
+
const treeId = gedcom.getTreeId?.() || "";
|
|
1565
|
+
const treeName = gedcom.getTreeName?.() || "";
|
|
1566
|
+
const sanitizedName = treeName.toLowerCase().replace(/[^a-z0-9]+/g, "_").replace(/^_+|_+$/g, "");
|
|
1567
|
+
if (treeId && sanitizedName) {
|
|
1568
|
+
return `${treeId}_${sanitizedName}`;
|
|
1569
|
+
} else if (treeId) {
|
|
1570
|
+
return treeId;
|
|
1571
|
+
} else if (sanitizedName) {
|
|
1572
|
+
return sanitizedName;
|
|
1573
|
+
}
|
|
1574
|
+
return `gedcom_${gedcom.refcount}`;
|
|
1575
|
+
};
|
|
1576
|
+
var caches = {
|
|
1577
|
+
pathCache: {},
|
|
1578
|
+
relativesOnDegreeCache: {},
|
|
1579
|
+
relativesOnLevelCache: {},
|
|
1580
|
+
profilePictureCache: {}
|
|
1581
|
+
};
|
|
1582
|
+
var cacheDbs;
|
|
1583
|
+
var getCacheDbs = () => {
|
|
1584
|
+
if (!cacheDbs) {
|
|
1585
|
+
const getInstance = getCacheManagerFactory();
|
|
1586
|
+
cacheDbs = {
|
|
1587
|
+
pathCache: getInstance(
|
|
1588
|
+
"ftv",
|
|
1589
|
+
"Main",
|
|
1590
|
+
"path",
|
|
1591
|
+
true
|
|
1592
|
+
),
|
|
1593
|
+
relativesOnDegreeCache: getInstance("ftv", "Main", "path", true),
|
|
1594
|
+
relativesOnLevelCache: getInstance(
|
|
1595
|
+
"ftv",
|
|
1596
|
+
"Main",
|
|
1597
|
+
"path",
|
|
1598
|
+
true
|
|
1599
|
+
),
|
|
1600
|
+
profilePictureCache: getInstance(
|
|
1601
|
+
"ftv",
|
|
1602
|
+
"Main",
|
|
1603
|
+
"images",
|
|
1604
|
+
false
|
|
1605
|
+
)
|
|
1606
|
+
};
|
|
1607
|
+
}
|
|
1608
|
+
return cacheDbs;
|
|
1609
|
+
};
|
|
1610
|
+
var storeCache = {
|
|
1611
|
+
// NOTE: pathCache, relativesOnLevelCache, and relativesOnDegreeCache are intentionally
|
|
1612
|
+
// kept in memory only. These debounced functions exist to satisfy the type system
|
|
1613
|
+
// but are never called.
|
|
1614
|
+
pathCache: debounce((value) => {
|
|
1615
|
+
if (value) {
|
|
1616
|
+
getCacheDbs().pathCache.setItem(value);
|
|
1617
|
+
}
|
|
1618
|
+
}, 50),
|
|
1619
|
+
relativesOnLevelCache: debounce((value) => {
|
|
1620
|
+
if (value) {
|
|
1621
|
+
getCacheDbs().relativesOnLevelCache.setItem(value);
|
|
1622
|
+
}
|
|
1623
|
+
}, 50),
|
|
1624
|
+
relativesOnDegreeCache: debounce((value) => {
|
|
1625
|
+
if (value) {
|
|
1626
|
+
getCacheDbs().relativesOnDegreeCache.setItem(value);
|
|
1627
|
+
}
|
|
1628
|
+
}, 50),
|
|
1629
|
+
// profilePictureCache IS persisted to IndexedDB
|
|
1630
|
+
profilePictureCache: debounce((value) => {
|
|
1631
|
+
if (value) {
|
|
1632
|
+
getCacheDbs().profilePictureCache.setItem(value);
|
|
1633
|
+
}
|
|
1634
|
+
}, 100)
|
|
1635
|
+
};
|
|
1636
|
+
var relativesCache = (cacheKey) => (gedcom, key, subKey, value) => {
|
|
1637
|
+
const gedcomId = getGedcomId(gedcom);
|
|
1638
|
+
const fullKey = `${gedcomId}:${key}`;
|
|
1639
|
+
const cache = caches[cacheKey];
|
|
1640
|
+
if (!cache) {
|
|
1641
|
+
caches[cacheKey] = {};
|
|
1642
|
+
}
|
|
1643
|
+
if (value) {
|
|
1644
|
+
const typedCache2 = caches[cacheKey];
|
|
1645
|
+
if (!typedCache2[fullKey]) {
|
|
1646
|
+
typedCache2[fullKey] = {};
|
|
1647
|
+
}
|
|
1648
|
+
typedCache2[fullKey][subKey] = value;
|
|
1649
|
+
return typedCache2[fullKey][subKey];
|
|
1650
|
+
}
|
|
1651
|
+
const typedCache = caches[cacheKey];
|
|
1652
|
+
return typedCache?.[fullKey]?.[subKey];
|
|
1653
|
+
};
|
|
1654
|
+
var pathCache = (gedcom, key, value) => {
|
|
1655
|
+
const gedcomId = getGedcomId(gedcom);
|
|
1656
|
+
const fullKey = `${gedcomId}:${key}`;
|
|
1657
|
+
if (!caches.pathCache) {
|
|
1658
|
+
caches.pathCache = {};
|
|
1659
|
+
}
|
|
1660
|
+
if (value && caches.pathCache) {
|
|
1661
|
+
caches.pathCache[fullKey] = value;
|
|
1662
|
+
return caches.pathCache[fullKey];
|
|
1663
|
+
}
|
|
1664
|
+
return caches.pathCache?.[fullKey];
|
|
1665
|
+
};
|
|
1666
|
+
var profilePictureCache = (gedcom, key, value) => {
|
|
1667
|
+
const gedcomId = getGedcomId(gedcom);
|
|
1668
|
+
const fullKey = `${gedcomId}:${key}`;
|
|
1669
|
+
if (!caches.profilePictureCache) {
|
|
1670
|
+
caches.profilePictureCache = {};
|
|
1671
|
+
}
|
|
1672
|
+
if (value && caches.profilePictureCache) {
|
|
1673
|
+
caches.profilePictureCache[fullKey] = value;
|
|
1674
|
+
storeCache.profilePictureCache(caches.profilePictureCache);
|
|
1675
|
+
return caches.profilePictureCache[fullKey];
|
|
1676
|
+
}
|
|
1677
|
+
const cached = caches.profilePictureCache?.[fullKey];
|
|
1678
|
+
return cached;
|
|
1679
|
+
};
|
|
1680
|
+
var isNonBiologicalPath = (path) => path.some(
|
|
1681
|
+
(item) => item.relation && item.relation !== "biological" /* BIOLOGICAL */
|
|
1682
|
+
);
|
|
1683
|
+
var invertHop = (kinship) => {
|
|
1684
|
+
if (kinship === "parent") {
|
|
1267
1685
|
return "child";
|
|
1268
1686
|
}
|
|
1269
1687
|
if (kinship === "child") {
|
|
@@ -1649,16 +2067,58 @@ var getPlaces = (common, type = ["ALL" /* All */], maxLevel = 1, level = 0, main
|
|
|
1649
2067
|
});
|
|
1650
2068
|
return places;
|
|
1651
2069
|
};
|
|
1652
|
-
var implemented = (type, ...args) => {
|
|
1653
|
-
};
|
|
1654
2070
|
|
|
1655
|
-
// src/utils/media
|
|
1656
|
-
var
|
|
1657
|
-
|
|
1658
|
-
|
|
1659
|
-
|
|
2071
|
+
// src/utils/local-media.ts
|
|
2072
|
+
var localMediaResolver;
|
|
2073
|
+
var isRemoteOrEmbeddedMediaUrl = (path) => {
|
|
2074
|
+
if (!path) {
|
|
2075
|
+
return false;
|
|
2076
|
+
}
|
|
2077
|
+
return path.startsWith("data:") || path.startsWith("blob:") || /^https?:\/\//i.test(path);
|
|
2078
|
+
};
|
|
2079
|
+
var resolveLocalMediaUrl = async (path) => {
|
|
2080
|
+
if (!path) {
|
|
2081
|
+
return void 0;
|
|
2082
|
+
}
|
|
2083
|
+
if (isRemoteOrEmbeddedMediaUrl(path)) {
|
|
2084
|
+
return path;
|
|
2085
|
+
}
|
|
2086
|
+
const resolved = await localMediaResolver?.(path);
|
|
2087
|
+
return resolved;
|
|
2088
|
+
};
|
|
2089
|
+
var implemented = (type, ...args) => {
|
|
2090
|
+
};
|
|
2091
|
+
|
|
2092
|
+
// src/utils/media-utils.ts
|
|
2093
|
+
var getFileExtension = (filename) => {
|
|
2094
|
+
if (!filename) {
|
|
2095
|
+
return "";
|
|
2096
|
+
}
|
|
2097
|
+
if (filename.startsWith("data:")) {
|
|
2098
|
+
const mime = filename.slice(5).split(";")[0] || "";
|
|
2099
|
+
const subtype = (mime.split("/")[1] || "").toLowerCase();
|
|
2100
|
+
if (subtype === "jpeg") {
|
|
2101
|
+
return "jpg";
|
|
2102
|
+
}
|
|
2103
|
+
return subtype.split("+")[0] || "";
|
|
2104
|
+
}
|
|
2105
|
+
const withoutQuery = filename.split(/[?#]/)[0] || filename;
|
|
2106
|
+
const match = withoutQuery.match(/\.([^.]+)$/);
|
|
2107
|
+
return match ? match[1].toLowerCase() : "";
|
|
2108
|
+
};
|
|
1660
2109
|
var isImageFormat = (format2) => {
|
|
1661
|
-
if (!format2)
|
|
2110
|
+
if (!format2) {
|
|
2111
|
+
return false;
|
|
2112
|
+
}
|
|
2113
|
+
let normalized = format2.toLowerCase().trim();
|
|
2114
|
+
if (normalized.startsWith("data:")) {
|
|
2115
|
+
normalized = getFileExtension(normalized);
|
|
2116
|
+
} else if (normalized.includes("/")) {
|
|
2117
|
+
normalized = normalized.split("/")[1]?.split("+")[0] || "";
|
|
2118
|
+
if (normalized === "jpeg") {
|
|
2119
|
+
normalized = "jpg";
|
|
2120
|
+
}
|
|
2121
|
+
}
|
|
1662
2122
|
const imageFormats = [
|
|
1663
2123
|
"jpg",
|
|
1664
2124
|
"jpeg",
|
|
@@ -1670,178 +2130,731 @@ var isImageFormat = (format2) => {
|
|
|
1670
2130
|
"tiff",
|
|
1671
2131
|
"tif"
|
|
1672
2132
|
];
|
|
1673
|
-
return imageFormats.includes(
|
|
2133
|
+
return imageFormats.includes(normalized);
|
|
1674
2134
|
};
|
|
1675
|
-
|
|
1676
|
-
|
|
1677
|
-
|
|
1678
|
-
|
|
1679
|
-
|
|
1680
|
-
|
|
1681
|
-
|
|
1682
|
-
set value
|
|
1683
|
-
|
|
1684
|
-
|
|
1685
|
-
|
|
1686
|
-
)
|
|
1687
|
-
|
|
1688
|
-
|
|
1689
|
-
|
|
1690
|
-
|
|
1691
|
-
|
|
1692
|
-
|
|
1693
|
-
|
|
1694
|
-
|
|
1695
|
-
|
|
1696
|
-
|
|
1697
|
-
if (nameParts?.suffix?.trim()) {
|
|
1698
|
-
this.NSFX = this.NSFX || createCommon(this._gedcom, void 0, this.main);
|
|
1699
|
-
this.NSFX.value = nameParts.suffix.trim();
|
|
1700
|
-
this.NSFX.isListable = false;
|
|
2135
|
+
var resolveObjeForm = (obje) => {
|
|
2136
|
+
const value = obje?.get?.("FILE.FORM")?.toValue?.() ?? obje?.get?.("FORM")?.toValue?.();
|
|
2137
|
+
return typeof value === "string" && value.trim() ? value.trim() : void 0;
|
|
2138
|
+
};
|
|
2139
|
+
var uniqueItemsCache = /* @__PURE__ */ new WeakMap();
|
|
2140
|
+
var setNestedGroup = (obj, key, value, uniqueCounting = true) => {
|
|
2141
|
+
const parts = Array.isArray(key) ? key : key.split(/,\s*/);
|
|
2142
|
+
set(obj, [...parts, "items"], value);
|
|
2143
|
+
parts.forEach((_, index) => {
|
|
2144
|
+
if (!uniqueCounting) {
|
|
2145
|
+
const key2 = [...parts.toSpliced(index + 1), "length"];
|
|
2146
|
+
const length = get(obj, key2);
|
|
2147
|
+
set(obj, key2, (length ?? 0) + value.length);
|
|
2148
|
+
return;
|
|
2149
|
+
}
|
|
2150
|
+
const pathKey = [...parts.toSpliced(index + 1)];
|
|
2151
|
+
const node = get(obj, pathKey);
|
|
2152
|
+
if (node) {
|
|
2153
|
+
let uniqueItems = uniqueItemsCache.get(node);
|
|
2154
|
+
if (!uniqueItems) {
|
|
2155
|
+
uniqueItems = new Individuals();
|
|
2156
|
+
uniqueItemsCache.set(node, uniqueItems);
|
|
1701
2157
|
}
|
|
2158
|
+
uniqueItems.merge(value);
|
|
2159
|
+
set(obj, [...pathKey, "length"], uniqueItems.length);
|
|
1702
2160
|
}
|
|
1703
|
-
|
|
2161
|
+
});
|
|
2162
|
+
};
|
|
2163
|
+
|
|
2164
|
+
// src/utils/place-parser.ts
|
|
2165
|
+
var getPlaceParts = (place = []) => {
|
|
2166
|
+
const partsString = Array.isArray(place) ? place.filter(Boolean).join(", ") : place;
|
|
2167
|
+
if (!partsString) {
|
|
2168
|
+
return [{}];
|
|
1704
2169
|
}
|
|
1705
|
-
|
|
1706
|
-
|
|
1707
|
-
|
|
1708
|
-
}
|
|
1709
|
-
return this._value;
|
|
2170
|
+
const parts = partsString.split(/,\s*/).map((p) => p.trim()).filter(Boolean);
|
|
2171
|
+
if (parts.length === 0) {
|
|
2172
|
+
return [{}];
|
|
1710
2173
|
}
|
|
1711
|
-
|
|
1712
|
-
|
|
1713
|
-
|
|
2174
|
+
const result = {};
|
|
2175
|
+
if (parts.length === 1) {
|
|
2176
|
+
result.town = parts[0];
|
|
2177
|
+
} else if (parts.length === 2) {
|
|
2178
|
+
result.town = parts[0];
|
|
2179
|
+
result.country = parts[1];
|
|
2180
|
+
} else if (parts.length === 3) {
|
|
2181
|
+
result.town = parts[0];
|
|
2182
|
+
result.county = parts[1];
|
|
2183
|
+
result.country = parts[2];
|
|
2184
|
+
} else {
|
|
2185
|
+
result.leftParts = parts.slice(0, parts.length - 3);
|
|
2186
|
+
result.town = parts[parts.length - 3];
|
|
2187
|
+
result.county = parts[parts.length - 2];
|
|
2188
|
+
result.country = parts[parts.length - 1];
|
|
1714
2189
|
}
|
|
2190
|
+
return [result];
|
|
1715
2191
|
};
|
|
1716
|
-
|
|
1717
|
-
|
|
1718
|
-
|
|
1719
|
-
);
|
|
2192
|
+
|
|
2193
|
+
// src/utils/place-translator.ts
|
|
2194
|
+
var placeTranslator = (place) => {
|
|
2195
|
+
return Array.isArray(place) ? place.join(", ") : place;
|
|
1720
2196
|
};
|
|
1721
2197
|
|
|
1722
|
-
// src/classes/
|
|
1723
|
-
var
|
|
1724
|
-
|
|
1725
|
-
|
|
1726
|
-
"OCCUPATIONS",
|
|
1727
|
-
"RESI",
|
|
1728
|
-
"BAPT",
|
|
1729
|
-
"CHRI",
|
|
1730
|
-
"CHR",
|
|
1731
|
-
"BURI",
|
|
1732
|
-
"EDUC",
|
|
1733
|
-
"GRAD",
|
|
1734
|
-
"DIV",
|
|
1735
|
-
"IMMI",
|
|
1736
|
-
"RELI",
|
|
1737
|
-
"_MILT",
|
|
1738
|
-
"_MILTID",
|
|
1739
|
-
"FACT",
|
|
1740
|
-
"_ORIG"
|
|
1741
|
-
];
|
|
1742
|
-
var DISALLOWED_CUSTOM_FACTS = ["DNA Test", "Newspaper"];
|
|
1743
|
-
var CustomFactRenderers = {
|
|
1744
|
-
AKA: (label, fact, indi) => {
|
|
1745
|
-
const originalNameObj = indi?.NAME;
|
|
1746
|
-
const note = fact.get("NOTE");
|
|
1747
|
-
const factName = note?.toValue();
|
|
1748
|
-
const name = createCommonName(fact.getGedcom(), void 0, indi);
|
|
1749
|
-
const suffix = originalNameObj?.NSFX?.toValue();
|
|
1750
|
-
const surname = originalNameObj?.SURN?.toValue();
|
|
1751
|
-
const givenname = originalNameObj?.GIVN?.toValue();
|
|
1752
|
-
const nameParts = [
|
|
1753
|
-
...givenname?.split(" ").map((s) => ({ name: s, givenname: true })) ?? [],
|
|
1754
|
-
...surname?.split(" ").map((s) => ({ name: s, surname: true })) ?? [],
|
|
1755
|
-
...suffix?.split(" ").map((s) => ({ name: s, suffix: true })) ?? []
|
|
1756
|
-
].filter(Boolean);
|
|
1757
|
-
const factParts = factName?.split(" ");
|
|
1758
|
-
if (nameParts.length === factParts?.length && !(note instanceof CommonName)) {
|
|
1759
|
-
const guessedSuffix = [];
|
|
1760
|
-
const guessedSurname = [];
|
|
1761
|
-
const guessedGivenname = [];
|
|
1762
|
-
factParts.forEach((f, i) => {
|
|
1763
|
-
const namePart = nameParts[i];
|
|
1764
|
-
if (!f) {
|
|
1765
|
-
return;
|
|
1766
|
-
}
|
|
1767
|
-
if (namePart.suffix) {
|
|
1768
|
-
guessedSuffix.push(f);
|
|
1769
|
-
} else if (namePart.givenname) {
|
|
1770
|
-
guessedGivenname.push(f);
|
|
1771
|
-
} else if (namePart.surname) {
|
|
1772
|
-
guessedSurname.push(f);
|
|
1773
|
-
}
|
|
1774
|
-
});
|
|
1775
|
-
const allNamePart = [];
|
|
1776
|
-
if (guessedGivenname.length) {
|
|
1777
|
-
allNamePart.push(guessedGivenname.join(" "));
|
|
1778
|
-
}
|
|
1779
|
-
if (guessedSurname.length) {
|
|
1780
|
-
allNamePart.push(`/${guessedSurname.join(" ")}/`);
|
|
1781
|
-
}
|
|
1782
|
-
if (guessedSuffix.length) {
|
|
1783
|
-
allNamePart.push(guessedSuffix.join(" "));
|
|
1784
|
-
}
|
|
1785
|
-
name.value = allNamePart.join(" ");
|
|
1786
|
-
} else {
|
|
1787
|
-
name.value = factName;
|
|
1788
|
-
}
|
|
1789
|
-
fact.set("NOTE", name);
|
|
1790
|
-
label.value = "AKA";
|
|
1791
|
-
fact.set("_LABEL", label);
|
|
2198
|
+
// src/classes/indis.ts
|
|
2199
|
+
var Individuals = class _Individuals extends List {
|
|
2200
|
+
copy() {
|
|
2201
|
+
return super.copy(_Individuals);
|
|
1792
2202
|
}
|
|
1793
|
-
|
|
1794
|
-
|
|
1795
|
-
var relativesOnDegreeCache = relativesCache("relativesOnDegreeCache");
|
|
1796
|
-
var Indi = class extends Common {
|
|
1797
|
-
toName() {
|
|
1798
|
-
return this.get("NAME")?.toValue();
|
|
2203
|
+
except(item) {
|
|
2204
|
+
return super.except(item, _Individuals);
|
|
1799
2205
|
}
|
|
1800
|
-
|
|
1801
|
-
return
|
|
2206
|
+
filter(filters) {
|
|
2207
|
+
return super.filter(filters, _Individuals);
|
|
1802
2208
|
}
|
|
1803
|
-
|
|
1804
|
-
return
|
|
1805
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
1806
|
-
this.id ? { [this.id]: this } : { ...[this] }
|
|
1807
|
-
);
|
|
2209
|
+
find(filters) {
|
|
2210
|
+
return super.find(filters, _Individuals);
|
|
1808
2211
|
}
|
|
1809
|
-
|
|
1810
|
-
|
|
1811
|
-
|
|
1812
|
-
level,
|
|
1813
|
-
index,
|
|
1814
|
-
showDescendants,
|
|
1815
|
-
offspringSpouses,
|
|
1816
|
-
ancestorSpouses,
|
|
1817
|
-
onlyDescendants,
|
|
1818
|
-
maxLevel,
|
|
1819
|
-
minLevel,
|
|
1820
|
-
drawNonBiologicalAncestors,
|
|
1821
|
-
ancestorSiblings
|
|
1822
|
-
} = props;
|
|
1823
|
-
if (!this.id) {
|
|
1824
|
-
throw new Error("Indi must have an id");
|
|
2212
|
+
unattachedFilter(useUnattached) {
|
|
2213
|
+
if (useUnattached) {
|
|
2214
|
+
return this;
|
|
1825
2215
|
}
|
|
1826
|
-
|
|
1827
|
-
|
|
1828
|
-
|
|
1829
|
-
|
|
2216
|
+
return this.filter((item) => !item.isUnattachedMember());
|
|
2217
|
+
}
|
|
2218
|
+
orderBy(orders) {
|
|
2219
|
+
return super.orderBy(orders, _Individuals);
|
|
2220
|
+
}
|
|
2221
|
+
getFirstEvent() {
|
|
2222
|
+
const firstBirthPerson = this.getFirstBirth();
|
|
2223
|
+
const firstDeathPerson = this.getFirstDeath();
|
|
2224
|
+
const firstBirth = firstBirthPerson?.BIRT?.index(0);
|
|
2225
|
+
const firstDeath = firstDeathPerson?.DEAT?.index(0);
|
|
2226
|
+
if (!firstBirth?.DATE?.rawValue && !firstDeath?.DATE?.rawValue) {
|
|
2227
|
+
return void 0;
|
|
1830
2228
|
}
|
|
1831
|
-
if (
|
|
1832
|
-
return
|
|
2229
|
+
if (!firstBirth?.DATE?.rawValue) {
|
|
2230
|
+
return firstDeathPerson;
|
|
1833
2231
|
}
|
|
1834
|
-
|
|
1835
|
-
|
|
1836
|
-
|
|
1837
|
-
|
|
1838
|
-
|
|
1839
|
-
}
|
|
1840
|
-
|
|
1841
|
-
|
|
1842
|
-
|
|
1843
|
-
|
|
1844
|
-
|
|
2232
|
+
if (!firstDeath?.DATE?.rawValue) {
|
|
2233
|
+
return firstBirthPerson;
|
|
2234
|
+
}
|
|
2235
|
+
if (firstDeath.DATE.rawValue < firstBirth.DATE.rawValue) {
|
|
2236
|
+
return firstDeathPerson;
|
|
2237
|
+
}
|
|
2238
|
+
return firstBirthPerson;
|
|
2239
|
+
}
|
|
2240
|
+
getLastEvent() {
|
|
2241
|
+
const lastDeathPerson = this.getLastDeath();
|
|
2242
|
+
const lastBirthPerson = this.getLastBirth();
|
|
2243
|
+
const lastBirth = lastBirthPerson?.BIRT?.index(0);
|
|
2244
|
+
const lastDeath = lastDeathPerson?.DEAT?.index(0);
|
|
2245
|
+
if (!lastBirth?.DATE?.rawValue && !lastDeath?.DATE?.rawValue) {
|
|
2246
|
+
return void 0;
|
|
2247
|
+
}
|
|
2248
|
+
if (!lastDeath?.DATE?.rawValue) {
|
|
2249
|
+
return lastBirthPerson;
|
|
2250
|
+
}
|
|
2251
|
+
if (!lastBirth?.DATE?.rawValue) {
|
|
2252
|
+
return lastDeathPerson;
|
|
2253
|
+
}
|
|
2254
|
+
if (lastDeath.DATE.rawValue < lastBirth.DATE.rawValue) {
|
|
2255
|
+
return lastBirthPerson;
|
|
2256
|
+
}
|
|
2257
|
+
return lastDeathPerson;
|
|
2258
|
+
}
|
|
2259
|
+
getFirstBirth() {
|
|
2260
|
+
return this.filter((item) => {
|
|
2261
|
+
const birth = item.BIRT?.index(0);
|
|
2262
|
+
if (birth?.DATE?.rawValue?.getTime() === 0) {
|
|
2263
|
+
return true;
|
|
2264
|
+
}
|
|
2265
|
+
return !!birth?.DATE?.rawValue?.getTime();
|
|
2266
|
+
}).orderBy(BIRTH_ASC).index(0);
|
|
2267
|
+
}
|
|
2268
|
+
getLastBirth() {
|
|
2269
|
+
return this.filter((item) => {
|
|
2270
|
+
const birth = item.BIRT?.index(0);
|
|
2271
|
+
if (birth?.DATE?.rawValue?.getTime() === 0) {
|
|
2272
|
+
return true;
|
|
2273
|
+
}
|
|
2274
|
+
return !!birth?.DATE?.rawValue?.getTime();
|
|
2275
|
+
}).orderBy(BIRTH_DESC).index(0);
|
|
2276
|
+
}
|
|
2277
|
+
getFirstDeath() {
|
|
2278
|
+
return this.filter((item) => {
|
|
2279
|
+
const death = item.DEAT?.index(0);
|
|
2280
|
+
if (death?.DATE?.rawValue?.getTime() === 0) {
|
|
2281
|
+
return true;
|
|
2282
|
+
}
|
|
2283
|
+
return !!death?.DATE?.rawValue?.getTime();
|
|
2284
|
+
}).orderBy(DEATH_ASC).index(0);
|
|
2285
|
+
}
|
|
2286
|
+
getLastDeath() {
|
|
2287
|
+
return this.filter((item) => {
|
|
2288
|
+
const death = item.DEAT?.index(0);
|
|
2289
|
+
if (death?.DATE?.rawValue?.getTime() === 0) {
|
|
2290
|
+
return true;
|
|
2291
|
+
}
|
|
2292
|
+
return !!death?.DATE?.rawValue?.getTime();
|
|
2293
|
+
}).orderBy(DEATH_DESC).index(0);
|
|
2294
|
+
}
|
|
2295
|
+
groupBy(group, sort, minOccurance = -1, lessOccuranceLabel) {
|
|
2296
|
+
return super.groupBy(
|
|
2297
|
+
group,
|
|
2298
|
+
sort,
|
|
2299
|
+
minOccurance,
|
|
2300
|
+
lessOccuranceLabel,
|
|
2301
|
+
_Individuals
|
|
2302
|
+
);
|
|
2303
|
+
}
|
|
2304
|
+
groupByFirstLetters(sort = "group", minOccurance = -1, settings) {
|
|
2305
|
+
return this.groupBy(
|
|
2306
|
+
(item) => {
|
|
2307
|
+
const { letter } = nameFormatter(item, settings);
|
|
2308
|
+
return letter.trim() || "Unknown";
|
|
2309
|
+
},
|
|
2310
|
+
sort,
|
|
2311
|
+
minOccurance,
|
|
2312
|
+
"Letters appearing less than 5 times"
|
|
2313
|
+
);
|
|
2314
|
+
}
|
|
2315
|
+
groupBySurnames(sort, minOccurance = -1) {
|
|
2316
|
+
return this.groupBy(
|
|
2317
|
+
"NAME.SURN",
|
|
2318
|
+
sort,
|
|
2319
|
+
minOccurance,
|
|
2320
|
+
"Surnames appearing less than 5 times"
|
|
2321
|
+
);
|
|
2322
|
+
}
|
|
2323
|
+
groupByTimeRanges(range, sort = "group", minOccurance = -1) {
|
|
2324
|
+
return this.groupBy(
|
|
2325
|
+
{
|
|
2326
|
+
["BIRT.DATE.YEAR"]: {
|
|
2327
|
+
getter: (year) => {
|
|
2328
|
+
if (!Number(year)) {
|
|
2329
|
+
return;
|
|
2330
|
+
}
|
|
2331
|
+
if (range === 1 /* Year */) {
|
|
2332
|
+
return `${Math.floor(Number(year) / range) * range}`;
|
|
2333
|
+
}
|
|
2334
|
+
return `${Math.floor(Number(year) / range) * range + 1}-${Math.ceil((Number(year) + 1) / range) * range}`;
|
|
2335
|
+
}
|
|
2336
|
+
}
|
|
2337
|
+
},
|
|
2338
|
+
sort,
|
|
2339
|
+
minOccurance,
|
|
2340
|
+
"Time ranges appearing less than 5 times"
|
|
2341
|
+
);
|
|
2342
|
+
}
|
|
2343
|
+
nestedGroupByPlacesAndTimeRanges(sort, minOccurance = -1, uniqueCounting = true) {
|
|
2344
|
+
const placesWithYear = this.groupBy(
|
|
2345
|
+
(item) => item.getPlaces().map((place) => {
|
|
2346
|
+
const date = place.obj?.get("DATE");
|
|
2347
|
+
if (date?.YEAR) {
|
|
2348
|
+
return `${place.place}, ${date.YEAR}`;
|
|
2349
|
+
}
|
|
2350
|
+
return `${place.place}, Unknown`;
|
|
2351
|
+
}).filter(Boolean),
|
|
2352
|
+
sort,
|
|
2353
|
+
minOccurance,
|
|
2354
|
+
"Places appearing less than 5 times"
|
|
2355
|
+
);
|
|
2356
|
+
return Object.entries(placesWithYear).reduce(
|
|
2357
|
+
(acc, [place, indis]) => {
|
|
2358
|
+
setNestedGroup(acc, place, indis, uniqueCounting);
|
|
2359
|
+
return acc;
|
|
2360
|
+
},
|
|
2361
|
+
{}
|
|
2362
|
+
);
|
|
2363
|
+
}
|
|
2364
|
+
nestedGroupByTimeRangesAndPlaces(sort, minOccurance = -1, uniqueCounting = true) {
|
|
2365
|
+
const placesWithYear = this.groupBy(
|
|
2366
|
+
(item) => item.getPlaces().map((place) => {
|
|
2367
|
+
const date = place.obj?.get("DATE");
|
|
2368
|
+
if (date?.YEAR) {
|
|
2369
|
+
return `${date.YEAR}, ${place.place}`;
|
|
2370
|
+
}
|
|
2371
|
+
return `Unknown, ${place.place}`;
|
|
2372
|
+
}).filter(Boolean),
|
|
2373
|
+
sort,
|
|
2374
|
+
minOccurance,
|
|
2375
|
+
"Places appearing less than 5 times"
|
|
2376
|
+
);
|
|
2377
|
+
return Object.entries(placesWithYear).reduce(
|
|
2378
|
+
(acc, [place, indis]) => {
|
|
2379
|
+
setNestedGroup(acc, place, indis, uniqueCounting);
|
|
2380
|
+
return acc;
|
|
2381
|
+
},
|
|
2382
|
+
{}
|
|
2383
|
+
);
|
|
2384
|
+
}
|
|
2385
|
+
nestedGroupByPlaces(sort, minOccurance = -1, partOrder = "reverse", translate = true, uniqueCounting = true, groupKeyTranslator) {
|
|
2386
|
+
const places = this.groupByPlaces(
|
|
2387
|
+
sort,
|
|
2388
|
+
minOccurance,
|
|
2389
|
+
partOrder,
|
|
2390
|
+
translate,
|
|
2391
|
+
groupKeyTranslator
|
|
2392
|
+
);
|
|
2393
|
+
return Object.entries(places).reduce(
|
|
2394
|
+
(acc, [place, indis]) => {
|
|
2395
|
+
setNestedGroup(acc, place, indis, uniqueCounting);
|
|
2396
|
+
return acc;
|
|
2397
|
+
},
|
|
2398
|
+
{}
|
|
2399
|
+
);
|
|
2400
|
+
}
|
|
2401
|
+
groupByPlaces(sort, minOccurance = -1, partOrder = "reverse", translate = true, groupKeyTranslator) {
|
|
2402
|
+
return this.groupBy(
|
|
2403
|
+
(item) => item.getPlaces().map((place) => {
|
|
2404
|
+
const placeParts = getPlaceParts(place.place || "");
|
|
2405
|
+
const {
|
|
2406
|
+
leftParts = [],
|
|
2407
|
+
town,
|
|
2408
|
+
county,
|
|
2409
|
+
country
|
|
2410
|
+
} = placeParts[0] || {};
|
|
2411
|
+
const normalizedParts = [
|
|
2412
|
+
...leftParts,
|
|
2413
|
+
town,
|
|
2414
|
+
county,
|
|
2415
|
+
country
|
|
2416
|
+
].filter(Boolean);
|
|
2417
|
+
const orderedParts = partOrder === "original" ? normalizedParts : normalizedParts.toReversed();
|
|
2418
|
+
let newPlace = "";
|
|
2419
|
+
if (groupKeyTranslator) {
|
|
2420
|
+
newPlace = groupKeyTranslator(orderedParts);
|
|
2421
|
+
} else if (translate) {
|
|
2422
|
+
{
|
|
2423
|
+
newPlace = placeTranslator(orderedParts);
|
|
2424
|
+
}
|
|
2425
|
+
} else {
|
|
2426
|
+
newPlace = orderedParts.join(", ");
|
|
2427
|
+
}
|
|
2428
|
+
if (!newPlace) {
|
|
2429
|
+
return void 0;
|
|
2430
|
+
}
|
|
2431
|
+
return {
|
|
2432
|
+
marker: place.place,
|
|
2433
|
+
group: newPlace
|
|
2434
|
+
};
|
|
2435
|
+
}).filter(Boolean),
|
|
2436
|
+
sort,
|
|
2437
|
+
minOccurance,
|
|
2438
|
+
"Places appearing less than 5 times"
|
|
2439
|
+
);
|
|
2440
|
+
}
|
|
2441
|
+
getFacts() {
|
|
2442
|
+
const facts = new List();
|
|
2443
|
+
this.values().forEach((indi) => {
|
|
2444
|
+
const indiFacts = indi?.getFacts();
|
|
2445
|
+
if (indi?.id && indiFacts) {
|
|
2446
|
+
facts.merge(indiFacts);
|
|
2447
|
+
}
|
|
2448
|
+
});
|
|
2449
|
+
return facts;
|
|
2450
|
+
}
|
|
2451
|
+
isRelativeOf(type, indi, every = false) {
|
|
2452
|
+
const usedIndi = typeof indi === "string" ? this.index(0)?.getGedcom()?.indi(indi) : indi;
|
|
2453
|
+
let getter;
|
|
2454
|
+
if (type === "sibling") {
|
|
2455
|
+
getter = "getSiblings";
|
|
2456
|
+
}
|
|
2457
|
+
if (type === "parent") {
|
|
2458
|
+
getter = "getParents";
|
|
2459
|
+
}
|
|
2460
|
+
if (type === "child") {
|
|
2461
|
+
getter = "getChildren";
|
|
2462
|
+
}
|
|
2463
|
+
if (type === "spouse") {
|
|
2464
|
+
getter = "getCoParents";
|
|
2465
|
+
}
|
|
2466
|
+
if (type === "parentInLaw") {
|
|
2467
|
+
getter = "getParentsInLaw";
|
|
2468
|
+
}
|
|
2469
|
+
if (type === "childInLaw") {
|
|
2470
|
+
getter = "getChildrenInLaw";
|
|
2471
|
+
}
|
|
2472
|
+
if (!usedIndi || !getter) {
|
|
2473
|
+
return false;
|
|
2474
|
+
}
|
|
2475
|
+
const relatives = usedIndi[getter]();
|
|
2476
|
+
const thisIds = this.keys();
|
|
2477
|
+
if (relatives.length <= 0 || this.length <= 0) {
|
|
2478
|
+
return false;
|
|
2479
|
+
}
|
|
2480
|
+
const filtered = relatives.filter({ id: thisIds });
|
|
2481
|
+
if (every) {
|
|
2482
|
+
return filtered.length === this.length ? filtered.index(0)?.id || true : false;
|
|
2483
|
+
}
|
|
2484
|
+
return filtered.length > 0 ? filtered.index(0)?.id || true : false;
|
|
2485
|
+
}
|
|
2486
|
+
isSiblingOf(indi, every = false) {
|
|
2487
|
+
return this.isRelativeOf("sibling", indi, every);
|
|
2488
|
+
}
|
|
2489
|
+
isSpouseOf(indi, every = false) {
|
|
2490
|
+
return this.isRelativeOf("spouse", indi, every);
|
|
2491
|
+
}
|
|
2492
|
+
isParentOf(indi, every = false) {
|
|
2493
|
+
return this.isRelativeOf("parent", indi, every);
|
|
2494
|
+
}
|
|
2495
|
+
isChildOf(indi, every = false) {
|
|
2496
|
+
return this.isRelativeOf("child", indi, every);
|
|
2497
|
+
}
|
|
2498
|
+
isParentInLawOf(indi, every = false) {
|
|
2499
|
+
return this.isRelativeOf("parentInLaw", indi, every);
|
|
2500
|
+
}
|
|
2501
|
+
isChildInLawOf(indi, every = false) {
|
|
2502
|
+
return this.isRelativeOf("childInLaw", indi, every);
|
|
2503
|
+
}
|
|
2504
|
+
splitByFamily(type, relativeTo) {
|
|
2505
|
+
const splittedList = {};
|
|
2506
|
+
const familiesRelativeTo = relativeTo?.get(type !== "Parents" ? "FAMS" : "FAMC")?.toValueList().keys() ?? [];
|
|
2507
|
+
let lengthOfIndividuals = 0;
|
|
2508
|
+
this.forEach((indi) => {
|
|
2509
|
+
const families = indi.get(type === "Spouses" ? "FAMS" : "FAMC")?.toValueList();
|
|
2510
|
+
if (families) {
|
|
2511
|
+
families.keys().forEach((fKey) => {
|
|
2512
|
+
const famKey = fKey;
|
|
2513
|
+
if (familiesRelativeTo && !familiesRelativeTo.includes(famKey)) {
|
|
2514
|
+
return;
|
|
2515
|
+
}
|
|
2516
|
+
if (!splittedList[famKey]) {
|
|
2517
|
+
splittedList[famKey] = new _Individuals();
|
|
2518
|
+
}
|
|
2519
|
+
splittedList[famKey]?.append(indi);
|
|
2520
|
+
lengthOfIndividuals++;
|
|
2521
|
+
});
|
|
2522
|
+
}
|
|
2523
|
+
});
|
|
2524
|
+
if (type === "Spouses" && relativeTo) {
|
|
2525
|
+
const missingFams = difference(
|
|
2526
|
+
familiesRelativeTo,
|
|
2527
|
+
Object.keys(splittedList)
|
|
2528
|
+
);
|
|
2529
|
+
if (missingFams.length) {
|
|
2530
|
+
missingFams.forEach((fKey) => {
|
|
2531
|
+
const famKey = fKey;
|
|
2532
|
+
if (familiesRelativeTo && !familiesRelativeTo.includes(famKey)) {
|
|
2533
|
+
return;
|
|
2534
|
+
}
|
|
2535
|
+
const missingChildren = relativeTo.getGedcom()?.fam(famKey)?.getChildren();
|
|
2536
|
+
if (!splittedList[famKey] && missingChildren?.length) {
|
|
2537
|
+
splittedList[famKey] = new _Individuals();
|
|
2538
|
+
}
|
|
2539
|
+
});
|
|
2540
|
+
}
|
|
2541
|
+
}
|
|
2542
|
+
return {
|
|
2543
|
+
items: splittedList,
|
|
2544
|
+
lengthOfFamily: Object.keys(splittedList).length,
|
|
2545
|
+
lengthOfIndividuals
|
|
2546
|
+
};
|
|
2547
|
+
}
|
|
2548
|
+
getRelativesOnDegree(degree = 0) {
|
|
2549
|
+
const persons = new _Individuals();
|
|
2550
|
+
this.values().forEach((indi) => {
|
|
2551
|
+
if (indi) {
|
|
2552
|
+
persons.merge(indi.getRelativesOnLevel(degree));
|
|
2553
|
+
}
|
|
2554
|
+
});
|
|
2555
|
+
return persons;
|
|
2556
|
+
}
|
|
2557
|
+
getRelativesOnLevel(level = 0, filter) {
|
|
2558
|
+
const persons = new _Individuals();
|
|
2559
|
+
this.values().forEach((indi) => {
|
|
2560
|
+
if (indi) {
|
|
2561
|
+
persons.merge(indi.getRelativesOnLevel(level, filter));
|
|
2562
|
+
}
|
|
2563
|
+
});
|
|
2564
|
+
return persons;
|
|
2565
|
+
}
|
|
2566
|
+
getAscendants(level = 0, filter) {
|
|
2567
|
+
const persons = new _Individuals();
|
|
2568
|
+
this.values().forEach((indi) => {
|
|
2569
|
+
if (indi) {
|
|
2570
|
+
persons.merge(indi.getAscendants(level, filter));
|
|
2571
|
+
}
|
|
2572
|
+
});
|
|
2573
|
+
return persons;
|
|
2574
|
+
}
|
|
2575
|
+
getDescendants(level = 0, filter) {
|
|
2576
|
+
const persons = new _Individuals();
|
|
2577
|
+
this.values().forEach((indi) => {
|
|
2578
|
+
if (indi) {
|
|
2579
|
+
persons.merge(indi.getDescendants(level, filter));
|
|
2580
|
+
}
|
|
2581
|
+
});
|
|
2582
|
+
return persons;
|
|
2583
|
+
}
|
|
2584
|
+
getAllAscendants(individuals) {
|
|
2585
|
+
const persons = new _Individuals();
|
|
2586
|
+
this.values().forEach((indi) => {
|
|
2587
|
+
if (indi) {
|
|
2588
|
+
persons.merge(indi.getAllAscendants(individuals));
|
|
2589
|
+
}
|
|
2590
|
+
});
|
|
2591
|
+
return persons;
|
|
2592
|
+
}
|
|
2593
|
+
getAllDescendants(individuals, containDescendantsInLaw = false) {
|
|
2594
|
+
const persons = new _Individuals();
|
|
2595
|
+
this.values().forEach((indi) => {
|
|
2596
|
+
if (indi) {
|
|
2597
|
+
persons.merge(
|
|
2598
|
+
indi.getAllDescendants(individuals, containDescendantsInLaw)
|
|
2599
|
+
);
|
|
2600
|
+
}
|
|
2601
|
+
});
|
|
2602
|
+
return persons;
|
|
2603
|
+
}
|
|
2604
|
+
getSiblings() {
|
|
2605
|
+
const persons = new _Individuals();
|
|
2606
|
+
this.values().forEach((indi) => {
|
|
2607
|
+
if (indi) {
|
|
2608
|
+
persons.merge(indi.getSiblings());
|
|
2609
|
+
}
|
|
2610
|
+
});
|
|
2611
|
+
return persons;
|
|
2612
|
+
}
|
|
2613
|
+
getChildren() {
|
|
2614
|
+
const persons = new _Individuals();
|
|
2615
|
+
this.values().forEach((indi) => {
|
|
2616
|
+
if (indi) {
|
|
2617
|
+
persons.merge(indi.getChildren());
|
|
2618
|
+
}
|
|
2619
|
+
});
|
|
2620
|
+
return persons;
|
|
2621
|
+
}
|
|
2622
|
+
getParents() {
|
|
2623
|
+
const persons = new _Individuals();
|
|
2624
|
+
this.values().forEach((indi) => {
|
|
2625
|
+
if (indi) {
|
|
2626
|
+
persons.merge(indi.getParents());
|
|
2627
|
+
}
|
|
2628
|
+
});
|
|
2629
|
+
return persons;
|
|
2630
|
+
}
|
|
2631
|
+
getCoParents() {
|
|
2632
|
+
const persons = new _Individuals();
|
|
2633
|
+
this.values().forEach((indi) => {
|
|
2634
|
+
if (indi) {
|
|
2635
|
+
persons.merge(indi.getCoParents());
|
|
2636
|
+
}
|
|
2637
|
+
});
|
|
2638
|
+
return persons;
|
|
2639
|
+
}
|
|
2640
|
+
getSpouses() {
|
|
2641
|
+
const persons = new _Individuals();
|
|
2642
|
+
this.values().forEach((indi) => {
|
|
2643
|
+
if (indi) {
|
|
2644
|
+
persons.merge(indi.getCoParents());
|
|
2645
|
+
}
|
|
2646
|
+
});
|
|
2647
|
+
return persons;
|
|
2648
|
+
}
|
|
2649
|
+
toName() {
|
|
2650
|
+
return super.toProp("NAME")?.toValue();
|
|
2651
|
+
}
|
|
2652
|
+
toList() {
|
|
2653
|
+
return new _Individuals().concat(this.getItems());
|
|
2654
|
+
}
|
|
2655
|
+
};
|
|
2656
|
+
|
|
2657
|
+
// src/classes/name.ts
|
|
2658
|
+
var CommonName = class extends Common {
|
|
2659
|
+
constructor(gedcom, id, main, parent) {
|
|
2660
|
+
super(gedcom, id, main, parent);
|
|
2661
|
+
delete this.id;
|
|
2662
|
+
}
|
|
2663
|
+
set value(value) {
|
|
2664
|
+
if (value && this._main instanceof Indi) {
|
|
2665
|
+
const nameParts = value.match(
|
|
2666
|
+
/(?<givenname>[^/]*)(\/(?<surname>[^/]*)\/)?(?<suffix>.*)$/
|
|
2667
|
+
)?.groups;
|
|
2668
|
+
if (nameParts?.givenname?.trim()) {
|
|
2669
|
+
this.GIVN = this.GIVN || createCommon(this._gedcom, void 0, this.main);
|
|
2670
|
+
this.GIVN.isListable = false;
|
|
2671
|
+
this.GIVN.value = nameParts.givenname.trim();
|
|
2672
|
+
}
|
|
2673
|
+
if (nameParts?.surname?.trim()) {
|
|
2674
|
+
this.SURN = this.SURN || createCommon(this._gedcom, void 0, this.main);
|
|
2675
|
+
this.SURN.value = nameParts.surname.trim();
|
|
2676
|
+
this.SURN.isListable = false;
|
|
2677
|
+
}
|
|
2678
|
+
if (nameParts?.suffix?.trim()) {
|
|
2679
|
+
this.NSFX = this.NSFX || createCommon(this._gedcom, void 0, this.main);
|
|
2680
|
+
this.NSFX.value = nameParts.suffix.trim();
|
|
2681
|
+
this.NSFX.isListable = false;
|
|
2682
|
+
}
|
|
2683
|
+
}
|
|
2684
|
+
this._value = value;
|
|
2685
|
+
}
|
|
2686
|
+
get value() {
|
|
2687
|
+
if (this._value === void 0 && this.DISPLAY?.value) {
|
|
2688
|
+
return this.DISPLAY?.value;
|
|
2689
|
+
}
|
|
2690
|
+
return this._value;
|
|
2691
|
+
}
|
|
2692
|
+
name(value) {
|
|
2693
|
+
this.value = value;
|
|
2694
|
+
return this;
|
|
2695
|
+
}
|
|
2696
|
+
};
|
|
2697
|
+
var createCommonName = (gedcom, id, main, parent) => {
|
|
2698
|
+
return createProxy(
|
|
2699
|
+
new CommonName(gedcom, id, main, parent)
|
|
2700
|
+
);
|
|
2701
|
+
};
|
|
2702
|
+
|
|
2703
|
+
// src/classes/indi.ts
|
|
2704
|
+
var ALLOWED_FACTS = [
|
|
2705
|
+
"EVEN",
|
|
2706
|
+
"OCCU",
|
|
2707
|
+
"OCCUPATIONS",
|
|
2708
|
+
"RESI",
|
|
2709
|
+
"BIRT",
|
|
2710
|
+
"DEAT",
|
|
2711
|
+
"BAPT",
|
|
2712
|
+
"BAPM",
|
|
2713
|
+
"CHRI",
|
|
2714
|
+
"CHR",
|
|
2715
|
+
"CHRA",
|
|
2716
|
+
"BURI",
|
|
2717
|
+
"CREM",
|
|
2718
|
+
"ADOP",
|
|
2719
|
+
"BARM",
|
|
2720
|
+
"BASM",
|
|
2721
|
+
"BLES",
|
|
2722
|
+
"CONF",
|
|
2723
|
+
"FCOM",
|
|
2724
|
+
"ORDN",
|
|
2725
|
+
"NATU",
|
|
2726
|
+
"EMIG",
|
|
2727
|
+
"IMMI",
|
|
2728
|
+
"CENS",
|
|
2729
|
+
"PROB",
|
|
2730
|
+
"WILL",
|
|
2731
|
+
"GRAD",
|
|
2732
|
+
"RETI",
|
|
2733
|
+
"EDUC",
|
|
2734
|
+
"DIV",
|
|
2735
|
+
"RELI",
|
|
2736
|
+
"CAST",
|
|
2737
|
+
"DSCR",
|
|
2738
|
+
"NATI",
|
|
2739
|
+
"PROP",
|
|
2740
|
+
"SSN",
|
|
2741
|
+
"TITL",
|
|
2742
|
+
"ADDR",
|
|
2743
|
+
"BAPL",
|
|
2744
|
+
"CONL",
|
|
2745
|
+
"ENDL",
|
|
2746
|
+
"SLGC",
|
|
2747
|
+
"_MILT",
|
|
2748
|
+
"_MILTID",
|
|
2749
|
+
"FACT",
|
|
2750
|
+
"_ORIG",
|
|
2751
|
+
"_WLNK",
|
|
2752
|
+
"WWW",
|
|
2753
|
+
"URL"
|
|
2754
|
+
];
|
|
2755
|
+
var DISALLOWED_CUSTOM_FACTS = ["DNA Test", "Newspaper"];
|
|
2756
|
+
var CustomFactRenderers = {
|
|
2757
|
+
AKA: (label, fact, indi) => {
|
|
2758
|
+
const originalNameObj = indi?.NAME;
|
|
2759
|
+
const note = fact.get("NOTE");
|
|
2760
|
+
const factName = note?.toValue();
|
|
2761
|
+
const name = createCommonName(fact.getGedcom(), void 0, indi);
|
|
2762
|
+
const suffix = originalNameObj?.NSFX?.toValue();
|
|
2763
|
+
const surname = originalNameObj?.SURN?.toValue();
|
|
2764
|
+
const givenname = originalNameObj?.GIVN?.toValue();
|
|
2765
|
+
const nameParts = [
|
|
2766
|
+
...givenname?.split(" ").map((s) => ({ name: s, givenname: true })) ?? [],
|
|
2767
|
+
...surname?.split(" ").map((s) => ({ name: s, surname: true })) ?? [],
|
|
2768
|
+
...suffix?.split(" ").map((s) => ({ name: s, suffix: true })) ?? []
|
|
2769
|
+
].filter(Boolean);
|
|
2770
|
+
const factParts = factName?.split(" ");
|
|
2771
|
+
if (nameParts.length === factParts?.length && !(note instanceof CommonName)) {
|
|
2772
|
+
const guessedSuffix = [];
|
|
2773
|
+
const guessedSurname = [];
|
|
2774
|
+
const guessedGivenname = [];
|
|
2775
|
+
factParts.forEach((f, i) => {
|
|
2776
|
+
const namePart = nameParts[i];
|
|
2777
|
+
if (!f) {
|
|
2778
|
+
return;
|
|
2779
|
+
}
|
|
2780
|
+
if (namePart.suffix) {
|
|
2781
|
+
guessedSuffix.push(f);
|
|
2782
|
+
} else if (namePart.givenname) {
|
|
2783
|
+
guessedGivenname.push(f);
|
|
2784
|
+
} else if (namePart.surname) {
|
|
2785
|
+
guessedSurname.push(f);
|
|
2786
|
+
}
|
|
2787
|
+
});
|
|
2788
|
+
const allNamePart = [];
|
|
2789
|
+
if (guessedGivenname.length) {
|
|
2790
|
+
allNamePart.push(guessedGivenname.join(" "));
|
|
2791
|
+
}
|
|
2792
|
+
if (guessedSurname.length) {
|
|
2793
|
+
allNamePart.push(`/${guessedSurname.join(" ")}/`);
|
|
2794
|
+
}
|
|
2795
|
+
if (guessedSuffix.length) {
|
|
2796
|
+
allNamePart.push(guessedSuffix.join(" "));
|
|
2797
|
+
}
|
|
2798
|
+
name.value = allNamePart.join(" ");
|
|
2799
|
+
} else {
|
|
2800
|
+
name.value = factName;
|
|
2801
|
+
}
|
|
2802
|
+
fact.set("NOTE", name);
|
|
2803
|
+
label.value = "AKA";
|
|
2804
|
+
fact.set("_LABEL", label);
|
|
2805
|
+
}
|
|
2806
|
+
};
|
|
2807
|
+
var relativesOnLevelCache = relativesCache("relativesOnLevelCache");
|
|
2808
|
+
var relativesOnDegreeCache = relativesCache("relativesOnDegreeCache");
|
|
2809
|
+
var Indi = class extends Common {
|
|
2810
|
+
toName() {
|
|
2811
|
+
return this.get("NAME")?.toValue();
|
|
2812
|
+
}
|
|
2813
|
+
toNaturalName() {
|
|
2814
|
+
return this.get("NAME")?.toValue()?.replaceAll("/", "");
|
|
2815
|
+
}
|
|
2816
|
+
toList() {
|
|
2817
|
+
return new Individuals().concat(
|
|
2818
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
2819
|
+
this.id ? { [this.id]: this } : { ...[this] }
|
|
2820
|
+
);
|
|
2821
|
+
}
|
|
2822
|
+
generateTree(props) {
|
|
2823
|
+
const {
|
|
2824
|
+
generations,
|
|
2825
|
+
level,
|
|
2826
|
+
index,
|
|
2827
|
+
showDescendants,
|
|
2828
|
+
offspringSpouses,
|
|
2829
|
+
ancestorSpouses,
|
|
2830
|
+
onlyDescendants,
|
|
2831
|
+
maxLevel,
|
|
2832
|
+
minLevel,
|
|
2833
|
+
drawNonBiologicalAncestors,
|
|
2834
|
+
ancestorSiblings
|
|
2835
|
+
} = props;
|
|
2836
|
+
if (!this.id) {
|
|
2837
|
+
throw new Error("Indi must have an id");
|
|
2838
|
+
}
|
|
2839
|
+
const isMainDescendantLevel = showDescendants && level <= 1;
|
|
2840
|
+
const isDescendantLevel = showDescendants && level < 1;
|
|
2841
|
+
if (level < 1 && !isDescendantLevel) {
|
|
2842
|
+
throw new Error("Arguments 2 must be greater than 0.");
|
|
2843
|
+
}
|
|
2844
|
+
if (maxLevel !== void 0 && maxLevel < level || minLevel !== void 0 && minLevel > level) {
|
|
2845
|
+
return this;
|
|
2846
|
+
}
|
|
2847
|
+
const gens = generations ?? {
|
|
2848
|
+
existed: {},
|
|
2849
|
+
tree: {},
|
|
2850
|
+
halves: {},
|
|
2851
|
+
lastItems: {}
|
|
2852
|
+
};
|
|
2853
|
+
const families = this.getFamiliesBiologicalFirst("FAMC");
|
|
2854
|
+
const familiesAllMember = families.getParents();
|
|
2855
|
+
families.forEach((fam, famKey, famIndex) => {
|
|
2856
|
+
if (!this.id) {
|
|
2857
|
+
return;
|
|
1845
2858
|
}
|
|
1846
2859
|
const id = fam.id;
|
|
1847
2860
|
let father = isDescendantLevel ? void 0 : fam.getHusband().index(0);
|
|
@@ -2281,7 +3294,7 @@ var Indi = class extends Common {
|
|
|
2281
3294
|
return result;
|
|
2282
3295
|
}
|
|
2283
3296
|
ancestryLink() {
|
|
2284
|
-
const www = this._gedcom?.HEAD?.SOUR?.CORP?.WWW?.value;
|
|
3297
|
+
const www = this.getFromSourceHeads("SOUR.CORP.WWW.value") || this._gedcom?.HEAD?.SOUR?.CORP?.WWW?.value;
|
|
2285
3298
|
const tree = this.getAncestryTreeId();
|
|
2286
3299
|
if (this.id) {
|
|
2287
3300
|
return `https://${www}/family-tree/person/tree/${tree}/person/${this.id.replace(
|
|
@@ -2293,7 +3306,7 @@ var Indi = class extends Common {
|
|
|
2293
3306
|
async ancestryMedia(namespace) {
|
|
2294
3307
|
const list = {};
|
|
2295
3308
|
const objeList = this.get("OBJE")?.toList().copy();
|
|
2296
|
-
const www = this._gedcom?.HEAD?.SOUR?.CORP?.WWW?.value;
|
|
3309
|
+
const www = this.getFromSourceHeads("SOUR.CORP.WWW.value") || this._gedcom?.HEAD?.SOUR?.CORP?.WWW?.value;
|
|
2297
3310
|
const tree = this.getAncestryTreeId();
|
|
2298
3311
|
if (objeList) {
|
|
2299
3312
|
await Promise.all(
|
|
@@ -2311,10 +3324,14 @@ var Indi = class extends Common {
|
|
|
2311
3324
|
const clone = obje?.get("_CLON._OID")?.toValue();
|
|
2312
3325
|
const mser = obje?.get("_MSER._LKID")?.toValue();
|
|
2313
3326
|
let url = obje?.get("FILE")?.toValue();
|
|
2314
|
-
const title = obje?.get("TITL")?.toValue() ?? "";
|
|
2315
|
-
const type = obje
|
|
2316
|
-
|
|
2317
|
-
|
|
3327
|
+
const title = obje?.get("FILE.TITL")?.toValue() ?? obje?.get("TITL")?.toValue() ?? "";
|
|
3328
|
+
const type = resolveObjeForm(obje) ?? (url ? getFileExtension(url) : void 0) ?? "raw";
|
|
3329
|
+
let imgId = clone || mser;
|
|
3330
|
+
const hasEmbeddedOrLocalFile = !!url && (url.startsWith("data:") || url.startsWith("blob:") || !/^https?:\/\//i.test(url));
|
|
3331
|
+
if (!hasEmbeddedOrLocalFile && (!www || !tree || !this.id)) {
|
|
3332
|
+
return;
|
|
3333
|
+
}
|
|
3334
|
+
if (!this.id) {
|
|
2318
3335
|
return;
|
|
2319
3336
|
}
|
|
2320
3337
|
if (!namespace && !url) {
|
|
@@ -2332,13 +3349,16 @@ var Indi = class extends Common {
|
|
|
2332
3349
|
}
|
|
2333
3350
|
url = url || `https://${www}/mediaui-viewer/tree/${tree}/media/${media}`;
|
|
2334
3351
|
}
|
|
3352
|
+
if (!imgId && hasEmbeddedOrLocalFile && url) {
|
|
3353
|
+
imgId = typeof media === "string" && media || `local-${String(key).replace(/[@]/g, "")}-${getFileExtension(url) || "bin"}`;
|
|
3354
|
+
}
|
|
2335
3355
|
if (url && imgId) {
|
|
2336
|
-
const id = `${tree}-${this.id}-${imgId}`;
|
|
3356
|
+
const id = `${tree || "gedzip"}-${this.id}-${imgId}`;
|
|
2337
3357
|
list[id] = {
|
|
2338
3358
|
key,
|
|
2339
3359
|
isPrimary,
|
|
2340
3360
|
id,
|
|
2341
|
-
tree,
|
|
3361
|
+
tree: tree || "gedzip",
|
|
2342
3362
|
imgId,
|
|
2343
3363
|
person: this.id,
|
|
2344
3364
|
title,
|
|
@@ -2353,7 +3373,7 @@ var Indi = class extends Common {
|
|
|
2353
3373
|
return list;
|
|
2354
3374
|
}
|
|
2355
3375
|
myheritageLink(poolId = 0) {
|
|
2356
|
-
const www = this._gedcom?.HEAD?.SOUR?.CORP?.value?.toLowerCase().replace(/^www\./gi, "");
|
|
3376
|
+
const www = (this.getFromSourceHeads("SOUR.CORP.value") || this._gedcom?.HEAD?.SOUR?.CORP?.value)?.toLowerCase().replace(/^www\./gi, "");
|
|
2357
3377
|
const site = this.getMyHeritageTreeId();
|
|
2358
3378
|
const file = this._gedcom?.HEAD?.get("FILE")?.toValue()?.match(/Exported by MyHeritage.com from .+ in (?<site>.+) on .+$/)?.groups?.site;
|
|
2359
3379
|
const normalizedFile = file?.normalize("NFD").replace(/[\u0300-\u036f]/g, "").toLowerCase().replace(/[^a-z0-9]+/g, "-");
|
|
@@ -2384,9 +3404,11 @@ var Indi = class extends Common {
|
|
|
2384
3404
|
obje.standardizeMedia();
|
|
2385
3405
|
const isPrimary = obje?.get("_PRIM")?.toValue() === "Y";
|
|
2386
3406
|
const url = obje?.get("FILE")?.toValue();
|
|
2387
|
-
const title = obje?.get("NOTE")?.toValue() ?? "";
|
|
2388
|
-
const type = obje
|
|
2389
|
-
const
|
|
3407
|
+
const title = obje?.get("FILE.NOTE")?.toValue() ?? obje?.get("NOTE")?.toValue() ?? "";
|
|
3408
|
+
const type = resolveObjeForm(obje) ?? (url ? getFileExtension(url) : void 0) ?? "raw";
|
|
3409
|
+
const photoRin = obje?.get("_PHOTO_RIN")?.toValue();
|
|
3410
|
+
const hasEmbeddedOrLocalFile = !!url && (url.startsWith("data:") || url.startsWith("blob:") || !/^https?:\/\//i.test(url));
|
|
3411
|
+
const imgId = photoRin || (hasEmbeddedOrLocalFile && url ? `local-${String(key).replace(/[@]/g, "")}-${getFileExtension(url) || "bin"}` : void 0);
|
|
2390
3412
|
if (url && imgId) {
|
|
2391
3413
|
const id = `${tree}-${this.id}-${imgId}`;
|
|
2392
3414
|
list[id] = {
|
|
@@ -2509,10 +3531,10 @@ var Indi = class extends Common {
|
|
|
2509
3531
|
const isPrimary = obje?.get("_PRIM")?.toValue() === "Y";
|
|
2510
3532
|
const url = obje?.get("FILE")?.toValue();
|
|
2511
3533
|
const title = obje?.get("TITL")?.toValue() ?? "";
|
|
2512
|
-
const type = obje
|
|
3534
|
+
const type = resolveObjeForm(obje) ?? (url ? getFileExtension(url) : void 0) ?? "raw";
|
|
2513
3535
|
if (url) {
|
|
2514
3536
|
const urlMatch = url.match(/\/([^/]+)\?hash=/);
|
|
2515
|
-
const imgId = urlMatch?.[1] || `img-${index}-${Date.now().toString(36)}
|
|
3537
|
+
const imgId = urlMatch?.[1] || (url.startsWith("data:") ? `data-${index}-${getFileExtension(url) || "bin"}` : `img-${index}-${Date.now().toString(36)}`);
|
|
2516
3538
|
const id = `geni-${geniId}-${imgId}`;
|
|
2517
3539
|
list[id] = {
|
|
2518
3540
|
isPrimary,
|
|
@@ -2549,10 +3571,10 @@ var Indi = class extends Common {
|
|
|
2549
3571
|
obje.standardizeMedia();
|
|
2550
3572
|
const isPrimary = obje?.get("_PRIM")?.toValue() === "Y";
|
|
2551
3573
|
const url = obje?.get("FILE")?.toValue();
|
|
2552
|
-
const title = obje?.get("TITL")?.toValue() ?? "";
|
|
2553
|
-
const type = obje
|
|
3574
|
+
const title = obje?.get("FILE.TITL")?.toValue() ?? obje?.get("TITL")?.toValue() ?? "";
|
|
3575
|
+
const type = resolveObjeForm(obje) ?? (url ? getFileExtension(url) : void 0) ?? "raw";
|
|
2554
3576
|
if (url) {
|
|
2555
|
-
const imgId = `media-${index}-${url.split("/").pop()?.split("?")[0]?.substring(0, 20) || Date.now().toString(36)}`;
|
|
3577
|
+
const imgId = `media-${index}-${url.startsWith("data:") ? getFileExtension(url) || "bin" : url.split("/").pop()?.split("?")[0]?.substring(0, 20) || Date.now().toString(36)}`;
|
|
2556
3578
|
const id = `${treeId}-${this.id}-${imgId}`;
|
|
2557
3579
|
list[id] = {
|
|
2558
3580
|
isPrimary,
|
|
@@ -2592,7 +3614,20 @@ var Indi = class extends Common {
|
|
|
2592
3614
|
cacheKey
|
|
2593
3615
|
);
|
|
2594
3616
|
if (cached !== void 0) {
|
|
2595
|
-
|
|
3617
|
+
if (cached?.file && !isRemoteOrEmbeddedMediaUrl(cached.file)) {
|
|
3618
|
+
const resolvedCached = await resolveLocalMediaUrl(cached.file);
|
|
3619
|
+
if (resolvedCached && isRemoteOrEmbeddedMediaUrl(resolvedCached)) {
|
|
3620
|
+
const refreshed = { ...cached, file: resolvedCached };
|
|
3621
|
+
profilePictureCache(
|
|
3622
|
+
this._gedcom,
|
|
3623
|
+
cacheKey,
|
|
3624
|
+
refreshed
|
|
3625
|
+
);
|
|
3626
|
+
return refreshed;
|
|
3627
|
+
}
|
|
3628
|
+
} else {
|
|
3629
|
+
return cached;
|
|
3630
|
+
}
|
|
2596
3631
|
}
|
|
2597
3632
|
const mediaList = await this.multimedia(namespace);
|
|
2598
3633
|
if (!mediaList) {
|
|
@@ -2604,39 +3639,40 @@ var Indi = class extends Common {
|
|
|
2604
3639
|
return void 0;
|
|
2605
3640
|
}
|
|
2606
3641
|
const mediaArray = Object.values(mediaList);
|
|
2607
|
-
const
|
|
2608
|
-
|
|
2609
|
-
|
|
2610
|
-
|
|
2611
|
-
|
|
2612
|
-
|
|
2613
|
-
|
|
2614
|
-
|
|
2615
|
-
|
|
3642
|
+
const toDisplayableProfile = async (media, isPrimary) => {
|
|
3643
|
+
const resolvedFile = await resolveLocalMediaUrl(media.url);
|
|
3644
|
+
if (!resolvedFile || !isRemoteOrEmbeddedMediaUrl(resolvedFile)) {
|
|
3645
|
+
return void 0;
|
|
3646
|
+
}
|
|
3647
|
+
return {
|
|
3648
|
+
file: resolvedFile,
|
|
3649
|
+
form: media.contentType,
|
|
3650
|
+
title: media.title,
|
|
3651
|
+
isPrimary
|
|
2616
3652
|
};
|
|
2617
|
-
|
|
2618
|
-
|
|
2619
|
-
|
|
2620
|
-
|
|
2621
|
-
|
|
2622
|
-
this._gedcom,
|
|
2623
|
-
cacheKey,
|
|
2624
|
-
void 0
|
|
2625
|
-
);
|
|
2626
|
-
return void 0;
|
|
2627
|
-
}
|
|
2628
|
-
const secondaryMedia = mediaArray.find(
|
|
2629
|
-
(media) => isImageFormat(media.contentType || getFileExtension(media.url))
|
|
3653
|
+
};
|
|
3654
|
+
const candidates = mediaArray.filter(
|
|
3655
|
+
(media) => isImageFormat(
|
|
3656
|
+
media.contentType || media.url || getFileExtension(media.url)
|
|
3657
|
+
)
|
|
2630
3658
|
);
|
|
2631
|
-
|
|
2632
|
-
|
|
2633
|
-
|
|
2634
|
-
|
|
2635
|
-
|
|
2636
|
-
|
|
2637
|
-
|
|
2638
|
-
|
|
2639
|
-
|
|
3659
|
+
const ordered = [
|
|
3660
|
+
...candidates.filter((media) => media.isPrimary),
|
|
3661
|
+
...candidates.filter((media) => !media.isPrimary)
|
|
3662
|
+
];
|
|
3663
|
+
for (const media of ordered) {
|
|
3664
|
+
if (onlyPrimary && !media.isPrimary) {
|
|
3665
|
+
break;
|
|
3666
|
+
}
|
|
3667
|
+
const result = await toDisplayableProfile(media, !!media.isPrimary);
|
|
3668
|
+
if (result) {
|
|
3669
|
+
profilePictureCache(
|
|
3670
|
+
this._gedcom,
|
|
3671
|
+
cacheKey,
|
|
3672
|
+
result
|
|
3673
|
+
);
|
|
3674
|
+
return result;
|
|
3675
|
+
}
|
|
2640
3676
|
}
|
|
2641
3677
|
profilePictureCache(
|
|
2642
3678
|
this._gedcom,
|
|
@@ -2868,11 +3904,161 @@ var Indi = class extends Common {
|
|
|
2868
3904
|
isMale() {
|
|
2869
3905
|
return this.get("SEX")?.toValue() === "M";
|
|
2870
3906
|
}
|
|
2871
|
-
isFemale() {
|
|
2872
|
-
return this.get("SEX")?.toValue() === "F";
|
|
3907
|
+
isFemale() {
|
|
3908
|
+
return this.get("SEX")?.toValue() === "F";
|
|
3909
|
+
}
|
|
3910
|
+
isUnknownSex() {
|
|
3911
|
+
return !this.isMale() && !this.isFemale();
|
|
3912
|
+
}
|
|
3913
|
+
addSpouse(other) {
|
|
3914
|
+
if (!this.id || !other?.id || this.id === other.id || !this._gedcom) {
|
|
3915
|
+
return void 0;
|
|
3916
|
+
}
|
|
3917
|
+
const existing = getFamilyWith(this, other.id);
|
|
3918
|
+
if (existing) {
|
|
3919
|
+
return existing;
|
|
3920
|
+
}
|
|
3921
|
+
const fam = this._gedcom.createFamily();
|
|
3922
|
+
if (!fam.addSpouse(this) || !fam.addSpouse(other)) {
|
|
3923
|
+
return void 0;
|
|
3924
|
+
}
|
|
3925
|
+
return fam;
|
|
3926
|
+
}
|
|
3927
|
+
addChild(child, pedigree) {
|
|
3928
|
+
if (!this.id || !child?.id || this.id === child.id || !this._gedcom) {
|
|
3929
|
+
return void 0;
|
|
3930
|
+
}
|
|
3931
|
+
const existing = findReusableParentChildFamily(
|
|
3932
|
+
this,
|
|
3933
|
+
child
|
|
3934
|
+
);
|
|
3935
|
+
if (existing === "already") {
|
|
3936
|
+
const fam2 = child.getFamilies("FAMC")?.find(
|
|
3937
|
+
(item) => !!item && item.hasParent(this.id) && item.hasChild(child.id)
|
|
3938
|
+
);
|
|
3939
|
+
if (fam2) {
|
|
3940
|
+
setChildPedigree(
|
|
3941
|
+
fam2,
|
|
3942
|
+
child,
|
|
3943
|
+
pedigree,
|
|
3944
|
+
this
|
|
3945
|
+
);
|
|
3946
|
+
}
|
|
3947
|
+
return fam2;
|
|
3948
|
+
}
|
|
3949
|
+
const fam = existing ?? this._gedcom.createFamily();
|
|
3950
|
+
if (!fam.addSpouse(this)) {
|
|
3951
|
+
return void 0;
|
|
3952
|
+
}
|
|
3953
|
+
if (!fam.addChild(child, pedigree, this)) {
|
|
3954
|
+
return void 0;
|
|
3955
|
+
}
|
|
3956
|
+
return fam;
|
|
3957
|
+
}
|
|
3958
|
+
addParent(parent, pedigree) {
|
|
3959
|
+
return parent.addChild(this, pedigree);
|
|
3960
|
+
}
|
|
3961
|
+
/**
|
|
3962
|
+
* Link an existing top-level OBJE record to this individual (`1 OBJE @On@`).
|
|
3963
|
+
*/
|
|
3964
|
+
attachMultimedia(objeOrKey, options) {
|
|
3965
|
+
if (!this._gedcom || !this.id) {
|
|
3966
|
+
return void 0;
|
|
3967
|
+
}
|
|
3968
|
+
const obje = typeof objeOrKey === "string" ? this._gedcom.obje(objeOrKey) : objeOrKey;
|
|
3969
|
+
if (!obje?.id) {
|
|
3970
|
+
return void 0;
|
|
3971
|
+
}
|
|
3972
|
+
const already = this.get("OBJE")?.toList()?.values()?.some((item) => item?.toValue?.() === obje.id);
|
|
3973
|
+
if (!already) {
|
|
3974
|
+
const pointer = makePointer(
|
|
3975
|
+
this._gedcom,
|
|
3976
|
+
this,
|
|
3977
|
+
obje.id,
|
|
3978
|
+
"OBJE"
|
|
3979
|
+
);
|
|
3980
|
+
this.assign("OBJE", pointer);
|
|
3981
|
+
}
|
|
3982
|
+
if (options?.primary) {
|
|
3983
|
+
this.get("OBJE")?.toList()?.forEach((item) => {
|
|
3984
|
+
const target = item?.refType === "OBJE" ? this._gedcom?.obje(
|
|
3985
|
+
String(item.toValue())
|
|
3986
|
+
) : item;
|
|
3987
|
+
if (!target) {
|
|
3988
|
+
return;
|
|
3989
|
+
}
|
|
3990
|
+
if (target.id === obje.id) {
|
|
3991
|
+
target.set("_PRIM", "Y");
|
|
3992
|
+
} else if (target.get("_PRIM")?.toValue() === "Y") {
|
|
3993
|
+
target.set("_PRIM", "N");
|
|
3994
|
+
}
|
|
3995
|
+
});
|
|
3996
|
+
obje.set("_PRIM", "Y");
|
|
3997
|
+
}
|
|
3998
|
+
return obje;
|
|
3999
|
+
}
|
|
4000
|
+
detachMultimedia(objeKey) {
|
|
4001
|
+
const list = this.get("OBJE")?.toList();
|
|
4002
|
+
if (!list) {
|
|
4003
|
+
return;
|
|
4004
|
+
}
|
|
4005
|
+
const toRemove = list.values().filter(
|
|
4006
|
+
(item) => item?.toValue?.() === objeKey || item?.id === objeKey
|
|
4007
|
+
);
|
|
4008
|
+
toRemove.forEach((item) => {
|
|
4009
|
+
if (item) {
|
|
4010
|
+
list.delete(item);
|
|
4011
|
+
}
|
|
4012
|
+
});
|
|
4013
|
+
if (list.length === 0) {
|
|
4014
|
+
this.remove("OBJE");
|
|
4015
|
+
}
|
|
4016
|
+
}
|
|
4017
|
+
/**
|
|
4018
|
+
* Create a multimedia record and attach it to this person.
|
|
4019
|
+
*/
|
|
4020
|
+
attachMediaFromUrl(url, options) {
|
|
4021
|
+
if (!this._gedcom || !url) {
|
|
4022
|
+
return void 0;
|
|
4023
|
+
}
|
|
4024
|
+
const obje = this._gedcom.createMultimediaRecord({
|
|
4025
|
+
file: url,
|
|
4026
|
+
form: options?.form,
|
|
4027
|
+
title: options?.title,
|
|
4028
|
+
mediType: options?.mediType,
|
|
4029
|
+
primary: options?.primary,
|
|
4030
|
+
gedcomVersion: options?.gedcomVersion
|
|
4031
|
+
});
|
|
4032
|
+
return this.attachMultimedia(obje, { primary: options?.primary });
|
|
4033
|
+
}
|
|
4034
|
+
/**
|
|
4035
|
+
* Link a shared SNOTE record via `1 NOTE @Nn@` (GEDCOM 7).
|
|
4036
|
+
*/
|
|
4037
|
+
attachSharedNote(noteOrKey) {
|
|
4038
|
+
if (!this._gedcom || !this.id) {
|
|
4039
|
+
return void 0;
|
|
4040
|
+
}
|
|
4041
|
+
const note = typeof noteOrKey === "string" ? this._gedcom.snote(noteOrKey) : noteOrKey;
|
|
4042
|
+
if (!note?.id) {
|
|
4043
|
+
return void 0;
|
|
4044
|
+
}
|
|
4045
|
+
const already = this.get("NOTE")?.toList()?.values()?.some((item) => item?.toValue?.() === note.id);
|
|
4046
|
+
if (!already) {
|
|
4047
|
+
const pointer = makePointer(
|
|
4048
|
+
this._gedcom,
|
|
4049
|
+
this,
|
|
4050
|
+
note.id,
|
|
4051
|
+
"SNOTE"
|
|
4052
|
+
);
|
|
4053
|
+
this.assign("NOTE", pointer);
|
|
4054
|
+
}
|
|
4055
|
+
return note;
|
|
4056
|
+
}
|
|
4057
|
+
addFact(input) {
|
|
4058
|
+
return addIndividualFact(this, input);
|
|
2873
4059
|
}
|
|
2874
|
-
|
|
2875
|
-
return
|
|
4060
|
+
addNonEvent(input) {
|
|
4061
|
+
return addNonEvent(this, input);
|
|
2876
4062
|
}
|
|
2877
4063
|
getParentType(id) {
|
|
2878
4064
|
let indi;
|
|
@@ -2914,7 +4100,7 @@ var Indi = class extends Common {
|
|
|
2914
4100
|
if (!famChild) {
|
|
2915
4101
|
const childIndi = this._gedcom?.indi(child.id);
|
|
2916
4102
|
const childState = childIndi?.get("FAMC")?.toList()?.filter((item) => item.value === family.id).index(0);
|
|
2917
|
-
childType = childState?.get("PEDI")?.toValue() || "biological" /* BIOLOGICAL */;
|
|
4103
|
+
childType = (childState?.get("PEDI") ?? childState?.get("PEDT"))?.toValue() || "biological" /* BIOLOGICAL */;
|
|
2918
4104
|
} else {
|
|
2919
4105
|
childType = famChild.get(usedRel)?.toValue() || "biological" /* BIOLOGICAL */;
|
|
2920
4106
|
}
|
|
@@ -3074,7 +4260,9 @@ var Indi = class extends Common {
|
|
|
3074
4260
|
}
|
|
3075
4261
|
}
|
|
3076
4262
|
if (kinship !== "child" || !breakAfterSpouse) {
|
|
3077
|
-
indi.getBiologicalFathers().copy().merge(indi.getBiologicalMothers()).merge(
|
|
4263
|
+
indi.getBiologicalFathers().copy().merge(indi.getBiologicalMothers()).merge(
|
|
4264
|
+
indi.getFathers().copy().merge(indi.getMothers())
|
|
4265
|
+
).forEach((relative) => {
|
|
3078
4266
|
if (!visited.has(relative)) {
|
|
3079
4267
|
const currentRelation = indi.getParentType(relative);
|
|
3080
4268
|
const isNonBiological = !!currentRelation && currentRelation !== "biological" /* BIOLOGICAL */;
|
|
@@ -3473,7 +4661,7 @@ var Indi = class extends Common {
|
|
|
3473
4661
|
return;
|
|
3474
4662
|
}
|
|
3475
4663
|
const childState = child?.get("FAMC")?.toList()?.filter((item) => item.value === family.id).index(0);
|
|
3476
|
-
const childType = childState?.get("PEDI")?.toValue() || "biological" /* BIOLOGICAL */;
|
|
4664
|
+
const childType = (childState?.get("PEDI") ?? childState?.get("PEDT"))?.toValue() || "biological" /* BIOLOGICAL */;
|
|
3477
4665
|
if (childType?.toLowerCase() === filter.PEDI.toLowerCase()) {
|
|
3478
4666
|
children.append(child);
|
|
3479
4667
|
}
|
|
@@ -3581,7 +4769,7 @@ var Indi = class extends Common {
|
|
|
3581
4769
|
const child = this.id && family.CHIL?.toValueList()?.item(this.id);
|
|
3582
4770
|
if (!child) {
|
|
3583
4771
|
const childState = this?.get("FAMC")?.toList()?.filter((item) => item.value === family.id).index(0);
|
|
3584
|
-
const parentType = childState?.get("PEDI")?.toValue() || "biological" /* BIOLOGICAL */;
|
|
4772
|
+
const parentType = (childState?.get("PEDI") ?? childState?.get("PEDT"))?.toValue() || "biological" /* BIOLOGICAL */;
|
|
3585
4773
|
if (parentType?.toLowerCase() === filter.PEDI.toLowerCase()) {
|
|
3586
4774
|
parents.merge(family.getParents());
|
|
3587
4775
|
}
|
|
@@ -5780,7 +6968,11 @@ var STANDARD_QUALIFIERS = {
|
|
|
5780
6968
|
BEF: "Bef.",
|
|
5781
6969
|
BEFORE: "Bef.",
|
|
5782
6970
|
AFT: "Aft.",
|
|
5783
|
-
AFTER: "Aft."
|
|
6971
|
+
AFTER: "Aft.",
|
|
6972
|
+
CAL: "Abt.",
|
|
6973
|
+
// calculated ≈ about for display
|
|
6974
|
+
EST: "Abt."
|
|
6975
|
+
// estimated ≈ about for display
|
|
5784
6976
|
};
|
|
5785
6977
|
var EXPORT_QUALIFIERS = {
|
|
5786
6978
|
"Abt.": "ABT",
|
|
@@ -5788,6 +6980,11 @@ var EXPORT_QUALIFIERS = {
|
|
|
5788
6980
|
"Aft.": "AFT"
|
|
5789
6981
|
};
|
|
5790
6982
|
var GEDCOM_MONTHS = /\b(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)\b/g;
|
|
6983
|
+
var CALENDAR_PREFIX = /^(?<calendar>GREGORIAN|JULIAN|FRENCH_R|HEBREW)\b\s+/i;
|
|
6984
|
+
var isGedcomDateValueForm = (value) => (
|
|
6985
|
+
// Require space/end after the token so display forms like "Abt." are not opaque.
|
|
6986
|
+
/^(FROM|TO|BET|AFT|BEF|ABT|CAL|EST|INT)(\s|$)/i.test(value) || /\bAND\b/i.test(value)
|
|
6987
|
+
);
|
|
5791
6988
|
var NOTE_MARKER = "####";
|
|
5792
6989
|
var formatDateWithComponents = (date, hasDay, hasMonth, hasYear, noteValue, baseFormat = "dd MMM yyyy", locale) => {
|
|
5793
6990
|
const hasNote = baseFormat.includes("NOTE");
|
|
@@ -5812,29 +7009,45 @@ var CommonDate = class extends Common {
|
|
|
5812
7009
|
super(gedcom, id, main, parent);
|
|
5813
7010
|
delete this.id;
|
|
5814
7011
|
}
|
|
7012
|
+
get calendar() {
|
|
7013
|
+
return this._calendar;
|
|
7014
|
+
}
|
|
5815
7015
|
set value(value) {
|
|
5816
7016
|
if (value) {
|
|
5817
|
-
const noteRegExp = /^(?<note>[a-zA-Z]+\.)/;
|
|
5818
|
-
const noteMatch = value.match(noteRegExp)?.groups;
|
|
5819
7017
|
let validValue = value;
|
|
7018
|
+
const calendarMatch = validValue.match(CALENDAR_PREFIX);
|
|
7019
|
+
if (calendarMatch?.groups?.calendar) {
|
|
7020
|
+
this._calendar = calendarMatch.groups.calendar.toUpperCase();
|
|
7021
|
+
validValue = validValue.slice(calendarMatch[0].length);
|
|
7022
|
+
} else {
|
|
7023
|
+
this._calendar = void 0;
|
|
7024
|
+
}
|
|
7025
|
+
const noteRegExp = /^(?<note>[a-zA-Z]+\.)/;
|
|
7026
|
+
const noteMatch = validValue.match(noteRegExp)?.groups;
|
|
5820
7027
|
if (noteMatch?.note) {
|
|
5821
7028
|
this.NOTE = this.NOTE || createCommon(this._gedcom, void 0, this.main);
|
|
5822
7029
|
this.NOTE.value = noteMatch?.note;
|
|
5823
|
-
validValue =
|
|
7030
|
+
validValue = validValue.replace(noteRegExp, "");
|
|
5824
7031
|
} else {
|
|
5825
|
-
const qualifierMatch =
|
|
5826
|
-
/^(?<qualifier>ABT|ABOUT|BEF|BEFORE|AFT|AFTER)\b\s*/i
|
|
7032
|
+
const qualifierMatch = validValue.match(
|
|
7033
|
+
/^(?<qualifier>ABT|ABOUT|BEF|BEFORE|AFT|AFTER|CAL|EST)\b\s*/i
|
|
5827
7034
|
);
|
|
5828
7035
|
const qualifier = qualifierMatch?.groups?.qualifier?.toUpperCase();
|
|
5829
7036
|
const note = qualifier ? STANDARD_QUALIFIERS[qualifier] : void 0;
|
|
5830
7037
|
if (note) {
|
|
5831
7038
|
this.NOTE = this.NOTE || createCommon(this._gedcom, void 0, this.main);
|
|
5832
7039
|
this.NOTE.value = note;
|
|
5833
|
-
validValue =
|
|
7040
|
+
validValue = validValue.slice(qualifierMatch[0].length);
|
|
5834
7041
|
}
|
|
5835
7042
|
}
|
|
5836
7043
|
const acceptedDate = this.isValidDateFormat(validValue);
|
|
5837
|
-
if (
|
|
7044
|
+
if (isGedcomDateValueForm(validValue.trim())) {
|
|
7045
|
+
delete this.DAY;
|
|
7046
|
+
delete this.MONTH;
|
|
7047
|
+
delete this.YEAR;
|
|
7048
|
+
this._date = void 0;
|
|
7049
|
+
this._value = value;
|
|
7050
|
+
} else if (acceptedDate) {
|
|
5838
7051
|
this.DAY = this.DAY || createCommon(this._gedcom, void 0, this.main);
|
|
5839
7052
|
this.DAY.value = format(acceptedDate, "dd");
|
|
5840
7053
|
this.MONTH = this.MONTH || createCommon(this._gedcom, void 0, this.main);
|
|
@@ -5937,6 +7150,15 @@ var CommonDate = class extends Common {
|
|
|
5937
7150
|
);
|
|
5938
7151
|
}
|
|
5939
7152
|
exportValue() {
|
|
7153
|
+
if (typeof this._value === "string") {
|
|
7154
|
+
const withoutCalendar = this._value.replace(CALENDAR_PREFIX, "");
|
|
7155
|
+
if (isGedcomDateValueForm(withoutCalendar.trim())) {
|
|
7156
|
+
return this._value.replace(
|
|
7157
|
+
/^((?:GREGORIAN|JULIAN|FRENCH_R|HEBREW)\s+)?(FROM|TO|BET|AFT|BEF|ABT|CAL|EST|INT)\b/i,
|
|
7158
|
+
(_m, cal, q) => `${cal || ""}${q.toUpperCase()}`
|
|
7159
|
+
);
|
|
7160
|
+
}
|
|
7161
|
+
}
|
|
5940
7162
|
const formatted = this.toValue("NOTE dd MMM yyyy", null);
|
|
5941
7163
|
if (!formatted) {
|
|
5942
7164
|
return formatted;
|
|
@@ -5944,826 +7166,987 @@ var CommonDate = class extends Common {
|
|
|
5944
7166
|
const note = this.NOTE?.value?.trim();
|
|
5945
7167
|
const qualifier = note ? EXPORT_QUALIFIERS[note] : void 0;
|
|
5946
7168
|
const standardized = qualifier ? formatted.replace(note, qualifier) : formatted;
|
|
5947
|
-
|
|
7169
|
+
const withMonths = standardized.replace(
|
|
5948
7170
|
GEDCOM_MONTHS,
|
|
5949
7171
|
(month) => month.toUpperCase()
|
|
5950
7172
|
);
|
|
7173
|
+
if (this._calendar && this._calendar !== "GREGORIAN") {
|
|
7174
|
+
return `${this._calendar} ${withMonths}`;
|
|
7175
|
+
}
|
|
7176
|
+
return withMonths;
|
|
5951
7177
|
}
|
|
5952
|
-
toGedcomLines(tag, level = 0, options) {
|
|
5953
|
-
const internal = new RegExp(
|
|
5954
|
-
`^${level} (DAY|MONTH|YEAR)( |$)|^${level} NOTE (Abt\\.|Bef\\.|Aft\\.)$`
|
|
5955
|
-
);
|
|
5956
|
-
return super.toGedcomLines(tag, level, options).filter((line) => !internal.test(line));
|
|
5957
|
-
}
|
|
5958
|
-
inRange(range, trueIfNoYear = false) {
|
|
5959
|
-
return inRange(this.YEAR?.value, range, trueIfNoYear);
|
|
5960
|
-
}
|
|
5961
|
-
};
|
|
5962
|
-
var createCommonDate = (gedcom, id, main, parent) => {
|
|
5963
|
-
return createProxy(
|
|
5964
|
-
new CommonDate(gedcom, id, main, parent)
|
|
5965
|
-
);
|
|
5966
|
-
};
|
|
5967
|
-
var isCommonDate = (value) => {
|
|
5968
|
-
return !!value && value !== null && typeof value === "object" && "_date" in value;
|
|
5969
|
-
};
|
|
5970
|
-
|
|
5971
|
-
// src/utils/get-family-with.ts
|
|
5972
|
-
var getFamilyWith = (person1, person2, famType = "FAMS") => {
|
|
5973
|
-
return person1?.get(famType)?.toValueList().find((fam) => {
|
|
5974
|
-
const family = fam;
|
|
5975
|
-
return famType === "FAMC" || family?.HUSB?.value === person2 || family?.WIFE?.value === person2;
|
|
5976
|
-
});
|
|
5977
|
-
};
|
|
5978
|
-
|
|
5979
|
-
// src/constants/orders.ts
|
|
5980
|
-
var BIRTH_ASC = {
|
|
5981
|
-
"BIRT.DATE": {
|
|
5982
|
-
direction: "ASC",
|
|
5983
|
-
getter: (value, raw) => {
|
|
5984
|
-
if (isCommonDate(raw) && raw.rawValue) {
|
|
5985
|
-
return raw.rawValue.getTime();
|
|
5986
|
-
}
|
|
5987
|
-
return new Date(value).getTime();
|
|
5988
|
-
}
|
|
5989
|
-
}
|
|
5990
|
-
};
|
|
5991
|
-
var BIRTH_DESC = {
|
|
5992
|
-
"BIRT.DATE": {
|
|
5993
|
-
direction: "DESC",
|
|
5994
|
-
getter: (value, raw) => {
|
|
5995
|
-
if (isCommonDate(raw) && raw.rawValue) {
|
|
5996
|
-
return raw.rawValue.getTime();
|
|
5997
|
-
}
|
|
5998
|
-
return new Date(value).getTime();
|
|
5999
|
-
}
|
|
6000
|
-
}
|
|
6001
|
-
};
|
|
6002
|
-
var DEATH_ASC = {
|
|
6003
|
-
"DEAT.DATE": {
|
|
6004
|
-
direction: "ASC",
|
|
6005
|
-
getter: (value, raw) => {
|
|
6006
|
-
if (isCommonDate(raw) && raw.rawValue) {
|
|
6007
|
-
return raw.rawValue.getTime();
|
|
6008
|
-
}
|
|
6009
|
-
return new Date(value).getTime();
|
|
6010
|
-
}
|
|
6011
|
-
}
|
|
6012
|
-
};
|
|
6013
|
-
var DEATH_DESC = {
|
|
6014
|
-
"DEAT.DATE": {
|
|
6015
|
-
direction: "DESC",
|
|
6016
|
-
getter: (value, raw) => {
|
|
6017
|
-
if (isCommonDate(raw) && raw.rawValue) {
|
|
6018
|
-
return raw.rawValue.getTime();
|
|
6019
|
-
}
|
|
6020
|
-
return new Date(value).getTime();
|
|
6021
|
-
}
|
|
6022
|
-
}
|
|
6023
|
-
};
|
|
6024
|
-
var DATE_ASC = {
|
|
6025
|
-
DATE: {
|
|
6026
|
-
direction: "ASC",
|
|
6027
|
-
getter: (value, raw) => {
|
|
6028
|
-
if (isCommonDate(raw) && raw.rawValue) {
|
|
6029
|
-
return raw.rawValue.getTime();
|
|
6030
|
-
}
|
|
6031
|
-
return new Date(value).getTime();
|
|
6032
|
-
}
|
|
6033
|
-
}
|
|
6034
|
-
};
|
|
6035
|
-
var chars = [
|
|
6036
|
-
"a",
|
|
6037
|
-
"\xE0",
|
|
6038
|
-
"\xE1",
|
|
6039
|
-
"\xE2",
|
|
6040
|
-
"\xE4",
|
|
6041
|
-
"\xE6",
|
|
6042
|
-
"\xE3",
|
|
6043
|
-
"\xE5",
|
|
6044
|
-
"\u0101",
|
|
6045
|
-
"b",
|
|
6046
|
-
"c",
|
|
6047
|
-
"\xE7",
|
|
6048
|
-
"\u0107",
|
|
6049
|
-
"\u010D",
|
|
6050
|
-
"cs",
|
|
6051
|
-
"d",
|
|
6052
|
-
"dz",
|
|
6053
|
-
"dzs",
|
|
6054
|
-
"e",
|
|
6055
|
-
"\xE8",
|
|
6056
|
-
"\xE9",
|
|
6057
|
-
"\xEA",
|
|
6058
|
-
"\xEB",
|
|
6059
|
-
"\u0113",
|
|
6060
|
-
"\u0117",
|
|
6061
|
-
"\u0119",
|
|
6062
|
-
"f",
|
|
6063
|
-
"g",
|
|
6064
|
-
"gy",
|
|
6065
|
-
"h",
|
|
6066
|
-
"i",
|
|
6067
|
-
"\xEE",
|
|
6068
|
-
"\xEF",
|
|
6069
|
-
"\xED",
|
|
6070
|
-
"\u012B",
|
|
6071
|
-
"\u012F",
|
|
6072
|
-
"\xEC",
|
|
6073
|
-
"j",
|
|
6074
|
-
"k",
|
|
6075
|
-
"l",
|
|
6076
|
-
"\u0142",
|
|
6077
|
-
"ly",
|
|
6078
|
-
"m",
|
|
6079
|
-
"n",
|
|
6080
|
-
"\xF1",
|
|
6081
|
-
"\u0144",
|
|
6082
|
-
"ny",
|
|
6083
|
-
"o",
|
|
6084
|
-
"\xF3",
|
|
6085
|
-
"\xF6",
|
|
6086
|
-
"\u0151",
|
|
6087
|
-
"\xF4",
|
|
6088
|
-
"\xF2",
|
|
6089
|
-
"\xF5",
|
|
6090
|
-
"\u0153",
|
|
6091
|
-
"\xF8",
|
|
6092
|
-
"\u014D",
|
|
6093
|
-
"p",
|
|
6094
|
-
"q",
|
|
6095
|
-
"r",
|
|
6096
|
-
"s",
|
|
6097
|
-
"\u015B",
|
|
6098
|
-
"\u0161",
|
|
6099
|
-
"\xDF",
|
|
6100
|
-
"sz",
|
|
6101
|
-
"t",
|
|
6102
|
-
"ty",
|
|
6103
|
-
"u",
|
|
6104
|
-
"\xFA",
|
|
6105
|
-
"\xFC",
|
|
6106
|
-
"\u0171",
|
|
6107
|
-
"\xFB",
|
|
6108
|
-
"\xF9",
|
|
6109
|
-
"\u016B",
|
|
6110
|
-
"v",
|
|
6111
|
-
"w",
|
|
6112
|
-
"x",
|
|
6113
|
-
"y",
|
|
6114
|
-
"z",
|
|
6115
|
-
"zs"
|
|
6116
|
-
];
|
|
6117
|
-
chars.reduce((acc, curr, idx) => {
|
|
6118
|
-
acc[curr] = idx;
|
|
6119
|
-
return acc;
|
|
6120
|
-
}, {});
|
|
6121
|
-
var getBirthAsc = (itemA, _keyA, itemB, _keyB) => {
|
|
6122
|
-
const birthA = itemA?.BIRT?.index(0);
|
|
6123
|
-
const birthB = itemB?.BIRT?.index(0);
|
|
6124
|
-
const valueA = birthA?.DATE?.rawValue;
|
|
6125
|
-
const valueB = birthB?.DATE?.rawValue;
|
|
6126
|
-
if (valueA?.getTime() === valueB?.getTime()) {
|
|
6127
|
-
return 0;
|
|
6128
|
-
}
|
|
6129
|
-
if (!valueA || valueB && valueA > valueB) {
|
|
6130
|
-
return 1;
|
|
6131
|
-
}
|
|
6132
|
-
return -1;
|
|
6133
|
-
};
|
|
6134
|
-
var getMarriageAsc = (person, famType = "FAMS") => (itemA, _keyA, itemB, _keyB) => {
|
|
6135
|
-
if (!person && famType === "FAMS") {
|
|
6136
|
-
return 0;
|
|
6137
|
-
}
|
|
6138
|
-
const familyA = getFamilyWith(itemA, person);
|
|
6139
|
-
const familyB = getFamilyWith(itemB, person);
|
|
6140
|
-
const marriageA = familyA?.MARR?.DATE?.rawValue;
|
|
6141
|
-
const marriageB = familyB?.MARR?.DATE?.rawValue;
|
|
6142
|
-
if (marriageA?.getTime() === marriageB?.getTime()) {
|
|
6143
|
-
return 0;
|
|
6144
|
-
}
|
|
6145
|
-
if (!marriageA || marriageB && marriageA > marriageB) {
|
|
6146
|
-
return 1;
|
|
6147
|
-
}
|
|
6148
|
-
return -1;
|
|
6149
|
-
};
|
|
6150
|
-
var getMarriageAscAndChildBirth = (person) => (itemA, keyA, itemB, keyB) => {
|
|
6151
|
-
const marriageSort = getMarriageAsc(person)(itemA, keyA, itemB, keyB);
|
|
6152
|
-
if (marriageSort !== 0) {
|
|
6153
|
-
return marriageSort;
|
|
6154
|
-
}
|
|
6155
|
-
const familyA = getFamilyWith(itemA, person);
|
|
6156
|
-
const familyB = getFamilyWith(itemB, person);
|
|
6157
|
-
const childA = familyA?.getChildren().orderBy(BIRTH_ASC).index(0);
|
|
6158
|
-
const childB = familyB?.getChildren().orderBy(BIRTH_ASC).index(0);
|
|
6159
|
-
return getBirthAsc(childA, keyA, childB);
|
|
6160
|
-
};
|
|
6161
|
-
var uniqueItemsCache = /* @__PURE__ */ new WeakMap();
|
|
6162
|
-
var setNestedGroup = (obj, key, value, uniqueCounting = true) => {
|
|
6163
|
-
const parts = Array.isArray(key) ? key : key.split(/,\s*/);
|
|
6164
|
-
set(obj, [...parts, "items"], value);
|
|
6165
|
-
parts.forEach((_, index) => {
|
|
6166
|
-
if (!uniqueCounting) {
|
|
6167
|
-
const key2 = [...parts.toSpliced(index + 1), "length"];
|
|
6168
|
-
const length = get(obj, key2);
|
|
6169
|
-
set(obj, key2, (length ?? 0) + value.length);
|
|
6170
|
-
return;
|
|
6171
|
-
}
|
|
6172
|
-
const pathKey = [...parts.toSpliced(index + 1)];
|
|
6173
|
-
const node = get(obj, pathKey);
|
|
6174
|
-
if (node) {
|
|
6175
|
-
let uniqueItems = uniqueItemsCache.get(node);
|
|
6176
|
-
if (!uniqueItems) {
|
|
6177
|
-
uniqueItems = new Individuals();
|
|
6178
|
-
uniqueItemsCache.set(node, uniqueItems);
|
|
6179
|
-
}
|
|
6180
|
-
uniqueItems.merge(value);
|
|
6181
|
-
set(obj, [...pathKey, "length"], uniqueItems.length);
|
|
6182
|
-
}
|
|
6183
|
-
});
|
|
6184
|
-
};
|
|
6185
|
-
|
|
6186
|
-
// src/utils/place-parser.ts
|
|
6187
|
-
var getPlaceParts = (place = []) => {
|
|
6188
|
-
const partsString = Array.isArray(place) ? place.filter(Boolean).join(", ") : place;
|
|
6189
|
-
if (!partsString) {
|
|
6190
|
-
return [{}];
|
|
6191
|
-
}
|
|
6192
|
-
const parts = partsString.split(/,\s*/).map((p) => p.trim()).filter(Boolean);
|
|
6193
|
-
if (parts.length === 0) {
|
|
6194
|
-
return [{}];
|
|
7178
|
+
toGedcomLines(tag, level = 0, options) {
|
|
7179
|
+
const internal = new RegExp(
|
|
7180
|
+
`^${level} (DAY|MONTH|YEAR)( |$)|^${level} NOTE (Abt\\.|Bef\\.|Aft\\.)$`
|
|
7181
|
+
);
|
|
7182
|
+
return super.toGedcomLines(tag, level, options).filter((line) => !internal.test(line));
|
|
6195
7183
|
}
|
|
6196
|
-
|
|
6197
|
-
|
|
6198
|
-
result.town = parts[0];
|
|
6199
|
-
} else if (parts.length === 2) {
|
|
6200
|
-
result.town = parts[0];
|
|
6201
|
-
result.country = parts[1];
|
|
6202
|
-
} else if (parts.length === 3) {
|
|
6203
|
-
result.town = parts[0];
|
|
6204
|
-
result.county = parts[1];
|
|
6205
|
-
result.country = parts[2];
|
|
6206
|
-
} else {
|
|
6207
|
-
result.leftParts = parts.slice(0, parts.length - 3);
|
|
6208
|
-
result.town = parts[parts.length - 3];
|
|
6209
|
-
result.county = parts[parts.length - 2];
|
|
6210
|
-
result.country = parts[parts.length - 1];
|
|
7184
|
+
inRange(range, trueIfNoYear = false) {
|
|
7185
|
+
return inRange(this.YEAR?.value, range, trueIfNoYear);
|
|
6211
7186
|
}
|
|
6212
|
-
return [result];
|
|
6213
7187
|
};
|
|
6214
|
-
|
|
6215
|
-
|
|
6216
|
-
|
|
6217
|
-
|
|
7188
|
+
var createCommonDate = (gedcom, id, main, parent) => {
|
|
7189
|
+
return createProxy(
|
|
7190
|
+
new CommonDate(gedcom, id, main, parent)
|
|
7191
|
+
);
|
|
7192
|
+
};
|
|
7193
|
+
var isCommonDate = (value) => {
|
|
7194
|
+
return !!value && value !== null && typeof value === "object" && "_date" in value;
|
|
6218
7195
|
};
|
|
6219
7196
|
|
|
6220
|
-
// src/
|
|
6221
|
-
var
|
|
6222
|
-
|
|
6223
|
-
|
|
7197
|
+
// src/utils/fact-edit.ts
|
|
7198
|
+
var SINGLETON_TAGS = /* @__PURE__ */ new Set(["BIRT", "DEAT", "SSN", "SEX", "DSCR"]);
|
|
7199
|
+
var firstRecord = (node) => {
|
|
7200
|
+
if (!node) {
|
|
7201
|
+
return void 0;
|
|
6224
7202
|
}
|
|
6225
|
-
|
|
6226
|
-
return
|
|
7203
|
+
if (node instanceof List) {
|
|
7204
|
+
return node.index(0);
|
|
6227
7205
|
}
|
|
6228
|
-
|
|
6229
|
-
|
|
7206
|
+
return node.index(0) ?? node;
|
|
7207
|
+
};
|
|
7208
|
+
var setDateOn = (gedcom, owner, parent, date) => {
|
|
7209
|
+
const trimmed = date.trim();
|
|
7210
|
+
if (!trimmed) {
|
|
7211
|
+
return;
|
|
6230
7212
|
}
|
|
6231
|
-
|
|
6232
|
-
|
|
7213
|
+
let dateNode = parent.get("DATE");
|
|
7214
|
+
if (!dateNode || dateNode instanceof List) {
|
|
7215
|
+
dateNode = createCommonDate(gedcom, void 0, owner, parent);
|
|
7216
|
+
dateNode.type = "DATE";
|
|
7217
|
+
parent.set("DATE", dateNode);
|
|
6233
7218
|
}
|
|
6234
|
-
|
|
6235
|
-
|
|
6236
|
-
|
|
6237
|
-
|
|
6238
|
-
|
|
7219
|
+
dateNode.value = trimmed;
|
|
7220
|
+
};
|
|
7221
|
+
var fillFact = (gedcom, owner, event, input) => {
|
|
7222
|
+
if (input.value?.trim()) {
|
|
7223
|
+
event.value = input.value.trim();
|
|
6239
7224
|
}
|
|
6240
|
-
|
|
6241
|
-
|
|
7225
|
+
if (input.type?.trim()) {
|
|
7226
|
+
event.set("TYPE", input.type.trim());
|
|
6242
7227
|
}
|
|
6243
|
-
|
|
6244
|
-
|
|
6245
|
-
const firstDeathPerson = this.getFirstDeath();
|
|
6246
|
-
const firstBirth = firstBirthPerson?.BIRT?.index(0);
|
|
6247
|
-
const firstDeath = firstDeathPerson?.DEAT?.index(0);
|
|
6248
|
-
if (!firstBirth?.DATE?.rawValue && !firstDeath?.DATE?.rawValue) {
|
|
6249
|
-
return void 0;
|
|
6250
|
-
}
|
|
6251
|
-
if (!firstBirth?.DATE?.rawValue) {
|
|
6252
|
-
return firstDeathPerson;
|
|
6253
|
-
}
|
|
6254
|
-
if (!firstDeath?.DATE?.rawValue) {
|
|
6255
|
-
return firstBirthPerson;
|
|
6256
|
-
}
|
|
6257
|
-
if (firstDeath.DATE.rawValue < firstBirth.DATE.rawValue) {
|
|
6258
|
-
return firstDeathPerson;
|
|
6259
|
-
}
|
|
6260
|
-
return firstBirthPerson;
|
|
7228
|
+
if (input.date) {
|
|
7229
|
+
setDateOn(gedcom, owner, event, input.date);
|
|
6261
7230
|
}
|
|
6262
|
-
|
|
6263
|
-
|
|
6264
|
-
const lastBirthPerson = this.getLastBirth();
|
|
6265
|
-
const lastBirth = lastBirthPerson?.BIRT?.index(0);
|
|
6266
|
-
const lastDeath = lastDeathPerson?.DEAT?.index(0);
|
|
6267
|
-
if (!lastBirth?.DATE?.rawValue && !lastDeath?.DATE?.rawValue) {
|
|
6268
|
-
return void 0;
|
|
6269
|
-
}
|
|
6270
|
-
if (!lastDeath?.DATE?.rawValue) {
|
|
6271
|
-
return lastBirthPerson;
|
|
6272
|
-
}
|
|
6273
|
-
if (!lastBirth?.DATE?.rawValue) {
|
|
6274
|
-
return lastDeathPerson;
|
|
6275
|
-
}
|
|
6276
|
-
if (lastDeath.DATE.rawValue < lastBirth.DATE.rawValue) {
|
|
6277
|
-
return lastBirthPerson;
|
|
6278
|
-
}
|
|
6279
|
-
return lastDeathPerson;
|
|
7231
|
+
if (input.place?.trim()) {
|
|
7232
|
+
event.set("PLAC", input.place.trim());
|
|
6280
7233
|
}
|
|
6281
|
-
|
|
6282
|
-
|
|
6283
|
-
const birth = item.BIRT?.index(0);
|
|
6284
|
-
if (birth?.DATE?.rawValue?.getTime() === 0) {
|
|
6285
|
-
return true;
|
|
6286
|
-
}
|
|
6287
|
-
return !!birth?.DATE?.rawValue?.getTime();
|
|
6288
|
-
}).orderBy(BIRTH_ASC).index(0);
|
|
7234
|
+
if (input.note?.trim()) {
|
|
7235
|
+
event.set("NOTE", input.note.trim());
|
|
6289
7236
|
}
|
|
6290
|
-
|
|
6291
|
-
|
|
6292
|
-
|
|
6293
|
-
|
|
6294
|
-
|
|
6295
|
-
}
|
|
6296
|
-
return !!birth?.DATE?.rawValue?.getTime();
|
|
6297
|
-
}).orderBy(BIRTH_DESC).index(0);
|
|
7237
|
+
};
|
|
7238
|
+
var addIndividualFact = (indi, input) => {
|
|
7239
|
+
const gedcom = indi.getGedcom();
|
|
7240
|
+
if (!gedcom) {
|
|
7241
|
+
return void 0;
|
|
6298
7242
|
}
|
|
6299
|
-
|
|
6300
|
-
|
|
6301
|
-
|
|
6302
|
-
|
|
6303
|
-
|
|
6304
|
-
|
|
6305
|
-
|
|
6306
|
-
}
|
|
7243
|
+
const tag = input.tag;
|
|
7244
|
+
let event = SINGLETON_TAGS.has(tag) ? firstRecord(indi.get(tag)) : void 0;
|
|
7245
|
+
if (!event) {
|
|
7246
|
+
event = createCommon(gedcom, void 0, indi);
|
|
7247
|
+
event.type = tag;
|
|
7248
|
+
if (SINGLETON_TAGS.has(tag)) {
|
|
7249
|
+
indi.set(tag, event);
|
|
7250
|
+
} else {
|
|
7251
|
+
indi.assign(tag, event);
|
|
7252
|
+
}
|
|
6307
7253
|
}
|
|
6308
|
-
|
|
6309
|
-
|
|
6310
|
-
|
|
6311
|
-
|
|
6312
|
-
|
|
6313
|
-
|
|
6314
|
-
|
|
6315
|
-
}).orderBy(DEATH_DESC).index(0);
|
|
7254
|
+
fillFact(gedcom, indi, event, input);
|
|
7255
|
+
return event;
|
|
7256
|
+
};
|
|
7257
|
+
var addFamilyFact = (fam, input) => {
|
|
7258
|
+
const gedcom = fam.getGedcom();
|
|
7259
|
+
if (!gedcom) {
|
|
7260
|
+
return void 0;
|
|
6316
7261
|
}
|
|
6317
|
-
|
|
6318
|
-
|
|
6319
|
-
|
|
6320
|
-
|
|
6321
|
-
|
|
6322
|
-
|
|
6323
|
-
|
|
6324
|
-
|
|
7262
|
+
const event = createCommon(gedcom, void 0, fam);
|
|
7263
|
+
event.type = input.tag;
|
|
7264
|
+
fam.assign(input.tag, event);
|
|
7265
|
+
fillFact(gedcom, fam, event, input);
|
|
7266
|
+
return event;
|
|
7267
|
+
};
|
|
7268
|
+
var addNonEvent = (owner, input) => {
|
|
7269
|
+
const gedcom = owner.getGedcom();
|
|
7270
|
+
const eventType = input.event?.trim().toUpperCase();
|
|
7271
|
+
if (!gedcom || !eventType) {
|
|
7272
|
+
return void 0;
|
|
6325
7273
|
}
|
|
6326
|
-
|
|
6327
|
-
|
|
6328
|
-
|
|
6329
|
-
|
|
6330
|
-
|
|
6331
|
-
},
|
|
6332
|
-
sort,
|
|
6333
|
-
minOccurance,
|
|
6334
|
-
"Letters appearing less than 5 times"
|
|
6335
|
-
);
|
|
7274
|
+
const no = createCommon(gedcom, void 0, owner);
|
|
7275
|
+
no.type = "NO";
|
|
7276
|
+
no.value = eventType;
|
|
7277
|
+
if (input.date?.trim()) {
|
|
7278
|
+
setDateOn(gedcom, owner, no, input.date);
|
|
6336
7279
|
}
|
|
6337
|
-
|
|
6338
|
-
|
|
6339
|
-
"NAME.SURN",
|
|
6340
|
-
sort,
|
|
6341
|
-
minOccurance,
|
|
6342
|
-
"Surnames appearing less than 5 times"
|
|
6343
|
-
);
|
|
7280
|
+
if (input.note?.trim()) {
|
|
7281
|
+
no.set("NOTE", input.note.trim());
|
|
6344
7282
|
}
|
|
6345
|
-
|
|
6346
|
-
|
|
6347
|
-
|
|
6348
|
-
|
|
6349
|
-
|
|
6350
|
-
|
|
6351
|
-
|
|
6352
|
-
|
|
6353
|
-
|
|
6354
|
-
|
|
6355
|
-
|
|
6356
|
-
|
|
6357
|
-
|
|
6358
|
-
|
|
6359
|
-
|
|
6360
|
-
|
|
6361
|
-
minOccurance,
|
|
6362
|
-
"Time ranges appearing less than 5 times"
|
|
6363
|
-
);
|
|
7283
|
+
owner.assign("NO", no);
|
|
7284
|
+
return no;
|
|
7285
|
+
};
|
|
7286
|
+
|
|
7287
|
+
// src/classes/fam.ts
|
|
7288
|
+
var Fam = class extends Common {
|
|
7289
|
+
getFamilyMembers(type) {
|
|
7290
|
+
const familyMembers = new Individuals();
|
|
7291
|
+
this.get(type)?.toList().forEach((item) => {
|
|
7292
|
+
const indiId = item.value;
|
|
7293
|
+
const indi = this._gedcom?.indi(indiId);
|
|
7294
|
+
if (indi) {
|
|
7295
|
+
familyMembers.item(indiId, indi);
|
|
7296
|
+
}
|
|
7297
|
+
});
|
|
7298
|
+
return familyMembers;
|
|
6364
7299
|
}
|
|
6365
|
-
|
|
6366
|
-
|
|
6367
|
-
(item) => item.getPlaces().map((place) => {
|
|
6368
|
-
const date = place.obj?.get("DATE");
|
|
6369
|
-
if (date?.YEAR) {
|
|
6370
|
-
return `${place.place}, ${date.YEAR}`;
|
|
6371
|
-
}
|
|
6372
|
-
return `${place.place}, Unknown`;
|
|
6373
|
-
}).filter(Boolean),
|
|
6374
|
-
sort,
|
|
6375
|
-
minOccurance,
|
|
6376
|
-
"Places appearing less than 5 times"
|
|
6377
|
-
);
|
|
6378
|
-
return Object.entries(placesWithYear).reduce(
|
|
6379
|
-
(acc, [place, indis]) => {
|
|
6380
|
-
setNestedGroup(acc, place, indis, uniqueCounting);
|
|
6381
|
-
return acc;
|
|
6382
|
-
},
|
|
6383
|
-
{}
|
|
6384
|
-
);
|
|
7300
|
+
getChildren() {
|
|
7301
|
+
return this.getFamilyMembers("CHIL");
|
|
6385
7302
|
}
|
|
6386
|
-
|
|
6387
|
-
|
|
6388
|
-
(item) => item.getPlaces().map((place) => {
|
|
6389
|
-
const date = place.obj?.get("DATE");
|
|
6390
|
-
if (date?.YEAR) {
|
|
6391
|
-
return `${date.YEAR}, ${place.place}`;
|
|
6392
|
-
}
|
|
6393
|
-
return `Unknown, ${place.place}`;
|
|
6394
|
-
}).filter(Boolean),
|
|
6395
|
-
sort,
|
|
6396
|
-
minOccurance,
|
|
6397
|
-
"Places appearing less than 5 times"
|
|
6398
|
-
);
|
|
6399
|
-
return Object.entries(placesWithYear).reduce(
|
|
6400
|
-
(acc, [place, indis]) => {
|
|
6401
|
-
setNestedGroup(acc, place, indis, uniqueCounting);
|
|
6402
|
-
return acc;
|
|
6403
|
-
},
|
|
6404
|
-
{}
|
|
6405
|
-
);
|
|
7303
|
+
getHusband() {
|
|
7304
|
+
return this.getFamilyMembers("HUSB");
|
|
6406
7305
|
}
|
|
6407
|
-
|
|
6408
|
-
|
|
6409
|
-
|
|
6410
|
-
|
|
6411
|
-
|
|
6412
|
-
|
|
6413
|
-
|
|
6414
|
-
|
|
6415
|
-
return
|
|
6416
|
-
|
|
6417
|
-
|
|
6418
|
-
|
|
6419
|
-
|
|
6420
|
-
|
|
7306
|
+
getWife() {
|
|
7307
|
+
return this.getFamilyMembers("WIFE");
|
|
7308
|
+
}
|
|
7309
|
+
getParents() {
|
|
7310
|
+
return this.getHusband().copy().merge(this.getWife());
|
|
7311
|
+
}
|
|
7312
|
+
hasParent(indi) {
|
|
7313
|
+
const indiId = typeof indi === "string" ? indi : indi?.id;
|
|
7314
|
+
return !!indiId && familyHasParent(this, indiId);
|
|
7315
|
+
}
|
|
7316
|
+
hasChild(indi) {
|
|
7317
|
+
const indiId = typeof indi === "string" ? indi : indi?.id;
|
|
7318
|
+
return !!indiId && familyHasChild(this, indiId);
|
|
7319
|
+
}
|
|
7320
|
+
canAddSpouse(indi) {
|
|
7321
|
+
return canAttachAsSpouse(this, indi);
|
|
7322
|
+
}
|
|
7323
|
+
addSpouse(indi) {
|
|
7324
|
+
return attachSpouseToFamily(this, indi);
|
|
7325
|
+
}
|
|
7326
|
+
addChild(child, pedigree, parent) {
|
|
7327
|
+
return attachChildToFamily(
|
|
7328
|
+
this,
|
|
7329
|
+
child,
|
|
7330
|
+
pedigree,
|
|
7331
|
+
parent
|
|
6421
7332
|
);
|
|
6422
7333
|
}
|
|
6423
|
-
|
|
6424
|
-
return this
|
|
6425
|
-
|
|
6426
|
-
|
|
6427
|
-
|
|
6428
|
-
|
|
6429
|
-
|
|
6430
|
-
|
|
6431
|
-
|
|
6432
|
-
|
|
6433
|
-
const normalizedParts = [
|
|
6434
|
-
...leftParts,
|
|
6435
|
-
town,
|
|
6436
|
-
county,
|
|
6437
|
-
country
|
|
6438
|
-
].filter(Boolean);
|
|
6439
|
-
const orderedParts = partOrder === "original" ? normalizedParts : normalizedParts.toReversed();
|
|
6440
|
-
let newPlace = "";
|
|
6441
|
-
if (groupKeyTranslator) {
|
|
6442
|
-
newPlace = groupKeyTranslator(orderedParts);
|
|
6443
|
-
} else if (translate) {
|
|
6444
|
-
{
|
|
6445
|
-
newPlace = placeTranslator(orderedParts);
|
|
6446
|
-
}
|
|
6447
|
-
} else {
|
|
6448
|
-
newPlace = orderedParts.join(", ");
|
|
6449
|
-
}
|
|
6450
|
-
if (!newPlace) {
|
|
6451
|
-
return void 0;
|
|
6452
|
-
}
|
|
6453
|
-
return {
|
|
6454
|
-
marker: place.place,
|
|
6455
|
-
group: newPlace
|
|
6456
|
-
};
|
|
6457
|
-
}).filter(Boolean),
|
|
6458
|
-
sort,
|
|
6459
|
-
minOccurance,
|
|
6460
|
-
"Places appearing less than 5 times"
|
|
7334
|
+
addFact(input) {
|
|
7335
|
+
return addFamilyFact(this, input);
|
|
7336
|
+
}
|
|
7337
|
+
addNonEvent(input) {
|
|
7338
|
+
return addNonEvent(this, input);
|
|
7339
|
+
}
|
|
7340
|
+
toList() {
|
|
7341
|
+
return new Families().concat(
|
|
7342
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
7343
|
+
this.id ? { [this.id]: this } : { ...[this] }
|
|
6461
7344
|
);
|
|
6462
7345
|
}
|
|
6463
|
-
|
|
6464
|
-
|
|
6465
|
-
|
|
6466
|
-
|
|
6467
|
-
|
|
6468
|
-
|
|
7346
|
+
};
|
|
7347
|
+
var createFam = (gedcom, id, main, parent) => {
|
|
7348
|
+
return createProxy(
|
|
7349
|
+
new Fam(gedcom, id, main, parent)
|
|
7350
|
+
);
|
|
7351
|
+
};
|
|
7352
|
+
|
|
7353
|
+
// src/classes/fams.ts
|
|
7354
|
+
var Families = class _Families extends List {
|
|
7355
|
+
copy() {
|
|
7356
|
+
return super.copy(_Families);
|
|
7357
|
+
}
|
|
7358
|
+
except(item) {
|
|
7359
|
+
return super.except(item, _Families);
|
|
7360
|
+
}
|
|
7361
|
+
filter(filters) {
|
|
7362
|
+
return super.filter(filters, _Families);
|
|
7363
|
+
}
|
|
7364
|
+
find(filters) {
|
|
7365
|
+
return super.find(filters, _Families);
|
|
7366
|
+
}
|
|
7367
|
+
orderBy(orders) {
|
|
7368
|
+
return super.orderBy(orders, _Families);
|
|
7369
|
+
}
|
|
7370
|
+
getParents() {
|
|
7371
|
+
const persons = new Individuals();
|
|
7372
|
+
this.values().forEach((fam) => {
|
|
7373
|
+
if (fam && fam instanceof Fam) {
|
|
7374
|
+
persons.merge(fam.getParents());
|
|
6469
7375
|
}
|
|
6470
7376
|
});
|
|
6471
|
-
return
|
|
7377
|
+
return persons;
|
|
6472
7378
|
}
|
|
6473
|
-
|
|
6474
|
-
const
|
|
6475
|
-
|
|
6476
|
-
|
|
6477
|
-
|
|
6478
|
-
|
|
6479
|
-
|
|
6480
|
-
|
|
6481
|
-
|
|
6482
|
-
|
|
6483
|
-
|
|
6484
|
-
|
|
6485
|
-
|
|
6486
|
-
|
|
6487
|
-
|
|
6488
|
-
|
|
6489
|
-
|
|
6490
|
-
|
|
6491
|
-
|
|
6492
|
-
|
|
6493
|
-
|
|
6494
|
-
|
|
6495
|
-
|
|
6496
|
-
|
|
6497
|
-
|
|
6498
|
-
|
|
6499
|
-
|
|
6500
|
-
|
|
7379
|
+
getChildren() {
|
|
7380
|
+
const persons = new Individuals();
|
|
7381
|
+
this.values().forEach((fam) => {
|
|
7382
|
+
if (fam && fam instanceof Fam) {
|
|
7383
|
+
persons.merge(fam.getChildren());
|
|
7384
|
+
}
|
|
7385
|
+
});
|
|
7386
|
+
return persons;
|
|
7387
|
+
}
|
|
7388
|
+
toList() {
|
|
7389
|
+
return new _Families().concat(this.getItems());
|
|
7390
|
+
}
|
|
7391
|
+
};
|
|
7392
|
+
|
|
7393
|
+
// src/utils/gedcom-version.ts
|
|
7394
|
+
var normalizeGedcomVersion = (value) => {
|
|
7395
|
+
const trimmed = value?.trim() ?? "";
|
|
7396
|
+
if (trimmed.startsWith("7")) {
|
|
7397
|
+
return "7.0";
|
|
7398
|
+
}
|
|
7399
|
+
return "5.5.1";
|
|
7400
|
+
};
|
|
7401
|
+
var GEDZIP_GEDCOM_ENTRY = "gedcom.ged";
|
|
7402
|
+
var sanitizePathSegment = (name) => name.replace(/[^a-zA-Z0-9._-]+/g, "-").replace(/^\.+/, "") || "file";
|
|
7403
|
+
var extensionFor = (contentType) => {
|
|
7404
|
+
const raw = (contentType || "bin").replace(/^\./, "").toLowerCase();
|
|
7405
|
+
if (raw.includes("/")) {
|
|
7406
|
+
return raw.split("/").pop() || "bin";
|
|
7407
|
+
}
|
|
7408
|
+
return raw || "bin";
|
|
7409
|
+
};
|
|
7410
|
+
var rewriteGedcomFilePaths = (gedcomText, urlToPath) => {
|
|
7411
|
+
const entries = urlToPath instanceof Map ? urlToPath : new Map(Object.entries(urlToPath));
|
|
7412
|
+
let text = gedcomText;
|
|
7413
|
+
entries.forEach((path, url) => {
|
|
7414
|
+
const escaped = url.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
7415
|
+
text = text.replace(
|
|
7416
|
+
new RegExp(`(^|\\r?\\n)(\\d+ FILE )${escaped}`, "g"),
|
|
7417
|
+
`$1$2${path}`
|
|
7418
|
+
);
|
|
7419
|
+
});
|
|
7420
|
+
return text;
|
|
7421
|
+
};
|
|
7422
|
+
var assignMediaPaths = (mediaFiles) => {
|
|
7423
|
+
const urlToPath = /* @__PURE__ */ new Map();
|
|
7424
|
+
const usedPaths = /* @__PURE__ */ new Set([GEDZIP_GEDCOM_ENTRY]);
|
|
7425
|
+
const files = [];
|
|
7426
|
+
for (const file of mediaFiles) {
|
|
7427
|
+
if (!file.content || !file.url) {
|
|
7428
|
+
continue;
|
|
6501
7429
|
}
|
|
6502
|
-
const
|
|
6503
|
-
|
|
6504
|
-
|
|
7430
|
+
const ext = extensionFor(file.contentType);
|
|
7431
|
+
const base = sanitizePathSegment(
|
|
7432
|
+
file.imgId || file.title || file.id || "media"
|
|
7433
|
+
);
|
|
7434
|
+
let path = `media/${base}.${ext}`;
|
|
7435
|
+
let suffix = 1;
|
|
7436
|
+
while (usedPaths.has(path)) {
|
|
7437
|
+
path = `media/${base}-${suffix++}.${ext}`;
|
|
7438
|
+
}
|
|
7439
|
+
usedPaths.add(path);
|
|
7440
|
+
urlToPath.set(file.url, path);
|
|
7441
|
+
const marker = "base64,";
|
|
7442
|
+
const idx = file.content.indexOf(marker);
|
|
7443
|
+
if (idx >= 0) {
|
|
7444
|
+
files.push({
|
|
7445
|
+
path,
|
|
7446
|
+
url: file.url,
|
|
7447
|
+
content: file.content.substring(idx + marker.length),
|
|
7448
|
+
base64: true
|
|
7449
|
+
});
|
|
7450
|
+
} else {
|
|
7451
|
+
files.push({
|
|
7452
|
+
path,
|
|
7453
|
+
url: file.url,
|
|
7454
|
+
content: file.content,
|
|
7455
|
+
base64: false
|
|
7456
|
+
});
|
|
6505
7457
|
}
|
|
6506
|
-
return filtered.length > 0 ? filtered.index(0)?.id || true : false;
|
|
6507
7458
|
}
|
|
6508
|
-
|
|
6509
|
-
|
|
7459
|
+
return { urlToPath, files };
|
|
7460
|
+
};
|
|
7461
|
+
var buildGedzip = async (gedcomText, mediaFiles = []) => {
|
|
7462
|
+
const zip = new JSZip();
|
|
7463
|
+
const { urlToPath, files } = assignMediaPaths(mediaFiles);
|
|
7464
|
+
for (const file of files) {
|
|
7465
|
+
zip.file(file.path, file.content, { base64: file.base64 });
|
|
6510
7466
|
}
|
|
6511
|
-
|
|
6512
|
-
|
|
7467
|
+
zip.file(GEDZIP_GEDCOM_ENTRY, rewriteGedcomFilePaths(gedcomText, urlToPath));
|
|
7468
|
+
return zip.generateAsync({ type: "uint8array" });
|
|
7469
|
+
};
|
|
7470
|
+
|
|
7471
|
+
// src/utils/gedcom7-enumerations.ts
|
|
7472
|
+
var GEDCOM7_SEX_VALUES = ["M", "F", "U", "X", "N"];
|
|
7473
|
+
var GEDCOM7_PEDI_VALUES = [
|
|
7474
|
+
"adopted",
|
|
7475
|
+
"birth",
|
|
7476
|
+
"foster",
|
|
7477
|
+
"sealing"
|
|
7478
|
+
];
|
|
7479
|
+
var GEDCOM7_ROLE_VALUES = [
|
|
7480
|
+
"CHIL",
|
|
7481
|
+
"CLERGY",
|
|
7482
|
+
"FATH",
|
|
7483
|
+
"FRIEND",
|
|
7484
|
+
"GODP",
|
|
7485
|
+
"HUSB",
|
|
7486
|
+
"MOTH",
|
|
7487
|
+
"MULTIPLE",
|
|
7488
|
+
"NGHBR",
|
|
7489
|
+
"OFFICIATOR",
|
|
7490
|
+
"OTHER",
|
|
7491
|
+
"PARENT",
|
|
7492
|
+
"SPOU",
|
|
7493
|
+
"WIFE",
|
|
7494
|
+
"WITN"
|
|
7495
|
+
];
|
|
7496
|
+
var GEDCOM7_RESN_VALUES = [
|
|
7497
|
+
"CONFIDENTIAL",
|
|
7498
|
+
"LOCKED",
|
|
7499
|
+
"PRIVACY"
|
|
7500
|
+
];
|
|
7501
|
+
var isAllowed = (value, allowed) => allowed.includes(value);
|
|
7502
|
+
var moveToPhrase = (node, phrase) => {
|
|
7503
|
+
const previousValue = node.value;
|
|
7504
|
+
const previousPhrase = node.get("PHRASE");
|
|
7505
|
+
const previousPhraseValue = previousPhrase?.toValue();
|
|
7506
|
+
node.removeValue();
|
|
7507
|
+
if (previousPhrase) {
|
|
7508
|
+
previousPhrase.value = phrase;
|
|
7509
|
+
} else {
|
|
7510
|
+
const phraseNode = createCommon(node.getGedcom(), void 0, node.main);
|
|
7511
|
+
phraseNode.value = phrase;
|
|
7512
|
+
node.set("PHRASE", phraseNode);
|
|
6513
7513
|
}
|
|
6514
|
-
|
|
6515
|
-
|
|
7514
|
+
return () => {
|
|
7515
|
+
if (previousValue === void 0) {
|
|
7516
|
+
node.removeValue();
|
|
7517
|
+
} else {
|
|
7518
|
+
node.value = previousValue;
|
|
7519
|
+
}
|
|
7520
|
+
if (previousPhrase) {
|
|
7521
|
+
previousPhrase.value = previousPhraseValue;
|
|
7522
|
+
} else {
|
|
7523
|
+
node.remove("PHRASE");
|
|
7524
|
+
}
|
|
7525
|
+
};
|
|
7526
|
+
};
|
|
7527
|
+
var normalizeEnum = (node, allowed, mode, restores) => {
|
|
7528
|
+
const value = node?.toValue();
|
|
7529
|
+
if (!node || typeof value !== "string" || !value.trim()) {
|
|
7530
|
+
return;
|
|
6516
7531
|
}
|
|
6517
|
-
|
|
6518
|
-
|
|
7532
|
+
const normalized = mode === "upper" ? value.trim().toUpperCase() : value.trim().toLowerCase();
|
|
7533
|
+
if (isAllowed(normalized, allowed)) {
|
|
7534
|
+
if (value !== normalized) {
|
|
7535
|
+
const previous = node.value;
|
|
7536
|
+
node.value = normalized;
|
|
7537
|
+
restores.push(() => {
|
|
7538
|
+
node.value = previous;
|
|
7539
|
+
});
|
|
7540
|
+
}
|
|
7541
|
+
return;
|
|
6519
7542
|
}
|
|
6520
|
-
|
|
6521
|
-
|
|
7543
|
+
restores.push(moveToPhrase(node, value.trim()));
|
|
7544
|
+
};
|
|
7545
|
+
var applyGedcom7Enumerations = (gedcom) => {
|
|
7546
|
+
const restores = [];
|
|
7547
|
+
gedcom.indis()?.forEach((indi) => {
|
|
7548
|
+
if (!indi) return;
|
|
7549
|
+
normalizeEnum(indi.get("SEX"), GEDCOM7_SEX_VALUES, "upper", restores);
|
|
7550
|
+
normalizeEnum(indi.get("RESN"), GEDCOM7_RESN_VALUES, "upper", restores);
|
|
7551
|
+
indi.get("FAMC")?.toList()?.forEach((famc) => {
|
|
7552
|
+
normalizeEnum(
|
|
7553
|
+
famc?.get("PEDI") ?? famc?.get("PEDT"),
|
|
7554
|
+
GEDCOM7_PEDI_VALUES,
|
|
7555
|
+
"lower",
|
|
7556
|
+
restores
|
|
7557
|
+
);
|
|
7558
|
+
});
|
|
7559
|
+
indi.get("ASSO")?.toList()?.forEach((asso) => {
|
|
7560
|
+
normalizeEnum(
|
|
7561
|
+
asso?.get("ROLE"),
|
|
7562
|
+
GEDCOM7_ROLE_VALUES,
|
|
7563
|
+
"upper",
|
|
7564
|
+
restores
|
|
7565
|
+
);
|
|
7566
|
+
});
|
|
7567
|
+
});
|
|
7568
|
+
gedcom.fams()?.forEach((fam) => {
|
|
7569
|
+
if (!fam) return;
|
|
7570
|
+
normalizeEnum(fam.get("RESN"), GEDCOM7_RESN_VALUES, "upper", restores);
|
|
7571
|
+
fam.get("ASSO")?.toList()?.forEach((asso) => {
|
|
7572
|
+
normalizeEnum(
|
|
7573
|
+
asso?.get("ROLE"),
|
|
7574
|
+
GEDCOM7_ROLE_VALUES,
|
|
7575
|
+
"upper",
|
|
7576
|
+
restores
|
|
7577
|
+
);
|
|
7578
|
+
});
|
|
7579
|
+
});
|
|
7580
|
+
return () => {
|
|
7581
|
+
for (let i = restores.length - 1; i >= 0; i -= 1) {
|
|
7582
|
+
restores[i]?.();
|
|
7583
|
+
}
|
|
7584
|
+
};
|
|
7585
|
+
};
|
|
7586
|
+
|
|
7587
|
+
// src/utils/gedcom7-dates.ts
|
|
7588
|
+
var GEDCOM7_CALENDARS = [
|
|
7589
|
+
"GREGORIAN",
|
|
7590
|
+
"JULIAN",
|
|
7591
|
+
"FRENCH_R",
|
|
7592
|
+
"HEBREW"
|
|
7593
|
+
];
|
|
7594
|
+
var CALENDAR_PREFIX2 = /^(?<calendar>GREGORIAN|JULIAN|FRENCH_R|HEBREW)\b\s+/i;
|
|
7595
|
+
var parseGedcom7CalendarPrefix = (value) => {
|
|
7596
|
+
const match = value.match(CALENDAR_PREFIX2);
|
|
7597
|
+
if (!match?.groups?.calendar) {
|
|
7598
|
+
return { calendar: void 0, rest: value };
|
|
6522
7599
|
}
|
|
6523
|
-
|
|
6524
|
-
|
|
7600
|
+
return {
|
|
7601
|
+
calendar: match.groups.calendar.toUpperCase(),
|
|
7602
|
+
rest: value.slice(match[0].length)
|
|
7603
|
+
};
|
|
7604
|
+
};
|
|
7605
|
+
var withGedcom7Calendar = (value, calendar) => {
|
|
7606
|
+
if (!calendar || calendar.toUpperCase() === "GREGORIAN") {
|
|
7607
|
+
return value;
|
|
6525
7608
|
}
|
|
6526
|
-
|
|
6527
|
-
|
|
6528
|
-
const
|
|
6529
|
-
|
|
6530
|
-
|
|
6531
|
-
|
|
6532
|
-
|
|
6533
|
-
|
|
6534
|
-
|
|
6535
|
-
|
|
6536
|
-
|
|
6537
|
-
|
|
6538
|
-
|
|
6539
|
-
|
|
6540
|
-
|
|
6541
|
-
|
|
6542
|
-
|
|
6543
|
-
|
|
7609
|
+
const upper = calendar.toUpperCase();
|
|
7610
|
+
if (GEDCOM7_CALENDARS.includes(upper)) {
|
|
7611
|
+
const { rest } = parseGedcom7CalendarPrefix(value);
|
|
7612
|
+
return `${upper} ${rest}`.trim();
|
|
7613
|
+
}
|
|
7614
|
+
return value;
|
|
7615
|
+
};
|
|
7616
|
+
var applyGedcom7DatePhrases = (gedcom) => {
|
|
7617
|
+
const restores = [];
|
|
7618
|
+
const visitDate = (dateNode) => {
|
|
7619
|
+
if (!dateNode || typeof dateNode.toValue !== "function") {
|
|
7620
|
+
return;
|
|
7621
|
+
}
|
|
7622
|
+
const asDate = dateNode;
|
|
7623
|
+
const hasComponents = !!(asDate.DAY || asDate.MONTH || asDate.YEAR);
|
|
7624
|
+
const raw = dateNode.exportValue?.() ?? dateNode.toValue();
|
|
7625
|
+
if (typeof raw !== "string" || !raw.trim()) {
|
|
7626
|
+
return;
|
|
7627
|
+
}
|
|
7628
|
+
const { calendar, rest } = parseGedcom7CalendarPrefix(raw.trim());
|
|
7629
|
+
const looksStructured = hasComponents || /^(ABT|CAL|EST|BEF|AFT|FROM|TO|BET|INT)(\s|$)/i.test(rest) || /\bAND\b/i.test(rest) || /^\d{1,2}\s+[A-Z]{3}\s+\d{1,4}/i.test(rest) || /^[A-Z]{3}\s+\d{1,4}/i.test(rest) || /^\d{1,4}$/.test(rest);
|
|
7630
|
+
if (looksStructured) {
|
|
7631
|
+
if (calendar && calendar !== "GREGORIAN") {
|
|
7632
|
+
const previous = dateNode.value;
|
|
7633
|
+
const next = withGedcom7Calendar(rest, calendar);
|
|
7634
|
+
if (previous !== next) {
|
|
7635
|
+
dateNode.value = next;
|
|
7636
|
+
restores.push(() => {
|
|
7637
|
+
dateNode.value = previous;
|
|
7638
|
+
});
|
|
7639
|
+
}
|
|
6544
7640
|
}
|
|
6545
|
-
|
|
6546
|
-
|
|
6547
|
-
|
|
6548
|
-
|
|
6549
|
-
|
|
7641
|
+
return;
|
|
7642
|
+
}
|
|
7643
|
+
const previousValue = dateNode.value;
|
|
7644
|
+
const previousPhrase = dateNode.get("PHRASE");
|
|
7645
|
+
const previousPhraseValue = previousPhrase?.toValue();
|
|
7646
|
+
dateNode.removeValue();
|
|
7647
|
+
if (previousPhrase) {
|
|
7648
|
+
previousPhrase.value = raw.trim();
|
|
7649
|
+
} else {
|
|
7650
|
+
const phrase = createCommon(
|
|
7651
|
+
dateNode.getGedcom(),
|
|
7652
|
+
void 0,
|
|
7653
|
+
dateNode.main
|
|
6550
7654
|
);
|
|
6551
|
-
|
|
6552
|
-
|
|
6553
|
-
const famKey = fKey;
|
|
6554
|
-
if (familiesRelativeTo && !familiesRelativeTo.includes(famKey)) {
|
|
6555
|
-
return;
|
|
6556
|
-
}
|
|
6557
|
-
const missingChildren = relativeTo.getGedcom()?.fam(famKey)?.getChildren();
|
|
6558
|
-
if (!splittedList[famKey] && missingChildren?.length) {
|
|
6559
|
-
splittedList[famKey] = new _Individuals();
|
|
6560
|
-
}
|
|
6561
|
-
});
|
|
6562
|
-
}
|
|
7655
|
+
phrase.value = raw.trim();
|
|
7656
|
+
dateNode.set("PHRASE", phrase);
|
|
6563
7657
|
}
|
|
6564
|
-
|
|
6565
|
-
|
|
6566
|
-
|
|
6567
|
-
|
|
6568
|
-
|
|
6569
|
-
}
|
|
6570
|
-
getRelativesOnDegree(degree = 0) {
|
|
6571
|
-
const persons = new _Individuals();
|
|
6572
|
-
this.values().forEach((indi) => {
|
|
6573
|
-
if (indi) {
|
|
6574
|
-
persons.merge(indi.getRelativesOnLevel(degree));
|
|
7658
|
+
restores.push(() => {
|
|
7659
|
+
if (previousValue === void 0) {
|
|
7660
|
+
dateNode.removeValue();
|
|
7661
|
+
} else {
|
|
7662
|
+
dateNode.value = previousValue;
|
|
6575
7663
|
}
|
|
6576
|
-
|
|
6577
|
-
|
|
6578
|
-
|
|
6579
|
-
|
|
6580
|
-
const persons = new _Individuals();
|
|
6581
|
-
this.values().forEach((indi) => {
|
|
6582
|
-
if (indi) {
|
|
6583
|
-
persons.merge(indi.getRelativesOnLevel(level, filter));
|
|
7664
|
+
if (previousPhrase) {
|
|
7665
|
+
previousPhrase.value = previousPhraseValue;
|
|
7666
|
+
} else {
|
|
7667
|
+
dateNode.remove("PHRASE");
|
|
6584
7668
|
}
|
|
6585
7669
|
});
|
|
6586
|
-
|
|
6587
|
-
|
|
6588
|
-
|
|
6589
|
-
|
|
6590
|
-
|
|
6591
|
-
|
|
6592
|
-
|
|
6593
|
-
|
|
7670
|
+
};
|
|
7671
|
+
const walk = (node) => {
|
|
7672
|
+
if (!node) return;
|
|
7673
|
+
node.get("DATE")?.toList()?.forEach((item) => visitDate(item));
|
|
7674
|
+
node.get("SDATE")?.toList()?.forEach((item) => visitDate(item));
|
|
7675
|
+
};
|
|
7676
|
+
gedcom.indis()?.forEach((indi) => {
|
|
7677
|
+
if (!indi) return;
|
|
7678
|
+
walk(indi);
|
|
7679
|
+
[
|
|
7680
|
+
"BIRT",
|
|
7681
|
+
"DEAT",
|
|
7682
|
+
"CHR",
|
|
7683
|
+
"BAPM",
|
|
7684
|
+
"BURI",
|
|
7685
|
+
"CREM",
|
|
7686
|
+
"ADOP",
|
|
7687
|
+
"EVEN",
|
|
7688
|
+
"RESI",
|
|
7689
|
+
"OCCU",
|
|
7690
|
+
"MARR"
|
|
7691
|
+
].forEach((tag) => {
|
|
7692
|
+
indi.get(tag)?.toList()?.forEach((event) => walk(event));
|
|
6594
7693
|
});
|
|
6595
|
-
|
|
6596
|
-
|
|
6597
|
-
|
|
6598
|
-
|
|
6599
|
-
|
|
6600
|
-
if (indi) {
|
|
6601
|
-
persons.merge(indi.getDescendants(level, filter));
|
|
6602
|
-
}
|
|
7694
|
+
});
|
|
7695
|
+
gedcom.fams()?.forEach((fam) => {
|
|
7696
|
+
if (!fam) return;
|
|
7697
|
+
["MARR", "DIV", "ENGA", "ANUL", "EVEN"].forEach((tag) => {
|
|
7698
|
+
fam.get(tag)?.toList()?.forEach((event) => walk(event));
|
|
6603
7699
|
});
|
|
6604
|
-
|
|
7700
|
+
});
|
|
7701
|
+
return () => {
|
|
7702
|
+
for (let i = restores.length - 1; i >= 0; i -= 1) {
|
|
7703
|
+
restores[i]?.();
|
|
7704
|
+
}
|
|
7705
|
+
};
|
|
7706
|
+
};
|
|
7707
|
+
|
|
7708
|
+
// src/utils/uid.ts
|
|
7709
|
+
var createGedcomUid = () => {
|
|
7710
|
+
const cryptoObj = typeof globalThis !== "undefined" ? globalThis.crypto : void 0;
|
|
7711
|
+
if (cryptoObj && typeof cryptoObj.randomUUID === "function") {
|
|
7712
|
+
return cryptoObj.randomUUID();
|
|
7713
|
+
}
|
|
7714
|
+
return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (char) => {
|
|
7715
|
+
const rand = Math.random() * 16 | 0;
|
|
7716
|
+
const value = char === "x" ? rand : rand & 3 | 8;
|
|
7717
|
+
return value.toString(16);
|
|
7718
|
+
});
|
|
7719
|
+
};
|
|
7720
|
+
|
|
7721
|
+
// src/utils/gedcom7-metadata.ts
|
|
7722
|
+
var GEDCOM_MONTHS2 = [
|
|
7723
|
+
"JAN",
|
|
7724
|
+
"FEB",
|
|
7725
|
+
"MAR",
|
|
7726
|
+
"APR",
|
|
7727
|
+
"MAY",
|
|
7728
|
+
"JUN",
|
|
7729
|
+
"JUL",
|
|
7730
|
+
"AUG",
|
|
7731
|
+
"SEP",
|
|
7732
|
+
"OCT",
|
|
7733
|
+
"NOV",
|
|
7734
|
+
"DEC"
|
|
7735
|
+
];
|
|
7736
|
+
var formatGedcom7Timestamp = (date = /* @__PURE__ */ new Date()) => {
|
|
7737
|
+
const day = String(date.getUTCDate());
|
|
7738
|
+
const month = GEDCOM_MONTHS2[date.getUTCMonth()];
|
|
7739
|
+
const year = String(date.getUTCFullYear());
|
|
7740
|
+
const hh = String(date.getUTCHours()).padStart(2, "0");
|
|
7741
|
+
const mm = String(date.getUTCMinutes()).padStart(2, "0");
|
|
7742
|
+
const ss = String(date.getUTCSeconds()).padStart(2, "0");
|
|
7743
|
+
return {
|
|
7744
|
+
date: `${day} ${month} ${year}`,
|
|
7745
|
+
time: `${hh}:${mm}:${ss}Z`
|
|
7746
|
+
};
|
|
7747
|
+
};
|
|
7748
|
+
var ensureMetaDate = (gedcom, record, tag, when, restores) => {
|
|
7749
|
+
if (record.get(tag)) {
|
|
7750
|
+
return;
|
|
6605
7751
|
}
|
|
6606
|
-
|
|
6607
|
-
|
|
6608
|
-
|
|
6609
|
-
|
|
6610
|
-
|
|
6611
|
-
|
|
6612
|
-
|
|
6613
|
-
|
|
7752
|
+
const { date, time } = formatGedcom7Timestamp(when);
|
|
7753
|
+
const meta = createCommon(gedcom, void 0, record);
|
|
7754
|
+
meta.type = tag;
|
|
7755
|
+
const dateNode = createCommonDate(gedcom, void 0, record, meta);
|
|
7756
|
+
dateNode.type = "DATE";
|
|
7757
|
+
dateNode.value = date;
|
|
7758
|
+
dateNode.set("TIME", time);
|
|
7759
|
+
meta.set("DATE", dateNode);
|
|
7760
|
+
record.set(tag, meta);
|
|
7761
|
+
restores.push(() => {
|
|
7762
|
+
record.remove(tag);
|
|
7763
|
+
});
|
|
7764
|
+
};
|
|
7765
|
+
var ensureUid = (record, restores) => {
|
|
7766
|
+
const existing = record.get("UID")?.toValue();
|
|
7767
|
+
if (typeof existing === "string" && existing.trim()) {
|
|
7768
|
+
return;
|
|
6614
7769
|
}
|
|
6615
|
-
|
|
6616
|
-
|
|
6617
|
-
|
|
6618
|
-
|
|
6619
|
-
|
|
6620
|
-
|
|
6621
|
-
|
|
6622
|
-
|
|
6623
|
-
|
|
6624
|
-
|
|
7770
|
+
const uid = createGedcomUid();
|
|
7771
|
+
record.set("UID", uid);
|
|
7772
|
+
restores.push(() => {
|
|
7773
|
+
record.remove("UID");
|
|
7774
|
+
});
|
|
7775
|
+
};
|
|
7776
|
+
var applyGedcom7RecordMetadata = (gedcom, options) => {
|
|
7777
|
+
const restores = [];
|
|
7778
|
+
const now = /* @__PURE__ */ new Date();
|
|
7779
|
+
const visit = (record) => {
|
|
7780
|
+
if (!record?.id) {
|
|
7781
|
+
return;
|
|
7782
|
+
}
|
|
7783
|
+
ensureUid(record, restores);
|
|
7784
|
+
ensureMetaDate(gedcom, record, "CREA", now, restores);
|
|
7785
|
+
ensureMetaDate(gedcom, record, "CHAN", now, restores);
|
|
7786
|
+
};
|
|
7787
|
+
gedcom.indis()?.forEach((indi) => visit(indi));
|
|
7788
|
+
gedcom.fams()?.forEach((fam) => visit(fam));
|
|
7789
|
+
gedcom.objes()?.forEach((obje) => visit(obje));
|
|
7790
|
+
gedcom.sours()?.forEach((sour) => visit(sour));
|
|
7791
|
+
gedcom.repos()?.forEach((repo) => visit(repo));
|
|
7792
|
+
gedcom.subms()?.forEach((subm) => visit(subm));
|
|
7793
|
+
gedcom.snotes()?.forEach((note) => visit(note));
|
|
7794
|
+
return () => {
|
|
7795
|
+
for (let i = restores.length - 1; i >= 0; i -= 1) {
|
|
7796
|
+
restores[i]?.();
|
|
7797
|
+
}
|
|
7798
|
+
};
|
|
7799
|
+
};
|
|
7800
|
+
|
|
7801
|
+
// src/utils/gedcom7-schema.ts
|
|
7802
|
+
var TREEVIZ_EXTENSION_BASE_URI = "https://treeviz.com/gedcom";
|
|
7803
|
+
var TREEVIZ_EXTENSION_URIS = {
|
|
7804
|
+
_ORIGHEAD: `${TREEVIZ_EXTENSION_BASE_URI}#_ORIGHEAD`,
|
|
7805
|
+
_TREE: `${TREEVIZ_EXTENSION_BASE_URI}#_TREE`,
|
|
7806
|
+
_TID: `${TREEVIZ_EXTENSION_BASE_URI}#_TID`,
|
|
7807
|
+
_PRIM: `${TREEVIZ_EXTENSION_BASE_URI}#_PRIM`,
|
|
7808
|
+
_FREL: `${TREEVIZ_EXTENSION_BASE_URI}#_FREL`,
|
|
7809
|
+
_MREL: `${TREEVIZ_EXTENSION_BASE_URI}#_MREL`,
|
|
7810
|
+
_SREL: `${TREEVIZ_EXTENSION_BASE_URI}#_SREL`,
|
|
7811
|
+
_UID: `${TREEVIZ_EXTENSION_BASE_URI}#_UID`,
|
|
7812
|
+
_WLNK: `${TREEVIZ_EXTENSION_BASE_URI}#_WLNK`,
|
|
7813
|
+
_MTTAG: `${TREEVIZ_EXTENSION_BASE_URI}#_MTTAG`,
|
|
7814
|
+
_MTCAT: `${TREEVIZ_EXTENSION_BASE_URI}#_MTCAT`,
|
|
7815
|
+
_CLON: `${TREEVIZ_EXTENSION_BASE_URI}#_CLON`,
|
|
7816
|
+
_MSER: `${TREEVIZ_EXTENSION_BASE_URI}#_MSER`,
|
|
7817
|
+
_OID: `${TREEVIZ_EXTENSION_BASE_URI}#_OID`,
|
|
7818
|
+
_LKID: `${TREEVIZ_EXTENSION_BASE_URI}#_LKID`,
|
|
7819
|
+
_PHOTO_RIN: `${TREEVIZ_EXTENSION_BASE_URI}#_PHOTO_RIN`,
|
|
7820
|
+
_EXPORTED_FROM_SITE_ID: `${TREEVIZ_EXTENSION_BASE_URI}#_EXPORTED_FROM_SITE_ID`,
|
|
7821
|
+
_FS_ID: `${TREEVIZ_EXTENSION_BASE_URI}#_FS_ID`,
|
|
7822
|
+
_FS_LINK: `${TREEVIZ_EXTENSION_BASE_URI}#_FS_LINK`,
|
|
7823
|
+
_FS_MATCH: `${TREEVIZ_EXTENSION_BASE_URI}#_FS_MATCH`,
|
|
7824
|
+
_FS_SOUR: `${TREEVIZ_EXTENSION_BASE_URI}#_FS_SOUR`,
|
|
7825
|
+
_IS_FS: `${TREEVIZ_EXTENSION_BASE_URI}#_IS_FS`,
|
|
7826
|
+
_LABEL: `${TREEVIZ_EXTENSION_BASE_URI}#_LABEL`,
|
|
7827
|
+
_MILT: `${TREEVIZ_EXTENSION_BASE_URI}#_MILT`,
|
|
7828
|
+
_MILTID: `${TREEVIZ_EXTENSION_BASE_URI}#_MILTID`,
|
|
7829
|
+
_ORIG: `${TREEVIZ_EXTENSION_BASE_URI}#_ORIG`,
|
|
7830
|
+
_ENV: `${TREEVIZ_EXTENSION_BASE_URI}#_ENV`,
|
|
7831
|
+
_TREEVIZ_SETTINGS: `${TREEVIZ_EXTENSION_BASE_URI}#_TREEVIZ_SETTINGS`,
|
|
7832
|
+
_TREEVIZ_VIEW: `${TREEVIZ_EXTENSION_BASE_URI}#_TREEVIZ_VIEW`,
|
|
7833
|
+
_TREEVIZ_DETECTIVE: `${TREEVIZ_EXTENSION_BASE_URI}#_TREEVIZ_DETECTIVE`,
|
|
7834
|
+
_TREEVIZ_DETECTIVE_STATE: `${TREEVIZ_EXTENSION_BASE_URI}#_TREEVIZ_DETECTIVE_STATE`
|
|
7835
|
+
};
|
|
7836
|
+
var parseTagDefinition = (payload) => {
|
|
7837
|
+
const trimmed = payload.trim();
|
|
7838
|
+
const space = trimmed.indexOf(" ");
|
|
7839
|
+
if (space <= 0) {
|
|
7840
|
+
return void 0;
|
|
6625
7841
|
}
|
|
6626
|
-
|
|
6627
|
-
|
|
6628
|
-
|
|
6629
|
-
|
|
6630
|
-
persons.merge(indi.getSiblings());
|
|
6631
|
-
}
|
|
6632
|
-
});
|
|
6633
|
-
return persons;
|
|
7842
|
+
const tag = trimmed.slice(0, space).trim();
|
|
7843
|
+
const uri = trimmed.slice(space + 1).trim();
|
|
7844
|
+
if (!tag || !uri) {
|
|
7845
|
+
return void 0;
|
|
6634
7846
|
}
|
|
6635
|
-
|
|
6636
|
-
|
|
6637
|
-
|
|
6638
|
-
|
|
6639
|
-
|
|
6640
|
-
|
|
6641
|
-
|
|
6642
|
-
return persons;
|
|
7847
|
+
return { tag, uri };
|
|
7848
|
+
};
|
|
7849
|
+
var getExtensionSchema = (gedcom) => {
|
|
7850
|
+
const map = /* @__PURE__ */ new Map();
|
|
7851
|
+
const schma = gedcom.get("HEAD")?.get("SCHMA");
|
|
7852
|
+
if (!schma) {
|
|
7853
|
+
return map;
|
|
6643
7854
|
}
|
|
6644
|
-
|
|
6645
|
-
const
|
|
6646
|
-
|
|
6647
|
-
|
|
6648
|
-
|
|
6649
|
-
|
|
6650
|
-
|
|
6651
|
-
|
|
7855
|
+
schma.get("TAG")?.toList()?.forEach((tagNode) => {
|
|
7856
|
+
const payload = tagNode?.toValue();
|
|
7857
|
+
if (typeof payload !== "string") {
|
|
7858
|
+
return;
|
|
7859
|
+
}
|
|
7860
|
+
const parsed = parseTagDefinition(payload);
|
|
7861
|
+
if (parsed) {
|
|
7862
|
+
map.set(parsed.tag.toUpperCase(), parsed.uri);
|
|
7863
|
+
}
|
|
7864
|
+
});
|
|
7865
|
+
return map;
|
|
7866
|
+
};
|
|
7867
|
+
var ensureSchemaNode = (gedcom) => {
|
|
7868
|
+
const head = gedcom.get("HEAD");
|
|
7869
|
+
if (!head) {
|
|
7870
|
+
return void 0;
|
|
6652
7871
|
}
|
|
6653
|
-
|
|
6654
|
-
|
|
6655
|
-
|
|
6656
|
-
|
|
6657
|
-
|
|
7872
|
+
let schma = head.get("SCHMA");
|
|
7873
|
+
if (!schma) {
|
|
7874
|
+
schma = createCommon(gedcom, void 0, head);
|
|
7875
|
+
head.set("SCHMA", schma);
|
|
7876
|
+
}
|
|
7877
|
+
return schma;
|
|
7878
|
+
};
|
|
7879
|
+
var registerExtensionTag = (gedcom, tag, uri) => {
|
|
7880
|
+
const normalizedTag = tag.trim().toUpperCase();
|
|
7881
|
+
const normalizedUri = uri.trim();
|
|
7882
|
+
if (!normalizedTag.startsWith("_") || !normalizedUri) {
|
|
7883
|
+
return void 0;
|
|
7884
|
+
}
|
|
7885
|
+
const schma = ensureSchemaNode(gedcom);
|
|
7886
|
+
if (!schma) {
|
|
7887
|
+
return void 0;
|
|
7888
|
+
}
|
|
7889
|
+
const payload = `${normalizedTag} ${normalizedUri}`;
|
|
7890
|
+
const existingList = schma.get("TAG")?.toList();
|
|
7891
|
+
const existing = existingList?.values().find((node) => {
|
|
7892
|
+
const value = node?.toValue();
|
|
7893
|
+
return typeof value === "string" && value.trim().toUpperCase().startsWith(`${normalizedTag} `);
|
|
7894
|
+
});
|
|
7895
|
+
if (existing) {
|
|
7896
|
+
existing.value = payload;
|
|
7897
|
+
return existing;
|
|
7898
|
+
}
|
|
7899
|
+
const tagNode = createCommon(gedcom, void 0, schma);
|
|
7900
|
+
tagNode.value = payload;
|
|
7901
|
+
schma.assign("TAG", tagNode);
|
|
7902
|
+
return tagNode;
|
|
7903
|
+
};
|
|
7904
|
+
var ensureExtensionSchema = (gedcom, extraTags) => {
|
|
7905
|
+
const head = gedcom.get("HEAD");
|
|
7906
|
+
const hadSchma = !!head?.get("SCHMA");
|
|
7907
|
+
const previousPayloads = head?.get("SCHMA")?.get("TAG")?.toList()?.values().map((node) => ({
|
|
7908
|
+
node,
|
|
7909
|
+
value: node?.toValue()
|
|
7910
|
+
})) ?? [];
|
|
7911
|
+
const tags = /* @__PURE__ */ new Set([
|
|
7912
|
+
...Object.keys(TREEVIZ_EXTENSION_URIS),
|
|
7913
|
+
...(extraTags ?? []).map((tag) => tag.toUpperCase())
|
|
7914
|
+
]);
|
|
7915
|
+
tags.forEach((tag) => {
|
|
7916
|
+
const uri = TREEVIZ_EXTENSION_URIS[tag] ?? `${TREEVIZ_EXTENSION_BASE_URI}#${tag}`;
|
|
7917
|
+
if (tag.startsWith("_")) {
|
|
7918
|
+
registerExtensionTag(gedcom, tag, uri);
|
|
7919
|
+
}
|
|
7920
|
+
});
|
|
7921
|
+
return () => {
|
|
7922
|
+
if (!head) {
|
|
7923
|
+
return;
|
|
7924
|
+
}
|
|
7925
|
+
if (!hadSchma) {
|
|
7926
|
+
head.remove("SCHMA");
|
|
7927
|
+
return;
|
|
7928
|
+
}
|
|
7929
|
+
const schma = head.get("SCHMA");
|
|
7930
|
+
const list = schma?.get("TAG")?.toList();
|
|
7931
|
+
const keep = new Set(
|
|
7932
|
+
previousPayloads.map(
|
|
7933
|
+
(item) => typeof item.value === "string" ? item.value : void 0
|
|
7934
|
+
).filter((value) => !!value)
|
|
7935
|
+
);
|
|
7936
|
+
list?.values().forEach((node) => {
|
|
7937
|
+
const value = node?.toValue();
|
|
7938
|
+
if (typeof value === "string" && !keep.has(value) && node) {
|
|
7939
|
+
list.delete(node);
|
|
6658
7940
|
}
|
|
6659
7941
|
});
|
|
6660
|
-
|
|
6661
|
-
|
|
6662
|
-
|
|
6663
|
-
const persons = new _Individuals();
|
|
6664
|
-
this.values().forEach((indi) => {
|
|
6665
|
-
if (indi) {
|
|
6666
|
-
persons.merge(indi.getCoParents());
|
|
7942
|
+
previousPayloads.forEach(({ node, value }) => {
|
|
7943
|
+
if (node && value !== void 0) {
|
|
7944
|
+
node.value = value;
|
|
6667
7945
|
}
|
|
6668
7946
|
});
|
|
6669
|
-
|
|
6670
|
-
|
|
6671
|
-
|
|
6672
|
-
|
|
7947
|
+
};
|
|
7948
|
+
};
|
|
7949
|
+
|
|
7950
|
+
// package.json
|
|
7951
|
+
var package_default = {
|
|
7952
|
+
version: "2.1.0"};
|
|
7953
|
+
|
|
7954
|
+
// src/utils/get-product-details.ts
|
|
7955
|
+
var isDevelopment = () => {
|
|
7956
|
+
return !process.env.NODE_ENV || process.env.NODE_ENV === "development";
|
|
7957
|
+
};
|
|
7958
|
+
var getVersion = () => package_default.version;
|
|
7959
|
+
|
|
7960
|
+
// src/utils/multimedia.ts
|
|
7961
|
+
var inferMediaForm = (file, fallback = "bin") => {
|
|
7962
|
+
const withoutQuery = file.split("?")[0] || file;
|
|
7963
|
+
const ext = getFileExtension(withoutQuery);
|
|
7964
|
+
if (ext) {
|
|
7965
|
+
return ext.toLowerCase() === "jpeg" ? "jpg" : ext.toLowerCase();
|
|
6673
7966
|
}
|
|
6674
|
-
|
|
6675
|
-
|
|
7967
|
+
return fallback;
|
|
7968
|
+
};
|
|
7969
|
+
var mergeMediaLists = (...lists) => {
|
|
7970
|
+
const merged = {};
|
|
7971
|
+
for (const list of lists) {
|
|
7972
|
+
if (!list) continue;
|
|
7973
|
+
Object.assign(merged, list);
|
|
6676
7974
|
}
|
|
7975
|
+
return merged;
|
|
6677
7976
|
};
|
|
6678
7977
|
|
|
6679
|
-
// src/classes/
|
|
6680
|
-
var
|
|
6681
|
-
|
|
6682
|
-
|
|
6683
|
-
|
|
6684
|
-
|
|
6685
|
-
|
|
6686
|
-
if (indi) {
|
|
6687
|
-
familyMembers.item(indiId, indi);
|
|
6688
|
-
}
|
|
6689
|
-
});
|
|
6690
|
-
return familyMembers;
|
|
6691
|
-
}
|
|
6692
|
-
getChildren() {
|
|
6693
|
-
return this.getFamilyMembers("CHIL");
|
|
7978
|
+
// src/classes/note.ts
|
|
7979
|
+
var CommonNote = class extends Common {
|
|
7980
|
+
constructor(gedcom, id, main, parent) {
|
|
7981
|
+
super(gedcom, id, main, parent);
|
|
7982
|
+
if (!id) {
|
|
7983
|
+
delete this.id;
|
|
7984
|
+
}
|
|
6694
7985
|
}
|
|
6695
|
-
|
|
6696
|
-
|
|
7986
|
+
set value(value) {
|
|
7987
|
+
const [note, ...contents] = value?.split(/\r?\n/) ?? [];
|
|
7988
|
+
this._value = note;
|
|
7989
|
+
if (contents.length) {
|
|
7990
|
+
const newContents = new List();
|
|
7991
|
+
contents.forEach((c, i) => {
|
|
7992
|
+
const newContent = createCommon(
|
|
7993
|
+
this._gedcom,
|
|
7994
|
+
void 0,
|
|
7995
|
+
this.main
|
|
7996
|
+
);
|
|
7997
|
+
newContent.id = `@U${i}@`;
|
|
7998
|
+
newContent.value = c;
|
|
7999
|
+
newContents.append(newContent);
|
|
8000
|
+
});
|
|
8001
|
+
const firstItem = newContents.index(0);
|
|
8002
|
+
if (firstItem) {
|
|
8003
|
+
if (newContents.length === 1) {
|
|
8004
|
+
this.set("CONT", firstItem);
|
|
8005
|
+
} else {
|
|
8006
|
+
this.set("CONT", newContents);
|
|
8007
|
+
}
|
|
8008
|
+
}
|
|
8009
|
+
}
|
|
6697
8010
|
}
|
|
6698
|
-
|
|
6699
|
-
|
|
8011
|
+
get value() {
|
|
8012
|
+
const contents = this.get("CONT")?.toList().map((content) => content.value).join("\n");
|
|
8013
|
+
if (contents) {
|
|
8014
|
+
return `${this._value}
|
|
8015
|
+
${contents}`;
|
|
8016
|
+
}
|
|
8017
|
+
return this._value;
|
|
6700
8018
|
}
|
|
6701
|
-
|
|
6702
|
-
return this.
|
|
8019
|
+
exportValue() {
|
|
8020
|
+
return this._value;
|
|
6703
8021
|
}
|
|
6704
|
-
|
|
6705
|
-
|
|
6706
|
-
|
|
6707
|
-
|
|
8022
|
+
};
|
|
8023
|
+
var createCommonNote = (gedcom, id, main, parent) => {
|
|
8024
|
+
return createProxy(
|
|
8025
|
+
new CommonNote(gedcom, id, main, parent)
|
|
8026
|
+
);
|
|
8027
|
+
};
|
|
8028
|
+
|
|
8029
|
+
// src/classes/obje.ts
|
|
8030
|
+
var Obje = class extends Common {
|
|
8031
|
+
standardizeMedia(namespace, override = true, urlGetter, gedcomVersion) {
|
|
8032
|
+
if (!this._gedcom) {
|
|
8033
|
+
return this;
|
|
8034
|
+
}
|
|
8035
|
+
const rin = this?.get("RIN")?.toValue();
|
|
8036
|
+
const clone = this?.get("_CLON._OID")?.toValue();
|
|
8037
|
+
const mser = this?.get("_MSER._LKID")?.toValue();
|
|
8038
|
+
const title = this?.get("FILE.TITL")?.toValue() ?? this?.get("TITL")?.toValue() ?? "";
|
|
8039
|
+
const note = this?.get("FILE.NOTE")?.toValue() ?? this?.get("NOTE")?.toValue() ?? "";
|
|
8040
|
+
const formRaw = this?.get("FILE.FORM")?.toValue() ?? this?.get("FORM")?.toValue();
|
|
8041
|
+
const mediType = this?.get("FILE.FORM.TYPE")?.toValue() ?? this?.get("FORM.TYPE")?.toValue() ?? this?.get("MEDI")?.toValue();
|
|
8042
|
+
const file = this?.get("FILE")?.toValue();
|
|
8043
|
+
const imgId = rin || clone || mser;
|
|
8044
|
+
const url = file || namespace && urlGetter?.(namespace, imgId);
|
|
8045
|
+
if (!url) {
|
|
8046
|
+
return this;
|
|
8047
|
+
}
|
|
8048
|
+
const version = normalizeGedcomVersion(
|
|
8049
|
+
gedcomVersion ?? this._gedcom.getGedcomVersion?.()
|
|
6708
8050
|
);
|
|
8051
|
+
const form = formRaw || inferMediaForm(String(url));
|
|
8052
|
+
const newObject = createObje(this._gedcom, this.id, this.main);
|
|
8053
|
+
if (!override) {
|
|
8054
|
+
Object.assign(newObject, this);
|
|
8055
|
+
}
|
|
8056
|
+
const fileNode = createCommon(this._gedcom, void 0, this.main);
|
|
8057
|
+
fileNode.value = url;
|
|
8058
|
+
if (version === "7.0") {
|
|
8059
|
+
const formNode = createCommon(this._gedcom, void 0, fileNode);
|
|
8060
|
+
formNode.value = form;
|
|
8061
|
+
if (mediType) {
|
|
8062
|
+
formNode.set("TYPE", String(mediType));
|
|
8063
|
+
}
|
|
8064
|
+
fileNode.set("FORM", formNode);
|
|
8065
|
+
if (title) {
|
|
8066
|
+
fileNode.set("TITL", String(title));
|
|
8067
|
+
}
|
|
8068
|
+
if (note) {
|
|
8069
|
+
fileNode.set("NOTE", String(note));
|
|
8070
|
+
}
|
|
8071
|
+
newObject.set("FILE", fileNode);
|
|
8072
|
+
} else {
|
|
8073
|
+
newObject.set("FILE", fileNode);
|
|
8074
|
+
newObject.set("FORM", form);
|
|
8075
|
+
if (mediType) {
|
|
8076
|
+
newObject.set("MEDI", String(mediType));
|
|
8077
|
+
}
|
|
8078
|
+
if (title) {
|
|
8079
|
+
newObject.set("TITL", String(title));
|
|
8080
|
+
if (!note) {
|
|
8081
|
+
newObject.set("NOTE", String(title));
|
|
8082
|
+
}
|
|
8083
|
+
}
|
|
8084
|
+
if (note) {
|
|
8085
|
+
newObject.set("NOTE", String(note));
|
|
8086
|
+
if (!title) {
|
|
8087
|
+
newObject.set("TITL", String(note));
|
|
8088
|
+
}
|
|
8089
|
+
}
|
|
8090
|
+
}
|
|
8091
|
+
const prim = this.get("_PRIM")?.toValue();
|
|
8092
|
+
if (prim === "Y" || prim === "N") {
|
|
8093
|
+
newObject.set("_PRIM", prim);
|
|
8094
|
+
}
|
|
8095
|
+
const photoRin = this.get("_PHOTO_RIN")?.toValue();
|
|
8096
|
+
if (rin) {
|
|
8097
|
+
newObject.set("RIN", String(rin));
|
|
8098
|
+
}
|
|
8099
|
+
if (photoRin) {
|
|
8100
|
+
newObject.set("_PHOTO_RIN", String(photoRin));
|
|
8101
|
+
}
|
|
8102
|
+
const clonNode = this.get("_CLON");
|
|
8103
|
+
if (clonNode) {
|
|
8104
|
+
newObject.set("_CLON", clonNode);
|
|
8105
|
+
}
|
|
8106
|
+
const mserNode = this.get("_MSER");
|
|
8107
|
+
if (mserNode) {
|
|
8108
|
+
newObject.set("_MSER", mserNode);
|
|
8109
|
+
}
|
|
8110
|
+
const oidNode = this.get("_OID");
|
|
8111
|
+
if (oidNode && !newObject.get("_OID")) {
|
|
8112
|
+
newObject.set("_OID", oidNode);
|
|
8113
|
+
}
|
|
8114
|
+
const lkidNode = this.get("_LKID");
|
|
8115
|
+
if (lkidNode && !newObject.get("_LKID")) {
|
|
8116
|
+
newObject.set("_LKID", lkidNode);
|
|
8117
|
+
}
|
|
8118
|
+
if (override) {
|
|
8119
|
+
this.remove("FILE");
|
|
8120
|
+
this.remove("FORM");
|
|
8121
|
+
this.remove("MEDI");
|
|
8122
|
+
this.remove("TITL");
|
|
8123
|
+
this.remove("NOTE");
|
|
8124
|
+
Object.assign(this, newObject);
|
|
8125
|
+
return this;
|
|
8126
|
+
}
|
|
8127
|
+
return newObject;
|
|
6709
8128
|
}
|
|
6710
8129
|
};
|
|
6711
|
-
var
|
|
8130
|
+
var createObje = (gedcom, id, main, parent) => {
|
|
6712
8131
|
return createProxy(
|
|
6713
|
-
new
|
|
8132
|
+
new Obje(gedcom, id, main, parent)
|
|
6714
8133
|
);
|
|
6715
8134
|
};
|
|
6716
8135
|
|
|
6717
|
-
// src/classes/
|
|
6718
|
-
var
|
|
8136
|
+
// src/classes/objes.ts
|
|
8137
|
+
var Objects = class _Objects extends List {
|
|
6719
8138
|
copy() {
|
|
6720
|
-
|
|
6721
|
-
|
|
6722
|
-
|
|
6723
|
-
return super.except(item, _Families);
|
|
6724
|
-
}
|
|
6725
|
-
filter(filters) {
|
|
6726
|
-
return super.filter(filters, _Families);
|
|
6727
|
-
}
|
|
6728
|
-
find(filters) {
|
|
6729
|
-
return super.find(filters, _Families);
|
|
6730
|
-
}
|
|
6731
|
-
orderBy(orders) {
|
|
6732
|
-
return super.orderBy(orders, _Families);
|
|
6733
|
-
}
|
|
6734
|
-
getParents() {
|
|
6735
|
-
const persons = new Individuals();
|
|
6736
|
-
this.values().forEach((fam) => {
|
|
6737
|
-
if (fam && fam instanceof Fam) {
|
|
6738
|
-
persons.merge(fam.getParents());
|
|
6739
|
-
}
|
|
6740
|
-
});
|
|
6741
|
-
return persons;
|
|
6742
|
-
}
|
|
6743
|
-
getChildren() {
|
|
6744
|
-
const persons = new Individuals();
|
|
6745
|
-
this.values().forEach((fam) => {
|
|
6746
|
-
if (fam && fam instanceof Fam) {
|
|
6747
|
-
persons.merge(fam.getChildren());
|
|
6748
|
-
}
|
|
8139
|
+
const newList = new _Objects();
|
|
8140
|
+
this.entries().forEach(([key, value]) => {
|
|
8141
|
+
newList.item(key, value);
|
|
6749
8142
|
});
|
|
6750
|
-
return
|
|
8143
|
+
return newList;
|
|
6751
8144
|
}
|
|
6752
|
-
|
|
6753
|
-
return
|
|
8145
|
+
except(item) {
|
|
8146
|
+
return this.copy().delete(item);
|
|
6754
8147
|
}
|
|
6755
8148
|
};
|
|
6756
8149
|
|
|
6757
|
-
// package.json
|
|
6758
|
-
var package_default = {
|
|
6759
|
-
version: "2.0.10"};
|
|
6760
|
-
|
|
6761
|
-
// src/utils/get-product-details.ts
|
|
6762
|
-
var isDevelopment = () => {
|
|
6763
|
-
return !process.env.NODE_ENV || process.env.NODE_ENV === "development";
|
|
6764
|
-
};
|
|
6765
|
-
var getVersion = () => package_default.version;
|
|
6766
|
-
|
|
6767
8150
|
// src/classes/gedcom.ts
|
|
6768
8151
|
var isObjectPatch = (value) => {
|
|
6769
8152
|
return !!value && typeof value === "object" && !Array.isArray(value);
|
|
@@ -6959,6 +8342,189 @@ var GedCom = class extends Common {
|
|
|
6959
8342
|
fams() {
|
|
6960
8343
|
return this.getList("@@FAM");
|
|
6961
8344
|
}
|
|
8345
|
+
nextIndiKey() {
|
|
8346
|
+
const ids = [];
|
|
8347
|
+
this.indis()?.forEach((_indi, id) => {
|
|
8348
|
+
ids.push(String(id));
|
|
8349
|
+
});
|
|
8350
|
+
return nextRecordId(ids, "I");
|
|
8351
|
+
}
|
|
8352
|
+
nextFamKey() {
|
|
8353
|
+
const ids = [];
|
|
8354
|
+
this.fams()?.forEach((_fam, id) => {
|
|
8355
|
+
ids.push(String(id));
|
|
8356
|
+
});
|
|
8357
|
+
return nextRecordId(ids, "F");
|
|
8358
|
+
}
|
|
8359
|
+
createIndividual() {
|
|
8360
|
+
const existing = this.indis();
|
|
8361
|
+
const indis = existing ?? new Individuals();
|
|
8362
|
+
if (!existing) {
|
|
8363
|
+
this.set("@@INDI", indis);
|
|
8364
|
+
}
|
|
8365
|
+
const id = this.nextIndiKey();
|
|
8366
|
+
const indi = createIndi(this, id);
|
|
8367
|
+
indi.type = "INDI";
|
|
8368
|
+
if (this.getGedcomVersion() === "7.0") {
|
|
8369
|
+
indi.set("UID", createGedcomUid());
|
|
8370
|
+
}
|
|
8371
|
+
indis.item(id, indi);
|
|
8372
|
+
return indi;
|
|
8373
|
+
}
|
|
8374
|
+
createFamily() {
|
|
8375
|
+
const existing = this.fams();
|
|
8376
|
+
const fams = existing ?? new Families();
|
|
8377
|
+
if (!existing) {
|
|
8378
|
+
this.set("@@FAM", fams);
|
|
8379
|
+
}
|
|
8380
|
+
const id = this.nextFamKey();
|
|
8381
|
+
const fam = createFam(this, id);
|
|
8382
|
+
fam.type = "FAM";
|
|
8383
|
+
if (this.getGedcomVersion() === "7.0") {
|
|
8384
|
+
fam.set("UID", createGedcomUid());
|
|
8385
|
+
}
|
|
8386
|
+
fams.item(id, fam);
|
|
8387
|
+
return fam;
|
|
8388
|
+
}
|
|
8389
|
+
nextObjeKey() {
|
|
8390
|
+
const ids = [];
|
|
8391
|
+
this.objes()?.forEach((_obje, id) => {
|
|
8392
|
+
ids.push(String(id));
|
|
8393
|
+
});
|
|
8394
|
+
return nextRecordId(ids, "O");
|
|
8395
|
+
}
|
|
8396
|
+
/**
|
|
8397
|
+
* Create a top-level multimedia record (`0 @On@ OBJE`) with FILE/FORM/TITL.
|
|
8398
|
+
* GEDCOM 7 uses nested `FILE → FORM [→ TYPE]`; 5.5.1 uses sibling FORM/TITL.
|
|
8399
|
+
*/
|
|
8400
|
+
createMultimediaRecord(input) {
|
|
8401
|
+
const existing = this.objes();
|
|
8402
|
+
const objes = existing ?? new Objects();
|
|
8403
|
+
if (!existing) {
|
|
8404
|
+
this.set("@@OBJE", objes);
|
|
8405
|
+
}
|
|
8406
|
+
const id = this.nextObjeKey();
|
|
8407
|
+
const obje = createObje(this, id);
|
|
8408
|
+
obje.type = "OBJE";
|
|
8409
|
+
objes.item(id, obje);
|
|
8410
|
+
const version = normalizeGedcomVersion(
|
|
8411
|
+
input.gedcomVersion ?? this.getGedcomVersion()
|
|
8412
|
+
);
|
|
8413
|
+
const form = input.form || inferMediaForm(input.file);
|
|
8414
|
+
const fileNode = createCommon(this, void 0, obje);
|
|
8415
|
+
fileNode.value = input.file;
|
|
8416
|
+
if (version === "7.0") {
|
|
8417
|
+
const formNode = createCommon(
|
|
8418
|
+
this,
|
|
8419
|
+
void 0,
|
|
8420
|
+
fileNode
|
|
8421
|
+
);
|
|
8422
|
+
formNode.value = form;
|
|
8423
|
+
if (input.mediType) {
|
|
8424
|
+
formNode.set("TYPE", input.mediType);
|
|
8425
|
+
}
|
|
8426
|
+
fileNode.set("FORM", formNode);
|
|
8427
|
+
if (input.title) {
|
|
8428
|
+
fileNode.set("TITL", input.title);
|
|
8429
|
+
}
|
|
8430
|
+
obje.set("FILE", fileNode);
|
|
8431
|
+
} else {
|
|
8432
|
+
obje.set("FILE", fileNode);
|
|
8433
|
+
obje.set("FORM", form);
|
|
8434
|
+
if (input.mediType) {
|
|
8435
|
+
obje.set("MEDI", input.mediType);
|
|
8436
|
+
}
|
|
8437
|
+
if (input.title) {
|
|
8438
|
+
obje.set("TITL", input.title);
|
|
8439
|
+
}
|
|
8440
|
+
}
|
|
8441
|
+
if (input.primary) {
|
|
8442
|
+
obje.set("_PRIM", "Y");
|
|
8443
|
+
}
|
|
8444
|
+
if (normalizeGedcomVersion(
|
|
8445
|
+
input.gedcomVersion ?? this.getGedcomVersion()
|
|
8446
|
+
) === "7.0") {
|
|
8447
|
+
obje.set("UID", createGedcomUid());
|
|
8448
|
+
}
|
|
8449
|
+
return obje;
|
|
8450
|
+
}
|
|
8451
|
+
nextSnoteKey() {
|
|
8452
|
+
const ids = [];
|
|
8453
|
+
this.snotes()?.forEach((_note, id) => {
|
|
8454
|
+
ids.push(String(id));
|
|
8455
|
+
});
|
|
8456
|
+
return nextRecordId(ids, "N");
|
|
8457
|
+
}
|
|
8458
|
+
snotes() {
|
|
8459
|
+
return this.getList("@@SNOTE");
|
|
8460
|
+
}
|
|
8461
|
+
snote(index) {
|
|
8462
|
+
return this.getMain(this.snotes(), index);
|
|
8463
|
+
}
|
|
8464
|
+
/**
|
|
8465
|
+
* Create a top-level shared note record (`0 @Nn@ SNOTE` for GEDCOM 7).
|
|
8466
|
+
*/
|
|
8467
|
+
createSharedNote(text) {
|
|
8468
|
+
const existing = this.snotes();
|
|
8469
|
+
const notes = existing ?? new List();
|
|
8470
|
+
if (!existing) {
|
|
8471
|
+
this.set("@@SNOTE", notes);
|
|
8472
|
+
}
|
|
8473
|
+
const id = this.nextSnoteKey();
|
|
8474
|
+
const note = createCommonNote(this, id);
|
|
8475
|
+
note.type = "SNOTE";
|
|
8476
|
+
note.value = text;
|
|
8477
|
+
if (this.getGedcomVersion() === "7.0") {
|
|
8478
|
+
note.set("UID", createGedcomUid());
|
|
8479
|
+
}
|
|
8480
|
+
notes.item(id, note);
|
|
8481
|
+
return note;
|
|
8482
|
+
}
|
|
8483
|
+
registerExtensionTag(tag, uri) {
|
|
8484
|
+
return registerExtensionTag(this, tag, uri);
|
|
8485
|
+
}
|
|
8486
|
+
getExtensionSchema() {
|
|
8487
|
+
return getExtensionSchema(this);
|
|
8488
|
+
}
|
|
8489
|
+
ensureExtensionSchema(extraTags) {
|
|
8490
|
+
ensureExtensionSchema(this, extraTags);
|
|
8491
|
+
return getExtensionSchema(this);
|
|
8492
|
+
}
|
|
8493
|
+
/**
|
|
8494
|
+
* Collect multimedia descriptors via each individual's `multimedia()`.
|
|
8495
|
+
*/
|
|
8496
|
+
async collectMultimedia(options) {
|
|
8497
|
+
const people = [];
|
|
8498
|
+
if (options?.indiIds?.length) {
|
|
8499
|
+
options.indiIds.forEach((id) => {
|
|
8500
|
+
const indi = this.indi(id);
|
|
8501
|
+
if (indi) {
|
|
8502
|
+
people.push(indi);
|
|
8503
|
+
}
|
|
8504
|
+
});
|
|
8505
|
+
} else {
|
|
8506
|
+
this.indis()?.forEach((indi) => {
|
|
8507
|
+
if (indi) {
|
|
8508
|
+
people.push(indi);
|
|
8509
|
+
}
|
|
8510
|
+
});
|
|
8511
|
+
}
|
|
8512
|
+
const lists = await Promise.all(
|
|
8513
|
+
people.map((indi) => indi.multimedia(options?.namespace))
|
|
8514
|
+
);
|
|
8515
|
+
return mergeMediaLists(...lists);
|
|
8516
|
+
}
|
|
8517
|
+
/**
|
|
8518
|
+
* Serialize as GEDCOM 7 and pack a FamilySearch GEDZIP (`.gdz`).
|
|
8519
|
+
* Media bytes must be supplied by the caller (cache/fetch outside the parser).
|
|
8520
|
+
*/
|
|
8521
|
+
async toGedzip(options) {
|
|
8522
|
+
const text = this.toGedcom(void 0, 0, {
|
|
8523
|
+
...options,
|
|
8524
|
+
gedcomVersion: "7.0"
|
|
8525
|
+
});
|
|
8526
|
+
return buildGedzip(text, options?.media ?? []);
|
|
8527
|
+
}
|
|
6962
8528
|
objes() {
|
|
6963
8529
|
return this.getList("@@OBJE");
|
|
6964
8530
|
}
|
|
@@ -7043,18 +8609,70 @@ var GedCom = class extends Common {
|
|
|
7043
8609
|
});
|
|
7044
8610
|
return lists;
|
|
7045
8611
|
}
|
|
7046
|
-
|
|
8612
|
+
getGedcomVersion() {
|
|
8613
|
+
const raw = this.get("HEAD")?.get("GEDC")?.get("VERS")?.toValue();
|
|
8614
|
+
return normalizeGedcomVersion(
|
|
8615
|
+
typeof raw === "string" ? raw : void 0
|
|
8616
|
+
);
|
|
8617
|
+
}
|
|
8618
|
+
/** Rewrite HEAD.GEDC (and CHAR/FORM) for the requested export version. */
|
|
8619
|
+
applyExportVersion(version) {
|
|
8620
|
+
const head = this.get("HEAD");
|
|
8621
|
+
if (!head) {
|
|
8622
|
+
return;
|
|
8623
|
+
}
|
|
8624
|
+
this.applyGedcomSpecToHead(head, normalizeGedcomVersion(version));
|
|
8625
|
+
}
|
|
8626
|
+
applyGedcomSpecToHead(head, version) {
|
|
8627
|
+
const previousGedc = head.get("GEDC");
|
|
8628
|
+
const previousForm = previousGedc?.get("FORM")?.toValue();
|
|
8629
|
+
const previousChar = head.get("CHAR")?.toValue();
|
|
8630
|
+
head.remove("GEDC");
|
|
8631
|
+
const gedc = head.set("GEDC", "");
|
|
8632
|
+
if (!gedc) {
|
|
8633
|
+
return;
|
|
8634
|
+
}
|
|
8635
|
+
gedc.set("VERS", version);
|
|
8636
|
+
if (version === "7.0") {
|
|
8637
|
+
head.remove("CHAR");
|
|
8638
|
+
return;
|
|
8639
|
+
}
|
|
8640
|
+
gedc.set(
|
|
8641
|
+
"FORM",
|
|
8642
|
+
typeof previousForm === "string" && previousForm ? previousForm : "LINEAGE-LINKED"
|
|
8643
|
+
);
|
|
8644
|
+
if (!head.get("CHAR")?.toValue()) {
|
|
8645
|
+
head.set(
|
|
8646
|
+
"CHAR",
|
|
8647
|
+
typeof previousChar === "string" && previousChar ? previousChar : "UTF-8"
|
|
8648
|
+
);
|
|
8649
|
+
}
|
|
8650
|
+
}
|
|
8651
|
+
getDownloadHeader(gedcomVersion) {
|
|
7047
8652
|
const newHead = createCommon();
|
|
7048
8653
|
Object.assign(newHead, this.get("HEAD") ?? {});
|
|
8654
|
+
this.applyGedcomSpecToHead(
|
|
8655
|
+
newHead,
|
|
8656
|
+
gedcomVersion ?? this.getGedcomVersion()
|
|
8657
|
+
);
|
|
8658
|
+
const existingSour = this.get("HEAD")?.get("SOUR");
|
|
8659
|
+
const existingTreeName = existingSour?.get("_TREE")?.toValue();
|
|
8660
|
+
const existingTreeUniqueId = existingSour?.get("_TID")?.toValue();
|
|
7049
8661
|
const newSour = createCommon();
|
|
7050
|
-
newSour.
|
|
7051
|
-
newSour.set("
|
|
7052
|
-
newSour.set("
|
|
7053
|
-
|
|
7054
|
-
|
|
7055
|
-
|
|
7056
|
-
|
|
7057
|
-
|
|
8662
|
+
newSour.value = APP_BRANDING;
|
|
8663
|
+
newSour.set("NAME", APP_BRANDING);
|
|
8664
|
+
newSour.set("VERS", getVersion());
|
|
8665
|
+
if (typeof existingTreeName === "string" && existingTreeName.trim()) {
|
|
8666
|
+
newSour.set("_TREE", existingTreeName.trim());
|
|
8667
|
+
}
|
|
8668
|
+
if (typeof existingTreeUniqueId === "string" && existingTreeUniqueId.trim()) {
|
|
8669
|
+
newSour.set("_TID", existingTreeUniqueId.trim());
|
|
8670
|
+
}
|
|
8671
|
+
const corp = createCommon();
|
|
8672
|
+
corp.value = APP_BRANDING;
|
|
8673
|
+
corp.set("WWW", "treeviz.com");
|
|
8674
|
+
corp.set("EMAIL", "info@treeviz.com");
|
|
8675
|
+
newSour.set("CORP", corp);
|
|
7058
8676
|
newHead.set("SOUR", newSour);
|
|
7059
8677
|
return newHead;
|
|
7060
8678
|
}
|
|
@@ -7083,20 +8701,45 @@ var GedCom = class extends Common {
|
|
|
7083
8701
|
}
|
|
7084
8702
|
toGedcom(tag, level, options) {
|
|
7085
8703
|
if (options?.super) {
|
|
7086
|
-
return super.toGedcom(tag, level, options);
|
|
8704
|
+
return appendGedcomTrailer(super.toGedcom(tag, level, options));
|
|
7087
8705
|
}
|
|
8706
|
+
const requestedVersion = options?.gedcomVersion;
|
|
8707
|
+
const exportVersion = requestedVersion ? normalizeGedcomVersion(requestedVersion) : this.getGedcomVersion();
|
|
8708
|
+
const exportOptions = {
|
|
8709
|
+
...options,
|
|
8710
|
+
obje: {
|
|
8711
|
+
standardize: options?.obje?.standardize ?? (requestedVersion !== void 0 || !options?.original),
|
|
8712
|
+
override: options?.obje?.override,
|
|
8713
|
+
namespace: options?.obje?.namespace
|
|
8714
|
+
}
|
|
8715
|
+
};
|
|
7088
8716
|
const newGedcom = createGedCom();
|
|
7089
|
-
|
|
8717
|
+
Object.assign(newGedcom, this);
|
|
8718
|
+
if (!exportOptions.original) {
|
|
7090
8719
|
Object.assign(newGedcom, {
|
|
7091
|
-
HEAD: this.getDownloadHeader()
|
|
8720
|
+
HEAD: this.getDownloadHeader(exportVersion)
|
|
7092
8721
|
});
|
|
7093
8722
|
}
|
|
7094
|
-
|
|
7095
|
-
|
|
7096
|
-
const newContent = this.getIndiRelatedLists(options.indis);
|
|
8723
|
+
if (exportOptions.indis?.length) {
|
|
8724
|
+
const newContent = this.getIndiRelatedLists(exportOptions.indis);
|
|
7097
8725
|
Object.assign(newGedcom, newContent);
|
|
7098
8726
|
}
|
|
7099
|
-
|
|
8727
|
+
const restoreEnums = exportVersion === "7.0" ? applyGedcom7Enumerations(newGedcom) : void 0;
|
|
8728
|
+
const restoreDates = exportVersion === "7.0" ? applyGedcom7DatePhrases(newGedcom) : void 0;
|
|
8729
|
+
const restoreMetadata = exportVersion === "7.0" ? applyGedcom7RecordMetadata(newGedcom) : void 0;
|
|
8730
|
+
const restoreSchema = exportVersion === "7.0" ? ensureExtensionSchema(newGedcom) : void 0;
|
|
8731
|
+
try {
|
|
8732
|
+
return newGedcom.toGedcom(tag, level, {
|
|
8733
|
+
...exportOptions,
|
|
8734
|
+
gedcomVersion: exportVersion,
|
|
8735
|
+
super: true
|
|
8736
|
+
});
|
|
8737
|
+
} finally {
|
|
8738
|
+
restoreSchema?.();
|
|
8739
|
+
restoreMetadata?.();
|
|
8740
|
+
restoreDates?.();
|
|
8741
|
+
restoreEnums?.();
|
|
8742
|
+
}
|
|
7100
8743
|
}
|
|
7101
8744
|
hasTag(tag) {
|
|
7102
8745
|
const tagName = typeof tag === "string" ? tag : tag?.get("NAME")?.toValue();
|
|
@@ -7540,20 +9183,6 @@ var mergeGedcoms = (targetGedcom, sourceGedcom, strategy = "id") => {
|
|
|
7540
9183
|
return mergedGedcom;
|
|
7541
9184
|
};
|
|
7542
9185
|
|
|
7543
|
-
// src/classes/objes.ts
|
|
7544
|
-
var Objects = class _Objects extends List {
|
|
7545
|
-
copy() {
|
|
7546
|
-
const newList = new _Objects();
|
|
7547
|
-
this.entries().forEach(([key, value]) => {
|
|
7548
|
-
newList.item(key, value);
|
|
7549
|
-
});
|
|
7550
|
-
return newList;
|
|
7551
|
-
}
|
|
7552
|
-
except(item) {
|
|
7553
|
-
return this.copy().delete(item);
|
|
7554
|
-
}
|
|
7555
|
-
};
|
|
7556
|
-
|
|
7557
9186
|
// src/classes/repos.ts
|
|
7558
9187
|
var Repositories = class _Repositories extends List {
|
|
7559
9188
|
copy() {
|
|
@@ -7596,144 +9225,6 @@ var Submitters = class _Submitters extends List {
|
|
|
7596
9225
|
}
|
|
7597
9226
|
};
|
|
7598
9227
|
|
|
7599
|
-
// src/classes/note.ts
|
|
7600
|
-
var CommonNote = class extends Common {
|
|
7601
|
-
constructor(gedcom, id, main, parent) {
|
|
7602
|
-
super(gedcom, id, main, parent);
|
|
7603
|
-
delete this.id;
|
|
7604
|
-
}
|
|
7605
|
-
set value(value) {
|
|
7606
|
-
const [note, ...contents] = value?.split(/\r?\n/) ?? [];
|
|
7607
|
-
this._value = note;
|
|
7608
|
-
if (contents.length) {
|
|
7609
|
-
const newContents = new List();
|
|
7610
|
-
contents.forEach((c, i) => {
|
|
7611
|
-
const newContent = createCommon(
|
|
7612
|
-
this._gedcom,
|
|
7613
|
-
void 0,
|
|
7614
|
-
this.main
|
|
7615
|
-
);
|
|
7616
|
-
newContent.id = `@U${i}@`;
|
|
7617
|
-
newContent.value = c;
|
|
7618
|
-
newContents.append(newContent);
|
|
7619
|
-
});
|
|
7620
|
-
const firstItem = newContents.index(0);
|
|
7621
|
-
if (firstItem) {
|
|
7622
|
-
if (newContents.length === 1) {
|
|
7623
|
-
this.set("CONT", firstItem);
|
|
7624
|
-
} else {
|
|
7625
|
-
this.set("CONT", newContents);
|
|
7626
|
-
}
|
|
7627
|
-
}
|
|
7628
|
-
}
|
|
7629
|
-
}
|
|
7630
|
-
get value() {
|
|
7631
|
-
const contents = this.get("CONT")?.toList().map((content) => content.value).join("\n");
|
|
7632
|
-
if (contents) {
|
|
7633
|
-
return `${this._value}
|
|
7634
|
-
${contents}`;
|
|
7635
|
-
}
|
|
7636
|
-
return this._value;
|
|
7637
|
-
}
|
|
7638
|
-
exportValue() {
|
|
7639
|
-
return this._value;
|
|
7640
|
-
}
|
|
7641
|
-
};
|
|
7642
|
-
var createCommonNote = (gedcom, id, main, parent) => {
|
|
7643
|
-
return createProxy(
|
|
7644
|
-
new CommonNote(gedcom, id, main, parent)
|
|
7645
|
-
);
|
|
7646
|
-
};
|
|
7647
|
-
|
|
7648
|
-
// src/classes/obje.ts
|
|
7649
|
-
var Obje = class extends Common {
|
|
7650
|
-
standardizeMedia(namespace, override = true, urlGetter) {
|
|
7651
|
-
if (!this._gedcom) {
|
|
7652
|
-
return this;
|
|
7653
|
-
}
|
|
7654
|
-
const rin = this?.get("RIN")?.toValue();
|
|
7655
|
-
const clone = this?.get("_CLON._OID")?.toValue();
|
|
7656
|
-
const mser = this?.get("_MSER._LKID")?.toValue();
|
|
7657
|
-
const title = this?.get("FILE.TITL")?.toValue() ?? this?.get("TITL")?.toValue() ?? "";
|
|
7658
|
-
const note = this?.get("FILE.NOTE")?.toValue() ?? this?.get("NOTE")?.toValue() ?? "";
|
|
7659
|
-
const form = this?.get("FILE.FORM")?.toValue();
|
|
7660
|
-
const file = this?.get("FILE")?.toValue();
|
|
7661
|
-
const imgId = rin || clone || mser;
|
|
7662
|
-
const url = file || namespace && urlGetter?.(namespace, imgId);
|
|
7663
|
-
if (!url) {
|
|
7664
|
-
return this;
|
|
7665
|
-
}
|
|
7666
|
-
const newObject = createObje(this._gedcom, this.id, this.main);
|
|
7667
|
-
if (!override) {
|
|
7668
|
-
Object.assign(newObject, this);
|
|
7669
|
-
}
|
|
7670
|
-
if (form) {
|
|
7671
|
-
if (typeof form === "string") {
|
|
7672
|
-
const newForm = createCommon(
|
|
7673
|
-
this._gedcom,
|
|
7674
|
-
void 0,
|
|
7675
|
-
this.main
|
|
7676
|
-
);
|
|
7677
|
-
newForm.value = form;
|
|
7678
|
-
newObject.set("FORM", newForm);
|
|
7679
|
-
} else {
|
|
7680
|
-
newObject.set("FORM", form);
|
|
7681
|
-
}
|
|
7682
|
-
}
|
|
7683
|
-
if (title) {
|
|
7684
|
-
if (typeof title === "string") {
|
|
7685
|
-
const newTitle = createCommon(
|
|
7686
|
-
this._gedcom,
|
|
7687
|
-
void 0,
|
|
7688
|
-
this.main
|
|
7689
|
-
);
|
|
7690
|
-
newTitle.value = title;
|
|
7691
|
-
newObject.set("TITL", newTitle);
|
|
7692
|
-
if (!note) {
|
|
7693
|
-
newObject.set("NOTE", newTitle);
|
|
7694
|
-
}
|
|
7695
|
-
} else {
|
|
7696
|
-
newObject.set("TITL", title);
|
|
7697
|
-
if (!note) {
|
|
7698
|
-
newObject.set("NOTE", title);
|
|
7699
|
-
}
|
|
7700
|
-
}
|
|
7701
|
-
}
|
|
7702
|
-
if (note) {
|
|
7703
|
-
if (typeof note === "string") {
|
|
7704
|
-
const newNote = createCommon(
|
|
7705
|
-
this._gedcom,
|
|
7706
|
-
void 0,
|
|
7707
|
-
this.main
|
|
7708
|
-
);
|
|
7709
|
-
newNote.value = note;
|
|
7710
|
-
newObject.set("NOTE", newNote);
|
|
7711
|
-
if (!title) {
|
|
7712
|
-
newObject.set("TITL", newNote);
|
|
7713
|
-
}
|
|
7714
|
-
} else {
|
|
7715
|
-
newObject.set("NOTE", note);
|
|
7716
|
-
if (!title) {
|
|
7717
|
-
newObject.set("TITL", note);
|
|
7718
|
-
}
|
|
7719
|
-
}
|
|
7720
|
-
}
|
|
7721
|
-
const newUrl = createCommon(this._gedcom, void 0, this.main);
|
|
7722
|
-
newUrl.value = url;
|
|
7723
|
-
newObject.set("FILE", newUrl);
|
|
7724
|
-
if (override) {
|
|
7725
|
-
Object.assign(this, newObject);
|
|
7726
|
-
return this;
|
|
7727
|
-
}
|
|
7728
|
-
return newObject;
|
|
7729
|
-
}
|
|
7730
|
-
};
|
|
7731
|
-
var createObje = (gedcom, id, main, parent) => {
|
|
7732
|
-
return createProxy(
|
|
7733
|
-
new Obje(gedcom, id, main, parent)
|
|
7734
|
-
);
|
|
7735
|
-
};
|
|
7736
|
-
|
|
7737
9228
|
// src/classes/repo.ts
|
|
7738
9229
|
var Repo = class extends Common {
|
|
7739
9230
|
};
|
|
@@ -7782,6 +9273,8 @@ var create = (gedcom, type, id, nodes) => {
|
|
|
7782
9273
|
prevNode = createIndi(gedcom, id);
|
|
7783
9274
|
} else if (convertType === "FAM") {
|
|
7784
9275
|
prevNode = createFam(gedcom, id);
|
|
9276
|
+
} else if (convertType === "SNOTE" || convertType === "NOTE") {
|
|
9277
|
+
prevNode = createCommonNote(gedcom, id);
|
|
7785
9278
|
} else {
|
|
7786
9279
|
prevNode = createCommon(gedcom, id);
|
|
7787
9280
|
}
|
|
@@ -7797,7 +9290,7 @@ var create = (gedcom, type, id, nodes) => {
|
|
|
7797
9290
|
prevNode = createObje(gedcom, void 0, mainNode, curNode);
|
|
7798
9291
|
} else if (type === "DATE") {
|
|
7799
9292
|
prevNode = createCommonDate(gedcom, void 0, mainNode, curNode);
|
|
7800
|
-
} else if (type === "NOTE") {
|
|
9293
|
+
} else if (type === "NOTE" || type === "SNOTE") {
|
|
7801
9294
|
prevNode = createCommonNote(gedcom, void 0, mainNode, curNode);
|
|
7802
9295
|
} else if (type === "NAME" && mainNode instanceof Indi) {
|
|
7803
9296
|
prevNode = createCommonName(gedcom, void 0, mainNode, curNode);
|
|
@@ -7849,9 +9342,7 @@ var GedcomTree = {
|
|
|
7849
9342
|
}, {}) : {};
|
|
7850
9343
|
const links = new Individuals();
|
|
7851
9344
|
const tags = [];
|
|
7852
|
-
let lines =
|
|
7853
|
-
0 TRLR
|
|
7854
|
-
`.split(/\r?\n/).reduce((acc, line) => {
|
|
9345
|
+
let lines = content.split(/\r?\n/).reduce((acc, line) => {
|
|
7855
9346
|
const lineMatch = line.match(LINE_REG);
|
|
7856
9347
|
if (lineMatch) {
|
|
7857
9348
|
const lineIndent = Number(lineMatch?.groups?.indent ?? 0);
|
|
@@ -7864,6 +9355,13 @@ var GedcomTree = {
|
|
|
7864
9355
|
linesAcc._hasFile = false;
|
|
7865
9356
|
return acc;
|
|
7866
9357
|
}
|
|
9358
|
+
if (lineIndent === 0 && lineType === "TRLR") {
|
|
9359
|
+
if (linesAcc._inHead && filename && !linesAcc._hasFile) {
|
|
9360
|
+
acc.push(`1 FILE ${filename}`);
|
|
9361
|
+
}
|
|
9362
|
+
linesAcc._inHead = false;
|
|
9363
|
+
return acc;
|
|
9364
|
+
}
|
|
7867
9365
|
if (lineIndent === 0 && linesAcc._inHead) {
|
|
7868
9366
|
if (filename && !linesAcc._hasFile) {
|
|
7869
9367
|
acc.push(`1 FILE ${filename}`);
|
|
@@ -7875,6 +9373,13 @@ var GedcomTree = {
|
|
|
7875
9373
|
if (linesAcc._inHead && lineIndent === 1 && lineType === "FILE") {
|
|
7876
9374
|
linesAcc._hasFile = true;
|
|
7877
9375
|
}
|
|
9376
|
+
if (lineType.toUpperCase() === "CONC") {
|
|
9377
|
+
const last = acc[acc.length - 1];
|
|
9378
|
+
if (last !== void 0) {
|
|
9379
|
+
acc[acc.length - 1] = `${last}${lineValue}`;
|
|
9380
|
+
return acc;
|
|
9381
|
+
}
|
|
9382
|
+
}
|
|
7878
9383
|
if (lineIndent > 0 && lineIndent > prevLineIndent && lineValue && isId(lineValue)) {
|
|
7879
9384
|
const refLines = lineValue.split(/,\s*/).map((id) => line.replace(lineValue, id));
|
|
7880
9385
|
if (refLines.length > 1) {
|
|
@@ -7918,8 +9423,9 @@ var GedcomTree = {
|
|
|
7918
9423
|
).replace(/0\s(@[^@]+@)(\sSOUR[^\n]*\n)([123456789]\s.+\n)*/, "").replace(/0 HEAD(.*)\n/, "0 HEAD$1\n1 _IS_PURGED true\n");
|
|
7919
9424
|
lines = linesJoined.split("\n");
|
|
7920
9425
|
}
|
|
9426
|
+
lines = lines.filter((line) => !isGedcomTrailerLine(line));
|
|
7921
9427
|
lines.forEach((line, index) => {
|
|
7922
|
-
if (line.length === 0) {
|
|
9428
|
+
if (line.length === 0 || isGedcomTrailerLine(line)) {
|
|
7923
9429
|
return;
|
|
7924
9430
|
}
|
|
7925
9431
|
const match = reg.exec(line);
|