@pierre/diffs 1.3.0-beta.8 → 1.3.0-rc.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/dist/components/CodeView.d.ts +12 -12
- package/dist/components/CodeView.d.ts.map +1 -1
- package/dist/components/CodeView.js +51 -43
- package/dist/components/CodeView.js.map +1 -1
- package/dist/components/File.d.ts +7 -2
- package/dist/components/File.d.ts.map +1 -1
- package/dist/components/File.js +36 -8
- package/dist/components/File.js.map +1 -1
- package/dist/components/FileDiff.d.ts +34 -6
- package/dist/components/FileDiff.d.ts.map +1 -1
- package/dist/components/FileDiff.js +198 -17
- package/dist/components/FileDiff.js.map +1 -1
- package/dist/components/FileStream.d.ts.map +1 -1
- package/dist/components/FileStream.js +2 -1
- package/dist/components/FileStream.js.map +1 -1
- package/dist/components/VirtualizedFile.d.ts +2 -1
- package/dist/components/VirtualizedFile.d.ts.map +1 -1
- package/dist/components/VirtualizedFile.js +9 -5
- package/dist/components/VirtualizedFile.js.map +1 -1
- package/dist/components/VirtualizedFileDiff.d.ts +14 -0
- package/dist/components/VirtualizedFileDiff.d.ts.map +1 -1
- package/dist/components/VirtualizedFileDiff.js +61 -3
- package/dist/components/VirtualizedFileDiff.js.map +1 -1
- package/dist/components/Virtualizer.d.ts +14 -2
- package/dist/components/Virtualizer.d.ts.map +1 -1
- package/dist/components/Virtualizer.js +29 -3
- package/dist/components/Virtualizer.js.map +1 -1
- package/dist/edit/index.d.ts +5 -0
- package/dist/edit/index.js +3 -0
- package/dist/editor/command.d.ts +1 -1
- package/dist/editor/command.d.ts.map +1 -1
- package/dist/editor/command.js +11 -0
- package/dist/editor/command.js.map +1 -1
- package/dist/editor/editStack.d.ts +6 -2
- package/dist/editor/editStack.d.ts.map +1 -1
- package/dist/editor/editStack.js +54 -13
- package/dist/editor/editStack.js.map +1 -1
- package/dist/editor/editor.d.ts +51 -23
- package/dist/editor/editor.d.ts.map +1 -1
- package/dist/editor/editor.js +995 -242
- package/dist/editor/editor.js.map +1 -1
- package/dist/editor/editor2.js +1 -1
- package/dist/editor/languages.d.ts +26 -0
- package/dist/editor/languages.d.ts.map +1 -0
- package/dist/editor/languages.js +363 -0
- package/dist/editor/languages.js.map +1 -0
- package/dist/editor/lineAnnotations.d.ts.map +1 -1
- package/dist/editor/lineAnnotations.js +25 -26
- package/dist/editor/lineAnnotations.js.map +1 -1
- package/dist/editor/marker.d.ts +5 -3
- package/dist/editor/marker.d.ts.map +1 -1
- package/dist/editor/marker.js +111 -91
- package/dist/editor/marker.js.map +1 -1
- package/dist/editor/matchBrackets.d.ts +3 -2
- package/dist/editor/matchBrackets.d.ts.map +1 -1
- package/dist/editor/matchBrackets.js +2 -10
- package/dist/editor/matchBrackets.js.map +1 -1
- package/dist/editor/pieceTable.d.ts +2 -1
- package/dist/editor/pieceTable.d.ts.map +1 -1
- package/dist/editor/pieceTable.js +103 -39
- package/dist/editor/pieceTable.js.map +1 -1
- package/dist/editor/platform.js +2 -0
- package/dist/editor/platform.js.map +1 -1
- package/dist/editor/popover.d.ts +25 -5
- package/dist/editor/popover.d.ts.map +1 -1
- package/dist/editor/popover.js +60 -14
- package/dist/editor/popover.js.map +1 -1
- package/dist/editor/searchPanel.d.ts +1 -0
- package/dist/editor/searchPanel.d.ts.map +1 -1
- package/dist/editor/searchPanel.js +15 -8
- package/dist/editor/searchPanel.js.map +1 -1
- package/dist/editor/selection.d.ts +31 -11
- package/dist/editor/selection.d.ts.map +1 -1
- package/dist/editor/selection.js +198 -70
- package/dist/editor/selection.js.map +1 -1
- package/dist/editor/selectionAction.d.ts +4 -3
- package/dist/editor/selectionAction.d.ts.map +1 -1
- package/dist/editor/selectionAction.js +9 -5
- package/dist/editor/selectionAction.js.map +1 -1
- package/dist/editor/stateStorage.d.ts +15 -0
- package/dist/editor/stateStorage.d.ts.map +1 -0
- package/dist/editor/stateStorage.js +65 -0
- package/dist/editor/stateStorage.js.map +1 -0
- package/dist/editor/textDocument.d.ts +12 -77
- package/dist/editor/textDocument.d.ts.map +1 -1
- package/dist/editor/textDocument.js +76 -34
- package/dist/editor/textDocument.js.map +1 -1
- package/dist/editor/textMeasure.d.ts +7 -12
- package/dist/editor/textMeasure.d.ts.map +1 -1
- package/dist/editor/textMeasure.js +40 -32
- package/dist/editor/textMeasure.js.map +1 -1
- package/dist/editor/{tokenzier.d.ts → tokenizer.d.ts} +3 -3
- package/dist/editor/tokenizer.d.ts.map +1 -0
- package/dist/editor/{tokenzier.js → tokenizer.js} +91 -26
- package/dist/editor/tokenizer.js.map +1 -0
- package/dist/editor/utils.js +1 -1
- package/dist/editor/utils.js.map +1 -1
- package/dist/index.d.ts +5 -4
- package/dist/index.js +7 -6
- package/dist/managers/InteractionManager.d.ts +18 -7
- package/dist/managers/InteractionManager.d.ts.map +1 -1
- package/dist/managers/InteractionManager.js +154 -99
- package/dist/managers/InteractionManager.js.map +1 -1
- package/dist/managers/UniversalRenderingManager.d.ts +2 -1
- package/dist/managers/UniversalRenderingManager.d.ts.map +1 -1
- package/dist/managers/UniversalRenderingManager.js +7 -3
- package/dist/managers/UniversalRenderingManager.js.map +1 -1
- package/dist/react/CodeView.d.ts +13 -13
- package/dist/react/CodeView.d.ts.map +1 -1
- package/dist/react/CodeView.js +38 -29
- package/dist/react/CodeView.js.map +1 -1
- package/dist/react/EditContext.d.ts +20 -0
- package/dist/react/EditContext.d.ts.map +1 -0
- package/dist/react/EditContext.js +20 -0
- package/dist/react/EditContext.js.map +1 -0
- package/dist/react/File.d.ts +2 -1
- package/dist/react/File.d.ts.map +1 -1
- package/dist/react/File.js +3 -2
- package/dist/react/File.js.map +1 -1
- package/dist/react/FileDiff.d.ts +2 -2
- package/dist/react/FileDiff.d.ts.map +1 -1
- package/dist/react/FileDiff.js +3 -2
- package/dist/react/FileDiff.js.map +1 -1
- package/dist/react/MultiFileDiff.d.ts +2 -2
- package/dist/react/MultiFileDiff.d.ts.map +1 -1
- package/dist/react/MultiFileDiff.js +3 -2
- package/dist/react/MultiFileDiff.js.map +1 -1
- package/dist/react/PatchDiff.d.ts +2 -2
- package/dist/react/PatchDiff.d.ts.map +1 -1
- package/dist/react/PatchDiff.js +3 -2
- package/dist/react/PatchDiff.js.map +1 -1
- package/dist/react/UnresolvedFile.d.ts +1 -1
- package/dist/react/UnresolvedFile.js.map +1 -1
- package/dist/react/index.d.ts +4 -4
- package/dist/react/index.js +3 -3
- package/dist/react/types.d.ts +9 -1
- package/dist/react/types.d.ts.map +1 -1
- package/dist/react/utils/useFileDiffInstance.d.ts +5 -3
- package/dist/react/utils/useFileDiffInstance.d.ts.map +1 -1
- package/dist/react/utils/useFileDiffInstance.js +28 -27
- package/dist/react/utils/useFileDiffInstance.js.map +1 -1
- package/dist/react/utils/useFileInstance.d.ts +5 -3
- package/dist/react/utils/useFileInstance.d.ts.map +1 -1
- package/dist/react/utils/useFileInstance.js +29 -25
- package/dist/react/utils/useFileInstance.js.map +1 -1
- package/dist/react/utils/useUnresolvedFileInstance.js +3 -3
- package/dist/react/utils/useUnresolvedFileInstance.js.map +1 -1
- package/dist/renderers/DiffHunksRenderer.d.ts +33 -1
- package/dist/renderers/DiffHunksRenderer.d.ts.map +1 -1
- package/dist/renderers/DiffHunksRenderer.js +134 -21
- package/dist/renderers/DiffHunksRenderer.js.map +1 -1
- package/dist/renderers/FileRenderer.d.ts +2 -0
- package/dist/renderers/FileRenderer.d.ts.map +1 -1
- package/dist/renderers/FileRenderer.js +33 -11
- package/dist/renderers/FileRenderer.js.map +1 -1
- package/dist/ssr/FileDiffReact.js +1 -1
- package/dist/ssr/index.d.ts +2 -2
- package/dist/ssr/preloadDiffs.js +1 -1
- package/dist/style.js +1 -1
- package/dist/types.d.ts +185 -42
- package/dist/types.d.ts.map +1 -1
- package/dist/utils/annotationHelpers.d.ts +20 -0
- package/dist/utils/annotationHelpers.d.ts.map +1 -0
- package/dist/utils/annotationHelpers.js +29 -0
- package/dist/utils/annotationHelpers.js.map +1 -0
- package/dist/utils/computeFileOffsets.d.ts.map +1 -1
- package/dist/utils/computeFileOffsets.js +34 -5
- package/dist/utils/computeFileOffsets.js.map +1 -1
- package/dist/utils/editSessionHunks.d.ts +66 -0
- package/dist/utils/editSessionHunks.d.ts.map +1 -0
- package/dist/utils/editSessionHunks.js +437 -0
- package/dist/utils/editSessionHunks.js.map +1 -0
- package/dist/utils/getHunkSideBoundaries.d.ts +7 -0
- package/dist/utils/getHunkSideBoundaries.d.ts.map +1 -0
- package/dist/utils/getHunkSideBoundaries.js +12 -0
- package/dist/utils/getHunkSideBoundaries.js.map +1 -0
- package/dist/utils/getTotalLineCountFromHunks.d.ts.map +1 -1
- package/dist/utils/getTotalLineCountFromHunks.js +2 -1
- package/dist/utils/getTotalLineCountFromHunks.js.map +1 -1
- package/dist/utils/hydratePartialDiff.d.ts.map +1 -1
- package/dist/utils/hydratePartialDiff.js +4 -3
- package/dist/utils/hydratePartialDiff.js.map +1 -1
- package/dist/utils/isGutterUtilityPath.d.ts +5 -0
- package/dist/utils/isGutterUtilityPath.d.ts.map +1 -0
- package/dist/utils/isGutterUtilityPath.js +12 -0
- package/dist/utils/isGutterUtilityPath.js.map +1 -0
- package/dist/utils/iterateOverDiff.d.ts.map +1 -1
- package/dist/utils/iterateOverDiff.js +17 -12
- package/dist/utils/iterateOverDiff.js.map +1 -1
- package/dist/utils/parseMergeConflictDiffFromFile.d.ts.map +1 -1
- package/dist/utils/parseMergeConflictDiffFromFile.js +9 -6
- package/dist/utils/parseMergeConflictDiffFromFile.js.map +1 -1
- package/dist/utils/parsePatchFiles.d.ts.map +1 -1
- package/dist/utils/parsePatchFiles.js +6 -3
- package/dist/utils/parsePatchFiles.js.map +1 -1
- package/dist/utils/realignChangeContent.d.ts +33 -0
- package/dist/utils/realignChangeContent.d.ts.map +1 -0
- package/dist/utils/realignChangeContent.js +148 -0
- package/dist/utils/realignChangeContent.js.map +1 -0
- package/dist/utils/renderDiffWithHighlighter.js +1 -1
- package/dist/utils/resolveRegion.d.ts.map +1 -1
- package/dist/utils/resolveRegion.js +18 -2
- package/dist/utils/resolveRegion.js.map +1 -1
- package/dist/utils/updateDiffHunks.d.ts +8 -2
- package/dist/utils/updateDiffHunks.d.ts.map +1 -1
- package/dist/utils/updateDiffHunks.js +9 -7
- package/dist/utils/updateDiffHunks.js.map +1 -1
- package/dist/utils/virtualDiffLayout.d.ts +42 -2
- package/dist/utils/virtualDiffLayout.d.ts.map +1 -1
- package/dist/utils/virtualDiffLayout.js +101 -7
- package/dist/utils/virtualDiffLayout.js.map +1 -1
- package/dist/worker/WorkerPoolManager.d.ts.map +1 -1
- package/dist/worker/WorkerPoolManager.js +4 -2
- package/dist/worker/WorkerPoolManager.js.map +1 -1
- package/dist/worker/types.d.ts +4 -0
- package/dist/worker/types.d.ts.map +1 -1
- package/dist/worker/worker-portable.js +60 -20
- package/dist/worker/worker-portable.js.map +1 -1
- package/dist/worker/worker.js +61 -19
- package/dist/worker/worker.js.map +1 -1
- package/package.json +13 -8
- package/dist/editor/index.d.ts +0 -3
- package/dist/editor/index.js +0 -3
- package/dist/editor/tokenzier.d.ts.map +0 -1
- package/dist/editor/tokenzier.js.map +0 -1
- package/dist/react/EditorContext.d.ts +0 -15
- package/dist/react/EditorContext.d.ts.map +0 -1
- package/dist/react/EditorContext.js +0 -23
- package/dist/react/EditorContext.js.map +0 -1
package/dist/editor/marker.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { Range
|
|
1
|
+
import { Range } from "../types.js";
|
|
2
|
+
import { TextDocument } from "./textDocument.js";
|
|
2
3
|
import { PopoverManager } from "./popover.js";
|
|
3
4
|
|
|
4
5
|
//#region src/editor/marker.d.ts
|
|
@@ -24,10 +25,11 @@ declare class MarkerRenderer {
|
|
|
24
25
|
#private;
|
|
25
26
|
constructor(editor: MarkerRenderOptions);
|
|
26
27
|
get markers(): readonly Marker[];
|
|
27
|
-
|
|
28
|
+
isPopoverVisible(): boolean;
|
|
29
|
+
updatePopoverPosition(): void;
|
|
28
30
|
setMarkers<LAnnotation>(markers: Marker[], textDocument: TextDocument<LAnnotation>): void;
|
|
29
31
|
listenHover(contentEl: HTMLElement): void;
|
|
30
|
-
|
|
32
|
+
removePopover(): void;
|
|
31
33
|
cleanup(): void;
|
|
32
34
|
}
|
|
33
35
|
declare function markerSeverityDatasetKey(severity: MarkerSeverity): string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"marker.d.ts","names":[],"sources":["../../src/editor/marker.ts"],"mappings":"
|
|
1
|
+
{"version":3,"file":"marker.d.ts","names":[],"sources":["../../src/editor/marker.ts"],"mappings":";;;;;KAeY,cAAA;AAAA,UAEK,MAAA,SAAe,KAAA;EAC9B,QAAA,EAAU,cAAA;EACV,OAAA;IAAoB,IAAA;EAAA,IAAiB,WAAA;EACrC,MAAA;EACA,QAAA,GAAW,MAAA;AAAA;AAAA,UAGI,mBAAA;EACf,cAAA,EAAgB,cAAA;EAChB,aAAA;EACA,iBAAA,QAAyB,WAAW;EACpC,cAAA;EACA,QAAA,GAAW,IAAA,UAAc,SAAA;EACzB,QAAA,GAAW,IAAA;EACX,WAAA;AAAA;AAAA,cAGW,cAAA;EAAA;EAcX,WAAA,CAAY,MAAA,EAAQ,mBAAA;EAAA,IAIhB,OAAA,aAAoB,MAAA;EAIxB,gBAAA;EAIA,qBAAA;EAkBA,UAAA,cACE,OAAA,EAAS,MAAA,IACT,YAAA,EAAc,YAAA,CAAa,WAAA;EAW7B,WAAA,CAAY,SAAA,EAAW,WAAA;EAgCvB,aAAA;EAMA,OAAA;AAAA;AAAA,iBAyQc,wBAAA,CAAyB,QAAwB,EAAd,cAAc"}
|
package/dist/editor/marker.js
CHANGED
|
@@ -1,30 +1,42 @@
|
|
|
1
1
|
import { addEventListener, getLineNumberAttr, h } from "./utils.js";
|
|
2
|
-
import "./popover.js";
|
|
2
|
+
import { setPopoverPositionStyles } from "./popover.js";
|
|
3
3
|
import { selectionIntersects } from "./selection.js";
|
|
4
4
|
//#region src/editor/marker.ts
|
|
5
|
-
const
|
|
6
|
-
const
|
|
5
|
+
const MARKER_POPOVER_SHOW_DELAY_MS = 300;
|
|
6
|
+
const MARKER_POPOVER_HIDE_DELAY_MS = 100;
|
|
7
|
+
const MARKER_POPOVER_PLACEMENT_KEY = "marker-popover";
|
|
7
8
|
var MarkerRenderer = class {
|
|
8
9
|
#options;
|
|
9
10
|
#markers = [];
|
|
10
11
|
#lineCount = 0;
|
|
11
|
-
#
|
|
12
|
-
#
|
|
12
|
+
#markerPopoverElement;
|
|
13
|
+
#markerPopoverEventDisposes;
|
|
13
14
|
#markerEventDisposes;
|
|
14
|
-
#
|
|
15
|
-
#
|
|
16
|
-
#
|
|
15
|
+
#markerPopoverShowTimeout;
|
|
16
|
+
#markerPopoverHideTimeout;
|
|
17
|
+
#pendingMarkerPopoverIndex;
|
|
17
18
|
#hoveredMarkerIndex;
|
|
18
|
-
#
|
|
19
|
+
#isMarkerPopoverHovered = false;
|
|
19
20
|
constructor(editor) {
|
|
20
21
|
this.#options = editor;
|
|
21
22
|
}
|
|
22
23
|
get markers() {
|
|
23
24
|
return this.#markers;
|
|
24
25
|
}
|
|
25
|
-
|
|
26
|
+
isPopoverVisible() {
|
|
26
27
|
return this.#hoveredMarkerIndex !== void 0;
|
|
27
28
|
}
|
|
29
|
+
updatePopoverPosition() {
|
|
30
|
+
const hoveredMarkerIndex = this.#hoveredMarkerIndex;
|
|
31
|
+
const popover = this.#markerPopoverElement;
|
|
32
|
+
if (hoveredMarkerIndex === void 0 || popover === void 0) return;
|
|
33
|
+
const marker = this.#markers[hoveredMarkerIndex];
|
|
34
|
+
if (marker === void 0) {
|
|
35
|
+
this.removePopover();
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
this.#positionMarkerPopover(popover, marker.start.line, marker.start.character);
|
|
39
|
+
}
|
|
28
40
|
setMarkers(markers, textDocument) {
|
|
29
41
|
this.#lineCount = textDocument.lineCount;
|
|
30
42
|
this.#markers = markers.map((marker) => ({
|
|
@@ -32,7 +44,7 @@ var MarkerRenderer = class {
|
|
|
32
44
|
start: textDocument.normalizePosition(marker.start),
|
|
33
45
|
end: textDocument.normalizePosition(marker.end)
|
|
34
46
|
}));
|
|
35
|
-
this.
|
|
47
|
+
this.removePopover();
|
|
36
48
|
}
|
|
37
49
|
listenHover(contentEl) {
|
|
38
50
|
this.#markerEventDisposes?.forEach((dispose) => dispose());
|
|
@@ -43,25 +55,25 @@ var MarkerRenderer = class {
|
|
|
43
55
|
const target = e.composedPath()[0];
|
|
44
56
|
if (target === void 0) return;
|
|
45
57
|
const hoverMarkerIndex = this.#findHoveredMarkerIndex(target);
|
|
46
|
-
if (hoverMarkerIndex !== void 0) this.#
|
|
58
|
+
if (hoverMarkerIndex !== void 0) this.#scheduleMarkerPopover(hoverMarkerIndex);
|
|
47
59
|
else {
|
|
48
|
-
this.#
|
|
49
|
-
this.#
|
|
60
|
+
this.#cancelMarkerPopoverShow();
|
|
61
|
+
this.#scheduleMarkerPopoverHide();
|
|
50
62
|
}
|
|
51
63
|
}), addEventListener(contentEl, "mouseleave", () => {
|
|
52
|
-
this.#
|
|
53
|
-
this.#
|
|
64
|
+
this.#cancelMarkerPopoverShow();
|
|
65
|
+
this.#scheduleMarkerPopoverHide();
|
|
54
66
|
})];
|
|
55
67
|
}
|
|
56
|
-
|
|
57
|
-
this.#
|
|
58
|
-
this.#
|
|
59
|
-
this.#
|
|
68
|
+
removePopover() {
|
|
69
|
+
this.#cancelMarkerPopoverShow();
|
|
70
|
+
this.#cancelMarkerPopoverHide();
|
|
71
|
+
this.#dismissMarkerPopover();
|
|
60
72
|
}
|
|
61
73
|
cleanup() {
|
|
62
74
|
this.#markerEventDisposes?.forEach((dispose) => dispose());
|
|
63
75
|
this.#markerEventDisposes = void 0;
|
|
64
|
-
this.
|
|
76
|
+
this.removePopover();
|
|
65
77
|
this.#markers = [];
|
|
66
78
|
}
|
|
67
79
|
#findHoveredMarkerIndex(target) {
|
|
@@ -86,57 +98,60 @@ var MarkerRenderer = class {
|
|
|
86
98
|
end: position
|
|
87
99
|
}, this.#markers[i])) return i;
|
|
88
100
|
}
|
|
89
|
-
#
|
|
90
|
-
if (this.#
|
|
91
|
-
clearTimeout(this.#
|
|
92
|
-
this.#
|
|
101
|
+
#cancelMarkerPopoverShow() {
|
|
102
|
+
if (this.#markerPopoverShowTimeout !== void 0) {
|
|
103
|
+
clearTimeout(this.#markerPopoverShowTimeout);
|
|
104
|
+
this.#markerPopoverShowTimeout = void 0;
|
|
93
105
|
}
|
|
94
|
-
this.#
|
|
106
|
+
this.#pendingMarkerPopoverIndex = void 0;
|
|
95
107
|
}
|
|
96
|
-
#
|
|
97
|
-
if (this.#
|
|
98
|
-
clearTimeout(this.#
|
|
99
|
-
this.#
|
|
108
|
+
#cancelMarkerPopoverHide() {
|
|
109
|
+
if (this.#markerPopoverHideTimeout !== void 0) {
|
|
110
|
+
clearTimeout(this.#markerPopoverHideTimeout);
|
|
111
|
+
this.#markerPopoverHideTimeout = void 0;
|
|
100
112
|
}
|
|
101
113
|
}
|
|
102
|
-
#
|
|
103
|
-
if (markerIndex === this.#hoveredMarkerIndex || markerIndex === this.#
|
|
104
|
-
this.#
|
|
114
|
+
#scheduleMarkerPopover(markerIndex) {
|
|
115
|
+
if (markerIndex === this.#hoveredMarkerIndex || markerIndex === this.#pendingMarkerPopoverIndex) {
|
|
116
|
+
this.#cancelMarkerPopoverHide();
|
|
105
117
|
return;
|
|
106
118
|
}
|
|
107
|
-
this.#
|
|
108
|
-
this.#
|
|
109
|
-
if (this.#
|
|
110
|
-
this.#
|
|
119
|
+
this.#cancelMarkerPopoverShow();
|
|
120
|
+
this.#cancelMarkerPopoverHide();
|
|
121
|
+
if (this.#markerPopoverElement !== void 0) {
|
|
122
|
+
this.#renderMarkerPopover(markerIndex);
|
|
111
123
|
return;
|
|
112
124
|
}
|
|
113
|
-
this.#
|
|
114
|
-
this.#
|
|
115
|
-
this.#
|
|
116
|
-
this.#
|
|
117
|
-
this.#
|
|
118
|
-
},
|
|
119
|
-
}
|
|
120
|
-
#
|
|
121
|
-
if (this.#
|
|
122
|
-
this.#
|
|
123
|
-
this.#
|
|
124
|
-
this.#
|
|
125
|
-
if (!this.#
|
|
126
|
-
},
|
|
127
|
-
}
|
|
128
|
-
#
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
125
|
+
this.#pendingMarkerPopoverIndex = markerIndex;
|
|
126
|
+
this.#markerPopoverShowTimeout = setTimeout(() => {
|
|
127
|
+
this.#markerPopoverShowTimeout = void 0;
|
|
128
|
+
this.#pendingMarkerPopoverIndex = void 0;
|
|
129
|
+
this.#renderMarkerPopover(markerIndex);
|
|
130
|
+
}, MARKER_POPOVER_SHOW_DELAY_MS);
|
|
131
|
+
}
|
|
132
|
+
#scheduleMarkerPopoverHide() {
|
|
133
|
+
if (this.#isMarkerPopoverHovered) return;
|
|
134
|
+
this.#cancelMarkerPopoverHide();
|
|
135
|
+
this.#markerPopoverHideTimeout = setTimeout(() => {
|
|
136
|
+
this.#markerPopoverHideTimeout = void 0;
|
|
137
|
+
if (!this.#isMarkerPopoverHovered) this.removePopover();
|
|
138
|
+
}, MARKER_POPOVER_HIDE_DELAY_MS);
|
|
139
|
+
}
|
|
140
|
+
#setMarkerPopoverPosition(popover, x, y, placeAbove, viewport = this.#options.popoverManager.getPlacementBounds()) {
|
|
141
|
+
setPopoverPositionStyles(popover, {
|
|
142
|
+
gutterWidth: this.#options.getGutterWidth(),
|
|
143
|
+
placeAbove,
|
|
144
|
+
viewport,
|
|
145
|
+
x,
|
|
146
|
+
y
|
|
147
|
+
});
|
|
148
|
+
}
|
|
149
|
+
#positionMarkerPopover(popover, line, character) {
|
|
135
150
|
const { getCharX, getLineY, getLineHeight, popoverManager } = this.#options;
|
|
136
151
|
const [left, wrapLine] = getCharX(line, character);
|
|
137
152
|
const lineHeight = getLineHeight();
|
|
138
153
|
const rowTop = getLineY(line) + wrapLine * lineHeight;
|
|
139
|
-
const popoverHeight =
|
|
154
|
+
const popoverHeight = popover.offsetHeight;
|
|
140
155
|
const preferred = {
|
|
141
156
|
top: rowTop + lineHeight,
|
|
142
157
|
bottom: rowTop + lineHeight + popoverHeight
|
|
@@ -147,42 +162,47 @@ var MarkerRenderer = class {
|
|
|
147
162
|
};
|
|
148
163
|
const atDocumentEdge = line >= this.#lineCount - 3;
|
|
149
164
|
const viewport = popoverManager.getPlacementBounds();
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
this.#
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
this.#
|
|
165
|
+
const placeAbove = popoverManager.choosePlacement({
|
|
166
|
+
preferred,
|
|
167
|
+
fallback,
|
|
168
|
+
viewport,
|
|
169
|
+
popoverHeight,
|
|
170
|
+
atDocumentEdge,
|
|
171
|
+
placementKey: MARKER_POPOVER_PLACEMENT_KEY
|
|
172
|
+
}) === "fallback";
|
|
173
|
+
this.#setMarkerPopoverPosition(popover, left, placeAbove ? rowTop : rowTop + lineHeight, placeAbove, viewport);
|
|
174
|
+
}
|
|
175
|
+
#dismissMarkerPopover() {
|
|
176
|
+
this.#markerPopoverEventDisposes?.forEach((dispose) => dispose());
|
|
177
|
+
this.#markerPopoverEventDisposes = void 0;
|
|
178
|
+
this.#markerPopoverElement?.remove();
|
|
179
|
+
this.#markerPopoverElement = void 0;
|
|
162
180
|
this.#hoveredMarkerIndex = void 0;
|
|
163
|
-
this.#
|
|
181
|
+
this.#isMarkerPopoverHovered = false;
|
|
182
|
+
this.#options.popoverManager.resetPlacement(MARKER_POPOVER_PLACEMENT_KEY);
|
|
164
183
|
}
|
|
165
|
-
#
|
|
184
|
+
#renderMarkerPopover(hoveredMarkerIndex) {
|
|
166
185
|
if (hoveredMarkerIndex === this.#hoveredMarkerIndex) return;
|
|
167
186
|
const overlayElement = this.#options.getOverlayElement();
|
|
168
187
|
if (hoveredMarkerIndex >= this.#markers.length || overlayElement == null) return;
|
|
169
188
|
const { start, message, severity } = this.#markers[hoveredMarkerIndex];
|
|
170
189
|
const { line, character } = start;
|
|
171
|
-
const
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
190
|
+
const popover = this.#markerPopoverElement;
|
|
191
|
+
this.#options.popoverManager.resetPlacement(MARKER_POPOVER_PLACEMENT_KEY);
|
|
192
|
+
if (popover !== void 0) {
|
|
193
|
+
setMarkerPopoverSeverity(popover, severity);
|
|
194
|
+
const content = popover.firstElementChild;
|
|
175
195
|
if (content?.dataset.markerMessage !== void 0) if (typeof message === "string") content.textContent = message;
|
|
176
196
|
else if (message instanceof HTMLElement) content.replaceChildren(message);
|
|
177
197
|
else content.innerHTML = message.html;
|
|
178
|
-
this.#
|
|
198
|
+
this.#positionMarkerPopover(popover, line, character);
|
|
179
199
|
this.#hoveredMarkerIndex = hoveredMarkerIndex;
|
|
180
200
|
return;
|
|
181
201
|
}
|
|
182
|
-
this.#
|
|
202
|
+
this.#markerPopoverElement = h("div", {
|
|
183
203
|
dataset: {
|
|
184
204
|
editorWidget: "",
|
|
185
|
-
|
|
205
|
+
markerPopover: "",
|
|
186
206
|
[markerSeverityDatasetKey(severity)]: ""
|
|
187
207
|
},
|
|
188
208
|
children: [h("div", {
|
|
@@ -190,14 +210,14 @@ var MarkerRenderer = class {
|
|
|
190
210
|
...typeof message === "string" ? { textContent: message } : message instanceof HTMLElement ? { children: [message] } : { innerHTML: message.html }
|
|
191
211
|
})]
|
|
192
212
|
}, overlayElement);
|
|
193
|
-
this.#
|
|
213
|
+
this.#positionMarkerPopover(this.#markerPopoverElement, line, character);
|
|
194
214
|
this.#hoveredMarkerIndex = hoveredMarkerIndex;
|
|
195
|
-
this.#
|
|
196
|
-
this.#
|
|
197
|
-
this.#
|
|
198
|
-
}), addEventListener(this.#
|
|
199
|
-
this.#
|
|
200
|
-
this.#
|
|
215
|
+
this.#markerPopoverEventDisposes = [addEventListener(this.#markerPopoverElement, "mouseenter", () => {
|
|
216
|
+
this.#isMarkerPopoverHovered = true;
|
|
217
|
+
this.#cancelMarkerPopoverHide();
|
|
218
|
+
}), addEventListener(this.#markerPopoverElement, "mouseleave", () => {
|
|
219
|
+
this.#isMarkerPopoverHovered = false;
|
|
220
|
+
this.#scheduleMarkerPopoverHide();
|
|
201
221
|
})];
|
|
202
222
|
}
|
|
203
223
|
};
|
|
@@ -207,9 +227,9 @@ const MARKER_SEVERITIES = [
|
|
|
207
227
|
"info",
|
|
208
228
|
"hint"
|
|
209
229
|
];
|
|
210
|
-
function
|
|
211
|
-
for (const candidate of MARKER_SEVERITIES) delete
|
|
212
|
-
|
|
230
|
+
function setMarkerPopoverSeverity(popover, severity) {
|
|
231
|
+
for (const candidate of MARKER_SEVERITIES) delete popover.dataset[markerSeverityDatasetKey(candidate)];
|
|
232
|
+
popover.dataset[markerSeverityDatasetKey(severity)] = "";
|
|
213
233
|
}
|
|
214
234
|
function markerSeverityDatasetKey(severity) {
|
|
215
235
|
switch (severity) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"marker.js","names":["#options","#markers","#hoveredMarkerIndex","#lineCount","#markerEventDisposes","#findHoveredMarkerIndex","#scheduleMarkerPopup","#cancelMarkerPopupShow","#scheduleMarkerPopupHide","#cancelMarkerPopupHide","#dismissMarkerPopup","#markerPopupShowTimeout","#pendingMarkerPopupIndex","#markerPopupHideTimeout","#markerPopupElement","#renderMarkerPopup","#isMarkerPopupHovered","#setMarkerPopupPosition","#markerPopupEventDisposes","#positionMarkerPopup"],"sources":["../../src/editor/marker.ts"],"sourcesContent":["import {\n POPOVER_BOUNDARY_LINES,\n type PopoverManager,\n type PopoverPlacementBounds,\n} from './popover';\nimport { selectionIntersects } from './selection';\nimport type { Position, Range, TextDocument } from './textDocument';\nimport { addEventListener, getLineNumberAttr, h } from './utils';\n\nconst MARKER_POPUP_SHOW_DELAY_MS = 300;\nconst MARKER_POPUP_HIDE_DELAY_MS = 100;\n\nexport type MarkerSeverity = 'error' | 'warning' | 'info' | 'hint';\n\nexport interface Marker extends Range {\n severity: MarkerSeverity;\n message: string | { html: string } | HTMLElement;\n source?: string;\n metadata?: Record<string, unknown>;\n}\n\nexport interface MarkerRenderOptions {\n popoverManager: PopoverManager;\n getLineHeight: () => number;\n getOverlayElement: () => HTMLElement | undefined;\n getGutterWidth: () => number;\n getCharX: (line: number, character: number) => [number, number];\n getLineY: (line: number) => number;\n isMouseDown: () => boolean;\n}\n\nexport class MarkerRenderer {\n #options: MarkerRenderOptions;\n #markers: Marker[] = [];\n // Document line count, used only by the no-viewport document-edge fallback.\n #lineCount = 0;\n #markerPopupElement?: HTMLElement;\n #markerPopupEventDisposes?: (() => void)[];\n #markerEventDisposes?: (() => void)[];\n #markerPopupShowTimeout?: ReturnType<typeof setTimeout>;\n #markerPopupHideTimeout?: ReturnType<typeof setTimeout>;\n #pendingMarkerPopupIndex?: number;\n #hoveredMarkerIndex?: number;\n #isMarkerPopupHovered = false;\n\n constructor(editor: MarkerRenderOptions) {\n this.#options = editor;\n }\n\n get markers(): readonly Marker[] {\n return this.#markers;\n }\n\n isPopupVisible(): boolean {\n return this.#hoveredMarkerIndex !== undefined;\n }\n\n setMarkers<LAnnotation>(\n markers: Marker[],\n textDocument: TextDocument<LAnnotation>\n ): void {\n this.#lineCount = textDocument.lineCount;\n this.#markers = markers.map((marker) => ({\n ...marker,\n start: textDocument.normalizePosition(marker.start),\n end: textDocument.normalizePosition(marker.end),\n }));\n this.removePopup();\n }\n\n listenHover(contentEl: HTMLElement): void {\n this.#markerEventDisposes?.forEach((dispose) => dispose());\n this.#markerEventDisposes = undefined;\n if (this.#markers.length === 0) {\n return;\n }\n\n this.#markerEventDisposes = [\n addEventListener(contentEl, 'mouseover', (e) => {\n if (this.#options.isMouseDown()) {\n return;\n }\n const target = e.composedPath()[0] as HTMLElement | undefined;\n if (target === undefined) {\n return;\n }\n\n const hoverMarkerIndex = this.#findHoveredMarkerIndex(target);\n if (hoverMarkerIndex !== undefined) {\n this.#scheduleMarkerPopup(hoverMarkerIndex);\n } else {\n this.#cancelMarkerPopupShow();\n this.#scheduleMarkerPopupHide();\n }\n }),\n addEventListener(contentEl, 'mouseleave', () => {\n this.#cancelMarkerPopupShow();\n this.#scheduleMarkerPopupHide();\n }),\n ];\n }\n\n removePopup(): void {\n this.#cancelMarkerPopupShow();\n this.#cancelMarkerPopupHide();\n this.#dismissMarkerPopup();\n }\n\n cleanup(): void {\n this.#markerEventDisposes?.forEach((dispose) => dispose());\n this.#markerEventDisposes = undefined;\n this.removePopup();\n this.#markers = [];\n }\n\n #findHoveredMarkerIndex(target: HTMLElement): number | undefined {\n const lineElement = target.closest('[data-line]');\n if (lineElement == null) {\n return;\n }\n\n const lineNumber = getLineNumberAttr(lineElement as HTMLElement);\n if (lineNumber === undefined) {\n return;\n }\n\n let character: number | undefined;\n if (target.tagName === 'SPAN') {\n const char = target.dataset.char;\n if (char === undefined) {\n return;\n }\n character = parseInt(char, 10);\n if (Number.isNaN(character)) {\n return;\n }\n } else if (target.tagName === 'BR') {\n character = 0;\n } else {\n return;\n }\n\n const position: Position = { line: lineNumber - 1, character };\n for (let i = this.#markers.length - 1; i >= 0; i--) {\n if (\n selectionIntersects(\n { start: position, end: position },\n this.#markers[i]\n )\n ) {\n return i;\n }\n }\n return undefined;\n }\n\n #cancelMarkerPopupShow(): void {\n if (this.#markerPopupShowTimeout !== undefined) {\n clearTimeout(this.#markerPopupShowTimeout);\n this.#markerPopupShowTimeout = undefined;\n }\n this.#pendingMarkerPopupIndex = undefined;\n }\n\n #cancelMarkerPopupHide(): void {\n if (this.#markerPopupHideTimeout !== undefined) {\n clearTimeout(this.#markerPopupHideTimeout);\n this.#markerPopupHideTimeout = undefined;\n }\n }\n\n #scheduleMarkerPopup(markerIndex: number): void {\n if (\n markerIndex === this.#hoveredMarkerIndex ||\n markerIndex === this.#pendingMarkerPopupIndex\n ) {\n this.#cancelMarkerPopupHide();\n return;\n }\n\n this.#cancelMarkerPopupShow();\n this.#cancelMarkerPopupHide();\n if (this.#markerPopupElement !== undefined) {\n this.#renderMarkerPopup(markerIndex);\n return;\n }\n\n this.#pendingMarkerPopupIndex = markerIndex;\n this.#markerPopupShowTimeout = setTimeout(() => {\n this.#markerPopupShowTimeout = undefined;\n this.#pendingMarkerPopupIndex = undefined;\n this.#renderMarkerPopup(markerIndex);\n }, MARKER_POPUP_SHOW_DELAY_MS);\n }\n\n #scheduleMarkerPopupHide(): void {\n if (this.#isMarkerPopupHovered) {\n return;\n }\n\n this.#cancelMarkerPopupHide();\n this.#markerPopupHideTimeout = setTimeout(() => {\n this.#markerPopupHideTimeout = undefined;\n if (!this.#isMarkerPopupHovered) {\n this.removePopup();\n }\n }, MARKER_POPUP_HIDE_DELAY_MS);\n }\n\n // Positions the popup in overlay coordinate space (see [data-marker-popup]\n // in editor.css). When `placeAbove` is true, `y` is the top edge of the\n // marker's row and the popup is shifted up by its own height.\n #setMarkerPopupPosition(\n popup: HTMLElement,\n x: number,\n y: number,\n placeAbove: boolean\n ): void {\n popup.style.setProperty(\n '--gutter-width',\n this.#options.getGutterWidth() + 'px'\n );\n popup.style.setProperty('--popover-x', x + 'px');\n popup.style.setProperty('--popover-y', y + 'px');\n popup.style.setProperty('--popover-y-shift', placeAbove ? '-100%' : '0px');\n }\n\n // Positions the popup for a marker at `(line, character)`: prefers below\n // (the default), flipping above when below would be clipped by the visible\n // scrollport. Must run after the popup's content is final, since it reads\n // the popup's rendered height to decide whether either side fits.\n #positionMarkerPopup(\n popup: HTMLElement,\n line: number,\n character: number\n ): void {\n const { getCharX, getLineY, getLineHeight, popoverManager } = this.#options;\n const [left, wrapLine] = getCharX(line, character);\n const lineHeight = getLineHeight();\n const rowTop = getLineY(line) + wrapLine * lineHeight;\n const popoverHeight = popup.offsetHeight;\n\n const preferred: PopoverPlacementBounds = {\n top: rowTop + lineHeight,\n bottom: rowTop + lineHeight + popoverHeight,\n };\n const fallback: PopoverPlacementBounds = {\n top: rowTop - popoverHeight,\n bottom: rowTop,\n };\n const atDocumentEdge = line >= this.#lineCount - POPOVER_BOUNDARY_LINES;\n const viewport = popoverManager.getPlacementBounds();\n let placeAbove: boolean;\n if (viewport !== undefined && popoverHeight > 0) {\n const fits = (bounds: PopoverPlacementBounds): boolean =>\n bounds.top >= viewport.top && bounds.bottom <= viewport.bottom;\n placeAbove = !fits(preferred) && fits(fallback);\n } else {\n placeAbove = atDocumentEdge;\n }\n\n this.#setMarkerPopupPosition(\n popup,\n left,\n placeAbove ? rowTop : rowTop + lineHeight,\n placeAbove\n );\n }\n\n #dismissMarkerPopup(): void {\n this.#markerPopupEventDisposes?.forEach((dispose) => dispose());\n this.#markerPopupEventDisposes = undefined;\n this.#markerPopupElement?.remove();\n this.#markerPopupElement = undefined;\n this.#hoveredMarkerIndex = undefined;\n this.#isMarkerPopupHovered = false;\n }\n\n #renderMarkerPopup(hoveredMarkerIndex: number): void {\n if (hoveredMarkerIndex === this.#hoveredMarkerIndex) {\n return;\n }\n\n const overlayElement = this.#options.getOverlayElement();\n if (hoveredMarkerIndex >= this.#markers.length || overlayElement == null) {\n return;\n }\n\n const { start, message, severity } = this.#markers[hoveredMarkerIndex];\n const { line, character } = start;\n const popup = this.#markerPopupElement;\n\n if (popup !== undefined) {\n setMarkerPopupSeverity(popup, severity);\n const content = popup.firstElementChild as HTMLElement | null;\n if (content?.dataset.markerMessage !== undefined) {\n if (typeof message === 'string') {\n content.textContent = message;\n } else if (message instanceof HTMLElement) {\n content.replaceChildren(message);\n } else {\n content.innerHTML = message.html;\n }\n }\n // Position after updating content: a different message size changes\n // the offsetHeight #positionMarkerPopup reads to decide placement.\n this.#positionMarkerPopup(popup, line, character);\n this.#hoveredMarkerIndex = hoveredMarkerIndex;\n return;\n }\n\n this.#markerPopupElement = h(\n 'div',\n {\n dataset: {\n editorWidget: '',\n markerPopup: '',\n [markerSeverityDatasetKey(severity)]: '',\n },\n children: [\n h('div', {\n dataset: 'markerMessage',\n ...(typeof message === 'string'\n ? { textContent: message }\n : message instanceof HTMLElement\n ? { children: [message] }\n : { innerHTML: message.html }),\n }),\n ],\n },\n overlayElement\n );\n this.#positionMarkerPopup(this.#markerPopupElement, line, character);\n this.#hoveredMarkerIndex = hoveredMarkerIndex;\n this.#markerPopupEventDisposes = [\n addEventListener(this.#markerPopupElement, 'mouseenter', () => {\n this.#isMarkerPopupHovered = true;\n this.#cancelMarkerPopupHide();\n }),\n addEventListener(this.#markerPopupElement, 'mouseleave', () => {\n this.#isMarkerPopupHovered = false;\n this.#scheduleMarkerPopupHide();\n }),\n ];\n }\n}\n\nconst MARKER_SEVERITIES: readonly MarkerSeverity[] = [\n 'error',\n 'warning',\n 'info',\n 'hint',\n];\n\n// Marks the popup with data-marker-<severity> (the same boolean attribute the\n// squiggle range element uses) so the CSS severity palette can target both with\n// a single selector. The popup element is reused across hovers, so any\n// previously applied severity attribute is cleared first.\nfunction setMarkerPopupSeverity(\n popup: HTMLElement,\n severity: MarkerSeverity\n): void {\n for (const candidate of MARKER_SEVERITIES) {\n delete popup.dataset[markerSeverityDatasetKey(candidate)];\n }\n popup.dataset[markerSeverityDatasetKey(severity)] = '';\n}\n\nexport function markerSeverityDatasetKey(severity: MarkerSeverity): string {\n switch (severity) {\n case 'error':\n return 'markerError';\n case 'warning':\n return 'markerWarning';\n case 'info':\n return 'markerInfo';\n case 'hint':\n return 'markerHint';\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"marker.js","names":["#options","#markers","#hoveredMarkerIndex","#markerPopoverElement","#positionMarkerPopover","#lineCount","#markerEventDisposes","#findHoveredMarkerIndex","#scheduleMarkerPopover","#cancelMarkerPopoverShow","#scheduleMarkerPopoverHide","#cancelMarkerPopoverHide","#dismissMarkerPopover","#markerPopoverShowTimeout","#pendingMarkerPopoverIndex","#markerPopoverHideTimeout","#renderMarkerPopover","#isMarkerPopoverHovered","#setMarkerPopoverPosition","#markerPopoverEventDisposes"],"sources":["../../src/editor/marker.ts"],"sourcesContent":["import type { Position, Range } from '../types';\nimport {\n POPOVER_BOUNDARY_LINES,\n type PopoverManager,\n type PopoverPlacementBounds,\n setPopoverPositionStyles,\n} from './popover';\nimport { selectionIntersects } from './selection';\nimport type { TextDocument } from './textDocument';\nimport { addEventListener, getLineNumberAttr, h } from './utils';\n\nconst MARKER_POPOVER_SHOW_DELAY_MS = 300;\nconst MARKER_POPOVER_HIDE_DELAY_MS = 100;\nconst MARKER_POPOVER_PLACEMENT_KEY = 'marker-popover';\n\nexport type MarkerSeverity = 'error' | 'warning' | 'info' | 'hint';\n\nexport interface Marker extends Range {\n severity: MarkerSeverity;\n message: string | { html: string } | HTMLElement;\n source?: string;\n metadata?: Record<string, unknown>;\n}\n\nexport interface MarkerRenderOptions {\n popoverManager: PopoverManager;\n getLineHeight: () => number;\n getOverlayElement: () => HTMLElement | undefined;\n getGutterWidth: () => number;\n getCharX: (line: number, character: number) => [number, number];\n getLineY: (line: number) => number;\n isMouseDown: () => boolean;\n}\n\nexport class MarkerRenderer {\n #options: MarkerRenderOptions;\n #markers: Marker[] = [];\n // Document line count, used only by the no-viewport document-edge fallback.\n #lineCount = 0;\n #markerPopoverElement?: HTMLElement;\n #markerPopoverEventDisposes?: (() => void)[];\n #markerEventDisposes?: (() => void)[];\n #markerPopoverShowTimeout?: ReturnType<typeof setTimeout>;\n #markerPopoverHideTimeout?: ReturnType<typeof setTimeout>;\n #pendingMarkerPopoverIndex?: number;\n #hoveredMarkerIndex?: number;\n #isMarkerPopoverHovered = false;\n\n constructor(editor: MarkerRenderOptions) {\n this.#options = editor;\n }\n\n get markers(): readonly Marker[] {\n return this.#markers;\n }\n\n isPopoverVisible(): boolean {\n return this.#hoveredMarkerIndex !== undefined;\n }\n\n updatePopoverPosition(): void {\n const hoveredMarkerIndex = this.#hoveredMarkerIndex;\n const popover = this.#markerPopoverElement;\n if (hoveredMarkerIndex === undefined || popover === undefined) {\n return;\n }\n const marker = this.#markers[hoveredMarkerIndex];\n if (marker === undefined) {\n this.removePopover();\n return;\n }\n this.#positionMarkerPopover(\n popover,\n marker.start.line,\n marker.start.character\n );\n }\n\n setMarkers<LAnnotation>(\n markers: Marker[],\n textDocument: TextDocument<LAnnotation>\n ): void {\n this.#lineCount = textDocument.lineCount;\n this.#markers = markers.map((marker) => ({\n ...marker,\n start: textDocument.normalizePosition(marker.start),\n end: textDocument.normalizePosition(marker.end),\n }));\n this.removePopover();\n }\n\n listenHover(contentEl: HTMLElement): void {\n this.#markerEventDisposes?.forEach((dispose) => dispose());\n this.#markerEventDisposes = undefined;\n if (this.#markers.length === 0) {\n return;\n }\n\n this.#markerEventDisposes = [\n addEventListener(contentEl, 'mouseover', (e) => {\n if (this.#options.isMouseDown()) {\n return;\n }\n const target = e.composedPath()[0] as HTMLElement | undefined;\n if (target === undefined) {\n return;\n }\n\n const hoverMarkerIndex = this.#findHoveredMarkerIndex(target);\n if (hoverMarkerIndex !== undefined) {\n this.#scheduleMarkerPopover(hoverMarkerIndex);\n } else {\n this.#cancelMarkerPopoverShow();\n this.#scheduleMarkerPopoverHide();\n }\n }),\n addEventListener(contentEl, 'mouseleave', () => {\n this.#cancelMarkerPopoverShow();\n this.#scheduleMarkerPopoverHide();\n }),\n ];\n }\n\n removePopover(): void {\n this.#cancelMarkerPopoverShow();\n this.#cancelMarkerPopoverHide();\n this.#dismissMarkerPopover();\n }\n\n cleanup(): void {\n this.#markerEventDisposes?.forEach((dispose) => dispose());\n this.#markerEventDisposes = undefined;\n this.removePopover();\n this.#markers = [];\n }\n\n #findHoveredMarkerIndex(target: HTMLElement): number | undefined {\n const lineElement = target.closest('[data-line]');\n if (lineElement == null) {\n return;\n }\n\n const lineNumber = getLineNumberAttr(lineElement as HTMLElement);\n if (lineNumber === undefined) {\n return;\n }\n\n let character: number | undefined;\n if (target.tagName === 'SPAN') {\n const char = target.dataset.char;\n if (char === undefined) {\n return;\n }\n character = parseInt(char, 10);\n if (Number.isNaN(character)) {\n return;\n }\n } else if (target.tagName === 'BR') {\n character = 0;\n } else {\n return;\n }\n\n const position: Position = { line: lineNumber - 1, character };\n for (let i = this.#markers.length - 1; i >= 0; i--) {\n if (\n selectionIntersects(\n { start: position, end: position },\n this.#markers[i]\n )\n ) {\n return i;\n }\n }\n return undefined;\n }\n\n #cancelMarkerPopoverShow(): void {\n if (this.#markerPopoverShowTimeout !== undefined) {\n clearTimeout(this.#markerPopoverShowTimeout);\n this.#markerPopoverShowTimeout = undefined;\n }\n this.#pendingMarkerPopoverIndex = undefined;\n }\n\n #cancelMarkerPopoverHide(): void {\n if (this.#markerPopoverHideTimeout !== undefined) {\n clearTimeout(this.#markerPopoverHideTimeout);\n this.#markerPopoverHideTimeout = undefined;\n }\n }\n\n #scheduleMarkerPopover(markerIndex: number): void {\n if (\n markerIndex === this.#hoveredMarkerIndex ||\n markerIndex === this.#pendingMarkerPopoverIndex\n ) {\n this.#cancelMarkerPopoverHide();\n return;\n }\n\n this.#cancelMarkerPopoverShow();\n this.#cancelMarkerPopoverHide();\n if (this.#markerPopoverElement !== undefined) {\n this.#renderMarkerPopover(markerIndex);\n return;\n }\n\n this.#pendingMarkerPopoverIndex = markerIndex;\n this.#markerPopoverShowTimeout = setTimeout(() => {\n this.#markerPopoverShowTimeout = undefined;\n this.#pendingMarkerPopoverIndex = undefined;\n this.#renderMarkerPopover(markerIndex);\n }, MARKER_POPOVER_SHOW_DELAY_MS);\n }\n\n #scheduleMarkerPopoverHide(): void {\n if (this.#isMarkerPopoverHovered) {\n return;\n }\n\n this.#cancelMarkerPopoverHide();\n this.#markerPopoverHideTimeout = setTimeout(() => {\n this.#markerPopoverHideTimeout = undefined;\n if (!this.#isMarkerPopoverHovered) {\n this.removePopover();\n }\n }, MARKER_POPOVER_HIDE_DELAY_MS);\n }\n\n // Positions the popover in overlay coordinate space (see [data-marker-popover]\n // in editor.css). When `placeAbove` is true, `y` is the top edge of the\n // marker's row and the popover is shifted up by its own height.\n #setMarkerPopoverPosition(\n popover: HTMLElement,\n x: number,\n y: number,\n placeAbove: boolean,\n viewport = this.#options.popoverManager.getPlacementBounds()\n ): void {\n setPopoverPositionStyles(popover, {\n gutterWidth: this.#options.getGutterWidth(),\n placeAbove,\n viewport,\n x,\n y,\n });\n }\n\n // Positions the popover for a marker at `(line, character)`: prefers below\n // (the default), flipping above when below would be clipped by the visible\n // scrollport. Must run after the popover's content is final, since it reads\n // the popover's rendered height to decide whether either side fits.\n #positionMarkerPopover(\n popover: HTMLElement,\n line: number,\n character: number\n ): void {\n const { getCharX, getLineY, getLineHeight, popoverManager } = this.#options;\n const [left, wrapLine] = getCharX(line, character);\n const lineHeight = getLineHeight();\n const rowTop = getLineY(line) + wrapLine * lineHeight;\n const popoverHeight = popover.offsetHeight;\n\n const preferred: PopoverPlacementBounds = {\n top: rowTop + lineHeight,\n bottom: rowTop + lineHeight + popoverHeight,\n };\n const fallback: PopoverPlacementBounds = {\n top: rowTop - popoverHeight,\n bottom: rowTop,\n };\n const atDocumentEdge = line >= this.#lineCount - POPOVER_BOUNDARY_LINES;\n const viewport = popoverManager.getPlacementBounds();\n const placeAbove =\n popoverManager.choosePlacement({\n preferred,\n fallback,\n viewport,\n popoverHeight,\n atDocumentEdge,\n placementKey: MARKER_POPOVER_PLACEMENT_KEY,\n }) === 'fallback';\n\n this.#setMarkerPopoverPosition(\n popover,\n left,\n placeAbove ? rowTop : rowTop + lineHeight,\n placeAbove,\n viewport\n );\n }\n\n #dismissMarkerPopover(): void {\n this.#markerPopoverEventDisposes?.forEach((dispose) => dispose());\n this.#markerPopoverEventDisposes = undefined;\n this.#markerPopoverElement?.remove();\n this.#markerPopoverElement = undefined;\n this.#hoveredMarkerIndex = undefined;\n this.#isMarkerPopoverHovered = false;\n this.#options.popoverManager.resetPlacement(MARKER_POPOVER_PLACEMENT_KEY);\n }\n\n #renderMarkerPopover(hoveredMarkerIndex: number): void {\n if (hoveredMarkerIndex === this.#hoveredMarkerIndex) {\n return;\n }\n\n const overlayElement = this.#options.getOverlayElement();\n if (hoveredMarkerIndex >= this.#markers.length || overlayElement == null) {\n return;\n }\n\n const { start, message, severity } = this.#markers[hoveredMarkerIndex];\n const { line, character } = start;\n const popover = this.#markerPopoverElement;\n this.#options.popoverManager.resetPlacement(MARKER_POPOVER_PLACEMENT_KEY);\n\n if (popover !== undefined) {\n setMarkerPopoverSeverity(popover, severity);\n const content = popover.firstElementChild as HTMLElement | null;\n if (content?.dataset.markerMessage !== undefined) {\n if (typeof message === 'string') {\n content.textContent = message;\n } else if (message instanceof HTMLElement) {\n content.replaceChildren(message);\n } else {\n content.innerHTML = message.html;\n }\n }\n // Position after updating content: a different message size changes\n // the offsetHeight #positionMarkerPopover reads to decide placement.\n this.#positionMarkerPopover(popover, line, character);\n this.#hoveredMarkerIndex = hoveredMarkerIndex;\n return;\n }\n\n this.#markerPopoverElement = h(\n 'div',\n {\n dataset: {\n editorWidget: '',\n markerPopover: '',\n [markerSeverityDatasetKey(severity)]: '',\n },\n children: [\n h('div', {\n dataset: 'markerMessage',\n ...(typeof message === 'string'\n ? { textContent: message }\n : message instanceof HTMLElement\n ? { children: [message] }\n : { innerHTML: message.html }),\n }),\n ],\n },\n overlayElement\n );\n this.#positionMarkerPopover(this.#markerPopoverElement, line, character);\n this.#hoveredMarkerIndex = hoveredMarkerIndex;\n this.#markerPopoverEventDisposes = [\n addEventListener(this.#markerPopoverElement, 'mouseenter', () => {\n this.#isMarkerPopoverHovered = true;\n this.#cancelMarkerPopoverHide();\n }),\n addEventListener(this.#markerPopoverElement, 'mouseleave', () => {\n this.#isMarkerPopoverHovered = false;\n this.#scheduleMarkerPopoverHide();\n }),\n ];\n }\n}\n\nconst MARKER_SEVERITIES: readonly MarkerSeverity[] = [\n 'error',\n 'warning',\n 'info',\n 'hint',\n];\n\n// Marks the popover with data-marker-<severity> (the same boolean attribute the\n// squiggle range element uses) so the CSS severity palette can target both with\n// a single selector. The popover element is reused across hovers, so any\n// previously applied severity attribute is cleared first.\nfunction setMarkerPopoverSeverity(\n popover: HTMLElement,\n severity: MarkerSeverity\n): void {\n for (const candidate of MARKER_SEVERITIES) {\n delete popover.dataset[markerSeverityDatasetKey(candidate)];\n }\n popover.dataset[markerSeverityDatasetKey(severity)] = '';\n}\n\nexport function markerSeverityDatasetKey(severity: MarkerSeverity): string {\n switch (severity) {\n case 'error':\n return 'markerError';\n case 'warning':\n return 'markerWarning';\n case 'info':\n return 'markerInfo';\n case 'hint':\n return 'markerHint';\n }\n}\n"],"mappings":";;;;AAWA,MAAM,+BAA+B;AACrC,MAAM,+BAA+B;AACrC,MAAM,+BAA+B;AAqBrC,IAAa,iBAAb,MAA4B;CAC1B;CACA,WAAqB,CAAC;CAEtB,aAAa;CACb;CACA;CACA;CACA;CACA;CACA;CACA;CACA,0BAA0B;CAE1B,YAAY,QAA6B;EACvC,KAAKA,WAAW;CAClB;CAEA,IAAI,UAA6B;EAC/B,OAAO,KAAKC;CACd;CAEA,mBAA4B;EAC1B,OAAO,KAAKC,wBAAwB,KAAA;CACtC;CAEA,wBAA8B;EAC5B,MAAM,qBAAqB,KAAKA;EAChC,MAAM,UAAU,KAAKC;EACrB,IAAI,uBAAuB,KAAA,KAAa,YAAY,KAAA,GAClD;EAEF,MAAM,SAAS,KAAKF,SAAS;EAC7B,IAAI,WAAW,KAAA,GAAW;GACxB,KAAK,cAAc;GACnB;EACF;EACA,KAAKG,uBACH,SACA,OAAO,MAAM,MACb,OAAO,MAAM,SACf;CACF;CAEA,WACE,SACA,cACM;EACN,KAAKC,aAAa,aAAa;EAC/B,KAAKJ,WAAW,QAAQ,KAAK,YAAY;GACvC,GAAG;GACH,OAAO,aAAa,kBAAkB,OAAO,KAAK;GAClD,KAAK,aAAa,kBAAkB,OAAO,GAAG;EAChD,EAAE;EACF,KAAK,cAAc;CACrB;CAEA,YAAY,WAA8B;EACxC,KAAKK,sBAAsB,SAAS,YAAY,QAAQ,CAAC;EACzD,KAAKA,uBAAuB,KAAA;EAC5B,IAAI,KAAKL,SAAS,WAAW,GAC3B;EAGF,KAAKK,uBAAuB,CAC1B,iBAAiB,WAAW,cAAc,MAAM;GAC9C,IAAI,KAAKN,SAAS,YAAY,GAC5B;GAEF,MAAM,SAAS,EAAE,aAAa,CAAC,CAAC;GAChC,IAAI,WAAW,KAAA,GACb;GAGF,MAAM,mBAAmB,KAAKO,wBAAwB,MAAM;GAC5D,IAAI,qBAAqB,KAAA,GACvB,KAAKC,uBAAuB,gBAAgB;QACvC;IACL,KAAKC,yBAAyB;IAC9B,KAAKC,2BAA2B;GAClC;EACF,CAAC,GACD,iBAAiB,WAAW,oBAAoB;GAC9C,KAAKD,yBAAyB;GAC9B,KAAKC,2BAA2B;EAClC,CAAC,CACH;CACF;CAEA,gBAAsB;EACpB,KAAKD,yBAAyB;EAC9B,KAAKE,yBAAyB;EAC9B,KAAKC,sBAAsB;CAC7B;CAEA,UAAgB;EACd,KAAKN,sBAAsB,SAAS,YAAY,QAAQ,CAAC;EACzD,KAAKA,uBAAuB,KAAA;EAC5B,KAAK,cAAc;EACnB,KAAKL,WAAW,CAAC;CACnB;CAEA,wBAAwB,QAAyC;EAC/D,MAAM,cAAc,OAAO,QAAQ,aAAa;EAChD,IAAI,eAAe,MACjB;EAGF,MAAM,aAAa,kBAAkB,WAA0B;EAC/D,IAAI,eAAe,KAAA,GACjB;EAGF,IAAI;EACJ,IAAI,OAAO,YAAY,QAAQ;GAC7B,MAAM,OAAO,OAAO,QAAQ;GAC5B,IAAI,SAAS,KAAA,GACX;GAEF,YAAY,SAAS,MAAM,EAAE;GAC7B,IAAI,OAAO,MAAM,SAAS,GACxB;EAEJ,OAAO,IAAI,OAAO,YAAY,MAC5B,YAAY;OAEZ;EAGF,MAAM,WAAqB;GAAE,MAAM,aAAa;GAAG;EAAU;EAC7D,KAAK,IAAI,IAAI,KAAKA,SAAS,SAAS,GAAG,KAAK,GAAG,KAC7C,IACE,oBACE;GAAE,OAAO;GAAU,KAAK;EAAS,GACjC,KAAKA,SAAS,EAChB,GAEA,OAAO;CAIb;CAEA,2BAAiC;EAC/B,IAAI,KAAKY,8BAA8B,KAAA,GAAW;GAChD,aAAa,KAAKA,yBAAyB;GAC3C,KAAKA,4BAA4B,KAAA;EACnC;EACA,KAAKC,6BAA6B,KAAA;CACpC;CAEA,2BAAiC;EAC/B,IAAI,KAAKC,8BAA8B,KAAA,GAAW;GAChD,aAAa,KAAKA,yBAAyB;GAC3C,KAAKA,4BAA4B,KAAA;EACnC;CACF;CAEA,uBAAuB,aAA2B;EAChD,IACE,gBAAgB,KAAKb,uBACrB,gBAAgB,KAAKY,4BACrB;GACA,KAAKH,yBAAyB;GAC9B;EACF;EAEA,KAAKF,yBAAyB;EAC9B,KAAKE,yBAAyB;EAC9B,IAAI,KAAKR,0BAA0B,KAAA,GAAW;GAC5C,KAAKa,qBAAqB,WAAW;GACrC;EACF;EAEA,KAAKF,6BAA6B;EAClC,KAAKD,4BAA4B,iBAAiB;GAChD,KAAKA,4BAA4B,KAAA;GACjC,KAAKC,6BAA6B,KAAA;GAClC,KAAKE,qBAAqB,WAAW;EACvC,GAAG,4BAA4B;CACjC;CAEA,6BAAmC;EACjC,IAAI,KAAKC,yBACP;EAGF,KAAKN,yBAAyB;EAC9B,KAAKI,4BAA4B,iBAAiB;GAChD,KAAKA,4BAA4B,KAAA;GACjC,IAAI,CAAC,KAAKE,yBACR,KAAK,cAAc;EAEvB,GAAG,4BAA4B;CACjC;CAKA,0BACE,SACA,GACA,GACA,YACA,WAAW,KAAKjB,SAAS,eAAe,mBAAmB,GACrD;EACN,yBAAyB,SAAS;GAChC,aAAa,KAAKA,SAAS,eAAe;GAC1C;GACA;GACA;GACA;EACF,CAAC;CACH;CAMA,uBACE,SACA,MACA,WACM;EACN,MAAM,EAAE,UAAU,UAAU,eAAe,mBAAmB,KAAKA;EACnE,MAAM,CAAC,MAAM,YAAY,SAAS,MAAM,SAAS;EACjD,MAAM,aAAa,cAAc;EACjC,MAAM,SAAS,SAAS,IAAI,IAAI,WAAW;EAC3C,MAAM,gBAAgB,QAAQ;EAE9B,MAAM,YAAoC;GACxC,KAAK,SAAS;GACd,QAAQ,SAAS,aAAa;EAChC;EACA,MAAM,WAAmC;GACvC,KAAK,SAAS;GACd,QAAQ;EACV;EACA,MAAM,iBAAiB,QAAQ,KAAKK,aAAAA;EACpC,MAAM,WAAW,eAAe,mBAAmB;EACnD,MAAM,aACJ,eAAe,gBAAgB;GAC7B;GACA;GACA;GACA;GACA;GACA,cAAc;EAChB,CAAC,MAAM;EAET,KAAKa,0BACH,SACA,MACA,aAAa,SAAS,SAAS,YAC/B,YACA,QACF;CACF;CAEA,wBAA8B;EAC5B,KAAKC,6BAA6B,SAAS,YAAY,QAAQ,CAAC;EAChE,KAAKA,8BAA8B,KAAA;EACnC,KAAKhB,uBAAuB,OAAO;EACnC,KAAKA,wBAAwB,KAAA;EAC7B,KAAKD,sBAAsB,KAAA;EAC3B,KAAKe,0BAA0B;EAC/B,KAAKjB,SAAS,eAAe,eAAe,4BAA4B;CAC1E;CAEA,qBAAqB,oBAAkC;EACrD,IAAI,uBAAuB,KAAKE,qBAC9B;EAGF,MAAM,iBAAiB,KAAKF,SAAS,kBAAkB;EACvD,IAAI,sBAAsB,KAAKC,SAAS,UAAU,kBAAkB,MAClE;EAGF,MAAM,EAAE,OAAO,SAAS,aAAa,KAAKA,SAAS;EACnD,MAAM,EAAE,MAAM,cAAc;EAC5B,MAAM,UAAU,KAAKE;EACrB,KAAKH,SAAS,eAAe,eAAe,4BAA4B;EAExE,IAAI,YAAY,KAAA,GAAW;GACzB,yBAAyB,SAAS,QAAQ;GAC1C,MAAM,UAAU,QAAQ;GACxB,IAAI,SAAS,QAAQ,kBAAkB,KAAA,GACrC,IAAI,OAAO,YAAY,UACrB,QAAQ,cAAc;QACjB,IAAI,mBAAmB,aAC5B,QAAQ,gBAAgB,OAAO;QAE/B,QAAQ,YAAY,QAAQ;GAKhC,KAAKI,uBAAuB,SAAS,MAAM,SAAS;GACpD,KAAKF,sBAAsB;GAC3B;EACF;EAEA,KAAKC,wBAAwB,EAC3B,OACA;GACE,SAAS;IACP,cAAc;IACd,eAAe;KACd,yBAAyB,QAAQ,IAAI;GACxC;GACA,UAAU,CACR,EAAE,OAAO;IACP,SAAS;IACT,GAAI,OAAO,YAAY,WACnB,EAAE,aAAa,QAAQ,IACvB,mBAAmB,cACjB,EAAE,UAAU,CAAC,OAAO,EAAE,IACtB,EAAE,WAAW,QAAQ,KAAK;GAClC,CAAC,CACH;EACF,GACA,cACF;EACA,KAAKC,uBAAuB,KAAKD,uBAAuB,MAAM,SAAS;EACvE,KAAKD,sBAAsB;EAC3B,KAAKiB,8BAA8B,CACjC,iBAAiB,KAAKhB,uBAAuB,oBAAoB;GAC/D,KAAKc,0BAA0B;GAC/B,KAAKN,yBAAyB;EAChC,CAAC,GACD,iBAAiB,KAAKR,uBAAuB,oBAAoB;GAC/D,KAAKc,0BAA0B;GAC/B,KAAKP,2BAA2B;EAClC,CAAC,CACH;CACF;AACF;AAEA,MAAM,oBAA+C;CACnD;CACA;CACA;CACA;AACF;AAMA,SAAS,yBACP,SACA,UACM;CACN,KAAK,MAAM,aAAa,mBACtB,OAAO,QAAQ,QAAQ,yBAAyB,SAAS;CAE3D,QAAQ,QAAQ,yBAAyB,QAAQ,KAAK;AACxD;AAEA,SAAgB,yBAAyB,UAAkC;CACzE,QAAQ,UAAR;EACE,KAAK,SACH,OAAO;EACT,KAAK,WACH,OAAO;EACT,KAAK,QACH,OAAO;EACT,KAAK,QACH,OAAO;CACX;AACF"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { Position, Range
|
|
2
|
-
import {
|
|
1
|
+
import { Position, Range } from "../types.js";
|
|
2
|
+
import { TextDocument } from "./textDocument.js";
|
|
3
|
+
import { EditorTokenizer } from "./tokenizer.js";
|
|
3
4
|
|
|
4
5
|
//#region src/editor/matchBrackets.d.ts
|
|
5
6
|
declare function findBracketMatchRanges<LAnnotation>(textDocument: TextDocument<LAnnotation>, tokenizer: EditorTokenizer, position: Position): [open: Range, close: Range] | undefined;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"matchBrackets.d.ts","names":[],"sources":["../../src/editor/matchBrackets.ts"],"mappings":"
|
|
1
|
+
{"version":3,"file":"matchBrackets.d.ts","names":[],"sources":["../../src/editor/matchBrackets.ts"],"mappings":";;;;;iBAqBgB,sBAAA,cACd,YAAA,EAAc,YAAA,CAAa,WAAA,GAC3B,SAAA,EAAW,eAAA,EACX,QAAA,EAAU,QAAA,IACR,IAAA,EAAM,KAAA,EAAO,KAAA,EAAO,KAAA"}
|
|
@@ -16,26 +16,18 @@ function findBracketMatchRanges(textDocument, tokenizer, position) {
|
|
|
16
16
|
if (openingBracket !== void 0) return createBracketMatchRanges(findOpeningBracket(textDocument, tokenizer, bracketPosition, openingBracket), bracketPosition);
|
|
17
17
|
}
|
|
18
18
|
function findAdjacentBracket(textDocument, tokenizer, position) {
|
|
19
|
-
const previousPosition = getPreviousCharacterPosition(
|
|
19
|
+
const previousPosition = getPreviousCharacterPosition(position);
|
|
20
20
|
if (previousPosition !== void 0) {
|
|
21
21
|
const previousBracket = getBracketAtPosition(textDocument, tokenizer, previousPosition);
|
|
22
22
|
if (previousBracket !== void 0) return previousBracket;
|
|
23
23
|
}
|
|
24
24
|
return getBracketAtPosition(textDocument, tokenizer, position);
|
|
25
25
|
}
|
|
26
|
-
function getPreviousCharacterPosition(
|
|
26
|
+
function getPreviousCharacterPosition(position) {
|
|
27
27
|
if (position.character > 0) return {
|
|
28
28
|
line: position.line,
|
|
29
29
|
character: position.character - 1
|
|
30
30
|
};
|
|
31
|
-
if (position.line <= 0) return;
|
|
32
|
-
const previousLine = position.line - 1;
|
|
33
|
-
const previousLineLength = textDocument.getLineText(previousLine).length;
|
|
34
|
-
if (previousLineLength === 0) return;
|
|
35
|
-
return {
|
|
36
|
-
line: previousLine,
|
|
37
|
-
character: previousLineLength - 1
|
|
38
|
-
};
|
|
39
31
|
}
|
|
40
32
|
function getBracketAtPosition(textDocument, tokenizer, position) {
|
|
41
33
|
const char = textDocument.getLineText(position.line)[position.character];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"matchBrackets.js","names":[],"sources":["../../src/editor/matchBrackets.ts"],"sourcesContent":["import type { Position, Range, TextDocument } from './textDocument';\nimport type { EditorTokenizer } from './tokenzier';\n\nconst OPEN_BRACKETS = new Map([\n ['(', ')'],\n ['[', ']'],\n ['{', '}'],\n]);\n\nconst CLOSE_BRACKETS = new Map(\n [...OPEN_BRACKETS].map(([open, close]) => [close, open])\n);\n\nconst MAX_BRACKET_SCAN_LINES = 1_000;\nconst MAX_BRACKET_SCAN_CHARACTERS = 50_000;\n\ninterface BracketPosition extends Position {\n char: string;\n}\n\nexport function findBracketMatchRanges<LAnnotation>(\n textDocument: TextDocument<LAnnotation>,\n tokenizer: EditorTokenizer,\n position: Position\n): [open: Range, close: Range] | undefined {\n const bracketPosition = findAdjacentBracket(\n textDocument,\n tokenizer,\n textDocument.normalizePosition(position)\n );\n if (bracketPosition === undefined) {\n return undefined;\n }\n\n const closingBracket = OPEN_BRACKETS.get(bracketPosition.char);\n const openingBracket = CLOSE_BRACKETS.get(bracketPosition.char);\n if (closingBracket !== undefined) {\n const matchPosition = findClosingBracket(\n textDocument,\n tokenizer,\n bracketPosition,\n closingBracket\n );\n return createBracketMatchRanges(bracketPosition, matchPosition);\n }\n if (openingBracket !== undefined) {\n const matchPosition = findOpeningBracket(\n textDocument,\n tokenizer,\n bracketPosition,\n openingBracket\n );\n return createBracketMatchRanges(matchPosition, bracketPosition);\n }\n return undefined;\n}\n\nfunction findAdjacentBracket<LAnnotation>(\n textDocument: TextDocument<LAnnotation>,\n tokenizer: EditorTokenizer,\n position: Position\n): BracketPosition | undefined {\n const previousPosition = getPreviousCharacterPosition(textDocument, position);\n if (previousPosition !== undefined) {\n const previousBracket = getBracketAtPosition(\n textDocument,\n tokenizer,\n previousPosition\n );\n if (previousBracket !== undefined) {\n return previousBracket;\n }\n }\n return getBracketAtPosition(textDocument, tokenizer, position);\n}\n\nfunction getPreviousCharacterPosition<LAnnotation>(\n textDocument: TextDocument<LAnnotation>,\n position: Position\n): Position | undefined {\n if (position.character > 0) {\n return { line: position.line, character: position.character - 1 };\n }\n if (position.line <= 0) {\n return undefined;\n }\n const previousLine = position.line - 1;\n const previousLineLength = textDocument.getLineText(previousLine).length;\n if (previousLineLength === 0) {\n return undefined;\n }\n return { line: previousLine, character: previousLineLength - 1 };\n}\n\nfunction getBracketAtPosition<LAnnotation>(\n textDocument: TextDocument<LAnnotation>,\n tokenizer: EditorTokenizer,\n position: Position\n): BracketPosition | undefined {\n const lineText = textDocument.getLineText(position.line);\n const char = lineText[position.character];\n if (\n char === undefined ||\n (!OPEN_BRACKETS.has(char) && !CLOSE_BRACKETS.has(char)) ||\n isInIgnoredTokenRange(tokenizer, position)\n ) {\n return undefined;\n }\n return { ...position, char };\n}\n\nfunction findClosingBracket<LAnnotation>(\n textDocument: TextDocument<LAnnotation>,\n tokenizer: EditorTokenizer,\n bracketPosition: BracketPosition,\n closingBracket: string\n): BracketPosition | undefined {\n let depth = 0;\n let scannedLines = 0;\n let scannedCharacters = 0;\n for (let line = bracketPosition.line; line < textDocument.lineCount; line++) {\n if (scannedLines >= MAX_BRACKET_SCAN_LINES) {\n return undefined;\n }\n scannedLines++;\n const lineText = textDocument.getLineText(line);\n const ignoredRanges = tokenizer.getStringCommentRegexpRangesInLine(line);\n const ignoredRangeCursor = { index: 0 };\n const startCharacter =\n line === bracketPosition.line ? bracketPosition.character : 0;\n for (\n let character = startCharacter;\n character < lineText.length;\n character++\n ) {\n if (scannedCharacters >= MAX_BRACKET_SCAN_CHARACTERS) {\n return undefined;\n }\n scannedCharacters++;\n if (\n isCharacterIgnoredForward(ignoredRanges, character, ignoredRangeCursor)\n ) {\n continue;\n }\n const char = lineText[character];\n if (char === bracketPosition.char) {\n depth++;\n } else if (char === closingBracket) {\n depth--;\n if (depth === 0) {\n return { line, character, char };\n }\n }\n }\n }\n return undefined;\n}\n\nfunction findOpeningBracket<LAnnotation>(\n textDocument: TextDocument<LAnnotation>,\n tokenizer: EditorTokenizer,\n bracketPosition: BracketPosition,\n openingBracket: string\n): BracketPosition | undefined {\n let depth = 0;\n let scannedLines = 0;\n let scannedCharacters = 0;\n for (let line = bracketPosition.line; line >= 0; line--) {\n if (scannedLines >= MAX_BRACKET_SCAN_LINES) {\n return undefined;\n }\n scannedLines++;\n const lineText = textDocument.getLineText(line);\n const ignoredRanges = tokenizer.getStringCommentRegexpRangesInLine(line);\n const ignoredRangeCursor = {\n index: ignoredRanges === null ? -1 : ignoredRanges.length - 1,\n };\n const startCharacter =\n line === bracketPosition.line\n ? bracketPosition.character\n : lineText.length - 1;\n for (let character = startCharacter; character >= 0; character--) {\n if (scannedCharacters >= MAX_BRACKET_SCAN_CHARACTERS) {\n return undefined;\n }\n scannedCharacters++;\n if (\n isCharacterIgnoredBackward(ignoredRanges, character, ignoredRangeCursor)\n ) {\n continue;\n }\n const char = lineText[character];\n if (char === bracketPosition.char) {\n depth++;\n } else if (char === openingBracket) {\n depth--;\n if (depth === 0) {\n return { line, character, char };\n }\n }\n }\n }\n return undefined;\n}\n\nfunction isInIgnoredTokenRange(\n tokenizer: EditorTokenizer,\n position: Position\n): boolean {\n const ranges = tokenizer.getStringCommentRegexpRangesInLine(position.line);\n return isCharacterInIgnoredRanges(ranges, position.character);\n}\n\nfunction isCharacterInIgnoredRanges(\n ranges: [start: number, end: number][] | null,\n character: number\n): boolean {\n if (ranges === null) {\n return false;\n }\n for (const [start, end] of ranges) {\n if (character < start) {\n return false;\n }\n if (character < end) {\n return true;\n }\n }\n return false;\n}\n\nfunction isCharacterIgnoredForward(\n ranges: [start: number, end: number][] | null,\n character: number,\n cursor: { index: number }\n): boolean {\n if (ranges === null) {\n return false;\n }\n while (cursor.index < ranges.length && character >= ranges[cursor.index][1]) {\n cursor.index++;\n }\n const range = ranges[cursor.index];\n return range !== undefined && character >= range[0];\n}\n\nfunction isCharacterIgnoredBackward(\n ranges: [start: number, end: number][] | null,\n character: number,\n cursor: { index: number }\n): boolean {\n if (ranges === null) {\n return false;\n }\n while (cursor.index >= 0 && character < ranges[cursor.index][0]) {\n cursor.index--;\n }\n const range = ranges[cursor.index];\n return range !== undefined && character < range[1];\n}\n\nfunction createBracketMatchRanges(\n firstPosition: Position | undefined,\n secondPosition: Position | undefined\n): [open: Range, close: Range] | undefined {\n if (firstPosition === undefined || secondPosition === undefined) {\n return;\n }\n return [\n createCharacterRange(firstPosition),\n createCharacterRange(secondPosition),\n ];\n}\n\nfunction createCharacterRange(position: Position): Range {\n return {\n start: { line: position.line, character: position.character },\n end: { line: position.line, character: position.character + 1 },\n };\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"matchBrackets.js","names":[],"sources":["../../src/editor/matchBrackets.ts"],"sourcesContent":["import type { Position, Range } from '../types';\nimport type { TextDocument } from './textDocument';\nimport type { EditorTokenizer } from './tokenizer';\n\nconst OPEN_BRACKETS = new Map([\n ['(', ')'],\n ['[', ']'],\n ['{', '}'],\n]);\n\nconst CLOSE_BRACKETS = new Map(\n [...OPEN_BRACKETS].map(([open, close]) => [close, open])\n);\n\nconst MAX_BRACKET_SCAN_LINES = 1_000;\nconst MAX_BRACKET_SCAN_CHARACTERS = 50_000;\n\ninterface BracketPosition extends Position {\n char: string;\n}\n\nexport function findBracketMatchRanges<LAnnotation>(\n textDocument: TextDocument<LAnnotation>,\n tokenizer: EditorTokenizer,\n position: Position\n): [open: Range, close: Range] | undefined {\n const bracketPosition = findAdjacentBracket(\n textDocument,\n tokenizer,\n textDocument.normalizePosition(position)\n );\n if (bracketPosition === undefined) {\n return undefined;\n }\n\n const closingBracket = OPEN_BRACKETS.get(bracketPosition.char);\n const openingBracket = CLOSE_BRACKETS.get(bracketPosition.char);\n if (closingBracket !== undefined) {\n const matchPosition = findClosingBracket(\n textDocument,\n tokenizer,\n bracketPosition,\n closingBracket\n );\n return createBracketMatchRanges(bracketPosition, matchPosition);\n }\n if (openingBracket !== undefined) {\n const matchPosition = findOpeningBracket(\n textDocument,\n tokenizer,\n bracketPosition,\n openingBracket\n );\n return createBracketMatchRanges(matchPosition, bracketPosition);\n }\n return undefined;\n}\n\nfunction findAdjacentBracket<LAnnotation>(\n textDocument: TextDocument<LAnnotation>,\n tokenizer: EditorTokenizer,\n position: Position\n): BracketPosition | undefined {\n const previousPosition = getPreviousCharacterPosition(position);\n if (previousPosition !== undefined) {\n const previousBracket = getBracketAtPosition(\n textDocument,\n tokenizer,\n previousPosition\n );\n if (previousBracket !== undefined) {\n return previousBracket;\n }\n }\n return getBracketAtPosition(textDocument, tokenizer, position);\n}\n\nfunction getPreviousCharacterPosition(\n position: Position\n): Position | undefined {\n if (position.character > 0) {\n return { line: position.line, character: position.character - 1 };\n }\n // Bracket adjacency is line-local: column-zero carets are not visually next to\n // the previous line's last character.\n return undefined;\n}\n\nfunction getBracketAtPosition<LAnnotation>(\n textDocument: TextDocument<LAnnotation>,\n tokenizer: EditorTokenizer,\n position: Position\n): BracketPosition | undefined {\n const lineText = textDocument.getLineText(position.line);\n const char = lineText[position.character];\n if (\n char === undefined ||\n (!OPEN_BRACKETS.has(char) && !CLOSE_BRACKETS.has(char)) ||\n isInIgnoredTokenRange(tokenizer, position)\n ) {\n return undefined;\n }\n return { ...position, char };\n}\n\nfunction findClosingBracket<LAnnotation>(\n textDocument: TextDocument<LAnnotation>,\n tokenizer: EditorTokenizer,\n bracketPosition: BracketPosition,\n closingBracket: string\n): BracketPosition | undefined {\n let depth = 0;\n let scannedLines = 0;\n let scannedCharacters = 0;\n for (let line = bracketPosition.line; line < textDocument.lineCount; line++) {\n if (scannedLines >= MAX_BRACKET_SCAN_LINES) {\n return undefined;\n }\n scannedLines++;\n const lineText = textDocument.getLineText(line);\n const ignoredRanges = tokenizer.getStringCommentRegexpRangesInLine(line);\n const ignoredRangeCursor = { index: 0 };\n const startCharacter =\n line === bracketPosition.line ? bracketPosition.character : 0;\n for (\n let character = startCharacter;\n character < lineText.length;\n character++\n ) {\n if (scannedCharacters >= MAX_BRACKET_SCAN_CHARACTERS) {\n return undefined;\n }\n scannedCharacters++;\n if (\n isCharacterIgnoredForward(ignoredRanges, character, ignoredRangeCursor)\n ) {\n continue;\n }\n const char = lineText[character];\n if (char === bracketPosition.char) {\n depth++;\n } else if (char === closingBracket) {\n depth--;\n if (depth === 0) {\n return { line, character, char };\n }\n }\n }\n }\n return undefined;\n}\n\nfunction findOpeningBracket<LAnnotation>(\n textDocument: TextDocument<LAnnotation>,\n tokenizer: EditorTokenizer,\n bracketPosition: BracketPosition,\n openingBracket: string\n): BracketPosition | undefined {\n let depth = 0;\n let scannedLines = 0;\n let scannedCharacters = 0;\n for (let line = bracketPosition.line; line >= 0; line--) {\n if (scannedLines >= MAX_BRACKET_SCAN_LINES) {\n return undefined;\n }\n scannedLines++;\n const lineText = textDocument.getLineText(line);\n const ignoredRanges = tokenizer.getStringCommentRegexpRangesInLine(line);\n const ignoredRangeCursor = {\n index: ignoredRanges === null ? -1 : ignoredRanges.length - 1,\n };\n const startCharacter =\n line === bracketPosition.line\n ? bracketPosition.character\n : lineText.length - 1;\n for (let character = startCharacter; character >= 0; character--) {\n if (scannedCharacters >= MAX_BRACKET_SCAN_CHARACTERS) {\n return undefined;\n }\n scannedCharacters++;\n if (\n isCharacterIgnoredBackward(ignoredRanges, character, ignoredRangeCursor)\n ) {\n continue;\n }\n const char = lineText[character];\n if (char === bracketPosition.char) {\n depth++;\n } else if (char === openingBracket) {\n depth--;\n if (depth === 0) {\n return { line, character, char };\n }\n }\n }\n }\n return undefined;\n}\n\nfunction isInIgnoredTokenRange(\n tokenizer: EditorTokenizer,\n position: Position\n): boolean {\n const ranges = tokenizer.getStringCommentRegexpRangesInLine(position.line);\n return isCharacterInIgnoredRanges(ranges, position.character);\n}\n\nfunction isCharacterInIgnoredRanges(\n ranges: [start: number, end: number][] | null,\n character: number\n): boolean {\n if (ranges === null) {\n return false;\n }\n for (const [start, end] of ranges) {\n if (character < start) {\n return false;\n }\n if (character < end) {\n return true;\n }\n }\n return false;\n}\n\nfunction isCharacterIgnoredForward(\n ranges: [start: number, end: number][] | null,\n character: number,\n cursor: { index: number }\n): boolean {\n if (ranges === null) {\n return false;\n }\n while (cursor.index < ranges.length && character >= ranges[cursor.index][1]) {\n cursor.index++;\n }\n const range = ranges[cursor.index];\n return range !== undefined && character >= range[0];\n}\n\nfunction isCharacterIgnoredBackward(\n ranges: [start: number, end: number][] | null,\n character: number,\n cursor: { index: number }\n): boolean {\n if (ranges === null) {\n return false;\n }\n while (cursor.index >= 0 && character < ranges[cursor.index][0]) {\n cursor.index--;\n }\n const range = ranges[cursor.index];\n return range !== undefined && character < range[1];\n}\n\nfunction createBracketMatchRanges(\n firstPosition: Position | undefined,\n secondPosition: Position | undefined\n): [open: Range, close: Range] | undefined {\n if (firstPosition === undefined || secondPosition === undefined) {\n return;\n }\n return [\n createCharacterRange(firstPosition),\n createCharacterRange(secondPosition),\n ];\n}\n\nfunction createCharacterRange(position: Position): Range {\n return {\n start: { line: position.line, character: position.character },\n end: { line: position.line, character: position.character + 1 },\n };\n}\n"],"mappings":"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"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
+
import { Position, Range } from "../types.js";
|
|
1
2
|
import { SearchParams } from "./searchPanel.js";
|
|
2
|
-
import {
|
|
3
|
+
import { ResolvedTextEdit } from "./textDocument.js";
|
|
3
4
|
|
|
4
5
|
//#region src/editor/pieceTable.d.ts
|
|
5
6
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pieceTable.d.ts","names":[],"sources":["../../src/editor/pieceTable.ts"],"mappings":"
|
|
1
|
+
{"version":3,"file":"pieceTable.d.ts","names":[],"sources":["../../src/editor/pieceTable.ts"],"mappings":";;;;;;;AAsHA;;;;;;;cAAa,UAAA;EAAA;EAiBX,WAAA,CAAY,YAAA;EAAA,IAQR,SAAA;EAIJ,OAAA,CAAQ,KAAA,GAAQ,KAAA;EAShB,WAAA,CAAY,IAAA,UAAc,gBAAA;EAkB1B,aAAA,CAAc,IAAA,UAAc,gBAAA;EAqC5B,YAAA,CAAa,KAAA,UAAe,GAAA,UAAa,OAAA;EAsCzC,MAAA,CAAO,MAAA;EAWP,QAAA,CAAS,MAAA;EA2BT,+BAAA,CACE,MAAA,UACA,QAAA,YAAoB,KAAA,UAAe,GAAA;EA0CrC,MAAA,CAAO,YAAA,EAAc,YAAA,IAAgB,KAAA,UAAe,GAAA;EAsFpD,MAAA,CAAO,IAAA,UAAc,MAAA;EASrB,MAAA,CAAO,MAAA,UAAgB,MAAA;EAavB,UAAA,CAAW,KAAA,WAAgB,gBAAA;EAiB3B,UAAA,CAAW,MAAA,WAAiB,QAAA;EAY5B,WAAA,CAAY,OAAA,sBAA6B,QAAA;EAgBzC,QAAA,CAAS,QAAA,EAAU,QAAA;AAAA;;;;;iBA6qBL,0BAAA,CACd,UAAA,GAAa,MAAA,aAAmB,QAAA,EAChC,QAAA,GAAW,QAAA,EAAU,QAAA,aACrB,WAAA,GAAc,IAAA,qBACd,YAAA,EAAc,YAAA,EACd,UAAA,UACA,QAAA"}
|