@treeviz/gedcom-parser 2.1.17 → 2.1.18

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.
@@ -361,6 +361,30 @@ var mediaIdValue = (obje, path) => {
361
361
  return typeof value === "string" && value.trim() ? value.trim() : void 0;
362
362
  };
363
363
  var resolveObjeMediaId = (obje) => mediaIdValue(obje, "RIN") || mediaIdValue(obje, "_CLON._OID") || mediaIdValue(obje, "_MSER._LKID") || mediaIdValue(obje, "_OID") || mediaIdValue(obje, "_LKID");
364
+ var ANCESTRY_TREE_MEDIA_NAMESPACE = 1093;
365
+ var ANCESTRY_NAMESPACE_IN_URL = /\/namespaces\/(\d+)\/media\//i;
366
+ var parseAncestryNamespaceFromUrl = (url) => {
367
+ if (!url) {
368
+ return void 0;
369
+ }
370
+ const match = url.match(ANCESTRY_NAMESPACE_IN_URL);
371
+ const namespace = match?.[1] ? Number(match[1]) : NaN;
372
+ return Number.isFinite(namespace) ? namespace : void 0;
373
+ };
374
+ var isAncestryOriginObje = (obje) => {
375
+ if (!obje) {
376
+ return false;
377
+ }
378
+ const orig = mediaIdValue(obje, "_ORIG");
379
+ if (orig?.toLowerCase() === "acom") {
380
+ return true;
381
+ }
382
+ const file = mediaIdValue(obje, "FILE") ?? "";
383
+ if (parseAncestryNamespaceFromUrl(file)) {
384
+ return true;
385
+ }
386
+ return Boolean(resolveObjeMediaId(obje) && !file.trim());
387
+ };
364
388
  var ANCESTRY_MEDIA_RETRIEVAL_PREFIX = "https://www.ancestry.com/api/media/retrieval/v2/image";
365
389
  var ANCESTRY_MEDIA_QUERY = "client=trees-mediaservice&imageQuality=hq";
366
390
  var ancestryMediaPath = (namespace, imgId) => `/namespaces/${namespace}/media/${imgId}?${ANCESTRY_MEDIA_QUERY}`;
@@ -1154,8 +1178,25 @@ var Common = class _Common {
1154
1178
  getHeadRecord() {
1155
1179
  return get(this, "HEAD") || get(this.getGedcom(), "HEAD");
1156
1180
  }
1181
+ unwrapHeadRecord(node) {
1182
+ if (!node) {
1183
+ return void 0;
1184
+ }
1185
+ const common = node instanceof List ? node.index(0) : node;
1186
+ if (!common || typeof common.get !== "function") {
1187
+ return void 0;
1188
+ }
1189
+ const nested = common.get("HEAD");
1190
+ if (nested instanceof List) {
1191
+ return nested.index(0) ?? common;
1192
+ }
1193
+ if (nested instanceof _Common) {
1194
+ return nested;
1195
+ }
1196
+ return common;
1197
+ }
1157
1198
  getOriginalHeadRecord() {
1158
- return get(this, ORIG_HEAD_TAG) || get(this.getGedcom(), ORIG_HEAD_TAG) || get(this.getHeadRecord(), ORIG_HEAD_TAG);
1199
+ return this.unwrapHeadRecord(get(this, ORIG_HEAD_TAG)) || this.unwrapHeadRecord(get(this.getGedcom(), ORIG_HEAD_TAG)) || this.unwrapHeadRecord(get(this.getHeadRecord(), ORIG_HEAD_TAG));
1159
1200
  }
1160
1201
  getSourceHeads() {
1161
1202
  const heads = [this.getOriginalHeadRecord(), this.getHeadRecord()];
@@ -1163,9 +1204,23 @@ var Common = class _Common {
1163
1204
  return Boolean(head && heads.indexOf(head) === index);
1164
1205
  });
1165
1206
  }
