sqlui 0.1.67 → 0.1.69

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
  });
@@ -9480,7 +9566,7 @@
9480
9566
  }
9481
9567
  });
9482
9568
  }
9483
- const baseTheme$1$3 = /*@__PURE__*/buildTheme("." + baseThemeID, {
9569
+ const baseTheme$1$2 = /*@__PURE__*/buildTheme("." + baseThemeID, {
9484
9570
  "&": {
9485
9571
  position: "relative !important",
9486
9572
  boxSizing: "border-box",
@@ -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();
@@ -10809,7 +10921,7 @@
10809
10921
  }
10810
10922
  mountStyles() {
10811
10923
  this.styleModules = this.state.facet(styleModule);
10812
- StyleModule.mount(this.root, this.styleModules.concat(baseTheme$1$3).reverse());
10924
+ StyleModule.mount(this.root, this.styleModules.concat(baseTheme$1$2).reverse());
10813
10925
  }
10814
10926
  readMeasured() {
10815
10927
  if (this.updateState == 2 /* UpdateState.Updating */)
@@ -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) {
@@ -12744,214 +12865,6 @@
12744
12865
  const showTooltip = /*@__PURE__*/Facet.define({
12745
12866
  enables: [tooltipPlugin, baseTheme$4]
12746
12867
  });
12747
- const showHoverTooltip = /*@__PURE__*/Facet.define();
12748
- class HoverTooltipHost {
12749
- constructor(view) {
12750
- this.view = view;
12751
- this.mounted = false;
12752
- this.dom = document.createElement("div");
12753
- this.dom.classList.add("cm-tooltip-hover");
12754
- this.manager = new TooltipViewManager(view, showHoverTooltip, t => this.createHostedView(t));
12755
- }
12756
- // Needs to be static so that host tooltip instances always match
12757
- static create(view) {
12758
- return new HoverTooltipHost(view);
12759
- }
12760
- createHostedView(tooltip) {
12761
- let hostedView = tooltip.create(this.view);
12762
- hostedView.dom.classList.add("cm-tooltip-section");
12763
- this.dom.appendChild(hostedView.dom);
12764
- if (this.mounted && hostedView.mount)
12765
- hostedView.mount(this.view);
12766
- return hostedView;
12767
- }
12768
- mount(view) {
12769
- for (let hostedView of this.manager.tooltipViews) {
12770
- if (hostedView.mount)
12771
- hostedView.mount(view);
12772
- }
12773
- this.mounted = true;
12774
- }
12775
- positioned(space) {
12776
- for (let hostedView of this.manager.tooltipViews) {
12777
- if (hostedView.positioned)
12778
- hostedView.positioned(space);
12779
- }
12780
- }
12781
- update(update) {
12782
- this.manager.update(update);
12783
- }
12784
- }
12785
- const showHoverTooltipHost = /*@__PURE__*/showTooltip.compute([showHoverTooltip], state => {
12786
- let tooltips = state.facet(showHoverTooltip).filter(t => t);
12787
- if (tooltips.length === 0)
12788
- return null;
12789
- return {
12790
- pos: Math.min(...tooltips.map(t => t.pos)),
12791
- end: Math.max(...tooltips.filter(t => t.end != null).map(t => t.end)),
12792
- create: HoverTooltipHost.create,
12793
- above: tooltips[0].above,
12794
- arrow: tooltips.some(t => t.arrow),
12795
- };
12796
- });
12797
- class HoverPlugin {
12798
- constructor(view, source, field, setHover, hoverTime) {
12799
- this.view = view;
12800
- this.source = source;
12801
- this.field = field;
12802
- this.setHover = setHover;
12803
- this.hoverTime = hoverTime;
12804
- this.hoverTimeout = -1;
12805
- this.restartTimeout = -1;
12806
- this.pending = null;
12807
- this.lastMove = { x: 0, y: 0, target: view.dom, time: 0 };
12808
- this.checkHover = this.checkHover.bind(this);
12809
- view.dom.addEventListener("mouseleave", this.mouseleave = this.mouseleave.bind(this));
12810
- view.dom.addEventListener("mousemove", this.mousemove = this.mousemove.bind(this));
12811
- }
12812
- update() {
12813
- if (this.pending) {
12814
- this.pending = null;
12815
- clearTimeout(this.restartTimeout);
12816
- this.restartTimeout = setTimeout(() => this.startHover(), 20);
12817
- }
12818
- }
12819
- get active() {
12820
- return this.view.state.field(this.field);
12821
- }
12822
- checkHover() {
12823
- this.hoverTimeout = -1;
12824
- if (this.active)
12825
- return;
12826
- let hovered = Date.now() - this.lastMove.time;
12827
- if (hovered < this.hoverTime)
12828
- this.hoverTimeout = setTimeout(this.checkHover, this.hoverTime - hovered);
12829
- else
12830
- this.startHover();
12831
- }
12832
- startHover() {
12833
- clearTimeout(this.restartTimeout);
12834
- let { lastMove } = this;
12835
- let pos = this.view.contentDOM.contains(lastMove.target) ? this.view.posAtCoords(lastMove) : null;
12836
- if (pos == null)
12837
- return;
12838
- let posCoords = this.view.coordsAtPos(pos);
12839
- if (posCoords == null || lastMove.y < posCoords.top || lastMove.y > posCoords.bottom ||
12840
- lastMove.x < posCoords.left - this.view.defaultCharacterWidth ||
12841
- lastMove.x > posCoords.right + this.view.defaultCharacterWidth)
12842
- return;
12843
- let bidi = this.view.bidiSpans(this.view.state.doc.lineAt(pos)).find(s => s.from <= pos && s.to >= pos);
12844
- let rtl = bidi && bidi.dir == Direction.RTL ? -1 : 1;
12845
- let open = this.source(this.view, pos, (lastMove.x < posCoords.left ? -rtl : rtl));
12846
- if (open === null || open === void 0 ? void 0 : open.then) {
12847
- let pending = this.pending = { pos };
12848
- open.then(result => {
12849
- if (this.pending == pending) {
12850
- this.pending = null;
12851
- if (result)
12852
- this.view.dispatch({ effects: this.setHover.of(result) });
12853
- }
12854
- }, e => logException(this.view.state, e, "hover tooltip"));
12855
- }
12856
- else if (open) {
12857
- this.view.dispatch({ effects: this.setHover.of(open) });
12858
- }
12859
- }
12860
- mousemove(event) {
12861
- var _a;
12862
- this.lastMove = { x: event.clientX, y: event.clientY, target: event.target, time: Date.now() };
12863
- if (this.hoverTimeout < 0)
12864
- this.hoverTimeout = setTimeout(this.checkHover, this.hoverTime);
12865
- let tooltip = this.active;
12866
- if (tooltip && !isInTooltip(this.lastMove.target) || this.pending) {
12867
- let { pos } = tooltip || this.pending, end = (_a = tooltip === null || tooltip === void 0 ? void 0 : tooltip.end) !== null && _a !== void 0 ? _a : pos;
12868
- if ((pos == end ? this.view.posAtCoords(this.lastMove) != pos
12869
- : !isOverRange(this.view, pos, end, event.clientX, event.clientY, 6 /* Hover.MaxDist */))) {
12870
- this.view.dispatch({ effects: this.setHover.of(null) });
12871
- this.pending = null;
12872
- }
12873
- }
12874
- }
12875
- mouseleave(e) {
12876
- clearTimeout(this.hoverTimeout);
12877
- this.hoverTimeout = -1;
12878
- if (this.active && !isInTooltip(e.relatedTarget))
12879
- this.view.dispatch({ effects: this.setHover.of(null) });
12880
- }
12881
- destroy() {
12882
- clearTimeout(this.hoverTimeout);
12883
- this.view.dom.removeEventListener("mouseleave", this.mouseleave);
12884
- this.view.dom.removeEventListener("mousemove", this.mousemove);
12885
- }
12886
- }
12887
- function isInTooltip(elt) {
12888
- for (let cur = elt; cur; cur = cur.parentNode)
12889
- if (cur.nodeType == 1 && cur.classList.contains("cm-tooltip"))
12890
- return true;
12891
- return false;
12892
- }
12893
- function isOverRange(view, from, to, x, y, margin) {
12894
- let range = document.createRange();
12895
- let fromDOM = view.domAtPos(from), toDOM = view.domAtPos(to);
12896
- range.setEnd(toDOM.node, toDOM.offset);
12897
- range.setStart(fromDOM.node, fromDOM.offset);
12898
- let rects = range.getClientRects();
12899
- range.detach();
12900
- for (let i = 0; i < rects.length; i++) {
12901
- let rect = rects[i];
12902
- let dist = Math.max(rect.top - y, y - rect.bottom, rect.left - x, x - rect.right);
12903
- if (dist <= margin)
12904
- return true;
12905
- }
12906
- return false;
12907
- }
12908
- /**
12909
- Set up a hover tooltip, which shows up when the pointer hovers
12910
- over ranges of text. The callback is called when the mouse hovers
12911
- over the document text. It should, if there is a tooltip
12912
- associated with position `pos`, return the tooltip description
12913
- (either directly or in a promise). The `side` argument indicates
12914
- on which side of the position the pointer is—it will be -1 if the
12915
- pointer is before the position, 1 if after the position.
12916
-
12917
- Note that all hover tooltips are hosted within a single tooltip
12918
- container element. This allows multiple tooltips over the same
12919
- range to be "merged" together without overlapping.
12920
- */
12921
- function hoverTooltip(source, options = {}) {
12922
- let setHover = StateEffect.define();
12923
- let hoverState = StateField.define({
12924
- create() { return null; },
12925
- update(value, tr) {
12926
- if (value && (options.hideOnChange && (tr.docChanged || tr.selection) ||
12927
- options.hideOn && options.hideOn(tr, value)))
12928
- return null;
12929
- if (value && tr.docChanged) {
12930
- let newPos = tr.changes.mapPos(value.pos, -1, MapMode.TrackDel);
12931
- if (newPos == null)
12932
- return null;
12933
- let copy = Object.assign(Object.create(null), value);
12934
- copy.pos = newPos;
12935
- if (value.end != null)
12936
- copy.end = tr.changes.mapPos(value.end);
12937
- value = copy;
12938
- }
12939
- for (let effect of tr.effects) {
12940
- if (effect.is(setHover))
12941
- value = effect.value;
12942
- if (effect.is(closeHoverTooltipEffect))
12943
- value = null;
12944
- }
12945
- return value;
12946
- },
12947
- provide: f => showHoverTooltip.from(f)
12948
- });
12949
- return [
12950
- hoverState,
12951
- ViewPlugin.define(view => new HoverPlugin(view, source, hoverState, setHover, options.hoverTime || 300 /* Hover.Time */)),
12952
- showHoverTooltipHost
12953
- ];
12954
- }
12955
12868
  /**
12956
12869
  Get the active tooltip view for a given tooltip, if available.
12957
12870
  */
@@ -12962,7 +12875,6 @@
12962
12875
  let found = plugin.manager.tooltips.indexOf(tooltip);
12963
12876
  return found < 0 ? null : plugin.manager.tooltipViews[found];
12964
12877
  }
12965
- const closeHoverTooltipEffect = /*@__PURE__*/StateEffect.define();
12966
12878
 
12967
12879
  const panelConfig = /*@__PURE__*/Facet.define({
12968
12880
  combine(configs) {
@@ -14943,45 +14855,59 @@
14943
14855
  new NodeProp({ perNode: true });
14944
14856
 
14945
14857
  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).
14858
+ /**
14859
+ Highlighting tags are markers that denote a highlighting category.
14860
+ They are [associated](#highlight.styleTags) with parts of a syntax
14861
+ tree by a language mode, and then mapped to an actual CSS style by
14862
+ a [highlighter](#highlight.Highlighter).
14863
+
14864
+ Because syntax tree node types and highlight styles have to be
14865
+ able to talk the same language, CodeMirror uses a mostly _closed_
14866
+ [vocabulary](#highlight.tags) of syntax tags (as opposed to
14867
+ traditional open string-based systems, which make it hard for
14868
+ highlighting themes to cover all the tokens produced by the
14869
+ various languages).
14870
+
14871
+ It _is_ possible to [define](#highlight.Tag^define) your own
14872
+ highlighting tags for system-internal use (where you control both
14873
+ the language package and the highlighter), but such tags will not
14874
+ be picked up by regular highlighters (though you can derive them
14875
+ from standard tags to allow highlighters to fall back to those).
14876
+ */
14963
14877
  class Tag {
14964
- /// @internal
14878
+ /**
14879
+ @internal
14880
+ */
14965
14881
  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.
14882
+ /**
14883
+ The set of this tag and all its parent tags, starting with
14884
+ this one itself and sorted in order of decreasing specificity.
14885
+ */
14968
14886
  set,
14969
- /// The base unmodified tag that this one is based on, if it's
14970
- /// modified @internal
14887
+ /**
14888
+ The base unmodified tag that this one is based on, if it's
14889
+ modified @internal
14890
+ */
14971
14891
  base,
14972
- /// The modifiers applied to this.base @internal
14892
+ /**
14893
+ The modifiers applied to this.base @internal
14894
+ */
14973
14895
  modified) {
14974
14896
  this.set = set;
14975
14897
  this.base = base;
14976
14898
  this.modified = modified;
14977
- /// @internal
14899
+ /**
14900
+ @internal
14901
+ */
14978
14902
  this.id = nextTagID++;
14979
14903
  }
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).
14904
+ /**
14905
+ Define a new tag. If `parent` is given, the tag is treated as a
14906
+ sub-tag of that parent, and
14907
+ [highlighters](#highlight.tagHighlighter) that don't mention
14908
+ this tag will try to fall back to the parent tag (or grandparent
14909
+ tag, etc).
14910
+ */
14985
14911
  static define(parent) {
14986
14912
  if (parent === null || parent === void 0 ? void 0 : parent.base)
14987
14913
  throw new Error("Can not derive from a modified tag");
@@ -14992,16 +14918,18 @@
14992
14918
  tag.set.push(t);
14993
14919
  return tag;
14994
14920
  }
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.
14921
+ /**
14922
+ Define a tag _modifier_, which is a function that, given a tag,
14923
+ will return a tag that is a subtag of the original. Applying the
14924
+ same modifier to a twice tag will return the same value (`m1(t1)
14925
+ == m1(t1)`) and applying multiple modifiers will, regardless or
14926
+ order, produce the same tag (`m1(m2(t1)) == m2(m1(t1))`).
14927
+
14928
+ When multiple modifiers are applied to a given base tag, each
14929
+ smaller set of modifiers is registered as a parent, so that for
14930
+ example `m1(m2(m3(t1)))` is a subtype of `m1(m2(t1))`,
14931
+ `m1(m3(t1)`, and so on.
14932
+ */
15005
14933
  static defineModifier() {
15006
14934
  let mod = new Modifier;
15007
14935
  return (tag) => {
@@ -15046,55 +14974,57 @@
15046
14974
  }
15047
14975
  return sets.sort((a, b) => b.length - a.length);
15048
14976
  }
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
- /// ```
14977
+ /**
14978
+ This function is used to add a set of tags to a language syntax
14979
+ via [`NodeSet.extend`](#common.NodeSet.extend) or
14980
+ [`LRParser.configure`](#lr.LRParser.configure).
14981
+
14982
+ The argument object maps node selectors to [highlighting
14983
+ tags](#highlight.Tag) or arrays of tags.
14984
+
14985
+ Node selectors may hold one or more (space-separated) node paths.
14986
+ Such a path can be a [node name](#common.NodeType.name), or
14987
+ multiple node names (or `*` wildcards) separated by slash
14988
+ characters, as in `"Block/Declaration/VariableName"`. Such a path
14989
+ matches the final node but only if its direct parent nodes are the
14990
+ other nodes mentioned. A `*` in such a path matches any parent,
14991
+ but only a single level—wildcards that match multiple parents
14992
+ aren't supported, both for efficiency reasons and because Lezer
14993
+ trees make it rather hard to reason about what they would match.)
14994
+
14995
+ A path can be ended with `/...` to indicate that the tag assigned
14996
+ to the node should also apply to all child nodes, even if they
14997
+ match their own style (by default, only the innermost style is
14998
+ used).
14999
+
15000
+ When a path ends in `!`, as in `Attribute!`, no further matching
15001
+ happens for the node's child nodes, and the entire node gets the
15002
+ given style.
15003
+
15004
+ In this notation, node names that contain `/`, `!`, `*`, or `...`
15005
+ must be quoted as JSON strings.
15006
+
15007
+ For example:
15008
+
15009
+ ```javascript
15010
+ parser.withProps(
15011
+ styleTags({
15012
+ // Style Number and BigNumber nodes
15013
+ "Number BigNumber": tags.number,
15014
+ // Style Escape nodes whose parent is String
15015
+ "String/Escape": tags.escape,
15016
+ // Style anything inside Attributes nodes
15017
+ "Attributes!": tags.meta,
15018
+ // Add a style to all content inside Italic nodes
15019
+ "Italic/...": tags.emphasis,
15020
+ // Style InvalidString nodes as both `string` and `invalid`
15021
+ "InvalidString": [tags.string, tags.invalid],
15022
+ // Style the node named "/" as punctuation
15023
+ '"/"': tags.punctuation
15024
+ })
15025
+ )
15026
+ ```
15027
+ */
15098
15028
  function styleTags(spec) {
15099
15029
  let byName = Object.create(null);
15100
15030
  for (let prop in spec) {
@@ -15103,10 +15033,10 @@
15103
15033
  tags = [tags];
15104
15034
  for (let part of prop.split(" "))
15105
15035
  if (part) {
15106
- let pieces = [], mode = 2 /* Mode.Normal */, rest = part;
15036
+ let pieces = [], mode = 2 /* Normal */, rest = part;
15107
15037
  for (let pos = 0;;) {
15108
15038
  if (rest == "..." && pos > 0 && pos + 3 == part.length) {
15109
- mode = 1 /* Mode.Inherit */;
15039
+ mode = 1 /* Inherit */;
15110
15040
  break;
15111
15041
  }
15112
15042
  let m = /^"(?:[^"\\]|\\.)*?"|[^\/!]+/.exec(rest);
@@ -15118,7 +15048,7 @@
15118
15048
  break;
15119
15049
  let next = part[pos++];
15120
15050
  if (pos == part.length && next == "!") {
15121
- mode = 0 /* Mode.Opaque */;
15051
+ mode = 0 /* Opaque */;
15122
15052
  break;
15123
15053
  }
15124
15054
  if (next != "/")
@@ -15142,8 +15072,8 @@
15142
15072
  this.context = context;
15143
15073
  this.next = next;
15144
15074
  }
15145
- get opaque() { return this.mode == 0 /* Mode.Opaque */; }
15146
- get inherit() { return this.mode == 1 /* Mode.Inherit */; }
15075
+ get opaque() { return this.mode == 0 /* Opaque */; }
15076
+ get inherit() { return this.mode == 1 /* Inherit */; }
15147
15077
  sort(other) {
15148
15078
  if (!other || other.depth < this.depth) {
15149
15079
  this.next = other;
@@ -15154,10 +15084,12 @@
15154
15084
  }
15155
15085
  get depth() { return this.context ? this.context.length : 0; }
15156
15086
  }
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.
15087
+ Rule.empty = new Rule([], 2 /* Normal */, null);
15088
+ /**
15089
+ Define a [highlighter](#highlight.Highlighter) from an array of
15090
+ tag/class pairs. Classes associated with more specific tags will
15091
+ take precedence.
15092
+ */
15161
15093
  function tagHighlighter(tags, options) {
15162
15094
  let map = Object.create(null);
15163
15095
  for (let style of tags) {
@@ -15194,16 +15126,24 @@
15194
15126
  }
15195
15127
  return result;
15196
15128
  }
15197
- /// Highlight the given [tree](#common.Tree) with the given
15198
- /// [highlighter](#highlight.Highlighter).
15129
+ /**
15130
+ Highlight the given [tree](#common.Tree) with the given
15131
+ [highlighter](#highlight.Highlighter).
15132
+ */
15199
15133
  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.
15134
+ /**
15135
+ Assign styling to a region of the text. Will be called, in order
15136
+ of position, for any ranges where more than zero classes apply.
15137
+ `classes` is a space separated string of CSS classes.
15138
+ */
15203
15139
  putStyle,
15204
- /// The start of the range to highlight.
15140
+ /**
15141
+ The start of the range to highlight.
15142
+ */
15205
15143
  from = 0,
15206
- /// The end of the range.
15144
+ /**
15145
+ The end of the range.
15146
+ */
15207
15147
  to = tree.length) {
15208
15148
  let builder = new HighlightBuilder(from, Array.isArray(highlighter) ? highlighter : [highlighter], putStyle);
15209
15149
  builder.highlightRange(tree.cursor(), from, to, "", builder.highlighters);
@@ -15241,7 +15181,7 @@
15241
15181
  if (cls)
15242
15182
  cls += " ";
15243
15183
  cls += tagCls;
15244
- if (rule.mode == 1 /* Mode.Inherit */)
15184
+ if (rule.mode == 1 /* Inherit */)
15245
15185
  inheritedClass += (inheritedClass ? " " : "") + tagCls;
15246
15186
  }
15247
15187
  this.startSpan(cursor.from, cls);
@@ -15288,9 +15228,11 @@
15288
15228
  }
15289
15229
  }
15290
15230
  }
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 (`/...`).
15231
+ /**
15232
+ Match a syntax node's [highlight rules](#highlight.styleTags). If
15233
+ there's a match, return its set of tags, and whether it is
15234
+ opaque (uses a `!`) or applies to all child nodes (`/...`).
15235
+ */
15294
15236
  function getStyleTags(node) {
15295
15237
  let rule = node.type.prop(ruleNodeProp);
15296
15238
  while (rule && rule.context && !node.matchContext(rule.context))
@@ -15299,268 +15241,440 @@
15299
15241
  }
15300
15242
  const t = Tag.define;
15301
15243
  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.
15244
+ /**
15245
+ The default set of highlighting [tags](#highlight.Tag).
15246
+
15247
+ This collection is heavily biased towards programming languages,
15248
+ and necessarily incomplete. A full ontology of syntactic
15249
+ constructs would fill a stack of books, and be impractical to
15250
+ write themes for. So try to make do with this set. If all else
15251
+ fails, [open an
15252
+ issue](https://github.com/codemirror/codemirror.next) to propose a
15253
+ new tag, or [define](#highlight.Tag^define) a local custom tag for
15254
+ your use case.
15255
+
15256
+ Note that it is not obligatory to always attach the most specific
15257
+ tag possible to an element—if your grammar can't easily
15258
+ distinguish a certain type of element (such as a local variable),
15259
+ it is okay to style it as its more general variant (a variable).
15260
+
15261
+ For tags that extend some parent tag, the documentation links to
15262
+ the parent.
15263
+ */
15320
15264
  const tags = {
15321
- /// A comment.
15265
+ /**
15266
+ A comment.
15267
+ */
15322
15268
  comment,
15323
- /// A line [comment](#highlight.tags.comment).
15269
+ /**
15270
+ A line [comment](#highlight.tags.comment).
15271
+ */
15324
15272
  lineComment: t(comment),
15325
- /// A block [comment](#highlight.tags.comment).
15273
+ /**
15274
+ A block [comment](#highlight.tags.comment).
15275
+ */
15326
15276
  blockComment: t(comment),
15327
- /// A documentation [comment](#highlight.tags.comment).
15277
+ /**
15278
+ A documentation [comment](#highlight.tags.comment).
15279
+ */
15328
15280
  docComment: t(comment),
15329
- /// Any kind of identifier.
15281
+ /**
15282
+ Any kind of identifier.
15283
+ */
15330
15284
  name,
15331
- /// The [name](#highlight.tags.name) of a variable.
15285
+ /**
15286
+ The [name](#highlight.tags.name) of a variable.
15287
+ */
15332
15288
  variableName: t(name),
15333
- /// A type [name](#highlight.tags.name).
15289
+ /**
15290
+ A type [name](#highlight.tags.name).
15291
+ */
15334
15292
  typeName: typeName,
15335
- /// A tag name (subtag of [`typeName`](#highlight.tags.typeName)).
15293
+ /**
15294
+ A tag name (subtag of [`typeName`](#highlight.tags.typeName)).
15295
+ */
15336
15296
  tagName: t(typeName),
15337
- /// A property or field [name](#highlight.tags.name).
15297
+ /**
15298
+ A property or field [name](#highlight.tags.name).
15299
+ */
15338
15300
  propertyName: propertyName,
15339
- /// An attribute name (subtag of [`propertyName`](#highlight.tags.propertyName)).
15301
+ /**
15302
+ An attribute name (subtag of [`propertyName`](#highlight.tags.propertyName)).
15303
+ */
15340
15304
  attributeName: t(propertyName),
15341
- /// The [name](#highlight.tags.name) of a class.
15305
+ /**
15306
+ The [name](#highlight.tags.name) of a class.
15307
+ */
15342
15308
  className: t(name),
15343
- /// A label [name](#highlight.tags.name).
15309
+ /**
15310
+ A label [name](#highlight.tags.name).
15311
+ */
15344
15312
  labelName: t(name),
15345
- /// A namespace [name](#highlight.tags.name).
15313
+ /**
15314
+ A namespace [name](#highlight.tags.name).
15315
+ */
15346
15316
  namespace: t(name),
15347
- /// The [name](#highlight.tags.name) of a macro.
15317
+ /**
15318
+ The [name](#highlight.tags.name) of a macro.
15319
+ */
15348
15320
  macroName: t(name),
15349
- /// A literal value.
15321
+ /**
15322
+ A literal value.
15323
+ */
15350
15324
  literal,
15351
- /// A string [literal](#highlight.tags.literal).
15325
+ /**
15326
+ A string [literal](#highlight.tags.literal).
15327
+ */
15352
15328
  string,
15353
- /// A documentation [string](#highlight.tags.string).
15329
+ /**
15330
+ A documentation [string](#highlight.tags.string).
15331
+ */
15354
15332
  docString: t(string),
15355
- /// A character literal (subtag of [string](#highlight.tags.string)).
15333
+ /**
15334
+ A character literal (subtag of [string](#highlight.tags.string)).
15335
+ */
15356
15336
  character: t(string),
15357
- /// An attribute value (subtag of [string](#highlight.tags.string)).
15337
+ /**
15338
+ An attribute value (subtag of [string](#highlight.tags.string)).
15339
+ */
15358
15340
  attributeValue: t(string),
15359
- /// A number [literal](#highlight.tags.literal).
15341
+ /**
15342
+ A number [literal](#highlight.tags.literal).
15343
+ */
15360
15344
  number,
15361
- /// An integer [number](#highlight.tags.number) literal.
15345
+ /**
15346
+ An integer [number](#highlight.tags.number) literal.
15347
+ */
15362
15348
  integer: t(number),
15363
- /// A floating-point [number](#highlight.tags.number) literal.
15349
+ /**
15350
+ A floating-point [number](#highlight.tags.number) literal.
15351
+ */
15364
15352
  float: t(number),
15365
- /// A boolean [literal](#highlight.tags.literal).
15353
+ /**
15354
+ A boolean [literal](#highlight.tags.literal).
15355
+ */
15366
15356
  bool: t(literal),
15367
- /// Regular expression [literal](#highlight.tags.literal).
15357
+ /**
15358
+ Regular expression [literal](#highlight.tags.literal).
15359
+ */
15368
15360
  regexp: t(literal),
15369
- /// An escape [literal](#highlight.tags.literal), for example a
15370
- /// backslash escape in a string.
15361
+ /**
15362
+ An escape [literal](#highlight.tags.literal), for example a
15363
+ backslash escape in a string.
15364
+ */
15371
15365
  escape: t(literal),
15372
- /// A color [literal](#highlight.tags.literal).
15366
+ /**
15367
+ A color [literal](#highlight.tags.literal).
15368
+ */
15373
15369
  color: t(literal),
15374
- /// A URL [literal](#highlight.tags.literal).
15370
+ /**
15371
+ A URL [literal](#highlight.tags.literal).
15372
+ */
15375
15373
  url: t(literal),
15376
- /// A language keyword.
15374
+ /**
15375
+ A language keyword.
15376
+ */
15377
15377
  keyword,
15378
- /// The [keyword](#highlight.tags.keyword) for the self or this
15379
- /// object.
15378
+ /**
15379
+ The [keyword](#highlight.tags.keyword) for the self or this
15380
+ object.
15381
+ */
15380
15382
  self: t(keyword),
15381
- /// The [keyword](#highlight.tags.keyword) for null.
15383
+ /**
15384
+ The [keyword](#highlight.tags.keyword) for null.
15385
+ */
15382
15386
  null: t(keyword),
15383
- /// A [keyword](#highlight.tags.keyword) denoting some atomic value.
15387
+ /**
15388
+ A [keyword](#highlight.tags.keyword) denoting some atomic value.
15389
+ */
15384
15390
  atom: t(keyword),
15385
- /// A [keyword](#highlight.tags.keyword) that represents a unit.
15391
+ /**
15392
+ A [keyword](#highlight.tags.keyword) that represents a unit.
15393
+ */
15386
15394
  unit: t(keyword),
15387
- /// A modifier [keyword](#highlight.tags.keyword).
15395
+ /**
15396
+ A modifier [keyword](#highlight.tags.keyword).
15397
+ */
15388
15398
  modifier: t(keyword),
15389
- /// A [keyword](#highlight.tags.keyword) that acts as an operator.
15399
+ /**
15400
+ A [keyword](#highlight.tags.keyword) that acts as an operator.
15401
+ */
15390
15402
  operatorKeyword: t(keyword),
15391
- /// A control-flow related [keyword](#highlight.tags.keyword).
15403
+ /**
15404
+ A control-flow related [keyword](#highlight.tags.keyword).
15405
+ */
15392
15406
  controlKeyword: t(keyword),
15393
- /// A [keyword](#highlight.tags.keyword) that defines something.
15407
+ /**
15408
+ A [keyword](#highlight.tags.keyword) that defines something.
15409
+ */
15394
15410
  definitionKeyword: t(keyword),
15395
- /// A [keyword](#highlight.tags.keyword) related to defining or
15396
- /// interfacing with modules.
15411
+ /**
15412
+ A [keyword](#highlight.tags.keyword) related to defining or
15413
+ interfacing with modules.
15414
+ */
15397
15415
  moduleKeyword: t(keyword),
15398
- /// An operator.
15416
+ /**
15417
+ An operator.
15418
+ */
15399
15419
  operator,
15400
- /// An [operator](#highlight.tags.operator) that dereferences something.
15420
+ /**
15421
+ An [operator](#highlight.tags.operator) that dereferences something.
15422
+ */
15401
15423
  derefOperator: t(operator),
15402
- /// Arithmetic-related [operator](#highlight.tags.operator).
15424
+ /**
15425
+ Arithmetic-related [operator](#highlight.tags.operator).
15426
+ */
15403
15427
  arithmeticOperator: t(operator),
15404
- /// Logical [operator](#highlight.tags.operator).
15428
+ /**
15429
+ Logical [operator](#highlight.tags.operator).
15430
+ */
15405
15431
  logicOperator: t(operator),
15406
- /// Bit [operator](#highlight.tags.operator).
15432
+ /**
15433
+ Bit [operator](#highlight.tags.operator).
15434
+ */
15407
15435
  bitwiseOperator: t(operator),
15408
- /// Comparison [operator](#highlight.tags.operator).
15436
+ /**
15437
+ Comparison [operator](#highlight.tags.operator).
15438
+ */
15409
15439
  compareOperator: t(operator),
15410
- /// [Operator](#highlight.tags.operator) that updates its operand.
15440
+ /**
15441
+ [Operator](#highlight.tags.operator) that updates its operand.
15442
+ */
15411
15443
  updateOperator: t(operator),
15412
- /// [Operator](#highlight.tags.operator) that defines something.
15444
+ /**
15445
+ [Operator](#highlight.tags.operator) that defines something.
15446
+ */
15413
15447
  definitionOperator: t(operator),
15414
- /// Type-related [operator](#highlight.tags.operator).
15448
+ /**
15449
+ Type-related [operator](#highlight.tags.operator).
15450
+ */
15415
15451
  typeOperator: t(operator),
15416
- /// Control-flow [operator](#highlight.tags.operator).
15452
+ /**
15453
+ Control-flow [operator](#highlight.tags.operator).
15454
+ */
15417
15455
  controlOperator: t(operator),
15418
- /// Program or markup punctuation.
15456
+ /**
15457
+ Program or markup punctuation.
15458
+ */
15419
15459
  punctuation,
15420
- /// [Punctuation](#highlight.tags.punctuation) that separates
15421
- /// things.
15460
+ /**
15461
+ [Punctuation](#highlight.tags.punctuation) that separates
15462
+ things.
15463
+ */
15422
15464
  separator: t(punctuation),
15423
- /// Bracket-style [punctuation](#highlight.tags.punctuation).
15465
+ /**
15466
+ Bracket-style [punctuation](#highlight.tags.punctuation).
15467
+ */
15424
15468
  bracket,
15425
- /// Angle [brackets](#highlight.tags.bracket) (usually `<` and `>`
15426
- /// tokens).
15469
+ /**
15470
+ Angle [brackets](#highlight.tags.bracket) (usually `<` and `>`
15471
+ tokens).
15472
+ */
15427
15473
  angleBracket: t(bracket),
15428
- /// Square [brackets](#highlight.tags.bracket) (usually `[` and `]`
15429
- /// tokens).
15474
+ /**
15475
+ Square [brackets](#highlight.tags.bracket) (usually `[` and `]`
15476
+ tokens).
15477
+ */
15430
15478
  squareBracket: t(bracket),
15431
- /// Parentheses (usually `(` and `)` tokens). Subtag of
15432
- /// [bracket](#highlight.tags.bracket).
15479
+ /**
15480
+ Parentheses (usually `(` and `)` tokens). Subtag of
15481
+ [bracket](#highlight.tags.bracket).
15482
+ */
15433
15483
  paren: t(bracket),
15434
- /// Braces (usually `{` and `}` tokens). Subtag of
15435
- /// [bracket](#highlight.tags.bracket).
15484
+ /**
15485
+ Braces (usually `{` and `}` tokens). Subtag of
15486
+ [bracket](#highlight.tags.bracket).
15487
+ */
15436
15488
  brace: t(bracket),
15437
- /// Content, for example plain text in XML or markup documents.
15489
+ /**
15490
+ Content, for example plain text in XML or markup documents.
15491
+ */
15438
15492
  content,
15439
- /// [Content](#highlight.tags.content) that represents a heading.
15493
+ /**
15494
+ [Content](#highlight.tags.content) that represents a heading.
15495
+ */
15440
15496
  heading,
15441
- /// A level 1 [heading](#highlight.tags.heading).
15497
+ /**
15498
+ A level 1 [heading](#highlight.tags.heading).
15499
+ */
15442
15500
  heading1: t(heading),
15443
- /// A level 2 [heading](#highlight.tags.heading).
15501
+ /**
15502
+ A level 2 [heading](#highlight.tags.heading).
15503
+ */
15444
15504
  heading2: t(heading),
15445
- /// A level 3 [heading](#highlight.tags.heading).
15505
+ /**
15506
+ A level 3 [heading](#highlight.tags.heading).
15507
+ */
15446
15508
  heading3: t(heading),
15447
- /// A level 4 [heading](#highlight.tags.heading).
15509
+ /**
15510
+ A level 4 [heading](#highlight.tags.heading).
15511
+ */
15448
15512
  heading4: t(heading),
15449
- /// A level 5 [heading](#highlight.tags.heading).
15513
+ /**
15514
+ A level 5 [heading](#highlight.tags.heading).
15515
+ */
15450
15516
  heading5: t(heading),
15451
- /// A level 6 [heading](#highlight.tags.heading).
15517
+ /**
15518
+ A level 6 [heading](#highlight.tags.heading).
15519
+ */
15452
15520
  heading6: t(heading),
15453
- /// A prose separator (such as a horizontal rule).
15521
+ /**
15522
+ A prose separator (such as a horizontal rule).
15523
+ */
15454
15524
  contentSeparator: t(content),
15455
- /// [Content](#highlight.tags.content) that represents a list.
15525
+ /**
15526
+ [Content](#highlight.tags.content) that represents a list.
15527
+ */
15456
15528
  list: t(content),
15457
- /// [Content](#highlight.tags.content) that represents a quote.
15529
+ /**
15530
+ [Content](#highlight.tags.content) that represents a quote.
15531
+ */
15458
15532
  quote: t(content),
15459
- /// [Content](#highlight.tags.content) that is emphasized.
15533
+ /**
15534
+ [Content](#highlight.tags.content) that is emphasized.
15535
+ */
15460
15536
  emphasis: t(content),
15461
- /// [Content](#highlight.tags.content) that is styled strong.
15537
+ /**
15538
+ [Content](#highlight.tags.content) that is styled strong.
15539
+ */
15462
15540
  strong: t(content),
15463
- /// [Content](#highlight.tags.content) that is part of a link.
15541
+ /**
15542
+ [Content](#highlight.tags.content) that is part of a link.
15543
+ */
15464
15544
  link: t(content),
15465
- /// [Content](#highlight.tags.content) that is styled as code or
15466
- /// monospace.
15545
+ /**
15546
+ [Content](#highlight.tags.content) that is styled as code or
15547
+ monospace.
15548
+ */
15467
15549
  monospace: t(content),
15468
- /// [Content](#highlight.tags.content) that has a strike-through
15469
- /// style.
15550
+ /**
15551
+ [Content](#highlight.tags.content) that has a strike-through
15552
+ style.
15553
+ */
15470
15554
  strikethrough: t(content),
15471
- /// Inserted text in a change-tracking format.
15555
+ /**
15556
+ Inserted text in a change-tracking format.
15557
+ */
15472
15558
  inserted: t(),
15473
- /// Deleted text.
15559
+ /**
15560
+ Deleted text.
15561
+ */
15474
15562
  deleted: t(),
15475
- /// Changed text.
15563
+ /**
15564
+ Changed text.
15565
+ */
15476
15566
  changed: t(),
15477
- /// An invalid or unsyntactic element.
15567
+ /**
15568
+ An invalid or unsyntactic element.
15569
+ */
15478
15570
  invalid: t(),
15479
- /// Metadata or meta-instruction.
15571
+ /**
15572
+ Metadata or meta-instruction.
15573
+ */
15480
15574
  meta,
15481
- /// [Metadata](#highlight.tags.meta) that applies to the entire
15482
- /// document.
15575
+ /**
15576
+ [Metadata](#highlight.tags.meta) that applies to the entire
15577
+ document.
15578
+ */
15483
15579
  documentMeta: t(meta),
15484
- /// [Metadata](#highlight.tags.meta) that annotates or adds
15485
- /// attributes to a given syntactic element.
15580
+ /**
15581
+ [Metadata](#highlight.tags.meta) that annotates or adds
15582
+ attributes to a given syntactic element.
15583
+ */
15486
15584
  annotation: t(meta),
15487
- /// Processing instruction or preprocessor directive. Subtag of
15488
- /// [meta](#highlight.tags.meta).
15585
+ /**
15586
+ Processing instruction or preprocessor directive. Subtag of
15587
+ [meta](#highlight.tags.meta).
15588
+ */
15489
15589
  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.
15590
+ /**
15591
+ [Modifier](#highlight.Tag^defineModifier) that indicates that a
15592
+ given element is being defined. Expected to be used with the
15593
+ various [name](#highlight.tags.name) tags.
15594
+ */
15493
15595
  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).
15596
+ /**
15597
+ [Modifier](#highlight.Tag^defineModifier) that indicates that
15598
+ something is constant. Mostly expected to be used with
15599
+ [variable names](#highlight.tags.variableName).
15600
+ */
15497
15601
  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.
15602
+ /**
15603
+ [Modifier](#highlight.Tag^defineModifier) used to indicate that
15604
+ a [variable](#highlight.tags.variableName) or [property
15605
+ name](#highlight.tags.propertyName) is being called or defined
15606
+ as a function.
15607
+ */
15502
15608
  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.
15609
+ /**
15610
+ [Modifier](#highlight.Tag^defineModifier) that can be applied to
15611
+ [names](#highlight.tags.name) to indicate that they belong to
15612
+ the language's standard environment.
15613
+ */
15506
15614
  standard: Tag.defineModifier(),
15507
- /// [Modifier](#highlight.Tag^defineModifier) that indicates a given
15508
- /// [names](#highlight.tags.name) is local to some scope.
15615
+ /**
15616
+ [Modifier](#highlight.Tag^defineModifier) that indicates a given
15617
+ [names](#highlight.tags.name) is local to some scope.
15618
+ */
15509
15619
  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.
15620
+ /**
15621
+ A generic variant [modifier](#highlight.Tag^defineModifier) that
15622
+ can be used to tag language-specific alternative variants of
15623
+ some common tag. It is recommended for themes to define special
15624
+ forms of at least the [string](#highlight.tags.string) and
15625
+ [variable name](#highlight.tags.variableName) tags, since those
15626
+ come up a lot.
15627
+ */
15516
15628
  special: Tag.defineModifier()
15517
15629
  };
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"`
15630
+ /**
15631
+ This is a highlighter that adds stable, predictable classes to
15632
+ tokens, for styling with external CSS.
15633
+
15634
+ The following tags are mapped to their name prefixed with `"tok-"`
15635
+ (for example `"tok-comment"`):
15636
+
15637
+ * [`link`](#highlight.tags.link)
15638
+ * [`heading`](#highlight.tags.heading)
15639
+ * [`emphasis`](#highlight.tags.emphasis)
15640
+ * [`strong`](#highlight.tags.strong)
15641
+ * [`keyword`](#highlight.tags.keyword)
15642
+ * [`atom`](#highlight.tags.atom)
15643
+ * [`bool`](#highlight.tags.bool)
15644
+ * [`url`](#highlight.tags.url)
15645
+ * [`labelName`](#highlight.tags.labelName)
15646
+ * [`inserted`](#highlight.tags.inserted)
15647
+ * [`deleted`](#highlight.tags.deleted)
15648
+ * [`literal`](#highlight.tags.literal)
15649
+ * [`string`](#highlight.tags.string)
15650
+ * [`number`](#highlight.tags.number)
15651
+ * [`variableName`](#highlight.tags.variableName)
15652
+ * [`typeName`](#highlight.tags.typeName)
15653
+ * [`namespace`](#highlight.tags.namespace)
15654
+ * [`className`](#highlight.tags.className)
15655
+ * [`macroName`](#highlight.tags.macroName)
15656
+ * [`propertyName`](#highlight.tags.propertyName)
15657
+ * [`operator`](#highlight.tags.operator)
15658
+ * [`comment`](#highlight.tags.comment)
15659
+ * [`meta`](#highlight.tags.meta)
15660
+ * [`punctuation`](#highlight.tags.punctuation)
15661
+ * [`invalid`](#highlight.tags.invalid)
15662
+
15663
+ In addition, these mappings are provided:
15664
+
15665
+ * [`regexp`](#highlight.tags.regexp),
15666
+ [`escape`](#highlight.tags.escape), and
15667
+ [`special`](#highlight.tags.special)[`(string)`](#highlight.tags.string)
15668
+ are mapped to `"tok-string2"`
15669
+ * [`special`](#highlight.tags.special)[`(variableName)`](#highlight.tags.variableName)
15670
+ to `"tok-variableName2"`
15671
+ * [`local`](#highlight.tags.local)[`(variableName)`](#highlight.tags.variableName)
15672
+ to `"tok-variableName tok-local"`
15673
+ * [`definition`](#highlight.tags.definition)[`(variableName)`](#highlight.tags.variableName)
15674
+ to `"tok-variableName tok-definition"`
15675
+ * [`definition`](#highlight.tags.definition)[`(propertyName)`](#highlight.tags.propertyName)
15676
+ to `"tok-propertyName tok-definition"`
15677
+ */
15564
15678
  tagHighlighter([
15565
15679
  { tag: tags.link, class: "tok-link" },
15566
15680
  { tag: tags.heading, class: "tok-heading" },
@@ -15614,6 +15728,11 @@
15614
15728
  });
15615
15729
  }
