@codemirror/view 0.20.2 → 0.20.5

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
+ ## 0.20.5 (2022-05-18)
2
+
3
+ ### Bug fixes
4
+
5
+ Fix an issue where gutter elements without any markers in them would not get the `cm-gutterElement` class assigned.
6
+
7
+ Fix an issue where DOM event handlers registered by plugins were retained indefinitely, even after the editor was reconfigured.
8
+
9
+ ## 0.20.4 (2022-05-03)
10
+
11
+ ### Bug fixes
12
+
13
+ Prevent Mac-style behavior of inserting a period when the user inserts two spaces.
14
+
15
+ Fix an issue where the editor would sometimes not restore the DOM selection when refocused with a selection identical to the one it held when it lost focus.
16
+
17
+ ## 0.20.3 (2022-04-27)
18
+
19
+ ### Bug fixes
20
+
21
+ Fix a bug where the input handling could crash on repeated (or held) backspace presses on Chrome Android.
22
+
1
23
  ## 0.20.2 (2022-04-22)
2
24
 
3
25
  ### New features
package/dist/index.cjs CHANGED
@@ -1157,9 +1157,6 @@ of content. You'll usually use it wrapped in a
1157
1157
  @nonabstract
1158
1158
  */
1159
1159
  class Decoration extends state.RangeValue {
1160
- /**
1161
- @internal
1162
- */
1163
1160
  constructor(
1164
1161
  /**
1165
1162
  @internal
@@ -1704,7 +1701,6 @@ class NullWidget extends WidgetType {
1704
1701
  updateDOM(elt) { return elt.nodeName.toLowerCase() == this.tag; }
1705
1702
  }
1706
1703
 
1707
- const none = [];
1708
1704
  const clickAddsSelectionRange = state.Facet.define();
1709
1705
  const dragMovesSelection$1 = state.Facet.define();
1710
1706
  const mouseSelectionStyle = state.Facet.define();
@@ -1923,9 +1919,6 @@ View [plugins](https://codemirror.net/6/docs/ref/#view.ViewPlugin) are given ins
1923
1919
  class, which describe what happened, whenever the view is updated.
1924
1920
  */
1925
1921
  class ViewUpdate {
1926
- /**
1927
- @internal
1928
- */
1929
1922
  constructor(
1930
1923
  /**
1931
1924
  The editor view that the update is associated with.
@@ -1938,7 +1931,7 @@ class ViewUpdate {
1938
1931
  /**
1939
1932
  The transactions involved in the update. May be empty.
1940
1933
  */
1941
- transactions = none) {
1934
+ transactions) {
1942
1935
  this.view = view;
1943
1936
  this.state = state$1;
1944
1937
  this.transactions = transactions;
@@ -1960,6 +1953,12 @@ class ViewUpdate {
1960
1953
  }
1961
1954
  }
1962
1955
  /**
1956
+ @internal
1957
+ */
1958
+ static create(view, state, transactions) {
1959
+ return new ViewUpdate(view, state, transactions);
1960
+ }
1961
+ /**
1963
1962
  Tells you whether the [viewport](https://codemirror.net/6/docs/ref/#view.EditorView.viewport) or
1964
1963
  [visible ranges](https://codemirror.net/6/docs/ref/#view.EditorView.visibleRanges) changed in this
1965
1964
  update.
@@ -2880,7 +2879,8 @@ function computeCompositionDeco(view, changes) {
2880
2879
  topView = topView.widget.topView;
2881
2880
  else if (topView)
2882
2881
  topView.parent = null;
2883
- return Decoration.set(Decoration.replace({ widget: new CompositionWidget(node, textNode, topView) }).range(newFrom, newTo));
2882
+ return Decoration.set(Decoration.replace({ widget: new CompositionWidget(node, textNode, topView), inclusive: true })
2883
+ .range(newFrom, newTo));
2884
2884
  }
2885
2885
  class CompositionWidget extends WidgetType {
2886
2886
  constructor(top, text, topView) {
@@ -3319,6 +3319,7 @@ class InputState {
3319
3319
  ensureHandlers(view, plugins) {
3320
3320
  var _a;
3321
3321
  let handlers;
3322
+ this.customHandlers = [];
3322
3323
  for (let plugin of plugins)
3323
3324
  if (handlers = (_a = plugin.update(view).spec) === null || _a === void 0 ? void 0 : _a.domEventHandlers) {
3324
3325
  this.customHandlers.push({ plugin: plugin.value, handlers });
@@ -3844,11 +3845,16 @@ handlers.copy = handlers.cut = (view, event) => {
3844
3845
  userEvent: "delete.cut"
3845
3846
  });
3846
3847
  };
3847
- handlers.focus = handlers.blur = view => {
3848
+ function updateForFocusChange(view) {
3848
3849
  setTimeout(() => {
3849
3850
  if (view.hasFocus != view.inputState.notifiedFocused)
3850
3851
  view.update([]);
3851
3852
  }, 10);
3853
+ }
3854
+ handlers.focus = updateForFocusChange;
3855
+ handlers.blur = view => {
3856
+ view.observer.clearSelectionRange();
3857
+ updateForFocusChange(view);
3852
3858
  };
3853
3859
  function forceClearComposition(view, rapid) {
3854
3860
  if (view.docView.compositionDeco.size) {
@@ -5486,6 +5492,9 @@ class DOMObserver {
5486
5492
  this.selectionRange.set(anchor.node, anchor.offset, head.node, head.offset);
5487
5493
  this.selectionChanged = false;
5488
5494
  }
5495
+ clearSelectionRange() {
5496
+ this.selectionRange.set(null, 0, null, 0);
5497
+ }
5489
5498
  listenForScroll() {
5490
5499
  this.parentCheck = -1;
5491
5500
  let i = 0, changed = null;
@@ -5563,6 +5572,7 @@ class DOMObserver {
5563
5572
  let key = this.delayedAndroidKey;
5564
5573
  this.delayedAndroidKey = null;
5565
5574
  let startState = this.view.state;
5575
+ this.readSelectionRange();
5566
5576
  if (dispatchKey(this.view.contentDOM, key.key, key.keyCode))
5567
5577
  this.processRecords();
5568
5578
  else
@@ -5764,6 +5774,11 @@ function applyDOMChange(view, start, end, typeOver) {
5764
5774
  from: sel.from, to: sel.to,
5765
5775
  insert: view.state.doc.slice(sel.from, change.from).append(change.insert).append(view.state.doc.slice(change.to, sel.to))
5766
5776
  };
5777
+ // Detect insert-period-on-double-space Mac behavior, and transform
5778
+ // it into a regular space insert.
5779
+ else if (browser.mac && change && change.from == change.to && change.from == sel.head - 1 &&
5780
+ change.insert.toString() == ".")
5781
+ change = { from: sel.from, to: sel.to, insert: state.Text.of([" "]) };
5767
5782
  if (change) {
5768
5783
  let startState = view.state;
5769
5784
  if (browser.ios && view.inputState.flushIOSKey(view))
@@ -6052,7 +6067,7 @@ class EditorView {
6052
6067
  // When the phrases change, redraw the editor
6053
6068
  if (state$1.facet(state.EditorState.phrases) != this.state.facet(state.EditorState.phrases))
6054
6069
  return this.setState(state$1);
6055
- update = new ViewUpdate(this, state$1, transactions);
6070
+ update = ViewUpdate.create(this, state$1, transactions);
6056
6071
  let scrollTarget = this.viewState.scrollTarget;
6057
6072
  try {
6058
6073
  this.updateState = 2 /* Updating */;
@@ -6195,7 +6210,7 @@ class EditorView {
6195
6210
  return BadMeasure;
6196
6211
  }
6197
6212
  });
6198
- let update = new ViewUpdate(this, this.state), redrawn = false, scrolled = false;
6213
+ let update = ViewUpdate.create(this, this.state, []), redrawn = false, scrolled = false;
6199
6214
  update.flags |= changed;
6200
6215
  if (!updated)
6201
6216
  updated = update;
@@ -6655,8 +6670,8 @@ EditorView.inputHandler = inputHandler;
6655
6670
  /**
6656
6671
  By default, the editor assumes all its content has the same
6657
6672
  [text direction](https://codemirror.net/6/docs/ref/#view.Direction). Configure this with a `true`
6658
- value to make it read and store the text direction of every
6659
- (rendered) line separately.
6673
+ value to make it read the text direction of every (rendered)
6674
+ line separately.
6660
6675
  */
6661
6676
  EditorView.perLineTextDirection = perLineTextDirection;
6662
6677
  /**
@@ -8167,7 +8182,6 @@ class HoverPlugin {
8167
8182
  this.startHover();
8168
8183
  }
8169
8184
  startHover() {
8170
- var _a;
8171
8185
  clearTimeout(this.restartTimeout);
8172
8186
  let { lastMove } = this;
8173
8187
  let pos = this.view.contentDOM.contains(lastMove.target) ? this.view.posAtCoords(lastMove) : null;
@@ -8181,7 +8195,7 @@ class HoverPlugin {
8181
8195
  let bidi = this.view.bidiSpans(this.view.state.doc.lineAt(pos)).find(s => s.from <= pos && s.to >= pos);
8182
8196
  let rtl = bidi && bidi.dir == exports.Direction.RTL ? -1 : 1;
8183
8197
  let open = this.source(this.view, pos, (lastMove.x < posCoords.left ? -rtl : rtl));
8184
- if ((_a = open) === null || _a === void 0 ? void 0 : _a.then) {
8198
+ if (open === null || open === void 0 ? void 0 : open.then) {
8185
8199
  let pending = this.pending = { pos };
8186
8200
  open.then(result => {
8187
8201
  if (this.pending == pending) {
@@ -8781,6 +8795,7 @@ class GutterElement {
8781
8795
  this.above = 0;
8782
8796
  this.markers = [];
8783
8797
  this.dom = document.createElement("div");
8798
+ this.dom.className = "cm-gutterElement";
8784
8799
  this.update(view, height, above, markers);
8785
8800
  }
8786
8801
  update(view, height, above, markers) {
package/dist/index.d.ts CHANGED
@@ -214,6 +214,25 @@ declare abstract class Decoration extends RangeValue {
214
214
  your decoration.
215
215
  */
216
216
  readonly spec: any;
217
+ protected constructor(
218
+ /**
219
+ @internal
220
+ */
221
+ startSide: number,
222
+ /**
223
+ @internal
224
+ */
225
+ endSide: number,
226
+ /**
227
+ @internal
228
+ */
229
+ widget: WidgetType | null,
230
+ /**
231
+ The config object used to create this decoration. You can
232
+ include additional properties in there to store metadata about
233
+ your decoration.
234
+ */
235
+ spec: any);
217
236
  abstract eq(other: Decoration): boolean;
218
237
  /**
219
238
  Create a mark decoration, which influences the styling of the
@@ -324,10 +343,10 @@ interface PluginSpec<V extends PluginValue> {
324
343
  provide?: (plugin: ViewPlugin<V>) => Extension;
325
344
  /**
326
345
  Allow the plugin to provide decorations. When given, this should
327
- a function that take the plugin value and return a [decoration
328
- set](https://codemirror.net/6/docs/ref/#view.DecorationSet). See also the caveat about
329
- [layout-changing decorations](https://codemirror.net/6/docs/ref/#view.EditorView^decorations)
330
- that depend on the view.
346
+ be a function that take the plugin value and return a
347
+ [decoration set](https://codemirror.net/6/docs/ref/#view.DecorationSet). See also the caveat about
348
+ [layout-changing decorations](https://codemirror.net/6/docs/ref/#view.EditorView^decorations) that
349
+ depend on the view.
331
350
  */
332
351
  decorations?: (value: V) => DecorationSet;
333
352
  }
