@treeviz/gedcom-parser 2.0.12 → 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 +4 -4
- 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 +2 -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 +39 -2
- package/dist/classes/gedcom.d.ts.map +1 -1
- package/dist/classes/index.js +1364 -318
- package/dist/classes/indi.d.ts +19 -2
- 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 +1368 -313
- package/dist/constants/constants.d.ts.map +1 -1
- package/dist/constants/index.js +312 -73
- package/dist/factories/index.js +310 -71
- package/dist/index.d.ts +10 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1547 -288
- package/dist/interfaces/common.d.ts +6 -4
- package/dist/interfaces/common.d.ts.map +1 -1
- package/dist/interfaces/fam.d.ts +3 -0
- package/dist/interfaces/fam.d.ts.map +1 -1
- package/dist/interfaces/gedcom.d.ts +21 -1
- package/dist/interfaces/gedcom.d.ts.map +1 -1
- package/dist/interfaces/indi.d.ts +11 -1
- package/dist/interfaces/indi.d.ts.map +1 -1
- package/dist/kinship-translator/index.js +310 -71
- package/dist/structures/gedcom.d.ts +1 -0
- package/dist/structures/gedcom.d.ts.map +1 -1
- package/dist/types/types.d.ts +22 -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 +12 -0
- package/dist/utils/fact-edit.d.ts.map +1 -1
- package/dist/utils/family-edit.d.ts +2 -2
- package/dist/utils/family-edit.d.ts.map +1 -1
- 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 +9 -0
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/index.js +1547 -288
- 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.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) => {
|
|
@@ -293,8 +294,8 @@ var cacheDiscoveredPath = (gedcom, path) => {
|
|
|
293
294
|
|
|
294
295
|
// src/constants/constants.ts
|
|
295
296
|
var APP_BRANDING = "TreeViz - The Family Tree Visualiser & Editor";
|
|
296
|
-
var REF_LINE_REG = /^0 (?:(@[_a-zA-Z0-9]*@) )?(?<type>_[_A-Z][_a-zA-
|
|
297
|
-
var LINE_REG = /(?<indent>^[0-9]) (?:(@[_a-zA-Z0-9]*@) )?(?<type>_[_A-Z][_a-zA-
|
|
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>.*)/;
|
|
298
299
|
var ID_REG = /^@[_a-zA-Z0-9]+@/;
|
|
299
300
|
var ID_GETTER_REG = /^(?<at>@)?(?<letter>[A-Z])?/i;
|
|
300
301
|
var ORIG_HEAD_TAG = "_ORIGHEAD";
|
|
@@ -692,11 +693,17 @@ var List = class _List {
|
|
|
692
693
|
const gedcom = [];
|
|
693
694
|
this.entries().forEach(([_, item]) => {
|
|
694
695
|
const validTag = getValidTag(tag);
|
|
695
|
-
const
|
|
696
|
-
const
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
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
|
+
}
|
|
700
707
|
gedcom.push(
|
|
701
708
|
...item.toGedcomLines(
|
|
702
709
|
validTag,
|
|
@@ -954,12 +961,14 @@ var Common = class _Common {
|
|
|
954
961
|
);
|
|
955
962
|
}
|
|
956
963
|
standardizeObject(tag, options) {
|
|
957
|
-
if (tag === "OBJE" &&
|
|
964
|
+
if (tag === "OBJE" && options?.obje?.standardize && "standardizeMedia" in this) {
|
|
958
965
|
const standardize = this.standardizeMedia;
|
|
959
966
|
return standardize.call(
|
|
960
967
|
this,
|
|
961
968
|
options.obje.namespace,
|
|
962
|
-
options.obje.override
|
|
969
|
+
options.obje.override,
|
|
970
|
+
void 0,
|
|
971
|
+
options.gedcomVersion
|
|
963
972
|
);
|
|
964
973
|
}
|
|
965
974
|
}
|
|
@@ -986,7 +995,7 @@ var Common = class _Common {
|
|
|
986
995
|
if (typeof prop?.toObject === "function") {
|
|
987
996
|
if (prop instanceof _Common) {
|
|
988
997
|
json[validKey] = prop.toObject(validKey, options);
|
|
989
|
-
} else {
|
|
998
|
+
} else if (prop instanceof List) {
|
|
990
999
|
json = {
|
|
991
1000
|
...json,
|
|
992
1001
|
...prop.toObject(validKey, options)
|
|
@@ -1044,8 +1053,12 @@ var Common = class _Common {
|
|
|
1044
1053
|
this.standardizeObject(tag, options);
|
|
1045
1054
|
const validKeys = getValidKeys(this);
|
|
1046
1055
|
const gedcom = [];
|
|
1056
|
+
const isGedcom7Export = options?.gedcomVersion === "7.0";
|
|
1047
1057
|
validKeys.forEach((key) => {
|
|
1048
1058
|
const validKey = key;
|
|
1059
|
+
if (isGedcom7Export && validKey === "CONC") {
|
|
1060
|
+
return;
|
|
1061
|
+
}
|
|
1049
1062
|
const prop = this.get(validKey);
|
|
1050
1063
|
if (typeof prop?.toGedcomLines === "function") {
|
|
1051
1064
|
if (prop instanceof _Common) {
|
|
@@ -1056,7 +1069,7 @@ var Common = class _Common {
|
|
|
1056
1069
|
gedcom.push(
|
|
1057
1070
|
...prop.toGedcomLines(validKey, level + 1, options)
|
|
1058
1071
|
);
|
|
1059
|
-
} else {
|
|
1072
|
+
} else if (prop instanceof List) {
|
|
1060
1073
|
gedcom.push(
|
|
1061
1074
|
...prop.toGedcomLines(validKey, level, options)
|
|
1062
1075
|
);
|
|
@@ -1999,6 +2012,24 @@ var setDeceased = (indi, deceased) => {
|
|
|
1999
2012
|
}
|
|
2000
2013
|
addIndividualFact(indi, { tag: "DEAT", value: "Y" });
|
|
2001
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
|
+
};
|
|
2002
2033
|
|
|
2003
2034
|
// src/utils/family-edit.ts
|
|
2004
2035
|
var PEDIGREE_VALUES = [
|
|
@@ -2246,6 +2277,81 @@ var getPlaces = (common, type = ["ALL" /* All */], maxLevel = 1, level = 0, main
|
|
|
2246
2277
|
});
|
|
2247
2278
|
return places;
|
|
2248
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
|
+
};
|
|
2249
2355
|
var implemented = (type, ...args) => {
|
|
2250
2356
|
};
|
|
2251
2357
|
var notImplemented = (type, ...args) => {
|
|
@@ -2254,11 +2360,34 @@ var notImplemented = (type, ...args) => {
|
|
|
2254
2360
|
|
|
2255
2361
|
// src/utils/media-utils.ts
|
|
2256
2362
|
var getFileExtension = (filename) => {
|
|
2257
|
-
|
|
2258
|
-
|
|
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() : "";
|
|
2259
2377
|
};
|
|
2260
2378
|
var isImageFormat = (format2) => {
|
|
2261
|
-
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
|
+
}
|
|
2262
2391
|
const imageFormats = [
|
|
2263
2392
|
"jpg",
|
|
2264
2393
|
"jpeg",
|
|
@@ -2270,7 +2399,11 @@ var isImageFormat = (format2) => {
|
|
|
2270
2399
|
"tiff",
|
|
2271
2400
|
"tif"
|
|
2272
2401
|
];
|
|
2273
|
-
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;
|
|
2274
2407
|
};
|
|
2275
2408
|
var uniqueItemsCache = /* @__PURE__ */ new WeakMap();
|
|
2276
2409
|
var setNestedGroup = (obj, key, value, uniqueCounting = true) => {
|
|
@@ -2840,6 +2973,9 @@ var Fam = class extends Common {
|
|
|
2840
2973
|
addFact(input) {
|
|
2841
2974
|
return addFamilyFact(this, input);
|
|
2842
2975
|
}
|
|
2976
|
+
addNonEvent(input) {
|
|
2977
|
+
return addNonEvent(this, input);
|
|
2978
|
+
}
|
|
2843
2979
|
toList() {
|
|
2844
2980
|
return new Families().concat(
|
|
2845
2981
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
@@ -3563,10 +3699,14 @@ var Indi = class extends Common {
|
|
|
3563
3699
|
const clone = obje?.get("_CLON._OID")?.toValue();
|
|
3564
3700
|
const mser = obje?.get("_MSER._LKID")?.toValue();
|
|
3565
3701
|
let url = obje?.get("FILE")?.toValue();
|
|
3566
|
-
const title = obje?.get("TITL")?.toValue() ?? "";
|
|
3567
|
-
const type = obje
|
|
3568
|
-
|
|
3569
|
-
|
|
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) {
|
|
3570
3710
|
return;
|
|
3571
3711
|
}
|
|
3572
3712
|
if (!namespace && !url) {
|
|
@@ -3584,13 +3724,16 @@ var Indi = class extends Common {
|
|
|
3584
3724
|
}
|
|
3585
3725
|
url = url || `https://${www}/mediaui-viewer/tree/${tree}/media/${media}`;
|
|
3586
3726
|
}
|
|
3727
|
+
if (!imgId && hasEmbeddedOrLocalFile && url) {
|
|
3728
|
+
imgId = typeof media === "string" && media || `local-${String(key).replace(/[@]/g, "")}-${getFileExtension(url) || "bin"}`;
|
|
3729
|
+
}
|
|
3587
3730
|
if (url && imgId) {
|
|
3588
|
-
const id = `${tree}-${this.id}-${imgId}`;
|
|
3731
|
+
const id = `${tree || "gedzip"}-${this.id}-${imgId}`;
|
|
3589
3732
|
list[id] = {
|
|
3590
3733
|
key,
|
|
3591
3734
|
isPrimary,
|
|
3592
3735
|
id,
|
|
3593
|
-
tree,
|
|
3736
|
+
tree: tree || "gedzip",
|
|
3594
3737
|
imgId,
|
|
3595
3738
|
person: this.id,
|
|
3596
3739
|
title,
|
|
@@ -3636,9 +3779,11 @@ var Indi = class extends Common {
|
|
|
3636
3779
|
obje.standardizeMedia();
|
|
3637
3780
|
const isPrimary = obje?.get("_PRIM")?.toValue() === "Y";
|
|
3638
3781
|
const url = obje?.get("FILE")?.toValue();
|
|
3639
|
-
const title = obje?.get("NOTE")?.toValue() ?? "";
|
|
3640
|
-
const type = obje
|
|
3641
|
-
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);
|
|
3642
3787
|
if (url && imgId) {
|
|
3643
3788
|
const id = `${tree}-${this.id}-${imgId}`;
|
|
3644
3789
|
list[id] = {
|
|
@@ -3761,10 +3906,10 @@ var Indi = class extends Common {
|
|
|
3761
3906
|
const isPrimary = obje?.get("_PRIM")?.toValue() === "Y";
|
|
3762
3907
|
const url = obje?.get("FILE")?.toValue();
|
|
3763
3908
|
const title = obje?.get("TITL")?.toValue() ?? "";
|
|
3764
|
-
const type = obje
|
|
3909
|
+
const type = resolveObjeForm(obje) ?? (url ? getFileExtension(url) : void 0) ?? "raw";
|
|
3765
3910
|
if (url) {
|
|
3766
3911
|
const urlMatch = url.match(/\/([^/]+)\?hash=/);
|
|
3767
|
-
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)}`);
|
|
3768
3913
|
const id = `geni-${geniId}-${imgId}`;
|
|
3769
3914
|
list[id] = {
|
|
3770
3915
|
isPrimary,
|
|
@@ -3801,10 +3946,10 @@ var Indi = class extends Common {
|
|
|
3801
3946
|
obje.standardizeMedia();
|
|
3802
3947
|
const isPrimary = obje?.get("_PRIM")?.toValue() === "Y";
|
|
3803
3948
|
const url = obje?.get("FILE")?.toValue();
|
|
3804
|
-
const title = obje?.get("TITL")?.toValue() ?? "";
|
|
3805
|
-
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";
|
|
3806
3951
|
if (url) {
|
|
3807
|
-
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)}`;
|
|
3808
3953
|
const id = `${treeId}-${this.id}-${imgId}`;
|
|
3809
3954
|
list[id] = {
|
|
3810
3955
|
isPrimary,
|
|
@@ -3844,7 +3989,20 @@ var Indi = class extends Common {
|
|
|
3844
3989
|
cacheKey
|
|
3845
3990
|
);
|
|
3846
3991
|
if (cached !== void 0) {
|
|
3847
|
-
|
|
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
|
+
}
|
|
3848
4006
|
}
|
|
3849
4007
|
const mediaList = await this.multimedia(namespace);
|
|
3850
4008
|
if (!mediaList) {
|
|
@@ -3856,39 +4014,40 @@ var Indi = class extends Common {
|
|
|
3856
4014
|
return void 0;
|
|
3857
4015
|
}
|
|
3858
4016
|
const mediaArray = Object.values(mediaList);
|
|
3859
|
-
const
|
|
3860
|
-
|
|
3861
|
-
|
|
3862
|
-
|
|
3863
|
-
|
|
3864
|
-
|
|
3865
|
-
|
|
3866
|
-
|
|
3867
|
-
|
|
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
|
|
3868
4027
|
};
|
|
3869
|
-
|
|
3870
|
-
|
|
3871
|
-
|
|
3872
|
-
|
|
3873
|
-
|
|
3874
|
-
this._gedcom,
|
|
3875
|
-
cacheKey,
|
|
3876
|
-
void 0
|
|
3877
|
-
);
|
|
3878
|
-
return void 0;
|
|
3879
|
-
}
|
|
3880
|
-
const secondaryMedia = mediaArray.find(
|
|
3881
|
-
(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
|
+
)
|
|
3882
4033
|
);
|
|
3883
|
-
|
|
3884
|
-
|
|
3885
|
-
|
|
3886
|
-
|
|
3887
|
-
|
|
3888
|
-
|
|
3889
|
-
|
|
3890
|
-
|
|
3891
|
-
|
|
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
|
+
}
|
|
3892
4051
|
}
|
|
3893
4052
|
profilePictureCache(
|
|
3894
4053
|
this._gedcom,
|
|
@@ -4174,9 +4333,108 @@ var Indi = class extends Common {
|
|
|
4174
4333
|
addParent(parent, pedigree) {
|
|
4175
4334
|
return parent.addChild(this, pedigree);
|
|
4176
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
|
+
}
|
|
4177
4432
|
addFact(input) {
|
|
4178
4433
|
return addIndividualFact(this, input);
|
|
4179
4434
|
}
|
|
4435
|
+
addNonEvent(input) {
|
|
4436
|
+
return addNonEvent(this, input);
|
|
4437
|
+
}
|
|
4180
4438
|
getParentType(id) {
|
|
4181
4439
|
let indi;
|
|
4182
4440
|
if (typeof id === "string" || typeof id === "number") {
|
|
@@ -4217,7 +4475,7 @@ var Indi = class extends Common {
|
|
|
4217
4475
|
if (!famChild) {
|
|
4218
4476
|
const childIndi = this._gedcom?.indi(child.id);
|
|
4219
4477
|
const childState = childIndi?.get("FAMC")?.toList()?.filter((item) => item.value === family.id).index(0);
|
|
4220
|
-
childType = childState?.get("PEDI")?.toValue() || "biological" /* BIOLOGICAL */;
|
|
4478
|
+
childType = (childState?.get("PEDI") ?? childState?.get("PEDT"))?.toValue() || "biological" /* BIOLOGICAL */;
|
|
4221
4479
|
} else {
|
|
4222
4480
|
childType = famChild.get(usedRel)?.toValue() || "biological" /* BIOLOGICAL */;
|
|
4223
4481
|
}
|
|
@@ -4778,7 +5036,7 @@ var Indi = class extends Common {
|
|
|
4778
5036
|
return;
|
|
4779
5037
|
}
|
|
4780
5038
|
const childState = child?.get("FAMC")?.toList()?.filter((item) => item.value === family.id).index(0);
|
|
4781
|
-
const childType = childState?.get("PEDI")?.toValue() || "biological" /* BIOLOGICAL */;
|
|
5039
|
+
const childType = (childState?.get("PEDI") ?? childState?.get("PEDT"))?.toValue() || "biological" /* BIOLOGICAL */;
|
|
4782
5040
|
if (childType?.toLowerCase() === filter.PEDI.toLowerCase()) {
|
|
4783
5041
|
children.append(child);
|
|
4784
5042
|
}
|
|
@@ -4886,7 +5144,7 @@ var Indi = class extends Common {
|
|
|
4886
5144
|
const child = this.id && family.CHIL?.toValueList()?.item(this.id);
|
|
4887
5145
|
if (!child) {
|
|
4888
5146
|
const childState = this?.get("FAMC")?.toList()?.filter((item) => item.value === family.id).index(0);
|
|
4889
|
-
const parentType = childState?.get("PEDI")?.toValue() || "biological" /* BIOLOGICAL */;
|
|
5147
|
+
const parentType = (childState?.get("PEDI") ?? childState?.get("PEDT"))?.toValue() || "biological" /* BIOLOGICAL */;
|
|
4890
5148
|
if (parentType?.toLowerCase() === filter.PEDI.toLowerCase()) {
|
|
4891
5149
|
parents.merge(family.getParents());
|
|
4892
5150
|
}
|
|
@@ -7287,7 +7545,11 @@ var STANDARD_QUALIFIERS = {
|
|
|
7287
7545
|
BEF: "Bef.",
|
|
7288
7546
|
BEFORE: "Bef.",
|
|
7289
7547
|
AFT: "Aft.",
|
|
7290
|
-
AFTER: "Aft."
|
|
7548
|
+
AFTER: "Aft.",
|
|
7549
|
+
CAL: "Abt.",
|
|
7550
|
+
// calculated ≈ about for display
|
|
7551
|
+
EST: "Abt."
|
|
7552
|
+
// estimated ≈ about for display
|
|
7291
7553
|
};
|
|
7292
7554
|
var EXPORT_QUALIFIERS = {
|
|
7293
7555
|
"Abt.": "ABT",
|
|
@@ -7295,6 +7557,11 @@ var EXPORT_QUALIFIERS = {
|
|
|
7295
7557
|
"Aft.": "AFT"
|
|
7296
7558
|
};
|
|
7297
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
|
+
);
|
|
7298
7565
|
var NOTE_MARKER = "####";
|
|
7299
7566
|
var formatDateWithComponents = (date, hasDay, hasMonth, hasYear, noteValue, baseFormat = "dd MMM yyyy", locale) => {
|
|
7300
7567
|
const hasNote = baseFormat.includes("NOTE");
|
|
@@ -7319,29 +7586,45 @@ var CommonDate = class extends Common {
|
|
|
7319
7586
|
super(gedcom, id, main, parent);
|
|
7320
7587
|
delete this.id;
|
|
7321
7588
|
}
|
|
7589
|
+
get calendar() {
|
|
7590
|
+
return this._calendar;
|
|
7591
|
+
}
|
|
7322
7592
|
set value(value) {
|
|
7323
7593
|
if (value) {
|
|
7324
|
-
const noteRegExp = /^(?<note>[a-zA-Z]+\.)/;
|
|
7325
|
-
const noteMatch = value.match(noteRegExp)?.groups;
|
|
7326
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;
|
|
7327
7604
|
if (noteMatch?.note) {
|
|
7328
7605
|
this.NOTE = this.NOTE || createCommon(this._gedcom, void 0, this.main);
|
|
7329
7606
|
this.NOTE.value = noteMatch?.note;
|
|
7330
|
-
validValue =
|
|
7607
|
+
validValue = validValue.replace(noteRegExp, "");
|
|
7331
7608
|
} else {
|
|
7332
|
-
const qualifierMatch =
|
|
7333
|
-
/^(?<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
|
|
7334
7611
|
);
|
|
7335
7612
|
const qualifier = qualifierMatch?.groups?.qualifier?.toUpperCase();
|
|
7336
7613
|
const note = qualifier ? STANDARD_QUALIFIERS[qualifier] : void 0;
|
|
7337
7614
|
if (note) {
|
|
7338
7615
|
this.NOTE = this.NOTE || createCommon(this._gedcom, void 0, this.main);
|
|
7339
7616
|
this.NOTE.value = note;
|
|
7340
|
-
validValue =
|
|
7617
|
+
validValue = validValue.slice(qualifierMatch[0].length);
|
|
7341
7618
|
}
|
|
7342
7619
|
}
|
|
7343
7620
|
const acceptedDate = this.isValidDateFormat(validValue);
|
|
7344
|
-
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) {
|
|
7345
7628
|
this.DAY = this.DAY || createCommon(this._gedcom, void 0, this.main);
|
|
7346
7629
|
this.DAY.value = format(acceptedDate, "dd");
|
|
7347
7630
|
this.MONTH = this.MONTH || createCommon(this._gedcom, void 0, this.main);
|
|
@@ -7444,6 +7727,15 @@ var CommonDate = class extends Common {
|
|
|
7444
7727
|
);
|
|
7445
7728
|
}
|
|
7446
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
|
+
}
|
|
7447
7739
|
const formatted = this.toValue("NOTE dd MMM yyyy", null);
|
|
7448
7740
|
if (!formatted) {
|
|
7449
7741
|
return formatted;
|
|
@@ -7451,10 +7743,14 @@ var CommonDate = class extends Common {
|
|
|
7451
7743
|
const note = this.NOTE?.value?.trim();
|
|
7452
7744
|
const qualifier = note ? EXPORT_QUALIFIERS[note] : void 0;
|
|
7453
7745
|
const standardized = qualifier ? formatted.replace(note, qualifier) : formatted;
|
|
7454
|
-
|
|
7746
|
+
const withMonths = standardized.replace(
|
|
7455
7747
|
GEDCOM_MONTHS,
|
|
7456
7748
|
(month) => month.toUpperCase()
|
|
7457
7749
|
);
|
|
7750
|
+
if (this._calendar && this._calendar !== "GREGORIAN") {
|
|
7751
|
+
return `${this._calendar} ${withMonths}`;
|
|
7752
|
+
}
|
|
7753
|
+
return withMonths;
|
|
7458
7754
|
}
|
|
7459
7755
|
toGedcomLines(tag, level = 0, options) {
|
|
7460
7756
|
const internal = new RegExp(
|
|
@@ -7475,70 +7771,965 @@ var isCommonDate = (value) => {
|
|
|
7475
7771
|
return !!value && value !== null && typeof value === "object" && "_date" in value;
|
|
7476
7772
|
};
|
|
7477
7773
|
|
|
7478
|
-
//
|
|
7479
|
-
var
|
|
7480
|
-
|
|
7481
|
-
|
|
7482
|
-
|
|
7483
|
-
|
|
7484
|
-
|
|
7485
|
-
|
|
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;
|
|
7815
|
+
}
|
|
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
|
+
});
|
|
7843
|
+
}
|
|
7844
|
+
}
|
|
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;
|
|
7920
|
+
}
|
|
7921
|
+
if (path.toLowerCase().endsWith(".ged")) {
|
|
7922
|
+
continue;
|
|
7923
|
+
}
|
|
7924
|
+
mediaEntries.push({
|
|
7925
|
+
path,
|
|
7926
|
+
content: await entry.async("uint8array")
|
|
7927
|
+
});
|
|
7928
|
+
}
|
|
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) {
|
|
7963
|
+
return;
|
|
7964
|
+
}
|
|
7965
|
+
downloaded.push({
|
|
7966
|
+
...item,
|
|
7967
|
+
content: resolved.content,
|
|
7968
|
+
contentType: resolved.contentType || item.contentType
|
|
7969
|
+
});
|
|
7970
|
+
} catch {
|
|
7971
|
+
} finally {
|
|
7972
|
+
done += 1;
|
|
7973
|
+
onProgress?.(done, total);
|
|
7974
|
+
}
|
|
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 });
|
|
7486
7982
|
};
|
|
7487
|
-
var getVersion = () => package_default.version;
|
|
7488
|
-
var getName = () => package_default.name;
|
|
7489
7983
|
|
|
7490
|
-
// src/
|
|
7491
|
-
var
|
|
7492
|
-
|
|
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
|
+
};
|
|
7493
8039
|
};
|
|
7494
|
-
var
|
|
7495
|
-
|
|
7496
|
-
|
|
7497
|
-
|
|
7498
|
-
this.reflist = {};
|
|
7499
|
-
this.refcount = 0;
|
|
7500
|
-
delete this._gedcom;
|
|
7501
|
-
delete this.id;
|
|
7502
|
-
this.removeValue();
|
|
8040
|
+
var normalizeEnum = (node, allowed, mode, restores) => {
|
|
8041
|
+
const value = node?.toValue();
|
|
8042
|
+
if (!node || typeof value !== "string" || !value.trim()) {
|
|
8043
|
+
return;
|
|
7503
8044
|
}
|
|
7504
|
-
|
|
7505
|
-
|
|
7506
|
-
if (
|
|
7507
|
-
|
|
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
|
+
});
|
|
7508
8053
|
}
|
|
7509
|
-
|
|
7510
|
-
|
|
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
|
+
);
|
|
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]?.();
|
|
7511
8096
|
}
|
|
7512
|
-
|
|
7513
|
-
|
|
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 };
|
|
7514
8112
|
}
|
|
7515
|
-
|
|
7516
|
-
|
|
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;
|
|
7517
8121
|
}
|
|
7518
|
-
|
|
7519
|
-
|
|
7520
|
-
|
|
8122
|
+
const upper = calendar.toUpperCase();
|
|
8123
|
+
if (GEDCOM7_CALENDARS.includes(upper)) {
|
|
8124
|
+
const { rest } = parseGedcom7CalendarPrefix(value);
|
|
8125
|
+
return `${upper} ${rest}`.trim();
|
|
8126
|
+
}
|
|
8127
|
+
return value;
|
|
8128
|
+
};
|
|
8129
|
+
var applyGedcom7DatePhrases = (gedcom) => {
|
|
8130
|
+
const restores = [];
|
|
8131
|
+
const visitDate = (dateNode) => {
|
|
8132
|
+
if (!dateNode || typeof dateNode.toValue !== "function") {
|
|
8133
|
+
return;
|
|
7521
8134
|
}
|
|
7522
|
-
const
|
|
7523
|
-
|
|
7524
|
-
|
|
7525
|
-
|
|
7526
|
-
|
|
7527
|
-
|
|
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
|
+
});
|
|
7528
8152
|
}
|
|
7529
|
-
}
|
|
7530
|
-
return
|
|
8153
|
+
}
|
|
8154
|
+
return;
|
|
7531
8155
|
}
|
|
7532
|
-
|
|
7533
|
-
|
|
7534
|
-
|
|
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);
|
|
7535
8170
|
}
|
|
7536
|
-
|
|
7537
|
-
|
|
7538
|
-
|
|
7539
|
-
|
|
7540
|
-
|
|
7541
|
-
|
|
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") {
|
|
7542
8733
|
if (value === null || value === void 0 || Array.isArray(value) || isObjectPatch(value)) {
|
|
7543
8734
|
return;
|
|
7544
8735
|
}
|
|
@@ -7705,6 +8896,9 @@ var GedCom = class extends Common {
|
|
|
7705
8896
|
const id = this.nextIndiKey();
|
|
7706
8897
|
const indi = createIndi(this, id);
|
|
7707
8898
|
indi.type = "INDI";
|
|
8899
|
+
if (this.getGedcomVersion() === "7.0") {
|
|
8900
|
+
indi.set("UID", createGedcomUid());
|
|
8901
|
+
}
|
|
7708
8902
|
indis.item(id, indi);
|
|
7709
8903
|
return indi;
|
|
7710
8904
|
}
|
|
@@ -7717,9 +8911,151 @@ var GedCom = class extends Common {
|
|
|
7717
8911
|
const id = this.nextFamKey();
|
|
7718
8912
|
const fam = createFam(this, id);
|
|
7719
8913
|
fam.type = "FAM";
|
|
8914
|
+
if (this.getGedcomVersion() === "7.0") {
|
|
8915
|
+
fam.set("UID", createGedcomUid());
|
|
8916
|
+
}
|
|
7720
8917
|
fams.item(id, fam);
|
|
7721
8918
|
return fam;
|
|
7722
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
|
+
}
|
|
7723
9059
|
objes() {
|
|
7724
9060
|
return this.getList("@@OBJE");
|
|
7725
9061
|
}
|
|
@@ -7804,9 +9140,52 @@ var GedCom = class extends Common {
|
|
|
7804
9140
|
});
|
|
7805
9141
|
return lists;
|
|
7806
9142
|
}
|
|
7807
|
-
|
|
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) {
|
|
7808
9183
|
const newHead = createCommon();
|
|
7809
9184
|
Object.assign(newHead, this.get("HEAD") ?? {});
|
|
9185
|
+
this.applyGedcomSpecToHead(
|
|
9186
|
+
newHead,
|
|
9187
|
+
gedcomVersion ?? this.getGedcomVersion()
|
|
9188
|
+
);
|
|
7810
9189
|
const existingSour = this.get("HEAD")?.get("SOUR");
|
|
7811
9190
|
const existingTreeName = existingSour?.get("_TREE")?.toValue();
|
|
7812
9191
|
const existingTreeUniqueId = existingSour?.get("_TID")?.toValue();
|
|
@@ -7853,22 +9232,45 @@ var GedCom = class extends Common {
|
|
|
7853
9232
|
}
|
|
7854
9233
|
toGedcom(tag, level, options) {
|
|
7855
9234
|
if (options?.super) {
|
|
7856
|
-
return appendGedcomTrailer(
|
|
7857
|
-
super.toGedcom(tag, level, options)
|
|
7858
|
-
);
|
|
9235
|
+
return appendGedcomTrailer(super.toGedcom(tag, level, options));
|
|
7859
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
|
+
};
|
|
7860
9247
|
const newGedcom = createGedCom();
|
|
7861
9248
|
Object.assign(newGedcom, this);
|
|
7862
|
-
if (!
|
|
9249
|
+
if (!exportOptions.original) {
|
|
7863
9250
|
Object.assign(newGedcom, {
|
|
7864
|
-
HEAD: this.getDownloadHeader()
|
|
9251
|
+
HEAD: this.getDownloadHeader(exportVersion)
|
|
7865
9252
|
});
|
|
7866
9253
|
}
|
|
7867
|
-
if (
|
|
7868
|
-
const newContent = this.getIndiRelatedLists(
|
|
9254
|
+
if (exportOptions.indis?.length) {
|
|
9255
|
+
const newContent = this.getIndiRelatedLists(exportOptions.indis);
|
|
7869
9256
|
Object.assign(newGedcom, newContent);
|
|
7870
9257
|
}
|
|
7871
|
-
|
|
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
|
+
}
|
|
7872
9274
|
}
|
|
7873
9275
|
hasTag(tag) {
|
|
7874
9276
|
const tagName = typeof tag === "string" ? tag : tag?.get("NAME")?.toValue();
|
|
@@ -8084,144 +9486,6 @@ var createGedCom = () => {
|
|
|
8084
9486
|
return new GedCom();
|
|
8085
9487
|
};
|
|
8086
9488
|
|
|
8087
|
-
// src/classes/note.ts
|
|
8088
|
-
var CommonNote = class extends Common {
|
|
8089
|
-
constructor(gedcom, id, main, parent) {
|
|
8090
|
-
super(gedcom, id, main, parent);
|
|
8091
|
-
delete this.id;
|
|
8092
|
-
}
|
|
8093
|
-
set value(value) {
|
|
8094
|
-
const [note, ...contents] = value?.split(/\r?\n/) ?? [];
|
|
8095
|
-
this._value = note;
|
|
8096
|
-
if (contents.length) {
|
|
8097
|
-
const newContents = new List();
|
|
8098
|
-
contents.forEach((c, i) => {
|
|
8099
|
-
const newContent = createCommon(
|
|
8100
|
-
this._gedcom,
|
|
8101
|
-
void 0,
|
|
8102
|
-
this.main
|
|
8103
|
-
);
|
|
8104
|
-
newContent.id = `@U${i}@`;
|
|
8105
|
-
newContent.value = c;
|
|
8106
|
-
newContents.append(newContent);
|
|
8107
|
-
});
|
|
8108
|
-
const firstItem = newContents.index(0);
|
|
8109
|
-
if (firstItem) {
|
|
8110
|
-
if (newContents.length === 1) {
|
|
8111
|
-
this.set("CONT", firstItem);
|
|
8112
|
-
} else {
|
|
8113
|
-
this.set("CONT", newContents);
|
|
8114
|
-
}
|
|
8115
|
-
}
|
|
8116
|
-
}
|
|
8117
|
-
}
|
|
8118
|
-
get value() {
|
|
8119
|
-
const contents = this.get("CONT")?.toList().map((content) => content.value).join("\n");
|
|
8120
|
-
if (contents) {
|
|
8121
|
-
return `${this._value}
|
|
8122
|
-
${contents}`;
|
|
8123
|
-
}
|
|
8124
|
-
return this._value;
|
|
8125
|
-
}
|
|
8126
|
-
exportValue() {
|
|
8127
|
-
return this._value;
|
|
8128
|
-
}
|
|
8129
|
-
};
|
|
8130
|
-
var createCommonNote = (gedcom, id, main, parent) => {
|
|
8131
|
-
return createProxy(
|
|
8132
|
-
new CommonNote(gedcom, id, main, parent)
|
|
8133
|
-
);
|
|
8134
|
-
};
|
|
8135
|
-
|
|
8136
|
-
// src/classes/obje.ts
|
|
8137
|
-
var Obje = class extends Common {
|
|
8138
|
-
standardizeMedia(namespace, override = true, urlGetter) {
|
|
8139
|
-
if (!this._gedcom) {
|
|
8140
|
-
return this;
|
|
8141
|
-
}
|
|
8142
|
-
const rin = this?.get("RIN")?.toValue();
|
|
8143
|
-
const clone = this?.get("_CLON._OID")?.toValue();
|
|
8144
|
-
const mser = this?.get("_MSER._LKID")?.toValue();
|
|
8145
|
-
const title = this?.get("FILE.TITL")?.toValue() ?? this?.get("TITL")?.toValue() ?? "";
|
|
8146
|
-
const note = this?.get("FILE.NOTE")?.toValue() ?? this?.get("NOTE")?.toValue() ?? "";
|
|
8147
|
-
const form = this?.get("FILE.FORM")?.toValue();
|
|
8148
|
-
const file = this?.get("FILE")?.toValue();
|
|
8149
|
-
const imgId = rin || clone || mser;
|
|
8150
|
-
const url = file || namespace && urlGetter?.(namespace, imgId);
|
|
8151
|
-
if (!url) {
|
|
8152
|
-
return this;
|
|
8153
|
-
}
|
|
8154
|
-
const newObject = createObje(this._gedcom, this.id, this.main);
|
|
8155
|
-
if (!override) {
|
|
8156
|
-
Object.assign(newObject, this);
|
|
8157
|
-
}
|
|
8158
|
-
if (form) {
|
|
8159
|
-
if (typeof form === "string") {
|
|
8160
|
-
const newForm = createCommon(
|
|
8161
|
-
this._gedcom,
|
|
8162
|
-
void 0,
|
|
8163
|
-
this.main
|
|
8164
|
-
);
|
|
8165
|
-
newForm.value = form;
|
|
8166
|
-
newObject.set("FORM", newForm);
|
|
8167
|
-
} else {
|
|
8168
|
-
newObject.set("FORM", form);
|
|
8169
|
-
}
|
|
8170
|
-
}
|
|
8171
|
-
if (title) {
|
|
8172
|
-
if (typeof title === "string") {
|
|
8173
|
-
const newTitle = createCommon(
|
|
8174
|
-
this._gedcom,
|
|
8175
|
-
void 0,
|
|
8176
|
-
this.main
|
|
8177
|
-
);
|
|
8178
|
-
newTitle.value = title;
|
|
8179
|
-
newObject.set("TITL", newTitle);
|
|
8180
|
-
if (!note) {
|
|
8181
|
-
newObject.set("NOTE", newTitle);
|
|
8182
|
-
}
|
|
8183
|
-
} else {
|
|
8184
|
-
newObject.set("TITL", title);
|
|
8185
|
-
if (!note) {
|
|
8186
|
-
newObject.set("NOTE", title);
|
|
8187
|
-
}
|
|
8188
|
-
}
|
|
8189
|
-
}
|
|
8190
|
-
if (note) {
|
|
8191
|
-
if (typeof note === "string") {
|
|
8192
|
-
const newNote = createCommon(
|
|
8193
|
-
this._gedcom,
|
|
8194
|
-
void 0,
|
|
8195
|
-
this.main
|
|
8196
|
-
);
|
|
8197
|
-
newNote.value = note;
|
|
8198
|
-
newObject.set("NOTE", newNote);
|
|
8199
|
-
if (!title) {
|
|
8200
|
-
newObject.set("TITL", newNote);
|
|
8201
|
-
}
|
|
8202
|
-
} else {
|
|
8203
|
-
newObject.set("NOTE", note);
|
|
8204
|
-
if (!title) {
|
|
8205
|
-
newObject.set("TITL", note);
|
|
8206
|
-
}
|
|
8207
|
-
}
|
|
8208
|
-
}
|
|
8209
|
-
const newUrl = createCommon(this._gedcom, void 0, this.main);
|
|
8210
|
-
newUrl.value = url;
|
|
8211
|
-
newObject.set("FILE", newUrl);
|
|
8212
|
-
if (override) {
|
|
8213
|
-
Object.assign(this, newObject);
|
|
8214
|
-
return this;
|
|
8215
|
-
}
|
|
8216
|
-
return newObject;
|
|
8217
|
-
}
|
|
8218
|
-
};
|
|
8219
|
-
var createObje = (gedcom, id, main, parent) => {
|
|
8220
|
-
return createProxy(
|
|
8221
|
-
new Obje(gedcom, id, main, parent)
|
|
8222
|
-
);
|
|
8223
|
-
};
|
|
8224
|
-
|
|
8225
9489
|
// src/classes/repo.ts
|
|
8226
9490
|
var Repo = class extends Common {
|
|
8227
9491
|
};
|
|
@@ -8270,6 +9534,8 @@ var create = (gedcom, type, id, nodes) => {
|
|
|
8270
9534
|
prevNode = createIndi(gedcom, id);
|
|
8271
9535
|
} else if (convertType === "FAM") {
|
|
8272
9536
|
prevNode = createFam(gedcom, id);
|
|
9537
|
+
} else if (convertType === "SNOTE" || convertType === "NOTE") {
|
|
9538
|
+
prevNode = createCommonNote(gedcom, id);
|
|
8273
9539
|
} else {
|
|
8274
9540
|
prevNode = createCommon(gedcom, id);
|
|
8275
9541
|
}
|
|
@@ -8285,7 +9551,7 @@ var create = (gedcom, type, id, nodes) => {
|
|
|
8285
9551
|
prevNode = createObje(gedcom, void 0, mainNode, curNode);
|
|
8286
9552
|
} else if (type === "DATE") {
|
|
8287
9553
|
prevNode = createCommonDate(gedcom, void 0, mainNode, curNode);
|
|
8288
|
-
} else if (type === "NOTE") {
|
|
9554
|
+
} else if (type === "NOTE" || type === "SNOTE") {
|
|
8289
9555
|
prevNode = createCommonNote(gedcom, void 0, mainNode, curNode);
|
|
8290
9556
|
} else if (type === "NAME" && mainNode instanceof Indi) {
|
|
8291
9557
|
prevNode = createCommonName(gedcom, void 0, mainNode, curNode);
|
|
@@ -8302,20 +9568,6 @@ var getRawSize = (raw) => {
|
|
|
8302
9568
|
return `${raw || ""}`?.length ?? 0;
|
|
8303
9569
|
};
|
|
8304
9570
|
|
|
8305
|
-
// src/classes/objes.ts
|
|
8306
|
-
var Objects = class _Objects extends List {
|
|
8307
|
-
copy() {
|
|
8308
|
-
const newList = new _Objects();
|
|
8309
|
-
this.entries().forEach(([key, value]) => {
|
|
8310
|
-
newList.item(key, value);
|
|
8311
|
-
});
|
|
8312
|
-
return newList;
|
|
8313
|
-
}
|
|
8314
|
-
except(item) {
|
|
8315
|
-
return this.copy().delete(item);
|
|
8316
|
-
}
|
|
8317
|
-
};
|
|
8318
|
-
|
|
8319
9571
|
// src/classes/repos.ts
|
|
8320
9572
|
var Repositories = class _Repositories extends List {
|
|
8321
9573
|
copy() {
|
|
@@ -8424,6 +9676,13 @@ var GedcomTree = {
|
|
|
8424
9676
|
if (linesAcc._inHead && lineIndent === 1 && lineType === "FILE") {
|
|
8425
9677
|
linesAcc._hasFile = true;
|
|
8426
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
|
+
}
|
|
8427
9686
|
if (lineIndent > 0 && lineIndent > prevLineIndent && lineValue && isId(lineValue)) {
|
|
8428
9687
|
const refLines = lineValue.split(/,\s*/).map((id) => line.replace(lineValue, id));
|
|
8429
9688
|
if (refLines.length > 1) {
|
|
@@ -8622,4 +9881,4 @@ var createEmptyGedcom = (options) => {
|
|
|
8622
9881
|
return gedcom;
|
|
8623
9882
|
};
|
|
8624
9883
|
|
|
8625
|
-
export { ACCEPTED_DATE_FORMATS, ACCEPTED_DATE_FORMATS_REGEX, GEDCOM_TRAILER_TAG, parser_default as GedcomTree, PEDIGREE_VALUES, PlaceType, addFamilyFact, addIndividualFact, appendGedcomTrailer, attachChildToFamily, attachSpouseToFamily, cacheDiscoveredPath, canAttachAsSpouse, commonDateFormatter, create, createEmptyGedcom, dateFormatter, extractSeparationYears, extractSplitPoints, familyHasChild, familyHasParent, findMatchingRangeForSplitRange, findReusableParentChildFamily, firstPointerId, fromTuple, generateSplitRanges, getAllProp, getFamilyWith, getFileExtension, getName, getPlaceParts, getPlaces, getRawSize, getVersion, hungarianOrdinalize, implemented, inRange, initializeCache, isDevelopment, isGedcomTrailerLine, isGedcomTrailerTag, isImageFormat, isIntersectedRange, isRangeContained, makePointer, marriageDateFormatter, nameFormatter, nextRecordId, notImplemented, noteDateFormatter, ordinalize, parseRangeBounds, pathCache, placeTranslator, pointerIds, profilePictureCache, relativesCache, resetRelativesCache, setCauseOfDeath, setChildPedigree, setDeceased, setFamilyMarriage, setNestedGroup, splitOverlappingRanges, splitRange, spouseTagFor, toGedcomPedigree, updateFactRecord };
|
|
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 };
|