@treeviz/gedcom-parser 2.1.2 → 2.1.4
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/classes/index.js +204 -6
- package/dist/classes/indi.d.ts +7 -2
- package/dist/classes/indi.d.ts.map +1 -1
- package/dist/cli/index.js +468 -268
- package/dist/constants/index.js +201 -5
- package/dist/factories/index.js +201 -5
- package/dist/index.js +811 -386
- package/dist/interfaces/indi.d.ts +8 -3
- package/dist/interfaces/indi.d.ts.map +1 -1
- package/dist/kinship-translator/index.js +201 -5
- package/dist/utils/family-edit.d.ts +81 -2
- package/dist/utils/family-edit.d.ts.map +1 -1
- package/dist/utils/gedcom7-schema.d.ts.map +1 -1
- package/dist/utils/index.js +430 -7
- package/package.json +1 -1
package/dist/utils/index.js
CHANGED
|
@@ -2032,6 +2032,28 @@ var addNonEvent = (owner, input) => {
|
|
|
2032
2032
|
};
|
|
2033
2033
|
|
|
2034
2034
|
// src/utils/family-edit.ts
|
|
2035
|
+
var refTypeForTag = (tag) => {
|
|
2036
|
+
if (tag === "FAMS" || tag === "FAMC") return "FAM";
|
|
2037
|
+
return "INDI";
|
|
2038
|
+
};
|
|
2039
|
+
var normalizeSinglePointer = (owner, tag) => {
|
|
2040
|
+
const node = owner.get(tag);
|
|
2041
|
+
if (!node) return;
|
|
2042
|
+
if (node instanceof List && node.length === 1) {
|
|
2043
|
+
const only = node.index(0);
|
|
2044
|
+
if (only) {
|
|
2045
|
+
owner.set(tag, only);
|
|
2046
|
+
return;
|
|
2047
|
+
}
|
|
2048
|
+
const raw = node.values()[0];
|
|
2049
|
+
if (typeof raw === "string") {
|
|
2050
|
+
const gedcom = owner.getGedcom?.();
|
|
2051
|
+
if (gedcom) {
|
|
2052
|
+
owner.set(tag, makePointer(gedcom, owner, raw, refTypeForTag(tag)));
|
|
2053
|
+
}
|
|
2054
|
+
}
|
|
2055
|
+
}
|
|
2056
|
+
};
|
|
2035
2057
|
var PEDIGREE_VALUES = [
|
|
2036
2058
|
"birth" /* BIRTH */,
|
|
2037
2059
|
"adopted" /* ADOPTED */,
|
|
@@ -2150,6 +2172,9 @@ var attachSpouseToFamily = (fam, indi) => {
|
|
|
2150
2172
|
fam.set(tag, makePointer(gedcom, fam, indi.id, "INDI"));
|
|
2151
2173
|
}
|
|
2152
2174
|
indi.assign("FAMS", makePointer(gedcom, indi, fam.id, "FAM"), true);
|
|
2175
|
+
normalizeSinglePointer(indi, "FAMS");
|
|
2176
|
+
normalizeSinglePointer(fam, spouseTagFor(indi, fam));
|
|
2177
|
+
resetRelativesCache();
|
|
2153
2178
|
return true;
|
|
2154
2179
|
};
|
|
2155
2180
|
var attachChildToFamily = (fam, child, pedigree, parent) => {
|
|
@@ -2165,14 +2190,351 @@ var attachChildToFamily = (fam, child, pedigree, parent) => {
|
|
|
2165
2190
|
child.assign("FAMC", makePointer(gedcom, child, fam.id, "FAM"), true);
|
|
2166
2191
|
}
|
|
2167
2192
|
setChildPedigree(fam, child, pedigree, parent);
|
|
2193
|
+
normalizeSinglePointer(child, "FAMC");
|
|
2194
|
+
normalizeSinglePointer(fam, "CHIL");
|
|
2195
|
+
resetRelativesCache();
|
|
2168
2196
|
return true;
|
|
2169
2197
|
};
|
|
2170
|
-
var
|
|
2198
|
+
var removePointerByValue = (owner, tag, targetId) => {
|
|
2199
|
+
const node = owner.get(tag);
|
|
2200
|
+
if (!node) {
|
|
2201
|
+
return false;
|
|
2202
|
+
}
|
|
2203
|
+
if (node instanceof List) {
|
|
2204
|
+
const keysToRemove = [];
|
|
2205
|
+
node.entries().forEach(([key, item]) => {
|
|
2206
|
+
if (item?.toValue?.() === targetId || item?.id === targetId || String(key) === targetId) {
|
|
2207
|
+
keysToRemove.push(key);
|
|
2208
|
+
}
|
|
2209
|
+
});
|
|
2210
|
+
keysToRemove.forEach((key) => {
|
|
2211
|
+
node.removeItem(key);
|
|
2212
|
+
});
|
|
2213
|
+
if (node.length === 0) {
|
|
2214
|
+
owner.remove(tag);
|
|
2215
|
+
}
|
|
2216
|
+
return keysToRemove.length > 0;
|
|
2217
|
+
}
|
|
2218
|
+
if (node.toValue?.() === targetId) {
|
|
2219
|
+
owner.remove(tag);
|
|
2220
|
+
return true;
|
|
2221
|
+
}
|
|
2222
|
+
const asList = node.toList?.();
|
|
2223
|
+
if (asList && asList.length > 0) {
|
|
2224
|
+
const keysToRemove = [];
|
|
2225
|
+
asList.entries().forEach(([key, item]) => {
|
|
2226
|
+
if (item?.toValue?.() === targetId || item?.id === targetId) {
|
|
2227
|
+
keysToRemove.push(key);
|
|
2228
|
+
}
|
|
2229
|
+
});
|
|
2230
|
+
if (keysToRemove.length === asList.length) {
|
|
2231
|
+
owner.remove(tag);
|
|
2232
|
+
return true;
|
|
2233
|
+
}
|
|
2234
|
+
if (keysToRemove.length > 0) {
|
|
2235
|
+
const remaining = asList.values().filter((item) => item?.toValue?.() !== targetId);
|
|
2236
|
+
if (remaining.length === 1 && remaining[0]) {
|
|
2237
|
+
owner.set(tag, remaining[0]);
|
|
2238
|
+
} else {
|
|
2239
|
+
owner.set(tag, new List(remaining));
|
|
2240
|
+
}
|
|
2241
|
+
return true;
|
|
2242
|
+
}
|
|
2243
|
+
}
|
|
2244
|
+
return false;
|
|
2245
|
+
};
|
|
2246
|
+
var familyMemberCount = (fam) => {
|
|
2247
|
+
let count = 0;
|
|
2248
|
+
if (firstPointerId(fam.get("HUSB"))) {
|
|
2249
|
+
count += 1;
|
|
2250
|
+
}
|
|
2251
|
+
if (firstPointerId(fam.get("WIFE"))) {
|
|
2252
|
+
count += 1;
|
|
2253
|
+
}
|
|
2254
|
+
count += pointerIds(fam.get("CHIL")).length;
|
|
2255
|
+
return count;
|
|
2256
|
+
};
|
|
2257
|
+
var isDegenerateFamily = (fam) => familyMemberCount(fam) <= 1;
|
|
2258
|
+
var pruneEmptyFamilies = (gedcom) => {
|
|
2259
|
+
const emptyIds = [];
|
|
2260
|
+
gedcom.fams()?.forEach((fam, id) => {
|
|
2261
|
+
if (fam && isDegenerateFamily(fam) && id) {
|
|
2262
|
+
emptyIds.push(id);
|
|
2263
|
+
}
|
|
2264
|
+
});
|
|
2265
|
+
if (emptyIds.length === 0) {
|
|
2266
|
+
return [];
|
|
2267
|
+
}
|
|
2268
|
+
gedcom.indis()?.forEach((indi) => {
|
|
2269
|
+
if (!indi) {
|
|
2270
|
+
return;
|
|
2271
|
+
}
|
|
2272
|
+
emptyIds.forEach((famId) => {
|
|
2273
|
+
removePointerByValue(indi, "FAMS", famId);
|
|
2274
|
+
removePointerByValue(indi, "FAMC", famId);
|
|
2275
|
+
});
|
|
2276
|
+
});
|
|
2277
|
+
emptyIds.forEach((famId) => {
|
|
2278
|
+
gedcom.fams()?.removeItem(famId);
|
|
2279
|
+
});
|
|
2280
|
+
return emptyIds;
|
|
2281
|
+
};
|
|
2282
|
+
var findDegenerateFamiliesForIndi = (indi) => {
|
|
2283
|
+
const found = [];
|
|
2284
|
+
const seen = /* @__PURE__ */ new Set();
|
|
2285
|
+
["FAMC", "FAMS"].forEach((pointer) => {
|
|
2286
|
+
indi.getFamilies(pointer)?.forEach((fam) => {
|
|
2287
|
+
if (!fam?.id || seen.has(fam.id) || !isDegenerateFamily(fam)) {
|
|
2288
|
+
return;
|
|
2289
|
+
}
|
|
2290
|
+
seen.add(fam.id);
|
|
2291
|
+
found.push(fam);
|
|
2292
|
+
});
|
|
2293
|
+
});
|
|
2294
|
+
return found;
|
|
2295
|
+
};
|
|
2296
|
+
var coupleKeyForFam = (fam) => {
|
|
2297
|
+
const husb = firstPointerId(fam.get("HUSB"));
|
|
2298
|
+
const wife = firstPointerId(fam.get("WIFE"));
|
|
2299
|
+
if (!husb || !wife) {
|
|
2300
|
+
return void 0;
|
|
2301
|
+
}
|
|
2302
|
+
return husb < wife ? `${husb}|${wife}` : `${wife}|${husb}`;
|
|
2303
|
+
};
|
|
2304
|
+
var findDuplicateCoupleFamiliesForIndi = (indi) => {
|
|
2305
|
+
const gedcom = indi.getGedcom();
|
|
2306
|
+
if (!gedcom) {
|
|
2307
|
+
return [];
|
|
2308
|
+
}
|
|
2309
|
+
const relevantKeys = /* @__PURE__ */ new Set();
|
|
2310
|
+
["FAMC", "FAMS"].forEach((pointer) => {
|
|
2311
|
+
indi.getFamilies(pointer)?.forEach((fam) => {
|
|
2312
|
+
const key = fam ? coupleKeyForFam(fam) : void 0;
|
|
2313
|
+
if (key) {
|
|
2314
|
+
relevantKeys.add(key);
|
|
2315
|
+
}
|
|
2316
|
+
});
|
|
2317
|
+
});
|
|
2318
|
+
if (relevantKeys.size === 0) {
|
|
2319
|
+
return [];
|
|
2320
|
+
}
|
|
2321
|
+
const byKey = /* @__PURE__ */ new Map();
|
|
2322
|
+
gedcom.fams()?.forEach((fam) => {
|
|
2323
|
+
if (!fam?.id) {
|
|
2324
|
+
return;
|
|
2325
|
+
}
|
|
2326
|
+
const key = coupleKeyForFam(fam);
|
|
2327
|
+
if (!key || !relevantKeys.has(key)) {
|
|
2328
|
+
return;
|
|
2329
|
+
}
|
|
2330
|
+
const list = byKey.get(key) ?? [];
|
|
2331
|
+
list.push(fam);
|
|
2332
|
+
byKey.set(key, list);
|
|
2333
|
+
});
|
|
2334
|
+
return [...byKey.entries()].filter(([, families]) => families.length > 1).map(([key, families]) => ({ key, families }));
|
|
2335
|
+
};
|
|
2336
|
+
var mergeDuplicateCoupleFamilies = (gedcom, families) => {
|
|
2337
|
+
const usable = families.filter((fam) => !!fam?.id);
|
|
2338
|
+
if (usable.length === 0) {
|
|
2339
|
+
return void 0;
|
|
2340
|
+
}
|
|
2341
|
+
if (usable.length === 1) {
|
|
2342
|
+
return usable[0];
|
|
2343
|
+
}
|
|
2344
|
+
const sorted = [...usable].sort((a, b) => {
|
|
2345
|
+
const childDiff = pointerIds(b.get("CHIL")).length - pointerIds(a.get("CHIL")).length;
|
|
2346
|
+
if (childDiff !== 0) {
|
|
2347
|
+
return childDiff;
|
|
2348
|
+
}
|
|
2349
|
+
return String(a.id).localeCompare(String(b.id));
|
|
2350
|
+
});
|
|
2351
|
+
const keep = sorted[0];
|
|
2352
|
+
const drops = sorted.slice(1);
|
|
2353
|
+
if (!keep?.id) {
|
|
2354
|
+
return void 0;
|
|
2355
|
+
}
|
|
2356
|
+
drops.forEach((drop) => {
|
|
2357
|
+
if (!drop?.id || drop.id === keep.id) {
|
|
2358
|
+
return;
|
|
2359
|
+
}
|
|
2360
|
+
pointerIds(drop.get("CHIL")).forEach((childId) => {
|
|
2361
|
+
const child = gedcom.indi(childId);
|
|
2362
|
+
if (!child) {
|
|
2363
|
+
return;
|
|
2364
|
+
}
|
|
2365
|
+
attachChildToFamily(keep, child);
|
|
2366
|
+
removePointerByValue(drop, "CHIL", childId);
|
|
2367
|
+
normalizeSinglePointer(drop, "CHIL");
|
|
2368
|
+
removePointerByValue(child, "FAMC", drop.id);
|
|
2369
|
+
normalizeSinglePointer(child, "FAMC");
|
|
2370
|
+
});
|
|
2371
|
+
const husbId = firstPointerId(drop.get("HUSB"));
|
|
2372
|
+
const wifeId = firstPointerId(drop.get("WIFE"));
|
|
2373
|
+
[husbId, wifeId].forEach((parentId) => {
|
|
2374
|
+
if (!parentId) {
|
|
2375
|
+
return;
|
|
2376
|
+
}
|
|
2377
|
+
const parent = gedcom.indi(parentId);
|
|
2378
|
+
if (parent) {
|
|
2379
|
+
removePointerByValue(parent, "FAMS", drop.id);
|
|
2380
|
+
normalizeSinglePointer(parent, "FAMS");
|
|
2381
|
+
}
|
|
2382
|
+
});
|
|
2383
|
+
gedcom.fams()?.removeItem(drop.id);
|
|
2384
|
+
});
|
|
2385
|
+
resetRelativesCache();
|
|
2386
|
+
return keep;
|
|
2387
|
+
};
|
|
2388
|
+
var pruneFamiliesByIds = (gedcom, famIds) => {
|
|
2389
|
+
const unique = [...new Set(famIds.filter(Boolean))];
|
|
2390
|
+
if (unique.length === 0) {
|
|
2391
|
+
return 0;
|
|
2392
|
+
}
|
|
2393
|
+
gedcom.indis()?.forEach((indi) => {
|
|
2394
|
+
if (!indi) {
|
|
2395
|
+
return;
|
|
2396
|
+
}
|
|
2397
|
+
unique.forEach((famId) => {
|
|
2398
|
+
removePointerByValue(indi, "FAMS", famId);
|
|
2399
|
+
removePointerByValue(indi, "FAMC", famId);
|
|
2400
|
+
});
|
|
2401
|
+
});
|
|
2402
|
+
unique.forEach((famId) => {
|
|
2403
|
+
gedcom.fams()?.removeItem(famId);
|
|
2404
|
+
});
|
|
2405
|
+
return unique.length;
|
|
2406
|
+
};
|
|
2407
|
+
var findSharedSpouseFamily = (parent, coParentId) => {
|
|
2408
|
+
let found;
|
|
2409
|
+
parent.getFamilies("FAMS")?.forEach((fam) => {
|
|
2410
|
+
if (!found && fam && familyHasParent(fam, coParentId)) {
|
|
2411
|
+
found = fam;
|
|
2412
|
+
}
|
|
2413
|
+
});
|
|
2414
|
+
return found;
|
|
2415
|
+
};
|
|
2416
|
+
var unlinkRelative = (anchor, relative, kind) => {
|
|
2417
|
+
if (!anchor.id || !relative.id || anchor.id === relative.id) {
|
|
2418
|
+
return false;
|
|
2419
|
+
}
|
|
2420
|
+
let changed = false;
|
|
2421
|
+
if (kind === "spouse") {
|
|
2422
|
+
anchor.getFamilies("FAMS")?.forEach((fam) => {
|
|
2423
|
+
if (!fam?.id || !familyHasParent(fam, relative.id)) {
|
|
2424
|
+
return;
|
|
2425
|
+
}
|
|
2426
|
+
if (firstPointerId(fam.get("HUSB")) === relative.id) {
|
|
2427
|
+
fam.remove("HUSB");
|
|
2428
|
+
changed = true;
|
|
2429
|
+
}
|
|
2430
|
+
if (firstPointerId(fam.get("WIFE")) === relative.id) {
|
|
2431
|
+
fam.remove("WIFE");
|
|
2432
|
+
changed = true;
|
|
2433
|
+
}
|
|
2434
|
+
changed = removePointerByValue(relative, "FAMS", fam.id) || changed;
|
|
2435
|
+
});
|
|
2436
|
+
} else if (kind === "parent") {
|
|
2437
|
+
anchor.getFamilies("FAMC")?.forEach((fam) => {
|
|
2438
|
+
if (!fam?.id || !familyHasParent(fam, relative.id)) {
|
|
2439
|
+
return;
|
|
2440
|
+
}
|
|
2441
|
+
if (firstPointerId(fam.get("HUSB")) === relative.id) {
|
|
2442
|
+
fam.remove("HUSB");
|
|
2443
|
+
changed = true;
|
|
2444
|
+
}
|
|
2445
|
+
if (firstPointerId(fam.get("WIFE")) === relative.id) {
|
|
2446
|
+
fam.remove("WIFE");
|
|
2447
|
+
changed = true;
|
|
2448
|
+
}
|
|
2449
|
+
changed = removePointerByValue(relative, "FAMS", fam.id) || changed;
|
|
2450
|
+
});
|
|
2451
|
+
} else if (kind === "sibling") {
|
|
2452
|
+
anchor.getFamilies("FAMC")?.forEach((fam) => {
|
|
2453
|
+
if (!fam?.id || !familyHasChild(fam, relative.id)) {
|
|
2454
|
+
return;
|
|
2455
|
+
}
|
|
2456
|
+
changed = removePointerByValue(fam, "CHIL", relative.id) || changed;
|
|
2457
|
+
changed = removePointerByValue(relative, "FAMC", fam.id) || changed;
|
|
2458
|
+
});
|
|
2459
|
+
} else {
|
|
2460
|
+
anchor.getFamilies("FAMS")?.forEach((fam) => {
|
|
2461
|
+
if (!fam?.id || !familyHasChild(fam, relative.id)) {
|
|
2462
|
+
return;
|
|
2463
|
+
}
|
|
2464
|
+
changed = removePointerByValue(fam, "CHIL", relative.id) || changed;
|
|
2465
|
+
changed = removePointerByValue(relative, "FAMC", fam.id) || changed;
|
|
2466
|
+
});
|
|
2467
|
+
}
|
|
2468
|
+
if (changed) {
|
|
2469
|
+
const gedcom = anchor.getGedcom() ?? relative.getGedcom();
|
|
2470
|
+
if (gedcom) {
|
|
2471
|
+
pruneEmptyFamilies(gedcom);
|
|
2472
|
+
}
|
|
2473
|
+
resetRelativesCache();
|
|
2474
|
+
}
|
|
2475
|
+
return changed;
|
|
2476
|
+
};
|
|
2477
|
+
var deleteIndividual = (gedcom, indiId) => {
|
|
2478
|
+
const indi = gedcom.indi(indiId);
|
|
2479
|
+
if (!indi?.id) {
|
|
2480
|
+
return false;
|
|
2481
|
+
}
|
|
2482
|
+
const famsIds = pointerIds(indi.get("FAMS"));
|
|
2483
|
+
const famcIds = pointerIds(indi.get("FAMC"));
|
|
2484
|
+
famsIds.forEach((famId) => {
|
|
2485
|
+
const fam = gedcom.fam(famId);
|
|
2486
|
+
if (!fam) {
|
|
2487
|
+
return;
|
|
2488
|
+
}
|
|
2489
|
+
if (firstPointerId(fam.get("HUSB")) === indiId) {
|
|
2490
|
+
fam.remove("HUSB");
|
|
2491
|
+
}
|
|
2492
|
+
if (firstPointerId(fam.get("WIFE")) === indiId) {
|
|
2493
|
+
fam.remove("WIFE");
|
|
2494
|
+
}
|
|
2495
|
+
});
|
|
2496
|
+
famcIds.forEach((famId) => {
|
|
2497
|
+
const fam = gedcom.fam(famId);
|
|
2498
|
+
if (fam) {
|
|
2499
|
+
removePointerByValue(fam, "CHIL", indiId);
|
|
2500
|
+
}
|
|
2501
|
+
});
|
|
2502
|
+
gedcom.fams()?.forEach((fam) => {
|
|
2503
|
+
if (fam && familyHasChild(fam, indiId)) {
|
|
2504
|
+
removePointerByValue(fam, "CHIL", indiId);
|
|
2505
|
+
}
|
|
2506
|
+
if (fam && familyHasParent(fam, indiId)) {
|
|
2507
|
+
if (firstPointerId(fam.get("HUSB")) === indiId) {
|
|
2508
|
+
fam.remove("HUSB");
|
|
2509
|
+
}
|
|
2510
|
+
if (firstPointerId(fam.get("WIFE")) === indiId) {
|
|
2511
|
+
fam.remove("WIFE");
|
|
2512
|
+
}
|
|
2513
|
+
}
|
|
2514
|
+
});
|
|
2515
|
+
gedcom.indis()?.removeItem(indiId);
|
|
2516
|
+
pruneEmptyFamilies(gedcom);
|
|
2517
|
+
resetRelativesCache();
|
|
2518
|
+
return true;
|
|
2519
|
+
};
|
|
2520
|
+
var findReusableParentChildFamily = (parent, child, options) => {
|
|
2171
2521
|
if (!parent.id || !child.id) {
|
|
2172
2522
|
return void 0;
|
|
2173
2523
|
}
|
|
2524
|
+
const reuseParentFamilies = options?.reuseParentFamilies !== false;
|
|
2525
|
+
const gedcom = parent.getGedcom() ?? child.getGedcom();
|
|
2174
2526
|
let reusableFamc;
|
|
2527
|
+
let coupleFam;
|
|
2175
2528
|
let already = false;
|
|
2529
|
+
const noteCoupleWith = (coParentId) => {
|
|
2530
|
+
if (!coParentId || coParentId === parent.id || coupleFam || !parent.id) {
|
|
2531
|
+
return;
|
|
2532
|
+
}
|
|
2533
|
+
const shared = findSharedSpouseFamily(parent, coParentId);
|
|
2534
|
+
if (shared) {
|
|
2535
|
+
coupleFam = shared;
|
|
2536
|
+
}
|
|
2537
|
+
};
|
|
2176
2538
|
child.getFamilies("FAMC")?.forEach((fam) => {
|
|
2177
2539
|
if (!fam) {
|
|
2178
2540
|
return;
|
|
@@ -2181,6 +2543,8 @@ var findReusableParentChildFamily = (parent, child) => {
|
|
|
2181
2543
|
already = true;
|
|
2182
2544
|
return;
|
|
2183
2545
|
}
|
|
2546
|
+
pointerIds(fam.get("HUSB")).forEach(noteCoupleWith);
|
|
2547
|
+
pointerIds(fam.get("WIFE")).forEach(noteCoupleWith);
|
|
2184
2548
|
if (!reusableFamc && canAttachAsSpouse(fam, parent)) {
|
|
2185
2549
|
reusableFamc = fam;
|
|
2186
2550
|
}
|
|
@@ -2188,9 +2552,21 @@ var findReusableParentChildFamily = (parent, child) => {
|
|
|
2188
2552
|
if (already) {
|
|
2189
2553
|
return "already";
|
|
2190
2554
|
}
|
|
2555
|
+
if (coupleFam) {
|
|
2556
|
+
return coupleFam;
|
|
2557
|
+
}
|
|
2191
2558
|
if (reusableFamc) {
|
|
2192
2559
|
return reusableFamc;
|
|
2193
2560
|
}
|
|
2561
|
+
if (options?.targetFamilyId && gedcom) {
|
|
2562
|
+
const target = gedcom.fam(options.targetFamilyId);
|
|
2563
|
+
if (target && (familyHasParent(target, parent.id) || canAttachAsSpouse(target, parent))) {
|
|
2564
|
+
return target;
|
|
2565
|
+
}
|
|
2566
|
+
}
|
|
2567
|
+
if (!reuseParentFamilies) {
|
|
2568
|
+
return void 0;
|
|
2569
|
+
}
|
|
2194
2570
|
const parentFams = [];
|
|
2195
2571
|
parent.getFamilies("FAMS")?.forEach((fam) => {
|
|
2196
2572
|
if (fam) {
|
|
@@ -2202,6 +2578,41 @@ var findReusableParentChildFamily = (parent, child) => {
|
|
|
2202
2578
|
}
|
|
2203
2579
|
return void 0;
|
|
2204
2580
|
};
|
|
2581
|
+
var consolidateChildIntoFamily = (child, keep) => {
|
|
2582
|
+
if (!child.id || !keep.id) {
|
|
2583
|
+
return [];
|
|
2584
|
+
}
|
|
2585
|
+
const keepParentIds = /* @__PURE__ */ new Set([
|
|
2586
|
+
...pointerIds(keep.get("HUSB")),
|
|
2587
|
+
...pointerIds(keep.get("WIFE"))
|
|
2588
|
+
]);
|
|
2589
|
+
const removed = [];
|
|
2590
|
+
child.getFamilies("FAMC")?.forEach((fam) => {
|
|
2591
|
+
if (!fam?.id || fam.id === keep.id) {
|
|
2592
|
+
return;
|
|
2593
|
+
}
|
|
2594
|
+
const famParentIds = [
|
|
2595
|
+
...pointerIds(fam.get("HUSB")),
|
|
2596
|
+
...pointerIds(fam.get("WIFE"))
|
|
2597
|
+
];
|
|
2598
|
+
if (famParentIds.length === 0 || !famParentIds.every((id) => keepParentIds.has(id))) {
|
|
2599
|
+
return;
|
|
2600
|
+
}
|
|
2601
|
+
removePointerByValue(fam, "CHIL", child.id);
|
|
2602
|
+
normalizeSinglePointer(fam, "CHIL");
|
|
2603
|
+
removePointerByValue(child, "FAMC", fam.id);
|
|
2604
|
+
normalizeSinglePointer(child, "FAMC");
|
|
2605
|
+
removed.push(fam.id);
|
|
2606
|
+
});
|
|
2607
|
+
const gedcom = child.getGedcom() ?? keep.getGedcom();
|
|
2608
|
+
if (gedcom && removed.length > 0) {
|
|
2609
|
+
pruneEmptyFamilies(gedcom);
|
|
2610
|
+
}
|
|
2611
|
+
if (removed.length > 0) {
|
|
2612
|
+
resetRelativesCache();
|
|
2613
|
+
}
|
|
2614
|
+
return removed;
|
|
2615
|
+
};
|
|
2205
2616
|
|
|
2206
2617
|
// src/utils/get-places.ts
|
|
2207
2618
|
var PlaceType = /* @__PURE__ */ ((PlaceType2) => {
|
|
@@ -4299,13 +4710,17 @@ var Indi = class extends Common {
|
|
|
4299
4710
|
}
|
|
4300
4711
|
return fam;
|
|
4301
4712
|
}
|
|
4302
|
-
addChild(child, pedigree) {
|
|
4713
|
+
addChild(child, pedigree, options) {
|
|
4303
4714
|
if (!this.id || !child?.id || this.id === child.id || !this._gedcom) {
|
|
4304
4715
|
return void 0;
|
|
4305
4716
|
}
|
|
4306
4717
|
const existing = findReusableParentChildFamily(
|
|
4307
4718
|
this,
|
|
4308
|
-
child
|
|
4719
|
+
child,
|
|
4720
|
+
{
|
|
4721
|
+
reuseParentFamilies: options?.reuseParentFamilies,
|
|
4722
|
+
targetFamilyId: options?.targetFamilyId
|
|
4723
|
+
}
|
|
4309
4724
|
);
|
|
4310
4725
|
if (existing === "already") {
|
|
4311
4726
|
const fam2 = child.getFamilies("FAMC")?.find(
|
|
@@ -4328,10 +4743,16 @@ var Indi = class extends Common {
|
|
|
4328
4743
|
if (!fam.addChild(child, pedigree, this)) {
|
|
4329
4744
|
return void 0;
|
|
4330
4745
|
}
|
|
4746
|
+
if (existing) {
|
|
4747
|
+
consolidateChildIntoFamily(child, fam);
|
|
4748
|
+
}
|
|
4331
4749
|
return fam;
|
|
4332
4750
|
}
|
|
4333
|
-
addParent(parent, pedigree) {
|
|
4334
|
-
return parent.addChild(this, pedigree
|
|
4751
|
+
addParent(parent, pedigree, options) {
|
|
4752
|
+
return parent.addChild(this, pedigree, {
|
|
4753
|
+
reuseParentFamilies: false,
|
|
4754
|
+
targetFamilyId: options?.targetFamilyId
|
|
4755
|
+
});
|
|
4335
4756
|
}
|
|
4336
4757
|
/**
|
|
4337
4758
|
* Link an existing top-level OBJE record to this individual (`1 OBJE @On@`).
|
|
@@ -8338,6 +8759,8 @@ var TREEVIZ_EXTENSION_URIS = {
|
|
|
8338
8759
|
_FS_MATCH: `${TREEVIZ_EXTENSION_BASE_URI}#_FS_MATCH`,
|
|
8339
8760
|
_FS_SOUR: `${TREEVIZ_EXTENSION_BASE_URI}#_FS_SOUR`,
|
|
8340
8761
|
_IS_FS: `${TREEVIZ_EXTENSION_BASE_URI}#_IS_FS`,
|
|
8762
|
+
_IS_ORPHAN_FAMILY: `${TREEVIZ_EXTENSION_BASE_URI}#_IS_ORPHAN_FAMILY`,
|
|
8763
|
+
_GUESSEDORIGINAL: `${TREEVIZ_EXTENSION_BASE_URI}#_GUESSEDORIGINAL`,
|
|
8341
8764
|
_LABEL: `${TREEVIZ_EXTENSION_BASE_URI}#_LABEL`,
|
|
8342
8765
|
_MILT: `${TREEVIZ_EXTENSION_BASE_URI}#_MILT`,
|
|
8343
8766
|
_MILTID: `${TREEVIZ_EXTENSION_BASE_URI}#_MILTID`,
|
|
@@ -8480,7 +8903,7 @@ var collectExtensionTagsFrom = (node, into = /* @__PURE__ */ new Set()) => {
|
|
|
8480
8903
|
// package.json
|
|
8481
8904
|
var package_default = {
|
|
8482
8905
|
name: "@treeviz/gedcom-parser",
|
|
8483
|
-
version: "2.1.
|
|
8906
|
+
version: "2.1.4"};
|
|
8484
8907
|
|
|
8485
8908
|
// src/utils/get-product-details.ts
|
|
8486
8909
|
var isDevelopment = () => {
|
|
@@ -9883,4 +10306,4 @@ var createEmptyGedcom = (options) => {
|
|
|
9883
10306
|
return gedcom;
|
|
9884
10307
|
};
|
|
9885
10308
|
|
|
9886
|
-
export { ACCEPTED_DATE_FORMATS, ACCEPTED_DATE_FORMATS_REGEX, DEFAULT_GEDCOM_EXPORT_VERSION, GEDCOM7_CALENDARS, GEDCOM7_PEDI_VALUES, GEDCOM7_RESN_VALUES, GEDCOM7_ROLE_VALUES, GEDCOM7_SEX_VALUES, GEDCOM_EXPORT_VERSIONS, GEDCOM_TRAILER_TAG, GEDZIP_EXTENSION, GEDZIP_GEDCOM_ENTRY, GEDZIP_MIME, parser_default as GedcomTree, PEDIGREE_VALUES, PlaceType, TREEVIZ_EXTENSION_BASE_URI, TREEVIZ_EXTENSION_URIS, addFamilyFact, addIndividualFact, addNonEvent, appendGedcomTrailer, applyGedcom7DatePhrases, applyGedcom7Enumerations, applyGedcom7RecordMetadata, attachChildToFamily, attachSpouseToFamily, buildGedzip, buildGedzipBlob, bytesToDataUrl, cacheDiscoveredPath, canAttachAsSpouse, collectExtensionTagsFrom, commonDateFormatter, create, createEmptyGedcom, createGedcomUid, dateFormatter, downloadGedzipMedia, ensureExtensionSchema, extractGedzip, extractGedzipGedcom, extractSeparationYears, extractSplitPoints, familyHasChild, familyHasParent, findMatchingRangeForSplitRange, findReusableParentChildFamily, firstPointerId, formatGedcom7Timestamp, fromTuple, generateSplitRanges, getAllProp, getExtensionSchema, getFamilyWith, getFileExtension, getName, getPlaceParts, getPlaces, getRawSize, getVersion, hungarianOrdinalize, implemented, inRange, inferMediaForm, initializeCache, isDevelopment, isGedcom7, isGedcomTrailerLine, isGedcomTrailerTag, isGedzipContainer, isImageFormat, isIntersectedRange, isObjePointer, isRangeContained, isRemoteOrEmbeddedMediaUrl, makePointer, marriageDateFormatter, mergeMediaLists, nameFormatter, nextRecordId, normalizeGedcomVersion, notImplemented, noteDateFormatter, ordinalize, parseGedcom7CalendarPrefix, parseRangeBounds, pathCache, placeTranslator, pointerIds, profilePictureCache, registerExtensionTag, relativesCache, remountGedzipMediaAsDataUrls, resetRelativesCache, resolveLocalMediaUrl, resolveMediaContent, resolveObjeForm, rewriteGedcomFilePaths, setCauseOfDeath, setChildPedigree, setDeceased, setFamilyMarriage, setLocalMediaResolver, setMediaContentResolver, setNestedGroup, splitOverlappingRanges, splitRange, spouseTagFor, toGedcomPedigree, updateFactRecord, withGedcom7Calendar };
|
|
10309
|
+
export { ACCEPTED_DATE_FORMATS, ACCEPTED_DATE_FORMATS_REGEX, DEFAULT_GEDCOM_EXPORT_VERSION, GEDCOM7_CALENDARS, GEDCOM7_PEDI_VALUES, GEDCOM7_RESN_VALUES, GEDCOM7_ROLE_VALUES, GEDCOM7_SEX_VALUES, GEDCOM_EXPORT_VERSIONS, GEDCOM_TRAILER_TAG, GEDZIP_EXTENSION, GEDZIP_GEDCOM_ENTRY, GEDZIP_MIME, parser_default as GedcomTree, PEDIGREE_VALUES, PlaceType, TREEVIZ_EXTENSION_BASE_URI, TREEVIZ_EXTENSION_URIS, addFamilyFact, addIndividualFact, addNonEvent, appendGedcomTrailer, applyGedcom7DatePhrases, applyGedcom7Enumerations, applyGedcom7RecordMetadata, attachChildToFamily, attachSpouseToFamily, buildGedzip, buildGedzipBlob, bytesToDataUrl, cacheDiscoveredPath, canAttachAsSpouse, collectExtensionTagsFrom, commonDateFormatter, consolidateChildIntoFamily, coupleKeyForFam, create, createEmptyGedcom, createGedcomUid, dateFormatter, deleteIndividual, downloadGedzipMedia, ensureExtensionSchema, extractGedzip, extractGedzipGedcom, extractSeparationYears, extractSplitPoints, familyHasChild, familyHasParent, findDegenerateFamiliesForIndi, findDuplicateCoupleFamiliesForIndi, findMatchingRangeForSplitRange, findReusableParentChildFamily, firstPointerId, formatGedcom7Timestamp, fromTuple, generateSplitRanges, getAllProp, getExtensionSchema, getFamilyWith, getFileExtension, getName, getPlaceParts, getPlaces, getRawSize, getVersion, hungarianOrdinalize, implemented, inRange, inferMediaForm, initializeCache, isDegenerateFamily, isDevelopment, isGedcom7, isGedcomTrailerLine, isGedcomTrailerTag, isGedzipContainer, isImageFormat, isIntersectedRange, isObjePointer, isRangeContained, isRemoteOrEmbeddedMediaUrl, makePointer, marriageDateFormatter, mergeDuplicateCoupleFamilies, mergeMediaLists, nameFormatter, nextRecordId, normalizeGedcomVersion, notImplemented, noteDateFormatter, ordinalize, parseGedcom7CalendarPrefix, parseRangeBounds, pathCache, placeTranslator, pointerIds, profilePictureCache, pruneEmptyFamilies, pruneFamiliesByIds, registerExtensionTag, relativesCache, remountGedzipMediaAsDataUrls, removePointerByValue, resetRelativesCache, resolveLocalMediaUrl, resolveMediaContent, resolveObjeForm, rewriteGedcomFilePaths, setCauseOfDeath, setChildPedigree, setDeceased, setFamilyMarriage, setLocalMediaResolver, setMediaContentResolver, setNestedGroup, splitOverlappingRanges, splitRange, spouseTagFor, toGedcomPedigree, unlinkRelative, updateFactRecord, withGedcom7Calendar };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@treeviz/gedcom-parser",
|
|
3
|
-
"version": "2.1.
|
|
3
|
+
"version": "2.1.4",
|
|
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",
|