linked-rolls 0.55.0 → 0.57.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.
package/README.md CHANGED
@@ -230,15 +230,21 @@ Three kinds of act rather than two, because the CRM tells them apart.
230
230
  E79 Part Addition asks that what is added be "a separate identifiable
231
231
  whole prior to" the act, which a glued-on label is and a pencil line is
232
232
  not: drawing, writing and punching bring a feature into being and are
233
- productions (E12), which state what they made with P108 has produced.
233
+ productions (E12), which state what they made with `reo:produced`, a
234
+ subproperty of P108 has produced.
234
235
 
235
- The export states what that shape only implies. A copy bears every
236
+ The format states nothing a reasoner can derive. That a copy bears every
236
237
  feature its acts brought about (P56 bears feature) and is composed of
237
238
  the patches glued onto it (P46 is composed of, a patch being an object
238
- rather than a feature); an attachment augments the copy and a removal
239
- diminishes it. The four keys are derived on the way out and read off
240
- again on the way in, so they are no part of the edition, and they are
241
- the one place where the JSON tree and the graph differ in shape.
239
+ rather than a feature) follows from property chains in `reo.ttl`, all
240
+ within OWL 2 RL. The chain for the punching runs over `reo:produced`
241
+ rather than P108, because R28 produced is itself a subproperty of P108
242
+ (LRMoo 1.0, p. 44), and a chain over P108 would have the copy bear
243
+ itself. That an attachment augments the copy and a removal diminishes
244
+ it depends on the class of the act, which no chain can test. These two
245
+ keys are derived on the way out and read off again on the way in, so
246
+ they are no part of the edition, and they are the one place where the
247
+ JSON tree and the graph differ in shape.
242
248
 
243
249
  ## Where a copy's features come from
244
250
 
@@ -1,11 +1,10 @@
1
- import { WithType } from "./utils.js";
2
1
  /**
3
2
  * Physical condition of a roll or
4
3
  * of a feature on the roll (e.g. a damaged
5
4
  * or unsuccessful perforation).
6
5
  * @see crm:E3 Condition State
7
6
  */
