linked-rolls 0.62.0 → 0.64.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 +26 -7
- package/lib/analysis/constraints.d.ts +2 -2
- package/lib/analysis/constraints.js +30 -21
- package/lib/analysis/ownPaper.d.ts +11 -16
- package/lib/analysis/ownPaper.js +13 -31
- package/lib/analysis/paper.d.ts +129 -0
- package/lib/analysis/paper.js +260 -0
- package/lib/analysis/reservations.d.ts +2 -2
- package/lib/analysis/reservations.js +6 -6
- package/lib/analysis/sigla.d.ts +4 -5
- package/lib/analysis/sigla.js +4 -4
- package/lib/analysis/stemma.d.ts +22 -0
- package/lib/analysis/stemma.js +38 -0
- package/lib/analysis/text.d.ts +31 -0
- package/lib/analysis/text.js +62 -0
- package/lib/analysis/witnesses.d.ts +5 -5
- package/lib/analysis/witnesses.js +22 -20
- package/lib/collation/alignment.d.ts +46 -8
- package/lib/collation/alignment.js +137 -47
- package/lib/collation/scatter.d.ts +4 -4
- package/lib/collation/scatter.js +15 -13
- package/lib/emulation/Emulation.d.ts +7 -7
- package/lib/emulation/Emulation.js +29 -27
- package/lib/emulation/negotiation.d.ts +2 -2
- package/lib/emulation/negotiation.js +3 -2
- package/lib/index.d.ts +6 -2
- package/lib/index.js +6 -2
- package/lib/io/asJsonLd.js +16 -1
- package/lib/io/importJsonLd.d.ts +5 -0
- package/lib/io/importJsonLd.js +18 -1
- package/lib/io/migrate.js +94 -2
- package/lib/lookup/lookup.d.ts +32 -0
- package/lib/lookup/lookup.js +40 -0
- package/lib/lookup/paths.d.ts +11 -0
- package/lib/lookup/paths.js +78 -0
- package/lib/lookup/perState.d.ts +32 -0
- package/lib/lookup/perState.js +63 -0
- package/lib/model/Assumption.d.ts +21 -9
- package/lib/model/Edit.d.ts +4 -0
- package/lib/model/Edition.d.ts +19 -0
- package/lib/model/Edition.js +9 -1
- package/lib/model/Quantity.d.ts +4 -1
- package/lib/model/Quantity.js +1 -0
- package/lib/model/RollCopy.d.ts +144 -48
- package/lib/model/RollCopy.js +9 -6
- package/lib/model/Version.d.ts +7 -1
- package/lib/ops/beliefs.d.ts +1 -1
- package/lib/ops/beliefs.js +1 -1
- package/lib/ops/collation.d.ts +3 -4
- package/lib/ops/collation.js +25 -23
- package/lib/ops/commands.d.ts +4 -5
- package/lib/ops/commands.js +10 -10
- package/lib/ops/copies.d.ts +47 -10
- package/lib/ops/copies.js +92 -26
- package/lib/ops/draft.d.ts +12 -12
- package/lib/ops/draft.js +11 -13
- package/lib/ops/edits.d.ts +1 -2
- package/lib/ops/edits.js +13 -10
- package/lib/ops/features.d.ts +2 -2
- package/lib/ops/features.js +3 -2
- package/lib/ops/index.d.ts +2 -2
- package/lib/ops/index.js +7 -1
- package/lib/ops/versions.d.ts +2 -3
- package/lib/ops/versions.js +6 -5
- package/lib/readers/stanfordAton.js +28 -1
- package/lib/schema.json +185 -26
- package/lib/spec/context.json +33 -1
- package/lib/systems/ReproducingSystem.d.ts +7 -6
- package/package.json +1 -1
- package/lib/view/EditionView.d.ts +0 -103
- package/lib/view/EditionView.js +0 -329
package/lib/ops/copies.js
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import { v4 } from "uuid";
|
|
2
|
+
import { referenceCopyOf } from "../model/Edition.js";
|
|
2
3
|
import { asSymbols, barOf, featuresOf, isPaperStretch } from "../model/RollCopy.js";
|
|
3
4
|
import { systemOf } from "../systems/TrackerBar.js";
|
|
4
|
-
import {
|
|
5
|
+
import { alignFeatures, ALIGNMENT_METHOD, applyAlignment, ownFeaturesOf, revertAlignment, revertShortening, shortenChains } from "../collation/alignment.js";
|
|
5
6
|
import { idOf } from "../model/Assumption.js";
|
|
7
|
+
import { track } from "../model/Quantity.js";
|
|
6
8
|
import { onCopy, stateOf, insertion, insertedIn, referenceHeld, withoutReferences } from "./draft.js";
|
|
7
9
|
import { without } from "./immutable.js";
|
|
8
10
|
import { featureIdsOf, carriedOnlyOn, forgetFeatures } from "./forget.js";
|
|
@@ -30,36 +32,80 @@ export const createVersion = (copy) => draft => {
|
|
|
30
32
|
export const addCopy = (copy) => draft => {
|
|
31
33
|
draft.copies.push(copy);
|
|
32
34
|
};
|
|
33
|
-
/**
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
35
|
+
/**
|
|
36
|
+
* What aligning the copy with the reference copy finds, or nothing
|
|
37
|
+
* where the two share no run of notes, where there is no reference
|
|
38
|
+
* copy, or where the copy is the reference itself. The copy is read at
|
|
39
|
+
* its own places whatever alignment it has, and through its own bar,
|
|
40
|
+
* which is what lets a copy cut for another system be aligned at all.
|
|
41
|
+
*/
|
|
42
|
+
export const alignmentFor = (edition, copy, date = new Date()) => {
|
|
43
|
+
const reference = referenceCopyOf(edition);
|
|
44
|
+
if (!reference || reference.id === copy.id)
|
|
45
|
+
return undefined;
|
|
46
|
+
const found = alignFeatures(ownFeaturesOf(copy), featuresOf(reference), barOf(copy), barOf(reference));
|
|
47
|
+
if (!found)
|
|
48
|
+
return undefined;
|
|
49
|
+
return {
|
|
50
|
+
against: reference.id,
|
|
51
|
+
shift: { horizontal: found.shift, vertical: track(0) },
|
|
52
|
+
scale: found.scale,
|
|
53
|
+
matched: found.matched,
|
|
54
|
+
residual: found.residual,
|
|
55
|
+
scaleError: found.scaleError,
|
|
56
|
+
foundBy: { ...ALIGNMENT_METHOD, date }
|
|
57
|
+
};
|
|
58
|
+
};
|
|
59
|
+
/**
|
|
60
|
+
* Aligns the copy with the edition's reference copy: finds the shift
|
|
61
|
+
* and scale that carry its notes onto the reference copy's, and puts
|
|
62
|
+
* its features and tears onto the axis by them, in place of any
|
|
63
|
+
* alignment it had. A copy that shares no run of notes with the
|
|
64
|
+
* reference copy is left as it was.
|
|
65
|
+
*/
|
|
66
|
+
export const alignCopy = (copyId, date = new Date()) => draft => {
|
|
67
|
+
const state = stateOf(draft);
|
|
68
|
+
const copy = state.copies.find(c => c.id === copyId);
|
|
69
|
+
const alignment = copy && alignmentFor(state, copy, date);
|
|
70
|
+
const target = draft.copies.find(c => c.id === copyId);
|
|
71
|
+
if (alignment && target)
|
|
72
|
+
applyAlignment(alignment, target);
|
|
73
|
+
};
|
|
74
|
+
/**
|
|
75
|
+
* Aligns every copy that has features with the reference copy, as
|
|
76
|
+
* `alignCopy` does one. The reference copy itself is taken off any
|
|
77
|
+
* alignment it had, its places being the axis.
|
|
78
|
+
*/
|
|
79
|
+
export const alignCopies = (date = new Date()) => draft => {
|
|
80
|
+
const reference = referenceCopyOf(stateOf(draft));
|
|
81
|
+
if (!reference)
|
|
37
82
|
return;
|
|
38
|
-
|
|
39
|
-
if (
|
|
40
|
-
|
|
41
|
-
|
|
83
|
+
const own = draft.copies.find(c => c.id === reference.id);
|
|
84
|
+
if (own)
|
|
85
|
+
revertAlignment(own);
|
|
86
|
+
stateOf(draft).copies
|
|
87
|
+
.filter(copy => copy.id !== reference.id && featuresOf(copy).length > 0)
|
|
88
|
+
.forEach(copy => alignCopy(copy.id, date)(draft));
|
|
42
89
|
};
|
|
43
90
|
/**
|
|
44
|
-
*
|
|
45
|
-
*
|
|
46
|
-
*
|
|
91
|
+
* Makes the copy the one whose millimetres are the edition's axis, and
|
|
92
|
+
* aligns every other copy onto it. Every place the edition gives along
|
|
93
|
+
* the roll moves with this, which is why it is a choice and not
|
|
94
|
+
* something worked out.
|
|
47
95
|
*/
|
|
48
|
-
export const
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
}
|
|
96
|
+
export const chooseReferenceCopy = (copyId, date = new Date()) => draft => {
|
|
97
|
+
if (!draft.copies.some(copy => copy.id === copyId))
|
|
98
|
+
return;
|
|
99
|
+
draft.referenceCopy = copyId;
|
|
100
|
+
alignCopies(date)(draft);
|
|
101
|
+
};
|
|
54
102
|
/**
|
|
55
|
-
* Puts the copy's features back where they were measured
|
|
56
|
-
*
|
|
57
|
-
*
|
|
103
|
+
* Puts the copy's features back where they were measured, off the
|
|
104
|
+
* axis. What the alignments say about the paper goes with it, since
|
|
105
|
+
* that is worked out from them.
|
|
58
106
|
*/
|
|
59
107
|
export const unalignCopy = (copyId) => onCopy(copyId, copy => {
|
|
60
|
-
|
|
61
|
-
revertShift(copy);
|
|
62
|
-
copy.conditions = without(copy.conditions, isPaperStretch);
|
|
108
|
+
revertAlignment(copy);
|
|
63
109
|
});
|
|
64
110
|
/**
|
|
65
111
|
* Takes the extension a pneumatic reader adds off the ends of the
|
|
@@ -113,12 +159,30 @@ export const stateCarriage = (copyId, versionId, belief) => onCopy(copyId, copy
|
|
|
113
159
|
export const clearCarriage = (copyId, versionId) => onCopy(copyId, copy => dropStatements(copy, statement => idOf(statement) === versionId));
|
|
114
160
|
/**
|
|
115
161
|
* Adds a general condition to the copy, beside whatever is stated of it
|
|
116
|
-
* already.
|
|
117
|
-
*
|
|
162
|
+
* already. A paper stretch is added the same way, where one was
|
|
163
|
+
* measured; what the alignments say of the paper is worked out from
|
|
164
|
+
* them and stated nowhere.
|
|
118
165
|
*/
|
|
119
166
|
export const addGeneralCondition = (copyId, condition) => onCopy(copyId, copy => {
|
|
120
167
|
copy.conditions.push(condition);
|
|
121
168
|
});
|
|
169
|
+
/**
|
|
170
|
+
* States what the copy's paper was measured to have done, in place of
|
|
171
|
+
* what was stated before; given nothing, it takes the statement away. A
|
|
172
|
+
* copy has one paper, so it has one such condition, which may give a
|
|
173
|
+
* strain in either direction.
|
|
174
|
+
*/
|
|
175
|
+
export const statePaperStretch = (copyId, stretch) => onCopy(copyId, copy => {
|
|
176
|
+
copy.conditions = [...without(copy.conditions, isPaperStretch), ...(stretch ? [stretch] : [])];
|
|
177
|
+
});
|
|
178
|
+
/**
|
|
179
|
+
* Adds a tear to the copy, beside whatever is stated of it already. The
|
|
180
|
+
* tear is given on the axis, where the copy's features stand, and moves
|
|
181
|
+
* with them from then on.
|
|
182
|
+
*/
|
|
183
|
+
export const addTear = (copyId, tear) => onCopy(copyId, copy => {
|
|
184
|
+
copy.conditions.push(tear);
|
|
185
|
+
});
|
|
122
186
|
/** The symbols of the versions that no other copy carries. */
|
|
123
187
|
export const symbolsCarriedOnlyBy = (edition, copyId) => {
|
|
124
188
|
const copy = edition.copies.find(c => c.id === copyId);
|
|
@@ -132,4 +196,6 @@ export const symbolsCarriedOnlyBy = (edition, copyId) => {
|
|
|
132
196
|
export const removeCopy = (copyId) => onCopy(copyId, (copy, draft) => {
|
|
133
197
|
forgetFeatures(draft, featureIdsOf(copy));
|
|
134
198
|
draft.copies = draft.copies.filter(c => c.id !== copyId);
|
|
199
|
+
if (draft.referenceCopy === copyId)
|
|
200
|
+
delete draft.referenceCopy;
|
|
135
201
|
});
|
package/lib/ops/draft.d.ts
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { EditionView } from "../view/EditionView.js";
|
|
2
1
|
/** What the operations are built from: the type of an operation, how one finds what it writes to on the draft, and the edits it writes. */
|
|
3
2
|
import { Draft } from "immer";
|
|
4
3
|
import { Edition } from "../model/Edition.js";
|
|
@@ -12,10 +11,10 @@ import { WithId } from "../shared/utils.js";
|
|
|
12
11
|
/**
|
|
13
12
|
* A change to an edition, written onto an immer draft of it. One
|
|
14
13
|
* operation is one undo step, so an operation that has to read the
|
|
15
|
-
* edition
|
|
16
|
-
*
|
|
17
|
-
* Where operations run one after another on one draft,
|
|
18
|
-
*
|
|
14
|
+
* edition reads it as the draft stands when the operation is applied
|
|
15
|
+
* (`reading`) and does all its writing in the one function it builds
|
|
16
|
+
* from that. Where operations run one after another on one draft, each
|
|
17
|
+
* reads what the ones before it wrote.
|
|
19
18
|
*/
|
|
20
19
|
export type EditionOp = (draft: Draft<Edition>) => void;
|
|
21
20
|
export declare const noChange: EditionOp;
|
|
@@ -23,16 +22,17 @@ export declare const onCopy: (copyId: string, op: (copy: Draft<RollCopy>, draft:
|
|
|
23
22
|
export declare const onVersion: (versionId: string, op: (version: Draft<Version>, draft: Draft<Edition>) => void) => EditionOp;
|
|
24
23
|
export declare const onFeature: (copyId: string, featureId: string, op: (feature: Draft<FeatureOrPatch>) => void) => EditionOp;
|
|
25
24
|
/**
|
|
26
|
-
* The operation built from
|
|
27
|
-
*
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
*
|
|
25
|
+
* The operation built from the state it is applied to: the draft as it
|
|
26
|
+
* stands, an operation run before on the same draft included. A path
|
|
27
|
+
* or an index read off an earlier state would name what stood there
|
|
28
|
+
* before. What is worked out from a state is kept with it, so a draft
|
|
29
|
+
* nothing has changed yet is read from what is known already.
|
|
31
30
|
*/
|
|
32
|
-
export declare const reading: (
|
|
31
|
+
export declare const reading: (build: (edition: Edition) => EditionOp) => EditionOp;
|
|
33
32
|
/**
|
|
34
33
|
* The state a draft stands at, as plain data. Reading a draft proxies
|
|
35
|
-
* everything it touches, so what is only read is read from this
|
|
34
|
+
* everything it touches, so what is only read is read from this, and
|
|
35
|
+
* what is looked up in an edition is looked up in this (`takenOf`).
|
|
36
36
|
*/
|
|
37
37
|
export declare const stateOf: <T>(draft: Draft<T>) => T;
|
|
38
38
|
/** The ids of the items the rewriting left out. */
|
package/lib/ops/draft.js
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import { EditionView } from "../view/EditionView.js";
|
|
2
1
|
/** What the operations are built from: the type of an operation, how one finds what it writes to on the draft, and the edits it writes. */
|
|
3
|
-
import {
|
|
2
|
+
import { isDraft } from "immer";
|
|
4
3
|
import { v4 } from "uuid";
|
|
5
4
|
import { unchecked, uncheckedMotivation } from "../collation/Collation.js";
|
|
6
5
|
import { insertedBy } from "../model/Version.js";
|
|
7
6
|
import { featuresOf } from "../model/RollCopy.js";
|
|
8
7
|
import { assignReference } from "../model/Assumption.js";
|
|
9
8
|
import { without, pruned } from "./immutable.js";
|
|
9
|
+
import { takenOf } from "../lookup/perState.js";
|
|
10
10
|
export const noChange = () => undefined;
|
|
11
11
|
export const onCopy = (copyId, op) => draft => {
|
|
12
12
|
const copy = draft.copies.find(c => c.id === copyId);
|
|
@@ -24,21 +24,19 @@ export const onFeature = (copyId, featureId, op) => onCopy(copyId, copy => {
|
|
|
24
24
|
op(feature);
|
|
25
25
|
});
|
|
26
26
|
/**
|
|
27
|
-
* The operation built from
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
*
|
|
31
|
-
*
|
|
27
|
+
* The operation built from the state it is applied to: the draft as it
|
|
28
|
+
* stands, an operation run before on the same draft included. A path
|
|
29
|
+
* or an index read off an earlier state would name what stood there
|
|
30
|
+
* before. What is worked out from a state is kept with it, so a draft
|
|
31
|
+
* nothing has changed yet is read from what is known already.
|
|
32
32
|
*/
|
|
33
|
-
export const reading = (
|
|
34
|
-
const state = stateOf(draft);
|
|
35
|
-
build(state === view.edition ? view : new EditionView(state))(draft);
|
|
36
|
-
};
|
|
33
|
+
export const reading = (build) => draft => build(stateOf(draft))(draft);
|
|
37
34
|
/**
|
|
38
35
|
* The state a draft stands at, as plain data. Reading a draft proxies
|
|
39
|
-
* everything it touches, so what is only read is read from this
|
|
36
|
+
* everything it touches, so what is only read is read from this, and
|
|
37
|
+
* what is looked up in an edition is looked up in this (`takenOf`).
|
|
40
38
|
*/
|
|
41
|
-
export const stateOf = (draft) => isDraft(draft) ?
|
|
39
|
+
export const stateOf = (draft) => isDraft(draft) ? takenOf(draft) : draft;
|
|
42
40
|
/** The ids of the items the rewriting left out. */
|
|
43
41
|
export const droppedIds = (before, after) => {
|
|
44
42
|
const kept = new Set(after.map(item => item.id));
|
package/lib/ops/edits.d.ts
CHANGED
|
@@ -1,10 +1,9 @@
|
|
|
1
|
-
import { EditionView } from "../view/EditionView.js";
|
|
2
1
|
import { Edit } from "../model/Edit.js";
|
|
3
2
|
import { EditionOp } from "./draft.js";
|
|
4
3
|
/**
|
|
5
4
|
* Replaces the edits with a single one carrying all their insertions
|
|
6
5
|
* and deletions, classified by a guess at what the exchange does.
|
|
7
6
|
*/
|
|
8
|
-
export declare const mergeEdits: (
|
|
7
|
+
export declare const mergeEdits: (versionId: string, toMerge: readonly Edit[]) => EditionOp;
|
|
9
8
|
/** Replaces the edit with one edit per inserted and one per deleted symbol. */
|
|
10
9
|
export declare const splitEdit: (versionId: string, toSplit: Edit) => EditionOp;
|
package/lib/ops/edits.js
CHANGED
|
@@ -4,6 +4,9 @@ import { editsOf } from "../model/Version.js";
|
|
|
4
4
|
import { trackerBarOf } from "../systems/index.js";
|
|
5
5
|
import { distance, mm, subtract } from "../model/Quantity.js";
|
|
6
6
|
import { noChange, onVersion, insertion, deletion, reading } from "./draft.js";
|
|
7
|
+
import { predecessorOf } from "../analysis/stemma.js";
|
|
8
|
+
import { placeOf } from "../analysis/text.js";
|
|
9
|
+
import { symbolsIn, versionIn } from "../lookup/lookup.js";
|
|
7
10
|
const sameSequence = (a, b) => a.length === b.length && a.every((value, i) => value === b[i]);
|
|
8
11
|
const expressionTypesOf = (symbols) => symbols.filter((symbol) => symbol.type === 'expression').map(symbol => symbol.expressionType);
|
|
9
12
|
/** The spellings of a single added accent the bar offers, none where no bar is known. */
|
|
@@ -12,9 +15,9 @@ const lengthOf = (span) => subtract(span.to, span.from);
|
|
|
12
15
|
/** How far apart two onsets may lie for the one symbol to count as a replacement of the other. */
|
|
13
16
|
const REPLACEMENT_TOLERANCE = mm(5);
|
|
14
17
|
/** Shorten or prolong, where the inserted symbol starts about where the deleted one did. */
|
|
15
|
-
const replacementType = (
|
|
16
|
-
const after =
|
|
17
|
-
const before =
|
|
18
|
+
const replacementType = (edition, inserted, deleted) => {
|
|
19
|
+
const after = placeOf(edition, inserted);
|
|
20
|
+
const before = placeOf(edition, deleted);
|
|
18
21
|
if (!after || !before || distance(after.from, before.from) >= REPLACEMENT_TOLERANCE)
|
|
19
22
|
return undefined;
|
|
20
23
|
return lengthOf(after) < lengthOf(before) ? 'shorten' : 'prolong';
|
|
@@ -23,13 +26,13 @@ const replacementType = (view, inserted, deleted) => {
|
|
|
23
26
|
* A guess at what an edit does, from the symbols it exchanges and from
|
|
24
27
|
* the systems the version and the one it is based on are coded for.
|
|
25
28
|
*/
|
|
26
|
-
const guessEditType = (
|
|
29
|
+
const guessEditType = (edition, versionId, edit) => {
|
|
27
30
|
const inserts = edit.insert ?? [];
|
|
28
|
-
const deletes =
|
|
31
|
+
const deletes = symbolsIn(edition, edit.delete ?? []);
|
|
29
32
|
const inserted = expressionTypesOf(inserts);
|
|
30
33
|
const deleted = expressionTypesOf(deletes);
|
|
31
|
-
const bar = trackerBarOf(
|
|
32
|
-
const parentBar = trackerBarOf(
|
|
34
|
+
const bar = trackerBarOf(versionIn(edition, versionId)?.system);
|
|
35
|
+
const parentBar = trackerBarOf(predecessorOf(edition, versionId)?.system);
|
|
33
36
|
/**
|
|
34
37
|
* Where the version is coded for another system than its parent,
|
|
35
38
|
* expression matter changed is the transfer being carried out: a red
|
|
@@ -54,14 +57,14 @@ const guessEditType = (view, versionId, edit) => {
|
|
|
54
57
|
if (inserted.length === 0 && deleted.length === 1)
|
|
55
58
|
return 'remove-redundancy';
|
|
56
59
|
if (inserts.length === 1 && deletes.length === 1)
|
|
57
|
-
return replacementType(
|
|
60
|
+
return replacementType(edition, inserts[0], deletes[0]) ?? 'correct-error';
|
|
58
61
|
return 'correct-error';
|
|
59
62
|
};
|
|
60
63
|
/**
|
|
61
64
|
* Replaces the edits with a single one carrying all their insertions
|
|
62
65
|
* and deletions, classified by a guess at what the exchange does.
|
|
63
66
|
*/
|
|
64
|
-
export const mergeEdits = (
|
|
67
|
+
export const mergeEdits = (versionId, toMerge) => reading(edition => {
|
|
65
68
|
if (toMerge.length === 0)
|
|
66
69
|
return noChange;
|
|
67
70
|
const merged = {
|
|
@@ -70,7 +73,7 @@ export const mergeEdits = (given, versionId, toMerge) => reading(given, view =>
|
|
|
70
73
|
insert: toMerge.flatMap(edit => edit.insert ?? []),
|
|
71
74
|
delete: toMerge.flatMap(edit => edit.delete ?? [])
|
|
72
75
|
};
|
|
73
|
-
merged.editType = guessEditType(
|
|
76
|
+
merged.editType = guessEditType(edition, versionId, merged);
|
|
74
77
|
const mergedIds = new Set(toMerge.map(edit => edit.id));
|
|
75
78
|
return onVersion(versionId, version => {
|
|
76
79
|
version.edits = [...editsOf(version).filter(edit => !mergedIds.has(edit.id)), merged];
|
package/lib/ops/features.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Edition } from "../model/Edition.js";
|
|
2
2
|
import { ModificationPurpose } from "../model/RollCopy.js";
|
|
3
3
|
import { FeatureConditionAssignment, FeatureOrPatch, NestedFeature } from "../model/Feature.js";
|
|
4
4
|
import { EditionOp } from "./draft.js";
|
|
@@ -62,7 +62,7 @@ export declare const mergeObstacle: (features: readonly FeatureOrPatch[]) => Mer
|
|
|
62
62
|
* feature is the work of one act, and where the features stand is the
|
|
63
63
|
* edition's business rather than theirs.
|
|
64
64
|
*/
|
|
65
|
-
export declare const mergeObstacleIn: (
|
|
65
|
+
export declare const mergeObstacleIn: (edition: Edition, featureIds: readonly string[]) => MergeObstacle | undefined;
|
|
66
66
|
/**
|
|
67
67
|
* Replaces the features of the copy with a single one covering them
|
|
68
68
|
* all, where a scan has split what the editor reads as one feature.
|
package/lib/ops/features.js
CHANGED
|
@@ -6,6 +6,7 @@ import { mm } from "../model/Quantity.js";
|
|
|
6
6
|
import { onCopy, onFeature, stateOf } from "./draft.js";
|
|
7
7
|
import { without, mapped, pruned, replacing, isRecord } from "./immutable.js";
|
|
8
8
|
import { renameReferences, forgetFeatures } from "./forget.js";
|
|
9
|
+
import { copyOfFeature } from "../lookup/lookup.js";
|
|
9
10
|
/**
|
|
10
11
|
* Whether the feature's own kind allows a condition of this kind. The
|
|
11
12
|
* type narrowed to is the weaker statement, holding of a condition any
|
|
@@ -209,8 +210,8 @@ const obstacleIn = (copy, featureIds) => {
|
|
|
209
210
|
* feature is the work of one act, and where the features stand is the
|
|
210
211
|
* edition's business rather than theirs.
|
|
211
212
|
*/
|
|
212
|
-
export const mergeObstacleIn = (
|
|
213
|
-
const copy = featureIds.map(id =>
|
|
213
|
+
export const mergeObstacleIn = (edition, featureIds) => {
|
|
214
|
+
const copy = featureIds.map(id => copyOfFeature(edition, id)).find(copy => copy !== undefined);
|
|
214
215
|
return copy ? obstacleIn(copy, featureIds) : 'fewer-than-two';
|
|
215
216
|
};
|
|
216
217
|
/** The items with the replacement in the place of the first it stands for, the others dropped. */
|
package/lib/ops/index.d.ts
CHANGED
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
* They are grouped by what they change under `ops/`; this module names
|
|
4
4
|
* the ones the library offers.
|
|
5
5
|
*/
|
|
6
|
-
export type
|
|
7
|
-
export { createVersion, addCopy, alignCopy, unalignCopy, shortenCopy, unshortenCopy, stateSource, clearSource, nameCopy, stateCarriage, clearCarriage, addGeneralCondition, symbolsCarriedOnlyBy, removeCopy } from "./copies.js";
|
|
6
|
+
export { stateOf, type EditionOp } from "./draft.js";
|
|
7
|
+
export { createVersion, addCopy, alignmentFor, alignCopy, alignCopies, chooseReferenceCopy, unalignCopy, shortenCopy, unshortenCopy, stateSource, clearSource, nameCopy, stateCarriage, clearCarriage, addGeneralCondition, statePaperStretch, addTear, symbolsCarriedOnlyBy, removeCopy } from "./copies.js";
|
|
8
8
|
export { stateFeatureCondition, addFeature, addBorneFeature, removeFeatures, mergeObstacle, mergeObstacleIn, mergeFeatures, type FeatureAct, type MergeObstacle } from "./features.js";
|
|
9
9
|
export { detachVersion, removeVersion, removeSymbols, deriveVersion, stateDerivation, clearDerivation } from "./versions.js";
|
|
10
10
|
export { connectVersions, collateSymbols, separateReadings } from "./collation.js";
|
package/lib/ops/index.js
CHANGED
|
@@ -1,4 +1,10 @@
|
|
|
1
|
-
|
|
1
|
+
/**
|
|
2
|
+
* The operations on an edition, each written onto an immer draft of it.
|
|
3
|
+
* They are grouped by what they change under `ops/`; this module names
|
|
4
|
+
* the ones the library offers.
|
|
5
|
+
*/
|
|
6
|
+
export { stateOf } from "./draft.js";
|
|
7
|
+
export { createVersion, addCopy, alignmentFor, alignCopy, alignCopies, chooseReferenceCopy, unalignCopy, shortenCopy, unshortenCopy, stateSource, clearSource, nameCopy, stateCarriage, clearCarriage, addGeneralCondition, statePaperStretch, addTear, symbolsCarriedOnlyBy, removeCopy } from "./copies.js";
|
|
2
8
|
export { stateFeatureCondition, addFeature, addBorneFeature, removeFeatures, mergeObstacle, mergeObstacleIn, mergeFeatures } from "./features.js";
|
|
3
9
|
export { detachVersion, removeVersion, removeSymbols, deriveVersion, stateDerivation, clearDerivation } from "./versions.js";
|
|
4
10
|
export { connectVersions, collateSymbols, separateReadings } from "./collation.js";
|
package/lib/ops/versions.d.ts
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { EditionView } from "../view/EditionView.js";
|
|
2
1
|
import { Derivation, Version } from "../model/Version.js";
|
|
3
2
|
import { Belief } from "../model/Assumption.js";
|
|
4
3
|
import { EditionOp } from "./draft.js";
|
|
@@ -9,13 +8,13 @@ export declare const hypothesesBeside: (version: Readonly<Version>, parentId: st
|
|
|
9
8
|
* own insertions, and its derivations go, the hypotheses among them,
|
|
10
9
|
* with the motivations that belonged to them.
|
|
11
10
|
*/
|
|
12
|
-
export declare const detachVersion: (
|
|
11
|
+
export declare const detachVersion: (versionId: string) => EditionOp;
|
|
13
12
|
/**
|
|
14
13
|
* Takes the version out. Whatever read its text against it comes to
|
|
15
14
|
* stand on its own, a hypothesis that something derives from it goes,
|
|
16
15
|
* and so does a copy's statement that it carries the version.
|
|
17
16
|
*/
|
|
18
|
-
export declare const removeVersion: (
|
|
17
|
+
export declare const removeVersion: (versionId: string) => EditionOp;
|
|
19
18
|
/** Takes the symbols out of the version's own insertions, and the edits that had nothing else. */
|
|
20
19
|
export declare const removeSymbols: (versionId: string, symbolIds: readonly string[]) => EditionOp;
|
|
21
20
|
/** Moves the edits into a new version based on this one. */
|
package/lib/ops/versions.js
CHANGED
|
@@ -4,6 +4,7 @@ import { assignReference, idOf } from "../model/Assumption.js";
|
|
|
4
4
|
import { onVersion, stateOf, insertion, dropInsertions, referenceHeld, withoutReferences, reading } from "./draft.js";
|
|
5
5
|
import { without } from "./immutable.js";
|
|
6
6
|
import { dropStatements } from "./copies.js";
|
|
7
|
+
import { snapshotOf } from "../analysis/text.js";
|
|
7
8
|
/** Whether the version's text is read against the parent, its principal derivation naming it. */
|
|
8
9
|
const readsAgainst = (version, parentId) => {
|
|
9
10
|
const principal = principalDerivationOf(version);
|
|
@@ -30,8 +31,8 @@ const dropDerivations = (version, matches) => {
|
|
|
30
31
|
* own insertions, and its derivations go, the hypotheses among them,
|
|
31
32
|
* with the motivations that belonged to them.
|
|
32
33
|
*/
|
|
33
|
-
export const detachVersion = (
|
|
34
|
-
const edits =
|
|
34
|
+
export const detachVersion = (versionId) => reading(edition => {
|
|
35
|
+
const edits = snapshotOf(edition, versionId).map(insertion);
|
|
35
36
|
return onVersion(versionId, version => {
|
|
36
37
|
version.edits = edits;
|
|
37
38
|
delete version.basedOn;
|
|
@@ -43,10 +44,10 @@ export const detachVersion = (given, versionId) => reading(given, view => {
|
|
|
43
44
|
* stand on its own, a hypothesis that something derives from it goes,
|
|
44
45
|
* and so does a copy's statement that it carries the version.
|
|
45
46
|
*/
|
|
46
|
-
export const removeVersion = (
|
|
47
|
-
const detachments =
|
|
47
|
+
export const removeVersion = (versionId) => reading(edition => {
|
|
48
|
+
const detachments = edition.versions
|
|
48
49
|
.filter(version => readsAgainst(version, versionId))
|
|
49
|
-
.map(version => detachVersion(
|
|
50
|
+
.map(version => detachVersion(version.id));
|
|
50
51
|
const namesIt = (reference) => idOf(reference) === versionId;
|
|
51
52
|
return draft => {
|
|
52
53
|
detachments.forEach(detach => detach(draft));
|
|
@@ -96,6 +96,33 @@ const stanfordScan = (druid) => ({
|
|
|
96
96
|
scan: `https://stacks.stanford.edu/image/iiif/${druid}%2F${druid}_0001/`,
|
|
97
97
|
depictionOf: (column, row, width, height) => `https://stacks.stanford.edu/image/iiif/${druid}/${druid}_0001/${column},${row},${width},${height}/128,/270/default.jpg`
|
|
98
98
|
});
|
|
99
|
+
/**
|
|
100
|
+
* The edge tears the analysis found, one condition each. The analysis
|
|
101
|
+
* lists only those that reach deeper into the paper than a tenth of an
|
|
102
|
+
* inch, and measures each by the box around it, so the tear runs across
|
|
103
|
+
* the roll as far as the box is wide.
|
|
104
|
+
*/
|
|
105
|
+
const tearsIn = (tears, dpi, depictionOf) => {
|
|
106
|
+
const onEdge = (edge, listed) => listOf(listed).map((tear) => {
|
|
107
|
+
const row = readPx(tear.ORIGIN_ROW);
|
|
108
|
+
const length = readPx(tear.WIDTH_ROW);
|
|
109
|
+
const column = readPx(tear.ORIGIN_COL);
|
|
110
|
+
const depth = readPx(tear.WIDTH_COL);
|
|
111
|
+
return {
|
|
112
|
+
conditionType: 'torn',
|
|
113
|
+
horizontal: {
|
|
114
|
+
unit: 'mm',
|
|
115
|
+
from: inMillimeters(row, dpi),
|
|
116
|
+
to: inMillimeters(px(row + length), dpi)
|
|
117
|
+
},
|
|
118
|
+
edge,
|
|
119
|
+
depth: { value: inMillimeters(depth, dpi), unit: 'mm' },
|
|
120
|
+
...(depictionOf && { depiction: depictionOf(column, row, depth, length) })
|
|
121
|
+
};
|
|
122
|
+
});
|
|
123
|
+
return [...onEdge('bass', tears?.BASS_TEARS?.TEAR), ...onEdge('treble', tears?.TREBLE_TEARS?.TEAR)]
|
|
124
|
+
.sort((a, b) => a.horizontal.from - b.horizontal.from);
|
|
125
|
+
};
|
|
99
126
|
/**
|
|
100
127
|
* The software behind an analysis and when it was run, as the
|
|
101
128
|
* analysis file states them.
|
|
@@ -155,7 +182,7 @@ export function readFromStanfordAton(atonString, { trackShift, system = welteT10
|
|
|
155
182
|
return {
|
|
156
183
|
type: 'RollCopy',
|
|
157
184
|
id: v4(),
|
|
158
|
-
conditions:
|
|
185
|
+
conditions: tearsIn(json.ROLLINFO.TEARS, dpi, stanford?.depictionOf),
|
|
159
186
|
production: {
|
|
160
187
|
system: systemOf(system),
|
|
161
188
|
...(punchDiameter !== undefined && {
|