@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
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../src/constants/constants.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,eAAO,MAAM,YAAY,kDAAkD,CAAC;AAE5E;;;GAGG;AAEH,eAAO,MAAM,YAAY,
|
|
1
|
+
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../src/constants/constants.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,eAAO,MAAM,YAAY,kDAAkD,CAAC;AAE5E;;;GAGG;AAEH,eAAO,MAAM,YAAY,QAC2E,CAAC;AACrG,eAAO,MAAM,QAAQ,QACiG,CAAC;AACvH,eAAO,MAAM,MAAM,QAAqB,CAAC;AACzC,eAAO,MAAM,aAAa,QAAiC,CAAC;AAC5D,eAAO,MAAM,YAAY,QAAsB,CAAC;AAEhD,8EAA8E;AAC9E,eAAO,MAAM,aAAa,cAAc,CAAC;AAEzC;;GAEG;AACH,eAAO,MAAM,qBAAqB,QAAmB,CAAC"}
|
package/dist/constants/index.js
CHANGED
|
@@ -9,8 +9,8 @@ var __export = (target, all) => {
|
|
|
9
9
|
|
|
10
10
|
// src/constants/constants.ts
|
|
11
11
|
var APP_BRANDING = "TreeViz - The Family Tree Visualiser & Editor";
|
|
12
|
-
var REF_LINE_REG = /^0 (?:(@[_a-zA-Z0-9]*@) )?(?<type>_[_A-Z][_a-zA-
|
|
13
|
-
var LINE_REG = /(?<indent>^[0-9]) (?:(@[_a-zA-Z0-9]*@) )?(?<type>_[_A-Z][_a-zA-
|
|
12
|
+
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;
|
|
13
|
+
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>.*)/;
|
|
14
14
|
var ID_REG = /^@[_a-zA-Z0-9]+@/;
|
|
15
15
|
var ID_GETTER_REG = /^(?<at>@)?(?<letter>[A-Z])?/i;
|
|
16
16
|
var ID_SPLIT_REG = /^@[_a-zA-Z0-9]+@:/;
|
|
@@ -924,11 +924,17 @@ var List = class _List {
|
|
|
924
924
|
const gedcom = [];
|
|
925
925
|
this.entries().forEach(([_, item]) => {
|
|
926
926
|
const validTag = getValidTag(tag);
|
|
927
|
-
const
|
|
928
|
-
const
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
927
|
+
const xref = item.id;
|
|
928
|
+
const payload = item.exportValue?.();
|
|
929
|
+
if (xref) {
|
|
930
|
+
gedcom.push(
|
|
931
|
+
`${level} ${xref} ${validTag}${payload ? ` ${payload}` : ""}`
|
|
932
|
+
);
|
|
933
|
+
} else {
|
|
934
|
+
gedcom.push(
|
|
935
|
+
`${level} ${validTag}${payload ? ` ${payload}` : ""}`
|
|
936
|
+
);
|
|
937
|
+
}
|
|
932
938
|
gedcom.push(
|
|
933
939
|
...item.toGedcomLines(
|
|
934
940
|
validTag,
|
|
@@ -1186,12 +1192,14 @@ var Common = class _Common {
|
|
|
1186
1192
|
);
|
|
1187
1193
|
}
|
|
1188
1194
|
standardizeObject(tag, options) {
|
|
1189
|
-
if (tag === "OBJE" &&
|
|
1195
|
+
if (tag === "OBJE" && options?.obje?.standardize && "standardizeMedia" in this) {
|
|
1190
1196
|
const standardize = this.standardizeMedia;
|
|
1191
1197
|
return standardize.call(
|
|
1192
1198
|
this,
|
|
1193
1199
|
options.obje.namespace,
|
|
1194
|
-
options.obje.override
|
|
1200
|
+
options.obje.override,
|
|
1201
|
+
void 0,
|
|
1202
|
+
options.gedcomVersion
|
|
1195
1203
|
);
|
|
1196
1204
|
}
|
|
1197
1205
|
}
|
|
@@ -1218,7 +1226,7 @@ var Common = class _Common {
|
|
|
1218
1226
|
if (typeof prop?.toObject === "function") {
|
|
1219
1227
|
if (prop instanceof _Common) {
|
|
1220
1228
|
json[validKey] = prop.toObject(validKey, options);
|
|
1221
|
-
} else {
|
|
1229
|
+
} else if (prop instanceof List) {
|
|
1222
1230
|
json = {
|
|
1223
1231
|
...json,
|
|
1224
1232
|
...prop.toObject(validKey, options)
|
|
@@ -1276,8 +1284,12 @@ var Common = class _Common {
|
|
|
1276
1284
|
this.standardizeObject(tag, options);
|
|
1277
1285
|
const validKeys = getValidKeys(this);
|
|
1278
1286
|
const gedcom = [];
|
|
1287
|
+
const isGedcom7Export = options?.gedcomVersion === "7.0";
|
|
1279
1288
|
validKeys.forEach((key) => {
|
|
1280
1289
|
const validKey = key;
|
|
1290
|
+
if (isGedcom7Export && validKey === "CONC") {
|
|
1291
|
+
return;
|
|
1292
|
+
}
|
|
1281
1293
|
const prop = this.get(validKey);
|
|
1282
1294
|
if (typeof prop?.toGedcomLines === "function") {
|
|
1283
1295
|
if (prop instanceof _Common) {
|
|
@@ -1288,7 +1300,7 @@ var Common = class _Common {
|
|
|
1288
1300
|
gedcom.push(
|
|
1289
1301
|
...prop.toGedcomLines(validKey, level + 1, options)
|
|
1290
1302
|
);
|
|
1291
|
-
} else {
|
|
1303
|
+
} else if (prop instanceof List) {
|
|
1292
1304
|
gedcom.push(
|
|
1293
1305
|
...prop.toGedcomLines(validKey, level, options)
|
|
1294
1306
|
);
|
|
@@ -1688,6 +1700,24 @@ var addFamilyFact = (fam, input) => {
|
|
|
1688
1700
|
fillFact(gedcom, fam, event, input);
|
|
1689
1701
|
return event;
|
|
1690
1702
|
};
|
|
1703
|
+
var addNonEvent = (owner, input) => {
|
|
1704
|
+
const gedcom = owner.getGedcom();
|
|
1705
|
+
const eventType = input.event?.trim().toUpperCase();
|
|
1706
|
+
if (!gedcom || !eventType) {
|
|
1707
|
+
return void 0;
|
|
1708
|
+
}
|
|
1709
|
+
const no = createCommon(gedcom, void 0, owner);
|
|
1710
|
+
no.type = "NO";
|
|
1711
|
+
no.value = eventType;
|
|
1712
|
+
if (input.date?.trim()) {
|
|
1713
|
+
setDateOn(gedcom, owner, no, input.date);
|
|
1714
|
+
}
|
|
1715
|
+
if (input.note?.trim()) {
|
|
1716
|
+
no.set("NOTE", input.note.trim());
|
|
1717
|
+
}
|
|
1718
|
+
owner.assign("NO", no);
|
|
1719
|
+
return no;
|
|
1720
|
+
};
|
|
1691
1721
|
|
|
1692
1722
|
// src/utils/family-edit.ts
|
|
1693
1723
|
var PEDIGREE_VALUES = [
|
|
@@ -1922,16 +1952,58 @@ var getPlaces = (common, type = ["ALL" /* All */], maxLevel = 1, level = 0, main
|
|
|
1922
1952
|
});
|
|
1923
1953
|
return places;
|
|
1924
1954
|
};
|
|
1955
|
+
|
|
1956
|
+
// src/utils/local-media.ts
|
|
1957
|
+
var localMediaResolver;
|
|
1958
|
+
var isRemoteOrEmbeddedMediaUrl = (path) => {
|
|
1959
|
+
if (!path) {
|
|
1960
|
+
return false;
|
|
1961
|
+
}
|
|
1962
|
+
return path.startsWith("data:") || path.startsWith("blob:") || /^https?:\/\//i.test(path);
|
|
1963
|
+
};
|
|
1964
|
+
var resolveLocalMediaUrl = async (path) => {
|
|
1965
|
+
if (!path) {
|
|
1966
|
+
return void 0;
|
|
1967
|
+
}
|
|
1968
|
+
if (isRemoteOrEmbeddedMediaUrl(path)) {
|
|
1969
|
+
return path;
|
|
1970
|
+
}
|
|
1971
|
+
const resolved = await localMediaResolver?.(path);
|
|
1972
|
+
return resolved;
|
|
1973
|
+
};
|
|
1925
1974
|
var implemented = (type, ...args) => {
|
|
1926
1975
|
};
|
|
1927
1976
|
|
|
1928
1977
|
// src/utils/media-utils.ts
|
|
1929
1978
|
var getFileExtension = (filename) => {
|
|
1930
|
-
|
|
1931
|
-
|
|
1979
|
+
if (!filename) {
|
|
1980
|
+
return "";
|
|
1981
|
+
}
|
|
1982
|
+
if (filename.startsWith("data:")) {
|
|
1983
|
+
const mime = filename.slice(5).split(";")[0] || "";
|
|
1984
|
+
const subtype = (mime.split("/")[1] || "").toLowerCase();
|
|
1985
|
+
if (subtype === "jpeg") {
|
|
1986
|
+
return "jpg";
|
|
1987
|
+
}
|
|
1988
|
+
return subtype.split("+")[0] || "";
|
|
1989
|
+
}
|
|
1990
|
+
const withoutQuery = filename.split(/[?#]/)[0] || filename;
|
|
1991
|
+
const match = withoutQuery.match(/\.([^.]+)$/);
|
|
1992
|
+
return match ? match[1].toLowerCase() : "";
|
|
1932
1993
|
};
|
|
1933
1994
|
var isImageFormat = (format2) => {
|
|
1934
|
-
if (!format2)
|
|
1995
|
+
if (!format2) {
|
|
1996
|
+
return false;
|
|
1997
|
+
}
|
|
1998
|
+
let normalized = format2.toLowerCase().trim();
|
|
1999
|
+
if (normalized.startsWith("data:")) {
|
|
2000
|
+
normalized = getFileExtension(normalized);
|
|
2001
|
+
} else if (normalized.includes("/")) {
|
|
2002
|
+
normalized = normalized.split("/")[1]?.split("+")[0] || "";
|
|
2003
|
+
if (normalized === "jpeg") {
|
|
2004
|
+
normalized = "jpg";
|
|
2005
|
+
}
|
|
2006
|
+
}
|
|
1935
2007
|
const imageFormats = [
|
|
1936
2008
|
"jpg",
|
|
1937
2009
|
"jpeg",
|
|
@@ -1943,7 +2015,11 @@ var isImageFormat = (format2) => {
|
|
|
1943
2015
|
"tiff",
|
|
1944
2016
|
"tif"
|
|
1945
2017
|
];
|
|
1946
|
-
return imageFormats.includes(
|
|
2018
|
+
return imageFormats.includes(normalized);
|
|
2019
|
+
};
|
|
2020
|
+
var resolveObjeForm = (obje) => {
|
|
2021
|
+
const value = obje?.get?.("FILE.FORM")?.toValue?.() ?? obje?.get?.("FORM")?.toValue?.();
|
|
2022
|
+
return typeof value === "string" && value.trim() ? value.trim() : void 0;
|
|
1947
2023
|
};
|
|
1948
2024
|
var uniqueItemsCache = /* @__PURE__ */ new WeakMap();
|
|
1949
2025
|
var setNestedGroup = (obj, key, value, uniqueCounting = true) => {
|
|
@@ -2513,6 +2589,9 @@ var Fam = class extends Common {
|
|
|
2513
2589
|
addFact(input) {
|
|
2514
2590
|
return addFamilyFact(this, input);
|
|
2515
2591
|
}
|
|
2592
|
+
addNonEvent(input) {
|
|
2593
|
+
return addNonEvent(this, input);
|
|
2594
|
+
}
|
|
2516
2595
|
toList() {
|
|
2517
2596
|
return new Families().concat(
|
|
2518
2597
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
@@ -3231,10 +3310,14 @@ var Indi = class extends Common {
|
|
|
3231
3310
|
const clone = obje?.get("_CLON._OID")?.toValue();
|
|
3232
3311
|
const mser = obje?.get("_MSER._LKID")?.toValue();
|
|
3233
3312
|
let url = obje?.get("FILE")?.toValue();
|
|
3234
|
-
const title = obje?.get("TITL")?.toValue() ?? "";
|
|
3235
|
-
const type = obje
|
|
3236
|
-
|
|
3237
|
-
|
|
3313
|
+
const title = obje?.get("FILE.TITL")?.toValue() ?? obje?.get("TITL")?.toValue() ?? "";
|
|
3314
|
+
const type = resolveObjeForm(obje) ?? (url ? getFileExtension(url) : void 0) ?? "raw";
|
|
3315
|
+
let imgId = clone || mser;
|
|
3316
|
+
const hasEmbeddedOrLocalFile = !!url && (url.startsWith("data:") || url.startsWith("blob:") || !/^https?:\/\//i.test(url));
|
|
3317
|
+
if (!hasEmbeddedOrLocalFile && (!www || !tree || !this.id)) {
|
|
3318
|
+
return;
|
|
3319
|
+
}
|
|
3320
|
+
if (!this.id) {
|
|
3238
3321
|
return;
|
|
3239
3322
|
}
|
|
3240
3323
|
if (!namespace && !url) {
|
|
@@ -3252,13 +3335,16 @@ var Indi = class extends Common {
|
|
|
3252
3335
|
}
|
|
3253
3336
|
url = url || `https://${www}/mediaui-viewer/tree/${tree}/media/${media}`;
|
|
3254
3337
|
}
|
|
3338
|
+
if (!imgId && hasEmbeddedOrLocalFile && url) {
|
|
3339
|
+
imgId = typeof media === "string" && media || `local-${String(key).replace(/[@]/g, "")}-${getFileExtension(url) || "bin"}`;
|
|
3340
|
+
}
|
|
3255
3341
|
if (url && imgId) {
|
|
3256
|
-
const id = `${tree}-${this.id}-${imgId}`;
|
|
3342
|
+
const id = `${tree || "gedzip"}-${this.id}-${imgId}`;
|
|
3257
3343
|
list[id] = {
|
|
3258
3344
|
key,
|
|
3259
3345
|
isPrimary,
|
|
3260
3346
|
id,
|
|
3261
|
-
tree,
|
|
3347
|
+
tree: tree || "gedzip",
|
|
3262
3348
|
imgId,
|
|
3263
3349
|
person: this.id,
|
|
3264
3350
|
title,
|
|
@@ -3304,9 +3390,11 @@ var Indi = class extends Common {
|
|
|
3304
3390
|
obje.standardizeMedia();
|
|
3305
3391
|
const isPrimary = obje?.get("_PRIM")?.toValue() === "Y";
|
|
3306
3392
|
const url = obje?.get("FILE")?.toValue();
|
|
3307
|
-
const title = obje?.get("NOTE")?.toValue() ?? "";
|
|
3308
|
-
const type = obje
|
|
3309
|
-
const
|
|
3393
|
+
const title = obje?.get("FILE.NOTE")?.toValue() ?? obje?.get("NOTE")?.toValue() ?? "";
|
|
3394
|
+
const type = resolveObjeForm(obje) ?? (url ? getFileExtension(url) : void 0) ?? "raw";
|
|
3395
|
+
const photoRin = obje?.get("_PHOTO_RIN")?.toValue();
|
|
3396
|
+
const hasEmbeddedOrLocalFile = !!url && (url.startsWith("data:") || url.startsWith("blob:") || !/^https?:\/\//i.test(url));
|
|
3397
|
+
const imgId = photoRin || (hasEmbeddedOrLocalFile && url ? `local-${String(key).replace(/[@]/g, "")}-${getFileExtension(url) || "bin"}` : void 0);
|
|
3310
3398
|
if (url && imgId) {
|
|
3311
3399
|
const id = `${tree}-${this.id}-${imgId}`;
|
|
3312
3400
|
list[id] = {
|
|
@@ -3429,10 +3517,10 @@ var Indi = class extends Common {
|
|
|
3429
3517
|
const isPrimary = obje?.get("_PRIM")?.toValue() === "Y";
|
|
3430
3518
|
const url = obje?.get("FILE")?.toValue();
|
|
3431
3519
|
const title = obje?.get("TITL")?.toValue() ?? "";
|
|
3432
|
-
const type = obje
|
|
3520
|
+
const type = resolveObjeForm(obje) ?? (url ? getFileExtension(url) : void 0) ?? "raw";
|
|
3433
3521
|
if (url) {
|
|
3434
3522
|
const urlMatch = url.match(/\/([^/]+)\?hash=/);
|
|
3435
|
-
const imgId = urlMatch?.[1] || `img-${index}-${Date.now().toString(36)}
|
|
3523
|
+
const imgId = urlMatch?.[1] || (url.startsWith("data:") ? `data-${index}-${getFileExtension(url) || "bin"}` : `img-${index}-${Date.now().toString(36)}`);
|
|
3436
3524
|
const id = `geni-${geniId}-${imgId}`;
|
|
3437
3525
|
list[id] = {
|
|
3438
3526
|
isPrimary,
|
|
@@ -3469,10 +3557,10 @@ var Indi = class extends Common {
|
|
|
3469
3557
|
obje.standardizeMedia();
|
|
3470
3558
|
const isPrimary = obje?.get("_PRIM")?.toValue() === "Y";
|
|
3471
3559
|
const url = obje?.get("FILE")?.toValue();
|
|
3472
|
-
const title = obje?.get("TITL")?.toValue() ?? "";
|
|
3473
|
-
const type = obje
|
|
3560
|
+
const title = obje?.get("FILE.TITL")?.toValue() ?? obje?.get("TITL")?.toValue() ?? "";
|
|
3561
|
+
const type = resolveObjeForm(obje) ?? (url ? getFileExtension(url) : void 0) ?? "raw";
|
|
3474
3562
|
if (url) {
|
|
3475
|
-
const imgId = `media-${index}-${url.split("/").pop()?.split("?")[0]?.substring(0, 20) || Date.now().toString(36)}`;
|
|
3563
|
+
const imgId = `media-${index}-${url.startsWith("data:") ? getFileExtension(url) || "bin" : url.split("/").pop()?.split("?")[0]?.substring(0, 20) || Date.now().toString(36)}`;
|
|
3476
3564
|
const id = `${treeId}-${this.id}-${imgId}`;
|
|
3477
3565
|
list[id] = {
|
|
3478
3566
|
isPrimary,
|
|
@@ -3512,7 +3600,20 @@ var Indi = class extends Common {
|
|
|
3512
3600
|
cacheKey
|
|
3513
3601
|
);
|
|
3514
3602
|
if (cached !== void 0) {
|
|
3515
|
-
|
|
3603
|
+
if (cached?.file && !isRemoteOrEmbeddedMediaUrl(cached.file)) {
|
|
3604
|
+
const resolvedCached = await resolveLocalMediaUrl(cached.file);
|
|
3605
|
+
if (resolvedCached && isRemoteOrEmbeddedMediaUrl(resolvedCached)) {
|
|
3606
|
+
const refreshed = { ...cached, file: resolvedCached };
|
|
3607
|
+
profilePictureCache(
|
|
3608
|
+
this._gedcom,
|
|
3609
|
+
cacheKey,
|
|
3610
|
+
refreshed
|
|
3611
|
+
);
|
|
3612
|
+
return refreshed;
|
|
3613
|
+
}
|
|
3614
|
+
} else {
|
|
3615
|
+
return cached;
|
|
3616
|
+
}
|
|
3516
3617
|
}
|
|
3517
3618
|
const mediaList = await this.multimedia(namespace);
|
|
3518
3619
|
if (!mediaList) {
|
|
@@ -3524,39 +3625,40 @@ var Indi = class extends Common {
|
|
|
3524
3625
|
return void 0;
|
|
3525
3626
|
}
|
|
3526
3627
|
const mediaArray = Object.values(mediaList);
|
|
3527
|
-
const
|
|
3528
|
-
|
|
3529
|
-
|
|
3530
|
-
|
|
3531
|
-
|
|
3532
|
-
|
|
3533
|
-
|
|
3534
|
-
|
|
3535
|
-
|
|
3628
|
+
const toDisplayableProfile = async (media, isPrimary) => {
|
|
3629
|
+
const resolvedFile = await resolveLocalMediaUrl(media.url);
|
|
3630
|
+
if (!resolvedFile || !isRemoteOrEmbeddedMediaUrl(resolvedFile)) {
|
|
3631
|
+
return void 0;
|
|
3632
|
+
}
|
|
3633
|
+
return {
|
|
3634
|
+
file: resolvedFile,
|
|
3635
|
+
form: media.contentType,
|
|
3636
|
+
title: media.title,
|
|
3637
|
+
isPrimary
|
|
3536
3638
|
};
|
|
3537
|
-
|
|
3538
|
-
|
|
3539
|
-
|
|
3540
|
-
|
|
3541
|
-
|
|
3542
|
-
this._gedcom,
|
|
3543
|
-
cacheKey,
|
|
3544
|
-
void 0
|
|
3545
|
-
);
|
|
3546
|
-
return void 0;
|
|
3547
|
-
}
|
|
3548
|
-
const secondaryMedia = mediaArray.find(
|
|
3549
|
-
(media) => isImageFormat(media.contentType || getFileExtension(media.url))
|
|
3639
|
+
};
|
|
3640
|
+
const candidates = mediaArray.filter(
|
|
3641
|
+
(media) => isImageFormat(
|
|
3642
|
+
media.contentType || media.url || getFileExtension(media.url)
|
|
3643
|
+
)
|
|
3550
3644
|
);
|
|
3551
|
-
|
|
3552
|
-
|
|
3553
|
-
|
|
3554
|
-
|
|
3555
|
-
|
|
3556
|
-
|
|
3557
|
-
|
|
3558
|
-
|
|
3559
|
-
|
|
3645
|
+
const ordered = [
|
|
3646
|
+
...candidates.filter((media) => media.isPrimary),
|
|
3647
|
+
...candidates.filter((media) => !media.isPrimary)
|
|
3648
|
+
];
|
|
3649
|
+
for (const media of ordered) {
|
|
3650
|
+
if (onlyPrimary && !media.isPrimary) {
|
|
3651
|
+
break;
|
|
3652
|
+
}
|
|
3653
|
+
const result = await toDisplayableProfile(media, !!media.isPrimary);
|
|
3654
|
+
if (result) {
|
|
3655
|
+
profilePictureCache(
|
|
3656
|
+
this._gedcom,
|
|
3657
|
+
cacheKey,
|
|
3658
|
+
result
|
|
3659
|
+
);
|
|
3660
|
+
return result;
|
|
3661
|
+
}
|
|
3560
3662
|
}
|
|
3561
3663
|
profilePictureCache(
|
|
3562
3664
|
this._gedcom,
|
|
@@ -3842,9 +3944,108 @@ var Indi = class extends Common {
|
|
|
3842
3944
|
addParent(parent, pedigree) {
|
|
3843
3945
|
return parent.addChild(this, pedigree);
|
|
3844
3946
|
}
|
|
3947
|
+
/**
|
|
3948
|
+
* Link an existing top-level OBJE record to this individual (`1 OBJE @On@`).
|
|
3949
|
+
*/
|
|
3950
|
+
attachMultimedia(objeOrKey, options) {
|
|
3951
|
+
if (!this._gedcom || !this.id) {
|
|
3952
|
+
return void 0;
|
|
3953
|
+
}
|
|
3954
|
+
const obje = typeof objeOrKey === "string" ? this._gedcom.obje(objeOrKey) : objeOrKey;
|
|
3955
|
+
if (!obje?.id) {
|
|
3956
|
+
return void 0;
|
|
3957
|
+
}
|
|
3958
|
+
const already = this.get("OBJE")?.toList()?.values()?.some((item) => item?.toValue?.() === obje.id);
|
|
3959
|
+
if (!already) {
|
|
3960
|
+
const pointer = makePointer(
|
|
3961
|
+
this._gedcom,
|
|
3962
|
+
this,
|
|
3963
|
+
obje.id,
|
|
3964
|
+
"OBJE"
|
|
3965
|
+
);
|
|
3966
|
+
this.assign("OBJE", pointer);
|
|
3967
|
+
}
|
|
3968
|
+
if (options?.primary) {
|
|
3969
|
+
this.get("OBJE")?.toList()?.forEach((item) => {
|
|
3970
|
+
const target = item?.refType === "OBJE" ? this._gedcom?.obje(
|
|
3971
|
+
String(item.toValue())
|
|
3972
|
+
) : item;
|
|
3973
|
+
if (!target) {
|
|
3974
|
+
return;
|
|
3975
|
+
}
|
|
3976
|
+
if (target.id === obje.id) {
|
|
3977
|
+
target.set("_PRIM", "Y");
|
|
3978
|
+
} else if (target.get("_PRIM")?.toValue() === "Y") {
|
|
3979
|
+
target.set("_PRIM", "N");
|
|
3980
|
+
}
|
|
3981
|
+
});
|
|
3982
|
+
obje.set("_PRIM", "Y");
|
|
3983
|
+
}
|
|
3984
|
+
return obje;
|
|
3985
|
+
}
|
|
3986
|
+
detachMultimedia(objeKey) {
|
|
3987
|
+
const list = this.get("OBJE")?.toList();
|
|
3988
|
+
if (!list) {
|
|
3989
|
+
return;
|
|
3990
|
+
}
|
|
3991
|
+
const toRemove = list.values().filter(
|
|
3992
|
+
(item) => item?.toValue?.() === objeKey || item?.id === objeKey
|
|
3993
|
+
);
|
|
3994
|
+
toRemove.forEach((item) => {
|
|
3995
|
+
if (item) {
|
|
3996
|
+
list.delete(item);
|
|
3997
|
+
}
|
|
3998
|
+
});
|
|
3999
|
+
if (list.length === 0) {
|
|
4000
|
+
this.remove("OBJE");
|
|
4001
|
+
}
|
|
4002
|
+
}
|
|
4003
|
+
/**
|
|
4004
|
+
* Create a multimedia record and attach it to this person.
|
|
4005
|
+
*/
|
|
4006
|
+
attachMediaFromUrl(url, options) {
|
|
4007
|
+
if (!this._gedcom || !url) {
|
|
4008
|
+
return void 0;
|
|
4009
|
+
}
|
|
4010
|
+
const obje = this._gedcom.createMultimediaRecord({
|
|
4011
|
+
file: url,
|
|
4012
|
+
form: options?.form,
|
|
4013
|
+
title: options?.title,
|
|
4014
|
+
mediType: options?.mediType,
|
|
4015
|
+
primary: options?.primary,
|
|
4016
|
+
gedcomVersion: options?.gedcomVersion
|
|
4017
|
+
});
|
|
4018
|
+
return this.attachMultimedia(obje, { primary: options?.primary });
|
|
4019
|
+
}
|
|
4020
|
+
/**
|
|
4021
|
+
* Link a shared SNOTE record via `1 NOTE @Nn@` (GEDCOM 7).
|
|
4022
|
+
*/
|
|
4023
|
+
attachSharedNote(noteOrKey) {
|
|
4024
|
+
if (!this._gedcom || !this.id) {
|
|
4025
|
+
return void 0;
|
|
4026
|
+
}
|
|
4027
|
+
const note = typeof noteOrKey === "string" ? this._gedcom.snote(noteOrKey) : noteOrKey;
|
|
4028
|
+
if (!note?.id) {
|
|
4029
|
+
return void 0;
|
|
4030
|
+
}
|
|
4031
|
+
const already = this.get("NOTE")?.toList()?.values()?.some((item) => item?.toValue?.() === note.id);
|
|
4032
|
+
if (!already) {
|
|
4033
|
+
const pointer = makePointer(
|
|
4034
|
+
this._gedcom,
|
|
4035
|
+
this,
|
|
4036
|
+
note.id,
|
|
4037
|
+
"SNOTE"
|
|
4038
|
+
);
|
|
4039
|
+
this.assign("NOTE", pointer);
|
|
4040
|
+
}
|
|
4041
|
+
return note;
|
|
4042
|
+
}
|
|
3845
4043
|
addFact(input) {
|
|
3846
4044
|
return addIndividualFact(this, input);
|
|
3847
4045
|
}
|
|
4046
|
+
addNonEvent(input) {
|
|
4047
|
+
return addNonEvent(this, input);
|
|
4048
|
+
}
|
|
3848
4049
|
getParentType(id) {
|
|
3849
4050
|
let indi;
|
|
3850
4051
|
if (typeof id === "string" || typeof id === "number") {
|
|
@@ -3885,7 +4086,7 @@ var Indi = class extends Common {
|
|
|
3885
4086
|
if (!famChild) {
|
|
3886
4087
|
const childIndi = this._gedcom?.indi(child.id);
|
|
3887
4088
|
const childState = childIndi?.get("FAMC")?.toList()?.filter((item) => item.value === family.id).index(0);
|
|
3888
|
-
childType = childState?.get("PEDI")?.toValue() || "biological" /* BIOLOGICAL */;
|
|
4089
|
+
childType = (childState?.get("PEDI") ?? childState?.get("PEDT"))?.toValue() || "biological" /* BIOLOGICAL */;
|
|
3889
4090
|
} else {
|
|
3890
4091
|
childType = famChild.get(usedRel)?.toValue() || "biological" /* BIOLOGICAL */;
|
|
3891
4092
|
}
|
|
@@ -4446,7 +4647,7 @@ var Indi = class extends Common {
|
|
|
4446
4647
|
return;
|
|
4447
4648
|
}
|
|
4448
4649
|
const childState = child?.get("FAMC")?.toList()?.filter((item) => item.value === family.id).index(0);
|
|
4449
|
-
const childType = childState?.get("PEDI")?.toValue() || "biological" /* BIOLOGICAL */;
|
|
4650
|
+
const childType = (childState?.get("PEDI") ?? childState?.get("PEDT"))?.toValue() || "biological" /* BIOLOGICAL */;
|
|
4450
4651
|
if (childType?.toLowerCase() === filter.PEDI.toLowerCase()) {
|
|
4451
4652
|
children.append(child);
|
|
4452
4653
|
}
|
|
@@ -4554,7 +4755,7 @@ var Indi = class extends Common {
|
|
|
4554
4755
|
const child = this.id && family.CHIL?.toValueList()?.item(this.id);
|
|
4555
4756
|
if (!child) {
|
|
4556
4757
|
const childState = this?.get("FAMC")?.toList()?.filter((item) => item.value === family.id).index(0);
|
|
4557
|
-
const parentType = childState?.get("PEDI")?.toValue() || "biological" /* BIOLOGICAL */;
|
|
4758
|
+
const parentType = (childState?.get("PEDI") ?? childState?.get("PEDT"))?.toValue() || "biological" /* BIOLOGICAL */;
|
|
4558
4759
|
if (parentType?.toLowerCase() === filter.PEDI.toLowerCase()) {
|
|
4559
4760
|
parents.merge(family.getParents());
|
|
4560
4761
|
}
|
|
@@ -6753,7 +6954,11 @@ var STANDARD_QUALIFIERS = {
|
|
|
6753
6954
|
BEF: "Bef.",
|
|
6754
6955
|
BEFORE: "Bef.",
|
|
6755
6956
|
AFT: "Aft.",
|
|
6756
|
-
AFTER: "Aft."
|
|
6957
|
+
AFTER: "Aft.",
|
|
6958
|
+
CAL: "Abt.",
|
|
6959
|
+
// calculated ≈ about for display
|
|
6960
|
+
EST: "Abt."
|
|
6961
|
+
// estimated ≈ about for display
|
|
6757
6962
|
};
|
|
6758
6963
|
var EXPORT_QUALIFIERS = {
|
|
6759
6964
|
"Abt.": "ABT",
|
|
@@ -6761,6 +6966,11 @@ var EXPORT_QUALIFIERS = {
|
|
|
6761
6966
|
"Aft.": "AFT"
|
|
6762
6967
|
};
|
|
6763
6968
|
var GEDCOM_MONTHS = /\b(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)\b/g;
|
|
6969
|
+
var CALENDAR_PREFIX = /^(?<calendar>GREGORIAN|JULIAN|FRENCH_R|HEBREW)\b\s+/i;
|
|
6970
|
+
var isGedcomDateValueForm = (value) => (
|
|
6971
|
+
// Require space/end after the token so display forms like "Abt." are not opaque.
|
|
6972
|
+
/^(FROM|TO|BET|AFT|BEF|ABT|CAL|EST|INT)(\s|$)/i.test(value) || /\bAND\b/i.test(value)
|
|
6973
|
+
);
|
|
6764
6974
|
var NOTE_MARKER = "####";
|
|
6765
6975
|
var formatDateWithComponents = (date, hasDay, hasMonth, hasYear, noteValue, baseFormat = "dd MMM yyyy", locale) => {
|
|
6766
6976
|
const hasNote = baseFormat.includes("NOTE");
|
|
@@ -6785,29 +6995,45 @@ var CommonDate = class extends Common {
|
|
|
6785
6995
|
super(gedcom, id, main, parent);
|
|
6786
6996
|
delete this.id;
|
|
6787
6997
|
}
|
|
6998
|
+
get calendar() {
|
|
6999
|
+
return this._calendar;
|
|
7000
|
+
}
|
|
6788
7001
|
set value(value) {
|
|
6789
7002
|
if (value) {
|
|
6790
|
-
const noteRegExp = /^(?<note>[a-zA-Z]+\.)/;
|
|
6791
|
-
const noteMatch = value.match(noteRegExp)?.groups;
|
|
6792
7003
|
let validValue = value;
|
|
7004
|
+
const calendarMatch = validValue.match(CALENDAR_PREFIX);
|
|
7005
|
+
if (calendarMatch?.groups?.calendar) {
|
|
7006
|
+
this._calendar = calendarMatch.groups.calendar.toUpperCase();
|
|
7007
|
+
validValue = validValue.slice(calendarMatch[0].length);
|
|
7008
|
+
} else {
|
|
7009
|
+
this._calendar = void 0;
|
|
7010
|
+
}
|
|
7011
|
+
const noteRegExp = /^(?<note>[a-zA-Z]+\.)/;
|
|
7012
|
+
const noteMatch = validValue.match(noteRegExp)?.groups;
|
|
6793
7013
|
if (noteMatch?.note) {
|
|
6794
7014
|
this.NOTE = this.NOTE || createCommon(this._gedcom, void 0, this.main);
|
|
6795
7015
|
this.NOTE.value = noteMatch?.note;
|
|
6796
|
-
validValue =
|
|
7016
|
+
validValue = validValue.replace(noteRegExp, "");
|
|
6797
7017
|
} else {
|
|
6798
|
-
const qualifierMatch =
|
|
6799
|
-
/^(?<qualifier>ABT|ABOUT|BEF|BEFORE|AFT|AFTER)\b\s*/i
|
|
7018
|
+
const qualifierMatch = validValue.match(
|
|
7019
|
+
/^(?<qualifier>ABT|ABOUT|BEF|BEFORE|AFT|AFTER|CAL|EST)\b\s*/i
|
|
6800
7020
|
);
|
|
6801
7021
|
const qualifier = qualifierMatch?.groups?.qualifier?.toUpperCase();
|
|
6802
7022
|
const note = qualifier ? STANDARD_QUALIFIERS[qualifier] : void 0;
|
|
6803
7023
|
if (note) {
|
|
6804
7024
|
this.NOTE = this.NOTE || createCommon(this._gedcom, void 0, this.main);
|
|
6805
7025
|
this.NOTE.value = note;
|
|
6806
|
-
validValue =
|
|
7026
|
+
validValue = validValue.slice(qualifierMatch[0].length);
|
|
6807
7027
|
}
|
|
6808
7028
|
}
|
|
6809
7029
|
const acceptedDate = this.isValidDateFormat(validValue);
|
|
6810
|
-
if (
|
|
7030
|
+
if (isGedcomDateValueForm(validValue.trim())) {
|
|
7031
|
+
delete this.DAY;
|
|
7032
|
+
delete this.MONTH;
|
|
7033
|
+
delete this.YEAR;
|
|
7034
|
+
this._date = void 0;
|
|
7035
|
+
this._value = value;
|
|
7036
|
+
} else if (acceptedDate) {
|
|
6811
7037
|
this.DAY = this.DAY || createCommon(this._gedcom, void 0, this.main);
|
|
6812
7038
|
this.DAY.value = format(acceptedDate, "dd");
|
|
6813
7039
|
this.MONTH = this.MONTH || createCommon(this._gedcom, void 0, this.main);
|
|
@@ -6910,6 +7136,15 @@ var CommonDate = class extends Common {
|
|
|
6910
7136
|
);
|
|
6911
7137
|
}
|
|
6912
7138
|
exportValue() {
|
|
7139
|
+
if (typeof this._value === "string") {
|
|
7140
|
+
const withoutCalendar = this._value.replace(CALENDAR_PREFIX, "");
|
|
7141
|
+
if (isGedcomDateValueForm(withoutCalendar.trim())) {
|
|
7142
|
+
return this._value.replace(
|
|
7143
|
+
/^((?:GREGORIAN|JULIAN|FRENCH_R|HEBREW)\s+)?(FROM|TO|BET|AFT|BEF|ABT|CAL|EST|INT)\b/i,
|
|
7144
|
+
(_m, cal, q) => `${cal || ""}${q.toUpperCase()}`
|
|
7145
|
+
);
|
|
7146
|
+
}
|
|
7147
|
+
}
|
|
6913
7148
|
const formatted = this.toValue("NOTE dd MMM yyyy", null);
|
|
6914
7149
|
if (!formatted) {
|
|
6915
7150
|
return formatted;
|
|
@@ -6917,10 +7152,14 @@ var CommonDate = class extends Common {
|
|
|
6917
7152
|
const note = this.NOTE?.value?.trim();
|
|
6918
7153
|
const qualifier = note ? EXPORT_QUALIFIERS[note] : void 0;
|
|
6919
7154
|
const standardized = qualifier ? formatted.replace(note, qualifier) : formatted;
|
|
6920
|
-
|
|
7155
|
+
const withMonths = standardized.replace(
|
|
6921
7156
|
GEDCOM_MONTHS,
|
|
6922
7157
|
(month) => month.toUpperCase()
|
|
6923
7158
|
);
|
|
7159
|
+
if (this._calendar && this._calendar !== "GREGORIAN") {
|
|
7160
|
+
return `${this._calendar} ${withMonths}`;
|
|
7161
|
+
}
|
|
7162
|
+
return withMonths;
|
|
6924
7163
|
}
|
|
6925
7164
|
toGedcomLines(tag, level = 0, options) {
|
|
6926
7165
|
const internal = new RegExp(
|