@codemirror/view 6.17.1 → 6.18.0
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 +8 -0
- package/dist/index.cjs +142 -53
- package/dist/index.d.cts +13 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.js +142 -53
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,11 @@
|
|
|
1
|
+
## 6.18.0 (2023-09-05)
|
|
2
|
+
|
|
3
|
+
### New features
|
|
4
|
+
|
|
5
|
+
The new `EditorView.scaleX` and `scaleY` properties return the CSS-transformed scale of the editor (or 1 when not scaled).
|
|
6
|
+
|
|
7
|
+
The editor now supports being scaled with CSS.
|
|
8
|
+
|
|
1
9
|
## 6.17.1 (2023-08-31)
|
|
2
10
|
|
|
3
11
|
### Bug fixes
|
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 };
|
|
@@ -2781,7 +2784,7 @@ class DocView extends ContentView {
|
|
|
2781
2784
|
// messes with the scroll position during DOM mutation (though
|
|
2782
2785
|
// no relayout is triggered and I cannot imagine how it can
|
|
2783
2786
|
// recompute the scroll position without a layout)
|
|
2784
|
-
this.dom.style.height = this.view.viewState.contentHeight + "px";
|
|
2787
|
+
this.dom.style.height = this.view.viewState.contentHeight / this.view.scaleY + "px";
|
|
2785
2788
|
this.dom.style.flexBasis = this.minWidth ? this.minWidth + "px" : "";
|
|
2786
2789
|
// Chrome will sometimes, when DOM mutations occur directly
|
|
2787
2790
|
// around the selection, get confused and report a different
|
|
@@ -2853,7 +2856,7 @@ class DocView extends ContentView {
|
|
|
2853
2856
|
}
|
|
2854
2857
|
fixCompositionDOM(composition) {
|
|
2855
2858
|
let fix = (dom, cView) => {
|
|
2856
|
-
cView.flags |= 8 /* ViewFlag.Composition
|
|
2859
|
+
cView.flags |= 8 /* ViewFlag.Composition */ | (cView.children.some(c => c.flags & 7 /* ViewFlag.Dirty */) ? 1 /* ViewFlag.ChildDirty */ : 0);
|
|
2857
2860
|
this.markedForComposition.add(cView);
|
|
2858
2861
|
let prev = ContentView.get(dom);
|
|
2859
2862
|
if (prev != cView) {
|
|
@@ -3119,7 +3122,7 @@ class DocView extends ContentView {
|
|
|
3119
3122
|
let next = i == vs.viewports.length ? null : vs.viewports[i];
|
|
3120
3123
|
let end = next ? next.from - 1 : this.length;
|
|
3121
3124
|
if (end > pos) {
|
|
3122
|
-
let height = vs.lineBlockAt(end).bottom - vs.lineBlockAt(pos).top;
|
|
3125
|
+
let height = (vs.lineBlockAt(end).bottom - vs.lineBlockAt(pos).top) / this.view.scaleY;
|
|
3123
3126
|
deco.push(Decoration.replace({
|
|
3124
3127
|
widget: new BlockGapWidget(height),
|
|
3125
3128
|
block: true,
|
|
@@ -5276,8 +5279,10 @@ class LineGap {
|
|
|
5276
5279
|
}
|
|
5277
5280
|
return true;
|
|
5278
5281
|
}
|
|
5279
|
-
draw(wrapping) {
|
|
5280
|
-
return Decoration.replace({
|
|
5282
|
+
draw(viewState, wrapping) {
|
|
5283
|
+
return Decoration.replace({
|
|
5284
|
+
widget: new LineGapWidget(this.size * (wrapping ? viewState.scaleY : viewState.scaleX), wrapping)
|
|
5285
|
+
}).range(this.from, this.to);
|
|
5281
5286
|
}
|
|
5282
5287
|
}
|
|
5283
5288
|
class LineGapWidget extends WidgetType {
|
|
@@ -5307,14 +5312,18 @@ class ViewState {
|
|
|
5307
5312
|
// These are contentDOM-local coordinates
|
|
5308
5313
|
this.pixelViewport = { left: 0, right: window.innerWidth, top: 0, bottom: 0 };
|
|
5309
5314
|
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;
|
|
5315
|
+
this.paddingTop = 0; // Padding above the document, scaled
|
|
5316
|
+
this.paddingBottom = 0; // Padding below the document, scaled
|
|
5317
|
+
this.contentDOMWidth = 0; // contentDOM.getBoundingClientRect().width
|
|
5318
|
+
this.contentDOMHeight = 0; // contentDOM.getBoundingClientRect().height
|
|
5319
|
+
this.editorHeight = 0; // scrollDOM.clientHeight, unscaled
|
|
5320
|
+
this.editorWidth = 0; // scrollDOM.clientWidth, unscaled
|
|
5321
|
+
this.scrollTop = 0; // Last seen scrollDOM.scrollTop, scaled
|
|
5317
5322
|
this.scrolledToBottom = true;
|
|
5323
|
+
// The CSS-transformation scale of the editor (transformed size /
|
|
5324
|
+
// concrete size)
|
|
5325
|
+
this.scaleX = 1;
|
|
5326
|
+
this.scaleY = 1;
|
|
5318
5327
|
// The vertical position (document-relative) to which to anchor the
|
|
5319
5328
|
// scroll position. -1 means anchor to the end of the document.
|
|
5320
5329
|
this.scrollAnchorPos = 0;
|
|
@@ -5348,7 +5357,7 @@ class ViewState {
|
|
|
5348
5357
|
this.updateViewportLines();
|
|
5349
5358
|
this.updateForViewport();
|
|
5350
5359
|
this.lineGaps = this.ensureLineGaps([]);
|
|
5351
|
-
this.lineGapDeco = Decoration.set(this.lineGaps.map(gap => gap.draw(false)));
|
|
5360
|
+
this.lineGapDeco = Decoration.set(this.lineGaps.map(gap => gap.draw(this, false)));
|
|
5352
5361
|
this.computeVisibleRanges();
|
|
5353
5362
|
}
|
|
5354
5363
|
updateForViewport() {
|
|
@@ -5420,8 +5429,23 @@ class ViewState {
|
|
|
5420
5429
|
this.contentDOMHeight = domRect.height;
|
|
5421
5430
|
this.mustMeasureContent = false;
|
|
5422
5431
|
let result = 0, bias = 0;
|
|
5432
|
+
if (domRect.width && domRect.height) {
|
|
5433
|
+
let scaleX = domRect.width / dom.offsetWidth;
|
|
5434
|
+
let scaleY = domRect.height / dom.offsetHeight;
|
|
5435
|
+
if (scaleX > 0.995 && scaleX < 1.005)
|
|
5436
|
+
scaleX = 1;
|
|
5437
|
+
if (scaleY > 0.995 && scaleY < 1.005)
|
|
5438
|
+
scaleY = 1;
|
|
5439
|
+
if (this.scaleX != scaleX || this.scaleY != scaleY) {
|
|
5440
|
+
this.scaleX = scaleX;
|
|
5441
|
+
this.scaleY = scaleY;
|
|
5442
|
+
result |= 8 /* UpdateFlag.Geometry */;
|
|
5443
|
+
refresh = measureContent = true;
|
|
5444
|
+
}
|
|
5445
|
+
}
|
|
5423
5446
|
// Vertical padding
|
|
5424
|
-
let paddingTop = parseInt(style.paddingTop) || 0
|
|
5447
|
+
let paddingTop = (parseInt(style.paddingTop) || 0) * this.scaleY;
|
|
5448
|
+
let paddingBottom = (parseInt(style.paddingBottom) || 0) * this.scaleY;
|
|
5425
5449
|
if (this.paddingTop != paddingTop || this.paddingBottom != paddingBottom) {
|
|
5426
5450
|
this.paddingTop = paddingTop;
|
|
5427
5451
|
this.paddingBottom = paddingBottom;
|
|
@@ -5433,9 +5457,10 @@ class ViewState {
|
|
|
5433
5457
|
this.editorWidth = view.scrollDOM.clientWidth;
|
|
5434
5458
|
result |= 8 /* UpdateFlag.Geometry */;
|
|
5435
5459
|
}
|
|
5436
|
-
|
|
5460
|
+
let scrollTop = view.scrollDOM.scrollTop * this.scaleY;
|
|
5461
|
+
if (this.scrollTop != scrollTop) {
|
|
5437
5462
|
this.scrollAnchorHeight = -1;
|
|
5438
|
-
this.scrollTop =
|
|
5463
|
+
this.scrollTop = scrollTop;
|
|
5439
5464
|
}
|
|
5440
5465
|
this.scrolledToBottom = isScrolledToBottom(view.scrollDOM);
|
|
5441
5466
|
// Pixel viewport
|
|
@@ -5656,7 +5681,7 @@ class ViewState {
|
|
|
5656
5681
|
updateLineGaps(gaps) {
|
|
5657
5682
|
if (!LineGap.same(gaps, this.lineGaps)) {
|
|
5658
5683
|
this.lineGaps = gaps;
|
|
5659
|
-
this.lineGapDeco = Decoration.set(gaps.map(gap => gap.draw(this.heightOracle.lineWrapping)));
|
|
5684
|
+
this.lineGapDeco = Decoration.set(gaps.map(gap => gap.draw(this, this.heightOracle.lineWrapping)));
|
|
5660
5685
|
}
|
|
5661
5686
|
}
|
|
5662
5687
|
computeVisibleRanges() {
|
|
@@ -7067,9 +7092,9 @@ class EditorView {
|
|
|
7067
7092
|
if (flush)
|
|
7068
7093
|
this.observer.forceFlush();
|
|
7069
7094
|
let updated = null;
|
|
7070
|
-
let sDOM = this.scrollDOM,
|
|
7095
|
+
let sDOM = this.scrollDOM, scrollTop = sDOM.scrollTop * this.scaleY;
|
|
7071
7096
|
let { scrollAnchorPos, scrollAnchorHeight } = this.viewState;
|
|
7072
|
-
if (scrollTop
|
|
7097
|
+
if (Math.abs(scrollTop - this.viewState.scrollTop) > 1)
|
|
7073
7098
|
scrollAnchorHeight = -1;
|
|
7074
7099
|
this.viewState.scrollAnchorHeight = -1;
|
|
7075
7100
|
try {
|
|
@@ -7146,7 +7171,8 @@ class EditorView {
|
|
|
7146
7171
|
this.viewState.lineBlockAt(scrollAnchorPos).top;
|
|
7147
7172
|
let diff = newAnchorHeight - scrollAnchorHeight;
|
|
7148
7173
|
if (diff > 1 || diff < -1) {
|
|
7149
|
-
scrollTop =
|
|
7174
|
+
scrollTop = scrollTop + diff;
|
|
7175
|
+
sDOM.scrollTop = scrollTop / this.scaleY;
|
|
7150
7176
|
scrollAnchorHeight = -1;
|
|
7151
7177
|
continue;
|
|
7152
7178
|
}
|
|
@@ -7273,6 +7299,16 @@ class EditorView {
|
|
|
7273
7299
|
return { top: this.viewState.paddingTop, bottom: this.viewState.paddingBottom };
|
|
7274
7300
|
}
|
|
7275
7301
|
/**
|
|
7302
|
+
If the editor is transformed with CSS, this provides the scale
|
|
7303
|
+
along the X axis. Otherwise, it will just be 1. Note that
|
|
7304
|
+
transforms other than translation and scaling are not supported.
|
|
7305
|
+
*/
|
|
7306
|
+
get scaleX() { return this.viewState.scaleX; }
|
|
7307
|
+
/**
|
|
7308
|
+
Provide the CSS transformed scale along the Y axis.
|
|
7309
|
+
*/
|
|
7310
|
+
get scaleY() { return this.viewState.scaleY; }
|
|
7311
|
+
/**
|
|
7276
7312
|
Find the text line or block widget at the given vertical
|
|
7277
7313
|
position (which is interpreted as relative to the [top of the
|
|
7278
7314
|
document](https://codemirror.net/6/docs/ref/#view.EditorView.documentTop)).
|
|
@@ -8063,8 +8099,8 @@ class RectangleMarker {
|
|
|
8063
8099
|
}
|
|
8064
8100
|
function getBase(view) {
|
|
8065
8101
|
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 };
|
|
8102
|
+
let left = view.textDirection == exports.Direction.LTR ? rect.left : rect.right - view.scrollDOM.clientWidth * view.scaleX;
|
|
8103
|
+
return { left: left - view.scrollDOM.scrollLeft * view.scaleX, top: rect.top - view.scrollDOM.scrollTop * view.scaleY };
|
|
8068
8104
|
}
|
|
8069
8105
|
function wrappedLine(view, pos, inside) {
|
|
8070
8106
|
let range = state.EditorSelection.cursor(pos);
|
|
@@ -8166,6 +8202,8 @@ class LayerView {
|
|
|
8166
8202
|
this.view = view;
|
|
8167
8203
|
this.layer = layer;
|
|
8168
8204
|
this.drawn = [];
|
|
8205
|
+
this.scaleX = 1;
|
|
8206
|
+
this.scaleY = 1;
|
|
8169
8207
|
this.measureReq = { read: this.measure.bind(this), write: this.draw.bind(this) };
|
|
8170
8208
|
this.dom = view.scrollDOM.appendChild(document.createElement("div"));
|
|
8171
8209
|
this.dom.classList.add("cm-layer");
|
|
@@ -8173,6 +8211,7 @@ class LayerView {
|
|
|
8173
8211
|
this.dom.classList.add("cm-layer-above");
|
|
8174
8212
|
if (layer.class)
|
|
8175
8213
|
this.dom.classList.add(layer.class);
|
|
8214
|
+
this.scale();
|
|
8176
8215
|
this.dom.setAttribute("aria-hidden", "true");
|
|
8177
8216
|
this.setOrder(view.state);
|
|
8178
8217
|
view.requestMeasure(this.measureReq);
|
|
@@ -8182,8 +8221,10 @@ class LayerView {
|
|
|
8182
8221
|
update(update) {
|
|
8183
8222
|
if (update.startState.facet(layerOrder) != update.state.facet(layerOrder))
|
|
8184
8223
|
this.setOrder(update.state);
|
|
8185
|
-
if (this.layer.update(update, this.dom) || update.geometryChanged)
|
|
8224
|
+
if (this.layer.update(update, this.dom) || update.geometryChanged) {
|
|
8225
|
+
this.scale();
|
|
8186
8226
|
update.view.requestMeasure(this.measureReq);
|
|
8227
|
+
}
|
|
8187
8228
|
}
|
|
8188
8229
|
setOrder(state) {
|
|
8189
8230
|
let pos = 0, order = state.facet(layerOrder);
|
|
@@ -8194,6 +8235,14 @@ class LayerView {
|
|
|
8194
8235
|
measure() {
|
|
8195
8236
|
return this.layer.markers(this.view);
|
|
8196
8237
|
}
|
|
8238
|
+
scale() {
|
|
8239
|
+
let { scaleX, scaleY } = this.view;
|
|
8240
|
+
if (scaleX != this.scaleX || scaleY != this.scaleY) {
|
|
8241
|
+
this.scaleX = scaleX;
|
|
8242
|
+
this.scaleY = scaleY;
|
|
8243
|
+
this.dom.style.transform = `scale(${1 / scaleX}, ${1 / scaleY})`;
|
|
8244
|
+
}
|
|
8245
|
+
}
|
|
8197
8246
|
draw(markers) {
|
|
8198
8247
|
if (markers.length != this.drawn.length || markers.some((p, i) => !sameMarker(p, this.drawn[i]))) {
|
|
8199
8248
|
let old = this.dom.firstChild, oldI = 0;
|
|
@@ -8363,23 +8412,25 @@ const drawDropCursor = ViewPlugin.fromClass(class {
|
|
|
8363
8412
|
}
|
|
8364
8413
|
}
|
|
8365
8414
|
readPos() {
|
|
8366
|
-
let
|
|
8367
|
-
let
|
|
8415
|
+
let { view } = this;
|
|
8416
|
+
let pos = view.state.field(dropCursorPos);
|
|
8417
|
+
let rect = pos != null && view.coordsAtPos(pos);
|
|
8368
8418
|
if (!rect)
|
|
8369
8419
|
return null;
|
|
8370
|
-
let outer =
|
|
8420
|
+
let outer = view.scrollDOM.getBoundingClientRect();
|
|
8371
8421
|
return {
|
|
8372
|
-
left: rect.left - outer.left +
|
|
8373
|
-
top: rect.top - outer.top +
|
|
8422
|
+
left: rect.left - outer.left + view.scrollDOM.scrollLeft * view.scaleX,
|
|
8423
|
+
top: rect.top - outer.top + view.scrollDOM.scrollTop * view.scaleY,
|
|
8374
8424
|
height: rect.bottom - rect.top
|
|
8375
8425
|
};
|
|
8376
8426
|
}
|
|
8377
8427
|
drawCursor(pos) {
|
|
8378
8428
|
if (this.cursor) {
|
|
8429
|
+
let { scaleX, scaleY } = this.view;
|
|
8379
8430
|
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";
|
|
8431
|
+
this.cursor.style.left = pos.left / scaleX + "px";
|
|
8432
|
+
this.cursor.style.top = pos.top / scaleY + "px";
|
|
8433
|
+
this.cursor.style.height = pos.height / scaleY + "px";
|
|
8383
8434
|
}
|
|
8384
8435
|
else {
|
|
8385
8436
|
this.cursor.style.left = "-100000px";
|
|
@@ -8621,7 +8672,9 @@ function specialCharPlugin() {
|
|
|
8621
8672
|
if (code == 9) {
|
|
8622
8673
|
let line = doc.lineAt(pos);
|
|
8623
8674
|
let size = view.state.tabSize, col = state.countColumn(line.text, size, pos - line.from);
|
|
8624
|
-
return Decoration.replace({
|
|
8675
|
+
return Decoration.replace({
|
|
8676
|
+
widget: new TabWidget((size - (col % size)) * this.view.defaultCharacterWidth / this.view.scaleX)
|
|
8677
|
+
});
|
|
8625
8678
|
}
|
|
8626
8679
|
return this.decorationCache[code] ||
|
|
8627
8680
|
(this.decorationCache[code] = Decoration.replace({ widget: new SpecialCharWidget(conf, code) }));
|
|
@@ -8698,7 +8751,8 @@ const plugin = ViewPlugin.fromClass(class {
|
|
|
8698
8751
|
}
|
|
8699
8752
|
update(update) {
|
|
8700
8753
|
let { view } = update;
|
|
8701
|
-
let height = view.viewState.editorHeight
|
|
8754
|
+
let height = view.viewState.editorHeight * view.scaleY -
|
|
8755
|
+
view.defaultLineHeight - view.documentPadding.top - 0.5;
|
|
8702
8756
|
if (height >= 0 && height != this.height) {
|
|
8703
8757
|
this.height = height;
|
|
8704
8758
|
this.attrs = { style: `padding-bottom: ${height}px` };
|
|
@@ -8995,6 +9049,7 @@ const tooltipPlugin = ViewPlugin.fromClass(class {
|
|
|
8995
9049
|
constructor(view) {
|
|
8996
9050
|
this.view = view;
|
|
8997
9051
|
this.inView = true;
|
|
9052
|
+
this.madeAbsolute = false;
|
|
8998
9053
|
this.lastTransaction = 0;
|
|
8999
9054
|
this.measureTimeout = -1;
|
|
9000
9055
|
let config = view.state.facet(tooltipConfig);
|
|
@@ -9046,7 +9101,7 @@ const tooltipPlugin = ViewPlugin.fromClass(class {
|
|
|
9046
9101
|
this.observeIntersection();
|
|
9047
9102
|
let shouldMeasure = updated || update.geometryChanged;
|
|
9048
9103
|
let newConfig = update.state.facet(tooltipConfig);
|
|
9049
|
-
if (newConfig.position != this.position) {
|
|
9104
|
+
if (newConfig.position != this.position && !this.madeAbsolute) {
|
|
9050
9105
|
this.position = newConfig.position;
|
|
9051
9106
|
for (let t of this.manager.tooltipViews)
|
|
9052
9107
|
t.dom.style.position = this.position;
|
|
@@ -9094,6 +9149,27 @@ const tooltipPlugin = ViewPlugin.fromClass(class {
|
|
|
9094
9149
|
}
|
|
9095
9150
|
readMeasure() {
|
|
9096
9151
|
let editor = this.view.dom.getBoundingClientRect();
|
|
9152
|
+
let scaleX = 1, scaleY = 1, makeAbsolute = false;
|
|
9153
|
+
if (this.position == "fixed") {
|
|
9154
|
+
let views = this.manager.tooltipViews;
|
|
9155
|
+
// When the dialog's offset parent isn't the body, we are
|
|
9156
|
+
// probably in a transformed container, and should use absolute
|
|
9157
|
+
// positioning instead, since fixed positioning inside a
|
|
9158
|
+
// transform works in a very broken way.
|
|
9159
|
+
makeAbsolute = views.length > 0 && views[0].dom.offsetParent != this.container.ownerDocument.body;
|
|
9160
|
+
}
|
|
9161
|
+
if (makeAbsolute || this.position == "absolute") {
|
|
9162
|
+
if (this.parent) {
|
|
9163
|
+
let rect = this.parent.getBoundingClientRect();
|
|
9164
|
+
if (rect.width && rect.height) {
|
|
9165
|
+
scaleX = rect.width / this.parent.offsetWidth;
|
|
9166
|
+
scaleY = rect.height / this.parent.offsetHeight;
|
|
9167
|
+
}
|
|
9168
|
+
}
|
|
9169
|
+
else {
|
|
9170
|
+
({ scaleX, scaleY } = this.view.viewState);
|
|
9171
|
+
}
|
|
9172
|
+
}
|
|
9097
9173
|
return {
|
|
9098
9174
|
editor,
|
|
9099
9175
|
parent: this.parent ? this.container.getBoundingClientRect() : editor,
|
|
@@ -9103,11 +9179,18 @@ const tooltipPlugin = ViewPlugin.fromClass(class {
|
|
|
9103
9179
|
}),
|
|
9104
9180
|
size: this.manager.tooltipViews.map(({ dom }) => dom.getBoundingClientRect()),
|
|
9105
9181
|
space: this.view.state.facet(tooltipConfig).tooltipSpace(this.view),
|
|
9182
|
+
scaleX, scaleY, makeAbsolute
|
|
9106
9183
|
};
|
|
9107
9184
|
}
|
|
9108
9185
|
writeMeasure(measured) {
|
|
9109
9186
|
var _a;
|
|
9110
|
-
|
|
9187
|
+
if (measured.makeAbsolute) {
|
|
9188
|
+
this.madeAbsolute = true;
|
|
9189
|
+
this.position = "absolute";
|
|
9190
|
+
for (let t of this.manager.tooltipViews)
|
|
9191
|
+
t.dom.style.position = "absolute";
|
|
9192
|
+
}
|
|
9193
|
+
let { editor, space, scaleX, scaleY } = measured;
|
|
9111
9194
|
let others = [];
|
|
9112
9195
|
for (let i = 0; i < this.manager.tooltips.length; i++) {
|
|
9113
9196
|
let tooltip = this.manager.tooltips[i], tView = this.manager.tooltipViews[i], { dom } = tView;
|
|
@@ -9140,7 +9223,7 @@ const tooltipPlugin = ViewPlugin.fromClass(class {
|
|
|
9140
9223
|
continue;
|
|
9141
9224
|
}
|
|
9142
9225
|
knownHeight.set(tView, height);
|
|
9143
|
-
dom.style.height = (height = spaceVert) + "px";
|
|
9226
|
+
dom.style.height = (height = spaceVert) / scaleY + "px";
|
|
9144
9227
|
}
|
|
9145
9228
|
else if (dom.style.height) {
|
|
9146
9229
|
dom.style.height = "";
|
|
@@ -9152,15 +9235,17 @@ const tooltipPlugin = ViewPlugin.fromClass(class {
|
|
|
9152
9235
|
if (r.left < right && r.right > left && r.top < top + height && r.bottom > top)
|
|
9153
9236
|
top = above ? r.top - height - 2 - arrowHeight : r.bottom + arrowHeight + 2;
|
|
9154
9237
|
if (this.position == "absolute") {
|
|
9155
|
-
dom.style.top = (top - measured.parent.top) + "px";
|
|
9156
|
-
dom.style.left = (left - measured.parent.left) + "px";
|
|
9238
|
+
dom.style.top = (top - measured.parent.top) / scaleY + "px";
|
|
9239
|
+
dom.style.left = (left - measured.parent.left) / scaleX + "px";
|
|
9157
9240
|
}
|
|
9158
9241
|
else {
|
|
9159
|
-
dom.style.top = top + "px";
|
|
9160
|
-
dom.style.left = left + "px";
|
|
9242
|
+
dom.style.top = top / scaleY + "px";
|
|
9243
|
+
dom.style.left = left / scaleX + "px";
|
|
9244
|
+
}
|
|
9245
|
+
if (arrow) {
|
|
9246
|
+
let arrowLeft = pos.left + (ltr ? offset.x : -offset.x) - (left + 14 /* Arrow.Offset */ - 7 /* Arrow.Size */);
|
|
9247
|
+
arrow.style.left = arrowLeft / scaleX + "px";
|
|
9161
9248
|
}
|
|
9162
|
-
if (arrow)
|
|
9163
|
-
arrow.style.left = `${pos.left + (ltr ? offset.x : -offset.x) - (left + 14 /* Arrow.Offset */ - 7 /* Arrow.Size */)}px`;
|
|
9164
9249
|
if (tView.overlap !== true)
|
|
9165
9250
|
others.push({ left, top, right, bottom: top + height });
|
|
9166
9251
|
dom.classList.toggle("cm-tooltip-above", above);
|
|
@@ -9762,7 +9847,7 @@ const gutterView = ViewPlugin.fromClass(class {
|
|
|
9762
9847
|
this.dom = document.createElement("div");
|
|
9763
9848
|
this.dom.className = "cm-gutters";
|
|
9764
9849
|
this.dom.setAttribute("aria-hidden", "true");
|
|
9765
|
-
this.dom.style.minHeight = this.view.contentHeight + "px";
|
|
9850
|
+
this.dom.style.minHeight = (this.view.contentHeight / this.view.scaleY) + "px";
|
|
9766
9851
|
this.gutters = view.state.facet(activeGutters).map(conf => new SingleGutterView(view, conf));
|
|
9767
9852
|
for (let gutter of this.gutters)
|
|
9768
9853
|
this.dom.appendChild(gutter.dom);
|
|
@@ -9872,7 +9957,9 @@ const gutterView = ViewPlugin.fromClass(class {
|
|
|
9872
9957
|
let value = view.plugin(plugin);
|
|
9873
9958
|
if (!value || value.gutters.length == 0 || !value.fixed)
|
|
9874
9959
|
return null;
|
|
9875
|
-
return view.textDirection == exports.Direction.LTR
|
|
9960
|
+
return view.textDirection == exports.Direction.LTR
|
|
9961
|
+
? { left: value.dom.offsetWidth * view.scaleX }
|
|
9962
|
+
: { right: value.dom.offsetWidth * view.scaleX };
|
|
9876
9963
|
})
|
|
9877
9964
|
});
|
|
9878
9965
|
function asArray(val) { return (Array.isArray(val) ? val : [val]); }
|
|
@@ -9989,10 +10076,12 @@ class GutterElement {
|
|
|
9989
10076
|
this.update(view, height, above, markers);
|
|
9990
10077
|
}
|
|
9991
10078
|
update(view, height, above, markers) {
|
|
9992
|
-
if (this.height != height)
|
|
9993
|
-
this.
|
|
10079
|
+
if (this.height != height) {
|
|
10080
|
+
this.height = height;
|
|
10081
|
+
this.dom.style.height = height / view.scaleY + "px";
|
|
10082
|
+
}
|
|
9994
10083
|
if (this.above != above)
|
|
9995
|
-
this.dom.style.marginTop = (this.above = above) ? above + "px" : "";
|
|
10084
|
+
this.dom.style.marginTop = (this.above = above) ? above / view.scaleY + "px" : "";
|
|
9996
10085
|
if (!sameMarkers(this.markers, markers))
|
|
9997
10086
|
this.setMarkers(view, markers);
|
|
9998
10087
|
}
|
package/dist/index.d.cts
CHANGED
|
@@ -802,6 +802,16 @@ declare class EditorView {
|
|
|
802
802
|
bottom: number;
|
|
803
803
|
};
|
|
804
804
|
/**
|
|
805
|
+
If the editor is transformed with CSS, this provides the scale
|
|
806
|
+
along the X axis. Otherwise, it will just be 1. Note that
|
|
807
|
+
transforms other than translation and scaling are not supported.
|
|
808
|
+
*/
|
|
809
|
+
get scaleX(): number;
|
|
810
|
+
/**
|
|
811
|
+
Provide the CSS transformed scale along the Y axis.
|
|
812
|
+
*/
|
|
813
|
+
get scaleY(): number;
|
|
814
|
+
/**
|
|
805
815
|
Find the text line or block widget at the given vertical
|
|
806
816
|
position (which is interpreted as relative to the [top of the
|
|
807
817
|
document](https://codemirror.net/6/docs/ref/#view.EditorView.documentTop)).
|
|
@@ -1653,6 +1663,9 @@ declare function tooltips(config?: {
|
|
|
1653
1663
|
On iOS, which at the time of writing still doesn't properly
|
|
1654
1664
|
support fixed positioning, the library always uses absolute
|
|
1655
1665
|
positioning.
|
|
1666
|
+
|
|
1667
|
+
If the tooltip parent element sits in a transformed element, the
|
|
1668
|
+
library also falls back to absolute positioning.
|
|
1656
1669
|
*/
|
|
1657
1670
|
position?: "fixed" | "absolute";
|
|
1658
1671
|
/**
|
package/dist/index.d.ts
CHANGED
|
@@ -802,6 +802,16 @@ declare class EditorView {
|
|
|
802
802
|
bottom: number;
|
|
803
803
|
};
|
|
804
804
|
/**
|
|
805
|
+
If the editor is transformed with CSS, this provides the scale
|
|
806
|
+
along the X axis. Otherwise, it will just be 1. Note that
|
|
807
|
+
transforms other than translation and scaling are not supported.
|
|
808
|
+
*/
|
|
809
|
+
get scaleX(): number;
|
|
810
|
+
/**
|
|
811
|
+
Provide the CSS transformed scale along the Y axis.
|
|
812
|
+
*/
|
|
813
|
+
get scaleY(): number;
|
|
814
|
+
/**
|
|
805
815
|
Find the text line or block widget at the given vertical
|
|
806
816
|
position (which is interpreted as relative to the [top of the
|
|
807
817
|
document](https://codemirror.net/6/docs/ref/#view.EditorView.documentTop)).
|
|
@@ -1653,6 +1663,9 @@ declare function tooltips(config?: {
|
|
|
1653
1663
|
On iOS, which at the time of writing still doesn't properly
|
|
1654
1664
|
support fixed positioning, the library always uses absolute
|
|
1655
1665
|
positioning.
|
|
1666
|
+
|
|
1667
|
+
If the tooltip parent element sits in a transformed element, the
|
|
1668
|
+
library also falls back to absolute positioning.
|
|
1656
1669
|
*/
|
|
1657
1670
|
position?: "fixed" | "absolute";
|
|
1658
1671
|
/**
|
package/dist/index.js
CHANGED
|
@@ -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 };
|
|
@@ -2777,7 +2780,7 @@ class DocView extends ContentView {
|
|
|
2777
2780
|
// messes with the scroll position during DOM mutation (though
|
|
2778
2781
|
// no relayout is triggered and I cannot imagine how it can
|
|
2779
2782
|
// recompute the scroll position without a layout)
|
|
2780
|
-
this.dom.style.height = this.view.viewState.contentHeight + "px";
|
|
2783
|
+
this.dom.style.height = this.view.viewState.contentHeight / this.view.scaleY + "px";
|
|
2781
2784
|
this.dom.style.flexBasis = this.minWidth ? this.minWidth + "px" : "";
|
|
2782
2785
|
// Chrome will sometimes, when DOM mutations occur directly
|
|
2783
2786
|
// around the selection, get confused and report a different
|
|
@@ -2849,7 +2852,7 @@ class DocView extends ContentView {
|
|
|
2849
2852
|
}
|
|
2850
2853
|
fixCompositionDOM(composition) {
|
|
2851
2854
|
let fix = (dom, cView) => {
|
|
2852
|
-
cView.flags |= 8 /* ViewFlag.Composition
|
|
2855
|
+
cView.flags |= 8 /* ViewFlag.Composition */ | (cView.children.some(c => c.flags & 7 /* ViewFlag.Dirty */) ? 1 /* ViewFlag.ChildDirty */ : 0);
|
|
2853
2856
|
this.markedForComposition.add(cView);
|
|
2854
2857
|
let prev = ContentView.get(dom);
|
|
2855
2858
|
if (prev != cView) {
|
|
@@ -3115,7 +3118,7 @@ class DocView extends ContentView {
|
|
|
3115
3118
|
let next = i == vs.viewports.length ? null : vs.viewports[i];
|
|
3116
3119
|
let end = next ? next.from - 1 : this.length;
|
|
3117
3120
|
if (end > pos) {
|
|
3118
|
-
let height = vs.lineBlockAt(end).bottom - vs.lineBlockAt(pos).top;
|
|
3121
|
+
let height = (vs.lineBlockAt(end).bottom - vs.lineBlockAt(pos).top) / this.view.scaleY;
|
|
3119
3122
|
deco.push(Decoration.replace({
|
|
3120
3123
|
widget: new BlockGapWidget(height),
|
|
3121
3124
|
block: true,
|
|
@@ -5271,8 +5274,10 @@ class LineGap {
|
|
|
5271
5274
|
}
|
|
5272
5275
|
return true;
|
|
5273
5276
|
}
|
|
5274
|
-
draw(wrapping) {
|
|
5275
|
-
return Decoration.replace({
|
|
5277
|
+
draw(viewState, wrapping) {
|
|
5278
|
+
return Decoration.replace({
|
|
5279
|
+
widget: new LineGapWidget(this.size * (wrapping ? viewState.scaleY : viewState.scaleX), wrapping)
|
|
5280
|
+
}).range(this.from, this.to);
|
|
5276
5281
|
}
|
|
5277
5282
|
}
|
|
5278
5283
|
class LineGapWidget extends WidgetType {
|
|
@@ -5302,14 +5307,18 @@ class ViewState {
|
|
|
5302
5307
|
// These are contentDOM-local coordinates
|
|
5303
5308
|
this.pixelViewport = { left: 0, right: window.innerWidth, top: 0, bottom: 0 };
|
|
5304
5309
|
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;
|
|
5310
|
+
this.paddingTop = 0; // Padding above the document, scaled
|
|
5311
|
+
this.paddingBottom = 0; // Padding below the document, scaled
|
|
5312
|
+
this.contentDOMWidth = 0; // contentDOM.getBoundingClientRect().width
|
|
5313
|
+
this.contentDOMHeight = 0; // contentDOM.getBoundingClientRect().height
|
|
5314
|
+
this.editorHeight = 0; // scrollDOM.clientHeight, unscaled
|
|
5315
|
+
this.editorWidth = 0; // scrollDOM.clientWidth, unscaled
|
|
5316
|
+
this.scrollTop = 0; // Last seen scrollDOM.scrollTop, scaled
|
|
5312
5317
|
this.scrolledToBottom = true;
|
|
5318
|
+
// The CSS-transformation scale of the editor (transformed size /
|
|
5319
|
+
// concrete size)
|
|
5320
|
+
this.scaleX = 1;
|
|
5321
|
+
this.scaleY = 1;
|
|
5313
5322
|
// The vertical position (document-relative) to which to anchor the
|
|
5314
5323
|
// scroll position. -1 means anchor to the end of the document.
|
|
5315
5324
|
this.scrollAnchorPos = 0;
|
|
@@ -5343,7 +5352,7 @@ class ViewState {
|
|
|
5343
5352
|
this.updateViewportLines();
|
|
5344
5353
|
this.updateForViewport();
|
|
5345
5354
|
this.lineGaps = this.ensureLineGaps([]);
|
|
5346
|
-
this.lineGapDeco = Decoration.set(this.lineGaps.map(gap => gap.draw(false)));
|
|
5355
|
+
this.lineGapDeco = Decoration.set(this.lineGaps.map(gap => gap.draw(this, false)));
|
|
5347
5356
|
this.computeVisibleRanges();
|
|
5348
5357
|
}
|
|
5349
5358
|
updateForViewport() {
|
|
@@ -5415,8 +5424,23 @@ class ViewState {
|
|
|
5415
5424
|
this.contentDOMHeight = domRect.height;
|
|
5416
5425
|
this.mustMeasureContent = false;
|
|
5417
5426
|
let result = 0, bias = 0;
|
|
5427
|
+
if (domRect.width && domRect.height) {
|
|
5428
|
+
let scaleX = domRect.width / dom.offsetWidth;
|
|
5429
|
+
let scaleY = domRect.height / dom.offsetHeight;
|
|
5430
|
+
if (scaleX > 0.995 && scaleX < 1.005)
|
|
5431
|
+
scaleX = 1;
|
|
5432
|
+
if (scaleY > 0.995 && scaleY < 1.005)
|
|
5433
|
+
scaleY = 1;
|
|
5434
|
+
if (this.scaleX != scaleX || this.scaleY != scaleY) {
|
|
5435
|
+
this.scaleX = scaleX;
|
|
5436
|
+
this.scaleY = scaleY;
|
|
5437
|
+
result |= 8 /* UpdateFlag.Geometry */;
|
|
5438
|
+
refresh = measureContent = true;
|
|
5439
|
+
}
|
|
5440
|
+
}
|
|
5418
5441
|
// Vertical padding
|
|
5419
|
-
let paddingTop = parseInt(style.paddingTop) || 0
|
|
5442
|
+
let paddingTop = (parseInt(style.paddingTop) || 0) * this.scaleY;
|
|
5443
|
+
let paddingBottom = (parseInt(style.paddingBottom) || 0) * this.scaleY;
|
|
5420
5444
|
if (this.paddingTop != paddingTop || this.paddingBottom != paddingBottom) {
|
|
5421
5445
|
this.paddingTop = paddingTop;
|
|
5422
5446
|
this.paddingBottom = paddingBottom;
|
|
@@ -5428,9 +5452,10 @@ class ViewState {
|
|
|
5428
5452
|
this.editorWidth = view.scrollDOM.clientWidth;
|
|
5429
5453
|
result |= 8 /* UpdateFlag.Geometry */;
|
|
5430
5454
|
}
|
|
5431
|
-
|
|
5455
|
+
let scrollTop = view.scrollDOM.scrollTop * this.scaleY;
|
|
5456
|
+
if (this.scrollTop != scrollTop) {
|
|
5432
5457
|
this.scrollAnchorHeight = -1;
|
|
5433
|
-
this.scrollTop =
|
|
5458
|
+
this.scrollTop = scrollTop;
|
|
5434
5459
|
}
|
|
5435
5460
|
this.scrolledToBottom = isScrolledToBottom(view.scrollDOM);
|
|
5436
5461
|
// Pixel viewport
|
|
@@ -5651,7 +5676,7 @@ class ViewState {
|
|
|
5651
5676
|
updateLineGaps(gaps) {
|
|
5652
5677
|
if (!LineGap.same(gaps, this.lineGaps)) {
|
|
5653
5678
|
this.lineGaps = gaps;
|
|
5654
|
-
this.lineGapDeco = Decoration.set(gaps.map(gap => gap.draw(this.heightOracle.lineWrapping)));
|
|
5679
|
+
this.lineGapDeco = Decoration.set(gaps.map(gap => gap.draw(this, this.heightOracle.lineWrapping)));
|
|
5655
5680
|
}
|
|
5656
5681
|
}
|
|
5657
5682
|
computeVisibleRanges() {
|
|
@@ -7062,9 +7087,9 @@ class EditorView {
|
|
|
7062
7087
|
if (flush)
|
|
7063
7088
|
this.observer.forceFlush();
|
|
7064
7089
|
let updated = null;
|
|
7065
|
-
let sDOM = this.scrollDOM,
|
|
7090
|
+
let sDOM = this.scrollDOM, scrollTop = sDOM.scrollTop * this.scaleY;
|
|
7066
7091
|
let { scrollAnchorPos, scrollAnchorHeight } = this.viewState;
|
|
7067
|
-
if (scrollTop
|
|
7092
|
+
if (Math.abs(scrollTop - this.viewState.scrollTop) > 1)
|
|
7068
7093
|
scrollAnchorHeight = -1;
|
|
7069
7094
|
this.viewState.scrollAnchorHeight = -1;
|
|
7070
7095
|
try {
|
|
@@ -7141,7 +7166,8 @@ class EditorView {
|
|
|
7141
7166
|
this.viewState.lineBlockAt(scrollAnchorPos).top;
|
|
7142
7167
|
let diff = newAnchorHeight - scrollAnchorHeight;
|
|
7143
7168
|
if (diff > 1 || diff < -1) {
|
|
7144
|
-
scrollTop =
|
|
7169
|
+
scrollTop = scrollTop + diff;
|
|
7170
|
+
sDOM.scrollTop = scrollTop / this.scaleY;
|
|
7145
7171
|
scrollAnchorHeight = -1;
|
|
7146
7172
|
continue;
|
|
7147
7173
|
}
|
|
@@ -7268,6 +7294,16 @@ class EditorView {
|
|
|
7268
7294
|
return { top: this.viewState.paddingTop, bottom: this.viewState.paddingBottom };
|
|
7269
7295
|
}
|
|
7270
7296
|
/**
|
|
7297
|
+
If the editor is transformed with CSS, this provides the scale
|
|
7298
|
+
along the X axis. Otherwise, it will just be 1. Note that
|
|
7299
|
+
transforms other than translation and scaling are not supported.
|
|
7300
|
+
*/
|
|
7301
|
+
get scaleX() { return this.viewState.scaleX; }
|
|
7302
|
+
/**
|
|
7303
|
+
Provide the CSS transformed scale along the Y axis.
|
|
7304
|
+
*/
|
|
7305
|
+
get scaleY() { return this.viewState.scaleY; }
|
|
7306
|
+
/**
|
|
7271
7307
|
Find the text line or block widget at the given vertical
|
|
7272
7308
|
position (which is interpreted as relative to the [top of the
|
|
7273
7309
|
document](https://codemirror.net/6/docs/ref/#view.EditorView.documentTop)).
|
|
@@ -8058,8 +8094,8 @@ class RectangleMarker {
|
|
|
8058
8094
|
}
|
|
8059
8095
|
function getBase(view) {
|
|
8060
8096
|
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 };
|
|
8097
|
+
let left = view.textDirection == Direction.LTR ? rect.left : rect.right - view.scrollDOM.clientWidth * view.scaleX;
|
|
8098
|
+
return { left: left - view.scrollDOM.scrollLeft * view.scaleX, top: rect.top - view.scrollDOM.scrollTop * view.scaleY };
|
|
8063
8099
|
}
|
|
8064
8100
|
function wrappedLine(view, pos, inside) {
|
|
8065
8101
|
let range = EditorSelection.cursor(pos);
|
|
@@ -8161,6 +8197,8 @@ class LayerView {
|
|
|
8161
8197
|
this.view = view;
|
|
8162
8198
|
this.layer = layer;
|
|
8163
8199
|
this.drawn = [];
|
|
8200
|
+
this.scaleX = 1;
|
|
8201
|
+
this.scaleY = 1;
|
|
8164
8202
|
this.measureReq = { read: this.measure.bind(this), write: this.draw.bind(this) };
|
|
8165
8203
|
this.dom = view.scrollDOM.appendChild(document.createElement("div"));
|
|
8166
8204
|
this.dom.classList.add("cm-layer");
|
|
@@ -8168,6 +8206,7 @@ class LayerView {
|
|
|
8168
8206
|
this.dom.classList.add("cm-layer-above");
|
|
8169
8207
|
if (layer.class)
|
|
8170
8208
|
this.dom.classList.add(layer.class);
|
|
8209
|
+
this.scale();
|
|
8171
8210
|
this.dom.setAttribute("aria-hidden", "true");
|
|
8172
8211
|
this.setOrder(view.state);
|
|
8173
8212
|
view.requestMeasure(this.measureReq);
|
|
@@ -8177,8 +8216,10 @@ class LayerView {
|
|
|
8177
8216
|
update(update) {
|
|
8178
8217
|
if (update.startState.facet(layerOrder) != update.state.facet(layerOrder))
|
|
8179
8218
|
this.setOrder(update.state);
|
|
8180
|
-
if (this.layer.update(update, this.dom) || update.geometryChanged)
|
|
8219
|
+
if (this.layer.update(update, this.dom) || update.geometryChanged) {
|
|
8220
|
+
this.scale();
|
|
8181
8221
|
update.view.requestMeasure(this.measureReq);
|
|
8222
|
+
}
|
|
8182
8223
|
}
|
|
8183
8224
|
setOrder(state) {
|
|
8184
8225
|
let pos = 0, order = state.facet(layerOrder);
|
|
@@ -8189,6 +8230,14 @@ class LayerView {
|
|
|
8189
8230
|
measure() {
|
|
8190
8231
|
return this.layer.markers(this.view);
|
|
8191
8232
|
}
|
|
8233
|
+
scale() {
|
|
8234
|
+
let { scaleX, scaleY } = this.view;
|
|
8235
|
+
if (scaleX != this.scaleX || scaleY != this.scaleY) {
|
|
8236
|
+
this.scaleX = scaleX;
|
|
8237
|
+
this.scaleY = scaleY;
|
|
8238
|
+
this.dom.style.transform = `scale(${1 / scaleX}, ${1 / scaleY})`;
|
|
8239
|
+
}
|
|
8240
|
+
}
|
|
8192
8241
|
draw(markers) {
|
|
8193
8242
|
if (markers.length != this.drawn.length || markers.some((p, i) => !sameMarker(p, this.drawn[i]))) {
|
|
8194
8243
|
let old = this.dom.firstChild, oldI = 0;
|
|
@@ -8358,23 +8407,25 @@ const drawDropCursor = /*@__PURE__*/ViewPlugin.fromClass(class {
|
|
|
8358
8407
|
}
|
|
8359
8408
|
}
|
|
8360
8409
|
readPos() {
|
|
8361
|
-
let
|
|
8362
|
-
let
|
|
8410
|
+
let { view } = this;
|
|
8411
|
+
let pos = view.state.field(dropCursorPos);
|
|
8412
|
+
let rect = pos != null && view.coordsAtPos(pos);
|
|
8363
8413
|
if (!rect)
|
|
8364
8414
|
return null;
|
|
8365
|
-
let outer =
|
|
8415
|
+
let outer = view.scrollDOM.getBoundingClientRect();
|
|
8366
8416
|
return {
|
|
8367
|
-
left: rect.left - outer.left +
|
|
8368
|
-
top: rect.top - outer.top +
|
|
8417
|
+
left: rect.left - outer.left + view.scrollDOM.scrollLeft * view.scaleX,
|
|
8418
|
+
top: rect.top - outer.top + view.scrollDOM.scrollTop * view.scaleY,
|
|
8369
8419
|
height: rect.bottom - rect.top
|
|
8370
8420
|
};
|
|
8371
8421
|
}
|
|
8372
8422
|
drawCursor(pos) {
|
|
8373
8423
|
if (this.cursor) {
|
|
8424
|
+
let { scaleX, scaleY } = this.view;
|
|
8374
8425
|
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";
|
|
8426
|
+
this.cursor.style.left = pos.left / scaleX + "px";
|
|
8427
|
+
this.cursor.style.top = pos.top / scaleY + "px";
|
|
8428
|
+
this.cursor.style.height = pos.height / scaleY + "px";
|
|
8378
8429
|
}
|
|
8379
8430
|
else {
|
|
8380
8431
|
this.cursor.style.left = "-100000px";
|
|
@@ -8616,7 +8667,9 @@ function specialCharPlugin() {
|
|
|
8616
8667
|
if (code == 9) {
|
|
8617
8668
|
let line = doc.lineAt(pos);
|
|
8618
8669
|
let size = view.state.tabSize, col = countColumn(line.text, size, pos - line.from);
|
|
8619
|
-
return Decoration.replace({
|
|
8670
|
+
return Decoration.replace({
|
|
8671
|
+
widget: new TabWidget((size - (col % size)) * this.view.defaultCharacterWidth / this.view.scaleX)
|
|
8672
|
+
});
|
|
8620
8673
|
}
|
|
8621
8674
|
return this.decorationCache[code] ||
|
|
8622
8675
|
(this.decorationCache[code] = Decoration.replace({ widget: new SpecialCharWidget(conf, code) }));
|
|
@@ -8693,7 +8746,8 @@ const plugin = /*@__PURE__*/ViewPlugin.fromClass(class {
|
|
|
8693
8746
|
}
|
|
8694
8747
|
update(update) {
|
|
8695
8748
|
let { view } = update;
|
|
8696
|
-
let height = view.viewState.editorHeight
|
|
8749
|
+
let height = view.viewState.editorHeight * view.scaleY -
|
|
8750
|
+
view.defaultLineHeight - view.documentPadding.top - 0.5;
|
|
8697
8751
|
if (height >= 0 && height != this.height) {
|
|
8698
8752
|
this.height = height;
|
|
8699
8753
|
this.attrs = { style: `padding-bottom: ${height}px` };
|
|
@@ -8990,6 +9044,7 @@ const tooltipPlugin = /*@__PURE__*/ViewPlugin.fromClass(class {
|
|
|
8990
9044
|
constructor(view) {
|
|
8991
9045
|
this.view = view;
|
|
8992
9046
|
this.inView = true;
|
|
9047
|
+
this.madeAbsolute = false;
|
|
8993
9048
|
this.lastTransaction = 0;
|
|
8994
9049
|
this.measureTimeout = -1;
|
|
8995
9050
|
let config = view.state.facet(tooltipConfig);
|
|
@@ -9041,7 +9096,7 @@ const tooltipPlugin = /*@__PURE__*/ViewPlugin.fromClass(class {
|
|
|
9041
9096
|
this.observeIntersection();
|
|
9042
9097
|
let shouldMeasure = updated || update.geometryChanged;
|
|
9043
9098
|
let newConfig = update.state.facet(tooltipConfig);
|
|
9044
|
-
if (newConfig.position != this.position) {
|
|
9099
|
+
if (newConfig.position != this.position && !this.madeAbsolute) {
|
|
9045
9100
|
this.position = newConfig.position;
|
|
9046
9101
|
for (let t of this.manager.tooltipViews)
|
|
9047
9102
|
t.dom.style.position = this.position;
|
|
@@ -9089,6 +9144,27 @@ const tooltipPlugin = /*@__PURE__*/ViewPlugin.fromClass(class {
|
|
|
9089
9144
|
}
|
|
9090
9145
|
readMeasure() {
|
|
9091
9146
|
let editor = this.view.dom.getBoundingClientRect();
|
|
9147
|
+
let scaleX = 1, scaleY = 1, makeAbsolute = false;
|
|
9148
|
+
if (this.position == "fixed") {
|
|
9149
|
+
let views = this.manager.tooltipViews;
|
|
9150
|
+
// When the dialog's offset parent isn't the body, we are
|
|
9151
|
+
// probably in a transformed container, and should use absolute
|
|
9152
|
+
// positioning instead, since fixed positioning inside a
|
|
9153
|
+
// transform works in a very broken way.
|
|
9154
|
+
makeAbsolute = views.length > 0 && views[0].dom.offsetParent != this.container.ownerDocument.body;
|
|
9155
|
+
}
|
|
9156
|
+
if (makeAbsolute || this.position == "absolute") {
|
|
9157
|
+
if (this.parent) {
|
|
9158
|
+
let rect = this.parent.getBoundingClientRect();
|
|
9159
|
+
if (rect.width && rect.height) {
|
|
9160
|
+
scaleX = rect.width / this.parent.offsetWidth;
|
|
9161
|
+
scaleY = rect.height / this.parent.offsetHeight;
|
|
9162
|
+
}
|
|
9163
|
+
}
|
|
9164
|
+
else {
|
|
9165
|
+
({ scaleX, scaleY } = this.view.viewState);
|
|
9166
|
+
}
|
|
9167
|
+
}
|
|
9092
9168
|
return {
|
|
9093
9169
|
editor,
|
|
9094
9170
|
parent: this.parent ? this.container.getBoundingClientRect() : editor,
|
|
@@ -9098,11 +9174,18 @@ const tooltipPlugin = /*@__PURE__*/ViewPlugin.fromClass(class {
|
|
|
9098
9174
|
}),
|
|
9099
9175
|
size: this.manager.tooltipViews.map(({ dom }) => dom.getBoundingClientRect()),
|
|
9100
9176
|
space: this.view.state.facet(tooltipConfig).tooltipSpace(this.view),
|
|
9177
|
+
scaleX, scaleY, makeAbsolute
|
|
9101
9178
|
};
|
|
9102
9179
|
}
|
|
9103
9180
|
writeMeasure(measured) {
|
|
9104
9181
|
var _a;
|
|
9105
|
-
|
|
9182
|
+
if (measured.makeAbsolute) {
|
|
9183
|
+
this.madeAbsolute = true;
|
|
9184
|
+
this.position = "absolute";
|
|
9185
|
+
for (let t of this.manager.tooltipViews)
|
|
9186
|
+
t.dom.style.position = "absolute";
|
|
9187
|
+
}
|
|
9188
|
+
let { editor, space, scaleX, scaleY } = measured;
|
|
9106
9189
|
let others = [];
|
|
9107
9190
|
for (let i = 0; i < this.manager.tooltips.length; i++) {
|
|
9108
9191
|
let tooltip = this.manager.tooltips[i], tView = this.manager.tooltipViews[i], { dom } = tView;
|
|
@@ -9135,7 +9218,7 @@ const tooltipPlugin = /*@__PURE__*/ViewPlugin.fromClass(class {
|
|
|
9135
9218
|
continue;
|
|
9136
9219
|
}
|
|
9137
9220
|
knownHeight.set(tView, height);
|
|
9138
|
-
dom.style.height = (height = spaceVert) + "px";
|
|
9221
|
+
dom.style.height = (height = spaceVert) / scaleY + "px";
|
|
9139
9222
|
}
|
|
9140
9223
|
else if (dom.style.height) {
|
|
9141
9224
|
dom.style.height = "";
|
|
@@ -9147,15 +9230,17 @@ const tooltipPlugin = /*@__PURE__*/ViewPlugin.fromClass(class {
|
|
|
9147
9230
|
if (r.left < right && r.right > left && r.top < top + height && r.bottom > top)
|
|
9148
9231
|
top = above ? r.top - height - 2 - arrowHeight : r.bottom + arrowHeight + 2;
|
|
9149
9232
|
if (this.position == "absolute") {
|
|
9150
|
-
dom.style.top = (top - measured.parent.top) + "px";
|
|
9151
|
-
dom.style.left = (left - measured.parent.left) + "px";
|
|
9233
|
+
dom.style.top = (top - measured.parent.top) / scaleY + "px";
|
|
9234
|
+
dom.style.left = (left - measured.parent.left) / scaleX + "px";
|
|
9152
9235
|
}
|
|
9153
9236
|
else {
|
|
9154
|
-
dom.style.top = top + "px";
|
|
9155
|
-
dom.style.left = left + "px";
|
|
9237
|
+
dom.style.top = top / scaleY + "px";
|
|
9238
|
+
dom.style.left = left / scaleX + "px";
|
|
9239
|
+
}
|
|
9240
|
+
if (arrow) {
|
|
9241
|
+
let arrowLeft = pos.left + (ltr ? offset.x : -offset.x) - (left + 14 /* Arrow.Offset */ - 7 /* Arrow.Size */);
|
|
9242
|
+
arrow.style.left = arrowLeft / scaleX + "px";
|
|
9156
9243
|
}
|
|
9157
|
-
if (arrow)
|
|
9158
|
-
arrow.style.left = `${pos.left + (ltr ? offset.x : -offset.x) - (left + 14 /* Arrow.Offset */ - 7 /* Arrow.Size */)}px`;
|
|
9159
9244
|
if (tView.overlap !== true)
|
|
9160
9245
|
others.push({ left, top, right, bottom: top + height });
|
|
9161
9246
|
dom.classList.toggle("cm-tooltip-above", above);
|
|
@@ -9757,7 +9842,7 @@ const gutterView = /*@__PURE__*/ViewPlugin.fromClass(class {
|
|
|
9757
9842
|
this.dom = document.createElement("div");
|
|
9758
9843
|
this.dom.className = "cm-gutters";
|
|
9759
9844
|
this.dom.setAttribute("aria-hidden", "true");
|
|
9760
|
-
this.dom.style.minHeight = this.view.contentHeight + "px";
|
|
9845
|
+
this.dom.style.minHeight = (this.view.contentHeight / this.view.scaleY) + "px";
|
|
9761
9846
|
this.gutters = view.state.facet(activeGutters).map(conf => new SingleGutterView(view, conf));
|
|
9762
9847
|
for (let gutter of this.gutters)
|
|
9763
9848
|
this.dom.appendChild(gutter.dom);
|
|
@@ -9867,7 +9952,9 @@ const gutterView = /*@__PURE__*/ViewPlugin.fromClass(class {
|
|
|
9867
9952
|
let value = view.plugin(plugin);
|
|
9868
9953
|
if (!value || value.gutters.length == 0 || !value.fixed)
|
|
9869
9954
|
return null;
|
|
9870
|
-
return view.textDirection == Direction.LTR
|
|
9955
|
+
return view.textDirection == Direction.LTR
|
|
9956
|
+
? { left: value.dom.offsetWidth * view.scaleX }
|
|
9957
|
+
: { right: value.dom.offsetWidth * view.scaleX };
|
|
9871
9958
|
})
|
|
9872
9959
|
});
|
|
9873
9960
|
function asArray(val) { return (Array.isArray(val) ? val : [val]); }
|
|
@@ -9984,10 +10071,12 @@ class GutterElement {
|
|
|
9984
10071
|
this.update(view, height, above, markers);
|
|
9985
10072
|
}
|
|
9986
10073
|
update(view, height, above, markers) {
|
|
9987
|
-
if (this.height != height)
|
|
9988
|
-
this.
|
|
10074
|
+
if (this.height != height) {
|
|
10075
|
+
this.height = height;
|
|
10076
|
+
this.dom.style.height = height / view.scaleY + "px";
|
|
10077
|
+
}
|
|
9989
10078
|
if (this.above != above)
|
|
9990
|
-
this.dom.style.marginTop = (this.above = above) ? above + "px" : "";
|
|
10079
|
+
this.dom.style.marginTop = (this.above = above) ? above / view.scaleY + "px" : "";
|
|
9991
10080
|
if (!sameMarkers(this.markers, markers))
|
|
9992
10081
|
this.setMarkers(view, markers);
|
|
9993
10082
|
}
|