@nerd-bible/wordgard 0.3.6 → 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 +15 -3
- package/dist/command.js +51 -19
- package/dist/doc.d.ts +16 -13
- package/dist/doc.js +53 -58
- package/dist/editor.d.ts +13 -4
- package/dist/editor.js +441 -279
- package/dist/schema.js +1 -1
- package/dist/state.d.ts +1 -3
- package/dist/state.js +5 -15
- 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) {
|
|
@@ -337,18 +505,6 @@ function nodeSelection(state) {
|
|
|
337
505
|
return PointSet.create([[state.selection.from, nodeSelectionDeco]]);
|
|
338
506
|
return PointSet.empty;
|
|
339
507
|
}
|
|
340
|
-
function findAbove(array, start, n) {
|
|
341
|
-
let from = start, to = array.length;
|
|
342
|
-
for (;;) {
|
|
343
|
-
if (from == to)
|
|
344
|
-
return from;
|
|
345
|
-
let mid = (from + to) >> 1;
|
|
346
|
-
if (array[mid] > n)
|
|
347
|
-
to = mid;
|
|
348
|
-
else
|
|
349
|
-
from = mid + 1;
|
|
350
|
-
}
|
|
351
|
-
}
|
|
352
508
|
const none = [];
|
|
353
509
|
class PointSet {
|
|
354
510
|
values;
|
|
@@ -360,16 +516,17 @@ class PointSet {
|
|
|
360
516
|
this.positions = positions;
|
|
361
517
|
}
|
|
362
518
|
get length() { return this.positions.length; }
|
|
363
|
-
|
|
519
|
+
get size() { return this.positions.length ? this.positions[this.positions.length - 1] : 0; }
|
|
520
|
+
map(changes, start = 0) {
|
|
364
521
|
if (changes.empty)
|
|
365
522
|
return this;
|
|
366
523
|
let positions = this.positions.slice();
|
|
367
|
-
let pos =
|
|
524
|
+
let pos = start, i = 0, startB = start && changes.mapPos(start, -1);
|
|
368
525
|
let deleted = [], deletions = 0;
|
|
369
|
-
changes.iterGaps((fromA, toA, fromB) => {
|
|
370
|
-
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;
|
|
371
528
|
if (end > pos) {
|
|
372
|
-
let nextI = findAbove(positions, i, end);
|
|
529
|
+
let nextI = findAbove(positions, i, end - start);
|
|
373
530
|
if (off)
|
|
374
531
|
for (; i < nextI; i++)
|
|
375
532
|
positions[i] += off;
|
|
@@ -378,15 +535,15 @@ class PointSet {
|
|
|
378
535
|
pos = end;
|
|
379
536
|
}
|
|
380
537
|
}, (_fromA, toA) => {
|
|
381
|
-
let nextI = findAbove(positions, i, toA + 1);
|
|
538
|
+
let nextI = findAbove(positions, i, toA + 1 + start);
|
|
382
539
|
for (; i < nextI; i++) {
|
|
383
|
-
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);
|
|
384
541
|
if (mapped == null) {
|
|
385
542
|
addDel(deleted, i);
|
|
386
543
|
deletions++;
|
|
387
544
|
}
|
|
388
545
|
else
|
|
389
|
-
positions[i] = mapped;
|
|
546
|
+
positions[i] = mapped - startB;
|
|
390
547
|
}
|
|
391
548
|
pos = toA + 1;
|
|
392
549
|
});
|
|
@@ -394,22 +551,22 @@ class PointSet {
|
|
|
394
551
|
return new PointSet(this.values, positions);
|
|
395
552
|
return new PointSet(applyDel(deleted, deletions, this.values), applyDel(deleted, deletions, positions));
|
|
396
553
|
}
|
|
397
|
-
merge(other) {
|
|
554
|
+
merge(other, maskFrom, maskTo = maskFrom) {
|
|
398
555
|
if (!this.length)
|
|
399
556
|
return other;
|
|
400
|
-
if (!other.length)
|
|
557
|
+
if (!other.length && maskFrom == null)
|
|
401
558
|
return this;
|
|
402
559
|
let posA = this.positions, posB = other.positions;
|
|
403
|
-
let pos = new Array(posA.length
|
|
560
|
+
let pos = new Array((maskFrom == null ? posA.length : 0) + posB.length), values = new Array(pos.length);
|
|
404
561
|
for (let i = 0, a = 0, b = 0;;) {
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
}
|
|
412
|
-
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) {
|
|
413
570
|
pos[i] = posB[b];
|
|
414
571
|
values[i++] = other.values[b++];
|
|
415
572
|
}
|
|
@@ -465,9 +622,8 @@ class PointSet {
|
|
|
465
622
|
for (let i = positions.length;;) {
|
|
466
623
|
positions[i] = positions[i - 1];
|
|
467
624
|
values[i] = values[i - 1];
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
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) {
|
|
471
627
|
positions[i] = pos;
|
|
472
628
|
values[i] = value;
|
|
473
629
|
break;
|
|
@@ -492,14 +648,15 @@ class PointIterator {
|
|
|
492
648
|
this.set = set;
|
|
493
649
|
this.fill(0);
|
|
494
650
|
}
|
|
651
|
+
get to() { return this.from; }
|
|
495
652
|
fill(i) {
|
|
496
653
|
this.i = i;
|
|
497
654
|
if (i < this.set.positions.length) {
|
|
498
|
-
this.
|
|
655
|
+
this.from = this.set.positions[i];
|
|
499
656
|
this.value = this.set.values[i];
|
|
500
657
|
}
|
|
501
658
|
else {
|
|
502
|
-
this.
|
|
659
|
+
this.from = 1e8;
|
|
503
660
|
this.value = null;
|
|
504
661
|
this.done = true;
|
|
505
662
|
}
|
|
@@ -561,16 +718,17 @@ class RangeSet {
|
|
|
561
718
|
this.to = to;
|
|
562
719
|
}
|
|
563
720
|
get length() { return this.from.length; }
|
|
564
|
-
|
|
721
|
+
get size() { return this.to.length ? this.to[this.to.length - 1] : 0; }
|
|
722
|
+
map(changes, start = 0) {
|
|
565
723
|
if (changes.empty || !this.length)
|
|
566
724
|
return this;
|
|
567
725
|
let from = this.from.slice(), to = this.to.slice();
|
|
568
|
-
let pos =
|
|
726
|
+
let pos = start, i = 0, startB = start && changes.mapPos(start, -1);
|
|
569
727
|
let deleted = [], deletions = 0;
|
|
570
|
-
changes.iterGaps((fromA, toA, fromB) => {
|
|
571
|
-
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;
|
|
572
730
|
if (end > pos) {
|
|
573
|
-
let nextI = findAbove(
|
|
731
|
+
let nextI = findAbove(to, i, end - start);
|
|
574
732
|
if (off)
|
|
575
733
|
for (; i < nextI; i++) {
|
|
576
734
|
from[i] += off;
|
|
@@ -581,18 +739,18 @@ class RangeSet {
|
|
|
581
739
|
pos = end;
|
|
582
740
|
}
|
|
583
741
|
}, (_fromA, toA) => {
|
|
584
|
-
let nextI = findAbove(
|
|
742
|
+
let nextI = findAbove(from, i, toA - start);
|
|
585
743
|
for (; i < nextI; i++) {
|
|
586
744
|
let value = this.values[i];
|
|
587
|
-
let mappedFrom = changes.mapPos(from[i], value.inclusiveStart ? -1 : 1);
|
|
588
|
-
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);
|
|
589
747
|
if (mappedFrom >= mappedTo) {
|
|
590
748
|
addDel(deleted, i);
|
|
591
749
|
deletions++;
|
|
592
750
|
}
|
|
593
751
|
else {
|
|
594
|
-
from[i] = mappedFrom;
|
|
595
|
-
to[i] = mappedTo;
|
|
752
|
+
from[i] = mappedFrom - startB;
|
|
753
|
+
to[i] = mappedTo - startB;
|
|
596
754
|
}
|
|
597
755
|
}
|
|
598
756
|
pos = toA + 1;
|
|
@@ -601,6 +759,35 @@ class RangeSet {
|
|
|
601
759
|
return new RangeSet(this.values, from, to);
|
|
602
760
|
return new RangeSet(applyDel(deleted, deletions, this.values), applyDel(deleted, deletions, from), applyDel(deleted, deletions, to));
|
|
603
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
|
+
}
|
|
604
791
|
iter() {
|
|
605
792
|
return new RangeIterator(this);
|
|
606
793
|
}
|
|
@@ -648,6 +835,7 @@ class RangeSet {
|
|
|
648
835
|
throw new Error("Ranges must be added in order and cannot overlap");
|
|
649
836
|
from.push(f);
|
|
650
837
|
to.push(t);
|
|
838
|
+
curPos = t;
|
|
651
839
|
values.push(value);
|
|
652
840
|
});
|
|
653
841
|
return new RangeSet(values, from, to);
|
|
@@ -683,31 +871,87 @@ class RangeIterator {
|
|
|
683
871
|
this.fill(findAbove(this.set.to, 0, pos));
|
|
684
872
|
}
|
|
685
873
|
}
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
}
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
let idx = index[i], set = ranges[i];
|
|
701
|
-
if (idx < set.length && (minI < 0 || set[idx] < minFrom)) {
|
|
702
|
-
minI = i;
|
|
703
|
-
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;
|
|
704
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++;
|
|
705
946
|
}
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
let
|
|
709
|
-
|
|
710
|
-
|
|
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);
|
|
711
955
|
}
|
|
712
956
|
}
|
|
713
957
|
function compareDecoSet(setA, setB, cmp) {
|
|
@@ -747,8 +991,11 @@ function findChangedRanges(prevState, prevDeco, state, deco, sections) {
|
|
|
747
991
|
compareDecoSet(prevDeco.points, deco.points, (a, b) => {
|
|
748
992
|
(a || PointSet.empty).compareRange(posA, b || PointSet.empty, posB, len, (pos, val) => {
|
|
749
993
|
add(pos, Math.min(pos + (val instanceof WidgetDecoration ? 0 : 1), endB));
|
|
750
|
-
if (val instanceof ShapeDecoration && !globalChange)
|
|
751
|
-
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
|
+
}
|
|
752
999
|
});
|
|
753
1000
|
});
|
|
754
1001
|
let joined = joinRanges(ranges), pos = posB, end = pos + len, j = 0;
|
|
@@ -781,15 +1028,12 @@ function findChangedRanges(prevState, prevDeco, state, deco, sections) {
|
|
|
781
1028
|
return addAtomicityChanges(result, prevState, shapeChanges);
|
|
782
1029
|
return result;
|
|
783
1030
|
}
|
|
784
|
-
function addAtomicityChanges(
|
|
1031
|
+
function addAtomicityChanges(changes, prev, nodes) {
|
|
785
1032
|
let added = [];
|
|
786
|
-
let scan = prev.doc.resolve(0),
|
|
787
|
-
for (let posB of
|
|
788
|
-
if (posB == last)
|
|
789
|
-
continue;
|
|
790
|
-
last = posB;
|
|
1033
|
+
let scan = prev.doc.resolve(0), sectionPos = 0, sectionI = 0, off = 0;
|
|
1034
|
+
for (let posB of nodes) {
|
|
791
1035
|
while (posB >= sectionPos) {
|
|
792
|
-
let len =
|
|
1036
|
+
let len = changes[sectionI++], ins = changes[sectionI++];
|
|
793
1037
|
if (ins < 0) {
|
|
794
1038
|
sectionPos += len;
|
|
795
1039
|
}
|
|
@@ -806,35 +1050,7 @@ function addAtomicityChanges(sections, prev, changes) {
|
|
|
806
1050
|
continue;
|
|
807
1051
|
added.push(posA, posA + node.length);
|
|
808
1052
|
}
|
|
809
|
-
|
|
810
|
-
return sections;
|
|
811
|
-
let changedSections = [], pos = 0;
|
|
812
|
-
for (let i = 0; i < added.length;) {
|
|
813
|
-
let from = added[i++], to = added[i++];
|
|
814
|
-
if (from > pos)
|
|
815
|
-
changedSections.push(from - pos, -1);
|
|
816
|
-
changedSections.push(to - from, to - from);
|
|
817
|
-
pos = to;
|
|
818
|
-
}
|
|
819
|
-
if (pos < prev.doc.length)
|
|
820
|
-
changedSections.push(prev.doc.length - pos, -1);
|
|
821
|
-
return ChangeSet.composeSections(changedSections, sections);
|
|
822
|
-
}
|
|
823
|
-
function addSection(sections, len, ins) {
|
|
824
|
-
let last = sections.length - 1;
|
|
825
|
-
if (last >= 0) {
|
|
826
|
-
let lastIns = sections[last];
|
|
827
|
-
if (lastIns >= 0 && ins >= 0) {
|
|
828
|
-
sections[last - 1] += len;
|
|
829
|
-
sections[last] += ins;
|
|
830
|
-
return;
|
|
831
|
-
}
|
|
832
|
-
if (lastIns < 0 && lastIns == ins) {
|
|
833
|
-
sections[last - 1] += len;
|
|
834
|
-
return;
|
|
835
|
-
}
|
|
836
|
-
}
|
|
837
|
-
sections.push(len, ins);
|
|
1053
|
+
return added.length ? addUpdated(changes, added) : changes;
|
|
838
1054
|
}
|
|
839
1055
|
class HeapIterator {
|
|
840
1056
|
rangeHeap;
|
|
@@ -872,7 +1088,7 @@ class HeapIterator {
|
|
|
872
1088
|
? [rangeHeap[0].from, rangeHeap[0].value.inclusiveStart ? -1 : 1]
|
|
873
1089
|
: [1e9, 0];
|
|
874
1090
|
let [endPos, endSide] = active.length ? [active[0].to, active[0].value.inclusiveEnd ? 1 : -1] : [1e9, 0];
|
|
875
|
-
let {
|
|
1091
|
+
let { from: pointPos, side: pointSide } = pointHeap.length ? pointHeap[0] : { from: 1e9, side: 1 };
|
|
876
1092
|
let nextPos = Math.min(startPos, endPos, pointPos);
|
|
877
1093
|
if (this.to == this.end && nextPos > this.to) {
|
|
878
1094
|
this.done = true;
|
|
@@ -949,7 +1165,7 @@ function cmpRangeTo(a, b) {
|
|
|
949
1165
|
return a.to - b.to || cmpBool(a.value.inclusiveEnd, b.value.inclusiveEnd);
|
|
950
1166
|
}
|
|
951
1167
|
function cmpPoint(a, b) {
|
|
952
|
-
return a.
|
|
1168
|
+
return a.from - b.from || a.side - b.side;
|
|
953
1169
|
}
|
|
954
1170
|
function nodeWrappers(schema, tag, active, atom) {
|
|
955
1171
|
let wrappers;
|
|
@@ -1018,6 +1234,8 @@ class DecoIterator {
|
|
|
1018
1234
|
}
|
|
1019
1235
|
}
|
|
1020
1236
|
widgets(tag, place, walker) {
|
|
1237
|
+
if (place == 2 && tag.type.isInline)
|
|
1238
|
+
walker.widget(Widget.img, -1);
|
|
1021
1239
|
for (let src of this.globalWidgets) {
|
|
1022
1240
|
if (src.place == place && tag.type == src.type) {
|
|
1023
1241
|
let widget = typeof src.widget == "function" ? src.widget(tag) : src.widget;
|
|
@@ -1025,6 +1243,8 @@ class DecoIterator {
|
|
|
1025
1243
|
walker.widget(widget, place == 0 || place == 3 ? 1 : -1);
|
|
1026
1244
|
}
|
|
1027
1245
|
}
|
|
1246
|
+
if (place == 3 && tag.type.isInline)
|
|
1247
|
+
walker.widget(Widget.img, 1);
|
|
1028
1248
|
}
|
|
1029
1249
|
hasEndWidget(type) {
|
|
1030
1250
|
return this.globalWidgets.some(tw => tw.type == type &&
|
|
@@ -1194,31 +1414,6 @@ function compareSetPrec(setA, setB, array) {
|
|
|
1194
1414
|
return 0;
|
|
1195
1415
|
}
|
|
1196
1416
|
|
|
1197
|
-
function eqArray(a, b) {
|
|
1198
|
-
if (!a || !b)
|
|
1199
|
-
return a == b;
|
|
1200
|
-
if (a == b)
|
|
1201
|
-
return true;
|
|
1202
|
-
if (a.length != b.length)
|
|
1203
|
-
return false;
|
|
1204
|
-
for (let i = 0; i < a.length; i++)
|
|
1205
|
-
if (!a[i].eq(b[i]))
|
|
1206
|
-
return false;
|
|
1207
|
-
return true;
|
|
1208
|
-
}
|
|
1209
|
-
const exceptionSink = /*@__PURE__*/GardState.Facet.define();
|
|
1210
|
-
function logException(state, exception, context) {
|
|
1211
|
-
let handler = state.facet(exceptionSink);
|
|
1212
|
-
if (handler.length)
|
|
1213
|
-
handler[0](exception);
|
|
1214
|
-
else if (window.onerror)
|
|
1215
|
-
window.onerror(String(exception), context, undefined, undefined, exception);
|
|
1216
|
-
else if (context)
|
|
1217
|
-
console.error(context + ":", exception);
|
|
1218
|
-
else
|
|
1219
|
-
console.error(exception);
|
|
1220
|
-
}
|
|
1221
|
-
|
|
1222
1417
|
function getSelection(root) {
|
|
1223
1418
|
let target;
|
|
1224
1419
|
if (root.nodeType == 11) { target = root.getSelection ? root : root.ownerDocument;
|
|
@@ -1257,7 +1452,7 @@ function rmDOM(dom) {
|
|
|
1257
1452
|
function isBlockElement(node) {
|
|
1258
1453
|
let tile = node.wgTile;
|
|
1259
1454
|
if (tile?.node)
|
|
1260
|
-
return tile.node.
|
|
1455
|
+
return tile.node.isBlock;
|
|
1261
1456
|
return node.nodeType == 1 && /^(DIV|P|LI|UL|OL|BLOCKQUOTE|DD|DT|H\d|SECTION|PRE)$/.test(node.nodeName);
|
|
1262
1457
|
}
|
|
1263
1458
|
function isBlocking(node) {
|
|
@@ -1597,6 +1792,12 @@ class Tile {
|
|
|
1597
1792
|
let last = this.children.length - 1;
|
|
1598
1793
|
return last < 0 ? null : this.children[last];
|
|
1599
1794
|
}
|
|
1795
|
+
get nodeParent() {
|
|
1796
|
+
let tile = this;
|
|
1797
|
+
while (!tile.node)
|
|
1798
|
+
tile = tile.parent;
|
|
1799
|
+
return tile;
|
|
1800
|
+
}
|
|
1600
1801
|
ignoreEvent(event) { return false; }
|
|
1601
1802
|
get ignoreMutations() { return false; }
|
|
1602
1803
|
toString() { return this.dom.nodeName + (this.children.length ? `(${this.children})` : ""); }
|
|
@@ -1673,7 +1874,7 @@ class CompositeTile extends Tile {
|
|
|
1673
1874
|
orientation = node.type.orientation == "row" ? 0 : 1;
|
|
1674
1875
|
if (node.isTextblock)
|
|
1675
1876
|
textblock = TextblockMap.get(state, start, node);
|
|
1676
|
-
else if (node.
|
|
1877
|
+
else if (node.isBlock)
|
|
1677
1878
|
textblock = null;
|
|
1678
1879
|
}
|
|
1679
1880
|
else if (node && node.isText) {
|
|
@@ -1693,7 +1894,7 @@ class CompositeTile extends Tile {
|
|
|
1693
1894
|
posAtCoordsRow(start, state, x, y, textblock) {
|
|
1694
1895
|
let result = rowScan(x, y, add => {
|
|
1695
1896
|
for (let child of this.children) {
|
|
1696
|
-
if (child.
|
|
1897
|
+
if (child instanceof WidgetTile && !child.widget.type.inFlow)
|
|
1697
1898
|
continue;
|
|
1698
1899
|
let rects, { dom } = child;
|
|
1699
1900
|
if (dom.nodeType == 1)
|
|
@@ -1711,6 +1912,14 @@ class CompositeTile extends Tile {
|
|
|
1711
1912
|
return null;
|
|
1712
1913
|
let { closest, rect } = result;
|
|
1713
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
|
+
}
|
|
1714
1923
|
return closest.posAtCoordsInner(pos + closest.boundary, state, x, Math.max(rect.top, Math.min(rect.bottom, y)), textblock, 0);
|
|
1715
1924
|
}
|
|
1716
1925
|
posAtCoordsCol(start, state, x, y, textblock) {
|
|
@@ -1795,29 +2004,29 @@ class DocTile extends CompositeTile {
|
|
|
1795
2004
|
let changed = findChangedRanges(this.state, this.decoSet, state, decoSet, changes);
|
|
1796
2005
|
return this.updateRanges(state, decoSet, changed, wg, composition);
|
|
1797
2006
|
}
|
|
1798
|
-
updateRanges(state, decoSet,
|
|
2007
|
+
updateRanges(state, decoSet, changes, wg, composition) {
|
|
1799
2008
|
let wrapper = composition?.wrapCursor || null;
|
|
1800
|
-
if ((
|
|
2009
|
+
if (isEmpty(changes) && eqArray(wrapper, this.cursorWrapper))
|
|
1801
2010
|
return this;
|
|
1802
2011
|
if (composition) {
|
|
1803
|
-
let separated =
|
|
2012
|
+
let separated = separateChange(changes, composition.fromB, composition.toB);
|
|
1804
2013
|
if (!separated)
|
|
1805
2014
|
composition = null;
|
|
1806
2015
|
else
|
|
1807
|
-
|
|
2016
|
+
changes = separated;
|
|
1808
2017
|
}
|
|
1809
2018
|
let builder = new ContentUpdate(state, this, wg, new DecoIterator(state, decoSet), wrapper);
|
|
1810
|
-
for (let i = 0, posB = 0, startCovered = false; i <
|
|
1811
|
-
let len =
|
|
2019
|
+
for (let i = 0, posB = 0, startCovered = false; i < changes.length;) {
|
|
2020
|
+
let len = changes[i++], ins = changes[i++];
|
|
1812
2021
|
if (composition && posB == composition.fromB && ins >= 0) {
|
|
1813
2022
|
if (!startCovered)
|
|
1814
2023
|
builder.update(0, false);
|
|
1815
2024
|
builder.composition(composition, len);
|
|
1816
|
-
if (ins && (startCovered = i ==
|
|
2025
|
+
if (ins && (startCovered = i == changes.length || changes[i + 1] == -1))
|
|
1817
2026
|
builder.update(0, false);
|
|
1818
2027
|
}
|
|
1819
2028
|
else if (ins == -1) {
|
|
1820
|
-
builder.keep(len, !startCovered, i ==
|
|
2029
|
+
builder.keep(len, !startCovered, i == changes.length);
|
|
1821
2030
|
startCovered = false;
|
|
1822
2031
|
}
|
|
1823
2032
|
else if (ins == -2) {
|
|
@@ -1886,7 +2095,8 @@ class DocTile extends CompositeTile {
|
|
|
1886
2095
|
else if (pos == end)
|
|
1887
2096
|
i = j + 1;
|
|
1888
2097
|
}
|
|
1889
|
-
if (
|
|
2098
|
+
if (!ch.isPoint &&
|
|
2099
|
+
((ch.isPlotContent || ch.isNodeInner) && !ch.boundary ? pos >= off && pos <= end : pos > off && pos < end)) {
|
|
1890
2100
|
if (ch instanceof TextTile)
|
|
1891
2101
|
return new TilePos(ch, pos - off, pos);
|
|
1892
2102
|
else if (ch.isAtom) {
|
|
@@ -1995,6 +2205,8 @@ class DocTile extends CompositeTile {
|
|
|
1995
2205
|
dom = dom.parentNode;
|
|
1996
2206
|
domBefore = dom.previousSibling;
|
|
1997
2207
|
}
|
|
2208
|
+
if (elt.node && elt.node.isInline && elt.node.isPlot && (!domBefore || !domBefore.nextSibling))
|
|
2209
|
+
return domBefore ? elt.posAfter : elt.posBefore;
|
|
1998
2210
|
while (domBefore && !((eltBefore = domBefore.wgTile) && eltBefore.parent == elt))
|
|
1999
2211
|
domBefore = domBefore.previousSibling;
|
|
2000
2212
|
return domBefore ? elt.posBeforeChild(eltBefore) + eltBefore.length : elt.posAtStart;
|
|
@@ -2189,7 +2401,7 @@ class TilePointer {
|
|
|
2189
2401
|
}
|
|
2190
2402
|
if (!dist && next.isNodeInner && !nodeBoundary)
|
|
2191
2403
|
break;
|
|
2192
|
-
if (next.length
|
|
2404
|
+
if (next.length < dist || next.length == dist && (next.isPoint || next.boundary)) {
|
|
2193
2405
|
if (walker)
|
|
2194
2406
|
walker.skip(next, 0, next.length);
|
|
2195
2407
|
dist -= next.length;
|
|
@@ -2425,7 +2637,7 @@ class ContentUpdate {
|
|
|
2425
2637
|
if (mark.type.element) {
|
|
2426
2638
|
this.openWrapper(renderMarkWrapper(mark), mark.spanning, false);
|
|
2427
2639
|
}
|
|
2428
|
-
this.new.addChild(new WidgetTile(
|
|
2640
|
+
this.new.addChild(new WidgetTile(Widget.img, null, 16 | 32, Widget.img.render(this.wg)));
|
|
2429
2641
|
return;
|
|
2430
2642
|
}
|
|
2431
2643
|
let found = [];
|
|
@@ -2626,22 +2838,17 @@ class ContentUpdate {
|
|
|
2626
2838
|
while (tile.isNodeInner)
|
|
2627
2839
|
tile = tile.parent;
|
|
2628
2840
|
let node = tile.node;
|
|
2629
|
-
if (!node || !node.isPlot || !(node.isTextblock || node.
|
|
2841
|
+
if (!node || !node.isPlot || !(node.isTextblock || node.isInline))
|
|
2630
2842
|
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
|
-
}
|
|
2636
2843
|
let hasHack = -1, needsHack = true;
|
|
2637
2844
|
for (let parent = this.new, i = parent.children.length;;) {
|
|
2638
2845
|
if (i > 0) {
|
|
2639
2846
|
let next = parent.children[--i];
|
|
2640
2847
|
if (next.isNodeInner || next instanceof WidgetTile && !next.widget.type.inFlow) ;
|
|
2641
|
-
else if (next instanceof WidgetTile && next.widget ==
|
|
2848
|
+
else if (next instanceof WidgetTile && next.widget == Widget.br && parent == this.new) {
|
|
2642
2849
|
hasHack = i;
|
|
2643
2850
|
}
|
|
2644
|
-
else if (next.dom.nodeName == "BR"
|
|
2851
|
+
else if (next.dom.nodeName == "BR") {
|
|
2645
2852
|
break;
|
|
2646
2853
|
}
|
|
2647
2854
|
else if (next instanceof CompositeTile && !next.isAtom) {
|
|
@@ -2666,7 +2873,7 @@ class ContentUpdate {
|
|
|
2666
2873
|
this.new.children.splice(hasHack, 1);
|
|
2667
2874
|
}
|
|
2668
2875
|
else if (needsHack) {
|
|
2669
|
-
this.new.addChild(new WidgetTile(
|
|
2876
|
+
this.new.addChild(new WidgetTile(Widget.br, null, 16 | 64, Widget.br.render(this.wg)));
|
|
2670
2877
|
}
|
|
2671
2878
|
}
|
|
2672
2879
|
up() {
|
|
@@ -2793,47 +3000,6 @@ function updateAttributes(dom, a, b) {
|
|
|
2793
3000
|
}
|
|
2794
3001
|
return changed;
|
|
2795
3002
|
}
|
|
2796
|
-
const brHack = /*@__PURE__*/Widget.create({
|
|
2797
|
-
render() { return document.createElement("br"); },
|
|
2798
|
-
editable: true
|
|
2799
|
-
});
|
|
2800
|
-
const imgHack = /*@__PURE__*/Widget.create({
|
|
2801
|
-
render() {
|
|
2802
|
-
let img = document.createElement("img");
|
|
2803
|
-
img.className = "wg-buffer";
|
|
2804
|
-
return img;
|
|
2805
|
-
},
|
|
2806
|
-
editable: true
|
|
2807
|
-
});
|
|
2808
|
-
function separateComposition(sections, comp) {
|
|
2809
|
-
let result = [], { fromB, toB } = comp;
|
|
2810
|
-
let lenI = 0, dLen = 0;
|
|
2811
|
-
for (let posB = 0, done = false, i = 0; i < sections.length;) {
|
|
2812
|
-
let len = sections[i++], ins = sections[i++], endB = posB + (ins < 0 ? len : ins);
|
|
2813
|
-
if (fromB > endB || toB < posB) {
|
|
2814
|
-
result.push(len, ins);
|
|
2815
|
-
}
|
|
2816
|
-
else {
|
|
2817
|
-
if (ins >= 0) {
|
|
2818
|
-
if (posB < fromB || endB > toB)
|
|
2819
|
-
return null;
|
|
2820
|
-
dLen = len - ins;
|
|
2821
|
-
}
|
|
2822
|
-
if (posB < fromB)
|
|
2823
|
-
result.push(fromB - posB, ins);
|
|
2824
|
-
if (!done) {
|
|
2825
|
-
lenI = result.length;
|
|
2826
|
-
result.push(0, comp.text.length);
|
|
2827
|
-
done = true;
|
|
2828
|
-
}
|
|
2829
|
-
if (endB > toB)
|
|
2830
|
-
result.push(endB - toB, ins);
|
|
2831
|
-
}
|
|
2832
|
-
posB = endB;
|
|
2833
|
-
}
|
|
2834
|
-
result[lenI] = comp.text.length + dLen;
|
|
2835
|
-
return result;
|
|
2836
|
-
}
|
|
2837
3003
|
|
|
2838
3004
|
class Coords {
|
|
2839
3005
|
ref;
|
|
@@ -2846,15 +3012,13 @@ class Coords {
|
|
|
2846
3012
|
function coordsAtPos(wg, pos, assoc) {
|
|
2847
3013
|
let { offset, tile, pos: tilePos } = wg.docTile.resolve(pos, assoc);
|
|
2848
3014
|
if (tile instanceof TextTile) {
|
|
2849
|
-
let
|
|
2850
|
-
|
|
2851
|
-
return new Coords(tile, singleRect(textRange(node, 0, 0), 1));
|
|
2852
|
-
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;
|
|
2853
3017
|
if (side < 0)
|
|
2854
3018
|
to++;
|
|
2855
3019
|
else
|
|
2856
3020
|
from--;
|
|
2857
|
-
return new Coords(tile, flattenV(singleRect(textRange(
|
|
3021
|
+
return new Coords(tile, flattenV(singleRect(textRange(tile.dom, from, to), side, true), (side < 0) == ltrAt(wg.state, pos, assoc)));
|
|
2858
3022
|
}
|
|
2859
3023
|
let tagTile = tile;
|
|
2860
3024
|
while (!tagTile.node)
|
|
@@ -2878,6 +3042,8 @@ function coordsAtPos(wg, pos, assoc) {
|
|
|
2878
3042
|
let before = tile.children[i - 1];
|
|
2879
3043
|
if (before instanceof WidgetTile && !before.widget.type.inFlow)
|
|
2880
3044
|
continue;
|
|
3045
|
+
if (before.dom.nodeName == "BR")
|
|
3046
|
+
break;
|
|
2881
3047
|
let rect = singleRect(before.dom, 1);
|
|
2882
3048
|
if (rect.width || rect.height)
|
|
2883
3049
|
return new Coords(before, horizontal ? flattenH(rect, false) : flattenV(rect, !ltrAt(wg.state, pos, 1)));
|
|
@@ -3293,6 +3459,32 @@ function readDOMSelection(wg, range) {
|
|
|
3293
3459
|
: wg.posAtDOM(range.focusNode, range.focusOffset);
|
|
3294
3460
|
return GardSelection.range(anchor, head);
|
|
3295
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
|
+
}
|
|
3296
3488
|
const Y_STEP = 5;
|
|
3297
3489
|
function moveVertically(wg, start, forward, distance = 0, selectNode = false) {
|
|
3298
3490
|
let editorRect = wg.contentDOM.getBoundingClientRect();
|
|
@@ -3515,13 +3707,21 @@ class DOMObserver {
|
|
|
3515
3707
|
this.wg.scheduleFlush();
|
|
3516
3708
|
}
|
|
3517
3709
|
pollSelection() {
|
|
3710
|
+
let { wg } = this;
|
|
3518
3711
|
if (this.selectionChanged &&
|
|
3519
|
-
(
|
|
3712
|
+
(wg.hasFocus || !wg.focusable) && hasSelection(wg.contentDOM, this.selectionRange)) {
|
|
3520
3713
|
this.selectionChanged = false;
|
|
3521
|
-
let
|
|
3522
|
-
|
|
3523
|
-
|
|
3524
|
-
|
|
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 });
|
|
3525
3725
|
}
|
|
3526
3726
|
}
|
|
3527
3727
|
}
|
|
@@ -3570,11 +3770,7 @@ class DOMObserver {
|
|
|
3570
3770
|
return records;
|
|
3571
3771
|
}
|
|
3572
3772
|
addDirtyRange(from, to) {
|
|
3573
|
-
|
|
3574
|
-
sections.push(to - from, -2);
|
|
3575
|
-
if (to < len)
|
|
3576
|
-
sections.push(len - to, -1);
|
|
3577
|
-
this.dirty = this.dirty ? ChangeSet.composeSections(this.dirty, sections) : sections;
|
|
3773
|
+
addRange(this.dirty || (this.dirty = []), from, to);
|
|
3578
3774
|
}
|
|
3579
3775
|
processRecords(records) {
|
|
3580
3776
|
for (let record of records) {
|
|
@@ -3890,6 +4086,7 @@ class InputState {
|
|
|
3890
4086
|
lastKeyCode = 0;
|
|
3891
4087
|
lastKeyTime = 0;
|
|
3892
4088
|
lastTouchTime = 0;
|
|
4089
|
+
lastTouchEvent = null;
|
|
3893
4090
|
lastScrollTop = 0;
|
|
3894
4091
|
lastScrollLeft = 0;
|
|
3895
4092
|
lastContextMenu = 0;
|
|
@@ -4023,8 +4220,8 @@ class InputState {
|
|
|
4023
4220
|
let type = event.inputType, range;
|
|
4024
4221
|
let { wg } = this, sel = wg.state.selection;
|
|
4025
4222
|
if (data.domRange) {
|
|
4026
|
-
range = { from:
|
|
4027
|
-
to:
|
|
4223
|
+
range = { from: this.domMapping.mapPos(data.domRange.from),
|
|
4224
|
+
to: this.domMapping.mapPos(data.domRange.to) };
|
|
4028
4225
|
if (!this.domMapping.empty && type == "insertText" && !this.composing && range.from == range.to) {
|
|
4029
4226
|
let fromMax = this.domMapping.mapPos(data.domRange.from, 1);
|
|
4030
4227
|
if (range.from <= sel.from && fromMax >= sel.to)
|
|
@@ -4118,6 +4315,10 @@ class InputState {
|
|
|
4118
4315
|
: prev == after ? after : before;
|
|
4119
4316
|
}
|
|
4120
4317
|
}
|
|
4318
|
+
recordTouch(e) {
|
|
4319
|
+
this.lastTouchTime = Date.now();
|
|
4320
|
+
this.lastTouchEvent = e;
|
|
4321
|
+
}
|
|
4121
4322
|
connect() {
|
|
4122
4323
|
this.ensureHandlers(this.wg.state);
|
|
4123
4324
|
}
|
|
@@ -4126,39 +4327,6 @@ class InputState {
|
|
|
4126
4327
|
this.mouseSelection.disconnect();
|
|
4127
4328
|
}
|
|
4128
4329
|
}
|
|
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
|
-
}
|
|
4162
4330
|
function isSingleChar(doc, from, to) {
|
|
4163
4331
|
if (to > from + 10)
|
|
4164
4332
|
return false;
|
|
@@ -4350,23 +4518,6 @@ function eventBelongsToEditor(wg, event) {
|
|
|
4350
4518
|
function queryPos(wg, event) {
|
|
4351
4519
|
return wg.posAtCoords({ x: event.clientX, y: event.clientY });
|
|
4352
4520
|
}
|
|
4353
|
-
function rangeForClick(wg, pos, type) {
|
|
4354
|
-
if (type < 3 && pos.target != null) {
|
|
4355
|
-
let target = wg.state.doc.nodeAt(pos.target);
|
|
4356
|
-
if (target && target.type.isSelectable && wg.state.isAtom(target.type))
|
|
4357
|
-
return GardSelection.node(pos.target, target);
|
|
4358
|
-
}
|
|
4359
|
-
if (type == 1) { return GardSelection.near(wg.state, pos.pos, pos.side || -1);
|
|
4360
|
-
}
|
|
4361
|
-
else if (type == 2) { return wg.state.wordAt(pos.pos, pos.side || 1);
|
|
4362
|
-
}
|
|
4363
|
-
else { let cx = wg.state.doc.resolve(pos.pos), block = cx.textblockParent;
|
|
4364
|
-
if (block)
|
|
4365
|
-
return GardSelection.range(block.start, block.end);
|
|
4366
|
-
else
|
|
4367
|
-
return GardSelection.near(wg.state, pos.pos, pos.side || -1);
|
|
4368
|
-
}
|
|
4369
|
-
}
|
|
4370
4521
|
function basicMouseSelection(wg, event) {
|
|
4371
4522
|
let start = queryPos(wg, event), type = event.detail;
|
|
4372
4523
|
let startSel = wg.state.selection;
|
|
@@ -4462,11 +4613,13 @@ function compositionUpdate(wg, event) {
|
|
|
4462
4613
|
if (!wg.inputState.composing) {
|
|
4463
4614
|
wg.inputState.composing = { changes: 0, target: null };
|
|
4464
4615
|
let wrap = null;
|
|
4465
|
-
if (!
|
|
4616
|
+
if (!event.data) {
|
|
4466
4617
|
let sel = wg.state.selection, rSel = wg.state.sel;
|
|
4467
4618
|
if (sel.empty && (sel instanceof GardSelection.Text && sel.marks || !rSel.head.inText && rSel.head.index) &&
|
|
4468
4619
|
!eqArray(rSel.head.nodeBefore?.tag.marks, rSel.activeMarks))
|
|
4469
4620
|
wrap = rSel.activeMarks;
|
|
4621
|
+
else if (sel.empty && inlineBoundNear(wg.state.sel.head))
|
|
4622
|
+
wrap = rSel.activeMarks;
|
|
4470
4623
|
}
|
|
4471
4624
|
if (wrap)
|
|
4472
4625
|
try {
|
|
@@ -4478,6 +4631,13 @@ function compositionUpdate(wg, event) {
|
|
|
4478
4631
|
}
|
|
4479
4632
|
}
|
|
4480
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
|
+
}
|
|
4481
4641
|
function isDeletionInputEvent(type) { return /^delete(Content|Word)/.test(type); }
|
|
4482
4642
|
const inputTypeCommands = /*@__PURE__*/(() => ({
|
|
4483
4643
|
historyUndo: undo,
|
|
@@ -4654,12 +4814,8 @@ const baseObservers = {
|
|
|
4654
4814
|
wg.inputState.lastScrollTop = wg.scrollDOM.scrollTop;
|
|
4655
4815
|
wg.inputState.lastScrollLeft = wg.scrollDOM.scrollLeft;
|
|
4656
4816
|
},
|
|
4657
|
-
touchstart(wg, e) {
|
|
4658
|
-
|
|
4659
|
-
},
|
|
4660
|
-
touchmove(wg) {
|
|
4661
|
-
wg.inputState.lastTouchTime = Date.now();
|
|
4662
|
-
},
|
|
4817
|
+
touchstart(wg, e) { wg.inputState.recordTouch(e); },
|
|
4818
|
+
touchmove(wg, e) { wg.inputState.recordTouch(e); },
|
|
4663
4819
|
focus(wg) {
|
|
4664
4820
|
if (!wg.scrollDOM.scrollTop && (wg.inputState.lastScrollTop || wg.inputState.lastScrollLeft)) {
|
|
4665
4821
|
wg.scrollDOM.scrollTop = wg.inputState.lastScrollTop;
|
|
@@ -4871,6 +5027,10 @@ function alignOffset(align, height) {
|
|
|
4871
5027
|
return height * (+align.slice(0, align.length - 1)) * 100;
|
|
4872
5028
|
return 0;
|
|
4873
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
|
+
}
|
|
4874
5034
|
const VertWidth = 30, VertGap = 5;
|
|
4875
5035
|
function getCursorInfo(wg, plugin, cont) {
|
|
4876
5036
|
let { state } = wg;
|
|
@@ -4880,7 +5040,7 @@ function getCursorInfo(wg, plugin, cont) {
|
|
|
4880
5040
|
let { ref, rect } = coordsAtPos(wg, head, headSide);
|
|
4881
5041
|
let doc = wg.contentDOM.getBoundingClientRect();
|
|
4882
5042
|
if (!sel.head.parent.node.inlineContent) {
|
|
4883
|
-
let width = Math.
|
|
5043
|
+
let width = Math.min(VertWidth, rect.width), top = rect.top;
|
|
4884
5044
|
let other = wg.coordsAtPos(head, headSide > 0 ? -1 : 1);
|
|
4885
5045
|
if (other.top == other.bottom && other.top != top) {
|
|
4886
5046
|
let move = Math.min(VertGap, Math.abs(other.top - top) / 2);
|
|
@@ -4898,7 +5058,7 @@ function getCursorInfo(wg, plugin, cont) {
|
|
|
4898
5058
|
plugin.cached = { style, marks, parent: sel.head.parent.node.tag };
|
|
4899
5059
|
let height = style ? style.height : rect.height;
|
|
4900
5060
|
let bot = rect.bottom;
|
|
4901
|
-
if (vertRect && (vertRect
|
|
5061
|
+
if (vertRect && vertOverlap(vertRect, rect)) {
|
|
4902
5062
|
bot = vertRect.bottom;
|
|
4903
5063
|
}
|
|
4904
5064
|
else {
|
|
@@ -4922,7 +5082,7 @@ function getCursorInfo(wg, plugin, cont) {
|
|
|
4922
5082
|
return finish(CursorStyle.read(ref.dom, rect.height), rect);
|
|
4923
5083
|
}
|
|
4924
5084
|
let pos = sel.head.parent.start, foundRect, foundNode;
|
|
4925
|
-
for (let sibling of sel.head.parent.node.content) {
|
|
5085
|
+
scan: for (let sibling of sel.head.parent.node.content) {
|
|
4926
5086
|
if (sibling.isText && Mark.sameSet(sibling.marks, marks)) {
|
|
4927
5087
|
let { tile } = wg.docTile.resolve(pos, 1);
|
|
4928
5088
|
if (tile instanceof TextTile) {
|
|
@@ -4930,8 +5090,8 @@ function getCursorInfo(wg, plugin, cont) {
|
|
|
4930
5090
|
foundNode = tile.dom;
|
|
4931
5091
|
for (let i = 0; i < rects.length; i++) {
|
|
4932
5092
|
foundRect = rects[i];
|
|
4933
|
-
if (foundRect
|
|
4934
|
-
break;
|
|
5093
|
+
if (vertOverlap(foundRect, rect))
|
|
5094
|
+
break scan;
|
|
4935
5095
|
}
|
|
4936
5096
|
}
|
|
4937
5097
|
}
|
|
@@ -5149,7 +5309,7 @@ class Wordgard {
|
|
|
5149
5309
|
}
|
|
5150
5310
|
runUpdate(update, domChanges) {
|
|
5151
5311
|
let composition = this.composing ? getCompositionInfo(this) : null;
|
|
5152
|
-
let changes = domChanges ?
|
|
5312
|
+
let changes = domChanges ? addUpdated(update.changes.sections, domChanges) : update.changes.sections;
|
|
5153
5313
|
let prevDocTile = this.docTile;
|
|
5154
5314
|
if (!update.empty) {
|
|
5155
5315
|
this.updatePlugins(update);
|
|
@@ -5860,6 +6020,7 @@ class BarButton {
|
|
|
5860
6020
|
this.item = item;
|
|
5861
6021
|
this.dom = document.createElement("button");
|
|
5862
6022
|
this.dom.className = "wg-menu-button";
|
|
6023
|
+
this.dom.type = "button";
|
|
5863
6024
|
this.dom.tabIndex = -1;
|
|
5864
6025
|
labelButton(wg, this.dom, item.label);
|
|
5865
6026
|
if (item.description) {
|
|
@@ -5945,6 +6106,7 @@ class BarSubmenu {
|
|
|
5945
6106
|
this.item = item;
|
|
5946
6107
|
this.dom = document.createElement("wg-submenu");
|
|
5947
6108
|
this.button = this.dom.appendChild(document.createElement("button"));
|
|
6109
|
+
this.button.type = "button";
|
|
5948
6110
|
this.button.tabIndex = -1;
|
|
5949
6111
|
this.button.className = "wg-menu-button";
|
|
5950
6112
|
this.button.setAttribute("aria-haspopup", "true");
|