@codemirror/view 0.19.21 → 0.19.25

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1082,8 +1082,9 @@ class Decoration extends RangeValue {
1082
1082
  position.
1083
1083
  */
1084
1084
  static widget(spec) {
1085
- let side = spec.side || 0;
1086
- return new PointDecoration(spec, side, side, !!spec.block, spec.widget || null, false);
1085
+ let side = spec.side || 0, block = !!spec.block;
1086
+ side += block ? (side > 0 ? 300000000 /* BlockAfter */ : -400000000 /* BlockBefore */) : (side > 0 ? 100000000 /* InlineAfter */ : -100000000 /* InlineBefore */);
1087
+ return new PointDecoration(spec, side, side, block, spec.widget || null, false);
1087
1088
  }
1088
1089
  /**
1089
1090
  Create a replace decoration which replaces the given range with
@@ -1092,8 +1093,8 @@ class Decoration extends RangeValue {
1092
1093
  static replace(spec) {
1093
1094
  let block = !!spec.block;
1094
1095
  let { start, end } = getInclusive(spec, block);
1095
- let startSide = 100000000 /* Big */ * (start ? -1 : 1) * (block ? 2 : 1);
1096
- let endSide = 100000000 /* Big */ * (end ? 1 : -1) * (block ? 2 : 1);
1096
+ let startSide = block ? (start ? -300000000 /* BlockIncStart */ : -1 /* InlineIncStart */) : 400000000 /* NonIncStart */;
1097
+ let endSide = block ? (end ? 200000000 /* BlockIncEnd */ : 1 /* InlineIncEnd */) : -500000000 /* NonIncEnd */;
1097
1098
  return new PointDecoration(spec, startSide, endSide, block, spec.widget || null, true);
1098
1099
  }
1099
1100
  /**
@@ -1123,7 +1124,7 @@ Decoration.none = RangeSet.empty;
1123
1124
  class MarkDecoration extends Decoration {
1124
1125
  constructor(spec) {
1125
1126
  let { start, end } = getInclusive(spec);
1126
- super(100000000 /* Big */ * (start ? -1 : 1), 100000000 /* Big */ * (end ? 1 : -1), null, spec);
1127
+ super(start ? -1 /* InlineIncStart */ : 400000000 /* NonIncStart */, end ? 1 /* InlineIncEnd */ : -500000000 /* NonIncEnd */, null, spec);
1127
1128
  this.tagName = spec.tagName || "span";
1128
1129
  this.class = spec.class || "";
1129
1130
  this.attrs = spec.attributes || null;
