@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 +34 -0
- package/dist/index.cjs +62 -71
- package/dist/index.d.ts +2 -1
- package/dist/index.js +62 -71
- package/package.json +1 -1
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 =
|
|
1112
|
-
let endSide =
|
|
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 /*
|
|
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 /*
|
|
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
|
|
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
|
-
|
|
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
|
-
//
|
|
3094
|
-
//
|
|
3095
|
-
//
|
|
3096
|
-
|
|
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.
|
|
3191
|
+
this.pendingIOSKey = pending;
|
|
3192
|
+
setTimeout(() => this.flushIOSKey(view), 250);
|
|
3210
3193
|
return true;
|
|
3211
3194
|
}
|
|
3212
3195
|
return false;
|
|
3213
3196
|
}
|
|
3214
|
-
|
|
3215
|
-
|
|
3216
|
-
|
|
3217
|
-
|
|
3218
|
-
|
|
3219
|
-
|
|
3220
|
-
|
|
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.
|
|
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
|
-
|
|
4392
|
+
let body = dom.ownerDocument.body;
|
|
4393
|
+
for (let parent = dom.parentNode; parent && parent != body;) {
|
|
4403
4394
|
if (parent.nodeType == 1) {
|
|
4404
|
-
let
|
|
4405
|
-
|
|
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 =
|
|
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" ?
|
|
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
|
-
|
|
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.
|
|
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
|
|
5374
|
-
if (start > -1
|
|
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.
|
|
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" :
|
|
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 =
|
|
1108
|
-
let endSide =
|
|
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 /*
|
|
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 /*
|
|
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
|
|
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
|
-
|
|
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
|
-
//
|
|
3089
|
-
//
|
|
3090
|
-
//
|
|
3091
|
-
|
|
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.
|
|
3186
|
+
this.pendingIOSKey = pending;
|
|
3187
|
+
setTimeout(() => this.flushIOSKey(view), 250);
|
|
3205
3188
|
return true;
|
|
3206
3189
|
}
|
|
3207
3190
|
return false;
|
|
3208
3191
|
}
|
|
3209
|
-
|
|
3210
|
-
|
|
3211
|
-
|
|
3212
|
-
|
|
3213
|
-
|
|
3214
|
-
|
|
3215
|
-
|
|
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.
|
|
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
|
-
|
|
4386
|
+
let body = dom.ownerDocument.body;
|
|
4387
|
+
for (let parent = dom.parentNode; parent && parent != body;) {
|
|
4397
4388
|
if (parent.nodeType == 1) {
|
|
4398
|
-
let
|
|
4399
|
-
|
|
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 =
|
|
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" ?
|
|
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
|
-
|
|
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.
|
|
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
|
|
5368
|
-
if (start > -1
|
|
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.
|
|
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" :
|
|
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",
|