strom-research 1.22.2 → 1.23.0-beta.2

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/core/tree.js CHANGED
@@ -29,7 +29,7 @@ export const TREE_FILE = "strom.json";
29
29
  export const SEAL_FOREIGN = "seal.foreign";
30
30
  // between releases the candidate being made (a bridge run from the sources says what it is: the Strom app goes by it);
31
31
  // at a release the release's own (package.json)
32
- export const VERSION = "1.22.2";
32
+ export const VERSION = "1.23.0-beta.2";
33
33
  const GITIGNORE = `# Strom Research — local state and large files are not versioned
34
34
  .strom/
35
35
  /media/
@@ -200,8 +200,12 @@ function checkPerson(p, out) {
200
200
  out.push({ path: `names[${i}].${t}`, message: "must be a title (a string, not empty)" });
201
201
  if (n.kind !== undefined && !NAME_KINDS.includes(n.kind))
202
202
  out.push({ path: `names[${i}].kind`, message: `must be one of ${NAME_KINDS.join(", ")}` });
203
+ if (n.primary !== undefined && n.primary !== true)
204
+ out.push({ path: `names[${i}].primary`, message: "must be true, or left out" });
203
205
  checkCitations(n.citations, `names[${i}].citations`, out);
204
206
  });
207
+ if (Array.isArray(p.names) && p.names.filter((n) => isObj(n) && n.primary).length > 1)
208
+ out.push({ path: "names", message: "at most one name is the one the person is shown by (primary)" });
205
209
  if (p.retractedNames !== undefined) {
206
210
  if (!Array.isArray(p.retractedNames))
207
211
  out.push({ path: "retractedNames", message: "must be an array" });
@@ -27,7 +27,7 @@
27
27
  import { GedWriter, clipChars, lineValue } from "./lines.js";
28
28
  import { labels, RELA } from "./labels.js";
29
29
  import { linkInTree, recordedLinks } from "../core/hypolinks.js";
30
- import { birthEvent, claimText, conflictTitle, coupleSides, displayName, familySides, formatName, gedcomTitledName, noName, preferredOrder, primaryName, relationTo } from "../core/people.js";
30
+ import { birthEvent, claimText, conflictTitle, coupleSides, currentName, displayName, familySides, formatName, gedcomTitledName, noName, preferredOrder, primaryName, relationTo } from "../core/people.js";
31
31
  import { foldText } from "../core/text.js";
32
32
  import { dateYears } from "../core/gdate.js";
33
33
  import { humanAge, isGedcomAge, normalizeAge } from "../core/age.js";
@@ -258,7 +258,17 @@ export function exportGedcom(tree, opts = {}) {
258
258
  w.record(x(p.id), "INDI");
259
259
  const primary = primaryName(p);
260
260
  const nameQuotes = [];
261
- for (const n of [primary, ...p.names.filter((n) => n !== primary)]) {
261
+ // the name the person is shown by now (Name.primary): first for any program (GEDCOM 7: the preferred name first);
262
+ // the Strom file keeps the name of their identity first (the app's birth surname) and says the mark — a married
263
+ // name marked last of them (the app keeps one name after a marriage: the last), so even an app that reads no mark
264
+ // shows it
265
+ const current = currentName(p);
266
+ const rest = p.names.filter((n) => n !== primary && n !== current);
267
+ const order = current === primary ? [primary, ...rest]
268
+ : strict ? [current, primary, ...rest]
269
+ : current.kind === "married" ? [primary, ...rest, current]
270
+ : [primary, ...p.names.filter((n) => n !== primary)];
271
+ for (const n of order) {
262
272
  // a name with a title says it in the line (any program shows it) and spells its parts out below: NPFX, GIVN, SURN,
263
273
  // NSFX — for any program (GEDCOM 5.5.1's own tags), for the Strom app from its 3.10 (titles; an older one reads
264
274
  // the line). A part holding a comma gets no GIVN / SURN (GEDCOM reads commas there as a list); the line has it.
@@ -280,6 +290,8 @@ export function exportGedcom(tree, opts = {}) {
280
290
  // "birth" says something only next to another name
281
291
  if (n.kind && (n.kind !== "birth" || p.names.length > 1))
282
292
  w.line(2, "TYPE", NAME_TYPE[n.kind]);
293
+ if (!strict && n.primary)
294
+ w.line(2, "_STROM_PRIMARY", "Y");
283
295
  for (const c of n.citations ?? []) {
284
296
  const q = citation(2, c);
285
297
  if (q)
@@ -5,7 +5,7 @@ import { normalizeDate } from "../core/gdate.js";
5
5
  import { isGedcomAge } from "../core/age.js";
6
6
  import { MAX_LINE_BYTES } from "./lines.js";
7
7
  const LINE = /^(\d{1,2}) (?:(@[^@ ]+@) )?([A-Za-z0-9_]+)(?: (.*))?$/;
8
- const EVENT_DETAIL = ["TYPE", "DATE", "PLAC", "AGE", "SOUR", "NOTE", "ASSO", "_WITN", "CAUS", "ADDR", "AGNC", "RELI", "OBJE", "HUSB", "WIFE"];
8
+ const EVENT_DETAIL = ["TYPE", "DATE", "PLAC", "AGE", "SOUR", "NOTE", "ASSO", "_WITN", "CAUS", "ADDR", "AGNC", "RELI", "OBJE", "HUSB", "WIFE", "_STROM_STATUS"];
9
9
  const INDI_EVENTS = [
10
10
  "BIRT", "DEAT", "BAPM", "CHR", "CHRA", "CONF", "FCOM", "BARM", "BASM", "ORDN", "EDUC", "GRAD", "OCCU", "RESI", "EMIG", "IMMI",
11
11
  "NATU", "RELI", "TITL", "NATI", "ADOP", "WILL", "PROB", "BURI", "CREM", "CENS", "EVEN", "RETI", "BLES", "CAST", "DSCR", "IDNO",
@@ -14,7 +14,7 @@ const INDI_EVENTS = [
14
14
  const FAM_EVENTS = ["MARR", "DIV", "MARB", "MARC", "MARL", "MARS", "ANUL", "DIVF", "ENGA", "CENS", "RESI", "EVEN", "NCHI"];
15
15
  /** Allowed child tags by parent context ("INDI", "INDI.BIRT", …). CONC/CONT are allowed under anything with text. */
16
16
  const CHILDREN = {
17
- HEAD: ["SOUR", "DEST", "DATE", "SUBM", "SUBN", "FILE", "COPR", "GEDC", "CHAR", "LANG", "PLAC", "NOTE", "_STROM_TREE", "_STROM_HEAD", "_STROM_LINKS", "_STROM_ASOF"],
17
+ HEAD: ["SOUR", "DEST", "DATE", "SUBM", "SUBN", "FILE", "COPR", "GEDC", "CHAR", "LANG", "PLAC", "NOTE", "_STROM_TREE", "_STROM_HEAD", "_STROM_LINKS", "_STROM_ASOF", "_STROM_MODE"],
18
18
  "HEAD.SOUR": ["VERS", "NAME", "CORP", "DATA"],
19
19
  "HEAD._STROM_LINKS": ["_SCHEME"],
20
20
  "HEAD.GEDC": ["VERS", "FORM"],
@@ -33,14 +33,16 @@ const CHILDREN = {
33
33
  "_STROM_EDGE._JOIN": ["_VAR", "_ISLAND", "_HELD"],
34
34
  // a value of a conflict the app decides by side: its side, a sex as M, F or U
35
35
  _STROM_VALUE: ["SOUR", "_STROM_SIDE", "_STROM_RAW"],
36
- "INDI.NAME": ["TYPE", "GIVN", "SURN", "NPFX", "NSFX", "NICK", "SPFX", "SOUR", "NOTE"],
36
+ "INDI.NAME": ["TYPE", "GIVN", "SURN", "NPFX", "NSFX", "NICK", "SPFX", "SOUR", "NOTE", "_STROM_PRIMARY"],
37
37
  "INDI.FAMC": ["PEDI", "NOTE"],
38
38
  "INDI.FAMS": ["NOTE"],
39
39
  "FAM.CHIL": ["_FREL", "_MREL"],
40
40
  "INDI.ASSO": ["RELA", "SOUR", "NOTE"],
41
- FAM: ["HUSB", "WIFE", "CHIL", "NOTE", "SOUR", "REFN", "OBJE", "RIN", "CHAN", "_STORY", ...FAM_EVENTS],
41
+ FAM: ["HUSB", "WIFE", "CHIL", "NOTE", "SOUR", "REFN", "OBJE", "RIN", "CHAN", "_STORY", "_STAT", "_STROM_NO_COUPLE", ...FAM_EVENTS],
42
42
  // the Strom profile also writes PAGE on the record: where in the book the source is (the Strom app's reference)
43
- SOUR: ["TITL", "AUTH", "ABBR", "PUBL", "TEXT", "REPO", "NOTE", "REFN", "DATA", "OBJE", "RIN", "CHAN"],
43
+ SOUR: ["TITL", "AUTH", "ABBR", "PUBL", "TEXT", "REPO", "NOTE", "REFN", "DATA", "OBJE", "RIN", "CHAN", "_STROM_READ", "_STROM_VERIFIED", "_STROM_READING", "_STROM_IMG_OMITTED"],
44
+ "SOUR._STROM_READING": ["_STROM_ENTRY"],
45
+ "SOUR._STROM_IMG_OMITTED": ["_STROM_CLIP"],
44
46
  "SOUR.REPO": ["CALN", "NOTE"],
45
47
  REPO: ["NAME", "ADDR", "NOTE", "REFN", "RIN", "CHAN"],
46
48
  SUBM: ["NAME", "ADDR", "LANG", "NOTE", "RIN", "CHAN"],
@@ -73,6 +75,12 @@ const EXTENSIONS = new Set([
73
75
  "_VAR", "_LINK", "_PERS", "_FAM", "_PAR", "_CHOSEN", "_INTREE",
74
76
  // a source's excerpts the file leaves out, and why
75
77
  "_STROM_IMG_OMITTED",
78
+ // the name a person is shown by; a couple's state; parents who are no couple; an archive
79
+ "_STROM_PRIMARY", "_STAT", "_STROM_NO_COUPLE", "_STROM_MODE",
80
+ // who read a source, the user's verification, the reading it is an entry of; how sure a fact is
81
+ "_STROM_READ", "_STROM_VERIFIED", "_STROM_READING", "_STROM_ENTRY", "_STROM_STATUS",
82
+ // an excerpt's original by its content, and how its picture lies
83
+ "_STROM_SHA", "_STROM_ORIENT",
76
84
  ]);
77
85
  /** Context of the children of the last tag in `anc` (the ancestors of a line). */
78
86
  function contextOf(anc) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "strom-research",
3
- "version": "1.22.2",
3
+ "version": "1.23.0-beta.2",
4
4
  "description": "Genealogical research toolkit for AI coding agents",
5
5
  "type": "module",
6
6
  "bin": {
@@ -57,5 +57,8 @@
57
57
  "devDependencies": {
58
58
  "@types/node": "^22.20.4",
59
59
  "typescript": "^7.0.2"
60
+ },
61
+ "publishConfig": {
62
+ "tag": "beta"
60
63
  }
61
64
  }