@treeviz/gedcom-parser 1.0.23 → 2.0.1

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;
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;
884
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;
903
1134
  }
1135
+ if (this?.isGNO2GED()) {
1136
+ const name = this.getGNO2GEDTreeName();
1137
+ if (name) return name;
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) {
@@ -2789,7 +3037,7 @@ var Indi = class extends Common {
2789
3037
  title,
2790
3038
  url,
2791
3039
  contentType: type,
2792
- downloadName: `${this.id.replaceAll("@", "")}_${this.toNaturalName().replaceAll(" ", "-") || ""}_${(title || key.replaceAll("@", "").toString()).replaceAll(" ", "-")}`
3040
+ downloadName: `${this.id.replaceAll("@", "")}_${this.toNaturalName()?.replaceAll(" ", "-") || ""}_${(title || key.replaceAll("@", "").toString()).replaceAll(" ", "-")}`
2793
3041
  };
2794
3042
  }
2795
3043
  })
@@ -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) {
@@ -2843,7 +3092,7 @@ var Indi = class extends Common {
2843
3092
  title,
2844
3093
  url,
2845
3094
  contentType: type,
2846
- downloadName: `${this.id.replaceAll("@", "")}_${this.toNaturalName().replaceAll(" ", "-") || ""}_${(title || key.replaceAll("@", "").toString()).replaceAll(" ", "-")}`
3095
+ downloadName: `${this.id.replaceAll("@", "")}_${this.toNaturalName()?.replaceAll(" ", "-") || ""}_${(title || key.replaceAll("@", "").toString()).replaceAll(" ", "-")}`
2847
3096
  };
2848
3097
  }
2849
3098
  });
