@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,566 @@
|
|
|
1
|
+
import * as Arr from "effect/Array";
|
|
2
|
+
// src/view/decoration.ts
|
|
3
|
+
/**
|
|
4
|
+
* Decorations: widgets, inline and node decorations, and decoration sets.
|
|
5
|
+
*
|
|
6
|
+
* @since 0.1.0
|
|
7
|
+
*/
|
|
8
|
+
function compareObjs(a, b) {
|
|
9
|
+
if (a == b) return true;
|
|
10
|
+
for (const p in a) if (a[p] !== b[p]) return false;
|
|
11
|
+
for (const p in b) if (!(p in a)) return false;
|
|
12
|
+
return true;
|
|
13
|
+
}
|
|
14
|
+
var FragmentCursor = class {
|
|
15
|
+
constructor(frag) {
|
|
16
|
+
this.frag = frag;
|
|
17
|
+
this.index = 0;
|
|
18
|
+
this.off = 0;
|
|
19
|
+
}
|
|
20
|
+
spansNode(from, to) {
|
|
21
|
+
const children = this.frag.content;
|
|
22
|
+
while (this.off <= from && this.index < children.length) {
|
|
23
|
+
const next = children[this.index];
|
|
24
|
+
if (!next) break;
|
|
25
|
+
if (this.off == from) return !next.isText && from + next.nodeSize == to;
|
|
26
|
+
this.off += next.nodeSize;
|
|
27
|
+
this.index++;
|
|
28
|
+
}
|
|
29
|
+
return false;
|
|
30
|
+
}
|
|
31
|
+
};
|
|
32
|
+
/** @internal */
|
|
33
|
+
var WidgetType = class WidgetType {
|
|
34
|
+
constructor(toDOM, spec) {
|
|
35
|
+
this.toDOM = toDOM;
|
|
36
|
+
this.spec = spec || noSpec;
|
|
37
|
+
this.side = this.spec.side || 0;
|
|
38
|
+
}
|
|
39
|
+
map(mapping, span, offset, oldOffset) {
|
|
40
|
+
const { deleted, pos } = mapping.mapResult(span.from + oldOffset, this.side < 0 ? -1 : 1);
|
|
41
|
+
return deleted ? null : new Decoration(pos - offset, pos - offset, this);
|
|
42
|
+
}
|
|
43
|
+
valid() {
|
|
44
|
+
return true;
|
|
45
|
+
}
|
|
46
|
+
eq(other) {
|
|
47
|
+
return this == other || other instanceof WidgetType && (this.spec.key && this.spec.key == other.spec.key || this.toDOM == other.toDOM && compareObjs(this.spec, other.spec));
|
|
48
|
+
}
|
|
49
|
+
destroy(node) {
|
|
50
|
+
if (this.spec.destroy) this.spec.destroy(node);
|
|
51
|
+
}
|
|
52
|
+
};
|
|
53
|
+
/** @internal */
|
|
54
|
+
var InlineType = class InlineType {
|
|
55
|
+
constructor(attrs, spec) {
|
|
56
|
+
this.attrs = attrs;
|
|
57
|
+
this.spec = spec || noSpec;
|
|
58
|
+
}
|
|
59
|
+
map(mapping, span, offset, oldOffset) {
|
|
60
|
+
const from = mapping.map(span.from + oldOffset, this.spec.inclusiveStart ? -1 : 1) - offset;
|
|
61
|
+
const to = mapping.map(span.to + oldOffset, this.spec.inclusiveEnd ? 1 : -1) - offset;
|
|
62
|
+
return from >= to ? null : new Decoration(from, to, this);
|
|
63
|
+
}
|
|
64
|
+
valid(_, span) {
|
|
65
|
+
return span.from < span.to;
|
|
66
|
+
}
|
|
67
|
+
eq(other) {
|
|
68
|
+
return this == other || other instanceof InlineType && compareObjs(this.attrs, other.attrs) && compareObjs(this.spec, other.spec);
|
|
69
|
+
}
|
|
70
|
+
static is(span) {
|
|
71
|
+
return span.type instanceof InlineType;
|
|
72
|
+
}
|
|
73
|
+
destroy() {}
|
|
74
|
+
};
|
|
75
|
+
/** @internal */
|
|
76
|
+
var NodeType = class NodeType {
|
|
77
|
+
constructor(attrs, spec) {
|
|
78
|
+
this.attrs = attrs;
|
|
79
|
+
this.spec = spec || noSpec;
|
|
80
|
+
}
|
|
81
|
+
map(mapping, span, offset, oldOffset) {
|
|
82
|
+
const from = mapping.mapResult(span.from + oldOffset, 1);
|
|
83
|
+
if (from.deleted) return null;
|
|
84
|
+
const to = mapping.mapResult(span.to + oldOffset, -1);
|
|
85
|
+
if (to.deleted || to.pos <= from.pos) return null;
|
|
86
|
+
return new Decoration(from.pos - offset, to.pos - offset, this);
|
|
87
|
+
}
|
|
88
|
+
valid(_node, span, cursor) {
|
|
89
|
+
return cursor.spansNode(span.from, span.to);
|
|
90
|
+
}
|
|
91
|
+
eq(other) {
|
|
92
|
+
return this == other || other instanceof NodeType && compareObjs(this.attrs, other.attrs) && compareObjs(this.spec, other.spec);
|
|
93
|
+
}
|
|
94
|
+
destroy() {}
|
|
95
|
+
};
|
|
96
|
+
/**
|
|
97
|
+
* Decoration objects can be provided to the view through the
|
|
98
|
+
* `decorations` prop. They come in several variants—see the static
|
|
99
|
+
* members of this class for details.
|
|
100
|
+
*
|
|
101
|
+
* @since 0.1.0
|
|
102
|
+
* @category models
|
|
103
|
+
*/
|
|
104
|
+
var Decoration = class Decoration {
|
|
105
|
+
/** @internal */
|
|
106
|
+
constructor(from, to, type) {
|
|
107
|
+
this.from = from;
|
|
108
|
+
this.to = to;
|
|
109
|
+
this.type = type;
|
|
110
|
+
}
|
|
111
|
+
/** @internal */
|
|
112
|
+
copy(from, to) {
|
|
113
|
+
return new Decoration(from, to, this.type);
|
|
114
|
+
}
|
|
115
|
+
/** @internal */
|
|
116
|
+
eq(other, offset = 0) {
|
|
117
|
+
return this.type.eq(other.type) && this.from + offset == other.from && this.to + offset == other.to;
|
|
118
|
+
}
|
|
119
|
+
/** @internal */
|
|
120
|
+
map(mapping, offset, oldOffset) {
|
|
121
|
+
return this.type.map(mapping, this, offset, oldOffset);
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Creates a widget decoration, which is a DOM node that's shown in
|
|
125
|
+
* the document at the given position. It is recommended that you
|
|
126
|
+
* delay rendering the widget by passing a function that will be
|
|
127
|
+
* called when the widget is actually drawn in a view, but you can
|
|
128
|
+
* also directly pass a DOM node. `getPos` can be used to find the
|
|
129
|
+
* widget's current document position.
|
|
130
|
+
*/
|
|
131
|
+
static widget(pos, toDOM, spec) {
|
|
132
|
+
return new Decoration(pos, pos, new WidgetType(toDOM, spec));
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Creates an inline decoration, which adds the given attributes to
|
|
136
|
+
* each inline node between `from` and `to`.
|
|
137
|
+
*/
|
|
138
|
+
static inline(from, to, attrs, spec) {
|
|
139
|
+
return new Decoration(from, to, new InlineType(attrs, spec));
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* Creates a node decoration. `from` and `to` should point precisely
|
|
143
|
+
* before and after a node in the document. That node, and only that
|
|
144
|
+
* node, will receive the given attributes.
|
|
145
|
+
*/
|
|
146
|
+
static node(from, to, attrs, spec) {
|
|
147
|
+
return new Decoration(from, to, new NodeType(attrs, spec));
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* The spec provided when creating this decoration. Can be useful if
|
|
151
|
+
* you've stored extra information in that object.
|
|
152
|
+
*/
|
|
153
|
+
get spec() {
|
|
154
|
+
return this.type.spec;
|
|
155
|
+
}
|
|
156
|
+
/** @internal */
|
|
157
|
+
get inline() {
|
|
158
|
+
return this.type instanceof InlineType;
|
|
159
|
+
}
|
|
160
|
+
/** @internal */
|
|
161
|
+
get widget() {
|
|
162
|
+
return this.type instanceof WidgetType;
|
|
163
|
+
}
|
|
164
|
+
};
|
|
165
|
+
const none = [];
|
|
166
|
+
const noSpec = {};
|
|
167
|
+
/**
|
|
168
|
+
* A collection of decorations, organized in such a way that the
|
|
169
|
+
* drawing algorithm can efficiently use and compare them. This is a
|
|
170
|
+
* persistent data structure—it is not modified, updates create a new
|
|
171
|
+
* value.
|
|
172
|
+
*
|
|
173
|
+
* @since 0.1.0
|
|
174
|
+
* @category models
|
|
175
|
+
*/
|
|
176
|
+
var DecorationSet = class DecorationSet {
|
|
177
|
+
/** @internal */
|
|
178
|
+
constructor(local, children) {
|
|
179
|
+
this.local = local.length ? local : none;
|
|
180
|
+
this.children = children.length ? children : none;
|
|
181
|
+
}
|
|
182
|
+
/**
|
|
183
|
+
* Create a set of decorations, using the structure of the given
|
|
184
|
+
* document. This will consume (modify) the `decorations` array, so you
|
|
185
|
+
* must make a copy if you want need to preserve that.
|
|
186
|
+
*/
|
|
187
|
+
static create(doc, decorations) {
|
|
188
|
+
return decorations.length ? buildTree(decorations, doc, 0, noSpec) : empty;
|
|
189
|
+
}
|
|
190
|
+
/**
|
|
191
|
+
* Find all decorations in this set which touch the given range
|
|
192
|
+
* (including decorations that start or end directly at the
|
|
193
|
+
* boundaries) and match the given predicate on their spec. When
|
|
194
|
+
* `start` and `end` are omitted, all decorations in the set are
|
|
195
|
+
* considered. When `predicate` isn't given, all decorations are
|
|
196
|
+
* assumed to match.
|
|
197
|
+
*/
|
|
198
|
+
find(start, end, predicate) {
|
|
199
|
+
const result = [];
|
|
200
|
+
this.findInner(start == null ? 0 : start, end == null ? 1e9 : end, result, 0, predicate);
|
|
201
|
+
return result;
|
|
202
|
+
}
|
|
203
|
+
findInner(start, end, result, offset, predicate) {
|
|
204
|
+
for (let i = 0; i < this.local.length; i++) {
|
|
205
|
+
const span = this.local[i];
|
|
206
|
+
if (span.from <= end && span.to >= start && (!predicate || predicate(span.spec))) result.push(span.copy(span.from + offset, span.to + offset));
|
|
207
|
+
}
|
|
208
|
+
for (let i = 0; i < this.children.length; i += 3) if (this.children[i] < end && this.children[i + 1] > start) {
|
|
209
|
+
const childOff = this.children[i] + 1;
|
|
210
|
+
this.children[i + 2].findInner(start - childOff, end - childOff, result, offset + childOff, predicate);
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
/** Map the set of decorations in response to a change in the document. */
|
|
214
|
+
map(mapping, doc, options) {
|
|
215
|
+
if (this == empty || Arr.isReadonlyArrayEmpty(mapping.maps)) return this;
|
|
216
|
+
return this.mapInner(mapping, doc, 0, 0, options || noSpec);
|
|
217
|
+
}
|
|
218
|
+
/** @internal */
|
|
219
|
+
mapInner(mapping, node, offset, oldOffset, options) {
|
|
220
|
+
let newLocal;
|
|
221
|
+
if (this.local.length) {
|
|
222
|
+
const cur = new FragmentCursor(node.content);
|
|
223
|
+
for (let i = 0; i < this.local.length; i++) {
|
|
224
|
+
const mapped = this.local[i].map(mapping, offset, oldOffset);
|
|
225
|
+
if (mapped && mapped.type.valid(node, mapped, cur)) (newLocal || (newLocal = [])).push(mapped);
|
|
226
|
+
else if (options.onRemove) options.onRemove(this.local[i].spec);
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
if (this.children.length) return mapChildren(this.children, newLocal || [], mapping, node, offset, oldOffset, options);
|
|
230
|
+
else return newLocal ? new DecorationSet(Arr.sort(newLocal, byPos), none) : empty;
|
|
231
|
+
}
|
|
232
|
+
/**
|
|
233
|
+
* Add the given array of decorations to the ones in the set, producing
|
|
234
|
+
* a new set. Consumes the `decorations` array. Needs access to the
|
|
235
|
+
* current document to create the appropriate tree structure.
|
|
236
|
+
*/
|
|
237
|
+
add(doc, decorations) {
|
|
238
|
+
if (!decorations.length) return this;
|
|
239
|
+
if (this == empty) return DecorationSet.create(doc, decorations);
|
|
240
|
+
return this.addInner(doc, decorations, 0);
|
|
241
|
+
}
|
|
242
|
+
addInner(doc, decorations, offset) {
|
|
243
|
+
let children, childIndex = 0;
|
|
244
|
+
doc.forEach((childNode, childOffset) => {
|
|
245
|
+
const baseOffset = childOffset + offset;
|
|
246
|
+
let found;
|
|
247
|
+
if (!(found = takeSpansForNode(decorations, childNode, baseOffset))) return;
|
|
248
|
+
if (!children) children = this.children.slice();
|
|
249
|
+
while (childIndex < children.length && children[childIndex] < childOffset) childIndex += 3;
|
|
250
|
+
if (children[childIndex] == childOffset) children[childIndex + 2] = children[childIndex + 2].addInner(childNode, found, baseOffset + 1);
|
|
251
|
+
else children.splice(childIndex, 0, childOffset, childOffset + childNode.nodeSize, buildTree(found, childNode, baseOffset + 1, noSpec));
|
|
252
|
+
childIndex += 3;
|
|
253
|
+
});
|
|
254
|
+
const local = moveSpans(childIndex ? withoutNulls(decorations) : decorations, -offset);
|
|
255
|
+
if (local.length) {
|
|
256
|
+
const cur = new FragmentCursor(doc.content);
|
|
257
|
+
for (let i = 0; i < local.length; i++) if (!local[i].type.valid(doc, local[i], cur)) local.splice(i--, 1);
|
|
258
|
+
}
|
|
259
|
+
return new DecorationSet(local.length ? Arr.sort(this.local.concat(local), byPos) : this.local, children || this.children);
|
|
260
|
+
}
|
|
261
|
+
/**
|
|
262
|
+
* Create a new set that contains the decorations in this set, minus
|
|
263
|
+
* the ones in the given array.
|
|
264
|
+
*/
|
|
265
|
+
remove(decorations) {
|
|
266
|
+
if (Arr.isReadonlyArrayEmpty(decorations) || this == empty) return this;
|
|
267
|
+
return this.removeInner(decorations, 0);
|
|
268
|
+
}
|
|
269
|
+
removeInner(decorations, offset) {
|
|
270
|
+
let children = this.children, local = this.local;
|
|
271
|
+
for (let i = 0; i < children.length; i += 3) {
|
|
272
|
+
let found;
|
|
273
|
+
const from = children[i] + offset, to = children[i + 1] + offset;
|
|
274
|
+
for (let j = 0, span; j < decorations.length; j++) if (span = decorations[j]) {
|
|
275
|
+
if (span.from > from && span.to < to) {
|
|
276
|
+
decorations[j] = null;
|
|
277
|
+
(found || (found = [])).push(span);
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
if (!found) continue;
|
|
281
|
+
if (children == this.children) children = this.children.slice();
|
|
282
|
+
const removed = children[i + 2].removeInner(found, from + 1);
|
|
283
|
+
if (removed != empty) children[i + 2] = removed;
|
|
284
|
+
else {
|
|
285
|
+
children.splice(i, 3);
|
|
286
|
+
i -= 3;
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
if (local.length) {
|
|
290
|
+
for (let i = 0, span; i < decorations.length; i++) if (span = decorations[i]) {
|
|
291
|
+
for (let j = 0; j < local.length; j++) if (local[j].eq(span, offset)) {
|
|
292
|
+
if (local == this.local) local = this.local.slice();
|
|
293
|
+
local.splice(j--, 1);
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
if (children == this.children && local == this.local) return this;
|
|
298
|
+
return local.length || children.length ? new DecorationSet(local, children) : empty;
|
|
299
|
+
}
|
|
300
|
+
forChild(offset, node) {
|
|
301
|
+
if (this == empty) return this;
|
|
302
|
+
if (node.isLeaf) return DecorationSet.empty;
|
|
303
|
+
let child, local;
|
|
304
|
+
for (let i = 0; i < this.children.length; i += 3) if (this.children[i] >= offset) {
|
|
305
|
+
if (this.children[i] == offset) child = this.children[i + 2];
|
|
306
|
+
break;
|
|
307
|
+
}
|
|
308
|
+
const start = offset + 1, end = start + node.content.size;
|
|
309
|
+
for (let i = 0; i < this.local.length; i++) {
|
|
310
|
+
const dec = this.local[i];
|
|
311
|
+
if (dec.from < end && dec.to > start && dec.type instanceof InlineType) {
|
|
312
|
+
const from = Math.max(start, dec.from) - start, to = Math.min(end, dec.to) - start;
|
|
313
|
+
if (from < to) (local || (local = [])).push(dec.copy(from, to));
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
if (local) {
|
|
317
|
+
const localSet = new DecorationSet(Arr.sort(local, byPos), none);
|
|
318
|
+
return child ? new DecorationGroup([localSet, child]) : localSet;
|
|
319
|
+
}
|
|
320
|
+
return child || empty;
|
|
321
|
+
}
|
|
322
|
+
/** @internal */
|
|
323
|
+
eq(other) {
|
|
324
|
+
if (this == other) return true;
|
|
325
|
+
if (!(other instanceof DecorationSet) || this.local.length != other.local.length || this.children.length != other.children.length) return false;
|
|
326
|
+
for (let i = 0; i < this.local.length; i++) if (!this.local[i].eq(other.local[i])) return false;
|
|
327
|
+
for (let i = 0; i < this.children.length; i += 3) if (this.children[i] != other.children[i] || this.children[i + 1] != other.children[i + 1] || !this.children[i + 2].eq(other.children[i + 2])) return false;
|
|
328
|
+
return true;
|
|
329
|
+
}
|
|
330
|
+
/** @internal */
|
|
331
|
+
locals(node) {
|
|
332
|
+
return removeOverlap(this.localsInner(node));
|
|
333
|
+
}
|
|
334
|
+
/** @internal */
|
|
335
|
+
localsInner(node) {
|
|
336
|
+
if (this == empty) return none;
|
|
337
|
+
if (node.inlineContent || !this.local.some(InlineType.is)) return this.local;
|
|
338
|
+
const result = [];
|
|
339
|
+
for (let i = 0; i < this.local.length; i++) if (!(this.local[i].type instanceof InlineType)) result.push(this.local[i]);
|
|
340
|
+
return result;
|
|
341
|
+
}
|
|
342
|
+
static {
|
|
343
|
+
this.empty = new DecorationSet([], []);
|
|
344
|
+
}
|
|
345
|
+
static {
|
|
346
|
+
this.removeOverlap = removeOverlap;
|
|
347
|
+
}
|
|
348
|
+
forEachSet(f) {
|
|
349
|
+
f(this);
|
|
350
|
+
}
|
|
351
|
+
};
|
|
352
|
+
const empty = DecorationSet.empty;
|
|
353
|
+
/** @internal */
|
|
354
|
+
var DecorationGroup = class DecorationGroup {
|
|
355
|
+
constructor(members) {
|
|
356
|
+
this.members = members;
|
|
357
|
+
}
|
|
358
|
+
map(mapping, doc) {
|
|
359
|
+
const mappedDecos = this.members.map((member) => member.map(mapping, doc, noSpec));
|
|
360
|
+
return DecorationGroup.from(mappedDecos);
|
|
361
|
+
}
|
|
362
|
+
forChild(offset, child) {
|
|
363
|
+
if (child.isLeaf) return DecorationSet.empty;
|
|
364
|
+
let found = [];
|
|
365
|
+
for (let i = 0; i < this.members.length; i++) {
|
|
366
|
+
const result = this.members[i].forChild(offset, child);
|
|
367
|
+
if (result == empty) continue;
|
|
368
|
+
if (result instanceof DecorationGroup) found = found.concat(result.members);
|
|
369
|
+
else found.push(result);
|
|
370
|
+
}
|
|
371
|
+
return DecorationGroup.from(found);
|
|
372
|
+
}
|
|
373
|
+
eq(other) {
|
|
374
|
+
if (!(other instanceof DecorationGroup) || other.members.length != this.members.length) return false;
|
|
375
|
+
for (let i = 0; i < this.members.length; i++) if (!this.members[i].eq(other.members[i])) return false;
|
|
376
|
+
return true;
|
|
377
|
+
}
|
|
378
|
+
locals(node) {
|
|
379
|
+
let result, sorted = true;
|
|
380
|
+
for (let i = 0; i < this.members.length; i++) {
|
|
381
|
+
const locals = this.members[i].localsInner(node);
|
|
382
|
+
if (!locals.length) continue;
|
|
383
|
+
if (!result) result = locals;
|
|
384
|
+
else {
|
|
385
|
+
if (sorted) {
|
|
386
|
+
result = result.slice();
|
|
387
|
+
sorted = false;
|
|
388
|
+
}
|
|
389
|
+
for (let j = 0; j < locals.length; j++) result.push(locals[j]);
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
return result ? removeOverlap(sorted ? result : Arr.sort(result, byPos)) : none;
|
|
393
|
+
}
|
|
394
|
+
static from(members) {
|
|
395
|
+
if (Arr.isReadonlyArrayEmpty(members)) return empty;
|
|
396
|
+
if (members.length == 1) return members[0];
|
|
397
|
+
return new DecorationGroup(members.every((m) => m instanceof DecorationSet) ? members : members.reduce((r, m) => r.concat(m instanceof DecorationSet ? m : m.members), []));
|
|
398
|
+
}
|
|
399
|
+
forEachSet(f) {
|
|
400
|
+
for (let i = 0; i < this.members.length; i++) this.members[i].forEachSet(f);
|
|
401
|
+
}
|
|
402
|
+
};
|
|
403
|
+
function mapChildren(oldChildren, newLocal, mapping, node, offset, oldOffset, options) {
|
|
404
|
+
const children = oldChildren.slice();
|
|
405
|
+
for (let i = 0, baseOffset = oldOffset; i < mapping.maps.length; i++) {
|
|
406
|
+
let moved = 0;
|
|
407
|
+
mapping.maps[i].forEach((oldStart, oldEnd, newStart, newEnd) => {
|
|
408
|
+
const dSize = newEnd - newStart - (oldEnd - oldStart);
|
|
409
|
+
for (let i = 0; i < children.length; i += 3) {
|
|
410
|
+
const end = children[i + 1];
|
|
411
|
+
if (end < 0 || oldStart > end + baseOffset - moved) continue;
|
|
412
|
+
const start = children[i] + baseOffset - moved;
|
|
413
|
+
if (oldEnd >= start) children[i + 1] = oldStart <= start ? -2 : -1;
|
|
414
|
+
else if (oldStart >= baseOffset && dSize) {
|
|
415
|
+
children[i] += dSize;
|
|
416
|
+
children[i + 1] += dSize;
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
moved += dSize;
|
|
420
|
+
});
|
|
421
|
+
baseOffset = mapping.maps[i].map(baseOffset, -1);
|
|
422
|
+
}
|
|
423
|
+
let mustRebuild = false;
|
|
424
|
+
for (let i = 0; i < children.length; i += 3) if (children[i + 1] < 0) {
|
|
425
|
+
if (children[i + 1] == -2) {
|
|
426
|
+
mustRebuild = true;
|
|
427
|
+
children[i + 1] = -1;
|
|
428
|
+
continue;
|
|
429
|
+
}
|
|
430
|
+
const from = mapping.map(oldChildren[i] + oldOffset), fromLocal = from - offset;
|
|
431
|
+
if (fromLocal < 0 || fromLocal >= node.content.size) {
|
|
432
|
+
mustRebuild = true;
|
|
433
|
+
continue;
|
|
434
|
+
}
|
|
435
|
+
const toLocal = mapping.map(oldChildren[i + 1] + oldOffset, -1) - offset;
|
|
436
|
+
const { index, offset: childOffset } = node.content.findIndex(fromLocal);
|
|
437
|
+
const childNode = node.content.content[index];
|
|
438
|
+
if (childNode && childOffset == fromLocal && childOffset + childNode.nodeSize == toLocal) {
|
|
439
|
+
const mapped = children[i + 2].mapInner(mapping, childNode, from + 1, oldChildren[i] + oldOffset + 1, options);
|
|
440
|
+
if (mapped != empty) {
|
|
441
|
+
children[i] = fromLocal;
|
|
442
|
+
children[i + 1] = toLocal;
|
|
443
|
+
children[i + 2] = mapped;
|
|
444
|
+
} else {
|
|
445
|
+
children[i + 1] = -2;
|
|
446
|
+
mustRebuild = true;
|
|
447
|
+
}
|
|
448
|
+
} else mustRebuild = true;
|
|
449
|
+
}
|
|
450
|
+
if (mustRebuild) {
|
|
451
|
+
const built = buildTree(mapAndGatherRemainingDecorations(children, oldChildren, newLocal, mapping, offset, oldOffset, options), node, 0, options);
|
|
452
|
+
newLocal = built.local;
|
|
453
|
+
for (let i = 0; i < children.length; i += 3) if (children[i + 1] < 0) {
|
|
454
|
+
children.splice(i, 3);
|
|
455
|
+
i -= 3;
|
|
456
|
+
}
|
|
457
|
+
for (let i = 0, j = 0; i < built.children.length; i += 3) {
|
|
458
|
+
const from = built.children[i];
|
|
459
|
+
while (j < children.length && children[j] < from) j += 3;
|
|
460
|
+
children.splice(j, 0, built.children[i], built.children[i + 1], built.children[i + 2]);
|
|
461
|
+
}
|
|
462
|
+
}
|
|
463
|
+
return new DecorationSet(Arr.sort(newLocal, byPos), children);
|
|
464
|
+
}
|
|
465
|
+
function moveSpans(spans, offset) {
|
|
466
|
+
if (!offset || !spans.length) return spans;
|
|
467
|
+
const result = [];
|
|
468
|
+
for (let i = 0; i < spans.length; i++) {
|
|
469
|
+
const span = spans[i];
|
|
470
|
+
result.push(new Decoration(span.from + offset, span.to + offset, span.type));
|
|
471
|
+
}
|
|
472
|
+
return result;
|
|
473
|
+
}
|
|
474
|
+
function mapAndGatherRemainingDecorations(children, oldChildren, decorations, mapping, offset, oldOffset, options) {
|
|
475
|
+
function gather(set, oldOffset) {
|
|
476
|
+
for (let i = 0; i < set.local.length; i++) {
|
|
477
|
+
const mapped = set.local[i].map(mapping, offset, oldOffset);
|
|
478
|
+
if (mapped) decorations.push(mapped);
|
|
479
|
+
else if (options.onRemove) options.onRemove(set.local[i].spec);
|
|
480
|
+
}
|
|
481
|
+
for (let i = 0; i < set.children.length; i += 3) gather(set.children[i + 2], set.children[i] + oldOffset + 1);
|
|
482
|
+
}
|
|
483
|
+
for (let i = 0; i < children.length; i += 3) if (children[i + 1] == -1) gather(children[i + 2], oldChildren[i] + oldOffset + 1);
|
|
484
|
+
return decorations;
|
|
485
|
+
}
|
|
486
|
+
function takeSpansForNode(spans, node, offset) {
|
|
487
|
+
if (node.isLeaf) return null;
|
|
488
|
+
const end = offset + node.nodeSize;
|
|
489
|
+
let found = null;
|
|
490
|
+
for (let i = 0, span; i < spans.length; i++) if ((span = spans[i]) && span.from > offset && span.to < end) {
|
|
491
|
+
(found || (found = [])).push(span);
|
|
492
|
+
spans[i] = null;
|
|
493
|
+
}
|
|
494
|
+
return found;
|
|
495
|
+
}
|
|
496
|
+
function withoutNulls(array) {
|
|
497
|
+
const result = [];
|
|
498
|
+
for (let i = 0; i < array.length; i++) if (array[i] != null) result.push(array[i]);
|
|
499
|
+
return result;
|
|
500
|
+
}
|
|
501
|
+
function buildTree(spans, node, offset, options) {
|
|
502
|
+
const children = [];
|
|
503
|
+
let hasNulls = false;
|
|
504
|
+
node.forEach((childNode, localStart) => {
|
|
505
|
+
const found = takeSpansForNode(spans, childNode, localStart + offset);
|
|
506
|
+
if (found) {
|
|
507
|
+
hasNulls = true;
|
|
508
|
+
const subtree = buildTree(found, childNode, offset + localStart + 1, options);
|
|
509
|
+
if (subtree != empty) children.push(localStart, localStart + childNode.nodeSize, subtree);
|
|
510
|
+
}
|
|
511
|
+
});
|
|
512
|
+
const locals = Arr.sort(moveSpans(hasNulls ? withoutNulls(spans) : spans, -offset), byPos);
|
|
513
|
+
if (locals.length) {
|
|
514
|
+
const cur = new FragmentCursor(node.content);
|
|
515
|
+
for (let i = 0; i < locals.length; i++) if (!locals[i].type.valid(node, locals[i], cur)) {
|
|
516
|
+
if (options.onRemove) options.onRemove(locals[i].spec);
|
|
517
|
+
locals.splice(i--, 1);
|
|
518
|
+
}
|
|
519
|
+
}
|
|
520
|
+
return locals.length || children.length ? new DecorationSet(locals, children) : empty;
|
|
521
|
+
}
|
|
522
|
+
const byPos = (a, b) => a.from < b.from ? -1 : a.from > b.from ? 1 : a.to < b.to ? -1 : a.to > b.to ? 1 : 0;
|
|
523
|
+
function removeOverlap(spans) {
|
|
524
|
+
let working = spans;
|
|
525
|
+
for (let i = 0; i < working.length - 1; i++) {
|
|
526
|
+
const span = working[i];
|
|
527
|
+
if (span.from != span.to) for (let j = i + 1; j < working.length; j++) {
|
|
528
|
+
const next = working[j];
|
|
529
|
+
if (next.from == span.from) {
|
|
530
|
+
if (next.to != span.to) {
|
|
531
|
+
if (working == spans) working = spans.slice();
|
|
532
|
+
working[j] = next.copy(next.from, span.to);
|
|
533
|
+
insertAhead(working, j + 1, next.copy(span.to, next.to));
|
|
534
|
+
}
|
|
535
|
+
continue;
|
|
536
|
+
} else {
|
|
537
|
+
if (next.from < span.to) {
|
|
538
|
+
if (working == spans) working = spans.slice();
|
|
539
|
+
working[i] = span.copy(span.from, next.from);
|
|
540
|
+
insertAhead(working, j, span.copy(next.from, span.to));
|
|
541
|
+
}
|
|
542
|
+
break;
|
|
543
|
+
}
|
|
544
|
+
}
|
|
545
|
+
}
|
|
546
|
+
return working;
|
|
547
|
+
}
|
|
548
|
+
function insertAhead(array, i, deco) {
|
|
549
|
+
while (i < array.length && byPos(deco, array[i]) > 0) i++;
|
|
550
|
+
array.splice(i, 0, deco);
|
|
551
|
+
}
|
|
552
|
+
/**
|
|
553
|
+
* Get the decorations associated with the current props of a view.
|
|
554
|
+
*
|
|
555
|
+
* @internal
|
|
556
|
+
*/
|
|
557
|
+
function viewDecorations(view) {
|
|
558
|
+
const found = [];
|
|
559
|
+
view.someProp("decorations", (f) => {
|
|
560
|
+
const result = f(view.state);
|
|
561
|
+
if (result && result != empty) found.push(result);
|
|
562
|
+
});
|
|
563
|
+
if (view.cursorWrapper) found.push(DecorationSet.create(view.state.doc, [view.cursorWrapper.deco]));
|
|
564
|
+
return DecorationGroup.from(found);
|
|
565
|
+
}
|
|
566
|
+
export { Decoration, DecorationGroup, DecorationSet, InlineType, NodeType, WidgetType, viewDecorations };
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { ViewDesc } from "./viewdesc.js";
|
|
2
|
+
declare global {
|
|
3
|
+
interface Node {
|
|
4
|
+
/** @internal */
|
|
5
|
+
pmViewDesc?: ViewDesc | undefined;
|
|
6
|
+
}
|
|
7
|
+
}
|
|
8
|
+
/** @internal */
|
|
9
|
+
export type DOMNode = globalThis.Node;
|
|
10
|
+
/** @internal */
|
|
11
|
+
export type DOMSelection = globalThis.Selection;
|
|
12
|
+
/** @internal */
|
|
13
|
+
export type DOMSelectionRange = {
|
|
14
|
+
focusNode: DOMNode | null;
|
|
15
|
+
focusOffset: number;
|
|
16
|
+
anchorNode: DOMNode | null;
|
|
17
|
+
anchorOffset: number;
|
|
18
|
+
};
|