gedcom
Version:
a simple and readable gedcom parser
1,499 lines (1,488 loc) • 789 kB
JavaScript
import { createRequire } from "node:module";
//#region rolldown:runtime
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __commonJSMin = (cb, mod) => () => (mod || cb((mod = { exports: {} }).exports, mod), mod.exports);
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (var keys$7 = __getOwnPropNames(from), i = 0, n = keys$7.length, key; i < n; i++) {
key = keys$7[i];
if (!__hasOwnProp.call(to, key) && key !== except) {
__defProp(to, key, {
get: ((k) => from[k]).bind(null, key),
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
});
}
}
}
return to;
};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
value: mod,
enumerable: true
}) : target, mod));
var __require = /* @__PURE__ */ createRequire(import.meta.url);
//#endregion
//#region lib/formal_names.ts
const FORMAL_NAMES = {
ABBR: "ABBREVIATION",
ADDR: "ADDRESS",
ADR1: "ADDRESS1",
ADR2: "ADDRESS2",
ADOP: "ADOPTION",
AFN: "AFN",
AGE: "AGE",
AGNC: "AGENCY",
ALIA: "ALIAS",
ANCE: "ANCESTORS",
ANCI: "ANCES_INTEREST",
ANUL: "ANNULMENT",
ASSO: "ASSOCIATES",
AUTH: "AUTHOR",
BAPL: "BAPTISM-LDS",
BAPM: "BAPTISM",
BARM: "BAR_MITZVAH",
BASM: "BAS_MITZVAH",
BIRT: "BIRTH",
BLES: "BLESSING",
BURI: "BURIAL",
CALN: "CALL_NUMBER",
CAST: "CASTE",
CAUS: "CAUSE",
CENS: "CENSUS",
CHAN: "CHANGE",
CHAR: "CHARACTER",
CHIL: "CHILD",
CHR: "CHRISTENING",
CHRA: "ADULT_CHRISTENING",
CITY: "CITY",
CONC: "CONCATENATION",
CONF: "CONFIRMATION",
CONL: "CONFIRMATION_LDS",
CONT: "CONTINUED",
COPR: "COPYRIGHT",
CORP: "CORPORATE",
CREM: "CREMATION",
CTRY: "COUNTRY",
DATA: "DATA",
DATE: "DATE",
DEAT: "DEATH",
DESC: "DESCENDANTS",
DESI: "DESCENDANT_INT",
DEST: "DESTINATION",
DIV: "DIVORCE",
DIVF: "DIVORCE_FILED",
DSCR: "PHY_DESCRIPTION",
EDUC: "EDUCATION",
EMAI: "EMAIL",
EMIG: "EMIGRATION",
ENDL: "ENDOWMENT",
ENGA: "ENGAGEMENT",
EVEN: "EVENT",
FACT: "FACT",
FAM: "FAMILY",
FAMC: "FAMILY_CHILD",
FAMF: "FAMILY_FILE",
FAMS: "FAMILY_SPOUSE",
FAX: "FACIMILIE",
FCOM: "FIRST_COMMUNICATION",
FILE: "FILE",
FORM: "FORMAT",
FONE: "PHONETIC",
GEDC: "GEDCOM",
GIVN: "GIVEN_NAME",
GRAD: "GRADUATION",
HEAD: "HEADER",
HUSB: "HUSBAND",
IDNO: "IDENT_NUMVER",
IMMI: "IMMIGRATION",
INDI: "INDIVIDUAL",
LANG: "LANGUAGE",
LATI: "LATITUDE",
LONG: "LONGITUDE",
MAP: "MAP",
MARB: "MARRIAGE_BANN",
MARC: "MARRIAGE_CONTRACT",
MARL: "MARRIAGE_LICENSE",
MARR: "MARRIAGE",
MARS: "MARRIAGE_SETTLEMENT",
MEDI: "MEDIA",
NAME: "NAME",
NATI: "NATIONALITY",
NATU: "NATURALIZATION",
NCHI: "CHILDREN_COUNT",
NICK: "NICKNAME",
NMR: "MARRIAGE_COUNT",
NOTE: "NOTE",
NPFX: "NAME_PREFIX",
NSFX: "NAME_SUFFIX",
OBJE: "OBJECT",
OCCU: "OCCUPATION",
ORDI: "ORDINANCE",
ORDN: "ORDINATION",
PAGE: "PAGE",
PEDI: "PEDIGREE",
PHON: "PHONE",
PLAC: "PLACE",
POST: "POSTAL_CODE",
PROB: "PROBATE",
PROP: "PROPERTY",
PUBL: "PUBLICATION",
QUAY: "QUALITY_OF_DATA",
REFN: "REFERENCE",
RELA: "RELATIONSHIP",
RELI: "RELIGION",
REPO: "REPOSITORY",
RESI: "RESIDENCE",
RESN: "RESTRICTION",
RETI: "RETIREMENT",
RFN: "REC_FILE_NUMBER",
RIN: "REC_ID_NUMBER",
ROLE: "ROLE",
ROMN: "ROMANIZED",
SEX: "SEX",
SLGC: "SEALING_CHILD",
SLGS: "SEALING_SPOUCE",
SOUR: "SOURCE",
SPFX: "SURN_PREFIX",
SSN: "SURN_PREFIX",
STAE: "STATE",
STAT: "STATUS",
SUBM: "SUBMITTER",
SUBN: "SUBMISSION",
SURN: "SURNAME",
TEMP: "TEMPLE",
TEXT: "TEXT",
TIME: "TIME",
TITL: "TITLE",
TRLR: "TRAILER",
TYPE: "TYPE",
VERS: "VERSION",
WIFE: "WIFE",
WILL: "WILL",
WWW: "WEB"
};
//#endregion
//#region lib/tokenize.ts
const cDigit = "0-9";
const rLevel = /* @__PURE__ */ new RegExp(`^([${cDigit}]*)`);
const cDelim = /(\s+)/;
const rDelim = /* @__PURE__ */ new RegExp(`^([${cDelim}])`);
const cAt = "@";
const cAlpha = "A-ZÀ-ÿa-z_";
const cAlphanum = `${cAlpha}${cDigit}`;
const cPointerChar = `${cAlpha}${cDigit}${cDelim}#`;
const rPointer = /* @__PURE__ */ new RegExp(`^${cAt}([${cAlphanum}])([${cPointerChar}\\-])*${cAt}`);
const rTag = /* @__PURE__ */ new RegExp(`^(_?[${cAlphanum}]+)`);
const rLineItem = /* @__PURE__ */ new RegExp(/^(.*)/);
/**
* Lowest-level API to parse-gedcom: parses a single line
* of GEDCOM into its constituent tag, level, xref_id,
* and so on. It's unlikely that external applications would use this API.
* Instead they will more often use `parse`.
*
* @param buf - One line of GEDCOM data as a string
* @returns a line object.
*/
function tokenize(buf, lineNumber) {
function expect(re, message) {
const match = buf.match(re);
if (!match) throw new Error(`${message} at line ${lineNumber}`);
buf = buf.substring(match[0].length);
return match[1];
}
buf = buf.trimStart();
let xref_id = void 0;
const levelStr = expect(rLevel, "Expected level");
if (levelStr.length > 2 || levelStr.length === 2 && levelStr[0] === "0") throw new Error(`Invalid level: ${levelStr} at line ${lineNumber}`);
const level = Number.parseInt(levelStr);
expect(rDelim, "Expected delimiter after level");
const xref = buf.match(rPointer);
if (xref) {
xref_id = xref[0];
buf = buf.substring(xref[0].length);
expect(rDelim, "Expected delimiter after pointer");
}
const tag = expect(rTag, "Expected tag");
const line = {
level,
tag
};
if (xref_id) line.xref_id = xref_id;
const plaintext = tag === "CONC" || tag === "CONT" || tag === "NOTE";
const delim = buf.match(rDelim);
if (delim) {
buf = buf.substring(delim[0].length);
const pointer_match = !plaintext && buf.match(rPointer);
const value_match = buf.match(rLineItem);
if (pointer_match) line.pointer = pointer_match[0];
else if (value_match) line.value = value_match[1];
}
return line;
}
//#endregion
//#region lib/parse-to-unist.ts
const rTerminator = /(\r|\n|\r\n|\n\r)/g;
function lineToNode({ tag, value, xref_id, pointer }) {
const node = {
type: tag,
data: {
formal_name: FORMAL_NAMES[tag],
...value !== void 0 ? { value } : {}
},
children: []
};
if (xref_id) node.data.xref_id = xref_id;
if (pointer) node.data.pointer = pointer;
if (tag.startsWith("_")) node.data.custom_tag = true;
return node;
}
function handleContinued({ tag, value, pointer }, head, lineNumber) {
if (!(tag === "CONC" || tag === "CONT")) return false;
if (pointer) throw new Error(`Cannot concatenate a pointer (CONC/CONT cannot have a pointer value) at line ${lineNumber}`);
if (head.data) {
if (!head.data.value) head.data.value = "";
if (tag === "CONT") head.data.value += "\n";
if (value) head.data.value += value;
}
return true;
}
/**
* Parse a string of GEDCOM data into an unist-compatible
* abstract syntax tree. This is the core function for transforming
* GEDCOM into JSON data that captures all of its detail, but
* for practical usage you may also want to run `compact`
* on the generated syntax tree to compress attributes.
*
* **Note**: the AST format uses 'children' to indicate the children
* of abstract syntax tree nodes, but these are not equivalent to
* parent/child relationships in family data.
*
* @param input - GEDCOM data as a string
* @returns ast
*/
function parse(input) {
const root$3 = {
data: {},
type: "root",
children: []
};
const lines = input.split(rTerminator).filter((str) => str.trim());
let stack = [];
let lastLevel = 0;
for (let i = 0; i < lines.length; i++) {
const lineNumber = i + 1;
const tokens = tokenize(lines[i], lineNumber);
if (handleContinued(tokens, stack[stack.length - 1], lineNumber)) continue;
const node = lineToNode(tokens);
const { level } = tokens;
if (level === 0) {
root$3.children.push(node);
stack = [node];
} else if (lastLevel === level - 1 || level <= lastLevel) {
for (let i$1 = 0; i$1 <= lastLevel - level; i$1++) stack.pop();
stack[stack.length - 1].children.push(node);
stack.push(node);
} else throw new Error(`Illegal nesting at line ${lineNumber}: transition from level ${lastLevel} to ${level}`);
lastLevel = level;
}
return root$3;
}
//#endregion
//#region node_modules/.pnpm/unist-util-is@6.0.0/node_modules/unist-util-is/lib/index.js
/**
* Generate an assertion from a test.
*
* Useful if you’re going to test many nodes, for example when creating a
* utility where something else passes a compatible test.
*
* The created function is a bit faster because it expects valid input only:
* a `node`, `index`, and `parent`.
*
* @param {Test} test
* * when nullish, checks if `node` is a `Node`.
* * when `string`, works like passing `(node) => node.type === test`.
* * when `function` checks if function passed the node is true.
* * when `object`, checks that all keys in test are in node, and that they have (strictly) equal values.
* * when `array`, checks if any one of the subtests pass.
* @returns {Check}
* An assertion.
*/
const convert = (function(test) {
if (test === null || test === void 0) return ok;
if (typeof test === "function") return castFactory(test);
if (typeof test === "object") return Array.isArray(test) ? anyFactory(test) : propsFactory(test);
if (typeof test === "string") return typeFactory(test);
throw new Error("Expected function, string, or object as test");
});
/**
* @param {Array<Props | TestFunction | string>} tests
* @returns {Check}
*/
function anyFactory(tests) {
/** @type {Array<Check>} */
const checks = [];
let index = -1;
while (++index < tests.length) checks[index] = convert(tests[index]);
return castFactory(any);
/**
* @this {unknown}
* @type {TestFunction}
*/
function any(...parameters) {
let index$1 = -1;
while (++index$1 < checks.length) if (checks[index$1].apply(this, parameters)) return true;
return false;
}
}
/**
* Turn an object into a test for a node with a certain fields.
*
* @param {Props} check
* @returns {Check}
*/
function propsFactory(check) {
const checkAsRecord = check;
return castFactory(all);
/**
* @param {Node} node
* @returns {boolean}
*/
function all(node) {
const nodeAsRecord = node;
/** @type {string} */
let key;
for (key in check) if (nodeAsRecord[key] !== checkAsRecord[key]) return false;
return true;
}
}
/**
* Turn a string into a test for a node with a certain type.
*
* @param {string} check
* @returns {Check}
*/
function typeFactory(check) {
return castFactory(type);
/**
* @param {Node} node
*/
function type(node) {
return node && node.type === check;
}
}
/**
* Turn a custom test into a test for a node that passes that test.
*
* @param {TestFunction} testFunction
* @returns {Check}
*/
function castFactory(testFunction) {
return check;
/**
* @this {unknown}
* @type {Check}
*/
function check(value, index, parent) {
return Boolean(looksLikeANode(value) && testFunction.call(this, value, typeof index === "number" ? index : void 0, parent || void 0));
}
}
function ok() {
return true;
}
/**
* @param {unknown} value
* @returns {value is Node}
*/
function looksLikeANode(value) {
return value !== null && typeof value === "object" && "type" in value;
}
//#endregion
//#region node_modules/.pnpm/unist-util-remove@4.0.0/node_modules/unist-util-remove/lib/index.js
/**
* @typedef {import('unist').Node} Node
* @typedef {import('unist').Parent} Parent
* @typedef {import('unist-util-is').Test} Test
*/
/**
* @typedef Options
* Configuration.
* @property {boolean | null | undefined} [cascade=true]
* Whether to drop parent nodes if they had children, but all their children
* were filtered out (default: `true`).
*/
/**
* Change the given `tree` by removing all nodes that pass `test`.
*
* `tree` itself is never tested.
* The tree is walked in preorder (NLR), visiting the node itself, then its
* head, etc.
*
* @overload
* @param {Node} node
* @param {Test} [test]
* @returns {undefined}
*
* @overload
* @param {Node} node
* @param {Options | null | undefined} options
* @param {Test} [test]
* @returns {undefined}
*
* @param {Node} tree
* Tree to change.
* @param {Options | Test} options
* Configuration (optional).
* @param {Test} [test]
* `unist-util-is` compatible test.
* @returns {undefined}
* Nothing.
*/
function remove(tree, options, test) {
const is = convert(test || options);
let cascade = true;
if (options && typeof options === "object" && "cascade" in options && typeof options.cascade === "boolean") cascade = options.cascade;
preorder$1(tree);
/**
* Check and remove nodes recursively in preorder.
* For each composite node, modify its children array in-place.
*
* @param {Node} node
* @param {number | undefined} [index]
* @param {Parent | undefined} [parent]
* @returns {boolean}
*/
function preorder$1(node, index, parent) {
if (node !== tree && is(node, index, parent)) return false;
if ("children" in node && Array.isArray(node.children)) {
const nodeAsParent = node;
const children = nodeAsParent.children;
let oldChildIndex = -1;
let newChildIndex = 0;
if (children.length > 0) {
while (++oldChildIndex < children.length) if (preorder$1(children[oldChildIndex], oldChildIndex, nodeAsParent)) children[newChildIndex++] = children[oldChildIndex];
if (node !== tree && cascade && !newChildIndex) return false;
children.length = newChildIndex;
}
}
return true;
}
}
//#endregion
//#region node_modules/.pnpm/unist-util-visit-parents@6.0.1/node_modules/unist-util-visit-parents/lib/color.node.js
/**
* @param {string} d
* @returns {string}
*/
function color(d) {
return "\x1B[33m" + d + "\x1B[39m";
}
//#endregion
//#region node_modules/.pnpm/unist-util-visit-parents@6.0.1/node_modules/unist-util-visit-parents/lib/index.js
/**
* @typedef {import('unist').Node} UnistNode
* @typedef {import('unist').Parent} UnistParent
*/
/**
* @typedef {Exclude<import('unist-util-is').Test, undefined> | undefined} Test
* Test from `unist-util-is`.
*
* Note: we have remove and add `undefined`, because otherwise when generating
* automatic `.d.ts` files, TS tries to flatten paths from a local perspective,
* which doesn’t work when publishing on npm.
*/
/**
* @typedef {(
* Fn extends (value: any) => value is infer Thing
* ? Thing
* : Fallback
* )} Predicate
* Get the value of a type guard `Fn`.
* @template Fn
* Value; typically function that is a type guard (such as `(x): x is Y`).
* @template Fallback
* Value to yield if `Fn` is not a type guard.
*/
/**
* @typedef {(
* Check extends null | undefined // No test.
* ? Value
* : Value extends {type: Check} // String (type) test.
* ? Value
* : Value extends Check // Partial test.
* ? Value
* : Check extends Function // Function test.
* ? Predicate<Check, Value> extends Value
* ? Predicate<Check, Value>
* : never
* : never // Some other test?
* )} MatchesOne
* Check whether a node matches a primitive check in the type system.
* @template Value
* Value; typically unist `Node`.
* @template Check
* Value; typically `unist-util-is`-compatible test, but not arrays.
*/
/**
* @typedef {(
* Check extends Array<any>
* ? MatchesOne<Value, Check[keyof Check]>
* : MatchesOne<Value, Check>
* )} Matches
* Check whether a node matches a check in the type system.
* @template Value
* Value; typically unist `Node`.
* @template Check
* Value; typically `unist-util-is`-compatible test.
*/
/**
* @typedef {0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10} Uint
* Number; capped reasonably.
*/
/**
* @typedef {I extends 0 ? 1 : I extends 1 ? 2 : I extends 2 ? 3 : I extends 3 ? 4 : I extends 4 ? 5 : I extends 5 ? 6 : I extends 6 ? 7 : I extends 7 ? 8 : I extends 8 ? 9 : 10} Increment
* Increment a number in the type system.
* @template {Uint} [I=0]
* Index.
*/
/**
* @typedef {(
* Node extends UnistParent
* ? Node extends {children: Array<infer Children>}
* ? Child extends Children ? Node : never
* : never
* : never
* )} InternalParent
* Collect nodes that can be parents of `Child`.
* @template {UnistNode} Node
* All node types in a tree.
* @template {UnistNode} Child
* Node to search for.
*/
/**
* @typedef {InternalParent<InclusiveDescendant<Tree>, Child>} Parent
* Collect nodes in `Tree` that can be parents of `Child`.
* @template {UnistNode} Tree
* All node types in a tree.
* @template {UnistNode} Child
* Node to search for.
*/
/**
* @typedef {(
* Depth extends Max
* ? never
* :
* | InternalParent<Node, Child>
* | InternalAncestor<Node, InternalParent<Node, Child>, Max, Increment<Depth>>
* )} InternalAncestor
* Collect nodes in `Tree` that can be ancestors of `Child`.
* @template {UnistNode} Node
* All node types in a tree.
* @template {UnistNode} Child
* Node to search for.
* @template {Uint} [Max=10]
* Max; searches up to this depth.
* @template {Uint} [Depth=0]
* Current depth.
*/
/**
* @typedef {InternalAncestor<InclusiveDescendant<Tree>, Child>} Ancestor
* Collect nodes in `Tree` that can be ancestors of `Child`.
* @template {UnistNode} Tree
* All node types in a tree.
* @template {UnistNode} Child
* Node to search for.
*/
/**
* @typedef {(
* Tree extends UnistParent
* ? Depth extends Max
* ? Tree
* : Tree | InclusiveDescendant<Tree['children'][number], Max, Increment<Depth>>
* : Tree
* )} InclusiveDescendant
* Collect all (inclusive) descendants of `Tree`.
*
* > 👉 **Note**: for performance reasons, this seems to be the fastest way to
* > recurse without actually running into an infinite loop, which the
* > previous version did.
* >
* > Practically, a max of `2` is typically enough assuming a `Root` is
* > passed, but it doesn’t improve performance.
* > It gets higher with `List > ListItem > Table > TableRow > TableCell`.
* > Using up to `10` doesn’t hurt or help either.
* @template {UnistNode} Tree
* Tree type.
* @template {Uint} [Max=10]
* Max; searches up to this depth.
* @template {Uint} [Depth=0]
* Current depth.
*/
/**
* @typedef {'skip' | boolean} Action
* Union of the action types.
*
* @typedef {number} Index
* Move to the sibling at `index` next (after node itself is completely
* traversed).
*
* Useful if mutating the tree, such as removing the node the visitor is
* currently on, or any of its previous siblings.
* Results less than 0 or greater than or equal to `children.length` stop
* traversing the parent.
*
* @typedef {[(Action | null | undefined | void)?, (Index | null | undefined)?]} ActionTuple
* List with one or two values, the first an action, the second an index.
*
* @typedef {Action | ActionTuple | Index | null | undefined | void} VisitorResult
* Any value that can be returned from a visitor.
*/
/**
* @callback Visitor
* Handle a node (matching `test`, if given).
*
* Visitors are free to transform `node`.
* They can also transform the parent of node (the last of `ancestors`).
*
* Replacing `node` itself, if `SKIP` is not returned, still causes its
* descendants to be walked (which is a bug).
*
* When adding or removing previous siblings of `node` (or next siblings, in
* case of reverse), the `Visitor` should return a new `Index` to specify the
* sibling to traverse after `node` is traversed.
* Adding or removing next siblings of `node` (or previous siblings, in case
* of reverse) is handled as expected without needing to return a new `Index`.
*
* Removing the children property of an ancestor still results in them being
* traversed.
* @param {Visited} node
* Found node.
* @param {Array<VisitedParents>} ancestors
* Ancestors of `node`.
* @returns {VisitorResult}
* What to do next.
*
* An `Index` is treated as a tuple of `[CONTINUE, Index]`.
* An `Action` is treated as a tuple of `[Action]`.
*
* Passing a tuple back only makes sense if the `Action` is `SKIP`.
* When the `Action` is `EXIT`, that action can be returned.
* When the `Action` is `CONTINUE`, `Index` can be returned.
* @template {UnistNode} [Visited=UnistNode]
* Visited node type.
* @template {UnistParent} [VisitedParents=UnistParent]
* Ancestor type.
*/
/**
* @typedef {Visitor<Matches<InclusiveDescendant<Tree>, Check>, Ancestor<Tree, Matches<InclusiveDescendant<Tree>, Check>>>} BuildVisitor
* Build a typed `Visitor` function from a tree and a test.
*
* It will infer which values are passed as `node` and which as `parents`.
* @template {UnistNode} [Tree=UnistNode]
* Tree type.
* @template {Test} [Check=Test]
* Test type.
*/
/** @type {Readonly<ActionTuple>} */
const empty = [];
/**
* Continue traversing as normal.
*/
const CONTINUE = true;
/**
* Stop traversing immediately.
*/
const EXIT = false;
/**
* Do not traverse this node’s children.
*/
const SKIP = "skip";
/**
* Visit nodes, with ancestral information.
*
* This algorithm performs *depth-first* *tree traversal* in *preorder*
* (**NLR**) or if `reverse` is given, in *reverse preorder* (**NRL**).
*
* You can choose for which nodes `visitor` is called by passing a `test`.
* For complex tests, you should test yourself in `visitor`, as it will be
* faster and will have improved type information.
*
* Walking the tree is an intensive task.
* Make use of the return values of the visitor when possible.
* Instead of walking a tree multiple times, walk it once, use `unist-util-is`
* to check if a node matches, and then perform different operations.
*
* You can change the tree.
* See `Visitor` for more info.
*
* @overload
* @param {Tree} tree
* @param {Check} check
* @param {BuildVisitor<Tree, Check>} visitor
* @param {boolean | null | undefined} [reverse]
* @returns {undefined}
*
* @overload
* @param {Tree} tree
* @param {BuildVisitor<Tree>} visitor
* @param {boolean | null | undefined} [reverse]
* @returns {undefined}
*
* @param {UnistNode} tree
* Tree to traverse.
* @param {Visitor | Test} test
* `unist-util-is`-compatible test
* @param {Visitor | boolean | null | undefined} [visitor]
* Handle each node.
* @param {boolean | null | undefined} [reverse]
* Traverse in reverse preorder (NRL) instead of the default preorder (NLR).
* @returns {undefined}
* Nothing.
*
* @template {UnistNode} Tree
* Node type.
* @template {Test} Check
* `unist-util-is`-compatible test.
*/
function visitParents(tree, test, visitor, reverse) {
/** @type {Test} */
let check;
if (typeof test === "function" && typeof visitor !== "function") {
reverse = visitor;
visitor = test;
} else check = test;
const is = convert(check);
const step = reverse ? -1 : 1;
factory(tree, void 0, [])();
/**
* @param {UnistNode} node
* @param {number | undefined} index
* @param {Array<UnistParent>} parents
*/
function factory(node, index, parents) {
const value = node && typeof node === "object" ? node : {};
if (typeof value.type === "string") {
const name = typeof value.tagName === "string" ? value.tagName : typeof value.name === "string" ? value.name : void 0;
Object.defineProperty(visit, "name", { value: "node (" + color(node.type + (name ? "<" + name + ">" : "")) + ")" });
}
return visit;
function visit() {
/** @type {Readonly<ActionTuple>} */
let result = empty;
/** @type {Readonly<ActionTuple>} */
let subresult;
/** @type {number} */
let offset;
/** @type {Array<UnistParent>} */
let grandparents;
if (!test || is(node, index, parents[parents.length - 1] || void 0)) {
result = toResult(visitor(node, parents));
if (result[0] === EXIT) return result;
}
if ("children" in node && node.children) {
const nodeAsParent = node;
if (nodeAsParent.children && result[0] !== SKIP) {
offset = (reverse ? nodeAsParent.children.length : -1) + step;
grandparents = parents.concat(nodeAsParent);
while (offset > -1 && offset < nodeAsParent.children.length) {
const child = nodeAsParent.children[offset];
subresult = factory(child, offset, grandparents)();
if (subresult[0] === EXIT) return subresult;
offset = typeof subresult[1] === "number" ? subresult[1] : offset + step;
}
}
}
return result;
}
}
}
/**
* Turn a return value into a clean result.
*
* @param {VisitorResult} value
* Valid return values from visitors.
* @returns {Readonly<ActionTuple>}
* Clean result.
*/
function toResult(value) {
if (Array.isArray(value)) return value;
if (typeof value === "number") return [CONTINUE, value];
return value === null || value === void 0 ? empty : [value];
}
//#endregion
//#region lib/unist-compact.ts
function addValue(data, path, value) {
if (!data[path]) data[path] = value;
else data["+" + path] = (data["+" + path] || []).concat(value);
}
/**
* This applies an opinionated transformation to GEDCOM data,
* making it easier for common use cases. In the raw GEDCOM
* AST, attributes like birth years are represented as nodes.
* This transformation compresses those attributes into properties
* of a node’s `.data` member.
*
* Here's how this transformation works:
*
* For example, let's say you have this content:
*
* ```
* 0 INDI
* 1 BIRT
* 2 DATE 12 MAY 1920
* 1 DEAT
* 2 DATE 1960
* ```
*
* The output of `parse` will create nodes for the INDI, BIRT, DATE,
* DEAT, and DATE objects. If you simply want to ask 'when was this individual
* alive?' This can be a difficult question to answer. Compact will transform
* those nodes into a simplified form:
*
* ```js
* {
* type: "INDI",
* data: {
* formal_name: "INDIVIDUAL",
* "BIRTH/DATE": "12 MAY 1920",
* "DEATH/DATE": "1960",
* },
* value: undefined,
* children: [],
* }
* ```
*
* If there are multiple values for something like a birth date, they'll be
* included in an additional property with a `+`:
*
* {
* "BIRTH/DATE": "12 MAY 1920",
* "+BIRTH/DATE": ["13 MAY 1920"],
* }
*
* This also removes nodes from the syntax tree that are unlikely
* to have any use for genealogical or visualization applications.
*
* @param root - a parsed GEDCOM document
* @param removeNodes - a list of nodes that should be removed.
* @returns the same document, with attributes compacted.
*/
function compact(root$3, removeNodes = [
"TRLR",
"SUBM",
"SUBN",
"HEAD",
"NOTE",
"SOUR"
]) {
remove(root$3, removeNodes);
for (const child of root$3.children) {
if (!child.data) child.data = {};
visitParents(child, (node, ancestors) => {
const path = ancestors.slice(1).concat(node).map((a) => a.data?.formal_name || a.type).join("/");
if (node.data?.value) addValue(child.data, path, node.data.value);
else if (node.data?.pointer) addValue(child.data, `@${path}`, node.data.pointer);
});
child.children = [];
}
return root$3;
}
//#endregion
//#region lib/to-d3-force.ts
function removeBidirectionals(linkIndex, links) {
const pairs = [
["@HUSBAND", "@FAMILY_SPOUSE"],
["@WIFE", "@FAMILY_SPOUSE"],
["@FAMILY_CHILD", "@CHILD"]
];
for (const [_$15, group] of linkIndex) for (const pair of pairs) {
const [a, b] = pair.map((key) => group.find((elem) => elem.value === key));
if (a && b) links.splice(links.indexOf(a), 1);
}
}
/**
* Transforms a GEDCOM AST - likely produced using
* `parse` - into a data structure suited for
* a [D3 force directed graph](https://observablehq.com/@d3/force-directed-graph)
* layout.
*
* @param root - Parsed GEDCOM content
* @returns D3-friendly JSON
*/
function toD3Force(root$3) {
const nodes = compact(root$3).children;
const index = new Set(nodes.map((child) => child.data?.xref_id).filter(Boolean));
const links = [];
const linkIndex = /* @__PURE__ */ new Map();
for (const node of nodes) {
if (!node.data) continue;
for (const [key, value] of Object.entries(node.data).filter(([key$1, _$15]) => key$1.startsWith("@"))) {
if (!index.has(value)) throw new Error(`Undefined reference: ${value}`);
if (!node.data?.xref_id) throw new Error(`Link from node with no xref id`);
const source = node.data?.xref_id;
const target = value;
const link = {
source,
target,
value: key
};
links.push(link);
const idxKey = [source, target].sort().join("/");
if (!linkIndex.has(idxKey)) linkIndex.set(idxKey, [link]);
else linkIndex.get(idxKey).push(link);
}
}
removeBidirectionals(linkIndex, links);
return {
nodes,
links
};
}
//#endregion
//#region node_modules/.pnpm/lodash@4.17.21/node_modules/lodash/lodash.js
var require_lodash$2 = /* @__PURE__ */ __commonJSMin(((exports, module) => {
(function() {
/** Used as a safe reference for `undefined` in pre-ES5 environments. */
var undefined$1;
/** Used as the semantic version number. */
var VERSION = "4.17.21";
/** Used as the size to enable large array optimizations. */
var LARGE_ARRAY_SIZE$2 = 200;
/** Error message constants. */
var CORE_ERROR_TEXT = "Unsupported core-js use. Try https://npms.io/search?q=ponyfill.", FUNC_ERROR_TEXT$1 = "Expected a function", INVALID_TEMPL_VAR_ERROR_TEXT = "Invalid `variable` option passed into `_.template`";
/** Used to stand-in for `undefined` hash values. */
var HASH_UNDEFINED$3 = "__lodash_hash_undefined__";
/** Used as the maximum memoize cache size. */
var MAX_MEMOIZE_SIZE$1 = 500;
/** Used as the internal argument placeholder. */
var PLACEHOLDER = "__lodash_placeholder__";
/** Used to compose bitmasks for cloning. */
var CLONE_DEEP_FLAG$1 = 1, CLONE_FLAT_FLAG$1 = 2, CLONE_SYMBOLS_FLAG$2 = 4;
/** Used to compose bitmasks for value comparisons. */
var COMPARE_PARTIAL_FLAG$6 = 1, COMPARE_UNORDERED_FLAG$4 = 2;
/** Used to compose bitmasks for function metadata. */
var WRAP_BIND_FLAG = 1, WRAP_BIND_KEY_FLAG = 2, WRAP_CURRY_BOUND_FLAG = 4, WRAP_CURRY_FLAG = 8, WRAP_CURRY_RIGHT_FLAG = 16, WRAP_PARTIAL_FLAG = 32, WRAP_PARTIAL_RIGHT_FLAG = 64, WRAP_ARY_FLAG = 128, WRAP_REARG_FLAG = 256, WRAP_FLIP_FLAG = 512;
/** Used as default options for `_.truncate`. */
var DEFAULT_TRUNC_LENGTH = 30, DEFAULT_TRUNC_OMISSION = "...";
/** Used to detect hot functions by number of calls within a span of milliseconds. */
var HOT_COUNT$1 = 800, HOT_SPAN$1 = 16;
/** Used to indicate the type of lazy iteratees. */
var LAZY_FILTER_FLAG = 1, LAZY_MAP_FLAG = 2, LAZY_WHILE_FLAG = 3;
/** Used as references for various `Number` constants. */
var INFINITY$2 = Infinity, MAX_SAFE_INTEGER$2 = 9007199254740991, MAX_INTEGER = 17976931348623157e292, NAN = NaN;
/** Used as references for the maximum length and index of an array. */
var MAX_ARRAY_LENGTH = 4294967295, MAX_ARRAY_INDEX = MAX_ARRAY_LENGTH - 1, HALF_MAX_ARRAY_LENGTH = MAX_ARRAY_LENGTH >>> 1;
/** Used to associate wrap methods with their bit flags. */
var wrapFlags = [
["ary", WRAP_ARY_FLAG],
["bind", WRAP_BIND_FLAG],
["bindKey", WRAP_BIND_KEY_FLAG],
["curry", WRAP_CURRY_FLAG],
["curryRight", WRAP_CURRY_RIGHT_FLAG],
["flip", WRAP_FLIP_FLAG],
["partial", WRAP_PARTIAL_FLAG],
["partialRight", WRAP_PARTIAL_RIGHT_FLAG],
["rearg", WRAP_REARG_FLAG]
];
/** `Object#toString` result references. */
var argsTag$4 = "[object Arguments]", arrayTag$3 = "[object Array]", asyncTag$1 = "[object AsyncFunction]", boolTag$4 = "[object Boolean]", dateTag$4 = "[object Date]", domExcTag = "[object DOMException]", errorTag$3 = "[object Error]", funcTag$3 = "[object Function]", genTag$2 = "[object GeneratorFunction]", mapTag$8 = "[object Map]", numberTag$4 = "[object Number]", nullTag$1 = "[object Null]", objectTag$4 = "[object Object]", promiseTag$1 = "[object Promise]", proxyTag$1 = "[object Proxy]", regexpTag$4 = "[object RegExp]", setTag$8 = "[object Set]", stringTag$5 = "[object String]", symbolTag$4 = "[object Symbol]", undefinedTag$1 = "[object Undefined]", weakMapTag$3 = "[object WeakMap]", weakSetTag = "[object WeakSet]";
var arrayBufferTag$4 = "[object ArrayBuffer]", dataViewTag$5 = "[object DataView]", float32Tag$3 = "[object Float32Array]", float64Tag$3 = "[object Float64Array]", int8Tag$3 = "[object Int8Array]", int16Tag$3 = "[object Int16Array]", int32Tag$3 = "[object Int32Array]", uint8Tag$3 = "[object Uint8Array]", uint8ClampedTag$3 = "[object Uint8ClampedArray]", uint16Tag$3 = "[object Uint16Array]", uint32Tag$3 = "[object Uint32Array]";
/** Used to match empty string literals in compiled template source. */
var reEmptyStringLeading = /\b__p \+= '';/g, reEmptyStringMiddle = /\b(__p \+=) '' \+/g, reEmptyStringTrailing = /(__e\(.*?\)|\b__t\)) \+\n'';/g;
/** Used to match HTML entities and HTML characters. */
var reEscapedHtml = /&(?:amp|lt|gt|quot|#39);/g, reUnescapedHtml = /[&<>"']/g, reHasEscapedHtml = RegExp(reEscapedHtml.source), reHasUnescapedHtml = RegExp(reUnescapedHtml.source);
/** Used to match template delimiters. */
var reEscape = /<%-([\s\S]+?)%>/g, reEvaluate = /<%([\s\S]+?)%>/g, reInterpolate = /<%=([\s\S]+?)%>/g;
/** Used to match property names within property paths. */
var reIsDeepProp$1 = /\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/, reIsPlainProp$1 = /^\w*$/, rePropName$1 = /[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(?:\.|\[\])(?:\.|\[\]|$))/g;
/**
* Used to match `RegExp`
* [syntax characters](http://ecma-international.org/ecma-262/7.0/#sec-patterns).
*/
var reRegExpChar$1 = /[\\^$.*+?()[\]{}|]/g, reHasRegExpChar = RegExp(reRegExpChar$1.source);
/** Used to match leading whitespace. */
var reTrimStart = /^\s+/;
/** Used to match a single whitespace character. */
var reWhitespace = /\s/;
/** Used to match wrap detail comments. */
var reWrapComment = /\{(?:\n\/\* \[wrapped with .+\] \*\/)?\n?/, reWrapDetails = /\{\n\/\* \[wrapped with (.+)\] \*/, reSplitDetails = /,? & /;
/** Used to match words composed of alphanumeric characters. */
var reAsciiWord = /[^\x00-\x2f\x3a-\x40\x5b-\x60\x7b-\x7f]+/g;
/**
* Used to validate the `validate` option in `_.template` variable.
*
* Forbids characters which could potentially change the meaning of the function argument definition:
* - "()," (modification of function parameters)
* - "=" (default value)
* - "[]{}" (destructuring of function parameters)
* - "/" (beginning of a comment)
* - whitespace
*/
var reForbiddenIdentifierChars = /[()=,{}\[\]\/\s]/;
/** Used to match backslashes in property paths. */
var reEscapeChar$1 = /\\(\\)?/g;
/**
* Used to match
* [ES template delimiters](http://ecma-international.org/ecma-262/7.0/#sec-template-literal-lexical-components).
*/
var reEsTemplate = /\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g;
/** Used to match `RegExp` flags from their coerced string values. */
var reFlags$1 = /\w*$/;
/** Used to detect bad signed hexadecimal string values. */
var reIsBadHex = /^[-+]0x[0-9a-f]+$/i;
/** Used to detect binary string values. */
var reIsBinary = /^0b[01]+$/i;
/** Used to detect host constructors (Safari). */
var reIsHostCtor$1 = /^\[object .+?Constructor\]$/;
/** Used to detect octal string values. */
var reIsOctal = /^0o[0-7]+$/i;
/** Used to detect unsigned integer values. */
var reIsUint$1 = /^(?:0|[1-9]\d*)$/;
/** Used to match Latin Unicode letters (excluding mathematical operators). */
var reLatin = /[\xc0-\xd6\xd8-\xf6\xf8-\xff\u0100-\u017f]/g;
/** Used to ensure capturing order of template delimiters. */
var reNoMatch = /($^)/;
/** Used to match unescaped characters in compiled string literals. */
var reUnescapedString = /['\n\r\u2028\u2029\\]/g;
/** Used to compose unicode character classes. */
var rsAstralRange$1 = "\\ud800-\\udfff", rsComboRange$1 = "\\u0300-\\u036f\\ufe20-\\ufe2f\\u20d0-\\u20ff", rsDingbatRange = "\\u2700-\\u27bf", rsLowerRange = "a-z\\xdf-\\xf6\\xf8-\\xff", rsMathOpRange = "\\xac\\xb1\\xd7\\xf7", rsNonCharRange = "\\x00-\\x2f\\x3a-\\x40\\x5b-\\x60\\x7b-\\xbf", rsPunctuationRange = "\\u2000-\\u206f", rsSpaceRange = " \\t\\x0b\\f\\xa0\\ufeff\\n\\r\\u2028\\u2029\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000", rsUpperRange = "A-Z\\xc0-\\xd6\\xd8-\\xde", rsVarRange$1 = "\\ufe0e\\ufe0f", rsBreakRange = rsMathOpRange + rsNonCharRange + rsPunctuationRange + rsSpaceRange;
/** Used to compose unicode capture groups. */
var rsApos = "['’]", rsAstral$1 = "[" + rsAstralRange$1 + "]", rsBreak = "[" + rsBreakRange + "]", rsCombo$1 = "[" + rsComboRange$1 + "]", rsDigits = "\\d+", rsDingbat = "[" + rsDingbatRange + "]", rsLower = "[" + rsLowerRange + "]", rsMisc = "[^" + rsAstralRange$1 + rsBreakRange + rsDigits + rsDingbatRange + rsLowerRange + rsUpperRange + "]", rsFitz$1 = "\\ud83c[\\udffb-\\udfff]", rsModifier$1 = "(?:" + rsCombo$1 + "|" + rsFitz$1 + ")", rsNonAstral$1 = "[^" + rsAstralRange$1 + "]", rsRegional$1 = "(?:\\ud83c[\\udde6-\\uddff]){2}", rsSurrPair$1 = "[\\ud800-\\udbff][\\udc00-\\udfff]", rsUpper = "[" + rsUpperRange + "]", rsZWJ$1 = "\\u200d";
/** Used to compose unicode regexes. */
var rsMiscLower = "(?:" + rsLower + "|" + rsMisc + ")", rsMiscUpper = "(?:" + rsUpper + "|" + rsMisc + ")", rsOptContrLower = "(?:" + rsApos + "(?:d|ll|m|re|s|t|ve))?", rsOptContrUpper = "(?:" + rsApos + "(?:D|LL|M|RE|S|T|VE))?", reOptMod$1 = rsModifier$1 + "?", rsOptVar$1 = "[" + rsVarRange$1 + "]?", rsOptJoin$1 = "(?:" + rsZWJ$1 + "(?:" + [
rsNonAstral$1,
rsRegional$1,
rsSurrPair$1
].join("|") + ")" + rsOptVar$1 + reOptMod$1 + ")*", rsOrdLower = "\\d*(?:1st|2nd|3rd|(?![123])\\dth)(?=\\b|[A-Z_])", rsOrdUpper = "\\d*(?:1ST|2ND|3RD|(?![123])\\dTH)(?=\\b|[a-z_])", rsSeq$1 = rsOptVar$1 + reOptMod$1 + rsOptJoin$1, rsEmoji = "(?:" + [
rsDingbat,
rsRegional$1,
rsSurrPair$1
].join("|") + ")" + rsSeq$1, rsSymbol$1 = "(?:" + [
rsNonAstral$1 + rsCombo$1 + "?",
rsCombo$1,
rsRegional$1,
rsSurrPair$1,
rsAstral$1
].join("|") + ")";
/** Used to match apostrophes. */
var reApos = RegExp(rsApos, "g");
/**
* Used to match [combining diacritical marks](https://en.wikipedia.org/wiki/Combining_Diacritical_Marks) and
* [combining diacritical marks for symbols](https://en.wikipedia.org/wiki/Combining_Diacritical_Marks_for_Symbols).
*/
var reComboMark = RegExp(rsCombo$1, "g");
/** Used to match [string symbols](https://mathiasbynens.be/notes/javascript-unicode). */
var reUnicode$1 = RegExp(rsFitz$1 + "(?=" + rsFitz$1 + ")|" + rsSymbol$1 + rsSeq$1, "g");
/** Used to match complex or compound words. */
var reUnicodeWord = RegExp([
rsUpper + "?" + rsLower + "+" + rsOptContrLower + "(?=" + [
rsBreak,
rsUpper,
"$"
].join("|") + ")",
rsMiscUpper + "+" + rsOptContrUpper + "(?=" + [
rsBreak,
rsUpper + rsMiscLower,
"$"
].join("|") + ")",
rsUpper + "?" + rsMiscLower + "+" + rsOptContrLower,
rsUpper + "+" + rsOptContrUpper,
rsOrdUpper,
rsOrdLower,
rsDigits,
rsEmoji
].join("|"), "g");
/** Used to detect strings with [zero-width joiners or code points from the astral planes](http://eev.ee/blog/2015/09/12/dark-corners-of-unicode/). */
var reHasUnicode$1 = RegExp("[" + rsZWJ$1 + rsAstralRange$1 + rsComboRange$1 + rsVarRange$1 + "]");
/** Used to detect strings that need a more robust regexp to match words. */
var reHasUnicodeWord = /[a-z][A-Z]|[A-Z]{2}[a-z]|[0-9][a-zA-Z]|[a-zA-Z][0-9]|[^a-zA-Z0-9 ]/;
/** Used to assign default `context` object properties. */
var contextProps = [
"Array",
"Buffer",
"DataView",
"Date",
"Error",
"Float32Array",
"Float64Array",
"Function",
"Int8Array",
"Int16Array",
"Int32Array",
"Map",
"Math",
"Object",
"Promise",
"RegExp",
"Set",
"String",
"Symbol",
"TypeError",
"Uint8Array",
"Uint8ClampedArray",
"Uint16Array",
"Uint32Array",
"WeakMap",
"_",
"clearTimeout",
"isFinite",
"parseInt",
"setTimeout"
];
/** Used to make template sourceURLs easier to identify. */
var templateCounter = -1;
/** Used to identify `toStringTag` values of typed arrays. */
var typedArrayTags$1 = {};
typedArrayTags$1[float32Tag$3] = typedArrayTags$1[float64Tag$3] = typedArrayTags$1[int8Tag$3] = typedArrayTags$1[int16Tag$3] = typedArrayTags$1[int32Tag$3] = typedArrayTags$1[uint8Tag$3] = typedArrayTags$1[uint8ClampedTag$3] = typedArrayTags$1[uint16Tag$3] = typedArrayTags$1[uint32Tag$3] = true;
typedArrayTags$1[argsTag$4] = typedArrayTags$1[arrayTag$3] = typedArrayTags$1[arrayBufferTag$4] = typedArrayTags$1[boolTag$4] = typedArrayTags$1[dataViewTag$5] = typedArrayTags$1[dateTag$4] = typedArrayTags$1[errorTag$3] = typedArrayTags$1[funcTag$3] = typedArrayTags$1[mapTag$8] = typedArrayTags$1[numberTag$4] = typedArrayTags$1[objectTag$4] = typedArrayTags$1[regexpTag$4] = typedArrayTags$1[setTag$8] = typedArrayTags$1[stringTag$5] = typedArrayTags$1[weakMapTag$3] = false;
/** Used to identify `toStringTag` values supported by `_.clone`. */
var cloneableTags$1 = {};
cloneableTags$1[argsTag$4] = cloneableTags$1[arrayTag$3] = cloneableTags$1[arrayBufferTag$4] = cloneableTags$1[dataViewTag$5] = cloneableTags$1[boolTag$4] = cloneableTags$1[dateTag$4] = cloneableTags$1[float32Tag$3] = cloneableTags$1[float64Tag$3] = cloneableTags$1[int8Tag$3] = cloneableTags$1[int16Tag$3] = cloneableTags$1[int32Tag$3] = cloneableTags$1[mapTag$8] = cloneableTags$1[numberTag$4] = cloneableTags$1[objectTag$4] = cloneableTags$1[regexpTag$4] = cloneableTags$1[setTag$8] = cloneableTags$1[stringTag$5] = cloneableTags$1[symbolTag$4] = cloneableTags$1[uint8Tag$3] = cloneableTags$1[uint8ClampedTag$3] = cloneableTags$1[uint16Tag$3] = cloneableTags$1[uint32Tag$3] = true;
cloneableTags$1[errorTag$3] = cloneableTags$1[funcTag$3] = cloneableTags$1[weakMapTag$3] = false;
/** Used to map Latin Unicode letters to basic Latin letters. */
var deburredLetters = {
"À": "A",
"Á": "A",
"Â": "A",
"Ã": "A",
"Ä": "A",
"Å": "A",
"à": "a",
"á": "a",
"â": "a",
"ã": "a",
"ä": "a",
"å": "a",
"Ç": "C",
"ç": "c",
"Ð": "D",
"ð": "d",
"È": "E",
"É": "E",
"Ê": "E",
"Ë": "E",
"è": "e",
"é": "e",
"ê": "e",
"ë": "e",
"Ì": "I",
"Í": "I",
"Î": "I",
"Ï": "I",
"ì": "i",
"í": "i",
"î": "i",
"ï": "i",
"Ñ": "N",
"ñ": "n",
"Ò": "O",
"Ó": "O",
"Ô": "O",
"Õ": "O",
"Ö": "O",
"Ø": "O",
"ò": "o",
"ó": "o",
"ô": "o",
"õ": "o",
"ö": "o",
"ø": "o",
"Ù": "U",
"Ú": "U",
"Û": "U",
"Ü": "U",
"ù": "u",
"ú": "u",
"û": "u",
"ü": "u",
"Ý": "Y",
"ý": "y",
"ÿ": "y",
"Æ": "Ae",
"æ": "ae",
"Þ": "Th",
"þ": "th",
"ß": "ss",
"Ā": "A",
"Ă": "A",
"Ą": "A",
"ā": "a",
"ă": "a",
"ą": "a",
"Ć": "C",
"Ĉ": "C",
"Ċ": "C",
"Č": "C",
"ć": "c",
"ĉ": "c",
"ċ": "c",
"č": "c",
"Ď": "D",
"Đ": "D",
"ď": "d",
"đ": "d",
"Ē": "E",
"Ĕ": "E",
"Ė": "E",
"Ę": "E",
"Ě": "E",
"ē": "e",
"ĕ": "e",
"ė": "e",
"ę": "e",
"ě": "e",
"Ĝ": "G",
"Ğ": "G",
"Ġ": "G",
"Ģ": "G",
"ĝ": "g",
"ğ": "g",
"ġ": "g",
"ģ": "g",
"Ĥ": "H",
"Ħ": "H",
"ĥ": "h",
"ħ": "h",
"Ĩ": "I",
"Ī": "I",
"Ĭ": "I",
"Į": "I",
"İ": "I",
"ĩ": "i",
"ī": "i",
"ĭ": "i",
"į": "i",
"ı": "i",
"Ĵ": "J",
"ĵ": "j",
"Ķ": "K",
"ķ": "k",
"ĸ": "k",
"Ĺ": "L",
"Ļ": "L",
"Ľ": "L",
"Ŀ": "L",
"Ł": "L",
"ĺ": "l",
"ļ": "l",
"ľ": "l",
"ŀ": "l",
"ł": "l",
"Ń": "N",
"Ņ": "N",
"Ň": "N",
"Ŋ": "N",
"ń": "n",
"ņ": "n",
"ň": "n",
"ŋ": "n",
"Ō": "O",
"Ŏ": "O",
"Ő": "O",
"ō": "o",
"ŏ": "o",
"ő": "o",
"Ŕ": "R",
"Ŗ": "R",
"Ř": "R",
"ŕ": "r",
"ŗ": "r",
"ř": "r",
"Ś": "S",
"Ŝ": "S",
"Ş": "S",
"Š": "S",
"ś": "s",
"ŝ": "s",
"ş": "s",
"š": "s",
"Ţ": "T",
"Ť": "T",
"Ŧ": "T",
"ţ": "t",
"ť": "t",
"ŧ": "t",
"Ũ": "U",
"Ū": "U",
"Ŭ": "U",
"Ů": "U",
"Ű": "U",
"Ų": "U",
"ũ": "u",
"ū": "u",
"ŭ": "u",
"ů": "u",
"ű": "u",
"ų": "u",
"Ŵ": "W",
"ŵ": "w",
"Ŷ": "Y",
"ŷ": "y",
"Ÿ": "Y",
"Ź": "Z",
"Ż": "Z",
"Ž": "Z",
"ź": "z",
"ż": "z",
"ž": "z",
"IJ": "IJ",
"ij": "ij",
"Œ": "Oe",
"œ": "oe",
"ʼn": "'n",
"ſ": "s"
};
/** Used to map characters to HTML entities. */
var htmlEscapes = {
"&": "&",
"<": "<",
">": ">",
"\"": """,
"'": "'"
};
/** Used to map HTML entities to characters. */
var htmlUnescapes = {
"&": "&",
"<": "<",
">": ">",
""": "\"",
"'": "'"
};
/** Used to escape characters for inclusion in compiled string literals. */
var stringEscapes = {
"\\": "\\",
"'": "'",
"\n": "n",
"\r": "r",
"\u2028": "u2028",
"\u2029": "u2029"
};
/** Built-in method references without a dependency on `root`. */
var freeParseFloat = parseFloat, freeParseInt = parseInt;
/** Detect free variable `global` from Node.js. */
var freeGlobal$3 = typeof global == "object" && global && global.Object === Object && global;
/** Detect free variable `self`. */
var freeSelf$1 = typeof self == "object" && self && self.Object === Object && self;
/** Used as a reference to the global object. */
var root$3 = freeGlobal$3 || freeSelf$1 || Function("return this")();
/** Detect free variable `exports`. */
var freeExports$3 = typeof exports == "object" && exports && !exports.nodeType && exports;
/** Detect free variable `module`. */
var freeModule$3 = freeExports$3 && typeof module == "object" && module && !module.nodeType && module;
/** Detect the popular CommonJS extension `module.exports`. */
var moduleExports = freeModule$3 && freeModule$3.exports === freeExports$3;
/** Detect free variable `process` from Node.js. */
var freeProcess$1 = moduleExports && freeGlobal$3.process;
/** Used to access faster Node.js helpers. */
var nodeUtil$4 = function() {
try {
var types = freeModule$3 && freeModule$3.require && freeModule$3.require("util").types;
if (types) return types;
return freeProcess$1 && freeProcess$1.binding && freeProcess$1.binding("util");
} catch (e) {}
}();
var nodeIsArrayBuffer = nodeUtil$4 && nodeUtil$4.isArrayBuffer, nodeIsDate = nodeUtil$4 && nodeUtil$4.isDate, nodeIsMap$1 = nodeUtil$4 && nodeUtil$4.isMap, nodeIsRegExp = nodeUtil$4 && nodeUtil$4.isRegExp, nodeIsSet$1 = nodeUtil$4 && nodeUtil$4.isSet, nodeIsTypedArray$1 = nodeUtil$4 && nodeUtil$4.isTypedArray;
/**
* A faster alternative to `Function#apply`, this function invokes `func`
* with the `this` binding of `thisArg` and the arguments of `args`.
*
* @private
* @param {Function} func The function to invoke.
* @param {*} thisArg The `this` binding of `func`.
* @param {Array} args The arguments to invoke `func` with.
* @returns {*} Returns the result of `func`.
*/
function apply$2(func, thisArg, args) {
switch (args.length) {
case 0: return func.call(thisArg);
case 1: return func.call(thisArg, args[0]);
case 2: return func.call(thisArg, args[0], args[1]);
case 3: return func.call(thisArg, args[0], args[1], args[2]);
}
return func.apply(thisArg, args);
}
/**
* A specialized version of `baseAggregator` for arrays.
*
* @private
* @param {Array} [array] The array to iterate over.
* @param {Function} setter The function to set `accumulator` values.
* @param {Function} iteratee The iteratee to transform keys.
* @param {Object} accumulator The initial aggregated object.
* @returns {Function} Returns `accumulator`.
*/
function arrayAggregator(array, setter, iteratee, accumulator) {
var index = -1, length = array == null ? 0 : array.length;
while (++index < length) {
var value = array[index];
setter(accumulator, value, iteratee(value), array);
}
return accumulator;
}
/**
* A specialized version of `_.forEach` for arrays without support for
* iteratee shorthands.
*
* @private
* @param {Array} [array] The array to iterate over.
* @param {Function} iteratee The function invoked per iteration.
* @returns {Array} Returns `array`.
*/
function arrayEach$4(array, iteratee) {
var index = -1, length = array == null ? 0 : array.length;
while (++index < length) if (iteratee(array[index], index, array) === false) break;
return array;
}
/**
* A specialized version of `_.forEachRight` for arrays without support for
* iteratee shorthands.
*
* @private
* @param {Array} [array] The array to iterate over.
* @param {Function} iteratee The function invoked per iteration.
* @returns {Array} Returns `array`.
*/
function arrayEachRight(array, iteratee) {
var length = array == null ? 0 : array.length;
while (length--) if (iteratee(array[length], length, array) === false) break;
return array;
}
/**
* A specialized version of `_.every` for arrays without support for
* iteratee shorthands.
*
* @private
* @param {Array} [array] The array to iterate over.
* @param {Function} predicate The function invoked per iteration.
* @returns {boolean} Returns `true` if all elements pass the predicate check,
* else `false`.
*/
function arrayEvery(array, predicate) {
var index = -1, length = array == null ? 0 : array.length;
while (++index < length) if (!predicate(array[index], index, array)) return false;
return true;
}
/**
* A specialized version of `_.filter` for arrays without support for
* iteratee shorthands.
*
* @private
* @param {Array} [array] The array to iterate over.
* @param {Function} predicate The function invoked per iteration.
* @returns {Array} Returns the new filtered array.
*/
function arrayFilter$3(array, predicate) {
var index = -1, length = array == null ? 0 : array.length, resIndex = 0, result = [];
while (++index < length) {
var value = array[index];
if (predicate(value, index, array)) result[resIndex++] = value;
}
return result;
}
/**
* A specialized version of `_.includes` for arrays without support for
* specifying an index to s