sqlui 0.1.66 → 0.1.68

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
  });
@@ -9536,6 +9622,9 @@
9536
9622
  padding: "0 2px 0 6px"
9537
9623
  },
9538
9624
  ".cm-layer": {
9625
+ position: "absolute",
9626
+ left: 0,
9627
+ top: 0,
9539
9628
  contain: "size style",
9540
9629
  "& > *": {
9541
9630
  position: "absolute"
@@ -9575,6 +9664,9 @@
9575
9664
  "&dark .cm-cursor": {
9576
9665
  borderLeftColor: "#444"
9577
9666
  },
9667
+ ".cm-dropCursor": {
9668
+ position: "absolute"
9669
+ },
9578
9670
  "&.cm-focused .cm-cursor": {
9579
9671
  display: "block"
9580
9672
  },
@@ -9786,7 +9878,7 @@
9786
9878
  };
9787
9879
  }
9788
9880
  else if ((browser.mac || browser.android) && change && change.from == change.to && change.from == sel.head - 1 &&
9789
- /^\. ?$/.test(change.insert.toString())) {
9881
+ /^\. ?$/.test(change.insert.toString()) && view.contentDOM.getAttribute("autocorrect") == "off") {
9790
9882
  // Detect insert-period-on-double-space Mac and Android behavior,
9791
9883
  // and transform it into a regular space insert.
9792
9884
  if (newSel && change.insert.length == 2)
@@ -10540,6 +10632,20 @@
10540
10632
  this.viewState.state = state;
10541
10633
  return;
10542
10634
  }
10635
+ let focus = this.hasFocus, focusFlag = 0, dispatchFocus = null;
10636
+ if (transactions.some(tr => tr.annotation(isFocusChange))) {
10637
+ this.inputState.notifiedFocused = focus;
10638
+ // If a focus-change transaction is being dispatched, set this update flag.
10639
+ focusFlag = 1 /* UpdateFlag.Focus */;
10640
+ }
10641
+ else if (focus != this.inputState.notifiedFocused) {
10642
+ this.inputState.notifiedFocused = focus;
10643
+ // Schedule a separate focus transaction if necessary, otherwise
10644
+ // add a flag to this update
10645
+ dispatchFocus = focusChangeTransaction(state, focus);
10646
+ if (!dispatchFocus)
10647
+ focusFlag = 1 /* UpdateFlag.Focus */;
10648
+ }
10543
10649
  // If there was a pending DOM change, eagerly read it and try to
10544
10650
  // apply it after the given transactions.
10545
10651
  let pendingKey = this.observer.delayedAndroidKey, domChange = null;
@@ -10558,6 +10664,7 @@
10558
10664
  if (state.facet(EditorState.phrases) != this.state.facet(EditorState.phrases))
10559
10665
  return this.setState(state);
10560
10666
  update = ViewUpdate.create(this, state, transactions);
10667
+ update.flags |= focusFlag;
10561
10668
  let scrollTarget = this.viewState.scrollTarget;
10562
10669
  try {
10563
10670
  this.updateState = 2 /* UpdateState.Updating */;
@@ -10595,10 +10702,15 @@
10595
10702
  if (!update.empty)
10596
10703
  for (let listener of this.state.facet(updateListener))
10597
10704
  listener(update);
10598
- if (domChange) {
10599
- if (!applyDOMChange(this, domChange) && pendingKey.force)
10600
- dispatchKey(this.contentDOM, pendingKey.key, pendingKey.keyCode);
10601
- }
10705
+ if (dispatchFocus || domChange)
10706
+ Promise.resolve().then(() => {
10707
+ if (dispatchFocus && this.state == dispatchFocus.startState)
10708
+ this.dispatch(dispatchFocus);
10709
+ if (domChange) {
10710
+ if (!applyDOMChange(this, domChange) && pendingKey.force)
10711
+ dispatchKey(this.contentDOM, pendingKey.key, pendingKey.keyCode);
10712
+ }
10713
+ });
10602
10714
  }
10603
10715
  /**
10604
10716
  Reset the view to the given state. (This will cause the entire
@@ -10673,7 +10785,7 @@
10673
10785
  if (this.destroyed)
10674
10786
  return;
10675
10787
  if (this.measureScheduled > -1)
10676
- cancelAnimationFrame(this.measureScheduled);
10788
+ this.win.cancelAnimationFrame(this.measureScheduled);
10677
10789
  this.measureScheduled = 0; // Prevent requestMeasure calls from scheduling another animation frame
10678
10790
  if (flush)
10679
10791
  this.observer.forceFlush();
@@ -11111,7 +11223,7 @@
11111
11223
  this.dom.remove();
11112
11224
  this.observer.destroy();
11113
11225
  if (this.measureScheduled > -1)
11114
- cancelAnimationFrame(this.measureScheduled);
11226
+ this.win.cancelAnimationFrame(this.measureScheduled);
11115
11227
  this.destroyed = true;
11116
11228
  }
11117
11229
  /**
@@ -11200,6 +11312,11 @@
11200
11312
  */
11201
11313
  EditorView.inputHandler = inputHandler$1;
11202
11314
  /**
11315
+ This facet can be used to provide functions that create effects
11316
+ to be dispatched when the editor's focus state changes.
11317
+ */
11318
+ EditorView.focusChangeEffect = focusChangeEffect;
11319
+ /**
11203
11320
  By default, the editor assumes all its content has the same
11204
11321
  [text direction](https://codemirror.net/6/docs/ref/#view.Direction). Configure this with a `true`
11205
11322
  value to make it read the text direction of every (rendered)
@@ -11618,9 +11735,10 @@
11618
11735
  let from = Math.max(range.from, view.viewport.from), to = Math.min(range.to, view.viewport.to);
11619
11736
  let ltr = view.textDirection == Direction.LTR;
11620
11737
  let content = view.contentDOM, contentRect = content.getBoundingClientRect(), base = getBase(view);
11621
- let lineStyle = window.getComputedStyle(content.firstChild);
11622
- let leftSide = contentRect.left + parseInt(lineStyle.paddingLeft) + Math.min(0, parseInt(lineStyle.textIndent));
11623
- let rightSide = contentRect.right - parseInt(lineStyle.paddingRight);
11738
+ let lineElt = content.querySelector(".cm-line"), lineStyle = lineElt && window.getComputedStyle(lineElt);
11739
+ let leftSide = contentRect.left +
11740
+ (lineStyle ? parseInt(lineStyle.paddingLeft) + Math.min(0, parseInt(lineStyle.textIndent)) : 0);
11741
+ let rightSide = contentRect.right - (lineStyle ? parseInt(lineStyle.paddingRight) : 0);
11624
11742
  let startBlock = blockAt(view, from), endBlock = blockAt(view, to);
11625
11743
  let visualStart = startBlock.type == BlockType.Text ? startBlock : null;
11626
11744
  let visualEnd = endBlock.type == BlockType.Text ? endBlock : null;
@@ -12482,6 +12600,7 @@
12482
12600
  });
12483
12601
  }
12484
12602
  });
12603
+ const knownHeight = /*@__PURE__*/new WeakMap();
12485
12604
  const tooltipPlugin = /*@__PURE__*/ViewPlugin.fromClass(class {
12486
12605
  constructor(view) {
12487
12606
  this.view = view;
@@ -12597,6 +12716,7 @@
12597
12716
  };
12598
12717
  }
12599
12718
  writeMeasure(measured) {
12719
+ var _a;
12600
12720
  let { editor, space } = measured;
12601
12721
  let others = [];
12602
12722
  for (let i = 0; i < this.manager.tooltips.length; i++) {
@@ -12612,7 +12732,7 @@
12612
12732
  }
12613
12733
  let arrow = tooltip.arrow ? tView.dom.querySelector(".cm-tooltip-arrow") : null;
12614
12734
  let arrowHeight = arrow ? 7 /* Arrow.Size */ : 0;
12615
- let width = size.right - size.left, height = size.bottom - size.top;
12735
+ let width = size.right - size.left, height = (_a = knownHeight.get(tView)) !== null && _a !== void 0 ? _a : size.bottom - size.top;
12616
12736
  let offset = tView.offset || noOffset, ltr = this.view.textDirection == Direction.LTR;
12617
12737
  let left = size.width > space.right - space.left ? (ltr ? space.left : space.right - size.width)
12618
12738
  : ltr ? Math.min(pos.left - (arrow ? 14 /* Arrow.Offset */ : 0) + offset.x, space.right - width)
@@ -12629,6 +12749,7 @@
12629
12749
  dom.style.top = Outside;
12630
12750
  continue;
12631
12751
  }
12752
+ knownHeight.set(tView, height);
12632
12753
  dom.style.height = (height = spaceVert) + "px";
12633
12754
  }
