@codemirror/view 6.17.1 → 6.18.1
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 +18 -0
- package/dist/index.cjs +326 -234
- package/dist/index.d.cts +13 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.js +327 -235
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Text, RangeSet, MapMode, RangeValue, Facet, StateEffect, ChangeSet, findClusterBreak, EditorSelection, findColumn, CharCategory, Annotation, EditorState, Transaction, Prec, codePointAt, codePointSize, combineConfig, StateField, RangeSetBuilder, countColumn } from '@codemirror/state';
|
|
2
2
|
import { StyleModule } from 'style-mod';
|
|
3
3
|
import { keyName, base, shift } from 'w3c-keyname';
|
|
4
4
|
|
|
@@ -99,6 +99,7 @@ function scrollRectIntoView(dom, rect, side, x, y, xMargin, yMargin, ltr) {
|
|
|
99
99
|
for (let cur = dom, stop = false; cur && !stop;) {
|
|
100
100
|
if (cur.nodeType == 1) { // Element
|
|
101
101
|
let bounding, top = cur == doc.body;
|
|
102
|
+
let scaleX = 1, scaleY = 1;
|
|
102
103
|
if (top) {
|
|
103
104
|
bounding = windowRect(win);
|
|
104
105
|
}
|
|
@@ -110,9 +111,11 @@ function scrollRectIntoView(dom, rect, side, x, y, xMargin, yMargin, ltr) {
|
|
|
110
111
|
continue;
|
|
111
112
|
}
|
|
112
113
|
let rect = cur.getBoundingClientRect();
|
|
114
|
+
scaleX = rect.width / cur.offsetWidth;
|
|
115
|
+
scaleY = rect.height / cur.offsetHeight;
|
|
113
116
|
// Make sure scrollbar width isn't included in the rectangle
|
|
114
|
-
bounding = { left: rect.left, right: rect.left + cur.clientWidth,
|
|
115
|
-
top: rect.top, bottom: rect.top + cur.clientHeight };
|
|
117
|
+
bounding = { left: rect.left, right: rect.left + cur.clientWidth * scaleX,
|
|
118
|
+
top: rect.top, bottom: rect.top + cur.clientHeight * scaleY };
|
|
116
119
|
}
|
|
117
120
|
let moveX = 0, moveY = 0;
|
|
118
121
|
if (y == "nearest") {
|
|
@@ -160,13 +163,13 @@ function scrollRectIntoView(dom, rect, side, x, y, xMargin, yMargin, ltr) {
|
|
|
160
163
|
let movedX = 0, movedY = 0;
|
|
161
164
|
if (moveY) {
|
|
162
165
|
let start = cur.scrollTop;
|
|
163
|
-
cur.scrollTop += moveY;
|
|
164
|
-
movedY = cur.scrollTop - start;
|
|
166
|
+
cur.scrollTop += moveY / scaleY;
|
|
167
|
+
movedY = (cur.scrollTop - start) * scaleY;
|
|
165
168
|
}
|
|
166
169
|
if (moveX) {
|
|
167
170
|
let start = cur.scrollLeft;
|
|
168
|
-
cur.scrollLeft += moveX;
|
|
169
|
-
movedX = cur.scrollLeft - start;
|
|
171
|
+
cur.scrollLeft += moveX / scaleX;
|
|
172
|
+
movedX = (cur.scrollLeft - start) * scaleX;
|
|
170
173
|
}
|
|
171
174
|
rect = { left: rect.left - movedX, top: rect.top - movedY,
|
|
172
175
|
right: rect.right - movedX, bottom: rect.bottom - movedY };
|
|
@@ -479,6 +482,8 @@ class ContentView {
|
|
|
479
482
|
}
|
|
480
483
|
}
|
|
481
484
|
setDOM(dom) {
|
|
485
|
+
if (this.dom == dom)
|
|
486
|
+
return;
|
|
482
487
|
if (this.dom)
|
|
483
488
|
this.dom.cmView = null;
|
|
484
489
|
this.dom = dom;
|
|
@@ -651,113 +656,6 @@ function mergeChildrenInto(parent, from, to, insert, openStart, openEnd) {
|
|
|
651
656
|
replaceRange(parent, fromI, fromOff, toI, toOff, insert, 0, openStart, openEnd);
|
|
652
657
|
}
|
|
653
658
|
|
|
654
|
-
const LineBreakPlaceholder = "\uffff";
|
|
655
|
-
class DOMReader {
|
|
656
|
-
constructor(points, state) {
|
|
657
|
-
this.points = points;
|
|
658
|
-
this.text = "";
|
|
659
|
-
this.lineSeparator = state.facet(EditorState.lineSeparator);
|
|
660
|
-
}
|
|
661
|
-
append(text) {
|
|
662
|
-
this.text += text;
|
|
663
|
-
}
|
|
664
|
-
lineBreak() {
|
|
665
|
-
this.text += LineBreakPlaceholder;
|
|
666
|
-
}
|
|
667
|
-
readRange(start, end) {
|
|
668
|
-
if (!start)
|
|
669
|
-
return this;
|
|
670
|
-
let parent = start.parentNode;
|
|
671
|
-
for (let cur = start;;) {
|
|
672
|
-
this.findPointBefore(parent, cur);
|
|
673
|
-
let oldLen = this.text.length;
|
|
674
|
-
this.readNode(cur);
|
|
675
|
-
let next = cur.nextSibling;
|
|
676
|
-
if (next == end)
|
|
677
|
-
break;
|
|
678
|
-
let view = ContentView.get(cur), nextView = ContentView.get(next);
|
|
679
|
-
if (view && nextView ? view.breakAfter :
|
|
680
|
-
(view ? view.breakAfter : isBlockElement(cur)) ||
|
|
681
|
-
(isBlockElement(next) && (cur.nodeName != "BR" || cur.cmIgnore) && this.text.length > oldLen))
|
|
682
|
-
this.lineBreak();
|
|
683
|
-
cur = next;
|
|
684
|
-
}
|
|
685
|
-
this.findPointBefore(parent, end);
|
|
686
|
-
return this;
|
|
687
|
-
}
|
|
688
|
-
readTextNode(node) {
|
|
689
|
-
let text = node.nodeValue;
|
|
690
|
-
for (let point of this.points)
|
|
691
|
-
if (point.node == node)
|
|
692
|
-
point.pos = this.text.length + Math.min(point.offset, text.length);
|
|
693
|
-
for (let off = 0, re = this.lineSeparator ? null : /\r\n?|\n/g;;) {
|
|
694
|
-
let nextBreak = -1, breakSize = 1, m;
|
|
695
|
-
if (this.lineSeparator) {
|
|
696
|
-
nextBreak = text.indexOf(this.lineSeparator, off);
|
|
697
|
-
breakSize = this.lineSeparator.length;
|
|
698
|
-
}
|
|
699
|
-
else if (m = re.exec(text)) {
|
|
700
|
-
nextBreak = m.index;
|
|
701
|
-
breakSize = m[0].length;
|
|
702
|
-
}
|
|
703
|
-
this.append(text.slice(off, nextBreak < 0 ? text.length : nextBreak));
|
|
704
|
-
if (nextBreak < 0)
|
|
705
|
-
break;
|
|
706
|
-
this.lineBreak();
|
|
707
|
-
if (breakSize > 1)
|
|
708
|
-
for (let point of this.points)
|
|
709
|
-
if (point.node == node && point.pos > this.text.length)
|
|
710
|
-
point.pos -= breakSize - 1;
|
|
711
|
-
off = nextBreak + breakSize;
|
|
712
|
-
}
|
|
713
|
-
}
|
|
714
|
-
readNode(node) {
|
|
715
|
-
if (node.cmIgnore)
|
|
716
|
-
return;
|
|
717
|
-
let view = ContentView.get(node);
|
|
718
|
-
let fromView = view && view.overrideDOMText;
|
|
719
|
-
if (fromView != null) {
|
|
720
|
-
this.findPointInside(node, fromView.length);
|
|
721
|
-
for (let i = fromView.iter(); !i.next().done;) {
|
|
722
|
-
if (i.lineBreak)
|
|
723
|
-
this.lineBreak();
|
|
724
|
-
else
|
|
725
|
-
this.append(i.value);
|
|
726
|
-
}
|
|
727
|
-
}
|
|
728
|
-
else if (node.nodeType == 3) {
|
|
729
|
-
this.readTextNode(node);
|
|
730
|
-
}
|
|
731
|
-
else if (node.nodeName == "BR") {
|
|
732
|
-
if (node.nextSibling)
|
|
733
|
-
this.lineBreak();
|
|
734
|
-
}
|
|
735
|
-
else if (node.nodeType == 1) {
|
|
736
|
-
this.readRange(node.firstChild, null);
|
|
737
|
-
}
|
|
738
|
-
}
|
|
739
|
-
findPointBefore(node, next) {
|
|
740
|
-
for (let point of this.points)
|
|
741
|
-
if (point.node == node && node.childNodes[point.offset] == next)
|
|
742
|
-
point.pos = this.text.length;
|
|
743
|
-
}
|
|
744
|
-
findPointInside(node, maxLen) {
|
|
745
|
-
for (let point of this.points)
|
|
746
|
-
if (node.nodeType == 3 ? point.node == node : node.contains(point.node))
|
|
747
|
-
point.pos = this.text.length + Math.min(maxLen, point.offset);
|
|
748
|
-
}
|
|
749
|
-
}
|
|
750
|
-
function isBlockElement(node) {
|
|
751
|
-
return node.nodeType == 1 && /^(DIV|P|LI|UL|OL|BLOCKQUOTE|DD|DT|H\d|SECTION|PRE)$/.test(node.nodeName);
|
|
752
|
-
}
|
|
753
|
-
class DOMPoint {
|
|
754
|
-
constructor(node, offset) {
|
|
755
|
-
this.node = node;
|
|
756
|
-
this.offset = offset;
|
|
757
|
-
this.pos = -1;
|
|
758
|
-
}
|
|
759
|
-
}
|
|
760
|
-
|
|
761
659
|
let nav = typeof navigator != "undefined" ? navigator : { userAgent: "", vendor: "", platform: "" };
|
|
762
660
|
let doc = typeof document != "undefined" ? document : { documentElement: { style: {} } };
|
|
763
661
|
const ie_edge = /*@__PURE__*//Edge\/(\d+)/.exec(nav.userAgent);
|
|
@@ -2699,6 +2597,7 @@ class DocView extends ContentView {
|
|
|
2699
2597
|
this.view = view;
|
|
2700
2598
|
this.decorations = [];
|
|
2701
2599
|
this.dynamicDecorationMap = [];
|
|
2600
|
+
this.domChanged = null;
|
|
2702
2601
|
this.hasComposition = null;
|
|
2703
2602
|
this.markedForComposition = new Set;
|
|
2704
2603
|
// Track a minimum width for the editor. When measuring sizes in
|
|
@@ -2727,6 +2626,7 @@ class DocView extends ContentView {
|
|
|
2727
2626
|
}
|
|
2728
2627
|
// Update the document view to a given state.
|
|
2729
2628
|
update(update) {
|
|
2629
|
+
var _a;
|
|
2730
2630
|
let changedRanges = update.changedRanges;
|
|
2731
2631
|
if (this.minWidth > 0 && changedRanges.length) {
|
|
2732
2632
|
if (!changedRanges.every(({ fromA, toA }) => toA < this.minWidthFrom || fromA > this.minWidthTo)) {
|
|
@@ -2737,7 +2637,15 @@ class DocView extends ContentView {
|
|
|
2737
2637
|
this.minWidthTo = update.changes.mapPos(this.minWidthTo, 1);
|
|
2738
2638
|
}
|
|
2739
2639
|
}
|
|
2740
|
-
let
|
|
2640
|
+
let readCompositionAt = -1;
|
|
2641
|
+
if (this.view.inputState.composing >= 0) {
|
|
2642
|
+
if ((_a = this.domChanged) === null || _a === void 0 ? void 0 : _a.newSel)
|
|
2643
|
+
readCompositionAt = this.domChanged.newSel.head;
|
|
2644
|
+
else if (!touchesComposition(update.changes, this.hasComposition) && !update.selectionSet)
|
|
2645
|
+
readCompositionAt = update.state.selection.main.head;
|
|
2646
|
+
}
|
|
2647
|
+
let composition = readCompositionAt > -1 ? findCompositionRange(this.view, update.changes, readCompositionAt) : null;
|
|
2648
|
+
this.domChanged = null;
|
|
2741
2649
|
if (this.hasComposition) {
|
|
2742
2650
|
this.markedForComposition.clear();
|
|
2743
2651
|
let { from, to } = this.hasComposition;
|
|
@@ -2777,7 +2685,7 @@ class DocView extends ContentView {
|
|
|
2777
2685
|
// messes with the scroll position during DOM mutation (though
|
|
2778
2686
|
// no relayout is triggered and I cannot imagine how it can
|
|
2779
2687
|
// recompute the scroll position without a layout)
|
|
2780
|
-
this.dom.style.height = this.view.viewState.contentHeight + "px";
|
|
2688
|
+
this.dom.style.height = this.view.viewState.contentHeight / this.view.scaleY + "px";
|
|
2781
2689
|
this.dom.style.flexBasis = this.minWidth ? this.minWidth + "px" : "";
|
|
2782
2690
|
// Chrome will sometimes, when DOM mutations occur directly
|
|
2783
2691
|
// around the selection, get confused and report a different
|
|
@@ -2849,14 +2757,12 @@ class DocView extends ContentView {
|
|
|
2849
2757
|
}
|
|
2850
2758
|
fixCompositionDOM(composition) {
|
|
2851
2759
|
let fix = (dom, cView) => {
|
|
2852
|
-
cView.flags |= 8 /* ViewFlag.Composition
|
|
2760
|
+
cView.flags |= 8 /* ViewFlag.Composition */ | (cView.children.some(c => c.flags & 7 /* ViewFlag.Dirty */) ? 1 /* ViewFlag.ChildDirty */ : 0);
|
|
2853
2761
|
this.markedForComposition.add(cView);
|
|
2854
2762
|
let prev = ContentView.get(dom);
|
|
2855
|
-
if (prev != cView)
|
|
2856
|
-
|
|
2857
|
-
|
|
2858
|
-
cView.setDOM(dom);
|
|
2859
|
-
}
|
|
2763
|
+
if (prev && prev != cView)
|
|
2764
|
+
prev.dom = null;
|
|
2765
|
+
cView.setDOM(dom);
|
|
2860
2766
|
};
|
|
2861
2767
|
let pos = this.childPos(composition.range.fromB, 1);
|
|
2862
2768
|
let cView = this.children[pos.i];
|
|
@@ -2879,9 +2785,8 @@ class DocView extends ContentView {
|
|
|
2879
2785
|
let force = this.forceSelection;
|
|
2880
2786
|
this.forceSelection = false;
|
|
2881
2787
|
let main = this.view.state.selection.main;
|
|
2882
|
-
|
|
2883
|
-
let
|
|
2884
|
-
let head = main.empty ? anchor : this.domAtPos(main.head);
|
|
2788
|
+
let anchor = this.moveToLine(this.domAtPos(main.anchor));
|
|
2789
|
+
let head = main.empty ? anchor : this.moveToLine(this.domAtPos(main.head));
|
|
2885
2790
|
// Always reset on Firefox when next to an uneditable node to
|
|
2886
2791
|
// avoid invisible cursor bugs (#111)
|
|
2887
2792
|
if (browser.gecko && main.empty && !this.hasComposition && betweenUneditable(anchor)) {
|
|
@@ -2914,12 +2819,12 @@ class DocView extends ContentView {
|
|
|
2914
2819
|
if (nextTo && nextTo != (1 /* NextTo.Before */ | 2 /* NextTo.After */)) {
|
|
2915
2820
|
let text = nearbyTextNode(anchor.node, anchor.offset, nextTo == 1 /* NextTo.Before */ ? 1 : -1);
|
|
2916
2821
|
if (text)
|
|
2917
|
-
anchor = new DOMPos(text,
|
|
2822
|
+
anchor = new DOMPos(text.node, text.offset);
|
|
2918
2823
|
}
|
|
2919
2824
|
}
|
|
2920
2825
|
rawSel.collapse(anchor.node, anchor.offset);
|
|
2921
|
-
if (main.bidiLevel != null &&
|
|
2922
|
-
|
|
2826
|
+
if (main.bidiLevel != null && rawSel.caretBidiLevel !== undefined)
|
|
2827
|
+
rawSel.caretBidiLevel = main.bidiLevel;
|
|
2923
2828
|
}
|
|
2924
2829
|
else if (rawSel.extend) {
|
|
2925
2830
|
// Selection.extend can be used to create an 'inverted' selection
|
|
@@ -2982,6 +2887,26 @@ class DocView extends ContentView {
|
|
|
2982
2887
|
if (view.docView.posFromDOM(newRange.anchorNode, newRange.anchorOffset) != cursor.from)
|
|
2983
2888
|
sel.collapse(anchorNode, anchorOffset);
|
|
2984
2889
|
}
|
|
2890
|
+
// If a position is in/near a block widget, move it to a nearby text
|
|
2891
|
+
// line, since we don't want the cursor inside a block widget.
|
|
2892
|
+
moveToLine(pos) {
|
|
2893
|
+
// Block widgets will return positions before/after them, which
|
|
2894
|
+
// are thus directly in the document DOM element.
|
|
2895
|
+
let dom = this.dom, newPos;
|
|
2896
|
+
if (pos.node != dom)
|
|
2897
|
+
return pos;
|
|
2898
|
+
for (let i = pos.offset; !newPos && i < dom.childNodes.length; i++) {
|
|
2899
|
+
let view = ContentView.get(dom.childNodes[i]);
|
|
2900
|
+
if (view instanceof LineView)
|
|
2901
|
+
newPos = view.domAtPos(0);
|
|
2902
|
+
}
|
|
2903
|
+
for (let i = pos.offset - 1; !newPos && i >= 0; i--) {
|
|
2904
|
+
let view = ContentView.get(dom.childNodes[i]);
|
|
2905
|
+
if (view instanceof LineView)
|
|
2906
|
+
newPos = view.domAtPos(view.length);
|
|
2907
|
+
}
|
|
2908
|
+
return newPos ? new DOMPos(newPos.node, newPos.offset, true) : pos;
|
|
2909
|
+
}
|
|
2985
2910
|
nearest(dom) {
|
|
2986
2911
|
for (let cur = dom; cur;) {
|
|
2987
2912
|
let domView = ContentView.get(cur);
|
|
@@ -3115,7 +3040,7 @@ class DocView extends ContentView {
|
|
|
3115
3040
|
let next = i == vs.viewports.length ? null : vs.viewports[i];
|
|
3116
3041
|
let end = next ? next.from - 1 : this.length;
|
|
3117
3042
|
if (end > pos) {
|
|
3118
|
-
let height = vs.lineBlockAt(end).bottom - vs.lineBlockAt(pos).top;
|
|
3043
|
+
let height = (vs.lineBlockAt(end).bottom - vs.lineBlockAt(pos).top) / this.view.scaleY;
|
|
3119
3044
|
deco.push(Decoration.replace({
|
|
3120
3045
|
widget: new BlockGapWidget(height),
|
|
3121
3046
|
block: true,
|
|
@@ -3180,74 +3105,27 @@ class BlockGapWidget extends WidgetType {
|
|
|
3180
3105
|
}
|
|
3181
3106
|
get estimatedHeight() { return this.height; }
|
|
3182
3107
|
}
|
|
3183
|
-
function findCompositionNode(view,
|
|
3108
|
+
function findCompositionNode(view, headPos) {
|
|
3184
3109
|
let sel = view.observer.selectionRange;
|
|
3185
3110
|
let textNode = sel.focusNode && nearbyTextNode(sel.focusNode, sel.focusOffset, 0);
|
|
3186
3111
|
if (!textNode)
|
|
3187
3112
|
return null;
|
|
3188
|
-
let
|
|
3189
|
-
|
|
3190
|
-
if (cView instanceof TextView) {
|
|
3191
|
-
from = cView.posAtStart;
|
|
3192
|
-
to = from + cView.length;
|
|
3193
|
-
}
|
|
3194
|
-
else {
|
|
3195
|
-
let oldLen = Math.max(0, textNode.nodeValue.length - dLen);
|
|
3196
|
-
up: for (let offset = 0, node = textNode;;) {
|
|
3197
|
-
for (let sibling = node.previousSibling, cView; sibling; sibling = sibling.previousSibling) {
|
|
3198
|
-
if (cView = ContentView.get(sibling)) {
|
|
3199
|
-
to = cView.posAtEnd + offset;
|
|
3200
|
-
from = Math.max(0, to - oldLen);
|
|
3201
|
-
break up;
|
|
3202
|
-
}
|
|
3203
|
-
let reader = new DOMReader([], view.state);
|
|
3204
|
-
reader.readNode(sibling);
|
|
3205
|
-
if (reader.text.indexOf(LineBreakPlaceholder) > -1)
|
|
3206
|
-
return null;
|
|
3207
|
-
offset += reader.text.length;
|
|
3208
|
-
}
|
|
3209
|
-
node = node.parentNode;
|
|
3210
|
-
if (!node)
|
|
3211
|
-
return null;
|
|
3212
|
-
let parentView = ContentView.get(node);
|
|
3213
|
-
if (parentView) {
|
|
3214
|
-
from = parentView.posAtStart + offset;
|
|
3215
|
-
to = from + oldLen;
|
|
3216
|
-
break;
|
|
3217
|
-
}
|
|
3218
|
-
}
|
|
3219
|
-
}
|
|
3220
|
-
return { from, to: to, node: textNode };
|
|
3113
|
+
let from = headPos - textNode.offset;
|
|
3114
|
+
return { from, to: from + textNode.node.nodeValue.length, node: textNode.node };
|
|
3221
3115
|
}
|
|
3222
|
-
function findCompositionRange(view, changes) {
|
|
3223
|
-
let found = findCompositionNode(view,
|
|
3116
|
+
function findCompositionRange(view, changes, headPos) {
|
|
3117
|
+
let found = findCompositionNode(view, headPos);
|
|
3224
3118
|
if (!found)
|
|
3225
3119
|
return null;
|
|
3226
|
-
let {
|
|
3227
|
-
let fromB = changes.mapPos(fromA, -1), toB = changes.mapPos(toA, 1);
|
|
3228
|
-
let text = textNode.nodeValue;
|
|
3120
|
+
let { node: textNode, from, to } = found, text = textNode.nodeValue;
|
|
3229
3121
|
// Don't try to preserve multi-line compositions
|
|
3230
3122
|
if (/[\n\r]/.test(text))
|
|
3231
3123
|
return null;
|
|
3232
|
-
if (
|
|
3233
|
-
// If there is a length mismatch, see if mapping non-inclusively helps
|
|
3234
|
-
let fromB2 = changes.mapPos(fromA, 1), toB2 = changes.mapPos(toA, -1);
|
|
3235
|
-
if (toB2 - fromB2 == text.length)
|
|
3236
|
-
fromB = fromB2, toB = toB2;
|
|
3237
|
-
// See if we can find an instance of the text at either side
|
|
3238
|
-
else if (view.state.doc.sliceString(toB - text.length, toB) == text)
|
|
3239
|
-
fromB = toB - text.length;
|
|
3240
|
-
else if (view.state.doc.sliceString(fromB, fromB + text.length) == text)
|
|
3241
|
-
toB = fromB + text.length;
|
|
3242
|
-
// Not found
|
|
3243
|
-
else
|
|
3244
|
-
return null;
|
|
3245
|
-
}
|
|
3246
|
-
let { main } = view.state.selection;
|
|
3247
|
-
if (view.state.doc.sliceString(fromB, toB) != text || fromB > main.head || toB < main.head)
|
|
3124
|
+
if (view.state.doc.sliceString(found.from, found.to) != text)
|
|
3248
3125
|
return null;
|
|
3126
|
+
let inv = changes.invertedDesc;
|
|
3127
|
+
let range = new ChangedRange(inv.mapPos(from), inv.mapPos(to), from, to);
|
|
3249
3128
|
let marks = [];
|
|
3250
|
-
let range = new ChangedRange(fromA, toA, fromB, toB);
|
|
3251
3129
|
for (let parent = textNode.parentNode;; parent = parent.parentNode) {
|
|
3252
3130
|
let parentView = ContentView.get(parent);
|
|
3253
3131
|
if (parentView instanceof MarkView)
|
|
@@ -3268,7 +3146,7 @@ function nearbyTextNode(startNode, startOffset, side) {
|
|
|
3268
3146
|
if (side <= 0)
|
|
3269
3147
|
for (let node = startNode, offset = startOffset;;) {
|
|
3270
3148
|
if (node.nodeType == 3)
|
|
3271
|
-
return node;
|
|
3149
|
+
return { node: node, offset: offset };
|
|
3272
3150
|
if (node.nodeType == 1 && offset > 0) {
|
|
3273
3151
|
node = node.childNodes[offset - 1];
|
|
3274
3152
|
offset = maxOffset(node);
|
|
@@ -3280,7 +3158,7 @@ function nearbyTextNode(startNode, startOffset, side) {
|
|
|
3280
3158
|
if (side >= 0)
|
|
3281
3159
|
for (let node = startNode, offset = startOffset;;) {
|
|
3282
3160
|
if (node.nodeType == 3)
|
|
3283
|
-
return node;
|
|
3161
|
+
return { node: node, offset: offset };
|
|
3284
3162
|
if (node.nodeType == 1 && offset < node.childNodes.length && side >= 0) {
|
|
3285
3163
|
node = node.childNodes[offset];
|
|
3286
3164
|
offset = 0;
|
|
@@ -3317,6 +3195,15 @@ function inUneditable(node, inside) {
|
|
|
3317
3195
|
}
|
|
3318
3196
|
return false;
|
|
3319
3197
|
}
|
|
3198
|
+
function touchesComposition(changes, composition) {
|
|
3199
|
+
let touched = false;
|
|
3200
|
+
if (composition)
|
|
3201
|
+
changes.iterChangedRanges((from, to) => {
|
|
3202
|
+
if (from < composition.to && to > composition.from)
|
|
3203
|
+
touched = true;
|
|
3204
|
+
});
|
|
3205
|
+
return touched;
|
|
3206
|
+
}
|
|
3320
3207
|
|
|
3321
3208
|
function groupAt(state, pos, bias = 1) {
|
|
3322
3209
|
let categorize = state.charCategorizer(pos);
|
|
@@ -5271,8 +5158,10 @@ class LineGap {
|
|
|
5271
5158
|
}
|
|
5272
5159
|
return true;
|
|
5273
5160
|
}
|
|
5274
|
-
draw(wrapping) {
|
|
5275
|
-
return Decoration.replace({
|
|
5161
|
+
draw(viewState, wrapping) {
|
|
5162
|
+
return Decoration.replace({
|
|
5163
|
+
widget: new LineGapWidget(this.size * (wrapping ? viewState.scaleY : viewState.scaleX), wrapping)
|
|
5164
|
+
}).range(this.from, this.to);
|
|
5276
5165
|
}
|
|
5277
5166
|
}
|
|
5278
5167
|
class LineGapWidget extends WidgetType {
|
|
@@ -5302,14 +5191,18 @@ class ViewState {
|
|
|
5302
5191
|
// These are contentDOM-local coordinates
|
|
5303
5192
|
this.pixelViewport = { left: 0, right: window.innerWidth, top: 0, bottom: 0 };
|
|
5304
5193
|
this.inView = true;
|
|
5305
|
-
this.paddingTop = 0;
|
|
5306
|
-
this.paddingBottom = 0;
|
|
5307
|
-
this.contentDOMWidth = 0;
|
|
5308
|
-
this.contentDOMHeight = 0;
|
|
5309
|
-
this.editorHeight = 0;
|
|
5310
|
-
this.editorWidth = 0;
|
|
5311
|
-
this.scrollTop = 0;
|
|
5194
|
+
this.paddingTop = 0; // Padding above the document, scaled
|
|
5195
|
+
this.paddingBottom = 0; // Padding below the document, scaled
|
|
5196
|
+
this.contentDOMWidth = 0; // contentDOM.getBoundingClientRect().width
|
|
5197
|
+
this.contentDOMHeight = 0; // contentDOM.getBoundingClientRect().height
|
|
5198
|
+
this.editorHeight = 0; // scrollDOM.clientHeight, unscaled
|
|
5199
|
+
this.editorWidth = 0; // scrollDOM.clientWidth, unscaled
|
|
5200
|
+
this.scrollTop = 0; // Last seen scrollDOM.scrollTop, scaled
|
|
5312
5201
|
this.scrolledToBottom = true;
|
|
5202
|
+
// The CSS-transformation scale of the editor (transformed size /
|
|
5203
|
+
// concrete size)
|
|
5204
|
+
this.scaleX = 1;
|
|
5205
|
+
this.scaleY = 1;
|
|
5313
5206
|
// The vertical position (document-relative) to which to anchor the
|
|
5314
5207
|
// scroll position. -1 means anchor to the end of the document.
|
|
5315
5208
|
this.scrollAnchorPos = 0;
|
|
@@ -5343,7 +5236,7 @@ class ViewState {
|
|
|
5343
5236
|
this.updateViewportLines();
|
|
5344
5237
|
this.updateForViewport();
|
|
5345
5238
|
this.lineGaps = this.ensureLineGaps([]);
|
|
5346
|
-
this.lineGapDeco = Decoration.set(this.lineGaps.map(gap => gap.draw(false)));
|
|
5239
|
+
this.lineGapDeco = Decoration.set(this.lineGaps.map(gap => gap.draw(this, false)));
|
|
5347
5240
|
this.computeVisibleRanges();
|
|
5348
5241
|
}
|
|
5349
5242
|
updateForViewport() {
|
|
@@ -5415,8 +5308,23 @@ class ViewState {
|
|
|
5415
5308
|
this.contentDOMHeight = domRect.height;
|
|
5416
5309
|
this.mustMeasureContent = false;
|
|
5417
5310
|
let result = 0, bias = 0;
|
|
5311
|
+
if (domRect.width && domRect.height) {
|
|
5312
|
+
let scaleX = domRect.width / dom.offsetWidth;
|
|
5313
|
+
let scaleY = domRect.height / dom.offsetHeight;
|
|
5314
|
+
if (scaleX > 0.995 && scaleX < 1.005)
|
|
5315
|
+
scaleX = 1;
|
|
5316
|
+
if (scaleY > 0.995 && scaleY < 1.005)
|
|
5317
|
+
scaleY = 1;
|
|
5318
|
+
if (this.scaleX != scaleX || this.scaleY != scaleY) {
|
|
5319
|
+
this.scaleX = scaleX;
|
|
5320
|
+
this.scaleY = scaleY;
|
|
5321
|
+
result |= 8 /* UpdateFlag.Geometry */;
|
|
5322
|
+
refresh = measureContent = true;
|
|
5323
|
+
}
|
|
5324
|
+
}
|
|
5418
5325
|
// Vertical padding
|
|
5419
|
-
let paddingTop = parseInt(style.paddingTop) || 0
|
|
5326
|
+
let paddingTop = (parseInt(style.paddingTop) || 0) * this.scaleY;
|
|
5327
|
+
let paddingBottom = (parseInt(style.paddingBottom) || 0) * this.scaleY;
|
|
5420
5328
|
if (this.paddingTop != paddingTop || this.paddingBottom != paddingBottom) {
|
|
5421
5329
|
this.paddingTop = paddingTop;
|
|
5422
5330
|
this.paddingBottom = paddingBottom;
|
|
@@ -5428,9 +5336,10 @@ class ViewState {
|
|
|
5428
5336
|
this.editorWidth = view.scrollDOM.clientWidth;
|
|
5429
5337
|
result |= 8 /* UpdateFlag.Geometry */;
|
|
5430
5338
|
}
|
|
5431
|
-
|
|
5339
|
+
let scrollTop = view.scrollDOM.scrollTop * this.scaleY;
|
|
5340
|
+
if (this.scrollTop != scrollTop) {
|
|
5432
5341
|
this.scrollAnchorHeight = -1;
|
|
5433
|
-
this.scrollTop =
|
|
5342
|
+
this.scrollTop = scrollTop;
|
|
5434
5343
|
}
|
|
5435
5344
|
this.scrolledToBottom = isScrolledToBottom(view.scrollDOM);
|
|
5436
5345
|
// Pixel viewport
|
|
@@ -5651,7 +5560,7 @@ class ViewState {
|
|
|
5651
5560
|
updateLineGaps(gaps) {
|
|
5652
5561
|
if (!LineGap.same(gaps, this.lineGaps)) {
|
|
5653
5562
|
this.lineGaps = gaps;
|
|
5654
|
-
this.lineGapDeco = Decoration.set(gaps.map(gap => gap.draw(this.heightOracle.lineWrapping)));
|
|
5563
|
+
this.lineGapDeco = Decoration.set(gaps.map(gap => gap.draw(this, this.heightOracle.lineWrapping)));
|
|
5655
5564
|
}
|
|
5656
5565
|
}
|
|
5657
5566
|
computeVisibleRanges() {
|
|
@@ -6052,6 +5961,113 @@ const baseTheme$1 = /*@__PURE__*/buildTheme("." + baseThemeID, {
|
|
|
6052
5961
|
}
|
|
6053
5962
|
}, lightDarkIDs);
|
|
6054
5963
|
|
|
5964
|
+
const LineBreakPlaceholder = "\uffff";
|
|
5965
|
+
class DOMReader {
|
|
5966
|
+
constructor(points, state) {
|
|
5967
|
+
this.points = points;
|
|
5968
|
+
this.text = "";
|
|
5969
|
+
this.lineSeparator = state.facet(EditorState.lineSeparator);
|
|
5970
|
+
}
|
|
5971
|
+
append(text) {
|
|
5972
|
+
this.text += text;
|
|
5973
|
+
}
|
|
5974
|
+
lineBreak() {
|
|
5975
|
+
this.text += LineBreakPlaceholder;
|
|
5976
|
+
}
|
|
5977
|
+
readRange(start, end) {
|
|
5978
|
+
if (!start)
|
|
5979
|
+
return this;
|
|
5980
|
+
let parent = start.parentNode;
|
|
5981
|
+
for (let cur = start;;) {
|
|
5982
|
+
this.findPointBefore(parent, cur);
|
|
5983
|
+
let oldLen = this.text.length;
|
|
5984
|
+
this.readNode(cur);
|
|
5985
|
+
let next = cur.nextSibling;
|
|
5986
|
+
if (next == end)
|
|
5987
|
+
break;
|
|
5988
|
+
let view = ContentView.get(cur), nextView = ContentView.get(next);
|
|
5989
|
+
if (view && nextView ? view.breakAfter :
|
|
5990
|
+
(view ? view.breakAfter : isBlockElement(cur)) ||
|
|
5991
|
+
(isBlockElement(next) && (cur.nodeName != "BR" || cur.cmIgnore) && this.text.length > oldLen))
|
|
5992
|
+
this.lineBreak();
|
|
5993
|
+
cur = next;
|
|
5994
|
+
}
|
|
5995
|
+
this.findPointBefore(parent, end);
|
|
5996
|
+
return this;
|
|
5997
|
+
}
|
|
5998
|
+
readTextNode(node) {
|
|
5999
|
+
let text = node.nodeValue;
|
|
6000
|
+
for (let point of this.points)
|
|
6001
|
+
if (point.node == node)
|
|
6002
|
+
point.pos = this.text.length + Math.min(point.offset, text.length);
|
|
6003
|
+
for (let off = 0, re = this.lineSeparator ? null : /\r\n?|\n/g;;) {
|
|
6004
|
+
let nextBreak = -1, breakSize = 1, m;
|
|
6005
|
+
if (this.lineSeparator) {
|
|
6006
|
+
nextBreak = text.indexOf(this.lineSeparator, off);
|
|
6007
|
+
breakSize = this.lineSeparator.length;
|
|
6008
|
+
}
|
|
6009
|
+
else if (m = re.exec(text)) {
|
|
6010
|
+
nextBreak = m.index;
|
|
6011
|
+
breakSize = m[0].length;
|
|
6012
|
+
}
|
|
6013
|
+
this.append(text.slice(off, nextBreak < 0 ? text.length : nextBreak));
|
|
6014
|
+
if (nextBreak < 0)
|
|
6015
|
+
break;
|
|
6016
|
+
this.lineBreak();
|
|
6017
|
+
if (breakSize > 1)
|
|
6018
|
+
for (let point of this.points)
|
|
6019
|
+
if (point.node == node && point.pos > this.text.length)
|
|
6020
|
+
point.pos -= breakSize - 1;
|
|
6021
|
+
off = nextBreak + breakSize;
|
|
6022
|
+
}
|
|
6023
|
+
}
|
|
6024
|
+
readNode(node) {
|
|
6025
|
+
if (node.cmIgnore)
|
|
6026
|
+
return;
|
|
6027
|
+
let view = ContentView.get(node);
|
|
6028
|
+
let fromView = view && view.overrideDOMText;
|
|
6029
|
+
if (fromView != null) {
|
|
6030
|
+
this.findPointInside(node, fromView.length);
|
|
6031
|
+
for (let i = fromView.iter(); !i.next().done;) {
|
|
6032
|
+
if (i.lineBreak)
|
|
6033
|
+
this.lineBreak();
|
|
6034
|
+
else
|
|
6035
|
+
this.append(i.value);
|
|
6036
|
+
}
|
|
6037
|
+
}
|
|
6038
|
+
else if (node.nodeType == 3) {
|
|
6039
|
+
this.readTextNode(node);
|
|
6040
|
+
}
|
|
6041
|
+
else if (node.nodeName == "BR") {
|
|
6042
|
+
if (node.nextSibling)
|
|
6043
|
+
this.lineBreak();
|
|
6044
|
+
}
|
|
6045
|
+
else if (node.nodeType == 1) {
|
|
6046
|
+
this.readRange(node.firstChild, null);
|
|
6047
|
+
}
|
|
6048
|
+
}
|
|
6049
|
+
findPointBefore(node, next) {
|
|
6050
|
+
for (let point of this.points)
|
|
6051
|
+
if (point.node == node && node.childNodes[point.offset] == next)
|
|
6052
|
+
point.pos = this.text.length;
|
|
6053
|
+
}
|
|
6054
|
+
findPointInside(node, maxLen) {
|
|
6055
|
+
for (let point of this.points)
|
|
6056
|
+
if (node.nodeType == 3 ? point.node == node : node.contains(point.node))
|
|
6057
|
+
point.pos = this.text.length + Math.min(maxLen, point.offset);
|
|
6058
|
+
}
|
|
6059
|
+
}
|
|
6060
|
+
function isBlockElement(node) {
|
|
6061
|
+
return node.nodeType == 1 && /^(DIV|P|LI|UL|OL|BLOCKQUOTE|DD|DT|H\d|SECTION|PRE)$/.test(node.nodeName);
|
|
6062
|
+
}
|
|
6063
|
+
class DOMPoint {
|
|
6064
|
+
constructor(node, offset) {
|
|
6065
|
+
this.node = node;
|
|
6066
|
+
this.offset = offset;
|
|
6067
|
+
this.pos = -1;
|
|
6068
|
+
}
|
|
6069
|
+
}
|
|
6070
|
+
|
|
6055
6071
|
class DOMChange {
|
|
6056
6072
|
constructor(view, start, end, typeOver) {
|
|
6057
6073
|
this.typeOver = typeOver;
|
|
@@ -6202,8 +6218,14 @@ function applyDefaultInsert(view, change, newSel) {
|
|
|
6202
6218
|
if (startState.selection.ranges.length > 1 && view.inputState.composing >= 0 &&
|
|
6203
6219
|
change.to <= sel.to && change.to >= sel.to - 10) {
|
|
6204
6220
|
let replaced = view.state.sliceDoc(change.from, change.to);
|
|
6205
|
-
let composition = findCompositionNode(view,
|
|
6206
|
-
|
|
6221
|
+
let compositionRange, composition = newSel && findCompositionNode(view, newSel.main.head);
|
|
6222
|
+
if (composition) {
|
|
6223
|
+
let dLen = change.insert.length - (change.to - change.from);
|
|
6224
|
+
compositionRange = { from: composition.from, to: composition.to - dLen };
|
|
6225
|
+
}
|
|
6226
|
+
else {
|
|
6227
|
+
compositionRange = view.state.doc.lineAt(sel.head);
|
|
6228
|
+
}
|
|
6207
6229
|
let offset = sel.to - change.to, size = sel.to - sel.from;
|
|
6208
6230
|
tr = startState.changeByRange(range => {
|
|
6209
6231
|
if (range.from == sel.from && range.to == sel.to)
|
|
@@ -6214,7 +6236,7 @@ function applyDefaultInsert(view, change, newSel) {
|
|
|
6214
6236
|
// changes in the same node work without aborting
|
|
6215
6237
|
// composition, so cursors in the composition range are
|
|
6216
6238
|
// ignored.
|
|
6217
|
-
|
|
6239
|
+
range.to >= compositionRange.from && range.from <= compositionRange.to)
|
|
6218
6240
|
return { range };
|
|
6219
6241
|
let rangeChanges = startState.changes({ from, to, insert: change.insert }), selOff = range.to - sel.to;
|
|
6220
6242
|
return {
|
|
@@ -6633,7 +6655,9 @@ class DOMObserver {
|
|
|
6633
6655
|
this.lastChange = Date.now();
|
|
6634
6656
|
this.view.inputState.lastFocusTime = 0;
|
|
6635
6657
|
this.selectionChanged = false;
|
|
6636
|
-
|
|
6658
|
+
let change = new DOMChange(this.view, from, to, typeOver);
|
|
6659
|
+
this.view.docView.domChanged = { newSel: change.newSel ? change.newSel.main : null };
|
|
6660
|
+
return change;
|
|
6637
6661
|
}
|
|
6638
6662
|
// Apply pending changes, if any
|
|
6639
6663
|
flush(readSelection = true) {
|
|
@@ -7062,9 +7086,9 @@ class EditorView {
|
|
|
7062
7086
|
if (flush)
|
|
7063
7087
|
this.observer.forceFlush();
|
|
7064
7088
|
let updated = null;
|
|
7065
|
-
let sDOM = this.scrollDOM,
|
|
7089
|
+
let sDOM = this.scrollDOM, scrollTop = sDOM.scrollTop * this.scaleY;
|
|
7066
7090
|
let { scrollAnchorPos, scrollAnchorHeight } = this.viewState;
|
|
7067
|
-
if (scrollTop
|
|
7091
|
+
if (Math.abs(scrollTop - this.viewState.scrollTop) > 1)
|
|
7068
7092
|
scrollAnchorHeight = -1;
|
|
7069
7093
|
this.viewState.scrollAnchorHeight = -1;
|
|
7070
7094
|
try {
|
|
@@ -7141,7 +7165,8 @@ class EditorView {
|
|
|
7141
7165
|
this.viewState.lineBlockAt(scrollAnchorPos).top;
|
|
7142
7166
|
let diff = newAnchorHeight - scrollAnchorHeight;
|
|
7143
7167
|
if (diff > 1 || diff < -1) {
|
|
7144
|
-
scrollTop =
|
|
7168
|
+
scrollTop = scrollTop + diff;
|
|
7169
|
+
sDOM.scrollTop = scrollTop / this.scaleY;
|
|
7145
7170
|
scrollAnchorHeight = -1;
|
|
7146
7171
|
continue;
|
|
7147
7172
|
}
|
|
@@ -7268,6 +7293,16 @@ class EditorView {
|
|
|
7268
7293
|
return { top: this.viewState.paddingTop, bottom: this.viewState.paddingBottom };
|
|
7269
7294
|
}
|
|
7270
7295
|
/**
|
|
7296
|
+
If the editor is transformed with CSS, this provides the scale
|
|
7297
|
+
along the X axis. Otherwise, it will just be 1. Note that
|
|
7298
|
+
transforms other than translation and scaling are not supported.
|
|
7299
|
+
*/
|
|
7300
|
+
get scaleX() { return this.viewState.scaleX; }
|
|
7301
|
+
/**
|
|
7302
|
+
Provide the CSS transformed scale along the Y axis.
|
|
7303
|
+
*/
|
|
7304
|
+
get scaleY() { return this.viewState.scaleY; }
|
|
7305
|
+
/**
|
|
7271
7306
|
Find the text line or block widget at the given vertical
|
|
7272
7307
|
position (which is interpreted as relative to the [top of the
|
|
7273
7308
|
document](https://codemirror.net/6/docs/ref/#view.EditorView.documentTop)).
|
|
@@ -8058,8 +8093,8 @@ class RectangleMarker {
|
|
|
8058
8093
|
}
|
|
8059
8094
|
function getBase(view) {
|
|
8060
8095
|
let rect = view.scrollDOM.getBoundingClientRect();
|
|
8061
|
-
let left = view.textDirection == Direction.LTR ? rect.left : rect.right - view.scrollDOM.clientWidth;
|
|
8062
|
-
return { left: left - view.scrollDOM.scrollLeft, top: rect.top - view.scrollDOM.scrollTop };
|
|
8096
|
+
let left = view.textDirection == Direction.LTR ? rect.left : rect.right - view.scrollDOM.clientWidth * view.scaleX;
|
|
8097
|
+
return { left: left - view.scrollDOM.scrollLeft * view.scaleX, top: rect.top - view.scrollDOM.scrollTop * view.scaleY };
|
|
8063
8098
|
}
|
|
8064
8099
|
function wrappedLine(view, pos, inside) {
|
|
8065
8100
|
let range = EditorSelection.cursor(pos);
|
|
@@ -8161,6 +8196,8 @@ class LayerView {
|
|
|
8161
8196
|
this.view = view;
|
|
8162
8197
|
this.layer = layer;
|
|
8163
8198
|
this.drawn = [];
|
|
8199
|
+
this.scaleX = 1;
|
|
8200
|
+
this.scaleY = 1;
|
|
8164
8201
|
this.measureReq = { read: this.measure.bind(this), write: this.draw.bind(this) };
|
|
8165
8202
|
this.dom = view.scrollDOM.appendChild(document.createElement("div"));
|
|
8166
8203
|
this.dom.classList.add("cm-layer");
|
|
@@ -8168,6 +8205,7 @@ class LayerView {
|
|
|
8168
8205
|
this.dom.classList.add("cm-layer-above");
|
|
8169
8206
|
if (layer.class)
|
|
8170
8207
|
this.dom.classList.add(layer.class);
|
|
8208
|
+
this.scale();
|
|
8171
8209
|
this.dom.setAttribute("aria-hidden", "true");
|
|
8172
8210
|
this.setOrder(view.state);
|
|
8173
8211
|
view.requestMeasure(this.measureReq);
|
|
@@ -8177,8 +8215,10 @@ class LayerView {
|
|
|
8177
8215
|
update(update) {
|
|
8178
8216
|
if (update.startState.facet(layerOrder) != update.state.facet(layerOrder))
|
|
8179
8217
|
this.setOrder(update.state);
|
|
8180
|
-
if (this.layer.update(update, this.dom) || update.geometryChanged)
|
|
8218
|
+
if (this.layer.update(update, this.dom) || update.geometryChanged) {
|
|
8219
|
+
this.scale();
|
|
8181
8220
|
update.view.requestMeasure(this.measureReq);
|
|
8221
|
+
}
|
|
8182
8222
|
}
|
|
8183
8223
|
setOrder(state) {
|
|
8184
8224
|
let pos = 0, order = state.facet(layerOrder);
|
|
@@ -8189,6 +8229,14 @@ class LayerView {
|
|
|
8189
8229
|
measure() {
|
|
8190
8230
|
return this.layer.markers(this.view);
|
|
8191
8231
|
}
|
|
8232
|
+
scale() {
|
|
8233
|
+
let { scaleX, scaleY } = this.view;
|
|
8234
|
+
if (scaleX != this.scaleX || scaleY != this.scaleY) {
|
|
8235
|
+
this.scaleX = scaleX;
|
|
8236
|
+
this.scaleY = scaleY;
|
|
8237
|
+
this.dom.style.transform = `scale(${1 / scaleX}, ${1 / scaleY})`;
|
|
8238
|
+
}
|
|
8239
|
+
}
|
|
8192
8240
|
draw(markers) {
|
|
8193
8241
|
if (markers.length != this.drawn.length || markers.some((p, i) => !sameMarker(p, this.drawn[i]))) {
|
|
8194
8242
|
let old = this.dom.firstChild, oldI = 0;
|
|
@@ -8358,23 +8406,25 @@ const drawDropCursor = /*@__PURE__*/ViewPlugin.fromClass(class {
|
|
|
8358
8406
|
}
|
|
8359
8407
|
}
|
|
8360
8408
|
readPos() {
|
|
8361
|
-
let
|
|
8362
|
-
let
|
|
8409
|
+
let { view } = this;
|
|
8410
|
+
let pos = view.state.field(dropCursorPos);
|
|
8411
|
+
let rect = pos != null && view.coordsAtPos(pos);
|
|
8363
8412
|
if (!rect)
|
|
8364
8413
|
return null;
|
|
8365
|
-
let outer =
|
|
8414
|
+
let outer = view.scrollDOM.getBoundingClientRect();
|
|
8366
8415
|
return {
|
|
8367
|
-
left: rect.left - outer.left +
|
|
8368
|
-
top: rect.top - outer.top +
|
|
8416
|
+
left: rect.left - outer.left + view.scrollDOM.scrollLeft * view.scaleX,
|
|
8417
|
+
top: rect.top - outer.top + view.scrollDOM.scrollTop * view.scaleY,
|
|
8369
8418
|
height: rect.bottom - rect.top
|
|
8370
8419
|
};
|
|
8371
8420
|
}
|
|
8372
8421
|
drawCursor(pos) {
|
|
8373
8422
|
if (this.cursor) {
|
|
8423
|
+
let { scaleX, scaleY } = this.view;
|
|
8374
8424
|
if (pos) {
|
|
8375
|
-
this.cursor.style.left = pos.left + "px";
|
|
8376
|
-
this.cursor.style.top = pos.top + "px";
|
|
8377
|
-
this.cursor.style.height = pos.height + "px";
|
|
8425
|
+
this.cursor.style.left = pos.left / scaleX + "px";
|
|
8426
|
+
this.cursor.style.top = pos.top / scaleY + "px";
|
|
8427
|
+
this.cursor.style.height = pos.height / scaleY + "px";
|
|
8378
8428
|
}
|
|
8379
8429
|
else {
|
|
8380
8430
|
this.cursor.style.left = "-100000px";
|
|
@@ -8616,7 +8666,9 @@ function specialCharPlugin() {
|
|
|
8616
8666
|
if (code == 9) {
|
|
8617
8667
|
let line = doc.lineAt(pos);
|
|
8618
8668
|
let size = view.state.tabSize, col = countColumn(line.text, size, pos - line.from);
|
|
8619
|
-
return Decoration.replace({
|
|
8669
|
+
return Decoration.replace({
|
|
8670
|
+
widget: new TabWidget((size - (col % size)) * this.view.defaultCharacterWidth / this.view.scaleX)
|
|
8671
|
+
});
|
|
8620
8672
|
}
|
|
8621
8673
|
return this.decorationCache[code] ||
|
|
8622
8674
|
(this.decorationCache[code] = Decoration.replace({ widget: new SpecialCharWidget(conf, code) }));
|
|
@@ -8693,7 +8745,8 @@ const plugin = /*@__PURE__*/ViewPlugin.fromClass(class {
|
|
|
8693
8745
|
}
|
|
8694
8746
|
update(update) {
|
|
8695
8747
|
let { view } = update;
|
|
8696
|
-
let height = view.viewState.editorHeight
|
|
8748
|
+
let height = view.viewState.editorHeight * view.scaleY -
|
|
8749
|
+
view.defaultLineHeight - view.documentPadding.top - 0.5;
|
|
8697
8750
|
if (height >= 0 && height != this.height) {
|
|
8698
8751
|
this.height = height;
|
|
8699
8752
|
this.attrs = { style: `padding-bottom: ${height}px` };
|
|
@@ -8990,6 +9043,7 @@ const tooltipPlugin = /*@__PURE__*/ViewPlugin.fromClass(class {
|
|
|
8990
9043
|
constructor(view) {
|
|
8991
9044
|
this.view = view;
|
|
8992
9045
|
this.inView = true;
|
|
9046
|
+
this.madeAbsolute = false;
|
|
8993
9047
|
this.lastTransaction = 0;
|
|
8994
9048
|
this.measureTimeout = -1;
|
|
8995
9049
|
let config = view.state.facet(tooltipConfig);
|
|
@@ -9041,7 +9095,7 @@ const tooltipPlugin = /*@__PURE__*/ViewPlugin.fromClass(class {
|
|
|
9041
9095
|
this.observeIntersection();
|
|
9042
9096
|
let shouldMeasure = updated || update.geometryChanged;
|
|
9043
9097
|
let newConfig = update.state.facet(tooltipConfig);
|
|
9044
|
-
if (newConfig.position != this.position) {
|
|
9098
|
+
if (newConfig.position != this.position && !this.madeAbsolute) {
|
|
9045
9099
|
this.position = newConfig.position;
|
|
9046
9100
|
for (let t of this.manager.tooltipViews)
|
|
9047
9101
|
t.dom.style.position = this.position;
|
|
@@ -9089,6 +9143,27 @@ const tooltipPlugin = /*@__PURE__*/ViewPlugin.fromClass(class {
|
|
|
9089
9143
|
}
|
|
9090
9144
|
readMeasure() {
|
|
9091
9145
|
let editor = this.view.dom.getBoundingClientRect();
|
|
9146
|
+
let scaleX = 1, scaleY = 1, makeAbsolute = false;
|
|
9147
|
+
if (this.position == "fixed") {
|
|
9148
|
+
let views = this.manager.tooltipViews;
|
|
9149
|
+
// When the dialog's offset parent isn't the body, we are
|
|
9150
|
+
// probably in a transformed container, and should use absolute
|
|
9151
|
+
// positioning instead, since fixed positioning inside a
|
|
9152
|
+
// transform works in a very broken way.
|
|
9153
|
+
makeAbsolute = views.length > 0 && views[0].dom.offsetParent != this.container.ownerDocument.body;
|
|
9154
|
+
}
|
|
9155
|
+
if (makeAbsolute || this.position == "absolute") {
|
|
9156
|
+
if (this.parent) {
|
|
9157
|
+
let rect = this.parent.getBoundingClientRect();
|
|
9158
|
+
if (rect.width && rect.height) {
|
|
9159
|
+
scaleX = rect.width / this.parent.offsetWidth;
|
|
9160
|
+
scaleY = rect.height / this.parent.offsetHeight;
|
|
9161
|
+
}
|
|
9162
|
+
}
|
|
9163
|
+
else {
|
|
9164
|
+
({ scaleX, scaleY } = this.view.viewState);
|
|
9165
|
+
}
|
|
9166
|
+
}
|
|
9092
9167
|
return {
|
|
9093
9168
|
editor,
|
|
9094
9169
|
parent: this.parent ? this.container.getBoundingClientRect() : editor,
|
|
@@ -9098,11 +9173,18 @@ const tooltipPlugin = /*@__PURE__*/ViewPlugin.fromClass(class {
|
|
|
9098
9173
|
}),
|
|
9099
9174
|
size: this.manager.tooltipViews.map(({ dom }) => dom.getBoundingClientRect()),
|
|
9100
9175
|
space: this.view.state.facet(tooltipConfig).tooltipSpace(this.view),
|
|
9176
|
+
scaleX, scaleY, makeAbsolute
|
|
9101
9177
|
};
|
|
9102
9178
|
}
|
|
9103
9179
|
writeMeasure(measured) {
|
|
9104
9180
|
var _a;
|
|
9105
|
-
|
|
9181
|
+
if (measured.makeAbsolute) {
|
|
9182
|
+
this.madeAbsolute = true;
|
|
9183
|
+
this.position = "absolute";
|
|
9184
|
+
for (let t of this.manager.tooltipViews)
|
|
9185
|
+
t.dom.style.position = "absolute";
|
|
9186
|
+
}
|
|
9187
|
+
let { editor, space, scaleX, scaleY } = measured;
|
|
9106
9188
|
let others = [];
|
|
9107
9189
|
for (let i = 0; i < this.manager.tooltips.length; i++) {
|
|
9108
9190
|
let tooltip = this.manager.tooltips[i], tView = this.manager.tooltipViews[i], { dom } = tView;
|
|
@@ -9135,7 +9217,7 @@ const tooltipPlugin = /*@__PURE__*/ViewPlugin.fromClass(class {
|
|
|
9135
9217
|
continue;
|
|
9136
9218
|
}
|
|
9137
9219
|
knownHeight.set(tView, height);
|
|
9138
|
-
dom.style.height = (height = spaceVert) + "px";
|
|
9220
|
+
dom.style.height = (height = spaceVert) / scaleY + "px";
|
|
9139
9221
|
}
|
|
9140
9222
|
else if (dom.style.height) {
|
|
9141
9223
|
dom.style.height = "";
|
|
@@ -9147,15 +9229,17 @@ const tooltipPlugin = /*@__PURE__*/ViewPlugin.fromClass(class {
|
|
|
9147
9229
|
if (r.left < right && r.right > left && r.top < top + height && r.bottom > top)
|
|
9148
9230
|
top = above ? r.top - height - 2 - arrowHeight : r.bottom + arrowHeight + 2;
|
|
9149
9231
|
if (this.position == "absolute") {
|
|
9150
|
-
dom.style.top = (top - measured.parent.top) + "px";
|
|
9151
|
-
dom.style.left = (left - measured.parent.left) + "px";
|
|
9232
|
+
dom.style.top = (top - measured.parent.top) / scaleY + "px";
|
|
9233
|
+
dom.style.left = (left - measured.parent.left) / scaleX + "px";
|
|
9152
9234
|
}
|
|
9153
9235
|
else {
|
|
9154
|
-
dom.style.top = top + "px";
|
|
9155
|
-
dom.style.left = left + "px";
|
|
9236
|
+
dom.style.top = top / scaleY + "px";
|
|
9237
|
+
dom.style.left = left / scaleX + "px";
|
|
9238
|
+
}
|
|
9239
|
+
if (arrow) {
|
|
9240
|
+
let arrowLeft = pos.left + (ltr ? offset.x : -offset.x) - (left + 14 /* Arrow.Offset */ - 7 /* Arrow.Size */);
|
|
9241
|
+
arrow.style.left = arrowLeft / scaleX + "px";
|
|
9156
9242
|
}
|
|
9157
|
-
if (arrow)
|
|
9158
|
-
arrow.style.left = `${pos.left + (ltr ? offset.x : -offset.x) - (left + 14 /* Arrow.Offset */ - 7 /* Arrow.Size */)}px`;
|
|
9159
9243
|
if (tView.overlap !== true)
|
|
9160
9244
|
others.push({ left, top, right, bottom: top + height });
|
|
9161
9245
|
dom.classList.toggle("cm-tooltip-above", above);
|
|
@@ -9757,7 +9841,7 @@ const gutterView = /*@__PURE__*/ViewPlugin.fromClass(class {
|
|
|
9757
9841
|
this.dom = document.createElement("div");
|
|
9758
9842
|
this.dom.className = "cm-gutters";
|
|
9759
9843
|
this.dom.setAttribute("aria-hidden", "true");
|
|
9760
|
-
this.dom.style.minHeight = this.view.contentHeight + "px";
|
|
9844
|
+
this.dom.style.minHeight = (this.view.contentHeight / this.view.scaleY) + "px";
|
|
9761
9845
|
this.gutters = view.state.facet(activeGutters).map(conf => new SingleGutterView(view, conf));
|
|
9762
9846
|
for (let gutter of this.gutters)
|
|
9763
9847
|
this.dom.appendChild(gutter.dom);
|
|
@@ -9818,6 +9902,10 @@ const gutterView = /*@__PURE__*/ViewPlugin.fromClass(class {
|
|
|
9818
9902
|
for (let cx of contexts)
|
|
9819
9903
|
cx.line(this.view, line, classSet);
|
|
9820
9904
|
}
|
|
9905
|
+
else if (line.widget) {
|
|
9906
|
+
for (let cx of contexts)
|
|
9907
|
+
cx.widget(this.view, line);
|
|
9908
|
+
}
|
|
9821
9909
|
}
|
|
9822
9910
|
for (let cx of contexts)
|
|
9823
9911
|
cx.finish();
|
|
@@ -9867,7 +9955,9 @@ const gutterView = /*@__PURE__*/ViewPlugin.fromClass(class {
|
|
|
9867
9955
|
let value = view.plugin(plugin);
|
|
9868
9956
|
if (!value || value.gutters.length == 0 || !value.fixed)
|
|
9869
9957
|
return null;
|
|
9870
|
-
return view.textDirection == Direction.LTR
|
|
9958
|
+
return view.textDirection == Direction.LTR
|
|
9959
|
+
? { left: value.dom.offsetWidth * view.scaleX }
|
|
9960
|
+
: { right: value.dom.offsetWidth * view.scaleX };
|
|
9871
9961
|
})
|
|
9872
9962
|
});
|
|
9873
9963
|
function asArray(val) { return (Array.isArray(val) ? val : [val]); }
|
|
@@ -9984,10 +10074,12 @@ class GutterElement {
|
|
|
9984
10074
|
this.update(view, height, above, markers);
|
|
9985
10075
|
}
|
|
9986
10076
|
update(view, height, above, markers) {
|
|
9987
|
-
if (this.height != height)
|
|
9988
|
-
this.
|
|
10077
|
+
if (this.height != height) {
|
|
10078
|
+
this.height = height;
|
|
10079
|
+
this.dom.style.height = height / view.scaleY + "px";
|
|
10080
|
+
}
|
|
9989
10081
|
if (this.above != above)
|
|
9990
|
-
this.dom.style.marginTop = (this.above = above) ? above + "px" : "";
|
|
10082
|
+
this.dom.style.marginTop = (this.above = above) ? above / view.scaleY + "px" : "";
|
|
9991
10083
|
if (!sameMarkers(this.markers, markers))
|
|
9992
10084
|
this.setMarkers(view, markers);
|
|
9993
10085
|
}
|