@codemirror/view 0.19.40 → 0.19.44
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 +43 -1
- package/dist/index.cjs +113 -65
- package/dist/index.d.ts +9 -1
- package/dist/index.js +114 -66
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,45 @@
|
|
|
1
|
+
## 0.19.44 (2022-02-17)
|
|
2
|
+
|
|
3
|
+
### Bug fixes
|
|
4
|
+
|
|
5
|
+
Fix a crash that occasionally occurred when drag-selecting in a way that scrolled the editor.
|
|
6
|
+
|
|
7
|
+
### New features
|
|
8
|
+
|
|
9
|
+
The new `EditorView.compositionStarted` property indicates whether a composition is starting.
|
|
10
|
+
|
|
11
|
+
## 0.19.43 (2022-02-16)
|
|
12
|
+
|
|
13
|
+
### Bug fixes
|
|
14
|
+
|
|
15
|
+
Fix several issues where editing or composition went wrong due to our zero-width space kludge characters ending up in unexpected places.
|
|
16
|
+
|
|
17
|
+
Make sure the editor re-measures its dimensions whenever its theme changes.
|
|
18
|
+
|
|
19
|
+
Fix an issue where some keys on Android phones could leave the editor DOM unsynced with the actual document.
|
|
20
|
+
|
|
21
|
+
## 0.19.42 (2022-02-05)
|
|
22
|
+
|
|
23
|
+
### Bug fixes
|
|
24
|
+
|
|
25
|
+
Fix a regression in cursor position determination after making an edit next to a widget.
|
|
26
|
+
|
|
27
|
+
## 0.19.41 (2022-02-04)
|
|
28
|
+
|
|
29
|
+
### Bug fixes
|
|
30
|
+
|
|
31
|
+
Fix an issue where the editor's view of its content height could go out of sync with the DOM when a line-wrapping editor had its width changed, causing wrapping to change.
|
|
32
|
+
|
|
33
|
+
Fix a bug that caused the editor to draw way too much content when scrolling to a position in an editor (much) taller than the window.
|
|
34
|
+
|
|
35
|
+
Report an error when a replace decoration from a plugin crosses a line break, rather than silently ignoring it.
|
|
36
|
+
|
|
37
|
+
Fix an issue where reading DOM changes was broken when `lineSeparator` contained more than one character.
|
|
38
|
+
|
|
39
|
+
Make ordering of replace and mark decorations with the same extent and inclusivness more predictable by giving replace decorations precedence.
|
|
40
|
+
|
|
41
|
+
Fix a bug where, on Chrome, replacement across line boundaries and next to widgets could cause bogus zero-width characters to appear in the content.
|
|
42
|
+
|
|
1
43
|
## 0.19.40 (2022-01-19)
|
|
2
44
|
|
|
3
45
|
### Bug fixes
|
|
@@ -66,7 +108,7 @@ Fix an issue where backspacing out a selection on Chrome Android would sometimes
|
|
|
66
108
|
|
|
67
109
|
### Bug fixes
|
|
68
110
|
|
|
69
|
-
Fix a bug where content line elements would in some cases lose their `cm-line` class.
|
|
111
|
+
Fix a bug where content line elements would in some cases lose their `cm-line` class.
|
|
70
112
|
|
|
71
113
|
## 0.19.33 (2021-12-16)
|
|
72
114
|
|
package/dist/index.cjs
CHANGED
|
@@ -602,9 +602,8 @@ function mergeChildrenInto(parent, from, to, insert, openStart, openEnd) {
|
|
|
602
602
|
replaceRange(parent, fromI, fromOff, toI, toOff, insert, 0, openStart, openEnd);
|
|
603
603
|
}
|
|
604
604
|
|
|
605
|
-
let
|
|
606
|
-
|
|
607
|
-
: [{ userAgent: "", vendor: "", platform: "" }, { documentElement: { style: {} } }];
|
|
605
|
+
let nav = typeof navigator != "undefined" ? navigator : { userAgent: "", vendor: "", platform: "" };
|
|
606
|
+
let doc = typeof document != "undefined" ? document : { documentElement: { style: {} } };
|
|
608
607
|
const ie_edge = /Edge\/(\d+)/.exec(nav.userAgent);
|
|
609
608
|
const ie_upto10 = /MSIE \d/.test(nav.userAgent);
|
|
610
609
|
const ie_11up = /Trident\/(?:[7-9]|\d{2,})\..*rv:(\d+)/.exec(nav.userAgent);
|
|
@@ -860,9 +859,6 @@ class CompositionView extends WidgetView {
|
|
|
860
859
|
coordsAt(pos, side) { return textCoords(this.widget.text, pos, side); }
|
|
861
860
|
get isEditable() { return true; }
|
|
862
861
|
}
|
|
863
|
-
// Use two characters on Android, to prevent Chrome from closing the
|
|
864
|
-
// virtual keyboard when backspacing after a widget (#602).
|
|
865
|
-
const ZeroWidthSpace = browser.android ? "\u200b\u200b" : "\u200b";
|
|
866
862
|
// These are drawn around uneditable widgets to avoid a number of
|
|
867
863
|
// browser bugs that show up when the cursor is directly next to
|
|
868
864
|
// uneditable inline content.
|
|
@@ -878,21 +874,21 @@ class WidgetBufferView extends ContentView {
|
|
|
878
874
|
}
|
|
879
875
|
split() { return new WidgetBufferView(this.side); }
|
|
880
876
|
sync() {
|
|
881
|
-
if (!this.dom)
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
this.dom
|
|
877
|
+
if (!this.dom) {
|
|
878
|
+
let dom = document.createElement("img");
|
|
879
|
+
dom.className = "cm-widgetBuffer";
|
|
880
|
+
this.setDOM(dom);
|
|
881
|
+
}
|
|
885
882
|
}
|
|
886
883
|
getSide() { return this.side; }
|
|
887
884
|
domAtPos(pos) { return DOMPos.before(this.dom); }
|
|
888
885
|
localPosFromDOM() { return 0; }
|
|
889
886
|
domBoundsAround() { return null; }
|
|
890
887
|
coordsAt(pos) {
|
|
891
|
-
|
|
892
|
-
return rects[rects.length - 1] || null;
|
|
888
|
+
return this.dom.getBoundingClientRect();
|
|
893
889
|
}
|
|
894
890
|
get overrideDOMText() {
|
|
895
|
-
return text.Text.
|
|
891
|
+
return text.Text.empty;
|
|
896
892
|
}
|
|
897
893
|
}
|
|
898
894
|
TextView.prototype.children = WidgetView.prototype.children = WidgetBufferView.prototype.children = noChildren;
|
|
@@ -939,7 +935,7 @@ function coordsInChildren(view, pos, side) {
|
|
|
939
935
|
continue;
|
|
940
936
|
flatten = side = -child.getSide();
|
|
941
937
|
}
|
|
942
|
-
let rect = child.coordsAt(pos - off, side);
|
|
938
|
+
let rect = child.coordsAt(Math.max(0, pos - off), side);
|
|
943
939
|
return flatten && rect ? flattenRect(rect, side < 0) : rect;
|
|
944
940
|
}
|
|
945
941
|
off = end;
|
|
@@ -1131,8 +1127,8 @@ class Decoration extends rangeset.RangeValue {
|
|
|
1131
1127
|
static replace(spec) {
|
|
1132
1128
|
let block = !!spec.block;
|
|
1133
1129
|
let { start, end } = getInclusive(spec, block);
|
|
1134
|
-
let startSide =
|
|
1135
|
-
let endSide =
|
|
1130
|
+
let startSide = (start ? (block ? -300000000 /* BlockIncStart */ : -1 /* InlineIncStart */) : 400000000 /* NonIncStart */) - 1;
|
|
1131
|
+
let endSide = (end ? (block ? 200000000 /* BlockIncEnd */ : 1 /* InlineIncEnd */) : -500000000 /* NonIncEnd */) + 1;
|
|
1136
1132
|
return new PointDecoration(spec, startSide, endSide, block, spec.widget || null, true);
|
|
1137
1133
|
}
|
|
1138
1134
|
/**
|
|
@@ -1577,11 +1573,13 @@ class ContentBuilder {
|
|
|
1577
1573
|
this.openStart = openStart;
|
|
1578
1574
|
}
|
|
1579
1575
|
filterPoint(from, to, value, index) {
|
|
1580
|
-
if (index
|
|
1581
|
-
|
|
1582
|
-
|
|
1583
|
-
|
|
1584
|
-
|
|
1576
|
+
if (index < this.disallowBlockEffectsBelow && value instanceof PointDecoration) {
|
|
1577
|
+
if (value.block)
|
|
1578
|
+
throw new RangeError("Block decorations may not be specified via plugins");
|
|
1579
|
+
if (to > this.doc.lineAt(this.pos).to)
|
|
1580
|
+
throw new RangeError("Decorations that replace line breaks may not be specified via plugins");
|
|
1581
|
+
}
|
|
1582
|
+
return true;
|
|
1585
1583
|
}
|
|
1586
1584
|
static build(text, from, to, decorations, pluginDecorationLength) {
|
|
1587
1585
|
let builder = new ContentBuilder(text, from, to, pluginDecorationLength);
|
|
@@ -2305,12 +2303,18 @@ function moveVisually(line, order, dir, start, forward) {
|
|
|
2305
2303
|
return state.EditorSelection.cursor(nextIndex + line.from, forward ? -1 : 1, span.level);
|
|
2306
2304
|
}
|
|
2307
2305
|
|
|
2306
|
+
const LineBreakPlaceholder = "\uffff";
|
|
2308
2307
|
class DOMReader {
|
|
2309
|
-
constructor(points,
|
|
2308
|
+
constructor(points, state$1) {
|
|
2310
2309
|
this.points = points;
|
|
2311
|
-
this.view = view;
|
|
2312
2310
|
this.text = "";
|
|
2313
|
-
this.
|
|
2311
|
+
this.lineSeparator = state$1.facet(state.EditorState.lineSeparator);
|
|
2312
|
+
}
|
|
2313
|
+
append(text) {
|
|
2314
|
+
this.text += text;
|
|
2315
|
+
}
|
|
2316
|
+
lineBreak() {
|
|
2317
|
+
this.text += LineBreakPlaceholder;
|
|
2314
2318
|
}
|
|
2315
2319
|
readRange(start, end) {
|
|
2316
2320
|
if (!start)
|
|
@@ -2326,42 +2330,61 @@ class DOMReader {
|
|
|
2326
2330
|
if (view && nextView ? view.breakAfter :
|
|
2327
2331
|
(view ? view.breakAfter : isBlockElement(cur)) ||
|
|
2328
2332
|
(isBlockElement(next) && (cur.nodeName != "BR" || cur.cmIgnore)))
|
|
2329
|
-
this.
|
|
2333
|
+
this.lineBreak();
|
|
2330
2334
|
cur = next;
|
|
2331
2335
|
}
|
|
2332
2336
|
this.findPointBefore(parent, end);
|
|
2333
2337
|
return this;
|
|
2334
2338
|
}
|
|
2335
2339
|
readTextNode(node) {
|
|
2336
|
-
var _a, _b;
|
|
2337
2340
|
let text = node.nodeValue;
|
|
2338
|
-
|
|
2339
|
-
|
|
2340
|
-
|
|
2341
|
-
|
|
2342
|
-
|
|
2341
|
+
for (let point of this.points)
|
|
2342
|
+
if (point.node == node)
|
|
2343
|
+
point.pos = this.text.length + Math.min(point.offset, text.length);
|
|
2344
|
+
for (let off = 0, re = this.lineSeparator ? null : /\r\n?|\n/g;;) {
|
|
2345
|
+
let nextBreak = -1, breakSize = 1, m;
|
|
2346
|
+
if (this.lineSeparator) {
|
|
2347
|
+
nextBreak = text.indexOf(this.lineSeparator, off);
|
|
2348
|
+
breakSize = this.lineSeparator.length;
|
|
2349
|
+
}
|
|
2350
|
+
else if (m = re.exec(text)) {
|
|
2351
|
+
nextBreak = m.index;
|
|
2352
|
+
breakSize = m[0].length;
|
|
2353
|
+
}
|
|
2354
|
+
this.append(text.slice(off, nextBreak < 0 ? text.length : nextBreak));
|
|
2355
|
+
if (nextBreak < 0)
|
|
2356
|
+
break;
|
|
2357
|
+
this.lineBreak();
|
|
2358
|
+
if (breakSize > 1)
|
|
2359
|
+
for (let point of this.points)
|
|
2360
|
+
if (point.node == node && point.pos > this.text.length)
|
|
2361
|
+
point.pos -= breakSize - 1;
|
|
2362
|
+
off = nextBreak + breakSize;
|
|
2363
|
+
}
|
|
2343
2364
|
}
|
|
2344
2365
|
readNode(node) {
|
|
2345
2366
|
if (node.cmIgnore)
|
|
2346
2367
|
return;
|
|
2347
2368
|
let view = ContentView.get(node);
|
|
2348
2369
|
let fromView = view && view.overrideDOMText;
|
|
2349
|
-
|
|
2350
|
-
|
|
2351
|
-
|
|
2352
|
-
|
|
2353
|
-
|
|
2354
|
-
|
|
2355
|
-
|
|
2356
|
-
|
|
2370
|
+
if (fromView != null) {
|
|
2371
|
+
this.findPointInside(node, fromView.length);
|
|
2372
|
+
for (let i = fromView.iter(); !i.next().done;) {
|
|
2373
|
+
if (i.lineBreak)
|
|
2374
|
+
this.lineBreak();
|
|
2375
|
+
else
|
|
2376
|
+
this.append(i.value);
|
|
2377
|
+
}
|
|
2378
|
+
}
|
|
2379
|
+
else if (node.nodeType == 3) {
|
|
2380
|
+
this.readTextNode(node);
|
|
2381
|
+
}
|
|
2382
|
+
else if (node.nodeName == "BR") {
|
|
2383
|
+
if (node.nextSibling)
|
|
2384
|
+
this.lineBreak();
|
|
2385
|
+
}
|
|
2386
|
+
else if (node.nodeType == 1) {
|
|
2357
2387
|
this.readRange(node.firstChild, null);
|
|
2358
|
-
if (text != null) {
|
|
2359
|
-
this.findPointIn(node, text.length);
|
|
2360
|
-
this.text += text;
|
|
2361
|
-
// Chrome inserts two newlines when pressing shift-enter at the
|
|
2362
|
-
// end of a line. This drops one of those.
|
|
2363
|
-
if (browser.chrome && this.view.inputState.lastKeyCode == 13 && !node.nextSibling && /\n\n$/.test(this.text))
|
|
2364
|
-
this.text = this.text.slice(0, -1);
|
|
2365
2388
|
}
|
|
2366
2389
|
}
|
|
2367
2390
|
findPointBefore(node, next) {
|
|
@@ -2369,10 +2392,10 @@ class DOMReader {
|
|
|
2369
2392
|
if (point.node == node && node.childNodes[point.offset] == next)
|
|
2370
2393
|
point.pos = this.text.length;
|
|
2371
2394
|
}
|
|
2372
|
-
|
|
2395
|
+
findPointInside(node, maxLen) {
|
|
2373
2396
|
for (let point of this.points)
|
|
2374
|
-
if (point.node == node)
|
|
2375
|
-
point.pos = this.text.length + Math.min(point.offset
|
|
2397
|
+
if (node.nodeType == 3 ? point.node == node : node.contains(point.node))
|
|
2398
|
+
point.pos = this.text.length + Math.min(maxLen, point.offset);
|
|
2376
2399
|
}
|
|
2377
2400
|
}
|
|
2378
2401
|
function isBlockElement(node) {
|
|
@@ -2815,16 +2838,16 @@ function computeCompositionDeco(view, changes) {
|
|
|
2815
2838
|
let { from, to, node, text: textNode } = surrounding;
|
|
2816
2839
|
let newFrom = changes.mapPos(from, 1), newTo = Math.max(newFrom, changes.mapPos(to, -1));
|
|
2817
2840
|
let { state } = view, text = node.nodeType == 3 ? node.nodeValue :
|
|
2818
|
-
new DOMReader([],
|
|
2841
|
+
new DOMReader([], state).readRange(node.firstChild, null).text;
|
|
2819
2842
|
if (newTo - newFrom < text.length) {
|
|
2820
|
-
if (state.
|
|
2843
|
+
if (state.doc.sliceString(newFrom, Math.min(state.doc.length, newFrom + text.length), LineBreakPlaceholder) == text)
|
|
2821
2844
|
newTo = newFrom + text.length;
|
|
2822
|
-
else if (state.
|
|
2845
|
+
else if (state.doc.sliceString(Math.max(0, newTo - text.length), newTo, LineBreakPlaceholder) == text)
|
|
2823
2846
|
newFrom = newTo - text.length;
|
|
2824
2847
|
else
|
|
2825
2848
|
return Decoration.none;
|
|
2826
2849
|
}
|
|
2827
|
-
else if (state.
|
|
2850
|
+
else if (state.doc.sliceString(newFrom, newTo, LineBreakPlaceholder) != text) {
|
|
2828
2851
|
return Decoration.none;
|
|
2829
2852
|
}
|
|
2830
2853
|
return Decoration.set(Decoration.replace({ widget: new CompositionWidget(node, textNode) }).range(newFrom, newTo));
|
|
@@ -4697,6 +4720,12 @@ class ViewState {
|
|
|
4697
4720
|
let refresh = this.heightOracle.mustRefreshForStyle(whiteSpace, direction);
|
|
4698
4721
|
let measureContent = refresh || this.mustMeasureContent || this.contentDOMHeight != dom.clientHeight;
|
|
4699
4722
|
let result = 0, bias = 0;
|
|
4723
|
+
if (this.editorWidth != view.scrollDOM.clientWidth) {
|
|
4724
|
+
if (oracle.lineWrapping)
|
|
4725
|
+
measureContent = true;
|
|
4726
|
+
this.editorWidth = view.scrollDOM.clientWidth;
|
|
4727
|
+
result |= 8 /* Geometry */;
|
|
4728
|
+
}
|
|
4700
4729
|
if (measureContent) {
|
|
4701
4730
|
this.mustMeasureContent = false;
|
|
4702
4731
|
this.contentDOMHeight = dom.clientHeight;
|
|
@@ -4722,11 +4751,9 @@ class ViewState {
|
|
|
4722
4751
|
if (!this.inView)
|
|
4723
4752
|
return 0;
|
|
4724
4753
|
let contentWidth = dom.clientWidth;
|
|
4725
|
-
if (this.contentDOMWidth != contentWidth || this.editorHeight != view.scrollDOM.clientHeight
|
|
4726
|
-
this.editorWidth != view.scrollDOM.clientWidth) {
|
|
4754
|
+
if (this.contentDOMWidth != contentWidth || this.editorHeight != view.scrollDOM.clientHeight) {
|
|
4727
4755
|
this.contentDOMWidth = contentWidth;
|
|
4728
4756
|
this.editorHeight = view.scrollDOM.clientHeight;
|
|
4729
|
-
this.editorWidth = view.scrollDOM.clientWidth;
|
|
4730
4757
|
result |= 8 /* Geometry */;
|
|
4731
4758
|
}
|
|
4732
4759
|
if (measureContent) {
|
|
@@ -4781,8 +4808,9 @@ class ViewState {
|
|
|
4781
4808
|
let viewport = new Viewport(map.lineAt(visibleTop - marginTop * 1000 /* Margin */, QueryType.ByHeight, doc, 0, 0).from, map.lineAt(visibleBottom + (1 - marginTop) * 1000 /* Margin */, QueryType.ByHeight, doc, 0, 0).to);
|
|
4782
4809
|
// If scrollTarget is given, make sure the viewport includes that position
|
|
4783
4810
|
if (scrollTarget) {
|
|
4784
|
-
let { head } = scrollTarget.range
|
|
4811
|
+
let { head } = scrollTarget.range;
|
|
4785
4812
|
if (head < viewport.from || head > viewport.to) {
|
|
4813
|
+
let viewHeight = Math.min(this.editorHeight, this.pixelViewport.bottom - this.pixelViewport.top);
|
|
4786
4814
|
let block = map.lineAt(head, QueryType.ByPos, doc, 0, 0), topPos;
|
|
4787
4815
|
if (scrollTarget.y == "center")
|
|
4788
4816
|
topPos = (block.top + block.bottom) / 2 - viewHeight / 2;
|
|
@@ -5168,6 +5196,10 @@ const baseTheme = buildTheme("." + baseThemeID, {
|
|
|
5168
5196
|
overflow: "hidden",
|
|
5169
5197
|
verticalAlign: "bottom"
|
|
5170
5198
|
},
|
|
5199
|
+
".cm-widgetBuffer": {
|
|
5200
|
+
verticalAlign: "text-bottom",
|
|
5201
|
+
height: "1em",
|
|
5202
|
+
},
|
|
5171
5203
|
".cm-placeholder": {
|
|
5172
5204
|
color: "#888",
|
|
5173
5205
|
display: "inline-block",
|
|
@@ -5416,7 +5448,7 @@ class DOMObserver {
|
|
|
5416
5448
|
}
|
|
5417
5449
|
// Throw away any pending changes
|
|
5418
5450
|
clear() {
|
|
5419
|
-
this.
|
|
5451
|
+
this.processRecords();
|
|
5420
5452
|
this.queue.length = 0;
|
|
5421
5453
|
this.selectionChanged = false;
|
|
5422
5454
|
}
|
|
@@ -5582,9 +5614,8 @@ function applyDOMChange(view, start, end, typeOver) {
|
|
|
5582
5614
|
return;
|
|
5583
5615
|
let { from, to } = bounds;
|
|
5584
5616
|
let selPoints = view.docView.impreciseHead || view.docView.impreciseAnchor ? [] : selectionPoints(view);
|
|
5585
|
-
let reader = new DOMReader(selPoints, view);
|
|
5617
|
+
let reader = new DOMReader(selPoints, view.state);
|
|
5586
5618
|
reader.readRange(bounds.startDOM, bounds.endDOM);
|
|
5587
|
-
newSel = selectionFromPoints(selPoints, from);
|
|
5588
5619
|
let preferredPos = sel.from, preferredSide = null;
|
|
5589
5620
|
// Prefer anchoring to end when Backspace is pressed (or, on
|
|
5590
5621
|
// Android, when something was deleted)
|
|
@@ -5593,10 +5624,17 @@ function applyDOMChange(view, start, end, typeOver) {
|
|
|
5593
5624
|
preferredPos = sel.to;
|
|
5594
5625
|
preferredSide = "end";
|
|
5595
5626
|
}
|
|
5596
|
-
let diff = findDiff(view.state.
|
|
5597
|
-
if (diff)
|
|
5627
|
+
let diff = findDiff(view.state.doc.sliceString(from, to, LineBreakPlaceholder), reader.text, preferredPos - from, preferredSide);
|
|
5628
|
+
if (diff) {
|
|
5629
|
+
// Chrome inserts two newlines when pressing shift-enter at the
|
|
5630
|
+
// end of a line. This drops one of those.
|
|
5631
|
+
if (browser.chrome && view.inputState.lastKeyCode == 13 &&
|
|
5632
|
+
diff.toB == diff.from + 2 && reader.text.slice(diff.from, diff.toB) == LineBreakPlaceholder + LineBreakPlaceholder)
|
|
5633
|
+
diff.toB--;
|
|
5598
5634
|
change = { from: from + diff.from, to: from + diff.toA,
|
|
5599
|
-
insert:
|
|
5635
|
+
insert: state.Text.of(reader.text.slice(diff.from, diff.toB).split(LineBreakPlaceholder)) };
|
|
5636
|
+
}
|
|
5637
|
+
newSel = selectionFromPoints(selPoints, from);
|
|
5600
5638
|
}
|
|
5601
5639
|
else if (view.hasFocus || !view.state.facet(editable)) {
|
|
5602
5640
|
let domSel = view.observer.selectionRange;
|
|
@@ -5875,9 +5913,17 @@ class EditorView {
|
|
|
5875
5913
|
get inView() { return this.viewState.inView; }
|
|
5876
5914
|
/**
|
|
5877
5915
|
Indicates whether the user is currently composing text via
|
|
5878
|
-
[IME](https://en.wikipedia.org/wiki/Input_method)
|
|
5916
|
+
[IME](https://en.wikipedia.org/wiki/Input_method), and at least
|
|
5917
|
+
one change has been made in the current composition.
|
|
5879
5918
|
*/
|
|
5880
5919
|
get composing() { return this.inputState.composing > 0; }
|
|
5920
|
+
/**
|
|
5921
|
+
Indicates whether the user is currently in composing state. Note
|
|
5922
|
+
that on some platforms, like Android, this will be the case a
|
|
5923
|
+
lot, since just putting the cursor on a word starts a
|
|
5924
|
+
composition there.
|
|
5925
|
+
*/
|
|
5926
|
+
get compositionStarted() { return this.inputState.composing >= 0; }
|
|
5881
5927
|
dispatch(...input) {
|
|
5882
5928
|
this._dispatch(input.length == 1 && input[0] instanceof state.Transaction ? input[0]
|
|
5883
5929
|
: this.state.update(...input));
|
|
@@ -5943,7 +5989,9 @@ class EditorView {
|
|
|
5943
5989
|
finally {
|
|
5944
5990
|
this.updateState = 0 /* Idle */;
|
|
5945
5991
|
}
|
|
5946
|
-
if (
|
|
5992
|
+
if (update.startState.facet(theme) != update.state.facet(theme))
|
|
5993
|
+
this.viewState.mustMeasureContent = true;
|
|
5994
|
+
if (redrawn || scrollTarget || this.viewState.mustEnforceCursorAssoc || this.viewState.mustMeasureContent)
|
|
5947
5995
|
this.requestMeasure();
|
|
5948
5996
|
if (!update.empty)
|
|
5949
5997
|
for (let listener of this.state.facet(updateListener))
|
package/dist/index.d.ts
CHANGED
|
@@ -676,9 +676,17 @@ declare class EditorView {
|
|
|
676
676
|
get inView(): boolean;
|
|
677
677
|
/**
|
|
678
678
|
Indicates whether the user is currently composing text via
|
|
679
|
-
[IME](https://en.wikipedia.org/wiki/Input_method)
|
|
679
|
+
[IME](https://en.wikipedia.org/wiki/Input_method), and at least
|
|
680
|
+
one change has been made in the current composition.
|
|
680
681
|
*/
|
|
681
682
|
get composing(): boolean;
|
|
683
|
+
/**
|
|
684
|
+
Indicates whether the user is currently in composing state. Note
|
|
685
|
+
that on some platforms, like Android, this will be the case a
|
|
686
|
+
lot, since just putting the cursor on a word starts a
|
|
687
|
+
composition there.
|
|
688
|
+
*/
|
|
689
|
+
get compositionStarted(): boolean;
|
|
682
690
|
private _dispatch;
|
|
683
691
|
/**
|
|
684
692
|
The document or shadow root that the view lives in.
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { MapMode, Text as Text$1, Facet, StateEffect, ChangeSet, EditorSelection,
|
|
1
|
+
import { MapMode, Text as Text$1, Facet, StateEffect, ChangeSet, EditorSelection, EditorState, CharCategory, Transaction, Prec, combineConfig, StateField } from '@codemirror/state';
|
|
2
2
|
import { StyleModule } from 'style-mod';
|
|
3
3
|
import { RangeSet, RangeValue, RangeSetBuilder } from '@codemirror/rangeset';
|
|
4
4
|
export { Range } from '@codemirror/rangeset';
|
|
@@ -599,9 +599,8 @@ function mergeChildrenInto(parent, from, to, insert, openStart, openEnd) {
|
|
|
599
599
|
replaceRange(parent, fromI, fromOff, toI, toOff, insert, 0, openStart, openEnd);
|
|
600
600
|
}
|
|
601
601
|
|
|
602
|
-
let
|
|
603
|
-
|
|
604
|
-
: [{ userAgent: "", vendor: "", platform: "" }, { documentElement: { style: {} } }];
|
|
602
|
+
let nav = typeof navigator != "undefined" ? navigator : { userAgent: "", vendor: "", platform: "" };
|
|
603
|
+
let doc = typeof document != "undefined" ? document : { documentElement: { style: {} } };
|
|
605
604
|
const ie_edge = /*@__PURE__*//Edge\/(\d+)/.exec(nav.userAgent);
|
|
606
605
|
const ie_upto10 = /*@__PURE__*//MSIE \d/.test(nav.userAgent);
|
|
607
606
|
const ie_11up = /*@__PURE__*//Trident\/(?:[7-9]|\d{2,})\..*rv:(\d+)/.exec(nav.userAgent);
|
|
@@ -857,9 +856,6 @@ class CompositionView extends WidgetView {
|
|
|
857
856
|
coordsAt(pos, side) { return textCoords(this.widget.text, pos, side); }
|
|
858
857
|
get isEditable() { return true; }
|
|
859
858
|
}
|
|
860
|
-
// Use two characters on Android, to prevent Chrome from closing the
|
|
861
|
-
// virtual keyboard when backspacing after a widget (#602).
|
|
862
|
-
const ZeroWidthSpace = browser.android ? "\u200b\u200b" : "\u200b";
|
|
863
859
|
// These are drawn around uneditable widgets to avoid a number of
|
|
864
860
|
// browser bugs that show up when the cursor is directly next to
|
|
865
861
|
// uneditable inline content.
|
|
@@ -875,21 +871,21 @@ class WidgetBufferView extends ContentView {
|
|
|
875
871
|
}
|
|
876
872
|
split() { return new WidgetBufferView(this.side); }
|
|
877
873
|
sync() {
|
|
878
|
-
if (!this.dom)
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
this.dom
|
|
874
|
+
if (!this.dom) {
|
|
875
|
+
let dom = document.createElement("img");
|
|
876
|
+
dom.className = "cm-widgetBuffer";
|
|
877
|
+
this.setDOM(dom);
|
|
878
|
+
}
|
|
882
879
|
}
|
|
883
880
|
getSide() { return this.side; }
|
|
884
881
|
domAtPos(pos) { return DOMPos.before(this.dom); }
|
|
885
882
|
localPosFromDOM() { return 0; }
|
|
886
883
|
domBoundsAround() { return null; }
|
|
887
884
|
coordsAt(pos) {
|
|
888
|
-
|
|
889
|
-
return rects[rects.length - 1] || null;
|
|
885
|
+
return this.dom.getBoundingClientRect();
|
|
890
886
|
}
|
|
891
887
|
get overrideDOMText() {
|
|
892
|
-
return Text.
|
|
888
|
+
return Text.empty;
|
|
893
889
|
}
|
|
894
890
|
}
|
|
895
891
|
TextView.prototype.children = WidgetView.prototype.children = WidgetBufferView.prototype.children = noChildren;
|
|
@@ -936,7 +932,7 @@ function coordsInChildren(view, pos, side) {
|
|
|
936
932
|
continue;
|
|
937
933
|
flatten = side = -child.getSide();
|
|
938
934
|
}
|
|
939
|
-
let rect = child.coordsAt(pos - off, side);
|
|
935
|
+
let rect = child.coordsAt(Math.max(0, pos - off), side);
|
|
940
936
|
return flatten && rect ? flattenRect(rect, side < 0) : rect;
|
|
941
937
|
}
|
|
942
938
|
off = end;
|
|
@@ -1127,8 +1123,8 @@ class Decoration extends RangeValue {
|
|
|
1127
1123
|
static replace(spec) {
|
|
1128
1124
|
let block = !!spec.block;
|
|
1129
1125
|
let { start, end } = getInclusive(spec, block);
|
|
1130
|
-
let startSide =
|
|
1131
|
-
let endSide =
|
|
1126
|
+
let startSide = (start ? (block ? -300000000 /* BlockIncStart */ : -1 /* InlineIncStart */) : 400000000 /* NonIncStart */) - 1;
|
|
1127
|
+
let endSide = (end ? (block ? 200000000 /* BlockIncEnd */ : 1 /* InlineIncEnd */) : -500000000 /* NonIncEnd */) + 1;
|
|
1132
1128
|
return new PointDecoration(spec, startSide, endSide, block, spec.widget || null, true);
|
|
1133
1129
|
}
|
|
1134
1130
|
/**
|
|
@@ -1573,11 +1569,13 @@ class ContentBuilder {
|
|
|
1573
1569
|
this.openStart = openStart;
|
|
1574
1570
|
}
|
|
1575
1571
|
filterPoint(from, to, value, index) {
|
|
1576
|
-
if (index
|
|
1577
|
-
|
|
1578
|
-
|
|
1579
|
-
|
|
1580
|
-
|
|
1572
|
+
if (index < this.disallowBlockEffectsBelow && value instanceof PointDecoration) {
|
|
1573
|
+
if (value.block)
|
|
1574
|
+
throw new RangeError("Block decorations may not be specified via plugins");
|
|
1575
|
+
if (to > this.doc.lineAt(this.pos).to)
|
|
1576
|
+
throw new RangeError("Decorations that replace line breaks may not be specified via plugins");
|
|
1577
|
+
}
|
|
1578
|
+
return true;
|
|
1581
1579
|
}
|
|
1582
1580
|
static build(text, from, to, decorations, pluginDecorationLength) {
|
|
1583
1581
|
let builder = new ContentBuilder(text, from, to, pluginDecorationLength);
|
|
@@ -2300,12 +2298,18 @@ function moveVisually(line, order, dir, start, forward) {
|
|
|
2300
2298
|
return EditorSelection.cursor(nextIndex + line.from, forward ? -1 : 1, span.level);
|
|
2301
2299
|
}
|
|
2302
2300
|
|
|
2301
|
+
const LineBreakPlaceholder = "\uffff";
|
|
2303
2302
|
class DOMReader {
|
|
2304
|
-
constructor(points,
|
|
2303
|
+
constructor(points, state) {
|
|
2305
2304
|
this.points = points;
|
|
2306
|
-
this.view = view;
|
|
2307
2305
|
this.text = "";
|
|
2308
|
-
this.
|
|
2306
|
+
this.lineSeparator = state.facet(EditorState.lineSeparator);
|
|
2307
|
+
}
|
|
2308
|
+
append(text) {
|
|
2309
|
+
this.text += text;
|
|
2310
|
+
}
|
|
2311
|
+
lineBreak() {
|
|
2312
|
+
this.text += LineBreakPlaceholder;
|
|
2309
2313
|
}
|
|
2310
2314
|
readRange(start, end) {
|
|
2311
2315
|
if (!start)
|
|
@@ -2321,42 +2325,61 @@ class DOMReader {
|
|
|
2321
2325
|
if (view && nextView ? view.breakAfter :
|
|
2322
2326
|
(view ? view.breakAfter : isBlockElement(cur)) ||
|
|
2323
2327
|
(isBlockElement(next) && (cur.nodeName != "BR" || cur.cmIgnore)))
|
|
2324
|
-
this.
|
|
2328
|
+
this.lineBreak();
|
|
2325
2329
|
cur = next;
|
|
2326
2330
|
}
|
|
2327
2331
|
this.findPointBefore(parent, end);
|
|
2328
2332
|
return this;
|
|
2329
2333
|
}
|
|
2330
2334
|
readTextNode(node) {
|
|
2331
|
-
var _a, _b;
|
|
2332
2335
|
let text = node.nodeValue;
|
|
2333
|
-
|
|
2334
|
-
|
|
2335
|
-
|
|
2336
|
-
|
|
2337
|
-
|
|
2336
|
+
for (let point of this.points)
|
|
2337
|
+
if (point.node == node)
|
|
2338
|
+
point.pos = this.text.length + Math.min(point.offset, text.length);
|
|
2339
|
+
for (let off = 0, re = this.lineSeparator ? null : /\r\n?|\n/g;;) {
|
|
2340
|
+
let nextBreak = -1, breakSize = 1, m;
|
|
2341
|
+
if (this.lineSeparator) {
|
|
2342
|
+
nextBreak = text.indexOf(this.lineSeparator, off);
|
|
2343
|
+
breakSize = this.lineSeparator.length;
|
|
2344
|
+
}
|
|
2345
|
+
else if (m = re.exec(text)) {
|
|
2346
|
+
nextBreak = m.index;
|
|
2347
|
+
breakSize = m[0].length;
|
|
2348
|
+
}
|
|
2349
|
+
this.append(text.slice(off, nextBreak < 0 ? text.length : nextBreak));
|
|
2350
|
+
if (nextBreak < 0)
|
|
2351
|
+
break;
|
|
2352
|
+
this.lineBreak();
|
|
2353
|
+
if (breakSize > 1)
|
|
2354
|
+
for (let point of this.points)
|
|
2355
|
+
if (point.node == node && point.pos > this.text.length)
|
|
2356
|
+
point.pos -= breakSize - 1;
|
|
2357
|
+
off = nextBreak + breakSize;
|
|
2358
|
+
}
|
|
2338
2359
|
}
|
|
2339
2360
|
readNode(node) {
|
|
2340
2361
|
if (node.cmIgnore)
|
|
2341
2362
|
return;
|
|
2342
2363
|
let view = ContentView.get(node);
|
|
2343
2364
|
let fromView = view && view.overrideDOMText;
|
|
2344
|
-
|
|
2345
|
-
|
|
2346
|
-
|
|
2347
|
-
|
|
2348
|
-
|
|
2349
|
-
|
|
2350
|
-
|
|
2351
|
-
|
|
2365
|
+
if (fromView != null) {
|
|
2366
|
+
this.findPointInside(node, fromView.length);
|
|
2367
|
+
for (let i = fromView.iter(); !i.next().done;) {
|
|
2368
|
+
if (i.lineBreak)
|
|
2369
|
+
this.lineBreak();
|
|
2370
|
+
else
|
|
2371
|
+
this.append(i.value);
|
|
2372
|
+
}
|
|
2373
|
+
}
|
|
2374
|
+
else if (node.nodeType == 3) {
|
|
2375
|
+
this.readTextNode(node);
|
|
2376
|
+
}
|
|
2377
|
+
else if (node.nodeName == "BR") {
|
|
2378
|
+
if (node.nextSibling)
|
|
2379
|
+
this.lineBreak();
|
|
2380
|
+
}
|
|
2381
|
+
else if (node.nodeType == 1) {
|
|
2352
2382
|
this.readRange(node.firstChild, null);
|
|
2353
|
-
if (text != null) {
|
|
2354
|
-
this.findPointIn(node, text.length);
|
|
2355
|
-
this.text += text;
|
|
2356
|
-
// Chrome inserts two newlines when pressing shift-enter at the
|
|
2357
|
-
// end of a line. This drops one of those.
|
|
2358
|
-
if (browser.chrome && this.view.inputState.lastKeyCode == 13 && !node.nextSibling && /\n\n$/.test(this.text))
|
|
2359
|
-
this.text = this.text.slice(0, -1);
|
|
2360
2383
|
}
|
|
2361
2384
|
}
|
|
2362
2385
|
findPointBefore(node, next) {
|
|
@@ -2364,10 +2387,10 @@ class DOMReader {
|
|
|
2364
2387
|
if (point.node == node && node.childNodes[point.offset] == next)
|
|
2365
2388
|
point.pos = this.text.length;
|
|
2366
2389
|
}
|
|
2367
|
-
|
|
2390
|
+
findPointInside(node, maxLen) {
|
|
2368
2391
|
for (let point of this.points)
|
|
2369
|
-
if (point.node == node)
|
|
2370
|
-
point.pos = this.text.length + Math.min(point.offset
|
|
2392
|
+
if (node.nodeType == 3 ? point.node == node : node.contains(point.node))
|
|
2393
|
+
point.pos = this.text.length + Math.min(maxLen, point.offset);
|
|
2371
2394
|
}
|
|
2372
2395
|
}
|
|
2373
2396
|
function isBlockElement(node) {
|
|
@@ -2810,16 +2833,16 @@ function computeCompositionDeco(view, changes) {
|
|
|
2810
2833
|
let { from, to, node, text: textNode } = surrounding;
|
|
2811
2834
|
let newFrom = changes.mapPos(from, 1), newTo = Math.max(newFrom, changes.mapPos(to, -1));
|
|
2812
2835
|
let { state } = view, text = node.nodeType == 3 ? node.nodeValue :
|
|
2813
|
-
new DOMReader([],
|
|
2836
|
+
new DOMReader([], state).readRange(node.firstChild, null).text;
|
|
2814
2837
|
if (newTo - newFrom < text.length) {
|
|
2815
|
-
if (state.
|
|
2838
|
+
if (state.doc.sliceString(newFrom, Math.min(state.doc.length, newFrom + text.length), LineBreakPlaceholder) == text)
|
|
2816
2839
|
newTo = newFrom + text.length;
|
|
2817
|
-
else if (state.
|
|
2840
|
+
else if (state.doc.sliceString(Math.max(0, newTo - text.length), newTo, LineBreakPlaceholder) == text)
|
|
2818
2841
|
newFrom = newTo - text.length;
|
|
2819
2842
|
else
|
|
2820
2843
|
return Decoration.none;
|
|
2821
2844
|
}
|
|
2822
|
-
else if (state.
|
|
2845
|
+
else if (state.doc.sliceString(newFrom, newTo, LineBreakPlaceholder) != text) {
|
|
2823
2846
|
return Decoration.none;
|
|
2824
2847
|
}
|
|
2825
2848
|
return Decoration.set(Decoration.replace({ widget: new CompositionWidget(node, textNode) }).range(newFrom, newTo));
|
|
@@ -4691,6 +4714,12 @@ class ViewState {
|
|
|
4691
4714
|
let refresh = this.heightOracle.mustRefreshForStyle(whiteSpace, direction);
|
|
4692
4715
|
let measureContent = refresh || this.mustMeasureContent || this.contentDOMHeight != dom.clientHeight;
|
|
4693
4716
|
let result = 0, bias = 0;
|
|
4717
|
+
if (this.editorWidth != view.scrollDOM.clientWidth) {
|
|
4718
|
+
if (oracle.lineWrapping)
|
|
4719
|
+
measureContent = true;
|
|
4720
|
+
this.editorWidth = view.scrollDOM.clientWidth;
|
|
4721
|
+
result |= 8 /* Geometry */;
|
|
4722
|
+
}
|
|
4694
4723
|
if (measureContent) {
|
|
4695
4724
|
this.mustMeasureContent = false;
|
|
4696
4725
|
this.contentDOMHeight = dom.clientHeight;
|
|
@@ -4716,11 +4745,9 @@ class ViewState {
|
|
|
4716
4745
|
if (!this.inView)
|
|
4717
4746
|
return 0;
|
|
4718
4747
|
let contentWidth = dom.clientWidth;
|
|
4719
|
-
if (this.contentDOMWidth != contentWidth || this.editorHeight != view.scrollDOM.clientHeight
|
|
4720
|
-
this.editorWidth != view.scrollDOM.clientWidth) {
|
|
4748
|
+
if (this.contentDOMWidth != contentWidth || this.editorHeight != view.scrollDOM.clientHeight) {
|
|
4721
4749
|
this.contentDOMWidth = contentWidth;
|
|
4722
4750
|
this.editorHeight = view.scrollDOM.clientHeight;
|
|
4723
|
-
this.editorWidth = view.scrollDOM.clientWidth;
|
|
4724
4751
|
result |= 8 /* Geometry */;
|
|
4725
4752
|
}
|
|
4726
4753
|
if (measureContent) {
|
|
@@ -4775,8 +4802,9 @@ class ViewState {
|
|
|
4775
4802
|
let viewport = new Viewport(map.lineAt(visibleTop - marginTop * 1000 /* Margin */, QueryType.ByHeight, doc, 0, 0).from, map.lineAt(visibleBottom + (1 - marginTop) * 1000 /* Margin */, QueryType.ByHeight, doc, 0, 0).to);
|
|
4776
4803
|
// If scrollTarget is given, make sure the viewport includes that position
|
|
4777
4804
|
if (scrollTarget) {
|
|
4778
|
-
let { head } = scrollTarget.range
|
|
4805
|
+
let { head } = scrollTarget.range;
|
|
4779
4806
|
if (head < viewport.from || head > viewport.to) {
|
|
4807
|
+
let viewHeight = Math.min(this.editorHeight, this.pixelViewport.bottom - this.pixelViewport.top);
|
|
4780
4808
|
let block = map.lineAt(head, QueryType.ByPos, doc, 0, 0), topPos;
|
|
4781
4809
|
if (scrollTarget.y == "center")
|
|
4782
4810
|
topPos = (block.top + block.bottom) / 2 - viewHeight / 2;
|
|
@@ -5162,6 +5190,10 @@ const baseTheme = /*@__PURE__*/buildTheme("." + baseThemeID, {
|
|
|
5162
5190
|
overflow: "hidden",
|
|
5163
5191
|
verticalAlign: "bottom"
|
|
5164
5192
|
},
|
|
5193
|
+
".cm-widgetBuffer": {
|
|
5194
|
+
verticalAlign: "text-bottom",
|
|
5195
|
+
height: "1em",
|
|
5196
|
+
},
|
|
5165
5197
|
".cm-placeholder": {
|
|
5166
5198
|
color: "#888",
|
|
5167
5199
|
display: "inline-block",
|
|
@@ -5410,7 +5442,7 @@ class DOMObserver {
|
|
|
5410
5442
|
}
|
|
5411
5443
|
// Throw away any pending changes
|
|
5412
5444
|
clear() {
|
|
5413
|
-
this.
|
|
5445
|
+
this.processRecords();
|
|
5414
5446
|
this.queue.length = 0;
|
|
5415
5447
|
this.selectionChanged = false;
|
|
5416
5448
|
}
|
|
@@ -5576,9 +5608,8 @@ function applyDOMChange(view, start, end, typeOver) {
|
|
|
5576
5608
|
return;
|
|
5577
5609
|
let { from, to } = bounds;
|
|
5578
5610
|
let selPoints = view.docView.impreciseHead || view.docView.impreciseAnchor ? [] : selectionPoints(view);
|
|
5579
|
-
let reader = new DOMReader(selPoints, view);
|
|
5611
|
+
let reader = new DOMReader(selPoints, view.state);
|
|
5580
5612
|
reader.readRange(bounds.startDOM, bounds.endDOM);
|
|
5581
|
-
newSel = selectionFromPoints(selPoints, from);
|
|
5582
5613
|
let preferredPos = sel.from, preferredSide = null;
|
|
5583
5614
|
// Prefer anchoring to end when Backspace is pressed (or, on
|
|
5584
5615
|
// Android, when something was deleted)
|
|
@@ -5587,10 +5618,17 @@ function applyDOMChange(view, start, end, typeOver) {
|
|
|
5587
5618
|
preferredPos = sel.to;
|
|
5588
5619
|
preferredSide = "end";
|
|
5589
5620
|
}
|
|
5590
|
-
let diff = findDiff(view.state.
|
|
5591
|
-
if (diff)
|
|
5621
|
+
let diff = findDiff(view.state.doc.sliceString(from, to, LineBreakPlaceholder), reader.text, preferredPos - from, preferredSide);
|
|
5622
|
+
if (diff) {
|
|
5623
|
+
// Chrome inserts two newlines when pressing shift-enter at the
|
|
5624
|
+
// end of a line. This drops one of those.
|
|
5625
|
+
if (browser.chrome && view.inputState.lastKeyCode == 13 &&
|
|
5626
|
+
diff.toB == diff.from + 2 && reader.text.slice(diff.from, diff.toB) == LineBreakPlaceholder + LineBreakPlaceholder)
|
|
5627
|
+
diff.toB--;
|
|
5592
5628
|
change = { from: from + diff.from, to: from + diff.toA,
|
|
5593
|
-
insert:
|
|
5629
|
+
insert: Text$1.of(reader.text.slice(diff.from, diff.toB).split(LineBreakPlaceholder)) };
|
|
5630
|
+
}
|
|
5631
|
+
newSel = selectionFromPoints(selPoints, from);
|
|
5594
5632
|
}
|
|
5595
5633
|
else if (view.hasFocus || !view.state.facet(editable)) {
|
|
5596
5634
|
let domSel = view.observer.selectionRange;
|
|
@@ -5869,9 +5907,17 @@ class EditorView {
|
|
|
5869
5907
|
get inView() { return this.viewState.inView; }
|
|
5870
5908
|
/**
|
|
5871
5909
|
Indicates whether the user is currently composing text via
|
|
5872
|
-
[IME](https://en.wikipedia.org/wiki/Input_method)
|
|
5910
|
+
[IME](https://en.wikipedia.org/wiki/Input_method), and at least
|
|
5911
|
+
one change has been made in the current composition.
|
|
5873
5912
|
*/
|
|
5874
5913
|
get composing() { return this.inputState.composing > 0; }
|
|
5914
|
+
/**
|
|
5915
|
+
Indicates whether the user is currently in composing state. Note
|
|
5916
|
+
that on some platforms, like Android, this will be the case a
|
|
5917
|
+
lot, since just putting the cursor on a word starts a
|
|
5918
|
+
composition there.
|
|
5919
|
+
*/
|
|
5920
|
+
get compositionStarted() { return this.inputState.composing >= 0; }
|
|
5875
5921
|
dispatch(...input) {
|
|
5876
5922
|
this._dispatch(input.length == 1 && input[0] instanceof Transaction ? input[0]
|
|
5877
5923
|
: this.state.update(...input));
|
|
@@ -5937,7 +5983,9 @@ class EditorView {
|
|
|
5937
5983
|
finally {
|
|
5938
5984
|
this.updateState = 0 /* Idle */;
|
|
5939
5985
|
}
|
|
5940
|
-
if (
|
|
5986
|
+
if (update.startState.facet(theme) != update.state.facet(theme))
|
|
5987
|
+
this.viewState.mustMeasureContent = true;
|
|
5988
|
+
if (redrawn || scrollTarget || this.viewState.mustEnforceCursorAssoc || this.viewState.mustMeasureContent)
|
|
5941
5989
|
this.requestMeasure();
|
|
5942
5990
|
if (!update.empty)
|
|
5943
5991
|
for (let listener of this.state.facet(updateListener))
|