12634
12755
  else if (dom.style.height) {
@@ -14943,45 +15064,59 @@
14943
15064
  new NodeProp({ perNode: true });
14944
15065
 
14945
15066
  let nextTagID = 0;
14946
- /// Highlighting tags are markers that denote a highlighting category.
14947
- /// They are [associated](#highlight.styleTags) with parts of a syntax
14948
- /// tree by a language mode, and then mapped to an actual CSS style by
14949
- /// a [highlighter](#highlight.Highlighter).
14950
- ///
14951
- /// Because syntax tree node types and highlight styles have to be
14952
- /// able to talk the same language, CodeMirror uses a mostly _closed_
14953
- /// [vocabulary](#highlight.tags) of syntax tags (as opposed to
14954
- /// traditional open string-based systems, which make it hard for
14955
- /// highlighting themes to cover all the tokens produced by the
14956
- /// various languages).
14957
- ///
14958
- /// It _is_ possible to [define](#highlight.Tag^define) your own
14959
- /// highlighting tags for system-internal use (where you control both
14960
- /// the language package and the highlighter), but such tags will not
14961
- /// be picked up by regular highlighters (though you can derive them
14962
- /// from standard tags to allow highlighters to fall back to those).
15067
+ /**
15068
+ Highlighting tags are markers that denote a highlighting category.
15069
+ They are [associated](#highlight.styleTags) with parts of a syntax
15070
+ tree by a language mode, and then mapped to an actual CSS style by
15071
+ a [highlighter](#highlight.Highlighter).
15072
+
15073
+ Because syntax tree node types and highlight styles have to be
15074
+ able to talk the same language, CodeMirror uses a mostly _closed_
15075
+ [vocabulary](#highlight.tags) of syntax tags (as opposed to
15076
+ traditional open string-based systems, which make it hard for
15077
+ highlighting themes to cover all the tokens produced by the
15078
+ various languages).
15079
+
15080
+ It _is_ possible to [define](#highlight.Tag^define) your own
15081
+ highlighting tags for system-internal use (where you control both
15082
+ the language package and the highlighter), but such tags will not
15083
+ be picked up by regular highlighters (though you can derive them
15084
+ from standard tags to allow highlighters to fall back to those).
15085
+ */
14963
15086
  class Tag {
14964
- /// @internal
15087
+ /**
15088
+ @internal
15089
+ */
14965
15090
  constructor(
14966
- /// The set of this tag and all its parent tags, starting with
14967
- /// this one itself and sorted in order of decreasing specificity.
15091
+ /**
15092
+ The set of this tag and all its parent tags, starting with
15093
+ this one itself and sorted in order of decreasing specificity.
15094
+ */
14968
15095
  set,
14969
- /// The base unmodified tag that this one is based on, if it's
14970
- /// modified @internal
15096
+ /**
15097
+ The base unmodified tag that this one is based on, if it's
15098
+ modified @internal
15099
+ */
14971
15100
  base,
14972
- /// The modifiers applied to this.base @internal
15101
+ /**
15102
+ The modifiers applied to this.base @internal
15103
+ */
14973
15104
  modified) {
14974
15105
  this.set = set;
14975
15106
  this.base = base;
14976
15107
  this.modified = modified;
14977
- /// @internal
15108
+ /**
15109
+ @internal
15110
+ */
14978
15111
  this.id = nextTagID++;
14979
15112
  }
14980
- /// Define a new tag. If `parent` is given, the tag is treated as a
14981
- /// sub-tag of that parent, and
14982
- /// [highlighters](#highlight.tagHighlighter) that don't mention
14983
- /// this tag will try to fall back to the parent tag (or grandparent
14984
- /// tag, etc).
15113
+ /**
15114
+ Define a new tag. If `parent` is given, the tag is treated as a
15115
+ sub-tag of that parent, and
15116
+ [highlighters](#highlight.tagHighlighter) that don't mention
15117
+ this tag will try to fall back to the parent tag (or grandparent
15118
+ tag, etc).
15119
+ */
14985
15120
  static define(parent) {
14986
15121
  if (parent === null || parent === void 0 ? void 0 : parent.base)
14987
15122
  throw new Error("Can not derive from a modified tag");
@@ -14992,16 +15127,18 @@
14992
15127
  tag.set.push(t);
14993
15128
  return tag;
14994
15129
  }
14995
- /// Define a tag _modifier_, which is a function that, given a tag,
14996
- /// will return a tag that is a subtag of the original. Applying the
14997
- /// same modifier to a twice tag will return the same value (`m1(t1)
14998
- /// == m1(t1)`) and applying multiple modifiers will, regardless or
14999
- /// order, produce the same tag (`m1(m2(t1)) == m2(m1(t1))`).
15000
- ///
15001
- /// When multiple modifiers are applied to a given base tag, each
15002
- /// smaller set of modifiers is registered as a parent, so that for
15003
- /// example `m1(m2(m3(t1)))` is a subtype of `m1(m2(t1))`,
15004
- /// `m1(m3(t1)`, and so on.
15130
+ /**
15131
+ Define a tag _modifier_, which is a function that, given a tag,
15132
+ will return a tag that is a subtag of the original. Applying the
15133
+ same modifier to a twice tag will return the same value (`m1(t1)
15134
+ == m1(t1)`) and applying multiple modifiers will, regardless or
15135
+ order, produce the same tag (`m1(m2(t1)) == m2(m1(t1))`).
15136
+
15137
+ When multiple modifiers are applied to a given base tag, each
15138
+ smaller set of modifiers is registered as a parent, so that for
15139
+ example `m1(m2(m3(t1)))` is a subtype of `m1(m2(t1))`,
15140
+ `m1(m3(t1)`, and so on.
15141
+ */
15005
15142
  static defineModifier() {
15006
15143
  let mod = new Modifier;
15007
15144
  return (tag) => {
@@ -15046,55 +15183,57 @@
15046
15183
  }
15047
15184
  return sets.sort((a, b) => b.length - a.length);
15048
15185
  }
15049
- /// This function is used to add a set of tags to a language syntax
15050
- /// via [`NodeSet.extend`](#common.NodeSet.extend) or
15051
- /// [`LRParser.configure`](#lr.LRParser.configure).
15052
- ///
15053
- /// The argument object maps node selectors to [highlighting
15054
- /// tags](#highlight.Tag) or arrays of tags.
15055
- ///
15056
- /// Node selectors may hold one or more (space-separated) node paths.
15057
- /// Such a path can be a [node name](#common.NodeType.name), or
15058
- /// multiple node names (or `*` wildcards) separated by slash
15059
- /// characters, as in `"Block/Declaration/VariableName"`. Such a path
15060
- /// matches the final node but only if its direct parent nodes are the
15061
- /// other nodes mentioned. A `*` in such a path matches any parent,
15062
- /// but only a single level—wildcards that match multiple parents
15063
- /// aren't supported, both for efficiency reasons and because Lezer
15064
- /// trees make it rather hard to reason about what they would match.)
15065
- ///
15066
- /// A path can be ended with `/...` to indicate that the tag assigned
15067
- /// to the node should also apply to all child nodes, even if they
15068
- /// match their own style (by default, only the innermost style is
15069
- /// used).
15070
- ///
15071
- /// When a path ends in `!`, as in `Attribute!`, no further matching
15072
- /// happens for the node's child nodes, and the entire node gets the
15073
- /// given style.
15074
- ///
15075
- /// In this notation, node names that contain `/`, `!`, `*`, or `...`
15076
- /// must be quoted as JSON strings.
15077
- ///
15078
- /// For example:
15079
- ///
15080
- /// ```javascript
15081
- /// parser.withProps(
15082
- /// styleTags({
15083
- /// // Style Number and BigNumber nodes
15084
- /// "Number BigNumber": tags.number,
15085
- /// // Style Escape nodes whose parent is String
15086
- /// "String/Escape": tags.escape,
15087
- /// // Style anything inside Attributes nodes
15088
- /// "Attributes!": tags.meta,
15089
- /// // Add a style to all content inside Italic nodes
15090
- /// "Italic/...": tags.emphasis,
15091
- /// // Style InvalidString nodes as both `string` and `invalid`
15092
- /// "InvalidString": [tags.string, tags.invalid],
15093
- /// // Style the node named "/" as punctuation
15094
- /// '"/"': tags.punctuation
15095
- /// })
15096
- /// )
15097
- /// ```
15186
+ /**
15187
+ This function is used to add a set of tags to a language syntax
15188
+ via [`NodeSet.extend`](#common.NodeSet.extend) or
15189
+ [`LRParser.configure`](#lr.LRParser.configure).
15190
+
15191
+ The argument object maps node selectors to [highlighting
15192
+ tags](#highlight.Tag) or arrays of tags.
15193
+
15194
+ Node selectors may hold one or more (space-separated) node paths.
15195
+ Such a path can be a [node name](#common.NodeType.name), or
15196
+ multiple node names (or `*` wildcards) separated by slash
15197
+ characters, as in `"Block/Declaration/VariableName"`. Such a path
15198
+ matches the final node but only if its direct parent nodes are the
15199
+ other nodes mentioned. A `*` in such a path matches any parent,
15200
+ but only a single level—wildcards that match multiple parents
15201
+ aren't supported, both for efficiency reasons and because Lezer
15202
+ trees make it rather hard to reason about what they would match.)
15203
+
15204
+ A path can be ended with `/...` to indicate that the tag assigned
15205
+ to the node should also apply to all child nodes, even if they
15206
+ match their own style (by default, only the innermost style is
15207
+ used).
15208
+
15209
+ When a path ends in `!`, as in `Attribute!`, no further matching
15210
+ happens for the node's child nodes, and the entire node gets the
15211
+ given style.
15212
+
15213
+ In this notation, node names that contain `/`, `!`, `*`, or `...`
15214
+ must be quoted as JSON strings.
15215
+
15216
+ For example:
15217
+
15218
+ ```javascript
15219
+ parser.withProps(
15220
+ styleTags({
15221
+ // Style Number and BigNumber nodes
15222
+ "Number BigNumber": tags.number,
15223
+ // Style Escape nodes whose parent is String
15224
+ "String/Escape": tags.escape,
15225
+ // Style anything inside Attributes nodes
15226
+ "Attributes!": tags.meta,
15227
+ // Add a style to all content inside Italic nodes
15228
+ "Italic/...": tags.emphasis,
15229
+ // Style InvalidString nodes as both `string` and `invalid`
15230
+ "InvalidString": [tags.string, tags.invalid],
15231
+ // Style the node named "/" as punctuation
15232
+ '"/"': tags.punctuation
15233
+ })
15234
+ )
15235
+ ```
15236
+ */
15098
15237
  function styleTags(spec) {
15099
15238
  let byName = Object.create(null);
15100
15239
  for (let prop in spec) {
@@ -15103,10 +15242,10 @@
15103
15242
  tags = [tags];
15104
15243
  for (let part of prop.split(" "))
15105
15244
  if (part) {
15106
- let pieces = [], mode = 2 /* Mode.Normal */, rest = part;
15245
+ let pieces = [], mode = 2 /* Normal */, rest = part;
15107
15246
  for (let pos = 0;;) {
15108
15247
  if (rest == "..." && pos > 0 && pos + 3 == part.length) {
15109
- mode = 1 /* Mode.Inherit */;
15248
+ mode = 1 /* Inherit */;
15110
15249
  break;
15111
15250
  }
15112
15251
  let m = /^"(?:[^"\\]|\\.)*?"|[^\/!]+/.exec(rest);
@@ -15118,7 +15257,7 @@
15118
15257
  break;
15119
15258
  let next = part[pos++];
15120
15259
  if (pos == part.length && next == "!") {
15121
- mode = 0 /* Mode.Opaque */;
15260
+ mode = 0 /* Opaque */;
15122
15261
  break;
15123
15262
  }
15124
15263
  if (next != "/")
@@ -15142,8 +15281,8 @@
15142
15281
  this.context = context;
15143
15282
  this.next = next;
15144
15283
  }
15145
- get opaque() { return this.mode == 0 /* Mode.Opaque */; }
15146
- get inherit() { return this.mode == 1 /* Mode.Inherit */; }
15284
+ get opaque() { return this.mode == 0 /* Opaque */; }
15285
+ get inherit() { return this.mode == 1 /* Inherit */; }
15147
15286
  sort(other) {
15148
15287
  if (!other || other.depth < this.depth) {
15149
15288
  this.next = other;
@@ -15154,10 +15293,12 @@
15154
15293
  }
15155
15294
  get depth() { return this.context ? this.context.length : 0; }
15156
15295
  }
15157
- Rule.empty = new Rule([], 2 /* Mode.Normal */, null);
15158
- /// Define a [highlighter](#highlight.Highlighter) from an array of
15159
- /// tag/class pairs. Classes associated with more specific tags will
15160
- /// take precedence.
15296
+ Rule.empty = new Rule([], 2 /* Normal */, null);
15297
+ /**
15298
+ Define a [highlighter](#highlight.Highlighter) from an array of
15299
+ tag/class pairs. Classes associated with more specific tags will
15300
+ take precedence.
15301
+ */
15161
15302
  function tagHighlighter(tags, options) {
15162
15303
  let map = Object.create(null);
15163
15304
  for (let style of tags) {
@@ -15194,16 +15335,24 @@
15194
15335
  }
15195
15336
  return result;
15196
15337
  }
15197
- /// Highlight the given [tree](#common.Tree) with the given
15198
- /// [highlighter](#highlight.Highlighter).
15338
+ /**
15339
+ Highlight the given [tree](#common.Tree) with the given
15340
+ [highlighter](#highlight.Highlighter).
15341
+ */
15199
15342
  function highlightTree(tree, highlighter,
15200
- /// Assign styling to a region of the text. Will be called, in order
15201
- /// of position, for any ranges where more than zero classes apply.
15202
- /// `classes` is a space separated string of CSS classes.
15343
+ /**
15344
+ Assign styling to a region of the text. Will be called, in order
15345
+ of position, for any ranges where more than zero classes apply.
15346
+ `classes` is a space separated string of CSS classes.
15347
+ */
15203
15348
  putStyle,
15204
- /// The start of the range to highlight.
15349
+ /**
15350
+ The start of the range to highlight.
15351
+ */
15205
15352
  from = 0,
15206
- /// The end of the range.
15353
+ /**
15354
+ The end of the range.
15355
+ */
15207
15356
  to = tree.length) {
15208
15357
  let builder = new HighlightBuilder(from, Array.isArray(highlighter) ? highlighter : [highlighter], putStyle);
15209
15358
  builder.highlightRange(tree.cursor(), from, to, "", builder.highlighters);
@@ -15241,7 +15390,7 @@
15241
15390
  if (cls)
15242
15391
  cls += " ";
15243
15392
  cls += tagCls;
15244
- if (rule.mode == 1 /* Mode.Inherit */)
15393
+ if (rule.mode == 1 /* Inherit */)
15245
15394
  inheritedClass += (inheritedClass ? " " : "") + tagCls;
15246
15395
  }
15247
15396
  this.startSpan(cursor.from, cls);
@@ -15288,9 +15437,11 @@
15288
15437
  }
15289
15438
  }
15290
15439
  }
