@treeviz/gedcom-parser 1.0.22 → 2.0.0

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.
@@ -23,70 +23,143 @@ var getCacheManagerFactory = () => {
23
23
  };
24
24
 
25
25
  // src/utils/cache.ts
26
+ var getGedcomId = (gedcom) => {
27
+ if (!gedcom) {
28
+ return "unknown";
29
+ }
30
+ const treeId = gedcom.getTreeId?.() || "";
31
+ const treeName = gedcom.getTreeName?.() || "";
32
+ const sanitizedName = treeName.toLowerCase().replace(/[^a-z0-9]+/g, "_").replace(/^_+|_+$/g, "");
33
+ if (treeId && sanitizedName) {
34
+ return `${treeId}_${sanitizedName}`;
35
+ } else if (treeId) {
36
+ return treeId;
37
+ } else if (sanitizedName) {
38
+ return sanitizedName;
39
+ }
40
+ return `gedcom_${gedcom.refcount}`;
41
+ };
26
42
  var caches = {
27
43
  pathCache: {},
28
44
  relativesOnDegreeCache: {},
29
- relativesOnLevelCache: {}
45
+ relativesOnLevelCache: {},
46
+ profilePictureCache: {}
30
47
  };
31
- var getInstance = getCacheManagerFactory();
32
- var cacheDbs = {
33
- pathCache: getInstance("ftv", "Main", "path", true),
34
- relativesOnDegreeCache: getInstance(
35
- "ftv",
36
- "Main",
37
- "path",
38
- true
39
- ),
40
- relativesOnLevelCache: getInstance(
41
- "ftv",
42
- "Main",
43
- "path",
44
- true
45
- )
48
+ var cacheDbs;
49
+ var getCacheDbs = () => {
50
+ if (!cacheDbs) {
51
+ const getInstance = getCacheManagerFactory();
52
+ cacheDbs = {
53
+ pathCache: getInstance(
54
+ "ftv",
55
+ "Main",
56
+ "path",
57
+ true
58
+ ),
59
+ relativesOnDegreeCache: getInstance("ftv", "Main", "path", true),
60
+ relativesOnLevelCache: getInstance(
61
+ "ftv",
62
+ "Main",
63
+ "path",
64
+ true
65
+ ),
66
+ profilePictureCache: getInstance(
67
+ "ftv",
68
+ "Main",
69
+ "images",
70
+ false
71
+ )
72
+ };
73
+ }
74
+ return cacheDbs;
46
75
  };
47
- ({
76
+ var storeCache = {
77
+ // NOTE: pathCache, relativesOnLevelCache, and relativesOnDegreeCache are intentionally
78
+ // kept in memory only. These debounced functions exist to satisfy the type system
79
+ // but are never called.
48
80
  pathCache: debounce((value) => {
49
81
  if (value) {
50
- cacheDbs.pathCache.setItem(value);
82
+ getCacheDbs().pathCache.setItem(value);
51
83
  }
52
84
  }, 50),
53
85
  relativesOnLevelCache: debounce((value) => {
54
86
  if (value) {
55
- cacheDbs.relativesOnLevelCache.setItem(value);
87
+ getCacheDbs().relativesOnLevelCache.setItem(value);
56
88
  }
57
89
  }, 50),
58
90
  relativesOnDegreeCache: debounce((value) => {
59
91
  if (value) {
60
- cacheDbs.relativesOnDegreeCache.setItem(value);
92
+ getCacheDbs().relativesOnDegreeCache.setItem(value);
61
93
  }
62
- }, 50)
63
- });
94
+ }, 50),
95
+ // profilePictureCache IS persisted to IndexedDB
96
+ profilePictureCache: debounce((value) => {
97
+ if (value) {
98
+ getCacheDbs().profilePictureCache.setItem(value);
99
+ }
100
+ }, 100)
101
+ };
102
+ var cacheInitialized = false;
103
+ var initializeCache = async () => {
104
+ if (cacheInitialized) {
105
+ return;
106
+ }
107
+ cacheInitialized = true;
108
+ try {
109
+ const profilePictureData = await getCacheDbs().profilePictureCache.getItem();
110
+ if (profilePictureData) {
111
+ caches.profilePictureCache = profilePictureData;
112
+ }
113
+ } catch (_error) {
114
+ }
115
+ };
64
116
  var resetRelativesCache = () => {
65
117
  caches.relativesOnDegreeCache = {};
66
118
  caches.relativesOnLevelCache = {};
67
119
  };
