@nerd-bible/wordgard 0.3.5 → 0.5.2-beta
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/command.d.ts +19 -7
- package/dist/command.js +78 -50
- package/dist/doc.d.ts +17 -9
- package/dist/doc.js +67 -62
- package/dist/editor.d.ts +13 -4
- package/dist/editor.js +615 -275
- package/dist/schema.js +1 -1
- package/dist/state.d.ts +5 -11
- package/dist/state.js +52 -30
- package/dist/table.js +4 -3
- package/dist/types.d.ts +5 -5
- package/dist/types.js +8 -8
- package/package.json +1 -1
package/dist/editor.js
CHANGED
|
@@ -1,11 +1,167 @@
|
|
|
1
1
|
import { GardState, GardSelection, TextblockMap, BidiSpan, Transaction } from 'wordgard/state';
|
|
2
|
-
import { Attributes, Elt, Node, Leaf,
|
|
2
|
+
import { Attributes, Elt, Node, Leaf, parse, Slice, Plot, serialize, Pos, ChangeSet, 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';
|
|
6
6
|
import { PhraseSet, phrases } from 'wordgard/phrases';
|
|
7
7
|
import { history } from 'wordgard/history';
|
|
8
8
|
|
|
9
|
+
function eqArray(a, b) {
|
|
10
|
+
if (!a || !b)
|
|
11
|
+
return a == b;
|
|
12
|
+
if (a == b)
|
|
13
|
+
return true;
|
|
14
|
+
if (a.length != b.length)
|
|
15
|
+
return false;
|
|
16
|
+
for (let i = 0; i < a.length; i++)
|
|
17
|
+
if (!a[i].eq(b[i]))
|
|
18
|
+
return false;
|
|
19
|
+
return true;
|
|
20
|
+
}
|
|
21
|
+
const exceptionSink = /*@__PURE__*/GardState.Facet.define();
|
|
22
|
+
function logException(state, exception, context) {
|
|
23
|
+
let handler = state.facet(exceptionSink);
|
|
24
|
+
if (handler.length)
|
|
25
|
+
handler[0](exception);
|
|
26
|
+
else if (window.onerror)
|
|
27
|
+
window.onerror(String(exception), context, undefined, undefined, exception);
|
|
28
|
+
else if (context)
|
|
29
|
+
console.error(context + ":", exception);
|
|
30
|
+
else
|
|
31
|
+
console.error(exception);
|
|
32
|
+
}
|
|
33
|
+
function findAbove(array, start, n) {
|
|
34
|
+
let from = start, to = array.length;
|
|
35
|
+
for (;;) {
|
|
36
|
+
if (from == to)
|
|
37
|
+
return from;
|
|
38
|
+
let mid = (from + to) >> 1;
|
|
39
|
+
if (array[mid] > n)
|
|
40
|
+
to = mid;
|
|
41
|
+
else
|
|
42
|
+
from = mid + 1;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function addUpdated(sections, updated) {
|
|
47
|
+
let result = [];
|
|
48
|
+
let j = 0, [uFrom, uTo] = updated.length ? [updated[j++], updated[j++]] : [1e9, 1e9];
|
|
49
|
+
for (let i = 0, pos = 0; i < sections.length;) {
|
|
50
|
+
let len = sections[i++], ins = sections[i++];
|
|
51
|
+
if (ins == -1) {
|
|
52
|
+
let end = pos + len;
|
|
53
|
+
while (uFrom < end) {
|
|
54
|
+
if (uTo > pos) {
|
|
55
|
+
if (uFrom > pos)
|
|
56
|
+
addSection(result, uFrom - pos, -1);
|
|
57
|
+
addSection(result, Math.min(uTo, end) - Math.max(pos, uFrom), -2);
|
|
58
|
+
pos = uTo;
|
|
59
|
+
}
|
|
60
|
+
if (uTo >= end)
|
|
61
|
+
break;
|
|
62
|
+
if (j == updated.length) {
|
|
63
|
+
uFrom = uTo = 1e9;
|
|
64
|
+
break;
|
|
65
|
+
}
|
|
66
|
+
uFrom = updated[j++];
|
|
67
|
+
uTo = updated[j++];
|
|
68
|
+
}
|
|
69
|
+
if (pos < end)
|
|
70
|
+
addSection(result, end - pos, -1);
|
|
71
|
+
pos = end;
|
|
72
|
+
}
|
|
73
|
+
else {
|
|
74
|
+
addSection(result, len, ins);
|
|
75
|
+
pos += len;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
return result;
|
|
79
|
+
}
|
|
80
|
+
function addSection(sections, len, ins) {
|
|
81
|
+
let last = sections.length - 1;
|
|
82
|
+
if (last >= 0) {
|
|
83
|
+
let lastIns = sections[last];
|
|
84
|
+
if (lastIns >= 0 && ins >= 0) {
|
|
85
|
+
sections[last - 1] += len;
|
|
86
|
+
sections[last] += ins;
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
if (lastIns < 0 && lastIns == ins) {
|
|
90
|
+
sections[last - 1] += len;
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
sections.push(len, ins);
|
|
95
|
+
}
|
|
96
|
+
function separateChange(changes, fromB, toB) {
|
|
97
|
+
let result = [];
|
|
98
|
+
let lenI = 0, dLen = 0;
|
|
99
|
+
for (let posB = 0, done = false, i = 0; i < changes.length;) {
|
|
100
|
+
let len = changes[i++], ins = changes[i++], endB = posB + (ins < 0 ? len : ins);
|
|
101
|
+
if (fromB > endB || toB < posB) {
|
|
102
|
+
result.push(len, ins);
|
|
103
|
+
}
|
|
104
|
+
else {
|
|
105
|
+
if (ins >= 0) {
|
|
106
|
+
if (posB < fromB || endB > toB)
|
|
107
|
+
return null;
|
|
108
|
+
dLen = len - ins;
|
|
109
|
+
}
|
|
110
|
+
if (posB < fromB)
|
|
111
|
+
result.push(fromB - posB, ins);
|
|
112
|
+
if (!done) {
|
|
113
|
+
lenI = result.length;
|
|
114
|
+
result.push(0, toB - fromB);
|
|
115
|
+
done = true;
|
|
116
|
+
}
|
|
117
|
+
if (endB > toB)
|
|
118
|
+
result.push(endB - toB, ins);
|
|
119
|
+
}
|
|
120
|
+
posB = endB;
|
|
121
|
+
}
|
|
122
|
+
result[lenI] = (toB - fromB) + dLen;
|
|
123
|
+
return result;
|
|
124
|
+
}
|
|
125
|
+
function isEmpty(changes) {
|
|
126
|
+
return changes.length == 0 || changes.length == 2 && changes[1] == -1;
|
|
127
|
+
}
|
|
128
|
+
function addRange(ranges, from, to) {
|
|
129
|
+
if (!ranges.length || ranges[ranges.length - 1] < from) {
|
|
130
|
+
ranges.push(from, to);
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
133
|
+
let i = findAbove(ranges, 0, from) & -2, j = i;
|
|
134
|
+
if (j && ranges[j - 1] == from) {
|
|
135
|
+
j -= 2;
|
|
136
|
+
from = ranges[j];
|
|
137
|
+
}
|
|
138
|
+
while (i < ranges.length && ranges[i] <= to) {
|
|
139
|
+
from = Math.min(from, ranges[i++]);
|
|
140
|
+
to = Math.max(to, ranges[i++]);
|
|
141
|
+
}
|
|
142
|
+
ranges.splice(j, i - j, from, to);
|
|
143
|
+
}
|
|
144
|
+
function joinRanges(ranges) {
|
|
145
|
+
if (ranges.length == 1)
|
|
146
|
+
return ranges[0];
|
|
147
|
+
let result = [], index = ranges.map(() => 0);
|
|
148
|
+
for (;;) {
|
|
149
|
+
let minI = -1, minFrom = -1;
|
|
150
|
+
for (let i = 0; i < ranges.length; i++) {
|
|
151
|
+
let idx = index[i], set = ranges[i];
|
|
152
|
+
if (idx < set.length && (minI < 0 || set[idx] < minFrom)) {
|
|
153
|
+
minI = i;
|
|
154
|
+
minFrom = set[idx];
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
if (minI < 0)
|
|
158
|
+
return result;
|
|
159
|
+
let idx = index[minI], set = ranges[minI];
|
|
160
|
+
addRange(result, set[idx], set[idx + 1]);
|
|
161
|
+
index[minI] += 2;
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
|
|
9
165
|
class Widget {
|
|
10
166
|
value;
|
|
11
167
|
constructor(type,
|
|
@@ -68,6 +224,18 @@ class Widget {
|
|
|
68
224
|
Widget.EditableText = Widget.define({
|
|
69
225
|
render: s => document.createTextNode(s)
|
|
70
226
|
});
|
|
227
|
+
Widget.img = Widget.create({
|
|
228
|
+
render() {
|
|
229
|
+
let img = document.createElement("img");
|
|
230
|
+
img.className = "wg-buffer";
|
|
231
|
+
return img;
|
|
232
|
+
},
|
|
233
|
+
editable: true
|
|
234
|
+
});
|
|
235
|
+
Widget.br = Widget.create({
|
|
236
|
+
render() { return document.createElement("br"); },
|
|
237
|
+
editable: true
|
|
238
|
+
});
|
|
71
239
|
;return Widget})(Widget);
|
|
72
240
|
const Decoration = /*@__PURE__*/(function (Decoration) {
|
|
73
241
|
(function (Tag) {
|
|
@@ -229,6 +397,15 @@ const baseTagShape = /*@__PURE__*/memo((tag) => {
|
|
|
229
397
|
return addMarkAttributes(tag.is(Leaf.Text) ? Widget.EditableText.of(tag.param)
|
|
230
398
|
: tag.type.shape.create(tag.param), tag);
|
|
231
399
|
});
|
|
400
|
+
function renderMarks(marks, around) {
|
|
401
|
+
let result = addMarkAttributes(Elt.create("span", Attributes.none, [around]), Leaf.text(around, marks));
|
|
402
|
+
for (let i = marks.length - 1; i >= 0; i--) {
|
|
403
|
+
let mark = marks[i];
|
|
404
|
+
if (mark.type.element)
|
|
405
|
+
result = renderMarkWrapper(mark).fill([result]);
|
|
406
|
+
}
|
|
407
|
+
return result.toDOM();
|
|
408
|
+
}
|
|
232
409
|
class AttributeRangeDecoration extends Decoration.Range {
|
|
233
410
|
attribute;
|
|
234
411
|
value;
|
|
@@ -328,18 +505,6 @@ function nodeSelection(state) {
|
|
|
328
505
|
return PointSet.create([[state.selection.from, nodeSelectionDeco]]);
|
|
329
506
|
return PointSet.empty;
|
|
330
507
|
}
|
|
331
|
-
function findAbove(array, start, n) {
|
|
332
|
-
let from = start, to = array.length;
|
|
333
|
-
for (;;) {
|
|
334
|
-
if (from == to)
|
|
335
|
-
return from;
|
|
336
|
-
let mid = (from + to) >> 1;
|
|
337
|
-
if (array[mid] > n)
|
|
338
|
-
to = mid;
|
|
339
|
-
else
|
|
340
|
-
from = mid + 1;
|
|
341
|
-
}
|
|
342
|
-
}
|
|
343
508
|
const none = [];
|
|
344
509
|
class PointSet {
|
|
345
510
|
values;
|
|
@@ -351,16 +516,17 @@ class PointSet {
|
|
|
351
516
|
this.positions = positions;
|
|
352
517
|
}
|
|
353
518
|
get length() { return this.positions.length; }
|
|
354
|
-
|
|
519
|
+
get size() { return this.positions.length ? this.positions[this.positions.length - 1] : 0; }
|
|
520
|
+
map(changes, start = 0) {
|
|
355
521
|
if (changes.empty)
|
|
356
522
|
return this;
|
|
357
523
|
let positions = this.positions.slice();
|
|
358
|
-
let pos =
|
|
524
|
+
let pos = start, i = 0, startB = start && changes.mapPos(start, -1);
|
|
359
525
|
let deleted = [], deletions = 0;
|
|
360
|
-
changes.iterGaps((fromA, toA, fromB) => {
|
|
361
|
-
let off = fromB - fromA, end = toA - 1;
|
|
526
|
+
changes.iterGaps((fromA, toA, fromB, _toB, last) => {
|
|
527
|
+
let off = fromB - fromA, end = last ? toA : toA - 1;
|
|
362
528
|
if (end > pos) {
|
|
363
|
-
let nextI = findAbove(positions, i, end);
|
|
529
|
+
let nextI = findAbove(positions, i, end - start);
|
|
364
530
|
if (off)
|
|
365
531
|
for (; i < nextI; i++)
|
|
366
532
|
positions[i] += off;
|
|
@@ -369,15 +535,15 @@ class PointSet {
|
|
|
369
535
|
pos = end;
|
|
370
536
|
}
|
|
371
537
|
}, (_fromA, toA) => {
|
|
372
|
-
let nextI = findAbove(positions, i, toA + 1);
|
|
538
|
+
let nextI = findAbove(positions, i, toA + 1 + start);
|
|
373
539
|
for (; i < nextI; i++) {
|
|
374
|
-
let mapped = changes.mapPos(positions[i], this.values[i].side < 0 ? -1 : 1, this.values[i].trackMode);
|
|
540
|
+
let mapped = changes.mapPos(positions[i] + start, this.values[i].side < 0 ? -1 : 1, this.values[i].trackMode);
|
|
375
541
|
if (mapped == null) {
|
|
376
542
|
addDel(deleted, i);
|
|
377
543
|
deletions++;
|
|
378
544
|
}
|
|
379
545
|
else
|
|
380
|
-
positions[i] = mapped;
|
|
546
|
+
positions[i] = mapped - startB;
|
|
381
547
|
}
|
|
382
548
|
pos = toA + 1;
|
|
383
549
|
});
|
|
@@ -385,22 +551,22 @@ class PointSet {
|
|
|
385
551
|
return new PointSet(this.values, positions);
|
|
386
552
|
return new PointSet(applyDel(deleted, deletions, this.values), applyDel(deleted, deletions, positions));
|
|
387
553
|
}
|
|
388
|
-
merge(other) {
|
|
554
|
+
merge(other, maskFrom, maskTo = maskFrom) {
|
|
389
555
|
if (!this.length)
|
|
390
556
|
return other;
|
|
391
|
-
if (!other.length)
|
|
557
|
+
if (!other.length && maskFrom == null)
|
|
392
558
|
return this;
|
|
393
559
|
let posA = this.positions, posB = other.positions;
|
|
394
|
-
let pos = new Array(posA.length
|
|
560
|
+
let pos = new Array((maskFrom == null ? posA.length : 0) + posB.length), values = new Array(pos.length);
|
|
395
561
|
for (let i = 0, a = 0, b = 0;;) {
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
}
|
|
403
|
-
else if (
|
|
562
|
+
if (a < posA.length && (b == posB.length || (posA[a] - posB[b] || this.values[a].side - other.values[b].side) < 0)) {
|
|
563
|
+
if (maskFrom == null || maskFrom > posA[a] || maskTo < posA[a]) {
|
|
564
|
+
pos[i] = posA[a];
|
|
565
|
+
values[i++] = this.values[a];
|
|
566
|
+
}
|
|
567
|
+
a++;
|
|
568
|
+
}
|
|
569
|
+
else if (b < posB.length) {
|
|
404
570
|
pos[i] = posB[b];
|
|
405
571
|
values[i++] = other.values[b++];
|
|
406
572
|
}
|
|
@@ -456,9 +622,8 @@ class PointSet {
|
|
|
456
622
|
for (let i = positions.length;;) {
|
|
457
623
|
positions[i] = positions[i - 1];
|
|
458
624
|
values[i] = values[i - 1];
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
if (!i-- || (positions[i] - pos || values[i].side - value.side) <= 0) {
|
|
625
|
+
--i;
|
|
626
|
+
if (!i || (positions[i - 1] - pos || values[i - 1].side - value.side) <= 0) {
|
|
462
627
|
positions[i] = pos;
|
|
463
628
|
values[i] = value;
|
|
464
629
|
break;
|
|
@@ -483,14 +648,15 @@ class PointIterator {
|
|
|
483
648
|
this.set = set;
|
|
484
649
|
this.fill(0);
|
|
485
650
|
}
|
|
651
|
+
get to() { return this.from; }
|
|
486
652
|
fill(i) {
|
|
487
653
|
this.i = i;
|
|
488
654
|
if (i < this.set.positions.length) {
|
|
489
|
-
this.
|
|
655
|
+
this.from = this.set.positions[i];
|
|
490
656
|
this.value = this.set.values[i];
|
|
491
657
|
}
|
|
492
658
|
else {
|
|
493
|
-
this.
|
|
659
|
+
this.from = 1e8;
|
|
494
660
|
this.value = null;
|
|
495
661
|
this.done = true;
|
|
496
662
|
}
|
|
@@ -552,16 +718,17 @@ class RangeSet {
|
|
|
552
718
|
this.to = to;
|
|
553
719
|
}
|
|
554
720
|
get length() { return this.from.length; }
|
|
555
|
-
|
|
721
|
+
get size() { return this.to.length ? this.to[this.to.length - 1] : 0; }
|
|
722
|
+
map(changes, start = 0) {
|
|
556
723
|
if (changes.empty || !this.length)
|
|
557
724
|
return this;
|
|
558
725
|
let from = this.from.slice(), to = this.to.slice();
|
|
559
|
-
let pos =
|
|
726
|
+
let pos = start, i = 0, startB = start && changes.mapPos(start, -1);
|
|
560
727
|
let deleted = [], deletions = 0;
|
|
561
|
-
changes.iterGaps((fromA, toA, fromB) => {
|
|
562
|
-
let off = fromB - fromA, end = toA - 1;
|
|
728
|
+
changes.iterGaps((fromA, toA, fromB, _toB, last) => {
|
|
729
|
+
let off = fromB - fromA, end = last ? toA : toA - 1;
|
|
563
730
|
if (end > pos) {
|
|
564
|
-
let nextI = findAbove(
|
|
731
|
+
let nextI = findAbove(to, i, end - start);
|
|
565
732
|
if (off)
|
|
566
733
|
for (; i < nextI; i++) {
|
|
567
734
|
from[i] += off;
|
|
@@ -572,18 +739,18 @@ class RangeSet {
|
|
|
572
739
|
pos = end;
|
|
573
740
|
}
|
|
574
741
|
}, (_fromA, toA) => {
|
|
575
|
-
let nextI = findAbove(
|
|
742
|
+
let nextI = findAbove(from, i, toA - start);
|
|
576
743
|
for (; i < nextI; i++) {
|
|
577
744
|
let value = this.values[i];
|
|
578
|
-
let mappedFrom = changes.mapPos(from[i], value.inclusiveStart ? -1 : 1);
|
|
579
|
-
let mappedTo = changes.mapPos(to[i], value.inclusiveEnd ? 1 : -1);
|
|
745
|
+
let mappedFrom = changes.mapPos(from[i] + start, value.inclusiveStart ? -1 : 1);
|
|
746
|
+
let mappedTo = changes.mapPos(to[i] + start, value.inclusiveEnd ? 1 : -1);
|
|
580
747
|
if (mappedFrom >= mappedTo) {
|
|
581
748
|
addDel(deleted, i);
|
|
582
749
|
deletions++;
|
|
583
750
|
}
|
|
584
751
|
else {
|
|
585
|
-
from[i] = mappedFrom;
|
|
586
|
-
to[i] = mappedTo;
|
|
752
|
+
from[i] = mappedFrom - startB;
|
|
753
|
+
to[i] = mappedTo - startB;
|
|
587
754
|
}
|
|
588
755
|
}
|
|
589
756
|
pos = toA + 1;
|
|
@@ -592,6 +759,35 @@ class RangeSet {
|
|
|
592
759
|
return new RangeSet(this.values, from, to);
|
|
593
760
|
return new RangeSet(applyDel(deleted, deletions, this.values), applyDel(deleted, deletions, from), applyDel(deleted, deletions, to));
|
|
594
761
|
}
|
|
762
|
+
merge(other, maskFrom, maskTo = maskFrom) {
|
|
763
|
+
if (!this.length)
|
|
764
|
+
return other;
|
|
765
|
+
if (!other.length && maskFrom == null)
|
|
766
|
+
return this;
|
|
767
|
+
let fromA = this.from, fromB = other.from;
|
|
768
|
+
let from = new Array((maskFrom == null ? fromA.length : 0) + fromB.length);
|
|
769
|
+
let to = new Array(from.length), values = new Array(from.length);
|
|
770
|
+
for (let i = 0, a = 0, b = 0, at = 0;;) {
|
|
771
|
+
if (a < fromA.length && (b == fromB.length || fromA[a] < fromB[b])) {
|
|
772
|
+
if (maskFrom == null || maskFrom >= this.to[a] || maskTo <= this.from[a]) {
|
|
773
|
+
if ((from[i] = fromA[a]) < at)
|
|
774
|
+
throw new Error("Overlapping ranges");
|
|
775
|
+
at = to[i] = this.to[a];
|
|
776
|
+
values[i++] = this.values[a];
|
|
777
|
+
}
|
|
778
|
+
a++;
|
|
779
|
+
}
|
|
780
|
+
else if (b < fromB.length) {
|
|
781
|
+
if ((from[i] = fromB[b]) < at)
|
|
782
|
+
throw new Error("Overlapping ranges");
|
|
783
|
+
at = to[i] = other.to[b];
|
|
784
|
+
values[i++] = other.values[b++];
|
|
785
|
+
}
|
|
786
|
+
else {
|
|
787
|
+
return new RangeSet(values, from, to);
|
|
788
|
+
}
|
|
789
|
+
}
|
|
790
|
+
}
|
|
595
791
|
iter() {
|
|
596
792
|
return new RangeIterator(this);
|
|
597
793
|
}
|
|
@@ -639,6 +835,7 @@ class RangeSet {
|
|
|
639
835
|
throw new Error("Ranges must be added in order and cannot overlap");
|
|
640
836
|
from.push(f);
|
|
641
837
|
to.push(t);
|
|
838
|
+
curPos = t;
|
|
642
839
|
values.push(value);
|
|
643
840
|
});
|
|
644
841
|
return new RangeSet(values, from, to);
|
|
@@ -674,31 +871,87 @@ class RangeIterator {
|
|
|
674
871
|
this.fill(findAbove(this.set.to, 0, pos));
|
|
675
872
|
}
|
|
676
873
|
}
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
}
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
let idx = index[i], set = ranges[i];
|
|
692
|
-
if (idx < set.length && (minI < 0 || set[idx] < minFrom)) {
|
|
693
|
-
minI = i;
|
|
694
|
-
minFrom = set[idx];
|
|
874
|
+
class MultiSet {
|
|
875
|
+
sets;
|
|
876
|
+
pos;
|
|
877
|
+
constructor(sets, pos) {
|
|
878
|
+
this.sets = sets;
|
|
879
|
+
this.pos = pos;
|
|
880
|
+
}
|
|
881
|
+
map(changes) {
|
|
882
|
+
if (changes.empty)
|
|
883
|
+
return this;
|
|
884
|
+
let pos = this.pos.slice(), sets = this.sets.slice(), i = 0;
|
|
885
|
+
changes.iterGaps((fromA, toA, fromB, _toB, last) => {
|
|
886
|
+
while (i < sets.length && (last || pos[i] + sets[i].length < fromA)) {
|
|
887
|
+
pos[i++] += fromB - fromA;
|
|
695
888
|
}
|
|
889
|
+
}, (_fromA, toA) => {
|
|
890
|
+
while (i < sets.length && pos[i] <= toA) {
|
|
891
|
+
sets[i] = sets[i].map(changes, pos[i]);
|
|
892
|
+
pos[i] = changes.mapPos(pos[i], -1);
|
|
893
|
+
i++;
|
|
894
|
+
}
|
|
895
|
+
});
|
|
896
|
+
return new MultiSet(sets, pos);
|
|
897
|
+
}
|
|
898
|
+
iter() {
|
|
899
|
+
return new MultiIterator(this);
|
|
900
|
+
}
|
|
901
|
+
static empty = /*@__PURE__*/(() => new MultiSet([], []))();
|
|
902
|
+
static create(f) {
|
|
903
|
+
let sets = [], pos = [], at = 0;
|
|
904
|
+
f((p, set) => {
|
|
905
|
+
if (p < at)
|
|
906
|
+
throw new Error("Overlapping sets in MultiSet.create");
|
|
907
|
+
sets.push(set);
|
|
908
|
+
pos.push(p);
|
|
909
|
+
at = p + set.size;
|
|
910
|
+
});
|
|
911
|
+
return sets.length ? new MultiSet(sets, pos) : MultiSet.empty;
|
|
912
|
+
}
|
|
913
|
+
}
|
|
914
|
+
const empty = {
|
|
915
|
+
from: 1e9, to: 1e9,
|
|
916
|
+
value: null,
|
|
917
|
+
done: true,
|
|
918
|
+
next() { },
|
|
919
|
+
goto() { }
|
|
920
|
+
};
|
|
921
|
+
class MultiIterator {
|
|
922
|
+
set;
|
|
923
|
+
get value() { return this.cur.value; }
|
|
924
|
+
get done() { return this.cur.done; }
|
|
925
|
+
get from() { return this.cur.from + this.offset; }
|
|
926
|
+
get to() { return this.cur.to + this.offset; }
|
|
927
|
+
i = 0;
|
|
928
|
+
constructor(set) {
|
|
929
|
+
this.set = set;
|
|
930
|
+
this.nextSet();
|
|
931
|
+
}
|
|
932
|
+
next() {
|
|
933
|
+
this.cur.next();
|
|
934
|
+
while (this.cur != empty && this.cur.done)
|
|
935
|
+
this.nextSet();
|
|
936
|
+
}
|
|
937
|
+
nextSet() {
|
|
938
|
+
if (this.i == this.set.sets.length) {
|
|
939
|
+
this.offset = 0;
|
|
940
|
+
this.cur = empty;
|
|
941
|
+
}
|
|
942
|
+
else {
|
|
943
|
+
this.offset = this.set.pos[this.i];
|
|
944
|
+
this.cur = this.set.sets[this.i].iter();
|
|
945
|
+
this.i++;
|
|
696
946
|
}
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
let
|
|
700
|
-
|
|
701
|
-
|
|
947
|
+
}
|
|
948
|
+
goto(pos, inclusive = false) {
|
|
949
|
+
let i = 0;
|
|
950
|
+
while (i < this.set.pos.length && this.set.pos[i] + this.set.sets[i].size)
|
|
951
|
+
i++;
|
|
952
|
+
this.i = i;
|
|
953
|
+
this.nextSet();
|
|
954
|
+
this.cur.goto(pos - this.offset, inclusive);
|
|
702
955
|
}
|
|
703
956
|
}
|
|
704
957
|
function compareDecoSet(setA, setB, cmp) {
|
|
@@ -738,8 +991,11 @@ function findChangedRanges(prevState, prevDeco, state, deco, sections) {
|
|
|
738
991
|
compareDecoSet(prevDeco.points, deco.points, (a, b) => {
|
|
739
992
|
(a || PointSet.empty).compareRange(posA, b || PointSet.empty, posB, len, (pos, val) => {
|
|
740
993
|
add(pos, Math.min(pos + (val instanceof WidgetDecoration ? 0 : 1), endB));
|
|
741
|
-
if (val instanceof ShapeDecoration && !globalChange)
|
|
742
|
-
shapeChanges
|
|
994
|
+
if (val instanceof ShapeDecoration && !globalChange) {
|
|
995
|
+
let idx = findAbove(shapeChanges, 0, pos - 1);
|
|
996
|
+
if (idx == shapeChanges.length || shapeChanges[idx] != pos)
|
|
997
|
+
shapeChanges.splice(idx, 0, pos);
|
|
998
|
+
}
|
|
743
999
|
});
|
|
744
1000
|
});
|
|
745
1001
|
let joined = joinRanges(ranges), pos = posB, end = pos + len, j = 0;
|
|
@@ -772,15 +1028,12 @@ function findChangedRanges(prevState, prevDeco, state, deco, sections) {
|
|
|
772
1028
|
return addAtomicityChanges(result, prevState, shapeChanges);
|
|
773
1029
|
return result;
|
|
774
1030
|
}
|
|
775
|
-
function addAtomicityChanges(
|
|
1031
|
+
function addAtomicityChanges(changes, prev, nodes) {
|
|
776
1032
|
let added = [];
|
|
777
|
-
let scan = prev.doc.resolve(0),
|
|
778
|
-
for (let posB of
|
|
779
|
-
if (posB == last)
|
|
780
|
-
continue;
|
|
781
|
-
last = posB;
|
|
1033
|
+
let scan = prev.doc.resolve(0), sectionPos = 0, sectionI = 0, off = 0;
|
|
1034
|
+
for (let posB of nodes) {
|
|
782
1035
|
while (posB >= sectionPos) {
|
|
783
|
-
let len =
|
|
1036
|
+
let len = changes[sectionI++], ins = changes[sectionI++];
|
|
784
1037
|
if (ins < 0) {
|
|
785
1038
|
sectionPos += len;
|
|
786
1039
|
}
|
|
@@ -797,35 +1050,7 @@ function addAtomicityChanges(sections, prev, changes) {
|
|
|
797
1050
|
continue;
|
|
798
1051
|
added.push(posA, posA + node.length);
|
|
799
1052
|
}
|
|
800
|
-
|
|
801
|
-
return sections;
|
|
802
|
-
let changedSections = [], pos = 0;
|
|
803
|
-
for (let i = 0; i < added.length;) {
|
|
804
|
-
let from = added[i++], to = added[i++];
|
|
805
|
-
if (from > pos)
|
|
806
|
-
changedSections.push(from - pos, -1);
|
|
807
|
-
changedSections.push(to - from, to - from);
|
|
808
|
-
pos = to;
|
|
809
|
-
}
|
|
810
|
-
if (pos < prev.doc.length)
|
|
811
|
-
changedSections.push(prev.doc.length - pos, -1);
|
|
812
|
-
return ChangeSet.composeSections(changedSections, sections);
|
|
813
|
-
}
|
|
814
|
-
function addSection(sections, len, ins) {
|
|
815
|
-
let last = sections.length - 1;
|
|
816
|
-
if (last >= 0) {
|
|
817
|
-
let lastIns = sections[last];
|
|
818
|
-
if (lastIns >= 0 && ins >= 0) {
|
|
819
|
-
sections[last - 1] += len;
|
|
820
|
-
sections[last] += ins;
|
|
821
|
-
return;
|
|
822
|
-
}
|
|
823
|
-
if (lastIns < 0 && lastIns == ins) {
|
|
824
|
-
sections[last - 1] += len;
|
|
825
|
-
return;
|
|
826
|
-
}
|
|
827
|
-
}
|
|
828
|
-
sections.push(len, ins);
|
|
1053
|
+
return added.length ? addUpdated(changes, added) : changes;
|
|
829
1054
|
}
|
|
830
1055
|
class HeapIterator {
|
|
831
1056
|
rangeHeap;
|
|
@@ -863,7 +1088,7 @@ class HeapIterator {
|
|
|
863
1088
|
? [rangeHeap[0].from, rangeHeap[0].value.inclusiveStart ? -1 : 1]
|
|
864
1089
|
: [1e9, 0];
|
|
865
1090
|
let [endPos, endSide] = active.length ? [active[0].to, active[0].value.inclusiveEnd ? 1 : -1] : [1e9, 0];
|
|
866
|
-
let {
|
|
1091
|
+
let { from: pointPos, side: pointSide } = pointHeap.length ? pointHeap[0] : { from: 1e9, side: 1 };
|
|
867
1092
|
let nextPos = Math.min(startPos, endPos, pointPos);
|
|
868
1093
|
if (this.to == this.end && nextPos > this.to) {
|
|
869
1094
|
this.done = true;
|
|
@@ -940,7 +1165,7 @@ function cmpRangeTo(a, b) {
|
|
|
940
1165
|
return a.to - b.to || cmpBool(a.value.inclusiveEnd, b.value.inclusiveEnd);
|
|
941
1166
|
}
|
|
942
1167
|
function cmpPoint(a, b) {
|
|
943
|
-
return a.
|
|
1168
|
+
return a.from - b.from || a.side - b.side;
|
|
944
1169
|
}
|
|
945
1170
|
function nodeWrappers(schema, tag, active, atom) {
|
|
946
1171
|
let wrappers;
|
|
@@ -1009,6 +1234,8 @@ class DecoIterator {
|
|
|
1009
1234
|
}
|
|
1010
1235
|
}
|
|
1011
1236
|
widgets(tag, place, walker) {
|
|
1237
|
+
if (place == 2 && tag.type.isInline)
|
|
1238
|
+
walker.widget(Widget.img, -1);
|
|
1012
1239
|
for (let src of this.globalWidgets) {
|
|
1013
1240
|
if (src.place == place && tag.type == src.type) {
|
|
1014
1241
|
let widget = typeof src.widget == "function" ? src.widget(tag) : src.widget;
|
|
@@ -1016,6 +1243,8 @@ class DecoIterator {
|
|
|
1016
1243
|
walker.widget(widget, place == 0 || place == 3 ? 1 : -1);
|
|
1017
1244
|
}
|
|
1018
1245
|
}
|
|
1246
|
+
if (place == 3 && tag.type.isInline)
|
|
1247
|
+
walker.widget(Widget.img, 1);
|
|
1019
1248
|
}
|
|
1020
1249
|
hasEndWidget(type) {
|
|
1021
1250
|
return this.globalWidgets.some(tw => tw.type == type &&
|
|
@@ -1185,31 +1414,6 @@ function compareSetPrec(setA, setB, array) {
|
|
|
1185
1414
|
return 0;
|
|
1186
1415
|
}
|
|
1187
1416
|
|
|
1188
|
-
function eqArray(a, b) {
|
|
1189
|
-
if (!a || !b)
|
|
1190
|
-
return a == b;
|
|
1191
|
-
if (a == b)
|
|
1192
|
-
return true;
|
|
1193
|
-
if (a.length != b.length)
|
|
1194
|
-
return false;
|
|
1195
|
-
for (let i = 0; i < a.length; i++)
|
|
1196
|
-
if (!a[i].eq(b[i]))
|
|
1197
|
-
return false;
|
|
1198
|
-
return true;
|
|
1199
|
-
}
|
|
1200
|
-
const exceptionSink = /*@__PURE__*/GardState.Facet.define();
|
|
1201
|
-
function logException(state, exception, context) {
|
|
1202
|
-
let handler = state.facet(exceptionSink);
|
|
1203
|
-
if (handler.length)
|
|
1204
|
-
handler[0](exception);
|
|
1205
|
-
else if (window.onerror)
|
|
1206
|
-
window.onerror(String(exception), context, undefined, undefined, exception);
|
|
1207
|
-
else if (context)
|
|
1208
|
-
console.error(context + ":", exception);
|
|
1209
|
-
else
|
|
1210
|
-
console.error(exception);
|
|
1211
|
-
}
|
|
1212
|
-
|
|
1213
1417
|
function getSelection(root) {
|
|
1214
1418
|
let target;
|
|
1215
1419
|
if (root.nodeType == 11) { target = root.getSelection ? root : root.ownerDocument;
|
|
@@ -1248,7 +1452,7 @@ function rmDOM(dom) {
|
|
|
1248
1452
|
function isBlockElement(node) {
|
|
1249
1453
|
let tile = node.wgTile;
|
|
1250
1454
|
if (tile?.node)
|
|
1251
|
-
return tile.node.
|
|
1455
|
+
return tile.node.isBlock;
|
|
1252
1456
|
return node.nodeType == 1 && /^(DIV|P|LI|UL|OL|BLOCKQUOTE|DD|DT|H\d|SECTION|PRE)$/.test(node.nodeName);
|
|
1253
1457
|
}
|
|
1254
1458
|
function isBlocking(node) {
|
|
@@ -1588,6 +1792,12 @@ class Tile {
|
|
|
1588
1792
|
let last = this.children.length - 1;
|
|
1589
1793
|
return last < 0 ? null : this.children[last];
|
|
1590
1794
|
}
|
|
1795
|
+
get nodeParent() {
|
|
1796
|
+
let tile = this;
|
|
1797
|
+
while (!tile.node)
|
|
1798
|
+
tile = tile.parent;
|
|
1799
|
+
return tile;
|
|
1800
|
+
}
|
|
1591
1801
|
ignoreEvent(event) { return false; }
|
|
1592
1802
|
get ignoreMutations() { return false; }
|
|
1593
1803
|
toString() { return this.dom.nodeName + (this.children.length ? `(${this.children})` : ""); }
|
|
@@ -1664,7 +1874,7 @@ class CompositeTile extends Tile {
|
|
|
1664
1874
|
orientation = node.type.orientation == "row" ? 0 : 1;
|
|
1665
1875
|
if (node.isTextblock)
|
|
1666
1876
|
textblock = TextblockMap.get(state, start, node);
|
|
1667
|
-
else if (node.
|
|
1877
|
+
else if (node.isBlock)
|
|
1668
1878
|
textblock = null;
|
|
1669
1879
|
}
|
|
1670
1880
|
else if (node && node.isText) {
|
|
@@ -1684,7 +1894,7 @@ class CompositeTile extends Tile {
|
|
|
1684
1894
|
posAtCoordsRow(start, state, x, y, textblock) {
|
|
1685
1895
|
let result = rowScan(x, y, add => {
|
|
1686
1896
|
for (let child of this.children) {
|
|
1687
|
-
if (child.
|
|
1897
|
+
if (child instanceof WidgetTile && !child.widget.type.inFlow)
|
|
1688
1898
|
continue;
|
|
1689
1899
|
let rects, { dom } = child;
|
|
1690
1900
|
if (dom.nodeType == 1)
|
|
@@ -1702,6 +1912,14 @@ class CompositeTile extends Tile {
|
|
|
1702
1912
|
return null;
|
|
1703
1913
|
let { closest, rect } = result;
|
|
1704
1914
|
let pos = this.posBeforeChild(closest, start);
|
|
1915
|
+
if (closest.dom.nodeName == "BR")
|
|
1916
|
+
return CoordPos.create(pos, 1);
|
|
1917
|
+
if (closest.node && closest.node.isPlot && closest.node.isInline) {
|
|
1918
|
+
if (x > rect.right)
|
|
1919
|
+
return CoordPos.create(pos + closest.length, -1);
|
|
1920
|
+
if (x < rect.left)
|
|
1921
|
+
return CoordPos.create(pos, 1);
|
|
1922
|
+
}
|
|
1705
1923
|
return closest.posAtCoordsInner(pos + closest.boundary, state, x, Math.max(rect.top, Math.min(rect.bottom, y)), textblock, 0);
|
|
1706
1924
|
}
|
|
1707
1925
|
posAtCoordsCol(start, state, x, y, textblock) {
|
|
@@ -1786,29 +2004,29 @@ class DocTile extends CompositeTile {
|
|
|
1786
2004
|
let changed = findChangedRanges(this.state, this.decoSet, state, decoSet, changes);
|
|
1787
2005
|
return this.updateRanges(state, decoSet, changed, wg, composition);
|
|
1788
2006
|
}
|
|
1789
|
-
updateRanges(state, decoSet,
|
|
2007
|
+
updateRanges(state, decoSet, changes, wg, composition) {
|
|
1790
2008
|
let wrapper = composition?.wrapCursor || null;
|
|
1791
|
-
if ((
|
|
2009
|
+
if (isEmpty(changes) && eqArray(wrapper, this.cursorWrapper))
|
|
1792
2010
|
return this;
|
|
1793
2011
|
if (composition) {
|
|
1794
|
-
let separated =
|
|
2012
|
+
let separated = separateChange(changes, composition.fromB, composition.toB);
|
|
1795
2013
|
if (!separated)
|
|
1796
2014
|
composition = null;
|
|
1797
2015
|
else
|
|
1798
|
-
|
|
2016
|
+
changes = separated;
|
|
1799
2017
|
}
|
|
1800
2018
|
let builder = new ContentUpdate(state, this, wg, new DecoIterator(state, decoSet), wrapper);
|
|
1801
|
-
for (let i = 0, posB = 0, startCovered = false; i <
|
|
1802
|
-
let len =
|
|
2019
|
+
for (let i = 0, posB = 0, startCovered = false; i < changes.length;) {
|
|
2020
|
+
let len = changes[i++], ins = changes[i++];
|
|
1803
2021
|
if (composition && posB == composition.fromB && ins >= 0) {
|
|
1804
2022
|
if (!startCovered)
|
|
1805
2023
|
builder.update(0, false);
|
|
1806
2024
|
builder.composition(composition, len);
|
|
1807
|
-
if (ins && (startCovered = i ==
|
|
2025
|
+
if (ins && (startCovered = i == changes.length || changes[i + 1] == -1))
|
|
1808
2026
|
builder.update(0, false);
|
|
1809
2027
|
}
|
|
1810
2028
|
else if (ins == -1) {
|
|
1811
|
-
builder.keep(len, !startCovered, i ==
|
|
2029
|
+
builder.keep(len, !startCovered, i == changes.length);
|
|
1812
2030
|
startCovered = false;
|
|
1813
2031
|
}
|
|
1814
2032
|
else if (ins == -2) {
|
|
@@ -1877,7 +2095,8 @@ class DocTile extends CompositeTile {
|
|
|
1877
2095
|
else if (pos == end)
|
|
1878
2096
|
i = j + 1;
|
|
1879
2097
|
}
|
|
1880
|
-
if (
|
|
2098
|
+
if (!ch.isPoint &&
|
|
2099
|
+
((ch.isPlotContent || ch.isNodeInner) && !ch.boundary ? pos >= off && pos <= end : pos > off && pos < end)) {
|
|
1881
2100
|
if (ch instanceof TextTile)
|
|
1882
2101
|
return new TilePos(ch, pos - off, pos);
|
|
1883
2102
|
else if (ch.isAtom) {
|
|
@@ -1986,6 +2205,8 @@ class DocTile extends CompositeTile {
|
|
|
1986
2205
|
dom = dom.parentNode;
|
|
1987
2206
|
domBefore = dom.previousSibling;
|
|
1988
2207
|
}
|
|
2208
|
+
if (elt.node && elt.node.isInline && elt.node.isPlot && (!domBefore || !domBefore.nextSibling))
|
|
2209
|
+
return domBefore ? elt.posAfter : elt.posBefore;
|
|
1989
2210
|
while (domBefore && !((eltBefore = domBefore.wgTile) && eltBefore.parent == elt))
|
|
1990
2211
|
domBefore = domBefore.previousSibling;
|
|
1991
2212
|
return domBefore ? elt.posBeforeChild(eltBefore) + eltBefore.length : elt.posAtStart;
|
|
@@ -2180,7 +2401,7 @@ class TilePointer {
|
|
|
2180
2401
|
}
|
|
2181
2402
|
if (!dist && next.isNodeInner && !nodeBoundary)
|
|
2182
2403
|
break;
|
|
2183
|
-
if (next.length
|
|
2404
|
+
if (next.length < dist || next.length == dist && (next.isPoint || next.boundary)) {
|
|
2184
2405
|
if (walker)
|
|
2185
2406
|
walker.skip(next, 0, next.length);
|
|
2186
2407
|
dist -= next.length;
|
|
@@ -2416,7 +2637,7 @@ class ContentUpdate {
|
|
|
2416
2637
|
if (mark.type.element) {
|
|
2417
2638
|
this.openWrapper(renderMarkWrapper(mark), mark.spanning, false);
|
|
2418
2639
|
}
|
|
2419
|
-
this.new.addChild(new WidgetTile(
|
|
2640
|
+
this.new.addChild(new WidgetTile(Widget.img, null, 16 | 32, Widget.img.render(this.wg)));
|
|
2420
2641
|
return;
|
|
2421
2642
|
}
|
|
2422
2643
|
let found = [];
|
|
@@ -2610,24 +2831,24 @@ class ContentUpdate {
|
|
|
2610
2831
|
return tile;
|
|
2611
2832
|
}
|
|
2612
2833
|
}
|
|
2613
|
-
|
|
2834
|
+
ensureHackNode() {
|
|
2614
2835
|
let tile = this.new;
|
|
2615
2836
|
if (!tile.isPlotContent)
|
|
2616
2837
|
return;
|
|
2617
2838
|
while (tile.isNodeInner)
|
|
2618
2839
|
tile = tile.parent;
|
|
2619
2840
|
let node = tile.node;
|
|
2620
|
-
if (!node || !node.isPlot || !node.isTextblock)
|
|
2841
|
+
if (!node || !node.isPlot || !(node.isTextblock || node.isInline))
|
|
2621
2842
|
return;
|
|
2622
2843
|
let hasHack = -1, needsHack = true;
|
|
2623
2844
|
for (let parent = this.new, i = parent.children.length;;) {
|
|
2624
2845
|
if (i > 0) {
|
|
2625
2846
|
let next = parent.children[--i];
|
|
2626
2847
|
if (next.isNodeInner || next instanceof WidgetTile && !next.widget.type.inFlow) ;
|
|
2627
|
-
else if (next instanceof WidgetTile && next.widget ==
|
|
2848
|
+
else if (next instanceof WidgetTile && next.widget == Widget.br && parent == this.new) {
|
|
2628
2849
|
hasHack = i;
|
|
2629
2850
|
}
|
|
2630
|
-
else if (next.dom.nodeName == "BR"
|
|
2851
|
+
else if (next.dom.nodeName == "BR") {
|
|
2631
2852
|
break;
|
|
2632
2853
|
}
|
|
2633
2854
|
else if (next instanceof CompositeTile && !next.isAtom) {
|
|
@@ -2652,11 +2873,11 @@ class ContentUpdate {
|
|
|
2652
2873
|
this.new.children.splice(hasHack, 1);
|
|
2653
2874
|
}
|
|
2654
2875
|
else if (needsHack) {
|
|
2655
|
-
this.new.addChild(new WidgetTile(
|
|
2876
|
+
this.new.addChild(new WidgetTile(Widget.br, null, 16 | 64, Widget.br.render(this.wg)));
|
|
2656
2877
|
}
|
|
2657
2878
|
}
|
|
2658
2879
|
up() {
|
|
2659
|
-
this.
|
|
2880
|
+
this.ensureHackNode();
|
|
2660
2881
|
this.new = this.new.parent;
|
|
2661
2882
|
}
|
|
2662
2883
|
leaveNode() {
|
|
@@ -2739,7 +2960,7 @@ class ContentUpdate {
|
|
|
2739
2960
|
finish() {
|
|
2740
2961
|
while (!(this.new instanceof DocTile))
|
|
2741
2962
|
this.up();
|
|
2742
|
-
this.
|
|
2963
|
+
this.ensureHackNode();
|
|
2743
2964
|
return this.new;
|
|
2744
2965
|
}
|
|
2745
2966
|
}
|
|
@@ -2779,56 +3000,25 @@ function updateAttributes(dom, a, b) {
|
|
|
2779
3000
|
}
|
|
2780
3001
|
return changed;
|
|
2781
3002
|
}
|
|
2782
|
-
|
|
2783
|
-
|
|
2784
|
-
|
|
2785
|
-
|
|
2786
|
-
|
|
2787
|
-
|
|
2788
|
-
|
|
2789
|
-
});
|
|
2790
|
-
function separateComposition(sections, comp) {
|
|
2791
|
-
let result = [], { fromB, toB } = comp;
|
|
2792
|
-
let lenI = 0, dLen = 0;
|
|
2793
|
-
for (let posB = 0, done = false, i = 0; i < sections.length;) {
|
|
2794
|
-
let len = sections[i++], ins = sections[i++], endB = posB + (ins < 0 ? len : ins);
|
|
2795
|
-
if (fromB > endB || toB < posB) {
|
|
2796
|
-
result.push(len, ins);
|
|
2797
|
-
}
|
|
2798
|
-
else {
|
|
2799
|
-
if (ins >= 0) {
|
|
2800
|
-
if (posB < fromB || endB > toB)
|
|
2801
|
-
return null;
|
|
2802
|
-
dLen = len - ins;
|
|
2803
|
-
}
|
|
2804
|
-
if (posB < fromB)
|
|
2805
|
-
result.push(fromB - posB, ins);
|
|
2806
|
-
if (!done) {
|
|
2807
|
-
lenI = result.length;
|
|
2808
|
-
result.push(0, comp.text.length);
|
|
2809
|
-
done = true;
|
|
2810
|
-
}
|
|
2811
|
-
if (endB > toB)
|
|
2812
|
-
result.push(endB - toB, ins);
|
|
2813
|
-
}
|
|
2814
|
-
posB = endB;
|
|
3003
|
+
|
|
3004
|
+
class Coords {
|
|
3005
|
+
ref;
|
|
3006
|
+
rect;
|
|
3007
|
+
constructor(ref, rect) {
|
|
3008
|
+
this.ref = ref;
|
|
3009
|
+
this.rect = rect;
|
|
2815
3010
|
}
|
|
2816
|
-
result[lenI] = comp.text.length + dLen;
|
|
2817
|
-
return result;
|
|
2818
3011
|
}
|
|
2819
|
-
|
|
2820
3012
|
function coordsAtPos(wg, pos, assoc) {
|
|
2821
3013
|
let { offset, tile, pos: tilePos } = wg.docTile.resolve(pos, assoc);
|
|
2822
3014
|
if (tile instanceof TextTile) {
|
|
2823
|
-
let
|
|
2824
|
-
|
|
2825
|
-
return singleRect(textRange(node, 0, 0), 1);
|
|
2826
|
-
let from = offset, to = offset, side = assoc < 0 && from || from == len ? 1 : -1;
|
|
3015
|
+
let from = offset, to = offset;
|
|
3016
|
+
let side = from == 0 ? -1 : from == tile.length ? 1 : -assoc;
|
|
2827
3017
|
if (side < 0)
|
|
2828
3018
|
to++;
|
|
2829
3019
|
else
|
|
2830
3020
|
from--;
|
|
2831
|
-
return flattenV(singleRect(textRange(
|
|
3021
|
+
return new Coords(tile, flattenV(singleRect(textRange(tile.dom, from, to), side, true), (side < 0) == ltrAt(wg.state, pos, assoc)));
|
|
2832
3022
|
}
|
|
2833
3023
|
let tagTile = tile;
|
|
2834
3024
|
while (!tagTile.node)
|
|
@@ -2839,10 +3029,10 @@ function coordsAtPos(wg, pos, assoc) {
|
|
|
2839
3029
|
if (tile.widget.type.inFlow) {
|
|
2840
3030
|
let rect = singleRect(tile.dom, after ? 1 : -1);
|
|
2841
3031
|
if (rect.width || rect.height)
|
|
2842
|
-
return horizontal ? flattenH(rect, !after) : flattenV(rect, ltrAt(wg.state, pos, 1) == !after);
|
|
3032
|
+
return new Coords(tile, horizontal ? flattenH(rect, !after) : flattenV(rect, ltrAt(wg.state, pos, 1) == !after));
|
|
2843
3033
|
}
|
|
2844
3034
|
if (!tile.parent)
|
|
2845
|
-
return new DOMRect;
|
|
3035
|
+
return new Coords(tile, new DOMRect);
|
|
2846
3036
|
offset = tile.parent.children.indexOf(tile) + (after ? 1 : 0);
|
|
2847
3037
|
tile = tile.parent;
|
|
2848
3038
|
assoc = after ? 1 : -1;
|
|
@@ -2852,9 +3042,11 @@ function coordsAtPos(wg, pos, assoc) {
|
|
|
2852
3042
|
let before = tile.children[i - 1];
|
|
2853
3043
|
if (before instanceof WidgetTile && !before.widget.type.inFlow)
|
|
2854
3044
|
continue;
|
|
3045
|
+
if (before.dom.nodeName == "BR")
|
|
3046
|
+
break;
|
|
2855
3047
|
let rect = singleRect(before.dom, 1);
|
|
2856
3048
|
if (rect.width || rect.height)
|
|
2857
|
-
return horizontal ? flattenH(rect, false) : flattenV(rect, !ltrAt(wg.state, pos, 1));
|
|
3049
|
+
return new Coords(before, horizontal ? flattenH(rect, false) : flattenV(rect, !ltrAt(wg.state, pos, 1)));
|
|
2858
3050
|
}
|
|
2859
3051
|
}
|
|
2860
3052
|
else { for (let i = offset; i < tile.children.length; i++) {
|
|
@@ -2863,12 +3055,12 @@ function coordsAtPos(wg, pos, assoc) {
|
|
|
2863
3055
|
continue;
|
|
2864
3056
|
let rect = singleRect(after.dom, -1);
|
|
2865
3057
|
if (rect.width || rect.height)
|
|
2866
|
-
return horizontal ? flattenH(rect, true) : flattenV(rect, ltrAt(wg.state, pos, 1));
|
|
3058
|
+
return new Coords(after, horizontal ? flattenH(rect, true) : flattenV(rect, ltrAt(wg.state, pos, 1)));
|
|
2867
3059
|
}
|
|
2868
3060
|
}
|
|
2869
3061
|
}
|
|
2870
3062
|
let rect = singleRect(tile.dom, -assoc);
|
|
2871
|
-
return horizontal ? flattenH(rect, assoc < 0) : flattenV(rect, assoc < 0);
|
|
3063
|
+
return new Coords(tile, horizontal ? flattenH(rect, assoc < 0) : flattenV(rect, assoc < 0));
|
|
2872
3064
|
}
|
|
2873
3065
|
function flattenV(rect, left) {
|
|
2874
3066
|
return rect.width ? new DOMRect(left ? rect.left : rect.right, rect.top, 0, rect.height) : rect;
|
|
@@ -3141,6 +3333,13 @@ const baseStyles = /*@__PURE__*/buildTheme("." + styleID, {
|
|
|
3141
3333
|
borderLeft: "1.8px solid currentColor",
|
|
3142
3334
|
marginLeft: "-0.9px",
|
|
3143
3335
|
},
|
|
3336
|
+
".wg-cursor-v.wg-cursor-bold": {
|
|
3337
|
+
borderLeft: "2.4px solid currentColor",
|
|
3338
|
+
marginLeft: "-1.2px",
|
|
3339
|
+
},
|
|
3340
|
+
".wg-cursor-v.wg-cursor-italic": {
|
|
3341
|
+
transform: "rotate(10deg)"
|
|
3342
|
+
},
|
|
3144
3343
|
".wg-cursor-h": {
|
|
3145
3344
|
borderTop: "1.8px solid currentColor",
|
|
3146
3345
|
marginTop: "-0.9px",
|
|
@@ -3151,6 +3350,10 @@ const baseStyles = /*@__PURE__*/buildTheme("." + styleID, {
|
|
|
3151
3350
|
backgroundColor: "transparent"
|
|
3152
3351
|
}
|
|
3153
3352
|
},
|
|
3353
|
+
".wg-buffer": {
|
|
3354
|
+
verticalAlign: "bottom",
|
|
3355
|
+
height: "1em",
|
|
3356
|
+
},
|
|
3154
3357
|
"wg-placeholder": {
|
|
3155
3358
|
opacity: "0.6",
|
|
3156
3359
|
display: "inline-block",
|
|
@@ -3256,6 +3459,32 @@ function readDOMSelection(wg, range) {
|
|
|
3256
3459
|
: wg.posAtDOM(range.focusNode, range.focusOffset);
|
|
3257
3460
|
return GardSelection.range(anchor, head);
|
|
3258
3461
|
}
|
|
3462
|
+
function selectionFromTouch(event, wg) {
|
|
3463
|
+
let pos = wg.posAtCoords({ x: event.touches[0].clientX, y: event.touches[0].clientY });
|
|
3464
|
+
if (pos.target != null) {
|
|
3465
|
+
let target = wg.state.doc.nodeAt(pos.target);
|
|
3466
|
+
if (target && target.type.isSelectable && wg.state.isAtom(target.type))
|
|
3467
|
+
return GardSelection.node(pos.target, target);
|
|
3468
|
+
}
|
|
3469
|
+
return GardSelection.near(wg.state, pos.pos, pos.side);
|
|
3470
|
+
}
|
|
3471
|
+
function rangeForClick(wg, pos, type) {
|
|
3472
|
+
if (type < 3 && pos.target != null) {
|
|
3473
|
+
let target = wg.state.doc.nodeAt(pos.target);
|
|
3474
|
+
if (target && target.type.isSelectable && wg.state.isAtom(target.type))
|
|
3475
|
+
return GardSelection.node(pos.target, target);
|
|
3476
|
+
}
|
|
3477
|
+
if (type == 1) { return GardSelection.near(wg.state, pos.pos, pos.side || -1);
|
|
3478
|
+
}
|
|
3479
|
+
else if (type == 2) { return wg.state.wordAt(pos.pos, pos.side || 1);
|
|
3480
|
+
}
|
|
3481
|
+
else { let cx = wg.state.doc.resolve(pos.pos), block = cx.textblockParent;
|
|
3482
|
+
if (block)
|
|
3483
|
+
return GardSelection.range(block.start, block.end);
|
|
3484
|
+
else
|
|
3485
|
+
return GardSelection.near(wg.state, pos.pos, pos.side || -1);
|
|
3486
|
+
}
|
|
3487
|
+
}
|
|
3259
3488
|
const Y_STEP = 5;
|
|
3260
3489
|
function moveVertically(wg, start, forward, distance = 0, selectNode = false) {
|
|
3261
3490
|
let editorRect = wg.contentDOM.getBoundingClientRect();
|
|
@@ -3478,13 +3707,21 @@ class DOMObserver {
|
|
|
3478
3707
|
this.wg.scheduleFlush();
|
|
3479
3708
|
}
|
|
3480
3709
|
pollSelection() {
|
|
3710
|
+
let { wg } = this;
|
|
3481
3711
|
if (this.selectionChanged &&
|
|
3482
|
-
(
|
|
3712
|
+
(wg.hasFocus || !wg.focusable) && hasSelection(wg.contentDOM, this.selectionRange)) {
|
|
3483
3713
|
this.selectionChanged = false;
|
|
3484
|
-
let
|
|
3485
|
-
|
|
3486
|
-
|
|
3487
|
-
|
|
3714
|
+
let fromTouch = wg.inputState.lastTouchTime > Date.now() - 100;
|
|
3715
|
+
let sel = readDOMSelection(wg, this.selectionRange);
|
|
3716
|
+
if (!sel.eqPos(wg.state.selection)) {
|
|
3717
|
+
let userEvent = "select";
|
|
3718
|
+
if (fromTouch) {
|
|
3719
|
+
userEvent = "select.pointer";
|
|
3720
|
+
let event = wg.inputState.lastTouchEvent;
|
|
3721
|
+
if (event.touches.length == 1 && sel.isCursor)
|
|
3722
|
+
sel = selectionFromTouch(event, wg);
|
|
3723
|
+
}
|
|
3724
|
+
wg.dispatch({ selection: sel, userEvent });
|
|
3488
3725
|
}
|
|
3489
3726
|
}
|
|
3490
3727
|
}
|
|
@@ -3533,11 +3770,7 @@ class DOMObserver {
|
|
|
3533
3770
|
return records;
|
|
3534
3771
|
}
|
|
3535
3772
|
addDirtyRange(from, to) {
|
|
3536
|
-
|
|
3537
|
-
sections.push(to - from, -2);
|
|
3538
|
-
if (to < len)
|
|
3539
|
-
sections.push(len - to, -1);
|
|
3540
|
-
this.dirty = this.dirty ? ChangeSet.composeSections(this.dirty, sections) : sections;
|
|
3773
|
+
addRange(this.dirty || (this.dirty = []), from, to);
|
|
3541
3774
|
}
|
|
3542
3775
|
processRecords(records) {
|
|
3543
3776
|
for (let record of records) {
|
|
@@ -3853,6 +4086,7 @@ class InputState {
|
|
|
3853
4086
|
lastKeyCode = 0;
|
|
3854
4087
|
lastKeyTime = 0;
|
|
3855
4088
|
lastTouchTime = 0;
|
|
4089
|
+
lastTouchEvent = null;
|
|
3856
4090
|
lastScrollTop = 0;
|
|
3857
4091
|
lastScrollLeft = 0;
|
|
3858
4092
|
lastContextMenu = 0;
|
|
@@ -3963,7 +4197,7 @@ class InputState {
|
|
|
3963
4197
|
let inText = node.nodeType == 3;
|
|
3964
4198
|
let ref = this.wg.docTile.posFromDOM(node, inText ? 0 : offset);
|
|
3965
4199
|
let dir = -1;
|
|
3966
|
-
let textBefore = textNodeBefore(node.parentNode, domIndex(node));
|
|
4200
|
+
let textBefore = node.parentNode && textNodeBefore(node.parentNode, domIndex(node));
|
|
3967
4201
|
let prev = textBefore && Tile.get(textBefore);
|
|
3968
4202
|
if (prev instanceof TextTile && prev.length < prev.dom.nodeValue.length)
|
|
3969
4203
|
dir = 1;
|
|
@@ -3996,7 +4230,7 @@ class InputState {
|
|
|
3996
4230
|
}
|
|
3997
4231
|
let command = inputTypeCommands[type];
|
|
3998
4232
|
if ((type == "deleteContentBackward" || type == "deleteContentForward") && range &&
|
|
3999
|
-
(sel.empty
|
|
4233
|
+
range.from != range.to && (sel.empty
|
|
4000
4234
|
? !isSingleChar(this.domDoc, data.domRange.from, data.domRange.to) ||
|
|
4001
4235
|
sel.head != (type == "deleteContentBackward" ? range.to : range.from)
|
|
4002
4236
|
: sel.from != range.from || sel.to != range.to)) {
|
|
@@ -4081,6 +4315,10 @@ class InputState {
|
|
|
4081
4315
|
: prev == after ? after : before;
|
|
4082
4316
|
}
|
|
4083
4317
|
}
|
|
4318
|
+
recordTouch(e) {
|
|
4319
|
+
this.lastTouchTime = Date.now();
|
|
4320
|
+
this.lastTouchEvent = e;
|
|
4321
|
+
}
|
|
4084
4322
|
connect() {
|
|
4085
4323
|
this.ensureHandlers(this.wg.state);
|
|
4086
4324
|
}
|
|
@@ -4280,23 +4518,6 @@ function eventBelongsToEditor(wg, event) {
|
|
|
4280
4518
|
function queryPos(wg, event) {
|
|
4281
4519
|
return wg.posAtCoords({ x: event.clientX, y: event.clientY });
|
|
4282
4520
|
}
|
|
4283
|
-
function rangeForClick(wg, pos, type) {
|
|
4284
|
-
if (type < 3 && pos.target != null) {
|
|
4285
|
-
let target = wg.state.doc.nodeAt(pos.target);
|
|
4286
|
-
if (target && target.type.isSelectable && wg.state.isAtom(target.type))
|
|
4287
|
-
return GardSelection.node(pos.target, target);
|
|
4288
|
-
}
|
|
4289
|
-
if (type == 1) { return GardSelection.near(wg.state, pos.pos, pos.side || -1);
|
|
4290
|
-
}
|
|
4291
|
-
else if (type == 2) { return wg.state.wordAt(pos.pos, pos.side || 1);
|
|
4292
|
-
}
|
|
4293
|
-
else { let cx = wg.state.doc.resolve(pos.pos), block = cx.textblockParent;
|
|
4294
|
-
if (block)
|
|
4295
|
-
return GardSelection.range(block.start, block.end);
|
|
4296
|
-
else
|
|
4297
|
-
return GardSelection.near(wg.state, pos.pos, pos.side || -1);
|
|
4298
|
-
}
|
|
4299
|
-
}
|
|
4300
4521
|
function basicMouseSelection(wg, event) {
|
|
4301
4522
|
let start = queryPos(wg, event), type = event.detail;
|
|
4302
4523
|
let startSel = wg.state.selection;
|
|
@@ -4392,11 +4613,13 @@ function compositionUpdate(wg, event) {
|
|
|
4392
4613
|
if (!wg.inputState.composing) {
|
|
4393
4614
|
wg.inputState.composing = { changes: 0, target: null };
|
|
4394
4615
|
let wrap = null;
|
|
4395
|
-
if (!
|
|
4616
|
+
if (!event.data) {
|
|
4396
4617
|
let sel = wg.state.selection, rSel = wg.state.sel;
|
|
4397
4618
|
if (sel.empty && (sel instanceof GardSelection.Text && sel.marks || !rSel.head.inText && rSel.head.index) &&
|
|
4398
4619
|
!eqArray(rSel.head.nodeBefore?.tag.marks, rSel.activeMarks))
|
|
4399
4620
|
wrap = rSel.activeMarks;
|
|
4621
|
+
else if (sel.empty && inlineBoundNear(wg.state.sel.head))
|
|
4622
|
+
wrap = rSel.activeMarks;
|
|
4400
4623
|
}
|
|
4401
4624
|
if (wrap)
|
|
4402
4625
|
try {
|
|
@@ -4408,6 +4631,13 @@ function compositionUpdate(wg, event) {
|
|
|
4408
4631
|
}
|
|
4409
4632
|
}
|
|
4410
4633
|
}
|
|
4634
|
+
function inlineBoundNear(pos) {
|
|
4635
|
+
let { parent, index, inText } = pos;
|
|
4636
|
+
if (inText || !parent.node.inlineContent)
|
|
4637
|
+
return false;
|
|
4638
|
+
return (index ? parent.node.content[index - 1].isPlot : parent.node.isInline) ||
|
|
4639
|
+
(index < parent.node.content.length ? parent.node.content[index].isPlot : parent.node.isInline);
|
|
4640
|
+
}
|
|
4411
4641
|
function isDeletionInputEvent(type) { return /^delete(Content|Word)/.test(type); }
|
|
4412
4642
|
const inputTypeCommands = /*@__PURE__*/(() => ({
|
|
4413
4643
|
historyUndo: undo,
|
|
@@ -4584,12 +4814,8 @@ const baseObservers = {
|
|
|
4584
4814
|
wg.inputState.lastScrollTop = wg.scrollDOM.scrollTop;
|
|
4585
4815
|
wg.inputState.lastScrollLeft = wg.scrollDOM.scrollLeft;
|
|
4586
4816
|
},
|
|
4587
|
-
touchstart(wg, e) {
|
|
4588
|
-
|
|
4589
|
-
},
|
|
4590
|
-
touchmove(wg) {
|
|
4591
|
-
wg.inputState.lastTouchTime = Date.now();
|
|
4592
|
-
},
|
|
4817
|
+
touchstart(wg, e) { wg.inputState.recordTouch(e); },
|
|
4818
|
+
touchmove(wg, e) { wg.inputState.recordTouch(e); },
|
|
4593
4819
|
focus(wg) {
|
|
4594
4820
|
if (!wg.scrollDOM.scrollTop && (wg.inputState.lastScrollTop || wg.inputState.lastScrollLeft)) {
|
|
4595
4821
|
wg.scrollDOM.scrollTop = wg.inputState.lastScrollTop;
|
|
@@ -4712,9 +4938,34 @@ class ViewState {
|
|
|
4712
4938
|
const cursorBlinkRate = /*@__PURE__*/GardState.Facet.define({
|
|
4713
4939
|
combine: inputs => inputs.length ? Math.min(...inputs) : 1200
|
|
4714
4940
|
});
|
|
4715
|
-
class
|
|
4941
|
+
class CursorStyle {
|
|
4942
|
+
height;
|
|
4943
|
+
align;
|
|
4944
|
+
color;
|
|
4945
|
+
bold;
|
|
4946
|
+
italic;
|
|
4947
|
+
constructor(height, align, color, bold, italic) {
|
|
4948
|
+
this.height = height;
|
|
4949
|
+
this.align = align;
|
|
4950
|
+
this.color = color;
|
|
4951
|
+
this.bold = bold;
|
|
4952
|
+
this.italic = italic;
|
|
4953
|
+
}
|
|
4954
|
+
static read(node, height) {
|
|
4955
|
+
let win = node.ownerDocument.defaultView || window;
|
|
4956
|
+
let elt = node.nodeType == 1 ? node : node.parentNode;
|
|
4957
|
+
let style = win.getComputedStyle(elt);
|
|
4958
|
+
return new CursorStyle(height, style.verticalAlign, style.color, +style.fontWeight > 400, style.fontStyle == "italic");
|
|
4959
|
+
}
|
|
4960
|
+
eq(other) {
|
|
4961
|
+
return other && this.height == other.height && this.align == other.align &&
|
|
4962
|
+
this.color == other.color && this.bold == other.bold && this.italic == other.italic;
|
|
4963
|
+
}
|
|
4964
|
+
}
|
|
4965
|
+
class CursorLayer {
|
|
4716
4966
|
layer;
|
|
4717
|
-
|
|
4967
|
+
info = null;
|
|
4968
|
+
cached = null;
|
|
4718
4969
|
constructor(wg) {
|
|
4719
4970
|
this.layer = wg.scrollDOM.appendChild(document.createElement("wg-cursor-layer"));
|
|
4720
4971
|
this.positionCursor = this.positionCursor.bind(this);
|
|
@@ -4737,48 +4988,135 @@ class cursorLayer {
|
|
|
4737
4988
|
this.layer.remove();
|
|
4738
4989
|
}
|
|
4739
4990
|
positionCursor(wg) {
|
|
4740
|
-
|
|
4741
|
-
|
|
4742
|
-
|
|
4743
|
-
|
|
4744
|
-
|
|
4745
|
-
|
|
4746
|
-
|
|
4747
|
-
|
|
4748
|
-
|
|
4749
|
-
|
|
4750
|
-
|
|
4751
|
-
|
|
4752
|
-
|
|
4753
|
-
|
|
4754
|
-
|
|
4755
|
-
|
|
4756
|
-
|
|
4757
|
-
|
|
4758
|
-
|
|
4759
|
-
|
|
4991
|
+
getCursorInfo(wg, this, info => {
|
|
4992
|
+
let cur = this.info;
|
|
4993
|
+
if (!info ? cur : !cur || cur.left != info.left || cur.top != info.top || cur.size != info.size ||
|
|
4994
|
+
(cur.style ? !cur.style.eq(info.style) : info.style)) {
|
|
4995
|
+
this.info = info;
|
|
4996
|
+
wg.scheduleDOMWrite(() => {
|
|
4997
|
+
let cursor = this.layer.firstChild;
|
|
4998
|
+
if (!info) {
|
|
4999
|
+
if (cursor)
|
|
5000
|
+
cursor.remove();
|
|
5001
|
+
}
|
|
5002
|
+
else {
|
|
5003
|
+
if (!cursor)
|
|
5004
|
+
cursor = this.layer.appendChild(document.createElement("wg-cursor"));
|
|
5005
|
+
cursor.className = "wg-cursor-" + (info.horiz ? "h" : "v");
|
|
5006
|
+
cursor.style.top = info.top + "px";
|
|
5007
|
+
cursor.style.left = info.left + "px";
|
|
5008
|
+
cursor.style.width = info.horiz ? info.size + "px" : "";
|
|
5009
|
+
cursor.style.height = info.horiz ? "" : info.size + "px";
|
|
5010
|
+
cursor.style.borderLeftColor = info.style ? info.style.color : "";
|
|
5011
|
+
cursor.classList.toggle("wg-cursor-bold", info.style?.bold ?? false);
|
|
5012
|
+
cursor.classList.toggle("wg-cursor-italic", info.style?.italic ?? false);
|
|
5013
|
+
}
|
|
5014
|
+
});
|
|
5015
|
+
}
|
|
5016
|
+
});
|
|
4760
5017
|
}
|
|
4761
5018
|
}
|
|
5019
|
+
function alignOffset(align, height) {
|
|
5020
|
+
if (align == "super")
|
|
5021
|
+
return height * 0.36;
|
|
5022
|
+
if (align == "sub")
|
|
5023
|
+
return height * -0.17;
|
|
5024
|
+
if (align.endsWith("px"))
|
|
5025
|
+
return +align.slice(0, align.length - 2);
|
|
5026
|
+
if (align.endsWith("%"))
|
|
5027
|
+
return height * (+align.slice(0, align.length - 1)) * 100;
|
|
5028
|
+
return 0;
|
|
5029
|
+
}
|
|
5030
|
+
function vertOverlap(a, b) {
|
|
5031
|
+
let margin = a.height / 3;
|
|
5032
|
+
return a.top < b.bottom - margin && a.bottom > b.top + margin;
|
|
5033
|
+
}
|
|
4762
5034
|
const VertWidth = 30, VertGap = 5;
|
|
4763
|
-
function
|
|
5035
|
+
function getCursorInfo(wg, plugin, cont) {
|
|
4764
5036
|
let { state } = wg;
|
|
4765
5037
|
if (!state.selection.isCursor)
|
|
4766
|
-
return null;
|
|
4767
|
-
let { head, headSide } = state.selection;
|
|
4768
|
-
let {
|
|
4769
|
-
let
|
|
4770
|
-
if (
|
|
4771
|
-
|
|
4772
|
-
if (!wg.state.textLTR)
|
|
4773
|
-
left = right - size;
|
|
5038
|
+
return cont(null);
|
|
5039
|
+
let { head, headSide } = state.selection, { sel } = wg.state;
|
|
5040
|
+
let { ref, rect } = coordsAtPos(wg, head, headSide);
|
|
5041
|
+
let doc = wg.contentDOM.getBoundingClientRect();
|
|
5042
|
+
if (!sel.head.parent.node.inlineContent) {
|
|
5043
|
+
let width = Math.min(VertWidth, rect.width), top = rect.top;
|
|
4774
5044
|
let other = wg.coordsAtPos(head, headSide > 0 ? -1 : 1);
|
|
4775
5045
|
if (other.top == other.bottom && other.top != top) {
|
|
4776
5046
|
let move = Math.min(VertGap, Math.abs(other.top - top) / 2);
|
|
4777
|
-
top =
|
|
5047
|
+
top = top + move * (other.top < top ? -1 : 1);
|
|
4778
5048
|
}
|
|
5049
|
+
return cont({
|
|
5050
|
+
left: (wg.state.textLTR ? rect.left : rect.right - width) - doc.left,
|
|
5051
|
+
top: top - doc.top,
|
|
5052
|
+
size: width,
|
|
5053
|
+
horiz: true, style: null
|
|
5054
|
+
});
|
|
4779
5055
|
}
|
|
4780
|
-
let
|
|
4781
|
-
|
|
5056
|
+
let finish = (style, vertRect) => {
|
|
5057
|
+
if (style && (!plugin.cached || plugin.cached.style != style))
|
|
5058
|
+
plugin.cached = { style, marks, parent: sel.head.parent.node.tag };
|
|
5059
|
+
let height = style ? style.height : rect.height;
|
|
5060
|
+
let bot = rect.bottom;
|
|
5061
|
+
if (vertRect && vertOverlap(vertRect, rect)) {
|
|
5062
|
+
bot = vertRect.bottom;
|
|
5063
|
+
}
|
|
5064
|
+
else {
|
|
5065
|
+
let win = ref.dom.ownerDocument.defaultView || window;
|
|
5066
|
+
let refAlign = win.getComputedStyle((ref.dom.nodeType == 1 ? ref.dom : ref.dom.parentNode)).verticalAlign;
|
|
5067
|
+
if (style && refAlign != style.align) {
|
|
5068
|
+
bot += alignOffset(refAlign, rect.height) - alignOffset(style.align, style.height);
|
|
5069
|
+
}
|
|
5070
|
+
}
|
|
5071
|
+
cont({
|
|
5072
|
+
left: rect.left - doc.left,
|
|
5073
|
+
top: bot - height - doc.top,
|
|
5074
|
+
size: height,
|
|
5075
|
+
horiz: false, style
|
|
5076
|
+
});
|
|
5077
|
+
};
|
|
5078
|
+
let marks = sel.activeMarks;
|
|
5079
|
+
if (ref instanceof TextTile) {
|
|
5080
|
+
let node = ref.posBefore < head ? state.sel.head.nodeBefore : state.sel.head.nodeAfter;
|
|
5081
|
+
if (node && node.isText && Mark.sameSet(node.marks, marks))
|
|
5082
|
+
return finish(CursorStyle.read(ref.dom, rect.height), rect);
|
|
5083
|
+
}
|
|
5084
|
+
let pos = sel.head.parent.start, foundRect, foundNode;
|
|
5085
|
+
scan: for (let sibling of sel.head.parent.node.content) {
|
|
5086
|
+
if (sibling.isText && Mark.sameSet(sibling.marks, marks)) {
|
|
5087
|
+
let { tile } = wg.docTile.resolve(pos, 1);
|
|
5088
|
+
if (tile instanceof TextTile) {
|
|
5089
|
+
let rects = textRange(tile.dom, 0, tile.length).getClientRects();
|
|
5090
|
+
foundNode = tile.dom;
|
|
5091
|
+
for (let i = 0; i < rects.length; i++) {
|
|
5092
|
+
foundRect = rects[i];
|
|
5093
|
+
if (vertOverlap(foundRect, rect))
|
|
5094
|
+
break scan;
|
|
5095
|
+
}
|
|
5096
|
+
}
|
|
5097
|
+
}
|
|
5098
|
+
pos += sibling.length;
|
|
5099
|
+
}
|
|
5100
|
+
if (foundNode)
|
|
5101
|
+
return finish(CursorStyle.read(foundNode, foundRect.height), foundRect);
|
|
5102
|
+
if (plugin.cached && Mark.sameSet(plugin.cached.marks, marks) && plugin.cached.parent.eq(sel.head.parent.node.tag))
|
|
5103
|
+
return finish(plugin.cached.style);
|
|
5104
|
+
if (!marks.length)
|
|
5105
|
+
return finish(null);
|
|
5106
|
+
let target = sel.head.parent.node.isDoc ? wg.contentDOM : wg.nodeDOM(sel.head.parent.before);
|
|
5107
|
+
wg.scheduleDOMWrite(() => {
|
|
5108
|
+
let temp = renderMarks(marks, "M");
|
|
5109
|
+
temp.style.position = "absolute";
|
|
5110
|
+
wg.observer.ignore(() => target.insertBefore(temp, target.firstChild));
|
|
5111
|
+
wg.scheduleDOMRead(() => {
|
|
5112
|
+
wg.scheduleDOMWrite(() => wg.observer.ignore(() => temp.remove()));
|
|
5113
|
+
let inner = temp;
|
|
5114
|
+
while (inner.firstChild)
|
|
5115
|
+
inner = inner.firstChild;
|
|
5116
|
+
let r = textRange(inner, 0, 1).getClientRects()[0];
|
|
5117
|
+
finish(CursorStyle.read(inner, r.height), r);
|
|
5118
|
+
});
|
|
5119
|
+
});
|
|
4782
5120
|
}
|
|
4783
5121
|
function setBlinkRate(state, dom) {
|
|
4784
5122
|
dom.style.animationDuration = state.facet(cursorBlinkRate) + "ms";
|
|
@@ -4971,7 +5309,7 @@ class Wordgard {
|
|
|
4971
5309
|
}
|
|
4972
5310
|
runUpdate(update, domChanges) {
|
|
4973
5311
|
let composition = this.composing ? getCompositionInfo(this) : null;
|
|
4974
|
-
let changes = domChanges ?
|
|
5312
|
+
let changes = domChanges ? addUpdated(update.changes.sections, domChanges) : update.changes.sections;
|
|
4975
5313
|
let prevDocTile = this.docTile;
|
|
4976
5314
|
if (!update.empty) {
|
|
4977
5315
|
this.updatePlugins(update);
|
|
@@ -5132,7 +5470,7 @@ class Wordgard {
|
|
|
5132
5470
|
}
|
|
5133
5471
|
coordsAtPos(pos, assoc = -1) {
|
|
5134
5472
|
this.ensureFlushed();
|
|
5135
|
-
return coordsAtPos(this, pos, assoc);
|
|
5473
|
+
return coordsAtPos(this, pos, assoc).rect;
|
|
5136
5474
|
}
|
|
5137
5475
|
coordsForElement(pos) {
|
|
5138
5476
|
this.ensureFlushed();
|
|
@@ -5381,7 +5719,7 @@ function attrsFromFacet(wg, facet, base) {
|
|
|
5381
5719
|
Wordgard.Update = Update;
|
|
5382
5720
|
;return Wordgard})(Wordgard);
|
|
5383
5721
|
const editorPlugin = /*@__PURE__*/GardState.Facet.define();
|
|
5384
|
-
const cursorPlugin = /*@__PURE__*/Wordgard.Plugin.fromClass(
|
|
5722
|
+
const cursorPlugin = /*@__PURE__*/Wordgard.Plugin.fromClass(CursorLayer);
|
|
5385
5723
|
class PluginInstance {
|
|
5386
5724
|
spec;
|
|
5387
5725
|
mustUpdate = null;
|
|
@@ -5682,6 +6020,7 @@ class BarButton {
|
|
|
5682
6020
|
this.item = item;
|
|
5683
6021
|
this.dom = document.createElement("button");
|
|
5684
6022
|
this.dom.className = "wg-menu-button";
|
|
6023
|
+
this.dom.type = "button";
|
|
5685
6024
|
this.dom.tabIndex = -1;
|
|
5686
6025
|
labelButton(wg, this.dom, item.label);
|
|
5687
6026
|
if (item.description) {
|
|
@@ -5767,6 +6106,7 @@ class BarSubmenu {
|
|
|
5767
6106
|
this.item = item;
|
|
5768
6107
|
this.dom = document.createElement("wg-submenu");
|
|
5769
6108
|
this.button = this.dom.appendChild(document.createElement("button"));
|
|
6109
|
+
this.button.type = "button";
|
|
5770
6110
|
this.button.tabIndex = -1;
|
|
5771
6111
|
this.button.className = "wg-menu-button";
|
|
5772
6112
|
this.button.setAttribute("aria-haspopup", "true");
|