@treeviz/gedcom-parser 1.0.23 → 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.
package/dist/index.js CHANGED
@@ -781,11 +781,30 @@ var Common = class _Common {
781
781
  const sour = get(head, "SOUR.value");
782
782
  return !!sour?.toLowerCase()?.startsWith("myheritage");
783
783
  }
784
+ /**
785
+ * Get the source type as a string (for prefixing tree IDs and names)
786
+ * Returns the detected source type or undefined if unknown
787
+ */
788
+ getSourceType() {
789
+ if (this.isAncestry()) return "Ancestry";
790
+ if (this.isMyHeritage()) return "MyHeritage";
791
+ if (this.isFamilySearch()) return "FamilySearch";
792
+ if (this.isGNO2GED()) return "GNO2GED";
793
+ if (this.isGenoPro()) return "GenoPro";
794
+ if (this.isAhnenblatt()) return "Ahnenblatt";
795
+ if (this.isGeni()) return "Geni";
796
+ return void 0;
797
+ }
784
798
  isFamilySearch() {
785
799
  const head = get(this, "HEAD") || get(this.getGedcom(), "HEAD");
786
800
  const sourName = get(head, "SOUR.NAME.value");
787
801
  return sourName === "FamilySearch API";
788
802
  }
803
+ isGNO2GED() {
804
+ const head = get(this, "HEAD") || get(this.getGedcom(), "HEAD");
805
+ const sour = get(head, "SOUR.value");
806
+ return sour === "GNO2GED";
807
+ }
789
808
  getAncestryTreeId() {
790
809
  const path = "HEAD.SOUR._TREE.RIN.value";
791
810
  return get(this, path) || get(this.getGedcom(), path);
@@ -796,11 +815,34 @@ var Common = class _Common {
796
815
  }
797
816
  getTreeId() {
798
817
  if (this?.isAncestry()) {
799
- return this.getAncestryTreeId();
818
+ const id = this.getAncestryTreeId();
819
+ if (id !== void 0) return id;
800
820
  }
801
821
  if (this?.isMyHeritage()) {
802
- return this.getMyHeritageTreeId();
822
+ const id = this.getMyHeritageTreeId();
823
+ if (id !== void 0) return id;
824
+ }
825
+ if (this?.isFamilySearch()) {
826
+ const id = this.getFamilySearchTreeId();
827
+ if (id !== void 0) return id;
828
+ }
829
+ if (this?.isGNO2GED()) {
830
+ const id = this.getGNO2GEDTreeId();
831
+ if (id !== void 0) return id;
803
832
  }
833
+ if (this?.isAhnenblatt()) {
834
+ const id = this.getAhnenblattTreeId();
835
+ if (id !== void 0) return id;
836
+ }
837
+ if (this?.isGeni()) {
838
+ const id = this.getGeniTreeId();
839
+ if (id !== void 0) return id;
840
+ }
841
+ if (this?.isGenoPro()) {
842
+ const id = this.getGenoProTreeId();
843
+ if (id !== void 0) return id;
844
+ }
845
+ return this.getUniversalTreeId();
804
846
  }
805
847
  getAncestryTreeName() {
806
848
  const path = "HEAD.SOUR._TREE.value";
@@ -813,13 +855,146 @@ var Common = class _Common {
813
855
  /Exported by MyHeritage.com from (?<tree>.+) in.+$/
814
856
  )?.groups?.tree;
815
857
  }
858
+ getFamilySearchTreeId() {
859
+ const rin = get(this, "HEAD.SOUR._TREE.RIN.value") || get(this.getGedcom(), "HEAD.SOUR._TREE.RIN.value");
860
+ if (rin) {
861
+ return rin;
862
+ }
863
+ return "familysearch";
864
+ }
865
+ getFamilySearchTreeName() {
866
+ const treeName = get(this, "HEAD.SOUR._TREE.value") || get(this.getGedcom(), "HEAD.SOUR._TREE.value");
867
+ if (treeName) {
868
+ return treeName;
869
+ }
870
+ const fileName = get(this, "HEAD.FILE.value") || get(this.getGedcom(), "HEAD.FILE.value");
871
+ return fileName || "FamilySearch Import";
872
+ }
873
+ getAhnenblattTreeId() {
874
+ const fileName = get(this, "HEAD.FILE.value") || get(this.getGedcom(), "HEAD.FILE.value");
875
+ if (fileName) {
876
+ const idMatch = fileName.match(/_(\d+)/);
877
+ if (idMatch) {
878
+ return idMatch[1];
879
+ }
880
+ }
881
+ return void 0;
882
+ }
883
+ getAhnenblattTreeName() {
884
+ const fileName = get(this, "HEAD.FILE.value") || get(this.getGedcom(), "HEAD.FILE.value");
885
+ return fileName?.replace(/\.ged$/i, "").replace(/_/g, " ");
886
+ }
887
+ getGeniTreeId() {
888
+ const fileName = get(this, "HEAD.FILE.value") || get(this.getGedcom(), "HEAD.FILE.value");
889
+ if (fileName) {
890
+ const idMatch = fileName.match(/_(\d+)/);
891
+ if (idMatch) {
892
+ return idMatch[1];
893
+ }
894
+ }
895
+ return void 0;
896
+ }
897
+ getGeniTreeName() {
898
+ const fileName = get(this, "HEAD.FILE.value") || get(this.getGedcom(), "HEAD.FILE.value");
899
+ return fileName?.replace(/\.ged$/i, "").replace(/_/g, " ");
900
+ }
901
+ getGenoProTreeId() {
902
+ const fileName = get(this, "HEAD.FILE.value") || get(this.getGedcom(), "HEAD.FILE.value");
903
+ if (fileName) {
904
+ const idMatch = fileName.match(/_(\d+)/);
905
+ if (idMatch) {
906
+ return idMatch[1];
907
+ }
908
+ }
909
+ return void 0;
910
+ }
911
+ getGenoProTreeName() {
912
+ const fileName = get(this, "HEAD.FILE.value") || get(this.getGedcom(), "HEAD.FILE.value");
913
+ return fileName?.replace(/\.ged$/i, "").replace(/_/g, " ");
914
+ }
915
+ getGNO2GEDTreeId() {
916
+ const rin = get(this, "HEAD._TREE.RIN.value") || get(this.getGedcom(), "HEAD._TREE.RIN.value");
917
+ if (rin) {
918
+ return rin;
919
+ }
920
+ return `gno_${this._gedcom?.refcount || "unknown"}`;
921
+ }
922
+ getGNO2GEDTreeName() {
923
+ const treeName = get(this, "HEAD._TREE.value") || get(this.getGedcom(), "HEAD._TREE.value");
924
+ if (treeName) {
925
+ return treeName;
926
+ }
927
+ const fileName = get(this, "HEAD.FILE.value") || get(this.getGedcom(), "HEAD.FILE.value");
928
+ return fileName || "GNO2GED Export";
929
+ }
930
+ /**
931
+ * Universal tree ID getter for unknown/unrecognized GEDCOM sources
932
+ * Tries to extract an ID from various common locations
933
+ */
934
+ getUniversalTreeId() {
935
+ const sourceType = this.getSourceType();
936
+ const prefix = sourceType ? sourceType.toLowerCase() : "tree";
937
+ const fileName = get(this, "HEAD.FILE.value") || get(this.getGedcom(), "HEAD.FILE.value");
938
+ if (fileName) {
939
+ const idMatch = fileName.match(/_(\d+)/);
940
+ if (idMatch) {
941
+ return `${prefix}_${idMatch[1]}`;
942
+ }
943
+ }
944
+ return `${prefix}_${this._gedcom?.refcount || "unknown"}`;
945
+ }
946
+ /**
947
+ * Universal tree name getter for unknown/unrecognized GEDCOM sources
948
+ * Tries to extract a name from various common locations
949
+ */
950
+ getUniversalTreeName() {
951
+ const sourceType = this.getSourceType();
952
+ const prefix = sourceType ? `${sourceType}-` : "";
953
+ const fileName = get(this, "HEAD.FILE.value") || get(this.getGedcom(), "HEAD.FILE.value");
954
+ if (fileName) {
955
+ const cleanName = fileName.replace(/\.ged$/i, "").replace(/_/g, " ");
956
+ return `${prefix}${cleanName}`;
957
+ }
958
+ const sourName = get(this, "HEAD.SOUR.NAME.value") || get(this.getGedcom(), "HEAD.SOUR.NAME.value");
959
+ if (sourName) {
960
+ return `${prefix}${sourName}`;
961
+ }
962
+ const sourValue = get(this, "HEAD.SOUR.value") || get(this.getGedcom(), "HEAD.SOUR.value");
963
+ if (sourValue) {
964
+ return `${prefix}${sourValue}`;
965
+ }
966
+ return `${prefix}Unknown Tree`;
967
+ }
816
968
  getTreeName() {
817
969
  if (this?.isAncestry()) {
818
- return this.getAncestryTreeName();
970
+ const name = this.getAncestryTreeName();
971
+ if (name) return name;
819
972
  }
820
973
  if (this?.isMyHeritage()) {
821
- return this.getMyHeritageTreeName();
974
+ const name = this.getMyHeritageTreeName();
975
+ if (name) return name;
822
976
  }
977
+ if (this?.isFamilySearch()) {
978
+ const name = this.getFamilySearchTreeName();
979
+ if (name) return name;
980
+ }
981
+ if (this?.isGNO2GED()) {
982
+ const name = this.getGNO2GEDTreeName();
983
+ if (name) return name;
984
+ }
985
+ if (this?.isAhnenblatt()) {
986
+ const name = this.getAhnenblattTreeName();
987
+ if (name) return name;
988
+ }
989
+ if (this?.isGeni()) {
990
+ const name = this.getGeniTreeName();
991
+ if (name) return name;
992
+ }
993
+ if (this?.isGenoPro()) {
994
+ const name = this.getGenoProTreeName();
995
+ if (name) return name;
996
+ }
997
+ return this.getUniversalTreeName();
823
998
  }
824
999
  };
