@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
@@ -98,7 +98,9 @@ __export(translators_exports, {
98
98
  es: () => KinshipTranslatorEs,
99
99
  fr: () => KinshipTranslatorFr,
100
100
  hu: () => KinshipTranslatorHU,
101
- ru: () => KinshipTranslatorRu
101
+ ja: () => KinshipTranslatorJa,
102
+ ru: () => KinshipTranslatorRu,
103
+ zh: () => KinshipTranslatorZh
102
104
  });
103
105
  var getGedcomId = (gedcom) => {
104
106
  if (!gedcom) {
@@ -169,11 +171,8 @@ var storeCache = {
169
171
  getCacheDbs().relativesOnDegreeCache.setItem(value);
170
172
  }
171
173
  }, 50),
172
- // profilePictureCache IS persisted to IndexedDB
174
+ // Image bytes are stored as one IndexedDB record per photo.
173
175
  profilePictureCache: debounce((value) => {
174
- if (value) {
175
- getCacheDbs().profilePictureCache.setItem(value);
176
- }
177
176
  }, 100)
178
177
  };
179
178
  var resetRelativesCache = () => {
@@ -553,6 +552,82 @@ var dateFormatter = (indi, showMarriages = false, showDays = false, showPlaces =
553
552
  // src/utils/gedcom-trailer.ts
554
553
  var GEDCOM_TRAILER_TAG = "TRLR";
555
554
  var isGedcomTrailerTag = (tag) => tag === GEDCOM_TRAILER_TAG;
555
+
556
+ // src/utils/media-utils.ts
557
+ var getFileExtension = (filename) => {
558
+ if (!filename) {
559
+ return "";
560
+ }
561
+ if (filename.startsWith("data:")) {
562
+ const mime = filename.slice(5).split(";")[0] || "";
563
+ const subtype = (mime.split("/")[1] || "").toLowerCase();
564
+ if (subtype === "jpeg") {
565
+ return "jpg";
566
+ }
567
+ return subtype.split("+")[0] || "";
568
+ }
569
+ const withoutQuery = filename.split(/[?#]/)[0] || filename;
570
+ const match = withoutQuery.match(/\.([^.]+)$/);
571
+ return match ? match[1].toLowerCase() : "";
572
+ };
573
+ var isImageFormat = (format2) => {
574
+ if (!format2) {
575
+ return false;
576
+ }
577
+ let normalized = format2.toLowerCase().trim();
578
+ if (normalized.startsWith("data:")) {
579
+ normalized = getFileExtension(normalized);
580
+ } else if (normalized.includes("/")) {
581
+ normalized = normalized.split("/")[1]?.split("+")[0] || "";
582
+ if (normalized === "jpeg") {
583
+ normalized = "jpg";
584
+ }
585
+ }
586
+ const imageFormats = [
587
+ "jpg",
588
+ "jpeg",
589
+ "png",
590
+ "gif",
591
+ "bmp",
592
+ "webp",
593
+ "svg",
594
+ "tiff",
595
+ "tif"
596
+ ];
597
+ return imageFormats.includes(normalized);
598
+ };
599
+ var resolveObjeForm = (obje) => {
600
+ const value = obje?.get?.("FILE.FORM")?.toValue?.() ?? obje?.get?.("FORM")?.toValue?.();
601
+ return typeof value === "string" && value.trim() ? value.trim() : void 0;
602
+ };
603
+ var mediaIdValue = (obje, path) => {
604
+ const value = obje?.get?.(path)?.toValue?.();
605
+ return typeof value === "string" && value.trim() ? value.trim() : void 0;
606
+ };
607
+ var resolveObjeMediaId = (obje) => mediaIdValue(obje, "RIN") || mediaIdValue(obje, "_CLON._OID") || mediaIdValue(obje, "_MSER._LKID") || mediaIdValue(obje, "_OID") || mediaIdValue(obje, "_LKID");
608
+ var ANCESTRY_MEDIA_RETRIEVAL_PREFIX = "https://www.ancestry.com/api/media/retrieval/v2/image";
609
+ var ANCESTRY_MEDIA_QUERY = "client=trees-mediaservice&imageQuality=hq";
610
+ var ancestryMediaPath = (namespace, imgId) => `/namespaces/${namespace}/media/${imgId}?${ANCESTRY_MEDIA_QUERY}`;
611
+ var ancestryMediaFileUrl = (namespace, imgId) => {
612
+ if (!namespace || !imgId) {
613
+ return void 0;
614
+ }
615
+ return `${ANCESTRY_MEDIA_RETRIEVAL_PREFIX}${ancestryMediaPath(namespace, imgId)}`;
616
+ };
617
+ var objeXrefKey = (obje, fallback = 0) => {
618
+ if (typeof obje?.id === "string" && obje.id) {
619
+ return obje.id;
620
+ }
621
+ const value = obje?.toValue?.();
622
+ if (typeof value === "string" && value.trim()) {
623
+ return value.trim();
624
+ }
625
+ if (typeof fallback === "string" && fallback.trim()) {
626
+ return fallback.trim();
627
+ }
628
+ return `@O${fallback}@`;
629
+ };
630
+ var objeNoteValue = (obje) => mediaIdValue(obje, "FILE.NOTE") || mediaIdValue(obje, "NOTE") || "";
556
631
  var List = class _List {
557
632
  // length = 0;
558
633
  constructor(items) {
@@ -1202,7 +1277,7 @@ var Common = class _Common {
1202
1277
  this,
1203
1278
  options.obje.namespace,
1204
1279
  options.obje.override,
1205
- void 0,
1280
+ this.isAncestry() ? ancestryMediaFileUrl : void 0,
1206
1281
  options.gedcomVersion
1207
1282
  );
1208
1283
  }
@@ -2150,65 +2225,23 @@ var isRemoteOrEmbeddedMediaUrl = (path) => {
2150
2225
  }
2151
2226
  return path.startsWith("data:") || path.startsWith("blob:") || /^https?:\/\//i.test(path);
2152
2227
  };
2153
- var resolveLocalMediaUrl = async (path) => {
2228
+ var resolveLocalMediaUrl = async (path, context) => {
2154
2229
  if (!path) {
2155
2230
  return void 0;
2156
2231
  }
2157
- if (isRemoteOrEmbeddedMediaUrl(path)) {
2232
+ if (path.startsWith("data:") || path.startsWith("blob:")) {
2158
2233
  return path;
2159
2234
  }
2160
- const resolved = await localMediaResolver?.(path);
2161
- return resolved;
2162
- };
2163
- var implemented = (type, ...args) => {
2164
- };
2165
-
2166
- // src/utils/media-utils.ts
2167
- var getFileExtension = (filename) => {
2168
- if (!filename) {
2169
- return "";
2170
- }
2171
- if (filename.startsWith("data:")) {
2172
- const mime = filename.slice(5).split(";")[0] || "";
2173
- const subtype = (mime.split("/")[1] || "").toLowerCase();
2174
- if (subtype === "jpeg") {
2175
- return "jpg";
2176
- }
2177
- return subtype.split("+")[0] || "";
2178
- }
2179
- const withoutQuery = filename.split(/[?#]/)[0] || filename;
2180
- const match = withoutQuery.match(/\.([^.]+)$/);
2181
- return match ? match[1].toLowerCase() : "";
2182
- };
2183
- var isImageFormat = (format2) => {
2184
- if (!format2) {
2185
- return false;
2235
+ const resolved = await localMediaResolver?.(path, context);
2236
+ if (resolved) {
2237
+ return resolved;
2186
2238
  }
2187
- let normalized = format2.toLowerCase().trim();
2188
- if (normalized.startsWith("data:")) {
2189
- normalized = getFileExtension(normalized);
2190
- } else if (normalized.includes("/")) {
2191
- normalized = normalized.split("/")[1]?.split("+")[0] || "";
2192
- if (normalized === "jpeg") {
2193
- normalized = "jpg";
2194
- }
2239
+ if (/^https?:\/\//i.test(path)) {
2240
+ return path;
2195
2241
  }
2196
- const imageFormats = [
2197
- "jpg",
2198
- "jpeg",
2199
- "png",
2200
- "gif",
2201
- "bmp",
2202
- "webp",
2203
- "svg",
2204
- "tiff",
2205
- "tif"
2206
- ];
2207
- return imageFormats.includes(normalized);
2242
+ return void 0;
2208
2243
  };
2209
- var resolveObjeForm = (obje) => {
2210
- const value = obje?.get?.("FILE.FORM")?.toValue?.() ?? obje?.get?.("FORM")?.toValue?.();
2211
- return typeof value === "string" && value.trim() ? value.trim() : void 0;
2244
+ var implemented = (type, ...args) => {
2212
2245
  };
2213
2246
  var uniqueItemsCache = /* @__PURE__ */ new WeakMap();
2214
2247
  var setNestedGroup = (obj, key, value, uniqueCounting = true) => {
@@ -3486,22 +3519,19 @@ var Indi = class extends Common {
3486
3519
  if (objeList) {
3487
3520
  await Promise.all(
3488
3521
  objeList.map(async (objeRef) => {
3489
- const key = objeRef?.id;
3522
+ const key = objeXrefKey(objeRef, 0);
3490
3523
  const obje = objeRef?.standardizeMedia(
3491
3524
  namespace,
3492
3525
  true,
3493
- (ns, iId) => {
3494
- return ns && iId ? `https://mediasvc.ancestry.com/v2/image/namespaces/${ns}/media/${iId}?client=trees-mediaservice&imageQuality=hq` : void 0;
3495
- }
3526
+ ancestryMediaFileUrl
3496
3527
  );
3497
3528
  const isPrimary = obje?.get("_PRIM")?.toValue() === "Y";
3498
- const media = obje?.RIN?.toValue() || obje?.get("_OID")?.toValue();
3499
- const clone = obje?.get("_CLON._OID")?.toValue();
3500
- const mser = obje?.get("_MSER._LKID")?.toValue();
3529
+ const media = resolveObjeMediaId(obje);
3501
3530
  let url = obje?.get("FILE")?.toValue();
3502
3531
  const title = obje?.get("FILE.TITL")?.toValue() ?? obje?.get("TITL")?.toValue() ?? "";
3532
+ const note = objeNoteValue(obje);
3503
3533
  const type = resolveObjeForm(obje) ?? (url ? getFileExtension(url) : void 0) ?? "raw";
3504
- let imgId = clone || mser;
3534
+ let imgId = media;
3505
3535
  const hasEmbeddedOrLocalFile = !!url && (url.startsWith("data:") || url.startsWith("blob:") || !/^https?:\/\//i.test(url));
3506
3536
  if (!hasEmbeddedOrLocalFile && (!www || !tree || !this.id)) {
3507
3537
  return;
@@ -3537,6 +3567,7 @@ var Indi = class extends Common {
3537
3567
  imgId,
3538
3568
  person: this.id,
3539
3569
  title,
3570
+ note,
3540
3571
  url,
3541
3572
  contentType: type,
3542
3573
  downloadName: `${this.id.replaceAll("@", "")}_${this.toNaturalName()?.replaceAll(" ", "-") || ""}_${(title || key.replaceAll("@", "").toString()).replaceAll(" ", "-")}`
@@ -3575,7 +3606,7 @@ var Indi = class extends Common {
3575
3606
  return;
3576
3607
  }
3577
3608
  const obje = o;
3578
- const key = `@O${index}@`;
3609
+ const key = objeXrefKey(obje, index);
3579
3610
  obje.standardizeMedia();
3580
3611
  const isPrimary = obje?.get("_PRIM")?.toValue() === "Y";
3581
3612
  const url = obje?.get("FILE")?.toValue();
@@ -3594,6 +3625,7 @@ var Indi = class extends Common {
3594
3625
  imgId,
3595
3626
  person: this.id,
3596
3627
  title,
3628
+ note: objeNoteValue(obje),
3597
3629
  url,
3598
3630
  contentType: type,
3599
3631
  downloadName: `${this.id.replaceAll("@", "")}_${this.toNaturalName()?.replaceAll(" ", "-") || ""}_${(title || key.replaceAll("@", "").toString()).replaceAll(" ", "-")}`
@@ -3702,7 +3734,7 @@ var Indi = class extends Common {
3702
3734
  if (!obje) {
3703
3735
  return;
3704
3736
  }
3705
- const key = `@O${index}@`;
3737
+ const key = objeXrefKey(obje, index);
3706
3738
  const isPrimary = obje?.get("_PRIM")?.toValue() === "Y";
3707
3739
  const url = obje?.get("FILE")?.toValue();
3708
3740
  const title = obje?.get("TITL")?.toValue() ?? "";
@@ -3719,6 +3751,7 @@ var Indi = class extends Common {
3719
3751
  imgId,
3720
3752
  person: this.id,
3721
3753
  title,
3754
+ note: objeNoteValue(obje),
3722
3755
  url,
3723
3756
  contentType: type,
3724
3757
  downloadName: `${this.id.replaceAll("@", "")}_${this.toNaturalName()?.replaceAll(" ", "-") || ""}_${(title || key.replaceAll("@", "").toString()).replaceAll(" ", "-")}`
@@ -3742,7 +3775,7 @@ var Indi = class extends Common {
3742
3775
  if (!obje) {
3743
3776
  return;
3744
3777
  }
3745
- const key = `@O${index}@`;
3778
+ const key = objeXrefKey(obje, index);
3746
3779
  obje.standardizeMedia();
3747
3780
  const isPrimary = obje?.get("_PRIM")?.toValue() === "Y";
3748
3781
  const url = obje?.get("FILE")?.toValue();
@@ -3759,6 +3792,7 @@ var Indi = class extends Common {
3759
3792
  imgId,
3760
3793
  person: this.id,
3761
3794
  title,
3795
+ note: objeNoteValue(obje),
3762
3796
  url,
3763
3797
  contentType: type,
3764
3798
  downloadName: `${this.id.replaceAll("@", "")}_${this.toNaturalName()?.replaceAll(" ", "-") || ""}_${(title || key.replaceAll("@", "").toString()).replaceAll(" ", "-")}`
@@ -3790,7 +3824,12 @@ var Indi = class extends Common {
3790
3824
  );
3791
3825
  if (cached !== void 0) {
3792
3826
  if (cached?.file && !isRemoteOrEmbeddedMediaUrl(cached.file)) {
3793
- const resolvedCached = await resolveLocalMediaUrl(cached.file);
3827
+ const resolvedCached = await resolveLocalMediaUrl(cached.file, {
3828
+ url: cached.file,
3829
+ person: this.id,
3830
+ tree: this.getTreeId?.(),
3831
+ treeName: this.getTreeName?.()
3832
+ });
3794
3833
  if (resolvedCached && isRemoteOrEmbeddedMediaUrl(resolvedCached)) {
3795
3834
  const refreshed = { ...cached, file: resolvedCached };
3796
3835
  profilePictureCache(
@@ -3815,7 +3854,16 @@ var Indi = class extends Common {
3815
3854
  }
3816
3855
  const mediaArray = Object.values(mediaList);
3817
3856
  const toDisplayableProfile = async (media, isPrimary) => {
3818
- const resolvedFile = await resolveLocalMediaUrl(media.url);
3857
+ const resolvedFile = await resolveLocalMediaUrl(media.url, {
3858
+ url: media.url,
3859
+ id: media.id,
3860
+ imgId: media.imgId,
3861
+ key: media.key,
3862
+ contentType: media.contentType,
3863
+ person: media.person || this.id,
3864
+ tree: media.tree || this.getTreeId?.(),
3865
+ treeName: this.getTreeName?.()
3866
+ });
3819
3867
  if (!resolvedFile || !isRemoteOrEmbeddedMediaUrl(resolvedFile)) {
3820
3868
  return void 0;
3821
3869
  }
@@ -7003,6 +7051,445 @@ var KinshipTranslatorRu = class extends KinshipTranslatorBasic {
7003
7051
  }
7004
7052
  };
7005
7053
 
7054
+ // src/kinship-translator/patterns.ja.ts
7055
+ var InLawsJa = {
7056
+ "(\u5B50|\u5A18|\u606F\u5B50)\u306E\u914D\u5076\u8005": "\u7FA9\u7406\u306E\u5B50",
7057
+ "(\u5B50|\u5A18|\u606F\u5B50)\u306E\u59BB": "\u5AC1",
7058
+ "(\u5B50|\u5A18|\u606F\u5B50)\u306E\u592B": "\u5A7F",
7059
+ "(\u914D\u5076\u8005|\u59BB|\u592B)\u306E\u6BCD": "\u7FA9\u6BCD",
7060
+ "(\u914D\u5076\u8005|\u59BB|\u592B)\u306E\u7236": "\u7FA9\u7236",
7061
+ "(\u914D\u5076\u8005|\u59BB|\u592B)\u306E\u89AA": "\u7FA9\u7406\u306E\u89AA",
7062
+ "(\u7570\u7236\u6BCD\u306E)?(\u5144\u5F1F|\u59C9\u59B9|\u5144\u5F1F\u59C9\u59B9)\u306E\u59BB": "\u7FA9\u7406\u306E\u59C9\u59B9",
7063
+ "(\u7570\u7236\u6BCD\u306E)?(\u5144\u5F1F|\u59C9\u59B9|\u5144\u5F1F\u59C9\u59B9)\u306E\u592B": "\u7FA9\u7406\u306E\u5144\u5F1F",
7064
+ "(\u7570\u7236\u6BCD\u306E)?(\u5144\u5F1F|\u59C9\u59B9|\u5144\u5F1F\u59C9\u59B9)\u306E\u914D\u5076\u8005": "\u7FA9\u7406\u306E\u5144\u5F1F\u59C9\u59B9",
7065
+ "(\u7570\u7236\u6BCD\u306E)?\u59C9\u59B9\u306E(\u914D\u5076\u8005|\u59BB|\u592B)": "\u7FA9\u7406\u306E\u59C9\u59B9",
7066
+ "(\u7570\u7236\u6BCD\u306E)?\u5144\u5F1F\u306E(\u914D\u5076\u8005|\u59BB|\u592B)": "\u7FA9\u7406\u306E\u5144\u5F1F",
7067
+ "(\u7570\u7236\u6BCD\u306E)?\u5144\u5F1F\u59C9\u59B9\u306E(\u914D\u5076\u8005|\u59BB|\u592B)": "\u7FA9\u7406\u306E\u5144\u5F1F\u59C9\u59B9",
7068
+ "(\u7570\u7236\u6BCD\u306E)?(\u914D\u5076\u8005|\u59BB|\u592B)\u306E\u59C9\u59B9": "\u7FA9\u7406\u306E\u59C9\u59B9",
7069
+ "(\u7570\u7236\u6BCD\u306E)?(\u914D\u5076\u8005|\u59BB|\u592B)\u306E\u5144\u5F1F": "\u7FA9\u7406\u306E\u5144\u5F1F",
7070
+ "(\u7570\u7236\u6BCD\u306E)?(\u914D\u5076\u8005|\u59BB|\u592B)\u306E\u5144\u5F1F\u59C9\u59B9": "\u7FA9\u7406\u306E\u5144\u5F1F\u59C9\u59B9"
7071
+ };
7072
+
7073
+ // src/kinship-translator/kinship-translator.ja.ts
7074
+ var sexOf2 = (person) => {
7075
+ if (person?.isMale?.()) {
7076
+ return "m";
7077
+ }
7078
+ if (person?.isFemale?.()) {
7079
+ return "f";
7080
+ }
7081
+ return "n";
7082
+ };
7083
+ var pick = (sex, male, female, neutral) => {
7084
+ if (sex === "m") {
7085
+ return male;
7086
+ }
7087
+ if (sex === "f") {
7088
+ return female;
7089
+ }
7090
+ return neutral;
7091
+ };
7092
+ var lineal = (level, sex, kind) => {
7093
+ const L = Math.max(1, level);
7094
+ if (kind === "asc") {
7095
+ if (L <= 1) {
7096
+ return pick(sex, "\u7236", "\u6BCD", "\u89AA");
7097
+ }
7098
+ if (L === 2) {
7099
+ return pick(sex, "\u7956\u7236", "\u7956\u6BCD", "\u7956\u7236\u6BCD");
7100
+ }
7101
+ if (L === 3) {
7102
+ return pick(sex, "\u66FE\u7956\u7236", "\u66FE\u7956\u6BCD", "\u66FE\u7956\u7236\u6BCD");
7103
+ }
7104
+ if (L === 4) {
7105
+ return pick(sex, "\u9AD8\u7956\u7236", "\u9AD8\u7956\u6BCD", "\u9AD8\u7956\u7236\u6BCD");
7106
+ }
7107
+ return pick(
7108
+ sex,
7109
+ `${L - 1}\u4E16\u306E\u7956\u7236`,
7110
+ `${L - 1}\u4E16\u306E\u7956\u6BCD`,
7111
+ `${L - 1}\u4E16\u306E\u7956\u7236\u6BCD`
7112
+ );
7113
+ }
7114
+ if (L <= 1) {
7115
+ return pick(sex, "\u606F\u5B50", "\u5A18", "\u5B50");
7116
+ }
7117
+ if (L === 2) {
7118
+ return "\u5B6B";
7119
+ }
7120
+ if (L === 3) {
7121
+ return "\u66FE\u5B6B";
7122
+ }
7123
+ if (L === 4) {
7124
+ return "\u7384\u5B6B";
7125
+ }
7126
+ return `${L - 1}\u4E16\u306E\u5B6B`;
7127
+ };
7128
+ var cousinPlain = (degree) => {
7129
+ if (degree <= 1) {
7130
+ return "\u3044\u3068\u3053";
7131
+ }
7132
+ if (degree === 2) {
7133
+ return "\u307E\u305F\u3044\u3068\u3053";
7134
+ }
7135
+ if (degree === 3) {
7136
+ return "\u306F\u3068\u3053";
7137
+ }
7138
+ return `${degree}\u89AA\u7B49\u306E\u3044\u3068\u3053`;
7139
+ };
7140
+ var KinshipTranslatorJa = class extends KinshipTranslatorBasic {
7141
+ indirect() {
7142
+ let degree = Math.abs(this.pathN?.degree ?? 0);
7143
+ if (degree > 0) {
7144
+ degree = degree - 1;
7145
+ }
7146
+ return cousinPlain(degree);
7147
+ }
7148
+ removal() {
7149
+ const level = this.pathN?.level ?? 0;
7150
+ let degree = Math.abs(this.pathN?.degree ?? 0);
7151
+ if (degree > 0) {
7152
+ degree = degree - 1;
7153
+ }
7154
+ if (!degree) {
7155
+ return level < 0 ? this.nibling() : this.auncle();
7156
+ }
7157
+ const removed = Math.abs(level);
7158
+ return `${cousinPlain(degree)}\uFF08${removed}\u4E16\u4EE3\u9055\u3044\uFF09`;
7159
+ }
7160
+ auncle() {
7161
+ const level = Math.abs(this.pathN?.level ?? 0);
7162
+ const sex = sexOf2(this.personN);
7163
+ if (level <= 2) {
7164
+ return pick(sex, "\u304A\u3058", "\u304A\u3070", "\u304A\u3058/\u304A\u3070");
7165
+ }
7166
+ if (level === 3) {
7167
+ return pick(sex, "\u5927\u304A\u3058", "\u5927\u304A\u3070", "\u5927\u304A\u3058/\u5927\u304A\u3070");
7168
+ }
7169
+ return pick(
7170
+ sex,
7171
+ `${level - 2}\u4EE3\u524D\u306E\u304A\u3058`,
7172
+ `${level - 2}\u4EE3\u524D\u306E\u304A\u3070`,
7173
+ `${level - 2}\u4EE3\u524D\u306E\u304A\u3058/\u304A\u3070`
7174
+ );
7175
+ }
7176
+ nibling() {
7177
+ const level = Math.abs(this.pathN?.level ?? 0);
7178
+ const sex = sexOf2(this.personN);
7179
+ if (level <= 2) {
7180
+ return pick(sex, "\u7525", "\u59EA", "\u7525/\u59EA");
7181
+ }
7182
+ if (level === 3) {
7183
+ return pick(sex, "\u5927\u7525", "\u5927\u59EA", "\u5927\u7525/\u5927\u59EA");
7184
+ }
7185
+ return pick(
7186
+ sex,
7187
+ `${level - 2}\u4EE3\u4E0B\u306E\u7525`,
7188
+ `${level - 2}\u4EE3\u4E0B\u306E\u59EA`,
7189
+ `${level - 2}\u4EE3\u4E0B\u306E\u7525/\u59EA`
7190
+ );
7191
+ }
7192
+ parent() {
7193
+ return lineal(
7194
+ Math.abs(this.pathN?.level ?? 0),
7195
+ sexOf2(this.personN),
7196
+ "asc"
7197
+ );
7198
+ }
7199
+ child() {
7200
+ return lineal(
7201
+ Math.abs(this.pathN?.level ?? 0),
7202
+ sexOf2(this.personN),
7203
+ "desc"
7204
+ );
7205
+ }
7206
+ sibling() {
7207
+ return pick(sexOf2(this.personN), "\u5144\u5F1F", "\u59C9\u59B9", "\u5144\u5F1F\u59C9\u59B9");
7208
+ }
7209
+ halfBlood(relation) {
7210
+ if (!relation || !this.isHalfBlood) {
7211
+ return relation ?? "";
7212
+ }
7213
+ return `\u7570\u7236\u6BCD\u306E${relation}`;
7214
+ }
7215
+ spouse() {
7216
+ return pick(sexOf2(this.personN), "\u592B", "\u59BB", "\u914D\u5076\u8005");
7217
+ }
7218
+ ofSpouse(relation) {
7219
+ if (!relation) {
7220
+ return "";
7221
+ }
7222
+ const spouseType = pick(
7223
+ sexOf2(this.path?.[1].indi),
7224
+ "\u592B",
7225
+ "\u59BB",
7226
+ "\u914D\u5076\u8005"
7227
+ );
7228
+ return `${spouseType}\u306E${relation}`;
7229
+ }
7230
+ spouseOf(relation) {
7231
+ if (!relation) {
7232
+ return "";
7233
+ }
7234
+ const spouse = this.path?.[this.path.length - 1].indi;
7235
+ const spouseType = pick(sexOf2(spouse), "\u592B", "\u59BB", "\u914D\u5076\u8005");
7236
+ return `${relation}\u306E${spouseType}`;
7237
+ }
7238
+ of(relation) {
7239
+ const formattedName = nameFormatter(this.path?.[0]?.indi, {
7240
+ nameOrder: "last-first"
7241
+ });
7242
+ let name = formattedName.inOrder.filter(Boolean).join(" ");
7243
+ if (this.displayName === "none") {
7244
+ name = "";
7245
+ } else if (this.displayName === "givenname") {
7246
+ name = formattedName.givenname;
7247
+ } else if (this.displayName === "surname") {
7248
+ name = `${formattedName.surname}`;
7249
+ }
7250
+ if (!name || !relation) {
7251
+ return relation ?? "";
7252
+ }
7253
+ return `${name}\u306E${relation}`;
7254
+ }
7255
+ inLaw(relation) {
7256
+ let inLawRelation = relation;
7257
+ Object.keys(InLawsJa).find((pattern) => {
7258
+ const regex = new RegExp(`^${pattern}$`);
7259
+ if (relation?.match(regex)) {
7260
+ inLawRelation = InLawsJa[pattern];
7261
+ return true;
7262
+ }
7263
+ return false;
7264
+ });
7265
+ return inLawRelation ?? "";
7266
+ }
7267
+ relationType(relation) {
7268
+ if (!relation || !this.pathN?.relation) {
7269
+ return relation ?? "";
7270
+ }
7271
+ return `${this.pathN.relation}\u306E${relation}`;
7272
+ }
7273
+ };
7274
+
7275
+ // src/kinship-translator/patterns.zh.ts
7276
+ var InLawsZh = {
7277
+ "(\u5B50\u5973|\u5973\u513F|\u513F\u5B50)\u7684\u914D\u5076": "\u513F\u5AB3/\u5973\u5A7F",
7278
+ "(\u5B50\u5973|\u5973\u513F|\u513F\u5B50)\u7684\u59BB\u5B50": "\u513F\u5AB3",
7279
+ "(\u5B50\u5973|\u5973\u513F|\u513F\u5B50)\u7684\u4E08\u592B": "\u5973\u5A7F",
7280
+ "(\u914D\u5076|\u59BB\u5B50|\u4E08\u592B)\u7684\u6BCD\u4EB2": "\u5CB3\u6BCD/\u5A46\u5A46",
7281
+ "(\u914D\u5076|\u59BB\u5B50|\u4E08\u592B)\u7684\u7236\u4EB2": "\u5CB3\u7236/\u516C\u516C",
7282
+ "(\u914D\u5076|\u59BB\u5B50|\u4E08\u592B)\u7684\u7236\u6BCD": "\u5CB3\u7236\u5CB3\u6BCD/\u516C\u516C\u5A46\u5A46",
7283
+ "(\u5F02\u7236\u6BCD\u7684)?(\u5144\u5F1F\u59D0\u59B9|\u59D0\u59B9|\u5144\u5F1F)\u7684\u59BB\u5B50": "\u5AC2\u5B50/\u5F1F\u59B9",
7284
+ "(\u5F02\u7236\u6BCD\u7684)?(\u5144\u5F1F\u59D0\u59B9|\u59D0\u59B9|\u5144\u5F1F)\u7684\u4E08\u592B": "\u59D0\u592B/\u59B9\u592B",
7285
+ "(\u5F02\u7236\u6BCD\u7684)?(\u5144\u5F1F\u59D0\u59B9|\u59D0\u59B9|\u5144\u5F1F)\u7684\u914D\u5076": "\u59FB\u4EB2\u5144\u5F1F\u59D0\u59B9",
7286
+ "(\u5F02\u7236\u6BCD\u7684)?\u59D0\u59B9\u7684(\u914D\u5076|\u59BB\u5B50|\u4E08\u592B)": "\u59D0\u592B/\u59B9\u592B",
7287
+ "(\u5F02\u7236\u6BCD\u7684)?\u5144\u5F1F\u7684(\u914D\u5076|\u59BB\u5B50|\u4E08\u592B)": "\u5AC2\u5B50/\u5F1F\u59B9",
7288
+ "(\u5F02\u7236\u6BCD\u7684)?\u5144\u5F1F\u59D0\u59B9\u7684(\u914D\u5076|\u59BB\u5B50|\u4E08\u592B)": "\u59FB\u4EB2\u5144\u5F1F\u59D0\u59B9",
7289
+ "(\u5F02\u7236\u6BCD\u7684)?(\u914D\u5076|\u59BB\u5B50|\u4E08\u592B)\u7684\u59D0\u59B9": "\u59D1\u5B50/\u59E8\u5B50",
7290
+ "(\u5F02\u7236\u6BCD\u7684)?(\u914D\u5076|\u59BB\u5B50|\u4E08\u592B)\u7684\u5144\u5F1F": "\u5927\u4F2F/\u5C0F\u53D4/\u5185\u5144/\u5185\u5F1F",
7291
+ "(\u5F02\u7236\u6BCD\u7684)?(\u914D\u5076|\u59BB\u5B50|\u4E08\u592B)\u7684\u5144\u5F1F\u59D0\u59B9": "\u59FB\u4EB2\u5144\u5F1F\u59D0\u59B9"
7292
+ };
7293
+
7294
+ // src/kinship-translator/kinship-translator.zh.ts
7295
+ var sexOf3 = (person) => {
7296
+ if (person?.isMale?.()) {
7297
+ return "m";
7298
+ }
7299
+ if (person?.isFemale?.()) {
7300
+ return "f";
7301
+ }
7302
+ return "n";
7303
+ };
7304
+ var pick2 = (sex, male, female, neutral) => {
7305
+ if (sex === "m") {
7306
+ return male;
7307
+ }
7308
+ if (sex === "f") {
7309
+ return female;
7310
+ }
7311
+ return neutral;
7312
+ };
7313
+ var lineal2 = (level, sex, kind) => {
7314
+ const L = Math.max(1, level);
7315
+ if (kind === "asc") {
7316
+ if (L <= 1) {
7317
+ return pick2(sex, "\u7236\u4EB2", "\u6BCD\u4EB2", "\u7236\u6BCD");
7318
+ }
7319
+ if (L === 2) {
7320
+ return pick2(sex, "\u7956\u7236", "\u7956\u6BCD", "\u7956\u7236\u6BCD");
7321
+ }
7322
+ if (L === 3) {
7323
+ return pick2(sex, "\u66FE\u7956\u7236", "\u66FE\u7956\u6BCD", "\u66FE\u7956\u7236\u6BCD");
7324
+ }
7325
+ if (L === 4) {
7326
+ return pick2(sex, "\u9AD8\u7956\u7236", "\u9AD8\u7956\u6BCD", "\u9AD8\u7956\u7236\u6BCD");
7327
+ }
7328
+ return pick2(sex, `${L}\u4E16\u7956`, `${L}\u4E16\u7956\u6BCD`, `${L}\u4E16\u7956\u7236\u6BCD`);
7329
+ }
7330
+ if (L <= 1) {
7331
+ return pick2(sex, "\u513F\u5B50", "\u5973\u513F", "\u5B50\u5973");
7332
+ }
7333
+ if (L === 2) {
7334
+ return pick2(sex, "\u5B59\u5B50", "\u5B59\u5973", "\u5B59\u5B50\u5973");
7335
+ }
7336
+ if (L === 3) {
7337
+ return pick2(sex, "\u66FE\u5B59", "\u66FE\u5B59\u5973", "\u66FE\u5B59\u5B50\u5973");
7338
+ }
7339
+ if (L === 4) {
7340
+ return pick2(sex, "\u7384\u5B59", "\u7384\u5B59\u5973", "\u7384\u5B59\u5B50\u5973");
7341
+ }
7342
+ return pick2(sex, `${L}\u4E16\u5B59`, `${L}\u4E16\u5B59\u5973`, `${L}\u4E16\u5B59\u5B50\u5973`);
7343
+ };
7344
+ var cousinPlain2 = (degree, sex) => {
7345
+ if (degree <= 1) {
7346
+ return pick2(sex, "\u5802\u8868\u5144\u5F1F", "\u5802\u8868\u59D0\u59B9", "\u5802\u8868\u4EB2");
7347
+ }
7348
+ if (degree === 2) {
7349
+ return pick2(sex, "\u4ECE\u5802\u8868\u5144\u5F1F", "\u4ECE\u5802\u8868\u59D0\u59B9", "\u4ECE\u5802\u8868\u4EB2");
7350
+ }
7351
+ return pick2(
7352
+ sex,
7353
+ `${degree}\u4EE3\u5802\u8868\u5144\u5F1F`,
7354
+ `${degree}\u4EE3\u5802\u8868\u59D0\u59B9`,
7355
+ `${degree}\u4EE3\u5802\u8868\u4EB2`
7356
+ );
7357
+ };
7358
+ var KinshipTranslatorZh = class extends KinshipTranslatorBasic {
7359
+ indirect() {
7360
+ let degree = Math.abs(this.pathN?.degree ?? 0);
7361
+ if (degree > 0) {
7362
+ degree = degree - 1;
7363
+ }
7364
+ return cousinPlain2(degree, sexOf3(this.personN));
7365
+ }
7366
+ removal() {
7367
+ const level = this.pathN?.level ?? 0;
7368
+ let degree = Math.abs(this.pathN?.degree ?? 0);
7369
+ if (degree > 0) {
7370
+ degree = degree - 1;
7371
+ }
7372
+ if (!degree) {
7373
+ return level < 0 ? this.nibling() : this.auncle();
7374
+ }
7375
+ const removed = Math.abs(level);
7376
+ return `${cousinPlain2(degree, sexOf3(this.personN))}\uFF08\u9694${removed}\u4EE3\uFF09`;
7377
+ }
7378
+ auncle() {
7379
+ const level = Math.abs(this.pathN?.level ?? 0);
7380
+ const sex = sexOf3(this.personN);
7381
+ if (level <= 2) {
7382
+ return pick2(sex, "\u53D4\u53D4", "\u963F\u59E8", "\u53D4\u4F2F/\u59D1\u59E8");
7383
+ }
7384
+ if (level === 3) {
7385
+ return pick2(sex, "\u4F2F\u53D4\u7956\u7236", "\u59D1\u7956\u6BCD", "\u4F2F\u53D4\u7956\u7236\u6BCD");
7386
+ }
7387
+ return pick2(
7388
+ sex,
7389
+ `${level - 2}\u4EE3\u524D\u7684\u53D4\u53D4`,
7390
+ `${level - 2}\u4EE3\u524D\u7684\u963F\u59E8`,
7391
+ `${level - 2}\u4EE3\u524D\u7684\u53D4\u4F2F/\u59D1\u59E8`
7392
+ );
7393
+ }
7394
+ nibling() {
7395
+ const level = Math.abs(this.pathN?.level ?? 0);
7396
+ const sex = sexOf3(this.personN);
7397
+ if (level <= 2) {
7398
+ return pick2(sex, "\u4F84\u5B50", "\u4F84\u5973", "\u4F84\u5B50\u5973");
7399
+ }
7400
+ if (level === 3) {
7401
+ return pick2(sex, "\u4F84\u5B59", "\u4F84\u5B59\u5973", "\u4F84\u5B59\u5B50\u5973");
7402
+ }
7403
+ return pick2(
7404
+ sex,
7405
+ `${level - 2}\u4EE3\u4E0B\u7684\u4F84\u5B50`,
7406
+ `${level - 2}\u4EE3\u4E0B\u7684\u4F84\u5973`,
7407
+ `${level - 2}\u4EE3\u4E0B\u7684\u4F84\u5B50\u5973`
7408
+ );
7409
+ }
7410
+ parent() {
7411
+ return lineal2(
7412
+ Math.abs(this.pathN?.level ?? 0),
7413
+ sexOf3(this.personN),
7414
+ "asc"
7415
+ );
7416
+ }
7417
+ child() {
7418
+ return lineal2(
7419
+ Math.abs(this.pathN?.level ?? 0),
7420
+ sexOf3(this.personN),
7421
+ "desc"
7422
+ );
7423
+ }
7424
+ sibling() {
7425
+ return pick2(sexOf3(this.personN), "\u5144\u5F1F", "\u59D0\u59B9", "\u5144\u5F1F\u59D0\u59B9");
7426
+ }
7427
+ halfBlood(relation) {
7428
+ if (!relation || !this.isHalfBlood) {
7429
+ return relation ?? "";
7430
+ }
7431
+ return `\u5F02\u7236\u6BCD\u7684${relation}`;
7432
+ }
7433
+ spouse() {
7434
+ return pick2(sexOf3(this.personN), "\u4E08\u592B", "\u59BB\u5B50", "\u914D\u5076");
7435
+ }
7436
+ ofSpouse(relation) {
7437
+ if (!relation) {
7438
+ return "";
7439
+ }
7440
+ const spouseType = pick2(
7441
+ sexOf3(this.path?.[1].indi),
7442
+ "\u4E08\u592B",
7443
+ "\u59BB\u5B50",
7444
+ "\u914D\u5076"
7445
+ );
7446
+ return `${spouseType}\u7684${relation}`;
7447
+ }
7448
+ spouseOf(relation) {
7449
+ if (!relation) {
7450
+ return "";
7451
+ }
7452
+ const spouse = this.path?.[this.path.length - 1].indi;
7453
+ const spouseType = pick2(sexOf3(spouse), "\u4E08\u592B", "\u59BB\u5B50", "\u914D\u5076");
7454
+ return `${relation}\u7684${spouseType}`;
7455
+ }
7456
+ of(relation) {
7457
+ const formattedName = nameFormatter(this.path?.[0]?.indi, {
7458
+ nameOrder: "last-first"
7459
+ });
7460
+ let name = formattedName.inOrder.filter(Boolean).join(" ");
7461
+ if (this.displayName === "none") {
7462
+ name = "";
7463
+ } else if (this.displayName === "givenname") {
7464
+ name = formattedName.givenname;
7465
+ } else if (this.displayName === "surname") {
7466
+ name = `${formattedName.surname}`;
7467
+ }
7468
+ if (!name || !relation) {
7469
+ return relation ?? "";
7470
+ }
7471
+ return `${name}\u7684${relation}`;
7472
+ }
7473
+ inLaw(relation) {
7474
+ let inLawRelation = relation;
7475
+ Object.keys(InLawsZh).find((pattern) => {
7476
+ const regex = new RegExp(`^${pattern}$`);
7477
+ if (relation?.match(regex)) {
7478
+ inLawRelation = InLawsZh[pattern];
7479
+ return true;
7480
+ }
7481
+ return false;
7482
+ });
7483
+ return inLawRelation ?? "";
7484
+ }
7485
+ relationType(relation) {
7486
+ if (!relation || !this.pathN?.relation) {
7487
+ return relation ?? "";
7488
+ }
7489
+ return `${this.pathN.relation}${relation}`;
7490
+ }
7491
+ };
7492
+
7006
7493
  // src/kinship-translator/kinship-translator.ts
7007
7494
  var KinshipTranslator = class {
7008
7495
  constructor(person1, person2, lang = "en", entirePath, displayName = "givenname") {