@nerd-bible/wordgard 0.3.4 → 0.3.6
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/dist/command.d.ts +6 -6
- package/dist/command.js +32 -36
- package/dist/doc.d.ts +15 -1
- package/dist/doc.js +37 -13
- package/dist/editor.d.ts +16 -6
- package/dist/editor.js +352 -92
- package/dist/schema.js +93 -2
- package/dist/state.d.ts +4 -8
- package/dist/state.js +54 -21
- package/dist/table.js +1 -1
- package/package.json +1 -1
package/dist/editor.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { GardState, GardSelection, TextblockMap, BidiSpan, Transaction } from 'wordgard/state';
|
|
2
|
-
import { Attributes, Elt, Node, Leaf, ChangeSet, parse, Slice, Plot, serialize, Pos, ValidationError } from 'wordgard/doc';
|
|
2
|
+
import { Attributes, Elt, Node, Leaf, ChangeSet, parse, Slice, Plot, serialize, Pos, ValidationError, Mark } from 'wordgard/doc';
|
|
3
3
|
import { StyleModule } from 'style-mod';
|
|
4
4
|
import { findClusterBreak } from '@marijn/find-cluster-break';
|
|
5
5
|
import { enter, insertLineBreak, selectAll, undo, redo, transposeChars, Command, deleteUnit, deleteWord, deleteToLineEnd, moveByUnit, moveByLine, moveByWord, moveToLineSide, moveToDocSide, moveByPage, moveToTextblockSide, setAlignment, toggleUnderline, toggleEmphasis, toggleStrong, deleteLine, insertText, setDirection, deleteSelection, Menu, findWrappable, wrapBlockRange, autoJoinBlocks } from 'wordgard/command';
|
|
@@ -24,32 +24,40 @@ class Widget {
|
|
|
24
24
|
return Widget.Type.new(spec).of(null);
|
|
25
25
|
}
|
|
26
26
|
type;
|
|
27
|
+
render(wg) {
|
|
28
|
+
return this.type.render(this.value, wg);
|
|
29
|
+
}
|
|
27
30
|
get hasContent() { return false; }
|
|
28
31
|
}
|
|
29
32
|
;Widget = /*@__PURE__*/(function (Widget) {
|
|
30
33
|
class Type {
|
|
31
34
|
render;
|
|
32
35
|
eq;
|
|
33
|
-
|
|
36
|
+
propagateEvent;
|
|
34
37
|
connect;
|
|
35
38
|
disconnect;
|
|
36
39
|
inFlow;
|
|
40
|
+
editable;
|
|
37
41
|
constructor(
|
|
38
42
|
render,
|
|
39
43
|
eq,
|
|
40
|
-
|
|
44
|
+
propagateEvent,
|
|
41
45
|
connect,
|
|
42
46
|
disconnect,
|
|
43
|
-
inFlow
|
|
47
|
+
inFlow,
|
|
48
|
+
editable) {
|
|
44
49
|
this.render = render;
|
|
45
50
|
this.eq = eq;
|
|
46
|
-
this.
|
|
51
|
+
this.propagateEvent = propagateEvent;
|
|
47
52
|
this.connect = connect;
|
|
48
53
|
this.disconnect = disconnect;
|
|
49
54
|
this.inFlow = inFlow;
|
|
55
|
+
this.editable = editable;
|
|
50
56
|
}
|
|
51
57
|
static new(spec) {
|
|
52
|
-
|
|
58
|
+
let prop = spec.propagateEvent;
|
|
59
|
+
let propEvent = typeof prop == "function" ? prop : prop == null ? () => true : () => prop;
|
|
60
|
+
return new Type(spec.render, spec.eq || ((a, b) => a === b), propEvent, spec.connect ?? null, spec.disconnect ?? null, spec.inFlow !== false, spec.editable === true);
|
|
53
61
|
}
|
|
54
62
|
of(value) { return Widget.new(this, value); }
|
|
55
63
|
}
|
|
@@ -106,7 +114,7 @@ const Decoration = /*@__PURE__*/(function (Decoration) {
|
|
|
106
114
|
return tagWidget.of({
|
|
107
115
|
type: Node.Type.get(type),
|
|
108
116
|
place: getPlace(place),
|
|
109
|
-
widget: typeof widget == "function" ? memo(widget) :
|
|
117
|
+
widget: typeof widget == "function" ? memo(widget) : widget
|
|
110
118
|
});
|
|
111
119
|
}
|
|
112
120
|
Tag.widget = widget;
|
|
@@ -119,7 +127,7 @@ const Decoration = /*@__PURE__*/(function (Decoration) {
|
|
|
119
127
|
return {
|
|
120
128
|
type: tp,
|
|
121
129
|
place: p,
|
|
122
|
-
widget: typeof w == "function" ? memo(w) :
|
|
130
|
+
widget: typeof w == "function" ? memo(w) : w
|
|
123
131
|
};
|
|
124
132
|
});
|
|
125
133
|
}
|
|
@@ -221,6 +229,15 @@ const baseTagShape = /*@__PURE__*/memo((tag) => {
|
|
|
221
229
|
return addMarkAttributes(tag.is(Leaf.Text) ? Widget.EditableText.of(tag.param)
|
|
222
230
|
: tag.type.shape.create(tag.param), tag);
|
|
223
231
|
});
|
|
232
|
+
function renderMarks(marks, around) {
|
|
233
|
+
let result = addMarkAttributes(Elt.create("span", Attributes.none, [around]), Leaf.text(around, marks));
|
|
234
|
+
for (let i = marks.length - 1; i >= 0; i--) {
|
|
235
|
+
let mark = marks[i];
|
|
236
|
+
if (mark.type.element)
|
|
237
|
+
result = renderMarkWrapper(mark).fill([result]);
|
|
238
|
+
}
|
|
239
|
+
return result.toDOM();
|
|
240
|
+
}
|
|
224
241
|
class AttributeRangeDecoration extends Decoration.Range {
|
|
225
242
|
attribute;
|
|
226
243
|
value;
|
|
@@ -262,7 +279,7 @@ class ShapeDecoration extends Decoration.Point {
|
|
|
262
279
|
return this == other || other instanceof ShapeDecoration && other.shape.eq(this.shape);
|
|
263
280
|
}
|
|
264
281
|
get trackMode() { return "after"; }
|
|
265
|
-
get side() { return
|
|
282
|
+
get side() { return 1000000000; }
|
|
266
283
|
}
|
|
267
284
|
class WidgetDecoration extends Decoration.Point {
|
|
268
285
|
widget;
|
|
@@ -273,7 +290,7 @@ class WidgetDecoration extends Decoration.Point {
|
|
|
273
290
|
this.widget = widget;
|
|
274
291
|
this.side = side;
|
|
275
292
|
this.trackMode = trackMode;
|
|
276
|
-
if (side >=
|
|
293
|
+
if (side >= 1000000000)
|
|
277
294
|
throw new Error("Invalid widget side");
|
|
278
295
|
}
|
|
279
296
|
eq(other) {
|
|
@@ -297,7 +314,7 @@ class AttributeDecoration extends Decoration.Point {
|
|
|
297
314
|
selectorEq(other.selector, this.selector);
|
|
298
315
|
}
|
|
299
316
|
get trackMode() { return "after"; }
|
|
300
|
-
get side() { return
|
|
317
|
+
get side() { return 1000000000; }
|
|
301
318
|
}
|
|
302
319
|
class WrapperDecoration extends Decoration.Point {
|
|
303
320
|
elt;
|
|
@@ -312,7 +329,7 @@ class WrapperDecoration extends Decoration.Point {
|
|
|
312
329
|
selectorEq(other.selector, this.selector);
|
|
313
330
|
}
|
|
314
331
|
get trackMode() { return "after"; }
|
|
315
|
-
get side() { return
|
|
332
|
+
get side() { return 1000000000; }
|
|
316
333
|
}
|
|
317
334
|
const nodeSelectionDeco = /*@__PURE__*/Decoration.Point.attributes({ class: "wg-selected-node" });
|
|
318
335
|
function nodeSelection(state) {
|
|
@@ -494,9 +511,14 @@ class PointIterator {
|
|
|
494
511
|
get side() {
|
|
495
512
|
return this.done ? 1 : this.value.side;
|
|
496
513
|
}
|
|
497
|
-
goto(pos) {
|
|
514
|
+
goto(pos, inclusive) {
|
|
498
515
|
this.done = false;
|
|
499
|
-
|
|
516
|
+
let i = findAbove(this.set.positions, 0, pos - 1);
|
|
517
|
+
if (!inclusive) {
|
|
518
|
+
while (i < this.set.values.length && this.set.values[i].side < 1000000000)
|
|
519
|
+
i++;
|
|
520
|
+
}
|
|
521
|
+
this.fill(i);
|
|
500
522
|
}
|
|
501
523
|
}
|
|
502
524
|
function addDel(deleted, i) {
|
|
@@ -585,8 +607,8 @@ class RangeSet {
|
|
|
585
607
|
compareRange(fromA, b, fromB, len, change) {
|
|
586
608
|
let a = this, toB = fromB + len;
|
|
587
609
|
if (a != b || fromA != fromB) {
|
|
588
|
-
let iA = findAbove(a.
|
|
589
|
-
let iB = findAbove(b.
|
|
610
|
+
let iA = findAbove(a.to, 0, fromA - 1), lA = a.from.length;
|
|
611
|
+
let iB = findAbove(b.to, 0, fromB - 1), lB = b.from.length;
|
|
590
612
|
let off = fromB - fromA;
|
|
591
613
|
let sameVals = a.values == b.values;
|
|
592
614
|
for (;;) {
|
|
@@ -972,11 +994,14 @@ class DecoIterator {
|
|
|
972
994
|
pos;
|
|
973
995
|
rangeIter = [];
|
|
974
996
|
pointIter = [];
|
|
997
|
+
endWidgets;
|
|
975
998
|
constructor(state, decoSet) {
|
|
976
999
|
this.state = state;
|
|
977
1000
|
this.decoSet = decoSet;
|
|
978
1001
|
this.tagShapes = state.facet(tagShape);
|
|
979
1002
|
this.globalWidgets = state.facet(tagWidget);
|
|
1003
|
+
this.endWidgets = this.globalWidgets
|
|
1004
|
+
.some(w => (w.place == 1 || w.place == 3) && typeof w.widget == "function");
|
|
980
1005
|
this.globalWrappers = state.facet(tagWrapper);
|
|
981
1006
|
this.globalAttrs = state.facet(tagAttribute);
|
|
982
1007
|
this.pos = state.doc.resolve(0);
|
|
@@ -995,17 +1020,22 @@ class DecoIterator {
|
|
|
995
1020
|
widgets(tag, place, walker) {
|
|
996
1021
|
for (let src of this.globalWidgets) {
|
|
997
1022
|
if (src.place == place && tag.type == src.type) {
|
|
998
|
-
let widget = src.widget(tag);
|
|
1023
|
+
let widget = typeof src.widget == "function" ? src.widget(tag) : src.widget;
|
|
999
1024
|
if (widget)
|
|
1000
1025
|
walker.widget(widget, place == 0 || place == 3 ? 1 : -1);
|
|
1001
1026
|
}
|
|
1002
1027
|
}
|
|
1003
1028
|
}
|
|
1029
|
+
hasEndWidget(type) {
|
|
1030
|
+
return this.globalWidgets.some(tw => tw.type == type &&
|
|
1031
|
+
(tw.place == 3 || tw.place == 1) &&
|
|
1032
|
+
typeof tw.widget == "function");
|
|
1033
|
+
}
|
|
1004
1034
|
walk(from, inclusiveStart, to, walker) {
|
|
1005
1035
|
for (let i of this.rangeIter)
|
|
1006
1036
|
i.goto(from);
|
|
1007
1037
|
for (let i of this.pointIter)
|
|
1008
|
-
i.goto(
|
|
1038
|
+
i.goto(from, inclusiveStart);
|
|
1009
1039
|
let iter = new HeapIterator(this.rangeIter.filter(i => !i.done), this.pointIter.filter(i => !i.done), from, to);
|
|
1010
1040
|
let pos = this.pos.advance(from - this.pos.pos), started = inclusiveStart;
|
|
1011
1041
|
let atomParent;
|
|
@@ -1567,7 +1597,7 @@ class Tile {
|
|
|
1567
1597
|
let last = this.children.length - 1;
|
|
1568
1598
|
return last < 0 ? null : this.children[last];
|
|
1569
1599
|
}
|
|
1570
|
-
|
|
1600
|
+
ignoreEvent(event) { return false; }
|
|
1571
1601
|
get ignoreMutations() { return false; }
|
|
1572
1602
|
toString() { return this.dom.nodeName + (this.children.length ? `(${this.children})` : ""); }
|
|
1573
1603
|
sync() { }
|
|
@@ -1754,18 +1784,18 @@ class DocTile extends CompositeTile {
|
|
|
1754
1784
|
this.cursorWrapper = cursorWrapper;
|
|
1755
1785
|
this.decoSet = decoSet;
|
|
1756
1786
|
}
|
|
1757
|
-
static create(state, dom) {
|
|
1787
|
+
static create(state, dom, wg) {
|
|
1758
1788
|
return new DocTile(state, dom, null, { points: new Map, ranges: new Map })
|
|
1759
|
-
.updateRanges(state, getDecoSet(state), [0, state.doc.length],
|
|
1789
|
+
.updateRanges(state, getDecoSet(state), [0, state.doc.length], wg);
|
|
1760
1790
|
}
|
|
1761
1791
|
get isDoc() { return true; }
|
|
1762
1792
|
get node() { return this.state.doc; }
|
|
1763
|
-
update(state, changes,
|
|
1793
|
+
update(state, changes, wg, composition) {
|
|
1764
1794
|
let decoSet = getDecoSet(state);
|
|
1765
1795
|
let changed = findChangedRanges(this.state, this.decoSet, state, decoSet, changes);
|
|
1766
|
-
return this.updateRanges(state, decoSet, changed,
|
|
1796
|
+
return this.updateRanges(state, decoSet, changed, wg, composition);
|
|
1767
1797
|
}
|
|
1768
|
-
updateRanges(state, decoSet, sections,
|
|
1798
|
+
updateRanges(state, decoSet, sections, wg, composition) {
|
|
1769
1799
|
let wrapper = composition?.wrapCursor || null;
|
|
1770
1800
|
if ((!sections.length || sections.length == 2 && sections[1] == -1) && eqArray(wrapper, this.cursorWrapper))
|
|
1771
1801
|
return this;
|
|
@@ -1776,7 +1806,7 @@ class DocTile extends CompositeTile {
|
|
|
1776
1806
|
else
|
|
1777
1807
|
sections = separated;
|
|
1778
1808
|
}
|
|
1779
|
-
let builder = new ContentUpdate(state, this, new DecoIterator(state, decoSet), wrapper);
|
|
1809
|
+
let builder = new ContentUpdate(state, this, wg, new DecoIterator(state, decoSet), wrapper);
|
|
1780
1810
|
for (let i = 0, posB = 0, startCovered = false; i < sections.length;) {
|
|
1781
1811
|
let len = sections[i++], ins = sections[i++];
|
|
1782
1812
|
if (composition && posB == composition.fromB && ins >= 0) {
|
|
@@ -1802,7 +1832,7 @@ class DocTile extends CompositeTile {
|
|
|
1802
1832
|
}
|
|
1803
1833
|
let result = builder.finish();
|
|
1804
1834
|
result.sync();
|
|
1805
|
-
if (connected) {
|
|
1835
|
+
if (wg.connected) {
|
|
1806
1836
|
for (let ch of this.children)
|
|
1807
1837
|
ch.disconnect(builder.reused);
|
|
1808
1838
|
for (let tile of builder.toConnect)
|
|
@@ -2031,17 +2061,19 @@ class EltTile extends CompositeTile {
|
|
|
2031
2061
|
class WidgetTile extends Tile {
|
|
2032
2062
|
widget;
|
|
2033
2063
|
_node;
|
|
2034
|
-
constructor(widget, _node, flags, length = 0
|
|
2035
|
-
super(dom
|
|
2064
|
+
constructor(widget, _node, flags, dom, length = 0) {
|
|
2065
|
+
super(dom, flags);
|
|
2036
2066
|
this.widget = widget;
|
|
2037
2067
|
this._node = _node;
|
|
2038
2068
|
this.length = length;
|
|
2069
|
+
if (dom.nodeType == 1 && !widget.type.editable && dom.contentEditable == "inherit")
|
|
2070
|
+
dom.contentEditable = "false";
|
|
2039
2071
|
}
|
|
2040
2072
|
get isNodeOuter() { return !!this._node; }
|
|
2041
2073
|
get isAtom() { return true; }
|
|
2042
2074
|
get node() { return this._node; }
|
|
2043
2075
|
get children() { return noChildren; }
|
|
2044
|
-
|
|
2076
|
+
ignoreEvent(event) { return !this.widget.type.propagateEvent(event); }
|
|
2045
2077
|
connect() {
|
|
2046
2078
|
this.widget.type.connect?.(this.widget.value, this.dom);
|
|
2047
2079
|
}
|
|
@@ -2232,6 +2264,7 @@ class TilePointer {
|
|
|
2232
2264
|
}
|
|
2233
2265
|
class ContentUpdate {
|
|
2234
2266
|
state;
|
|
2267
|
+
wg;
|
|
2235
2268
|
deco;
|
|
2236
2269
|
old;
|
|
2237
2270
|
new;
|
|
@@ -2240,8 +2273,9 @@ class ContentUpdate {
|
|
|
2240
2273
|
keepWalker;
|
|
2241
2274
|
toConnect = [];
|
|
2242
2275
|
partialNode = null;
|
|
2243
|
-
constructor(state, old, deco, cursorWrapper) {
|
|
2276
|
+
constructor(state, old, wg, deco, cursorWrapper) {
|
|
2244
2277
|
this.state = state;
|
|
2278
|
+
this.wg = wg;
|
|
2245
2279
|
this.deco = deco;
|
|
2246
2280
|
this.old = new TilePointer(old, 0, null);
|
|
2247
2281
|
this.new = new DocTile(state, old.dom, cursorWrapper, deco.decoSet);
|
|
@@ -2321,6 +2355,54 @@ class ContentUpdate {
|
|
|
2321
2355
|
};
|
|
2322
2356
|
}
|
|
2323
2357
|
keep(len, includeStart, includeEnd) {
|
|
2358
|
+
let cut = [], end = this.posB + len;
|
|
2359
|
+
if (this.deco.endWidgets)
|
|
2360
|
+
for (let nw = this.new, { tile, index, parent } = this.old, pos = this.posB; pos < end;) {
|
|
2361
|
+
if (tile instanceof TextTile) {
|
|
2362
|
+
pos += tile.length - index;
|
|
2363
|
+
({ tile, index, parent } = parent);
|
|
2364
|
+
index++;
|
|
2365
|
+
}
|
|
2366
|
+
else if (index < tile.children.length) {
|
|
2367
|
+
pos += tile.children[index].length;
|
|
2368
|
+
index++;
|
|
2369
|
+
}
|
|
2370
|
+
else {
|
|
2371
|
+
if (tile.node) {
|
|
2372
|
+
while (!nw.node && nw.parent)
|
|
2373
|
+
nw = nw.parent;
|
|
2374
|
+
if (!nw.parent)
|
|
2375
|
+
break;
|
|
2376
|
+
if (!nw.node.tag.eq(tile.node.tag) &&
|
|
2377
|
+
(this.deco.hasEndWidget(tile.node.type) || this.deco.hasEndWidget(nw.node.type)))
|
|
2378
|
+
cut.push(pos);
|
|
2379
|
+
nw = nw.parent;
|
|
2380
|
+
if (!nw)
|
|
2381
|
+
break;
|
|
2382
|
+
pos++;
|
|
2383
|
+
}
|
|
2384
|
+
if (!parent)
|
|
2385
|
+
break;
|
|
2386
|
+
({ tile, index, parent } = parent);
|
|
2387
|
+
index++;
|
|
2388
|
+
}
|
|
2389
|
+
}
|
|
2390
|
+
for (let i = cut.length; i;) {
|
|
2391
|
+
let from = cut[--i], to = Math.min(from + 1, includeEnd ? end : end - 1);
|
|
2392
|
+
while (i && cut[i - 1] == from - 1) {
|
|
2393
|
+
from--;
|
|
2394
|
+
i--;
|
|
2395
|
+
}
|
|
2396
|
+
if (from > this.posB)
|
|
2397
|
+
this.keepInner(from - this.posB, includeStart, false);
|
|
2398
|
+
this.update(to - from, true);
|
|
2399
|
+
includeStart = false;
|
|
2400
|
+
len = end - to;
|
|
2401
|
+
}
|
|
2402
|
+
if (len)
|
|
2403
|
+
this.keepInner(len, includeStart, includeEnd);
|
|
2404
|
+
}
|
|
2405
|
+
keepInner(len, includeStart, includeEnd) {
|
|
2324
2406
|
if (!includeStart) {
|
|
2325
2407
|
this.old = this.old.walk(0, 1);
|
|
2326
2408
|
this.openOldWrappers();
|
|
@@ -2343,7 +2425,7 @@ class ContentUpdate {
|
|
|
2343
2425
|
if (mark.type.element) {
|
|
2344
2426
|
this.openWrapper(renderMarkWrapper(mark), mark.spanning, false);
|
|
2345
2427
|
}
|
|
2346
|
-
this.new.addChild(new WidgetTile(imgHack, null, 16 | 32));
|
|
2428
|
+
this.new.addChild(new WidgetTile(imgHack, null, 16 | 32, imgHack.render(this.wg)));
|
|
2347
2429
|
return;
|
|
2348
2430
|
}
|
|
2349
2431
|
let found = [];
|
|
@@ -2460,7 +2542,7 @@ class ContentUpdate {
|
|
|
2460
2542
|
: endOld && this.posB == end ? endOld.matchingWidget(widget, sideFlag, this.reused)
|
|
2461
2543
|
: null;
|
|
2462
2544
|
if (!tile) {
|
|
2463
|
-
tile = new WidgetTile(widget, null, 16 | sideFlag,
|
|
2545
|
+
tile = new WidgetTile(widget, null, 16 | sideFlag, widget.render(this.wg));
|
|
2464
2546
|
if (widget.type.connect)
|
|
2465
2547
|
this.toConnect.push(tile);
|
|
2466
2548
|
}
|
|
@@ -2497,6 +2579,9 @@ class ContentUpdate {
|
|
|
2497
2579
|
}
|
|
2498
2580
|
buildNodeShape(node, shape, reuse, afterContent = 0) {
|
|
2499
2581
|
if (shape instanceof Elt) {
|
|
2582
|
+
if (node && !shape.hasContent && Attributes.get(shape.attrs, "contenteditable") == null &&
|
|
2583
|
+
!/^(br|hr|img|input|wbr)$/i.test(shape.tagName))
|
|
2584
|
+
shape = Elt.create(shape.tagName, Attributes.merge(shape.attrs, ["contenteditable", "false"]), shape.children);
|
|
2500
2585
|
let reusable, dom, strict = true;
|
|
2501
2586
|
if (reusable = this.findReusableTile(shape, reuse, strict) || this.findReusableTile(shape, reuse, strict = false)) {
|
|
2502
2587
|
this.reused.set(reusable, 2);
|
|
@@ -2528,21 +2613,26 @@ class ContentUpdate {
|
|
|
2528
2613
|
dom = reusable.dom;
|
|
2529
2614
|
}
|
|
2530
2615
|
let flags = (node ? 512 : 16 | 1) | afterContent;
|
|
2531
|
-
let tile = new WidgetTile(shape, node, flags, node ? node.length : 0
|
|
2616
|
+
let tile = new WidgetTile(shape, node, flags, dom || shape.render(this.wg), node ? node.length : 0);
|
|
2532
2617
|
if (shape.type.connect)
|
|
2533
2618
|
this.toConnect.push(tile);
|
|
2534
2619
|
return tile;
|
|
2535
2620
|
}
|
|
2536
2621
|
}
|
|
2537
|
-
|
|
2622
|
+
ensureHackNode() {
|
|
2538
2623
|
let tile = this.new;
|
|
2539
2624
|
if (!tile.isPlotContent)
|
|
2540
2625
|
return;
|
|
2541
2626
|
while (tile.isNodeInner)
|
|
2542
2627
|
tile = tile.parent;
|
|
2543
2628
|
let node = tile.node;
|
|
2544
|
-
if (!node || !node.isPlot || !node.isTextblock)
|
|
2629
|
+
if (!node || !node.isPlot || !(node.isTextblock || node.type.isInline))
|
|
2545
2630
|
return;
|
|
2631
|
+
if (node.type.isInline) {
|
|
2632
|
+
if (!this.new.children.length)
|
|
2633
|
+
this.new.addChild(new WidgetTile(imgHack, null, 16 | 64, imgHack.render(this.wg)));
|
|
2634
|
+
return;
|
|
2635
|
+
}
|
|
2546
2636
|
let hasHack = -1, needsHack = true;
|
|
2547
2637
|
for (let parent = this.new, i = parent.children.length;;) {
|
|
2548
2638
|
if (i > 0) {
|
|
@@ -2576,11 +2666,11 @@ class ContentUpdate {
|
|
|
2576
2666
|
this.new.children.splice(hasHack, 1);
|
|
2577
2667
|
}
|
|
2578
2668
|
else if (needsHack) {
|
|
2579
|
-
this.new.addChild(new WidgetTile(brHack, null, 16 | 64,
|
|
2669
|
+
this.new.addChild(new WidgetTile(brHack, null, 16 | 64, brHack.render(this.wg)));
|
|
2580
2670
|
}
|
|
2581
2671
|
}
|
|
2582
2672
|
up() {
|
|
2583
|
-
this.
|
|
2673
|
+
this.ensureHackNode();
|
|
2584
2674
|
this.new = this.new.parent;
|
|
2585
2675
|
}
|
|
2586
2676
|
leaveNode() {
|
|
@@ -2663,7 +2753,7 @@ class ContentUpdate {
|
|
|
2663
2753
|
finish() {
|
|
2664
2754
|
while (!(this.new instanceof DocTile))
|
|
2665
2755
|
this.up();
|
|
2666
|
-
this.
|
|
2756
|
+
this.ensureHackNode();
|
|
2667
2757
|
return this.new;
|
|
2668
2758
|
}
|
|
2669
2759
|
}
|
|
@@ -2704,10 +2794,16 @@ function updateAttributes(dom, a, b) {
|
|
|
2704
2794
|
return changed;
|
|
2705
2795
|
}
|
|
2706
2796
|
const brHack = /*@__PURE__*/Widget.create({
|
|
2707
|
-
render() { return document.createElement("br"); }
|
|
2797
|
+
render() { return document.createElement("br"); },
|
|
2798
|
+
editable: true
|
|
2708
2799
|
});
|
|
2709
2800
|
const imgHack = /*@__PURE__*/Widget.create({
|
|
2710
|
-
render() {
|
|
2801
|
+
render() {
|
|
2802
|
+
let img = document.createElement("img");
|
|
2803
|
+
img.className = "wg-buffer";
|
|
2804
|
+
return img;
|
|
2805
|
+
},
|
|
2806
|
+
editable: true
|
|
2711
2807
|
});
|
|
2712
2808
|
function separateComposition(sections, comp) {
|
|
2713
2809
|
let result = [], { fromB, toB } = comp;
|
|
@@ -2739,18 +2835,26 @@ function separateComposition(sections, comp) {
|
|
|
2739
2835
|
return result;
|
|
2740
2836
|
}
|
|
2741
2837
|
|
|
2838
|
+
class Coords {
|
|
2839
|
+
ref;
|
|
2840
|
+
rect;
|
|
2841
|
+
constructor(ref, rect) {
|
|
2842
|
+
this.ref = ref;
|
|
2843
|
+
this.rect = rect;
|
|
2844
|
+
}
|
|
2845
|
+
}
|
|
2742
2846
|
function coordsAtPos(wg, pos, assoc) {
|
|
2743
2847
|
let { offset, tile, pos: tilePos } = wg.docTile.resolve(pos, assoc);
|
|
2744
2848
|
if (tile instanceof TextTile) {
|
|
2745
2849
|
let node = tile.dom, len = node.nodeValue.length;
|
|
2746
2850
|
if (!len)
|
|
2747
|
-
return singleRect(textRange(node, 0, 0), 1);
|
|
2851
|
+
return new Coords(tile, singleRect(textRange(node, 0, 0), 1));
|
|
2748
2852
|
let from = offset, to = offset, side = assoc < 0 && from || from == len ? 1 : -1;
|
|
2749
2853
|
if (side < 0)
|
|
2750
2854
|
to++;
|
|
2751
2855
|
else
|
|
2752
2856
|
from--;
|
|
2753
|
-
return flattenV(singleRect(textRange(node, from, to), side, true), (side < 0) == ltrAt(wg.state, pos, assoc));
|
|
2857
|
+
return new Coords(tile, flattenV(singleRect(textRange(node, from, to), side, true), (side < 0) == ltrAt(wg.state, pos, assoc)));
|
|
2754
2858
|
}
|
|
2755
2859
|
let tagTile = tile;
|
|
2756
2860
|
while (!tagTile.node)
|
|
@@ -2761,10 +2865,10 @@ function coordsAtPos(wg, pos, assoc) {
|
|
|
2761
2865
|
if (tile.widget.type.inFlow) {
|
|
2762
2866
|
let rect = singleRect(tile.dom, after ? 1 : -1);
|
|
2763
2867
|
if (rect.width || rect.height)
|
|
2764
|
-
return horizontal ? flattenH(rect, !after) : flattenV(rect, ltrAt(wg.state, pos, 1) == !after);
|
|
2868
|
+
return new Coords(tile, horizontal ? flattenH(rect, !after) : flattenV(rect, ltrAt(wg.state, pos, 1) == !after));
|
|
2765
2869
|
}
|
|
2766
2870
|
if (!tile.parent)
|
|
2767
|
-
return new DOMRect;
|
|
2871
|
+
return new Coords(tile, new DOMRect);
|
|
2768
2872
|
offset = tile.parent.children.indexOf(tile) + (after ? 1 : 0);
|
|
2769
2873
|
tile = tile.parent;
|
|
2770
2874
|
assoc = after ? 1 : -1;
|
|
@@ -2776,7 +2880,7 @@ function coordsAtPos(wg, pos, assoc) {
|
|
|
2776
2880
|
continue;
|
|
2777
2881
|
let rect = singleRect(before.dom, 1);
|
|
2778
2882
|
if (rect.width || rect.height)
|
|
2779
|
-
return horizontal ? flattenH(rect, false) : flattenV(rect, !ltrAt(wg.state, pos, 1));
|
|
2883
|
+
return new Coords(before, horizontal ? flattenH(rect, false) : flattenV(rect, !ltrAt(wg.state, pos, 1)));
|
|
2780
2884
|
}
|
|
2781
2885
|
}
|
|
2782
2886
|
else { for (let i = offset; i < tile.children.length; i++) {
|
|
@@ -2785,12 +2889,12 @@ function coordsAtPos(wg, pos, assoc) {
|
|
|
2785
2889
|
continue;
|
|
2786
2890
|
let rect = singleRect(after.dom, -1);
|
|
2787
2891
|
if (rect.width || rect.height)
|
|
2788
|
-
return horizontal ? flattenH(rect, true) : flattenV(rect, ltrAt(wg.state, pos, 1));
|
|
2892
|
+
return new Coords(after, horizontal ? flattenH(rect, true) : flattenV(rect, ltrAt(wg.state, pos, 1)));
|
|
2789
2893
|
}
|
|
2790
2894
|
}
|
|
2791
2895
|
}
|
|
2792
2896
|
let rect = singleRect(tile.dom, -assoc);
|
|
2793
|
-
return horizontal ? flattenH(rect, assoc < 0) : flattenV(rect, assoc < 0);
|
|
2897
|
+
return new Coords(tile, horizontal ? flattenH(rect, assoc < 0) : flattenV(rect, assoc < 0));
|
|
2794
2898
|
}
|
|
2795
2899
|
function flattenV(rect, left) {
|
|
2796
2900
|
return rect.width ? new DOMRect(left ? rect.left : rect.right, rect.top, 0, rect.height) : rect;
|
|
@@ -3063,6 +3167,13 @@ const baseStyles = /*@__PURE__*/buildTheme("." + styleID, {
|
|
|
3063
3167
|
borderLeft: "1.8px solid currentColor",
|
|
3064
3168
|
marginLeft: "-0.9px",
|
|
3065
3169
|
},
|
|
3170
|
+
".wg-cursor-v.wg-cursor-bold": {
|
|
3171
|
+
borderLeft: "2.4px solid currentColor",
|
|
3172
|
+
marginLeft: "-1.2px",
|
|
3173
|
+
},
|
|
3174
|
+
".wg-cursor-v.wg-cursor-italic": {
|
|
3175
|
+
transform: "rotate(10deg)"
|
|
3176
|
+
},
|
|
3066
3177
|
".wg-cursor-h": {
|
|
3067
3178
|
borderTop: "1.8px solid currentColor",
|
|
3068
3179
|
marginTop: "-0.9px",
|
|
@@ -3073,6 +3184,10 @@ const baseStyles = /*@__PURE__*/buildTheme("." + styleID, {
|
|
|
3073
3184
|
backgroundColor: "transparent"
|
|
3074
3185
|
}
|
|
3075
3186
|
},
|
|
3187
|
+
".wg-buffer": {
|
|
3188
|
+
verticalAlign: "bottom",
|
|
3189
|
+
height: "1em",
|
|
3190
|
+
},
|
|
3076
3191
|
"wg-placeholder": {
|
|
3077
3192
|
opacity: "0.6",
|
|
3078
3193
|
display: "inline-block",
|
|
@@ -3885,7 +4000,7 @@ class InputState {
|
|
|
3885
4000
|
let inText = node.nodeType == 3;
|
|
3886
4001
|
let ref = this.wg.docTile.posFromDOM(node, inText ? 0 : offset);
|
|
3887
4002
|
let dir = -1;
|
|
3888
|
-
let textBefore = textNodeBefore(node.parentNode, domIndex(node));
|
|
4003
|
+
let textBefore = node.parentNode && textNodeBefore(node.parentNode, domIndex(node));
|
|
3889
4004
|
let prev = textBefore && Tile.get(textBefore);
|
|
3890
4005
|
if (prev instanceof TextTile && prev.length < prev.dom.nodeValue.length)
|
|
3891
4006
|
dir = 1;
|
|
@@ -3908,8 +4023,8 @@ class InputState {
|
|
|
3908
4023
|
let type = event.inputType, range;
|
|
3909
4024
|
let { wg } = this, sel = wg.state.selection;
|
|
3910
4025
|
if (data.domRange) {
|
|
3911
|
-
range = { from: this.domMapping.mapPos(data.domRange.from),
|
|
3912
|
-
to: this.domMapping.mapPos(data.domRange.to) };
|
|
4026
|
+
range = { from: snapToSel(wg.state, this.domMapping.mapPos(data.domRange.from)),
|
|
4027
|
+
to: snapToSel(wg.state, this.domMapping.mapPos(data.domRange.to)) };
|
|
3913
4028
|
if (!this.domMapping.empty && type == "insertText" && !this.composing && range.from == range.to) {
|
|
3914
4029
|
let fromMax = this.domMapping.mapPos(data.domRange.from, 1);
|
|
3915
4030
|
if (range.from <= sel.from && fromMax >= sel.to)
|
|
@@ -3918,7 +4033,7 @@ class InputState {
|
|
|
3918
4033
|
}
|
|
3919
4034
|
let command = inputTypeCommands[type];
|
|
3920
4035
|
if ((type == "deleteContentBackward" || type == "deleteContentForward") && range &&
|
|
3921
|
-
(sel.empty
|
|
4036
|
+
range.from != range.to && (sel.empty
|
|
3922
4037
|
? !isSingleChar(this.domDoc, data.domRange.from, data.domRange.to) ||
|
|
3923
4038
|
sel.head != (type == "deleteContentBackward" ? range.to : range.from)
|
|
3924
4039
|
: sel.from != range.from || sel.to != range.to)) {
|
|
@@ -4011,6 +4126,39 @@ class InputState {
|
|
|
4011
4126
|
this.mouseSelection.disconnect();
|
|
4012
4127
|
}
|
|
4013
4128
|
}
|
|
4129
|
+
function snapToSel(state, pos) {
|
|
4130
|
+
let { head, anchor } = state.selection;
|
|
4131
|
+
if (pos == head || pos == anchor)
|
|
4132
|
+
return pos;
|
|
4133
|
+
if (onlyInlineNodeBoundsBetween(state.doc, head, pos))
|
|
4134
|
+
return head;
|
|
4135
|
+
if (head != anchor && onlyInlineNodeBoundsBetween(state.doc, head, pos))
|
|
4136
|
+
return anchor;
|
|
4137
|
+
return pos;
|
|
4138
|
+
}
|
|
4139
|
+
function onlyInlineNodeBoundsBetween(doc, a, b) {
|
|
4140
|
+
if (a > b)
|
|
4141
|
+
[a, b] = [b, a];
|
|
4142
|
+
let { parent, index, inText } = doc.resolve(a);
|
|
4143
|
+
if (inText)
|
|
4144
|
+
return false;
|
|
4145
|
+
for (; a < b; a++) {
|
|
4146
|
+
if (index == parent.node.content.length) {
|
|
4147
|
+
if (!parent.node.type.isInline)
|
|
4148
|
+
return false;
|
|
4149
|
+
index = parent.index + 1;
|
|
4150
|
+
parent = parent.parent;
|
|
4151
|
+
}
|
|
4152
|
+
else {
|
|
4153
|
+
let next = parent.node.content[index];
|
|
4154
|
+
if (!next.isPlot || !next.type.isInline)
|
|
4155
|
+
return false;
|
|
4156
|
+
parent = Pos.Plot.create(parent, next, a, index);
|
|
4157
|
+
index = 0;
|
|
4158
|
+
}
|
|
4159
|
+
}
|
|
4160
|
+
return true;
|
|
4161
|
+
}
|
|
4014
4162
|
function isSingleChar(doc, from, to) {
|
|
4015
4163
|
if (to > from + 10)
|
|
4016
4164
|
return false;
|
|
@@ -4185,13 +4333,17 @@ function isInPrimarySelection(wg, event) {
|
|
|
4185
4333
|
}
|
|
4186
4334
|
return false;
|
|
4187
4335
|
}
|
|
4336
|
+
const focusEvents = /*@__PURE__*/(() => new Set(["input", "beforeinput", "keydown", "keyup", "keypress", "copy", "cut", "paste"]))();
|
|
4188
4337
|
function eventBelongsToEditor(wg, event) {
|
|
4189
|
-
if (!event.bubbles)
|
|
4190
|
-
return true;
|
|
4191
4338
|
if (event.defaultPrevented)
|
|
4192
4339
|
return false;
|
|
4340
|
+
if (!event.bubbles)
|
|
4341
|
+
return true;
|
|
4342
|
+
let active = wg.root.activeElement;
|
|
4193
4343
|
for (let node = event.target, tile; node != wg.contentDOM; node = node.parentNode)
|
|
4194
|
-
if (!node || node.nodeType == 11 ||
|
|
4344
|
+
if (!node || node.nodeType == 11 ||
|
|
4345
|
+
(tile = Tile.get(node)) && tile.ignoreEvent(event) ||
|
|
4346
|
+
node == active && focusEvents.has(event.type))
|
|
4195
4347
|
return false;
|
|
4196
4348
|
return true;
|
|
4197
4349
|
}
|
|
@@ -4630,9 +4782,34 @@ class ViewState {
|
|
|
4630
4782
|
const cursorBlinkRate = /*@__PURE__*/GardState.Facet.define({
|
|
4631
4783
|
combine: inputs => inputs.length ? Math.min(...inputs) : 1200
|
|
4632
4784
|
});
|
|
4633
|
-
class
|
|
4785
|
+
class CursorStyle {
|
|
4786
|
+
height;
|
|
4787
|
+
align;
|
|
4788
|
+
color;
|
|
4789
|
+
bold;
|
|
4790
|
+
italic;
|
|
4791
|
+
constructor(height, align, color, bold, italic) {
|
|
4792
|
+
this.height = height;
|
|
4793
|
+
this.align = align;
|
|
4794
|
+
this.color = color;
|
|
4795
|
+
this.bold = bold;
|
|
4796
|
+
this.italic = italic;
|
|
4797
|
+
}
|
|
4798
|
+
static read(node, height) {
|
|
4799
|
+
let win = node.ownerDocument.defaultView || window;
|
|
4800
|
+
let elt = node.nodeType == 1 ? node : node.parentNode;
|
|
4801
|
+
let style = win.getComputedStyle(elt);
|
|
4802
|
+
return new CursorStyle(height, style.verticalAlign, style.color, +style.fontWeight > 400, style.fontStyle == "italic");
|
|
4803
|
+
}
|
|
4804
|
+
eq(other) {
|
|
4805
|
+
return other && this.height == other.height && this.align == other.align &&
|
|
4806
|
+
this.color == other.color && this.bold == other.bold && this.italic == other.italic;
|
|
4807
|
+
}
|
|
4808
|
+
}
|
|
4809
|
+
class CursorLayer {
|
|
4634
4810
|
layer;
|
|
4635
|
-
|
|
4811
|
+
info = null;
|
|
4812
|
+
cached = null;
|
|
4636
4813
|
constructor(wg) {
|
|
4637
4814
|
this.layer = wg.scrollDOM.appendChild(document.createElement("wg-cursor-layer"));
|
|
4638
4815
|
this.positionCursor = this.positionCursor.bind(this);
|
|
@@ -4655,48 +4832,131 @@ class cursorLayer {
|
|
|
4655
4832
|
this.layer.remove();
|
|
4656
4833
|
}
|
|
4657
4834
|
positionCursor(wg) {
|
|
4658
|
-
|
|
4659
|
-
|
|
4660
|
-
|
|
4661
|
-
|
|
4662
|
-
|
|
4663
|
-
|
|
4664
|
-
|
|
4665
|
-
|
|
4666
|
-
|
|
4667
|
-
|
|
4668
|
-
|
|
4669
|
-
|
|
4670
|
-
|
|
4671
|
-
|
|
4672
|
-
|
|
4673
|
-
|
|
4674
|
-
|
|
4675
|
-
|
|
4676
|
-
|
|
4677
|
-
|
|
4835
|
+
getCursorInfo(wg, this, info => {
|
|
4836
|
+
let cur = this.info;
|
|
4837
|
+
if (!info ? cur : !cur || cur.left != info.left || cur.top != info.top || cur.size != info.size ||
|
|
4838
|
+
(cur.style ? !cur.style.eq(info.style) : info.style)) {
|
|
4839
|
+
this.info = info;
|
|
4840
|
+
wg.scheduleDOMWrite(() => {
|
|
4841
|
+
let cursor = this.layer.firstChild;
|
|
4842
|
+
if (!info) {
|
|
4843
|
+
if (cursor)
|
|
4844
|
+
cursor.remove();
|
|
4845
|
+
}
|
|
4846
|
+
else {
|
|
4847
|
+
if (!cursor)
|
|
4848
|
+
cursor = this.layer.appendChild(document.createElement("wg-cursor"));
|
|
4849
|
+
cursor.className = "wg-cursor-" + (info.horiz ? "h" : "v");
|
|
4850
|
+
cursor.style.top = info.top + "px";
|
|
4851
|
+
cursor.style.left = info.left + "px";
|
|
4852
|
+
cursor.style.width = info.horiz ? info.size + "px" : "";
|
|
4853
|
+
cursor.style.height = info.horiz ? "" : info.size + "px";
|
|
4854
|
+
cursor.style.borderLeftColor = info.style ? info.style.color : "";
|
|
4855
|
+
cursor.classList.toggle("wg-cursor-bold", info.style?.bold ?? false);
|
|
4856
|
+
cursor.classList.toggle("wg-cursor-italic", info.style?.italic ?? false);
|
|
4857
|
+
}
|
|
4858
|
+
});
|
|
4859
|
+
}
|
|
4860
|
+
});
|
|
4678
4861
|
}
|
|
4679
4862
|
}
|
|
4863
|
+
function alignOffset(align, height) {
|
|
4864
|
+
if (align == "super")
|
|
4865
|
+
return height * 0.36;
|
|
4866
|
+
if (align == "sub")
|
|
4867
|
+
return height * -0.17;
|
|
4868
|
+
if (align.endsWith("px"))
|
|
4869
|
+
return +align.slice(0, align.length - 2);
|
|
4870
|
+
if (align.endsWith("%"))
|
|
4871
|
+
return height * (+align.slice(0, align.length - 1)) * 100;
|
|
4872
|
+
return 0;
|
|
4873
|
+
}
|
|
4680
4874
|
const VertWidth = 30, VertGap = 5;
|
|
4681
|
-
function
|
|
4875
|
+
function getCursorInfo(wg, plugin, cont) {
|
|
4682
4876
|
let { state } = wg;
|
|
4683
4877
|
if (!state.selection.isCursor)
|
|
4684
|
-
return null;
|
|
4685
|
-
let { head, headSide } = state.selection;
|
|
4686
|
-
let {
|
|
4687
|
-
let
|
|
4688
|
-
if (
|
|
4689
|
-
|
|
4690
|
-
if (!wg.state.textLTR)
|
|
4691
|
-
left = right - size;
|
|
4878
|
+
return cont(null);
|
|
4879
|
+
let { head, headSide } = state.selection, { sel } = wg.state;
|
|
4880
|
+
let { ref, rect } = coordsAtPos(wg, head, headSide);
|
|
4881
|
+
let doc = wg.contentDOM.getBoundingClientRect();
|
|
4882
|
+
if (!sel.head.parent.node.inlineContent) {
|
|
4883
|
+
let width = Math.max(VertWidth, rect.width), top = rect.top;
|
|
4692
4884
|
let other = wg.coordsAtPos(head, headSide > 0 ? -1 : 1);
|
|
4693
4885
|
if (other.top == other.bottom && other.top != top) {
|
|
4694
4886
|
let move = Math.min(VertGap, Math.abs(other.top - top) / 2);
|
|
4695
|
-
top =
|
|
4887
|
+
top = top + move * (other.top < top ? -1 : 1);
|
|
4696
4888
|
}
|
|
4889
|
+
return cont({
|
|
4890
|
+
left: (wg.state.textLTR ? rect.left : rect.right - width) - doc.left,
|
|
4891
|
+
top: top - doc.top,
|
|
4892
|
+
size: width,
|
|
4893
|
+
horiz: true, style: null
|
|
4894
|
+
});
|
|
4697
4895
|
}
|
|
4698
|
-
let
|
|
4699
|
-
|
|
4896
|
+
let finish = (style, vertRect) => {
|
|
4897
|
+
if (style && (!plugin.cached || plugin.cached.style != style))
|
|
4898
|
+
plugin.cached = { style, marks, parent: sel.head.parent.node.tag };
|
|
4899
|
+
let height = style ? style.height : rect.height;
|
|
4900
|
+
let bot = rect.bottom;
|
|
4901
|
+
if (vertRect && (vertRect.top < rect.bottom && vertRect.bottom > rect.top)) {
|
|
4902
|
+
bot = vertRect.bottom;
|
|
4903
|
+
}
|
|
4904
|
+
else {
|
|
4905
|
+
let win = ref.dom.ownerDocument.defaultView || window;
|
|
4906
|
+
let refAlign = win.getComputedStyle((ref.dom.nodeType == 1 ? ref.dom : ref.dom.parentNode)).verticalAlign;
|
|
4907
|
+
if (style && refAlign != style.align) {
|
|
4908
|
+
bot += alignOffset(refAlign, rect.height) - alignOffset(style.align, style.height);
|
|
4909
|
+
}
|
|
4910
|
+
}
|
|
4911
|
+
cont({
|
|
4912
|
+
left: rect.left - doc.left,
|
|
4913
|
+
top: bot - height - doc.top,
|
|
4914
|
+
size: height,
|
|
4915
|
+
horiz: false, style
|
|
4916
|
+
});
|
|
4917
|
+
};
|
|
4918
|
+
let marks = sel.activeMarks;
|
|
4919
|
+
if (ref instanceof TextTile) {
|
|
4920
|
+
let node = ref.posBefore < head ? state.sel.head.nodeBefore : state.sel.head.nodeAfter;
|
|
4921
|
+
if (node && node.isText && Mark.sameSet(node.marks, marks))
|
|
4922
|
+
return finish(CursorStyle.read(ref.dom, rect.height), rect);
|
|
4923
|
+
}
|
|
4924
|
+
let pos = sel.head.parent.start, foundRect, foundNode;
|
|
4925
|
+
for (let sibling of sel.head.parent.node.content) {
|
|
4926
|
+
if (sibling.isText && Mark.sameSet(sibling.marks, marks)) {
|
|
4927
|
+
let { tile } = wg.docTile.resolve(pos, 1);
|
|
4928
|
+
if (tile instanceof TextTile) {
|
|
4929
|
+
let rects = textRange(tile.dom, 0, tile.length).getClientRects();
|
|
4930
|
+
foundNode = tile.dom;
|
|
4931
|
+
for (let i = 0; i < rects.length; i++) {
|
|
4932
|
+
foundRect = rects[i];
|
|
4933
|
+
if (foundRect.top < rect.bottom && foundRect.bottom > rect.top)
|
|
4934
|
+
break;
|
|
4935
|
+
}
|
|
4936
|
+
}
|
|
4937
|
+
}
|
|
4938
|
+
pos += sibling.length;
|
|
4939
|
+
}
|
|
4940
|
+
if (foundNode)
|
|
4941
|
+
return finish(CursorStyle.read(foundNode, foundRect.height), foundRect);
|
|
4942
|
+
if (plugin.cached && Mark.sameSet(plugin.cached.marks, marks) && plugin.cached.parent.eq(sel.head.parent.node.tag))
|
|
4943
|
+
return finish(plugin.cached.style);
|
|
4944
|
+
if (!marks.length)
|
|
4945
|
+
return finish(null);
|
|
4946
|
+
let target = sel.head.parent.node.isDoc ? wg.contentDOM : wg.nodeDOM(sel.head.parent.before);
|
|
4947
|
+
wg.scheduleDOMWrite(() => {
|
|
4948
|
+
let temp = renderMarks(marks, "M");
|
|
4949
|
+
temp.style.position = "absolute";
|
|
4950
|
+
wg.observer.ignore(() => target.insertBefore(temp, target.firstChild));
|
|
4951
|
+
wg.scheduleDOMRead(() => {
|
|
4952
|
+
wg.scheduleDOMWrite(() => wg.observer.ignore(() => temp.remove()));
|
|
4953
|
+
let inner = temp;
|
|
4954
|
+
while (inner.firstChild)
|
|
4955
|
+
inner = inner.firstChild;
|
|
4956
|
+
let r = textRange(inner, 0, 1).getClientRects()[0];
|
|
4957
|
+
finish(CursorStyle.read(inner, r.height), r);
|
|
4958
|
+
});
|
|
4959
|
+
});
|
|
4700
4960
|
}
|
|
4701
4961
|
function setBlinkRate(state, dom) {
|
|
4702
4962
|
dom.style.animationDuration = state.facet(cursorBlinkRate) + "ms";
|
|
@@ -4756,7 +5016,7 @@ class Wordgard {
|
|
|
4756
5016
|
for (let plugin of this.plugins)
|
|
4757
5017
|
plugin.update(this);
|
|
4758
5018
|
this.inputState = new InputState(this);
|
|
4759
|
-
this.docTile = DocTile.create(this.state, this.contentDOM);
|
|
5019
|
+
this.docTile = DocTile.create(this.state, this.contentDOM, this);
|
|
4760
5020
|
this.updateAttrs();
|
|
4761
5021
|
this.observer = new DOMObserver(this);
|
|
4762
5022
|
if (spec.parent)
|
|
@@ -4899,7 +5159,7 @@ class Wordgard {
|
|
|
4899
5159
|
this.mountStyles();
|
|
4900
5160
|
this.updateAttrs();
|
|
4901
5161
|
}
|
|
4902
|
-
this.docTile = prevDocTile.update(update.state, changes, this
|
|
5162
|
+
this.docTile = prevDocTile.update(update.state, changes, this, composition);
|
|
4903
5163
|
if ((composition?.wrapCursor || !composition && (prevDocTile != this.docTile || update.selectionSet)) && this.hasFocus)
|
|
4904
5164
|
setDOMSelection(this);
|
|
4905
5165
|
this.observer.clear();
|
|
@@ -5050,7 +5310,7 @@ class Wordgard {
|
|
|
5050
5310
|
}
|
|
5051
5311
|
coordsAtPos(pos, assoc = -1) {
|
|
5052
5312
|
this.ensureFlushed();
|
|
5053
|
-
return coordsAtPos(this, pos, assoc);
|
|
5313
|
+
return coordsAtPos(this, pos, assoc).rect;
|
|
5054
5314
|
}
|
|
5055
5315
|
coordsForElement(pos) {
|
|
5056
5316
|
this.ensureFlushed();
|
|
@@ -5299,7 +5559,7 @@ function attrsFromFacet(wg, facet, base) {
|
|
|
5299
5559
|
Wordgard.Update = Update;
|
|
5300
5560
|
;return Wordgard})(Wordgard);
|
|
5301
5561
|
const editorPlugin = /*@__PURE__*/GardState.Facet.define();
|
|
5302
|
-
const cursorPlugin = /*@__PURE__*/Wordgard.Plugin.fromClass(
|
|
5562
|
+
const cursorPlugin = /*@__PURE__*/Wordgard.Plugin.fromClass(CursorLayer);
|
|
5303
5563
|
class PluginInstance {
|
|
5304
5564
|
spec;
|
|
5305
5565
|
mustUpdate = null;
|