15291
- /// Match a syntax node's [highlight rules](#highlight.styleTags). If
15292
- /// there's a match, return its set of tags, and whether it is
15293
- /// opaque (uses a `!`) or applies to all child nodes (`/...`).
15440
+ /**
15441
+ Match a syntax node's [highlight rules](#highlight.styleTags). If
15442
+ there's a match, return its set of tags, and whether it is
15443
+ opaque (uses a `!`) or applies to all child nodes (`/...`).
15444
+ */
15294
15445
  function getStyleTags(node) {
15295
15446
  let rule = node.type.prop(ruleNodeProp);
15296
15447
  while (rule && rule.context && !node.matchContext(rule.context))
@@ -15299,268 +15450,440 @@
15299
15450
  }
15300
15451
  const t = Tag.define;
15301
15452
  const comment = t(), name = t(), typeName = t(name), propertyName = t(name), literal = t(), string = t(literal), number = t(literal), content = t(), heading = t(content), keyword = t(), operator = t(), punctuation = t(), bracket = t(punctuation), meta = t();
15302
- /// The default set of highlighting [tags](#highlight.Tag).
15303
- ///
15304
- /// This collection is heavily biased towards programming languages,
15305
- /// and necessarily incomplete. A full ontology of syntactic
15306
- /// constructs would fill a stack of books, and be impractical to
15307
- /// write themes for. So try to make do with this set. If all else
15308
- /// fails, [open an
15309
- /// issue](https://github.com/codemirror/codemirror.next) to propose a
15310
- /// new tag, or [define](#highlight.Tag^define) a local custom tag for
15311
- /// your use case.
15312
- ///
15313
- /// Note that it is not obligatory to always attach the most specific
15314
- /// tag possible to an element—if your grammar can't easily
15315
- /// distinguish a certain type of element (such as a local variable),
15316
- /// it is okay to style it as its more general variant (a variable).
15317
- ///
15318
- /// For tags that extend some parent tag, the documentation links to
15319
- /// the parent.
15453
+ /**
15454
+ The default set of highlighting [tags](#highlight.Tag).
15455
+
15456
+ This collection is heavily biased towards programming languages,
15457
+ and necessarily incomplete. A full ontology of syntactic
15458
+ constructs would fill a stack of books, and be impractical to
15459
+ write themes for. So try to make do with this set. If all else
15460
+ fails, [open an
15461
+ issue](https://github.com/codemirror/codemirror.next) to propose a
15462
+ new tag, or [define](#highlight.Tag^define) a local custom tag for
15463
+ your use case.
15464
+
15465
+ Note that it is not obligatory to always attach the most specific
15466
+ tag possible to an element—if your grammar can't easily
15467
+ distinguish a certain type of element (such as a local variable),
15468
+ it is okay to style it as its more general variant (a variable).
15469
+
15470
+ For tags that extend some parent tag, the documentation links to
15471
+ the parent.
15472
+ */
15320
15473
  const tags = {
15321
- /// A comment.
15474
+ /**
15475
+ A comment.
15476
+ */
15322
15477
  comment,
15323
- /// A line [comment](#highlight.tags.comment).
15478
+ /**
15479
+ A line [comment](#highlight.tags.comment).
15480
+ */
15324
15481
  lineComment: t(comment),
15325
- /// A block [comment](#highlight.tags.comment).
15482
+ /**
15483
+ A block [comment](#highlight.tags.comment).
15484
+ */
15326
15485
  blockComment: t(comment),
15327
- /// A documentation [comment](#highlight.tags.comment).
15486
+ /**
15487
+ A documentation [comment](#highlight.tags.comment).
15488
+ */
15328
15489
  docComment: t(comment),
15329
- /// Any kind of identifier.
15490
+ /**
15491
+ Any kind of identifier.
15492
+ */
15330
15493
  name,
15331
- /// The [name](#highlight.tags.name) of a variable.
15494
+ /**
15495
+ The [name](#highlight.tags.name) of a variable.
15496
+ */
15332
15497
  variableName: t(name),
15333
- /// A type [name](#highlight.tags.name).
15498
+ /**
15499
+ A type [name](#highlight.tags.name).
15500
+ */
15334
15501
  typeName: typeName,
15335
- /// A tag name (subtag of [`typeName`](#highlight.tags.typeName)).
15502
+ /**
15503
+ A tag name (subtag of [`typeName`](#highlight.tags.typeName)).
15504
+ */
15336
15505
  tagName: t(typeName),
15337
- /// A property or field [name](#highlight.tags.name).
15506
+ /**
15507
+ A property or field [name](#highlight.tags.name).
15508
+ */
15338
15509
  propertyName: propertyName,
15339
- /// An attribute name (subtag of [`propertyName`](#highlight.tags.propertyName)).
15510
+ /**
15511
+ An attribute name (subtag of [`propertyName`](#highlight.tags.propertyName)).
15512
+ */
15340
15513
  attributeName: t(propertyName),
15341
- /// The [name](#highlight.tags.name) of a class.
15514
+ /**
15515
+ The [name](#highlight.tags.name) of a class.
15516
+ */
15342
15517
  className: t(name),
15343
- /// A label [name](#highlight.tags.name).
15518
+ /**
15519
+ A label [name](#highlight.tags.name).
15520
+ */
15344
15521
  labelName: t(name),
15345
- /// A namespace [name](#highlight.tags.name).
15522
+ /**
15523
+ A namespace [name](#highlight.tags.name).
15524
+ */
15346
15525
  namespace: t(name),
15347
- /// The [name](#highlight.tags.name) of a macro.
15526
+ /**
15527
+ The [name](#highlight.tags.name) of a macro.
15528
+ */
15348
15529
  macroName: t(name),
15349
- /// A literal value.
15530
+ /**
15531
+ A literal value.
15532
+ */
15350
15533
  literal,
15351
- /// A string [literal](#highlight.tags.literal).
15534
+ /**
15535
+ A string [literal](#highlight.tags.literal).
15536
+ */
15352
15537
  string,
15353
- /// A documentation [string](#highlight.tags.string).
15538
+ /**
15539
+ A documentation [string](#highlight.tags.string).
15540
+ */
15354
15541
  docString: t(string),
15355
- /// A character literal (subtag of [string](#highlight.tags.string)).
15542
+ /**
15543
+ A character literal (subtag of [string](#highlight.tags.string)).
15544
+ */
15356
15545
  character: t(string),
15357
- /// An attribute value (subtag of [string](#highlight.tags.string)).
15546
+ /**
15547
+ An attribute value (subtag of [string](#highlight.tags.string)).
15548
+ */
15358
15549
  attributeValue: t(string),
15359
- /// A number [literal](#highlight.tags.literal).
15550
+ /**
15551
+ A number [literal](#highlight.tags.literal).
15552
+ */
15360
15553
  number,
15361
- /// An integer [number](#highlight.tags.number) literal.
15554
+ /**
15555
+ An integer [number](#highlight.tags.number) literal.
15556
+ */
15362
15557
  integer: t(number),
15363
- /// A floating-point [number](#highlight.tags.number) literal.
15558
+ /**
15559
+ A floating-point [number](#highlight.tags.number) literal.
15560
+ */
15364
15561
  float: t(number),
15365
- /// A boolean [literal](#highlight.tags.literal).
15562
+ /**
15563
+ A boolean [literal](#highlight.tags.literal).
15564
+ */
15366
15565
  bool: t(literal),
15367
- /// Regular expression [literal](#highlight.tags.literal).
15566
+ /**
15567
+ Regular expression [literal](#highlight.tags.literal).
15568
+ */
15368
15569
  regexp: t(literal),
15369
- /// An escape [literal](#highlight.tags.literal), for example a
15370
- /// backslash escape in a string.
15570
+ /**
15571
+ An escape [literal](#highlight.tags.literal), for example a
15572
+ backslash escape in a string.
15573
+ */
15371
15574
  escape: t(literal),
15372
- /// A color [literal](#highlight.tags.literal).
15575
+ /**
15576
+ A color [literal](#highlight.tags.literal).
15577
+ */
15373
15578
  color: t(literal),
15374
- /// A URL [literal](#highlight.tags.literal).
15579
+ /**
15580
+ A URL [literal](#highlight.tags.literal).
15581
+ */
15375
15582
  url: t(literal),
15376
- /// A language keyword.
15583
+ /**
15584
+ A language keyword.
15585
+ */
15377
15586
  keyword,
15378
- /// The [keyword](#highlight.tags.keyword) for the self or this
15379
- /// object.
15587
+ /**
15588
+ The [keyword](#highlight.tags.keyword) for the self or this
15589
+ object.
15590
+ */
15380
15591
  self: t(keyword),
15381
- /// The [keyword](#highlight.tags.keyword) for null.
15592
+ /**
15593
+ The [keyword](#highlight.tags.keyword) for null.
15594
+ */
15382
15595
  null: t(keyword),
15383
- /// A [keyword](#highlight.tags.keyword) denoting some atomic value.
15596
+ /**
15597
+ A [keyword](#highlight.tags.keyword) denoting some atomic value.
15598
+ */
15384
15599
  atom: t(keyword),
15385
- /// A [keyword](#highlight.tags.keyword) that represents a unit.
15600
+ /**
15601
+ A [keyword](#highlight.tags.keyword) that represents a unit.
15602
+ */
15386
15603
  unit: t(keyword),
15387
- /// A modifier [keyword](#highlight.tags.keyword).
15604
+ /**
15605
+ A modifier [keyword](#highlight.tags.keyword).
15606
+ */
15388
15607
  modifier: t(keyword),
15389
- /// A [keyword](#highlight.tags.keyword) that acts as an operator.
15608
+ /**
15609
+ A [keyword](#highlight.tags.keyword) that acts as an operator.
15610
+ */
15390
15611
  operatorKeyword: t(keyword),
15391
- /// A control-flow related [keyword](#highlight.tags.keyword).
15612
+ /**
15613
+ A control-flow related [keyword](#highlight.tags.keyword).
15614
+ */
15392
15615
  controlKeyword: t(keyword),
15393
- /// A [keyword](#highlight.tags.keyword) that defines something.
15616
+ /**
15617
+ A [keyword](#highlight.tags.keyword) that defines something.
15618
+ */
15394
15619
  definitionKeyword: t(keyword),
15395
- /// A [keyword](#highlight.tags.keyword) related to defining or
15396
- /// interfacing with modules.
15620
+ /**
15621
+ A [keyword](#highlight.tags.keyword) related to defining or
15622
+ interfacing with modules.
15623
+ */
15397
15624
  moduleKeyword: t(keyword),
15398
- /// An operator.
15625
+ /**
15626
+ An operator.
15627
+ */
15399
15628
  operator,
15400
- /// An [operator](#highlight.tags.operator) that dereferences something.
15629
+ /**
15630
+ An [operator](#highlight.tags.operator) that dereferences something.
15631
+ */
15401
15632
  derefOperator: t(operator),
15402
- /// Arithmetic-related [operator](#highlight.tags.operator).
15633
+ /**
15634
+ Arithmetic-related [operator](#highlight.tags.operator).
15635
+ */
15403
15636
  arithmeticOperator: t(operator),
15404
- /// Logical [operator](#highlight.tags.operator).
15637
+ /**
15638
+ Logical [operator](#highlight.tags.operator).
15639
+ */
15405
15640
  logicOperator: t(operator),
15406
- /// Bit [operator](#highlight.tags.operator).
15641
+ /**
15642
+ Bit [operator](#highlight.tags.operator).
15643
+ */
15407
15644
  bitwiseOperator: t(operator),
15408
- /// Comparison [operator](#highlight.tags.operator).
15645
+ /**
15646
+ Comparison [operator](#highlight.tags.operator).
15647
+ */
15409
15648
  compareOperator: t(operator),
15410
- /// [Operator](#highlight.tags.operator) that updates its operand.
15649
+ /**
15650
+ [Operator](#highlight.tags.operator) that updates its operand.
15651
+ */
15411
15652
  updateOperator: t(operator),
15412
- /// [Operator](#highlight.tags.operator) that defines something.
15653
+ /**
15654
+ [Operator](#highlight.tags.operator) that defines something.
15655
+ */
15413
15656
  definitionOperator: t(operator),
15414
- /// Type-related [operator](#highlight.tags.operator).
15657
+ /**
15658
+ Type-related [operator](#highlight.tags.operator).
15659
+ */
15415
15660
  typeOperator: t(operator),
15416
- /// Control-flow [operator](#highlight.tags.operator).
15661
+ /**
15662
+ Control-flow [operator](#highlight.tags.operator).
15663
+ */
15417
15664
  controlOperator: t(operator),
15418
- /// Program or markup punctuation.
15665
+ /**
15666
+ Program or markup punctuation.
15667
+ */
15419
15668
  punctuation,
15420
- /// [Punctuation](#highlight.tags.punctuation) that separates
15421
- /// things.
15669
+ /**
15670
+ [Punctuation](#highlight.tags.punctuation) that separates
15671
+ things.
15672
+ */
15422
15673
  separator: t(punctuation),
15423
- /// Bracket-style [punctuation](#highlight.tags.punctuation).
15674
+ /**
15675
+ Bracket-style [punctuation](#highlight.tags.punctuation).
15676
+ */
15424
15677
  bracket,
15425
- /// Angle [brackets](#highlight.tags.bracket) (usually `<` and `>`
15426
- /// tokens).
15678
+ /**
15679
+ Angle [brackets](#highlight.tags.bracket) (usually `<` and `>`
15680
+ tokens).
15681
+ */
15427
15682
  angleBracket: t(bracket),
15428
- /// Square [brackets](#highlight.tags.bracket) (usually `[` and `]`
15429
- /// tokens).
15683
+ /**
15684
+ Square [brackets](#highlight.tags.bracket) (usually `[` and `]`
15685
+ tokens).
15686
+ */
15430
15687
  squareBracket: t(bracket),
15431
- /// Parentheses (usually `(` and `)` tokens). Subtag of
15432
- /// [bracket](#highlight.tags.bracket).
15688
+ /**
15689
+ Parentheses (usually `(` and `)` tokens). Subtag of
15690
+ [bracket](#highlight.tags.bracket).
15691
+ */
15433
15692
  paren: t(bracket),
15434
- /// Braces (usually `{` and `}` tokens). Subtag of
15435
- /// [bracket](#highlight.tags.bracket).
15693
+ /**
15694
+ Braces (usually `{` and `}` tokens). Subtag of
15695
+ [bracket](#highlight.tags.bracket).
15696
+ */
15436
15697
  brace: t(bracket),
15437
- /// Content, for example plain text in XML or markup documents.
15698
+ /**
15699
+ Content, for example plain text in XML or markup documents.
15700
+ */
15438
15701
  content,
15439
- /// [Content](#highlight.tags.content) that represents a heading.
15702
+ /**
15703
+ [Content](#highlight.tags.content) that represents a heading.
15704
+ */
15440
15705
  heading,
15441
- /// A level 1 [heading](#highlight.tags.heading).
15706
+ /**
15707
+ A level 1 [heading](#highlight.tags.heading).
15708
+ */
15442
15709
  heading1: t(heading),
15443
- /// A level 2 [heading](#highlight.tags.heading).
15710
+ /**
15711
+ A level 2 [heading](#highlight.tags.heading).
15712
+ */
15444
15713
  heading2: t(heading),
15445
- /// A level 3 [heading](#highlight.tags.heading).
15714
+ /**
15715
+ A level 3 [heading](#highlight.tags.heading).
15716
+ */
15446
15717
  heading3: t(heading),
15447
- /// A level 4 [heading](#highlight.tags.heading).
15718
+ /**
15719
+ A level 4 [heading](#highlight.tags.heading).
15720
+ */
15448
15721
  heading4: t(heading),
15449
- /// A level 5 [heading](#highlight.tags.heading).
15722
+ /**
15723
+ A level 5 [heading](#highlight.tags.heading).
15724
+ */
15450
15725
  heading5: t(heading),
15451
- /// A level 6 [heading](#highlight.tags.heading).
15726
+ /**
15727
+ A level 6 [heading](#highlight.tags.heading).
15728
+ */
15452
15729
  heading6: t(heading),
15453
- /// A prose separator (such as a horizontal rule).
15730
+ /**
15731
+ A prose separator (such as a horizontal rule).
15732
+ */
15454
15733
  contentSeparator: t(content),
15455
- /// [Content](#highlight.tags.content) that represents a list.
15734
+ /**
15735
+ [Content](#highlight.tags.content) that represents a list.
15736
+ */
15456
15737
  list: t(content),
15457
- /// [Content](#highlight.tags.content) that represents a quote.
15738
+ /**
15739
+ [Content](#highlight.tags.content) that represents a quote.
15740
+ */
15458
15741
  quote: t(content),
15459
- /// [Content](#highlight.tags.content) that is emphasized.
15742
+ /**
15743
+ [Content](#highlight.tags.content) that is emphasized.
15744
+ */
15460
15745
  emphasis: t(content),
15461
- /// [Content](#highlight.tags.content) that is styled strong.
15746
+ /**
15747
+ [Content](#highlight.tags.content) that is styled strong.
15748
+ */
15462
15749
  strong: t(content),
15463
- /// [Content](#highlight.tags.content) that is part of a link.
15750
+ /**
15751
+ [Content](#highlight.tags.content) that is part of a link.
15752
+ */
15464
15753
  link: t(content),
15465
- /// [Content](#highlight.tags.content) that is styled as code or
15466
- /// monospace.
15754
+ /**
15755
+ [Content](#highlight.tags.content) that is styled as code or
15756
+ monospace.
15757
+ */
15467
15758
  monospace: t(content),
15468
- /// [Content](#highlight.tags.content) that has a strike-through
15469
- /// style.
15759
+ /**
15760
+ [Content](#highlight.tags.content) that has a strike-through
15761
+ style.
15762
+ */
15470
15763
  strikethrough: t(content),
15471
- /// Inserted text in a change-tracking format.
15764
+ /**
15765
+ Inserted text in a change-tracking format.
15766
+ */
15472
15767
  inserted: t(),
15473
- /// Deleted text.
15768
+ /**
15769
+ Deleted text.
15770
+ */
15474
15771
  deleted: t(),
15475
- /// Changed text.
15772
+ /**
15773
+ Changed text.
15774
+ */
15476
15775
  changed: t(),
15477
- /// An invalid or unsyntactic element.
15776
+ /**
15777
+ An invalid or unsyntactic element.
15778
+ */
15478
15779
  invalid: t(),
15479
- /// Metadata or meta-instruction.
15780
+ /**
15781
+ Metadata or meta-instruction.
15782
+ */
15480
15783
  meta,
15481
- /// [Metadata](#highlight.tags.meta) that applies to the entire
15482
- /// document.
15784
+ /**
15785
+ [Metadata](#highlight.tags.meta) that applies to the entire
15786
+ document.
15787
+ */
15483
15788
  documentMeta: t(meta),
15484
- /// [Metadata](#highlight.tags.meta) that annotates or adds
15485
- /// attributes to a given syntactic element.
15789
+ /**
15790
+ [Metadata](#highlight.tags.meta) that annotates or adds
15791
+ attributes to a given syntactic element.
15792
+ */
15486
15793
  annotation: t(meta),
15487
- /// Processing instruction or preprocessor directive. Subtag of
15488
- /// [meta](#highlight.tags.meta).
15794
+ /**
15795
+ Processing instruction or preprocessor directive. Subtag of
15796
+ [meta](#highlight.tags.meta).
15797
+ */
15489
15798
  processingInstruction: t(meta),
15490
- /// [Modifier](#highlight.Tag^defineModifier) that indicates that a
15491
- /// given element is being defined. Expected to be used with the
15492
- /// various [name](#highlight.tags.name) tags.
15799
+ /**
15800
+ [Modifier](#highlight.Tag^defineModifier) that indicates that a
15801
+ given element is being defined. Expected to be used with the
15802
+ various [name](#highlight.tags.name) tags.
15803
+ */
15493
15804
  definition: Tag.defineModifier(),
15494
- /// [Modifier](#highlight.Tag^defineModifier) that indicates that
15495
- /// something is constant. Mostly expected to be used with
15496
- /// [variable names](#highlight.tags.variableName).
15805
+ /**
15806
+ [Modifier](#highlight.Tag^defineModifier) that indicates that
15807
+ something is constant. Mostly expected to be used with
15808
+ [variable names](#highlight.tags.variableName).
15809
+ */
15497
15810
  constant: Tag.defineModifier(),
15498
- /// [Modifier](#highlight.Tag^defineModifier) used to indicate that
15499
- /// a [variable](#highlight.tags.variableName) or [property
15500
- /// name](#highlight.tags.propertyName) is being called or defined
15501
- /// as a function.
15811
+ /**
15812
+ [Modifier](#highlight.Tag^defineModifier) used to indicate that
15813
+ a [variable](#highlight.tags.variableName) or [property
15814
+ name](#highlight.tags.propertyName) is being called or defined
15815
+ as a function.
15816
+ */
15502
15817
  function: Tag.defineModifier(),
15503
- /// [Modifier](#highlight.Tag^defineModifier) that can be applied to
15504
- /// [names](#highlight.tags.name) to indicate that they belong to
15505
- /// the language's standard environment.
15818
+ /**
15819
+ [Modifier](#highlight.Tag^defineModifier) that can be applied to
15820
+ [names](#highlight.tags.name) to indicate that they belong to
15821
+ the language's standard environment.
15822
+ */
15506
15823
  standard: Tag.defineModifier(),
15507
- /// [Modifier](#highlight.Tag^defineModifier) that indicates a given
15508
- /// [names](#highlight.tags.name) is local to some scope.
15824
+ /**
15825
+ [Modifier](#highlight.Tag^defineModifier) that indicates a given
15826
+ [names](#highlight.tags.name) is local to some scope.
15827
+ */
15509
15828
  local: Tag.defineModifier(),
15510
- /// A generic variant [modifier](#highlight.Tag^defineModifier) that
15511
- /// can be used to tag language-specific alternative variants of
15512
- /// some common tag. It is recommended for themes to define special
15513
- /// forms of at least the [string](#highlight.tags.string) and
15514
- /// [variable name](#highlight.tags.variableName) tags, since those
15515
- /// come up a lot.
15829
+ /**
15830
+ A generic variant [modifier](#highlight.Tag^defineModifier) that
15831
+ can be used to tag language-specific alternative variants of
15832
+ some common tag. It is recommended for themes to define special
15833
+ forms of at least the [string](#highlight.tags.string) and
15834
+ [variable name](#highlight.tags.variableName) tags, since those
15835
+ come up a lot.
15836
+ */
15516
15837
  special: Tag.defineModifier()
15517
15838
  };
