linked-rolls 0.54.0 → 0.56.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/editionOps.js CHANGED
@@ -8,9 +8,9 @@ import { asSymbols, barOf, featuresByAct, featuresOf, isPaperStretch, statesNoth
8
8
  import { systemOf } from "./TrackerBar.js";
9
9
  import { substitutionsBetween } from "./substitution.js";
10
10
  import { trackerBarOf } from "./systems/index.js";
11
- import { applyShift, applyScale, revertShift, revertScale, revertShortening, shortenHoles } from "./alignment.js";
11
+ import { applyShift, applyScale, revertShift, revertScale, revertShortening, shortenChains } from "./alignment.js";
12
12
  import { assignReference, idOf } from "./Assumption.js";
13
- import { conditions as conditionsAllowed, featuresBorneBy, isGluedOn, withBorneFeatures } from "./Feature.js";
13
+ import { conditions as conditionsAllowed, featuresBorneBy, isPatch, withBorneFeatures } from "./Feature.js";
14
14
  import { distance, mm, subtract } from "./Quantity.js";
15
15
  const noChange = () => undefined;
16
16
  const onCopy = (copyId, op) => draft => {
@@ -138,11 +138,11 @@ export const unalignCopy = (copyId) => onCopy(copyId, copy => {
138
138
  });
139
139
  /**
140
140
  * Takes the extension a pneumatic reader adds off the ends of the
141
- * copy's holes, and records how much was taken, so that its lengths
141
+ * copy's chains of holes, and records how much was taken, so that their lengths
142
142
  * can be compared with a scanned copy's at all.
143
143
  */
144
- export const shortenCopy = (copyId, extension, leaving) => onCopy(copyId, copy => shortenHoles(extension, copy, leaving));
145
- /** Puts the reader's extension back on the copy's holes. */
144
+ export const shortenCopy = (copyId, extension, leaving) => onCopy(copyId, copy => shortenChains(extension, copy, leaving));
145
+ /** Puts the reader's extension back on the copy's chains of holes. */
146
146
  export const unshortenCopy = (copyId) => onCopy(copyId, copy => revertShortening(copy));
147
147
  /** States what the copy's features were read from, in place of any earlier statement. */
148
148
  export const stateSource = (copyId, source) => onCopy(copyId, copy => {
@@ -369,7 +369,7 @@ const goneWith = (features, named) => features.flatMap(feature => named.has(feat
369
369
  : goneWith(featuresBorneBy(feature), named));
370
370
  /** The feature with the named ones gone from what it bears, or the very same one where it bears none of them. */
371
371
  const withoutBorne = (feature, named) => {
372
- if (!isGluedOn(feature) || !feature.features)
372
+ if (!isPatch(feature) || !feature.features)
373
373
  return feature;
374
374
  const borne = withoutFeatures(feature.features, named);
375
375
  return borne === feature.features ? feature : { ...feature, features: borne };
@@ -443,7 +443,7 @@ const actFor = (copy, patch, act) => {
443
443
  * the feature goes into an act of its own.
444
444
  */
445
445
  export const addFeature = (copyId, feature, act = {}) => onCopy(copyId, copy => {
446
- actFor(copy, isGluedOn(feature), act).push(feature);
446
+ actFor(copy, isPatch(feature), act).push(feature);
447
447
  });
448
448
  /**
449
449
  * States that the patch bears the feature. What a patch bears came onto
@@ -452,7 +452,7 @@ export const addFeature = (copyId, feature, act = {}) => onCopy(copyId, copy =>
452
452
  */
453
453
  export const addBorneFeature = (copyId, patchId, feature) => onCopy(copyId, copy => {
454
454
  const patch = featuresOf(copy).flatMap(withBorneFeatures).find(borne => borne.id === patchId);
455
- if (!patch || !isGluedOn(patch))
455
+ if (!patch || !isPatch(patch))
456
456
  return;
457
457
  if (!patch.features)
458
458
  patch.features = [];
@@ -502,7 +502,7 @@ const sayTheSame = (a, b) => {
502
502
  */
503
503
  const nature = (feature) => {
504
504
  const { id, horizontal, depiction, condition, ...rest } = feature;
505
- return isGluedOn(feature) && feature.features
505
+ return isPatch(feature) && feature.features
506
506
  ? { ...rest, features: feature.features.map(borne => borne.id) }
507
507
  : rest;
508
508
  };
package/lib/migrate.js CHANGED
@@ -11,6 +11,14 @@ const renamedKeys = {
11
11
  annotates: 'depiction',
12
12
  classification: 'editType'
13
13
  };
14
+ /**
15
+ * Classes of feature renamed since: a chain of holes was named after a
16
+ * single hole, and a patch after the act that glued it on.
17
+ */
18
+ const renamedTypes = {
19
+ Hole: 'HoleChain',
20
+ GluedOn: 'Patch'
21
+ };
14
22
  const referenceKeys = ['alignedWith', 'pairedWith', 'basedOn'];
15
23
  /**
16
24
  * The five type terms that were capitalised while the rest of the
@@ -33,6 +41,9 @@ const withTypology = (node) => {
33
41
  }
34
42
  return node;
35
43
  };
44
+ const withRenamedType = (node) => Object.hasOwn(renamedTypes, node['@type']) ? { ...node, '@type': renamedTypes[node['@type']] } : node;
45
+ /** Whether the feature is of the class under either name, since a node is migrated before its children are. */
46
+ const isOfType = (type) => (feature) => feature?.['@type'] === type || renamedTypes[feature?.['@type']] === type;
36
47
  /** A version once stated whether it served as a master or stood on one copy. */
37
48
  const withoutVersionType = (node) => {
38
49
  if (!Object.hasOwn(node, 'versionType'))
@@ -163,9 +174,9 @@ const withTypedPerforator = (node) => {
163
174
  };
164
175
  const asynchronous = 'https://w3id.org/reo/type/drive/asynchronous';
165
176
  /**
166
- * Each hole once stated its punching pattern. A staggering hole the copy
167
- * was punched with shows that its perforator drove each punch on its
168
- * own; one a later act made shows nothing about the machine. Regular
177
+ * Each chain once stated its punching pattern. A staggering chain the
178
+ * copy was punched with shows that its perforator drove each punch on
179
+ * its own; one a later act made shows nothing about the machine. Regular
169
180
  * and accelerating bridges are not carried over: the chain pitch states
170
181
  * the one, and for the other no source was found. The features are in
171
182
  * their acts here, since a node is migrated before its children are.
@@ -180,7 +191,7 @@ const withDriveOfStaggering = (node) => {
180
191
  return { ...node, production: { ...node.production, perforator: { ...perforator, drive: { '@id': asynchronous } } } };
181
192
  };
182
193
  const withoutPattern = (node) => {
183
- if (node['@type'] !== 'Hole' || !Object.hasOwn(node, 'pattern'))
194
+ if (node['@type'] !== 'HoleChain' || !Object.hasOwn(node, 'pattern'))
184
195
  return node;
185
196
  const { pattern: _moved, ...rest } = node;
186
197
  return rest;
@@ -193,13 +204,13 @@ const featuresOf = (copy) => [
193
204
  ...(Array.isArray(copy.features) ? copy.features : []),
194
205
  ...(Array.isArray(copy.production?.produced) ? copy.production.produced : [])
195
206
  ];
207
+ const isHoleChain = isOfType('HoleChain');
196
208
  /**
197
209
  * A copy read on a roll reader was stated as a recording before a sound
198
210
  * recording could be one. A sound recording gives no holes, so a recording
199
211
  * with holes is a reading.
200
212
  */
201
- const withReadingKind = (node) => node.readFrom?.kind === 'recording'
202
- && featuresOf(node).some((feature) => feature?.['@type'] === 'Hole')
213
+ const withReadingKind = (node) => node.readFrom?.kind === 'recording' && featuresOf(node).some(isHoleChain)
203
214
  ? { ...node, readFrom: { ...node.readFrom, kind: 'reading' } }
204
215
  : node;
205
216
  /** A feature written while the kind of a feature was a type beside its class. */
@@ -209,7 +220,7 @@ const withoutFeatureKind = (node) => {
209
220
  const { kind: _typed, ...rest } = node;
210
221
  return rest;
211
222
  };
212
- const isPatch = (feature) => feature?.['@type'] === 'GluedOn';
223
+ const isPatch = isOfType('Patch');
213
224
  /**
214
225
  * A feature a patch bears was sometimes written without an id, and what
215
226
  * has no id can be referred to from nowhere: neither by a reading of it
@@ -300,7 +311,7 @@ const withTimeSpanDates = (node) => {
300
311
  const { '@value': within, '@type': _typed, ...rest } = node;
301
312
  return { ...rest, within };
302
313
  };
303
- const migrateNode = (node) => [withRenamedKeys, withTypology, withoutVersionType, withoutVersionSiglum, withLowerCaseTerms, withSplitMethod, withReferences, withKeeper, withoutEmptyKeeper,
314
+ const migrateNode = (node) => [withRenamedKeys, withTypology, withRenamedType, withoutVersionType, withoutVersionSiglum, withLowerCaseTerms, withSplitMethod, withReferences, withKeeper, withoutEmptyKeeper,
304
315
  withPerforator, withProductionNodes, withTypedPerforator, withScale, withDerivationList, withReadingKind, withTimeSpanDates,
305
316
  withoutFeatureKind, withBorneFeaturesNamed, withFeaturesInActs, withDriveOfStaggering, withoutPattern]
306
317
  .reduce((result, step) => step(result), node);
@@ -14,17 +14,17 @@ import { Millimeters, Seconds } from "../Quantity.js";
14
14
  * elapsed time, not paper, and the take-up spool accelerates the paper
15
15
  * as it fills, so `placeAt` has to put the time back onto the paper.
16
16
  * And a switch stays open longer than its perforation is long, so a
17
- * hole read here runs past the punched one: Phillips measures the
17
+ * chain read here runs past the punched one: Phillips measures the
18
18
  * pneumatic on-time as exceeding the apparent length of a perforation
19
19
  * (p. 178), and names what it depends on as the length of the
20
20
  * perforation, the height of the tracker bar hole and the paper speed
21
21
  * (p. 180).
22
22
  *
23
23
  * Left in, that extension is not a difference between copies at all:
24
- * the end of a hole here is a pneumatic on-time where the end of a
25
- * scanned copy's hole is a punched slot, so a collation comparing the
24
+ * the end of a chain here is a pneumatic on-time where the end of a
25
+ * scanned copy's chain is a punched slot, so a collation comparing the
26
26
  * two reads the one as a lengthening of the other. `extension` takes it
27
- * off at the end of every hole, and the copy records what was taken.
27
+ * off at the end of every chain, and the copy records what was taken.
28
28
  *
29
29
  * How much to take off is measured rather than derived, since he gives
30
30
  * only the 0.5 mm by which the Welte bar's holes exceed the Licensee's
@@ -71,8 +71,8 @@ export interface PhillipsErollOptions {
71
71
  placeAt?: (elapsed: Seconds) => Millimeters;
72
72
  /**
73
73
  * How much longer a valve is held on than the perforation that
74
- * opened it, taken off the end of every hole so that these lengths
75
- * can be compared with a scanned copy's. Nothing leaves the holes
74
+ * opened it, taken off the end of every chain so that these lengths
75
+ * can be compared with a scanned copy's. Nothing leaves the chains
76
76
  * as the reader reported them, which is what every copy read before
77
77
  * this option existed states.
78
78
  *
@@ -2,7 +2,7 @@ import { read } from "midifile-ts";
2
2
  import { v4 } from "uuid";
3
3
  import { assignObject } from "../Assumption.js";
4
4
  import { systemOf } from "../TrackerBar.js";
5
- import { shortenHoles } from "../alignment.js";
5
+ import { shortenChains } from "../alignment.js";
6
6
  import { welteT100 } from "../systems/welteT100/bar.js";
7
7
  import { welteLicensee } from "../systems/welteLicensee/bar.js";
8
8
  import { inMetersPerMinute, mm, seconds, track } from "../Quantity.js";
@@ -19,17 +19,17 @@ import { inMetersPerMinute, mm, seconds, track } from "../Quantity.js";
19
19
  * elapsed time, not paper, and the take-up spool accelerates the paper
20
20
  * as it fills, so `placeAt` has to put the time back onto the paper.
21
21
  * And a switch stays open longer than its perforation is long, so a
22
- * hole read here runs past the punched one: Phillips measures the
22
+ * chain read here runs past the punched one: Phillips measures the
23
23
  * pneumatic on-time as exceeding the apparent length of a perforation
24
24
  * (p. 178), and names what it depends on as the length of the
25
25
  * perforation, the height of the tracker bar hole and the paper speed
26
26
  * (p. 180).
27
27
  *
28
28
  * Left in, that extension is not a difference between copies at all:
29
- * the end of a hole here is a pneumatic on-time where the end of a
30
- * scanned copy's hole is a punched slot, so a collation comparing the
29
+ * the end of a chain here is a pneumatic on-time where the end of a
30
+ * scanned copy's chain is a punched slot, so a collation comparing the
31
31
  * two reads the one as a lengthening of the other. `extension` takes it
32
- * off at the end of every hole, and the copy records what was taken.
32
+ * off at the end of every chain, and the copy records what was taken.
33
33
  *
34
34
  * How much to take off is measured rather than derived, since he gives
35
35
  * only the 0.5 mm by which the Welte bar's holes exceed the Licensee's
@@ -153,7 +153,7 @@ export function readFromPhillipsEroll(buffer, { system = welteT100, controlOffse
153
153
  if (!system.meaningOf(position))
154
154
  return [];
155
155
  return [{
156
- type: 'Hole',
156
+ type: 'HoleChain',
157
157
  id: v4(),
158
158
  vertical: { from: position, unit: 'track' },
159
159
  horizontal: {
@@ -174,11 +174,11 @@ export function readFromPhillipsEroll(buffer, { system = welteT100, controlOffse
174
174
  readFrom: {
175
175
  kind: 'reading',
176
176
  actor: assignObject({ name: 'Phillips, Peter', sameAs: [] }),
177
- note: 'Read on Phillips’s pneumatic roll reader. The places are elapsed time put back onto the paper, and a hole runs as long as its switch stayed open, which is longer than the perforation.'
177
+ note: 'Read on Phillips’s pneumatic roll reader. The places are elapsed time put back onto the paper, and a chain of holes runs as long as its switch stayed open, which is longer than the perforation.'
178
178
  }
179
179
  };
180
180
  if (extension !== undefined)
181
- shortenHoles(extension, copy);
181
+ shortenChains(extension, copy);
182
182
  return copy;
183
183
  }
184
184
  /** The bars his files are known to be numbered by. */
@@ -19,7 +19,7 @@ export interface SpencerBarOptions {
19
19
  }
20
20
  /**
21
21
  * Reads the copy on the bar it was cut for, whose numbering it keeps.
22
- * A hole on a position that bar does not read is left out, as the bar
22
+ * A chain on a position that bar does not read is left out, as the bar
23
23
  * would leave it.
24
24
  */
25
25
  export declare function readFromSpencerBar(buffer: ArrayBuffer, { rowsPerInch, system }?: SpencerBarOptions): RollCopy;
@@ -80,7 +80,7 @@ const holesOf = (events) => {
80
80
  };
81
81
  /**
82
82
  * Reads the copy on the bar it was cut for, whose numbering it keeps.
83
- * A hole on a position that bar does not read is left out, as the bar
83
+ * A chain on a position that bar does not read is left out, as the bar
84
84
  * would leave it.
85
85
  */
86
86
  export function readFromSpencerBar(buffer, { rowsPerInch = SPENCER_ROWS_PER_INCH, system = welteLicensee } = {}) {
@@ -95,7 +95,7 @@ export function readFromSpencerBar(buffer, { rowsPerInch = SPENCER_ROWS_PER_INCH
95
95
  if (!system.meaningOf(position))
96
96
  return [];
97
97
  return [{
98
- type: 'Hole',
98
+ type: 'HoleChain',
99
99
  id: v4(),
100
100
  vertical: {
101
101
  from: position,
@@ -136,7 +136,7 @@ export function readFromStanfordAton(atonString, { trackShift, system = welteT10
136
136
  const column = readPx(hole.ORIGIN_COL);
137
137
  const columnWidth = readPx(hole.WIDTH_COL);
138
138
  return [{
139
- type: 'Hole',
139
+ type: 'HoleChain',
140
140
  id: v4(),
141
141
  ...(stanford && {
142
142
  depiction: stanford.depictionOf(column, attack, columnWidth, subtract(release, attack))
package/lib/schema.json CHANGED
@@ -78,7 +78,7 @@
78
78
  "AnyFeature": {
79
79
  "anyOf": [
80
80
  {
81
- "$ref": "#/definitions/Hole"
81
+ "$ref": "#/definitions/HoleChain"
82
82
  },
83
83
  {
84
84
  "$ref": "#/definitions/Writing"
@@ -87,7 +87,7 @@
87
87
  "$ref": "#/definitions/Mark"
88
88
  }
89
89
  ],
90
- "description": "The features proper: a hole, a writing and a mark are all human-made features, and each of them is borne by whatever it sits on. A patch is an object glued onto the paper and stands apart from them."
90
+ "description": "The features proper: a chain of holes, a writing and a mark are all human-made features, and each of them is borne by whatever it sits on. A patch is an object glued onto the paper and stands apart from them."
91
91
  },
92
92
  "AnySymbol": {
93
93
  "anyOf": [
@@ -688,7 +688,7 @@
688
688
  "ontology": "reo:before"
689
689
  },
690
690
  "carriers": {
691
- "description": "References to the physical features (e.g. holes) on the roll copies that carry this symbol. Since the association might be debatable, it can be annotated. There might be e.g. doubts about the meaning and correct transcription of a feature on a physical roll. This points to a feature by its `@id`.",
691
+ "description": "References to the physical features (e.g. chains of holes) on the roll copies that carry this symbol. Since the association might be debatable, it can be annotated. There might be e.g. doubts about the meaning and correct transcription of a feature on a physical roll. This points to a feature by its `@id`.",
692
692
  "items": {
693
693
  "$ref": "#/definitions/ReferenceAssumption"
694
694
  },
@@ -793,99 +793,8 @@
793
793
  "type": "object",
794
794
  "ontology": "crm:E7 Activity"
795
795
  },
796
- "GluedOn": {
797
- "description": "A piece of material (paper or tape) glued onto the roll surface. Glued-on features are typically used to cover perforations (for corrections) or to reinforce damaged areas. They may themselves carry other features such as writings or additional holes.",
798
- "properties": {
799
- "condition": {
800
- "$ref": "#/definitions/ObjectAssumption%3CConditionState%3C(%22detaching%22%7C%22ripped%22)%3E%3E",
801
- "description": "This can be used e.g. to indicate a perforation which is torn out or in any other way damaged.",
802
- "ontology": "crm:P44 has condition"
803
- },
804
- "depiction": {
805
- "description": "IIIF region pointing to a depiction of this feature in the scan.",
806
- "type": "string",
807
- "ontology": "crm:P138i has representation"
808
- },
809
- "features": {
810
- "description": "A glued-on feature itself may carry other features. Nested features do not need to be positioned explicitly.",
811
- "items": {
812
- "$ref": "#/definitions/NestedFeature"
813
- },
814
- "type": "array",
815
- "ontology": "crm:P46 is composed of"
816
- },
817
- "horizontal": {
818
- "$ref": "#/definitions/HorizontalSpan",
819
- "description": "Horizontal span of the feature on the roll.",
820
- "ontology": "crm:P43 has dimension"
821
- },
822
- "material": {
823
- "description": "The material of the glued-on feature.",
824
- "enum": [
825
- "paper",
826
- "tape"
827
- ],
828
- "type": "string",
829
- "ontology": "crm:P45 consists of"
830
- },
831
- "rotation": {
832
- "$ref": "#/definitions/Measure%3C%22deg%22%3E",
833
- "description": "How far the patch was stuck on askew. At zero its edges stand square to the roll, and the angle turns them towards the end of it, as a writing's reading direction turns.",
834
- "ontology": "reo:rotation"
835
- },
836
- "side": {
837
- "description": "The face of the roll it lies on: the side that faces the reader as the roll plays, or the back of it.",
838
- "enum": [
839
- "recto",
840
- "verso"
841
- ],
842
- "type": "string",
843
- "ontology": "reo:side"
844
- },
845
- "vertical": {
846
- "$ref": "#/definitions/VerticalSpan",
847
- "description": "Vertical span of the feature on the roll.",
848
- "ontology": "crm:P43 has dimension"
849
- },
850
- "@id": {
851
- "description": "A unique identifier for this object.",
852
- "type": "string"
853
- },
854
- "@type": {
855
- "const": "GluedOn",
856
- "description": "The type discriminator for this object.",
857
- "type": "string",
858
- "ontology": "rdf:type"
859
- },
860
- "bears": {
861
- "type": "array",
862
- "items": {
863
- "type": "object",
864
- "properties": {
865
- "@id": {
866
- "type": "string"
867
- }
868
- },
869
- "required": [
870
- "@id"
871
- ]
872
- },
873
- "description": "The features the patch bears. Derived on export.",
874
- "ontology": "crm:P56 bears feature"
875
- }
876
- },
877
- "required": [
878
- "horizontal",
879
- "@id",
880
- "material",
881
- "@type",
882
- "vertical"
883
- ],
884
- "type": "object",
885
- "ontology": "reo:GluedOn"
886
- },
887
- "Hole": {
888
- "description": "A hole (perforation) in the roll paper. Holes are the primary carriers of musical information on piano rolls, as they trigger notes and expression controls when passing over the tracker bar. A punched hole is a human-made feature: CRM counts \"the information encoding features on mechanical or digital carriers\" among the features purposely created by human activity.",
796
+ "HoleChain": {
797
+ "description": "A chain of holes punched along the roll, which the tracker bar reads as it passes. The perforator cuts a held note or function as a row of punches with bridges of paper left between them, so most perforations are chains; one without a bridge is a chain of a single hole. The holes are the chain's parts and are not stated one by one. A punched chain is a human-made feature: CRM counts \"the information encoding features on mechanical or digital carriers\" among the features purposely created by human activity.",
889
798
  "properties": {
890
799
  "condition": {
891
800
  "$ref": "#/definitions/ObjectAssumption%3CConditionState%3C(%22partially-torn%22%7C%22missing-perforation%22)%3E%3E",
@@ -912,7 +821,7 @@
912
821
  "type": "string"
913
822
  },
914
823
  "@type": {
915
- "const": "Hole",
824
+ "const": "HoleChain",
916
825
  "description": "The type discriminator for this object.",
917
826
  "type": "string",
918
827
  "ontology": "rdf:type"
@@ -925,7 +834,7 @@
925
834
  "vertical"
926
835
  ],
927
836
  "type": "object",
928
- "ontology": "reo:Hole"
837
+ "ontology": "reo:HoleChain"
929
838
  },
930
839
  "HorizontalSpan": {
931
840
  "description": "Describes the horizontal extent of a feature on the roll, measured in millimeters from the beginning of the roll. The `from` value is the start position and `to` is the end position.",
@@ -1254,7 +1163,7 @@
1254
1163
  "added": {
1255
1164
  "description": "The patches glued onto the copy, each with whatever it bears.",
1256
1165
  "items": {
1257
- "$ref": "#/definitions/GluedOn"
1166
+ "$ref": "#/definitions/Patch"
1258
1167
  },
1259
1168
  "type": "array",
1260
1169
  "ontology": "crm:P111 added"
@@ -1455,7 +1364,7 @@
1455
1364
  "type": "string"
1456
1365
  },
1457
1366
  "@type": {
1458
- "const": "Hole",
1367
+ "const": "HoleChain",
1459
1368
  "description": "The type discriminator for this object.",
1460
1369
  "type": "string",
1461
1370
  "ontology": "rdf:type"
@@ -1608,7 +1517,7 @@
1608
1517
  "ontology": "crm:P138i has representation"
1609
1518
  },
1610
1519
  "features": {
1611
- "description": "A glued-on feature itself may carry other features. Nested features do not need to be positioned explicitly.",
1520
+ "description": "The features the patch itself carries. They need not be positioned explicitly.",
1612
1521
  "items": {
1613
1522
  "$ref": "#/definitions/NestedFeature"
1614
1523
  },
@@ -1621,7 +1530,7 @@
1621
1530
  "ontology": "crm:P43 has dimension"
1622
1531
  },
1623
1532
  "material": {
1624
- "description": "The material of the glued-on feature.",
1533
+ "description": "What the patch is made of.",
1625
1534
  "enum": [
1626
1535
  "paper",
1627
1536
  "tape"
@@ -1653,7 +1562,7 @@
1653
1562
  "type": "string"
1654
1563
  },
1655
1564
  "@type": {
1656
- "const": "GluedOn",
1565
+ "const": "Patch",
1657
1566
  "description": "The type discriminator for this object.",
1658
1567
  "type": "string",
1659
1568
  "ontology": "rdf:type"
@@ -1703,7 +1612,7 @@
1703
1612
  "ontology": "reo:before"
1704
1613
  },
1705
1614
  "carriers": {
1706
- "description": "References to the physical features (e.g. holes) on the roll copies that carry this symbol. Since the association might be debatable, it can be annotated. There might be e.g. doubts about the meaning and correct transcription of a feature on a physical roll. This points to a feature by its `@id`.",
1615
+ "description": "References to the physical features (e.g. chains of holes) on the roll copies that carry this symbol. Since the association might be debatable, it can be annotated. There might be e.g. doubts about the meaning and correct transcription of a feature on a physical roll. This points to a feature by its `@id`.",
1707
1616
  "items": {
1708
1617
  "$ref": "#/definitions/ReferenceAssumption"
1709
1618
  },
@@ -2678,6 +2587,97 @@
2678
2587
  ],
2679
2588
  "type": "object"
2680
2589
  },
2590
+ "Patch": {
2591
+ "description": "A piece of paper or tape glued onto the roll: a label naming it, a strip covering perforations, or a patch reinforcing a tear. A patch may itself carry other features, such as writings or holes.",
2592
+ "properties": {
2593
+ "condition": {
2594
+ "$ref": "#/definitions/ObjectAssumption%3CConditionState%3C(%22detaching%22%7C%22ripped%22)%3E%3E",
2595
+ "description": "This can be used e.g. to indicate a perforation which is torn out or in any other way damaged.",
2596
+ "ontology": "crm:P44 has condition"
2597
+ },
2598
+ "depiction": {
2599
+ "description": "IIIF region pointing to a depiction of this feature in the scan.",
2600
+ "type": "string",
2601
+ "ontology": "crm:P138i has representation"
2602
+ },
2603
+ "features": {
2604
+ "description": "The features the patch itself carries. They need not be positioned explicitly.",
2605
+ "items": {
2606
+ "$ref": "#/definitions/NestedFeature"
2607
+ },
2608
+ "type": "array",
2609
+ "ontology": "crm:P46 is composed of"
2610
+ },
2611
+ "horizontal": {
2612
+ "$ref": "#/definitions/HorizontalSpan",
2613
+ "description": "Horizontal span of the feature on the roll.",
2614
+ "ontology": "crm:P43 has dimension"
2615
+ },
2616
+ "material": {
2617
+ "description": "What the patch is made of.",
2618
+ "enum": [
2619
+ "paper",
2620
+ "tape"
2621
+ ],
2622
+ "type": "string",
2623
+ "ontology": "crm:P45 consists of"
2624
+ },
2625
+ "rotation": {
2626
+ "$ref": "#/definitions/Measure%3C%22deg%22%3E",
2627
+ "description": "How far the patch was stuck on askew. At zero its edges stand square to the roll, and the angle turns them towards the end of it, as a writing's reading direction turns.",
2628
+ "ontology": "reo:rotation"
2629
+ },
2630
+ "side": {
2631
+ "description": "The face of the roll it lies on: the side that faces the reader as the roll plays, or the back of it.",
2632
+ "enum": [
2633
+ "recto",
2634
+ "verso"
2635
+ ],
2636
+ "type": "string",
2637
+ "ontology": "reo:side"
2638
+ },
2639
+ "vertical": {
2640
+ "$ref": "#/definitions/VerticalSpan",
2641
+ "description": "Vertical span of the feature on the roll.",
2642
+ "ontology": "crm:P43 has dimension"
2643
+ },
2644
+ "@id": {
2645
+ "description": "A unique identifier for this object.",
2646
+ "type": "string"
2647
+ },
2648
+ "@type": {
2649
+ "const": "Patch",
2650
+ "description": "The type discriminator for this object.",
2651
+ "type": "string",
2652
+ "ontology": "rdf:type"
2653
+ },
2654
+ "bears": {
2655
+ "type": "array",
2656
+ "items": {
2657
+ "type": "object",
2658
+ "properties": {
2659
+ "@id": {
2660
+ "type": "string"
2661
+ }
2662
+ },
2663
+ "required": [
2664
+ "@id"
2665
+ ]
2666
+ },
2667
+ "description": "The features the patch bears. Derived on export.",
2668
+ "ontology": "crm:P56 bears feature"
2669
+ }
2670
+ },
2671
+ "required": [
2672
+ "horizontal",
2673
+ "@id",
2674
+ "material",
2675
+ "@type",
2676
+ "vertical"
2677
+ ],
2678
+ "type": "object",
2679
+ "ontology": "reo:Patch"
2680
+ },
2681
2681
  "Perforator": {
2682
2682
  "description": "The machine that punched the copy. It stands for this production alone. Whether it is the one another copy was punched on is left to a statement of identity made about it elsewhere, which its id allows.",
2683
2683
  "properties": {
@@ -2808,7 +2808,7 @@
2808
2808
  "ontology": "crm:P16 used specific object"
2809
2809
  },
2810
2810
  "produced": {
2811
- "description": "The features the copy came from its punching with: the note and expression perforations, and now and then a mark the perforator left. A reading of a scan finds every hole on the paper at once and states it here, and a feature an editor reads as the work of a later hand belongs in the act that made it, whichever kind of feature it is.",
2811
+ "description": "The features the copy came from its punching with: the note and expression perforations, and now and then a mark the perforator left. A reading of a scan finds every chain of holes on the paper at once and states it here, and a feature an editor reads as the work of a later hand belongs in the act that made it, whichever kind of feature it is.",
2812
2812
  "items": {
2813
2813
  "$ref": "#/definitions/AnyFeature"
2814
2814
  },
@@ -3064,10 +3064,10 @@
3064
3064
  "ontology": "crmdig:L23 used software or firmware"
3065
3065
  },
3066
3066
  "readerExtension": {
3067
- "description": "What a pneumatic reader added to this copy's holes, where it was taken off again. Such a reader reports how long a valve stayed open, which exceeds the perforation that opened it, so its holes are overlong by a constant while its onsets agree. Nothing for a copy read by other means, whose holes are the punched slots themselves. Not exported to RDF.",
3067
+ "description": "What a pneumatic reader added to this copy's chains of holes, where it was taken off again. Such a reader reports how long a valve stayed open, which exceeds the perforation that opened it, so its chains are overlong by a constant while its onsets agree. Nothing for a copy read by other means, whose chains are the punched ones themselves. Not exported to RDF.",
3068
3068
  "properties": {
3069
3069
  "leaving": {
3070
- "description": "The holes it was not taken off, by `@id`, being no longer than it is. The constant reaches its limit there rather than the copy being wrong, and why they were left is for the edition to state about the features themselves; this only records that they stand as the reader gave them, so that putting the extension back does not lengthen a hole nothing was taken from.",
3070
+ "description": "The chains it was not taken off, by `@id`, being no longer than it is. The constant reaches its limit there rather than the copy being wrong, and why they were left is for the edition to state about the features themselves; this only records that they stand as the reader gave them, so that putting the extension back does not lengthen a chain nothing was taken from.",
3071
3071
  "items": {
3072
3072
  "type": "string"
3073
3073
  },
@@ -3075,7 +3075,7 @@
3075
3075
  },
3076
3076
  "length": {
3077
3077
  "$ref": "#/definitions/Millimeters",
3078
- "description": "How much longer the reading of a hole ran than the perforation that caused it."
3078
+ "description": "How much longer the reading of a chain ran than the perforation that caused it."
3079
3079
  }
3080
3080
  },
3081
3081
  "required": [
@@ -3258,7 +3258,7 @@
3258
3258
  "description": "A textual symbol, e.g. a label or annotation found on the roll.",
3259
3259
  "properties": {
3260
3260
  "carriers": {
3261
- "description": "References to the physical features (e.g. holes) on the roll copies that carry this symbol. Since the association might be debatable, it can be annotated. There might be e.g. doubts about the meaning and correct transcription of a feature on a physical roll. This points to a feature by its `@id`.",
3261
+ "description": "References to the physical features (e.g. chains of holes) on the roll copies that carry this symbol. Since the association might be debatable, it can be annotated. There might be e.g. doubts about the meaning and correct transcription of a feature on a physical roll. This points to a feature by its `@id`.",
3262
3262
  "items": {
3263
3263
  "$ref": "#/definitions/ReferenceAssumption"
3264
3264
  },
@@ -14,10 +14,10 @@
14
14
  "Edition": "lrmoo:F2_Expression",
15
15
  "Version": "lrmoo:F2_Expression",
16
16
  "RollCopy": "reo:RollCopy",
17
- "Hole": "reo:Hole",
17
+ "HoleChain": "reo:HoleChain",
18
18
  "Mark": "reo:Mark",
19
19
  "Writing": "reo:Writing",
20
- "GluedOn": "reo:GluedOn",
20
+ "Patch": "reo:Patch",
21
21
  "Attachment": "crm:E79_Part_Addition",
22
22
  "Removal": "crm:E80_Part_Removal",
23
23
  "Alteration": "crm:E12_Production",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "linked-rolls",
3
- "version": "0.54.0",
3
+ "version": "0.56.0",
4
4
  "description": "Digital editions of piano rolls: import, collation, editorial assumptions, JSON-LD export, and emulation through a reproducing system",
5
5
  "license": "MIT",
6
6
  "repository": {