linked-rolls 0.63.0 → 0.65.0

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.
Files changed (67) hide show
  1. package/README.md +13 -5
  2. package/lib/analysis/constraints.d.ts +2 -2
  3. package/lib/analysis/constraints.js +38 -32
  4. package/lib/analysis/ownPaper.d.ts +3 -3
  5. package/lib/analysis/ownPaper.js +3 -3
  6. package/lib/analysis/reservations.d.ts +2 -2
  7. package/lib/analysis/reservations.js +6 -6
  8. package/lib/analysis/sigla.d.ts +4 -5
  9. package/lib/analysis/sigla.js +4 -4
  10. package/lib/analysis/stemma.d.ts +22 -0
  11. package/lib/analysis/stemma.js +38 -0
  12. package/lib/analysis/text.d.ts +31 -0
  13. package/lib/analysis/text.js +62 -0
  14. package/lib/analysis/witnesses.d.ts +5 -5
  15. package/lib/analysis/witnesses.js +27 -22
  16. package/lib/collation/alignment.js +55 -20
  17. package/lib/collation/scatter.d.ts +6 -6
  18. package/lib/collation/scatter.js +15 -13
  19. package/lib/emulation/Emulation.d.ts +7 -7
  20. package/lib/emulation/Emulation.js +29 -27
  21. package/lib/emulation/negotiation.d.ts +2 -2
  22. package/lib/emulation/negotiation.js +3 -2
  23. package/lib/index.d.ts +4 -1
  24. package/lib/index.js +4 -1
  25. package/lib/io/asJsonLd.js +43 -38
  26. package/lib/io/importJsonLd.js +11 -1
  27. package/lib/io/migrate.js +20 -26
  28. package/lib/lookup/lookup.d.ts +32 -0
  29. package/lib/lookup/lookup.js +40 -0
  30. package/lib/lookup/paths.d.ts +11 -0
  31. package/lib/lookup/paths.js +78 -0
  32. package/lib/lookup/perState.d.ts +32 -0
  33. package/lib/lookup/perState.js +63 -0
  34. package/lib/model/Edit.d.ts +4 -0
  35. package/lib/model/Edition.d.ts +0 -13
  36. package/lib/model/Version.d.ts +7 -1
  37. package/lib/ops/beliefs.d.ts +1 -1
  38. package/lib/ops/beliefs.js +1 -1
  39. package/lib/ops/collation.d.ts +3 -4
  40. package/lib/ops/collation.js +38 -32
  41. package/lib/ops/commands.d.ts +4 -5
  42. package/lib/ops/commands.js +10 -10
  43. package/lib/ops/copies.js +11 -3
  44. package/lib/ops/draft.d.ts +12 -12
  45. package/lib/ops/draft.js +11 -13
  46. package/lib/ops/edits.d.ts +1 -2
  47. package/lib/ops/edits.js +13 -10
  48. package/lib/ops/features.d.ts +2 -2
  49. package/lib/ops/features.js +3 -2
  50. package/lib/ops/immutable.d.ts +7 -1
  51. package/lib/ops/immutable.js +22 -8
  52. package/lib/ops/index.d.ts +1 -1
  53. package/lib/ops/index.js +6 -0
  54. package/lib/ops/versions.d.ts +2 -3
  55. package/lib/ops/versions.js +6 -5
  56. package/lib/readers/phillipsEroll.js +1 -8
  57. package/lib/readers/stanfordAton.js +2 -6
  58. package/lib/schema.json +2 -33
  59. package/lib/systems/welte.d.ts +17 -0
  60. package/lib/systems/welte.js +17 -1
  61. package/lib/systems/welteT100/system.d.ts +1 -16
  62. package/lib/systems/welteT100/system.js +3 -17
  63. package/lib/systems/welteT98/system.d.ts +1 -12
  64. package/lib/systems/welteT98/system.js +3 -13
  65. package/package.json +1 -1
  66. package/lib/view/EditionView.d.ts +0 -103
  67. package/lib/view/EditionView.js +0 -329
package/lib/io/migrate.js CHANGED
@@ -2,6 +2,7 @@ import { systemIdIn, systemOf, translationBetween } from "../systems/TrackerBar.
2
2
  import { trackerBars } from "../systems/index.js";
3
3
  import { welteT100 } from "../systems/welteT100/bar.js";
4
4
  import { isDateString } from "../shared/utils.js";
5
+ import { mapped, withValues } from "../ops/immutable.js";
5
6
  const retiredVersionTypes = new Set(['edition', 'unicum']);
6
7
  /**
7
8
  * The vocabulary the steps below were written against, as it stood in
@@ -37,10 +38,10 @@ const referenceKeys = ['alignedWith', 'pairedWith', 'basedOn'];
37
38
  * The five type terms that were capitalised while the rest of the
38
39
  * vocabulary was not, under the keys that carried them then.
39
40
  */