15616
15730
  /**
15731
+ Syntax node prop used to register sublangauges. Should be added to
15732
+ the top level node type for the language.
15733
+ */
15734
+ const sublanguageProp = /*@__PURE__*/new NodeProp();
15735
+ /**
15617
15736
  A language object manages parsing and per-language
15618
15737
  [metadata](https://codemirror.net/6/docs/ref/#state.EditorState.languageDataAt). Parse data is
15619
15738
  managed as a [Lezer](https://lezer.codemirror.net) tree. The class
@@ -15650,14 +15769,28 @@
15650
15769
  this.parser = parser;
15651
15770
  this.extension = [
15652
15771
  language.of(this),
15653
- EditorState.languageData.of((state, pos, side) => state.facet(languageDataFacetAt(state, pos, side)))
15772
+ EditorState.languageData.of((state, pos, side) => {
15773
+ let top = topNodeAt(state, pos, side), data = top.type.prop(languageDataProp);
15774
+ if (!data)
15775
+ return [];
15776
+ let base = state.facet(data), sub = top.type.prop(sublanguageProp);
15777
+ if (sub) {
15778
+ let innerNode = top.resolve(pos - top.from, side);
15779
+ for (let sublang of sub)
15780
+ if (sublang.test(innerNode, state)) {
15781
+ let data = state.facet(sublang.facet);
15782
+ return sublang.type == "replace" ? data : data.concat(base);
15783
+ }
15784
+ }
15785
+ return base;
15786
+ })
15654
15787
  ].concat(extraExtensions);
15655
15788
  }
15656
15789
  /**
15657
15790
  Query whether this language is active at the given position.
15658
15791
  */
