@sametalmdr/word-editor 0.2.0-alpha → 0.3.0-alpha
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/CHANGELOG.md +108 -70
- package/LICENSE +21 -21
- package/README.md +286 -247
- package/dist/canvas/box-clipboard.js +238 -238
- package/dist/canvas/box-selection.js +80 -80
- package/dist/canvas/canvas-editor.js +502 -502
- package/dist/canvas/controller.js +717 -717
- package/dist/canvas/geometry.js +131 -131
- package/dist/canvas/gesture.d.ts +0 -1
- package/dist/canvas/gesture.js +289 -289
- package/dist/canvas/handles.js +212 -212
- package/dist/canvas/menu.js +82 -82
- package/dist/canvas/mode-controller.js +81 -81
- package/dist/canvas/nudge.js +108 -108
- package/dist/canvas/overlay.js +149 -149
- package/dist/canvas/snap.js +132 -132
- package/dist/canvas/viewport.js +112 -112
- package/dist/canvas/z-order.js +171 -171
- package/dist/commands/alignment.js +150 -150
- package/dist/commands/box.js +272 -272
- package/dist/commands/clipboard.js +93 -93
- package/dist/commands/graphemes.js +112 -112
- package/dist/commands/marks.js +153 -153
- package/dist/commands/paragraph-props.js +176 -176
- package/dist/commands/size.js +368 -368
- package/dist/commands/text.js +291 -291
- package/dist/docx.d.ts +1 -0
- package/dist/docx.js +15 -13
- package/dist/editor/editing-host.js +434 -434
- package/dist/element.js +41 -41
- package/dist/fonts/OFL-Carlito.txt +94 -0
- package/dist/fonts/calibri-metrics.d.ts +27 -0
- package/dist/fonts/calibri-metrics.js +88 -0
- package/dist/history/history.js +433 -433
- package/dist/index.js +63 -63
- package/dist/input/beforeinput.js +224 -224
- package/dist/input/clipboard.js +107 -107
- package/dist/input/composition.js +341 -341
- package/dist/input/keymap.js +54 -54
- package/dist/io/ooxml/custgeom.js +72 -72
- package/dist/io/ooxml/drawingml.js +232 -232
- package/dist/io/ooxml/edits.js +67 -67
- package/dist/io/ooxml/export-splice.js +880 -880
- package/dist/io/ooxml/export.js +365 -365
- package/dist/io/ooxml/fill.d.ts +93 -8
- package/dist/io/ooxml/fill.js +618 -562
- package/dist/io/ooxml/fit.d.ts +252 -0
- package/dist/io/ooxml/fit.js +598 -0
- package/dist/io/ooxml/import-gate.js +200 -200
- package/dist/io/ooxml/import.js +691 -691
- package/dist/io/ooxml/inflate.js +126 -126
- package/dist/io/ooxml/media.js +87 -87
- package/dist/io/ooxml/ns.d.ts +2 -0
- package/dist/io/ooxml/ns.js +26 -21
- package/dist/io/ooxml/numbering.js +290 -290
- package/dist/io/ooxml/opc-write.js +171 -171
- package/dist/io/ooxml/provenance.js +93 -93
- package/dist/io/ooxml/recipe.js +708 -708
- package/dist/io/ooxml/relationships.js +59 -59
- package/dist/io/ooxml/run-fonts.d.ts +89 -0
- package/dist/io/ooxml/run-fonts.js +378 -0
- package/dist/io/ooxml/slots.d.ts +4 -0
- package/dist/io/ooxml/slots.js +582 -581
- package/dist/io/ooxml/styles-resolve.js +257 -257
- package/dist/io/ooxml/units.js +43 -43
- package/dist/io/ooxml/value.js +120 -120
- package/dist/io/ooxml/xml-scan.js +616 -616
- package/dist/io/ooxml/zip-container.js +228 -228
- package/dist/io/ooxml/zip-reject.js +106 -106
- package/dist/measure/placement.js +83 -83
- package/dist/measure/report.js +75 -75
- package/dist/model/ids.js +70 -70
- package/dist/model/normalize.js +146 -146
- package/dist/model/position.js +283 -283
- package/dist/model/transaction.js +209 -209
- package/dist/platform/capabilities.js +25 -25
- package/dist/react/index.js +21 -21
- package/dist/selection/controller.js +315 -315
- package/dist/selection/dom-map.js +334 -334
- package/dist/state/editor-state.js +109 -109
- package/dist/styles.css +66 -66
- package/package.json +94 -93
|
@@ -1,209 +1,209 @@
|
|
|
1
|
-
import { normalizeDoc } from "./normalize.js";
|
|
2
|
-
import { apply, dirtyParagraphIds } from "./step-apply.js";
|
|
3
|
-
import { mapThroughSteps } from "./step-map.js";
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* One user-visible change. A transaction is the unit of undo, so everything that
|
|
7
|
-
* should disappear on a single Ctrl+Z belongs in one of these — typing over a
|
|
8
|
-
* selection is a delete *and* an insert, but one transaction.
|
|
9
|
-
*
|
|
10
|
-
* @typedef {object} Transaction
|
|
11
|
-
* @property {import("./step.js").Step[]} steps
|
|
12
|
-
* @property {import("./node.js").Doc} docBefore
|
|
13
|
-
* @property {import("./node.js").Doc} doc normalized result
|
|
14
|
-
* @property {import("./position.js").Selection} selectionBefore
|
|
15
|
-
* @property {import("./position.js").Selection} selectionAfter
|
|
16
|
-
* @property {TransactionOrigin} origin
|
|
17
|
-
* @property {number} timestamp
|
|
18
|
-
* @property {import("./node.js").Marks | null | undefined} storedMarks
|
|
19
|
-
* `undefined` means "derive from the default rules"; an explicit value (or
|
|
20
|
-
* `null`) overrides them. See `state/editor-state.js`.
|
|
21
|
-
* @property {number} [gestureId]
|
|
22
|
-
* ADR-0016 §1 / ADR-0018 Karar 3's pointer-gesture bracket id. Set only by
|
|
23
|
-
* a pointer drag or a keyboard nudge (both `origin: "pointer"`) via
|
|
24
|
-
* `setGesture`; `undefined` for every other origin. `HistoryEngine`
|
|
25
|
-
* compares this by equality across consecutive "pointer" transactions to
|
|
26
|
-
* decide whether they belong to the SAME user gesture — it never enters
|
|
27
|
-
* `Doc`'s own schema, never reaches `toJSON`, never reaches the clipboard
|
|
28
|
-
* (invariant #13): it lives on `Transaction`/`HistoryEntry` only.
|
|
29
|
-
* @property {readonly string[]} [unverifiedAssumptions]
|
|
30
|
-
* The command-layer counterpart of `ImportReport.unverifiedAssumptions`
|
|
31
|
-
* (`io/ooxml/import.js`) — but DYNAMIC, not static: import's list is
|
|
32
|
-
* disclosed unconditionally on every document, this one is populated only
|
|
33
|
-
* when a command actually exercised a constant it could not verify from a
|
|
34
|
-
* primary source (ADR-0028: `commands/size.js`'s clamp ceiling, sourced
|
|
35
|
-
* only from a secondary reference). `undefined` when nothing was noted —
|
|
36
|
-
* same absent-vs-empty convention as `gestureId`. Same scope restriction:
|
|
37
|
-
* never model schema, never `toJSON`, never the clipboard.
|
|
38
|
-
*/
|
|
39
|
-
|
|
40
|
-
/**
|
|
41
|
-
* What produced the transaction. Drives undo coalescing, so it has to be set
|
|
42
|
-
* honestly — `"input"` is only for ordinary typing, `"pointer"` is only for a
|
|
43
|
-
* box drag (`commands/box.js`'s `moveBox`/`resizeBox`), each origin coalescing
|
|
44
|
-
* under its own rule in `HistoryEngine.canCoalesce`.
|
|
45
|
-
* @typedef {"input" | "paste" | "format" | "history" | "ime" | "pointer"} TransactionOrigin
|
|
46
|
-
*/
|
|
47
|
-
|
|
48
|
-
/**
|
|
49
|
-
* Accumulates steps against an evolving document.
|
|
50
|
-
*
|
|
51
|
-
* Commands naturally compute their ranges against the document they were handed,
|
|
52
|
-
* but each step after the first must be expressed in coordinates *after* the
|
|
53
|
-
* preceding steps. `map()` bridges that: hand it a position in the original
|
|
54
|
-
* document and it returns the equivalent position now.
|
|
55
|
-
*/
|
|
56
|
-
export class TransactionBuilder {
|
|
57
|
-
/**
|
|
58
|
-
* @param {import("./node.js").Doc} doc
|
|
59
|
-
* @param {import("./position.js").Selection} selection
|
|
60
|
-
* @param {TransactionOrigin} [origin]
|
|
61
|
-
*/
|
|
62
|
-
constructor(doc, selection, origin = "input") {
|
|
63
|
-
/** @type {import("./node.js").Doc} */
|
|
64
|
-
this.docBefore = doc;
|
|
65
|
-
/** @type {import("./node.js").Doc} */
|
|
66
|
-
this.doc = doc;
|
|
67
|
-
/** @type {import("./step.js").Step[]} */
|
|
68
|
-
this.steps = [];
|
|
69
|
-
/** @type {import("./position.js").Selection} */
|
|
70
|
-
this.selectionBefore = selection;
|
|
71
|
-
/** @type {import("./position.js").Selection} */
|
|
72
|
-
this.selectionAfter = selection;
|
|
73
|
-
/** @type {TransactionOrigin} */
|
|
74
|
-
this.origin = origin;
|
|
75
|
-
/** @type {Set<import("./node.js").NodeId>} */
|
|
76
|
-
this.dirtyIds = new Set();
|
|
77
|
-
/** @type {import("./node.js").Marks | null | undefined} */
|
|
78
|
-
this.storedMarks = undefined;
|
|
79
|
-
/** @type {number | undefined} */
|
|
80
|
-
this.gestureId = undefined;
|
|
81
|
-
/** @type {string[] | undefined} */
|
|
82
|
-
this.unverifiedAssumptions = undefined;
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
/**
|
|
86
|
-
* Applies a step, expressed in *current* coordinates.
|
|
87
|
-
* @param {import("./step.js").Step} step
|
|
88
|
-
* @returns {this}
|
|
89
|
-
*/
|
|
90
|
-
step(step) {
|
|
91
|
-
for (const id of dirtyParagraphIds(this.doc, step)) {
|
|
92
|
-
this.dirtyIds.add(id);
|
|
93
|
-
}
|
|
94
|
-
this.doc = apply(this.doc, step);
|
|
95
|
-
this.steps.push(step);
|
|
96
|
-
return this;
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
/**
|
|
100
|
-
* Translates a position from the original document into current coordinates.
|
|
101
|
-
* @param {import("./position.js").Position} pos
|
|
102
|
-
* @param {-1 | 1} [bias]
|
|
103
|
-
* @returns {import("./position.js").Position}
|
|
104
|
-
*/
|
|
105
|
-
map(pos, bias = 1) {
|
|
106
|
-
return mapThroughSteps(this.docBefore, this.steps, pos, bias).pos;
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
/**
|
|
110
|
-
* @param {import("./position.js").Selection} selection
|
|
111
|
-
* @returns {this}
|
|
112
|
-
*/
|
|
113
|
-
setSelection(selection) {
|
|
114
|
-
this.selectionAfter = selection;
|
|
115
|
-
return this;
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
/**
|
|
119
|
-
* Overrides the default `storedMarks` handling. Used by `toggleMark` on a
|
|
120
|
-
* collapsed selection, which changes no document content at all.
|
|
121
|
-
* @param {import("./node.js").Marks | null} marks
|
|
122
|
-
* @returns {this}
|
|
123
|
-
*/
|
|
124
|
-
setStoredMarks(marks) {
|
|
125
|
-
this.storedMarks = marks;
|
|
126
|
-
return this;
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
/**
|
|
130
|
-
* Tags this transaction with the pointer-gesture bracket it belongs to
|
|
131
|
-
* (ADR-0016 §1, ADR-0018 Karar 3) — `HistoryEngine.canCoalesce` compares
|
|
132
|
-
* this by equality across consecutive `"pointer"` transactions to decide
|
|
133
|
-
* whether they are the SAME user gesture. Never model schema, never
|
|
134
|
-
* `toJSON`, never the clipboard (invariant #13) — `id` is minted by the
|
|
135
|
-
* caller's `IdFactory` before this is called; this method never mints one.
|
|
136
|
-
* @param {number} id
|
|
137
|
-
* @returns {this}
|
|
138
|
-
*/
|
|
139
|
-
setGesture(id) {
|
|
140
|
-
this.gestureId = id;
|
|
141
|
-
return this;
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
/**
|
|
145
|
-
* Records that this transaction exercised a constant not verified from a
|
|
146
|
-
* primary source — the dynamic, command-layer counterpart of
|
|
147
|
-
* `ImportReport.unverifiedAssumptions`. Deduplicates identical messages
|
|
148
|
-
* (a range edit can clamp several segments against the same ceiling in one
|
|
149
|
-
* transaction; the caller should not have to track "already noted" itself).
|
|
150
|
-
* @param {string} message
|
|
151
|
-
* @returns {this}
|
|
152
|
-
*/
|
|
153
|
-
noteUnverifiedAssumption(message) {
|
|
154
|
-
if (this.unverifiedAssumptions === undefined) {
|
|
155
|
-
this.unverifiedAssumptions = [];
|
|
156
|
-
}
|
|
157
|
-
if (!this.unverifiedAssumptions.includes(message)) {
|
|
158
|
-
this.unverifiedAssumptions.push(message);
|
|
159
|
-
}
|
|
160
|
-
return this;
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
/** @returns {boolean} */
|
|
164
|
-
get isEmpty() {
|
|
165
|
-
return this.steps.length === 0;
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
/**
|
|
169
|
-
* Whether the steps actually changed anything. A step can be a no-op — marking
|
|
170
|
-
* text that already carries the mark, deleting an empty range — and such a
|
|
171
|
-
* transaction must not reach the history stack, or Ctrl+Z would appear to do
|
|
172
|
-
* nothing.
|
|
173
|
-
* @returns {boolean}
|
|
174
|
-
*/
|
|
175
|
-
get changesDoc() {
|
|
176
|
-
return this.doc !== this.docBefore;
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
/**
|
|
180
|
-
* @param {number} [timestamp]
|
|
181
|
-
* @returns {Transaction}
|
|
182
|
-
*/
|
|
183
|
-
build(timestamp = Date.now()) {
|
|
184
|
-
return {
|
|
185
|
-
steps: this.steps,
|
|
186
|
-
docBefore: this.docBefore,
|
|
187
|
-
// Normalisation happens once, here — never between steps, so a step is
|
|
188
|
-
// free to leave empty or mergeable runs behind.
|
|
189
|
-
doc: normalizeDoc(this.doc, this.dirtyIds),
|
|
190
|
-
selectionBefore: this.selectionBefore,
|
|
191
|
-
selectionAfter: this.selectionAfter,
|
|
192
|
-
origin: this.origin,
|
|
193
|
-
timestamp,
|
|
194
|
-
storedMarks: this.storedMarks,
|
|
195
|
-
gestureId: this.gestureId,
|
|
196
|
-
unverifiedAssumptions: this.unverifiedAssumptions,
|
|
197
|
-
};
|
|
198
|
-
}
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
/**
|
|
202
|
-
* @param {import("./node.js").Doc} doc
|
|
203
|
-
* @param {import("./position.js").Selection} selection
|
|
204
|
-
* @param {TransactionOrigin} [origin]
|
|
205
|
-
* @returns {TransactionBuilder}
|
|
206
|
-
*/
|
|
207
|
-
export function createTransaction(doc, selection, origin = "input") {
|
|
208
|
-
return new TransactionBuilder(doc, selection, origin);
|
|
209
|
-
}
|
|
1
|
+
import { normalizeDoc } from "./normalize.js";
|
|
2
|
+
import { apply, dirtyParagraphIds } from "./step-apply.js";
|
|
3
|
+
import { mapThroughSteps } from "./step-map.js";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* One user-visible change. A transaction is the unit of undo, so everything that
|
|
7
|
+
* should disappear on a single Ctrl+Z belongs in one of these — typing over a
|
|
8
|
+
* selection is a delete *and* an insert, but one transaction.
|
|
9
|
+
*
|
|
10
|
+
* @typedef {object} Transaction
|
|
11
|
+
* @property {import("./step.js").Step[]} steps
|
|
12
|
+
* @property {import("./node.js").Doc} docBefore
|
|
13
|
+
* @property {import("./node.js").Doc} doc normalized result
|
|
14
|
+
* @property {import("./position.js").Selection} selectionBefore
|
|
15
|
+
* @property {import("./position.js").Selection} selectionAfter
|
|
16
|
+
* @property {TransactionOrigin} origin
|
|
17
|
+
* @property {number} timestamp
|
|
18
|
+
* @property {import("./node.js").Marks | null | undefined} storedMarks
|
|
19
|
+
* `undefined` means "derive from the default rules"; an explicit value (or
|
|
20
|
+
* `null`) overrides them. See `state/editor-state.js`.
|
|
21
|
+
* @property {number} [gestureId]
|
|
22
|
+
* ADR-0016 §1 / ADR-0018 Karar 3's pointer-gesture bracket id. Set only by
|
|
23
|
+
* a pointer drag or a keyboard nudge (both `origin: "pointer"`) via
|
|
24
|
+
* `setGesture`; `undefined` for every other origin. `HistoryEngine`
|
|
25
|
+
* compares this by equality across consecutive "pointer" transactions to
|
|
26
|
+
* decide whether they belong to the SAME user gesture — it never enters
|
|
27
|
+
* `Doc`'s own schema, never reaches `toJSON`, never reaches the clipboard
|
|
28
|
+
* (invariant #13): it lives on `Transaction`/`HistoryEntry` only.
|
|
29
|
+
* @property {readonly string[]} [unverifiedAssumptions]
|
|
30
|
+
* The command-layer counterpart of `ImportReport.unverifiedAssumptions`
|
|
31
|
+
* (`io/ooxml/import.js`) — but DYNAMIC, not static: import's list is
|
|
32
|
+
* disclosed unconditionally on every document, this one is populated only
|
|
33
|
+
* when a command actually exercised a constant it could not verify from a
|
|
34
|
+
* primary source (ADR-0028: `commands/size.js`'s clamp ceiling, sourced
|
|
35
|
+
* only from a secondary reference). `undefined` when nothing was noted —
|
|
36
|
+
* same absent-vs-empty convention as `gestureId`. Same scope restriction:
|
|
37
|
+
* never model schema, never `toJSON`, never the clipboard.
|
|
38
|
+
*/
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* What produced the transaction. Drives undo coalescing, so it has to be set
|
|
42
|
+
* honestly — `"input"` is only for ordinary typing, `"pointer"` is only for a
|
|
43
|
+
* box drag (`commands/box.js`'s `moveBox`/`resizeBox`), each origin coalescing
|
|
44
|
+
* under its own rule in `HistoryEngine.canCoalesce`.
|
|
45
|
+
* @typedef {"input" | "paste" | "format" | "history" | "ime" | "pointer"} TransactionOrigin
|
|
46
|
+
*/
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Accumulates steps against an evolving document.
|
|
50
|
+
*
|
|
51
|
+
* Commands naturally compute their ranges against the document they were handed,
|
|
52
|
+
* but each step after the first must be expressed in coordinates *after* the
|
|
53
|
+
* preceding steps. `map()` bridges that: hand it a position in the original
|
|
54
|
+
* document and it returns the equivalent position now.
|
|
55
|
+
*/
|
|
56
|
+
export class TransactionBuilder {
|
|
57
|
+
/**
|
|
58
|
+
* @param {import("./node.js").Doc} doc
|
|
59
|
+
* @param {import("./position.js").Selection} selection
|
|
60
|
+
* @param {TransactionOrigin} [origin]
|
|
61
|
+
*/
|
|
62
|
+
constructor(doc, selection, origin = "input") {
|
|
63
|
+
/** @type {import("./node.js").Doc} */
|
|
64
|
+
this.docBefore = doc;
|
|
65
|
+
/** @type {import("./node.js").Doc} */
|
|
66
|
+
this.doc = doc;
|
|
67
|
+
/** @type {import("./step.js").Step[]} */
|
|
68
|
+
this.steps = [];
|
|
69
|
+
/** @type {import("./position.js").Selection} */
|
|
70
|
+
this.selectionBefore = selection;
|
|
71
|
+
/** @type {import("./position.js").Selection} */
|
|
72
|
+
this.selectionAfter = selection;
|
|
73
|
+
/** @type {TransactionOrigin} */
|
|
74
|
+
this.origin = origin;
|
|
75
|
+
/** @type {Set<import("./node.js").NodeId>} */
|
|
76
|
+
this.dirtyIds = new Set();
|
|
77
|
+
/** @type {import("./node.js").Marks | null | undefined} */
|
|
78
|
+
this.storedMarks = undefined;
|
|
79
|
+
/** @type {number | undefined} */
|
|
80
|
+
this.gestureId = undefined;
|
|
81
|
+
/** @type {string[] | undefined} */
|
|
82
|
+
this.unverifiedAssumptions = undefined;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Applies a step, expressed in *current* coordinates.
|
|
87
|
+
* @param {import("./step.js").Step} step
|
|
88
|
+
* @returns {this}
|
|
89
|
+
*/
|
|
90
|
+
step(step) {
|
|
91
|
+
for (const id of dirtyParagraphIds(this.doc, step)) {
|
|
92
|
+
this.dirtyIds.add(id);
|
|
93
|
+
}
|
|
94
|
+
this.doc = apply(this.doc, step);
|
|
95
|
+
this.steps.push(step);
|
|
96
|
+
return this;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Translates a position from the original document into current coordinates.
|
|
101
|
+
* @param {import("./position.js").Position} pos
|
|
102
|
+
* @param {-1 | 1} [bias]
|
|
103
|
+
* @returns {import("./position.js").Position}
|
|
104
|
+
*/
|
|
105
|
+
map(pos, bias = 1) {
|
|
106
|
+
return mapThroughSteps(this.docBefore, this.steps, pos, bias).pos;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* @param {import("./position.js").Selection} selection
|
|
111
|
+
* @returns {this}
|
|
112
|
+
*/
|
|
113
|
+
setSelection(selection) {
|
|
114
|
+
this.selectionAfter = selection;
|
|
115
|
+
return this;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* Overrides the default `storedMarks` handling. Used by `toggleMark` on a
|
|
120
|
+
* collapsed selection, which changes no document content at all.
|
|
121
|
+
* @param {import("./node.js").Marks | null} marks
|
|
122
|
+
* @returns {this}
|
|
123
|
+
*/
|
|
124
|
+
setStoredMarks(marks) {
|
|
125
|
+
this.storedMarks = marks;
|
|
126
|
+
return this;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* Tags this transaction with the pointer-gesture bracket it belongs to
|
|
131
|
+
* (ADR-0016 §1, ADR-0018 Karar 3) — `HistoryEngine.canCoalesce` compares
|
|
132
|
+
* this by equality across consecutive `"pointer"` transactions to decide
|
|
133
|
+
* whether they are the SAME user gesture. Never model schema, never
|
|
134
|
+
* `toJSON`, never the clipboard (invariant #13) — `id` is minted by the
|
|
135
|
+
* caller's `IdFactory` before this is called; this method never mints one.
|
|
136
|
+
* @param {number} id
|
|
137
|
+
* @returns {this}
|
|
138
|
+
*/
|
|
139
|
+
setGesture(id) {
|
|
140
|
+
this.gestureId = id;
|
|
141
|
+
return this;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* Records that this transaction exercised a constant not verified from a
|
|
146
|
+
* primary source — the dynamic, command-layer counterpart of
|
|
147
|
+
* `ImportReport.unverifiedAssumptions`. Deduplicates identical messages
|
|
148
|
+
* (a range edit can clamp several segments against the same ceiling in one
|
|
149
|
+
* transaction; the caller should not have to track "already noted" itself).
|
|
150
|
+
* @param {string} message
|
|
151
|
+
* @returns {this}
|
|
152
|
+
*/
|
|
153
|
+
noteUnverifiedAssumption(message) {
|
|
154
|
+
if (this.unverifiedAssumptions === undefined) {
|
|
155
|
+
this.unverifiedAssumptions = [];
|
|
156
|
+
}
|
|
157
|
+
if (!this.unverifiedAssumptions.includes(message)) {
|
|
158
|
+
this.unverifiedAssumptions.push(message);
|
|
159
|
+
}
|
|
160
|
+
return this;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
/** @returns {boolean} */
|
|
164
|
+
get isEmpty() {
|
|
165
|
+
return this.steps.length === 0;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* Whether the steps actually changed anything. A step can be a no-op — marking
|
|
170
|
+
* text that already carries the mark, deleting an empty range — and such a
|
|
171
|
+
* transaction must not reach the history stack, or Ctrl+Z would appear to do
|
|
172
|
+
* nothing.
|
|
173
|
+
* @returns {boolean}
|
|
174
|
+
*/
|
|
175
|
+
get changesDoc() {
|
|
176
|
+
return this.doc !== this.docBefore;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
/**
|
|
180
|
+
* @param {number} [timestamp]
|
|
181
|
+
* @returns {Transaction}
|
|
182
|
+
*/
|
|
183
|
+
build(timestamp = Date.now()) {
|
|
184
|
+
return {
|
|
185
|
+
steps: this.steps,
|
|
186
|
+
docBefore: this.docBefore,
|
|
187
|
+
// Normalisation happens once, here — never between steps, so a step is
|
|
188
|
+
// free to leave empty or mergeable runs behind.
|
|
189
|
+
doc: normalizeDoc(this.doc, this.dirtyIds),
|
|
190
|
+
selectionBefore: this.selectionBefore,
|
|
191
|
+
selectionAfter: this.selectionAfter,
|
|
192
|
+
origin: this.origin,
|
|
193
|
+
timestamp,
|
|
194
|
+
storedMarks: this.storedMarks,
|
|
195
|
+
gestureId: this.gestureId,
|
|
196
|
+
unverifiedAssumptions: this.unverifiedAssumptions,
|
|
197
|
+
};
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
/**
|
|
202
|
+
* @param {import("./node.js").Doc} doc
|
|
203
|
+
* @param {import("./position.js").Selection} selection
|
|
204
|
+
* @param {TransactionOrigin} [origin]
|
|
205
|
+
* @returns {TransactionBuilder}
|
|
206
|
+
*/
|
|
207
|
+
export function createTransaction(doc, selection, origin = "input") {
|
|
208
|
+
return new TransactionBuilder(doc, selection, origin);
|
|
209
|
+
}
|
|
@@ -1,25 +1,25 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @typedef {object} Capabilities
|
|
3
|
-
* @property {boolean} indexedDB
|
|
4
|
-
* @property {boolean} compressionStream
|
|
5
|
-
* @property {boolean} decompressionStream
|
|
6
|
-
* @property {boolean} fileSystemAccess
|
|
7
|
-
* @property {boolean} dom
|
|
8
|
-
*/
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* Detects platform capabilities without touching any global at import time.
|
|
12
|
-
* Every check is lazy — it only runs when this function is called.
|
|
13
|
-
* @returns {Capabilities}
|
|
14
|
-
*/
|
|
15
|
-
export function detectCapabilities() {
|
|
16
|
-
return {
|
|
17
|
-
indexedDB: typeof indexedDB !== "undefined",
|
|
18
|
-
compressionStream: typeof CompressionStream !== "undefined",
|
|
19
|
-
decompressionStream: typeof DecompressionStream !== "undefined",
|
|
20
|
-
fileSystemAccess:
|
|
21
|
-
typeof window !== "undefined" &&
|
|
22
|
-
typeof (/** @type {any} */ (window).showOpenFilePicker) === "function",
|
|
23
|
-
dom: typeof document !== "undefined",
|
|
24
|
-
};
|
|
25
|
-
}
|
|
1
|
+
/**
|
|
2
|
+
* @typedef {object} Capabilities
|
|
3
|
+
* @property {boolean} indexedDB
|
|
4
|
+
* @property {boolean} compressionStream
|
|
5
|
+
* @property {boolean} decompressionStream
|
|
6
|
+
* @property {boolean} fileSystemAccess
|
|
7
|
+
* @property {boolean} dom
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Detects platform capabilities without touching any global at import time.
|
|
12
|
+
* Every check is lazy — it only runs when this function is called.
|
|
13
|
+
* @returns {Capabilities}
|
|
14
|
+
*/
|
|
15
|
+
export function detectCapabilities() {
|
|
16
|
+
return {
|
|
17
|
+
indexedDB: typeof indexedDB !== "undefined",
|
|
18
|
+
compressionStream: typeof CompressionStream !== "undefined",
|
|
19
|
+
decompressionStream: typeof DecompressionStream !== "undefined",
|
|
20
|
+
fileSystemAccess:
|
|
21
|
+
typeof window !== "undefined" &&
|
|
22
|
+
typeof (/** @type {any} */ (window).showOpenFilePicker) === "function",
|
|
23
|
+
dom: typeof document !== "undefined",
|
|
24
|
+
};
|
|
25
|
+
}
|
package/dist/react/index.js
CHANGED
|
@@ -1,21 +1,21 @@
|
|
|
1
|
-
import { createElement, useEffect, useRef } from "react";
|
|
2
|
-
import { createEditor } from "../index.js";
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Thin React wrapper around createEditor(). Holds no internal state of its
|
|
6
|
-
* own — the editor instance is the single source of truth.
|
|
7
|
-
* @returns {import("react").ReactElement}
|
|
8
|
-
*/
|
|
9
|
-
export function WordEditor() {
|
|
10
|
-
const containerRef = useRef(/** @type {HTMLDivElement | null} */ (null));
|
|
11
|
-
|
|
12
|
-
useEffect(() => {
|
|
13
|
-
if (!containerRef.current) {
|
|
14
|
-
return undefined;
|
|
15
|
-
}
|
|
16
|
-
const editor = createEditor({ container: containerRef.current });
|
|
17
|
-
return () => editor.destroy();
|
|
18
|
-
}, []);
|
|
19
|
-
|
|
20
|
-
return createElement("div", { ref: containerRef });
|
|
21
|
-
}
|
|
1
|
+
import { createElement, useEffect, useRef } from "react";
|
|
2
|
+
import { createEditor } from "../index.js";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Thin React wrapper around createEditor(). Holds no internal state of its
|
|
6
|
+
* own — the editor instance is the single source of truth.
|
|
7
|
+
* @returns {import("react").ReactElement}
|
|
8
|
+
*/
|
|
9
|
+
export function WordEditor() {
|
|
10
|
+
const containerRef = useRef(/** @type {HTMLDivElement | null} */ (null));
|
|
11
|
+
|
|
12
|
+
useEffect(() => {
|
|
13
|
+
if (!containerRef.current) {
|
|
14
|
+
return undefined;
|
|
15
|
+
}
|
|
16
|
+
const editor = createEditor({ container: containerRef.current });
|
|
17
|
+
return () => editor.destroy();
|
|
18
|
+
}, []);
|
|
19
|
+
|
|
20
|
+
return createElement("div", { ref: containerRef });
|
|
21
|
+
}
|