@nerd-bible/wordgard 0.3.6 → 0.5.2-beta2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/editor.js CHANGED
@@ -1,11 +1,167 @@
1
1
  import { GardState, GardSelection, TextblockMap, BidiSpan, Transaction } from 'wordgard/state';
2
- import { Attributes, Elt, Node, Leaf, ChangeSet, parse, Slice, Plot, serialize, Pos, ValidationError, Mark } from 'wordgard/doc';
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
- map(changes) {
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 = 0, i = 0;
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, posB.length), values = new Array(pos.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
- let nextA = a < posA.length ? posA[a] : 1e9;
406
- let nextB = b < posB.length ? posB[b] : 1e9;
407
- let cmp = nextA - nextB || this.values[a].side - other.values[b].side;
408
- if (cmp < 0) {
409
- pos[i] = posA[a];
410
- values[i++] = this.values[a++];
411
- }
412
- else if (nextB < 1e9) {
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
- if (--i < 0)
469
- break;
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.pos = this.set.positions[i];
655
+ this.from = this.set.positions[i];
499
656
  this.value = this.set.values[i];
500
657
  }
501
658
  else {
502
- this.pos = 1e8;
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
- map(changes) {
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 = 0, i = 0;
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(from, i, end);
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(to, i, toA + 1);
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
- function addRange(ranges, from, to) {
687
- let last = ranges.length - 1;
688
- if (last < 0 || ranges[last] < from)
689
- ranges.push(from, to);
690
- else
691
- ranges[last] = Math.max(to, ranges[last]);
692
- }
693
- function joinRanges(ranges) {
694
- if (ranges.length == 1)
695
- return ranges[0];
696
- let result = [], index = ranges.map(() => 0);
697
- for (;;) {
698
- let minI = -1, minFrom = -1;
699
- for (let i = 0; i < ranges.length; i++) {
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
- if (minI < 0)
707
- return result;
708
- let idx = index[minI], set = ranges[minI];
709
- addRange(result, set[idx], set[idx + 1]);
710
- index[minI] += 2;
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.push(pos);
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(sections, prev, changes) {
1031
+ function addAtomicityChanges(changes, prev, nodes) {
785
1032
  let added = [];
786
- let scan = prev.doc.resolve(0), last = -1, sectionPos = 0, sectionI = 0, off = 0;
787
- for (let posB of changes.sort()) {
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 = sections[sectionI++], ins = sections[sectionI++];
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
- if (!added.length)
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 { pos: pointPos, side: pointSide } = pointHeap.length ? pointHeap[0] : { pos: 1e9, side: 1 };
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.pos - b.pos || a.side - b.side;
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.type.isBlock;
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.type.isBlock)
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.isPoint)
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, sections, wg, composition) {
2007
+ updateRanges(state, decoSet, changes, wg, composition) {
1799
2008
  let wrapper = composition?.wrapCursor || null;
1800
- if ((!sections.length || sections.length == 2 && sections[1] == -1) && eqArray(wrapper, this.cursorWrapper))
2009
+ if (isEmpty(changes) && eqArray(wrapper, this.cursorWrapper))
1801
2010
  return this;
1802
2011
  if (composition) {
1803
- let separated = separateComposition(sections, composition);
2012
+ let separated = separateChange(changes, composition.fromB, composition.toB);
1804
2013
  if (!separated)
1805
2014
  composition = null;
1806
2015
  else
1807
- sections = separated;
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 < sections.length;) {
1811
- let len = sections[i++], ins = sections[i++];
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
- builder.update(0, false);
2023
+ builder.update(0, true);
1815
2024
  builder.composition(composition, len);
1816
- if (ins && (startCovered = i == sections.length || sections[i + 1] == -1))
1817
- builder.update(0, false);
2025
+ if (ins && (startCovered = i == changes.length || changes[i + 1] == -1))
2026
+ builder.update(0, true);
1818
2027
  }
1819
2028
  else if (ins == -1) {
1820
- builder.keep(len, !startCovered, i == sections.length);
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 (ch.isPlotContent && !ch.boundary ? pos >= off && pos <= end : pos > off && pos < end) {
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 <= dist) {
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(imgHack, null, 16 | 32, imgHack.render(this.wg)));
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.type.isInline))
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 == brHack && parent == this.new) {
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" || next instanceof TextTile && /\n$/.test(next.text)) {
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(brHack, null, 16 | 64, brHack.render(this.wg)));
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 node = tile.dom, len = node.nodeValue.length;
2850
- if (!len)
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(node, from, to), side, true), (side < 0) == ltrAt(wg.state, pos, assoc)));
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
- (this.wg.hasFocus || !this.wg.focusable) && hasSelection(this.wg.contentDOM, this.selectionRange)) {
3712
+ (wg.hasFocus || !wg.focusable) && hasSelection(wg.contentDOM, this.selectionRange)) {
3520
3713
  this.selectionChanged = false;
3521
- let sel = readDOMSelection(this.wg, this.selectionRange);
3522
- if (!sel.eqPos(this.wg.state.selection)) {
3523
- let userEvent = this.wg.inputState.lastTouchTime > Date.now() - 100 ? "select.pointer" : "select";
3524
- this.wg.dispatch({ selection: sel, userEvent });
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
- let sections = from ? [from, -1] : [], len = this.wg.flushedState.doc.length;
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;
@@ -3993,11 +4190,13 @@ class InputState {
3993
4190
  this.domChanges = null;
3994
4191
  }
3995
4192
  getDOMPos(node, offset) {
4193
+ if (!this.domChanges)
4194
+ return this.wg.docTile.posFromDOM(node, offset);
3996
4195
  if (node.nodeType == 1 && offset && node.childNodes[offset - 1].nodeType == 3) {
3997
4196
  node = node.childNodes[offset - 1];
3998
4197
  offset = node.nodeValue.length;
3999
4198
  }
4000
- let inText = node.nodeType == 3;
4199
+ let inText = node.nodeType == 3 && !this.wg.docTile.nearest(node)?.isPoint;
4001
4200
  let ref = this.wg.docTile.posFromDOM(node, inText ? 0 : offset);
4002
4201
  let dir = -1;
4003
4202
  let textBefore = node.parentNode && textNodeBefore(node.parentNode, domIndex(node));
@@ -4023,8 +4222,8 @@ class InputState {
4023
4222
  let type = event.inputType, range;
4024
4223
  let { wg } = this, sel = wg.state.selection;
4025
4224
  if (data.domRange) {
4026
- range = { from: snapToSel(wg.state, this.domMapping.mapPos(data.domRange.from)),
4027
- to: snapToSel(wg.state, this.domMapping.mapPos(data.domRange.to)) };
4225
+ range = { from: this.domMapping.mapPos(data.domRange.from),
4226
+ to: this.domMapping.mapPos(data.domRange.to) };
4028
4227
  if (!this.domMapping.empty && type == "insertText" && !this.composing && range.from == range.to) {
4029
4228
  let fromMax = this.domMapping.mapPos(data.domRange.from, 1);
4030
4229
  if (range.from <= sel.from && fromMax >= sel.to)
@@ -4113,11 +4312,17 @@ class InputState {
4113
4312
  }
4114
4313
  else {
4115
4314
  let tileBefore = Tile.get(before), tileAfter = Tile.get(after);
4116
- return !tileBefore || tileBefore.text != before.nodeValue ? before
4117
- : !tileAfter || tileAfter.text != after.nodeValue ? after
4118
- : prev == after ? after : before;
4315
+ if (tileBefore instanceof TextTile && tileBefore.text != before.nodeValue)
4316
+ return before;
4317
+ if (tileAfter instanceof TextTile && tileAfter.text != after.nodeValue)
4318
+ return after;
4319
+ return !tileBefore ? before : !tileAfter ? after : prev == after ? after : before;
4119
4320
  }
4120
4321
  }
4322
+ recordTouch(e) {
4323
+ this.lastTouchTime = Date.now();
4324
+ this.lastTouchEvent = e;
4325
+ }
4121
4326
  connect() {
4122
4327
  this.ensureHandlers(this.wg.state);
4123
4328
  }
@@ -4126,39 +4331,6 @@ class InputState {
4126
4331
  this.mouseSelection.disconnect();
4127
4332
  }
4128
4333
  }
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
4334
  function isSingleChar(doc, from, to) {
4163
4335
  if (to > from + 10)
4164
4336
  return false;
@@ -4350,23 +4522,6 @@ function eventBelongsToEditor(wg, event) {
4350
4522
  function queryPos(wg, event) {
4351
4523
  return wg.posAtCoords({ x: event.clientX, y: event.clientY });
4352
4524
  }
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
4525
  function basicMouseSelection(wg, event) {
4371
4526
  let start = queryPos(wg, event), type = event.detail;
4372
4527
  let startSel = wg.state.selection;
@@ -4462,11 +4617,13 @@ function compositionUpdate(wg, event) {
4462
4617
  if (!wg.inputState.composing) {
4463
4618
  wg.inputState.composing = { changes: 0, target: null };
4464
4619
  let wrap = null;
4465
- if (!wg.inputState.composing.changes && !event.data) {
4620
+ if (!event.data) {
4466
4621
  let sel = wg.state.selection, rSel = wg.state.sel;
4467
4622
  if (sel.empty && (sel instanceof GardSelection.Text && sel.marks || !rSel.head.inText && rSel.head.index) &&
4468
4623
  !eqArray(rSel.head.nodeBefore?.tag.marks, rSel.activeMarks))
4469
4624
  wrap = rSel.activeMarks;
4625
+ else if (sel.empty && inlineBoundNear(wg.state.sel.head))
4626
+ wrap = rSel.activeMarks;
4470
4627
  }
4471
4628
  if (wrap)
4472
4629
  try {
@@ -4478,6 +4635,13 @@ function compositionUpdate(wg, event) {
4478
4635
  }
4479
4636
  }
4480
4637
  }
4638
+ function inlineBoundNear(pos) {
4639
+ let { parent, index, inText } = pos;
4640
+ if (inText || !parent.node.inlineContent)
4641
+ return false;
4642
+ return (index ? parent.node.content[index - 1].isPlot : parent.node.isInline) ||
4643
+ (index < parent.node.content.length ? parent.node.content[index].isPlot : parent.node.isInline);
4644
+ }
4481
4645
  function isDeletionInputEvent(type) { return /^delete(Content|Word)/.test(type); }
4482
4646
  const inputTypeCommands = /*@__PURE__*/(() => ({
4483
4647
  historyUndo: undo,
@@ -4654,12 +4818,8 @@ const baseObservers = {
4654
4818
  wg.inputState.lastScrollTop = wg.scrollDOM.scrollTop;
4655
4819
  wg.inputState.lastScrollLeft = wg.scrollDOM.scrollLeft;
4656
4820
  },
4657
- touchstart(wg, e) {
4658
- wg.inputState.lastTouchTime = Date.now();
4659
- },
4660
- touchmove(wg) {
4661
- wg.inputState.lastTouchTime = Date.now();
4662
- },
4821
+ touchstart(wg, e) { wg.inputState.recordTouch(e); },
4822
+ touchmove(wg, e) { wg.inputState.recordTouch(e); },
4663
4823
  focus(wg) {
4664
4824
  if (!wg.scrollDOM.scrollTop && (wg.inputState.lastScrollTop || wg.inputState.lastScrollLeft)) {
4665
4825
  wg.scrollDOM.scrollTop = wg.inputState.lastScrollTop;
@@ -4871,6 +5031,10 @@ function alignOffset(align, height) {
4871
5031
  return height * (+align.slice(0, align.length - 1)) * 100;
4872
5032
  return 0;
4873
5033
  }
5034
+ function vertOverlap(a, b) {
5035
+ let margin = a.height / 3;
5036
+ return a.top < b.bottom - margin && a.bottom > b.top + margin;
5037
+ }
4874
5038
  const VertWidth = 30, VertGap = 5;
4875
5039
  function getCursorInfo(wg, plugin, cont) {
4876
5040
  let { state } = wg;
@@ -4880,7 +5044,7 @@ function getCursorInfo(wg, plugin, cont) {
4880
5044
  let { ref, rect } = coordsAtPos(wg, head, headSide);
4881
5045
  let doc = wg.contentDOM.getBoundingClientRect();
4882
5046
  if (!sel.head.parent.node.inlineContent) {
4883
- let width = Math.max(VertWidth, rect.width), top = rect.top;
5047
+ let width = Math.min(VertWidth, rect.width), top = rect.top;
4884
5048
  let other = wg.coordsAtPos(head, headSide > 0 ? -1 : 1);
4885
5049
  if (other.top == other.bottom && other.top != top) {
4886
5050
  let move = Math.min(VertGap, Math.abs(other.top - top) / 2);
@@ -4898,7 +5062,7 @@ function getCursorInfo(wg, plugin, cont) {
4898
5062
  plugin.cached = { style, marks, parent: sel.head.parent.node.tag };
4899
5063
  let height = style ? style.height : rect.height;
4900
5064
  let bot = rect.bottom;
4901
- if (vertRect && (vertRect.top < rect.bottom && vertRect.bottom > rect.top)) {
5065
+ if (vertRect && vertOverlap(vertRect, rect)) {
4902
5066
  bot = vertRect.bottom;
4903
5067
  }
4904
5068
  else {
@@ -4922,7 +5086,7 @@ function getCursorInfo(wg, plugin, cont) {
4922
5086
  return finish(CursorStyle.read(ref.dom, rect.height), rect);
4923
5087
  }
4924
5088
  let pos = sel.head.parent.start, foundRect, foundNode;
4925
- for (let sibling of sel.head.parent.node.content) {
5089
+ scan: for (let sibling of sel.head.parent.node.content) {
4926
5090
  if (sibling.isText && Mark.sameSet(sibling.marks, marks)) {
4927
5091
  let { tile } = wg.docTile.resolve(pos, 1);
4928
5092
  if (tile instanceof TextTile) {
@@ -4930,8 +5094,8 @@ function getCursorInfo(wg, plugin, cont) {
4930
5094
  foundNode = tile.dom;
4931
5095
  for (let i = 0; i < rects.length; i++) {
4932
5096
  foundRect = rects[i];
4933
- if (foundRect.top < rect.bottom && foundRect.bottom > rect.top)
4934
- break;
5097
+ if (vertOverlap(foundRect, rect))
5098
+ break scan;
4935
5099
  }
4936
5100
  }
4937
5101
  }
@@ -5149,7 +5313,7 @@ class Wordgard {
5149
5313
  }
5150
5314
  runUpdate(update, domChanges) {
5151
5315
  let composition = this.composing ? getCompositionInfo(this) : null;
5152
- let changes = domChanges ? ChangeSet.composeSections(domChanges, update.changes.sections) : update.changes.sections;
5316
+ let changes = domChanges ? addUpdated(update.changes.sections, domChanges) : update.changes.sections;
5153
5317
  let prevDocTile = this.docTile;
5154
5318
  if (!update.empty) {
5155
5319
  this.updatePlugins(update);
@@ -5860,6 +6024,7 @@ class BarButton {
5860
6024
  this.item = item;
5861
6025
  this.dom = document.createElement("button");
5862
6026
  this.dom.className = "wg-menu-button";
6027
+ this.dom.type = "button";
5863
6028
  this.dom.tabIndex = -1;
5864
6029
  labelButton(wg, this.dom, item.label);
5865
6030
  if (item.description) {
@@ -5945,6 +6110,7 @@ class BarSubmenu {
5945
6110
  this.item = item;
5946
6111
  this.dom = document.createElement("wg-submenu");
5947
6112
  this.button = this.dom.appendChild(document.createElement("button"));
6113
+ this.button.type = "button";
5948
6114
  this.button.tabIndex = -1;
5949
6115
  this.button.className = "wg-menu-button";
5950
6116
  this.button.setAttribute("aria-haspopup", "true");