15659
15792
  isActiveAt(state, pos, side = -1) {
15660
- return languageDataFacetAt(state, pos, side) == this.data;
15793
+ return topNodeAt(state, pos, side).type.prop(languageDataProp) == this.data;
15661
15794
  }
15662
15795
  /**
15663
15796
  Find the document regions that were parsed using this language.
@@ -15712,16 +15845,14 @@
15712
15845
  @internal
15713
15846
  */
15714
15847
  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;
15848
+ function topNodeAt(state, pos, side) {
15849
+ let topLang = state.facet(language), tree = syntaxTree(state).topNode;
15850
+ if (!topLang || topLang.allowsNesting) {
15851
+ for (let node = tree; node; node = node.enter(pos, side, IterMode.ExcludeBuffers))
15852
+ if (node.type.isTop)
15853
+ tree = node;
15723
15854
  }
15724
- return facet;
15855
+ return tree;
15725
15856
  }
15726
15857
  /**
15727
15858
  A subclass of [`Language`](https://codemirror.net/6/docs/ref/#language.Language) for use with Lezer
@@ -15763,13 +15894,13 @@
15763
15894
  }
15764
15895
  // Lezer-style Input object for a Text document.
15765
15896
  class DocInput {
15766
- constructor(doc, length = doc.length) {
15897
+ constructor(doc) {
15767
15898
  this.doc = doc;
15768
- this.length = length;
15769
15899
  this.cursorPos = 0;
15770
15900
  this.string = "";
15771
15901
  this.cursor = doc.iter();
15772
15902
  }
15903
+ get length() { return this.doc.length; }
15773
15904
  syncTo(pos) {
15774
15905
  this.string = this.cursor.next(pos - this.cursorPos).value;
15775
15906
  this.cursorPos = pos + this.string.length;
@@ -16217,17 +16348,18 @@
16217
16348
  */
