@treeviz/gedcom-parser 2.1.9 → 2.1.11

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.
@@ -350,6 +350,82 @@ var ORIG_HEAD_TAG = "_ORIGHEAD";
350
350
  // src/utils/gedcom-trailer.ts
351
351
  var GEDCOM_TRAILER_TAG = "TRLR";
352
352
  var isGedcomTrailerTag = (tag) => tag === GEDCOM_TRAILER_TAG;
353
+
354
+ // src/utils/media-utils.ts
355
+ var getFileExtension = (filename) => {
356
+ if (!filename) {
357
+ return "";
358
+ }
359
+ if (filename.startsWith("data:")) {
360
+ const mime = filename.slice(5).split(";")[0] || "";
361
+ const subtype = (mime.split("/")[1] || "").toLowerCase();
362
+ if (subtype === "jpeg") {
363
+ return "jpg";
364
+ }
365
+ return subtype.split("+")[0] || "";
366
+ }
367
+ const withoutQuery = filename.split(/[?#]/)[0] || filename;
368
+ const match = withoutQuery.match(/\.([^.]+)$/);
369
+ return match ? match[1].toLowerCase() : "";
370
+ };
371
+ var isImageFormat = (format2) => {
372
+ if (!format2) {
373
+ return false;
374
+ }
375
+ let normalized = format2.toLowerCase().trim();
376
+ if (normalized.startsWith("data:")) {
377
+ normalized = getFileExtension(normalized);
378
+ } else if (normalized.includes("/")) {
379
+ normalized = normalized.split("/")[1]?.split("+")[0] || "";
380
+ if (normalized === "jpeg") {
381
+ normalized = "jpg";
382
+ }
383
+ }
384
+ const imageFormats = [
385
+ "jpg",
386
+ "jpeg",
387
+ "png",
388
+ "gif",
389
+ "bmp",
390
+ "webp",
391
+ "svg",
392
+ "tiff",
393
+ "tif"
394
+ ];
395
+ return imageFormats.includes(normalized);
396
+ };
397
+ var resolveObjeForm = (obje) => {
398
+ const value = obje?.get?.("FILE.FORM")?.toValue?.() ?? obje?.get?.("FORM")?.toValue?.();
399
+ return typeof value === "string" && value.trim() ? value.trim() : void 0;
400
+ };
401
+ var mediaIdValue = (obje, path) => {
402
+ const value = obje?.get?.(path)?.toValue?.();
403
+ return typeof value === "string" && value.trim() ? value.trim() : void 0;
404
+ };
405
+ var resolveObjeMediaId = (obje) => mediaIdValue(obje, "RIN") || mediaIdValue(obje, "_CLON._OID") || mediaIdValue(obje, "_MSER._LKID") || mediaIdValue(obje, "_OID") || mediaIdValue(obje, "_LKID");
406
+ var ANCESTRY_MEDIA_RETRIEVAL_PREFIX = "https://www.ancestry.com/api/media/retrieval/v2/image";
407
+ var ANCESTRY_MEDIA_QUERY = "client=trees-mediaservice&imageQuality=hq";
408
+ var ancestryMediaPath = (namespace, imgId) => `/namespaces/${namespace}/media/${imgId}?${ANCESTRY_MEDIA_QUERY}`;
409
+ var ancestryMediaFileUrl = (namespace, imgId) => {
410
+ if (!namespace || !imgId) {
411
+ return void 0;
412
+ }
413
+ return `${ANCESTRY_MEDIA_RETRIEVAL_PREFIX}${ancestryMediaPath(namespace, imgId)}`;
414
+ };
415
+ var objeXrefKey = (obje, fallback = 0) => {
416
+ if (typeof obje?.id === "string" && obje.id) {
417
+ return obje.id;
418
+ }
419
+ const value = obje?.toValue?.();
420
+ if (typeof value === "string" && value.trim()) {
421
+ return value.trim();
422
+ }
423
+ if (typeof fallback === "string" && fallback.trim()) {
424
+ return fallback.trim();
425
+ }
426
+ return `@O${fallback}@`;
427
+ };
428
+ var objeNoteValue = (obje) => mediaIdValue(obje, "FILE.NOTE") || mediaIdValue(obje, "NOTE") || "";
353
429
  var List = class _List {
354
430
  // length = 0;
355
431
  constructor(items) {
@@ -999,7 +1075,7 @@ var Common = class _Common {
999
1075
  this,
1000
1076
  options.obje.namespace,
1001
1077
  options.obje.override,
1002
- void 0,
1078
+ this.isAncestry() ? ancestryMediaFileUrl : void 0,
1003
1079
  options.gedcomVersion
1004
1080
  );
1005
1081
  }
@@ -1930,11 +2006,8 @@ var storeCache = {
1930
2006
  getCacheDbs().relativesOnDegreeCache.setItem(value);
1931
2007
  }
1932
2008
  }, 50),
1933
- // profilePictureCache IS persisted to IndexedDB
2009
+ // Image bytes are stored as one IndexedDB record per photo.
1934
2010
  profilePictureCache: debounce((value) => {
1935
- if (value) {
1936
- getCacheDbs().profilePictureCache.setItem(value);
1937
- }
1938
2011
  }, 100)
1939
2012
  };
