@codemirror/view 0.19.16 → 0.19.20

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,27 @@
1
+ ## 0.19.20 (2021-11-19)
2
+
3
+ ### Bug fixes
4
+
5
+ Run a measure cycle when the editor's size spontaneously changes.
6
+
7
+ ## 0.19.19 (2021-11-17)
8
+
9
+ ### Bug fixes
10
+
11
+ Fix a bug that caused the precedence of `editorAttributes` and `contentAttributes` to be inverted, making lower-precedence extensions override higher-precedence ones.
12
+
13
+ ## 0.19.18 (2021-11-16)
14
+
15
+ ### Bug fixes
16
+
17
+ Fix an issue where the editor wasn't aware it was line-wrapping with its own `lineWrapping` extension enabled.
18
+
19
+ ## 0.19.17 (2021-11-16)
20
+
21
+ ### Bug fixes
22
+
23
+ Avoid an issue where stretches of whitespace on line wrap points could cause the cursor to be placed outside of the content.
24
+
1
25
  ## 0.19.16 (2021-11-11)
2
26
 
3
27
  ### Breaking changes
package/dist/index.cjs CHANGED
@@ -666,7 +666,7 @@ function textCoords(text, pos, side) {
666
666
  let rect = rects[(flatten ? flatten < 0 : side >= 0) ? 0 : rects.length - 1];
667
667
  if (browser.safari && !flatten && rect.width == 0)
668
668
  rect = Array.prototype.find.call(rects, r => r.width) || rect;
669
- return flatten ? flattenRect(rect, flatten < 0) : rect;
669
+ return flatten ? flattenRect(rect, flatten < 0) : rect || null;
670
670
  }
671
671
  // Also used for collapsed ranges that don't have a placeholder widget!
