@codemirror/view 0.19.13 → 0.19.17

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,37 @@
1
+ ## 0.19.17 (2021-11-16)
2
+
3
+ ### Bug fixes
4
+
5
+ Avoid an issue where stretches of whitespace on line wrap points could cause the cursor to be placed outside of the content.
6
+
7
+ ## 0.19.16 (2021-11-11)
8
+
9
+ ### Breaking changes
10
+
11
+ Block replacement decorations now default to inclusive, because non-inclusive block decorations are rarely what you need.
12
+
13
+ ### Bug fixes
14
+
15
+ Fix an issue that caused block widgets to always have a large side value, making it impossible to show them between to replacement decorations.
16
+
17
+ Fix a crash that could happen after some types of viewport changes, due to a bug in the block widget view data structure.
18
+
19
+ ## 0.19.15 (2021-11-09)
20
+
21
+ ### Bug fixes
22
+
23
+ Fix a bug where the editor would think it was invisible when the document body was given screen height and scroll behavior.
24
+
25
+ Fix selection reading inside a shadow root on iOS.
26
+
27
+ ## 0.19.14 (2021-11-07)
28
+
29
+ ### Bug fixes
30
+
31
+ Fix an issue where typing into a read-only editor would move the selection.
32
+
33
+ Fix slowness when backspace is held down on iOS.
34
+
1
35
  ## 0.19.13 (2021-11-06)
2
36
 
3
37
  ### Bug fixes
package/dist/index.cjs CHANGED
@@ -252,24 +252,11 @@ function dispatchKey(elt, name, code) {
252
252
  elt.dispatchEvent(up);
253
253
  return down.defaultPrevented || up.defaultPrevented;
254
254
  }
255
- let _plainTextSupported = null;
256
- function contentEditablePlainTextSupported() {
257
- if (_plainTextSupported == null) {
258
- _plainTextSupported = false;
259
- let dummy = document.createElement("div");
260
- try {
261
- dummy.contentEditable = "plaintext-only";
262
- _plainTextSupported = dummy.contentEditable == "plaintext-only";
263
- }
264
- catch (_) { }
265
- }
266
- return _plainTextSupported;
267
- }
268
255
  function getRoot(node) {
269
256
  while (node) {
270
- node = node.assignedSlot || node.parentNode;
271
257
  if (node && (node.nodeType == 9 || node.nodeType == 11 && node.host))
272
258
  return node;
259
+ node = node.assignedSlot || node.parentNode;
273
260
  }
274
261
  return null;
275
262
  }
@@ -679,7 +666,7 @@ function textCoords(text, pos, side) {
679
666
  let rect = rects[(flatten ? flatten < 0 : side >= 0) ? 0 : rects.length - 1];
680
667
  if (browser.safari && !flatten && rect.width == 0)
681
668
  rect = Array.prototype.find.call(rects, r => r.width) || rect;
682
- return flatten ? flattenRect(rect, flatten < 0) : rect;
669
+ return flatten ? flattenRect(rect, flatten < 0) : rect || null;
683
670
  }
684
671
  // Also used for collapsed ranges that don't have a placeholder widget!