16218
16349
  const indentService = /*@__PURE__*/Facet.define();
16219
16350
  /**
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.
16351
+ Facet for overriding the unit by which indentation happens. Should
16352
+ be a string consisting either entirely of the same whitespace
16353
+ character. When not set, this defaults to 2 spaces.
16223
16354
  */
16224
16355
  const indentUnit = /*@__PURE__*/Facet.define({
16225
16356
  combine: values => {
16226
16357
  if (!values.length)
16227
16358
  return " ";
16228
- if (!/^(?: +|\t+)$/.test(values[0]))
16359
+ let unit = values[0];
16360
+ if (!unit || /\S/.test(unit) || Array.from(unit).some(e => e != unit[0]))
16229
16361
  throw new Error("Invalid indent unit: " + JSON.stringify(values[0]));
16230
- return values[0];
16362
+ return unit;
16231
16363
  }
16232
16364
  });
16233
16365
  /**
@@ -16247,14 +16379,16 @@
16247
16379
  tabs.
16248
16380
  */
16249
16381
  function indentString(state, cols) {
16250
- let result = "", ts = state.tabSize;
16251
- if (state.facet(indentUnit).charCodeAt(0) == 9)
16382
+ let result = "", ts = state.tabSize, ch = state.facet(indentUnit)[0];
16383
+ if (ch == "\t") {
16252
16384
  while (cols >= ts) {
16253
16385
  result += "\t";
16254
16386
  cols -= ts;
16255
16387
  }
16388
+ ch = " ";
16389
+ }
16256
16390
  for (let i = 0; i < cols; i++)
16257
- result += " ";
16391
+ result += ch;
16258
16392
  return result;
16259
16393
  }
16260
16394
  /**
@@ -16802,7 +16936,7 @@
16802
16936
  Create an extension that configures code folding.
16803
16937
  */
16804
16938
  function codeFolding(config) {
16805
- let result = [foldState, baseTheme$1$2];
16939
+ let result = [foldState, baseTheme$1$1];
16806
16940
  if (config)
16807
16941
  result.push(foldConfig.of(config));
16808
16942
  return result;
@@ -16911,7 +17045,7 @@
16911
17045
  codeFolding()
16912
17046
  ];
16913
17047
  }