1207
+ sourceHeadField(head, path) {
1208
+ const normalized = path.endsWith(".value") ? path.slice(0, -".value".length) : path;
1209
+ const node = head.get(normalized);
1210
+ if (!node) {
1211
+ return void 0;
1212
+ }
1213
+ if (node instanceof List) {
1214
+ return node.index(0)?.toValue();
1215
+ }
1216
+ if (typeof node.toValue === "function") {
1217
+ return node.toValue();
1218
+ }
1219
+ return void 0;
1220
+ }
1166
1221
  getFromSourceHeads(path) {
1167
1222
  for (const head of this.getSourceHeads()) {
1168
- const value = get(head, path);
1223
+ const value = this.sourceHeadField(head, path);
1169
1224
  if (value !== void 0 && value !== null && value !== "") {
1170
1225
  return value;
1171
1226
  }
@@ -1174,8 +1229,8 @@ var Common = class _Common {
1174
1229
  }
1175
1230
  sourStartsWith(prefix) {
1176
1231
  return this.getSourceHeads().some((head) => {
1177
- const sour = get(head, "SOUR.value");
1178
- return !!sour?.toLowerCase()?.startsWith(prefix);
1232
+ const sour = this.sourceHeadField(head, "SOUR");
1233
+ return typeof sour === "string" && sour.toLowerCase().startsWith(prefix);
1179
1234
  });
1180
1235
  }
1181
1236
  isGenoPro() {
@@ -1193,6 +1248,51 @@ var Common = class _Common {
1193
1248
  isMyHeritage() {
1194
1249
  return this.sourStartsWith("myheritage");
1195
1250
  }
1251
+ /**
1252
+ * GEDCOM root for Ancestry media helpers.
1253
+ * `this._gedcom` when called on a child record; `this` when called on the file root.
1254
+ *
1255
+ * Cannot use `instanceof GedCom`: `GedComType` is a type alias (erased at runtime),
1256
+ * and importing the `GedCom` class here would cycle (`GedCom extends Common`).
1257
+ * The root is the only Common with an `objes()` method.
1258
+ */
1259
+ hostGedcom() {
1260
+ const linked = this.getGedcom();
1261
+ if (linked) {
1262
+ return linked;
1263
+ }
1264
+ if ("objes" in this && typeof this.objes === "function") {
1265
+ return this;
1266
+ }
1267
+ return void 0;
1268
+ }
1269
+ /** True when the file still has Ancestry tree media (`_ORIG acom`, `_OID`, retrieval URL). */
1270
+ hasAncestryOriginMedia() {
1271
+ const objes = this.hostGedcom()?.objes?.();
1272
+ return objes?.values().some((obje) => isAncestryOriginObje(obje)) ?? false;
1273
+ }
1274
+ /**
1275
+ * Namespace for Ancestry tree photos. Prefer a `namespaces/{id}` FILE URL
1276
+ * (TreeViz GEDCOM 7 / GEDZIP export), otherwise 1093 for member-tree media.
1277
+ */
1278
+ getAncestryMediaNamespace() {
1279
+ const objes = this.hostGedcom()?.objes?.();
1280
+ if (objes) {
1281
+ for (const obje of objes.values()) {
1282
+ const file = obje?.get("FILE")?.toValue();
1283
+ const fromUrl = parseAncestryNamespaceFromUrl(
1284
+ typeof file === "string" ? file : void 0
1285
+ );
1286
+ if (fromUrl) {
1287
+ return fromUrl;
1288
+ }
1289
+ }
1290
+ }
1291
+ if (this.isAncestry() || this.hasAncestryOriginMedia()) {
1292
+ return ANCESTRY_TREE_MEDIA_NAMESPACE;
1293
+ }
1294
+ return void 0;
1295
+ }
1196
1296
  /**
1197
1297
  * Get the source type as a string (for prefixing tree IDs and names)
1198
1298
  * Returns the detected source type or undefined if unknown
@@ -1209,13 +1309,13 @@ var Common = class _Common {
1209
1309
  }
1210
1310
  isFamilySearch() {
1211
1311
  return this.getSourceHeads().some((head) => {
1212
- const sourName = get(head, "SOUR.NAME.value");
1312
+ const sourName = this.sourceHeadField(head, "SOUR.NAME");
1213
1313
  return sourName === "FamilySearch API";
1214
1314
  });
1215
1315
  }
1216
1316
  isGNO2GED() {
1217
1317
  return this.getSourceHeads().some((head) => {
1218
- const sour = get(head, "SOUR.value");
1318
+ const sour = this.sourceHeadField(head, "SOUR");
1219
1319
  return sour === "GNO2GED";
1220
1320
  });
1221
1321
  }
@@ -1260,8 +1360,7 @@ var Common = class _Common {
1260
1360
  return this.getFromSourceHeads("SOUR._TREE.value") || (get(this, "HEAD.SOUR._TREE.value") || get(this.getGedcom(), "HEAD.SOUR._TREE.value"));
1261
1361
  }
1262
1362
  getMyHeritageTreeName() {
1263
- const path = "HEAD.FILE.value";
1264
- const treeDetails = get(this, path) || get(this.getGedcom(), path);
1363
+ const treeDetails = this.getFromSourceHeads("FILE.value") || (get(this, "HEAD.FILE.value") || get(this.getGedcom(), "HEAD.FILE.value"));
1265
1364
  return treeDetails?.match(
1266
1365
  /Exported by MyHeritage.com from (?<tree>.+) in.+$/
1267
1366
  )?.groups?.tree;
@@ -1278,7 +1377,7 @@ var Common = class _Common {
1278
1377
  if (treeName) {
1279
1378
  return treeName;
1280
1379
  }
1281
- const fileName = get(this, "HEAD.FILE.value") || get(this.getGedcom(), "HEAD.FILE.value");
1380
+ const fileName = this.getFromSourceHeads("FILE.value") || get(this, "HEAD.FILE.value") || get(this.getGedcom(), "HEAD.FILE.value");
1282
1381
  return fileName || "FamilySearch Import";
1283
1382
  }
1284
1383
  getAhnenblattTreeId() {
@@ -2873,6 +2972,45 @@ var implemented = (type, ...args) => {
2873
2972
  var notImplemented = (type, ...args) => {
2874
2973
  console.error(`[Not Implemented] ${type}`, ...args);
2875
2974
  };
2975
+
2976
+ // src/utils/multimedia.ts
2977
+ var inferMediaForm = (file, fallback = "bin") => {
2978
+ const withoutQuery = file.split("?")[0] || file;
2979
+ const ext = getFileExtension(withoutQuery);
2980
+ if (ext) {
2981
+ return ext.toLowerCase() === "jpeg" ? "jpg" : ext.toLowerCase();
2982
+ }
2983
+ return fallback;
2984
+ };
2985
+ var mergeMediaLists = (...lists) => {
2986
+ const merged = {};
2987
+ for (const list of lists) {
2988
+ if (!list) continue;
2989
+ Object.assign(merged, list);
2990
+ }
2991
+ return merged;
2992
+ };
2993
+ var mergeMediaListsByObjeKey = (...lists) => {
2994
+ const merged = {};
2995
+ const seen = /* @__PURE__ */ new Set();
2996
+ for (const list of lists) {
2997
+ if (!list) {
2998
+ continue;
2999
+ }
3000
+ for (const [id, item] of Object.entries(list)) {
3001
+ const objeKey = item.key ? String(item.key) : "";
3002
+ if (objeKey && seen.has(objeKey)) {
3003
+ continue;
3004
+ }
3005
+ merged[id] = item;
3006
+ if (objeKey) {
3007
+ seen.add(objeKey);
3008
+ }
3009
+ }
3010
+ }
3011
+ return merged;
3012
+ };
3013
+ var isObjePointer = (value) => typeof value === "string" && /^@O\d+@$/.test(value);
2876
3014
  var uniqueItemsCache = /* @__PURE__ */ new WeakMap();
2877
3015
  var setNestedGroup = (obj, key, value, uniqueCounting = true) => {
2878
3016
  const parts = Array.isArray(key) ? key : key.split(/,\s*/);
@@ -4137,7 +4275,10 @@ var Indi = class extends Common {
4137
4275
  return result;
4138
4276
  }
4139
4277
  ancestryLink() {
4140
- const www = this.getFromSourceHeads("SOUR.CORP.WWW.value") || this._gedcom?.HEAD?.SOUR?.CORP?.WWW?.value;
4278
+ let www = this.getFromSourceHeads("SOUR.CORP.WWW.value") || this._gedcom?.HEAD?.SOUR?.CORP?.WWW?.value;
4279
+ if (!www || /treeviz/i.test(String(www))) {
4280
+ www = "www.ancestry.com";
4281
+ }
4141
4282
  const tree = this.getAncestryTreeId();
4142
4283
  if (this.id) {
4143
4284
  return `https://${www}/family-tree/person/tree/${tree}/person/${this.id.replace(
@@ -4149,14 +4290,15 @@ var Indi = class extends Common {
4149
4290
  async ancestryMedia(namespace) {
4150
4291
  const list = {};
4151
4292
  const objeList = this.get("OBJE")?.toList().copy();
4152
- const www = this.getFromSourceHeads("SOUR.CORP.WWW.value") || this._gedcom?.HEAD?.SOUR?.CORP?.WWW?.value;
4293
+ this.getFromSourceHeads("SOUR.CORP.WWW.value") || this._gedcom?.HEAD?.SOUR?.CORP?.WWW?.value;
4153
4294
  const tree = this.getAncestryTreeId();
4295
+ const usedNamespace = namespace || this.getAncestryMediaNamespace() || ANCESTRY_TREE_MEDIA_NAMESPACE;
4154
4296
  if (objeList) {
4155
4297
  await Promise.all(
4156
4298
  objeList.map(async (objeRef) => {
4157
4299
  const key = objeXrefKey(objeRef, 0);
4158
4300
  const obje = objeRef?.standardizeMedia(
4159
- namespace,
4301
+ usedNamespace,
4160
4302
  true,
4161
4303
  ancestryMediaFileUrl
4162
4304
  );
@@ -4168,27 +4310,9 @@ var Indi = class extends Common {
4168
4310
  const type = resolveObjeForm(obje) ?? (url ? getFileExtension(url) : void 0) ?? "raw";
4169
4311
  let imgId = media;
4170
4312
  const hasEmbeddedOrLocalFile = !!url && (url.startsWith("data:") || url.startsWith("blob:") || !/^https?:\/\//i.test(url));
4171
- if (!hasEmbeddedOrLocalFile && (!www || !tree || !this.id)) {
4172
- return;
4173
- }
4174
4313
  if (!this.id) {
4175
4314
  return;
4176
4315
  }
4177
- if (!namespace && !url) {
4178
- try {
4179
- if (media) {
4180
- const mediaDetailsResponse = await fetch(
4181
- `https://www.ancestry.com/api/media/viewer/v2/trees/${tree}/media?id=${media}`
4182
- );
4183
- const mediaDetails = await mediaDetailsResponse.json();
4184
- if (mediaDetails.url) {
4185
- url = `${mediaDetails.url}&imageQuality=hq`;
4186
- }
4187
- }
4188
- } catch (_e) {
4189
- }
4190
- url = url || `https://${www}/mediaui-viewer/tree/${tree}/media/${media}`;
4191
- }
4192
4316
  if (!imgId && hasEmbeddedOrLocalFile && url) {
4193
4317
  imgId = typeof media === "string" && media || `local-${String(key).replace(/[@]/g, "")}-${getFileExtension(url) || "bin"}`;
4194
4318
  }
@@ -4214,9 +4338,12 @@ var Indi = class extends Common {
4214
4338
  return list;
4215
4339
  }
4216
4340
  myheritageLink(poolId = 0) {
4217
- const www = (this.getFromSourceHeads("SOUR.CORP.value") || this._gedcom?.HEAD?.SOUR?.CORP?.value)?.toLowerCase().replace(/^www\./gi, "");
4341
+ let www = (this.getFromSourceHeads("SOUR.CORP.value") || this._gedcom?.HEAD?.SOUR?.CORP?.value)?.toLowerCase().replace(/^www\./gi, "");
4342
+ if (!www || /treeviz/i.test(www)) {
4343
+ www = "myheritage.com";
4344
+ }
4218
4345
  const site = this.getMyHeritageTreeId();
4219
- const file = this._gedcom?.HEAD?.get("FILE")?.toValue()?.match(/Exported by MyHeritage.com from .+ in (?<site>.+) on .+$/)?.groups?.site;
4346
+ const file = (this.getFromSourceHeads("FILE.value") || this._gedcom?.HEAD?.get("FILE")?.toValue())?.match(/Exported by MyHeritage.com from .+ in (?<site>.+) on .+$/)?.groups?.site;
4220
4347
  const normalizedFile = file?.normalize("NFD").replace(/[\u0300-\u036f]/g, "").toLowerCase().replace(/[^a-z0-9]+/g, "-");
4221
4348
  if (normalizedFile && this.id) {
4222
4349
  const id = Number(this.id.replace(/@|I/g, "")) + poolId;
@@ -4437,16 +4564,26 @@ var Indi = class extends Common {
4437
4564
  return list;
4438
4565
  }
4439
4566
  async multimedia(namespace) {
4440
- if (this?.isAncestry()) {
4441
- return await this.ancestryMedia(namespace);
4567
+ const lists = [];
4568
+ const ownObjes = this.get("OBJE")?.toList()?.values() ?? [];
4569
+ const ownAncestryMedia = ownObjes.some(
4570
+ (obje) => !!obje && (isAncestryOriginObje(obje) || isAncestryOriginObje(obje.ref))
4571
+ );
4572
+ if (this.isAncestry() || ownAncestryMedia) {
4573
+ lists.push(
4574
+ await this.ancestryMedia(
4575
+ namespace || this.getAncestryMediaNamespace()
4576
+ )
4577
+ );
4442
4578
  }
4443
4579
  if (this?.isMyHeritage()) {
4444
- return this.myheritageMedia();
4580
+ lists.push(this.myheritageMedia());
4445
4581
  }
4446
4582
  if (this?.isGeni()) {
4447
- return this.geniMedia();
4583
+ lists.push(this.geniMedia());
4448
4584
  }
4449
- return this.universalMedia();
4585
+ lists.push(this.universalMedia());
4586
+ return mergeMediaListsByObjeKey(...lists);
4450
4587
  }
4451
4588
  async getProfilePicture(namespace, onlyPrimary = true) {
4452
4589
  if (!this.id) {
@@ -9773,7 +9910,7 @@ var collectExtensionTagsFrom = (node, into = /* @__PURE__ */ new Set()) => {
9773
9910
  // package.json
9774
9911
  var package_default = {
9775
9912
  name: "@treeviz/gedcom-parser",
9776
- version: "2.1.17"};
9913
+ version: "2.1.18"};
9777
9914
 
9778
9915
  // src/utils/get-product-details.ts
9779
9916
  var isDevelopment = () => {
@@ -9782,25 +9919,6 @@ var isDevelopment = () => {
9782
9919
  var getVersion = () => package_default.version;
9783
9920
  var getName = () => package_default.name;
9784
9921
 
9785
- // src/utils/multimedia.ts
9786
- var inferMediaForm = (file, fallback = "bin") => {
9787
- const withoutQuery = file.split("?")[0] || file;
9788
- const ext = getFileExtension(withoutQuery);
9789
- if (ext) {
9790
- return ext.toLowerCase() === "jpeg" ? "jpg" : ext.toLowerCase();
9791
- }
9792
- return fallback;
9793
- };
9794
- var mergeMediaLists = (...lists) => {
9795
- const merged = {};
9796
- for (const list of lists) {
9797
- if (!list) continue;
9798
- Object.assign(merged, list);
9799
- }
9800
- return merged;
9801
- };
9802
- var isObjePointer = (value) => typeof value === "string" && /^@O\d+@$/.test(value);
9803
-
9804
9922
  // src/classes/note.ts
9805
9923
  var CommonNote = class extends Common {
9806
9924
  constructor(gedcom, id, main, parent) {
@@ -9951,6 +10069,10 @@ var Obje = class extends Common {
9951
10069
  if (lkidNode && !newObject.get("_LKID")) {
9952
10070
  newObject.set("_LKID", lkidNode);
9953
10071
  }
10072
+ const origNode = this.get("_ORIG");
10073
+ if (origNode && !newObject.get("_ORIG")) {
10074
+ newObject.set("_ORIG", origNode);
10075
+ }
9954
10076
  if (override) {
9955
10077
  this.remove("FILE");
9956
10078
  this.remove("FORM");
@@ -11451,4 +11573,4 @@ var hydrateFromContentAsync = async (content, options) => {
11451
11573
  return hydrateFromContent(content, options);
11452
11574
  };
11453
11575
 
11454
- export { ACCEPTED_DATE_FORMATS, ACCEPTED_DATE_FORMATS_REGEX, ANCESTRY_MEDIA_RETRIEVAL_PREFIX, DEFAULT_GEDCOM_EXPORT_VERSION, GEDCOM7_CALENDARS, GEDCOM7_PEDI_VALUES, GEDCOM7_RESN_VALUES, GEDCOM7_ROLE_VALUES, GEDCOM7_SEX_VALUES, GEDCOM_EXPORT_VERSIONS, GEDCOM_TRAILER_TAG, GEDZIP_EXTENSION, GEDZIP_GEDCOM_ENTRY, GEDZIP_MIME, parser_default as GedcomTree, PEDIGREE_VALUES, PlaceType, STRUCTURAL_FORMAT, STRUCTURAL_VERSION, TREEVIZ_EXTENSION_BASE_URI, TREEVIZ_EXTENSION_URIS, addFamilyFact, addIndividualFact, addNonEvent, ancestryMediaFileUrl, appendGedcomTrailer, applyGedcom7DatePhrases, applyGedcom7Enumerations, applyGedcom7RecordMetadata, attachChildToFamily, attachSpouseToFamily, buildGedzip, buildGedzipBlob, bytesToDataUrl, cacheDiscoveredPath, canAttachAsSpouse, collectExtensionTagsFrom, commonDateFormatter, consolidateChildIntoFamily, coupleKeyForFam, create, createEmptyGedcom, createGedcomUid, dateFormatter, deleteIndividual, downloadGedzipMedia, ensureExtensionSchema, extractGedzip, extractGedzipGedcom, extractSeparationYears, extractSplitPoints, familyHasChild, familyHasParent, findDegenerateFamiliesForIndi, findDuplicateCoupleFamiliesForIndi, findMatchingRangeForSplitRange, findReusableParentChildFamily, firstPointerId, formatGedcom7Timestamp, fromObject, fromObjectAsync, fromTuple, generateSplitRanges, getAllProp, getExtensionSchema, getFamilyWith, getFileExtension, getName, getPlaceParts, getPlaces, getRawSize, getVersion, hungarianOrdinalize, hydrateFromContent, hydrateFromContentAsync, implemented, inRange, inferMediaForm, initializeCache, isDegenerateFamily, isDevelopment, isGedcom7, isGedcomTrailerLine, isGedcomTrailerTag, isGedzipContainer, isImageFormat, isIntersectedRange, isObjePointer, isRangeContained, isRemoteOrEmbeddedMediaUrl, isStructuralEnvelope, makePointer, marriageDateFormatter, mergeDuplicateCoupleFamilies, mergeMediaLists, nameFormatter, nextRecordId, normalizeGedcomVersion, notImplemented, noteDateFormatter, objeNoteValue, objeXrefKey, ordinalize, parseGedcom7CalendarPrefix, parseRangeBounds, parseStructuralEnvelope, pathCache, placeTranslator, pointerIds, profilePictureCache, pruneEmptyFamilies, pruneFamiliesByIds, registerExtensionTag, relativesCache, remountGedzipMediaAsDataUrls, removePointerByValue, resetRelativesCache, resolveLocalMediaUrl, resolveMediaContent, resolveObjeForm, resolveObjeMediaId, rewriteGedcomFilePaths, serializeStructural, setCauseOfDeath, setChildPedigree, setDeceased, setFamilyMarriage, setLocalMediaResolver, setMediaContentResolver, setNestedGroup, splitOverlappingRanges, splitRange, spouseTagFor, toGedcomPedigree, unlinkRelative, updateFactRecord, withGedcom7Calendar };
11576
+ export { ACCEPTED_DATE_FORMATS, ACCEPTED_DATE_FORMATS_REGEX, ANCESTRY_MEDIA_RETRIEVAL_PREFIX, ANCESTRY_TREE_MEDIA_NAMESPACE, DEFAULT_GEDCOM_EXPORT_VERSION, GEDCOM7_CALENDARS, GEDCOM7_PEDI_VALUES, GEDCOM7_RESN_VALUES, GEDCOM7_ROLE_VALUES, GEDCOM7_SEX_VALUES, GEDCOM_EXPORT_VERSIONS, GEDCOM_TRAILER_TAG, GEDZIP_EXTENSION, GEDZIP_GEDCOM_ENTRY, GEDZIP_MIME, parser_default as GedcomTree, PEDIGREE_VALUES, PlaceType, STRUCTURAL_FORMAT, STRUCTURAL_VERSION, TREEVIZ_EXTENSION_BASE_URI, TREEVIZ_EXTENSION_URIS, addFamilyFact, addIndividualFact, addNonEvent, ancestryMediaFileUrl, appendGedcomTrailer, applyGedcom7DatePhrases, applyGedcom7Enumerations, applyGedcom7RecordMetadata, attachChildToFamily, attachSpouseToFamily, buildGedzip, buildGedzipBlob, bytesToDataUrl, cacheDiscoveredPath, canAttachAsSpouse, collectExtensionTagsFrom, commonDateFormatter, consolidateChildIntoFamily, coupleKeyForFam, create, createEmptyGedcom, createGedcomUid, dateFormatter, deleteIndividual, downloadGedzipMedia, ensureExtensionSchema, extractGedzip, extractGedzipGedcom, extractSeparationYears, extractSplitPoints, familyHasChild, familyHasParent, findDegenerateFamiliesForIndi, findDuplicateCoupleFamiliesForIndi, findMatchingRangeForSplitRange, findReusableParentChildFamily, firstPointerId, formatGedcom7Timestamp, fromObject, fromObjectAsync, fromTuple, generateSplitRanges, getAllProp, getExtensionSchema, getFamilyWith, getFileExtension, getName, getPlaceParts, getPlaces, getRawSize, getVersion, hungarianOrdinalize, hydrateFromContent, hydrateFromContentAsync, implemented, inRange, inferMediaForm, initializeCache, isAncestryOriginObje, isDegenerateFamily, isDevelopment, isGedcom7, isGedcomTrailerLine, isGedcomTrailerTag, isGedzipContainer, isImageFormat, isIntersectedRange, isObjePointer, isRangeContained, isRemoteOrEmbeddedMediaUrl, isStructuralEnvelope, makePointer, marriageDateFormatter, mergeDuplicateCoupleFamilies, mergeMediaLists, mergeMediaListsByObjeKey, nameFormatter, nextRecordId, normalizeGedcomVersion, notImplemented, noteDateFormatter, objeNoteValue, objeXrefKey, ordinalize, parseAncestryNamespaceFromUrl, parseGedcom7CalendarPrefix, parseRangeBounds, parseStructuralEnvelope, pathCache, placeTranslator, pointerIds, profilePictureCache, pruneEmptyFamilies, pruneFamiliesByIds, registerExtensionTag, relativesCache, remountGedzipMediaAsDataUrls, removePointerByValue, resetRelativesCache, resolveLocalMediaUrl, resolveMediaContent, resolveObjeForm, resolveObjeMediaId, rewriteGedcomFilePaths, serializeStructural, setCauseOfDeath, setChildPedigree, setDeceased, setFamilyMarriage, setLocalMediaResolver, setMediaContentResolver, setNestedGroup, splitOverlappingRanges, splitRange, spouseTagFor, toGedcomPedigree, unlinkRelative, updateFactRecord, withGedcom7Calendar };
@@ -24,6 +24,16 @@ type ObjeGetter = {
24
24
  * have `_OID` without `_MSER._LKID`; both are the UUID used in media URLs.
25
25
  */
26
26
  export declare const resolveObjeMediaId: (obje?: ObjeGetter) => string | undefined;
27
+ /**
28
+ * Ancestry member-tree photos (user uploads) always live in media
29
+ * namespace 1093. Ancestry GEDCOM exports do not store this id — only
30
+ * `_OID` / `_MSER._LKID` UUIDs and `_ORIG acom`. Other namespaces
31
+ * (e.g. 7163) are historical record databases, not tree media.
32
+ */
33
+ export declare const ANCESTRY_TREE_MEDIA_NAMESPACE = 1093;
34
+ export declare const parseAncestryNamespaceFromUrl: (url?: string) => number | undefined;
35
+ /** Tree-media object from Ancestry: `_ORIG acom`, empty FILE + UUID, or a retrieval URL. */
36
+ export declare const isAncestryOriginObje: (obje?: ObjeGetter) => boolean;
27
37
  /** Ancestry tree media host used by their viewer. */
28
38
  export declare const ANCESTRY_MEDIA_RETRIEVAL_PREFIX = "https://www.ancestry.com/api/media/retrieval/v2/image";
29
39
  export declare const ancestryMediaFileUrl: (namespace?: string | number, imgId?: string) => string | undefined;
@@ -1 +1 @@
1
- {"version":3,"file":"media-utils.d.ts","sourceRoot":"","sources":["../../src/utils/media-utils.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAE/C,eAAO,MAAM,gBAAgB,GAAI,UAAU,MAAM,KAAG,MAenD,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,aAAa,GAAI,QAAQ,MAAM,KAAG,OAyB9C,CAAC;AAEF,6EAA6E;AAC7E,eAAO,MAAM,eAAe,GAAI,OAAO;IACtC,GAAG,CAAC,EAAE,CAAC,IAAI,EAAE,QAAQ,KAAK;QAAE,OAAO,CAAC,EAAE,MAAM,OAAO,CAAA;KAAE,GAAG,SAAS,CAAC;CAClE,KAAG,MAAM,GAAG,SAKZ,CAAC;AAEF,KAAK,UAAU,GAAG;IACjB,GAAG,CAAC,EAAE,CAAC,IAAI,EAAE,QAAQ,KAAK;QAAE,OAAO,CAAC,EAAE,MAAM,OAAO,CAAA;KAAE,GAAG,SAAS,CAAC;CAClE,CAAC;AAOF;;;GAGG;AACH,eAAO,MAAM,kBAAkB,GAAI,OAAO,UAAU,KAAG,MAAM,GAAG,SAKpC,CAAC;AAE7B,qDAAqD;AACrD,eAAO,MAAM,+BAA+B,0DACY,CAAC;AAMzD,eAAO,MAAM,oBAAoB,GAChC,YAAY,MAAM,GAAG,MAAM,EAC3B,QAAQ,MAAM,KACZ,MAAM,GAAG,SAKX,CAAC;AAEF,0FAA0F;AAC1F,eAAO,MAAM,WAAW,GACvB,OAAO;IAAE,EAAE,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,OAAO,CAAA;CAAE,EAC/C,WAAU,MAAM,GAAG,MAAU,KAC3B,MAYF,CAAC;AAEF,eAAO,MAAM,aAAa,GAAI,OAAO,UAAU,KAAG,MACkB,CAAC"}
1
+ {"version":3,"file":"media-utils.d.ts","sourceRoot":"","sources":["../../src/utils/media-utils.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAE/C,eAAO,MAAM,gBAAgB,GAAI,UAAU,MAAM,KAAG,MAenD,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,aAAa,GAAI,QAAQ,MAAM,KAAG,OAyB9C,CAAC;AAEF,6EAA6E;AAC7E,eAAO,MAAM,eAAe,GAAI,OAAO;IACtC,GAAG,CAAC,EAAE,CAAC,IAAI,EAAE,QAAQ,KAAK;QAAE,OAAO,CAAC,EAAE,MAAM,OAAO,CAAA;KAAE,GAAG,SAAS,CAAC;CAClE,KAAG,MAAM,GAAG,SAKZ,CAAC;AAEF,KAAK,UAAU,GAAG;IACjB,GAAG,CAAC,EAAE,CAAC,IAAI,EAAE,QAAQ,KAAK;QAAE,OAAO,CAAC,EAAE,MAAM,OAAO,CAAA;KAAE,GAAG,SAAS,CAAC;CAClE,CAAC;AAOF;;;GAGG;AACH,eAAO,MAAM,kBAAkB,GAAI,OAAO,UAAU,KAAG,MAAM,GAAG,SAKpC,CAAC;AAE7B;;;;;GAKG;AACH,eAAO,MAAM,6BAA6B,OAAO,CAAC;AAIlD,eAAO,MAAM,6BAA6B,GACzC,MAAM,MAAM,KACV,MAAM,GAAG,SAOX,CAAC;AAEF,4FAA4F;AAC5F,eAAO,MAAM,oBAAoB,GAAI,OAAO,UAAU,KAAG,OAaxD,CAAC;AAEF,qDAAqD;AACrD,eAAO,MAAM,+BAA+B,0DACY,CAAC;AAMzD,eAAO,MAAM,oBAAoB,GAChC,YAAY,MAAM,GAAG,MAAM,EAC3B,QAAQ,MAAM,KACZ,MAAM,GAAG,SAKX,CAAC;AAEF,0FAA0F;AAC1F,eAAO,MAAM,WAAW,GACvB,OAAO;IAAE,EAAE,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,OAAO,CAAA;CAAE,EAC/C,WAAU,MAAM,GAAG,MAAU,KAC3B,MAYF,CAAC;AAEF,eAAO,MAAM,aAAa,GAAI,OAAO,UAAU,KAAG,MACkB,CAAC"}
@@ -34,5 +34,10 @@ export declare const inferMediaForm: (file: string, fallback?: string) => string
34
34
  * Merge MediaList maps (later entries overwrite same keys).
35
35
  */
36
36
  export declare const mergeMediaLists: (...lists: Array<MediaList | undefined>) => MediaList;
37
+ /**
38
+ * Merge media from vendor resolvers and local/GEDZIP FILE payloads.
39
+ * First list wins when the same OBJE xref appears twice.
40
+ */
41
+ export declare const mergeMediaListsByObjeKey: (...lists: Array<MediaList | undefined>) => MediaList;
37
42
  export declare const isObjePointer: (value: unknown) => value is ObjeKey;
38
43
  //# sourceMappingURL=multimedia.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"multimedia.d.ts","sourceRoot":"","sources":["../../src/utils/multimedia.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AACpD,OAAO,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AACvD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AAG5D,MAAM,MAAM,qBAAqB,GAAG;IACnC,iDAAiD;IACjD,IAAI,EAAE,MAAM,CAAC;IACb,2EAA2E;IAC3E,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB;;;OAGG;IACH,aAAa,CAAC,EAAE,mBAAmB,GAAG,MAAM,CAAC;CAC7C,CAAC;AAEF,MAAM,MAAM,uBAAuB,GAAG;IACrC,OAAO,CAAC,EAAE,OAAO,CAAC;CAClB,CAAC;AAEF,MAAM,MAAM,wBAAwB,GAAG;IACtC,OAAO,CAAC,EAAE,OAAO,EAAE,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;CAC5B,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,cAAc,GAAI,MAAM,MAAM,EAAE,iBAAgB,WAO5D,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,eAAe,GAAI,GAAG,OAAO,KAAK,CAAC,SAAS,GAAG,SAAS,CAAC,cAOrE,CAAC;AAEF,eAAO,MAAM,aAAa,GAAI,OAAO,OAAO,KAAG,KAAK,IAAI,OACJ,CAAC"}
1
+ {"version":3,"file":"multimedia.d.ts","sourceRoot":"","sources":["../../src/utils/multimedia.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AACpD,OAAO,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AACvD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AAG5D,MAAM,MAAM,qBAAqB,GAAG;IACnC,iDAAiD;IACjD,IAAI,EAAE,MAAM,CAAC;IACb,2EAA2E;IAC3E,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB;;;OAGG;IACH,aAAa,CAAC,EAAE,mBAAmB,GAAG,MAAM,CAAC;CAC7C,CAAC;AAEF,MAAM,MAAM,uBAAuB,GAAG;IACrC,OAAO,CAAC,EAAE,OAAO,CAAC;CAClB,CAAC;AAEF,MAAM,MAAM,wBAAwB,GAAG;IACtC,OAAO,CAAC,EAAE,OAAO,EAAE,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;CAC5B,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,cAAc,GAAI,MAAM,MAAM,EAAE,iBAAgB,WAO5D,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,eAAe,GAAI,GAAG,OAAO,KAAK,CAAC,SAAS,GAAG,SAAS,CAAC,cAOrE,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,wBAAwB,GACpC,GAAG,OAAO,KAAK,CAAC,SAAS,GAAG,SAAS,CAAC,cAoBtC,CAAC;AAEF,eAAO,MAAM,aAAa,GAAI,OAAO,OAAO,KAAG,KAAK,IAAI,OACJ,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@treeviz/gedcom-parser",
3
- "version": "2.1.17",
3
+ "version": "2.1.18",
4
4
  "description": "Lightweight, pluggable GEDCOM parser for JavaScript/TypeScript with optional caching and place matching. Zero browser dependencies.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",