linked-rolls 0.36.0 → 0.37.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 +28 -1
- package/lib/EditionView.d.ts +2 -2
- package/lib/EditionView.js +2 -2
- package/lib/Feature.d.ts +46 -18
- package/lib/Feature.js +4 -2
- package/lib/RollCopy.d.ts +58 -26
- package/lib/RollCopy.js +26 -0
- package/lib/alignment.d.ts +2 -2
- package/lib/alignment.js +5 -4
- package/lib/asJsonLd.d.ts +5 -0
- package/lib/asJsonLd.js +55 -1
- package/lib/editionOps.d.ts +7 -5
- package/lib/editionOps.js +59 -30
- package/lib/importJsonLd.js +11 -1
- package/lib/migrate.js +103 -5
- package/lib/readers/phillipsEroll.js +1 -2
- package/lib/readers/spencerBar.js +2 -3
- package/lib/readers/stanfordAton.js +2 -3
- package/lib/reservations.js +2 -2
- package/lib/schema.json +390 -58
- package/lib/spec/context.json +31 -13
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -42,7 +42,10 @@ which versions and conditions carry a typology key beside their type,
|
|
|
42
42
|
the keeper and the production metadata are nodes with a name and
|
|
43
43
|
authority links, and the roll names its reproducing system. A date
|
|
44
44
|
written as a value of its own is read as the day the event falls
|
|
45
|
-
within.
|
|
45
|
+
within. A copy that held its features in one list, naming by id what a
|
|
46
|
+
modification had added, has each feature put into the act that brought
|
|
47
|
+
it about, and a feature a patch bears that was left unnamed is named
|
|
48
|
+
after the patch. Exports are always in the current format.
|
|
46
49
|
|
|
47
50
|
## How a date is stated
|
|
48
51
|
|
|
@@ -72,6 +75,30 @@ at. It then reads as the version it derives from, and
|
|
|
72
75
|
`reservationsAboutVersion` says so. A file that names a single
|
|
73
76
|
derivation loads as a list of one.
|
|
74
77
|
|
|
78
|
+
## What brought a feature about
|
|
79
|
+
|
|
80
|
+
A copy states no list of features. Each feature stands in the act that
|
|
81
|
+
brought it about: the perforations in the copy's own production, a
|
|
82
|
+
writing or a mark in the `Alteration` that made it, a patch in the
|
|
83
|
+
`Attachment` that glued it on. A `Removal` names by id what was taken
|
|
84
|
+
off, which stood there before the act. A feature no later act is known
|
|
85
|
+
to have made belongs to the punching, which is where a reading of a
|
|
86
|
+
scan puts every hole it finds.
|
|
87
|
+
|
|
88
|
+
Three kinds of act rather than two, because the CRM tells them apart.
|
|
89
|
+
E79 Part Addition asks that what is added be "a separate identifiable
|
|
90
|
+
whole prior to" the act, which a glued-on label is and a pencil line is
|
|
91
|
+
not: drawing, writing and punching bring a feature into being and are
|
|
92
|
+
productions (E12), which state what they made with P108 has produced.
|
|
93
|
+
|
|
94
|
+
The export states what that shape only implies. A copy bears every
|
|
95
|
+
feature its acts brought about (P56 bears feature) and is composed of
|
|
96
|
+
the patches glued onto it (P46 is composed of, a patch being an object
|
|
97
|
+
rather than a feature); an attachment augments the copy and a removal
|
|
98
|
+
diminishes it. The four keys are derived on the way out and read off
|
|
99
|
+
again on the way in, so they are no part of the edition, and they are
|
|
100
|
+
the one place where the JSON tree and the graph differ in shape.
|
|
101
|
+
|
|
75
102
|
## Where a copy's features come from
|
|
76
103
|
|
|
77
104
|
`readFrom` states what a copy's features were read from: the roll
|
package/lib/EditionView.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Edition } from "./Edition";
|
|
2
|
-
import { HorizontalSpan,
|
|
2
|
+
import { HorizontalSpan, FeatureOrPatch } from "./Feature";
|
|
3
3
|
import { AnySymbol, Expression, Note } from "./Symbol";
|
|
4
4
|
import { Version } from "./Version";
|
|
5
5
|
import { NegotiatedEvent } from "./ReproducingSystem";
|
|
@@ -34,7 +34,7 @@ export declare class EditionView {
|
|
|
34
34
|
travelUp(versionId: string, callback: (version: Readonly<Version>) => void): void;
|
|
35
35
|
/** The version and its ancestors along the principal line, from the version up to the root. */
|
|
36
36
|
lineageOf(versionId: string): Readonly<Version>[];
|
|
37
|
-
carriersOf(symbol: AnySymbol): Readonly<
|
|
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
40
|
/**
|
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 { isPaperStretch } from "./RollCopy";
|
|
4
|
+
import { featuresOf, isPaperStretch } from "./RollCopy";
|
|
5
5
|
import { idOf, idsOf } from "./Assumption";
|
|
6
6
|
import { mean } from "./Quantity";
|
|
7
7
|
export const getAt = (path, obj) => {
|
|
@@ -155,7 +155,7 @@ export class EditionView {
|
|
|
155
155
|
/** The copy a feature sits on, a patch and everything it bears included. */
|
|
156
156
|
copyOf(featureId) {
|
|
157
157
|
if (!this.copiesByFeature) {
|
|
158
|
-
this.copiesByFeature = new Map(this.edition.copies.flatMap(copy => copy
|
|
158
|
+
this.copiesByFeature = new Map(this.edition.copies.flatMap(copy => featuresOf(copy)
|
|
159
159
|
.flatMap(withBorneFeatures)
|
|
160
160
|
.map(feature => [feature.id, copy])));
|
|
161
161
|
}
|
package/lib/Feature.d.ts
CHANGED
|
@@ -55,10 +55,12 @@ export interface VerticalSpan {
|
|
|
55
55
|
}
|
|
56
56
|
export declare const featureTypes: readonly ['Hole', 'Writing', 'Mark', 'GluedOn'];
|
|
57
57
|
export type FeatureType = typeof featureTypes[number];
|
|
58
|
+
export declare const isFeatureType: (value: unknown) => value is FeatureType;
|
|
58
59
|
/**
|
|
59
|
-
* A
|
|
60
|
-
* defined by its horizontal and vertical position and
|
|
61
|
-
*
|
|
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
|
|
62
|
+
* extent. Each kind of feature is a class of its own, which its type
|
|
63
|
+
* names.
|
|
62
64
|
*/
|
|
63
65
|
export interface RollFeature<T extends FeatureType, DamageT extends string> extends WithId, WithType<T> {
|
|
64
66
|
/**
|
|
@@ -101,6 +103,10 @@ export type FeatureConditionAssignment = ObjectAssumption<ConditionState<Feature
|
|
|
101
103
|
* A hole (perforation) in the roll paper. Holes are the primary
|
|
102
104
|
* carriers of musical information on piano rolls, as they trigger
|
|
103
105
|
* notes and expression controls when passing over the tracker bar.
|
|
106
|
+
* A punched hole is a human-made feature: CRM counts "the information
|
|
107
|
+
* encoding features on mechanical or digital carriers" among the
|
|
108
|
+
* features purposely created by human activity.
|
|
109
|
+
* @see reo:Hole
|
|
104
110
|
*/
|
|
105
111
|
export interface Hole extends RollFeature<'Hole', typeof conditions.Hole[number]> {
|
|
106
112
|
/**
|
|
@@ -119,25 +125,28 @@ export interface Hole extends RollFeature<'Hole', typeof conditions.Hole[number]
|
|
|
119
125
|
*/
|
|
120
126
|
export interface Trace<T extends FeatureType> extends RollFeature<T, typeof conditions[T][number]> {
|
|
121
127
|
}
|
|
122
|
-
export declare const writingMethods: readonly ['
|
|
128
|
+
export declare const writingMethods: readonly ['print', 'handwriting', 'stamp'];
|
|
123
129
|
/**
|
|
124
130
|
* The method by which a writing was produced on the roll:
|
|
125
131
|
* printed, handwritten, or stamped.
|
|
126
132
|
*/
|
|
127
133
|
export type WritingMethod = typeof writingMethods[number];
|
|
134
|
+
export declare const markMethods: readonly ['ink', 'pencil', 'crayon'];
|
|
135
|
+
/** The medium a mark was drawn in. */
|
|
136
|
+
export type MarkMethod = typeof markMethods[number];
|
|
128
137
|
/** The text a writing carries. It names no carriers of its own, the writing being its carrier. */
|
|
129
138
|
export type Transcription = Omit<Text, 'carriers'>;
|
|
130
139
|
/**
|
|
131
140
|
* A piece of writing found on the roll, such as a label,
|
|
132
141
|
* catalogue number, or annotation. Writings have a method
|
|
133
142
|
* of production and a transcription of their content.
|
|
134
|
-
* @see
|
|
143
|
+
* @see reo:Writing
|
|
135
144
|
*/
|
|
136
145
|
export interface Writing extends Trace<'Writing'> {
|
|
137
146
|
/**
|
|
138
147
|
* The method by which this writing was produced
|
|
139
148
|
* (e.g. through print, handwriting, or stamping).
|
|
140
|
-
* @see
|
|
149
|
+
* @see reo:method
|
|
141
150
|
*/
|
|
142
151
|
method: WritingMethod;
|
|
143
152
|
/**
|
|
@@ -149,46 +158,65 @@ export interface Writing extends Trace<'Writing'> {
|
|
|
149
158
|
transcription: ObjectAssumption<Transcription>;
|
|
150
159
|
}
|
|
151
160
|
/**
|
|
152
|
-
* A visible mark on the roll, such as a pencil
|
|
153
|
-
*
|
|
154
|
-
*
|
|
161
|
+
* A visible mark on the roll, such as a pencil circle, an ink stroke,
|
|
162
|
+
* or other non-textual annotation. What a mark was meant to say is a
|
|
163
|
+
* reading of it (crminf:I16 Meaning Comprehension) rather than a
|
|
164
|
+
* property of the feature, so its shape is not stated here.
|
|
165
|
+
* @see reo:Mark
|
|
155
166
|
*/
|
|
156
167
|
export interface Mark extends Trace<'Mark'> {
|
|
168
|
+
/**
|
|
169
|
+
* The medium the mark was drawn in, where it can be told.
|
|
170
|
+
* @see reo:method
|
|
171
|
+
*/
|
|
172
|
+
method?: MarkMethod;
|
|
157
173
|
}
|
|
158
174
|
/**
|
|
159
175
|
* A piece of material (paper or tape) glued onto the roll surface.
|
|
160
176
|
* Glued-on features are typically used to cover perforations (for corrections)
|
|
161
177
|
* or to reinforce damaged areas. They may themselves carry other features
|
|
162
178
|
* such as writings or additional holes.
|
|
163
|
-
* @see
|
|
179
|
+
* @see reo:GluedOn
|
|
164
180
|
*/
|
|
165
181
|
export interface GluedOn extends RollFeature<'GluedOn', typeof conditions.GluedOn[number]> {
|
|
166
182
|
/**
|
|
167
183
|
* The material of the glued-on feature.
|
|
168
184
|
* @see crm:P45 consists of
|
|
169
185
|
*/
|
|
170
|
-
material: '
|
|
186
|
+
material: 'paper' | 'tape';
|
|
171
187
|
/**
|
|
172
188
|
* A glued-on feature itself may carry other features.
|
|
173
189
|
* Nested features do not need to be positioned explicitly.
|
|
174
|
-
* @see crm:
|
|
190
|
+
* @see crm:P46 is composed of
|
|
175
191
|
*/
|
|
176
192
|
features?: NestedFeature[];
|
|
177
193
|
}
|
|
178
194
|
/**
|
|
179
|
-
* The
|
|
180
|
-
*
|
|
181
|
-
*
|
|
195
|
+
* The features proper: a hole, a writing and a mark are all human-made
|
|
196
|
+
* features, and each of them is borne by whatever it sits on. A patch
|
|
197
|
+
* is an object glued onto the paper and stands apart from them.
|
|
198
|
+
*/
|
|
199
|
+
export type AnyFeature = Hole | Writing | Mark;
|
|
200
|
+
/**
|
|
201
|
+
* Anything found at a place of its own on the roll: a feature or a
|
|
202
|
+
* glued-on patch. E24 Physical Human-Made Thing is the class both fall
|
|
203
|
+
* under, E22 and E25 being its subclasses.
|
|
204
|
+
*/
|
|
205
|
+
export type FeatureOrPatch = AnyFeature | GluedOn;
|
|
206
|
+
/**
|
|
207
|
+
* A feature without the place it would state of its own. The union is
|
|
208
|
+
* distributed over, so that each kind of feature keeps its own keys.
|
|
182
209
|
*/
|
|
183
|
-
|
|
210
|
+
type Unplaced<T> = T extends FeatureOrPatch ? PartialBy<T, 'horizontal' | 'vertical'> : never;
|
|
184
211
|
/**
|
|
185
212
|
* A feature borne by another feature. It states no place of its own,
|
|
186
213
|
* the feature bearing it standing in one.
|
|
187
214
|
*/
|
|
188
|
-
export type NestedFeature =
|
|
189
|
-
export declare const isRollFeature: (obj: object) => obj is
|
|
215
|
+
export type NestedFeature = Unplaced<FeatureOrPatch>;
|
|
216
|
+
export declare const isRollFeature: (obj: object) => obj is FeatureOrPatch;
|
|
190
217
|
export declare const isGluedOn: <T extends NestedFeature>(feature: T) => feature is T & GluedOn;
|
|
191
218
|
/** The features a feature bears: a patch those stated as parts of it, any other feature none. */
|
|
192
219
|
export declare const featuresBorneBy: (feature: NestedFeature) => NestedFeature[];
|
|
193
220
|
/** The feature together with everything it bears, as deep as a patch on a patch goes. */
|
|
194
221
|
export declare const withBorneFeatures: (feature: NestedFeature) => NestedFeature[];
|
|
222
|
+
export {};
|
package/lib/Feature.js
CHANGED
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
export const featureTypes = ['Hole', 'Writing', 'Mark', 'GluedOn'];
|
|
2
|
+
export const isFeatureType = (value) => featureTypes.includes(value);
|
|
2
3
|
export const conditions = {
|
|
3
4
|
Hole: ['partially-torn', 'missing-perforation'],
|
|
4
5
|
Writing: ['illegible'],
|
|
5
6
|
Mark: ['faded'],
|
|
6
7
|
GluedOn: ['detaching', 'ripped']
|
|
7
8
|
};
|
|
8
|
-
export const writingMethods = ['
|
|
9
|
+
export const writingMethods = ['print', 'handwriting', 'stamp'];
|
|
10
|
+
export const markMethods = ['ink', 'pencil', 'crayon'];
|
|
9
11
|
export const isRollFeature = (obj) => {
|
|
10
|
-
return 'type' in obj &&
|
|
12
|
+
return 'type' in obj && isFeatureType(obj.type);
|
|
11
13
|
};
|
|
12
14
|
export const isGluedOn = (feature) => feature.type === 'GluedOn';
|
|
13
15
|
/** The features a feature bears: a patch those stated as parts of it, any other feature none. */
|
package/lib/RollCopy.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ import { ConditionState } from "./ConditionState";
|
|
|
2
2
|
import { AnySymbol } from "./Symbol";
|
|
3
3
|
import { TrackerBar } from "./TrackerBar";
|
|
4
4
|
import { TrackCalibration } from "./TrackCalibration";
|
|
5
|
-
import { AnyFeature } from "./Feature";
|
|
5
|
+
import { AnyFeature, FeatureOrPatch, GluedOn } from "./Feature";
|
|
6
6
|
import { ActorAssignment, DateAssignment, ObjectAssumption, ReferenceAssumption } from "./Assumption";
|
|
7
7
|
import { WithId, WithType } from "./utils";
|
|
8
8
|
import { Agent, Concept } from "./Agent";
|
|
@@ -114,12 +114,26 @@ export interface ProductionEvent {
|
|
|
114
114
|
* @see reo:paperSpeed
|
|
115
115
|
*/
|
|
116
116
|
speed?: ObjectAssumption<PaperSpeed>;
|
|
117
|
+
/**
|
|
118
|
+
* The features the punching brought into being, which are the note
|
|
119
|
+
* and expression perforations. A reading of a scan finds every hole
|
|
120
|
+
* on the paper at once and states it here. A hole an editor reads as
|
|
121
|
+
* punched later belongs in the act that made it.
|
|
122
|
+
* @see crm:P108 has produced
|
|
123
|
+
*/
|
|
124
|
+
produced?: AnyFeature[];
|
|
117
125
|
}
|
|
126
|
+
export declare const modificationPurposes: readonly ['musical-improvement', 'technical-improvement', 'repair', 'labeling', 'control', 'dating', 'glossing'];
|
|
127
|
+
/** What a modification of a copy was for, as far as it can be told. */
|
|
128
|
+
export type ModificationPurpose = typeof modificationPurposes[number];
|
|
118
129
|
/**
|
|
119
|
-
*
|
|
120
|
-
*
|
|
121
|
-
*
|
|
122
|
-
*
|
|
130
|
+
* An identifiable act that changed the roll copy after it was punched.
|
|
131
|
+
* Three kinds of act are told apart, because the CRM tells them apart.
|
|
132
|
+
* E79 Part Addition asks that what is added be "a separate identifiable
|
|
133
|
+
* whole prior to" the act, which a label glued on is and a pencil line
|
|
134
|
+
* is not: drawing, writing and punching bring a feature into being and
|
|
135
|
+
* are productions.
|
|
136
|
+
* @see crm:E79 Part Addition, crm:E80 Part Removal, crm:E12 Production
|
|
123
137
|
*/
|
|
124
138
|
export type Modification = Partial<{
|
|
125
139
|
/**
|
|
@@ -133,36 +147,49 @@ export type Modification = Partial<{
|
|
|
133
147
|
*/
|
|
134
148
|
date: DateAssignment;
|
|
135
149
|
}> & ({
|
|
136
|
-
type: '
|
|
150
|
+
type: 'Attachment';
|
|
137
151
|
/**
|
|
152
|
+
* The patches glued onto the copy, each with whatever it bears.
|
|
138
153
|
* @see crm:P111 added
|
|
139
154
|
*/
|
|
140
|
-
added:
|
|
155
|
+
added: GluedOn[];
|
|
156
|
+
/**
|
|
157
|
+
* @see crm:P21 had general purpose
|
|
158
|
+
*/
|
|
159
|
+
purpose?: ModificationPurpose;
|
|
160
|
+
} | {
|
|
161
|
+
type: 'Alteration';
|
|
162
|
+
/**
|
|
163
|
+
* The features the act brought into being: a date written on the
|
|
164
|
+
* paper, a circle in pencil, a hole punched by hand.
|
|
165
|
+
* @see crm:P108 has produced
|
|
166
|
+
*/
|
|
167
|
+
produced: AnyFeature[];
|
|
141
168
|
/**
|
|
142
169
|
* @see crm:P21 had general purpose
|
|
143
170
|
*/
|
|
144
|
-
purpose
|
|
171
|
+
purpose?: ModificationPurpose;
|
|
145
172
|
} | {
|
|
146
173
|
type: 'Removal';
|
|
147
174
|
/**
|
|
175
|
+
* What was taken off the copy, by id. It stood there before the act
|
|
176
|
+
* and is named rather than stated here. Removals are read from what
|
|
177
|
+
* they leave behind, such as a bright spot where a label sat.
|
|
148
178
|
* @see crm:P113 removed
|
|
149
179
|
*/
|
|
150
180
|
removed: string[];
|
|
151
181
|
/**
|
|
152
|
-
* Usually, roll features are being added.
|
|
153
|
-
* Sometimes however, we may see traces of features
|
|
154
|
-
* that have been removed, e.g. through bright spots on
|
|
155
|
-
* the roll.
|
|
156
182
|
* @see crm:P21 had general purpose
|
|
157
183
|
*/
|
|
158
|
-
purpose
|
|
184
|
+
purpose?: 'delabeling';
|
|
159
185
|
});
|
|
160
186
|
/**
|
|
161
|
-
* A physical copy of a roll, held at a specific location.
|
|
162
|
-
*
|
|
163
|
-
*
|
|
164
|
-
* roll may exist across different archives
|
|
165
|
-
*
|
|
187
|
+
* A physical copy of a roll, held at a specific location. Each roll
|
|
188
|
+
* copy has its own measurements, conditions and modifications, and
|
|
189
|
+
* states its features in the act that brought each of them about.
|
|
190
|
+
* Multiple copies of the same roll may exist across different archives
|
|
191
|
+
* or collections.
|
|
192
|
+
* @see reo:RollCopy
|
|
166
193
|
*/
|
|
167
194
|
export interface RollCopy extends WithType<'RollCopy'>, WithId {
|
|
168
195
|
/**
|
|
@@ -295,12 +322,6 @@ export interface RollCopy extends WithType<'RollCopy'>, WithId {
|
|
|
295
322
|
* @see crm:P50 has current keeper
|
|
296
323
|
*/
|
|
297
324
|
keeper?: KeeperAssignment;
|
|
298
|
-
/**
|
|
299
|
-
* The physical features found on this copy, with shift
|
|
300
|
-
* and stretch already applied when `ops` says so.
|
|
301
|
-
* @see crm:P56 bears feature
|
|
302
|
-
*/
|
|
303
|
-
features: AnyFeature[];
|
|
304
325
|
/**
|
|
305
326
|
* @see crm:P31i was modified by
|
|
306
327
|
*/
|
|
@@ -325,6 +346,17 @@ export interface RollCopy extends WithType<'RollCopy'>, WithId {
|
|
|
325
346
|
*/
|
|
326
347
|
carries?: ReferenceAssumption[];
|
|
327
348
|
}
|
|
349
|
+
/** Whether the act is left stating nothing: it produced, added or removed nothing. */
|
|
350
|
+
export declare const statesNothing: (modification: Modification) => boolean;
|
|
351
|
+
/**
|
|
352
|
+
* The features of the copy act by act: what the punching produced
|
|
353
|
+
* first, then what each modification produced or glued on. A feature a
|
|
354
|
+
* patch bears states no place of its own and is not among them;
|
|
355
|
+
* `withBorneFeatures` reaches those.
|
|
356
|
+
*/
|
|
357
|
+
export declare const featuresByAct: (copy: Pick<RollCopy, 'production' | 'modifications'>) => FeatureOrPatch[][];
|
|
358
|
+
/** Every feature the copy states at a place of its own, whichever act made it. */
|
|
359
|
+
export declare const featuresOf: (copy: Pick<RollCopy, 'production' | 'modifications'>) => FeatureOrPatch[];
|
|
328
360
|
/**
|
|
329
361
|
* Whether the condition is the stretch or shrinkage of the paper. A
|
|
330
362
|
* scale put down to this belongs to the one exemplar and says nothing
|
|
@@ -353,14 +385,14 @@ export declare const barOf: (copy: Pick<RollCopy, 'production'>) => TrackerBar;
|
|
|
353
385
|
* since they are really on the paper and are his calibration of his own
|
|
354
386
|
* scan; it is the reading that stops.
|
|
355
387
|
*/
|
|
356
|
-
export declare function asSymbols(features:
|
|
388
|
+
export declare function asSymbols(features: readonly FeatureOrPatch[], bar: TrackerBar): AnySymbol[];
|
|
357
389
|
/**
|
|
358
390
|
* The tracks a copy carries holes on that the tracker bar does not read.
|
|
359
391
|
* A non-empty result usually means the scan is calibrated wrongly. A hole
|
|
360
392
|
* lying across several positions is counted against each one the bar
|
|
361
393
|
* cannot read, and not at all where it reads them all.
|
|
362
394
|
*/
|
|
363
|
-
export declare function unreadTracks(features:
|
|
395
|
+
export declare function unreadTracks(features: readonly FeatureOrPatch[], bar: TrackerBar): Map<Track, number>;
|
|
364
396
|
/**
|
|
365
397
|
* Falls back to the way the scan geometry was reconstructed before the
|
|
366
398
|
* calibration was recorded: the bass hard margin stood in for the phase
|
package/lib/RollCopy.js
CHANGED
|
@@ -7,6 +7,32 @@ export const rollConditions = [
|
|
|
7
7
|
'general',
|
|
8
8
|
'paper-stretch'
|
|
9
9
|
];
|
|
10
|
+
export const modificationPurposes = [
|
|
11
|
+
'musical-improvement',
|
|
12
|
+
'technical-improvement',
|
|
13
|
+
'repair',
|
|
14
|
+
'labeling',
|
|
15
|
+
'control',
|
|
16
|
+
'dating',
|
|
17
|
+
'glossing'
|
|
18
|
+
];
|
|
19
|
+
/** What an act brought onto the copy: what it produced or glued on, a removal nothing. */
|
|
20
|
+
const madeBy = (modification) => {
|
|
21
|
+
if (modification.type === 'Alteration')
|
|
22
|
+
return modification.produced;
|
|
23
|
+
return modification.type === 'Attachment' ? modification.added : [];
|
|
24
|
+
};
|
|
25
|
+
/** 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 : madeBy(modification).length === 0;
|
|
27
|
+
/**
|
|
28
|
+
* The features of the copy act by act: what the punching produced
|
|
29
|
+
* first, then what each modification produced or glued on. A feature a
|
|
30
|
+
* patch bears states no place of its own and is not among them;
|
|
31
|
+
* `withBorneFeatures` reaches those.
|
|
32
|
+
*/
|
|
33
|
+
export const featuresByAct = (copy) => [copy.production?.produced ?? [], ...copy.modifications.map(madeBy)];
|
|
34
|
+
/** Every feature the copy states at a place of its own, whichever act made it. */
|
|
35
|
+
export const featuresOf = (copy) => featuresByAct(copy).flat();
|
|
10
36
|
/**
|
|
11
37
|
* Whether the condition is the stretch or shrinkage of the paper. A
|
|
12
38
|
* scale put down to this belongs to the one exemplar and says nothing
|
package/lib/alignment.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { FeatureOrPatch } from "./Feature";
|
|
2
2
|
import { RollCopy, Shift } from "./RollCopy";
|
|
3
3
|
import { TrackerBar } from "./TrackerBar";
|
|
4
4
|
import { Millimeters } from "./Quantity";
|
|
@@ -38,4 +38,4 @@ export interface AlignmentResult {
|
|
|
38
38
|
* sounds, and it is the pitches that are matched. Where a copy's holes
|
|
39
39
|
* have already been put onto the edition's bar, that bar reads it.
|
|
40
40
|
*/
|
|
41
|
-
export declare function alignFeatures(rollA: readonly
|
|
41
|
+
export declare function alignFeatures(rollA: readonly FeatureOrPatch[], rollB: readonly FeatureOrPatch[], barA?: TrackerBar, barB?: TrackerBar): AlignmentResult | undefined;
|
package/lib/alignment.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { featuresOf } from "./RollCopy";
|
|
1
2
|
import { welteT100 } from "./systems/welteT100/bar";
|
|
2
3
|
import { add, mm, scale } from "./Quantity";
|
|
3
4
|
/** Moves both ends of a span, the far end only where the span has one. */
|
|
@@ -16,7 +17,7 @@ const back = (shift) => ({ horizontal: scale(shift.horizontal, -1), vertical: sc
|
|
|
16
17
|
export const applyShift = (shift, copy) => {
|
|
17
18
|
if (copy.ops.includes('shifted'))
|
|
18
19
|
return;
|
|
19
|
-
copy.
|
|
20
|
+
featuresOf(copy).forEach(feature => {
|
|
20
21
|
move(feature.horizontal, shift.horizontal);
|
|
21
22
|
move(feature.vertical, shift.vertical);
|
|
22
23
|
});
|
|
@@ -27,7 +28,7 @@ export const applyShift = (shift, copy) => {
|
|
|
27
28
|
export const applyScale = (factor, copy) => {
|
|
28
29
|
if (copy.ops.includes('stretched'))
|
|
29
30
|
return;
|
|
30
|
-
copy.
|
|
31
|
+
featuresOf(copy).forEach(feature => stretch(feature.horizontal, factor));
|
|
31
32
|
copy.ops = [...copy.ops, 'stretched'];
|
|
32
33
|
copy.measurements.scale = factor;
|
|
33
34
|
};
|
|
@@ -37,7 +38,7 @@ export const revertShift = (copy) => {
|
|
|
37
38
|
if (!copy.ops.includes('shifted') || !shift)
|
|
38
39
|
return;
|
|
39
40
|
const reversed = back(shift);
|
|
40
|
-
copy.
|
|
41
|
+
featuresOf(copy).forEach(feature => {
|
|
41
42
|
move(feature.horizontal, reversed.horizontal);
|
|
42
43
|
move(feature.vertical, reversed.vertical);
|
|
43
44
|
});
|
|
@@ -49,7 +50,7 @@ export const revertScale = (copy) => {
|
|
|
49
50
|
const factor = copy.measurements.scale;
|
|
50
51
|
if (!copy.ops.includes('stretched') || factor === undefined)
|
|
51
52
|
return;
|
|
52
|
-
copy.
|
|
53
|
+
featuresOf(copy).forEach(feature => stretch(feature.horizontal, 1 / factor));
|
|
53
54
|
copy.ops = copy.ops.filter(op => op !== 'stretched');
|
|
54
55
|
delete copy.measurements.scale;
|
|
55
56
|
};
|
package/lib/asJsonLd.d.ts
CHANGED
|
@@ -1,3 +1,8 @@
|
|
|
1
1
|
import { Edition } from "./Edition";
|
|
2
|
+
/**
|
|
3
|
+
* The keys an export derives from the tree, which no node of the
|
|
4
|
+
* edition states itself. An import reads them off again.
|
|
5
|
+
*/
|
|
6
|
+
export declare const derivedKeys: ReadonlySet<string>;
|
|
2
7
|
export declare const exportDate: (date: Date) => string;
|
|
3
8
|
export declare const asJsonLd: (edition: Edition) => any;
|
package/lib/asJsonLd.js
CHANGED
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
import { systemIdIn } from "./TrackerBar";
|
|
2
2
|
import { certaintyOf, isAsserted } from "./Assumption";
|
|
3
3
|
import context from "./spec/context.json";
|
|
4
|
+
/**
|
|
5
|
+
* The keys an export derives from the tree, which no node of the
|
|
6
|
+
* edition states itself. An import reads them off again.
|
|
7
|
+
*/
|
|
8
|
+
export const derivedKeys = new Set(['bears', 'composedOf', 'augmented', 'diminished']);
|
|
4
9
|
export const exportDate = (date) => {
|
|
5
10
|
const year = date.getFullYear();
|
|
6
11
|
const month = String(date.getMonth() + 1).padStart(2, "0");
|
|
@@ -62,6 +67,55 @@ const withSystemContexts = (node) => {
|
|
|
62
67
|
: walked;
|
|
63
68
|
};
|
|
64
69
|
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
|
+
/** The act with what it changed named: an attachment augments the copy, a removal diminishes it. */
|
|
83
|
+
const changing = (copyId) => (act) => {
|
|
84
|
+
if (typeof copyId !== 'string' || !isRecord(act))
|
|
85
|
+
return act;
|
|
86
|
+
if (act['@type'] === 'Attachment')
|
|
87
|
+
return { ...act, augmented: { '@id': copyId } };
|
|
88
|
+
if (act['@type'] === 'Removal')
|
|
89
|
+
return { ...act, diminished: { '@id': copyId } };
|
|
90
|
+
return act;
|
|
91
|
+
};
|
|
92
|
+
/**
|
|
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.
|
|
99
|
+
*/
|
|
100
|
+
const withBearings = (value) => {
|
|
101
|
+
if (Array.isArray(value))
|
|
102
|
+
return value.map(withBearings);
|
|
103
|
+
if (!isRecord(value))
|
|
104
|
+
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;
|
|
118
|
+
};
|
|
65
119
|
/** Terms the context sets to null, which say nothing when the edition is read as RDF. */
|
|
66
120
|
const silentTerms = new Set(Object.entries(context['@context'])
|
|
67
121
|
.filter(([, definition]) => definition === null)
|
|
@@ -128,7 +182,7 @@ const withDoubtedReferencesQuoted = (value) => {
|
|
|
128
182
|
};
|
|
129
183
|
};
|
|
130
184
|
export const asJsonLd = (edition) => {
|
|
131
|
-
const { node, quoted } = withDoubtedReferencesQuoted(withSystemContexts(asJsonLdEntity(edition)));
|
|
185
|
+
const { node, quoted } = withDoubtedReferencesQuoted(withSystemContexts(withBearings(asJsonLdEntity(edition))));
|
|
132
186
|
// The context is the export's own; one carried in from an import must not override it.
|
|
133
187
|
const { base, '@context': carried, ...rest } = node;
|
|
134
188
|
return {
|
package/lib/editionOps.d.ts
CHANGED
|
@@ -7,7 +7,7 @@ import { Edit } from "./Edit";
|
|
|
7
7
|
import { GeneralRollCondition, RollCopy, ScaleReading, Shift } from "./RollCopy";
|
|
8
8
|
import { FeatureSource } from "./FeatureSource";
|
|
9
9
|
import { AnyArgumentation, Belief, Certainty, ObjectAssumption } from "./Assumption";
|
|
10
|
-
import {
|
|
10
|
+
import { FeatureConditionAssignment, FeatureOrPatch } 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
|
|
@@ -74,7 +74,8 @@ export declare const symbolsCarriedOnlyBy: (edition: Edition, copyId: string) =>
|
|
|
74
74
|
* Takes the features off the copy, and out of the versions with what
|
|
75
75
|
* only they carried. A feature may be named wherever the copy bears it:
|
|
76
76
|
* a patch goes with everything glued onto it, and a feature of a patch
|
|
77
|
-
* may be taken back on its own, the patch staying where it is.
|
|
77
|
+
* may be taken back on its own, the patch staying where it is. An act
|
|
78
|
+
* left having produced or added nothing goes as well.
|
|
78
79
|
*/
|
|
79
80
|
export declare const removeFeatures: (copyId: string, featureIds: readonly string[]) => EditionOp;
|
|
80
81
|
/**
|
|
@@ -84,7 +85,7 @@ export declare const removeFeatures: (copyId: string, featureIds: readonly strin
|
|
|
84
85
|
*/
|
|
85
86
|
export declare const removeCopy: (copyId: string) => EditionOp;
|
|
86
87
|
/** Why several features cannot be replaced by one. */
|
|
87
|
-
export type MergeObstacle = 'fewer-than-two' | 'different-types' | 'different-tracks' | 'differing-conditions' | 'unlike-features';
|
|
88
|
+
export type MergeObstacle = 'fewer-than-two' | 'different-types' | 'different-tracks' | 'differing-conditions' | 'unlike-features' | 'different-acts';
|
|
88
89
|
/**
|
|
89
90
|
* What stands in the way of reading the features as one, or nothing
|
|
90
91
|
* where they may be merged. Features may be merged where they differ
|
|
@@ -93,7 +94,7 @@ export type MergeObstacle = 'fewer-than-two' | 'different-types' | 'different-tr
|
|
|
93
94
|
* asked: whether a gap is a bridge of the perforator, a tear or two
|
|
94
95
|
* perforations of their own is the editor's reading.
|
|
95
96
|
*/
|
|
96
|
-
export declare const mergeObstacle: (features: readonly
|
|
97
|
+
export declare const mergeObstacle: (features: readonly FeatureOrPatch[]) => MergeObstacle | undefined;
|
|
97
98
|
/**
|
|
98
99
|
* Replaces the features of the copy with a single one covering them
|
|
99
100
|
* all, where a scan has split what the editor reads as one feature.
|
|
@@ -106,7 +107,8 @@ export declare const mergeObstacle: (features: readonly AnyFeature[]) => MergeOb
|
|
|
106
107
|
* Only the features the copy bears itself are merged. A feature of a
|
|
107
108
|
* patch states no place along the roll of its own, so there is nothing
|
|
108
109
|
* for a merge to span, and an id naming one is passed over as an id the
|
|
109
|
-
* copy does not bear is.
|
|
110
|
+
* copy does not bear is. Features of two different acts are not merged
|
|
111
|
+
* either: one feature is the work of one act.
|
|
110
112
|
*
|
|
111
113
|
* Throws where the features cannot stand for one; `mergeObstacle`
|
|
112
114
|
* says beforehand whether they can.
|