@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/utils/index.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { debounce, set, get, uniqBy, unset, difference, intersectionBy, differenceBy } from 'lodash-es';
|
|
2
2
|
import { format, isValid, parse } from 'date-fns';
|
|
3
|
+
import JSZip from 'jszip';
|
|
3
4
|
|
|
4
5
|
var __defProp = Object.defineProperty;
|
|
5
6
|
var __export = (target, all) => {
|
|
@@ -292,11 +293,31 @@ var cacheDiscoveredPath = (gedcom, path) => {
|
|
|
292
293
|
};
|
|
293
294
|
|
|
294
295
|
// src/constants/constants.ts
|
|
295
|
-
var
|
|
296
|
-
var
|
|
296
|
+
var APP_BRANDING = "TreeViz - The Family Tree Visualiser & Editor";
|
|
297
|
+
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;
|
|
298
|
+
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>.*)/;
|
|
297
299
|
var ID_REG = /^@[_a-zA-Z0-9]+@/;
|
|
298
300
|
var ID_GETTER_REG = /^(?<at>@)?(?<letter>[A-Z])?/i;
|
|
301
|
+
var ORIG_HEAD_TAG = "_ORIGHEAD";
|
|
299
302
|
var MAX_FILE_SIZE_TO_SYNC = 1024 * 1024 * 20;
|
|
303
|
+
|
|
304
|
+
// src/utils/gedcom-trailer.ts
|
|
305
|
+
var TRAILER_LINE = /^0 TRLR\s*$/i;
|
|
306
|
+
var GEDCOM_TRAILER_TAG = "TRLR";
|
|
307
|
+
var isGedcomTrailerTag = (tag) => tag === GEDCOM_TRAILER_TAG;
|
|
308
|
+
var isGedcomTrailerLine = (line) => TRAILER_LINE.test(line);
|
|
309
|
+
var appendGedcomTrailer = (serialized) => {
|
|
310
|
+
const newline = serialized.includes("\r\n") ? "\r\n" : "\n";
|
|
311
|
+
const trimmed = serialized.replace(/(?:\r?\n)+$/, "");
|
|
312
|
+
if (!trimmed) {
|
|
313
|
+
return "0 TRLR";
|
|
314
|
+
}
|
|
315
|
+
const lastLine = trimmed.split(/\r?\n/).at(-1) ?? "";
|
|
316
|
+
if (isGedcomTrailerLine(lastLine)) {
|
|
317
|
+
return trimmed;
|
|
318
|
+
}
|
|
319
|
+
return `${trimmed}${newline}0 TRLR`;
|
|
320
|
+
};
|
|
300
321
|
var List = class _List {
|
|
301
322
|
// length = 0;
|
|
302
323
|
constructor(items) {
|
|
@@ -672,11 +693,17 @@ var List = class _List {
|
|
|
672
693
|
const gedcom = [];
|
|
673
694
|
this.entries().forEach(([_, item]) => {
|
|
674
695
|
const validTag = getValidTag(tag);
|
|
675
|
-
const
|
|
676
|
-
const
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
696
|
+
const xref = item.id;
|
|
697
|
+
const payload = item.exportValue?.();
|
|
698
|
+
if (xref) {
|
|
699
|
+
gedcom.push(
|
|
700
|
+
`${level} ${xref} ${validTag}${payload ? ` ${payload}` : ""}`
|
|
701
|
+
);
|
|
702
|
+
} else {
|
|
703
|
+
gedcom.push(
|
|
704
|
+
`${level} ${validTag}${payload ? ` ${payload}` : ""}`
|
|
705
|
+
);
|
|
706
|
+
}
|
|
680
707
|
gedcom.push(
|
|
681
708
|
...item.toGedcomLines(
|
|
682
709
|
validTag,
|
|
@@ -807,6 +834,9 @@ var Common = class _Common {
|
|
|
807
834
|
delete this._value;
|
|
808
835
|
}
|
|
809
836
|
set(name, value) {
|
|
837
|
+
if (isGedcomTrailerTag(name)) {
|
|
838
|
+
return void 0;
|
|
839
|
+
}
|
|
810
840
|
if (typeof value === "string") {
|
|
811
841
|
const usedValue = createCommon(this._gedcom, void 0, this.main);
|
|
812
842
|
usedValue.value = value;
|
|
@@ -817,6 +847,9 @@ var Common = class _Common {
|
|
|
817
847
|
return get(this, name);
|
|
818
848
|
}
|
|
819
849
|
assign(name, value, unique = false) {
|
|
850
|
+
if (isGedcomTrailerTag(name)) {
|
|
851
|
+
return void 0;
|
|
852
|
+
}
|
|
820
853
|
let curValue = this.get(name);
|
|
821
854
|
if (curValue?.isListable) {
|
|
822
855
|
if (curValue instanceof _Common) {
|
|
@@ -928,12 +961,14 @@ var Common = class _Common {
|
|
|
928
961
|
);
|
|
929
962
|
}
|
|
930
963
|
standardizeObject(tag, options) {
|
|
931
|
-
if (tag === "OBJE" &&
|
|
964
|
+
if (tag === "OBJE" && options?.obje?.standardize && "standardizeMedia" in this) {
|
|
932
965
|
const standardize = this.standardizeMedia;
|
|
933
966
|
return standardize.call(
|
|
934
967
|
this,
|
|
935
968
|
options.obje.namespace,
|
|
936
|
-
options.obje.override
|
|
969
|
+
options.obje.override,
|
|
970
|
+
void 0,
|
|
971
|
+
options.gedcomVersion
|
|
937
972
|
);
|
|
938
973
|
}
|
|
939
974
|
}
|
|
@@ -960,7 +995,7 @@ var Common = class _Common {
|
|
|
960
995
|
if (typeof prop?.toObject === "function") {
|
|
961
996
|
if (prop instanceof _Common) {
|
|
962
997
|
json[validKey] = prop.toObject(validKey, options);
|
|
963
|
-
} else {
|
|
998
|
+
} else if (prop instanceof List) {
|
|
964
999
|
json = {
|
|
965
1000
|
...json,
|
|
966
1001
|
...prop.toObject(validKey, options)
|
|
@@ -1018,8 +1053,12 @@ var Common = class _Common {
|
|
|
1018
1053
|
this.standardizeObject(tag, options);
|
|
1019
1054
|
const validKeys = getValidKeys(this);
|
|
1020
1055
|
const gedcom = [];
|
|
1056
|
+
const isGedcom7Export = options?.gedcomVersion === "7.0";
|
|
1021
1057
|
validKeys.forEach((key) => {
|
|
1022
1058
|
const validKey = key;
|
|
1059
|
+
if (isGedcom7Export && validKey === "CONC") {
|
|
1060
|
+
return;
|
|
1061
|
+
}
|
|
1023
1062
|
const prop = this.get(validKey);
|
|
1024
1063
|
if (typeof prop?.toGedcomLines === "function") {
|
|
1025
1064
|
if (prop instanceof _Common) {
|
|
@@ -1030,7 +1069,7 @@ var Common = class _Common {
|
|
|
1030
1069
|
gedcom.push(
|
|
1031
1070
|
...prop.toGedcomLines(validKey, level + 1, options)
|
|
1032
1071
|
);
|
|
1033
|
-
} else {
|
|
1072
|
+
} else if (prop instanceof List) {
|
|
1034
1073
|
gedcom.push(
|
|
1035
1074
|
...prop.toGedcomLines(validKey, level, options)
|
|
1036
1075
|
);
|
|
@@ -1039,30 +1078,47 @@ var Common = class _Common {
|
|
|
1039
1078
|
});
|
|
1040
1079
|
return gedcom;
|
|
1041
1080
|
}
|
|
1081
|
+
getHeadRecord() {
|
|
1082
|
+
return get(this, "HEAD") || get(this.getGedcom(), "HEAD");
|
|
1083
|
+
}
|
|
1084
|
+
getOriginalHeadRecord() {
|
|
1085
|
+
return get(this, ORIG_HEAD_TAG) || get(this.getGedcom(), ORIG_HEAD_TAG) || get(this.getHeadRecord(), ORIG_HEAD_TAG);
|
|
1086
|
+
}
|
|
1087
|
+
getSourceHeads() {
|
|
1088
|
+
const heads = [this.getOriginalHeadRecord(), this.getHeadRecord()];
|
|
1089
|
+
return heads.filter((head, index) => {
|
|
1090
|
+
return Boolean(head && heads.indexOf(head) === index);
|
|
1091
|
+
});
|
|
1092
|
+
}
|
|
1093
|
+
getFromSourceHeads(path) {
|
|
1094
|
+
for (const head of this.getSourceHeads()) {
|
|
1095
|
+
const value = get(head, path);
|
|
1096
|
+
if (value !== void 0 && value !== null && value !== "") {
|
|
1097
|
+
return value;
|
|
1098
|
+
}
|
|
1099
|
+
}
|
|
1100
|
+
return void 0;
|
|
1101
|
+
}
|
|
1102
|
+
sourStartsWith(prefix) {
|
|
1103
|
+
return this.getSourceHeads().some((head) => {
|
|
1104
|
+
const sour = get(head, "SOUR.value");
|
|
1105
|
+
return !!sour?.toLowerCase()?.startsWith(prefix);
|
|
1106
|
+
});
|
|
1107
|
+
}
|
|
1042
1108
|
isGenoPro() {
|
|
1043
|
-
|
|
1044
|
-
const sour = get(head, "SOUR.value");
|
|
1045
|
-
return !!sour?.toLowerCase()?.startsWith("genopro");
|
|
1109
|
+
return this.sourStartsWith("genopro");
|
|
1046
1110
|
}
|
|
1047
1111
|
isAhnenblatt() {
|
|
1048
|
-
|
|
1049
|
-
const sour = get(head, "SOUR.value");
|
|
1050
|
-
return !!sour?.toLowerCase()?.startsWith("ahnenblatt");
|
|
1112
|
+
return this.sourStartsWith("ahnenblatt");
|
|
1051
1113
|
}
|
|
1052
1114
|
isGeni() {
|
|
1053
|
-
|
|
1054
|
-
const sour = get(head, "SOUR.value");
|
|
1055
|
-
return !!sour?.toLowerCase()?.startsWith("geni");
|
|
1115
|
+
return this.sourStartsWith("geni");
|
|
1056
1116
|
}
|
|
1057
1117
|
isAncestry() {
|
|
1058
|
-
|
|
1059
|
-
const sour = get(head, "SOUR.value");
|
|
1060
|
-
return !!sour?.toLowerCase()?.startsWith("ancestry");
|
|
1118
|
+
return this.sourStartsWith("ancestry");
|
|
1061
1119
|
}
|
|
1062
1120
|
isMyHeritage() {
|
|
1063
|
-
|
|
1064
|
-
const sour = get(head, "SOUR.value");
|
|
1065
|
-
return !!sour?.toLowerCase()?.startsWith("myheritage");
|
|
1121
|
+
return this.sourStartsWith("myheritage");
|
|
1066
1122
|
}
|
|
1067
1123
|
/**
|
|
1068
1124
|
* Get the source type as a string (for prefixing tree IDs and names)
|
|
@@ -1079,22 +1135,22 @@ var Common = class _Common {
|
|
|
1079
1135
|
return void 0;
|
|
1080
1136
|
}
|
|
1081
1137
|
isFamilySearch() {
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1138
|
+
return this.getSourceHeads().some((head) => {
|
|
1139
|
+
const sourName = get(head, "SOUR.NAME.value");
|
|
1140
|
+
return sourName === "FamilySearch API";
|
|
1141
|
+
});
|
|
1085
1142
|
}
|
|
1086
1143
|
isGNO2GED() {
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1144
|
+
return this.getSourceHeads().some((head) => {
|
|
1145
|
+
const sour = get(head, "SOUR.value");
|
|
1146
|
+
return sour === "GNO2GED";
|
|
1147
|
+
});
|
|
1090
1148
|
}
|
|
1091
1149
|
getAncestryTreeId() {
|
|
1092
|
-
|
|
1093
|
-
return get(this, path) || get(this.getGedcom(), path);
|
|
1150
|
+
return this.getFromSourceHeads("SOUR._TREE.RIN.value") || (get(this, "HEAD.SOUR._TREE.RIN.value") || get(this.getGedcom(), "HEAD.SOUR._TREE.RIN.value"));
|
|
1094
1151
|
}
|
|
1095
1152
|
getMyHeritageTreeId() {
|
|
1096
|
-
|
|
1097
|
-
return get(this, path) || get(this.getGedcom(), path);
|
|
1153
|
+
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"));
|
|
1098
1154
|
}
|
|
1099
1155
|
getTreeId() {
|
|
1100
1156
|
if (this?.isAncestry()) {
|
|
@@ -1128,8 +1184,7 @@ var Common = class _Common {
|
|
|
1128
1184
|
return this.getUniversalTreeId();
|
|
1129
1185
|
}
|
|
1130
1186
|
getAncestryTreeName() {
|
|
1131
|
-
|
|
1132
|
-
return get(this, path) || get(this.getGedcom(), path);
|
|
1187
|
+
return this.getFromSourceHeads("SOUR._TREE.value") || (get(this, "HEAD.SOUR._TREE.value") || get(this.getGedcom(), "HEAD.SOUR._TREE.value"));
|
|
1133
1188
|
}
|
|
1134
1189
|
getMyHeritageTreeName() {
|
|
1135
1190
|
const path = "HEAD.FILE.value";
|
|
@@ -1139,14 +1194,14 @@ var Common = class _Common {
|
|
|
1139
1194
|
)?.groups?.tree;
|
|
1140
1195
|
}
|
|
1141
1196
|
getFamilySearchTreeId() {
|
|
1142
|
-
const rin = get(this, "HEAD.SOUR._TREE.RIN.value") || get(this.getGedcom(), "HEAD.SOUR._TREE.RIN.value");
|
|
1197
|
+
const rin = this.getFromSourceHeads("SOUR._TREE.RIN.value") || get(this, "HEAD.SOUR._TREE.RIN.value") || get(this.getGedcom(), "HEAD.SOUR._TREE.RIN.value");
|
|
1143
1198
|
if (rin) {
|
|
1144
1199
|
return rin;
|
|
1145
1200
|
}
|
|
1146
1201
|
return "familysearch";
|
|
1147
1202
|
}
|
|
1148
1203
|
getFamilySearchTreeName() {
|
|
1149
|
-
const treeName = get(this, "HEAD.SOUR._TREE.value") || get(this.getGedcom(), "HEAD.SOUR._TREE.value");
|
|
1204
|
+
const treeName = this.getFromSourceHeads("SOUR._TREE.value") || get(this, "HEAD.SOUR._TREE.value") || get(this.getGedcom(), "HEAD.SOUR._TREE.value");
|
|
1150
1205
|
if (treeName) {
|
|
1151
1206
|
return treeName;
|
|
1152
1207
|
}
|
|
@@ -1238,11 +1293,11 @@ var Common = class _Common {
|
|
|
1238
1293
|
const cleanName = fileName.replace(/\.ged$/i, "").replace(/_/g, " ");
|
|
1239
1294
|
return `${prefix}${cleanName}`;
|
|
1240
1295
|
}
|
|
1241
|
-
const sourName = get(this, "HEAD.SOUR.NAME.value") || get(this.getGedcom(), "HEAD.SOUR.NAME.value");
|
|
1296
|
+
const sourName = this.getFromSourceHeads("SOUR.NAME.value") || get(this, "HEAD.SOUR.NAME.value") || get(this.getGedcom(), "HEAD.SOUR.NAME.value");
|
|
1242
1297
|
if (sourName) {
|
|
1243
1298
|
return `${prefix}${sourName}`;
|
|
1244
1299
|
}
|
|
1245
|
-
const sourValue = get(this, "HEAD.SOUR.value") || get(this.getGedcom(), "HEAD.SOUR.value");
|
|
1300
|
+
const sourValue = this.getFromSourceHeads("SOUR.value") || get(this, "HEAD.SOUR.value") || get(this.getGedcom(), "HEAD.SOUR.value");
|
|
1246
1301
|
if (sourValue) {
|
|
1247
1302
|
return `${prefix}${sourValue}`;
|
|
1248
1303
|
}
|
|
@@ -1308,7 +1363,7 @@ var isOnlyMainProp = (key) => {
|
|
|
1308
1363
|
};
|
|
1309
1364
|
var isValidKey = (common, key) => {
|
|
1310
1365
|
const prop = get(common, key);
|
|
1311
|
-
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);
|
|
1366
|
+
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);
|
|
1312
1367
|
};
|
|
1313
1368
|
var getValidKeys = (common) => {
|
|
1314
1369
|
return Object.keys(common).filter((key) => {
|
|
@@ -1802,6 +1857,352 @@ var dateFormatter = (indi, showMarriages = false, showDays = false, showPlaces =
|
|
|
1802
1857
|
};
|
|
1803
1858
|
};
|
|
1804
1859
|
|
|
1860
|
+
// src/utils/fact-edit.ts
|
|
1861
|
+
var SINGLETON_TAGS = /* @__PURE__ */ new Set(["BIRT", "DEAT", "SSN", "SEX", "DSCR"]);
|
|
1862
|
+
var firstRecord = (node) => {
|
|
1863
|
+
if (!node) {
|
|
1864
|
+
return void 0;
|
|
1865
|
+
}
|
|
1866
|
+
if (node instanceof List) {
|
|
1867
|
+
return node.index(0);
|
|
1868
|
+
}
|
|
1869
|
+
return node.index(0) ?? node;
|
|
1870
|
+
};
|
|
1871
|
+
var setDateOn = (gedcom, owner, parent, date) => {
|
|
1872
|
+
const trimmed = date.trim();
|
|
1873
|
+
if (!trimmed) {
|
|
1874
|
+
return;
|
|
1875
|
+
}
|
|
1876
|
+
let dateNode = parent.get("DATE");
|
|
1877
|
+
if (!dateNode || dateNode instanceof List) {
|
|
1878
|
+
dateNode = createCommonDate(gedcom, void 0, owner, parent);
|
|
1879
|
+
dateNode.type = "DATE";
|
|
1880
|
+
parent.set("DATE", dateNode);
|
|
1881
|
+
}
|
|
1882
|
+
dateNode.value = trimmed;
|
|
1883
|
+
};
|
|
1884
|
+
var fillFact = (gedcom, owner, event, input) => {
|
|
1885
|
+
if (input.value?.trim()) {
|
|
1886
|
+
event.value = input.value.trim();
|
|
1887
|
+
}
|
|
1888
|
+
if (input.type?.trim()) {
|
|
1889
|
+
event.set("TYPE", input.type.trim());
|
|
1890
|
+
}
|
|
1891
|
+
if (input.date) {
|
|
1892
|
+
setDateOn(gedcom, owner, event, input.date);
|
|
1893
|
+
}
|
|
1894
|
+
if (input.place?.trim()) {
|
|
1895
|
+
event.set("PLAC", input.place.trim());
|
|
1896
|
+
}
|
|
1897
|
+
if (input.note?.trim()) {
|
|
1898
|
+
event.set("NOTE", input.note.trim());
|
|
1899
|
+
}
|
|
1900
|
+
};
|
|
1901
|
+
var updateFactRecord = (owner, event, input) => {
|
|
1902
|
+
const gedcom = owner.getGedcom();
|
|
1903
|
+
if (!gedcom) {
|
|
1904
|
+
return event;
|
|
1905
|
+
}
|
|
1906
|
+
const asOwner = owner;
|
|
1907
|
+
if (input.value !== void 0) {
|
|
1908
|
+
const trimmed = input.value.trim();
|
|
1909
|
+
if (trimmed) {
|
|
1910
|
+
event.value = trimmed;
|
|
1911
|
+
} else {
|
|
1912
|
+
event.removeValue();
|
|
1913
|
+
}
|
|
1914
|
+
}
|
|
1915
|
+
if (input.type !== void 0) {
|
|
1916
|
+
const trimmed = input.type.trim();
|
|
1917
|
+
if (trimmed) {
|
|
1918
|
+
event.set("TYPE", trimmed);
|
|
1919
|
+
} else {
|
|
1920
|
+
event.remove("TYPE");
|
|
1921
|
+
}
|
|
1922
|
+
}
|
|
1923
|
+
if (input.date !== void 0) {
|
|
1924
|
+
const trimmed = input.date.trim();
|
|
1925
|
+
if (trimmed) {
|
|
1926
|
+
setDateOn(gedcom, asOwner, event, trimmed);
|
|
1927
|
+
} else {
|
|
1928
|
+
event.remove("DATE");
|
|
1929
|
+
}
|
|
1930
|
+
}
|
|
1931
|
+
if (input.place !== void 0) {
|
|
1932
|
+
const trimmed = input.place.trim();
|
|
1933
|
+
if (trimmed) {
|
|
1934
|
+
event.set("PLAC", trimmed);
|
|
1935
|
+
} else {
|
|
1936
|
+
event.remove("PLAC");
|
|
1937
|
+
}
|
|
1938
|
+
}
|
|
1939
|
+
if (input.note !== void 0) {
|
|
1940
|
+
const trimmed = input.note.trim();
|
|
1941
|
+
if (trimmed) {
|
|
1942
|
+
event.set("NOTE", trimmed);
|
|
1943
|
+
} else {
|
|
1944
|
+
event.remove("NOTE");
|
|
1945
|
+
}
|
|
1946
|
+
}
|
|
1947
|
+
return event;
|
|
1948
|
+
};
|
|
1949
|
+
var setFamilyMarriage = (fam, input) => {
|
|
1950
|
+
const existing = firstRecord(fam.get("MARR"));
|
|
1951
|
+
if (existing) {
|
|
1952
|
+
return updateFactRecord(fam, existing, {
|
|
1953
|
+
date: input.date,
|
|
1954
|
+
place: input.place
|
|
1955
|
+
});
|
|
1956
|
+
}
|
|
1957
|
+
return addFamilyFact(fam, {
|
|
1958
|
+
tag: "MARR",
|
|
1959
|
+
date: input.date,
|
|
1960
|
+
place: input.place
|
|
1961
|
+
});
|
|
1962
|
+
};
|
|
1963
|
+
var addIndividualFact = (indi, input) => {
|
|
1964
|
+
const gedcom = indi.getGedcom();
|
|
1965
|
+
if (!gedcom) {
|
|
1966
|
+
return void 0;
|
|
1967
|
+
}
|
|
1968
|
+
const tag = input.tag;
|
|
1969
|
+
let event = SINGLETON_TAGS.has(tag) ? firstRecord(indi.get(tag)) : void 0;
|
|
1970
|
+
if (!event) {
|
|
1971
|
+
event = createCommon(gedcom, void 0, indi);
|
|
1972
|
+
event.type = tag;
|
|
1973
|
+
if (SINGLETON_TAGS.has(tag)) {
|
|
1974
|
+
indi.set(tag, event);
|
|
1975
|
+
} else {
|
|
1976
|
+
indi.assign(tag, event);
|
|
1977
|
+
}
|
|
1978
|
+
}
|
|
1979
|
+
fillFact(gedcom, indi, event, input);
|
|
1980
|
+
return event;
|
|
1981
|
+
};
|
|
1982
|
+
var addFamilyFact = (fam, input) => {
|
|
1983
|
+
const gedcom = fam.getGedcom();
|
|
1984
|
+
if (!gedcom) {
|
|
1985
|
+
return void 0;
|
|
1986
|
+
}
|
|
1987
|
+
const event = createCommon(gedcom, void 0, fam);
|
|
1988
|
+
event.type = input.tag;
|
|
1989
|
+
fam.assign(input.tag, event);
|
|
1990
|
+
fillFact(gedcom, fam, event, input);
|
|
1991
|
+
return event;
|
|
1992
|
+
};
|
|
1993
|
+
var setCauseOfDeath = (indi, text) => {
|
|
1994
|
+
const trimmed = text.trim();
|
|
1995
|
+
if (!trimmed) {
|
|
1996
|
+
return void 0;
|
|
1997
|
+
}
|
|
1998
|
+
const death = firstRecord(indi.get("DEAT")) || addIndividualFact(indi, { tag: "DEAT", value: "Y" });
|
|
1999
|
+
if (!death) {
|
|
2000
|
+
return void 0;
|
|
2001
|
+
}
|
|
2002
|
+
death.set("CAUS", trimmed);
|
|
2003
|
+
return death;
|
|
2004
|
+
};
|
|
2005
|
+
var setDeceased = (indi, deceased) => {
|
|
2006
|
+
if (!deceased) {
|
|
2007
|
+
indi.remove("DEAT");
|
|
2008
|
+
return;
|
|
2009
|
+
}
|
|
2010
|
+
if (firstRecord(indi.get("DEAT"))) {
|
|
2011
|
+
return;
|
|
2012
|
+
}
|
|
2013
|
+
addIndividualFact(indi, { tag: "DEAT", value: "Y" });
|
|
2014
|
+
};
|
|
2015
|
+
var addNonEvent = (owner, input) => {
|
|
2016
|
+
const gedcom = owner.getGedcom();
|
|
2017
|
+
const eventType = input.event?.trim().toUpperCase();
|
|
2018
|
+
if (!gedcom || !eventType) {
|
|
2019
|
+
return void 0;
|
|
2020
|
+
}
|
|
2021
|
+
const no = createCommon(gedcom, void 0, owner);
|
|
2022
|
+
no.type = "NO";
|
|
2023
|
+
no.value = eventType;
|
|
2024
|
+
if (input.date?.trim()) {
|
|
2025
|
+
setDateOn(gedcom, owner, no, input.date);
|
|
2026
|
+
}
|
|
2027
|
+
if (input.note?.trim()) {
|
|
2028
|
+
no.set("NOTE", input.note.trim());
|
|
2029
|
+
}
|
|
2030
|
+
owner.assign("NO", no);
|
|
2031
|
+
return no;
|
|
2032
|
+
};
|
|
2033
|
+
|
|
2034
|
+
// src/utils/family-edit.ts
|
|
2035
|
+
var PEDIGREE_VALUES = [
|
|
2036
|
+
"birth" /* BIRTH */,
|
|
2037
|
+
"adopted" /* ADOPTED */,
|
|
2038
|
+
"foster" /* FOSTER */,
|
|
2039
|
+
"step" /* STEP */,
|
|
2040
|
+
"sealing" /* SEALING */
|
|
2041
|
+
];
|
|
2042
|
+
var toGedcomPedigree = (value) => {
|
|
2043
|
+
const normalized = String(value || "birth" /* BIRTH */).toLowerCase();
|
|
2044
|
+
if (normalized === "biological" /* BIOLOGICAL */ || normalized === "birth" /* BIRTH */) {
|
|
2045
|
+
return "birth" /* BIRTH */;
|
|
2046
|
+
}
|
|
2047
|
+
const match = PEDIGREE_VALUES.find((item) => item === normalized);
|
|
2048
|
+
return match ?? "birth" /* BIRTH */;
|
|
2049
|
+
};
|
|
2050
|
+
var pointerIds = (tag) => {
|
|
2051
|
+
if (!tag) {
|
|
2052
|
+
return [];
|
|
2053
|
+
}
|
|
2054
|
+
if (tag instanceof List) {
|
|
2055
|
+
return tag.values().map((item) => item?.toValue?.()).filter((value2) => !!value2);
|
|
2056
|
+
}
|
|
2057
|
+
const value = tag.toValue?.();
|
|
2058
|
+
return value ? [String(value)] : [];
|
|
2059
|
+
};
|
|
2060
|
+
var firstPointerId = (tag) => pointerIds(tag)[0];
|
|
2061
|
+
var makePointer = (gedcom, parent, value, refType) => {
|
|
2062
|
+
const pointer = createCommon(gedcom, void 0, parent);
|
|
2063
|
+
pointer.value = value;
|
|
2064
|
+
pointer.refType = refType;
|
|
2065
|
+
return pointer;
|
|
2066
|
+
};
|
|
2067
|
+
var nextRecordId = (ids, prefix) => {
|
|
2068
|
+
let max = 0;
|
|
2069
|
+
ids.forEach((id) => {
|
|
2070
|
+
const match = String(id).match(/(\d+)/);
|
|
2071
|
+
const n = match ? Number.parseInt(match[1], 10) : 0;
|
|
2072
|
+
if (n > max) {
|
|
2073
|
+
max = n;
|
|
2074
|
+
}
|
|
2075
|
+
});
|
|
2076
|
+
return `@${prefix}${max + 1}@`;
|
|
2077
|
+
};
|
|
2078
|
+
var familyHasParent = (fam, indiId) => pointerIds(fam.get("HUSB")).includes(indiId) || pointerIds(fam.get("WIFE")).includes(indiId);
|
|
2079
|
+
var familyHasChild = (fam, indiId) => pointerIds(fam.get("CHIL")).includes(indiId);
|
|
2080
|
+
var spouseTagFor = (indi, fam) => {
|
|
2081
|
+
const husbId = firstPointerId(fam.get("HUSB"));
|
|
2082
|
+
const wifeId = firstPointerId(fam.get("WIFE"));
|
|
2083
|
+
if (husbId === indi.id) {
|
|
2084
|
+
return "HUSB";
|
|
2085
|
+
}
|
|
2086
|
+
if (wifeId === indi.id) {
|
|
2087
|
+
return "WIFE";
|
|
2088
|
+
}
|
|
2089
|
+
if (indi.isFemale()) {
|
|
2090
|
+
return wifeId && wifeId !== indi.id ? "HUSB" : "WIFE";
|
|
2091
|
+
}
|
|
2092
|
+
if (indi.isMale()) {
|
|
2093
|
+
return husbId && husbId !== indi.id ? "WIFE" : "HUSB";
|
|
2094
|
+
}
|
|
2095
|
+
return husbId ? "WIFE" : "HUSB";
|
|
2096
|
+
};
|
|
2097
|
+
var canAttachAsSpouse = (fam, indi) => {
|
|
2098
|
+
if (!indi.id) {
|
|
2099
|
+
return false;
|
|
2100
|
+
}
|
|
2101
|
+
if (familyHasParent(fam, indi.id)) {
|
|
2102
|
+
return true;
|
|
2103
|
+
}
|
|
2104
|
+
const tag = spouseTagFor(indi, fam);
|
|
2105
|
+
const occupied = firstPointerId(fam.get(tag));
|
|
2106
|
+
return !occupied || occupied === indi.id;
|
|
2107
|
+
};
|
|
2108
|
+
var pointerByValue = (tag, id) => {
|
|
2109
|
+
if (!tag) {
|
|
2110
|
+
return void 0;
|
|
2111
|
+
}
|
|
2112
|
+
const fromValues = tag.toValueList?.().item(id);
|
|
2113
|
+
if (fromValues) {
|
|
2114
|
+
return fromValues;
|
|
2115
|
+
}
|
|
2116
|
+
return tag.toList()?.values().find((item) => item?.toValue?.() === id);
|
|
2117
|
+
};
|
|
2118
|
+
var setChildPedigree = (fam, child, pedigree, parent) => {
|
|
2119
|
+
if (!fam.id || !child.id) {
|
|
2120
|
+
return;
|
|
2121
|
+
}
|
|
2122
|
+
const pedi = toGedcomPedigree(pedigree);
|
|
2123
|
+
const famc = pointerByValue(child.get("FAMC"), fam.id);
|
|
2124
|
+
if (famc) {
|
|
2125
|
+
famc.set("PEDI", pedi);
|
|
2126
|
+
}
|
|
2127
|
+
const chil = pointerByValue(fam.get("CHIL"), child.id);
|
|
2128
|
+
if (!chil) {
|
|
2129
|
+
return;
|
|
2130
|
+
}
|
|
2131
|
+
const setFather = !parent || parent.isMale() || parent.isUnknownSex();
|
|
2132
|
+
const setMother = !parent || parent.isFemale() || parent.isUnknownSex();
|
|
2133
|
+
if (setFather) {
|
|
2134
|
+
chil.set("_FREL", pedi);
|
|
2135
|
+
}
|
|
2136
|
+
if (setMother) {
|
|
2137
|
+
chil.set("_MREL", pedi);
|
|
2138
|
+
}
|
|
2139
|
+
};
|
|
2140
|
+
var attachSpouseToFamily = (fam, indi) => {
|
|
2141
|
+
const gedcom = fam.getGedcom() ?? indi.getGedcom();
|
|
2142
|
+
if (!indi.id || !fam.id || !gedcom) {
|
|
2143
|
+
return false;
|
|
2144
|
+
}
|
|
2145
|
+
if (!canAttachAsSpouse(fam, indi)) {
|
|
2146
|
+
return false;
|
|
2147
|
+
}
|
|
2148
|
+
const tag = spouseTagFor(indi, fam);
|
|
2149
|
+
if (firstPointerId(fam.get(tag)) !== indi.id) {
|
|
2150
|
+
fam.set(tag, makePointer(gedcom, fam, indi.id, "INDI"));
|
|
2151
|
+
}
|
|
2152
|
+
indi.assign("FAMS", makePointer(gedcom, indi, fam.id, "FAM"), true);
|
|
2153
|
+
return true;
|
|
2154
|
+
};
|
|
2155
|
+
var attachChildToFamily = (fam, child, pedigree, parent) => {
|
|
2156
|
+
const gedcom = fam.getGedcom() ?? child.getGedcom();
|
|
2157
|
+
if (!child.id || !fam.id || !gedcom) {
|
|
2158
|
+
return false;
|
|
2159
|
+
}
|
|
2160
|
+
if (!familyHasChild(fam, child.id)) {
|
|
2161
|
+
fam.assign("CHIL", makePointer(gedcom, fam, child.id, "INDI"), true);
|
|
2162
|
+
}
|
|
2163
|
+
const existingFamc = pointerByValue(child.get("FAMC"), fam.id);
|
|
2164
|
+
if (!existingFamc) {
|
|
2165
|
+
child.assign("FAMC", makePointer(gedcom, child, fam.id, "FAM"), true);
|
|
2166
|
+
}
|
|
2167
|
+
setChildPedigree(fam, child, pedigree, parent);
|
|
2168
|
+
return true;
|
|
2169
|
+
};
|
|
2170
|
+
var findReusableParentChildFamily = (parent, child) => {
|
|
2171
|
+
if (!parent.id || !child.id) {
|
|
2172
|
+
return void 0;
|
|
2173
|
+
}
|
|
2174
|
+
let reusableFamc;
|
|
2175
|
+
let already = false;
|
|
2176
|
+
child.getFamilies("FAMC")?.forEach((fam) => {
|
|
2177
|
+
if (!fam) {
|
|
2178
|
+
return;
|
|
2179
|
+
}
|
|
2180
|
+
if (familyHasParent(fam, parent.id) && familyHasChild(fam, child.id)) {
|
|
2181
|
+
already = true;
|
|
2182
|
+
return;
|
|
2183
|
+
}
|
|
2184
|
+
if (!reusableFamc && canAttachAsSpouse(fam, parent)) {
|
|
2185
|
+
reusableFamc = fam;
|
|
2186
|
+
}
|
|
2187
|
+
});
|
|
2188
|
+
if (already) {
|
|
2189
|
+
return "already";
|
|
2190
|
+
}
|
|
2191
|
+
if (reusableFamc) {
|
|
2192
|
+
return reusableFamc;
|
|
2193
|
+
}
|
|
2194
|
+
const parentFams = [];
|
|
2195
|
+
parent.getFamilies("FAMS")?.forEach((fam) => {
|
|
2196
|
+
if (fam) {
|
|
2197
|
+
parentFams.push(fam);
|
|
2198
|
+
}
|
|
2199
|
+
});
|
|
2200
|
+
if (parentFams.length === 1) {
|
|
2201
|
+
return parentFams[0];
|
|
2202
|
+
}
|
|
2203
|
+
return void 0;
|
|
2204
|
+
};
|
|
2205
|
+
|
|
1805
2206
|
// src/utils/get-places.ts
|
|
1806
2207
|
var PlaceType = /* @__PURE__ */ ((PlaceType2) => {
|
|
1807
2208
|
PlaceType2["All"] = "ALL";
|
|
@@ -1876,6 +2277,81 @@ var getPlaces = (common, type = ["ALL" /* All */], maxLevel = 1, level = 0, main
|
|
|
1876
2277
|
});
|
|
1877
2278
|
return places;
|
|
1878
2279
|
};
|
|
2280
|
+
|
|
2281
|
+
// src/utils/local-media.ts
|
|
2282
|
+
var localMediaResolver;
|
|
2283
|
+
var mediaContentResolver;
|
|
2284
|
+
var setLocalMediaResolver = (resolver) => {
|
|
2285
|
+
localMediaResolver = resolver;
|
|
2286
|
+
};
|
|
2287
|
+
var setMediaContentResolver = (resolver) => {
|
|
2288
|
+
mediaContentResolver = resolver;
|
|
2289
|
+
};
|
|
2290
|
+
var isRemoteOrEmbeddedMediaUrl = (path) => {
|
|
2291
|
+
if (!path) {
|
|
2292
|
+
return false;
|
|
2293
|
+
}
|
|
2294
|
+
return path.startsWith("data:") || path.startsWith("blob:") || /^https?:\/\//i.test(path);
|
|
2295
|
+
};
|
|
2296
|
+
var resolveLocalMediaUrl = async (path) => {
|
|
2297
|
+
if (!path) {
|
|
2298
|
+
return void 0;
|
|
2299
|
+
}
|
|
2300
|
+
if (isRemoteOrEmbeddedMediaUrl(path)) {
|
|
2301
|
+
return path;
|
|
2302
|
+
}
|
|
2303
|
+
const resolved = await localMediaResolver?.(path);
|
|
2304
|
+
return resolved;
|
|
2305
|
+
};
|
|
2306
|
+
var blobToDataUrl = async (blob) => {
|
|
2307
|
+
const buffer = await blob.arrayBuffer();
|
|
2308
|
+
const bytes = new Uint8Array(buffer);
|
|
2309
|
+
const mime = blob.type || "application/octet-stream";
|
|
2310
|
+
if (typeof Buffer !== "undefined") {
|
|
2311
|
+
return `data:${mime};base64,${Buffer.from(bytes).toString("base64")}`;
|
|
2312
|
+
}
|
|
2313
|
+
let binary = "";
|
|
2314
|
+
const chunk = 32768;
|
|
2315
|
+
for (let i = 0; i < bytes.length; i += chunk) {
|
|
2316
|
+
binary += String.fromCharCode(...bytes.subarray(i, i + chunk));
|
|
2317
|
+
}
|
|
2318
|
+
return `data:${mime};base64,${btoa(binary)}`;
|
|
2319
|
+
};
|
|
2320
|
+
var resolveMediaContent = async (media) => {
|
|
2321
|
+
const fromHost = await mediaContentResolver?.(media);
|
|
2322
|
+
if (fromHost?.content) {
|
|
2323
|
+
return fromHost;
|
|
2324
|
+
}
|
|
2325
|
+
const url = media.url;
|
|
2326
|
+
if (!url) {
|
|
2327
|
+
return void 0;
|
|
2328
|
+
}
|
|
2329
|
+
if (url.startsWith("data:") || url.startsWith("blob:")) {
|
|
2330
|
+
return { content: url, contentType: media.contentType };
|
|
2331
|
+
}
|
|
2332
|
+
if (!isRemoteOrEmbeddedMediaUrl(url)) {
|
|
2333
|
+
const local = await resolveLocalMediaUrl(url);
|
|
2334
|
+
if (local && isRemoteOrEmbeddedMediaUrl(local)) {
|
|
2335
|
+
return { content: local, contentType: media.contentType };
|
|
2336
|
+
}
|
|
2337
|
+
return void 0;
|
|
2338
|
+
}
|
|
2339
|
+
if (typeof fetch !== "function") {
|
|
2340
|
+
return void 0;
|
|
2341
|
+
}
|
|
2342
|
+
try {
|
|
2343
|
+
const response = await fetch(url);
|
|
2344
|
+
if (!response.ok) {
|
|
2345
|
+
return void 0;
|
|
2346
|
+
}
|
|
2347
|
+
const blob = await response.blob();
|
|
2348
|
+
const content = await blobToDataUrl(blob);
|
|
2349
|
+
const contentType = media.contentType || blob.type.split("/").pop() || "bin";
|
|
2350
|
+
return { content, contentType };
|
|
2351
|
+
} catch {
|
|
2352
|
+
return void 0;
|
|
2353
|
+
}
|
|
2354
|
+
};
|
|
1879
2355
|
var implemented = (type, ...args) => {
|
|
1880
2356
|
};
|
|
1881
2357
|
var notImplemented = (type, ...args) => {
|
|
@@ -1884,11 +2360,34 @@ var notImplemented = (type, ...args) => {
|
|
|
1884
2360
|
|
|
1885
2361
|
// src/utils/media-utils.ts
|
|
1886
2362
|
var getFileExtension = (filename) => {
|
|
1887
|
-
|
|
1888
|
-
|
|
2363
|
+
if (!filename) {
|
|
2364
|
+
return "";
|
|
2365
|
+
}
|
|
2366
|
+
if (filename.startsWith("data:")) {
|
|
2367
|
+
const mime = filename.slice(5).split(";")[0] || "";
|
|
2368
|
+
const subtype = (mime.split("/")[1] || "").toLowerCase();
|
|
2369
|
+
if (subtype === "jpeg") {
|
|
2370
|
+
return "jpg";
|
|
2371
|
+
}
|
|
2372
|
+
return subtype.split("+")[0] || "";
|
|
2373
|
+
}
|
|
2374
|
+
const withoutQuery = filename.split(/[?#]/)[0] || filename;
|
|
2375
|
+
const match = withoutQuery.match(/\.([^.]+)$/);
|
|
2376
|
+
return match ? match[1].toLowerCase() : "";
|
|
1889
2377
|
};
|
|
1890
2378
|
var isImageFormat = (format2) => {
|
|
1891
|
-
if (!format2)
|
|
2379
|
+
if (!format2) {
|
|
2380
|
+
return false;
|
|
2381
|
+
}
|
|
2382
|
+
let normalized = format2.toLowerCase().trim();
|
|
2383
|
+
if (normalized.startsWith("data:")) {
|
|
2384
|
+
normalized = getFileExtension(normalized);
|
|
2385
|
+
} else if (normalized.includes("/")) {
|
|
2386
|
+
normalized = normalized.split("/")[1]?.split("+")[0] || "";
|
|
2387
|
+
if (normalized === "jpeg") {
|
|
2388
|
+
normalized = "jpg";
|
|
2389
|
+
}
|
|
2390
|
+
}
|
|
1892
2391
|
const imageFormats = [
|
|
1893
2392
|
"jpg",
|
|
1894
2393
|
"jpeg",
|
|
@@ -1900,7 +2399,11 @@ var isImageFormat = (format2) => {
|
|
|
1900
2399
|
"tiff",
|
|
1901
2400
|
"tif"
|
|
1902
2401
|
];
|
|
1903
|
-
return imageFormats.includes(
|
|
2402
|
+
return imageFormats.includes(normalized);
|
|
2403
|
+
};
|
|
2404
|
+
var resolveObjeForm = (obje) => {
|
|
2405
|
+
const value = obje?.get?.("FILE.FORM")?.toValue?.() ?? obje?.get?.("FORM")?.toValue?.();
|
|
2406
|
+
return typeof value === "string" && value.trim() ? value.trim() : void 0;
|
|
1904
2407
|
};
|
|
1905
2408
|
var uniqueItemsCache = /* @__PURE__ */ new WeakMap();
|
|
1906
2409
|
var setNestedGroup = (obj, key, value, uniqueCounting = true) => {
|
|
@@ -2445,6 +2948,34 @@ var Fam = class extends Common {
|
|
|
2445
2948
|
getParents() {
|
|
2446
2949
|
return this.getHusband().copy().merge(this.getWife());
|
|
2447
2950
|
}
|
|
2951
|
+
hasParent(indi) {
|
|
2952
|
+
const indiId = typeof indi === "string" ? indi : indi?.id;
|
|
2953
|
+
return !!indiId && familyHasParent(this, indiId);
|
|
2954
|
+
}
|
|
2955
|
+
hasChild(indi) {
|
|
2956
|
+
const indiId = typeof indi === "string" ? indi : indi?.id;
|
|
2957
|
+
return !!indiId && familyHasChild(this, indiId);
|
|
2958
|
+
}
|
|
2959
|
+
canAddSpouse(indi) {
|
|
2960
|
+
return canAttachAsSpouse(this, indi);
|
|
2961
|
+
}
|
|
2962
|
+
addSpouse(indi) {
|
|
2963
|
+
return attachSpouseToFamily(this, indi);
|
|
2964
|
+
}
|
|
2965
|
+
addChild(child, pedigree, parent) {
|
|
2966
|
+
return attachChildToFamily(
|
|
2967
|
+
this,
|
|
2968
|
+
child,
|
|
2969
|
+
pedigree,
|
|
2970
|
+
parent
|
|
2971
|
+
);
|
|
2972
|
+
}
|
|
2973
|
+
addFact(input) {
|
|
2974
|
+
return addFamilyFact(this, input);
|
|
2975
|
+
}
|
|
2976
|
+
addNonEvent(input) {
|
|
2977
|
+
return addNonEvent(this, input);
|
|
2978
|
+
}
|
|
2448
2979
|
toList() {
|
|
2449
2980
|
return new Families().concat(
|
|
2450
2981
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
@@ -2550,19 +3081,51 @@ var ALLOWED_FACTS = [
|
|
|
2550
3081
|
"OCCU",
|
|
2551
3082
|
"OCCUPATIONS",
|
|
2552
3083
|
"RESI",
|
|
3084
|
+
"BIRT",
|
|
3085
|
+
"DEAT",
|
|
2553
3086
|
"BAPT",
|
|
3087
|
+
"BAPM",
|
|
2554
3088
|
"CHRI",
|
|
2555
3089
|
"CHR",
|
|
3090
|
+
"CHRA",
|
|
2556
3091
|
"BURI",
|
|
2557
|
-
"
|
|
3092
|
+
"CREM",
|
|
3093
|
+
"ADOP",
|
|
3094
|
+
"BARM",
|
|
3095
|
+
"BASM",
|
|
3096
|
+
"BLES",
|
|
3097
|
+
"CONF",
|
|
3098
|
+
"FCOM",
|
|
3099
|
+
"ORDN",
|
|
3100
|
+
"NATU",
|
|
3101
|
+
"EMIG",
|
|
3102
|
+
"IMMI",
|
|
3103
|
+
"CENS",
|
|
3104
|
+
"PROB",
|
|
3105
|
+
"WILL",
|
|
2558
3106
|
"GRAD",
|
|
3107
|
+
"RETI",
|
|
3108
|
+
"EDUC",
|
|
2559
3109
|
"DIV",
|
|
2560
|
-
"IMMI",
|
|
2561
3110
|
"RELI",
|
|
3111
|
+
"CAST",
|
|
3112
|
+
"DSCR",
|
|
3113
|
+
"NATI",
|
|
3114
|
+
"PROP",
|
|
3115
|
+
"SSN",
|
|
3116
|
+
"TITL",
|
|
3117
|
+
"ADDR",
|
|
3118
|
+
"BAPL",
|
|
3119
|
+
"CONL",
|
|
3120
|
+
"ENDL",
|
|
3121
|
+
"SLGC",
|
|
2562
3122
|
"_MILT",
|
|
2563
3123
|
"_MILTID",
|
|
2564
3124
|
"FACT",
|
|
2565
|
-
"_ORIG"
|
|
3125
|
+
"_ORIG",
|
|
3126
|
+
"_WLNK",
|
|
3127
|
+
"WWW",
|
|
3128
|
+
"URL"
|
|
2566
3129
|
];
|
|
2567
3130
|
var DISALLOWED_CUSTOM_FACTS = ["DNA Test", "Newspaper"];
|
|
2568
3131
|
var CustomFactRenderers = {
|
|
@@ -3106,7 +3669,7 @@ var Indi = class extends Common {
|
|
|
3106
3669
|
return result;
|
|
3107
3670
|
}
|
|
3108
3671
|
ancestryLink() {
|
|
3109
|
-
const www = this._gedcom?.HEAD?.SOUR?.CORP?.WWW?.value;
|
|
3672
|
+
const www = this.getFromSourceHeads("SOUR.CORP.WWW.value") || this._gedcom?.HEAD?.SOUR?.CORP?.WWW?.value;
|
|
3110
3673
|
const tree = this.getAncestryTreeId();
|
|
3111
3674
|
if (this.id) {
|
|
3112
3675
|
return `https://${www}/family-tree/person/tree/${tree}/person/${this.id.replace(
|
|
@@ -3118,7 +3681,7 @@ var Indi = class extends Common {
|
|
|
3118
3681
|
async ancestryMedia(namespace) {
|
|
3119
3682
|
const list = {};
|
|
3120
3683
|
const objeList = this.get("OBJE")?.toList().copy();
|
|
3121
|
-
const www = this._gedcom?.HEAD?.SOUR?.CORP?.WWW?.value;
|
|
3684
|
+
const www = this.getFromSourceHeads("SOUR.CORP.WWW.value") || this._gedcom?.HEAD?.SOUR?.CORP?.WWW?.value;
|
|
3122
3685
|
const tree = this.getAncestryTreeId();
|
|
3123
3686
|
if (objeList) {
|
|
3124
3687
|
await Promise.all(
|
|
@@ -3136,10 +3699,14 @@ var Indi = class extends Common {
|
|
|
3136
3699
|
const clone = obje?.get("_CLON._OID")?.toValue();
|
|
3137
3700
|
const mser = obje?.get("_MSER._LKID")?.toValue();
|
|
3138
3701
|
let url = obje?.get("FILE")?.toValue();
|
|
3139
|
-
const title = obje?.get("TITL")?.toValue() ?? "";
|
|
3140
|
-
const type = obje
|
|
3141
|
-
|
|
3142
|
-
|
|
3702
|
+
const title = obje?.get("FILE.TITL")?.toValue() ?? obje?.get("TITL")?.toValue() ?? "";
|
|
3703
|
+
const type = resolveObjeForm(obje) ?? (url ? getFileExtension(url) : void 0) ?? "raw";
|
|
3704
|
+
let imgId = clone || mser;
|
|
3705
|
+
const hasEmbeddedOrLocalFile = !!url && (url.startsWith("data:") || url.startsWith("blob:") || !/^https?:\/\//i.test(url));
|
|
3706
|
+
if (!hasEmbeddedOrLocalFile && (!www || !tree || !this.id)) {
|
|
3707
|
+
return;
|
|
3708
|
+
}
|
|
3709
|
+
if (!this.id) {
|
|
3143
3710
|
return;
|
|
3144
3711
|
}
|
|
3145
3712
|
if (!namespace && !url) {
|
|
@@ -3157,13 +3724,16 @@ var Indi = class extends Common {
|
|
|
3157
3724
|
}
|
|
3158
3725
|
url = url || `https://${www}/mediaui-viewer/tree/${tree}/media/${media}`;
|
|
3159
3726
|
}
|
|
3727
|
+
if (!imgId && hasEmbeddedOrLocalFile && url) {
|
|
3728
|
+
imgId = typeof media === "string" && media || `local-${String(key).replace(/[@]/g, "")}-${getFileExtension(url) || "bin"}`;
|
|
3729
|
+
}
|
|
3160
3730
|
if (url && imgId) {
|
|
3161
|
-
const id = `${tree}-${this.id}-${imgId}`;
|
|
3731
|
+
const id = `${tree || "gedzip"}-${this.id}-${imgId}`;
|
|
3162
3732
|
list[id] = {
|
|
3163
3733
|
key,
|
|
3164
3734
|
isPrimary,
|
|
3165
3735
|
id,
|
|
3166
|
-
tree,
|
|
3736
|
+
tree: tree || "gedzip",
|
|
3167
3737
|
imgId,
|
|
3168
3738
|
person: this.id,
|
|
3169
3739
|
title,
|
|
@@ -3178,7 +3748,7 @@ var Indi = class extends Common {
|
|
|
3178
3748
|
return list;
|
|
3179
3749
|
}
|
|
3180
3750
|
myheritageLink(poolId = 0) {
|
|
3181
|
-
const www = this._gedcom?.HEAD?.SOUR?.CORP?.value?.toLowerCase().replace(/^www\./gi, "");
|
|
3751
|
+
const www = (this.getFromSourceHeads("SOUR.CORP.value") || this._gedcom?.HEAD?.SOUR?.CORP?.value)?.toLowerCase().replace(/^www\./gi, "");
|
|
3182
3752
|
const site = this.getMyHeritageTreeId();
|
|
3183
3753
|
const file = this._gedcom?.HEAD?.get("FILE")?.toValue()?.match(/Exported by MyHeritage.com from .+ in (?<site>.+) on .+$/)?.groups?.site;
|
|
3184
3754
|
const normalizedFile = file?.normalize("NFD").replace(/[\u0300-\u036f]/g, "").toLowerCase().replace(/[^a-z0-9]+/g, "-");
|
|
@@ -3209,9 +3779,11 @@ var Indi = class extends Common {
|
|
|
3209
3779
|
obje.standardizeMedia();
|
|
3210
3780
|
const isPrimary = obje?.get("_PRIM")?.toValue() === "Y";
|
|
3211
3781
|
const url = obje?.get("FILE")?.toValue();
|
|
3212
|
-
const title = obje?.get("NOTE")?.toValue() ?? "";
|
|
3213
|
-
const type = obje
|
|
3214
|
-
const
|
|
3782
|
+
const title = obje?.get("FILE.NOTE")?.toValue() ?? obje?.get("NOTE")?.toValue() ?? "";
|
|
3783
|
+
const type = resolveObjeForm(obje) ?? (url ? getFileExtension(url) : void 0) ?? "raw";
|
|
3784
|
+
const photoRin = obje?.get("_PHOTO_RIN")?.toValue();
|
|
3785
|
+
const hasEmbeddedOrLocalFile = !!url && (url.startsWith("data:") || url.startsWith("blob:") || !/^https?:\/\//i.test(url));
|
|
3786
|
+
const imgId = photoRin || (hasEmbeddedOrLocalFile && url ? `local-${String(key).replace(/[@]/g, "")}-${getFileExtension(url) || "bin"}` : void 0);
|
|
3215
3787
|
if (url && imgId) {
|
|
3216
3788
|
const id = `${tree}-${this.id}-${imgId}`;
|
|
3217
3789
|
list[id] = {
|
|
@@ -3334,10 +3906,10 @@ var Indi = class extends Common {
|
|
|
3334
3906
|
const isPrimary = obje?.get("_PRIM")?.toValue() === "Y";
|
|
3335
3907
|
const url = obje?.get("FILE")?.toValue();
|
|
3336
3908
|
const title = obje?.get("TITL")?.toValue() ?? "";
|
|
3337
|
-
const type = obje
|
|
3909
|
+
const type = resolveObjeForm(obje) ?? (url ? getFileExtension(url) : void 0) ?? "raw";
|
|
3338
3910
|
if (url) {
|
|
3339
3911
|
const urlMatch = url.match(/\/([^/]+)\?hash=/);
|
|
3340
|
-
const imgId = urlMatch?.[1] || `img-${index}-${Date.now().toString(36)}
|
|
3912
|
+
const imgId = urlMatch?.[1] || (url.startsWith("data:") ? `data-${index}-${getFileExtension(url) || "bin"}` : `img-${index}-${Date.now().toString(36)}`);
|
|
3341
3913
|
const id = `geni-${geniId}-${imgId}`;
|
|
3342
3914
|
list[id] = {
|
|
3343
3915
|
isPrimary,
|
|
@@ -3374,10 +3946,10 @@ var Indi = class extends Common {
|
|
|
3374
3946
|
obje.standardizeMedia();
|
|
3375
3947
|
const isPrimary = obje?.get("_PRIM")?.toValue() === "Y";
|
|
3376
3948
|
const url = obje?.get("FILE")?.toValue();
|
|
3377
|
-
const title = obje?.get("TITL")?.toValue() ?? "";
|
|
3378
|
-
const type = obje
|
|
3949
|
+
const title = obje?.get("FILE.TITL")?.toValue() ?? obje?.get("TITL")?.toValue() ?? "";
|
|
3950
|
+
const type = resolveObjeForm(obje) ?? (url ? getFileExtension(url) : void 0) ?? "raw";
|
|
3379
3951
|
if (url) {
|
|
3380
|
-
const imgId = `media-${index}-${url.split("/").pop()?.split("?")[0]?.substring(0, 20) || Date.now().toString(36)}`;
|
|
3952
|
+
const imgId = `media-${index}-${url.startsWith("data:") ? getFileExtension(url) || "bin" : url.split("/").pop()?.split("?")[0]?.substring(0, 20) || Date.now().toString(36)}`;
|
|
3381
3953
|
const id = `${treeId}-${this.id}-${imgId}`;
|
|
3382
3954
|
list[id] = {
|
|
3383
3955
|
isPrimary,
|
|
@@ -3417,7 +3989,20 @@ var Indi = class extends Common {
|
|
|
3417
3989
|
cacheKey
|
|
3418
3990
|
);
|
|
3419
3991
|
if (cached !== void 0) {
|
|
3420
|
-
|
|
3992
|
+
if (cached?.file && !isRemoteOrEmbeddedMediaUrl(cached.file)) {
|
|
3993
|
+
const resolvedCached = await resolveLocalMediaUrl(cached.file);
|
|
3994
|
+
if (resolvedCached && isRemoteOrEmbeddedMediaUrl(resolvedCached)) {
|
|
3995
|
+
const refreshed = { ...cached, file: resolvedCached };
|
|
3996
|
+
profilePictureCache(
|
|
3997
|
+
this._gedcom,
|
|
3998
|
+
cacheKey,
|
|
3999
|
+
refreshed
|
|
4000
|
+
);
|
|
4001
|
+
return refreshed;
|
|
4002
|
+
}
|
|
4003
|
+
} else {
|
|
4004
|
+
return cached;
|
|
4005
|
+
}
|
|
3421
4006
|
}
|
|
3422
4007
|
const mediaList = await this.multimedia(namespace);
|
|
3423
4008
|
if (!mediaList) {
|
|
@@ -3429,39 +4014,40 @@ var Indi = class extends Common {
|
|
|
3429
4014
|
return void 0;
|
|
3430
4015
|
}
|
|
3431
4016
|
const mediaArray = Object.values(mediaList);
|
|
3432
|
-
const
|
|
3433
|
-
|
|
3434
|
-
|
|
3435
|
-
|
|
3436
|
-
|
|
3437
|
-
|
|
3438
|
-
|
|
3439
|
-
|
|
3440
|
-
|
|
4017
|
+
const toDisplayableProfile = async (media, isPrimary) => {
|
|
4018
|
+
const resolvedFile = await resolveLocalMediaUrl(media.url);
|
|
4019
|
+
if (!resolvedFile || !isRemoteOrEmbeddedMediaUrl(resolvedFile)) {
|
|
4020
|
+
return void 0;
|
|
4021
|
+
}
|
|
4022
|
+
return {
|
|
4023
|
+
file: resolvedFile,
|
|
4024
|
+
form: media.contentType,
|
|
4025
|
+
title: media.title,
|
|
4026
|
+
isPrimary
|
|
3441
4027
|
};
|
|
3442
|
-
|
|
3443
|
-
|
|
3444
|
-
|
|
3445
|
-
|
|
3446
|
-
|
|
3447
|
-
this._gedcom,
|
|
3448
|
-
cacheKey,
|
|
3449
|
-
void 0
|
|
3450
|
-
);
|
|
3451
|
-
return void 0;
|
|
3452
|
-
}
|
|
3453
|
-
const secondaryMedia = mediaArray.find(
|
|
3454
|
-
(media) => isImageFormat(media.contentType || getFileExtension(media.url))
|
|
4028
|
+
};
|
|
4029
|
+
const candidates = mediaArray.filter(
|
|
4030
|
+
(media) => isImageFormat(
|
|
4031
|
+
media.contentType || media.url || getFileExtension(media.url)
|
|
4032
|
+
)
|
|
3455
4033
|
);
|
|
3456
|
-
|
|
3457
|
-
|
|
3458
|
-
|
|
3459
|
-
|
|
3460
|
-
|
|
3461
|
-
|
|
3462
|
-
|
|
3463
|
-
|
|
3464
|
-
|
|
4034
|
+
const ordered = [
|
|
4035
|
+
...candidates.filter((media) => media.isPrimary),
|
|
4036
|
+
...candidates.filter((media) => !media.isPrimary)
|
|
4037
|
+
];
|
|
4038
|
+
for (const media of ordered) {
|
|
4039
|
+
if (onlyPrimary && !media.isPrimary) {
|
|
4040
|
+
break;
|
|
4041
|
+
}
|
|
4042
|
+
const result = await toDisplayableProfile(media, !!media.isPrimary);
|
|
4043
|
+
if (result) {
|
|
4044
|
+
profilePictureCache(
|
|
4045
|
+
this._gedcom,
|
|
4046
|
+
cacheKey,
|
|
4047
|
+
result
|
|
4048
|
+
);
|
|
4049
|
+
return result;
|
|
4050
|
+
}
|
|
3465
4051
|
}
|
|
3466
4052
|
profilePictureCache(
|
|
3467
4053
|
this._gedcom,
|
|
@@ -3699,31 +4285,181 @@ var Indi = class extends Common {
|
|
|
3699
4285
|
isUnknownSex() {
|
|
3700
4286
|
return !this.isMale() && !this.isFemale();
|
|
3701
4287
|
}
|
|
3702
|
-
|
|
3703
|
-
|
|
3704
|
-
|
|
3705
|
-
indi = this._gedcom?.indi(id);
|
|
3706
|
-
} else {
|
|
3707
|
-
indi = id;
|
|
4288
|
+
addSpouse(other) {
|
|
4289
|
+
if (!this.id || !other?.id || this.id === other.id || !this._gedcom) {
|
|
4290
|
+
return void 0;
|
|
3708
4291
|
}
|
|
3709
|
-
|
|
3710
|
-
|
|
4292
|
+
const existing = getFamilyWith(this, other.id);
|
|
4293
|
+
if (existing) {
|
|
4294
|
+
return existing;
|
|
3711
4295
|
}
|
|
3712
|
-
const
|
|
3713
|
-
|
|
3714
|
-
|
|
3715
|
-
if (!parent?.id) {
|
|
3716
|
-
const children = this.getChildren();
|
|
3717
|
-
if (children.item(indi.id)) {
|
|
3718
|
-
parent = this._gedcom?.indi(this.id);
|
|
3719
|
-
child = indi;
|
|
3720
|
-
}
|
|
4296
|
+
const fam = this._gedcom.createFamily();
|
|
4297
|
+
if (!fam.addSpouse(this) || !fam.addSpouse(other)) {
|
|
4298
|
+
return void 0;
|
|
3721
4299
|
}
|
|
3722
|
-
|
|
3723
|
-
|
|
3724
|
-
|
|
4300
|
+
return fam;
|
|
4301
|
+
}
|
|
4302
|
+
addChild(child, pedigree) {
|
|
4303
|
+
if (!this.id || !child?.id || this.id === child.id || !this._gedcom) {
|
|
4304
|
+
return void 0;
|
|
3725
4305
|
}
|
|
3726
|
-
const
|
|
4306
|
+
const existing = findReusableParentChildFamily(
|
|
4307
|
+
this,
|
|
4308
|
+
child
|
|
4309
|
+
);
|
|
4310
|
+
if (existing === "already") {
|
|
4311
|
+
const fam2 = child.getFamilies("FAMC")?.find(
|
|
4312
|
+
(item) => !!item && item.hasParent(this.id) && item.hasChild(child.id)
|
|
4313
|
+
);
|
|
4314
|
+
if (fam2) {
|
|
4315
|
+
setChildPedigree(
|
|
4316
|
+
fam2,
|
|
4317
|
+
child,
|
|
4318
|
+
pedigree,
|
|
4319
|
+
this
|
|
4320
|
+
);
|
|
4321
|
+
}
|
|
4322
|
+
return fam2;
|
|
4323
|
+
}
|
|
4324
|
+
const fam = existing ?? this._gedcom.createFamily();
|
|
4325
|
+
if (!fam.addSpouse(this)) {
|
|
4326
|
+
return void 0;
|
|
4327
|
+
}
|
|
4328
|
+
if (!fam.addChild(child, pedigree, this)) {
|
|
4329
|
+
return void 0;
|
|
4330
|
+
}
|
|
4331
|
+
return fam;
|
|
4332
|
+
}
|
|
4333
|
+
addParent(parent, pedigree) {
|
|
4334
|
+
return parent.addChild(this, pedigree);
|
|
4335
|
+
}
|
|
4336
|
+
/**
|
|
4337
|
+
* Link an existing top-level OBJE record to this individual (`1 OBJE @On@`).
|
|
4338
|
+
*/
|
|
4339
|
+
attachMultimedia(objeOrKey, options) {
|
|
4340
|
+
if (!this._gedcom || !this.id) {
|
|
4341
|
+
return void 0;
|
|
4342
|
+
}
|
|
4343
|
+
const obje = typeof objeOrKey === "string" ? this._gedcom.obje(objeOrKey) : objeOrKey;
|
|
4344
|
+
if (!obje?.id) {
|
|
4345
|
+
return void 0;
|
|
4346
|
+
}
|
|
4347
|
+
const already = this.get("OBJE")?.toList()?.values()?.some((item) => item?.toValue?.() === obje.id);
|
|
4348
|
+
if (!already) {
|
|
4349
|
+
const pointer = makePointer(
|
|
4350
|
+
this._gedcom,
|
|
4351
|
+
this,
|
|
4352
|
+
obje.id,
|
|
4353
|
+
"OBJE"
|
|
4354
|
+
);
|
|
4355
|
+
this.assign("OBJE", pointer);
|
|
4356
|
+
}
|
|
4357
|
+
if (options?.primary) {
|
|
4358
|
+
this.get("OBJE")?.toList()?.forEach((item) => {
|
|
4359
|
+
const target = item?.refType === "OBJE" ? this._gedcom?.obje(
|
|
4360
|
+
String(item.toValue())
|
|
4361
|
+
) : item;
|
|
4362
|
+
if (!target) {
|
|
4363
|
+
return;
|
|
4364
|
+
}
|
|
4365
|
+
if (target.id === obje.id) {
|
|
4366
|
+
target.set("_PRIM", "Y");
|
|
4367
|
+
} else if (target.get("_PRIM")?.toValue() === "Y") {
|
|
4368
|
+
target.set("_PRIM", "N");
|
|
4369
|
+
}
|
|
4370
|
+
});
|
|
4371
|
+
obje.set("_PRIM", "Y");
|
|
4372
|
+
}
|
|
4373
|
+
return obje;
|
|
4374
|
+
}
|
|
4375
|
+
detachMultimedia(objeKey) {
|
|
4376
|
+
const list = this.get("OBJE")?.toList();
|
|
4377
|
+
if (!list) {
|
|
4378
|
+
return;
|
|
4379
|
+
}
|
|
4380
|
+
const toRemove = list.values().filter(
|
|
4381
|
+
(item) => item?.toValue?.() === objeKey || item?.id === objeKey
|
|
4382
|
+
);
|
|
4383
|
+
toRemove.forEach((item) => {
|
|
4384
|
+
if (item) {
|
|
4385
|
+
list.delete(item);
|
|
4386
|
+
}
|
|
4387
|
+
});
|
|
4388
|
+
if (list.length === 0) {
|
|
4389
|
+
this.remove("OBJE");
|
|
4390
|
+
}
|
|
4391
|
+
}
|
|
4392
|
+
/**
|
|
4393
|
+
* Create a multimedia record and attach it to this person.
|
|
4394
|
+
*/
|
|
4395
|
+
attachMediaFromUrl(url, options) {
|
|
4396
|
+
if (!this._gedcom || !url) {
|
|
4397
|
+
return void 0;
|
|
4398
|
+
}
|
|
4399
|
+
const obje = this._gedcom.createMultimediaRecord({
|
|
4400
|
+
file: url,
|
|
4401
|
+
form: options?.form,
|
|
4402
|
+
title: options?.title,
|
|
4403
|
+
mediType: options?.mediType,
|
|
4404
|
+
primary: options?.primary,
|
|
4405
|
+
gedcomVersion: options?.gedcomVersion
|
|
4406
|
+
});
|
|
4407
|
+
return this.attachMultimedia(obje, { primary: options?.primary });
|
|
4408
|
+
}
|
|
4409
|
+
/**
|
|
4410
|
+
* Link a shared SNOTE record via `1 NOTE @Nn@` (GEDCOM 7).
|
|
4411
|
+
*/
|
|
4412
|
+
attachSharedNote(noteOrKey) {
|
|
4413
|
+
if (!this._gedcom || !this.id) {
|
|
4414
|
+
return void 0;
|
|
4415
|
+
}
|
|
4416
|
+
const note = typeof noteOrKey === "string" ? this._gedcom.snote(noteOrKey) : noteOrKey;
|
|
4417
|
+
if (!note?.id) {
|
|
4418
|
+
return void 0;
|
|
4419
|
+
}
|
|
4420
|
+
const already = this.get("NOTE")?.toList()?.values()?.some((item) => item?.toValue?.() === note.id);
|
|
4421
|
+
if (!already) {
|
|
4422
|
+
const pointer = makePointer(
|
|
4423
|
+
this._gedcom,
|
|
4424
|
+
this,
|
|
4425
|
+
note.id,
|
|
4426
|
+
"SNOTE"
|
|
4427
|
+
);
|
|
4428
|
+
this.assign("NOTE", pointer);
|
|
4429
|
+
}
|
|
4430
|
+
return note;
|
|
4431
|
+
}
|
|
4432
|
+
addFact(input) {
|
|
4433
|
+
return addIndividualFact(this, input);
|
|
4434
|
+
}
|
|
4435
|
+
addNonEvent(input) {
|
|
4436
|
+
return addNonEvent(this, input);
|
|
4437
|
+
}
|
|
4438
|
+
getParentType(id) {
|
|
4439
|
+
let indi;
|
|
4440
|
+
if (typeof id === "string" || typeof id === "number") {
|
|
4441
|
+
indi = this._gedcom?.indi(id);
|
|
4442
|
+
} else {
|
|
4443
|
+
indi = id;
|
|
4444
|
+
}
|
|
4445
|
+
if (!indi?.id || !this.id) {
|
|
4446
|
+
return;
|
|
4447
|
+
}
|
|
4448
|
+
const parents = this.getParents();
|
|
4449
|
+
let parent = parents.item(indi.id) ? indi : void 0;
|
|
4450
|
+
let child = this._gedcom?.indi(this.id);
|
|
4451
|
+
if (!parent?.id) {
|
|
4452
|
+
const children = this.getChildren();
|
|
4453
|
+
if (children.item(indi.id)) {
|
|
4454
|
+
parent = this._gedcom?.indi(this.id);
|
|
4455
|
+
child = indi;
|
|
4456
|
+
}
|
|
4457
|
+
}
|
|
4458
|
+
const familiesOfChildren = child?.get("FAMC")?.toValueList();
|
|
4459
|
+
if (!parent?.id || !child?.id || !familiesOfChildren) {
|
|
4460
|
+
return;
|
|
4461
|
+
}
|
|
4462
|
+
const families = this.toFamilies(familiesOfChildren);
|
|
3727
4463
|
let childType = "";
|
|
3728
4464
|
families.forEach((family) => {
|
|
3729
4465
|
if (childType) {
|
|
@@ -3739,7 +4475,7 @@ var Indi = class extends Common {
|
|
|
3739
4475
|
if (!famChild) {
|
|
3740
4476
|
const childIndi = this._gedcom?.indi(child.id);
|
|
3741
4477
|
const childState = childIndi?.get("FAMC")?.toList()?.filter((item) => item.value === family.id).index(0);
|
|
3742
|
-
childType = childState?.get("PEDI")?.toValue() || "biological" /* BIOLOGICAL */;
|
|
4478
|
+
childType = (childState?.get("PEDI") ?? childState?.get("PEDT"))?.toValue() || "biological" /* BIOLOGICAL */;
|
|
3743
4479
|
} else {
|
|
3744
4480
|
childType = famChild.get(usedRel)?.toValue() || "biological" /* BIOLOGICAL */;
|
|
3745
4481
|
}
|
|
@@ -3899,7 +4635,9 @@ var Indi = class extends Common {
|
|
|
3899
4635
|
}
|
|
3900
4636
|
}
|
|
3901
4637
|
if (kinship !== "child" || !breakAfterSpouse) {
|
|
3902
|
-
indi.getBiologicalFathers().copy().merge(indi.getBiologicalMothers()).merge(
|
|
4638
|
+
indi.getBiologicalFathers().copy().merge(indi.getBiologicalMothers()).merge(
|
|
4639
|
+
indi.getFathers().copy().merge(indi.getMothers())
|
|
4640
|
+
).forEach((relative) => {
|
|
3903
4641
|
if (!visited.has(relative)) {
|
|
3904
4642
|
const currentRelation = indi.getParentType(relative);
|
|
3905
4643
|
const isNonBiological = !!currentRelation && currentRelation !== "biological" /* BIOLOGICAL */;
|
|
@@ -4298,7 +5036,7 @@ var Indi = class extends Common {
|
|
|
4298
5036
|
return;
|
|
4299
5037
|
}
|
|
4300
5038
|
const childState = child?.get("FAMC")?.toList()?.filter((item) => item.value === family.id).index(0);
|
|
4301
|
-
const childType = childState?.get("PEDI")?.toValue() || "biological" /* BIOLOGICAL */;
|
|
5039
|
+
const childType = (childState?.get("PEDI") ?? childState?.get("PEDT"))?.toValue() || "biological" /* BIOLOGICAL */;
|
|
4302
5040
|
if (childType?.toLowerCase() === filter.PEDI.toLowerCase()) {
|
|
4303
5041
|
children.append(child);
|
|
4304
5042
|
}
|
|
@@ -4406,7 +5144,7 @@ var Indi = class extends Common {
|
|
|
4406
5144
|
const child = this.id && family.CHIL?.toValueList()?.item(this.id);
|
|
4407
5145
|
if (!child) {
|
|
4408
5146
|
const childState = this?.get("FAMC")?.toList()?.filter((item) => item.value === family.id).index(0);
|
|
4409
|
-
const parentType = childState?.get("PEDI")?.toValue() || "biological" /* BIOLOGICAL */;
|
|
5147
|
+
const parentType = (childState?.get("PEDI") ?? childState?.get("PEDT"))?.toValue() || "biological" /* BIOLOGICAL */;
|
|
4410
5148
|
if (parentType?.toLowerCase() === filter.PEDI.toLowerCase()) {
|
|
4411
5149
|
parents.merge(family.getParents());
|
|
4412
5150
|
}
|
|
@@ -6807,7 +7545,11 @@ var STANDARD_QUALIFIERS = {
|
|
|
6807
7545
|
BEF: "Bef.",
|
|
6808
7546
|
BEFORE: "Bef.",
|
|
6809
7547
|
AFT: "Aft.",
|
|
6810
|
-
AFTER: "Aft."
|
|
7548
|
+
AFTER: "Aft.",
|
|
7549
|
+
CAL: "Abt.",
|
|
7550
|
+
// calculated ≈ about for display
|
|
7551
|
+
EST: "Abt."
|
|
7552
|
+
// estimated ≈ about for display
|
|
6811
7553
|
};
|
|
6812
7554
|
var EXPORT_QUALIFIERS = {
|
|
6813
7555
|
"Abt.": "ABT",
|
|
@@ -6815,6 +7557,11 @@ var EXPORT_QUALIFIERS = {
|
|
|
6815
7557
|
"Aft.": "AFT"
|
|
6816
7558
|
};
|
|
6817
7559
|
var GEDCOM_MONTHS = /\b(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)\b/g;
|
|
7560
|
+
var CALENDAR_PREFIX = /^(?<calendar>GREGORIAN|JULIAN|FRENCH_R|HEBREW)\b\s+/i;
|
|
7561
|
+
var isGedcomDateValueForm = (value) => (
|
|
7562
|
+
// Require space/end after the token so display forms like "Abt." are not opaque.
|
|
7563
|
+
/^(FROM|TO|BET|AFT|BEF|ABT|CAL|EST|INT)(\s|$)/i.test(value) || /\bAND\b/i.test(value)
|
|
7564
|
+
);
|
|
6818
7565
|
var NOTE_MARKER = "####";
|
|
6819
7566
|
var formatDateWithComponents = (date, hasDay, hasMonth, hasYear, noteValue, baseFormat = "dd MMM yyyy", locale) => {
|
|
6820
7567
|
const hasNote = baseFormat.includes("NOTE");
|
|
@@ -6839,29 +7586,45 @@ var CommonDate = class extends Common {
|
|
|
6839
7586
|
super(gedcom, id, main, parent);
|
|
6840
7587
|
delete this.id;
|
|
6841
7588
|
}
|
|
7589
|
+
get calendar() {
|
|
7590
|
+
return this._calendar;
|
|
7591
|
+
}
|
|
6842
7592
|
set value(value) {
|
|
6843
7593
|
if (value) {
|
|
6844
|
-
const noteRegExp = /^(?<note>[a-zA-Z]+\.)/;
|
|
6845
|
-
const noteMatch = value.match(noteRegExp)?.groups;
|
|
6846
7594
|
let validValue = value;
|
|
7595
|
+
const calendarMatch = validValue.match(CALENDAR_PREFIX);
|
|
7596
|
+
if (calendarMatch?.groups?.calendar) {
|
|
7597
|
+
this._calendar = calendarMatch.groups.calendar.toUpperCase();
|
|
7598
|
+
validValue = validValue.slice(calendarMatch[0].length);
|
|
7599
|
+
} else {
|
|
7600
|
+
this._calendar = void 0;
|
|
7601
|
+
}
|
|
7602
|
+
const noteRegExp = /^(?<note>[a-zA-Z]+\.)/;
|
|
7603
|
+
const noteMatch = validValue.match(noteRegExp)?.groups;
|
|
6847
7604
|
if (noteMatch?.note) {
|
|
6848
7605
|
this.NOTE = this.NOTE || createCommon(this._gedcom, void 0, this.main);
|
|
6849
7606
|
this.NOTE.value = noteMatch?.note;
|
|
6850
|
-
validValue =
|
|
7607
|
+
validValue = validValue.replace(noteRegExp, "");
|
|
6851
7608
|
} else {
|
|
6852
|
-
const qualifierMatch =
|
|
6853
|
-
/^(?<qualifier>ABT|ABOUT|BEF|BEFORE|AFT|AFTER)\b\s*/i
|
|
7609
|
+
const qualifierMatch = validValue.match(
|
|
7610
|
+
/^(?<qualifier>ABT|ABOUT|BEF|BEFORE|AFT|AFTER|CAL|EST)\b\s*/i
|
|
6854
7611
|
);
|
|
6855
7612
|
const qualifier = qualifierMatch?.groups?.qualifier?.toUpperCase();
|
|
6856
7613
|
const note = qualifier ? STANDARD_QUALIFIERS[qualifier] : void 0;
|
|
6857
7614
|
if (note) {
|
|
6858
7615
|
this.NOTE = this.NOTE || createCommon(this._gedcom, void 0, this.main);
|
|
6859
7616
|
this.NOTE.value = note;
|
|
6860
|
-
validValue =
|
|
7617
|
+
validValue = validValue.slice(qualifierMatch[0].length);
|
|
6861
7618
|
}
|
|
6862
7619
|
}
|
|
6863
7620
|
const acceptedDate = this.isValidDateFormat(validValue);
|
|
6864
|
-
if (
|
|
7621
|
+
if (isGedcomDateValueForm(validValue.trim())) {
|
|
7622
|
+
delete this.DAY;
|
|
7623
|
+
delete this.MONTH;
|
|
7624
|
+
delete this.YEAR;
|
|
7625
|
+
this._date = void 0;
|
|
7626
|
+
this._value = value;
|
|
7627
|
+
} else if (acceptedDate) {
|
|
6865
7628
|
this.DAY = this.DAY || createCommon(this._gedcom, void 0, this.main);
|
|
6866
7629
|
this.DAY.value = format(acceptedDate, "dd");
|
|
6867
7630
|
this.MONTH = this.MONTH || createCommon(this._gedcom, void 0, this.main);
|
|
@@ -6964,6 +7727,15 @@ var CommonDate = class extends Common {
|
|
|
6964
7727
|
);
|
|
6965
7728
|
}
|
|
6966
7729
|
exportValue() {
|
|
7730
|
+
if (typeof this._value === "string") {
|
|
7731
|
+
const withoutCalendar = this._value.replace(CALENDAR_PREFIX, "");
|
|
7732
|
+
if (isGedcomDateValueForm(withoutCalendar.trim())) {
|
|
7733
|
+
return this._value.replace(
|
|
7734
|
+
/^((?:GREGORIAN|JULIAN|FRENCH_R|HEBREW)\s+)?(FROM|TO|BET|AFT|BEF|ABT|CAL|EST|INT)\b/i,
|
|
7735
|
+
(_m, cal, q) => `${cal || ""}${q.toUpperCase()}`
|
|
7736
|
+
);
|
|
7737
|
+
}
|
|
7738
|
+
}
|
|
6967
7739
|
const formatted = this.toValue("NOTE dd MMM yyyy", null);
|
|
6968
7740
|
if (!formatted) {
|
|
6969
7741
|
return formatted;
|
|
@@ -6971,10 +7743,14 @@ var CommonDate = class extends Common {
|
|
|
6971
7743
|
const note = this.NOTE?.value?.trim();
|
|
6972
7744
|
const qualifier = note ? EXPORT_QUALIFIERS[note] : void 0;
|
|
6973
7745
|
const standardized = qualifier ? formatted.replace(note, qualifier) : formatted;
|
|
6974
|
-
|
|
7746
|
+
const withMonths = standardized.replace(
|
|
6975
7747
|
GEDCOM_MONTHS,
|
|
6976
7748
|
(month) => month.toUpperCase()
|
|
6977
7749
|
);
|
|
7750
|
+
if (this._calendar && this._calendar !== "GREGORIAN") {
|
|
7751
|
+
return `${this._calendar} ${withMonths}`;
|
|
7752
|
+
}
|
|
7753
|
+
return withMonths;
|
|
6978
7754
|
}
|
|
6979
7755
|
toGedcomLines(tag, level = 0, options) {
|
|
6980
7756
|
const internal = new RegExp(
|
|
@@ -6995,130 +7771,1025 @@ var isCommonDate = (value) => {
|
|
|
6995
7771
|
return !!value && value !== null && typeof value === "object" && "_date" in value;
|
|
6996
7772
|
};
|
|
6997
7773
|
|
|
6998
|
-
//
|
|
6999
|
-
var
|
|
7000
|
-
|
|
7001
|
-
|
|
7002
|
-
|
|
7003
|
-
|
|
7004
|
-
|
|
7005
|
-
|
|
7006
|
-
|
|
7007
|
-
|
|
7008
|
-
var
|
|
7009
|
-
|
|
7010
|
-
|
|
7011
|
-
var
|
|
7012
|
-
|
|
7013
|
-
|
|
7014
|
-
|
|
7015
|
-
|
|
7016
|
-
|
|
7017
|
-
|
|
7018
|
-
|
|
7019
|
-
|
|
7020
|
-
|
|
7021
|
-
|
|
7022
|
-
|
|
7023
|
-
|
|
7024
|
-
|
|
7025
|
-
|
|
7026
|
-
|
|
7027
|
-
|
|
7774
|
+
// src/utils/gedcom-version.ts
|
|
7775
|
+
var GEDCOM_EXPORT_VERSIONS = ["5.5.1", "7.0"];
|
|
7776
|
+
var DEFAULT_GEDCOM_EXPORT_VERSION = "5.5.1";
|
|
7777
|
+
var normalizeGedcomVersion = (value) => {
|
|
7778
|
+
const trimmed = value?.trim() ?? "";
|
|
7779
|
+
if (trimmed.startsWith("7")) {
|
|
7780
|
+
return "7.0";
|
|
7781
|
+
}
|
|
7782
|
+
return "5.5.1";
|
|
7783
|
+
};
|
|
7784
|
+
var isGedcom7 = (value) => normalizeGedcomVersion(value) === "7.0";
|
|
7785
|
+
var GEDZIP_MIME = "application/vnd.familysearch.gedcom+zip";
|
|
7786
|
+
var GEDZIP_EXTENSION = "gdz";
|
|
7787
|
+
var GEDZIP_GEDCOM_ENTRY = "gedcom.ged";
|
|
7788
|
+
var sanitizePathSegment = (name) => name.replace(/[^a-zA-Z0-9._-]+/g, "-").replace(/^\.+/, "") || "file";
|
|
7789
|
+
var extensionFor = (contentType) => {
|
|
7790
|
+
const raw = (contentType || "bin").replace(/^\./, "").toLowerCase();
|
|
7791
|
+
if (raw.includes("/")) {
|
|
7792
|
+
return raw.split("/").pop() || "bin";
|
|
7793
|
+
}
|
|
7794
|
+
return raw || "bin";
|
|
7795
|
+
};
|
|
7796
|
+
var rewriteGedcomFilePaths = (gedcomText, urlToPath) => {
|
|
7797
|
+
const entries = urlToPath instanceof Map ? urlToPath : new Map(Object.entries(urlToPath));
|
|
7798
|
+
let text = gedcomText;
|
|
7799
|
+
entries.forEach((path, url) => {
|
|
7800
|
+
const escaped = url.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
7801
|
+
text = text.replace(
|
|
7802
|
+
new RegExp(`(^|\\r?\\n)(\\d+ FILE )${escaped}`, "g"),
|
|
7803
|
+
`$1$2${path}`
|
|
7804
|
+
);
|
|
7805
|
+
});
|
|
7806
|
+
return text;
|
|
7807
|
+
};
|
|
7808
|
+
var assignMediaPaths = (mediaFiles) => {
|
|
7809
|
+
const urlToPath = /* @__PURE__ */ new Map();
|
|
7810
|
+
const usedPaths = /* @__PURE__ */ new Set([GEDZIP_GEDCOM_ENTRY]);
|
|
7811
|
+
const files = [];
|
|
7812
|
+
for (const file of mediaFiles) {
|
|
7813
|
+
if (!file.content || !file.url) {
|
|
7814
|
+
continue;
|
|
7028
7815
|
}
|
|
7029
|
-
|
|
7030
|
-
|
|
7816
|
+
const ext = extensionFor(file.contentType);
|
|
7817
|
+
const base = sanitizePathSegment(
|
|
7818
|
+
file.imgId || file.title || file.id || "media"
|
|
7819
|
+
);
|
|
7820
|
+
let path = `media/${base}.${ext}`;
|
|
7821
|
+
let suffix = 1;
|
|
7822
|
+
while (usedPaths.has(path)) {
|
|
7823
|
+
path = `media/${base}-${suffix++}.${ext}`;
|
|
7824
|
+
}
|
|
7825
|
+
usedPaths.add(path);
|
|
7826
|
+
urlToPath.set(file.url, path);
|
|
7827
|
+
const marker = "base64,";
|
|
7828
|
+
const idx = file.content.indexOf(marker);
|
|
7829
|
+
if (idx >= 0) {
|
|
7830
|
+
files.push({
|
|
7831
|
+
path,
|
|
7832
|
+
url: file.url,
|
|
7833
|
+
content: file.content.substring(idx + marker.length),
|
|
7834
|
+
base64: true
|
|
7835
|
+
});
|
|
7836
|
+
} else {
|
|
7837
|
+
files.push({
|
|
7838
|
+
path,
|
|
7839
|
+
url: file.url,
|
|
7840
|
+
content: file.content,
|
|
7841
|
+
base64: false
|
|
7842
|
+
});
|
|
7031
7843
|
}
|
|
7032
|
-
const keys = list.keys();
|
|
7033
|
-
return list.item(keys[index]);
|
|
7034
|
-
}
|
|
7035
|
-
getList(type) {
|
|
7036
|
-
return this.get(type);
|
|
7037
7844
|
}
|
|
7038
|
-
|
|
7039
|
-
|
|
7040
|
-
|
|
7041
|
-
|
|
7042
|
-
|
|
7043
|
-
|
|
7044
|
-
|
|
7045
|
-
|
|
7046
|
-
|
|
7047
|
-
|
|
7048
|
-
|
|
7049
|
-
|
|
7050
|
-
|
|
7845
|
+
return { urlToPath, files };
|
|
7846
|
+
};
|
|
7847
|
+
var buildGedzip = async (gedcomText, mediaFiles = []) => {
|
|
7848
|
+
const zip = new JSZip();
|
|
7849
|
+
const { urlToPath, files } = assignMediaPaths(mediaFiles);
|
|
7850
|
+
for (const file of files) {
|
|
7851
|
+
zip.file(file.path, file.content, { base64: file.base64 });
|
|
7852
|
+
}
|
|
7853
|
+
zip.file(GEDZIP_GEDCOM_ENTRY, rewriteGedcomFilePaths(gedcomText, urlToPath));
|
|
7854
|
+
return zip.generateAsync({ type: "uint8array" });
|
|
7855
|
+
};
|
|
7856
|
+
var normalizeZipPath = (name) => name.replace(/\\/g, "/").replace(/^\.\//, "");
|
|
7857
|
+
var MIME_BY_EXT = {
|
|
7858
|
+
jpg: "image/jpeg",
|
|
7859
|
+
jpeg: "image/jpeg",
|
|
7860
|
+
png: "image/png",
|
|
7861
|
+
gif: "image/gif",
|
|
7862
|
+
webp: "image/webp",
|
|
7863
|
+
bmp: "image/bmp",
|
|
7864
|
+
tif: "image/tiff",
|
|
7865
|
+
tiff: "image/tiff",
|
|
7866
|
+
svg: "image/svg+xml",
|
|
7867
|
+
pdf: "application/pdf"
|
|
7868
|
+
};
|
|
7869
|
+
var mimeForPath = (path) => {
|
|
7870
|
+
const ext = (path.split(".").pop() || "").toLowerCase();
|
|
7871
|
+
return MIME_BY_EXT[ext] || "application/octet-stream";
|
|
7872
|
+
};
|
|
7873
|
+
var bytesToBase64 = (bytes) => {
|
|
7874
|
+
if (typeof Buffer !== "undefined") {
|
|
7875
|
+
return Buffer.from(bytes).toString("base64");
|
|
7876
|
+
}
|
|
7877
|
+
let binary = "";
|
|
7878
|
+
const chunk = 32768;
|
|
7879
|
+
for (let i = 0; i < bytes.length; i += chunk) {
|
|
7880
|
+
binary += String.fromCharCode(...bytes.subarray(i, i + chunk));
|
|
7881
|
+
}
|
|
7882
|
+
return btoa(binary);
|
|
7883
|
+
};
|
|
7884
|
+
var bytesToDataUrl = (bytes, mime) => `data:${mime};base64,${bytesToBase64(bytes)}`;
|
|
7885
|
+
var remountGedzipMediaAsDataUrls = (extracted) => {
|
|
7886
|
+
if (!extracted.mediaEntries.length) {
|
|
7887
|
+
return extracted.gedcomText;
|
|
7888
|
+
}
|
|
7889
|
+
const pathToDataUrl = /* @__PURE__ */ new Map();
|
|
7890
|
+
for (const media of extracted.mediaEntries) {
|
|
7891
|
+
const path = normalizeZipPath(media.path);
|
|
7892
|
+
const dataUrl = bytesToDataUrl(media.content, mimeForPath(path));
|
|
7893
|
+
pathToDataUrl.set(path, dataUrl);
|
|
7894
|
+
pathToDataUrl.set(`./${path}`, dataUrl);
|
|
7895
|
+
const base = path.split("/").pop();
|
|
7896
|
+
if (base) {
|
|
7897
|
+
pathToDataUrl.set(base, dataUrl);
|
|
7898
|
+
pathToDataUrl.set(`media/${base}`, dataUrl);
|
|
7899
|
+
}
|
|
7900
|
+
}
|
|
7901
|
+
return rewriteGedcomFilePaths(extracted.gedcomText, pathToDataUrl);
|
|
7902
|
+
};
|
|
7903
|
+
var extractGedzip = async (data) => {
|
|
7904
|
+
const zip = await JSZip.loadAsync(data);
|
|
7905
|
+
const entries = Object.values(zip.files).filter((entry) => !entry.dir);
|
|
7906
|
+
const preferred = entries.find(
|
|
7907
|
+
(entry) => normalizeZipPath(entry.name).toLowerCase() === GEDZIP_GEDCOM_ENTRY
|
|
7908
|
+
) ?? entries.find(
|
|
7909
|
+
(entry) => normalizeZipPath(entry.name).toLowerCase().endsWith(".ged")
|
|
7910
|
+
);
|
|
7911
|
+
if (!preferred) {
|
|
7912
|
+
throw new Error("No .ged file found in the archive.");
|
|
7913
|
+
}
|
|
7914
|
+
const gedcomText = await preferred.async("string");
|
|
7915
|
+
const mediaEntries = [];
|
|
7916
|
+
for (const entry of entries) {
|
|
7917
|
+
const path = normalizeZipPath(entry.name);
|
|
7918
|
+
if (path === normalizeZipPath(preferred.name)) {
|
|
7919
|
+
continue;
|
|
7051
7920
|
}
|
|
7052
|
-
if (
|
|
7053
|
-
|
|
7054
|
-
return node;
|
|
7921
|
+
if (path.toLowerCase().endsWith(".ged")) {
|
|
7922
|
+
continue;
|
|
7055
7923
|
}
|
|
7056
|
-
|
|
7057
|
-
|
|
7924
|
+
mediaEntries.push({
|
|
7925
|
+
path,
|
|
7926
|
+
content: await entry.async("uint8array")
|
|
7927
|
+
});
|
|
7058
7928
|
}
|
|
7059
|
-
|
|
7060
|
-
|
|
7061
|
-
|
|
7062
|
-
|
|
7929
|
+
return {
|
|
7930
|
+
gedcomText,
|
|
7931
|
+
entryName: normalizeZipPath(preferred.name),
|
|
7932
|
+
mediaEntries
|
|
7933
|
+
};
|
|
7934
|
+
};
|
|
7935
|
+
var extractGedzipGedcom = async (data, options) => {
|
|
7936
|
+
const extracted = await extractGedzip(data);
|
|
7937
|
+
if (options?.embedMediaAsDataUrls === false) {
|
|
7938
|
+
return extracted.gedcomText;
|
|
7939
|
+
}
|
|
7940
|
+
return remountGedzipMediaAsDataUrls(extracted);
|
|
7941
|
+
};
|
|
7942
|
+
var isGedzipContainer = (file) => {
|
|
7943
|
+
const name = (file.name || "").toLowerCase();
|
|
7944
|
+
const type = (file.type || "").toLowerCase();
|
|
7945
|
+
return name.endsWith(`.${GEDZIP_EXTENSION}`) || name.endsWith(".zip") || type === GEDZIP_MIME || type === "application/zip" || type === "application/x-zip-compressed";
|
|
7946
|
+
};
|
|
7947
|
+
var downloadGedzipMedia = async (media, onProgress) => {
|
|
7948
|
+
const entries = Object.values(media).filter((item) => !!item.url);
|
|
7949
|
+
const total = entries.length;
|
|
7950
|
+
let done = 0;
|
|
7951
|
+
const downloaded = [];
|
|
7952
|
+
await Promise.all(
|
|
7953
|
+
entries.map(async (item) => {
|
|
7954
|
+
try {
|
|
7955
|
+
const resolved = await resolveMediaContent({
|
|
7956
|
+
url: item.url,
|
|
7957
|
+
id: item.id,
|
|
7958
|
+
imgId: item.imgId,
|
|
7959
|
+
key: "key" in item ? item.key : void 0,
|
|
7960
|
+
contentType: item.contentType
|
|
7961
|
+
});
|
|
7962
|
+
if (!resolved?.content) {
|
|
7063
7963
|
return;
|
|
7064
7964
|
}
|
|
7065
|
-
|
|
7066
|
-
|
|
7067
|
-
|
|
7068
|
-
|
|
7069
|
-
if (typeof value === "string") {
|
|
7070
|
-
target.id = value;
|
|
7071
|
-
}
|
|
7072
|
-
return;
|
|
7073
|
-
}
|
|
7074
|
-
const tag = rawTag;
|
|
7075
|
-
if (value === void 0) {
|
|
7076
|
-
return;
|
|
7077
|
-
}
|
|
7078
|
-
if (value === null) {
|
|
7079
|
-
target.remove(tag);
|
|
7080
|
-
return;
|
|
7081
|
-
}
|
|
7082
|
-
if (Array.isArray(value)) {
|
|
7083
|
-
target.remove(tag);
|
|
7084
|
-
value.forEach((item) => {
|
|
7085
|
-
const listNode = this.createNodeFromPatchValue(
|
|
7086
|
-
item,
|
|
7087
|
-
target.main ?? this
|
|
7088
|
-
);
|
|
7089
|
-
if (listNode) {
|
|
7090
|
-
target.assign(tag, listNode);
|
|
7091
|
-
}
|
|
7965
|
+
downloaded.push({
|
|
7966
|
+
...item,
|
|
7967
|
+
content: resolved.content,
|
|
7968
|
+
contentType: resolved.contentType || item.contentType
|
|
7092
7969
|
});
|
|
7093
|
-
|
|
7094
|
-
}
|
|
7095
|
-
|
|
7096
|
-
|
|
7097
|
-
const objectNode = existing ?? createCommon(this, void 0, target.main ?? this);
|
|
7098
|
-
this.applyObjectToCommon(objectNode, value);
|
|
7099
|
-
target.set(tag, objectNode);
|
|
7100
|
-
return;
|
|
7970
|
+
} catch {
|
|
7971
|
+
} finally {
|
|
7972
|
+
done += 1;
|
|
7973
|
+
onProgress?.(done, total);
|
|
7101
7974
|
}
|
|
7102
|
-
|
|
7975
|
+
})
|
|
7976
|
+
);
|
|
7977
|
+
return downloaded;
|
|
7978
|
+
};
|
|
7979
|
+
var buildGedzipBlob = async (gedcomText, mediaFiles = []) => {
|
|
7980
|
+
const bytes = await buildGedzip(gedcomText, mediaFiles);
|
|
7981
|
+
return new Blob([bytes], { type: GEDZIP_MIME });
|
|
7982
|
+
};
|
|
7983
|
+
|
|
7984
|
+
// src/utils/gedcom7-enumerations.ts
|
|
7985
|
+
var GEDCOM7_SEX_VALUES = ["M", "F", "U", "X", "N"];
|
|
7986
|
+
var GEDCOM7_PEDI_VALUES = [
|
|
7987
|
+
"adopted",
|
|
7988
|
+
"birth",
|
|
7989
|
+
"foster",
|
|
7990
|
+
"sealing"
|
|
7991
|
+
];
|
|
7992
|
+
var GEDCOM7_ROLE_VALUES = [
|
|
7993
|
+
"CHIL",
|
|
7994
|
+
"CLERGY",
|
|
7995
|
+
"FATH",
|
|
7996
|
+
"FRIEND",
|
|
7997
|
+
"GODP",
|
|
7998
|
+
"HUSB",
|
|
7999
|
+
"MOTH",
|
|
8000
|
+
"MULTIPLE",
|
|
8001
|
+
"NGHBR",
|
|
8002
|
+
"OFFICIATOR",
|
|
8003
|
+
"OTHER",
|
|
8004
|
+
"PARENT",
|
|
8005
|
+
"SPOU",
|
|
8006
|
+
"WIFE",
|
|
8007
|
+
"WITN"
|
|
8008
|
+
];
|
|
8009
|
+
var GEDCOM7_RESN_VALUES = [
|
|
8010
|
+
"CONFIDENTIAL",
|
|
8011
|
+
"LOCKED",
|
|
8012
|
+
"PRIVACY"
|
|
8013
|
+
];
|
|
8014
|
+
var isAllowed = (value, allowed) => allowed.includes(value);
|
|
8015
|
+
var moveToPhrase = (node, phrase) => {
|
|
8016
|
+
const previousValue = node.value;
|
|
8017
|
+
const previousPhrase = node.get("PHRASE");
|
|
8018
|
+
const previousPhraseValue = previousPhrase?.toValue();
|
|
8019
|
+
node.removeValue();
|
|
8020
|
+
if (previousPhrase) {
|
|
8021
|
+
previousPhrase.value = phrase;
|
|
8022
|
+
} else {
|
|
8023
|
+
const phraseNode = createCommon(node.getGedcom(), void 0, node.main);
|
|
8024
|
+
phraseNode.value = phrase;
|
|
8025
|
+
node.set("PHRASE", phraseNode);
|
|
8026
|
+
}
|
|
8027
|
+
return () => {
|
|
8028
|
+
if (previousValue === void 0) {
|
|
8029
|
+
node.removeValue();
|
|
8030
|
+
} else {
|
|
8031
|
+
node.value = previousValue;
|
|
8032
|
+
}
|
|
8033
|
+
if (previousPhrase) {
|
|
8034
|
+
previousPhrase.value = previousPhraseValue;
|
|
8035
|
+
} else {
|
|
8036
|
+
node.remove("PHRASE");
|
|
8037
|
+
}
|
|
8038
|
+
};
|
|
8039
|
+
};
|
|
8040
|
+
var normalizeEnum = (node, allowed, mode, restores) => {
|
|
8041
|
+
const value = node?.toValue();
|
|
8042
|
+
if (!node || typeof value !== "string" || !value.trim()) {
|
|
8043
|
+
return;
|
|
8044
|
+
}
|
|
8045
|
+
const normalized = mode === "upper" ? value.trim().toUpperCase() : value.trim().toLowerCase();
|
|
8046
|
+
if (isAllowed(normalized, allowed)) {
|
|
8047
|
+
if (value !== normalized) {
|
|
8048
|
+
const previous = node.value;
|
|
8049
|
+
node.value = normalized;
|
|
8050
|
+
restores.push(() => {
|
|
8051
|
+
node.value = previous;
|
|
8052
|
+
});
|
|
8053
|
+
}
|
|
8054
|
+
return;
|
|
8055
|
+
}
|
|
8056
|
+
restores.push(moveToPhrase(node, value.trim()));
|
|
8057
|
+
};
|
|
8058
|
+
var applyGedcom7Enumerations = (gedcom) => {
|
|
8059
|
+
const restores = [];
|
|
8060
|
+
gedcom.indis()?.forEach((indi) => {
|
|
8061
|
+
if (!indi) return;
|
|
8062
|
+
normalizeEnum(indi.get("SEX"), GEDCOM7_SEX_VALUES, "upper", restores);
|
|
8063
|
+
normalizeEnum(indi.get("RESN"), GEDCOM7_RESN_VALUES, "upper", restores);
|
|
8064
|
+
indi.get("FAMC")?.toList()?.forEach((famc) => {
|
|
8065
|
+
normalizeEnum(
|
|
8066
|
+
famc?.get("PEDI") ?? famc?.get("PEDT"),
|
|
8067
|
+
GEDCOM7_PEDI_VALUES,
|
|
8068
|
+
"lower",
|
|
8069
|
+
restores
|
|
8070
|
+
);
|
|
8071
|
+
});
|
|
8072
|
+
indi.get("ASSO")?.toList()?.forEach((asso) => {
|
|
8073
|
+
normalizeEnum(
|
|
8074
|
+
asso?.get("ROLE"),
|
|
8075
|
+
GEDCOM7_ROLE_VALUES,
|
|
8076
|
+
"upper",
|
|
8077
|
+
restores
|
|
8078
|
+
);
|
|
7103
8079
|
});
|
|
8080
|
+
});
|
|
8081
|
+
gedcom.fams()?.forEach((fam) => {
|
|
8082
|
+
if (!fam) return;
|
|
8083
|
+
normalizeEnum(fam.get("RESN"), GEDCOM7_RESN_VALUES, "upper", restores);
|
|
8084
|
+
fam.get("ASSO")?.toList()?.forEach((asso) => {
|
|
8085
|
+
normalizeEnum(
|
|
8086
|
+
asso?.get("ROLE"),
|
|
8087
|
+
GEDCOM7_ROLE_VALUES,
|
|
8088
|
+
"upper",
|
|
8089
|
+
restores
|
|
8090
|
+
);
|
|
8091
|
+
});
|
|
8092
|
+
});
|
|
8093
|
+
return () => {
|
|
8094
|
+
for (let i = restores.length - 1; i >= 0; i -= 1) {
|
|
8095
|
+
restores[i]?.();
|
|
8096
|
+
}
|
|
8097
|
+
};
|
|
8098
|
+
};
|
|
8099
|
+
|
|
8100
|
+
// src/utils/gedcom7-dates.ts
|
|
8101
|
+
var GEDCOM7_CALENDARS = [
|
|
8102
|
+
"GREGORIAN",
|
|
8103
|
+
"JULIAN",
|
|
8104
|
+
"FRENCH_R",
|
|
8105
|
+
"HEBREW"
|
|
8106
|
+
];
|
|
8107
|
+
var CALENDAR_PREFIX2 = /^(?<calendar>GREGORIAN|JULIAN|FRENCH_R|HEBREW)\b\s+/i;
|
|
8108
|
+
var parseGedcom7CalendarPrefix = (value) => {
|
|
8109
|
+
const match = value.match(CALENDAR_PREFIX2);
|
|
8110
|
+
if (!match?.groups?.calendar) {
|
|
8111
|
+
return { calendar: void 0, rest: value };
|
|
7104
8112
|
}
|
|
7105
|
-
|
|
7106
|
-
|
|
7107
|
-
|
|
8113
|
+
return {
|
|
8114
|
+
calendar: match.groups.calendar.toUpperCase(),
|
|
8115
|
+
rest: value.slice(match[0].length)
|
|
8116
|
+
};
|
|
8117
|
+
};
|
|
8118
|
+
var withGedcom7Calendar = (value, calendar) => {
|
|
8119
|
+
if (!calendar || calendar.toUpperCase() === "GREGORIAN") {
|
|
8120
|
+
return value;
|
|
7108
8121
|
}
|
|
7109
|
-
|
|
7110
|
-
|
|
8122
|
+
const upper = calendar.toUpperCase();
|
|
8123
|
+
if (GEDCOM7_CALENDARS.includes(upper)) {
|
|
8124
|
+
const { rest } = parseGedcom7CalendarPrefix(value);
|
|
8125
|
+
return `${upper} ${rest}`.trim();
|
|
7111
8126
|
}
|
|
7112
|
-
|
|
7113
|
-
|
|
7114
|
-
|
|
7115
|
-
|
|
7116
|
-
|
|
7117
|
-
|
|
8127
|
+
return value;
|
|
8128
|
+
};
|
|
8129
|
+
var applyGedcom7DatePhrases = (gedcom) => {
|
|
8130
|
+
const restores = [];
|
|
8131
|
+
const visitDate = (dateNode) => {
|
|
8132
|
+
if (!dateNode || typeof dateNode.toValue !== "function") {
|
|
8133
|
+
return;
|
|
7118
8134
|
}
|
|
7119
|
-
const
|
|
7120
|
-
const
|
|
7121
|
-
const
|
|
8135
|
+
const asDate = dateNode;
|
|
8136
|
+
const hasComponents = !!(asDate.DAY || asDate.MONTH || asDate.YEAR);
|
|
8137
|
+
const raw = dateNode.exportValue?.() ?? dateNode.toValue();
|
|
8138
|
+
if (typeof raw !== "string" || !raw.trim()) {
|
|
8139
|
+
return;
|
|
8140
|
+
}
|
|
8141
|
+
const { calendar, rest } = parseGedcom7CalendarPrefix(raw.trim());
|
|
8142
|
+
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);
|
|
8143
|
+
if (looksStructured) {
|
|
8144
|
+
if (calendar && calendar !== "GREGORIAN") {
|
|
8145
|
+
const previous = dateNode.value;
|
|
8146
|
+
const next = withGedcom7Calendar(rest, calendar);
|
|
8147
|
+
if (previous !== next) {
|
|
8148
|
+
dateNode.value = next;
|
|
8149
|
+
restores.push(() => {
|
|
8150
|
+
dateNode.value = previous;
|
|
8151
|
+
});
|
|
8152
|
+
}
|
|
8153
|
+
}
|
|
8154
|
+
return;
|
|
8155
|
+
}
|
|
8156
|
+
const previousValue = dateNode.value;
|
|
8157
|
+
const previousPhrase = dateNode.get("PHRASE");
|
|
8158
|
+
const previousPhraseValue = previousPhrase?.toValue();
|
|
8159
|
+
dateNode.removeValue();
|
|
8160
|
+
if (previousPhrase) {
|
|
8161
|
+
previousPhrase.value = raw.trim();
|
|
8162
|
+
} else {
|
|
8163
|
+
const phrase = createCommon(
|
|
8164
|
+
dateNode.getGedcom(),
|
|
8165
|
+
void 0,
|
|
8166
|
+
dateNode.main
|
|
8167
|
+
);
|
|
8168
|
+
phrase.value = raw.trim();
|
|
8169
|
+
dateNode.set("PHRASE", phrase);
|
|
8170
|
+
}
|
|
8171
|
+
restores.push(() => {
|
|
8172
|
+
if (previousValue === void 0) {
|
|
8173
|
+
dateNode.removeValue();
|
|
8174
|
+
} else {
|
|
8175
|
+
dateNode.value = previousValue;
|
|
8176
|
+
}
|
|
8177
|
+
if (previousPhrase) {
|
|
8178
|
+
previousPhrase.value = previousPhraseValue;
|
|
8179
|
+
} else {
|
|
8180
|
+
dateNode.remove("PHRASE");
|
|
8181
|
+
}
|
|
8182
|
+
});
|
|
8183
|
+
};
|
|
8184
|
+
const walk = (node) => {
|
|
8185
|
+
if (!node) return;
|
|
8186
|
+
node.get("DATE")?.toList()?.forEach((item) => visitDate(item));
|
|
8187
|
+
node.get("SDATE")?.toList()?.forEach((item) => visitDate(item));
|
|
8188
|
+
};
|
|
8189
|
+
gedcom.indis()?.forEach((indi) => {
|
|
8190
|
+
if (!indi) return;
|
|
8191
|
+
walk(indi);
|
|
8192
|
+
[
|
|
8193
|
+
"BIRT",
|
|
8194
|
+
"DEAT",
|
|
8195
|
+
"CHR",
|
|
8196
|
+
"BAPM",
|
|
8197
|
+
"BURI",
|
|
8198
|
+
"CREM",
|
|
8199
|
+
"ADOP",
|
|
8200
|
+
"EVEN",
|
|
8201
|
+
"RESI",
|
|
8202
|
+
"OCCU",
|
|
8203
|
+
"MARR"
|
|
8204
|
+
].forEach((tag) => {
|
|
8205
|
+
indi.get(tag)?.toList()?.forEach((event) => walk(event));
|
|
8206
|
+
});
|
|
8207
|
+
});
|
|
8208
|
+
gedcom.fams()?.forEach((fam) => {
|
|
8209
|
+
if (!fam) return;
|
|
8210
|
+
["MARR", "DIV", "ENGA", "ANUL", "EVEN"].forEach((tag) => {
|
|
8211
|
+
fam.get(tag)?.toList()?.forEach((event) => walk(event));
|
|
8212
|
+
});
|
|
8213
|
+
});
|
|
8214
|
+
return () => {
|
|
8215
|
+
for (let i = restores.length - 1; i >= 0; i -= 1) {
|
|
8216
|
+
restores[i]?.();
|
|
8217
|
+
}
|
|
8218
|
+
};
|
|
8219
|
+
};
|
|
8220
|
+
|
|
8221
|
+
// src/utils/uid.ts
|
|
8222
|
+
var createGedcomUid = () => {
|
|
8223
|
+
const cryptoObj = typeof globalThis !== "undefined" ? globalThis.crypto : void 0;
|
|
8224
|
+
if (cryptoObj && typeof cryptoObj.randomUUID === "function") {
|
|
8225
|
+
return cryptoObj.randomUUID();
|
|
8226
|
+
}
|
|
8227
|
+
return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (char) => {
|
|
8228
|
+
const rand = Math.random() * 16 | 0;
|
|
8229
|
+
const value = char === "x" ? rand : rand & 3 | 8;
|
|
8230
|
+
return value.toString(16);
|
|
8231
|
+
});
|
|
8232
|
+
};
|
|
8233
|
+
|
|
8234
|
+
// src/utils/gedcom7-metadata.ts
|
|
8235
|
+
var GEDCOM_MONTHS2 = [
|
|
8236
|
+
"JAN",
|
|
8237
|
+
"FEB",
|
|
8238
|
+
"MAR",
|
|
8239
|
+
"APR",
|
|
8240
|
+
"MAY",
|
|
8241
|
+
"JUN",
|
|
8242
|
+
"JUL",
|
|
8243
|
+
"AUG",
|
|
8244
|
+
"SEP",
|
|
8245
|
+
"OCT",
|
|
8246
|
+
"NOV",
|
|
8247
|
+
"DEC"
|
|
8248
|
+
];
|
|
8249
|
+
var formatGedcom7Timestamp = (date = /* @__PURE__ */ new Date()) => {
|
|
8250
|
+
const day = String(date.getUTCDate());
|
|
8251
|
+
const month = GEDCOM_MONTHS2[date.getUTCMonth()];
|
|
8252
|
+
const year = String(date.getUTCFullYear());
|
|
8253
|
+
const hh = String(date.getUTCHours()).padStart(2, "0");
|
|
8254
|
+
const mm = String(date.getUTCMinutes()).padStart(2, "0");
|
|
8255
|
+
const ss = String(date.getUTCSeconds()).padStart(2, "0");
|
|
8256
|
+
return {
|
|
8257
|
+
date: `${day} ${month} ${year}`,
|
|
8258
|
+
time: `${hh}:${mm}:${ss}Z`
|
|
8259
|
+
};
|
|
8260
|
+
};
|
|
8261
|
+
var ensureMetaDate = (gedcom, record, tag, when, restores) => {
|
|
8262
|
+
if (record.get(tag)) {
|
|
8263
|
+
return;
|
|
8264
|
+
}
|
|
8265
|
+
const { date, time } = formatGedcom7Timestamp(when);
|
|
8266
|
+
const meta = createCommon(gedcom, void 0, record);
|
|
8267
|
+
meta.type = tag;
|
|
8268
|
+
const dateNode = createCommonDate(gedcom, void 0, record, meta);
|
|
8269
|
+
dateNode.type = "DATE";
|
|
8270
|
+
dateNode.value = date;
|
|
8271
|
+
dateNode.set("TIME", time);
|
|
8272
|
+
meta.set("DATE", dateNode);
|
|
8273
|
+
record.set(tag, meta);
|
|
8274
|
+
restores.push(() => {
|
|
8275
|
+
record.remove(tag);
|
|
8276
|
+
});
|
|
8277
|
+
};
|
|
8278
|
+
var ensureUid = (record, restores) => {
|
|
8279
|
+
const existing = record.get("UID")?.toValue();
|
|
8280
|
+
if (typeof existing === "string" && existing.trim()) {
|
|
8281
|
+
return;
|
|
8282
|
+
}
|
|
8283
|
+
const uid = createGedcomUid();
|
|
8284
|
+
record.set("UID", uid);
|
|
8285
|
+
restores.push(() => {
|
|
8286
|
+
record.remove("UID");
|
|
8287
|
+
});
|
|
8288
|
+
};
|
|
8289
|
+
var applyGedcom7RecordMetadata = (gedcom, options) => {
|
|
8290
|
+
const restores = [];
|
|
8291
|
+
const now = options?.now ?? /* @__PURE__ */ new Date();
|
|
8292
|
+
const visit = (record) => {
|
|
8293
|
+
if (!record?.id) {
|
|
8294
|
+
return;
|
|
8295
|
+
}
|
|
8296
|
+
ensureUid(record, restores);
|
|
8297
|
+
ensureMetaDate(gedcom, record, "CREA", now, restores);
|
|
8298
|
+
ensureMetaDate(gedcom, record, "CHAN", now, restores);
|
|
8299
|
+
};
|
|
8300
|
+
gedcom.indis()?.forEach((indi) => visit(indi));
|
|
8301
|
+
gedcom.fams()?.forEach((fam) => visit(fam));
|
|
8302
|
+
gedcom.objes()?.forEach((obje) => visit(obje));
|
|
8303
|
+
gedcom.sours()?.forEach((sour) => visit(sour));
|
|
8304
|
+
gedcom.repos()?.forEach((repo) => visit(repo));
|
|
8305
|
+
gedcom.subms()?.forEach((subm) => visit(subm));
|
|
8306
|
+
gedcom.snotes()?.forEach((note) => visit(note));
|
|
8307
|
+
return () => {
|
|
8308
|
+
for (let i = restores.length - 1; i >= 0; i -= 1) {
|
|
8309
|
+
restores[i]?.();
|
|
8310
|
+
}
|
|
8311
|
+
};
|
|
8312
|
+
};
|
|
8313
|
+
|
|
8314
|
+
// src/utils/gedcom7-schema.ts
|
|
8315
|
+
var TREEVIZ_EXTENSION_BASE_URI = "https://treeviz.com/gedcom";
|
|
8316
|
+
var TREEVIZ_EXTENSION_URIS = {
|
|
8317
|
+
_ORIGHEAD: `${TREEVIZ_EXTENSION_BASE_URI}#_ORIGHEAD`,
|
|
8318
|
+
_TREE: `${TREEVIZ_EXTENSION_BASE_URI}#_TREE`,
|
|
8319
|
+
_TID: `${TREEVIZ_EXTENSION_BASE_URI}#_TID`,
|
|
8320
|
+
_PRIM: `${TREEVIZ_EXTENSION_BASE_URI}#_PRIM`,
|
|
8321
|
+
_FREL: `${TREEVIZ_EXTENSION_BASE_URI}#_FREL`,
|
|
8322
|
+
_MREL: `${TREEVIZ_EXTENSION_BASE_URI}#_MREL`,
|
|
8323
|
+
_SREL: `${TREEVIZ_EXTENSION_BASE_URI}#_SREL`,
|
|
8324
|
+
_UID: `${TREEVIZ_EXTENSION_BASE_URI}#_UID`,
|
|
8325
|
+
_WLNK: `${TREEVIZ_EXTENSION_BASE_URI}#_WLNK`,
|
|
8326
|
+
_MTTAG: `${TREEVIZ_EXTENSION_BASE_URI}#_MTTAG`,
|
|
8327
|
+
_MTCAT: `${TREEVIZ_EXTENSION_BASE_URI}#_MTCAT`,
|
|
8328
|
+
_CLON: `${TREEVIZ_EXTENSION_BASE_URI}#_CLON`,
|
|
8329
|
+
_MSER: `${TREEVIZ_EXTENSION_BASE_URI}#_MSER`,
|
|
8330
|
+
_OID: `${TREEVIZ_EXTENSION_BASE_URI}#_OID`,
|
|
8331
|
+
_LKID: `${TREEVIZ_EXTENSION_BASE_URI}#_LKID`,
|
|
8332
|
+
_PHOTO_RIN: `${TREEVIZ_EXTENSION_BASE_URI}#_PHOTO_RIN`,
|
|
8333
|
+
_EXPORTED_FROM_SITE_ID: `${TREEVIZ_EXTENSION_BASE_URI}#_EXPORTED_FROM_SITE_ID`,
|
|
8334
|
+
_FS_ID: `${TREEVIZ_EXTENSION_BASE_URI}#_FS_ID`,
|
|
8335
|
+
_FS_LINK: `${TREEVIZ_EXTENSION_BASE_URI}#_FS_LINK`,
|
|
8336
|
+
_FS_MATCH: `${TREEVIZ_EXTENSION_BASE_URI}#_FS_MATCH`,
|
|
8337
|
+
_FS_SOUR: `${TREEVIZ_EXTENSION_BASE_URI}#_FS_SOUR`,
|
|
8338
|
+
_IS_FS: `${TREEVIZ_EXTENSION_BASE_URI}#_IS_FS`,
|
|
8339
|
+
_LABEL: `${TREEVIZ_EXTENSION_BASE_URI}#_LABEL`,
|
|
8340
|
+
_MILT: `${TREEVIZ_EXTENSION_BASE_URI}#_MILT`,
|
|
8341
|
+
_MILTID: `${TREEVIZ_EXTENSION_BASE_URI}#_MILTID`,
|
|
8342
|
+
_ORIG: `${TREEVIZ_EXTENSION_BASE_URI}#_ORIG`,
|
|
8343
|
+
_ENV: `${TREEVIZ_EXTENSION_BASE_URI}#_ENV`,
|
|
8344
|
+
_TREEVIZ_SETTINGS: `${TREEVIZ_EXTENSION_BASE_URI}#_TREEVIZ_SETTINGS`,
|
|
8345
|
+
_TREEVIZ_VIEW: `${TREEVIZ_EXTENSION_BASE_URI}#_TREEVIZ_VIEW`,
|
|
8346
|
+
_TREEVIZ_DETECTIVE: `${TREEVIZ_EXTENSION_BASE_URI}#_TREEVIZ_DETECTIVE`,
|
|
8347
|
+
_TREEVIZ_DETECTIVE_STATE: `${TREEVIZ_EXTENSION_BASE_URI}#_TREEVIZ_DETECTIVE_STATE`
|
|
8348
|
+
};
|
|
8349
|
+
var parseTagDefinition = (payload) => {
|
|
8350
|
+
const trimmed = payload.trim();
|
|
8351
|
+
const space = trimmed.indexOf(" ");
|
|
8352
|
+
if (space <= 0) {
|
|
8353
|
+
return void 0;
|
|
8354
|
+
}
|
|
8355
|
+
const tag = trimmed.slice(0, space).trim();
|
|
8356
|
+
const uri = trimmed.slice(space + 1).trim();
|
|
8357
|
+
if (!tag || !uri) {
|
|
8358
|
+
return void 0;
|
|
8359
|
+
}
|
|
8360
|
+
return { tag, uri };
|
|
8361
|
+
};
|
|
8362
|
+
var getExtensionSchema = (gedcom) => {
|
|
8363
|
+
const map = /* @__PURE__ */ new Map();
|
|
8364
|
+
const schma = gedcom.get("HEAD")?.get("SCHMA");
|
|
8365
|
+
if (!schma) {
|
|
8366
|
+
return map;
|
|
8367
|
+
}
|
|
8368
|
+
schma.get("TAG")?.toList()?.forEach((tagNode) => {
|
|
8369
|
+
const payload = tagNode?.toValue();
|
|
8370
|
+
if (typeof payload !== "string") {
|
|
8371
|
+
return;
|
|
8372
|
+
}
|
|
8373
|
+
const parsed = parseTagDefinition(payload);
|
|
8374
|
+
if (parsed) {
|
|
8375
|
+
map.set(parsed.tag.toUpperCase(), parsed.uri);
|
|
8376
|
+
}
|
|
8377
|
+
});
|
|
8378
|
+
return map;
|
|
8379
|
+
};
|
|
8380
|
+
var ensureSchemaNode = (gedcom) => {
|
|
8381
|
+
const head = gedcom.get("HEAD");
|
|
8382
|
+
if (!head) {
|
|
8383
|
+
return void 0;
|
|
8384
|
+
}
|
|
8385
|
+
let schma = head.get("SCHMA");
|
|
8386
|
+
if (!schma) {
|
|
8387
|
+
schma = createCommon(gedcom, void 0, head);
|
|
8388
|
+
head.set("SCHMA", schma);
|
|
8389
|
+
}
|
|
8390
|
+
return schma;
|
|
8391
|
+
};
|
|
8392
|
+
var registerExtensionTag = (gedcom, tag, uri) => {
|
|
8393
|
+
const normalizedTag = tag.trim().toUpperCase();
|
|
8394
|
+
const normalizedUri = uri.trim();
|
|
8395
|
+
if (!normalizedTag.startsWith("_") || !normalizedUri) {
|
|
8396
|
+
return void 0;
|
|
8397
|
+
}
|
|
8398
|
+
const schma = ensureSchemaNode(gedcom);
|
|
8399
|
+
if (!schma) {
|
|
8400
|
+
return void 0;
|
|
8401
|
+
}
|
|
8402
|
+
const payload = `${normalizedTag} ${normalizedUri}`;
|
|
8403
|
+
const existingList = schma.get("TAG")?.toList();
|
|
8404
|
+
const existing = existingList?.values().find((node) => {
|
|
8405
|
+
const value = node?.toValue();
|
|
8406
|
+
return typeof value === "string" && value.trim().toUpperCase().startsWith(`${normalizedTag} `);
|
|
8407
|
+
});
|
|
8408
|
+
if (existing) {
|
|
8409
|
+
existing.value = payload;
|
|
8410
|
+
return existing;
|
|
8411
|
+
}
|
|
8412
|
+
const tagNode = createCommon(gedcom, void 0, schma);
|
|
8413
|
+
tagNode.value = payload;
|
|
8414
|
+
schma.assign("TAG", tagNode);
|
|
8415
|
+
return tagNode;
|
|
8416
|
+
};
|
|
8417
|
+
var ensureExtensionSchema = (gedcom, extraTags) => {
|
|
8418
|
+
const head = gedcom.get("HEAD");
|
|
8419
|
+
const hadSchma = !!head?.get("SCHMA");
|
|
8420
|
+
const previousPayloads = head?.get("SCHMA")?.get("TAG")?.toList()?.values().map((node) => ({
|
|
8421
|
+
node,
|
|
8422
|
+
value: node?.toValue()
|
|
8423
|
+
})) ?? [];
|
|
8424
|
+
const tags = /* @__PURE__ */ new Set([
|
|
8425
|
+
...Object.keys(TREEVIZ_EXTENSION_URIS),
|
|
8426
|
+
...(extraTags ?? []).map((tag) => tag.toUpperCase())
|
|
8427
|
+
]);
|
|
8428
|
+
tags.forEach((tag) => {
|
|
8429
|
+
const uri = TREEVIZ_EXTENSION_URIS[tag] ?? `${TREEVIZ_EXTENSION_BASE_URI}#${tag}`;
|
|
8430
|
+
if (tag.startsWith("_")) {
|
|
8431
|
+
registerExtensionTag(gedcom, tag, uri);
|
|
8432
|
+
}
|
|
8433
|
+
});
|
|
8434
|
+
return () => {
|
|
8435
|
+
if (!head) {
|
|
8436
|
+
return;
|
|
8437
|
+
}
|
|
8438
|
+
if (!hadSchma) {
|
|
8439
|
+
head.remove("SCHMA");
|
|
8440
|
+
return;
|
|
8441
|
+
}
|
|
8442
|
+
const schma = head.get("SCHMA");
|
|
8443
|
+
const list = schma?.get("TAG")?.toList();
|
|
8444
|
+
const keep = new Set(
|
|
8445
|
+
previousPayloads.map(
|
|
8446
|
+
(item) => typeof item.value === "string" ? item.value : void 0
|
|
8447
|
+
).filter((value) => !!value)
|
|
8448
|
+
);
|
|
8449
|
+
list?.values().forEach((node) => {
|
|
8450
|
+
const value = node?.toValue();
|
|
8451
|
+
if (typeof value === "string" && !keep.has(value) && node) {
|
|
8452
|
+
list.delete(node);
|
|
8453
|
+
}
|
|
8454
|
+
});
|
|
8455
|
+
previousPayloads.forEach(({ node, value }) => {
|
|
8456
|
+
if (node && value !== void 0) {
|
|
8457
|
+
node.value = value;
|
|
8458
|
+
}
|
|
8459
|
+
});
|
|
8460
|
+
};
|
|
8461
|
+
};
|
|
8462
|
+
var collectExtensionTagsFrom = (node, into = /* @__PURE__ */ new Set()) => {
|
|
8463
|
+
if (!node) {
|
|
8464
|
+
return into;
|
|
8465
|
+
}
|
|
8466
|
+
const keys = Object.keys(node).filter(
|
|
8467
|
+
(key) => key.startsWith("_") && !key.startsWith("_gedcom") && !key.startsWith("_value") && !key.startsWith("_id") && !key.startsWith("_main") && !key.startsWith("_parent") && !key.startsWith("_unique") && !key.startsWith("_type") && !key.startsWith("_refs") && !key.startsWith("_date")
|
|
8468
|
+
);
|
|
8469
|
+
keys.forEach((key) => {
|
|
8470
|
+
const tag = key.toUpperCase();
|
|
8471
|
+
if (/^_[A-Z0-9_]+$/.test(tag)) {
|
|
8472
|
+
into.add(tag);
|
|
8473
|
+
}
|
|
8474
|
+
});
|
|
8475
|
+
return into;
|
|
8476
|
+
};
|
|
8477
|
+
|
|
8478
|
+
// package.json
|
|
8479
|
+
var package_default = {
|
|
8480
|
+
name: "@treeviz/gedcom-parser",
|
|
8481
|
+
version: "2.1.0"};
|
|
8482
|
+
|
|
8483
|
+
// src/utils/get-product-details.ts
|
|
8484
|
+
var isDevelopment = () => {
|
|
8485
|
+
return !process.env.NODE_ENV || process.env.NODE_ENV === "development";
|
|
8486
|
+
};
|
|
8487
|
+
var getVersion = () => package_default.version;
|
|
8488
|
+
var getName = () => package_default.name;
|
|
8489
|
+
|
|
8490
|
+
// src/utils/multimedia.ts
|
|
8491
|
+
var inferMediaForm = (file, fallback = "bin") => {
|
|
8492
|
+
const withoutQuery = file.split("?")[0] || file;
|
|
8493
|
+
const ext = getFileExtension(withoutQuery);
|
|
8494
|
+
if (ext) {
|
|
8495
|
+
return ext.toLowerCase() === "jpeg" ? "jpg" : ext.toLowerCase();
|
|
8496
|
+
}
|
|
8497
|
+
return fallback;
|
|
8498
|
+
};
|
|
8499
|
+
var mergeMediaLists = (...lists) => {
|
|
8500
|
+
const merged = {};
|
|
8501
|
+
for (const list of lists) {
|
|
8502
|
+
if (!list) continue;
|
|
8503
|
+
Object.assign(merged, list);
|
|
8504
|
+
}
|
|
8505
|
+
return merged;
|
|
8506
|
+
};
|
|
8507
|
+
var isObjePointer = (value) => typeof value === "string" && /^@O\d+@$/.test(value);
|
|
8508
|
+
|
|
8509
|
+
// src/classes/note.ts
|
|
8510
|
+
var CommonNote = class extends Common {
|
|
8511
|
+
constructor(gedcom, id, main, parent) {
|
|
8512
|
+
super(gedcom, id, main, parent);
|
|
8513
|
+
if (!id) {
|
|
8514
|
+
delete this.id;
|
|
8515
|
+
}
|
|
8516
|
+
}
|
|
8517
|
+
set value(value) {
|
|
8518
|
+
const [note, ...contents] = value?.split(/\r?\n/) ?? [];
|
|
8519
|
+
this._value = note;
|
|
8520
|
+
if (contents.length) {
|
|
8521
|
+
const newContents = new List();
|
|
8522
|
+
contents.forEach((c, i) => {
|
|
8523
|
+
const newContent = createCommon(
|
|
8524
|
+
this._gedcom,
|
|
8525
|
+
void 0,
|
|
8526
|
+
this.main
|
|
8527
|
+
);
|
|
8528
|
+
newContent.id = `@U${i}@`;
|
|
8529
|
+
newContent.value = c;
|
|
8530
|
+
newContents.append(newContent);
|
|
8531
|
+
});
|
|
8532
|
+
const firstItem = newContents.index(0);
|
|
8533
|
+
if (firstItem) {
|
|
8534
|
+
if (newContents.length === 1) {
|
|
8535
|
+
this.set("CONT", firstItem);
|
|
8536
|
+
} else {
|
|
8537
|
+
this.set("CONT", newContents);
|
|
8538
|
+
}
|
|
8539
|
+
}
|
|
8540
|
+
}
|
|
8541
|
+
}
|
|
8542
|
+
get value() {
|
|
8543
|
+
const contents = this.get("CONT")?.toList().map((content) => content.value).join("\n");
|
|
8544
|
+
if (contents) {
|
|
8545
|
+
return `${this._value}
|
|
8546
|
+
${contents}`;
|
|
8547
|
+
}
|
|
8548
|
+
return this._value;
|
|
8549
|
+
}
|
|
8550
|
+
exportValue() {
|
|
8551
|
+
return this._value;
|
|
8552
|
+
}
|
|
8553
|
+
};
|
|
8554
|
+
var createCommonNote = (gedcom, id, main, parent) => {
|
|
8555
|
+
return createProxy(
|
|
8556
|
+
new CommonNote(gedcom, id, main, parent)
|
|
8557
|
+
);
|
|
8558
|
+
};
|
|
8559
|
+
|
|
8560
|
+
// src/classes/obje.ts
|
|
8561
|
+
var Obje = class extends Common {
|
|
8562
|
+
standardizeMedia(namespace, override = true, urlGetter, gedcomVersion) {
|
|
8563
|
+
if (!this._gedcom) {
|
|
8564
|
+
return this;
|
|
8565
|
+
}
|
|
8566
|
+
const rin = this?.get("RIN")?.toValue();
|
|
8567
|
+
const clone = this?.get("_CLON._OID")?.toValue();
|
|
8568
|
+
const mser = this?.get("_MSER._LKID")?.toValue();
|
|
8569
|
+
const title = this?.get("FILE.TITL")?.toValue() ?? this?.get("TITL")?.toValue() ?? "";
|
|
8570
|
+
const note = this?.get("FILE.NOTE")?.toValue() ?? this?.get("NOTE")?.toValue() ?? "";
|
|
8571
|
+
const formRaw = this?.get("FILE.FORM")?.toValue() ?? this?.get("FORM")?.toValue();
|
|
8572
|
+
const mediType = this?.get("FILE.FORM.TYPE")?.toValue() ?? this?.get("FORM.TYPE")?.toValue() ?? this?.get("MEDI")?.toValue();
|
|
8573
|
+
const file = this?.get("FILE")?.toValue();
|
|
8574
|
+
const imgId = rin || clone || mser;
|
|
8575
|
+
const url = file || namespace && urlGetter?.(namespace, imgId);
|
|
8576
|
+
if (!url) {
|
|
8577
|
+
return this;
|
|
8578
|
+
}
|
|
8579
|
+
const version = normalizeGedcomVersion(
|
|
8580
|
+
gedcomVersion ?? this._gedcom.getGedcomVersion?.()
|
|
8581
|
+
);
|
|
8582
|
+
const form = formRaw || inferMediaForm(String(url));
|
|
8583
|
+
const newObject = createObje(this._gedcom, this.id, this.main);
|
|
8584
|
+
if (!override) {
|
|
8585
|
+
Object.assign(newObject, this);
|
|
8586
|
+
}
|
|
8587
|
+
const fileNode = createCommon(this._gedcom, void 0, this.main);
|
|
8588
|
+
fileNode.value = url;
|
|
8589
|
+
if (version === "7.0") {
|
|
8590
|
+
const formNode = createCommon(this._gedcom, void 0, fileNode);
|
|
8591
|
+
formNode.value = form;
|
|
8592
|
+
if (mediType) {
|
|
8593
|
+
formNode.set("TYPE", String(mediType));
|
|
8594
|
+
}
|
|
8595
|
+
fileNode.set("FORM", formNode);
|
|
8596
|
+
if (title) {
|
|
8597
|
+
fileNode.set("TITL", String(title));
|
|
8598
|
+
}
|
|
8599
|
+
if (note) {
|
|
8600
|
+
fileNode.set("NOTE", String(note));
|
|
8601
|
+
}
|
|
8602
|
+
newObject.set("FILE", fileNode);
|
|
8603
|
+
} else {
|
|
8604
|
+
newObject.set("FILE", fileNode);
|
|
8605
|
+
newObject.set("FORM", form);
|
|
8606
|
+
if (mediType) {
|
|
8607
|
+
newObject.set("MEDI", String(mediType));
|
|
8608
|
+
}
|
|
8609
|
+
if (title) {
|
|
8610
|
+
newObject.set("TITL", String(title));
|
|
8611
|
+
if (!note) {
|
|
8612
|
+
newObject.set("NOTE", String(title));
|
|
8613
|
+
}
|
|
8614
|
+
}
|
|
8615
|
+
if (note) {
|
|
8616
|
+
newObject.set("NOTE", String(note));
|
|
8617
|
+
if (!title) {
|
|
8618
|
+
newObject.set("TITL", String(note));
|
|
8619
|
+
}
|
|
8620
|
+
}
|
|
8621
|
+
}
|
|
8622
|
+
const prim = this.get("_PRIM")?.toValue();
|
|
8623
|
+
if (prim === "Y" || prim === "N") {
|
|
8624
|
+
newObject.set("_PRIM", prim);
|
|
8625
|
+
}
|
|
8626
|
+
const photoRin = this.get("_PHOTO_RIN")?.toValue();
|
|
8627
|
+
if (rin) {
|
|
8628
|
+
newObject.set("RIN", String(rin));
|
|
8629
|
+
}
|
|
8630
|
+
if (photoRin) {
|
|
8631
|
+
newObject.set("_PHOTO_RIN", String(photoRin));
|
|
8632
|
+
}
|
|
8633
|
+
const clonNode = this.get("_CLON");
|
|
8634
|
+
if (clonNode) {
|
|
8635
|
+
newObject.set("_CLON", clonNode);
|
|
8636
|
+
}
|
|
8637
|
+
const mserNode = this.get("_MSER");
|
|
8638
|
+
if (mserNode) {
|
|
8639
|
+
newObject.set("_MSER", mserNode);
|
|
8640
|
+
}
|
|
8641
|
+
const oidNode = this.get("_OID");
|
|
8642
|
+
if (oidNode && !newObject.get("_OID")) {
|
|
8643
|
+
newObject.set("_OID", oidNode);
|
|
8644
|
+
}
|
|
8645
|
+
const lkidNode = this.get("_LKID");
|
|
8646
|
+
if (lkidNode && !newObject.get("_LKID")) {
|
|
8647
|
+
newObject.set("_LKID", lkidNode);
|
|
8648
|
+
}
|
|
8649
|
+
if (override) {
|
|
8650
|
+
this.remove("FILE");
|
|
8651
|
+
this.remove("FORM");
|
|
8652
|
+
this.remove("MEDI");
|
|
8653
|
+
this.remove("TITL");
|
|
8654
|
+
this.remove("NOTE");
|
|
8655
|
+
Object.assign(this, newObject);
|
|
8656
|
+
return this;
|
|
8657
|
+
}
|
|
8658
|
+
return newObject;
|
|
8659
|
+
}
|
|
8660
|
+
};
|
|
8661
|
+
var createObje = (gedcom, id, main, parent) => {
|
|
8662
|
+
return createProxy(
|
|
8663
|
+
new Obje(gedcom, id, main, parent)
|
|
8664
|
+
);
|
|
8665
|
+
};
|
|
8666
|
+
|
|
8667
|
+
// src/classes/objes.ts
|
|
8668
|
+
var Objects = class _Objects extends List {
|
|
8669
|
+
copy() {
|
|
8670
|
+
const newList = new _Objects();
|
|
8671
|
+
this.entries().forEach(([key, value]) => {
|
|
8672
|
+
newList.item(key, value);
|
|
8673
|
+
});
|
|
8674
|
+
return newList;
|
|
8675
|
+
}
|
|
8676
|
+
except(item) {
|
|
8677
|
+
return this.copy().delete(item);
|
|
8678
|
+
}
|
|
8679
|
+
};
|
|
8680
|
+
|
|
8681
|
+
// src/classes/gedcom.ts
|
|
8682
|
+
var isObjectPatch = (value) => {
|
|
8683
|
+
return !!value && typeof value === "object" && !Array.isArray(value);
|
|
8684
|
+
};
|
|
8685
|
+
var GedCom = class extends Common {
|
|
8686
|
+
constructor() {
|
|
8687
|
+
super();
|
|
8688
|
+
this.tagMembers = {};
|
|
8689
|
+
this.reflist = {};
|
|
8690
|
+
this.refcount = 0;
|
|
8691
|
+
delete this._gedcom;
|
|
8692
|
+
delete this.id;
|
|
8693
|
+
this.removeValue();
|
|
8694
|
+
}
|
|
8695
|
+
getMain(type, index) {
|
|
8696
|
+
const list = !type || type instanceof List ? type : this.getList(type);
|
|
8697
|
+
if (!list) {
|
|
8698
|
+
return void 0;
|
|
8699
|
+
}
|
|
8700
|
+
if (typeof index === "string") {
|
|
8701
|
+
return list.item(index);
|
|
8702
|
+
}
|
|
8703
|
+
const keys = list.keys();
|
|
8704
|
+
return list.item(keys[index]);
|
|
8705
|
+
}
|
|
8706
|
+
getList(type) {
|
|
8707
|
+
return this.get(type);
|
|
8708
|
+
}
|
|
8709
|
+
createNodeFromPatchValue(value, main) {
|
|
8710
|
+
if (value === void 0 || value === null) {
|
|
8711
|
+
return void 0;
|
|
8712
|
+
}
|
|
8713
|
+
const node = createCommon(this, void 0, main);
|
|
8714
|
+
if (Array.isArray(value)) {
|
|
8715
|
+
value.forEach((item) => {
|
|
8716
|
+
const childNode = this.createNodeFromPatchValue(item, node);
|
|
8717
|
+
if (childNode) {
|
|
8718
|
+
node.assign("DATA", childNode);
|
|
8719
|
+
}
|
|
8720
|
+
});
|
|
8721
|
+
return node;
|
|
8722
|
+
}
|
|
8723
|
+
if (isObjectPatch(value)) {
|
|
8724
|
+
this.applyObjectToCommon(node, value);
|
|
8725
|
+
return node;
|
|
8726
|
+
}
|
|
8727
|
+
node.value = String(value);
|
|
8728
|
+
return node;
|
|
8729
|
+
}
|
|
8730
|
+
applyObjectToCommon(target, patch) {
|
|
8731
|
+
Object.entries(patch).forEach(([rawTag, value]) => {
|
|
8732
|
+
if (rawTag === "value") {
|
|
8733
|
+
if (value === null || value === void 0 || Array.isArray(value) || isObjectPatch(value)) {
|
|
8734
|
+
return;
|
|
8735
|
+
}
|
|
8736
|
+
target.value = String(value);
|
|
8737
|
+
return;
|
|
8738
|
+
}
|
|
8739
|
+
if (rawTag === "id") {
|
|
8740
|
+
if (typeof value === "string") {
|
|
8741
|
+
target.id = value;
|
|
8742
|
+
}
|
|
8743
|
+
return;
|
|
8744
|
+
}
|
|
8745
|
+
const tag = rawTag;
|
|
8746
|
+
if (value === void 0) {
|
|
8747
|
+
return;
|
|
8748
|
+
}
|
|
8749
|
+
if (value === null) {
|
|
8750
|
+
target.remove(tag);
|
|
8751
|
+
return;
|
|
8752
|
+
}
|
|
8753
|
+
if (Array.isArray(value)) {
|
|
8754
|
+
target.remove(tag);
|
|
8755
|
+
value.forEach((item) => {
|
|
8756
|
+
const listNode = this.createNodeFromPatchValue(
|
|
8757
|
+
item,
|
|
8758
|
+
target.main ?? this
|
|
8759
|
+
);
|
|
8760
|
+
if (listNode) {
|
|
8761
|
+
target.assign(tag, listNode);
|
|
8762
|
+
}
|
|
8763
|
+
});
|
|
8764
|
+
return;
|
|
8765
|
+
}
|
|
8766
|
+
if (isObjectPatch(value)) {
|
|
8767
|
+
const existing = target.get(tag);
|
|
8768
|
+
const objectNode = existing ?? createCommon(this, void 0, target.main ?? this);
|
|
8769
|
+
this.applyObjectToCommon(objectNode, value);
|
|
8770
|
+
target.set(tag, objectNode);
|
|
8771
|
+
return;
|
|
8772
|
+
}
|
|
8773
|
+
target.set(tag, String(value));
|
|
8774
|
+
});
|
|
8775
|
+
}
|
|
8776
|
+
applyObject(patch) {
|
|
8777
|
+
this.applyObjectToCommon(this, patch);
|
|
8778
|
+
return this;
|
|
8779
|
+
}
|
|
8780
|
+
indis() {
|
|
8781
|
+
return this.getList("@@INDI");
|
|
8782
|
+
}
|
|
8783
|
+
cloneIndis(target, source, avoidKeys = [], removeFromOriginalList = true) {
|
|
8784
|
+
const hasFAMS = avoidKeys.includes("FAMS");
|
|
8785
|
+
const targetIndi = typeof target === "string" ? this.indi(target) : target;
|
|
8786
|
+
const sourceIndi = typeof source === "string" ? this.indi(source) : source;
|
|
8787
|
+
if (!targetIndi || !sourceIndi) {
|
|
8788
|
+
return this;
|
|
8789
|
+
}
|
|
8790
|
+
const spousesFamily = hasFAMS ? sourceIndi.FAMS?.toList() : void 0;
|
|
8791
|
+
const childrenFamily = sourceIndi.FAMC?.toList();
|
|
8792
|
+
const cloned = targetIndi.clone(false, avoidKeys);
|
|
7122
8793
|
const newCloned = sourceIndi.merge(cloned);
|
|
7123
8794
|
newCloned.cloneOf = targetIndi.id;
|
|
7124
8795
|
targetIndi.clonedBy = newCloned.id;
|
|
@@ -7202,6 +8873,189 @@ var GedCom = class extends Common {
|
|
|
7202
8873
|
fams() {
|
|
7203
8874
|
return this.getList("@@FAM");
|
|
7204
8875
|
}
|
|
8876
|
+
nextIndiKey() {
|
|
8877
|
+
const ids = [];
|
|
8878
|
+
this.indis()?.forEach((_indi, id) => {
|
|
8879
|
+
ids.push(String(id));
|
|
8880
|
+
});
|
|
8881
|
+
return nextRecordId(ids, "I");
|
|
8882
|
+
}
|
|
8883
|
+
nextFamKey() {
|
|
8884
|
+
const ids = [];
|
|
8885
|
+
this.fams()?.forEach((_fam, id) => {
|
|
8886
|
+
ids.push(String(id));
|
|
8887
|
+
});
|
|
8888
|
+
return nextRecordId(ids, "F");
|
|
8889
|
+
}
|
|
8890
|
+
createIndividual() {
|
|
8891
|
+
const existing = this.indis();
|
|
8892
|
+
const indis = existing ?? new Individuals();
|
|
8893
|
+
if (!existing) {
|
|
8894
|
+
this.set("@@INDI", indis);
|
|
8895
|
+
}
|
|
8896
|
+
const id = this.nextIndiKey();
|
|
8897
|
+
const indi = createIndi(this, id);
|
|
8898
|
+
indi.type = "INDI";
|
|
8899
|
+
if (this.getGedcomVersion() === "7.0") {
|
|
8900
|
+
indi.set("UID", createGedcomUid());
|
|
8901
|
+
}
|
|
8902
|
+
indis.item(id, indi);
|
|
8903
|
+
return indi;
|
|
8904
|
+
}
|
|
8905
|
+
createFamily() {
|
|
8906
|
+
const existing = this.fams();
|
|
8907
|
+
const fams = existing ?? new Families();
|
|
8908
|
+
if (!existing) {
|
|
8909
|
+
this.set("@@FAM", fams);
|
|
8910
|
+
}
|
|
8911
|
+
const id = this.nextFamKey();
|
|
8912
|
+
const fam = createFam(this, id);
|
|
8913
|
+
fam.type = "FAM";
|
|
8914
|
+
if (this.getGedcomVersion() === "7.0") {
|
|
8915
|
+
fam.set("UID", createGedcomUid());
|
|
8916
|
+
}
|
|
8917
|
+
fams.item(id, fam);
|
|
8918
|
+
return fam;
|
|
8919
|
+
}
|
|
8920
|
+
nextObjeKey() {
|
|
8921
|
+
const ids = [];
|
|
8922
|
+
this.objes()?.forEach((_obje, id) => {
|
|
8923
|
+
ids.push(String(id));
|
|
8924
|
+
});
|
|
8925
|
+
return nextRecordId(ids, "O");
|
|
8926
|
+
}
|
|
8927
|
+
/**
|
|
8928
|
+
* Create a top-level multimedia record (`0 @On@ OBJE`) with FILE/FORM/TITL.
|
|
8929
|
+
* GEDCOM 7 uses nested `FILE → FORM [→ TYPE]`; 5.5.1 uses sibling FORM/TITL.
|
|
8930
|
+
*/
|
|
8931
|
+
createMultimediaRecord(input) {
|
|
8932
|
+
const existing = this.objes();
|
|
8933
|
+
const objes = existing ?? new Objects();
|
|
8934
|
+
if (!existing) {
|
|
8935
|
+
this.set("@@OBJE", objes);
|
|
8936
|
+
}
|
|
8937
|
+
const id = this.nextObjeKey();
|
|
8938
|
+
const obje = createObje(this, id);
|
|
8939
|
+
obje.type = "OBJE";
|
|
8940
|
+
objes.item(id, obje);
|
|
8941
|
+
const version = normalizeGedcomVersion(
|
|
8942
|
+
input.gedcomVersion ?? this.getGedcomVersion()
|
|
8943
|
+
);
|
|
8944
|
+
const form = input.form || inferMediaForm(input.file);
|
|
8945
|
+
const fileNode = createCommon(this, void 0, obje);
|
|
8946
|
+
fileNode.value = input.file;
|
|
8947
|
+
if (version === "7.0") {
|
|
8948
|
+
const formNode = createCommon(
|
|
8949
|
+
this,
|
|
8950
|
+
void 0,
|
|
8951
|
+
fileNode
|
|
8952
|
+
);
|
|
8953
|
+
formNode.value = form;
|
|
8954
|
+
if (input.mediType) {
|
|
8955
|
+
formNode.set("TYPE", input.mediType);
|
|
8956
|
+
}
|
|
8957
|
+
fileNode.set("FORM", formNode);
|
|
8958
|
+
if (input.title) {
|
|
8959
|
+
fileNode.set("TITL", input.title);
|
|
8960
|
+
}
|
|
8961
|
+
obje.set("FILE", fileNode);
|
|
8962
|
+
} else {
|
|
8963
|
+
obje.set("FILE", fileNode);
|
|
8964
|
+
obje.set("FORM", form);
|
|
8965
|
+
if (input.mediType) {
|
|
8966
|
+
obje.set("MEDI", input.mediType);
|
|
8967
|
+
}
|
|
8968
|
+
if (input.title) {
|
|
8969
|
+
obje.set("TITL", input.title);
|
|
8970
|
+
}
|
|
8971
|
+
}
|
|
8972
|
+
if (input.primary) {
|
|
8973
|
+
obje.set("_PRIM", "Y");
|
|
8974
|
+
}
|
|
8975
|
+
if (normalizeGedcomVersion(
|
|
8976
|
+
input.gedcomVersion ?? this.getGedcomVersion()
|
|
8977
|
+
) === "7.0") {
|
|
8978
|
+
obje.set("UID", createGedcomUid());
|
|
8979
|
+
}
|
|
8980
|
+
return obje;
|
|
8981
|
+
}
|
|
8982
|
+
nextSnoteKey() {
|
|
8983
|
+
const ids = [];
|
|
8984
|
+
this.snotes()?.forEach((_note, id) => {
|
|
8985
|
+
ids.push(String(id));
|
|
8986
|
+
});
|
|
8987
|
+
return nextRecordId(ids, "N");
|
|
8988
|
+
}
|
|
8989
|
+
snotes() {
|
|
8990
|
+
return this.getList("@@SNOTE");
|
|
8991
|
+
}
|
|
8992
|
+
snote(index) {
|
|
8993
|
+
return this.getMain(this.snotes(), index);
|
|
8994
|
+
}
|
|
8995
|
+
/**
|
|
8996
|
+
* Create a top-level shared note record (`0 @Nn@ SNOTE` for GEDCOM 7).
|
|
8997
|
+
*/
|
|
8998
|
+
createSharedNote(text) {
|
|
8999
|
+
const existing = this.snotes();
|
|
9000
|
+
const notes = existing ?? new List();
|
|
9001
|
+
if (!existing) {
|
|
9002
|
+
this.set("@@SNOTE", notes);
|
|
9003
|
+
}
|
|
9004
|
+
const id = this.nextSnoteKey();
|
|
9005
|
+
const note = createCommonNote(this, id);
|
|
9006
|
+
note.type = "SNOTE";
|
|
9007
|
+
note.value = text;
|
|
9008
|
+
if (this.getGedcomVersion() === "7.0") {
|
|
9009
|
+
note.set("UID", createGedcomUid());
|
|
9010
|
+
}
|
|
9011
|
+
notes.item(id, note);
|
|
9012
|
+
return note;
|
|
9013
|
+
}
|
|
9014
|
+
registerExtensionTag(tag, uri) {
|
|
9015
|
+
return registerExtensionTag(this, tag, uri);
|
|
9016
|
+
}
|
|
9017
|
+
getExtensionSchema() {
|
|
9018
|
+
return getExtensionSchema(this);
|
|
9019
|
+
}
|
|
9020
|
+
ensureExtensionSchema(extraTags) {
|
|
9021
|
+
ensureExtensionSchema(this, extraTags);
|
|
9022
|
+
return getExtensionSchema(this);
|
|
9023
|
+
}
|
|
9024
|
+
/**
|
|
9025
|
+
* Collect multimedia descriptors via each individual's `multimedia()`.
|
|
9026
|
+
*/
|
|
9027
|
+
async collectMultimedia(options) {
|
|
9028
|
+
const people = [];
|
|
9029
|
+
if (options?.indiIds?.length) {
|
|
9030
|
+
options.indiIds.forEach((id) => {
|
|
9031
|
+
const indi = this.indi(id);
|
|
9032
|
+
if (indi) {
|
|
9033
|
+
people.push(indi);
|
|
9034
|
+
}
|
|
9035
|
+
});
|
|
9036
|
+
} else {
|
|
9037
|
+
this.indis()?.forEach((indi) => {
|
|
9038
|
+
if (indi) {
|
|
9039
|
+
people.push(indi);
|
|
9040
|
+
}
|
|
9041
|
+
});
|
|
9042
|
+
}
|
|
9043
|
+
const lists = await Promise.all(
|
|
9044
|
+
people.map((indi) => indi.multimedia(options?.namespace))
|
|
9045
|
+
);
|
|
9046
|
+
return mergeMediaLists(...lists);
|
|
9047
|
+
}
|
|
9048
|
+
/**
|
|
9049
|
+
* Serialize as GEDCOM 7 and pack a FamilySearch GEDZIP (`.gdz`).
|
|
9050
|
+
* Media bytes must be supplied by the caller (cache/fetch outside the parser).
|
|
9051
|
+
*/
|
|
9052
|
+
async toGedzip(options) {
|
|
9053
|
+
const text = this.toGedcom(void 0, 0, {
|
|
9054
|
+
...options,
|
|
9055
|
+
gedcomVersion: "7.0"
|
|
9056
|
+
});
|
|
9057
|
+
return buildGedzip(text, options?.media ?? []);
|
|
9058
|
+
}
|
|
7205
9059
|
objes() {
|
|
7206
9060
|
return this.getList("@@OBJE");
|
|
7207
9061
|
}
|
|
@@ -7286,18 +9140,70 @@ var GedCom = class extends Common {
|
|
|
7286
9140
|
});
|
|
7287
9141
|
return lists;
|
|
7288
9142
|
}
|
|
7289
|
-
|
|
9143
|
+
getGedcomVersion() {
|
|
9144
|
+
const raw = this.get("HEAD")?.get("GEDC")?.get("VERS")?.toValue();
|
|
9145
|
+
return normalizeGedcomVersion(
|
|
9146
|
+
typeof raw === "string" ? raw : void 0
|
|
9147
|
+
);
|
|
9148
|
+
}
|
|
9149
|
+
/** Rewrite HEAD.GEDC (and CHAR/FORM) for the requested export version. */
|
|
9150
|
+
applyExportVersion(version) {
|
|
9151
|
+
const head = this.get("HEAD");
|
|
9152
|
+
if (!head) {
|
|
9153
|
+
return;
|
|
9154
|
+
}
|
|
9155
|
+
this.applyGedcomSpecToHead(head, normalizeGedcomVersion(version));
|
|
9156
|
+
}
|
|
9157
|
+
applyGedcomSpecToHead(head, version) {
|
|
9158
|
+
const previousGedc = head.get("GEDC");
|
|
9159
|
+
const previousForm = previousGedc?.get("FORM")?.toValue();
|
|
9160
|
+
const previousChar = head.get("CHAR")?.toValue();
|
|
9161
|
+
head.remove("GEDC");
|
|
9162
|
+
const gedc = head.set("GEDC", "");
|
|
9163
|
+
if (!gedc) {
|
|
9164
|
+
return;
|
|
9165
|
+
}
|
|
9166
|
+
gedc.set("VERS", version);
|
|
9167
|
+
if (version === "7.0") {
|
|
9168
|
+
head.remove("CHAR");
|
|
9169
|
+
return;
|
|
9170
|
+
}
|
|
9171
|
+
gedc.set(
|
|
9172
|
+
"FORM",
|
|
9173
|
+
typeof previousForm === "string" && previousForm ? previousForm : "LINEAGE-LINKED"
|
|
9174
|
+
);
|
|
9175
|
+
if (!head.get("CHAR")?.toValue()) {
|
|
9176
|
+
head.set(
|
|
9177
|
+
"CHAR",
|
|
9178
|
+
typeof previousChar === "string" && previousChar ? previousChar : "UTF-8"
|
|
9179
|
+
);
|
|
9180
|
+
}
|
|
9181
|
+
}
|
|
9182
|
+
getDownloadHeader(gedcomVersion) {
|
|
7290
9183
|
const newHead = createCommon();
|
|
7291
9184
|
Object.assign(newHead, this.get("HEAD") ?? {});
|
|
9185
|
+
this.applyGedcomSpecToHead(
|
|
9186
|
+
newHead,
|
|
9187
|
+
gedcomVersion ?? this.getGedcomVersion()
|
|
9188
|
+
);
|
|
9189
|
+
const existingSour = this.get("HEAD")?.get("SOUR");
|
|
9190
|
+
const existingTreeName = existingSour?.get("_TREE")?.toValue();
|
|
9191
|
+
const existingTreeUniqueId = existingSour?.get("_TID")?.toValue();
|
|
7292
9192
|
const newSour = createCommon();
|
|
7293
|
-
newSour.
|
|
7294
|
-
newSour.set("
|
|
7295
|
-
newSour.set("
|
|
7296
|
-
|
|
7297
|
-
|
|
7298
|
-
|
|
7299
|
-
|
|
7300
|
-
|
|
9193
|
+
newSour.value = APP_BRANDING;
|
|
9194
|
+
newSour.set("NAME", APP_BRANDING);
|
|
9195
|
+
newSour.set("VERS", getVersion());
|
|
9196
|
+
if (typeof existingTreeName === "string" && existingTreeName.trim()) {
|
|
9197
|
+
newSour.set("_TREE", existingTreeName.trim());
|
|
9198
|
+
}
|
|
9199
|
+
if (typeof existingTreeUniqueId === "string" && existingTreeUniqueId.trim()) {
|
|
9200
|
+
newSour.set("_TID", existingTreeUniqueId.trim());
|
|
9201
|
+
}
|
|
9202
|
+
const corp = createCommon();
|
|
9203
|
+
corp.value = APP_BRANDING;
|
|
9204
|
+
corp.set("WWW", "treeviz.com");
|
|
9205
|
+
corp.set("EMAIL", "info@treeviz.com");
|
|
9206
|
+
newSour.set("CORP", corp);
|
|
7301
9207
|
newHead.set("SOUR", newSour);
|
|
7302
9208
|
return newHead;
|
|
7303
9209
|
}
|
|
@@ -7326,20 +9232,45 @@ var GedCom = class extends Common {
|
|
|
7326
9232
|
}
|
|
7327
9233
|
toGedcom(tag, level, options) {
|
|
7328
9234
|
if (options?.super) {
|
|
7329
|
-
return super.toGedcom(tag, level, options);
|
|
9235
|
+
return appendGedcomTrailer(super.toGedcom(tag, level, options));
|
|
7330
9236
|
}
|
|
9237
|
+
const requestedVersion = options?.gedcomVersion;
|
|
9238
|
+
const exportVersion = requestedVersion ? normalizeGedcomVersion(requestedVersion) : this.getGedcomVersion();
|
|
9239
|
+
const exportOptions = {
|
|
9240
|
+
...options,
|
|
9241
|
+
obje: {
|
|
9242
|
+
standardize: options?.obje?.standardize ?? (requestedVersion !== void 0 || !options?.original),
|
|
9243
|
+
override: options?.obje?.override,
|
|
9244
|
+
namespace: options?.obje?.namespace
|
|
9245
|
+
}
|
|
9246
|
+
};
|
|
7331
9247
|
const newGedcom = createGedCom();
|
|
7332
|
-
|
|
9248
|
+
Object.assign(newGedcom, this);
|
|
9249
|
+
if (!exportOptions.original) {
|
|
7333
9250
|
Object.assign(newGedcom, {
|
|
7334
|
-
HEAD: this.getDownloadHeader()
|
|
9251
|
+
HEAD: this.getDownloadHeader(exportVersion)
|
|
7335
9252
|
});
|
|
7336
9253
|
}
|
|
7337
|
-
|
|
7338
|
-
|
|
7339
|
-
const newContent = this.getIndiRelatedLists(options.indis);
|
|
9254
|
+
if (exportOptions.indis?.length) {
|
|
9255
|
+
const newContent = this.getIndiRelatedLists(exportOptions.indis);
|
|
7340
9256
|
Object.assign(newGedcom, newContent);
|
|
7341
9257
|
}
|
|
7342
|
-
|
|
9258
|
+
const restoreEnums = exportVersion === "7.0" ? applyGedcom7Enumerations(newGedcom) : void 0;
|
|
9259
|
+
const restoreDates = exportVersion === "7.0" ? applyGedcom7DatePhrases(newGedcom) : void 0;
|
|
9260
|
+
const restoreMetadata = exportVersion === "7.0" ? applyGedcom7RecordMetadata(newGedcom) : void 0;
|
|
9261
|
+
const restoreSchema = exportVersion === "7.0" ? ensureExtensionSchema(newGedcom) : void 0;
|
|
9262
|
+
try {
|
|
9263
|
+
return newGedcom.toGedcom(tag, level, {
|
|
9264
|
+
...exportOptions,
|
|
9265
|
+
gedcomVersion: exportVersion,
|
|
9266
|
+
super: true
|
|
9267
|
+
});
|
|
9268
|
+
} finally {
|
|
9269
|
+
restoreSchema?.();
|
|
9270
|
+
restoreMetadata?.();
|
|
9271
|
+
restoreDates?.();
|
|
9272
|
+
restoreEnums?.();
|
|
9273
|
+
}
|
|
7343
9274
|
}
|
|
7344
9275
|
hasTag(tag) {
|
|
7345
9276
|
const tagName = typeof tag === "string" ? tag : tag?.get("NAME")?.toValue();
|
|
@@ -7555,144 +9486,6 @@ var createGedCom = () => {
|
|
|
7555
9486
|
return new GedCom();
|
|
7556
9487
|
};
|
|
7557
9488
|
|
|
7558
|
-
// src/classes/note.ts
|
|
7559
|
-
var CommonNote = class extends Common {
|
|
7560
|
-
constructor(gedcom, id, main, parent) {
|
|
7561
|
-
super(gedcom, id, main, parent);
|
|
7562
|
-
delete this.id;
|
|
7563
|
-
}
|
|
7564
|
-
set value(value) {
|
|
7565
|
-
const [note, ...contents] = value?.split(/\r?\n/) ?? [];
|
|
7566
|
-
this._value = note;
|
|
7567
|
-
if (contents.length) {
|
|
7568
|
-
const newContents = new List();
|
|
7569
|
-
contents.forEach((c, i) => {
|
|
7570
|
-
const newContent = createCommon(
|
|
7571
|
-
this._gedcom,
|
|
7572
|
-
void 0,
|
|
7573
|
-
this.main
|
|
7574
|
-
);
|
|
7575
|
-
newContent.id = `@U${i}@`;
|
|
7576
|
-
newContent.value = c;
|
|
7577
|
-
newContents.append(newContent);
|
|
7578
|
-
});
|
|
7579
|
-
const firstItem = newContents.index(0);
|
|
7580
|
-
if (firstItem) {
|
|
7581
|
-
if (newContents.length === 1) {
|
|
7582
|
-
this.set("CONT", firstItem);
|
|
7583
|
-
} else {
|
|
7584
|
-
this.set("CONT", newContents);
|
|
7585
|
-
}
|
|
7586
|
-
}
|
|
7587
|
-
}
|
|
7588
|
-
}
|
|
7589
|
-
get value() {
|
|
7590
|
-
const contents = this.get("CONT")?.toList().map((content) => content.value).join("\n");
|
|
7591
|
-
if (contents) {
|
|
7592
|
-
return `${this._value}
|
|
7593
|
-
${contents}`;
|
|
7594
|
-
}
|
|
7595
|
-
return this._value;
|
|
7596
|
-
}
|
|
7597
|
-
exportValue() {
|
|
7598
|
-
return this._value;
|
|
7599
|
-
}
|
|
7600
|
-
};
|
|
7601
|
-
var createCommonNote = (gedcom, id, main, parent) => {
|
|
7602
|
-
return createProxy(
|
|
7603
|
-
new CommonNote(gedcom, id, main, parent)
|
|
7604
|
-
);
|
|
7605
|
-
};
|
|
7606
|
-
|
|
7607
|
-
// src/classes/obje.ts
|
|
7608
|
-
var Obje = class extends Common {
|
|
7609
|
-
standardizeMedia(namespace, override = true, urlGetter) {
|
|
7610
|
-
if (!this._gedcom) {
|
|
7611
|
-
return this;
|
|
7612
|
-
}
|
|
7613
|
-
const rin = this?.get("RIN")?.toValue();
|
|
7614
|
-
const clone = this?.get("_CLON._OID")?.toValue();
|
|
7615
|
-
const mser = this?.get("_MSER._LKID")?.toValue();
|
|
7616
|
-
const title = this?.get("FILE.TITL")?.toValue() ?? this?.get("TITL")?.toValue() ?? "";
|
|
7617
|
-
const note = this?.get("FILE.NOTE")?.toValue() ?? this?.get("NOTE")?.toValue() ?? "";
|
|
7618
|
-
const form = this?.get("FILE.FORM")?.toValue();
|
|
7619
|
-
const file = this?.get("FILE")?.toValue();
|
|
7620
|
-
const imgId = rin || clone || mser;
|
|
7621
|
-
const url = file || namespace && urlGetter?.(namespace, imgId);
|
|
7622
|
-
if (!url) {
|
|
7623
|
-
return this;
|
|
7624
|
-
}
|
|
7625
|
-
const newObject = createObje(this._gedcom, this.id, this.main);
|
|
7626
|
-
if (!override) {
|
|
7627
|
-
Object.assign(newObject, this);
|
|
7628
|
-
}
|
|
7629
|
-
if (form) {
|
|
7630
|
-
if (typeof form === "string") {
|
|
7631
|
-
const newForm = createCommon(
|
|
7632
|
-
this._gedcom,
|
|
7633
|
-
void 0,
|
|
7634
|
-
this.main
|
|
7635
|
-
);
|
|
7636
|
-
newForm.value = form;
|
|
7637
|
-
newObject.set("FORM", newForm);
|
|
7638
|
-
} else {
|
|
7639
|
-
newObject.set("FORM", form);
|
|
7640
|
-
}
|
|
7641
|
-
}
|
|
7642
|
-
if (title) {
|
|
7643
|
-
if (typeof title === "string") {
|
|
7644
|
-
const newTitle = createCommon(
|
|
7645
|
-
this._gedcom,
|
|
7646
|
-
void 0,
|
|
7647
|
-
this.main
|
|
7648
|
-
);
|
|
7649
|
-
newTitle.value = title;
|
|
7650
|
-
newObject.set("TITL", newTitle);
|
|
7651
|
-
if (!note) {
|
|
7652
|
-
newObject.set("NOTE", newTitle);
|
|
7653
|
-
}
|
|
7654
|
-
} else {
|
|
7655
|
-
newObject.set("TITL", title);
|
|
7656
|
-
if (!note) {
|
|
7657
|
-
newObject.set("NOTE", title);
|
|
7658
|
-
}
|
|
7659
|
-
}
|
|
7660
|
-
}
|
|
7661
|
-
if (note) {
|
|
7662
|
-
if (typeof note === "string") {
|
|
7663
|
-
const newNote = createCommon(
|
|
7664
|
-
this._gedcom,
|
|
7665
|
-
void 0,
|
|
7666
|
-
this.main
|
|
7667
|
-
);
|
|
7668
|
-
newNote.value = note;
|
|
7669
|
-
newObject.set("NOTE", newNote);
|
|
7670
|
-
if (!title) {
|
|
7671
|
-
newObject.set("TITL", newNote);
|
|
7672
|
-
}
|
|
7673
|
-
} else {
|
|
7674
|
-
newObject.set("NOTE", note);
|
|
7675
|
-
if (!title) {
|
|
7676
|
-
newObject.set("TITL", note);
|
|
7677
|
-
}
|
|
7678
|
-
}
|
|
7679
|
-
}
|
|
7680
|
-
const newUrl = createCommon(this._gedcom, void 0, this.main);
|
|
7681
|
-
newUrl.value = url;
|
|
7682
|
-
newObject.set("FILE", newUrl);
|
|
7683
|
-
if (override) {
|
|
7684
|
-
Object.assign(this, newObject);
|
|
7685
|
-
return this;
|
|
7686
|
-
}
|
|
7687
|
-
return newObject;
|
|
7688
|
-
}
|
|
7689
|
-
};
|
|
7690
|
-
var createObje = (gedcom, id, main, parent) => {
|
|
7691
|
-
return createProxy(
|
|
7692
|
-
new Obje(gedcom, id, main, parent)
|
|
7693
|
-
);
|
|
7694
|
-
};
|
|
7695
|
-
|
|
7696
9489
|
// src/classes/repo.ts
|
|
7697
9490
|
var Repo = class extends Common {
|
|
7698
9491
|
};
|
|
@@ -7741,6 +9534,8 @@ var create = (gedcom, type, id, nodes) => {
|
|
|
7741
9534
|
prevNode = createIndi(gedcom, id);
|
|
7742
9535
|
} else if (convertType === "FAM") {
|
|
7743
9536
|
prevNode = createFam(gedcom, id);
|
|
9537
|
+
} else if (convertType === "SNOTE" || convertType === "NOTE") {
|
|
9538
|
+
prevNode = createCommonNote(gedcom, id);
|
|
7744
9539
|
} else {
|
|
7745
9540
|
prevNode = createCommon(gedcom, id);
|
|
7746
9541
|
}
|
|
@@ -7756,7 +9551,7 @@ var create = (gedcom, type, id, nodes) => {
|
|
|
7756
9551
|
prevNode = createObje(gedcom, void 0, mainNode, curNode);
|
|
7757
9552
|
} else if (type === "DATE") {
|
|
7758
9553
|
prevNode = createCommonDate(gedcom, void 0, mainNode, curNode);
|
|
7759
|
-
} else if (type === "NOTE") {
|
|
9554
|
+
} else if (type === "NOTE" || type === "SNOTE") {
|
|
7760
9555
|
prevNode = createCommonNote(gedcom, void 0, mainNode, curNode);
|
|
7761
9556
|
} else if (type === "NAME" && mainNode instanceof Indi) {
|
|
7762
9557
|
prevNode = createCommonName(gedcom, void 0, mainNode, curNode);
|
|
@@ -7773,20 +9568,6 @@ var getRawSize = (raw) => {
|
|
|
7773
9568
|
return `${raw || ""}`?.length ?? 0;
|
|
7774
9569
|
};
|
|
7775
9570
|
|
|
7776
|
-
// src/classes/objes.ts
|
|
7777
|
-
var Objects = class _Objects extends List {
|
|
7778
|
-
copy() {
|
|
7779
|
-
const newList = new _Objects();
|
|
7780
|
-
this.entries().forEach(([key, value]) => {
|
|
7781
|
-
newList.item(key, value);
|
|
7782
|
-
});
|
|
7783
|
-
return newList;
|
|
7784
|
-
}
|
|
7785
|
-
except(item) {
|
|
7786
|
-
return this.copy().delete(item);
|
|
7787
|
-
}
|
|
7788
|
-
};
|
|
7789
|
-
|
|
7790
9571
|
// src/classes/repos.ts
|
|
7791
9572
|
var Repositories = class _Repositories extends List {
|
|
7792
9573
|
copy() {
|
|
@@ -7864,9 +9645,7 @@ var GedcomTree = {
|
|
|
7864
9645
|
}, {}) : {};
|
|
7865
9646
|
const links = new Individuals();
|
|
7866
9647
|
const tags = [];
|
|
7867
|
-
let lines =
|
|
7868
|
-
0 TRLR
|
|
7869
|
-
`.split(/\r?\n/).reduce((acc, line) => {
|
|
9648
|
+
let lines = content.split(/\r?\n/).reduce((acc, line) => {
|
|
7870
9649
|
const lineMatch = line.match(LINE_REG);
|
|
7871
9650
|
if (lineMatch) {
|
|
7872
9651
|
const lineIndent = Number(lineMatch?.groups?.indent ?? 0);
|
|
@@ -7879,6 +9658,13 @@ var GedcomTree = {
|
|
|
7879
9658
|
linesAcc._hasFile = false;
|
|
7880
9659
|
return acc;
|
|
7881
9660
|
}
|
|
9661
|
+
if (lineIndent === 0 && lineType === "TRLR") {
|
|
9662
|
+
if (linesAcc._inHead && filename && !linesAcc._hasFile) {
|
|
9663
|
+
acc.push(`1 FILE ${filename}`);
|
|
9664
|
+
}
|
|
9665
|
+
linesAcc._inHead = false;
|
|
9666
|
+
return acc;
|
|
9667
|
+
}
|
|
7882
9668
|
if (lineIndent === 0 && linesAcc._inHead) {
|
|
7883
9669
|
if (filename && !linesAcc._hasFile) {
|
|
7884
9670
|
acc.push(`1 FILE ${filename}`);
|
|
@@ -7890,6 +9676,13 @@ var GedcomTree = {
|
|
|
7890
9676
|
if (linesAcc._inHead && lineIndent === 1 && lineType === "FILE") {
|
|
7891
9677
|
linesAcc._hasFile = true;
|
|
7892
9678
|
}
|
|
9679
|
+
if (lineType.toUpperCase() === "CONC") {
|
|
9680
|
+
const last = acc[acc.length - 1];
|
|
9681
|
+
if (last !== void 0) {
|
|
9682
|
+
acc[acc.length - 1] = `${last}${lineValue}`;
|
|
9683
|
+
return acc;
|
|
9684
|
+
}
|
|
9685
|
+
}
|
|
7893
9686
|
if (lineIndent > 0 && lineIndent > prevLineIndent && lineValue && isId(lineValue)) {
|
|
7894
9687
|
const refLines = lineValue.split(/,\s*/).map((id) => line.replace(lineValue, id));
|
|
7895
9688
|
if (refLines.length > 1) {
|
|
@@ -7933,8 +9726,9 @@ var GedcomTree = {
|
|
|
7933
9726
|
).replace(/0\s(@[^@]+@)(\sSOUR[^\n]*\n)([123456789]\s.+\n)*/, "").replace(/0 HEAD(.*)\n/, "0 HEAD$1\n1 _IS_PURGED true\n");
|
|
7934
9727
|
lines = linesJoined.split("\n");
|
|
7935
9728
|
}
|
|
9729
|
+
lines = lines.filter((line) => !isGedcomTrailerLine(line));
|
|
7936
9730
|
lines.forEach((line, index) => {
|
|
7937
|
-
if (line.length === 0) {
|
|
9731
|
+
if (line.length === 0 || isGedcomTrailerLine(line)) {
|
|
7938
9732
|
return;
|
|
7939
9733
|
}
|
|
7940
9734
|
const match = reg.exec(line);
|
|
@@ -8071,5 +9865,20 @@ if (isDev) {
|
|
|
8071
9865
|
globalThis.GedcomTree = GedcomTree;
|
|
8072
9866
|
}
|
|
8073
9867
|
var parser_default = GedcomTree;
|
|
9868
|
+
var createEmptyGedcom = (options) => {
|
|
9869
|
+
const { gedcom } = GedcomTree.parse(
|
|
9870
|
+
`0 HEAD
|
|
9871
|
+
1 GEDC
|
|
9872
|
+
2 VERS 5.5.1
|
|
9873
|
+
2 FORM LINEAGE-LINKED
|
|
9874
|
+
1 CHAR UTF-8
|
|
9875
|
+
0 TRLR`,
|
|
9876
|
+
{ filename: options?.filename }
|
|
9877
|
+
);
|
|
9878
|
+
if (!gedcom) {
|
|
9879
|
+
throw new Error("Failed to create empty GEDCOM");
|
|
9880
|
+
}
|
|
9881
|
+
return gedcom;
|
|
9882
|
+
};
|
|
8074
9883
|
|
|
8075
|
-
export { ACCEPTED_DATE_FORMATS, ACCEPTED_DATE_FORMATS_REGEX, parser_default as GedcomTree, PlaceType, cacheDiscoveredPath, commonDateFormatter, create, dateFormatter, extractSeparationYears, extractSplitPoints, findMatchingRangeForSplitRange, fromTuple, generateSplitRanges, getAllProp, getFamilyWith, getFileExtension, getName, getPlaceParts, getPlaces, getRawSize, getVersion, hungarianOrdinalize, implemented, inRange, initializeCache, isDevelopment, isImageFormat, isIntersectedRange, isRangeContained, marriageDateFormatter, nameFormatter, notImplemented, noteDateFormatter, ordinalize, parseRangeBounds, pathCache, placeTranslator, profilePictureCache, relativesCache, resetRelativesCache, setNestedGroup, splitOverlappingRanges, splitRange };
|
|
9884
|
+
export { ACCEPTED_DATE_FORMATS, ACCEPTED_DATE_FORMATS_REGEX, DEFAULT_GEDCOM_EXPORT_VERSION, GEDCOM7_CALENDARS, GEDCOM7_PEDI_VALUES, GEDCOM7_RESN_VALUES, GEDCOM7_ROLE_VALUES, GEDCOM7_SEX_VALUES, GEDCOM_EXPORT_VERSIONS, GEDCOM_TRAILER_TAG, GEDZIP_EXTENSION, GEDZIP_GEDCOM_ENTRY, GEDZIP_MIME, parser_default as GedcomTree, PEDIGREE_VALUES, PlaceType, TREEVIZ_EXTENSION_BASE_URI, TREEVIZ_EXTENSION_URIS, addFamilyFact, addIndividualFact, addNonEvent, appendGedcomTrailer, applyGedcom7DatePhrases, applyGedcom7Enumerations, applyGedcom7RecordMetadata, attachChildToFamily, attachSpouseToFamily, buildGedzip, buildGedzipBlob, bytesToDataUrl, cacheDiscoveredPath, canAttachAsSpouse, collectExtensionTagsFrom, commonDateFormatter, create, createEmptyGedcom, createGedcomUid, dateFormatter, downloadGedzipMedia, ensureExtensionSchema, extractGedzip, extractGedzipGedcom, extractSeparationYears, extractSplitPoints, familyHasChild, familyHasParent, findMatchingRangeForSplitRange, findReusableParentChildFamily, firstPointerId, formatGedcom7Timestamp, fromTuple, generateSplitRanges, getAllProp, getExtensionSchema, getFamilyWith, getFileExtension, getName, getPlaceParts, getPlaces, getRawSize, getVersion, hungarianOrdinalize, implemented, inRange, inferMediaForm, initializeCache, isDevelopment, isGedcom7, isGedcomTrailerLine, isGedcomTrailerTag, isGedzipContainer, isImageFormat, isIntersectedRange, isObjePointer, isRangeContained, isRemoteOrEmbeddedMediaUrl, makePointer, marriageDateFormatter, mergeMediaLists, nameFormatter, nextRecordId, normalizeGedcomVersion, notImplemented, noteDateFormatter, ordinalize, parseGedcom7CalendarPrefix, parseRangeBounds, pathCache, placeTranslator, pointerIds, profilePictureCache, registerExtensionTag, relativesCache, remountGedzipMediaAsDataUrls, resetRelativesCache, resolveLocalMediaUrl, resolveMediaContent, resolveObjeForm, rewriteGedcomFilePaths, setCauseOfDeath, setChildPedigree, setDeceased, setFamilyMarriage, setLocalMediaResolver, setMediaContentResolver, setNestedGroup, splitOverlappingRanges, splitRange, spouseTagFor, toGedcomPedigree, updateFactRecord, withGedcom7Calendar };
|