15518
- /// This is a highlighter that adds stable, predictable classes to
15519
- /// tokens, for styling with external CSS.
15520
- ///
15521
- /// The following tags are mapped to their name prefixed with `"tok-"`
15522
- /// (for example `"tok-comment"`):
15523
- ///
15524
- /// * [`link`](#highlight.tags.link)
15525
- /// * [`heading`](#highlight.tags.heading)
15526
- /// * [`emphasis`](#highlight.tags.emphasis)
15527
- /// * [`strong`](#highlight.tags.strong)
15528
- /// * [`keyword`](#highlight.tags.keyword)
15529
- /// * [`atom`](#highlight.tags.atom)
15530
- /// * [`bool`](#highlight.tags.bool)
15531
- /// * [`url`](#highlight.tags.url)
15532
- /// * [`labelName`](#highlight.tags.labelName)
15533
- /// * [`inserted`](#highlight.tags.inserted)
15534
- /// * [`deleted`](#highlight.tags.deleted)
15535
- /// * [`literal`](#highlight.tags.literal)
15536
- /// * [`string`](#highlight.tags.string)
15537
- /// * [`number`](#highlight.tags.number)
15538
- /// * [`variableName`](#highlight.tags.variableName)
15539
- /// * [`typeName`](#highlight.tags.typeName)
15540
- /// * [`namespace`](#highlight.tags.namespace)
15541
- /// * [`className`](#highlight.tags.className)
15542
- /// * [`macroName`](#highlight.tags.macroName)
15543
- /// * [`propertyName`](#highlight.tags.propertyName)
15544
- /// * [`operator`](#highlight.tags.operator)
15545
- /// * [`comment`](#highlight.tags.comment)
15546
- /// * [`meta`](#highlight.tags.meta)
15547
- /// * [`punctuation`](#highlight.tags.punctuation)
15548
- /// * [`invalid`](#highlight.tags.invalid)
15549
- ///
15550
- /// In addition, these mappings are provided:
15551
- ///
15552
- /// * [`regexp`](#highlight.tags.regexp),
15553
- /// [`escape`](#highlight.tags.escape), and
15554
- /// [`special`](#highlight.tags.special)[`(string)`](#highlight.tags.string)
15555
- /// are mapped to `"tok-string2"`
15556
- /// * [`special`](#highlight.tags.special)[`(variableName)`](#highlight.tags.variableName)
15557
- /// to `"tok-variableName2"`
15558
- /// * [`local`](#highlight.tags.local)[`(variableName)`](#highlight.tags.variableName)
15559
- /// to `"tok-variableName tok-local"`
15560
- /// * [`definition`](#highlight.tags.definition)[`(variableName)`](#highlight.tags.variableName)
15561
- /// to `"tok-variableName tok-definition"`
15562
- /// * [`definition`](#highlight.tags.definition)[`(propertyName)`](#highlight.tags.propertyName)
15563
- /// to `"tok-propertyName tok-definition"`
15839
+ /**
15840
+ This is a highlighter that adds stable, predictable classes to
15841
+ tokens, for styling with external CSS.
15842
+
15843
+ The following tags are mapped to their name prefixed with `"tok-"`
15844
+ (for example `"tok-comment"`):
15845
+
15846
+ * [`link`](#highlight.tags.link)
15847
+ * [`heading`](#highlight.tags.heading)
15848
+ * [`emphasis`](#highlight.tags.emphasis)
15849
+ * [`strong`](#highlight.tags.strong)
15850
+ * [`keyword`](#highlight.tags.keyword)
15851
+ * [`atom`](#highlight.tags.atom)
15852
+ * [`bool`](#highlight.tags.bool)
15853
+ * [`url`](#highlight.tags.url)
15854
+ * [`labelName`](#highlight.tags.labelName)
15855
+ * [`inserted`](#highlight.tags.inserted)
15856
+ * [`deleted`](#highlight.tags.deleted)
15857
+ * [`literal`](#highlight.tags.literal)
15858
+ * [`string`](#highlight.tags.string)
15859
+ * [`number`](#highlight.tags.number)
15860
+ * [`variableName`](#highlight.tags.variableName)
15861
+ * [`typeName`](#highlight.tags.typeName)
15862
+ * [`namespace`](#highlight.tags.namespace)
15863
+ * [`className`](#highlight.tags.className)
15864
+ * [`macroName`](#highlight.tags.macroName)
15865
+ * [`propertyName`](#highlight.tags.propertyName)
15866
+ * [`operator`](#highlight.tags.operator)
15867
+ * [`comment`](#highlight.tags.comment)
15868
+ * [`meta`](#highlight.tags.meta)
15869
+ * [`punctuation`](#highlight.tags.punctuation)
15870
+ * [`invalid`](#highlight.tags.invalid)
15871
+
15872
+ In addition, these mappings are provided:
15873
+
15874
+ * [`regexp`](#highlight.tags.regexp),
15875
+ [`escape`](#highlight.tags.escape), and
15876
+ [`special`](#highlight.tags.special)[`(string)`](#highlight.tags.string)
15877
+ are mapped to `"tok-string2"`
15878
+ * [`special`](#highlight.tags.special)[`(variableName)`](#highlight.tags.variableName)
15879
+ to `"tok-variableName2"`
15880
+ * [`local`](#highlight.tags.local)[`(variableName)`](#highlight.tags.variableName)
15881
+ to `"tok-variableName tok-local"`
15882
+ * [`definition`](#highlight.tags.definition)[`(variableName)`](#highlight.tags.variableName)
15883
+ to `"tok-variableName tok-definition"`
15884
+ * [`definition`](#highlight.tags.definition)[`(propertyName)`](#highlight.tags.propertyName)
15885
+ to `"tok-propertyName tok-definition"`
15886
+ */
15564
15887
  tagHighlighter([
15565
15888
  { tag: tags.link, class: "tok-link" },
15566
15889
  { tag: tags.heading, class: "tok-heading" },
@@ -15614,6 +15937,11 @@
15614
15937
  });