825
1000
  var createProxy = (target) => {
@@ -1019,70 +1194,143 @@ var SPOUSE = {
1019
1194
  var UNKOWN = {
1020
1195
  PART: "unknown" /* UNKOWN */
1021
1196
  };
1197
+ var getGedcomId = (gedcom) => {
1198
+ if (!gedcom) {
1199
+ return "unknown";
1200
+ }
1201
+ const treeId = gedcom.getTreeId?.() || "";
1202
+ const treeName = gedcom.getTreeName?.() || "";
1203
+ const sanitizedName = treeName.toLowerCase().replace(/[^a-z0-9]+/g, "_").replace(/^_+|_+$/g, "");
1204
+ if (treeId && sanitizedName) {
1205
+ return `${treeId}_${sanitizedName}`;
1206
+ } else if (treeId) {
1207
+ return treeId;
1208
+ } else if (sanitizedName) {
1209
+ return sanitizedName;
1210
+ }
1211
+ return `gedcom_${gedcom.refcount}`;
1212
+ };
1022
1213
  var caches = {
1023
1214
  pathCache: {},
1024
1215
  relativesOnDegreeCache: {},
1025
- relativesOnLevelCache: {}
1026
- };
1027
- var getInstance = getCacheManagerFactory();
1028
- var cacheDbs = {
1029
- pathCache: getInstance("ftv", "Main", "path", true),
1030
- relativesOnDegreeCache: getInstance(
1031
- "ftv",
1032
- "Main",
1033
- "path",
1034
- true
1035
- ),
1036
- relativesOnLevelCache: getInstance(
1037
- "ftv",
1038
- "Main",
1039
- "path",
1040
- true
1041
- )
1042
- };
1043
- ({
1216
+ relativesOnLevelCache: {},
1217
+ profilePictureCache: {}
1218
+ };
1219
+ var cacheDbs;
1220
+ var getCacheDbs = () => {
1221
+ if (!cacheDbs) {
1222
+ const getInstance = getCacheManagerFactory();
1223
+ cacheDbs = {
1224
+ pathCache: getInstance(
1225
+ "ftv",
1226
+ "Main",
1227
+ "path",
1228
+ true
1229
+ ),
1230
+ relativesOnDegreeCache: getInstance("ftv", "Main", "path", true),
1231
+ relativesOnLevelCache: getInstance(
1232
+ "ftv",
1233
+ "Main",
1234
+ "path",
1235
+ true
1236
+ ),
1237
+ profilePictureCache: getInstance(
1238
+ "ftv",
1239
+ "Main",
1240
+ "images",
1241
+ false
1242
+ )
1243
+ };
1244
+ }
1245
+ return cacheDbs;
1246
+ };
1247
+ var storeCache = {
1248
+ // NOTE: pathCache, relativesOnLevelCache, and relativesOnDegreeCache are intentionally
1249
+ // kept in memory only. These debounced functions exist to satisfy the type system
1250
+ // but are never called.
1044
1251
  pathCache: debounce((value) => {
1045
1252
  if (value) {
1046
- cacheDbs.pathCache.setItem(value);
1253
+ getCacheDbs().pathCache.setItem(value);
1047
1254
  }
1048
1255
  }, 50),
1049
1256
  relativesOnLevelCache: debounce((value) => {
1050
1257
  if (value) {
1051
- cacheDbs.relativesOnLevelCache.setItem(value);
1258
+ getCacheDbs().relativesOnLevelCache.setItem(value);
1052
1259
  }
1053
1260
  }, 50),
1054
1261
  relativesOnDegreeCache: debounce((value) => {
1055
1262
  if (value) {
1056
- cacheDbs.relativesOnDegreeCache.setItem(value);
1263
+ getCacheDbs().relativesOnDegreeCache.setItem(value);
1057
1264
  }
1058
- }, 50)
1059
- });
1265
+ }, 50),
1266
+ // profilePictureCache IS persisted to IndexedDB
1267
+ profilePictureCache: debounce((value) => {
1268
+ if (value) {
1269
+ getCacheDbs().profilePictureCache.setItem(value);
1270
+ }
1271
+ }, 100)
1272
+ };
1273
+ var cacheInitialized = false;
1274
+ var initializeCache = async () => {
1275
+ if (cacheInitialized) {
1276
+ return;
1277
+ }
1278
+ cacheInitialized = true;
1279
+ try {
1280
+ const profilePictureData = await getCacheDbs().profilePictureCache.getItem();
1281
+ if (profilePictureData) {
1282
+ caches.profilePictureCache = profilePictureData;
1283
+ }
1284
+ } catch (_error) {
1285
+ }
1286
+ };
1060
1287
  var resetRelativesCache = () => {
1061
1288
  caches.relativesOnDegreeCache = {};
1062
1289
  caches.relativesOnLevelCache = {};
1063
1290
  };
