@codemirror/view 6.16.0 → 6.17.1
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/CHANGELOG.md +32 -0
- package/dist/index.cjs +694 -433
- package/dist/index.d.cts +100 -64
- package/dist/index.d.ts +100 -64
- package/dist/index.js +695 -432
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { EditorState, Text, RangeSet, MapMode, RangeValue, Facet, StateEffect, ChangeSet, findClusterBreak, EditorSelection, findColumn, CharCategory, Annotation,
|
|
1
|
+
import { EditorState, Text, RangeSet, MapMode, RangeValue, Facet, StateEffect, ChangeSet, findClusterBreak, EditorSelection, findColumn, CharCategory, Annotation, Transaction, Prec, codePointAt, codePointSize, combineConfig, StateField, RangeSetBuilder, countColumn } from '@codemirror/state';
|
|
2
2
|
import { StyleModule } from 'style-mod';
|
|
3
3
|
import { keyName, base, shift } from 'w3c-keyname';
|
|
4
4
|
|
|
@@ -336,7 +336,7 @@ class ContentView {
|
|
|
336
336
|
constructor() {
|
|
337
337
|
this.parent = null;
|
|
338
338
|
this.dom = null;
|
|
339
|
-
this.flags = 2 /* NodeDirty */;
|
|
339
|
+
this.flags = 2 /* ViewFlag.NodeDirty */;
|
|
340
340
|
}
|
|
341
341
|
get overrideDOMText() { return null; }
|
|
342
342
|
get posAtStart() {
|
|
@@ -358,18 +358,18 @@ class ContentView {
|
|
|
358
358
|
return this.posBefore(view) + view.length;
|
|
359
359
|
}
|
|
360
360
|
sync(view, track) {
|
|
361
|
-
if (this.flags & 2 /* NodeDirty */) {
|
|
361
|
+
if (this.flags & 2 /* ViewFlag.NodeDirty */) {
|
|
362
362
|
let parent = this.dom;
|
|
363
363
|
let prev = null, next;
|
|
364
364
|
for (let child of this.children) {
|
|
365
|
-
if (child.flags & 7 /* Dirty */) {
|
|
365
|
+
if (child.flags & 7 /* ViewFlag.Dirty */) {
|
|
366
366
|
if (!child.dom && (next = prev ? prev.nextSibling : parent.firstChild)) {
|
|
367
367
|
let contentView = ContentView.get(next);
|
|
368
368
|
if (!contentView || !contentView.parent && contentView.canReuseDOM(child))
|
|
369
369
|
child.reuseDOM(next);
|
|
370
370
|
}
|
|
371
371
|
child.sync(view, track);
|
|
372
|
-
child.flags &= ~7 /* Dirty */;
|
|
372
|
+
child.flags &= ~7 /* ViewFlag.Dirty */;
|
|
373
373
|
}
|
|
374
374
|
next = prev ? prev.nextSibling : parent.firstChild;
|
|
375
375
|
if (track && !track.written && track.node == parent && next != child.dom)
|
|
@@ -389,11 +389,11 @@ class ContentView {
|
|
|
389
389
|
while (next)
|
|
390
390
|
next = rm$1(next);
|
|
391
391
|
}
|
|
392
|
-
else if (this.flags & 1 /* ChildDirty */) {
|
|
392
|
+
else if (this.flags & 1 /* ViewFlag.ChildDirty */) {
|
|
393
393
|
for (let child of this.children)
|
|
394
|
-
if (child.flags & 7 /* Dirty */) {
|
|
394
|
+
if (child.flags & 7 /* ViewFlag.Dirty */) {
|
|
395
395
|
child.sync(view, track);
|
|
396
|
-
child.flags &= ~7 /* Dirty */;
|
|
396
|
+
child.flags &= ~7 /* ViewFlag.Dirty */;
|
|
397
397
|
}
|
|
398
398
|
}
|
|
399
399
|
}
|
|
@@ -458,23 +458,23 @@ class ContentView {
|
|
|
458
458
|
endDOM: toI < this.children.length && toI >= 0 ? this.children[toI].dom : null };
|
|
459
459
|
}
|
|
460
460
|
markDirty(andParent = false) {
|
|
461
|
-
this.flags |= 2 /* NodeDirty */;
|
|
461
|
+
this.flags |= 2 /* ViewFlag.NodeDirty */;
|
|
462
462
|
this.markParentsDirty(andParent);
|
|
463
463
|
}
|
|
464
464
|
markParentsDirty(childList) {
|
|
465
465
|
for (let parent = this.parent; parent; parent = parent.parent) {
|
|
466
466
|
if (childList)
|
|
467
|
-
parent.flags |= 2 /* NodeDirty */;
|
|
468
|
-
if (parent.flags & 1 /* ChildDirty */)
|
|
467
|
+
parent.flags |= 2 /* ViewFlag.NodeDirty */;
|
|
468
|
+
if (parent.flags & 1 /* ViewFlag.ChildDirty */)
|
|
469
469
|
return;
|
|
470
|
-
parent.flags |= 1 /* ChildDirty */;
|
|
470
|
+
parent.flags |= 1 /* ViewFlag.ChildDirty */;
|
|
471
471
|
childList = false;
|
|
472
472
|
}
|
|
473
473
|
}
|
|
474
474
|
setParent(parent) {
|
|
475
475
|
if (this.parent != parent) {
|
|
476
476
|
this.parent = parent;
|
|
477
|
-
if (this.flags & 7 /* Dirty */)
|
|
477
|
+
if (this.flags & 7 /* ViewFlag.Dirty */)
|
|
478
478
|
this.markParentsDirty(true);
|
|
479
479
|
}
|
|
480
480
|
}
|
|
@@ -526,7 +526,7 @@ class ContentView {
|
|
|
526
526
|
}
|
|
527
527
|
become(other) { return false; }
|
|
528
528
|
canReuseDOM(other) {
|
|
529
|
-
return other.constructor == this.constructor && !((this.flags | other.flags) & 8 /* Composition */);
|
|
529
|
+
return other.constructor == this.constructor && !((this.flags | other.flags) & 8 /* ViewFlag.Composition */);
|
|
530
530
|
}
|
|
531
531
|
// When this is a zero-length view with a side, this should return a
|
|
532
532
|
// number <= 0 to indicate it is before its position, or a
|
|
@@ -811,10 +811,10 @@ class TextView extends ContentView {
|
|
|
811
811
|
this.createDOM(dom);
|
|
812
812
|
}
|
|
813
813
|
merge(from, to, source) {
|
|
814
|
-
if ((this.flags & 8 /* Composition */) ||
|
|
814
|
+
if ((this.flags & 8 /* ViewFlag.Composition */) ||
|
|
815
815
|
source && (!(source instanceof TextView) ||
|
|
816
816
|
this.length - (to - from) + source.length > MaxJoinLen ||
|
|
817
|
-
(source.flags & 8 /* Composition */)))
|
|
817
|
+
(source.flags & 8 /* ViewFlag.Composition */)))
|
|
818
818
|
return false;
|
|
819
819
|
this.text = this.text.slice(0, from) + (source ? source.text : "") + this.text.slice(to);
|
|
820
820
|
this.markDirty();
|
|
@@ -824,7 +824,7 @@ class TextView extends ContentView {
|
|
|
824
824
|
let result = new TextView(this.text.slice(from));
|
|
825
825
|
this.text = this.text.slice(0, from);
|
|
826
826
|
this.markDirty();
|
|
827
|
-
result.flags |= this.flags & 8 /* Composition */;
|
|
827
|
+
result.flags |= this.flags & 8 /* ViewFlag.Composition */;
|
|
828
828
|
return result;
|
|
829
829
|
}
|
|
830
830
|
localPosFromDOM(node, offset) {
|
|
@@ -857,18 +857,18 @@ class MarkView extends ContentView {
|
|
|
857
857
|
return dom;
|
|
858
858
|
}
|
|
859
859
|
canReuseDOM(other) {
|
|
860
|
-
return super.canReuseDOM(other) && !((this.flags | other.flags) & 8 /* Composition */);
|
|
860
|
+
return super.canReuseDOM(other) && !((this.flags | other.flags) & 8 /* ViewFlag.Composition */);
|
|
861
861
|
}
|
|
862
862
|
reuseDOM(node) {
|
|
863
863
|
if (node.nodeName == this.mark.tagName.toUpperCase()) {
|
|
864
864
|
this.setDOM(node);
|
|
865
|
-
this.flags |= 4 /* AttrsDirty */ | 2 /* NodeDirty */;
|
|
865
|
+
this.flags |= 4 /* ViewFlag.AttrsDirty */ | 2 /* ViewFlag.NodeDirty */;
|
|
866
866
|
}
|
|
867
867
|
}
|
|
868
868
|
sync(view, track) {
|
|
869
869
|
if (!this.dom)
|
|
870
870
|
this.setDOM(this.setAttrs(document.createElement(this.mark.tagName)));
|
|
871
|
-
else if (this.flags & 4 /* AttrsDirty */)
|
|
871
|
+
else if (this.flags & 4 /* ViewFlag.AttrsDirty */)
|
|
872
872
|
this.setAttrs(this.dom);
|
|
873
873
|
super.sync(view, track);
|
|
874
874
|
}
|
|
@@ -939,6 +939,9 @@ function textCoords(text, pos, side) {
|
|
|
939
939
|
}
|
|
940
940
|
// Also used for collapsed ranges that don't have a placeholder widget!
|
|
941
941
|
class WidgetView extends ContentView {
|
|
942
|
+
static create(widget, length, side) {
|
|
943
|
+
return new WidgetView(widget, length, side);
|
|
944
|
+
}
|
|
942
945
|
constructor(widget, length, side) {
|
|
943
946
|
super();
|
|
944
947
|
this.widget = widget;
|
|
@@ -946,9 +949,6 @@ class WidgetView extends ContentView {
|
|
|
946
949
|
this.side = side;
|
|
947
950
|
this.prevWidget = null;
|
|
948
951
|
}
|
|
949
|
-
static create(widget, length, side) {
|
|
950
|
-
return new WidgetView(widget, length, side);
|
|
951
|
-
}
|
|
952
952
|
split(from) {
|
|
953
953
|
let result = WidgetView.create(this.widget, this.length - from, this.side);
|
|
954
954
|
this.length -= from;
|
|
@@ -1163,16 +1163,26 @@ function attrsEq(a, b, ignore) {
|
|
|
1163
1163
|
return true;
|
|
1164
1164
|
}
|
|
1165
1165
|
function updateAttrs(dom, prev, attrs) {
|
|
1166
|
-
let changed =
|
|
1166
|
+
let changed = false;
|
|
1167
1167
|
if (prev)
|
|
1168
1168
|
for (let name in prev)
|
|
1169
|
-
if (!(attrs && name in attrs))
|
|
1170
|
-
|
|
1169
|
+
if (!(attrs && name in attrs)) {
|
|
1170
|
+
changed = true;
|
|
1171
|
+
if (name == "style")
|
|
1172
|
+
dom.style.cssText = "";
|
|
1173
|
+
else
|
|
1174
|
+
dom.removeAttribute(name);
|
|
1175
|
+
}
|
|
1171
1176
|
if (attrs)
|
|
1172
1177
|
for (let name in attrs)
|
|
1173
|
-
if (!(prev && prev[name] == attrs[name]))
|
|
1174
|
-
|
|
1175
|
-
|
|
1178
|
+
if (!(prev && prev[name] == attrs[name])) {
|
|
1179
|
+
changed = true;
|
|
1180
|
+
if (name == "style")
|
|
1181
|
+
dom.style.cssText = attrs[name];
|
|
1182
|
+
else
|
|
1183
|
+
dom.setAttribute(name, attrs[name]);
|
|
1184
|
+
}
|
|
1185
|
+
return changed;
|
|
1176
1186
|
}
|
|
1177
1187
|
function getAttrs(dom) {
|
|
1178
1188
|
let attrs = Object.create(null);
|
|
@@ -1329,8 +1339,8 @@ class Decoration extends RangeValue {
|
|
|
1329
1339
|
static widget(spec) {
|
|
1330
1340
|
let side = Math.max(-10000, Math.min(10000, spec.side || 0)), block = !!spec.block;
|
|
1331
1341
|
side += (block && !spec.inlineOrder)
|
|
1332
|
-
? (side > 0 ? 300000000 /* BlockAfter */ : -400000000 /* BlockBefore */)
|
|
1333
|
-
: (side > 0 ? 100000000 /* InlineAfter */ : -100000000 /* InlineBefore */);
|
|
1342
|
+
? (side > 0 ? 300000000 /* Side.BlockAfter */ : -400000000 /* Side.BlockBefore */)
|
|
1343
|
+
: (side > 0 ? 100000000 /* Side.InlineAfter */ : -100000000 /* Side.InlineBefore */);
|
|
1334
1344
|
return new PointDecoration(spec, side, side, block, spec.widget || null, false);
|
|
1335
1345
|
}
|
|
1336
1346
|
/**
|
|
@@ -1340,13 +1350,13 @@ class Decoration extends RangeValue {
|
|
|
1340
1350
|
static replace(spec) {
|
|
1341
1351
|
let block = !!spec.block, startSide, endSide;
|
|
1342
1352
|
if (spec.isBlockGap) {
|
|
1343
|
-
startSide = -500000000 /* GapStart */;
|
|
1344
|
-
endSide = 400000000 /* GapEnd */;
|
|
1353
|
+
startSide = -500000000 /* Side.GapStart */;
|
|
1354
|
+
endSide = 400000000 /* Side.GapEnd */;
|
|
1345
1355
|
}
|
|
1346
1356
|
else {
|
|
1347
1357
|
let { start, end } = getInclusive(spec, block);
|
|
1348
|
-
startSide = (start ? (block ? -300000000 /* BlockIncStart */ : -1 /* InlineIncStart */) : 500000000 /* NonIncStart */) - 1;
|
|
1349
|
-
endSide = (end ? (block ? 200000000 /* BlockIncEnd */ : 1 /* InlineIncEnd */) : -600000000 /* NonIncEnd */) + 1;
|
|
1358
|
+
startSide = (start ? (block ? -300000000 /* Side.BlockIncStart */ : -1 /* Side.InlineIncStart */) : 500000000 /* Side.NonIncStart */) - 1;
|
|
1359
|
+
endSide = (end ? (block ? 200000000 /* Side.BlockIncEnd */ : 1 /* Side.InlineIncEnd */) : -600000000 /* Side.NonIncEnd */) + 1;
|
|
1350
1360
|
}
|
|
1351
1361
|
return new PointDecoration(spec, startSide, endSide, block, spec.widget || null, true);
|
|
1352
1362
|
}
|
|
@@ -1377,7 +1387,7 @@ Decoration.none = RangeSet.empty;
|
|
|
1377
1387
|
class MarkDecoration extends Decoration {
|
|
1378
1388
|
constructor(spec) {
|
|
1379
1389
|
let { start, end } = getInclusive(spec);
|
|
1380
|
-
super(start ? -1 /* InlineIncStart */ : 500000000 /* NonIncStart */, end ? 1 /* InlineIncEnd */ : -600000000 /* NonIncEnd */, null, spec);
|
|
1390
|
+
super(start ? -1 /* Side.InlineIncStart */ : 500000000 /* Side.NonIncStart */, end ? 1 /* Side.InlineIncEnd */ : -600000000 /* Side.NonIncEnd */, null, spec);
|
|
1381
1391
|
this.tagName = spec.tagName || "span";
|
|
1382
1392
|
this.class = spec.class || "";
|
|
1383
1393
|
this.attrs = spec.attributes || null;
|
|
@@ -1399,7 +1409,7 @@ class MarkDecoration extends Decoration {
|
|
|
1399
1409
|
MarkDecoration.prototype.point = false;
|
|
1400
1410
|
class LineDecoration extends Decoration {
|
|
1401
1411
|
constructor(spec) {
|
|
1402
|
-
super(-200000000 /* Line */, -200000000 /* Line */, null, spec);
|
|
1412
|
+
super(-200000000 /* Side.Line */, -200000000 /* Side.Line */, null, spec);
|
|
1403
1413
|
}
|
|
1404
1414
|
eq(other) {
|
|
1405
1415
|
return other instanceof LineDecoration &&
|
|
@@ -1540,7 +1550,7 @@ class LineView extends ContentView {
|
|
|
1540
1550
|
reuseDOM(node) {
|
|
1541
1551
|
if (node.nodeName == "DIV") {
|
|
1542
1552
|
this.setDOM(node);
|
|
1543
|
-
this.flags |= 4 /* AttrsDirty */ | 2 /* NodeDirty */;
|
|
1553
|
+
this.flags |= 4 /* ViewFlag.AttrsDirty */ | 2 /* ViewFlag.NodeDirty */;
|
|
1544
1554
|
}
|
|
1545
1555
|
}
|
|
1546
1556
|
sync(view, track) {
|
|
@@ -1550,7 +1560,7 @@ class LineView extends ContentView {
|
|
|
1550
1560
|
this.dom.className = "cm-line";
|
|
1551
1561
|
this.prevAttrs = this.attrs ? null : undefined;
|
|
1552
1562
|
}
|
|
1553
|
-
else if (this.flags & 4 /* AttrsDirty */) {
|
|
1563
|
+
else if (this.flags & 4 /* ViewFlag.AttrsDirty */) {
|
|
1554
1564
|
clearAttributes(this.dom);
|
|
1555
1565
|
this.dom.className = "cm-line";
|
|
1556
1566
|
this.prevAttrs = this.attrs ? null : undefined;
|
|
@@ -1698,7 +1708,7 @@ class ContentBuilder {
|
|
|
1698
1708
|
this.content = [];
|
|
1699
1709
|
this.curLine = null;
|
|
1700
1710
|
this.breakAtStart = 0;
|
|
1701
|
-
this.pendingBuffer = 0 /* No */;
|
|
1711
|
+
this.pendingBuffer = 0 /* Buf.No */;
|
|
1702
1712
|
this.bufferMarks = [];
|
|
1703
1713
|
// Set to false directly after a widget that covers the position after it
|
|
1704
1714
|
this.atCursorPos = true;
|
|
@@ -1725,7 +1735,7 @@ class ContentBuilder {
|
|
|
1725
1735
|
flushBuffer(active = this.bufferMarks) {
|
|
1726
1736
|
if (this.pendingBuffer) {
|
|
1727
1737
|
this.curLine.append(wrapMarks(new WidgetBufferView(-1), active), active.length);
|
|
1728
|
-
this.pendingBuffer = 0 /* No */;
|
|
1738
|
+
this.pendingBuffer = 0 /* Buf.No */;
|
|
1729
1739
|
}
|
|
1730
1740
|
}
|
|
1731
1741
|
addBlockWidget(view) {
|
|
@@ -1737,7 +1747,7 @@ class ContentBuilder {
|
|
|
1737
1747
|
if (this.pendingBuffer && openEnd <= this.bufferMarks.length)
|
|
1738
1748
|
this.flushBuffer();
|
|
1739
1749
|
else
|
|
1740
|
-
this.pendingBuffer = 0 /* No */;
|
|
1750
|
+
this.pendingBuffer = 0 /* Buf.No */;
|
|
1741
1751
|
if (!this.posCovered())
|
|
1742
1752
|
this.getLine();
|
|
1743
1753
|
}
|
|
@@ -1766,7 +1776,7 @@ class ContentBuilder {
|
|
|
1766
1776
|
this.textOff = 0;
|
|
1767
1777
|
}
|
|
1768
1778
|
}
|
|
1769
|
-
let take = Math.min(this.text.length - this.textOff, length, 512 /* Chunk */);
|
|
1779
|
+
let take = Math.min(this.text.length - this.textOff, length, 512 /* T.Chunk */);
|
|
1770
1780
|
this.flushBuffer(active.slice(active.length - openStart));
|
|
1771
1781
|
this.getLine().append(wrapMarks(new TextView(this.text.slice(this.textOff, this.textOff + take)), active), openStart);
|
|
1772
1782
|
this.atCursorPos = true;
|
|
@@ -1802,8 +1812,8 @@ class ContentBuilder {
|
|
|
1802
1812
|
(from < to || deco.startSide > 0);
|
|
1803
1813
|
let cursorAfter = !view.isEditable && (from < to || openStart > active.length || deco.startSide <= 0);
|
|
1804
1814
|
let line = this.getLine();
|
|
1805
|
-
if (this.pendingBuffer == 2 /* IfCursor */ && !cursorBefore && !view.isEditable)
|
|
1806
|
-
this.pendingBuffer = 0 /* No */;
|
|
1815
|
+
if (this.pendingBuffer == 2 /* Buf.IfCursor */ && !cursorBefore && !view.isEditable)
|
|
1816
|
+
this.pendingBuffer = 0 /* Buf.No */;
|
|
1807
1817
|
this.flushBuffer(active);
|
|
1808
1818
|
if (cursorBefore) {
|
|
1809
1819
|
line.append(wrapMarks(new WidgetBufferView(1), active), openStart);
|
|
@@ -1811,7 +1821,7 @@ class ContentBuilder {
|
|
|
1811
1821
|
}
|
|
1812
1822
|
line.append(wrapMarks(view, active), openStart);
|
|
1813
1823
|
this.atCursorPos = cursorAfter;
|
|
1814
|
-
this.pendingBuffer = !cursorAfter ? 0 /* No */ : from < to || openStart > active.length ? 1 /* Yes */ : 2 /* IfCursor */;
|
|
1824
|
+
this.pendingBuffer = !cursorAfter ? 0 /* Buf.No */ : from < to || openStart > active.length ? 1 /* Buf.Yes */ : 2 /* Buf.IfCursor */;
|
|
1815
1825
|
if (this.pendingBuffer)
|
|
1816
1826
|
this.bufferMarks = active.slice();
|
|
1817
1827
|
}
|
|
@@ -2025,6 +2035,36 @@ const contentAttributes = /*@__PURE__*/Facet.define();
|
|
|
2025
2035
|
// Provide decorations
|
|
2026
2036
|
const decorations = /*@__PURE__*/Facet.define();
|
|
2027
2037
|
const atomicRanges = /*@__PURE__*/Facet.define();
|
|
2038
|
+
const bidiIsolatedRanges = /*@__PURE__*/Facet.define();
|
|
2039
|
+
function getIsolatedRanges(view, from, to) {
|
|
2040
|
+
let isolates = view.state.facet(bidiIsolatedRanges);
|
|
2041
|
+
if (!isolates.length)
|
|
2042
|
+
return isolates;
|
|
2043
|
+
let sets = isolates.map(i => i instanceof Function ? i(view) : i);
|
|
2044
|
+
let result = [];
|
|
2045
|
+
RangeSet.spans(sets, from, to, {
|
|
2046
|
+
point() { },
|
|
2047
|
+
span(from, to, active, open) {
|
|
2048
|
+
let level = result;
|
|
2049
|
+
for (let i = active.length - 1; i >= 0; i--, open--) {
|
|
2050
|
+
let iso = active[i].spec.bidiIsolate, update;
|
|
2051
|
+
if (iso == null)
|
|
2052
|
+
continue;
|
|
2053
|
+
if (open > 0 && level.length &&
|
|
2054
|
+
(update = level[level.length - 1]).to == from && update.direction == iso) {
|
|
2055
|
+
update.to = to;
|
|
2056
|
+
level = update.inner;
|
|
2057
|
+
}
|
|
2058
|
+
else {
|
|
2059
|
+
let add = { from, to, direction: iso, inner: [] };
|
|
2060
|
+
level.push(add);
|
|
2061
|
+
level = add.inner;
|
|
2062
|
+
}
|
|
2063
|
+
}
|
|
2064
|
+
}
|
|
2065
|
+
});
|
|
2066
|
+
return result;
|
|
2067
|
+
}
|
|
2028
2068
|
const scrollMargins = /*@__PURE__*/Facet.define();
|
|
2029
2069
|
function getScrollMargins(view) {
|
|
2030
2070
|
let left = 0, right = 0, top = 0, bottom = 0;
|
|
@@ -2138,27 +2178,27 @@ class ViewUpdate {
|
|
|
2138
2178
|
update.
|
|
2139
2179
|
*/
|
|
2140
2180
|
get viewportChanged() {
|
|
2141
|
-
return (this.flags & 4 /* Viewport */) > 0;
|
|
2181
|
+
return (this.flags & 4 /* UpdateFlag.Viewport */) > 0;
|
|
2142
2182
|
}
|
|
2143
2183
|
/**
|
|
2144
2184
|
Indicates whether the height of a block element in the editor
|
|
2145
2185
|
changed in this update.
|
|
2146
2186
|
*/
|
|
2147
2187
|
get heightChanged() {
|
|
2148
|
-
return (this.flags & 2 /* Height */) > 0;
|
|
2188
|
+
return (this.flags & 2 /* UpdateFlag.Height */) > 0;
|
|
2149
2189
|
}
|
|
2150
2190
|
/**
|
|
2151
2191
|
Returns true when the document was modified or the size of the
|
|
2152
2192
|
editor, or elements within the editor, changed.
|
|
2153
2193
|
*/
|
|
2154
2194
|
get geometryChanged() {
|
|
2155
|
-
return this.docChanged || (this.flags & (8 /* Geometry */ | 2 /* Height */)) > 0;
|
|
2195
|
+
return this.docChanged || (this.flags & (8 /* UpdateFlag.Geometry */ | 2 /* UpdateFlag.Height */)) > 0;
|
|
2156
2196
|
}
|
|
2157
2197
|
/**
|
|
2158
2198
|
True when this update indicates a focus change.
|
|
2159
2199
|
*/
|
|
2160
2200
|
get focusChanged() {
|
|
2161
|
-
return (this.flags & 1 /* Focus */) > 0;
|
|
2201
|
+
return (this.flags & 1 /* UpdateFlag.Focus */) > 0;
|
|
2162
2202
|
}
|
|
2163
2203
|
/**
|
|
2164
2204
|
Whether the document changed in this update.
|
|
@@ -2216,12 +2256,12 @@ for (let p of ["()", "[]", "{}"]) {
|
|
|
2216
2256
|
}
|
|
2217
2257
|
function charType(ch) {
|
|
2218
2258
|
return ch <= 0xf7 ? LowTypes[ch] :
|
|
2219
|
-
0x590 <= ch && ch <= 0x5f4 ? 2 /* R */ :
|
|
2259
|
+
0x590 <= ch && ch <= 0x5f4 ? 2 /* T.R */ :
|
|
2220
2260
|
0x600 <= ch && ch <= 0x6f9 ? ArabicTypes[ch - 0x600] :
|
|
2221
|
-
0x6ee <= ch && ch <= 0x8ac ? 4 /* AL */ :
|
|
2222
|
-
0x2000 <= ch && ch <= 0x200b ? 256 /* NI */ :
|
|
2223
|
-
0xfb50 <= ch && ch <= 0xfdff ? 4 /* AL */ :
|
|
2224
|
-
ch == 0x200c ? 256 /* NI */ : 1 /* L */;
|
|
2261
|
+
0x6ee <= ch && ch <= 0x8ac ? 4 /* T.AL */ :
|
|
2262
|
+
0x2000 <= ch && ch <= 0x200b ? 256 /* T.NI */ :
|
|
2263
|
+
0xfb50 <= ch && ch <= 0xfdff ? 4 /* T.AL */ :
|
|
2264
|
+
ch == 0x200c ? 256 /* T.NI */ : 1 /* T.L */;
|
|
2225
2265
|
}
|
|
2226
2266
|
const BidiRE = /[\u0590-\u05f4\u0600-\u06ff\u0700-\u08ac\ufb50-\ufdff]/;
|
|
2227
2267
|
/**
|
|
@@ -2229,6 +2269,10 @@ Represents a contiguous range of text that has a single direction
|
|
|
2229
2269
|
(as in left-to-right or right-to-left).
|
|
2230
2270
|
*/
|
|
2231
2271
|
class BidiSpan {
|
|
2272
|
+
/**
|
|
2273
|
+
The direction of this span.
|
|
2274
|
+
*/
|
|
2275
|
+
get dir() { return this.level % 2 ? RTL : LTR; }
|
|
2232
2276
|
/**
|
|
2233
2277
|
@internal
|
|
2234
2278
|
*/
|
|
@@ -2254,10 +2298,6 @@ class BidiSpan {
|
|
|
2254
2298
|
this.level = level;
|
|
2255
2299
|
}
|
|
2256
2300
|
/**
|
|
2257
|
-
The direction of this span.
|
|
2258
|
-
*/
|
|
2259
|
-
get dir() { return this.level % 2 ? RTL : LTR; }
|
|
2260
|
-
/**
|
|
2261
2301
|
@internal
|
|
2262
2302
|
*/
|
|
2263
2303
|
side(end, dir) { return (this.dir == dir) == end ? this.to : this.from; }
|
|
@@ -2283,166 +2323,328 @@ class BidiSpan {
|
|
|
2283
2323
|
return maybe;
|
|
2284
2324
|
}
|
|
2285
2325
|
}
|
|
2326
|
+
function isolatesEq(a, b) {
|
|
2327
|
+
if (a.length != b.length)
|
|
2328
|
+
return false;
|
|
2329
|
+
for (let i = 0; i < a.length; i++) {
|
|
2330
|
+
let iA = a[i], iB = b[i];
|
|
2331
|
+
if (iA.from != iB.from || iA.to != iB.to || iA.direction != iB.direction || !isolatesEq(iA.inner, iB.inner))
|
|
2332
|
+
return false;
|
|
2333
|
+
}
|
|
2334
|
+
return true;
|
|
2335
|
+
}
|
|
2286
2336
|
// Reused array of character types
|
|
2287
2337
|
const types = [];
|
|
2288
|
-
|
|
2289
|
-
|
|
2290
|
-
|
|
2291
|
-
|
|
2292
|
-
|
|
2293
|
-
|
|
2294
|
-
|
|
2295
|
-
|
|
2296
|
-
|
|
2297
|
-
|
|
2298
|
-
|
|
2299
|
-
|
|
2300
|
-
|
|
2301
|
-
|
|
2302
|
-
|
|
2303
|
-
|
|
2304
|
-
|
|
2305
|
-
type =
|
|
2306
|
-
|
|
2307
|
-
|
|
2308
|
-
|
|
2309
|
-
|
|
2310
|
-
|
|
2311
|
-
|
|
2312
|
-
|
|
2313
|
-
|
|
2314
|
-
|
|
2315
|
-
|
|
2316
|
-
|
|
2317
|
-
|
|
2318
|
-
|
|
2319
|
-
|
|
2320
|
-
|
|
2321
|
-
|
|
2322
|
-
|
|
2323
|
-
|
|
2324
|
-
|
|
2325
|
-
|
|
2326
|
-
|
|
2327
|
-
|
|
2328
|
-
|
|
2329
|
-
|
|
2330
|
-
|
|
2331
|
-
|
|
2332
|
-
end
|
|
2333
|
-
|
|
2334
|
-
|
|
2335
|
-
types[
|
|
2336
|
-
|
|
2337
|
-
|
|
2338
|
-
|
|
2339
|
-
|
|
2340
|
-
|
|
2341
|
-
|
|
2342
|
-
|
|
2343
|
-
|
|
2344
|
-
|
|
2345
|
-
|
|
2346
|
-
|
|
2347
|
-
|
|
2348
|
-
|
|
2349
|
-
|
|
2350
|
-
|
|
2351
|
-
|
|
2352
|
-
|
|
2353
|
-
|
|
2338
|
+
// Fill in the character types (in `types`) from `from` to `to` and
|
|
2339
|
+
// apply W normalization rules.
|
|
2340
|
+
function computeCharTypes(line, rFrom, rTo, isolates, outerType) {
|
|
2341
|
+
for (let iI = 0; iI <= isolates.length; iI++) {
|
|
2342
|
+
let from = iI ? isolates[iI - 1].to : rFrom, to = iI < isolates.length ? isolates[iI].from : rTo;
|
|
2343
|
+
let prevType = iI ? 256 /* T.NI */ : outerType;
|
|
2344
|
+
// W1. Examine each non-spacing mark (NSM) in the level run, and
|
|
2345
|
+
// change the type of the NSM to the type of the previous
|
|
2346
|
+
// character. If the NSM is at the start of the level run, it will
|
|
2347
|
+
// get the type of sor.
|
|
2348
|
+
// W2. Search backwards from each instance of a European number
|
|
2349
|
+
// until the first strong type (R, L, AL, or sor) is found. If an
|
|
2350
|
+
// AL is found, change the type of the European number to Arabic
|
|
2351
|
+
// number.
|
|
2352
|
+
// W3. Change all ALs to R.
|
|
2353
|
+
// (Left after this: L, R, EN, AN, ET, CS, NI)
|
|
2354
|
+
for (let i = from, prev = prevType, prevStrong = prevType; i < to; i++) {
|
|
2355
|
+
let type = charType(line.charCodeAt(i));
|
|
2356
|
+
if (type == 512 /* T.NSM */)
|
|
2357
|
+
type = prev;
|
|
2358
|
+
else if (type == 8 /* T.EN */ && prevStrong == 4 /* T.AL */)
|
|
2359
|
+
type = 16 /* T.AN */;
|
|
2360
|
+
types[i] = type == 4 /* T.AL */ ? 2 /* T.R */ : type;
|
|
2361
|
+
if (type & 7 /* T.Strong */)
|
|
2362
|
+
prevStrong = type;
|
|
2363
|
+
prev = type;
|
|
2364
|
+
}
|
|
2365
|
+
// W5. A sequence of European terminators adjacent to European
|
|
2366
|
+
// numbers changes to all European numbers.
|
|
2367
|
+
// W6. Otherwise, separators and terminators change to Other
|
|
2368
|
+
// Neutral.
|
|
2369
|
+
// W7. Search backwards from each instance of a European number
|
|
2370
|
+
// until the first strong type (R, L, or sor) is found. If an L is
|
|
2371
|
+
// found, then change the type of the European number to L.
|
|
2372
|
+
// (Left after this: L, R, EN+AN, NI)
|
|
2373
|
+
for (let i = from, prev = prevType, prevStrong = prevType; i < to; i++) {
|
|
2374
|
+
let type = types[i];
|
|
2375
|
+
if (type == 128 /* T.CS */) {
|
|
2376
|
+
if (i < to - 1 && prev == types[i + 1] && (prev & 24 /* T.Num */))
|
|
2377
|
+
type = types[i] = prev;
|
|
2378
|
+
else
|
|
2379
|
+
types[i] = 256 /* T.NI */;
|
|
2380
|
+
}
|
|
2381
|
+
else if (type == 64 /* T.ET */) {
|
|
2382
|
+
let end = i + 1;
|
|
2383
|
+
while (end < to && types[end] == 64 /* T.ET */)
|
|
2384
|
+
end++;
|
|
2385
|
+
let replace = (i && prev == 8 /* T.EN */) || (end < rTo && types[end] == 8 /* T.EN */) ? (prevStrong == 1 /* T.L */ ? 1 /* T.L */ : 8 /* T.EN */) : 256 /* T.NI */;
|
|
2386
|
+
for (let j = i; j < end; j++)
|
|
2387
|
+
types[j] = replace;
|
|
2388
|
+
i = end - 1;
|
|
2389
|
+
}
|
|
2390
|
+
else if (type == 8 /* T.EN */ && prevStrong == 1 /* T.L */) {
|
|
2391
|
+
types[i] = 1 /* T.L */;
|
|
2392
|
+
}
|
|
2393
|
+
prev = type;
|
|
2394
|
+
if (type & 7 /* T.Strong */)
|
|
2395
|
+
prevStrong = type;
|
|
2396
|
+
}
|
|
2397
|
+
}
|
|
2398
|
+
}
|
|
2399
|
+
// Process brackets throughout a run sequence.
|
|
2400
|
+
function processBracketPairs(line, rFrom, rTo, isolates, outerType) {
|
|
2401
|
+
let oppositeType = outerType == 1 /* T.L */ ? 2 /* T.R */ : 1 /* T.L */;
|
|
2402
|
+
for (let iI = 0, sI = 0, context = 0; iI <= isolates.length; iI++) {
|
|
2403
|
+
let from = iI ? isolates[iI - 1].to : rFrom, to = iI < isolates.length ? isolates[iI].from : rTo;
|
|
2404
|
+
// N0. Process bracket pairs in an isolating run sequence
|
|
2405
|
+
// sequentially in the logical order of the text positions of the
|
|
2406
|
+
// opening paired brackets using the logic given below. Within this
|
|
2407
|
+
// scope, bidirectional types EN and AN are treated as R.
|
|
2408
|
+
for (let i = from, ch, br, type; i < to; i++) {
|
|
2409
|
+
// Keeps [startIndex, type, strongSeen] triples for each open
|
|
2410
|
+
// bracket on BracketStack.
|
|
2411
|
+
if (br = Brackets[ch = line.charCodeAt(i)]) {
|
|
2412
|
+
if (br < 0) { // Closing bracket
|
|
2413
|
+
for (let sJ = sI - 3; sJ >= 0; sJ -= 3) {
|
|
2414
|
+
if (BracketStack[sJ + 1] == -br) {
|
|
2415
|
+
let flags = BracketStack[sJ + 2];
|
|
2416
|
+
let type = (flags & 2 /* Bracketed.EmbedInside */) ? outerType :
|
|
2417
|
+
!(flags & 4 /* Bracketed.OppositeInside */) ? 0 :
|
|
2418
|
+
(flags & 1 /* Bracketed.OppositeBefore */) ? oppositeType : outerType;
|
|
2419
|
+
if (type)
|
|
2420
|
+
types[i] = types[BracketStack[sJ]] = type;
|
|
2421
|
+
sI = sJ;
|
|
2422
|
+
break;
|
|
2423
|
+
}
|
|
2424
|
+
}
|
|
2425
|
+
}
|
|
2426
|
+
else if (BracketStack.length == 189 /* Bracketed.MaxDepth */) {
|
|
2427
|
+
break;
|
|
2428
|
+
}
|
|
2429
|
+
else {
|
|
2430
|
+
BracketStack[sI++] = i;
|
|
2431
|
+
BracketStack[sI++] = ch;
|
|
2432
|
+
BracketStack[sI++] = context;
|
|
2433
|
+
}
|
|
2434
|
+
}
|
|
2435
|
+
else if ((type = types[i]) == 2 /* T.R */ || type == 1 /* T.L */) {
|
|
2436
|
+
let embed = type == outerType;
|
|
2437
|
+
context = embed ? 0 : 1 /* Bracketed.OppositeBefore */;
|
|
2354
2438
|
for (let sJ = sI - 3; sJ >= 0; sJ -= 3) {
|
|
2355
|
-
|
|
2356
|
-
|
|
2357
|
-
let type = (flags & 2 /* EmbedInside */) ? outerType :
|
|
2358
|
-
!(flags & 4 /* OppositeInside */) ? 0 :
|
|
2359
|
-
(flags & 1 /* OppositeBefore */) ? oppositeType : outerType;
|
|
2360
|
-
if (type)
|
|
2361
|
-
types[i] = types[BracketStack[sJ]] = type;
|
|
2362
|
-
sI = sJ;
|
|
2439
|
+
let cur = BracketStack[sJ + 2];
|
|
2440
|
+
if (cur & 2 /* Bracketed.EmbedInside */)
|
|
2363
2441
|
break;
|
|
2442
|
+
if (embed) {
|
|
2443
|
+
BracketStack[sJ + 2] |= 2 /* Bracketed.EmbedInside */;
|
|
2444
|
+
}
|
|
2445
|
+
else {
|
|
2446
|
+
if (cur & 4 /* Bracketed.OppositeInside */)
|
|
2447
|
+
break;
|
|
2448
|
+
BracketStack[sJ + 2] |= 4 /* Bracketed.OppositeInside */;
|
|
2364
2449
|
}
|
|
2365
2450
|
}
|
|
2366
2451
|
}
|
|
2367
|
-
|
|
2368
|
-
|
|
2452
|
+
}
|
|
2453
|
+
}
|
|
2454
|
+
}
|
|
2455
|
+
function processNeutrals(rFrom, rTo, isolates, outerType) {
|
|
2456
|
+
for (let iI = 0, prev = outerType; iI <= isolates.length; iI++) {
|
|
2457
|
+
let from = iI ? isolates[iI - 1].to : rFrom, to = iI < isolates.length ? isolates[iI].from : rTo;
|
|
2458
|
+
// N1. A sequence of neutrals takes the direction of the
|
|
2459
|
+
// surrounding strong text if the text on both sides has the same
|
|
2460
|
+
// direction. European and Arabic numbers act as if they were R in
|
|
2461
|
+
// terms of their influence on neutrals. Start-of-level-run (sor)
|
|
2462
|
+
// and end-of-level-run (eor) are used at level run boundaries.
|
|
2463
|
+
// N2. Any remaining neutrals take the embedding direction.
|
|
2464
|
+
// (Left after this: L, R, EN+AN)
|
|
2465
|
+
for (let i = from; i < to;) {
|
|
2466
|
+
let type = types[i];
|
|
2467
|
+
if (type == 256 /* T.NI */) {
|
|
2468
|
+
let end = i + 1;
|
|
2469
|
+
for (;;) {
|
|
2470
|
+
if (end == to) {
|
|
2471
|
+
if (iI == isolates.length)
|
|
2472
|
+
break;
|
|
2473
|
+
end = isolates[iI++].to;
|
|
2474
|
+
to = iI < isolates.length ? isolates[iI].from : rTo;
|
|
2475
|
+
}
|
|
2476
|
+
else if (types[end] == 256 /* T.NI */) {
|
|
2477
|
+
end++;
|
|
2478
|
+
}
|
|
2479
|
+
else {
|
|
2480
|
+
break;
|
|
2481
|
+
}
|
|
2482
|
+
}
|
|
2483
|
+
let beforeL = prev == 1 /* T.L */;
|
|
2484
|
+
let afterL = (end < rTo ? types[end] : outerType) == 1 /* T.L */;
|
|
2485
|
+
let replace = beforeL == afterL ? (beforeL ? 1 /* T.L */ : 2 /* T.R */) : outerType;
|
|
2486
|
+
for (let j = end, jI = iI, fromJ = jI ? isolates[jI - 1].to : rFrom; j > i;) {
|
|
2487
|
+
if (j == fromJ) {
|
|
2488
|
+
j = isolates[--jI].from;
|
|
2489
|
+
fromJ = jI ? isolates[jI - 1].to : rFrom;
|
|
2490
|
+
}
|
|
2491
|
+
types[--j] = replace;
|
|
2492
|
+
}
|
|
2493
|
+
i = end;
|
|
2369
2494
|
}
|
|
2370
2495
|
else {
|
|
2371
|
-
|
|
2372
|
-
|
|
2373
|
-
BracketStack[sI++] = context;
|
|
2496
|
+
prev = type;
|
|
2497
|
+
i++;
|
|
2374
2498
|
}
|
|
2375
2499
|
}
|
|
2376
|
-
|
|
2377
|
-
|
|
2378
|
-
|
|
2379
|
-
|
|
2380
|
-
|
|
2381
|
-
|
|
2500
|
+
}
|
|
2501
|
+
}
|
|
2502
|
+
// Find the contiguous ranges of character types in a given range, and
|
|
2503
|
+
// emit spans for them. Flip the order of the spans as appropriate
|
|
2504
|
+
// based on the level, and call through to compute the spans for
|
|
2505
|
+
// isolates at the proper point.
|
|
2506
|
+
function emitSpans(line, from, to, level, baseLevel, isolates, order) {
|
|
2507
|
+
let ourType = level % 2 ? 2 /* T.R */ : 1 /* T.L */;
|
|
2508
|
+
if ((level % 2) == (baseLevel % 2)) { // Same dir as base direction, don't flip
|
|
2509
|
+
for (let iCh = from, iI = 0; iCh < to;) {
|
|
2510
|
+
// Scan a section of characters in direction ourType, unless
|
|
2511
|
+
// there's another type of char right after iCh, in which case
|
|
2512
|
+
// we scan a section of other characters (which, if ourType ==
|
|
2513
|
+
// T.L, may contain both T.R and T.AN chars).
|
|
2514
|
+
let sameDir = true, isNum = false;
|
|
2515
|
+
if (iI == isolates.length || iCh < isolates[iI].from) {
|
|
2516
|
+
let next = types[iCh];
|
|
2517
|
+
if (next != ourType) {
|
|
2518
|
+
sameDir = false;
|
|
2519
|
+
isNum = next == 16 /* T.AN */;
|
|
2520
|
+
}
|
|
2521
|
+
}
|
|
2522
|
+
// Holds an array of isolates to pass to a recursive call if we
|
|
2523
|
+
// must recurse (to distinguish T.AN inside an RTL section in
|
|
2524
|
+
// LTR text), null if we can emit directly
|
|
2525
|
+
let recurse = !sameDir && ourType == 1 /* T.L */ ? [] : null;
|
|
2526
|
+
let localLevel = sameDir ? level : level + 1;
|
|
2527
|
+
let iScan = iCh;
|
|
2528
|
+
run: for (;;) {
|
|
2529
|
+
if (iI < isolates.length && iScan == isolates[iI].from) {
|
|
2530
|
+
if (isNum)
|
|
2531
|
+
break run;
|
|
2532
|
+
let iso = isolates[iI];
|
|
2533
|
+
// Scan ahead to verify that there is another char in this dir after the isolate(s)
|
|
2534
|
+
if (!sameDir)
|
|
2535
|
+
for (let upto = iso.to, jI = iI + 1;;) {
|
|
2536
|
+
if (upto == to)
|
|
2537
|
+
break run;
|
|
2538
|
+
if (jI < isolates.length && isolates[jI].from == upto)
|
|
2539
|
+
upto = isolates[jI++].to;
|
|
2540
|
+
else if (types[upto] == ourType)
|
|
2541
|
+
break run;
|
|
2542
|
+
else
|
|
2543
|
+
break;
|
|
2544
|
+
}
|
|
2545
|
+
iI++;
|
|
2546
|
+
if (recurse) {
|
|
2547
|
+
recurse.push(iso);
|
|
2548
|
+
}
|
|
2549
|
+
else {
|
|
2550
|
+
if (iso.from > iCh)
|
|
2551
|
+
order.push(new BidiSpan(iCh, iso.from, localLevel));
|
|
2552
|
+
let dirSwap = (iso.direction == LTR) != !(localLevel % 2);
|
|
2553
|
+
computeSectionOrder(line, dirSwap ? level + 1 : level, baseLevel, iso.inner, iso.from, iso.to, order);
|
|
2554
|
+
iCh = iso.to;
|
|
2555
|
+
}
|
|
2556
|
+
iScan = iso.to;
|
|
2557
|
+
}
|
|
2558
|
+
else if (iScan == to || (sameDir ? types[iScan] != ourType : types[iScan] == ourType)) {
|
|
2382
2559
|
break;
|
|
2383
|
-
if (embed) {
|
|
2384
|
-
BracketStack[sJ + 2] |= 2 /* EmbedInside */;
|
|
2385
2560
|
}
|
|
2386
2561
|
else {
|
|
2387
|
-
|
|
2388
|
-
break;
|
|
2389
|
-
BracketStack[sJ + 2] |= 4 /* OppositeInside */;
|
|
2562
|
+
iScan++;
|
|
2390
2563
|
}
|
|
2391
2564
|
}
|
|
2565
|
+
if (recurse)
|
|
2566
|
+
emitSpans(line, iCh, iScan, level + 1, baseLevel, recurse, order);
|
|
2567
|
+
else if (iCh < iScan)
|
|
2568
|
+
order.push(new BidiSpan(iCh, iScan, localLevel));
|
|
2569
|
+
iCh = iScan;
|
|
2392
2570
|
}
|
|
2393
2571
|
}
|
|
2394
|
-
|
|
2395
|
-
|
|
2396
|
-
|
|
2397
|
-
|
|
2398
|
-
|
|
2399
|
-
|
|
2400
|
-
|
|
2401
|
-
|
|
2402
|
-
|
|
2403
|
-
|
|
2404
|
-
while (end < len && types[end] == 256 /* NI */)
|
|
2405
|
-
end++;
|
|
2406
|
-
let beforeL = (i ? types[i - 1] : outerType) == 1 /* L */;
|
|
2407
|
-
let afterL = (end < len ? types[end] : outerType) == 1 /* L */;
|
|
2408
|
-
let replace = beforeL == afterL ? (beforeL ? 1 /* L */ : 2 /* R */) : outerType;
|
|
2409
|
-
for (let j = i; j < end; j++)
|
|
2410
|
-
types[j] = replace;
|
|
2411
|
-
i = end - 1;
|
|
2412
|
-
}
|
|
2413
|
-
}
|
|
2414
|
-
// Here we depart from the documented algorithm, in order to avoid
|
|
2415
|
-
// building up an actual levels array. Since there are only three
|
|
2416
|
-
// levels (0, 1, 2) in an implementation that doesn't take
|
|
2417
|
-
// explicit embedding into account, we can build up the order on
|
|
2418
|
-
// the fly, without following the level-based algorithm.
|
|
2419
|
-
let order = [];
|
|
2420
|
-
if (outerType == 1 /* L */) {
|
|
2421
|
-
for (let i = 0; i < len;) {
|
|
2422
|
-
let start = i, rtl = types[i++] != 1 /* L */;
|
|
2423
|
-
while (i < len && rtl == (types[i] != 1 /* L */))
|
|
2424
|
-
i++;
|
|
2425
|
-
if (rtl) {
|
|
2426
|
-
for (let j = i; j > start;) {
|
|
2427
|
-
let end = j, l = types[--j] != 2 /* R */;
|
|
2428
|
-
while (j > start && l == (types[j - 1] != 2 /* R */))
|
|
2429
|
-
j--;
|
|
2430
|
-
order.push(new BidiSpan(j, end, l ? 2 : 1));
|
|
2572
|
+
else {
|
|
2573
|
+
// Iterate in reverse to flip the span order. Same code again, but
|
|
2574
|
+
// going from the back of the section to the front
|
|
2575
|
+
for (let iCh = to, iI = isolates.length; iCh > from;) {
|
|
2576
|
+
let sameDir = true, isNum = false;
|
|
2577
|
+
if (!iI || iCh > isolates[iI - 1].to) {
|
|
2578
|
+
let next = types[iCh - 1];
|
|
2579
|
+
if (next != ourType) {
|
|
2580
|
+
sameDir = false;
|
|
2581
|
+
isNum = next == 16 /* T.AN */;
|
|
2431
2582
|
}
|
|
2432
2583
|
}
|
|
2433
|
-
|
|
2434
|
-
|
|
2584
|
+
let recurse = !sameDir && ourType == 1 /* T.L */ ? [] : null;
|
|
2585
|
+
let localLevel = sameDir ? level : level + 1;
|
|
2586
|
+
let iScan = iCh;
|
|
2587
|
+
run: for (;;) {
|
|
2588
|
+
if (iI && iScan == isolates[iI - 1].to) {
|
|
2589
|
+
if (isNum)
|
|
2590
|
+
break run;
|
|
2591
|
+
let iso = isolates[--iI];
|
|
2592
|
+
// Scan ahead to verify that there is another char in this dir after the isolate(s)
|
|
2593
|
+
if (!sameDir)
|
|
2594
|
+
for (let upto = iso.from, jI = iI;;) {
|
|
2595
|
+
if (upto == from)
|
|
2596
|
+
break run;
|
|
2597
|
+
if (jI && isolates[jI - 1].to == upto)
|
|
2598
|
+
upto = isolates[--jI].from;
|
|
2599
|
+
else if (types[upto - 1] == ourType)
|
|
2600
|
+
break run;
|
|
2601
|
+
else
|
|
2602
|
+
break;
|
|
2603
|
+
}
|
|
2604
|
+
if (recurse) {
|
|
2605
|
+
recurse.push(iso);
|
|
2606
|
+
}
|
|
2607
|
+
else {
|
|
2608
|
+
if (iso.to < iCh)
|
|
2609
|
+
order.push(new BidiSpan(iso.to, iCh, localLevel));
|
|
2610
|
+
let dirSwap = (iso.direction == LTR) != !(localLevel % 2);
|
|
2611
|
+
computeSectionOrder(line, dirSwap ? level + 1 : level, baseLevel, iso.inner, iso.from, iso.to, order);
|
|
2612
|
+
iCh = iso.from;
|
|
2613
|
+
}
|
|
2614
|
+
iScan = iso.from;
|
|
2615
|
+
}
|
|
2616
|
+
else if (iScan == from || (sameDir ? types[iScan - 1] != ourType : types[iScan - 1] == ourType)) {
|
|
2617
|
+
break;
|
|
2618
|
+
}
|
|
2619
|
+
else {
|
|
2620
|
+
iScan--;
|
|
2621
|
+
}
|
|
2435
2622
|
}
|
|
2623
|
+
if (recurse)
|
|
2624
|
+
emitSpans(line, iScan, iCh, level + 1, baseLevel, recurse, order);
|
|
2625
|
+
else if (iScan < iCh)
|
|
2626
|
+
order.push(new BidiSpan(iScan, iCh, localLevel));
|
|
2627
|
+
iCh = iScan;
|
|
2436
2628
|
}
|
|
2437
2629
|
}
|
|
2438
|
-
|
|
2439
|
-
|
|
2440
|
-
|
|
2441
|
-
|
|
2442
|
-
|
|
2443
|
-
|
|
2444
|
-
|
|
2445
|
-
|
|
2630
|
+
}
|
|
2631
|
+
function computeSectionOrder(line, level, baseLevel, isolates, from, to, order) {
|
|
2632
|
+
let outerType = (level % 2 ? 2 /* T.R */ : 1 /* T.L */);
|
|
2633
|
+
computeCharTypes(line, from, to, isolates, outerType);
|
|
2634
|
+
processBracketPairs(line, from, to, isolates, outerType);
|
|
2635
|
+
processNeutrals(from, to, isolates, outerType);
|
|
2636
|
+
emitSpans(line, from, to, level, baseLevel, isolates, order);
|
|
2637
|
+
}
|
|
2638
|
+
function computeOrder(line, direction, isolates) {
|
|
2639
|
+
if (!line)
|
|
2640
|
+
return [new BidiSpan(0, 0, direction == RTL ? 1 : 0)];
|
|
2641
|
+
if (direction == LTR && !isolates.length && !BidiRE.test(line))
|
|
2642
|
+
return trivialOrder(line.length);
|
|
2643
|
+
if (isolates.length)
|
|
2644
|
+
while (line.length > types.length)
|
|
2645
|
+
types[types.length] = 256 /* T.NI */; // Make sure types array has no gaps
|
|
2646
|
+
let order = [], level = direction == LTR ? 0 : 1;
|
|
2647
|
+
computeSectionOrder(line, level, level, isolates, 0, line.length, order);
|
|
2446
2648
|
return order;
|
|
2447
2649
|
}
|
|
2448
2650
|
function trivialOrder(length) {
|
|
@@ -2491,6 +2693,7 @@ function moveVisually(line, order, dir, start, forward) {
|
|
|
2491
2693
|
}
|
|
2492
2694
|
|
|
2493
2695
|
class DocView extends ContentView {
|
|
2696
|
+
get length() { return this.view.state.doc.length; }
|
|
2494
2697
|
constructor(view) {
|
|
2495
2698
|
super();
|
|
2496
2699
|
this.view = view;
|
|
@@ -2522,7 +2725,6 @@ class DocView extends ContentView {
|
|
|
2522
2725
|
this.updateDeco();
|
|
2523
2726
|
this.updateInner([new ChangedRange(0, 0, 0, view.state.doc.length)], 0, null);
|
|
2524
2727
|
}
|
|
2525
|
-
get length() { return this.view.state.doc.length; }
|
|
2526
2728
|
// Update the document view to a given state.
|
|
2527
2729
|
update(update) {
|
|
2528
2730
|
let changedRanges = update.changedRanges;
|
|
@@ -2554,7 +2756,7 @@ class DocView extends ContentView {
|
|
|
2554
2756
|
let prevDeco = this.decorations, deco = this.updateDeco();
|
|
2555
2757
|
let decoDiff = findChangedDeco(prevDeco, deco, update.changes);
|
|
2556
2758
|
changedRanges = ChangedRange.extendWithRanges(changedRanges, decoDiff);
|
|
2557
|
-
if (!(this.flags & 7 /* Dirty */) && changedRanges.length == 0) {
|
|
2759
|
+
if (!(this.flags & 7 /* ViewFlag.Dirty */) && changedRanges.length == 0) {
|
|
2558
2760
|
return false;
|
|
2559
2761
|
}
|
|
2560
2762
|
else {
|
|
@@ -2583,12 +2785,12 @@ class DocView extends ContentView {
|
|
|
2583
2785
|
// to detect that situation.
|
|
2584
2786
|
let track = browser.chrome || browser.ios ? { node: observer.selectionRange.focusNode, written: false } : undefined;
|
|
2585
2787
|
this.sync(this.view, track);
|
|
2586
|
-
this.flags &= ~7 /* Dirty */;
|
|
2788
|
+
this.flags &= ~7 /* ViewFlag.Dirty */;
|
|
2587
2789
|
if (track && (track.written || observer.selectionRange.focusNode != track.node))
|
|
2588
2790
|
this.forceSelection = true;
|
|
2589
2791
|
this.dom.style.height = "";
|
|
2590
2792
|
});
|
|
2591
|
-
this.markedForComposition.forEach(cView => cView.flags &= ~8 /* Composition */);
|
|
2793
|
+
this.markedForComposition.forEach(cView => cView.flags &= ~8 /* ViewFlag.Composition */);
|
|
2592
2794
|
let gaps = [];
|
|
2593
2795
|
if (this.view.viewport.from || this.view.viewport.to < this.view.state.doc.length)
|
|
2594
2796
|
for (let child of this.children)
|
|
@@ -2638,7 +2840,7 @@ class DocView extends ContentView {
|
|
|
2638
2840
|
}
|
|
2639
2841
|
compositionView(composition) {
|
|
2640
2842
|
let cur = new TextView(composition.text.nodeValue);
|
|
2641
|
-
cur.flags |= 8 /* Composition */;
|
|
2843
|
+
cur.flags |= 8 /* ViewFlag.Composition */;
|
|
2642
2844
|
for (let { deco } of composition.marks)
|
|
2643
2845
|
cur = new MarkView(deco, [cur], cur.length);
|
|
2644
2846
|
let line = new LineView;
|
|
@@ -2647,7 +2849,7 @@ class DocView extends ContentView {
|
|
|
2647
2849
|
}
|
|
2648
2850
|
fixCompositionDOM(composition) {
|
|
2649
2851
|
let fix = (dom, cView) => {
|
|
2650
|
-
cView.flags |= 8 /* Composition */;
|
|
2852
|
+
cView.flags |= 8 /* ViewFlag.Composition */;
|
|
2651
2853
|
this.markedForComposition.add(cView);
|
|
2652
2854
|
let prev = ContentView.get(dom);
|
|
2653
2855
|
if (prev != cView) {
|
|
@@ -2709,15 +2911,15 @@ class DocView extends ContentView {
|
|
|
2709
2911
|
// Work around https://bugzilla.mozilla.org/show_bug.cgi?id=1612076
|
|
2710
2912
|
if (browser.gecko) {
|
|
2711
2913
|
let nextTo = nextToUneditable(anchor.node, anchor.offset);
|
|
2712
|
-
if (nextTo && nextTo != (1 /* Before */ | 2 /* After */)) {
|
|
2713
|
-
let text = nearbyTextNode(anchor.node, anchor.offset, nextTo == 1 /* Before */ ? 1 : -1);
|
|
2914
|
+
if (nextTo && nextTo != (1 /* NextTo.Before */ | 2 /* NextTo.After */)) {
|
|
2915
|
+
let text = nearbyTextNode(anchor.node, anchor.offset, nextTo == 1 /* NextTo.Before */ ? 1 : -1);
|
|
2714
2916
|
if (text)
|
|
2715
|
-
anchor = new DOMPos(text, nextTo == 1 /* Before */ ? 0 : text.nodeValue.length);
|
|
2917
|
+
anchor = new DOMPos(text, nextTo == 1 /* NextTo.Before */ ? 0 : text.nodeValue.length);
|
|
2716
2918
|
}
|
|
2717
2919
|
}
|
|
2718
2920
|
rawSel.collapse(anchor.node, anchor.offset);
|
|
2719
|
-
if (main.bidiLevel != null && domSel.
|
|
2720
|
-
domSel.
|
|
2921
|
+
if (main.bidiLevel != null && domSel.caretBidiLevel != null)
|
|
2922
|
+
domSel.caretBidiLevel = main.bidiLevel;
|
|
2721
2923
|
}
|
|
2722
2924
|
else if (rawSel.extend) {
|
|
2723
2925
|
// Selection.extend can be used to create an 'inverted' selection
|
|
@@ -2978,7 +3180,7 @@ class BlockGapWidget extends WidgetType {
|
|
|
2978
3180
|
}
|
|
2979
3181
|
get estimatedHeight() { return this.height; }
|
|
2980
3182
|
}
|
|
2981
|
-
function findCompositionNode(view) {
|
|
3183
|
+
function findCompositionNode(view, dLen) {
|
|
2982
3184
|
let sel = view.observer.selectionRange;
|
|
2983
3185
|
let textNode = sel.focusNode && nearbyTextNode(sel.focusNode, sel.focusOffset, 0);
|
|
2984
3186
|
if (!textNode)
|
|
@@ -2990,10 +3192,12 @@ function findCompositionNode(view) {
|
|
|
2990
3192
|
to = from + cView.length;
|
|
2991
3193
|
}
|
|
2992
3194
|
else {
|
|
3195
|
+
let oldLen = Math.max(0, textNode.nodeValue.length - dLen);
|
|
2993
3196
|
up: for (let offset = 0, node = textNode;;) {
|
|
2994
3197
|
for (let sibling = node.previousSibling, cView; sibling; sibling = sibling.previousSibling) {
|
|
2995
3198
|
if (cView = ContentView.get(sibling)) {
|
|
2996
|
-
|
|
3199
|
+
to = cView.posAtEnd + offset;
|
|
3200
|
+
from = Math.max(0, to - oldLen);
|
|
2997
3201
|
break up;
|
|
2998
3202
|
}
|
|
2999
3203
|
let reader = new DOMReader([], view.state);
|
|
@@ -3007,15 +3211,16 @@ function findCompositionNode(view) {
|
|
|
3007
3211
|
return null;
|
|
3008
3212
|
let parentView = ContentView.get(node);
|
|
3009
3213
|
if (parentView) {
|
|
3010
|
-
from =
|
|
3214
|
+
from = parentView.posAtStart + offset;
|
|
3215
|
+
to = from + oldLen;
|
|
3011
3216
|
break;
|
|
3012
3217
|
}
|
|
3013
3218
|
}
|
|
3014
3219
|
}
|
|
3015
|
-
return { from, to, node: textNode };
|
|
3220
|
+
return { from, to: to, node: textNode };
|
|
3016
3221
|
}
|
|
3017
3222
|
function findCompositionRange(view, changes) {
|
|
3018
|
-
let found = findCompositionNode(view);
|
|
3223
|
+
let found = findCompositionNode(view, changes.newLength - changes.length);
|
|
3019
3224
|
if (!found)
|
|
3020
3225
|
return null;
|
|
3021
3226
|
let { from: fromA, to: toA, node: textNode } = found;
|
|
@@ -3089,16 +3294,16 @@ function nearbyTextNode(startNode, startOffset, side) {
|
|
|
3089
3294
|
function nextToUneditable(node, offset) {
|
|
3090
3295
|
if (node.nodeType != 1)
|
|
3091
3296
|
return 0;
|
|
3092
|
-
return (offset && node.childNodes[offset - 1].contentEditable == "false" ? 1 /* Before */ : 0) |
|
|
3093
|
-
(offset < node.childNodes.length && node.childNodes[offset].contentEditable == "false" ? 2 /* After */ : 0);
|
|
3297
|
+
return (offset && node.childNodes[offset - 1].contentEditable == "false" ? 1 /* NextTo.Before */ : 0) |
|
|
3298
|
+
(offset < node.childNodes.length && node.childNodes[offset].contentEditable == "false" ? 2 /* NextTo.After */ : 0);
|
|
3094
3299
|
}
|
|
3095
|
-
|
|
3300
|
+
let DecorationComparator$1 = class DecorationComparator {
|
|
3096
3301
|
constructor() {
|
|
3097
3302
|
this.changes = [];
|
|
3098
3303
|
}
|
|
3099
3304
|
compareRange(from, to) { addRange(from, to, this.changes); }
|
|
3100
3305
|
comparePoint(from, to) { addRange(from, to, this.changes); }
|
|
3101
|
-
}
|
|
3306
|
+
};
|
|
3102
3307
|
function findChangedDeco(a, b, diff) {
|
|
3103
3308
|
let comp = new DecorationComparator$1;
|
|
3104
3309
|
RangeSet.compare(a, b, diff, comp);
|
|
@@ -3480,6 +3685,10 @@ function skipAtoms(view, oldPos, pos) {
|
|
|
3480
3685
|
|
|
3481
3686
|
// This will also be where dragging info and such goes
|
|
3482
3687
|
class InputState {
|
|
3688
|
+
setSelectionOrigin(origin) {
|
|
3689
|
+
this.lastSelectionOrigin = origin;
|
|
3690
|
+
this.lastSelectionTime = Date.now();
|
|
3691
|
+
}
|
|
3483
3692
|
constructor(view) {
|
|
3484
3693
|
this.lastKeyCode = 0;
|
|
3485
3694
|
this.lastKeyTime = 0;
|
|
@@ -3575,10 +3784,8 @@ class InputState {
|
|
|
3575
3784
|
// issue where the composition vanishes when you press enter.
|
|
3576
3785
|
if (browser.safari)
|
|
3577
3786
|
view.contentDOM.addEventListener("input", () => null);
|
|
3578
|
-
|
|
3579
|
-
|
|
3580
|
-
this.lastSelectionOrigin = origin;
|
|
3581
|
-
this.lastSelectionTime = Date.now();
|
|
3787
|
+
if (browser.gecko)
|
|
3788
|
+
firefoxCopyCutHack(view.contentDOM.ownerDocument);
|
|
3582
3789
|
}
|
|
3583
3790
|
ensureHandlers(view, plugins) {
|
|
3584
3791
|
var _a;
|
|
@@ -4284,6 +4491,18 @@ handlers.beforeinput = (view, event) => {
|
|
|
4284
4491
|
}
|
|
4285
4492
|
}
|
|
4286
4493
|
};
|
|
4494
|
+
const appliedFirefoxHack = /*@__PURE__*/new Set;
|
|
4495
|
+
// In Firefox, when cut/copy handlers are added to the document, that
|
|
4496
|
+
// somehow avoids a bug where those events aren't fired when the
|
|
4497
|
+
// selection is empty. See https://github.com/codemirror/dev/issues/1082
|
|
4498
|
+
// and https://bugzilla.mozilla.org/show_bug.cgi?id=995961
|
|
4499
|
+
function firefoxCopyCutHack(doc) {
|
|
4500
|
+
if (!appliedFirefoxHack.has(doc)) {
|
|
4501
|
+
appliedFirefoxHack.add(doc);
|
|
4502
|
+
doc.addEventListener("copy", () => { });
|
|
4503
|
+
doc.addEventListener("cut", () => { });
|
|
4504
|
+
}
|
|
4505
|
+
}
|
|
4287
4506
|
|
|
4288
4507
|
const wrappingWhiteSpace = ["pre-wrap", "normal", "pre-line", "break-spaces"];
|
|
4289
4508
|
class HeightOracle {
|
|
@@ -4447,13 +4666,13 @@ const Epsilon = 1e-3;
|
|
|
4447
4666
|
class HeightMap {
|
|
4448
4667
|
constructor(length, // The number of characters covered
|
|
4449
4668
|
height, // Height of this part of the document
|
|
4450
|
-
flags = 2 /* Outdated */) {
|
|
4669
|
+
flags = 2 /* Flag.Outdated */) {
|
|
4451
4670
|
this.length = length;
|
|
4452
4671
|
this.height = height;
|
|
4453
4672
|
this.flags = flags;
|
|
4454
4673
|
}
|
|
4455
|
-
get outdated() { return (this.flags & 2 /* Outdated */) > 0; }
|
|
4456
|
-
set outdated(value) { this.flags = (value ? 2 /* Outdated */ : 0) | (this.flags & ~2 /* Outdated */); }
|
|
4674
|
+
get outdated() { return (this.flags & 2 /* Flag.Outdated */) > 0; }
|
|
4675
|
+
set outdated(value) { this.flags = (value ? 2 /* Flag.Outdated */ : 0) | (this.flags & ~2 /* Flag.Outdated */); }
|
|
4457
4676
|
setHeight(oracle, height) {
|
|
4458
4677
|
if (this.height != height) {
|
|
4459
4678
|
if (Math.abs(this.height - height) > Epsilon)
|
|
@@ -4584,7 +4803,7 @@ class HeightMapText extends HeightMapBlock {
|
|
|
4584
4803
|
}
|
|
4585
4804
|
replace(_from, _to, nodes) {
|
|
4586
4805
|
let node = nodes[0];
|
|
4587
|
-
if (nodes.length == 1 && (node instanceof HeightMapText || node instanceof HeightMapGap && (node.flags & 4 /* SingleLine */)) &&
|
|
4806
|
+
if (nodes.length == 1 && (node instanceof HeightMapText || node instanceof HeightMapGap && (node.flags & 4 /* Flag.SingleLine */)) &&
|
|
4588
4807
|
Math.abs(this.length - node.length) < 10) {
|
|
4589
4808
|
if (node instanceof HeightMapGap)
|
|
4590
4809
|
node = new HeightMapText(node.length, this.height);
|
|
@@ -4737,12 +4956,12 @@ class HeightMapGap extends HeightMap {
|
|
|
4737
4956
|
}
|
|
4738
4957
|
class HeightMapBranch extends HeightMap {
|
|
4739
4958
|
constructor(left, brk, right) {
|
|
4740
|
-
super(left.length + brk + right.length, left.height + right.height, brk | (left.outdated || right.outdated ? 2 /* Outdated */ : 0));
|
|
4959
|
+
super(left.length + brk + right.length, left.height + right.height, brk | (left.outdated || right.outdated ? 2 /* Flag.Outdated */ : 0));
|
|
4741
4960
|
this.left = left;
|
|
4742
4961
|
this.right = right;
|
|
4743
4962
|
this.size = left.size + right.size;
|
|
4744
4963
|
}
|
|
4745
|
-
get break() { return this.flags & 1 /* Break */; }
|
|
4964
|
+
get break() { return this.flags & 1 /* Flag.Break */; }
|
|
4746
4965
|
blockAt(height, oracle, top, offset) {
|
|
4747
4966
|
let mid = top + this.left.height;
|
|
4748
4967
|
return height < mid ? this.left.blockAt(height, oracle, top, offset)
|
|
@@ -4927,7 +5146,7 @@ class NodeBuilder {
|
|
|
4927
5146
|
blankContent(from, to) {
|
|
4928
5147
|
let gap = new HeightMapGap(to - from);
|
|
4929
5148
|
if (this.oracle.doc.lineAt(from).to == to)
|
|
4930
|
-
gap.flags |= 4 /* SingleLine */;
|
|
5149
|
+
gap.flags |= 4 /* Flag.SingleLine */;
|
|
4931
5150
|
return gap;
|
|
4932
5151
|
}
|
|
4933
5152
|
ensureLine() {
|
|
@@ -5137,7 +5356,7 @@ class ViewState {
|
|
|
5137
5356
|
}
|
|
5138
5357
|
}
|
|
5139
5358
|
this.viewports = viewports.sort((a, b) => a.from - b.from);
|
|
5140
|
-
this.scaler = this.heightMap.height <= 7000000 /* MaxDOMHeight */ ? IdScaler :
|
|
5359
|
+
this.scaler = this.heightMap.height <= 7000000 /* VP.MaxDOMHeight */ ? IdScaler :
|
|
5141
5360
|
new BigScaler(this.heightOracle, this.heightMap, this.viewports);
|
|
5142
5361
|
}
|
|
5143
5362
|
updateViewportLines() {
|
|
@@ -5156,7 +5375,7 @@ class ViewState {
|
|
|
5156
5375
|
let scrollAnchor = this.scrolledToBottom ? null : this.scrollAnchorAt(this.scrollTop);
|
|
5157
5376
|
this.heightMap = this.heightMap.applyChanges(this.stateDeco, update.startState.doc, this.heightOracle.setDoc(this.state.doc), heightChanges);
|
|
5158
5377
|
if (this.heightMap.height != prevHeight)
|
|
5159
|
-
update.flags |= 2 /* Height */;
|
|
5378
|
+
update.flags |= 2 /* UpdateFlag.Height */;
|
|
5160
5379
|
if (scrollAnchor) {
|
|
5161
5380
|
this.scrollAnchorPos = update.changes.mapPos(scrollAnchor.from, -1);
|
|
5162
5381
|
this.scrollAnchorHeight = scrollAnchor.top;
|
|
@@ -5169,13 +5388,13 @@ class ViewState {
|
|
|
5169
5388
|
if (scrollTarget && (scrollTarget.range.head < viewport.from || scrollTarget.range.head > viewport.to) ||
|
|
5170
5389
|
!this.viewportIsAppropriate(viewport))
|
|
5171
5390
|
viewport = this.getViewport(0, scrollTarget);
|
|
5172
|
-
let updateLines = !update.changes.empty || (update.flags & 2 /* Height */) ||
|
|
5391
|
+
let updateLines = !update.changes.empty || (update.flags & 2 /* UpdateFlag.Height */) ||
|
|
5173
5392
|
viewport.from != this.viewport.from || viewport.to != this.viewport.to;
|
|
5174
5393
|
this.viewport = viewport;
|
|
5175
5394
|
this.updateForViewport();
|
|
5176
5395
|
if (updateLines)
|
|
5177
5396
|
this.updateViewportLines();
|
|
5178
|
-
if (this.lineGaps.length || this.viewport.to - this.viewport.from > (2000 /* Margin */ << 1))
|
|
5397
|
+
if (this.lineGaps.length || this.viewport.to - this.viewport.from > (2000 /* LG.Margin */ << 1))
|
|
5179
5398
|
this.updateLineGaps(this.ensureLineGaps(this.mapLineGaps(this.lineGaps, update.changes)));
|
|
5180
5399
|
update.flags |= this.computeVisibleRanges();
|
|
5181
5400
|
if (scrollTarget)
|
|
@@ -5201,13 +5420,13 @@ class ViewState {
|
|
|
5201
5420
|
if (this.paddingTop != paddingTop || this.paddingBottom != paddingBottom) {
|
|
5202
5421
|
this.paddingTop = paddingTop;
|
|
5203
5422
|
this.paddingBottom = paddingBottom;
|
|
5204
|
-
result |= 8 /* Geometry */ | 2 /* Height */;
|
|
5423
|
+
result |= 8 /* UpdateFlag.Geometry */ | 2 /* UpdateFlag.Height */;
|
|
5205
5424
|
}
|
|
5206
5425
|
if (this.editorWidth != view.scrollDOM.clientWidth) {
|
|
5207
5426
|
if (oracle.lineWrapping)
|
|
5208
5427
|
measureContent = true;
|
|
5209
5428
|
this.editorWidth = view.scrollDOM.clientWidth;
|
|
5210
|
-
result |= 8 /* Geometry */;
|
|
5429
|
+
result |= 8 /* UpdateFlag.Geometry */;
|
|
5211
5430
|
}
|
|
5212
5431
|
if (this.scrollTop != view.scrollDOM.scrollTop) {
|
|
5213
5432
|
this.scrollAnchorHeight = -1;
|
|
@@ -5230,7 +5449,7 @@ class ViewState {
|
|
|
5230
5449
|
if (this.contentDOMWidth != contentWidth || this.editorHeight != view.scrollDOM.clientHeight) {
|
|
5231
5450
|
this.contentDOMWidth = domRect.width;
|
|
5232
5451
|
this.editorHeight = view.scrollDOM.clientHeight;
|
|
5233
|
-
result |= 8 /* Geometry */;
|
|
5452
|
+
result |= 8 /* UpdateFlag.Geometry */;
|
|
5234
5453
|
}
|
|
5235
5454
|
if (measureContent) {
|
|
5236
5455
|
let lineHeights = view.docView.measureVisibleLineHeights(this.viewport);
|
|
@@ -5241,7 +5460,7 @@ class ViewState {
|
|
|
5241
5460
|
refresh = lineHeight > 0 && oracle.refresh(whiteSpace, lineHeight, charWidth, textHeight, contentWidth / charWidth, lineHeights);
|
|
5242
5461
|
if (refresh) {
|
|
5243
5462
|
view.docView.minWidth = 0;
|
|
5244
|
-
result |= 8 /* Geometry */;
|
|
5463
|
+
result |= 8 /* UpdateFlag.Geometry */;
|
|
5245
5464
|
}
|
|
5246
5465
|
}
|
|
5247
5466
|
if (dTop > 0 && dBottom > 0)
|
|
@@ -5254,7 +5473,7 @@ class ViewState {
|
|
|
5254
5473
|
this.heightMap = (refresh ? HeightMap.empty().applyChanges(this.stateDeco, Text.empty, this.heightOracle, [new ChangedRange(0, 0, 0, view.state.doc.length)]) : this.heightMap).updateHeight(oracle, 0, refresh, new MeasuredHeights(vp.from, heights));
|
|
5255
5474
|
}
|
|
5256
5475
|
if (oracle.heightChanged)
|
|
5257
|
-
result |= 2 /* Height */;
|
|
5476
|
+
result |= 2 /* UpdateFlag.Height */;
|
|
5258
5477
|
}
|
|
5259
5478
|
let viewportChange = !this.viewportIsAppropriate(this.viewport, bias) ||
|
|
5260
5479
|
this.scrollTarget && (this.scrollTarget.range.head < this.viewport.from ||
|
|
@@ -5262,9 +5481,9 @@ class ViewState {
|
|
|
5262
5481
|
if (viewportChange)
|
|
5263
5482
|
this.viewport = this.getViewport(bias, this.scrollTarget);
|
|
5264
5483
|
this.updateForViewport();
|
|
5265
|
-
if ((result & 2 /* Height */) || viewportChange)
|
|
5484
|
+
if ((result & 2 /* UpdateFlag.Height */) || viewportChange)
|
|
5266
5485
|
this.updateViewportLines();
|
|
5267
|
-
if (this.lineGaps.length || this.viewport.to - this.viewport.from > (2000 /* Margin */ << 1))
|
|
5486
|
+
if (this.lineGaps.length || this.viewport.to - this.viewport.from > (2000 /* LG.Margin */ << 1))
|
|
5268
5487
|
this.updateLineGaps(this.ensureLineGaps(refresh ? [] : this.lineGaps, view));
|
|
5269
5488
|
result |= this.computeVisibleRanges();
|
|
5270
5489
|
if (this.mustEnforceCursorAssoc) {
|
|
@@ -5283,10 +5502,10 @@ class ViewState {
|
|
|
5283
5502
|
// This will divide VP.Margin between the top and the
|
|
5284
5503
|
// bottom, depending on the bias (the change in viewport position
|
|
5285
5504
|
// since the last update). It'll hold a number between 0 and 1
|
|
5286
|
-
let marginTop = 0.5 - Math.max(-0.5, Math.min(0.5, bias / 1000 /* Margin */ / 2));
|
|
5505
|
+
let marginTop = 0.5 - Math.max(-0.5, Math.min(0.5, bias / 1000 /* VP.Margin */ / 2));
|
|
5287
5506
|
let map = this.heightMap, oracle = this.heightOracle;
|
|
5288
5507
|
let { visibleTop, visibleBottom } = this;
|
|
5289
|
-
let viewport = new Viewport(map.lineAt(visibleTop - marginTop * 1000 /* Margin */, QueryType.ByHeight, oracle, 0, 0).from, map.lineAt(visibleBottom + (1 - marginTop) * 1000 /* Margin */, QueryType.ByHeight, oracle, 0, 0).to);
|
|
5508
|
+
let viewport = new Viewport(map.lineAt(visibleTop - marginTop * 1000 /* VP.Margin */, QueryType.ByHeight, oracle, 0, 0).from, map.lineAt(visibleBottom + (1 - marginTop) * 1000 /* VP.Margin */, QueryType.ByHeight, oracle, 0, 0).to);
|
|
5290
5509
|
// If scrollTarget is given, make sure the viewport includes that position
|
|
5291
5510
|
if (scrollTarget) {
|
|
5292
5511
|
let { head } = scrollTarget.range;
|
|
@@ -5299,7 +5518,7 @@ class ViewState {
|
|
|
5299
5518
|
topPos = block.top;
|
|
5300
5519
|
else
|
|
5301
5520
|
topPos = block.bottom - viewHeight;
|
|
5302
|
-
viewport = new Viewport(map.lineAt(topPos - 1000 /* Margin */ / 2, QueryType.ByHeight, oracle, 0, 0).from, map.lineAt(topPos + viewHeight + 1000 /* Margin */ / 2, QueryType.ByHeight, oracle, 0, 0).to);
|
|
5521
|
+
viewport = new Viewport(map.lineAt(topPos - 1000 /* VP.Margin */ / 2, QueryType.ByHeight, oracle, 0, 0).from, map.lineAt(topPos + viewHeight + 1000 /* VP.Margin */ / 2, QueryType.ByHeight, oracle, 0, 0).to);
|
|
5303
5522
|
}
|
|
5304
5523
|
}
|
|
5305
5524
|
return viewport;
|
|
@@ -5316,10 +5535,10 @@ class ViewState {
|
|
|
5316
5535
|
let { top } = this.heightMap.lineAt(from, QueryType.ByPos, this.heightOracle, 0, 0);
|
|
5317
5536
|
let { bottom } = this.heightMap.lineAt(to, QueryType.ByPos, this.heightOracle, 0, 0);
|
|
5318
5537
|
let { visibleTop, visibleBottom } = this;
|
|
5319
|
-
return (from == 0 || top <= visibleTop - Math.max(10 /* MinCoverMargin */, Math.min(-bias, 250 /* MaxCoverMargin */))) &&
|
|
5538
|
+
return (from == 0 || top <= visibleTop - Math.max(10 /* VP.MinCoverMargin */, Math.min(-bias, 250 /* VP.MaxCoverMargin */))) &&
|
|
5320
5539
|
(to == this.state.doc.length ||
|
|
5321
|
-
bottom >= visibleBottom + Math.max(10 /* MinCoverMargin */, Math.min(bias, 250 /* MaxCoverMargin */))) &&
|
|
5322
|
-
(top > visibleTop - 2 * 1000 /* Margin */ && bottom < visibleBottom + 2 * 1000 /* Margin */);
|
|
5540
|
+
bottom >= visibleBottom + Math.max(10 /* VP.MinCoverMargin */, Math.min(bias, 250 /* VP.MaxCoverMargin */))) &&
|
|
5541
|
+
(top > visibleTop - 2 * 1000 /* VP.Margin */ && bottom < visibleBottom + 2 * 1000 /* VP.Margin */);
|
|
5323
5542
|
}
|
|
5324
5543
|
mapLineGaps(gaps, changes) {
|
|
5325
5544
|
if (!gaps.length || changes.empty)
|
|
@@ -5339,7 +5558,7 @@ class ViewState {
|
|
|
5339
5558
|
// the artifacts this might produce from the user.
|
|
5340
5559
|
ensureLineGaps(current, mayMeasure) {
|
|
5341
5560
|
let wrapping = this.heightOracle.lineWrapping;
|
|
5342
|
-
let margin = wrapping ? 10000 /* MarginWrap */ : 2000 /* Margin */, halfMargin = margin >> 1, doubleMargin = margin << 1;
|
|
5561
|
+
let margin = wrapping ? 10000 /* LG.MarginWrap */ : 2000 /* LG.Margin */, halfMargin = margin >> 1, doubleMargin = margin << 1;
|
|
5343
5562
|
// The non-wrapping logic won't work at all in predominantly right-to-left text.
|
|
5344
5563
|
if (this.defaultTextDirection != Direction.LTR && !wrapping)
|
|
5345
5564
|
return [];
|
|
@@ -5352,8 +5571,8 @@ class ViewState {
|
|
|
5352
5571
|
avoid.push(sel.to);
|
|
5353
5572
|
for (let pos of avoid) {
|
|
5354
5573
|
if (pos > from && pos < to) {
|
|
5355
|
-
addGap(from, pos - 10 /* SelectionMargin */, line, structure);
|
|
5356
|
-
addGap(pos + 10 /* SelectionMargin */, to, line, structure);
|
|
5574
|
+
addGap(from, pos - 10 /* LG.SelectionMargin */, line, structure);
|
|
5575
|
+
addGap(pos + 10 /* LG.SelectionMargin */, to, line, structure);
|
|
5357
5576
|
return;
|
|
5358
5577
|
}
|
|
5359
5578
|
}
|
|
@@ -5447,7 +5666,7 @@ class ViewState {
|
|
|
5447
5666
|
let changed = ranges.length != this.visibleRanges.length ||
|
|
5448
5667
|
this.visibleRanges.some((r, i) => r.from != ranges[i].from || r.to != ranges[i].to);
|
|
5449
5668
|
this.visibleRanges = ranges;
|
|
5450
|
-
return changed ? 4 /* Viewport */ : 0;
|
|
5669
|
+
return changed ? 4 /* UpdateFlag.Viewport */ : 0;
|
|
5451
5670
|
}
|
|
5452
5671
|
lineBlockAt(pos) {
|
|
5453
5672
|
return (pos >= this.viewport.from && pos <= this.viewport.to && this.viewportLines.find(b => b.from <= pos && b.to >= pos)) ||
|
|
@@ -5543,7 +5762,7 @@ class BigScaler {
|
|
|
5543
5762
|
vpHeight += bottom - top;
|
|
5544
5763
|
return { from, to, top, bottom, domTop: 0, domBottom: 0 };
|
|
5545
5764
|
});
|
|
5546
|
-
this.scale = (7000000 /* MaxDOMHeight */ - vpHeight) / (heightMap.height - vpHeight);
|
|
5765
|
+
this.scale = (7000000 /* VP.MaxDOMHeight */ - vpHeight) / (heightMap.height - vpHeight);
|
|
5547
5766
|
for (let obj of this.viewports) {
|
|
5548
5767
|
obj.domTop = domBase + (obj.top - base) * this.scale;
|
|
5549
5768
|
domBase = obj.domBottom = obj.domTop + (obj.bottom - obj.top);
|
|
@@ -5926,7 +6145,6 @@ function applyDOMChange(view, domChange) {
|
|
|
5926
6145
|
change = { from: sel.from, to: sel.to, insert: Text.of([" "]) };
|
|
5927
6146
|
}
|
|
5928
6147
|
if (change) {
|
|
5929
|
-
let startState = view.state;
|
|
5930
6148
|
if (browser.ios && view.inputState.flushIOSKey(view))
|
|
5931
6149
|
return true;
|
|
5932
6150
|
// Android browsers don't fire reasonable key events for enter,
|
|
@@ -5940,70 +6158,18 @@ function applyDOMChange(view, domChange) {
|
|
|
5940
6158
|
change.insert.length == 1 && change.insert.lines == 2 &&
|
|
5941
6159
|
dispatchKey(view.contentDOM, "Enter", 13)) ||
|
|
5942
6160
|
((change.from == sel.from - 1 && change.to == sel.to && change.insert.length == 0 ||
|
|
5943
|
-
lastKey == 8 && change.insert.length < change.to - change.from) &&
|
|
6161
|
+
lastKey == 8 && change.insert.length < change.to - change.from && change.to > sel.head) &&
|
|
5944
6162
|
dispatchKey(view.contentDOM, "Backspace", 8)) ||
|
|
5945
6163
|
(change.from == sel.from && change.to == sel.to + 1 && change.insert.length == 0 &&
|
|
5946
6164
|
dispatchKey(view.contentDOM, "Delete", 46))))
|
|
5947
6165
|
return true;
|
|
5948
6166
|
let text = change.insert.toString();
|
|
5949
|
-
if (view.state.facet(inputHandler).some(h => h(view, change.from, change.to, text)))
|
|
5950
|
-
return true;
|
|
5951
6167
|
if (view.inputState.composing >= 0)
|
|
5952
6168
|
view.inputState.composing++;
|
|
5953
|
-
let
|
|
5954
|
-
|
|
5955
|
-
|
|
5956
|
-
view.
|
|
5957
|
-
let before = sel.from < change.from ? startState.sliceDoc(sel.from, change.from) : "";
|
|
5958
|
-
let after = sel.to > change.to ? startState.sliceDoc(change.to, sel.to) : "";
|
|
5959
|
-
tr = startState.replaceSelection(view.state.toText(before + change.insert.sliceString(0, undefined, view.state.lineBreak) + after));
|
|
5960
|
-
}
|
|
5961
|
-
else {
|
|
5962
|
-
let changes = startState.changes(change);
|
|
5963
|
-
let mainSel = newSel && newSel.main.to <= changes.newLength ? newSel.main : undefined;
|
|
5964
|
-
// Try to apply a composition change to all cursors
|
|
5965
|
-
if (startState.selection.ranges.length > 1 && view.inputState.composing >= 0 &&
|
|
5966
|
-
change.to <= sel.to && change.to >= sel.to - 10) {
|
|
5967
|
-
let replaced = view.state.sliceDoc(change.from, change.to);
|
|
5968
|
-
let composition = findCompositionNode(view) || view.state.doc.lineAt(sel.head);
|
|
5969
|
-
let offset = sel.to - change.to, size = sel.to - sel.from;
|
|
5970
|
-
tr = startState.changeByRange(range => {
|
|
5971
|
-
if (range.from == sel.from && range.to == sel.to)
|
|
5972
|
-
return { changes, range: mainSel || range.map(changes) };
|
|
5973
|
-
let to = range.to - offset, from = to - replaced.length;
|
|
5974
|
-
if (range.to - range.from != size || view.state.sliceDoc(from, to) != replaced ||
|
|
5975
|
-
// Unfortunately, there's no way to make multiple
|
|
5976
|
-
// changes in the same node work without aborting
|
|
5977
|
-
// composition, so cursors in the composition range are
|
|
5978
|
-
// ignored.
|
|
5979
|
-
composition && range.to >= composition.from && range.from <= composition.to)
|
|
5980
|
-
return { range };
|
|
5981
|
-
let rangeChanges = startState.changes({ from, to, insert: change.insert }), selOff = range.to - sel.to;
|
|
5982
|
-
return {
|
|
5983
|
-
changes: rangeChanges,
|
|
5984
|
-
range: !mainSel ? range.map(rangeChanges) :
|
|
5985
|
-
EditorSelection.range(Math.max(0, mainSel.anchor + selOff), Math.max(0, mainSel.head + selOff))
|
|
5986
|
-
};
|
|
5987
|
-
});
|
|
5988
|
-
}
|
|
5989
|
-
else {
|
|
5990
|
-
tr = {
|
|
5991
|
-
changes,
|
|
5992
|
-
selection: mainSel && startState.selection.replaceRange(mainSel)
|
|
5993
|
-
};
|
|
5994
|
-
}
|
|
5995
|
-
}
|
|
5996
|
-
let userEvent = "input.type";
|
|
5997
|
-
if (view.composing ||
|
|
5998
|
-
view.inputState.compositionPendingChange && view.inputState.compositionEndedAt > Date.now() - 50) {
|
|
5999
|
-
view.inputState.compositionPendingChange = false;
|
|
6000
|
-
userEvent += ".compose";
|
|
6001
|
-
if (view.inputState.compositionFirstChange) {
|
|
6002
|
-
userEvent += ".start";
|
|
6003
|
-
view.inputState.compositionFirstChange = false;
|
|
6004
|
-
}
|
|
6005
|
-
}
|
|
6006
|
-
view.dispatch(tr, { scrollIntoView: true, userEvent });
|
|
6169
|
+
let defaultTr;
|
|
6170
|
+
let defaultInsert = () => defaultTr || (defaultTr = applyDefaultInsert(view, change, newSel));
|
|
6171
|
+
if (!view.state.facet(inputHandler).some(h => h(view, change.from, change.to, text, defaultInsert)))
|
|
6172
|
+
view.dispatch(defaultInsert());
|
|
6007
6173
|
return true;
|
|
6008
6174
|
}
|
|
6009
6175
|
else if (newSel && !newSel.main.eq(sel)) {
|
|
@@ -6020,6 +6186,63 @@ function applyDOMChange(view, domChange) {
|
|
|
6020
6186
|
return false;
|
|
6021
6187
|
}
|
|
6022
6188
|
}
|
|
6189
|
+
function applyDefaultInsert(view, change, newSel) {
|
|
6190
|
+
let tr, startState = view.state, sel = startState.selection.main;
|
|
6191
|
+
if (change.from >= sel.from && change.to <= sel.to && change.to - change.from >= (sel.to - sel.from) / 3 &&
|
|
6192
|
+
(!newSel || newSel.main.empty && newSel.main.from == change.from + change.insert.length) &&
|
|
6193
|
+
view.inputState.composing < 0) {
|
|
6194
|
+
let before = sel.from < change.from ? startState.sliceDoc(sel.from, change.from) : "";
|
|
6195
|
+
let after = sel.to > change.to ? startState.sliceDoc(change.to, sel.to) : "";
|
|
6196
|
+
tr = startState.replaceSelection(view.state.toText(before + change.insert.sliceString(0, undefined, view.state.lineBreak) + after));
|
|
6197
|
+
}
|
|
6198
|
+
else {
|
|
6199
|
+
let changes = startState.changes(change);
|
|
6200
|
+
let mainSel = newSel && newSel.main.to <= changes.newLength ? newSel.main : undefined;
|
|
6201
|
+
// Try to apply a composition change to all cursors
|
|
6202
|
+
if (startState.selection.ranges.length > 1 && view.inputState.composing >= 0 &&
|
|
6203
|
+
change.to <= sel.to && change.to >= sel.to - 10) {
|
|
6204
|
+
let replaced = view.state.sliceDoc(change.from, change.to);
|
|
6205
|
+
let composition = findCompositionNode(view, change.insert.length - (change.to - change.from)) ||
|
|
6206
|
+
view.state.doc.lineAt(sel.head);
|
|
6207
|
+
let offset = sel.to - change.to, size = sel.to - sel.from;
|
|
6208
|
+
tr = startState.changeByRange(range => {
|
|
6209
|
+
if (range.from == sel.from && range.to == sel.to)
|
|
6210
|
+
return { changes, range: mainSel || range.map(changes) };
|
|
6211
|
+
let to = range.to - offset, from = to - replaced.length;
|
|
6212
|
+
if (range.to - range.from != size || view.state.sliceDoc(from, to) != replaced ||
|
|
6213
|
+
// Unfortunately, there's no way to make multiple
|
|
6214
|
+
// changes in the same node work without aborting
|
|
6215
|
+
// composition, so cursors in the composition range are
|
|
6216
|
+
// ignored.
|
|
6217
|
+
composition && range.to >= composition.from && range.from <= composition.to)
|
|
6218
|
+
return { range };
|
|
6219
|
+
let rangeChanges = startState.changes({ from, to, insert: change.insert }), selOff = range.to - sel.to;
|
|
6220
|
+
return {
|
|
6221
|
+
changes: rangeChanges,
|
|
6222
|
+
range: !mainSel ? range.map(rangeChanges) :
|
|
6223
|
+
EditorSelection.range(Math.max(0, mainSel.anchor + selOff), Math.max(0, mainSel.head + selOff))
|
|
6224
|
+
};
|
|
6225
|
+
});
|
|
6226
|
+
}
|
|
6227
|
+
else {
|
|
6228
|
+
tr = {
|
|
6229
|
+
changes,
|
|
6230
|
+
selection: mainSel && startState.selection.replaceRange(mainSel)
|
|
6231
|
+
};
|
|
6232
|
+
}
|
|
6233
|
+
}
|
|
6234
|
+
let userEvent = "input.type";
|
|
6235
|
+
if (view.composing ||
|
|
6236
|
+
view.inputState.compositionPendingChange && view.inputState.compositionEndedAt > Date.now() - 50) {
|
|
6237
|
+
view.inputState.compositionPendingChange = false;
|
|
6238
|
+
userEvent += ".compose";
|
|
6239
|
+
if (view.inputState.compositionFirstChange) {
|
|
6240
|
+
userEvent += ".start";
|
|
6241
|
+
view.inputState.compositionFirstChange = false;
|
|
6242
|
+
}
|
|
6243
|
+
}
|
|
6244
|
+
return startState.update(tr, { userEvent, scrollIntoView: true });
|
|
6245
|
+
}
|
|
6023
6246
|
function findDiff(a, b, preferredPos, preferredSide) {
|
|
6024
6247
|
let minLen = Math.min(a.length, b.length);
|
|
6025
6248
|
let from = 0;
|
|
@@ -6437,7 +6660,7 @@ class DOMObserver {
|
|
|
6437
6660
|
return null;
|
|
6438
6661
|
cView.markDirty(rec.type == "attributes");
|
|
6439
6662
|
if (rec.type == "attributes")
|
|
6440
|
-
cView.flags |= 4 /* AttrsDirty */;
|
|
6663
|
+
cView.flags |= 4 /* ViewFlag.AttrsDirty */;
|
|
6441
6664
|
if (rec.type == "childList") {
|
|
6442
6665
|
let childBefore = findChild(cView, rec.previousSibling || rec.target.previousSibling, -1);
|
|
6443
6666
|
let childAfter = findChild(cView, rec.nextSibling || rec.target.nextSibling, 1);
|
|
@@ -6545,6 +6768,53 @@ line number gutter. It handles events and dispatches state
|
|
|
6545
6768
|
transactions for editing actions.
|
|
6546
6769
|
*/
|
|
6547
6770
|
class EditorView {
|
|
6771
|
+
/**
|
|
6772
|
+
The current editor state.
|
|
6773
|
+
*/
|
|
6774
|
+
get state() { return this.viewState.state; }
|
|
6775
|
+
/**
|
|
6776
|
+
To be able to display large documents without consuming too much
|
|
6777
|
+
memory or overloading the browser, CodeMirror only draws the
|
|
6778
|
+
code that is visible (plus a margin around it) to the DOM. This
|
|
6779
|
+
property tells you the extent of the current drawn viewport, in
|
|
6780
|
+
document positions.
|
|
6781
|
+
*/
|
|
6782
|
+
get viewport() { return this.viewState.viewport; }
|
|
6783
|
+
/**
|
|
6784
|
+
When there are, for example, large collapsed ranges in the
|
|
6785
|
+
viewport, its size can be a lot bigger than the actual visible
|
|
6786
|
+
content. Thus, if you are doing something like styling the
|
|
6787
|
+
content in the viewport, it is preferable to only do so for
|
|
6788
|
+
these ranges, which are the subset of the viewport that is
|
|
6789
|
+
actually drawn.
|
|
6790
|
+
*/
|
|
6791
|
+
get visibleRanges() { return this.viewState.visibleRanges; }
|
|
6792
|
+
/**
|
|
6793
|
+
Returns false when the editor is entirely scrolled out of view
|
|
6794
|
+
or otherwise hidden.
|
|
6795
|
+
*/
|
|
6796
|
+
get inView() { return this.viewState.inView; }
|
|
6797
|
+
/**
|
|
6798
|
+
Indicates whether the user is currently composing text via
|
|
6799
|
+
[IME](https://en.wikipedia.org/wiki/Input_method), and at least
|
|
6800
|
+
one change has been made in the current composition.
|
|
6801
|
+
*/
|
|
6802
|
+
get composing() { return this.inputState.composing > 0; }
|
|
6803
|
+
/**
|
|
6804
|
+
Indicates whether the user is currently in composing state. Note
|
|
6805
|
+
that on some platforms, like Android, this will be the case a
|
|
6806
|
+
lot, since just putting the cursor on a word starts a
|
|
6807
|
+
composition there.
|
|
6808
|
+
*/
|
|
6809
|
+
get compositionStarted() { return this.inputState.composing >= 0; }
|
|
6810
|
+
/**
|
|
6811
|
+
The document or shadow root that the view lives in.
|
|
6812
|
+
*/
|
|
6813
|
+
get root() { return this._root; }
|
|
6814
|
+
/**
|
|
6815
|
+
@internal
|
|
6816
|
+
*/
|
|
6817
|
+
get win() { return this.dom.ownerDocument.defaultView || window; }
|
|
6548
6818
|
/**
|
|
6549
6819
|
Construct a new view. You'll want to either provide a `parent`
|
|
6550
6820
|
option, or put `view.dom` into your document after creating a
|
|
@@ -6560,7 +6830,7 @@ class EditorView {
|
|
|
6560
6830
|
/**
|
|
6561
6831
|
@internal
|
|
6562
6832
|
*/
|
|
6563
|
-
this.updateState = 2 /* Updating */;
|
|
6833
|
+
this.updateState = 2 /* UpdateState.Updating */;
|
|
6564
6834
|
/**
|
|
6565
6835
|
@internal
|
|
6566
6836
|
*/
|
|
@@ -6580,7 +6850,10 @@ class EditorView {
|
|
|
6580
6850
|
this.dom = document.createElement("div");
|
|
6581
6851
|
this.dom.appendChild(this.announceDOM);
|
|
6582
6852
|
this.dom.appendChild(this.scrollDOM);
|
|
6583
|
-
|
|
6853
|
+
let { dispatch } = config;
|
|
6854
|
+
this.dispatchTransactions = config.dispatchTransactions ||
|
|
6855
|
+
(dispatch && ((trs) => trs.forEach(tr => dispatch(tr, this)))) ||
|
|
6856
|
+
((trs) => this.update(trs));
|
|
6584
6857
|
this.dispatch = this.dispatch.bind(this);
|
|
6585
6858
|
this._root = (config.root || getRoot(config.parent) || document);
|
|
6586
6859
|
this.viewState = new ViewState(config.state || EditorState.create(config));
|
|
@@ -6593,62 +6866,16 @@ class EditorView {
|
|
|
6593
6866
|
this.docView = new DocView(this);
|
|
6594
6867
|
this.mountStyles();
|
|
6595
6868
|
this.updateAttrs();
|
|
6596
|
-
this.updateState = 0 /* Idle */;
|
|
6869
|
+
this.updateState = 0 /* UpdateState.Idle */;
|
|
6597
6870
|
this.requestMeasure();
|
|
6598
6871
|
if (config.parent)
|
|
6599
6872
|
config.parent.appendChild(this.dom);
|
|
6600
6873
|
}
|
|
6601
|
-
/**
|
|
6602
|
-
The current editor state.
|
|
6603
|
-
*/
|
|
6604
|
-
get state() { return this.viewState.state; }
|
|
6605
|
-
/**
|
|
6606
|
-
To be able to display large documents without consuming too much
|
|
6607
|
-
memory or overloading the browser, CodeMirror only draws the
|
|
6608
|
-
code that is visible (plus a margin around it) to the DOM. This
|
|
6609
|
-
property tells you the extent of the current drawn viewport, in
|
|
6610
|
-
document positions.
|
|
6611
|
-
*/
|
|
6612
|
-
get viewport() { return this.viewState.viewport; }
|
|
6613
|
-
/**
|
|
6614
|
-
When there are, for example, large collapsed ranges in the
|
|
6615
|
-
viewport, its size can be a lot bigger than the actual visible
|
|
6616
|
-
content. Thus, if you are doing something like styling the
|
|
6617
|
-
content in the viewport, it is preferable to only do so for
|
|
6618
|
-
these ranges, which are the subset of the viewport that is
|
|
6619
|
-
actually drawn.
|
|
6620
|
-
*/
|
|
6621
|
-
get visibleRanges() { return this.viewState.visibleRanges; }
|
|
6622
|
-
/**
|
|
6623
|
-
Returns false when the editor is entirely scrolled out of view
|
|
6624
|
-
or otherwise hidden.
|
|
6625
|
-
*/
|
|
6626
|
-
get inView() { return this.viewState.inView; }
|
|
6627
|
-
/**
|
|
6628
|
-
Indicates whether the user is currently composing text via
|
|
6629
|
-
[IME](https://en.wikipedia.org/wiki/Input_method), and at least
|
|
6630
|
-
one change has been made in the current composition.
|
|
6631
|
-
*/
|
|
6632
|
-
get composing() { return this.inputState.composing > 0; }
|
|
6633
|
-
/**
|
|
6634
|
-
Indicates whether the user is currently in composing state. Note
|
|
6635
|
-
that on some platforms, like Android, this will be the case a
|
|
6636
|
-
lot, since just putting the cursor on a word starts a
|
|
6637
|
-
composition there.
|
|
6638
|
-
*/
|
|
6639
|
-
get compositionStarted() { return this.inputState.composing >= 0; }
|
|
6640
|
-
/**
|
|
6641
|
-
The document or shadow root that the view lives in.
|
|
6642
|
-
*/
|
|
6643
|
-
get root() { return this._root; }
|
|
6644
|
-
/**
|
|
6645
|
-
@internal
|
|
6646
|
-
*/
|
|
6647
|
-
get win() { return this.dom.ownerDocument.defaultView || window; }
|
|
6648
6874
|
dispatch(...input) {
|
|
6649
|
-
let
|
|
6650
|
-
:
|
|
6651
|
-
|
|
6875
|
+
let trs = input.length == 1 && input[0] instanceof Transaction ? input
|
|
6876
|
+
: input.length == 1 && Array.isArray(input[0]) ? input[0]
|
|
6877
|
+
: [this.state.update(...input)];
|
|
6878
|
+
this.dispatchTransactions(trs, this);
|
|
6652
6879
|
}
|
|
6653
6880
|
/**
|
|
6654
6881
|
Update the view for the given array of transactions. This will
|
|
@@ -6659,7 +6886,7 @@ class EditorView {
|
|
|
6659
6886
|
as a primitive.
|
|
6660
6887
|
*/
|
|
6661
6888
|
update(transactions) {
|
|
6662
|
-
if (this.updateState != 0 /* Idle */)
|
|
6889
|
+
if (this.updateState != 0 /* UpdateState.Idle */)
|
|
6663
6890
|
throw new Error("Calls to EditorView.update are not allowed while an update is in progress");
|
|
6664
6891
|
let redrawn = false, attrsChanged = false, update;
|
|
6665
6892
|
let state = this.state;
|
|
@@ -6676,7 +6903,7 @@ class EditorView {
|
|
|
6676
6903
|
if (transactions.some(tr => tr.annotation(isFocusChange))) {
|
|
6677
6904
|
this.inputState.notifiedFocused = focus;
|
|
6678
6905
|
// If a focus-change transaction is being dispatched, set this update flag.
|
|
6679
|
-
focusFlag = 1 /* Focus */;
|
|
6906
|
+
focusFlag = 1 /* UpdateFlag.Focus */;
|
|
6680
6907
|
}
|
|
6681
6908
|
else if (focus != this.inputState.notifiedFocused) {
|
|
6682
6909
|
this.inputState.notifiedFocused = focus;
|
|
@@ -6684,7 +6911,7 @@ class EditorView {
|
|
|
6684
6911
|
// add a flag to this update
|
|
6685
6912
|
dispatchFocus = focusChangeTransaction(state, focus);
|
|
6686
6913
|
if (!dispatchFocus)
|
|
6687
|
-
focusFlag = 1 /* Focus */;
|
|
6914
|
+
focusFlag = 1 /* UpdateFlag.Focus */;
|
|
6688
6915
|
}
|
|
6689
6916
|
// If there was a pending DOM change, eagerly read it and try to
|
|
6690
6917
|
// apply it after the given transactions.
|
|
@@ -6707,7 +6934,7 @@ class EditorView {
|
|
|
6707
6934
|
update.flags |= focusFlag;
|
|
6708
6935
|
let scrollTarget = this.viewState.scrollTarget;
|
|
6709
6936
|
try {
|
|
6710
|
-
this.updateState = 2 /* Updating */;
|
|
6937
|
+
this.updateState = 2 /* UpdateState.Updating */;
|
|
6711
6938
|
for (let tr of transactions) {
|
|
6712
6939
|
if (scrollTarget)
|
|
6713
6940
|
scrollTarget = scrollTarget.map(tr.changes);
|
|
@@ -6733,7 +6960,7 @@ class EditorView {
|
|
|
6733
6960
|
this.docView.updateSelection(redrawn, transactions.some(tr => tr.isUserEvent("select.pointer")));
|
|
6734
6961
|
}
|
|
6735
6962
|
finally {
|
|
6736
|
-
this.updateState = 0 /* Idle */;
|
|
6963
|
+
this.updateState = 0 /* UpdateState.Idle */;
|
|
6737
6964
|
}
|
|
6738
6965
|
if (update.startState.facet(theme) != update.state.facet(theme))
|
|
6739
6966
|
this.viewState.mustMeasureContent = true;
|
|
@@ -6760,13 +6987,13 @@ class EditorView {
|
|
|
6760
6987
|
[`dispatch`](https://codemirror.net/6/docs/ref/#view.EditorView.dispatch) instead.)
|
|
6761
6988
|
*/
|
|
6762
6989
|
setState(newState) {
|
|
6763
|
-
if (this.updateState != 0 /* Idle */)
|
|
6990
|
+
if (this.updateState != 0 /* UpdateState.Idle */)
|
|
6764
6991
|
throw new Error("Calls to EditorView.setState are not allowed while an update is in progress");
|
|
6765
6992
|
if (this.destroyed) {
|
|
6766
6993
|
this.viewState.state = newState;
|
|
6767
6994
|
return;
|
|
6768
6995
|
}
|
|
6769
|
-
this.updateState = 2 /* Updating */;
|
|
6996
|
+
this.updateState = 2 /* UpdateState.Updating */;
|
|
6770
6997
|
let hadFocus = this.hasFocus;
|
|
6771
6998
|
try {
|
|
6772
6999
|
for (let plugin of this.plugins)
|
|
@@ -6783,7 +7010,7 @@ class EditorView {
|
|
|
6783
7010
|
this.bidiCache = [];
|
|
6784
7011
|
}
|
|
6785
7012
|
finally {
|
|
6786
|
-
this.updateState = 0 /* Idle */;
|
|
7013
|
+
this.updateState = 0 /* UpdateState.Idle */;
|
|
6787
7014
|
}
|
|
6788
7015
|
if (hadFocus)
|
|
6789
7016
|
this.focus();
|
|
@@ -6826,6 +7053,11 @@ class EditorView {
|
|
|
6826
7053
|
return;
|
|
6827
7054
|
if (this.measureScheduled > -1)
|
|
6828
7055
|
this.win.cancelAnimationFrame(this.measureScheduled);
|
|
7056
|
+
if (this.observer.delayedAndroidKey) {
|
|
7057
|
+
this.measureScheduled = -1;
|
|
7058
|
+
this.requestMeasure();
|
|
7059
|
+
return;
|
|
7060
|
+
}
|
|
6829
7061
|
this.measureScheduled = 0; // Prevent requestMeasure calls from scheduling another animation frame
|
|
6830
7062
|
if (flush)
|
|
6831
7063
|
this.observer.forceFlush();
|
|
@@ -6848,7 +7080,7 @@ class EditorView {
|
|
|
6848
7080
|
scrollAnchorHeight = block.top;
|
|
6849
7081
|
}
|
|
6850
7082
|
}
|
|
6851
|
-
this.updateState = 1 /* Measuring */;
|
|
7083
|
+
this.updateState = 1 /* UpdateState.Measuring */;
|
|
6852
7084
|
let changed = this.viewState.measure(this);
|
|
6853
7085
|
if (!changed && !this.measureRequests.length && this.viewState.scrollTarget == null)
|
|
6854
7086
|
break;
|
|
@@ -6860,7 +7092,7 @@ class EditorView {
|
|
|
6860
7092
|
}
|
|
6861
7093
|
let measuring = [];
|
|
6862
7094
|
// Only run measure requests in this cycle when the viewport didn't change
|
|
6863
|
-
if (!(changed & 4 /* Viewport */))
|
|
7095
|
+
if (!(changed & 4 /* UpdateFlag.Viewport */))
|
|
6864
7096
|
[this.measureRequests, measuring] = [measuring, this.measureRequests];
|
|
6865
7097
|
let measured = measuring.map(m => {
|
|
6866
7098
|
try {
|
|
@@ -6877,7 +7109,7 @@ class EditorView {
|
|
|
6877
7109
|
updated = update;
|
|
6878
7110
|
else
|
|
6879
7111
|
updated.flags |= changed;
|
|
6880
|
-
this.updateState = 2 /* Updating */;
|
|
7112
|
+
this.updateState = 2 /* UpdateState.Updating */;
|
|
6881
7113
|
if (!update.empty) {
|
|
6882
7114
|
this.updatePlugins(update);
|
|
6883
7115
|
this.inputState.update(update);
|
|
@@ -6920,7 +7152,7 @@ class EditorView {
|
|
|
6920
7152
|
}
|
|
6921
7153
|
}
|
|
6922
7154
|
finally {
|
|
6923
|
-
this.updateState = 0 /* Idle */;
|
|
7155
|
+
this.updateState = 0 /* UpdateState.Idle */;
|
|
6924
7156
|
this.measureScheduled = -1;
|
|
6925
7157
|
}
|
|
6926
7158
|
if (updated && !updated.empty)
|
|
@@ -6976,12 +7208,13 @@ class EditorView {
|
|
|
6976
7208
|
}
|
|
6977
7209
|
mountStyles() {
|
|
6978
7210
|
this.styleModules = this.state.facet(styleModule);
|
|
6979
|
-
|
|
7211
|
+
let nonce = this.state.facet(EditorView.cspNonce);
|
|
7212
|
+
StyleModule.mount(this.root, this.styleModules.concat(baseTheme$1).reverse(), nonce ? { nonce } : undefined);
|
|
6980
7213
|
}
|
|
6981
7214
|
readMeasured() {
|
|
6982
|
-
if (this.updateState == 2 /* Updating */)
|
|
7215
|
+
if (this.updateState == 2 /* UpdateState.Updating */)
|
|
6983
7216
|
throw new Error("Reading the editor layout isn't allowed during an update");
|
|
6984
|
-
if (this.updateState == 0 /* Idle */ && this.measureScheduled > -1)
|
|
7217
|
+
if (this.updateState == 0 /* UpdateState.Idle */ && this.measureScheduled > -1)
|
|
6985
7218
|
this.measure(false);
|
|
6986
7219
|
}
|
|
6987
7220
|
/**
|
|
@@ -7235,12 +7468,16 @@ class EditorView {
|
|
|
7235
7468
|
bidiSpans(line) {
|
|
7236
7469
|
if (line.length > MaxBidiLine)
|
|
7237
7470
|
return trivialOrder(line.length);
|
|
7238
|
-
let dir = this.textDirectionAt(line.from);
|
|
7239
|
-
for (let entry of this.bidiCache)
|
|
7240
|
-
if (entry.from == line.from && entry.dir == dir
|
|
7471
|
+
let dir = this.textDirectionAt(line.from), isolates;
|
|
7472
|
+
for (let entry of this.bidiCache) {
|
|
7473
|
+
if (entry.from == line.from && entry.dir == dir &&
|
|
7474
|
+
(entry.fresh || isolatesEq(entry.isolates, isolates = getIsolatedRanges(this, line.from, line.to))))
|
|
7241
7475
|
return entry.order;
|
|
7242
|
-
|
|
7243
|
-
|
|
7476
|
+
}
|
|
7477
|
+
if (!isolates)
|
|
7478
|
+
isolates = getIsolatedRanges(this, line.from, line.to);
|
|
7479
|
+
let order = computeOrder(line.text, dir, isolates);
|
|
7480
|
+
this.bidiCache.push(new CachedOrder(line.from, line.to, dir, isolates, true, order));
|
|
7244
7481
|
return order;
|
|
7245
7482
|
}
|
|
7246
7483
|
/**
|
|
@@ -7375,6 +7612,10 @@ DOM content are handled. Handlers are passed the document
|
|
|
7375
7612
|
positions between which the change was found, and the new
|
|
7376
7613
|
content. When one returns true, no further input handlers are
|
|
7377
7614
|
called and the default behavior is prevented.
|
|
7615
|
+
|
|
7616
|
+
The `insert` argument can be used to get the default transaction
|
|
7617
|
+
that would be applied for this input. This can be useful when
|
|
7618
|
+
dispatching the custom behavior as a separate transaction.
|
|
7378
7619
|
*/
|
|
7379
7620
|
EditorView.inputHandler = inputHandler;
|
|
7380
7621
|
/**
|
|
@@ -7462,6 +7703,16 @@ regions.
|
|
|
7462
7703
|
*/
|
|
7463
7704
|
EditorView.atomicRanges = atomicRanges;
|
|
7464
7705
|
/**
|
|
7706
|
+
When range decorations add a `unicode-bidi: isolate` style, they
|
|
7707
|
+
should also include a
|
|
7708
|
+
[`bidiIsolate`](https://codemirror.net/6/docs/ref/#view.MarkDecorationSpec.bidiIsolate) property
|
|
7709
|
+
in their decoration spec, and be exposed through this facet, so
|
|
7710
|
+
that the editor can compute the proper text order. (Other values
|
|
7711
|
+
for `unicode-bidi`, except of course `normal`, are not
|
|
7712
|
+
supported.)
|
|
7713
|
+
*/
|
|
7714
|
+
EditorView.bidiIsolatedRanges = bidiIsolatedRanges;
|
|
7715
|
+
/**
|
|
7465
7716
|
Facet that allows extensions to provide additional scroll
|
|
7466
7717
|
margins (space around the sides of the scrolling element that
|
|
7467
7718
|
should be considered invisible). This can be useful when the
|
|
@@ -7477,6 +7728,12 @@ true.
|
|
|
7477
7728
|
*/
|
|
7478
7729
|
EditorView.darkTheme = darkTheme;
|
|
7479
7730
|
/**
|
|
7731
|
+
Provides a Content Security Policy nonce to use when creating
|
|
7732
|
+
the style sheets for the editor. Holds the empty string when no
|
|
7733
|
+
nonce has been provided.
|
|
7734
|
+
*/
|
|
7735
|
+
EditorView.cspNonce = /*@__PURE__*/Facet.define({ combine: values => values.length ? values[0] : "" });
|
|
7736
|
+
/**
|
|
7480
7737
|
Facet that provides additional DOM attributes for the editor's
|
|
7481
7738
|
editable DOM element.
|
|
7482
7739
|
*/
|
|
@@ -7504,20 +7761,22 @@ EditorView.announce = /*@__PURE__*/StateEffect.define();
|
|
|
7504
7761
|
const MaxBidiLine = 4096;
|
|
7505
7762
|
const BadMeasure = {};
|
|
7506
7763
|
class CachedOrder {
|
|
7507
|
-
constructor(from, to, dir, order) {
|
|
7764
|
+
constructor(from, to, dir, isolates, fresh, order) {
|
|
7508
7765
|
this.from = from;
|
|
7509
7766
|
this.to = to;
|
|
7510
7767
|
this.dir = dir;
|
|
7768
|
+
this.isolates = isolates;
|
|
7769
|
+
this.fresh = fresh;
|
|
7511
7770
|
this.order = order;
|
|
7512
7771
|
}
|
|
7513
7772
|
static update(cache, changes) {
|
|
7514
|
-
if (changes.empty)
|
|
7773
|
+
if (changes.empty && !cache.some(c => c.fresh))
|
|
7515
7774
|
return cache;
|
|
7516
7775
|
let result = [], lastDir = cache.length ? cache[cache.length - 1].dir : Direction.LTR;
|
|
7517
7776
|
for (let i = Math.max(0, cache.length - 10); i < cache.length; i++) {
|
|
7518
7777
|
let entry = cache[i];
|
|
7519
7778
|
if (entry.dir == lastDir && !changes.touchesRange(entry.from, entry.to))
|
|
7520
|
-
result.push(new CachedOrder(changes.mapPos(entry.from, 1), changes.mapPos(entry.to, -1), entry.dir, entry.order));
|
|
7779
|
+
result.push(new CachedOrder(changes.mapPos(entry.from, 1), changes.mapPos(entry.to, -1), entry.dir, entry.isolates, false, entry.order));
|
|
7521
7780
|
}
|
|
7522
7781
|
return result;
|
|
7523
7782
|
}
|
|
@@ -7840,7 +8099,7 @@ function rectanglesForRange(view, className, range) {
|
|
|
7840
8099
|
return pieces(top).concat(between).concat(pieces(bottom));
|
|
7841
8100
|
}
|
|
7842
8101
|
function piece(left, top, right, bottom) {
|
|
7843
|
-
return new RectangleMarker(className, left - base.left, top - base.top - 0.01 /* Epsilon */, right - left, bottom - top + 0.01 /* Epsilon */);
|
|
8102
|
+
return new RectangleMarker(className, left - base.left, top - base.top - 0.01 /* C.Epsilon */, right - left, bottom - top + 0.01 /* C.Epsilon */);
|
|
7844
8103
|
}
|
|
7845
8104
|
function pieces({ top, bottom, horizontal }) {
|
|
7846
8105
|
let pieces = [];
|
|
@@ -8857,12 +9116,12 @@ const tooltipPlugin = /*@__PURE__*/ViewPlugin.fromClass(class {
|
|
|
8857
9116
|
continue;
|
|
8858
9117
|
}
|
|
8859
9118
|
let arrow = tooltip.arrow ? tView.dom.querySelector(".cm-tooltip-arrow") : null;
|
|
8860
|
-
let arrowHeight = arrow ? 7 /* Size */ : 0;
|
|
9119
|
+
let arrowHeight = arrow ? 7 /* Arrow.Size */ : 0;
|
|
8861
9120
|
let width = size.right - size.left, height = (_a = knownHeight.get(tView)) !== null && _a !== void 0 ? _a : size.bottom - size.top;
|
|
8862
9121
|
let offset = tView.offset || noOffset, ltr = this.view.textDirection == Direction.LTR;
|
|
8863
9122
|
let left = size.width > space.right - space.left ? (ltr ? space.left : space.right - size.width)
|
|
8864
|
-
: ltr ? Math.min(pos.left - (arrow ? 14 /* Offset */ : 0) + offset.x, space.right - width)
|
|
8865
|
-
: Math.max(space.left, pos.left - width + (arrow ? 14 /* Offset */ : 0) - offset.x);
|
|
9123
|
+
: ltr ? Math.min(pos.left - (arrow ? 14 /* Arrow.Offset */ : 0) + offset.x, space.right - width)
|
|
9124
|
+
: Math.max(space.left, pos.left - width + (arrow ? 14 /* Arrow.Offset */ : 0) - offset.x);
|
|
8866
9125
|
let above = !!tooltip.above;
|
|
8867
9126
|
if (!tooltip.strictSide && (above
|
|
8868
9127
|
? pos.top - (size.bottom - size.top) - offset.y < space.top
|
|
@@ -8896,7 +9155,7 @@ const tooltipPlugin = /*@__PURE__*/ViewPlugin.fromClass(class {
|
|
|
8896
9155
|
dom.style.left = left + "px";
|
|
8897
9156
|
}
|
|
8898
9157
|
if (arrow)
|
|
8899
|
-
arrow.style.left = `${pos.left + (ltr ? offset.x : -offset.x) - (left + 14 /* Offset */ - 7 /* Size */)}px`;
|
|
9158
|
+
arrow.style.left = `${pos.left + (ltr ? offset.x : -offset.x) - (left + 14 /* Arrow.Offset */ - 7 /* Arrow.Size */)}px`;
|
|
8900
9159
|
if (tView.overlap !== true)
|
|
8901
9160
|
others.push({ left, top, right, bottom: top + height });
|
|
8902
9161
|
dom.classList.toggle("cm-tooltip-above", above);
|
|
@@ -8939,8 +9198,8 @@ const baseTheme = /*@__PURE__*/EditorView.baseTheme({
|
|
|
8939
9198
|
color: "white"
|
|
8940
9199
|
},
|
|
8941
9200
|
".cm-tooltip-arrow": {
|
|
8942
|
-
height: `${7 /* Size */}px`,
|
|
8943
|
-
width: `${7 /* Size */ * 2}px`,
|
|
9201
|
+
height: `${7 /* Arrow.Size */}px`,
|
|
9202
|
+
width: `${7 /* Arrow.Size */ * 2}px`,
|
|
8944
9203
|
position: "absolute",
|
|
8945
9204
|
zIndex: -1,
|
|
8946
9205
|
overflow: "hidden",
|
|
@@ -8949,26 +9208,26 @@ const baseTheme = /*@__PURE__*/EditorView.baseTheme({
|
|
|
8949
9208
|
position: "absolute",
|
|
8950
9209
|
width: 0,
|
|
8951
9210
|
height: 0,
|
|
8952
|
-
borderLeft: `${7 /* Size */}px solid transparent`,
|
|
8953
|
-
borderRight: `${7 /* Size */}px solid transparent`,
|
|
9211
|
+
borderLeft: `${7 /* Arrow.Size */}px solid transparent`,
|
|
9212
|
+
borderRight: `${7 /* Arrow.Size */}px solid transparent`,
|
|
8954
9213
|
},
|
|
8955
9214
|
".cm-tooltip-above &": {
|
|
8956
|
-
bottom: `-${7 /* Size */}px`,
|
|
9215
|
+
bottom: `-${7 /* Arrow.Size */}px`,
|
|
8957
9216
|
"&:before": {
|
|
8958
|
-
borderTop: `${7 /* Size */}px solid #bbb`,
|
|
9217
|
+
borderTop: `${7 /* Arrow.Size */}px solid #bbb`,
|
|
8959
9218
|
},
|
|
8960
9219
|
"&:after": {
|
|
8961
|
-
borderTop: `${7 /* Size */}px solid #f5f5f5`,
|
|
9220
|
+
borderTop: `${7 /* Arrow.Size */}px solid #f5f5f5`,
|
|
8962
9221
|
bottom: "1px"
|
|
8963
9222
|
}
|
|
8964
9223
|
},
|
|
8965
9224
|
".cm-tooltip-below &": {
|
|
8966
|
-
top: `-${7 /* Size */}px`,
|
|
9225
|
+
top: `-${7 /* Arrow.Size */}px`,
|
|
8967
9226
|
"&:before": {
|
|
8968
|
-
borderBottom: `${7 /* Size */}px solid #bbb`,
|
|
9227
|
+
borderBottom: `${7 /* Arrow.Size */}px solid #bbb`,
|
|
8969
9228
|
},
|
|
8970
9229
|
"&:after": {
|
|
8971
|
-
borderBottom: `${7 /* Size */}px solid #f5f5f5`,
|
|
9230
|
+
borderBottom: `${7 /* Arrow.Size */}px solid #f5f5f5`,
|
|
8972
9231
|
top: "1px"
|
|
8973
9232
|
}
|
|
8974
9233
|
},
|
|
@@ -8993,6 +9252,10 @@ const showTooltip = /*@__PURE__*/Facet.define({
|
|
|
8993
9252
|
});
|
|
8994
9253
|
const showHoverTooltip = /*@__PURE__*/Facet.define();
|
|
8995
9254
|
class HoverTooltipHost {
|
|
9255
|
+
// Needs to be static so that host tooltip instances always match
|
|
9256
|
+
static create(view) {
|
|
9257
|
+
return new HoverTooltipHost(view);
|
|
9258
|
+
}
|
|
8996
9259
|
constructor(view) {
|
|
8997
9260
|
this.view = view;
|
|
8998
9261
|
this.mounted = false;
|
|
@@ -9000,10 +9263,6 @@ class HoverTooltipHost {
|
|
|
9000
9263
|
this.dom.classList.add("cm-tooltip-hover");
|
|
9001
9264
|
this.manager = new TooltipViewManager(view, showHoverTooltip, t => this.createHostedView(t));
|
|
9002
9265
|
}
|
|
9003
|
-
// Needs to be static so that host tooltip instances always match
|
|
9004
|
-
static create(view) {
|
|
9005
|
-
return new HoverTooltipHost(view);
|
|
9006
|
-
}
|
|
9007
9266
|
createHostedView(tooltip) {
|
|
9008
9267
|
let hostedView = tooltip.create(this.view);
|
|
9009
9268
|
hostedView.dom.classList.add("cm-tooltip-section");
|
|
@@ -9083,30 +9342,41 @@ class HoverPlugin {
|
|
|
9083
9342
|
}
|
|
9084
9343
|
startHover() {
|
|
9085
9344
|
clearTimeout(this.restartTimeout);
|
|
9086
|
-
let { lastMove } = this;
|
|
9087
|
-
let
|
|
9088
|
-
if (
|
|
9345
|
+
let { view, lastMove } = this;
|
|
9346
|
+
let desc = view.docView.nearest(lastMove.target);
|
|
9347
|
+
if (!desc)
|
|
9089
9348
|
return;
|
|
9090
|
-
let
|
|
9091
|
-
if (
|
|
9092
|
-
|
|
9093
|
-
|
|
9094
|
-
|
|
9095
|
-
|
|
9096
|
-
|
|
9097
|
-
|
|
9349
|
+
let pos, side = 1;
|
|
9350
|
+
if (desc instanceof WidgetView) {
|
|
9351
|
+
pos = desc.posAtStart;
|
|
9352
|
+
}
|
|
9353
|
+
else {
|
|
9354
|
+
pos = view.posAtCoords(lastMove);
|
|
9355
|
+
if (pos == null)
|
|
9356
|
+
return;
|
|
9357
|
+
let posCoords = view.coordsAtPos(pos);
|
|
9358
|
+
if (!posCoords ||
|
|
9359
|
+
lastMove.y < posCoords.top || lastMove.y > posCoords.bottom ||
|
|
9360
|
+
lastMove.x < posCoords.left - view.defaultCharacterWidth ||
|
|
9361
|
+
lastMove.x > posCoords.right + view.defaultCharacterWidth)
|
|
9362
|
+
return;
|
|
9363
|
+
let bidi = view.bidiSpans(view.state.doc.lineAt(pos)).find(s => s.from <= pos && s.to >= pos);
|
|
9364
|
+
let rtl = bidi && bidi.dir == Direction.RTL ? -1 : 1;
|
|
9365
|
+
side = (lastMove.x < posCoords.left ? -rtl : rtl);
|
|
9366
|
+
}
|
|
9367
|
+
let open = this.source(view, pos, side);
|
|
9098
9368
|
if (open === null || open === void 0 ? void 0 : open.then) {
|
|
9099
9369
|
let pending = this.pending = { pos };
|
|
9100
9370
|
open.then(result => {
|
|
9101
9371
|
if (this.pending == pending) {
|
|
9102
9372
|
this.pending = null;
|
|
9103
9373
|
if (result)
|
|
9104
|
-
|
|
9374
|
+
view.dispatch({ effects: this.setHover.of(result) });
|
|
9105
9375
|
}
|
|
9106
|
-
}, e => logException(
|
|
9376
|
+
}, e => logException(view.state, e, "hover tooltip"));
|
|
9107
9377
|
}
|
|
9108
9378
|
else if (open) {
|
|
9109
|
-
|
|
9379
|
+
view.dispatch({ effects: this.setHover.of(open) });
|
|
9110
9380
|
}
|
|
9111
9381
|
}
|
|
9112
9382
|
mousemove(event) {
|
|
@@ -9118,7 +9388,7 @@ class HoverPlugin {
|
|
|
9118
9388
|
if (tooltip && !isInTooltip(this.lastMove.target) || this.pending) {
|
|
9119
9389
|
let { pos } = tooltip || this.pending, end = (_a = tooltip === null || tooltip === void 0 ? void 0 : tooltip.end) !== null && _a !== void 0 ? _a : pos;
|
|
9120
9390
|
if ((pos == end ? this.view.posAtCoords(this.lastMove) != pos
|
|
9121
|
-
: !isOverRange(this.view, pos, end, event.clientX, event.clientY
|
|
9391
|
+
: !isOverRange(this.view, pos, end, event.clientX, event.clientY))) {
|
|
9122
9392
|
this.view.dispatch({ effects: this.setHover.of(null) });
|
|
9123
9393
|
this.pending = null;
|
|
9124
9394
|
}
|
|
@@ -9143,19 +9413,12 @@ function isInTooltip(elt) {
|
|
|
9143
9413
|
return false;
|
|
9144
9414
|
}
|
|
9145
9415
|
function isOverRange(view, from, to, x, y, margin) {
|
|
9146
|
-
let
|
|
9147
|
-
let
|
|
9148
|
-
|
|
9149
|
-
|
|
9150
|
-
let
|
|
9151
|
-
|
|
9152
|
-
for (let i = 0; i < rects.length; i++) {
|
|
9153
|
-
let rect = rects[i];
|
|
9154
|
-
let dist = Math.max(rect.top - y, y - rect.bottom, rect.left - x, x - rect.right);
|
|
9155
|
-
if (dist <= margin)
|
|
9156
|
-
return true;
|
|
9157
|
-
}
|
|
9158
|
-
return false;
|
|
9416
|
+
let rect = view.scrollDOM.getBoundingClientRect();
|
|
9417
|
+
let docBottom = view.documentTop + view.documentPadding.top + view.contentHeight;
|
|
9418
|
+
if (rect.left > x || rect.right < x || rect.top > y || Math.min(rect.bottom, docBottom) < y)
|
|
9419
|
+
return false;
|
|
9420
|
+
let pos = view.posAtCoords({ x, y }, false);
|
|
9421
|
+
return pos >= from && pos <= to;
|
|
9159
9422
|
}
|
|
9160
9423
|
/**
|
|
9161
9424
|
Set up a hover tooltip, which shows up when the pointer hovers
|
|
@@ -9200,7 +9463,7 @@ function hoverTooltip(source, options = {}) {
|
|
|
9200
9463
|
});
|
|
9201
9464
|
return [
|
|
9202
9465
|
hoverState,
|
|
9203
|
-
ViewPlugin.define(view => new HoverPlugin(view, source, hoverState, setHover, options.hoverTime || 300 /* Time */)),
|
|
9466
|
+
ViewPlugin.define(view => new HoverPlugin(view, source, hoverState, setHover, options.hoverTime || 300 /* Hover.Time */)),
|
|
9204
9467
|
showHoverTooltipHost
|
|
9205
9468
|
];
|
|
9206
9469
|
}
|