@codemirror/view 6.37.1 → 6.38.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 +14 -0
- package/dist/index.cjs +71 -22
- package/dist/index.d.cts +6 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +71 -22
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,17 @@
|
|
|
1
|
+
## 6.38.0 (2025-06-27)
|
|
2
|
+
|
|
3
|
+
### New features
|
|
4
|
+
|
|
5
|
+
Gutters can now specify that they should be displayed after the content (which would be to the right in a left-to-right layout).
|
|
6
|
+
|
|
7
|
+
## 6.37.2 (2025-06-12)
|
|
8
|
+
|
|
9
|
+
### Bug fixes
|
|
10
|
+
|
|
11
|
+
Fix an issue where moving the cursor vertically from the one-but-last character on a line would sometimes move incorrectly on Safari.
|
|
12
|
+
|
|
13
|
+
Fix an issue causing coordinates between lines of text to sometimes be inappropriately placed at the end of the line by `posAtCoords`.
|
|
14
|
+
|
|
1
15
|
## 6.37.1 (2025-05-30)
|
|
2
16
|
|
|
3
17
|
### Bug fixes
|
package/dist/index.cjs
CHANGED
|
@@ -3479,8 +3479,7 @@ function domPosAtCoords(parent, x, y) {
|
|
|
3479
3479
|
closestRect = rect;
|
|
3480
3480
|
closestX = dx;
|
|
3481
3481
|
closestY = dy;
|
|
3482
|
-
|
|
3483
|
-
closestOverlap = !side || (side > 0 ? i < rects.length - 1 : i > 0);
|
|
3482
|
+
closestOverlap = !dx ? true : x < rect.left ? i > 0 : i < rects.length - 1;
|
|
3484
3483
|
}
|
|
3485
3484
|
if (dx == 0) {
|
|
3486
3485
|
if (y > rect.bottom && (!aboveRect || aboveRect.bottom < rect.bottom)) {
|
|
@@ -3656,13 +3655,24 @@ function posAtCoordsImprecise(view, contentRect, block, x, y) {
|
|
|
3656
3655
|
// line before. This is used to detect such a result so that it can be
|
|
3657
3656
|
// ignored (issue #401).
|
|
3658
3657
|
function isSuspiciousSafariCaretResult(node, offset, x) {
|
|
3659
|
-
let len;
|
|
3658
|
+
let len, scan = node;
|
|
3660
3659
|
if (node.nodeType != 3 || offset != (len = node.nodeValue.length))
|
|
3661
3660
|
return false;
|
|
3662
|
-
for (
|
|
3663
|
-
|
|
3661
|
+
for (;;) { // Check that there is no content after this node
|
|
3662
|
+
let next = scan.nextSibling;
|
|
3663
|
+
if (next) {
|
|
3664
|
+
if (next.nodeName == "BR")
|
|
3665
|
+
break;
|
|
3664
3666
|
return false;
|
|
3665
|
-
|
|
3667
|
+
}
|
|
3668
|
+
else {
|
|
3669
|
+
let parent = scan.parentNode;
|
|
3670
|
+
if (!parent || parent.nodeName == "DIV")
|
|
3671
|
+
break;
|
|
3672
|
+
scan = parent;
|
|
3673
|
+
}
|
|
3674
|
+
}
|
|
3675
|
+
return textRange(node, len - 1, len).getBoundingClientRect().right > x;
|
|
3666
3676
|
}
|
|
3667
3677
|
// Chrome will move positions between lines to the start of the next line
|
|
3668
3678
|
function isSuspiciousChromeCaretResult(node, offset, x) {
|
|
@@ -6581,13 +6591,16 @@ const baseTheme$1 = buildTheme("." + baseThemeID, {
|
|
|
6581
6591
|
display: "flex",
|
|
6582
6592
|
height: "100%",
|
|
6583
6593
|
boxSizing: "border-box",
|
|
6584
|
-
|
|
6585
|
-
zIndex: 200
|
|
6594
|
+
zIndex: 200,
|
|
6586
6595
|
},
|
|
6596
|
+
".cm-gutters-before": { insetInlineStart: 0 },
|
|
6597
|
+
".cm-gutters-after": { insetInlineEnd: 0 },
|
|
6587
6598
|
"&light .cm-gutters": {
|
|
6588
6599
|
backgroundColor: "#f5f5f5",
|
|
6589
6600
|
color: "#6c6c6c",
|
|
6590
|
-
|
|
6601
|
+
border: "0px solid #ddd",
|
|
6602
|
+
"&.cm-gutters-before": { borderRightWidth: "1px" },
|
|
6603
|
+
"&.cm-gutters-after": { borderLeftWidth: "1px" },
|
|
6591
6604
|
},
|
|
6592
6605
|
"&dark .cm-gutters": {
|
|
6593
6606
|
backgroundColor: "#333338",
|
|
@@ -6778,7 +6791,7 @@ class DOMObserver {
|
|
|
6778
6791
|
else
|
|
6779
6792
|
this.flush();
|
|
6780
6793
|
});
|
|
6781
|
-
if (window.EditContext && view.constructor.EDIT_CONTEXT !== false &&
|
|
6794
|
+
if (window.EditContext && browser.android && view.constructor.EDIT_CONTEXT !== false &&
|
|
6782
6795
|
// Chrome <126 doesn't support inverted selections in edit context (#1392)
|
|
6783
6796
|
!(browser.chrome && browser.chrome_version < 126)) {
|
|
6784
6797
|
this.editContext = new EditContextManager(view);
|
|
@@ -10858,7 +10871,8 @@ const defaults = {
|
|
|
10858
10871
|
lineMarkerChange: null,
|
|
10859
10872
|
initialSpacer: null,
|
|
10860
10873
|
updateSpacer: null,
|
|
10861
|
-
domEventHandlers: {}
|
|
10874
|
+
domEventHandlers: {},
|
|
10875
|
+
side: "before"
|
|
10862
10876
|
};
|
|
10863
10877
|
const activeGutters = state.Facet.define();
|
|
10864
10878
|
/**
|
|
@@ -10892,15 +10906,20 @@ function gutters(config) {
|
|
|
10892
10906
|
const gutterView = ViewPlugin.fromClass(class {
|
|
10893
10907
|
constructor(view) {
|
|
10894
10908
|
this.view = view;
|
|
10909
|
+
this.domAfter = null;
|
|
10895
10910
|
this.prevViewport = view.viewport;
|
|
10896
10911
|
this.dom = document.createElement("div");
|
|
10897
|
-
this.dom.className = "cm-gutters";
|
|
10912
|
+
this.dom.className = "cm-gutters cm-gutters-before";
|
|
10898
10913
|
this.dom.setAttribute("aria-hidden", "true");
|
|
10899
10914
|
this.dom.style.minHeight = (this.view.contentHeight / this.view.scaleY) + "px";
|
|
10900
10915
|
this.gutters = view.state.facet(activeGutters).map(conf => new SingleGutterView(view, conf));
|
|
10901
|
-
for (let gutter of this.gutters)
|
|
10902
|
-
this.dom.appendChild(gutter.dom);
|
|
10903
10916
|
this.fixed = !view.state.facet(unfixGutters);
|
|
10917
|
+
for (let gutter of this.gutters) {
|
|
10918
|
+
if (gutter.config.side == "after")
|
|
10919
|
+
this.getDOMAfter().appendChild(gutter.dom);
|
|
10920
|
+
else
|
|
10921
|
+
this.dom.appendChild(gutter.dom);
|
|
10922
|
+
}
|
|
10904
10923
|
if (this.fixed) {
|
|
10905
10924
|
// FIXME IE11 fallback, which doesn't support position: sticky,
|
|
10906
10925
|
// by using position: relative + event handlers that realign the
|
|
@@ -10910,6 +10929,17 @@ const gutterView = ViewPlugin.fromClass(class {
|
|
|
10910
10929
|
this.syncGutters(false);
|
|
10911
10930
|
view.scrollDOM.insertBefore(this.dom, view.contentDOM);
|
|
10912
10931
|
}
|
|
10932
|
+
getDOMAfter() {
|
|
10933
|
+
if (!this.domAfter) {
|
|
10934
|
+
this.domAfter = document.createElement("div");
|
|
10935
|
+
this.domAfter.className = "cm-gutters cm-gutters-after";
|
|
10936
|
+
this.domAfter.setAttribute("aria-hidden", "true");
|
|
10937
|
+
this.domAfter.style.minHeight = (this.view.contentHeight / this.view.scaleY) + "px";
|
|
10938
|
+
this.domAfter.style.position = this.fixed ? "sticky" : "";
|
|
10939
|
+
this.view.scrollDOM.appendChild(this.domAfter);
|
|
10940
|
+
}
|
|
10941
|
+
return this.domAfter;
|
|
10942
|
+
}
|
|
10913
10943
|
update(update) {
|
|
10914
10944
|
if (this.updateGutters(update)) {
|
|
10915
10945
|
// Detach during sync when the viewport changed significantly
|
|
@@ -10920,18 +10950,26 @@ const gutterView = ViewPlugin.fromClass(class {
|
|
|
10920
10950
|
this.syncGutters(vpOverlap < (vpB.to - vpB.from) * 0.8);
|
|
10921
10951
|
}
|
|
10922
10952
|
if (update.geometryChanged) {
|
|
10923
|
-
|
|
10953
|
+
let min = (this.view.contentHeight / this.view.scaleY) + "px";
|
|
10954
|
+
this.dom.style.minHeight = min;
|
|
10955
|
+
if (this.domAfter)
|
|
10956
|
+
this.domAfter.style.minHeight = min;
|
|
10924
10957
|
}
|
|
10925
10958
|
if (this.view.state.facet(unfixGutters) != !this.fixed) {
|
|
10926
10959
|
this.fixed = !this.fixed;
|
|
10927
10960
|
this.dom.style.position = this.fixed ? "sticky" : "";
|
|
10961
|
+
if (this.domAfter)
|
|
10962
|
+
this.domAfter.style.position = this.fixed ? "sticky" : "";
|
|
10928
10963
|
}
|
|
10929
10964
|
this.prevViewport = update.view.viewport;
|
|
10930
10965
|
}
|
|
10931
10966
|
syncGutters(detach) {
|
|
10932
10967
|
let after = this.dom.nextSibling;
|
|
10933
|
-
if (detach)
|
|
10968
|
+
if (detach) {
|
|
10934
10969
|
this.dom.remove();
|
|
10970
|
+
if (this.domAfter)
|
|
10971
|
+
this.domAfter.remove();
|
|
10972
|
+
}
|
|
10935
10973
|
let lineClasses = state.RangeSet.iter(this.view.state.facet(gutterLineClass), this.view.viewport.from);
|
|
10936
10974
|
let classSet = [];
|
|
10937
10975
|
let contexts = this.gutters.map(gutter => new UpdateContext(gutter, this.view.viewport, -this.view.documentPadding.top));
|
|
@@ -10965,8 +11003,11 @@ const gutterView = ViewPlugin.fromClass(class {
|
|
|
10965
11003
|
}
|
|
10966
11004
|
for (let cx of contexts)
|
|
10967
11005
|
cx.finish();
|
|
10968
|
-
if (detach)
|
|
11006
|
+
if (detach) {
|
|
10969
11007
|
this.view.scrollDOM.insertBefore(this.dom, after);
|
|
11008
|
+
if (this.domAfter)
|
|
11009
|
+
this.view.scrollDOM.appendChild(this.domAfter);
|
|
11010
|
+
}
|
|
10970
11011
|
}
|
|
10971
11012
|
updateGutters(update) {
|
|
10972
11013
|
let prev = update.startState.facet(activeGutters), cur = update.state.facet(activeGutters);
|
|
@@ -10995,8 +11036,12 @@ const gutterView = ViewPlugin.fromClass(class {
|
|
|
10995
11036
|
if (gutters.indexOf(g) < 0)
|
|
10996
11037
|
g.destroy();
|
|
10997
11038
|
}
|
|
10998
|
-
for (let g of gutters)
|
|
10999
|
-
|
|
11039
|
+
for (let g of gutters) {
|
|
11040
|
+
if (g.config.side == "after")
|
|
11041
|
+
this.getDOMAfter().appendChild(g.dom);
|
|
11042
|
+
else
|
|
11043
|
+
this.dom.appendChild(g.dom);
|
|
11044
|
+
}
|
|
11000
11045
|
this.gutters = gutters;
|
|
11001
11046
|
}
|
|
11002
11047
|
return change;
|
|
@@ -11005,15 +11050,18 @@ const gutterView = ViewPlugin.fromClass(class {
|
|
|
11005
11050
|
for (let view of this.gutters)
|
|
11006
11051
|
view.destroy();
|
|
11007
11052
|
this.dom.remove();
|
|
11053
|
+
if (this.domAfter)
|
|
11054
|
+
this.domAfter.remove();
|
|
11008
11055
|
}
|
|
11009
11056
|
}, {
|
|
11010
11057
|
provide: plugin => EditorView.scrollMargins.of(view => {
|
|
11011
11058
|
let value = view.plugin(plugin);
|
|
11012
11059
|
if (!value || value.gutters.length == 0 || !value.fixed)
|
|
11013
11060
|
return null;
|
|
11061
|
+
let before = value.dom.offsetWidth * view.scaleX, after = value.domAfter ? value.domAfter.offsetWidth * view.scaleX : 0;
|
|
11014
11062
|
return view.textDirection == exports.Direction.LTR
|
|
11015
|
-
? { left:
|
|
11016
|
-
: { right:
|
|
11063
|
+
? { left: before, right: after }
|
|
11064
|
+
: { right: before, left: after };
|
|
11017
11065
|
})
|
|
11018
11066
|
});
|
|
11019
11067
|
function asArray(val) { return (Array.isArray(val) ? val : [val]); }
|
|
@@ -11255,7 +11303,8 @@ const lineNumberGutter = activeGutters.compute([lineNumberConfig], state => ({
|
|
|
11255
11303
|
let max = formatNumber(update.view, maxLineNumber(update.view.state.doc.lines));
|
|
11256
11304
|
return max == spacer.number ? spacer : new NumberMarker(max);
|
|
11257
11305
|
},
|
|
11258
|
-
domEventHandlers: state.facet(lineNumberConfig).domEventHandlers
|
|
11306
|
+
domEventHandlers: state.facet(lineNumberConfig).domEventHandlers,
|
|
11307
|
+
side: "before"
|
|
11259
11308
|
}));
|
|
11260
11309
|
/**
|
|
11261
11310
|
Create a line number gutter extension.
|
package/dist/index.d.cts
CHANGED
|
@@ -2235,6 +2235,12 @@ interface GutterConfig {
|
|
|
2235
2235
|
Supply event handlers for DOM events on this gutter.
|
|
2236
2236
|
*/
|
|
2237
2237
|
domEventHandlers?: Handlers;
|
|
2238
|
+
/**
|
|
2239
|
+
By default, gutters are shown horizontally before the editor
|
|
2240
|
+
content (to the left in a left-to-right layout). Set this to
|
|
2241
|
+
`"after"` to show a gutter on the other side of the content.
|
|
2242
|
+
*/
|
|
2243
|
+
side?: "before" | "after";
|
|
2238
2244
|
}
|
|
2239
2245
|
/**
|
|
2240
2246
|
Define an editor gutter. The order in which the gutters appear is
|
package/dist/index.d.ts
CHANGED
|
@@ -2235,6 +2235,12 @@ interface GutterConfig {
|
|
|
2235
2235
|
Supply event handlers for DOM events on this gutter.
|
|
2236
2236
|
*/
|
|
2237
2237
|
domEventHandlers?: Handlers;
|
|
2238
|
+
/**
|
|
2239
|
+
By default, gutters are shown horizontally before the editor
|
|
2240
|
+
content (to the left in a left-to-right layout). Set this to
|
|
2241
|
+
`"after"` to show a gutter on the other side of the content.
|
|
2242
|
+
*/
|
|
2243
|
+
side?: "before" | "after";
|
|
2238
2244
|
}
|
|
2239
2245
|
/**
|
|
2240
2246
|
Define an editor gutter. The order in which the gutters appear is
|
package/dist/index.js
CHANGED
|
@@ -3475,8 +3475,7 @@ function domPosAtCoords(parent, x, y) {
|
|
|
3475
3475
|
closestRect = rect;
|
|
3476
3476
|
closestX = dx;
|
|
3477
3477
|
closestY = dy;
|
|
3478
|
-
|
|
3479
|
-
closestOverlap = !side || (side > 0 ? i < rects.length - 1 : i > 0);
|
|
3478
|
+
closestOverlap = !dx ? true : x < rect.left ? i > 0 : i < rects.length - 1;
|
|
3480
3479
|
}
|
|
3481
3480
|
if (dx == 0) {
|
|
3482
3481
|
if (y > rect.bottom && (!aboveRect || aboveRect.bottom < rect.bottom)) {
|
|
@@ -3652,13 +3651,24 @@ function posAtCoordsImprecise(view, contentRect, block, x, y) {
|
|
|
3652
3651
|
// line before. This is used to detect such a result so that it can be
|
|
3653
3652
|
// ignored (issue #401).
|
|
3654
3653
|
function isSuspiciousSafariCaretResult(node, offset, x) {
|
|
3655
|
-
let len;
|
|
3654
|
+
let len, scan = node;
|
|
3656
3655
|
if (node.nodeType != 3 || offset != (len = node.nodeValue.length))
|
|
3657
3656
|
return false;
|
|
3658
|
-
for (
|
|
3659
|
-
|
|
3657
|
+
for (;;) { // Check that there is no content after this node
|
|
3658
|
+
let next = scan.nextSibling;
|
|
3659
|
+
if (next) {
|
|
3660
|
+
if (next.nodeName == "BR")
|
|
3661
|
+
break;
|
|
3660
3662
|
return false;
|
|
3661
|
-
|
|
3663
|
+
}
|
|
3664
|
+
else {
|
|
3665
|
+
let parent = scan.parentNode;
|
|
3666
|
+
if (!parent || parent.nodeName == "DIV")
|
|
3667
|
+
break;
|
|
3668
|
+
scan = parent;
|
|
3669
|
+
}
|
|
3670
|
+
}
|
|
3671
|
+
return textRange(node, len - 1, len).getBoundingClientRect().right > x;
|
|
3662
3672
|
}
|
|
3663
3673
|
// Chrome will move positions between lines to the start of the next line
|
|
3664
3674
|
function isSuspiciousChromeCaretResult(node, offset, x) {
|
|
@@ -6576,13 +6586,16 @@ const baseTheme$1 = /*@__PURE__*/buildTheme("." + baseThemeID, {
|
|
|
6576
6586
|
display: "flex",
|
|
6577
6587
|
height: "100%",
|
|
6578
6588
|
boxSizing: "border-box",
|
|
6579
|
-
|
|
6580
|
-
zIndex: 200
|
|
6589
|
+
zIndex: 200,
|
|
6581
6590
|
},
|
|
6591
|
+
".cm-gutters-before": { insetInlineStart: 0 },
|
|
6592
|
+
".cm-gutters-after": { insetInlineEnd: 0 },
|
|
6582
6593
|
"&light .cm-gutters": {
|
|
6583
6594
|
backgroundColor: "#f5f5f5",
|
|
6584
6595
|
color: "#6c6c6c",
|
|
6585
|
-
|
|
6596
|
+
border: "0px solid #ddd",
|
|
6597
|
+
"&.cm-gutters-before": { borderRightWidth: "1px" },
|
|
6598
|
+
"&.cm-gutters-after": { borderLeftWidth: "1px" },
|
|
6586
6599
|
},
|
|
6587
6600
|
"&dark .cm-gutters": {
|
|
6588
6601
|
backgroundColor: "#333338",
|
|
@@ -6773,7 +6786,7 @@ class DOMObserver {
|
|
|
6773
6786
|
else
|
|
6774
6787
|
this.flush();
|
|
6775
6788
|
});
|
|
6776
|
-
if (window.EditContext && view.constructor.EDIT_CONTEXT !== false &&
|
|
6789
|
+
if (window.EditContext && browser.android && view.constructor.EDIT_CONTEXT !== false &&
|
|
6777
6790
|
// Chrome <126 doesn't support inverted selections in edit context (#1392)
|
|
6778
6791
|
!(browser.chrome && browser.chrome_version < 126)) {
|
|
6779
6792
|
this.editContext = new EditContextManager(view);
|
|
@@ -10853,7 +10866,8 @@ const defaults = {
|
|
|
10853
10866
|
lineMarkerChange: null,
|
|
10854
10867
|
initialSpacer: null,
|
|
10855
10868
|
updateSpacer: null,
|
|
10856
|
-
domEventHandlers: {}
|
|
10869
|
+
domEventHandlers: {},
|
|
10870
|
+
side: "before"
|
|
10857
10871
|
};
|
|
10858
10872
|
const activeGutters = /*@__PURE__*/Facet.define();
|
|
10859
10873
|
/**
|
|
@@ -10887,15 +10901,20 @@ function gutters(config) {
|
|
|
10887
10901
|
const gutterView = /*@__PURE__*/ViewPlugin.fromClass(class {
|
|
10888
10902
|
constructor(view) {
|
|
10889
10903
|
this.view = view;
|
|
10904
|
+
this.domAfter = null;
|
|
10890
10905
|
this.prevViewport = view.viewport;
|
|
10891
10906
|
this.dom = document.createElement("div");
|
|
10892
|
-
this.dom.className = "cm-gutters";
|
|
10907
|
+
this.dom.className = "cm-gutters cm-gutters-before";
|
|
10893
10908
|
this.dom.setAttribute("aria-hidden", "true");
|
|
10894
10909
|
this.dom.style.minHeight = (this.view.contentHeight / this.view.scaleY) + "px";
|
|
10895
10910
|
this.gutters = view.state.facet(activeGutters).map(conf => new SingleGutterView(view, conf));
|
|
10896
|
-
for (let gutter of this.gutters)
|
|
10897
|
-
this.dom.appendChild(gutter.dom);
|
|
10898
10911
|
this.fixed = !view.state.facet(unfixGutters);
|
|
10912
|
+
for (let gutter of this.gutters) {
|
|
10913
|
+
if (gutter.config.side == "after")
|
|
10914
|
+
this.getDOMAfter().appendChild(gutter.dom);
|
|
10915
|
+
else
|
|
10916
|
+
this.dom.appendChild(gutter.dom);
|
|
10917
|
+
}
|
|
10899
10918
|
if (this.fixed) {
|
|
10900
10919
|
// FIXME IE11 fallback, which doesn't support position: sticky,
|
|
10901
10920
|
// by using position: relative + event handlers that realign the
|
|
@@ -10905,6 +10924,17 @@ const gutterView = /*@__PURE__*/ViewPlugin.fromClass(class {
|
|
|
10905
10924
|
this.syncGutters(false);
|
|
10906
10925
|
view.scrollDOM.insertBefore(this.dom, view.contentDOM);
|
|
10907
10926
|
}
|
|
10927
|
+
getDOMAfter() {
|
|
10928
|
+
if (!this.domAfter) {
|
|
10929
|
+
this.domAfter = document.createElement("div");
|
|
10930
|
+
this.domAfter.className = "cm-gutters cm-gutters-after";
|
|
10931
|
+
this.domAfter.setAttribute("aria-hidden", "true");
|
|
10932
|
+
this.domAfter.style.minHeight = (this.view.contentHeight / this.view.scaleY) + "px";
|
|
10933
|
+
this.domAfter.style.position = this.fixed ? "sticky" : "";
|
|
10934
|
+
this.view.scrollDOM.appendChild(this.domAfter);
|
|
10935
|
+
}
|
|
10936
|
+
return this.domAfter;
|
|
10937
|
+
}
|
|
10908
10938
|
update(update) {
|
|
10909
10939
|
if (this.updateGutters(update)) {
|
|
10910
10940
|
// Detach during sync when the viewport changed significantly
|
|
@@ -10915,18 +10945,26 @@ const gutterView = /*@__PURE__*/ViewPlugin.fromClass(class {
|
|
|
10915
10945
|
this.syncGutters(vpOverlap < (vpB.to - vpB.from) * 0.8);
|
|
10916
10946
|
}
|
|
10917
10947
|
if (update.geometryChanged) {
|
|
10918
|
-
|
|
10948
|
+
let min = (this.view.contentHeight / this.view.scaleY) + "px";
|
|
10949
|
+
this.dom.style.minHeight = min;
|
|
10950
|
+
if (this.domAfter)
|
|
10951
|
+
this.domAfter.style.minHeight = min;
|
|
10919
10952
|
}
|
|
10920
10953
|
if (this.view.state.facet(unfixGutters) != !this.fixed) {
|
|
10921
10954
|
this.fixed = !this.fixed;
|
|
10922
10955
|
this.dom.style.position = this.fixed ? "sticky" : "";
|
|
10956
|
+
if (this.domAfter)
|
|
10957
|
+
this.domAfter.style.position = this.fixed ? "sticky" : "";
|
|
10923
10958
|
}
|
|
10924
10959
|
this.prevViewport = update.view.viewport;
|
|
10925
10960
|
}
|
|
10926
10961
|
syncGutters(detach) {
|
|
10927
10962
|
let after = this.dom.nextSibling;
|
|
10928
|
-
if (detach)
|
|
10963
|
+
if (detach) {
|
|
10929
10964
|
this.dom.remove();
|
|
10965
|
+
if (this.domAfter)
|
|
10966
|
+
this.domAfter.remove();
|
|
10967
|
+
}
|
|
10930
10968
|
let lineClasses = RangeSet.iter(this.view.state.facet(gutterLineClass), this.view.viewport.from);
|
|
10931
10969
|
let classSet = [];
|
|
10932
10970
|
let contexts = this.gutters.map(gutter => new UpdateContext(gutter, this.view.viewport, -this.view.documentPadding.top));
|
|
@@ -10960,8 +10998,11 @@ const gutterView = /*@__PURE__*/ViewPlugin.fromClass(class {
|
|
|
10960
10998
|
}
|
|
10961
10999
|
for (let cx of contexts)
|
|
10962
11000
|
cx.finish();
|
|
10963
|
-
if (detach)
|
|
11001
|
+
if (detach) {
|
|
10964
11002
|
this.view.scrollDOM.insertBefore(this.dom, after);
|
|
11003
|
+
if (this.domAfter)
|
|
11004
|
+
this.view.scrollDOM.appendChild(this.domAfter);
|
|
11005
|
+
}
|
|
10965
11006
|
}
|
|
10966
11007
|
updateGutters(update) {
|
|
10967
11008
|
let prev = update.startState.facet(activeGutters), cur = update.state.facet(activeGutters);
|
|
@@ -10990,8 +11031,12 @@ const gutterView = /*@__PURE__*/ViewPlugin.fromClass(class {
|
|
|
10990
11031
|
if (gutters.indexOf(g) < 0)
|
|
10991
11032
|
g.destroy();
|
|
10992
11033
|
}
|
|
10993
|
-
for (let g of gutters)
|
|
10994
|
-
|
|
11034
|
+
for (let g of gutters) {
|
|
11035
|
+
if (g.config.side == "after")
|
|
11036
|
+
this.getDOMAfter().appendChild(g.dom);
|
|
11037
|
+
else
|
|
11038
|
+
this.dom.appendChild(g.dom);
|
|
11039
|
+
}
|
|
10995
11040
|
this.gutters = gutters;
|
|
10996
11041
|
}
|
|
10997
11042
|
return change;
|
|
@@ -11000,15 +11045,18 @@ const gutterView = /*@__PURE__*/ViewPlugin.fromClass(class {
|
|
|
11000
11045
|
for (let view of this.gutters)
|
|
11001
11046
|
view.destroy();
|
|
11002
11047
|
this.dom.remove();
|
|
11048
|
+
if (this.domAfter)
|
|
11049
|
+
this.domAfter.remove();
|
|
11003
11050
|
}
|
|
11004
11051
|
}, {
|
|
11005
11052
|
provide: plugin => EditorView.scrollMargins.of(view => {
|
|
11006
11053
|
let value = view.plugin(plugin);
|
|
11007
11054
|
if (!value || value.gutters.length == 0 || !value.fixed)
|
|
11008
11055
|
return null;
|
|
11056
|
+
let before = value.dom.offsetWidth * view.scaleX, after = value.domAfter ? value.domAfter.offsetWidth * view.scaleX : 0;
|
|
11009
11057
|
return view.textDirection == Direction.LTR
|
|
11010
|
-
? { left:
|
|
11011
|
-
: { right:
|
|
11058
|
+
? { left: before, right: after }
|
|
11059
|
+
: { right: before, left: after };
|
|
11012
11060
|
})
|
|
11013
11061
|
});
|
|
11014
11062
|
function asArray(val) { return (Array.isArray(val) ? val : [val]); }
|
|
@@ -11250,7 +11298,8 @@ const lineNumberGutter = /*@__PURE__*/activeGutters.compute([lineNumberConfig],
|
|
|
11250
11298
|
let max = formatNumber(update.view, maxLineNumber(update.view.state.doc.lines));
|
|
11251
11299
|
return max == spacer.number ? spacer : new NumberMarker(max);
|
|
11252
11300
|
},
|
|
11253
|
-
domEventHandlers: state.facet(lineNumberConfig).domEventHandlers
|
|
11301
|
+
domEventHandlers: state.facet(lineNumberConfig).domEventHandlers,
|
|
11302
|
+
side: "before"
|
|
11254
11303
|
}));
|
|
11255
11304
|
/**
|
|
11256
11305
|
Create a line number gutter extension.
|