linked-rolls 0.74.0 → 0.76.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 +62 -26
- package/lib/collation/Collation.d.ts +12 -42
- package/lib/collation/Collation.js +15 -48
- package/lib/filiation/adoption.d.ts +23 -4
- package/lib/filiation/adoption.js +81 -23
- package/lib/filiation/edits.d.ts +35 -19
- package/lib/filiation/edits.js +68 -34
- package/lib/filiation/index.d.ts +2 -1
- package/lib/filiation/index.js +2 -1
- package/lib/filiation/record.d.ts +49 -0
- package/lib/filiation/record.js +49 -0
- package/lib/index.d.ts +1 -0
- package/lib/index.js +1 -0
- package/lib/io/asJsonLd.js +5 -1
- package/lib/io/importJsonLd.js +42 -4
- package/lib/io/migrate.d.ts +7 -0
- package/lib/io/migrate.js +196 -2
- package/lib/model/Agent.d.ts +3 -1
- package/lib/model/Assumption.d.ts +8 -1
- package/lib/model/Assumption.js +2 -1
- package/lib/model/Edit.d.ts +76 -17
- package/lib/model/Edit.js +52 -3
- package/lib/model/Edition.d.ts +32 -3
- package/lib/model/RollCopy.js +1 -1
- package/lib/model/Version.d.ts +3 -13
- package/lib/model/Version.js +7 -2
- package/lib/ops/collation.d.ts +8 -4
- package/lib/ops/collation.js +40 -23
- package/lib/ops/copies.js +1 -2
- package/lib/ops/draft.d.ts +1 -9
- package/lib/ops/draft.js +0 -12
- package/lib/ops/edits.d.ts +20 -3
- package/lib/ops/edits.js +36 -15
- package/lib/ops/index.d.ts +1 -1
- package/lib/ops/index.js +1 -1
- package/lib/ops/versions.d.ts +3 -2
- package/lib/ops/versions.js +4 -5
- package/lib/schema.json +60 -64
- package/lib/software.d.ts +12 -0
- package/lib/software.js +10 -0
- package/lib/spec/context.json +8 -5
- package/package.json +1 -1
package/lib/io/migrate.js
CHANGED
|
@@ -4,6 +4,7 @@ import { trackerBars } from "../systems/index.js";
|
|
|
4
4
|
import { welteT100 } from "../systems/welteT100/bar.js";
|
|
5
5
|
import { isDateString } from "../shared/utils.js";
|
|
6
6
|
import { mapped, withValues } from "../ops/immutable.js";
|
|
7
|
+
import { musicalChange, technicalChange } from "../model/Edit.js";
|
|
7
8
|
const retiredVersionTypes = new Set(['edition', 'unicum']);
|
|
8
9
|
/**
|
|
9
10
|
* The vocabulary the steps below were written against, as it stood in
|
|
@@ -63,6 +64,37 @@ const renamedEditTypes = {
|
|
|
63
64
|
const withRenamedEditType = (node) => typeof node.editType === 'string' && Object.hasOwn(renamedEditTypes, node.editType)
|
|
64
65
|
? { ...node, editType: renamedEditTypes[node.editType] }
|
|
65
66
|
: node;
|
|
67
|
+
/** The motivation a corrected error is stated with, as `correctedErrorMotivation` was when the kind of edit was retired. */
|
|
68
|
+
const correctedErrorMotivation = {
|
|
69
|
+
'@type': 'motivation',
|
|
70
|
+
'@id': 'corrected-error',
|
|
71
|
+
note: 'Puts right an error of the version it derives from.'
|
|
72
|
+
};
|
|
73
|
+
const isTypedCorrectError = (edit) => edit !== null && typeof edit === 'object' && (edit.editType === 'correct-error' || edit.classification === 'correct-error');
|
|
74
|
+
/**
|
|
75
|
+
* Whether a change corrects an error was once one of the kinds of edit,
|
|
76
|
+
* though it is not read off the shape of a change but is a reason for
|
|
77
|
+
* it. An edit typed so states it as its motivation instead, where it
|
|
78
|
+
* gives none of its own, and the version states what the motivation
|
|
79
|
+
* means; one that gives a motivation of its own keeps that one. Either
|
|
80
|
+
* way it states no kind, its shape being left to be read again. Once
|
|
81
|
+
* motivations are the edition's, a corrected error is a musical change
|
|
82
|
+
* (`withMotivationsOfTheEdition`).
|
|
83
|
+
*/
|
|
84
|
+
const withCorrectedErrorsMotivated = (node) => {
|
|
85
|
+
if (!Array.isArray(node.edits) || !node.edits.some(isTypedCorrectError))
|
|
86
|
+
return node;
|
|
87
|
+
const edits = node.edits.map((edit) => {
|
|
88
|
+
if (!isTypedCorrectError(edit))
|
|
89
|
+
return edit;
|
|
90
|
+
const { editType: _kind, classification: _named, ...rest } = edit;
|
|
91
|
+
return rest.motivation === undefined || rest.motivation === 'unchecked' ? { ...rest, motivation: correctedErrorMotivation['@id'] } : rest;
|
|
92
|
+
});
|
|
93
|
+
const motivations = Array.isArray(node.motivations) ? node.motivations : [];
|
|
94
|
+
const declare = edits.some((edit) => edit?.motivation === correctedErrorMotivation['@id'])
|
|
95
|
+
&& !motivations.some(motivation => motivation?.['@id'] === correctedErrorMotivation['@id']);
|
|
96
|
+
return { ...node, edits, ...(declare && { motivations: [...motivations, correctedErrorMotivation] }) };
|
|
97
|
+
};
|
|
66
98
|
const withRenamedType = (node) => Object.hasOwn(renamedTypes, node['@type']) ? { ...node, '@type': renamedTypes[node['@type']] } : node;
|
|
67
99
|
/** Whether the feature is of the class under either name, since a node is migrated before its children are. */
|
|
68
100
|
const isOfType = (type) => (feature) => feature?.['@type'] === type || renamedTypes[feature?.['@type']] === type;
|
|
@@ -503,7 +535,7 @@ const withMeasuredByInReasons = (node) => {
|
|
|
503
535
|
}
|
|
504
536
|
};
|
|
505
537
|
};
|
|
506
|
-
const nodeSteps = [withRenamedKeys, withRenamedEditType, withTypology, withRenamedType, withoutVersionType, withoutVersionSiglum, withLowerCaseTerms, withSplitMethod, withReferences, withKeeper, withoutEmptyKeeper,
|
|
538
|
+
const nodeSteps = [withRenamedKeys, withRenamedEditType, withCorrectedErrorsMotivated, withTypology, withRenamedType, withoutVersionType, withoutVersionSiglum, withLowerCaseTerms, withSplitMethod, withReferences, withKeeper, withoutEmptyKeeper,
|
|
507
539
|
withPerforator, withProductionNodes, withTypedPerforator, withScale, withoutOps, withDerivationList, withReadingKind, withTimeSpanDates,
|
|
508
540
|
withoutFeatureKind, withBorneFeaturesNamed, withFeaturesInActs, withOwnPlaces, withDriveOfStaggering, withoutPattern, withoutBearings, withoutEntailedType,
|
|
509
541
|
withMeasuredByInReasons];
|
|
@@ -677,6 +709,168 @@ const withReferenceCopy = (edition) => {
|
|
|
677
709
|
: edition;
|
|
678
710
|
};
|
|
679
711
|
const editionSteps = [withoutFormatVersion, withoutTempoAdjustment, withoutEditionType, withSystems, withEditors, withDerivationTolerance, withReferenceCopy];
|
|
712
|
+
/**
|
|
713
|
+
* The motivation an edit of a version that derives from another is left
|
|
714
|
+
* with where only the edition can tell what kind of change it is: one
|
|
715
|
+
* that states neither a kind nor a reason, as a collation once left
|
|
716
|
+
* them. `importJsonLd` reads its kind off its shape (`proposedMotivations`).
|
|
717
|
+
*/
|
|
718
|
+
export const uncheckedMotivation = 'unchecked';
|
|
719
|
+
/** The kinds of edit, as they were stated once, whose shape is a musical decision. */
|
|
720
|
+
const musicalEditTypes = new Set(['additional-accent', 'shift', 'shorten', 'prolong']);
|
|
721
|
+
/** The kinds of edit, as they were stated once, whose shape is a technical change. */
|
|
722
|
+
const technicalEditTypes = new Set(['recoding', 'remove-redundancy', 'add-redundancy']);
|
|
723
|
+
const isRecord = (value) => value !== null && typeof value === 'object' && !Array.isArray(value);
|
|
724
|
+
/** Whether the version derives from another, so that its edits are changes rather than its text. */
|
|
725
|
+
const derives = (version) => Array.isArray(version?.basedOn) ? version.basedOn.length > 0 : version?.basedOn !== undefined;
|
|
726
|
+
/**
|
|
727
|
+
* The motivation an edit states once motivations say what kind of
|
|
728
|
+
* change it is, from the kind it was given and the reason it gave.
|
|
729
|
+
*/
|
|
730
|
+
const motivationOfEdit = (editType, motivation, derived) => {
|
|
731
|
+
// A corrected error put back a perforation in its place, and so made a musical change.
|
|
732
|
+
const stated = motivation === 'corrected-error' ? musicalChange : motivation;
|
|
733
|
+
if (!derived)
|
|
734
|
+
return stated === uncheckedMotivation || stated === musicalChange ? undefined : stated;
|
|
735
|
+
const technical = typeof editType === 'string' && technicalEditTypes.has(editType);
|
|
736
|
+
// A reason given for a technical change explained what the change or the procedure says already.
|
|
737
|
+
if (technical)
|
|
738
|
+
return technicalChange;
|
|
739
|
+
if (stated === undefined || stated === uncheckedMotivation) {
|
|
740
|
+
return typeof editType === 'string' && musicalEditTypes.has(editType) ? musicalChange : uncheckedMotivation;
|
|
741
|
+
}
|
|
742
|
+
return stated;
|
|
743
|
+
};
|
|
744
|
+
/** Whether the document still states what motivations and kinds of edit were before 0.76. */
|
|
745
|
+
const statesMotivationsPerVersion = (versions) => versions.some(version => Array.isArray(version?.motivations)
|
|
746
|
+
|| (Array.isArray(version?.edits) && version.edits.some((edit) => isRecord(edit) && (Object.hasOwn(edit, 'editType') || edit.motivation === 'corrected-error'))));
|
|
747
|
+
/**
|
|
748
|
+
* Before 0.76 each version stated the motivations its edits named, and
|
|
749
|
+
* an edit stated its kind beside its reason. The motivations are the
|
|
750
|
+
* edition's now, once each, and the motivation alone says what kind of
|
|
751
|
+
* change an edit is (`kindOfChange`):
|
|
752
|
+
*
|
|
753
|
+
* - A motivation two versions stated under one id with different notes
|
|
754
|
+
* is kept under an id of its own for the second.
|
|
755
|
+
* - The unchecked motivation goes, and so does the declaration of a
|
|
756
|
+
* corrected error: it put a perforation back in its place, and so is
|
|
757
|
+
* a musical change whose reason is not given.
|
|
758
|
+
* - An edit of a version that derives from another, that gave no reason
|
|
759
|
+
* or only that it was unchecked, is a musical change whose reason is
|
|
760
|
+
* not given where its kind was an added accent, a shift, a shortening
|
|
761
|
+
* or a prolongation, and a technical change where it was a recoding or
|
|
762
|
+
* a redundancy removed or added. One that stated no kind is left
|
|
763
|
+
* unchecked, for an import to read its kind off its shape.
|
|
764
|
+
* - A reason given for a recoding or a redundancy goes, since a
|
|
765
|
+
* technical change needs none, and a motivation nothing names any
|
|
766
|
+
* longer goes with it. Every other reason stays, and makes the change
|
|
767
|
+
* a musical one.
|
|
768
|
+
* - The edits of a version that derives from none state its text and
|
|
769
|
+
* keep no motivation but a reason someone gave.
|
|
770
|
+
*/
|
|
771
|
+
const withMotivationsOfTheEdition = (edition) => {
|
|
772
|
+
const versions = listAt(edition, 'versions');
|
|
773
|
+
if (!versions || !statesMotivationsPerVersion(versions))
|
|
774
|
+
return edition;
|
|
775
|
+
const notes = new Map((listAt(edition, 'motivations') ?? []).filter(isRecord).map(motivation => [motivation['@id'], motivation]));
|
|
776
|
+
const referencedBefore = new Set();
|
|
777
|
+
const migrated = versions.map((version, index) => {
|
|
778
|
+
if (!isRecord(version))
|
|
779
|
+
return version;
|
|
780
|
+
const renamed = new Map();
|
|
781
|
+
for (const motivation of Array.isArray(version.motivations) ? version.motivations.filter(isRecord) : []) {
|
|
782
|
+
const id = motivation['@id'];
|
|
783
|
+
if (typeof id !== 'string' || id === uncheckedMotivation || id === 'corrected-error')
|
|
784
|
+
continue;
|
|
785
|
+
const known = notes.get(id);
|
|
786
|
+
if (!known)
|
|
787
|
+
notes.set(id, motivation);
|
|
788
|
+
else if (known.note !== motivation.note) {
|
|
789
|
+
const own = `${id}-${index}`;
|
|
790
|
+
renamed.set(id, own);
|
|
791
|
+
notes.set(own, { ...motivation, '@id': own });
|
|
792
|
+
}
|
|
793
|
+
}
|
|
794
|
+
const derived = derives(version);
|
|
795
|
+
const { motivations: _declared, ...rest } = version;
|
|
796
|
+
if (!Array.isArray(version.edits))
|
|
797
|
+
return rest;
|
|
798
|
+
return {
|
|
799
|
+
...rest,
|
|
800
|
+
edits: version.edits.map((edit) => {
|
|
801
|
+
if (!isRecord(edit))
|
|
802
|
+
return edit;
|
|
803
|
+
const { editType, motivation: given, ...stated } = edit;
|
|
804
|
+
const named = typeof given === 'string' ? renamed.get(given) ?? given : given;
|
|
805
|
+
if (typeof named === 'string')
|
|
806
|
+
referencedBefore.add(named);
|
|
807
|
+
const motivation = motivationOfEdit(editType, named, derived);
|
|
808
|
+
return motivation === undefined ? stated : { ...stated, motivation };
|
|
809
|
+
})
|
|
810
|
+
};
|
|
811
|
+
});
|
|
812
|
+
const referenced = new Set(migrated.flatMap((version) => (Array.isArray(version?.edits) ? version.edits : []).map((edit) => edit?.motivation).filter((id) => typeof id === 'string')));
|
|
813
|
+
const motivations = [...notes.values()].filter(motivation => referenced.has(motivation['@id']) || !referencedBefore.has(motivation['@id']));
|
|
814
|
+
const { motivations: _stated, ...rest } = edition;
|
|
815
|
+
return { ...rest, versions: migrated, ...(motivations.length > 0 && { motivations }) };
|
|
816
|
+
};
|
|
817
|
+
/**
|
|
818
|
+
* Before 0.76 an adopted proposal was recorded as a proposition set: each
|
|
819
|
+
* statement of it named the set in its annotation, and the set held them
|
|
820
|
+
* under one belief whose inference named the release that found them and
|
|
821
|
+
* the rules it followed. The edition states what a program concluded
|
|
822
|
+
* plainly now, and its creation names the rules among its principles and
|
|
823
|
+
* the release among its software. A statement of a set the edition held
|
|
824
|
+
* below likely keeps the doubt, under a belief of its own that is the
|
|
825
|
+
* set's.
|
|
826
|
+
*/
|
|
827
|
+
const withoutPropositionSets = (edition) => {
|
|
828
|
+
const sets = listAt(edition, 'propositionSets');
|
|
829
|
+
if (!sets)
|
|
830
|
+
return edition;
|
|
831
|
+
const beliefOf = new Map(sets.filter(isRecord).map(set => [set['@id'], set.belief]));
|
|
832
|
+
const inferences = sets.filter(isRecord).flatMap(set => Array.isArray(set.belief?.reasons) ? set.belief.reasons : []);
|
|
833
|
+
const rules = inferences.flatMap(inference => Array.isArray(inference?.applies) ? inference.applies : []);
|
|
834
|
+
const programs = inferences.flatMap(inference => Array.isArray(inference?.software) ? inference.software : []);
|
|
835
|
+
let held = 0;
|
|
836
|
+
const unset = (value) => {
|
|
837
|
+
if (Array.isArray(value))
|
|
838
|
+
return mapped(value, unset);
|
|
839
|
+
if (!isRecord(value))
|
|
840
|
+
return value;
|
|
841
|
+
const annotation = value['@annotation'];
|
|
842
|
+
const set = isRecord(annotation) && typeof annotation['@id'] === 'string' ? beliefOf.get(annotation['@id']) : undefined;
|
|
843
|
+
if (!set || (isRecord(annotation.belief) && Object.keys(annotation.belief).some(key => key !== '@id')))
|
|
844
|
+
return withValues(value, unset);
|
|
845
|
+
const { '@annotation': _member, ...rest } = value;
|
|
846
|
+
if (set.certainty === 'true' || set.certainty === 'likely')
|
|
847
|
+
return withValues(rest, unset);
|
|
848
|
+
held += 1;
|
|
849
|
+
return withValues({
|
|
850
|
+
...rest,
|
|
851
|
+
'@annotation': { '@id': `${annotation['@id']}/${held}`, belief: { ...set, '@id': `${set['@id']}/${held}` } }
|
|
852
|
+
}, unset);
|
|
853
|
+
};
|
|
854
|
+
const { propositionSets: _recorded, ...rest } = edition;
|
|
855
|
+
const unsetted = unset(rest);
|
|
856
|
+
const creation = isRecord(unsetted.creation) ? unsetted.creation : undefined;
|
|
857
|
+
if (!creation)
|
|
858
|
+
return unsetted;
|
|
859
|
+
const principles = [...new Set([...(Array.isArray(creation.principles) ? creation.principles : []), ...rules])];
|
|
860
|
+
const known = Array.isArray(creation.software) ? creation.software : [];
|
|
861
|
+
const software = [...known, ...programs.filter((program, index) => !known.some((other) => other?.name === program?.name && other?.version === program?.version)
|
|
862
|
+
&& programs.findIndex(other => other?.name === program?.name && other?.version === program?.version) === index)];
|
|
863
|
+
return {
|
|
864
|
+
...unsetted,
|
|
865
|
+
creation: {
|
|
866
|
+
...creation,
|
|
867
|
+
...(principles.length > 0 && { principles }),
|
|
868
|
+
...(software.length > 0 && { software })
|
|
869
|
+
}
|
|
870
|
+
};
|
|
871
|
+
};
|
|
872
|
+
/** Steps that read the document as the node steps leave it, an old document's kinds of edit renamed. */
|
|
873
|
+
const finalSteps = [withoutPropositionSets, withMotivationsOfTheEdition];
|
|
680
874
|
/**
|
|
681
875
|
* Brings the JSON of an edition written by an earlier release of the
|
|
682
876
|
* format up to the current shape. A document that is current already
|
|
@@ -685,4 +879,4 @@ const editionSteps = [withoutFormatVersion, withoutTempoAdjustment, withoutEditi
|
|
|
685
879
|
* to look at an old document as JSON.
|
|
686
880
|
* @category Reading and writing
|
|
687
881
|
*/
|
|
688
|
-
export const migrate = (edition) => walk(editionSteps.reduce((result, step) => step(result), edition));
|
|
882
|
+
export const migrate = (edition) => finalSteps.reduce((result, step) => step(result), walk(editionSteps.reduce((result, step) => step(result), edition)));
|
package/lib/model/Agent.d.ts
CHANGED
|
@@ -107,7 +107,9 @@ export type Concept = (WithId & Partial<Named>) | (Named & Partial<WithId>);
|
|
|
107
107
|
/**
|
|
108
108
|
* Software that captured a copy or measured it: the transcriber that
|
|
109
109
|
* read a recording into notes, the emulator that wrote a MIDI file, the
|
|
110
|
-
* program that found the holes on a scan or aligned two copies.
|
|
110
|
+
* program that found the holes on a scan or aligned two copies. Or the
|
|
111
|
+
* software an edition was made with, such as the release of this
|
|
112
|
+
* library that found its stemma.
|
|
111
113
|
* @see crmdig:D14 Software
|
|
112
114
|
* @category Format types
|
|
113
115
|
*/
|
|
@@ -21,7 +21,8 @@ export type Certainty = typeof certainties[number];
|
|
|
21
21
|
*/
|
|
22
22
|
export declare const isAsserted: (certainty: Certainty) => boolean;
|
|
23
23
|
/**
|
|
24
|
-
* The certainty a statement is held with. One that carries no belief is
|
|
24
|
+
* The certainty a statement is held with. One that carries no belief is
|
|
25
|
+
* stated plainly, and so held true.
|
|
25
26
|
* @category Assumptions and beliefs
|
|
26
27
|
*/
|
|
27
28
|
export declare const certaintyOf: (assumption: Readonly<Assumption>) => Certainty;
|
|
@@ -202,6 +203,12 @@ export interface Assumption {
|
|
|
202
203
|
* An optional annotation expressing a belief about this assumption.
|
|
203
204
|
* Uses the JSON-LD-star `@annotation` mechanism to attach
|
|
204
205
|
* epistemic metadata (certainty and reasons) to any triple.
|
|
206
|
+
*
|
|
207
|
+
* A statement that carries none is stated plainly, and what a
|
|
208
|
+
* program concluded is stated so too: an edition asserts its stemma
|
|
209
|
+
* and its edits, as a printed edition does, and its creation names
|
|
210
|
+
* the principles and the release they were found by
|
|
211
|
+
* (`EditionCreation`). A belief is kept for what the editor doubts.
|
|
205
212
|
*/
|
|
206
213
|
'@annotation'?: WithId & {
|
|
207
214
|
/**
|
package/lib/model/Assumption.js
CHANGED
|
@@ -19,7 +19,8 @@ export const certainties = [
|
|
|
19
19
|
*/
|
|
20
20
|
export const isAsserted = (certainty) => certainty === 'true' || certainty === 'likely';
|
|
21
21
|
/**
|
|
22
|
-
* The certainty a statement is held with. One that carries no belief is
|
|
22
|
+
* The certainty a statement is held with. One that carries no belief is
|
|
23
|
+
* stated plainly, and so held true.
|
|
23
24
|
* @category Assumptions and beliefs
|
|
24
25
|
*/
|
|
25
26
|
export const certaintyOf = (assumption) => assumption['@annotation']?.belief.certainty ?? 'true';
|
package/lib/model/Edit.d.ts
CHANGED
|
@@ -1,30 +1,92 @@
|
|
|
1
1
|
import { Assumption } from "./Assumption.js";
|
|
2
2
|
import { AnySymbol } from "./Symbol.js";
|
|
3
|
-
import { WithId } from "../shared/utils.js";
|
|
3
|
+
import { WithId, WithNote, WithType } from "../shared/utils.js";
|
|
4
4
|
/**
|
|
5
|
-
*
|
|
5
|
+
* A reason for a musical change, in the editor's words. The edition
|
|
6
|
+
* states its motivations once (`Edition.motivations`), and an edit of
|
|
7
|
+
* any version names the one it was made for. Every change of a version
|
|
8
|
+
* that derives from another states a motivation: a program states
|
|
9
|
+
* whether it is musical or technical (`musicalChange`,
|
|
10
|
+
* `technicalChange`), and the editor puts a reason of their own in
|
|
11
|
+
* place of a musical one. Speculating about why a change was made is
|
|
12
|
+
* kept to the musical changes.
|
|
13
|
+
* @see crm:E33 Linguistic Object
|
|
14
|
+
* @category Format types
|
|
15
|
+
*/
|
|
16
|
+
export type Motivation = WithType<'motivation'> & WithId & WithNote;
|
|
17
|
+
/**
|
|
18
|
+
* The motivation of a musical change whose reason is not given yet: a
|
|
19
|
+
* change of the performance, such as an added accent or a perforation
|
|
20
|
+
* put elsewhere. A program states it for a change whose shape a musical
|
|
21
|
+
* decision makes, under the rule that later versions are the more
|
|
22
|
+
* refined; the editor puts a reason of their own in its place.
|
|
23
|
+
* @category Versions and stemma
|
|
24
|
+
*/
|
|
25
|
+
export declare const musicalChange = "https://w3id.org/reo/type/motivation/musical";
|
|
26
|
+
/**
|
|
27
|
+
* The motivation of a technical change: one that changes only how the
|
|
28
|
+
* performance is carried, a redundancy cleaned up or added, or a
|
|
29
|
+
* command recoded for another reproducing system. A program states it
|
|
30
|
+
* for a change of such a shape, and the procedure of the version's
|
|
31
|
+
* creation explains it, so that no reason of its own is given.
|
|
32
|
+
* @category Versions and stemma
|
|
33
|
+
*/
|
|
34
|
+
export declare const technicalChange = "https://w3id.org/reo/type/motivation/technical";
|
|
35
|
+
/**
|
|
36
|
+
* The kinds of change an edit can be: one that changes the
|
|
37
|
+
* performance, and one that changes only how it is carried.
|
|
6
38
|
* @category Vocabulary
|
|
7
39
|
*/
|
|
8
|
-
export declare const
|
|
40
|
+
export declare const changeKinds: readonly ['musical', 'technical'];
|
|
41
|
+
/**
|
|
42
|
+
* The kind of change an edit is (`kindOfChange`).
|
|
43
|
+
* @category Format types
|
|
44
|
+
*/
|
|
45
|
+
export type ChangeKind = typeof changeKinds[number];
|
|
46
|
+
/**
|
|
47
|
+
* What kind of change the edit is, as its motivation says: technical
|
|
48
|
+
* if it is `technicalChange`, musical if it is `musicalChange` or a
|
|
49
|
+
* reason of the editor's.
|
|
50
|
+
*
|
|
51
|
+
* An edit without a motivation is of no kind: the edits of a version
|
|
52
|
+
* that derives from none state its text rather than a change.
|
|
53
|
+
* @category Versions and stemma
|
|
54
|
+
*/
|
|
55
|
+
export declare const kindOfChange: (edit: Readonly<Pick<Edit, 'motivation'>>) => ChangeKind | undefined;
|
|
56
|
+
/**
|
|
57
|
+
* The shapes a change can take, read off what it inserts and deletes
|
|
58
|
+
* and the systems of the two versions (`shapeOf`, `proposeEdits`). A
|
|
59
|
+
* shape is not stated: it is what a program reads to propose a
|
|
60
|
+
* motivation, and what a view can call a change.
|
|
61
|
+
* @category Vocabulary
|
|
62
|
+
*/
|
|
63
|
+
export declare const editShapes: readonly ['additional-accent', 'add-redundancy', 'remove-redundancy',
|
|
9
64
|
/**
|
|
10
65
|
* Carries the text into another reproducing system's coding: a
|
|
11
66
|
* latched pair of one system giving way to the other's held command,
|
|
12
67
|
* a command the other system cannot read struck, or one of its own
|
|
13
68
|
* put in where the first had no word for it.
|
|
14
69
|
*/
|
|
15
|
-
'recoding', 'shift', '
|
|
70
|
+
'recoding', 'shift', 'shorten', 'prolong'];
|
|
16
71
|
/**
|
|
17
|
-
* The
|
|
18
|
-
* Classifies the nature of the edit, e.g. whether it corrects an error,
|
|
19
|
-
* adds an accent, shifts a note, or shortens/prolongs a perforation.
|
|
72
|
+
* The shape of a change (`editShapes`).
|
|
20
73
|
* @category Format types
|
|
21
74
|
*/
|
|
22
|
-
export type
|
|
75
|
+
export type EditShape = typeof editShapes[number];
|
|
76
|
+
/**
|
|
77
|
+
* The motivation a program states for a change of this shape. A
|
|
78
|
+
* recoding and a redundancy removed or added are technical changes
|
|
79
|
+
* (`technicalChange`). Every other change of a later version is taken
|
|
80
|
+
* for a refinement, and so for a musical change whose reason is not
|
|
81
|
+
* given yet (`musicalChange`).
|
|
82
|
+
* @category Versions and stemma
|
|
83
|
+
*/
|
|
84
|
+
export declare const motivationProposedFor: (shape: EditShape | undefined) => string;
|
|
23
85
|
/**
|
|
24
86
|
* A set of edits transforms a version of a roll into another version.
|
|
25
87
|
* Edits insert or delete symbols, or both (= replace).
|
|
26
|
-
*
|
|
27
|
-
*
|
|
88
|
+
* What kind of change an edit is follows from its motivation
|
|
89
|
+
* (`kindOfChange`).
|
|
28
90
|
* If an edit is the interpretation of a metamark,
|
|
29
91
|
* such as a pencil mark, this should be made explicit
|
|
30
92
|
* using a meaning comprehension on the `@annotation` field.
|
|
@@ -38,13 +100,10 @@ export type EditType = typeof editTypes[number];
|
|
|
38
100
|
export interface Edit extends WithId, Assumption {
|
|
39
101
|
type: 'edit';
|
|
40
102
|
/**
|
|
41
|
-
*
|
|
42
|
-
*
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
/**
|
|
46
|
-
* A textual description of the motivation for this edit,
|
|
47
|
-
* referencing a motivation defined in the version's motivations list.
|
|
103
|
+
* Why the edit was made: one of the edition's motivations, by id,
|
|
104
|
+
* or one the vocabulary publishes, by IRI (`musicalChange`,
|
|
105
|
+
* `technicalChange`). An edit of a version that derives from none
|
|
106
|
+
* states none.
|
|
48
107
|
* @see crm:P17 was motivated by
|
|
49
108
|
*/
|
|
50
109
|
motivation?: string;
|
package/lib/model/Edit.js
CHANGED
|
@@ -1,8 +1,47 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* The
|
|
2
|
+
* The motivation of a musical change whose reason is not given yet: a
|
|
3
|
+
* change of the performance, such as an added accent or a perforation
|
|
4
|
+
* put elsewhere. A program states it for a change whose shape a musical
|
|
5
|
+
* decision makes, under the rule that later versions are the more
|
|
6
|
+
* refined; the editor puts a reason of their own in its place.
|
|
7
|
+
* @category Versions and stemma
|
|
8
|
+
*/
|
|
9
|
+
export const musicalChange = 'https://w3id.org/reo/type/motivation/musical';
|
|
10
|
+
/**
|
|
11
|
+
* The motivation of a technical change: one that changes only how the
|
|
12
|
+
* performance is carried, a redundancy cleaned up or added, or a
|
|
13
|
+
* command recoded for another reproducing system. A program states it
|
|
14
|
+
* for a change of such a shape, and the procedure of the version's
|
|
15
|
+
* creation explains it, so that no reason of its own is given.
|
|
16
|
+
* @category Versions and stemma
|
|
17
|
+
*/
|
|
18
|
+
export const technicalChange = 'https://w3id.org/reo/type/motivation/technical';
|
|
19
|
+
/**
|
|
20
|
+
* The kinds of change an edit can be: one that changes the
|
|
21
|
+
* performance, and one that changes only how it is carried.
|
|
3
22
|
* @category Vocabulary
|
|
4
23
|
*/
|
|
5
|
-
export const
|
|
24
|
+
export const changeKinds = ['musical', 'technical'];
|
|
25
|
+
/**
|
|
26
|
+
* What kind of change the edit is, as its motivation says: technical
|
|
27
|
+
* if it is `technicalChange`, musical if it is `musicalChange` or a
|
|
28
|
+
* reason of the editor's.
|
|
29
|
+
*
|
|
30
|
+
* An edit without a motivation is of no kind: the edits of a version
|
|
31
|
+
* that derives from none state its text rather than a change.
|
|
32
|
+
* @category Versions and stemma
|
|
33
|
+
*/
|
|
34
|
+
export const kindOfChange = (edit) => edit.motivation === undefined
|
|
35
|
+
? undefined
|
|
36
|
+
: edit.motivation === technicalChange ? 'technical' : 'musical';
|
|
37
|
+
/**
|
|
38
|
+
* The shapes a change can take, read off what it inserts and deletes
|
|
39
|
+
* and the systems of the two versions (`shapeOf`, `proposeEdits`). A
|
|
40
|
+
* shape is not stated: it is what a program reads to propose a
|
|
41
|
+
* motivation, and what a view can call a change.
|
|
42
|
+
* @category Vocabulary
|
|
43
|
+
*/
|
|
44
|
+
export const editShapes = [
|
|
6
45
|
'additional-accent',
|
|
7
46
|
'add-redundancy',
|
|
8
47
|
'remove-redundancy',
|
|
@@ -14,10 +53,20 @@ export const editTypes = [
|
|
|
14
53
|
*/
|
|
15
54
|
'recoding',
|
|
16
55
|
'shift',
|
|
17
|
-
'correct-error',
|
|
18
56
|
'shorten',
|
|
19
57
|
'prolong',
|
|
20
58
|
];
|
|
59
|
+
/**
|
|
60
|
+
* The motivation a program states for a change of this shape. A
|
|
61
|
+
* recoding and a redundancy removed or added are technical changes
|
|
62
|
+
* (`technicalChange`). Every other change of a later version is taken
|
|
63
|
+
* for a refinement, and so for a musical change whose reason is not
|
|
64
|
+
* given yet (`musicalChange`).
|
|
65
|
+
* @category Versions and stemma
|
|
66
|
+
*/
|
|
67
|
+
export const motivationProposedFor = (shape) => shape === 'recoding' || shape === 'remove-redundancy' || shape === 'add-redundancy'
|
|
68
|
+
? technicalChange
|
|
69
|
+
: musicalChange;
|
|
21
70
|
/**
|
|
22
71
|
* Whether the object is an edit.
|
|
23
72
|
* @category Lookups
|
package/lib/model/Edition.d.ts
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import { RollCopy } from "./RollCopy.js";
|
|
2
2
|
import { Version } from "./Version.js";
|
|
3
|
+
import { Motivation } from "./Edit.js";
|
|
3
4
|
import { DateAssignment } from "./Assumption.js";
|
|
4
|
-
import { Editor, Person, Place } from "./Agent.js";
|
|
5
|
+
import { Editor, Person, Place, Software } from "./Agent.js";
|
|
5
6
|
/**
|
|
6
|
-
* This type describes the creation of an edition,
|
|
7
|
-
*
|
|
7
|
+
* This type describes the creation of an edition: the editors,
|
|
8
|
+
* publisher and publication date, the editorial principles the edition
|
|
9
|
+
* follows, and the programs it was made with.
|
|
8
10
|
* @see lrmoo:F28 Expression Creation
|
|
9
11
|
* @category Format types
|
|
10
12
|
*/
|
|
@@ -28,6 +30,25 @@ export interface EditionCreation {
|
|
|
28
30
|
* @see dcterms:date
|
|
29
31
|
*/
|
|
30
32
|
publicationDate: Date;
|
|
33
|
+
/**
|
|
34
|
+
* The editorial principles the edition follows, by IRI: the
|
|
35
|
+
* published rules its stemma and its edits rest on, whether the
|
|
36
|
+
* editor applied them or a program did, such as that the same
|
|
37
|
+
* addition at the same place is not made twice independently
|
|
38
|
+
* (`stemmaRules`, `editRules`). Adopting a proposal names those it
|
|
39
|
+
* follows. An edition that names none leaves it out.
|
|
40
|
+
* @see crm:P33 used specific technique
|
|
41
|
+
*/
|
|
42
|
+
principles?: string[];
|
|
43
|
+
/**
|
|
44
|
+
* The programs the edition was made with, each with its release:
|
|
45
|
+
* the release of this library that found its stemma and grouped its
|
|
46
|
+
* edits, which finds them again with the defaults it has. Adopting a
|
|
47
|
+
* proposal names it, and saving the edition does not, so that the
|
|
48
|
+
* release named is the one that found what the edition states.
|
|
49
|
+
* @see crm:P16 used specific object
|
|
50
|
+
*/
|
|
51
|
+
software?: Software[];
|
|
31
52
|
}
|
|
32
53
|
/**
|
|
33
54
|
* Describes the event of recording and documents
|
|
@@ -159,6 +180,14 @@ export interface Edition {
|
|
|
159
180
|
* @see lrmoo:R75 incorporates
|
|
160
181
|
*/
|
|
161
182
|
versions: Version[];
|
|
183
|
+
/**
|
|
184
|
+
* The editor's motivations, each a reason for musical changes in
|
|
185
|
+
* words, stated once and named by the edits of any version
|
|
186
|
+
* (`Edit.motivation`). The motivations the vocabulary publishes are
|
|
187
|
+
* named by IRI and not stated here (`musicalChange`,
|
|
188
|
+
* `technicalChange`).
|
|
189
|
+
*/
|
|
190
|
+
motivations?: Motivation[];
|
|
162
191
|
}
|
|
163
192
|
/**
|
|
164
193
|
* What an edition states about itself rather than about the copies and
|
package/lib/model/RollCopy.js
CHANGED
|
@@ -65,7 +65,7 @@ const exportedMeasurementsOf = (copy) => [copy.measurements.dimensions, copy.mea
|
|
|
65
65
|
*/
|
|
66
66
|
export const measuringSoftwareOf = (copy) => {
|
|
67
67
|
const named = exportedMeasurementsOf(copy)
|
|
68
|
-
.flatMap(value => value['@annotation']?.belief
|
|
68
|
+
.flatMap(value => value['@annotation']?.belief?.reasons ?? [])
|
|
69
69
|
.flatMap(reason => reason.type === 'measurement' ? reason.software ?? [] : []);
|
|
70
70
|
return [...new Map(named.map(software => [`${software.name}\u0000${software.version ?? ''}`, software])).values()];
|
|
71
71
|
};
|
package/lib/model/Version.d.ts
CHANGED
|
@@ -3,14 +3,7 @@ import { Concept } from "./Agent.js";
|
|
|
3
3
|
import { ActorAssignment, Belief, Certainty, DateAssignment, ObjectAssumption, ReferenceAssumption } from "./Assumption.js";
|
|
4
4
|
import { CollationTolerance } from "../collation/Collation.js";
|
|
5
5
|
import { AnySymbol } from "./Symbol.js";
|
|
6
|
-
import { WithId
|
|
7
|
-
/**
|
|
8
|
-
* A motivation provides a reason or rationale for an editorial change.
|
|
9
|
-
* Motivations are defined at the version level and referenced by edits.
|
|
10
|
-
* @see crm:E33 Linguistic Object
|
|
11
|
-
* @category Format types
|
|
12
|
-
*/
|
|
13
|
-
export type Motivation = WithType<'motivation'> & WithId & WithNote;
|
|
6
|
+
import { WithId } from "../shared/utils.js";
|
|
14
7
|
/**
|
|
15
8
|
* A derivation names the version another one was derived from, together
|
|
16
9
|
* with the tolerance the two were collated at. How precisely the copies
|
|
@@ -148,10 +141,6 @@ export interface Version extends WithId {
|
|
|
148
141
|
* @see reo:involvedEdit
|
|
149
142
|
*/
|
|
150
143
|
edits?: Edit[];
|
|
151
|
-
/**
|
|
152
|
-
* A collection of motivations used in this version's edits.
|
|
153
|
-
*/
|
|
154
|
-
motivations: Motivation[];
|
|
155
144
|
}
|
|
156
145
|
/**
|
|
157
146
|
* The edits the version states, none where it leaves its text unstated.
|
|
@@ -170,7 +159,8 @@ export declare const insertedBy: (version: Readonly<Version>) => AnySymbol[];
|
|
|
170
159
|
export declare const deletedBy: (version: Readonly<Version>) => string[];
|
|
171
160
|
/**
|
|
172
161
|
* The parents the version names, in the order of `basedOn`, each with the
|
|
173
|
-
* certainty its derivation is held with and the belief it rests on
|
|
162
|
+
* certainty its derivation is held with and the belief it rests on, where
|
|
163
|
+
* it carries one.
|
|
174
164
|
* @category Versions and stemma
|
|
175
165
|
*/
|
|
176
166
|
export declare const derivationsOf: (version: Readonly<Version>) => {
|
package/lib/model/Version.js
CHANGED
|
@@ -22,12 +22,17 @@ export const insertedBy = (version) => editsOf(version).flatMap(edit => edit.ins
|
|
|
22
22
|
export const deletedBy = (version) => editsOf(version).flatMap(edit => edit.delete ?? []);
|
|
23
23
|
/**
|
|
24
24
|
* The parents the version names, in the order of `basedOn`, each with the
|
|
25
|
-
* certainty its derivation is held with and the belief it rests on
|
|
25
|
+
* certainty its derivation is held with and the belief it rests on, where
|
|
26
|
+
* it carries one.
|
|
26
27
|
* @category Versions and stemma
|
|
27
28
|
*/
|
|
28
29
|
export const derivationsOf = (version) => (version.basedOn ?? []).map(derivation => {
|
|
29
30
|
const belief = derivation['@annotation']?.belief;
|
|
30
|
-
return {
|
|
31
|
+
return {
|
|
32
|
+
parent: idOf(derivation),
|
|
33
|
+
certainty: belief?.certainty ?? 'true',
|
|
34
|
+
...(belief && { belief })
|
|
35
|
+
};
|
|
31
36
|
});
|
|
32
37
|
const rankOf = (derivation) => certainties.indexOf(certaintyOf(derivation));
|
|
33
38
|
/**
|
package/lib/ops/collation.d.ts
CHANGED
|
@@ -9,15 +9,18 @@ import { EditionOp } from "./draft.js";
|
|
|
9
9
|
* tolerance it was collated at and becomes the principal one; the
|
|
10
10
|
* hypotheses the child stated beside its former one stay.
|
|
11
11
|
*
|
|
12
|
-
* The edits the child already stated are rewritten only as far as
|
|
13
|
-
*
|
|
12
|
+
* The edits the child already stated are rewritten only as far as they
|
|
13
|
+
* are the program's (`isCollationsOwn`). An editor's reading of the
|
|
14
14
|
* difference between the two texts stays, and the symbols it speaks for
|
|
15
15
|
* are left out of the collation, so that connecting the two again
|
|
16
16
|
* neither doubles them nor silently drops what somebody established by
|
|
17
17
|
* hand. An equivalence is the collation's own, since it is drawn from
|
|
18
18
|
* the two systems' vocabularies rather than read off the paper, but one
|
|
19
19
|
* drawn again over the very same symbols is kept as it stands, with its
|
|
20
|
-
* identifier and whatever was written on it.
|
|
20
|
+
* identifier and whatever was written on it. An insertion or deletion
|
|
21
|
+
* drawn anew has the motivation its shape calls for
|
|
22
|
+
* (`motivationProposedFor`): the generic musical one, or the technical
|
|
23
|
+
* one, which an equivalence drawn anew always has.
|
|
21
24
|
*
|
|
22
25
|
* The child's own text is what it shows less what the parent hands
|
|
23
26
|
* down, so that connecting two versions already connected collates the
|
|
@@ -40,7 +43,8 @@ export declare const collateSymbols: (versionId: string, symbolIds: readonly str
|
|
|
40
43
|
* Takes the named copies' reading of a symbol back out of the symbol it
|
|
41
44
|
* was collated into: their carriers pass to a new symbol of the
|
|
42
45
|
* version's own, the remaining copies keep the symbol they had, and the
|
|
43
|
-
* version states the exchange
|
|
46
|
+
* version states the exchange, with the motivation its shape calls for
|
|
47
|
+
* (`motivationProposedFor`) where the version derives from another.
|
|
44
48
|
*
|
|
45
49
|
* This is the inverse of the hand-over a collation makes, and it is
|
|
46
50
|
* what lets a derivation be collated a second time. A collated symbol
|