8
- export interface ConditionState<T extends string> extends WithType<'ConditionState'> {
7
+ export interface ConditionState<T extends string> {
9
8
  /**
10
9
  * The kind of condition, from the list the roll or
11
10
  * the kind of feature allows.
@@ -1,5 +1,5 @@
1
1
  import { Edition } from "./Edition.js";
2
- import { HorizontalSpan, FeatureOrPatch } from "./Feature.js";
2
+ import { FeatureOrPatch, HorizontalSpan, NestedFeature } from "./Feature.js";
3
3
  import { AnySymbol, Expression, Note } from "./Symbol.js";
4
4
  import { Version } from "./Version.js";
5
5
  import { NegotiatedEvent } from "./ReproducingSystem.js";
@@ -10,10 +10,6 @@ export type Path = (string | number)[];
10
10
  export declare const getAt: <T>(path: Path, obj: unknown) => T | undefined;
11
11
  export declare class EditionView {
12
12
  readonly edition: Edition;
13
- /**
14
- * Map from id to object
15
- */
16
- private readonly byId;
17
13
  /**
18
14
  * Map from id to its path within the edition
19
15
  */
@@ -24,17 +20,35 @@ export declare class EditionView {
24
20
  private readonly links;
25
21
  /** Built when a copy is first asked for, the walk not recording it. */
26
22
  private copiesByFeature?;
23
+ /**
24
+ * One index for each kind of entity, built from where the edition
25
+ * holds it. The index an entity is found in says what it is, so a
26
+ * lookup needs neither a type discriminator nor a cast.
27
+ */
28
+ private readonly versionsById;
29
+ private readonly copiesById;
30
+ private readonly symbolsById;
31
+ private featuresById?;
27
32
  constructor(edition: Edition);
28
33
  atPath<T>(path: Path): T | null;
29
34
  indexObjects(): void;
30
- get<T>(anyId: string): T | undefined;
31
- getAll<T>(anyIds: readonly string[]): T[];
35
+ version(id: string): Readonly<Version> | undefined;
36
+ copy(id: string): Readonly<RollCopy> | undefined;
37
+ symbol(id: string): Readonly<AnySymbol> | undefined;
38
+ /** The symbols under the ids, leaving out an id that names none. */
39
+ symbols(ids: readonly string[]): Readonly<AnySymbol>[];
40
+ /** A feature or a patch on any copy, one a patch bears included. */
41
+ feature(id: string): Readonly<NestedFeature> | undefined;
42
+ /** The features and patches under the ids, leaving out an id that names none. */
43
+ features(ids: readonly string[]): Readonly<NestedFeature>[];
32
44
  getPath(anyId: string): Path | undefined;
33
45
  linksTo(anyId: string): Path[];
34
46
  travelUp(versionId: string, callback: (version: Readonly<Version>) => void): void;
35
47
  /** The version and its ancestors along the principal line, from the version up to the root. */
36
48
  lineageOf(versionId: string): Readonly<Version>[];
37
- carriersOf(symbol: AnySymbol): Readonly<FeatureOrPatch>[];
49
+ carriersOf(symbol: AnySymbol): Readonly<NestedFeature>[];
50
+ /** The carriers that state a place of their own, which a feature on a patch does not. */
51
+ placedCarriersOf(symbol: AnySymbol): Readonly<FeatureOrPatch>[];
38
52
  /** The copy a feature sits on, a patch and everything it bears included. */
39
53
  copyOf(featureId: string): Readonly<RollCopy> | undefined;
40
54
  /**
@@ -1,4 +1,4 @@
1
- import { withBorneFeatures } from "./Feature.js";
1
+ import { isPlaced, withBorneFeatures } from "./Feature.js";
2
2
  import { deletedBy, insertedBy, principalDerivationOf } from "./Version.js";
3
3
  import { systemIdOf } from "./TrackerBar.js";
4
4
  import { featuresMadeBy, featuresOf, isPaperStretch } from "./RollCopy.js";
@@ -15,6 +15,7 @@ export const getAt = (path, obj) => {
15
15
  };
16
16
  /** Keys under which an object names others by id, singly or in a list. */
17
17
  const referenceKeys = ['delete', 'comprehends', 'motivation', 'premises', 'used'];
18
+ const byIdIn = (entities) => new Map(entities.map(entity => [entity.id, entity]));
18
19
  const isObject = (v) => v !== null && typeof v === "object";
19
20
  /** What a reference may state besides the id: a belief about it, and the tolerance a derivation was collated at. */
20
21
  const referenceOwnKeys = new Set(['id', '@annotation', 'collationTolerance']);
@@ -34,15 +35,6 @@ export class EditionView {
34
35
  writable: true,
35
36
  value: void 0
36
37
  });
37
- /**
38
- * Map from id to object
39
- */
40
- Object.defineProperty(this, "byId", {
41
- enumerable: true,
42
- configurable: true,
43
- writable: true,
44
- value: new Map()
45
- });
46
38
  /**
47
39
  * Map from id to its path within the edition
48
40
  */
@@ -68,7 +60,39 @@ export class EditionView {
68
60
  writable: true,
69
61
  value: void 0
70
62
  });
63
+ /**
64
+ * One index for each kind of entity, built from where the edition
65
+ * holds it. The index an entity is found in says what it is, so a
66
+ * lookup needs neither a type discriminator nor a cast.
67
+ */
68
+ Object.defineProperty(this, "versionsById", {
69
+ enumerable: true,
70
+ configurable: true,
71
+ writable: true,
72
+ value: void 0
73
+ });
74
+ Object.defineProperty(this, "copiesById", {
75
+ enumerable: true,
76
+ configurable: true,
77
+ writable: true,
78
+ value: void 0
79
+ });
80
+ Object.defineProperty(this, "symbolsById", {
81
+ enumerable: true,
82
+ configurable: true,
83
+ writable: true,
84
+ value: void 0
85
+ });
86
+ Object.defineProperty(this, "featuresById", {
87
+ enumerable: true,
88
+ configurable: true,
89
+ writable: true,
90
+ value: void 0
91
+ });
71
92
  this.edition = edition;
93
+ this.versionsById = byIdIn(edition.versions);
94
+ this.copiesById = byIdIn(edition.copies);
95
+ this.symbolsById = byIdIn(edition.versions.flatMap(insertedBy));
72
96
  this.indexObjects();
73
97
  }
