@codemirror/view 0.19.48 → 0.20.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -4,8 +4,6 @@ Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
5
  var state = require('@codemirror/state');
6
6
  var styleMod = require('style-mod');
7
- var rangeset = require('@codemirror/rangeset');
8
- var text = require('@codemirror/text');
9
7
  var w3cKeyname = require('w3c-keyname');
10
8
 
11
9
  function getSelection(root) {
@@ -334,7 +332,7 @@ class ContentView {
334
332
  track.written = true;
335
333
  if (child.dom.parentNode == parent) {
336
334
  while (next && next != child.dom)
337
- next = rm(next);
335
+ next = rm$1(next);
338
336
  }
339
337
  else {
340
338
  parent.insertBefore(child.dom, next);
@@ -345,7 +343,7 @@ class ContentView {
345
343
  if (next && track && track.node == parent)
346
344
  track.written = true;
347
345
  while (next)
348
- next = rm(next);
346
+ next = rm$1(next);
349
347
  }
350
348
  else if (this.dirty & 1 /* Child */) {
351
349
  for (let child of this.children)
@@ -491,7 +489,7 @@ class ContentView {
491
489
  }
492
490
  ContentView.prototype.breakAfter = 0;
493
491
  // Remove a DOM node and return its next sibling.
494
- function rm(dom) {
492
+ function rm$1(dom) {
495
493
  let next = dom.nextSibling;
496
494
  dom.parentNode.removeChild(dom);
497
495
  return next;
@@ -827,12 +825,12 @@ class WidgetView extends ContentView {
827
825
  ignoreEvent(event) { return this.widget.ignoreEvent(event); }
828
826
  get overrideDOMText() {
829
827
  if (this.length == 0)
830
- return text.Text.empty;
828
+ return state.Text.empty;
831
829
  let top = this;
832
830
  while (top.parent)
833
831
  top = top.parent;
834
- let view = top.editorView, text$1 = view && view.state.doc, start = this.posAtStart;
835
- return text$1 ? text$1.slice(start, start + this.length) : text.Text.empty;
832
+ let view = top.editorView, text = view && view.state.doc, start = this.posAtStart;
833
+ return text ? text.slice(start, start + this.length) : state.Text.empty;
836
834
  }
837
835
  domAtPos(pos) {
838
836
  return pos == 0 ? DOMPos.before(this.dom) : DOMPos.after(this.dom, pos == this.length);
@@ -955,7 +953,7 @@ class WidgetBufferView extends ContentView {
955
953
  ? { left: imgRect.left, right: imgRect.right, top: siblingRect.top, bottom: siblingRect.bottom } : imgRect;
956
954
  }
957
955
  get overrideDOMText() {
958
- return text.Text.empty;
956
+ return state.Text.empty;
959
957
  }
960
958
  }
961
959
  TextView.prototype.children = WidgetView.prototype.children = WidgetBufferView.prototype.children = noChildren;
@@ -1079,7 +1077,7 @@ function updateAttrs(dom, prev, attrs) {
1079
1077
  Widgets added to the content are described by subclasses of this
1080
1078
  class. Using a description object like that makes it possible to
1081
1079
  delay creating of the DOM structure for a widget until it is
1082
- needed, and to avoid redrawing widgets even when the decorations
1080
+ needed, and to avoid redrawing widgets even if the decorations
1083
1081
  that define them are recreated.
1084
1082
  */
1085
1083
  class WidgetType {
@@ -1092,7 +1090,7 @@ class WidgetType {
1092
1090
  returns `false`, which will cause new instances of the widget to
1093
1091
  always be redrawn.
1094
1092
  */
1095
- eq(_widget) { return false; }
1093
+ eq(widget) { return false; }
1096
1094
  /**
1097
1095
  Update a DOM element created by a widget of the same type (but
1098
1096
  different, non-`eq` content) to reflect this widget. May return
@@ -1100,7 +1098,7 @@ class WidgetType {
1100
1098
  couldn't (in which case the widget will be redrawn). The default
1101
1099
  implementation just returns false.
1102
1100
  */
1103
- updateDOM(_dom) { return false; }
1101
+ updateDOM(dom) { return false; }
1104
1102
  /**
1105
1103
  @internal
1106
1104
  */
@@ -1119,7 +1117,7 @@ class WidgetType {
1119
1117
  should be ignored by the editor. The default is to ignore all
1120
1118
  events.
1121
1119
  */
1122
- ignoreEvent(_event) { return true; }
1120
+ ignoreEvent(event) { return true; }
1123
1121
  /**
1124
1122
  @internal
1125
1123
  */
@@ -1128,7 +1126,7 @@ class WidgetType {
1128
1126
  This is called when the an instance of the widget is removed
1129
1127
  from the editor view.
1130
1128
  */
1131
- destroy(_dom) { }
1129
+ destroy(dom) { }
1132
1130
  }
1133
1131
  /**
1134
1132
  The different types of blocks that can occur in an editor view.
@@ -1155,9 +1153,10 @@ exports.BlockType = void 0;
1155
1153
  /**
1156
1154
  A decoration provides information on how to draw or style a piece
1157
1155
  of content. You'll usually use it wrapped in a
1158
- [`Range`](https://codemirror.net/6/docs/ref/#rangeset.Range), which adds a start and end position.
1156
+ [`Range`](https://codemirror.net/6/docs/ref/#state.Range), which adds a start and end position.
1157
+ @nonabstract
1159
1158
  */
1160
- class Decoration extends rangeset.RangeValue {
1159
+ class Decoration extends state.RangeValue {
1161
1160
  /**
1162
1161
  @internal
1163
1162
  */
@@ -1194,18 +1193,17 @@ class Decoration extends rangeset.RangeValue {
1194
1193
  Create a mark decoration, which influences the styling of the
1195
1194
  content in its range. Nested mark decorations will cause nested
1196
1195
  DOM elements to be created. Nesting order is determined by
1197
- precedence of the [facet](https://codemirror.net/6/docs/ref/#view.EditorView^decorations) or
1198
- (below the facet-provided decorations) [view
1199
- plugin](https://codemirror.net/6/docs/ref/#view.PluginSpec.decorations). Such elements are split
1200
- on line boundaries and on the boundaries of higher-precedence
1201
- decorations.
1196
+ precedence of the [facet](https://codemirror.net/6/docs/ref/#view.EditorView^decorations), with
1197
+ the higher-precedence decorations creating the inner DOM nodes.
1198
+ Such elements are split on line boundaries and on the boundaries
1199
+ of lower-precedence decorations.
1202
1200
  */
1203
1201
  static mark(spec) {
1204
1202
  return new MarkDecoration(spec);
1205
1203
  }
1206
1204
  /**
1207
- Create a widget decoration, which adds an element at the given
1208
- position.
1205
+ Create a widget decoration, which displays a DOM element at the
1206
+ given position.
1209
1207
  */
1210
1208
  static widget(spec) {
1211
1209
  let side = spec.side || 0, block = !!spec.block;
@@ -1242,7 +1240,7 @@ class Decoration extends rangeset.RangeValue {
1242
1240
  pass `true` for `sort` to make the library sort them for you.
1243
1241
  */
1244
1242
  static set(of, sort = false) {
1245
- return rangeset.RangeSet.of(of, sort);
1243
+ return state.RangeSet.of(of, sort);
1246
1244
  }
1247
1245
  /**
1248
1246
  @internal
@@ -1252,7 +1250,7 @@ class Decoration extends rangeset.RangeValue {
1252
1250
  /**
1253
1251
  The empty set of decorations.
1254
1252
  */
1255
- Decoration.none = rangeset.RangeSet.empty;
1253
+ Decoration.none = state.RangeSet.empty;
1256
1254
  class MarkDecoration extends Decoration {
1257
1255
  constructor(spec) {
1258
1256
  let { start, end } = getInclusive(spec);
@@ -1543,11 +1541,11 @@ class BlockWidgetView extends ContentView {
1543
1541
  }
1544
1542
 
1545
1543
  class ContentBuilder {
1546
- constructor(doc, pos, end, disallowBlockEffectsBelow) {
1544
+ constructor(doc, pos, end, disallowBlockEffectsFor) {
1547
1545
  this.doc = doc;
1548
1546
  this.pos = pos;
1549
1547
  this.end = end;
1550
- this.disallowBlockEffectsBelow = disallowBlockEffectsBelow;
1548
+ this.disallowBlockEffectsFor = disallowBlockEffectsFor;
1551
1549
  this.content = [];
1552
1550
  this.curLine = null;
1553
1551
  this.breakAtStart = 0;
@@ -1632,7 +1630,13 @@ class ContentBuilder {
1632
1630
  if (this.openStart < 0)
1633
1631
  this.openStart = openStart;
1634
1632
  }
1635
- point(from, to, deco, active, openStart) {
1633
+ point(from, to, deco, active, openStart, index) {
1634
+ if (this.disallowBlockEffectsFor[index] && deco instanceof PointDecoration) {
1635
+ if (deco.block)
1636
+ throw new RangeError("Block decorations may not be specified via plugins");
1637
+ if (to > this.doc.lineAt(this.pos).to)
1638
+ throw new RangeError("Decorations that replace line breaks may not be specified via plugins");
1639
+ }
1636
1640
  let len = to - from;
1637
1641
  if (deco instanceof PointDecoration) {
1638
1642
  if (deco.block) {
@@ -1676,18 +1680,9 @@ class ContentBuilder {
1676
1680
  if (this.openStart < 0)
1677
1681
  this.openStart = openStart;
1678
1682
  }
1679
- filterPoint(from, to, value, index) {
1680
- if (index < this.disallowBlockEffectsBelow && value instanceof PointDecoration) {
1681
- if (value.block)
1682
- throw new RangeError("Block decorations may not be specified via plugins");
1683
- if (to > this.doc.lineAt(this.pos).to)
1684
- throw new RangeError("Decorations that replace line breaks may not be specified via plugins");
1685
- }
1686
- return true;
1687
- }
1688
- static build(text, from, to, decorations, pluginDecorationLength) {
1689
- let builder = new ContentBuilder(text, from, to, pluginDecorationLength);
1690
- builder.openEnd = rangeset.RangeSet.spans(decorations, from, to, builder);
1683
+ static build(text, from, to, decorations, dynamicDecorationMap) {
1684
+ let builder = new ContentBuilder(text, from, to, dynamicDecorationMap);
1685
+ builder.openEnd = state.RangeSet.spans(decorations, from, to, builder);
1691
1686
  if (builder.openStart < 0)
1692
1687
  builder.openStart = builder.openEnd;
1693
1688
  builder.finish(builder.openEnd);
@@ -1716,13 +1711,8 @@ const mouseSelectionStyle = state.Facet.define();
1716
1711
  const exceptionSink = state.Facet.define();
1717
1712
  const updateListener = state.Facet.define();
1718
1713
  const inputHandler = state.Facet.define();
1719
- // FIXME remove
1720
- const scrollTo = state.StateEffect.define({
1721
- map: (range, changes) => range.map(changes)
1722
- });
1723
- // FIXME remove
1724
- const centerOn = state.StateEffect.define({
1725
- map: (range, changes) => range.map(changes)
1714
+ const perLineTextDirection = state.Facet.define({
1715
+ combine: values => values.some(x => x)
1726
1716
  });
1727
1717
  class ScrollTarget {
1728
1718
  constructor(range, y = "nearest", x = "nearest", yMargin = 5, xMargin = 5) {
@@ -1761,83 +1751,6 @@ function logException(state, exception, context) {
1761
1751
  console.error(exception);
1762
1752
  }
1763
1753
  const editable = state.Facet.define({ combine: values => values.length ? values[0] : true });
1764
- /**
1765
- Used to [declare](https://codemirror.net/6/docs/ref/#view.PluginSpec.provide) which
1766
- [fields](https://codemirror.net/6/docs/ref/#view.PluginValue) a [view plugin](https://codemirror.net/6/docs/ref/#view.ViewPlugin)
1767
- provides.
1768
- */
1769
- class PluginFieldProvider {
1770
- /**
1771
- @internal
1772
- */
1773
- constructor(
1774
- /**
1775
- @internal
1776
- */
1777
- field,
1778
- /**
1779
- @internal
1780
- */
1781
- get) {
1782
- this.field = field;
1783
- this.get = get;
1784
- }
1785
- }
1786
- /**
1787
- Plugin fields are a mechanism for allowing plugins to provide
1788
- values that can be retrieved through the
1789
- [`pluginField`](https://codemirror.net/6/docs/ref/#view.EditorView.pluginField) view method.
1790
- */
1791
- class PluginField {
1792
- /**
1793
- Create a [provider](https://codemirror.net/6/docs/ref/#view.PluginFieldProvider) for this field,
1794
- to use with a plugin's [provide](https://codemirror.net/6/docs/ref/#view.PluginSpec.provide)
1795
- option.
1796
- */
1797
- from(get) {
1798
- return new PluginFieldProvider(this, get);
1799
- }
1800
- /**
1801
- Define a new plugin field.
1802
- */
1803
- static define() { return new PluginField(); }
1804
- }
1805
- /**
1806
- This field can be used by plugins to provide
1807
- [decorations](https://codemirror.net/6/docs/ref/#view.Decoration).
1808
-
1809
- **Note**: For reasons of data flow (plugins are only updated
1810
- after the viewport is computed), decorations produced by plugins
1811
- are _not_ taken into account when predicting the vertical layout
1812
- structure of the editor. They **must not** introduce block
1813
- widgets (that will raise an error) or replacing decorations that
1814
- cover line breaks (these will be ignored if they occur). Such
1815
- decorations, or others that cause a large amount of vertical
1816
- size shift compared to the undecorated content, should be
1817
- provided through the state-level [`decorations`
1818
- facet](https://codemirror.net/6/docs/ref/#view.EditorView^decorations) instead.
1819
- */
1820
- PluginField.decorations = PluginField.define();
1821
- /**
1822
- Used to provide ranges that should be treated as atoms as far as
1823
- cursor motion is concerned. This causes methods like
1824
- [`moveByChar`](https://codemirror.net/6/docs/ref/#view.EditorView.moveByChar) and
1825
- [`moveVertically`](https://codemirror.net/6/docs/ref/#view.EditorView.moveVertically) (and the
1826
- commands built on top of them) to skip across such regions when
1827
- a selection endpoint would enter them. This does _not_ prevent
1828
- direct programmatic [selection
1829
- updates](https://codemirror.net/6/docs/ref/#state.TransactionSpec.selection) from moving into such
1830
- regions.
1831
- */
1832
- PluginField.atomicRanges = PluginField.define();
1833
- /**
1834
- Plugins can provide additional scroll margins (space around the
1835
- sides of the scrolling element that should be considered
1836
- invisible) through this field. This can be useful when the
1837
- plugin introduces elements that cover part of that element (for
1838
- example a horizontally fixed gutter).
1839
- */
1840
- PluginField.scrollMargins = PluginField.define();
1841
1754
  let nextPluginID = 0;
1842
1755
  const viewPlugin = state.Facet.define();
1843
1756
  /**
@@ -1858,27 +1771,29 @@ class ViewPlugin {
1858
1771
  /**
1859
1772
  @internal
1860
1773
  */
1861
- fields) {
1774
+ domEventHandlers, buildExtensions) {
1862
1775
  this.id = id;
1863
1776
  this.create = create;
1864
- this.fields = fields;
1865
- this.extension = viewPlugin.of(this);
1777
+ this.domEventHandlers = domEventHandlers;
1778
+ this.extension = buildExtensions(this);
1866
1779
  }
1867
1780
  /**
1868
1781
  Define a plugin from a constructor function that creates the
1869
1782
  plugin's value, given an editor view.
1870
1783
  */
1871
1784
  static define(create, spec) {
1872
- let { eventHandlers, provide, decorations } = spec || {};
1873
- let fields = [];
1874
- if (provide)
1875
- for (let provider of Array.isArray(provide) ? provide : [provide])
1876
- fields.push(provider);
1877
- if (eventHandlers)
1878
- fields.push(domEventHandlers.from((value) => ({ plugin: value, handlers: eventHandlers })));
1879
- if (decorations)
1880
- fields.push(PluginField.decorations.from(decorations));
1881
- return new ViewPlugin(nextPluginID++, create, fields);
1785
+ const { eventHandlers, provide, decorations: deco } = spec || {};
1786
+ return new ViewPlugin(nextPluginID++, create, eventHandlers, plugin => {
1787
+ let ext = [viewPlugin.of(plugin)];
1788
+ if (deco)
1789
+ ext.push(decorations.of(view => {
1790
+ let pluginInst = view.plugin(plugin);
1791
+ return pluginInst ? deco(pluginInst) : Decoration.none;
1792
+ }));
1793
+ if (provide)
1794
+ ext.push(provide(plugin));
1795
+ return ext;
1796
+ });
1882
1797
  }
1883
1798
  /**
1884
1799
  Create a plugin for a class whose constructor takes a single
@@ -1888,7 +1803,6 @@ class ViewPlugin {
1888
1803
  return ViewPlugin.define(view => new cls(view), spec);
1889
1804
  }
1890
1805
  }
1891
- const domEventHandlers = PluginField.define();
1892
1806
  class PluginInstance {
1893
1807
  constructor(spec) {
1894
1808
  this.spec = spec;
@@ -1901,12 +1815,6 @@ class PluginInstance {
1901
1815
  // initialized on the first update.
1902
1816
  this.value = null;
1903
1817
  }
1904
- takeField(type, target) {
1905
- if (this.spec)
1906
- for (let { field, get } of this.spec.fields)
1907
- if (field == type)
1908
- target.push(get(this.value));
1909
- }
1910
1818
  update(view) {
1911
1819
  if (!this.value) {
1912
1820
  if (this.spec) {
@@ -1958,6 +1866,8 @@ const editorAttributes = state.Facet.define();
1958
1866
  const contentAttributes = state.Facet.define();
1959
1867
  // Provide decorations
1960
1868
  const decorations = state.Facet.define();
1869
+ const atomicRanges = state.Facet.define();
1870
+ const scrollMargins = state.Facet.define();
1961
1871
  const styleModule = state.Facet.define();
1962
1872
  class ChangedRange {
1963
1873
  constructor(fromA, toA, fromB, toB) {
@@ -2058,8 +1968,8 @@ class ViewUpdate {
2058
1968
  return (this.flags & 4 /* Viewport */) > 0;
2059
1969
  }
2060
1970
  /**
2061
- Indicates whether the height of an element in the editor changed
2062
- in this update.
1971
+ Indicates whether the height of a block element in the editor
1972
+ changed in this update.
2063
1973
  */
2064
1974
  get heightChanged() {
2065
1975
  return (this.flags & 2 /* Height */) > 0;
@@ -2395,7 +2305,7 @@ function moveVisually(line, order, dir, start, forward) {
2395
2305
  startIndex = span.side(!forward, dir);
2396
2306
  }
2397
2307
  let indexForward = forward == (span.dir == dir);
2398
- let nextIndex = text.findClusterBreak(line.text, startIndex, indexForward);
2308
+ let nextIndex = state.findClusterBreak(line.text, startIndex, indexForward);
2399
2309
  movedOver = line.text.slice(Math.min(startIndex, nextIndex), Math.max(startIndex, nextIndex));
2400
2310
  if (nextIndex != span.side(forward, dir))
2401
2311
  return state.EditorSelection.cursor(nextIndex + line.from, indexForward ? -1 : 1, span.level);
@@ -2519,7 +2429,7 @@ class DocView extends ContentView {
2519
2429
  this.view = view;
2520
2430
  this.compositionDeco = Decoration.none;
2521
2431
  this.decorations = [];
2522
- this.pluginDecorationLength = 0;
2432
+ this.dynamicDecorationMap = [];
2523
2433
  // Track a minimum width for the editor. When measuring sizes in
2524
2434
  // measureVisibleLineHeights, this is updated to point at the width
2525
2435
  // of a given element and its extent in the document. When a change
@@ -2625,7 +2535,7 @@ class DocView extends ContentView {
2625
2535
  if (!next)
2626
2536
  break;
2627
2537
  let { fromA, toA, fromB, toB } = next;
2628
- let { content, breakAtStart, openStart, openEnd } = ContentBuilder.build(this.view.state.doc, fromB, toB, this.decorations, this.pluginDecorationLength);
2538
+ let { content, breakAtStart, openStart, openEnd } = ContentBuilder.build(this.view.state.doc, fromB, toB, this.decorations, this.dynamicDecorationMap);
2629
2539
  let { i: toI, off: toOff } = cursor.findPos(toA, 1);
2630
2540
  let { i: fromI, off: fromOff } = cursor.findPos(fromA, -1);
2631
2541
  replaceRange(this, fromI, fromOff, toI, toOff, content, breakAtStart, openStart, openEnd);
@@ -2766,11 +2676,11 @@ class DocView extends ContentView {
2766
2676
  off = start;
2767
2677
  }
2768
2678
  }
2769
- measureVisibleLineHeights() {
2770
- let result = [], { from, to } = this.view.viewState.viewport;
2679
+ measureVisibleLineHeights(viewport) {
2680
+ let result = [], { from, to } = viewport;
2771
2681
  let contentWidth = this.view.contentDOM.clientWidth;
2772
2682
  let isWider = contentWidth > Math.max(this.view.scrollDOM.clientWidth, this.minWidth) + 1;
2773
- let widest = -1;
2683
+ let widest = -1, ltr = this.view.textDirection == exports.Direction.LTR;
2774
2684
  for (let pos = 0, i = 0; i < this.children.length; i++) {
2775
2685
  let child = this.children[i], end = pos + child.length;
2776
2686
  if (end > to)
@@ -2783,8 +2693,7 @@ class DocView extends ContentView {
2783
2693
  let rects = last ? clientRectsFor(last) : [];
2784
2694
  if (rects.length) {
2785
2695
  let rect = rects[rects.length - 1];
2786
- let width = this.view.textDirection == exports.Direction.LTR ? rect.right - childRect.left
2787
- : childRect.right - rect.left;
2696
+ let width = ltr ? rect.right - childRect.left : childRect.right - rect.left;
2788
2697
  if (width > widest) {
2789
2698
  widest = width;
2790
2699
  this.minWidth = contentWidth;
@@ -2798,6 +2707,10 @@ class DocView extends ContentView {
2798
2707
  }
2799
2708
  return result;
2800
2709
  }
2710
+ textDirectionAt(pos) {
2711
+ let { i } = this.childPos(pos, 1);
2712
+ return getComputedStyle(this.children[i].dom).direction == "rtl" ? exports.Direction.RTL : exports.Direction.LTR;
2713
+ }
2801
2714
  measureTextSize() {
2802
2715
  for (let child of this.children) {
2803
2716
  if (child instanceof LineView) {
@@ -2849,11 +2762,14 @@ class DocView extends ContentView {
2849
2762
  return Decoration.set(deco);
2850
2763
  }
2851
2764
  updateDeco() {
2852
- let pluginDecorations = this.view.pluginField(PluginField.decorations);
2853
- this.pluginDecorationLength = pluginDecorations.length;
2765
+ let allDeco = this.view.state.facet(decorations).map((d, i) => {
2766
+ let dynamic = this.dynamicDecorationMap[i] = typeof d == "function";
2767
+ return dynamic ? d(this.view) : d;
2768
+ });
2769
+ for (let i = allDeco.length; i < allDeco.length + 3; i++)
2770
+ this.dynamicDecorationMap[i] = false;
2854
2771
  return this.decorations = [
2855
- ...pluginDecorations,
2856
- ...this.view.state.facet(decorations),
2772
+ ...allDeco,
2857
2773
  this.compositionDeco,
2858
2774
  this.computeBlockGapDeco(),
2859
2775
  this.view.viewState.lineGapDeco
@@ -2868,7 +2784,7 @@ class DocView extends ContentView {
2868
2784
  rect = { left: Math.min(rect.left, other.left), top: Math.min(rect.top, other.top),
2869
2785
  right: Math.max(rect.right, other.right), bottom: Math.max(rect.bottom, other.bottom) };
2870
2786
  let mLeft = 0, mRight = 0, mTop = 0, mBottom = 0;
2871
- for (let margins of this.view.pluginField(PluginField.scrollMargins))
2787
+ for (let margins of this.view.state.facet(scrollMargins).map(f => f(this.view)))
2872
2788
  if (margins) {
2873
2789
  let { left, right, top, bottom } = margins;
2874
2790
  if (left != null)
@@ -3010,7 +2926,7 @@ class DecorationComparator$1 {
3010
2926
  }
3011
2927
  function findChangedDeco(a, b, diff) {
3012
2928
  let comp = new DecorationComparator$1;
3013
- rangeset.RangeSet.compare(a, b, diff, comp);
2929
+ state.RangeSet.compare(a, b, diff, comp);
3014
2930
  return comp.changes;
3015
2931
  }
3016
2932
  function inUneditable(node, inside) {
@@ -3033,18 +2949,18 @@ function groupAt(state$1, pos, bias = 1) {
3033
2949
  bias = -1;
3034
2950
  let from = linePos, to = linePos;
3035
2951
  if (bias < 0)
3036
- from = text.findClusterBreak(line.text, linePos, false);
2952
+ from = state.findClusterBreak(line.text, linePos, false);
3037
2953
  else
3038
- to = text.findClusterBreak(line.text, linePos);
2954
+ to = state.findClusterBreak(line.text, linePos);
3039
2955
  let cat = categorize(line.text.slice(from, to));
3040
2956
  while (from > 0) {
3041
- let prev = text.findClusterBreak(line.text, from, false);
2957
+ let prev = state.findClusterBreak(line.text, from, false);
3042
2958
  if (categorize(line.text.slice(prev, from)) != cat)
3043
2959
  break;
3044
2960
  from = prev;
3045
2961
  }
3046
2962
  while (to < line.length) {
3047
- let next = text.findClusterBreak(line.text, to);
2963
+ let next = state.findClusterBreak(line.text, to);
3048
2964
  if (categorize(line.text.slice(to, next)) != cat)
3049
2965
  break;
3050
2966
  to = next;
@@ -3236,7 +3152,7 @@ function posAtCoordsImprecise(view, contentRect, block, x, y) {
3236
3152
  into += line * view.viewState.heightOracle.lineLength;
3237
3153
  }
3238
3154
  let content = view.state.sliceDoc(block.from, block.to);
3239
- return block.from + text.findColumn(content, into, view.state.tabSize);
3155
+ return block.from + state.findColumn(content, into, view.state.tabSize);
3240
3156
  }
3241
3157
  // In case of a high line height, Safari's caretRangeFromPoint treats
3242
3158
  // the space between lines as belonging to the last character of the
@@ -3257,7 +3173,8 @@ function moveToLineBoundary(view, start, forward, includeWrap) {
3257
3173
  : view.coordsAtPos(start.assoc < 0 && start.head > line.from ? start.head - 1 : start.head);
3258
3174
  if (coords) {
3259
3175
  let editorRect = view.dom.getBoundingClientRect();
3260
- let pos = view.posAtCoords({ x: forward == (view.textDirection == exports.Direction.LTR) ? editorRect.right - 1 : editorRect.left + 1,
3176
+ let direction = view.textDirectionAt(line.from);
3177
+ let pos = view.posAtCoords({ x: forward == (direction == exports.Direction.LTR) ? editorRect.right - 1 : editorRect.left + 1,
3261
3178
  y: (coords.top + coords.bottom) / 2 });
3262
3179
  if (pos != null)
3263
3180
  return state.EditorSelection.cursor(pos, forward ? -1 : 1);
@@ -3268,8 +3185,9 @@ function moveToLineBoundary(view, start, forward, includeWrap) {
3268
3185
  }
3269
3186
  function moveByChar(view, start, forward, by) {
3270
3187
  let line = view.state.doc.lineAt(start.head), spans = view.bidiSpans(line);
3188
+ let direction = view.textDirectionAt(line.from);
3271
3189
  for (let cur = start, check = null;;) {
3272
- let next = moveVisually(line, spans, view.textDirection, cur, forward), char = movedOver;
3190
+ let next = moveVisually(line, spans, direction, cur, forward), char = movedOver;
3273
3191
  if (!next) {
3274
3192
  if (line.number == (forward ? view.state.doc.lines : 1))
3275
3193
  return cur;
@@ -3327,7 +3245,7 @@ function moveVertically(view, start, forward, distance) {
3327
3245
  }
3328
3246
  }
3329
3247
  function skipAtoms(view, oldPos, pos) {
3330
- let atoms = view.pluginField(PluginField.atomicRanges);
3248
+ let atoms = view.state.facet(atomicRanges).map(f => f(view));
3331
3249
  for (;;) {
3332
3250
  let moved = false;
3333
3251
  for (let set of atoms) {
@@ -3389,7 +3307,6 @@ class InputState {
3389
3307
  this.registeredEvents.push(type);
3390
3308
  }
3391
3309
  this.notifiedFocused = view.hasFocus;
3392
- this.ensureHandlers(view);
3393
3310
  // On Safari adding an input event handler somehow prevents an
3394
3311
  // issue where the composition vanishes when you press enter.
3395
3312
  if (browser.safari)
@@ -3399,20 +3316,23 @@ class InputState {
3399
3316
  this.lastSelectionOrigin = origin;
3400
3317
  this.lastSelectionTime = Date.now();
3401
3318
  }
3402
- ensureHandlers(view) {
3403
- let handlers = this.customHandlers = view.pluginField(domEventHandlers);
3404
- for (let set of handlers) {
3405
- for (let type in set.handlers)
3406
- if (this.registeredEvents.indexOf(type) < 0 && type != "scroll") {
3407
- this.registeredEvents.push(type);
3408
- view.contentDOM.addEventListener(type, (event) => {
3409
- if (!eventBelongsToEditor(view, event))
3410
- return;
3411
- if (this.runCustomHandlers(type, view, event))
3412
- event.preventDefault();
3413
- });
3414
- }
3415
- }
3319
+ ensureHandlers(view, plugins) {
3320
+ var _a;
3321
+ let handlers;
3322
+ for (let plugin of plugins)
3323
+ if (handlers = (_a = plugin.update(view).spec) === null || _a === void 0 ? void 0 : _a.domEventHandlers) {
3324
+ this.customHandlers.push({ plugin: plugin.value, handlers });
3325
+ for (let type in handlers)
3326
+ if (this.registeredEvents.indexOf(type) < 0 && type != "scroll") {
3327
+ this.registeredEvents.push(type);
3328
+ view.contentDOM.addEventListener(type, (event) => {
3329
+ if (!eventBelongsToEditor(view, event))
3330
+ return;
3331
+ if (this.runCustomHandlers(type, view, event))
3332
+ event.preventDefault();
3333
+ });
3334
+ }
3335
+ }
3416
3336
  }
3417
3337
  runCustomHandlers(type, view, event) {
3418
3338
  for (let set of this.customHandlers) {
@@ -3490,7 +3410,7 @@ class InputState {
3490
3410
  // compositionend and keydown events are sometimes emitted in the
3491
3411
  // wrong order. The key event should still be ignored, even when
3492
3412
  // it happens after the compositionend event.
3493
- if (browser.safari && Date.now() - this.compositionEndedAt < 500) {
3413
+ if (browser.safari && Date.now() - this.compositionEndedAt < 100) {
3494
3414
  this.compositionEndedAt = 0;
3495
3415
  return true;
3496
3416
  }
@@ -3996,9 +3916,8 @@ handlers.beforeinput = (view, event) => {
3996
3916
  const wrappingWhiteSpace = ["pre-wrap", "normal", "pre-line", "break-spaces"];
3997
3917
  class HeightOracle {
3998
3918
  constructor() {
3999
- this.doc = text.Text.empty;
3919
+ this.doc = state.Text.empty;
4000
3920
  this.lineWrapping = false;
4001
- this.direction = exports.Direction.LTR;
4002
3921
  this.heightSamples = {};
4003
3922
  this.lineHeight = 14;
4004
3923
  this.charWidth = 7;
@@ -4019,8 +3938,8 @@ class HeightOracle {
4019
3938
  return lines * this.lineHeight;
4020
3939
  }
4021
3940
  setDoc(doc) { this.doc = doc; return this; }
4022
- mustRefreshForStyle(whiteSpace, direction) {
4023
- return (wrappingWhiteSpace.indexOf(whiteSpace) > -1) != this.lineWrapping || this.direction != direction;
3941
+ mustRefreshForWrapping(whiteSpace) {
3942
+ return (wrappingWhiteSpace.indexOf(whiteSpace) > -1) != this.lineWrapping;
4024
3943
  }
4025
3944
  mustRefreshForHeights(lineHeights) {
4026
3945
  let newHeight = false;
@@ -4036,13 +3955,10 @@ class HeightOracle {
4036
3955
  }
4037
3956
  return newHeight;
4038
3957
  }
4039
- refresh(whiteSpace, direction, lineHeight, charWidth, lineLength, knownHeights) {
3958
+ refresh(whiteSpace, lineHeight, charWidth, lineLength, knownHeights) {
4040
3959
  let lineWrapping = wrappingWhiteSpace.indexOf(whiteSpace) > -1;
4041
- let changed = Math.round(lineHeight) != Math.round(this.lineHeight) ||
4042
- this.lineWrapping != lineWrapping ||
4043
- this.direction != direction;
3960
+ let changed = Math.round(lineHeight) != Math.round(this.lineHeight) || this.lineWrapping != lineWrapping;
4044
3961
  this.lineWrapping = lineWrapping;
4045
- this.direction = direction;
4046
3962
  this.lineHeight = lineHeight;
4047
3963
  this.charWidth = charWidth;
4048
3964
  this.lineLength = lineLength;
@@ -4123,12 +4039,6 @@ class BlockInfo {
4123
4039
  .concat(Array.isArray(other.type) ? other.type : [other]);
4124
4040
  return new BlockInfo(this.from, this.length + other.length, this.top, this.height + other.height, detail);
4125
4041
  }
4126
- /**
4127
- FIXME remove on next breaking release @internal
4128
- */
4129
- moveY(offset) {
4130
- return !offset ? this : new BlockInfo(this.from, this.length, this.top + offset, this.height, Array.isArray(this.type) ? this.type.map(b => b.moveY(offset)) : this.type);
4131
- }
4132
4042
  }
4133
4043
  var QueryType;
4134
4044
  (function (QueryType) {
@@ -4253,8 +4163,9 @@ class HeightMapBlock extends HeightMap {
4253
4163
  lineAt(_value, _type, doc, top, offset) {
4254
4164
  return this.blockAt(0, doc, top, offset);
4255
4165
  }
4256
- forEachLine(_from, _to, doc, top, offset, f) {
4257
- f(this.blockAt(0, doc, top, offset));
4166
+ forEachLine(from, to, doc, top, offset, f) {
4167
+ if (from <= offset + this.length && to >= offset)
4168
+ f(this.blockAt(0, doc, top, offset));
4258
4169
  }
4259
4170
  updateHeight(oracle, offset = 0, _force = false, measured) {
4260
4171
  if (measured && measured.from <= offset && measured.more)
@@ -4636,13 +4547,13 @@ class NodeBuilder {
4636
4547
  // to each other.
4637
4548
  static build(oracle, decorations, from, to) {
4638
4549
  let builder = new NodeBuilder(from, oracle);
4639
- rangeset.RangeSet.spans(decorations, from, to, builder, 0);
4550
+ state.RangeSet.spans(decorations, from, to, builder, 0);
4640
4551
  return builder.finish(from);
4641
4552
  }
4642
4553
  }
4643
4554
  function heightRelevantDecoChanges(a, b, diff) {
4644
4555
  let comp = new DecorationComparator;
4645
- rangeset.RangeSet.compare(a, b, diff, comp, 0);
4556
+ state.RangeSet.compare(a, b, diff, comp, 0);
4646
4557
  return comp.changes;
4647
4558
  }
4648
4559
  class DecorationComparator {
@@ -4735,8 +4646,8 @@ class LineGapWidget extends WidgetType {
4735
4646
  get estimatedHeight() { return this.vertical ? this.size : -1; }
4736
4647
  }
4737
4648
  class ViewState {
4738
- constructor(state) {
4739
- this.state = state;
4649
+ constructor(state$1) {
4650
+ this.state = state$1;
4740
4651
  // These are contentDOM-local coordinates
4741
4652
  this.pixelViewport = { left: 0, right: window.innerWidth, top: 0, bottom: 0 };
4742
4653
  this.inView = true;
@@ -4755,6 +4666,7 @@ class ViewState {
4755
4666
  // Flag set when editor content was redrawn, so that the next
4756
4667
  // measure stage knows it must read DOM layout
4757
4668
  this.mustMeasureContent = true;
4669
+ this.defaultTextDirection = exports.Direction.RTL;
4758
4670
  this.visibleRanges = [];
4759
4671
  // Cursor 'assoc' is only significant when the cursor is on a line
4760
4672
  // wrap point, where it must stick to the character that it is
@@ -4765,7 +4677,8 @@ class ViewState {
4765
4677
  // boundary and, if so, reset it to make sure it is positioned in
4766
4678
  // the right place.
4767
4679
  this.mustEnforceCursorAssoc = false;
4768
- this.heightMap = HeightMap.empty().applyChanges(state.facet(decorations), text.Text.empty, this.heightOracle.setDoc(state.doc), [new ChangedRange(0, 0, 0, state.doc.length)]);
4680
+ this.stateDeco = state$1.facet(decorations).filter(d => typeof d != "function");
4681
+ this.heightMap = HeightMap.empty().applyChanges(this.stateDeco, state.Text.empty, this.heightOracle.setDoc(state$1.doc), [new ChangedRange(0, 0, 0, state$1.doc.length)]);
4769
4682
  this.viewport = this.getViewport(0, null);
4770
4683
  this.updateViewportLines();
4771
4684
  this.updateForViewport();
@@ -4793,13 +4706,13 @@ class ViewState {
4793
4706
  });
4794
4707
  }
4795
4708
  update(update, scrollTarget = null) {
4796
- let prev = this.state;
4797
4709
  this.state = update.state;
4798
- let newDeco = this.state.facet(decorations);
4710
+ let prevDeco = this.stateDeco;
4711
+ this.stateDeco = this.state.facet(decorations).filter(d => typeof d != "function");
4799
4712
  let contentChanges = update.changedRanges;
4800
- let heightChanges = ChangedRange.extendWithRanges(contentChanges, heightRelevantDecoChanges(update.startState.facet(decorations), newDeco, update ? update.changes : state.ChangeSet.empty(this.state.doc.length)));
4713
+ let heightChanges = ChangedRange.extendWithRanges(contentChanges, heightRelevantDecoChanges(prevDeco, this.stateDeco, update ? update.changes : state.ChangeSet.empty(this.state.doc.length)));
4801
4714
  let prevHeight = this.heightMap.height;
4802
- this.heightMap = this.heightMap.applyChanges(newDeco, prev.doc, this.heightOracle.setDoc(this.state.doc), heightChanges);
4715
+ this.heightMap = this.heightMap.applyChanges(this.stateDeco, update.startState.doc, this.heightOracle.setDoc(this.state.doc), heightChanges);
4803
4716
  if (this.heightMap.height != prevHeight)
4804
4717
  update.flags |= 2 /* Height */;
4805
4718
  let viewport = heightChanges.length ? this.mapViewport(this.viewport, update.changes) : this.viewport;
@@ -4824,8 +4737,9 @@ class ViewState {
4824
4737
  measure(view) {
4825
4738
  let dom = view.contentDOM, style = window.getComputedStyle(dom);
4826
4739
  let oracle = this.heightOracle;
4827
- let whiteSpace = style.whiteSpace, direction = style.direction == "rtl" ? exports.Direction.RTL : exports.Direction.LTR;
4828
- let refresh = this.heightOracle.mustRefreshForStyle(whiteSpace, direction);
4740
+ let whiteSpace = style.whiteSpace;
4741
+ this.defaultTextDirection = style.direction == "rtl" ? exports.Direction.RTL : exports.Direction.LTR;
4742
+ let refresh = this.heightOracle.mustRefreshForWrapping(whiteSpace);
4829
4743
  let measureContent = refresh || this.mustMeasureContent || this.contentDOMHeight != dom.clientHeight;
4830
4744
  let result = 0, bias = 0;
4831
4745
  if (this.editorWidth != view.scrollDOM.clientWidth) {
@@ -4864,12 +4778,12 @@ class ViewState {
4864
4778
  result |= 8 /* Geometry */;
4865
4779
  }
4866
4780
  if (measureContent) {
4867
- let lineHeights = view.docView.measureVisibleLineHeights();
4781
+ let lineHeights = view.docView.measureVisibleLineHeights(this.viewport);
4868
4782
  if (oracle.mustRefreshForHeights(lineHeights))
4869
4783
  refresh = true;
4870
4784
  if (refresh || oracle.lineWrapping && Math.abs(contentWidth - this.contentDOMWidth) > oracle.charWidth) {
4871
4785
  let { lineHeight, charWidth } = view.docView.measureTextSize();
4872
- refresh = oracle.refresh(whiteSpace, direction, lineHeight, charWidth, contentWidth / charWidth, lineHeights);
4786
+ refresh = oracle.refresh(whiteSpace, lineHeight, charWidth, contentWidth / charWidth, lineHeights);
4873
4787
  if (refresh) {
4874
4788
  view.docView.minWidth = 0;
4875
4789
  result |= 8 /* Geometry */;
@@ -4880,7 +4794,10 @@ class ViewState {
4880
4794
  else if (dTop < 0 && dBottom < 0)
4881
4795
  bias = Math.min(dTop, dBottom);
4882
4796
  oracle.heightChanged = false;
4883
- this.heightMap = this.heightMap.updateHeight(oracle, 0, refresh, new MeasuredHeights(this.viewport.from, lineHeights));
4797
+ for (let vp of this.viewports) {
4798
+ let heights = vp.from == this.viewport.from ? lineHeights : view.docView.measureVisibleLineHeights(vp);
4799
+ this.heightMap = this.heightMap.updateHeight(oracle, 0, refresh, new MeasuredHeights(vp.from, heights));
4800
+ }
4884
4801
  if (oracle.heightChanged)
4885
4802
  result |= 2 /* Height */;
4886
4803
  }
@@ -4966,12 +4883,12 @@ class ViewState {
4966
4883
  ensureLineGaps(current) {
4967
4884
  let gaps = [];
4968
4885
  // This won't work at all in predominantly right-to-left text.
4969
- if (this.heightOracle.direction != exports.Direction.LTR)
4886
+ if (this.defaultTextDirection != exports.Direction.LTR)
4970
4887
  return gaps;
4971
4888
  for (let line of this.viewportLines) {
4972
4889
  if (line.length < 4000 /* DoubleMargin */)
4973
4890
  continue;
4974
- let structure = lineStructure(line.from, line.to, this.state);
4891
+ let structure = lineStructure(line.from, line.to, this.stateDeco);
4975
4892
  if (structure.total < 4000 /* DoubleMargin */)
4976
4893
  continue;
4977
4894
  let viewFrom, viewTo;
@@ -5022,11 +4939,11 @@ class ViewState {
5022
4939
  }
5023
4940
  }
5024
4941
  computeVisibleRanges() {
5025
- let deco = this.state.facet(decorations);
4942
+ let deco = this.stateDeco;
5026
4943
  if (this.lineGaps.length)
5027
4944
  deco = deco.concat(this.lineGapDeco);
5028
4945
  let ranges = [];
5029
- rangeset.RangeSet.spans(deco, this.viewport.from, this.viewport.to, {
4946
+ state.RangeSet.spans(deco, this.viewport.from, this.viewport.to, {
5030
4947
  span(from, to) { ranges.push({ from, to }); },
5031
4948
  point() { }
5032
4949
  }, 20);
@@ -5058,9 +4975,9 @@ class Viewport {
5058
4975
  this.to = to;
5059
4976
  }
5060
4977
  }
5061
- function lineStructure(from, to, state) {
4978
+ function lineStructure(from, to, stateDeco) {
5062
4979
  let ranges = [], pos = from, total = 0;
5063
- rangeset.RangeSet.spans(state.facet(decorations), from, to, {
4980
+ state.RangeSet.spans(stateDeco, from, to, {
5064
4981
  span() { },
5065
4982
  point(from, to) {
5066
4983
  if (from > pos) {
@@ -5193,7 +5110,7 @@ function buildTheme(main, spec, scopes) {
5193
5110
  }
5194
5111
  });
5195
5112
  }
5196
- const baseTheme = buildTheme("." + baseThemeID, {
5113
+ const baseTheme$1 = buildTheme("." + baseThemeID, {
5197
5114
  "&.cm-editor": {
5198
5115
  position: "relative !important",
5199
5116
  boxSizing: "border-box",
@@ -5298,6 +5215,65 @@ const baseTheme = buildTheme("." + baseThemeID, {
5298
5215
  "&dark .cm-activeLine": { backgroundColor: "#223039" },
5299
5216
  "&light .cm-specialChar": { color: "red" },
5300
5217
  "&dark .cm-specialChar": { color: "#f78" },
5218
+ ".cm-gutters": {
5219
+ display: "flex",
5220
+ height: "100%",
5221
+ boxSizing: "border-box",
5222
+ left: 0,
5223
+ zIndex: 200
5224
+ },
5225
+ "&light .cm-gutters": {
5226
+ backgroundColor: "#f5f5f5",
5227
+ color: "#6c6c6c",
5228
+ borderRight: "1px solid #ddd"
5229
+ },
5230
+ "&dark .cm-gutters": {
5231
+ backgroundColor: "#333338",
5232
+ color: "#ccc"
5233
+ },
5234
+ ".cm-gutter": {
5235
+ display: "flex !important",
5236
+ flexDirection: "column",
5237
+ flexShrink: 0,
5238
+ boxSizing: "border-box",
5239
+ minHeight: "100%",
5240
+ overflow: "hidden"
5241
+ },
5242
+ ".cm-gutterElement": {
5243
+ boxSizing: "border-box"
5244
+ },
5245
+ ".cm-lineNumbers .cm-gutterElement": {
5246
+ padding: "0 3px 0 5px",
5247
+ minWidth: "20px",
5248
+ textAlign: "right",
5249
+ whiteSpace: "nowrap"
5250
+ },
5251
+ "&light .cm-activeLineGutter": {
5252
+ backgroundColor: "#e2f2ff"
5253
+ },
5254
+ "&dark .cm-activeLineGutter": {
5255
+ backgroundColor: "#222227"
5256
+ },
5257
+ ".cm-panels": {
5258
+ boxSizing: "border-box",
5259
+ position: "sticky",
5260
+ left: 0,
5261
+ right: 0
5262
+ },
5263
+ "&light .cm-panels": {
5264
+ backgroundColor: "#f5f5f5",
5265
+ color: "black"
5266
+ },
5267
+ "&light .cm-panels-top": {
5268
+ borderBottom: "1px solid #ddd"
5269
+ },
5270
+ "&light .cm-panels-bottom": {
5271
+ borderTop: "1px solid #ddd"
5272
+ },
5273
+ "&dark .cm-panels": {
5274
+ backgroundColor: "#333338",
5275
+ color: "white"
5276
+ },
5301
5277
  ".cm-tab": {
5302
5278
  display: "inline-block",
5303
5279
  overflow: "hidden",
@@ -5946,9 +5922,9 @@ transactions for editing actions.
5946
5922
  */
5947
5923
  class EditorView {
5948
5924
  /**
5949
- Construct a new view. You'll usually want to put `view.dom` into
5950
- your document after creating a view, so that the user can see
5951
- it.
5925
+ Construct a new view. You'll want to either provide a `parent`
5926
+ option, or put `view.dom` into your document after creating a
5927
+ view, so that the user can see the editor.
5952
5928
  */
5953
5929
  constructor(
5954
5930
  /**
@@ -5999,6 +5975,7 @@ class EditorView {
5999
5975
  this.measure();
6000
5976
  });
6001
5977
  this.inputState = new InputState(this);
5978
+ this.inputState.ensureHandlers(this, this.plugins);
6002
5979
  this.docView = new DocView(this);
6003
5980
  this.mountStyles();
6004
5981
  this.updateAttrs();
@@ -6086,14 +6063,9 @@ class EditorView {
6086
6063
  let { main } = tr.state.selection;
6087
6064
  scrollTarget = new ScrollTarget(main.empty ? main : state.EditorSelection.cursor(main.head, main.head > main.anchor ? -1 : 1));
6088
6065
  }
6089
- for (let e of tr.effects) {
6090
- if (e.is(scrollTo))
6091
- scrollTarget = new ScrollTarget(e.value);
6092
- else if (e.is(centerOn))
6093
- scrollTarget = new ScrollTarget(e.value, "center");
6094
- else if (e.is(scrollIntoView))
6066
+ for (let e of tr.effects)
6067
+ if (e.is(scrollIntoView))
6095
6068
  scrollTarget = e.value;
6096
- }
6097
6069
  }
6098
6070
  this.viewState.update(update, scrollTarget);
6099
6071
  this.bidiCache = CachedOrder.update(this.bidiCache, update.changes);
@@ -6144,7 +6116,7 @@ class EditorView {
6144
6116
  for (let plugin of this.plugins)
6145
6117
  plugin.update(this);
6146
6118
  this.docView = new DocView(this);
6147
- this.inputState.ensureHandlers(this);
6119
+ this.inputState.ensureHandlers(this, this.plugins);
6148
6120
  this.mountStyles();
6149
6121
  this.updateAttrs();
6150
6122
  this.bidiCache = [];
@@ -6176,7 +6148,7 @@ class EditorView {
6176
6148
  plugin.destroy(this);
6177
6149
  this.plugins = newPlugins;
6178
6150
  this.pluginMap.clear();
6179
- this.inputState.ensureHandlers(this);
6151
+ this.inputState.ensureHandlers(this, this.plugins);
6180
6152
  }
6181
6153
  else {
6182
6154
  for (let p of this.plugins)
@@ -6314,7 +6286,7 @@ class EditorView {
6314
6286
  }
6315
6287
  mountStyles() {
6316
6288
  this.styleModules = this.state.facet(styleModule);
6317
- styleMod.StyleModule.mount(this.root, this.styleModules.concat(baseTheme).reverse());
6289
+ styleMod.StyleModule.mount(this.root, this.styleModules.concat(baseTheme$1).reverse());
6318
6290
  }
6319
6291
  readMeasured() {
6320
6292
  if (this.updateState == 2 /* Updating */)
@@ -6345,16 +6317,6 @@ class EditorView {
6345
6317
  }
6346
6318
  }
6347
6319
  /**
6348
- Collect all values provided by the active plugins for a given
6349
- field.
6350
- */
6351
- pluginField(field) {
6352
- let result = [];
6353
- for (let plugin of this.plugins)
6354
- plugin.update(this).takeField(field, result);
6355
- return result;
6356
- }
6357
- /**
6358
6320
  Get the value of a specific plugin, if present. Note that
6359
6321
  plugins that crash can be dropped from a view, so even when you
6360
6322
  know you registered a given plugin, it is recommended to check
@@ -6381,23 +6343,6 @@ class EditorView {
6381
6343
  return { top: this.viewState.paddingTop, bottom: this.viewState.paddingBottom };
6382
6344
  }
6383
6345
  /**
6384
- Find the line or block widget at the given vertical position.
6385
-
6386
- By default, this position is interpreted as a screen position,
6387
- meaning `docTop` is set to the DOM top position of the editor
6388
- content (forcing a layout). You can pass a different `docTop`
6389
- value—for example 0 to interpret `height` as a document-relative
6390
- position, or a precomputed document top
6391
- (`view.contentDOM.getBoundingClientRect().top`) to limit layout
6392
- queries.
6393
-
6394
- *Deprecated: use `elementAtHeight` instead.*
6395
- */
6396
- blockAtHeight(height, docTop) {
6397
- let top = ensureTop(docTop, this);
6398
- return this.elementAtHeight(height - top).moveY(top);
6399
- }
6400
- /**
6401
6346
  Find the text line or block widget at the given vertical
6402
6347
  position (which is interpreted as relative to the [top of the
6403
6348
  document](https://codemirror.net/6/docs/ref/#view.EditorView.documentTop)
@@ -6407,23 +6352,6 @@ class EditorView {
6407
6352
  return this.viewState.elementAtHeight(height);
6408
6353
  }
6409
6354
  /**
6410
- Find information for the visual line (see
6411
- [`visualLineAt`](https://codemirror.net/6/docs/ref/#view.EditorView.visualLineAt)) at the given
6412
- vertical position. The resulting block info might hold another
6413
- array of block info structs in its `type` field if this line
6414
- consists of more than one block.
6415
-
6416
- Defaults to treating `height` as a screen position. See
6417
- [`blockAtHeight`](https://codemirror.net/6/docs/ref/#view.EditorView.blockAtHeight) for the
6418
- interpretation of the `docTop` parameter.
6419
-
6420
- *Deprecated: use `lineBlockAtHeight` instead.*
6421
- */
6422
- visualLineAtHeight(height, docTop) {
6423
- let top = ensureTop(docTop, this);
6424
- return this.lineBlockAtHeight(height - top).moveY(top);
6425
- }
6426
- /**
6427
6355
  Find the line block (see
6428
6356
  [`lineBlockAt`](https://codemirror.net/6/docs/ref/#view.EditorView.lineBlockAt) at the given
6429
6357
  height.
@@ -6433,19 +6361,6 @@ class EditorView {
6433
6361
  return this.viewState.lineBlockAtHeight(height);
6434
6362
  }
6435
6363
  /**
6436
- Iterate over the height information of the visual lines in the
6437
- viewport. The heights of lines are reported relative to the
6438
- given document top, which defaults to the screen position of the
6439
- document (forcing a layout).
6440
-
6441
- *Deprecated: use `viewportLineBlocks` instead.*
6442
- */
6443
- viewportLines(f, docTop) {
6444
- let top = ensureTop(docTop, this);
6445
- for (let line of this.viewportLineBlocks)
6446
- f(line.moveY(top));
6447
- }
6448
- /**
6449
6364
  Get the extent and vertical position of all [line
6450
6365
  blocks](https://codemirror.net/6/docs/ref/#view.EditorView.lineBlockAt) in the viewport. Positions
6451
6366
  are relative to the [top of the
@@ -6455,24 +6370,9 @@ class EditorView {
6455
6370
  return this.viewState.viewportLines;
6456
6371
  }
6457
6372
  /**
6458
- Find the extent and height of the visual line (a range delimited
6459
- on both sides by either non-[hidden](https://codemirror.net/6/docs/ref/#view.Decoration^range)
6460
- line breaks, or the start/end of the document) at the given position.
6461
-
6462
- Vertical positions are computed relative to the `docTop`
6463
- argument, which defaults to 0 for this method. You can pass
6464
- `view.contentDOM.getBoundingClientRect().top` here to get screen
6465
- coordinates.
6466
-
6467
- *Deprecated: use `lineBlockAt` instead.*
6468
- */
6469
- visualLineAt(pos, docTop = 0) {
6470
- return this.lineBlockAt(pos).moveY(docTop + this.viewState.paddingTop);
6471
- }
6472
- /**
6473
6373
  Find the line block around the given document position. A line
6474
6374
  block is a range delimited on both sides by either a
6475
- non-[hidden](https://codemirror.net/6/docs/ref/#view.Decoration^range) line breaks, or the
6375
+ non-[hidden](https://codemirror.net/6/docs/ref/#view.Decoration^replace) line breaks, or the
6476
6376
  start/end of the document. It will usually just hold a line of
6477
6377
  text, but may be broken into multiple textblocks by block
6478
6378
  widgets.
@@ -6488,13 +6388,13 @@ class EditorView {
6488
6388
  }
6489
6389
  /**
6490
6390
  Move a cursor position by [grapheme
6491
- cluster](https://codemirror.net/6/docs/ref/#text.findClusterBreak). `forward` determines whether
6492
- the motion is away from the line start, or towards it. Motion in
6493
- bidirectional text is in visual order, in the editor's [text
6494
- direction](https://codemirror.net/6/docs/ref/#view.EditorView.textDirection). When the start
6495
- position was the last one on the line, the returned position
6496
- will be across the line break. If there is no further line, the
6497
- original position is returned.
6391
+ cluster](https://codemirror.net/6/docs/ref/#state.findClusterBreak). `forward` determines whether
6392
+ the motion is away from the line start, or towards it. In
6393
+ bidirectional text, the line is traversed in visual order, using
6394
+ the editor's [text direction](https://codemirror.net/6/docs/ref/#view.EditorView.textDirection).
6395
+ When the start position was the last one on the line, the
6396
+ returned position will be across the line break. If there is no
6397
+ further line, the original position is returned.
6498
6398
 
6499
6399
  By default, this method moves over a single cluster. The
6500
6400
  optional `by` argument can be used to move across more. It will
@@ -6539,10 +6439,6 @@ class EditorView {
6539
6439
  moveVertically(start, forward, distance) {
6540
6440
  return skipAtoms(this, start, moveVertically(this, start, forward, distance));
6541
6441
  }
6542
- // FIXME remove on next major version
6543
- scrollPosIntoView(pos) {
6544
- this.dispatch({ effects: scrollTo.of(state.EditorSelection.cursor(pos)) });
6545
- }
6546
6442
  /**
6547
6443
  Find the DOM parent node and offset (child offset if `node` is
6548
6444
  an element, character offset when it is a text node) at the
@@ -6598,9 +6494,25 @@ class EditorView {
6598
6494
  /**
6599
6495
  The text direction
6600
6496
  ([`direction`](https://developer.mozilla.org/en-US/docs/Web/CSS/direction)
6601
- CSS property) of the editor.
6497
+ CSS property) of the editor's content element.
6498
+ */
6499
+ get textDirection() { return this.viewState.defaultTextDirection; }
6500
+ /**
6501
+ Find the text direction of the block at the given position, as
6502
+ assigned by CSS. If
6503
+ [`perLineTextDirection`](https://codemirror.net/6/docs/ref/#view.EditorView^perLineTextDirection)
6504
+ isn't enabled, or the given position is outside of the viewport,
6505
+ this will always return the same as
6506
+ [`textDirection`](https://codemirror.net/6/docs/ref/#view.EditorView.textDirection). Note that
6507
+ this may trigger a DOM layout.
6602
6508
  */
6603
- get textDirection() { return this.viewState.heightOracle.direction; }
6509
+ textDirectionAt(pos) {
6510
+ let perLine = this.state.facet(perLineTextDirection);
6511
+ if (!perLine || pos < this.viewport.from || pos > this.viewport.to)
6512
+ return this.textDirection;
6513
+ this.readMeasured();
6514
+ return this.docView.textDirectionAt(pos);
6515
+ }
6604
6516
  /**
6605
6517
  Whether this editor [wraps lines](https://codemirror.net/6/docs/ref/#view.EditorView.lineWrapping)
6606
6518
  (as determined by the
@@ -6619,11 +6531,11 @@ class EditorView {
6619
6531
  bidiSpans(line) {
6620
6532
  if (line.length > MaxBidiLine)
6621
6533
  return trivialOrder(line.length);
6622
- let dir = this.textDirection;
6534
+ let dir = this.textDirectionAt(line.from);
6623
6535
  for (let entry of this.bidiCache)
6624
6536
  if (entry.from == line.from && entry.dir == dir)
6625
6537
  return entry.order;
6626
- let order = computeOrder(line.text, this.textDirection);
6538
+ let order = computeOrder(line.text, dir);
6627
6539
  this.bidiCache.push(new CachedOrder(line.from, line.to, dir, order));
6628
6540
  return order;
6629
6541
  }
@@ -6674,16 +6586,16 @@ class EditorView {
6674
6586
  return scrollIntoView.of(new ScrollTarget(typeof pos == "number" ? state.EditorSelection.cursor(pos) : pos, options.y, options.x, options.yMargin, options.xMargin));
6675
6587
  }
6676
6588
  /**
6677
- Facet that can be used to add DOM event handlers. The value
6678
- should be an object mapping event names to handler functions. The
6679
- first such function to return true will be assumed to have handled
6680
- that event, and no other handlers or built-in behavior will be
6681
- activated for it.
6682
- These are registered on the [content
6683
- element](https://codemirror.net/6/docs/ref/#view.EditorView.contentDOM), except for `scroll`
6684
- handlers, which will be called any time the editor's [scroll
6685
- element](https://codemirror.net/6/docs/ref/#view.EditorView.scrollDOM) or one of its parent nodes
6686
- is scrolled.
6589
+ Returns an extension that can be used to add DOM event handlers.
6590
+ The value should be an object mapping event names to handler
6591
+ functions. For any given event, such functions are ordered by
6592
+ extension precedence, and the first handler to return true will
6593
+ be assumed to have handled that event, and no other handlers or
6594
+ built-in behavior will be activated for it. These are registered
6595
+ on the [content element](https://codemirror.net/6/docs/ref/#view.EditorView.contentDOM), except
6596
+ for `scroll` handlers, which will be called any time the
6597
+ editor's [scroll element](https://codemirror.net/6/docs/ref/#view.EditorView.scrollDOM) or one of
6598
+ its parent nodes is scrolled.
6687
6599
  */
6688
6600
  static domEventHandlers(handlers) {
6689
6601
  return ViewPlugin.define(() => ({}), { eventHandlers: handlers });
@@ -6725,20 +6637,6 @@ class EditorView {
6725
6637
  }
6726
6638
  }
6727
6639
  /**
6728
- Effect that can be [added](https://codemirror.net/6/docs/ref/#state.TransactionSpec.effects) to a
6729
- transaction to make it scroll the given range into view.
6730
-
6731
- *Deprecated*. Use [`scrollIntoView`](https://codemirror.net/6/docs/ref/#view.EditorView^scrollIntoView) instead.
6732
- */
6733
- EditorView.scrollTo = scrollTo;
6734
- /**
6735
- Effect that makes the editor scroll the given range to the
6736
- center of the visible view.
6737
-
6738
- *Deprecated*. Use [`scrollIntoView`](https://codemirror.net/6/docs/ref/#view.EditorView^scrollIntoView) instead.
6739
- */
6740
- EditorView.centerOn = centerOn;
6741
- /**
6742
6640
  Facet to add a [style
6743
6641
  module](https://github.com/marijnh/style-mod#documentation) to
6744
6642
  an editor view. The view will ensure that the module is
@@ -6755,6 +6653,13 @@ called and the default behavior is prevented.
6755
6653
  */
6756
6654
  EditorView.inputHandler = inputHandler;
6757
6655
  /**
6656
+ By default, the editor assumes all its content has the same
6657
+ [text direction](https://codemirror.net/6/docs/ref/#view.Direction). Configure this with a `true`
6658
+ value to make it read and store the text direction of every
6659
+ (rendered) line separately.
6660
+ */
6661
+ EditorView.perLineTextDirection = perLineTextDirection;
6662
+ /**
6758
6663
  Allows you to provide a function that should be called when the
6759
6664
  library catches an exception from an extension (mostly from view
6760
6665
  plugins, but may be used by other extensions to route exceptions
@@ -6770,9 +6675,9 @@ EditorView.updateListener = updateListener;
6770
6675
  /**
6771
6676
  Facet that controls whether the editor content DOM is editable.
6772
6677
  When its highest-precedence value is `false`, the element will
6773
- not longer have its `contenteditable` attribute set. (Note that
6774
- this doesn't affect API calls that change the editor content,
6775
- even when those are bound to keys or buttons. See the
6678
+ not have its `contenteditable` attribute set. (Note that this
6679
+ doesn't affect API calls that change the editor content, even
6680
+ when those are bound to keys or buttons. See the
6776
6681
  [`readOnly`](https://codemirror.net/6/docs/ref/#state.EditorState.readOnly) facet for that.)
6777
6682
  */
6778
6683
  EditorView.editable = editable;
@@ -6791,18 +6696,45 @@ the drag should move the content.
6791
6696
  */
6792
6697
  EditorView.dragMovesSelection = dragMovesSelection$1;
6793
6698
  /**
6794
- Facet used to configure whether a given selecting click adds
6795
- a new range to the existing selection or replaces it entirely.
6699
+ Facet used to configure whether a given selecting click adds a
6700
+ new range to the existing selection or replaces it entirely. The
6701
+ default behavior is to check `event.metaKey` on macOS, and
6702
+ `event.ctrlKey` elsewhere.
6796
6703
  */
6797
6704
  EditorView.clickAddsSelectionRange = clickAddsSelectionRange;
6798
6705
  /**
6799
6706
  A facet that determines which [decorations](https://codemirror.net/6/docs/ref/#view.Decoration)
6800
- are shown in the view. See also [view
6801
- plugins](https://codemirror.net/6/docs/ref/#view.EditorView^decorations), which have a separate
6802
- mechanism for providing decorations.
6707
+ are shown in the view. Decorations can be provided in two
6708
+ ways—directly, or via a function that takes an editor view.
6709
+
6710
+ Only decoration sets provided directly are allowed to influence
6711
+ the editor's vertical layout structure. The ones provided as
6712
+ functions are called _after_ the new viewport has been computed,
6713
+ and thus **must not** introduce block widgets or replacing
6714
+ decorations that cover line breaks.
6803
6715
  */
6804
6716
  EditorView.decorations = decorations;
6805
6717
  /**
6718
+ Used to provide ranges that should be treated as atoms as far as
6719
+ cursor motion is concerned. This causes methods like
6720
+ [`moveByChar`](https://codemirror.net/6/docs/ref/#view.EditorView.moveByChar) and
6721
+ [`moveVertically`](https://codemirror.net/6/docs/ref/#view.EditorView.moveVertically) (and the
6722
+ commands built on top of them) to skip across such regions when
6723
+ a selection endpoint would enter them. This does _not_ prevent
6724
+ direct programmatic [selection
6725
+ updates](https://codemirror.net/6/docs/ref/#state.TransactionSpec.selection) from moving into such
6726
+ regions.
6727
+ */
6728
+ EditorView.atomicRanges = atomicRanges;
6729
+ /**
6730
+ Facet that allows extensions to provide additional scroll
6731
+ margins (space around the sides of the scrolling element that
6732
+ should be considered invisible). This can be useful when the
6733
+ plugin introduces elements that cover part of that element (for
6734
+ example a horizontally fixed gutter).
6735
+ */
6736
+ EditorView.scrollMargins = scrollMargins;
6737
+ /**
6806
6738
  This facet records whether a dark theme is active. The extension
6807
6739
  returned by [`theme`](https://codemirror.net/6/docs/ref/#view.EditorView^theme) automatically
6808
6740
  includes an instance of this when the `dark` option is set to
@@ -6835,10 +6767,6 @@ search match).
6835
6767
  EditorView.announce = state.StateEffect.define();
6836
6768
  // Maximum line length for which we compute accurate bidi info
6837
6769
  const MaxBidiLine = 4096;
6838
- // FIXME remove this and its callers on next breaking release
6839
- function ensureTop(given, view) {
6840
- return (given == null ? view.contentDOM.getBoundingClientRect().top : given) + view.viewState.paddingTop;
6841
- }
6842
6770
  const BadMeasure = {};
6843
6771
  class CachedOrder {
6844
6772
  constructor(from, to, dir, order) {
@@ -6941,7 +6869,7 @@ function getKeymap(state) {
6941
6869
  }
6942
6870
  /**
6943
6871
  Run the key handlers registered for a given scope. The event
6944
- object should be `"keydown"` event. Returns true if any of the
6872
+ object should be a `"keydown"` event. Returns true if any of the
6945
6873
  handlers handled it.
6946
6874
  */
6947
6875
  function runScopeHandlers(view, event, scope) {
@@ -7421,7 +7349,7 @@ class MatchDecorator {
7421
7349
  plugin.
7422
7350
  */
7423
7351
  createDeco(view) {
7424
- let build = new rangeset.RangeSetBuilder();
7352
+ let build = new state.RangeSetBuilder();
7425
7353
  for (let { from, to } of matchRanges(view, this.maxLength))
7426
7354
  iterMatches(view.state.doc, this.regexp, from, to, (a, b, m) => build.add(a, b, this.getDeco(m, view, a)));
7427
7355
  return build.finish();
@@ -7553,10 +7481,10 @@ function specialCharPlugin() {
7553
7481
  regexp: conf.specialChars,
7554
7482
  decoration: (m, view, pos) => {
7555
7483
  let { doc } = view.state;
7556
- let code = text.codePointAt(m[0], 0);
7484
+ let code = state.codePointAt(m[0], 0);
7557
7485
  if (code == 9) {
7558
7486
  let line = doc.lineAt(pos);
7559
- let size = view.state.tabSize, col = text.countColumn(line.text, size, pos - line.from);
7487
+ let size = view.state.tabSize, col = state.countColumn(line.text, size, pos - line.from);
7560
7488
  return Decoration.replace({ widget: new TabWidget((size - (col % size)) * this.view.defaultCharacterWidth) });
7561
7489
  }
7562
7490
  return this.decorationCache[code] ||
@@ -7718,32 +7646,1338 @@ function placeholder(content) {
7718
7646
  }, { decorations: v => v.decorations });
7719
7647
  }
7720
7648
 
7649
+ // Don't compute precise column positions for line offsets above this
7650
+ // (since it could get expensive). Assume offset==column for them.
7651
+ const MaxOff = 2000;
7652
+ function rectangleFor(state$1, a, b) {
7653
+ let startLine = Math.min(a.line, b.line), endLine = Math.max(a.line, b.line);
7654
+ let ranges = [];
7655
+ if (a.off > MaxOff || b.off > MaxOff || a.col < 0 || b.col < 0) {
7656
+ let startOff = Math.min(a.off, b.off), endOff = Math.max(a.off, b.off);
7657
+ for (let i = startLine; i <= endLine; i++) {
7658
+ let line = state$1.doc.line(i);
7659
+ if (line.length <= endOff)
7660
+ ranges.push(state.EditorSelection.range(line.from + startOff, line.to + endOff));
7661
+ }
7662
+ }
7663
+ else {
7664
+ let startCol = Math.min(a.col, b.col), endCol = Math.max(a.col, b.col);
7665
+ for (let i = startLine; i <= endLine; i++) {
7666
+ let line = state$1.doc.line(i);
7667
+ let start = state.findColumn(line.text, startCol, state$1.tabSize, true);
7668
+ if (start > -1) {
7669
+ let end = state.findColumn(line.text, endCol, state$1.tabSize);
7670
+ ranges.push(state.EditorSelection.range(line.from + start, line.from + end));
7671
+ }
7672
+ }
7673
+ }
7674
+ return ranges;
7675
+ }
7676
+ function absoluteColumn(view, x) {
7677
+ let ref = view.coordsAtPos(view.viewport.from);
7678
+ return ref ? Math.round(Math.abs((ref.left - x) / view.defaultCharacterWidth)) : -1;
7679
+ }
7680
+ function getPos(view, event) {
7681
+ let offset = view.posAtCoords({ x: event.clientX, y: event.clientY }, false);
7682
+ let line = view.state.doc.lineAt(offset), off = offset - line.from;
7683
+ let col = off > MaxOff ? -1
7684
+ : off == line.length ? absoluteColumn(view, event.clientX)
7685
+ : state.countColumn(line.text, view.state.tabSize, offset - line.from);
7686
+ return { line: line.number, col, off };
7687
+ }
7688
+ function rectangleSelectionStyle(view, event) {
7689
+ let start = getPos(view, event), startSel = view.state.selection;
7690
+ if (!start)
7691
+ return null;
7692
+ return {
7693
+ update(update) {
7694
+ if (update.docChanged) {
7695
+ let newStart = update.changes.mapPos(update.startState.doc.line(start.line).from);
7696
+ let newLine = update.state.doc.lineAt(newStart);
7697
+ start = { line: newLine.number, col: start.col, off: Math.min(start.off, newLine.length) };
7698
+ startSel = startSel.map(update.changes);
7699
+ }
7700
+ },
7701
+ get(event, _extend, multiple) {
7702
+ let cur = getPos(view, event);
7703
+ if (!cur)
7704
+ return startSel;
7705
+ let ranges = rectangleFor(view.state, start, cur);
7706
+ if (!ranges.length)
7707
+ return startSel;
7708
+ if (multiple)
7709
+ return state.EditorSelection.create(ranges.concat(startSel.ranges));
7710
+ else
7711
+ return state.EditorSelection.create(ranges);
7712
+ }
7713
+ };
7714
+ }
7715
+ /**
7716
+ Create an extension that enables rectangular selections. By
7717
+ default, it will react to left mouse drag with the Alt key held
7718
+ down. When such a selection occurs, the text within the rectangle
7719
+ that was dragged over will be selected, as one selection
7720
+ [range](https://codemirror.net/6/docs/ref/#state.SelectionRange) per line.
7721
+ */
7722
+ function rectangularSelection(options) {
7723
+ let filter = (options === null || options === void 0 ? void 0 : options.eventFilter) || (e => e.altKey && e.button == 0);
7724
+ return EditorView.mouseSelectionStyle.of((view, event) => filter(event) ? rectangleSelectionStyle(view, event) : null);
7725
+ }
7726
+ const keys = {
7727
+ Alt: [18, e => e.altKey],
7728
+ Control: [17, e => e.ctrlKey],
7729
+ Shift: [16, e => e.shiftKey],
7730
+ Meta: [91, e => e.metaKey]
7731
+ };
7732
+ const showCrosshair = { style: "cursor: crosshair" };
7733
+ /**
7734
+ Returns an extension that turns the pointer cursor into a
7735
+ crosshair when a given modifier key, defaulting to Alt, is held
7736
+ down. Can serve as a visual hint that rectangular selection is
7737
+ going to happen when paired with
7738
+ [`rectangularSelection`](https://codemirror.net/6/docs/ref/#view.rectangularSelection).
7739
+ */
7740
+ function crosshairCursor(options = {}) {
7741
+ let [code, getter] = keys[options.key || "Alt"];
7742
+ let plugin = ViewPlugin.fromClass(class {
7743
+ constructor(view) {
7744
+ this.view = view;
7745
+ this.isDown = false;
7746
+ }
7747
+ set(isDown) {
7748
+ if (this.isDown != isDown) {
7749
+ this.isDown = isDown;
7750
+ this.view.update([]);
7751
+ }
7752
+ }
7753
+ }, {
7754
+ eventHandlers: {
7755
+ keydown(e) {
7756
+ this.set(e.keyCode == code || getter(e));
7757
+ },
7758
+ keyup(e) {
7759
+ if (e.keyCode == code || !getter(e))
7760
+ this.set(false);
7761
+ }
7762
+ }
7763
+ });
7764
+ return [
7765
+ plugin,
7766
+ EditorView.contentAttributes.of(view => { var _a; return ((_a = view.plugin(plugin)) === null || _a === void 0 ? void 0 : _a.isDown) ? showCrosshair : null; })
7767
+ ];
7768
+ }
7769
+
7770
+ const Outside = "-10000px";
7771
+ class TooltipViewManager {
7772
+ constructor(view, facet, createTooltipView) {
7773
+ this.facet = facet;
7774
+ this.createTooltipView = createTooltipView;
7775
+ this.input = view.state.facet(facet);
7776
+ this.tooltips = this.input.filter(t => t);
7777
+ this.tooltipViews = this.tooltips.map(createTooltipView);
7778
+ }
7779
+ update(update) {
7780
+ let input = update.state.facet(this.facet);
7781
+ let tooltips = input.filter(x => x);
7782
+ if (input === this.input) {
7783
+ for (let t of this.tooltipViews)
7784
+ if (t.update)
7785
+ t.update(update);
7786
+ return false;
7787
+ }
7788
+ let tooltipViews = [];
7789
+ for (let i = 0; i < tooltips.length; i++) {
7790
+ let tip = tooltips[i], known = -1;
7791
+ if (!tip)
7792
+ continue;
7793
+ for (let i = 0; i < this.tooltips.length; i++) {
7794
+ let other = this.tooltips[i];
7795
+ if (other && other.create == tip.create)
7796
+ known = i;
7797
+ }
7798
+ if (known < 0) {
7799
+ tooltipViews[i] = this.createTooltipView(tip);
7800
+ }
7801
+ else {
7802
+ let tooltipView = tooltipViews[i] = this.tooltipViews[known];
7803
+ if (tooltipView.update)
7804
+ tooltipView.update(update);
7805
+ }
7806
+ }
7807
+ for (let t of this.tooltipViews)
7808
+ if (tooltipViews.indexOf(t) < 0)
7809
+ t.dom.remove();
7810
+ this.input = input;
7811
+ this.tooltips = tooltips;
7812
+ this.tooltipViews = tooltipViews;
7813
+ return true;
7814
+ }
7815
+ }
7816
+ /**
7817
+ Creates an extension that configures tooltip behavior.
7818
+ */
7819
+ function tooltips(config = {}) {
7820
+ return tooltipConfig.of(config);
7821
+ }
7822
+ function windowSpace() {
7823
+ return { top: 0, left: 0, bottom: innerHeight, right: innerWidth };
7824
+ }
7825
+ const tooltipConfig = state.Facet.define({
7826
+ combine: values => {
7827
+ var _a, _b, _c;
7828
+ return ({
7829
+ position: browser.ios ? "absolute" : ((_a = values.find(conf => conf.position)) === null || _a === void 0 ? void 0 : _a.position) || "fixed",
7830
+ parent: ((_b = values.find(conf => conf.parent)) === null || _b === void 0 ? void 0 : _b.parent) || null,
7831
+ tooltipSpace: ((_c = values.find(conf => conf.tooltipSpace)) === null || _c === void 0 ? void 0 : _c.tooltipSpace) || windowSpace,
7832
+ });
7833
+ }
7834
+ });
7835
+ const tooltipPlugin = ViewPlugin.fromClass(class {
7836
+ constructor(view) {
7837
+ var _a;
7838
+ this.view = view;
7839
+ this.inView = true;
7840
+ this.lastTransaction = 0;
7841
+ this.measureTimeout = -1;
7842
+ let config = view.state.facet(tooltipConfig);
7843
+ this.position = config.position;
7844
+ this.parent = config.parent;
7845
+ this.classes = view.themeClasses;
7846
+ this.createContainer();
7847
+ this.measureReq = { read: this.readMeasure.bind(this), write: this.writeMeasure.bind(this), key: this };
7848
+ this.manager = new TooltipViewManager(view, showTooltip, t => this.createTooltip(t));
7849
+ this.intersectionObserver = typeof IntersectionObserver == "function" ? new IntersectionObserver(entries => {
7850
+ if (Date.now() > this.lastTransaction - 50 &&
7851
+ entries.length > 0 && entries[entries.length - 1].intersectionRatio < 1)
7852
+ this.measureSoon();
7853
+ }, { threshold: [1] }) : null;
7854
+ this.observeIntersection();
7855
+ (_a = view.dom.ownerDocument.defaultView) === null || _a === void 0 ? void 0 : _a.addEventListener("resize", this.measureSoon = this.measureSoon.bind(this));
7856
+ this.maybeMeasure();
7857
+ }
7858
+ createContainer() {
7859
+ if (this.parent) {
7860
+ this.container = document.createElement("div");
7861
+ this.container.style.position = "relative";
7862
+ this.container.className = this.view.themeClasses;
7863
+ this.parent.appendChild(this.container);
7864
+ }
7865
+ else {
7866
+ this.container = this.view.dom;
7867
+ }
7868
+ }
7869
+ observeIntersection() {
7870
+ if (this.intersectionObserver) {
7871
+ this.intersectionObserver.disconnect();
7872
+ for (let tooltip of this.manager.tooltipViews)
7873
+ this.intersectionObserver.observe(tooltip.dom);
7874
+ }
7875
+ }
7876
+ measureSoon() {
7877
+ if (this.measureTimeout < 0)
7878
+ this.measureTimeout = setTimeout(() => {
7879
+ this.measureTimeout = -1;
7880
+ this.maybeMeasure();
7881
+ }, 50);
7882
+ }
7883
+ update(update) {
7884
+ if (update.transactions.length)
7885
+ this.lastTransaction = Date.now();
7886
+ let updated = this.manager.update(update);
7887
+ if (updated)
7888
+ this.observeIntersection();
7889
+ let shouldMeasure = updated || update.geometryChanged;
7890
+ let newConfig = update.state.facet(tooltipConfig);
7891
+ if (newConfig.position != this.position) {
7892
+ this.position = newConfig.position;
7893
+ for (let t of this.manager.tooltipViews)
7894
+ t.dom.style.position = this.position;
7895
+ shouldMeasure = true;
7896
+ }
7897
+ if (newConfig.parent != this.parent) {
7898
+ if (this.parent)
7899
+ this.container.remove();
7900
+ this.parent = newConfig.parent;
7901
+ this.createContainer();
7902
+ for (let t of this.manager.tooltipViews)
7903
+ this.container.appendChild(t.dom);
7904
+ shouldMeasure = true;
7905
+ }
7906
+ else if (this.parent && this.view.themeClasses != this.classes) {
7907
+ this.classes = this.container.className = this.view.themeClasses;
7908
+ }
7909
+ if (shouldMeasure)
7910
+ this.maybeMeasure();
7911
+ }
7912
+ createTooltip(tooltip) {
7913
+ let tooltipView = tooltip.create(this.view);
7914
+ tooltipView.dom.classList.add("cm-tooltip");
7915
+ if (tooltip.arrow && !tooltipView.dom.querySelector(".cm-tooltip > .cm-tooltip-arrow")) {
7916
+ let arrow = document.createElement("div");
7917
+ arrow.className = "cm-tooltip-arrow";
7918
+ tooltipView.dom.appendChild(arrow);
7919
+ }
7920
+ tooltipView.dom.style.position = this.position;
7921
+ tooltipView.dom.style.top = Outside;
7922
+ this.container.appendChild(tooltipView.dom);
7923
+ if (tooltipView.mount)
7924
+ tooltipView.mount(this.view);
7925
+ return tooltipView;
7926
+ }
7927
+ destroy() {
7928
+ var _a, _b;
7929
+ (_a = this.view.dom.ownerDocument.defaultView) === null || _a === void 0 ? void 0 : _a.removeEventListener("resize", this.measureSoon);
7930
+ for (let { dom } of this.manager.tooltipViews)
7931
+ dom.remove();
7932
+ (_b = this.intersectionObserver) === null || _b === void 0 ? void 0 : _b.disconnect();
7933
+ clearTimeout(this.measureTimeout);
7934
+ }
7935
+ readMeasure() {
7936
+ let editor = this.view.dom.getBoundingClientRect();
7937
+ return {
7938
+ editor,
7939
+ parent: this.parent ? this.container.getBoundingClientRect() : editor,
7940
+ pos: this.manager.tooltips.map((t, i) => {
7941
+ let tv = this.manager.tooltipViews[i];
7942
+ return tv.getCoords ? tv.getCoords(t.pos) : this.view.coordsAtPos(t.pos);
7943
+ }),
7944
+ size: this.manager.tooltipViews.map(({ dom }) => dom.getBoundingClientRect()),
7945
+ space: this.view.state.facet(tooltipConfig).tooltipSpace(this.view),
7946
+ };
7947
+ }
7948
+ writeMeasure(measured) {
7949
+ let { editor, space } = measured;
7950
+ let others = [];
7951
+ for (let i = 0; i < this.manager.tooltips.length; i++) {
7952
+ let tooltip = this.manager.tooltips[i], tView = this.manager.tooltipViews[i], { dom } = tView;
7953
+ let pos = measured.pos[i], size = measured.size[i];
7954
+ // Hide tooltips that are outside of the editor.
7955
+ if (!pos || pos.bottom <= Math.max(editor.top, space.top) ||
7956
+ pos.top >= Math.min(editor.bottom, space.bottom) ||
7957
+ pos.right < Math.max(editor.left, space.left) - .1 ||
7958
+ pos.left > Math.min(editor.right, space.right) + .1) {
7959
+ dom.style.top = Outside;
7960
+ continue;
7961
+ }
7962
+ let arrow = tooltip.arrow ? tView.dom.querySelector(".cm-tooltip-arrow") : null;
7963
+ let arrowHeight = arrow ? 7 /* Size */ : 0;
7964
+ let width = size.right - size.left, height = size.bottom - size.top;
7965
+ let offset = tView.offset || noOffset, ltr = this.view.textDirection == exports.Direction.LTR;
7966
+ let left = size.width > space.right - space.left ? (ltr ? space.left : space.right - size.width)
7967
+ : ltr ? Math.min(pos.left - (arrow ? 14 /* Offset */ : 0) + offset.x, space.right - width)
7968
+ : Math.max(space.left, pos.left - width + (arrow ? 14 /* Offset */ : 0) - offset.x);
7969
+ let above = !!tooltip.above;
7970
+ if (!tooltip.strictSide && (above
7971
+ ? pos.top - (size.bottom - size.top) - offset.y < space.top
7972
+ : pos.bottom + (size.bottom - size.top) + offset.y > space.bottom) &&
7973
+ above == (space.bottom - pos.bottom > pos.top - space.top))
7974
+ above = !above;
7975
+ let top = above ? pos.top - height - arrowHeight - offset.y : pos.bottom + arrowHeight + offset.y;
7976
+ let right = left + width;
7977
+ if (tView.overlap !== true)
7978
+ for (let r of others)
7979
+ if (r.left < right && r.right > left && r.top < top + height && r.bottom > top)
7980
+ top = above ? r.top - height - 2 - arrowHeight : r.bottom + arrowHeight + 2;
7981
+ if (this.position == "absolute") {
7982
+ dom.style.top = (top - measured.parent.top) + "px";
7983
+ dom.style.left = (left - measured.parent.left) + "px";
7984
+ }
7985
+ else {
7986
+ dom.style.top = top + "px";
7987
+ dom.style.left = left + "px";
7988
+ }
7989
+ if (arrow)
7990
+ arrow.style.left = `${pos.left + (ltr ? offset.x : -offset.x) - (left + 14 /* Offset */ - 7 /* Size */)}px`;
7991
+ if (tView.overlap !== true)
7992
+ others.push({ left, top, right, bottom: top + height });
7993
+ dom.classList.toggle("cm-tooltip-above", above);
7994
+ dom.classList.toggle("cm-tooltip-below", !above);
7995
+ if (tView.positioned)
7996
+ tView.positioned();
7997
+ }
7998
+ }
7999
+ maybeMeasure() {
8000
+ if (this.manager.tooltips.length) {
8001
+ if (this.view.inView)
8002
+ this.view.requestMeasure(this.measureReq);
8003
+ if (this.inView != this.view.inView) {
8004
+ this.inView = this.view.inView;
8005
+ if (!this.inView)
8006
+ for (let tv of this.manager.tooltipViews)
8007
+ tv.dom.style.top = Outside;
8008
+ }
8009
+ }
8010
+ }
8011
+ }, {
8012
+ eventHandlers: {
8013
+ scroll() { this.maybeMeasure(); }
8014
+ }
8015
+ });
8016
+ const baseTheme = EditorView.baseTheme({
8017
+ ".cm-tooltip": {
8018
+ zIndex: 100
8019
+ },
8020
+ "&light .cm-tooltip": {
8021
+ border: "1px solid #bbb",
8022
+ backgroundColor: "#f5f5f5"
8023
+ },
8024
+ "&light .cm-tooltip-section:not(:first-child)": {
8025
+ borderTop: "1px solid #bbb",
8026
+ },
8027
+ "&dark .cm-tooltip": {
8028
+ backgroundColor: "#333338",
8029
+ color: "white"
8030
+ },
8031
+ ".cm-tooltip-arrow": {
8032
+ height: `${7 /* Size */}px`,
8033
+ width: `${7 /* Size */ * 2}px`,
8034
+ position: "absolute",
8035
+ zIndex: -1,
8036
+ overflow: "hidden",
8037
+ "&:before, &:after": {
8038
+ content: "''",
8039
+ position: "absolute",
8040
+ width: 0,
8041
+ height: 0,
8042
+ borderLeft: `${7 /* Size */}px solid transparent`,
8043
+ borderRight: `${7 /* Size */}px solid transparent`,
8044
+ },
8045
+ ".cm-tooltip-above &": {
8046
+ bottom: `-${7 /* Size */}px`,
8047
+ "&:before": {
8048
+ borderTop: `${7 /* Size */}px solid #bbb`,
8049
+ },
8050
+ "&:after": {
8051
+ borderTop: `${7 /* Size */}px solid #f5f5f5`,
8052
+ bottom: "1px"
8053
+ }
8054
+ },
8055
+ ".cm-tooltip-below &": {
8056
+ top: `-${7 /* Size */}px`,
8057
+ "&:before": {
8058
+ borderBottom: `${7 /* Size */}px solid #bbb`,
8059
+ },
8060
+ "&:after": {
8061
+ borderBottom: `${7 /* Size */}px solid #f5f5f5`,
8062
+ top: "1px"
8063
+ }
8064
+ },
8065
+ },
8066
+ "&dark .cm-tooltip .cm-tooltip-arrow": {
8067
+ "&:before": {
8068
+ borderTopColor: "#333338",
8069
+ borderBottomColor: "#333338"
8070
+ },
8071
+ "&:after": {
8072
+ borderTopColor: "transparent",
8073
+ borderBottomColor: "transparent"
8074
+ }
8075
+ }
8076
+ });
8077
+ const noOffset = { x: 0, y: 0 };
8078
+ /**
8079
+ Facet to which an extension can add a value to show a tooltip.
8080
+ */
8081
+ const showTooltip = state.Facet.define({
8082
+ enables: [tooltipPlugin, baseTheme]
8083
+ });
8084
+ const showHoverTooltip = state.Facet.define({
8085
+ combine(x) { console.log("show", x.map(x => !!x)); return x; }
8086
+ });
8087
+ class HoverTooltipHost {
8088
+ constructor(view) {
8089
+ this.view = view;
8090
+ this.mounted = false;
8091
+ this.dom = document.createElement("div");
8092
+ this.dom.classList.add("cm-tooltip-hover");
8093
+ this.manager = new TooltipViewManager(view, showHoverTooltip, t => this.createHostedView(t));
8094
+ }
8095
+ // Needs to be static so that host tooltip instances always match
8096
+ static create(view) {
8097
+ return new HoverTooltipHost(view);
8098
+ }
8099
+ createHostedView(tooltip) {
8100
+ let hostedView = tooltip.create(this.view);
8101
+ hostedView.dom.classList.add("cm-tooltip-section");
8102
+ this.dom.appendChild(hostedView.dom);
8103
+ if (this.mounted && hostedView.mount)
8104
+ hostedView.mount(this.view);
8105
+ return hostedView;
8106
+ }
8107
+ mount(view) {
8108
+ for (let hostedView of this.manager.tooltipViews) {
8109
+ if (hostedView.mount)
8110
+ hostedView.mount(view);
8111
+ }
8112
+ this.mounted = true;
8113
+ }
8114
+ positioned() {
8115
+ for (let hostedView of this.manager.tooltipViews) {
8116
+ if (hostedView.positioned)
8117
+ hostedView.positioned();
8118
+ }
8119
+ }
8120
+ update(update) {
8121
+ this.manager.update(update);
8122
+ }
8123
+ }
8124
+ const showHoverTooltipHost = showTooltip.compute([showHoverTooltip], state => {
8125
+ let tooltips = state.facet(showHoverTooltip).filter(t => t);
8126
+ console.log("hover tooltips: ", tooltips.length);
8127
+ if (tooltips.length === 0)
8128
+ return null;
8129
+ return {
8130
+ pos: Math.min(...tooltips.map(t => t.pos)),
8131
+ end: Math.max(...tooltips.filter(t => t.end != null).map(t => t.end)),
8132
+ create: HoverTooltipHost.create,
8133
+ above: tooltips[0].above,
8134
+ arrow: tooltips.some(t => t.arrow),
8135
+ };
8136
+ });
8137
+ class HoverPlugin {
8138
+ constructor(view, source, field, setHover, hoverTime) {
8139
+ this.view = view;
8140
+ this.source = source;
8141
+ this.field = field;
8142
+ this.setHover = setHover;
8143
+ this.hoverTime = hoverTime;
8144
+ this.hoverTimeout = -1;
8145
+ this.restartTimeout = -1;
8146
+ this.pending = null;
8147
+ this.lastMove = { x: 0, y: 0, target: view.dom, time: 0 };
8148
+ this.checkHover = this.checkHover.bind(this);
8149
+ view.dom.addEventListener("mouseleave", this.mouseleave = this.mouseleave.bind(this));
8150
+ view.dom.addEventListener("mousemove", this.mousemove = this.mousemove.bind(this));
8151
+ }
8152
+ update() {
8153
+ if (this.pending) {
8154
+ this.pending = null;
8155
+ clearTimeout(this.restartTimeout);
8156
+ this.restartTimeout = setTimeout(() => this.startHover(), 20);
8157
+ }
8158
+ }
8159
+ get active() {
8160
+ return this.view.state.field(this.field);
8161
+ }
8162
+ checkHover() {
8163
+ this.hoverTimeout = -1;
8164
+ if (this.active)
8165
+ return;
8166
+ let hovered = Date.now() - this.lastMove.time;
8167
+ if (hovered < this.hoverTime)
8168
+ this.hoverTimeout = setTimeout(this.checkHover, this.hoverTime - hovered);
8169
+ else
8170
+ this.startHover();
8171
+ }
8172
+ startHover() {
8173
+ var _a;
8174
+ clearTimeout(this.restartTimeout);
8175
+ let { lastMove } = this;
8176
+ let pos = this.view.contentDOM.contains(lastMove.target) ? this.view.posAtCoords(lastMove) : null;
8177
+ if (pos == null)
8178
+ return;
8179
+ let posCoords = this.view.coordsAtPos(pos);
8180
+ if (posCoords == null || lastMove.y < posCoords.top || lastMove.y > posCoords.bottom ||
8181
+ lastMove.x < posCoords.left - this.view.defaultCharacterWidth ||
8182
+ lastMove.x > posCoords.right + this.view.defaultCharacterWidth)
8183
+ return;
8184
+ let bidi = this.view.bidiSpans(this.view.state.doc.lineAt(pos)).find(s => s.from <= pos && s.to >= pos);
8185
+ let rtl = bidi && bidi.dir == exports.Direction.RTL ? -1 : 1;
8186
+ let open = this.source(this.view, pos, (lastMove.x < posCoords.left ? -rtl : rtl));
8187
+ if ((_a = open) === null || _a === void 0 ? void 0 : _a.then) {
8188
+ let pending = this.pending = { pos };
8189
+ open.then(result => {
8190
+ if (this.pending == pending) {
8191
+ this.pending = null;
8192
+ if (result)
8193
+ this.view.dispatch({ effects: this.setHover.of(result) });
8194
+ }
8195
+ }, e => logException(this.view.state, e, "hover tooltip"));
8196
+ }
8197
+ else if (open) {
8198
+ this.view.dispatch({ effects: this.setHover.of(open) });
8199
+ }
8200
+ }
8201
+ mousemove(event) {
8202
+ var _a;
8203
+ this.lastMove = { x: event.clientX, y: event.clientY, target: event.target, time: Date.now() };
8204
+ if (this.hoverTimeout < 0)
8205
+ this.hoverTimeout = setTimeout(this.checkHover, this.hoverTime);
8206
+ let tooltip = this.active;
8207
+ if (tooltip && !isInTooltip(this.lastMove.target) || this.pending) {
8208
+ let { pos } = tooltip || this.pending, end = (_a = tooltip === null || tooltip === void 0 ? void 0 : tooltip.end) !== null && _a !== void 0 ? _a : pos;
8209
+ if ((pos == end ? this.view.posAtCoords(this.lastMove) != pos
8210
+ : !isOverRange(this.view, pos, end, event.clientX, event.clientY, 6 /* MaxDist */))) {
8211
+ this.view.dispatch({ effects: this.setHover.of(null) });
8212
+ this.pending = null;
8213
+ }
8214
+ }
8215
+ }
8216
+ mouseleave() {
8217
+ clearTimeout(this.hoverTimeout);
8218
+ this.hoverTimeout = -1;
8219
+ if (this.active)
8220
+ this.view.dispatch({ effects: this.setHover.of(null) });
8221
+ }
8222
+ destroy() {
8223
+ clearTimeout(this.hoverTimeout);
8224
+ this.view.dom.removeEventListener("mouseleave", this.mouseleave);
8225
+ this.view.dom.removeEventListener("mousemove", this.mousemove);
8226
+ }
8227
+ }
8228
+ function isInTooltip(elt) {
8229
+ for (let cur = elt; cur; cur = cur.parentNode)
8230
+ if (cur.nodeType == 1 && cur.classList.contains("cm-tooltip"))
8231
+ return true;
8232
+ return false;
8233
+ }
8234
+ function isOverRange(view, from, to, x, y, margin) {
8235
+ let range = document.createRange();
8236
+ let fromDOM = view.domAtPos(from), toDOM = view.domAtPos(to);
8237
+ range.setEnd(toDOM.node, toDOM.offset);
8238
+ range.setStart(fromDOM.node, fromDOM.offset);
8239
+ let rects = range.getClientRects();
8240
+ range.detach();
8241
+ for (let i = 0; i < rects.length; i++) {
8242
+ let rect = rects[i];
8243
+ let dist = Math.max(rect.top - y, y - rect.bottom, rect.left - x, x - rect.right);
8244
+ if (dist <= margin)
8245
+ return true;
8246
+ }
8247
+ return false;
8248
+ }
8249
+ /**
8250
+ Set up a hover tooltip, which shows up when the pointer hovers
8251
+ over ranges of text. The callback is called when the mouse hovers
8252
+ over the document text. It should, if there is a tooltip
8253
+ associated with position `pos`, return the tooltip description
8254
+ (either directly or in a promise). The `side` argument indicates
8255
+ on which side of the position the pointer is—it will be -1 if the
8256
+ pointer is before the position, 1 if after the position.
8257
+
8258
+ Note that all hover tooltips are hosted within a single tooltip
8259
+ container element. This allows multiple tooltips over the same
8260
+ range to be "merged" together without overlapping.
8261
+ */
8262
+ function hoverTooltip(source, options = {}) {
8263
+ let setHover = state.StateEffect.define();
8264
+ let hoverState = state.StateField.define({
8265
+ create() { return null; },
8266
+ update(value, tr) {
8267
+ console.log("update tooltip", !!value);
8268
+ if (value && (options.hideOnChange && (tr.docChanged || tr.selection)))
8269
+ return null;
8270
+ if (value && tr.docChanged) {
8271
+ let newPos = tr.changes.mapPos(value.pos, -1, state.MapMode.TrackDel);
8272
+ if (newPos == null)
8273
+ return null;
8274
+ let copy = Object.assign(Object.create(null), value);
8275
+ copy.pos = newPos;
8276
+ if (value.end != null)
8277
+ copy.end = tr.changes.mapPos(value.end);
8278
+ value = copy;
8279
+ }
8280
+ for (let effect of tr.effects) {
8281
+ if (effect.is(setHover))
8282
+ value = effect.value;
8283
+ if (effect.is(closeHoverTooltipEffect))
8284
+ value = (console.log("CLOSE"), null);
8285
+ }
8286
+ console.log("updated: " + !!value);
8287
+ return value;
8288
+ },
8289
+ provide: f => showHoverTooltip.from(f)
8290
+ });
8291
+ return [
8292
+ hoverState,
8293
+ ViewPlugin.define(view => new HoverPlugin(view, source, hoverState, setHover, options.hoverTime || 300 /* Time */)),
8294
+ showHoverTooltipHost
8295
+ ];
8296
+ }
8297
+ /**
8298
+ Get the active tooltip view for a given tooltip, if available.
8299
+ */
8300
+ function getTooltip(view, tooltip) {
8301
+ let plugin = view.plugin(tooltipPlugin);
8302
+ if (!plugin)
8303
+ return null;
8304
+ let found = plugin.manager.tooltips.indexOf(tooltip);
8305
+ return found < 0 ? null : plugin.manager.tooltipViews[found];
8306
+ }
8307
+ /**
8308
+ Returns true if any hover tooltips are currently active.
8309
+ */
8310
+ function hasHoverTooltips(state) {
8311
+ return state.facet(showHoverTooltip).some(x => x);
8312
+ }
8313
+ const closeHoverTooltipEffect = state.StateEffect.define();
8314
+ /**
8315
+ Transaction effect that closes all hover tooltips.
8316
+ */
8317
+ const closeHoverTooltips = closeHoverTooltipEffect.of(null);
8318
+ /**
8319
+ Tell the tooltip extension to recompute the position of the active
8320
+ tooltips. This can be useful when something happens (such as a
8321
+ re-positioning or CSS change affecting the editor) that could
8322
+ invalidate the existing tooltip positions.
8323
+ */
8324
+ function repositionTooltips(view) {
8325
+ var _a;
8326
+ (_a = view.plugin(tooltipPlugin)) === null || _a === void 0 ? void 0 : _a.maybeMeasure();
8327
+ }
8328
+
8329
+ const panelConfig = state.Facet.define({
8330
+ combine(configs) {
8331
+ let topContainer, bottomContainer;
8332
+ for (let c of configs) {
8333
+ topContainer = topContainer || c.topContainer;
8334
+ bottomContainer = bottomContainer || c.bottomContainer;
8335
+ }
8336
+ return { topContainer, bottomContainer };
8337
+ }
8338
+ });
8339
+ /**
8340
+ Configures the panel-managing extension.
8341
+ */
8342
+ function panels(config) {
8343
+ return config ? [panelConfig.of(config)] : [];
8344
+ }
8345
+ /**
8346
+ Get the active panel created by the given constructor, if any.
8347
+ This can be useful when you need access to your panels' DOM
8348
+ structure.
8349
+ */
8350
+ function getPanel(view, panel) {
8351
+ let plugin = view.plugin(panelPlugin);
8352
+ let index = plugin ? plugin.specs.indexOf(panel) : -1;
8353
+ return index > -1 ? plugin.panels[index] : null;
8354
+ }
8355
+ const panelPlugin = ViewPlugin.fromClass(class {
8356
+ constructor(view) {
8357
+ this.input = view.state.facet(showPanel);
8358
+ this.specs = this.input.filter(s => s);
8359
+ this.panels = this.specs.map(spec => spec(view));
8360
+ let conf = view.state.facet(panelConfig);
8361
+ this.top = new PanelGroup(view, true, conf.topContainer);
8362
+ this.bottom = new PanelGroup(view, false, conf.bottomContainer);
8363
+ this.top.sync(this.panels.filter(p => p.top));
8364
+ this.bottom.sync(this.panels.filter(p => !p.top));
8365
+ for (let p of this.panels) {
8366
+ p.dom.classList.add("cm-panel");
8367
+ if (p.mount)
8368
+ p.mount();
8369
+ }
8370
+ }
8371
+ update(update) {
8372
+ let conf = update.state.facet(panelConfig);
8373
+ if (this.top.container != conf.topContainer) {
8374
+ this.top.sync([]);
8375
+ this.top = new PanelGroup(update.view, true, conf.topContainer);
8376
+ }
8377
+ if (this.bottom.container != conf.bottomContainer) {
8378
+ this.bottom.sync([]);
8379
+ this.bottom = new PanelGroup(update.view, false, conf.bottomContainer);
8380
+ }
8381
+ this.top.syncClasses();
8382
+ this.bottom.syncClasses();
8383
+ let input = update.state.facet(showPanel);
8384
+ if (input != this.input) {
8385
+ let specs = input.filter(x => x);
8386
+ let panels = [], top = [], bottom = [], mount = [];
8387
+ for (let spec of specs) {
8388
+ let known = this.specs.indexOf(spec), panel;
8389
+ if (known < 0) {
8390
+ panel = spec(update.view);
8391
+ mount.push(panel);
8392
+ }
8393
+ else {
8394
+ panel = this.panels[known];
8395
+ if (panel.update)
8396
+ panel.update(update);
8397
+ }
8398
+ panels.push(panel);
8399
+ (panel.top ? top : bottom).push(panel);
8400
+ }
8401
+ this.specs = specs;
8402
+ this.panels = panels;
8403
+ this.top.sync(top);
8404
+ this.bottom.sync(bottom);
8405
+ for (let p of mount) {
8406
+ p.dom.classList.add("cm-panel");
8407
+ if (p.mount)
8408
+ p.mount();
8409
+ }
8410
+ }
8411
+ else {
8412
+ for (let p of this.panels)
8413
+ if (p.update)
8414
+ p.update(update);
8415
+ }
8416
+ }
8417
+ destroy() {
8418
+ this.top.sync([]);
8419
+ this.bottom.sync([]);
8420
+ }
8421
+ }, {
8422
+ provide: plugin => EditorView.scrollMargins.of(view => {
8423
+ let value = view.plugin(plugin);
8424
+ return value && { top: value.top.scrollMargin(), bottom: value.bottom.scrollMargin() };
8425
+ })
8426
+ });
8427
+ class PanelGroup {
8428
+ constructor(view, top, container) {
8429
+ this.view = view;
8430
+ this.top = top;
8431
+ this.container = container;
8432
+ this.dom = undefined;
8433
+ this.classes = "";
8434
+ this.panels = [];
8435
+ this.syncClasses();
8436
+ }
8437
+ sync(panels) {
8438
+ for (let p of this.panels)
8439
+ if (p.destroy && panels.indexOf(p) < 0)
8440
+ p.destroy();
8441
+ this.panels = panels;
8442
+ this.syncDOM();
8443
+ }
8444
+ syncDOM() {
8445
+ if (this.panels.length == 0) {
8446
+ if (this.dom) {
8447
+ this.dom.remove();
8448
+ this.dom = undefined;
8449
+ }
8450
+ return;
8451
+ }
8452
+ if (!this.dom) {
8453
+ this.dom = document.createElement("div");
8454
+ this.dom.className = this.top ? "cm-panels cm-panels-top" : "cm-panels cm-panels-bottom";
8455
+ this.dom.style[this.top ? "top" : "bottom"] = "0";
8456
+ let parent = this.container || this.view.dom;
8457
+ parent.insertBefore(this.dom, this.top ? parent.firstChild : null);
8458
+ }
8459
+ let curDOM = this.dom.firstChild;
8460
+ for (let panel of this.panels) {
8461
+ if (panel.dom.parentNode == this.dom) {
8462
+ while (curDOM != panel.dom)
8463
+ curDOM = rm(curDOM);
8464
+ curDOM = curDOM.nextSibling;
8465
+ }
8466
+ else {
8467
+ this.dom.insertBefore(panel.dom, curDOM);
8468
+ }
8469
+ }
8470
+ while (curDOM)
8471
+ curDOM = rm(curDOM);
8472
+ }
8473
+ scrollMargin() {
8474
+ return !this.dom || this.container ? 0
8475
+ : Math.max(0, this.top ?
8476
+ this.dom.getBoundingClientRect().bottom - Math.max(0, this.view.scrollDOM.getBoundingClientRect().top) :
8477
+ Math.min(innerHeight, this.view.scrollDOM.getBoundingClientRect().bottom) - this.dom.getBoundingClientRect().top);
8478
+ }
8479
+ syncClasses() {
8480
+ if (!this.container || this.classes == this.view.themeClasses)
8481
+ return;
8482
+ for (let cls of this.classes.split(" "))
8483
+ if (cls)
8484
+ this.container.classList.remove(cls);
8485
+ for (let cls of (this.classes = this.view.themeClasses).split(" "))
8486
+ if (cls)
8487
+ this.container.classList.add(cls);
8488
+ }
8489
+ }
8490
+ function rm(node) {
8491
+ let next = node.nextSibling;
8492
+ node.remove();
8493
+ return next;
8494
+ }
8495
+ /**
8496
+ Opening a panel is done by providing a constructor function for
8497
+ the panel through this facet. (The panel is closed again when its
8498
+ constructor is no longer provided.) Values of `null` are ignored.
8499
+ */
8500
+ const showPanel = state.Facet.define({
8501
+ enables: panelPlugin
8502
+ });
8503
+
8504
+ /**
8505
+ A gutter marker represents a bit of information attached to a line
8506
+ in a specific gutter. Your own custom markers have to extend this
8507
+ class.
8508
+ */
8509
+ class GutterMarker extends state.RangeValue {
8510
+ /**
8511
+ @internal
8512
+ */
8513
+ compare(other) {
8514
+ return this == other || this.constructor == other.constructor && this.eq(other);
8515
+ }
8516
+ /**
8517
+ Compare this marker to another marker of the same type.
8518
+ */
8519
+ eq(other) { return false; }
8520
+ /**
8521
+ Called if the marker has a `toDOM` method and its representation
8522
+ was removed from a gutter.
8523
+ */
8524
+ destroy(dom) { }
8525
+ }
8526
+ GutterMarker.prototype.elementClass = "";
8527
+ GutterMarker.prototype.toDOM = undefined;
8528
+ GutterMarker.prototype.mapMode = state.MapMode.TrackBefore;
8529
+ GutterMarker.prototype.startSide = GutterMarker.prototype.endSide = -1;
8530
+ GutterMarker.prototype.point = true;
8531
+ /**
8532
+ Facet used to add a class to all gutter elements for a given line.
8533
+ Markers given to this facet should _only_ define an
8534
+ [`elementclass`](https://codemirror.net/6/docs/ref/#view.GutterMarker.elementClass), not a
8535
+ [`toDOM`](https://codemirror.net/6/docs/ref/#view.GutterMarker.toDOM) (or the marker will appear
8536
+ in all gutters for the line).
8537
+ */
8538
+ const gutterLineClass = state.Facet.define();
8539
+ const defaults = {
8540
+ class: "",
8541
+ renderEmptyElements: false,
8542
+ elementStyle: "",
8543
+ markers: () => state.RangeSet.empty,
8544
+ lineMarker: () => null,
8545
+ lineMarkerChange: null,
8546
+ initialSpacer: null,
8547
+ updateSpacer: null,
8548
+ domEventHandlers: {}
8549
+ };
8550
+ const activeGutters = state.Facet.define();
8551
+ /**
8552
+ Define an editor gutter. The order in which the gutters appear is
8553
+ determined by their extension priority.
8554
+ */
8555
+ function gutter(config) {
8556
+ return [gutters(), activeGutters.of(Object.assign(Object.assign({}, defaults), config))];
8557
+ }
8558
+ const unfixGutters = state.Facet.define({
8559
+ combine: values => values.some(x => x)
8560
+ });
8561
+ /**
8562
+ The gutter-drawing plugin is automatically enabled when you add a
8563
+ gutter, but you can use this function to explicitly configure it.
8564
+
8565
+ Unless `fixed` is explicitly set to `false`, the gutters are
8566
+ fixed, meaning they don't scroll along with the content
8567
+ horizontally (except on Internet Explorer, which doesn't support
8568
+ CSS [`position:
8569
+ sticky`](https://developer.mozilla.org/en-US/docs/Web/CSS/position#sticky)).
8570
+ */
8571
+ function gutters(config) {
8572
+ let result = [
8573
+ gutterView,
8574
+ ];
8575
+ if (config && config.fixed === false)
8576
+ result.push(unfixGutters.of(true));
8577
+ return result;
8578
+ }
8579
+ const gutterView = ViewPlugin.fromClass(class {
8580
+ constructor(view) {
8581
+ this.view = view;
8582
+ this.prevViewport = view.viewport;
8583
+ this.dom = document.createElement("div");
8584
+ this.dom.className = "cm-gutters";
8585
+ this.dom.setAttribute("aria-hidden", "true");
8586
+ this.dom.style.minHeight = this.view.contentHeight + "px";
8587
+ this.gutters = view.state.facet(activeGutters).map(conf => new SingleGutterView(view, conf));
8588
+ for (let gutter of this.gutters)
8589
+ this.dom.appendChild(gutter.dom);
8590
+ this.fixed = !view.state.facet(unfixGutters);
8591
+ if (this.fixed) {
8592
+ // FIXME IE11 fallback, which doesn't support position: sticky,
8593
+ // by using position: relative + event handlers that realign the
8594
+ // gutter (or just force fixed=false on IE11?)
8595
+ this.dom.style.position = "sticky";
8596
+ }
8597
+ this.syncGutters(false);
8598
+ view.scrollDOM.insertBefore(this.dom, view.contentDOM);
8599
+ }
8600
+ update(update) {
8601
+ if (this.updateGutters(update)) {
8602
+ // Detach during sync when the viewport changed significantly
8603
+ // (such as during scrolling), since for large updates that is
8604
+ // faster.
8605
+ let vpA = this.prevViewport, vpB = update.view.viewport;
8606
+ let vpOverlap = Math.min(vpA.to, vpB.to) - Math.max(vpA.from, vpB.from);
8607
+ this.syncGutters(vpOverlap < (vpB.to - vpB.from) * 0.8);
8608
+ }
8609
+ if (update.geometryChanged)
8610
+ this.dom.style.minHeight = this.view.contentHeight + "px";
8611
+ if (this.view.state.facet(unfixGutters) != !this.fixed) {
8612
+ this.fixed = !this.fixed;
8613
+ this.dom.style.position = this.fixed ? "sticky" : "";
8614
+ }
8615
+ this.prevViewport = update.view.viewport;
8616
+ }
8617
+ syncGutters(detach) {
8618
+ let after = this.dom.nextSibling;
8619
+ if (detach)
8620
+ this.dom.remove();
8621
+ let lineClasses = state.RangeSet.iter(this.view.state.facet(gutterLineClass), this.view.viewport.from);
8622
+ let classSet = [];
8623
+ let contexts = this.gutters.map(gutter => new UpdateContext(gutter, this.view.viewport, -this.view.documentPadding.top));
8624
+ for (let line of this.view.viewportLineBlocks) {
8625
+ let text;
8626
+ if (Array.isArray(line.type)) {
8627
+ for (let b of line.type)
8628
+ if (b.type == exports.BlockType.Text) {
8629
+ text = b;
8630
+ break;
8631
+ }
8632
+ }
8633
+ else {
8634
+ text = line.type == exports.BlockType.Text ? line : undefined;
8635
+ }
8636
+ if (!text)
8637
+ continue;
8638
+ if (classSet.length)
8639
+ classSet = [];
8640
+ advanceCursor(lineClasses, classSet, line.from);
8641
+ for (let cx of contexts)
8642
+ cx.line(this.view, text, classSet);
8643
+ }
8644
+ for (let cx of contexts)
8645
+ cx.finish();
8646
+ if (detach)
8647
+ this.view.scrollDOM.insertBefore(this.dom, after);
8648
+ }
8649
+ updateGutters(update) {
8650
+ let prev = update.startState.facet(activeGutters), cur = update.state.facet(activeGutters);
8651
+ let change = update.docChanged || update.heightChanged || update.viewportChanged ||
8652
+ !state.RangeSet.eq(update.startState.facet(gutterLineClass), update.state.facet(gutterLineClass), update.view.viewport.from, update.view.viewport.to);
8653
+ if (prev == cur) {
8654
+ for (let gutter of this.gutters)
8655
+ if (gutter.update(update))
8656
+ change = true;
8657
+ }
8658
+ else {
8659
+ change = true;
8660
+ let gutters = [];
8661
+ for (let conf of cur) {
8662
+ let known = prev.indexOf(conf);
8663
+ if (known < 0) {
8664
+ gutters.push(new SingleGutterView(this.view, conf));
8665
+ }
8666
+ else {
8667
+ this.gutters[known].update(update);
8668
+ gutters.push(this.gutters[known]);
8669
+ }
8670
+ }
8671
+ for (let g of this.gutters) {
8672
+ g.dom.remove();
8673
+ if (gutters.indexOf(g) < 0)
8674
+ g.destroy();
8675
+ }
8676
+ for (let g of gutters)
8677
+ this.dom.appendChild(g.dom);
8678
+ this.gutters = gutters;
8679
+ }
8680
+ return change;
8681
+ }
8682
+ destroy() {
8683
+ for (let view of this.gutters)
8684
+ view.destroy();
8685
+ this.dom.remove();
8686
+ }
8687
+ }, {
8688
+ provide: plugin => EditorView.scrollMargins.of(view => {
8689
+ let value = view.plugin(plugin);
8690
+ if (!value || value.gutters.length == 0 || !value.fixed)
8691
+ return null;
8692
+ return view.textDirection == exports.Direction.LTR ? { left: value.dom.offsetWidth } : { right: value.dom.offsetWidth };
8693
+ })
8694
+ });
8695
+ function asArray(val) { return (Array.isArray(val) ? val : [val]); }
8696
+ function advanceCursor(cursor, collect, pos) {
8697
+ while (cursor.value && cursor.from <= pos) {
8698
+ if (cursor.from == pos)
8699
+ collect.push(cursor.value);
8700
+ cursor.next();
8701
+ }
8702
+ }
8703
+ class UpdateContext {
8704
+ constructor(gutter, viewport, height) {
8705
+ this.gutter = gutter;
8706
+ this.height = height;
8707
+ this.localMarkers = [];
8708
+ this.i = 0;
8709
+ this.cursor = state.RangeSet.iter(gutter.markers, viewport.from);
8710
+ }
8711
+ line(view, line, extraMarkers) {
8712
+ if (this.localMarkers.length)
8713
+ this.localMarkers = [];
8714
+ advanceCursor(this.cursor, this.localMarkers, line.from);
8715
+ let localMarkers = extraMarkers.length ? this.localMarkers.concat(extraMarkers) : this.localMarkers;
8716
+ let forLine = this.gutter.config.lineMarker(view, line, localMarkers);
8717
+ if (forLine)
8718
+ localMarkers.unshift(forLine);
8719
+ let gutter = this.gutter;
8720
+ if (localMarkers.length == 0 && !gutter.config.renderEmptyElements)
8721
+ return;
8722
+ let above = line.top - this.height;
8723
+ if (this.i == gutter.elements.length) {
8724
+ let newElt = new GutterElement(view, line.height, above, localMarkers);
8725
+ gutter.elements.push(newElt);
8726
+ gutter.dom.appendChild(newElt.dom);
8727
+ }
8728
+ else {
8729
+ gutter.elements[this.i].update(view, line.height, above, localMarkers);
8730
+ }
8731
+ this.height = line.bottom;
8732
+ this.i++;
8733
+ }
8734
+ finish() {
8735
+ let gutter = this.gutter;
8736
+ while (gutter.elements.length > this.i) {
8737
+ let last = gutter.elements.pop();
8738
+ gutter.dom.removeChild(last.dom);
8739
+ last.destroy();
8740
+ }
8741
+ }
8742
+ }
8743
+ class SingleGutterView {
8744
+ constructor(view, config) {
8745
+ this.view = view;
8746
+ this.config = config;
8747
+ this.elements = [];
8748
+ this.spacer = null;
8749
+ this.dom = document.createElement("div");
8750
+ this.dom.className = "cm-gutter" + (this.config.class ? " " + this.config.class : "");
8751
+ for (let prop in config.domEventHandlers) {
8752
+ this.dom.addEventListener(prop, (event) => {
8753
+ let line = view.lineBlockAtHeight(event.clientY - view.documentTop);
8754
+ if (config.domEventHandlers[prop](view, line, event))
8755
+ event.preventDefault();
8756
+ });
8757
+ }
8758
+ this.markers = asArray(config.markers(view));
8759
+ if (config.initialSpacer) {
8760
+ this.spacer = new GutterElement(view, 0, 0, [config.initialSpacer(view)]);
8761
+ this.dom.appendChild(this.spacer.dom);
8762
+ this.spacer.dom.style.cssText += "visibility: hidden; pointer-events: none";
8763
+ }
8764
+ }
8765
+ update(update) {
8766
+ let prevMarkers = this.markers;
8767
+ this.markers = asArray(this.config.markers(update.view));
8768
+ if (this.spacer && this.config.updateSpacer) {
8769
+ let updated = this.config.updateSpacer(this.spacer.markers[0], update);
8770
+ if (updated != this.spacer.markers[0])
8771
+ this.spacer.update(update.view, 0, 0, [updated]);
8772
+ }
8773
+ let vp = update.view.viewport;
8774
+ return !state.RangeSet.eq(this.markers, prevMarkers, vp.from, vp.to) ||
8775
+ (this.config.lineMarkerChange ? this.config.lineMarkerChange(update) : false);
8776
+ }
8777
+ destroy() {
8778
+ for (let elt of this.elements)
8779
+ elt.destroy();
8780
+ }
8781
+ }
8782
+ class GutterElement {
8783
+ constructor(view, height, above, markers) {
8784
+ this.height = -1;
8785
+ this.above = 0;
8786
+ this.markers = [];
8787
+ this.dom = document.createElement("div");
8788
+ this.update(view, height, above, markers);
8789
+ }
8790
+ update(view, height, above, markers) {
8791
+ if (this.height != height)
8792
+ this.dom.style.height = (this.height = height) + "px";
8793
+ if (this.above != above)
8794
+ this.dom.style.marginTop = (this.above = above) ? above + "px" : "";
8795
+ if (!sameMarkers(this.markers, markers))
8796
+ this.setMarkers(view, markers);
8797
+ }
8798
+ setMarkers(view, markers) {
8799
+ let cls = "cm-gutterElement", domPos = this.dom.firstChild;
8800
+ for (let iNew = 0, iOld = 0;;) {
8801
+ let skipTo = iOld, marker = iNew < markers.length ? markers[iNew++] : null, matched = false;
8802
+ if (marker) {
8803
+ let c = marker.elementClass;
8804
+ if (c)
8805
+ cls += " " + c;
8806
+ for (let i = iOld; i < this.markers.length; i++)
8807
+ if (this.markers[i].compare(marker)) {
8808
+ skipTo = i;
8809
+ matched = true;
8810
+ break;
8811
+ }
8812
+ }
8813
+ else {
8814
+ skipTo = this.markers.length;
8815
+ }
8816
+ while (iOld < skipTo) {
8817
+ let next = this.markers[iOld++];
8818
+ if (next.toDOM) {
8819
+ next.destroy(domPos);
8820
+ let after = domPos.nextSibling;
8821
+ domPos.remove();
8822
+ domPos = after;
8823
+ }
8824
+ }
8825
+ if (!marker)
8826
+ break;
8827
+ if (marker.toDOM) {
8828
+ if (matched)
8829
+ domPos = domPos.nextSibling;
8830
+ else
8831
+ this.dom.insertBefore(marker.toDOM(view), domPos);
8832
+ }
8833
+ if (matched)
8834
+ iOld++;
8835
+ }
8836
+ this.dom.className = cls;
8837
+ this.markers = markers;
8838
+ }
8839
+ destroy() {
8840
+ this.setMarkers(null, []); // First argument not used unless creating markers
8841
+ }
8842
+ }
8843
+ function sameMarkers(a, b) {
8844
+ if (a.length != b.length)
8845
+ return false;
8846
+ for (let i = 0; i < a.length; i++)
8847
+ if (!a[i].compare(b[i]))
8848
+ return false;
8849
+ return true;
8850
+ }
8851
+ /**
8852
+ Facet used to provide markers to the line number gutter.
8853
+ */
8854
+ const lineNumberMarkers = state.Facet.define();
8855
+ const lineNumberConfig = state.Facet.define({
8856
+ combine(values) {
8857
+ return state.combineConfig(values, { formatNumber: String, domEventHandlers: {} }, {
8858
+ domEventHandlers(a, b) {
8859
+ let result = Object.assign({}, a);
8860
+ for (let event in b) {
8861
+ let exists = result[event], add = b[event];
8862
+ result[event] = exists ? (view, line, event) => exists(view, line, event) || add(view, line, event) : add;
8863
+ }
8864
+ return result;
8865
+ }
8866
+ });
8867
+ }
8868
+ });
8869
+ class NumberMarker extends GutterMarker {
8870
+ constructor(number) {
8871
+ super();
8872
+ this.number = number;
8873
+ }
8874
+ eq(other) { return this.number == other.number; }
8875
+ toDOM() { return document.createTextNode(this.number); }
8876
+ }
8877
+ function formatNumber(view, number) {
8878
+ return view.state.facet(lineNumberConfig).formatNumber(number, view.state);
8879
+ }
8880
+ const lineNumberGutter = activeGutters.compute([lineNumberConfig], state => ({
8881
+ class: "cm-lineNumbers",
8882
+ renderEmptyElements: false,
8883
+ markers(view) { return view.state.facet(lineNumberMarkers); },
8884
+ lineMarker(view, line, others) {
8885
+ if (others.some(m => m.toDOM))
8886
+ return null;
8887
+ return new NumberMarker(formatNumber(view, view.state.doc.lineAt(line.from).number));
8888
+ },
8889
+ lineMarkerChange: update => update.startState.facet(lineNumberConfig) != update.state.facet(lineNumberConfig),
8890
+ initialSpacer(view) {
8891
+ return new NumberMarker(formatNumber(view, maxLineNumber(view.state.doc.lines)));
8892
+ },
8893
+ updateSpacer(spacer, update) {
8894
+ let max = formatNumber(update.view, maxLineNumber(update.view.state.doc.lines));
8895
+ return max == spacer.number ? spacer : new NumberMarker(max);
8896
+ },
8897
+ domEventHandlers: state.facet(lineNumberConfig).domEventHandlers
8898
+ }));
8899
+ /**
8900
+ Create a line number gutter extension.
8901
+ */
8902
+ function lineNumbers(config = {}) {
8903
+ return [
8904
+ lineNumberConfig.of(config),
8905
+ gutters(),
8906
+ lineNumberGutter
8907
+ ];
8908
+ }
8909
+ function maxLineNumber(lines) {
8910
+ let last = 9;
8911
+ while (last < lines)
8912
+ last = last * 10 + 9;
8913
+ return last;
8914
+ }
8915
+ const activeLineGutterMarker = new class extends GutterMarker {
8916
+ constructor() {
8917
+ super(...arguments);
8918
+ this.elementClass = "cm-activeLineGutter";
8919
+ }
8920
+ };
8921
+ const activeLineGutterHighlighter = gutterLineClass.compute(["selection"], state$1 => {
8922
+ let marks = [], last = -1;
8923
+ for (let range of state$1.selection.ranges)
8924
+ if (range.empty) {
8925
+ let linePos = state$1.doc.lineAt(range.head).from;
8926
+ if (linePos > last) {
8927
+ last = linePos;
8928
+ marks.push(activeLineGutterMarker.range(linePos));
8929
+ }
8930
+ }
8931
+ return state.RangeSet.of(marks);
8932
+ });
8933
+ /**
8934
+ Returns an extension that adds a `cm-activeLineGutter` class to
8935
+ all gutter elements on the [active
8936
+ line](https://codemirror.net/6/docs/ref/#view.highlightActiveLine).
8937
+ */
8938
+ function highlightActiveLineGutter() {
8939
+ return activeLineGutterHighlighter;
8940
+ }
8941
+
7721
8942
  /**
7722
8943
  @internal
7723
8944
  */
7724
8945
  const __test = { HeightMap, HeightOracle, MeasuredHeights, QueryType, ChangedRange, computeOrder, moveVisually };
7725
8946
 
7726
- Object.defineProperty(exports, 'Range', {
7727
- enumerable: true,
7728
- get: function () { return rangeset.Range; }
7729
- });
7730
8947
  exports.BidiSpan = BidiSpan;
7731
8948
  exports.BlockInfo = BlockInfo;
7732
8949
  exports.Decoration = Decoration;
7733
8950
  exports.EditorView = EditorView;
8951
+ exports.GutterMarker = GutterMarker;
7734
8952
  exports.MatchDecorator = MatchDecorator;
7735
- exports.PluginField = PluginField;
7736
- exports.PluginFieldProvider = PluginFieldProvider;
7737
8953
  exports.ViewPlugin = ViewPlugin;
7738
8954
  exports.ViewUpdate = ViewUpdate;
7739
8955
  exports.WidgetType = WidgetType;
7740
8956
  exports.__test = __test;
8957
+ exports.closeHoverTooltips = closeHoverTooltips;
8958
+ exports.crosshairCursor = crosshairCursor;
7741
8959
  exports.drawSelection = drawSelection;
7742
8960
  exports.dropCursor = dropCursor;
8961
+ exports.getPanel = getPanel;
8962
+ exports.getTooltip = getTooltip;
8963
+ exports.gutter = gutter;
8964
+ exports.gutterLineClass = gutterLineClass;
8965
+ exports.gutters = gutters;
8966
+ exports.hasHoverTooltips = hasHoverTooltips;
7743
8967
  exports.highlightActiveLine = highlightActiveLine;
8968
+ exports.highlightActiveLineGutter = highlightActiveLineGutter;
7744
8969
  exports.highlightSpecialChars = highlightSpecialChars;
8970
+ exports.hoverTooltip = hoverTooltip;
7745
8971
  exports.keymap = keymap;
8972
+ exports.lineNumberMarkers = lineNumberMarkers;
8973
+ exports.lineNumbers = lineNumbers;
7746
8974
  exports.logException = logException;
8975
+ exports.panels = panels;
7747
8976
  exports.placeholder = placeholder;
8977
+ exports.rectangularSelection = rectangularSelection;
8978
+ exports.repositionTooltips = repositionTooltips;
7748
8979
  exports.runScopeHandlers = runScopeHandlers;
7749
8980
  exports.scrollPastEnd = scrollPastEnd;
8981
+ exports.showPanel = showPanel;
8982
+ exports.showTooltip = showTooltip;
8983
+ exports.tooltips = tooltips;