@treeviz/gedcom-parser 2.0.12 → 2.1.1
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/cli/index.js
CHANGED
|
@@ -5,6 +5,7 @@ import { fileURLToPath } from 'url';
|
|
|
5
5
|
import { Command } from 'commander';
|
|
6
6
|
import { debounce, set, get, uniqBy, unset, difference, intersectionBy, differenceBy } from 'lodash-es';
|
|
7
7
|
import { format, isValid, parse } from 'date-fns';
|
|
8
|
+
import JSZip from 'jszip';
|
|
8
9
|
import chalk from 'chalk';
|
|
9
10
|
import * as readline from 'readline';
|
|
10
11
|
|
|
@@ -16,8 +17,8 @@ var __export = (target, all) => {
|
|
|
16
17
|
|
|
17
18
|
// src/constants/constants.ts
|
|
18
19
|
var APP_BRANDING = "TreeViz - The Family Tree Visualiser & Editor";
|
|
19
|
-
var REF_LINE_REG = /^0 (?:(@[_a-zA-Z0-9]*@) )?(?<type>_[_A-Z][_a-zA-
|
|
20
|
-
var LINE_REG = /(?<indent>^[0-9]) (?:(@[_a-zA-Z0-9]*@) )?(?<type>_[_A-Z][_a-zA-
|
|
20
|
+
var REF_LINE_REG = /^0 (?:(@[_a-zA-Z0-9]*@) )?(?<type>_[_A-Z][_a-zA-Z0-9]{2,}|_?[A-Z][A-Za-z0-9]{2,}) ?(?<value>.*)/gm;
|
|
21
|
+
var LINE_REG = /(?<indent>^[0-9]{1,2}) (?:(@[_a-zA-Z0-9]*@) )?(?<type>_[_A-Z][_a-zA-Z0-9]{2,}|_?[A-Z][A-Za-z0-9]{2,}) ?(?<value>.*)/;
|
|
21
22
|
var ID_REG = /^@[_a-zA-Z0-9]+@/;
|
|
22
23
|
var ID_GETTER_REG = /^(?<at>@)?(?<letter>[A-Z])?/i;
|
|
23
24
|
var ORIG_HEAD_TAG = "_ORIGHEAD";
|
|
@@ -415,11 +416,17 @@ var List = class _List {
|
|
|
415
416
|
const gedcom = [];
|
|
416
417
|
this.entries().forEach(([_, item]) => {
|
|
417
418
|
const validTag = getValidTag(tag);
|
|
418
|
-
const
|
|
419
|
-
const
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
419
|
+
const xref = item.id;
|
|
420
|
+
const payload = item.exportValue?.();
|
|
421
|
+
if (xref) {
|
|
422
|
+
gedcom.push(
|
|
423
|
+
`${level} ${xref} ${validTag}${payload ? ` ${payload}` : ""}`
|
|
424
|
+
);
|
|
425
|
+
} else {
|
|
426
|
+
gedcom.push(
|
|
427
|
+
`${level} ${validTag}${payload ? ` ${payload}` : ""}`
|
|
428
|
+
);
|
|
429
|
+
}
|
|
423
430
|
gedcom.push(
|
|
424
431
|
...item.toGedcomLines(
|
|
425
432
|
validTag,
|
|
@@ -677,12 +684,14 @@ var Common = class _Common {
|
|
|
677
684
|
);
|
|
678
685
|
}
|
|
679
686
|
standardizeObject(tag, options) {
|
|
680
|
-
if (tag === "OBJE" &&
|
|
687
|
+
if (tag === "OBJE" && options?.obje?.standardize && "standardizeMedia" in this) {
|
|
681
688
|
const standardize = this.standardizeMedia;
|
|
682
689
|
return standardize.call(
|
|
683
690
|
this,
|
|
684
691
|
options.obje.namespace,
|
|
685
|
-
options.obje.override
|
|
692
|
+
options.obje.override,
|
|
693
|
+
void 0,
|
|
694
|
+
options.gedcomVersion
|
|
686
695
|
);
|
|
687
696
|
}
|
|
688
697
|
}
|
|
@@ -709,7 +718,7 @@ var Common = class _Common {
|
|
|
709
718
|
if (typeof prop?.toObject === "function") {
|
|
710
719
|
if (prop instanceof _Common) {
|
|
711
720
|
json[validKey] = prop.toObject(validKey, options);
|
|
712
|
-
} else {
|
|
721
|
+
} else if (prop instanceof List) {
|
|
713
722
|
json = {
|
|
714
723
|
...json,
|
|
715
724
|
...prop.toObject(validKey, options)
|
|
@@ -767,8 +776,12 @@ var Common = class _Common {
|
|
|
767
776
|
this.standardizeObject(tag, options);
|
|
768
777
|
const validKeys = getValidKeys(this);
|
|
769
778
|
const gedcom = [];
|
|
779
|
+
const isGedcom7Export = options?.gedcomVersion === "7.0";
|
|
770
780
|
validKeys.forEach((key) => {
|
|
771
781
|
const validKey = key;
|
|
782
|
+
if (isGedcom7Export && validKey === "CONC") {
|
|
783
|
+
return;
|
|
784
|
+
}
|
|
772
785
|
const prop = this.get(validKey);
|
|
773
786
|
if (typeof prop?.toGedcomLines === "function") {
|
|
774
787
|
if (prop instanceof _Common) {
|
|
@@ -779,7 +792,7 @@ var Common = class _Common {
|
|
|
779
792
|
gedcom.push(
|
|
780
793
|
...prop.toGedcomLines(validKey, level + 1, options)
|
|
781
794
|
);
|
|
782
|
-
} else {
|
|
795
|
+
} else if (prop instanceof List) {
|
|
783
796
|
gedcom.push(
|
|
784
797
|
...prop.toGedcomLines(validKey, level, options)
|
|
785
798
|
);
|
|
@@ -2054,16 +2067,58 @@ var getPlaces = (common, type = ["ALL" /* All */], maxLevel = 1, level = 0, main
|
|
|
2054
2067
|
});
|
|
2055
2068
|
return places;
|
|
2056
2069
|
};
|
|
2070
|
+
|
|
2071
|
+
// src/utils/local-media.ts
|
|
2072
|
+
var localMediaResolver;
|
|
2073
|
+
var isRemoteOrEmbeddedMediaUrl = (path) => {
|
|
2074
|
+
if (!path) {
|
|
2075
|
+
return false;
|
|
2076
|
+
}
|
|
2077
|
+
return path.startsWith("data:") || path.startsWith("blob:") || /^https?:\/\//i.test(path);
|
|
2078
|
+
};
|
|
2079
|
+
var resolveLocalMediaUrl = async (path) => {
|
|
2080
|
+
if (!path) {
|
|
2081
|
+
return void 0;
|
|
2082
|
+
}
|
|
2083
|
+
if (isRemoteOrEmbeddedMediaUrl(path)) {
|
|
2084
|
+
return path;
|
|
2085
|
+
}
|
|
2086
|
+
const resolved = await localMediaResolver?.(path);
|
|
2087
|
+
return resolved;
|
|
2088
|
+
};
|
|
2057
2089
|
var implemented = (type, ...args) => {
|
|
2058
2090
|
};
|
|
2059
2091
|
|
|
2060
2092
|
// src/utils/media-utils.ts
|
|
2061
2093
|
var getFileExtension = (filename) => {
|
|
2062
|
-
|
|
2063
|
-
|
|
2094
|
+
if (!filename) {
|
|
2095
|
+
return "";
|
|
2096
|
+
}
|
|
2097
|
+
if (filename.startsWith("data:")) {
|
|
2098
|
+
const mime = filename.slice(5).split(";")[0] || "";
|
|
2099
|
+
const subtype = (mime.split("/")[1] || "").toLowerCase();
|
|
2100
|
+
if (subtype === "jpeg") {
|
|
2101
|
+
return "jpg";
|
|
2102
|
+
}
|
|
2103
|
+
return subtype.split("+")[0] || "";
|
|
2104
|
+
}
|
|
2105
|
+
const withoutQuery = filename.split(/[?#]/)[0] || filename;
|
|
2106
|
+
const match = withoutQuery.match(/\.([^.]+)$/);
|
|
2107
|
+
return match ? match[1].toLowerCase() : "";
|
|
2064
2108
|
};
|
|
2065
2109
|
var isImageFormat = (format2) => {
|
|
2066
|
-
if (!format2)
|
|
2110
|
+
if (!format2) {
|
|
2111
|
+
return false;
|
|
2112
|
+
}
|
|
2113
|
+
let normalized = format2.toLowerCase().trim();
|
|
2114
|
+
if (normalized.startsWith("data:")) {
|
|
2115
|
+
normalized = getFileExtension(normalized);
|
|
2116
|
+
} else if (normalized.includes("/")) {
|
|
2117
|
+
normalized = normalized.split("/")[1]?.split("+")[0] || "";
|
|
2118
|
+
if (normalized === "jpeg") {
|
|
2119
|
+
normalized = "jpg";
|
|
2120
|
+
}
|
|
2121
|
+
}
|
|
2067
2122
|
const imageFormats = [
|
|
2068
2123
|
"jpg",
|
|
2069
2124
|
"jpeg",
|
|
@@ -2075,7 +2130,11 @@ var isImageFormat = (format2) => {
|
|
|
2075
2130
|
"tiff",
|
|
2076
2131
|
"tif"
|
|
2077
2132
|
];
|
|
2078
|
-
return imageFormats.includes(
|
|
2133
|
+
return imageFormats.includes(normalized);
|
|
2134
|
+
};
|
|
2135
|
+
var resolveObjeForm = (obje) => {
|
|
2136
|
+
const value = obje?.get?.("FILE.FORM")?.toValue?.() ?? obje?.get?.("FORM")?.toValue?.();
|
|
2137
|
+
return typeof value === "string" && value.trim() ? value.trim() : void 0;
|
|
2079
2138
|
};
|
|
2080
2139
|
var uniqueItemsCache = /* @__PURE__ */ new WeakMap();
|
|
2081
2140
|
var setNestedGroup = (obj, key, value, uniqueCounting = true) => {
|
|
@@ -3265,10 +3324,14 @@ var Indi = class extends Common {
|
|
|
3265
3324
|
const clone = obje?.get("_CLON._OID")?.toValue();
|
|
3266
3325
|
const mser = obje?.get("_MSER._LKID")?.toValue();
|
|
3267
3326
|
let url = obje?.get("FILE")?.toValue();
|
|
3268
|
-
const title = obje?.get("TITL")?.toValue() ?? "";
|
|
3269
|
-
const type = obje
|
|
3270
|
-
|
|
3271
|
-
|
|
3327
|
+
const title = obje?.get("FILE.TITL")?.toValue() ?? obje?.get("TITL")?.toValue() ?? "";
|
|
3328
|
+
const type = resolveObjeForm(obje) ?? (url ? getFileExtension(url) : void 0) ?? "raw";
|
|
3329
|
+
let imgId = clone || mser;
|
|
3330
|
+
const hasEmbeddedOrLocalFile = !!url && (url.startsWith("data:") || url.startsWith("blob:") || !/^https?:\/\//i.test(url));
|
|
3331
|
+
if (!hasEmbeddedOrLocalFile && (!www || !tree || !this.id)) {
|
|
3332
|
+
return;
|
|
3333
|
+
}
|
|
3334
|
+
if (!this.id) {
|
|
3272
3335
|
return;
|
|
3273
3336
|
}
|
|
3274
3337
|
if (!namespace && !url) {
|
|
@@ -3286,13 +3349,16 @@ var Indi = class extends Common {
|
|
|
3286
3349
|
}
|
|
3287
3350
|
url = url || `https://${www}/mediaui-viewer/tree/${tree}/media/${media}`;
|
|
3288
3351
|
}
|
|
3352
|
+
if (!imgId && hasEmbeddedOrLocalFile && url) {
|
|
3353
|
+
imgId = typeof media === "string" && media || `local-${String(key).replace(/[@]/g, "")}-${getFileExtension(url) || "bin"}`;
|
|
3354
|
+
}
|
|
3289
3355
|
if (url && imgId) {
|
|
3290
|
-
const id = `${tree}-${this.id}-${imgId}`;
|
|
3356
|
+
const id = `${tree || "gedzip"}-${this.id}-${imgId}`;
|
|
3291
3357
|
list[id] = {
|
|
3292
3358
|
key,
|
|
3293
3359
|
isPrimary,
|
|
3294
3360
|
id,
|
|
3295
|
-
tree,
|
|
3361
|
+
tree: tree || "gedzip",
|
|
3296
3362
|
imgId,
|
|
3297
3363
|
person: this.id,
|
|
3298
3364
|
title,
|
|
@@ -3338,9 +3404,11 @@ var Indi = class extends Common {
|
|
|
3338
3404
|
obje.standardizeMedia();
|
|
3339
3405
|
const isPrimary = obje?.get("_PRIM")?.toValue() === "Y";
|
|
3340
3406
|
const url = obje?.get("FILE")?.toValue();
|
|
3341
|
-
const title = obje?.get("NOTE")?.toValue() ?? "";
|
|
3342
|
-
const type = obje
|
|
3343
|
-
const
|
|
3407
|
+
const title = obje?.get("FILE.NOTE")?.toValue() ?? obje?.get("NOTE")?.toValue() ?? "";
|
|
3408
|
+
const type = resolveObjeForm(obje) ?? (url ? getFileExtension(url) : void 0) ?? "raw";
|
|
3409
|
+
const photoRin = obje?.get("_PHOTO_RIN")?.toValue();
|
|
3410
|
+
const hasEmbeddedOrLocalFile = !!url && (url.startsWith("data:") || url.startsWith("blob:") || !/^https?:\/\//i.test(url));
|
|
3411
|
+
const imgId = photoRin || (hasEmbeddedOrLocalFile && url ? `local-${String(key).replace(/[@]/g, "")}-${getFileExtension(url) || "bin"}` : void 0);
|
|
3344
3412
|
if (url && imgId) {
|
|
3345
3413
|
const id = `${tree}-${this.id}-${imgId}`;
|
|
3346
3414
|
list[id] = {
|
|
@@ -3463,10 +3531,10 @@ var Indi = class extends Common {
|
|
|
3463
3531
|
const isPrimary = obje?.get("_PRIM")?.toValue() === "Y";
|
|
3464
3532
|
const url = obje?.get("FILE")?.toValue();
|
|
3465
3533
|
const title = obje?.get("TITL")?.toValue() ?? "";
|
|
3466
|
-
const type = obje
|
|
3534
|
+
const type = resolveObjeForm(obje) ?? (url ? getFileExtension(url) : void 0) ?? "raw";
|
|
3467
3535
|
if (url) {
|
|
3468
3536
|
const urlMatch = url.match(/\/([^/]+)\?hash=/);
|
|
3469
|
-
const imgId = urlMatch?.[1] || `img-${index}-${Date.now().toString(36)}
|
|
3537
|
+
const imgId = urlMatch?.[1] || (url.startsWith("data:") ? `data-${index}-${getFileExtension(url) || "bin"}` : `img-${index}-${Date.now().toString(36)}`);
|
|
3470
3538
|
const id = `geni-${geniId}-${imgId}`;
|
|
3471
3539
|
list[id] = {
|
|
3472
3540
|
isPrimary,
|
|
@@ -3503,10 +3571,10 @@ var Indi = class extends Common {
|
|
|
3503
3571
|
obje.standardizeMedia();
|
|
3504
3572
|
const isPrimary = obje?.get("_PRIM")?.toValue() === "Y";
|
|
3505
3573
|
const url = obje?.get("FILE")?.toValue();
|
|
3506
|
-
const title = obje?.get("TITL")?.toValue() ?? "";
|
|
3507
|
-
const type = obje
|
|
3574
|
+
const title = obje?.get("FILE.TITL")?.toValue() ?? obje?.get("TITL")?.toValue() ?? "";
|
|
3575
|
+
const type = resolveObjeForm(obje) ?? (url ? getFileExtension(url) : void 0) ?? "raw";
|
|
3508
3576
|
if (url) {
|
|
3509
|
-
const imgId = `media-${index}-${url.split("/").pop()?.split("?")[0]?.substring(0, 20) || Date.now().toString(36)}`;
|
|
3577
|
+
const imgId = `media-${index}-${url.startsWith("data:") ? getFileExtension(url) || "bin" : url.split("/").pop()?.split("?")[0]?.substring(0, 20) || Date.now().toString(36)}`;
|
|
3510
3578
|
const id = `${treeId}-${this.id}-${imgId}`;
|
|
3511
3579
|
list[id] = {
|
|
3512
3580
|
isPrimary,
|
|
@@ -3546,7 +3614,20 @@ var Indi = class extends Common {
|
|
|
3546
3614
|
cacheKey
|
|
3547
3615
|
);
|
|
3548
3616
|
if (cached !== void 0) {
|
|
3549
|
-
|
|
3617
|
+
if (cached?.file && !isRemoteOrEmbeddedMediaUrl(cached.file)) {
|
|
3618
|
+
const resolvedCached = await resolveLocalMediaUrl(cached.file);
|
|
3619
|
+
if (resolvedCached && isRemoteOrEmbeddedMediaUrl(resolvedCached)) {
|
|
3620
|
+
const refreshed = { ...cached, file: resolvedCached };
|
|
3621
|
+
profilePictureCache(
|
|
3622
|
+
this._gedcom,
|
|
3623
|
+
cacheKey,
|
|
3624
|
+
refreshed
|
|
3625
|
+
);
|
|
3626
|
+
return refreshed;
|
|
3627
|
+
}
|
|
3628
|
+
} else {
|
|
3629
|
+
return cached;
|
|
3630
|
+
}
|
|
3550
3631
|
}
|
|
3551
3632
|
const mediaList = await this.multimedia(namespace);
|
|
3552
3633
|
if (!mediaList) {
|
|
@@ -3558,39 +3639,40 @@ var Indi = class extends Common {
|
|
|
3558
3639
|
return void 0;
|
|
3559
3640
|
}
|
|
3560
3641
|
const mediaArray = Object.values(mediaList);
|
|
3561
|
-
const
|
|
3562
|
-
|
|
3563
|
-
|
|
3564
|
-
|
|
3565
|
-
|
|
3566
|
-
|
|
3567
|
-
|
|
3568
|
-
|
|
3569
|
-
|
|
3642
|
+
const toDisplayableProfile = async (media, isPrimary) => {
|
|
3643
|
+
const resolvedFile = await resolveLocalMediaUrl(media.url);
|
|
3644
|
+
if (!resolvedFile || !isRemoteOrEmbeddedMediaUrl(resolvedFile)) {
|
|
3645
|
+
return void 0;
|
|
3646
|
+
}
|
|
3647
|
+
return {
|
|
3648
|
+
file: resolvedFile,
|
|
3649
|
+
form: media.contentType,
|
|
3650
|
+
title: media.title,
|
|
3651
|
+
isPrimary
|
|
3570
3652
|
};
|
|
3571
|
-
|
|
3572
|
-
|
|
3573
|
-
|
|
3574
|
-
|
|
3575
|
-
|
|
3576
|
-
this._gedcom,
|
|
3577
|
-
cacheKey,
|
|
3578
|
-
void 0
|
|
3579
|
-
);
|
|
3580
|
-
return void 0;
|
|
3581
|
-
}
|
|
3582
|
-
const secondaryMedia = mediaArray.find(
|
|
3583
|
-
(media) => isImageFormat(media.contentType || getFileExtension(media.url))
|
|
3653
|
+
};
|
|
3654
|
+
const candidates = mediaArray.filter(
|
|
3655
|
+
(media) => isImageFormat(
|
|
3656
|
+
media.contentType || media.url || getFileExtension(media.url)
|
|
3657
|
+
)
|
|
3584
3658
|
);
|
|
3585
|
-
|
|
3586
|
-
|
|
3587
|
-
|
|
3588
|
-
|
|
3589
|
-
|
|
3590
|
-
|
|
3591
|
-
|
|
3592
|
-
|
|
3593
|
-
|
|
3659
|
+
const ordered = [
|
|
3660
|
+
...candidates.filter((media) => media.isPrimary),
|
|
3661
|
+
...candidates.filter((media) => !media.isPrimary)
|
|
3662
|
+
];
|
|
3663
|
+
for (const media of ordered) {
|
|
3664
|
+
if (onlyPrimary && !media.isPrimary) {
|
|
3665
|
+
break;
|
|
3666
|
+
}
|
|
3667
|
+
const result = await toDisplayableProfile(media, !!media.isPrimary);
|
|
3668
|
+
if (result) {
|
|
3669
|
+
profilePictureCache(
|
|
3670
|
+
this._gedcom,
|
|
3671
|
+
cacheKey,
|
|
3672
|
+
result
|
|
3673
|
+
);
|
|
3674
|
+
return result;
|
|
3675
|
+
}
|
|
3594
3676
|
}
|
|
3595
3677
|
profilePictureCache(
|
|
3596
3678
|
this._gedcom,
|
|
@@ -3876,9 +3958,108 @@ var Indi = class extends Common {
|
|
|
3876
3958
|
addParent(parent, pedigree) {
|
|
3877
3959
|
return parent.addChild(this, pedigree);
|
|
3878
3960
|
}
|
|
3961
|
+
/**
|
|
3962
|
+
* Link an existing top-level OBJE record to this individual (`1 OBJE @On@`).
|
|
3963
|
+
*/
|
|
3964
|
+
attachMultimedia(objeOrKey, options) {
|
|
3965
|
+
if (!this._gedcom || !this.id) {
|
|
3966
|
+
return void 0;
|
|
3967
|
+
}
|
|
3968
|
+
const obje = typeof objeOrKey === "string" ? this._gedcom.obje(objeOrKey) : objeOrKey;
|
|
3969
|
+
if (!obje?.id) {
|
|
3970
|
+
return void 0;
|
|
3971
|
+
}
|
|
3972
|
+
const already = this.get("OBJE")?.toList()?.values()?.some((item) => item?.toValue?.() === obje.id);
|
|
3973
|
+
if (!already) {
|
|
3974
|
+
const pointer = makePointer(
|
|
3975
|
+
this._gedcom,
|
|
3976
|
+
this,
|
|
3977
|
+
obje.id,
|
|
3978
|
+
"OBJE"
|
|
3979
|
+
);
|
|
3980
|
+
this.assign("OBJE", pointer);
|
|
3981
|
+
}
|
|
3982
|
+
if (options?.primary) {
|
|
3983
|
+
this.get("OBJE")?.toList()?.forEach((item) => {
|
|
3984
|
+
const target = item?.refType === "OBJE" ? this._gedcom?.obje(
|
|
3985
|
+
String(item.toValue())
|
|
3986
|
+
) : item;
|
|
3987
|
+
if (!target) {
|
|
3988
|
+
return;
|
|
3989
|
+
}
|
|
3990
|
+
if (target.id === obje.id) {
|
|
3991
|
+
target.set("_PRIM", "Y");
|
|
3992
|
+
} else if (target.get("_PRIM")?.toValue() === "Y") {
|
|
3993
|
+
target.set("_PRIM", "N");
|
|
3994
|
+
}
|
|
3995
|
+
});
|
|
3996
|
+
obje.set("_PRIM", "Y");
|
|
3997
|
+
}
|
|
3998
|
+
return obje;
|
|
3999
|
+
}
|
|
4000
|
+
detachMultimedia(objeKey) {
|
|
4001
|
+
const list = this.get("OBJE")?.toList();
|
|
4002
|
+
if (!list) {
|
|
4003
|
+
return;
|
|
4004
|
+
}
|
|
4005
|
+
const toRemove = list.values().filter(
|
|
4006
|
+
(item) => item?.toValue?.() === objeKey || item?.id === objeKey
|
|
4007
|
+
);
|
|
4008
|
+
toRemove.forEach((item) => {
|
|
4009
|
+
if (item) {
|
|
4010
|
+
list.delete(item);
|
|
4011
|
+
}
|
|
4012
|
+
});
|
|
4013
|
+
if (list.length === 0) {
|
|
4014
|
+
this.remove("OBJE");
|
|
4015
|
+
}
|
|
4016
|
+
}
|
|
4017
|
+
/**
|
|
4018
|
+
* Create a multimedia record and attach it to this person.
|
|
4019
|
+
*/
|
|
4020
|
+
attachMediaFromUrl(url, options) {
|
|
4021
|
+
if (!this._gedcom || !url) {
|
|
4022
|
+
return void 0;
|
|
4023
|
+
}
|
|
4024
|
+
const obje = this._gedcom.createMultimediaRecord({
|
|
4025
|
+
file: url,
|
|
4026
|
+
form: options?.form,
|
|
4027
|
+
title: options?.title,
|
|
4028
|
+
mediType: options?.mediType,
|
|
4029
|
+
primary: options?.primary,
|
|
4030
|
+
gedcomVersion: options?.gedcomVersion
|
|
4031
|
+
});
|
|
4032
|
+
return this.attachMultimedia(obje, { primary: options?.primary });
|
|
4033
|
+
}
|
|
4034
|
+
/**
|
|
4035
|
+
* Link a shared SNOTE record via `1 NOTE @Nn@` (GEDCOM 7).
|
|
4036
|
+
*/
|
|
4037
|
+
attachSharedNote(noteOrKey) {
|
|
4038
|
+
if (!this._gedcom || !this.id) {
|
|
4039
|
+
return void 0;
|
|
4040
|
+
}
|
|
4041
|
+
const note = typeof noteOrKey === "string" ? this._gedcom.snote(noteOrKey) : noteOrKey;
|
|
4042
|
+
if (!note?.id) {
|
|
4043
|
+
return void 0;
|
|
4044
|
+
}
|
|
4045
|
+
const already = this.get("NOTE")?.toList()?.values()?.some((item) => item?.toValue?.() === note.id);
|
|
4046
|
+
if (!already) {
|
|
4047
|
+
const pointer = makePointer(
|
|
4048
|
+
this._gedcom,
|
|
4049
|
+
this,
|
|
4050
|
+
note.id,
|
|
4051
|
+
"SNOTE"
|
|
4052
|
+
);
|
|
4053
|
+
this.assign("NOTE", pointer);
|
|
4054
|
+
}
|
|
4055
|
+
return note;
|
|
4056
|
+
}
|
|
3879
4057
|
addFact(input) {
|
|
3880
4058
|
return addIndividualFact(this, input);
|
|
3881
4059
|
}
|
|
4060
|
+
addNonEvent(input) {
|
|
4061
|
+
return addNonEvent(this, input);
|
|
4062
|
+
}
|
|
3882
4063
|
getParentType(id) {
|
|
3883
4064
|
let indi;
|
|
3884
4065
|
if (typeof id === "string" || typeof id === "number") {
|
|
@@ -3919,7 +4100,7 @@ var Indi = class extends Common {
|
|
|
3919
4100
|
if (!famChild) {
|
|
3920
4101
|
const childIndi = this._gedcom?.indi(child.id);
|
|
3921
4102
|
const childState = childIndi?.get("FAMC")?.toList()?.filter((item) => item.value === family.id).index(0);
|
|
3922
|
-
childType = childState?.get("PEDI")?.toValue() || "biological" /* BIOLOGICAL */;
|
|
4103
|
+
childType = (childState?.get("PEDI") ?? childState?.get("PEDT"))?.toValue() || "biological" /* BIOLOGICAL */;
|
|
3923
4104
|
} else {
|
|
3924
4105
|
childType = famChild.get(usedRel)?.toValue() || "biological" /* BIOLOGICAL */;
|
|
3925
4106
|
}
|
|
@@ -4480,7 +4661,7 @@ var Indi = class extends Common {
|
|
|
4480
4661
|
return;
|
|
4481
4662
|
}
|
|
4482
4663
|
const childState = child?.get("FAMC")?.toList()?.filter((item) => item.value === family.id).index(0);
|
|
4483
|
-
const childType = childState?.get("PEDI")?.toValue() || "biological" /* BIOLOGICAL */;
|
|
4664
|
+
const childType = (childState?.get("PEDI") ?? childState?.get("PEDT"))?.toValue() || "biological" /* BIOLOGICAL */;
|
|
4484
4665
|
if (childType?.toLowerCase() === filter.PEDI.toLowerCase()) {
|
|
4485
4666
|
children.append(child);
|
|
4486
4667
|
}
|
|
@@ -4588,7 +4769,7 @@ var Indi = class extends Common {
|
|
|
4588
4769
|
const child = this.id && family.CHIL?.toValueList()?.item(this.id);
|
|
4589
4770
|
if (!child) {
|
|
4590
4771
|
const childState = this?.get("FAMC")?.toList()?.filter((item) => item.value === family.id).index(0);
|
|
4591
|
-
const parentType = childState?.get("PEDI")?.toValue() || "biological" /* BIOLOGICAL */;
|
|
4772
|
+
const parentType = (childState?.get("PEDI") ?? childState?.get("PEDT"))?.toValue() || "biological" /* BIOLOGICAL */;
|
|
4592
4773
|
if (parentType?.toLowerCase() === filter.PEDI.toLowerCase()) {
|
|
4593
4774
|
parents.merge(family.getParents());
|
|
4594
4775
|
}
|
|
@@ -6787,7 +6968,11 @@ var STANDARD_QUALIFIERS = {
|
|
|
6787
6968
|
BEF: "Bef.",
|
|
6788
6969
|
BEFORE: "Bef.",
|
|
6789
6970
|
AFT: "Aft.",
|
|
6790
|
-
AFTER: "Aft."
|
|
6971
|
+
AFTER: "Aft.",
|
|
6972
|
+
CAL: "Abt.",
|
|
6973
|
+
// calculated ≈ about for display
|
|
6974
|
+
EST: "Abt."
|
|
6975
|
+
// estimated ≈ about for display
|
|
6791
6976
|
};
|
|
6792
6977
|
var EXPORT_QUALIFIERS = {
|
|
6793
6978
|
"Abt.": "ABT",
|
|
@@ -6795,6 +6980,11 @@ var EXPORT_QUALIFIERS = {
|
|
|
6795
6980
|
"Aft.": "AFT"
|
|
6796
6981
|
};
|
|
6797
6982
|
var GEDCOM_MONTHS = /\b(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)\b/g;
|
|
6983
|
+
var CALENDAR_PREFIX = /^(?<calendar>GREGORIAN|JULIAN|FRENCH_R|HEBREW)\b\s+/i;
|
|
6984
|
+
var isGedcomDateValueForm = (value) => (
|
|
6985
|
+
// Require space/end after the token so display forms like "Abt." are not opaque.
|
|
6986
|
+
/^(FROM|TO|BET|AFT|BEF|ABT|CAL|EST|INT)(\s|$)/i.test(value) || /\bAND\b/i.test(value)
|
|
6987
|
+
);
|
|
6798
6988
|
var NOTE_MARKER = "####";
|
|
6799
6989
|
var formatDateWithComponents = (date, hasDay, hasMonth, hasYear, noteValue, baseFormat = "dd MMM yyyy", locale) => {
|
|
6800
6990
|
const hasNote = baseFormat.includes("NOTE");
|
|
@@ -6819,29 +7009,45 @@ var CommonDate = class extends Common {
|
|
|
6819
7009
|
super(gedcom, id, main, parent);
|
|
6820
7010
|
delete this.id;
|
|
6821
7011
|
}
|
|
7012
|
+
get calendar() {
|
|
7013
|
+
return this._calendar;
|
|
7014
|
+
}
|
|
6822
7015
|
set value(value) {
|
|
6823
7016
|
if (value) {
|
|
6824
|
-
const noteRegExp = /^(?<note>[a-zA-Z]+\.)/;
|
|
6825
|
-
const noteMatch = value.match(noteRegExp)?.groups;
|
|
6826
7017
|
let validValue = value;
|
|
7018
|
+
const calendarMatch = validValue.match(CALENDAR_PREFIX);
|
|
7019
|
+
if (calendarMatch?.groups?.calendar) {
|
|
7020
|
+
this._calendar = calendarMatch.groups.calendar.toUpperCase();
|
|
7021
|
+
validValue = validValue.slice(calendarMatch[0].length);
|
|
7022
|
+
} else {
|
|
7023
|
+
this._calendar = void 0;
|
|
7024
|
+
}
|
|
7025
|
+
const noteRegExp = /^(?<note>[a-zA-Z]+\.)/;
|
|
7026
|
+
const noteMatch = validValue.match(noteRegExp)?.groups;
|
|
6827
7027
|
if (noteMatch?.note) {
|
|
6828
7028
|
this.NOTE = this.NOTE || createCommon(this._gedcom, void 0, this.main);
|
|
6829
7029
|
this.NOTE.value = noteMatch?.note;
|
|
6830
|
-
validValue =
|
|
7030
|
+
validValue = validValue.replace(noteRegExp, "");
|
|
6831
7031
|
} else {
|
|
6832
|
-
const qualifierMatch =
|
|
6833
|
-
/^(?<qualifier>ABT|ABOUT|BEF|BEFORE|AFT|AFTER)\b\s*/i
|
|
7032
|
+
const qualifierMatch = validValue.match(
|
|
7033
|
+
/^(?<qualifier>ABT|ABOUT|BEF|BEFORE|AFT|AFTER|CAL|EST)\b\s*/i
|
|
6834
7034
|
);
|
|
6835
7035
|
const qualifier = qualifierMatch?.groups?.qualifier?.toUpperCase();
|
|
6836
7036
|
const note = qualifier ? STANDARD_QUALIFIERS[qualifier] : void 0;
|
|
6837
7037
|
if (note) {
|
|
6838
7038
|
this.NOTE = this.NOTE || createCommon(this._gedcom, void 0, this.main);
|
|
6839
7039
|
this.NOTE.value = note;
|
|
6840
|
-
validValue =
|
|
7040
|
+
validValue = validValue.slice(qualifierMatch[0].length);
|
|
6841
7041
|
}
|
|
6842
7042
|
}
|
|
6843
7043
|
const acceptedDate = this.isValidDateFormat(validValue);
|
|
6844
|
-
if (
|
|
7044
|
+
if (isGedcomDateValueForm(validValue.trim())) {
|
|
7045
|
+
delete this.DAY;
|
|
7046
|
+
delete this.MONTH;
|
|
7047
|
+
delete this.YEAR;
|
|
7048
|
+
this._date = void 0;
|
|
7049
|
+
this._value = value;
|
|
7050
|
+
} else if (acceptedDate) {
|
|
6845
7051
|
this.DAY = this.DAY || createCommon(this._gedcom, void 0, this.main);
|
|
6846
7052
|
this.DAY.value = format(acceptedDate, "dd");
|
|
6847
7053
|
this.MONTH = this.MONTH || createCommon(this._gedcom, void 0, this.main);
|
|
@@ -6944,6 +7150,15 @@ var CommonDate = class extends Common {
|
|
|
6944
7150
|
);
|
|
6945
7151
|
}
|
|
6946
7152
|
exportValue() {
|
|
7153
|
+
if (typeof this._value === "string") {
|
|
7154
|
+
const withoutCalendar = this._value.replace(CALENDAR_PREFIX, "");
|
|
7155
|
+
if (isGedcomDateValueForm(withoutCalendar.trim())) {
|
|
7156
|
+
return this._value.replace(
|
|
7157
|
+
/^((?:GREGORIAN|JULIAN|FRENCH_R|HEBREW)\s+)?(FROM|TO|BET|AFT|BEF|ABT|CAL|EST|INT)\b/i,
|
|
7158
|
+
(_m, cal, q) => `${cal || ""}${q.toUpperCase()}`
|
|
7159
|
+
);
|
|
7160
|
+
}
|
|
7161
|
+
}
|
|
6947
7162
|
const formatted = this.toValue("NOTE dd MMM yyyy", null);
|
|
6948
7163
|
if (!formatted) {
|
|
6949
7164
|
return formatted;
|
|
@@ -6951,10 +7166,14 @@ var CommonDate = class extends Common {
|
|
|
6951
7166
|
const note = this.NOTE?.value?.trim();
|
|
6952
7167
|
const qualifier = note ? EXPORT_QUALIFIERS[note] : void 0;
|
|
6953
7168
|
const standardized = qualifier ? formatted.replace(note, qualifier) : formatted;
|
|
6954
|
-
|
|
7169
|
+
const withMonths = standardized.replace(
|
|
6955
7170
|
GEDCOM_MONTHS,
|
|
6956
7171
|
(month) => month.toUpperCase()
|
|
6957
7172
|
);
|
|
7173
|
+
if (this._calendar && this._calendar !== "GREGORIAN") {
|
|
7174
|
+
return `${this._calendar} ${withMonths}`;
|
|
7175
|
+
}
|
|
7176
|
+
return withMonths;
|
|
6958
7177
|
}
|
|
6959
7178
|
toGedcomLines(tag, level = 0, options) {
|
|
6960
7179
|
const internal = new RegExp(
|
|
@@ -7046,6 +7265,24 @@ var addFamilyFact = (fam, input) => {
|
|
|
7046
7265
|
fillFact(gedcom, fam, event, input);
|
|
7047
7266
|
return event;
|
|
7048
7267
|
};
|
|
7268
|
+
var addNonEvent = (owner, input) => {
|
|
7269
|
+
const gedcom = owner.getGedcom();
|
|
7270
|
+
const eventType = input.event?.trim().toUpperCase();
|
|
7271
|
+
if (!gedcom || !eventType) {
|
|
7272
|
+
return void 0;
|
|
7273
|
+
}
|
|
7274
|
+
const no = createCommon(gedcom, void 0, owner);
|
|
7275
|
+
no.type = "NO";
|
|
7276
|
+
no.value = eventType;
|
|
7277
|
+
if (input.date?.trim()) {
|
|
7278
|
+
setDateOn(gedcom, owner, no, input.date);
|
|
7279
|
+
}
|
|
7280
|
+
if (input.note?.trim()) {
|
|
7281
|
+
no.set("NOTE", input.note.trim());
|
|
7282
|
+
}
|
|
7283
|
+
owner.assign("NO", no);
|
|
7284
|
+
return no;
|
|
7285
|
+
};
|
|
7049
7286
|
|
|
7050
7287
|
// src/classes/fam.ts
|
|
7051
7288
|
var Fam = class extends Common {
|
|
@@ -7097,6 +7334,9 @@ var Fam = class extends Common {
|
|
|
7097
7334
|
addFact(input) {
|
|
7098
7335
|
return addFamilyFact(this, input);
|
|
7099
7336
|
}
|
|
7337
|
+
addNonEvent(input) {
|
|
7338
|
+
return addNonEvent(this, input);
|
|
7339
|
+
}
|
|
7100
7340
|
toList() {
|
|
7101
7341
|
return new Families().concat(
|
|
7102
7342
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
@@ -7150,98 +7390,845 @@ var Families = class _Families extends List {
|
|
|
7150
7390
|
}
|
|
7151
7391
|
};
|
|
7152
7392
|
|
|
7153
|
-
//
|
|
7154
|
-
var
|
|
7155
|
-
|
|
7156
|
-
|
|
7157
|
-
|
|
7158
|
-
|
|
7159
|
-
return
|
|
7393
|
+
// src/utils/gedcom-version.ts
|
|
7394
|
+
var normalizeGedcomVersion = (value) => {
|
|
7395
|
+
const trimmed = value?.trim() ?? "";
|
|
7396
|
+
if (trimmed.startsWith("7")) {
|
|
7397
|
+
return "7.0";
|
|
7398
|
+
}
|
|
7399
|
+
return "5.5.1";
|
|
7400
|
+
};
|
|
7401
|
+
var GEDZIP_GEDCOM_ENTRY = "gedcom.ged";
|
|
7402
|
+
var sanitizePathSegment = (name) => name.replace(/[^a-zA-Z0-9._-]+/g, "-").replace(/^\.+/, "") || "file";
|
|
7403
|
+
var extensionFor = (contentType) => {
|
|
7404
|
+
const raw = (contentType || "bin").replace(/^\./, "").toLowerCase();
|
|
7405
|
+
if (raw.includes("/")) {
|
|
7406
|
+
return raw.split("/").pop() || "bin";
|
|
7407
|
+
}
|
|
7408
|
+
return raw || "bin";
|
|
7409
|
+
};
|
|
7410
|
+
var rewriteGedcomFilePaths = (gedcomText, urlToPath) => {
|
|
7411
|
+
const entries = urlToPath instanceof Map ? urlToPath : new Map(Object.entries(urlToPath));
|
|
7412
|
+
let text = gedcomText;
|
|
7413
|
+
entries.forEach((path, url) => {
|
|
7414
|
+
const escaped = url.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
7415
|
+
text = text.replace(
|
|
7416
|
+
new RegExp(`(^|\\r?\\n)(\\d+ FILE )${escaped}`, "g"),
|
|
7417
|
+
`$1$2${path}`
|
|
7418
|
+
);
|
|
7419
|
+
});
|
|
7420
|
+
return text;
|
|
7421
|
+
};
|
|
7422
|
+
var assignMediaPaths = (mediaFiles) => {
|
|
7423
|
+
const urlToPath = /* @__PURE__ */ new Map();
|
|
7424
|
+
const usedPaths = /* @__PURE__ */ new Set([GEDZIP_GEDCOM_ENTRY]);
|
|
7425
|
+
const files = [];
|
|
7426
|
+
for (const file of mediaFiles) {
|
|
7427
|
+
if (!file.content || !file.url) {
|
|
7428
|
+
continue;
|
|
7429
|
+
}
|
|
7430
|
+
const ext = extensionFor(file.contentType);
|
|
7431
|
+
const base = sanitizePathSegment(
|
|
7432
|
+
file.imgId || file.title || file.id || "media"
|
|
7433
|
+
);
|
|
7434
|
+
let path = `media/${base}.${ext}`;
|
|
7435
|
+
let suffix = 1;
|
|
7436
|
+
while (usedPaths.has(path)) {
|
|
7437
|
+
path = `media/${base}-${suffix++}.${ext}`;
|
|
7438
|
+
}
|
|
7439
|
+
usedPaths.add(path);
|
|
7440
|
+
urlToPath.set(file.url, path);
|
|
7441
|
+
const marker = "base64,";
|
|
7442
|
+
const idx = file.content.indexOf(marker);
|
|
7443
|
+
if (idx >= 0) {
|
|
7444
|
+
files.push({
|
|
7445
|
+
path,
|
|
7446
|
+
url: file.url,
|
|
7447
|
+
content: file.content.substring(idx + marker.length),
|
|
7448
|
+
base64: true
|
|
7449
|
+
});
|
|
7450
|
+
} else {
|
|
7451
|
+
files.push({
|
|
7452
|
+
path,
|
|
7453
|
+
url: file.url,
|
|
7454
|
+
content: file.content,
|
|
7455
|
+
base64: false
|
|
7456
|
+
});
|
|
7457
|
+
}
|
|
7458
|
+
}
|
|
7459
|
+
return { urlToPath, files };
|
|
7160
7460
|
};
|
|
7161
|
-
var
|
|
7162
|
-
|
|
7163
|
-
|
|
7164
|
-
|
|
7165
|
-
|
|
7461
|
+
var buildGedzip = async (gedcomText, mediaFiles = []) => {
|
|
7462
|
+
const zip = new JSZip();
|
|
7463
|
+
const { urlToPath, files } = assignMediaPaths(mediaFiles);
|
|
7464
|
+
for (const file of files) {
|
|
7465
|
+
zip.file(file.path, file.content, { base64: file.base64 });
|
|
7466
|
+
}
|
|
7467
|
+
zip.file(GEDZIP_GEDCOM_ENTRY, rewriteGedcomFilePaths(gedcomText, urlToPath));
|
|
7468
|
+
return zip.generateAsync({ type: "uint8array" });
|
|
7166
7469
|
};
|
|
7167
|
-
|
|
7168
|
-
|
|
7169
|
-
|
|
7170
|
-
|
|
7171
|
-
|
|
7172
|
-
|
|
7173
|
-
|
|
7174
|
-
|
|
7175
|
-
|
|
7470
|
+
|
|
7471
|
+
// src/utils/gedcom7-enumerations.ts
|
|
7472
|
+
var GEDCOM7_SEX_VALUES = ["M", "F", "U", "X", "N"];
|
|
7473
|
+
var GEDCOM7_PEDI_VALUES = [
|
|
7474
|
+
"adopted",
|
|
7475
|
+
"birth",
|
|
7476
|
+
"foster",
|
|
7477
|
+
"sealing"
|
|
7478
|
+
];
|
|
7479
|
+
var GEDCOM7_ROLE_VALUES = [
|
|
7480
|
+
"CHIL",
|
|
7481
|
+
"CLERGY",
|
|
7482
|
+
"FATH",
|
|
7483
|
+
"FRIEND",
|
|
7484
|
+
"GODP",
|
|
7485
|
+
"HUSB",
|
|
7486
|
+
"MOTH",
|
|
7487
|
+
"MULTIPLE",
|
|
7488
|
+
"NGHBR",
|
|
7489
|
+
"OFFICIATOR",
|
|
7490
|
+
"OTHER",
|
|
7491
|
+
"PARENT",
|
|
7492
|
+
"SPOU",
|
|
7493
|
+
"WIFE",
|
|
7494
|
+
"WITN"
|
|
7495
|
+
];
|
|
7496
|
+
var GEDCOM7_RESN_VALUES = [
|
|
7497
|
+
"CONFIDENTIAL",
|
|
7498
|
+
"LOCKED",
|
|
7499
|
+
"PRIVACY"
|
|
7500
|
+
];
|
|
7501
|
+
var isAllowed = (value, allowed) => allowed.includes(value);
|
|
7502
|
+
var moveToPhrase = (node, phrase) => {
|
|
7503
|
+
const previousValue = node.value;
|
|
7504
|
+
const previousPhrase = node.get("PHRASE");
|
|
7505
|
+
const previousPhraseValue = previousPhrase?.toValue();
|
|
7506
|
+
node.removeValue();
|
|
7507
|
+
if (previousPhrase) {
|
|
7508
|
+
previousPhrase.value = phrase;
|
|
7509
|
+
} else {
|
|
7510
|
+
const phraseNode = createCommon(node.getGedcom(), void 0, node.main);
|
|
7511
|
+
phraseNode.value = phrase;
|
|
7512
|
+
node.set("PHRASE", phraseNode);
|
|
7176
7513
|
}
|
|
7177
|
-
|
|
7178
|
-
|
|
7179
|
-
|
|
7180
|
-
|
|
7514
|
+
return () => {
|
|
7515
|
+
if (previousValue === void 0) {
|
|
7516
|
+
node.removeValue();
|
|
7517
|
+
} else {
|
|
7518
|
+
node.value = previousValue;
|
|
7181
7519
|
}
|
|
7182
|
-
if (
|
|
7183
|
-
|
|
7520
|
+
if (previousPhrase) {
|
|
7521
|
+
previousPhrase.value = previousPhraseValue;
|
|
7522
|
+
} else {
|
|
7523
|
+
node.remove("PHRASE");
|
|
7184
7524
|
}
|
|
7185
|
-
|
|
7186
|
-
|
|
7187
|
-
|
|
7188
|
-
|
|
7189
|
-
|
|
7525
|
+
};
|
|
7526
|
+
};
|
|
7527
|
+
var normalizeEnum = (node, allowed, mode, restores) => {
|
|
7528
|
+
const value = node?.toValue();
|
|
7529
|
+
if (!node || typeof value !== "string" || !value.trim()) {
|
|
7530
|
+
return;
|
|
7190
7531
|
}
|
|
7191
|
-
|
|
7192
|
-
|
|
7193
|
-
|
|
7194
|
-
|
|
7195
|
-
|
|
7196
|
-
|
|
7197
|
-
|
|
7198
|
-
const childNode = this.createNodeFromPatchValue(item, node);
|
|
7199
|
-
if (childNode) {
|
|
7200
|
-
node.assign("DATA", childNode);
|
|
7201
|
-
}
|
|
7532
|
+
const normalized = mode === "upper" ? value.trim().toUpperCase() : value.trim().toLowerCase();
|
|
7533
|
+
if (isAllowed(normalized, allowed)) {
|
|
7534
|
+
if (value !== normalized) {
|
|
7535
|
+
const previous = node.value;
|
|
7536
|
+
node.value = normalized;
|
|
7537
|
+
restores.push(() => {
|
|
7538
|
+
node.value = previous;
|
|
7202
7539
|
});
|
|
7203
|
-
return node;
|
|
7204
7540
|
}
|
|
7205
|
-
|
|
7206
|
-
|
|
7207
|
-
|
|
7541
|
+
return;
|
|
7542
|
+
}
|
|
7543
|
+
restores.push(moveToPhrase(node, value.trim()));
|
|
7544
|
+
};
|
|
7545
|
+
var applyGedcom7Enumerations = (gedcom) => {
|
|
7546
|
+
const restores = [];
|
|
7547
|
+
gedcom.indis()?.forEach((indi) => {
|
|
7548
|
+
if (!indi) return;
|
|
7549
|
+
normalizeEnum(indi.get("SEX"), GEDCOM7_SEX_VALUES, "upper", restores);
|
|
7550
|
+
normalizeEnum(indi.get("RESN"), GEDCOM7_RESN_VALUES, "upper", restores);
|
|
7551
|
+
indi.get("FAMC")?.toList()?.forEach((famc) => {
|
|
7552
|
+
normalizeEnum(
|
|
7553
|
+
famc?.get("PEDI") ?? famc?.get("PEDT"),
|
|
7554
|
+
GEDCOM7_PEDI_VALUES,
|
|
7555
|
+
"lower",
|
|
7556
|
+
restores
|
|
7557
|
+
);
|
|
7558
|
+
});
|
|
7559
|
+
indi.get("ASSO")?.toList()?.forEach((asso) => {
|
|
7560
|
+
normalizeEnum(
|
|
7561
|
+
asso?.get("ROLE"),
|
|
7562
|
+
GEDCOM7_ROLE_VALUES,
|
|
7563
|
+
"upper",
|
|
7564
|
+
restores
|
|
7565
|
+
);
|
|
7566
|
+
});
|
|
7567
|
+
});
|
|
7568
|
+
gedcom.fams()?.forEach((fam) => {
|
|
7569
|
+
if (!fam) return;
|
|
7570
|
+
normalizeEnum(fam.get("RESN"), GEDCOM7_RESN_VALUES, "upper", restores);
|
|
7571
|
+
fam.get("ASSO")?.toList()?.forEach((asso) => {
|
|
7572
|
+
normalizeEnum(
|
|
7573
|
+
asso?.get("ROLE"),
|
|
7574
|
+
GEDCOM7_ROLE_VALUES,
|
|
7575
|
+
"upper",
|
|
7576
|
+
restores
|
|
7577
|
+
);
|
|
7578
|
+
});
|
|
7579
|
+
});
|
|
7580
|
+
return () => {
|
|
7581
|
+
for (let i = restores.length - 1; i >= 0; i -= 1) {
|
|
7582
|
+
restores[i]?.();
|
|
7208
7583
|
}
|
|
7209
|
-
|
|
7210
|
-
|
|
7584
|
+
};
|
|
7585
|
+
};
|
|
7586
|
+
|
|
7587
|
+
// src/utils/gedcom7-dates.ts
|
|
7588
|
+
var GEDCOM7_CALENDARS = [
|
|
7589
|
+
"GREGORIAN",
|
|
7590
|
+
"JULIAN",
|
|
7591
|
+
"FRENCH_R",
|
|
7592
|
+
"HEBREW"
|
|
7593
|
+
];
|
|
7594
|
+
var CALENDAR_PREFIX2 = /^(?<calendar>GREGORIAN|JULIAN|FRENCH_R|HEBREW)\b\s+/i;
|
|
7595
|
+
var parseGedcom7CalendarPrefix = (value) => {
|
|
7596
|
+
const match = value.match(CALENDAR_PREFIX2);
|
|
7597
|
+
if (!match?.groups?.calendar) {
|
|
7598
|
+
return { calendar: void 0, rest: value };
|
|
7211
7599
|
}
|
|
7212
|
-
|
|
7213
|
-
|
|
7214
|
-
|
|
7215
|
-
|
|
7216
|
-
|
|
7217
|
-
|
|
7218
|
-
|
|
7219
|
-
|
|
7220
|
-
|
|
7221
|
-
|
|
7222
|
-
|
|
7223
|
-
|
|
7600
|
+
return {
|
|
7601
|
+
calendar: match.groups.calendar.toUpperCase(),
|
|
7602
|
+
rest: value.slice(match[0].length)
|
|
7603
|
+
};
|
|
7604
|
+
};
|
|
7605
|
+
var withGedcom7Calendar = (value, calendar) => {
|
|
7606
|
+
if (!calendar || calendar.toUpperCase() === "GREGORIAN") {
|
|
7607
|
+
return value;
|
|
7608
|
+
}
|
|
7609
|
+
const upper = calendar.toUpperCase();
|
|
7610
|
+
if (GEDCOM7_CALENDARS.includes(upper)) {
|
|
7611
|
+
const { rest } = parseGedcom7CalendarPrefix(value);
|
|
7612
|
+
return `${upper} ${rest}`.trim();
|
|
7613
|
+
}
|
|
7614
|
+
return value;
|
|
7615
|
+
};
|
|
7616
|
+
var applyGedcom7DatePhrases = (gedcom) => {
|
|
7617
|
+
const restores = [];
|
|
7618
|
+
const visitDate = (dateNode) => {
|
|
7619
|
+
if (!dateNode || typeof dateNode.toValue !== "function") {
|
|
7620
|
+
return;
|
|
7621
|
+
}
|
|
7622
|
+
const asDate = dateNode;
|
|
7623
|
+
const hasComponents = !!(asDate.DAY || asDate.MONTH || asDate.YEAR);
|
|
7624
|
+
const raw = dateNode.exportValue?.() ?? dateNode.toValue();
|
|
7625
|
+
if (typeof raw !== "string" || !raw.trim()) {
|
|
7626
|
+
return;
|
|
7627
|
+
}
|
|
7628
|
+
const { calendar, rest } = parseGedcom7CalendarPrefix(raw.trim());
|
|
7629
|
+
const looksStructured = hasComponents || /^(ABT|CAL|EST|BEF|AFT|FROM|TO|BET|INT)(\s|$)/i.test(rest) || /\bAND\b/i.test(rest) || /^\d{1,2}\s+[A-Z]{3}\s+\d{1,4}/i.test(rest) || /^[A-Z]{3}\s+\d{1,4}/i.test(rest) || /^\d{1,4}$/.test(rest);
|
|
7630
|
+
if (looksStructured) {
|
|
7631
|
+
if (calendar && calendar !== "GREGORIAN") {
|
|
7632
|
+
const previous = dateNode.value;
|
|
7633
|
+
const next = withGedcom7Calendar(rest, calendar);
|
|
7634
|
+
if (previous !== next) {
|
|
7635
|
+
dateNode.value = next;
|
|
7636
|
+
restores.push(() => {
|
|
7637
|
+
dateNode.value = previous;
|
|
7638
|
+
});
|
|
7224
7639
|
}
|
|
7225
|
-
return;
|
|
7226
7640
|
}
|
|
7227
|
-
|
|
7228
|
-
|
|
7229
|
-
|
|
7641
|
+
return;
|
|
7642
|
+
}
|
|
7643
|
+
const previousValue = dateNode.value;
|
|
7644
|
+
const previousPhrase = dateNode.get("PHRASE");
|
|
7645
|
+
const previousPhraseValue = previousPhrase?.toValue();
|
|
7646
|
+
dateNode.removeValue();
|
|
7647
|
+
if (previousPhrase) {
|
|
7648
|
+
previousPhrase.value = raw.trim();
|
|
7649
|
+
} else {
|
|
7650
|
+
const phrase = createCommon(
|
|
7651
|
+
dateNode.getGedcom(),
|
|
7652
|
+
void 0,
|
|
7653
|
+
dateNode.main
|
|
7654
|
+
);
|
|
7655
|
+
phrase.value = raw.trim();
|
|
7656
|
+
dateNode.set("PHRASE", phrase);
|
|
7657
|
+
}
|
|
7658
|
+
restores.push(() => {
|
|
7659
|
+
if (previousValue === void 0) {
|
|
7660
|
+
dateNode.removeValue();
|
|
7661
|
+
} else {
|
|
7662
|
+
dateNode.value = previousValue;
|
|
7230
7663
|
}
|
|
7231
|
-
if (
|
|
7232
|
-
|
|
7233
|
-
|
|
7664
|
+
if (previousPhrase) {
|
|
7665
|
+
previousPhrase.value = previousPhraseValue;
|
|
7666
|
+
} else {
|
|
7667
|
+
dateNode.remove("PHRASE");
|
|
7234
7668
|
}
|
|
7235
|
-
|
|
7236
|
-
|
|
7237
|
-
|
|
7238
|
-
|
|
7239
|
-
|
|
7240
|
-
|
|
7241
|
-
|
|
7242
|
-
|
|
7243
|
-
|
|
7244
|
-
|
|
7669
|
+
});
|
|
7670
|
+
};
|
|
7671
|
+
const walk = (node) => {
|
|
7672
|
+
if (!node) return;
|
|
7673
|
+
node.get("DATE")?.toList()?.forEach((item) => visitDate(item));
|
|
7674
|
+
node.get("SDATE")?.toList()?.forEach((item) => visitDate(item));
|
|
7675
|
+
};
|
|
7676
|
+
gedcom.indis()?.forEach((indi) => {
|
|
7677
|
+
if (!indi) return;
|
|
7678
|
+
walk(indi);
|
|
7679
|
+
[
|
|
7680
|
+
"BIRT",
|
|
7681
|
+
"DEAT",
|
|
7682
|
+
"CHR",
|
|
7683
|
+
"BAPM",
|
|
7684
|
+
"BURI",
|
|
7685
|
+
"CREM",
|
|
7686
|
+
"ADOP",
|
|
7687
|
+
"EVEN",
|
|
7688
|
+
"RESI",
|
|
7689
|
+
"OCCU",
|
|
7690
|
+
"MARR"
|
|
7691
|
+
].forEach((tag) => {
|
|
7692
|
+
indi.get(tag)?.toList()?.forEach((event) => walk(event));
|
|
7693
|
+
});
|
|
7694
|
+
});
|
|
7695
|
+
gedcom.fams()?.forEach((fam) => {
|
|
7696
|
+
if (!fam) return;
|
|
7697
|
+
["MARR", "DIV", "ENGA", "ANUL", "EVEN"].forEach((tag) => {
|
|
7698
|
+
fam.get(tag)?.toList()?.forEach((event) => walk(event));
|
|
7699
|
+
});
|
|
7700
|
+
});
|
|
7701
|
+
return () => {
|
|
7702
|
+
for (let i = restores.length - 1; i >= 0; i -= 1) {
|
|
7703
|
+
restores[i]?.();
|
|
7704
|
+
}
|
|
7705
|
+
};
|
|
7706
|
+
};
|
|
7707
|
+
|
|
7708
|
+
// src/utils/uid.ts
|
|
7709
|
+
var createGedcomUid = () => {
|
|
7710
|
+
const cryptoObj = typeof globalThis !== "undefined" ? globalThis.crypto : void 0;
|
|
7711
|
+
if (cryptoObj && typeof cryptoObj.randomUUID === "function") {
|
|
7712
|
+
return cryptoObj.randomUUID();
|
|
7713
|
+
}
|
|
7714
|
+
return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (char) => {
|
|
7715
|
+
const rand = Math.random() * 16 | 0;
|
|
7716
|
+
const value = char === "x" ? rand : rand & 3 | 8;
|
|
7717
|
+
return value.toString(16);
|
|
7718
|
+
});
|
|
7719
|
+
};
|
|
7720
|
+
|
|
7721
|
+
// src/utils/gedcom7-metadata.ts
|
|
7722
|
+
var GEDCOM_MONTHS2 = [
|
|
7723
|
+
"JAN",
|
|
7724
|
+
"FEB",
|
|
7725
|
+
"MAR",
|
|
7726
|
+
"APR",
|
|
7727
|
+
"MAY",
|
|
7728
|
+
"JUN",
|
|
7729
|
+
"JUL",
|
|
7730
|
+
"AUG",
|
|
7731
|
+
"SEP",
|
|
7732
|
+
"OCT",
|
|
7733
|
+
"NOV",
|
|
7734
|
+
"DEC"
|
|
7735
|
+
];
|
|
7736
|
+
var formatGedcom7Timestamp = (date = /* @__PURE__ */ new Date()) => {
|
|
7737
|
+
const day = String(date.getUTCDate());
|
|
7738
|
+
const month = GEDCOM_MONTHS2[date.getUTCMonth()];
|
|
7739
|
+
const year = String(date.getUTCFullYear());
|
|
7740
|
+
const hh = String(date.getUTCHours()).padStart(2, "0");
|
|
7741
|
+
const mm = String(date.getUTCMinutes()).padStart(2, "0");
|
|
7742
|
+
const ss = String(date.getUTCSeconds()).padStart(2, "0");
|
|
7743
|
+
return {
|
|
7744
|
+
date: `${day} ${month} ${year}`,
|
|
7745
|
+
time: `${hh}:${mm}:${ss}Z`
|
|
7746
|
+
};
|
|
7747
|
+
};
|
|
7748
|
+
var ensureMetaDate = (gedcom, record, tag, when, restores) => {
|
|
7749
|
+
if (record.get(tag)) {
|
|
7750
|
+
return;
|
|
7751
|
+
}
|
|
7752
|
+
const { date, time } = formatGedcom7Timestamp(when);
|
|
7753
|
+
const meta = createCommon(gedcom, void 0, record);
|
|
7754
|
+
meta.type = tag;
|
|
7755
|
+
const dateNode = createCommonDate(gedcom, void 0, record, meta);
|
|
7756
|
+
dateNode.type = "DATE";
|
|
7757
|
+
dateNode.value = date;
|
|
7758
|
+
dateNode.set("TIME", time);
|
|
7759
|
+
meta.set("DATE", dateNode);
|
|
7760
|
+
record.set(tag, meta);
|
|
7761
|
+
restores.push(() => {
|
|
7762
|
+
record.remove(tag);
|
|
7763
|
+
});
|
|
7764
|
+
};
|
|
7765
|
+
var ensureUid = (record, restores) => {
|
|
7766
|
+
const existing = record.get("UID")?.toValue();
|
|
7767
|
+
if (typeof existing === "string" && existing.trim()) {
|
|
7768
|
+
return;
|
|
7769
|
+
}
|
|
7770
|
+
const uid = createGedcomUid();
|
|
7771
|
+
record.set("UID", uid);
|
|
7772
|
+
restores.push(() => {
|
|
7773
|
+
record.remove("UID");
|
|
7774
|
+
});
|
|
7775
|
+
};
|
|
7776
|
+
var applyGedcom7RecordMetadata = (gedcom, options) => {
|
|
7777
|
+
const restores = [];
|
|
7778
|
+
const now = /* @__PURE__ */ new Date();
|
|
7779
|
+
const visit = (record) => {
|
|
7780
|
+
if (!record?.id) {
|
|
7781
|
+
return;
|
|
7782
|
+
}
|
|
7783
|
+
ensureUid(record, restores);
|
|
7784
|
+
ensureMetaDate(gedcom, record, "CREA", now, restores);
|
|
7785
|
+
ensureMetaDate(gedcom, record, "CHAN", now, restores);
|
|
7786
|
+
};
|
|
7787
|
+
gedcom.indis()?.forEach((indi) => visit(indi));
|
|
7788
|
+
gedcom.fams()?.forEach((fam) => visit(fam));
|
|
7789
|
+
gedcom.objes()?.forEach((obje) => visit(obje));
|
|
7790
|
+
gedcom.sours()?.forEach((sour) => visit(sour));
|
|
7791
|
+
gedcom.repos()?.forEach((repo) => visit(repo));
|
|
7792
|
+
gedcom.subms()?.forEach((subm) => visit(subm));
|
|
7793
|
+
gedcom.snotes()?.forEach((note) => visit(note));
|
|
7794
|
+
return () => {
|
|
7795
|
+
for (let i = restores.length - 1; i >= 0; i -= 1) {
|
|
7796
|
+
restores[i]?.();
|
|
7797
|
+
}
|
|
7798
|
+
};
|
|
7799
|
+
};
|
|
7800
|
+
|
|
7801
|
+
// src/utils/gedcom7-schema.ts
|
|
7802
|
+
var TREEVIZ_EXTENSION_BASE_URI = "https://treeviz.com/gedcom";
|
|
7803
|
+
var TREEVIZ_EXTENSION_URIS = {
|
|
7804
|
+
_ORIGHEAD: `${TREEVIZ_EXTENSION_BASE_URI}#_ORIGHEAD`,
|
|
7805
|
+
_TREE: `${TREEVIZ_EXTENSION_BASE_URI}#_TREE`,
|
|
7806
|
+
_TID: `${TREEVIZ_EXTENSION_BASE_URI}#_TID`,
|
|
7807
|
+
_PRIM: `${TREEVIZ_EXTENSION_BASE_URI}#_PRIM`,
|
|
7808
|
+
_FREL: `${TREEVIZ_EXTENSION_BASE_URI}#_FREL`,
|
|
7809
|
+
_MREL: `${TREEVIZ_EXTENSION_BASE_URI}#_MREL`,
|
|
7810
|
+
_SREL: `${TREEVIZ_EXTENSION_BASE_URI}#_SREL`,
|
|
7811
|
+
_UID: `${TREEVIZ_EXTENSION_BASE_URI}#_UID`,
|
|
7812
|
+
_WLNK: `${TREEVIZ_EXTENSION_BASE_URI}#_WLNK`,
|
|
7813
|
+
_MTTAG: `${TREEVIZ_EXTENSION_BASE_URI}#_MTTAG`,
|
|
7814
|
+
_MTCAT: `${TREEVIZ_EXTENSION_BASE_URI}#_MTCAT`,
|
|
7815
|
+
_CLON: `${TREEVIZ_EXTENSION_BASE_URI}#_CLON`,
|
|
7816
|
+
_MSER: `${TREEVIZ_EXTENSION_BASE_URI}#_MSER`,
|
|
7817
|
+
_OID: `${TREEVIZ_EXTENSION_BASE_URI}#_OID`,
|
|
7818
|
+
_LKID: `${TREEVIZ_EXTENSION_BASE_URI}#_LKID`,
|
|
7819
|
+
_PHOTO_RIN: `${TREEVIZ_EXTENSION_BASE_URI}#_PHOTO_RIN`,
|
|
7820
|
+
_EXPORTED_FROM_SITE_ID: `${TREEVIZ_EXTENSION_BASE_URI}#_EXPORTED_FROM_SITE_ID`,
|
|
7821
|
+
_FS_ID: `${TREEVIZ_EXTENSION_BASE_URI}#_FS_ID`,
|
|
7822
|
+
_FS_LINK: `${TREEVIZ_EXTENSION_BASE_URI}#_FS_LINK`,
|
|
7823
|
+
_FS_MATCH: `${TREEVIZ_EXTENSION_BASE_URI}#_FS_MATCH`,
|
|
7824
|
+
_FS_SOUR: `${TREEVIZ_EXTENSION_BASE_URI}#_FS_SOUR`,
|
|
7825
|
+
_IS_FS: `${TREEVIZ_EXTENSION_BASE_URI}#_IS_FS`,
|
|
7826
|
+
_LABEL: `${TREEVIZ_EXTENSION_BASE_URI}#_LABEL`,
|
|
7827
|
+
_MILT: `${TREEVIZ_EXTENSION_BASE_URI}#_MILT`,
|
|
7828
|
+
_MILTID: `${TREEVIZ_EXTENSION_BASE_URI}#_MILTID`,
|
|
7829
|
+
_ORIG: `${TREEVIZ_EXTENSION_BASE_URI}#_ORIG`,
|
|
7830
|
+
_ENV: `${TREEVIZ_EXTENSION_BASE_URI}#_ENV`,
|
|
7831
|
+
_TREEVIZ_SETTINGS: `${TREEVIZ_EXTENSION_BASE_URI}#_TREEVIZ_SETTINGS`,
|
|
7832
|
+
_TREEVIZ_VIEW: `${TREEVIZ_EXTENSION_BASE_URI}#_TREEVIZ_VIEW`,
|
|
7833
|
+
_TREEVIZ_DETECTIVE: `${TREEVIZ_EXTENSION_BASE_URI}#_TREEVIZ_DETECTIVE`,
|
|
7834
|
+
_TREEVIZ_DETECTIVE_STATE: `${TREEVIZ_EXTENSION_BASE_URI}#_TREEVIZ_DETECTIVE_STATE`
|
|
7835
|
+
};
|
|
7836
|
+
var parseTagDefinition = (payload) => {
|
|
7837
|
+
const trimmed = payload.trim();
|
|
7838
|
+
const space = trimmed.indexOf(" ");
|
|
7839
|
+
if (space <= 0) {
|
|
7840
|
+
return void 0;
|
|
7841
|
+
}
|
|
7842
|
+
const tag = trimmed.slice(0, space).trim();
|
|
7843
|
+
const uri = trimmed.slice(space + 1).trim();
|
|
7844
|
+
if (!tag || !uri) {
|
|
7845
|
+
return void 0;
|
|
7846
|
+
}
|
|
7847
|
+
return { tag, uri };
|
|
7848
|
+
};
|
|
7849
|
+
var getExtensionSchema = (gedcom) => {
|
|
7850
|
+
const map = /* @__PURE__ */ new Map();
|
|
7851
|
+
const schma = gedcom.get("HEAD")?.get("SCHMA");
|
|
7852
|
+
if (!schma) {
|
|
7853
|
+
return map;
|
|
7854
|
+
}
|
|
7855
|
+
schma.get("TAG")?.toList()?.forEach((tagNode) => {
|
|
7856
|
+
const payload = tagNode?.toValue();
|
|
7857
|
+
if (typeof payload !== "string") {
|
|
7858
|
+
return;
|
|
7859
|
+
}
|
|
7860
|
+
const parsed = parseTagDefinition(payload);
|
|
7861
|
+
if (parsed) {
|
|
7862
|
+
map.set(parsed.tag.toUpperCase(), parsed.uri);
|
|
7863
|
+
}
|
|
7864
|
+
});
|
|
7865
|
+
return map;
|
|
7866
|
+
};
|
|
7867
|
+
var ensureSchemaNode = (gedcom) => {
|
|
7868
|
+
const head = gedcom.get("HEAD");
|
|
7869
|
+
if (!head) {
|
|
7870
|
+
return void 0;
|
|
7871
|
+
}
|
|
7872
|
+
let schma = head.get("SCHMA");
|
|
7873
|
+
if (!schma) {
|
|
7874
|
+
schma = createCommon(gedcom, void 0, head);
|
|
7875
|
+
head.set("SCHMA", schma);
|
|
7876
|
+
}
|
|
7877
|
+
return schma;
|
|
7878
|
+
};
|
|
7879
|
+
var registerExtensionTag = (gedcom, tag, uri) => {
|
|
7880
|
+
const normalizedTag = tag.trim().toUpperCase();
|
|
7881
|
+
const normalizedUri = uri.trim();
|
|
7882
|
+
if (!normalizedTag.startsWith("_") || !normalizedUri) {
|
|
7883
|
+
return void 0;
|
|
7884
|
+
}
|
|
7885
|
+
const schma = ensureSchemaNode(gedcom);
|
|
7886
|
+
if (!schma) {
|
|
7887
|
+
return void 0;
|
|
7888
|
+
}
|
|
7889
|
+
const payload = `${normalizedTag} ${normalizedUri}`;
|
|
7890
|
+
const existingList = schma.get("TAG")?.toList();
|
|
7891
|
+
const existing = existingList?.values().find((node) => {
|
|
7892
|
+
const value = node?.toValue();
|
|
7893
|
+
return typeof value === "string" && value.trim().toUpperCase().startsWith(`${normalizedTag} `);
|
|
7894
|
+
});
|
|
7895
|
+
if (existing) {
|
|
7896
|
+
existing.value = payload;
|
|
7897
|
+
return existing;
|
|
7898
|
+
}
|
|
7899
|
+
const tagNode = createCommon(gedcom, void 0, schma);
|
|
7900
|
+
tagNode.value = payload;
|
|
7901
|
+
schma.assign("TAG", tagNode);
|
|
7902
|
+
return tagNode;
|
|
7903
|
+
};
|
|
7904
|
+
var ensureExtensionSchema = (gedcom, extraTags) => {
|
|
7905
|
+
const head = gedcom.get("HEAD");
|
|
7906
|
+
const hadSchma = !!head?.get("SCHMA");
|
|
7907
|
+
const previousPayloads = head?.get("SCHMA")?.get("TAG")?.toList()?.values().map((node) => ({
|
|
7908
|
+
node,
|
|
7909
|
+
value: node?.toValue()
|
|
7910
|
+
})) ?? [];
|
|
7911
|
+
const tags = /* @__PURE__ */ new Set([
|
|
7912
|
+
...Object.keys(TREEVIZ_EXTENSION_URIS),
|
|
7913
|
+
...(extraTags ?? []).map((tag) => tag.toUpperCase())
|
|
7914
|
+
]);
|
|
7915
|
+
tags.forEach((tag) => {
|
|
7916
|
+
const uri = TREEVIZ_EXTENSION_URIS[tag] ?? `${TREEVIZ_EXTENSION_BASE_URI}#${tag}`;
|
|
7917
|
+
if (tag.startsWith("_")) {
|
|
7918
|
+
registerExtensionTag(gedcom, tag, uri);
|
|
7919
|
+
}
|
|
7920
|
+
});
|
|
7921
|
+
return () => {
|
|
7922
|
+
if (!head) {
|
|
7923
|
+
return;
|
|
7924
|
+
}
|
|
7925
|
+
if (!hadSchma) {
|
|
7926
|
+
head.remove("SCHMA");
|
|
7927
|
+
return;
|
|
7928
|
+
}
|
|
7929
|
+
const schma = head.get("SCHMA");
|
|
7930
|
+
const list = schma?.get("TAG")?.toList();
|
|
7931
|
+
const keep = new Set(
|
|
7932
|
+
previousPayloads.map(
|
|
7933
|
+
(item) => typeof item.value === "string" ? item.value : void 0
|
|
7934
|
+
).filter((value) => !!value)
|
|
7935
|
+
);
|
|
7936
|
+
list?.values().forEach((node) => {
|
|
7937
|
+
const value = node?.toValue();
|
|
7938
|
+
if (typeof value === "string" && !keep.has(value) && node) {
|
|
7939
|
+
list.delete(node);
|
|
7940
|
+
}
|
|
7941
|
+
});
|
|
7942
|
+
previousPayloads.forEach(({ node, value }) => {
|
|
7943
|
+
if (node && value !== void 0) {
|
|
7944
|
+
node.value = value;
|
|
7945
|
+
}
|
|
7946
|
+
});
|
|
7947
|
+
};
|
|
7948
|
+
};
|
|
7949
|
+
|
|
7950
|
+
// package.json
|
|
7951
|
+
var package_default = {
|
|
7952
|
+
version: "2.1.1"};
|
|
7953
|
+
|
|
7954
|
+
// src/utils/get-product-details.ts
|
|
7955
|
+
var isDevelopment = () => {
|
|
7956
|
+
return !process.env.NODE_ENV || process.env.NODE_ENV === "development";
|
|
7957
|
+
};
|
|
7958
|
+
var getVersion = () => package_default.version;
|
|
7959
|
+
|
|
7960
|
+
// src/utils/multimedia.ts
|
|
7961
|
+
var inferMediaForm = (file, fallback = "bin") => {
|
|
7962
|
+
const withoutQuery = file.split("?")[0] || file;
|
|
7963
|
+
const ext = getFileExtension(withoutQuery);
|
|
7964
|
+
if (ext) {
|
|
7965
|
+
return ext.toLowerCase() === "jpeg" ? "jpg" : ext.toLowerCase();
|
|
7966
|
+
}
|
|
7967
|
+
return fallback;
|
|
7968
|
+
};
|
|
7969
|
+
var mergeMediaLists = (...lists) => {
|
|
7970
|
+
const merged = {};
|
|
7971
|
+
for (const list of lists) {
|
|
7972
|
+
if (!list) continue;
|
|
7973
|
+
Object.assign(merged, list);
|
|
7974
|
+
}
|
|
7975
|
+
return merged;
|
|
7976
|
+
};
|
|
7977
|
+
|
|
7978
|
+
// src/classes/note.ts
|
|
7979
|
+
var CommonNote = class extends Common {
|
|
7980
|
+
constructor(gedcom, id, main, parent) {
|
|
7981
|
+
super(gedcom, id, main, parent);
|
|
7982
|
+
if (!id) {
|
|
7983
|
+
delete this.id;
|
|
7984
|
+
}
|
|
7985
|
+
}
|
|
7986
|
+
set value(value) {
|
|
7987
|
+
const [note, ...contents] = value?.split(/\r?\n/) ?? [];
|
|
7988
|
+
this._value = note;
|
|
7989
|
+
if (contents.length) {
|
|
7990
|
+
const newContents = new List();
|
|
7991
|
+
contents.forEach((c, i) => {
|
|
7992
|
+
const newContent = createCommon(
|
|
7993
|
+
this._gedcom,
|
|
7994
|
+
void 0,
|
|
7995
|
+
this.main
|
|
7996
|
+
);
|
|
7997
|
+
newContent.id = `@U${i}@`;
|
|
7998
|
+
newContent.value = c;
|
|
7999
|
+
newContents.append(newContent);
|
|
8000
|
+
});
|
|
8001
|
+
const firstItem = newContents.index(0);
|
|
8002
|
+
if (firstItem) {
|
|
8003
|
+
if (newContents.length === 1) {
|
|
8004
|
+
this.set("CONT", firstItem);
|
|
8005
|
+
} else {
|
|
8006
|
+
this.set("CONT", newContents);
|
|
8007
|
+
}
|
|
8008
|
+
}
|
|
8009
|
+
}
|
|
8010
|
+
}
|
|
8011
|
+
get value() {
|
|
8012
|
+
const contents = this.get("CONT")?.toList().map((content) => content.value).join("\n");
|
|
8013
|
+
if (contents) {
|
|
8014
|
+
return `${this._value}
|
|
8015
|
+
${contents}`;
|
|
8016
|
+
}
|
|
8017
|
+
return this._value;
|
|
8018
|
+
}
|
|
8019
|
+
exportValue() {
|
|
8020
|
+
return this._value;
|
|
8021
|
+
}
|
|
8022
|
+
};
|
|
8023
|
+
var createCommonNote = (gedcom, id, main, parent) => {
|
|
8024
|
+
return createProxy(
|
|
8025
|
+
new CommonNote(gedcom, id, main, parent)
|
|
8026
|
+
);
|
|
8027
|
+
};
|
|
8028
|
+
|
|
8029
|
+
// src/classes/obje.ts
|
|
8030
|
+
var Obje = class extends Common {
|
|
8031
|
+
standardizeMedia(namespace, override = true, urlGetter, gedcomVersion) {
|
|
8032
|
+
if (!this._gedcom) {
|
|
8033
|
+
return this;
|
|
8034
|
+
}
|
|
8035
|
+
const rin = this?.get("RIN")?.toValue();
|
|
8036
|
+
const clone = this?.get("_CLON._OID")?.toValue();
|
|
8037
|
+
const mser = this?.get("_MSER._LKID")?.toValue();
|
|
8038
|
+
const title = this?.get("FILE.TITL")?.toValue() ?? this?.get("TITL")?.toValue() ?? "";
|
|
8039
|
+
const note = this?.get("FILE.NOTE")?.toValue() ?? this?.get("NOTE")?.toValue() ?? "";
|
|
8040
|
+
const formRaw = this?.get("FILE.FORM")?.toValue() ?? this?.get("FORM")?.toValue();
|
|
8041
|
+
const mediType = this?.get("FILE.FORM.TYPE")?.toValue() ?? this?.get("FORM.TYPE")?.toValue() ?? this?.get("MEDI")?.toValue();
|
|
8042
|
+
const file = this?.get("FILE")?.toValue();
|
|
8043
|
+
const imgId = rin || clone || mser;
|
|
8044
|
+
const url = file || namespace && urlGetter?.(namespace, imgId);
|
|
8045
|
+
if (!url) {
|
|
8046
|
+
return this;
|
|
8047
|
+
}
|
|
8048
|
+
const version = normalizeGedcomVersion(
|
|
8049
|
+
gedcomVersion ?? this._gedcom.getGedcomVersion?.()
|
|
8050
|
+
);
|
|
8051
|
+
const form = formRaw || inferMediaForm(String(url));
|
|
8052
|
+
const newObject = createObje(this._gedcom, this.id, this.main);
|
|
8053
|
+
if (!override) {
|
|
8054
|
+
Object.assign(newObject, this);
|
|
8055
|
+
}
|
|
8056
|
+
const fileNode = createCommon(this._gedcom, void 0, this.main);
|
|
8057
|
+
fileNode.value = url;
|
|
8058
|
+
if (version === "7.0") {
|
|
8059
|
+
const formNode = createCommon(this._gedcom, void 0, fileNode);
|
|
8060
|
+
formNode.value = form;
|
|
8061
|
+
if (mediType) {
|
|
8062
|
+
formNode.set("TYPE", String(mediType));
|
|
8063
|
+
}
|
|
8064
|
+
fileNode.set("FORM", formNode);
|
|
8065
|
+
if (title) {
|
|
8066
|
+
fileNode.set("TITL", String(title));
|
|
8067
|
+
}
|
|
8068
|
+
if (note) {
|
|
8069
|
+
fileNode.set("NOTE", String(note));
|
|
8070
|
+
}
|
|
8071
|
+
newObject.set("FILE", fileNode);
|
|
8072
|
+
} else {
|
|
8073
|
+
newObject.set("FILE", fileNode);
|
|
8074
|
+
newObject.set("FORM", form);
|
|
8075
|
+
if (mediType) {
|
|
8076
|
+
newObject.set("MEDI", String(mediType));
|
|
8077
|
+
}
|
|
8078
|
+
if (title) {
|
|
8079
|
+
newObject.set("TITL", String(title));
|
|
8080
|
+
if (!note) {
|
|
8081
|
+
newObject.set("NOTE", String(title));
|
|
8082
|
+
}
|
|
8083
|
+
}
|
|
8084
|
+
if (note) {
|
|
8085
|
+
newObject.set("NOTE", String(note));
|
|
8086
|
+
if (!title) {
|
|
8087
|
+
newObject.set("TITL", String(note));
|
|
8088
|
+
}
|
|
8089
|
+
}
|
|
8090
|
+
}
|
|
8091
|
+
const prim = this.get("_PRIM")?.toValue();
|
|
8092
|
+
if (prim === "Y" || prim === "N") {
|
|
8093
|
+
newObject.set("_PRIM", prim);
|
|
8094
|
+
}
|
|
8095
|
+
const photoRin = this.get("_PHOTO_RIN")?.toValue();
|
|
8096
|
+
if (rin) {
|
|
8097
|
+
newObject.set("RIN", String(rin));
|
|
8098
|
+
}
|
|
8099
|
+
if (photoRin) {
|
|
8100
|
+
newObject.set("_PHOTO_RIN", String(photoRin));
|
|
8101
|
+
}
|
|
8102
|
+
const clonNode = this.get("_CLON");
|
|
8103
|
+
if (clonNode) {
|
|
8104
|
+
newObject.set("_CLON", clonNode);
|
|
8105
|
+
}
|
|
8106
|
+
const mserNode = this.get("_MSER");
|
|
8107
|
+
if (mserNode) {
|
|
8108
|
+
newObject.set("_MSER", mserNode);
|
|
8109
|
+
}
|
|
8110
|
+
const oidNode = this.get("_OID");
|
|
8111
|
+
if (oidNode && !newObject.get("_OID")) {
|
|
8112
|
+
newObject.set("_OID", oidNode);
|
|
8113
|
+
}
|
|
8114
|
+
const lkidNode = this.get("_LKID");
|
|
8115
|
+
if (lkidNode && !newObject.get("_LKID")) {
|
|
8116
|
+
newObject.set("_LKID", lkidNode);
|
|
8117
|
+
}
|
|
8118
|
+
if (override) {
|
|
8119
|
+
this.remove("FILE");
|
|
8120
|
+
this.remove("FORM");
|
|
8121
|
+
this.remove("MEDI");
|
|
8122
|
+
this.remove("TITL");
|
|
8123
|
+
this.remove("NOTE");
|
|
8124
|
+
Object.assign(this, newObject);
|
|
8125
|
+
return this;
|
|
8126
|
+
}
|
|
8127
|
+
return newObject;
|
|
8128
|
+
}
|
|
8129
|
+
};
|
|
8130
|
+
var createObje = (gedcom, id, main, parent) => {
|
|
8131
|
+
return createProxy(
|
|
8132
|
+
new Obje(gedcom, id, main, parent)
|
|
8133
|
+
);
|
|
8134
|
+
};
|
|
8135
|
+
|
|
8136
|
+
// src/classes/objes.ts
|
|
8137
|
+
var Objects = class _Objects extends List {
|
|
8138
|
+
copy() {
|
|
8139
|
+
const newList = new _Objects();
|
|
8140
|
+
this.entries().forEach(([key, value]) => {
|
|
8141
|
+
newList.item(key, value);
|
|
8142
|
+
});
|
|
8143
|
+
return newList;
|
|
8144
|
+
}
|
|
8145
|
+
except(item) {
|
|
8146
|
+
return this.copy().delete(item);
|
|
8147
|
+
}
|
|
8148
|
+
};
|
|
8149
|
+
|
|
8150
|
+
// src/classes/gedcom.ts
|
|
8151
|
+
var isObjectPatch = (value) => {
|
|
8152
|
+
return !!value && typeof value === "object" && !Array.isArray(value);
|
|
8153
|
+
};
|
|
8154
|
+
var GedCom = class extends Common {
|
|
8155
|
+
constructor() {
|
|
8156
|
+
super();
|
|
8157
|
+
this.tagMembers = {};
|
|
8158
|
+
this.reflist = {};
|
|
8159
|
+
this.refcount = 0;
|
|
8160
|
+
delete this._gedcom;
|
|
8161
|
+
delete this.id;
|
|
8162
|
+
this.removeValue();
|
|
8163
|
+
}
|
|
8164
|
+
getMain(type, index) {
|
|
8165
|
+
const list = !type || type instanceof List ? type : this.getList(type);
|
|
8166
|
+
if (!list) {
|
|
8167
|
+
return void 0;
|
|
8168
|
+
}
|
|
8169
|
+
if (typeof index === "string") {
|
|
8170
|
+
return list.item(index);
|
|
8171
|
+
}
|
|
8172
|
+
const keys = list.keys();
|
|
8173
|
+
return list.item(keys[index]);
|
|
8174
|
+
}
|
|
8175
|
+
getList(type) {
|
|
8176
|
+
return this.get(type);
|
|
8177
|
+
}
|
|
8178
|
+
createNodeFromPatchValue(value, main) {
|
|
8179
|
+
if (value === void 0 || value === null) {
|
|
8180
|
+
return void 0;
|
|
8181
|
+
}
|
|
8182
|
+
const node = createCommon(this, void 0, main);
|
|
8183
|
+
if (Array.isArray(value)) {
|
|
8184
|
+
value.forEach((item) => {
|
|
8185
|
+
const childNode = this.createNodeFromPatchValue(item, node);
|
|
8186
|
+
if (childNode) {
|
|
8187
|
+
node.assign("DATA", childNode);
|
|
8188
|
+
}
|
|
8189
|
+
});
|
|
8190
|
+
return node;
|
|
8191
|
+
}
|
|
8192
|
+
if (isObjectPatch(value)) {
|
|
8193
|
+
this.applyObjectToCommon(node, value);
|
|
8194
|
+
return node;
|
|
8195
|
+
}
|
|
8196
|
+
node.value = String(value);
|
|
8197
|
+
return node;
|
|
8198
|
+
}
|
|
8199
|
+
applyObjectToCommon(target, patch) {
|
|
8200
|
+
Object.entries(patch).forEach(([rawTag, value]) => {
|
|
8201
|
+
if (rawTag === "value") {
|
|
8202
|
+
if (value === null || value === void 0 || Array.isArray(value) || isObjectPatch(value)) {
|
|
8203
|
+
return;
|
|
8204
|
+
}
|
|
8205
|
+
target.value = String(value);
|
|
8206
|
+
return;
|
|
8207
|
+
}
|
|
8208
|
+
if (rawTag === "id") {
|
|
8209
|
+
if (typeof value === "string") {
|
|
8210
|
+
target.id = value;
|
|
8211
|
+
}
|
|
8212
|
+
return;
|
|
8213
|
+
}
|
|
8214
|
+
const tag = rawTag;
|
|
8215
|
+
if (value === void 0) {
|
|
8216
|
+
return;
|
|
8217
|
+
}
|
|
8218
|
+
if (value === null) {
|
|
8219
|
+
target.remove(tag);
|
|
8220
|
+
return;
|
|
8221
|
+
}
|
|
8222
|
+
if (Array.isArray(value)) {
|
|
8223
|
+
target.remove(tag);
|
|
8224
|
+
value.forEach((item) => {
|
|
8225
|
+
const listNode = this.createNodeFromPatchValue(
|
|
8226
|
+
item,
|
|
8227
|
+
target.main ?? this
|
|
8228
|
+
);
|
|
8229
|
+
if (listNode) {
|
|
8230
|
+
target.assign(tag, listNode);
|
|
8231
|
+
}
|
|
7245
8232
|
});
|
|
7246
8233
|
return;
|
|
7247
8234
|
}
|
|
@@ -7378,6 +8365,9 @@ var GedCom = class extends Common {
|
|
|
7378
8365
|
const id = this.nextIndiKey();
|
|
7379
8366
|
const indi = createIndi(this, id);
|
|
7380
8367
|
indi.type = "INDI";
|
|
8368
|
+
if (this.getGedcomVersion() === "7.0") {
|
|
8369
|
+
indi.set("UID", createGedcomUid());
|
|
8370
|
+
}
|
|
7381
8371
|
indis.item(id, indi);
|
|
7382
8372
|
return indi;
|
|
7383
8373
|
}
|
|
@@ -7390,9 +8380,151 @@ var GedCom = class extends Common {
|
|
|
7390
8380
|
const id = this.nextFamKey();
|
|
7391
8381
|
const fam = createFam(this, id);
|
|
7392
8382
|
fam.type = "FAM";
|
|
8383
|
+
if (this.getGedcomVersion() === "7.0") {
|
|
8384
|
+
fam.set("UID", createGedcomUid());
|
|
8385
|
+
}
|
|
7393
8386
|
fams.item(id, fam);
|
|
7394
8387
|
return fam;
|
|
7395
8388
|
}
|
|
8389
|
+
nextObjeKey() {
|
|
8390
|
+
const ids = [];
|
|
8391
|
+
this.objes()?.forEach((_obje, id) => {
|
|
8392
|
+
ids.push(String(id));
|
|
8393
|
+
});
|
|
8394
|
+
return nextRecordId(ids, "O");
|
|
8395
|
+
}
|
|
8396
|
+
/**
|
|
8397
|
+
* Create a top-level multimedia record (`0 @On@ OBJE`) with FILE/FORM/TITL.
|
|
8398
|
+
* GEDCOM 7 uses nested `FILE → FORM [→ TYPE]`; 5.5.1 uses sibling FORM/TITL.
|
|
8399
|
+
*/
|
|
8400
|
+
createMultimediaRecord(input) {
|
|
8401
|
+
const existing = this.objes();
|
|
8402
|
+
const objes = existing ?? new Objects();
|
|
8403
|
+
if (!existing) {
|
|
8404
|
+
this.set("@@OBJE", objes);
|
|
8405
|
+
}
|
|
8406
|
+
const id = this.nextObjeKey();
|
|
8407
|
+
const obje = createObje(this, id);
|
|
8408
|
+
obje.type = "OBJE";
|
|
8409
|
+
objes.item(id, obje);
|
|
8410
|
+
const version = normalizeGedcomVersion(
|
|
8411
|
+
input.gedcomVersion ?? this.getGedcomVersion()
|
|
8412
|
+
);
|
|
8413
|
+
const form = input.form || inferMediaForm(input.file);
|
|
8414
|
+
const fileNode = createCommon(this, void 0, obje);
|
|
8415
|
+
fileNode.value = input.file;
|
|
8416
|
+
if (version === "7.0") {
|
|
8417
|
+
const formNode = createCommon(
|
|
8418
|
+
this,
|
|
8419
|
+
void 0,
|
|
8420
|
+
fileNode
|
|
8421
|
+
);
|
|
8422
|
+
formNode.value = form;
|
|
8423
|
+
if (input.mediType) {
|
|
8424
|
+
formNode.set("TYPE", input.mediType);
|
|
8425
|
+
}
|
|
8426
|
+
fileNode.set("FORM", formNode);
|
|
8427
|
+
if (input.title) {
|
|
8428
|
+
fileNode.set("TITL", input.title);
|
|
8429
|
+
}
|
|
8430
|
+
obje.set("FILE", fileNode);
|
|
8431
|
+
} else {
|
|
8432
|
+
obje.set("FILE", fileNode);
|
|
8433
|
+
obje.set("FORM", form);
|
|
8434
|
+
if (input.mediType) {
|
|
8435
|
+
obje.set("MEDI", input.mediType);
|
|
8436
|
+
}
|
|
8437
|
+
if (input.title) {
|
|
8438
|
+
obje.set("TITL", input.title);
|
|
8439
|
+
}
|
|
8440
|
+
}
|
|
8441
|
+
if (input.primary) {
|
|
8442
|
+
obje.set("_PRIM", "Y");
|
|
8443
|
+
}
|
|
8444
|
+
if (normalizeGedcomVersion(
|
|
8445
|
+
input.gedcomVersion ?? this.getGedcomVersion()
|
|
8446
|
+
) === "7.0") {
|
|
8447
|
+
obje.set("UID", createGedcomUid());
|
|
8448
|
+
}
|
|
8449
|
+
return obje;
|
|
8450
|
+
}
|
|
8451
|
+
nextSnoteKey() {
|
|
8452
|
+
const ids = [];
|
|
8453
|
+
this.snotes()?.forEach((_note, id) => {
|
|
8454
|
+
ids.push(String(id));
|
|
8455
|
+
});
|
|
8456
|
+
return nextRecordId(ids, "N");
|
|
8457
|
+
}
|
|
8458
|
+
snotes() {
|
|
8459
|
+
return this.getList("@@SNOTE");
|
|
8460
|
+
}
|
|
8461
|
+
snote(index) {
|
|
8462
|
+
return this.getMain(this.snotes(), index);
|
|
8463
|
+
}
|
|
8464
|
+
/**
|
|
8465
|
+
* Create a top-level shared note record (`0 @Nn@ SNOTE` for GEDCOM 7).
|
|
8466
|
+
*/
|
|
8467
|
+
createSharedNote(text) {
|
|
8468
|
+
const existing = this.snotes();
|
|
8469
|
+
const notes = existing ?? new List();
|
|
8470
|
+
if (!existing) {
|
|
8471
|
+
this.set("@@SNOTE", notes);
|
|
8472
|
+
}
|
|
8473
|
+
const id = this.nextSnoteKey();
|
|
8474
|
+
const note = createCommonNote(this, id);
|
|
8475
|
+
note.type = "SNOTE";
|
|
8476
|
+
note.value = text;
|
|
8477
|
+
if (this.getGedcomVersion() === "7.0") {
|
|
8478
|
+
note.set("UID", createGedcomUid());
|
|
8479
|
+
}
|
|
8480
|
+
notes.item(id, note);
|
|
8481
|
+
return note;
|
|
8482
|
+
}
|
|
8483
|
+
registerExtensionTag(tag, uri) {
|
|
8484
|
+
return registerExtensionTag(this, tag, uri);
|
|
8485
|
+
}
|
|
8486
|
+
getExtensionSchema() {
|
|
8487
|
+
return getExtensionSchema(this);
|
|
8488
|
+
}
|
|
8489
|
+
ensureExtensionSchema(extraTags) {
|
|
8490
|
+
ensureExtensionSchema(this, extraTags);
|
|
8491
|
+
return getExtensionSchema(this);
|
|
8492
|
+
}
|
|
8493
|
+
/**
|
|
8494
|
+
* Collect multimedia descriptors via each individual's `multimedia()`.
|
|
8495
|
+
*/
|
|
8496
|
+
async collectMultimedia(options) {
|
|
8497
|
+
const people = [];
|
|
8498
|
+
if (options?.indiIds?.length) {
|
|
8499
|
+
options.indiIds.forEach((id) => {
|
|
8500
|
+
const indi = this.indi(id);
|
|
8501
|
+
if (indi) {
|
|
8502
|
+
people.push(indi);
|
|
8503
|
+
}
|
|
8504
|
+
});
|
|
8505
|
+
} else {
|
|
8506
|
+
this.indis()?.forEach((indi) => {
|
|
8507
|
+
if (indi) {
|
|
8508
|
+
people.push(indi);
|
|
8509
|
+
}
|
|
8510
|
+
});
|
|
8511
|
+
}
|
|
8512
|
+
const lists = await Promise.all(
|
|
8513
|
+
people.map((indi) => indi.multimedia(options?.namespace))
|
|
8514
|
+
);
|
|
8515
|
+
return mergeMediaLists(...lists);
|
|
8516
|
+
}
|
|
8517
|
+
/**
|
|
8518
|
+
* Serialize as GEDCOM 7 and pack a FamilySearch GEDZIP (`.gdz`).
|
|
8519
|
+
* Media bytes must be supplied by the caller (cache/fetch outside the parser).
|
|
8520
|
+
*/
|
|
8521
|
+
async toGedzip(options) {
|
|
8522
|
+
const text = this.toGedcom(void 0, 0, {
|
|
8523
|
+
...options,
|
|
8524
|
+
gedcomVersion: "7.0"
|
|
8525
|
+
});
|
|
8526
|
+
return buildGedzip(text, options?.media ?? []);
|
|
8527
|
+
}
|
|
7396
8528
|
objes() {
|
|
7397
8529
|
return this.getList("@@OBJE");
|
|
7398
8530
|
}
|
|
@@ -7477,9 +8609,52 @@ var GedCom = class extends Common {
|
|
|
7477
8609
|
});
|
|
7478
8610
|
return lists;
|
|
7479
8611
|
}
|
|
7480
|
-
|
|
8612
|
+
getGedcomVersion() {
|
|
8613
|
+
const raw = this.get("HEAD")?.get("GEDC")?.get("VERS")?.toValue();
|
|
8614
|
+
return normalizeGedcomVersion(
|
|
8615
|
+
typeof raw === "string" ? raw : void 0
|
|
8616
|
+
);
|
|
8617
|
+
}
|
|
8618
|
+
/** Rewrite HEAD.GEDC (and CHAR/FORM) for the requested export version. */
|
|
8619
|
+
applyExportVersion(version) {
|
|
8620
|
+
const head = this.get("HEAD");
|
|
8621
|
+
if (!head) {
|
|
8622
|
+
return;
|
|
8623
|
+
}
|
|
8624
|
+
this.applyGedcomSpecToHead(head, normalizeGedcomVersion(version));
|
|
8625
|
+
}
|
|
8626
|
+
applyGedcomSpecToHead(head, version) {
|
|
8627
|
+
const previousGedc = head.get("GEDC");
|
|
8628
|
+
const previousForm = previousGedc?.get("FORM")?.toValue();
|
|
8629
|
+
const previousChar = head.get("CHAR")?.toValue();
|
|
8630
|
+
head.remove("GEDC");
|
|
8631
|
+
const gedc = head.set("GEDC", "");
|
|
8632
|
+
if (!gedc) {
|
|
8633
|
+
return;
|
|
8634
|
+
}
|
|
8635
|
+
gedc.set("VERS", version);
|
|
8636
|
+
if (version === "7.0") {
|
|
8637
|
+
head.remove("CHAR");
|
|
8638
|
+
return;
|
|
8639
|
+
}
|
|
8640
|
+
gedc.set(
|
|
8641
|
+
"FORM",
|
|
8642
|
+
typeof previousForm === "string" && previousForm ? previousForm : "LINEAGE-LINKED"
|
|
8643
|
+
);
|
|
8644
|
+
if (!head.get("CHAR")?.toValue()) {
|
|
8645
|
+
head.set(
|
|
8646
|
+
"CHAR",
|
|
8647
|
+
typeof previousChar === "string" && previousChar ? previousChar : "UTF-8"
|
|
8648
|
+
);
|
|
8649
|
+
}
|
|
8650
|
+
}
|
|
8651
|
+
getDownloadHeader(gedcomVersion) {
|
|
7481
8652
|
const newHead = createCommon();
|
|
7482
8653
|
Object.assign(newHead, this.get("HEAD") ?? {});
|
|
8654
|
+
this.applyGedcomSpecToHead(
|
|
8655
|
+
newHead,
|
|
8656
|
+
gedcomVersion ?? this.getGedcomVersion()
|
|
8657
|
+
);
|
|
7483
8658
|
const existingSour = this.get("HEAD")?.get("SOUR");
|
|
7484
8659
|
const existingTreeName = existingSour?.get("_TREE")?.toValue();
|
|
7485
8660
|
const existingTreeUniqueId = existingSour?.get("_TID")?.toValue();
|
|
@@ -7526,22 +8701,45 @@ var GedCom = class extends Common {
|
|
|
7526
8701
|
}
|
|
7527
8702
|
toGedcom(tag, level, options) {
|
|
7528
8703
|
if (options?.super) {
|
|
7529
|
-
return appendGedcomTrailer(
|
|
7530
|
-
super.toGedcom(tag, level, options)
|
|
7531
|
-
);
|
|
8704
|
+
return appendGedcomTrailer(super.toGedcom(tag, level, options));
|
|
7532
8705
|
}
|
|
8706
|
+
const requestedVersion = options?.gedcomVersion;
|
|
8707
|
+
const exportVersion = requestedVersion ? normalizeGedcomVersion(requestedVersion) : this.getGedcomVersion();
|
|
8708
|
+
const exportOptions = {
|
|
8709
|
+
...options,
|
|
8710
|
+
obje: {
|
|
8711
|
+
standardize: options?.obje?.standardize ?? (requestedVersion !== void 0 || !options?.original),
|
|
8712
|
+
override: options?.obje?.override,
|
|
8713
|
+
namespace: options?.obje?.namespace
|
|
8714
|
+
}
|
|
8715
|
+
};
|
|
7533
8716
|
const newGedcom = createGedCom();
|
|
7534
8717
|
Object.assign(newGedcom, this);
|
|
7535
|
-
if (!
|
|
8718
|
+
if (!exportOptions.original) {
|
|
7536
8719
|
Object.assign(newGedcom, {
|
|
7537
|
-
HEAD: this.getDownloadHeader()
|
|
8720
|
+
HEAD: this.getDownloadHeader(exportVersion)
|
|
7538
8721
|
});
|
|
7539
8722
|
}
|
|
7540
|
-
if (
|
|
7541
|
-
const newContent = this.getIndiRelatedLists(
|
|
8723
|
+
if (exportOptions.indis?.length) {
|
|
8724
|
+
const newContent = this.getIndiRelatedLists(exportOptions.indis);
|
|
7542
8725
|
Object.assign(newGedcom, newContent);
|
|
7543
8726
|
}
|
|
7544
|
-
|
|
8727
|
+
const restoreEnums = exportVersion === "7.0" ? applyGedcom7Enumerations(newGedcom) : void 0;
|
|
8728
|
+
const restoreDates = exportVersion === "7.0" ? applyGedcom7DatePhrases(newGedcom) : void 0;
|
|
8729
|
+
const restoreMetadata = exportVersion === "7.0" ? applyGedcom7RecordMetadata(newGedcom) : void 0;
|
|
8730
|
+
const restoreSchema = exportVersion === "7.0" ? ensureExtensionSchema(newGedcom) : void 0;
|
|
8731
|
+
try {
|
|
8732
|
+
return newGedcom.toGedcom(tag, level, {
|
|
8733
|
+
...exportOptions,
|
|
8734
|
+
gedcomVersion: exportVersion,
|
|
8735
|
+
super: true
|
|
8736
|
+
});
|
|
8737
|
+
} finally {
|
|
8738
|
+
restoreSchema?.();
|
|
8739
|
+
restoreMetadata?.();
|
|
8740
|
+
restoreDates?.();
|
|
8741
|
+
restoreEnums?.();
|
|
8742
|
+
}
|
|
7545
8743
|
}
|
|
7546
8744
|
hasTag(tag) {
|
|
7547
8745
|
const tagName = typeof tag === "string" ? tag : tag?.get("NAME")?.toValue();
|
|
@@ -7985,20 +9183,6 @@ var mergeGedcoms = (targetGedcom, sourceGedcom, strategy = "id") => {
|
|
|
7985
9183
|
return mergedGedcom;
|
|
7986
9184
|
};
|
|
7987
9185
|
|
|
7988
|
-
// src/classes/objes.ts
|
|
7989
|
-
var Objects = class _Objects extends List {
|
|
7990
|
-
copy() {
|
|
7991
|
-
const newList = new _Objects();
|
|
7992
|
-
this.entries().forEach(([key, value]) => {
|
|
7993
|
-
newList.item(key, value);
|
|
7994
|
-
});
|
|
7995
|
-
return newList;
|
|
7996
|
-
}
|
|
7997
|
-
except(item) {
|
|
7998
|
-
return this.copy().delete(item);
|
|
7999
|
-
}
|
|
8000
|
-
};
|
|
8001
|
-
|
|
8002
9186
|
// src/classes/repos.ts
|
|
8003
9187
|
var Repositories = class _Repositories extends List {
|
|
8004
9188
|
copy() {
|
|
@@ -8041,144 +9225,6 @@ var Submitters = class _Submitters extends List {
|
|
|
8041
9225
|
}
|
|
8042
9226
|
};
|
|
8043
9227
|
|
|
8044
|
-
// src/classes/note.ts
|
|
8045
|
-
var CommonNote = class extends Common {
|
|
8046
|
-
constructor(gedcom, id, main, parent) {
|
|
8047
|
-
super(gedcom, id, main, parent);
|
|
8048
|
-
delete this.id;
|
|
8049
|
-
}
|
|
8050
|
-
set value(value) {
|
|
8051
|
-
const [note, ...contents] = value?.split(/\r?\n/) ?? [];
|
|
8052
|
-
this._value = note;
|
|
8053
|
-
if (contents.length) {
|
|
8054
|
-
const newContents = new List();
|
|
8055
|
-
contents.forEach((c, i) => {
|
|
8056
|
-
const newContent = createCommon(
|
|
8057
|
-
this._gedcom,
|
|
8058
|
-
void 0,
|
|
8059
|
-
this.main
|
|
8060
|
-
);
|
|
8061
|
-
newContent.id = `@U${i}@`;
|
|
8062
|
-
newContent.value = c;
|
|
8063
|
-
newContents.append(newContent);
|
|
8064
|
-
});
|
|
8065
|
-
const firstItem = newContents.index(0);
|
|
8066
|
-
if (firstItem) {
|
|
8067
|
-
if (newContents.length === 1) {
|
|
8068
|
-
this.set("CONT", firstItem);
|
|
8069
|
-
} else {
|
|
8070
|
-
this.set("CONT", newContents);
|
|
8071
|
-
}
|
|
8072
|
-
}
|
|
8073
|
-
}
|
|
8074
|
-
}
|
|
8075
|
-
get value() {
|
|
8076
|
-
const contents = this.get("CONT")?.toList().map((content) => content.value).join("\n");
|
|
8077
|
-
if (contents) {
|
|
8078
|
-
return `${this._value}
|
|
8079
|
-
${contents}`;
|
|
8080
|
-
}
|
|
8081
|
-
return this._value;
|
|
8082
|
-
}
|
|
8083
|
-
exportValue() {
|
|
8084
|
-
return this._value;
|
|
8085
|
-
}
|
|
8086
|
-
};
|
|
8087
|
-
var createCommonNote = (gedcom, id, main, parent) => {
|
|
8088
|
-
return createProxy(
|
|
8089
|
-
new CommonNote(gedcom, id, main, parent)
|
|
8090
|
-
);
|
|
8091
|
-
};
|
|
8092
|
-
|
|
8093
|
-
// src/classes/obje.ts
|
|
8094
|
-
var Obje = class extends Common {
|
|
8095
|
-
standardizeMedia(namespace, override = true, urlGetter) {
|
|
8096
|
-
if (!this._gedcom) {
|
|
8097
|
-
return this;
|
|
8098
|
-
}
|
|
8099
|
-
const rin = this?.get("RIN")?.toValue();
|
|
8100
|
-
const clone = this?.get("_CLON._OID")?.toValue();
|
|
8101
|
-
const mser = this?.get("_MSER._LKID")?.toValue();
|
|
8102
|
-
const title = this?.get("FILE.TITL")?.toValue() ?? this?.get("TITL")?.toValue() ?? "";
|
|
8103
|
-
const note = this?.get("FILE.NOTE")?.toValue() ?? this?.get("NOTE")?.toValue() ?? "";
|
|
8104
|
-
const form = this?.get("FILE.FORM")?.toValue();
|
|
8105
|
-
const file = this?.get("FILE")?.toValue();
|
|
8106
|
-
const imgId = rin || clone || mser;
|
|
8107
|
-
const url = file || namespace && urlGetter?.(namespace, imgId);
|
|
8108
|
-
if (!url) {
|
|
8109
|
-
return this;
|
|
8110
|
-
}
|
|
8111
|
-
const newObject = createObje(this._gedcom, this.id, this.main);
|
|
8112
|
-
if (!override) {
|
|
8113
|
-
Object.assign(newObject, this);
|
|
8114
|
-
}
|
|
8115
|
-
if (form) {
|
|
8116
|
-
if (typeof form === "string") {
|
|
8117
|
-
const newForm = createCommon(
|
|
8118
|
-
this._gedcom,
|
|
8119
|
-
void 0,
|
|
8120
|
-
this.main
|
|
8121
|
-
);
|
|
8122
|
-
newForm.value = form;
|
|
8123
|
-
newObject.set("FORM", newForm);
|
|
8124
|
-
} else {
|
|
8125
|
-
newObject.set("FORM", form);
|
|
8126
|
-
}
|
|
8127
|
-
}
|
|
8128
|
-
if (title) {
|
|
8129
|
-
if (typeof title === "string") {
|
|
8130
|
-
const newTitle = createCommon(
|
|
8131
|
-
this._gedcom,
|
|
8132
|
-
void 0,
|
|
8133
|
-
this.main
|
|
8134
|
-
);
|
|
8135
|
-
newTitle.value = title;
|
|
8136
|
-
newObject.set("TITL", newTitle);
|
|
8137
|
-
if (!note) {
|
|
8138
|
-
newObject.set("NOTE", newTitle);
|
|
8139
|
-
}
|
|
8140
|
-
} else {
|
|
8141
|
-
newObject.set("TITL", title);
|
|
8142
|
-
if (!note) {
|
|
8143
|
-
newObject.set("NOTE", title);
|
|
8144
|
-
}
|
|
8145
|
-
}
|
|
8146
|
-
}
|
|
8147
|
-
if (note) {
|
|
8148
|
-
if (typeof note === "string") {
|
|
8149
|
-
const newNote = createCommon(
|
|
8150
|
-
this._gedcom,
|
|
8151
|
-
void 0,
|
|
8152
|
-
this.main
|
|
8153
|
-
);
|
|
8154
|
-
newNote.value = note;
|
|
8155
|
-
newObject.set("NOTE", newNote);
|
|
8156
|
-
if (!title) {
|
|
8157
|
-
newObject.set("TITL", newNote);
|
|
8158
|
-
}
|
|
8159
|
-
} else {
|
|
8160
|
-
newObject.set("NOTE", note);
|
|
8161
|
-
if (!title) {
|
|
8162
|
-
newObject.set("TITL", note);
|
|
8163
|
-
}
|
|
8164
|
-
}
|
|
8165
|
-
}
|
|
8166
|
-
const newUrl = createCommon(this._gedcom, void 0, this.main);
|
|
8167
|
-
newUrl.value = url;
|
|
8168
|
-
newObject.set("FILE", newUrl);
|
|
8169
|
-
if (override) {
|
|
8170
|
-
Object.assign(this, newObject);
|
|
8171
|
-
return this;
|
|
8172
|
-
}
|
|
8173
|
-
return newObject;
|
|
8174
|
-
}
|
|
8175
|
-
};
|
|
8176
|
-
var createObje = (gedcom, id, main, parent) => {
|
|
8177
|
-
return createProxy(
|
|
8178
|
-
new Obje(gedcom, id, main, parent)
|
|
8179
|
-
);
|
|
8180
|
-
};
|
|
8181
|
-
|
|
8182
9228
|
// src/classes/repo.ts
|
|
8183
9229
|
var Repo = class extends Common {
|
|
8184
9230
|
};
|
|
@@ -8227,6 +9273,8 @@ var create = (gedcom, type, id, nodes) => {
|
|
|
8227
9273
|
prevNode = createIndi(gedcom, id);
|
|
8228
9274
|
} else if (convertType === "FAM") {
|
|
8229
9275
|
prevNode = createFam(gedcom, id);
|
|
9276
|
+
} else if (convertType === "SNOTE" || convertType === "NOTE") {
|
|
9277
|
+
prevNode = createCommonNote(gedcom, id);
|
|
8230
9278
|
} else {
|
|
8231
9279
|
prevNode = createCommon(gedcom, id);
|
|
8232
9280
|
}
|
|
@@ -8242,7 +9290,7 @@ var create = (gedcom, type, id, nodes) => {
|
|
|
8242
9290
|
prevNode = createObje(gedcom, void 0, mainNode, curNode);
|
|
8243
9291
|
} else if (type === "DATE") {
|
|
8244
9292
|
prevNode = createCommonDate(gedcom, void 0, mainNode, curNode);
|
|
8245
|
-
} else if (type === "NOTE") {
|
|
9293
|
+
} else if (type === "NOTE" || type === "SNOTE") {
|
|
8246
9294
|
prevNode = createCommonNote(gedcom, void 0, mainNode, curNode);
|
|
8247
9295
|
} else if (type === "NAME" && mainNode instanceof Indi) {
|
|
8248
9296
|
prevNode = createCommonName(gedcom, void 0, mainNode, curNode);
|
|
@@ -8325,6 +9373,13 @@ var GedcomTree = {
|
|
|
8325
9373
|
if (linesAcc._inHead && lineIndent === 1 && lineType === "FILE") {
|
|
8326
9374
|
linesAcc._hasFile = true;
|
|
8327
9375
|
}
|
|
9376
|
+
if (lineType.toUpperCase() === "CONC") {
|
|
9377
|
+
const last = acc[acc.length - 1];
|
|
9378
|
+
if (last !== void 0) {
|
|
9379
|
+
acc[acc.length - 1] = `${last}${lineValue}`;
|
|
9380
|
+
return acc;
|
|
9381
|
+
}
|
|
9382
|
+
}
|
|
8328
9383
|
if (lineIndent > 0 && lineIndent > prevLineIndent && lineValue && isId(lineValue)) {
|
|
8329
9384
|
const refLines = lineValue.split(/,\s*/).map((id) => line.replace(lineValue, id));
|
|
8330
9385
|
if (refLines.length > 1) {
|