672
672
  class WidgetView extends InlineView {
@@ -774,7 +774,7 @@ class WidgetBufferView extends InlineView {
774
774
  domBoundsAround() { return null; }
775
775
  coordsAt(pos) {
776
776
  let rects = clientRectsFor(this.dom);
777
- return rects[rects.length - 1];
777
+ return rects[rects.length - 1] || null;
778
778
  }
779
779
  get overrideDOMText() {
780
780
  return text.Text.of([this.dom.nodeValue.replace(/\u200b/g, "")]);
@@ -916,7 +916,7 @@ function coordsInChildren(view, pos, side) {
916
916
  if (!last)
917
917
  return view.dom.getBoundingClientRect();
918
918
  let rects = clientRectsFor(last);
919
- return rects[rects.length - 1];
919
+ return rects[rects.length - 1] || null;
920
920
  }
921
921
 
922
922
  function combineAttrs(source, target) {
@@ -1771,11 +1771,17 @@ class PluginInstance {
1771
1771
  }
1772
1772
  }
1773
1773
  PluginInstance.dummy = new PluginInstance(ViewPlugin.define(() => ({})));
1774
+ function combineFacetAttrs(values) {
1775
+ let result = {};
1776
+ for (let i = values.length - 1; i >= 0; i--)
1777
+ combineAttrs(values[i], result);
1778
+ return result;
1779
+ }
1774
1780
  const editorAttributes = state.Facet.define({
1775
- combine: values => values.reduce((a, b) => combineAttrs(b, a), {})
1781
+ combine: combineFacetAttrs
1776
1782
  });
1777
1783
  const contentAttributes = state.Facet.define({
1778
- combine: values => values.reduce((a, b) => combineAttrs(b, a), {})
1784
+ combine: combineFacetAttrs
1779
1785
  });
1780
1786
  // Provide decorations
1781
1787
  const decorations = state.Facet.define();
@@ -1937,6 +1943,9 @@ class DocView extends ContentView {
1937
1943
  // we don't mess it up when reading it back it
1938
1944
  this.impreciseAnchor = null;
1939
1945
  this.impreciseHead = null;
1946
+ // Used by the resize observer to ignore resizes that we caused
1947
+ // ourselves
1948
+ this.lastUpdate = 0;
1940
1949
  this.setDOM(view.contentDOM);
1941
1950
  this.children = [new LineView];
1942
1951
  this.children[0].setParent(this);
@@ -1950,6 +1959,7 @@ class DocView extends ContentView {
1950
1959
  // position, if we know the editor is going to scroll that position
1951
1960
  // into view.
1952
1961
  update(update) {
1962
+ this.lastUpdate = Date.now();
1953
1963
  let changedRanges = update.changedRanges;
1954
1964
  if (this.minWidth > 0 && changedRanges.length) {
1955
1965
  if (!changedRanges.every(({ fromA, toA }) => toA < this.minWidthFrom || fromA > this.minWidthTo)) {
@@ -3742,7 +3752,7 @@ handlers.beforeinput = (view, event) => {
3742
3752
  }
3743
3753
  };
3744
3754
 
3745
- const wrappingWhiteSpace = ["pre-wrap", "normal", "pre-line"];
3755
+ const wrappingWhiteSpace = ["pre-wrap", "normal", "pre-line", "break-spaces"];
3746
3756
  class HeightOracle {
3747
3757
  constructor() {
3748
3758
  this.doc = text.Text.empty;
@@ -4476,6 +4486,7 @@ class ViewState {
4476
4486
  this.paddingTop = 0;
4477
4487
  this.paddingBottom = 0;
4478
4488
  this.contentWidth = 0;
4489
+ this.editorHeight = 0;
4479
4490
  this.heightOracle = new HeightOracle;
4480
4491
  // See VP.MaxDOMHeight
4481
4492
  this.scaler = IdScaler;
@@ -4575,6 +4586,10 @@ class ViewState {
4575
4586
  this.contentWidth = contentWidth;
4576
4587
  result |= 8 /* Geometry */;
4577
4588
  }
4589
+ if (this.editorHeight != docView.view.scrollDOM.clientHeight) {
4590
+ this.editorHeight = docView.view.scrollDOM.clientHeight;
4591
+ result |= 8 /* Geometry */;
4592
+ }
4578
4593
  if (dTop > 0 && dBottom > 0)
4579
4594
  bias = Math.max(dTop, dBottom);
4580
4595
  else if (dTop < 0 && dBottom < 0)
@@ -4938,7 +4953,8 @@ const baseTheme = buildTheme("." + baseThemeID, {
4938
4953
  }
4939
4954
  },
4940
4955
  ".cm-lineWrapping": {
4941
- whiteSpace: "pre-wrap",
4956
+ whiteSpace_fallback: "pre-wrap",
4957
+ whiteSpace: "break-spaces",
4942
4958
  wordBreak: "break-word",
4943
4959
  overflowWrap: "anywhere"
4944
4960
  },
@@ -5065,6 +5081,7 @@ class DOMObserver {
5065
5081
  this.lastFlush = 0;
5066
5082
  this.scrollTargets = [];
5067
5083
  this.intersection = null;
5084
+ this.resize = null;
5068
5085
  this.intersecting = false;
5069
5086
  this.gapIntersection = null;
5070
5087
  this.gaps = [];
@@ -5101,6 +5118,13 @@ class DOMObserver {
5101
5118
  this.flushSoon();
5102
5119
  };
5103
5120
  this.onSelectionChange = this.onSelectionChange.bind(this);
5121
+ if (typeof ResizeObserver == "function") {
5122
+ this.resize = new ResizeObserver(() => {
5123
+ if (this.view.docView.lastUpdate < Date.now() - 100)
5124
+ this.view.requestMeasure();
5125
+ });
5126
+ this.resize.observe(view.scrollDOM);
5127
+ }
5104
5128
  this.start();
5105
5129
  this.onScroll = this.onScroll.bind(this);
5106
5130
  window.addEventListener("scroll", this.onScroll);
@@ -5314,11 +5338,11 @@ class DOMObserver {
5314
5338
  }
5315
5339
  }
5316
5340
  destroy() {
5341
+ var _a, _b, _c;
5317
5342
  this.stop();
5318
- if (this.intersection)
5319
- this.intersection.disconnect();
5320
- if (this.gapIntersection)
5321
- this.gapIntersection.disconnect();
5343
+ (_a = this.intersection) === null || _a === void 0 ? void 0 : _a.disconnect();
5344
+ (_b = this.gapIntersection) === null || _b === void 0 ? void 0 : _b.disconnect();
5345
+ (_c = this.resize) === null || _c === void 0 ? void 0 : _c.disconnect();
5322
5346
  for (let dom of this.scrollTargets)
5323
5347
  dom.removeEventListener("scroll", this.onScroll);
5324
5348
  window.removeEventListener("scroll", this.onScroll);
@@ -5831,7 +5855,7 @@ class EditorView {
5831
5855
  return;
5832
5856
  if (this.measureScheduled > -1)
5833
5857
  cancelAnimationFrame(this.measureScheduled);
5834
- this.measureScheduled = -1; // Prevent requestMeasure calls from scheduling another animation frame
5858
+ this.measureScheduled = 0; // Prevent requestMeasure calls from scheduling another animation frame
5835
5859
  if (flush)
5836
5860
  this.observer.flush();
5837
5861
  let updated = null;
@@ -5892,8 +5916,8 @@ class EditorView {
5892
5916
  }
5893
5917
  finally {
5894
5918
  this.updateState = 0 /* Idle */;
5919
+ this.measureScheduled = -1;
5895
5920
  }
5896
- this.measureScheduled = -1;
5897
5921
  if (updated && !updated.empty)
5898
5922
  for (let listener of this.state.facet(updateListener))
5899
5923
  listener(updated);
package/dist/index.js CHANGED
@@ -663,7 +663,7 @@ function textCoords(text, pos, side) {
663
663
  let rect = rects[(flatten ? flatten < 0 : side >= 0) ? 0 : rects.length - 1];
664
664
  if (browser.safari && !flatten && rect.width == 0)
665
665
  rect = Array.prototype.find.call(rects, r => r.width) || rect;
666
- return flatten ? flattenRect(rect, flatten < 0) : rect;
666
+ return flatten ? flattenRect(rect, flatten < 0) : rect || null;
667
667
  }
668
668
  // Also used for collapsed ranges that don't have a placeholder widget!
669
669
  class WidgetView extends InlineView {
@@ -771,7 +771,7 @@ class WidgetBufferView extends InlineView {
771
771
  domBoundsAround() { return null; }
772
772
  coordsAt(pos) {
773
773
  let rects = clientRectsFor(this.dom);
774
- return rects[rects.length - 1];
774
+ return rects[rects.length - 1] || null;
775
775
  }
776
776
  get overrideDOMText() {
777
777
  return Text.of([this.dom.nodeValue.replace(/\u200b/g, "")]);
@@ -913,7 +913,7 @@ function coordsInChildren(view, pos, side) {
913
913
  if (!last)
914
914
  return view.dom.getBoundingClientRect();
915
915
  let rects = clientRectsFor(last);
916
- return rects[rects.length - 1];
916
+ return rects[rects.length - 1] || null;
917
917
  }
918
918
 
919
919
  function combineAttrs(source, target) {
@@ -1767,11 +1767,17 @@ class PluginInstance {
1767
1767
  }
1768
1768
  }
1769
1769
  PluginInstance.dummy = /*@__PURE__*/new PluginInstance(/*@__PURE__*/ViewPlugin.define(() => ({})));
1770
+ function combineFacetAttrs(values) {
1771
+ let result = {};
1772
+ for (let i = values.length - 1; i >= 0; i--)
1773
+ combineAttrs(values[i], result);
1774
+ return result;
1775
+ }
1770
1776
  const editorAttributes = /*@__PURE__*/Facet.define({
1771
- combine: values => values.reduce((a, b) => combineAttrs(b, a), {})
1777
+ combine: combineFacetAttrs
1772
1778
  });
1773
1779
  const contentAttributes = /*@__PURE__*/Facet.define({
1774
- combine: values => values.reduce((a, b) => combineAttrs(b, a), {})
1780
+ combine: combineFacetAttrs
1775
1781
  });
1776
1782
  // Provide decorations
1777
1783
  const decorations = /*@__PURE__*/Facet.define();
@@ -1933,6 +1939,9 @@ class DocView extends ContentView {
1933
1939
  // we don't mess it up when reading it back it
1934
1940
  this.impreciseAnchor = null;
1935
1941
  this.impreciseHead = null;
1942
+ // Used by the resize observer to ignore resizes that we caused
1943
+ // ourselves
1944
+ this.lastUpdate = 0;
1936
1945
  this.setDOM(view.contentDOM);
1937
1946
  this.children = [new LineView];
1938
1947
  this.children[0].setParent(this);
@@ -1946,6 +1955,7 @@ class DocView extends ContentView {
1946
1955
  // position, if we know the editor is going to scroll that position
1947
1956
  // into view.
1948
1957
  update(update) {
1958
+ this.lastUpdate = Date.now();
1949
1959
  let changedRanges = update.changedRanges;
1950
1960
  if (this.minWidth > 0 && changedRanges.length) {
1951
1961
  if (!changedRanges.every(({ fromA, toA }) => toA < this.minWidthFrom || fromA > this.minWidthTo)) {
@@ -3737,7 +3747,7 @@ handlers.beforeinput = (view, event) => {
3737
3747
  }
3738
3748
  };
3739
3749
 
3740
- const wrappingWhiteSpace = ["pre-wrap", "normal", "pre-line"];
3750
+ const wrappingWhiteSpace = ["pre-wrap", "normal", "pre-line", "break-spaces"];
3741
3751
  class HeightOracle {
3742
3752
  constructor() {
3743
3753
  this.doc = Text.empty;
@@ -4470,6 +4480,7 @@ class ViewState {
4470
4480
  this.paddingTop = 0;
4471
4481
  this.paddingBottom = 0;
4472
4482
  this.contentWidth = 0;
4483
+ this.editorHeight = 0;
4473
4484
  this.heightOracle = new HeightOracle;
4474
4485
  // See VP.MaxDOMHeight
4475
4486
  this.scaler = IdScaler;
@@ -4569,6 +4580,10 @@ class ViewState {
4569
4580
  this.contentWidth = contentWidth;
4570
4581
  result |= 8 /* Geometry */;
4571
4582
  }
4583
+ if (this.editorHeight != docView.view.scrollDOM.clientHeight) {
4584
+ this.editorHeight = docView.view.scrollDOM.clientHeight;
4585
+ result |= 8 /* Geometry */;
4586
+ }
4572
4587
  if (dTop > 0 && dBottom > 0)
4573
4588
  bias = Math.max(dTop, dBottom);
4574
4589
  else if (dTop < 0 && dBottom < 0)
@@ -4932,7 +4947,8 @@ const baseTheme = /*@__PURE__*/buildTheme("." + baseThemeID, {
4932
4947
  }
4933
4948
  },
4934
4949
  ".cm-lineWrapping": {
4935
- whiteSpace: "pre-wrap",
4950
+ whiteSpace_fallback: "pre-wrap",
4951
+ whiteSpace: "break-spaces",
4936
4952
  wordBreak: "break-word",
4937
4953
  overflowWrap: "anywhere"
4938
4954
  },
@@ -5059,6 +5075,7 @@ class DOMObserver {
5059
5075
  this.lastFlush = 0;
5060
5076
  this.scrollTargets = [];
5061
5077
  this.intersection = null;
5078
+ this.resize = null;
5062
5079
  this.intersecting = false;
5063
5080
  this.gapIntersection = null;
5064
5081
  this.gaps = [];
@@ -5095,6 +5112,13 @@ class DOMObserver {
5095
5112
  this.flushSoon();
5096
5113
  };
5097
5114
  this.onSelectionChange = this.onSelectionChange.bind(this);
5115
+ if (typeof ResizeObserver == "function") {
5116
+ this.resize = new ResizeObserver(() => {
5117
+ if (this.view.docView.lastUpdate < Date.now() - 100)
5118
+ this.view.requestMeasure();
5119
+ });
5120
+ this.resize.observe(view.scrollDOM);
5121
+ }
5098
5122
  this.start();
5099
5123
  this.onScroll = this.onScroll.bind(this);
5100
5124
  window.addEventListener("scroll", this.onScroll);
@@ -5308,11 +5332,11 @@ class DOMObserver {
5308
5332
  }
5309
5333
  }
5310
5334
  destroy() {
5335
+ var _a, _b, _c;
5311
5336
  this.stop();
5312
- if (this.intersection)
5313
- this.intersection.disconnect();
5314
- if (this.gapIntersection)
5315
- this.gapIntersection.disconnect();
5337
+ (_a = this.intersection) === null || _a === void 0 ? void 0 : _a.disconnect();
5338
+ (_b = this.gapIntersection) === null || _b === void 0 ? void 0 : _b.disconnect();
5339
+ (_c = this.resize) === null || _c === void 0 ? void 0 : _c.disconnect();
5316
5340
  for (let dom of this.scrollTargets)
5317
5341
  dom.removeEventListener("scroll", this.onScroll);
5318
5342
  window.removeEventListener("scroll", this.onScroll);
@@ -5825,7 +5849,7 @@ class EditorView {
5825
5849
  return;
5826
5850
  if (this.measureScheduled > -1)
5827
5851
  cancelAnimationFrame(this.measureScheduled);
5828
- this.measureScheduled = -1; // Prevent requestMeasure calls from scheduling another animation frame
5852
+ this.measureScheduled = 0; // Prevent requestMeasure calls from scheduling another animation frame
5829
5853
  if (flush)
5830
5854
  this.observer.flush();
5831
5855
  let updated = null;
@@ -5886,8 +5910,8 @@ class EditorView {
5886
5910
  }
5887
5911
  finally {
5888
5912
  this.updateState = 0 /* Idle */;
5913
+ this.measureScheduled = -1;
5889
5914
  }
5890
- this.measureScheduled = -1;
5891
5915
  if (updated && !updated.empty)
5892
5916
  for (let listener of this.state.facet(updateListener))
5893
5917
  listener(updated);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@codemirror/view",
3
- "version": "0.19.16",
3
+ "version": "0.19.20",
4
4
  "description": "DOM view component for the CodeMirror code editor",
5
5
  "scripts": {
6
6
  "test": "cm-runtests",