1940
2013
  var resetRelativesCache = () => {
@@ -2621,65 +2694,23 @@ var isRemoteOrEmbeddedMediaUrl = (path) => {
2621
2694
  }
2622
2695
  return path.startsWith("data:") || path.startsWith("blob:") || /^https?:\/\//i.test(path);
2623
2696
  };
2624
- var resolveLocalMediaUrl = async (path) => {
2697
+ var resolveLocalMediaUrl = async (path, context) => {
2625
2698
  if (!path) {
2626
2699
  return void 0;
2627
2700
  }
2628
- if (isRemoteOrEmbeddedMediaUrl(path)) {
2701
+ if (path.startsWith("data:") || path.startsWith("blob:")) {
2629
2702
  return path;
2630
2703
  }
2631
- const resolved = await localMediaResolver?.(path);
2632
- return resolved;
2633
- };
2634
- var implemented = (type, ...args) => {
2635
- };
2636
-
2637
- // src/utils/media-utils.ts
2638
- var getFileExtension = (filename) => {
2639
- if (!filename) {
2640
- return "";
2641
- }
2642
- if (filename.startsWith("data:")) {
2643
- const mime = filename.slice(5).split(";")[0] || "";
2644
- const subtype = (mime.split("/")[1] || "").toLowerCase();
2645
- if (subtype === "jpeg") {
2646
- return "jpg";
2647
- }
2648
- return subtype.split("+")[0] || "";
2649
- }
2650
- const withoutQuery = filename.split(/[?#]/)[0] || filename;
2651
- const match = withoutQuery.match(/\.([^.]+)$/);
2652
- return match ? match[1].toLowerCase() : "";
2653
- };
2654
- var isImageFormat = (format2) => {
2655
- if (!format2) {
2656
- return false;
2704
+ const resolved = await localMediaResolver?.(path, context);
2705
+ if (resolved) {
2706
+ return resolved;
2657
2707
  }
2658
- let normalized = format2.toLowerCase().trim();
2659
- if (normalized.startsWith("data:")) {
2660
- normalized = getFileExtension(normalized);
2661
- } else if (normalized.includes("/")) {
2662
- normalized = normalized.split("/")[1]?.split("+")[0] || "";
2663
- if (normalized === "jpeg") {
2664
- normalized = "jpg";
2665
- }
2708
+ if (/^https?:\/\//i.test(path)) {
2709
+ return path;
2666
2710
  }
2667
- const imageFormats = [
2668
- "jpg",
2669
- "jpeg",
2670
- "png",
2671
- "gif",
2672
- "bmp",
2673
- "webp",
2674
- "svg",
2675
- "tiff",
2676
- "tif"
2677
- ];
2678
- return imageFormats.includes(normalized);
2711
+ return void 0;
2679
2712
  };
2680
- var resolveObjeForm = (obje) => {
2681
- const value = obje?.get?.("FILE.FORM")?.toValue?.() ?? obje?.get?.("FORM")?.toValue?.();
2682
- return typeof value === "string" && value.trim() ? value.trim() : void 0;
2713
+ var implemented = (type, ...args) => {
2683
2714
  };
2684
2715
 
2685
2716
  // src/factories/place-parser-provider.ts
@@ -3985,22 +4016,19 @@ var Indi = class extends Common {
3985
4016
  if (objeList) {
3986
4017
  await Promise.all(
3987
4018
  objeList.map(async (objeRef) => {
3988
- const key = objeRef?.id;
4019
+ const key = objeXrefKey(objeRef, 0);
3989
4020
  const obje = objeRef?.standardizeMedia(
3990
4021
  namespace,
3991
4022
  true,
3992
- (ns, iId) => {
3993
- return ns && iId ? `https://mediasvc.ancestry.com/v2/image/namespaces/${ns}/media/${iId}?client=trees-mediaservice&imageQuality=hq` : void 0;
3994
- }
4023
+ ancestryMediaFileUrl
3995
4024
  );
3996
4025
  const isPrimary = obje?.get("_PRIM")?.toValue() === "Y";
3997
- const media = obje?.RIN?.toValue() || obje?.get("_OID")?.toValue();
3998
- const clone = obje?.get("_CLON._OID")?.toValue();
3999
- const mser = obje?.get("_MSER._LKID")?.toValue();
4026
+ const media = resolveObjeMediaId(obje);
4000
4027
  let url = obje?.get("FILE")?.toValue();
4001
4028
  const title = obje?.get("FILE.TITL")?.toValue() ?? obje?.get("TITL")?.toValue() ?? "";
4029
+ const note = objeNoteValue(obje);
4002
4030
  const type = resolveObjeForm(obje) ?? (url ? getFileExtension(url) : void 0) ?? "raw";
4003
- let imgId = clone || mser;
4031
+ let imgId = media;
4004
4032
  const hasEmbeddedOrLocalFile = !!url && (url.startsWith("data:") || url.startsWith("blob:") || !/^https?:\/\//i.test(url));
4005
4033
  if (!hasEmbeddedOrLocalFile && (!www || !tree || !this.id)) {
4006
4034
  return;
@@ -4036,6 +4064,7 @@ var Indi = class extends Common {
4036
4064
  imgId,
4037
4065
  person: this.id,
4038
4066
  title,
4067
+ note,
4039
4068
  url,
4040
4069
  contentType: type,
4041
4070
  downloadName: `${this.id.replaceAll("@", "")}_${this.toNaturalName()?.replaceAll(" ", "-") || ""}_${(title || key.replaceAll("@", "").toString()).replaceAll(" ", "-")}`
@@ -4074,7 +4103,7 @@ var Indi = class extends Common {
4074
4103
  return;
4075
4104
  }
4076
4105
  const obje = o;
4077
- const key = `@O${index}@`;
4106
+ const key = objeXrefKey(obje, index);
4078
4107
  obje.standardizeMedia();
4079
4108
  const isPrimary = obje?.get("_PRIM")?.toValue() === "Y";
4080
4109
  const url = obje?.get("FILE")?.toValue();
@@ -4093,6 +4122,7 @@ var Indi = class extends Common {
4093
4122
  imgId,
4094
4123
  person: this.id,
4095
4124
  title,
4125
+ note: objeNoteValue(obje),
4096
4126
  url,
4097
4127
  contentType: type,
4098
4128
  downloadName: `${this.id.replaceAll("@", "")}_${this.toNaturalName()?.replaceAll(" ", "-") || ""}_${(title || key.replaceAll("@", "").toString()).replaceAll(" ", "-")}`
@@ -4201,7 +4231,7 @@ var Indi = class extends Common {
4201
4231
  if (!obje) {
4202
4232
  return;
4203
4233
  }
4204
- const key = `@O${index}@`;
4234
+ const key = objeXrefKey(obje, index);
4205
4235
  const isPrimary = obje?.get("_PRIM")?.toValue() === "Y";
4206
4236
  const url = obje?.get("FILE")?.toValue();
4207
4237
  const title = obje?.get("TITL")?.toValue() ?? "";
@@ -4218,6 +4248,7 @@ var Indi = class extends Common {
4218
4248
  imgId,
4219
4249
  person: this.id,
4220
4250
  title,
4251
+ note: objeNoteValue(obje),
4221
4252
  url,
4222
4253
  contentType: type,
4223
4254
  downloadName: `${this.id.replaceAll("@", "")}_${this.toNaturalName()?.replaceAll(" ", "-") || ""}_${(title || key.replaceAll("@", "").toString()).replaceAll(" ", "-")}`
@@ -4241,7 +4272,7 @@ var Indi = class extends Common {
4241
4272
  if (!obje) {
4242
4273
  return;
4243
4274
  }
4244
- const key = `@O${index}@`;
4275
+ const key = objeXrefKey(obje, index);
4245
4276
  obje.standardizeMedia();
4246
4277
  const isPrimary = obje?.get("_PRIM")?.toValue() === "Y";
4247
4278
  const url = obje?.get("FILE")?.toValue();
@@ -4258,6 +4289,7 @@ var Indi = class extends Common {
4258
4289
  imgId,
4259
4290
  person: this.id,
4260
4291
  title,
4292
+ note: objeNoteValue(obje),
4261
4293
  url,
4262
4294
  contentType: type,
4263
4295
  downloadName: `${this.id.replaceAll("@", "")}_${this.toNaturalName()?.replaceAll(" ", "-") || ""}_${(title || key.replaceAll("@", "").toString()).replaceAll(" ", "-")}`
@@ -4289,7 +4321,12 @@ var Indi = class extends Common {
4289
4321
  );
4290
4322
  if (cached !== void 0) {
4291
4323
  if (cached?.file && !isRemoteOrEmbeddedMediaUrl(cached.file)) {
4292
- const resolvedCached = await resolveLocalMediaUrl(cached.file);
4324
+ const resolvedCached = await resolveLocalMediaUrl(cached.file, {
4325
+ url: cached.file,
4326
+ person: this.id,
4327
+ tree: this.getTreeId?.(),
4328
+ treeName: this.getTreeName?.()
4329
+ });
4293
4330
  if (resolvedCached && isRemoteOrEmbeddedMediaUrl(resolvedCached)) {
4294
4331
  const refreshed = { ...cached, file: resolvedCached };
4295
4332
  profilePictureCache(
@@ -4314,7 +4351,16 @@ var Indi = class extends Common {
4314
4351
  }
4315
4352
  const mediaArray = Object.values(mediaList);
4316
4353
  const toDisplayableProfile = async (media, isPrimary) => {
4317
- const resolvedFile = await resolveLocalMediaUrl(media.url);
4354
+ const resolvedFile = await resolveLocalMediaUrl(media.url, {
4355
+ url: media.url,
4356
+ id: media.id,
4357
+ imgId: media.imgId,
4358
+ key: media.key,
4359
+ contentType: media.contentType,
4360
+ person: media.person || this.id,
4361
+ tree: media.tree || this.getTreeId?.(),
4362
+ treeName: this.getTreeName?.()
4363
+ });
4318
4364
  if (!resolvedFile || !isRemoteOrEmbeddedMediaUrl(resolvedFile)) {
4319
4365
  return void 0;
4320
4366
  }