@@ -398,6 +417,7 @@ declare class ViewUpdate {
398
417
  The previous editor state.
399
418
  */
400
419
  readonly startState: EditorState;
420
+ private constructor();
401
421
  /**
402
422
  Tells you whether the [viewport](https://codemirror.net/6/docs/ref/#view.EditorView.viewport) or
403
423
  [visible ranges](https://codemirror.net/6/docs/ref/#view.EditorView.visibleRanges) changed in this
@@ -968,8 +988,8 @@ declare class EditorView {
968
988
  /**
969
989
  By default, the editor assumes all its content has the same
970
990
  [text direction](https://codemirror.net/6/docs/ref/#view.Direction). Configure this with a `true`
971
- value to make it read and store the text direction of every
972
- (rendered) line separately.
991
+ value to make it read the text direction of every (rendered)
992
+ line separately.
973
993
  */
974
994
  static perLineTextDirection: Facet<boolean, boolean>;
975
995
  /**
package/dist/index.js CHANGED
@@ -1152,9 +1152,6 @@ of content. You'll usually use it wrapped in a
1152
1152
  @nonabstract
1153
1153
  */
1154
1154
  class Decoration extends RangeValue {
1155
- /**
1156
- @internal
1157
- */
1158
1155
  constructor(
1159
1156
  /**
1160
1157
  @internal
@@ -1699,7 +1696,6 @@ class NullWidget extends WidgetType {
1699
1696
  updateDOM(elt) { return elt.nodeName.toLowerCase() == this.tag; }
1700
1697
  }
1701
1698
 
1702
- const none = [];
1703
1699
  const clickAddsSelectionRange = /*@__PURE__*/Facet.define();
1704
1700
  const dragMovesSelection$1 = /*@__PURE__*/Facet.define();
1705
1701
  const mouseSelectionStyle = /*@__PURE__*/Facet.define();
@@ -1918,9 +1914,6 @@ View [plugins](https://codemirror.net/6/docs/ref/#view.ViewPlugin) are given ins
1918
1914
  class, which describe what happened, whenever the view is updated.
1919
1915
  */
1920
1916
  class ViewUpdate {
1921
- /**
1922
- @internal
1923
- */
1924
1917
  constructor(
1925
1918
  /**
1926
1919
  The editor view that the update is associated with.
@@ -1933,7 +1926,7 @@ class ViewUpdate {
1933
1926
  /**
1934
1927
  The transactions involved in the update. May be empty.
1935
1928
  */
1936
- transactions = none) {
1929
+ transactions) {
1937
1930
  this.view = view;
1938
1931
  this.state = state;
1939
1932
  this.transactions = transactions;
@@ -1955,6 +1948,12 @@ class ViewUpdate {
1955
1948
  }
1956
1949
  }
1957
1950
  /**
1951
+ @internal
1952
+ */
1953
+ static create(view, state, transactions) {
1954
+ return new ViewUpdate(view, state, transactions);
1955
+ }
1956
+ /**
1958
1957
  Tells you whether the [viewport](https://codemirror.net/6/docs/ref/#view.EditorView.viewport) or
1959
1958
  [visible ranges](https://codemirror.net/6/docs/ref/#view.EditorView.visibleRanges) changed in this
1960
1959
  update.
@@ -2874,7 +2873,8 @@ function computeCompositionDeco(view, changes) {
2874
2873
  topView = topView.widget.topView;
2875
2874
  else if (topView)
2876
2875
  topView.parent = null;
2877
- return Decoration.set(Decoration.replace({ widget: new CompositionWidget(node, textNode, topView) }).range(newFrom, newTo));
2876
+ return Decoration.set(Decoration.replace({ widget: new CompositionWidget(node, textNode, topView), inclusive: true })
2877
+ .range(newFrom, newTo));
2878
2878
  }
2879
2879
  class CompositionWidget extends WidgetType {
2880
2880
  constructor(top, text, topView) {
@@ -3313,6 +3313,7 @@ class InputState {
3313
3313
  ensureHandlers(view, plugins) {
3314
3314
  var _a;
3315
3315
  let handlers;
3316
+ this.customHandlers = [];
3316
3317
  for (let plugin of plugins)
3317
3318
  if (handlers = (_a = plugin.update(view).spec) === null || _a === void 0 ? void 0 : _a.domEventHandlers) {
3318
3319
  this.customHandlers.push({ plugin: plugin.value, handlers });
@@ -3838,11 +3839,16 @@ handlers.copy = handlers.cut = (view, event) => {
3838
3839
  userEvent: "delete.cut"
3839
3840
  });
3840
3841
  };
3841
- handlers.focus = handlers.blur = view => {
3842
+ function updateForFocusChange(view) {
3842
3843
  setTimeout(() => {
3843
3844
  if (view.hasFocus != view.inputState.notifiedFocused)
3844
3845
  view.update([]);
3845
3846
  }, 10);
3847
+ }
3848
+ handlers.focus = updateForFocusChange;
3849
+ handlers.blur = view => {
3850
+ view.observer.clearSelectionRange();
3851
+ updateForFocusChange(view);
3846
3852
  };
3847
3853
  function forceClearComposition(view, rapid) {
3848
3854
  if (view.docView.compositionDeco.size) {
@@ -5479,6 +5485,9 @@ class DOMObserver {
5479
5485
  this.selectionRange.set(anchor.node, anchor.offset, head.node, head.offset);
5480
5486
  this.selectionChanged = false;
5481
5487
  }
5488
+ clearSelectionRange() {
5489
+ this.selectionRange.set(null, 0, null, 0);
5490
+ }
5482
5491
  listenForScroll() {
5483
5492
  this.parentCheck = -1;
5484
5493
  let i = 0, changed = null;
@@ -5556,6 +5565,7 @@ class DOMObserver {
5556
5565
  let key = this.delayedAndroidKey;
5557
5566
  this.delayedAndroidKey = null;
5558
5567
  let startState = this.view.state;
5568
+ this.readSelectionRange();
5559
5569
  if (dispatchKey(this.view.contentDOM, key.key, key.keyCode))
5560
5570
  this.processRecords();
5561
5571
  else
@@ -5757,6 +5767,11 @@ function applyDOMChange(view, start, end, typeOver) {
5757
5767
  from: sel.from, to: sel.to,
5758
5768
  insert: view.state.doc.slice(sel.from, change.from).append(change.insert).append(view.state.doc.slice(change.to, sel.to))
5759
5769
  };
5770
+ // Detect insert-period-on-double-space Mac behavior, and transform
5771
+ // it into a regular space insert.
5772
+ else if (browser.mac && change && change.from == change.to && change.from == sel.head - 1 &&
5773
+ change.insert.toString() == ".")
5774
+ change = { from: sel.from, to: sel.to, insert: Text.of([" "]) };
5760
5775
  if (change) {
5761
5776
  let startState = view.state;
5762
5777
  if (browser.ios && view.inputState.flushIOSKey(view))
@@ -6045,7 +6060,7 @@ class EditorView {
6045
6060
  // When the phrases change, redraw the editor
6046
6061
  if (state.facet(EditorState.phrases) != this.state.facet(EditorState.phrases))
6047
6062
  return this.setState(state);
6048
- update = new ViewUpdate(this, state, transactions);
6063
+ update = ViewUpdate.create(this, state, transactions);
6049
6064
  let scrollTarget = this.viewState.scrollTarget;
6050
6065
  try {
6051
6066
  this.updateState = 2 /* Updating */;
@@ -6188,7 +6203,7 @@ class EditorView {
6188
6203
  return BadMeasure;
6189
6204
  }
6190
6205
  });
6191
- let update = new ViewUpdate(this, this.state), redrawn = false, scrolled = false;
6206
+ let update = ViewUpdate.create(this, this.state, []), redrawn = false, scrolled = false;
6192
6207
  update.flags |= changed;
6193
6208
  if (!updated)
6194
6209
  updated = update;
@@ -6648,8 +6663,8 @@ EditorView.inputHandler = inputHandler;
6648
6663
  /**
6649
6664
  By default, the editor assumes all its content has the same
6650
6665
  [text direction](https://codemirror.net/6/docs/ref/#view.Direction). Configure this with a `true`
6651
- value to make it read and store the text direction of every
6652
- (rendered) line separately.
6666
+ value to make it read the text direction of every (rendered)
6667
+ line separately.
6653
6668
  */
6654
6669
  EditorView.perLineTextDirection = perLineTextDirection;
6655
6670
  /**
@@ -8160,7 +8175,6 @@ class HoverPlugin {
8160
8175
  this.startHover();
8161
8176
  }
8162
8177
  startHover() {
8163
- var _a;
8164
8178
  clearTimeout(this.restartTimeout);
8165
8179
  let { lastMove } = this;
8166
8180
  let pos = this.view.contentDOM.contains(lastMove.target) ? this.view.posAtCoords(lastMove) : null;
@@ -8174,7 +8188,7 @@ class HoverPlugin {
8174
8188
  let bidi = this.view.bidiSpans(this.view.state.doc.lineAt(pos)).find(s => s.from <= pos && s.to >= pos);
8175
8189
  let rtl = bidi && bidi.dir == Direction.RTL ? -1 : 1;
8176
8190
  let open = this.source(this.view, pos, (lastMove.x < posCoords.left ? -rtl : rtl));
8177
- if ((_a = open) === null || _a === void 0 ? void 0 : _a.then) {
8191
+ if (open === null || open === void 0 ? void 0 : open.then) {
8178
8192
  let pending = this.pending = { pos };
8179
8193
  open.then(result => {
8180
8194
  if (this.pending == pending) {
@@ -8774,6 +8788,7 @@ class GutterElement {
8774
8788
  this.above = 0;
8775
8789
  this.markers = [];
8776
8790
  this.dom = document.createElement("div");
8791
+ this.dom.className = "cm-gutterElement";
8777
8792
  this.update(view, height, above, markers);
8778
8793
  }
8779
8794
  update(view, height, above, markers) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@codemirror/view",
3
- "version": "0.20.2",
3
+ "version": "0.20.5",
4
4
  "description": "DOM view component for the CodeMirror code editor",
5
5
  "scripts": {
6
6
  "test": "cm-runtests",