linked-rolls 0.55.0 → 0.57.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/editionOps.js CHANGED
@@ -10,7 +10,7 @@ import { substitutionsBetween } from "./substitution.js";
10
10
  import { trackerBarOf } from "./systems/index.js";
11
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 => {
@@ -90,7 +90,6 @@ export const createVersion = (copy) => draft => {
90
90
  const bar = barOf(copy);
91
91
  draft.copies.push(copy);
92
92
  draft.versions.push({
93
- type: 'Version',
94
93
  id: v4(),
95
94
  system: systemOf(bar),
96
95
  edits: asSymbols(featuresOf(copy), bar).map(insertion),
@@ -369,7 +368,7 @@ const goneWith = (features, named) => features.flatMap(feature => named.has(feat
369
368
  : goneWith(featuresBorneBy(feature), named));
370
369
  /** The feature with the named ones gone from what it bears, or the very same one where it bears none of them. */
371
370
  const withoutBorne = (feature, named) => {
372
- if (!isGluedOn(feature) || !feature.features)
371
+ if (!isPatch(feature) || !feature.features)
373
372
  return feature;
374
373
  const borne = withoutFeatures(feature.features, named);
375
374
  return borne === feature.features ? feature : { ...feature, features: borne };
@@ -443,7 +442,7 @@ const actFor = (copy, patch, act) => {
443
442
  * the feature goes into an act of its own.
444
443
  */
445
444
  export const addFeature = (copyId, feature, act = {}) => onCopy(copyId, copy => {
446
- actFor(copy, isGluedOn(feature), act).push(feature);
445
+ actFor(copy, isPatch(feature), act).push(feature);
447
446
  });
448
447
  /**
449
448
  * States that the patch bears the feature. What a patch bears came onto
@@ -452,7 +451,7 @@ export const addFeature = (copyId, feature, act = {}) => onCopy(copyId, copy =>
452
451
  */
453
452
  export const addBorneFeature = (copyId, patchId, feature) => onCopy(copyId, copy => {
454
453
  const patch = featuresOf(copy).flatMap(withBorneFeatures).find(borne => borne.id === patchId);
455
- if (!patch || !isGluedOn(patch))
454
+ if (!patch || !isPatch(patch))
456
455
  return;
457
456
  if (!patch.features)
458
457
  patch.features = [];
@@ -502,7 +501,7 @@ const sayTheSame = (a, b) => {
502
501
  */
503
502
  const nature = (feature) => {
504
503
  const { id, horizontal, depiction, condition, ...rest } = feature;
505
- return isGluedOn(feature) && feature.features
504
+ return isPatch(feature) && feature.features
506
505
  ? { ...rest, features: feature.features.map(borne => borne.id) }
507
506
  : rest;
508
507
  };
@@ -707,7 +706,7 @@ const byExchange = (edits) => new Map(edits.map(edit => [exchangeKey((edit.inser
707
706
  * child's symbols and not the parent's with themselves.
708
707
  */
709
708
  export const connectVersions = (view, childId, parentId, tolerance = defaultCollationTolerance) => {
710
- const child = view.get(childId);
709
+ const child = view.version(childId);
711
710
  const stated = child ? editsOf(child) : [];
712
711
  const established = stated.filter(edit => !isCollationsOwn(edit));
713
712
  const spokenFor = spokenForBy(established);
@@ -732,7 +731,7 @@ export const connectVersions = (view, childId, parentId, tolerance = defaultColl
732
731
  * apart would make the apparatus a list of unexplained losses beside
733
732
  * a list of unexplained gains.
734
733
  */
735
- const substituted = differ(child, view.get(parentId))
734
+ const substituted = differ(child, view.version(parentId))
736
735
  ? substitutionsBetween(own.filter(symbol => !collated.has(symbol.id)), inherited.filter(symbol => !matched.has(symbol.id)), locate, tolerance)
737
736
  : [];
738
737
  const paired = new Set(substituted.flatMap(({ replaced, by }) => [...by, ...replaced].map(symbol => symbol.id)));
@@ -773,7 +772,7 @@ export const connectVersions = (view, childId, parentId, tolerance = defaultColl
773
772
  * tolerance of the derivation, where the caller names none.
774
773
  */
775
774
  export const collateSymbols = (view, versionId, symbolIds, tolerance) => {
776
- const version = view.get(versionId);
775
+ const version = view.version(versionId);
777
776
  const principal = version && principalDerivationOf(version);
778
777
  if (!version || !principal)
779
778
  return noChange;
@@ -843,7 +842,7 @@ const sharedWith = (view, symbol, copies) => {
843
842
  * narrow the act to those; naming none separates the whole reading.
844
843
  */
845
844
  export const separateReadings = (view, versionId, copies, symbolIds) => {
846
- const version = view.get(versionId);
845
+ const version = view.version(versionId);
847
846
  if (!version)
848
847
  return noChange;
849
848
  const chosen = symbolIds && new Set(symbolIds);
@@ -911,7 +910,6 @@ export const deriveVersion = (versionId, editIds) => onVersion(versionId, (versi
911
910
  if (version.edits)
912
911
  version.edits = without(version.edits, edit => chosen.has(edit.id));
913
912
  draft.versions.push({
914
- type: 'Version',
915
913
  id: v4(),
916
914
  system: stateOf(version).system,
917
915
  basedOn: [assignReference(versionId)],
@@ -970,10 +968,10 @@ const replacementType = (view, inserted, deleted) => {
970
968
  */
971
969
  const guessEditType = (view, versionId, edit) => {
972
970
  const inserts = edit.insert ?? [];
973
- const deletes = view.getAll(edit.delete ?? []);
971
+ const deletes = view.symbols(edit.delete ?? []);
974
972
  const inserted = expressionTypesOf(inserts);
975
973
  const deleted = expressionTypesOf(deletes);
976
- const bar = trackerBarOf(view.get(versionId)?.system);
974
+ const bar = trackerBarOf(view.version(versionId)?.system);
977
975
  const parentBar = trackerBarOf(view.predecessorOf(versionId)?.system);
978
976
  /**
979
977
  * Where the version is coded for another system than its parent, an
@@ -18,12 +18,7 @@ const fromJsonLdValue = (value) => {
18
18
  return fromJsonLdEntity(value);
19
19
  return value;
20
20
  };
21
- /**
22
- * A node without what the export derived from it. A copy bears the
23
- * features its acts brought about, and the graph has to be told so.
24
- * In the edition the act that made a feature is the one place it
25
- * stands.
26
- */
21
+ /** A node without what the export derived from it: what an act changed follows from where the act stands. */
27
22
  const asStated = (json) => Object.keys(json).some(key => derivedKeys.has(key))
28
23
  ? Object.fromEntries(Object.entries(json).filter(([key]) => !derivedKeys.has(key)))
29
24
  : json;
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,8 +41,9 @@ const withTypology = (node) => {
33
41
  }
34
42
  return node;
35
43
  };
36
- /** A chain of holes written while its class was named after a single hole. */
37
- const withHoleChainType = (node) => node['@type'] === 'Hole' ? { ...node, '@type': 'HoleChain' } : node;
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;
38
47
  /** A version once stated whether it served as a master or stood on one copy. */
39
48
  const withoutVersionType = (node) => {
40
49
  if (!Object.hasOwn(node, 'versionType'))
@@ -147,7 +156,6 @@ const withPerforator = (node) => {
147
156
  perforator: {
148
157
  ...perforator,
149
158
  condition: {
150
- '@type': 'ConditionState',
151
159
  conditionType: 'setting',
152
160
  ...perforator.condition,
153
161
  punchDiameter: diameter
@@ -187,6 +195,22 @@ const withoutPattern = (node) => {
187
195
  const { pattern: _moved, ...rest } = node;
188
196
  return rest;
189
197
  };
198
+ /** A version and a condition state once stated their class, which the key they stand under entails. */
199
+ const withoutEntailedType = (node) => {
200
+ if (node['@type'] !== 'Version' && node['@type'] !== 'ConditionState')
201
+ return node;
202
+ const { '@type': _entailed, ...rest } = node;
203
+ return rest;
204
+ };
205
+ /** An export once stated what a copy or a patch bears, which a reasoner now derives from the acts. */
206
+ const withoutBearings = (node) => {
207
+ if (!Object.hasOwn(node, 'bears') && !Object.hasOwn(node, 'composedOf'))
208
+ return node;
209
+ if (node['@type'] !== 'RollCopy' && node['@type'] !== 'Patch')
210
+ return node;
211
+ const { bears: _bears, composedOf: _composedOf, ...rest } = node;
212
+ return rest;
213
+ };
190
214
  /** A derivation written as a single one, before a version could name several. */
191
215
  const isSingleDerivation = (basedOn) => basedOn !== null && typeof basedOn === 'object' && !Array.isArray(basedOn);
192
216
  const withDerivationList = (node) => isSingleDerivation(node.basedOn) ? { ...node, basedOn: [node.basedOn] } : node;
@@ -195,8 +219,7 @@ const featuresOf = (copy) => [
195
219
  ...(Array.isArray(copy.features) ? copy.features : []),
196
220
  ...(Array.isArray(copy.production?.produced) ? copy.production.produced : [])
197
221
  ];
198
- /** A chain of holes under either name, since a node is migrated before its children are. */
199
- const isHoleChain = (feature) => feature?.['@type'] === 'HoleChain' || feature?.['@type'] === 'Hole';
222
+ const isHoleChain = isOfType('HoleChain');
200
223
  /**
201
224
  * A copy read on a roll reader was stated as a recording before a sound
202
225
  * recording could be one. A sound recording gives no holes, so a recording
@@ -212,7 +235,7 @@ const withoutFeatureKind = (node) => {
212
235
  const { kind: _typed, ...rest } = node;
213
236
  return rest;
214
237
  };
215
- const isPatch = (feature) => feature?.['@type'] === 'GluedOn';
238
+ const isPatch = isOfType('Patch');
216
239
  /**
217
240
  * A feature a patch bears was sometimes written without an id, and what
218
241
  * has no id can be referred to from nowhere: neither by a reading of it
@@ -303,9 +326,9 @@ const withTimeSpanDates = (node) => {
303
326
  const { '@value': within, '@type': _typed, ...rest } = node;
304
327
  return { ...rest, within };
305
328
  };
306
- const migrateNode = (node) => [withRenamedKeys, withTypology, withHoleChainType, withoutVersionType, withoutVersionSiglum, withLowerCaseTerms, withSplitMethod, withReferences, withKeeper, withoutEmptyKeeper,
329
+ const migrateNode = (node) => [withRenamedKeys, withTypology, withRenamedType, withoutVersionType, withoutVersionSiglum, withLowerCaseTerms, withSplitMethod, withReferences, withKeeper, withoutEmptyKeeper,
307
330
  withPerforator, withProductionNodes, withTypedPerforator, withScale, withDerivationList, withReadingKind, withTimeSpanDates,
308
- withoutFeatureKind, withBorneFeaturesNamed, withFeaturesInActs, withDriveOfStaggering, withoutPattern]
331
+ withoutFeatureKind, withBorneFeaturesNamed, withFeaturesInActs, withDriveOfStaggering, withoutPattern, withoutBearings, withoutEntailedType]
309
332
  .reduce((result, step) => step(result), node);
310
333
  /** The items each walked, or the very same list where the walk changed none. */
311
334
  const walked = (items) => {
@@ -382,6 +405,13 @@ const onOwnBar = (copy, rollSystem) => {
382
405
  * roll that named no system was a T-100 roll, and the text a copy's
383
406
  * production gave for it is kept as the system's name.
384
407
  */
408
+ /** An export once stated the class of the edition, which R17i was created by entails. */
409
+ const withoutEditionType = (edition) => {
410
+ if (edition['@type'] !== 'Edition')
411
+ return edition;
412
+ const { '@type': _entailed, ...rest } = edition;
413
+ return rest;
414
+ };
385
415
  const withSystems = (edition) => {
386
416
  if (!edition.roll || !namesSystemOnTheRoll(edition))
387
417
  return edition;
@@ -453,14 +483,16 @@ const referenceOf = (statement) => {
453
483
  }
454
484
  };
455
485
  };
456
- /** The document with each quoted reference back on the node that makes it, a node being what has a type. */
486
+ /** Whether the object states anything beside its id, which a reference to a node does not. */
487
+ const isNode = (value) => typeof value['@id'] === 'string' && Object.keys(value).some(key => key !== '@id' && key !== '@annotation');
488
+ /** The document with each quoted reference back on the node that makes it. */
457
489
  const withReferencesOn = (value, bySubject) => {
458
490
  if (Array.isArray(value))
459
491
  return value.map(item => withReferencesOn(item, bySubject));
460
492
  if (!value || typeof value !== 'object')
461
493
  return value;
462
494
  const walked = Object.fromEntries(Object.entries(value).map(([key, child]) => [key, withReferencesOn(child, bySubject)]));
463
- const references = typeof value['@id'] === 'string' && value['@type'] !== undefined
495
+ const references = isNode(value)
464
496
  ? bySubject.get(value['@id']) ?? []
465
497
  : [];
466
498
  return references.reduce((node, { key, listed, reference }) => ({ ...node, [key]: listed ? [...(node[key] ?? []), reference] : reference }), walked);
@@ -482,5 +514,5 @@ const withQuotedStatementsInPlace = (edition) => {
482
514
  const bySubject = Map.groupBy(statements.map(referenceOf), ({ subject }) => subject);
483
515
  return withReferencesOn({ ...rest, ...(others.length > 0 && { '@included': others }) }, bySubject);
484
516
  };
485
- const editionSteps = [withQuotedStatementsInPlace, withSystems, withEditors, withDerivationTolerance];
517
+ const editionSteps = [withoutEditionType, withQuotedStatementsInPlace, withSystems, withEditors, withDerivationTolerance];
486
518
  export const migrate = (edition) => walk(editionSteps.reduce((result, step) => step(result), edition));
@@ -164,7 +164,6 @@ export function readFromStanfordAton(atonString, { trackShift, system = welteT10
164
164
  type: 'Perforator',
165
165
  id: `perforator_${v4()}`,
166
166
  condition: {
167
- type: 'ConditionState',
168
167
  conditionType: 'setting',
169
168
  punchDiameter: { value: punchDiameter, unit: 'mm' }
170
169
  }
package/lib/scatter.js CHANGED
@@ -37,7 +37,7 @@ const sitsOn = (view, copies) => (feature) => {
37
37
  export const readingsOf = (view, symbols, copies) => {
38
38
  const tested = sitsOn(view, copies);
39
39
  return symbols.flatMap((symbol) => {
40
- const carriers = view.carriersOf(symbol);
40
+ const carriers = view.placedCarriersOf(symbol);
41
41
  const here = carriers.filter(tested);
42
42
  const there = carriers.filter(carrier => !tested(carrier));
43
43
  if (here.length === 0 || there.length === 0)
@@ -220,12 +220,12 @@ const copiesBearing = (view, symbols) => {
220
220
  * stopped saying and an editor has to.
221
221
  */
222
222
  export const sidesOf = (view, versionId) => {
223
- const version = view.get(versionId);
223
+ const version = view.version(versionId);
224
224
  if (!version)
225
225
  return undefined;
226
226
  return {
227
227
  child: copiesBearing(view, insertedBy(version)),
228
- parent: copiesBearing(view, view.getAll(deletedBy(version)))
228
+ parent: copiesBearing(view, view.symbols(deletedBy(version)))
229
229
  };
230
230
  };
231
231
  const inMillimetres = (value) => `${value.toFixed(2)} mm`;