linked-rolls 0.1.1 → 0.2.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/RollCopy.d.ts CHANGED
@@ -6,6 +6,7 @@ import { AnyFeature } from "./Feature";
6
6
  import { ObjectAssumption, ValueAssumption } from "./Assumption";
7
7
  import { WithId, WithType } from "./utils";
8
8
  import { ActorAssignment } from "./Edit";
9
+ import { Agent, Concept } from "./Edition";
9
10
  /**
10
11
  * This condition state is used to describe the roll's
11
12
  * paper shrinkage or stretching. It might be calculated
@@ -16,6 +17,7 @@ export interface PaperStretch extends ConditionState<'paper-stretch'> {
16
17
  /**
17
18
  * The stretch factor, e.g. 1.02 means the paper has
18
19
  * stretched by 2% compared to its original dimensions.
20
+ * @see rdf:value
19
21
  */
20
22
  factor: number;
21
23
  }
@@ -53,11 +55,17 @@ export declare const applyStretch: (paperStretch: ObjectAssumption<PaperStretch>
53
55
  * A date value wrapped as an assumption, so that the date
54
56
  * can be annotated with a belief about its certainty and source.
55
57
  */
56
- export type DateAssignment = ValueAssumption<Date>;
58
+ export type DateAssignment = ValueAssumption<Date> & {
59
+ /**
60
+ * The datatype of the value. Written on export so that
61
+ * RDF reads the value as a date rather than a string.
62
+ */
63
+ '@type'?: 'xsd:date';
64
+ };
57
65
  /**
58
- * Describes the production of a roll copy, including the
59
- * manufacturing company, the roll system, and the paper used.
60
- * @see lrm:F33 Reproduction Event
66
+ * Describes the production of a roll copy: the manufacturer,
67
+ * the paper used, and the date.
68
+ * @see lrmoo:F32 Item Production Event
61
69
  */
62
70
  export interface ProductionEvent {
63
71
  /**
@@ -65,20 +73,15 @@ export interface ProductionEvent {
65
73
  * (e.g. "M. Welte & Söhne").
66
74
  * @see crm:P14 carried out by
67
75
  */
68
- company: string;
69
- /**
70
- * The roll system used for production
71
- * (e.g. "Welte-Mignon T100", "Welte-Mignon T98").
72
- */
73
- system: string;
76
+ company?: Agent;
74
77
  /**
75
- * The paper type used for the roll copy.
76
- * @see P126:employed
78
+ * The paper the roll copy was cut on.
79
+ * @see crm:P126 employed
77
80
  */
78
- paper: string;
81
+ paper?: Concept;
79
82
  /**
80
83
  * The date of production, if known.
81
- * @see crm:P4 has time-span
84
+ * @see dcterms:date
82
85
  */
83
86
  date?: DateAssignment;
84
87
  }
@@ -89,7 +92,15 @@ export interface ProductionEvent {
89
92
  * @see crm:E79 Part Addition, crm:E80 Part Removal
90
93
  */
91
94
  export type Modification = Partial<{
95
+ /**
96
+ * Who carried out the modification.
97
+ * @see crm:P14 carried out by
98
+ */
92
99
  actor: ActorAssignment;
100
+ /**
101
+ * When the modification took place.
102
+ * @see dcterms:date
103
+ */
93
104
  date: DateAssignment;
94
105
  }> & ({
95
106
  type: 'Addition';
@@ -112,6 +123,7 @@ export type Modification = Partial<{
112
123
  * Sometimes however, we may see traces of features
113
124
  * that have been removed, e.g. through bright spots on
114
125
  * the roll.
126
+ * @see crm:P21 had general purpose
115
127
  */
116
128
  purpose: 'delabeling';
117
129
  });
@@ -120,66 +132,78 @@ export type Modification = Partial<{
120
132
  * Each roll copy has its own set of features, measurements,
121
133
  * conditions, and modifications. Multiple copies of the same
122
134
  * roll may exist across different archives or collections.
123
- * @see crm:E22 Human-Made Object
135
+ * @see lrmoo:F5 Item
124
136
  */
125
137
  export interface RollCopy extends WithType<'RollCopy'>, WithId {
126
138
  /**
127
139
  * A list of operations that have been applied to this copy's features
128
140
  * (e.g. 'shifted', 'stretched') to normalize measurements
129
- * for comparison with other copies.
141
+ * for comparison with other copies. Not exported to RDF.
130
142
  */
131
143
  ops: Array<'shifted' | 'stretched'>;
132
144
  /**
133
145
  * Physical measurements of this roll copy, including
134
146
  * dimensions, punch diameter, hole separation, margins,
135
147
  * shift corrections, and information about the measuring software.
148
+ * @see crm:P39i was measured by
136
149
  */
137
150
  measurements: Partial<{
138
151
  /**
139
152
  * The physical dimensions of the roll.
153
+ * @see reo:dimensions
140
154
  */
141
155
  dimensions: {
142
156
  /**
143
157
  * The width of the roll in the given unit.
158
+ * @see reo:width
144
159
  */
145
160
  width: number;
146
161
  /**
147
162
  * The total height (length) of the roll in the given unit.
163
+ * @see reo:height
148
164
  */
149
165
  height: number;
150
166
  /**
151
167
  * The unit of measurement (e.g. 'mm').
168
+ * @see crm:P91 has unit
152
169
  */
153
170
  unit: string;
154
171
  };
155
172
  /**
156
173
  * The average diameter of punched holes.
174
+ * @see reo:punchDiameter
157
175
  */
158
176
  punchDiameter: {
159
177
  /**
160
178
  * The measured punch diameter value.
179
+ * @see crm:P90 has value
161
180
  */
162
181
  value: number;
163
182
  /**
164
183
  * The unit of measurement (e.g. 'mm').
184
+ * @see crm:P91 has unit
165
185
  */
166
186
  unit: string;
167
187
  };
168
188
  /**
169
189
  * The distance between adjacent tracker bar holes.
190
+ * @see reo:holeSeparation
170
191
  */
171
192
  holeSeparation: {
172
193
  /**
173
194
  * The measured hole separation value.
195
+ * @see crm:P90 has value
174
196
  */
175
197
  value: number;
176
198
  /**
177
199
  * The unit of measurement (e.g. 'px', 'mm').
200
+ * @see crm:P91 has unit
178
201
  */
179
202
  unit: string;
180
203
  };
181
204
  /**
182
205
  * The margins on the treble and bass sides of the roll.
206
+ * Not exported to RDF.
183
207
  */
184
208
  margins: {
185
209
  /**
@@ -195,57 +219,65 @@ export interface RollCopy extends WithType<'RollCopy'>, WithId {
195
219
  */
196
220
  unit: string;
197
221
  };
222
+ /**
223
+ * The shift applied to align this copy with the others.
224
+ * Not exported to RDF.
225
+ */
198
226
  shift: Shift;
199
227
  /**
200
228
  * Relates this copy's scan to the tracker bar: how the scanning
201
229
  * software's hole numbering was shifted onto the bar, and where
202
- * the track grid sits in the image.
230
+ * the track grid sits in the image. Not exported to RDF.
203
231
  */
204
232
  trackCalibration: TrackCalibration;
205
233
  /**
206
234
  * Information about the software used to take the measurements.
235
+ * @see crmdig:L23 used software or firmware
207
236
  */
208
237
  measuredBy: {
209
238
  /**
210
239
  * The name of the measurement software.
240
+ * @see rdfs:label
211
241
  */
212
242
  software: string;
213
243
  /**
214
244
  * The version of the measurement software.
245
+ * @see owl:versionInfo
215
246
  */
216
247
  version: string;
217
248
  /**
218
249
  * The date on which the measurements were taken.
219
250
  * @format date
251
+ * @see dcterms:date
220
252
  */
221
253
  date: Date;
222
254
  };
223
255
  }>;
224
256
  /**
225
257
  * The production event that created this roll copy.
226
- * @see lrm:R28i was produced by
258
+ * @see lrmoo:R28i was produced by
227
259
  */
228
260
  production?: ProductionEvent;
229
261
  /**
230
262
  * Condition assessments of this roll copy (e.g. paper stretch,
231
263
  * general wear). Each condition is an assumption annotatable
232
264
  * with a belief.
265
+ * @see crm:P44 has condition
233
266
  */
234
267
  conditions: RollConditionAssignment[];
235
268
  /**
236
- * The current physical location or archive where this copy is held.
237
- * @see crm:P55 has current location
269
+ * The institution or person holding this copy.
270
+ * @see crm:P50 has current keeper
238
271
  */
239
- location: string;
272
+ keeper: Agent;
240
273
  /**
241
- * Provides a reconstructed version of the roll,
242
- * with shift, stretch and emendations already
243
- * taken into account. This property will not be
244
- * exported in the final JSON.
274
+ * The physical features found on this copy, with shift
275
+ * and stretch already applied when `ops` says so.
276
+ * @see crm:P56 bears feature
245
277
  */
246
278
  features: AnyFeature[];
247
279
  /**
248
- * @see crm:P31 was modified by
280
+ * @see crm:P31i was modified by
249
281
  */
250
282
  modifications: Modification[];
251
283
  /**
package/lib/RollCopy.js CHANGED
@@ -226,7 +226,7 @@ export function readFromStanfordAton(atonString, { trackShift, bar = welteT100,
226
226
  id: v4(),
227
227
  ops: [],
228
228
  conditions: [],
229
- location: '',
229
+ keeper: { name: '', sameAs: [] },
230
230
  modifications: [],
231
231
  ...((scan ?? stanford) && { scan: scan ?? stanford?.scan }),
232
232
  measurements: {
@@ -302,7 +302,7 @@ export function readFromSpencerMIDI(midiBuffer, placeAt = atConstantSpeed(SPENCE
302
302
  id: v4(),
303
303
  ops: [],
304
304
  conditions: [],
305
- location: '',
305
+ keeper: { name: '', sameAs: [] },
306
306
  measurements: {},
307
307
  modifications: [],
308
308
  features
package/lib/Symbol.d.ts CHANGED
@@ -1,9 +1,10 @@
1
- import { ReferenceAssumption, ValueAssumption } from "./Assumption";
1
+ import { ReferenceAssumption } from "./Assumption";
2
2
  import { WithId } from "./utils";
3
3
  /**
4
4
  * A symbol is an abstract musical or textual entity carried by one or more
5
5
  * physical features on the roll. Symbols are the result of interpreting
6
6
  * the physical features (holes, writings, etc.) on the roll copies.
7
+ * @see crm:E90 Symbolic Object
7
8
  */
8
9
  export interface Symbol<T extends string> extends WithId {
9
10
  type: T;
@@ -22,69 +23,84 @@ export declare const isSymbol: (object: any) => object is AnySymbol;
22
23
  * A perforation is a symbol that is typically encoded as a single punched
23
24
  * hole or a group of punched holes in the physical carrier.
24
25
  * However, it might also have different physical appearences.
25
- * @see reo:C5 Perforation
26
+ * @see reo:Perforation
26
27
  */
27
28
  export interface Perforation<T extends string> extends Symbol<T> {
28
29
  /**
29
30
  * In piano rolls, perforations are often aligned with other
30
31
  * perforations, e.g. a "crescendo off" might be logically
31
- * aligned to the start of a note perforation.
32
- * @see reo:P3 aligned with
32
+ * aligned to the start of a note perforation. This points
33
+ * to the perforation by its `@id`.
34
+ * @see reo:alignedWith
33
35
  */
34
- alignedWith?: ValueAssumption<string>;
36
+ alignedWith?: ReferenceAssumption;
37
+ /**
38
+ * The perforation this one forms a pair with, e.g. a "forzando on"
39
+ * with its "forzando off". Any two perforations may be paired.
40
+ * The distance between the two is fixed: whatever displaces the
41
+ * one displaces the other. The relation is symmetric and is stated
42
+ * on one side only. This points to the perforation by its `@id`.
43
+ * @see reo:pairedWith
44
+ */
45
+ pairedWith?: ReferenceAssumption;
35
46
  }
47
+ type Pairable = WithId & {
48
+ pairedWith?: ReferenceAssumption;
49
+ };
50
+ /**
51
+ * The pairs among the given perforations, each once and in the order
52
+ * the pairing is stated. A pair whose partner is absent is left out.
53
+ */
54
+ export declare const pairsAmong: <S extends Pairable>(perforations: readonly S[]) => [S, S][];
36
55
  /**
37
56
  * A note symbol, representing a single pitched musical event on the roll.
38
57
  * The pitch is encoded via the tracker bar position (track number).
39
- * @see reo:P6 Note
58
+ * @see reo:Note
40
59
  */
41
60
  export interface Note extends Perforation<'note'> {
42
61
  /**
43
62
  * The MIDI pitch number of the note (e.g. 60 for middle C).
44
- * @see reo:P5 has pitch
63
+ * @see reo:pitch
45
64
  */
46
65
  pitch: number;
47
66
  }
48
67
  /**
49
68
  * The scope of an expression perforation, indicating whether it
50
69
  * applies to the bass or treble register of the piano.
51
- * @see reo:P6 has scope
70
+ * @see reo:scope
52
71
  */
53
72
  export type ExpressionScope = 'bass' | 'treble';
54
- /**
55
- * The type of expression encoded by a perforation on the roll,
56
- * e.g. "crescendo on", "crescendo off", etc. on Welte T-100
57
- * rolls.
58
- * @see crm:P2 has type
59
- */
60
- export type ExpressionType = 'SustainPedalOn' | 'SustainPedalOff' | 'SoftPedalOn' | 'SoftPedalOff' | 'MezzoforteOff' | 'MezzoforteOn' | 'SlowCrescendoOn' | 'SlowCrescendoOff' | 'ForzandoOn' | 'ForzandoOff' | 'MotorOff' | 'MotorOn' | 'Rewind' | 'ElectricCutOff';
61
73
  /**
62
74
  * An expression symbol, representing a perforation on the roll
63
75
  * that governs dynamics, pedaling, or mechanical functions of the
64
76
  * reproducing piano. Each expression has a scope (bass or treble)
65
77
  * and a specific expression type.
66
- * @see reo:C7 Expression
78
+ * @see reo:Expression
67
79
  */
68
80
  export interface Expression extends Perforation<'expression'> {
69
81
  /**
70
82
  * Whether this expression applies to the bass or treble register.
71
- * @see reo:P6 has scope
83
+ * @see reo:scope
72
84
  */
73
85
  scope: ExpressionScope;
74
86
  /**
75
- * The specific type of expression (e.g. sustain pedal, forzando, etc.).
87
+ * The command the perforation gives, named as the reproducing
88
+ * system of the roll names it: "SustainPedalOn", "ForzandoOff"
89
+ * and so on for the Welte-Mignon T-100. The tracker bar of the
90
+ * system lists the values it reads.
76
91
  * @see crm:P2 has type
77
92
  */
78
- expressionType: ExpressionType;
93
+ expressionType: string;
79
94
  }
80
95
  /**
81
96
  * A textual symbol, e.g. a label or annotation found on the roll.
82
97
  * @see crm:E33 Linguistic Object
83
98
  */
84
99
  export interface Text extends Symbol<'text'> {
100
+ type: 'text';
85
101
  /**
86
102
  * The text content of the symbol.
87
- * @see crm:P3 has note
103
+ * @see crm:P190 has symbolic content
88
104
  */
89
105
  text: string;
90
106
  }
@@ -93,3 +109,4 @@ export interface Text extends Symbol<'text'> {
93
109
  * Notes and expressions are perforations; texts are carried by writings.
94
110
  */
95
111
  export type AnySymbol = Note | Expression | Text;
112
+ export {};
package/lib/Symbol.js CHANGED
@@ -1,4 +1,16 @@
1
+ import { idOf } from "./Assumption";
1
2
  export const isSymbol = (object) => {
2
3
  return ('type' in object
3
4
  && (object.type === 'note' || object.type === 'expression' || object.type === 'text'));
4
5
  };
6
+ /**
7
+ * The pairs among the given perforations, each once and in the order
8
+ * the pairing is stated. A pair whose partner is absent is left out.
9
+ */
10
+ export const pairsAmong = (perforations) => {
11
+ const byId = new Map(perforations.map(p => [p.id, p]));
12
+ return perforations
13
+ .filter((p) => p.pairedWith !== undefined)
14
+ .map((p) => [p, byId.get(idOf(p.pairedWith))])
15
+ .filter((pair) => pair[1] !== undefined);
16
+ };
@@ -1,3 +1,4 @@
1
+ import type { Concept } from "./Edition";
1
2
  import { Expression, Note } from "./Symbol";
2
3
  /**
3
4
  * What a tracker bar position does: sound a note, or operate one of
@@ -27,6 +28,12 @@ export type TrackMeaning = NoteMeaning | ExpressionMeaning;
27
28
  * ask the tracker bar rather than repeat the boundaries.
28
29
  */
29
30
  export interface TrackerBar {
31
+ /**
32
+ * Names the reproducing system in the type vocabulary:
33
+ * the system is `https://w3id.org/reo/type/system/<id>` and its
34
+ * expression types live under `https://w3id.org/reo/type/<id>/`.
35
+ */
36
+ readonly id: string;
30
37
  readonly name: string;
31
38
  /** Width of the roll the bar reads, in mm. */
32
39
  readonly width: number;
@@ -34,6 +41,8 @@ export interface TrackerBar {
34
41
  readonly trackCount: number;
35
42
  /** The blocks of positions, from the bass edge upwards. */
36
43
  readonly areas: readonly TrackArea[];
44
+ /** The expression types the bar reads, each a term of the system. */
45
+ readonly expressionTypes: readonly string[];
37
46
  /**
38
47
  * The position carrying the rewind perforation, which runs at
39
48
  * the very end of a roll and is the usual landmark for calibrating
@@ -45,6 +54,15 @@ export interface TrackerBar {
45
54
  /** `undefined` for a position the bar does not read. */
46
55
  roleOf(track: number): TrackRole | undefined;
47
56
  }
57
+ /** The roll system a tracker bar belongs to, as the roll metadata states it. */
58
+ export declare const systemOf: (bar: TrackerBar) => Concept;
59
+ /** The identifier of a system the type vocabulary knows, from its concept. */
60
+ export declare const systemIdOf: (system: Concept | undefined) => string | undefined;
61
+ /**
62
+ * The commands of the Welte-Mignon T-100, as its tracker bar reads them.
63
+ */
64
+ export declare const welteT100ExpressionTypes: readonly ["SustainPedalOn", "SustainPedalOff", "SoftPedalOn", "SoftPedalOff", "MezzoforteOff", "MezzoforteOn", "SlowCrescendoOn", "SlowCrescendoOff", "ForzandoOn", "ForzandoOff", "MotorOff", "MotorOn", "Rewind", "ElectricCutOff"];
65
+ export type WelteT100ExpressionType = typeof welteT100ExpressionTypes[number];
48
66
  /**
49
67
  * Welte-Mignon T-100 ("red Welte"), cf. Hagmann, pp. 75 and 178.
50
68
  *
package/lib/TrackerBar.js CHANGED
@@ -1,3 +1,8 @@
1
+ const SYSTEM_IRI = 'https://w3id.org/reo/type/system/';
2
+ /** The roll system a tracker bar belongs to, as the roll metadata states it. */
3
+ export const systemOf = (bar) => ({ id: SYSTEM_IRI + bar.id, name: bar.name, sameAs: [] });
4
+ /** The identifier of a system the type vocabulary knows, from its concept. */
5
+ export const systemIdOf = (system) => system?.id?.startsWith(SYSTEM_IRI) ? system.id.slice(SYSTEM_IRI.length) : undefined;
1
6
  const areasOf = ({ notes, trackCount }) => [
2
7
  { role: 'bass-expression', from: 1, to: notes.from - 1 },
3
8
  { role: 'note', from: notes.from, to: notes.to },
@@ -28,15 +33,36 @@ const describe = (spec) => {
28
33
  throw new Error(`${spec.name} declares no rewind track`);
29
34
  }
30
35
  return {
36
+ id: spec.id,
31
37
  name: spec.name,
32
38
  width: spec.width,
33
39
  trackCount: spec.trackCount,
34
40
  areas,
41
+ expressionTypes: [...new Set(spec.expressions.values())],
35
42
  rewindTrack,
36
43
  meaningOf,
37
44
  roleOf
38
45
  };
39
46
  };
47
+ /**
48
+ * The commands of the Welte-Mignon T-100, as its tracker bar reads them.
49
+ */
50
+ export const welteT100ExpressionTypes = [
51
+ 'SustainPedalOn',
52
+ 'SustainPedalOff',
53
+ 'SoftPedalOn',
54
+ 'SoftPedalOff',
55
+ 'MezzoforteOff',
56
+ 'MezzoforteOn',
57
+ 'SlowCrescendoOn',
58
+ 'SlowCrescendoOff',
59
+ 'ForzandoOn',
60
+ 'ForzandoOff',
61
+ 'MotorOff',
62
+ 'MotorOn',
63
+ 'Rewind',
64
+ 'ElectricCutOff'
65
+ ];
40
66
  /**
41
67
  * Welte-Mignon T-100 ("red Welte"), cf. Hagmann, pp. 75 and 178.
42
68
  *
@@ -45,6 +71,7 @@ const describe = (spec) => {
45
71
  * treble above it, in mirrored order.
46
72
  */
47
73
  export const welteT100 = describe({
74
+ id: 'welte-t100',
48
75
  name: 'Welte-Mignon T100',
49
76
  width: 328,
50
77
  trackCount: 100,
package/lib/Version.d.ts CHANGED
@@ -11,31 +11,39 @@ export type VersionType = typeof versionTypes[number];
11
11
  /**
12
12
  * A motivation provides a reason or rationale for an editorial change.
13
13
  * Motivations are defined at the version level and referenced by edits.
14
- * @see crm:E73 Information Object
14
+ * @see crm:E33 Linguistic Object
15
15
  */
16
16
  export type Motivation = WithType<'motivation'> & WithId & WithNote;
17
17
  /**
18
18
  * A version is defined by the sum of edits applied
19
19
  * to the version it is based on. For simple identification,
20
20
  * a siglum is given to each version.
21
+ * @see lrmoo:F2 Expression
21
22
  */
22
- export interface Version {
23
- id: string;
23
+ export interface Version extends WithId, WithType<'Version'> {
24
24
  /**
25
25
  * A short siglum to identify the version, e.g. "A", "B1", "B2_rev", etc.
26
+ * @see reo:siglum
26
27
  */
27
28
  siglum: string;
29
+ /**
30
+ * Whether the version served as a master for reproductions
31
+ * or exists on one copy only.
32
+ * @see crm:P2 has type
33
+ */
34
+ versionType: VersionType;
28
35
  /**
29
36
  * If no derivation is defined, it is assumed that this version represents the mother roll.
37
+ * @see lrmoo:R76 is derivative of
30
38
  */
31
39
  basedOn?: ReferenceAssumption;
32
40
  /**
33
41
  * The list of edits that, applied to the base version, produce this version.
42
+ * @see reo:involvedEdit
34
43
  */
35
44
  edits: Edit[];
36
45
  /**
37
46
  * A collection of motivations used in this version's edits.
38
47
  */
39
48
  motivations: Motivation[];
40
- type: VersionType;
41
49
  }
package/lib/asJsonLd.js CHANGED
@@ -1,3 +1,4 @@
1
+ import { systemIdOf } from "./TrackerBar";
1
2
  export const exportDate = (date) => {
2
3
  const year = date.getFullYear();
3
4
  const month = String(date.getMonth() + 1).padStart(2, "0");
@@ -32,13 +33,26 @@ const asJsonLdEntity = (obj) => {
32
33
  result[key] = value;
33
34
  }
34
35
  }
36
+ if ('@value' in obj && obj['@value'] instanceof Date) {
37
+ result['@type'] = 'xsd:date';
38
+ }
35
39
  return result;
36
40
  };
41
+ /**
42
+ * The context of the roll's reproducing system, which reads the
43
+ * expression types as that system's terms.
44
+ */
45
+ const systemContextOf = (edition) => {
46
+ const system = systemIdOf(edition.roll?.system);
47
+ return system ? [`https://w3id.org/reo/${system}/context.jsonld`] : [];
48
+ };
37
49
  export const asJsonLd = (edition) => {
38
- const { base, copies, ...rest } = asJsonLdEntity(edition);
50
+ // The context is the export's own; one carried in from an import must not override it.
51
+ const { base, copies, '@context': carried, ...rest } = asJsonLdEntity(edition);
39
52
  return {
40
53
  '@context': [
41
- 'https://linked-rolls.org/rollo/1.0/edition.jsonld',
54
+ 'https://w3id.org/reo/context.jsonld',
55
+ ...systemContextOf(edition),
42
56
  {
43
57
  '@base': edition.base
44
58
  }
package/lib/context.d.ts CHANGED
@@ -1 +1,3 @@
1
1
  export { default as jsonLdContext } from './spec/context.json';
2
+ /** The context of the Welte-Mignon T-100, added to an edition of a T-100 roll. */
3
+ export { default as welteT100JsonLdContext } from './spec/welte-t100.context.json';
package/lib/context.js CHANGED
@@ -1 +1,3 @@
1
1
  export { default as jsonLdContext } from './spec/context.json';
2
+ /** The context of the Welte-Mignon T-100, added to an edition of a T-100 roll. */
3
+ export { default as welteT100JsonLdContext } from './spec/welte-t100.context.json';
@@ -1,3 +1,4 @@
1
+ import { migrate } from "./migrate";
1
2
  const isDate = (value) => {
2
3
  const datePattern = /^\d{4}-\d{1,2}-\d{1,2}$/;
3
4
  return datePattern.test(value);
@@ -14,7 +15,11 @@ const fromJsonLdEntity = (json) => {
14
15
  return json;
15
16
  }
16
17
  let result = json;
17
- if ('@type' in json) {
18
+ if ('@value' in json) {
19
+ // the datatype of a value object, not a class
20
+ delete result['@type'];
21
+ }
22
+ else if ('@type' in json) {
18
23
  result['type'] = json['@type'];
19
24
  delete result['@type'];
20
25
  }
@@ -49,10 +54,19 @@ const fromJsonLdEntity = (json) => {
49
54
  }
50
55
  return result;
51
56
  };
57
+ // The export prefixes copy identifiers with `copy/`; this is its inverse.
58
+ const withPlainCopyIds = (json) => ({
59
+ ...json,
60
+ copies: (json.copies ?? []).map((copy) => ({
61
+ ...copy,
62
+ '@id': typeof copy['@id'] === 'string' ? copy['@id'].replace(/^copy\//, '') : copy['@id']
63
+ }))
64
+ });
52
65
  export const importJsonLd = (json) => {
53
- const edition = fromJsonLdEntity(json);
54
- if (Array.isArray(json['@context'])) {
55
- edition.base = json['@context'].find((c) => c['@base'])?.['@base'] || '';
56
- }
66
+ const { '@context': context, ...document } = withPlainCopyIds(migrate(json));
67
+ const edition = fromJsonLdEntity(document);
68
+ edition.base = Array.isArray(context)
69
+ ? context.find((c) => c['@base'])?.['@base'] || ''
70
+ : '';
57
71
  return edition;
58
72
  };
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Brings the JSON of an edition written by an earlier release of the
3
+ * format up to the current shape. The shapes are recognised
4
+ * structurally, so a file that is current already passes through
5
+ * unchanged, and a file may be migrated any number of times.
6
+ *
7
+ * Format 0.1 used the type discriminator of versions and conditions
8
+ * for their typology, held the keeper and the production metadata as
9
+ * strings, and named the roll system on each copy. Some 0.1 files
10
+ * also carry references written as values and two keys the format
11
+ * had renamed before.
12
+ */
13
+ type Json = any;
14
+ export declare const migrate: (edition: Json) => Json;
15
+ export {};