@codemirror/view 6.9.1 → 6.9.3

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/CHANGELOG.md CHANGED
@@ -1,3 +1,25 @@
1
+ ## 6.9.3 (2023-03-21)
2
+
3
+ ### Bug fixes
4
+
5
+ Work around a Firefox issue that caused `coordsAtPos` to return rectangles with the full line height on empty lines.
6
+
7
+ Opening a context menu by clicking below the content element but inside the editor now properly shows the browser's menu for editable elements.
8
+
9
+ Fix an issue that broke composition (especially of Chinese IME) after widget decorations.
10
+
11
+ Fix an issue that would cause the cursor to jump around during compositions inside nested mark decorations.
12
+
13
+ ## 6.9.2 (2023-03-08)
14
+
15
+ ### Bug fixes
16
+
17
+ Work around a Firefox CSS bug that caused cursors to stop blinking in a scrolled editor.
18
+
19
+ Fix an issue in `drawSelection` where the selection extended into the editor's padding.
20
+
21
+ Fix pasting of links copied from iOS share sheet.
22
+
1
23
  ## 6.9.1 (2023-02-17)
2
24
 
3
25
  ### Bug fixes
package/dist/index.cjs CHANGED
@@ -957,8 +957,9 @@ function scanCompositionTree(pos, side, view, text, enterView, fromText) {
957
957
  }
