@domorium/validator 2.2.0 → 2.2.1

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.esm.js CHANGED
@@ -893,10 +893,10 @@ function T() {
893
893
  requireDeclaration: !1
894
894
  };
895
895
  }
896
- function ce(e, t) {
896
+ function E(e, t) {
897
897
  return e.aliases.get(y(t)) ?? y(t);
898
898
  }
899
- function le(e, t) {
899
+ function ce(e, t) {
900
900
  return {
901
901
  code: m.UndocumentedTag,
902
902
  message: `Extension tag ${e} is not declared in HEAD.SCHMA`,
@@ -904,19 +904,19 @@ function le(e, t) {
904
904
  level: "warning"
905
905
  };
906
906
  }
907
- var ue = /^(_[A-Z0-9_]+)\s+([A-Za-z][A-Za-z0-9+.-]*:\S*)$/;
908
- function E(e) {
909
- let t = e.trim().match(ue);
907
+ var le = /^(_[A-Z0-9_]+)\s+([A-Za-z][A-Za-z0-9+.-]*:\S*)$/;
908
+ function D(e) {
909
+ let t = e.trim().match(le);
910
910
  return t ? {
911
911
  tag: y(t[1]),
912
912
  uri: t[2]
913
913
  } : null;
914
914
  }
915
- function de(e, t, n) {
915
+ function ue(e, t, n) {
916
916
  let r = /* @__PURE__ */ new Map(), i = /* @__PURE__ */ new Map(), a = /* @__PURE__ */ new Set(), o = [], s = e.find((e) => e.tokens.TAG?.value === "HEAD")?.children.find((e) => e.tokens.TAG?.value === "SCHMA");
917
917
  for (let e of s?.children ?? []) {
918
918
  if (e.tokens.TAG?.value !== "TAG") continue;
919
- let t = E(v(e));
919
+ let t = D(v(e));
920
920
  if (!t) continue;
921
921
  let s = `${t.tag} ${t.uri}`;
922
922
  if (a.has(s)) {
@@ -944,37 +944,37 @@ function de(e, t, n) {
944
944
  }
945
945
  //#endregion
946
946
  //#region src/validator/calendars.ts
947
- var D = "@#D([A-Z][A-Z ]*)@", fe = RegExp(`^${D}\\s*`, "u"), pe = RegExp(`^${D}$`, "u"), me = RegExp(`${D}|\\S+`, "gu"), O = y("GREGORIAN"), he = {
947
+ var O = "@#D([A-Z][A-Z ]*)@", de = RegExp(`^${O}\\s*`, "u"), fe = RegExp(`^${O}$`, "u"), pe = RegExp(`${O}|\\S+`, "gu"), k = y("GREGORIAN"), me = {
948
948
  months: null,
949
949
  epochs: null
950
- }, ge = /* @__PURE__ */ new WeakMap();
951
- function k(e, t) {
952
- let n = ge.get(e);
953
- n || (n = /* @__PURE__ */ new Map(), ge.set(e, n));
950
+ }, he = /* @__PURE__ */ new WeakMap();
951
+ function A(e, t) {
952
+ let n = he.get(e);
953
+ n || (n = /* @__PURE__ */ new Map(), he.set(e, n));
954
954
  let r = n.get(t);
955
955
  if (r) return r;
956
956
  let i = e.calendar[t];
957
- if (!i) return he;
957
+ if (!i) return me;
958
958
  let a = {
959
959
  months: new Set(Object.keys(i.months)),
960
960
  epochs: new Set(i.epochs)
961
961
  };
962
962
  return n.set(t, a), a;
963
963
  }
964
- function A(e, t) {
964
+ function j(e, t) {
965
965
  return e === null ? w(t) : e.has(t) || w(t);
966
966
  }
967
- function _e(e) {
967
+ function ge(e) {
968
968
  return `@#D${e}@`;
969
969
  }
970
- function ve(e, t) {
971
- let n = pe.exec(t)?.[1];
970
+ function _e(e, t) {
971
+ let n = fe.exec(t)?.[1];
972
972
  if (n !== void 0) return y(n);
973
973
  let r = y(t);
974
974
  return e.calendar[r] ? r : null;
975
975
  }
976
- function j(e) {
977
- let t = fe.exec(e);
976
+ function ve(e) {
977
+ let t = de.exec(e);
978
978
  return t ? {
979
979
  calendar: y(t[1]),
980
980
  rest: e.slice(t[0].length)
@@ -984,7 +984,7 @@ function j(e) {
984
984
  };
985
985
  }
986
986
  function M(e) {
987
- return e.match(me) ?? [];
987
+ return e.match(pe) ?? [];
988
988
  }
989
989
  //#endregion
990
990
  //#region src/validator/epoch.ts
@@ -1007,7 +1007,7 @@ var P = {
1007
1007
  OCT: 31,
1008
1008
  NOV: 30,
1009
1009
  DEC: 31
1010
- }, xe = /* @__PURE__ */ new Set([O, "JULIAN"]), Se = /^\d+$/u, Ce = /* @__PURE__ */ new Set([
1010
+ }, xe = /* @__PURE__ */ new Set([k, "JULIAN"]), Se = /^\d+$/u, Ce = /* @__PURE__ */ new Set([
1011
1011
  "ABT",
1012
1012
  "AFT",
1013
1013
  "AND",
@@ -1029,29 +1029,29 @@ function Te(e, t, n) {
1029
1029
  function Ee(e) {
1030
1030
  return e.replace(/\([^()]*\)/gu, " ");
1031
1031
  }
1032
- function De(e, t) {
1033
- let n = M(Ee(t)), r = [], i = O;
1034
- for (let t = 0; t < n.length; t += 1) {
1035
- let a = n[t];
1036
- if (Ce.has(a)) {
1037
- i = O;
1032
+ function De(e, t, n = T()) {
1033
+ let r = M(Ee(t)).map((e) => E(n, e)), i = [], a = k;
1034
+ for (let t = 0; t < r.length; t += 1) {
1035
+ let n = r[t];
1036
+ if (Ce.has(n)) {
1037
+ a = k;
1038
1038
  continue;
1039
1039
  }
1040
- let o = ve(e, a);
1040
+ let o = _e(e, n);
1041
1041
  if (o !== null) {
1042
- i = o;
1042
+ a = o;
1043
1043
  continue;
1044
1044
  }
1045
- let s = n[t + 1];
1046
- if (!xe.has(i) || !Se.test(a) || s === void 0 || P[s] === void 0) continue;
1047
- let c = Te(s, Se.test(n[t + 2] ?? "") && !be(n[t + 3]) ? Number(n[t + 2]) : null, i), l = Number(a);
1048
- c !== null && (l < 1 || l > c) && r.push({
1045
+ let s = r[t + 1];
1046
+ if (!xe.has(a) || !Se.test(n) || s === void 0 || P[s] === void 0) continue;
1047
+ let c = Te(s, Se.test(r[t + 2] ?? "") && !be(r[t + 3]) ? Number(r[t + 2]) : null, a), l = Number(n);
1048
+ c !== null && (l < 1 || l > c) && i.push({
1049
1049
  day: l,
1050
1050
  month: s,
1051
1051
  length: c
1052
1052
  }), t += 1;
1053
1053
  }
1054
- return r;
1054
+ return i;
1055
1055
  }
1056
1056
  function Oe(e) {
1057
1057
  return e.filter(({ calendar: e, year: t, epoch: n }) => t === 0 && xe.has(e) && (n === void 0 || n === "BCE")).map(({ year: e, calendar: t }) => ({
@@ -1069,13 +1069,13 @@ var F = /^\d+$/, ke = [
1069
1069
  function L(e, t, n, r) {
1070
1070
  let i = t, a = e[i];
1071
1071
  if (a === void 0) return I;
1072
- let o = O;
1072
+ let o = k;
1073
1073
  (n.calendar[y(a)] || w(a)) && (o = y(a), i += 1);
1074
- let { months: s, epochs: c } = k(n, o), l = {
1074
+ let { months: s, epochs: c } = A(n, o), l = {
1075
1075
  calendar: o,
1076
1076
  year: 0
1077
1077
  };
1078
- return F.test(e[i] ?? "") && e[i + 1] !== void 0 && A(s, e[i + 1]) && F.test(e[i + 2] ?? "") ? (l.day = Number(e[i]), l.month = e[i + 1], i += 2) : e[i] !== void 0 && A(s, e[i]) && F.test(e[i + 1] ?? "") && (l.month = e[i], i += 1), F.test(e[i] ?? "") ? (l.year = Number(e[i]), i += 1, e[i] !== void 0 && A(c, e[i]) && (l.epoch = e[i], i += 1), r.push(l), i) : I;
1078
+ return F.test(e[i] ?? "") && e[i + 1] !== void 0 && j(s, e[i + 1]) && F.test(e[i + 2] ?? "") ? (l.day = Number(e[i]), l.month = e[i + 1], i += 2) : e[i] !== void 0 && j(s, e[i]) && F.test(e[i + 1] ?? "") && (l.month = e[i], i += 1), F.test(e[i] ?? "") ? (l.year = Number(e[i]), i += 1, e[i] !== void 0 && j(c, e[i]) && (l.epoch = e[i], i += 1), r.push(l), i) : I;
1079
1079
  }
1080
1080
  function R(e, t, n, r) {
1081
1081
  if (e[t] === "TO") return L(e, t + 1, n, r);
@@ -1096,7 +1096,7 @@ function Ae(e) {
1096
1096
  return e.trim().split(/\s+/);
1097
1097
  }
1098
1098
  function B(e, t) {
1099
- return Ae(e).map((e) => ce(t, e));
1099
+ return Ae(e).map((e) => E(t, e));
1100
1100
  }
1101
1101
  function V(e, t, n, r) {
1102
1102
  let i = B(e, n);
@@ -1132,8 +1132,8 @@ function Ne(e, t, n = T()) {
1132
1132
  function Pe(e, t, n = T()) {
1133
1133
  let r = B(e, n);
1134
1134
  if (r.length !== 3) return !1;
1135
- let { months: i } = k(t, O);
1136
- return F.test(r[0]) && A(i, r[1]) && F.test(r[2]);
1135
+ let { months: i } = A(t, k);
1136
+ return F.test(r[0]) && j(i, r[1]) && F.test(r[2]);
1137
1137
  }
1138
1138
  //#endregion
1139
1139
  //#region src/validator/date-551.ts
@@ -1154,11 +1154,11 @@ function W(e, t) {
1154
1154
  return n.set(t, a), a;
1155
1155
  }
1156
1156
  function Le(e, t) {
1157
- let { calendar: n, rest: r } = j(t), i = W(e, n ?? O);
1157
+ let { calendar: n, rest: r } = ve(t), i = W(e, n ?? k);
1158
1158
  return i === null ? r.length > 0 : i.dated.test(r);
1159
1159
  }
1160
1160
  function Re(e, t) {
1161
- let { calendar: n, rest: r } = j(t), i = n ?? O, a = W(e, i)?.dated.exec(r)?.groups;
1161
+ let { calendar: n, rest: r } = ve(t), i = n ?? k, a = W(e, i)?.dated.exec(r)?.groups;
1162
1162
  if (!a) return null;
1163
1163
  let { day: o, month: s, year: c, dual: l, epoch: u } = a, d = {
1164
1164
  calendar: i.replace(" ", "_"),
@@ -1218,7 +1218,7 @@ function Xe(e, t) {
1218
1218
  return Je(e, qe(t));
1219
1219
  }
1220
1220
  function Ze(e, t) {
1221
- let n = W(e, O);
1221
+ let n = W(e, k);
1222
1222
  return n === null ? t.length > 0 : n.exact.test(t);
1223
1223
  }
1224
1224
  function G(e, t) {
@@ -1259,8 +1259,8 @@ function q(e, t, n = m.IncorrectValue) {
1259
1259
  level: "error"
1260
1260
  };
1261
1261
  }
1262
- function it(e, t, n, r) {
1263
- return [...De(e, n).map(({ day: e, month: n, length: r }) => q(t, `names ${e} ${n}, and ${n} has ${r} days`, m.ImpossibleDay)), ...Oe(r?.dates ?? []).map(({ year: e, calendar: n }) => q(t, `names year ${e}, and ${n} has no year ${e}`, m.ImpossibleYear))];
1262
+ function it(e, t, n, r, i) {
1263
+ return [...De(e, r, t.requireDeclaration ? t : T()).map(({ day: e, month: t, length: r }) => q(n, `names ${e} ${t}, and ${t} has ${r} days`, m.ImpossibleDay)), ...Oe(i?.dates ?? []).map(({ year: e, calendar: t }) => q(n, `names year ${e}, and ${t} has no year ${e}`, m.ImpossibleYear))];
1264
1264
  }
1265
1265
  var at = "(?:[01]?\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?", ot = RegExp(`^${at}$`), st = RegExp(`^${at}Z?$`), ct = "(?:CHILD|INFANT|STILLBORN|\\d+y(?:\\s\\d+m)?(?:\\s\\d+w)?(?:\\s\\d+d)?|\\d+m(?:\\s\\d+w)?(?:\\s\\d+d)?|\\d+w(?:\\s\\d+d)?|\\d+d)", lt = RegExp(`^(?:[<>]\\s)?${ct}$`), ut = RegExp(`^(?:[<>]\\s*)?${ct}$`, "i"), dt = /^[^/]*(?:\/[^/]*\/[^/]*)?$/, ft = /^[A-Za-z0-9][A-Za-z0-9!#$&^_.+-]*\/[A-Za-z0-9][A-Za-z0-9!#$&^_.+-]*(;\s*[\w-]+=[^;]+)*$/, pt = /^\d+$/, mt = /^[NS]\d+(\.\d+)?$/, ht = /^[EW]\d+(\.\d+)?$/, gt = /* @__PURE__ */ RegExp("^(?:(?:en-GB-oed|i-ami|i-bnn|i-default|i-enochian|i-hak|i-klingon|i-lux|i-mingo|i-navajo|i-pwn|i-tao|i-tay|i-tsu|sgn-BE-FR|sgn-BE-NL|sgn-CH-DE|art-lojban|cel-gaulish|no-bok|no-nyn|zh-guoyu|zh-hakka|zh-min|zh-min-nan|zh-xiang)|(?:(?:[A-Za-z]{2,3}(?:-[A-Za-z]{3}){0,3}|[A-Za-z]{4}|[A-Za-z]{5,8})(?:-[A-Za-z]{4})?(?:-(?:[A-Za-z]{2}|[0-9]{3}))?(?:-(?:[A-Za-z0-9]{5,8}|[0-9][A-Za-z0-9]{3}))*(?:-[0-9A-WY-Za-wy-z](?:-[A-Za-z0-9]{2,8})+)*(?:-x(?:-[A-Za-z0-9]{1,8})+)?)|(?:x(?:-[A-Za-z0-9]{1,8})+))$", "i"), _t = {
1266
1266
  "Y|<NULL>": "boolean",
@@ -1336,7 +1336,7 @@ var at = "(?:[01]?\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?", ot = RegExp(`
1336
1336
  message: "should be a valid RFC 5646 language tag (e.g. \"en\", \"en-US\")"
1337
1337
  },
1338
1338
  "tag-def": {
1339
- test: (e) => !!E(e),
1339
+ test: (e) => !!D(e),
1340
1340
  message: "should be an extension tag and its URI (e.g. \"_SKYPEID http://xmlns.com/foaf/0.1/skypeID\")"
1341
1341
  },
1342
1342
  nonNegativeInteger: {
@@ -1396,7 +1396,7 @@ function bt(e, t) {
1396
1396
  let r = /* @__PURE__ */ new Map();
1397
1397
  for (let n of e.values()) for (let e of n) {
1398
1398
  let n = e.tokens.TAG?.value, i = e.tokens.POINTER?.value;
1399
- if (n && i) for (let e of /* @__PURE__ */ new Set([n, ce(t, n)])) {
1399
+ if (n && i) for (let e of /* @__PURE__ */ new Set([n, E(t, n)])) {
1400
1400
  let t = r.get(e);
1401
1401
  t || (t = /* @__PURE__ */ new Set(), r.set(e, t)), t.add(i);
1402
1402
  }
@@ -1429,7 +1429,7 @@ var J = class {
1429
1429
  }
1430
1430
  validateEnumeration(e, t, n) {
1431
1431
  let r = n.tokens.VALUE?.range || n.range, i = this.getAvailableValues(t), a = [], o = new Set(e.filter((e) => w(e) && this.extensions.requireDeclaration && !this.extensions.tags.has(y(e))));
1432
- for (let e of o) a.push(le(y(e), r));
1432
+ for (let e of o) a.push(ce(y(e), r));
1433
1433
  let s = this.scheme.payload[t]?.set, c = s !== void 0 && et.has(s), l = c ? i?.map((e) => e.toLowerCase()) : i;
1434
1434
  return e.some((e) => !w(e) && !l?.includes(c ? e.toLowerCase() : e)) && a.push(q(n, `should be in set [${rt(i)}]`, m.ShouldBeSetValue)), a;
1435
1435
  }
@@ -1471,7 +1471,7 @@ var J = class {
1471
1471
  let r = n || this.getNodeType(t), i = this.getFieldType(r), a = v(t).trim(), o = t.tokens.TAG;
1472
1472
  if (!a && this.mayOmitPayload(r) || i.type === null) return;
1473
1473
  let s = vt[i.type];
1474
- if (s) !a || !s.test(a, this.scheme, this.extensions) ? e.push(q(t, s.message)) : s.read && e.push(...it(this.scheme, t, a, s.read(a, this.scheme, this.extensions)));
1474
+ if (s) !a || !s.test(a, this.scheme, this.extensions) ? e.push(q(t, s.message)) : s.read && e.push(...it(this.scheme, this.extensions, t, a, s.read(a, this.scheme, this.extensions)));
1475
1475
  else switch (i.type) {
1476
1476
  case "boolean":
1477
1477
  a && a !== "Y" ? e.push(q(t, "should be Y or null")) : !a && t.children.length === 0 && e.push({
@@ -1586,7 +1586,7 @@ var Et = class {
1586
1586
  if (t === y("CONT") || t === y("CONC")) continue;
1587
1587
  let i = n.tokens.TAG;
1588
1588
  if (w(t)) {
1589
- this.extensions.requireDeclaration && !this.extensions.tags.has(t) && e.push(le(t, i?.range || n.range));
1589
+ this.extensions.requireDeclaration && !this.extensions.tags.has(t) && e.push(ce(t, i?.range || n.range));
1590
1590
  let a = wt(this.extensions, t, r);
1591
1591
  a && (c.collect(e, n, a), this.collect(e, n.children, a, r, n));
1592
1592
  continue;
@@ -1742,7 +1742,7 @@ function Ft(e) {
1742
1742
  return /\s$/u.test(e) ? t : t.slice(0, -1);
1743
1743
  }
1744
1744
  function It(e, t) {
1745
- let n = 0, r = O, i = t[0] === void 0 ? null : ve(e, t[0]);
1745
+ let n = 0, r = k, i = t[0] === void 0 ? null : _e(e, t[0]);
1746
1746
  i !== null && (r = i, n = 1);
1747
1747
  let a = t.slice(n);
1748
1748
  if (a.length === 0) return {
@@ -1752,7 +1752,7 @@ function It(e, t) {
1752
1752
  keywords: [],
1753
1753
  complete: !1
1754
1754
  };
1755
- let { epochs: o } = k(e, r);
1755
+ let { epochs: o } = A(e, r);
1756
1756
  if (a.some((e) => o?.has(e))) return {
1757
1757
  ...Z,
1758
1758
  complete: !0
@@ -1780,12 +1780,12 @@ function Lt(e, t, n) {
1780
1780
  let r = Ft(t);
1781
1781
  if (n === "exact") return r.length === 1 ? {
1782
1782
  ...Z,
1783
- months: O
1783
+ months: k
1784
1784
  } : Z;
1785
1785
  let i = n === "period" ? Nt : Mt;
1786
1786
  if (r.length === 0) return {
1787
1787
  calendars: !0,
1788
- months: O,
1788
+ months: k,
1789
1789
  epochs: null,
1790
1790
  keywords: i
1791
1791
  };
@@ -1896,7 +1896,7 @@ var qt = {
1896
1896
  }
1897
1897
  };
1898
1898
  function Jt(e, { grammar: t, escaped: n }, r) {
1899
- let i = Lt(e.scheme, r, t), a = (t) => t === null ? void 0 : e.scheme.calendar[y(t)], o = Object.keys(e.scheme.calendar).map((e) => n ? _e(e) : e);
1899
+ let i = Lt(e.scheme, r, t), a = (t) => t === null ? void 0 : e.scheme.calendar[y(t)], o = Object.keys(e.scheme.calendar).map((e) => n ? ge(e) : e);
1900
1900
  return [
1901
1901
  ...i.calendars ? o : [],
1902
1902
  ...Object.keys(a(i.months)?.months ?? {}),
@@ -1939,8 +1939,8 @@ function Zt(e) {
1939
1939
  return e.startsWith("@") ? "An xref holds letters, digits and underscore between two @ marks, so this line cannot be read" : `This line cannot be read from ${JSON.stringify(e)} onward`;
1940
1940
  }
1941
1941
  var Qt = /* @__PURE__ */ new Set([m.UnresolvedXref, m.UndocumentedTag]);
1942
- function $(e, t, n) {
1943
- return n && De(e, t).length === 0 && Oe(n.dates).length === 0 ? n : null;
1942
+ function $(e, t, n, r = T()) {
1943
+ return n && De(e, t, r).length === 0 && Oe(n.dates).length === 0 ? n : null;
1944
1944
  }
1945
1945
  var $t = class {
1946
1946
  nodes = [];
@@ -2023,7 +2023,7 @@ var $t = class {
2023
2023
  }
2024
2024
  applyScheme(e, t, n) {
2025
2025
  this.scheme = t.scheme, this.validatedAs = t.dialect, this.requiresSchmaDeclaration = t.requiresSchmaDeclaration;
2026
- let { context: r, errors: i } = de(e, this.requiresSchmaDeclaration, this.scheme);
2026
+ let { context: r, errors: i } = ue(e, this.requiresSchmaDeclaration, this.scheme);
2027
2027
  this.extensions = r;
2028
2028
  for (let e of i) this.errors.push(e);
2029
2029
  new Et(this.pointers, r, n.fragment ?? !1).collect(this.errors, this.nodes, b(""), this.scheme), n.fragment && (this.errors = this.errors.filter((e) => !Qt.has(e.code)));
@@ -2082,7 +2082,7 @@ var $t = class {
2082
2082
  }
2083
2083
  readDate(e) {
2084
2084
  let t = e.trim();
2085
- if (this.scheme && this.validatedAs) return $(this.scheme, t, this.validatedAs === "7.0" ? H(t, this.scheme, this.extensions) : G(this.scheme, t));
2085
+ if (this.scheme && this.validatedAs) return $(this.scheme, t, this.validatedAs === "7.0" ? H(t, this.scheme, this.extensions) : G(this.scheme, t), this.extensions.requireDeclaration ? this.extensions : T());
2086
2086
  let n = X("5.5.1").scheme, r = X("7.0").scheme;
2087
2087
  return $(n, t, G(n, t)) ?? $(r, t, H(t, r));
2088
2088
  }
@@ -13,6 +13,7 @@
13
13
  */
14
14
  import { GedcomScheme } from "../schemes/schema-types";
15
15
  import type { GedcomDate } from "../types/date";
16
+ import { ExtensionContext } from "./extensions";
16
17
  export declare const LENGTHS: Record<string, number>;
17
18
  export interface ImpossibleYear {
18
19
  year: number;
@@ -26,7 +27,7 @@ export interface ImpossibleDay {
26
27
  }
27
28
  export declare function isLeapYear(year: number, calendar: string): boolean;
28
29
  export declare function daysInMonth(month: string, year: number | null, calendar: string): number | null;
29
- export declare function impossibleDays(scheme: GedcomScheme, value: string): ImpossibleDay[];
30
+ export declare function impossibleDays(scheme: GedcomScheme, value: string, extensions?: ExtensionContext): ImpossibleDay[];
30
31
  /**
31
32
  * Judged on what a grammar read rather than on tokens: only the grammar knows
32
33
  * that `0BC` is a year and an epoch, or that `_CAL 0` is not Gregorian.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@domorium/validator",
3
- "version": "2.2.0",
3
+ "version": "2.2.1",
4
4
  "description": "GEDCOM 5.5.1 and 7.0 parser and validator",
5
5
  "keywords": [
6
6
  "gedcom",