@thomasfosterau/effect-richtext 0.0.0 → 0.1.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/LICENSE +48 -0
- package/README.md +117 -1
- package/dist/_virtual/_rolldown/runtime.js +12 -0
- package/dist/commands/commands.d.ts +323 -0
- package/dist/commands/commands.js +722 -0
- package/dist/commands/internal.js +43 -0
- package/dist/commands/keymaps.d.ts +46 -0
- package/dist/commands/keymaps.js +64 -0
- package/dist/commands.d.ts +3 -0
- package/dist/commands.js +3 -0
- package/dist/compat/commands.d.ts +250 -0
- package/dist/compat/commands.js +275 -0
- package/dist/compat/internal/core.d.ts +20 -0
- package/dist/compat/internal/core.js +148 -0
- package/dist/compat/internal/props.js +82 -0
- package/dist/compat/keymap.d.ts +21 -0
- package/dist/compat/keymap.js +38 -0
- package/dist/compat/model.d.ts +893 -0
- package/dist/compat/model.js +1212 -0
- package/dist/compat/orderedmap.d.ts +74 -0
- package/dist/compat/orderedmap.js +124 -0
- package/dist/compat/schema-basic.d.ts +38 -0
- package/dist/compat/schema-basic.js +238 -0
- package/dist/compat/schema-list.d.ts +81 -0
- package/dist/compat/schema-list.js +156 -0
- package/dist/compat/state.d.ts +415 -0
- package/dist/compat/state.js +689 -0
- package/dist/compat/test-builder.d.ts +98 -0
- package/dist/compat/test-builder.js +197 -0
- package/dist/compat/transform.d.ts +458 -0
- package/dist/compat/transform.js +803 -0
- package/dist/compat/view.d.ts +411 -0
- package/dist/compat/view.js +409 -0
- package/dist/dropcursor.d.ts +46 -0
- package/dist/dropcursor.js +176 -0
- package/dist/extensions/defaults.d.ts +716 -0
- package/dist/extensions/defaults.js +209 -0
- package/dist/extensions/editor.d.ts +246 -0
- package/dist/extensions/editor.js +271 -0
- package/dist/extensions/extension.d.ts +375 -0
- package/dist/extensions/extension.js +233 -0
- package/dist/extensions.d.ts +4 -0
- package/dist/extensions.js +4 -0
- package/dist/gapcursor.d.ts +66 -0
- package/dist/gapcursor.js +273 -0
- package/dist/history.d.ts +178 -0
- package/dist/history.js +412 -0
- package/dist/html.d.ts +158 -0
- package/dist/html.js +164 -0
- package/dist/inputrules.d.ts +271 -0
- package/dist/inputrules.js +321 -0
- package/dist/internal/attempt.js +15 -0
- package/dist/internal/json.js +29 -0
- package/dist/keymap/keymap.d.ts +130 -0
- package/dist/keymap/keymap.js +159 -0
- package/dist/keymap.d.ts +2 -0
- package/dist/keymap.js +1 -0
- package/dist/markdown/errors.d.ts +23 -0
- package/dist/markdown/errors.js +26 -0
- package/dist/markdown/from_markdown.d.ts +185 -0
- package/dist/markdown/from_markdown.js +266 -0
- package/dist/markdown/schema.d.ts +522 -0
- package/dist/markdown/schema.js +292 -0
- package/dist/markdown/to_markdown.d.ts +251 -0
- package/dist/markdown/to_markdown.js +413 -0
- package/dist/markdown.d.ts +5 -0
- package/dist/markdown.js +5 -0
- package/dist/model/attrsCodec.js +48 -0
- package/dist/model/comparedeep.js +17 -0
- package/dist/model/content.d.ts +232 -0
- package/dist/model/content.js +630 -0
- package/dist/model/diff.js +66 -0
- package/dist/model/dom.d.ts +3 -0
- package/dist/model/errors.d.ts +90 -0
- package/dist/model/errors.js +76 -0
- package/dist/model/fragment.d.ts +131 -0
- package/dist/model/fragment.js +262 -0
- package/dist/model/from_dom.d.ts +299 -0
- package/dist/model/from_dom.js +618 -0
- package/dist/model/json.d.ts +37 -0
- package/dist/model/json.js +126 -0
- package/dist/model/mark.d.ts +73 -0
- package/dist/model/mark.js +121 -0
- package/dist/model/node.d.ts +267 -0
- package/dist/model/node.js +434 -0
- package/dist/model/replace.d.ts +78 -0
- package/dist/model/replace.js +207 -0
- package/dist/model/resolvedpos.d.ts +196 -0
- package/dist/model/resolvedpos.js +305 -0
- package/dist/model/schema.d.ts +740 -0
- package/dist/model/schema.js +451 -0
- package/dist/model/to_dom.d.ts +169 -0
- package/dist/model/to_dom.js +238 -0
- package/dist/model.d.ts +12 -0
- package/dist/model.js +12 -0
- package/dist/placeholder.d.ts +53 -0
- package/dist/placeholder.js +79 -0
- package/dist/reactive/observer.d.ts +54 -0
- package/dist/reactive/observer.js +61 -0
- package/dist/reactive/selectors.d.ts +22 -0
- package/dist/reactive/selectors.js +61 -0
- package/dist/reactive/stateref.d.ts +72 -0
- package/dist/reactive/stateref.js +71 -0
- package/dist/reactive/streams.d.ts +83 -0
- package/dist/reactive/streams.js +85 -0
- package/dist/reactive.d.ts +16 -0
- package/dist/reactive.js +26 -0
- package/dist/schema-basic.d.ts +448 -0
- package/dist/schema-basic.js +269 -0
- package/dist/schema-list/commands.d.ts +66 -0
- package/dist/schema-list/commands.js +203 -0
- package/dist/schema-list.d.ts +92 -0
- package/dist/schema-list.js +100 -0
- package/dist/state/errors.d.ts +39 -0
- package/dist/state/errors.js +32 -0
- package/dist/state/plugin.d.ts +232 -0
- package/dist/state/plugin.js +82 -0
- package/dist/state/selection.d.ts +297 -0
- package/dist/state/selection.js +486 -0
- package/dist/state/state.d.ts +212 -0
- package/dist/state/state.js +489 -0
- package/dist/state/transaction.d.ts +145 -0
- package/dist/state/transaction.js +195 -0
- package/dist/state.d.ts +6 -0
- package/dist/state.js +6 -0
- package/dist/test-builder.d.ts +3582 -0
- package/dist/test-builder.js +239 -0
- package/dist/transform/attr_step.d.ts +60 -0
- package/dist/transform/attr_step.js +105 -0
- package/dist/transform/errors.d.ts +50 -0
- package/dist/transform/errors.js +35 -0
- package/dist/transform/map.d.ts +182 -0
- package/dist/transform/map.js +280 -0
- package/dist/transform/mark.js +98 -0
- package/dist/transform/mark_set_step.js +69 -0
- package/dist/transform/mark_step.d.ts +113 -0
- package/dist/transform/mark_step.js +225 -0
- package/dist/transform/replace.d.ts +18 -0
- package/dist/transform/replace.js +381 -0
- package/dist/transform/replace_step.d.ts +109 -0
- package/dist/transform/replace_step.js +175 -0
- package/dist/transform/step.d.ts +157 -0
- package/dist/transform/step.js +168 -0
- package/dist/transform/structure.d.ts +89 -0
- package/dist/transform/structure.js +350 -0
- package/dist/transform/transform.d.ts +248 -0
- package/dist/transform/transform.js +373 -0
- package/dist/transform.d.ts +10 -0
- package/dist/transform.js +10 -0
- package/dist/view/browser.js +39 -0
- package/dist/view/capturekeys.js +282 -0
- package/dist/view/clipboard.d.ts +8 -0
- package/dist/view/clipboard.js +245 -0
- package/dist/view/decoration.d.ts +339 -0
- package/dist/view/decoration.js +566 -0
- package/dist/view/dom.d.ts +18 -0
- package/dist/view/dom.js +140 -0
- package/dist/view/domchange.js +295 -0
- package/dist/view/domcoords.d.ts +22 -0
- package/dist/view/domcoords.js +448 -0
- package/dist/view/domobserver.d.ts +47 -0
- package/dist/view/domobserver.js +328 -0
- package/dist/view/errors.d.ts +18 -0
- package/dist/view/errors.js +21 -0
- package/dist/view/input.d.ts +58 -0
- package/dist/view/input.js +704 -0
- package/dist/view/selection.js +198 -0
- package/dist/view/view.d.ts +699 -0
- package/dist/view/view.js +623 -0
- package/dist/view/viewdesc.d.ts +236 -0
- package/dist/view/viewdesc.js +1205 -0
- package/dist/view-css.d.ts +43 -0
- package/dist/view-css.js +124 -0
- package/dist/view.d.ts +6 -0
- package/dist/view.js +4 -0
- package/package.json +200 -4
|
@@ -0,0 +1,280 @@
|
|
|
1
|
+
import * as Option from "effect/Option";
|
|
2
|
+
import * as S from "effect/Schema";
|
|
3
|
+
// src/transform/map.ts
|
|
4
|
+
/**
|
|
5
|
+
* Position maps: `StepMap`, `Mapping` and `MapResult`.
|
|
6
|
+
*
|
|
7
|
+
* @since 0.1.0
|
|
8
|
+
*/
|
|
9
|
+
const encodeRanges = S.encodeSync(S.fromJsonString(S.Array(S.Number)));
|
|
10
|
+
const lower16 = 65535;
|
|
11
|
+
const factor16 = Math.pow(2, 16);
|
|
12
|
+
const makeRecover = (index, offset) => index + offset * factor16;
|
|
13
|
+
const recoverIndex = (value) => value & lower16;
|
|
14
|
+
const recoverOffset = (value) => (value - (value & lower16)) / factor16;
|
|
15
|
+
const DEL_BEFORE = 1;
|
|
16
|
+
const DEL_AFTER = 2;
|
|
17
|
+
const DEL_ACROSS = 4;
|
|
18
|
+
const DEL_SIDE = 8;
|
|
19
|
+
/**
|
|
20
|
+
* An object representing a mapped position with extra information.
|
|
21
|
+
*
|
|
22
|
+
* @since 0.1.0
|
|
23
|
+
* @category models
|
|
24
|
+
*/
|
|
25
|
+
var MapResult = class {
|
|
26
|
+
/** @internal */
|
|
27
|
+
constructor(pos, delInfo, recover) {
|
|
28
|
+
this.pos = pos;
|
|
29
|
+
this.delInfo = delInfo;
|
|
30
|
+
this.recover = recover;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Tells you whether the position was deleted, that is, whether the
|
|
34
|
+
* step removed the token on the side queried (via the `assoc`)
|
|
35
|
+
* argument from the document.
|
|
36
|
+
*/
|
|
37
|
+
get deleted() {
|
|
38
|
+
return (this.delInfo & DEL_SIDE) > 0;
|
|
39
|
+
}
|
|
40
|
+
/** Tells you whether the token before the mapped position was deleted. */
|
|
41
|
+
get deletedBefore() {
|
|
42
|
+
return (this.delInfo & 5) > 0;
|
|
43
|
+
}
|
|
44
|
+
/** True when the token after the mapped position was deleted. */
|
|
45
|
+
get deletedAfter() {
|
|
46
|
+
return (this.delInfo & 6) > 0;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Tells whether any of the steps mapped through deletes across the
|
|
50
|
+
* position (including both the token before and after the position).
|
|
51
|
+
*/
|
|
52
|
+
get deletedAcross() {
|
|
53
|
+
return (this.delInfo & DEL_ACROSS) > 0;
|
|
54
|
+
}
|
|
55
|
+
};
|
|
56
|
+
/**
|
|
57
|
+
* A map describing the deletions and insertions made by a step, which
|
|
58
|
+
* can be used to find the correspondence between positions in the
|
|
59
|
+
* pre-step version of a document and the same position in the
|
|
60
|
+
* post-step version.
|
|
61
|
+
*
|
|
62
|
+
* @since 0.1.0
|
|
63
|
+
* @category models
|
|
64
|
+
*/
|
|
65
|
+
var StepMap = class StepMap {
|
|
66
|
+
/**
|
|
67
|
+
* Create a position map. The modifications to the document are
|
|
68
|
+
* represented as an array of numbers, in which each group of three
|
|
69
|
+
* represents a modified chunk as `[start, oldSize, newSize]`.
|
|
70
|
+
*/
|
|
71
|
+
constructor(ranges, inverted = false) {
|
|
72
|
+
this.ranges = ranges;
|
|
73
|
+
this.inverted = inverted;
|
|
74
|
+
if (!ranges.length && StepMap.empty) return StepMap.empty;
|
|
75
|
+
}
|
|
76
|
+
/** @internal */
|
|
77
|
+
recover(value) {
|
|
78
|
+
let diff = 0;
|
|
79
|
+
const index = recoverIndex(value);
|
|
80
|
+
if (!this.inverted) for (let i = 0; i < index; i++) diff += this.ranges[i * 3 + 2] - this.ranges[i * 3 + 1];
|
|
81
|
+
return this.ranges[index * 3] + diff + recoverOffset(value);
|
|
82
|
+
}
|
|
83
|
+
mapResult(pos, assoc = 1) {
|
|
84
|
+
return this._map(pos, assoc, false);
|
|
85
|
+
}
|
|
86
|
+
map(pos, assoc = 1) {
|
|
87
|
+
return this._map(pos, assoc, true);
|
|
88
|
+
}
|
|
89
|
+
/** @internal */
|
|
90
|
+
_map(pos, assoc, simple) {
|
|
91
|
+
let diff = 0;
|
|
92
|
+
const oldIndex = this.inverted ? 2 : 1, newIndex = this.inverted ? 1 : 2;
|
|
93
|
+
for (let i = 0; i < this.ranges.length; i += 3) {
|
|
94
|
+
const start = this.ranges[i] - (this.inverted ? diff : 0);
|
|
95
|
+
if (start > pos) break;
|
|
96
|
+
const oldSize = this.ranges[i + oldIndex], newSize = this.ranges[i + newIndex], end = start + oldSize;
|
|
97
|
+
if (pos <= end) {
|
|
98
|
+
const side = !oldSize ? assoc : pos === start ? -1 : pos === end ? 1 : assoc;
|
|
99
|
+
const result = start + diff + (side < 0 ? 0 : newSize);
|
|
100
|
+
if (simple) return result;
|
|
101
|
+
const recover = pos === (assoc < 0 ? start : end) ? null : makeRecover(i / 3, pos - start);
|
|
102
|
+
let del = 0;
|
|
103
|
+
if (oldSize) {
|
|
104
|
+
del |= pos === start ? DEL_AFTER : pos === end ? DEL_BEFORE : DEL_ACROSS;
|
|
105
|
+
if (assoc < 0 ? pos !== start : pos !== end) del |= DEL_SIDE;
|
|
106
|
+
}
|
|
107
|
+
return new MapResult(result, del, recover);
|
|
108
|
+
}
|
|
109
|
+
diff += newSize - oldSize;
|
|
110
|
+
}
|
|
111
|
+
return simple ? pos + diff : new MapResult(pos + diff, 0, null);
|
|
112
|
+
}
|
|
113
|
+
/** @internal */
|
|
114
|
+
touches(pos, recover) {
|
|
115
|
+
let diff = 0;
|
|
116
|
+
const index = recoverIndex(recover);
|
|
117
|
+
const oldIndex = this.inverted ? 2 : 1, newIndex = this.inverted ? 1 : 2;
|
|
118
|
+
for (let i = 0; i < this.ranges.length; i += 3) {
|
|
119
|
+
const start = this.ranges[i] - (this.inverted ? diff : 0);
|
|
120
|
+
if (start > pos) break;
|
|
121
|
+
const oldSize = this.ranges[i + oldIndex];
|
|
122
|
+
if (pos <= start + oldSize && i === index * 3) return true;
|
|
123
|
+
diff += this.ranges[i + newIndex] - oldSize;
|
|
124
|
+
}
|
|
125
|
+
return false;
|
|
126
|
+
}
|
|
127
|
+
/** Calls the given function on each of the changed ranges included in this map. */
|
|
128
|
+
forEach(f) {
|
|
129
|
+
const oldIndex = this.inverted ? 2 : 1, newIndex = this.inverted ? 1 : 2;
|
|
130
|
+
for (let i = 0, diff = 0; i < this.ranges.length; i += 3) {
|
|
131
|
+
const start = this.ranges[i], oldStart = start - (this.inverted ? diff : 0), newStart = start + (this.inverted ? 0 : diff);
|
|
132
|
+
const oldSize = this.ranges[i + oldIndex], newSize = this.ranges[i + newIndex];
|
|
133
|
+
f(oldStart, oldStart + oldSize, newStart, newStart + newSize);
|
|
134
|
+
diff += newSize - oldSize;
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Create an inverted version of this map. The result can be used to
|
|
139
|
+
* map positions in the post-step document to the pre-step document.
|
|
140
|
+
*/
|
|
141
|
+
invert() {
|
|
142
|
+
return new StepMap(this.ranges, !this.inverted);
|
|
143
|
+
}
|
|
144
|
+
/** @internal */
|
|
145
|
+
toString() {
|
|
146
|
+
return (this.inverted ? "-" : "") + encodeRanges(this.ranges);
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* Create a map that moves all positions by offset `n` (which may be
|
|
150
|
+
* negative). This can be useful when applying steps meant for a
|
|
151
|
+
* sub-document to a larger document, or vice-versa.
|
|
152
|
+
*/
|
|
153
|
+
static offset(n) {
|
|
154
|
+
return n === 0 ? StepMap.empty : new StepMap(n < 0 ? [
|
|
155
|
+
0,
|
|
156
|
+
-n,
|
|
157
|
+
0
|
|
158
|
+
] : [
|
|
159
|
+
0,
|
|
160
|
+
0,
|
|
161
|
+
n
|
|
162
|
+
]);
|
|
163
|
+
}
|
|
164
|
+
static {
|
|
165
|
+
this.empty = new StepMap([]);
|
|
166
|
+
}
|
|
167
|
+
};
|
|
168
|
+
/**
|
|
169
|
+
* A mapping represents a pipeline of zero or more step maps. It has
|
|
170
|
+
* special provisions for losslessly handling mapping positions through
|
|
171
|
+
* a series of steps in which some steps are inverted versions of
|
|
172
|
+
* earlier steps. (This comes up when ‘rebasing’ steps for collaboration
|
|
173
|
+
* or history management.)
|
|
174
|
+
*
|
|
175
|
+
* Mappings are mutable: `appendMap` and friends modify the mapping in
|
|
176
|
+
* place.
|
|
177
|
+
*
|
|
178
|
+
* @since 0.1.0
|
|
179
|
+
* @category models
|
|
180
|
+
*/
|
|
181
|
+
var Mapping = class Mapping {
|
|
182
|
+
/** Create a new mapping with the given position maps. */
|
|
183
|
+
constructor(maps, mirror, from = 0, to = maps ? maps.length : 0) {
|
|
184
|
+
this.mirror = mirror;
|
|
185
|
+
this.from = from;
|
|
186
|
+
this.to = to;
|
|
187
|
+
this._maps = maps || [];
|
|
188
|
+
this.ownData = !(maps || mirror);
|
|
189
|
+
}
|
|
190
|
+
/** The step maps in this mapping. */
|
|
191
|
+
get maps() {
|
|
192
|
+
return this._maps;
|
|
193
|
+
}
|
|
194
|
+
/** Create a mapping that maps only through a part of this one. */
|
|
195
|
+
slice(from = 0, to = this.maps.length) {
|
|
196
|
+
return new Mapping(this._maps, this.mirror, from, to);
|
|
197
|
+
}
|
|
198
|
+
/**
|
|
199
|
+
* Add a step map to the end of this mapping. If `mirrors` is given,
|
|
200
|
+
* it should be the index of the step map that is the mirror image of
|
|
201
|
+
* this one.
|
|
202
|
+
*/
|
|
203
|
+
appendMap(map, mirrors) {
|
|
204
|
+
if (!this.ownData) {
|
|
205
|
+
this._maps = this._maps.slice();
|
|
206
|
+
this.mirror = this.mirror && this.mirror.slice();
|
|
207
|
+
this.ownData = true;
|
|
208
|
+
}
|
|
209
|
+
this.to = this._maps.push(map);
|
|
210
|
+
if (mirrors != null) this.setMirror(this._maps.length - 1, mirrors);
|
|
211
|
+
}
|
|
212
|
+
/** Add all the step maps in a given mapping to this one (preserving mirroring information). */
|
|
213
|
+
appendMapping(mapping) {
|
|
214
|
+
for (let i = 0, startSize = this._maps.length; i < mapping._maps.length; i++) {
|
|
215
|
+
const mirr = mapping.getMirrorOrUndefined(i);
|
|
216
|
+
this.appendMap(mapping._maps[i], mirr != null && mirr < i ? startSize + mirr : void 0);
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
/**
|
|
220
|
+
* Finds the offset of the step map that mirrors the map at the given
|
|
221
|
+
* offset, in this mapping (as per the second argument to
|
|
222
|
+
* `appendMap`).
|
|
223
|
+
*/
|
|
224
|
+
getMirror(n) {
|
|
225
|
+
return Option.fromUndefinedOr(this.getMirrorOrUndefined(n));
|
|
226
|
+
}
|
|
227
|
+
/** @internal */
|
|
228
|
+
getMirrorOrUndefined(n) {
|
|
229
|
+
if (this.mirror) {
|
|
230
|
+
for (let i = 0; i < this.mirror.length; i++) if (this.mirror[i] === n) return this.mirror[i + (i % 2 ? -1 : 1)];
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
/** Record that the maps at offsets `n` and `m` mirror each other. */
|
|
234
|
+
setMirror(n, m) {
|
|
235
|
+
if (!this.mirror) this.mirror = [];
|
|
236
|
+
this.mirror.push(n, m);
|
|
237
|
+
}
|
|
238
|
+
/** Append the inverse of the given mapping to this one. */
|
|
239
|
+
appendMappingInverted(mapping) {
|
|
240
|
+
for (let i = mapping.maps.length - 1, totalSize = this._maps.length + mapping._maps.length; i >= 0; i--) {
|
|
241
|
+
const mirr = mapping.getMirrorOrUndefined(i);
|
|
242
|
+
this.appendMap(mapping._maps[i].invert(), mirr != null && mirr > i ? totalSize - mirr - 1 : void 0);
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
/** Create an inverted version of this mapping. */
|
|
246
|
+
invert() {
|
|
247
|
+
const inverse = new Mapping();
|
|
248
|
+
inverse.appendMappingInverted(this);
|
|
249
|
+
return inverse;
|
|
250
|
+
}
|
|
251
|
+
/** Map a position through this mapping. */
|
|
252
|
+
map(pos, assoc = 1) {
|
|
253
|
+
if (this.mirror) return this._map(pos, assoc, true);
|
|
254
|
+
for (let i = this.from; i < this.to; i++) pos = this._maps[i].map(pos, assoc);
|
|
255
|
+
return pos;
|
|
256
|
+
}
|
|
257
|
+
/** Map a position through this mapping, returning a mapping result. */
|
|
258
|
+
mapResult(pos, assoc = 1) {
|
|
259
|
+
return this._map(pos, assoc, false);
|
|
260
|
+
}
|
|
261
|
+
/** @internal */
|
|
262
|
+
_map(pos, assoc, simple) {
|
|
263
|
+
let delInfo = 0;
|
|
264
|
+
for (let i = this.from; i < this.to; i++) {
|
|
265
|
+
const result = this._maps[i].mapResult(pos, assoc);
|
|
266
|
+
if (result.recover != null) {
|
|
267
|
+
const corr = this.getMirrorOrUndefined(i);
|
|
268
|
+
if (corr != null && corr > i && corr < this.to) {
|
|
269
|
+
i = corr;
|
|
270
|
+
pos = this._maps[corr].recover(result.recover);
|
|
271
|
+
continue;
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
delInfo |= result.delInfo;
|
|
275
|
+
pos = result.pos;
|
|
276
|
+
}
|
|
277
|
+
return simple ? pos : new MapResult(pos, delInfo, null);
|
|
278
|
+
}
|
|
279
|
+
};
|
|
280
|
+
export { MapResult, Mapping, StepMap };
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import { Fragment } from "../model/fragment.js";
|
|
2
|
+
import { MarkType } from "../model/schema.js";
|
|
3
|
+
import { Slice } from "../model/replace.js";
|
|
4
|
+
import { pushMarkStep } from "./mark_set_step.js";
|
|
5
|
+
import { AddMarkStep, RemoveMarkStep } from "./mark_step.js";
|
|
6
|
+
import { ReplaceStep } from "./replace_step.js";
|
|
7
|
+
import * as Option from "effect/Option";
|
|
8
|
+
// src/transform/mark.ts
|
|
9
|
+
/**
|
|
10
|
+
* Mark-related transform implementations.
|
|
11
|
+
*
|
|
12
|
+
* @internal
|
|
13
|
+
*/
|
|
14
|
+
/** @internal */
|
|
15
|
+
function addMark(tr, from, to, mark) {
|
|
16
|
+
const added = [];
|
|
17
|
+
tr.doc.nodesBetween(from, to, (node, pos, parent) => {
|
|
18
|
+
if (!node.isInline) return;
|
|
19
|
+
const marks = node.marks;
|
|
20
|
+
if (!mark.isInSet(marks) && Option.isSome(parent) && parent.value.type.allowsMarkType(mark.type)) {
|
|
21
|
+
const start = Math.max(pos, from), end = Math.min(pos + node.nodeSize, to);
|
|
22
|
+
pushMarkStep(AddMarkStep, start, end, mark, added);
|
|
23
|
+
}
|
|
24
|
+
});
|
|
25
|
+
added.forEach((s) => tr.stepUnsafe(s));
|
|
26
|
+
}
|
|
27
|
+
/** @internal */
|
|
28
|
+
function removeMark(tr, from, to, mark) {
|
|
29
|
+
const matched = [];
|
|
30
|
+
let step = 0;
|
|
31
|
+
tr.doc.nodesBetween(from, to, (node, pos) => {
|
|
32
|
+
if (!node.isInline || !node.isAtom) return;
|
|
33
|
+
step++;
|
|
34
|
+
let toRemove = null;
|
|
35
|
+
if (mark instanceof MarkType) {
|
|
36
|
+
let set = node.marks, found;
|
|
37
|
+
const list = [];
|
|
38
|
+
while (found = mark.findInSet(set)) {
|
|
39
|
+
list.push(found);
|
|
40
|
+
set = found.removeFromSet(set);
|
|
41
|
+
}
|
|
42
|
+
if (list.length) toRemove = list;
|
|
43
|
+
} else if (mark) {
|
|
44
|
+
if (mark.isInSet(node.marks)) toRemove = [mark];
|
|
45
|
+
} else toRemove = node.marks;
|
|
46
|
+
if (toRemove && toRemove.length) {
|
|
47
|
+
const end = Math.min(pos + node.nodeSize, to);
|
|
48
|
+
for (let i = 0; i < toRemove.length; i++) {
|
|
49
|
+
const style = toRemove[i];
|
|
50
|
+
let found;
|
|
51
|
+
for (let j = 0; j < matched.length; j++) {
|
|
52
|
+
const m = matched[j];
|
|
53
|
+
if (m.step === step - 1 && style.eq(m.style)) found = m;
|
|
54
|
+
}
|
|
55
|
+
if (found) {
|
|
56
|
+
found.to = end;
|
|
57
|
+
found.step = step;
|
|
58
|
+
} else matched.push({
|
|
59
|
+
style,
|
|
60
|
+
from: Math.max(pos, from),
|
|
61
|
+
to: end,
|
|
62
|
+
step
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
});
|
|
67
|
+
matched.forEach((m) => tr.stepUnsafe(new RemoveMarkStep(m.from, m.to, m.style)));
|
|
68
|
+
}
|
|
69
|
+
/** @internal */
|
|
70
|
+
function clearIncompatible(tr, pos, parentType, match = parentType.contentMatch, clearNewlines = true) {
|
|
71
|
+
const node = tr.doc.nodeAtOrNull(pos);
|
|
72
|
+
const replSteps = [];
|
|
73
|
+
let cur = pos + 1;
|
|
74
|
+
for (let i = 0; i < node.childCount; i++) {
|
|
75
|
+
const child = node.content.content[i], end = cur + child.nodeSize;
|
|
76
|
+
const allowed = match.matchTypeOrNull(child.type);
|
|
77
|
+
if (!allowed) replSteps.push(new ReplaceStep(cur, end, Slice.empty));
|
|
78
|
+
else {
|
|
79
|
+
match = allowed;
|
|
80
|
+
for (let j = 0; j < child.marks.length; j++) if (!parentType.allowsMarkType(child.marks[j].type)) tr.stepUnsafe(new RemoveMarkStep(cur, end, child.marks[j]));
|
|
81
|
+
if (clearNewlines && child.isText && parentType.whitespace !== "pre") {
|
|
82
|
+
let m, slice;
|
|
83
|
+
const newline = /\r?\n|\r/g;
|
|
84
|
+
while (m = newline.exec(child.text)) {
|
|
85
|
+
if (!slice) slice = new Slice(Fragment.from(parentType.schema.textUnsafe(" ", parentType.allowedMarks(child.marks))), 0, 0);
|
|
86
|
+
replSteps.push(new ReplaceStep(cur + m.index, cur + m.index + m[0].length, slice));
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
cur = end;
|
|
91
|
+
}
|
|
92
|
+
if (!match.validEnd) {
|
|
93
|
+
const fill = match.fillBeforeOrNull(Fragment.empty, true);
|
|
94
|
+
tr.replaceUnsafe(cur, cur, new Slice(fill, 0, 0));
|
|
95
|
+
}
|
|
96
|
+
for (let i = replSteps.length - 1; i >= 0; i--) tr.stepUnsafe(replSteps[i]);
|
|
97
|
+
}
|
|
98
|
+
export { addMark, clearIncompatible, removeMark };
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { JSONError } from "../model/errors.js";
|
|
2
|
+
import { Step, StepResult } from "./step.js";
|
|
3
|
+
import * as Arr from "effect/Array";
|
|
4
|
+
import * as Option from "effect/Option";
|
|
5
|
+
// src/transform/mark_set_step.ts
|
|
6
|
+
/**
|
|
7
|
+
* Internal helpers for mark steps: `pushMarkStep` and the `MarkSetStep`
|
|
8
|
+
* that inverting a mark step can produce. Not part of the public API
|
|
9
|
+
* (prosemirror-transform keeps both private too).
|
|
10
|
+
*
|
|
11
|
+
* Ported from prosemirror-transform 1.12.3 / 1.12.4 (MIT, Marijn Haverbeke and others).
|
|
12
|
+
*
|
|
13
|
+
* @internal
|
|
14
|
+
*/
|
|
15
|
+
/**
|
|
16
|
+
* Append a mark step to `target`, extending the last step instead when
|
|
17
|
+
* it is of the same class, carries an equal mark, and ends at `from`.
|
|
18
|
+
*
|
|
19
|
+
* @internal
|
|
20
|
+
*/
|
|
21
|
+
function pushMarkStep(cls, from, to, mark, target) {
|
|
22
|
+
const last = target.at(-1);
|
|
23
|
+
if (last && last instanceof cls && last.to === from && last.mark.eq(mark)) target[target.length - 1] = new cls(last.from, to, mark);
|
|
24
|
+
else target.push(new cls(from, to, mark));
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* A group of mark steps applied as one, produced when inverting a mark
|
|
28
|
+
* step needs more than one step. Serialized as `"markSet"`.
|
|
29
|
+
*
|
|
30
|
+
* @internal
|
|
31
|
+
*/
|
|
32
|
+
var MarkSetStep = class MarkSetStep extends Step {
|
|
33
|
+
constructor(steps) {
|
|
34
|
+
super();
|
|
35
|
+
this.steps = steps;
|
|
36
|
+
}
|
|
37
|
+
apply(doc) {
|
|
38
|
+
return this.steps.reduce((result, step) => result.docOrNull === null ? result : step.apply(result.docOrNull), StepResult.ok(doc));
|
|
39
|
+
}
|
|
40
|
+
invert(doc) {
|
|
41
|
+
return new MarkSetStep(this.steps.map((s) => s.invert(doc)));
|
|
42
|
+
}
|
|
43
|
+
map(mapping) {
|
|
44
|
+
const result = Arr.getSomes(this.steps.map((step) => step.map(mapping)));
|
|
45
|
+
return result.length ? Option.some(new MarkSetStep(result)) : Option.none();
|
|
46
|
+
}
|
|
47
|
+
toJSON() {
|
|
48
|
+
return {
|
|
49
|
+
stepType: "markSet",
|
|
50
|
+
steps: this.steps.map((s) => s.toJSON())
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
/** @internal */
|
|
54
|
+
static fromJSONUnsafe(schema, json) {
|
|
55
|
+
if (!Array.isArray(json.steps) || !json.steps.every((s) => s && (s.stepType === "addMark" || s.stepType === "removeMark"))) throw new JSONError({ message: "Invalid JSON for MarkSetStep" });
|
|
56
|
+
return new MarkSetStep(json.steps.map((s) => Step.fromJSONUnsafe(schema, s)));
|
|
57
|
+
}
|
|
58
|
+
};
|
|
59
|
+
Step.jsonID("markSet", MarkSetStep);
|
|
60
|
+
/**
|
|
61
|
+
* The single step in `steps`, or a `MarkSetStep` grouping them.
|
|
62
|
+
*
|
|
63
|
+
* @internal
|
|
64
|
+
*/
|
|
65
|
+
const markStepGroup = (steps) => {
|
|
66
|
+
const [only] = steps;
|
|
67
|
+
return steps.length === 1 && only ? only : new MarkSetStep(steps);
|
|
68
|
+
};
|
|
69
|
+
export { MarkSetStep, markStepGroup, pushMarkStep };
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import { AnySchema } from "../model/schema.js";
|
|
2
|
+
import { Mark } from "../model/mark.js";
|
|
3
|
+
import { Node } from "../model/node.js";
|
|
4
|
+
import "../model.js";
|
|
5
|
+
import { Mappable } from "./map.js";
|
|
6
|
+
import { Step, StepJSON, StepResult } from "./step.js";
|
|
7
|
+
import * as Option from "effect/Option";
|
|
8
|
+
/**
|
|
9
|
+
* Add a mark to all inline content between two positions.
|
|
10
|
+
*
|
|
11
|
+
* @since 0.1.0
|
|
12
|
+
* @category steps
|
|
13
|
+
*/
|
|
14
|
+
export declare class AddMarkStep<Sc extends AnySchema = AnySchema> extends Step<Sc> {
|
|
15
|
+
/** The start of the marked range. */
|
|
16
|
+
readonly from: number;
|
|
17
|
+
/** The end of the marked range. */
|
|
18
|
+
readonly to: number;
|
|
19
|
+
/** The mark to add. */
|
|
20
|
+
readonly mark: Mark<Sc>;
|
|
21
|
+
/** Create a mark step. */
|
|
22
|
+
constructor(
|
|
23
|
+
/** The start of the marked range. */
|
|
24
|
+
from: number,
|
|
25
|
+
/** The end of the marked range. */
|
|
26
|
+
to: number,
|
|
27
|
+
/** The mark to add. */
|
|
28
|
+
mark: Mark<Sc>);
|
|
29
|
+
apply(doc: Node<Sc>): StepResult<Sc>;
|
|
30
|
+
invert(doc: Node<Sc>): Step<Sc>;
|
|
31
|
+
map(mapping: Mappable): Option.Option<Step<Sc>>;
|
|
32
|
+
merge(other: Step<Sc>): Option.Option<Step<Sc>>;
|
|
33
|
+
toJSON(): StepJSON;
|
|
34
|
+
/** @internal */
|
|
35
|
+
static fromJSONUnsafe<Sc extends AnySchema>(schema: Sc, json: any): AddMarkStep<Sc>;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Remove a mark from all inline content between two positions.
|
|
39
|
+
*
|
|
40
|
+
* @since 0.1.0
|
|
41
|
+
* @category steps
|
|
42
|
+
*/
|
|
43
|
+
export declare class RemoveMarkStep<Sc extends AnySchema = AnySchema> extends Step<Sc> {
|
|
44
|
+
/** The start of the unmarked range. */
|
|
45
|
+
readonly from: number;
|
|
46
|
+
/** The end of the unmarked range. */
|
|
47
|
+
readonly to: number;
|
|
48
|
+
/** The mark to remove. */
|
|
49
|
+
readonly mark: Mark<Sc>;
|
|
50
|
+
/** Create a mark-removing step. */
|
|
51
|
+
constructor(
|
|
52
|
+
/** The start of the unmarked range. */
|
|
53
|
+
from: number,
|
|
54
|
+
/** The end of the unmarked range. */
|
|
55
|
+
to: number,
|
|
56
|
+
/** The mark to remove. */
|
|
57
|
+
mark: Mark<Sc>);
|
|
58
|
+
apply(doc: Node<Sc>): StepResult<Sc>;
|
|
59
|
+
invert(doc: Node<Sc>): Step<Sc>;
|
|
60
|
+
map(mapping: Mappable): Option.Option<Step<Sc>>;
|
|
61
|
+
merge(other: Step<Sc>): Option.Option<Step<Sc>>;
|
|
62
|
+
toJSON(): StepJSON;
|
|
63
|
+
/** @internal */
|
|
64
|
+
static fromJSONUnsafe<Sc extends AnySchema>(schema: Sc, json: any): RemoveMarkStep<Sc>;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Add a mark to a specific node.
|
|
68
|
+
*
|
|
69
|
+
* @since 0.1.0
|
|
70
|
+
* @category steps
|
|
71
|
+
*/
|
|
72
|
+
export declare class AddNodeMarkStep<Sc extends AnySchema = AnySchema> extends Step<Sc> {
|
|
73
|
+
/** The position of the target node. */
|
|
74
|
+
readonly pos: number;
|
|
75
|
+
/** The mark to add. */
|
|
76
|
+
readonly mark: Mark<Sc>;
|
|
77
|
+
/** Create a node mark step. */
|
|
78
|
+
constructor(
|
|
79
|
+
/** The position of the target node. */
|
|
80
|
+
pos: number,
|
|
81
|
+
/** The mark to add. */
|
|
82
|
+
mark: Mark<Sc>);
|
|
83
|
+
apply(doc: Node<Sc>): StepResult<Sc>;
|
|
84
|
+
invert(doc: Node<Sc>): Step<Sc>;
|
|
85
|
+
map(mapping: Mappable): Option.Option<Step<Sc>>;
|
|
86
|
+
toJSON(): StepJSON;
|
|
87
|
+
/** @internal */
|
|
88
|
+
static fromJSONUnsafe<Sc extends AnySchema>(schema: Sc, json: any): AddNodeMarkStep<Sc>;
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Remove a mark from a specific node.
|
|
92
|
+
*
|
|
93
|
+
* @since 0.1.0
|
|
94
|
+
* @category steps
|
|
95
|
+
*/
|
|
96
|
+
export declare class RemoveNodeMarkStep<Sc extends AnySchema = AnySchema> extends Step<Sc> {
|
|
97
|
+
/** The position of the target node. */
|
|
98
|
+
readonly pos: number;
|
|
99
|
+
/** The mark to remove. */
|
|
100
|
+
readonly mark: Mark<Sc>;
|
|
101
|
+
/** Create a mark-removing step. */
|
|
102
|
+
constructor(
|
|
103
|
+
/** The position of the target node. */
|
|
104
|
+
pos: number,
|
|
105
|
+
/** The mark to remove. */
|
|
106
|
+
mark: Mark<Sc>);
|
|
107
|
+
apply(doc: Node<Sc>): StepResult<Sc>;
|
|
108
|
+
invert(doc: Node<Sc>): Step<Sc>;
|
|
109
|
+
map(mapping: Mappable): Option.Option<Step<Sc>>;
|
|
110
|
+
toJSON(): StepJSON;
|
|
111
|
+
/** @internal */
|
|
112
|
+
static fromJSONUnsafe<Sc extends AnySchema>(schema: Sc, json: any): RemoveNodeMarkStep<Sc>;
|
|
113
|
+
}
|