958
958
  function posFromDOMInCompositionTree(node, offset, view, text) {
959
959
  if (view instanceof MarkView) {
960
+ let pos = 0;
960
961
  for (let child of view.children) {
961
- let pos = 0, hasComp = contains(child.dom, text);
962
+ let hasComp = contains(child.dom, text);
962
963
  if (contains(child.dom, node))
963
964
  return pos + (hasComp ? posFromDOMInCompositionTree(node, offset, child, text) : child.localPosFromDOM(node, offset));
964
965
  pos += hasComp ? text.nodeValue.length : child.length;
@@ -992,7 +993,7 @@ class WidgetBufferView extends ContentView {
992
993
  }
993
994
  }
994
995
  getSide() { return this.side; }
995
- domAtPos(pos) { return DOMPos.before(this.dom); }
996
+ domAtPos(pos) { return this.side > 0 ? DOMPos.before(this.dom) : DOMPos.after(this.dom); }
996
997
  localPosFromDOM() { return 0; }
997
998
  domBoundsAround() { return null; }
998
999
  coordsAt(pos) {
@@ -1516,7 +1517,7 @@ class LineView extends ContentView {
1516
1517
  measureTextSize() {
1517
1518
  if (this.children.length == 0 || this.length > 20)
1518
1519
  return null;
1519
- let totalWidth = 0;
1520
+ let totalWidth = 0, textHeight;
1520
1521
  for (let child of this.children) {
1521
1522
  if (!(child instanceof TextView) || /[^ -~]/.test(child.text))
1522
1523
  return null;
@@ -1524,14 +1525,26 @@ class LineView extends ContentView {
1524
1525
  if (rects.length != 1)
1525
1526
  return null;
1526
1527
  totalWidth += rects[0].width;
1528
+ textHeight = rects[0].height;
1527
1529
  }
1528
1530
  return !totalWidth ? null : {
1529
1531
  lineHeight: this.dom.getBoundingClientRect().height,
1530
- charWidth: totalWidth / this.length
1532
+ charWidth: totalWidth / this.length,
1533
+ textHeight
1531
1534
  };
1532
1535
  }
1533
1536
  coordsAt(pos, side) {
1534
- return coordsInChildren(this, pos, side);
1537
+ let rect = coordsInChildren(this, pos, side);
1538
+ // Correct rectangle height for empty lines when the returned
1539
+ // height is larger than the text height.
1540
+ if (!this.children.length && rect && this.parent) {
1541
+ let { heightOracle } = this.parent.view.viewState, height = rect.bottom - rect.top;
1542
+ if (Math.abs(height - heightOracle.lineHeight) < 2 && heightOracle.textHeight < height) {
1543
+ let dist = (height - heightOracle.textHeight) / 2;
1544
+ return { top: rect.top + dist, bottom: rect.bottom - dist, left: rect.left, right: rect.left };
1545
+ }
1546
+ }
1547
+ return rect;
1535
1548
  }
1536
1549
  become(_other) { return false; }
1537
1550
  get type() { return exports.BlockType.Text; }
@@ -2812,7 +2825,7 @@ class DocView extends ContentView {
2812
2825
  }
2813
2826
  }
2814
2827
  // If no workable line exists, force a layout of a measurable element
2815
- let dummy = document.createElement("div"), lineHeight, charWidth;
2828
+ let dummy = document.createElement("div"), lineHeight, charWidth, textHeight;
2816
2829
  dummy.className = "cm-line";
2817
2830
  dummy.style.width = "99999px";
2818
2831
  dummy.textContent = "abc def ghi jkl mno pqr stu";
@@ -2821,9 +2834,10 @@ class DocView extends ContentView {
2821
2834
  let rect = clientRectsFor(dummy.firstChild)[0];
2822
2835
  lineHeight = dummy.getBoundingClientRect().height;
2823
2836
  charWidth = rect ? rect.width / 27 : 7;
2837
+ textHeight = rect ? rect.height : lineHeight;
2824
2838
  dummy.remove();
2825
2839
  });
2826
- return { lineHeight, charWidth };
2840
+ return { lineHeight, charWidth, textHeight };
2827
2841
  }
2828
2842
  childCursor(pos = this.length) {
2829
2843
  // Move back to start of last element when possible, so that
@@ -2988,22 +3002,32 @@ class CompositionWidget extends WidgetType {
2988
3002
  ignoreEvent() { return false; }
2989
3003
  get customView() { return CompositionView; }
2990
3004
  }
2991
- function nearbyTextNode(node, offset, side) {
2992
- for (;;) {
2993
- if (node.nodeType == 3)
2994
- return node;
2995
- if (node.nodeType == 1 && offset > 0 && side <= 0) {
2996
- node = node.childNodes[offset - 1];
2997
- offset = maxOffset(node);
2998
- }
2999
- else if (node.nodeType == 1 && offset < node.childNodes.length && side >= 0) {
3000
- node = node.childNodes[offset];
3001
- offset = 0;
3005
+ function nearbyTextNode(startNode, startOffset, side) {
3006
+ if (side <= 0)
3007
+ for (let node = startNode, offset = startOffset;;) {
3008
+ if (node.nodeType == 3)
3009
+ return node;
3010
+ if (node.nodeType == 1 && offset > 0) {
3011
+ node = node.childNodes[offset - 1];
3012
+ offset = maxOffset(node);
3013
+ }
3014
+ else {
3015
+ break;
3016
+ }
3002
3017
  }
3003
- else {
3004
- return null;
3018
+ if (side >= 0)
3019
+ for (let node = startNode, offset = startOffset;;) {
3020
+ if (node.nodeType == 3)
3021
+ return node;
3022
+ if (node.nodeType == 1 && offset < node.childNodes.length && side >= 0) {
3023
+ node = node.childNodes[offset];
3024
+ offset = 0;
3025
+ }
3026
+ else {
3027
+ break;
3028
+ }
3005
3029
  }
3006
- }
3030
+ return null;
3007
3031
  }
3008
3032
  function nextToUneditable(node, offset) {
3009
3033
  if (node.nodeType != 1)
@@ -3167,7 +3191,7 @@ function domPosInText(node, x, y) {
3167
3191
  return { node, offset: closestOffset > -1 ? closestOffset : generalSide > 0 ? node.nodeValue.length : 0 };
3168
3192
  }
3169
3193
  function posAtCoords(view, coords, precise, bias = -1) {
3170
- var _a;
3194
+ var _a, _b;
3171
3195
  let content = view.contentDOM.getBoundingClientRect(), docTop = content.top + view.viewState.paddingTop;
3172
3196
  let block, { docHeight } = view.viewState;
3173
3197
  let { x, y } = coords, yOffset = y - docTop;
@@ -3244,7 +3268,7 @@ function posAtCoords(view, coords, precise, bias = -1) {
3244
3268
  let nearest = view.docView.nearest(node);
3245
3269
  if (!nearest)
3246
3270
  return null;
3247
- if (nearest.isWidget) {
3271
+ if (nearest.isWidget && ((_b = nearest.dom) === null || _b === void 0 ? void 0 : _b.nodeType) == 1) {
3248
3272
  let rect = nearest.dom.getBoundingClientRect();
3249
3273
  return coords.y < rect.top || coords.y <= rect.bottom && coords.x <= (rect.left + rect.right) / 2
3250
3274
  ? nearest.posAtStart : nearest.posAtEnd;
@@ -3439,8 +3463,16 @@ class InputState {
3439
3463
  this.registeredEvents.push(type);
3440
3464
  }
3441
3465
  view.scrollDOM.addEventListener("mousedown", (event) => {
3442
- if (event.target == view.scrollDOM && event.clientY > view.contentDOM.getBoundingClientRect().bottom)
3466
+ if (event.target == view.scrollDOM && event.clientY > view.contentDOM.getBoundingClientRect().bottom) {
3443
3467
  handleEvent(handlers.mousedown, event);
3468
+ if (!event.defaultPrevented && event.button == 2) {
3469
+ // Make sure the content covers the entire scroller height, in order
3470
+ // to catch a native context menu click below it
3471
+ let start = view.contentDOM.style.minHeight;
3472
+ view.contentDOM.style.minHeight = "100%";
3473
+ setTimeout(() => view.contentDOM.style.minHeight = start, 200);
3474
+ }
3475
+ }
3444
3476
  });
3445
3477
  if (browser.chrome && browser.chrome_version == 102) { // FIXME remove at some point
3446
3478
  // On Chrome 102, viewport updates somehow stop wheel-based
@@ -3974,7 +4006,7 @@ handlers.paste = (view, event) => {
3974
4006
  view.observer.flush();
3975
4007
  let data = brokenClipboardAPI ? null : event.clipboardData;
3976
4008
  if (data) {
3977
- doPaste(view, data.getData("text/plain"));
4009
+ doPaste(view, data.getData("text/plain") || data.getData("text/uri-text"));
3978
4010
  event.preventDefault();
3979
4011
  }
3980
4012
  else {
@@ -4134,8 +4166,9 @@ class HeightOracle {
4134
4166
  this.lineWrapping = lineWrapping;
4135
4167
  this.doc = state.Text.empty;
4136
4168
  this.heightSamples = {};
4137
- this.lineHeight = 14;
4169
+ this.lineHeight = 14; // The height of an entire line (line-height)
4138
4170
  this.charWidth = 7;
4171
+ this.textHeight = 14; // The height of the actual font (font-size)
4139
4172
  this.lineLength = 30;
4140
4173
  // Used to track, during updateHeight, if any actual heights changed
4141
4174
  this.heightChanged = false;
@@ -4170,12 +4203,13 @@ class HeightOracle {
4170
4203
  }
4171
4204
  return newHeight;
4172
4205
  }
4173
- refresh(whiteSpace, lineHeight, charWidth, lineLength, knownHeights) {
4206
+ refresh(whiteSpace, lineHeight, charWidth, textHeight, lineLength, knownHeights) {
4174
4207
  let lineWrapping = wrappingWhiteSpace.indexOf(whiteSpace) > -1;
4175
4208
  let changed = Math.round(lineHeight) != Math.round(this.lineHeight) || this.lineWrapping != lineWrapping;
4176
4209
  this.lineWrapping = lineWrapping;
4177
4210
  this.lineHeight = lineHeight;
4178
4211
  this.charWidth = charWidth;
4212
+ this.textHeight = textHeight;
4179
4213
  this.lineLength = lineLength;
4180
4214
  if (changed) {
4181
4215
  this.heightSamples = {};
@@ -5023,8 +5057,8 @@ class ViewState {
5023
5057
  if (oracle.mustRefreshForHeights(lineHeights))
5024
5058
  refresh = true;
5025
5059
  if (refresh || oracle.lineWrapping && Math.abs(contentWidth - this.contentDOMWidth) > oracle.charWidth) {
5026
- let { lineHeight, charWidth } = view.docView.measureTextSize();
5027
- refresh = lineHeight > 0 && oracle.refresh(whiteSpace, lineHeight, charWidth, contentWidth / charWidth, lineHeights);
5060
+ let { lineHeight, charWidth, textHeight } = view.docView.measureTextSize();
5061
+ refresh = lineHeight > 0 && oracle.refresh(whiteSpace, lineHeight, charWidth, textHeight, contentWidth / charWidth, lineHeights);
5028
5062
  if (refresh) {
5029
5063
  view.docView.minWidth = 0;
5030
5064
  result |= 8 /* UpdateFlag.Geometry */;
@@ -5435,6 +5469,9 @@ const baseTheme$1 = buildTheme("." + baseThemeID, {
5435
5469
  padding: "0 2px 0 6px"
5436
5470
  },
5437
5471
  ".cm-layer": {
5472
+ position: "absolute",
5473
+ left: 0,
5474
+ top: 0,
5438
5475
  contain: "size style",
5439
5476
  "& > *": {
5440
5477
  position: "absolute"
@@ -6595,7 +6632,7 @@ class EditorView {
6595
6632
  if (this.destroyed)
6596
6633
  return;
6597
6634
  if (this.measureScheduled > -1)
6598
- cancelAnimationFrame(this.measureScheduled);
6635
+ this.win.cancelAnimationFrame(this.measureScheduled);
6599
6636
  this.measureScheduled = 0; // Prevent requestMeasure calls from scheduling another animation frame
6600
6637
  if (flush)
6601
6638
  this.observer.forceFlush();
@@ -7033,7 +7070,7 @@ class EditorView {
7033
7070
  this.dom.remove();
7034
7071
  this.observer.destroy();
7035
7072
  if (this.measureScheduled > -1)
7036
- cancelAnimationFrame(this.measureScheduled);
7073
+ this.win.cancelAnimationFrame(this.measureScheduled);
7037
7074
  this.destroyed = true;
7038
7075
  }
7039
7076
  /**
@@ -7545,9 +7582,10 @@ function rectanglesForRange(view, className, range) {
7545
7582
  let from = Math.max(range.from, view.viewport.from), to = Math.min(range.to, view.viewport.to);
7546
7583
  let ltr = view.textDirection == exports.Direction.LTR;
7547
7584
  let content = view.contentDOM, contentRect = content.getBoundingClientRect(), base = getBase(view);
7548
- let lineStyle = window.getComputedStyle(content.firstChild);
7549
- let leftSide = contentRect.left + parseInt(lineStyle.paddingLeft) + Math.min(0, parseInt(lineStyle.textIndent));
7550
- let rightSide = contentRect.right - parseInt(lineStyle.paddingRight);
7585
+ let lineElt = content.querySelector(".cm-line"), lineStyle = lineElt && window.getComputedStyle(lineElt);
7586
+ let leftSide = contentRect.left +
7587
+ (lineStyle ? parseInt(lineStyle.paddingLeft) + Math.min(0, parseInt(lineStyle.textIndent)) : 0);
7588
+ let rightSide = contentRect.right - (lineStyle ? parseInt(lineStyle.paddingRight) : 0);
7551
7589
  let startBlock = blockAt(view, from), endBlock = blockAt(view, to);
7552
7590
  let visualStart = startBlock.type == exports.BlockType.Text ? startBlock : null;
7553
7591
  let visualEnd = endBlock.type == exports.BlockType.Text ? endBlock : null;
package/dist/index.js CHANGED
@@ -953,8 +953,9 @@ function scanCompositionTree(pos, side, view, text, enterView, fromText) {
953
953
  }
954
954
  function posFromDOMInCompositionTree(node, offset, view, text) {
955
955
  if (view instanceof MarkView) {
956
+ let pos = 0;
956
957
  for (let child of view.children) {
957
- let pos = 0, hasComp = contains(child.dom, text);
958
+ let hasComp = contains(child.dom, text);
958
959
  if (contains(child.dom, node))
959
960
  return pos + (hasComp ? posFromDOMInCompositionTree(node, offset, child, text) : child.localPosFromDOM(node, offset));
960
961
  pos += hasComp ? text.nodeValue.length : child.length;
@@ -988,7 +989,7 @@ class WidgetBufferView extends ContentView {
988
989
  }
989
990
  }
990
991
  getSide() { return this.side; }
991
- domAtPos(pos) { return DOMPos.before(this.dom); }
992
+ domAtPos(pos) { return this.side > 0 ? DOMPos.before(this.dom) : DOMPos.after(this.dom); }
992
993
  localPosFromDOM() { return 0; }
993
994
  domBoundsAround() { return null; }
994
995
  coordsAt(pos) {
@@ -1511,7 +1512,7 @@ class LineView extends ContentView {
1511
1512
  measureTextSize() {
1512
1513
  if (this.children.length == 0 || this.length > 20)
1513
1514
  return null;
1514
- let totalWidth = 0;
1515
+ let totalWidth = 0, textHeight;
1515
1516
  for (let child of this.children) {
1516
1517
  if (!(child instanceof TextView) || /[^ -~]/.test(child.text))
1517
1518
  return null;
@@ -1519,14 +1520,26 @@ class LineView extends ContentView {
1519
1520
  if (rects.length != 1)
1520
1521
  return null;
1521
1522
  totalWidth += rects[0].width;
1523
+ textHeight = rects[0].height;
1522
1524
  }
1523
1525
  return !totalWidth ? null : {
1524
1526
  lineHeight: this.dom.getBoundingClientRect().height,
1525
- charWidth: totalWidth / this.length
1527
+ charWidth: totalWidth / this.length,
1528
+ textHeight
1526
1529
  };
1527
1530
  }
1528
1531
  coordsAt(pos, side) {
1529
- return coordsInChildren(this, pos, side);
1532
+ let rect = coordsInChildren(this, pos, side);
1533
+ // Correct rectangle height for empty lines when the returned
1534
+ // height is larger than the text height.
1535
+ if (!this.children.length && rect && this.parent) {
1536
+ let { heightOracle } = this.parent.view.viewState, height = rect.bottom - rect.top;
1537
+ if (Math.abs(height - heightOracle.lineHeight) < 2 && heightOracle.textHeight < height) {
1538
+ let dist = (height - heightOracle.textHeight) / 2;
1539
+ return { top: rect.top + dist, bottom: rect.bottom - dist, left: rect.left, right: rect.left };
1540
+ }
1541
+ }
1542
+ return rect;
1530
1543
  }
1531
1544
  become(_other) { return false; }
1532
1545
  get type() { return BlockType.Text; }
@@ -2806,7 +2819,7 @@ class DocView extends ContentView {
2806
2819
  }
2807
2820
  }
2808
2821
  // If no workable line exists, force a layout of a measurable element
2809
- let dummy = document.createElement("div"), lineHeight, charWidth;
2822
+ let dummy = document.createElement("div"), lineHeight, charWidth, textHeight;
2810
2823
  dummy.className = "cm-line";
2811
2824
  dummy.style.width = "99999px";
2812
2825
  dummy.textContent = "abc def ghi jkl mno pqr stu";
@@ -2815,9 +2828,10 @@ class DocView extends ContentView {
2815
2828
  let rect = clientRectsFor(dummy.firstChild)[0];
2816
2829
  lineHeight = dummy.getBoundingClientRect().height;
2817
2830
  charWidth = rect ? rect.width / 27 : 7;
2831
+ textHeight = rect ? rect.height : lineHeight;
2818
2832
  dummy.remove();
2819
2833
  });
2820
- return { lineHeight, charWidth };
2834
+ return { lineHeight, charWidth, textHeight };
2821
2835
  }
2822
2836
  childCursor(pos = this.length) {
2823
2837
  // Move back to start of last element when possible, so that
@@ -2982,22 +2996,32 @@ class CompositionWidget extends WidgetType {
2982
2996
  ignoreEvent() { return false; }
2983
2997
  get customView() { return CompositionView; }
2984
2998
  }
2985
- function nearbyTextNode(node, offset, side) {
2986
- for (;;) {
2987
- if (node.nodeType == 3)
2988
- return node;
2989
- if (node.nodeType == 1 && offset > 0 && side <= 0) {
2990
- node = node.childNodes[offset - 1];
2991
- offset = maxOffset(node);
2992
- }
2993
- else if (node.nodeType == 1 && offset < node.childNodes.length && side >= 0) {
2994
- node = node.childNodes[offset];
2995
- offset = 0;
2999
+ function nearbyTextNode(startNode, startOffset, side) {
3000
+ if (side <= 0)
3001
+ for (let node = startNode, offset = startOffset;;) {
3002
+ if (node.nodeType == 3)
3003
+ return node;
3004
+ if (node.nodeType == 1 && offset > 0) {
3005
+ node = node.childNodes[offset - 1];
3006
+ offset = maxOffset(node);
3007
+ }
3008
+ else {
3009
+ break;
3010
+ }
2996
3011
  }
2997
- else {
2998
- return null;
3012
+ if (side >= 0)
3013
+ for (let node = startNode, offset = startOffset;;) {
3014
+ if (node.nodeType == 3)
3015
+ return node;
3016
+ if (node.nodeType == 1 && offset < node.childNodes.length && side >= 0) {
3017
+ node = node.childNodes[offset];
3018
+ offset = 0;
3019
+ }
3020
+ else {
3021
+ break;
3022
+ }
2999
3023
  }
3000
- }
3024
+ return null;
3001
3025
  }
3002
3026
  function nextToUneditable(node, offset) {
3003
3027
  if (node.nodeType != 1)
@@ -3161,7 +3185,7 @@ function domPosInText(node, x, y) {
3161
3185
  return { node, offset: closestOffset > -1 ? closestOffset : generalSide > 0 ? node.nodeValue.length : 0 };
3162
3186
  }
3163
3187
  function posAtCoords(view, coords, precise, bias = -1) {
3164
- var _a;
3188
+ var _a, _b;
3165
3189
  let content = view.contentDOM.getBoundingClientRect(), docTop = content.top + view.viewState.paddingTop;
3166
3190
  let block, { docHeight } = view.viewState;
3167
3191
  let { x, y } = coords, yOffset = y - docTop;
@@ -3238,7 +3262,7 @@ function posAtCoords(view, coords, precise, bias = -1) {
3238
3262
  let nearest = view.docView.nearest(node);
3239
3263
  if (!nearest)
3240
3264
  return null;
3241
- if (nearest.isWidget) {
3265
+ if (nearest.isWidget && ((_b = nearest.dom) === null || _b === void 0 ? void 0 : _b.nodeType) == 1) {
3242
3266
  let rect = nearest.dom.getBoundingClientRect();
3243
3267
  return coords.y < rect.top || coords.y <= rect.bottom && coords.x <= (rect.left + rect.right) / 2
3244
3268
  ? nearest.posAtStart : nearest.posAtEnd;
@@ -3433,8 +3457,16 @@ class InputState {
3433
3457
  this.registeredEvents.push(type);
3434
3458
  }
3435
3459
  view.scrollDOM.addEventListener("mousedown", (event) => {
3436
- if (event.target == view.scrollDOM && event.clientY > view.contentDOM.getBoundingClientRect().bottom)
3460
+ if (event.target == view.scrollDOM && event.clientY > view.contentDOM.getBoundingClientRect().bottom) {
3437
3461
  handleEvent(handlers.mousedown, event);
3462
+ if (!event.defaultPrevented && event.button == 2) {
3463
+ // Make sure the content covers the entire scroller height, in order
3464
+ // to catch a native context menu click below it
3465
+ let start = view.contentDOM.style.minHeight;
3466
+ view.contentDOM.style.minHeight = "100%";
3467
+ setTimeout(() => view.contentDOM.style.minHeight = start, 200);
3468
+ }
3469
+ }
3438
3470
  });
3439
3471
  if (browser.chrome && browser.chrome_version == 102) { // FIXME remove at some point
3440
3472
  // On Chrome 102, viewport updates somehow stop wheel-based
@@ -3968,7 +4000,7 @@ handlers.paste = (view, event) => {
3968
4000
  view.observer.flush();
3969
4001
  let data = brokenClipboardAPI ? null : event.clipboardData;
3970
4002
  if (data) {
3971
- doPaste(view, data.getData("text/plain"));
4003
+ doPaste(view, data.getData("text/plain") || data.getData("text/uri-text"));
3972
4004
  event.preventDefault();
3973
4005
  }
3974
4006
  else {
@@ -4128,8 +4160,9 @@ class HeightOracle {
4128
4160
  this.lineWrapping = lineWrapping;
4129
4161
  this.doc = Text.empty;
4130
4162
  this.heightSamples = {};
4131
- this.lineHeight = 14;
4163
+ this.lineHeight = 14; // The height of an entire line (line-height)
4132
4164
  this.charWidth = 7;
4165
+ this.textHeight = 14; // The height of the actual font (font-size)
4133
4166
  this.lineLength = 30;
4134
4167
  // Used to track, during updateHeight, if any actual heights changed
4135
4168
  this.heightChanged = false;
@@ -4164,12 +4197,13 @@ class HeightOracle {
4164
4197
  }
4165
4198
  return newHeight;
4166
4199
  }
4167
- refresh(whiteSpace, lineHeight, charWidth, lineLength, knownHeights) {
4200
+ refresh(whiteSpace, lineHeight, charWidth, textHeight, lineLength, knownHeights) {
4168
4201
  let lineWrapping = wrappingWhiteSpace.indexOf(whiteSpace) > -1;
4169
4202
  let changed = Math.round(lineHeight) != Math.round(this.lineHeight) || this.lineWrapping != lineWrapping;
4170
4203
  this.lineWrapping = lineWrapping;
4171
4204
  this.lineHeight = lineHeight;
4172
4205
  this.charWidth = charWidth;
4206
+ this.textHeight = textHeight;
4173
4207
  this.lineLength = lineLength;
4174
4208
  if (changed) {
4175
4209
  this.heightSamples = {};
@@ -5016,8 +5050,8 @@ class ViewState {
5016
5050
  if (oracle.mustRefreshForHeights(lineHeights))
5017
5051
  refresh = true;
5018
5052
  if (refresh || oracle.lineWrapping && Math.abs(contentWidth - this.contentDOMWidth) > oracle.charWidth) {
5019
- let { lineHeight, charWidth } = view.docView.measureTextSize();
5020
- refresh = lineHeight > 0 && oracle.refresh(whiteSpace, lineHeight, charWidth, contentWidth / charWidth, lineHeights);
5053
+ let { lineHeight, charWidth, textHeight } = view.docView.measureTextSize();
5054
+ refresh = lineHeight > 0 && oracle.refresh(whiteSpace, lineHeight, charWidth, textHeight, contentWidth / charWidth, lineHeights);
5021
5055
  if (refresh) {
5022
5056
  view.docView.minWidth = 0;
5023
5057
  result |= 8 /* UpdateFlag.Geometry */;
@@ -5428,6 +5462,9 @@ const baseTheme$1 = /*@__PURE__*/buildTheme("." + baseThemeID, {
5428
5462
  padding: "0 2px 0 6px"
5429
5463
  },
5430
5464
  ".cm-layer": {
5465
+ position: "absolute",
5466
+ left: 0,
5467
+ top: 0,
5431
5468
  contain: "size style",
5432
5469
  "& > *": {
5433
5470
  position: "absolute"
@@ -6588,7 +6625,7 @@ class EditorView {
6588
6625
  if (this.destroyed)
6589
6626
  return;
6590
6627
  if (this.measureScheduled > -1)
6591
- cancelAnimationFrame(this.measureScheduled);
6628
+ this.win.cancelAnimationFrame(this.measureScheduled);
6592
6629
  this.measureScheduled = 0; // Prevent requestMeasure calls from scheduling another animation frame
6593
6630
  if (flush)
6594
6631
  this.observer.forceFlush();
@@ -7026,7 +7063,7 @@ class EditorView {
7026
7063
  this.dom.remove();
7027
7064
  this.observer.destroy();
7028
7065
  if (this.measureScheduled > -1)
7029
- cancelAnimationFrame(this.measureScheduled);
7066
+ this.win.cancelAnimationFrame(this.measureScheduled);
7030
7067
  this.destroyed = true;
7031
7068
  }
7032
7069
  /**
@@ -7538,9 +7575,10 @@ function rectanglesForRange(view, className, range) {
7538
7575
  let from = Math.max(range.from, view.viewport.from), to = Math.min(range.to, view.viewport.to);
7539
7576
  let ltr = view.textDirection == Direction.LTR;
7540
7577
  let content = view.contentDOM, contentRect = content.getBoundingClientRect(), base = getBase(view);
7541
- let lineStyle = window.getComputedStyle(content.firstChild);
7542
- let leftSide = contentRect.left + parseInt(lineStyle.paddingLeft) + Math.min(0, parseInt(lineStyle.textIndent));
7543
- let rightSide = contentRect.right - parseInt(lineStyle.paddingRight);
7578
+ let lineElt = content.querySelector(".cm-line"), lineStyle = lineElt && window.getComputedStyle(lineElt);
7579
+ let leftSide = contentRect.left +
7580
+ (lineStyle ? parseInt(lineStyle.paddingLeft) + Math.min(0, parseInt(lineStyle.textIndent)) : 0);
7581
+ let rightSide = contentRect.right - (lineStyle ? parseInt(lineStyle.paddingRight) : 0);
7544
7582
  let startBlock = blockAt(view, from), endBlock = blockAt(view, to);
7545
7583
  let visualStart = startBlock.type == BlockType.Text ? startBlock : null;
7546
7584
  let visualEnd = endBlock.type == BlockType.Text ? endBlock : null;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@codemirror/view",
3
- "version": "6.9.1",
3
+ "version": "6.9.3",
4
4
  "description": "DOM view component for the CodeMirror code editor",
5
5
  "scripts": {
6
6
  "test": "cm-runtests",