@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.cjs
CHANGED
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
|
-
|
|
5
3
|
var state = require('@codemirror/state');
|
|
6
4
|
var styleMod = require('style-mod');
|
|
7
5
|
var w3cKeyname = require('w3c-keyname');
|
|
@@ -340,7 +338,7 @@ class ContentView {
|
|
|
340
338
|
constructor() {
|
|
341
339
|
this.parent = null;
|
|
342
340
|
this.dom = null;
|
|
343
|
-
this.flags = 2 /* NodeDirty */;
|
|
341
|
+
this.flags = 2 /* ViewFlag.NodeDirty */;
|
|
344
342
|
}
|
|
345
343
|
get overrideDOMText() { return null; }
|
|
346
344
|
get posAtStart() {
|
|
@@ -362,18 +360,18 @@ class ContentView {
|
|
|
362
360
|
return this.posBefore(view) + view.length;
|
|
363
361
|
}
|
|
364
362
|
sync(view, track) {
|
|
365
|
-
if (this.flags & 2 /* NodeDirty */) {
|
|
363
|
+
if (this.flags & 2 /* ViewFlag.NodeDirty */) {
|
|
366
364
|
let parent = this.dom;
|
|
367
365
|
let prev = null, next;
|
|
368
366
|
for (let child of this.children) {
|
|
369
|
-
if (child.flags & 7 /* Dirty */) {
|
|
367
|
+
if (child.flags & 7 /* ViewFlag.Dirty */) {
|
|
370
368
|
if (!child.dom && (next = prev ? prev.nextSibling : parent.firstChild)) {
|
|
371
369
|
let contentView = ContentView.get(next);
|
|
372
370
|
if (!contentView || !contentView.parent && contentView.canReuseDOM(child))
|
|
373
371
|
child.reuseDOM(next);
|
|
374
372
|
}
|
|
375
373
|
child.sync(view, track);
|
|
376
|
-
child.flags &= ~7 /* Dirty */;
|
|
374
|
+
child.flags &= ~7 /* ViewFlag.Dirty */;
|
|
377
375
|
}
|
|
378
376
|
next = prev ? prev.nextSibling : parent.firstChild;
|
|
379
377
|
if (track && !track.written && track.node == parent && next != child.dom)
|
|
@@ -393,11 +391,11 @@ class ContentView {
|
|
|
393
391
|
while (next)
|
|
394
392
|
next = rm$1(next);
|
|
395
393
|
}
|
|
396
|
-
else if (this.flags & 1 /* ChildDirty */) {
|
|
394
|
+
else if (this.flags & 1 /* ViewFlag.ChildDirty */) {
|
|
397
395
|
for (let child of this.children)
|
|
398
|
-
if (child.flags & 7 /* Dirty */) {
|
|
396
|
+
if (child.flags & 7 /* ViewFlag.Dirty */) {
|
|
399
397
|
child.sync(view, track);
|
|
400
|
-
child.flags &= ~7 /* Dirty */;
|
|
398
|
+
child.flags &= ~7 /* ViewFlag.Dirty */;
|
|
401
399
|
}
|
|
402
400
|
}
|
|
403
401
|
}
|
|
@@ -462,23 +460,23 @@ class ContentView {
|
|
|
462
460
|
endDOM: toI < this.children.length && toI >= 0 ? this.children[toI].dom : null };
|
|
463
461
|
}
|
|
464
462
|
markDirty(andParent = false) {
|
|
465
|
-
this.flags |= 2 /* NodeDirty */;
|
|
463
|
+
this.flags |= 2 /* ViewFlag.NodeDirty */;
|
|
466
464
|
this.markParentsDirty(andParent);
|
|
467
465
|
}
|
|
468
466
|
markParentsDirty(childList) {
|
|
469
467
|
for (let parent = this.parent; parent; parent = parent.parent) {
|
|
470
468
|
if (childList)
|
|
471
|
-
parent.flags |= 2 /* NodeDirty */;
|
|
472
|
-
if (parent.flags & 1 /* ChildDirty */)
|
|
469
|
+
parent.flags |= 2 /* ViewFlag.NodeDirty */;
|
|
470
|
+
if (parent.flags & 1 /* ViewFlag.ChildDirty */)
|
|
473
471
|
return;
|
|
474
|
-
parent.flags |= 1 /* ChildDirty */;
|
|
472
|
+
parent.flags |= 1 /* ViewFlag.ChildDirty */;
|
|
475
473
|
childList = false;
|
|
476
474
|
}
|
|
477
475
|
}
|
|
478
476
|
setParent(parent) {
|
|
479
477
|
if (this.parent != parent) {
|
|
480
478
|
this.parent = parent;
|
|
481
|
-
if (this.flags & 7 /* Dirty */)
|
|
479
|
+
if (this.flags & 7 /* ViewFlag.Dirty */)
|
|
482
480
|
this.markParentsDirty(true);
|
|
483
481
|
}
|
|
484
482
|
}
|
|
@@ -530,7 +528,7 @@ class ContentView {
|
|
|
530
528
|
}
|
|
531
529
|
become(other) { return false; }
|
|
532
530
|
canReuseDOM(other) {
|
|
533
|
-
return other.constructor == this.constructor && !((this.flags | other.flags) & 8 /* Composition */);
|
|
531
|
+
return other.constructor == this.constructor && !((this.flags | other.flags) & 8 /* ViewFlag.Composition */);
|
|
534
532
|
}
|
|
535
533
|
// When this is a zero-length view with a side, this should return a
|
|
536
534
|
// number <= 0 to indicate it is before its position, or a
|
|
@@ -815,10 +813,10 @@ class TextView extends ContentView {
|
|
|
815
813
|
this.createDOM(dom);
|
|
816
814
|
}
|
|
817
815
|
merge(from, to, source) {
|
|
818
|
-
if ((this.flags & 8 /* Composition */) ||
|
|
816
|
+
if ((this.flags & 8 /* ViewFlag.Composition */) ||
|
|
819
817
|
source && (!(source instanceof TextView) ||
|
|
820
818
|
this.length - (to - from) + source.length > MaxJoinLen ||
|
|
821
|
-
(source.flags & 8 /* Composition */)))
|
|
819
|
+
(source.flags & 8 /* ViewFlag.Composition */)))
|
|
822
820
|
return false;
|
|
823
821
|
this.text = this.text.slice(0, from) + (source ? source.text : "") + this.text.slice(to);
|
|
824
822
|
this.markDirty();
|
|
@@ -828,7 +826,7 @@ class TextView extends ContentView {
|
|
|
828
826
|
let result = new TextView(this.text.slice(from));
|
|
829
827
|
this.text = this.text.slice(0, from);
|
|
830
828
|
this.markDirty();
|
|
831
|
-
result.flags |= this.flags & 8 /* Composition */;
|
|
829
|
+
result.flags |= this.flags & 8 /* ViewFlag.Composition */;
|
|
832
830
|
return result;
|
|
833
831
|
}
|
|
834
832
|
localPosFromDOM(node, offset) {
|
|
@@ -861,18 +859,18 @@ class MarkView extends ContentView {
|
|
|
861
859
|
return dom;
|
|
862
860
|
}
|
|
863
861
|
canReuseDOM(other) {
|
|
864
|
-
return super.canReuseDOM(other) && !((this.flags | other.flags) & 8 /* Composition */);
|
|
862
|
+
return super.canReuseDOM(other) && !((this.flags | other.flags) & 8 /* ViewFlag.Composition */);
|
|
865
863
|
}
|
|
866
864
|
reuseDOM(node) {
|
|
867
865
|
if (node.nodeName == this.mark.tagName.toUpperCase()) {
|
|
868
866
|
this.setDOM(node);
|
|
869
|
-
this.flags |= 4 /* AttrsDirty */ | 2 /* NodeDirty */;
|
|
867
|
+
this.flags |= 4 /* ViewFlag.AttrsDirty */ | 2 /* ViewFlag.NodeDirty */;
|
|
870
868
|
}
|
|
871
869
|
}
|
|
872
870
|
sync(view, track) {
|
|
873
871
|
if (!this.dom)
|
|
874
872
|
this.setDOM(this.setAttrs(document.createElement(this.mark.tagName)));
|
|
875
|
-
else if (this.flags & 4 /* AttrsDirty */)
|
|
873
|
+
else if (this.flags & 4 /* ViewFlag.AttrsDirty */)
|
|
876
874
|
this.setAttrs(this.dom);
|
|
877
875
|
super.sync(view, track);
|
|
878
876
|
}
|
|
@@ -943,6 +941,9 @@ function textCoords(text, pos, side) {
|
|
|
943
941
|
}
|
|
944
942
|
// Also used for collapsed ranges that don't have a placeholder widget!
|
|
945
943
|
class WidgetView extends ContentView {
|
|
944
|
+
static create(widget, length, side) {
|
|
945
|
+
return new WidgetView(widget, length, side);
|
|
946
|
+
}
|
|
946
947
|
constructor(widget, length, side) {
|
|
947
948
|
super();
|
|
948
949
|
this.widget = widget;
|
|
@@ -950,9 +951,6 @@ class WidgetView extends ContentView {
|
|
|
950
951
|
this.side = side;
|
|
951
952
|
this.prevWidget = null;
|
|
952
953
|
}
|
|
953
|
-
static create(widget, length, side) {
|
|
954
|
-
return new WidgetView(widget, length, side);
|
|
955
|
-
}
|
|
956
954
|
split(from) {
|
|
957
955
|
let result = WidgetView.create(this.widget, this.length - from, this.side);
|
|
958
956
|
this.length -= from;
|
|
@@ -1167,16 +1165,26 @@ function attrsEq(a, b, ignore) {
|
|
|
1167
1165
|
return true;
|
|
1168
1166
|
}
|
|
1169
1167
|
function updateAttrs(dom, prev, attrs) {
|
|
1170
|
-
let changed =
|
|
1168
|
+
let changed = false;
|
|
1171
1169
|
if (prev)
|
|
1172
1170
|
for (let name in prev)
|
|
1173
|
-
if (!(attrs && name in attrs))
|
|
1174
|
-
|
|
1171
|
+
if (!(attrs && name in attrs)) {
|
|
1172
|
+
changed = true;
|
|
1173
|
+
if (name == "style")
|
|
1174
|
+
dom.style.cssText = "";
|
|
1175
|
+
else
|
|
1176
|
+
dom.removeAttribute(name);
|
|
1177
|
+
}
|
|
1175
1178
|
if (attrs)
|
|
1176
1179
|
for (let name in attrs)
|
|
1177
|
-
if (!(prev && prev[name] == attrs[name]))
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
+
if (!(prev && prev[name] == attrs[name])) {
|
|
1181
|
+
changed = true;
|
|
1182
|
+
if (name == "style")
|
|
1183
|
+
dom.style.cssText = attrs[name];
|
|
1184
|
+
else
|
|
1185
|
+
dom.setAttribute(name, attrs[name]);
|
|
1186
|
+
}
|
|
1187
|
+
return changed;
|
|
1180
1188
|
}
|
|
1181
1189
|
function getAttrs(dom) {
|
|
1182
1190
|
let attrs = Object.create(null);
|
|
@@ -1334,8 +1342,8 @@ class Decoration extends state.RangeValue {
|
|
|
1334
1342
|
static widget(spec) {
|
|
1335
1343
|
let side = Math.max(-10000, Math.min(10000, spec.side || 0)), block = !!spec.block;
|
|
1336
1344
|
side += (block && !spec.inlineOrder)
|
|
1337
|
-
? (side > 0 ? 300000000 /* BlockAfter */ : -400000000 /* BlockBefore */)
|
|
1338
|
-
: (side > 0 ? 100000000 /* InlineAfter */ : -100000000 /* InlineBefore */);
|
|
1345
|
+
? (side > 0 ? 300000000 /* Side.BlockAfter */ : -400000000 /* Side.BlockBefore */)
|
|
1346
|
+
: (side > 0 ? 100000000 /* Side.InlineAfter */ : -100000000 /* Side.InlineBefore */);
|
|
1339
1347
|
return new PointDecoration(spec, side, side, block, spec.widget || null, false);
|
|
1340
1348
|
}
|
|
1341
1349
|
/**
|
|
@@ -1345,13 +1353,13 @@ class Decoration extends state.RangeValue {
|
|
|
1345
1353
|
static replace(spec) {
|
|
1346
1354
|
let block = !!spec.block, startSide, endSide;
|
|
1347
1355
|
if (spec.isBlockGap) {
|
|
1348
|
-
startSide = -500000000 /* GapStart */;
|
|
1349
|
-
endSide = 400000000 /* GapEnd */;
|
|
1356
|
+
startSide = -500000000 /* Side.GapStart */;
|
|
1357
|
+
endSide = 400000000 /* Side.GapEnd */;
|
|
1350
1358
|
}
|
|
1351
1359
|
else {
|
|
1352
1360
|
let { start, end } = getInclusive(spec, block);
|
|
1353
|
-
startSide = (start ? (block ? -300000000 /* BlockIncStart */ : -1 /* InlineIncStart */) : 500000000 /* NonIncStart */) - 1;
|
|
1354
|
-
endSide = (end ? (block ? 200000000 /* BlockIncEnd */ : 1 /* InlineIncEnd */) : -600000000 /* NonIncEnd */) + 1;
|
|
1361
|
+
startSide = (start ? (block ? -300000000 /* Side.BlockIncStart */ : -1 /* Side.InlineIncStart */) : 500000000 /* Side.NonIncStart */) - 1;
|
|
1362
|
+
endSide = (end ? (block ? 200000000 /* Side.BlockIncEnd */ : 1 /* Side.InlineIncEnd */) : -600000000 /* Side.NonIncEnd */) + 1;
|
|
1355
1363
|
}
|
|
1356
1364
|
return new PointDecoration(spec, startSide, endSide, block, spec.widget || null, true);
|
|
1357
1365
|
}
|
|
@@ -1382,7 +1390,7 @@ Decoration.none = state.RangeSet.empty;
|
|
|
1382
1390
|
class MarkDecoration extends Decoration {
|
|
1383
1391
|
constructor(spec) {
|
|
1384
1392
|
let { start, end } = getInclusive(spec);
|
|
1385
|
-
super(start ? -1 /* InlineIncStart */ : 500000000 /* NonIncStart */, end ? 1 /* InlineIncEnd */ : -600000000 /* NonIncEnd */, null, spec);
|
|
1393
|
+
super(start ? -1 /* Side.InlineIncStart */ : 500000000 /* Side.NonIncStart */, end ? 1 /* Side.InlineIncEnd */ : -600000000 /* Side.NonIncEnd */, null, spec);
|
|
1386
1394
|
this.tagName = spec.tagName || "span";
|
|
1387
1395
|
this.class = spec.class || "";
|
|
1388
1396
|
this.attrs = spec.attributes || null;
|
|
@@ -1404,7 +1412,7 @@ class MarkDecoration extends Decoration {
|
|
|
1404
1412
|
MarkDecoration.prototype.point = false;
|
|
1405
1413
|
class LineDecoration extends Decoration {
|
|
1406
1414
|
constructor(spec) {
|
|
1407
|
-
super(-200000000 /* Line */, -200000000 /* Line */, null, spec);
|
|
1415
|
+
super(-200000000 /* Side.Line */, -200000000 /* Side.Line */, null, spec);
|
|
1408
1416
|
}
|
|
1409
1417
|
eq(other) {
|
|
1410
1418
|
return other instanceof LineDecoration &&
|
|
@@ -1545,7 +1553,7 @@ class LineView extends ContentView {
|
|
|
1545
1553
|
reuseDOM(node) {
|
|
1546
1554
|
if (node.nodeName == "DIV") {
|
|
1547
1555
|
this.setDOM(node);
|
|
1548
|
-
this.flags |= 4 /* AttrsDirty */ | 2 /* NodeDirty */;
|
|
1556
|
+
this.flags |= 4 /* ViewFlag.AttrsDirty */ | 2 /* ViewFlag.NodeDirty */;
|
|
1549
1557
|
}
|
|
1550
1558
|
}
|
|
1551
1559
|
sync(view, track) {
|
|
@@ -1555,7 +1563,7 @@ class LineView extends ContentView {
|
|
|
1555
1563
|
this.dom.className = "cm-line";
|
|
1556
1564
|
this.prevAttrs = this.attrs ? null : undefined;
|
|
1557
1565
|
}
|
|
1558
|
-
else if (this.flags & 4 /* AttrsDirty */) {
|
|
1566
|
+
else if (this.flags & 4 /* ViewFlag.AttrsDirty */) {
|
|
1559
1567
|
clearAttributes(this.dom);
|
|
1560
1568
|
this.dom.className = "cm-line";
|
|
1561
1569
|
this.prevAttrs = this.attrs ? null : undefined;
|
|
@@ -1703,7 +1711,7 @@ class ContentBuilder {
|
|
|
1703
1711
|
this.content = [];
|
|
1704
1712
|
this.curLine = null;
|
|
1705
1713
|
this.breakAtStart = 0;
|
|
1706
|
-
this.pendingBuffer = 0 /* No */;
|
|
1714
|
+
this.pendingBuffer = 0 /* Buf.No */;
|
|
1707
1715
|
this.bufferMarks = [];
|
|
1708
1716
|
// Set to false directly after a widget that covers the position after it
|
|
1709
1717
|
this.atCursorPos = true;
|
|
@@ -1730,7 +1738,7 @@ class ContentBuilder {
|
|
|
1730
1738
|
flushBuffer(active = this.bufferMarks) {
|
|
1731
1739
|
if (this.pendingBuffer) {
|
|
1732
1740
|
this.curLine.append(wrapMarks(new WidgetBufferView(-1), active), active.length);
|
|
1733
|
-
this.pendingBuffer = 0 /* No */;
|
|
1741
|
+
this.pendingBuffer = 0 /* Buf.No */;
|
|
1734
1742
|
}
|
|
1735
1743
|
}
|
|
1736
1744
|
addBlockWidget(view) {
|
|
@@ -1742,7 +1750,7 @@ class ContentBuilder {
|
|
|
1742
1750
|
if (this.pendingBuffer && openEnd <= this.bufferMarks.length)
|
|
1743
1751
|
this.flushBuffer();
|
|
1744
1752
|
else
|
|
1745
|
-
this.pendingBuffer = 0 /* No */;
|
|
1753
|
+
this.pendingBuffer = 0 /* Buf.No */;
|
|
1746
1754
|
if (!this.posCovered())
|
|
1747
1755
|
this.getLine();
|
|
1748
1756
|
}
|
|
@@ -1771,7 +1779,7 @@ class ContentBuilder {
|
|
|
1771
1779
|
this.textOff = 0;
|
|
1772
1780
|
}
|
|
1773
1781
|
}
|
|
1774
|
-
let take = Math.min(this.text.length - this.textOff, length, 512 /* Chunk */);
|
|
1782
|
+
let take = Math.min(this.text.length - this.textOff, length, 512 /* T.Chunk */);
|
|
1775
1783
|
this.flushBuffer(active.slice(active.length - openStart));
|
|
1776
1784
|
this.getLine().append(wrapMarks(new TextView(this.text.slice(this.textOff, this.textOff + take)), active), openStart);
|
|
1777
1785
|
this.atCursorPos = true;
|
|
@@ -1807,8 +1815,8 @@ class ContentBuilder {
|
|
|
1807
1815
|
(from < to || deco.startSide > 0);
|
|
1808
1816
|
let cursorAfter = !view.isEditable && (from < to || openStart > active.length || deco.startSide <= 0);
|
|
1809
1817
|
let line = this.getLine();
|
|
1810
|
-
if (this.pendingBuffer == 2 /* IfCursor */ && !cursorBefore && !view.isEditable)
|
|
1811
|
-
this.pendingBuffer = 0 /* No */;
|
|
1818
|
+
if (this.pendingBuffer == 2 /* Buf.IfCursor */ && !cursorBefore && !view.isEditable)
|
|
1819
|
+
this.pendingBuffer = 0 /* Buf.No */;
|
|
1812
1820
|
this.flushBuffer(active);
|
|
1813
1821
|
if (cursorBefore) {
|
|
1814
1822
|
line.append(wrapMarks(new WidgetBufferView(1), active), openStart);
|
|
@@ -1816,7 +1824,7 @@ class ContentBuilder {
|
|
|
1816
1824
|
}
|
|
1817
1825
|
line.append(wrapMarks(view, active), openStart);
|
|
1818
1826
|
this.atCursorPos = cursorAfter;
|
|
1819
|
-
this.pendingBuffer = !cursorAfter ? 0 /* No */ : from < to || openStart > active.length ? 1 /* Yes */ : 2 /* IfCursor */;
|
|
1827
|
+
this.pendingBuffer = !cursorAfter ? 0 /* Buf.No */ : from < to || openStart > active.length ? 1 /* Buf.Yes */ : 2 /* Buf.IfCursor */;
|
|
1820
1828
|
if (this.pendingBuffer)
|
|
1821
1829
|
this.bufferMarks = active.slice();
|
|
1822
1830
|
}
|
|
@@ -2030,6 +2038,36 @@ const contentAttributes = state.Facet.define();
|
|
|
2030
2038
|
// Provide decorations
|
|
2031
2039
|
const decorations = state.Facet.define();
|
|
2032
2040
|
const atomicRanges = state.Facet.define();
|
|
2041
|
+
const bidiIsolatedRanges = state.Facet.define();
|
|
2042
|
+
function getIsolatedRanges(view, from, to) {
|
|
2043
|
+
let isolates = view.state.facet(bidiIsolatedRanges);
|
|
2044
|
+
if (!isolates.length)
|
|
2045
|
+
return isolates;
|
|
2046
|
+
let sets = isolates.map(i => i instanceof Function ? i(view) : i);
|
|
2047
|
+
let result = [];
|
|
2048
|
+
state.RangeSet.spans(sets, from, to, {
|
|
2049
|
+
point() { },
|
|
2050
|
+
span(from, to, active, open) {
|
|
2051
|
+
let level = result;
|
|
2052
|
+
for (let i = active.length - 1; i >= 0; i--, open--) {
|
|
2053
|
+
let iso = active[i].spec.bidiIsolate, update;
|
|
2054
|
+
if (iso == null)
|
|
2055
|
+
continue;
|
|
2056
|
+
if (open > 0 && level.length &&
|
|
2057
|
+
(update = level[level.length - 1]).to == from && update.direction == iso) {
|
|
2058
|
+
update.to = to;
|
|
2059
|
+
level = update.inner;
|
|
2060
|
+
}
|
|
2061
|
+
else {
|
|
2062
|
+
let add = { from, to, direction: iso, inner: [] };
|
|
2063
|
+
level.push(add);
|
|
2064
|
+
level = add.inner;
|
|
2065
|
+
}
|
|
2066
|
+
}
|
|
2067
|
+
}
|
|
2068
|
+
});
|
|
2069
|
+
return result;
|
|
2070
|
+
}
|
|
2033
2071
|
const scrollMargins = state.Facet.define();
|
|
2034
2072
|
function getScrollMargins(view) {
|
|
2035
2073
|
let left = 0, right = 0, top = 0, bottom = 0;
|
|
@@ -2143,27 +2181,27 @@ class ViewUpdate {
|
|
|
2143
2181
|
update.
|
|
2144
2182
|
*/
|
|
2145
2183
|
get viewportChanged() {
|
|
2146
|
-
return (this.flags & 4 /* Viewport */) > 0;
|
|
2184
|
+
return (this.flags & 4 /* UpdateFlag.Viewport */) > 0;
|
|
2147
2185
|
}
|
|
2148
2186
|
/**
|
|
2149
2187
|
Indicates whether the height of a block element in the editor
|
|
2150
2188
|
changed in this update.
|
|
2151
2189
|
*/
|
|
2152
2190
|
get heightChanged() {
|
|
2153
|
-
return (this.flags & 2 /* Height */) > 0;
|
|
2191
|
+
return (this.flags & 2 /* UpdateFlag.Height */) > 0;
|
|
2154
2192
|
}
|
|
2155
2193
|
/**
|
|
2156
2194
|
Returns true when the document was modified or the size of the
|
|
2157
2195
|
editor, or elements within the editor, changed.
|
|
2158
2196
|
*/
|
|
2159
2197
|
get geometryChanged() {
|
|
2160
|
-
return this.docChanged || (this.flags & (8 /* Geometry */ | 2 /* Height */)) > 0;
|
|
2198
|
+
return this.docChanged || (this.flags & (8 /* UpdateFlag.Geometry */ | 2 /* UpdateFlag.Height */)) > 0;
|
|
2161
2199
|
}
|
|
2162
2200
|
/**
|
|
2163
2201
|
True when this update indicates a focus change.
|
|
2164
2202
|
*/
|
|
2165
2203
|
get focusChanged() {
|
|
2166
|
-
return (this.flags & 1 /* Focus */) > 0;
|
|
2204
|
+
return (this.flags & 1 /* UpdateFlag.Focus */) > 0;
|
|
2167
2205
|
}
|
|
2168
2206
|
/**
|
|
2169
2207
|
Whether the document changed in this update.
|
|
@@ -2222,12 +2260,12 @@ for (let p of ["()", "[]", "{}"]) {
|
|
|
2222
2260
|
}
|
|
2223
2261
|
function charType(ch) {
|
|
2224
2262
|
return ch <= 0xf7 ? LowTypes[ch] :
|
|
2225
|
-
0x590 <= ch && ch <= 0x5f4 ? 2 /* R */ :
|
|
2263
|
+
0x590 <= ch && ch <= 0x5f4 ? 2 /* T.R */ :
|
|
2226
2264
|
0x600 <= ch && ch <= 0x6f9 ? ArabicTypes[ch - 0x600] :
|
|
2227
|
-
0x6ee <= ch && ch <= 0x8ac ? 4 /* AL */ :
|
|
2228
|
-
0x2000 <= ch && ch <= 0x200b ? 256 /* NI */ :
|
|
2229
|
-
0xfb50 <= ch && ch <= 0xfdff ? 4 /* AL */ :
|
|
2230
|
-
ch == 0x200c ? 256 /* NI */ : 1 /* L */;
|
|
2265
|
+
0x6ee <= ch && ch <= 0x8ac ? 4 /* T.AL */ :
|
|
2266
|
+
0x2000 <= ch && ch <= 0x200b ? 256 /* T.NI */ :
|
|
2267
|
+
0xfb50 <= ch && ch <= 0xfdff ? 4 /* T.AL */ :
|
|
2268
|
+
ch == 0x200c ? 256 /* T.NI */ : 1 /* T.L */;
|
|
2231
2269
|
}
|
|
2232
2270
|
const BidiRE = /[\u0590-\u05f4\u0600-\u06ff\u0700-\u08ac\ufb50-\ufdff]/;
|
|
2233
2271
|
/**
|
|
@@ -2235,6 +2273,10 @@ Represents a contiguous range of text that has a single direction
|
|
|
2235
2273
|
(as in left-to-right or right-to-left).
|
|
2236
2274
|
*/
|
|
2237
2275
|
class BidiSpan {
|
|
2276
|
+
/**
|
|
2277
|
+
The direction of this span.
|
|
2278
|
+
*/
|
|
2279
|
+
get dir() { return this.level % 2 ? RTL : LTR; }
|
|
2238
2280
|
/**
|
|
2239
2281
|
@internal
|
|
2240
2282
|
*/
|
|
@@ -2260,10 +2302,6 @@ class BidiSpan {
|
|
|
2260
2302
|
this.level = level;
|
|
2261
2303
|
}
|
|
2262
2304
|
/**
|
|
2263
|
-
The direction of this span.
|
|
2264
|
-
*/
|
|
2265
|
-
get dir() { return this.level % 2 ? RTL : LTR; }
|
|
2266
|
-
/**
|
|
2267
2305
|
@internal
|
|
2268
2306
|
*/
|
|
2269
2307
|
side(end, dir) { return (this.dir == dir) == end ? this.to : this.from; }
|
|
@@ -2289,166 +2327,328 @@ class BidiSpan {
|
|
|
2289
2327
|
return maybe;
|
|
2290
2328
|
}
|
|
2291
2329
|
}
|
|
2330
|
+
function isolatesEq(a, b) {
|
|
2331
|
+
if (a.length != b.length)
|
|
2332
|
+
return false;
|
|
2333
|
+
for (let i = 0; i < a.length; i++) {
|
|
2334
|
+
let iA = a[i], iB = b[i];
|
|
2335
|
+
if (iA.from != iB.from || iA.to != iB.to || iA.direction != iB.direction || !isolatesEq(iA.inner, iB.inner))
|
|
2336
|
+
return false;
|
|
2337
|
+
}
|
|
2338
|
+
return true;
|
|
2339
|
+
}
|
|
2292
2340
|
// Reused array of character types
|
|
2293
2341
|
const types = [];
|
|
2294
|
-
|
|
2295
|
-
|
|
2296
|
-
|
|
2297
|
-
|
|
2298
|
-
|
|
2299
|
-
|
|
2300
|
-
|
|
2301
|
-
|
|
2302
|
-
|
|
2303
|
-
|
|
2304
|
-
|
|
2305
|
-
|
|
2306
|
-
|
|
2307
|
-
|
|
2308
|
-
|
|
2309
|
-
|
|
2310
|
-
|
|
2311
|
-
type =
|
|
2312
|
-
|
|
2313
|
-
|
|
2314
|
-
|
|
2315
|
-
|
|
2316
|
-
|
|
2317
|
-
|
|
2318
|
-
|
|
2319
|
-
|
|
2320
|
-
|
|
2321
|
-
|
|
2322
|
-
|
|
2323
|
-
|
|
2324
|
-
|
|
2325
|
-
|
|
2326
|
-
|
|
2327
|
-
|
|
2328
|
-
|
|
2329
|
-
|
|
2330
|
-
|
|
2331
|
-
|
|
2332
|
-
|
|
2333
|
-
|
|
2334
|
-
|
|
2335
|
-
|
|
2336
|
-
|
|
2337
|
-
|
|
2338
|
-
end
|
|
2339
|
-
|
|
2340
|
-
|
|
2341
|
-
types[
|
|
2342
|
-
|
|
2343
|
-
|
|
2344
|
-
|
|
2345
|
-
|
|
2346
|
-
|
|
2347
|
-
|
|
2348
|
-
|
|
2349
|
-
|
|
2350
|
-
|
|
2351
|
-
|
|
2352
|
-
|
|
2353
|
-
|
|
2354
|
-
|
|
2355
|
-
|
|
2356
|
-
|
|
2357
|
-
|
|
2358
|
-
|
|
2359
|
-
|
|
2342
|
+
// Fill in the character types (in `types`) from `from` to `to` and
|
|
2343
|
+
// apply W normalization rules.
|
|
2344
|
+
function computeCharTypes(line, rFrom, rTo, isolates, outerType) {
|
|
2345
|
+
for (let iI = 0; iI <= isolates.length; iI++) {
|
|
2346
|
+
let from = iI ? isolates[iI - 1].to : rFrom, to = iI < isolates.length ? isolates[iI].from : rTo;
|
|
2347
|
+
let prevType = iI ? 256 /* T.NI */ : outerType;
|
|
2348
|
+
// W1. Examine each non-spacing mark (NSM) in the level run, and
|
|
2349
|
+
// change the type of the NSM to the type of the previous
|
|
2350
|
+
// character. If the NSM is at the start of the level run, it will
|
|
2351
|
+
// get the type of sor.
|
|
2352
|
+
// W2. Search backwards from each instance of a European number
|
|
2353
|
+
// until the first strong type (R, L, AL, or sor) is found. If an
|
|
2354
|
+
// AL is found, change the type of the European number to Arabic
|
|
2355
|
+
// number.
|
|
2356
|
+
// W3. Change all ALs to R.
|
|
2357
|
+
// (Left after this: L, R, EN, AN, ET, CS, NI)
|
|
2358
|
+
for (let i = from, prev = prevType, prevStrong = prevType; i < to; i++) {
|
|
2359
|
+
let type = charType(line.charCodeAt(i));
|
|
2360
|
+
if (type == 512 /* T.NSM */)
|
|
2361
|
+
type = prev;
|
|
2362
|
+
else if (type == 8 /* T.EN */ && prevStrong == 4 /* T.AL */)
|
|
2363
|
+
type = 16 /* T.AN */;
|
|
2364
|
+
types[i] = type == 4 /* T.AL */ ? 2 /* T.R */ : type;
|
|
2365
|
+
if (type & 7 /* T.Strong */)
|
|
2366
|
+
prevStrong = type;
|
|
2367
|
+
prev = type;
|
|
2368
|
+
}
|
|
2369
|
+
// W5. A sequence of European terminators adjacent to European
|
|
2370
|
+
// numbers changes to all European numbers.
|
|
2371
|
+
// W6. Otherwise, separators and terminators change to Other
|
|
2372
|
+
// Neutral.
|
|
2373
|
+
// W7. Search backwards from each instance of a European number
|
|
2374
|
+
// until the first strong type (R, L, or sor) is found. If an L is
|
|
2375
|
+
// found, then change the type of the European number to L.
|
|
2376
|
+
// (Left after this: L, R, EN+AN, NI)
|
|
2377
|
+
for (let i = from, prev = prevType, prevStrong = prevType; i < to; i++) {
|
|
2378
|
+
let type = types[i];
|
|
2379
|
+
if (type == 128 /* T.CS */) {
|
|
2380
|
+
if (i < to - 1 && prev == types[i + 1] && (prev & 24 /* T.Num */))
|
|
2381
|
+
type = types[i] = prev;
|
|
2382
|
+
else
|
|
2383
|
+
types[i] = 256 /* T.NI */;
|
|
2384
|
+
}
|
|
2385
|
+
else if (type == 64 /* T.ET */) {
|
|
2386
|
+
let end = i + 1;
|
|
2387
|
+
while (end < to && types[end] == 64 /* T.ET */)
|
|
2388
|
+
end++;
|
|
2389
|
+
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 */;
|
|
2390
|
+
for (let j = i; j < end; j++)
|
|
2391
|
+
types[j] = replace;
|
|
2392
|
+
i = end - 1;
|
|
2393
|
+
}
|
|
2394
|
+
else if (type == 8 /* T.EN */ && prevStrong == 1 /* T.L */) {
|
|
2395
|
+
types[i] = 1 /* T.L */;
|
|
2396
|
+
}
|
|
2397
|
+
prev = type;
|
|
2398
|
+
if (type & 7 /* T.Strong */)
|
|
2399
|
+
prevStrong = type;
|
|
2400
|
+
}
|
|
2401
|
+
}
|
|
2402
|
+
}
|
|
2403
|
+
// Process brackets throughout a run sequence.
|
|
2404
|
+
function processBracketPairs(line, rFrom, rTo, isolates, outerType) {
|
|
2405
|
+
let oppositeType = outerType == 1 /* T.L */ ? 2 /* T.R */ : 1 /* T.L */;
|
|
2406
|
+
for (let iI = 0, sI = 0, context = 0; iI <= isolates.length; iI++) {
|
|
2407
|
+
let from = iI ? isolates[iI - 1].to : rFrom, to = iI < isolates.length ? isolates[iI].from : rTo;
|
|
2408
|
+
// N0. Process bracket pairs in an isolating run sequence
|
|
2409
|
+
// sequentially in the logical order of the text positions of the
|
|
2410
|
+
// opening paired brackets using the logic given below. Within this
|
|
2411
|
+
// scope, bidirectional types EN and AN are treated as R.
|
|
2412
|
+
for (let i = from, ch, br, type; i < to; i++) {
|
|
2413
|
+
// Keeps [startIndex, type, strongSeen] triples for each open
|
|
2414
|
+
// bracket on BracketStack.
|
|
2415
|
+
if (br = Brackets[ch = line.charCodeAt(i)]) {
|
|
2416
|
+
if (br < 0) { // Closing bracket
|
|
2417
|
+
for (let sJ = sI - 3; sJ >= 0; sJ -= 3) {
|
|
2418
|
+
if (BracketStack[sJ + 1] == -br) {
|
|
2419
|
+
let flags = BracketStack[sJ + 2];
|
|
2420
|
+
let type = (flags & 2 /* Bracketed.EmbedInside */) ? outerType :
|
|
2421
|
+
!(flags & 4 /* Bracketed.OppositeInside */) ? 0 :
|
|
2422
|
+
(flags & 1 /* Bracketed.OppositeBefore */) ? oppositeType : outerType;
|
|
2423
|
+
if (type)
|
|
2424
|
+
types[i] = types[BracketStack[sJ]] = type;
|
|
2425
|
+
sI = sJ;
|
|
2426
|
+
break;
|
|
2427
|
+
}
|
|
2428
|
+
}
|
|
2429
|
+
}
|
|
2430
|
+
else if (BracketStack.length == 189 /* Bracketed.MaxDepth */) {
|
|
2431
|
+
break;
|
|
2432
|
+
}
|
|
2433
|
+
else {
|
|
2434
|
+
BracketStack[sI++] = i;
|
|
2435
|
+
BracketStack[sI++] = ch;
|
|
2436
|
+
BracketStack[sI++] = context;
|
|
2437
|
+
}
|
|
2438
|
+
}
|
|
2439
|
+
else if ((type = types[i]) == 2 /* T.R */ || type == 1 /* T.L */) {
|
|
2440
|
+
let embed = type == outerType;
|
|
2441
|
+
context = embed ? 0 : 1 /* Bracketed.OppositeBefore */;
|
|
2360
2442
|
for (let sJ = sI - 3; sJ >= 0; sJ -= 3) {
|
|
2361
|
-
|
|
2362
|
-
|
|
2363
|
-
let type = (flags & 2 /* EmbedInside */) ? outerType :
|
|
2364
|
-
!(flags & 4 /* OppositeInside */) ? 0 :
|
|
2365
|
-
(flags & 1 /* OppositeBefore */) ? oppositeType : outerType;
|
|
2366
|
-
if (type)
|
|
2367
|
-
types[i] = types[BracketStack[sJ]] = type;
|
|
2368
|
-
sI = sJ;
|
|
2443
|
+
let cur = BracketStack[sJ + 2];
|
|
2444
|
+
if (cur & 2 /* Bracketed.EmbedInside */)
|
|
2369
2445
|
break;
|
|
2446
|
+
if (embed) {
|
|
2447
|
+
BracketStack[sJ + 2] |= 2 /* Bracketed.EmbedInside */;
|
|
2448
|
+
}
|
|
2449
|
+
else {
|
|
2450
|
+
if (cur & 4 /* Bracketed.OppositeInside */)
|
|
2451
|
+
break;
|
|
2452
|
+
BracketStack[sJ + 2] |= 4 /* Bracketed.OppositeInside */;
|
|
2370
2453
|
}
|
|
2371
2454
|
}
|
|
2372
2455
|
}
|
|
2373
|
-
|
|
2374
|
-
|
|
2456
|
+
}
|
|
2457
|
+
}
|
|
2458
|
+
}
|
|
2459
|
+
function processNeutrals(rFrom, rTo, isolates, outerType) {
|
|
2460
|
+
for (let iI = 0, prev = outerType; iI <= isolates.length; iI++) {
|
|
2461
|
+
let from = iI ? isolates[iI - 1].to : rFrom, to = iI < isolates.length ? isolates[iI].from : rTo;
|
|
2462
|
+
// N1. A sequence of neutrals takes the direction of the
|
|
2463
|
+
// surrounding strong text if the text on both sides has the same
|
|
2464
|
+
// direction. European and Arabic numbers act as if they were R in
|
|
2465
|
+
// terms of their influence on neutrals. Start-of-level-run (sor)
|
|
2466
|
+
// and end-of-level-run (eor) are used at level run boundaries.
|
|
2467
|
+
// N2. Any remaining neutrals take the embedding direction.
|
|
2468
|
+
// (Left after this: L, R, EN+AN)
|
|
2469
|
+
for (let i = from; i < to;) {
|
|
2470
|
+
let type = types[i];
|
|
2471
|
+
if (type == 256 /* T.NI */) {
|
|
2472
|
+
let end = i + 1;
|
|
2473
|
+
for (;;) {
|
|
2474
|
+
if (end == to) {
|
|
2475
|
+
if (iI == isolates.length)
|
|
2476
|
+
break;
|
|
2477
|
+
end = isolates[iI++].to;
|
|
2478
|
+
to = iI < isolates.length ? isolates[iI].from : rTo;
|
|
2479
|
+
}
|
|
2480
|
+
else if (types[end] == 256 /* T.NI */) {
|
|
2481
|
+
end++;
|
|
2482
|
+
}
|
|
2483
|
+
else {
|
|
2484
|
+
break;
|
|
2485
|
+
}
|
|
2486
|
+
}
|
|
2487
|
+
let beforeL = prev == 1 /* T.L */;
|
|
2488
|
+
let afterL = (end < rTo ? types[end] : outerType) == 1 /* T.L */;
|
|
2489
|
+
let replace = beforeL == afterL ? (beforeL ? 1 /* T.L */ : 2 /* T.R */) : outerType;
|
|
2490
|
+
for (let j = end, jI = iI, fromJ = jI ? isolates[jI - 1].to : rFrom; j > i;) {
|
|
2491
|
+
if (j == fromJ) {
|
|
2492
|
+
j = isolates[--jI].from;
|
|
2493
|
+
fromJ = jI ? isolates[jI - 1].to : rFrom;
|
|
2494
|
+
}
|
|
2495
|
+
types[--j] = replace;
|
|
2496
|
+
}
|
|
2497
|
+
i = end;
|
|
2375
2498
|
}
|
|
2376
2499
|
else {
|
|
2377
|
-
|
|
2378
|
-
|
|
2379
|
-
BracketStack[sI++] = context;
|
|
2500
|
+
prev = type;
|
|
2501
|
+
i++;
|
|
2380
2502
|
}
|
|
2381
2503
|
}
|
|
2382
|
-
|
|
2383
|
-
|
|
2384
|
-
|
|
2385
|
-
|
|
2386
|
-
|
|
2387
|
-
|
|
2504
|
+
}
|
|
2505
|
+
}
|
|
2506
|
+
// Find the contiguous ranges of character types in a given range, and
|
|
2507
|
+
// emit spans for them. Flip the order of the spans as appropriate
|
|
2508
|
+
// based on the level, and call through to compute the spans for
|
|
2509
|
+
// isolates at the proper point.
|
|
2510
|
+
function emitSpans(line, from, to, level, baseLevel, isolates, order) {
|
|
2511
|
+
let ourType = level % 2 ? 2 /* T.R */ : 1 /* T.L */;
|
|
2512
|
+
if ((level % 2) == (baseLevel % 2)) { // Same dir as base direction, don't flip
|
|
2513
|
+
for (let iCh = from, iI = 0; iCh < to;) {
|
|
2514
|
+
// Scan a section of characters in direction ourType, unless
|
|
2515
|
+
// there's another type of char right after iCh, in which case
|
|
2516
|
+
// we scan a section of other characters (which, if ourType ==
|
|
2517
|
+
// T.L, may contain both T.R and T.AN chars).
|
|
2518
|
+
let sameDir = true, isNum = false;
|
|
2519
|
+
if (iI == isolates.length || iCh < isolates[iI].from) {
|
|
2520
|
+
let next = types[iCh];
|
|
2521
|
+
if (next != ourType) {
|
|
2522
|
+
sameDir = false;
|
|
2523
|
+
isNum = next == 16 /* T.AN */;
|
|
2524
|
+
}
|
|
2525
|
+
}
|
|
2526
|
+
// Holds an array of isolates to pass to a recursive call if we
|
|
2527
|
+
// must recurse (to distinguish T.AN inside an RTL section in
|
|
2528
|
+
// LTR text), null if we can emit directly
|
|
2529
|
+
let recurse = !sameDir && ourType == 1 /* T.L */ ? [] : null;
|
|
2530
|
+
let localLevel = sameDir ? level : level + 1;
|
|
2531
|
+
let iScan = iCh;
|
|
2532
|
+
run: for (;;) {
|
|
2533
|
+
if (iI < isolates.length && iScan == isolates[iI].from) {
|
|
2534
|
+
if (isNum)
|
|
2535
|
+
break run;
|
|
2536
|
+
let iso = isolates[iI];
|
|
2537
|
+
// Scan ahead to verify that there is another char in this dir after the isolate(s)
|
|
2538
|
+
if (!sameDir)
|
|
2539
|
+
for (let upto = iso.to, jI = iI + 1;;) {
|
|
2540
|
+
if (upto == to)
|
|
2541
|
+
break run;
|
|
2542
|
+
if (jI < isolates.length && isolates[jI].from == upto)
|
|
2543
|
+
upto = isolates[jI++].to;
|
|
2544
|
+
else if (types[upto] == ourType)
|
|
2545
|
+
break run;
|
|
2546
|
+
else
|
|
2547
|
+
break;
|
|
2548
|
+
}
|
|
2549
|
+
iI++;
|
|
2550
|
+
if (recurse) {
|
|
2551
|
+
recurse.push(iso);
|
|
2552
|
+
}
|
|
2553
|
+
else {
|
|
2554
|
+
if (iso.from > iCh)
|
|
2555
|
+
order.push(new BidiSpan(iCh, iso.from, localLevel));
|
|
2556
|
+
let dirSwap = (iso.direction == LTR) != !(localLevel % 2);
|
|
2557
|
+
computeSectionOrder(line, dirSwap ? level + 1 : level, baseLevel, iso.inner, iso.from, iso.to, order);
|
|
2558
|
+
iCh = iso.to;
|
|
2559
|
+
}
|
|
2560
|
+
iScan = iso.to;
|
|
2561
|
+
}
|
|
2562
|
+
else if (iScan == to || (sameDir ? types[iScan] != ourType : types[iScan] == ourType)) {
|
|
2388
2563
|
break;
|
|
2389
|
-
if (embed) {
|
|
2390
|
-
BracketStack[sJ + 2] |= 2 /* EmbedInside */;
|
|
2391
2564
|
}
|
|
2392
2565
|
else {
|
|
2393
|
-
|
|
2394
|
-
break;
|
|
2395
|
-
BracketStack[sJ + 2] |= 4 /* OppositeInside */;
|
|
2566
|
+
iScan++;
|
|
2396
2567
|
}
|
|
2397
2568
|
}
|
|
2569
|
+
if (recurse)
|
|
2570
|
+
emitSpans(line, iCh, iScan, level + 1, baseLevel, recurse, order);
|
|
2571
|
+
else if (iCh < iScan)
|
|
2572
|
+
order.push(new BidiSpan(iCh, iScan, localLevel));
|
|
2573
|
+
iCh = iScan;
|
|
2398
2574
|
}
|
|
2399
2575
|
}
|
|
2400
|
-
|
|
2401
|
-
|
|
2402
|
-
|
|
2403
|
-
|
|
2404
|
-
|
|
2405
|
-
|
|
2406
|
-
|
|
2407
|
-
|
|
2408
|
-
|
|
2409
|
-
|
|
2410
|
-
while (end < len && types[end] == 256 /* NI */)
|
|
2411
|
-
end++;
|
|
2412
|
-
let beforeL = (i ? types[i - 1] : outerType) == 1 /* L */;
|
|
2413
|
-
let afterL = (end < len ? types[end] : outerType) == 1 /* L */;
|
|
2414
|
-
let replace = beforeL == afterL ? (beforeL ? 1 /* L */ : 2 /* R */) : outerType;
|
|
2415
|
-
for (let j = i; j < end; j++)
|
|
2416
|
-
types[j] = replace;
|
|
2417
|
-
i = end - 1;
|
|
2418
|
-
}
|
|
2419
|
-
}
|
|
2420
|
-
// Here we depart from the documented algorithm, in order to avoid
|
|
2421
|
-
// building up an actual levels array. Since there are only three
|
|
2422
|
-
// levels (0, 1, 2) in an implementation that doesn't take
|
|
2423
|
-
// explicit embedding into account, we can build up the order on
|
|
2424
|
-
// the fly, without following the level-based algorithm.
|
|
2425
|
-
let order = [];
|
|
2426
|
-
if (outerType == 1 /* L */) {
|
|
2427
|
-
for (let i = 0; i < len;) {
|
|
2428
|
-
let start = i, rtl = types[i++] != 1 /* L */;
|
|
2429
|
-
while (i < len && rtl == (types[i] != 1 /* L */))
|
|
2430
|
-
i++;
|
|
2431
|
-
if (rtl) {
|
|
2432
|
-
for (let j = i; j > start;) {
|
|
2433
|
-
let end = j, l = types[--j] != 2 /* R */;
|
|
2434
|
-
while (j > start && l == (types[j - 1] != 2 /* R */))
|
|
2435
|
-
j--;
|
|
2436
|
-
order.push(new BidiSpan(j, end, l ? 2 : 1));
|
|
2576
|
+
else {
|
|
2577
|
+
// Iterate in reverse to flip the span order. Same code again, but
|
|
2578
|
+
// going from the back of the section to the front
|
|
2579
|
+
for (let iCh = to, iI = isolates.length; iCh > from;) {
|
|
2580
|
+
let sameDir = true, isNum = false;
|
|
2581
|
+
if (!iI || iCh > isolates[iI - 1].to) {
|
|
2582
|
+
let next = types[iCh - 1];
|
|
2583
|
+
if (next != ourType) {
|
|
2584
|
+
sameDir = false;
|
|
2585
|
+
isNum = next == 16 /* T.AN */;
|
|
2437
2586
|
}
|
|
2438
2587
|
}
|
|
2439
|
-
|
|
2440
|
-
|
|
2588
|
+
let recurse = !sameDir && ourType == 1 /* T.L */ ? [] : null;
|
|
2589
|
+
let localLevel = sameDir ? level : level + 1;
|
|
2590
|
+
let iScan = iCh;
|
|
2591
|
+
run: for (;;) {
|
|
2592
|
+
if (iI && iScan == isolates[iI - 1].to) {
|
|
2593
|
+
if (isNum)
|
|
2594
|
+
break run;
|
|
2595
|
+
let iso = isolates[--iI];
|
|
2596
|
+
// Scan ahead to verify that there is another char in this dir after the isolate(s)
|
|
2597
|
+
if (!sameDir)
|
|
2598
|
+
for (let upto = iso.from, jI = iI;;) {
|
|
2599
|
+
if (upto == from)
|
|
2600
|
+
break run;
|
|
2601
|
+
if (jI && isolates[jI - 1].to == upto)
|
|
2602
|
+
upto = isolates[--jI].from;
|
|
2603
|
+
else if (types[upto - 1] == ourType)
|
|
2604
|
+
break run;
|
|
2605
|
+
else
|
|
2606
|
+
break;
|
|
2607
|
+
}
|
|
2608
|
+
if (recurse) {
|
|
2609
|
+
recurse.push(iso);
|
|
2610
|
+
}
|
|
2611
|
+
else {
|
|
2612
|
+
if (iso.to < iCh)
|
|
2613
|
+
order.push(new BidiSpan(iso.to, iCh, localLevel));
|
|
2614
|
+
let dirSwap = (iso.direction == LTR) != !(localLevel % 2);
|
|
2615
|
+
computeSectionOrder(line, dirSwap ? level + 1 : level, baseLevel, iso.inner, iso.from, iso.to, order);
|
|
2616
|
+
iCh = iso.from;
|
|
2617
|
+
}
|
|
2618
|
+
iScan = iso.from;
|
|
2619
|
+
}
|
|
2620
|
+
else if (iScan == from || (sameDir ? types[iScan - 1] != ourType : types[iScan - 1] == ourType)) {
|
|
2621
|
+
break;
|
|
2622
|
+
}
|
|
2623
|
+
else {
|
|
2624
|
+
iScan--;
|
|
2625
|
+
}
|
|
2441
2626
|
}
|
|
2627
|
+
if (recurse)
|
|
2628
|
+
emitSpans(line, iScan, iCh, level + 1, baseLevel, recurse, order);
|
|
2629
|
+
else if (iScan < iCh)
|
|
2630
|
+
order.push(new BidiSpan(iScan, iCh, localLevel));
|
|
2631
|
+
iCh = iScan;
|
|
2442
2632
|
}
|
|
2443
2633
|
}
|
|
2444
|
-
|
|
2445
|
-
|
|
2446
|
-
|
|
2447
|
-
|
|
2448
|
-
|
|
2449
|
-
|
|
2450
|
-
|
|
2451
|
-
|
|
2634
|
+
}
|
|
2635
|
+
function computeSectionOrder(line, level, baseLevel, isolates, from, to, order) {
|
|
2636
|
+
let outerType = (level % 2 ? 2 /* T.R */ : 1 /* T.L */);
|
|
2637
|
+
computeCharTypes(line, from, to, isolates, outerType);
|
|
2638
|
+
processBracketPairs(line, from, to, isolates, outerType);
|
|
2639
|
+
processNeutrals(from, to, isolates, outerType);
|
|
2640
|
+
emitSpans(line, from, to, level, baseLevel, isolates, order);
|
|
2641
|
+
}
|
|
2642
|
+
function computeOrder(line, direction, isolates) {
|
|
2643
|
+
if (!line)
|
|
2644
|
+
return [new BidiSpan(0, 0, direction == RTL ? 1 : 0)];
|
|
2645
|
+
if (direction == LTR && !isolates.length && !BidiRE.test(line))
|
|
2646
|
+
return trivialOrder(line.length);
|
|
2647
|
+
if (isolates.length)
|
|
2648
|
+
while (line.length > types.length)
|
|
2649
|
+
types[types.length] = 256 /* T.NI */; // Make sure types array has no gaps
|
|
2650
|
+
let order = [], level = direction == LTR ? 0 : 1;
|
|
2651
|
+
computeSectionOrder(line, level, level, isolates, 0, line.length, order);
|
|
2452
2652
|
return order;
|
|
2453
2653
|
}
|
|
2454
2654
|
function trivialOrder(length) {
|
|
@@ -2497,6 +2697,7 @@ function moveVisually(line, order, dir, start, forward) {
|
|
|
2497
2697
|
}
|
|
2498
2698
|
|
|
2499
2699
|
class DocView extends ContentView {
|
|
2700
|
+
get length() { return this.view.state.doc.length; }
|
|
2500
2701
|
constructor(view) {
|
|
2501
2702
|
super();
|
|
2502
2703
|
this.view = view;
|
|
@@ -2528,7 +2729,6 @@ class DocView extends ContentView {
|
|
|
2528
2729
|
this.updateDeco();
|
|
2529
2730
|
this.updateInner([new ChangedRange(0, 0, 0, view.state.doc.length)], 0, null);
|
|
2530
2731
|
}
|
|
2531
|
-
get length() { return this.view.state.doc.length; }
|
|
2532
2732
|
// Update the document view to a given state.
|
|
2533
2733
|
update(update) {
|
|
2534
2734
|
let changedRanges = update.changedRanges;
|
|
@@ -2560,7 +2760,7 @@ class DocView extends ContentView {
|
|
|
2560
2760
|
let prevDeco = this.decorations, deco = this.updateDeco();
|
|
2561
2761
|
let decoDiff = findChangedDeco(prevDeco, deco, update.changes);
|
|
2562
2762
|
changedRanges = ChangedRange.extendWithRanges(changedRanges, decoDiff);
|
|
2563
|
-
if (!(this.flags & 7 /* Dirty */) && changedRanges.length == 0) {
|
|
2763
|
+
if (!(this.flags & 7 /* ViewFlag.Dirty */) && changedRanges.length == 0) {
|
|
2564
2764
|
return false;
|
|
2565
2765
|
}
|
|
2566
2766
|
else {
|
|
@@ -2589,12 +2789,12 @@ class DocView extends ContentView {
|
|
|
2589
2789
|
// to detect that situation.
|
|
2590
2790
|
let track = browser.chrome || browser.ios ? { node: observer.selectionRange.focusNode, written: false } : undefined;
|
|
2591
2791
|
this.sync(this.view, track);
|
|
2592
|
-
this.flags &= ~7 /* Dirty */;
|
|
2792
|
+
this.flags &= ~7 /* ViewFlag.Dirty */;
|
|
2593
2793
|
if (track && (track.written || observer.selectionRange.focusNode != track.node))
|
|
2594
2794
|
this.forceSelection = true;
|
|
2595
2795
|
this.dom.style.height = "";
|
|
2596
2796
|
});
|
|
2597
|
-
this.markedForComposition.forEach(cView => cView.flags &= ~8 /* Composition */);
|
|
2797
|
+
this.markedForComposition.forEach(cView => cView.flags &= ~8 /* ViewFlag.Composition */);
|
|
2598
2798
|
let gaps = [];
|
|
2599
2799
|
if (this.view.viewport.from || this.view.viewport.to < this.view.state.doc.length)
|
|
2600
2800
|
for (let child of this.children)
|
|
@@ -2644,7 +2844,7 @@ class DocView extends ContentView {
|
|
|
2644
2844
|
}
|
|
2645
2845
|
compositionView(composition) {
|
|
2646
2846
|
let cur = new TextView(composition.text.nodeValue);
|
|
2647
|
-
cur.flags |= 8 /* Composition */;
|
|
2847
|
+
cur.flags |= 8 /* ViewFlag.Composition */;
|
|
2648
2848
|
for (let { deco } of composition.marks)
|
|
2649
2849
|
cur = new MarkView(deco, [cur], cur.length);
|
|
2650
2850
|
let line = new LineView;
|
|
@@ -2653,7 +2853,7 @@ class DocView extends ContentView {
|
|
|
2653
2853
|
}
|
|
2654
2854
|
fixCompositionDOM(composition) {
|
|
2655
2855
|
let fix = (dom, cView) => {
|
|
2656
|
-
cView.flags |= 8 /* Composition */;
|
|
2856
|
+
cView.flags |= 8 /* ViewFlag.Composition */;
|
|
2657
2857
|
this.markedForComposition.add(cView);
|
|
2658
2858
|
let prev = ContentView.get(dom);
|
|
2659
2859
|
if (prev != cView) {
|
|
@@ -2715,15 +2915,15 @@ class DocView extends ContentView {
|
|
|
2715
2915
|
// Work around https://bugzilla.mozilla.org/show_bug.cgi?id=1612076
|
|
2716
2916
|
if (browser.gecko) {
|
|
2717
2917
|
let nextTo = nextToUneditable(anchor.node, anchor.offset);
|
|
2718
|
-
if (nextTo && nextTo != (1 /* Before */ | 2 /* After */)) {
|
|
2719
|
-
let text = nearbyTextNode(anchor.node, anchor.offset, nextTo == 1 /* Before */ ? 1 : -1);
|
|
2918
|
+
if (nextTo && nextTo != (1 /* NextTo.Before */ | 2 /* NextTo.After */)) {
|
|
2919
|
+
let text = nearbyTextNode(anchor.node, anchor.offset, nextTo == 1 /* NextTo.Before */ ? 1 : -1);
|
|
2720
2920
|
if (text)
|
|
2721
|
-
anchor = new DOMPos(text, nextTo == 1 /* Before */ ? 0 : text.nodeValue.length);
|
|
2921
|
+
anchor = new DOMPos(text, nextTo == 1 /* NextTo.Before */ ? 0 : text.nodeValue.length);
|
|
2722
2922
|
}
|
|
2723
2923
|
}
|
|
2724
2924
|
rawSel.collapse(anchor.node, anchor.offset);
|
|
2725
|
-
if (main.bidiLevel != null && domSel.
|
|
2726
|
-
domSel.
|
|
2925
|
+
if (main.bidiLevel != null && domSel.caretBidiLevel != null)
|
|
2926
|
+
domSel.caretBidiLevel = main.bidiLevel;
|
|
2727
2927
|
}
|
|
2728
2928
|
else if (rawSel.extend) {
|
|
2729
2929
|
// Selection.extend can be used to create an 'inverted' selection
|
|
@@ -2984,7 +3184,7 @@ class BlockGapWidget extends WidgetType {
|
|
|
2984
3184
|
}
|
|
2985
3185
|
get estimatedHeight() { return this.height; }
|
|
2986
3186
|
}
|
|
2987
|
-
function findCompositionNode(view) {
|
|
3187
|
+
function findCompositionNode(view, dLen) {
|
|
2988
3188
|
let sel = view.observer.selectionRange;
|
|
2989
3189
|
let textNode = sel.focusNode && nearbyTextNode(sel.focusNode, sel.focusOffset, 0);
|
|
2990
3190
|
if (!textNode)
|
|
@@ -2996,10 +3196,12 @@ function findCompositionNode(view) {
|
|
|
2996
3196
|
to = from + cView.length;
|
|
2997
3197
|
}
|
|
2998
3198
|
else {
|
|
3199
|
+
let oldLen = Math.max(0, textNode.nodeValue.length - dLen);
|
|
2999
3200
|
up: for (let offset = 0, node = textNode;;) {
|
|
3000
3201
|
for (let sibling = node.previousSibling, cView; sibling; sibling = sibling.previousSibling) {
|
|
3001
3202
|
if (cView = ContentView.get(sibling)) {
|
|
3002
|
-
|
|
3203
|
+
to = cView.posAtEnd + offset;
|
|
3204
|
+
from = Math.max(0, to - oldLen);
|
|
3003
3205
|
break up;
|
|
3004
3206
|
}
|
|
3005
3207
|
let reader = new DOMReader([], view.state);
|
|
@@ -3013,15 +3215,16 @@ function findCompositionNode(view) {
|
|
|
3013
3215
|
return null;
|
|
3014
3216
|
let parentView = ContentView.get(node);
|
|
3015
3217
|
if (parentView) {
|
|
3016
|
-
from =
|
|
3218
|
+
from = parentView.posAtStart + offset;
|
|
3219
|
+
to = from + oldLen;
|
|
3017
3220
|
break;
|
|
3018
3221
|
}
|
|
3019
3222
|
}
|
|
3020
3223
|
}
|
|
3021
|
-
return { from, to, node: textNode };
|
|
3224
|
+
return { from, to: to, node: textNode };
|
|
3022
3225
|
}
|
|
3023
3226
|
function findCompositionRange(view, changes) {
|
|
3024
|
-
let found = findCompositionNode(view);
|
|
3227
|
+
let found = findCompositionNode(view, changes.newLength - changes.length);
|
|
3025
3228
|
if (!found)
|
|
3026
3229
|
return null;
|
|
3027
3230
|
let { from: fromA, to: toA, node: textNode } = found;
|
|
@@ -3095,16 +3298,16 @@ function nearbyTextNode(startNode, startOffset, side) {
|
|
|
3095
3298
|
function nextToUneditable(node, offset) {
|
|
3096
3299
|
if (node.nodeType != 1)
|
|
3097
3300
|
return 0;
|
|
3098
|
-
return (offset && node.childNodes[offset - 1].contentEditable == "false" ? 1 /* Before */ : 0) |
|
|
3099
|
-
(offset < node.childNodes.length && node.childNodes[offset].contentEditable == "false" ? 2 /* After */ : 0);
|
|
3301
|
+
return (offset && node.childNodes[offset - 1].contentEditable == "false" ? 1 /* NextTo.Before */ : 0) |
|
|
3302
|
+
(offset < node.childNodes.length && node.childNodes[offset].contentEditable == "false" ? 2 /* NextTo.After */ : 0);
|
|
3100
3303
|
}
|
|
3101
|
-
|
|
3304
|
+
let DecorationComparator$1 = class DecorationComparator {
|
|
3102
3305
|
constructor() {
|
|
3103
3306
|
this.changes = [];
|
|
3104
3307
|
}
|
|
3105
3308
|
compareRange(from, to) { addRange(from, to, this.changes); }
|
|
3106
3309
|
comparePoint(from, to) { addRange(from, to, this.changes); }
|
|
3107
|
-
}
|
|
3310
|
+
};
|
|
3108
3311
|
function findChangedDeco(a, b, diff) {
|
|
3109
3312
|
let comp = new DecorationComparator$1;
|
|
3110
3313
|
state.RangeSet.compare(a, b, diff, comp);
|
|
@@ -3486,6 +3689,10 @@ function skipAtoms(view, oldPos, pos) {
|
|
|
3486
3689
|
|
|
3487
3690
|
// This will also be where dragging info and such goes
|
|
3488
3691
|
class InputState {
|
|
3692
|
+
setSelectionOrigin(origin) {
|
|
3693
|
+
this.lastSelectionOrigin = origin;
|
|
3694
|
+
this.lastSelectionTime = Date.now();
|
|
3695
|
+
}
|
|
3489
3696
|
constructor(view) {
|
|
3490
3697
|
this.lastKeyCode = 0;
|
|
3491
3698
|
this.lastKeyTime = 0;
|
|
@@ -3581,10 +3788,8 @@ class InputState {
|
|
|
3581
3788
|
// issue where the composition vanishes when you press enter.
|
|
3582
3789
|
if (browser.safari)
|
|
3583
3790
|
view.contentDOM.addEventListener("input", () => null);
|
|
3584
|
-
|
|
3585
|
-
|
|
3586
|
-
this.lastSelectionOrigin = origin;
|
|
3587
|
-
this.lastSelectionTime = Date.now();
|
|
3791
|
+
if (browser.gecko)
|
|
3792
|
+
firefoxCopyCutHack(view.contentDOM.ownerDocument);
|
|
3588
3793
|
}
|
|
3589
3794
|
ensureHandlers(view, plugins) {
|
|
3590
3795
|
var _a;
|
|
@@ -4290,6 +4495,18 @@ handlers.beforeinput = (view, event) => {
|
|
|
4290
4495
|
}
|
|
4291
4496
|
}
|
|
4292
4497
|
};
|
|
4498
|
+
const appliedFirefoxHack = new Set;
|
|
4499
|
+
// In Firefox, when cut/copy handlers are added to the document, that
|
|
4500
|
+
// somehow avoids a bug where those events aren't fired when the
|
|
4501
|
+
// selection is empty. See https://github.com/codemirror/dev/issues/1082
|
|
4502
|
+
// and https://bugzilla.mozilla.org/show_bug.cgi?id=995961
|
|
4503
|
+
function firefoxCopyCutHack(doc) {
|
|
4504
|
+
if (!appliedFirefoxHack.has(doc)) {
|
|
4505
|
+
appliedFirefoxHack.add(doc);
|
|
4506
|
+
doc.addEventListener("copy", () => { });
|
|
4507
|
+
doc.addEventListener("cut", () => { });
|
|
4508
|
+
}
|
|
4509
|
+
}
|
|
4293
4510
|
|
|
4294
4511
|
const wrappingWhiteSpace = ["pre-wrap", "normal", "pre-line", "break-spaces"];
|
|
4295
4512
|
class HeightOracle {
|
|
@@ -4454,13 +4671,13 @@ const Epsilon = 1e-3;
|
|
|
4454
4671
|
class HeightMap {
|
|
4455
4672
|
constructor(length, // The number of characters covered
|
|
4456
4673
|
height, // Height of this part of the document
|
|
4457
|
-
flags = 2 /* Outdated */) {
|
|
4674
|
+
flags = 2 /* Flag.Outdated */) {
|
|
4458
4675
|
this.length = length;
|
|
4459
4676
|
this.height = height;
|
|
4460
4677
|
this.flags = flags;
|
|
4461
4678
|
}
|
|
4462
|
-
get outdated() { return (this.flags & 2 /* Outdated */) > 0; }
|
|
4463
|
-
set outdated(value) { this.flags = (value ? 2 /* Outdated */ : 0) | (this.flags & ~2 /* Outdated */); }
|
|
4679
|
+
get outdated() { return (this.flags & 2 /* Flag.Outdated */) > 0; }
|
|
4680
|
+
set outdated(value) { this.flags = (value ? 2 /* Flag.Outdated */ : 0) | (this.flags & ~2 /* Flag.Outdated */); }
|
|
4464
4681
|
setHeight(oracle, height) {
|
|
4465
4682
|
if (this.height != height) {
|
|
4466
4683
|
if (Math.abs(this.height - height) > Epsilon)
|
|
@@ -4591,7 +4808,7 @@ class HeightMapText extends HeightMapBlock {
|
|
|
4591
4808
|
}
|
|
4592
4809
|
replace(_from, _to, nodes) {
|
|
4593
4810
|
let node = nodes[0];
|
|
4594
|
-
if (nodes.length == 1 && (node instanceof HeightMapText || node instanceof HeightMapGap && (node.flags & 4 /* SingleLine */)) &&
|
|
4811
|
+
if (nodes.length == 1 && (node instanceof HeightMapText || node instanceof HeightMapGap && (node.flags & 4 /* Flag.SingleLine */)) &&
|
|
4595
4812
|
Math.abs(this.length - node.length) < 10) {
|
|
4596
4813
|
if (node instanceof HeightMapGap)
|
|
4597
4814
|
node = new HeightMapText(node.length, this.height);
|
|
@@ -4744,12 +4961,12 @@ class HeightMapGap extends HeightMap {
|
|
|
4744
4961
|
}
|
|
4745
4962
|
class HeightMapBranch extends HeightMap {
|
|
4746
4963
|
constructor(left, brk, right) {
|
|
4747
|
-
super(left.length + brk + right.length, left.height + right.height, brk | (left.outdated || right.outdated ? 2 /* Outdated */ : 0));
|
|
4964
|
+
super(left.length + brk + right.length, left.height + right.height, brk | (left.outdated || right.outdated ? 2 /* Flag.Outdated */ : 0));
|
|
4748
4965
|
this.left = left;
|
|
4749
4966
|
this.right = right;
|
|
4750
4967
|
this.size = left.size + right.size;
|
|
4751
4968
|
}
|
|
4752
|
-
get break() { return this.flags & 1 /* Break */; }
|
|
4969
|
+
get break() { return this.flags & 1 /* Flag.Break */; }
|
|
4753
4970
|
blockAt(height, oracle, top, offset) {
|
|
4754
4971
|
let mid = top + this.left.height;
|
|
4755
4972
|
return height < mid ? this.left.blockAt(height, oracle, top, offset)
|
|
@@ -4934,7 +5151,7 @@ class NodeBuilder {
|
|
|
4934
5151
|
blankContent(from, to) {
|
|
4935
5152
|
let gap = new HeightMapGap(to - from);
|
|
4936
5153
|
if (this.oracle.doc.lineAt(from).to == to)
|
|
4937
|
-
gap.flags |= 4 /* SingleLine */;
|
|
5154
|
+
gap.flags |= 4 /* Flag.SingleLine */;
|
|
4938
5155
|
return gap;
|
|
4939
5156
|
}
|
|
4940
5157
|
ensureLine() {
|
|
@@ -5144,7 +5361,7 @@ class ViewState {
|
|
|
5144
5361
|
}
|
|
5145
5362
|
}
|
|
5146
5363
|
this.viewports = viewports.sort((a, b) => a.from - b.from);
|
|
5147
|
-
this.scaler = this.heightMap.height <= 7000000 /* MaxDOMHeight */ ? IdScaler :
|
|
5364
|
+
this.scaler = this.heightMap.height <= 7000000 /* VP.MaxDOMHeight */ ? IdScaler :
|
|
5148
5365
|
new BigScaler(this.heightOracle, this.heightMap, this.viewports);
|
|
5149
5366
|
}
|
|
5150
5367
|
updateViewportLines() {
|
|
@@ -5163,7 +5380,7 @@ class ViewState {
|
|
|
5163
5380
|
let scrollAnchor = this.scrolledToBottom ? null : this.scrollAnchorAt(this.scrollTop);
|
|
5164
5381
|
this.heightMap = this.heightMap.applyChanges(this.stateDeco, update.startState.doc, this.heightOracle.setDoc(this.state.doc), heightChanges);
|
|
5165
5382
|
if (this.heightMap.height != prevHeight)
|
|
5166
|
-
update.flags |= 2 /* Height */;
|
|
5383
|
+
update.flags |= 2 /* UpdateFlag.Height */;
|
|
5167
5384
|
if (scrollAnchor) {
|
|
5168
5385
|
this.scrollAnchorPos = update.changes.mapPos(scrollAnchor.from, -1);
|
|
5169
5386
|
this.scrollAnchorHeight = scrollAnchor.top;
|
|
@@ -5176,13 +5393,13 @@ class ViewState {
|
|
|
5176
5393
|
if (scrollTarget && (scrollTarget.range.head < viewport.from || scrollTarget.range.head > viewport.to) ||
|
|
5177
5394
|
!this.viewportIsAppropriate(viewport))
|
|
5178
5395
|
viewport = this.getViewport(0, scrollTarget);
|
|
5179
|
-
let updateLines = !update.changes.empty || (update.flags & 2 /* Height */) ||
|
|
5396
|
+
let updateLines = !update.changes.empty || (update.flags & 2 /* UpdateFlag.Height */) ||
|
|
5180
5397
|
viewport.from != this.viewport.from || viewport.to != this.viewport.to;
|
|
5181
5398
|
this.viewport = viewport;
|
|
5182
5399
|
this.updateForViewport();
|
|
5183
5400
|
if (updateLines)
|
|
5184
5401
|
this.updateViewportLines();
|
|
5185
|
-
if (this.lineGaps.length || this.viewport.to - this.viewport.from > (2000 /* Margin */ << 1))
|
|
5402
|
+
if (this.lineGaps.length || this.viewport.to - this.viewport.from > (2000 /* LG.Margin */ << 1))
|
|
5186
5403
|
this.updateLineGaps(this.ensureLineGaps(this.mapLineGaps(this.lineGaps, update.changes)));
|
|
5187
5404
|
update.flags |= this.computeVisibleRanges();
|
|
5188
5405
|
if (scrollTarget)
|
|
@@ -5208,13 +5425,13 @@ class ViewState {
|
|
|
5208
5425
|
if (this.paddingTop != paddingTop || this.paddingBottom != paddingBottom) {
|
|
5209
5426
|
this.paddingTop = paddingTop;
|
|
5210
5427
|
this.paddingBottom = paddingBottom;
|
|
5211
|
-
result |= 8 /* Geometry */ | 2 /* Height */;
|
|
5428
|
+
result |= 8 /* UpdateFlag.Geometry */ | 2 /* UpdateFlag.Height */;
|
|
5212
5429
|
}
|
|
5213
5430
|
if (this.editorWidth != view.scrollDOM.clientWidth) {
|
|
5214
5431
|
if (oracle.lineWrapping)
|
|
5215
5432
|
measureContent = true;
|
|
5216
5433
|
this.editorWidth = view.scrollDOM.clientWidth;
|
|
5217
|
-
result |= 8 /* Geometry */;
|
|
5434
|
+
result |= 8 /* UpdateFlag.Geometry */;
|
|
5218
5435
|
}
|
|
5219
5436
|
if (this.scrollTop != view.scrollDOM.scrollTop) {
|
|
5220
5437
|
this.scrollAnchorHeight = -1;
|
|
@@ -5237,7 +5454,7 @@ class ViewState {
|
|
|
5237
5454
|
if (this.contentDOMWidth != contentWidth || this.editorHeight != view.scrollDOM.clientHeight) {
|
|
5238
5455
|
this.contentDOMWidth = domRect.width;
|
|
5239
5456
|
this.editorHeight = view.scrollDOM.clientHeight;
|
|
5240
|
-
result |= 8 /* Geometry */;
|
|
5457
|
+
result |= 8 /* UpdateFlag.Geometry */;
|
|
5241
5458
|
}
|
|
5242
5459
|
if (measureContent) {
|
|
5243
5460
|
let lineHeights = view.docView.measureVisibleLineHeights(this.viewport);
|
|
@@ -5248,7 +5465,7 @@ class ViewState {
|
|
|
5248
5465
|
refresh = lineHeight > 0 && oracle.refresh(whiteSpace, lineHeight, charWidth, textHeight, contentWidth / charWidth, lineHeights);
|
|
5249
5466
|
if (refresh) {
|
|
5250
5467
|
view.docView.minWidth = 0;
|
|
5251
|
-
result |= 8 /* Geometry */;
|
|
5468
|
+
result |= 8 /* UpdateFlag.Geometry */;
|
|
5252
5469
|
}
|
|
5253
5470
|
}
|
|
5254
5471
|
if (dTop > 0 && dBottom > 0)
|
|
@@ -5261,7 +5478,7 @@ class ViewState {
|
|
|
5261
5478
|
this.heightMap = (refresh ? HeightMap.empty().applyChanges(this.stateDeco, state.Text.empty, this.heightOracle, [new ChangedRange(0, 0, 0, view.state.doc.length)]) : this.heightMap).updateHeight(oracle, 0, refresh, new MeasuredHeights(vp.from, heights));
|
|
5262
5479
|
}
|
|
5263
5480
|
if (oracle.heightChanged)
|
|
5264
|
-
result |= 2 /* Height */;
|
|
5481
|
+
result |= 2 /* UpdateFlag.Height */;
|
|
5265
5482
|
}
|
|
5266
5483
|
let viewportChange = !this.viewportIsAppropriate(this.viewport, bias) ||
|
|
5267
5484
|
this.scrollTarget && (this.scrollTarget.range.head < this.viewport.from ||
|
|
@@ -5269,9 +5486,9 @@ class ViewState {
|
|
|
5269
5486
|
if (viewportChange)
|
|
5270
5487
|
this.viewport = this.getViewport(bias, this.scrollTarget);
|
|
5271
5488
|
this.updateForViewport();
|
|
5272
|
-
if ((result & 2 /* Height */) || viewportChange)
|
|
5489
|
+
if ((result & 2 /* UpdateFlag.Height */) || viewportChange)
|
|
5273
5490
|
this.updateViewportLines();
|
|
5274
|
-
if (this.lineGaps.length || this.viewport.to - this.viewport.from > (2000 /* Margin */ << 1))
|
|
5491
|
+
if (this.lineGaps.length || this.viewport.to - this.viewport.from > (2000 /* LG.Margin */ << 1))
|
|
5275
5492
|
this.updateLineGaps(this.ensureLineGaps(refresh ? [] : this.lineGaps, view));
|
|
5276
5493
|
result |= this.computeVisibleRanges();
|
|
5277
5494
|
if (this.mustEnforceCursorAssoc) {
|
|
@@ -5290,10 +5507,10 @@ class ViewState {
|
|
|
5290
5507
|
// This will divide VP.Margin between the top and the
|
|
5291
5508
|
// bottom, depending on the bias (the change in viewport position
|
|
5292
5509
|
// since the last update). It'll hold a number between 0 and 1
|
|
5293
|
-
let marginTop = 0.5 - Math.max(-0.5, Math.min(0.5, bias / 1000 /* Margin */ / 2));
|
|
5510
|
+
let marginTop = 0.5 - Math.max(-0.5, Math.min(0.5, bias / 1000 /* VP.Margin */ / 2));
|
|
5294
5511
|
let map = this.heightMap, oracle = this.heightOracle;
|
|
5295
5512
|
let { visibleTop, visibleBottom } = this;
|
|
5296
|
-
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);
|
|
5513
|
+
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);
|
|
5297
5514
|
// If scrollTarget is given, make sure the viewport includes that position
|
|
5298
5515
|
if (scrollTarget) {
|
|
5299
5516
|
let { head } = scrollTarget.range;
|
|
@@ -5306,7 +5523,7 @@ class ViewState {
|
|
|
5306
5523
|
topPos = block.top;
|
|
5307
5524
|
else
|
|
5308
5525
|
topPos = block.bottom - viewHeight;
|
|
5309
|
-
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);
|
|
5526
|
+
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);
|
|
5310
5527
|
}
|
|
5311
5528
|
}
|
|
5312
5529
|
return viewport;
|
|
@@ -5323,10 +5540,10 @@ class ViewState {
|
|
|
5323
5540
|
let { top } = this.heightMap.lineAt(from, QueryType.ByPos, this.heightOracle, 0, 0);
|
|
5324
5541
|
let { bottom } = this.heightMap.lineAt(to, QueryType.ByPos, this.heightOracle, 0, 0);
|
|
5325
5542
|
let { visibleTop, visibleBottom } = this;
|
|
5326
|
-
return (from == 0 || top <= visibleTop - Math.max(10 /* MinCoverMargin */, Math.min(-bias, 250 /* MaxCoverMargin */))) &&
|
|
5543
|
+
return (from == 0 || top <= visibleTop - Math.max(10 /* VP.MinCoverMargin */, Math.min(-bias, 250 /* VP.MaxCoverMargin */))) &&
|
|
5327
5544
|
(to == this.state.doc.length ||
|
|
5328
|
-
bottom >= visibleBottom + Math.max(10 /* MinCoverMargin */, Math.min(bias, 250 /* MaxCoverMargin */))) &&
|
|
5329
|
-
(top > visibleTop - 2 * 1000 /* Margin */ && bottom < visibleBottom + 2 * 1000 /* Margin */);
|
|
5545
|
+
bottom >= visibleBottom + Math.max(10 /* VP.MinCoverMargin */, Math.min(bias, 250 /* VP.MaxCoverMargin */))) &&
|
|
5546
|
+
(top > visibleTop - 2 * 1000 /* VP.Margin */ && bottom < visibleBottom + 2 * 1000 /* VP.Margin */);
|
|
5330
5547
|
}
|
|
5331
5548
|
mapLineGaps(gaps, changes) {
|
|
5332
5549
|
if (!gaps.length || changes.empty)
|
|
@@ -5346,7 +5563,7 @@ class ViewState {
|
|
|
5346
5563
|
// the artifacts this might produce from the user.
|
|
5347
5564
|
ensureLineGaps(current, mayMeasure) {
|
|
5348
5565
|
let wrapping = this.heightOracle.lineWrapping;
|
|
5349
|
-
let margin = wrapping ? 10000 /* MarginWrap */ : 2000 /* Margin */, halfMargin = margin >> 1, doubleMargin = margin << 1;
|
|
5566
|
+
let margin = wrapping ? 10000 /* LG.MarginWrap */ : 2000 /* LG.Margin */, halfMargin = margin >> 1, doubleMargin = margin << 1;
|
|
5350
5567
|
// The non-wrapping logic won't work at all in predominantly right-to-left text.
|
|
5351
5568
|
if (this.defaultTextDirection != exports.Direction.LTR && !wrapping)
|
|
5352
5569
|
return [];
|
|
@@ -5359,8 +5576,8 @@ class ViewState {
|
|
|
5359
5576
|
avoid.push(sel.to);
|
|
5360
5577
|
for (let pos of avoid) {
|
|
5361
5578
|
if (pos > from && pos < to) {
|
|
5362
|
-
addGap(from, pos - 10 /* SelectionMargin */, line, structure);
|
|
5363
|
-
addGap(pos + 10 /* SelectionMargin */, to, line, structure);
|
|
5579
|
+
addGap(from, pos - 10 /* LG.SelectionMargin */, line, structure);
|
|
5580
|
+
addGap(pos + 10 /* LG.SelectionMargin */, to, line, structure);
|
|
5364
5581
|
return;
|
|
5365
5582
|
}
|
|
5366
5583
|
}
|
|
@@ -5454,7 +5671,7 @@ class ViewState {
|
|
|
5454
5671
|
let changed = ranges.length != this.visibleRanges.length ||
|
|
5455
5672
|
this.visibleRanges.some((r, i) => r.from != ranges[i].from || r.to != ranges[i].to);
|
|
5456
5673
|
this.visibleRanges = ranges;
|
|
5457
|
-
return changed ? 4 /* Viewport */ : 0;
|
|
5674
|
+
return changed ? 4 /* UpdateFlag.Viewport */ : 0;
|
|
5458
5675
|
}
|
|
5459
5676
|
lineBlockAt(pos) {
|
|
5460
5677
|
return (pos >= this.viewport.from && pos <= this.viewport.to && this.viewportLines.find(b => b.from <= pos && b.to >= pos)) ||
|
|
@@ -5550,7 +5767,7 @@ class BigScaler {
|
|
|
5550
5767
|
vpHeight += bottom - top;
|
|
5551
5768
|
return { from, to, top, bottom, domTop: 0, domBottom: 0 };
|
|
5552
5769
|
});
|
|
5553
|
-
this.scale = (7000000 /* MaxDOMHeight */ - vpHeight) / (heightMap.height - vpHeight);
|
|
5770
|
+
this.scale = (7000000 /* VP.MaxDOMHeight */ - vpHeight) / (heightMap.height - vpHeight);
|
|
5554
5771
|
for (let obj of this.viewports) {
|
|
5555
5772
|
obj.domTop = domBase + (obj.top - base) * this.scale;
|
|
5556
5773
|
domBase = obj.domBottom = obj.domTop + (obj.bottom - obj.top);
|
|
@@ -5933,7 +6150,6 @@ function applyDOMChange(view, domChange) {
|
|
|
5933
6150
|
change = { from: sel.from, to: sel.to, insert: state.Text.of([" "]) };
|
|
5934
6151
|
}
|
|
5935
6152
|
if (change) {
|
|
5936
|
-
let startState = view.state;
|
|
5937
6153
|
if (browser.ios && view.inputState.flushIOSKey(view))
|
|
5938
6154
|
return true;
|
|
5939
6155
|
// Android browsers don't fire reasonable key events for enter,
|
|
@@ -5947,70 +6163,18 @@ function applyDOMChange(view, domChange) {
|
|
|
5947
6163
|
change.insert.length == 1 && change.insert.lines == 2 &&
|
|
5948
6164
|
dispatchKey(view.contentDOM, "Enter", 13)) ||
|
|
5949
6165
|
((change.from == sel.from - 1 && change.to == sel.to && change.insert.length == 0 ||
|
|
5950
|
-
lastKey == 8 && change.insert.length < change.to - change.from) &&
|
|
6166
|
+
lastKey == 8 && change.insert.length < change.to - change.from && change.to > sel.head) &&
|
|
5951
6167
|
dispatchKey(view.contentDOM, "Backspace", 8)) ||
|
|
5952
6168
|
(change.from == sel.from && change.to == sel.to + 1 && change.insert.length == 0 &&
|
|
5953
6169
|
dispatchKey(view.contentDOM, "Delete", 46))))
|
|
5954
6170
|
return true;
|
|
5955
6171
|
let text = change.insert.toString();
|
|
5956
|
-
if (view.state.facet(inputHandler).some(h => h(view, change.from, change.to, text)))
|
|
5957
|
-
return true;
|
|
5958
6172
|
if (view.inputState.composing >= 0)
|
|
5959
6173
|
view.inputState.composing++;
|
|
5960
|
-
let
|
|
5961
|
-
|
|
5962
|
-
|
|
5963
|
-
view.
|
|
5964
|
-
let before = sel.from < change.from ? startState.sliceDoc(sel.from, change.from) : "";
|
|
5965
|
-
let after = sel.to > change.to ? startState.sliceDoc(change.to, sel.to) : "";
|
|
5966
|
-
tr = startState.replaceSelection(view.state.toText(before + change.insert.sliceString(0, undefined, view.state.lineBreak) + after));
|
|
5967
|
-
}
|
|
5968
|
-
else {
|
|
5969
|
-
let changes = startState.changes(change);
|
|
5970
|
-
let mainSel = newSel && newSel.main.to <= changes.newLength ? newSel.main : undefined;
|
|
5971
|
-
// Try to apply a composition change to all cursors
|
|
5972
|
-
if (startState.selection.ranges.length > 1 && view.inputState.composing >= 0 &&
|
|
5973
|
-
change.to <= sel.to && change.to >= sel.to - 10) {
|
|
5974
|
-
let replaced = view.state.sliceDoc(change.from, change.to);
|
|
5975
|
-
let composition = findCompositionNode(view) || view.state.doc.lineAt(sel.head);
|
|
5976
|
-
let offset = sel.to - change.to, size = sel.to - sel.from;
|
|
5977
|
-
tr = startState.changeByRange(range => {
|
|
5978
|
-
if (range.from == sel.from && range.to == sel.to)
|
|
5979
|
-
return { changes, range: mainSel || range.map(changes) };
|
|
5980
|
-
let to = range.to - offset, from = to - replaced.length;
|
|
5981
|
-
if (range.to - range.from != size || view.state.sliceDoc(from, to) != replaced ||
|
|
5982
|
-
// Unfortunately, there's no way to make multiple
|
|
5983
|
-
// changes in the same node work without aborting
|
|
5984
|
-
// composition, so cursors in the composition range are
|
|
5985
|
-
// ignored.
|
|
5986
|
-
composition && range.to >= composition.from && range.from <= composition.to)
|
|
5987
|
-
return { range };
|
|
5988
|
-
let rangeChanges = startState.changes({ from, to, insert: change.insert }), selOff = range.to - sel.to;
|
|
5989
|
-
return {
|
|
5990
|
-
changes: rangeChanges,
|
|
5991
|
-
range: !mainSel ? range.map(rangeChanges) :
|
|
5992
|
-
state.EditorSelection.range(Math.max(0, mainSel.anchor + selOff), Math.max(0, mainSel.head + selOff))
|
|
5993
|
-
};
|
|
5994
|
-
});
|
|
5995
|
-
}
|
|
5996
|
-
else {
|
|
5997
|
-
tr = {
|
|
5998
|
-
changes,
|
|
5999
|
-
selection: mainSel && startState.selection.replaceRange(mainSel)
|
|
6000
|
-
};
|
|
6001
|
-
}
|
|
6002
|
-
}
|
|
6003
|
-
let userEvent = "input.type";
|
|
6004
|
-
if (view.composing ||
|
|
6005
|
-
view.inputState.compositionPendingChange && view.inputState.compositionEndedAt > Date.now() - 50) {
|
|
6006
|
-
view.inputState.compositionPendingChange = false;
|
|
6007
|
-
userEvent += ".compose";
|
|
6008
|
-
if (view.inputState.compositionFirstChange) {
|
|
6009
|
-
userEvent += ".start";
|
|
6010
|
-
view.inputState.compositionFirstChange = false;
|
|
6011
|
-
}
|
|
6012
|
-
}
|
|
6013
|
-
view.dispatch(tr, { scrollIntoView: true, userEvent });
|
|
6174
|
+
let defaultTr;
|
|
6175
|
+
let defaultInsert = () => defaultTr || (defaultTr = applyDefaultInsert(view, change, newSel));
|
|
6176
|
+
if (!view.state.facet(inputHandler).some(h => h(view, change.from, change.to, text, defaultInsert)))
|
|
6177
|
+
view.dispatch(defaultInsert());
|
|
6014
6178
|
return true;
|
|
6015
6179
|
}
|
|
6016
6180
|
else if (newSel && !newSel.main.eq(sel)) {
|
|
@@ -6027,6 +6191,63 @@ function applyDOMChange(view, domChange) {
|
|
|
6027
6191
|
return false;
|
|
6028
6192
|
}
|
|
6029
6193
|
}
|
|
6194
|
+
function applyDefaultInsert(view, change, newSel) {
|
|
6195
|
+
let tr, startState = view.state, sel = startState.selection.main;
|
|
6196
|
+
if (change.from >= sel.from && change.to <= sel.to && change.to - change.from >= (sel.to - sel.from) / 3 &&
|
|
6197
|
+
(!newSel || newSel.main.empty && newSel.main.from == change.from + change.insert.length) &&
|
|
6198
|
+
view.inputState.composing < 0) {
|
|
6199
|
+
let before = sel.from < change.from ? startState.sliceDoc(sel.from, change.from) : "";
|
|
6200
|
+
let after = sel.to > change.to ? startState.sliceDoc(change.to, sel.to) : "";
|
|
6201
|
+
tr = startState.replaceSelection(view.state.toText(before + change.insert.sliceString(0, undefined, view.state.lineBreak) + after));
|
|
6202
|
+
}
|
|
6203
|
+
else {
|
|
6204
|
+
let changes = startState.changes(change);
|
|
6205
|
+
let mainSel = newSel && newSel.main.to <= changes.newLength ? newSel.main : undefined;
|
|
6206
|
+
// Try to apply a composition change to all cursors
|
|
6207
|
+
if (startState.selection.ranges.length > 1 && view.inputState.composing >= 0 &&
|
|
6208
|
+
change.to <= sel.to && change.to >= sel.to - 10) {
|
|
6209
|
+
let replaced = view.state.sliceDoc(change.from, change.to);
|
|
6210
|
+
let composition = findCompositionNode(view, change.insert.length - (change.to - change.from)) ||
|
|
6211
|
+
view.state.doc.lineAt(sel.head);
|
|
6212
|
+
let offset = sel.to - change.to, size = sel.to - sel.from;
|
|
6213
|
+
tr = startState.changeByRange(range => {
|
|
6214
|
+
if (range.from == sel.from && range.to == sel.to)
|
|
6215
|
+
return { changes, range: mainSel || range.map(changes) };
|
|
6216
|
+
let to = range.to - offset, from = to - replaced.length;
|
|
6217
|
+
if (range.to - range.from != size || view.state.sliceDoc(from, to) != replaced ||
|
|
6218
|
+
// Unfortunately, there's no way to make multiple
|
|
6219
|
+
// changes in the same node work without aborting
|
|
6220
|
+
// composition, so cursors in the composition range are
|
|
6221
|
+
// ignored.
|
|
6222
|
+
composition && range.to >= composition.from && range.from <= composition.to)
|
|
6223
|
+
return { range };
|
|
6224
|
+
let rangeChanges = startState.changes({ from, to, insert: change.insert }), selOff = range.to - sel.to;
|
|
6225
|
+
return {
|
|
6226
|
+
changes: rangeChanges,
|
|
6227
|
+
range: !mainSel ? range.map(rangeChanges) :
|
|
6228
|
+
state.EditorSelection.range(Math.max(0, mainSel.anchor + selOff), Math.max(0, mainSel.head + selOff))
|
|
6229
|
+
};
|
|
6230
|
+
});
|
|
6231
|
+
}
|
|
6232
|
+
else {
|
|
6233
|
+
tr = {
|
|
6234
|
+
changes,
|
|
6235
|
+
selection: mainSel && startState.selection.replaceRange(mainSel)
|
|
6236
|
+
};
|
|
6237
|
+
}
|
|
6238
|
+
}
|
|
6239
|
+
let userEvent = "input.type";
|
|
6240
|
+
if (view.composing ||
|
|
6241
|
+
view.inputState.compositionPendingChange && view.inputState.compositionEndedAt > Date.now() - 50) {
|
|
6242
|
+
view.inputState.compositionPendingChange = false;
|
|
6243
|
+
userEvent += ".compose";
|
|
6244
|
+
if (view.inputState.compositionFirstChange) {
|
|
6245
|
+
userEvent += ".start";
|
|
6246
|
+
view.inputState.compositionFirstChange = false;
|
|
6247
|
+
}
|
|
6248
|
+
}
|
|
6249
|
+
return startState.update(tr, { userEvent, scrollIntoView: true });
|
|
6250
|
+
}
|
|
6030
6251
|
function findDiff(a, b, preferredPos, preferredSide) {
|
|
6031
6252
|
let minLen = Math.min(a.length, b.length);
|
|
6032
6253
|
let from = 0;
|
|
@@ -6444,7 +6665,7 @@ class DOMObserver {
|
|
|
6444
6665
|
return null;
|
|
6445
6666
|
cView.markDirty(rec.type == "attributes");
|
|
6446
6667
|
if (rec.type == "attributes")
|
|
6447
|
-
cView.flags |= 4 /* AttrsDirty */;
|
|
6668
|
+
cView.flags |= 4 /* ViewFlag.AttrsDirty */;
|
|
6448
6669
|
if (rec.type == "childList") {
|
|
6449
6670
|
let childBefore = findChild(cView, rec.previousSibling || rec.target.previousSibling, -1);
|
|
6450
6671
|
let childAfter = findChild(cView, rec.nextSibling || rec.target.nextSibling, 1);
|
|
@@ -6552,6 +6773,53 @@ line number gutter. It handles events and dispatches state
|
|
|
6552
6773
|
transactions for editing actions.
|
|
6553
6774
|
*/
|
|
6554
6775
|
class EditorView {
|
|
6776
|
+
/**
|
|
6777
|
+
The current editor state.
|
|
6778
|
+
*/
|
|
6779
|
+
get state() { return this.viewState.state; }
|
|
6780
|
+
/**
|
|
6781
|
+
To be able to display large documents without consuming too much
|
|
6782
|
+
memory or overloading the browser, CodeMirror only draws the
|
|
6783
|
+
code that is visible (plus a margin around it) to the DOM. This
|
|
6784
|
+
property tells you the extent of the current drawn viewport, in
|
|
6785
|
+
document positions.
|
|
6786
|
+
*/
|
|
6787
|
+
get viewport() { return this.viewState.viewport; }
|
|
6788
|
+
/**
|
|
6789
|
+
When there are, for example, large collapsed ranges in the
|
|
6790
|
+
viewport, its size can be a lot bigger than the actual visible
|
|
6791
|
+
content. Thus, if you are doing something like styling the
|
|
6792
|
+
content in the viewport, it is preferable to only do so for
|
|
6793
|
+
these ranges, which are the subset of the viewport that is
|
|
6794
|
+
actually drawn.
|
|
6795
|
+
*/
|
|
6796
|
+
get visibleRanges() { return this.viewState.visibleRanges; }
|
|
6797
|
+
/**
|
|
6798
|
+
Returns false when the editor is entirely scrolled out of view
|
|
6799
|
+
or otherwise hidden.
|
|
6800
|
+
*/
|
|
6801
|
+
get inView() { return this.viewState.inView; }
|
|
6802
|
+
/**
|
|
6803
|
+
Indicates whether the user is currently composing text via
|
|
6804
|
+
[IME](https://en.wikipedia.org/wiki/Input_method), and at least
|
|
6805
|
+
one change has been made in the current composition.
|
|
6806
|
+
*/
|
|
6807
|
+
get composing() { return this.inputState.composing > 0; }
|
|
6808
|
+
/**
|
|
6809
|
+
Indicates whether the user is currently in composing state. Note
|
|
6810
|
+
that on some platforms, like Android, this will be the case a
|
|
6811
|
+
lot, since just putting the cursor on a word starts a
|
|
6812
|
+
composition there.
|
|
6813
|
+
*/
|
|
6814
|
+
get compositionStarted() { return this.inputState.composing >= 0; }
|
|
6815
|
+
/**
|
|
6816
|
+
The document or shadow root that the view lives in.
|
|
6817
|
+
*/
|
|
6818
|
+
get root() { return this._root; }
|
|
6819
|
+
/**
|
|
6820
|
+
@internal
|
|
6821
|
+
*/
|
|
6822
|
+
get win() { return this.dom.ownerDocument.defaultView || window; }
|
|
6555
6823
|
/**
|
|
6556
6824
|
Construct a new view. You'll want to either provide a `parent`
|
|
6557
6825
|
option, or put `view.dom` into your document after creating a
|
|
@@ -6567,7 +6835,7 @@ class EditorView {
|
|
|
6567
6835
|
/**
|
|
6568
6836
|
@internal
|
|
6569
6837
|
*/
|
|
6570
|
-
this.updateState = 2 /* Updating */;
|
|
6838
|
+
this.updateState = 2 /* UpdateState.Updating */;
|
|
6571
6839
|
/**
|
|
6572
6840
|
@internal
|
|
6573
6841
|
*/
|
|
@@ -6587,7 +6855,10 @@ class EditorView {
|
|
|
6587
6855
|
this.dom = document.createElement("div");
|
|
6588
6856
|
this.dom.appendChild(this.announceDOM);
|
|
6589
6857
|
this.dom.appendChild(this.scrollDOM);
|
|
6590
|
-
|
|
6858
|
+
let { dispatch } = config;
|
|
6859
|
+
this.dispatchTransactions = config.dispatchTransactions ||
|
|
6860
|
+
(dispatch && ((trs) => trs.forEach(tr => dispatch(tr, this)))) ||
|
|
6861
|
+
((trs) => this.update(trs));
|
|
6591
6862
|
this.dispatch = this.dispatch.bind(this);
|
|
6592
6863
|
this._root = (config.root || getRoot(config.parent) || document);
|
|
6593
6864
|
this.viewState = new ViewState(config.state || state.EditorState.create(config));
|
|
@@ -6600,62 +6871,16 @@ class EditorView {
|
|
|
6600
6871
|
this.docView = new DocView(this);
|
|
6601
6872
|
this.mountStyles();
|
|
6602
6873
|
this.updateAttrs();
|
|
6603
|
-
this.updateState = 0 /* Idle */;
|
|
6874
|
+
this.updateState = 0 /* UpdateState.Idle */;
|
|
6604
6875
|
this.requestMeasure();
|
|
6605
6876
|
if (config.parent)
|
|
6606
6877
|
config.parent.appendChild(this.dom);
|
|
6607
6878
|
}
|
|
6608
|
-
/**
|
|
6609
|
-
The current editor state.
|
|
6610
|
-
*/
|
|
6611
|
-
get state() { return this.viewState.state; }
|
|
6612
|
-
/**
|
|
6613
|
-
To be able to display large documents without consuming too much
|
|
6614
|
-
memory or overloading the browser, CodeMirror only draws the
|
|
6615
|
-
code that is visible (plus a margin around it) to the DOM. This
|
|
6616
|
-
property tells you the extent of the current drawn viewport, in
|
|
6617
|
-
document positions.
|
|
6618
|
-
*/
|
|
6619
|
-
get viewport() { return this.viewState.viewport; }
|
|
6620
|
-
/**
|
|
6621
|
-
When there are, for example, large collapsed ranges in the
|
|
6622
|
-
viewport, its size can be a lot bigger than the actual visible
|
|
6623
|
-
content. Thus, if you are doing something like styling the
|
|
6624
|
-
content in the viewport, it is preferable to only do so for
|
|
6625
|
-
these ranges, which are the subset of the viewport that is
|
|
6626
|
-
actually drawn.
|
|
6627
|
-
*/
|
|
6628
|
-
get visibleRanges() { return this.viewState.visibleRanges; }
|
|
6629
|
-
/**
|
|
6630
|
-
Returns false when the editor is entirely scrolled out of view
|
|
6631
|
-
or otherwise hidden.
|
|
6632
|
-
*/
|
|
6633
|
-
get inView() { return this.viewState.inView; }
|
|
6634
|
-
/**
|
|
6635
|
-
Indicates whether the user is currently composing text via
|
|
6636
|
-
[IME](https://en.wikipedia.org/wiki/Input_method), and at least
|
|
6637
|
-
one change has been made in the current composition.
|
|
6638
|
-
*/
|
|
6639
|
-
get composing() { return this.inputState.composing > 0; }
|
|
6640
|
-
/**
|
|
6641
|
-
Indicates whether the user is currently in composing state. Note
|
|
6642
|
-
that on some platforms, like Android, this will be the case a
|
|
6643
|
-
lot, since just putting the cursor on a word starts a
|
|
6644
|
-
composition there.
|
|
6645
|
-
*/
|
|
6646
|
-
get compositionStarted() { return this.inputState.composing >= 0; }
|
|
6647
|
-
/**
|
|
6648
|
-
The document or shadow root that the view lives in.
|
|
6649
|
-
*/
|
|
6650
|
-
get root() { return this._root; }
|
|
6651
|
-
/**
|
|
6652
|
-
@internal
|
|
6653
|
-
*/
|
|
6654
|
-
get win() { return this.dom.ownerDocument.defaultView || window; }
|
|
6655
6879
|
dispatch(...input) {
|
|
6656
|
-
let
|
|
6657
|
-
:
|
|
6658
|
-
|
|
6880
|
+
let trs = input.length == 1 && input[0] instanceof state.Transaction ? input
|
|
6881
|
+
: input.length == 1 && Array.isArray(input[0]) ? input[0]
|
|
6882
|
+
: [this.state.update(...input)];
|
|
6883
|
+
this.dispatchTransactions(trs, this);
|
|
6659
6884
|
}
|
|
6660
6885
|
/**
|
|
6661
6886
|
Update the view for the given array of transactions. This will
|
|
@@ -6666,7 +6891,7 @@ class EditorView {
|
|
|
6666
6891
|
as a primitive.
|
|
6667
6892
|
*/
|
|
6668
6893
|
update(transactions) {
|
|
6669
|
-
if (this.updateState != 0 /* Idle */)
|
|
6894
|
+
if (this.updateState != 0 /* UpdateState.Idle */)
|
|
6670
6895
|
throw new Error("Calls to EditorView.update are not allowed while an update is in progress");
|
|
6671
6896
|
let redrawn = false, attrsChanged = false, update;
|
|
6672
6897
|
let state$1 = this.state;
|
|
@@ -6683,7 +6908,7 @@ class EditorView {
|
|
|
6683
6908
|
if (transactions.some(tr => tr.annotation(isFocusChange))) {
|
|
6684
6909
|
this.inputState.notifiedFocused = focus;
|
|
6685
6910
|
// If a focus-change transaction is being dispatched, set this update flag.
|
|
6686
|
-
focusFlag = 1 /* Focus */;
|
|
6911
|
+
focusFlag = 1 /* UpdateFlag.Focus */;
|
|
6687
6912
|
}
|
|
6688
6913
|
else if (focus != this.inputState.notifiedFocused) {
|
|
6689
6914
|
this.inputState.notifiedFocused = focus;
|
|
@@ -6691,7 +6916,7 @@ class EditorView {
|
|
|
6691
6916
|
// add a flag to this update
|
|
6692
6917
|
dispatchFocus = focusChangeTransaction(state$1, focus);
|
|
6693
6918
|
if (!dispatchFocus)
|
|
6694
|
-
focusFlag = 1 /* Focus */;
|
|
6919
|
+
focusFlag = 1 /* UpdateFlag.Focus */;
|
|
6695
6920
|
}
|
|
6696
6921
|
// If there was a pending DOM change, eagerly read it and try to
|
|
6697
6922
|
// apply it after the given transactions.
|
|
@@ -6714,7 +6939,7 @@ class EditorView {
|
|
|
6714
6939
|
update.flags |= focusFlag;
|
|
6715
6940
|
let scrollTarget = this.viewState.scrollTarget;
|
|
6716
6941
|
try {
|
|
6717
|
-
this.updateState = 2 /* Updating */;
|
|
6942
|
+
this.updateState = 2 /* UpdateState.Updating */;
|
|
6718
6943
|
for (let tr of transactions) {
|
|
6719
6944
|
if (scrollTarget)
|
|
6720
6945
|
scrollTarget = scrollTarget.map(tr.changes);
|
|
@@ -6740,7 +6965,7 @@ class EditorView {
|
|
|
6740
6965
|
this.docView.updateSelection(redrawn, transactions.some(tr => tr.isUserEvent("select.pointer")));
|
|
6741
6966
|
}
|
|
6742
6967
|
finally {
|
|
6743
|
-
this.updateState = 0 /* Idle */;
|
|
6968
|
+
this.updateState = 0 /* UpdateState.Idle */;
|
|
6744
6969
|
}
|
|
6745
6970
|
if (update.startState.facet(theme) != update.state.facet(theme))
|
|
6746
6971
|
this.viewState.mustMeasureContent = true;
|
|
@@ -6767,13 +6992,13 @@ class EditorView {
|
|
|
6767
6992
|
[`dispatch`](https://codemirror.net/6/docs/ref/#view.EditorView.dispatch) instead.)
|
|
6768
6993
|
*/
|
|
6769
6994
|
setState(newState) {
|
|
6770
|
-
if (this.updateState != 0 /* Idle */)
|
|
6995
|
+
if (this.updateState != 0 /* UpdateState.Idle */)
|
|
6771
6996
|
throw new Error("Calls to EditorView.setState are not allowed while an update is in progress");
|
|
6772
6997
|
if (this.destroyed) {
|
|
6773
6998
|
this.viewState.state = newState;
|
|
6774
6999
|
return;
|
|
6775
7000
|
}
|
|
6776
|
-
this.updateState = 2 /* Updating */;
|
|
7001
|
+
this.updateState = 2 /* UpdateState.Updating */;
|
|
6777
7002
|
let hadFocus = this.hasFocus;
|
|
6778
7003
|
try {
|
|
6779
7004
|
for (let plugin of this.plugins)
|
|
@@ -6790,7 +7015,7 @@ class EditorView {
|
|
|
6790
7015
|
this.bidiCache = [];
|
|
6791
7016
|
}
|
|
6792
7017
|
finally {
|
|
6793
|
-
this.updateState = 0 /* Idle */;
|
|
7018
|
+
this.updateState = 0 /* UpdateState.Idle */;
|
|
6794
7019
|
}
|
|
6795
7020
|
if (hadFocus)
|
|
6796
7021
|
this.focus();
|
|
@@ -6833,6 +7058,11 @@ class EditorView {
|
|
|
6833
7058
|
return;
|
|
6834
7059
|
if (this.measureScheduled > -1)
|
|
6835
7060
|
this.win.cancelAnimationFrame(this.measureScheduled);
|
|
7061
|
+
if (this.observer.delayedAndroidKey) {
|
|
7062
|
+
this.measureScheduled = -1;
|
|
7063
|
+
this.requestMeasure();
|
|
7064
|
+
return;
|
|
7065
|
+
}
|
|
6836
7066
|
this.measureScheduled = 0; // Prevent requestMeasure calls from scheduling another animation frame
|
|
6837
7067
|
if (flush)
|
|
6838
7068
|
this.observer.forceFlush();
|
|
@@ -6855,7 +7085,7 @@ class EditorView {
|
|
|
6855
7085
|
scrollAnchorHeight = block.top;
|
|
6856
7086
|
}
|
|
6857
7087
|
}
|
|
6858
|
-
this.updateState = 1 /* Measuring */;
|
|
7088
|
+
this.updateState = 1 /* UpdateState.Measuring */;
|
|
6859
7089
|
let changed = this.viewState.measure(this);
|
|
6860
7090
|
if (!changed && !this.measureRequests.length && this.viewState.scrollTarget == null)
|
|
6861
7091
|
break;
|
|
@@ -6867,7 +7097,7 @@ class EditorView {
|
|
|
6867
7097
|
}
|
|
6868
7098
|
let measuring = [];
|
|
6869
7099
|
// Only run measure requests in this cycle when the viewport didn't change
|
|
6870
|
-
if (!(changed & 4 /* Viewport */))
|
|
7100
|
+
if (!(changed & 4 /* UpdateFlag.Viewport */))
|
|
6871
7101
|
[this.measureRequests, measuring] = [measuring, this.measureRequests];
|
|
6872
7102
|
let measured = measuring.map(m => {
|
|
6873
7103
|
try {
|
|
@@ -6884,7 +7114,7 @@ class EditorView {
|
|
|
6884
7114
|
updated = update;
|
|
6885
7115
|
else
|
|
6886
7116
|
updated.flags |= changed;
|
|
6887
|
-
this.updateState = 2 /* Updating */;
|
|
7117
|
+
this.updateState = 2 /* UpdateState.Updating */;
|
|
6888
7118
|
if (!update.empty) {
|
|
6889
7119
|
this.updatePlugins(update);
|
|
6890
7120
|
this.inputState.update(update);
|
|
@@ -6927,7 +7157,7 @@ class EditorView {
|
|
|
6927
7157
|
}
|
|
6928
7158
|
}
|
|
6929
7159
|
finally {
|
|
6930
|
-
this.updateState = 0 /* Idle */;
|
|
7160
|
+
this.updateState = 0 /* UpdateState.Idle */;
|
|
6931
7161
|
this.measureScheduled = -1;
|
|
6932
7162
|
}
|
|
6933
7163
|
if (updated && !updated.empty)
|
|
@@ -6983,12 +7213,13 @@ class EditorView {
|
|
|
6983
7213
|
}
|
|
6984
7214
|
mountStyles() {
|
|
6985
7215
|
this.styleModules = this.state.facet(styleModule);
|
|
6986
|
-
|
|
7216
|
+
let nonce = this.state.facet(EditorView.cspNonce);
|
|
7217
|
+
styleMod.StyleModule.mount(this.root, this.styleModules.concat(baseTheme$1).reverse(), nonce ? { nonce } : undefined);
|
|
6987
7218
|
}
|
|
6988
7219
|
readMeasured() {
|
|
6989
|
-
if (this.updateState == 2 /* Updating */)
|
|
7220
|
+
if (this.updateState == 2 /* UpdateState.Updating */)
|
|
6990
7221
|
throw new Error("Reading the editor layout isn't allowed during an update");
|
|
6991
|
-
if (this.updateState == 0 /* Idle */ && this.measureScheduled > -1)
|
|
7222
|
+
if (this.updateState == 0 /* UpdateState.Idle */ && this.measureScheduled > -1)
|
|
6992
7223
|
this.measure(false);
|
|
6993
7224
|
}
|
|
6994
7225
|
/**
|
|
@@ -7242,12 +7473,16 @@ class EditorView {
|
|
|
7242
7473
|
bidiSpans(line) {
|
|
7243
7474
|
if (line.length > MaxBidiLine)
|
|
7244
7475
|
return trivialOrder(line.length);
|
|
7245
|
-
let dir = this.textDirectionAt(line.from);
|
|
7246
|
-
for (let entry of this.bidiCache)
|
|
7247
|
-
if (entry.from == line.from && entry.dir == dir
|
|
7476
|
+
let dir = this.textDirectionAt(line.from), isolates;
|
|
7477
|
+
for (let entry of this.bidiCache) {
|
|
7478
|
+
if (entry.from == line.from && entry.dir == dir &&
|
|
7479
|
+
(entry.fresh || isolatesEq(entry.isolates, isolates = getIsolatedRanges(this, line.from, line.to))))
|
|
7248
7480
|
return entry.order;
|
|
7249
|
-
|
|
7250
|
-
|
|
7481
|
+
}
|
|
7482
|
+
if (!isolates)
|
|
7483
|
+
isolates = getIsolatedRanges(this, line.from, line.to);
|
|
7484
|
+
let order = computeOrder(line.text, dir, isolates);
|
|
7485
|
+
this.bidiCache.push(new CachedOrder(line.from, line.to, dir, isolates, true, order));
|
|
7251
7486
|
return order;
|
|
7252
7487
|
}
|
|
7253
7488
|
/**
|
|
@@ -7382,6 +7617,10 @@ DOM content are handled. Handlers are passed the document
|
|
|
7382
7617
|
positions between which the change was found, and the new
|
|
7383
7618
|
content. When one returns true, no further input handlers are
|
|
7384
7619
|
called and the default behavior is prevented.
|
|
7620
|
+
|
|
7621
|
+
The `insert` argument can be used to get the default transaction
|
|
7622
|
+
that would be applied for this input. This can be useful when
|
|
7623
|
+
dispatching the custom behavior as a separate transaction.
|
|
7385
7624
|
*/
|
|
7386
7625
|
EditorView.inputHandler = inputHandler;
|
|
7387
7626
|
/**
|
|
@@ -7469,6 +7708,16 @@ regions.
|
|
|
7469
7708
|
*/
|
|
7470
7709
|
EditorView.atomicRanges = atomicRanges;
|
|
7471
7710
|
/**
|
|
7711
|
+
When range decorations add a `unicode-bidi: isolate` style, they
|
|
7712
|
+
should also include a
|
|
7713
|
+
[`bidiIsolate`](https://codemirror.net/6/docs/ref/#view.MarkDecorationSpec.bidiIsolate) property
|
|
7714
|
+
in their decoration spec, and be exposed through this facet, so
|
|
7715
|
+
that the editor can compute the proper text order. (Other values
|
|
7716
|
+
for `unicode-bidi`, except of course `normal`, are not
|
|
7717
|
+
supported.)
|
|
7718
|
+
*/
|
|
7719
|
+
EditorView.bidiIsolatedRanges = bidiIsolatedRanges;
|
|
7720
|
+
/**
|
|
7472
7721
|
Facet that allows extensions to provide additional scroll
|
|
7473
7722
|
margins (space around the sides of the scrolling element that
|
|
7474
7723
|
should be considered invisible). This can be useful when the
|
|
@@ -7484,6 +7733,12 @@ true.
|
|
|
7484
7733
|
*/
|
|
7485
7734
|
EditorView.darkTheme = darkTheme;
|
|
7486
7735
|
/**
|
|
7736
|
+
Provides a Content Security Policy nonce to use when creating
|
|
7737
|
+
the style sheets for the editor. Holds the empty string when no
|
|
7738
|
+
nonce has been provided.
|
|
7739
|
+
*/
|
|
7740
|
+
EditorView.cspNonce = state.Facet.define({ combine: values => values.length ? values[0] : "" });
|
|
7741
|
+
/**
|
|
7487
7742
|
Facet that provides additional DOM attributes for the editor's
|
|
7488
7743
|
editable DOM element.
|
|
7489
7744
|
*/
|
|
@@ -7511,20 +7766,22 @@ EditorView.announce = state.StateEffect.define();
|
|
|
7511
7766
|
const MaxBidiLine = 4096;
|
|
7512
7767
|
const BadMeasure = {};
|
|
7513
7768
|
class CachedOrder {
|
|
7514
|
-
constructor(from, to, dir, order) {
|
|
7769
|
+
constructor(from, to, dir, isolates, fresh, order) {
|
|
7515
7770
|
this.from = from;
|
|
7516
7771
|
this.to = to;
|
|
7517
7772
|
this.dir = dir;
|
|
7773
|
+
this.isolates = isolates;
|
|
7774
|
+
this.fresh = fresh;
|
|
7518
7775
|
this.order = order;
|
|
7519
7776
|
}
|
|
7520
7777
|
static update(cache, changes) {
|
|
7521
|
-
if (changes.empty)
|
|
7778
|
+
if (changes.empty && !cache.some(c => c.fresh))
|
|
7522
7779
|
return cache;
|
|
7523
7780
|
let result = [], lastDir = cache.length ? cache[cache.length - 1].dir : exports.Direction.LTR;
|
|
7524
7781
|
for (let i = Math.max(0, cache.length - 10); i < cache.length; i++) {
|
|
7525
7782
|
let entry = cache[i];
|
|
7526
7783
|
if (entry.dir == lastDir && !changes.touchesRange(entry.from, entry.to))
|
|
7527
|
-
result.push(new CachedOrder(changes.mapPos(entry.from, 1), changes.mapPos(entry.to, -1), entry.dir, entry.order));
|
|
7784
|
+
result.push(new CachedOrder(changes.mapPos(entry.from, 1), changes.mapPos(entry.to, -1), entry.dir, entry.isolates, false, entry.order));
|
|
7528
7785
|
}
|
|
7529
7786
|
return result;
|
|
7530
7787
|
}
|
|
@@ -7847,7 +8104,7 @@ function rectanglesForRange(view, className, range) {
|
|
|
7847
8104
|
return pieces(top).concat(between).concat(pieces(bottom));
|
|
7848
8105
|
}
|
|
7849
8106
|
function piece(left, top, right, bottom) {
|
|
7850
|
-
return new RectangleMarker(className, left - base.left, top - base.top - 0.01 /* Epsilon */, right - left, bottom - top + 0.01 /* Epsilon */);
|
|
8107
|
+
return new RectangleMarker(className, left - base.left, top - base.top - 0.01 /* C.Epsilon */, right - left, bottom - top + 0.01 /* C.Epsilon */);
|
|
7851
8108
|
}
|
|
7852
8109
|
function pieces({ top, bottom, horizontal }) {
|
|
7853
8110
|
let pieces = [];
|
|
@@ -8864,12 +9121,12 @@ const tooltipPlugin = ViewPlugin.fromClass(class {
|
|
|
8864
9121
|
continue;
|
|
8865
9122
|
}
|
|
8866
9123
|
let arrow = tooltip.arrow ? tView.dom.querySelector(".cm-tooltip-arrow") : null;
|
|
8867
|
-
let arrowHeight = arrow ? 7 /* Size */ : 0;
|
|
9124
|
+
let arrowHeight = arrow ? 7 /* Arrow.Size */ : 0;
|
|
8868
9125
|
let width = size.right - size.left, height = (_a = knownHeight.get(tView)) !== null && _a !== void 0 ? _a : size.bottom - size.top;
|
|
8869
9126
|
let offset = tView.offset || noOffset, ltr = this.view.textDirection == exports.Direction.LTR;
|
|
8870
9127
|
let left = size.width > space.right - space.left ? (ltr ? space.left : space.right - size.width)
|
|
8871
|
-
: ltr ? Math.min(pos.left - (arrow ? 14 /* Offset */ : 0) + offset.x, space.right - width)
|
|
8872
|
-
: Math.max(space.left, pos.left - width + (arrow ? 14 /* Offset */ : 0) - offset.x);
|
|
9128
|
+
: ltr ? Math.min(pos.left - (arrow ? 14 /* Arrow.Offset */ : 0) + offset.x, space.right - width)
|
|
9129
|
+
: Math.max(space.left, pos.left - width + (arrow ? 14 /* Arrow.Offset */ : 0) - offset.x);
|
|
8873
9130
|
let above = !!tooltip.above;
|
|
8874
9131
|
if (!tooltip.strictSide && (above
|
|
8875
9132
|
? pos.top - (size.bottom - size.top) - offset.y < space.top
|
|
@@ -8903,7 +9160,7 @@ const tooltipPlugin = ViewPlugin.fromClass(class {
|
|
|
8903
9160
|
dom.style.left = left + "px";
|
|
8904
9161
|
}
|
|
8905
9162
|
if (arrow)
|
|
8906
|
-
arrow.style.left = `${pos.left + (ltr ? offset.x : -offset.x) - (left + 14 /* Offset */ - 7 /* Size */)}px`;
|
|
9163
|
+
arrow.style.left = `${pos.left + (ltr ? offset.x : -offset.x) - (left + 14 /* Arrow.Offset */ - 7 /* Arrow.Size */)}px`;
|
|
8907
9164
|
if (tView.overlap !== true)
|
|
8908
9165
|
others.push({ left, top, right, bottom: top + height });
|
|
8909
9166
|
dom.classList.toggle("cm-tooltip-above", above);
|
|
@@ -8946,8 +9203,8 @@ const baseTheme = EditorView.baseTheme({
|
|
|
8946
9203
|
color: "white"
|
|
8947
9204
|
},
|
|
8948
9205
|
".cm-tooltip-arrow": {
|
|
8949
|
-
height: `${7 /* Size */}px`,
|
|
8950
|
-
width: `${7 /* Size */ * 2}px`,
|
|
9206
|
+
height: `${7 /* Arrow.Size */}px`,
|
|
9207
|
+
width: `${7 /* Arrow.Size */ * 2}px`,
|
|
8951
9208
|
position: "absolute",
|
|
8952
9209
|
zIndex: -1,
|
|
8953
9210
|
overflow: "hidden",
|
|
@@ -8956,26 +9213,26 @@ const baseTheme = EditorView.baseTheme({
|
|
|
8956
9213
|
position: "absolute",
|
|
8957
9214
|
width: 0,
|
|
8958
9215
|
height: 0,
|
|
8959
|
-
borderLeft: `${7 /* Size */}px solid transparent`,
|
|
8960
|
-
borderRight: `${7 /* Size */}px solid transparent`,
|
|
9216
|
+
borderLeft: `${7 /* Arrow.Size */}px solid transparent`,
|
|
9217
|
+
borderRight: `${7 /* Arrow.Size */}px solid transparent`,
|
|
8961
9218
|
},
|
|
8962
9219
|
".cm-tooltip-above &": {
|
|
8963
|
-
bottom: `-${7 /* Size */}px`,
|
|
9220
|
+
bottom: `-${7 /* Arrow.Size */}px`,
|
|
8964
9221
|
"&:before": {
|
|
8965
|
-
borderTop: `${7 /* Size */}px solid #bbb`,
|
|
9222
|
+
borderTop: `${7 /* Arrow.Size */}px solid #bbb`,
|
|
8966
9223
|
},
|
|
8967
9224
|
"&:after": {
|
|
8968
|
-
borderTop: `${7 /* Size */}px solid #f5f5f5`,
|
|
9225
|
+
borderTop: `${7 /* Arrow.Size */}px solid #f5f5f5`,
|
|
8969
9226
|
bottom: "1px"
|
|
8970
9227
|
}
|
|
8971
9228
|
},
|
|
8972
9229
|
".cm-tooltip-below &": {
|
|
8973
|
-
top: `-${7 /* Size */}px`,
|
|
9230
|
+
top: `-${7 /* Arrow.Size */}px`,
|
|
8974
9231
|
"&:before": {
|
|
8975
|
-
borderBottom: `${7 /* Size */}px solid #bbb`,
|
|
9232
|
+
borderBottom: `${7 /* Arrow.Size */}px solid #bbb`,
|
|
8976
9233
|
},
|
|
8977
9234
|
"&:after": {
|
|
8978
|
-
borderBottom: `${7 /* Size */}px solid #f5f5f5`,
|
|
9235
|
+
borderBottom: `${7 /* Arrow.Size */}px solid #f5f5f5`,
|
|
8979
9236
|
top: "1px"
|
|
8980
9237
|
}
|
|
8981
9238
|
},
|
|
@@ -9000,6 +9257,10 @@ const showTooltip = state.Facet.define({
|
|
|
9000
9257
|
});
|
|
9001
9258
|
const showHoverTooltip = state.Facet.define();
|
|
9002
9259
|
class HoverTooltipHost {
|
|
9260
|
+
// Needs to be static so that host tooltip instances always match
|
|
9261
|
+
static create(view) {
|
|
9262
|
+
return new HoverTooltipHost(view);
|
|
9263
|
+
}
|
|
9003
9264
|
constructor(view) {
|
|
9004
9265
|
this.view = view;
|
|
9005
9266
|
this.mounted = false;
|
|
@@ -9007,10 +9268,6 @@ class HoverTooltipHost {
|
|
|
9007
9268
|
this.dom.classList.add("cm-tooltip-hover");
|
|
9008
9269
|
this.manager = new TooltipViewManager(view, showHoverTooltip, t => this.createHostedView(t));
|
|
9009
9270
|
}
|
|
9010
|
-
// Needs to be static so that host tooltip instances always match
|
|
9011
|
-
static create(view) {
|
|
9012
|
-
return new HoverTooltipHost(view);
|
|
9013
|
-
}
|
|
9014
9271
|
createHostedView(tooltip) {
|
|
9015
9272
|
let hostedView = tooltip.create(this.view);
|
|
9016
9273
|
hostedView.dom.classList.add("cm-tooltip-section");
|
|
@@ -9090,30 +9347,41 @@ class HoverPlugin {
|
|
|
9090
9347
|
}
|
|
9091
9348
|
startHover() {
|
|
9092
9349
|
clearTimeout(this.restartTimeout);
|
|
9093
|
-
let { lastMove } = this;
|
|
9094
|
-
let
|
|
9095
|
-
if (
|
|
9350
|
+
let { view, lastMove } = this;
|
|
9351
|
+
let desc = view.docView.nearest(lastMove.target);
|
|
9352
|
+
if (!desc)
|
|
9096
9353
|
return;
|
|
9097
|
-
let
|
|
9098
|
-
if (
|
|
9099
|
-
|
|
9100
|
-
|
|
9101
|
-
|
|
9102
|
-
|
|
9103
|
-
|
|
9104
|
-
|
|
9354
|
+
let pos, side = 1;
|
|
9355
|
+
if (desc instanceof WidgetView) {
|
|
9356
|
+
pos = desc.posAtStart;
|
|
9357
|
+
}
|
|
9358
|
+
else {
|
|
9359
|
+
pos = view.posAtCoords(lastMove);
|
|
9360
|
+
if (pos == null)
|
|
9361
|
+
return;
|
|
9362
|
+
let posCoords = view.coordsAtPos(pos);
|
|
9363
|
+
if (!posCoords ||
|
|
9364
|
+
lastMove.y < posCoords.top || lastMove.y > posCoords.bottom ||
|
|
9365
|
+
lastMove.x < posCoords.left - view.defaultCharacterWidth ||
|
|
9366
|
+
lastMove.x > posCoords.right + view.defaultCharacterWidth)
|
|
9367
|
+
return;
|
|
9368
|
+
let bidi = view.bidiSpans(view.state.doc.lineAt(pos)).find(s => s.from <= pos && s.to >= pos);
|
|
9369
|
+
let rtl = bidi && bidi.dir == exports.Direction.RTL ? -1 : 1;
|
|
9370
|
+
side = (lastMove.x < posCoords.left ? -rtl : rtl);
|
|
9371
|
+
}
|
|
9372
|
+
let open = this.source(view, pos, side);
|
|
9105
9373
|
if (open === null || open === void 0 ? void 0 : open.then) {
|
|
9106
9374
|
let pending = this.pending = { pos };
|
|
9107
9375
|
open.then(result => {
|
|
9108
9376
|
if (this.pending == pending) {
|
|
9109
9377
|
this.pending = null;
|
|
9110
9378
|
if (result)
|
|
9111
|
-
|
|
9379
|
+
view.dispatch({ effects: this.setHover.of(result) });
|
|
9112
9380
|
}
|
|
9113
|
-
}, e => logException(
|
|
9381
|
+
}, e => logException(view.state, e, "hover tooltip"));
|
|
9114
9382
|
}
|
|
9115
9383
|
else if (open) {
|
|
9116
|
-
|
|
9384
|
+
view.dispatch({ effects: this.setHover.of(open) });
|
|
9117
9385
|
}
|
|
9118
9386
|
}
|
|
9119
9387
|
mousemove(event) {
|
|
@@ -9125,7 +9393,7 @@ class HoverPlugin {
|
|
|
9125
9393
|
if (tooltip && !isInTooltip(this.lastMove.target) || this.pending) {
|
|
9126
9394
|
let { pos } = tooltip || this.pending, end = (_a = tooltip === null || tooltip === void 0 ? void 0 : tooltip.end) !== null && _a !== void 0 ? _a : pos;
|
|
9127
9395
|
if ((pos == end ? this.view.posAtCoords(this.lastMove) != pos
|
|
9128
|
-
: !isOverRange(this.view, pos, end, event.clientX, event.clientY
|
|
9396
|
+
: !isOverRange(this.view, pos, end, event.clientX, event.clientY))) {
|
|
9129
9397
|
this.view.dispatch({ effects: this.setHover.of(null) });
|
|
9130
9398
|
this.pending = null;
|
|
9131
9399
|
}
|
|
@@ -9150,19 +9418,12 @@ function isInTooltip(elt) {
|
|
|
9150
9418
|
return false;
|
|
9151
9419
|
}
|
|
9152
9420
|
function isOverRange(view, from, to, x, y, margin) {
|
|
9153
|
-
let
|
|
9154
|
-
let
|
|
9155
|
-
|
|
9156
|
-
|
|
9157
|
-
let
|
|
9158
|
-
|
|
9159
|
-
for (let i = 0; i < rects.length; i++) {
|
|
9160
|
-
let rect = rects[i];
|
|
9161
|
-
let dist = Math.max(rect.top - y, y - rect.bottom, rect.left - x, x - rect.right);
|
|
9162
|
-
if (dist <= margin)
|
|
9163
|
-
return true;
|
|
9164
|
-
}
|
|
9165
|
-
return false;
|
|
9421
|
+
let rect = view.scrollDOM.getBoundingClientRect();
|
|
9422
|
+
let docBottom = view.documentTop + view.documentPadding.top + view.contentHeight;
|
|
9423
|
+
if (rect.left > x || rect.right < x || rect.top > y || Math.min(rect.bottom, docBottom) < y)
|
|
9424
|
+
return false;
|
|
9425
|
+
let pos = view.posAtCoords({ x, y }, false);
|
|
9426
|
+
return pos >= from && pos <= to;
|
|
9166
9427
|
}
|
|
9167
9428
|
/**
|
|
9168
9429
|
Set up a hover tooltip, which shows up when the pointer hovers
|
|
@@ -9207,7 +9468,7 @@ function hoverTooltip(source, options = {}) {
|
|
|
9207
9468
|
});
|
|
9208
9469
|
return [
|
|
9209
9470
|
hoverState,
|
|
9210
|
-
ViewPlugin.define(view => new HoverPlugin(view, source, hoverState, setHover, options.hoverTime || 300 /* Time */)),
|
|
9471
|
+
ViewPlugin.define(view => new HoverPlugin(view, source, hoverState, setHover, options.hoverTime || 300 /* Hover.Time */)),
|
|
9211
9472
|
showHoverTooltipHost
|
|
9212
9473
|
];
|
|
9213
9474
|
}
|