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