linked-rolls 0.37.0 → 0.39.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/lib/EditionView.d.ts +10 -1
- package/lib/EditionView.js +18 -1
- package/lib/Feature.d.ts +28 -3
- package/lib/Quantity.d.ts +4 -1
- package/lib/Quantity.js +1 -0
- package/lib/RollCopy.d.ts +4 -0
- package/lib/RollCopy.js +5 -3
- package/lib/editionOps.d.ts +38 -2
- package/lib/editionOps.js +90 -5
- package/lib/schema.json +99 -0
- package/lib/spec/context.json +9 -0
- package/package.json +1 -1
package/lib/EditionView.d.ts
CHANGED
|
@@ -4,7 +4,7 @@ import { AnySymbol, Expression, Note } from "./Symbol";
|
|
|
4
4
|
import { Version } from "./Version";
|
|
5
5
|
import { NegotiatedEvent } from "./ReproducingSystem";
|
|
6
6
|
import { TrackerBar } from "./TrackerBar";
|
|
7
|
-
import { RollCopy } from "./RollCopy";
|
|
7
|
+
import { Modification, ProductionEvent, RollCopy } from "./RollCopy";
|
|
8
8
|
import { Millimeters } from "./Quantity";
|
|
9
9
|
export type Path = (string | number)[];
|
|
10
10
|
export declare const getAt: <T>(path: Path, obj: unknown) => T | undefined;
|
|
@@ -37,6 +37,15 @@ export declare class EditionView {
|
|
|
37
37
|
carriersOf(symbol: AnySymbol): Readonly<FeatureOrPatch>[];
|
|
38
38
|
/** The copy a feature sits on, a patch and everything it bears included. */
|
|
39
39
|
copyOf(featureId: string): Readonly<RollCopy> | undefined;
|
|
40
|
+
/**
|
|
41
|
+
* The act a copy states a feature in: the production event that
|
|
42
|
+
* punched it, or the modification that brought it about. A feature
|
|
43
|
+
* a patch bears came onto the copy with the patch, so the act is
|
|
44
|
+
* the one that glued the patch on. Two features stand in one act
|
|
45
|
+
* where this returns the very same object, which is what
|
|
46
|
+
* `mergeFeatures` asks before it reads them as one.
|
|
47
|
+
*/
|
|
48
|
+
actOf(featureId: string): Readonly<ProductionEvent | Modification> | undefined;
|
|
40
49
|
/**
|
|
41
50
|
* How a place on the edition's shared axis relates to the paper of
|
|
42
51
|
* this version: place × factor = millimetres of its own paper.
|
package/lib/EditionView.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { withBorneFeatures } from "./Feature";
|
|
2
2
|
import { deletedBy, insertedBy, principalDerivationOf } from "./Version";
|
|
3
3
|
import { systemIdOf } from "./TrackerBar";
|
|
4
|
-
import { featuresOf, isPaperStretch } from "./RollCopy";
|
|
4
|
+
import { featuresMadeBy, featuresOf, isPaperStretch } from "./RollCopy";
|
|
5
5
|
import { idOf, idsOf } from "./Assumption";
|
|
6
6
|
import { mean } from "./Quantity";
|
|
7
7
|
export const getAt = (path, obj) => {
|
|
@@ -161,6 +161,23 @@ export class EditionView {
|
|
|
161
161
|
}
|
|
162
162
|
return this.copiesByFeature.get(featureId);
|
|
163
163
|
}
|
|
164
|
+
/**
|
|
165
|
+
* The act a copy states a feature in: the production event that
|
|
166
|
+
* punched it, or the modification that brought it about. A feature
|
|
167
|
+
* a patch bears came onto the copy with the patch, so the act is
|
|
168
|
+
* the one that glued the patch on. Two features stand in one act
|
|
169
|
+
* where this returns the very same object, which is what
|
|
170
|
+
* `mergeFeatures` asks before it reads them as one.
|
|
171
|
+
*/
|
|
172
|
+
actOf(featureId) {
|
|
173
|
+
const copy = this.copyOf(featureId);
|
|
174
|
+
if (!copy)
|
|
175
|
+
return undefined;
|
|
176
|
+
const states = (features) => features.flatMap(withBorneFeatures).some(feature => feature.id === featureId);
|
|
177
|
+
if (states(copy.production?.produced ?? []))
|
|
178
|
+
return copy.production;
|
|
179
|
+
return copy.modifications.find(act => states(featuresMadeBy(act)));
|
|
180
|
+
}
|
|
164
181
|
/**
|
|
165
182
|
* How a place on the edition's shared axis relates to the paper of
|
|
166
183
|
* this version: place × factor = millimetres of its own paper.
|
package/lib/Feature.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ import { ObjectAssumption } from "./Assumption";
|
|
|
2
2
|
import { ConditionState } from "./ConditionState";
|
|
3
3
|
import { Text } from "./Symbol";
|
|
4
4
|
import { PartialBy, WithId, WithType } from "./utils";
|
|
5
|
-
import { Millimeters, Track } from "./Quantity";
|
|
5
|
+
import { Measure, Millimeters, Track } from "./Quantity";
|
|
6
6
|
/**
|
|
7
7
|
* Describes the horizontal extent of a feature on the roll,
|
|
8
8
|
* measured in millimeters from the beginning of the roll.
|
|
@@ -119,11 +119,23 @@ export interface Hole extends RollFeature<'Hole', typeof conditions.Hole[number]
|
|
|
119
119
|
*/
|
|
120
120
|
pattern?: 'regular' | 'accelerating' | 'staggering';
|
|
121
121
|
}
|
|
122
|
+
/**
|
|
123
|
+
* Something that lies on a face of the paper rather than through it. A
|
|
124
|
+
* hole is not one: it goes through, and is on both faces at once.
|
|
125
|
+
*/
|
|
126
|
+
export interface OnAFace {
|
|
127
|
+
/**
|
|
128
|
+
* The face of the roll it lies on: the side that faces the reader
|
|
129
|
+
* as the roll plays, or the back of it.
|
|
130
|
+
* @see reo:side
|
|
131
|
+
*/
|
|
132
|
+
side?: 'recto' | 'verso';
|
|
133
|
+
}
|
|
122
134
|
/**
|
|
123
135
|
* A trace is a visible mark or writing on the roll surface.
|
|
124
136
|
* Traces may fade over time.
|
|
125
137
|
*/
|
|
126
|
-
export interface Trace<T extends FeatureType> extends RollFeature<T, typeof conditions[T][number]
|
|
138
|
+
export interface Trace<T extends FeatureType> extends RollFeature<T, typeof conditions[T][number]>, OnAFace {
|
|
127
139
|
}
|
|
128
140
|
export declare const writingMethods: readonly ['print', 'handwriting', 'stamp'];
|
|
129
141
|
/**
|
|
@@ -156,6 +168,13 @@ export interface Writing extends Trace<'Writing'> {
|
|
|
156
168
|
* @see crm:P128 carries
|
|
157
169
|
*/
|
|
158
170
|
transcription: ObjectAssumption<Transcription>;
|
|
171
|
+
/**
|
|
172
|
+
* How far the writing stands askew, clockwise from the line across
|
|
173
|
+
* the roll. A stamp pressed crooked and a label written along the
|
|
174
|
+
* roll rather than across it are both stated here.
|
|
175
|
+
* @see reo:rotation
|
|
176
|
+
*/
|
|
177
|
+
rotation?: Measure<'deg'>;
|
|
159
178
|
}
|
|
160
179
|
/**
|
|
161
180
|
* A visible mark on the roll, such as a pencil circle, an ink stroke,
|
|
@@ -178,12 +197,18 @@ export interface Mark extends Trace<'Mark'> {
|
|
|
178
197
|
* such as writings or additional holes.
|
|
179
198
|
* @see reo:GluedOn
|
|
180
199
|
*/
|
|
181
|
-
export interface GluedOn extends RollFeature<'GluedOn', typeof conditions.GluedOn[number]
|
|
200
|
+
export interface GluedOn extends RollFeature<'GluedOn', typeof conditions.GluedOn[number]>, OnAFace {
|
|
182
201
|
/**
|
|
183
202
|
* The material of the glued-on feature.
|
|
184
203
|
* @see crm:P45 consists of
|
|
185
204
|
*/
|
|
186
205
|
material: 'paper' | 'tape';
|
|
206
|
+
/**
|
|
207
|
+
* How far the patch was stuck on askew, clockwise from the line
|
|
208
|
+
* across the roll.
|
|
209
|
+
* @see reo:rotation
|
|
210
|
+
*/
|
|
211
|
+
rotation?: Measure<'deg'>;
|
|
187
212
|
/**
|
|
188
213
|
* A glued-on feature itself may carry other features.
|
|
189
214
|
* Nested features do not need to be positioned explicitly.
|
package/lib/Quantity.d.ts
CHANGED
|
@@ -11,7 +11,7 @@ declare const unit: unique symbol;
|
|
|
11
11
|
* The units a record may state. A `Measure` is limited to these, since
|
|
12
12
|
* they are what the `unit` field is allowed to say.
|
|
13
13
|
*/
|
|
14
|
-
export type Unit = 'mm' | 'cm' | 'px' | 'track' | 's' | 'ms' | 'ft/min' | 'm/min' | 'px/in';
|
|
14
|
+
export type Unit = 'mm' | 'cm' | 'px' | 'track' | 's' | 'ms' | 'ft/min' | 'm/min' | 'px/in' | 'deg';
|
|
15
15
|
export type Quantity<U extends string> = number & {
|
|
16
16
|
readonly [unit]: U;
|
|
17
17
|
};
|
|
@@ -28,6 +28,8 @@ export type FeetPerMinute = Quantity<'ft/min'>;
|
|
|
28
28
|
export type MetersPerMinute = Quantity<'m/min'>;
|
|
29
29
|
/** How finely a scan was read: pixels of the image per inch of paper. */
|
|
30
30
|
export type Resolution = Quantity<'px/in'>;
|
|
31
|
+
/** An angle, clockwise from the line across the roll. */
|
|
32
|
+
export type Degrees = Quantity<'deg'>;
|
|
31
33
|
/** Names a number in a unit. Partially apply it to make a constructor. */
|
|
32
34
|
export declare const quantity: <U extends string>(value: number) => Quantity<U>;
|
|
33
35
|
export declare const mm: (value: number) => Quantity<"mm">;
|
|
@@ -39,6 +41,7 @@ export declare const milliseconds: (value: number) => Quantity<"ms">;
|
|
|
39
41
|
export declare const feetPerMinute: (value: number) => Quantity<"ft/min">;
|
|
40
42
|
export declare const metersPerMinute: (value: number) => Quantity<"m/min">;
|
|
41
43
|
export declare const pixelsPerInch: (value: number) => Quantity<"px/in">;
|
|
44
|
+
export declare const degrees: (value: number) => Quantity<"deg">;
|
|
42
45
|
/**
|
|
43
46
|
* A value together with the unit it was measured in, as a record
|
|
44
47
|
* states it.
|
package/lib/Quantity.js
CHANGED
|
@@ -9,6 +9,7 @@ export const milliseconds = quantity;
|
|
|
9
9
|
export const feetPerMinute = quantity;
|
|
10
10
|
export const metersPerMinute = quantity;
|
|
11
11
|
export const pixelsPerInch = quantity;
|
|
12
|
+
export const degrees = quantity;
|
|
12
13
|
// The second operand takes its unit from the first. Inferred from both,
|
|
13
14
|
// TypeScript would unite two units rather than reject them.
|
|
14
15
|
export const add = (a, b) => quantity(a + b);
|
package/lib/RollCopy.d.ts
CHANGED
|
@@ -346,6 +346,10 @@ export interface RollCopy extends WithType<'RollCopy'>, WithId {
|
|
|
346
346
|
*/
|
|
347
347
|
carries?: ReferenceAssumption[];
|
|
348
348
|
}
|
|
349
|
+
/** What an act brought onto the copy: what it produced or glued on, a removal nothing. */
|
|
350
|
+
export declare const featuresMadeBy: (modification: Modification) => FeatureOrPatch[];
|
|
351
|
+
/** Whether the act is one that modified the copy, rather than the production that punched it. */
|
|
352
|
+
export declare const isModification: (act: ProductionEvent | Modification) => act is Modification;
|
|
349
353
|
/** Whether the act is left stating nothing: it produced, added or removed nothing. */
|
|
350
354
|
export declare const statesNothing: (modification: Modification) => boolean;
|
|
351
355
|
/**
|
package/lib/RollCopy.js
CHANGED
|
@@ -17,20 +17,22 @@ export const modificationPurposes = [
|
|
|
17
17
|
'glossing'
|
|
18
18
|
];
|
|
19
19
|
/** What an act brought onto the copy: what it produced or glued on, a removal nothing. */
|
|
20
|
-
const
|
|
20
|
+
export const featuresMadeBy = (modification) => {
|
|
21
21
|
if (modification.type === 'Alteration')
|
|
22
22
|
return modification.produced;
|
|
23
23
|
return modification.type === 'Attachment' ? modification.added : [];
|
|
24
24
|
};
|
|
25
|
+
/** Whether the act is one that modified the copy, rather than the production that punched it. */
|
|
26
|
+
export const isModification = (act) => 'type' in act;
|
|
25
27
|
/** Whether the act is left stating nothing: it produced, added or removed nothing. */
|
|
26
|
-
export const statesNothing = (modification) => modification.type === 'Removal' ? modification.removed.length === 0 :
|
|
28
|
+
export const statesNothing = (modification) => modification.type === 'Removal' ? modification.removed.length === 0 : featuresMadeBy(modification).length === 0;
|
|
27
29
|
/**
|
|
28
30
|
* The features of the copy act by act: what the punching produced
|
|
29
31
|
* first, then what each modification produced or glued on. A feature a
|
|
30
32
|
* patch bears states no place of its own and is not among them;
|
|
31
33
|
* `withBorneFeatures` reaches those.
|
|
32
34
|
*/
|
|
33
|
-
export const featuresByAct = (copy) => [copy.production?.produced ?? [], ...copy.modifications.map(
|
|
35
|
+
export const featuresByAct = (copy) => [copy.production?.produced ?? [], ...copy.modifications.map(featuresMadeBy)];
|
|
34
36
|
/** Every feature the copy states at a place of its own, whichever act made it. */
|
|
35
37
|
export const featuresOf = (copy) => featuresByAct(copy).flat();
|
|
36
38
|
/**
|
package/lib/editionOps.d.ts
CHANGED
|
@@ -4,10 +4,10 @@ import { Edition } from "./Edition";
|
|
|
4
4
|
import { AnySymbol, PlacementRelation } from "./Symbol";
|
|
5
5
|
import { CollationTolerance } from "./Collation";
|
|
6
6
|
import { Edit } from "./Edit";
|
|
7
|
-
import { GeneralRollCondition, RollCopy, ScaleReading, Shift } from "./RollCopy";
|
|
7
|
+
import { GeneralRollCondition, ModificationPurpose, RollCopy, ScaleReading, Shift } from "./RollCopy";
|
|
8
8
|
import { FeatureSource } from "./FeatureSource";
|
|
9
9
|
import { AnyArgumentation, Belief, Certainty, ObjectAssumption } from "./Assumption";
|
|
10
|
-
import { FeatureConditionAssignment, FeatureOrPatch } from "./Feature";
|
|
10
|
+
import { FeatureConditionAssignment, FeatureOrPatch, NestedFeature } from "./Feature";
|
|
11
11
|
/**
|
|
12
12
|
* A change to an edition, written onto an immer draft of it. One
|
|
13
13
|
* operation is one undo step, so an operation that has to read the
|
|
@@ -70,6 +70,34 @@ export declare const addGeneralCondition: (copyId: string, condition: ObjectAssu
|
|
|
70
70
|
export declare const stateFeatureCondition: (copyId: string, featureId: string, condition: FeatureConditionAssignment) => EditionOp;
|
|
71
71
|
/** The symbols of the versions that no other copy carries. */
|
|
72
72
|
export declare const symbolsCarriedOnlyBy: (edition: Edition, copyId: string) => AnySymbol[];
|
|
73
|
+
/**
|
|
74
|
+
* The act a feature an editor states belongs to: the punching of the
|
|
75
|
+
* copy, the act that brought another feature about, or, where neither
|
|
76
|
+
* is said, an act of its own for the purpose given. A patch is never
|
|
77
|
+
* punched, being glued on, so `punched` says nothing of one.
|
|
78
|
+
*/
|
|
79
|
+
export interface FeatureAct {
|
|
80
|
+
/** The copy was punched with it, which is where a reading of a scan puts every hole. */
|
|
81
|
+
punched?: boolean;
|
|
82
|
+
/** The act that brought this feature about brought the new one about as well. */
|
|
83
|
+
beside?: string;
|
|
84
|
+
/** What the act was for, where a new one is made for the feature. */
|
|
85
|
+
purpose?: ModificationPurpose;
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* States that the copy bears the feature, in the act that brought it
|
|
89
|
+
* about: a patch was glued on by an attachment, anything else was
|
|
90
|
+
* produced, by the punching or by a later act. Which act, `FeatureAct`
|
|
91
|
+
* says; a `beside` that names nothing the copy bears is passed over and
|
|
92
|
+
* the feature goes into an act of its own.
|
|
93
|
+
*/
|
|
94
|
+
export declare const addFeature: (copyId: string, feature: FeatureOrPatch, act?: FeatureAct) => EditionOp;
|
|
95
|
+
/**
|
|
96
|
+
* States that the patch bears the feature. What a patch bears came onto
|
|
97
|
+
* the copy with the patch, so it belongs to no act of its own and
|
|
98
|
+
* states no place: it stands where the patch stands.
|
|
99
|
+
*/
|
|
100
|
+
export declare const addBorneFeature: (copyId: string, patchId: string, feature: NestedFeature) => EditionOp;
|
|
73
101
|
/**
|
|
74
102
|
* Takes the features off the copy, and out of the versions with what
|
|
75
103
|
* only they carried. A feature may be named wherever the copy bears it:
|
|
@@ -95,6 +123,14 @@ export type MergeObstacle = 'fewer-than-two' | 'different-types' | 'different-tr
|
|
|
95
123
|
* perforations of their own is the editor's reading.
|
|
96
124
|
*/
|
|
97
125
|
export declare const mergeObstacle: (features: readonly FeatureOrPatch[]) => MergeObstacle | undefined;
|
|
126
|
+
/**
|
|
127
|
+
* What stands in the way of reading the features the ids name as one,
|
|
128
|
+
* as `mergeFeatures` will find it. `mergeObstacle` asks only what the
|
|
129
|
+
* features themselves say, which cannot reach `different-acts`: one
|
|
130
|
+
* feature is the work of one act, and where the features stand is the
|
|
131
|
+
* edition's business rather than theirs.
|
|
132
|
+
*/
|
|
133
|
+
export declare const mergeObstacleIn: (view: EditionView, featureIds: readonly string[]) => MergeObstacle | undefined;
|
|
98
134
|
/**
|
|
99
135
|
* Replaces the features of the copy with a single one covering them
|
|
100
136
|
* all, where a scan has split what the editor reads as one feature.
|
package/lib/editionOps.js
CHANGED
|
@@ -379,6 +379,66 @@ const rewriteFeatures = (copy, rewrite) => {
|
|
|
379
379
|
}
|
|
380
380
|
copy.modifications = pruned(state.modifications, rewritingAct(rewrite), statesNothing);
|
|
381
381
|
};
|
|
382
|
+
/** The features of the act that brought the named feature about, where that act produces features. */
|
|
383
|
+
const producedBeside = (copy, featureId) => {
|
|
384
|
+
const names = (features) => features.some(feature => feature.id === featureId);
|
|
385
|
+
const punched = copy.production?.produced;
|
|
386
|
+
if (punched && names(punched))
|
|
387
|
+
return punched;
|
|
388
|
+
const act = copy.modifications.find(act => act.type === 'Alteration' && names(act.produced));
|
|
389
|
+
return act?.type === 'Alteration' ? act.produced : undefined;
|
|
390
|
+
};
|
|
391
|
+
/** The patches of the attachment that glued the named one on. */
|
|
392
|
+
const gluedBeside = (copy, patchId) => {
|
|
393
|
+
const act = copy.modifications.find(act => act.type === 'Attachment' && act.added.some(patch => patch.id === patchId));
|
|
394
|
+
return act?.type === 'Attachment' ? act.added : undefined;
|
|
395
|
+
};
|
|
396
|
+
/** The list the copy states a new feature in, making the act it belongs to where there is none. */
|
|
397
|
+
const actFor = (copy, patch, act) => {
|
|
398
|
+
const beside = act.beside !== undefined
|
|
399
|
+
? (patch ? gluedBeside(copy, act.beside) : producedBeside(copy, act.beside))
|
|
400
|
+
: undefined;
|
|
401
|
+
if (beside)
|
|
402
|
+
return beside;
|
|
403
|
+
if (patch) {
|
|
404
|
+
const added = [];
|
|
405
|
+
copy.modifications.push({ type: 'Attachment', added, ...(act.purpose && { purpose: act.purpose }) });
|
|
406
|
+
return added;
|
|
407
|
+
}
|
|
408
|
+
if (act.punched) {
|
|
409
|
+
if (!copy.production)
|
|
410
|
+
copy.production = {};
|
|
411
|
+
if (!copy.production.produced)
|
|
412
|
+
copy.production.produced = [];
|
|
413
|
+
return copy.production.produced;
|
|
414
|
+
}
|
|
415
|
+
const produced = [];
|
|
416
|
+
copy.modifications.push({ type: 'Alteration', produced, ...(act.purpose && { purpose: act.purpose }) });
|
|
417
|
+
return produced;
|
|
418
|
+
};
|
|
419
|
+
/**
|
|
420
|
+
* States that the copy bears the feature, in the act that brought it
|
|
421
|
+
* about: a patch was glued on by an attachment, anything else was
|
|
422
|
+
* produced, by the punching or by a later act. Which act, `FeatureAct`
|
|
423
|
+
* says; a `beside` that names nothing the copy bears is passed over and
|
|
424
|
+
* the feature goes into an act of its own.
|
|
425
|
+
*/
|
|
426
|
+
export const addFeature = (copyId, feature, act = {}) => onCopy(copyId, copy => {
|
|
427
|
+
actFor(copy, isGluedOn(feature), act).push(feature);
|
|
428
|
+
});
|
|
429
|
+
/**
|
|
430
|
+
* States that the patch bears the feature. What a patch bears came onto
|
|
431
|
+
* the copy with the patch, so it belongs to no act of its own and
|
|
432
|
+
* states no place: it stands where the patch stands.
|
|
433
|
+
*/
|
|
434
|
+
export const addBorneFeature = (copyId, patchId, feature) => onCopy(copyId, copy => {
|
|
435
|
+
const patch = featuresOf(copy).flatMap(withBorneFeatures).find(borne => borne.id === patchId);
|
|
436
|
+
if (!patch || !isGluedOn(patch))
|
|
437
|
+
return;
|
|
438
|
+
if (!patch.features)
|
|
439
|
+
patch.features = [];
|
|
440
|
+
patch.features.push(feature);
|
|
441
|
+
});
|
|
382
442
|
/**
|
|
383
443
|
* Takes the features off the copy, and out of the versions with what
|
|
384
444
|
* only they carried. A feature may be named wherever the copy bears it:
|
|
@@ -451,6 +511,32 @@ export const mergeObstacle = (features) => {
|
|
|
451
511
|
return 'differing-conditions';
|
|
452
512
|
return undefined;
|
|
453
513
|
};
|
|
514
|
+
/** The acts of the copy that state any of the named features. */
|
|
515
|
+
const actsHolding = (copy, named) => featuresByAct(copy).filter(features => features.some(feature => named.has(feature.id)));
|
|
516
|
+
/**
|
|
517
|
+
* What stands in the way of reading the named features of the copy as
|
|
518
|
+
* one, which is the whole of what `mergeFeatures` asks: whether one act
|
|
519
|
+
* brought them all about, and what the features themselves say. An id
|
|
520
|
+
* the copy does not bear at a place of its own is passed over.
|
|
521
|
+
*/
|
|
522
|
+
const obstacleIn = (copy, featureIds) => {
|
|
523
|
+
const named = new Set(featureIds);
|
|
524
|
+
const acts = actsHolding(copy, named);
|
|
525
|
+
return acts.length > 1
|
|
526
|
+
? 'different-acts'
|
|
527
|
+
: mergeObstacle((acts[0] ?? []).filter(feature => named.has(feature.id)));
|
|
528
|
+
};
|
|
529
|
+
/**
|
|
530
|
+
* What stands in the way of reading the features the ids name as one,
|
|
531
|
+
* as `mergeFeatures` will find it. `mergeObstacle` asks only what the
|
|
532
|
+
* features themselves say, which cannot reach `different-acts`: one
|
|
533
|
+
* feature is the work of one act, and where the features stand is the
|
|
534
|
+
* edition's business rather than theirs.
|
|
535
|
+
*/
|
|
536
|
+
export const mergeObstacleIn = (view, featureIds) => {
|
|
537
|
+
const copy = featureIds.map(id => view.copyOf(id)).find(copy => copy !== undefined);
|
|
538
|
+
return copy ? obstacleIn(copy, featureIds) : 'fewer-than-two';
|
|
539
|
+
};
|
|
454
540
|
/** The items with the replacement in the place of the first it stands for, the others dropped. */
|
|
455
541
|
const standingFor = (items, stands, replacement) => {
|
|
456
542
|
const first = items.findIndex(stands);
|
|
@@ -516,14 +602,13 @@ const carryOver = (draft, replaced, mergedId) => {
|
|
|
516
602
|
* says beforehand whether they can.
|
|
517
603
|
*/
|
|
518
604
|
export const mergeFeatures = (copyId, featureIds) => onCopy(copyId, (copy, draft) => {
|
|
519
|
-
const
|
|
520
|
-
const
|
|
521
|
-
const acts = featuresByAct(stateOf(copy)).filter(holds);
|
|
522
|
-
const toMerge = (acts[0] ?? []).filter(feature => named.has(feature.id));
|
|
523
|
-
const obstacle = acts.length > 1 ? 'different-acts' : mergeObstacle(toMerge);
|
|
605
|
+
const state = stateOf(copy);
|
|
606
|
+
const obstacle = obstacleIn(state, featureIds);
|
|
524
607
|
if (obstacle) {
|
|
525
608
|
throw new Error(`The features of copy ${copyId} cannot be merged: ${obstacle}`);
|
|
526
609
|
}
|
|
610
|
+
const named = new Set(featureIds);
|
|
611
|
+
const toMerge = (actsHolding(state, named)[0] ?? []).filter(feature => named.has(feature.id));
|
|
527
612
|
const replaced = new Set(toMerge.map(feature => feature.id));
|
|
528
613
|
const mergedId = v4();
|
|
529
614
|
rewriteFeatures(copy, (stated) => {
|
package/lib/schema.json
CHANGED
|
@@ -780,6 +780,20 @@
|
|
|
780
780
|
"type": "string",
|
|
781
781
|
"ontology": "crm:P45 consists of"
|
|
782
782
|
},
|
|
783
|
+
"rotation": {
|
|
784
|
+
"$ref": "#/definitions/Measure%3C%22deg%22%3E",
|
|
785
|
+
"description": "How far the patch was stuck on askew, clockwise from the line across the roll.",
|
|
786
|
+
"ontology": "reo:rotation"
|
|
787
|
+
},
|
|
788
|
+
"side": {
|
|
789
|
+
"description": "The face of the roll it lies on: the side that faces the reader as the roll plays, or the back of it.",
|
|
790
|
+
"enum": [
|
|
791
|
+
"recto",
|
|
792
|
+
"verso"
|
|
793
|
+
],
|
|
794
|
+
"type": "string",
|
|
795
|
+
"ontology": "reo:side"
|
|
796
|
+
},
|
|
783
797
|
"vertical": {
|
|
784
798
|
"$ref": "#/definitions/VerticalSpan",
|
|
785
799
|
"description": "Vertical span of the feature on the roll.",
|
|
@@ -1015,6 +1029,15 @@
|
|
|
1015
1029
|
"description": "The medium the mark was drawn in, where it can be told.",
|
|
1016
1030
|
"ontology": "reo:method"
|
|
1017
1031
|
},
|
|
1032
|
+
"side": {
|
|
1033
|
+
"description": "The face of the roll it lies on: the side that faces the reader as the roll plays, or the back of it.",
|
|
1034
|
+
"enum": [
|
|
1035
|
+
"recto",
|
|
1036
|
+
"verso"
|
|
1037
|
+
],
|
|
1038
|
+
"type": "string",
|
|
1039
|
+
"ontology": "reo:side"
|
|
1040
|
+
},
|
|
1018
1041
|
"vertical": {
|
|
1019
1042
|
"$ref": "#/definitions/VerticalSpan",
|
|
1020
1043
|
"description": "Vertical span of the feature on the roll.",
|
|
@@ -1084,6 +1107,28 @@
|
|
|
1084
1107
|
"type": "object",
|
|
1085
1108
|
"ontology": "crminf:I16 Meaning Comprehension"
|
|
1086
1109
|
},
|
|
1110
|
+
"Measure<\"deg\">": {
|
|
1111
|
+
"description": "A value together with the unit it was measured in, as a record states it.",
|
|
1112
|
+
"properties": {
|
|
1113
|
+
"unit": {
|
|
1114
|
+
"const": "deg",
|
|
1115
|
+
"description": "The unit of measurement.",
|
|
1116
|
+
"type": "string",
|
|
1117
|
+
"ontology": "crm:P91 has unit"
|
|
1118
|
+
},
|
|
1119
|
+
"value": {
|
|
1120
|
+
"$ref": "#/definitions/Quantity%3C%22deg%22%3E",
|
|
1121
|
+
"description": "The measured value.",
|
|
1122
|
+
"ontology": "crm:P90 has value"
|
|
1123
|
+
}
|
|
1124
|
+
},
|
|
1125
|
+
"required": [
|
|
1126
|
+
"value",
|
|
1127
|
+
"unit"
|
|
1128
|
+
],
|
|
1129
|
+
"type": "object",
|
|
1130
|
+
"ontology": "crm:E54 Dimension"
|
|
1131
|
+
},
|
|
1087
1132
|
"Measure<\"mm\">": {
|
|
1088
1133
|
"description": "A value together with the unit it was measured in, as a record states it.",
|
|
1089
1134
|
"properties": {
|
|
@@ -1411,6 +1456,20 @@
|
|
|
1411
1456
|
"description": "The method by which this writing was produced (e.g. through print, handwriting, or stamping).",
|
|
1412
1457
|
"ontology": "reo:method"
|
|
1413
1458
|
},
|
|
1459
|
+
"rotation": {
|
|
1460
|
+
"$ref": "#/definitions/Measure%3C%22deg%22%3E",
|
|
1461
|
+
"description": "How far the writing stands askew, clockwise from the line across the roll. A stamp pressed crooked and a label written along the roll rather than across it are both stated here.",
|
|
1462
|
+
"ontology": "reo:rotation"
|
|
1463
|
+
},
|
|
1464
|
+
"side": {
|
|
1465
|
+
"description": "The face of the roll it lies on: the side that faces the reader as the roll plays, or the back of it.",
|
|
1466
|
+
"enum": [
|
|
1467
|
+
"recto",
|
|
1468
|
+
"verso"
|
|
1469
|
+
],
|
|
1470
|
+
"type": "string",
|
|
1471
|
+
"ontology": "reo:side"
|
|
1472
|
+
},
|
|
1414
1473
|
"transcription": {
|
|
1415
1474
|
"$ref": "#/definitions/ObjectAssumption%3CTranscription%3E",
|
|
1416
1475
|
"description": "A transcription of the text content of the writing. This is an object assumption so that the transcription can be annotated with a belief about its correctness.",
|
|
@@ -1462,6 +1521,15 @@
|
|
|
1462
1521
|
"description": "The medium the mark was drawn in, where it can be told.",
|
|
1463
1522
|
"ontology": "reo:method"
|
|
1464
1523
|
},
|
|
1524
|
+
"side": {
|
|
1525
|
+
"description": "The face of the roll it lies on: the side that faces the reader as the roll plays, or the back of it.",
|
|
1526
|
+
"enum": [
|
|
1527
|
+
"recto",
|
|
1528
|
+
"verso"
|
|
1529
|
+
],
|
|
1530
|
+
"type": "string",
|
|
1531
|
+
"ontology": "reo:side"
|
|
1532
|
+
},
|
|
1465
1533
|
"vertical": {
|
|
1466
1534
|
"$ref": "#/definitions/VerticalSpan",
|
|
1467
1535
|
"description": "Vertical span of the feature on the roll. Left out by a feature a patch bears.",
|
|
@@ -1518,6 +1586,20 @@
|
|
|
1518
1586
|
"type": "string",
|
|
1519
1587
|
"ontology": "crm:P45 consists of"
|
|
1520
1588
|
},
|
|
1589
|
+
"rotation": {
|
|
1590
|
+
"$ref": "#/definitions/Measure%3C%22deg%22%3E",
|
|
1591
|
+
"description": "How far the patch was stuck on askew, clockwise from the line across the roll.",
|
|
1592
|
+
"ontology": "reo:rotation"
|
|
1593
|
+
},
|
|
1594
|
+
"side": {
|
|
1595
|
+
"description": "The face of the roll it lies on: the side that faces the reader as the roll plays, or the back of it.",
|
|
1596
|
+
"enum": [
|
|
1597
|
+
"recto",
|
|
1598
|
+
"verso"
|
|
1599
|
+
],
|
|
1600
|
+
"type": "string",
|
|
1601
|
+
"ontology": "reo:side"
|
|
1602
|
+
},
|
|
1521
1603
|
"vertical": {
|
|
1522
1604
|
"$ref": "#/definitions/VerticalSpan",
|
|
1523
1605
|
"description": "Vertical span of the feature on the roll. Left out by a feature a patch bears.",
|
|
@@ -2406,6 +2488,9 @@
|
|
|
2406
2488
|
"type": "object",
|
|
2407
2489
|
"ontology": "lrmoo:F32 Item Production Event"
|
|
2408
2490
|
},
|
|
2491
|
+
"Quantity<\"deg\">": {
|
|
2492
|
+
"type": "number"
|
|
2493
|
+
},
|
|
2409
2494
|
"Quantity<\"ft/min\">": {
|
|
2410
2495
|
"type": "number"
|
|
2411
2496
|
},
|
|
@@ -3005,6 +3090,20 @@
|
|
|
3005
3090
|
"description": "The method by which this writing was produced (e.g. through print, handwriting, or stamping).",
|
|
3006
3091
|
"ontology": "reo:method"
|
|
3007
3092
|
},
|
|
3093
|
+
"rotation": {
|
|
3094
|
+
"$ref": "#/definitions/Measure%3C%22deg%22%3E",
|
|
3095
|
+
"description": "How far the writing stands askew, clockwise from the line across the roll. A stamp pressed crooked and a label written along the roll rather than across it are both stated here.",
|
|
3096
|
+
"ontology": "reo:rotation"
|
|
3097
|
+
},
|
|
3098
|
+
"side": {
|
|
3099
|
+
"description": "The face of the roll it lies on: the side that faces the reader as the roll plays, or the back of it.",
|
|
3100
|
+
"enum": [
|
|
3101
|
+
"recto",
|
|
3102
|
+
"verso"
|
|
3103
|
+
],
|
|
3104
|
+
"type": "string",
|
|
3105
|
+
"ontology": "reo:side"
|
|
3106
|
+
},
|
|
3008
3107
|
"transcription": {
|
|
3009
3108
|
"$ref": "#/definitions/ObjectAssumption%3CTranscription%3E",
|
|
3010
3109
|
"description": "A transcription of the text content of the writing. This is an object assumption so that the transcription can be annotated with a belief about its correctness.",
|
package/lib/spec/context.json
CHANGED
|
@@ -247,6 +247,15 @@
|
|
|
247
247
|
"@context": { "@vocab": "https://w3id.org/reo/type/" }
|
|
248
248
|
},
|
|
249
249
|
"transcription": "crm:P128_carries",
|
|
250
|
+
"side": {
|
|
251
|
+
"@id": "reo:side",
|
|
252
|
+
"@type": "@vocab",
|
|
253
|
+
"@context": { "@vocab": "https://w3id.org/reo/type/" }
|
|
254
|
+
},
|
|
255
|
+
"rotation": {
|
|
256
|
+
"@id": "reo:rotation",
|
|
257
|
+
"@context": { "value": "crm:P90_has_value" }
|
|
258
|
+
},
|
|
250
259
|
"material": {
|
|
251
260
|
"@id": "crm:P45_consists_of",
|
|
252
261
|
"@type": "@vocab",
|
package/package.json
CHANGED