16914
- const baseTheme$1$2 = /*@__PURE__*/EditorView.baseTheme({
17048
+ const baseTheme$1$1 = /*@__PURE__*/EditorView.baseTheme({
16915
17049
  ".cm-foldPlaceholder": {
16916
17050
  backgroundColor: "#eee",
16917
17051
  border: "1px solid #ddd",
@@ -17307,7 +17441,7 @@
17307
17441
  if available, otherwise falling back to block comments.
17308
17442
  */
17309
17443
  const toggleComment = target => {
17310
- let config = getConfig(target.state);
17444
+ let { state } = target, line = state.doc.lineAt(state.selection.main.from), config = getConfig(target.state, line.from);
17311
17445
  return config.line ? toggleLineComment(target) : config.block ? toggleBlockCommentByLine(target) : false;
17312
17446
  };
17313
17447
  function command(f, option) {
@@ -17340,7 +17474,7 @@
17340
17474
  block comments.
17341
17475
  */
17342
17476
  const toggleBlockCommentByLine = /*@__PURE__*/command((o, s) => changeBlockComment(o, s, selectedLineRanges(s)), 0 /* CommentOption.Toggle */);
17343
- function getConfig(state, pos = state.selection.main.head) {
17477
+ function getConfig(state, pos) {
17344
17478
  let data = state.languageDataAt("commentTokens", pos);
17345
17479
  return data.length ? data[0] : {};
17346
17480
  }
@@ -17422,13 +17556,13 @@
17422
17556
  let prevLine = -1;
17423
17557
  for (let { from, to } of ranges) {
17424
17558
  let startI = lines.length, minIndent = 1e9;
17559
+ let token = getConfig(state, from).line;
17560
+ if (!token)
17561
+ continue;
17425
17562
  for (let pos = from; pos <= to;) {
17426
17563
  let line = state.doc.lineAt(pos);
17427
17564
  if (line.from > prevLine && (from == to || to > line.from)) {
17428
17565
  prevLine = line.from;
17429
- let token = getConfig(state, pos).line;
17430
- if (!token)
17431
- continue;
17432
17566
  let indent = /^\s*/.exec(line.text)[0].length;
17433
17567
  let empty = indent == line.length;
17434
17568
  let comment = line.text.slice(indent, indent + token.length) == token ? indent : -1;
@@ -17910,21 +18044,41 @@
17910
18044
  Move the selection one line down.
17911
18045
  */
17912
18046
  const cursorLineDown = view => cursorByLine(view, true);
17913
- function pageHeight(view) {
17914
- return Math.max(view.defaultLineHeight, Math.min(view.dom.clientHeight, innerHeight) - 5);
18047
+ function pageInfo(view) {
18048
+ let selfScroll = view.scrollDOM.clientHeight < view.scrollDOM.scrollHeight - 2;
18049
+ let marginTop = 0, marginBottom = 0, height;
18050
+ if (selfScroll) {
18051
+ for (let source of view.state.facet(EditorView.scrollMargins)) {
18052
+ let margins = source(view);
18053
+ if (margins === null || margins === void 0 ? void 0 : margins.top)
18054
+ marginTop = Math.max(margins === null || margins === void 0 ? void 0 : margins.top, marginTop);
18055
+ if (margins === null || margins === void 0 ? void 0 : margins.bottom)
18056
+ marginBottom = Math.max(margins === null || margins === void 0 ? void 0 : margins.bottom, marginBottom);
18057
+ }
18058
+ height = view.scrollDOM.clientHeight - marginTop - marginBottom;
18059
+ }
18060
+ else {
18061
+ height = (view.dom.ownerDocument.defaultView || window).innerHeight;
18062
+ }
18063
+ return { marginTop, marginBottom, selfScroll,
18064
+ height: Math.max(view.defaultLineHeight, height - 5) };
17915
18065
  }
17916
18066
  function cursorByPage(view, forward) {
18067
+ let page = pageInfo(view);
17917
18068
  let { state } = view, selection = updateSel(state.selection, range => {
17918
- return range.empty ? view.moveVertically(range, forward, pageHeight(view)) : rangeEnd(range, forward);
18069
+ return range.empty ? view.moveVertically(range, forward, page.height)
18070
+ : rangeEnd(range, forward);
17919
18071
  });
17920
18072
  if (selection.eq(state.selection))
17921
18073
  return false;
17922
- let startPos = view.coordsAtPos(state.selection.main.head);
17923
- let scrollRect = view.scrollDOM.getBoundingClientRect();
17924
18074
  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 });
18075
+ if (page.selfScroll) {
18076
+ let startPos = view.coordsAtPos(state.selection.main.head);
18077
+ let scrollRect = view.scrollDOM.getBoundingClientRect();
18078
+ let scrollTop = scrollRect.top + page.marginTop, scrollBottom = scrollRect.bottom - page.marginBottom;
18079
+ if (startPos && startPos.top > scrollTop && startPos.bottom < scrollBottom)
18080
+ effect = EditorView.scrollIntoView(selection.main.head, { y: "start", yMargin: startPos.top - scrollTop });
18081
+ }
17928
18082
  view.dispatch(setSel(state, selection), { effects: effect });
17929
18083
  return true;
17930
18084
  }
@@ -18051,7 +18205,7 @@
18051
18205
  */
18052
18206
  const selectLineDown = view => selectByLine(view, true);
18053
18207
  function selectByPage(view, forward) {
18054
- return extendSel(view, range => view.moveVertically(range, forward, pageHeight(view)));
18208
+ return extendSel(view, range => view.moveVertically(range, forward, pageInfo(view).height));
18055
18209
  }
18056
18210
  /**
18057
18211
  Move the selection head one page up.
@@ -19072,16 +19226,13 @@
19072
19226
  `-`, document percentages suffixed with `%`, and an optional
19073
19227
  column position by adding `:` and a second number after the line
19074
19228
  number.
19075
-
19076
- The dialog can be styled with the `panel.gotoLine` theme
19077
- selector.
19078
19229
  */
19079
19230
  const gotoLine = view => {
19080
19231
  let panel = getPanel(view, createLineDialog);
19081
19232
  if (!panel) {
19082
19233
  let effects = [dialogEffect.of(true)];
19083
19234
  if (view.state.field(dialogField, false) == null)
19084
- effects.push(StateEffect.appendConfig.of([dialogField, baseTheme$1$1]));
19235
+ effects.push(StateEffect.appendConfig.of([dialogField, baseTheme$1]));
19085
19236
  view.dispatch({ effects });
19086
19237
  panel = getPanel(view, createLineDialog);
19087
19238
  }
@@ -19089,7 +19240,7 @@
19089
19240
  panel.dom.querySelector("input").focus();
19090
19241
  return true;
19091
19242
  };
19092
- const baseTheme$1$1 = /*@__PURE__*/EditorView.baseTheme({
19243
+ const baseTheme$1 = /*@__PURE__*/EditorView.baseTheme({
19093
19244
  ".cm-panel.cm-gotoLine": {
19094
19245
  padding: "2px 6px 4px",
19095
19246
  "& label": { fontSize: "80%" }
@@ -19261,7 +19412,8 @@
19261
19412
  caseSensitive: false,
19262
19413
  literal: false,
19263
19414
  wholeWord: false,
19264
- createPanel: view => new SearchPanel(view)
19415
+ createPanel: view => new SearchPanel(view),
19416
+ scrollToMatch: range => EditorView.scrollIntoView(range)
19265
19417
  });
19266
19418
  }
19267
19419
  });
@@ -19450,7 +19602,7 @@
19450
19602
  once).
19451
19603
  */
19452
19604
  const setSearchQuery = /*@__PURE__*/StateEffect.define();
19453
- const togglePanel$1 = /*@__PURE__*/StateEffect.define();
19605
+ const togglePanel = /*@__PURE__*/StateEffect.define();
19454
19606
  const searchState = /*@__PURE__*/StateField.define({
19455
19607
  create(state) {
19456
19608
  return new SearchState(defaultQuery(state).create(), null);
@@ -19459,7 +19611,7 @@
19459
19611
  for (let effect of tr.effects) {
19460
19612
  if (effect.is(setSearchQuery))
19461
19613
  value = new SearchState(effect.value.create(), value.panel);
19462
- else if (effect.is(togglePanel$1))
19614
+ else if (effect.is(togglePanel))
19463
19615
  value = new SearchState(value.query, effect.value ? createSearchPanel : null);
19464
19616
  }
19465
19617
  return value;
@@ -19519,10 +19671,11 @@
19519
19671
  let next = query.nextMatch(view.state, to, to);
19520
19672
  if (!next)
19521
19673
  return false;
19674
+ let selection = EditorSelection.single(next.from, next.to);
19675
+ let config = view.state.facet(searchConfigFacet);
19522
19676
  view.dispatch({
19523
- selection: { anchor: next.from, head: next.to },
19524
- scrollIntoView: true,
19525
- effects: announceMatch(view, next),
19677
+ selection,
19678
+ effects: [announceMatch(view, next), config.scrollToMatch(selection.main)],
19526
19679
  userEvent: "select.search"
19527
19680
  });
19528
19681
  return true;
@@ -19534,13 +19687,14 @@
19534
19687
  */
19535
19688
  const findPrevious = /*@__PURE__*/searchCommand((view, { query }) => {
19536
19689
  let { state } = view, { from } = state.selection.main;
19537
- let range = query.prevMatch(state, from, from);
19538
- if (!range)
19690
+ let prev = query.prevMatch(state, from, from);
19691
+ if (!prev)
19539
19692
  return false;
19693
+ let selection = EditorSelection.single(prev.from, prev.to);
19694
+ let config = view.state.facet(searchConfigFacet);
19540
19695
  view.dispatch({
19541
- selection: { anchor: range.from, head: range.to },
19542
- scrollIntoView: true,
19543
- effects: announceMatch(view, range),
19696
+ selection,
19697
+ effects: [announceMatch(view, prev), config.scrollToMatch(selection.main)],
19544
19698
  userEvent: "select.search"
19545
19699
  });
19546
19700
  return true;
@@ -19591,22 +19745,21 @@
19591
19745
  if (!next)
19592
19746
  return false;
19593
19747
  let changes = [], selection, replacement;
19594
- let announce = [];
19748
+ let effects = [];
19595
19749
  if (next.from == from && next.to == to) {
19596
19750
  replacement = state.toText(query.getReplacement(next));
19597
19751
  changes.push({ from: next.from, to: next.to, insert: replacement });
19598
19752
  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) + "."));
19753
+ effects.push(EditorView.announce.of(state.phrase("replaced match on line $", state.doc.lineAt(from).number) + "."));
19600
19754
  }
19601
19755
  if (next) {
19602
19756
  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));
19757
+ selection = EditorSelection.single(next.from - off, next.to - off);
19758
+ effects.push(announceMatch(view, next));
19759
+ effects.push(state.facet(searchConfigFacet).scrollToMatch(selection.main));
19605
19760
  }
19606
19761
  view.dispatch({
19607
- changes, selection,
19608
- scrollIntoView: !!selection,
19609
- effects: announce,
19762
+ changes, selection, effects,
19610
19763
  userEvent: "input.replace"
19611
19764
  });
19612
19765
  return true;
@@ -19669,7 +19822,7 @@
19669
19822
  }
19670
19823
  else {
19671
19824
  view.dispatch({ effects: [
19672
- togglePanel$1.of(true),
19825
+ togglePanel.of(true),
19673
19826
  state ? setSearchQuery.of(defaultQuery(view.state, state.query.spec)) : StateEffect.appendConfig.of(searchExtensions)
19674
19827
  ] });
19675
19828
  }
@@ -19685,7 +19838,7 @@
19685
19838
  let panel = getPanel(view, createSearchPanel);
19686
19839
  if (panel && panel.dom.contains(view.root.activeElement))
19687
19840
  view.focus();
19688
- view.dispatch({ effects: togglePanel$1.of(false) });
19841
+ view.dispatch({ effects: togglePanel.of(false) });
19689
19842
  return true;
19690
19843
  };
19691
19844
  /**
@@ -19990,9 +20143,12 @@
19990
20143
  */
19991
20144
  function ifNotIn(nodes, source) {
19992
20145
  return (context) => {
19993
- for (let pos = syntaxTree(context.state).resolveInner(context.pos, -1); pos; pos = pos.parent)
20146
+ for (let pos = syntaxTree(context.state).resolveInner(context.pos, -1); pos; pos = pos.parent) {
19994
20147
  if (nodes.indexOf(pos.name) > -1)
19995
20148
  return null;
20149
+ if (pos.type.isTop)
20150
+ break;
20151
+ }
19996
20152
  return source(context);
19997
20153
  };
19998
20154
  }
@@ -20097,13 +20253,18 @@
20097
20253
  // For single-character queries, only match when they occur right
20098
20254
  // at the start
20099
20255
  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;
20256
+ let first = codePointAt(word, 0), firstSize = codePointSize(first);
20257
+ let score = firstSize == word.length ? 0 : -100 /* Penalty.NotFull */;
20258
+ if (first == chars[0]) ;
20259
+ else if (first == folded[0])
20260
+ score += -200 /* Penalty.CaseFold */;
20261
+ else
20262
+ return null;
20263
+ return [score, 0, firstSize];
20103
20264
  }
20104
20265
  let direct = word.indexOf(this.pattern);
20105
20266
  if (direct == 0)
20106
- return [0, 0, this.pattern.length];
20267
+ return [word.length == this.pattern.length ? 0 : -100 /* Penalty.NotFull */, 0, this.pattern.length];
20107
20268
  let len = chars.length, anyTo = 0;
20108
20269
  if (direct < 0) {
20109
20270
  for (let i = 0, e = Math.min(word.length, 200); i < e && anyTo < len;) {
@@ -20159,7 +20320,7 @@
20159
20320
  if (byWordTo == len && byWord[0] == 0 && wordAdjacent)
20160
20321
  return this.result(-100 /* Penalty.ByWord */ + (byWordFolded ? -200 /* Penalty.CaseFold */ : 0), byWord, word);
20161
20322
  if (adjacentTo == len && adjacentStart == 0)
20162
- return [-200 /* Penalty.CaseFold */ - word.length, 0, adjacentEnd];
20323
+ return [-200 /* Penalty.CaseFold */ - word.length + (adjacentEnd == word.length ? 0 : -100 /* Penalty.NotFull */), 0, adjacentEnd];
20163
20324
  if (direct > -1)
20164
20325
  return [-700 /* Penalty.NotStart */ - word.length, direct, direct + this.pattern.length];
20165
20326
  if (adjacentTo == len)
@@ -20944,7 +21105,7 @@
20944
21105
  }
20945
21106
  });
20946
21107
 
20947
- const baseTheme$1 = /*@__PURE__*/EditorView.baseTheme({
21108
+ const baseTheme = /*@__PURE__*/EditorView.baseTheme({
20948
21109
  ".cm-tooltip.cm-tooltip-autocomplete": {
20949
21110
  "& > ul": {
20950
21111
  fontFamily: "monospace",
@@ -21320,7 +21481,7 @@
21320
21481
  completionConfig.of(config),
21321
21482
  completionPlugin,
21322
21483
  completionKeymapExt,
21323
- baseTheme$1
21484
+ baseTheme
21324
21485
  ];
21325
21486
  }
21326
21487
  /**
@@ -21345,560 +21506,6 @@
21345
21506
  ];
21346
21507
  const completionKeymapExt = /*@__PURE__*/Prec.highest(/*@__PURE__*/keymap.computeN([completionConfig], state => state.facet(completionConfig).defaultKeymap ? [completionKeymap] : []));
21347
21508
 
21348
- class SelectedDiagnostic {
21349
- constructor(from, to, diagnostic) {
21350
- this.from = from;
21351
- this.to = to;
21352
- this.diagnostic = diagnostic;
21353
- }
21354
- }
21355
- class LintState {
21356
- constructor(diagnostics, panel, selected) {
21357
- this.diagnostics = diagnostics;
21358
- this.panel = panel;
21359
- this.selected = selected;
21360
- }
21361
- static init(diagnostics, panel, state) {
21362
- // Filter the list of diagnostics for which to create markers
21363
- let markedDiagnostics = diagnostics;
21364
- let diagnosticFilter = state.facet(lintConfig).markerFilter;
21365
- if (diagnosticFilter)
21366
- markedDiagnostics = diagnosticFilter(markedDiagnostics);
21367
- let ranges = Decoration.set(markedDiagnostics.map((d) => {
21368
- // For zero-length ranges or ranges covering only a line break, create a widget
21369
- return d.from == d.to || (d.from == d.to - 1 && state.doc.lineAt(d.from).to == d.from)
21370
- ? Decoration.widget({
21371
- widget: new DiagnosticWidget(d),
21372
- diagnostic: d
21373
- }).range(d.from)
21374
- : Decoration.mark({
21375
- attributes: { class: "cm-lintRange cm-lintRange-" + d.severity },
21376
- diagnostic: d
21377
- }).range(d.from, d.to);
21378
- }), true);
21379
- return new LintState(ranges, panel, findDiagnostic(ranges));
21380
- }
21381
- }
21382
- function findDiagnostic(diagnostics, diagnostic = null, after = 0) {
21383
- let found = null;
21384
- diagnostics.between(after, 1e9, (from, to, { spec }) => {
21385
- if (diagnostic && spec.diagnostic != diagnostic)
21386
- return;
21387
- found = new SelectedDiagnostic(from, to, spec.diagnostic);
21388
- return false;
21389
- });
21390
- return found;
21391
- }
21392
- function hideTooltip(tr, tooltip) {
21393
- return !!(tr.effects.some(e => e.is(setDiagnosticsEffect)) || tr.changes.touchesRange(tooltip.pos));
21394
- }
21395
- function maybeEnableLint(state, effects) {
21396
- return state.field(lintState, false) ? effects : effects.concat(StateEffect.appendConfig.of([
21397
- lintState,
21398
- EditorView.decorations.compute([lintState], state => {
21399
- let { selected, panel } = state.field(lintState);
21400
- return !selected || !panel || selected.from == selected.to ? Decoration.none : Decoration.set([
21401
- activeMark.range(selected.from, selected.to)
21402
- ]);
21403
- }),
21404
- hoverTooltip(lintTooltip, { hideOn: hideTooltip }),
21405
- baseTheme
21406
- ]));
21407
- }
21408
- /**
21409
- Returns a transaction spec which updates the current set of
21410
- diagnostics, and enables the lint extension if if wasn't already
21411
- active.
21412
- */
21413
- function setDiagnostics(state, diagnostics) {
21414
- return {
21415
- effects: maybeEnableLint(state, [setDiagnosticsEffect.of(diagnostics)])
21416
- };
21417
- }
21418
- /**
21419
- The state effect that updates the set of active diagnostics. Can
21420
- be useful when writing an extension that needs to track these.
21421
- */
21422
- const setDiagnosticsEffect = /*@__PURE__*/StateEffect.define();
21423
- const togglePanel = /*@__PURE__*/StateEffect.define();
21424
- const movePanelSelection = /*@__PURE__*/StateEffect.define();
21425
- const lintState = /*@__PURE__*/StateField.define({
21426
- create() {
21427
- return new LintState(Decoration.none, null, null);
21428
- },
21429
- update(value, tr) {
21430
- if (tr.docChanged) {
21431
- let mapped = value.diagnostics.map(tr.changes), selected = null;
21432
- if (value.selected) {
21433
- let selPos = tr.changes.mapPos(value.selected.from, 1);
21434
- selected = findDiagnostic(mapped, value.selected.diagnostic, selPos) || findDiagnostic(mapped, null, selPos);
21435
- }
21436
- value = new LintState(mapped, value.panel, selected);
21437
- }
21438
- for (let effect of tr.effects) {
21439
- if (effect.is(setDiagnosticsEffect)) {
21440
- value = LintState.init(effect.value, value.panel, tr.state);
21441
- }
21442
- else if (effect.is(togglePanel)) {
21443
- value = new LintState(value.diagnostics, effect.value ? LintPanel.open : null, value.selected);
21444
- }
21445
- else if (effect.is(movePanelSelection)) {
21446
- value = new LintState(value.diagnostics, value.panel, effect.value);
21447
- }
21448
- }
21449
- return value;
21450
- },
21451
- provide: f => [showPanel.from(f, val => val.panel),
21452
- EditorView.decorations.from(f, s => s.diagnostics)]
21453
- });
21454
- const activeMark = /*@__PURE__*/Decoration.mark({ class: "cm-lintRange cm-lintRange-active" });
21455
- function lintTooltip(view, pos, side) {
21456
- let { diagnostics } = view.state.field(lintState);
21457
- let found = [], stackStart = 2e8, stackEnd = 0;
21458
- diagnostics.between(pos - (side < 0 ? 1 : 0), pos + (side > 0 ? 1 : 0), (from, to, { spec }) => {
21459
- if (pos >= from && pos <= to &&
21460
- (from == to || ((pos > from || side > 0) && (pos < to || side < 0)))) {
21461
- found.push(spec.diagnostic);
21462
- stackStart = Math.min(from, stackStart);
21463
- stackEnd = Math.max(to, stackEnd);
21464
- }
21465
- });
21466
- let diagnosticFilter = view.state.facet(lintConfig).tooltipFilter;
21467
- if (diagnosticFilter)
21468
- found = diagnosticFilter(found);
21469
- if (!found.length)
21470
- return null;
21471
- return {
21472
- pos: stackStart,
21473
- end: stackEnd,
21474
- above: view.state.doc.lineAt(stackStart).to < stackEnd,
21475
- create() {
21476
- return { dom: diagnosticsTooltip(view, found) };
21477
- }
21478
- };
21479
- }
21480
- function diagnosticsTooltip(view, diagnostics) {
21481
- return crelt("ul", { class: "cm-tooltip-lint" }, diagnostics.map(d => renderDiagnostic(view, d, false)));
21482
- }
21483
- /**
21484
- Command to open and focus the lint panel.
21485
- */
21486
- const openLintPanel = (view) => {
21487
- let field = view.state.field(lintState, false);
21488
- if (!field || !field.panel)
21489
- view.dispatch({ effects: maybeEnableLint(view.state, [togglePanel.of(true)]) });
21490
- let panel = getPanel(view, LintPanel.open);
21491
- if (panel)
21492
- panel.dom.querySelector(".cm-panel-lint ul").focus();
21493
- return true;
21494
- };
21495
- /**
21496
- Command to close the lint panel, when open.
21497
- */
21498
- const closeLintPanel = (view) => {
21499
- let field = view.state.field(lintState, false);
21500
- if (!field || !field.panel)
21501
- return false;
21502
- view.dispatch({ effects: togglePanel.of(false) });
21503
- return true;
21504
- };
21505
- /**
21506
- Move the selection to the next diagnostic.
21507
- */
21508
- const nextDiagnostic = (view) => {
21509
- let field = view.state.field(lintState, false);
21510
- if (!field)
21511
- return false;
21512
- let sel = view.state.selection.main, next = field.diagnostics.iter(sel.to + 1);
21513
- if (!next.value) {
21514
- next = field.diagnostics.iter(0);
21515
- if (!next.value || next.from == sel.from && next.to == sel.to)
21516
- return false;
21517
- }
21518
- view.dispatch({ selection: { anchor: next.from, head: next.to }, scrollIntoView: true });
21519
- return true;
21520
- };
21521
- /**
21522
- A set of default key bindings for the lint functionality.
21523
-
21524
- - Ctrl-Shift-m (Cmd-Shift-m on macOS): [`openLintPanel`](https://codemirror.net/6/docs/ref/#lint.openLintPanel)
21525
- - F8: [`nextDiagnostic`](https://codemirror.net/6/docs/ref/#lint.nextDiagnostic)
21526
- */
21527
- const lintKeymap = [
21528
- { key: "Mod-Shift-m", run: openLintPanel, preventDefault: true },
21529
- { key: "F8", run: nextDiagnostic }
21530
- ];
21531
- const lintPlugin = /*@__PURE__*/ViewPlugin.fromClass(class {
21532
- constructor(view) {
21533
- this.view = view;
21534
- this.timeout = -1;
21535
- this.set = true;
21536
- let { delay } = view.state.facet(lintConfig);
21537
- this.lintTime = Date.now() + delay;
21538
- this.run = this.run.bind(this);
21539
- this.timeout = setTimeout(this.run, delay);
21540
- }
21541
- run() {
21542
- let now = Date.now();
21543
- if (now < this.lintTime - 10) {
21544
- setTimeout(this.run, this.lintTime - now);
21545
- }
21546
- else {
21547
- this.set = false;
21548
- let { state } = this.view, { sources } = state.facet(lintConfig);
21549
- Promise.all(sources.map(source => Promise.resolve(source(this.view)))).then(annotations => {
21550
- let all = annotations.reduce((a, b) => a.concat(b));
21551
- if (this.view.state.doc == state.doc)
21552
- this.view.dispatch(setDiagnostics(this.view.state, all));
21553
- }, error => { logException(this.view.state, error); });
21554
- }
21555
- }
21556
- update(update) {
21557
- let config = update.state.facet(lintConfig);
21558
- if (update.docChanged || config != update.startState.facet(lintConfig)) {
21559
- this.lintTime = Date.now() + config.delay;
21560
- if (!this.set) {
21561
- this.set = true;
21562
- this.timeout = setTimeout(this.run, config.delay);
21563
- }
21564
- }
21565
- }
21566
- force() {
21567
- if (this.set) {
21568
- this.lintTime = Date.now();
21569
- this.run();
21570
- }
21571
- }
21572
- destroy() {
21573
- clearTimeout(this.timeout);
21574
- }
21575
- });
21576
- const lintConfig = /*@__PURE__*/Facet.define({
21577
- combine(input) {
21578
- return Object.assign({ sources: input.map(i => i.source) }, combineConfig(input.map(i => i.config), {
21579
- delay: 750,
21580
- markerFilter: null,
21581
- tooltipFilter: null
21582
- }));
21583
- },
21584
- enables: lintPlugin
21585
- });
21586
- function assignKeys(actions) {
21587
- let assigned = [];
21588
- if (actions)
21589
- actions: for (let { name } of actions) {
21590
- for (let i = 0; i < name.length; i++) {
21591
- let ch = name[i];
21592
- if (/[a-zA-Z]/.test(ch) && !assigned.some(c => c.toLowerCase() == ch.toLowerCase())) {
21593
- assigned.push(ch);
21594
- continue actions;
21595
- }
21596
- }
21597
- assigned.push("");
21598
- }
21599
- return assigned;
21600
- }
21601
- function renderDiagnostic(view, diagnostic, inPanel) {
21602
- var _a;
21603
- let keys = inPanel ? assignKeys(diagnostic.actions) : [];
21604
- 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) => {
21606
- e.preventDefault();
21607
- let found = findDiagnostic(view.state.field(lintState).diagnostics, diagnostic);
21608
- if (found)
21609
- action.apply(view, found.from, found.to);
21610
- };
21611
- let { name } = action, keyIndex = keys[i] ? name.indexOf(keys[i]) : -1;
21612
- let nameElt = keyIndex < 0 ? name : [name.slice(0, keyIndex),
21613
- crelt("u", name.slice(keyIndex, keyIndex + 1)),
21614
- name.slice(keyIndex + 1)];
21615
- return crelt("button", {
21616
- type: "button",
21617
- class: "cm-diagnosticAction",
21618
- onclick: click,
21619
- onmousedown: click,
21620
- "aria-label": ` Action: ${name}${keyIndex < 0 ? "" : ` (access key "${keys[i]})"`}.`
21621
- }, nameElt);
21622
- }), diagnostic.source && crelt("div", { class: "cm-diagnosticSource" }, diagnostic.source));
21623
- }
21624
- class DiagnosticWidget extends WidgetType {
21625
- constructor(diagnostic) {
21626
- super();
21627
- this.diagnostic = diagnostic;
21628
- }
21629
- eq(other) { return other.diagnostic == this.diagnostic; }
21630
- toDOM() {
21631
- return crelt("span", { class: "cm-lintPoint cm-lintPoint-" + this.diagnostic.severity });
21632
- }
21633
- }
21634
- class PanelItem {
21635
- constructor(view, diagnostic) {
21636
- this.diagnostic = diagnostic;
21637
- this.id = "item_" + Math.floor(Math.random() * 0xffffffff).toString(16);
21638
- this.dom = renderDiagnostic(view, diagnostic, true);
21639
- this.dom.id = this.id;
21640
- this.dom.setAttribute("role", "option");
21641
- }
21642
- }
21643
- class LintPanel {
21644
- constructor(view) {
21645
- this.view = view;
21646
- this.items = [];
21647
- let onkeydown = (event) => {
21648
- if (event.keyCode == 27) { // Escape
21649
- closeLintPanel(this.view);
21650
- this.view.focus();
21651
- }
21652
- else if (event.keyCode == 38 || event.keyCode == 33) { // ArrowUp, PageUp
21653
- this.moveSelection((this.selectedIndex - 1 + this.items.length) % this.items.length);
21654
- }
21655
- else if (event.keyCode == 40 || event.keyCode == 34) { // ArrowDown, PageDown
21656
- this.moveSelection((this.selectedIndex + 1) % this.items.length);
21657
- }
21658
- else if (event.keyCode == 36) { // Home
21659
- this.moveSelection(0);
21660
- }
21661
- else if (event.keyCode == 35) { // End
21662
- this.moveSelection(this.items.length - 1);
21663
- }
21664
- else if (event.keyCode == 13) { // Enter
21665
- this.view.focus();
21666
- }
21667
- else if (event.keyCode >= 65 && event.keyCode <= 90 && this.selectedIndex >= 0) { // A-Z
21668
- let { diagnostic } = this.items[this.selectedIndex], keys = assignKeys(diagnostic.actions);
21669
- for (let i = 0; i < keys.length; i++)
21670
- if (keys[i].toUpperCase().charCodeAt(0) == event.keyCode) {
21671
- let found = findDiagnostic(this.view.state.field(lintState).diagnostics, diagnostic);
21672
- if (found)
21673
- diagnostic.actions[i].apply(view, found.from, found.to);
21674
- }
21675
- }
21676
- else {
21677
- return;
21678
- }
21679
- event.preventDefault();
21680
- };
21681
- let onclick = (event) => {
21682
- for (let i = 0; i < this.items.length; i++) {
21683
- if (this.items[i].dom.contains(event.target))
21684
- this.moveSelection(i);
21685
- }
21686
- };
21687
- this.list = crelt("ul", {
21688
- tabIndex: 0,
21689
- role: "listbox",
21690
- "aria-label": this.view.state.phrase("Diagnostics"),
21691
- onkeydown,
21692
- onclick
21693
- });
21694
- this.dom = crelt("div", { class: "cm-panel-lint" }, this.list, crelt("button", {
21695
- type: "button",
21696
- name: "close",
21697
- "aria-label": this.view.state.phrase("close"),
21698
- onclick: () => closeLintPanel(this.view)
21699
- }, "×"));
21700
- this.update();
21701
- }
21702
- get selectedIndex() {
21703
- let selected = this.view.state.field(lintState).selected;
21704
- if (!selected)
21705
- return -1;
21706
- for (let i = 0; i < this.items.length; i++)
21707
- if (this.items[i].diagnostic == selected.diagnostic)
21708
- return i;
21709
- return -1;
21710
- }
21711
- update() {
21712
- let { diagnostics, selected } = this.view.state.field(lintState);
21713
- let i = 0, needsSync = false, newSelectedItem = null;
21714
- diagnostics.between(0, this.view.state.doc.length, (_start, _end, { spec }) => {
21715
- let found = -1, item;
21716
- for (let j = i; j < this.items.length; j++)
21717
- if (this.items[j].diagnostic == spec.diagnostic) {
21718
- found = j;
21719
- break;
21720
- }
21721
- if (found < 0) {
21722
- item = new PanelItem(this.view, spec.diagnostic);
21723
- this.items.splice(i, 0, item);
21724
- needsSync = true;
21725
- }
21726
- else {
21727
- item = this.items[found];
21728
- if (found > i) {
21729
- this.items.splice(i, found - i);
21730
- needsSync = true;
21731
- }
21732
- }
21733
- if (selected && item.diagnostic == selected.diagnostic) {
21734
- if (!item.dom.hasAttribute("aria-selected")) {
21735
- item.dom.setAttribute("aria-selected", "true");
21736
- newSelectedItem = item;
21737
- }
21738
- }
21739
- else if (item.dom.hasAttribute("aria-selected")) {
21740
- item.dom.removeAttribute("aria-selected");
21741
- }
21742
- i++;
21743
- });
21744
- while (i < this.items.length && !(this.items.length == 1 && this.items[0].diagnostic.from < 0)) {
21745
- needsSync = true;
21746
- this.items.pop();
21747
- }
21748
- if (this.items.length == 0) {
21749
- this.items.push(new PanelItem(this.view, {
21750
- from: -1, to: -1,
21751
- severity: "info",
21752
- message: this.view.state.phrase("No diagnostics")
21753
- }));
21754
- needsSync = true;
21755
- }
21756
- if (newSelectedItem) {
21757
- this.list.setAttribute("aria-activedescendant", newSelectedItem.id);
21758
- this.view.requestMeasure({
21759
- key: this,
21760
- read: () => ({ sel: newSelectedItem.dom.getBoundingClientRect(), panel: this.list.getBoundingClientRect() }),
21761
- write: ({ sel, panel }) => {
21762
- if (sel.top < panel.top)
21763
- this.list.scrollTop -= panel.top - sel.top;
21764
- else if (sel.bottom > panel.bottom)
21765
- this.list.scrollTop += sel.bottom - panel.bottom;
21766
- }
21767
- });
21768
- }
21769
- else if (this.selectedIndex < 0) {
21770
- this.list.removeAttribute("aria-activedescendant");
21771
- }
21772
- if (needsSync)
21773
- this.sync();
21774
- }
21775
- sync() {
21776
- let domPos = this.list.firstChild;
21777
- function rm() {
21778
- let prev = domPos;
21779
- domPos = prev.nextSibling;
21780
- prev.remove();
21781
- }
21782
- for (let item of this.items) {
21783
- if (item.dom.parentNode == this.list) {
21784
- while (domPos != item.dom)
21785
- rm();
21786
- domPos = item.dom.nextSibling;
21787
- }
21788
- else {
21789
- this.list.insertBefore(item.dom, domPos);
21790
- }
21791
- }
21792
- while (domPos)
21793
- rm();
21794
- }
21795
- moveSelection(selectedIndex) {
21796
- if (this.selectedIndex < 0)
21797
- return;
21798
- let field = this.view.state.field(lintState);
21799
- let selection = findDiagnostic(field.diagnostics, this.items[selectedIndex].diagnostic);
21800
- if (!selection)
21801
- return;
21802
- this.view.dispatch({
21803
- selection: { anchor: selection.from, head: selection.to },
21804
- scrollIntoView: true,
21805
- effects: movePanelSelection.of(selection)
21806
- });
21807
- }
21808
- static open(view) { return new LintPanel(view); }
21809
- }
21810
- function svg(content, attrs = `viewBox="0 0 40 40"`) {
21811
- return `url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" ${attrs}>${encodeURIComponent(content)}</svg>')`;
21812
- }
21813
- function underline(color) {
21814
- return svg(`<path d="m0 2.5 l2 -1.5 l1 0 l2 1.5 l1 0" stroke="${color}" fill="none" stroke-width=".7"/>`, `width="6" height="3"`);
21815
- }
21816
- const baseTheme = /*@__PURE__*/EditorView.baseTheme({
21817
- ".cm-diagnostic": {
21818
- padding: "3px 6px 3px 8px",
21819
- marginLeft: "-1px",
21820
- display: "block",
21821
- whiteSpace: "pre-wrap"
21822
- },
21823
- ".cm-diagnostic-error": { borderLeft: "5px solid #d11" },
21824
- ".cm-diagnostic-warning": { borderLeft: "5px solid orange" },
21825
- ".cm-diagnostic-info": { borderLeft: "5px solid #999" },
21826
- ".cm-diagnosticAction": {
21827
- font: "inherit",
21828
- border: "none",
21829
- padding: "2px 4px",
21830
- backgroundColor: "#444",
21831
- color: "white",
21832
- borderRadius: "3px",
21833
- marginLeft: "8px"
21834
- },
21835
- ".cm-diagnosticSource": {
21836
- fontSize: "70%",
21837
- opacity: .7
21838
- },
21839
- ".cm-lintRange": {
21840
- backgroundPosition: "left bottom",
21841
- backgroundRepeat: "repeat-x",
21842
- paddingBottom: "0.7px",
21843
- },
21844
- ".cm-lintRange-error": { backgroundImage: /*@__PURE__*/underline("#d11") },
21845
- ".cm-lintRange-warning": { backgroundImage: /*@__PURE__*/underline("orange") },
21846
- ".cm-lintRange-info": { backgroundImage: /*@__PURE__*/underline("#999") },
21847
- ".cm-lintRange-active": { backgroundColor: "#ffdd9980" },
21848
- ".cm-tooltip-lint": {
21849
- padding: 0,
21850
- margin: 0
21851
- },
21852
- ".cm-lintPoint": {
21853
- position: "relative",
21854
- "&:after": {
21855
- content: '""',
21856
- position: "absolute",
21857
- bottom: 0,
21858
- left: "-2px",
21859
- borderLeft: "3px solid transparent",
21860
- borderRight: "3px solid transparent",
21861
- borderBottom: "4px solid #d11"
21862
- }
21863
- },
21864
- ".cm-lintPoint-warning": {
21865
- "&:after": { borderBottomColor: "orange" }
21866
- },
21867
- ".cm-lintPoint-info": {
21868
- "&:after": { borderBottomColor: "#999" }
21869
- },
21870
- ".cm-panel.cm-panel-lint": {
21871
- position: "relative",
21872
- "& ul": {
21873
- maxHeight: "100px",
21874
- overflowY: "auto",
21875
- "& [aria-selected]": {
21876
- backgroundColor: "#ddd",
21877
- "& u": { textDecoration: "underline" }
21878
- },
21879
- "&:focus [aria-selected]": {
21880
- background_fallback: "#bdf",
21881
- backgroundColor: "Highlight",
21882
- color_fallback: "white",
21883
- color: "HighlightText"
21884
- },
21885
- "& u": { textDecoration: "none" },
21886
- padding: 0,
21887
- margin: 0
21888
- },
21889
- "& [name=close]": {
21890
- position: "absolute",
21891
- top: "0",
21892
- right: "2px",
21893
- background: "inherit",
21894
- border: "none",
21895
- font: "inherit",
21896
- padding: 0,
21897
- margin: 0
21898
- }
21899
- }
21900
- });
21901
-
21902
21509
  function base64Encode (str) {
21903
21510
  // https://stackoverflow.com/questions/30106476/using-javascripts-atob-to-decode-base64-doesnt-properly-decode-utf-8-strings
21904
21511
  return btoa(encodeURIComponent(str).replace(/%([0-9A-F]{2})/g,
@@ -24275,8 +23882,7 @@
24275
23882
  ...searchKeymap,
24276
23883
  ...historyKeymap,
24277
23884
  ...foldKeymap,
24278
- ...completionKeymap,
24279
- ...lintKeymap
23885
+ ...completionKeymap
24280
23886
  ]);
24281
23887
  const sqlConfig = {
24282
23888
  dialect: MySQL,
@@ -24535,6 +24141,7 @@
24535
24141
  this.headerRenderer = headerRenderer;
24536
24142
  this.cellRenderer = cellRenderer;
24537
24143
 
24144
+ this.classList.add('resize-table');
24538
24145
  this.style.tableLayout = 'auto';
24539
24146
  this.style.width = '100%';
24540
24147
 
@@ -24806,12 +24413,19 @@
24806
24413
  closeElement.focus();
24807
24414
  }
24808
24415
 
24416
+ function closePopup () {
24417
+ const wrapperElement = document.getElementById('popup-wrapper');
24418
+ if (wrapperElement) {
24419
+ document.body.removeChild(wrapperElement);
24420
+ return true
24421
+ }
24422
+ return false
24423
+ }
24424
+
24809
24425
  document.addEventListener('keydown', (event) => {
24810
24426
  if (event.code === 'Escape') {
24811
- const wrapperElement = document.getElementById('popup-wrapper');
24812
- if (wrapperElement) {
24427
+ if (closePopup()) {
24813
24428
  event.preventDefault();
24814
- document.body.removeChild(wrapperElement);
24815
24429
  }
24816
24430
  } else if (event.code === 'Tab') {
24817
24431
  const wrapperElement = document.getElementById('popup-wrapper');
@@ -24870,9 +24484,10 @@
24870
24484
 
24871
24485
  function init (parent, onSubmit, onShiftSubmit) {
24872
24486
  addEventListener('#query-tab-button', 'click', (event) => selectTab(event, 'query'));
24487
+ addEventListener('#graph-tab-button', 'click', (event) => selectTab(event, 'graph'));
24873
24488
  addEventListener('#saved-tab-button', 'click', (event) => selectTab(event, 'saved'));
24874
24489
  addEventListener('#structure-tab-button', 'click', (event) => selectTab(event, 'structure'));
24875
- addEventListener('#graph-tab-button', 'click', (event) => selectTab(event, 'graph'));
24490
+ addEventListener('#help-tab-button', 'click', (event) => selectTab(event, 'help'));
24876
24491
  addEventListener('#cancel-button', 'click', () => clearResult());
24877
24492
 
24878
24493
  addEventListener('#query-box', 'click', () => {
@@ -25023,14 +24638,24 @@
25023
24638
 
25024
24639
  function focus (selection = null) {
25025
24640
  window.editorView.focus();
25026
- if (selection) setSelection(selection);
24641
+ if (selection) {
24642
+ setSelection(selection);
24643
+ }
25027
24644
  }
25028
24645
 
25029
- function getValue () {
24646
+ function getEditorValue () {
25030
24647
  return window.editorView.state.doc.toString()
25031
24648
  }
25032
24649
 
25033
- function setValue (value) {
24650
+ function isLastEditorValueSet (value) {
24651
+ return window.lastEditorValueSet === value
24652
+ }
24653
+
24654
+ function setEditorValue (value) {
24655
+ window.lastEditorValueSet = value;
24656
+ if (getEditorValue() === value) {
24657
+ return
24658
+ }
25034
24659
  window.editorView.dispatch({
25035
24660
  changes: {
25036
24661
  from: 0,
@@ -25046,7 +24671,7 @@
25046
24671
 
25047
24672
  function getTabFromUrl (url) {
25048
24673
  const match = url.pathname.match(/\/([^/]+)$/);
25049
- if (match && ['query', 'graph', 'structure', 'saved'].includes(match[1])) {
24674
+ if (match && ['query', 'graph', 'saved', 'structure', 'help'].includes(match[1])) {
25050
24675
  return match[1]
25051
24676
  } else {
25052
24677
  throw new Error(`invalid tab: ${url.pathname}`)
@@ -25055,14 +24680,16 @@
25055
24680
 
25056
24681
  function updateTabs () {
25057
24682
  const url = new URL(window.location);
24683
+ setActionInUrl(url, 'query');
24684
+ document.getElementById('query-tab-button').href = url.pathname + url.search;
25058
24685
  setActionInUrl(url, 'graph');
25059
24686
  document.getElementById('graph-tab-button').href = url.pathname + url.search;
25060
24687
  setActionInUrl(url, 'saved');
25061
24688
  document.getElementById('saved-tab-button').href = url.pathname + url.search;
25062
24689
  setActionInUrl(url, 'structure');
25063
24690
  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;
24691
+ setActionInUrl(url, 'help');
24692
+ document.getElementById('help-tab-button').href = url.pathname + url.search;
25066
24693
  }
25067
24694
 
25068
24695
  function selectTab (event, tab) {
@@ -25072,6 +24699,8 @@
25072
24699
  }
25073
24700
 
25074
24701
  function route (target = null, event = null, url = null, internal = false) {
24702
+ closePopup();
24703
+
25075
24704
  if (url) {
25076
24705
  if (event) {
25077
24706
  event.preventDefault();
@@ -25111,7 +24740,7 @@
25111
24740
 
25112
24741
  switch (window.tab) {
25113
24742
  case 'query':
25114
- selectResultTab(internal);
24743
+ selectQueryTab(internal);
25115
24744
  break
25116
24745
  case 'graph':
25117
24746
  selectGraphTab(internal);
@@ -25122,6 +24751,9 @@
25122
24751
  case 'structure':
25123
24752
  selectStructureTab();
25124
24753
  break
24754
+ case 'help':
24755
+ selectHelpTab();
24756
+ break
25125
24757
  default:
25126
24758
  throw new Error(`Unexpected tab: ${window.tab}`)
25127
24759
  }
@@ -25149,42 +24781,53 @@
25149
24781
  selected.style.display = 'flex';
25150
24782
  });
25151
24783
 
24784
+ const schemaNames = Object.keys(window.metadata.schemas);
24785
+ const schemasElement = document.getElementById('schemas');
24786
+ const tablesElement = document.getElementById('tables');
24787
+ if (schemaNames.length === 1) {
24788
+ setTimeout(() => { tablesElement.focus(); }, 0);
24789
+ } else {
24790
+ setTimeout(() => { schemasElement.focus(); }, 0);
24791
+ }
24792
+
25152
24793
  if (window.structureLoaded) {
25153
24794
  return
25154
24795
  }
25155
24796
 
25156
- const schemasElement = document.getElementById('schemas');
25157
- const tablesElement = document.getElementById('tables');
25158
24797
  const statsElement = document.getElementById('stats');
25159
24798
  statsElement.innerHTML = statsHtml(null);
25160
24799
 
25161
24800
  const columnsElement = document.getElementById('columns');
25162
24801
  const indexesElement = document.getElementById('indexes');
25163
24802
 
25164
- const schemaNames = Object.keys(window.metadata.schemas);
25165
24803
  if (schemaNames.length === 1) {
25166
24804
  schemasElement.style.display = 'none';
25167
24805
  // TODO: duplicate code
25168
- while (tablesElement.firstChild) {
25169
- tablesElement.removeChild(tablesElement.firstChild);
25170
- }
25171
24806
  const schemaName = schemaNames[0];
25172
24807
  const schema = window.metadata.schemas[schemaName];
25173
24808
  const tableNames = Object.keys(schema.tables);
24809
+
25174
24810
  tableNames.forEach(function (tableName) {
25175
24811
  const optionElement = document.createElement('option');
25176
24812
  optionElement.value = tableName;
25177
24813
  optionElement.innerText = tableName;
25178
24814
  tablesElement.appendChild(optionElement);
25179
24815
  });
24816
+ if (tableNames.length > 0) {
24817
+ tablesElement.value = tableNames[0];
24818
+ }
25180
24819
  } else {
25181
24820
  schemasElement.style.display = 'flex';
24821
+
25182
24822
  schemaNames.forEach(function (schemaName) {
25183
24823
  const optionElement = document.createElement('option');
25184
24824
  optionElement.value = schemaName;
25185
24825
  optionElement.innerText = schemaName;
25186
24826
  schemasElement.appendChild(optionElement);
25187
24827
  });
24828
+ if (schemaNames.length > 0) {
24829
+ schemasElement.value = schemaNames[0];
24830
+ }
25188
24831
  schemasElement.addEventListener('change', function () {
25189
24832
  while (statsElement.firstChild) {
25190
24833
  statsElement.removeChild(statsElement.firstChild);
@@ -25202,12 +24845,16 @@
25202
24845
  const schemaName = schemasElement.value;
25203
24846
  const schema = window.metadata.schemas[schemaName];
25204
24847
  const tableNames = Object.keys(schema.tables);
24848
+
25205
24849
  tableNames.forEach(function (tableName) {
25206
24850
  const optionElement = document.createElement('option');
25207
24851
  optionElement.value = tableName;
25208
24852
  optionElement.innerText = tableName;
25209
24853
  tablesElement.appendChild(optionElement);
25210
24854
  });
24855
+ if (tableNames.length > 0) {
24856
+ tablesElement.value = tableNames[0];
24857
+ }
25211
24858
  });
25212
24859
  }
25213
24860
  tablesElement.addEventListener('change', function () {
@@ -25269,6 +24916,20 @@
25269
24916
  }
25270
24917
  });
25271
24918
  window.structureLoaded = true;
24919
+
24920
+ if (schemaNames.length === 1) {
24921
+ setTimeout(() => { tablesElement.focus(); }, 0);
24922
+ } else {
24923
+ setTimeout(() => { schemasElement.focus(); }, 0);
24924
+ }
24925
+
24926
+ tablesElement.dispatchEvent(new Event('change'));
24927
+ }
24928
+
24929
+ function selectHelpTab () {
24930
+ const helpBoxElement = document.getElementById('help-box');
24931
+ helpBoxElement.style.display = 'block';
24932
+ setTimeout(() => { helpBoxElement.focus(); }, 0);
25272
24933
  }
25273
24934
 
25274
24935
  function selectGraphTab (internal) {
@@ -25278,12 +24939,11 @@
25278
24939
  document.getElementById('fetch-sql-box').style.display = 'none';
25279
24940
  document.getElementById('cancel-button').style.visibility = 'hidden';
25280
24941
  updateDownloadButtons(window?.sqlFetch);
25281
- maybeFetchResult(internal);
25282
-
25283
24942
  focus(getSelection());
24943
+ maybeFetchResult(internal);
25284
24944
  }
25285
24945
 
25286
- function selectResultTab (internal) {
24946
+ function selectQueryTab (internal) {
25287
24947
  document.getElementById('query-box').style.display = 'flex';
25288
24948
  document.getElementById('submit-box').style.display = 'flex';
25289
24949
  document.getElementById('result-box').style.display = 'flex';
@@ -25299,6 +24959,8 @@
25299
24959
  });
25300
24960
 
25301
24961
  const savedElement = document.getElementById('saved-box');
24962
+ setTimeout(() => { savedElement.focus(); }, 0);
24963
+
25302
24964
  const saved = window.metadata.saved;
25303
24965
  const numFiles = Object.keys(saved).length;
25304
24966
  setStatus(`${numFiles} file${numFiles === 1 ? '' : 's'}`);
@@ -25332,7 +24994,6 @@
25332
24994
  runLinkElement.href = runUrl.pathname + runUrl.search;
25333
24995
  addEventListener(runLinkElement, 'click', (event) => {
25334
24996
  clearResult();
25335
- route(event.target, event, viewUrl, true);
25336
24997
  route(event.target, event, runUrl, true);
25337
24998
  });
25338
24999
 
@@ -25375,15 +25036,18 @@
25375
25036
  if (!target || !event) {
25376
25037
  throw new Error('you must specify target and event')
25377
25038
  }
25378
- clearResult();
25039
+
25040
+ window.lastSetSelectionValueFromUrlParam = null;
25041
+ window.lastEditorValueSet = null;
25042
+
25379
25043
  const url = new URL(window.location);
25380
- let sql = getValue().trim();
25044
+ let sql = getEditorValue().trim();
25381
25045
  sql = sql === '' ? null : sql;
25382
25046
 
25383
25047
  url.searchParams.set('run', 'true');
25384
25048
 
25385
25049
  if (url.searchParams.has('file')) {
25386
- if (window.metadata.saved[url.searchParams.get('file')].contents !== getValue()) {
25050
+ if (window.metadata.saved[url.searchParams.get('file')].contents !== getEditorValue()) {
25387
25051
  url.searchParams.delete('file');
25388
25052
  url.searchParams.set('sql', sql);
25389
25053
  }
@@ -25563,18 +25227,36 @@
25563
25227
  const hasSqluiReferrer = document.referrer && new URL(document.referrer).origin === url.origin;
25564
25228
  const variables = parseSqlVariables(params);
25565
25229
 
25230
+ if (params.has('file') && params.has('sql')) {
25231
+ // TODO: show an error.
25232
+ throw new Error('You can only specify a file or sql, not both.')
25233
+ }
25234
+
25566
25235
  // Only allow auto-run if coming from another SQLUI page. The idea here is to let the app link to URLs with run=true
25567
25236
  // but not other apps. This allows meta/shift-clicking to run a query.
25568
- let run = false;
25569
25237
  if (params.has('run')) {
25570
- run = (internal || hasSqluiReferrer) && ['1', 'true'].includes(params.get('run')?.toLowerCase());
25571
25238
  url.searchParams.delete('run');
25572
25239
  window.history.replaceState({}, '', url);
25573
- }
25240
+ clearResult();
25574
25241
 
25575
- if (params.has('file') && params.has('sql')) {
25576
- // TODO: show an error.
25577
- throw new Error('You can only specify a file or sql, not both.')
25242
+ if (!internal && !hasSqluiReferrer) {
25243
+ throw new Error('run only allowed for internal usage')
25244
+ }
25245
+
25246
+ if (params.has('sql') || params.has('file')) {
25247
+ const sqlFetch = buildSqlFetch(sql, file, variables, selection);
25248
+ setEditorValue(sqlFetch.sql);
25249
+ if (params.has('selection')) {
25250
+ window.lastSetSelectionValueFromUrlParam = selection;
25251
+ focus(selection);
25252
+ } else {
25253
+ window.lastSetSelectionValueFromUrlParam = null;
25254
+ }
25255
+ fetchSql(sqlFetch);
25256
+ return
25257
+ } else {
25258
+ throw new Error('run param specified without sql or file')
25259
+ }
25578
25260
  }
25579
25261
 
25580
25262
  const existingRequest = window.sqlFetch;
@@ -25586,7 +25268,7 @@
25586
25268
  const queryMatches = sqlMatches || fileMatches;
25587
25269
  if (selectionMatches && queryMatches && variablesMatch) {
25588
25270
  displaySqlFetch(existingRequest);
25589
- if (params.has('selection')) {
25271
+ if (params.has('selection') && window.lastSetSelectionValueFromUrlParam !== selection) {
25590
25272
  focus(selection);
25591
25273
  }
25592
25274
  return
@@ -25596,13 +25278,12 @@
25596
25278
  clearResult();
25597
25279
 
25598
25280
  const sqlFetch = buildSqlFetch(sql, file, variables, selection);
25599
- if (params.has('sql') || params.has('file')) {
25600
- setValue(sqlFetch.sql);
25601
- if (run) {
25602
- fetchSql(sqlFetch);
25603
- }
25281
+ if ((params.has('sql') || params.has('file')) && !isLastEditorValueSet(sqlFetch.sql)) {
25282
+ setEditorValue(sqlFetch.sql);
25604
25283
  }
25605
- if (params.has('selection')) {
25284
+
25285
+ if (params.has('selection') && window.lastSetSelectionValueFromUrlParam !== selection) {
25286
+ window.lastSetSelectionValueFromUrlParam = selection;
25606
25287
  focus(selection);
25607
25288
  }
25608
25289
  }
@@ -25784,7 +25465,7 @@
25784
25465
  const row = parseInt(node.dataset.row);
25785
25466
  const column = parseInt(node.dataset.column);
25786
25467
  const title = window.sqlFetch.result.columns[column].replaceAll('\n', '¶');
25787
- if (event.metaKey) {
25468
+ if (event.metaKey || event.ctrlKey) {
25788
25469
  createPopup(title, window.sqlFetch.result.rows[row][column]);
25789
25470
  } else if (event.altKey) {
25790
25471
  copyTextToClipboard(window.sqlFetch.result.rows[row][column]);
@@ -26009,8 +25690,38 @@
26009
25690
  });
26010
25691
 
26011
25692
  document.addEventListener('keydown', (event) => {
25693
+ if (event.code === 'ControlLeft' || event.code === 'ControlRight') {
25694
+ Array.prototype.forEach.call(document.getElementsByClassName('keyboard-shortcut-indicator'), function (selected) {
25695
+ selected.style.visibility = 'visible';
25696
+ });
25697
+ }
25698
+
26012
25699
  if (event.code === 'Escape') {
26013
25700
  focus();
25701
+ return
25702
+ }
25703
+
25704
+ const isMac = navigator.userAgent.includes('Mac');
25705
+ if (isMac && event.code === 'Digit0' && event.ctrlKey) {
25706
+ document.getElementById('header-link').click();
25707
+ } else if (isMac && event.code === 'Digit1' && event.ctrlKey) {
25708
+ selectTab(event, 'query');
25709
+ } else if (isMac && event.code === 'Digit2' && event.ctrlKey) {
25710
+ selectTab(event, 'graph');
25711
+ } else if (isMac && event.code === 'Digit3' && event.ctrlKey) {
25712
+ selectTab(event, 'saved');
25713
+ } else if (isMac && event.code === 'Digit4' && event.ctrlKey) {
25714
+ selectTab(event, 'structure');
25715
+ } else if (isMac && event.code === 'Digit5' && event.ctrlKey) {
25716
+ selectTab(event, 'help');
25717
+ }
25718
+ });
25719
+
25720
+ document.addEventListener('keyup', (event) => {
25721
+ if ((event.code === 'ControlLeft' || event.code === 'ControlRight') && !event.ctrlKey) {
25722
+ Array.prototype.forEach.call(document.getElementsByClassName('keyboard-shortcut-indicator'), function (selected) {
25723
+ selected.style.visibility = 'hidden';
25724
+ });
26014
25725
  }
26015
25726
  });
26016
25727