@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/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 = null;
1168
+ let changed = false;
1171
1169
  if (prev)
1172
1170
  for (let name in prev)
1173
- if (!(attrs && name in attrs))
1174
- dom.removeAttribute(changed = name);
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
- dom.setAttribute(changed = name, attrs[name]);
1179
- return !!changed;
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
- function computeOrder(line, direction) {
2295
- let len = line.length, outerType = direction == LTR ? 1 /* L */ : 2 /* R */, oppositeType = direction == LTR ? 2 /* R */ : 1 /* L */;
2296
- if (!line || outerType == 1 /* L */ && !BidiRE.test(line))
2297
- return trivialOrder(len);
2298
- // W1. Examine each non-spacing mark (NSM) in the level run, and
2299
- // change the type of the NSM to the type of the previous
2300
- // character. If the NSM is at the start of the level run, it will
2301
- // get the type of sor.
2302
- // W2. Search backwards from each instance of a European number
2303
- // until the first strong type (R, L, AL, or sor) is found. If an
2304
- // AL is found, change the type of the European number to Arabic
2305
- // number.
2306
- // W3. Change all ALs to R.
2307
- // (Left after this: L, R, EN, AN, ET, CS, NI)
2308
- for (let i = 0, prev = outerType, prevStrong = outerType; i < len; i++) {
2309
- let type = charType(line.charCodeAt(i));
2310
- if (type == 512 /* NSM */)
2311
- type = prev;
2312
- else if (type == 8 /* EN */ && prevStrong == 4 /* AL */)
2313
- type = 16 /* AN */;
2314
- types[i] = type == 4 /* AL */ ? 2 /* R */ : type;
2315
- if (type & 7 /* Strong */)
2316
- prevStrong = type;
2317
- prev = type;
2318
- }
2319
- // W5. A sequence of European terminators adjacent to European
2320
- // numbers changes to all European numbers.
2321
- // W6. Otherwise, separators and terminators change to Other
2322
- // Neutral.
2323
- // W7. Search backwards from each instance of a European number
2324
- // until the first strong type (R, L, or sor) is found. If an L is
2325
- // found, then change the type of the European number to L.
2326
- // (Left after this: L, R, EN+AN, NI)
2327
- for (let i = 0, prev = outerType, prevStrong = outerType; i < len; i++) {
2328
- let type = types[i];
2329
- if (type == 128 /* CS */) {
2330
- if (i < len - 1 && prev == types[i + 1] && (prev & 24 /* Num */))
2331
- type = types[i] = prev;
2332
- else
2333
- types[i] = 256 /* NI */;
2334
- }
2335
- else if (type == 64 /* ET */) {
2336
- let end = i + 1;
2337
- while (end < len && types[end] == 64 /* ET */)
2338
- end++;
2339
- let replace = (i && prev == 8 /* EN */) || (end < len && types[end] == 8 /* EN */) ? (prevStrong == 1 /* L */ ? 1 /* L */ : 8 /* EN */) : 256 /* NI */;
2340
- for (let j = i; j < end; j++)
2341
- types[j] = replace;
2342
- i = end - 1;
2343
- }
2344
- else if (type == 8 /* EN */ && prevStrong == 1 /* L */) {
2345
- types[i] = 1 /* L */;
2346
- }
2347
- prev = type;
2348
- if (type & 7 /* Strong */)
2349
- prevStrong = type;
2350
- }
2351
- // N0. Process bracket pairs in an isolating run sequence
2352
- // sequentially in the logical order of the text positions of the
2353
- // opening paired brackets using the logic given below. Within this
2354
- // scope, bidirectional types EN and AN are treated as R.
2355
- for (let i = 0, sI = 0, context = 0, ch, br, type; i < len; i++) {
2356
- // Keeps [startIndex, type, strongSeen] triples for each open
2357
- // bracket on BracketStack.
2358
- if (br = Brackets[ch = line.charCodeAt(i)]) {
2359
- if (br < 0) { // Closing bracket
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
- if (BracketStack[sJ + 1] == -br) {
2362
- let flags = BracketStack[sJ + 2];
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
- else if (BracketStack.length == 189 /* MaxDepth */) {
2374
- break;
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
- BracketStack[sI++] = i;
2378
- BracketStack[sI++] = ch;
2379
- BracketStack[sI++] = context;
2500
+ prev = type;
2501
+ i++;
2380
2502
  }
2381
2503
  }
2382
- else if ((type = types[i]) == 2 /* R */ || type == 1 /* L */) {
2383
- let embed = type == outerType;
2384
- context = embed ? 0 : 1 /* OppositeBefore */;
2385
- for (let sJ = sI - 3; sJ >= 0; sJ -= 3) {
2386
- let cur = BracketStack[sJ + 2];
2387
- if (cur & 2 /* EmbedInside */)
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
- if (cur & 4 /* OppositeInside */)
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
- // N1. A sequence of neutrals takes the direction of the
2401
- // surrounding strong text if the text on both sides has the same
2402
- // direction. European and Arabic numbers act as if they were R in
2403
- // terms of their influence on neutrals. Start-of-level-run (sor)
2404
- // and end-of-level-run (eor) are used at level run boundaries.
2405
- // N2. Any remaining neutrals take the embedding direction.
2406
- // (Left after this: L, R, EN+AN)
2407
- for (let i = 0; i < len; i++) {
2408
- if (types[i] == 256 /* NI */) {
2409
- let end = i + 1;
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
- else {
2440
- order.push(new BidiSpan(start, i, 0));
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
- else {
2445
- for (let i = 0; i < len;) {
2446
- let start = i, rtl = types[i++] == 2 /* R */;
2447
- while (i < len && rtl == (types[i] == 2 /* R */))
2448
- i++;
2449
- order.push(new BidiSpan(start, i, rtl ? 1 : 2));
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.cursorBidiLevel != null)
2726
- domSel.cursorBidiLevel = main.bidiLevel;
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
- from = to = cView.posAtEnd + offset;
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 = to = parentView.posAtStart + offset;
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
- class DecorationComparator$1 {
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
- setSelectionOrigin(origin) {
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 tr;
5961
- if (change.from >= sel.from && change.to <= sel.to && change.to - change.from >= (sel.to - sel.from) / 3 &&
5962
- (!newSel || newSel.main.empty && newSel.main.from == change.from + change.insert.length) &&
5963
- view.inputState.composing < 0) {
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
- this._dispatch = config.dispatch || ((tr) => this.update([tr]));
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 tr = input.length == 1 && input[0] instanceof state.Transaction ? input[0]
6657
- : this.state.update(...input);
6658
- this._dispatch(tr, this);
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
- styleMod.StyleModule.mount(this.root, this.styleModules.concat(baseTheme$1).reverse());
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
- let order = computeOrder(line.text, dir);
7250
- this.bidiCache.push(new CachedOrder(line.from, line.to, dir, order));
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 pos = this.view.contentDOM.contains(lastMove.target) ? this.view.posAtCoords(lastMove) : null;
9095
- if (pos == null)
9350
+ let { view, lastMove } = this;
9351
+ let desc = view.docView.nearest(lastMove.target);
9352
+ if (!desc)
9096
9353
  return;
9097
- let posCoords = this.view.coordsAtPos(pos);
9098
- if (posCoords == null || lastMove.y < posCoords.top || lastMove.y > posCoords.bottom ||
9099
- lastMove.x < posCoords.left - this.view.defaultCharacterWidth ||
9100
- lastMove.x > posCoords.right + this.view.defaultCharacterWidth)
9101
- return;
9102
- let bidi = this.view.bidiSpans(this.view.state.doc.lineAt(pos)).find(s => s.from <= pos && s.to >= pos);
9103
- let rtl = bidi && bidi.dir == exports.Direction.RTL ? -1 : 1;
9104
- let open = this.source(this.view, pos, (lastMove.x < posCoords.left ? -rtl : rtl));
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
- this.view.dispatch({ effects: this.setHover.of(result) });
9379
+ view.dispatch({ effects: this.setHover.of(result) });
9112
9380
  }
9113
- }, e => logException(this.view.state, e, "hover tooltip"));
9381
+ }, e => logException(view.state, e, "hover tooltip"));
9114
9382
  }
9115
9383
  else if (open) {
9116
- this.view.dispatch({ effects: this.setHover.of(open) });
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, 6 /* MaxDist */))) {
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 range = document.createRange();
9154
- let fromDOM = view.domAtPos(from), toDOM = view.domAtPos(to);
9155
- range.setEnd(toDOM.node, toDOM.offset);
9156
- range.setStart(fromDOM.node, fromDOM.offset);
9157
- let rects = range.getClientRects();
9158
- range.detach();
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
  }