15615
15938
  }
15616
15939
  /**
15940
+ Syntax node prop used to register sublangauges. Should be added to
15941
+ the top level node type for the language.
15942
+ */
15943
+ const sublanguageProp = /*@__PURE__*/new NodeProp();
15944
+ /**
15617
15945
  A language object manages parsing and per-language
15618
15946
  [metadata](https://codemirror.net/6/docs/ref/#state.EditorState.languageDataAt). Parse data is
15619
15947
  managed as a [Lezer](https://lezer.codemirror.net) tree. The class
@@ -15650,14 +15978,28 @@
15650
15978
  this.parser = parser;
15651
15979
  this.extension = [
15652
15980
  language.of(this),
15653
- EditorState.languageData.of((state, pos, side) => state.facet(languageDataFacetAt(state, pos, side)))
15981
+ EditorState.languageData.of((state, pos, side) => {
15982
+ let top = topNodeAt(state, pos, side), data = top.type.prop(languageDataProp);
15983
+ if (!data)
15984
+ return [];
15985
+ let base = state.facet(data), sub = top.type.prop(sublanguageProp);
15986
+ if (sub) {
15987
+ let innerNode = top.resolve(pos - top.from, side);
15988
+ for (let sublang of sub)
15989
+ if (sublang.test(innerNode, state)) {
15990
+ let data = state.facet(sublang.facet);
15991
+ return sublang.type == "replace" ? data : data.concat(base);
15992
+ }
15993
+ }
15994
+ return base;
15995
+ })
15654
15996
  ].concat(extraExtensions);
15655
15997
  }
15656
15998
  /**
15657
15999
  Query whether this language is active at the given position.
15658
16000
  */
