@codemirror/view 6.0.0 → 6.0.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.
@@ -11,6 +11,6 @@ jobs:
11
11
  with:
12
12
  # You should create a personal access token and store it in your repository
13
13
  token: ${{ secrets.DISPATCH_AUTH }}
14
- repo: codemirror.next
14
+ repo: dev
15
15
  owner: codemirror
16
16
  event_type: push
package/CHANGELOG.md CHANGED
@@ -1,3 +1,29 @@
1
+ ## 6.0.3 (2022-07-08)
2
+
3
+ ### Bug fixes
4
+
5
+ Fix a problem where `posAtCoords` could incorrectly return the start of the next line when querying positions between lines.
6
+
7
+ Fix an issue where registering a high-precedence keymap made keymap handling take precedence over other keydown event handlers.
8
+
9
+ Ctrl/Cmd-clicking can now remove ranges from a multi-range selection.
10
+
11
+ ## 6.0.2 (2022-06-23)
12
+
13
+ ### Bug fixes
14
+
15
+ Fix a CSS issue that broke horizontal scroll width stabilization.
16
+
17
+ Fix a bug where `defaultLineHeight` could get an incorrect value in very narrow editors.
18
+
19
+ ## 6.0.1 (2022-06-17)
20
+
21
+ ### Bug fixes
22
+
23
+ Avoid DOM selection corruption when the editor doesn't have focus but has selection and updates its content.
24
+
25
+ Fall back to dispatching by key code when a key event produces a non-ASCII character (so that Cyrillic and Arabic keyboards can still use bindings specified with Latin characters).
26
+
1
27
  ## 6.0.0 (2022-06-08)
2
28
 
3
29
  ### New features
package/README.md CHANGED
@@ -1,13 +1,13 @@
1
1
  # @codemirror/view [![NPM version](https://img.shields.io/npm/v/@codemirror/view.svg)](https://www.npmjs.org/package/@codemirror/view)
2
2
 