68
- var relativesCache = (cacheKey) => (key, subKey, value) => {
69
- if (!caches[cacheKey]) {
120
+ var relativesCache = (cacheKey) => (gedcom, key, subKey, value) => {
121
+ const gedcomId = getGedcomId(gedcom);
122
+ const fullKey = `${gedcomId}:${key}`;
123
+ const cache = caches[cacheKey];
124
+ if (!cache) {
70
125
  caches[cacheKey] = {};
71
126
  }
72
- if (value && caches[cacheKey]) {
73
- if (!caches[cacheKey][key]) {
74
- caches[cacheKey][key] = {};
127
+ if (value) {
128
+ const typedCache2 = caches[cacheKey];
129
+ if (!typedCache2[fullKey]) {
130
+ typedCache2[fullKey] = {};
75
131
  }
76
- caches[cacheKey][key][subKey] = value;
77
- return caches[cacheKey][key][subKey];
132
+ typedCache2[fullKey][subKey] = value;
133
+ return typedCache2[fullKey][subKey];
78
134
  }
79
- return caches[cacheKey]?.[key]?.[subKey];
135
+ const typedCache = caches[cacheKey];
136
+ return typedCache?.[fullKey]?.[subKey];
80
137
  };
81
- var pathCache = (key, value) => {
138
+ var pathCache = (gedcom, key, value) => {
139
+ const gedcomId = getGedcomId(gedcom);
140
+ const fullKey = `${gedcomId}:${key}`;
82
141
  if (!caches.pathCache) {
83
142
  caches.pathCache = {};
84
143
  }
85
144
  if (value && caches.pathCache) {
86
- caches.pathCache[key] = value;
87
- return caches.pathCache[key];
145
+ caches.pathCache[fullKey] = value;
146
+ return caches.pathCache[fullKey];
88
147
  }
89
- return caches.pathCache?.[key];
148
+ return caches.pathCache?.[fullKey];
149
+ };
150
+ var profilePictureCache = (gedcom, key, value) => {
151
+ const gedcomId = getGedcomId(gedcom);
152
+ const fullKey = `${gedcomId}:${key}`;
153
+ if (!caches.profilePictureCache) {
154
+ caches.profilePictureCache = {};
155
+ }
156
+ if (value && caches.profilePictureCache) {
157
+ caches.profilePictureCache[fullKey] = value;
158
+ storeCache.profilePictureCache(caches.profilePictureCache);
159
+ return caches.profilePictureCache[fullKey];
160
+ }
161
+ const cached = caches.profilePictureCache?.[fullKey];
162
+ return cached;
90
163
  };
91
164
 
92
165
  // src/constants/constants.ts
@@ -862,11 +935,30 @@ var Common = class _Common {
862
935
  const sour = get(head, "SOUR.value");
863
936
  return !!sour?.toLowerCase()?.startsWith("myheritage");
864
937
  }
938
+ /**
939
+ * Get the source type as a string (for prefixing tree IDs and names)
940
+ * Returns the detected source type or undefined if unknown
941
+ */
942
+ getSourceType() {
943
+ if (this.isAncestry()) return "Ancestry";
944
+ if (this.isMyHeritage()) return "MyHeritage";
945
+ if (this.isFamilySearch()) return "FamilySearch";
946
+ if (this.isGNO2GED()) return "GNO2GED";
947
+ if (this.isGenoPro()) return "GenoPro";
948
+ if (this.isAhnenblatt()) return "Ahnenblatt";
949
+ if (this.isGeni()) return "Geni";
950
+ return void 0;
951
+ }
865
952
  isFamilySearch() {
866
953
  const head = get(this, "HEAD") || get(this.getGedcom(), "HEAD");
867
954
  const sourName = get(head, "SOUR.NAME.value");
868
955
  return sourName === "FamilySearch API";
869
956
  }
957
+ isGNO2GED() {
958
+ const head = get(this, "HEAD") || get(this.getGedcom(), "HEAD");
959
+ const sour = get(head, "SOUR.value");
960
+ return sour === "GNO2GED";
961
+ }
870
962
  getAncestryTreeId() {
871
963
  const path = "HEAD.SOUR._TREE.RIN.value";
872
964
  return get(this, path) || get(this.getGedcom(), path);
@@ -877,11 +969,34 @@ var Common = class _Common {
877
969
  }
878
970
  getTreeId() {
879
971
  if (this?.isAncestry()) {
880
- return this.getAncestryTreeId();
972
+ const id = this.getAncestryTreeId();
973
+ if (id !== void 0) return id;
881
974
  }
882
975
  if (this?.isMyHeritage()) {
883
- return this.getMyHeritageTreeId();
976
+ const id = this.getMyHeritageTreeId();
977
+ if (id !== void 0) return id;
978
+ }
979
+ if (this?.isFamilySearch()) {
980
+ const id = this.getFamilySearchTreeId();
981
+ if (id !== void 0) return id;
982
+ }
983
+ if (this?.isGNO2GED()) {
984
+ const id = this.getGNO2GEDTreeId();
985
+ if (id !== void 0) return id;
884
986
  }
987
+ if (this?.isAhnenblatt()) {
988
+ const id = this.getAhnenblattTreeId();
989
+ if (id !== void 0) return id;
990
+ }
991
+ if (this?.isGeni()) {
992
+ const id = this.getGeniTreeId();
993
+ if (id !== void 0) return id;
994
+ }
995
+ if (this?.isGenoPro()) {
996
+ const id = this.getGenoProTreeId();
997
+ if (id !== void 0) return id;
998
+ }
999
+ return this.getUniversalTreeId();
885
1000
  }
886
1001
  getAncestryTreeName() {
887
1002
  const path = "HEAD.SOUR._TREE.value";
@@ -894,13 +1009,146 @@ var Common = class _Common {
894
1009
  /Exported by MyHeritage.com from (?<tree>.+) in.+$/
895
1010
  )?.groups?.tree;
896
1011
  }
1012
+ getFamilySearchTreeId() {
1013
+ const rin = get(this, "HEAD.SOUR._TREE.RIN.value") || get(this.getGedcom(), "HEAD.SOUR._TREE.RIN.value");
1014
+ if (rin) {
1015
+ return rin;
1016
+ }
1017
+ return "familysearch";
1018
+ }
1019
+ getFamilySearchTreeName() {
1020
+ const treeName = get(this, "HEAD.SOUR._TREE.value") || get(this.getGedcom(), "HEAD.SOUR._TREE.value");
1021
+ if (treeName) {
1022
+ return treeName;
1023
+ }
1024
+ const fileName = get(this, "HEAD.FILE.value") || get(this.getGedcom(), "HEAD.FILE.value");
1025
+ return fileName || "FamilySearch Import";
1026
+ }
1027
+ getAhnenblattTreeId() {
1028
+ const fileName = get(this, "HEAD.FILE.value") || get(this.getGedcom(), "HEAD.FILE.value");
1029
+ if (fileName) {
1030
+ const idMatch = fileName.match(/_(\d+)/);
1031
+ if (idMatch) {
1032
+ return idMatch[1];
1033
+ }
1034
+ }
1035
+ return void 0;
1036
+ }
1037
+ getAhnenblattTreeName() {
1038
+ const fileName = get(this, "HEAD.FILE.value") || get(this.getGedcom(), "HEAD.FILE.value");
1039
+ return fileName?.replace(/\.ged$/i, "").replace(/_/g, " ");
1040
+ }
1041
+ getGeniTreeId() {
1042
+ const fileName = get(this, "HEAD.FILE.value") || get(this.getGedcom(), "HEAD.FILE.value");
1043
+ if (fileName) {
1044
+ const idMatch = fileName.match(/_(\d+)/);
1045
+ if (idMatch) {
1046
+ return idMatch[1];
1047
+ }
1048
+ }
1049
+ return void 0;
1050
+ }
1051
+ getGeniTreeName() {
1052
+ const fileName = get(this, "HEAD.FILE.value") || get(this.getGedcom(), "HEAD.FILE.value");
1053
+ return fileName?.replace(/\.ged$/i, "").replace(/_/g, " ");
1054
+ }
1055
+ getGenoProTreeId() {
1056
+ const fileName = get(this, "HEAD.FILE.value") || get(this.getGedcom(), "HEAD.FILE.value");
1057
+ if (fileName) {
1058
+ const idMatch = fileName.match(/_(\d+)/);
1059
+ if (idMatch) {
1060
+ return idMatch[1];
1061
+ }
1062
+ }
1063
+ return void 0;
1064
+ }
1065
+ getGenoProTreeName() {
1066
+ const fileName = get(this, "HEAD.FILE.value") || get(this.getGedcom(), "HEAD.FILE.value");
1067
+ return fileName?.replace(/\.ged$/i, "").replace(/_/g, " ");
1068
+ }
1069
+ getGNO2GEDTreeId() {
1070
+ const rin = get(this, "HEAD._TREE.RIN.value") || get(this.getGedcom(), "HEAD._TREE.RIN.value");
1071
+ if (rin) {
1072
+ return rin;
1073
+ }
1074
+ return `gno_${this._gedcom?.refcount || "unknown"}`;
1075
+ }
1076
+ getGNO2GEDTreeName() {
1077
+ const treeName = get(this, "HEAD._TREE.value") || get(this.getGedcom(), "HEAD._TREE.value");
1078
+ if (treeName) {
1079
+ return treeName;
1080
+ }
1081
+ const fileName = get(this, "HEAD.FILE.value") || get(this.getGedcom(), "HEAD.FILE.value");
1082
+ return fileName || "GNO2GED Export";
1083
+ }
1084
+ /**
1085
+ * Universal tree ID getter for unknown/unrecognized GEDCOM sources
1086
+ * Tries to extract an ID from various common locations
1087
+ */
1088
+ getUniversalTreeId() {
1089
+ const sourceType = this.getSourceType();
1090
+ const prefix = sourceType ? sourceType.toLowerCase() : "tree";
1091
+ const fileName = get(this, "HEAD.FILE.value") || get(this.getGedcom(), "HEAD.FILE.value");
1092
+ if (fileName) {
1093
+ const idMatch = fileName.match(/_(\d+)/);
1094
+ if (idMatch) {
1095
+ return `${prefix}_${idMatch[1]}`;
1096
+ }
1097
+ }
1098
+ return `${prefix}_${this._gedcom?.refcount || "unknown"}`;
1099
+ }
1100
+ /**
1101
+ * Universal tree name getter for unknown/unrecognized GEDCOM sources
1102
+ * Tries to extract a name from various common locations
1103
+ */
1104
+ getUniversalTreeName() {
1105
+ const sourceType = this.getSourceType();
1106
+ const prefix = sourceType ? `${sourceType}-` : "";
1107
+ const fileName = get(this, "HEAD.FILE.value") || get(this.getGedcom(), "HEAD.FILE.value");
1108
+ if (fileName) {
1109
+ const cleanName = fileName.replace(/\.ged$/i, "").replace(/_/g, " ");
1110
+ return `${prefix}${cleanName}`;
1111
+ }
1112
+ const sourName = get(this, "HEAD.SOUR.NAME.value") || get(this.getGedcom(), "HEAD.SOUR.NAME.value");
1113
+ if (sourName) {
1114
+ return `${prefix}${sourName}`;
1115
+ }
1116
+ const sourValue = get(this, "HEAD.SOUR.value") || get(this.getGedcom(), "HEAD.SOUR.value");
1117
+ if (sourValue) {
1118
+ return `${prefix}${sourValue}`;
1119
+ }
1120
+ return `${prefix}Unknown Tree`;
1121
+ }
897
1122
  getTreeName() {
898
1123
  if (this?.isAncestry()) {
899
- return this.getAncestryTreeName();
1124
+ const name = this.getAncestryTreeName();
1125
+ if (name) return name;
900
1126
  }
901
1127
  if (this?.isMyHeritage()) {
902
- return this.getMyHeritageTreeName();
1128
+ const name = this.getMyHeritageTreeName();
1129
+ if (name) return name;
1130
+ }
1131
+ if (this?.isFamilySearch()) {
1132
+ const name = this.getFamilySearchTreeName();
1133
+ if (name) return name;
1134
+ }
1135
+ if (this?.isGNO2GED()) {
1136
+ const name = this.getGNO2GEDTreeName();
1137
+ if (name) return name;
903
1138
  }
1139
+ if (this?.isAhnenblatt()) {
1140
+ const name = this.getAhnenblattTreeName();
1141
+ if (name) return name;
1142
+ }
1143
+ if (this?.isGeni()) {
1144
+ const name = this.getGeniTreeName();
1145
+ if (name) return name;
1146
+ }
1147
+ if (this?.isGenoPro()) {
1148
+ const name = this.getGenoProTreeName();
1149
+ if (name) return name;
1150
+ }
1151
+ return this.getUniversalTreeName();
904
1152
  }
905
1153
  };
906
1154
  var createProxy = (target) => {
@@ -2739,7 +2987,7 @@ var Indi = class extends Common {
2739
2987
  }
2740
2988
  async ancestryMedia(namespace) {
2741
2989
  const list = {};
2742
- const objeList = this.get("OBJE")?.toList();
2990
+ const objeList = this.get("OBJE")?.toList().copy();
2743
2991
  const www = this._gedcom?.HEAD?.SOUR?.CORP?.WWW?.value;
2744
2992
  const tree = this.getAncestryTreeId();
2745
2993
  if (objeList) {
@@ -2813,11 +3061,12 @@ var Indi = class extends Common {
2813
3061
  if (!tree) {
2814
3062
  return;
2815
3063
  }
2816
- const objeList = this.get("OBJE")?.toList();
2817
- const birthObj = this.get("BIRT.OBJE")?.toList();
2818
- const deathObj = this.get("DEAT.OBJE")?.toList();
3064
+ const objeList = this.get("OBJE")?.toList().copy();
3065
+ const birthObj = this.get("BIRT.OBJE")?.toList().copy();
3066
+ const deathObj = this.get("DEAT.OBJE")?.toList().copy();
3067
+ objeList?.merge(birthObj).merge(deathObj);
2819
3068
  (this.get("FAMS")?.toValueList().values() ?? []).concat(this.get("FAMC")?.toValueList().values() ?? []).forEach((fam) => {
2820
- objeList?.merge(birthObj).merge(deathObj).merge(fam?.get("MARR.OBJE"));
3069
+ objeList.merge(fam?.get("MARR.OBJE"));
2821
3070
  });
2822
3071
  objeList?.forEach((o, index) => {
2823
3072
  if (!o) {
@@ -2935,6 +3184,88 @@ var Indi = class extends Common {
2935
3184
  };
2936
3185
  });
2937
3186
  }
3187
+ geniMedia() {
3188
+ const list = {};
3189
+ const objeList = this.get("OBJE")?.toList().copy();
3190
+ const sourList = this.get("SOUR")?.toList().copy();
3191
+ sourList?.forEach((sour) => {
3192
+ const sourObje = sour?.get("OBJE")?.toList();
3193
+ objeList.merge(sourObje);
3194
+ });
3195
+ if (!objeList || objeList.length === 0) {
3196
+ return void 0;
3197
+ }
3198
+ const rfn = this.get("RFN")?.toValue();
3199
+ const geniId = rfn?.replace(/^geni:/, "") || "unknown";
3200
+ objeList.forEach((obje, index) => {
3201
+ if (!obje) {
3202
+ return;
3203
+ }
3204
+ const key = `@O${index}@`;
3205
+ const isPrimary = obje?.get("_PRIM")?.toValue() === "Y";
3206
+ const url = obje?.get("FILE")?.toValue();
3207
+ const title = obje?.get("TITL")?.toValue() ?? "";
3208
+ const type = obje?.get("FORM")?.toValue() ?? "raw";
3209
+ if (url) {
3210
+ const urlMatch = url.match(/\/([^/]+)\?hash=/);
3211
+ const imgId = urlMatch?.[1] || `img-${index}-${Date.now().toString(36)}`;
3212
+ const id = `geni-${geniId}-${imgId}`;
3213
+ list[id] = {
3214
+ isPrimary,
3215
+ key,
3216
+ id,
3217
+ tree: geniId,
3218
+ imgId,
3219
+ person: this.id,
3220
+ title,
3221
+ url,
3222
+ contentType: type,
3223
+ downloadName: `${this.id.replaceAll("@", "")}_${this.toNaturalName()?.replaceAll(" ", "-") || ""}_${(title || key.replaceAll("@", "").toString()).replaceAll(" ", "-")}`
3224
+ };
3225
+ }
3226
+ });
3227
+ return list;
3228
+ }
3229
+ universalMedia() {
3230
+ const list = {};
3231
+ if (!this.id) {
3232
+ return list;
3233
+ }
3234
+ const objeList = this.get("OBJE")?.toList().copy();
3235
+ if (!objeList || objeList.length === 0) {
3236
+ return list;
3237
+ }
3238
+ const rfn = this.get("RFN")?.toValue();
3239
+ const treeId = rfn || "universal";
3240
+ objeList.forEach((obje, index) => {
3241
+ if (!obje) {
3242
+ return;
3243
+ }
3244
+ const key = `@O${index}@`;
3245
+ obje.standardizeMedia();
3246
+ const isPrimary = obje?.get("_PRIM")?.toValue() === "Y";
3247
+ const url = obje?.get("FILE")?.toValue();
3248
+ const title = obje?.get("TITL")?.toValue() ?? "";
3249
+ const type = obje?.get("FORM")?.toValue() ?? "raw";
3250
+ if (url) {
3251
+ const imgId = `media-${index}-${url.split("/").pop()?.split("?")[0]?.substring(0, 20) || Date.now().toString(36)}`;
3252
+ const id = `${treeId}-${this.id}-${imgId}`;
3253
+ list[id] = {
3254
+ isPrimary,
3255
+ key,
3256
+ id,
3257
+ tree: treeId,
3258
+ imgId,
3259
+ person: this.id,
3260
+ title,
3261
+ url,
3262
+ contentType: type,
3263
+ downloadName: `${this.id.replaceAll("@", "")}_${this.toNaturalName()?.replaceAll(" ", "-") || ""}_${(title || key.replaceAll("@", "").toString()).replaceAll(" ", "-")}`
3264
+ };
3265
+ }
3266
+ });
3267
+ return list;
3268
+ }
2938
3269
  async multimedia(namespace) {
2939
3270
  if (this?.isAncestry()) {
2940
3271
  return await this.ancestryMedia(namespace);
@@ -2942,11 +3273,30 @@ var Indi = class extends Common {
2942
3273
  if (this?.isMyHeritage()) {
2943
3274
  return this.myheritageMedia();
2944
3275
  }
2945
- return void 0;
3276
+ if (this?.isGeni()) {
3277
+ return this.geniMedia();
3278
+ }
3279
+ return this.universalMedia();
2946
3280
  }
2947
- async getProfilePicture(namespace) {
3281
+ async getProfilePicture(namespace, onlyPrimary = true) {
3282
+ if (!this.id) {
3283
+ return void 0;
3284
+ }
3285
+ const cacheKey = this.id;
3286
+ const cached = profilePictureCache(
3287
+ this._gedcom,
3288
+ cacheKey
3289
+ );
3290
+ if (cached !== void 0) {
3291
+ return cached;
3292
+ }
2948
3293
  const mediaList = await this.multimedia(namespace);
2949
3294
  if (!mediaList) {
3295
+ profilePictureCache(
3296
+ this._gedcom,
3297
+ cacheKey,
3298
+ void 0
3299
+ );
2950
3300
  return void 0;
2951
3301
  }
2952
3302
  const mediaArray = Object.values(mediaList);
@@ -2954,24 +3304,41 @@ var Indi = class extends Common {
2954
3304
  (media) => media.isPrimary && isImageFormat(media.contentType || getFileExtension(media.url))
2955
3305
  );
2956
3306
  if (primaryMedia) {
2957
- return {
3307
+ const result = {
2958
3308
  file: primaryMedia.url,
2959
3309
  form: primaryMedia.contentType,
2960
3310
  title: primaryMedia.title,
2961
3311
  isPrimary: true
2962
3312
  };
3313
+ profilePictureCache(this._gedcom, cacheKey, result);
3314
+ return result;
3315
+ }
3316
+ if (onlyPrimary) {
3317
+ profilePictureCache(
3318
+ this._gedcom,
3319
+ cacheKey,
3320
+ void 0
3321
+ );
3322
+ return void 0;
2963
3323
  }
2964
3324
  const secondaryMedia = mediaArray.find(
2965
3325
  (media) => isImageFormat(media.contentType || getFileExtension(media.url))
2966
3326
  );
2967
3327
  if (secondaryMedia) {
2968
- return {
3328
+ const result = {
2969
3329
  file: secondaryMedia.url,
2970
3330
  form: secondaryMedia.contentType,
2971
3331
  title: secondaryMedia.title,
2972
3332
  isPrimary: false
2973
3333
  };
3334
+ profilePictureCache(this._gedcom, cacheKey, result);
3335
+ return result;
2974
3336
  }
3337
+ profilePictureCache(
3338
+ this._gedcom,
3339
+ cacheKey,
3340
+ void 0
3341
+ );
2975
3342
  return void 0;
2976
3343
  }
2977
3344
  link(poolId) {
@@ -3339,7 +3706,7 @@ var Indi = class extends Common {
3339
3706
  return;
3340
3707
  }
3341
3708
  const cacheKey = `${this.id}|${usedIndi.id}`;
3342
- const cache = pathCache(cacheKey);
3709
+ const cache = pathCache(this._gedcom, cacheKey);
3343
3710
  if (cache) {
3344
3711
  return cache;
3345
3712
  }
@@ -3384,7 +3751,7 @@ var Indi = class extends Common {
3384
3751
  if (breakOnNext) {
3385
3752
  return void 0;
3386
3753
  }
3387
- pathCache(cacheKey, path2);
3754
+ pathCache(this._gedcom, cacheKey, path2);
3388
3755
  return path2;
3389
3756
  }
3390
3757
  visited.append(indi);
@@ -3554,7 +3921,7 @@ var Indi = class extends Common {
3554
3921
  }
3555
3922
  getRelativesOnDegree(degree = 0) {
3556
3923
  this.id = this.id || `@I${Math.random()}@`;
3557
- const cache = relativesOnDegreeCache(this.id, degree);
3924
+ const cache = relativesOnDegreeCache(this._gedcom, this.id, degree);
3558
3925
  if (cache) {
3559
3926
  return cache;
3560
3927
  }
@@ -3562,6 +3929,7 @@ var Indi = class extends Common {
3562
3929
  const excludes = persons;
3563
3930
  if (!Math.abs(degree)) {
3564
3931
  return relativesOnDegreeCache(
3932
+ this._gedcom,
3565
3933
  this.id,
3566
3934
  degree,
3567
3935
  persons.except(this)
@@ -3572,11 +3940,11 @@ var Indi = class extends Common {
3572
3940
  excludes.merge(persons);
3573
3941
  persons = this.getRelativesOnLevel(validDegree).getRelativesOnDegree(-validDegree).copy().exclude(excludes);
3574
3942
  }
3575
- return relativesOnDegreeCache(this.id, degree, persons);
3943
+ return relativesOnDegreeCache(this._gedcom, this.id, degree, persons);
3576
3944
  }
3577
3945
  getRelativesOnLevel(level = 0, filter) {
3578
3946
  this.id = this.id || `@I${Math.random()}@`;
3579
- const cache = relativesOnLevelCache(this.id, level);
3947
+ const cache = relativesOnLevelCache(this._gedcom, this.id, level);
3580
3948
  if (cache) {
3581
3949
  return cache;
3582
3950
  }
@@ -3587,7 +3955,7 @@ var Indi = class extends Common {
3587
3955
  };
3588
3956
  let families = this.get(config.key)?.toValueList();
3589
3957
  if (!families) {
3590
- return relativesOnLevelCache(this.id, level, persons);
3958
+ return relativesOnLevelCache(this._gedcom, this.id, level, persons);
3591
3959
  }
3592
3960
  if (filter) {
3593
3961
  families = families.filter(filter);
@@ -3598,7 +3966,12 @@ var Indi = class extends Common {
3598
3966
  persons = this.toFamilies(families).getParents();
3599
3967
  }
3600
3968
  if (level >= -1 && level <= 1) {
3601
- return relativesOnLevelCache(this.id, level, persons.except(this));
3969
+ return relativesOnLevelCache(
3970
+ this._gedcom,
3971
+ this.id,
3972
+ level,
3973
+ persons.except(this)
3974
+ );
3602
3975
  }
3603
3976
  for (let i = 1; i < Math.abs(level); i++) {
3604
3977
  if (config.isAscendant) {
@@ -3607,7 +3980,12 @@ var Indi = class extends Common {
3607
3980
  persons = persons.getParents();
3608
3981
  }
3609
3982
  }
3610
- return relativesOnLevelCache(this.id, level, persons.except(this));
3983
+ return relativesOnLevelCache(
3984
+ this._gedcom,
3985
+ this.id,
3986
+ level,
3987
+ persons.except(this)
3988
+ );
3611
3989
  }
3612
3990
  getAscendants(level = 0, filter) {
3613
3991
  if (!level) {
@@ -3646,7 +4024,12 @@ var Indi = class extends Common {
3646
4024
  }
3647
4025
  currentGen++;
3648
4026
  generations[currentGen] = descentants;
3649
- relativesOnLevelCache(this.id, -currentGen, descentants);
4027
+ relativesOnLevelCache(
4028
+ this._gedcom,
4029
+ this.id,
4030
+ -currentGen,
4031
+ descentants
4032
+ );
3650
4033
  descentants && relatives.merge(descentants);
3651
4034
  }
3652
4035
  return { relatives, generations };
@@ -3679,7 +4062,7 @@ var Indi = class extends Common {
3679
4062
  }
3680
4063
  currentGen++;
3681
4064
  generations[currentGen] = parents;
3682
- relativesOnLevelCache(this.id, currentGen, parents);
4065
+ relativesOnLevelCache(this._gedcom, this.id, currentGen, parents);
3683
4066
  parents && relatives.merge(parents);
3684
4067
  }
3685
4068
  return { relatives, generations };
@@ -6107,7 +6490,7 @@ var isCommonDate = (value) => {
6107
6490
  // package.json
6108
6491
  var package_default = {
6109
6492
  name: "@treeviz/gedcom-parser",
6110
- version: "1.0.22"};
6493
+ version: "2.0.0"};
6111
6494
 
6112
6495
  // src/utils/get-product-details.ts
6113
6496
  var isDevelopment = () => {
@@ -6871,7 +7254,7 @@ var GedcomTree = {
6871
7254
  return this.parseHierarchy(content, options);
6872
7255
  },
6873
7256
  parseHierarchy: function(content, options) {
6874
- const { settings } = options ?? {};
7257
+ const { settings, filename = "" } = options ?? {};
6875
7258
  const { linkedPersons = "skip", linkingKey } = settings ?? {};
6876
7259
  const gedcom = createGedCom();
6877
7260
  gedcom.removeValue();
@@ -6906,6 +7289,25 @@ var GedcomTree = {
6906
7289
  if (lineMatch) {
6907
7290
  const lineIndent = Number(lineMatch?.groups?.indent ?? 0);
6908
7291
  const lineValue = lineMatch?.groups?.value ?? "";
7292
+ const lineType = lineMatch?.groups?.type ?? "";
7293
+ const linesAcc = acc;
7294
+ if (lineIndent === 0 && lineType === "HEAD") {
7295
+ acc.push(line);
7296
+ linesAcc._inHead = true;
7297
+ linesAcc._hasFile = false;
7298
+ return acc;
7299
+ }
7300
+ if (lineIndent === 0 && linesAcc._inHead) {
7301
+ if (filename && !linesAcc._hasFile) {
7302
+ acc.push(`1 FILE ${filename}`);
7303
+ }
7304
+ linesAcc._inHead = false;
7305
+ acc.push(line);
7306
+ return acc;
7307
+ }
7308
+ if (linesAcc._inHead && lineIndent === 1 && lineType === "FILE") {
7309
+ linesAcc._hasFile = true;
7310
+ }
6909
7311
  if (lineIndent > 0 && lineIndent > prevLineIndent && lineValue && isId(lineValue)) {
6910
7312
  const refLines = lineValue.split(/,\s*/).map((id) => line.replace(lineValue, id));
6911
7313
  if (refLines.length > 1) {
@@ -7088,4 +7490,4 @@ if (isDev) {
7088
7490
  }
7089
7491
  var parser_default = GedcomTree;
7090
7492
 
7091
- export { ACCEPTED_DATE_FORMATS, ACCEPTED_DATE_FORMATS_REGEX, parser_default as GedcomTree, PlaceType, commonDateFormatter, create, dateFormatter, extractSeparationYears, extractSplitPoints, findMatchingRangeForSplitRange, fromTuple, generateSplitRanges, getAllProp, getFamilyWith, getFileExtension, getName, getPlaceParts, getPlaces, getRawSize, getVersion, hungarianOrdinalize, implemented, inRange, isDevelopment, isImageFormat, isIntersectedRange, isRangeContained, marriageDateFormatter, nameFormatter, notImplemented, noteDateFormatter, ordinalize, parseRangeBounds, pathCache, placeTranslator, relativesCache, resetRelativesCache, setNestedGroup, splitOverlappingRanges, splitRange };
7493
+ export { ACCEPTED_DATE_FORMATS, ACCEPTED_DATE_FORMATS_REGEX, parser_default as GedcomTree, PlaceType, commonDateFormatter, create, dateFormatter, extractSeparationYears, extractSplitPoints, findMatchingRangeForSplitRange, fromTuple, generateSplitRanges, getAllProp, getFamilyWith, getFileExtension, getName, getPlaceParts, getPlaces, getRawSize, getVersion, hungarianOrdinalize, implemented, inRange, initializeCache, isDevelopment, isImageFormat, isIntersectedRange, isRangeContained, marriageDateFormatter, nameFormatter, notImplemented, noteDateFormatter, ordinalize, parseRangeBounds, pathCache, placeTranslator, profilePictureCache, relativesCache, resetRelativesCache, setNestedGroup, splitOverlappingRanges, splitRange };