@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/classes/index.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { format, isValid, parse } from 'date-fns';
|
|
2
2
|
import { debounce, set, get, uniqBy, unset, difference, intersectionBy, differenceBy } from 'lodash-es';
|
|
3
|
+
import JSZip from 'jszip';
|
|
3
4
|
|
|
4
5
|
var __defProp = Object.defineProperty;
|
|
5
6
|
var __export = (target, all) => {
|
|
@@ -479,11 +480,17 @@ var List = class _List {
|
|
|
479
480
|
const gedcom = [];
|
|
480
481
|
this.entries().forEach(([_, item]) => {
|
|
481
482
|
const validTag = getValidTag(tag);
|
|
482
|
-
const
|
|
483
|
-
const
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
483
|
+
const xref = item.id;
|
|
484
|
+
const payload = item.exportValue?.();
|
|
485
|
+
if (xref) {
|
|
486
|
+
gedcom.push(
|
|
487
|
+
`${level} ${xref} ${validTag}${payload ? ` ${payload}` : ""}`
|
|
488
|
+
);
|
|
489
|
+
} else {
|
|
490
|
+
gedcom.push(
|
|
491
|
+
`${level} ${validTag}${payload ? ` ${payload}` : ""}`
|
|
492
|
+
);
|
|
493
|
+
}
|
|
487
494
|
gedcom.push(
|
|
488
495
|
...item.toGedcomLines(
|
|
489
496
|
validTag,
|
|
@@ -741,12 +748,14 @@ var Common = class _Common {
|
|
|
741
748
|
);
|
|
742
749
|
}
|
|
743
750
|
standardizeObject(tag, options) {
|
|
744
|
-
if (tag === "OBJE" &&
|
|
751
|
+
if (tag === "OBJE" && options?.obje?.standardize && "standardizeMedia" in this) {
|
|
745
752
|
const standardize = this.standardizeMedia;
|
|
746
753
|
return standardize.call(
|
|
747
754
|
this,
|
|
748
755
|
options.obje.namespace,
|
|
749
|
-
options.obje.override
|
|
756
|
+
options.obje.override,
|
|
757
|
+
void 0,
|
|
758
|
+
options.gedcomVersion
|
|
750
759
|
);
|
|
751
760
|
}
|
|
752
761
|
}
|
|
@@ -773,7 +782,7 @@ var Common = class _Common {
|
|
|
773
782
|
if (typeof prop?.toObject === "function") {
|
|
774
783
|
if (prop instanceof _Common) {
|
|
775
784
|
json[validKey] = prop.toObject(validKey, options);
|
|
776
|
-
} else {
|
|
785
|
+
} else if (prop instanceof List) {
|
|
777
786
|
json = {
|
|
778
787
|
...json,
|
|
779
788
|
...prop.toObject(validKey, options)
|
|
@@ -831,8 +840,12 @@ var Common = class _Common {
|
|
|
831
840
|
this.standardizeObject(tag, options);
|
|
832
841
|
const validKeys = getValidKeys(this);
|
|
833
842
|
const gedcom = [];
|
|
843
|
+
const isGedcom7Export = options?.gedcomVersion === "7.0";
|
|
834
844
|
validKeys.forEach((key) => {
|
|
835
845
|
const validKey = key;
|
|
846
|
+
if (isGedcom7Export && validKey === "CONC") {
|
|
847
|
+
return;
|
|
848
|
+
}
|
|
836
849
|
const prop = this.get(validKey);
|
|
837
850
|
if (typeof prop?.toGedcomLines === "function") {
|
|
838
851
|
if (prop instanceof _Common) {
|
|
@@ -843,7 +856,7 @@ var Common = class _Common {
|
|
|
843
856
|
gedcom.push(
|
|
844
857
|
...prop.toGedcomLines(validKey, level + 1, options)
|
|
845
858
|
);
|
|
846
|
-
} else {
|
|
859
|
+
} else if (prop instanceof List) {
|
|
847
860
|
gedcom.push(
|
|
848
861
|
...prop.toGedcomLines(validKey, level, options)
|
|
849
862
|
);
|
|
@@ -3224,7 +3237,11 @@ var STANDARD_QUALIFIERS = {
|
|
|
3224
3237
|
BEF: "Bef.",
|
|
3225
3238
|
BEFORE: "Bef.",
|
|
3226
3239
|
AFT: "Aft.",
|
|
3227
|
-
AFTER: "Aft."
|
|
3240
|
+
AFTER: "Aft.",
|
|
3241
|
+
CAL: "Abt.",
|
|
3242
|
+
// calculated ≈ about for display
|
|
3243
|
+
EST: "Abt."
|
|
3244
|
+
// estimated ≈ about for display
|
|
3228
3245
|
};
|
|
3229
3246
|
var EXPORT_QUALIFIERS = {
|
|
3230
3247
|
"Abt.": "ABT",
|
|
@@ -3232,6 +3249,11 @@ var EXPORT_QUALIFIERS = {
|
|
|
3232
3249
|
"Aft.": "AFT"
|
|
3233
3250
|
};
|
|
3234
3251
|
var GEDCOM_MONTHS = /\b(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)\b/g;
|
|
3252
|
+
var CALENDAR_PREFIX = /^(?<calendar>GREGORIAN|JULIAN|FRENCH_R|HEBREW)\b\s+/i;
|
|
3253
|
+
var isGedcomDateValueForm = (value) => (
|
|
3254
|
+
// Require space/end after the token so display forms like "Abt." are not opaque.
|
|
3255
|
+
/^(FROM|TO|BET|AFT|BEF|ABT|CAL|EST|INT)(\s|$)/i.test(value) || /\bAND\b/i.test(value)
|
|
3256
|
+
);
|
|
3235
3257
|
var NOTE_MARKER = "####";
|
|
3236
3258
|
var formatDateWithComponents = (date, hasDay, hasMonth, hasYear, noteValue, baseFormat = "dd MMM yyyy", locale) => {
|
|
3237
3259
|
const hasNote = baseFormat.includes("NOTE");
|
|
@@ -3256,29 +3278,45 @@ var CommonDate = class extends Common {
|
|
|
3256
3278
|
super(gedcom, id, main, parent);
|
|
3257
3279
|
delete this.id;
|
|
3258
3280
|
}
|
|
3281
|
+
get calendar() {
|
|
3282
|
+
return this._calendar;
|
|
3283
|
+
}
|
|
3259
3284
|
set value(value) {
|
|
3260
3285
|
if (value) {
|
|
3261
|
-
const noteRegExp = /^(?<note>[a-zA-Z]+\.)/;
|
|
3262
|
-
const noteMatch = value.match(noteRegExp)?.groups;
|
|
3263
3286
|
let validValue = value;
|
|
3287
|
+
const calendarMatch = validValue.match(CALENDAR_PREFIX);
|
|
3288
|
+
if (calendarMatch?.groups?.calendar) {
|
|
3289
|
+
this._calendar = calendarMatch.groups.calendar.toUpperCase();
|
|
3290
|
+
validValue = validValue.slice(calendarMatch[0].length);
|
|
3291
|
+
} else {
|
|
3292
|
+
this._calendar = void 0;
|
|
3293
|
+
}
|
|
3294
|
+
const noteRegExp = /^(?<note>[a-zA-Z]+\.)/;
|
|
3295
|
+
const noteMatch = validValue.match(noteRegExp)?.groups;
|
|
3264
3296
|
if (noteMatch?.note) {
|
|
3265
3297
|
this.NOTE = this.NOTE || createCommon(this._gedcom, void 0, this.main);
|
|
3266
3298
|
this.NOTE.value = noteMatch?.note;
|
|
3267
|
-
validValue =
|
|
3299
|
+
validValue = validValue.replace(noteRegExp, "");
|
|
3268
3300
|
} else {
|
|
3269
|
-
const qualifierMatch =
|
|
3270
|
-
/^(?<qualifier>ABT|ABOUT|BEF|BEFORE|AFT|AFTER)\b\s*/i
|
|
3301
|
+
const qualifierMatch = validValue.match(
|
|
3302
|
+
/^(?<qualifier>ABT|ABOUT|BEF|BEFORE|AFT|AFTER|CAL|EST)\b\s*/i
|
|
3271
3303
|
);
|
|
3272
3304
|
const qualifier = qualifierMatch?.groups?.qualifier?.toUpperCase();
|
|
3273
3305
|
const note = qualifier ? STANDARD_QUALIFIERS[qualifier] : void 0;
|
|
3274
3306
|
if (note) {
|
|
3275
3307
|
this.NOTE = this.NOTE || createCommon(this._gedcom, void 0, this.main);
|
|
3276
3308
|
this.NOTE.value = note;
|
|
3277
|
-
validValue =
|
|
3309
|
+
validValue = validValue.slice(qualifierMatch[0].length);
|
|
3278
3310
|
}
|
|
3279
3311
|
}
|
|
3280
3312
|
const acceptedDate = this.isValidDateFormat(validValue);
|
|
3281
|
-
if (
|
|
3313
|
+
if (isGedcomDateValueForm(validValue.trim())) {
|
|
3314
|
+
delete this.DAY;
|
|
3315
|
+
delete this.MONTH;
|
|
3316
|
+
delete this.YEAR;
|
|
3317
|
+
this._date = void 0;
|
|
3318
|
+
this._value = value;
|
|
3319
|
+
} else if (acceptedDate) {
|
|
3282
3320
|
this.DAY = this.DAY || createCommon(this._gedcom, void 0, this.main);
|
|
3283
3321
|
this.DAY.value = format(acceptedDate, "dd");
|
|
3284
3322
|
this.MONTH = this.MONTH || createCommon(this._gedcom, void 0, this.main);
|
|
@@ -3381,6 +3419,15 @@ var CommonDate = class extends Common {
|
|
|
3381
3419
|
);
|
|
3382
3420
|
}
|
|
3383
3421
|
exportValue() {
|
|
3422
|
+
if (typeof this._value === "string") {
|
|
3423
|
+
const withoutCalendar = this._value.replace(CALENDAR_PREFIX, "");
|
|
3424
|
+
if (isGedcomDateValueForm(withoutCalendar.trim())) {
|
|
3425
|
+
return this._value.replace(
|
|
3426
|
+
/^((?:GREGORIAN|JULIAN|FRENCH_R|HEBREW)\s+)?(FROM|TO|BET|AFT|BEF|ABT|CAL|EST|INT)\b/i,
|
|
3427
|
+
(_m, cal, q) => `${cal || ""}${q.toUpperCase()}`
|
|
3428
|
+
);
|
|
3429
|
+
}
|
|
3430
|
+
}
|
|
3384
3431
|
const formatted = this.toValue("NOTE dd MMM yyyy", null);
|
|
3385
3432
|
if (!formatted) {
|
|
3386
3433
|
return formatted;
|
|
@@ -3388,10 +3435,14 @@ var CommonDate = class extends Common {
|
|
|
3388
3435
|
const note = this.NOTE?.value?.trim();
|
|
3389
3436
|
const qualifier = note ? EXPORT_QUALIFIERS[note] : void 0;
|
|
3390
3437
|
const standardized = qualifier ? formatted.replace(note, qualifier) : formatted;
|
|
3391
|
-
|
|
3438
|
+
const withMonths = standardized.replace(
|
|
3392
3439
|
GEDCOM_MONTHS,
|
|
3393
3440
|
(month) => month.toUpperCase()
|
|
3394
3441
|
);
|
|
3442
|
+
if (this._calendar && this._calendar !== "GREGORIAN") {
|
|
3443
|
+
return `${this._calendar} ${withMonths}`;
|
|
3444
|
+
}
|
|
3445
|
+
return withMonths;
|
|
3395
3446
|
}
|
|
3396
3447
|
toGedcomLines(tag, level = 0, options) {
|
|
3397
3448
|
const internal = new RegExp(
|
|
@@ -3923,6 +3974,24 @@ var addFamilyFact = (fam, input) => {
|
|
|
3923
3974
|
fillFact(gedcom, fam, event, input);
|
|
3924
3975
|
return event;
|
|
3925
3976
|
};
|
|
3977
|
+
var addNonEvent = (owner, input) => {
|
|
3978
|
+
const gedcom = owner.getGedcom();
|
|
3979
|
+
const eventType = input.event?.trim().toUpperCase();
|
|
3980
|
+
if (!gedcom || !eventType) {
|
|
3981
|
+
return void 0;
|
|
3982
|
+
}
|
|
3983
|
+
const no = createCommon(gedcom, void 0, owner);
|
|
3984
|
+
no.type = "NO";
|
|
3985
|
+
no.value = eventType;
|
|
3986
|
+
if (input.date?.trim()) {
|
|
3987
|
+
setDateOn(gedcom, owner, no, input.date);
|
|
3988
|
+
}
|
|
3989
|
+
if (input.note?.trim()) {
|
|
3990
|
+
no.set("NOTE", input.note.trim());
|
|
3991
|
+
}
|
|
3992
|
+
owner.assign("NO", no);
|
|
3993
|
+
return no;
|
|
3994
|
+
};
|
|
3926
3995
|
|
|
3927
3996
|
// src/utils/family-edit.ts
|
|
3928
3997
|
var PEDIGREE_VALUES = [
|
|
@@ -4160,16 +4229,58 @@ var getPlaces = (common, type = ["ALL" /* All */], maxLevel = 1, level = 0, main
|
|
|
4160
4229
|
});
|
|
4161
4230
|
return places;
|
|
4162
4231
|
};
|
|
4232
|
+
|
|
4233
|
+
// src/utils/local-media.ts
|
|
4234
|
+
var localMediaResolver;
|
|
4235
|
+
var isRemoteOrEmbeddedMediaUrl = (path) => {
|
|
4236
|
+
if (!path) {
|
|
4237
|
+
return false;
|
|
4238
|
+
}
|
|
4239
|
+
return path.startsWith("data:") || path.startsWith("blob:") || /^https?:\/\//i.test(path);
|
|
4240
|
+
};
|
|
4241
|
+
var resolveLocalMediaUrl = async (path) => {
|
|
4242
|
+
if (!path) {
|
|
4243
|
+
return void 0;
|
|
4244
|
+
}
|
|
4245
|
+
if (isRemoteOrEmbeddedMediaUrl(path)) {
|
|
4246
|
+
return path;
|
|
4247
|
+
}
|
|
4248
|
+
const resolved = await localMediaResolver?.(path);
|
|
4249
|
+
return resolved;
|
|
4250
|
+
};
|
|
4163
4251
|
var implemented = (type, ...args) => {
|
|
4164
4252
|
};
|
|
4165
4253
|
|
|
4166
4254
|
// src/utils/media-utils.ts
|
|
4167
4255
|
var getFileExtension = (filename) => {
|
|
4168
|
-
|
|
4169
|
-
|
|
4256
|
+
if (!filename) {
|
|
4257
|
+
return "";
|
|
4258
|
+
}
|
|
4259
|
+
if (filename.startsWith("data:")) {
|
|
4260
|
+
const mime = filename.slice(5).split(";")[0] || "";
|
|
4261
|
+
const subtype = (mime.split("/")[1] || "").toLowerCase();
|
|
4262
|
+
if (subtype === "jpeg") {
|
|
4263
|
+
return "jpg";
|
|
4264
|
+
}
|
|
4265
|
+
return subtype.split("+")[0] || "";
|
|
4266
|
+
}
|
|
4267
|
+
const withoutQuery = filename.split(/[?#]/)[0] || filename;
|
|
4268
|
+
const match = withoutQuery.match(/\.([^.]+)$/);
|
|
4269
|
+
return match ? match[1].toLowerCase() : "";
|
|
4170
4270
|
};
|
|
4171
4271
|
var isImageFormat = (format2) => {
|
|
4172
|
-
if (!format2)
|
|
4272
|
+
if (!format2) {
|
|
4273
|
+
return false;
|
|
4274
|
+
}
|
|
4275
|
+
let normalized = format2.toLowerCase().trim();
|
|
4276
|
+
if (normalized.startsWith("data:")) {
|
|
4277
|
+
normalized = getFileExtension(normalized);
|
|
4278
|
+
} else if (normalized.includes("/")) {
|
|
4279
|
+
normalized = normalized.split("/")[1]?.split("+")[0] || "";
|
|
4280
|
+
if (normalized === "jpeg") {
|
|
4281
|
+
normalized = "jpg";
|
|
4282
|
+
}
|
|
4283
|
+
}
|
|
4173
4284
|
const imageFormats = [
|
|
4174
4285
|
"jpg",
|
|
4175
4286
|
"jpeg",
|
|
@@ -4181,7 +4292,11 @@ var isImageFormat = (format2) => {
|
|
|
4181
4292
|
"tiff",
|
|
4182
4293
|
"tif"
|
|
4183
4294
|
];
|
|
4184
|
-
return imageFormats.includes(
|
|
4295
|
+
return imageFormats.includes(normalized);
|
|
4296
|
+
};
|
|
4297
|
+
var resolveObjeForm = (obje) => {
|
|
4298
|
+
const value = obje?.get?.("FILE.FORM")?.toValue?.() ?? obje?.get?.("FORM")?.toValue?.();
|
|
4299
|
+
return typeof value === "string" && value.trim() ? value.trim() : void 0;
|
|
4185
4300
|
};
|
|
4186
4301
|
var uniqueItemsCache = /* @__PURE__ */ new WeakMap();
|
|
4187
4302
|
var setNestedGroup = (obj, key, value, uniqueCounting = true) => {
|
|
@@ -4751,6 +4866,9 @@ var Fam = class extends Common {
|
|
|
4751
4866
|
addFact(input) {
|
|
4752
4867
|
return addFamilyFact(this, input);
|
|
4753
4868
|
}
|
|
4869
|
+
addNonEvent(input) {
|
|
4870
|
+
return addNonEvent(this, input);
|
|
4871
|
+
}
|
|
4754
4872
|
toList() {
|
|
4755
4873
|
return new Families().concat(
|
|
4756
4874
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
@@ -5441,10 +5559,14 @@ var Indi = class extends Common {
|
|
|
5441
5559
|
const clone = obje?.get("_CLON._OID")?.toValue();
|
|
5442
5560
|
const mser = obje?.get("_MSER._LKID")?.toValue();
|
|
5443
5561
|
let url = obje?.get("FILE")?.toValue();
|
|
5444
|
-
const title = obje?.get("TITL")?.toValue() ?? "";
|
|
5445
|
-
const type = obje
|
|
5446
|
-
|
|
5447
|
-
|
|
5562
|
+
const title = obje?.get("FILE.TITL")?.toValue() ?? obje?.get("TITL")?.toValue() ?? "";
|
|
5563
|
+
const type = resolveObjeForm(obje) ?? (url ? getFileExtension(url) : void 0) ?? "raw";
|
|
5564
|
+
let imgId = clone || mser;
|
|
5565
|
+
const hasEmbeddedOrLocalFile = !!url && (url.startsWith("data:") || url.startsWith("blob:") || !/^https?:\/\//i.test(url));
|
|
5566
|
+
if (!hasEmbeddedOrLocalFile && (!www || !tree || !this.id)) {
|
|
5567
|
+
return;
|
|
5568
|
+
}
|
|
5569
|
+
if (!this.id) {
|
|
5448
5570
|
return;
|
|
5449
5571
|
}
|
|
5450
5572
|
if (!namespace && !url) {
|
|
@@ -5462,13 +5584,16 @@ var Indi = class extends Common {
|
|
|
5462
5584
|
}
|
|
5463
5585
|
url = url || `https://${www}/mediaui-viewer/tree/${tree}/media/${media}`;
|
|
5464
5586
|
}
|
|
5587
|
+
if (!imgId && hasEmbeddedOrLocalFile && url) {
|
|
5588
|
+
imgId = typeof media === "string" && media || `local-${String(key).replace(/[@]/g, "")}-${getFileExtension(url) || "bin"}`;
|
|
5589
|
+
}
|
|
5465
5590
|
if (url && imgId) {
|
|
5466
|
-
const id = `${tree}-${this.id}-${imgId}`;
|
|
5591
|
+
const id = `${tree || "gedzip"}-${this.id}-${imgId}`;
|
|
5467
5592
|
list[id] = {
|
|
5468
5593
|
key,
|
|
5469
5594
|
isPrimary,
|
|
5470
5595
|
id,
|
|
5471
|
-
tree,
|
|
5596
|
+
tree: tree || "gedzip",
|
|
5472
5597
|
imgId,
|
|
5473
5598
|
person: this.id,
|
|
5474
5599
|
title,
|
|
@@ -5514,9 +5639,11 @@ var Indi = class extends Common {
|
|
|
5514
5639
|
obje.standardizeMedia();
|
|
5515
5640
|
const isPrimary = obje?.get("_PRIM")?.toValue() === "Y";
|
|
5516
5641
|
const url = obje?.get("FILE")?.toValue();
|
|
5517
|
-
const title = obje?.get("NOTE")?.toValue() ?? "";
|
|
5518
|
-
const type = obje
|
|
5519
|
-
const
|
|
5642
|
+
const title = obje?.get("FILE.NOTE")?.toValue() ?? obje?.get("NOTE")?.toValue() ?? "";
|
|
5643
|
+
const type = resolveObjeForm(obje) ?? (url ? getFileExtension(url) : void 0) ?? "raw";
|
|
5644
|
+
const photoRin = obje?.get("_PHOTO_RIN")?.toValue();
|
|
5645
|
+
const hasEmbeddedOrLocalFile = !!url && (url.startsWith("data:") || url.startsWith("blob:") || !/^https?:\/\//i.test(url));
|
|
5646
|
+
const imgId = photoRin || (hasEmbeddedOrLocalFile && url ? `local-${String(key).replace(/[@]/g, "")}-${getFileExtension(url) || "bin"}` : void 0);
|
|
5520
5647
|
if (url && imgId) {
|
|
5521
5648
|
const id = `${tree}-${this.id}-${imgId}`;
|
|
5522
5649
|
list[id] = {
|
|
@@ -5639,10 +5766,10 @@ var Indi = class extends Common {
|
|
|
5639
5766
|
const isPrimary = obje?.get("_PRIM")?.toValue() === "Y";
|
|
5640
5767
|
const url = obje?.get("FILE")?.toValue();
|
|
5641
5768
|
const title = obje?.get("TITL")?.toValue() ?? "";
|
|
5642
|
-
const type = obje
|
|
5769
|
+
const type = resolveObjeForm(obje) ?? (url ? getFileExtension(url) : void 0) ?? "raw";
|
|
5643
5770
|
if (url) {
|
|
5644
5771
|
const urlMatch = url.match(/\/([^/]+)\?hash=/);
|
|
5645
|
-
const imgId = urlMatch?.[1] || `img-${index}-${Date.now().toString(36)}
|
|
5772
|
+
const imgId = urlMatch?.[1] || (url.startsWith("data:") ? `data-${index}-${getFileExtension(url) || "bin"}` : `img-${index}-${Date.now().toString(36)}`);
|
|
5646
5773
|
const id = `geni-${geniId}-${imgId}`;
|
|
5647
5774
|
list[id] = {
|
|
5648
5775
|
isPrimary,
|
|
@@ -5679,10 +5806,10 @@ var Indi = class extends Common {
|
|
|
5679
5806
|
obje.standardizeMedia();
|
|
5680
5807
|
const isPrimary = obje?.get("_PRIM")?.toValue() === "Y";
|
|
5681
5808
|
const url = obje?.get("FILE")?.toValue();
|
|
5682
|
-
const title = obje?.get("TITL")?.toValue() ?? "";
|
|
5683
|
-
const type = obje
|
|
5809
|
+
const title = obje?.get("FILE.TITL")?.toValue() ?? obje?.get("TITL")?.toValue() ?? "";
|
|
5810
|
+
const type = resolveObjeForm(obje) ?? (url ? getFileExtension(url) : void 0) ?? "raw";
|
|
5684
5811
|
if (url) {
|
|
5685
|
-
const imgId = `media-${index}-${url.split("/").pop()?.split("?")[0]?.substring(0, 20) || Date.now().toString(36)}`;
|
|
5812
|
+
const imgId = `media-${index}-${url.startsWith("data:") ? getFileExtension(url) || "bin" : url.split("/").pop()?.split("?")[0]?.substring(0, 20) || Date.now().toString(36)}`;
|
|
5686
5813
|
const id = `${treeId}-${this.id}-${imgId}`;
|
|
5687
5814
|
list[id] = {
|
|
5688
5815
|
isPrimary,
|
|
@@ -5722,7 +5849,20 @@ var Indi = class extends Common {
|
|
|
5722
5849
|
cacheKey
|
|
5723
5850
|
);
|
|
5724
5851
|
if (cached !== void 0) {
|
|
5725
|
-
|
|
5852
|
+
if (cached?.file && !isRemoteOrEmbeddedMediaUrl(cached.file)) {
|
|
5853
|
+
const resolvedCached = await resolveLocalMediaUrl(cached.file);
|
|
5854
|
+
if (resolvedCached && isRemoteOrEmbeddedMediaUrl(resolvedCached)) {
|
|
5855
|
+
const refreshed = { ...cached, file: resolvedCached };
|
|
5856
|
+
profilePictureCache(
|
|
5857
|
+
this._gedcom,
|
|
5858
|
+
cacheKey,
|
|
5859
|
+
refreshed
|
|
5860
|
+
);
|
|
5861
|
+
return refreshed;
|
|
5862
|
+
}
|
|
5863
|
+
} else {
|
|
5864
|
+
return cached;
|
|
5865
|
+
}
|
|
5726
5866
|
}
|
|
5727
5867
|
const mediaList = await this.multimedia(namespace);
|
|
5728
5868
|
if (!mediaList) {
|
|
@@ -5734,39 +5874,40 @@ var Indi = class extends Common {
|
|
|
5734
5874
|
return void 0;
|
|
5735
5875
|
}
|
|
5736
5876
|
const mediaArray = Object.values(mediaList);
|
|
5737
|
-
const
|
|
5738
|
-
|
|
5739
|
-
|
|
5740
|
-
|
|
5741
|
-
|
|
5742
|
-
|
|
5743
|
-
|
|
5744
|
-
|
|
5745
|
-
|
|
5877
|
+
const toDisplayableProfile = async (media, isPrimary) => {
|
|
5878
|
+
const resolvedFile = await resolveLocalMediaUrl(media.url);
|
|
5879
|
+
if (!resolvedFile || !isRemoteOrEmbeddedMediaUrl(resolvedFile)) {
|
|
5880
|
+
return void 0;
|
|
5881
|
+
}
|
|
5882
|
+
return {
|
|
5883
|
+
file: resolvedFile,
|
|
5884
|
+
form: media.contentType,
|
|
5885
|
+
title: media.title,
|
|
5886
|
+
isPrimary
|
|
5746
5887
|
};
|
|
5747
|
-
|
|
5748
|
-
|
|
5749
|
-
|
|
5750
|
-
|
|
5751
|
-
|
|
5752
|
-
this._gedcom,
|
|
5753
|
-
cacheKey,
|
|
5754
|
-
void 0
|
|
5755
|
-
);
|
|
5756
|
-
return void 0;
|
|
5757
|
-
}
|
|
5758
|
-
const secondaryMedia = mediaArray.find(
|
|
5759
|
-
(media) => isImageFormat(media.contentType || getFileExtension(media.url))
|
|
5888
|
+
};
|
|
5889
|
+
const candidates = mediaArray.filter(
|
|
5890
|
+
(media) => isImageFormat(
|
|
5891
|
+
media.contentType || media.url || getFileExtension(media.url)
|
|
5892
|
+
)
|
|
5760
5893
|
);
|
|
5761
|
-
|
|
5762
|
-
|
|
5763
|
-
|
|
5764
|
-
|
|
5765
|
-
|
|
5766
|
-
|
|
5767
|
-
|
|
5768
|
-
|
|
5769
|
-
|
|
5894
|
+
const ordered = [
|
|
5895
|
+
...candidates.filter((media) => media.isPrimary),
|
|
5896
|
+
...candidates.filter((media) => !media.isPrimary)
|
|
5897
|
+
];
|
|
5898
|
+
for (const media of ordered) {
|
|
5899
|
+
if (onlyPrimary && !media.isPrimary) {
|
|
5900
|
+
break;
|
|
5901
|
+
}
|
|
5902
|
+
const result = await toDisplayableProfile(media, !!media.isPrimary);
|
|
5903
|
+
if (result) {
|
|
5904
|
+
profilePictureCache(
|
|
5905
|
+
this._gedcom,
|
|
5906
|
+
cacheKey,
|
|
5907
|
+
result
|
|
5908
|
+
);
|
|
5909
|
+
return result;
|
|
5910
|
+
}
|
|
5770
5911
|
}
|
|
5771
5912
|
profilePictureCache(
|
|
5772
5913
|
this._gedcom,
|
|
@@ -6052,9 +6193,108 @@ var Indi = class extends Common {
|
|
|
6052
6193
|
addParent(parent, pedigree) {
|
|
6053
6194
|
return parent.addChild(this, pedigree);
|
|
6054
6195
|
}
|
|
6196
|
+
/**
|
|
6197
|
+
* Link an existing top-level OBJE record to this individual (`1 OBJE @On@`).
|
|
6198
|
+
*/
|
|
6199
|
+
attachMultimedia(objeOrKey, options) {
|
|
6200
|
+
if (!this._gedcom || !this.id) {
|
|
6201
|
+
return void 0;
|
|
6202
|
+
}
|
|
6203
|
+
const obje = typeof objeOrKey === "string" ? this._gedcom.obje(objeOrKey) : objeOrKey;
|
|
6204
|
+
if (!obje?.id) {
|
|
6205
|
+
return void 0;
|
|
6206
|
+
}
|
|
6207
|
+
const already = this.get("OBJE")?.toList()?.values()?.some((item) => item?.toValue?.() === obje.id);
|
|
6208
|
+
if (!already) {
|
|
6209
|
+
const pointer = makePointer(
|
|
6210
|
+
this._gedcom,
|
|
6211
|
+
this,
|
|
6212
|
+
obje.id,
|
|
6213
|
+
"OBJE"
|
|
6214
|
+
);
|
|
6215
|
+
this.assign("OBJE", pointer);
|
|
6216
|
+
}
|
|
6217
|
+
if (options?.primary) {
|
|
6218
|
+
this.get("OBJE")?.toList()?.forEach((item) => {
|
|
6219
|
+
const target = item?.refType === "OBJE" ? this._gedcom?.obje(
|
|
6220
|
+
String(item.toValue())
|
|
6221
|
+
) : item;
|
|
6222
|
+
if (!target) {
|
|
6223
|
+
return;
|
|
6224
|
+
}
|
|
6225
|
+
if (target.id === obje.id) {
|
|
6226
|
+
target.set("_PRIM", "Y");
|
|
6227
|
+
} else if (target.get("_PRIM")?.toValue() === "Y") {
|
|
6228
|
+
target.set("_PRIM", "N");
|
|
6229
|
+
}
|
|
6230
|
+
});
|
|
6231
|
+
obje.set("_PRIM", "Y");
|
|
6232
|
+
}
|
|
6233
|
+
return obje;
|
|
6234
|
+
}
|
|
6235
|
+
detachMultimedia(objeKey) {
|
|
6236
|
+
const list = this.get("OBJE")?.toList();
|
|
6237
|
+
if (!list) {
|
|
6238
|
+
return;
|
|
6239
|
+
}
|
|
6240
|
+
const toRemove = list.values().filter(
|
|
6241
|
+
(item) => item?.toValue?.() === objeKey || item?.id === objeKey
|
|
6242
|
+
);
|
|
6243
|
+
toRemove.forEach((item) => {
|
|
6244
|
+
if (item) {
|
|
6245
|
+
list.delete(item);
|
|
6246
|
+
}
|
|
6247
|
+
});
|
|
6248
|
+
if (list.length === 0) {
|
|
6249
|
+
this.remove("OBJE");
|
|
6250
|
+
}
|
|
6251
|
+
}
|
|
6252
|
+
/**
|
|
6253
|
+
* Create a multimedia record and attach it to this person.
|
|
6254
|
+
*/
|
|
6255
|
+
attachMediaFromUrl(url, options) {
|
|
6256
|
+
if (!this._gedcom || !url) {
|
|
6257
|
+
return void 0;
|
|
6258
|
+
}
|
|
6259
|
+
const obje = this._gedcom.createMultimediaRecord({
|
|
6260
|
+
file: url,
|
|
6261
|
+
form: options?.form,
|
|
6262
|
+
title: options?.title,
|
|
6263
|
+
mediType: options?.mediType,
|
|
6264
|
+
primary: options?.primary,
|
|
6265
|
+
gedcomVersion: options?.gedcomVersion
|
|
6266
|
+
});
|
|
6267
|
+
return this.attachMultimedia(obje, { primary: options?.primary });
|
|
6268
|
+
}
|
|
6269
|
+
/**
|
|
6270
|
+
* Link a shared SNOTE record via `1 NOTE @Nn@` (GEDCOM 7).
|
|
6271
|
+
*/
|
|
6272
|
+
attachSharedNote(noteOrKey) {
|
|
6273
|
+
if (!this._gedcom || !this.id) {
|
|
6274
|
+
return void 0;
|
|
6275
|
+
}
|
|
6276
|
+
const note = typeof noteOrKey === "string" ? this._gedcom.snote(noteOrKey) : noteOrKey;
|
|
6277
|
+
if (!note?.id) {
|
|
6278
|
+
return void 0;
|
|
6279
|
+
}
|
|
6280
|
+
const already = this.get("NOTE")?.toList()?.values()?.some((item) => item?.toValue?.() === note.id);
|
|
6281
|
+
if (!already) {
|
|
6282
|
+
const pointer = makePointer(
|
|
6283
|
+
this._gedcom,
|
|
6284
|
+
this,
|
|
6285
|
+
note.id,
|
|
6286
|
+
"SNOTE"
|
|
6287
|
+
);
|
|
6288
|
+
this.assign("NOTE", pointer);
|
|
6289
|
+
}
|
|
6290
|
+
return note;
|
|
6291
|
+
}
|
|
6055
6292
|
addFact(input) {
|
|
6056
6293
|
return addIndividualFact(this, input);
|
|
6057
6294
|
}
|
|
6295
|
+
addNonEvent(input) {
|
|
6296
|
+
return addNonEvent(this, input);
|
|
6297
|
+
}
|
|
6058
6298
|
getParentType(id) {
|
|
6059
6299
|
let indi;
|
|
6060
6300
|
if (typeof id === "string" || typeof id === "number") {
|
|
@@ -6095,7 +6335,7 @@ var Indi = class extends Common {
|
|
|
6095
6335
|
if (!famChild) {
|
|
6096
6336
|
const childIndi = this._gedcom?.indi(child.id);
|
|
6097
6337
|
const childState = childIndi?.get("FAMC")?.toList()?.filter((item) => item.value === family.id).index(0);
|
|
6098
|
-
childType = childState?.get("PEDI")?.toValue() || "biological" /* BIOLOGICAL */;
|
|
6338
|
+
childType = (childState?.get("PEDI") ?? childState?.get("PEDT"))?.toValue() || "biological" /* BIOLOGICAL */;
|
|
6099
6339
|
} else {
|
|
6100
6340
|
childType = famChild.get(usedRel)?.toValue() || "biological" /* BIOLOGICAL */;
|
|
6101
6341
|
}
|
|
@@ -6656,7 +6896,7 @@ var Indi = class extends Common {
|
|
|
6656
6896
|
return;
|
|
6657
6897
|
}
|
|
6658
6898
|
const childState = child?.get("FAMC")?.toList()?.filter((item) => item.value === family.id).index(0);
|
|
6659
|
-
const childType = childState?.get("PEDI")?.toValue() || "biological" /* BIOLOGICAL */;
|
|
6899
|
+
const childType = (childState?.get("PEDI") ?? childState?.get("PEDT"))?.toValue() || "biological" /* BIOLOGICAL */;
|
|
6660
6900
|
if (childType?.toLowerCase() === filter.PEDI.toLowerCase()) {
|
|
6661
6901
|
children.append(child);
|
|
6662
6902
|
}
|
|
@@ -6764,7 +7004,7 @@ var Indi = class extends Common {
|
|
|
6764
7004
|
const child = this.id && family.CHIL?.toValueList()?.item(this.id);
|
|
6765
7005
|
if (!child) {
|
|
6766
7006
|
const childState = this?.get("FAMC")?.toList()?.filter((item) => item.value === family.id).index(0);
|
|
6767
|
-
const parentType = childState?.get("PEDI")?.toValue() || "biological" /* BIOLOGICAL */;
|
|
7007
|
+
const parentType = (childState?.get("PEDI") ?? childState?.get("PEDT"))?.toValue() || "biological" /* BIOLOGICAL */;
|
|
6768
7008
|
if (parentType?.toLowerCase() === filter.PEDI.toLowerCase()) {
|
|
6769
7009
|
parents.merge(family.getParents());
|
|
6770
7010
|
}
|
|
@@ -7156,104 +7396,851 @@ var createIndi = (gedcom, id, main, parent) => {
|
|
|
7156
7396
|
);
|
|
7157
7397
|
};
|
|
7158
7398
|
|
|
7159
|
-
//
|
|
7160
|
-
var
|
|
7161
|
-
|
|
7162
|
-
|
|
7163
|
-
|
|
7164
|
-
|
|
7165
|
-
|
|
7166
|
-
|
|
7167
|
-
var
|
|
7168
|
-
|
|
7169
|
-
|
|
7170
|
-
|
|
7171
|
-
|
|
7172
|
-
|
|
7173
|
-
|
|
7174
|
-
|
|
7175
|
-
|
|
7176
|
-
|
|
7177
|
-
|
|
7178
|
-
|
|
7179
|
-
|
|
7180
|
-
|
|
7181
|
-
|
|
7182
|
-
|
|
7183
|
-
|
|
7399
|
+
// src/utils/gedcom-version.ts
|
|
7400
|
+
var normalizeGedcomVersion = (value) => {
|
|
7401
|
+
const trimmed = value?.trim() ?? "";
|
|
7402
|
+
if (trimmed.startsWith("7")) {
|
|
7403
|
+
return "7.0";
|
|
7404
|
+
}
|
|
7405
|
+
return "5.5.1";
|
|
7406
|
+
};
|
|
7407
|
+
var GEDZIP_GEDCOM_ENTRY = "gedcom.ged";
|
|
7408
|
+
var sanitizePathSegment = (name) => name.replace(/[^a-zA-Z0-9._-]+/g, "-").replace(/^\.+/, "") || "file";
|
|
7409
|
+
var extensionFor = (contentType) => {
|
|
7410
|
+
const raw = (contentType || "bin").replace(/^\./, "").toLowerCase();
|
|
7411
|
+
if (raw.includes("/")) {
|
|
7412
|
+
return raw.split("/").pop() || "bin";
|
|
7413
|
+
}
|
|
7414
|
+
return raw || "bin";
|
|
7415
|
+
};
|
|
7416
|
+
var rewriteGedcomFilePaths = (gedcomText, urlToPath) => {
|
|
7417
|
+
const entries = urlToPath instanceof Map ? urlToPath : new Map(Object.entries(urlToPath));
|
|
7418
|
+
let text = gedcomText;
|
|
7419
|
+
entries.forEach((path, url) => {
|
|
7420
|
+
const escaped = url.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
7421
|
+
text = text.replace(
|
|
7422
|
+
new RegExp(`(^|\\r?\\n)(\\d+ FILE )${escaped}`, "g"),
|
|
7423
|
+
`$1$2${path}`
|
|
7424
|
+
);
|
|
7425
|
+
});
|
|
7426
|
+
return text;
|
|
7427
|
+
};
|
|
7428
|
+
var assignMediaPaths = (mediaFiles) => {
|
|
7429
|
+
const urlToPath = /* @__PURE__ */ new Map();
|
|
7430
|
+
const usedPaths = /* @__PURE__ */ new Set([GEDZIP_GEDCOM_ENTRY]);
|
|
7431
|
+
const files = [];
|
|
7432
|
+
for (const file of mediaFiles) {
|
|
7433
|
+
if (!file.content || !file.url) {
|
|
7434
|
+
continue;
|
|
7184
7435
|
}
|
|
7185
|
-
|
|
7186
|
-
|
|
7436
|
+
const ext = extensionFor(file.contentType);
|
|
7437
|
+
const base = sanitizePathSegment(
|
|
7438
|
+
file.imgId || file.title || file.id || "media"
|
|
7439
|
+
);
|
|
7440
|
+
let path = `media/${base}.${ext}`;
|
|
7441
|
+
let suffix = 1;
|
|
7442
|
+
while (usedPaths.has(path)) {
|
|
7443
|
+
path = `media/${base}-${suffix++}.${ext}`;
|
|
7444
|
+
}
|
|
7445
|
+
usedPaths.add(path);
|
|
7446
|
+
urlToPath.set(file.url, path);
|
|
7447
|
+
const marker = "base64,";
|
|
7448
|
+
const idx = file.content.indexOf(marker);
|
|
7449
|
+
if (idx >= 0) {
|
|
7450
|
+
files.push({
|
|
7451
|
+
path,
|
|
7452
|
+
url: file.url,
|
|
7453
|
+
content: file.content.substring(idx + marker.length),
|
|
7454
|
+
base64: true
|
|
7455
|
+
});
|
|
7456
|
+
} else {
|
|
7457
|
+
files.push({
|
|
7458
|
+
path,
|
|
7459
|
+
url: file.url,
|
|
7460
|
+
content: file.content,
|
|
7461
|
+
base64: false
|
|
7462
|
+
});
|
|
7187
7463
|
}
|
|
7188
|
-
const keys = list.keys();
|
|
7189
|
-
return list.item(keys[index]);
|
|
7190
7464
|
}
|
|
7191
|
-
|
|
7192
|
-
|
|
7465
|
+
return { urlToPath, files };
|
|
7466
|
+
};
|
|
7467
|
+
var buildGedzip = async (gedcomText, mediaFiles = []) => {
|
|
7468
|
+
const zip = new JSZip();
|
|
7469
|
+
const { urlToPath, files } = assignMediaPaths(mediaFiles);
|
|
7470
|
+
for (const file of files) {
|
|
7471
|
+
zip.file(file.path, file.content, { base64: file.base64 });
|
|
7193
7472
|
}
|
|
7194
|
-
|
|
7195
|
-
|
|
7196
|
-
|
|
7473
|
+
zip.file(GEDZIP_GEDCOM_ENTRY, rewriteGedcomFilePaths(gedcomText, urlToPath));
|
|
7474
|
+
return zip.generateAsync({ type: "uint8array" });
|
|
7475
|
+
};
|
|
7476
|
+
|
|
7477
|
+
// src/utils/gedcom7-enumerations.ts
|
|
7478
|
+
var GEDCOM7_SEX_VALUES = ["M", "F", "U", "X", "N"];
|
|
7479
|
+
var GEDCOM7_PEDI_VALUES = [
|
|
7480
|
+
"adopted",
|
|
7481
|
+
"birth",
|
|
7482
|
+
"foster",
|
|
7483
|
+
"sealing"
|
|
7484
|
+
];
|
|
7485
|
+
var GEDCOM7_ROLE_VALUES = [
|
|
7486
|
+
"CHIL",
|
|
7487
|
+
"CLERGY",
|
|
7488
|
+
"FATH",
|
|
7489
|
+
"FRIEND",
|
|
7490
|
+
"GODP",
|
|
7491
|
+
"HUSB",
|
|
7492
|
+
"MOTH",
|
|
7493
|
+
"MULTIPLE",
|
|
7494
|
+
"NGHBR",
|
|
7495
|
+
"OFFICIATOR",
|
|
7496
|
+
"OTHER",
|
|
7497
|
+
"PARENT",
|
|
7498
|
+
"SPOU",
|
|
7499
|
+
"WIFE",
|
|
7500
|
+
"WITN"
|
|
7501
|
+
];
|
|
7502
|
+
var GEDCOM7_RESN_VALUES = [
|
|
7503
|
+
"CONFIDENTIAL",
|
|
7504
|
+
"LOCKED",
|
|
7505
|
+
"PRIVACY"
|
|
7506
|
+
];
|
|
7507
|
+
var isAllowed = (value, allowed) => allowed.includes(value);
|
|
7508
|
+
var moveToPhrase = (node, phrase) => {
|
|
7509
|
+
const previousValue = node.value;
|
|
7510
|
+
const previousPhrase = node.get("PHRASE");
|
|
7511
|
+
const previousPhraseValue = previousPhrase?.toValue();
|
|
7512
|
+
node.removeValue();
|
|
7513
|
+
if (previousPhrase) {
|
|
7514
|
+
previousPhrase.value = phrase;
|
|
7515
|
+
} else {
|
|
7516
|
+
const phraseNode = createCommon(node.getGedcom(), void 0, node.main);
|
|
7517
|
+
phraseNode.value = phrase;
|
|
7518
|
+
node.set("PHRASE", phraseNode);
|
|
7519
|
+
}
|
|
7520
|
+
return () => {
|
|
7521
|
+
if (previousValue === void 0) {
|
|
7522
|
+
node.removeValue();
|
|
7523
|
+
} else {
|
|
7524
|
+
node.value = previousValue;
|
|
7197
7525
|
}
|
|
7198
|
-
|
|
7199
|
-
|
|
7200
|
-
|
|
7201
|
-
|
|
7202
|
-
|
|
7203
|
-
|
|
7204
|
-
|
|
7526
|
+
if (previousPhrase) {
|
|
7527
|
+
previousPhrase.value = previousPhraseValue;
|
|
7528
|
+
} else {
|
|
7529
|
+
node.remove("PHRASE");
|
|
7530
|
+
}
|
|
7531
|
+
};
|
|
7532
|
+
};
|
|
7533
|
+
var normalizeEnum = (node, allowed, mode, restores) => {
|
|
7534
|
+
const value = node?.toValue();
|
|
7535
|
+
if (!node || typeof value !== "string" || !value.trim()) {
|
|
7536
|
+
return;
|
|
7537
|
+
}
|
|
7538
|
+
const normalized = mode === "upper" ? value.trim().toUpperCase() : value.trim().toLowerCase();
|
|
7539
|
+
if (isAllowed(normalized, allowed)) {
|
|
7540
|
+
if (value !== normalized) {
|
|
7541
|
+
const previous = node.value;
|
|
7542
|
+
node.value = normalized;
|
|
7543
|
+
restores.push(() => {
|
|
7544
|
+
node.value = previous;
|
|
7205
7545
|
});
|
|
7206
|
-
return node;
|
|
7207
7546
|
}
|
|
7208
|
-
|
|
7209
|
-
|
|
7210
|
-
|
|
7547
|
+
return;
|
|
7548
|
+
}
|
|
7549
|
+
restores.push(moveToPhrase(node, value.trim()));
|
|
7550
|
+
};
|
|
7551
|
+
var applyGedcom7Enumerations = (gedcom) => {
|
|
7552
|
+
const restores = [];
|
|
7553
|
+
gedcom.indis()?.forEach((indi) => {
|
|
7554
|
+
if (!indi) return;
|
|
7555
|
+
normalizeEnum(indi.get("SEX"), GEDCOM7_SEX_VALUES, "upper", restores);
|
|
7556
|
+
normalizeEnum(indi.get("RESN"), GEDCOM7_RESN_VALUES, "upper", restores);
|
|
7557
|
+
indi.get("FAMC")?.toList()?.forEach((famc) => {
|
|
7558
|
+
normalizeEnum(
|
|
7559
|
+
famc?.get("PEDI") ?? famc?.get("PEDT"),
|
|
7560
|
+
GEDCOM7_PEDI_VALUES,
|
|
7561
|
+
"lower",
|
|
7562
|
+
restores
|
|
7563
|
+
);
|
|
7564
|
+
});
|
|
7565
|
+
indi.get("ASSO")?.toList()?.forEach((asso) => {
|
|
7566
|
+
normalizeEnum(
|
|
7567
|
+
asso?.get("ROLE"),
|
|
7568
|
+
GEDCOM7_ROLE_VALUES,
|
|
7569
|
+
"upper",
|
|
7570
|
+
restores
|
|
7571
|
+
);
|
|
7572
|
+
});
|
|
7573
|
+
});
|
|
7574
|
+
gedcom.fams()?.forEach((fam) => {
|
|
7575
|
+
if (!fam) return;
|
|
7576
|
+
normalizeEnum(fam.get("RESN"), GEDCOM7_RESN_VALUES, "upper", restores);
|
|
7577
|
+
fam.get("ASSO")?.toList()?.forEach((asso) => {
|
|
7578
|
+
normalizeEnum(
|
|
7579
|
+
asso?.get("ROLE"),
|
|
7580
|
+
GEDCOM7_ROLE_VALUES,
|
|
7581
|
+
"upper",
|
|
7582
|
+
restores
|
|
7583
|
+
);
|
|
7584
|
+
});
|
|
7585
|
+
});
|
|
7586
|
+
return () => {
|
|
7587
|
+
for (let i = restores.length - 1; i >= 0; i -= 1) {
|
|
7588
|
+
restores[i]?.();
|
|
7211
7589
|
}
|
|
7212
|
-
|
|
7213
|
-
|
|
7590
|
+
};
|
|
7591
|
+
};
|
|
7592
|
+
|
|
7593
|
+
// src/utils/gedcom7-dates.ts
|
|
7594
|
+
var GEDCOM7_CALENDARS = [
|
|
7595
|
+
"GREGORIAN",
|
|
7596
|
+
"JULIAN",
|
|
7597
|
+
"FRENCH_R",
|
|
7598
|
+
"HEBREW"
|
|
7599
|
+
];
|
|
7600
|
+
var CALENDAR_PREFIX2 = /^(?<calendar>GREGORIAN|JULIAN|FRENCH_R|HEBREW)\b\s+/i;
|
|
7601
|
+
var parseGedcom7CalendarPrefix = (value) => {
|
|
7602
|
+
const match = value.match(CALENDAR_PREFIX2);
|
|
7603
|
+
if (!match?.groups?.calendar) {
|
|
7604
|
+
return { calendar: void 0, rest: value };
|
|
7214
7605
|
}
|
|
7215
|
-
|
|
7216
|
-
|
|
7217
|
-
|
|
7218
|
-
|
|
7219
|
-
|
|
7220
|
-
|
|
7221
|
-
|
|
7222
|
-
|
|
7223
|
-
|
|
7224
|
-
|
|
7225
|
-
|
|
7226
|
-
|
|
7606
|
+
return {
|
|
7607
|
+
calendar: match.groups.calendar.toUpperCase(),
|
|
7608
|
+
rest: value.slice(match[0].length)
|
|
7609
|
+
};
|
|
7610
|
+
};
|
|
7611
|
+
var withGedcom7Calendar = (value, calendar) => {
|
|
7612
|
+
if (!calendar || calendar.toUpperCase() === "GREGORIAN") {
|
|
7613
|
+
return value;
|
|
7614
|
+
}
|
|
7615
|
+
const upper = calendar.toUpperCase();
|
|
7616
|
+
if (GEDCOM7_CALENDARS.includes(upper)) {
|
|
7617
|
+
const { rest } = parseGedcom7CalendarPrefix(value);
|
|
7618
|
+
return `${upper} ${rest}`.trim();
|
|
7619
|
+
}
|
|
7620
|
+
return value;
|
|
7621
|
+
};
|
|
7622
|
+
var applyGedcom7DatePhrases = (gedcom) => {
|
|
7623
|
+
const restores = [];
|
|
7624
|
+
const visitDate = (dateNode) => {
|
|
7625
|
+
if (!dateNode || typeof dateNode.toValue !== "function") {
|
|
7626
|
+
return;
|
|
7627
|
+
}
|
|
7628
|
+
const asDate = dateNode;
|
|
7629
|
+
const hasComponents = !!(asDate.DAY || asDate.MONTH || asDate.YEAR);
|
|
7630
|
+
const raw = dateNode.exportValue?.() ?? dateNode.toValue();
|
|
7631
|
+
if (typeof raw !== "string" || !raw.trim()) {
|
|
7632
|
+
return;
|
|
7633
|
+
}
|
|
7634
|
+
const { calendar, rest } = parseGedcom7CalendarPrefix(raw.trim());
|
|
7635
|
+
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);
|
|
7636
|
+
if (looksStructured) {
|
|
7637
|
+
if (calendar && calendar !== "GREGORIAN") {
|
|
7638
|
+
const previous = dateNode.value;
|
|
7639
|
+
const next = withGedcom7Calendar(rest, calendar);
|
|
7640
|
+
if (previous !== next) {
|
|
7641
|
+
dateNode.value = next;
|
|
7642
|
+
restores.push(() => {
|
|
7643
|
+
dateNode.value = previous;
|
|
7644
|
+
});
|
|
7227
7645
|
}
|
|
7228
|
-
return;
|
|
7229
|
-
}
|
|
7230
|
-
const tag = rawTag;
|
|
7231
|
-
if (value === void 0) {
|
|
7232
|
-
return;
|
|
7233
|
-
}
|
|
7234
|
-
if (value === null) {
|
|
7235
|
-
target.remove(tag);
|
|
7236
|
-
return;
|
|
7237
7646
|
}
|
|
7238
|
-
|
|
7239
|
-
|
|
7240
|
-
|
|
7241
|
-
|
|
7242
|
-
|
|
7243
|
-
|
|
7244
|
-
|
|
7245
|
-
|
|
7246
|
-
|
|
7247
|
-
|
|
7248
|
-
|
|
7249
|
-
|
|
7647
|
+
return;
|
|
7648
|
+
}
|
|
7649
|
+
const previousValue = dateNode.value;
|
|
7650
|
+
const previousPhrase = dateNode.get("PHRASE");
|
|
7651
|
+
const previousPhraseValue = previousPhrase?.toValue();
|
|
7652
|
+
dateNode.removeValue();
|
|
7653
|
+
if (previousPhrase) {
|
|
7654
|
+
previousPhrase.value = raw.trim();
|
|
7655
|
+
} else {
|
|
7656
|
+
const phrase = createCommon(
|
|
7657
|
+
dateNode.getGedcom(),
|
|
7658
|
+
void 0,
|
|
7659
|
+
dateNode.main
|
|
7660
|
+
);
|
|
7661
|
+
phrase.value = raw.trim();
|
|
7662
|
+
dateNode.set("PHRASE", phrase);
|
|
7663
|
+
}
|
|
7664
|
+
restores.push(() => {
|
|
7665
|
+
if (previousValue === void 0) {
|
|
7666
|
+
dateNode.removeValue();
|
|
7667
|
+
} else {
|
|
7668
|
+
dateNode.value = previousValue;
|
|
7250
7669
|
}
|
|
7251
|
-
if (
|
|
7252
|
-
|
|
7253
|
-
|
|
7254
|
-
|
|
7255
|
-
|
|
7256
|
-
|
|
7670
|
+
if (previousPhrase) {
|
|
7671
|
+
previousPhrase.value = previousPhraseValue;
|
|
7672
|
+
} else {
|
|
7673
|
+
dateNode.remove("PHRASE");
|
|
7674
|
+
}
|
|
7675
|
+
});
|
|
7676
|
+
};
|
|
7677
|
+
const walk = (node) => {
|
|
7678
|
+
if (!node) return;
|
|
7679
|
+
node.get("DATE")?.toList()?.forEach((item) => visitDate(item));
|
|
7680
|
+
node.get("SDATE")?.toList()?.forEach((item) => visitDate(item));
|
|
7681
|
+
};
|
|
7682
|
+
gedcom.indis()?.forEach((indi) => {
|
|
7683
|
+
if (!indi) return;
|
|
7684
|
+
walk(indi);
|
|
7685
|
+
[
|
|
7686
|
+
"BIRT",
|
|
7687
|
+
"DEAT",
|
|
7688
|
+
"CHR",
|
|
7689
|
+
"BAPM",
|
|
7690
|
+
"BURI",
|
|
7691
|
+
"CREM",
|
|
7692
|
+
"ADOP",
|
|
7693
|
+
"EVEN",
|
|
7694
|
+
"RESI",
|
|
7695
|
+
"OCCU",
|
|
7696
|
+
"MARR"
|
|
7697
|
+
].forEach((tag) => {
|
|
7698
|
+
indi.get(tag)?.toList()?.forEach((event) => walk(event));
|
|
7699
|
+
});
|
|
7700
|
+
});
|
|
7701
|
+
gedcom.fams()?.forEach((fam) => {
|
|
7702
|
+
if (!fam) return;
|
|
7703
|
+
["MARR", "DIV", "ENGA", "ANUL", "EVEN"].forEach((tag) => {
|
|
7704
|
+
fam.get(tag)?.toList()?.forEach((event) => walk(event));
|
|
7705
|
+
});
|
|
7706
|
+
});
|
|
7707
|
+
return () => {
|
|
7708
|
+
for (let i = restores.length - 1; i >= 0; i -= 1) {
|
|
7709
|
+
restores[i]?.();
|
|
7710
|
+
}
|
|
7711
|
+
};
|
|
7712
|
+
};
|
|
7713
|
+
|
|
7714
|
+
// src/utils/uid.ts
|
|
7715
|
+
var createGedcomUid = () => {
|
|
7716
|
+
const cryptoObj = typeof globalThis !== "undefined" ? globalThis.crypto : void 0;
|
|
7717
|
+
if (cryptoObj && typeof cryptoObj.randomUUID === "function") {
|
|
7718
|
+
return cryptoObj.randomUUID();
|
|
7719
|
+
}
|
|
7720
|
+
return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (char) => {
|
|
7721
|
+
const rand = Math.random() * 16 | 0;
|
|
7722
|
+
const value = char === "x" ? rand : rand & 3 | 8;
|
|
7723
|
+
return value.toString(16);
|
|
7724
|
+
});
|
|
7725
|
+
};
|
|
7726
|
+
|
|
7727
|
+
// src/utils/gedcom7-metadata.ts
|
|
7728
|
+
var GEDCOM_MONTHS2 = [
|
|
7729
|
+
"JAN",
|
|
7730
|
+
"FEB",
|
|
7731
|
+
"MAR",
|
|
7732
|
+
"APR",
|
|
7733
|
+
"MAY",
|
|
7734
|
+
"JUN",
|
|
7735
|
+
"JUL",
|
|
7736
|
+
"AUG",
|
|
7737
|
+
"SEP",
|
|
7738
|
+
"OCT",
|
|
7739
|
+
"NOV",
|
|
7740
|
+
"DEC"
|
|
7741
|
+
];
|
|
7742
|
+
var formatGedcom7Timestamp = (date = /* @__PURE__ */ new Date()) => {
|
|
7743
|
+
const day = String(date.getUTCDate());
|
|
7744
|
+
const month = GEDCOM_MONTHS2[date.getUTCMonth()];
|
|
7745
|
+
const year = String(date.getUTCFullYear());
|
|
7746
|
+
const hh = String(date.getUTCHours()).padStart(2, "0");
|
|
7747
|
+
const mm = String(date.getUTCMinutes()).padStart(2, "0");
|
|
7748
|
+
const ss = String(date.getUTCSeconds()).padStart(2, "0");
|
|
7749
|
+
return {
|
|
7750
|
+
date: `${day} ${month} ${year}`,
|
|
7751
|
+
time: `${hh}:${mm}:${ss}Z`
|
|
7752
|
+
};
|
|
7753
|
+
};
|
|
7754
|
+
var ensureMetaDate = (gedcom, record, tag, when, restores) => {
|
|
7755
|
+
if (record.get(tag)) {
|
|
7756
|
+
return;
|
|
7757
|
+
}
|
|
7758
|
+
const { date, time } = formatGedcom7Timestamp(when);
|
|
7759
|
+
const meta = createCommon(gedcom, void 0, record);
|
|
7760
|
+
meta.type = tag;
|
|
7761
|
+
const dateNode = createCommonDate(gedcom, void 0, record, meta);
|
|
7762
|
+
dateNode.type = "DATE";
|
|
7763
|
+
dateNode.value = date;
|
|
7764
|
+
dateNode.set("TIME", time);
|
|
7765
|
+
meta.set("DATE", dateNode);
|
|
7766
|
+
record.set(tag, meta);
|
|
7767
|
+
restores.push(() => {
|
|
7768
|
+
record.remove(tag);
|
|
7769
|
+
});
|
|
7770
|
+
};
|
|
7771
|
+
var ensureUid = (record, restores) => {
|
|
7772
|
+
const existing = record.get("UID")?.toValue();
|
|
7773
|
+
if (typeof existing === "string" && existing.trim()) {
|
|
7774
|
+
return;
|
|
7775
|
+
}
|
|
7776
|
+
const uid = createGedcomUid();
|
|
7777
|
+
record.set("UID", uid);
|
|
7778
|
+
restores.push(() => {
|
|
7779
|
+
record.remove("UID");
|
|
7780
|
+
});
|
|
7781
|
+
};
|
|
7782
|
+
var applyGedcom7RecordMetadata = (gedcom, options) => {
|
|
7783
|
+
const restores = [];
|
|
7784
|
+
const now = /* @__PURE__ */ new Date();
|
|
7785
|
+
const visit = (record) => {
|
|
7786
|
+
if (!record?.id) {
|
|
7787
|
+
return;
|
|
7788
|
+
}
|
|
7789
|
+
ensureUid(record, restores);
|
|
7790
|
+
ensureMetaDate(gedcom, record, "CREA", now, restores);
|
|
7791
|
+
ensureMetaDate(gedcom, record, "CHAN", now, restores);
|
|
7792
|
+
};
|
|
7793
|
+
gedcom.indis()?.forEach((indi) => visit(indi));
|
|
7794
|
+
gedcom.fams()?.forEach((fam) => visit(fam));
|
|
7795
|
+
gedcom.objes()?.forEach((obje) => visit(obje));
|
|
7796
|
+
gedcom.sours()?.forEach((sour) => visit(sour));
|
|
7797
|
+
gedcom.repos()?.forEach((repo) => visit(repo));
|
|
7798
|
+
gedcom.subms()?.forEach((subm) => visit(subm));
|
|
7799
|
+
gedcom.snotes()?.forEach((note) => visit(note));
|
|
7800
|
+
return () => {
|
|
7801
|
+
for (let i = restores.length - 1; i >= 0; i -= 1) {
|
|
7802
|
+
restores[i]?.();
|
|
7803
|
+
}
|
|
7804
|
+
};
|
|
7805
|
+
};
|
|
7806
|
+
|
|
7807
|
+
// src/utils/gedcom7-schema.ts
|
|
7808
|
+
var TREEVIZ_EXTENSION_BASE_URI = "https://treeviz.com/gedcom";
|
|
7809
|
+
var TREEVIZ_EXTENSION_URIS = {
|
|
7810
|
+
_ORIGHEAD: `${TREEVIZ_EXTENSION_BASE_URI}#_ORIGHEAD`,
|
|
7811
|
+
_TREE: `${TREEVIZ_EXTENSION_BASE_URI}#_TREE`,
|
|
7812
|
+
_TID: `${TREEVIZ_EXTENSION_BASE_URI}#_TID`,
|
|
7813
|
+
_PRIM: `${TREEVIZ_EXTENSION_BASE_URI}#_PRIM`,
|
|
7814
|
+
_FREL: `${TREEVIZ_EXTENSION_BASE_URI}#_FREL`,
|
|
7815
|
+
_MREL: `${TREEVIZ_EXTENSION_BASE_URI}#_MREL`,
|
|
7816
|
+
_SREL: `${TREEVIZ_EXTENSION_BASE_URI}#_SREL`,
|
|
7817
|
+
_UID: `${TREEVIZ_EXTENSION_BASE_URI}#_UID`,
|
|
7818
|
+
_WLNK: `${TREEVIZ_EXTENSION_BASE_URI}#_WLNK`,
|
|
7819
|
+
_MTTAG: `${TREEVIZ_EXTENSION_BASE_URI}#_MTTAG`,
|
|
7820
|
+
_MTCAT: `${TREEVIZ_EXTENSION_BASE_URI}#_MTCAT`,
|
|
7821
|
+
_CLON: `${TREEVIZ_EXTENSION_BASE_URI}#_CLON`,
|
|
7822
|
+
_MSER: `${TREEVIZ_EXTENSION_BASE_URI}#_MSER`,
|
|
7823
|
+
_OID: `${TREEVIZ_EXTENSION_BASE_URI}#_OID`,
|
|
7824
|
+
_LKID: `${TREEVIZ_EXTENSION_BASE_URI}#_LKID`,
|
|
7825
|
+
_PHOTO_RIN: `${TREEVIZ_EXTENSION_BASE_URI}#_PHOTO_RIN`,
|
|
7826
|
+
_EXPORTED_FROM_SITE_ID: `${TREEVIZ_EXTENSION_BASE_URI}#_EXPORTED_FROM_SITE_ID`,
|
|
7827
|
+
_FS_ID: `${TREEVIZ_EXTENSION_BASE_URI}#_FS_ID`,
|
|
7828
|
+
_FS_LINK: `${TREEVIZ_EXTENSION_BASE_URI}#_FS_LINK`,
|
|
7829
|
+
_FS_MATCH: `${TREEVIZ_EXTENSION_BASE_URI}#_FS_MATCH`,
|
|
7830
|
+
_FS_SOUR: `${TREEVIZ_EXTENSION_BASE_URI}#_FS_SOUR`,
|
|
7831
|
+
_IS_FS: `${TREEVIZ_EXTENSION_BASE_URI}#_IS_FS`,
|
|
7832
|
+
_LABEL: `${TREEVIZ_EXTENSION_BASE_URI}#_LABEL`,
|
|
7833
|
+
_MILT: `${TREEVIZ_EXTENSION_BASE_URI}#_MILT`,
|
|
7834
|
+
_MILTID: `${TREEVIZ_EXTENSION_BASE_URI}#_MILTID`,
|
|
7835
|
+
_ORIG: `${TREEVIZ_EXTENSION_BASE_URI}#_ORIG`,
|
|
7836
|
+
_ENV: `${TREEVIZ_EXTENSION_BASE_URI}#_ENV`,
|
|
7837
|
+
_TREEVIZ_SETTINGS: `${TREEVIZ_EXTENSION_BASE_URI}#_TREEVIZ_SETTINGS`,
|
|
7838
|
+
_TREEVIZ_VIEW: `${TREEVIZ_EXTENSION_BASE_URI}#_TREEVIZ_VIEW`,
|
|
7839
|
+
_TREEVIZ_DETECTIVE: `${TREEVIZ_EXTENSION_BASE_URI}#_TREEVIZ_DETECTIVE`,
|
|
7840
|
+
_TREEVIZ_DETECTIVE_STATE: `${TREEVIZ_EXTENSION_BASE_URI}#_TREEVIZ_DETECTIVE_STATE`
|
|
7841
|
+
};
|
|
7842
|
+
var parseTagDefinition = (payload) => {
|
|
7843
|
+
const trimmed = payload.trim();
|
|
7844
|
+
const space = trimmed.indexOf(" ");
|
|
7845
|
+
if (space <= 0) {
|
|
7846
|
+
return void 0;
|
|
7847
|
+
}
|
|
7848
|
+
const tag = trimmed.slice(0, space).trim();
|
|
7849
|
+
const uri = trimmed.slice(space + 1).trim();
|
|
7850
|
+
if (!tag || !uri) {
|
|
7851
|
+
return void 0;
|
|
7852
|
+
}
|
|
7853
|
+
return { tag, uri };
|
|
7854
|
+
};
|
|
7855
|
+
var getExtensionSchema = (gedcom) => {
|
|
7856
|
+
const map = /* @__PURE__ */ new Map();
|
|
7857
|
+
const schma = gedcom.get("HEAD")?.get("SCHMA");
|
|
7858
|
+
if (!schma) {
|
|
7859
|
+
return map;
|
|
7860
|
+
}
|
|
7861
|
+
schma.get("TAG")?.toList()?.forEach((tagNode) => {
|
|
7862
|
+
const payload = tagNode?.toValue();
|
|
7863
|
+
if (typeof payload !== "string") {
|
|
7864
|
+
return;
|
|
7865
|
+
}
|
|
7866
|
+
const parsed = parseTagDefinition(payload);
|
|
7867
|
+
if (parsed) {
|
|
7868
|
+
map.set(parsed.tag.toUpperCase(), parsed.uri);
|
|
7869
|
+
}
|
|
7870
|
+
});
|
|
7871
|
+
return map;
|
|
7872
|
+
};
|
|
7873
|
+
var ensureSchemaNode = (gedcom) => {
|
|
7874
|
+
const head = gedcom.get("HEAD");
|
|
7875
|
+
if (!head) {
|
|
7876
|
+
return void 0;
|
|
7877
|
+
}
|
|
7878
|
+
let schma = head.get("SCHMA");
|
|
7879
|
+
if (!schma) {
|
|
7880
|
+
schma = createCommon(gedcom, void 0, head);
|
|
7881
|
+
head.set("SCHMA", schma);
|
|
7882
|
+
}
|
|
7883
|
+
return schma;
|
|
7884
|
+
};
|
|
7885
|
+
var registerExtensionTag = (gedcom, tag, uri) => {
|
|
7886
|
+
const normalizedTag = tag.trim().toUpperCase();
|
|
7887
|
+
const normalizedUri = uri.trim();
|
|
7888
|
+
if (!normalizedTag.startsWith("_") || !normalizedUri) {
|
|
7889
|
+
return void 0;
|
|
7890
|
+
}
|
|
7891
|
+
const schma = ensureSchemaNode(gedcom);
|
|
7892
|
+
if (!schma) {
|
|
7893
|
+
return void 0;
|
|
7894
|
+
}
|
|
7895
|
+
const payload = `${normalizedTag} ${normalizedUri}`;
|
|
7896
|
+
const existingList = schma.get("TAG")?.toList();
|
|
7897
|
+
const existing = existingList?.values().find((node) => {
|
|
7898
|
+
const value = node?.toValue();
|
|
7899
|
+
return typeof value === "string" && value.trim().toUpperCase().startsWith(`${normalizedTag} `);
|
|
7900
|
+
});
|
|
7901
|
+
if (existing) {
|
|
7902
|
+
existing.value = payload;
|
|
7903
|
+
return existing;
|
|
7904
|
+
}
|
|
7905
|
+
const tagNode = createCommon(gedcom, void 0, schma);
|
|
7906
|
+
tagNode.value = payload;
|
|
7907
|
+
schma.assign("TAG", tagNode);
|
|
7908
|
+
return tagNode;
|
|
7909
|
+
};
|
|
7910
|
+
var ensureExtensionSchema = (gedcom, extraTags) => {
|
|
7911
|
+
const head = gedcom.get("HEAD");
|
|
7912
|
+
const hadSchma = !!head?.get("SCHMA");
|
|
7913
|
+
const previousPayloads = head?.get("SCHMA")?.get("TAG")?.toList()?.values().map((node) => ({
|
|
7914
|
+
node,
|
|
7915
|
+
value: node?.toValue()
|
|
7916
|
+
})) ?? [];
|
|
7917
|
+
const tags = /* @__PURE__ */ new Set([
|
|
7918
|
+
...Object.keys(TREEVIZ_EXTENSION_URIS),
|
|
7919
|
+
...(extraTags ?? []).map((tag) => tag.toUpperCase())
|
|
7920
|
+
]);
|
|
7921
|
+
tags.forEach((tag) => {
|
|
7922
|
+
const uri = TREEVIZ_EXTENSION_URIS[tag] ?? `${TREEVIZ_EXTENSION_BASE_URI}#${tag}`;
|
|
7923
|
+
if (tag.startsWith("_")) {
|
|
7924
|
+
registerExtensionTag(gedcom, tag, uri);
|
|
7925
|
+
}
|
|
7926
|
+
});
|
|
7927
|
+
return () => {
|
|
7928
|
+
if (!head) {
|
|
7929
|
+
return;
|
|
7930
|
+
}
|
|
7931
|
+
if (!hadSchma) {
|
|
7932
|
+
head.remove("SCHMA");
|
|
7933
|
+
return;
|
|
7934
|
+
}
|
|
7935
|
+
const schma = head.get("SCHMA");
|
|
7936
|
+
const list = schma?.get("TAG")?.toList();
|
|
7937
|
+
const keep = new Set(
|
|
7938
|
+
previousPayloads.map(
|
|
7939
|
+
(item) => typeof item.value === "string" ? item.value : void 0
|
|
7940
|
+
).filter((value) => !!value)
|
|
7941
|
+
);
|
|
7942
|
+
list?.values().forEach((node) => {
|
|
7943
|
+
const value = node?.toValue();
|
|
7944
|
+
if (typeof value === "string" && !keep.has(value) && node) {
|
|
7945
|
+
list.delete(node);
|
|
7946
|
+
}
|
|
7947
|
+
});
|
|
7948
|
+
previousPayloads.forEach(({ node, value }) => {
|
|
7949
|
+
if (node && value !== void 0) {
|
|
7950
|
+
node.value = value;
|
|
7951
|
+
}
|
|
7952
|
+
});
|
|
7953
|
+
};
|
|
7954
|
+
};
|
|
7955
|
+
|
|
7956
|
+
// package.json
|
|
7957
|
+
var package_default = {
|
|
7958
|
+
version: "2.1.1"};
|
|
7959
|
+
|
|
7960
|
+
// src/utils/get-product-details.ts
|
|
7961
|
+
var getVersion = () => package_default.version;
|
|
7962
|
+
|
|
7963
|
+
// src/utils/multimedia.ts
|
|
7964
|
+
var inferMediaForm = (file, fallback = "bin") => {
|
|
7965
|
+
const withoutQuery = file.split("?")[0] || file;
|
|
7966
|
+
const ext = getFileExtension(withoutQuery);
|
|
7967
|
+
if (ext) {
|
|
7968
|
+
return ext.toLowerCase() === "jpeg" ? "jpg" : ext.toLowerCase();
|
|
7969
|
+
}
|
|
7970
|
+
return fallback;
|
|
7971
|
+
};
|
|
7972
|
+
var mergeMediaLists = (...lists) => {
|
|
7973
|
+
const merged = {};
|
|
7974
|
+
for (const list of lists) {
|
|
7975
|
+
if (!list) continue;
|
|
7976
|
+
Object.assign(merged, list);
|
|
7977
|
+
}
|
|
7978
|
+
return merged;
|
|
7979
|
+
};
|
|
7980
|
+
|
|
7981
|
+
// src/classes/note.ts
|
|
7982
|
+
var CommonNote = class extends Common {
|
|
7983
|
+
constructor(gedcom, id, main, parent) {
|
|
7984
|
+
super(gedcom, id, main, parent);
|
|
7985
|
+
if (!id) {
|
|
7986
|
+
delete this.id;
|
|
7987
|
+
}
|
|
7988
|
+
}
|
|
7989
|
+
set value(value) {
|
|
7990
|
+
const [note, ...contents] = value?.split(/\r?\n/) ?? [];
|
|
7991
|
+
this._value = note;
|
|
7992
|
+
if (contents.length) {
|
|
7993
|
+
const newContents = new List();
|
|
7994
|
+
contents.forEach((c, i) => {
|
|
7995
|
+
const newContent = createCommon(
|
|
7996
|
+
this._gedcom,
|
|
7997
|
+
void 0,
|
|
7998
|
+
this.main
|
|
7999
|
+
);
|
|
8000
|
+
newContent.id = `@U${i}@`;
|
|
8001
|
+
newContent.value = c;
|
|
8002
|
+
newContents.append(newContent);
|
|
8003
|
+
});
|
|
8004
|
+
const firstItem = newContents.index(0);
|
|
8005
|
+
if (firstItem) {
|
|
8006
|
+
if (newContents.length === 1) {
|
|
8007
|
+
this.set("CONT", firstItem);
|
|
8008
|
+
} else {
|
|
8009
|
+
this.set("CONT", newContents);
|
|
8010
|
+
}
|
|
8011
|
+
}
|
|
8012
|
+
}
|
|
8013
|
+
}
|
|
8014
|
+
get value() {
|
|
8015
|
+
const contents = this.get("CONT")?.toList().map((content) => content.value).join("\n");
|
|
8016
|
+
if (contents) {
|
|
8017
|
+
return `${this._value}
|
|
8018
|
+
${contents}`;
|
|
8019
|
+
}
|
|
8020
|
+
return this._value;
|
|
8021
|
+
}
|
|
8022
|
+
exportValue() {
|
|
8023
|
+
return this._value;
|
|
8024
|
+
}
|
|
8025
|
+
};
|
|
8026
|
+
var createCommonNote = (gedcom, id, main, parent) => {
|
|
8027
|
+
return createProxy(
|
|
8028
|
+
new CommonNote(gedcom, id, main, parent)
|
|
8029
|
+
);
|
|
8030
|
+
};
|
|
8031
|
+
|
|
8032
|
+
// src/classes/obje.ts
|
|
8033
|
+
var Obje = class extends Common {
|
|
8034
|
+
standardizeMedia(namespace, override = true, urlGetter, gedcomVersion) {
|
|
8035
|
+
if (!this._gedcom) {
|
|
8036
|
+
return this;
|
|
8037
|
+
}
|
|
8038
|
+
const rin = this?.get("RIN")?.toValue();
|
|
8039
|
+
const clone = this?.get("_CLON._OID")?.toValue();
|
|
8040
|
+
const mser = this?.get("_MSER._LKID")?.toValue();
|
|
8041
|
+
const title = this?.get("FILE.TITL")?.toValue() ?? this?.get("TITL")?.toValue() ?? "";
|
|
8042
|
+
const note = this?.get("FILE.NOTE")?.toValue() ?? this?.get("NOTE")?.toValue() ?? "";
|
|
8043
|
+
const formRaw = this?.get("FILE.FORM")?.toValue() ?? this?.get("FORM")?.toValue();
|
|
8044
|
+
const mediType = this?.get("FILE.FORM.TYPE")?.toValue() ?? this?.get("FORM.TYPE")?.toValue() ?? this?.get("MEDI")?.toValue();
|
|
8045
|
+
const file = this?.get("FILE")?.toValue();
|
|
8046
|
+
const imgId = rin || clone || mser;
|
|
8047
|
+
const url = file || namespace && urlGetter?.(namespace, imgId);
|
|
8048
|
+
if (!url) {
|
|
8049
|
+
return this;
|
|
8050
|
+
}
|
|
8051
|
+
const version = normalizeGedcomVersion(
|
|
8052
|
+
gedcomVersion ?? this._gedcom.getGedcomVersion?.()
|
|
8053
|
+
);
|
|
8054
|
+
const form = formRaw || inferMediaForm(String(url));
|
|
8055
|
+
const newObject = createObje(this._gedcom, this.id, this.main);
|
|
8056
|
+
if (!override) {
|
|
8057
|
+
Object.assign(newObject, this);
|
|
8058
|
+
}
|
|
8059
|
+
const fileNode = createCommon(this._gedcom, void 0, this.main);
|
|
8060
|
+
fileNode.value = url;
|
|
8061
|
+
if (version === "7.0") {
|
|
8062
|
+
const formNode = createCommon(this._gedcom, void 0, fileNode);
|
|
8063
|
+
formNode.value = form;
|
|
8064
|
+
if (mediType) {
|
|
8065
|
+
formNode.set("TYPE", String(mediType));
|
|
8066
|
+
}
|
|
8067
|
+
fileNode.set("FORM", formNode);
|
|
8068
|
+
if (title) {
|
|
8069
|
+
fileNode.set("TITL", String(title));
|
|
8070
|
+
}
|
|
8071
|
+
if (note) {
|
|
8072
|
+
fileNode.set("NOTE", String(note));
|
|
8073
|
+
}
|
|
8074
|
+
newObject.set("FILE", fileNode);
|
|
8075
|
+
} else {
|
|
8076
|
+
newObject.set("FILE", fileNode);
|
|
8077
|
+
newObject.set("FORM", form);
|
|
8078
|
+
if (mediType) {
|
|
8079
|
+
newObject.set("MEDI", String(mediType));
|
|
8080
|
+
}
|
|
8081
|
+
if (title) {
|
|
8082
|
+
newObject.set("TITL", String(title));
|
|
8083
|
+
if (!note) {
|
|
8084
|
+
newObject.set("NOTE", String(title));
|
|
8085
|
+
}
|
|
8086
|
+
}
|
|
8087
|
+
if (note) {
|
|
8088
|
+
newObject.set("NOTE", String(note));
|
|
8089
|
+
if (!title) {
|
|
8090
|
+
newObject.set("TITL", String(note));
|
|
8091
|
+
}
|
|
8092
|
+
}
|
|
8093
|
+
}
|
|
8094
|
+
const prim = this.get("_PRIM")?.toValue();
|
|
8095
|
+
if (prim === "Y" || prim === "N") {
|
|
8096
|
+
newObject.set("_PRIM", prim);
|
|
8097
|
+
}
|
|
8098
|
+
const photoRin = this.get("_PHOTO_RIN")?.toValue();
|
|
8099
|
+
if (rin) {
|
|
8100
|
+
newObject.set("RIN", String(rin));
|
|
8101
|
+
}
|
|
8102
|
+
if (photoRin) {
|
|
8103
|
+
newObject.set("_PHOTO_RIN", String(photoRin));
|
|
8104
|
+
}
|
|
8105
|
+
const clonNode = this.get("_CLON");
|
|
8106
|
+
if (clonNode) {
|
|
8107
|
+
newObject.set("_CLON", clonNode);
|
|
8108
|
+
}
|
|
8109
|
+
const mserNode = this.get("_MSER");
|
|
8110
|
+
if (mserNode) {
|
|
8111
|
+
newObject.set("_MSER", mserNode);
|
|
8112
|
+
}
|
|
8113
|
+
const oidNode = this.get("_OID");
|
|
8114
|
+
if (oidNode && !newObject.get("_OID")) {
|
|
8115
|
+
newObject.set("_OID", oidNode);
|
|
8116
|
+
}
|
|
8117
|
+
const lkidNode = this.get("_LKID");
|
|
8118
|
+
if (lkidNode && !newObject.get("_LKID")) {
|
|
8119
|
+
newObject.set("_LKID", lkidNode);
|
|
8120
|
+
}
|
|
8121
|
+
if (override) {
|
|
8122
|
+
this.remove("FILE");
|
|
8123
|
+
this.remove("FORM");
|
|
8124
|
+
this.remove("MEDI");
|
|
8125
|
+
this.remove("TITL");
|
|
8126
|
+
this.remove("NOTE");
|
|
8127
|
+
Object.assign(this, newObject);
|
|
8128
|
+
return this;
|
|
8129
|
+
}
|
|
8130
|
+
return newObject;
|
|
8131
|
+
}
|
|
8132
|
+
};
|
|
8133
|
+
var createObje = (gedcom, id, main, parent) => {
|
|
8134
|
+
return createProxy(
|
|
8135
|
+
new Obje(gedcom, id, main, parent)
|
|
8136
|
+
);
|
|
8137
|
+
};
|
|
8138
|
+
|
|
8139
|
+
// src/classes/objes.ts
|
|
8140
|
+
var Objects = class _Objects extends List {
|
|
8141
|
+
copy() {
|
|
8142
|
+
const newList = new _Objects();
|
|
8143
|
+
this.entries().forEach(([key, value]) => {
|
|
8144
|
+
newList.item(key, value);
|
|
8145
|
+
});
|
|
8146
|
+
return newList;
|
|
8147
|
+
}
|
|
8148
|
+
except(item) {
|
|
8149
|
+
return this.copy().delete(item);
|
|
8150
|
+
}
|
|
8151
|
+
};
|
|
8152
|
+
|
|
8153
|
+
// src/classes/gedcom.ts
|
|
8154
|
+
var isObjectPatch = (value) => {
|
|
8155
|
+
return !!value && typeof value === "object" && !Array.isArray(value);
|
|
8156
|
+
};
|
|
8157
|
+
var GedCom = class extends Common {
|
|
8158
|
+
constructor() {
|
|
8159
|
+
super();
|
|
8160
|
+
this.tagMembers = {};
|
|
8161
|
+
this.reflist = {};
|
|
8162
|
+
this.refcount = 0;
|
|
8163
|
+
delete this._gedcom;
|
|
8164
|
+
delete this.id;
|
|
8165
|
+
this.removeValue();
|
|
8166
|
+
}
|
|
8167
|
+
getMain(type, index) {
|
|
8168
|
+
const list = !type || type instanceof List ? type : this.getList(type);
|
|
8169
|
+
if (!list) {
|
|
8170
|
+
return void 0;
|
|
8171
|
+
}
|
|
8172
|
+
if (typeof index === "string") {
|
|
8173
|
+
return list.item(index);
|
|
8174
|
+
}
|
|
8175
|
+
const keys = list.keys();
|
|
8176
|
+
return list.item(keys[index]);
|
|
8177
|
+
}
|
|
8178
|
+
getList(type) {
|
|
8179
|
+
return this.get(type);
|
|
8180
|
+
}
|
|
8181
|
+
createNodeFromPatchValue(value, main) {
|
|
8182
|
+
if (value === void 0 || value === null) {
|
|
8183
|
+
return void 0;
|
|
8184
|
+
}
|
|
8185
|
+
const node = createCommon(this, void 0, main);
|
|
8186
|
+
if (Array.isArray(value)) {
|
|
8187
|
+
value.forEach((item) => {
|
|
8188
|
+
const childNode = this.createNodeFromPatchValue(item, node);
|
|
8189
|
+
if (childNode) {
|
|
8190
|
+
node.assign("DATA", childNode);
|
|
8191
|
+
}
|
|
8192
|
+
});
|
|
8193
|
+
return node;
|
|
8194
|
+
}
|
|
8195
|
+
if (isObjectPatch(value)) {
|
|
8196
|
+
this.applyObjectToCommon(node, value);
|
|
8197
|
+
return node;
|
|
8198
|
+
}
|
|
8199
|
+
node.value = String(value);
|
|
8200
|
+
return node;
|
|
8201
|
+
}
|
|
8202
|
+
applyObjectToCommon(target, patch) {
|
|
8203
|
+
Object.entries(patch).forEach(([rawTag, value]) => {
|
|
8204
|
+
if (rawTag === "value") {
|
|
8205
|
+
if (value === null || value === void 0 || Array.isArray(value) || isObjectPatch(value)) {
|
|
8206
|
+
return;
|
|
8207
|
+
}
|
|
8208
|
+
target.value = String(value);
|
|
8209
|
+
return;
|
|
8210
|
+
}
|
|
8211
|
+
if (rawTag === "id") {
|
|
8212
|
+
if (typeof value === "string") {
|
|
8213
|
+
target.id = value;
|
|
8214
|
+
}
|
|
8215
|
+
return;
|
|
8216
|
+
}
|
|
8217
|
+
const tag = rawTag;
|
|
8218
|
+
if (value === void 0) {
|
|
8219
|
+
return;
|
|
8220
|
+
}
|
|
8221
|
+
if (value === null) {
|
|
8222
|
+
target.remove(tag);
|
|
8223
|
+
return;
|
|
8224
|
+
}
|
|
8225
|
+
if (Array.isArray(value)) {
|
|
8226
|
+
target.remove(tag);
|
|
8227
|
+
value.forEach((item) => {
|
|
8228
|
+
const listNode = this.createNodeFromPatchValue(
|
|
8229
|
+
item,
|
|
8230
|
+
target.main ?? this
|
|
8231
|
+
);
|
|
8232
|
+
if (listNode) {
|
|
8233
|
+
target.assign(tag, listNode);
|
|
8234
|
+
}
|
|
8235
|
+
});
|
|
8236
|
+
return;
|
|
8237
|
+
}
|
|
8238
|
+
if (isObjectPatch(value)) {
|
|
8239
|
+
const existing = target.get(tag);
|
|
8240
|
+
const objectNode = existing ?? createCommon(this, void 0, target.main ?? this);
|
|
8241
|
+
this.applyObjectToCommon(objectNode, value);
|
|
8242
|
+
target.set(tag, objectNode);
|
|
8243
|
+
return;
|
|
7257
8244
|
}
|
|
7258
8245
|
target.set(tag, String(value));
|
|
7259
8246
|
});
|
|
@@ -7381,6 +8368,9 @@ var GedCom = class extends Common {
|
|
|
7381
8368
|
const id = this.nextIndiKey();
|
|
7382
8369
|
const indi = createIndi(this, id);
|
|
7383
8370
|
indi.type = "INDI";
|
|
8371
|
+
if (this.getGedcomVersion() === "7.0") {
|
|
8372
|
+
indi.set("UID", createGedcomUid());
|
|
8373
|
+
}
|
|
7384
8374
|
indis.item(id, indi);
|
|
7385
8375
|
return indi;
|
|
7386
8376
|
}
|
|
@@ -7393,9 +8383,151 @@ var GedCom = class extends Common {
|
|
|
7393
8383
|
const id = this.nextFamKey();
|
|
7394
8384
|
const fam = createFam(this, id);
|
|
7395
8385
|
fam.type = "FAM";
|
|
8386
|
+
if (this.getGedcomVersion() === "7.0") {
|
|
8387
|
+
fam.set("UID", createGedcomUid());
|
|
8388
|
+
}
|
|
7396
8389
|
fams.item(id, fam);
|
|
7397
8390
|
return fam;
|
|
7398
8391
|
}
|
|
8392
|
+
nextObjeKey() {
|
|
8393
|
+
const ids = [];
|
|
8394
|
+
this.objes()?.forEach((_obje, id) => {
|
|
8395
|
+
ids.push(String(id));
|
|
8396
|
+
});
|
|
8397
|
+
return nextRecordId(ids, "O");
|
|
8398
|
+
}
|
|
8399
|
+
/**
|
|
8400
|
+
* Create a top-level multimedia record (`0 @On@ OBJE`) with FILE/FORM/TITL.
|
|
8401
|
+
* GEDCOM 7 uses nested `FILE → FORM [→ TYPE]`; 5.5.1 uses sibling FORM/TITL.
|
|
8402
|
+
*/
|
|
8403
|
+
createMultimediaRecord(input) {
|
|
8404
|
+
const existing = this.objes();
|
|
8405
|
+
const objes = existing ?? new Objects();
|
|
8406
|
+
if (!existing) {
|
|
8407
|
+
this.set("@@OBJE", objes);
|
|
8408
|
+
}
|
|
8409
|
+
const id = this.nextObjeKey();
|
|
8410
|
+
const obje = createObje(this, id);
|
|
8411
|
+
obje.type = "OBJE";
|
|
8412
|
+
objes.item(id, obje);
|
|
8413
|
+
const version = normalizeGedcomVersion(
|
|
8414
|
+
input.gedcomVersion ?? this.getGedcomVersion()
|
|
8415
|
+
);
|
|
8416
|
+
const form = input.form || inferMediaForm(input.file);
|
|
8417
|
+
const fileNode = createCommon(this, void 0, obje);
|
|
8418
|
+
fileNode.value = input.file;
|
|
8419
|
+
if (version === "7.0") {
|
|
8420
|
+
const formNode = createCommon(
|
|
8421
|
+
this,
|
|
8422
|
+
void 0,
|
|
8423
|
+
fileNode
|
|
8424
|
+
);
|
|
8425
|
+
formNode.value = form;
|
|
8426
|
+
if (input.mediType) {
|
|
8427
|
+
formNode.set("TYPE", input.mediType);
|
|
8428
|
+
}
|
|
8429
|
+
fileNode.set("FORM", formNode);
|
|
8430
|
+
if (input.title) {
|
|
8431
|
+
fileNode.set("TITL", input.title);
|
|
8432
|
+
}
|
|
8433
|
+
obje.set("FILE", fileNode);
|
|
8434
|
+
} else {
|
|
8435
|
+
obje.set("FILE", fileNode);
|
|
8436
|
+
obje.set("FORM", form);
|
|
8437
|
+
if (input.mediType) {
|
|
8438
|
+
obje.set("MEDI", input.mediType);
|
|
8439
|
+
}
|
|
8440
|
+
if (input.title) {
|
|
8441
|
+
obje.set("TITL", input.title);
|
|
8442
|
+
}
|
|
8443
|
+
}
|
|
8444
|
+
if (input.primary) {
|
|
8445
|
+
obje.set("_PRIM", "Y");
|
|
8446
|
+
}
|
|
8447
|
+
if (normalizeGedcomVersion(
|
|
8448
|
+
input.gedcomVersion ?? this.getGedcomVersion()
|
|
8449
|
+
) === "7.0") {
|
|
8450
|
+
obje.set("UID", createGedcomUid());
|
|
8451
|
+
}
|
|
8452
|
+
return obje;
|
|
8453
|
+
}
|
|
8454
|
+
nextSnoteKey() {
|
|
8455
|
+
const ids = [];
|
|
8456
|
+
this.snotes()?.forEach((_note, id) => {
|
|
8457
|
+
ids.push(String(id));
|
|
8458
|
+
});
|
|
8459
|
+
return nextRecordId(ids, "N");
|
|
8460
|
+
}
|
|
8461
|
+
snotes() {
|
|
8462
|
+
return this.getList("@@SNOTE");
|
|
8463
|
+
}
|
|
8464
|
+
snote(index) {
|
|
8465
|
+
return this.getMain(this.snotes(), index);
|
|
8466
|
+
}
|
|
8467
|
+
/**
|
|
8468
|
+
* Create a top-level shared note record (`0 @Nn@ SNOTE` for GEDCOM 7).
|
|
8469
|
+
*/
|
|
8470
|
+
createSharedNote(text) {
|
|
8471
|
+
const existing = this.snotes();
|
|
8472
|
+
const notes = existing ?? new List();
|
|
8473
|
+
if (!existing) {
|
|
8474
|
+
this.set("@@SNOTE", notes);
|
|
8475
|
+
}
|
|
8476
|
+
const id = this.nextSnoteKey();
|
|
8477
|
+
const note = createCommonNote(this, id);
|
|
8478
|
+
note.type = "SNOTE";
|
|
8479
|
+
note.value = text;
|
|
8480
|
+
if (this.getGedcomVersion() === "7.0") {
|
|
8481
|
+
note.set("UID", createGedcomUid());
|
|
8482
|
+
}
|
|
8483
|
+
notes.item(id, note);
|
|
8484
|
+
return note;
|
|
8485
|
+
}
|
|
8486
|
+
registerExtensionTag(tag, uri) {
|
|
8487
|
+
return registerExtensionTag(this, tag, uri);
|
|
8488
|
+
}
|
|
8489
|
+
getExtensionSchema() {
|
|
8490
|
+
return getExtensionSchema(this);
|
|
8491
|
+
}
|
|
8492
|
+
ensureExtensionSchema(extraTags) {
|
|
8493
|
+
ensureExtensionSchema(this, extraTags);
|
|
8494
|
+
return getExtensionSchema(this);
|
|
8495
|
+
}
|
|
8496
|
+
/**
|
|
8497
|
+
* Collect multimedia descriptors via each individual's `multimedia()`.
|
|
8498
|
+
*/
|
|
8499
|
+
async collectMultimedia(options) {
|
|
8500
|
+
const people = [];
|
|
8501
|
+
if (options?.indiIds?.length) {
|
|
8502
|
+
options.indiIds.forEach((id) => {
|
|
8503
|
+
const indi = this.indi(id);
|
|
8504
|
+
if (indi) {
|
|
8505
|
+
people.push(indi);
|
|
8506
|
+
}
|
|
8507
|
+
});
|
|
8508
|
+
} else {
|
|
8509
|
+
this.indis()?.forEach((indi) => {
|
|
8510
|
+
if (indi) {
|
|
8511
|
+
people.push(indi);
|
|
8512
|
+
}
|
|
8513
|
+
});
|
|
8514
|
+
}
|
|
8515
|
+
const lists = await Promise.all(
|
|
8516
|
+
people.map((indi) => indi.multimedia(options?.namespace))
|
|
8517
|
+
);
|
|
8518
|
+
return mergeMediaLists(...lists);
|
|
8519
|
+
}
|
|
8520
|
+
/**
|
|
8521
|
+
* Serialize as GEDCOM 7 and pack a FamilySearch GEDZIP (`.gdz`).
|
|
8522
|
+
* Media bytes must be supplied by the caller (cache/fetch outside the parser).
|
|
8523
|
+
*/
|
|
8524
|
+
async toGedzip(options) {
|
|
8525
|
+
const text = this.toGedcom(void 0, 0, {
|
|
8526
|
+
...options,
|
|
8527
|
+
gedcomVersion: "7.0"
|
|
8528
|
+
});
|
|
8529
|
+
return buildGedzip(text, options?.media ?? []);
|
|
8530
|
+
}
|
|
7399
8531
|
objes() {
|
|
7400
8532
|
return this.getList("@@OBJE");
|
|
7401
8533
|
}
|
|
@@ -7480,9 +8612,52 @@ var GedCom = class extends Common {
|
|
|
7480
8612
|
});
|
|
7481
8613
|
return lists;
|
|
7482
8614
|
}
|
|
7483
|
-
|
|
8615
|
+
getGedcomVersion() {
|
|
8616
|
+
const raw = this.get("HEAD")?.get("GEDC")?.get("VERS")?.toValue();
|
|
8617
|
+
return normalizeGedcomVersion(
|
|
8618
|
+
typeof raw === "string" ? raw : void 0
|
|
8619
|
+
);
|
|
8620
|
+
}
|
|
8621
|
+
/** Rewrite HEAD.GEDC (and CHAR/FORM) for the requested export version. */
|
|
8622
|
+
applyExportVersion(version) {
|
|
8623
|
+
const head = this.get("HEAD");
|
|
8624
|
+
if (!head) {
|
|
8625
|
+
return;
|
|
8626
|
+
}
|
|
8627
|
+
this.applyGedcomSpecToHead(head, normalizeGedcomVersion(version));
|
|
8628
|
+
}
|
|
8629
|
+
applyGedcomSpecToHead(head, version) {
|
|
8630
|
+
const previousGedc = head.get("GEDC");
|
|
8631
|
+
const previousForm = previousGedc?.get("FORM")?.toValue();
|
|
8632
|
+
const previousChar = head.get("CHAR")?.toValue();
|
|
8633
|
+
head.remove("GEDC");
|
|
8634
|
+
const gedc = head.set("GEDC", "");
|
|
8635
|
+
if (!gedc) {
|
|
8636
|
+
return;
|
|
8637
|
+
}
|
|
8638
|
+
gedc.set("VERS", version);
|
|
8639
|
+
if (version === "7.0") {
|
|
8640
|
+
head.remove("CHAR");
|
|
8641
|
+
return;
|
|
8642
|
+
}
|
|
8643
|
+
gedc.set(
|
|
8644
|
+
"FORM",
|
|
8645
|
+
typeof previousForm === "string" && previousForm ? previousForm : "LINEAGE-LINKED"
|
|
8646
|
+
);
|
|
8647
|
+
if (!head.get("CHAR")?.toValue()) {
|
|
8648
|
+
head.set(
|
|
8649
|
+
"CHAR",
|
|
8650
|
+
typeof previousChar === "string" && previousChar ? previousChar : "UTF-8"
|
|
8651
|
+
);
|
|
8652
|
+
}
|
|
8653
|
+
}
|
|
8654
|
+
getDownloadHeader(gedcomVersion) {
|
|
7484
8655
|
const newHead = createCommon();
|
|
7485
8656
|
Object.assign(newHead, this.get("HEAD") ?? {});
|
|
8657
|
+
this.applyGedcomSpecToHead(
|
|
8658
|
+
newHead,
|
|
8659
|
+
gedcomVersion ?? this.getGedcomVersion()
|
|
8660
|
+
);
|
|
7486
8661
|
const existingSour = this.get("HEAD")?.get("SOUR");
|
|
7487
8662
|
const existingTreeName = existingSour?.get("_TREE")?.toValue();
|
|
7488
8663
|
const existingTreeUniqueId = existingSour?.get("_TID")?.toValue();
|
|
@@ -7529,22 +8704,45 @@ var GedCom = class extends Common {
|
|
|
7529
8704
|
}
|
|
7530
8705
|
toGedcom(tag, level, options) {
|
|
7531
8706
|
if (options?.super) {
|
|
7532
|
-
return appendGedcomTrailer(
|
|
7533
|
-
super.toGedcom(tag, level, options)
|
|
7534
|
-
);
|
|
8707
|
+
return appendGedcomTrailer(super.toGedcom(tag, level, options));
|
|
7535
8708
|
}
|
|
8709
|
+
const requestedVersion = options?.gedcomVersion;
|
|
8710
|
+
const exportVersion = requestedVersion ? normalizeGedcomVersion(requestedVersion) : this.getGedcomVersion();
|
|
8711
|
+
const exportOptions = {
|
|
8712
|
+
...options,
|
|
8713
|
+
obje: {
|
|
8714
|
+
standardize: options?.obje?.standardize ?? (requestedVersion !== void 0 || !options?.original),
|
|
8715
|
+
override: options?.obje?.override,
|
|
8716
|
+
namespace: options?.obje?.namespace
|
|
8717
|
+
}
|
|
8718
|
+
};
|
|
7536
8719
|
const newGedcom = createGedCom();
|
|
7537
8720
|
Object.assign(newGedcom, this);
|
|
7538
|
-
if (!
|
|
8721
|
+
if (!exportOptions.original) {
|
|
7539
8722
|
Object.assign(newGedcom, {
|
|
7540
|
-
HEAD: this.getDownloadHeader()
|
|
8723
|
+
HEAD: this.getDownloadHeader(exportVersion)
|
|
7541
8724
|
});
|
|
7542
8725
|
}
|
|
7543
|
-
if (
|
|
7544
|
-
const newContent = this.getIndiRelatedLists(
|
|
8726
|
+
if (exportOptions.indis?.length) {
|
|
8727
|
+
const newContent = this.getIndiRelatedLists(exportOptions.indis);
|
|
7545
8728
|
Object.assign(newGedcom, newContent);
|
|
7546
8729
|
}
|
|
7547
|
-
|
|
8730
|
+
const restoreEnums = exportVersion === "7.0" ? applyGedcom7Enumerations(newGedcom) : void 0;
|
|
8731
|
+
const restoreDates = exportVersion === "7.0" ? applyGedcom7DatePhrases(newGedcom) : void 0;
|
|
8732
|
+
const restoreMetadata = exportVersion === "7.0" ? applyGedcom7RecordMetadata(newGedcom) : void 0;
|
|
8733
|
+
const restoreSchema = exportVersion === "7.0" ? ensureExtensionSchema(newGedcom) : void 0;
|
|
8734
|
+
try {
|
|
8735
|
+
return newGedcom.toGedcom(tag, level, {
|
|
8736
|
+
...exportOptions,
|
|
8737
|
+
gedcomVersion: exportVersion,
|
|
8738
|
+
super: true
|
|
8739
|
+
});
|
|
8740
|
+
} finally {
|
|
8741
|
+
restoreSchema?.();
|
|
8742
|
+
restoreMetadata?.();
|
|
8743
|
+
restoreDates?.();
|
|
8744
|
+
restoreEnums?.();
|
|
8745
|
+
}
|
|
7548
8746
|
}
|
|
7549
8747
|
hasTag(tag) {
|
|
7550
8748
|
const tagName = typeof tag === "string" ? tag : tag?.get("NAME")?.toValue();
|
|
@@ -8023,158 +9221,6 @@ var mergeGedcoms = (targetGedcom, sourceGedcom, strategy = "id") => {
|
|
|
8023
9221
|
return mergedGedcom;
|
|
8024
9222
|
};
|
|
8025
9223
|
|
|
8026
|
-
// src/classes/note.ts
|
|
8027
|
-
var CommonNote = class extends Common {
|
|
8028
|
-
constructor(gedcom, id, main, parent) {
|
|
8029
|
-
super(gedcom, id, main, parent);
|
|
8030
|
-
delete this.id;
|
|
8031
|
-
}
|
|
8032
|
-
set value(value) {
|
|
8033
|
-
const [note, ...contents] = value?.split(/\r?\n/) ?? [];
|
|
8034
|
-
this._value = note;
|
|
8035
|
-
if (contents.length) {
|
|
8036
|
-
const newContents = new List();
|
|
8037
|
-
contents.forEach((c, i) => {
|
|
8038
|
-
const newContent = createCommon(
|
|
8039
|
-
this._gedcom,
|
|
8040
|
-
void 0,
|
|
8041
|
-
this.main
|
|
8042
|
-
);
|
|
8043
|
-
newContent.id = `@U${i}@`;
|
|
8044
|
-
newContent.value = c;
|
|
8045
|
-
newContents.append(newContent);
|
|
8046
|
-
});
|
|
8047
|
-
const firstItem = newContents.index(0);
|
|
8048
|
-
if (firstItem) {
|
|
8049
|
-
if (newContents.length === 1) {
|
|
8050
|
-
this.set("CONT", firstItem);
|
|
8051
|
-
} else {
|
|
8052
|
-
this.set("CONT", newContents);
|
|
8053
|
-
}
|
|
8054
|
-
}
|
|
8055
|
-
}
|
|
8056
|
-
}
|
|
8057
|
-
get value() {
|
|
8058
|
-
const contents = this.get("CONT")?.toList().map((content) => content.value).join("\n");
|
|
8059
|
-
if (contents) {
|
|
8060
|
-
return `${this._value}
|
|
8061
|
-
${contents}`;
|
|
8062
|
-
}
|
|
8063
|
-
return this._value;
|
|
8064
|
-
}
|
|
8065
|
-
exportValue() {
|
|
8066
|
-
return this._value;
|
|
8067
|
-
}
|
|
8068
|
-
};
|
|
8069
|
-
var createCommonNote = (gedcom, id, main, parent) => {
|
|
8070
|
-
return createProxy(
|
|
8071
|
-
new CommonNote(gedcom, id, main, parent)
|
|
8072
|
-
);
|
|
8073
|
-
};
|
|
8074
|
-
|
|
8075
|
-
// src/classes/obje.ts
|
|
8076
|
-
var Obje = class extends Common {
|
|
8077
|
-
standardizeMedia(namespace, override = true, urlGetter) {
|
|
8078
|
-
if (!this._gedcom) {
|
|
8079
|
-
return this;
|
|
8080
|
-
}
|
|
8081
|
-
const rin = this?.get("RIN")?.toValue();
|
|
8082
|
-
const clone = this?.get("_CLON._OID")?.toValue();
|
|
8083
|
-
const mser = this?.get("_MSER._LKID")?.toValue();
|
|
8084
|
-
const title = this?.get("FILE.TITL")?.toValue() ?? this?.get("TITL")?.toValue() ?? "";
|
|
8085
|
-
const note = this?.get("FILE.NOTE")?.toValue() ?? this?.get("NOTE")?.toValue() ?? "";
|
|
8086
|
-
const form = this?.get("FILE.FORM")?.toValue();
|
|
8087
|
-
const file = this?.get("FILE")?.toValue();
|
|
8088
|
-
const imgId = rin || clone || mser;
|
|
8089
|
-
const url = file || namespace && urlGetter?.(namespace, imgId);
|
|
8090
|
-
if (!url) {
|
|
8091
|
-
return this;
|
|
8092
|
-
}
|
|
8093
|
-
const newObject = createObje(this._gedcom, this.id, this.main);
|
|
8094
|
-
if (!override) {
|
|
8095
|
-
Object.assign(newObject, this);
|
|
8096
|
-
}
|
|
8097
|
-
if (form) {
|
|
8098
|
-
if (typeof form === "string") {
|
|
8099
|
-
const newForm = createCommon(
|
|
8100
|
-
this._gedcom,
|
|
8101
|
-
void 0,
|
|
8102
|
-
this.main
|
|
8103
|
-
);
|
|
8104
|
-
newForm.value = form;
|
|
8105
|
-
newObject.set("FORM", newForm);
|
|
8106
|
-
} else {
|
|
8107
|
-
newObject.set("FORM", form);
|
|
8108
|
-
}
|
|
8109
|
-
}
|
|
8110
|
-
if (title) {
|
|
8111
|
-
if (typeof title === "string") {
|
|
8112
|
-
const newTitle = createCommon(
|
|
8113
|
-
this._gedcom,
|
|
8114
|
-
void 0,
|
|
8115
|
-
this.main
|
|
8116
|
-
);
|
|
8117
|
-
newTitle.value = title;
|
|
8118
|
-
newObject.set("TITL", newTitle);
|
|
8119
|
-
if (!note) {
|
|
8120
|
-
newObject.set("NOTE", newTitle);
|
|
8121
|
-
}
|
|
8122
|
-
} else {
|
|
8123
|
-
newObject.set("TITL", title);
|
|
8124
|
-
if (!note) {
|
|
8125
|
-
newObject.set("NOTE", title);
|
|
8126
|
-
}
|
|
8127
|
-
}
|
|
8128
|
-
}
|
|
8129
|
-
if (note) {
|
|
8130
|
-
if (typeof note === "string") {
|
|
8131
|
-
const newNote = createCommon(
|
|
8132
|
-
this._gedcom,
|
|
8133
|
-
void 0,
|
|
8134
|
-
this.main
|
|
8135
|
-
);
|
|
8136
|
-
newNote.value = note;
|
|
8137
|
-
newObject.set("NOTE", newNote);
|
|
8138
|
-
if (!title) {
|
|
8139
|
-
newObject.set("TITL", newNote);
|
|
8140
|
-
}
|
|
8141
|
-
} else {
|
|
8142
|
-
newObject.set("NOTE", note);
|
|
8143
|
-
if (!title) {
|
|
8144
|
-
newObject.set("TITL", note);
|
|
8145
|
-
}
|
|
8146
|
-
}
|
|
8147
|
-
}
|
|
8148
|
-
const newUrl = createCommon(this._gedcom, void 0, this.main);
|
|
8149
|
-
newUrl.value = url;
|
|
8150
|
-
newObject.set("FILE", newUrl);
|
|
8151
|
-
if (override) {
|
|
8152
|
-
Object.assign(this, newObject);
|
|
8153
|
-
return this;
|
|
8154
|
-
}
|
|
8155
|
-
return newObject;
|
|
8156
|
-
}
|
|
8157
|
-
};
|
|
8158
|
-
var createObje = (gedcom, id, main, parent) => {
|
|
8159
|
-
return createProxy(
|
|
8160
|
-
new Obje(gedcom, id, main, parent)
|
|
8161
|
-
);
|
|
8162
|
-
};
|
|
8163
|
-
|
|
8164
|
-
// src/classes/objes.ts
|
|
8165
|
-
var Objects = class _Objects extends List {
|
|
8166
|
-
copy() {
|
|
8167
|
-
const newList = new _Objects();
|
|
8168
|
-
this.entries().forEach(([key, value]) => {
|
|
8169
|
-
newList.item(key, value);
|
|
8170
|
-
});
|
|
8171
|
-
return newList;
|
|
8172
|
-
}
|
|
8173
|
-
except(item) {
|
|
8174
|
-
return this.copy().delete(item);
|
|
8175
|
-
}
|
|
8176
|
-
};
|
|
8177
|
-
|
|
8178
9224
|
// src/classes/repo.ts
|
|
8179
9225
|
var Repo = class extends Common {
|
|
8180
9226
|
};
|