15659
16001
  isActiveAt(state, pos, side = -1) {
15660
- return languageDataFacetAt(state, pos, side) == this.data;
16002
+ return topNodeAt(state, pos, side).type.prop(languageDataProp) == this.data;
15661
16003
  }
15662
16004
  /**
15663
16005
  Find the document regions that were parsed using this language.
@@ -15712,16 +16054,14 @@
15712
16054
  @internal
15713
16055
  */
15714
16056
  Language.setState = /*@__PURE__*/StateEffect.define();
15715
- function languageDataFacetAt(state, pos, side) {
15716
- let topLang = state.facet(language);
15717
- if (!topLang)
15718
- return null;
15719
- let facet = topLang.data;
15720
- if (topLang.allowsNesting) {
15721
- for (let node = syntaxTree(state).topNode; node; node = node.enter(pos, side, IterMode.ExcludeBuffers))
15722
- facet = node.type.prop(languageDataProp) || facet;
16057
+ function topNodeAt(state, pos, side) {
16058
+ let topLang = state.facet(language), tree = syntaxTree(state).topNode;
16059
+ if (!topLang || topLang.allowsNesting) {
16060
+ for (let node = tree; node; node = node.enter(pos, side, IterMode.ExcludeBuffers))
16061
+ if (node.type.isTop)
16062
+ tree = node;
15723
16063
  }
15724
- return facet;
16064
+ return tree;
15725
16065
  }
15726
16066
  /**
15727
16067
  A subclass of [`Language`](https://codemirror.net/6/docs/ref/#language.Language) for use with Lezer
@@ -15763,13 +16103,13 @@
15763
16103
  }
15764
16104
  // Lezer-style Input object for a Text document.
15765
16105
  class DocInput {
15766
- constructor(doc, length = doc.length) {
16106
+ constructor(doc) {
15767
16107
  this.doc = doc;
15768
- this.length = length;
15769
16108
  this.cursorPos = 0;
15770
16109
  this.string = "";
15771
16110
  this.cursor = doc.iter();
15772
16111
  }
16112
+ get length() { return this.doc.length; }
15773
16113
  syncTo(pos) {
15774
16114
  this.string = this.cursor.next(pos - this.cursorPos).value;
15775
16115
  this.cursorPos = pos + this.string.length;
@@ -16217,17 +16557,18 @@
16217
16557
  */
16218
16558
  const indentService = /*@__PURE__*/Facet.define();
16219
16559
  /**
16220
- Facet for overriding the unit by which indentation happens.
16221
- Should be a string consisting either entirely of spaces or
16222
- entirely of tabs. When not set, this defaults to 2 spaces.
16560
+ Facet for overriding the unit by which indentation happens. Should
16561
+ be a string consisting either entirely of the same whitespace
16562
+ character. When not set, this defaults to 2 spaces.
16223
16563
  */
16224
16564
  const indentUnit = /*@__PURE__*/Facet.define({
16225
16565
  combine: values => {
16226
16566
  if (!values.length)
16227
16567
  return " ";
16228
- if (!/^(?: +|\t+)$/.test(values[0]))
16568
+ let unit = values[0];
16569
+ if (!unit || /\S/.test(unit) || Array.from(unit).some(e => e != unit[0]))
16229
16570
  throw new Error("Invalid indent unit: " + JSON.stringify(values[0]));
16230
- return values[0];
16571
+ return unit;
16231
16572
  }
16232
16573
  });
16233
16574
  /**
@@ -16247,14 +16588,16 @@
16247
16588
  tabs.
16248
16589
  */
16249
16590
  function indentString(state, cols) {
16250
- let result = "", ts = state.tabSize;
16251
- if (state.facet(indentUnit).charCodeAt(0) == 9)
16591
+ let result = "", ts = state.tabSize, ch = state.facet(indentUnit)[0];
16592
+ if (ch == "\t") {
16252
16593
  while (cols >= ts) {
16253
16594
  result += "\t";
16254
16595
  cols -= ts;
16255
16596
  }
16597
+ ch = " ";
16598
+ }
16256
16599
  for (let i = 0; i < cols; i++)
16257
- result += " ";
16600
+ result += ch;
16258
16601
  return result;
16259
16602
  }
16260
16603
  /**
@@ -17307,7 +17650,7 @@
17307
17650
  if available, otherwise falling back to block comments.
17308
17651
  */
17309
17652
  const toggleComment = target => {
17310
- let config = getConfig(target.state);
17653
+ let { state } = target, line = state.doc.lineAt(state.selection.main.from), config = getConfig(target.state, line.from);
17311
17654
  return config.line ? toggleLineComment(target) : config.block ? toggleBlockCommentByLine(target) : false;
17312
17655
  };
17313
17656
  function command(f, option) {
@@ -17340,7 +17683,7 @@
17340
17683
  block comments.
17341
17684
  */
17342
17685
  const toggleBlockCommentByLine = /*@__PURE__*/command((o, s) => changeBlockComment(o, s, selectedLineRanges(s)), 0 /* CommentOption.Toggle */);
17343
- function getConfig(state, pos = state.selection.main.head) {
17686
+ function getConfig(state, pos) {
17344
17687
  let data = state.languageDataAt("commentTokens", pos);
17345
17688
  return data.length ? data[0] : {};
17346
17689
  }
@@ -17422,13 +17765,13 @@
17422
17765
  let prevLine = -1;
17423
17766
  for (let { from, to } of ranges) {
17424
17767
  let startI = lines.length, minIndent = 1e9;
17768
+ let token = getConfig(state, from).line;
17769
+ if (!token)
17770
+ continue;
17425
17771
  for (let pos = from; pos <= to;) {
17426
17772
  let line = state.doc.lineAt(pos);
17427
17773
  if (line.from > prevLine && (from == to || to > line.from)) {
17428
17774
  prevLine = line.from;
17429
- let token = getConfig(state, pos).line;
17430
- if (!token)
17431
- continue;
17432
17775
  let indent = /^\s*/.exec(line.text)[0].length;
17433
17776
  let empty = indent == line.length;
17434
17777
  let comment = line.text.slice(indent, indent + token.length) == token ? indent : -1;
@@ -17910,21 +18253,41 @@
17910
18253
  Move the selection one line down.
17911
18254
  */
17912
18255
  const cursorLineDown = view => cursorByLine(view, true);
17913
- function pageHeight(view) {
17914
- return Math.max(view.defaultLineHeight, Math.min(view.dom.clientHeight, innerHeight) - 5);
18256
+ function pageInfo(view) {
18257
+ let selfScroll = view.scrollDOM.clientHeight < view.scrollDOM.scrollHeight - 2;
18258
+ let marginTop = 0, marginBottom = 0, height;
18259
+ if (selfScroll) {
18260
+ for (let source of view.state.facet(EditorView.scrollMargins)) {
18261
+ let margins = source(view);
18262
+ if (margins === null || margins === void 0 ? void 0 : margins.top)
18263
+ marginTop = Math.max(margins === null || margins === void 0 ? void 0 : margins.top, marginTop);
18264
+ if (margins === null || margins === void 0 ? void 0 : margins.bottom)
18265
+ marginBottom = Math.max(margins === null || margins === void 0 ? void 0 : margins.bottom, marginBottom);
18266
+ }
18267
+ height = view.scrollDOM.clientHeight - marginTop - marginBottom;
18268
+ }
18269
+ else {
18270
+ height = (view.dom.ownerDocument.defaultView || window).innerHeight;
18271
+ }
18272
+ return { marginTop, marginBottom, selfScroll,
18273
+ height: Math.max(view.defaultLineHeight, height - 5) };
17915
18274
  }
17916
18275
  function cursorByPage(view, forward) {
18276
+ let page = pageInfo(view);
17917
18277
  let { state } = view, selection = updateSel(state.selection, range => {
17918
- return range.empty ? view.moveVertically(range, forward, pageHeight(view)) : rangeEnd(range, forward);
18278
+ return range.empty ? view.moveVertically(range, forward, page.height)
18279
+ : rangeEnd(range, forward);
17919
18280
  });
17920
18281
  if (selection.eq(state.selection))
17921
18282
  return false;
17922
- let startPos = view.coordsAtPos(state.selection.main.head);
17923
- let scrollRect = view.scrollDOM.getBoundingClientRect();
17924
18283
  let effect;
17925
- if (startPos && startPos.top > scrollRect.top && startPos.bottom < scrollRect.bottom &&
17926
- startPos.top - scrollRect.top <= view.scrollDOM.scrollHeight - view.scrollDOM.scrollTop - view.scrollDOM.clientHeight)
17927
- effect = EditorView.scrollIntoView(selection.main.head, { y: "start", yMargin: startPos.top - scrollRect.top });
18284
+ if (page.selfScroll) {
18285
+ let startPos = view.coordsAtPos(state.selection.main.head);
18286
+ let scrollRect = view.scrollDOM.getBoundingClientRect();
18287
+ let scrollTop = scrollRect.top + page.marginTop, scrollBottom = scrollRect.bottom - page.marginBottom;
18288
+ if (startPos && startPos.top > scrollTop && startPos.bottom < scrollBottom)
18289
+ effect = EditorView.scrollIntoView(selection.main.head, { y: "start", yMargin: startPos.top - scrollTop });
18290
+ }
17928
18291
  view.dispatch(setSel(state, selection), { effects: effect });
17929
18292
  return true;
17930
18293
  }
@@ -18051,7 +18414,7 @@
18051
18414
  */
18052
18415
  const selectLineDown = view => selectByLine(view, true);
18053
18416
  function selectByPage(view, forward) {
18054
- return extendSel(view, range => view.moveVertically(range, forward, pageHeight(view)));
18417
+ return extendSel(view, range => view.moveVertically(range, forward, pageInfo(view).height));
18055
18418
  }
18056
18419
  /**
18057
18420
  Move the selection head one page up.
@@ -19072,9 +19435,6 @@
19072
19435
  `-`, document percentages suffixed with `%`, and an optional
19073
19436
  column position by adding `:` and a second number after the line
19074
19437
  number.
19075
-
19076
- The dialog can be styled with the `panel.gotoLine` theme
19077
- selector.
19078
19438
  */
19079
19439
  const gotoLine = view => {
19080
19440
  let panel = getPanel(view, createLineDialog);
@@ -19261,7 +19621,8 @@
19261
19621
  caseSensitive: false,
19262
19622
  literal: false,
19263
19623
  wholeWord: false,
19264
- createPanel: view => new SearchPanel(view)
19624
+ createPanel: view => new SearchPanel(view),
19625
+ scrollToMatch: range => EditorView.scrollIntoView(range)
19265
19626
  });
19266
19627
  }
19267
19628
  });
@@ -19519,10 +19880,11 @@
19519
19880
  let next = query.nextMatch(view.state, to, to);
19520
19881
  if (!next)
19521
19882
  return false;
19883
+ let selection = EditorSelection.single(next.from, next.to);
19884
+ let config = view.state.facet(searchConfigFacet);
19522
19885
  view.dispatch({
19523
- selection: { anchor: next.from, head: next.to },
19524
- scrollIntoView: true,
19525
- effects: announceMatch(view, next),
19886
+ selection,
19887
+ effects: [announceMatch(view, next), config.scrollToMatch(selection.main)],
19526
19888
  userEvent: "select.search"
19527
19889
  });
19528
19890
  return true;
@@ -19534,13 +19896,14 @@
19534
19896
  */
19535
19897
  const findPrevious = /*@__PURE__*/searchCommand((view, { query }) => {
19536
19898
  let { state } = view, { from } = state.selection.main;
19537
- let range = query.prevMatch(state, from, from);
19538
- if (!range)
19899
+ let prev = query.prevMatch(state, from, from);
19900
+ if (!prev)
19539
19901
  return false;
19902
+ let selection = EditorSelection.single(prev.from, prev.to);
19903
+ let config = view.state.facet(searchConfigFacet);
19540
19904
  view.dispatch({
19541
- selection: { anchor: range.from, head: range.to },
19542
- scrollIntoView: true,
19543
- effects: announceMatch(view, range),
19905
+ selection,
19906
+ effects: [announceMatch(view, prev), config.scrollToMatch(selection.main)],
19544
19907
  userEvent: "select.search"
19545
19908
  });
19546
19909
  return true;
@@ -19591,22 +19954,21 @@
19591
19954
  if (!next)
19592
19955
  return false;
19593
19956
  let changes = [], selection, replacement;
19594
- let announce = [];
19957
+ let effects = [];
19595
19958
  if (next.from == from && next.to == to) {
19596
19959
  replacement = state.toText(query.getReplacement(next));
19597
19960
  changes.push({ from: next.from, to: next.to, insert: replacement });
19598
19961
  next = query.nextMatch(state, next.from, next.to);
19599
- announce.push(EditorView.announce.of(state.phrase("replaced match on line $", state.doc.lineAt(from).number) + "."));
19962
+ effects.push(EditorView.announce.of(state.phrase("replaced match on line $", state.doc.lineAt(from).number) + "."));
19600
19963
  }
19601
19964
  if (next) {
19602
19965
  let off = changes.length == 0 || changes[0].from >= next.to ? 0 : next.to - next.from - replacement.length;
19603
- selection = { anchor: next.from - off, head: next.to - off };
19604
- announce.push(announceMatch(view, next));
19966
+ selection = EditorSelection.single(next.from - off, next.to - off);
19967
+ effects.push(announceMatch(view, next));
19968
+ effects.push(state.facet(searchConfigFacet).scrollToMatch(selection.main));
19605
19969
  }
19606
19970
  view.dispatch({
19607
- changes, selection,
19608
- scrollIntoView: !!selection,
19609
- effects: announce,
19971
+ changes, selection, effects,
19610
19972
  userEvent: "input.replace"
19611
19973
  });
19612
19974
  return true;
@@ -19990,9 +20352,12 @@
19990
20352
  */
19991
20353
  function ifNotIn(nodes, source) {
19992
20354
  return (context) => {
19993
- for (let pos = syntaxTree(context.state).resolveInner(context.pos, -1); pos; pos = pos.parent)
20355
+ for (let pos = syntaxTree(context.state).resolveInner(context.pos, -1); pos; pos = pos.parent) {
19994
20356
  if (nodes.indexOf(pos.name) > -1)
19995
20357
  return null;
20358
+ if (pos.type.isTop)
20359
+ break;
20360
+ }
19996
20361
  return source(context);
19997
20362
  };
19998
20363
  }
@@ -20097,13 +20462,18 @@
20097
20462
  // For single-character queries, only match when they occur right
20098
20463
  // at the start
20099
20464
  if (chars.length == 1) {
20100
- let first = codePointAt(word, 0);
20101
- return first == chars[0] ? [0, 0, codePointSize(first)]
20102
- : first == folded[0] ? [-200 /* Penalty.CaseFold */, 0, codePointSize(first)] : null;
20465
+ let first = codePointAt(word, 0), firstSize = codePointSize(first);
20466
+ let score = firstSize == word.length ? 0 : -100 /* Penalty.NotFull */;
20467
+ if (first == chars[0]) ;
20468
+ else if (first == folded[0])
20469
+ score += -200 /* Penalty.CaseFold */;
20470
+ else
20471
+ return null;
20472
+ return [score, 0, firstSize];
20103
20473
  }
20104
20474
  let direct = word.indexOf(this.pattern);
20105
20475
  if (direct == 0)
20106
- return [0, 0, this.pattern.length];
20476
+ return [word.length == this.pattern.length ? 0 : -100 /* Penalty.NotFull */, 0, this.pattern.length];
20107
20477
  let len = chars.length, anyTo = 0;
20108
20478
  if (direct < 0) {
20109
20479
  for (let i = 0, e = Math.min(word.length, 200); i < e && anyTo < len;) {
@@ -20159,7 +20529,7 @@
20159
20529
  if (byWordTo == len && byWord[0] == 0 && wordAdjacent)
20160
20530
  return this.result(-100 /* Penalty.ByWord */ + (byWordFolded ? -200 /* Penalty.CaseFold */ : 0), byWord, word);
20161
20531
  if (adjacentTo == len && adjacentStart == 0)
20162
- return [-200 /* Penalty.CaseFold */ - word.length, 0, adjacentEnd];
20532
+ return [-200 /* Penalty.CaseFold */ - word.length + (adjacentEnd == word.length ? 0 : -100 /* Penalty.NotFull */), 0, adjacentEnd];
20163
20533
  if (direct > -1)
20164
20534
  return [-700 /* Penalty.NotStart */ - word.length, direct, direct + this.pattern.length];
20165
20535
  if (adjacentTo == len)
@@ -21555,7 +21925,8 @@
21555
21925
  }
21556
21926
  update(update) {
21557
21927
  let config = update.state.facet(lintConfig);
21558
- if (update.docChanged || config != update.startState.facet(lintConfig)) {
21928
+ if (update.docChanged || config != update.startState.facet(lintConfig) ||
21929
+ config.needsRefresh && config.needsRefresh(update)) {
21559
21930
  this.lintTime = Date.now() + config.delay;
21560
21931
  if (!this.set) {
21561
21932
  this.set = true;
@@ -21578,7 +21949,10 @@
21578
21949
  return Object.assign({ sources: input.map(i => i.source) }, combineConfig(input.map(i => i.config), {
21579
21950
  delay: 750,
21580
21951
  markerFilter: null,
21581
- tooltipFilter: null
21952
+ tooltipFilter: null,
21953
+ needsRefresh: null
21954
+ }, {
21955
+ needsRefresh: (a, b) => !a ? b : !b ? a : u => a(u) || b(u)
21582
21956
  }));
21583
21957
  },
21584
21958
  enables: lintPlugin
@@ -21602,8 +21976,11 @@
21602
21976
  var _a;
21603
21977
  let keys = inPanel ? assignKeys(diagnostic.actions) : [];
21604
21978
  return crelt("li", { class: "cm-diagnostic cm-diagnostic-" + diagnostic.severity }, crelt("span", { class: "cm-diagnosticText" }, diagnostic.renderMessage ? diagnostic.renderMessage() : diagnostic.message), (_a = diagnostic.actions) === null || _a === void 0 ? void 0 : _a.map((action, i) => {
21605
- let click = (e) => {
21979
+ let fired = false, click = (e) => {
21606
21980
  e.preventDefault();
21981
+ if (fired)
21982
+ return;
21983
+ fired = true;
21607
21984
  let found = findDiagnostic(view.state.field(lintState).diagnostics, diagnostic);
21608
21985
  if (found)
21609
21986
  action.apply(view, found.from, found.to);
@@ -21830,7 +22207,8 @@
21830
22207
  backgroundColor: "#444",
21831
22208
  color: "white",
21832
22209
  borderRadius: "3px",
21833
- marginLeft: "8px"
22210
+ marginLeft: "8px",
22211
+ cursor: "pointer"
21834
22212
  },
21835
22213
  ".cm-diagnosticSource": {
21836
22214
  fontSize: "70%",
@@ -24535,6 +24913,7 @@
24535
24913
  this.headerRenderer = headerRenderer;
24536
24914
  this.cellRenderer = cellRenderer;
24537
24915
 
24916
+ this.classList.add('resize-table');
24538
24917
  this.style.tableLayout = 'auto';
24539
24918
  this.style.width = '100%';
24540
24919
 
@@ -24870,9 +25249,10 @@
24870
25249
 
24871
25250
  function init (parent, onSubmit, onShiftSubmit) {
24872
25251
  addEventListener('#query-tab-button', 'click', (event) => selectTab(event, 'query'));
25252
+ addEventListener('#graph-tab-button', 'click', (event) => selectTab(event, 'graph'));
24873
25253
  addEventListener('#saved-tab-button', 'click', (event) => selectTab(event, 'saved'));
24874
25254
  addEventListener('#structure-tab-button', 'click', (event) => selectTab(event, 'structure'));
24875
- addEventListener('#graph-tab-button', 'click', (event) => selectTab(event, 'graph'));
25255
+ addEventListener('#help-tab-button', 'click', (event) => selectTab(event, 'help'));
24876
25256
  addEventListener('#cancel-button', 'click', () => clearResult());
24877
25257
 
24878
25258
  addEventListener('#query-box', 'click', () => {
@@ -25046,7 +25426,7 @@
25046
25426
 
25047
25427
  function getTabFromUrl (url) {
25048
25428
  const match = url.pathname.match(/\/([^/]+)$/);
25049
- if (match && ['query', 'graph', 'structure', 'saved'].includes(match[1])) {
25429
+ if (match && ['query', 'graph', 'saved', 'structure', 'help'].includes(match[1])) {
25050
25430
  return match[1]
25051
25431
  } else {
25052
25432
  throw new Error(`invalid tab: ${url.pathname}`)
@@ -25055,14 +25435,16 @@
25055
25435
 
25056
25436
  function updateTabs () {
25057
25437
  const url = new URL(window.location);
25438
+ setActionInUrl(url, 'query');
25439
+ document.getElementById('query-tab-button').href = url.pathname + url.search;
25058
25440
  setActionInUrl(url, 'graph');
25059
25441
  document.getElementById('graph-tab-button').href = url.pathname + url.search;
25060
25442
  setActionInUrl(url, 'saved');
25061
25443
  document.getElementById('saved-tab-button').href = url.pathname + url.search;
25062
25444
  setActionInUrl(url, 'structure');
25063
25445
  document.getElementById('structure-tab-button').href = url.pathname + url.search;
25064
- setActionInUrl(url, 'query');
25065
- document.getElementById('query-tab-button').href = url.pathname + url.search;
25446
+ setActionInUrl(url, 'help');
25447
+ document.getElementById('help-tab-button').href = url.pathname + url.search;
25066
25448
  }
25067
25449
 
25068
25450
  function selectTab (event, tab) {
@@ -25122,11 +25504,31 @@
25122
25504
  case 'structure':
25123
25505
  selectStructureTab();
25124
25506
  break
25507
+ case 'help':
25508
+ selectHelpTab();
25509
+ break
25125
25510
  default:
25126
25511
  throw new Error(`Unexpected tab: ${window.tab}`)
25127
25512
  }
25128
25513
  }
25129
25514
 
25515
+ function statsHtml (info) {
25516
+ const hidden = info == null;
25517
+ info ||= {};
25518
+ return `
25519
+ <table ${hidden ? 'style="visibility: hidden;"' : ''}>
25520
+ <tr><td>created:</td><td>${valueOrNullHtml(info.created_at)}</td></tr>
25521
+ <tr><td>updated:</td><td>${valueOrNullHtml(info.updated_at)}</td></tr>
25522
+ <tr><td>data size:</td><td>${valueOrNullHtml(info.data_size)}</td></tr>
25523
+ <tr><td>index size:</td><td>${valueOrNullHtml(info.index_size)}</td></tr>
25524
+ <tr><td>rows:</td><td>${valueOrNullHtml(info.rows)}</td></tr>
25525
+ <tr><td>row size:</td><td>${valueOrNullHtml(info.average_row_size)}</td></tr>
25526
+ <tr><td>encoding:</td><td>${valueOrNullHtml(info.encoding)}</td></tr>
25527
+ <tr><td>auto increment:</td><td>${valueOrNullHtml(info.auto_increment)}</td></tr>
25528
+ </table>
25529
+ `
25530
+ }
25531
+
25130
25532
  function selectStructureTab () {
25131
25533
  Array.prototype.forEach.call(document.getElementsByClassName('structure-element'), function (selected) {
25132
25534
  selected.style.display = 'flex';
@@ -25138,6 +25540,9 @@
25138
25540
 
25139
25541
  const schemasElement = document.getElementById('schemas');
25140
25542
  const tablesElement = document.getElementById('tables');
25543
+ const statsElement = document.getElementById('stats');
25544
+ statsElement.innerHTML = statsHtml(null);
25545
+
25141
25546
  const columnsElement = document.getElementById('columns');
25142
25547
  const indexesElement = document.getElementById('indexes');
25143
25548
 
@@ -25166,6 +25571,10 @@
25166
25571
  schemasElement.appendChild(optionElement);
25167
25572
  });
25168
25573
  schemasElement.addEventListener('change', function () {
25574
+ while (statsElement.firstChild) {
25575
+ statsElement.removeChild(statsElement.firstChild);
25576
+ }
25577
+ statsElement.innerHTML = statsHtml(null);
25169
25578
  while (tablesElement.firstChild) {
25170
25579
  tablesElement.removeChild(tablesElement.firstChild);
25171
25580
  }
@@ -25187,6 +25596,9 @@
25187
25596
  });
25188
25597
  }
25189
25598
  tablesElement.addEventListener('change', function () {
25599
+ while (statsElement.firstChild) {
25600
+ statsElement.removeChild(statsElement.firstChild);
25601
+ }
25190
25602
  while (columnsElement.firstChild) {
25191
25603
  columnsElement.removeChild(columnsElement.firstChild);
25192
25604
  }
@@ -25196,7 +25608,9 @@
25196
25608
  const schemaName = schemaNames.length === 1 ? schemaNames[0] : schemasElement.value;
25197
25609
  const tableName = tablesElement.value;
25198
25610
  const table = window.metadata.schemas[schemaName].tables[tableName];
25611
+ const info = table.info;
25199
25612
 
25613
+ statsElement.innerHTML = statsHtml(info);
25200
25614
  const columnEntries = Object.entries(table.columns);
25201
25615
  if (columnEntries.length > 0) {
25202
25616
  const columns = Object.keys(columnEntries[0][1]);
@@ -25242,6 +25656,10 @@
25242
25656
  window.structureLoaded = true;
25243
25657
  }
25244
25658
 
25659
+ function selectHelpTab () {
25660
+ document.getElementById('help-box').style.display = 'block';
25661
+ }
25662
+
25245
25663
  function selectGraphTab (internal) {
25246
25664
  document.getElementById('query-box').style.display = 'flex';
25247
25665
  document.getElementById('submit-box').style.display = 'flex';
@@ -25284,7 +25702,7 @@
25284
25702
  viewUrl.searchParams.set('file', file.filename);
25285
25703
 
25286
25704
  const viewLinkElement = document.createElement('a');
25287
- viewLinkElement.classList.add('view-link');
25705
+ viewLinkElement.classList.add('link', 'view-link');
25288
25706
  viewLinkElement.innerText = 'view';
25289
25707
  viewLinkElement.href = viewUrl.pathname + viewUrl.search;
25290
25708
  addEventListener(viewLinkElement, 'click', (event) => {
@@ -25298,7 +25716,7 @@
25298
25716
  runUrl.searchParams.set('run', 'true');
25299
25717
 
25300
25718
  const runLinkElement = document.createElement('a');
25301
- runLinkElement.classList.add('run-link');
25719
+ runLinkElement.classList.add('link', 'run-link');
25302
25720
  runLinkElement.innerText = 'run';
25303
25721
  runLinkElement.href = runUrl.pathname + runUrl.search;
25304
25722
  addEventListener(runLinkElement, 'click', (event) => {
@@ -25309,25 +25727,31 @@
25309
25727
 
25310
25728
  const nameElement = document.createElement('h2');
25311
25729
  nameElement.innerText = file.filename;
25730
+ nameElement.classList.add('name');
25312
25731
 
25313
- const nameAndLinksElement = document.createElement('div');
25314
- nameAndLinksElement.classList.add('name-and-links');
25315
- nameAndLinksElement.appendChild(nameElement);
25316
- nameAndLinksElement.appendChild(viewLinkElement);
25317
- nameAndLinksElement.appendChild(runLinkElement);
25732
+ const linksElement = document.createElement('div');
25733
+ linksElement.classList.add('links');
25734
+ linksElement.appendChild(viewLinkElement);
25735
+ linksElement.appendChild(runLinkElement);
25318
25736
 
25319
25737
  const descriptionElement = document.createElement('p');
25320
25738
  descriptionElement.innerText = file.description;
25739
+ descriptionElement.classList.add('description');
25321
25740
 
25322
25741
  const divElement = document.createElement('div');
25323
25742
  divElement.classList.add('saved-list-item');
25324
- divElement.appendChild(nameAndLinksElement);
25743
+ divElement.appendChild(nameElement);
25744
+ divElement.appendChild(linksElement);
25325
25745
  divElement.appendChild(descriptionElement);
25326
25746
 
25327
25747
  savedElement.appendChild(divElement);
25328
25748
  });
25329
25749
  }
25330
25750
 
25751
+ function valueOrNullHtml (value) {
25752
+ return value == null ? '<span style="color: #888">null</span>' : value
25753
+ }
25754
+
25331
25755
  function submitAll (target, event) {
25332
25756
  submit(target, event);
25333
25757
  }
@@ -25973,6 +26397,12 @@
25973
26397
  }
25974
26398
  });
25975
26399
 
26400
+ document.addEventListener('keydown', (event) => {
26401
+ if (event.code === 'Escape') {
26402
+ focus();
26403
+ }
26404
+ });
26405
+
25976
26406
  window.onload = function () {
25977
26407
  Promise.all([
25978
26408
  google.charts.load('current', { packages: ['corechart', 'line'] }),