1064
- var relativesCache = (cacheKey) => (key, subKey, value) => {
1065
- if (!caches[cacheKey]) {
1291
+ var relativesCache = (cacheKey) => (gedcom, key, subKey, value) => {
1292
+ const gedcomId = getGedcomId(gedcom);
1293
+ const fullKey = `${gedcomId}:${key}`;
1294
+ const cache = caches[cacheKey];
1295
+ if (!cache) {
1066
1296
  caches[cacheKey] = {};
1067
1297
  }
1068
- if (value && caches[cacheKey]) {
1069
- if (!caches[cacheKey][key]) {
1070
- caches[cacheKey][key] = {};
1298
+ if (value) {
1299
+ const typedCache2 = caches[cacheKey];
1300
+ if (!typedCache2[fullKey]) {
1301
+ typedCache2[fullKey] = {};
1071
1302
  }
1072
- caches[cacheKey][key][subKey] = value;
1073
- return caches[cacheKey][key][subKey];
1303
+ typedCache2[fullKey][subKey] = value;
1304
+ return typedCache2[fullKey][subKey];
1074
1305
  }
1075
- return caches[cacheKey]?.[key]?.[subKey];
1306
+ const typedCache = caches[cacheKey];
1307
+ return typedCache?.[fullKey]?.[subKey];
1076
1308
  };
1077
- var pathCache = (key, value) => {
1309
+ var pathCache = (gedcom, key, value) => {
1310
+ const gedcomId = getGedcomId(gedcom);
1311
+ const fullKey = `${gedcomId}:${key}`;
1078
1312
  if (!caches.pathCache) {
1079
1313
  caches.pathCache = {};
1080
1314
  }
1081
1315
  if (value && caches.pathCache) {
1082
- caches.pathCache[key] = value;
1083
- return caches.pathCache[key];
1316
+ caches.pathCache[fullKey] = value;
1317
+ return caches.pathCache[fullKey];
1318
+ }
1319
+ return caches.pathCache?.[fullKey];
1320
+ };
1321
+ var profilePictureCache = (gedcom, key, value) => {
1322
+ const gedcomId = getGedcomId(gedcom);
1323
+ const fullKey = `${gedcomId}:${key}`;
1324
+ if (!caches.profilePictureCache) {
1325
+ caches.profilePictureCache = {};
1326
+ }
1327
+ if (value && caches.profilePictureCache) {
1328
+ caches.profilePictureCache[fullKey] = value;
1329
+ storeCache.profilePictureCache(caches.profilePictureCache);
1330
+ return caches.profilePictureCache[fullKey];
1084
1331
  }
1085
- return caches.pathCache?.[key];
1332
+ const cached = caches.profilePictureCache?.[fullKey];
1333
+ return cached;
1086
1334
  };
1087
1335
 
1088
1336
  // src/utils/get-all-prop.ts
@@ -2027,7 +2275,7 @@ var Indi = class extends Common {
2027
2275
  }
2028
2276
  async ancestryMedia(namespace) {
2029
2277
  const list = {};
2030
- const objeList = this.get("OBJE")?.toList();
2278
+ const objeList = this.get("OBJE")?.toList().copy();
2031
2279
  const www = this._gedcom?.HEAD?.SOUR?.CORP?.WWW?.value;
2032
2280
  const tree = this.getAncestryTreeId();
2033
2281
  if (objeList) {
@@ -2101,11 +2349,12 @@ var Indi = class extends Common {
2101
2349
  if (!tree) {
2102
2350
  return;
2103
2351
  }
2104
- const objeList = this.get("OBJE")?.toList();
2105
- const birthObj = this.get("BIRT.OBJE")?.toList();
2106
- const deathObj = this.get("DEAT.OBJE")?.toList();
2352
+ const objeList = this.get("OBJE")?.toList().copy();
2353
+ const birthObj = this.get("BIRT.OBJE")?.toList().copy();
2354
+ const deathObj = this.get("DEAT.OBJE")?.toList().copy();
2355
+ objeList?.merge(birthObj).merge(deathObj);
2107
2356
  (this.get("FAMS")?.toValueList().values() ?? []).concat(this.get("FAMC")?.toValueList().values() ?? []).forEach((fam) => {
2108
- objeList?.merge(birthObj).merge(deathObj).merge(fam?.get("MARR.OBJE"));
2357
+ objeList.merge(fam?.get("MARR.OBJE"));
2109
2358
  });
2110
2359
  objeList?.forEach((o, index) => {
2111
2360
  if (!o) {
@@ -2223,6 +2472,88 @@ var Indi = class extends Common {
2223
2472
  };
2224
2473
  });
2225
2474
  }
2475
+ geniMedia() {
2476
+ const list = {};
2477
+ const objeList = this.get("OBJE")?.toList().copy();
2478
+ const sourList = this.get("SOUR")?.toList().copy();
2479
+ sourList?.forEach((sour) => {
2480
+ const sourObje = sour?.get("OBJE")?.toList();
2481
+ objeList.merge(sourObje);
2482
+ });
2483
+ if (!objeList || objeList.length === 0) {
2484
+ return void 0;
2485
+ }
2486
+ const rfn = this.get("RFN")?.toValue();
2487
+ const geniId = rfn?.replace(/^geni:/, "") || "unknown";
2488
+ objeList.forEach((obje, index) => {
2489
+ if (!obje) {
2490
+ return;
2491
+ }
2492
+ const key = `@O${index}@`;
2493
+ const isPrimary = obje?.get("_PRIM")?.toValue() === "Y";
2494
+ const url = obje?.get("FILE")?.toValue();
2495
+ const title = obje?.get("TITL")?.toValue() ?? "";
2496
+ const type = obje?.get("FORM")?.toValue() ?? "raw";
2497
+ if (url) {
2498
+ const urlMatch = url.match(/\/([^/]+)\?hash=/);
2499
+ const imgId = urlMatch?.[1] || `img-${index}-${Date.now().toString(36)}`;
2500
+ const id = `geni-${geniId}-${imgId}`;
2501
+ list[id] = {
2502
+ isPrimary,
2503
+ key,
2504
+ id,
2505
+ tree: geniId,
2506
+ imgId,
2507
+ person: this.id,
2508
+ title,
2509
+ url,
2510
+ contentType: type,
2511
+ downloadName: `${this.id.replaceAll("@", "")}_${this.toNaturalName()?.replaceAll(" ", "-") || ""}_${(title || key.replaceAll("@", "").toString()).replaceAll(" ", "-")}`
2512
+ };
2513
+ }
2514
+ });
2515
+ return list;
2516
+ }
2517
+ universalMedia() {
2518
+ const list = {};
2519
+ if (!this.id) {
2520
+ return list;
2521
+ }
2522
+ const objeList = this.get("OBJE")?.toList().copy();
2523
+ if (!objeList || objeList.length === 0) {
2524
+ return list;
2525
+ }
2526
+ const rfn = this.get("RFN")?.toValue();
2527
+ const treeId = rfn || "universal";
2528
+ objeList.forEach((obje, index) => {
2529
+ if (!obje) {
2530
+ return;
2531
+ }
2532
+ const key = `@O${index}@`;
2533
+ obje.standardizeMedia();
2534
+ const isPrimary = obje?.get("_PRIM")?.toValue() === "Y";
2535
+ const url = obje?.get("FILE")?.toValue();
2536
+ const title = obje?.get("TITL")?.toValue() ?? "";
2537
+ const type = obje?.get("FORM")?.toValue() ?? "raw";
2538
+ if (url) {
2539
+ const imgId = `media-${index}-${url.split("/").pop()?.split("?")[0]?.substring(0, 20) || Date.now().toString(36)}`;
2540
+ const id = `${treeId}-${this.id}-${imgId}`;
2541
+ list[id] = {
2542
+ isPrimary,
2543
+ key,
2544
+ id,
2545
+ tree: treeId,
2546
+ imgId,
2547
+ person: this.id,
2548
+ title,
2549
+ url,
2550
+ contentType: type,
2551
+ downloadName: `${this.id.replaceAll("@", "")}_${this.toNaturalName()?.replaceAll(" ", "-") || ""}_${(title || key.replaceAll("@", "").toString()).replaceAll(" ", "-")}`
2552
+ };
2553
+ }
2554
+ });
2555
+ return list;
2556
+ }
2226
2557
  async multimedia(namespace) {
2227
2558
  if (this?.isAncestry()) {
2228
2559
  return await this.ancestryMedia(namespace);
@@ -2230,11 +2561,30 @@ var Indi = class extends Common {
2230
2561
  if (this?.isMyHeritage()) {
2231
2562
  return this.myheritageMedia();
2232
2563
  }
2233
- return void 0;
2564
+ if (this?.isGeni()) {
2565
+ return this.geniMedia();
2566
+ }
2567
+ return this.universalMedia();
2234
2568
  }
2235
2569
  async getProfilePicture(namespace, onlyPrimary = true) {
2570
+ if (!this.id) {
2571
+ return void 0;
2572
+ }
2573
+ const cacheKey = this.id;
2574
+ const cached = profilePictureCache(
2575
+ this._gedcom,
2576
+ cacheKey
2577
+ );
2578
+ if (cached !== void 0) {
2579
+ return cached;
2580
+ }
2236
2581
  const mediaList = await this.multimedia(namespace);
2237
2582
  if (!mediaList) {
2583
+ profilePictureCache(
2584
+ this._gedcom,
2585
+ cacheKey,
2586
+ void 0
2587
+ );
2238
2588
  return void 0;
2239
2589
  }
2240
2590
  const mediaArray = Object.values(mediaList);
@@ -2242,27 +2592,41 @@ var Indi = class extends Common {
2242
2592
  (media) => media.isPrimary && isImageFormat(media.contentType || getFileExtension(media.url))
2243
2593
  );
2244
2594
  if (primaryMedia) {
2245
- return {
2595
+ const result = {
2246
2596
  file: primaryMedia.url,
2247
2597
  form: primaryMedia.contentType,
2248
2598
  title: primaryMedia.title,
2249
2599
  isPrimary: true
2250
2600
  };
2251
- }
2252
- if (!onlyPrimary) {
2601
+ profilePictureCache(this._gedcom, cacheKey, result);
2602
+ return result;
2603
+ }
2604
+ if (onlyPrimary) {
2605
+ profilePictureCache(
2606
+ this._gedcom,
2607
+ cacheKey,
2608
+ void 0
2609
+ );
2253
2610
  return void 0;
2254
2611
  }
2255
2612
  const secondaryMedia = mediaArray.find(
2256
2613
  (media) => isImageFormat(media.contentType || getFileExtension(media.url))
2257
2614
  );
2258
2615
  if (secondaryMedia) {
2259
- return {
2616
+ const result = {
2260
2617
  file: secondaryMedia.url,
2261
2618
  form: secondaryMedia.contentType,
2262
2619
  title: secondaryMedia.title,
2263
2620
  isPrimary: false
2264
2621
  };
2622
+ profilePictureCache(this._gedcom, cacheKey, result);
2623
+ return result;
2265
2624
  }
2625
+ profilePictureCache(
2626
+ this._gedcom,
2627
+ cacheKey,
2628
+ void 0
2629
+ );
2266
2630
  return void 0;
2267
2631
  }
2268
2632
  link(poolId) {
@@ -2630,7 +2994,7 @@ var Indi = class extends Common {
2630
2994
  return;
2631
2995
  }
2632
2996
  const cacheKey = `${this.id}|${usedIndi.id}`;
2633
- const cache = pathCache(cacheKey);
2997
+ const cache = pathCache(this._gedcom, cacheKey);
2634
2998
  if (cache) {
2635
2999
  return cache;
2636
3000
  }
@@ -2675,7 +3039,7 @@ var Indi = class extends Common {
2675
3039
  if (breakOnNext) {
2676
3040
  return void 0;
2677
3041
  }
2678
- pathCache(cacheKey, path2);
3042
+ pathCache(this._gedcom, cacheKey, path2);
2679
3043
  return path2;
2680
3044
  }
2681
3045
  visited.append(indi);
@@ -2845,7 +3209,7 @@ var Indi = class extends Common {
2845
3209
  }
2846
3210
  getRelativesOnDegree(degree = 0) {
2847
3211
  this.id = this.id || `@I${Math.random()}@`;
2848
- const cache = relativesOnDegreeCache(this.id, degree);
3212
+ const cache = relativesOnDegreeCache(this._gedcom, this.id, degree);
2849
3213
  if (cache) {
2850
3214
  return cache;
2851
3215
  }
@@ -2853,6 +3217,7 @@ var Indi = class extends Common {
2853
3217
  const excludes = persons;
2854
3218
  if (!Math.abs(degree)) {
2855
3219
  return relativesOnDegreeCache(
3220
+ this._gedcom,
2856
3221
  this.id,
2857
3222
  degree,
2858
3223
  persons.except(this)
@@ -2863,11 +3228,11 @@ var Indi = class extends Common {
2863
3228
  excludes.merge(persons);
2864
3229
  persons = this.getRelativesOnLevel(validDegree).getRelativesOnDegree(-validDegree).copy().exclude(excludes);
2865
3230
  }
2866
- return relativesOnDegreeCache(this.id, degree, persons);
3231
+ return relativesOnDegreeCache(this._gedcom, this.id, degree, persons);
2867
3232
  }
2868
3233
  getRelativesOnLevel(level = 0, filter) {
2869
3234
  this.id = this.id || `@I${Math.random()}@`;
2870
- const cache = relativesOnLevelCache(this.id, level);
3235
+ const cache = relativesOnLevelCache(this._gedcom, this.id, level);
2871
3236
  if (cache) {
2872
3237
  return cache;
2873
3238
  }
@@ -2878,7 +3243,7 @@ var Indi = class extends Common {
2878
3243
  };
2879
3244
  let families = this.get(config.key)?.toValueList();
2880
3245
  if (!families) {
2881
- return relativesOnLevelCache(this.id, level, persons);
3246
+ return relativesOnLevelCache(this._gedcom, this.id, level, persons);
2882
3247
  }
2883
3248
  if (filter) {
2884
3249
  families = families.filter(filter);
@@ -2889,7 +3254,12 @@ var Indi = class extends Common {
2889
3254
  persons = this.toFamilies(families).getParents();
2890
3255
  }
2891
3256
  if (level >= -1 && level <= 1) {
2892
- return relativesOnLevelCache(this.id, level, persons.except(this));
3257
+ return relativesOnLevelCache(
3258
+ this._gedcom,
3259
+ this.id,
3260
+ level,
3261
+ persons.except(this)
3262
+ );
2893
3263
  }
2894
3264
  for (let i = 1; i < Math.abs(level); i++) {
2895
3265
  if (config.isAscendant) {
@@ -2898,7 +3268,12 @@ var Indi = class extends Common {
2898
3268
  persons = persons.getParents();
2899
3269
  }
2900
3270
  }
2901
- return relativesOnLevelCache(this.id, level, persons.except(this));
3271
+ return relativesOnLevelCache(
3272
+ this._gedcom,
3273
+ this.id,
3274
+ level,
3275
+ persons.except(this)
3276
+ );
2902
3277
  }
2903
3278
  getAscendants(level = 0, filter) {
2904
3279
  if (!level) {
@@ -2937,7 +3312,12 @@ var Indi = class extends Common {
2937
3312
  }
2938
3313
  currentGen++;
2939
3314
  generations[currentGen] = descentants;
2940
- relativesOnLevelCache(this.id, -currentGen, descentants);
3315
+ relativesOnLevelCache(
3316
+ this._gedcom,
3317
+ this.id,
3318
+ -currentGen,
3319
+ descentants
3320
+ );
2941
3321
  descentants && relatives.merge(descentants);
2942
3322
  }
2943
3323
  return { relatives, generations };
@@ -2970,7 +3350,7 @@ var Indi = class extends Common {
2970
3350
  }
2971
3351
  currentGen++;
2972
3352
  generations[currentGen] = parents;
2973
- relativesOnLevelCache(this.id, currentGen, parents);
3353
+ relativesOnLevelCache(this._gedcom, this.id, currentGen, parents);
2974
3354
  parents && relatives.merge(parents);
2975
3355
  }
2976
3356
  return { relatives, generations };
@@ -6274,7 +6654,7 @@ var Families = class _Families extends List {
6274
6654
  // package.json
6275
6655
  var package_default = {
6276
6656
  name: "@treeviz/gedcom-parser",
6277
- version: "1.0.23"};
6657
+ version: "2.0.0"};
6278
6658
 
6279
6659
  // src/utils/get-product-details.ts
6280
6660
  var isDevelopment = () => {
@@ -7301,7 +7681,7 @@ var GedcomTree = {
7301
7681
  return this.parseHierarchy(content, options);
7302
7682
  },
7303
7683
  parseHierarchy: function(content, options) {
7304
- const { settings } = options ?? {};
7684
+ const { settings, filename = "" } = options ?? {};
7305
7685
  const { linkedPersons = "skip", linkingKey } = settings ?? {};
7306
7686
  const gedcom = createGedCom();
7307
7687
  gedcom.removeValue();
@@ -7336,6 +7716,25 @@ var GedcomTree = {
7336
7716
  if (lineMatch) {
7337
7717
  const lineIndent = Number(lineMatch?.groups?.indent ?? 0);
7338
7718
  const lineValue = lineMatch?.groups?.value ?? "";
7719
+ const lineType = lineMatch?.groups?.type ?? "";
7720
+ const linesAcc = acc;
7721
+ if (lineIndent === 0 && lineType === "HEAD") {
7722
+ acc.push(line);
7723
+ linesAcc._inHead = true;
7724
+ linesAcc._hasFile = false;
7725
+ return acc;
7726
+ }
7727
+ if (lineIndent === 0 && linesAcc._inHead) {
7728
+ if (filename && !linesAcc._hasFile) {
7729
+ acc.push(`1 FILE ${filename}`);
7730
+ }
7731
+ linesAcc._inHead = false;
7732
+ acc.push(line);
7733
+ return acc;
7734
+ }
7735
+ if (linesAcc._inHead && lineIndent === 1 && lineType === "FILE") {
7736
+ linesAcc._hasFile = true;
7737
+ }
7339
7738
  if (lineIndent > 0 && lineIndent > prevLineIndent && lineValue && isId(lineValue)) {
7340
7739
  const refLines = lineValue.split(/,\s*/).map((id) => line.replace(lineValue, id));
7341
7740
  if (refLines.length > 1) {
@@ -7518,4 +7917,4 @@ if (isDev) {
7518
7917
  }
7519
7918
  var parser_default = GedcomTree;
7520
7919
 
7521
- export { ACCEPTED_DATE_FORMATS, ACCEPTED_DATE_FORMATS_REGEX, ADOPTED, BIOLOGICAL, BIRTH, BIRTH_ASC, BIRTH_DESC, Common, CommonDate, CommonName, CommonNote, CustomTags, DATE_ASC, DATE_DESC, DEATH_ASC, DEATH_DESC, DEFAULT, EVERY, Existed, FEMALE, FOSTER, FRIEND, Fam, Families, GedCom, parser_default as GedcomTree, ID_GETTER_REG, ID_REG, ID_SPLIT_REG, Indi, Individuals, KinshipTranslator, KinshipTranslatorBasic, KinshipTranslatorDe as KinshipTranslatorDE, KinshipTranslatorEn as KinshipTranslatorEN, KinshipTranslatorEs as KinshipTranslatorES, KinshipTranslatorFr as KinshipTranslatorFR, KinshipTranslatorHU, LINE_REG, List, MALE, MAX_FILE_SIZE_TO_SYNC, OTHER, Obje, Objects, PARTNER, PartnerType, PlaceType, REF_LINE_REG, Range, RelationType, Repo, Repositories, SEALING, SINGLE, SPOUSE, STEP, Sour, Sources, Subm, Submitters, UNKOWN, commonDateFormatter, create, createCommon, createCommonDate, createCommonName, createCommonNote, createFam, createGedCom, createIndi, createObje, createProxy, createRepo, createSour, createSubm, dateFormatter, parser_default as default, extractSeparationYears, extractSplitPoints, findMatchingRangeForSplitRange, fromTuple, generateSplitRanges, getAllProp, getBirthAsc, getCacheManagerFactory, getDateLocale, getFamilyWith, getI18n, getKinshipTranslatorClass, getListTag, getMarriageAsc, getMarriageAscAndBirth, getMarriageAscAndChildBirth, getName, getNameAsc, getNameAscAndBirth, getNameDesc, getPlaceParserProvider, getPlaceParts, getPlaceTranslatorProvider, getPlaces, getRawSize, getValidKey, getValidKeys, getValidTag, getVersion, hungarianOrdinalize, i18n, idGetter, implemented, inRange, isCommonDate, isDevelopment, isGedcomString, isId, isIntersectedRange, isOnlyMainProp, isRangeContained, isValidKey, marriageDateFormatter, mergeGedcoms, nameFormatter, notImplemented, noteDateFormatter, ordinalize, parseRangeBounds, pathCache, placeTranslator, relativesCache, resetCacheManagerFactory, resetDateLocaleProvider, resetI18nProvider, resetKinshipTranslatorClass, resetPlaceParserProvider, resetPlaceTranslatorProvider, resetRelativesCache, setCacheManagerFactory, setDateLocaleProvider, setI18nProvider, setKinshipTranslatorClass, setNestedGroup, setPlaceParserProvider, setPlaceTranslatorProvider, splitOverlappingRanges, splitRange, translators_exports as translators, validateGedcomContent };
7920
+ export { ACCEPTED_DATE_FORMATS, ACCEPTED_DATE_FORMATS_REGEX, ADOPTED, BIOLOGICAL, BIRTH, BIRTH_ASC, BIRTH_DESC, Common, CommonDate, CommonName, CommonNote, CustomTags, DATE_ASC, DATE_DESC, DEATH_ASC, DEATH_DESC, DEFAULT, EVERY, Existed, FEMALE, FOSTER, FRIEND, Fam, Families, GedCom, parser_default as GedcomTree, ID_GETTER_REG, ID_REG, ID_SPLIT_REG, Indi, Individuals, KinshipTranslator, KinshipTranslatorBasic, KinshipTranslatorDe as KinshipTranslatorDE, KinshipTranslatorEn as KinshipTranslatorEN, KinshipTranslatorEs as KinshipTranslatorES, KinshipTranslatorFr as KinshipTranslatorFR, KinshipTranslatorHU, LINE_REG, List, MALE, MAX_FILE_SIZE_TO_SYNC, OTHER, Obje, Objects, PARTNER, PartnerType, PlaceType, REF_LINE_REG, Range, RelationType, Repo, Repositories, SEALING, SINGLE, SPOUSE, STEP, Sour, Sources, Subm, Submitters, UNKOWN, commonDateFormatter, create, createCommon, createCommonDate, createCommonName, createCommonNote, createFam, createGedCom, createIndi, createObje, createProxy, createRepo, createSour, createSubm, dateFormatter, parser_default as default, extractSeparationYears, extractSplitPoints, findMatchingRangeForSplitRange, fromTuple, generateSplitRanges, getAllProp, getBirthAsc, getCacheManagerFactory, getDateLocale, getFamilyWith, getI18n, getKinshipTranslatorClass, getListTag, getMarriageAsc, getMarriageAscAndBirth, getMarriageAscAndChildBirth, getName, getNameAsc, getNameAscAndBirth, getNameDesc, getPlaceParserProvider, getPlaceParts, getPlaceTranslatorProvider, getPlaces, getRawSize, getValidKey, getValidKeys, getValidTag, getVersion, hungarianOrdinalize, i18n, idGetter, implemented, inRange, initializeCache, isCommonDate, isDevelopment, isGedcomString, isId, isIntersectedRange, isOnlyMainProp, isRangeContained, isValidKey, marriageDateFormatter, mergeGedcoms, nameFormatter, notImplemented, noteDateFormatter, ordinalize, parseRangeBounds, pathCache, placeTranslator, profilePictureCache, relativesCache, resetCacheManagerFactory, resetDateLocaleProvider, resetI18nProvider, resetKinshipTranslatorClass, resetPlaceParserProvider, resetPlaceTranslatorProvider, resetRelativesCache, setCacheManagerFactory, setDateLocaleProvider, setI18nProvider, setKinshipTranslatorClass, setNestedGroup, setPlaceParserProvider, setPlaceTranslatorProvider, splitOverlappingRanges, splitRange, translators_exports as translators, validateGedcomContent };