74
98
  atPath(path) {
@@ -89,8 +113,7 @@ export class EditionView {
89
113
  return;
90
114
  if (isReferenceOnly(keys))
91
115
  link(record.id, { key: 'id', up: trail });
92
- else if (!this.byId.has(record.id)) {
93
- this.byId.set(record.id, record);
116
+ else if (!this.paths.has(record.id)) {
94
117
  this.paths.set(record.id, trail);
95
118
  }
96
119
  };
@@ -120,11 +143,27 @@ export class EditionView {
120
143
  };
121
144
  traverse(this.edition, null);
122
145
  }
123
- get(anyId) {
124
- return this.byId.get(anyId);
146
+ version(id) {
147
+ return this.versionsById.get(id);
148
+ }
149
+ copy(id) {
150
+ return this.copiesById.get(id);
125
151
  }
126
- getAll(anyIds) {
127
- return anyIds.map(id => this.get(id)).filter((v) => !!v);
152
+ symbol(id) {
153
+ return this.symbolsById.get(id);
154
+ }
155
+ /** The symbols under the ids, leaving out an id that names none. */
156
+ symbols(ids) {
157
+ return ids.flatMap(id => this.symbol(id) ?? []);
158
+ }
159
+ /** A feature or a patch on any copy, one a patch bears included. */
160
+ feature(id) {
161
+ this.featuresById ?? (this.featuresById = byIdIn(this.edition.copies.flatMap(copy => featuresOf(copy).flatMap(withBorneFeatures))));
162
+ return this.featuresById.get(id);
163
+ }
164
+ /** The features and patches under the ids, leaving out an id that names none. */
165
+ features(ids) {
166
+ return ids.flatMap(id => this.feature(id) ?? []);
128
167
  }
129
168
  getPath(anyId) {
130
169
  const trail = this.paths.get(anyId);
@@ -134,7 +173,7 @@ export class EditionView {
134
173
  return (this.links.get(anyId) ?? []).map(pathOf);
135
174
  }
136
175
  travelUp(versionId, callback) {
137
- const v = this.get(versionId);
176
+ const v = this.version(versionId);
138
177
  if (!v)
139
178
  return;
140
179
  callback(v);
@@ -150,7 +189,11 @@ export class EditionView {
150
189
  return lineage;
151
190
  }
152
191
  carriersOf(symbol) {
153
- return this.getAll(idsOf(symbol.carriers));
192
+ return this.features(idsOf(symbol.carriers));
193
+ }
194
+ /** The carriers that state a place of their own, which a feature on a patch does not. */
195
+ placedCarriersOf(symbol) {
196
+ return this.carriersOf(symbol).filter(isPlaced);
154
197
  }
155
198
  /** The copy a feature sits on, a patch and everything it bears included. */
156
199
  copyOf(featureId) {
@@ -220,9 +263,9 @@ export class EditionView {
220
263
  }
221
264
  /** The version the given one's text is read against, by its principal derivation. */
222
265
  predecessorOf(versionId) {
223
- const v = this.get(versionId);
266
+ const v = this.version(versionId);
224
267
  const principal = v && principalDerivationOf(v);
225
- return principal && this.get(idOf(principal));
268
+ return principal && this.version(idOf(principal));
226
269
  }
227
270
  /**
228
271
  * Where along the roll the symbol lies, as its carriers put it, or
@@ -238,7 +281,7 @@ export class EditionView {
238
281
  * position a semitone away on either bar.
239
282
  */
240
283
  placeOf(symbol) {
241
- const carriers = this.getAll(idsOf(symbol.carriers));
284
+ const carriers = this.placedCarriersOf(symbol);
242
285
  if (carriers.length === 0)
243
286
  return;
244
287
  return {
@@ -282,7 +325,7 @@ export class EditionView {
282
325
  if (inStack.has(id)) {
283
326
  throw new Error(`Cycle detected involving node '${id}'. Check parentId links.`);
284
327
  }
285
- const node = this.get(id);
328
+ const node = this.version(id);
286
329
  if (!node) {
287
330
  memo.set(id, 0);
288
331
  return 0;
@@ -294,7 +337,7 @@ export class EditionView {
294
337
  if (basedOn === undefined) {
295
338
  gen = 0; // root
296
339
  }
297
- else if (!this.get(basedOn)) {
340
+ else if (!this.version(basedOn)) {
298
341
  // Orphaned parent reference — treat boundary as root
299
342
  gen = 0;
300
343
  }
package/lib/Emulation.js CHANGED
@@ -17,10 +17,10 @@ const propertiesOf = (view, version) => ({
17
17
  });
18
18
  /** The onset a symbol has on each copy carrying it, by the copy's index, as the mean of its chains there. */
19
19
  const onsetsByCopy = (view, symbolId) => {
20
- const symbol = view.get(symbolId);
20
+ const symbol = view.symbol(symbolId);
21
21
  if (!symbol)
22
22
  return new Map();
23
- const onsets = view.carriersOf(symbol).flatMap((carrier) => {
23
+ const onsets = view.placedCarriersOf(symbol).flatMap((carrier) => {
24
24
  const copy = view.getPath(carrier.id)?.[1];
25
25
  return typeof copy === 'number' ? [[copy, carrier.horizontal.from]] : [];
26
26
  });
package/lib/Feature.d.ts CHANGED
@@ -53,12 +53,12 @@ export interface VerticalSpan {
53
53
  */
54
54
  to?: Track;
55
55
  }
56
- export declare const featureTypes: readonly ['HoleChain', 'Writing', 'Mark', 'GluedOn'];
56
+ export declare const featureTypes: readonly ['HoleChain', 'Writing', 'Mark', 'Patch'];
57
57
  export type FeatureType = typeof featureTypes[number];
58
58
  export declare const isFeatureType: (value: unknown) => value is FeatureType;
59
59
  /**
60
60
  * A feature on the roll, e.g. a perforation, a writing, a mark or a
61
- * glued-on patch, defined by its horizontal and vertical position and
61
+ * patch, defined by its horizontal and vertical position and
62
62
  * extent. Each kind of feature is a class of its own, which its type
63
63
  * names.
64
64
  */
@@ -89,7 +89,7 @@ export declare const conditions: {
89
89
  readonly HoleChain: readonly ["partially-torn", "missing-perforation"];
90
90
  readonly Writing: readonly ["illegible"];
91
91
  readonly Mark: readonly ["faded"];
92
- readonly GluedOn: readonly ["detaching", "ripped"];
92
+ readonly Patch: readonly ["detaching", "ripped"];
93
93
  };
94
94
  /** The kinds of condition a feature may be in, whichever kind of feature it is. */
95
95
  export type FeatureConditionType = typeof conditions[FeatureType][number];
@@ -191,15 +191,14 @@ export interface Writing extends Trace<'Writing'> {
191
191
  export interface Mark extends Trace<'Mark'> {
192
192
  }
193
193
  /**
194
- * A piece of material (paper or tape) glued onto the roll surface.
195
- * Glued-on features are typically used to cover perforations (for corrections)
196
- * or to reinforce damaged areas. They may themselves carry other features
197
- * such as writings or additional holes.
198
- * @see reo:GluedOn
194
+ * A piece of paper or tape glued onto the roll: a label naming it, a
195
+ * strip covering perforations, or a patch reinforcing a tear. A patch
196
+ * may itself carry other features, such as writings or holes.
197
+ * @see reo:Patch
199
198
  */
200
- export interface GluedOn extends RollFeature<'GluedOn', typeof conditions.GluedOn[number]>, OnAFace {
199
+ export interface Patch extends RollFeature<'Patch', typeof conditions.Patch[number]>, OnAFace {
201
200
  /**
202
- * The material of the glued-on feature.
201
+ * What the patch is made of.
203
202
  * @see crm:P45 consists of
204
203
  */
205
204
  material: 'paper' | 'tape';
@@ -211,8 +210,8 @@ export interface GluedOn extends RollFeature<'GluedOn', typeof conditions.GluedO
211
210
  */
212
211
  rotation?: Measure<'deg'>;
213
212
  /**
214
- * A glued-on feature itself may carry other features.
215
- * Nested features do not need to be positioned explicitly.
213
+ * The features the patch itself carries. They need not be
214
+ * positioned explicitly.
216
215
  * @see crm:P46 is composed of
217
216
  */
218
217
  features?: NestedFeature[];
@@ -225,10 +224,10 @@ export interface GluedOn extends RollFeature<'GluedOn', typeof conditions.GluedO
225
224
  export type AnyFeature = HoleChain | Writing | Mark;
226
225
  /**
227
226
  * Anything found at a place of its own on the roll: a feature or a
228
- * glued-on patch. E24 Physical Human-Made Thing is the class both fall
229
- * under, E22 and E25 being its subclasses.
227
+ * patch. E24 Physical Human-Made Thing is the class both fall under,
228
+ * E22 and E25 being its subclasses.
230
229
  */
231
- export type FeatureOrPatch = AnyFeature | GluedOn;
230
+ export type FeatureOrPatch = AnyFeature | Patch;
232
231
  /**
233
232
  * A feature without the place it would state of its own. The union is
234
233
  * distributed over, so that each kind of feature keeps its own keys.
@@ -239,8 +238,10 @@ type Unplaced<T> = T extends FeatureOrPatch ? PartialBy<T, 'horizontal' | 'verti
239
238
  * the feature bearing it standing in one.
240
239
  */
241
240
  export type NestedFeature = Unplaced<FeatureOrPatch>;
241
+ /** Whether the feature states a place of its own, which one a patch bears does not. */
242
+ export declare const isPlaced: (feature: NestedFeature) => feature is FeatureOrPatch;
242
243
  export declare const isRollFeature: (obj: object) => obj is FeatureOrPatch;
243
- export declare const isGluedOn: <T extends NestedFeature>(feature: T) => feature is T & GluedOn;
244
+ export declare const isPatch: <T extends NestedFeature>(feature: T) => feature is T & Patch;
244
245
  /** The features a feature bears: a patch those stated as parts of it, any other feature none. */
245
246
  export declare const featuresBorneBy: (feature: NestedFeature) => NestedFeature[];
246
247
  /** The feature together with everything it bears, as deep as a patch on a patch goes. */
package/lib/Feature.js CHANGED
@@ -1,18 +1,20 @@
1
- export const featureTypes = ['HoleChain', 'Writing', 'Mark', 'GluedOn'];
1
+ export const featureTypes = ['HoleChain', 'Writing', 'Mark', 'Patch'];
2
2
  export const isFeatureType = (value) => featureTypes.includes(value);
3
3
  export const conditions = {
4
4
  HoleChain: ['partially-torn', 'missing-perforation'],
5
5
  Writing: ['illegible'],
6
6
  Mark: ['faded'],
7
- GluedOn: ['detaching', 'ripped']
7
+ Patch: ['detaching', 'ripped']
8
8
  };
9
9
  export const techniques = ['print', 'handwriting', 'stamp'];
10
10
  export const media = ['ink', 'pencil', 'crayon'];
11
+ /** Whether the feature states a place of its own, which one a patch bears does not. */
12
+ export const isPlaced = (feature) => feature.horizontal !== undefined && feature.vertical !== undefined;
11
13
  export const isRollFeature = (obj) => {
12
14
  return 'type' in obj && isFeatureType(obj.type);
13
15
  };
14
- export const isGluedOn = (feature) => feature.type === 'GluedOn';
16
+ export const isPatch = (feature) => feature.type === 'Patch';
15
17
  /** The features a feature bears: a patch those stated as parts of it, any other feature none. */
16
- export const featuresBorneBy = (feature) => isGluedOn(feature) ? feature.features ?? [] : [];
18
+ export const featuresBorneBy = (feature) => isPatch(feature) ? feature.features ?? [] : [];
17
19
  /** The feature together with everything it bears, as deep as a patch on a patch goes. */
18
20
  export const withBorneFeatures = (feature) => [feature, ...featuresBorneBy(feature).flatMap(withBorneFeatures)];
package/lib/RollCopy.d.ts CHANGED
@@ -2,7 +2,7 @@ import { ConditionState } from "./ConditionState.js";
2
2
  import { AnySymbol } from "./Symbol.js";
3
3
  import { TrackerBar } from "./TrackerBar.js";
4
4
  import { TrackCalibration } from "./TrackCalibration.js";
5
- import { AnyFeature, FeatureOrPatch, GluedOn } from "./Feature.js";
5
+ import { AnyFeature, FeatureOrPatch, Patch } from "./Feature.js";
6
6
  import { ActorAssignment, DateAssignment, ObjectAssumption, ReferenceAssumption } from "./Assumption.js";
7
7
  import { WithId, WithType } from "./utils.js";
8
8
  import { Agent, Concept } from "./Agent.js";
@@ -128,7 +128,7 @@ export interface ProductionEvent {
128
128
  * at once and states it here, and a feature an editor reads as the
129
129
  * work of a later hand belongs in the act that made it, whichever
130
130
  * kind of feature it is.
131
- * @see crm:P108 has produced
131
+ * @see reo:produced
132
132
  */
133
133
  produced?: AnyFeature[];
134
134
  }
@@ -161,7 +161,7 @@ export type Modification = Partial<{
161
161
  * The patches glued onto the copy, each with whatever it bears.
162
162
  * @see crm:P111 added
163
163
  */
164
- added: GluedOn[];
164
+ added: Patch[];
165
165
  /**
166
166
  * @see crm:P21 had general purpose
167
167
  */
@@ -173,7 +173,7 @@ export type Modification = Partial<{
173
173
  * paper, a circle in pencil, a hole punched by hand. Any kind of
174
174
  * feature may come of a later act, as any kind may come of the
175
175
  * punching.
176
- * @see crm:P108 has produced
176
+ * @see reo:produced
177
177
  */
178
178
  produced: AnyFeature[];
179
179
  /**
package/lib/Version.d.ts CHANGED
@@ -71,7 +71,7 @@ export interface VersionCreation {
71
71
  * it describes.
72
72
  * @see lrmoo:F2 Expression
73
73
  */
74
- export interface Version extends WithId, WithType<'Version'> {
74
+ export interface Version extends WithId {
75
75
  /**
76
76
  * The reproducing system this version is coded for. One roll was
77
77
  * often issued for several of them, and a version is a reading in
package/lib/asJsonLd.js CHANGED
@@ -5,7 +5,7 @@ import context from "./spec/context.json" with { type: 'json' };
5
5
  * The keys an export derives from the tree, which no node of the
6
6
  * edition states itself. An import reads them off again.
7
7
  */
8
- export const derivedKeys = new Set(['bears', 'composedOf', 'augmented', 'diminished']);
8
+ export const derivedKeys = new Set(['augmented', 'diminished']);
9
9
  export const exportDate = (date) => {
10
10
  const year = date.getFullYear();
11
11
  const month = String(date.getMonth() + 1).padStart(2, "0");
@@ -53,32 +53,12 @@ const asJsonLdEntity = (obj) => {
53
53
  * reading as whichever came last. An embedded context merges with the
54
54
  * active one, so the shared prefixes survive.
55
55
  */
56
- const withSystemContexts = (node) => {
57
- if (Array.isArray(node))
58
- return node.map(withSystemContexts);
59
- if (node === null || typeof node !== 'object')
60
- return node;
61
- const walked = Object.fromEntries(Object.entries(node).map(([key, value]) => [key, withSystemContexts(value)]));
62
- const system = node['@type'] === 'Version'
63
- ? systemIdIn(node.system?.['@id'])
64
- : undefined;
65
- return system
66
- ? { '@context': `https://w3id.org/reo/${system}/context.jsonld`, ...walked }
67
- : walked;
56
+ const withSystemContext = (version) => {
57
+ const system = systemIdIn(version?.system?.['@id']);
58
+ return system ? { '@context': `https://w3id.org/reo/${system}/context.jsonld`, ...version } : version;
68
59
  };
60
+ const withSystemContexts = (edition) => Array.isArray(edition.versions) ? { ...edition, versions: edition.versions.map(withSystemContext) } : edition;
69
61
  const isRecord = (value) => value !== null && typeof value === 'object' && !Array.isArray(value);
70
- const nodesIn = (value) => Array.isArray(value) ? value.filter(isRecord) : [];
71
- /** What the acts of a copy brought onto it: the features they produced and the patches they glued on. */
72
- const madeOn = (copy) => [
73
- ...nodesIn(copy.production?.produced),
74
- ...nodesIn(copy.modifications).flatMap(act => [...nodesIn(act.produced), ...nodesIn(act.added)])
75
- ];
76
- const referencing = (nodes, patches) => nodes.filter(node => (node['@type'] === 'GluedOn') === patches && typeof node['@id'] === 'string')
77
- .map(node => ({ '@id': node['@id'] }));
78
- const featuresAmong = (nodes) => referencing(nodes, false);
79
- const patchesAmong = (nodes) => referencing(nodes, true);
80
- /** The key, where there is anything to state under it. */
81
- const stating = (key, references) => references.length > 0 ? { [key]: references } : {};
82
62
  /** The act with what it changed named: an attachment augments the copy, a removal diminishes it. */
83
63
  const changing = (copyId) => (act) => {
84
64
  if (typeof copyId !== 'string' || !isRecord(act))
@@ -90,31 +70,21 @@ const changing = (copyId) => (act) => {
90
70
  return act;
91
71
  };
92
72
  /**
93
- * The document with every bearing stated that its tree only implies. A
94
- * copy bears the features its acts brought about and is composed of the
95
- * patches they glued on, a patch bears the features glued onto it in
96
- * turn. Each feature stands in the act that made it and nothing reads a
97
- * bearing off that, so the export states it; a patch is no feature, and
98
- * P56 bears feature takes only features, so a patch is stated as a part.
73
+ * The document with what each act changed stated. Which of P110
74
+ * augmented and P112 diminished applies depends on the class of the
75
+ * act, which no property chain in OWL 2 RL can test, so the export
76
+ * states it. What a copy or a patch bears is left to a reasoner (see
77
+ * the entailments in reo.ttl).
99
78
  */
100
- const withBearings = (value) => {
79
+ const withChanges = (value) => {
101
80
  if (Array.isArray(value))
102
- return value.map(withBearings);
81
+ return value.map(withChanges);
103
82
  if (!isRecord(value))
104
83
  return value;
105
- const node = Object.fromEntries(Object.entries(value).map(([key, child]) => [key, withBearings(child)]));
106
- if (node['@type'] === 'RollCopy') {
107
- const made = madeOn(node);
108
- return {
109
- ...node,
110
- ...(Array.isArray(node.modifications) && { modifications: node.modifications.map(changing(node['@id'])) }),
111
- ...stating('bears', featuresAmong(made)),
112
- ...stating('composedOf', patchesAmong(made))
113
- };
114
- }
115
- if (node['@type'] === 'GluedOn')
116
- return { ...node, ...stating('bears', featuresAmong(nodesIn(node.features))) };
117
- return node;
84
+ const node = Object.fromEntries(Object.entries(value).map(([key, child]) => [key, withChanges(child)]));
85
+ return node['@type'] === 'RollCopy' && Array.isArray(node.modifications)
86
+ ? { ...node, modifications: node.modifications.map(changing(node['@id'])) }
87
+ : node;
118
88
  };
119
89
  /** Terms the context sets to null, which say nothing when the edition is read as RDF. */
120
90
  const silentTerms = new Set(Object.entries(context['@context'])
@@ -182,7 +152,7 @@ const withDoubtedReferencesQuoted = (value) => {
182
152
  };
183
153
  };
184
154
  export const asJsonLd = (edition) => {
185
- const { node, quoted } = withDoubtedReferencesQuoted(withSystemContexts(withBearings(asJsonLdEntity(edition))));
155
+ const { node, quoted } = withDoubtedReferencesQuoted(withSystemContexts(withChanges(asJsonLdEntity(edition))));
186
156
  // The context is the export's own; one carried in from an import must not override it.
187
157
  const { base, '@context': carried, ...rest } = node;
188
158
  return {
@@ -192,7 +162,6 @@ export const asJsonLd = (edition) => {
192
162
  '@base': edition.base
193
163
  }
194
164
  ],
195
- '@type': "Edition",
196
165
  '@id': edition.base,
197
166
  ...rest,
198
167
  ...(quoted.length > 0 && { '@included': quoted })
@@ -86,7 +86,7 @@ const carriersOffTheirMeaning = (view, version, commands) => {
86
86
  .some(meaning => keyOf(meaning) === keyOf(symbol));
87
87
  };
88
88
  return commands
89
- .filter(symbol => view.carriersOf(symbol).some(carrier => misread(carrier, symbol)))
89
+ .filter(symbol => view.placedCarriersOf(symbol).some(carrier => misread(carrier, symbol)))
90
90
  .map(symbol => ({ version, symbol: symbol.id, problem: 'carrier-on-another-track' }));
91
91
  };
92
92
  /**