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 +12 -6
- package/lib/ConditionState.d.ts +1 -2
- package/lib/EditionView.d.ts +22 -8
- package/lib/EditionView.js +66 -23
- package/lib/Emulation.js +2 -2
- package/lib/Feature.d.ts +17 -16
- package/lib/Feature.js +6 -4
- package/lib/RollCopy.d.ts +4 -4
- package/lib/Version.d.ts +1 -1
- package/lib/asJsonLd.js +17 -48
- package/lib/constraints.js +1 -1
- package/lib/editionOps.js +11 -13
- package/lib/importJsonLd.js +1 -6
- package/lib/migrate.js +43 -11
- package/lib/readers/stanfordAton.js +0 -1
- package/lib/scatter.js +3 -3
- package/lib/schema.json +90 -217
- package/lib/spec/context.json +2 -13
- package/lib/witnesses.js +2 -2
- package/package.json +1 -1
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
|
|
233
|
+
productions (E12), which state what they made with `reo:produced`, a
|
|
234
|
+
subproperty of P108 has produced.
|
|
234
235
|
|
|
235
|
-
The
|
|
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)
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
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
|
|
package/lib/ConditionState.d.ts
CHANGED
|
@@ -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>
|
|
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.
|
package/lib/EditionView.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Edition } from "./Edition.js";
|
|
2
|
-
import { HorizontalSpan,
|
|
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
|
-
|
|
31
|
-
|
|
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<
|
|
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
|
/**
|
package/lib/EditionView.js
CHANGED
|
@@ -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.
|
|
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
|
-
|
|
124
|
-
return this.
|
|
146
|
+
version(id) {
|
|
147
|
+
return this.versionsById.get(id);
|
|
148
|
+
}
|
|
149
|
+
copy(id) {
|
|
150
|
+
return this.copiesById.get(id);
|
|
125
151
|
}
|
|
126
|
-
|
|
127
|
-
return
|
|
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.
|
|
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.
|
|
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.
|
|
266
|
+
const v = this.version(versionId);
|
|
224
267
|
const principal = v && principalDerivationOf(v);
|
|
225
|
-
return principal && this.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
20
|
+
const symbol = view.symbol(symbolId);
|
|
21
21
|
if (!symbol)
|
|
22
22
|
return new Map();
|
|
23
|
-
const onsets = view.
|
|
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', '
|
|
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
|
-
*
|
|
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
|
|
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
|
|
195
|
-
*
|
|
196
|
-
*
|
|
197
|
-
*
|
|
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
|
|
199
|
+
export interface Patch extends RollFeature<'Patch', typeof conditions.Patch[number]>, OnAFace {
|
|
201
200
|
/**
|
|
202
|
-
*
|
|
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
|
-
*
|
|
215
|
-
*
|
|
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
|
-
*
|
|
229
|
-
*
|
|
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 |
|
|
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
|
|
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', '
|
|
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
|
-
|
|
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
|
|
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) =>
|
|
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,
|
|
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
|
|
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:
|
|
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
|
|
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
|
|
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(['
|
|
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
|
|
57
|
-
|
|
58
|
-
|
|
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
|
|
94
|
-
*
|
|
95
|
-
*
|
|
96
|
-
*
|
|
97
|
-
*
|
|
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
|
|
79
|
+
const withChanges = (value) => {
|
|
101
80
|
if (Array.isArray(value))
|
|
102
|
-
return value.map(
|
|
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,
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
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(
|
|
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 })
|
package/lib/constraints.js
CHANGED
|
@@ -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.
|
|
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
|
/**
|