@treeviz/gedcom-parser 2.1.8 → 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.
Files changed (35) hide show
  1. package/dist/classes/common.d.ts.map +1 -1
  2. package/dist/classes/gedcom.d.ts +5 -0
  3. package/dist/classes/gedcom.d.ts.map +1 -1
  4. package/dist/classes/index.js +588 -75
  5. package/dist/classes/indi.d.ts.map +1 -1
  6. package/dist/classes/obje.d.ts.map +1 -1
  7. package/dist/cli/index.js +588 -75
  8. package/dist/constants/index.js +557 -70
  9. package/dist/factories/index.js +557 -70
  10. package/dist/index.js +593 -85
  11. package/dist/interfaces/indi.d.ts +1 -0
  12. package/dist/interfaces/indi.d.ts.map +1 -1
  13. package/dist/kinship-translator/index.d.ts +2 -0
  14. package/dist/kinship-translator/index.d.ts.map +1 -1
  15. package/dist/kinship-translator/index.js +558 -71
  16. package/dist/kinship-translator/kinship-translator.ja.d.ts +18 -0
  17. package/dist/kinship-translator/kinship-translator.ja.d.ts.map +1 -0
  18. package/dist/kinship-translator/kinship-translator.zh.d.ts +18 -0
  19. package/dist/kinship-translator/kinship-translator.zh.d.ts.map +1 -0
  20. package/dist/kinship-translator/patterns.ja.d.ts +2 -0
  21. package/dist/kinship-translator/patterns.ja.d.ts.map +1 -0
  22. package/dist/kinship-translator/patterns.zh.d.ts +2 -0
  23. package/dist/kinship-translator/patterns.zh.d.ts.map +1 -0
  24. package/dist/kinship-translator/translators.d.ts +2 -0
  25. package/dist/kinship-translator/translators.d.ts.map +1 -1
  26. package/dist/kinship-translator/types.d.ts +1 -1
  27. package/dist/kinship-translator/types.d.ts.map +1 -1
  28. package/dist/utils/cache.d.ts.map +1 -1
  29. package/dist/utils/gedzip.d.ts.map +1 -1
  30. package/dist/utils/index.js +593 -85
  31. package/dist/utils/local-media.d.ts +7 -3
  32. package/dist/utils/local-media.d.ts.map +1 -1
  33. package/dist/utils/media-utils.d.ts +20 -0
  34. package/dist/utils/media-utils.d.ts.map +1 -1
  35. package/package.json +1 -1
package/dist/cli/index.js CHANGED
@@ -41,6 +41,82 @@ var appendGedcomTrailer = (serialized) => {
41
41
  }
42
42
  return `${trimmed}${newline}0 TRLR`;
43
43
  };
44
+
45
+ // src/utils/media-utils.ts
46
+ var getFileExtension = (filename) => {
47
+ if (!filename) {
48
+ return "";
49
+ }
50
+ if (filename.startsWith("data:")) {
51
+ const mime = filename.slice(5).split(";")[0] || "";
52
+ const subtype = (mime.split("/")[1] || "").toLowerCase();
53
+ if (subtype === "jpeg") {
54
+ return "jpg";
55
+ }
56
+ return subtype.split("+")[0] || "";
57
+ }
58
+ const withoutQuery = filename.split(/[?#]/)[0] || filename;
59
+ const match = withoutQuery.match(/\.([^.]+)$/);
60
+ return match ? match[1].toLowerCase() : "";
61
+ };
62
+ var isImageFormat = (format2) => {
63
+ if (!format2) {
64
+ return false;
65
+ }
66
+ let normalized = format2.toLowerCase().trim();
67
+ if (normalized.startsWith("data:")) {
68
+ normalized = getFileExtension(normalized);
69
+ } else if (normalized.includes("/")) {
70
+ normalized = normalized.split("/")[1]?.split("+")[0] || "";
71
+ if (normalized === "jpeg") {
72
+ normalized = "jpg";
73
+ }
74
+ }
75
+ const imageFormats = [
76
+ "jpg",
77
+ "jpeg",
78
+ "png",
79
+ "gif",
80
+ "bmp",
81
+ "webp",
82
+ "svg",
83
+ "tiff",
84
+ "tif"
85
+ ];
86
+ return imageFormats.includes(normalized);
87
+ };
88
+ var resolveObjeForm = (obje) => {
89
+ const value = obje?.get?.("FILE.FORM")?.toValue?.() ?? obje?.get?.("FORM")?.toValue?.();
90
+ return typeof value === "string" && value.trim() ? value.trim() : void 0;
91
+ };
92
+ var mediaIdValue = (obje, path) => {
93
+ const value = obje?.get?.(path)?.toValue?.();
94
+ return typeof value === "string" && value.trim() ? value.trim() : void 0;
95
+ };
96
+ var resolveObjeMediaId = (obje) => mediaIdValue(obje, "RIN") || mediaIdValue(obje, "_CLON._OID") || mediaIdValue(obje, "_MSER._LKID") || mediaIdValue(obje, "_OID") || mediaIdValue(obje, "_LKID");
97
+ var ANCESTRY_MEDIA_RETRIEVAL_PREFIX = "https://www.ancestry.com/api/media/retrieval/v2/image";
98
+ var ANCESTRY_MEDIA_QUERY = "client=trees-mediaservice&imageQuality=hq";
99
+ var ancestryMediaPath = (namespace, imgId) => `/namespaces/${namespace}/media/${imgId}?${ANCESTRY_MEDIA_QUERY}`;
100
+ var ancestryMediaFileUrl = (namespace, imgId) => {
101
+ if (!namespace || !imgId) {
102
+ return void 0;
103
+ }
104
+ return `${ANCESTRY_MEDIA_RETRIEVAL_PREFIX}${ancestryMediaPath(namespace, imgId)}`;
105
+ };
106
+ var objeXrefKey = (obje, fallback = 0) => {
107
+ if (typeof obje?.id === "string" && obje.id) {
108
+ return obje.id;
109
+ }
110
+ const value = obje?.toValue?.();
111
+ if (typeof value === "string" && value.trim()) {
112
+ return value.trim();
113
+ }
114
+ if (typeof fallback === "string" && fallback.trim()) {
115
+ return fallback.trim();
116
+ }
117
+ return `@O${fallback}@`;
118
+ };
119
+ var objeNoteValue = (obje) => mediaIdValue(obje, "FILE.NOTE") || mediaIdValue(obje, "NOTE") || "";
44
120
  var List = class _List {
45
121
  // length = 0;
46
122
  constructor(items) {
@@ -690,7 +766,7 @@ var Common = class _Common {
690
766
  this,
691
767
  options.obje.namespace,
692
768
  options.obje.override,
693
- void 0,
769
+ this.isAncestry() ? ancestryMediaFileUrl : void 0,
694
770
  options.gedcomVersion
695
771
  );
696
772
  }
@@ -1209,11 +1285,8 @@ var storeCache = {
1209
1285
  getCacheDbs().relativesOnDegreeCache.setItem(value);
1210
1286
  }
1211
1287
  }, 50),
1212
- // profilePictureCache IS persisted to IndexedDB
1288
+ // Image bytes are stored as one IndexedDB record per photo.
1213
1289
  profilePictureCache: debounce((value) => {
1214
- if (value) {
1215
- getCacheDbs().profilePictureCache.setItem(value);
1216
- }
1217
1290
  }, 100)
1218
1291
  };
