@treeviz/familysearch-sdk 2.0.6 → 2.0.7
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.cjs +135 -50
- package/dist/index.js +135 -50
- package/dist/utils/index.cjs +135 -50
- package/dist/utils/index.js +135 -50
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -6418,6 +6418,64 @@ function transformSourceUrl(url) {
|
|
|
6418
6418
|
}
|
|
6419
6419
|
return `${baseUrl}/${arkId}`;
|
|
6420
6420
|
}
|
|
6421
|
+
function sanitizeGedcomValue(value) {
|
|
6422
|
+
return value.replace(/[\r\n\t]+/g, " ").trim();
|
|
6423
|
+
}
|
|
6424
|
+
var GEDCOM_MONTHS = [
|
|
6425
|
+
"JAN",
|
|
6426
|
+
"FEB",
|
|
6427
|
+
"MAR",
|
|
6428
|
+
"APR",
|
|
6429
|
+
"MAY",
|
|
6430
|
+
"JUN",
|
|
6431
|
+
"JUL",
|
|
6432
|
+
"AUG",
|
|
6433
|
+
"SEP",
|
|
6434
|
+
"OCT",
|
|
6435
|
+
"NOV",
|
|
6436
|
+
"DEC"
|
|
6437
|
+
];
|
|
6438
|
+
function formatSimpleFormalDate(value) {
|
|
6439
|
+
const match = value.match(/^([+-])(\d{1,6})(?:-(\d{2}))?(?:-(\d{2}))?/);
|
|
6440
|
+
if (!match) return void 0;
|
|
6441
|
+
const [, sign, yearPart, monthPart, dayPart] = match;
|
|
6442
|
+
if (sign === "-") return void 0;
|
|
6443
|
+
const year = String(parseInt(yearPart, 10));
|
|
6444
|
+
if (!monthPart) return year;
|
|
6445
|
+
const month = GEDCOM_MONTHS[parseInt(monthPart, 10) - 1];
|
|
6446
|
+
if (!month) return void 0;
|
|
6447
|
+
if (!dayPart) return `${month} ${year}`;
|
|
6448
|
+
return `${parseInt(dayPart, 10)} ${month} ${year}`;
|
|
6449
|
+
}
|
|
6450
|
+
function convertFormalDateToGedcom(formal) {
|
|
6451
|
+
if (!formal) return void 0;
|
|
6452
|
+
let value = formal.trim();
|
|
6453
|
+
let approximate = false;
|
|
6454
|
+
if (value.startsWith("A")) {
|
|
6455
|
+
approximate = true;
|
|
6456
|
+
value = value.slice(1);
|
|
6457
|
+
}
|
|
6458
|
+
if (value.includes("/")) {
|
|
6459
|
+
const slashIndex = value.indexOf("/");
|
|
6460
|
+
const start = value.slice(0, slashIndex);
|
|
6461
|
+
const end = value.slice(slashIndex + 1);
|
|
6462
|
+
const startDate = start ? formatSimpleFormalDate(start) : void 0;
|
|
6463
|
+
const endDate = end ? formatSimpleFormalDate(end) : void 0;
|
|
6464
|
+
if (start && !startDate) return void 0;
|
|
6465
|
+
if (end && !endDate) return void 0;
|
|
6466
|
+
if (startDate && endDate) return `BET ${startDate} AND ${endDate}`;
|
|
6467
|
+
if (startDate) return `FROM ${startDate}`;
|
|
6468
|
+
if (endDate) return `TO ${endDate}`;
|
|
6469
|
+
return void 0;
|
|
6470
|
+
}
|
|
6471
|
+
const simple = formatSimpleFormalDate(value);
|
|
6472
|
+
if (!simple) return void 0;
|
|
6473
|
+
return approximate ? `ABT ${simple}` : simple;
|
|
6474
|
+
}
|
|
6475
|
+
function resolveFactDate(date) {
|
|
6476
|
+
if (!date) return void 0;
|
|
6477
|
+
return convertFormalDateToGedcom(date.formal) || date.original;
|
|
6478
|
+
}
|
|
6421
6479
|
function extractName(person) {
|
|
6422
6480
|
if (!person) return null;
|
|
6423
6481
|
if (person.names?.[0]?.nameForms?.[0]) {
|
|
@@ -6425,8 +6483,14 @@ function extractName(person) {
|
|
|
6425
6483
|
const parts = nameForm.parts || [];
|
|
6426
6484
|
const given = parts.find((p) => p.type?.includes("Given"))?.value || "";
|
|
6427
6485
|
const surname = parts.find((p) => p.type?.includes("Surname"))?.value || "";
|
|
6428
|
-
if (given
|
|
6429
|
-
return `${given} /${surname}
|
|
6486
|
+
if (given && surname) {
|
|
6487
|
+
return `${given} /${surname}/`;
|
|
6488
|
+
}
|
|
6489
|
+
if (surname) {
|
|
6490
|
+
return `/${surname}/`;
|
|
6491
|
+
}
|
|
6492
|
+
if (given) {
|
|
6493
|
+
return given;
|
|
6430
6494
|
}
|
|
6431
6495
|
if (nameForm.fullText) {
|
|
6432
6496
|
return nameForm.fullText;
|
|
@@ -6456,11 +6520,9 @@ function extractFact(person, factType) {
|
|
|
6456
6520
|
const factTypeUrl = `http://gedcomx.org/${factType === "BIRTH" ? "Birth" : "Death"}`;
|
|
6457
6521
|
const fact = person.facts?.find((f) => f.type === factTypeUrl);
|
|
6458
6522
|
if (fact) {
|
|
6459
|
-
|
|
6460
|
-
|
|
6461
|
-
|
|
6462
|
-
""
|
|
6463
|
-
);
|
|
6523
|
+
const resolvedDate = resolveFactDate(fact.date);
|
|
6524
|
+
if (resolvedDate) {
|
|
6525
|
+
result.date = resolvedDate;
|
|
6464
6526
|
}
|
|
6465
6527
|
if (fact.place?.original) {
|
|
6466
6528
|
result.place = fact.place.original;
|
|
@@ -6513,25 +6575,30 @@ function convertFactToGedcom(fact) {
|
|
|
6513
6575
|
};
|
|
6514
6576
|
const gedcomTag = typeMap[fact.type] || "EVEN";
|
|
6515
6577
|
if (gedcomTag === "OCCU" && fact.value) {
|
|
6516
|
-
lines.push(`1 OCCU ${fact.value}`);
|
|
6578
|
+
lines.push(`1 OCCU ${sanitizeGedcomValue(fact.value)}`);
|
|
6517
6579
|
} else {
|
|
6518
6580
|
lines.push(`1 ${gedcomTag}`);
|
|
6519
6581
|
}
|
|
6582
|
+
if (gedcomTag === "EVEN") {
|
|
6583
|
+
const typeName = fact.type.split("/").pop();
|
|
6584
|
+
if (typeName) {
|
|
6585
|
+
lines.push(`2 TYPE ${sanitizeGedcomValue(typeName)}`);
|
|
6586
|
+
}
|
|
6587
|
+
}
|
|
6520
6588
|
if (fact.links?.conclusion?.href) {
|
|
6521
6589
|
const webUrl = transformFamilySearchUrl(fact.links.conclusion.href);
|
|
6522
6590
|
lines.push(`2 WWW ${webUrl}`);
|
|
6523
6591
|
lines.push(`3 _IS_FS Y`);
|
|
6524
6592
|
}
|
|
6525
|
-
|
|
6526
|
-
|
|
6527
|
-
|
|
6528
|
-
);
|
|
6593
|
+
const resolvedDate = resolveFactDate(fact.date);
|
|
6594
|
+
if (resolvedDate) {
|
|
6595
|
+
lines.push(`2 DATE ${sanitizeGedcomValue(resolvedDate)}`);
|
|
6529
6596
|
}
|
|
6530
6597
|
if (fact.place?.original) {
|
|
6531
|
-
lines.push(`2 PLAC ${fact.place.original}`);
|
|
6598
|
+
lines.push(`2 PLAC ${sanitizeGedcomValue(fact.place.original)}`);
|
|
6532
6599
|
}
|
|
6533
6600
|
if (fact.value && gedcomTag !== "OCCU") {
|
|
6534
|
-
lines.push(`2 NOTE ${fact.value}`);
|
|
6601
|
+
lines.push(`2 NOTE ${sanitizeGedcomValue(fact.value)}`);
|
|
6535
6602
|
}
|
|
6536
6603
|
return lines;
|
|
6537
6604
|
}
|
|
@@ -6551,14 +6618,14 @@ function convertToGedcom(pedigreeData, options = {}) {
|
|
|
6551
6618
|
lines.push("2 VERS 1.0");
|
|
6552
6619
|
lines.push("2 NAME FamilySearch API");
|
|
6553
6620
|
if (treeName) {
|
|
6554
|
-
lines.push(`2 _TREE ${treeName}`);
|
|
6621
|
+
lines.push(`2 _TREE ${sanitizeGedcomValue(treeName)}`);
|
|
6555
6622
|
const randomRIN = Math.floor(Math.random() * 1e8);
|
|
6556
6623
|
lines.push(`3 RIN ${randomRIN}`);
|
|
6557
6624
|
}
|
|
6558
6625
|
lines.push("1 DEST ANY");
|
|
6559
6626
|
lines.push("1 DATE " + formatDateForGedcom(/* @__PURE__ */ new Date()));
|
|
6560
6627
|
lines.push("1 SUBM @SUBM1@");
|
|
6561
|
-
lines.push("1 FILE " + treeName);
|
|
6628
|
+
lines.push("1 FILE " + sanitizeGedcomValue(treeName));
|
|
6562
6629
|
lines.push("1 GEDC");
|
|
6563
6630
|
lines.push("2 VERS 5.5");
|
|
6564
6631
|
lines.push("2 FORM LINEAGE-LINKED");
|
|
@@ -6580,20 +6647,22 @@ function convertToGedcom(pedigreeData, options = {}) {
|
|
|
6580
6647
|
const sourceId = `@S${sourceCounter++}@`;
|
|
6581
6648
|
lines.push(`0 ${sourceId} SOUR`);
|
|
6582
6649
|
const title = source.titles?.[0]?.value || "FamilySearch Source";
|
|
6583
|
-
lines.push(`1 TITL ${title}`);
|
|
6650
|
+
lines.push(`1 TITL ${sanitizeGedcomValue(title)}`);
|
|
6584
6651
|
if (source.citations?.[0]?.value) {
|
|
6585
|
-
lines.push(`1 TEXT ${source.citations[0].value}`);
|
|
6652
|
+
lines.push(`1 TEXT ${sanitizeGedcomValue(source.citations[0].value)}`);
|
|
6586
6653
|
}
|
|
6587
6654
|
if (source.about) {
|
|
6588
6655
|
const webUrl = transformSourceUrl(source.about);
|
|
6589
6656
|
lines.push(`1 WWW ${webUrl}`);
|
|
6590
6657
|
}
|
|
6591
6658
|
if (source.resourceType) {
|
|
6592
|
-
lines.push(
|
|
6659
|
+
lines.push(
|
|
6660
|
+
`1 NOTE Resource Type: ${sanitizeGedcomValue(source.resourceType)}`
|
|
6661
|
+
);
|
|
6593
6662
|
}
|
|
6594
6663
|
});
|
|
6595
6664
|
const fsSourMap = /* @__PURE__ */ new Map();
|
|
6596
|
-
let fsSourCounter =
|
|
6665
|
+
let fsSourCounter = sourceCounter;
|
|
6597
6666
|
pedigreeData.persons.forEach((person) => {
|
|
6598
6667
|
if (person.sources?.persons?.[0]?.sources) {
|
|
6599
6668
|
const sourceDescMap = /* @__PURE__ */ new Map();
|
|
@@ -6643,20 +6712,22 @@ function convertToGedcom(pedigreeData, options = {}) {
|
|
|
6643
6712
|
lines.push(`1 _IS_FS Y`);
|
|
6644
6713
|
lines.push(`1 _FS_ID ${id}`);
|
|
6645
6714
|
if (source.titles?.[0]?.value) {
|
|
6646
|
-
lines.push(`1 TITL ${source.titles[0].value}`);
|
|
6715
|
+
lines.push(`1 TITL ${sanitizeGedcomValue(source.titles[0].value)}`);
|
|
6647
6716
|
}
|
|
6648
6717
|
if (source.citations?.[0]?.value) {
|
|
6649
|
-
lines.push(`1 TEXT ${source.citations[0].value}`);
|
|
6718
|
+
lines.push(`1 TEXT ${sanitizeGedcomValue(source.citations[0].value)}`);
|
|
6650
6719
|
}
|
|
6651
6720
|
if (source.about) {
|
|
6652
6721
|
const webUrl = transformSourceUrl(source.about);
|
|
6653
6722
|
lines.push(`1 WWW ${webUrl}`);
|
|
6654
6723
|
}
|
|
6655
6724
|
if (source.resourceType) {
|
|
6656
|
-
lines.push(
|
|
6725
|
+
lines.push(
|
|
6726
|
+
`1 NOTE Resource Type: ${sanitizeGedcomValue(source.resourceType)}`
|
|
6727
|
+
);
|
|
6657
6728
|
}
|
|
6658
6729
|
notes.forEach((note) => {
|
|
6659
|
-
lines.push(`1 NOTE ${note}`);
|
|
6730
|
+
lines.push(`1 NOTE ${sanitizeGedcomValue(note)}`);
|
|
6660
6731
|
});
|
|
6661
6732
|
});
|
|
6662
6733
|
const fsMatchMap = /* @__PURE__ */ new Map();
|
|
@@ -6676,7 +6747,7 @@ function convertToGedcom(pedigreeData, options = {}) {
|
|
|
6676
6747
|
lines.push(`1 _IS_FS Y`);
|
|
6677
6748
|
lines.push(`1 _FS_ID ${id}`);
|
|
6678
6749
|
if (entry.title) {
|
|
6679
|
-
lines.push(`1 TITL ${entry.title}`);
|
|
6750
|
+
lines.push(`1 TITL ${sanitizeGedcomValue(entry.title)}`);
|
|
6680
6751
|
}
|
|
6681
6752
|
if (entry.content?.score !== void 0) {
|
|
6682
6753
|
lines.push(`1 SCORE ${entry.content.score}`);
|
|
@@ -6697,7 +6768,7 @@ function convertToGedcom(pedigreeData, options = {}) {
|
|
|
6697
6768
|
}
|
|
6698
6769
|
if (matchInfo.status) {
|
|
6699
6770
|
const statusName = matchInfo.status.includes("/") ? matchInfo.status.split("/").pop() : matchInfo.status;
|
|
6700
|
-
lines.push(`1 NOTE Status: ${statusName}`);
|
|
6771
|
+
lines.push(`1 NOTE Status: ${sanitizeGedcomValue(statusName || "")}`);
|
|
6701
6772
|
}
|
|
6702
6773
|
}
|
|
6703
6774
|
lines.push(`1 TYPE ${collectionType}`);
|
|
@@ -6709,42 +6780,52 @@ function convertToGedcom(pedigreeData, options = {}) {
|
|
|
6709
6780
|
if (entry.content?.gedcomx?.persons && entry.content.gedcomx.persons.length > 0) {
|
|
6710
6781
|
const matchedPerson = entry.content.gedcomx.persons[0];
|
|
6711
6782
|
if (matchedPerson.display?.name) {
|
|
6712
|
-
lines.push(`1 TEXT ${matchedPerson.display.name}`);
|
|
6783
|
+
lines.push(`1 TEXT ${sanitizeGedcomValue(matchedPerson.display.name)}`);
|
|
6713
6784
|
}
|
|
6714
6785
|
if (matchedPerson.display?.lifespan) {
|
|
6715
6786
|
lines.push(
|
|
6716
|
-
`1 NOTE Lifespan: ${matchedPerson.display.lifespan}`
|
|
6787
|
+
`1 NOTE Lifespan: ${sanitizeGedcomValue(matchedPerson.display.lifespan)}`
|
|
6717
6788
|
);
|
|
6718
6789
|
}
|
|
6719
6790
|
if (matchedPerson.display?.birthDate || matchedPerson.display?.birthPlace) {
|
|
6720
|
-
const birthInfo =
|
|
6721
|
-
|
|
6722
|
-
|
|
6723
|
-
|
|
6791
|
+
const birthInfo = sanitizeGedcomValue(
|
|
6792
|
+
[
|
|
6793
|
+
matchedPerson.display.birthDate,
|
|
6794
|
+
matchedPerson.display.birthPlace
|
|
6795
|
+
].filter(Boolean).join(", ")
|
|
6796
|
+
);
|
|
6724
6797
|
if (birthInfo) {
|
|
6725
6798
|
lines.push(`1 NOTE Birth: ${birthInfo}`);
|
|
6726
6799
|
}
|
|
6727
6800
|
}
|
|
6728
6801
|
if (matchedPerson.display?.deathDate || matchedPerson.display?.deathPlace) {
|
|
6729
|
-
const deathInfo =
|
|
6730
|
-
|
|
6731
|
-
|
|
6732
|
-
|
|
6802
|
+
const deathInfo = sanitizeGedcomValue(
|
|
6803
|
+
[
|
|
6804
|
+
matchedPerson.display.deathDate,
|
|
6805
|
+
matchedPerson.display.deathPlace
|
|
6806
|
+
].filter(Boolean).join(", ")
|
|
6807
|
+
);
|
|
6733
6808
|
if (deathInfo) {
|
|
6734
6809
|
lines.push(`1 NOTE Death: ${deathInfo}`);
|
|
6735
6810
|
}
|
|
6736
6811
|
}
|
|
6737
6812
|
if (matchedPerson.display?.gender) {
|
|
6738
|
-
lines.push(
|
|
6813
|
+
lines.push(
|
|
6814
|
+
`1 NOTE Gender: ${sanitizeGedcomValue(matchedPerson.display.gender)}`
|
|
6815
|
+
);
|
|
6739
6816
|
}
|
|
6740
6817
|
}
|
|
6741
6818
|
if (entry.content?.sourceDescription) {
|
|
6742
6819
|
const sourceDesc = entry.content.sourceDescription;
|
|
6743
6820
|
if (sourceDesc.citations?.[0]?.value) {
|
|
6744
|
-
lines.push(
|
|
6821
|
+
lines.push(
|
|
6822
|
+
`1 NOTE Citation: ${sanitizeGedcomValue(sourceDesc.citations[0].value)}`
|
|
6823
|
+
);
|
|
6745
6824
|
}
|
|
6746
6825
|
if (sourceDesc.resourceType) {
|
|
6747
|
-
lines.push(
|
|
6826
|
+
lines.push(
|
|
6827
|
+
`1 NOTE Resource Type: ${sanitizeGedcomValue(sourceDesc.resourceType)}`
|
|
6828
|
+
);
|
|
6748
6829
|
}
|
|
6749
6830
|
if (sourceDesc.about) {
|
|
6750
6831
|
const webUrl = transformSourceUrl(sourceDesc.about);
|
|
@@ -6987,7 +7068,7 @@ function convertToGedcom(pedigreeData, options = {}) {
|
|
|
6987
7068
|
const personData = person.fullDetails?.persons?.[0] || person;
|
|
6988
7069
|
const name = extractName(personData);
|
|
6989
7070
|
if (name) {
|
|
6990
|
-
lines.push(`1 NAME ${name}`);
|
|
7071
|
+
lines.push(`1 NAME ${sanitizeGedcomValue(name)}`);
|
|
6991
7072
|
}
|
|
6992
7073
|
const gender = extractGender(personData);
|
|
6993
7074
|
if (gender) {
|
|
@@ -6997,20 +7078,20 @@ function convertToGedcom(pedigreeData, options = {}) {
|
|
|
6997
7078
|
if (birth) {
|
|
6998
7079
|
lines.push("1 BIRT");
|
|
6999
7080
|
if (birth.date) {
|
|
7000
|
-
lines.push(`2 DATE ${birth.date}`);
|
|
7081
|
+
lines.push(`2 DATE ${sanitizeGedcomValue(birth.date)}`);
|
|
7001
7082
|
}
|
|
7002
7083
|
if (birth.place) {
|
|
7003
|
-
lines.push(`2 PLAC ${birth.place}`);
|
|
7084
|
+
lines.push(`2 PLAC ${sanitizeGedcomValue(birth.place)}`);
|
|
7004
7085
|
}
|
|
7005
7086
|
}
|
|
7006
7087
|
const death = extractFact(personData, "DEATH");
|
|
7007
7088
|
if (death) {
|
|
7008
7089
|
lines.push("1 DEAT");
|
|
7009
7090
|
if (death.date) {
|
|
7010
|
-
lines.push(`2 DATE ${death.date}`);
|
|
7091
|
+
lines.push(`2 DATE ${sanitizeGedcomValue(death.date)}`);
|
|
7011
7092
|
}
|
|
7012
7093
|
if (death.place) {
|
|
7013
|
-
lines.push(`2 PLAC ${death.place}`);
|
|
7094
|
+
lines.push(`2 PLAC ${sanitizeGedcomValue(death.place)}`);
|
|
7014
7095
|
}
|
|
7015
7096
|
}
|
|
7016
7097
|
personData.facts?.forEach((fact) => {
|
|
@@ -7022,8 +7103,7 @@ function convertToGedcom(pedigreeData, options = {}) {
|
|
|
7022
7103
|
if (includeNotes && person.notes?.persons?.[0]?.notes) {
|
|
7023
7104
|
person.notes.persons[0].notes.forEach((note) => {
|
|
7024
7105
|
if (note.text) {
|
|
7025
|
-
|
|
7026
|
-
lines.push(`1 NOTE ${noteText}`);
|
|
7106
|
+
lines.push(`1 NOTE ${sanitizeGedcomValue(note.text)}`);
|
|
7027
7107
|
}
|
|
7028
7108
|
});
|
|
7029
7109
|
}
|
|
@@ -7041,7 +7121,7 @@ function convertToGedcom(pedigreeData, options = {}) {
|
|
|
7041
7121
|
sourceRef.qualifiers.forEach((qualifier) => {
|
|
7042
7122
|
if (qualifier.name && qualifier.value) {
|
|
7043
7123
|
lines.push(
|
|
7044
|
-
`2 NOTE ${qualifier.name}: ${qualifier.value}`
|
|
7124
|
+
`2 NOTE ${sanitizeGedcomValue(`${qualifier.name}: ${qualifier.value}`)}`
|
|
7045
7125
|
);
|
|
7046
7126
|
}
|
|
7047
7127
|
});
|
|
@@ -7195,31 +7275,36 @@ function addMarriageFacts(lines, relationships, person1, person2) {
|
|
|
7195
7275
|
return [a, b].sort().join("-") === relKey;
|
|
7196
7276
|
});
|
|
7197
7277
|
if (!rel) return;
|
|
7278
|
+
const isMarriageEvent = (type) => !!type && (type.includes("Marriage") || type.includes("Divorce"));
|
|
7198
7279
|
const marriageFacts = [];
|
|
7199
7280
|
if (rel.facts && Array.isArray(rel.facts)) {
|
|
7200
7281
|
rel.facts.forEach((f) => {
|
|
7201
|
-
if (f.type
|
|
7282
|
+
if (isMarriageEvent(f.type)) {
|
|
7202
7283
|
marriageFacts.push(f);
|
|
7203
7284
|
}
|
|
7204
7285
|
});
|
|
7205
7286
|
}
|
|
7206
7287
|
if (rel.details?.facts && Array.isArray(rel.details.facts)) {
|
|
7207
7288
|
marriageFacts.push(
|
|
7208
|
-
...rel.details.facts.filter((f) => f.type
|
|
7289
|
+
...rel.details.facts.filter((f) => isMarriageEvent(f.type))
|
|
7209
7290
|
);
|
|
7210
7291
|
}
|
|
7211
7292
|
if (rel.details?.persons && Array.isArray(rel.details.persons)) {
|
|
7212
7293
|
rel.details.persons.forEach((p) => {
|
|
7213
7294
|
if (p.facts && Array.isArray(p.facts)) {
|
|
7214
7295
|
p.facts.forEach((f) => {
|
|
7215
|
-
if (f.type
|
|
7296
|
+
if (isMarriageEvent(f.type)) {
|
|
7216
7297
|
marriageFacts.push(f);
|
|
7217
7298
|
}
|
|
7218
7299
|
});
|
|
7219
7300
|
}
|
|
7220
7301
|
});
|
|
7221
7302
|
}
|
|
7303
|
+
const seenFacts = /* @__PURE__ */ new Set();
|
|
7222
7304
|
marriageFacts.forEach((mf) => {
|
|
7305
|
+
const key = `${mf.type}|${resolveFactDate(mf.date) || ""}|${mf.place?.original || ""}`;
|
|
7306
|
+
if (seenFacts.has(key)) return;
|
|
7307
|
+
seenFacts.add(key);
|
|
7223
7308
|
const factLines = convertFactToGedcom(mf);
|
|
7224
7309
|
factLines.forEach((line) => lines.push(line));
|
|
7225
7310
|
});
|