@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.cjs
CHANGED
|
@@ -101,6 +101,7 @@ function scrollRectIntoView(dom, rect, side, x, y, xMargin, yMargin, ltr) {
|
|
|
101
101
|
for (let cur = dom, stop = false; cur && !stop;) {
|
|
102
102
|
if (cur.nodeType == 1) { // Element
|
|
103
103
|
let bounding, top = cur == doc.body;
|
|
104
|
+
let scaleX = 1, scaleY = 1;
|
|
104
105
|
if (top) {
|
|
105
106
|
bounding = windowRect(win);
|
|
106
107
|
}
|
|
@@ -112,9 +113,11 @@ function scrollRectIntoView(dom, rect, side, x, y, xMargin, yMargin, ltr) {
|
|
|
112
113
|
continue;
|
|
113
114
|
}
|
|
114
115
|
let rect = cur.getBoundingClientRect();
|
|
116
|
+
scaleX = rect.width / cur.offsetWidth;
|
|
117
|
+
scaleY = rect.height / cur.offsetHeight;
|
|
115
118
|
// Make sure scrollbar width isn't included in the rectangle
|
|
116
|
-
bounding = { left: rect.left, right: rect.left + cur.clientWidth,
|
|
117
|
-
top: rect.top, bottom: rect.top + cur.clientHeight };
|
|
119
|
+
bounding = { left: rect.left, right: rect.left + cur.clientWidth * scaleX,
|
|
120
|
+
top: rect.top, bottom: rect.top + cur.clientHeight * scaleY };
|
|
118
121
|
}
|
|
119
122
|
let moveX = 0, moveY = 0;
|
|
120
123
|
if (y == "nearest") {
|
|
@@ -162,13 +165,13 @@ function scrollRectIntoView(dom, rect, side, x, y, xMargin, yMargin, ltr) {
|
|
|
162
165
|
let movedX = 0, movedY = 0;
|
|
163
166
|
if (moveY) {
|
|
164
167
|
let start = cur.scrollTop;
|
|
165
|
-
cur.scrollTop += moveY;
|
|
166
|
-
movedY = cur.scrollTop - start;
|
|
168
|
+
cur.scrollTop += moveY / scaleY;
|
|
169
|
+
movedY = (cur.scrollTop - start) * scaleY;
|
|
167
170
|
}
|
|
168
171
|
if (moveX) {
|
|
169
172
|
let start = cur.scrollLeft;
|
|
170
|
-
cur.scrollLeft += moveX;
|
|
171
|
-
movedX = cur.scrollLeft - start;
|
|
173
|
+
cur.scrollLeft += moveX / scaleX;
|
|
174
|
+
movedX = (cur.scrollLeft - start) * scaleX;
|
|
172
175
|
}
|
|
173
176
|
rect = { left: rect.left - movedX, top: rect.top - movedY,
|
|
174
177
|
right: rect.right - movedX, bottom: rect.bottom - movedY };
|
|
@@ -481,6 +484,8 @@ class ContentView {
|
|
|
481
484
|
}
|
|
482
485
|
}
|
|
483
486
|
setDOM(dom) {
|
|
487
|
+
if (this.dom == dom)
|
|
488
|
+
return;
|
|
484
489
|
if (this.dom)
|
|
485
490
|
this.dom.cmView = null;
|
|
486
491
|
this.dom = dom;
|
|
@@ -653,113 +658,6 @@ function mergeChildrenInto(parent, from, to, insert, openStart, openEnd) {
|
|
|
653
658
|
replaceRange(parent, fromI, fromOff, toI, toOff, insert, 0, openStart, openEnd);
|
|
654
659
|
}
|
|
655
660
|
|
|
656
|
-
const LineBreakPlaceholder = "\uffff";
|
|
657
|
-
class DOMReader {
|
|
658
|
-
constructor(points, state$1) {
|
|
659
|
-
this.points = points;
|
|
660
|
-
this.text = "";
|
|
661
|
-
this.lineSeparator = state$1.facet(state.EditorState.lineSeparator);
|
|
662
|
-
}
|
|
663
|
-
append(text) {
|
|
664
|
-
this.text += text;
|
|
665
|
-
}
|
|
666
|
-
lineBreak() {
|
|
667
|
-
this.text += LineBreakPlaceholder;
|
|
668
|
-
}
|
|
669
|
-
readRange(start, end) {
|
|
670
|
-
if (!start)
|
|
671
|
-
return this;
|
|
672
|
-
let parent = start.parentNode;
|
|
673
|
-
for (let cur = start;;) {
|
|
674
|
-
this.findPointBefore(parent, cur);
|
|
675
|
-
let oldLen = this.text.length;
|
|
676
|
-
this.readNode(cur);
|
|
677
|
-
let next = cur.nextSibling;
|
|
678
|
-
if (next == end)
|
|
679
|
-
break;
|
|
680
|
-
let view = ContentView.get(cur), nextView = ContentView.get(next);
|
|
681
|
-
if (view && nextView ? view.breakAfter :
|
|
682
|
-
(view ? view.breakAfter : isBlockElement(cur)) ||
|
|
683
|
-
(isBlockElement(next) && (cur.nodeName != "BR" || cur.cmIgnore) && this.text.length > oldLen))
|
|
684
|
-
this.lineBreak();
|
|
685
|
-
cur = next;
|
|
686
|
-
}
|
|
687
|
-
this.findPointBefore(parent, end);
|
|
688
|
-
return this;
|
|
689
|
-
}
|
|
690
|
-
readTextNode(node) {
|
|
691
|
-
let text = node.nodeValue;
|
|
692
|
-
for (let point of this.points)
|
|
693
|
-
if (point.node == node)
|
|
694
|
-
point.pos = this.text.length + Math.min(point.offset, text.length);
|
|
695
|
-
for (let off = 0, re = this.lineSeparator ? null : /\r\n?|\n/g;;) {
|
|
696
|
-
let nextBreak = -1, breakSize = 1, m;
|
|
697
|
-
if (this.lineSeparator) {
|
|
698
|
-
nextBreak = text.indexOf(this.lineSeparator, off);
|
|
699
|
-
breakSize = this.lineSeparator.length;
|
|
700
|
-
}
|
|
701
|
-
else if (m = re.exec(text)) {
|
|
702
|
-
nextBreak = m.index;
|
|
703
|
-
breakSize = m[0].length;
|
|
704
|
-
}
|
|
705
|
-
this.append(text.slice(off, nextBreak < 0 ? text.length : nextBreak));
|
|
706
|
-
if (nextBreak < 0)
|
|
707
|
-
break;
|
|
708
|
-
this.lineBreak();
|
|
709
|
-
if (breakSize > 1)
|
|
710
|
-
for (let point of this.points)
|
|
711
|
-
if (point.node == node && point.pos > this.text.length)
|
|
712
|
-
point.pos -= breakSize - 1;
|
|
713
|
-
off = nextBreak + breakSize;
|
|
714
|
-
}
|
|
715
|
-
}
|
|
716
|
-
readNode(node) {
|
|
717
|
-
if (node.cmIgnore)
|
|
718
|
-
return;
|
|
719
|
-
let view = ContentView.get(node);
|
|
720
|
-
let fromView = view && view.overrideDOMText;
|
|
721
|
-
if (fromView != null) {
|
|
722
|
-
this.findPointInside(node, fromView.length);
|
|
723
|
-
for (let i = fromView.iter(); !i.next().done;) {
|
|
724
|
-
if (i.lineBreak)
|
|
725
|
-
this.lineBreak();
|
|
726
|
-
else
|
|
727
|
-
this.append(i.value);
|
|
728
|
-
}
|
|
729
|
-
}
|
|
730
|
-
else if (node.nodeType == 3) {
|
|
731
|
-
this.readTextNode(node);
|
|
732
|
-
}
|
|
733
|
-
else if (node.nodeName == "BR") {
|
|
734
|
-
if (node.nextSibling)
|
|
735
|
-
this.lineBreak();
|
|
736
|
-
}
|
|
737
|
-
else if (node.nodeType == 1) {
|
|
738
|
-
this.readRange(node.firstChild, null);
|
|
739
|
-
}
|
|
740
|
-
}
|
|
741
|
-
findPointBefore(node, next) {
|
|
742
|
-
for (let point of this.points)
|
|
743
|
-
if (point.node == node && node.childNodes[point.offset] == next)
|
|
744
|
-
point.pos = this.text.length;
|
|
745
|
-
}
|
|
746
|
-
findPointInside(node, maxLen) {
|
|
747
|
-
for (let point of this.points)
|
|
748
|
-
if (node.nodeType == 3 ? point.node == node : node.contains(point.node))
|
|
749
|
-
point.pos = this.text.length + Math.min(maxLen, point.offset);
|
|
750
|
-
}
|
|
751
|
-
}
|
|
752
|
-
function isBlockElement(node) {
|
|
753
|
-
return node.nodeType == 1 && /^(DIV|P|LI|UL|OL|BLOCKQUOTE|DD|DT|H\d|SECTION|PRE)$/.test(node.nodeName);
|
|
754
|
-
}
|
|
755
|
-
class DOMPoint {
|
|
756
|
-
constructor(node, offset) {
|
|
757
|
-
this.node = node;
|
|
758
|
-
this.offset = offset;
|
|
759
|
-
this.pos = -1;
|
|
760
|
-
}
|
|
761
|
-
}
|
|
762
|
-
|
|
763
661
|
let nav = typeof navigator != "undefined" ? navigator : { userAgent: "", vendor: "", platform: "" };
|
|
764
662
|
let doc = typeof document != "undefined" ? document : { documentElement: { style: {} } };
|
|
765
663
|
const ie_edge = /Edge\/(\d+)/.exec(nav.userAgent);
|
|
@@ -2703,6 +2601,7 @@ class DocView extends ContentView {
|
|
|
2703
2601
|
this.view = view;
|
|
2704
2602
|
this.decorations = [];
|
|
2705
2603
|
this.dynamicDecorationMap = [];
|
|
2604
|
+
this.domChanged = null;
|
|
2706
2605
|
this.hasComposition = null;
|
|
2707
2606
|
this.markedForComposition = new Set;
|
|
2708
2607
|
// Track a minimum width for the editor. When measuring sizes in
|
|
@@ -2731,6 +2630,7 @@ class DocView extends ContentView {
|
|
|
2731
2630
|
}
|
|
2732
2631
|
// Update the document view to a given state.
|
|
2733
2632
|
update(update) {
|
|
2633
|
+
var _a;
|
|
2734
2634
|
let changedRanges = update.changedRanges;
|
|
2735
2635
|
if (this.minWidth > 0 && changedRanges.length) {
|
|
2736
2636
|
if (!changedRanges.every(({ fromA, toA }) => toA < this.minWidthFrom || fromA > this.minWidthTo)) {
|
|
@@ -2741,7 +2641,15 @@ class DocView extends ContentView {
|
|
|
2741
2641
|
this.minWidthTo = update.changes.mapPos(this.minWidthTo, 1);
|
|
2742
2642
|
}
|
|
2743
2643
|
}
|
|
2744
|
-
let
|
|
2644
|
+
let readCompositionAt = -1;
|
|
2645
|
+
if (this.view.inputState.composing >= 0) {
|
|
2646
|
+
if ((_a = this.domChanged) === null || _a === void 0 ? void 0 : _a.newSel)
|
|
2647
|
+
readCompositionAt = this.domChanged.newSel.head;
|
|
2648
|
+
else if (!touchesComposition(update.changes, this.hasComposition) && !update.selectionSet)
|
|
2649
|
+
readCompositionAt = update.state.selection.main.head;
|
|
2650
|
+
}
|
|
2651
|
+
let composition = readCompositionAt > -1 ? findCompositionRange(this.view, update.changes, readCompositionAt) : null;
|
|
2652
|
+
this.domChanged = null;
|
|
2745
2653
|
if (this.hasComposition) {
|
|
2746
2654
|
this.markedForComposition.clear();
|
|
2747
2655
|
let { from, to } = this.hasComposition;
|
|
@@ -2781,7 +2689,7 @@ class DocView extends ContentView {
|
|
|
2781
2689
|
// messes with the scroll position during DOM mutation (though
|
|
2782
2690
|
// no relayout is triggered and I cannot imagine how it can
|
|
2783
2691
|
// recompute the scroll position without a layout)
|
|
2784
|
-
this.dom.style.height = this.view.viewState.contentHeight + "px";
|
|
2692
|
+
this.dom.style.height = this.view.viewState.contentHeight / this.view.scaleY + "px";
|
|
2785
2693
|
this.dom.style.flexBasis = this.minWidth ? this.minWidth + "px" : "";
|
|
2786
2694
|
// Chrome will sometimes, when DOM mutations occur directly
|
|
2787
2695
|
// around the selection, get confused and report a different
|
|
@@ -2853,14 +2761,12 @@ class DocView extends ContentView {
|
|
|
2853
2761
|
}
|
|
2854
2762
|
fixCompositionDOM(composition) {
|
|
2855
2763
|
let fix = (dom, cView) => {
|
|
2856
|
-
cView.flags |= 8 /* ViewFlag.Composition
|
|
2764
|
+
cView.flags |= 8 /* ViewFlag.Composition */ | (cView.children.some(c => c.flags & 7 /* ViewFlag.Dirty */) ? 1 /* ViewFlag.ChildDirty */ : 0);
|
|
2857
2765
|
this.markedForComposition.add(cView);
|
|
2858
2766
|
let prev = ContentView.get(dom);
|
|
2859
|
-
if (prev != cView)
|
|
2860
|
-
|
|
2861
|
-
|
|
2862
|
-
cView.setDOM(dom);
|
|
2863
|
-
}
|
|
2767
|
+
if (prev && prev != cView)
|
|
2768
|
+
prev.dom = null;
|
|
2769
|
+
cView.setDOM(dom);
|
|
2864
2770
|
};
|
|
2865
2771
|
let pos = this.childPos(composition.range.fromB, 1);
|
|
2866
2772
|
let cView = this.children[pos.i];
|
|
@@ -2883,9 +2789,8 @@ class DocView extends ContentView {
|
|
|
2883
2789
|
let force = this.forceSelection;
|
|
2884
2790
|
this.forceSelection = false;
|
|
2885
2791
|
let main = this.view.state.selection.main;
|
|
2886
|
-
|
|
2887
|
-
let
|
|
2888
|
-
let head = main.empty ? anchor : this.domAtPos(main.head);
|
|
2792
|
+
let anchor = this.moveToLine(this.domAtPos(main.anchor));
|
|
2793
|
+
let head = main.empty ? anchor : this.moveToLine(this.domAtPos(main.head));
|
|
2889
2794
|
// Always reset on Firefox when next to an uneditable node to
|
|
2890
2795
|
// avoid invisible cursor bugs (#111)
|
|
2891
2796
|
if (browser.gecko && main.empty && !this.hasComposition && betweenUneditable(anchor)) {
|
|
@@ -2918,12 +2823,12 @@ class DocView extends ContentView {
|
|
|
2918
2823
|
if (nextTo && nextTo != (1 /* NextTo.Before */ | 2 /* NextTo.After */)) {
|
|
2919
2824
|
let text = nearbyTextNode(anchor.node, anchor.offset, nextTo == 1 /* NextTo.Before */ ? 1 : -1);
|
|
2920
2825
|
if (text)
|
|
2921
|
-
anchor = new DOMPos(text,
|
|
2826
|
+
anchor = new DOMPos(text.node, text.offset);
|
|
2922
2827
|
}
|
|
2923
2828
|
}
|
|
2924
2829
|
rawSel.collapse(anchor.node, anchor.offset);
|
|
2925
|
-
if (main.bidiLevel != null &&
|
|
2926
|
-
|
|
2830
|
+
if (main.bidiLevel != null && rawSel.caretBidiLevel !== undefined)
|
|
2831
|
+
rawSel.caretBidiLevel = main.bidiLevel;
|
|
2927
2832
|
}
|
|
2928
2833
|
else if (rawSel.extend) {
|
|
2929
2834
|
// Selection.extend can be used to create an 'inverted' selection
|
|
@@ -2986,6 +2891,26 @@ class DocView extends ContentView {
|
|
|
2986
2891
|
if (view.docView.posFromDOM(newRange.anchorNode, newRange.anchorOffset) != cursor.from)
|
|
2987
2892
|
sel.collapse(anchorNode, anchorOffset);
|
|
2988
2893
|
}
|
|
2894
|
+
// If a position is in/near a block widget, move it to a nearby text
|
|
2895
|
+
// line, since we don't want the cursor inside a block widget.
|
|
2896
|
+
moveToLine(pos) {
|
|
2897
|
+
// Block widgets will return positions before/after them, which
|
|
2898
|
+
// are thus directly in the document DOM element.
|
|
2899
|
+
let dom = this.dom, newPos;
|
|
2900
|
+
if (pos.node != dom)
|
|
2901
|
+
return pos;
|
|
2902
|
+
for (let i = pos.offset; !newPos && i < dom.childNodes.length; i++) {
|
|
2903
|
+
let view = ContentView.get(dom.childNodes[i]);
|
|
2904
|
+
if (view instanceof LineView)
|
|
2905
|
+
newPos = view.domAtPos(0);
|
|
2906
|
+
}
|
|
2907
|
+
for (let i = pos.offset - 1; !newPos && i >= 0; i--) {
|
|
2908
|
+
let view = ContentView.get(dom.childNodes[i]);
|
|
2909
|
+
if (view instanceof LineView)
|
|
2910
|
+
newPos = view.domAtPos(view.length);
|
|
2911
|
+
}
|
|
2912
|
+
return newPos ? new DOMPos(newPos.node, newPos.offset, true) : pos;
|
|
2913
|
+
}
|
|
2989
2914
|
nearest(dom) {
|
|
2990
2915
|
for (let cur = dom; cur;) {
|
|
2991
2916
|
let domView = ContentView.get(cur);
|
|
@@ -3119,7 +3044,7 @@ class DocView extends ContentView {
|
|
|
3119
3044
|
let next = i == vs.viewports.length ? null : vs.viewports[i];
|
|
3120
3045
|
let end = next ? next.from - 1 : this.length;
|
|
3121
3046
|
if (end > pos) {
|
|
3122
|
-
let height = vs.lineBlockAt(end).bottom - vs.lineBlockAt(pos).top;
|
|
3047
|
+
let height = (vs.lineBlockAt(end).bottom - vs.lineBlockAt(pos).top) / this.view.scaleY;
|
|
3123
3048
|
deco.push(Decoration.replace({
|
|
3124
3049
|
widget: new BlockGapWidget(height),
|
|
3125
3050
|
block: true,
|
|
@@ -3184,74 +3109,27 @@ class BlockGapWidget extends WidgetType {
|
|
|
3184
3109
|
}
|
|
3185
3110
|
get estimatedHeight() { return this.height; }
|
|
3186
3111
|
}
|
|
3187
|
-
function findCompositionNode(view,
|
|
3112
|
+
function findCompositionNode(view, headPos) {
|
|
3188
3113
|
let sel = view.observer.selectionRange;
|
|
3189
3114
|
let textNode = sel.focusNode && nearbyTextNode(sel.focusNode, sel.focusOffset, 0);
|
|
3190
3115
|
if (!textNode)
|
|
3191
3116
|
return null;
|
|
3192
|
-
let
|
|
3193
|
-
|
|
3194
|
-
if (cView instanceof TextView) {
|
|
3195
|
-
from = cView.posAtStart;
|
|
3196
|
-
to = from + cView.length;
|
|
3197
|
-
}
|
|
3198
|
-
else {
|
|
3199
|
-
let oldLen = Math.max(0, textNode.nodeValue.length - dLen);
|
|
3200
|
-
up: for (let offset = 0, node = textNode;;) {
|
|
3201
|
-
for (let sibling = node.previousSibling, cView; sibling; sibling = sibling.previousSibling) {
|
|
3202
|
-
if (cView = ContentView.get(sibling)) {
|
|
3203
|
-
to = cView.posAtEnd + offset;
|
|
3204
|
-
from = Math.max(0, to - oldLen);
|
|
3205
|
-
break up;
|
|
3206
|
-
}
|
|
3207
|
-
let reader = new DOMReader([], view.state);
|
|
3208
|
-
reader.readNode(sibling);
|
|
3209
|
-
if (reader.text.indexOf(LineBreakPlaceholder) > -1)
|
|
3210
|
-
return null;
|
|
3211
|
-
offset += reader.text.length;
|
|
3212
|
-
}
|
|
3213
|
-
node = node.parentNode;
|
|
3214
|
-
if (!node)
|
|
3215
|
-
return null;
|
|
3216
|
-
let parentView = ContentView.get(node);
|
|
3217
|
-
if (parentView) {
|
|
3218
|
-
from = parentView.posAtStart + offset;
|
|
3219
|
-
to = from + oldLen;
|
|
3220
|
-
break;
|
|
3221
|
-
}
|
|
3222
|
-
}
|
|
3223
|
-
}
|
|
3224
|
-
return { from, to: to, node: textNode };
|
|
3117
|
+
let from = headPos - textNode.offset;
|
|
3118
|
+
return { from, to: from + textNode.node.nodeValue.length, node: textNode.node };
|
|
3225
3119
|
}
|
|
3226
|
-
function findCompositionRange(view, changes) {
|
|
3227
|
-
let found = findCompositionNode(view,
|
|
3120
|
+
function findCompositionRange(view, changes, headPos) {
|
|
3121
|
+
let found = findCompositionNode(view, headPos);
|
|
3228
3122
|
if (!found)
|
|
3229
3123
|
return null;
|
|
3230
|
-
let {
|
|
3231
|
-
let fromB = changes.mapPos(fromA, -1), toB = changes.mapPos(toA, 1);
|
|
3232
|
-
let text = textNode.nodeValue;
|
|
3124
|
+
let { node: textNode, from, to } = found, text = textNode.nodeValue;
|
|
3233
3125
|
// Don't try to preserve multi-line compositions
|
|
3234
3126
|
if (/[\n\r]/.test(text))
|
|
3235
3127
|
return null;
|
|
3236
|
-
if (
|
|
3237
|
-
// If there is a length mismatch, see if mapping non-inclusively helps
|
|
3238
|
-
let fromB2 = changes.mapPos(fromA, 1), toB2 = changes.mapPos(toA, -1);
|
|
3239
|
-
if (toB2 - fromB2 == text.length)
|
|
3240
|
-
fromB = fromB2, toB = toB2;
|
|
3241
|
-
// See if we can find an instance of the text at either side
|
|
3242
|
-
else if (view.state.doc.sliceString(toB - text.length, toB) == text)
|
|
3243
|
-
fromB = toB - text.length;
|
|
3244
|
-
else if (view.state.doc.sliceString(fromB, fromB + text.length) == text)
|
|
3245
|
-
toB = fromB + text.length;
|
|
3246
|
-
// Not found
|
|
3247
|
-
else
|
|
3248
|
-
return null;
|
|
3249
|
-
}
|
|
3250
|
-
let { main } = view.state.selection;
|
|
3251
|
-
if (view.state.doc.sliceString(fromB, toB) != text || fromB > main.head || toB < main.head)
|
|
3128
|
+
if (view.state.doc.sliceString(found.from, found.to) != text)
|
|
3252
3129
|
return null;
|
|
3130
|
+
let inv = changes.invertedDesc;
|
|
3131
|
+
let range = new ChangedRange(inv.mapPos(from), inv.mapPos(to), from, to);
|
|
3253
3132
|
let marks = [];
|
|
3254
|
-
let range = new ChangedRange(fromA, toA, fromB, toB);
|
|
3255
3133
|
for (let parent = textNode.parentNode;; parent = parent.parentNode) {
|
|
3256
3134
|
let parentView = ContentView.get(parent);
|
|
3257
3135
|
if (parentView instanceof MarkView)
|
|
@@ -3272,7 +3150,7 @@ function nearbyTextNode(startNode, startOffset, side) {
|
|
|
3272
3150
|
if (side <= 0)
|
|
3273
3151
|
for (let node = startNode, offset = startOffset;;) {
|
|
3274
3152
|
if (node.nodeType == 3)
|
|
3275
|
-
return node;
|
|
3153
|
+
return { node: node, offset: offset };
|
|
3276
3154
|
if (node.nodeType == 1 && offset > 0) {
|
|
3277
3155
|
node = node.childNodes[offset - 1];
|
|
3278
3156
|
offset = maxOffset(node);
|
|
@@ -3284,7 +3162,7 @@ function nearbyTextNode(startNode, startOffset, side) {
|
|
|
3284
3162
|
if (side >= 0)
|
|
3285
3163
|
for (let node = startNode, offset = startOffset;;) {
|
|
3286
3164
|
if (node.nodeType == 3)
|
|
3287
|
-
return node;
|
|
3165
|
+
return { node: node, offset: offset };
|
|
3288
3166
|
if (node.nodeType == 1 && offset < node.childNodes.length && side >= 0) {
|
|
3289
3167
|
node = node.childNodes[offset];
|
|
3290
3168
|
offset = 0;
|
|
@@ -3321,6 +3199,15 @@ function inUneditable(node, inside) {
|
|
|
3321
3199
|
}
|
|
3322
3200
|
return false;
|
|
3323
3201
|
}
|
|
3202
|
+
function touchesComposition(changes, composition) {
|
|
3203
|
+
let touched = false;
|
|
3204
|
+
if (composition)
|
|
3205
|
+
changes.iterChangedRanges((from, to) => {
|
|
3206
|
+
if (from < composition.to && to > composition.from)
|
|
3207
|
+
touched = true;
|
|
3208
|
+
});
|
|
3209
|
+
return touched;
|
|
3210
|
+
}
|
|
3324
3211
|
|
|
3325
3212
|
function groupAt(state$1, pos, bias = 1) {
|
|
3326
3213
|
let categorize = state$1.charCategorizer(pos);
|
|
@@ -5276,8 +5163,10 @@ class LineGap {
|
|
|
5276
5163
|
}
|
|
5277
5164
|
return true;
|
|
5278
5165
|
}
|
|
5279
|
-
draw(wrapping) {
|
|
5280
|
-
return Decoration.replace({
|
|
5166
|
+
draw(viewState, wrapping) {
|
|
5167
|
+
return Decoration.replace({
|
|
5168
|
+
widget: new LineGapWidget(this.size * (wrapping ? viewState.scaleY : viewState.scaleX), wrapping)
|
|
5169
|
+
}).range(this.from, this.to);
|
|
5281
5170
|
}
|
|
5282
5171
|
}
|
|
5283
5172
|
class LineGapWidget extends WidgetType {
|
|
@@ -5307,14 +5196,18 @@ class ViewState {
|
|
|
5307
5196
|
// These are contentDOM-local coordinates
|
|
5308
5197
|
this.pixelViewport = { left: 0, right: window.innerWidth, top: 0, bottom: 0 };
|
|
5309
5198
|
this.inView = true;
|
|
5310
|
-
this.paddingTop = 0;
|
|
5311
|
-
this.paddingBottom = 0;
|
|
5312
|
-
this.contentDOMWidth = 0;
|
|
5313
|
-
this.contentDOMHeight = 0;
|
|
5314
|
-
this.editorHeight = 0;
|
|
5315
|
-
this.editorWidth = 0;
|
|
5316
|
-
this.scrollTop = 0;
|
|
5199
|
+
this.paddingTop = 0; // Padding above the document, scaled
|
|
5200
|
+
this.paddingBottom = 0; // Padding below the document, scaled
|
|
5201
|
+
this.contentDOMWidth = 0; // contentDOM.getBoundingClientRect().width
|
|
5202
|
+
this.contentDOMHeight = 0; // contentDOM.getBoundingClientRect().height
|
|
5203
|
+
this.editorHeight = 0; // scrollDOM.clientHeight, unscaled
|
|
5204
|
+
this.editorWidth = 0; // scrollDOM.clientWidth, unscaled
|
|
5205
|
+
this.scrollTop = 0; // Last seen scrollDOM.scrollTop, scaled
|
|
5317
5206
|
this.scrolledToBottom = true;
|
|
5207
|
+
// The CSS-transformation scale of the editor (transformed size /
|
|
5208
|
+
// concrete size)
|
|
5209
|
+
this.scaleX = 1;
|
|
5210
|
+
this.scaleY = 1;
|
|
5318
5211
|
// The vertical position (document-relative) to which to anchor the
|
|
5319
5212
|
// scroll position. -1 means anchor to the end of the document.
|
|
5320
5213
|
this.scrollAnchorPos = 0;
|
|
@@ -5348,7 +5241,7 @@ class ViewState {
|
|
|
5348
5241
|
this.updateViewportLines();
|
|
5349
5242
|
this.updateForViewport();
|
|
5350
5243
|
this.lineGaps = this.ensureLineGaps([]);
|
|
5351
|
-
this.lineGapDeco = Decoration.set(this.lineGaps.map(gap => gap.draw(false)));
|
|
5244
|
+
this.lineGapDeco = Decoration.set(this.lineGaps.map(gap => gap.draw(this, false)));
|
|
5352
5245
|
this.computeVisibleRanges();
|
|
5353
5246
|
}
|
|
5354
5247
|
updateForViewport() {
|
|
@@ -5420,8 +5313,23 @@ class ViewState {
|
|
|
5420
5313
|
this.contentDOMHeight = domRect.height;
|
|
5421
5314
|
this.mustMeasureContent = false;
|
|
5422
5315
|
let result = 0, bias = 0;
|
|
5316
|
+
if (domRect.width && domRect.height) {
|
|
5317
|
+
let scaleX = domRect.width / dom.offsetWidth;
|
|
5318
|
+
let scaleY = domRect.height / dom.offsetHeight;
|
|
5319
|
+
if (scaleX > 0.995 && scaleX < 1.005)
|
|
5320
|
+
scaleX = 1;
|
|
5321
|
+
if (scaleY > 0.995 && scaleY < 1.005)
|
|
5322
|
+
scaleY = 1;
|
|
5323
|
+
if (this.scaleX != scaleX || this.scaleY != scaleY) {
|
|
5324
|
+
this.scaleX = scaleX;
|
|
5325
|
+
this.scaleY = scaleY;
|
|
5326
|
+
result |= 8 /* UpdateFlag.Geometry */;
|
|
5327
|
+
refresh = measureContent = true;
|
|
5328
|
+
}
|
|
5329
|
+
}
|
|
5423
5330
|
// Vertical padding
|
|
5424
|
-
let paddingTop = parseInt(style.paddingTop) || 0
|
|
5331
|
+
let paddingTop = (parseInt(style.paddingTop) || 0) * this.scaleY;
|
|
5332
|
+
let paddingBottom = (parseInt(style.paddingBottom) || 0) * this.scaleY;
|
|
5425
5333
|
if (this.paddingTop != paddingTop || this.paddingBottom != paddingBottom) {
|
|
5426
5334
|
this.paddingTop = paddingTop;
|
|
5427
5335
|
this.paddingBottom = paddingBottom;
|
|
@@ -5433,9 +5341,10 @@ class ViewState {
|
|
|
5433
5341
|
this.editorWidth = view.scrollDOM.clientWidth;
|
|
5434
5342
|
result |= 8 /* UpdateFlag.Geometry */;
|
|
5435
5343
|
}
|
|
5436
|
-
|
|
5344
|
+
let scrollTop = view.scrollDOM.scrollTop * this.scaleY;
|
|
5345
|
+
if (this.scrollTop != scrollTop) {
|
|
5437
5346
|
this.scrollAnchorHeight = -1;
|
|
5438
|
-
this.scrollTop =
|
|
5347
|
+
this.scrollTop = scrollTop;
|
|
5439
5348
|
}
|
|
5440
5349
|
this.scrolledToBottom = isScrolledToBottom(view.scrollDOM);
|
|
5441
5350
|
// Pixel viewport
|
|
@@ -5656,7 +5565,7 @@ class ViewState {
|
|
|
5656
5565
|
updateLineGaps(gaps) {
|
|
5657
5566
|
if (!LineGap.same(gaps, this.lineGaps)) {
|
|
5658
5567
|
this.lineGaps = gaps;
|
|
5659
|
-
this.lineGapDeco = Decoration.set(gaps.map(gap => gap.draw(this.heightOracle.lineWrapping)));
|
|
5568
|
+
this.lineGapDeco = Decoration.set(gaps.map(gap => gap.draw(this, this.heightOracle.lineWrapping)));
|
|
5660
5569
|
}
|
|
5661
5570
|
}
|
|
5662
5571
|
computeVisibleRanges() {
|
|
@@ -6057,6 +5966,113 @@ const baseTheme$1 = buildTheme("." + baseThemeID, {
|
|
|
6057
5966
|
}
|
|
6058
5967
|
}, lightDarkIDs);
|
|
6059
5968
|
|
|
5969
|
+
const LineBreakPlaceholder = "\uffff";
|
|
5970
|
+
class DOMReader {
|
|
5971
|
+
constructor(points, state$1) {
|
|
5972
|
+
this.points = points;
|
|
5973
|
+
this.text = "";
|
|
5974
|
+
this.lineSeparator = state$1.facet(state.EditorState.lineSeparator);
|
|
5975
|
+
}
|
|
5976
|
+
append(text) {
|
|
5977
|
+
this.text += text;
|
|
5978
|
+
}
|
|
5979
|
+
lineBreak() {
|
|
5980
|
+
this.text += LineBreakPlaceholder;
|
|
5981
|
+
}
|
|
5982
|
+
readRange(start, end) {
|
|
5983
|
+
if (!start)
|
|
5984
|
+
return this;
|
|
5985
|
+
let parent = start.parentNode;
|
|
5986
|
+
for (let cur = start;;) {
|
|
5987
|
+
this.findPointBefore(parent, cur);
|
|
5988
|
+
let oldLen = this.text.length;
|
|
5989
|
+
this.readNode(cur);
|
|
5990
|
+
let next = cur.nextSibling;
|
|
5991
|
+
if (next == end)
|
|
5992
|
+
break;
|
|
5993
|
+
let view = ContentView.get(cur), nextView = ContentView.get(next);
|
|
5994
|
+
if (view && nextView ? view.breakAfter :
|
|
5995
|
+
(view ? view.breakAfter : isBlockElement(cur)) ||
|
|
5996
|
+
(isBlockElement(next) && (cur.nodeName != "BR" || cur.cmIgnore) && this.text.length > oldLen))
|
|
5997
|
+
this.lineBreak();
|
|
5998
|
+
cur = next;
|
|
5999
|
+
}
|
|
6000
|
+
this.findPointBefore(parent, end);
|
|
6001
|
+
return this;
|
|
6002
|
+
}
|
|
6003
|
+
readTextNode(node) {
|
|
6004
|
+
let text = node.nodeValue;
|
|
6005
|
+
for (let point of this.points)
|
|
6006
|
+
if (point.node == node)
|
|
6007
|
+
point.pos = this.text.length + Math.min(point.offset, text.length);
|
|
6008
|
+
for (let off = 0, re = this.lineSeparator ? null : /\r\n?|\n/g;;) {
|
|
6009
|
+
let nextBreak = -1, breakSize = 1, m;
|
|
6010
|
+
if (this.lineSeparator) {
|
|
6011
|
+
nextBreak = text.indexOf(this.lineSeparator, off);
|
|
6012
|
+
breakSize = this.lineSeparator.length;
|
|
6013
|
+
}
|
|
6014
|
+
else if (m = re.exec(text)) {
|
|
6015
|
+
nextBreak = m.index;
|
|
6016
|
+
breakSize = m[0].length;
|
|
6017
|
+
}
|
|
6018
|
+
this.append(text.slice(off, nextBreak < 0 ? text.length : nextBreak));
|
|
6019
|
+
if (nextBreak < 0)
|
|
6020
|
+
break;
|
|
6021
|
+
this.lineBreak();
|
|
6022
|
+
if (breakSize > 1)
|
|
6023
|
+
for (let point of this.points)
|
|
6024
|
+
if (point.node == node && point.pos > this.text.length)
|
|
6025
|
+
point.pos -= breakSize - 1;
|
|
6026
|
+
off = nextBreak + breakSize;
|
|
6027
|
+
}
|
|
6028
|
+
}
|
|
6029
|
+
readNode(node) {
|
|
6030
|
+
if (node.cmIgnore)
|
|
6031
|
+
return;
|
|
6032
|
+
let view = ContentView.get(node);
|
|
6033
|
+
let fromView = view && view.overrideDOMText;
|
|
6034
|
+
if (fromView != null) {
|
|
6035
|
+
this.findPointInside(node, fromView.length);
|
|
6036
|
+
for (let i = fromView.iter(); !i.next().done;) {
|
|
6037
|
+
if (i.lineBreak)
|
|
6038
|
+
this.lineBreak();
|
|
6039
|
+
else
|
|
6040
|
+
this.append(i.value);
|
|
6041
|
+
}
|
|
6042
|
+
}
|
|
6043
|
+
else if (node.nodeType == 3) {
|
|
6044
|
+
this.readTextNode(node);
|
|
6045
|
+
}
|
|
6046
|
+
else if (node.nodeName == "BR") {
|
|
6047
|
+
if (node.nextSibling)
|
|
6048
|
+
this.lineBreak();
|
|
6049
|
+
}
|
|
6050
|
+
else if (node.nodeType == 1) {
|
|
6051
|
+
this.readRange(node.firstChild, null);
|
|
6052
|
+
}
|
|
6053
|
+
}
|
|
6054
|
+
findPointBefore(node, next) {
|
|
6055
|
+
for (let point of this.points)
|
|
6056
|
+
if (point.node == node && node.childNodes[point.offset] == next)
|
|
6057
|
+
point.pos = this.text.length;
|
|
6058
|
+
}
|
|
6059
|
+
findPointInside(node, maxLen) {
|
|
6060
|
+
for (let point of this.points)
|
|
6061
|
+
if (node.nodeType == 3 ? point.node == node : node.contains(point.node))
|
|
6062
|
+
point.pos = this.text.length + Math.min(maxLen, point.offset);
|
|
6063
|
+
}
|
|
6064
|
+
}
|
|
6065
|
+
function isBlockElement(node) {
|
|
6066
|
+
return node.nodeType == 1 && /^(DIV|P|LI|UL|OL|BLOCKQUOTE|DD|DT|H\d|SECTION|PRE)$/.test(node.nodeName);
|
|
6067
|
+
}
|
|
6068
|
+
class DOMPoint {
|
|
6069
|
+
constructor(node, offset) {
|
|
6070
|
+
this.node = node;
|
|
6071
|
+
this.offset = offset;
|
|
6072
|
+
this.pos = -1;
|
|
6073
|
+
}
|
|
6074
|
+
}
|
|
6075
|
+
|
|
6060
6076
|
class DOMChange {
|
|
6061
6077
|
constructor(view, start, end, typeOver) {
|
|
6062
6078
|
this.typeOver = typeOver;
|
|
@@ -6207,8 +6223,14 @@ function applyDefaultInsert(view, change, newSel) {
|
|
|
6207
6223
|
if (startState.selection.ranges.length > 1 && view.inputState.composing >= 0 &&
|
|
6208
6224
|
change.to <= sel.to && change.to >= sel.to - 10) {
|
|
6209
6225
|
let replaced = view.state.sliceDoc(change.from, change.to);
|
|
6210
|
-
let composition = findCompositionNode(view,
|
|
6211
|
-
|
|
6226
|
+
let compositionRange, composition = newSel && findCompositionNode(view, newSel.main.head);
|
|
6227
|
+
if (composition) {
|
|
6228
|
+
let dLen = change.insert.length - (change.to - change.from);
|
|
6229
|
+
compositionRange = { from: composition.from, to: composition.to - dLen };
|
|
6230
|
+
}
|
|
6231
|
+
else {
|
|
6232
|
+
compositionRange = view.state.doc.lineAt(sel.head);
|
|
6233
|
+
}
|
|
6212
6234
|
let offset = sel.to - change.to, size = sel.to - sel.from;
|
|
6213
6235
|
tr = startState.changeByRange(range => {
|
|
6214
6236
|
if (range.from == sel.from && range.to == sel.to)
|
|
@@ -6219,7 +6241,7 @@ function applyDefaultInsert(view, change, newSel) {
|
|
|
6219
6241
|
// changes in the same node work without aborting
|
|
6220
6242
|
// composition, so cursors in the composition range are
|
|
6221
6243
|
// ignored.
|
|
6222
|
-
|
|
6244
|
+
range.to >= compositionRange.from && range.from <= compositionRange.to)
|
|
6223
6245
|
return { range };
|
|
6224
6246
|
let rangeChanges = startState.changes({ from, to, insert: change.insert }), selOff = range.to - sel.to;
|
|
6225
6247
|
return {
|
|
@@ -6638,7 +6660,9 @@ class DOMObserver {
|
|
|
6638
6660
|
this.lastChange = Date.now();
|
|
6639
6661
|
this.view.inputState.lastFocusTime = 0;
|
|
6640
6662
|
this.selectionChanged = false;
|
|
6641
|
-
|
|
6663
|
+
let change = new DOMChange(this.view, from, to, typeOver);
|
|
6664
|
+
this.view.docView.domChanged = { newSel: change.newSel ? change.newSel.main : null };
|
|
6665
|
+
return change;
|
|
6642
6666
|
}
|
|
6643
6667
|
// Apply pending changes, if any
|
|
6644
6668
|
flush(readSelection = true) {
|
|
@@ -7067,9 +7091,9 @@ class EditorView {
|
|
|
7067
7091
|
if (flush)
|
|
7068
7092
|
this.observer.forceFlush();
|
|
7069
7093
|
let updated = null;
|
|
7070
|
-
let sDOM = this.scrollDOM,
|
|
7094
|
+
let sDOM = this.scrollDOM, scrollTop = sDOM.scrollTop * this.scaleY;
|
|
7071
7095
|
let { scrollAnchorPos, scrollAnchorHeight } = this.viewState;
|
|
7072
|
-
if (scrollTop
|
|
7096
|
+
if (Math.abs(scrollTop - this.viewState.scrollTop) > 1)
|
|
7073
7097
|
scrollAnchorHeight = -1;
|
|
7074
7098
|
this.viewState.scrollAnchorHeight = -1;
|
|
7075
7099
|
try {
|
|
@@ -7146,7 +7170,8 @@ class EditorView {
|
|
|
7146
7170
|
this.viewState.lineBlockAt(scrollAnchorPos).top;
|
|
7147
7171
|
let diff = newAnchorHeight - scrollAnchorHeight;
|
|
7148
7172
|
if (diff > 1 || diff < -1) {
|
|
7149
|
-
scrollTop =
|
|
7173
|
+
scrollTop = scrollTop + diff;
|
|
7174
|
+
sDOM.scrollTop = scrollTop / this.scaleY;
|
|
7150
7175
|
scrollAnchorHeight = -1;
|
|
7151
7176
|
continue;
|
|
7152
7177
|
}
|
|
@@ -7273,6 +7298,16 @@ class EditorView {
|
|
|
7273
7298
|
return { top: this.viewState.paddingTop, bottom: this.viewState.paddingBottom };
|
|
7274
7299
|
}
|
|
7275
7300
|
/**
|
|
7301
|
+
If the editor is transformed with CSS, this provides the scale
|
|
7302
|
+
along the X axis. Otherwise, it will just be 1. Note that
|
|
7303
|
+
transforms other than translation and scaling are not supported.
|
|
7304
|
+
*/
|
|
7305
|
+
get scaleX() { return this.viewState.scaleX; }
|
|
7306
|
+
/**
|
|
7307
|
+
Provide the CSS transformed scale along the Y axis.
|
|
7308
|
+
*/
|
|
7309
|
+
get scaleY() { return this.viewState.scaleY; }
|
|
7310
|
+
/**
|
|
7276
7311
|
Find the text line or block widget at the given vertical
|
|
7277
7312
|
position (which is interpreted as relative to the [top of the
|
|
7278
7313
|
document](https://codemirror.net/6/docs/ref/#view.EditorView.documentTop)).
|
|
@@ -8063,8 +8098,8 @@ class RectangleMarker {
|
|
|
8063
8098
|
}
|
|
8064
8099
|
function getBase(view) {
|
|
8065
8100
|
let rect = view.scrollDOM.getBoundingClientRect();
|
|
8066
|
-
let left = view.textDirection == exports.Direction.LTR ? rect.left : rect.right - view.scrollDOM.clientWidth;
|
|
8067
|
-
return { left: left - view.scrollDOM.scrollLeft, top: rect.top - view.scrollDOM.scrollTop };
|
|
8101
|
+
let left = view.textDirection == exports.Direction.LTR ? rect.left : rect.right - view.scrollDOM.clientWidth * view.scaleX;
|
|
8102
|
+
return { left: left - view.scrollDOM.scrollLeft * view.scaleX, top: rect.top - view.scrollDOM.scrollTop * view.scaleY };
|
|
8068
8103
|
}
|
|
8069
8104
|
function wrappedLine(view, pos, inside) {
|
|
8070
8105
|
let range = state.EditorSelection.cursor(pos);
|
|
@@ -8166,6 +8201,8 @@ class LayerView {
|
|
|
8166
8201
|
this.view = view;
|
|
8167
8202
|
this.layer = layer;
|
|
8168
8203
|
this.drawn = [];
|
|
8204
|
+
this.scaleX = 1;
|
|
8205
|
+
this.scaleY = 1;
|
|
8169
8206
|
this.measureReq = { read: this.measure.bind(this), write: this.draw.bind(this) };
|
|
8170
8207
|
this.dom = view.scrollDOM.appendChild(document.createElement("div"));
|
|
8171
8208
|
this.dom.classList.add("cm-layer");
|
|
@@ -8173,6 +8210,7 @@ class LayerView {
|
|
|
8173
8210
|
this.dom.classList.add("cm-layer-above");
|
|
8174
8211
|
if (layer.class)
|
|
8175
8212
|
this.dom.classList.add(layer.class);
|
|
8213
|
+
this.scale();
|
|
8176
8214
|
this.dom.setAttribute("aria-hidden", "true");
|
|
8177
8215
|
this.setOrder(view.state);
|
|
8178
8216
|
view.requestMeasure(this.measureReq);
|
|
@@ -8182,8 +8220,10 @@ class LayerView {
|
|
|
8182
8220
|
update(update) {
|
|
8183
8221
|
if (update.startState.facet(layerOrder) != update.state.facet(layerOrder))
|
|
8184
8222
|
this.setOrder(update.state);
|
|
8185
|
-
if (this.layer.update(update, this.dom) || update.geometryChanged)
|
|
8223
|
+
if (this.layer.update(update, this.dom) || update.geometryChanged) {
|
|
8224
|
+
this.scale();
|
|
8186
8225
|
update.view.requestMeasure(this.measureReq);
|
|
8226
|
+
}
|
|
8187
8227
|
}
|
|
8188
8228
|
setOrder(state) {
|
|
8189
8229
|
let pos = 0, order = state.facet(layerOrder);
|
|
@@ -8194,6 +8234,14 @@ class LayerView {
|
|
|
8194
8234
|
measure() {
|
|
8195
8235
|
return this.layer.markers(this.view);
|
|
8196
8236
|
}
|
|
8237
|
+
scale() {
|
|
8238
|
+
let { scaleX, scaleY } = this.view;
|
|
8239
|
+
if (scaleX != this.scaleX || scaleY != this.scaleY) {
|
|
8240
|
+
this.scaleX = scaleX;
|
|
8241
|
+
this.scaleY = scaleY;
|
|
8242
|
+
this.dom.style.transform = `scale(${1 / scaleX}, ${1 / scaleY})`;
|
|
8243
|
+
}
|
|
8244
|
+
}
|
|
8197
8245
|
draw(markers) {
|
|
8198
8246
|
if (markers.length != this.drawn.length || markers.some((p, i) => !sameMarker(p, this.drawn[i]))) {
|
|
8199
8247
|
let old = this.dom.firstChild, oldI = 0;
|
|
@@ -8363,23 +8411,25 @@ const drawDropCursor = ViewPlugin.fromClass(class {
|
|
|
8363
8411
|
}
|
|
8364
8412
|
}
|
|
8365
8413
|
readPos() {
|
|
8366
|
-
let
|
|
8367
|
-
let
|
|
8414
|
+
let { view } = this;
|
|
8415
|
+
let pos = view.state.field(dropCursorPos);
|
|
8416
|
+
let rect = pos != null && view.coordsAtPos(pos);
|
|
8368
8417
|
if (!rect)
|
|
8369
8418
|
return null;
|
|
8370
|
-
let outer =
|
|
8419
|
+
let outer = view.scrollDOM.getBoundingClientRect();
|
|
8371
8420
|
return {
|
|
8372
|
-
left: rect.left - outer.left +
|
|
8373
|
-
top: rect.top - outer.top +
|
|
8421
|
+
left: rect.left - outer.left + view.scrollDOM.scrollLeft * view.scaleX,
|
|
8422
|
+
top: rect.top - outer.top + view.scrollDOM.scrollTop * view.scaleY,
|
|
8374
8423
|
height: rect.bottom - rect.top
|
|
8375
8424
|
};
|
|
8376
8425
|
}
|
|
8377
8426
|
drawCursor(pos) {
|
|
8378
8427
|
if (this.cursor) {
|
|
8428
|
+
let { scaleX, scaleY } = this.view;
|
|
8379
8429
|
if (pos) {
|
|
8380
|
-
this.cursor.style.left = pos.left + "px";
|
|
8381
|
-
this.cursor.style.top = pos.top + "px";
|
|
8382
|
-
this.cursor.style.height = pos.height + "px";
|
|
8430
|
+
this.cursor.style.left = pos.left / scaleX + "px";
|
|
8431
|
+
this.cursor.style.top = pos.top / scaleY + "px";
|
|
8432
|
+
this.cursor.style.height = pos.height / scaleY + "px";
|
|
8383
8433
|
}
|
|
8384
8434
|
else {
|
|
8385
8435
|
this.cursor.style.left = "-100000px";
|
|
@@ -8621,7 +8671,9 @@ function specialCharPlugin() {
|
|
|
8621
8671
|
if (code == 9) {
|
|
8622
8672
|
let line = doc.lineAt(pos);
|
|
8623
8673
|
let size = view.state.tabSize, col = state.countColumn(line.text, size, pos - line.from);
|
|
8624
|
-
return Decoration.replace({
|
|
8674
|
+
return Decoration.replace({
|
|
8675
|
+
widget: new TabWidget((size - (col % size)) * this.view.defaultCharacterWidth / this.view.scaleX)
|
|
8676
|
+
});
|
|
8625
8677
|
}
|
|
8626
8678
|
return this.decorationCache[code] ||
|
|
8627
8679
|
(this.decorationCache[code] = Decoration.replace({ widget: new SpecialCharWidget(conf, code) }));
|
|
@@ -8698,7 +8750,8 @@ const plugin = ViewPlugin.fromClass(class {
|
|
|
8698
8750
|
}
|
|
8699
8751
|
update(update) {
|
|
8700
8752
|
let { view } = update;
|
|
8701
|
-
let height = view.viewState.editorHeight
|
|
8753
|
+
let height = view.viewState.editorHeight * view.scaleY -
|
|
8754
|
+
view.defaultLineHeight - view.documentPadding.top - 0.5;
|
|
8702
8755
|
if (height >= 0 && height != this.height) {
|
|
8703
8756
|
this.height = height;
|
|
8704
8757
|
this.attrs = { style: `padding-bottom: ${height}px` };
|
|
@@ -8995,6 +9048,7 @@ const tooltipPlugin = ViewPlugin.fromClass(class {
|
|
|
8995
9048
|
constructor(view) {
|
|
8996
9049
|
this.view = view;
|
|
8997
9050
|
this.inView = true;
|
|
9051
|
+
this.madeAbsolute = false;
|
|
8998
9052
|
this.lastTransaction = 0;
|
|
8999
9053
|
this.measureTimeout = -1;
|
|
9000
9054
|
let config = view.state.facet(tooltipConfig);
|
|
@@ -9046,7 +9100,7 @@ const tooltipPlugin = ViewPlugin.fromClass(class {
|
|
|
9046
9100
|
this.observeIntersection();
|
|
9047
9101
|
let shouldMeasure = updated || update.geometryChanged;
|
|
9048
9102
|
let newConfig = update.state.facet(tooltipConfig);
|
|
9049
|
-
if (newConfig.position != this.position) {
|
|
9103
|
+
if (newConfig.position != this.position && !this.madeAbsolute) {
|
|
9050
9104
|
this.position = newConfig.position;
|
|
9051
9105
|
for (let t of this.manager.tooltipViews)
|
|
9052
9106
|
t.dom.style.position = this.position;
|
|
@@ -9094,6 +9148,27 @@ const tooltipPlugin = ViewPlugin.fromClass(class {
|
|
|
9094
9148
|
}
|
|
9095
9149
|
readMeasure() {
|
|
9096
9150
|
let editor = this.view.dom.getBoundingClientRect();
|
|
9151
|
+
let scaleX = 1, scaleY = 1, makeAbsolute = false;
|
|
9152
|
+
if (this.position == "fixed") {
|
|
9153
|
+
let views = this.manager.tooltipViews;
|
|
9154
|
+
// When the dialog's offset parent isn't the body, we are
|
|
9155
|
+
// probably in a transformed container, and should use absolute
|
|
9156
|
+
// positioning instead, since fixed positioning inside a
|
|
9157
|
+
// transform works in a very broken way.
|
|
9158
|
+
makeAbsolute = views.length > 0 && views[0].dom.offsetParent != this.container.ownerDocument.body;
|
|
9159
|
+
}
|
|
9160
|
+
if (makeAbsolute || this.position == "absolute") {
|
|
9161
|
+
if (this.parent) {
|
|
9162
|
+
let rect = this.parent.getBoundingClientRect();
|
|
9163
|
+
if (rect.width && rect.height) {
|
|
9164
|
+
scaleX = rect.width / this.parent.offsetWidth;
|
|
9165
|
+
scaleY = rect.height / this.parent.offsetHeight;
|
|
9166
|
+
}
|
|
9167
|
+
}
|
|
9168
|
+
else {
|
|
9169
|
+
({ scaleX, scaleY } = this.view.viewState);
|
|
9170
|
+
}
|
|
9171
|
+
}
|
|
9097
9172
|
return {
|
|
9098
9173
|
editor,
|
|
9099
9174
|
parent: this.parent ? this.container.getBoundingClientRect() : editor,
|
|
@@ -9103,11 +9178,18 @@ const tooltipPlugin = ViewPlugin.fromClass(class {
|
|
|
9103
9178
|
}),
|
|
9104
9179
|
size: this.manager.tooltipViews.map(({ dom }) => dom.getBoundingClientRect()),
|
|
9105
9180
|
space: this.view.state.facet(tooltipConfig).tooltipSpace(this.view),
|
|
9181
|
+
scaleX, scaleY, makeAbsolute
|
|
9106
9182
|
};
|
|
9107
9183
|
}
|
|
9108
9184
|
writeMeasure(measured) {
|
|
9109
9185
|
var _a;
|
|
9110
|
-
|
|
9186
|
+
if (measured.makeAbsolute) {
|
|
9187
|
+
this.madeAbsolute = true;
|
|
9188
|
+
this.position = "absolute";
|
|
9189
|
+
for (let t of this.manager.tooltipViews)
|
|
9190
|
+
t.dom.style.position = "absolute";
|
|
9191
|
+
}
|
|
9192
|
+
let { editor, space, scaleX, scaleY } = measured;
|
|
9111
9193
|
let others = [];
|
|
9112
9194
|
for (let i = 0; i < this.manager.tooltips.length; i++) {
|
|
9113
9195
|
let tooltip = this.manager.tooltips[i], tView = this.manager.tooltipViews[i], { dom } = tView;
|
|
@@ -9140,7 +9222,7 @@ const tooltipPlugin = ViewPlugin.fromClass(class {
|
|
|
9140
9222
|
continue;
|
|
9141
9223
|
}
|
|
9142
9224
|
knownHeight.set(tView, height);
|
|
9143
|
-
dom.style.height = (height = spaceVert) + "px";
|
|
9225
|
+
dom.style.height = (height = spaceVert) / scaleY + "px";
|
|
9144
9226
|
}
|
|
9145
9227
|
else if (dom.style.height) {
|
|
9146
9228
|
dom.style.height = "";
|
|
@@ -9152,15 +9234,17 @@ const tooltipPlugin = ViewPlugin.fromClass(class {
|
|
|
9152
9234
|
if (r.left < right && r.right > left && r.top < top + height && r.bottom > top)
|
|
9153
9235
|
top = above ? r.top - height - 2 - arrowHeight : r.bottom + arrowHeight + 2;
|
|
9154
9236
|
if (this.position == "absolute") {
|
|
9155
|
-
dom.style.top = (top - measured.parent.top) + "px";
|
|
9156
|
-
dom.style.left = (left - measured.parent.left) + "px";
|
|
9237
|
+
dom.style.top = (top - measured.parent.top) / scaleY + "px";
|
|
9238
|
+
dom.style.left = (left - measured.parent.left) / scaleX + "px";
|
|
9157
9239
|
}
|
|
9158
9240
|
else {
|
|
9159
|
-
dom.style.top = top + "px";
|
|
9160
|
-
dom.style.left = left + "px";
|
|
9241
|
+
dom.style.top = top / scaleY + "px";
|
|
9242
|
+
dom.style.left = left / scaleX + "px";
|
|
9243
|
+
}
|
|
9244
|
+
if (arrow) {
|
|
9245
|
+
let arrowLeft = pos.left + (ltr ? offset.x : -offset.x) - (left + 14 /* Arrow.Offset */ - 7 /* Arrow.Size */);
|
|
9246
|
+
arrow.style.left = arrowLeft / scaleX + "px";
|
|
9161
9247
|
}
|
|
9162
|
-
if (arrow)
|
|
9163
|
-
arrow.style.left = `${pos.left + (ltr ? offset.x : -offset.x) - (left + 14 /* Arrow.Offset */ - 7 /* Arrow.Size */)}px`;
|
|
9164
9248
|
if (tView.overlap !== true)
|
|
9165
9249
|
others.push({ left, top, right, bottom: top + height });
|
|
9166
9250
|
dom.classList.toggle("cm-tooltip-above", above);
|
|
@@ -9762,7 +9846,7 @@ const gutterView = ViewPlugin.fromClass(class {
|
|
|
9762
9846
|
this.dom = document.createElement("div");
|
|
9763
9847
|
this.dom.className = "cm-gutters";
|
|
9764
9848
|
this.dom.setAttribute("aria-hidden", "true");
|
|
9765
|
-
this.dom.style.minHeight = this.view.contentHeight + "px";
|
|
9849
|
+
this.dom.style.minHeight = (this.view.contentHeight / this.view.scaleY) + "px";
|
|
9766
9850
|
this.gutters = view.state.facet(activeGutters).map(conf => new SingleGutterView(view, conf));
|
|
9767
9851
|
for (let gutter of this.gutters)
|
|
9768
9852
|
this.dom.appendChild(gutter.dom);
|
|
@@ -9823,6 +9907,10 @@ const gutterView = ViewPlugin.fromClass(class {
|
|
|
9823
9907
|
for (let cx of contexts)
|
|
9824
9908
|
cx.line(this.view, line, classSet);
|
|
9825
9909
|
}
|
|
9910
|
+
else if (line.widget) {
|
|
9911
|
+
for (let cx of contexts)
|
|
9912
|
+
cx.widget(this.view, line);
|
|
9913
|
+
}
|
|
9826
9914
|
}
|
|
9827
9915
|
for (let cx of contexts)
|
|
9828
9916
|
cx.finish();
|
|
@@ -9872,7 +9960,9 @@ const gutterView = ViewPlugin.fromClass(class {
|
|
|
9872
9960
|
let value = view.plugin(plugin);
|
|
9873
9961
|
if (!value || value.gutters.length == 0 || !value.fixed)
|
|
9874
9962
|
return null;
|
|
9875
|
-
return view.textDirection == exports.Direction.LTR
|
|
9963
|
+
return view.textDirection == exports.Direction.LTR
|
|
9964
|
+
? { left: value.dom.offsetWidth * view.scaleX }
|
|
9965
|
+
: { right: value.dom.offsetWidth * view.scaleX };
|
|
9876
9966
|
})
|
|
9877
9967
|
});
|
|
9878
9968
|
function asArray(val) { return (Array.isArray(val) ? val : [val]); }
|
|
@@ -9989,10 +10079,12 @@ class GutterElement {
|
|
|
9989
10079
|
this.update(view, height, above, markers);
|
|
9990
10080
|
}
|
|
9991
10081
|
update(view, height, above, markers) {
|
|
9992
|
-
if (this.height != height)
|
|
9993
|
-
this.
|
|
10082
|
+
if (this.height != height) {
|
|
10083
|
+
this.height = height;
|
|
10084
|
+
this.dom.style.height = height / view.scaleY + "px";
|
|
10085
|
+
}
|
|
9994
10086
|
if (this.above != above)
|
|
9995
|
-
this.dom.style.marginTop = (this.above = above) ? above + "px" : "";
|
|
10087
|
+
this.dom.style.marginTop = (this.above = above) ? above / view.scaleY + "px" : "";
|
|
9996
10088
|
if (!sameMarkers(this.markers, markers))
|
|
9997
10089
|
this.setMarkers(view, markers);
|
|
9998
10090
|
}
|