1219
1292
  var resetRelativesCache = () => {
@@ -1769,7 +1842,9 @@ __export(translators_exports, {
1769
1842
  es: () => KinshipTranslatorEs,
1770
1843
  fr: () => KinshipTranslatorFr,
1771
1844
  hu: () => KinshipTranslatorHU,
1772
- ru: () => KinshipTranslatorRu
1845
+ ja: () => KinshipTranslatorJa,
1846
+ ru: () => KinshipTranslatorRu,
1847
+ zh: () => KinshipTranslatorZh
1773
1848
  });
1774
1849
 
1775
1850
  // src/constants/filters.ts
@@ -2267,65 +2342,23 @@ var isRemoteOrEmbeddedMediaUrl = (path) => {
2267
2342
  }
2268
2343
  return path.startsWith("data:") || path.startsWith("blob:") || /^https?:\/\//i.test(path);
2269
2344
  };
2270
- var resolveLocalMediaUrl = async (path) => {
2345
+ var resolveLocalMediaUrl = async (path, context) => {
2271
2346
  if (!path) {
2272
2347
  return void 0;
2273
2348
  }
2274
- if (isRemoteOrEmbeddedMediaUrl(path)) {
2349
+ if (path.startsWith("data:") || path.startsWith("blob:")) {
2275
2350
  return path;
2276
2351
  }
2277
- const resolved = await localMediaResolver?.(path);
2278
- return resolved;
2279
- };
2280
- var implemented = (type, ...args) => {
2281
- };
2282
-
2283
- // src/utils/media-utils.ts
2284
- var getFileExtension = (filename) => {
2285
- if (!filename) {
2286
- return "";
2287
- }
2288
- if (filename.startsWith("data:")) {
2289
- const mime = filename.slice(5).split(";")[0] || "";
2290
- const subtype = (mime.split("/")[1] || "").toLowerCase();
2291
- if (subtype === "jpeg") {
2292
- return "jpg";
2293
- }
2294
- return subtype.split("+")[0] || "";
2352
+ const resolved = await localMediaResolver?.(path, context);
2353
+ if (resolved) {
2354
+ return resolved;
2295
2355
  }
2296
- const withoutQuery = filename.split(/[?#]/)[0] || filename;
2297
- const match = withoutQuery.match(/\.([^.]+)$/);
2298
- return match ? match[1].toLowerCase() : "";
2299
- };
2300
- var isImageFormat = (format2) => {
2301
- if (!format2) {
2302
- return false;
2303
- }
2304
- let normalized = format2.toLowerCase().trim();
2305
- if (normalized.startsWith("data:")) {
2306
- normalized = getFileExtension(normalized);
2307
- } else if (normalized.includes("/")) {
2308
- normalized = normalized.split("/")[1]?.split("+")[0] || "";
2309
- if (normalized === "jpeg") {
2310
- normalized = "jpg";
2311
- }
2356
+ if (/^https?:\/\//i.test(path)) {
2357
+ return path;
2312
2358
  }
2313
- const imageFormats = [
2314
- "jpg",
2315
- "jpeg",
2316
- "png",
2317
- "gif",
2318
- "bmp",
2319
- "webp",
2320
- "svg",
2321
- "tiff",
2322
- "tif"
2323
- ];
2324
- return imageFormats.includes(normalized);
2359
+ return void 0;
2325
2360
  };
2326
- var resolveObjeForm = (obje) => {
2327
- const value = obje?.get?.("FILE.FORM")?.toValue?.() ?? obje?.get?.("FORM")?.toValue?.();
2328
- return typeof value === "string" && value.trim() ? value.trim() : void 0;
2361
+ var implemented = (type, ...args) => {
2329
2362
  };
2330
2363
  var uniqueItemsCache = /* @__PURE__ */ new WeakMap();
2331
2364
  var setNestedGroup = (obj, key, value, uniqueCounting = true) => {
@@ -3502,22 +3535,19 @@ var Indi = class extends Common {
3502
3535
  if (objeList) {
3503
3536
  await Promise.all(
3504
3537
  objeList.map(async (objeRef) => {
3505
- const key = objeRef?.id;
3538
+ const key = objeXrefKey(objeRef, 0);
3506
3539
  const obje = objeRef?.standardizeMedia(
3507
3540
  namespace,
3508
3541
  true,
3509
- (ns, iId) => {
3510
- return ns && iId ? `https://mediasvc.ancestry.com/v2/image/namespaces/${ns}/media/${iId}?client=trees-mediaservice&imageQuality=hq` : void 0;
3511
- }
3542
+ ancestryMediaFileUrl
3512
3543
  );
3513
3544
  const isPrimary = obje?.get("_PRIM")?.toValue() === "Y";
3514
- const media = obje?.RIN?.toValue() || obje?.get("_OID")?.toValue();
3515
- const clone = obje?.get("_CLON._OID")?.toValue();
3516
- const mser = obje?.get("_MSER._LKID")?.toValue();
3545
+ const media = resolveObjeMediaId(obje);
3517
3546
  let url = obje?.get("FILE")?.toValue();
3518
3547
  const title = obje?.get("FILE.TITL")?.toValue() ?? obje?.get("TITL")?.toValue() ?? "";
3548
+ const note = objeNoteValue(obje);
3519
3549
  const type = resolveObjeForm(obje) ?? (url ? getFileExtension(url) : void 0) ?? "raw";
3520
- let imgId = clone || mser;
3550
+ let imgId = media;
3521
3551
  const hasEmbeddedOrLocalFile = !!url && (url.startsWith("data:") || url.startsWith("blob:") || !/^https?:\/\//i.test(url));
3522
3552
  if (!hasEmbeddedOrLocalFile && (!www || !tree || !this.id)) {
3523
3553
  return;
@@ -3553,6 +3583,7 @@ var Indi = class extends Common {
3553
3583
  imgId,
3554
3584
  person: this.id,
3555
3585
  title,
3586
+ note,
3556
3587
  url,
3557
3588
  contentType: type,
3558
3589
  downloadName: `${this.id.replaceAll("@", "")}_${this.toNaturalName()?.replaceAll(" ", "-") || ""}_${(title || key.replaceAll("@", "").toString()).replaceAll(" ", "-")}`
@@ -3591,7 +3622,7 @@ var Indi = class extends Common {
3591
3622
  return;
3592
3623
  }
3593
3624
  const obje = o;
3594
- const key = `@O${index}@`;
3625
+ const key = objeXrefKey(obje, index);
3595
3626
  obje.standardizeMedia();
3596
3627
  const isPrimary = obje?.get("_PRIM")?.toValue() === "Y";
3597
3628
  const url = obje?.get("FILE")?.toValue();
@@ -3610,6 +3641,7 @@ var Indi = class extends Common {
3610
3641
  imgId,
3611
3642
  person: this.id,
3612
3643
  title,
3644
+ note: objeNoteValue(obje),
3613
3645
  url,
3614
3646
  contentType: type,
3615
3647
  downloadName: `${this.id.replaceAll("@", "")}_${this.toNaturalName()?.replaceAll(" ", "-") || ""}_${(title || key.replaceAll("@", "").toString()).replaceAll(" ", "-")}`
@@ -3718,7 +3750,7 @@ var Indi = class extends Common {
3718
3750
  if (!obje) {
3719
3751
  return;
3720
3752
  }
3721
- const key = `@O${index}@`;
3753
+ const key = objeXrefKey(obje, index);
3722
3754
  const isPrimary = obje?.get("_PRIM")?.toValue() === "Y";
3723
3755
  const url = obje?.get("FILE")?.toValue();
3724
3756
  const title = obje?.get("TITL")?.toValue() ?? "";
@@ -3735,6 +3767,7 @@ var Indi = class extends Common {
3735
3767
  imgId,
3736
3768
  person: this.id,
3737
3769
  title,
3770
+ note: objeNoteValue(obje),
3738
3771
  url,
3739
3772
  contentType: type,
3740
3773
  downloadName: `${this.id.replaceAll("@", "")}_${this.toNaturalName()?.replaceAll(" ", "-") || ""}_${(title || key.replaceAll("@", "").toString()).replaceAll(" ", "-")}`
@@ -3758,7 +3791,7 @@ var Indi = class extends Common {
3758
3791
  if (!obje) {
3759
3792
  return;
3760
3793
  }
3761
- const key = `@O${index}@`;
3794
+ const key = objeXrefKey(obje, index);
3762
3795
  obje.standardizeMedia();
3763
3796
  const isPrimary = obje?.get("_PRIM")?.toValue() === "Y";
3764
3797
  const url = obje?.get("FILE")?.toValue();
@@ -3775,6 +3808,7 @@ var Indi = class extends Common {
3775
3808
  imgId,
3776
3809
  person: this.id,
3777
3810
  title,
3811
+ note: objeNoteValue(obje),
3778
3812
  url,
3779
3813
  contentType: type,
3780
3814
  downloadName: `${this.id.replaceAll("@", "")}_${this.toNaturalName()?.replaceAll(" ", "-") || ""}_${(title || key.replaceAll("@", "").toString()).replaceAll(" ", "-")}`
@@ -3806,7 +3840,12 @@ var Indi = class extends Common {
3806
3840
  );
3807
3841
  if (cached !== void 0) {
3808
3842
  if (cached?.file && !isRemoteOrEmbeddedMediaUrl(cached.file)) {
3809
- const resolvedCached = await resolveLocalMediaUrl(cached.file);
3843
+ const resolvedCached = await resolveLocalMediaUrl(cached.file, {
3844
+ url: cached.file,
3845
+ person: this.id,
3846
+ tree: this.getTreeId?.(),
3847
+ treeName: this.getTreeName?.()
3848
+ });
3810
3849
  if (resolvedCached && isRemoteOrEmbeddedMediaUrl(resolvedCached)) {
3811
3850
  const refreshed = { ...cached, file: resolvedCached };
3812
3851
  profilePictureCache(
@@ -3831,7 +3870,16 @@ var Indi = class extends Common {
3831
3870
  }
3832
3871
  const mediaArray = Object.values(mediaList);
3833
3872
  const toDisplayableProfile = async (media, isPrimary) => {
3834
- const resolvedFile = await resolveLocalMediaUrl(media.url);
3873
+ const resolvedFile = await resolveLocalMediaUrl(media.url, {
3874
+ url: media.url,
3875
+ id: media.id,
3876
+ imgId: media.imgId,
3877
+ key: media.key,
3878
+ contentType: media.contentType,
3879
+ person: media.person || this.id,
3880
+ tree: media.tree || this.getTreeId?.(),
3881
+ treeName: this.getTreeName?.()
3882
+ });
3835
3883
  if (!resolvedFile || !isRemoteOrEmbeddedMediaUrl(resolvedFile)) {
3836
3884
  return void 0;
3837
3885
  }
@@ -7019,6 +7067,445 @@ var KinshipTranslatorRu = class extends KinshipTranslatorBasic {
7019
7067
  }
7020
7068
  };
7021
7069
 
7070
+ // src/kinship-translator/patterns.ja.ts
7071
+ var InLawsJa = {
7072
+ "(\u5B50|\u5A18|\u606F\u5B50)\u306E\u914D\u5076\u8005": "\u7FA9\u7406\u306E\u5B50",
7073
+ "(\u5B50|\u5A18|\u606F\u5B50)\u306E\u59BB": "\u5AC1",
7074
+ "(\u5B50|\u5A18|\u606F\u5B50)\u306E\u592B": "\u5A7F",
7075
+ "(\u914D\u5076\u8005|\u59BB|\u592B)\u306E\u6BCD": "\u7FA9\u6BCD",
7076
+ "(\u914D\u5076\u8005|\u59BB|\u592B)\u306E\u7236": "\u7FA9\u7236",
7077
+ "(\u914D\u5076\u8005|\u59BB|\u592B)\u306E\u89AA": "\u7FA9\u7406\u306E\u89AA",
7078
+ "(\u7570\u7236\u6BCD\u306E)?(\u5144\u5F1F|\u59C9\u59B9|\u5144\u5F1F\u59C9\u59B9)\u306E\u59BB": "\u7FA9\u7406\u306E\u59C9\u59B9",
7079
+ "(\u7570\u7236\u6BCD\u306E)?(\u5144\u5F1F|\u59C9\u59B9|\u5144\u5F1F\u59C9\u59B9)\u306E\u592B": "\u7FA9\u7406\u306E\u5144\u5F1F",
7080
+ "(\u7570\u7236\u6BCD\u306E)?(\u5144\u5F1F|\u59C9\u59B9|\u5144\u5F1F\u59C9\u59B9)\u306E\u914D\u5076\u8005": "\u7FA9\u7406\u306E\u5144\u5F1F\u59C9\u59B9",
7081
+ "(\u7570\u7236\u6BCD\u306E)?\u59C9\u59B9\u306E(\u914D\u5076\u8005|\u59BB|\u592B)": "\u7FA9\u7406\u306E\u59C9\u59B9",
7082
+ "(\u7570\u7236\u6BCD\u306E)?\u5144\u5F1F\u306E(\u914D\u5076\u8005|\u59BB|\u592B)": "\u7FA9\u7406\u306E\u5144\u5F1F",
7083
+ "(\u7570\u7236\u6BCD\u306E)?\u5144\u5F1F\u59C9\u59B9\u306E(\u914D\u5076\u8005|\u59BB|\u592B)": "\u7FA9\u7406\u306E\u5144\u5F1F\u59C9\u59B9",
7084
+ "(\u7570\u7236\u6BCD\u306E)?(\u914D\u5076\u8005|\u59BB|\u592B)\u306E\u59C9\u59B9": "\u7FA9\u7406\u306E\u59C9\u59B9",
7085
+ "(\u7570\u7236\u6BCD\u306E)?(\u914D\u5076\u8005|\u59BB|\u592B)\u306E\u5144\u5F1F": "\u7FA9\u7406\u306E\u5144\u5F1F",
7086
+ "(\u7570\u7236\u6BCD\u306E)?(\u914D\u5076\u8005|\u59BB|\u592B)\u306E\u5144\u5F1F\u59C9\u59B9": "\u7FA9\u7406\u306E\u5144\u5F1F\u59C9\u59B9"
7087
+ };
7088
+
7089
+ // src/kinship-translator/kinship-translator.ja.ts
7090
+ var sexOf2 = (person) => {
7091
+ if (person?.isMale?.()) {
7092
+ return "m";
7093
+ }
7094
+ if (person?.isFemale?.()) {
7095
+ return "f";
7096
+ }
7097
+ return "n";
7098
+ };
7099
+ var pick = (sex, male, female, neutral) => {
7100
+ if (sex === "m") {
7101
+ return male;
7102
+ }
7103
+ if (sex === "f") {
7104
+ return female;
7105
+ }
7106
+ return neutral;
7107
+ };
7108
+ var lineal = (level, sex, kind) => {
7109
+ const L = Math.max(1, level);
7110
+ if (kind === "asc") {
7111
+ if (L <= 1) {
7112
+ return pick(sex, "\u7236", "\u6BCD", "\u89AA");
7113
+ }
7114
+ if (L === 2) {
7115
+ return pick(sex, "\u7956\u7236", "\u7956\u6BCD", "\u7956\u7236\u6BCD");
7116
+ }
7117
+ if (L === 3) {
7118
+ return pick(sex, "\u66FE\u7956\u7236", "\u66FE\u7956\u6BCD", "\u66FE\u7956\u7236\u6BCD");
7119
+ }
7120
+ if (L === 4) {
7121
+ return pick(sex, "\u9AD8\u7956\u7236", "\u9AD8\u7956\u6BCD", "\u9AD8\u7956\u7236\u6BCD");
7122
+ }
7123
+ return pick(
7124
+ sex,
7125
+ `${L - 1}\u4E16\u306E\u7956\u7236`,
7126
+ `${L - 1}\u4E16\u306E\u7956\u6BCD`,
7127
+ `${L - 1}\u4E16\u306E\u7956\u7236\u6BCD`
7128
+ );
7129
+ }
7130
+ if (L <= 1) {
7131
+ return pick(sex, "\u606F\u5B50", "\u5A18", "\u5B50");
7132
+ }
7133
+ if (L === 2) {
7134
+ return "\u5B6B";
7135
+ }
7136
+ if (L === 3) {
7137
+ return "\u66FE\u5B6B";
7138
+ }
7139
+ if (L === 4) {
7140
+ return "\u7384\u5B6B";
7141
+ }
7142
+ return `${L - 1}\u4E16\u306E\u5B6B`;
7143
+ };
7144
+ var cousinPlain = (degree) => {
7145
+ if (degree <= 1) {
7146
+ return "\u3044\u3068\u3053";
7147
+ }
7148
+ if (degree === 2) {
7149
+ return "\u307E\u305F\u3044\u3068\u3053";
7150
+ }
7151
+ if (degree === 3) {
7152
+ return "\u306F\u3068\u3053";
7153
+ }
7154
+ return `${degree}\u89AA\u7B49\u306E\u3044\u3068\u3053`;
7155
+ };
7156
+ var KinshipTranslatorJa = class extends KinshipTranslatorBasic {
7157
+ indirect() {
7158
+ let degree = Math.abs(this.pathN?.degree ?? 0);
7159
+ if (degree > 0) {
7160
+ degree = degree - 1;
7161
+ }
7162
+ return cousinPlain(degree);
7163
+ }
7164
+ removal() {
7165
+ const level = this.pathN?.level ?? 0;
7166
+ let degree = Math.abs(this.pathN?.degree ?? 0);
7167
+ if (degree > 0) {
7168
+ degree = degree - 1;
7169
+ }
7170
+ if (!degree) {
7171
+ return level < 0 ? this.nibling() : this.auncle();
7172
+ }
7173
+ const removed = Math.abs(level);
7174
+ return `${cousinPlain(degree)}\uFF08${removed}\u4E16\u4EE3\u9055\u3044\uFF09`;
7175
+ }
7176
+ auncle() {
7177
+ const level = Math.abs(this.pathN?.level ?? 0);
7178
+ const sex = sexOf2(this.personN);
7179
+ if (level <= 2) {
7180
+ return pick(sex, "\u304A\u3058", "\u304A\u3070", "\u304A\u3058/\u304A\u3070");
7181
+ }
7182
+ if (level === 3) {
7183
+ return pick(sex, "\u5927\u304A\u3058", "\u5927\u304A\u3070", "\u5927\u304A\u3058/\u5927\u304A\u3070");
7184
+ }
7185
+ return pick(
7186
+ sex,
7187
+ `${level - 2}\u4EE3\u524D\u306E\u304A\u3058`,
7188
+ `${level - 2}\u4EE3\u524D\u306E\u304A\u3070`,
7189
+ `${level - 2}\u4EE3\u524D\u306E\u304A\u3058/\u304A\u3070`
7190
+ );
7191
+ }
7192
+ nibling() {
7193
+ const level = Math.abs(this.pathN?.level ?? 0);
7194
+ const sex = sexOf2(this.personN);
7195
+ if (level <= 2) {
7196
+ return pick(sex, "\u7525", "\u59EA", "\u7525/\u59EA");
7197
+ }
7198
+ if (level === 3) {
7199
+ return pick(sex, "\u5927\u7525", "\u5927\u59EA", "\u5927\u7525/\u5927\u59EA");
7200
+ }
7201
+ return pick(
7202
+ sex,
7203
+ `${level - 2}\u4EE3\u4E0B\u306E\u7525`,
7204
+ `${level - 2}\u4EE3\u4E0B\u306E\u59EA`,
7205
+ `${level - 2}\u4EE3\u4E0B\u306E\u7525/\u59EA`
7206
+ );
7207
+ }
7208
+ parent() {
7209
+ return lineal(
7210
+ Math.abs(this.pathN?.level ?? 0),
7211
+ sexOf2(this.personN),
7212
+ "asc"
7213
+ );
7214
+ }
7215
+ child() {
7216
+ return lineal(
7217
+ Math.abs(this.pathN?.level ?? 0),
7218
+ sexOf2(this.personN),
7219
+ "desc"
7220
+ );
7221
+ }
7222
+ sibling() {
7223
+ return pick(sexOf2(this.personN), "\u5144\u5F1F", "\u59C9\u59B9", "\u5144\u5F1F\u59C9\u59B9");
7224
+ }
7225
+ halfBlood(relation) {
7226
+ if (!relation || !this.isHalfBlood) {
7227
+ return relation ?? "";
7228
+ }
7229
+ return `\u7570\u7236\u6BCD\u306E${relation}`;
7230
+ }
7231
+ spouse() {
7232
+ return pick(sexOf2(this.personN), "\u592B", "\u59BB", "\u914D\u5076\u8005");
7233
+ }
7234
+ ofSpouse(relation) {
7235
+ if (!relation) {
7236
+ return "";
7237
+ }
7238
+ const spouseType = pick(
7239
+ sexOf2(this.path?.[1].indi),
7240
+ "\u592B",
7241
+ "\u59BB",
7242
+ "\u914D\u5076\u8005"
7243
+ );
7244
+ return `${spouseType}\u306E${relation}`;
7245
+ }
7246
+ spouseOf(relation) {
7247
+ if (!relation) {
7248
+ return "";
7249
+ }
7250
+ const spouse = this.path?.[this.path.length - 1].indi;
7251
+ const spouseType = pick(sexOf2(spouse), "\u592B", "\u59BB", "\u914D\u5076\u8005");
7252
+ return `${relation}\u306E${spouseType}`;
7253
+ }
7254
+ of(relation) {
7255
+ const formattedName = nameFormatter(this.path?.[0]?.indi, {
7256
+ nameOrder: "last-first"
7257
+ });
7258
+ let name = formattedName.inOrder.filter(Boolean).join(" ");
7259
+ if (this.displayName === "none") {
7260
+ name = "";
7261
+ } else if (this.displayName === "givenname") {
7262
+ name = formattedName.givenname;
7263
+ } else if (this.displayName === "surname") {
7264
+ name = `${formattedName.surname}`;
7265
+ }
7266
+ if (!name || !relation) {
7267
+ return relation ?? "";
7268
+ }
7269
+ return `${name}\u306E${relation}`;
7270
+ }
7271
+ inLaw(relation) {
7272
+ let inLawRelation = relation;
7273
+ Object.keys(InLawsJa).find((pattern) => {
7274
+ const regex = new RegExp(`^${pattern}$`);
7275
+ if (relation?.match(regex)) {
7276
+ inLawRelation = InLawsJa[pattern];
7277
+ return true;
7278
+ }
7279
+ return false;
7280
+ });
7281
+ return inLawRelation ?? "";
7282
+ }
7283
+ relationType(relation) {
7284
+ if (!relation || !this.pathN?.relation) {
7285
+ return relation ?? "";
7286
+ }
7287
+ return `${this.pathN.relation}\u306E${relation}`;
7288
+ }
7289
+ };
7290
+
7291
+ // src/kinship-translator/patterns.zh.ts
7292
+ var InLawsZh = {
7293
+ "(\u5B50\u5973|\u5973\u513F|\u513F\u5B50)\u7684\u914D\u5076": "\u513F\u5AB3/\u5973\u5A7F",
7294
+ "(\u5B50\u5973|\u5973\u513F|\u513F\u5B50)\u7684\u59BB\u5B50": "\u513F\u5AB3",
7295
+ "(\u5B50\u5973|\u5973\u513F|\u513F\u5B50)\u7684\u4E08\u592B": "\u5973\u5A7F",
7296
+ "(\u914D\u5076|\u59BB\u5B50|\u4E08\u592B)\u7684\u6BCD\u4EB2": "\u5CB3\u6BCD/\u5A46\u5A46",
7297
+ "(\u914D\u5076|\u59BB\u5B50|\u4E08\u592B)\u7684\u7236\u4EB2": "\u5CB3\u7236/\u516C\u516C",
7298
+ "(\u914D\u5076|\u59BB\u5B50|\u4E08\u592B)\u7684\u7236\u6BCD": "\u5CB3\u7236\u5CB3\u6BCD/\u516C\u516C\u5A46\u5A46",
7299
+ "(\u5F02\u7236\u6BCD\u7684)?(\u5144\u5F1F\u59D0\u59B9|\u59D0\u59B9|\u5144\u5F1F)\u7684\u59BB\u5B50": "\u5AC2\u5B50/\u5F1F\u59B9",
7300
+ "(\u5F02\u7236\u6BCD\u7684)?(\u5144\u5F1F\u59D0\u59B9|\u59D0\u59B9|\u5144\u5F1F)\u7684\u4E08\u592B": "\u59D0\u592B/\u59B9\u592B",
7301
+ "(\u5F02\u7236\u6BCD\u7684)?(\u5144\u5F1F\u59D0\u59B9|\u59D0\u59B9|\u5144\u5F1F)\u7684\u914D\u5076": "\u59FB\u4EB2\u5144\u5F1F\u59D0\u59B9",
7302
+ "(\u5F02\u7236\u6BCD\u7684)?\u59D0\u59B9\u7684(\u914D\u5076|\u59BB\u5B50|\u4E08\u592B)": "\u59D0\u592B/\u59B9\u592B",
7303
+ "(\u5F02\u7236\u6BCD\u7684)?\u5144\u5F1F\u7684(\u914D\u5076|\u59BB\u5B50|\u4E08\u592B)": "\u5AC2\u5B50/\u5F1F\u59B9",
7304
+ "(\u5F02\u7236\u6BCD\u7684)?\u5144\u5F1F\u59D0\u59B9\u7684(\u914D\u5076|\u59BB\u5B50|\u4E08\u592B)": "\u59FB\u4EB2\u5144\u5F1F\u59D0\u59B9",
7305
+ "(\u5F02\u7236\u6BCD\u7684)?(\u914D\u5076|\u59BB\u5B50|\u4E08\u592B)\u7684\u59D0\u59B9": "\u59D1\u5B50/\u59E8\u5B50",
7306
+ "(\u5F02\u7236\u6BCD\u7684)?(\u914D\u5076|\u59BB\u5B50|\u4E08\u592B)\u7684\u5144\u5F1F": "\u5927\u4F2F/\u5C0F\u53D4/\u5185\u5144/\u5185\u5F1F",
7307
+ "(\u5F02\u7236\u6BCD\u7684)?(\u914D\u5076|\u59BB\u5B50|\u4E08\u592B)\u7684\u5144\u5F1F\u59D0\u59B9": "\u59FB\u4EB2\u5144\u5F1F\u59D0\u59B9"
7308
+ };
7309
+
7310
+ // src/kinship-translator/kinship-translator.zh.ts
7311
+ var sexOf3 = (person) => {
7312
+ if (person?.isMale?.()) {
7313
+ return "m";
7314
+ }
7315
+ if (person?.isFemale?.()) {
7316
+ return "f";
7317
+ }
7318
+ return "n";
7319
+ };
7320
+ var pick2 = (sex, male, female, neutral) => {
7321
+ if (sex === "m") {
7322
+ return male;
7323
+ }
7324
+ if (sex === "f") {
7325
+ return female;
7326
+ }
7327
+ return neutral;
7328
+ };
7329
+ var lineal2 = (level, sex, kind) => {
7330
+ const L = Math.max(1, level);
7331
+ if (kind === "asc") {
7332
+ if (L <= 1) {
7333
+ return pick2(sex, "\u7236\u4EB2", "\u6BCD\u4EB2", "\u7236\u6BCD");
7334
+ }
7335
+ if (L === 2) {
7336
+ return pick2(sex, "\u7956\u7236", "\u7956\u6BCD", "\u7956\u7236\u6BCD");
7337
+ }
7338
+ if (L === 3) {
7339
+ return pick2(sex, "\u66FE\u7956\u7236", "\u66FE\u7956\u6BCD", "\u66FE\u7956\u7236\u6BCD");
7340
+ }
7341
+ if (L === 4) {
7342
+ return pick2(sex, "\u9AD8\u7956\u7236", "\u9AD8\u7956\u6BCD", "\u9AD8\u7956\u7236\u6BCD");
7343
+ }
7344
+ return pick2(sex, `${L}\u4E16\u7956`, `${L}\u4E16\u7956\u6BCD`, `${L}\u4E16\u7956\u7236\u6BCD`);
7345
+ }
7346
+ if (L <= 1) {
7347
+ return pick2(sex, "\u513F\u5B50", "\u5973\u513F", "\u5B50\u5973");
7348
+ }
7349
+ if (L === 2) {
7350
+ return pick2(sex, "\u5B59\u5B50", "\u5B59\u5973", "\u5B59\u5B50\u5973");
7351
+ }
7352
+ if (L === 3) {
7353
+ return pick2(sex, "\u66FE\u5B59", "\u66FE\u5B59\u5973", "\u66FE\u5B59\u5B50\u5973");
7354
+ }
7355
+ if (L === 4) {
7356
+ return pick2(sex, "\u7384\u5B59", "\u7384\u5B59\u5973", "\u7384\u5B59\u5B50\u5973");
7357
+ }
7358
+ return pick2(sex, `${L}\u4E16\u5B59`, `${L}\u4E16\u5B59\u5973`, `${L}\u4E16\u5B59\u5B50\u5973`);
7359
+ };
7360
+ var cousinPlain2 = (degree, sex) => {
7361
+ if (degree <= 1) {
7362
+ return pick2(sex, "\u5802\u8868\u5144\u5F1F", "\u5802\u8868\u59D0\u59B9", "\u5802\u8868\u4EB2");
7363
+ }
7364
+ if (degree === 2) {
7365
+ return pick2(sex, "\u4ECE\u5802\u8868\u5144\u5F1F", "\u4ECE\u5802\u8868\u59D0\u59B9", "\u4ECE\u5802\u8868\u4EB2");
7366
+ }
7367
+ return pick2(
7368
+ sex,
7369
+ `${degree}\u4EE3\u5802\u8868\u5144\u5F1F`,
7370
+ `${degree}\u4EE3\u5802\u8868\u59D0\u59B9`,
7371
+ `${degree}\u4EE3\u5802\u8868\u4EB2`
7372
+ );
7373
+ };
7374
+ var KinshipTranslatorZh = class extends KinshipTranslatorBasic {
7375
+ indirect() {
7376
+ let degree = Math.abs(this.pathN?.degree ?? 0);
7377
+ if (degree > 0) {
7378
+ degree = degree - 1;
7379
+ }
7380
+ return cousinPlain2(degree, sexOf3(this.personN));
7381
+ }
7382
+ removal() {
7383
+ const level = this.pathN?.level ?? 0;
7384
+ let degree = Math.abs(this.pathN?.degree ?? 0);
7385
+ if (degree > 0) {
7386
+ degree = degree - 1;
7387
+ }
7388
+ if (!degree) {
7389
+ return level < 0 ? this.nibling() : this.auncle();
7390
+ }
7391
+ const removed = Math.abs(level);
7392
+ return `${cousinPlain2(degree, sexOf3(this.personN))}\uFF08\u9694${removed}\u4EE3\uFF09`;
7393
+ }
7394
+ auncle() {
7395
+ const level = Math.abs(this.pathN?.level ?? 0);
7396
+ const sex = sexOf3(this.personN);
7397
+ if (level <= 2) {
7398
+ return pick2(sex, "\u53D4\u53D4", "\u963F\u59E8", "\u53D4\u4F2F/\u59D1\u59E8");
7399
+ }
7400
+ if (level === 3) {
7401
+ return pick2(sex, "\u4F2F\u53D4\u7956\u7236", "\u59D1\u7956\u6BCD", "\u4F2F\u53D4\u7956\u7236\u6BCD");
7402
+ }
7403
+ return pick2(
7404
+ sex,
7405
+ `${level - 2}\u4EE3\u524D\u7684\u53D4\u53D4`,
7406
+ `${level - 2}\u4EE3\u524D\u7684\u963F\u59E8`,
7407
+ `${level - 2}\u4EE3\u524D\u7684\u53D4\u4F2F/\u59D1\u59E8`
7408
+ );
7409
+ }
7410
+ nibling() {
7411
+ const level = Math.abs(this.pathN?.level ?? 0);
7412
+ const sex = sexOf3(this.personN);
7413
+ if (level <= 2) {
7414
+ return pick2(sex, "\u4F84\u5B50", "\u4F84\u5973", "\u4F84\u5B50\u5973");
7415
+ }
7416
+ if (level === 3) {
7417
+ return pick2(sex, "\u4F84\u5B59", "\u4F84\u5B59\u5973", "\u4F84\u5B59\u5B50\u5973");
7418
+ }
7419
+ return pick2(
7420
+ sex,
7421
+ `${level - 2}\u4EE3\u4E0B\u7684\u4F84\u5B50`,
7422
+ `${level - 2}\u4EE3\u4E0B\u7684\u4F84\u5973`,
7423
+ `${level - 2}\u4EE3\u4E0B\u7684\u4F84\u5B50\u5973`
7424
+ );
7425
+ }
7426
+ parent() {
7427
+ return lineal2(
7428
+ Math.abs(this.pathN?.level ?? 0),
7429
+ sexOf3(this.personN),
7430
+ "asc"
7431
+ );
7432
+ }
7433
+ child() {
7434
+ return lineal2(
7435
+ Math.abs(this.pathN?.level ?? 0),
7436
+ sexOf3(this.personN),
7437
+ "desc"
7438
+ );
7439
+ }
7440
+ sibling() {
7441
+ return pick2(sexOf3(this.personN), "\u5144\u5F1F", "\u59D0\u59B9", "\u5144\u5F1F\u59D0\u59B9");
7442
+ }
7443
+ halfBlood(relation) {
7444
+ if (!relation || !this.isHalfBlood) {
7445
+ return relation ?? "";
7446
+ }
7447
+ return `\u5F02\u7236\u6BCD\u7684${relation}`;
7448
+ }
7449
+ spouse() {
7450
+ return pick2(sexOf3(this.personN), "\u4E08\u592B", "\u59BB\u5B50", "\u914D\u5076");
7451
+ }
7452
+ ofSpouse(relation) {
7453
+ if (!relation) {
7454
+ return "";
7455
+ }
7456
+ const spouseType = pick2(
7457
+ sexOf3(this.path?.[1].indi),
7458
+ "\u4E08\u592B",
7459
+ "\u59BB\u5B50",
7460
+ "\u914D\u5076"
7461
+ );
7462
+ return `${spouseType}\u7684${relation}`;
7463
+ }
7464
+ spouseOf(relation) {
7465
+ if (!relation) {
7466
+ return "";
7467
+ }
7468
+ const spouse = this.path?.[this.path.length - 1].indi;
7469
+ const spouseType = pick2(sexOf3(spouse), "\u4E08\u592B", "\u59BB\u5B50", "\u914D\u5076");
7470
+ return `${relation}\u7684${spouseType}`;
7471
+ }
7472
+ of(relation) {
7473
+ const formattedName = nameFormatter(this.path?.[0]?.indi, {
7474
+ nameOrder: "last-first"
7475
+ });
7476
+ let name = formattedName.inOrder.filter(Boolean).join(" ");
7477
+ if (this.displayName === "none") {
7478
+ name = "";
7479
+ } else if (this.displayName === "givenname") {
7480
+ name = formattedName.givenname;
7481
+ } else if (this.displayName === "surname") {
7482
+ name = `${formattedName.surname}`;
7483
+ }
7484
+ if (!name || !relation) {
7485
+ return relation ?? "";
7486
+ }
7487
+ return `${name}\u7684${relation}`;
7488
+ }
7489
+ inLaw(relation) {
7490
+ let inLawRelation = relation;
7491
+ Object.keys(InLawsZh).find((pattern) => {
7492
+ const regex = new RegExp(`^${pattern}$`);
7493
+ if (relation?.match(regex)) {
7494
+ inLawRelation = InLawsZh[pattern];
7495
+ return true;
7496
+ }
7497
+ return false;
7498
+ });
7499
+ return inLawRelation ?? "";
7500
+ }
7501
+ relationType(relation) {
7502
+ if (!relation || !this.pathN?.relation) {
7503
+ return relation ?? "";
7504
+ }
7505
+ return `${this.pathN.relation}${relation}`;
7506
+ }
7507
+ };
7508
+
7022
7509
  // src/kinship-translator/kinship-translator.ts
7023
7510
  var KinshipTranslator = class {
7024
7511
  constructor(person1, person2, lang = "en", entirePath, displayName = "givenname") {
@@ -8170,7 +8657,7 @@ var ensureExtensionSchema = (gedcom, extraTags) => {
8170
8657
 
8171
8658
  // package.json
8172
8659
  var package_default = {
8173
- version: "2.1.8"};
8660
+ version: "2.1.11"};
8174
8661
 
8175
8662
  // src/utils/get-product-details.ts
8176
8663
  var isDevelopment = () => {
@@ -8253,16 +8740,26 @@ var Obje = class extends Common {
8253
8740
  if (!this._gedcom) {
8254
8741
  return this;
8255
8742
  }
8743
+ if (typeof this.value === "string" && isId(this.value) && this.refType === "OBJE") {
8744
+ const resolved = this.ref;
8745
+ if (resolved && resolved !== this && typeof resolved.standardizeMedia === "function") {
8746
+ resolved.standardizeMedia(
8747
+ namespace,
8748
+ override,
8749
+ urlGetter,
8750
+ gedcomVersion
8751
+ );
8752
+ return this;
8753
+ }
8754
+ }
8256
8755
  const rin = this?.get("RIN")?.toValue();
8257
- const clone = this?.get("_CLON._OID")?.toValue();
8258
- const mser = this?.get("_MSER._LKID")?.toValue();
8259
8756
  const title = this?.get("FILE.TITL")?.toValue() ?? this?.get("TITL")?.toValue() ?? "";
8260
8757
  const note = this?.get("FILE.NOTE")?.toValue() ?? this?.get("NOTE")?.toValue() ?? "";
8261
8758
  const formRaw = this?.get("FILE.FORM")?.toValue() ?? this?.get("FORM")?.toValue();
8262
8759
  const mediType = this?.get("FILE.FORM.TYPE")?.toValue() ?? this?.get("FORM.TYPE")?.toValue() ?? this?.get("MEDI")?.toValue();
8263
8760
  const file = this?.get("FILE")?.toValue();
8264
- const imgId = rin || clone || mser;
8265
- const url = file || namespace && urlGetter?.(namespace, imgId);
8761
+ const imgId = resolveObjeMediaId(this);
8762
+ const url = file || this.isAncestry() && namespace && urlGetter?.(namespace, imgId);
8266
8763
  if (!url) {
8267
8764
  return this;
8268
8765
  }
@@ -8775,6 +9272,22 @@ var GedCom = class extends Common {
8775
9272
  obje(index) {
8776
9273
  return this.getMain(this.objes(), index);
8777
9274
  }
9275
+ /**
9276
+ * People who link a shared multimedia record (`1 OBJE @On@`), i.e. Ancestry
9277
+ * face tags / everyone the photo is attached to.
9278
+ */
9279
+ indisLinkingObje(objeKey) {
9280
+ const people = [];
9281
+ this.indis()?.forEach((indi) => {
9282
+ const linked = indi?.get("OBJE")?.toList()?.values()?.some(
9283
+ (item) => item?.toValue?.() === objeKey || item?.id === objeKey
9284
+ );
9285
+ if (linked && indi) {
9286
+ people.push(indi);
9287
+ }
9288
+ });
9289
+ return people;
9290
+ }
8778
9291
  sour(index) {
8779
9292
  return this.getMain(this.sours(), index);
8780
9293
  }