sqlui 0.1.67 → 0.1.68

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.
@@ -3971,11 +3971,11 @@
3971
3971
  constructor(root) {
3972
3972
  if (!root.head && root.adoptedStyleSheets && typeof CSSStyleSheet != "undefined") {
3973
3973
  if (adoptedSet) {
3974
- root.adoptedStyleSheets = [adoptedSet.sheet].concat(root.adoptedStyleSheets);
3974
+ root.adoptedStyleSheets = [adoptedSet.sheet, ...root.adoptedStyleSheets];
3975
3975
  return root[SET] = adoptedSet
3976
3976
  }
3977
3977
  this.sheet = new CSSStyleSheet;
3978
- root.adoptedStyleSheets = [this.sheet].concat(root.adoptedStyleSheets);
3978
+ root.adoptedStyleSheets = [this.sheet, ...root.adoptedStyleSheets];
3979
3979
  adoptedSet = this;
3980
3980
  } else {
3981
3981
  this.styleTag = (root.ownerDocument || root).createElement("style");
@@ -4490,11 +4490,6 @@
4490
4490
  this.dom = null;
4491
4491
  this.dirty = 2 /* Dirty.Node */;
4492
4492
  }
4493
- get editorView() {
4494
- if (!this.parent)
4495
- throw new Error("Accessing view in orphan content view");
4496
- return this.parent.editorView;
4497
- }
4498
4493
  get overrideDOMText() { return null; }
4499
4494
  get posAtStart() {
4500
4495
  return this.parent ? this.parent.posBefore(this) : 0;
@@ -4518,7 +4513,7 @@
4518
4513
  // (side > 0) or directly on (when the browser supports it) the
4519
4514
  // given position.
4520
4515
  coordsAt(_pos, _side) { return null; }
4521
- sync(track) {
4516
+ sync(view, track) {
4522
4517
  if (this.dirty & 2 /* Dirty.Node */) {
4523
4518
  let parent = this.dom;
4524
4519
  let prev = null, next;
@@ -4529,7 +4524,7 @@
4529
4524
  if (!contentView || !contentView.parent && contentView.canReuseDOM(child))
4530
4525
  child.reuseDOM(next);
4531
4526
  }
4532
- child.sync(track);
4527
+ child.sync(view, track);
4533
4528
  child.dirty = 0 /* Dirty.Not */;
4534
4529
  }
4535
4530
  next = prev ? prev.nextSibling : parent.firstChild;
@@ -4553,7 +4548,7 @@
4553
4548
  else if (this.dirty & 1 /* Dirty.Child */) {
4554
4549
  for (let child of this.children)
4555
4550
  if (child.dirty) {
4556
- child.sync(track);
4551
+ child.sync(view, track);
4557
4552
  child.dirty = 0 /* Dirty.Not */;
4558
4553
  }
4559
4554
  }
@@ -4680,6 +4675,7 @@
4680
4675
  }
4681
4676
  static get(node) { return node.cmView; }
4682
4677
  get isEditable() { return true; }
4678
+ get isWidget() { return false; }
4683
4679
  merge(from, to, source, hasStart, openStart, openEnd) {
4684
4680
  return false;
4685
4681
  }
@@ -4847,7 +4843,7 @@
4847
4843
  createDOM(textDOM) {
4848
4844
  this.setDOM(textDOM || document.createTextNode(this.text));
4849
4845
  }
4850
- sync(track) {
4846
+ sync(view, track) {
4851
4847
  if (!this.dom)
4852
4848
  this.createDOM();
4853
4849
  if (this.dom.nodeValue != this.text) {
@@ -4908,12 +4904,12 @@
4908
4904
  this.dirty |= 4 /* Dirty.Attrs */ | 2 /* Dirty.Node */;
4909
4905
  }
4910
4906
  }
4911
- sync(track) {
4907
+ sync(view, track) {
4912
4908
  if (!this.dom)
4913
4909
  this.setDOM(this.setAttrs(document.createElement(this.mark.tagName)));
4914
4910
  else if (this.dirty & 4 /* Dirty.Attrs */)
4915
4911
  this.setAttrs(this.dom);
4916
- super.sync(track);
4912
+ super.sync(view, track);
4917
4913
  }
4918
4914
  merge(from, to, source, _hasStart, openStart, openEnd) {
4919
4915
  if (source && (!(source instanceof MarkView && source.mark.eq(this.mark)) ||
@@ -4997,12 +4993,12 @@
4997
4993
  this.length -= from;
4998
4994
  return result;
4999
4995
  }
5000
- sync() {
5001
- if (!this.dom || !this.widget.updateDOM(this.dom)) {
4996
+ sync(view) {
4997
+ if (!this.dom || !this.widget.updateDOM(this.dom, view)) {
5002
4998
  if (this.dom && this.prevWidget)
5003
4999
  this.prevWidget.destroy(this.dom);
5004
5000
  this.prevWidget = null;
5005
- this.setDOM(this.widget.toDOM(this.editorView));
5001
+ this.setDOM(this.widget.toDOM(view));
5006
5002
  this.dom.contentEditable = "false";
5007
5003
  }
5008
5004
  }
@@ -5035,7 +5031,7 @@
5035
5031
  let top = this;
5036
5032
  while (top.parent)
5037
5033
  top = top.parent;
5038
- let view = top.editorView, text = view && view.state.doc, start = this.posAtStart;
5034
+ let { view } = top, text = view && view.state.doc, start = this.posAtStart;
5039
5035
  return text ? text.slice(start, start + this.length) : Text.empty;
5040
5036
  }
5041
5037
  domAtPos(pos) {
@@ -5054,6 +5050,7 @@
5054
5050
  return this.length ? rect : flattenRect(rect, this.side > 0);
5055
5051
  }
5056
5052
  get isEditable() { return false; }
5053
+ get isWidget() { return true; }
5057
5054
  destroy() {
5058
5055
  super.destroy();
5059
5056
  if (this.dom)
@@ -5116,8 +5113,9 @@
5116
5113
  }
5117
5114
  function posFromDOMInCompositionTree(node, offset, view, text) {
5118
5115
  if (view instanceof MarkView) {
5116
+ let pos = 0;
5119
5117
  for (let child of view.children) {
5120
- let pos = 0, hasComp = contains(child.dom, text);
5118
+ let hasComp = contains(child.dom, text);
5121
5119
  if (contains(child.dom, node))
5122
5120
  return pos + (hasComp ? posFromDOMInCompositionTree(node, offset, child, text) : child.localPosFromDOM(node, offset));
5123
5121
  pos += hasComp ? text.nodeValue.length : child.length;
@@ -5151,7 +5149,7 @@
5151
5149
  }
5152
5150
  }
5153
5151
  getSide() { return this.side; }
5154
- domAtPos(pos) { return DOMPos.before(this.dom); }
5152
+ domAtPos(pos) { return this.side > 0 ? DOMPos.before(this.dom) : DOMPos.after(this.dom); }
5155
5153
  localPosFromDOM() { return 0; }
5156
5154
  domBoundsAround() { return null; }
5157
5155
  coordsAt(pos) {
@@ -5327,7 +5325,7 @@
5327
5325
  couldn't (in which case the widget will be redrawn). The default
5328
5326
  implementation just returns false.
5329
5327
  */
5330
- updateDOM(dom) { return false; }
5328
+ updateDOM(dom, view) { return false; }
5331
5329
  /**
5332
5330
  @internal
5333
5331
  */
@@ -5642,7 +5640,7 @@
5642
5640
  this.dirty |= 4 /* Dirty.Attrs */ | 2 /* Dirty.Node */;
5643
5641
  }
5644
5642
  }
5645
- sync(track) {
5643
+ sync(view, track) {
5646
5644
  var _a;
5647
5645
  if (!this.dom) {
5648
5646
  this.setDOM(document.createElement("div"));
@@ -5659,7 +5657,7 @@
5659
5657
  this.dom.classList.add("cm-line");
5660
5658
  this.prevAttrs = undefined;
5661
5659
  }
5662
- super.sync(track);
5660
+ super.sync(view, track);
5663
5661
  let last = this.dom.lastChild;
5664
5662
  while (last && ContentView.get(last) instanceof MarkView)
5665
5663
  last = last.lastChild;
@@ -5674,7 +5672,7 @@
5674
5672
  measureTextSize() {
5675
5673
  if (this.children.length == 0 || this.length > 20)
5676
5674
  return null;
5677
- let totalWidth = 0;
5675
+ let totalWidth = 0, textHeight;
5678
5676
  for (let child of this.children) {
5679
5677
  if (!(child instanceof TextView) || /[^ -~]/.test(child.text))
5680
5678
  return null;
@@ -5682,14 +5680,26 @@
5682
5680
  if (rects.length != 1)
5683
5681
  return null;
5684
5682
  totalWidth += rects[0].width;
5683
+ textHeight = rects[0].height;
5685
5684
  }
5686
5685
  return !totalWidth ? null : {
5687
5686
  lineHeight: this.dom.getBoundingClientRect().height,
5688
- charWidth: totalWidth / this.length
5687
+ charWidth: totalWidth / this.length,
5688
+ textHeight
5689
5689
  };
5690
5690
  }
5691
5691
  coordsAt(pos, side) {
5692
- return coordsInChildren(this, pos, side);
5692
+ let rect = coordsInChildren(this, pos, side);
5693
+ // Correct rectangle height for empty lines when the returned
5694
+ // height is larger than the text height.
5695
+ if (!this.children.length && rect && this.parent) {
5696
+ let { heightOracle } = this.parent.view.viewState, height = rect.bottom - rect.top;
5697
+ if (Math.abs(height - heightOracle.lineHeight) < 2 && heightOracle.textHeight < height) {
5698
+ let dist = (height - heightOracle.textHeight) / 2;
5699
+ return { top: rect.top + dist, bottom: rect.bottom - dist, left: rect.left, right: rect.left };
5700
+ }
5701
+ }
5702
+ return rect;
5693
5703
  }
5694
5704
  become(_other) { return false; }
5695
5705
  get type() { return BlockType.Text; }
@@ -5734,12 +5744,12 @@
5734
5744
  return end;
5735
5745
  }
5736
5746
  get children() { return noChildren; }
5737
- sync() {
5738
- if (!this.dom || !this.widget.updateDOM(this.dom)) {
5747
+ sync(view) {
5748
+ if (!this.dom || !this.widget.updateDOM(this.dom, view)) {
5739
5749
  if (this.dom && this.prevWidget)
5740
5750
  this.prevWidget.destroy(this.dom);
5741
5751
  this.prevWidget = null;
5742
- this.setDOM(this.widget.toDOM(this.editorView));
5752
+ this.setDOM(this.widget.toDOM(view));
5743
5753
  this.dom.contentEditable = "false";
5744
5754
  }
5745
5755
  }
@@ -5763,6 +5773,8 @@
5763
5773
  }
5764
5774
  ignoreMutation() { return true; }
5765
5775
  ignoreEvent(event) { return this.widget.ignoreEvent(event); }
5776
+ get isEditable() { return false; }
5777
+ get isWidget() { return true; }
5766
5778
  destroy() {
5767
5779
  super.destroy();
5768
5780
  if (this.dom)
@@ -5944,6 +5956,7 @@
5944
5956
  const exceptionSink = /*@__PURE__*/Facet.define();
5945
5957
  const updateListener = /*@__PURE__*/Facet.define();
5946
5958
  const inputHandler$1 = /*@__PURE__*/Facet.define();
5959
+ const focusChangeEffect = /*@__PURE__*/Facet.define();
5947
5960
  const perLineTextDirection = /*@__PURE__*/Facet.define({
5948
5961
  combine: values => values.some(x => x)
5949
5962
  });
@@ -6186,11 +6199,6 @@
6186
6199
  let changedRanges = [];
6187
6200
  this.changes.iterChangedRanges((fromA, toA, fromB, toB) => changedRanges.push(new ChangedRange(fromA, toA, fromB, toB)));
6188
6201
  this.changedRanges = changedRanges;
6189
- let focus = view.hasFocus;
6190
- if (focus != view.inputState.notifiedFocused) {
6191
- view.inputState.notifiedFocused = focus;
6192
- this.flags |= 1 /* UpdateFlag.Focus */;
6193
- }
6194
6202
  }
6195
6203
  /**
6196
6204
  @internal
@@ -6693,7 +6701,6 @@
6693
6701
  this.updateDeco();
6694
6702
  this.updateInner([new ChangedRange(0, 0, 0, view.state.doc.length)], 0);
6695
6703
  }
6696
- get editorView() { return this.view; }
6697
6704
  get length() { return this.view.state.doc.length; }
6698
6705
  // Update the document view to a given state. scrollIntoView can be
6699
6706
  // used as a hint to compute a new viewport that includes that
@@ -6753,7 +6760,7 @@
6753
6760
  // selection from the one it displays (issue #218). This tries
6754
6761
  // to detect that situation.
6755
6762
  let track = browser.chrome || browser.ios ? { node: observer.selectionRange.focusNode, written: false } : undefined;
6756
- this.sync(track);
6763
+ this.sync(this.view, track);
6757
6764
  this.dirty = 0 /* Dirty.Not */;
6758
6765
  if (track && (track.written || observer.selectionRange.focusNode != track.node))
6759
6766
  this.forceSelection = true;
@@ -6972,7 +6979,7 @@
6972
6979
  }
6973
6980
  }
6974
6981
  // If no workable line exists, force a layout of a measurable element
6975
- let dummy = document.createElement("div"), lineHeight, charWidth;
6982
+ let dummy = document.createElement("div"), lineHeight, charWidth, textHeight;
6976
6983
  dummy.className = "cm-line";
6977
6984
  dummy.style.width = "99999px";
6978
6985
  dummy.textContent = "abc def ghi jkl mno pqr stu";
@@ -6981,9 +6988,10 @@
6981
6988
  let rect = clientRectsFor(dummy.firstChild)[0];
6982
6989
  lineHeight = dummy.getBoundingClientRect().height;
6983
6990
  charWidth = rect ? rect.width / 27 : 7;
6991
+ textHeight = rect ? rect.height : lineHeight;
6984
6992
  dummy.remove();
6985
6993
  });
6986
- return { lineHeight, charWidth };
6994
+ return { lineHeight, charWidth, textHeight };
6987
6995
  }
6988
6996
  childCursor(pos = this.length) {
6989
6997
  // Move back to start of last element when possible, so that
@@ -7148,22 +7156,32 @@
7148
7156
  ignoreEvent() { return false; }
7149
7157
  get customView() { return CompositionView; }
7150
7158
  }
7151
- function nearbyTextNode(node, offset, side) {
7152
- for (;;) {
7153
- if (node.nodeType == 3)
7154
- return node;
7155
- if (node.nodeType == 1 && offset > 0 && side <= 0) {
7156
- node = node.childNodes[offset - 1];
7157
- offset = maxOffset(node);
7158
- }
7159
- else if (node.nodeType == 1 && offset < node.childNodes.length && side >= 0) {
7160
- node = node.childNodes[offset];
7161
- offset = 0;
7159
+ function nearbyTextNode(startNode, startOffset, side) {
7160
+ if (side <= 0)
7161
+ for (let node = startNode, offset = startOffset;;) {
7162
+ if (node.nodeType == 3)
7163
+ return node;
7164
+ if (node.nodeType == 1 && offset > 0) {
7165
+ node = node.childNodes[offset - 1];
7166
+ offset = maxOffset(node);
7167
+ }
7168
+ else {
7169
+ break;
7170
+ }
7162
7171
  }
7163
- else {
7164
- return null;
7172
+ if (side >= 0)
7173
+ for (let node = startNode, offset = startOffset;;) {
7174
+ if (node.nodeType == 3)
7175
+ return node;
7176
+ if (node.nodeType == 1 && offset < node.childNodes.length && side >= 0) {
7177
+ node = node.childNodes[offset];
7178
+ offset = 0;
7179
+ }
7180
+ else {
7181
+ break;
7182
+ }
7165
7183
  }
7166
- }
7184
+ return null;
7167
7185
  }
7168
7186
  function nextToUneditable(node, offset) {
7169
7187
  if (node.nodeType != 1)
@@ -7326,11 +7344,11 @@
7326
7344
  }
7327
7345
  return { node, offset: closestOffset > -1 ? closestOffset : generalSide > 0 ? node.nodeValue.length : 0 };
7328
7346
  }
7329
- function posAtCoords(view, { x, y }, precise, bias = -1) {
7330
- var _a;
7347
+ function posAtCoords(view, coords, precise, bias = -1) {
7348
+ var _a, _b;
7331
7349
  let content = view.contentDOM.getBoundingClientRect(), docTop = content.top + view.viewState.paddingTop;
7332
7350
  let block, { docHeight } = view.viewState;
7333
- let yOffset = y - docTop;
7351
+ let { x, y } = coords, yOffset = y - docTop;
7334
7352
  if (yOffset < 0)
7335
7353
  return 0;
7336
7354
  if (yOffset > docHeight)
@@ -7401,7 +7419,17 @@
7401
7419
  return yOffset > block.top + block.height / 2 ? block.to : block.from;
7402
7420
  ({ node, offset } = domPosAtCoords(line.dom, x, y));
7403
7421
  }
7404
- return view.docView.posFromDOM(node, offset);
7422
+ let nearest = view.docView.nearest(node);
7423
+ if (!nearest)
7424
+ return null;
7425
+ if (nearest.isWidget && ((_b = nearest.dom) === null || _b === void 0 ? void 0 : _b.nodeType) == 1) {
7426
+ let rect = nearest.dom.getBoundingClientRect();
7427
+ return coords.y < rect.top || coords.y <= rect.bottom && coords.x <= (rect.left + rect.right) / 2
7428
+ ? nearest.posAtStart : nearest.posAtEnd;
7429
+ }
7430
+ else {
7431
+ return nearest.localPosFromDOM(node, offset) + nearest.posAtStart;
7432
+ }
7405
7433
  }
7406
7434
  function posAtCoordsImprecise(view, contentRect, block, x, y) {
7407
7435
  let into = Math.round((x - contentRect.left) * view.defaultCharacterWidth);
@@ -7589,8 +7617,16 @@
7589
7617
  this.registeredEvents.push(type);
7590
7618
  }
7591
7619
  view.scrollDOM.addEventListener("mousedown", (event) => {
7592
- if (event.target == view.scrollDOM)
7620
+ if (event.target == view.scrollDOM && event.clientY > view.contentDOM.getBoundingClientRect().bottom) {
7593
7621
  handleEvent(handlers.mousedown, event);
7622
+ if (!event.defaultPrevented && event.button == 2) {
7623
+ // Make sure the content covers the entire scroller height, in order
7624
+ // to catch a native context menu click below it
7625
+ let start = view.contentDOM.style.minHeight;
7626
+ view.contentDOM.style.minHeight = "100%";
7627
+ setTimeout(() => view.contentDOM.style.minHeight = start, 200);
7628
+ }
7629
+ }
7594
7630
  });
7595
7631
  if (browser.chrome && browser.chrome_version == 102) { // FIXME remove at some point
7596
7632
  // On Chrome 102, viewport updates somehow stop wheel-based
@@ -7767,11 +7803,13 @@
7767
7803
  this.multiple = view.state.facet(EditorState.allowMultipleSelections) && addsSelectionRange(view, startEvent);
7768
7804
  this.dragMove = dragMovesSelection(view, startEvent);
7769
7805
  this.dragging = isInPrimarySelection(view, startEvent) && getClickType(startEvent) == 1 ? null : false;
7806
+ }
7807
+ start(event) {
7770
7808
  // When clicking outside of the selection, immediately apply the
7771
7809
  // effect of starting the selection
7772
7810
  if (this.dragging === false) {
7773
- startEvent.preventDefault();
7774
- this.select(startEvent);
7811
+ event.preventDefault();
7812
+ this.select(event);
7775
7813
  }
7776
7814
  }
7777
7815
  move(event) {
@@ -7963,9 +8001,11 @@
7963
8001
  style = basicMouseSelection(view, event);
7964
8002
  if (style) {
7965
8003
  let mustFocus = view.root.activeElement != view.contentDOM;
8004
+ view.inputState.startMouseSelection(new MouseSelection(view, event, style, mustFocus));
7966
8005
  if (mustFocus)
7967
8006
  view.observer.ignore(() => focusPreventScroll(view.contentDOM));
7968
- view.inputState.startMouseSelection(new MouseSelection(view, event, style, mustFocus));
8007
+ if (view.inputState.mouseSelection)
8008
+ view.inputState.mouseSelection.start(event);
7969
8009
  }
7970
8010
  };
7971
8011
  function rangeForClick(view, pos, bias, type) {
@@ -8120,7 +8160,7 @@
8120
8160
  view.observer.flush();
8121
8161
  let data = brokenClipboardAPI ? null : event.clipboardData;
8122
8162
  if (data) {
8123
- doPaste(view, data.getData("text/plain"));
8163
+ doPaste(view, data.getData("text/plain") || data.getData("text/uri-text"));
8124
8164
  event.preventDefault();
8125
8165
  }
8126
8166
  else {
@@ -8188,10 +8228,26 @@
8188
8228
  userEvent: "delete.cut"
8189
8229
  });
8190
8230
  };
8231
+ const isFocusChange = /*@__PURE__*/Annotation.define();
8232
+ function focusChangeTransaction(state, focus) {
8233
+ let effects = [];
8234
+ for (let getEffect of state.facet(focusChangeEffect)) {
8235
+ let effect = getEffect(state, focus);
8236
+ if (effect)
8237
+ effects.push(effect);
8238
+ }
8239
+ return effects ? state.update({ effects, annotations: isFocusChange.of(true) }) : null;
8240
+ }
8191
8241
  function updateForFocusChange(view) {
8192
8242
  setTimeout(() => {
8193
- if (view.hasFocus != view.inputState.notifiedFocused)
8194
- view.update([]);
8243
+ let focus = view.hasFocus;
8244
+ if (focus != view.inputState.notifiedFocused) {
8245
+ let tr = focusChangeTransaction(view.state, focus);
8246
+ if (tr)
8247
+ view.dispatch(tr);
8248
+ else
8249
+ view.update([]);
8250
+ }
8195
8251
  }, 10);
8196
8252
  }
8197
8253
  handlers.focus = view => {
@@ -8264,8 +8320,9 @@
8264
8320
  this.lineWrapping = lineWrapping;
8265
8321
  this.doc = Text.empty;
8266
8322
  this.heightSamples = {};
8267
- this.lineHeight = 14;
8323
+ this.lineHeight = 14; // The height of an entire line (line-height)
8268
8324
  this.charWidth = 7;
8325
+ this.textHeight = 14; // The height of the actual font (font-size)
8269
8326
  this.lineLength = 30;
8270
8327
  // Used to track, during updateHeight, if any actual heights changed
8271
8328
  this.heightChanged = false;
@@ -8273,7 +8330,7 @@
8273
8330
  heightForGap(from, to) {
8274
8331
  let lines = this.doc.lineAt(to).number - this.doc.lineAt(from).number + 1;
8275
8332
  if (this.lineWrapping)
8276
- lines += Math.ceil(((to - from) - (lines * this.lineLength * 0.5)) / this.lineLength);
8333
+ lines += Math.max(0, Math.ceil(((to - from) - (lines * this.lineLength * 0.5)) / this.lineLength));
8277
8334
  return this.lineHeight * lines;
8278
8335
  }
8279
8336
  heightForLine(length) {
@@ -8300,12 +8357,13 @@
8300
8357
  }
8301
8358
  return newHeight;
8302
8359
  }
8303
- refresh(whiteSpace, lineHeight, charWidth, lineLength, knownHeights) {
8360
+ refresh(whiteSpace, lineHeight, charWidth, textHeight, lineLength, knownHeights) {
8304
8361
  let lineWrapping = wrappingWhiteSpace.indexOf(whiteSpace) > -1;
8305
8362
  let changed = Math.round(lineHeight) != Math.round(this.lineHeight) || this.lineWrapping != lineWrapping;
8306
8363
  this.lineWrapping = lineWrapping;
8307
8364
  this.lineHeight = lineHeight;
8308
8365
  this.charWidth = charWidth;
8366
+ this.textHeight = textHeight;
8309
8367
  this.lineLength = lineLength;
8310
8368
  if (changed) {
8311
8369
  this.heightSamples = {};
@@ -8418,11 +8476,11 @@
8418
8476
  decomposeLeft(_to, result) { result.push(this); }
8419
8477
  decomposeRight(_from, result) { result.push(this); }
8420
8478
  applyChanges(decorations, oldDoc, oracle, changes) {
8421
- let me = this;
8479
+ let me = this, doc = oracle.doc;
8422
8480
  for (let i = changes.length - 1; i >= 0; i--) {
8423
8481
  let { fromA, toA, fromB, toB } = changes[i];
8424
- let start = me.lineAt(fromA, QueryType$1.ByPosNoHeight, oldDoc, 0, 0);
8425
- let end = start.to >= toA ? start : me.lineAt(toA, QueryType$1.ByPosNoHeight, oldDoc, 0, 0);
8482
+ let start = me.lineAt(fromA, QueryType$1.ByPosNoHeight, oracle.setDoc(oldDoc), 0, 0);
8483
+ let end = start.to >= toA ? start : me.lineAt(toA, QueryType$1.ByPosNoHeight, oracle, 0, 0);
8426
8484
  toB += end.to - toA;
8427
8485
  toA = end.to;
8428
8486
  while (i > 0 && start.from <= changes[i - 1].toA) {
@@ -8430,11 +8488,11 @@
8430
8488
  fromB = changes[i - 1].fromB;
8431
8489
  i--;
8432
8490
  if (fromA < start.from)
8433
- start = me.lineAt(fromA, QueryType$1.ByPosNoHeight, oldDoc, 0, 0);
8491
+ start = me.lineAt(fromA, QueryType$1.ByPosNoHeight, oracle, 0, 0);
8434
8492
  }
8435
8493
  fromB += start.from - fromA;
8436
8494
  fromA = start.from;
8437
- let nodes = NodeBuilder.build(oracle, decorations, fromB, toB);
8495
+ let nodes = NodeBuilder.build(oracle.setDoc(doc), decorations, fromB, toB);
8438
8496
  me = me.replace(fromA, toA, nodes);
8439
8497
  }
8440
8498
  return me.updateHeight(oracle, 0);
@@ -8501,15 +8559,15 @@
8501
8559
  super(length, height);
8502
8560
  this.type = type;
8503
8561
  }
8504
- blockAt(_height, _doc, top, offset) {
8562
+ blockAt(_height, _oracle, top, offset) {
8505
8563
  return new BlockInfo(offset, this.length, top, this.height, this.type);
8506
8564
  }
8507
- lineAt(_value, _type, doc, top, offset) {
8508
- return this.blockAt(0, doc, top, offset);
8565
+ lineAt(_value, _type, oracle, top, offset) {
8566
+ return this.blockAt(0, oracle, top, offset);
8509
8567
  }
8510
- forEachLine(from, to, doc, top, offset, f) {
8568
+ forEachLine(from, to, oracle, top, offset, f) {
8511
8569
  if (from <= offset + this.length && to >= offset)
8512
- f(this.blockAt(0, doc, top, offset));
8570
+ f(this.blockAt(0, oracle, top, offset));
8513
8571
  }
8514
8572
  updateHeight(oracle, offset = 0, _force = false, measured) {
8515
8573
  if (measured && measured.from <= offset && measured.more)
@@ -8555,35 +8613,60 @@
8555
8613
  }
8556
8614
  class HeightMapGap extends HeightMap {
8557
8615
  constructor(length) { super(length, 0); }
8558
- lines(doc, offset) {
8559
- let firstLine = doc.lineAt(offset).number, lastLine = doc.lineAt(offset + this.length).number;
8560
- return { firstLine, lastLine, lineHeight: this.height / (lastLine - firstLine + 1) };
8616
+ heightMetrics(oracle, offset) {
8617
+ let firstLine = oracle.doc.lineAt(offset).number, lastLine = oracle.doc.lineAt(offset + this.length).number;
8618
+ let lines = lastLine - firstLine + 1;
8619
+ let perLine, perChar = 0;
8620
+ if (oracle.lineWrapping) {
8621
+ let totalPerLine = Math.min(this.height, oracle.lineHeight * lines);
8622
+ perLine = totalPerLine / lines;
8623
+ perChar = (this.height - totalPerLine) / (this.length - lines - 1);
8624
+ }
8625
+ else {
8626
+ perLine = this.height / lines;
8627
+ }
8628
+ return { firstLine, lastLine, perLine, perChar };
8561
8629
  }
8562
- blockAt(height, doc, top, offset) {
8563
- let { firstLine, lastLine, lineHeight } = this.lines(doc, offset);
8564
- let line = Math.max(0, Math.min(lastLine - firstLine, Math.floor((height - top) / lineHeight)));
8565
- let { from, length } = doc.line(firstLine + line);
8566
- return new BlockInfo(from, length, top + lineHeight * line, lineHeight, BlockType.Text);
8630
+ blockAt(height, oracle, top, offset) {
8631
+ let { firstLine, lastLine, perLine, perChar } = this.heightMetrics(oracle, offset);
8632
+ if (oracle.lineWrapping) {
8633
+ let guess = offset + Math.round(Math.max(0, Math.min(1, (height - top) / this.height)) * this.length);
8634
+ let line = oracle.doc.lineAt(guess), lineHeight = perLine + line.length * perChar;
8635
+ let lineTop = Math.max(top, height - lineHeight / 2);
8636
+ return new BlockInfo(line.from, line.length, lineTop, lineHeight, BlockType.Text);
8637
+ }
8638
+ else {
8639
+ let line = Math.max(0, Math.min(lastLine - firstLine, Math.floor((height - top) / perLine)));
8640
+ let { from, length } = oracle.doc.line(firstLine + line);
8641
+ return new BlockInfo(from, length, top + perLine * line, perLine, BlockType.Text);
8642
+ }
8567
8643
  }
8568
- lineAt(value, type, doc, top, offset) {
8644
+ lineAt(value, type, oracle, top, offset) {
8569
8645
  if (type == QueryType$1.ByHeight)
8570
- return this.blockAt(value, doc, top, offset);
8646
+ return this.blockAt(value, oracle, top, offset);
8571
8647
  if (type == QueryType$1.ByPosNoHeight) {
8572
- let { from, to } = doc.lineAt(value);
8648
+ let { from, to } = oracle.doc.lineAt(value);
8573
8649
  return new BlockInfo(from, to - from, 0, 0, BlockType.Text);
8574
8650
  }
8575
- let { firstLine, lineHeight } = this.lines(doc, offset);
8576
- let { from, length, number } = doc.lineAt(value);
8577
- return new BlockInfo(from, length, top + lineHeight * (number - firstLine), lineHeight, BlockType.Text);
8578
- }
8579
- forEachLine(from, to, doc, top, offset, f) {
8580
- let { firstLine, lineHeight } = this.lines(doc, offset);
8581
- for (let pos = Math.max(from, offset), end = Math.min(offset + this.length, to); pos <= end;) {
8582
- let line = doc.lineAt(pos);
8583
- if (pos == from)
8584
- top += lineHeight * (line.number - firstLine);
8585
- f(new BlockInfo(line.from, line.length, top, lineHeight, BlockType.Text));
8586
- top += lineHeight;
8651
+ let { firstLine, perLine, perChar } = this.heightMetrics(oracle, offset);
8652
+ let line = oracle.doc.lineAt(value), lineHeight = perLine + line.length * perChar;
8653
+ let linesAbove = line.number - firstLine;
8654
+ let lineTop = top + perLine * linesAbove + perChar * (line.from - offset - linesAbove);
8655
+ return new BlockInfo(line.from, line.length, Math.max(top, Math.min(lineTop, top + this.height - lineHeight)), lineHeight, BlockType.Text);
8656
+ }
8657
+ forEachLine(from, to, oracle, top, offset, f) {
8658
+ from = Math.max(from, offset);
8659
+ to = Math.min(to, offset + this.length);
8660
+ let { firstLine, perLine, perChar } = this.heightMetrics(oracle, offset);
8661
+ for (let pos = from, lineTop = top; pos <= to;) {
8662
+ let line = oracle.doc.lineAt(pos);
8663
+ if (pos == from) {
8664
+ let linesAbove = line.number - firstLine;
8665
+ lineTop += perLine * linesAbove + perChar * (from - offset - linesAbove);
8666
+ }
8667
+ let lineHeight = perLine + perChar * line.length;
8668
+ f(new BlockInfo(line.from, line.length, lineTop, lineHeight, BlockType.Text));
8669
+ lineTop += lineHeight;
8587
8670
  pos = line.to + 1;
8588
8671
  }
8589
8672
  }
@@ -8619,7 +8702,6 @@
8619
8702
  // they would already have been added to the heightmap (gaps
8620
8703
  // only contain plain text).
8621
8704
  let nodes = [], pos = Math.max(offset, measured.from), singleHeight = -1;
8622
- let wasChanged = oracle.heightChanged;
8623
8705
  if (measured.from > offset)
8624
8706
  nodes.push(new HeightMapGap(measured.from - offset - 1).updateHeight(oracle, offset));
8625
8707
  while (pos <= end && measured.more) {
@@ -8639,8 +8721,9 @@
8639
8721
  if (pos <= end)
8640
8722
  nodes.push(null, new HeightMapGap(end - pos).updateHeight(oracle, pos));
8641
8723
  let result = HeightMap.of(nodes);
8642
- oracle.heightChanged = wasChanged || singleHeight < 0 || Math.abs(result.height - this.height) >= Epsilon ||
8643
- Math.abs(singleHeight - this.lines(oracle.doc, offset).lineHeight) >= Epsilon;
8724
+ if (singleHeight < 0 || Math.abs(result.height - this.height) >= Epsilon ||
8725
+ Math.abs(singleHeight - this.heightMetrics(oracle, offset).perLine) >= Epsilon)
8726
+ oracle.heightChanged = true;
8644
8727
  return result;
8645
8728
  }
8646
8729
  else if (force || this.outdated) {
@@ -8659,40 +8742,40 @@
8659
8742
  this.size = left.size + right.size;
8660
8743
  }
8661
8744
  get break() { return this.flags & 1 /* Flag.Break */; }
8662
- blockAt(height, doc, top, offset) {
8745
+ blockAt(height, oracle, top, offset) {
8663
8746
  let mid = top + this.left.height;
8664
- return height < mid ? this.left.blockAt(height, doc, top, offset)
8665
- : this.right.blockAt(height, doc, mid, offset + this.left.length + this.break);
8747
+ return height < mid ? this.left.blockAt(height, oracle, top, offset)
8748
+ : this.right.blockAt(height, oracle, mid, offset + this.left.length + this.break);
8666
8749
  }
8667
- lineAt(value, type, doc, top, offset) {
8750
+ lineAt(value, type, oracle, top, offset) {
8668
8751
  let rightTop = top + this.left.height, rightOffset = offset + this.left.length + this.break;
8669
8752
  let left = type == QueryType$1.ByHeight ? value < rightTop : value < rightOffset;
8670
- let base = left ? this.left.lineAt(value, type, doc, top, offset)
8671
- : this.right.lineAt(value, type, doc, rightTop, rightOffset);
8753
+ let base = left ? this.left.lineAt(value, type, oracle, top, offset)
8754
+ : this.right.lineAt(value, type, oracle, rightTop, rightOffset);
8672
8755
  if (this.break || (left ? base.to < rightOffset : base.from > rightOffset))
8673
8756
  return base;
8674
8757
  let subQuery = type == QueryType$1.ByPosNoHeight ? QueryType$1.ByPosNoHeight : QueryType$1.ByPos;
8675
8758
  if (left)
8676
- return base.join(this.right.lineAt(rightOffset, subQuery, doc, rightTop, rightOffset));
8759
+ return base.join(this.right.lineAt(rightOffset, subQuery, oracle, rightTop, rightOffset));
8677
8760
  else
8678
- return this.left.lineAt(rightOffset, subQuery, doc, top, offset).join(base);
8761
+ return this.left.lineAt(rightOffset, subQuery, oracle, top, offset).join(base);
8679
8762
  }
8680
- forEachLine(from, to, doc, top, offset, f) {
8763
+ forEachLine(from, to, oracle, top, offset, f) {
8681
8764
  let rightTop = top + this.left.height, rightOffset = offset + this.left.length + this.break;
8682
8765
  if (this.break) {
8683
8766
  if (from < rightOffset)
8684
- this.left.forEachLine(from, to, doc, top, offset, f);
8767
+ this.left.forEachLine(from, to, oracle, top, offset, f);
8685
8768
  if (to >= rightOffset)
8686
- this.right.forEachLine(from, to, doc, rightTop, rightOffset, f);
8769
+ this.right.forEachLine(from, to, oracle, rightTop, rightOffset, f);
8687
8770
  }
8688
8771
  else {
8689
- let mid = this.lineAt(rightOffset, QueryType$1.ByPos, doc, top, offset);
8772
+ let mid = this.lineAt(rightOffset, QueryType$1.ByPos, oracle, top, offset);
8690
8773
  if (from < mid.from)
8691
- this.left.forEachLine(from, mid.from - 1, doc, top, offset, f);
8774
+ this.left.forEachLine(from, mid.from - 1, oracle, top, offset, f);
8692
8775
  if (mid.to >= from && mid.from <= to)
8693
8776
  f(mid);
8694
8777
  if (to > mid.to)
8695
- this.right.forEachLine(mid.to + 1, to, doc, rightTop, rightOffset, f);
8778
+ this.right.forEachLine(mid.to + 1, to, oracle, rightTop, rightOffset, f);
8696
8779
  }
8697
8780
  }
8698
8781
  replace(from, to, nodes) {
@@ -9042,11 +9125,11 @@
9042
9125
  }
9043
9126
  this.viewports = viewports.sort((a, b) => a.from - b.from);
9044
9127
  this.scaler = this.heightMap.height <= 7000000 /* VP.MaxDOMHeight */ ? IdScaler :
9045
- new BigScaler(this.heightOracle.doc, this.heightMap, this.viewports);
9128
+ new BigScaler(this.heightOracle, this.heightMap, this.viewports);
9046
9129
  }
9047
9130
  updateViewportLines() {
9048
9131
  this.viewportLines = [];
9049
- this.heightMap.forEachLine(this.viewport.from, this.viewport.to, this.state.doc, 0, 0, block => {
9132
+ this.heightMap.forEachLine(this.viewport.from, this.viewport.to, this.heightOracle.setDoc(this.state.doc), 0, 0, block => {
9050
9133
  this.viewportLines.push(this.scaler.scale == 1 ? block : scaleBlock(block, this.scaler));
9051
9134
  });
9052
9135
  }
@@ -9086,8 +9169,9 @@
9086
9169
  let whiteSpace = style.whiteSpace;
9087
9170
  this.defaultTextDirection = style.direction == "rtl" ? Direction.RTL : Direction.LTR;
9088
9171
  let refresh = this.heightOracle.mustRefreshForWrapping(whiteSpace);
9089
- let measureContent = refresh || this.mustMeasureContent || this.contentDOMHeight != dom.clientHeight;
9090
- this.contentDOMHeight = dom.clientHeight;
9172
+ let domRect = dom.getBoundingClientRect();
9173
+ let measureContent = refresh || this.mustMeasureContent || this.contentDOMHeight != domRect.height;
9174
+ this.contentDOMHeight = domRect.height;
9091
9175
  this.mustMeasureContent = false;
9092
9176
  let result = 0, bias = 0;
9093
9177
  // Vertical padding
@@ -9115,9 +9199,9 @@
9115
9199
  }
9116
9200
  if (!this.inView && !this.scrollTarget)
9117
9201
  return 0;
9118
- let contentWidth = dom.clientWidth;
9202
+ let contentWidth = domRect.width;
9119
9203
  if (this.contentDOMWidth != contentWidth || this.editorHeight != view.scrollDOM.clientHeight) {
9120
- this.contentDOMWidth = contentWidth;
9204
+ this.contentDOMWidth = domRect.width;
9121
9205
  this.editorHeight = view.scrollDOM.clientHeight;
9122
9206
  result |= 8 /* UpdateFlag.Geometry */;
9123
9207
  }
@@ -9126,8 +9210,8 @@
9126
9210
  if (oracle.mustRefreshForHeights(lineHeights))
9127
9211
  refresh = true;
9128
9212
  if (refresh || oracle.lineWrapping && Math.abs(contentWidth - this.contentDOMWidth) > oracle.charWidth) {
9129
- let { lineHeight, charWidth } = view.docView.measureTextSize();
9130
- refresh = lineHeight > 0 && oracle.refresh(whiteSpace, lineHeight, charWidth, contentWidth / charWidth, lineHeights);
9213
+ let { lineHeight, charWidth, textHeight } = view.docView.measureTextSize();
9214
+ refresh = lineHeight > 0 && oracle.refresh(whiteSpace, lineHeight, charWidth, textHeight, contentWidth / charWidth, lineHeights);
9131
9215
  if (refresh) {
9132
9216
  view.docView.minWidth = 0;
9133
9217
  result |= 8 /* UpdateFlag.Geometry */;
@@ -9146,7 +9230,8 @@
9146
9230
  result |= 2 /* UpdateFlag.Height */;
9147
9231
  }
9148
9232
  let viewportChange = !this.viewportIsAppropriate(this.viewport, bias) ||
9149
- this.scrollTarget && (this.scrollTarget.range.head < this.viewport.from || this.scrollTarget.range.head > this.viewport.to);
9233
+ this.scrollTarget && (this.scrollTarget.range.head < this.viewport.from ||
9234
+ this.scrollTarget.range.head > this.viewport.to);
9150
9235
  if (viewportChange)
9151
9236
  this.viewport = this.getViewport(bias, this.scrollTarget);
9152
9237
  this.updateForViewport();
@@ -9172,36 +9257,37 @@
9172
9257
  // bottom, depending on the bias (the change in viewport position
9173
9258
  // since the last update). It'll hold a number between 0 and 1
9174
9259
  let marginTop = 0.5 - Math.max(-0.5, Math.min(0.5, bias / 1000 /* VP.Margin */ / 2));
9175
- let map = this.heightMap, doc = this.state.doc, { visibleTop, visibleBottom } = this;
9176
- let viewport = new Viewport(map.lineAt(visibleTop - marginTop * 1000 /* VP.Margin */, QueryType$1.ByHeight, doc, 0, 0).from, map.lineAt(visibleBottom + (1 - marginTop) * 1000 /* VP.Margin */, QueryType$1.ByHeight, doc, 0, 0).to);
9260
+ let map = this.heightMap, oracle = this.heightOracle;
9261
+ let { visibleTop, visibleBottom } = this;
9262
+ let viewport = new Viewport(map.lineAt(visibleTop - marginTop * 1000 /* VP.Margin */, QueryType$1.ByHeight, oracle, 0, 0).from, map.lineAt(visibleBottom + (1 - marginTop) * 1000 /* VP.Margin */, QueryType$1.ByHeight, oracle, 0, 0).to);
9177
9263
  // If scrollTarget is given, make sure the viewport includes that position
9178
9264
  if (scrollTarget) {
9179
9265
  let { head } = scrollTarget.range;
9180
9266
  if (head < viewport.from || head > viewport.to) {
9181
9267
  let viewHeight = Math.min(this.editorHeight, this.pixelViewport.bottom - this.pixelViewport.top);
9182
- let block = map.lineAt(head, QueryType$1.ByPos, doc, 0, 0), topPos;
9268
+ let block = map.lineAt(head, QueryType$1.ByPos, oracle, 0, 0), topPos;
9183
9269
  if (scrollTarget.y == "center")
9184
9270
  topPos = (block.top + block.bottom) / 2 - viewHeight / 2;
9185
9271
  else if (scrollTarget.y == "start" || scrollTarget.y == "nearest" && head < viewport.from)
9186
9272
  topPos = block.top;
9187
9273
  else
9188
9274
  topPos = block.bottom - viewHeight;
9189
- viewport = new Viewport(map.lineAt(topPos - 1000 /* VP.Margin */ / 2, QueryType$1.ByHeight, doc, 0, 0).from, map.lineAt(topPos + viewHeight + 1000 /* VP.Margin */ / 2, QueryType$1.ByHeight, doc, 0, 0).to);
9275
+ viewport = new Viewport(map.lineAt(topPos - 1000 /* VP.Margin */ / 2, QueryType$1.ByHeight, oracle, 0, 0).from, map.lineAt(topPos + viewHeight + 1000 /* VP.Margin */ / 2, QueryType$1.ByHeight, oracle, 0, 0).to);
9190
9276
  }
9191
9277
  }
9192
9278
  return viewport;
9193
9279
  }
9194
9280
  mapViewport(viewport, changes) {
9195
9281
  let from = changes.mapPos(viewport.from, -1), to = changes.mapPos(viewport.to, 1);
9196
- return new Viewport(this.heightMap.lineAt(from, QueryType$1.ByPos, this.state.doc, 0, 0).from, this.heightMap.lineAt(to, QueryType$1.ByPos, this.state.doc, 0, 0).to);
9282
+ return new Viewport(this.heightMap.lineAt(from, QueryType$1.ByPos, this.heightOracle, 0, 0).from, this.heightMap.lineAt(to, QueryType$1.ByPos, this.heightOracle, 0, 0).to);
9197
9283
  }
9198
9284
  // Checks if a given viewport covers the visible part of the
9199
9285
  // document and not too much beyond that.
9200
9286
  viewportIsAppropriate({ from, to }, bias = 0) {
9201
9287
  if (!this.inView)
9202
9288
  return true;
9203
- let { top } = this.heightMap.lineAt(from, QueryType$1.ByPos, this.state.doc, 0, 0);
9204
- let { bottom } = this.heightMap.lineAt(to, QueryType$1.ByPos, this.state.doc, 0, 0);
9289
+ let { top } = this.heightMap.lineAt(from, QueryType$1.ByPos, this.heightOracle, 0, 0);
9290
+ let { bottom } = this.heightMap.lineAt(to, QueryType$1.ByPos, this.heightOracle, 0, 0);
9205
9291
  let { visibleTop, visibleBottom } = this;
9206
9292
  return (from == 0 || top <= visibleTop - Math.max(10 /* VP.MinCoverMargin */, Math.min(-bias, 250 /* VP.MaxCoverMargin */))) &&
9207
9293
  (to == this.state.doc.length ||
@@ -9338,13 +9424,13 @@
9338
9424
  }
9339
9425
  lineBlockAt(pos) {
9340
9426
  return (pos >= this.viewport.from && pos <= this.viewport.to && this.viewportLines.find(b => b.from <= pos && b.to >= pos)) ||
9341
- scaleBlock(this.heightMap.lineAt(pos, QueryType$1.ByPos, this.state.doc, 0, 0), this.scaler);
9427
+ scaleBlock(this.heightMap.lineAt(pos, QueryType$1.ByPos, this.heightOracle, 0, 0), this.scaler);
9342
9428
  }
9343
9429
  lineBlockAtHeight(height) {
9344
- return scaleBlock(this.heightMap.lineAt(this.scaler.fromDOM(height), QueryType$1.ByHeight, this.state.doc, 0, 0), this.scaler);
9430
+ return scaleBlock(this.heightMap.lineAt(this.scaler.fromDOM(height), QueryType$1.ByHeight, this.heightOracle, 0, 0), this.scaler);
9345
9431
  }
9346
9432
  elementAtHeight(height) {
9347
- return scaleBlock(this.heightMap.blockAt(this.scaler.fromDOM(height), this.state.doc, 0, 0), this.scaler);
9433
+ return scaleBlock(this.heightMap.blockAt(this.scaler.fromDOM(height), this.heightOracle, 0, 0), this.scaler);
9348
9434
  }
9349
9435
  get docHeight() {
9350
9436
  return this.scaler.toDOM(this.heightMap.height);
@@ -9418,11 +9504,11 @@
9418
9504
  // regions outside the viewports so that the total height is
9419
9505
  // VP.MaxDOMHeight.
9420
9506
  class BigScaler {
9421
- constructor(doc, heightMap, viewports) {
9507
+ constructor(oracle, heightMap, viewports) {
9422
9508
  let vpHeight = 0, base = 0, domBase = 0;
9423
9509
  this.viewports = viewports.map(({ from, to }) => {
9424
- let top = heightMap.lineAt(from, QueryType$1.ByPos, doc, 0, 0).top;
9425
- let bottom = heightMap.lineAt(to, QueryType$1.ByPos, doc, 0, 0).bottom;
9510
+ let top = heightMap.lineAt(from, QueryType$1.ByPos, oracle, 0, 0).top;
9511
+ let bottom = heightMap.lineAt(to, QueryType$1.ByPos, oracle, 0, 0).bottom;
9426
9512
  vpHeight += bottom - top;
9427
9513
  return { from, to, top, bottom, domTop: 0, domBottom: 0 };
9428
9514
  });
@@ -9536,6 +9622,9 @@
9536
9622
  padding: "0 2px 0 6px"
9537
9623
  },
9538
9624
  ".cm-layer": {
9625
+ position: "absolute",
9626
+ left: 0,
9627
+ top: 0,
9539
9628
  contain: "size style",
9540
9629
  "& > *": {
9541
9630
  position: "absolute"
@@ -9575,6 +9664,9 @@
9575
9664
  "&dark .cm-cursor": {
9576
9665
  borderLeftColor: "#444"
9577
9666
  },
9667
+ ".cm-dropCursor": {
9668
+ position: "absolute"
9669
+ },
9578
9670
  "&.cm-focused .cm-cursor": {
9579
9671
  display: "block"
9580
9672
  },
@@ -9786,7 +9878,7 @@
9786
9878
  };
9787
9879
  }
9788
9880
  else if ((browser.mac || browser.android) && change && change.from == change.to && change.from == sel.head - 1 &&
9789
- /^\. ?$/.test(change.insert.toString())) {
9881
+ /^\. ?$/.test(change.insert.toString()) && view.contentDOM.getAttribute("autocorrect") == "off") {
9790
9882
  // Detect insert-period-on-double-space Mac and Android behavior,
9791
9883
  // and transform it into a regular space insert.
9792
9884
  if (newSel && change.insert.length == 2)
@@ -10540,6 +10632,20 @@
10540
10632
  this.viewState.state = state;
10541
10633
  return;
10542
10634
  }
10635
+ let focus = this.hasFocus, focusFlag = 0, dispatchFocus = null;
10636
+ if (transactions.some(tr => tr.annotation(isFocusChange))) {
10637
+ this.inputState.notifiedFocused = focus;
10638
+ // If a focus-change transaction is being dispatched, set this update flag.
10639
+ focusFlag = 1 /* UpdateFlag.Focus */;
10640
+ }
10641
+ else if (focus != this.inputState.notifiedFocused) {
10642
+ this.inputState.notifiedFocused = focus;
10643
+ // Schedule a separate focus transaction if necessary, otherwise
10644
+ // add a flag to this update
10645
+ dispatchFocus = focusChangeTransaction(state, focus);
10646
+ if (!dispatchFocus)
10647
+ focusFlag = 1 /* UpdateFlag.Focus */;
10648
+ }
10543
10649
  // If there was a pending DOM change, eagerly read it and try to
10544
10650
  // apply it after the given transactions.
10545
10651
  let pendingKey = this.observer.delayedAndroidKey, domChange = null;
@@ -10558,6 +10664,7 @@
10558
10664
  if (state.facet(EditorState.phrases) != this.state.facet(EditorState.phrases))
10559
10665
  return this.setState(state);
10560
10666
  update = ViewUpdate.create(this, state, transactions);
10667
+ update.flags |= focusFlag;
10561
10668
  let scrollTarget = this.viewState.scrollTarget;
10562
10669
  try {
10563
10670
  this.updateState = 2 /* UpdateState.Updating */;
@@ -10595,10 +10702,15 @@
10595
10702
  if (!update.empty)
10596
10703
  for (let listener of this.state.facet(updateListener))
10597
10704
  listener(update);
10598
- if (domChange) {
10599
- if (!applyDOMChange(this, domChange) && pendingKey.force)
10600
- dispatchKey(this.contentDOM, pendingKey.key, pendingKey.keyCode);
10601
- }
10705
+ if (dispatchFocus || domChange)
10706
+ Promise.resolve().then(() => {
10707
+ if (dispatchFocus && this.state == dispatchFocus.startState)
10708
+ this.dispatch(dispatchFocus);
10709
+ if (domChange) {
10710
+ if (!applyDOMChange(this, domChange) && pendingKey.force)
10711
+ dispatchKey(this.contentDOM, pendingKey.key, pendingKey.keyCode);
10712
+ }
10713
+ });
10602
10714
  }
10603
10715
  /**
10604
10716
  Reset the view to the given state. (This will cause the entire
@@ -10673,7 +10785,7 @@
10673
10785
  if (this.destroyed)
10674
10786
  return;
10675
10787
  if (this.measureScheduled > -1)
10676
- cancelAnimationFrame(this.measureScheduled);
10788
+ this.win.cancelAnimationFrame(this.measureScheduled);
10677
10789
  this.measureScheduled = 0; // Prevent requestMeasure calls from scheduling another animation frame
10678
10790
  if (flush)
10679
10791
  this.observer.forceFlush();
@@ -11111,7 +11223,7 @@
11111
11223
  this.dom.remove();
11112
11224
  this.observer.destroy();
11113
11225
  if (this.measureScheduled > -1)
11114
- cancelAnimationFrame(this.measureScheduled);
11226
+ this.win.cancelAnimationFrame(this.measureScheduled);
11115
11227
  this.destroyed = true;
11116
11228
  }
11117
11229
  /**
@@ -11200,6 +11312,11 @@
11200
11312
  */
11201
11313
  EditorView.inputHandler = inputHandler$1;
11202
11314
  /**
11315
+ This facet can be used to provide functions that create effects
11316
+ to be dispatched when the editor's focus state changes.
11317
+ */
11318
+ EditorView.focusChangeEffect = focusChangeEffect;
11319
+ /**
11203
11320
  By default, the editor assumes all its content has the same
11204
11321
  [text direction](https://codemirror.net/6/docs/ref/#view.Direction). Configure this with a `true`
11205
11322
  value to make it read the text direction of every (rendered)
@@ -11618,9 +11735,10 @@
11618
11735
  let from = Math.max(range.from, view.viewport.from), to = Math.min(range.to, view.viewport.to);
11619
11736
  let ltr = view.textDirection == Direction.LTR;
11620
11737
  let content = view.contentDOM, contentRect = content.getBoundingClientRect(), base = getBase(view);
11621
- let lineStyle = window.getComputedStyle(content.firstChild);
11622
- let leftSide = contentRect.left + parseInt(lineStyle.paddingLeft) + Math.min(0, parseInt(lineStyle.textIndent));
11623
- let rightSide = contentRect.right - parseInt(lineStyle.paddingRight);
11738
+ let lineElt = content.querySelector(".cm-line"), lineStyle = lineElt && window.getComputedStyle(lineElt);
11739
+ let leftSide = contentRect.left +
11740
+ (lineStyle ? parseInt(lineStyle.paddingLeft) + Math.min(0, parseInt(lineStyle.textIndent)) : 0);
11741
+ let rightSide = contentRect.right - (lineStyle ? parseInt(lineStyle.paddingRight) : 0);
11624
11742
  let startBlock = blockAt(view, from), endBlock = blockAt(view, to);
11625
11743
  let visualStart = startBlock.type == BlockType.Text ? startBlock : null;
11626
11744
  let visualEnd = endBlock.type == BlockType.Text ? endBlock : null;
@@ -12482,6 +12600,7 @@
12482
12600
  });
12483
12601
  }
12484
12602
  });
12603
+ const knownHeight = /*@__PURE__*/new WeakMap();
12485
12604
  const tooltipPlugin = /*@__PURE__*/ViewPlugin.fromClass(class {
12486
12605
  constructor(view) {
12487
12606
  this.view = view;
@@ -12597,6 +12716,7 @@
12597
12716
  };
12598
12717
  }
12599
12718
  writeMeasure(measured) {
12719
+ var _a;
12600
12720
  let { editor, space } = measured;
12601
12721
  let others = [];
12602
12722
  for (let i = 0; i < this.manager.tooltips.length; i++) {
@@ -12612,7 +12732,7 @@
12612
12732
  }
12613
12733
  let arrow = tooltip.arrow ? tView.dom.querySelector(".cm-tooltip-arrow") : null;
12614
12734
  let arrowHeight = arrow ? 7 /* Arrow.Size */ : 0;
12615
- let width = size.right - size.left, height = size.bottom - size.top;
12735
+ let width = size.right - size.left, height = (_a = knownHeight.get(tView)) !== null && _a !== void 0 ? _a : size.bottom - size.top;
12616
12736
  let offset = tView.offset || noOffset, ltr = this.view.textDirection == Direction.LTR;
12617
12737
  let left = size.width > space.right - space.left ? (ltr ? space.left : space.right - size.width)
12618
12738
  : ltr ? Math.min(pos.left - (arrow ? 14 /* Arrow.Offset */ : 0) + offset.x, space.right - width)
@@ -12629,6 +12749,7 @@
12629
12749
  dom.style.top = Outside;
12630
12750
  continue;
12631
12751
  }
12752
+ knownHeight.set(tView, height);
12632
12753
  dom.style.height = (height = spaceVert) + "px";
12633
12754
  }
12634
12755
  else if (dom.style.height) {
@@ -14943,45 +15064,59 @@
14943
15064
  new NodeProp({ perNode: true });
14944
15065
 
14945
15066
  let nextTagID = 0;
14946
- /// Highlighting tags are markers that denote a highlighting category.
14947
- /// They are [associated](#highlight.styleTags) with parts of a syntax
14948
- /// tree by a language mode, and then mapped to an actual CSS style by
14949
- /// a [highlighter](#highlight.Highlighter).
14950
- ///
14951
- /// Because syntax tree node types and highlight styles have to be
14952
- /// able to talk the same language, CodeMirror uses a mostly _closed_
14953
- /// [vocabulary](#highlight.tags) of syntax tags (as opposed to
14954
- /// traditional open string-based systems, which make it hard for
14955
- /// highlighting themes to cover all the tokens produced by the
14956
- /// various languages).
14957
- ///
14958
- /// It _is_ possible to [define](#highlight.Tag^define) your own
14959
- /// highlighting tags for system-internal use (where you control both
14960
- /// the language package and the highlighter), but such tags will not
14961
- /// be picked up by regular highlighters (though you can derive them
14962
- /// from standard tags to allow highlighters to fall back to those).
15067
+ /**
15068
+ Highlighting tags are markers that denote a highlighting category.
15069
+ They are [associated](#highlight.styleTags) with parts of a syntax
15070
+ tree by a language mode, and then mapped to an actual CSS style by
15071
+ a [highlighter](#highlight.Highlighter).
15072
+
15073
+ Because syntax tree node types and highlight styles have to be
15074
+ able to talk the same language, CodeMirror uses a mostly _closed_
15075
+ [vocabulary](#highlight.tags) of syntax tags (as opposed to
15076
+ traditional open string-based systems, which make it hard for
15077
+ highlighting themes to cover all the tokens produced by the
15078
+ various languages).
15079
+
15080
+ It _is_ possible to [define](#highlight.Tag^define) your own
15081
+ highlighting tags for system-internal use (where you control both
15082
+ the language package and the highlighter), but such tags will not
15083
+ be picked up by regular highlighters (though you can derive them
15084
+ from standard tags to allow highlighters to fall back to those).
15085
+ */
14963
15086
  class Tag {
14964
- /// @internal
15087
+ /**
15088
+ @internal
15089
+ */
14965
15090
  constructor(
14966
- /// The set of this tag and all its parent tags, starting with
14967
- /// this one itself and sorted in order of decreasing specificity.
15091
+ /**
15092
+ The set of this tag and all its parent tags, starting with
15093
+ this one itself and sorted in order of decreasing specificity.
15094
+ */
14968
15095
  set,
14969
- /// The base unmodified tag that this one is based on, if it's
14970
- /// modified @internal
15096
+ /**
15097
+ The base unmodified tag that this one is based on, if it's
15098
+ modified @internal
15099
+ */
14971
15100
  base,
14972
- /// The modifiers applied to this.base @internal
15101
+ /**
15102
+ The modifiers applied to this.base @internal
15103
+ */
14973
15104
  modified) {
14974
15105
  this.set = set;
14975
15106
  this.base = base;
14976
15107
  this.modified = modified;
14977
- /// @internal
15108
+ /**
15109
+ @internal
15110
+ */
14978
15111
  this.id = nextTagID++;
14979
15112
  }
14980
- /// Define a new tag. If `parent` is given, the tag is treated as a
14981
- /// sub-tag of that parent, and
14982
- /// [highlighters](#highlight.tagHighlighter) that don't mention
14983
- /// this tag will try to fall back to the parent tag (or grandparent
14984
- /// tag, etc).
15113
+ /**
15114
+ Define a new tag. If `parent` is given, the tag is treated as a
15115
+ sub-tag of that parent, and
15116
+ [highlighters](#highlight.tagHighlighter) that don't mention
15117
+ this tag will try to fall back to the parent tag (or grandparent
15118
+ tag, etc).
15119
+ */
14985
15120
  static define(parent) {
14986
15121
  if (parent === null || parent === void 0 ? void 0 : parent.base)
14987
15122
  throw new Error("Can not derive from a modified tag");
@@ -14992,16 +15127,18 @@
14992
15127
  tag.set.push(t);
14993
15128
  return tag;
14994
15129
  }
14995
- /// Define a tag _modifier_, which is a function that, given a tag,
14996
- /// will return a tag that is a subtag of the original. Applying the
14997
- /// same modifier to a twice tag will return the same value (`m1(t1)
14998
- /// == m1(t1)`) and applying multiple modifiers will, regardless or
14999
- /// order, produce the same tag (`m1(m2(t1)) == m2(m1(t1))`).
15000
- ///
15001
- /// When multiple modifiers are applied to a given base tag, each
15002
- /// smaller set of modifiers is registered as a parent, so that for
15003
- /// example `m1(m2(m3(t1)))` is a subtype of `m1(m2(t1))`,
15004
- /// `m1(m3(t1)`, and so on.
15130
+ /**
15131
+ Define a tag _modifier_, which is a function that, given a tag,
15132
+ will return a tag that is a subtag of the original. Applying the
15133
+ same modifier to a twice tag will return the same value (`m1(t1)
15134
+ == m1(t1)`) and applying multiple modifiers will, regardless or
15135
+ order, produce the same tag (`m1(m2(t1)) == m2(m1(t1))`).
15136
+
15137
+ When multiple modifiers are applied to a given base tag, each
15138
+ smaller set of modifiers is registered as a parent, so that for
15139
+ example `m1(m2(m3(t1)))` is a subtype of `m1(m2(t1))`,
15140
+ `m1(m3(t1)`, and so on.
15141
+ */
15005
15142
  static defineModifier() {
15006
15143
  let mod = new Modifier;
15007
15144
  return (tag) => {
@@ -15046,55 +15183,57 @@
15046
15183
  }
15047
15184
  return sets.sort((a, b) => b.length - a.length);
15048
15185
  }
15049
- /// This function is used to add a set of tags to a language syntax
15050
- /// via [`NodeSet.extend`](#common.NodeSet.extend) or
15051
- /// [`LRParser.configure`](#lr.LRParser.configure).
15052
- ///
15053
- /// The argument object maps node selectors to [highlighting
15054
- /// tags](#highlight.Tag) or arrays of tags.
15055
- ///
15056
- /// Node selectors may hold one or more (space-separated) node paths.
15057
- /// Such a path can be a [node name](#common.NodeType.name), or
15058
- /// multiple node names (or `*` wildcards) separated by slash
15059
- /// characters, as in `"Block/Declaration/VariableName"`. Such a path
15060
- /// matches the final node but only if its direct parent nodes are the
15061
- /// other nodes mentioned. A `*` in such a path matches any parent,
15062
- /// but only a single level—wildcards that match multiple parents
15063
- /// aren't supported, both for efficiency reasons and because Lezer
15064
- /// trees make it rather hard to reason about what they would match.)
15065
- ///
15066
- /// A path can be ended with `/...` to indicate that the tag assigned
15067
- /// to the node should also apply to all child nodes, even if they
15068
- /// match their own style (by default, only the innermost style is
15069
- /// used).
15070
- ///
15071
- /// When a path ends in `!`, as in `Attribute!`, no further matching
15072
- /// happens for the node's child nodes, and the entire node gets the
15073
- /// given style.
15074
- ///
15075
- /// In this notation, node names that contain `/`, `!`, `*`, or `...`
15076
- /// must be quoted as JSON strings.
15077
- ///
15078
- /// For example:
15079
- ///
15080
- /// ```javascript
15081
- /// parser.withProps(
15082
- /// styleTags({
15083
- /// // Style Number and BigNumber nodes
15084
- /// "Number BigNumber": tags.number,
15085
- /// // Style Escape nodes whose parent is String
15086
- /// "String/Escape": tags.escape,
15087
- /// // Style anything inside Attributes nodes
15088
- /// "Attributes!": tags.meta,
15089
- /// // Add a style to all content inside Italic nodes
15090
- /// "Italic/...": tags.emphasis,
15091
- /// // Style InvalidString nodes as both `string` and `invalid`
15092
- /// "InvalidString": [tags.string, tags.invalid],
15093
- /// // Style the node named "/" as punctuation
15094
- /// '"/"': tags.punctuation
15095
- /// })
15096
- /// )
15097
- /// ```
15186
+ /**
15187
+ This function is used to add a set of tags to a language syntax
15188
+ via [`NodeSet.extend`](#common.NodeSet.extend) or
15189
+ [`LRParser.configure`](#lr.LRParser.configure).
15190
+
15191
+ The argument object maps node selectors to [highlighting
15192
+ tags](#highlight.Tag) or arrays of tags.
15193
+
15194
+ Node selectors may hold one or more (space-separated) node paths.
15195
+ Such a path can be a [node name](#common.NodeType.name), or
15196
+ multiple node names (or `*` wildcards) separated by slash
15197
+ characters, as in `"Block/Declaration/VariableName"`. Such a path
15198
+ matches the final node but only if its direct parent nodes are the
15199
+ other nodes mentioned. A `*` in such a path matches any parent,
15200
+ but only a single level—wildcards that match multiple parents
15201
+ aren't supported, both for efficiency reasons and because Lezer
15202
+ trees make it rather hard to reason about what they would match.)
15203
+
15204
+ A path can be ended with `/...` to indicate that the tag assigned
15205
+ to the node should also apply to all child nodes, even if they
15206
+ match their own style (by default, only the innermost style is
15207
+ used).
15208
+
15209
+ When a path ends in `!`, as in `Attribute!`, no further matching
15210
+ happens for the node's child nodes, and the entire node gets the
15211
+ given style.
15212
+
15213
+ In this notation, node names that contain `/`, `!`, `*`, or `...`
15214
+ must be quoted as JSON strings.
15215
+
15216
+ For example:
15217
+
15218
+ ```javascript
15219
+ parser.withProps(
15220
+ styleTags({
15221
+ // Style Number and BigNumber nodes
15222
+ "Number BigNumber": tags.number,
15223
+ // Style Escape nodes whose parent is String
15224
+ "String/Escape": tags.escape,
15225
+ // Style anything inside Attributes nodes
15226
+ "Attributes!": tags.meta,
15227
+ // Add a style to all content inside Italic nodes
15228
+ "Italic/...": tags.emphasis,
15229
+ // Style InvalidString nodes as both `string` and `invalid`
15230
+ "InvalidString": [tags.string, tags.invalid],
15231
+ // Style the node named "/" as punctuation
15232
+ '"/"': tags.punctuation
15233
+ })
15234
+ )
15235
+ ```
15236
+ */
15098
15237
  function styleTags(spec) {
15099
15238
  let byName = Object.create(null);
15100
15239
  for (let prop in spec) {
@@ -15103,10 +15242,10 @@
15103
15242
  tags = [tags];
15104
15243
  for (let part of prop.split(" "))
15105
15244
  if (part) {
15106
- let pieces = [], mode = 2 /* Mode.Normal */, rest = part;
15245
+ let pieces = [], mode = 2 /* Normal */, rest = part;
15107
15246
  for (let pos = 0;;) {
15108
15247
  if (rest == "..." && pos > 0 && pos + 3 == part.length) {
15109
- mode = 1 /* Mode.Inherit */;
15248
+ mode = 1 /* Inherit */;
15110
15249
  break;
15111
15250
  }
15112
15251
  let m = /^"(?:[^"\\]|\\.)*?"|[^\/!]+/.exec(rest);
@@ -15118,7 +15257,7 @@
15118
15257
  break;
15119
15258
  let next = part[pos++];
15120
15259
  if (pos == part.length && next == "!") {
15121
- mode = 0 /* Mode.Opaque */;
15260
+ mode = 0 /* Opaque */;
15122
15261
  break;
15123
15262
  }
15124
15263
  if (next != "/")
@@ -15142,8 +15281,8 @@
15142
15281
  this.context = context;
15143
15282
  this.next = next;
15144
15283
  }
15145
- get opaque() { return this.mode == 0 /* Mode.Opaque */; }
15146
- get inherit() { return this.mode == 1 /* Mode.Inherit */; }
15284
+ get opaque() { return this.mode == 0 /* Opaque */; }
15285
+ get inherit() { return this.mode == 1 /* Inherit */; }
15147
15286
  sort(other) {
15148
15287
  if (!other || other.depth < this.depth) {
15149
15288
  this.next = other;
@@ -15154,10 +15293,12 @@
15154
15293
  }
15155
15294
  get depth() { return this.context ? this.context.length : 0; }
15156
15295
  }
15157
- Rule.empty = new Rule([], 2 /* Mode.Normal */, null);
15158
- /// Define a [highlighter](#highlight.Highlighter) from an array of
15159
- /// tag/class pairs. Classes associated with more specific tags will
15160
- /// take precedence.
15296
+ Rule.empty = new Rule([], 2 /* Normal */, null);
15297
+ /**
15298
+ Define a [highlighter](#highlight.Highlighter) from an array of
15299
+ tag/class pairs. Classes associated with more specific tags will
15300
+ take precedence.
15301
+ */
15161
15302
  function tagHighlighter(tags, options) {
15162
15303
  let map = Object.create(null);
15163
15304
  for (let style of tags) {
@@ -15194,16 +15335,24 @@
15194
15335
  }
15195
15336
  return result;
15196
15337
  }
15197
- /// Highlight the given [tree](#common.Tree) with the given
15198
- /// [highlighter](#highlight.Highlighter).
15338
+ /**
15339
+ Highlight the given [tree](#common.Tree) with the given
15340
+ [highlighter](#highlight.Highlighter).
15341
+ */
15199
15342
  function highlightTree(tree, highlighter,
15200
- /// Assign styling to a region of the text. Will be called, in order
15201
- /// of position, for any ranges where more than zero classes apply.
15202
- /// `classes` is a space separated string of CSS classes.
15343
+ /**
15344
+ Assign styling to a region of the text. Will be called, in order
15345
+ of position, for any ranges where more than zero classes apply.
15346
+ `classes` is a space separated string of CSS classes.
15347
+ */
15203
15348
  putStyle,
15204
- /// The start of the range to highlight.
15349
+ /**
15350
+ The start of the range to highlight.
15351
+ */
15205
15352
  from = 0,
15206
- /// The end of the range.
15353
+ /**
15354
+ The end of the range.
15355
+ */
15207
15356
  to = tree.length) {
15208
15357
  let builder = new HighlightBuilder(from, Array.isArray(highlighter) ? highlighter : [highlighter], putStyle);
15209
15358
  builder.highlightRange(tree.cursor(), from, to, "", builder.highlighters);
@@ -15241,7 +15390,7 @@
15241
15390
  if (cls)
15242
15391
  cls += " ";
15243
15392
  cls += tagCls;
15244
- if (rule.mode == 1 /* Mode.Inherit */)
15393
+ if (rule.mode == 1 /* Inherit */)
15245
15394
  inheritedClass += (inheritedClass ? " " : "") + tagCls;
15246
15395
  }
15247
15396
  this.startSpan(cursor.from, cls);
@@ -15288,9 +15437,11 @@
15288
15437
  }
15289
15438
  }
15290
15439
  }
15291
- /// Match a syntax node's [highlight rules](#highlight.styleTags). If
15292
- /// there's a match, return its set of tags, and whether it is
15293
- /// opaque (uses a `!`) or applies to all child nodes (`/...`).
15440
+ /**
15441
+ Match a syntax node's [highlight rules](#highlight.styleTags). If
15442
+ there's a match, return its set of tags, and whether it is
15443
+ opaque (uses a `!`) or applies to all child nodes (`/...`).
15444
+ */
15294
15445
  function getStyleTags(node) {
15295
15446
  let rule = node.type.prop(ruleNodeProp);
15296
15447
  while (rule && rule.context && !node.matchContext(rule.context))
@@ -15299,268 +15450,440 @@
15299
15450
  }
15300
15451
  const t = Tag.define;
15301
15452
  const comment = t(), name = t(), typeName = t(name), propertyName = t(name), literal = t(), string = t(literal), number = t(literal), content = t(), heading = t(content), keyword = t(), operator = t(), punctuation = t(), bracket = t(punctuation), meta = t();
15302
- /// The default set of highlighting [tags](#highlight.Tag).
15303
- ///
15304
- /// This collection is heavily biased towards programming languages,
15305
- /// and necessarily incomplete. A full ontology of syntactic
15306
- /// constructs would fill a stack of books, and be impractical to
15307
- /// write themes for. So try to make do with this set. If all else
15308
- /// fails, [open an
15309
- /// issue](https://github.com/codemirror/codemirror.next) to propose a
15310
- /// new tag, or [define](#highlight.Tag^define) a local custom tag for
15311
- /// your use case.
15312
- ///
15313
- /// Note that it is not obligatory to always attach the most specific
15314
- /// tag possible to an element—if your grammar can't easily
15315
- /// distinguish a certain type of element (such as a local variable),
15316
- /// it is okay to style it as its more general variant (a variable).
15317
- ///
15318
- /// For tags that extend some parent tag, the documentation links to
15319
- /// the parent.
15453
+ /**
15454
+ The default set of highlighting [tags](#highlight.Tag).
15455
+
15456
+ This collection is heavily biased towards programming languages,
15457
+ and necessarily incomplete. A full ontology of syntactic
15458
+ constructs would fill a stack of books, and be impractical to
15459
+ write themes for. So try to make do with this set. If all else
15460
+ fails, [open an
15461
+ issue](https://github.com/codemirror/codemirror.next) to propose a
15462
+ new tag, or [define](#highlight.Tag^define) a local custom tag for
15463
+ your use case.
15464
+
15465
+ Note that it is not obligatory to always attach the most specific
15466
+ tag possible to an element—if your grammar can't easily
15467
+ distinguish a certain type of element (such as a local variable),
15468
+ it is okay to style it as its more general variant (a variable).
15469
+
15470
+ For tags that extend some parent tag, the documentation links to
15471
+ the parent.
15472
+ */
15320
15473
  const tags = {
15321
- /// A comment.
15474
+ /**
15475
+ A comment.
15476
+ */
15322
15477
  comment,
15323
- /// A line [comment](#highlight.tags.comment).
15478
+ /**
15479
+ A line [comment](#highlight.tags.comment).
15480
+ */
15324
15481
  lineComment: t(comment),
15325
- /// A block [comment](#highlight.tags.comment).
15482
+ /**
15483
+ A block [comment](#highlight.tags.comment).
15484
+ */
15326
15485
  blockComment: t(comment),
15327
- /// A documentation [comment](#highlight.tags.comment).
15486
+ /**
15487
+ A documentation [comment](#highlight.tags.comment).
15488
+ */
15328
15489
  docComment: t(comment),
15329
- /// Any kind of identifier.
15490
+ /**
15491
+ Any kind of identifier.
15492
+ */
15330
15493
  name,
15331
- /// The [name](#highlight.tags.name) of a variable.
15494
+ /**
15495
+ The [name](#highlight.tags.name) of a variable.
15496
+ */
15332
15497
  variableName: t(name),
15333
- /// A type [name](#highlight.tags.name).
15498
+ /**
15499
+ A type [name](#highlight.tags.name).
15500
+ */
15334
15501
  typeName: typeName,
15335
- /// A tag name (subtag of [`typeName`](#highlight.tags.typeName)).
15502
+ /**
15503
+ A tag name (subtag of [`typeName`](#highlight.tags.typeName)).
15504
+ */
15336
15505
  tagName: t(typeName),
15337
- /// A property or field [name](#highlight.tags.name).
15506
+ /**
15507
+ A property or field [name](#highlight.tags.name).
15508
+ */
15338
15509
  propertyName: propertyName,
15339
- /// An attribute name (subtag of [`propertyName`](#highlight.tags.propertyName)).
15510
+ /**
15511
+ An attribute name (subtag of [`propertyName`](#highlight.tags.propertyName)).
15512
+ */
15340
15513
  attributeName: t(propertyName),
15341
- /// The [name](#highlight.tags.name) of a class.
15514
+ /**
15515
+ The [name](#highlight.tags.name) of a class.
15516
+ */
15342
15517
  className: t(name),
15343
- /// A label [name](#highlight.tags.name).
15518
+ /**
15519
+ A label [name](#highlight.tags.name).
15520
+ */
15344
15521
  labelName: t(name),
15345
- /// A namespace [name](#highlight.tags.name).
15522
+ /**
15523
+ A namespace [name](#highlight.tags.name).
15524
+ */
15346
15525
  namespace: t(name),
15347
- /// The [name](#highlight.tags.name) of a macro.
15526
+ /**
15527
+ The [name](#highlight.tags.name) of a macro.
15528
+ */
15348
15529
  macroName: t(name),
15349
- /// A literal value.
15530
+ /**
15531
+ A literal value.
15532
+ */
15350
15533
  literal,
15351
- /// A string [literal](#highlight.tags.literal).
15534
+ /**
15535
+ A string [literal](#highlight.tags.literal).
15536
+ */
15352
15537
  string,
15353
- /// A documentation [string](#highlight.tags.string).
15538
+ /**
15539
+ A documentation [string](#highlight.tags.string).
15540
+ */
15354
15541
  docString: t(string),
15355
- /// A character literal (subtag of [string](#highlight.tags.string)).
15542
+ /**
15543
+ A character literal (subtag of [string](#highlight.tags.string)).
15544
+ */
15356
15545
  character: t(string),
15357
- /// An attribute value (subtag of [string](#highlight.tags.string)).
15546
+ /**
15547
+ An attribute value (subtag of [string](#highlight.tags.string)).
15548
+ */
15358
15549
  attributeValue: t(string),
15359
- /// A number [literal](#highlight.tags.literal).
15550
+ /**
15551
+ A number [literal](#highlight.tags.literal).
15552
+ */
15360
15553
  number,
15361
- /// An integer [number](#highlight.tags.number) literal.
15554
+ /**
15555
+ An integer [number](#highlight.tags.number) literal.
15556
+ */
15362
15557
  integer: t(number),
15363
- /// A floating-point [number](#highlight.tags.number) literal.
15558
+ /**
15559
+ A floating-point [number](#highlight.tags.number) literal.
15560
+ */
15364
15561
  float: t(number),
15365
- /// A boolean [literal](#highlight.tags.literal).
15562
+ /**
15563
+ A boolean [literal](#highlight.tags.literal).
15564
+ */
15366
15565
  bool: t(literal),
15367
- /// Regular expression [literal](#highlight.tags.literal).
15566
+ /**
15567
+ Regular expression [literal](#highlight.tags.literal).
15568
+ */
15368
15569
  regexp: t(literal),
15369
- /// An escape [literal](#highlight.tags.literal), for example a
15370
- /// backslash escape in a string.
15570
+ /**
15571
+ An escape [literal](#highlight.tags.literal), for example a
15572
+ backslash escape in a string.
15573
+ */
15371
15574
  escape: t(literal),
15372
- /// A color [literal](#highlight.tags.literal).
15575
+ /**
15576
+ A color [literal](#highlight.tags.literal).
15577
+ */
15373
15578
  color: t(literal),
15374
- /// A URL [literal](#highlight.tags.literal).
15579
+ /**
15580
+ A URL [literal](#highlight.tags.literal).
15581
+ */
15375
15582
  url: t(literal),
15376
- /// A language keyword.
15583
+ /**
15584
+ A language keyword.
15585
+ */
15377
15586
  keyword,
15378
- /// The [keyword](#highlight.tags.keyword) for the self or this
15379
- /// object.
15587
+ /**
15588
+ The [keyword](#highlight.tags.keyword) for the self or this
15589
+ object.
15590
+ */
15380
15591
  self: t(keyword),
15381
- /// The [keyword](#highlight.tags.keyword) for null.
15592
+ /**
15593
+ The [keyword](#highlight.tags.keyword) for null.
15594
+ */
15382
15595
  null: t(keyword),
15383
- /// A [keyword](#highlight.tags.keyword) denoting some atomic value.
15596
+ /**
15597
+ A [keyword](#highlight.tags.keyword) denoting some atomic value.
15598
+ */
15384
15599
  atom: t(keyword),
15385
- /// A [keyword](#highlight.tags.keyword) that represents a unit.
15600
+ /**
15601
+ A [keyword](#highlight.tags.keyword) that represents a unit.
15602
+ */
15386
15603
  unit: t(keyword),
15387
- /// A modifier [keyword](#highlight.tags.keyword).
15604
+ /**
15605
+ A modifier [keyword](#highlight.tags.keyword).
15606
+ */
15388
15607
  modifier: t(keyword),
15389
- /// A [keyword](#highlight.tags.keyword) that acts as an operator.
15608
+ /**
15609
+ A [keyword](#highlight.tags.keyword) that acts as an operator.
15610
+ */
15390
15611
  operatorKeyword: t(keyword),
15391
- /// A control-flow related [keyword](#highlight.tags.keyword).
15612
+ /**
15613
+ A control-flow related [keyword](#highlight.tags.keyword).
15614
+ */
15392
15615
  controlKeyword: t(keyword),
15393
- /// A [keyword](#highlight.tags.keyword) that defines something.
15616
+ /**
15617
+ A [keyword](#highlight.tags.keyword) that defines something.
15618
+ */
15394
15619
  definitionKeyword: t(keyword),
15395
- /// A [keyword](#highlight.tags.keyword) related to defining or
15396
- /// interfacing with modules.
15620
+ /**
15621
+ A [keyword](#highlight.tags.keyword) related to defining or
15622
+ interfacing with modules.
15623
+ */
15397
15624
  moduleKeyword: t(keyword),
15398
- /// An operator.
15625
+ /**
15626
+ An operator.
15627
+ */
15399
15628
  operator,
15400
- /// An [operator](#highlight.tags.operator) that dereferences something.
15629
+ /**
15630
+ An [operator](#highlight.tags.operator) that dereferences something.
15631
+ */
15401
15632
  derefOperator: t(operator),
15402
- /// Arithmetic-related [operator](#highlight.tags.operator).
15633
+ /**
15634
+ Arithmetic-related [operator](#highlight.tags.operator).
15635
+ */
15403
15636
  arithmeticOperator: t(operator),
15404
- /// Logical [operator](#highlight.tags.operator).
15637
+ /**
15638
+ Logical [operator](#highlight.tags.operator).
15639
+ */
15405
15640
  logicOperator: t(operator),
15406
- /// Bit [operator](#highlight.tags.operator).
15641
+ /**
15642
+ Bit [operator](#highlight.tags.operator).
15643
+ */
15407
15644
  bitwiseOperator: t(operator),
15408
- /// Comparison [operator](#highlight.tags.operator).
15645
+ /**
15646
+ Comparison [operator](#highlight.tags.operator).
15647
+ */
15409
15648
  compareOperator: t(operator),
15410
- /// [Operator](#highlight.tags.operator) that updates its operand.
15649
+ /**
15650
+ [Operator](#highlight.tags.operator) that updates its operand.
15651
+ */
15411
15652
  updateOperator: t(operator),
15412
- /// [Operator](#highlight.tags.operator) that defines something.
15653
+ /**
15654
+ [Operator](#highlight.tags.operator) that defines something.
15655
+ */
15413
15656
  definitionOperator: t(operator),
15414
- /// Type-related [operator](#highlight.tags.operator).
15657
+ /**
15658
+ Type-related [operator](#highlight.tags.operator).
15659
+ */
15415
15660
  typeOperator: t(operator),
15416
- /// Control-flow [operator](#highlight.tags.operator).
15661
+ /**
15662
+ Control-flow [operator](#highlight.tags.operator).
15663
+ */
15417
15664
  controlOperator: t(operator),
15418
- /// Program or markup punctuation.
15665
+ /**
15666
+ Program or markup punctuation.
15667
+ */
15419
15668
  punctuation,
15420
- /// [Punctuation](#highlight.tags.punctuation) that separates
15421
- /// things.
15669
+ /**
15670
+ [Punctuation](#highlight.tags.punctuation) that separates
15671
+ things.
15672
+ */
15422
15673
  separator: t(punctuation),
15423
- /// Bracket-style [punctuation](#highlight.tags.punctuation).
15674
+ /**
15675
+ Bracket-style [punctuation](#highlight.tags.punctuation).
15676
+ */
15424
15677
  bracket,
15425
- /// Angle [brackets](#highlight.tags.bracket) (usually `<` and `>`
15426
- /// tokens).
15678
+ /**
15679
+ Angle [brackets](#highlight.tags.bracket) (usually `<` and `>`
15680
+ tokens).
15681
+ */
15427
15682
  angleBracket: t(bracket),
15428
- /// Square [brackets](#highlight.tags.bracket) (usually `[` and `]`
15429
- /// tokens).
15683
+ /**
15684
+ Square [brackets](#highlight.tags.bracket) (usually `[` and `]`
15685
+ tokens).
15686
+ */
15430
15687
  squareBracket: t(bracket),
15431
- /// Parentheses (usually `(` and `)` tokens). Subtag of
15432
- /// [bracket](#highlight.tags.bracket).
15688
+ /**
15689
+ Parentheses (usually `(` and `)` tokens). Subtag of
15690
+ [bracket](#highlight.tags.bracket).
15691
+ */
15433
15692
  paren: t(bracket),
15434
- /// Braces (usually `{` and `}` tokens). Subtag of
15435
- /// [bracket](#highlight.tags.bracket).
15693
+ /**
15694
+ Braces (usually `{` and `}` tokens). Subtag of
15695
+ [bracket](#highlight.tags.bracket).
15696
+ */
15436
15697
  brace: t(bracket),
15437
- /// Content, for example plain text in XML or markup documents.
15698
+ /**
15699
+ Content, for example plain text in XML or markup documents.
15700
+ */
15438
15701
  content,
15439
- /// [Content](#highlight.tags.content) that represents a heading.
15702
+ /**
15703
+ [Content](#highlight.tags.content) that represents a heading.
15704
+ */
15440
15705
  heading,
15441
- /// A level 1 [heading](#highlight.tags.heading).
15706
+ /**
15707
+ A level 1 [heading](#highlight.tags.heading).
15708
+ */
15442
15709
  heading1: t(heading),
15443
- /// A level 2 [heading](#highlight.tags.heading).
15710
+ /**
15711
+ A level 2 [heading](#highlight.tags.heading).
15712
+ */
15444
15713
  heading2: t(heading),
15445
- /// A level 3 [heading](#highlight.tags.heading).
15714
+ /**
15715
+ A level 3 [heading](#highlight.tags.heading).
15716
+ */
15446
15717
  heading3: t(heading),
15447
- /// A level 4 [heading](#highlight.tags.heading).
15718
+ /**
15719
+ A level 4 [heading](#highlight.tags.heading).
15720
+ */
15448
15721
  heading4: t(heading),
15449
- /// A level 5 [heading](#highlight.tags.heading).
15722
+ /**
15723
+ A level 5 [heading](#highlight.tags.heading).
15724
+ */
15450
15725
  heading5: t(heading),
15451
- /// A level 6 [heading](#highlight.tags.heading).
15726
+ /**
15727
+ A level 6 [heading](#highlight.tags.heading).
15728
+ */
15452
15729
  heading6: t(heading),
15453
- /// A prose separator (such as a horizontal rule).
15730
+ /**
15731
+ A prose separator (such as a horizontal rule).
15732
+ */
15454
15733
  contentSeparator: t(content),
15455
- /// [Content](#highlight.tags.content) that represents a list.
15734
+ /**
15735
+ [Content](#highlight.tags.content) that represents a list.
15736
+ */
15456
15737
  list: t(content),
15457
- /// [Content](#highlight.tags.content) that represents a quote.
15738
+ /**
15739
+ [Content](#highlight.tags.content) that represents a quote.
15740
+ */
15458
15741
  quote: t(content),
15459
- /// [Content](#highlight.tags.content) that is emphasized.
15742
+ /**
15743
+ [Content](#highlight.tags.content) that is emphasized.
15744
+ */
15460
15745
  emphasis: t(content),
15461
- /// [Content](#highlight.tags.content) that is styled strong.
15746
+ /**
15747
+ [Content](#highlight.tags.content) that is styled strong.
15748
+ */
15462
15749
  strong: t(content),
15463
- /// [Content](#highlight.tags.content) that is part of a link.
15750
+ /**
15751
+ [Content](#highlight.tags.content) that is part of a link.
15752
+ */
15464
15753
  link: t(content),
15465
- /// [Content](#highlight.tags.content) that is styled as code or
15466
- /// monospace.
15754
+ /**
15755
+ [Content](#highlight.tags.content) that is styled as code or
15756
+ monospace.
15757
+ */
15467
15758
  monospace: t(content),
15468
- /// [Content](#highlight.tags.content) that has a strike-through
15469
- /// style.
15759
+ /**
15760
+ [Content](#highlight.tags.content) that has a strike-through
15761
+ style.
15762
+ */
15470
15763
  strikethrough: t(content),
15471
- /// Inserted text in a change-tracking format.
15764
+ /**
15765
+ Inserted text in a change-tracking format.
15766
+ */
15472
15767
  inserted: t(),
15473
- /// Deleted text.
15768
+ /**
15769
+ Deleted text.
15770
+ */
15474
15771
  deleted: t(),
15475
- /// Changed text.
15772
+ /**
15773
+ Changed text.
15774
+ */
15476
15775
  changed: t(),
15477
- /// An invalid or unsyntactic element.
15776
+ /**
15777
+ An invalid or unsyntactic element.
15778
+ */
15478
15779
  invalid: t(),
15479
- /// Metadata or meta-instruction.
15780
+ /**
15781
+ Metadata or meta-instruction.
15782
+ */
15480
15783
  meta,
15481
- /// [Metadata](#highlight.tags.meta) that applies to the entire
15482
- /// document.
15784
+ /**
15785
+ [Metadata](#highlight.tags.meta) that applies to the entire
15786
+ document.
15787
+ */
15483
15788
  documentMeta: t(meta),
15484
- /// [Metadata](#highlight.tags.meta) that annotates or adds
15485
- /// attributes to a given syntactic element.
15789
+ /**
15790
+ [Metadata](#highlight.tags.meta) that annotates or adds
15791
+ attributes to a given syntactic element.
15792
+ */
15486
15793
  annotation: t(meta),
15487
- /// Processing instruction or preprocessor directive. Subtag of
15488
- /// [meta](#highlight.tags.meta).
15794
+ /**
15795
+ Processing instruction or preprocessor directive. Subtag of
15796
+ [meta](#highlight.tags.meta).
15797
+ */
15489
15798
  processingInstruction: t(meta),
15490
- /// [Modifier](#highlight.Tag^defineModifier) that indicates that a
15491
- /// given element is being defined. Expected to be used with the
15492
- /// various [name](#highlight.tags.name) tags.
15799
+ /**
15800
+ [Modifier](#highlight.Tag^defineModifier) that indicates that a
15801
+ given element is being defined. Expected to be used with the
15802
+ various [name](#highlight.tags.name) tags.
15803
+ */
15493
15804
  definition: Tag.defineModifier(),
15494
- /// [Modifier](#highlight.Tag^defineModifier) that indicates that
15495
- /// something is constant. Mostly expected to be used with
15496
- /// [variable names](#highlight.tags.variableName).
15805
+ /**
15806
+ [Modifier](#highlight.Tag^defineModifier) that indicates that
15807
+ something is constant. Mostly expected to be used with
15808
+ [variable names](#highlight.tags.variableName).
15809
+ */
15497
15810
  constant: Tag.defineModifier(),
15498
- /// [Modifier](#highlight.Tag^defineModifier) used to indicate that
15499
- /// a [variable](#highlight.tags.variableName) or [property
15500
- /// name](#highlight.tags.propertyName) is being called or defined
15501
- /// as a function.
15811
+ /**
15812
+ [Modifier](#highlight.Tag^defineModifier) used to indicate that
15813
+ a [variable](#highlight.tags.variableName) or [property
15814
+ name](#highlight.tags.propertyName) is being called or defined
15815
+ as a function.
15816
+ */
15502
15817
  function: Tag.defineModifier(),
15503
- /// [Modifier](#highlight.Tag^defineModifier) that can be applied to
15504
- /// [names](#highlight.tags.name) to indicate that they belong to
15505
- /// the language's standard environment.
15818
+ /**
15819
+ [Modifier](#highlight.Tag^defineModifier) that can be applied to
15820
+ [names](#highlight.tags.name) to indicate that they belong to
15821
+ the language's standard environment.
15822
+ */
15506
15823
  standard: Tag.defineModifier(),
15507
- /// [Modifier](#highlight.Tag^defineModifier) that indicates a given
15508
- /// [names](#highlight.tags.name) is local to some scope.
15824
+ /**
15825
+ [Modifier](#highlight.Tag^defineModifier) that indicates a given
15826
+ [names](#highlight.tags.name) is local to some scope.
15827
+ */
15509
15828
  local: Tag.defineModifier(),
15510
- /// A generic variant [modifier](#highlight.Tag^defineModifier) that
15511
- /// can be used to tag language-specific alternative variants of
15512
- /// some common tag. It is recommended for themes to define special
15513
- /// forms of at least the [string](#highlight.tags.string) and
15514
- /// [variable name](#highlight.tags.variableName) tags, since those
15515
- /// come up a lot.
15829
+ /**
15830
+ A generic variant [modifier](#highlight.Tag^defineModifier) that
15831
+ can be used to tag language-specific alternative variants of
15832
+ some common tag. It is recommended for themes to define special
15833
+ forms of at least the [string](#highlight.tags.string) and
15834
+ [variable name](#highlight.tags.variableName) tags, since those
15835
+ come up a lot.
15836
+ */
15516
15837
  special: Tag.defineModifier()
15517
15838
  };
15518
- /// This is a highlighter that adds stable, predictable classes to
15519
- /// tokens, for styling with external CSS.
15520
- ///
15521
- /// The following tags are mapped to their name prefixed with `"tok-"`
15522
- /// (for example `"tok-comment"`):
15523
- ///
15524
- /// * [`link`](#highlight.tags.link)
15525
- /// * [`heading`](#highlight.tags.heading)
15526
- /// * [`emphasis`](#highlight.tags.emphasis)
15527
- /// * [`strong`](#highlight.tags.strong)
15528
- /// * [`keyword`](#highlight.tags.keyword)
15529
- /// * [`atom`](#highlight.tags.atom)
15530
- /// * [`bool`](#highlight.tags.bool)
15531
- /// * [`url`](#highlight.tags.url)
15532
- /// * [`labelName`](#highlight.tags.labelName)
15533
- /// * [`inserted`](#highlight.tags.inserted)
15534
- /// * [`deleted`](#highlight.tags.deleted)
15535
- /// * [`literal`](#highlight.tags.literal)
15536
- /// * [`string`](#highlight.tags.string)
15537
- /// * [`number`](#highlight.tags.number)
15538
- /// * [`variableName`](#highlight.tags.variableName)
15539
- /// * [`typeName`](#highlight.tags.typeName)
15540
- /// * [`namespace`](#highlight.tags.namespace)
15541
- /// * [`className`](#highlight.tags.className)
15542
- /// * [`macroName`](#highlight.tags.macroName)
15543
- /// * [`propertyName`](#highlight.tags.propertyName)
15544
- /// * [`operator`](#highlight.tags.operator)
15545
- /// * [`comment`](#highlight.tags.comment)
15546
- /// * [`meta`](#highlight.tags.meta)
15547
- /// * [`punctuation`](#highlight.tags.punctuation)
15548
- /// * [`invalid`](#highlight.tags.invalid)
15549
- ///
15550
- /// In addition, these mappings are provided:
15551
- ///
15552
- /// * [`regexp`](#highlight.tags.regexp),
15553
- /// [`escape`](#highlight.tags.escape), and
15554
- /// [`special`](#highlight.tags.special)[`(string)`](#highlight.tags.string)
15555
- /// are mapped to `"tok-string2"`
15556
- /// * [`special`](#highlight.tags.special)[`(variableName)`](#highlight.tags.variableName)
15557
- /// to `"tok-variableName2"`
15558
- /// * [`local`](#highlight.tags.local)[`(variableName)`](#highlight.tags.variableName)
15559
- /// to `"tok-variableName tok-local"`
15560
- /// * [`definition`](#highlight.tags.definition)[`(variableName)`](#highlight.tags.variableName)
15561
- /// to `"tok-variableName tok-definition"`
15562
- /// * [`definition`](#highlight.tags.definition)[`(propertyName)`](#highlight.tags.propertyName)
15563
- /// to `"tok-propertyName tok-definition"`
15839
+ /**
15840
+ This is a highlighter that adds stable, predictable classes to
15841
+ tokens, for styling with external CSS.
15842
+
15843
+ The following tags are mapped to their name prefixed with `"tok-"`
15844
+ (for example `"tok-comment"`):
15845
+
15846
+ * [`link`](#highlight.tags.link)
15847
+ * [`heading`](#highlight.tags.heading)
15848
+ * [`emphasis`](#highlight.tags.emphasis)
15849
+ * [`strong`](#highlight.tags.strong)
15850
+ * [`keyword`](#highlight.tags.keyword)
15851
+ * [`atom`](#highlight.tags.atom)
15852
+ * [`bool`](#highlight.tags.bool)
15853
+ * [`url`](#highlight.tags.url)
15854
+ * [`labelName`](#highlight.tags.labelName)
15855
+ * [`inserted`](#highlight.tags.inserted)
15856
+ * [`deleted`](#highlight.tags.deleted)
15857
+ * [`literal`](#highlight.tags.literal)
15858
+ * [`string`](#highlight.tags.string)
15859
+ * [`number`](#highlight.tags.number)
15860
+ * [`variableName`](#highlight.tags.variableName)
15861
+ * [`typeName`](#highlight.tags.typeName)
15862
+ * [`namespace`](#highlight.tags.namespace)
15863
+ * [`className`](#highlight.tags.className)
15864
+ * [`macroName`](#highlight.tags.macroName)
15865
+ * [`propertyName`](#highlight.tags.propertyName)
15866
+ * [`operator`](#highlight.tags.operator)
15867
+ * [`comment`](#highlight.tags.comment)
15868
+ * [`meta`](#highlight.tags.meta)
15869
+ * [`punctuation`](#highlight.tags.punctuation)
15870
+ * [`invalid`](#highlight.tags.invalid)
15871
+
15872
+ In addition, these mappings are provided:
15873
+
15874
+ * [`regexp`](#highlight.tags.regexp),
15875
+ [`escape`](#highlight.tags.escape), and
15876
+ [`special`](#highlight.tags.special)[`(string)`](#highlight.tags.string)
15877
+ are mapped to `"tok-string2"`
15878
+ * [`special`](#highlight.tags.special)[`(variableName)`](#highlight.tags.variableName)
15879
+ to `"tok-variableName2"`
15880
+ * [`local`](#highlight.tags.local)[`(variableName)`](#highlight.tags.variableName)
15881
+ to `"tok-variableName tok-local"`
15882
+ * [`definition`](#highlight.tags.definition)[`(variableName)`](#highlight.tags.variableName)
15883
+ to `"tok-variableName tok-definition"`
15884
+ * [`definition`](#highlight.tags.definition)[`(propertyName)`](#highlight.tags.propertyName)
15885
+ to `"tok-propertyName tok-definition"`
15886
+ */
15564
15887
  tagHighlighter([
15565
15888
  { tag: tags.link, class: "tok-link" },
15566
15889
  { tag: tags.heading, class: "tok-heading" },
@@ -15614,6 +15937,11 @@
15614
15937
  });
15615
15938
  }
15616
15939
  /**
15940
+ Syntax node prop used to register sublangauges. Should be added to
15941
+ the top level node type for the language.
15942
+ */
15943
+ const sublanguageProp = /*@__PURE__*/new NodeProp();
15944
+ /**
15617
15945
  A language object manages parsing and per-language
15618
15946
  [metadata](https://codemirror.net/6/docs/ref/#state.EditorState.languageDataAt). Parse data is
15619
15947
  managed as a [Lezer](https://lezer.codemirror.net) tree. The class
@@ -15650,14 +15978,28 @@
15650
15978
  this.parser = parser;
15651
15979
  this.extension = [
15652
15980
  language.of(this),
15653
- EditorState.languageData.of((state, pos, side) => state.facet(languageDataFacetAt(state, pos, side)))
15981
+ EditorState.languageData.of((state, pos, side) => {
15982
+ let top = topNodeAt(state, pos, side), data = top.type.prop(languageDataProp);
15983
+ if (!data)
15984
+ return [];
15985
+ let base = state.facet(data), sub = top.type.prop(sublanguageProp);
15986
+ if (sub) {
15987
+ let innerNode = top.resolve(pos - top.from, side);
15988
+ for (let sublang of sub)
15989
+ if (sublang.test(innerNode, state)) {
15990
+ let data = state.facet(sublang.facet);
15991
+ return sublang.type == "replace" ? data : data.concat(base);
15992
+ }
15993
+ }
15994
+ return base;
15995
+ })
15654
15996
  ].concat(extraExtensions);
15655
15997
  }
15656
15998
  /**
15657
15999
  Query whether this language is active at the given position.
15658
16000
  */
15659
16001
  isActiveAt(state, pos, side = -1) {
15660
- return languageDataFacetAt(state, pos, side) == this.data;
16002
+ return topNodeAt(state, pos, side).type.prop(languageDataProp) == this.data;
15661
16003
  }
15662
16004
  /**
15663
16005
  Find the document regions that were parsed using this language.
@@ -15712,16 +16054,14 @@
15712
16054
  @internal
15713
16055
  */
15714
16056
  Language.setState = /*@__PURE__*/StateEffect.define();
15715
- function languageDataFacetAt(state, pos, side) {
15716
- let topLang = state.facet(language);
15717
- if (!topLang)
15718
- return null;
15719
- let facet = topLang.data;
15720
- if (topLang.allowsNesting) {
15721
- for (let node = syntaxTree(state).topNode; node; node = node.enter(pos, side, IterMode.ExcludeBuffers))
15722
- facet = node.type.prop(languageDataProp) || facet;
16057
+ function topNodeAt(state, pos, side) {
16058
+ let topLang = state.facet(language), tree = syntaxTree(state).topNode;
16059
+ if (!topLang || topLang.allowsNesting) {
16060
+ for (let node = tree; node; node = node.enter(pos, side, IterMode.ExcludeBuffers))
16061
+ if (node.type.isTop)
16062
+ tree = node;
15723
16063
  }
15724
- return facet;
16064
+ return tree;
15725
16065
  }
15726
16066
  /**
15727
16067
  A subclass of [`Language`](https://codemirror.net/6/docs/ref/#language.Language) for use with Lezer
@@ -15763,13 +16103,13 @@
15763
16103
  }
15764
16104
  // Lezer-style Input object for a Text document.
15765
16105
  class DocInput {
15766
- constructor(doc, length = doc.length) {
16106
+ constructor(doc) {
15767
16107
  this.doc = doc;
15768
- this.length = length;
15769
16108
  this.cursorPos = 0;
15770
16109
  this.string = "";
15771
16110
  this.cursor = doc.iter();
15772
16111
  }
16112
+ get length() { return this.doc.length; }
15773
16113
  syncTo(pos) {
15774
16114
  this.string = this.cursor.next(pos - this.cursorPos).value;
15775
16115
  this.cursorPos = pos + this.string.length;
@@ -16217,17 +16557,18 @@
16217
16557
  */
16218
16558
  const indentService = /*@__PURE__*/Facet.define();
16219
16559
  /**
16220
- Facet for overriding the unit by which indentation happens.
16221
- Should be a string consisting either entirely of spaces or
16222
- entirely of tabs. When not set, this defaults to 2 spaces.
16560
+ Facet for overriding the unit by which indentation happens. Should
16561
+ be a string consisting either entirely of the same whitespace
16562
+ character. When not set, this defaults to 2 spaces.
16223
16563
  */
16224
16564
  const indentUnit = /*@__PURE__*/Facet.define({
16225
16565
  combine: values => {
16226
16566
  if (!values.length)
16227
16567
  return " ";
16228
- if (!/^(?: +|\t+)$/.test(values[0]))
16568
+ let unit = values[0];
16569
+ if (!unit || /\S/.test(unit) || Array.from(unit).some(e => e != unit[0]))
16229
16570
  throw new Error("Invalid indent unit: " + JSON.stringify(values[0]));
16230
- return values[0];
16571
+ return unit;
16231
16572
  }
16232
16573
  });
16233
16574
  /**
@@ -16247,14 +16588,16 @@
16247
16588
  tabs.
16248
16589
  */
16249
16590
  function indentString(state, cols) {
16250
- let result = "", ts = state.tabSize;
16251
- if (state.facet(indentUnit).charCodeAt(0) == 9)
16591
+ let result = "", ts = state.tabSize, ch = state.facet(indentUnit)[0];
16592
+ if (ch == "\t") {
16252
16593
  while (cols >= ts) {
16253
16594
  result += "\t";
16254
16595
  cols -= ts;
16255
16596
  }
16597
+ ch = " ";
16598
+ }
16256
16599
  for (let i = 0; i < cols; i++)
16257
- result += " ";
16600
+ result += ch;
16258
16601
  return result;
16259
16602
  }
16260
16603
  /**
@@ -17307,7 +17650,7 @@
17307
17650
  if available, otherwise falling back to block comments.
17308
17651
  */
17309
17652
  const toggleComment = target => {
17310
- let config = getConfig(target.state);
17653
+ let { state } = target, line = state.doc.lineAt(state.selection.main.from), config = getConfig(target.state, line.from);
17311
17654
  return config.line ? toggleLineComment(target) : config.block ? toggleBlockCommentByLine(target) : false;
17312
17655
  };
17313
17656
  function command(f, option) {
@@ -17340,7 +17683,7 @@
17340
17683
  block comments.
17341
17684
  */
17342
17685
  const toggleBlockCommentByLine = /*@__PURE__*/command((o, s) => changeBlockComment(o, s, selectedLineRanges(s)), 0 /* CommentOption.Toggle */);
17343
- function getConfig(state, pos = state.selection.main.head) {
17686
+ function getConfig(state, pos) {
17344
17687
  let data = state.languageDataAt("commentTokens", pos);
17345
17688
  return data.length ? data[0] : {};
17346
17689
  }
@@ -17422,13 +17765,13 @@
17422
17765
  let prevLine = -1;
17423
17766
  for (let { from, to } of ranges) {
17424
17767
  let startI = lines.length, minIndent = 1e9;
17768
+ let token = getConfig(state, from).line;
17769
+ if (!token)
17770
+ continue;
17425
17771
  for (let pos = from; pos <= to;) {
17426
17772
  let line = state.doc.lineAt(pos);
17427
17773
  if (line.from > prevLine && (from == to || to > line.from)) {
17428
17774
  prevLine = line.from;
17429
- let token = getConfig(state, pos).line;
17430
- if (!token)
17431
- continue;
17432
17775
  let indent = /^\s*/.exec(line.text)[0].length;
17433
17776
  let empty = indent == line.length;
17434
17777
  let comment = line.text.slice(indent, indent + token.length) == token ? indent : -1;
@@ -17910,21 +18253,41 @@
17910
18253
  Move the selection one line down.
17911
18254
  */
17912
18255
  const cursorLineDown = view => cursorByLine(view, true);
17913
- function pageHeight(view) {
17914
- return Math.max(view.defaultLineHeight, Math.min(view.dom.clientHeight, innerHeight) - 5);
18256
+ function pageInfo(view) {
18257
+ let selfScroll = view.scrollDOM.clientHeight < view.scrollDOM.scrollHeight - 2;
18258
+ let marginTop = 0, marginBottom = 0, height;
18259
+ if (selfScroll) {
18260
+ for (let source of view.state.facet(EditorView.scrollMargins)) {
18261
+ let margins = source(view);
18262
+ if (margins === null || margins === void 0 ? void 0 : margins.top)
18263
+ marginTop = Math.max(margins === null || margins === void 0 ? void 0 : margins.top, marginTop);
18264
+ if (margins === null || margins === void 0 ? void 0 : margins.bottom)
18265
+ marginBottom = Math.max(margins === null || margins === void 0 ? void 0 : margins.bottom, marginBottom);
18266
+ }
18267
+ height = view.scrollDOM.clientHeight - marginTop - marginBottom;
18268
+ }
18269
+ else {
18270
+ height = (view.dom.ownerDocument.defaultView || window).innerHeight;
18271
+ }
18272
+ return { marginTop, marginBottom, selfScroll,
18273
+ height: Math.max(view.defaultLineHeight, height - 5) };
17915
18274
  }
17916
18275
  function cursorByPage(view, forward) {
18276
+ let page = pageInfo(view);
17917
18277
  let { state } = view, selection = updateSel(state.selection, range => {
17918
- return range.empty ? view.moveVertically(range, forward, pageHeight(view)) : rangeEnd(range, forward);
18278
+ return range.empty ? view.moveVertically(range, forward, page.height)
18279
+ : rangeEnd(range, forward);
17919
18280
  });
17920
18281
  if (selection.eq(state.selection))
17921
18282
  return false;
17922
- let startPos = view.coordsAtPos(state.selection.main.head);
17923
- let scrollRect = view.scrollDOM.getBoundingClientRect();
17924
18283
  let effect;
17925
- if (startPos && startPos.top > scrollRect.top && startPos.bottom < scrollRect.bottom &&
17926
- startPos.top - scrollRect.top <= view.scrollDOM.scrollHeight - view.scrollDOM.scrollTop - view.scrollDOM.clientHeight)
17927
- effect = EditorView.scrollIntoView(selection.main.head, { y: "start", yMargin: startPos.top - scrollRect.top });
18284
+ if (page.selfScroll) {
18285
+ let startPos = view.coordsAtPos(state.selection.main.head);
18286
+ let scrollRect = view.scrollDOM.getBoundingClientRect();
18287
+ let scrollTop = scrollRect.top + page.marginTop, scrollBottom = scrollRect.bottom - page.marginBottom;
18288
+ if (startPos && startPos.top > scrollTop && startPos.bottom < scrollBottom)
18289
+ effect = EditorView.scrollIntoView(selection.main.head, { y: "start", yMargin: startPos.top - scrollTop });
18290
+ }
17928
18291
  view.dispatch(setSel(state, selection), { effects: effect });
17929
18292
  return true;
17930
18293
  }
@@ -18051,7 +18414,7 @@
18051
18414
  */
18052
18415
  const selectLineDown = view => selectByLine(view, true);
18053
18416
  function selectByPage(view, forward) {
18054
- return extendSel(view, range => view.moveVertically(range, forward, pageHeight(view)));
18417
+ return extendSel(view, range => view.moveVertically(range, forward, pageInfo(view).height));
18055
18418
  }
18056
18419
  /**
18057
18420
  Move the selection head one page up.
@@ -19072,9 +19435,6 @@
19072
19435
  `-`, document percentages suffixed with `%`, and an optional
19073
19436
  column position by adding `:` and a second number after the line
19074
19437
  number.
19075
-
19076
- The dialog can be styled with the `panel.gotoLine` theme
19077
- selector.
19078
19438
  */
19079
19439
  const gotoLine = view => {
19080
19440
  let panel = getPanel(view, createLineDialog);
@@ -19261,7 +19621,8 @@
19261
19621
  caseSensitive: false,
19262
19622
  literal: false,
19263
19623
  wholeWord: false,
19264
- createPanel: view => new SearchPanel(view)
19624
+ createPanel: view => new SearchPanel(view),
19625
+ scrollToMatch: range => EditorView.scrollIntoView(range)
19265
19626
  });
19266
19627
  }
19267
19628
  });
@@ -19519,10 +19880,11 @@
19519
19880
  let next = query.nextMatch(view.state, to, to);
19520
19881
  if (!next)
19521
19882
  return false;
19883
+ let selection = EditorSelection.single(next.from, next.to);
19884
+ let config = view.state.facet(searchConfigFacet);
19522
19885
  view.dispatch({
19523
- selection: { anchor: next.from, head: next.to },
19524
- scrollIntoView: true,
19525
- effects: announceMatch(view, next),
19886
+ selection,
19887
+ effects: [announceMatch(view, next), config.scrollToMatch(selection.main)],
19526
19888
  userEvent: "select.search"
19527
19889
  });
19528
19890
  return true;
@@ -19534,13 +19896,14 @@
19534
19896
  */
19535
19897
  const findPrevious = /*@__PURE__*/searchCommand((view, { query }) => {
19536
19898
  let { state } = view, { from } = state.selection.main;
19537
- let range = query.prevMatch(state, from, from);
19538
- if (!range)
19899
+ let prev = query.prevMatch(state, from, from);
19900
+ if (!prev)
19539
19901
  return false;
19902
+ let selection = EditorSelection.single(prev.from, prev.to);
19903
+ let config = view.state.facet(searchConfigFacet);
19540
19904
  view.dispatch({
19541
- selection: { anchor: range.from, head: range.to },
19542
- scrollIntoView: true,
19543
- effects: announceMatch(view, range),
19905
+ selection,
19906
+ effects: [announceMatch(view, prev), config.scrollToMatch(selection.main)],
19544
19907
  userEvent: "select.search"
19545
19908
  });
19546
19909
  return true;
@@ -19591,22 +19954,21 @@
19591
19954
  if (!next)
19592
19955
  return false;
19593
19956
  let changes = [], selection, replacement;
19594
- let announce = [];
19957
+ let effects = [];
19595
19958
  if (next.from == from && next.to == to) {
19596
19959
  replacement = state.toText(query.getReplacement(next));
19597
19960
  changes.push({ from: next.from, to: next.to, insert: replacement });
19598
19961
  next = query.nextMatch(state, next.from, next.to);
19599
- announce.push(EditorView.announce.of(state.phrase("replaced match on line $", state.doc.lineAt(from).number) + "."));
19962
+ effects.push(EditorView.announce.of(state.phrase("replaced match on line $", state.doc.lineAt(from).number) + "."));
19600
19963
  }
19601
19964
  if (next) {
19602
19965
  let off = changes.length == 0 || changes[0].from >= next.to ? 0 : next.to - next.from - replacement.length;
19603
- selection = { anchor: next.from - off, head: next.to - off };
19604
- announce.push(announceMatch(view, next));
19966
+ selection = EditorSelection.single(next.from - off, next.to - off);
19967
+ effects.push(announceMatch(view, next));
19968
+ effects.push(state.facet(searchConfigFacet).scrollToMatch(selection.main));
19605
19969
  }
19606
19970
  view.dispatch({
19607
- changes, selection,
19608
- scrollIntoView: !!selection,
19609
- effects: announce,
19971
+ changes, selection, effects,
19610
19972
  userEvent: "input.replace"
19611
19973
  });
19612
19974
  return true;
@@ -19990,9 +20352,12 @@
19990
20352
  */
19991
20353
  function ifNotIn(nodes, source) {
19992
20354
  return (context) => {
19993
- for (let pos = syntaxTree(context.state).resolveInner(context.pos, -1); pos; pos = pos.parent)
20355
+ for (let pos = syntaxTree(context.state).resolveInner(context.pos, -1); pos; pos = pos.parent) {
19994
20356
  if (nodes.indexOf(pos.name) > -1)
19995
20357
  return null;
20358
+ if (pos.type.isTop)
20359
+ break;
20360
+ }
19996
20361
  return source(context);
19997
20362
  };
19998
20363
  }
@@ -20097,13 +20462,18 @@
20097
20462
  // For single-character queries, only match when they occur right
20098
20463
  // at the start
20099
20464
  if (chars.length == 1) {
20100
- let first = codePointAt(word, 0);
20101
- return first == chars[0] ? [0, 0, codePointSize(first)]
20102
- : first == folded[0] ? [-200 /* Penalty.CaseFold */, 0, codePointSize(first)] : null;
20465
+ let first = codePointAt(word, 0), firstSize = codePointSize(first);
20466
+ let score = firstSize == word.length ? 0 : -100 /* Penalty.NotFull */;
20467
+ if (first == chars[0]) ;
20468
+ else if (first == folded[0])
20469
+ score += -200 /* Penalty.CaseFold */;
20470
+ else
20471
+ return null;
20472
+ return [score, 0, firstSize];
20103
20473
  }
20104
20474
  let direct = word.indexOf(this.pattern);
20105
20475
  if (direct == 0)
20106
- return [0, 0, this.pattern.length];
20476
+ return [word.length == this.pattern.length ? 0 : -100 /* Penalty.NotFull */, 0, this.pattern.length];
20107
20477
  let len = chars.length, anyTo = 0;
20108
20478
  if (direct < 0) {
20109
20479
  for (let i = 0, e = Math.min(word.length, 200); i < e && anyTo < len;) {
@@ -20159,7 +20529,7 @@
20159
20529
  if (byWordTo == len && byWord[0] == 0 && wordAdjacent)
20160
20530
  return this.result(-100 /* Penalty.ByWord */ + (byWordFolded ? -200 /* Penalty.CaseFold */ : 0), byWord, word);
20161
20531
  if (adjacentTo == len && adjacentStart == 0)
20162
- return [-200 /* Penalty.CaseFold */ - word.length, 0, adjacentEnd];
20532
+ return [-200 /* Penalty.CaseFold */ - word.length + (adjacentEnd == word.length ? 0 : -100 /* Penalty.NotFull */), 0, adjacentEnd];
20163
20533
  if (direct > -1)
20164
20534
  return [-700 /* Penalty.NotStart */ - word.length, direct, direct + this.pattern.length];
20165
20535
  if (adjacentTo == len)
@@ -21555,7 +21925,8 @@
21555
21925
  }
21556
21926
  update(update) {
21557
21927
  let config = update.state.facet(lintConfig);
21558
- if (update.docChanged || config != update.startState.facet(lintConfig)) {
21928
+ if (update.docChanged || config != update.startState.facet(lintConfig) ||
21929
+ config.needsRefresh && config.needsRefresh(update)) {
21559
21930
  this.lintTime = Date.now() + config.delay;
21560
21931
  if (!this.set) {
21561
21932
  this.set = true;
@@ -21578,7 +21949,10 @@
21578
21949
  return Object.assign({ sources: input.map(i => i.source) }, combineConfig(input.map(i => i.config), {
21579
21950
  delay: 750,
21580
21951
  markerFilter: null,
21581
- tooltipFilter: null
21952
+ tooltipFilter: null,
21953
+ needsRefresh: null
21954
+ }, {
21955
+ needsRefresh: (a, b) => !a ? b : !b ? a : u => a(u) || b(u)
21582
21956
  }));
21583
21957
  },
21584
21958
  enables: lintPlugin
@@ -21602,8 +21976,11 @@
21602
21976
  var _a;
21603
21977
  let keys = inPanel ? assignKeys(diagnostic.actions) : [];
21604
21978
  return crelt("li", { class: "cm-diagnostic cm-diagnostic-" + diagnostic.severity }, crelt("span", { class: "cm-diagnosticText" }, diagnostic.renderMessage ? diagnostic.renderMessage() : diagnostic.message), (_a = diagnostic.actions) === null || _a === void 0 ? void 0 : _a.map((action, i) => {
21605
- let click = (e) => {
21979
+ let fired = false, click = (e) => {
21606
21980
  e.preventDefault();
21981
+ if (fired)
21982
+ return;
21983
+ fired = true;
21607
21984
  let found = findDiagnostic(view.state.field(lintState).diagnostics, diagnostic);
21608
21985
  if (found)
21609
21986
  action.apply(view, found.from, found.to);
@@ -21830,7 +22207,8 @@
21830
22207
  backgroundColor: "#444",
21831
22208
  color: "white",
21832
22209
  borderRadius: "3px",
21833
- marginLeft: "8px"
22210
+ marginLeft: "8px",
22211
+ cursor: "pointer"
21834
22212
  },
21835
22213
  ".cm-diagnosticSource": {
21836
22214
  fontSize: "70%",
@@ -24535,6 +24913,7 @@
24535
24913
  this.headerRenderer = headerRenderer;
24536
24914
  this.cellRenderer = cellRenderer;
24537
24915
 
24916
+ this.classList.add('resize-table');
24538
24917
  this.style.tableLayout = 'auto';
24539
24918
  this.style.width = '100%';
24540
24919
 
@@ -24870,9 +25249,10 @@
24870
25249
 
24871
25250
  function init (parent, onSubmit, onShiftSubmit) {
24872
25251
  addEventListener('#query-tab-button', 'click', (event) => selectTab(event, 'query'));
25252
+ addEventListener('#graph-tab-button', 'click', (event) => selectTab(event, 'graph'));
24873
25253
  addEventListener('#saved-tab-button', 'click', (event) => selectTab(event, 'saved'));
24874
25254
  addEventListener('#structure-tab-button', 'click', (event) => selectTab(event, 'structure'));
24875
- addEventListener('#graph-tab-button', 'click', (event) => selectTab(event, 'graph'));
25255
+ addEventListener('#help-tab-button', 'click', (event) => selectTab(event, 'help'));
24876
25256
  addEventListener('#cancel-button', 'click', () => clearResult());
24877
25257
 
24878
25258
  addEventListener('#query-box', 'click', () => {
@@ -25046,7 +25426,7 @@
25046
25426
 
25047
25427
  function getTabFromUrl (url) {
25048
25428
  const match = url.pathname.match(/\/([^/]+)$/);
25049
- if (match && ['query', 'graph', 'structure', 'saved'].includes(match[1])) {
25429
+ if (match && ['query', 'graph', 'saved', 'structure', 'help'].includes(match[1])) {
25050
25430
  return match[1]
25051
25431
  } else {
25052
25432
  throw new Error(`invalid tab: ${url.pathname}`)
@@ -25055,14 +25435,16 @@
25055
25435
 
25056
25436
  function updateTabs () {
25057
25437
  const url = new URL(window.location);
25438
+ setActionInUrl(url, 'query');
25439
+ document.getElementById('query-tab-button').href = url.pathname + url.search;
25058
25440
  setActionInUrl(url, 'graph');
25059
25441
  document.getElementById('graph-tab-button').href = url.pathname + url.search;
25060
25442
  setActionInUrl(url, 'saved');
25061
25443
  document.getElementById('saved-tab-button').href = url.pathname + url.search;
25062
25444
  setActionInUrl(url, 'structure');
25063
25445
  document.getElementById('structure-tab-button').href = url.pathname + url.search;
25064
- setActionInUrl(url, 'query');
25065
- document.getElementById('query-tab-button').href = url.pathname + url.search;
25446
+ setActionInUrl(url, 'help');
25447
+ document.getElementById('help-tab-button').href = url.pathname + url.search;
25066
25448
  }
25067
25449
 
25068
25450
  function selectTab (event, tab) {
@@ -25122,6 +25504,9 @@
25122
25504
  case 'structure':
25123
25505
  selectStructureTab();
25124
25506
  break
25507
+ case 'help':
25508
+ selectHelpTab();
25509
+ break
25125
25510
  default:
25126
25511
  throw new Error(`Unexpected tab: ${window.tab}`)
25127
25512
  }
@@ -25271,6 +25656,10 @@
25271
25656
  window.structureLoaded = true;
25272
25657
  }
25273
25658
 
25659
+ function selectHelpTab () {
25660
+ document.getElementById('help-box').style.display = 'block';
25661
+ }
25662
+
25274
25663
  function selectGraphTab (internal) {
25275
25664
  document.getElementById('query-box').style.display = 'flex';
25276
25665
  document.getElementById('submit-box').style.display = 'flex';