@@ -1144,7 +1145,7 @@ class MarkDecoration extends Decoration {
1144
1145
  MarkDecoration.prototype.point = false;
1145
1146
  class LineDecoration extends Decoration {
1146
1147
  constructor(spec) {
1147
- super(-100000000 /* Big */, -100000000 /* Big */, null, spec);
1148
+ super(-200000000 /* Line */, -200000000 /* Line */, null, spec);
1148
1149
  }
1149
1150
  eq(other) {
1150
1151
  return other instanceof LineDecoration && attrsEq(this.spec.attributes, other.spec.attributes);
@@ -1723,36 +1724,39 @@ class PluginInstance {
1723
1724
  this.value = null;
1724
1725
  }
1725
1726
  takeField(type, target) {
1726
- for (let { field, get } of this.spec.fields)
1727
- if (field == type)
1728
- target.push(get(this.value));
1727
+ if (this.spec)
1728
+ for (let { field, get } of this.spec.fields)
1729
+ if (field == type)
1730
+ target.push(get(this.value));
1729
1731
  }
1730
1732
  update(view) {
1731
1733
  if (!this.value) {
1732
- try {
1733
- this.value = this.spec.create(view);
1734
- }
1735
- catch (e) {
1736
- logException(view.state, e, "CodeMirror plugin crashed");
1737
- return PluginInstance.dummy;
1734
+ if (this.spec) {
1735
+ try {
1736
+ this.value = this.spec.create(view);
1737
+ }
1738
+ catch (e) {
1739
+ logException(view.state, e, "CodeMirror plugin crashed");
1740
+ this.deactivate();
1741
+ }
1738
1742
  }
1739
1743
  }
1740
1744
  else if (this.mustUpdate) {
1741
1745
  let update = this.mustUpdate;
1742
1746
  this.mustUpdate = null;
1743
- if (!this.value.update)
1744
- return this;
1745
- try {
1746
- this.value.update(update);
1747
- }
1748
- catch (e) {
1749
- logException(update.state, e, "CodeMirror plugin crashed");
1750
- if (this.value.destroy)
1751
- try {
1752
- this.value.destroy();
1753
- }
1754
- catch (_) { }
1755
- return PluginInstance.dummy;
1747
+ if (this.value.update) {
1748
+ try {
1749
+ this.value.update(update);
1750
+ }
1751
+ catch (e) {
1752
+ logException(update.state, e, "CodeMirror plugin crashed");
1753
+ if (this.value.destroy)
1754
+ try {
1755
+ this.value.destroy();
1756
+ }
1757
+ catch (_) { }
1758
+ this.deactivate();
1759
+ }
1756
1760
  }
1757
1761
  }
1758
1762
  return this;
@@ -1768,20 +1772,12 @@ class PluginInstance {
1768
1772
  }
1769
1773
  }
1770
1774
  }
1775
+ deactivate() {
1776
+ this.spec = this.value = null;
1777
+ }
1771
1778
  }
1772
- PluginInstance.dummy = /*@__PURE__*/new PluginInstance(/*@__PURE__*/ViewPlugin.define(() => ({})));
1773
- function combineFacetAttrs(values) {
1774
- let result = {};
1775
- for (let i = values.length - 1; i >= 0; i--)
1776
- combineAttrs(values[i], result);
1777
- return result;
1778
- }
1779
- const editorAttributes = /*@__PURE__*/Facet.define({
1780
- combine: combineFacetAttrs
1781
- });
1782
- const contentAttributes = /*@__PURE__*/Facet.define({
1783
- combine: combineFacetAttrs
1784
- });
1779
+ const editorAttributes = /*@__PURE__*/Facet.define();
1780
+ const contentAttributes = /*@__PURE__*/Facet.define();
1785
1781
  // Provide decorations
1786
1782
  const decorations = /*@__PURE__*/Facet.define();
1787
1783
  const styleModule = /*@__PURE__*/Facet.define();
@@ -1908,7 +1904,7 @@ class ViewUpdate {
1908
1904
  Whether the document changed in this update.
1909
1905
  */
1910
1906
  get docChanged() {
1911
- return this.transactions.some(tr => tr.docChanged);
1907
+ return !this.changes.empty;
1912
1908
  }
1913
1909
  /**
1914
1910
  Whether the selection was explicitly set in this update.
@@ -1929,12 +1925,12 @@ class DocView extends ContentView {
1929
1925
  this.compositionDeco = Decoration.none;
1930
1926
  this.decorations = [];
1931
1927
  // Track a minimum width for the editor. When measuring sizes in
1932
- // checkLayout, this is updated to point at the width of a given
1933
- // element and its extent in the document. When a change happens in
1934
- // that range, these are reset. That way, once we've seen a
1935
- // line/element of a given length, we keep the editor wide enough to
1936
- // fit at least that element, until it is changed, at which point we
1937
- // forget it again.
1928
+ // measureVisibleLineHeights, this is updated to point at the width
1929
+ // of a given element and its extent in the document. When a change
1930
+ // happens in that range, these are reset. That way, once we've seen
1931
+ // a line/element of a given length, we keep the editor wide enough
1932
+ // to fit at least that element, until it is changed, at which point
1933
+ // we forget it again.
1938
1934
  this.minWidth = 0;
1939
1935
  this.minWidthFrom = 0;
1940
1936
  this.minWidthTo = 0;
@@ -1984,10 +1980,7 @@ class DocView extends ContentView {
1984
1980
  let prevDeco = this.decorations, deco = this.updateDeco();
1985
1981
  let decoDiff = findChangedDeco(prevDeco, deco, update.changes);
1986
1982
  changedRanges = ChangedRange.extendWithRanges(changedRanges, decoDiff);
1987
- if (this.dirty == 0 /* Not */ && changedRanges.length == 0 &&
1988
- !(update.flags & 4 /* Viewport */) &&
1989
- update.state.selection.main.from >= this.view.viewport.from &&
1990
- update.state.selection.main.to <= this.view.viewport.to) {
1983
+ if (this.dirty == 0 /* Not */ && changedRanges.length == 0) {
1991
1984
  return false;
1992
1985
  }
1993
1986
  else {
@@ -2007,9 +2000,10 @@ class DocView extends ContentView {
2007
2000
  this.updateSelection();
2008
2001
  }
2009
2002
  }
2010
- // Used both by update and checkLayout do perform the actual DOM
2003
+ // Used by update and the constructor do perform the actual DOM
2011
2004
  // update
2012
2005
  updateInner(changes, deco, oldLength) {
2006
+ this.view.viewState.mustMeasureContent = true;
2013
2007
  this.updateChildren(changes, deco, oldLength);
2014
2008
  let { observer } = this.view;
2015
2009
  observer.ignore(() => {
@@ -2017,7 +2011,7 @@ class DocView extends ContentView {
2017
2011
  // messes with the scroll position during DOM mutation (though
2018
2012
  // no relayout is triggered and I cannot imagine how it can
2019
2013
  // recompute the scroll position without a layout)
2020
- this.dom.style.height = this.view.viewState.domHeight + "px";
2014
+ this.dom.style.height = this.view.viewState.contentHeight + "px";
2021
2015
  this.dom.style.minWidth = this.minWidth ? this.minWidth + "px" : "";
2022
2016
  // Chrome will sometimes, when DOM mutations occur directly
2023
2017
  // around the selection, get confused and report a different
@@ -2302,7 +2296,7 @@ class DocView extends ContentView {
2302
2296
  let next = i == vs.viewports.length ? null : vs.viewports[i];
2303
2297
  let end = next ? next.from - 1 : this.length;
2304
2298
  if (end > pos) {
2305
- let height = vs.lineAt(end, 0).bottom - vs.lineAt(pos, 0).top;
2299
+ let height = vs.lineBlockAt(end).bottom - vs.lineBlockAt(pos).top;
2306
2300
  deco.push(Decoration.replace({ widget: new BlockGapWidget(height), block: true, inclusive: true }).range(pos, end));
2307
2301
  }
2308
2302
  if (!next)
@@ -2908,13 +2902,14 @@ function domPosInText(node, x, y) {
2908
2902
  }
2909
2903
  function posAtCoords(view, { x, y }, precise, bias = -1) {
2910
2904
  var _a;
2911
- let content = view.contentDOM.getBoundingClientRect(), block;
2905
+ let content = view.contentDOM.getBoundingClientRect(), docTop = content.top + view.viewState.paddingTop;
2912
2906
  let halfLine = view.defaultLineHeight / 2;
2907
+ let block, yOffset = y - docTop;
2913
2908
  for (let bounced = false;;) {
2914
- block = view.blockAtHeight(y, content.top);
2915
- if (block.top > y || block.bottom < y) {
2916
- bias = block.top > y ? -1 : 1;
2917
- y = Math.min(block.bottom - halfLine, Math.max(block.top + halfLine, y));
2909
+ block = view.elementAtHeight(yOffset);
2910
+ if (block.top > yOffset || block.bottom < yOffset) {
2911
+ bias = block.top > yOffset ? -1 : 1;
2912
+ yOffset = Math.min(block.bottom - halfLine, Math.max(block.top + halfLine, yOffset));
2918
2913
  if (bounced)
2919
2914
  return precise ? null : 0;
2920
2915
  else
@@ -2922,11 +2917,12 @@ function posAtCoords(view, { x, y }, precise, bias = -1) {
2922
2917
  }
2923
2918
  if (block.type == BlockType.Text)
2924
2919
  break;
2925
- y = bias > 0 ? block.bottom + halfLine : block.top - halfLine;
2920
+ yOffset = bias > 0 ? block.bottom + halfLine : block.top - halfLine;
2926
2921
  }
2922
+ y = docTop + yOffset;
2927
2923
  let lineStart = block.from;
2928
2924
  // Clip x to the viewport sides
2929
- x = Math.max(content.left + 1, Math.min(content.right - 1, x));
2925
+ x = Math.max(content.left + 1, Math.min(Math.max(content.right, content.left + view.docView.minWidth) - 1, x));
2930
2926
  // If this is outside of the rendered viewport, we can't determine a position
2931
2927
  if (lineStart < view.viewport.from)
2932
2928
  return view.viewport.from == 0 ? 0 : posAtCoordsImprecise(view, content, block, x, y);
@@ -3036,17 +3032,17 @@ function moveVertically(view, start, forward, distance) {
3036
3032
  return EditorSelection.cursor(startPos);
3037
3033
  let goal = start.goalColumn, startY;
3038
3034
  let rect = view.contentDOM.getBoundingClientRect();
3039
- let startCoords = view.coordsAtPos(startPos);
3035
+ let startCoords = view.coordsAtPos(startPos), docTop = view.documentTop;
3040
3036
  if (startCoords) {
3041
3037
  if (goal == null)
3042
3038
  goal = startCoords.left - rect.left;
3043
3039
  startY = dir < 0 ? startCoords.top : startCoords.bottom;
3044
3040
  }
3045
3041
  else {
3046
- let line = view.viewState.lineAt(startPos, view.dom.getBoundingClientRect().top);
3042
+ let line = view.viewState.lineBlockAt(startPos - docTop);
3047
3043
  if (goal == null)
3048
3044
  goal = Math.min(rect.right - rect.left, view.defaultCharacterWidth * (startPos - line.from));
3049
- startY = dir < 0 ? line.top : line.bottom;
3045
+ startY = (dir < 0 ? line.top : line.bottom) + docTop;
3050
3046
  }
3051
3047
  let resolvedGoal = rect.left + goal;
3052
3048
  let dist = distance !== null && distance !== void 0 ? distance : (view.defaultLineHeight >> 1);
@@ -3297,7 +3293,7 @@ class MouseSelection {
3297
3293
  this.extend = startEvent.shiftKey;
3298
3294
  this.multiple = view.state.facet(EditorState.allowMultipleSelections) && addsSelectionRange(view, startEvent);
3299
3295
  this.dragMove = dragMovesSelection(view, startEvent);
3300
- this.dragging = isInPrimarySelection(view, startEvent) ? null : false;
3296
+ this.dragging = isInPrimarySelection(view, startEvent) && getClickType(startEvent) == 1 ? null : false;
3301
3297
  // When clicking outside of the selection, immediately apply the
3302
3298
  // effect of starting the selection
3303
3299
  if (this.dragging === false) {
@@ -3518,7 +3514,7 @@ function basicMouseSelection(view, event) {
3518
3514
  let last = start, lastEvent = event;
3519
3515
  return {
3520
3516
  update(update) {
3521
- if (update.changes) {
3517
+ if (update.docChanged) {
3522
3518
  if (start)
3523
3519
  start.pos = update.changes.mapPos(start.pos);
3524
3520
  startSel = startSel.map(update.changes);
@@ -3782,7 +3778,10 @@ class HeightOracle {
3782
3778
  return lines * this.lineHeight;
3783
3779
  }
3784
3780
  setDoc(doc) { this.doc = doc; return this; }
3785
- mustRefresh(lineHeights, whiteSpace, direction) {
3781
+ mustRefreshForStyle(whiteSpace, direction) {
3782
+ return (wrappingWhiteSpace.indexOf(whiteSpace) > -1) != this.lineWrapping || this.direction != direction;
3783
+ }
3784
+ mustRefreshForHeights(lineHeights) {
3786
3785
  let newHeight = false;
3787
3786
  for (let i = 0; i < lineHeights.length; i++) {
3788
3787
  let h = lineHeights[i];
@@ -3794,7 +3793,7 @@ class HeightOracle {
3794
3793
  this.heightSamples[Math.floor(h * 10)] = true;
3795
3794
  }
3796
3795
  }
3797
- return newHeight || (wrappingWhiteSpace.indexOf(whiteSpace) > -1) != this.lineWrapping || this.direction != direction;
3796
+ return newHeight;
3798
3797
  }
3799
3798
  refresh(whiteSpace, direction, lineHeight, charWidth, lineLength, knownHeights) {
3800
3799
  let lineWrapping = wrappingWhiteSpace.indexOf(whiteSpace) > -1;
@@ -3848,7 +3847,8 @@ class BlockInfo {
3848
3847
  */
3849
3848
  length,
3850
3849
  /**
3851
- The top position of the element.
3850
+ The top position of the element (relative to the top of the
3851
+ document).
3852
3852
  */
3853
3853
  top,
3854
3854
  /**
@@ -3882,13 +3882,19 @@ class BlockInfo {
3882
3882
  .concat(Array.isArray(other.type) ? other.type : [other]);
3883
3883
  return new BlockInfo(this.from, this.length + other.length, this.top, this.height + other.height, detail);
3884
3884
  }
3885
+ /**
3886
+ FIXME remove on next breaking release @internal
3887
+ */
3888
+ moveY(offset) {
3889
+ return !offset ? this : new BlockInfo(this.from, this.length, this.top + offset, this.height, Array.isArray(this.type) ? this.type.map(b => b.moveY(offset)) : this.type);
3890
+ }
3885
3891
  }
3886
3892
  var QueryType = /*@__PURE__*/(function (QueryType) {
3887
3893
  QueryType[QueryType["ByPos"] = 0] = "ByPos";
3888
3894
  QueryType[QueryType["ByHeight"] = 1] = "ByHeight";
3889
3895
  QueryType[QueryType["ByPosNoHeight"] = 2] = "ByPosNoHeight";
3890
3896
  return QueryType})(QueryType || (QueryType = {}));
3891
- const Epsilon = 1e-4;
3897
+ const Epsilon = 1e-3;
3892
3898
  class HeightMap {
3893
3899
  constructor(length, // The number of characters covered
3894
3900
  height, // Height of this part of the document
@@ -4115,22 +4121,30 @@ class HeightMapGap extends HeightMap {
4115
4121
  // can't be widgets or collapsed ranges in those lines, because
4116
4122
  // they would already have been added to the heightmap (gaps
4117
4123
  // only contain plain text).
4118
- let nodes = [], pos = Math.max(offset, measured.from);
4124
+ let nodes = [], pos = Math.max(offset, measured.from), singleHeight = -1;
4125
+ let wasChanged = oracle.heightChanged;
4119
4126
  if (measured.from > offset)
4120
4127
  nodes.push(new HeightMapGap(measured.from - offset - 1).updateHeight(oracle, offset));
4121
4128
  while (pos <= end && measured.more) {
4122
4129
  let len = oracle.doc.lineAt(pos).length;
4123
4130
  if (nodes.length)
4124
4131
  nodes.push(null);
4125
- let line = new HeightMapText(len, measured.heights[measured.index++]);
4132
+ let height = measured.heights[measured.index++];
4133
+ if (singleHeight == -1)
4134
+ singleHeight = height;
4135
+ else if (Math.abs(height - singleHeight) >= Epsilon)
4136
+ singleHeight = -2;
4137
+ let line = new HeightMapText(len, height);
4126
4138
  line.outdated = false;
4127
4139
  nodes.push(line);
4128
4140
  pos += len + 1;
4129
4141
  }
4130
4142
  if (pos <= end)
4131
4143
  nodes.push(null, new HeightMapGap(end - pos).updateHeight(oracle, pos));
4132
- oracle.heightChanged = true;
4133
- return HeightMap.of(nodes);
4144
+ let result = HeightMap.of(nodes);
4145
+ oracle.heightChanged = wasChanged || singleHeight < 0 || Math.abs(result.height - this.height) >= Epsilon ||
4146
+ Math.abs(singleHeight - this.lines(oracle.doc, offset).lineHeight) >= Epsilon;
4147
+ return result;
4134
4148
  }
4135
4149
  else if (force || this.outdated) {
4136
4150
  this.setHeight(oracle, oracle.heightForGap(offset, offset + this.length));
@@ -4488,7 +4502,8 @@ class ViewState {
4488
4502
  this.inView = true;
4489
4503
  this.paddingTop = 0;
4490
4504
  this.paddingBottom = 0;
4491
- this.contentWidth = 0;
4505
+ this.contentDOMWidth = 0;
4506
+ this.contentDOMHeight = 0;
4492
4507
  this.editorHeight = 0;
4493
4508
  this.heightOracle = new HeightOracle;
4494
4509
  // See VP.MaxDOMHeight
@@ -4496,6 +4511,9 @@ class ViewState {
4496
4511
  this.scrollTarget = null;
4497
4512
  // Briefly set to true when printing, to disable viewport limiting
4498
4513
  this.printing = false;
4514
+ // Flag set when editor content was redrawn, so that the next
4515
+ // measure stage knows it must read DOM layout
4516
+ this.mustMeasureContent = true;
4499
4517
  this.visibleRanges = [];
4500
4518
  // Cursor 'assoc' is only significant when the cursor is on a line
4501
4519
  // wrap point, where it must stick to the character that it is
@@ -4508,6 +4526,7 @@ class ViewState {
4508
4526
  this.mustEnforceCursorAssoc = false;
4509
4527
  this.heightMap = HeightMap.empty().applyChanges(state.facet(decorations), Text.empty, this.heightOracle.setDoc(state.doc), [new ChangedRange(0, 0, 0, state.doc.length)]);
4510
4528
  this.viewport = this.getViewport(0, null);
4529
+ this.updateViewportLines();
4511
4530
  this.updateForViewport();
4512
4531
  this.lineGaps = this.ensureLineGaps([]);
4513
4532
  this.lineGapDeco = Decoration.set(this.lineGaps.map(gap => gap.draw(false)));
@@ -4518,7 +4537,7 @@ class ViewState {
4518
4537
  for (let i = 0; i <= 1; i++) {
4519
4538
  let pos = i ? main.head : main.anchor;
4520
4539
  if (!viewports.some(({ from, to }) => pos >= from && pos <= to)) {
4521
- let { from, to } = this.lineAt(pos, 0);
4540
+ let { from, to } = this.lineBlockAt(pos);
4522
4541
  viewports.push(new Viewport(from, to));
4523
4542
  }
4524
4543
  }
@@ -4526,6 +4545,12 @@ class ViewState {
4526
4545
  this.scaler = this.heightMap.height <= 7000000 /* MaxDOMHeight */ ? IdScaler :
4527
4546
  new BigScaler(this.heightOracle.doc, this.heightMap, this.viewports);
4528
4547
  }
4548
+ updateViewportLines() {
4549
+ this.viewportLines = [];
4550
+ this.heightMap.forEachLine(this.viewport.from, this.viewport.to, this.state.doc, 0, 0, block => {
4551
+ this.viewportLines.push(this.scaler.scale == 1 ? block : scaleBlock(block, this.scaler));
4552
+ });
4553
+ }
4529
4554
  update(update, scrollTarget = null) {
4530
4555
  let prev = this.state;
4531
4556
  this.state = update.state;
@@ -4540,7 +4565,11 @@ class ViewState {
4540
4565
  if (scrollTarget && (scrollTarget.range.head < viewport.from || scrollTarget.range.head > viewport.to) ||
4541
4566
  !this.viewportIsAppropriate(viewport))
4542
4567
  viewport = this.getViewport(0, scrollTarget);
4568
+ let updateLines = !update.changes.empty || (update.flags & 2 /* Height */) ||
4569
+ viewport.from != this.viewport.from || viewport.to != this.viewport.to;
4543
4570
  this.viewport = viewport;
4571
+ if (updateLines)
4572
+ this.updateViewportLines();
4544
4573
  this.updateForViewport();
4545
4574
  if (this.lineGaps.length || this.viewport.to - this.viewport.from > 4000 /* DoubleMargin */)
4546
4575
  this.updateLineGaps(this.ensureLineGaps(this.mapLineGaps(this.lineGaps, update.changes)));
@@ -4551,13 +4580,17 @@ class ViewState {
4551
4580
  update.state.selection.main.empty && update.state.selection.main.assoc)
4552
4581
  this.mustEnforceCursorAssoc = true;
4553
4582
  }
4554
- measure(docView, repeated) {
4555
- let dom = docView.dom, whiteSpace = "", direction = Direction.LTR;
4556
- let result = 0;
4557
- if (!repeated) {
4583
+ measure(view) {
4584
+ let dom = view.contentDOM, style = window.getComputedStyle(dom);
4585
+ let oracle = this.heightOracle;
4586
+ let whiteSpace = style.whiteSpace, direction = style.direction == "rtl" ? Direction.RTL : Direction.LTR;
4587
+ let refresh = this.heightOracle.mustRefreshForStyle(whiteSpace, direction);
4588
+ let measureContent = refresh || this.mustMeasureContent || this.contentDOMHeight != dom.clientHeight;
4589
+ let result = 0, bias = 0;
4590
+ if (measureContent) {
4591
+ this.mustMeasureContent = false;
4592
+ this.contentDOMHeight = dom.clientHeight;
4558
4593
  // Vertical padding
4559
- let style = window.getComputedStyle(dom);
4560
- whiteSpace = style.whiteSpace, direction = (style.direction == "rtl" ? Direction.RTL : Direction.LTR);
4561
4594
  let paddingTop = parseInt(style.paddingTop) || 0, paddingBottom = parseInt(style.paddingBottom) || 0;
4562
4595
  if (this.paddingTop != paddingTop || this.paddingBottom != paddingBottom) {
4563
4596
  result |= 8 /* Geometry */;
@@ -4572,39 +4605,42 @@ class ViewState {
4572
4605
  this.inView = this.pixelViewport.bottom > this.pixelViewport.top && this.pixelViewport.right > this.pixelViewport.left;
4573
4606
  if (!this.inView)
4574
4607
  return 0;
4575
- let lineHeights = docView.measureVisibleLineHeights();
4576
- let refresh = false, bias = 0, oracle = this.heightOracle;
4577
- if (!repeated) {
4578
- let contentWidth = docView.dom.clientWidth;
4579
- if (oracle.mustRefresh(lineHeights, whiteSpace, direction) ||
4580
- oracle.lineWrapping && Math.abs(contentWidth - this.contentWidth) > oracle.charWidth) {
4581
- let { lineHeight, charWidth } = docView.measureTextSize();
4608
+ if (measureContent) {
4609
+ let lineHeights = view.docView.measureVisibleLineHeights();
4610
+ if (oracle.mustRefreshForHeights(lineHeights))
4611
+ refresh = true;
4612
+ let contentWidth = dom.clientWidth;
4613
+ if (refresh || oracle.lineWrapping && Math.abs(contentWidth - this.contentDOMWidth) > oracle.charWidth) {
4614
+ let { lineHeight, charWidth } = view.docView.measureTextSize();
4582
4615
  refresh = oracle.refresh(whiteSpace, direction, lineHeight, charWidth, contentWidth / charWidth, lineHeights);
4583
4616
  if (refresh) {
4584
- docView.minWidth = 0;
4617
+ view.docView.minWidth = 0;
4585
4618
  result |= 8 /* Geometry */;
4586
4619
  }
4587
4620
  }
4588
- if (this.contentWidth != contentWidth) {
4589
- this.contentWidth = contentWidth;
4621
+ if (this.contentDOMWidth != contentWidth) {
4622
+ this.contentDOMWidth = contentWidth;
4590
4623
  result |= 8 /* Geometry */;
4591
4624
  }
4592
- if (this.editorHeight != docView.view.scrollDOM.clientHeight) {
4593
- this.editorHeight = docView.view.scrollDOM.clientHeight;
4625
+ if (this.editorHeight != view.scrollDOM.clientHeight) {
4626
+ this.editorHeight = view.scrollDOM.clientHeight;
4594
4627
  result |= 8 /* Geometry */;
4595
4628
  }
4596
4629
  if (dTop > 0 && dBottom > 0)
4597
4630
  bias = Math.max(dTop, dBottom);
4598
4631
  else if (dTop < 0 && dBottom < 0)
4599
4632
  bias = Math.min(dTop, dBottom);
4600
- }
4601
- oracle.heightChanged = false;
4602
- this.heightMap = this.heightMap.updateHeight(oracle, 0, refresh, new MeasuredHeights(this.viewport.from, lineHeights));
4603
- if (oracle.heightChanged)
4604
- result |= 2 /* Height */;
4605
- if (!this.viewportIsAppropriate(this.viewport, bias) ||
4606
- this.scrollTarget && (this.scrollTarget.range.head < this.viewport.from || this.scrollTarget.range.head > this.viewport.to))
4633
+ oracle.heightChanged = false;
4634
+ this.heightMap = this.heightMap.updateHeight(oracle, 0, refresh, new MeasuredHeights(this.viewport.from, lineHeights));
4635
+ if (oracle.heightChanged)
4636
+ result |= 2 /* Height */;
4637
+ }
4638
+ let viewportChange = !this.viewportIsAppropriate(this.viewport, bias) ||
4639
+ this.scrollTarget && (this.scrollTarget.range.head < this.viewport.from || this.scrollTarget.range.head > this.viewport.to);
4640
+ if (viewportChange)
4607
4641
  this.viewport = this.getViewport(bias, this.scrollTarget);
4642
+ if ((result & 2 /* Height */) || viewportChange)
4643
+ this.updateViewportLines();
4608
4644
  this.updateForViewport();
4609
4645
  if (this.lineGaps.length || this.viewport.to - this.viewport.from > 4000 /* DoubleMargin */)
4610
4646
  this.updateLineGaps(this.ensureLineGaps(refresh ? [] : this.lineGaps));
@@ -4615,12 +4651,12 @@ class ViewState {
4615
4651
  // to a line end is going to trigger a layout anyway, so it
4616
4652
  // can't be a pure write. It should be rare that it does any
4617
4653
  // writing.
4618
- docView.enforceCursorAssoc();
4654
+ view.docView.enforceCursorAssoc();
4619
4655
  }
4620
4656
  return result;
4621
4657
  }
4622
- get visibleTop() { return this.scaler.fromDOM(this.pixelViewport.top, 0); }
4623
- get visibleBottom() { return this.scaler.fromDOM(this.pixelViewport.bottom, 0); }
4658
+ get visibleTop() { return this.scaler.fromDOM(this.pixelViewport.top); }
4659
+ get visibleBottom() { return this.scaler.fromDOM(this.pixelViewport.bottom); }
4624
4660
  getViewport(bias, scrollTarget) {
4625
4661
  // This will divide VP.Margin between the top and the
4626
4662
  // bottom, depending on the bias (the change in viewport position
@@ -4680,12 +4716,12 @@ class ViewState {
4680
4716
  // This won't work at all in predominantly right-to-left text.
4681
4717
  if (this.heightOracle.direction != Direction.LTR)
4682
4718
  return gaps;
4683
- this.heightMap.forEachLine(this.viewport.from, this.viewport.to, this.state.doc, 0, 0, line => {
4719
+ for (let line of this.viewportLines) {
4684
4720
  if (line.length < 4000 /* DoubleMargin */)
4685
- return;
4721
+ continue;
4686
4722
  let structure = lineStructure(line.from, line.to, this.state);
4687
4723
  if (structure.total < 4000 /* DoubleMargin */)
4688
- return;
4724
+ continue;
4689
4725
  let viewFrom, viewTo;
4690
4726
  if (this.heightOracle.lineWrapping) {
4691
4727
  let marginHeight = (2000 /* Margin */ / this.heightOracle.lineLength) * this.heightOracle.lineHeight;
@@ -4715,7 +4751,7 @@ class ViewState {
4715
4751
  Math.abs(gap.from - from) < 1000 /* HalfMargin */ && Math.abs(gap.to - to) < 1000 /* HalfMargin */) ||
4716
4752
  new LineGap(from, to, this.gapSize(line, from, to, structure)));
4717
4753
  }
4718
- });
4754
+ }
4719
4755
  return gaps;
4720
4756
  }
4721
4757
  gapSize(line, from, to, structure) {
@@ -4747,27 +4783,18 @@ class ViewState {
4747
4783
  this.visibleRanges = ranges;
4748
4784
  return changed ? 4 /* Viewport */ : 0;
4749
4785
  }
4750
- lineAt(pos, editorTop) {
4751
- editorTop += this.paddingTop;
4752
- return scaleBlock(this.heightMap.lineAt(pos, QueryType.ByPos, this.state.doc, editorTop, 0), this.scaler, editorTop);
4753
- }
4754
- lineAtHeight(height, editorTop) {
4755
- editorTop += this.paddingTop;
4756
- return scaleBlock(this.heightMap.lineAt(this.scaler.fromDOM(height, editorTop), QueryType.ByHeight, this.state.doc, editorTop, 0), this.scaler, editorTop);
4786
+ lineBlockAt(pos) {
4787
+ return (pos >= this.viewport.from && pos <= this.viewport.to && this.viewportLines.find(b => b.from <= pos && b.to >= pos)) ||
4788
+ scaleBlock(this.heightMap.lineAt(pos, QueryType.ByPos, this.state.doc, 0, 0), this.scaler);
4757
4789
  }
4758
- blockAtHeight(height, editorTop) {
4759
- editorTop += this.paddingTop;
4760
- return scaleBlock(this.heightMap.blockAt(this.scaler.fromDOM(height, editorTop), this.state.doc, editorTop, 0), this.scaler, editorTop);
4790
+ lineBlockAtHeight(height) {
4791
+ return scaleBlock(this.heightMap.lineAt(this.scaler.fromDOM(height), QueryType.ByHeight, this.state.doc, 0, 0), this.scaler);
4761
4792
  }
4762
- forEachLine(from, to, f, editorTop) {
4763
- editorTop += this.paddingTop;
4764
- return this.heightMap.forEachLine(from, to, this.state.doc, editorTop, 0, this.scaler.scale == 1 ? f : b => f(scaleBlock(b, this.scaler, editorTop)));
4793
+ elementAtHeight(height) {
4794
+ return scaleBlock(this.heightMap.blockAt(this.scaler.fromDOM(height), this.state.doc, 0, 0), this.scaler);
4765
4795
  }
4766
4796
  get contentHeight() {
4767
- return this.domHeight + this.paddingTop + this.paddingBottom;
4768
- }
4769
- get domHeight() {
4770
- return this.scaler.toDOM(this.heightMap.height, this.paddingTop);
4797
+ return this.scaler.toDOM(this.heightMap.height) + this.paddingTop + this.paddingBottom;
4771
4798
  }
4772
4799
  }
4773
4800
  class Viewport {
@@ -4864,36 +4891,34 @@ class BigScaler {
4864
4891
  base = obj.bottom;
4865
4892
  }
4866
4893
  }
4867
- toDOM(n, top) {
4868
- n -= top;
4894
+ toDOM(n) {
4869
4895
  for (let i = 0, base = 0, domBase = 0;; i++) {
4870
4896
  let vp = i < this.viewports.length ? this.viewports[i] : null;
4871
4897
  if (!vp || n < vp.top)
4872
- return domBase + (n - base) * this.scale + top;
4898
+ return domBase + (n - base) * this.scale;
4873
4899
  if (n <= vp.bottom)
4874
- return vp.domTop + (n - vp.top) + top;
4900
+ return vp.domTop + (n - vp.top);
4875
4901
  base = vp.bottom;
4876
4902
  domBase = vp.domBottom;
4877
4903
  }
4878
4904
  }
4879
- fromDOM(n, top) {
4880
- n -= top;
4905
+ fromDOM(n) {
4881
4906
  for (let i = 0, base = 0, domBase = 0;; i++) {
4882
4907
  let vp = i < this.viewports.length ? this.viewports[i] : null;
4883
4908
  if (!vp || n < vp.domTop)
4884
- return base + (n - domBase) / this.scale + top;
4909
+ return base + (n - domBase) / this.scale;
4885
4910
  if (n <= vp.domBottom)
4886
- return vp.top + (n - vp.domTop) + top;
4911
+ return vp.top + (n - vp.domTop);
4887
4912
  base = vp.bottom;
4888
4913
  domBase = vp.domBottom;
4889
4914
  }
4890
4915
  }
4891
4916
  }
4892
- function scaleBlock(block, scaler, top) {
4917
+ function scaleBlock(block, scaler) {
4893
4918
  if (scaler.scale == 1)
4894
4919
  return block;
4895
- let bTop = scaler.toDOM(block.top, top), bBottom = scaler.toDOM(block.bottom, top);
4896
- return new BlockInfo(block.from, block.length, bTop, bBottom - bTop, Array.isArray(block.type) ? block.type.map(b => scaleBlock(b, scaler, top)) : block.type);
4920
+ let bTop = scaler.toDOM(block.top), bBottom = scaler.toDOM(block.bottom);
4921
+ return new BlockInfo(block.from, block.length, bTop, bBottom - bTop, Array.isArray(block.type) ? block.type.map(b => scaleBlock(b, scaler)) : block.type);
4897
4922
  }
4898
4923
 
4899
4924
  const theme = /*@__PURE__*/Facet.define({ combine: strs => strs.join(" ") });
@@ -5030,7 +5055,7 @@ const baseTheme = /*@__PURE__*/buildTheme("." + baseThemeID, {
5030
5055
  color: "inherit",
5031
5056
  fontSize: "70%",
5032
5057
  padding: ".2em 1em",
5033
- borderRadius: "3px"
5058
+ borderRadius: "1px"
5034
5059
  },
5035
5060
  "&light .cm-button": {
5036
5061
  backgroundImage: "linear-gradient(#eff1f5, #d9d9df)",
@@ -5352,6 +5377,7 @@ class DOMObserver {
5352
5377
  for (let dom of this.scrollTargets)
5353
5378
  dom.removeEventListener("scroll", this.onScroll);
5354
5379
  window.removeEventListener("scroll", this.onScroll);
5380
+ this.dom.ownerDocument.removeEventListener("selectionchange", this.onSelectionChange);
5355
5381
  clearTimeout(this.parentCheck);
5356
5382
  clearTimeout(this.resizeTimeout);
5357
5383
  }
@@ -5648,6 +5674,7 @@ class EditorView {
5648
5674
  */
5649
5675
  config = {}) {
5650
5676
  this.plugins = [];
5677
+ this.pluginMap = new Map;
5651
5678
  this.editorAttrs = {};
5652
5679
  this.contentAttrs = {};
5653
5680
  this.bidiCache = [];
@@ -5817,6 +5844,7 @@ class EditorView {
5817
5844
  plugin.destroy(this);
5818
5845
  this.viewState = new ViewState(newState);
5819
5846
  this.plugins = newState.facet(viewPlugin).map(spec => new PluginInstance(spec).update(this));
5847
+ this.pluginMap.clear();
5820
5848
  this.docView = new DocView(this);
5821
5849
  this.inputState.ensureHandlers(this);
5822
5850
  this.mountStyles();
@@ -5847,6 +5875,7 @@ class EditorView {
5847
5875
  if (plugin.mustUpdate != update)
5848
5876
  plugin.destroy(this);
5849
5877
  this.plugins = newPlugins;
5878
+ this.pluginMap.clear();
5850
5879
  this.inputState.ensureHandlers(this);
5851
5880
  }
5852
5881
  else {
@@ -5854,7 +5883,7 @@ class EditorView {
5854
5883
  p.mustUpdate = update;
5855
5884
  }
5856
5885
  for (let i = 0; i < this.plugins.length; i++)
5857
- this.plugins[i] = this.plugins[i].update(this);
5886
+ this.plugins[i].update(this);
5858
5887
  }
5859
5888
  /**
5860
5889
  @internal
@@ -5872,11 +5901,11 @@ class EditorView {
5872
5901
  for (let i = 0;; i++) {
5873
5902
  this.updateState = 1 /* Measuring */;
5874
5903
  let oldViewport = this.viewport;
5875
- let changed = this.viewState.measure(this.docView, i > 0);
5904
+ let changed = this.viewState.measure(this);
5876
5905
  if (!changed && !this.measureRequests.length && this.viewState.scrollTarget == null)
5877
5906
  break;
5878
5907
  if (i > 5) {
5879
- console.warn("Viewport failed to stabilize");
5908
+ console.warn(this.measureRequests.length ? "Measure loop restarted more than 5 times" : "Viewport failed to stabilize");
5880
5909
  break;
5881
5910
  }
5882
5911
  let measuring = [];
@@ -5892,7 +5921,7 @@ class EditorView {
5892
5921
  return BadMeasure;
5893
5922
  }
5894
5923
  });
5895
- let update = new ViewUpdate(this, this.state);
5924
+ let update = new ViewUpdate(this, this.state), redrawn = false;
5896
5925
  update.flags |= changed;
5897
5926
  if (!updated)
5898
5927
  updated = update;
@@ -5902,13 +5931,15 @@ class EditorView {
5902
5931
  if (!update.empty) {
5903
5932
  this.updatePlugins(update);
5904
5933
  this.inputState.update(update);
5934
+ this.updateAttrs();
5935
+ redrawn = this.docView.update(update);
5905
5936
  }
5906
- this.updateAttrs();
5907
- let redrawn = changed > 0 && this.docView.update(update);
5908
5937
  for (let i = 0; i < measuring.length; i++)
5909
5938
  if (measured[i] != BadMeasure) {
5910
5939
  try {
5911
- measuring[i].write(measured[i], this);
5940
+ let m = measuring[i];
5941
+ if (m.write)
5942
+ m.write(measured[i], this);
5912
5943
  }
5913
5944
  catch (e) {
5914
5945
  logException(this.state, e);
@@ -5918,8 +5949,8 @@ class EditorView {
5918
5949
  this.docView.scrollIntoView(this.viewState.scrollTarget);
5919
5950
  this.viewState.scrollTarget = null;
5920
5951
  }
5921
- if (changed)
5922
- this.docView.updateSelection(redrawn);
5952
+ if (redrawn)
5953
+ this.docView.updateSelection(true);
5923
5954
  if (this.viewport.from == oldViewport.from && this.viewport.to == oldViewport.to && this.measureRequests.length == 0)
5924
5955
  break;
5925
5956
  }
@@ -5941,7 +5972,7 @@ class EditorView {
5941
5972
  this.state.facet(theme);
5942
5973
  }
5943
5974
  updateAttrs() {
5944
- let editorAttrs = combineAttrs(this.state.facet(editorAttributes), {
5975
+ let editorAttrs = attrsFromFacet(this, editorAttributes, {
5945
5976
  class: "cm-editor" + (this.hasFocus ? " cm-focused " : " ") + this.themeClasses
5946
5977
  });
5947
5978
  let contentAttrs = {
@@ -5957,7 +5988,7 @@ class EditorView {
5957
5988
  };
5958
5989
  if (this.state.readOnly)
5959
5990
  contentAttrs["aria-readonly"] = "true";
5960
- combineAttrs(this.state.facet(contentAttributes), contentAttrs);
5991
+ attrsFromFacet(this, contentAttributes, contentAttrs);
5961
5992
  this.observer.ignore(() => {
5962
5993
  updateAttrs(this.contentDOM, this.contentAttrs, contentAttrs);
5963
5994
  updateAttrs(this.dom, this.editorAttrs, editorAttrs);
@@ -6026,10 +6057,24 @@ class EditorView {
6026
6057
  the return value of this method.
6027
6058
  */
6028
6059
  plugin(plugin) {
6029
- for (let inst of this.plugins)
6030
- if (inst.spec == plugin)
6031
- return inst.update(this).value;
6032
- return null;
6060
+ let known = this.pluginMap.get(plugin);
6061
+ if (known === undefined || known && known.spec != plugin)
6062
+ this.pluginMap.set(plugin, known = this.plugins.find(p => p.spec == plugin) || null);
6063
+ return known && known.update(this).value;
6064
+ }
6065
+ /**
6066
+ The top position of the document, in screen coordinates. This
6067
+ may be negative when the editor is scrolled down. Points
6068
+ directly to the top of the first line, not above the padding.
6069
+ */
6070
+ get documentTop() {
6071
+ return this.contentDOM.getBoundingClientRect().top + this.viewState.paddingTop;
6072
+ }
6073
+ /**
6074
+ Reports the padding above and below the document.
6075
+ */
6076
+ get documentPadding() {
6077
+ return { top: this.viewState.paddingTop, bottom: this.viewState.paddingBottom };
6033
6078
  }
6034
6079
  /**
6035
6080
  Find the line or block widget at the given vertical position.
@@ -6041,10 +6086,21 @@ class EditorView {
6041
6086
  position, or a precomputed document top
6042
6087
  (`view.contentDOM.getBoundingClientRect().top`) to limit layout
6043
6088
  queries.
6089
+
6090
+ *Deprecated: use `blockAtHeight` instead.*
6044
6091
  */
6045
6092
  blockAtHeight(height, docTop) {
6093
+ let top = ensureTop(docTop, this);
6094
+ return this.elementAtHeight(height - top).moveY(top);
6095
+ }
6096
+ /**
6097
+ Find the text line or block widget at the given vertical
6098
+ position (which is interpreted as relative to the [top of the
6099
+ document](https://codemirror.net/6/docs/ref/#view.EditorView.documentTop)
6100
+ */
6101
+ elementAtHeight(height) {
6046
6102
  this.readMeasured();
6047
- return this.viewState.blockAtHeight(height, ensureTop(docTop, this.contentDOM));
6103
+ return this.viewState.elementAtHeight(height);
6048
6104
  }
6049
6105
  /**
6050
6106
  Find information for the visual line (see
@@ -6056,20 +6112,43 @@ class EditorView {
6056
6112
  Defaults to treating `height` as a screen position. See
6057
6113
  [`blockAtHeight`](https://codemirror.net/6/docs/ref/#view.EditorView.blockAtHeight) for the
6058
6114
  interpretation of the `docTop` parameter.
6115
+
6116
+ *Deprecated: use `lineBlockAtHeight` instead.*
6059
6117
  */
6060
6118
  visualLineAtHeight(height, docTop) {
6119
+ let top = ensureTop(docTop, this);
6120
+ return this.lineBlockAtHeight(height - top).moveY(top);
6121
+ }
6122
+ /**
6123
+ Find the line block (see
6124
+ [`lineBlockAt`](https://codemirror.net/6/docs/ref/#view.EditorView.lineBlockAt) at the given
6125
+ height.
6126
+ */
6127
+ lineBlockAtHeight(height) {
6061
6128
  this.readMeasured();
6062
- return this.viewState.lineAtHeight(height, ensureTop(docTop, this.contentDOM));
6129
+ return this.viewState.lineBlockAtHeight(height);
6063
6130
  }
6064
6131
  /**
6065
6132
  Iterate over the height information of the visual lines in the
6066
6133
  viewport. The heights of lines are reported relative to the
6067
6134
  given document top, which defaults to the screen position of the
6068
6135
  document (forcing a layout).
6136
+
6137
+ *Deprecated: use `viewportLineBlocks` instead.*
6069
6138
  */
6070
6139
  viewportLines(f, docTop) {
6071
- let { from, to } = this.viewport;
6072
- this.viewState.forEachLine(from, to, f, ensureTop(docTop, this.contentDOM));
6140
+ let top = ensureTop(docTop, this);
6141
+ for (let line of this.viewportLineBlocks)
6142
+ f(line.moveY(top));
6143
+ }
6144
+ /**
6145
+ Get the extent and vertical position of all [line
6146
+ blocks](https://codemirror.net/6/docs/ref/#view.EditorView.lineBlockAt) in the viewport. Positions
6147
+ are relative to the [top of the
6148
+ document](https://codemirror.net/6/docs/ref/#view.EditorView.documentTop);
6149
+ */
6150
+ get viewportLineBlocks() {
6151
+ return this.viewState.viewportLines;
6073
6152
  }
6074
6153
  /**
6075
6154
  Find the extent and height of the visual line (a range delimited
@@ -6080,9 +6159,22 @@ class EditorView {
6080
6159
  argument, which defaults to 0 for this method. You can pass
6081
6160
  `view.contentDOM.getBoundingClientRect().top` here to get screen
6082
6161
  coordinates.
6162
+
6163
+ *Deprecated: use `lineBlockAt` instead.*
6083
6164
  */
6084
6165
  visualLineAt(pos, docTop = 0) {
6085
- return this.viewState.lineAt(pos, docTop);
6166
+ return this.lineBlockAt(pos).moveY(docTop + this.viewState.paddingTop);
6167
+ }
6168
+ /**
6169
+ Find the line block around the given document position. A line
6170
+ block is a range delimited on both sides by either a
6171
+ non-[hidden](https://codemirror.net/6/docs/ref/#view.Decoration^range) line breaks, or the
6172
+ start/end of the document. It will usually just hold a line of
6173
+ text, but may be broken into multiple textblocks by block
6174
+ widgets.
6175
+ */
6176
+ lineBlockAt(pos) {
6177
+ return this.viewState.lineBlockAt(pos);
6086
6178
  }
6087
6179
  /**
6088
6180
  The editor's total content height.
@@ -6415,8 +6507,9 @@ search match).
6415
6507
  EditorView.announce = /*@__PURE__*/StateEffect.define();
6416
6508
  // Maximum line length for which we compute accurate bidi info
6417
6509
  const MaxBidiLine = 4096;
6418
- function ensureTop(given, dom) {
6419
- return given == null ? dom.getBoundingClientRect().top : given;
6510
+ // FIXME remove this and its callers on next breaking release
6511
+ function ensureTop(given, view) {
6512
+ return (given == null ? view.contentDOM.getBoundingClientRect().top : given) + view.viewState.paddingTop;
6420
6513
  }
6421
6514
  let resizeDebounce = -1;
6422
6515
  function ensureGlobalHandler() {
@@ -6454,6 +6547,14 @@ class CachedOrder {
6454
6547
  return result;
6455
6548
  }
6456
6549
  }
6550
+ function attrsFromFacet(view, facet, base) {
6551
+ for (let sources = view.state.facet(facet), i = sources.length - 1; i >= 0; i--) {
6552
+ let source = sources[i], value = typeof source == "function" ? source(view) : source;
6553
+ if (value)
6554
+ combineAttrs(value, base);
6555
+ }
6556
+ return base;
6557
+ }
6457
6558
 
6458
6559
  const currentPlatform = browser.mac ? "mac" : browser.windows ? "win" : browser.linux ? "linux" : "key";
6459
6560
  function normalizeKeyName(name, platform) {
@@ -6767,7 +6868,7 @@ function wrappedLine(view, pos, inside) {
6767
6868
  type: BlockType.Text };
6768
6869
  }
6769
6870
  function blockAt(view, pos) {
6770
- let line = view.visualLineAt(pos);
6871
+ let line = view.lineBlockAt(pos);
6771
6872
  if (Array.isArray(line.type))
6772
6873
  for (let l of line.type) {
6773
6874
  if (l.to > pos || l.to == pos && (l.to == line.to || l.type == BlockType.Text))
@@ -7106,35 +7207,29 @@ class TabWidget extends WidgetType {
7106
7207
  }
7107
7208
 
7108
7209
  const plugin = /*@__PURE__*/ViewPlugin.fromClass(class {
7109
- constructor(view) {
7110
- this.height = -1;
7111
- this.measure = {
7112
- read: view => Math.max(0, view.scrollDOM.clientHeight - view.defaultLineHeight),
7113
- write: (value, view) => {
7114
- if (Math.abs(value - this.height) > 1) {
7115
- this.height = value;
7116
- view.contentDOM.style.paddingBottom = value + "px";
7117
- }
7118
- }
7119
- };
7120
- view.requestMeasure(this.measure);
7210
+ constructor() {
7211
+ this.height = 1000;
7212
+ this.attrs = { style: "padding-bottom: 1000px" };
7121
7213
  }
7122
7214
  update(update) {
7123
- if (update.geometryChanged)
7124
- update.view.requestMeasure(this.measure);
7215
+ let height = update.view.viewState.editorHeight - update.view.defaultLineHeight;
7216
+ if (height != this.height) {
7217
+ this.height = height;
7218
+ this.attrs = { style: `padding-bottom: ${height}px` };
7219
+ }
7125
7220
  }
7126
7221
  });
7127
7222
  /**
7128
- Returns a plugin that makes sure the content has a bottom margin
7129
- equivalent to the height of the editor, minus one line height, so
7130
- that every line in the document can be scrolled to the top of the
7131
- editor.
7223
+ Returns an extension that makes sure the content has a bottom
7224
+ margin equivalent to the height of the editor, minus one line
7225
+ height, so that every line in the document can be scrolled to the
7226
+ top of the editor.
7132
7227
 
7133
7228
  This is only meaningful when the editor is scrollable, and should
7134
7229
  not be enabled in editors that take the size of their content.
7135
7230
  */
7136
7231
  function scrollPastEnd() {
7137
- return plugin;
7232
+ return [plugin, contentAttributes.of(view => { var _a; return ((_a = view.plugin(plugin)) === null || _a === void 0 ? void 0 : _a.attrs) || null; })];
7138
7233
  }
7139
7234
 
7140
7235
  /**
@@ -7158,7 +7253,7 @@ const activeLineHighlighter = /*@__PURE__*/ViewPlugin.fromClass(class {
7158
7253
  for (let r of view.state.selection.ranges) {
7159
7254
  if (!r.empty)
7160
7255
  return Decoration.none;
7161
- let line = view.visualLineAt(r.head);
7256
+ let line = view.lineBlockAt(r.head);
7162
7257
  if (line.from > lastLineStart) {
7163
7258
  deco.push(lineDeco.range(line.from));
7164
7259
  lastLineStart = line.from;