@codemirror/view 6.36.0 → 6.36.2

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,19 @@
1
+ ## 6.36.2 (2025-01-09)
2
+
3
+ ### Bug fixes
4
+
5
+ Fix an issue where some kinds of relayouts could put the editor in a state where it believed it wasn't in window, preventing relayout, though it in fact was.
6
+
7
+ Make sure macOS double-space-to-period conversions are properly suppressed.
8
+
9
+ Fix an issue where native selection changes, such as mobile spacebar-drag, weren't being picked up in edit context mode.
10
+
11
+ ## 6.36.1 (2024-12-19)
12
+
13
+ ### Bug fixes
14
+
15
+ Fix a crash in MatchDecorator when updating matches at the end of the document.
16
+
1
17
  ## 6.36.0 (2024-12-17)
2
18
 
3
19
  ### Bug fixes
package/README.md CHANGED
@@ -16,3 +16,22 @@ We aim to be an inclusive, welcoming community. To make that explicit,
16
16
  we have a [code of
17
17
  conduct](http://contributor-covenant.org/version/1/1/0/) that applies
18
18
  to communication around the project.
19
+
20
+ ## Usage
21
+
22
+ ```javascript
23
+ import {EditorView} from "@codemirror/view"
24
+ import {basicSetup} from "codemirror"
25
+
26
+ const view = new EditorView({
27
+ parent: document.querySelector("#some-node"),
28
+ doc: "Content text",
29
+ extensions: [basicSetup /* ... */]
30
+ })
31
+ ```
32
+
33
+ Add additional extensions, such as a [language
34
+ mode](https://codemirror.net/#languages), to configure the editor.
35
+ Call
36
+ [`view.dispatch`](https://codemirror.net/docs/ref/#view.EditorView.dispatch)
37
+ to update the editor's state.
package/dist/index.cjs CHANGED
@@ -3953,6 +3953,14 @@ function applyDOMChange(view, domChange) {
3953
3953
  // Heuristic to notice typing over a selected character
3954
3954
  change = { from: sel.from, to: sel.to, insert: view.state.doc.slice(sel.from, sel.to) };
3955
3955
  }
3956
+ else if ((browser.mac || browser.android) && change && change.from == change.to && change.from == sel.head - 1 &&
3957
+ /^\. ?$/.test(change.insert.toString()) && view.contentDOM.getAttribute("autocorrect") == "off") {
3958
+ // Detect insert-period-on-double-space Mac and Android behavior,
3959
+ // and transform it into a regular space insert.
3960
+ if (newSel && change.insert.length == 2)
3961
+ newSel = state.EditorSelection.single(newSel.main.anchor - 1, newSel.main.head - 1);
3962
+ change = { from: change.from, to: change.to, insert: state.Text.of([change.insert.toString().replace(".", " ")]) };
3963
+ }
3956
3964
  else if (change && change.from >= sel.from && change.to <= sel.to &&
3957
3965
  (change.from != sel.from || change.to != sel.to) &&
3958
3966
  (sel.to - sel.from) - (change.to - change.from) <= 4) {
@@ -3964,14 +3972,6 @@ function applyDOMChange(view, domChange) {
3964
3972
  insert: view.state.doc.slice(sel.from, change.from).append(change.insert).append(view.state.doc.slice(change.to, sel.to))
3965
3973
  };
3966
3974
  }
3967
- else if ((browser.mac || browser.android) && change && change.from == change.to && change.from == sel.head - 1 &&
3968
- /^\. ?$/.test(change.insert.toString()) && view.contentDOM.getAttribute("autocorrect") == "off") {
3969
- // Detect insert-period-on-double-space Mac and Android behavior,
3970
- // and transform it into a regular space insert.
3971
- if (newSel && change.insert.length == 2)
3972
- newSel = state.EditorSelection.single(newSel.main.anchor - 1, newSel.main.head - 1);
3973
- change = { from: sel.from, to: sel.to, insert: state.Text.of([" "]) };
3974
- }
3975
3975
  else if (browser.chrome && change && change.from == change.to && change.from == sel.head &&
3976
3976
  change.insert.toString() == "\n " && view.lineWrapping) {
3977
3977
  // In Chrome, if you insert a space at the start of a wrapped
@@ -5774,6 +5774,11 @@ function visiblePixelRange(dom, paddingTop) {
5774
5774
  return { left: left - rect.left, right: Math.max(left, right) - rect.left,
5775
5775
  top: top - (rect.top + paddingTop), bottom: Math.max(top, bottom) - (rect.top + paddingTop) };
5776
5776
  }
5777
+ function inWindow(elt) {
5778
+ let rect = elt.getBoundingClientRect(), win = elt.ownerDocument.defaultView || window;
5779
+ return rect.left < win.innerWidth && rect.right > 0 &&
5780
+ rect.top < win.innerHeight && rect.bottom > 0;
5781
+ }
5777
5782
  function fullPixelRange(dom, paddingTop) {
5778
5783
  let rect = dom.getBoundingClientRect();
5779
5784
  return { left: 0, right: rect.right - rect.left,
@@ -5997,7 +6002,7 @@ class ViewState {
5997
6002
  if (inView)
5998
6003
  measureContent = true;
5999
6004
  }
6000
- if (!this.inView && !this.scrollTarget)
6005
+ if (!this.inView && !this.scrollTarget && !inWindow(view.dom))
6001
6006
  return 0;
6002
6007
  let contentWidth = domRect.width;
6003
6008
  if (this.contentDOMWidth != contentWidth || this.editorHeight != view.scrollDOM.clientHeight) {
@@ -7187,7 +7192,7 @@ class EditContextManager {
7187
7192
  selectionEnd: this.toContextPos(view.state.selection.main.head)
7188
7193
  });
7189
7194
  this.handlers.textupdate = e => {
7190
- let { anchor } = view.state.selection.main;
7195
+ let main = view.state.selection.main, { anchor, head } = main;
7191
7196
  let from = this.toEditorPos(e.updateRangeStart), to = this.toEditorPos(e.updateRangeEnd);
7192
7197
  if (view.inputState.composing >= 0 && !this.composing)
7193
7198
  this.composing = { contextBase: e.updateRangeStart, editorBase: from, drifted: false };
@@ -7199,8 +7204,15 @@ class EditContextManager {
7199
7204
  else if (change.to == this.to && anchor > this.to)
7200
7205
  change.to = anchor;
7201
7206
  // Edit contexts sometimes fire empty changes
7202
- if (change.from == change.to && !change.insert.length)
7207
+ if (change.from == change.to && !change.insert.length) {
7208
+ let newSel = state.EditorSelection.single(this.toEditorPos(e.selectionStart), this.toEditorPos(e.selectionEnd));
7209
+ if (!newSel.main.eq(main))
7210
+ view.dispatch({ selection: newSel, userEvent: "select" });
7203
7211
  return;
7212
+ }
7213
+ if ((browser.mac || browser.android) && change.from == head - 1 &&
7214
+ /^\. ?$/.test(e.text) && view.contentDOM.getAttribute("autocorrect") == "off")
7215
+ change = { from, to, insert: state.Text.of([e.text.replace(".", " ")]) };
7204
7216
  this.pendingContextChange = change;
7205
7217
  if (!view.state.readOnly) {
7206
7218
  let newLen = this.to - this.from + (change.to - change.from + change.insert.length);
@@ -9293,7 +9305,7 @@ class MatchDecorator {
9293
9305
  let changeFrom = 1e9, changeTo = -1;
9294
9306
  if (update.docChanged)
9295
9307
  update.changes.iterChanges((_f, _t, from, to) => {
9296
- if (to > update.view.viewport.from && from < update.view.viewport.to) {
9308
+ if (to >= update.view.viewport.from && from <= update.view.viewport.to) {
9297
9309
  changeFrom = Math.min(from, changeFrom);
9298
9310
  changeTo = Math.max(to, changeTo);
9299
9311
  }
package/dist/index.js CHANGED
@@ -3949,6 +3949,14 @@ function applyDOMChange(view, domChange) {
3949
3949
  // Heuristic to notice typing over a selected character
3950
3950
  change = { from: sel.from, to: sel.to, insert: view.state.doc.slice(sel.from, sel.to) };
3951
3951
  }
3952
+ else if ((browser.mac || browser.android) && change && change.from == change.to && change.from == sel.head - 1 &&
3953
+ /^\. ?$/.test(change.insert.toString()) && view.contentDOM.getAttribute("autocorrect") == "off") {
3954
+ // Detect insert-period-on-double-space Mac and Android behavior,
3955
+ // and transform it into a regular space insert.
3956
+ if (newSel && change.insert.length == 2)
3957
+ newSel = EditorSelection.single(newSel.main.anchor - 1, newSel.main.head - 1);
3958
+ change = { from: change.from, to: change.to, insert: Text.of([change.insert.toString().replace(".", " ")]) };
3959
+ }
3952
3960
  else if (change && change.from >= sel.from && change.to <= sel.to &&
3953
3961
  (change.from != sel.from || change.to != sel.to) &&
3954
3962
  (sel.to - sel.from) - (change.to - change.from) <= 4) {
@@ -3960,14 +3968,6 @@ function applyDOMChange(view, domChange) {
3960
3968
  insert: view.state.doc.slice(sel.from, change.from).append(change.insert).append(view.state.doc.slice(change.to, sel.to))
3961
3969
  };
3962
3970
  }
3963
- else if ((browser.mac || browser.android) && change && change.from == change.to && change.from == sel.head - 1 &&
3964
- /^\. ?$/.test(change.insert.toString()) && view.contentDOM.getAttribute("autocorrect") == "off") {
3965
- // Detect insert-period-on-double-space Mac and Android behavior,
3966
- // and transform it into a regular space insert.
3967
- if (newSel && change.insert.length == 2)
3968
- newSel = EditorSelection.single(newSel.main.anchor - 1, newSel.main.head - 1);
3969
- change = { from: sel.from, to: sel.to, insert: Text.of([" "]) };
3970
- }
3971
3971
  else if (browser.chrome && change && change.from == change.to && change.from == sel.head &&
3972
3972
  change.insert.toString() == "\n " && view.lineWrapping) {
3973
3973
  // In Chrome, if you insert a space at the start of a wrapped
@@ -5769,6 +5769,11 @@ function visiblePixelRange(dom, paddingTop) {
5769
5769
  return { left: left - rect.left, right: Math.max(left, right) - rect.left,
5770
5770
  top: top - (rect.top + paddingTop), bottom: Math.max(top, bottom) - (rect.top + paddingTop) };
5771
5771
  }
5772
+ function inWindow(elt) {
5773
+ let rect = elt.getBoundingClientRect(), win = elt.ownerDocument.defaultView || window;
5774
+ return rect.left < win.innerWidth && rect.right > 0 &&
5775
+ rect.top < win.innerHeight && rect.bottom > 0;
5776
+ }
5772
5777
  function fullPixelRange(dom, paddingTop) {
5773
5778
  let rect = dom.getBoundingClientRect();
5774
5779
  return { left: 0, right: rect.right - rect.left,
@@ -5992,7 +5997,7 @@ class ViewState {
5992
5997
  if (inView)
5993
5998
  measureContent = true;
5994
5999
  }
5995
- if (!this.inView && !this.scrollTarget)
6000
+ if (!this.inView && !this.scrollTarget && !inWindow(view.dom))
5996
6001
  return 0;
5997
6002
  let contentWidth = domRect.width;
5998
6003
  if (this.contentDOMWidth != contentWidth || this.editorHeight != view.scrollDOM.clientHeight) {
@@ -7182,7 +7187,7 @@ class EditContextManager {
7182
7187
  selectionEnd: this.toContextPos(view.state.selection.main.head)
7183
7188
  });
7184
7189
  this.handlers.textupdate = e => {
7185
- let { anchor } = view.state.selection.main;
7190
+ let main = view.state.selection.main, { anchor, head } = main;
7186
7191
  let from = this.toEditorPos(e.updateRangeStart), to = this.toEditorPos(e.updateRangeEnd);
7187
7192
  if (view.inputState.composing >= 0 && !this.composing)
7188
7193
  this.composing = { contextBase: e.updateRangeStart, editorBase: from, drifted: false };
@@ -7194,8 +7199,15 @@ class EditContextManager {
7194
7199
  else if (change.to == this.to && anchor > this.to)
7195
7200
  change.to = anchor;
7196
7201
  // Edit contexts sometimes fire empty changes
7197
- if (change.from == change.to && !change.insert.length)
7202
+ if (change.from == change.to && !change.insert.length) {
7203
+ let newSel = EditorSelection.single(this.toEditorPos(e.selectionStart), this.toEditorPos(e.selectionEnd));
7204
+ if (!newSel.main.eq(main))
7205
+ view.dispatch({ selection: newSel, userEvent: "select" });
7198
7206
  return;
7207
+ }
7208
+ if ((browser.mac || browser.android) && change.from == head - 1 &&
7209
+ /^\. ?$/.test(e.text) && view.contentDOM.getAttribute("autocorrect") == "off")
7210
+ change = { from, to, insert: Text.of([e.text.replace(".", " ")]) };
7199
7211
  this.pendingContextChange = change;
7200
7212
  if (!view.state.readOnly) {
7201
7213
  let newLen = this.to - this.from + (change.to - change.from + change.insert.length);
@@ -9288,7 +9300,7 @@ class MatchDecorator {
9288
9300
  let changeFrom = 1e9, changeTo = -1;
9289
9301
  if (update.docChanged)
9290
9302
  update.changes.iterChanges((_f, _t, from, to) => {
9291
- if (to > update.view.viewport.from && from < update.view.viewport.to) {
9303
+ if (to >= update.view.viewport.from && from <= update.view.viewport.to) {
9292
9304
  changeFrom = Math.min(from, changeFrom);
9293
9305
  changeTo = Math.max(to, changeTo);
9294
9306
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@codemirror/view",
3
- "version": "6.36.0",
3
+ "version": "6.36.2",
4
4
  "description": "DOM view component for the CodeMirror code editor",
5
5
  "scripts": {
6
6
  "test": "cm-runtests",