@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
@@ -79,7 +79,9 @@ __export(translators_exports, {
79
79
  es: () => KinshipTranslatorEs,
80
80
  fr: () => KinshipTranslatorFr,
81
81
  hu: () => KinshipTranslatorHU,
82
- ru: () => KinshipTranslatorRu
82
+ ja: () => KinshipTranslatorJa,
83
+ ru: () => KinshipTranslatorRu,
84
+ zh: () => KinshipTranslatorZh
83
85
  });
84
86
 
85
87
  // src/constants/constants.ts
@@ -105,6 +107,82 @@ var appendGedcomTrailer = (serialized) => {
105
107
  }
106
108
  return `${trimmed}${newline}0 TRLR`;
107
109
  };
110
+
111
+ // src/utils/media-utils.ts
112
+ var getFileExtension = (filename) => {
113
+ if (!filename) {
114
+ return "";
115
+ }
116
+ if (filename.startsWith("data:")) {
117
+ const mime = filename.slice(5).split(";")[0] || "";
118
+ const subtype = (mime.split("/")[1] || "").toLowerCase();
119
+ if (subtype === "jpeg") {
120
+ return "jpg";
121
+ }
122
+ return subtype.split("+")[0] || "";
123
+ }
124
+ const withoutQuery = filename.split(/[?#]/)[0] || filename;
125
+ const match = withoutQuery.match(/\.([^.]+)$/);
126
+ return match ? match[1].toLowerCase() : "";
127
+ };
128
+ var isImageFormat = (format2) => {
129
+ if (!format2) {
130
+ return false;
131
+ }
132
+ let normalized = format2.toLowerCase().trim();
133
+ if (normalized.startsWith("data:")) {
134
+ normalized = getFileExtension(normalized);
135
+ } else if (normalized.includes("/")) {
136
+ normalized = normalized.split("/")[1]?.split("+")[0] || "";
137
+ if (normalized === "jpeg") {
138
+ normalized = "jpg";
139
+ }
140
+ }
141
+ const imageFormats = [
142
+ "jpg",
143
+ "jpeg",
144
+ "png",
145
+ "gif",
146
+ "bmp",
147
+ "webp",
148
+ "svg",
149
+ "tiff",
150
+ "tif"
151
+ ];
152
+ return imageFormats.includes(normalized);
153
+ };
154
+ var resolveObjeForm = (obje) => {
155
+ const value = obje?.get?.("FILE.FORM")?.toValue?.() ?? obje?.get?.("FORM")?.toValue?.();
156
+ return typeof value === "string" && value.trim() ? value.trim() : void 0;
157
+ };
158
+ var mediaIdValue = (obje, path) => {
159
+ const value = obje?.get?.(path)?.toValue?.();
160
+ return typeof value === "string" && value.trim() ? value.trim() : void 0;
161
+ };
162
+ var resolveObjeMediaId = (obje) => mediaIdValue(obje, "RIN") || mediaIdValue(obje, "_CLON._OID") || mediaIdValue(obje, "_MSER._LKID") || mediaIdValue(obje, "_OID") || mediaIdValue(obje, "_LKID");
163
+ var ANCESTRY_MEDIA_RETRIEVAL_PREFIX = "https://www.ancestry.com/api/media/retrieval/v2/image";
164
+ var ANCESTRY_MEDIA_QUERY = "client=trees-mediaservice&imageQuality=hq";
165
+ var ancestryMediaPath = (namespace, imgId) => `/namespaces/${namespace}/media/${imgId}?${ANCESTRY_MEDIA_QUERY}`;
166
+ var ancestryMediaFileUrl = (namespace, imgId) => {
167
+ if (!namespace || !imgId) {
168
+ return void 0;
169
+ }
170
+ return `${ANCESTRY_MEDIA_RETRIEVAL_PREFIX}${ancestryMediaPath(namespace, imgId)}`;
171
+ };
172
+ var objeXrefKey = (obje, fallback = 0) => {
173
+ if (typeof obje?.id === "string" && obje.id) {
174
+ return obje.id;
175
+ }
176
+ const value = obje?.toValue?.();
177
+ if (typeof value === "string" && value.trim()) {
178
+ return value.trim();
179
+ }
180
+ if (typeof fallback === "string" && fallback.trim()) {
181
+ return fallback.trim();
182
+ }
183
+ return `@O${fallback}@`;
184
+ };
185
+ var objeNoteValue = (obje) => mediaIdValue(obje, "FILE.NOTE") || mediaIdValue(obje, "NOTE") || "";
108
186
  var List = class _List {
109
187
  // length = 0;
110
188
  constructor(items) {
@@ -754,7 +832,7 @@ var Common = class _Common {
754
832
  this,
755
833
  options.obje.namespace,
756
834
  options.obje.override,
757
- void 0,
835
+ this.isAncestry() ? ancestryMediaFileUrl : void 0,
758
836
  options.gedcomVersion
759
837
  );
760
838
  }
@@ -2876,6 +2954,445 @@ var KinshipTranslatorRu = class extends KinshipTranslatorBasic {
2876
2954
  }
2877
2955
  };
2878
2956
 
2957
+ // src/kinship-translator/patterns.ja.ts
2958
+ var InLawsJa = {
2959
+ "(\u5B50|\u5A18|\u606F\u5B50)\u306E\u914D\u5076\u8005": "\u7FA9\u7406\u306E\u5B50",
2960
+ "(\u5B50|\u5A18|\u606F\u5B50)\u306E\u59BB": "\u5AC1",
2961
+ "(\u5B50|\u5A18|\u606F\u5B50)\u306E\u592B": "\u5A7F",
2962
+ "(\u914D\u5076\u8005|\u59BB|\u592B)\u306E\u6BCD": "\u7FA9\u6BCD",
2963
+ "(\u914D\u5076\u8005|\u59BB|\u592B)\u306E\u7236": "\u7FA9\u7236",
2964
+ "(\u914D\u5076\u8005|\u59BB|\u592B)\u306E\u89AA": "\u7FA9\u7406\u306E\u89AA",
2965
+ "(\u7570\u7236\u6BCD\u306E)?(\u5144\u5F1F|\u59C9\u59B9|\u5144\u5F1F\u59C9\u59B9)\u306E\u59BB": "\u7FA9\u7406\u306E\u59C9\u59B9",
2966
+ "(\u7570\u7236\u6BCD\u306E)?(\u5144\u5F1F|\u59C9\u59B9|\u5144\u5F1F\u59C9\u59B9)\u306E\u592B": "\u7FA9\u7406\u306E\u5144\u5F1F",
2967
+ "(\u7570\u7236\u6BCD\u306E)?(\u5144\u5F1F|\u59C9\u59B9|\u5144\u5F1F\u59C9\u59B9)\u306E\u914D\u5076\u8005": "\u7FA9\u7406\u306E\u5144\u5F1F\u59C9\u59B9",
2968
+ "(\u7570\u7236\u6BCD\u306E)?\u59C9\u59B9\u306E(\u914D\u5076\u8005|\u59BB|\u592B)": "\u7FA9\u7406\u306E\u59C9\u59B9",
2969
+ "(\u7570\u7236\u6BCD\u306E)?\u5144\u5F1F\u306E(\u914D\u5076\u8005|\u59BB|\u592B)": "\u7FA9\u7406\u306E\u5144\u5F1F",
2970
+ "(\u7570\u7236\u6BCD\u306E)?\u5144\u5F1F\u59C9\u59B9\u306E(\u914D\u5076\u8005|\u59BB|\u592B)": "\u7FA9\u7406\u306E\u5144\u5F1F\u59C9\u59B9",
2971
+ "(\u7570\u7236\u6BCD\u306E)?(\u914D\u5076\u8005|\u59BB|\u592B)\u306E\u59C9\u59B9": "\u7FA9\u7406\u306E\u59C9\u59B9",
2972
+ "(\u7570\u7236\u6BCD\u306E)?(\u914D\u5076\u8005|\u59BB|\u592B)\u306E\u5144\u5F1F": "\u7FA9\u7406\u306E\u5144\u5F1F",
2973
+ "(\u7570\u7236\u6BCD\u306E)?(\u914D\u5076\u8005|\u59BB|\u592B)\u306E\u5144\u5F1F\u59C9\u59B9": "\u7FA9\u7406\u306E\u5144\u5F1F\u59C9\u59B9"
2974
+ };
2975
+
2976
+ // src/kinship-translator/kinship-translator.ja.ts
2977
+ var sexOf2 = (person) => {
2978
+ if (person?.isMale?.()) {
2979
+ return "m";
2980
+ }
2981
+ if (person?.isFemale?.()) {
2982
+ return "f";
2983
+ }
2984
+ return "n";
2985
+ };
2986
+ var pick = (sex, male, female, neutral) => {
2987
+ if (sex === "m") {
2988
+ return male;
2989
+ }
2990
+ if (sex === "f") {
2991
+ return female;
2992
+ }
2993
+ return neutral;
2994
+ };
2995
+ var lineal = (level, sex, kind) => {
2996
+ const L = Math.max(1, level);
2997
+ if (kind === "asc") {
2998
+ if (L <= 1) {
2999
+ return pick(sex, "\u7236", "\u6BCD", "\u89AA");
3000
+ }
3001
+ if (L === 2) {
3002
+ return pick(sex, "\u7956\u7236", "\u7956\u6BCD", "\u7956\u7236\u6BCD");
3003
+ }
3004
+ if (L === 3) {
3005
+ return pick(sex, "\u66FE\u7956\u7236", "\u66FE\u7956\u6BCD", "\u66FE\u7956\u7236\u6BCD");
3006
+ }
3007
+ if (L === 4) {
3008
+ return pick(sex, "\u9AD8\u7956\u7236", "\u9AD8\u7956\u6BCD", "\u9AD8\u7956\u7236\u6BCD");
3009
+ }
3010
+ return pick(
3011
+ sex,
3012
+ `${L - 1}\u4E16\u306E\u7956\u7236`,
3013
+ `${L - 1}\u4E16\u306E\u7956\u6BCD`,
3014
+ `${L - 1}\u4E16\u306E\u7956\u7236\u6BCD`
3015
+ );
3016
+ }
3017
+ if (L <= 1) {
3018
+ return pick(sex, "\u606F\u5B50", "\u5A18", "\u5B50");
3019
+ }
3020
+ if (L === 2) {
3021
+ return "\u5B6B";
3022
+ }
3023
+ if (L === 3) {
3024
+ return "\u66FE\u5B6B";
3025
+ }
3026
+ if (L === 4) {
3027
+ return "\u7384\u5B6B";
3028
+ }
3029
+ return `${L - 1}\u4E16\u306E\u5B6B`;
3030
+ };
3031
+ var cousinPlain = (degree) => {
3032
+ if (degree <= 1) {
3033
+ return "\u3044\u3068\u3053";
3034
+ }
3035
+ if (degree === 2) {
3036
+ return "\u307E\u305F\u3044\u3068\u3053";
3037
+ }
3038
+ if (degree === 3) {
3039
+ return "\u306F\u3068\u3053";
3040
+ }
3041
+ return `${degree}\u89AA\u7B49\u306E\u3044\u3068\u3053`;
3042
+ };
3043
+ var KinshipTranslatorJa = class extends KinshipTranslatorBasic {
3044
+ indirect() {
3045
+ let degree = Math.abs(this.pathN?.degree ?? 0);
3046
+ if (degree > 0) {
3047
+ degree = degree - 1;
3048
+ }
3049
+ return cousinPlain(degree);
3050
+ }
3051
+ removal() {
3052
+ const level = this.pathN?.level ?? 0;
3053
+ let degree = Math.abs(this.pathN?.degree ?? 0);
3054
+ if (degree > 0) {
3055
+ degree = degree - 1;
3056
+ }
3057
+ if (!degree) {
3058
+ return level < 0 ? this.nibling() : this.auncle();
3059
+ }
3060
+ const removed = Math.abs(level);
3061
+ return `${cousinPlain(degree)}\uFF08${removed}\u4E16\u4EE3\u9055\u3044\uFF09`;
3062
+ }
3063
+ auncle() {
3064
+ const level = Math.abs(this.pathN?.level ?? 0);
3065
+ const sex = sexOf2(this.personN);
3066
+ if (level <= 2) {
3067
+ return pick(sex, "\u304A\u3058", "\u304A\u3070", "\u304A\u3058/\u304A\u3070");
3068
+ }
3069
+ if (level === 3) {
3070
+ return pick(sex, "\u5927\u304A\u3058", "\u5927\u304A\u3070", "\u5927\u304A\u3058/\u5927\u304A\u3070");
3071
+ }
3072
+ return pick(
3073
+ sex,
3074
+ `${level - 2}\u4EE3\u524D\u306E\u304A\u3058`,
3075
+ `${level - 2}\u4EE3\u524D\u306E\u304A\u3070`,
3076
+ `${level - 2}\u4EE3\u524D\u306E\u304A\u3058/\u304A\u3070`
3077
+ );
3078
+ }
3079
+ nibling() {
3080
+ const level = Math.abs(this.pathN?.level ?? 0);
3081
+ const sex = sexOf2(this.personN);
3082
+ if (level <= 2) {
3083
+ return pick(sex, "\u7525", "\u59EA", "\u7525/\u59EA");
3084
+ }
3085
+ if (level === 3) {
3086
+ return pick(sex, "\u5927\u7525", "\u5927\u59EA", "\u5927\u7525/\u5927\u59EA");
3087
+ }
3088
+ return pick(
3089
+ sex,
3090
+ `${level - 2}\u4EE3\u4E0B\u306E\u7525`,
3091
+ `${level - 2}\u4EE3\u4E0B\u306E\u59EA`,
3092
+ `${level - 2}\u4EE3\u4E0B\u306E\u7525/\u59EA`
3093
+ );
3094
+ }
3095
+ parent() {
3096
+ return lineal(
3097
+ Math.abs(this.pathN?.level ?? 0),
3098
+ sexOf2(this.personN),
3099
+ "asc"
3100
+ );
3101
+ }
3102
+ child() {
3103
+ return lineal(
3104
+ Math.abs(this.pathN?.level ?? 0),
3105
+ sexOf2(this.personN),
3106
+ "desc"
3107
+ );
3108
+ }
3109
+ sibling() {
3110
+ return pick(sexOf2(this.personN), "\u5144\u5F1F", "\u59C9\u59B9", "\u5144\u5F1F\u59C9\u59B9");
3111
+ }
3112
+ halfBlood(relation) {
3113
+ if (!relation || !this.isHalfBlood) {
3114
+ return relation ?? "";
3115
+ }
3116
+ return `\u7570\u7236\u6BCD\u306E${relation}`;
3117
+ }
3118
+ spouse() {
3119
+ return pick(sexOf2(this.personN), "\u592B", "\u59BB", "\u914D\u5076\u8005");
3120
+ }
3121
+ ofSpouse(relation) {
3122
+ if (!relation) {
3123
+ return "";
3124
+ }
3125
+ const spouseType = pick(
3126
+ sexOf2(this.path?.[1].indi),
3127
+ "\u592B",
3128
+ "\u59BB",
3129
+ "\u914D\u5076\u8005"
3130
+ );
3131
+ return `${spouseType}\u306E${relation}`;
3132
+ }
3133
+ spouseOf(relation) {
3134
+ if (!relation) {
3135
+ return "";
3136
+ }
3137
+ const spouse = this.path?.[this.path.length - 1].indi;
3138
+ const spouseType = pick(sexOf2(spouse), "\u592B", "\u59BB", "\u914D\u5076\u8005");
3139
+ return `${relation}\u306E${spouseType}`;
3140
+ }
3141
+ of(relation) {
3142
+ const formattedName = nameFormatter(this.path?.[0]?.indi, {
3143
+ nameOrder: "last-first"
3144
+ });
3145
+ let name = formattedName.inOrder.filter(Boolean).join(" ");
3146
+ if (this.displayName === "none") {
3147
+ name = "";
3148
+ } else if (this.displayName === "givenname") {
3149
+ name = formattedName.givenname;
3150
+ } else if (this.displayName === "surname") {
3151
+ name = `${formattedName.surname}`;
3152
+ }
3153
+ if (!name || !relation) {
3154
+ return relation ?? "";
3155
+ }
3156
+ return `${name}\u306E${relation}`;
3157
+ }
3158
+ inLaw(relation) {
3159
+ let inLawRelation = relation;
3160
+ Object.keys(InLawsJa).find((pattern) => {
3161
+ const regex = new RegExp(`^${pattern}$`);
3162
+ if (relation?.match(regex)) {
3163
+ inLawRelation = InLawsJa[pattern];
3164
+ return true;
3165
+ }
3166
+ return false;
3167
+ });
3168
+ return inLawRelation ?? "";
3169
+ }
3170
+ relationType(relation) {
3171
+ if (!relation || !this.pathN?.relation) {
3172
+ return relation ?? "";
3173
+ }
3174
+ return `${this.pathN.relation}\u306E${relation}`;
3175
+ }
3176
+ };
3177
+
3178
+ // src/kinship-translator/patterns.zh.ts
3179
+ var InLawsZh = {
3180
+ "(\u5B50\u5973|\u5973\u513F|\u513F\u5B50)\u7684\u914D\u5076": "\u513F\u5AB3/\u5973\u5A7F",
3181
+ "(\u5B50\u5973|\u5973\u513F|\u513F\u5B50)\u7684\u59BB\u5B50": "\u513F\u5AB3",
3182
+ "(\u5B50\u5973|\u5973\u513F|\u513F\u5B50)\u7684\u4E08\u592B": "\u5973\u5A7F",
3183
+ "(\u914D\u5076|\u59BB\u5B50|\u4E08\u592B)\u7684\u6BCD\u4EB2": "\u5CB3\u6BCD/\u5A46\u5A46",
3184
+ "(\u914D\u5076|\u59BB\u5B50|\u4E08\u592B)\u7684\u7236\u4EB2": "\u5CB3\u7236/\u516C\u516C",
3185
+ "(\u914D\u5076|\u59BB\u5B50|\u4E08\u592B)\u7684\u7236\u6BCD": "\u5CB3\u7236\u5CB3\u6BCD/\u516C\u516C\u5A46\u5A46",
3186
+ "(\u5F02\u7236\u6BCD\u7684)?(\u5144\u5F1F\u59D0\u59B9|\u59D0\u59B9|\u5144\u5F1F)\u7684\u59BB\u5B50": "\u5AC2\u5B50/\u5F1F\u59B9",
3187
+ "(\u5F02\u7236\u6BCD\u7684)?(\u5144\u5F1F\u59D0\u59B9|\u59D0\u59B9|\u5144\u5F1F)\u7684\u4E08\u592B": "\u59D0\u592B/\u59B9\u592B",
3188
+ "(\u5F02\u7236\u6BCD\u7684)?(\u5144\u5F1F\u59D0\u59B9|\u59D0\u59B9|\u5144\u5F1F)\u7684\u914D\u5076": "\u59FB\u4EB2\u5144\u5F1F\u59D0\u59B9",
3189
+ "(\u5F02\u7236\u6BCD\u7684)?\u59D0\u59B9\u7684(\u914D\u5076|\u59BB\u5B50|\u4E08\u592B)": "\u59D0\u592B/\u59B9\u592B",
3190
+ "(\u5F02\u7236\u6BCD\u7684)?\u5144\u5F1F\u7684(\u914D\u5076|\u59BB\u5B50|\u4E08\u592B)": "\u5AC2\u5B50/\u5F1F\u59B9",
3191
+ "(\u5F02\u7236\u6BCD\u7684)?\u5144\u5F1F\u59D0\u59B9\u7684(\u914D\u5076|\u59BB\u5B50|\u4E08\u592B)": "\u59FB\u4EB2\u5144\u5F1F\u59D0\u59B9",
3192
+ "(\u5F02\u7236\u6BCD\u7684)?(\u914D\u5076|\u59BB\u5B50|\u4E08\u592B)\u7684\u59D0\u59B9": "\u59D1\u5B50/\u59E8\u5B50",
3193
+ "(\u5F02\u7236\u6BCD\u7684)?(\u914D\u5076|\u59BB\u5B50|\u4E08\u592B)\u7684\u5144\u5F1F": "\u5927\u4F2F/\u5C0F\u53D4/\u5185\u5144/\u5185\u5F1F",
3194
+ "(\u5F02\u7236\u6BCD\u7684)?(\u914D\u5076|\u59BB\u5B50|\u4E08\u592B)\u7684\u5144\u5F1F\u59D0\u59B9": "\u59FB\u4EB2\u5144\u5F1F\u59D0\u59B9"
3195
+ };
3196
+
3197
+ // src/kinship-translator/kinship-translator.zh.ts
3198
+ var sexOf3 = (person) => {
3199
+ if (person?.isMale?.()) {
3200
+ return "m";
3201
+ }
3202
+ if (person?.isFemale?.()) {
3203
+ return "f";
3204
+ }
3205
+ return "n";
3206
+ };
3207
+ var pick2 = (sex, male, female, neutral) => {
3208
+ if (sex === "m") {
3209
+ return male;
3210
+ }
3211
+ if (sex === "f") {
3212
+ return female;
3213
+ }
3214
+ return neutral;
3215
+ };
3216
+ var lineal2 = (level, sex, kind) => {
3217
+ const L = Math.max(1, level);
3218
+ if (kind === "asc") {
3219
+ if (L <= 1) {
3220
+ return pick2(sex, "\u7236\u4EB2", "\u6BCD\u4EB2", "\u7236\u6BCD");
3221
+ }
3222
+ if (L === 2) {
3223
+ return pick2(sex, "\u7956\u7236", "\u7956\u6BCD", "\u7956\u7236\u6BCD");
3224
+ }
3225
+ if (L === 3) {
3226
+ return pick2(sex, "\u66FE\u7956\u7236", "\u66FE\u7956\u6BCD", "\u66FE\u7956\u7236\u6BCD");
3227
+ }
3228
+ if (L === 4) {
3229
+ return pick2(sex, "\u9AD8\u7956\u7236", "\u9AD8\u7956\u6BCD", "\u9AD8\u7956\u7236\u6BCD");
3230
+ }
3231
+ return pick2(sex, `${L}\u4E16\u7956`, `${L}\u4E16\u7956\u6BCD`, `${L}\u4E16\u7956\u7236\u6BCD`);
3232
+ }
3233
+ if (L <= 1) {
3234
+ return pick2(sex, "\u513F\u5B50", "\u5973\u513F", "\u5B50\u5973");
3235
+ }
3236
+ if (L === 2) {
3237
+ return pick2(sex, "\u5B59\u5B50", "\u5B59\u5973", "\u5B59\u5B50\u5973");
3238
+ }
3239
+ if (L === 3) {
3240
+ return pick2(sex, "\u66FE\u5B59", "\u66FE\u5B59\u5973", "\u66FE\u5B59\u5B50\u5973");
3241
+ }
3242
+ if (L === 4) {
3243
+ return pick2(sex, "\u7384\u5B59", "\u7384\u5B59\u5973", "\u7384\u5B59\u5B50\u5973");
3244
+ }
3245
+ return pick2(sex, `${L}\u4E16\u5B59`, `${L}\u4E16\u5B59\u5973`, `${L}\u4E16\u5B59\u5B50\u5973`);
3246
+ };
3247
+ var cousinPlain2 = (degree, sex) => {
3248
+ if (degree <= 1) {
3249
+ return pick2(sex, "\u5802\u8868\u5144\u5F1F", "\u5802\u8868\u59D0\u59B9", "\u5802\u8868\u4EB2");
3250
+ }
3251
+ if (degree === 2) {
3252
+ return pick2(sex, "\u4ECE\u5802\u8868\u5144\u5F1F", "\u4ECE\u5802\u8868\u59D0\u59B9", "\u4ECE\u5802\u8868\u4EB2");
3253
+ }
3254
+ return pick2(
3255
+ sex,
3256
+ `${degree}\u4EE3\u5802\u8868\u5144\u5F1F`,
3257
+ `${degree}\u4EE3\u5802\u8868\u59D0\u59B9`,
3258
+ `${degree}\u4EE3\u5802\u8868\u4EB2`
3259
+ );
3260
+ };
3261
+ var KinshipTranslatorZh = class extends KinshipTranslatorBasic {
3262
+ indirect() {
3263
+ let degree = Math.abs(this.pathN?.degree ?? 0);
3264
+ if (degree > 0) {
3265
+ degree = degree - 1;
3266
+ }
3267
+ return cousinPlain2(degree, sexOf3(this.personN));
3268
+ }
3269
+ removal() {
3270
+ const level = this.pathN?.level ?? 0;
3271
+ let degree = Math.abs(this.pathN?.degree ?? 0);
3272
+ if (degree > 0) {
3273
+ degree = degree - 1;
3274
+ }
3275
+ if (!degree) {
3276
+ return level < 0 ? this.nibling() : this.auncle();
3277
+ }
3278
+ const removed = Math.abs(level);
3279
+ return `${cousinPlain2(degree, sexOf3(this.personN))}\uFF08\u9694${removed}\u4EE3\uFF09`;
3280
+ }
3281
+ auncle() {
3282
+ const level = Math.abs(this.pathN?.level ?? 0);
3283
+ const sex = sexOf3(this.personN);
3284
+ if (level <= 2) {
3285
+ return pick2(sex, "\u53D4\u53D4", "\u963F\u59E8", "\u53D4\u4F2F/\u59D1\u59E8");
3286
+ }
3287
+ if (level === 3) {
3288
+ return pick2(sex, "\u4F2F\u53D4\u7956\u7236", "\u59D1\u7956\u6BCD", "\u4F2F\u53D4\u7956\u7236\u6BCD");
3289
+ }
3290
+ return pick2(
3291
+ sex,
3292
+ `${level - 2}\u4EE3\u524D\u7684\u53D4\u53D4`,
3293
+ `${level - 2}\u4EE3\u524D\u7684\u963F\u59E8`,
3294
+ `${level - 2}\u4EE3\u524D\u7684\u53D4\u4F2F/\u59D1\u59E8`
3295
+ );
3296
+ }
3297
+ nibling() {
3298
+ const level = Math.abs(this.pathN?.level ?? 0);
3299
+ const sex = sexOf3(this.personN);
3300
+ if (level <= 2) {
3301
+ return pick2(sex, "\u4F84\u5B50", "\u4F84\u5973", "\u4F84\u5B50\u5973");
3302
+ }
3303
+ if (level === 3) {
3304
+ return pick2(sex, "\u4F84\u5B59", "\u4F84\u5B59\u5973", "\u4F84\u5B59\u5B50\u5973");
3305
+ }
3306
+ return pick2(
3307
+ sex,
3308
+ `${level - 2}\u4EE3\u4E0B\u7684\u4F84\u5B50`,
3309
+ `${level - 2}\u4EE3\u4E0B\u7684\u4F84\u5973`,
3310
+ `${level - 2}\u4EE3\u4E0B\u7684\u4F84\u5B50\u5973`
3311
+ );
3312
+ }
3313
+ parent() {
3314
+ return lineal2(
3315
+ Math.abs(this.pathN?.level ?? 0),
3316
+ sexOf3(this.personN),
3317
+ "asc"
3318
+ );
3319
+ }
3320
+ child() {
3321
+ return lineal2(
3322
+ Math.abs(this.pathN?.level ?? 0),
3323
+ sexOf3(this.personN),
3324
+ "desc"
3325
+ );
3326
+ }
3327
+ sibling() {
3328
+ return pick2(sexOf3(this.personN), "\u5144\u5F1F", "\u59D0\u59B9", "\u5144\u5F1F\u59D0\u59B9");
3329
+ }
3330
+ halfBlood(relation) {
3331
+ if (!relation || !this.isHalfBlood) {
3332
+ return relation ?? "";
3333
+ }
3334
+ return `\u5F02\u7236\u6BCD\u7684${relation}`;
3335
+ }
3336
+ spouse() {
3337
+ return pick2(sexOf3(this.personN), "\u4E08\u592B", "\u59BB\u5B50", "\u914D\u5076");
3338
+ }
3339
+ ofSpouse(relation) {
3340
+ if (!relation) {
3341
+ return "";
3342
+ }
3343
+ const spouseType = pick2(
3344
+ sexOf3(this.path?.[1].indi),
3345
+ "\u4E08\u592B",
3346
+ "\u59BB\u5B50",
3347
+ "\u914D\u5076"
3348
+ );
3349
+ return `${spouseType}\u7684${relation}`;
3350
+ }
3351
+ spouseOf(relation) {
3352
+ if (!relation) {
3353
+ return "";
3354
+ }
3355
+ const spouse = this.path?.[this.path.length - 1].indi;
3356
+ const spouseType = pick2(sexOf3(spouse), "\u4E08\u592B", "\u59BB\u5B50", "\u914D\u5076");
3357
+ return `${relation}\u7684${spouseType}`;
3358
+ }
3359
+ of(relation) {
3360
+ const formattedName = nameFormatter(this.path?.[0]?.indi, {
3361
+ nameOrder: "last-first"
3362
+ });
3363
+ let name = formattedName.inOrder.filter(Boolean).join(" ");
3364
+ if (this.displayName === "none") {
3365
+ name = "";
3366
+ } else if (this.displayName === "givenname") {
3367
+ name = formattedName.givenname;
3368
+ } else if (this.displayName === "surname") {
3369
+ name = `${formattedName.surname}`;
3370
+ }
3371
+ if (!name || !relation) {
3372
+ return relation ?? "";
3373
+ }
3374
+ return `${name}\u7684${relation}`;
3375
+ }
3376
+ inLaw(relation) {
3377
+ let inLawRelation = relation;
3378
+ Object.keys(InLawsZh).find((pattern) => {
3379
+ const regex = new RegExp(`^${pattern}$`);
3380
+ if (relation?.match(regex)) {
3381
+ inLawRelation = InLawsZh[pattern];
3382
+ return true;
3383
+ }
3384
+ return false;
3385
+ });
3386
+ return inLawRelation ?? "";
3387
+ }
3388
+ relationType(relation) {
3389
+ if (!relation || !this.pathN?.relation) {
3390
+ return relation ?? "";
3391
+ }
3392
+ return `${this.pathN.relation}${relation}`;
3393
+ }
3394
+ };
3395
+
2879
3396
  // src/kinship-translator/kinship-translator.ts
2880
3397
  var KinshipTranslator = class {
2881
3398
  constructor(person1, person2, lang = "en", entirePath, displayName = "givenname") {
@@ -3725,11 +4242,8 @@ var storeCache = {
3725
4242
  getCacheDbs().relativesOnDegreeCache.setItem(value);
3726
4243
  }
3727
4244
  }, 50),
3728
- // profilePictureCache IS persisted to IndexedDB
4245
+ // Image bytes are stored as one IndexedDB record per photo.
3729
4246
  profilePictureCache: debounce((value) => {
3730
- if (value) {
3731
- getCacheDbs().profilePictureCache.setItem(value);
3732
- }
3733
4247
  }, 100)
3734
4248
  };
3735
4249
  var resetRelativesCache = () => {
@@ -4427,65 +4941,23 @@ var isRemoteOrEmbeddedMediaUrl = (path) => {
4427
4941
  }
4428
4942
  return path.startsWith("data:") || path.startsWith("blob:") || /^https?:\/\//i.test(path);
4429
4943
  };
4430
- var resolveLocalMediaUrl = async (path) => {
4944
+ var resolveLocalMediaUrl = async (path, context) => {
4431
4945
  if (!path) {
4432
4946
  return void 0;
4433
4947
  }
4434
- if (isRemoteOrEmbeddedMediaUrl(path)) {
4948
+ if (path.startsWith("data:") || path.startsWith("blob:")) {
4435
4949
  return path;
4436
4950
  }
4437
- const resolved = await localMediaResolver?.(path);
4438
- return resolved;
4439
- };
4440
- var implemented = (type, ...args) => {
4441
- };
4442
-
4443
- // src/utils/media-utils.ts
4444
- var getFileExtension = (filename) => {
4445
- if (!filename) {
4446
- return "";
4951
+ const resolved = await localMediaResolver?.(path, context);
4952
+ if (resolved) {
4953
+ return resolved;
4447
4954
  }
4448
- if (filename.startsWith("data:")) {
4449
- const mime = filename.slice(5).split(";")[0] || "";
4450
- const subtype = (mime.split("/")[1] || "").toLowerCase();
4451
- if (subtype === "jpeg") {
4452
- return "jpg";
4453
- }
4454
- return subtype.split("+")[0] || "";
4455
- }
4456
- const withoutQuery = filename.split(/[?#]/)[0] || filename;
4457
- const match = withoutQuery.match(/\.([^.]+)$/);
4458
- return match ? match[1].toLowerCase() : "";
4459
- };
4460
- var isImageFormat = (format2) => {
4461
- if (!format2) {
4462
- return false;
4463
- }
4464
- let normalized = format2.toLowerCase().trim();
4465
- if (normalized.startsWith("data:")) {
4466
- normalized = getFileExtension(normalized);
4467
- } else if (normalized.includes("/")) {
4468
- normalized = normalized.split("/")[1]?.split("+")[0] || "";
4469
- if (normalized === "jpeg") {
4470
- normalized = "jpg";
4471
- }
4955
+ if (/^https?:\/\//i.test(path)) {
4956
+ return path;
4472
4957
  }
4473
- const imageFormats = [
4474
- "jpg",
4475
- "jpeg",
4476
- "png",
4477
- "gif",
4478
- "bmp",
4479
- "webp",
4480
- "svg",
4481
- "tiff",
4482
- "tif"
4483
- ];
4484
- return imageFormats.includes(normalized);
4958
+ return void 0;
4485
4959
  };
4486
- var resolveObjeForm = (obje) => {
4487
- const value = obje?.get?.("FILE.FORM")?.toValue?.() ?? obje?.get?.("FORM")?.toValue?.();
4488
- return typeof value === "string" && value.trim() ? value.trim() : void 0;
4960
+ var implemented = (type, ...args) => {
4489
4961
  };
4490
4962
  var uniqueItemsCache = /* @__PURE__ */ new WeakMap();
4491
4963
  var setNestedGroup = (obj, key, value, uniqueCounting = true) => {
@@ -5735,22 +6207,19 @@ var Indi = class extends Common {
5735
6207
  if (objeList) {
5736
6208
  await Promise.all(
5737
6209
  objeList.map(async (objeRef) => {
5738
- const key = objeRef?.id;
6210
+ const key = objeXrefKey(objeRef, 0);
5739
6211
  const obje = objeRef?.standardizeMedia(
5740
6212
  namespace,
5741
6213
  true,
5742
- (ns, iId) => {
5743
- return ns && iId ? `https://mediasvc.ancestry.com/v2/image/namespaces/${ns}/media/${iId}?client=trees-mediaservice&imageQuality=hq` : void 0;
5744
- }
6214
+ ancestryMediaFileUrl
5745
6215
  );
5746
6216
  const isPrimary = obje?.get("_PRIM")?.toValue() === "Y";
5747
- const media = obje?.RIN?.toValue() || obje?.get("_OID")?.toValue();
5748
- const clone = obje?.get("_CLON._OID")?.toValue();
5749
- const mser = obje?.get("_MSER._LKID")?.toValue();
6217
+ const media = resolveObjeMediaId(obje);
5750
6218
  let url = obje?.get("FILE")?.toValue();
5751
6219
  const title = obje?.get("FILE.TITL")?.toValue() ?? obje?.get("TITL")?.toValue() ?? "";
6220
+ const note = objeNoteValue(obje);
5752
6221
  const type = resolveObjeForm(obje) ?? (url ? getFileExtension(url) : void 0) ?? "raw";
5753
- let imgId = clone || mser;
6222
+ let imgId = media;
5754
6223
  const hasEmbeddedOrLocalFile = !!url && (url.startsWith("data:") || url.startsWith("blob:") || !/^https?:\/\//i.test(url));
5755
6224
  if (!hasEmbeddedOrLocalFile && (!www || !tree || !this.id)) {
5756
6225
  return;
@@ -5786,6 +6255,7 @@ var Indi = class extends Common {
5786
6255
  imgId,
5787
6256
  person: this.id,
5788
6257
  title,
6258
+ note,
5789
6259
  url,
5790
6260
  contentType: type,
5791
6261
  downloadName: `${this.id.replaceAll("@", "")}_${this.toNaturalName()?.replaceAll(" ", "-") || ""}_${(title || key.replaceAll("@", "").toString()).replaceAll(" ", "-")}`
@@ -5824,7 +6294,7 @@ var Indi = class extends Common {
5824
6294
  return;
5825
6295
  }
5826
6296
  const obje = o;
5827
- const key = `@O${index}@`;
6297
+ const key = objeXrefKey(obje, index);
5828
6298
  obje.standardizeMedia();
5829
6299
  const isPrimary = obje?.get("_PRIM")?.toValue() === "Y";
5830
6300
  const url = obje?.get("FILE")?.toValue();
@@ -5843,6 +6313,7 @@ var Indi = class extends Common {
5843
6313
  imgId,
5844
6314
  person: this.id,
5845
6315
  title,
6316
+ note: objeNoteValue(obje),
5846
6317
  url,
5847
6318
  contentType: type,
5848
6319
  downloadName: `${this.id.replaceAll("@", "")}_${this.toNaturalName()?.replaceAll(" ", "-") || ""}_${(title || key.replaceAll("@", "").toString()).replaceAll(" ", "-")}`
@@ -5951,7 +6422,7 @@ var Indi = class extends Common {
5951
6422
  if (!obje) {
5952
6423
  return;
5953
6424
  }
5954
- const key = `@O${index}@`;
6425
+ const key = objeXrefKey(obje, index);
5955
6426
  const isPrimary = obje?.get("_PRIM")?.toValue() === "Y";
5956
6427
  const url = obje?.get("FILE")?.toValue();
5957
6428
  const title = obje?.get("TITL")?.toValue() ?? "";
@@ -5968,6 +6439,7 @@ var Indi = class extends Common {
5968
6439
  imgId,
5969
6440
  person: this.id,
5970
6441
  title,
6442
+ note: objeNoteValue(obje),
5971
6443
  url,
5972
6444
  contentType: type,
5973
6445
  downloadName: `${this.id.replaceAll("@", "")}_${this.toNaturalName()?.replaceAll(" ", "-") || ""}_${(title || key.replaceAll("@", "").toString()).replaceAll(" ", "-")}`
@@ -5991,7 +6463,7 @@ var Indi = class extends Common {
5991
6463
  if (!obje) {
5992
6464
  return;
5993
6465
  }
5994
- const key = `@O${index}@`;
6466
+ const key = objeXrefKey(obje, index);
5995
6467
  obje.standardizeMedia();
5996
6468
  const isPrimary = obje?.get("_PRIM")?.toValue() === "Y";
5997
6469
  const url = obje?.get("FILE")?.toValue();
@@ -6008,6 +6480,7 @@ var Indi = class extends Common {
6008
6480
  imgId,
6009
6481
  person: this.id,
6010
6482
  title,
6483
+ note: objeNoteValue(obje),
6011
6484
  url,
6012
6485
  contentType: type,
6013
6486
  downloadName: `${this.id.replaceAll("@", "")}_${this.toNaturalName()?.replaceAll(" ", "-") || ""}_${(title || key.replaceAll("@", "").toString()).replaceAll(" ", "-")}`
@@ -6039,7 +6512,12 @@ var Indi = class extends Common {
6039
6512
  );
6040
6513
  if (cached !== void 0) {
6041
6514
  if (cached?.file && !isRemoteOrEmbeddedMediaUrl(cached.file)) {
6042
- const resolvedCached = await resolveLocalMediaUrl(cached.file);
6515
+ const resolvedCached = await resolveLocalMediaUrl(cached.file, {
6516
+ url: cached.file,
6517
+ person: this.id,
6518
+ tree: this.getTreeId?.(),
6519
+ treeName: this.getTreeName?.()
6520
+ });
6043
6521
  if (resolvedCached && isRemoteOrEmbeddedMediaUrl(resolvedCached)) {
6044
6522
  const refreshed = { ...cached, file: resolvedCached };
6045
6523
  profilePictureCache(
@@ -6064,7 +6542,16 @@ var Indi = class extends Common {
6064
6542
  }
6065
6543
  const mediaArray = Object.values(mediaList);
6066
6544
  const toDisplayableProfile = async (media, isPrimary) => {
6067
- const resolvedFile = await resolveLocalMediaUrl(media.url);
6545
+ const resolvedFile = await resolveLocalMediaUrl(media.url, {
6546
+ url: media.url,
6547
+ id: media.id,
6548
+ imgId: media.imgId,
6549
+ key: media.key,
6550
+ contentType: media.contentType,
6551
+ person: media.person || this.id,
6552
+ tree: media.tree || this.getTreeId?.(),
6553
+ treeName: this.getTreeName?.()
6554
+ });
6068
6555
  if (!resolvedFile || !isRemoteOrEmbeddedMediaUrl(resolvedFile)) {
6069
6556
  return void 0;
6070
6557
  }
@@ -8174,7 +8661,7 @@ var ensureExtensionSchema = (gedcom, extraTags) => {
8174
8661
 
8175
8662
  // package.json
8176
8663
  var package_default = {
8177
- version: "2.1.8"};
8664
+ version: "2.1.11"};
8178
8665
 
8179
8666
  // src/utils/get-product-details.ts
8180
8667
  var getVersion = () => package_default.version;
@@ -8254,16 +8741,26 @@ var Obje = class extends Common {
8254
8741
  if (!this._gedcom) {
8255
8742
  return this;
8256
8743
  }
8744
+ if (typeof this.value === "string" && isId(this.value) && this.refType === "OBJE") {
8745
+ const resolved = this.ref;
8746
+ if (resolved && resolved !== this && typeof resolved.standardizeMedia === "function") {
8747
+ resolved.standardizeMedia(
8748
+ namespace,
8749
+ override,
8750
+ urlGetter,
8751
+ gedcomVersion
8752
+ );
8753
+ return this;
8754
+ }
8755
+ }
8257
8756
  const rin = this?.get("RIN")?.toValue();
8258
- const clone = this?.get("_CLON._OID")?.toValue();
8259
- const mser = this?.get("_MSER._LKID")?.toValue();
8260
8757
  const title = this?.get("FILE.TITL")?.toValue() ?? this?.get("TITL")?.toValue() ?? "";
8261
8758
  const note = this?.get("FILE.NOTE")?.toValue() ?? this?.get("NOTE")?.toValue() ?? "";
8262
8759
  const formRaw = this?.get("FILE.FORM")?.toValue() ?? this?.get("FORM")?.toValue();
8263
8760
  const mediType = this?.get("FILE.FORM.TYPE")?.toValue() ?? this?.get("FORM.TYPE")?.toValue() ?? this?.get("MEDI")?.toValue();
8264
8761
  const file = this?.get("FILE")?.toValue();
8265
- const imgId = rin || clone || mser;
8266
- const url = file || namespace && urlGetter?.(namespace, imgId);
8762
+ const imgId = resolveObjeMediaId(this);
8763
+ const url = file || this.isAncestry() && namespace && urlGetter?.(namespace, imgId);
8267
8764
  if (!url) {
8268
8765
  return this;
8269
8766
  }
@@ -8776,6 +9273,22 @@ var GedCom = class extends Common {
8776
9273
  obje(index) {
8777
9274
  return this.getMain(this.objes(), index);
8778
9275
  }
9276
+ /**
9277
+ * People who link a shared multimedia record (`1 OBJE @On@`), i.e. Ancestry
9278
+ * face tags / everyone the photo is attached to.
9279
+ */
9280
+ indisLinkingObje(objeKey) {
9281
+ const people = [];
9282
+ this.indis()?.forEach((indi) => {
9283
+ const linked = indi?.get("OBJE")?.toList()?.values()?.some(
9284
+ (item) => item?.toValue?.() === objeKey || item?.id === objeKey
9285
+ );
9286
+ if (linked && indi) {
9287
+ people.push(indi);
9288
+ }
9289
+ });
9290
+ return people;
9291
+ }
8779
9292
  sour(index) {
8780
9293
  return this.getMain(this.sours(), index);
8781
9294
  }