@@ -2935,6 +3184,85 @@ 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
+ const rfn = this.get("RFN")?.toValue();
3196
+ const geniId = rfn?.replace(/^geni:/, "") || "unknown";
3197
+ objeList?.forEach((obje, index) => {
3198
+ if (!obje) {
3199
+ return;
3200
+ }
3201
+ const key = `@O${index}@`;
3202
+ const isPrimary = obje?.get("_PRIM")?.toValue() === "Y";
3203
+ const url = obje?.get("FILE")?.toValue();
3204
+ const title = obje?.get("TITL")?.toValue() ?? "";
3205
+ const type = obje?.get("FORM")?.toValue() ?? "raw";
3206
+ if (url) {
3207
+ const urlMatch = url.match(/\/([^/]+)\?hash=/);
3208
+ const imgId = urlMatch?.[1] || `img-${index}-${Date.now().toString(36)}`;
3209
+ const id = `geni-${geniId}-${imgId}`;
3210
+ list[id] = {
3211
+ isPrimary,
3212
+ key,
3213
+ id,
3214
+ tree: geniId,
3215
+ imgId,
3216
+ person: this.id,
3217
+ title,
3218
+ url,
3219
+ contentType: type,
3220
+ downloadName: `${this.id.replaceAll("@", "")}_${this.toNaturalName()?.replaceAll(" ", "-") || ""}_${(title || key.replaceAll("@", "").toString()).replaceAll(" ", "-")}`
3221
+ };
3222
+ }
3223
+ });
3224
+ return list;
3225
+ }
3226
+ universalMedia() {
3227
+ const list = {};
3228
+ if (!this.id) {
3229
+ return list;
3230
+ }
3231
+ const objeList = this.get("OBJE")?.toList().copy();
3232
+ if (!objeList || objeList.length === 0) {
3233
+ return list;
3234
+ }
3235
+ const rfn = this.get("RFN")?.toValue();
3236
+ const treeId = this.getUniversalTreeId() || rfn || "universal";
3237
+ objeList.forEach((obje, index) => {
3238
+ if (!obje) {
3239
+ return;
3240
+ }
3241
+ const key = `@O${index}@`;
3242
+ obje.standardizeMedia();
3243
+ const isPrimary = obje?.get("_PRIM")?.toValue() === "Y";
3244
+ const url = obje?.get("FILE")?.toValue();
3245
+ const title = obje?.get("TITL")?.toValue() ?? "";
3246
+ const type = obje?.get("FORM")?.toValue() ?? "raw";
3247
+ if (url) {
3248
+ const imgId = `media-${index}-${url.split("/").pop()?.split("?")[0]?.substring(0, 20) || Date.now().toString(36)}`;
3249
+ const id = `${treeId}-${this.id}-${imgId}`;
3250
+ list[id] = {
3251
+ isPrimary,
3252
+ key,
3253
+ id,
3254
+ tree: treeId,
3255
+ imgId,
3256
+ person: this.id,
3257
+ title,
3258
+ url,
3259
+ contentType: type,
3260
+ downloadName: `${this.id.replaceAll("@", "")}_${this.toNaturalName()?.replaceAll(" ", "-") || ""}_${(title || key.replaceAll("@", "").toString()).replaceAll(" ", "-")}`
3261
+ };
3262
+ }
3263
+ });
3264
+ return list;
3265
+ }
2938
3266
  async multimedia(namespace) {
2939
3267
  if (this?.isAncestry()) {
2940
3268
  return await this.ancestryMedia(namespace);
@@ -2942,11 +3270,30 @@ var Indi = class extends Common {
2942
3270
  if (this?.isMyHeritage()) {
2943
3271
  return this.myheritageMedia();
2944
3272
  }
2945
- return void 0;
3273
+ if (this?.isGeni()) {
3274
+ return this.geniMedia();
3275
+ }
3276
+ return this.universalMedia();
2946
3277
  }
2947
3278
  async getProfilePicture(namespace, onlyPrimary = true) {
3279
+ if (!this.id) {
3280
+ return void 0;
3281
+ }
3282
+ const cacheKey = this.id;
3283
+ const cached = profilePictureCache(
3284
+ this._gedcom,
3285
+ cacheKey
3286
+ );
3287
+ if (cached !== void 0) {
3288
+ return cached;
3289
+ }
2948
3290
  const mediaList = await this.multimedia(namespace);
2949
3291
  if (!mediaList) {
3292
+ profilePictureCache(
3293
+ this._gedcom,
3294
+ cacheKey,
3295
+ void 0
3296
+ );
2950
3297
  return void 0;
2951
3298
  }
2952
3299
  const mediaArray = Object.values(mediaList);
@@ -2954,27 +3301,41 @@ var Indi = class extends Common {
2954
3301
  (media) => media.isPrimary && isImageFormat(media.contentType || getFileExtension(media.url))
2955
3302
  );
2956
3303
  if (primaryMedia) {
2957
- return {
3304
+ const result = {
2958
3305
  file: primaryMedia.url,
2959
3306
  form: primaryMedia.contentType,
2960
3307
  title: primaryMedia.title,
2961
3308
  isPrimary: true
2962
3309
  };
2963
- }
2964
- if (!onlyPrimary) {
3310
+ profilePictureCache(this._gedcom, cacheKey, result);
3311
+ return result;
3312
+ }
3313
+ if (onlyPrimary) {
3314
+ profilePictureCache(
3315
+ this._gedcom,
3316
+ cacheKey,
3317
+ void 0
3318
+ );
2965
3319
  return void 0;
2966
3320
  }
2967
3321
  const secondaryMedia = mediaArray.find(
2968
3322
  (media) => isImageFormat(media.contentType || getFileExtension(media.url))
2969
3323
  );
2970
3324
  if (secondaryMedia) {
2971
- return {
3325
+ const result = {
2972
3326
  file: secondaryMedia.url,
2973
3327
  form: secondaryMedia.contentType,
2974
3328
  title: secondaryMedia.title,
2975
3329
  isPrimary: false
2976
3330
  };
3331
+ profilePictureCache(this._gedcom, cacheKey, result);
3332
+ return result;
2977
3333
  }
3334
+ profilePictureCache(
3335
+ this._gedcom,
3336
+ cacheKey,
3337
+ void 0
3338
+ );
2978
3339
  return void 0;
2979
3340
  }
2980
3341
  link(poolId) {
@@ -3342,7 +3703,7 @@ var Indi = class extends Common {
3342
3703
  return;
3343
3704
  }
3344
3705
  const cacheKey = `${this.id}|${usedIndi.id}`;
3345
- const cache = pathCache(cacheKey);
3706
+ const cache = pathCache(this._gedcom, cacheKey);
3346
3707
  if (cache) {
3347
3708
  return cache;
3348
3709
  }
@@ -3387,7 +3748,7 @@ var Indi = class extends Common {
3387
3748
  if (breakOnNext) {
3388
3749
  return void 0;
3389
3750
  }
3390
- pathCache(cacheKey, path2);
3751
+ pathCache(this._gedcom, cacheKey, path2);
3391
3752
  return path2;
3392
3753
  }
3393
3754
  visited.append(indi);
@@ -3557,7 +3918,7 @@ var Indi = class extends Common {
3557
3918
  }
3558
3919
  getRelativesOnDegree(degree = 0) {
3559
3920
  this.id = this.id || `@I${Math.random()}@`;
3560
- const cache = relativesOnDegreeCache(this.id, degree);
3921
+ const cache = relativesOnDegreeCache(this._gedcom, this.id, degree);
3561
3922
  if (cache) {
3562
3923
  return cache;
3563
3924
  }
@@ -3565,6 +3926,7 @@ var Indi = class extends Common {
3565
3926
  const excludes = persons;
3566
3927
  if (!Math.abs(degree)) {
3567
3928
  return relativesOnDegreeCache(
3929
+ this._gedcom,
3568
3930
  this.id,
3569
3931
  degree,
3570
3932
  persons.except(this)
@@ -3575,11 +3937,11 @@ var Indi = class extends Common {
3575
3937
  excludes.merge(persons);
3576
3938
  persons = this.getRelativesOnLevel(validDegree).getRelativesOnDegree(-validDegree).copy().exclude(excludes);
3577
3939
  }
3578
- return relativesOnDegreeCache(this.id, degree, persons);
3940
+ return relativesOnDegreeCache(this._gedcom, this.id, degree, persons);
3579
3941
  }
3580
3942
  getRelativesOnLevel(level = 0, filter) {
3581
3943
  this.id = this.id || `@I${Math.random()}@`;
3582
- const cache = relativesOnLevelCache(this.id, level);
3944
+ const cache = relativesOnLevelCache(this._gedcom, this.id, level);
3583
3945
  if (cache) {
3584
3946
  return cache;
3585
3947
  }
@@ -3590,7 +3952,7 @@ var Indi = class extends Common {
3590
3952
  };
3591
3953
  let families = this.get(config.key)?.toValueList();
3592
3954
  if (!families) {
3593
- return relativesOnLevelCache(this.id, level, persons);
3955
+ return relativesOnLevelCache(this._gedcom, this.id, level, persons);
3594
3956
  }
3595
3957
  if (filter) {
3596
3958
  families = families.filter(filter);
@@ -3601,7 +3963,12 @@ var Indi = class extends Common {
3601
3963
  persons = this.toFamilies(families).getParents();
3602
3964
  }
3603
3965
  if (level >= -1 && level <= 1) {
3604
- return relativesOnLevelCache(this.id, level, persons.except(this));
3966
+ return relativesOnLevelCache(
3967
+ this._gedcom,
3968
+ this.id,
3969
+ level,
3970
+ persons.except(this)
3971
+ );
3605
3972
  }
3606
3973
  for (let i = 1; i < Math.abs(level); i++) {
3607
3974
  if (config.isAscendant) {
@@ -3610,7 +3977,12 @@ var Indi = class extends Common {
3610
3977
  persons = persons.getParents();
3611
3978
  }
3612
3979
  }
3613
- return relativesOnLevelCache(this.id, level, persons.except(this));
3980
+ return relativesOnLevelCache(
3981
+ this._gedcom,
3982
+ this.id,
3983
+ level,
3984
+ persons.except(this)
3985
+ );
3614
3986
  }
3615
3987
  getAscendants(level = 0, filter) {
3616
3988
  if (!level) {
@@ -3649,7 +4021,12 @@ var Indi = class extends Common {
3649
4021
  }
3650
4022
  currentGen++;
3651
4023
  generations[currentGen] = descentants;
3652
- relativesOnLevelCache(this.id, -currentGen, descentants);
4024
+ relativesOnLevelCache(
4025
+ this._gedcom,
4026
+ this.id,
4027
+ -currentGen,
4028
+ descentants
4029
+ );
3653
4030
  descentants && relatives.merge(descentants);
3654
4031
  }
3655
4032
  return { relatives, generations };
@@ -3682,7 +4059,7 @@ var Indi = class extends Common {
3682
4059
  }
3683
4060
  currentGen++;
3684
4061
  generations[currentGen] = parents;
3685
- relativesOnLevelCache(this.id, currentGen, parents);
4062
+ relativesOnLevelCache(this._gedcom, this.id, currentGen, parents);
3686
4063
  parents && relatives.merge(parents);
3687
4064
  }
3688
4065
  return { relatives, generations };
@@ -6110,7 +6487,7 @@ var isCommonDate = (value) => {
6110
6487
  // package.json
6111
6488
  var package_default = {
6112
6489
  name: "@treeviz/gedcom-parser",
6113
- version: "1.0.23"};
6490
+ version: "2.0.1"};
6114
6491
 
6115
6492
  // src/utils/get-product-details.ts
6116
6493
  var isDevelopment = () => {
@@ -6874,7 +7251,7 @@ var GedcomTree = {
6874
7251
  return this.parseHierarchy(content, options);
6875
7252
  },
6876
7253
  parseHierarchy: function(content, options) {
6877
- const { settings } = options ?? {};
7254
+ const { settings, filename = "" } = options ?? {};
6878
7255
  const { linkedPersons = "skip", linkingKey } = settings ?? {};
6879
7256
  const gedcom = createGedCom();
6880
7257
  gedcom.removeValue();
@@ -6909,6 +7286,25 @@ var GedcomTree = {
6909
7286
  if (lineMatch) {
6910
7287
  const lineIndent = Number(lineMatch?.groups?.indent ?? 0);
6911
7288
  const lineValue = lineMatch?.groups?.value ?? "";
7289
+ const lineType = lineMatch?.groups?.type ?? "";
7290
+ const linesAcc = acc;
7291
+ if (lineIndent === 0 && lineType === "HEAD") {
7292
+ acc.push(line);
7293
+ linesAcc._inHead = true;
7294
+ linesAcc._hasFile = false;
7295
+ return acc;
7296
+ }
7297
+ if (lineIndent === 0 && linesAcc._inHead) {
7298
+ if (filename && !linesAcc._hasFile) {
7299
+ acc.push(`1 FILE ${filename}`);
7300
+ }
7301
+ linesAcc._inHead = false;
7302
+ acc.push(line);
7303
+ return acc;
7304
+ }
7305
+ if (linesAcc._inHead && lineIndent === 1 && lineType === "FILE") {
7306
+ linesAcc._hasFile = true;
7307
+ }
6912
7308
  if (lineIndent > 0 && lineIndent > prevLineIndent && lineValue && isId(lineValue)) {
6913
7309
  const refLines = lineValue.split(/,\s*/).map((id) => line.replace(lineValue, id));
6914
7310
  if (refLines.length > 1) {
@@ -7091,4 +7487,4 @@ if (isDev) {
7091
7487
  }
7092
7488
  var parser_default = GedcomTree;
7093
7489
 
7094
- 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 };
7490
+ 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 };