685
672
  class WidgetView extends InlineView {
@@ -787,7 +774,7 @@ class WidgetBufferView extends InlineView {
787
774
  domBoundsAround() { return null; }
788
775
  coordsAt(pos) {
789
776
  let rects = clientRectsFor(this.dom);
790
- return rects[rects.length - 1];
777
+ return rects[rects.length - 1] || null;
791
778
  }
792
779
  get overrideDOMText() {
793
780
  return text.Text.of([this.dom.nodeValue.replace(/\u200b/g, "")]);
@@ -929,7 +916,7 @@ function coordsInChildren(view, pos, side) {
929
916
  if (!last)
930
917
  return view.dom.getBoundingClientRect();
931
918
  let rects = clientRectsFor(last);
932
- return rects[rects.length - 1];
919
+ return rects[rects.length - 1] || null;
933
920
  }
934
921
 
935
922
  function combineAttrs(source, target) {
@@ -1097,8 +1084,6 @@ class Decoration extends rangeset.RangeValue {
1097
1084
  */
1098
1085
  static widget(spec) {
1099
1086
  let side = spec.side || 0;
1100
- if (spec.block)
1101
- side += (200000000 /* BigBlock */ + 1) * (side > 0 ? 1 : -1);
1102
1087
  return new PointDecoration(spec, side, side, !!spec.block, spec.widget || null, false);
1103
1088
  }
1104
1089
  /**
@@ -1107,9 +1092,9 @@ class Decoration extends rangeset.RangeValue {
1107
1092
  */
1108
1093
  static replace(spec) {
1109
1094
  let block = !!spec.block;
1110
- let { start, end } = getInclusive(spec);
1111
- let startSide = block ? -200000000 /* BigBlock */ * (start ? 2 : 1) : 100000000 /* BigInline */ * (start ? -1 : 1);
1112
- let endSide = block ? 200000000 /* BigBlock */ * (end ? 2 : 1) : 100000000 /* BigInline */ * (end ? 1 : -1);
1095
+ let { start, end } = getInclusive(spec, block);
1096
+ let startSide = 100000000 /* Big */ * (start ? -1 : 1) * (block ? 2 : 1);
1097
+ let endSide = 100000000 /* Big */ * (end ? 1 : -1) * (block ? 2 : 1);
1113
1098
  return new PointDecoration(spec, startSide, endSide, block, spec.widget || null, true);
1114
1099
  }
1115
1100
  /**
@@ -1139,7 +1124,7 @@ Decoration.none = rangeset.RangeSet.empty;
1139
1124
  class MarkDecoration extends Decoration {
1140
1125
  constructor(spec) {
1141
1126
  let { start, end } = getInclusive(spec);
1142
- super(100000000 /* BigInline */ * (start ? -1 : 1), 100000000 /* BigInline */ * (end ? 1 : -1), null, spec);
1127
+ super(100000000 /* Big */ * (start ? -1 : 1), 100000000 /* Big */ * (end ? 1 : -1), null, spec);
1143
1128
  this.tagName = spec.tagName || "span";
1144
1129
  this.class = spec.class || "";
1145
1130
  this.attrs = spec.attributes || null;
@@ -1160,7 +1145,7 @@ class MarkDecoration extends Decoration {
1160
1145
  MarkDecoration.prototype.point = false;
1161
1146
  class LineDecoration extends Decoration {
1162
1147
  constructor(spec) {
1163
- super(-100000000 /* BigInline */, -100000000 /* BigInline */, null, spec);
1148
+ super(-100000000 /* Big */, -100000000 /* Big */, null, spec);
1164
1149
  }
1165
1150
  eq(other) {
1166
1151
  return other instanceof LineDecoration && attrsEq(this.spec.attributes, other.spec.attributes);
@@ -1201,13 +1186,13 @@ class PointDecoration extends Decoration {
1201
1186
  }
1202
1187
  }
1203
1188
  PointDecoration.prototype.point = true;
1204
- function getInclusive(spec) {
1189
+ function getInclusive(spec, block = false) {
1205
1190
  let { inclusiveStart: start, inclusiveEnd: end } = spec;
1206
1191
  if (start == null)
1207
1192
  start = spec.inclusive;
1208
1193
  if (end == null)
1209
1194
  end = spec.inclusive;
1210
- return { start: start || false, end: end || false };
1195
+ return { start: start !== null && start !== void 0 ? start : block, end: end !== null && end !== void 0 ? end : block };
1211
1196
  }
1212
1197
  function widgetsEq(a, b) {
1213
1198
  return a == b || !!(a && b && a.compare(b));
@@ -1375,7 +1360,9 @@ class BlockWidgetView extends ContentView {
1375
1360
  split(at) {
1376
1361
  let len = this.length - at;
1377
1362
  this.length = at;
1378
- return new BlockWidgetView(this.widget, len, this.type);
1363
+ let end = new BlockWidgetView(this.widget, len, this.type);
1364
+ end.breakAfter = this.breakAfter;
1365
+ return end;
1379
1366
  }
1380
1367
  get children() { return none$1; }
1381
1368
  sync() {
@@ -3078,10 +3065,6 @@ class InputState {
3078
3065
  constructor(view) {
3079
3066
  this.lastKeyCode = 0;
3080
3067
  this.lastKeyTime = 0;
3081
- // On iOS, some keys need to have their default behavior happen
3082
- // (after which we retroactively handle them and reset the DOM) to
3083
- // avoid messing up the virtual keyboard state.
3084
- //
3085
3068
  // On Chrome Android, backspace near widgets is just completely
3086
3069
  // broken, and there are no key events, so we need to handle the
3087
3070
  // beforeinput event. Deleting stuff will often create a flurry of
@@ -3089,12 +3072,11 @@ class InputState {
3089
3072
  // subsequent events even more broken, so again, we hold off doing
3090
3073
  // anything until the browser is finished with whatever it is trying
3091
3074
  // to do.
3092
- //
3093
- // setPendingKey sets this, causing the DOM observer to pause for a
3094
- // bit, and setting an animation frame (which seems the most
3095
- // reliable way to detect 'browser is done flailing') to fire a fake
3096
- // key event and re-sync the view again.
3097
- this.pendingKey = undefined;
3075
+ this.pendingAndroidKey = undefined;
3076
+ // On iOS, some keys need to have their default behavior happen
3077
+ // (after which we retroactively handle them and reset the DOM) to
3078
+ // avoid messing up the virtual keyboard state.
3079
+ this.pendingIOSKey = undefined;
3098
3080
  this.lastSelectionOrigin = null;
3099
3081
  this.lastSelectionTime = 0;
3100
3082
  this.lastEscPress = 0;
@@ -3206,28 +3188,36 @@ class InputState {
3206
3188
  let pending;
3207
3189
  if (browser.ios && (pending = PendingKeys.find(key => key.keyCode == event.keyCode)) &&
3208
3190
  !(event.ctrlKey || event.altKey || event.metaKey) && !event.synthetic) {
3209
- this.setPendingKey(view, pending);
3191
+ this.pendingIOSKey = pending;
3192
+ setTimeout(() => this.flushIOSKey(view), 250);
3210
3193
  return true;
3211
3194
  }
3212
3195
  return false;
3213
3196
  }
3214
- setPendingKey(view, pending) {
3215
- this.pendingKey = pending;
3216
- let flush = () => {
3217
- if (!this.pendingKey)
3218
- return false;
3219
- let key = this.pendingKey;
3220
- this.pendingKey = undefined;
3197
+ flushIOSKey(view) {
3198
+ let key = this.pendingIOSKey;
3199
+ if (!key)
3200
+ return false;
3201
+ this.pendingIOSKey = undefined;
3202
+ return dispatchKey(view.contentDOM, key.key, key.keyCode);
3203
+ }
3204
+ // This causes the DOM observer to pause for a bit, and sets an
3205
+ // animation frame (which seems the most reliable way to detect
3206
+ // 'Chrome is done flailing about messing with the DOM') to fire a
3207
+ // fake key event and re-sync the view again.
3208
+ setPendingAndroidKey(view, pending) {
3209
+ this.pendingAndroidKey = pending;
3210
+ requestAnimationFrame(() => {
3211
+ let key = this.pendingAndroidKey;
3212
+ if (!key)
3213
+ return;
3214
+ this.pendingAndroidKey = undefined;
3221
3215
  view.observer.processRecords();
3222
3216
  let startState = view.state;
3223
3217
  dispatchKey(view.contentDOM, key.key, key.keyCode);
3224
3218
  if (view.state == startState)
3225
3219
  view.docView.reset(true);
3226
- };
3227
- if (browser.ios)
3228
- setTimeout(() => requestAnimationFrame(flush), 50);
3229
- else
3230
- requestAnimationFrame(flush);
3220
+ });
3231
3221
  }
3232
3222
  ignoreDuringComposition(event) {
3233
3223
  if (!/^key/.test(event.type))
@@ -3735,7 +3725,7 @@ handlers.beforeinput = (view, event) => {
3735
3725
  // seems to do nothing at all on Chrome).
3736
3726
  let pending;
3737
3727
  if (browser.chrome && browser.android && (pending = PendingKeys.find(key => key.inputType == event.inputType))) {
3738
- view.inputState.setPendingKey(view, pending);
3728
+ view.inputState.setPendingAndroidKey(view, pending);
3739
3729
  if (pending.key == "Backspace" || pending.key == "Delete") {
3740
3730
  let startViewHeight = ((_a = window.visualViewport) === null || _a === void 0 ? void 0 : _a.height) || 0;
3741
3731
  setTimeout(() => {
@@ -4399,18 +4389,20 @@ function visiblePixelRange(dom, paddingTop) {
4399
4389
  let rect = dom.getBoundingClientRect();
4400
4390
  let left = Math.max(0, rect.left), right = Math.min(innerWidth, rect.right);
4401
4391
  let top = Math.max(0, rect.top), bottom = Math.min(innerHeight, rect.bottom);
4402
- for (let parent = dom.parentNode; parent;) { // (Cast to any because TypeScript is useless with Node types)
4392
+ let body = dom.ownerDocument.body;
4393
+ for (let parent = dom.parentNode; parent && parent != body;) {
4403
4394
  if (parent.nodeType == 1) {
4404
- let style = window.getComputedStyle(parent);
4405
- if ((parent.scrollHeight > parent.clientHeight || parent.scrollWidth > parent.clientWidth) &&
4395
+ let elt = parent;
4396
+ let style = window.getComputedStyle(elt);
4397
+ if ((elt.scrollHeight > elt.clientHeight || elt.scrollWidth > elt.clientWidth) &&
4406
4398
  style.overflow != "visible") {
4407
- let parentRect = parent.getBoundingClientRect();
4399
+ let parentRect = elt.getBoundingClientRect();
4408
4400
  left = Math.max(left, parentRect.left);
4409
4401
  right = Math.min(right, parentRect.right);
4410
4402
  top = Math.max(top, parentRect.top);
4411
4403
  bottom = Math.min(bottom, parentRect.bottom);
4412
4404
  }
4413
- parent = style.position == "absolute" || style.position == "fixed" ? parent.offsetParent : parent.parentNode;
4405
+ parent = style.position == "absolute" || style.position == "fixed" ? elt.offsetParent : elt.parentNode;
4414
4406
  }
4415
4407
  else if (parent.nodeType == 11) { // Shadow root
4416
4408
  parent = parent.host;
@@ -4940,10 +4932,14 @@ const baseTheme = buildTheme("." + baseThemeID, {
4940
4932
  wordWrap: "normal",
4941
4933
  boxSizing: "border-box",
4942
4934
  padding: "4px 0",
4943
- outline: "none"
4935
+ outline: "none",
4936
+ "&[contenteditable=true]": {
4937
+ WebkitUserModify: "read-write-plaintext-only",
4938
+ }
4944
4939
  },
4945
4940
  ".cm-lineWrapping": {
4946
- whiteSpace: "pre-wrap",
4941
+ whiteSpace_fallback: "pre-wrap",
4942
+ whiteSpace: "break-spaces",
4947
4943
  wordBreak: "break-word",
4948
4944
  overflowWrap: "anywhere"
4949
4945
  },
@@ -5283,7 +5279,7 @@ class DOMObserver {
5283
5279
  // Completely hold off flushing when pending keys are set—the code
5284
5280
  // managing those will make sure processRecords is called and the
5285
5281
  // view is resynchronized after
5286
- if (this.delayedFlush >= 0 || this.view.inputState.pendingKey)
5282
+ if (this.delayedFlush >= 0 || this.view.inputState.pendingAndroidKey)
5287
5283
  return;
5288
5284
  this.lastFlush = Date.now();
5289
5285
  let { from, to, typeOver } = this.processRecords();
@@ -5370,8 +5366,11 @@ function safariSelectionRangeHack(view) {
5370
5366
 
5371
5367
  function applyDOMChange(view, start, end, typeOver) {
5372
5368
  let change, newSel;
5373
- let sel = view.state.selection.main, bounds;
5374
- if (start > -1 && !view.state.readOnly && (bounds = view.docView.domBoundsAround(start, end, 0))) {
5369
+ let sel = view.state.selection.main;
5370
+ if (start > -1) {
5371
+ let bounds = view.docView.domBoundsAround(start, end, 0);
5372
+ if (!bounds || view.state.readOnly)
5373
+ return;
5375
5374
  let { from, to } = bounds;
5376
5375
  let selPoints = view.docView.impreciseHead || view.docView.impreciseAnchor ? [] : selectionPoints(view);
5377
5376
  let reader = new DOMReader(selPoints, view);
@@ -5425,16 +5424,8 @@ function applyDOMChange(view, start, end, typeOver) {
5425
5424
  // backspace, or delete. So this detects changes that look like
5426
5425
  // they're caused by those keys, and reinterprets them as key
5427
5426
  // events.
5428
- if (browser.android &&
5429
- ((change.from == sel.from && change.to == sel.to &&
5430
- change.insert.length == 1 && change.insert.lines == 2 &&
5431
- dispatchKey(view.contentDOM, "Enter", 13)) ||
5432
- (change.from == sel.from - 1 && change.to == sel.to && change.insert.length == 0 &&
5433
- dispatchKey(view.contentDOM, "Backspace", 8)) ||
5434
- (change.from == sel.from && change.to == sel.to + 1 && change.insert.length == 0 &&
5435
- dispatchKey(view.contentDOM, "Delete", 46)))) {
5427
+ if (browser.ios && view.inputState.flushIOSKey(view))
5436
5428
  return;
5437
- }
5438
5429
  let text = change.insert.toString();
5439
5430
  if (view.state.facet(inputHandler).some(h => h(view, change.from, change.to, text)))
5440
5431
  return;
@@ -5927,7 +5918,7 @@ class EditorView {
5927
5918
  autocorrect: "off",
5928
5919
  autocapitalize: "off",
5929
5920
  translate: "no",
5930
- contenteditable: !this.state.facet(editable) ? "false" : contentEditablePlainTextSupported() ? "plaintext-only" : "true",
5921
+ contenteditable: !this.state.facet(editable) ? "false" : "true",
5931
5922
  class: "cm-content",
5932
5923
  style: `${browser.tabSize}: ${this.state.tabSize}`,
5933
5924
  role: "textbox",
package/dist/index.d.ts CHANGED
@@ -91,7 +91,8 @@ interface ReplaceDecorationSpec {
91
91
  /**
92
92
  Whether this range covers the positions on its sides. This
93
93
  influences whether new content becomes part of the range and
94
- whether the cursor can be drawn on its sides. Defaults to false.
94
+ whether the cursor can be drawn on its sides. Defaults to false
95
+ for inline replacements, and true for block replacements.
95
96
  */
96
97
  inclusive?: boolean;
97
98
  /**
package/dist/index.js CHANGED
@@ -249,24 +249,11 @@ function dispatchKey(elt, name, code) {
249
249
  elt.dispatchEvent(up);
250
250
  return down.defaultPrevented || up.defaultPrevented;
251
251
  }
252
- let _plainTextSupported = null;
253
- function contentEditablePlainTextSupported() {
254
- if (_plainTextSupported == null) {
255
- _plainTextSupported = false;
256
- let dummy = document.createElement("div");
257
- try {
258
- dummy.contentEditable = "plaintext-only";
259
- _plainTextSupported = dummy.contentEditable == "plaintext-only";
260
- }
261
- catch (_) { }
262
- }
263
- return _plainTextSupported;
264
- }
265
252
  function getRoot(node) {
266
253
  while (node) {
267
- node = node.assignedSlot || node.parentNode;
268
254
  if (node && (node.nodeType == 9 || node.nodeType == 11 && node.host))
269
255
  return node;
256
+ node = node.assignedSlot || node.parentNode;
270
257
  }
271
258
  return null;
272
259
  }
@@ -676,7 +663,7 @@ function textCoords(text, pos, side) {
676
663
  let rect = rects[(flatten ? flatten < 0 : side >= 0) ? 0 : rects.length - 1];
677
664
  if (browser.safari && !flatten && rect.width == 0)
678
665
  rect = Array.prototype.find.call(rects, r => r.width) || rect;
679
- return flatten ? flattenRect(rect, flatten < 0) : rect;
666
+ return flatten ? flattenRect(rect, flatten < 0) : rect || null;
680
667
  }
681
668
  // Also used for collapsed ranges that don't have a placeholder widget!
682
669
  class WidgetView extends InlineView {
@@ -784,7 +771,7 @@ class WidgetBufferView extends InlineView {
784
771
  domBoundsAround() { return null; }
785
772
  coordsAt(pos) {
786
773
  let rects = clientRectsFor(this.dom);
787
- return rects[rects.length - 1];
774
+ return rects[rects.length - 1] || null;
788
775
  }
789
776
  get overrideDOMText() {
790
777
  return Text.of([this.dom.nodeValue.replace(/\u200b/g, "")]);
@@ -926,7 +913,7 @@ function coordsInChildren(view, pos, side) {
926
913
  if (!last)
927
914
  return view.dom.getBoundingClientRect();
928
915
  let rects = clientRectsFor(last);
929
- return rects[rects.length - 1];
916
+ return rects[rects.length - 1] || null;
930
917
  }
931
918
 
932
919
  function combineAttrs(source, target) {
@@ -1093,8 +1080,6 @@ class Decoration extends RangeValue {
1093
1080
  */
1094
1081
  static widget(spec) {
1095
1082
  let side = spec.side || 0;
1096
- if (spec.block)
1097
- side += (200000000 /* BigBlock */ + 1) * (side > 0 ? 1 : -1);
1098
1083
  return new PointDecoration(spec, side, side, !!spec.block, spec.widget || null, false);
1099
1084
  }
1100
1085
  /**
@@ -1103,9 +1088,9 @@ class Decoration extends RangeValue {
1103
1088
  */
1104
1089
  static replace(spec) {
1105
1090
  let block = !!spec.block;
1106
- let { start, end } = getInclusive(spec);
1107
- let startSide = block ? -200000000 /* BigBlock */ * (start ? 2 : 1) : 100000000 /* BigInline */ * (start ? -1 : 1);
1108
- let endSide = block ? 200000000 /* BigBlock */ * (end ? 2 : 1) : 100000000 /* BigInline */ * (end ? 1 : -1);
1091
+ let { start, end } = getInclusive(spec, block);
1092
+ let startSide = 100000000 /* Big */ * (start ? -1 : 1) * (block ? 2 : 1);
1093
+ let endSide = 100000000 /* Big */ * (end ? 1 : -1) * (block ? 2 : 1);
1109
1094
  return new PointDecoration(spec, startSide, endSide, block, spec.widget || null, true);
1110
1095
  }
1111
1096
  /**
@@ -1135,7 +1120,7 @@ Decoration.none = RangeSet.empty;
1135
1120
  class MarkDecoration extends Decoration {
1136
1121
  constructor(spec) {
1137
1122
  let { start, end } = getInclusive(spec);
1138
- super(100000000 /* BigInline */ * (start ? -1 : 1), 100000000 /* BigInline */ * (end ? 1 : -1), null, spec);
1123
+ super(100000000 /* Big */ * (start ? -1 : 1), 100000000 /* Big */ * (end ? 1 : -1), null, spec);
1139
1124
  this.tagName = spec.tagName || "span";
1140
1125
  this.class = spec.class || "";
1141
1126
  this.attrs = spec.attributes || null;
@@ -1156,7 +1141,7 @@ class MarkDecoration extends Decoration {
1156
1141
  MarkDecoration.prototype.point = false;
1157
1142
  class LineDecoration extends Decoration {
1158
1143
  constructor(spec) {
1159
- super(-100000000 /* BigInline */, -100000000 /* BigInline */, null, spec);
1144
+ super(-100000000 /* Big */, -100000000 /* Big */, null, spec);
1160
1145
  }
1161
1146
  eq(other) {
1162
1147
  return other instanceof LineDecoration && attrsEq(this.spec.attributes, other.spec.attributes);
@@ -1197,13 +1182,13 @@ class PointDecoration extends Decoration {
1197
1182
  }
1198
1183
  }
1199
1184
  PointDecoration.prototype.point = true;
1200
- function getInclusive(spec) {
1185
+ function getInclusive(spec, block = false) {
1201
1186
  let { inclusiveStart: start, inclusiveEnd: end } = spec;
1202
1187
  if (start == null)
1203
1188
  start = spec.inclusive;
1204
1189
  if (end == null)
1205
1190
  end = spec.inclusive;
1206
- return { start: start || false, end: end || false };
1191
+ return { start: start !== null && start !== void 0 ? start : block, end: end !== null && end !== void 0 ? end : block };
1207
1192
  }
1208
1193
  function widgetsEq(a, b) {
1209
1194
  return a == b || !!(a && b && a.compare(b));
@@ -1371,7 +1356,9 @@ class BlockWidgetView extends ContentView {
1371
1356
  split(at) {
1372
1357
  let len = this.length - at;
1373
1358
  this.length = at;
1374
- return new BlockWidgetView(this.widget, len, this.type);
1359
+ let end = new BlockWidgetView(this.widget, len, this.type);
1360
+ end.breakAfter = this.breakAfter;
1361
+ return end;
1375
1362
  }
1376
1363
  get children() { return none$1; }
1377
1364
  sync() {
@@ -3073,10 +3060,6 @@ class InputState {
3073
3060
  constructor(view) {
3074
3061
  this.lastKeyCode = 0;
3075
3062
  this.lastKeyTime = 0;
3076
- // On iOS, some keys need to have their default behavior happen
3077
- // (after which we retroactively handle them and reset the DOM) to
3078
- // avoid messing up the virtual keyboard state.
3079
- //
3080
3063
  // On Chrome Android, backspace near widgets is just completely
3081
3064
  // broken, and there are no key events, so we need to handle the
3082
3065
  // beforeinput event. Deleting stuff will often create a flurry of
@@ -3084,12 +3067,11 @@ class InputState {
3084
3067
  // subsequent events even more broken, so again, we hold off doing
3085
3068
  // anything until the browser is finished with whatever it is trying
3086
3069
  // to do.
3087
- //
3088
- // setPendingKey sets this, causing the DOM observer to pause for a
3089
- // bit, and setting an animation frame (which seems the most
3090
- // reliable way to detect 'browser is done flailing') to fire a fake
3091
- // key event and re-sync the view again.
3092
- this.pendingKey = undefined;
3070
+ this.pendingAndroidKey = undefined;
3071
+ // On iOS, some keys need to have their default behavior happen
3072
+ // (after which we retroactively handle them and reset the DOM) to
3073
+ // avoid messing up the virtual keyboard state.
3074
+ this.pendingIOSKey = undefined;
3093
3075
  this.lastSelectionOrigin = null;
3094
3076
  this.lastSelectionTime = 0;
3095
3077
  this.lastEscPress = 0;
@@ -3201,28 +3183,36 @@ class InputState {
3201
3183
  let pending;
3202
3184
  if (browser.ios && (pending = PendingKeys.find(key => key.keyCode == event.keyCode)) &&
3203
3185
  !(event.ctrlKey || event.altKey || event.metaKey) && !event.synthetic) {
3204
- this.setPendingKey(view, pending);
3186
+ this.pendingIOSKey = pending;
3187
+ setTimeout(() => this.flushIOSKey(view), 250);
3205
3188
  return true;
3206
3189
  }
3207
3190
  return false;
3208
3191
  }
3209
- setPendingKey(view, pending) {
3210
- this.pendingKey = pending;
3211
- let flush = () => {
3212
- if (!this.pendingKey)
3213
- return false;
3214
- let key = this.pendingKey;
3215
- this.pendingKey = undefined;
3192
+ flushIOSKey(view) {
3193
+ let key = this.pendingIOSKey;
3194
+ if (!key)
3195
+ return false;
3196
+ this.pendingIOSKey = undefined;
3197
+ return dispatchKey(view.contentDOM, key.key, key.keyCode);
3198
+ }
3199
+ // This causes the DOM observer to pause for a bit, and sets an
3200
+ // animation frame (which seems the most reliable way to detect
3201
+ // 'Chrome is done flailing about messing with the DOM') to fire a
3202
+ // fake key event and re-sync the view again.
3203
+ setPendingAndroidKey(view, pending) {
3204
+ this.pendingAndroidKey = pending;
3205
+ requestAnimationFrame(() => {
3206
+ let key = this.pendingAndroidKey;
3207
+ if (!key)
3208
+ return;
3209
+ this.pendingAndroidKey = undefined;
3216
3210
  view.observer.processRecords();
3217
3211
  let startState = view.state;
3218
3212
  dispatchKey(view.contentDOM, key.key, key.keyCode);
3219
3213
  if (view.state == startState)
3220
3214
  view.docView.reset(true);
3221
- };
3222
- if (browser.ios)
3223
- setTimeout(() => requestAnimationFrame(flush), 50);
3224
- else
3225
- requestAnimationFrame(flush);
3215
+ });
3226
3216
  }
3227
3217
  ignoreDuringComposition(event) {
3228
3218
  if (!/^key/.test(event.type))
@@ -3730,7 +3720,7 @@ handlers.beforeinput = (view, event) => {
3730
3720
  // seems to do nothing at all on Chrome).
3731
3721
  let pending;
3732
3722
  if (browser.chrome && browser.android && (pending = PendingKeys.find(key => key.inputType == event.inputType))) {
3733
- view.inputState.setPendingKey(view, pending);
3723
+ view.inputState.setPendingAndroidKey(view, pending);
3734
3724
  if (pending.key == "Backspace" || pending.key == "Delete") {
3735
3725
  let startViewHeight = ((_a = window.visualViewport) === null || _a === void 0 ? void 0 : _a.height) || 0;
3736
3726
  setTimeout(() => {
@@ -4393,18 +4383,20 @@ function visiblePixelRange(dom, paddingTop) {
4393
4383
  let rect = dom.getBoundingClientRect();
4394
4384
  let left = Math.max(0, rect.left), right = Math.min(innerWidth, rect.right);
4395
4385
  let top = Math.max(0, rect.top), bottom = Math.min(innerHeight, rect.bottom);
4396
- for (let parent = dom.parentNode; parent;) { // (Cast to any because TypeScript is useless with Node types)
4386
+ let body = dom.ownerDocument.body;
4387
+ for (let parent = dom.parentNode; parent && parent != body;) {
4397
4388
  if (parent.nodeType == 1) {
4398
- let style = window.getComputedStyle(parent);
4399
- if ((parent.scrollHeight > parent.clientHeight || parent.scrollWidth > parent.clientWidth) &&
4389
+ let elt = parent;
4390
+ let style = window.getComputedStyle(elt);
4391
+ if ((elt.scrollHeight > elt.clientHeight || elt.scrollWidth > elt.clientWidth) &&
4400
4392
  style.overflow != "visible") {
4401
- let parentRect = parent.getBoundingClientRect();
4393
+ let parentRect = elt.getBoundingClientRect();
4402
4394
  left = Math.max(left, parentRect.left);
4403
4395
  right = Math.min(right, parentRect.right);
4404
4396
  top = Math.max(top, parentRect.top);
4405
4397
  bottom = Math.min(bottom, parentRect.bottom);
4406
4398
  }
4407
- parent = style.position == "absolute" || style.position == "fixed" ? parent.offsetParent : parent.parentNode;
4399
+ parent = style.position == "absolute" || style.position == "fixed" ? elt.offsetParent : elt.parentNode;
4408
4400
  }
4409
4401
  else if (parent.nodeType == 11) { // Shadow root
4410
4402
  parent = parent.host;
@@ -4934,10 +4926,14 @@ const baseTheme = /*@__PURE__*/buildTheme("." + baseThemeID, {
4934
4926
  wordWrap: "normal",
4935
4927
  boxSizing: "border-box",
4936
4928
  padding: "4px 0",
4937
- outline: "none"
4929
+ outline: "none",
4930
+ "&[contenteditable=true]": {
4931
+ WebkitUserModify: "read-write-plaintext-only",
4932
+ }
4938
4933
  },
4939
4934
  ".cm-lineWrapping": {
4940
- whiteSpace: "pre-wrap",
4935
+ whiteSpace_fallback: "pre-wrap",
4936
+ whiteSpace: "break-spaces",
4941
4937
  wordBreak: "break-word",
4942
4938
  overflowWrap: "anywhere"
4943
4939
  },
@@ -5277,7 +5273,7 @@ class DOMObserver {
5277
5273
  // Completely hold off flushing when pending keys are set—the code
5278
5274
  // managing those will make sure processRecords is called and the
5279
5275
  // view is resynchronized after
5280
- if (this.delayedFlush >= 0 || this.view.inputState.pendingKey)
5276
+ if (this.delayedFlush >= 0 || this.view.inputState.pendingAndroidKey)
5281
5277
  return;
5282
5278
  this.lastFlush = Date.now();
5283
5279
  let { from, to, typeOver } = this.processRecords();
@@ -5364,8 +5360,11 @@ function safariSelectionRangeHack(view) {
5364
5360
 
5365
5361
  function applyDOMChange(view, start, end, typeOver) {
5366
5362
  let change, newSel;
5367
- let sel = view.state.selection.main, bounds;
5368
- if (start > -1 && !view.state.readOnly && (bounds = view.docView.domBoundsAround(start, end, 0))) {
5363
+ let sel = view.state.selection.main;
5364
+ if (start > -1) {
5365
+ let bounds = view.docView.domBoundsAround(start, end, 0);
5366
+ if (!bounds || view.state.readOnly)
5367
+ return;
5369
5368
  let { from, to } = bounds;
5370
5369
  let selPoints = view.docView.impreciseHead || view.docView.impreciseAnchor ? [] : selectionPoints(view);
5371
5370
  let reader = new DOMReader(selPoints, view);
@@ -5419,16 +5418,8 @@ function applyDOMChange(view, start, end, typeOver) {
5419
5418
  // backspace, or delete. So this detects changes that look like
5420
5419
  // they're caused by those keys, and reinterprets them as key
5421
5420
  // events.
5422
- if (browser.android &&
5423
- ((change.from == sel.from && change.to == sel.to &&
5424
- change.insert.length == 1 && change.insert.lines == 2 &&
5425
- dispatchKey(view.contentDOM, "Enter", 13)) ||
5426
- (change.from == sel.from - 1 && change.to == sel.to && change.insert.length == 0 &&
5427
- dispatchKey(view.contentDOM, "Backspace", 8)) ||
5428
- (change.from == sel.from && change.to == sel.to + 1 && change.insert.length == 0 &&
5429
- dispatchKey(view.contentDOM, "Delete", 46)))) {
5421
+ if (browser.ios && view.inputState.flushIOSKey(view))
5430
5422
  return;
5431
- }
5432
5423
  let text = change.insert.toString();
5433
5424
  if (view.state.facet(inputHandler).some(h => h(view, change.from, change.to, text)))
5434
5425
  return;
@@ -5921,7 +5912,7 @@ class EditorView {
5921
5912
  autocorrect: "off",
5922
5913
  autocapitalize: "off",
5923
5914
  translate: "no",
5924
- contenteditable: !this.state.facet(editable) ? "false" : contentEditablePlainTextSupported() ? "plaintext-only" : "true",
5915
+ contenteditable: !this.state.facet(editable) ? "false" : "true",
5925
5916
  class: "cm-content",
5926
5917
  style: `${browser.tabSize}: ${this.state.tabSize}`,
5927
5918
  role: "textbox",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@codemirror/view",
3
- "version": "0.19.13",
3
+ "version": "0.19.17",
4
4
  "description": "DOM view component for the CodeMirror code editor",
5
5
  "scripts": {
6
6
  "test": "cm-runtests",