40
- const lowerCasedTerms = {
41
+ const lowerCasedTerms = Object.entries({
41
42
  method: { Print: 'print', Handwriting: 'handwriting', Stamp: 'stamp' },
42
43
  material: { Paper: 'paper', Tape: 'tape' }
43
- };
44
+ });
44
45
  const named = (name) => ({ name, sameAs: [] });
45
46
  const withRenamedKeys = (node) => Object.keys(node).some(key => Object.hasOwn(renamedKeys, key))
46
47
  ? Object.fromEntries(Object.entries(node).map(([key, value]) => [renamedKeys[key] ?? key, value]))
@@ -82,7 +83,7 @@ const withoutVersionSiglum = (node) => {
82
83
  const { siglum: _labelled, ...rest } = node;
83
84
  return rest;
84
85
  };
85
- const withLowerCaseTerms = (node) => Object.entries(lowerCasedTerms).reduce((result, [key, terms]) => {
86
+ const withLowerCaseTerms = (node) => lowerCasedTerms.reduce((result, [key, terms]) => {
86
87
  const lowered = terms[result[key]];
87
88
  return lowered ? { ...result, [key]: lowered } : result;
88
89
  }, node);
@@ -450,26 +451,16 @@ const withTimeSpanDates = (node) => {
450
451
  const { '@value': within, '@type': _typed, ...rest } = node;
451
452
  return { ...rest, within };
452
453
  };
453
- const migrateNode = (node) => [withRenamedKeys, withRenamedEditType, withTypology, withRenamedType, withoutVersionType, withoutVersionSiglum, withLowerCaseTerms, withSplitMethod, withReferences, withKeeper, withoutEmptyKeeper,
454
+ const nodeSteps = [withRenamedKeys, withRenamedEditType, withTypology, withRenamedType, withoutVersionType, withoutVersionSiglum, withLowerCaseTerms, withSplitMethod, withReferences, withKeeper, withoutEmptyKeeper,
454
455
  withPerforator, withProductionNodes, withTypedPerforator, withScale, withoutOps, withDerivationList, withReadingKind, withTimeSpanDates,
455
- withoutFeatureKind, withBorneFeaturesNamed, withFeaturesInActs, withOwnPlaces, withDriveOfStaggering, withoutPattern, withoutBearings, withoutEntailedType]
456
- .reduce((result, step) => step(result), node);
457
- /** The items each walked, or the very same list where the walk changed none. */
458
- const walked = (items) => {
459
- const result = items.map(walk);
460
- return result.every((item, i) => item === items[i]) ? items : result;
461
- };
462
- /** The node with each child walked, or the very same node where the walk changed none. */
463
- const withWalkedChildren = (node) => {
464
- const entries = Object.entries(node);
465
- const result = entries.map(([key, child]) => [key, walk(child)]);
466
- return result.every(([, child], i) => child === entries[i][1]) ? node : Object.fromEntries(result);
467
- };
456
+ withoutFeatureKind, withBorneFeaturesNamed, withFeaturesInActs, withOwnPlaces, withDriveOfStaggering, withoutPattern, withoutBearings, withoutEntailedType];
457
+ const migrateNode = (node) => nodeSteps.reduce((result, step) => step(result), node);
458
+ /** The value with every node in it migrated, a node before its children; the very same value where nothing changed. */
468
459
  const walk = (value) => {
469
460
  if (Array.isArray(value))
470
- return walked(value);
461
+ return mapped(value, walk);
471
462
  if (value && typeof value === 'object')
472
- return withWalkedChildren(migrateNode(value));
463
+ return withValues(migrateNode(value), walk);
473
464
  return value;
474
465
  };
475
466
  /** The production of a copy, under whichever of its two names it carries. */
@@ -576,18 +567,21 @@ const statesNoTolerance = (version) => isSingleDerivation(version.basedOn) && !v
576
567
  * The collation tolerance was the edition's before it was stated on
577
568
  * each derivation. An edition written then collated every version at
578
569
  * that one value, so it is written onto every derivation that gives
579
- * none of its own.
570
+ * none of its own, and the edition states it no longer.
580
571
  */
581
572
  const withDerivationTolerance = (edition) => {
582
- const collationTolerance = edition.creation?.collationTolerance;
583
- const versions = Array.isArray(edition.versions) ? edition.versions : [];
584
- if (!collationTolerance || !versions.some(statesNoTolerance))
573
+ if (!edition.creation || !Object.hasOwn(edition.creation, 'collationTolerance'))
585
574
  return edition;
575
+ const { collationTolerance, ...creation } = edition.creation;
576
+ const versions = listAt(edition, 'versions');
586
577
  return {
587
578
  ...edition,
588
- versions: versions.map(version => statesNoTolerance(version)
589
- ? { ...version, basedOn: { ...version.basedOn, collationTolerance } }
590
- : version)
579
+ creation,
580
+ ...(collationTolerance && versions && {
581
+ versions: versions.map(version => statesNoTolerance(version)
582
+ ? { ...version, basedOn: { ...version.basedOn, collationTolerance } }
583
+ : version)
584
+ })
591
585
  };
592
586
  };
593
587
  /** Release 0.58.0 stated a revision of the format, which the format does not state. */
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Finding what an edition holds by its id. Each kind of entity has an
3
+ * index of its own, built from where the edition holds it when first
4
+ * asked for and kept for as long as the state is (`perState`). The index
5
+ * an entity is found in says what it is, so a lookup needs neither a
6
+ * type discriminator nor a cast.
7
+ */
8
+ import { Edition } from "../model/Edition.js";
9
+ import { NestedFeature } from "../model/Feature.js";
10
+ import { AnySymbol } from "../model/Symbol.js";
11
+ import { Version } from "../model/Version.js";
12
+ import { Modification, ProductionEvent, RollCopy } from "../model/RollCopy.js";
13
+ export declare const versionIn: (edition: Pick<Edition, 'versions'>, id: string) => Readonly<Version> | undefined;
14
+ export declare const copyIn: (edition: Pick<Edition, 'copies'>, id: string) => Readonly<RollCopy> | undefined;
15
+ /** A symbol any version inserts. */
16
+ export declare const symbolIn: (edition: Pick<Edition, 'versions'>, id: string) => Readonly<AnySymbol> | undefined;
17
+ /** The symbols under the ids, leaving out an id that names none. */
18
+ export declare const symbolsIn: (edition: Pick<Edition, 'versions'>, ids: readonly string[]) => Readonly<AnySymbol>[];
19
+ /** A feature or a patch on any copy, one a patch bears included. */
20
+ export declare const featureIn: (edition: Pick<Edition, 'copies'>, id: string) => Readonly<NestedFeature> | undefined;
21
+ /** The features and patches under the ids, leaving out an id that names none. */
22
+ export declare const featuresIn: (edition: Pick<Edition, 'copies'>, ids: readonly string[]) => Readonly<NestedFeature>[];
23
+ /** The copy a feature sits on, a patch and everything it bears included. */
24
+ export declare const copyOfFeature: (edition: Pick<Edition, 'copies'>, featureId: string) => Readonly<RollCopy> | undefined;
25
+ /**
26
+ * The act a copy states a feature in: the production event that
27
+ * punched it, or the modification that brought it about. A feature
28
+ * a patch bears came onto the copy with the patch, so the act is
29
+ * the one that glued the patch on. Two features stand in one act
30
+ * where this returns the very same object.
31
+ */
32
+ export declare const actOf: (edition: Pick<Edition, 'copies'>, featureId: string) => Readonly<ProductionEvent | Modification> | undefined;
@@ -0,0 +1,40 @@
1
+ import { withBorneFeatures } from "../model/Feature.js";
2
+ import { insertedBy } from "../model/Version.js";
3
+ import { featuresMadeBy, featuresOf } from "../model/RollCopy.js";
4
+ import { perState } from "./perState.js";
5
+ const byIdIn = (entities) => new Map(entities.map(entity => [entity.id, entity]));
6
+ const versionsById = perState((edition) => byIdIn(edition.versions));
7
+ const copiesById = perState((edition) => byIdIn(edition.copies));
8
+ const symbolsById = perState((edition) => byIdIn(edition.versions.flatMap(insertedBy)));
9
+ /** Every feature and patch on the copies, those a patch bears included. */
10
+ const featuresOnCopies = (edition) => edition.copies.flatMap(copy => featuresOf(copy).flatMap(withBorneFeatures).map(feature => ({ feature, copy })));
11
+ const featuresById = perState((edition) => new Map(featuresOnCopies(edition).map(({ feature }) => [feature.id, feature])));
12
+ const copiesByFeature = perState((edition) => new Map(featuresOnCopies(edition).map(({ feature, copy }) => [feature.id, copy])));
13
+ export const versionIn = (edition, id) => versionsById(edition).get(id);
14
+ export const copyIn = (edition, id) => copiesById(edition).get(id);
15
+ /** A symbol any version inserts. */
16
+ export const symbolIn = (edition, id) => symbolsById(edition).get(id);
17
+ /** The symbols under the ids, leaving out an id that names none. */
18
+ export const symbolsIn = (edition, ids) => ids.flatMap(id => symbolIn(edition, id) ?? []);
19
+ /** A feature or a patch on any copy, one a patch bears included. */
20
+ export const featureIn = (edition, id) => featuresById(edition).get(id);
21
+ /** The features and patches under the ids, leaving out an id that names none. */
22
+ export const featuresIn = (edition, ids) => ids.flatMap(id => featureIn(edition, id) ?? []);
23
+ /** The copy a feature sits on, a patch and everything it bears included. */
24
+ export const copyOfFeature = (edition, featureId) => copiesByFeature(edition).get(featureId);
25
+ /**
26
+ * The act a copy states a feature in: the production event that
27
+ * punched it, or the modification that brought it about. A feature
28
+ * a patch bears came onto the copy with the patch, so the act is
29
+ * the one that glued the patch on. Two features stand in one act
30
+ * where this returns the very same object.
31
+ */
32
+ export const actOf = (edition, featureId) => {
33
+ const copy = copyOfFeature(edition, featureId);
34
+ if (!copy)
35
+ return undefined;
36
+ const states = (features) => features.flatMap(withBorneFeatures).some(feature => feature.id === featureId);
37
+ if (states(copy.production?.produced ?? []))
38
+ return copy.production;
39
+ return copy.modifications.find(act => states(featuresMadeBy(act)));
40
+ };
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Where in an edition each id stands and where it is referenced, as
3
+ * paths an operation can follow into a draft of it.
4
+ */
5
+ import { Edition } from "../model/Edition.js";
6
+ export type Path = (string | number)[];
7
+ export declare const getAt: <T>(path: Path, obj: unknown) => T | undefined;
8
+ /** Where the entity with the id stands in the edition, or nothing where it holds none. */
9
+ export declare const pathIn: (edition: Edition, id: string) => Path | undefined;
10
+ /** Where the edition references the id. */
11
+ export declare const linksTo: (edition: Edition, id: string) => Path[];
@@ -0,0 +1,78 @@
1
+ import { perState } from "./perState.js";
2
+ export const getAt = (path, obj) => {
3
+ let node = obj;
4
+ for (const key of path) {
5
+ if (node == null)
6
+ return undefined;
7
+ node = node[key];
8
+ }
9
+ return node;
10
+ };
11
+ /** Keys under which an object names others by id, singly or in a list. */
12
+ const referenceKeys = ['delete', 'comprehends', 'motivation', 'premises', 'used'];
13
+ const isObject = (v) => v !== null && typeof v === "object";
14
+ /** What a reference may state besides the id: a belief about it, and the tolerance a derivation was collated at. */
15
+ const referenceOwnKeys = new Set(['id', '@annotation', 'collationTolerance']);
16
+ /** An object that names another by its id and says nothing of its own beyond that. */
17
+ const isReferenceOnly = (keys) => keys.every(key => referenceOwnKeys.has(key));
18
+ const laidOut = (trail) => {
19
+ const path = [];
20
+ for (let link = trail; link !== null; link = link.up)
21
+ path.push(link.key);
22
+ return path.reverse();
23
+ };
24
+ /** Walks the edition and records where each id stands and where it is referenced. */
25
+ const placesIn = perState((edition) => {
26
+ const paths = new Map();
27
+ const links = new Map();
28
+ const visited = new WeakSet();
29
+ const link = (id, trail) => {
30
+ const trails = links.get(id);
31
+ if (trails)
32
+ trails.push(trail);
33
+ else
34
+ links.set(id, [trail]);
35
+ };
36
+ const index = (record, keys, trail) => {
37
+ if (typeof record.id !== "string")
38
+ return;
39
+ if (isReferenceOnly(keys))
40
+ link(record.id, { key: 'id', up: trail });
41
+ else if (!paths.has(record.id)) {
42
+ paths.set(record.id, trail);
43
+ }
44
+ };
45
+ const linkReferences = (record, trail) => referenceKeys.forEach(key => {
46
+ const ref = record[key];
47
+ if (typeof ref === "string")
48
+ link(ref, { key, up: trail });
49
+ else if (Array.isArray(ref))
50
+ ref.forEach((r, i) => {
51
+ if (typeof r === "string")
52
+ link(r, { key: i, up: { key, up: trail } });
53
+ });
54
+ });
55
+ const traverse = (node, trail) => {
56
+ if (!isObject(node) || visited.has(node))
57
+ return;
58
+ visited.add(node);
59
+ if (Array.isArray(node)) {
60
+ node.forEach((item, i) => traverse(item, { key: i, up: trail }));
61
+ return;
62
+ }
63
+ const record = node;
64
+ const keys = Object.keys(record);
65
+ index(record, keys, trail);
66
+ linkReferences(record, trail);
67
+ keys.forEach(key => traverse(record[key], { key, up: trail }));
68
+ };
69
+ traverse(edition, null);
70
+ return { paths, links };
71
+ });
72
+ /** Where the entity with the id stands in the edition, or nothing where it holds none. */
73
+ export const pathIn = (edition, id) => {
74
+ const trail = placesIn(edition).paths.get(id);
75
+ return trail === undefined ? undefined : laidOut(trail);
76
+ };
77
+ /** Where the edition references the id. */
78
+ export const linksTo = (edition, id) => (placesIn(edition).links.get(id) ?? []).map(laidOut);
@@ -0,0 +1,32 @@
1
+ import { Draft } from "immer";
2
+ /**
3
+ * The draft as it stands, as plain data: the state it was drafted from
4
+ * while nothing has changed it, and a copy of it as it now stands once
5
+ * something has.
6
+ */
7
+ export declare const takenOf: <T extends object>(draft: Draft<T>) => T;
8
+ /**
9
+ * The edition as a state that no longer changes. It is frozen, deeply
10
+ * and once, as immer freezes what it produces, since what is worked out
11
+ * from a state is kept for as long as the state is: changed in place
12
+ * afterwards, it would leave that behind unnoticed, and frozen, the
13
+ * change throws instead. An edition immer produced is frozen already,
14
+ * and freezing stops at whatever is. A copy taken of a draft is left as
15
+ * it is (`takenOf`).
16
+ *
17
+ * A draft is no such state, since the next write changes it. It is read
18
+ * as it stands by taking `stateOf(draft)` first, once for all that is
19
+ * asked of it; asked of directly, it would have to be copied for every
20
+ * question.
21
+ */
22
+ export declare const settled: <T extends object>(edition: T) => T;
23
+ /**
24
+ * What is worked out from an edition, once for each state of it.
25
+ *
26
+ * Every change to an edition yields a new object, immer's produce
27
+ * included, so the state an object stands for never changes and what
28
+ * was worked out from it holds for as long as the object is around.
29
+ * Nothing is worked out before it is first asked for, and nothing is
30
+ * kept once the state is gone.
31
+ */
32
+ export declare const perState: <E extends object, T>(work: (edition: E) => T) => ((edition: E) => T);
@@ -0,0 +1,63 @@
1
+ import { current, freeze, isDraft, original } from "immer";
2
+ /**
3
+ * Copies taken of a draft as it stood, for an operation to read. Such a
4
+ * copy is the operation's alone and is not frozen: what the operation
5
+ * reads from it may go into the draft, and a later operation on the same
6
+ * draft may go on to change it there, as it may anything written there.
7
+ */
8
+ const takenOfDrafts = new WeakSet();
9
+ /**
10
+ * The draft as it stands, as plain data: the state it was drafted from
11
+ * while nothing has changed it, and a copy of it as it now stands once
12
+ * something has.
13
+ */
14
+ export const takenOf = (draft) => {
15
+ const state = current(draft);
16
+ if (state !== original(draft))
17
+ takenOfDrafts.add(state);
18
+ return state;
19
+ };
20
+ /**
21
+ * The edition as a state that no longer changes. It is frozen, deeply
22
+ * and once, as immer freezes what it produces, since what is worked out
23
+ * from a state is kept for as long as the state is: changed in place
24
+ * afterwards, it would leave that behind unnoticed, and frozen, the
25
+ * change throws instead. An edition immer produced is frozen already,
26
+ * and freezing stops at whatever is. A copy taken of a draft is left as
27
+ * it is (`takenOf`).
28
+ *
29
+ * A draft is no such state, since the next write changes it. It is read
30
+ * as it stands by taking `stateOf(draft)` first, once for all that is
31
+ * asked of it; asked of directly, it would have to be copied for every
32
+ * question.
33
+ */
34
+ export const settled = (edition) => {
35
+ if (isDraft(edition)) {
36
+ throw new Error('An edition is asked about as a state, not as a draft: take stateOf(draft) first.');
37
+ }
38
+ return takenOfDrafts.has(edition) ? edition : freeze(edition, true);
39
+ };
40
+ /**
41
+ * What is worked out from an edition, once for each state of it.
42
+ *
43
+ * Every change to an edition yields a new object, immer's produce
44
+ * included, so the state an object stands for never changes and what
45
+ * was worked out from it holds for as long as the object is around.
46
+ * Nothing is worked out before it is first asked for, and nothing is
47
+ * kept once the state is gone.
48
+ */
49
+ export const perState = (work) => {
50
+ const known = new WeakMap();
51
+ return edition => {
52
+ // A state known already was settled when it became known, and a
53
+ // draft never is, so only what is asked of for the first time
54
+ // needs settling.
55
+ const kept = known.get(edition);
56
+ if (kept)
57
+ return kept.value;
58
+ const state = settled(edition);
59
+ const entry = { value: work(state) };
60
+ known.set(state, entry);
61
+ return entry.value;
62
+ };
63
+ };
@@ -23,6 +23,10 @@ export type EditType = typeof editTypes[number];
23
23
  * If an edit is the interpretation of a metamark,
24
24
  * such as a pencil mark, this should be made explicit
25
25
  * using a meaning comprehension on the `@annotation` field.
26
+ * An edit states no date. That it ended no later than the act that
27
+ * made a feature carrying a symbol it inserts, a reasoner derives with
28
+ * the axioms of reo.ttl; which of those dates bounds it closest is for
29
+ * a query to pick.
26
30
  * @see reo:Edit
27
31
  */
28
32
  export interface Edit extends WithId, Assumption {
@@ -1,6 +1,5 @@
1
1
  import { RollCopy } from "./RollCopy.js";
2
2
  import { Version } from "./Version.js";
3
- import { CollationTolerance } from "../collation/Collation.js";
4
3
  import { DateAssignment, ObjectAssumption } from "./Assumption.js";
5
4
  import { Editor, Person, Place } from "./Agent.js";
6
5
  import { RollTempo } from "../systems/ReproducingSystem.js";
@@ -28,18 +27,6 @@ export interface EditionCreation {
28
27
  * @see dcterms:date
29
28
  */
30
29
  publicationDate: Date;
31
- /**
32
- * The tolerance every version of the edition was collated at,
33
- * before each derivation stated its own. How precisely two copies
34
- * place a symbol depends on which two they are, so the tolerance
35
- * belongs to the derivation, `Derivation.collationTolerance`, and
36
- * migration writes this one onto every derivation that gives none.
37
- * Nothing else reads it. A window's offset is the displacement
38
- * between two particular copies and so can never be stated here.
39
- * Not exported to RDF.
40
- * @deprecated
41
- */
42
- collationTolerance?: CollationTolerance;
43
30
  }
44
31
  /**
45
32
  * Describes the event of recording and documents
@@ -93,7 +93,13 @@ export interface Version extends WithId {
93
93
  basedOn?: Derivation[];
94
94
  /**
95
95
  * The act that made this version, where it is known: who carried it
96
- * out, when, and by what rule.
96
+ * out, when, and by what rule. The export states the act for every
97
+ * version, stating nothing of it where nothing is known, so that the
98
+ * axioms of reo.ttl can place it in time: it started after the
99
+ * recording and the creation of every version it derives from had
100
+ * started, and ended no later than the punching of any copy carrying
101
+ * a symbol it added. A date stated here stands beside those; which of
102
+ * them bounds the act closest is for a query to pick.
97
103
  * @see lrmoo:R17i was created by
98
104
  */
99
105
  creation?: VersionCreation;
@@ -1,4 +1,4 @@
1
- import { Path } from "../view/EditionView.js";
1
+ import { Path } from "../lookup/paths.js";
2
2
  import { AnyArgumentation, Certainty } from "../model/Assumption.js";
3
3
  import { EditionOp } from "./draft.js";
4
4
  /** Annotates the assumption at the path with a belief held true, for reasons to be added. */
@@ -1,5 +1,5 @@
1
1
  import { v4 } from "uuid";
2
- import { getAt } from "../view/EditionView.js";
2
+ import { getAt } from "../lookup/paths.js";
3
3
  const onAssumptionAt = (path, op) => draft => {
4
4
  const assumption = getAt(path, draft);
5
5
  if (assumption)
@@ -1,4 +1,3 @@
1
- import { EditionView } from "../view/EditionView.js";
2
1
  import { CollationTolerance } from "../collation/Collation.js";
3
2
  import { ObjectAssumption } from "../model/Assumption.js";
4
3
  import { EditionOp } from "./draft.js";
@@ -28,13 +27,13 @@ import { EditionOp } from "./draft.js";
28
27
  * statement, since the stemma would loop; asked for that, nothing
29
28
  * changes.
30
29
  */
31
- export declare const connectVersions: (given: EditionView, childId: string, parentId: string, tolerance?: ObjectAssumption<CollationTolerance>) => EditionOp;
30
+ export declare const connectVersions: (childId: string, parentId: string, tolerance?: ObjectAssumption<CollationTolerance>) => EditionOp;
32
31
  /**
33
32
  * Folds the version's own symbols into those it inherits and collates
34
33
  * with: the carriers pass over, and the insertions go. Collates at the
35
34
  * tolerance of the derivation, where the caller names none.
36
35
  */
37
- export declare const collateSymbols: (given: EditionView, versionId: string, symbolIds: readonly string[], tolerance?: CollationTolerance) => EditionOp;
36
+ export declare const collateSymbols: (versionId: string, symbolIds: readonly string[], tolerance?: CollationTolerance) => EditionOp;
38
37
  /**
39
38
  * Takes the named copies' reading of a symbol back out of the symbol it
40
39
  * was collated into: their carriers pass to a new symbol of the
@@ -59,4 +58,4 @@ export declare const collateSymbols: (given: EditionView, versionId: string, sym
59
58
  * keeps its identifier and the edit that speaks for it. Named symbols
60
59
  * narrow the act to those; naming none separates the whole reading.
61
60
  */
62
- export declare const separateReadings: (given: EditionView, versionId: string, copies: ReadonlySet<string>, symbolIds?: readonly string[]) => EditionOp;
61
+ export declare const separateReadings: (versionId: string, copies: ReadonlySet<string>, symbolIds?: readonly string[]) => EditionOp;
@@ -1,15 +1,17 @@
1
1
  import { v4 } from "uuid";
2
- import { getAt } from "../view/EditionView.js";
2
+ import { getAt, pathIn } from "../lookup/paths.js";
3
3
  import { collationsOf, defaultCollationTolerance, isCollationsOwn, unchecked } from "../collation/Collation.js";
4
4
  import { collationToleranceOf, derivesFrom, editsOf, insertedBy, principalDerivationOf } from "../model/Version.js";
5
5
  import { substitutionsBetween } from "../collation/substitution.js";
6
6
  import { trackerBarOf } from "../systems/index.js";
7
7
  import { assignReference, idOf } from "../model/Assumption.js";
8
- import { noChange, onVersion, stateOf, insertion, deletion, asUnchecked, declaring, insertedIn, dropInsertions, reading } from "./draft.js";
8
+ import { noChange, onVersion, insertion, deletion, asUnchecked, declaring, dropInsertions, reading } from "./draft.js";
9
9
  import { hypothesesBeside } from "./versions.js";
10
+ import { placeOf, snapshotOf } from "../analysis/text.js";
11
+ import { copyOfFeature, versionIn } from "../lookup/lookup.js";
10
12
  /** The carriers of each collated symbol pass to its counterpart. */
11
- const handOverCarriers = (view, draft, collations) => collations.forEach(({ symbol, counterpart }) => {
12
- const path = view.getPath(counterpart.id);
13
+ const handOverCarriers = (edition, draft, collations) => collations.forEach(({ symbol, counterpart }) => {
14
+ const path = pathIn(edition, counterpart.id);
13
15
  const target = path && getAt(path, draft);
14
16
  target?.carriers.push(...symbol.carriers);
15
17
  });
@@ -59,10 +61,10 @@ const byExchange = (edits) => new Map(edits.map(edit => [exchangeKey((edit.inser
59
61
  * statement, since the stemma would loop; asked for that, nothing
60
62
  * changes.
61
63
  */
62
- export const connectVersions = (given, childId, parentId, tolerance = defaultCollationTolerance) => reading(given, view => {
63
- if (childId === parentId || derivesFrom(view.edition.versions, parentId, childId))
64
+ export const connectVersions = (childId, parentId, tolerance = defaultCollationTolerance) => reading(edition => {
65
+ if (childId === parentId || derivesFrom(edition.versions, parentId, childId))
64
66
  return noChange;
65
- const child = view.version(childId);
67
+ const child = versionIn(edition, childId);
66
68
  const stated = child ? editsOf(child) : [];
67
69
  const established = stated.filter(edit => !isCollationsOwn(edit));
68
70
  const spokenFor = spokenForBy(established);
@@ -71,12 +73,12 @@ export const connectVersions = (given, childId, parentId, tolerance = defaultCol
71
73
  // through: it is neither the child's own symbol nor one it lacks.
72
74
  // Without that, connecting a pair already connected would collate
73
75
  // the inherited symbols with themselves and double their carriers.
74
- const handedDown = view.snapshot(parentId).filter(unspoken);
75
- const shown = new Set(view.snapshot(childId).map(symbol => symbol.id));
76
+ const handedDown = snapshotOf(edition, parentId).filter(unspoken);
77
+ const shown = new Set(snapshotOf(edition, childId).map(symbol => symbol.id));
76
78
  const inheritedIds = new Set(handedDown.map(symbol => symbol.id));
77
79
  const inherited = handedDown.filter(symbol => !shown.has(symbol.id));
78
- const own = view.snapshot(childId).filter(symbol => unspoken(symbol) && !inheritedIds.has(symbol.id));
79
- const locate = (symbol) => view.placeOf(symbol);
80
+ const own = snapshotOf(edition, childId).filter(symbol => unspoken(symbol) && !inheritedIds.has(symbol.id));
81
+ const locate = (symbol) => placeOf(edition, symbol);
80
82
  const collations = collationsOf(own, inherited, locate, tolerance);
81
83
  const collated = new Set(collations.map(({ symbol }) => symbol.id));
82
84
  const matched = new Set(collations.map(({ counterpart }) => counterpart.id));
@@ -87,7 +89,7 @@ export const connectVersions = (given, childId, parentId, tolerance = defaultCol
87
89
  * apart would make the apparatus a list of unexplained losses beside
88
90
  * a list of unexplained gains.
89
91
  */
90
- const substituted = differ(child, view.version(parentId))
92
+ const substituted = differ(child, versionIn(edition, parentId))
91
93
  ? substitutionsBetween(own.filter(symbol => !collated.has(symbol.id)), inherited.filter(symbol => !matched.has(symbol.id)), locate, tolerance)
92
94
  : [];
93
95
  const paired = new Set(substituted.flatMap(({ replaced, by }) => [...by, ...replaced].map(symbol => symbol.id)));
@@ -112,14 +114,18 @@ export const connectVersions = (given, childId, parentId, tolerance = defaultCol
112
114
  .filter(symbol => !matched.has(symbol.id) && !paired.has(symbol.id))
113
115
  .map(symbol => asUnchecked(deletion(symbol.id)))
114
116
  ];
115
- return onVersion(childId, (child, draft) => {
116
- handOverCarriers(view, draft, collations);
117
- child.edits = edits;
118
- child.motivations = declaring(stateOf(child).motivations, edits);
119
- child.basedOn = [
120
- { ...assignReference(parentId), collationTolerance: tolerance },
121
- ...hypothesesBeside(stateOf(child), parentId)
122
- ];
117
+ // Read off the child as it stands, since once its edits are written a
118
+ // reading of it would copy them all.
119
+ const motivations = declaring(child?.motivations ?? [], edits);
120
+ const basedOn = [
121
+ { ...assignReference(parentId), collationTolerance: tolerance },
122
+ ...(child ? hypothesesBeside(child, parentId) : [])
123
+ ];
124
+ return onVersion(childId, (version, draft) => {
125
+ handOverCarriers(edition, draft, collations);
126
+ version.edits = edits;
127
+ version.motivations = motivations;
128
+ version.basedOn = basedOn;
123
129
  });
124
130
  });
125
131
  /**
@@ -127,17 +133,17 @@ export const connectVersions = (given, childId, parentId, tolerance = defaultCol
127
133
  * with: the carriers pass over, and the insertions go. Collates at the
128
134
  * tolerance of the derivation, where the caller names none.
129
135
  */
130
- export const collateSymbols = (given, versionId, symbolIds, tolerance) => reading(given, view => {
131
- const version = view.version(versionId);
136
+ export const collateSymbols = (versionId, symbolIds, tolerance) => reading(edition => {
137
+ const version = versionIn(edition, versionId);
132
138
  const principal = version && principalDerivationOf(version);
133
139
  if (!version || !principal)
134
140
  return noChange;
135
141
  const chosen = new Set(symbolIds);
136
- const own = insertedIn([version]).filter(symbol => chosen.has(symbol.id));
137
- const collations = collationsOf(own, view.snapshot(idOf(principal)), symbol => view.placeOf(symbol), tolerance ?? collationToleranceOf(principal));
142
+ const own = insertedBy(version).filter(symbol => chosen.has(symbol.id));
143
+ const collations = collationsOf(own, snapshotOf(edition, idOf(principal)), symbol => placeOf(edition, symbol), tolerance ?? collationToleranceOf(principal));
138
144
  const collated = new Set(collations.map(({ symbol }) => symbol.id));
139
145
  return onVersion(versionId, (version, draft) => {
140
- handOverCarriers(view, draft, collations);
146
+ handOverCarriers(edition, draft, collations);
141
147
  dropInsertions(version, collated);
142
148
  });
143
149
  });
@@ -163,9 +169,9 @@ const readingOf = (symbol, carriers) => {
163
169
  * where the two versions do not disagree and there is nothing to take
164
170
  * apart.
165
171
  */
166
- const sharedWith = (view, symbol, copies) => {
172
+ const sharedWith = (edition, symbol, copies) => {
167
173
  const onNamedCopy = (carrier) => {
168
- const copy = view.copyOf(idOf(carrier));
174
+ const copy = copyOfFeature(edition, idOf(carrier));
169
175
  return copy !== undefined && copies.has(copy.id);
170
176
  };
171
177
  const mine = symbol.carriers.filter(onNamedCopy);
@@ -196,14 +202,14 @@ const sharedWith = (view, symbol, copies) => {
196
202
  * keeps its identifier and the edit that speaks for it. Named symbols
197
203
  * narrow the act to those; naming none separates the whole reading.
198
204
  */
199
- export const separateReadings = (given, versionId, copies, symbolIds) => reading(given, view => {
200
- const version = view.version(versionId);
205
+ export const separateReadings = (versionId, copies, symbolIds) => reading(edition => {
206
+ const version = versionIn(edition, versionId);
201
207
  if (!version)
202
208
  return noChange;
203
209
  const chosen = symbolIds && new Set(symbolIds);
204
- const shared = view.snapshot(versionId)
210
+ const shared = snapshotOf(edition, versionId)
205
211
  .filter(symbol => chosen === undefined || chosen.has(symbol.id))
206
- .flatMap(symbol => sharedWith(view, symbol, copies));
212
+ .flatMap(symbol => sharedWith(edition, symbol, copies));
207
213
  if (shared.length === 0)
208
214
  return noChange;
209
215
  const inserted = new Set(insertedBy(version).map(symbol => symbol.id));
@@ -218,7 +224,7 @@ export const separateReadings = (given, versionId, copies, symbolIds) => reading
218
224
  }));
219
225
  return onVersion(versionId, (version, draft) => {
220
226
  shared.forEach(({ symbol, theirs }) => {
221
- const path = view.getPath(symbol.id);
227
+ const path = pathIn(edition, symbol.id);
222
228
  const target = path && getAt(path, draft);
223
229
  if (target)
224
230
  target.carriers = theirs;
@@ -1,9 +1,8 @@
1
- import { EditionView } from "../view/EditionView.js";
2
1
  import { PlacementRelation } from "../model/Symbol.js";
3
2
  import { EditionOp } from "./draft.js";
4
3
  /** States how the follower is placed relative to the reference, in place of any earlier statement. */
5
- export declare const placeCommand: (view: EditionView, followerId: string, referenceId: string, relation: PlacementRelation) => EditionOp;
6
- export declare const unplaceCommand: (view: EditionView, followerId: string) => EditionOp;
4
+ export declare const placeCommand: (followerId: string, referenceId: string, relation: PlacementRelation) => EditionOp;
5
+ export declare const unplaceCommand: (followerId: string) => EditionOp;
7
6
  /** The pair is stated on `statingId` only, as the format asks. */
8
- export declare const pairCommands: (view: EditionView, statingId: string, partnerId: string) => EditionOp;
9
- export declare const unpairCommand: (view: EditionView, statingId: string) => EditionOp;
7
+ export declare const pairCommands: (statingId: string, partnerId: string) => EditionOp;
8
+ export declare const unpairCommand: (statingId: string) => EditionOp;