@treeviz/gedcom-parser 1.0.20 → 1.0.22

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.
@@ -2882,6 +2882,27 @@ var getPlaces = (common, type = ["ALL" /* All */], maxLevel = 1, level = 0, main
2882
2882
  };
2883
2883
  var implemented = (type, ...args) => {
2884
2884
  };
2885
+
2886
+ // src/utils/media-utils.ts
2887
+ var getFileExtension = (filename) => {
2888
+ const match = filename.match(/\.([^.]+)$/);
2889
+ return match ? match[1] : "";
2890
+ };
2891
+ var isImageFormat = (format2) => {
2892
+ if (!format2) return false;
2893
+ const imageFormats = [
2894
+ "jpg",
2895
+ "jpeg",
2896
+ "png",
2897
+ "gif",
2898
+ "bmp",
2899
+ "webp",
2900
+ "svg",
2901
+ "tiff",
2902
+ "tif"
2903
+ ];
2904
+ return imageFormats.includes(format2.toLowerCase());
2905
+ };
2885
2906
  var uniqueItemsCache = /* @__PURE__ */ new WeakMap();
2886
2907
  var setNestedGroup = (obj, key, value, uniqueCounting = true) => {
2887
2908
  const parts = Array.isArray(key) ? key : key.split(/,\s*/);
@@ -4092,54 +4113,62 @@ var Indi = class extends Common {
4092
4113
  }
4093
4114
  async ancestryMedia(namespace) {
4094
4115
  const list = {};
4095
- const objIds = this.get("OBJE")?.toValueList().keys() ?? [];
4116
+ const objeList = this.get("OBJE")?.toList();
4096
4117
  const www = this._gedcom?.HEAD?.SOUR?.CORP?.WWW?.value;
4097
4118
  const tree = this.getAncestryTreeId();
4098
- await Promise.all(
4099
- objIds.map(async (objId) => {
4100
- const key = objId;
4101
- const obje = this._gedcom?.obje(key)?.standardizeMedia(namespace, true, (ns, iId) => {
4102
- return ns && iId ? `https://mediasvc.ancestry.com/v2/image/namespaces/${ns}/media/${iId}?client=trees-mediaservice&imageQuality=hq` : void 0;
4103
- });
4104
- const media = obje?.RIN?.value;
4105
- const clone = obje?.get("_CLON._OID")?.toValue();
4106
- const mser = obje?.get("_MSER._LKID")?.toValue();
4107
- let url = obje?.get("FILE")?.toValue();
4108
- const title = obje?.get("TITL")?.toValue() ?? "";
4109
- const type = obje?.get("FORM")?.toValue() ?? "raw";
4110
- const imgId = clone || mser;
4111
- if (!www || !tree || !this.id) {
4112
- return;
4113
- }
4114
- if (!namespace && !url) {
4115
- try {
4116
- const mediaDetailsResponse = await fetch(
4117
- `https://www.ancestry.com/api/media/viewer/v2/trees/${tree}/media?id=${media}`
4118
- );
4119
- const mediaDetails = await mediaDetailsResponse.json();
4120
- if (mediaDetails.url) {
4121
- url = `${mediaDetails.url}&imageQuality=hq`;
4119
+ if (objeList) {
4120
+ await Promise.all(
4121
+ objeList.map(async (objeRef) => {
4122
+ const key = objeRef?.id;
4123
+ const obje = objeRef?.standardizeMedia(
4124
+ namespace,
4125
+ true,
4126
+ (ns, iId) => {
4127
+ return ns && iId ? `https://mediasvc.ancestry.com/v2/image/namespaces/${ns}/media/${iId}?client=trees-mediaservice&imageQuality=hq` : void 0;
4122
4128
  }
4123
- } catch (_e) {
4129
+ );
4130
+ const isPrimary = obje?.get("_PRIM")?.toValue() === "Y";
4131
+ const media = obje?.RIN?.value;
4132
+ const clone = obje?.get("_CLON._OID")?.toValue();
4133
+ const mser = obje?.get("_MSER._LKID")?.toValue();
4134
+ let url = obje?.get("FILE")?.toValue();
4135
+ const title = obje?.get("TITL")?.toValue() ?? "";
4136
+ const type = obje?.get("FORM")?.toValue() ?? "raw";
4137
+ const imgId = clone || mser;
4138
+ if (!www || !tree || !this.id) {
4139
+ return;
4124
4140
  }
4125
- url = url || `https://${www}/mediaui-viewer/tree/${tree}/media/${media}`;
4126
- }
4127
- if (url && imgId) {
4128
- const id = `${tree}-${this.id}-${imgId}`;
4129
- list[id] = {
4130
- key,
4131
- id,
4132
- tree,
4133
- imgId,
4134
- person: this.id,
4135
- title,
4136
- url,
4137
- contentType: type,
4138
- downloadName: `${this.id.replaceAll("@", "")}_${this.toNaturalName().replaceAll(" ", "-") || ""}_${(title || key.replaceAll("@", "").toString()).replaceAll(" ", "-")}`
4139
- };
4140
- }
4141
- })
4142
- );
4141
+ if (!namespace && !url) {
4142
+ try {
4143
+ const mediaDetailsResponse = await fetch(
4144
+ `https://www.ancestry.com/api/media/viewer/v2/trees/${tree}/media?id=${media}`
4145
+ );
4146
+ const mediaDetails = await mediaDetailsResponse.json();
4147
+ if (mediaDetails.url) {
4148
+ url = `${mediaDetails.url}&imageQuality=hq`;
4149
+ }
4150
+ } catch (_e) {
4151
+ }
4152
+ url = url || `https://${www}/mediaui-viewer/tree/${tree}/media/${media}`;
4153
+ }
4154
+ if (url && imgId) {
4155
+ const id = `${tree}-${this.id}-${imgId}`;
4156
+ list[id] = {
4157
+ key,
4158
+ isPrimary,
4159
+ id,
4160
+ tree,
4161
+ imgId,
4162
+ person: this.id,
4163
+ title,
4164
+ url,
4165
+ contentType: type,
4166
+ downloadName: `${this.id.replaceAll("@", "")}_${this.toNaturalName().replaceAll(" ", "-") || ""}_${(title || key.replaceAll("@", "").toString()).replaceAll(" ", "-")}`
4167
+ };
4168
+ }
4169
+ })
4170
+ );
4171
+ }
4143
4172
  return list;
4144
4173
  }
4145
4174
  myheritageLink(poolId = 0) {
@@ -4158,18 +4187,20 @@ var Indi = class extends Common {
4158
4187
  if (!tree) {
4159
4188
  return;
4160
4189
  }
4161
- const birthObj = this.get("BIRT.OBJE")?.toList().values();
4162
- const deathObj = this.get("DEAT.OBJE")?.toValueList().values();
4163
- const familiesObj = (this.get("FAMS")?.toValueList().values() ?? []).concat(this.get("FAMC")?.toValueList().values() ?? []).map((fam) => {
4164
- return fam?.get("MARR.OBJE");
4190
+ const objeList = this.get("OBJE")?.toList();
4191
+ const birthObj = this.get("BIRT.OBJE")?.toList();
4192
+ const deathObj = this.get("DEAT.OBJE")?.toList();
4193
+ (this.get("FAMS")?.toValueList().values() ?? []).concat(this.get("FAMC")?.toValueList().values() ?? []).forEach((fam) => {
4194
+ objeList?.merge(birthObj).merge(deathObj).merge(fam?.get("MARR.OBJE"));
4165
4195
  });
4166
- (birthObj ?? []).concat(deathObj ?? []).concat(familiesObj ?? []).forEach((o, index) => {
4196
+ objeList?.forEach((o, index) => {
4167
4197
  if (!o) {
4168
4198
  return;
4169
4199
  }
4170
4200
  const obje = o;
4171
4201
  const key = `@O${index}@`;
4172
4202
  obje.standardizeMedia();
4203
+ const isPrimary = obje?.get("_PRIM")?.toValue() === "Y";
4173
4204
  const url = obje?.get("FILE")?.toValue();
4174
4205
  const title = obje?.get("NOTE")?.toValue() ?? "";
4175
4206
  const type = obje?.get("FORM")?.toValue() ?? "raw";
@@ -4177,6 +4208,7 @@ var Indi = class extends Common {
4177
4208
  if (url && imgId) {
4178
4209
  const id = `${tree}-${this.id}-${imgId}`;
4179
4210
  list[id] = {
4211
+ isPrimary,
4180
4212
  key,
4181
4213
  id,
4182
4214
  tree,
@@ -4286,6 +4318,36 @@ var Indi = class extends Common {
4286
4318
  }
4287
4319
  return void 0;
4288
4320
  }
4321
+ async getProfilePicture(namespace) {
4322
+ const mediaList = await this.multimedia(namespace);
4323
+ if (!mediaList) {
4324
+ return void 0;
4325
+ }
4326
+ const mediaArray = Object.values(mediaList);
4327
+ const primaryMedia = mediaArray.find(
4328
+ (media) => media.isPrimary && isImageFormat(media.contentType || getFileExtension(media.url))
4329
+ );
4330
+ if (primaryMedia) {
4331
+ return {
4332
+ file: primaryMedia.url,
4333
+ form: primaryMedia.contentType,
4334
+ title: primaryMedia.title,
4335
+ isPrimary: true
4336
+ };
4337
+ }
4338
+ const secondaryMedia = mediaArray.find(
4339
+ (media) => isImageFormat(media.contentType || getFileExtension(media.url))
4340
+ );
4341
+ if (secondaryMedia) {
4342
+ return {
4343
+ file: secondaryMedia.url,
4344
+ form: secondaryMedia.contentType,
4345
+ title: secondaryMedia.title,
4346
+ isPrimary: false
4347
+ };
4348
+ }
4349
+ return void 0;
4350
+ }
4289
4351
  link(poolId) {
4290
4352
  if (this?.isAncestry()) {
4291
4353
  return this.ancestryLink();
@@ -1,4 +1,4 @@
1
- import { n as IndiKey, af as Path, aO as Individuals } from './index-DOapi7nN.js';
1
+ import { n as IndiKey, af as Path, aP as Individuals } from './index-BPEVN_DY.js';
2
2
 
3
3
  /**
4
4
  * Cache manager interface for pluggable cache implementations.
@@ -0,0 +1,88 @@
1
+ import { l as Settings, ak as GedComType, M as MultiTag, ao as Common, t as IdType, bl as IDateStructure, aj as FamType, az as CommonDate, a1 as IndiType, n as IndiKey, J as NestedGroup, aP as Individuals } from './index-BPEVN_DY.js';
2
+
3
+ declare const GedcomTree: {
4
+ parse: (content: string, options?: {
5
+ settings?: Settings;
6
+ }) => any;
7
+ parseHierarchy: (content: string, options?: {
8
+ settings?: Settings;
9
+ }) => {
10
+ gedcom: GedComType;
11
+ raw: string;
12
+ };
13
+ addToList: (id: string, type: MultiTag, common: Common, prev: Common) => void;
14
+ };
15
+
16
+ declare const create: (gedcom: GedComType, type: MultiTag, id?: string, nodes?: {
17
+ mainNode?: Common;
18
+ curNode?: Common;
19
+ prevNode?: Common;
20
+ }) => {
21
+ prevNode: Common<string, IdType>;
22
+ curNode: Common<string, IdType>;
23
+ mainNode: Common<string, IdType>;
24
+ };
25
+
26
+ declare const ACCEPTED_DATE_FORMATS: string[];
27
+ declare const ACCEPTED_DATE_FORMATS_REGEX: RegExp;
28
+ declare const commonDateFormatter: (date?: IDateStructure["DATE"], format?: string, prefix?: string) => string;
29
+ declare const noteDateFormatter: (date?: IDateStructure["DATE"], format?: string, prefix?: string, shortNote?: boolean, showNote?: boolean) => string;
30
+ declare const marriageDateFormatter: (fam?: FamType, showDays?: boolean, showPlaces?: boolean, shortNote?: boolean, showNote?: boolean, showDisplayTextIfNoDate?: boolean, showAllEvents?: boolean, dateFormatPattern?: string) => {
31
+ marriages?: string[];
32
+ marriagePlaces?: string[];
33
+ rawArray: CommonDate[];
34
+ inArray: string[];
35
+ inOrder: string;
36
+ places: string[];
37
+ marriage: string[];
38
+ };
39
+ declare const dateFormatter: (indi?: IndiType, showMarriages?: boolean, showDays?: boolean, showPlaces?: boolean, shortNote?: boolean, showNote?: boolean, isOnStage?: (key: IndiKey) => boolean, showAllEvents?: boolean, dateFormatPattern?: string) => {
40
+ births?: string[];
41
+ birthPlaces?: string[];
42
+ deaths?: string[];
43
+ deathPlaces?: string[];
44
+ marriages?: string[];
45
+ marriagePlaces?: string[];
46
+ birthPlace?: string;
47
+ deathPlace?: string;
48
+ inArray: string[];
49
+ inOrder: string;
50
+ places: string[];
51
+ birth: string;
52
+ marriage: string[];
53
+ death: string;
54
+ };
55
+
56
+ declare const getAllProp: <T>(indi?: IndiType, prop?: MultiTag) => T[];
57
+
58
+ declare const getFamilyWith: (person1: IndiType, person2?: IndiKey, famType?: "FAMS" | "FAMC") => FamType | undefined;
59
+
60
+ declare const isDevelopment: () => boolean;
61
+ declare const getVersion: () => string;
62
+ declare const getName: () => string;
63
+
64
+ declare const getRawSize: (raw?: string) => number;
65
+
66
+ declare const implemented: (type: string, ...args: any[]) => void;
67
+ declare const notImplemented: (type: string, ...args: any[]) => void;
68
+
69
+ declare const nameFormatter: (indiName?: IndiType | string, settings?: Partial<Settings>, letterOnAll?: boolean, indi?: IndiType, debug?: 3) => {
70
+ suffix: string;
71
+ givenname: string;
72
+ surname: string;
73
+ inOrder: [string, string, string];
74
+ letter: string;
75
+ };
76
+
77
+ declare const setNestedGroup: (obj: NestedGroup, key: string | string[], value: Individuals, uniqueCounting?: boolean) => void;
78
+
79
+ declare const ordinalize: (n: number) => string;
80
+ declare const hungarianOrdinalize: (n: number) => string;
81
+
82
+ /**
83
+ * Place translator stub for gedcom-parser
84
+ * This is a minimal no-op implementation - consumer apps can implement translation if needed
85
+ */
86
+ declare const placeTranslator: (place: string | string[]) => string;
87
+
88
+ export { ACCEPTED_DATE_FORMATS as A, GedcomTree as G, ACCEPTED_DATE_FORMATS_REGEX as a, commonDateFormatter as b, create as c, dateFormatter as d, getAllProp as e, getFamilyWith as f, getRawSize as g, getVersion as h, isDevelopment as i, getName as j, implemented as k, notImplemented as l, marriageDateFormatter as m, noteDateFormatter as n, nameFormatter as o, ordinalize as p, hungarianOrdinalize as q, placeTranslator as r, setNestedGroup as s };
@@ -1,5 +1,5 @@
1
- import { ao as Common, bw as INoteStructure, bz as ISourceCitationStructure } from '../index-DOapi7nN.js';
2
- export { bg as IAddress, bh as IAssociation, bi as IChangeDate, bj as ICreationDate, bk as IDate, bl as IEventDetail, bl as IEventDetailStructure, bm as IFamily, bn as IGedcomStructure, bq as IIndividual, bp as IIndividualEvent, bo as IIndividualEventDetail, bq as IIndividualStructure, br as ILdsOrdinanceDetail, bs as ILdsSpouseSealing, bt as IMarriageDate, bu as IMultimediaLink, bv as INonEvent, bx as IPlace, by as IRepository, bB as ISource, bA as ISourceRepositoryCitation } from '../index-DOapi7nN.js';
1
+ import { ao as Common, bx as INoteStructure, bA as ISourceCitationStructure } from '../index-BPEVN_DY.js';
2
+ export { bh as IAddress, bi as IAssociation, bj as IChangeDate, bk as ICreationDate, bl as IDate, bm as IEventDetail, bm as IEventDetailStructure, bn as IFamily, bo as IGedcomStructure, br as IIndividual, bq as IIndividualEvent, bp as IIndividualEventDetail, br as IIndividualStructure, bs as ILdsOrdinanceDetail, bt as ILdsSpouseSealing, bu as IMarriageDate, bv as IMultimediaLink, bw as INonEvent, by as IPlace, bz as IRepository, bC as ISource, bB as ISourceRepositoryCitation } from '../index-BPEVN_DY.js';
3
3
  import 'date-fns';
4
4
 
5
5
  interface IPersonalNamePiecesStructure extends Common {
@@ -1,4 +1,4 @@
1
- export { m as ConvertType, F as FamKey, x as Filter, w as FilterIterator, D as Group, G as GroupDefinition, H as GroupIterator, E as GroupMarker, t as IdType, n as IndiKey, V as LinkedPersons, v as ListTag, M as MultiTag, K as NameOrder, J as NestedGroup, N as NonStandard, O as ObjeKey, A as Order, z as OrderDefinition, B as OrderIterator, X as PartnerType, Q as PlaceOrder, Y as Range, W as RelationType, o as RepoKey, y as RequiredFilter, l as Settings, q as SourKey, r as SubmKey, u as Tag, T as TagKey, U as UnknownKey } from '../index-DOapi7nN.js';
1
+ export { m as ConvertType, F as FamKey, x as Filter, w as FilterIterator, D as Group, G as GroupDefinition, H as GroupIterator, E as GroupMarker, t as IdType, n as IndiKey, V as LinkedPersons, v as ListTag, M as MultiTag, K as NameOrder, J as NestedGroup, N as NonStandard, O as ObjeKey, A as Order, z as OrderDefinition, B as OrderIterator, X as PartnerType, Q as PlaceOrder, Y as Range, W as RelationType, o as RepoKey, y as RequiredFilter, l as Settings, q as SourKey, r as SubmKey, u as Tag, T as TagKey, U as UnknownKey } from '../index-BPEVN_DY.js';
2
2
  import 'date-fns';
3
3
 
4
4
  interface AncestryMedia {
@@ -1,91 +1,19 @@
1
- export { C as CacheRelatives, I as ICacheManager, P as PlaceParts, g as getPlaceParts, p as pathCache, a as relativesCache, r as resetRelativesCache } from '../place-parser-CIplmmDd.js';
2
- import { l as Settings, ak as GedComType, M as MultiTag, ao as Common, t as IdType, bk as IDateStructure, aj as FamType, az as CommonDate, a1 as IndiType, n as IndiKey, J as NestedGroup, aO as Individuals } from '../index-DOapi7nN.js';
3
- export { bC as Place, bD as PlaceType, P as PrimitiveRange, R as Range, S as SplitResult, h as extractSeparationYears, e as extractSplitPoints, d as findMatchingRangeForSplitRange, f as fromTuple, g as generateSplitRanges, bE as getPlaces, i as inRange, a as isIntersectedRange, b as isRangeContained, p as parseRangeBounds, c as splitOverlappingRanges, s as splitRange } from '../index-DOapi7nN.js';
1
+ export { C as CacheRelatives, I as ICacheManager, P as PlaceParts, g as getPlaceParts, p as pathCache, a as relativesCache, r as resetRelativesCache } from '../place-parser-CM0TJFj8.js';
2
+ export { A as ACCEPTED_DATE_FORMATS, a as ACCEPTED_DATE_FORMATS_REGEX, G as GedcomTree, b as commonDateFormatter, c as create, d as dateFormatter, e as getAllProp, f as getFamilyWith, j as getName, g as getRawSize, h as getVersion, q as hungarianOrdinalize, k as implemented, i as isDevelopment, m as marriageDateFormatter, o as nameFormatter, l as notImplemented, n as noteDateFormatter, p as ordinalize, r as placeTranslator, s as setNestedGroup } from '../place-translator-CRiaOO9v.js';
3
+ export { bD as Place, bE as PlaceType, P as PrimitiveRange, R as Range, S as SplitResult, h as extractSeparationYears, e as extractSplitPoints, d as findMatchingRangeForSplitRange, f as fromTuple, g as generateSplitRanges, bF as getPlaces, i as inRange, a as isIntersectedRange, b as isRangeContained, p as parseRangeBounds, c as splitOverlappingRanges, s as splitRange } from '../index-BPEVN_DY.js';
4
4
  import 'date-fns';
5
5
 
6
- declare const GedcomTree: {
7
- parse: (content: string, options?: {
8
- settings?: Settings;
9
- }) => any;
10
- parseHierarchy: (content: string, options?: {
11
- settings?: Settings;
12
- }) => {
13
- gedcom: GedComType;
14
- raw: string;
15
- };
16
- addToList: (id: string, type: MultiTag, common: Common, prev: Common) => void;
17
- };
18
-
19
- declare const create: (gedcom: GedComType, type: MultiTag, id?: string, nodes?: {
20
- mainNode?: Common;
21
- curNode?: Common;
22
- prevNode?: Common;
23
- }) => {
24
- prevNode: Common<string, IdType>;
25
- curNode: Common<string, IdType>;
26
- mainNode: Common<string, IdType>;
27
- };
28
-
29
- declare const ACCEPTED_DATE_FORMATS: string[];
30
- declare const ACCEPTED_DATE_FORMATS_REGEX: RegExp;
31
- declare const commonDateFormatter: (date?: IDateStructure["DATE"], format?: string, prefix?: string) => string;
32
- declare const noteDateFormatter: (date?: IDateStructure["DATE"], format?: string, prefix?: string, shortNote?: boolean, showNote?: boolean) => string;
33
- declare const marriageDateFormatter: (fam?: FamType, showDays?: boolean, showPlaces?: boolean, shortNote?: boolean, showNote?: boolean, showDisplayTextIfNoDate?: boolean, showAllEvents?: boolean, dateFormatPattern?: string) => {
34
- marriages?: string[];
35
- marriagePlaces?: string[];
36
- rawArray: CommonDate[];
37
- inArray: string[];
38
- inOrder: string;
39
- places: string[];
40
- marriage: string[];
41
- };
42
- declare const dateFormatter: (indi?: IndiType, showMarriages?: boolean, showDays?: boolean, showPlaces?: boolean, shortNote?: boolean, showNote?: boolean, isOnStage?: (key: IndiKey) => boolean, showAllEvents?: boolean, dateFormatPattern?: string) => {
43
- births?: string[];
44
- birthPlaces?: string[];
45
- deaths?: string[];
46
- deathPlaces?: string[];
47
- marriages?: string[];
48
- marriagePlaces?: string[];
49
- birthPlace?: string;
50
- deathPlace?: string;
51
- inArray: string[];
52
- inOrder: string;
53
- places: string[];
54
- birth: string;
55
- marriage: string[];
56
- death: string;
57
- };
58
-
59
- declare const getAllProp: <T>(indi?: IndiType, prop?: MultiTag) => T[];
60
-
61
- declare const getFamilyWith: (person1: IndiType, person2?: IndiKey, famType?: "FAMS" | "FAMC") => FamType | undefined;
62
-
63
- declare const isDevelopment: () => boolean;
64
- declare const getVersion: () => string;
65
- declare const getName: () => string;
66
-
67
- declare const getRawSize: (raw?: string) => number;
68
-
69
- declare const implemented: (type: string, ...args: any[]) => void;
70
- declare const notImplemented: (type: string, ...args: any[]) => void;
71
-
72
- declare const nameFormatter: (indiName?: IndiType | string, settings?: Partial<Settings>, letterOnAll?: boolean, indi?: IndiType, debug?: 3) => {
73
- suffix: string;
74
- givenname: string;
75
- surname: string;
76
- inOrder: [string, string, string];
77
- letter: string;
78
- };
79
-
80
- declare const setNestedGroup: (obj: NestedGroup, key: string | string[], value: Individuals, uniqueCounting?: boolean) => void;
81
-
82
- declare const ordinalize: (n: number) => string;
83
- declare const hungarianOrdinalize: (n: number) => string;
84
-
85
6
  /**
86
- * Place translator stub for gedcom-parser
87
- * This is a minimal no-op implementation - consumer apps can implement translation if needed
7
+ * Get file extension from filename
8
+ * @param filename - The filename to extract extension from
9
+ * @returns File extension without the dot, or empty string if no extension
10
+ */
11
+ declare const getFileExtension: (filename: string) => string;
12
+ /**
13
+ * Check if a file format is an image format
14
+ * @param format - The file format/extension to check
15
+ * @returns true if the format is a supported image format
88
16
  */
89
- declare const placeTranslator: (place: string | string[]) => string;
17
+ declare const isImageFormat: (format: string) => boolean;
90
18
 
91
- export { ACCEPTED_DATE_FORMATS, ACCEPTED_DATE_FORMATS_REGEX, GedcomTree, commonDateFormatter, create, dateFormatter, getAllProp, getFamilyWith, getName, getRawSize, getVersion, hungarianOrdinalize, implemented, isDevelopment, marriageDateFormatter, nameFormatter, notImplemented, noteDateFormatter, ordinalize, placeTranslator, setNestedGroup };
19
+ export { getFileExtension, isImageFormat };
@@ -1503,6 +1503,27 @@ var implemented = (type, ...args) => {
1503
1503
  var notImplemented = (type, ...args) => {
1504
1504
  console.error(`[Not Implemented] ${type}`, ...args);
1505
1505
  };
1506
+
1507
+ // src/utils/media-utils.ts
1508
+ var getFileExtension = (filename) => {
1509
+ const match = filename.match(/\.([^.]+)$/);
1510
+ return match ? match[1] : "";
1511
+ };
1512
+ var isImageFormat = (format2) => {
1513
+ if (!format2) return false;
1514
+ const imageFormats = [
1515
+ "jpg",
1516
+ "jpeg",
1517
+ "png",
1518
+ "gif",
1519
+ "bmp",
1520
+ "webp",
1521
+ "svg",
1522
+ "tiff",
1523
+ "tif"
1524
+ ];
1525
+ return imageFormats.includes(format2.toLowerCase());
1526
+ };
1506
1527
  var uniqueItemsCache = /* @__PURE__ */ new WeakMap();
1507
1528
  var setNestedGroup = (obj, key, value, uniqueCounting = true) => {
1508
1529
  const parts = Array.isArray(key) ? key : key.split(/,\s*/);
@@ -2718,54 +2739,62 @@ var Indi = class extends Common {
2718
2739
  }
2719
2740
  async ancestryMedia(namespace) {
2720
2741
  const list = {};
2721
- const objIds = this.get("OBJE")?.toValueList().keys() ?? [];
2742
+ const objeList = this.get("OBJE")?.toList();
2722
2743
  const www = this._gedcom?.HEAD?.SOUR?.CORP?.WWW?.value;
2723
2744
  const tree = this.getAncestryTreeId();
2724
- await Promise.all(
2725
- objIds.map(async (objId) => {
2726
- const key = objId;
2727
- const obje = this._gedcom?.obje(key)?.standardizeMedia(namespace, true, (ns, iId) => {
2728
- return ns && iId ? `https://mediasvc.ancestry.com/v2/image/namespaces/${ns}/media/${iId}?client=trees-mediaservice&imageQuality=hq` : void 0;
2729
- });
2730
- const media = obje?.RIN?.value;
2731
- const clone = obje?.get("_CLON._OID")?.toValue();
2732
- const mser = obje?.get("_MSER._LKID")?.toValue();
2733
- let url = obje?.get("FILE")?.toValue();
2734
- const title = obje?.get("TITL")?.toValue() ?? "";
2735
- const type = obje?.get("FORM")?.toValue() ?? "raw";
2736
- const imgId = clone || mser;
2737
- if (!www || !tree || !this.id) {
2738
- return;
2739
- }
2740
- if (!namespace && !url) {
2741
- try {
2742
- const mediaDetailsResponse = await fetch(
2743
- `https://www.ancestry.com/api/media/viewer/v2/trees/${tree}/media?id=${media}`
2744
- );
2745
- const mediaDetails = await mediaDetailsResponse.json();
2746
- if (mediaDetails.url) {
2747
- url = `${mediaDetails.url}&imageQuality=hq`;
2745
+ if (objeList) {
2746
+ await Promise.all(
2747
+ objeList.map(async (objeRef) => {
2748
+ const key = objeRef?.id;
2749
+ const obje = objeRef?.standardizeMedia(
2750
+ namespace,
2751
+ true,
2752
+ (ns, iId) => {
2753
+ return ns && iId ? `https://mediasvc.ancestry.com/v2/image/namespaces/${ns}/media/${iId}?client=trees-mediaservice&imageQuality=hq` : void 0;
2748
2754
  }
2749
- } catch (_e) {
2755
+ );
2756
+ const isPrimary = obje?.get("_PRIM")?.toValue() === "Y";
2757
+ const media = obje?.RIN?.value;
2758
+ const clone = obje?.get("_CLON._OID")?.toValue();
2759
+ const mser = obje?.get("_MSER._LKID")?.toValue();
2760
+ let url = obje?.get("FILE")?.toValue();
2761
+ const title = obje?.get("TITL")?.toValue() ?? "";
2762
+ const type = obje?.get("FORM")?.toValue() ?? "raw";
2763
+ const imgId = clone || mser;
2764
+ if (!www || !tree || !this.id) {
2765
+ return;
2750
2766
  }
2751
- url = url || `https://${www}/mediaui-viewer/tree/${tree}/media/${media}`;
2752
- }
2753
- if (url && imgId) {
2754
- const id = `${tree}-${this.id}-${imgId}`;
2755
- list[id] = {
2756
- key,
2757
- id,
2758
- tree,
2759
- imgId,
2760
- person: this.id,
2761
- title,
2762
- url,
2763
- contentType: type,
2764
- downloadName: `${this.id.replaceAll("@", "")}_${this.toNaturalName().replaceAll(" ", "-") || ""}_${(title || key.replaceAll("@", "").toString()).replaceAll(" ", "-")}`
2765
- };
2766
- }
2767
- })
2768
- );
2767
+ if (!namespace && !url) {
2768
+ try {
2769
+ const mediaDetailsResponse = await fetch(
2770
+ `https://www.ancestry.com/api/media/viewer/v2/trees/${tree}/media?id=${media}`
2771
+ );
2772
+ const mediaDetails = await mediaDetailsResponse.json();
2773
+ if (mediaDetails.url) {
2774
+ url = `${mediaDetails.url}&imageQuality=hq`;
2775
+ }
2776
+ } catch (_e) {
2777
+ }
2778
+ url = url || `https://${www}/mediaui-viewer/tree/${tree}/media/${media}`;
2779
+ }
2780
+ if (url && imgId) {
2781
+ const id = `${tree}-${this.id}-${imgId}`;
2782
+ list[id] = {
2783
+ key,
2784
+ isPrimary,
2785
+ id,
2786
+ tree,
2787
+ imgId,
2788
+ person: this.id,
2789
+ title,
2790
+ url,
2791
+ contentType: type,
2792
+ downloadName: `${this.id.replaceAll("@", "")}_${this.toNaturalName().replaceAll(" ", "-") || ""}_${(title || key.replaceAll("@", "").toString()).replaceAll(" ", "-")}`
2793
+ };
2794
+ }
2795
+ })
2796
+ );
2797
+ }
2769
2798
  return list;
2770
2799
  }
2771
2800
  myheritageLink(poolId = 0) {
@@ -2784,18 +2813,20 @@ var Indi = class extends Common {
2784
2813
  if (!tree) {
2785
2814
  return;
2786
2815
  }
2787
- const birthObj = this.get("BIRT.OBJE")?.toList().values();
2788
- const deathObj = this.get("DEAT.OBJE")?.toValueList().values();
2789
- const familiesObj = (this.get("FAMS")?.toValueList().values() ?? []).concat(this.get("FAMC")?.toValueList().values() ?? []).map((fam) => {
2790
- return fam?.get("MARR.OBJE");
2816
+ const objeList = this.get("OBJE")?.toList();
2817
+ const birthObj = this.get("BIRT.OBJE")?.toList();
2818
+ const deathObj = this.get("DEAT.OBJE")?.toList();
2819
+ (this.get("FAMS")?.toValueList().values() ?? []).concat(this.get("FAMC")?.toValueList().values() ?? []).forEach((fam) => {
2820
+ objeList?.merge(birthObj).merge(deathObj).merge(fam?.get("MARR.OBJE"));
2791
2821
  });
2792
- (birthObj ?? []).concat(deathObj ?? []).concat(familiesObj ?? []).forEach((o, index) => {
2822
+ objeList?.forEach((o, index) => {
2793
2823
  if (!o) {
2794
2824
  return;
2795
2825
  }
2796
2826
  const obje = o;
2797
2827
  const key = `@O${index}@`;
2798
2828
  obje.standardizeMedia();
2829
+ const isPrimary = obje?.get("_PRIM")?.toValue() === "Y";
2799
2830
  const url = obje?.get("FILE")?.toValue();
2800
2831
  const title = obje?.get("NOTE")?.toValue() ?? "";
2801
2832
  const type = obje?.get("FORM")?.toValue() ?? "raw";
@@ -2803,6 +2834,7 @@ var Indi = class extends Common {
2803
2834
  if (url && imgId) {
2804
2835
  const id = `${tree}-${this.id}-${imgId}`;
2805
2836
  list[id] = {
2837
+ isPrimary,
2806
2838
  key,
2807
2839
  id,
2808
2840
  tree,
@@ -2912,6 +2944,36 @@ var Indi = class extends Common {
2912
2944
  }
2913
2945
  return void 0;
2914
2946
  }
2947
+ async getProfilePicture(namespace) {
2948
+ const mediaList = await this.multimedia(namespace);
2949
+ if (!mediaList) {
2950
+ return void 0;
2951
+ }
2952
+ const mediaArray = Object.values(mediaList);
2953
+ const primaryMedia = mediaArray.find(
2954
+ (media) => media.isPrimary && isImageFormat(media.contentType || getFileExtension(media.url))
2955
+ );
2956
+ if (primaryMedia) {
2957
+ return {
2958
+ file: primaryMedia.url,
2959
+ form: primaryMedia.contentType,
2960
+ title: primaryMedia.title,
2961
+ isPrimary: true
2962
+ };
2963
+ }
2964
+ const secondaryMedia = mediaArray.find(
2965
+ (media) => isImageFormat(media.contentType || getFileExtension(media.url))
2966
+ );
2967
+ if (secondaryMedia) {
2968
+ return {
2969
+ file: secondaryMedia.url,
2970
+ form: secondaryMedia.contentType,
2971
+ title: secondaryMedia.title,
2972
+ isPrimary: false
2973
+ };
2974
+ }
2975
+ return void 0;
2976
+ }
2915
2977
  link(poolId) {
2916
2978
  if (this?.isAncestry()) {
2917
2979
  return this.ancestryLink();
@@ -6045,7 +6107,7 @@ var isCommonDate = (value) => {
6045
6107
  // package.json
6046
6108
  var package_default = {
6047
6109
  name: "@treeviz/gedcom-parser",
6048
- version: "1.0.20"};
6110
+ version: "1.0.22"};
6049
6111
 
6050
6112
  // src/utils/get-product-details.ts
6051
6113
  var isDevelopment = () => {
@@ -7026,4 +7088,4 @@ if (isDev) {
7026
7088
  }
7027
7089
  var parser_default = GedcomTree;
7028
7090
 
7029
- export { ACCEPTED_DATE_FORMATS, ACCEPTED_DATE_FORMATS_REGEX, parser_default as GedcomTree, PlaceType, commonDateFormatter, create, dateFormatter, extractSeparationYears, extractSplitPoints, findMatchingRangeForSplitRange, fromTuple, generateSplitRanges, getAllProp, getFamilyWith, getName, getPlaceParts, getPlaces, getRawSize, getVersion, hungarianOrdinalize, implemented, inRange, isDevelopment, isIntersectedRange, isRangeContained, marriageDateFormatter, nameFormatter, notImplemented, noteDateFormatter, ordinalize, parseRangeBounds, pathCache, placeTranslator, relativesCache, resetRelativesCache, setNestedGroup, splitOverlappingRanges, splitRange };
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 };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@treeviz/gedcom-parser",
3
- "version": "1.0.20",
3
+ "version": "1.0.22",
4
4
  "description": "Lightweight, pluggable GEDCOM parser for JavaScript/TypeScript with optional caching and place matching. Zero browser dependencies.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",