3
- [ [**WEBSITE**](https://codemirror.net/6/) | [**DOCS**](https://codemirror.net/6/docs/ref/#view) | [**ISSUES**](https://github.com/codemirror/codemirror.next/issues) | [**FORUM**](https://discuss.codemirror.net/c/next/) | [**CHANGELOG**](https://github.com/codemirror/view/blob/main/CHANGELOG.md) ]
3
+ [ [**WEBSITE**](https://codemirror.net/) | [**DOCS**](https://codemirror.net/docs/ref/#view) | [**ISSUES**](https://github.com/codemirror/dev/issues) | [**FORUM**](https://discuss.codemirror.net/c/next/) | [**CHANGELOG**](https://github.com/codemirror/view/blob/main/CHANGELOG.md) ]
4
4
 
5
5
  This package implements the DOM view component for the
6
- [CodeMirror](https://codemirror.net/6/) code editor.
6
+ [CodeMirror](https://codemirror.net/) code editor.
7
7
 
8
- The [project page](https://codemirror.net/6/) has more information, a
9
- number of [examples](https://codemirror.net/6/examples/) and the
10
- [documentation](https://codemirror.net/6/docs/).
8
+ The [project page](https://codemirror.net/) has more information, a
9
+ number of [examples](https://codemirror.net/examples/) and the
10
+ [documentation](https://codemirror.net/docs/).
11
11
 
12
12
  This code is released under an
13
13
  [MIT license](https://github.com/codemirror/view/tree/main/LICENSE).
package/dist/index.cjs CHANGED
@@ -2545,7 +2545,7 @@ class DocView extends ContentView {
2545
2545
  }
2546
2546
  // Sync the DOM selection to this.state.selection
2547
2547
  updateSelection(mustRead = false, fromPointer = false) {
2548
- if (mustRead)
2548
+ if (mustRead || !this.view.observer.selectionRange.focusNode)
2549
2549
  this.view.observer.readSelectionRange();
2550
2550
  if (!(fromPointer || this.mayControlSelection()) ||
2551
2551
  browser.ios && this.view.inputState.rapidCompositionStart)
@@ -2580,7 +2580,8 @@ class DocView extends ContentView {
2580
2580
  this.dom.focus({ preventScroll: true });
2581
2581
  }
2582
2582
  let rawSel = getSelection(this.root);
2583
- if (main.empty) {
2583
+ if (!rawSel) ;
2584
+ else if (main.empty) {
2584
2585
  // Work around https://bugzilla.mozilla.org/show_bug.cgi?id=1612076
2585
2586
  if (browser.gecko) {
2586
2587
  let nextTo = nextToUneditable(anchor.node, anchor.offset);
@@ -2622,7 +2623,7 @@ class DocView extends ContentView {
2622
2623
  return;
2623
2624
  let cursor = this.view.state.selection.main;
2624
2625
  let sel = getSelection(this.root);
2625
- if (!cursor.empty || !cursor.assoc || !sel.modify)
2626
+ if (!sel || !cursor.empty || !cursor.assoc || !sel.modify)
2626
2627
  return;
2627
2628
  let line = LineView.find(this, cursor.head);
2628
2629
  if (!line)
@@ -2638,8 +2639,9 @@ class DocView extends ContentView {
2638
2639
  sel.modify("move", cursor.assoc < 0 ? "forward" : "backward", "lineboundary");
2639
2640
  }
2640
2641
  mayControlSelection() {
2641
- return this.view.state.facet(editable) ? this.root.activeElement == this.dom
2642
- : hasSelection(this.dom, this.view.observer.selectionRange);
2642
+ let active = this.root.activeElement;
2643
+ return active == this.dom ||
2644
+ hasSelection(this.dom, this.view.observer.selectionRange) && !(active && this.dom.contains(active));
2643
2645
  }
2644
2646
  nearest(dom) {
2645
2647
  for (let cur = dom; cur;) {
@@ -2724,6 +2726,7 @@ class DocView extends ContentView {
2724
2726
  // If no workable line exists, force a layout of a measurable element
2725
2727
  let dummy = document.createElement("div"), lineHeight, charWidth;
2726
2728
  dummy.className = "cm-line";
2729
+ dummy.style.width = "99999px";
2727
2730
  dummy.textContent = "abc def ghi jkl mno pqr stu";
2728
2731
  this.view.observer.ignore(() => {
2729
2732
  this.dom.appendChild(dummy);
@@ -3134,7 +3137,8 @@ function posAtCoords(view, { x, y }, precise, bias = -1) {
3134
3137
  let range = doc.caretRangeFromPoint(x, y);
3135
3138
  if (range) {
3136
3139
  ({ startContainer: node, startOffset: offset } = range);
3137
- if (browser.safari && isSuspiciousCaretResult(node, offset, x))
3140
+ if (browser.safari && isSuspiciousSafariCaretResult(node, offset, x) ||
3141
+ browser.chrome && isSuspiciousChromeCaretResult(node, offset, x))
3138
3142
  node = undefined;
3139
3143
  }
3140
3144
  }
@@ -3161,7 +3165,7 @@ function posAtCoordsImprecise(view, contentRect, block, x, y) {
3161
3165
  // the space between lines as belonging to the last character of the
3162
3166
  // line before. This is used to detect such a result so that it can be
3163
3167
  // ignored (issue #401).
3164
- function isSuspiciousCaretResult(node, offset, x) {
3168
+ function isSuspiciousSafariCaretResult(node, offset, x) {
3165
3169
  let len;
3166
3170
  if (node.nodeType != 3 || offset != (len = node.nodeValue.length))
3167
3171
  return false;
@@ -3170,6 +3174,22 @@ function isSuspiciousCaretResult(node, offset, x) {
3170
3174
  return false;
3171
3175
  return textRange(node, len - 1, len).getBoundingClientRect().left > x;
3172
3176
  }
3177
+ // Chrome will move positions between lines to the start of the next line
3178
+ function isSuspiciousChromeCaretResult(node, offset, x) {
3179
+ if (offset != 0)
3180
+ return false;
3181
+ for (let cur = node;;) {
3182
+ let parent = cur.parentNode;
3183
+ if (!parent || parent.nodeType != 1 || parent.firstChild != cur)
3184
+ return false;
3185
+ if (parent.classList.contains("cm-line"))
3186
+ break;
3187
+ cur = parent;
3188
+ }
3189
+ let rect = node.nodeType == 1 ? node.getBoundingClientRect()
3190
+ : textRange(node, 0, Math.max(node.nodeValue.length, 1)).getBoundingClientRect();
3191
+ return x - rect.left > 5;
3192
+ }
3173
3193
  function moveToLineBoundary(view, start, forward, includeWrap) {
3174
3194
  let line = view.state.doc.lineAt(start.head);
3175
3195
  let coords = !includeWrap || !view.lineWrapping ? null
@@ -3536,7 +3556,7 @@ function isInPrimarySelection(view, event) {
3536
3556
  // On boundary clicks, check whether the coordinates are inside the
3537
3557
  // selection's client rectangles
3538
3558
  let sel = getSelection(view.root);
3539
- if (sel.rangeCount == 0)
3559
+ if (!sel || sel.rangeCount == 0)
3540
3560
  return true;
3541
3561
  let rects = sel.getRangeAt(0).getClientRects();
3542
3562
  for (let i = 0; i < rects.length; i++) {
@@ -3728,6 +3748,8 @@ function basicMouseSelection(view, event) {
3728
3748
  }
3729
3749
  if (extend)
3730
3750
  return startSel.replaceRange(startSel.main.extend(range.from, range.to));
3751
+ else if (multiple && startSel.ranges.length > 1 && startSel.ranges.some(r => r.eq(range)))
3752
+ return removeRange(startSel, range);
3731
3753
  else if (multiple)
3732
3754
  return startSel.addRange(range);
3733
3755
  else
@@ -3735,6 +3757,12 @@ function basicMouseSelection(view, event) {
3735
3757
  }
3736
3758
  };
3737
3759
  }
3760
+ function removeRange(sel, range) {
3761
+ for (let i = 0;; i++) {
3762
+ if (sel.ranges[i].eq(range))
3763
+ return state.EditorSelection.create(sel.ranges.slice(0, i).concat(sel.ranges.slice(i + 1)), sel.mainIndex == i ? 0 : sel.mainIndex - (sel.mainIndex > i ? 1 : 0));
3764
+ }
3765
+ }
3738
3766
  handlers.dragstart = (view, event) => {
3739
3767
  let { selection: { main } } = view.state;
3740
3768
  let { mouseSelection } = view.inputState;
@@ -5164,6 +5192,7 @@ const baseTheme$1 = buildTheme("." + baseThemeID, {
5164
5192
  ".cm-content": {
5165
5193
  margin: 0,
5166
5194
  flexGrow: 2,
5195
+ flexShrink: 0,
5167
5196
  minHeight: "100%",
5168
5197
  display: "block",
5169
5198
  whiteSpace: "pre",
@@ -5179,7 +5208,8 @@ const baseTheme$1 = buildTheme("." + baseThemeID, {
5179
5208
  whiteSpace_fallback: "pre-wrap",
5180
5209
  whiteSpace: "break-spaces",
5181
5210
  wordBreak: "break-word",
5182
- overflowWrap: "anywhere"
5211
+ overflowWrap: "anywhere",
5212
+ flexShrink: 1
5183
5213
  },
5184
5214
  "&light .cm-content": { caretColor: "black" },
5185
5215
  "&dark .cm-content": { caretColor: "white" },
@@ -5217,8 +5247,8 @@ const baseTheme$1 = buildTheme("." + baseThemeID, {
5217
5247
  // Two animations defined so that we can switch between them to
5218
5248
  // restart the animation without forcing another style
5219
5249
  // recomputation.
5220
- "@keyframes cm-blink": { "0%": {}, "50%": { visibility: "hidden" }, "100%": {} },
5221
- "@keyframes cm-blink2": { "0%": {}, "50%": { visibility: "hidden" }, "100%": {} },
5250
+ "@keyframes cm-blink": { "0%": {}, "50%": { opacity: 0 }, "100%": {} },
5251
+ "@keyframes cm-blink2": { "0%": {}, "50%": { opacity: 0 }, "100%": {} },
5222
5252
  ".cm-cursor, .cm-dropCursor": {
5223
5253
  position: "absolute",
5224
5254
  borderLeft: "1.2px solid black",
@@ -5495,12 +5525,12 @@ class DOMObserver {
5495
5525
  this.flush(false);
5496
5526
  }
5497
5527
  readSelectionRange() {
5498
- let { root } = this.view, domSel = getSelection(root);
5528
+ let { root } = this.view;
5499
5529
  // The Selection object is broken in shadow roots in Safari. See
5500
- // https://github.com/codemirror/codemirror.next/issues/414
5530
+ // https://github.com/codemirror/dev/issues/414
5501
5531
  let range = browser.safari && root.nodeType == 11 && deepActiveElement() == this.view.contentDOM &&
5502
- safariSelectionRangeHack(this.view) || domSel;
5503
- if (this.selectionRange.eq(range))
5532
+ safariSelectionRangeHack(this.view) || getSelection(root);
5533
+ if (!range || this.selectionRange.eq(range))
5504
5534
  return false;
5505
5535
  this.selectionRange.setRange(range);
5506
5536
  return this.selectionChanged = true;
@@ -6885,11 +6915,11 @@ function modifiers(name, event, shift) {
6885
6915
  name = "Shift-" + name;
6886
6916
  return name;
6887
6917
  }
6888
- const handleKeyEvents = EditorView.domEventHandlers({
6918
+ const handleKeyEvents = state.Prec.default(EditorView.domEventHandlers({
6889
6919
  keydown(event, view) {
6890
6920
  return runHandlers(getKeymap(view.state), event, view, "editor");
6891
6921
  }
6892
- });
6922
+ }));
6893
6923
  /**
6894
6924
  Facet used for registering keymaps.
6895
6925
 
@@ -6966,7 +6996,8 @@ function buildKeymap(bindings, platform = currentPlatform) {
6966
6996
  return bound;
6967
6997
  }
6968
6998
  function runHandlers(map, event, view, scope) {
6969
- let name = w3cKeyname.keyName(event), isChar = name.length == 1 && name != " ";
6999
+ let name = w3cKeyname.keyName(event);
7000
+ let charCode = state.codePointAt(name, 0), isChar = state.codePointSize(charCode) == name.length && name != " ";
6970
7001
  let prefix = "", fallthrough = false;
6971
7002
  if (storedPrefix && storedPrefix.view == view && storedPrefix.scope == scope) {
6972
7003
  prefix = storedPrefix.prefix + " ";
@@ -6987,10 +7018,13 @@ function runHandlers(map, event, view, scope) {
6987
7018
  if (scopeObj) {
6988
7019
  if (runFor(scopeObj[prefix + modifiers(name, event, !isChar)]))
6989
7020
  return true;
6990
- if (isChar && (event.shiftKey || event.altKey || event.metaKey) &&
7021
+ if (isChar && (event.shiftKey || event.altKey || event.metaKey || charCode > 127) &&
6991
7022
  (baseName = w3cKeyname.base[event.keyCode]) && baseName != name) {
6992
7023
  if (runFor(scopeObj[prefix + modifiers(baseName, event, true)]))
6993
7024
  return true;
7025
+ else if (event.shiftKey && w3cKeyname.shift[event.keyCode] != baseName &&
7026
+ runFor(scopeObj[prefix + modifiers(w3cKeyname.shift[event.keyCode], event, false)]))
7027
+ return true;
6994
7028
  }
6995
7029
  else if (isChar && event.shiftKey) {
6996
7030
  if (runFor(scopeObj[prefix + modifiers(name, event, true)]))
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
- import { Text, RangeSet, MapMode, RangeValue, Facet, StateEffect, ChangeSet, findClusterBreak, EditorSelection, EditorState, findColumn, CharCategory, Prec, Transaction, combineConfig, StateField, RangeSetBuilder, codePointAt, countColumn } from '@codemirror/state';
1
+ import { Text, RangeSet, MapMode, RangeValue, Facet, StateEffect, ChangeSet, findClusterBreak, EditorSelection, EditorState, findColumn, CharCategory, Prec, Transaction, codePointAt, codePointSize, combineConfig, StateField, RangeSetBuilder, countColumn } from '@codemirror/state';
2
2
  import { StyleModule } from 'style-mod';
3
- import { keyName, base } from 'w3c-keyname';
3
+ import { keyName, base, shift } from 'w3c-keyname';
4
4
 
5
5
  function getSelection(root) {
6
6
  let target;
@@ -2539,7 +2539,7 @@ class DocView extends ContentView {
2539
2539
  }
2540
2540
  // Sync the DOM selection to this.state.selection
2541
2541
  updateSelection(mustRead = false, fromPointer = false) {
2542
- if (mustRead)
2542
+ if (mustRead || !this.view.observer.selectionRange.focusNode)
2543
2543
  this.view.observer.readSelectionRange();
2544
2544
  if (!(fromPointer || this.mayControlSelection()) ||
2545
2545
  browser.ios && this.view.inputState.rapidCompositionStart)
@@ -2574,7 +2574,8 @@ class DocView extends ContentView {
2574
2574
  this.dom.focus({ preventScroll: true });
2575
2575
  }
2576
2576
  let rawSel = getSelection(this.root);
2577
- if (main.empty) {
2577
+ if (!rawSel) ;
2578
+ else if (main.empty) {
2578
2579
  // Work around https://bugzilla.mozilla.org/show_bug.cgi?id=1612076
2579
2580
  if (browser.gecko) {
2580
2581
  let nextTo = nextToUneditable(anchor.node, anchor.offset);
@@ -2616,7 +2617,7 @@ class DocView extends ContentView {
2616
2617
  return;
2617
2618
  let cursor = this.view.state.selection.main;
2618
2619
  let sel = getSelection(this.root);
2619
- if (!cursor.empty || !cursor.assoc || !sel.modify)
2620
+ if (!sel || !cursor.empty || !cursor.assoc || !sel.modify)
2620
2621
  return;
2621
2622
  let line = LineView.find(this, cursor.head);
2622
2623
  if (!line)
@@ -2632,8 +2633,9 @@ class DocView extends ContentView {
2632
2633
  sel.modify("move", cursor.assoc < 0 ? "forward" : "backward", "lineboundary");
2633
2634
  }
2634
2635
  mayControlSelection() {
2635
- return this.view.state.facet(editable) ? this.root.activeElement == this.dom
2636
- : hasSelection(this.dom, this.view.observer.selectionRange);
2636
+ let active = this.root.activeElement;
2637
+ return active == this.dom ||
2638
+ hasSelection(this.dom, this.view.observer.selectionRange) && !(active && this.dom.contains(active));
2637
2639
  }
2638
2640
  nearest(dom) {
2639
2641
  for (let cur = dom; cur;) {
@@ -2718,6 +2720,7 @@ class DocView extends ContentView {
2718
2720
  // If no workable line exists, force a layout of a measurable element
2719
2721
  let dummy = document.createElement("div"), lineHeight, charWidth;
2720
2722
  dummy.className = "cm-line";
2723
+ dummy.style.width = "99999px";
2721
2724
  dummy.textContent = "abc def ghi jkl mno pqr stu";
2722
2725
  this.view.observer.ignore(() => {
2723
2726
  this.dom.appendChild(dummy);
@@ -3128,7 +3131,8 @@ function posAtCoords(view, { x, y }, precise, bias = -1) {
3128
3131
  let range = doc.caretRangeFromPoint(x, y);
3129
3132
  if (range) {
3130
3133
  ({ startContainer: node, startOffset: offset } = range);
3131
- if (browser.safari && isSuspiciousCaretResult(node, offset, x))
3134
+ if (browser.safari && isSuspiciousSafariCaretResult(node, offset, x) ||
3135
+ browser.chrome && isSuspiciousChromeCaretResult(node, offset, x))
3132
3136
  node = undefined;
3133
3137
  }
3134
3138
  }
@@ -3155,7 +3159,7 @@ function posAtCoordsImprecise(view, contentRect, block, x, y) {
3155
3159
  // the space between lines as belonging to the last character of the
3156
3160
  // line before. This is used to detect such a result so that it can be
3157
3161
  // ignored (issue #401).
3158
- function isSuspiciousCaretResult(node, offset, x) {
3162
+ function isSuspiciousSafariCaretResult(node, offset, x) {
3159
3163
  let len;
3160
3164
  if (node.nodeType != 3 || offset != (len = node.nodeValue.length))
3161
3165
  return false;
@@ -3164,6 +3168,22 @@ function isSuspiciousCaretResult(node, offset, x) {
3164
3168
  return false;
3165
3169
  return textRange(node, len - 1, len).getBoundingClientRect().left > x;
3166
3170
  }
3171
+ // Chrome will move positions between lines to the start of the next line
3172
+ function isSuspiciousChromeCaretResult(node, offset, x) {
3173
+ if (offset != 0)
3174
+ return false;
3175
+ for (let cur = node;;) {
3176
+ let parent = cur.parentNode;
3177
+ if (!parent || parent.nodeType != 1 || parent.firstChild != cur)
3178
+ return false;
3179
+ if (parent.classList.contains("cm-line"))
3180
+ break;
3181
+ cur = parent;
3182
+ }
3183
+ let rect = node.nodeType == 1 ? node.getBoundingClientRect()
3184
+ : textRange(node, 0, Math.max(node.nodeValue.length, 1)).getBoundingClientRect();
3185
+ return x - rect.left > 5;
3186
+ }
3167
3187
  function moveToLineBoundary(view, start, forward, includeWrap) {
3168
3188
  let line = view.state.doc.lineAt(start.head);
3169
3189
  let coords = !includeWrap || !view.lineWrapping ? null
@@ -3530,7 +3550,7 @@ function isInPrimarySelection(view, event) {
3530
3550
  // On boundary clicks, check whether the coordinates are inside the
3531
3551
  // selection's client rectangles
3532
3552
  let sel = getSelection(view.root);
3533
- if (sel.rangeCount == 0)
3553
+ if (!sel || sel.rangeCount == 0)
3534
3554
  return true;
3535
3555
  let rects = sel.getRangeAt(0).getClientRects();
3536
3556
  for (let i = 0; i < rects.length; i++) {
@@ -3722,6 +3742,8 @@ function basicMouseSelection(view, event) {
3722
3742
  }
3723
3743
  if (extend)
3724
3744
  return startSel.replaceRange(startSel.main.extend(range.from, range.to));
3745
+ else if (multiple && startSel.ranges.length > 1 && startSel.ranges.some(r => r.eq(range)))
3746
+ return removeRange(startSel, range);
3725
3747
  else if (multiple)
3726
3748
  return startSel.addRange(range);
3727
3749
  else
@@ -3729,6 +3751,12 @@ function basicMouseSelection(view, event) {
3729
3751
  }
3730
3752
  };
3731
3753
  }
3754
+ function removeRange(sel, range) {
3755
+ for (let i = 0;; i++) {
3756
+ if (sel.ranges[i].eq(range))
3757
+ return EditorSelection.create(sel.ranges.slice(0, i).concat(sel.ranges.slice(i + 1)), sel.mainIndex == i ? 0 : sel.mainIndex - (sel.mainIndex > i ? 1 : 0));
3758
+ }
3759
+ }
3732
3760
  handlers.dragstart = (view, event) => {
3733
3761
  let { selection: { main } } = view.state;
3734
3762
  let { mouseSelection } = view.inputState;
@@ -5157,6 +5185,7 @@ const baseTheme$1 = /*@__PURE__*/buildTheme("." + baseThemeID, {
5157
5185
  ".cm-content": {
5158
5186
  margin: 0,
5159
5187
  flexGrow: 2,
5188
+ flexShrink: 0,
5160
5189
  minHeight: "100%",
5161
5190
  display: "block",
5162
5191
  whiteSpace: "pre",
@@ -5172,7 +5201,8 @@ const baseTheme$1 = /*@__PURE__*/buildTheme("." + baseThemeID, {
5172
5201
  whiteSpace_fallback: "pre-wrap",
5173
5202
  whiteSpace: "break-spaces",
5174
5203
  wordBreak: "break-word",
5175
- overflowWrap: "anywhere"
5204
+ overflowWrap: "anywhere",
5205
+ flexShrink: 1
5176
5206
  },
5177
5207
  "&light .cm-content": { caretColor: "black" },
5178
5208
  "&dark .cm-content": { caretColor: "white" },
@@ -5210,8 +5240,8 @@ const baseTheme$1 = /*@__PURE__*/buildTheme("." + baseThemeID, {
5210
5240
  // Two animations defined so that we can switch between them to
5211
5241
  // restart the animation without forcing another style
5212
5242
  // recomputation.
5213
- "@keyframes cm-blink": { "0%": {}, "50%": { visibility: "hidden" }, "100%": {} },
5214
- "@keyframes cm-blink2": { "0%": {}, "50%": { visibility: "hidden" }, "100%": {} },
5243
+ "@keyframes cm-blink": { "0%": {}, "50%": { opacity: 0 }, "100%": {} },
5244
+ "@keyframes cm-blink2": { "0%": {}, "50%": { opacity: 0 }, "100%": {} },
5215
5245
  ".cm-cursor, .cm-dropCursor": {
5216
5246
  position: "absolute",
5217
5247
  borderLeft: "1.2px solid black",
@@ -5488,12 +5518,12 @@ class DOMObserver {
5488
5518
  this.flush(false);
5489
5519
  }
5490
5520
  readSelectionRange() {
5491
- let { root } = this.view, domSel = getSelection(root);
5521
+ let { root } = this.view;
5492
5522
  // The Selection object is broken in shadow roots in Safari. See
5493
- // https://github.com/codemirror/codemirror.next/issues/414
5523
+ // https://github.com/codemirror/dev/issues/414
5494
5524
  let range = browser.safari && root.nodeType == 11 && deepActiveElement() == this.view.contentDOM &&
5495
- safariSelectionRangeHack(this.view) || domSel;
5496
- if (this.selectionRange.eq(range))
5525
+ safariSelectionRangeHack(this.view) || getSelection(root);
5526
+ if (!range || this.selectionRange.eq(range))
5497
5527
  return false;
5498
5528
  this.selectionRange.setRange(range);
5499
5529
  return this.selectionChanged = true;
@@ -6878,11 +6908,11 @@ function modifiers(name, event, shift) {
6878
6908
  name = "Shift-" + name;
6879
6909
  return name;
6880
6910
  }
6881
- const handleKeyEvents = /*@__PURE__*/EditorView.domEventHandlers({
6911
+ const handleKeyEvents = /*@__PURE__*/Prec.default(/*@__PURE__*/EditorView.domEventHandlers({
6882
6912
  keydown(event, view) {
6883
6913
  return runHandlers(getKeymap(view.state), event, view, "editor");
6884
6914
  }
6885
- });
6915
+ }));
6886
6916
  /**
6887
6917
  Facet used for registering keymaps.
6888
6918
 
@@ -6959,7 +6989,8 @@ function buildKeymap(bindings, platform = currentPlatform) {
6959
6989
  return bound;
6960
6990
  }
6961
6991
  function runHandlers(map, event, view, scope) {
6962
- let name = keyName(event), isChar = name.length == 1 && name != " ";
6992
+ let name = keyName(event);
6993
+ let charCode = codePointAt(name, 0), isChar = codePointSize(charCode) == name.length && name != " ";
6963
6994
  let prefix = "", fallthrough = false;
6964
6995
  if (storedPrefix && storedPrefix.view == view && storedPrefix.scope == scope) {
6965
6996
  prefix = storedPrefix.prefix + " ";
@@ -6980,10 +7011,13 @@ function runHandlers(map, event, view, scope) {
6980
7011
  if (scopeObj) {
6981
7012
  if (runFor(scopeObj[prefix + modifiers(name, event, !isChar)]))
6982
7013
  return true;
6983
- if (isChar && (event.shiftKey || event.altKey || event.metaKey) &&
7014
+ if (isChar && (event.shiftKey || event.altKey || event.metaKey || charCode > 127) &&
6984
7015
  (baseName = base[event.keyCode]) && baseName != name) {
6985
7016
  if (runFor(scopeObj[prefix + modifiers(baseName, event, true)]))
6986
7017
  return true;
7018
+ else if (event.shiftKey && shift[event.keyCode] != baseName &&
7019
+ runFor(scopeObj[prefix + modifiers(shift[event.keyCode], event, false)]))
7020
+ return true;
6987
7021
  }
6988
7022
  else if (isChar && event.shiftKey) {
6989
7023
  if (runFor(scopeObj[prefix + modifiers(name, event, true)]))
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@codemirror/view",
3
- "version": "6.0.0",
3
+ "version": "6.0.3",
4
4
  "description": "DOM view component for the CodeMirror code editor",
5
5
  "scripts": {
6
6
  "test": "cm-runtests",