@pierre/diffs 1.3.0-beta.3 → 1.3.0-beta.5
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/README.md +6 -6
- package/dist/components/CodeView.js +6 -6
- package/dist/components/CodeView.js.map +1 -1
- package/dist/components/File.d.ts +3 -2
- package/dist/components/File.d.ts.map +1 -1
- package/dist/components/File.js +35 -21
- package/dist/components/File.js.map +1 -1
- package/dist/components/FileDiff.d.ts +8 -4
- package/dist/components/FileDiff.d.ts.map +1 -1
- package/dist/components/FileDiff.js +66 -56
- package/dist/components/FileDiff.js.map +1 -1
- package/dist/components/FileStream.js +4 -2
- package/dist/components/FileStream.js.map +1 -1
- package/dist/components/UnresolvedFile.js +1 -1
- package/dist/components/VirtualizedFile.d.ts +6 -2
- package/dist/components/VirtualizedFile.d.ts.map +1 -1
- package/dist/components/VirtualizedFile.js +89 -24
- package/dist/components/VirtualizedFile.js.map +1 -1
- package/dist/components/VirtualizedFileDiff.d.ts +8 -2
- package/dist/components/VirtualizedFileDiff.d.ts.map +1 -1
- package/dist/components/VirtualizedFileDiff.js +91 -15
- package/dist/components/VirtualizedFileDiff.js.map +1 -1
- package/dist/editor/command.d.ts +1 -1
- package/dist/editor/command.d.ts.map +1 -1
- package/dist/editor/command.js +3 -3
- package/dist/editor/command.js.map +1 -1
- package/dist/editor/editStack.d.ts +1 -1
- package/dist/editor/editor.d.ts +37 -9
- package/dist/editor/editor.d.ts.map +1 -1
- package/dist/editor/editor.js +558 -449
- package/dist/editor/editor.js.map +1 -1
- package/dist/editor/editor2.js +1 -1
- package/dist/editor/editor2.js.map +1 -1
- package/dist/editor/index.d.ts +2 -2
- package/dist/editor/lineAnnotations.d.ts +2 -1
- package/dist/editor/lineAnnotations.d.ts.map +1 -1
- package/dist/editor/lineAnnotations.js +111 -1
- package/dist/editor/lineAnnotations.js.map +1 -1
- package/dist/editor/marker.d.ts +33 -0
- package/dist/editor/marker.d.ts.map +1 -0
- package/dist/editor/marker.js +185 -0
- package/dist/editor/marker.js.map +1 -0
- package/dist/editor/pieceTable.d.ts +8 -3
- package/dist/editor/pieceTable.d.ts.map +1 -1
- package/dist/editor/pieceTable.js +74 -12
- package/dist/editor/pieceTable.js.map +1 -1
- package/dist/editor/searchPanel.d.ts +12 -3
- package/dist/editor/searchPanel.d.ts.map +1 -1
- package/dist/editor/searchPanel.js +168 -54
- package/dist/editor/searchPanel.js.map +1 -1
- package/dist/editor/selection.d.ts +19 -3
- package/dist/editor/selection.d.ts.map +1 -1
- package/dist/editor/selection.js +188 -37
- package/dist/editor/selection.js.map +1 -1
- package/dist/editor/{quickEdit.d.ts → selectionAction.d.ts} +8 -8
- package/dist/editor/selectionAction.d.ts.map +1 -0
- package/dist/editor/{quickEdit.js → selectionAction.js} +18 -18
- package/dist/editor/selectionAction.js.map +1 -0
- package/dist/editor/sprite.d.ts +4 -3
- package/dist/editor/sprite.d.ts.map +1 -1
- package/dist/editor/sprite.js +19 -5
- package/dist/editor/sprite.js.map +1 -1
- package/dist/editor/textDocument.d.ts +4 -4
- package/dist/editor/textDocument.d.ts.map +1 -1
- package/dist/editor/textDocument.js +7 -7
- package/dist/editor/textDocument.js.map +1 -1
- package/dist/editor/textMeasure.d.ts +1 -0
- package/dist/editor/textMeasure.d.ts.map +1 -1
- package/dist/editor/textMeasure.js +6 -0
- package/dist/editor/textMeasure.js.map +1 -1
- package/dist/editor/tokenzier.js +20 -9
- package/dist/editor/tokenzier.js.map +1 -1
- package/dist/editor/utils.d.ts +3 -1
- package/dist/editor/utils.d.ts.map +1 -1
- package/dist/editor/utils.js +16 -1
- package/dist/editor/utils.js.map +1 -1
- package/dist/highlighter/shared_highlighter.js +3 -29
- package/dist/highlighter/shared_highlighter.js.map +1 -1
- package/dist/highlighter/themes/attachResolvedThemes.js +4 -3
- package/dist/highlighter/themes/attachResolvedThemes.js.map +1 -1
- package/dist/highlighter/themes/cleanUpResolvedThemes.js +3 -2
- package/dist/highlighter/themes/cleanUpResolvedThemes.js.map +1 -1
- package/dist/highlighter/themes/constants.d.ts +1 -7
- package/dist/highlighter/themes/constants.d.ts.map +1 -1
- package/dist/highlighter/themes/constants.js +1 -4
- package/dist/highlighter/themes/constants.js.map +1 -1
- package/dist/highlighter/themes/getResolvedOrResolveTheme.js +2 -2
- package/dist/highlighter/themes/getResolvedOrResolveTheme.js.map +1 -1
- package/dist/highlighter/themes/getResolvedThemes.js +2 -8
- package/dist/highlighter/themes/getResolvedThemes.js.map +1 -1
- package/dist/highlighter/themes/hasResolvedThemes.js +2 -3
- package/dist/highlighter/themes/hasResolvedThemes.js.map +1 -1
- package/dist/highlighter/themes/registerCustomCSSVariableTheme.js +1 -1
- package/dist/highlighter/themes/registerCustomTheme.d.ts +5 -3
- package/dist/highlighter/themes/registerCustomTheme.d.ts.map +1 -1
- package/dist/highlighter/themes/registerCustomTheme.js +15 -5
- package/dist/highlighter/themes/registerCustomTheme.js.map +1 -1
- package/dist/highlighter/themes/resolveTheme.js +6 -27
- package/dist/highlighter/themes/resolveTheme.js.map +1 -1
- package/dist/highlighter/themes/resolveThemes.js +5 -12
- package/dist/highlighter/themes/resolveThemes.js.map +1 -1
- package/dist/highlighter/themes/themeResolution.d.ts +8 -0
- package/dist/highlighter/themes/themeResolution.d.ts.map +1 -0
- package/dist/highlighter/themes/themeResolution.js +22 -0
- package/dist/highlighter/themes/themeResolution.js.map +1 -0
- package/dist/highlighter/themes/themeResolver.d.ts +8 -0
- package/dist/highlighter/themes/themeResolver.d.ts.map +1 -0
- package/dist/highlighter/themes/themeResolver.js +8 -0
- package/dist/highlighter/themes/themeResolver.js.map +1 -0
- package/dist/index.d.ts +4 -4
- package/dist/index.js +3 -3
- package/dist/managers/InteractionManager.js +1 -1
- package/dist/managers/InteractionManager.js.map +1 -1
- package/dist/managers/ResizeManager.js +1 -1
- package/dist/managers/ResizeManager.js.map +1 -1
- package/dist/react/CodeView.js +1 -1
- package/dist/react/index.d.ts +2 -2
- package/dist/react/utils/useFileDiffInstance.js +1 -0
- package/dist/react/utils/useFileDiffInstance.js.map +1 -1
- package/dist/renderers/DiffHunksRenderer.d.ts +6 -2
- package/dist/renderers/DiffHunksRenderer.d.ts.map +1 -1
- package/dist/renderers/DiffHunksRenderer.js +183 -12
- package/dist/renderers/DiffHunksRenderer.js.map +1 -1
- package/dist/renderers/FileRenderer.d.ts +2 -2
- package/dist/renderers/FileRenderer.d.ts.map +1 -1
- package/dist/renderers/FileRenderer.js +17 -5
- 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/types.d.ts +25 -8
- package/dist/types.d.ts.map +1 -1
- package/dist/utils/getHighlighterThemeStyles.js +16 -12
- package/dist/utils/getHighlighterThemeStyles.js.map +1 -1
- package/dist/utils/includesFileAnnotations.d.ts +17 -0
- package/dist/utils/includesFileAnnotations.d.ts.map +1 -0
- package/dist/utils/includesFileAnnotations.js +19 -0
- package/dist/utils/includesFileAnnotations.js.map +1 -0
- package/dist/utils/parseMergeConflictDiffFromFile.js.map +1 -1
- package/dist/utils/parsePatchFiles.js +93 -4
- package/dist/utils/parsePatchFiles.js.map +1 -1
- package/dist/utils/renderDiffWithHighlighter.js +4 -2
- package/dist/utils/renderDiffWithHighlighter.js.map +1 -1
- package/dist/utils/renderFileWithHighlighter.js +4 -2
- package/dist/utils/renderFileWithHighlighter.js.map +1 -1
- package/dist/utils/updateDiffHunks.d.ts +13 -0
- package/dist/utils/updateDiffHunks.d.ts.map +1 -0
- package/dist/utils/updateDiffHunks.js +171 -0
- package/dist/utils/updateDiffHunks.js.map +1 -0
- package/dist/utils/virtualDiffLayout.d.ts +2 -1
- package/dist/utils/virtualDiffLayout.d.ts.map +1 -1
- package/dist/utils/virtualDiffLayout.js +9 -1
- package/dist/utils/virtualDiffLayout.js.map +1 -1
- package/dist/worker/{wasm-BaDzIkIn.js → wasm-qE0LgnY3.js} +2 -2
- package/dist/worker/{wasm-BaDzIkIn.js.map → wasm-qE0LgnY3.js.map} +1 -1
- package/dist/worker/worker-portable.js +1016 -275
- package/dist/worker/worker-portable.js.map +1 -1
- package/dist/worker/worker.js +31 -19
- package/dist/worker/worker.js.map +1 -1
- package/package.json +5 -10
- package/dist/editor/quickEdit.d.ts.map +0 -1
- package/dist/editor/quickEdit.js.map +0 -1
package/dist/editor/editor.js
CHANGED
|
@@ -1,26 +1,20 @@
|
|
|
1
1
|
import { getFiletypeFromFileName } from "../utils/getFiletypeFromFileName.js";
|
|
2
2
|
import { isMoveCursorShortcut, isPrimaryModifier, isSafari } from "./platform.js";
|
|
3
3
|
import { resolveEditorCommandFromKeyboardEvent } from "./command.js";
|
|
4
|
+
import { EditStack } from "./editStack.js";
|
|
4
5
|
import editor_default from "./editor2.js";
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
6
|
+
import { addEventListener, clampDomOffset, extend, getLineNumberAttr, h, round } from "./utils.js";
|
|
7
|
+
import { applyDocumentChangeToLineAnnotations, renderLineAnnotations } from "./lineAnnotations.js";
|
|
8
|
+
import { DirectionBackward, DirectionForward, DirectionNone, applyDeleteHardLineForwardToSelections, applyDeleteSoftLineBackwardToSelections, applyDeleteWordBackwardToSelections, applyTextChangeToSelections, applyTextReplaceToSelections, applyTransposeToSelections, comparePosition, convertSelection, createSelectionFrom, createSelectionFromAnchorAndFocusOffsets, expandCollapsedSelectionToWord, extendSelection, extendSelections, findNexMatch, getCaretPosition, getDocumentBoundarySelection, getDocumentFullSelection, getSelectionAnchor, getSelectionText, isCollapsedSelection, isLineEditable, mapCursorMove, mapSelectionShift, mergeOverlappingSelections, resolveIndentEdits, selectionIntersects } from "./selection.js";
|
|
9
|
+
import { MarkerRenderer, markerSeverityDatasetKey } from "./marker.js";
|
|
10
|
+
import { createSpriteElement } from "./sprite.js";
|
|
9
11
|
import { SearchPanelWidget } from "./searchPanel.js";
|
|
10
|
-
import {
|
|
12
|
+
import { SelectionActionWidget } from "./selectionAction.js";
|
|
11
13
|
import { TextDocument } from "./textDocument.js";
|
|
12
14
|
import { Metrics, getExpandedAsciiTextColumns, getUnicodeMeasurementOffsets, snapTextOffsetToUnicodeBoundary } from "./textMeasure.js";
|
|
13
15
|
import { EditorTokenizer, renderLineTokens } from "./tokenzier.js";
|
|
14
16
|
|
|
15
17
|
//#region src/editor/editor.ts
|
|
16
|
-
function clampDomOffset(node, offset) {
|
|
17
|
-
if (node.nodeType === 3) {
|
|
18
|
-
const length = node.textContent?.length ?? 0;
|
|
19
|
-
return Math.max(0, Math.min(offset, length));
|
|
20
|
-
}
|
|
21
|
-
if (node.nodeType === 1) return Math.max(0, Math.min(offset, node.childNodes.length));
|
|
22
|
-
return 0;
|
|
23
|
-
}
|
|
24
18
|
var Editor = class {
|
|
25
19
|
#options;
|
|
26
20
|
#wrap = false;
|
|
@@ -28,50 +22,48 @@ var Editor = class {
|
|
|
28
22
|
#tokenizer;
|
|
29
23
|
#editorEventDisposes;
|
|
30
24
|
#globalEventDisposes;
|
|
31
|
-
#
|
|
25
|
+
#selectEventDisposes;
|
|
32
26
|
#detach;
|
|
33
|
-
#fileInstance;
|
|
34
|
-
#fileInstanceType;
|
|
35
|
-
#fileContents;
|
|
36
|
-
#lineAnnotations;
|
|
37
|
-
#textDocument;
|
|
38
|
-
#renderRange;
|
|
39
|
-
#codePaddingTop = 0;
|
|
40
27
|
#gutterWidthCache;
|
|
41
28
|
#contentWidthCache;
|
|
42
29
|
#lineYCache = /* @__PURE__ */ new Map();
|
|
43
30
|
#wrapLineOffsetsCache = /* @__PURE__ */ new Map();
|
|
44
|
-
#
|
|
31
|
+
#lastAccessedLineElement;
|
|
32
|
+
#lastAccessedCharX;
|
|
45
33
|
#globalStyleElement;
|
|
46
34
|
#editorStyleElement;
|
|
47
35
|
#themeStyleElement;
|
|
48
36
|
#spriteElement;
|
|
49
37
|
#fileContainer;
|
|
38
|
+
#gutterElement;
|
|
50
39
|
#contentElement;
|
|
51
40
|
#overlayElement;
|
|
41
|
+
#overlayElements;
|
|
52
42
|
#primaryCaretElement;
|
|
53
|
-
#selectionElements;
|
|
54
|
-
#quickEdit;
|
|
55
|
-
#searchPanel;
|
|
56
43
|
#resizeObserver;
|
|
44
|
+
#fileInstance;
|
|
45
|
+
#fileContents;
|
|
46
|
+
#lineAnnotations;
|
|
47
|
+
#textDocument;
|
|
48
|
+
#renderRange;
|
|
49
|
+
#markerRenderer;
|
|
50
|
+
#searchPanel;
|
|
51
|
+
#selectionAction;
|
|
57
52
|
#shouldIgnoreSelectionChange = false;
|
|
58
53
|
#isGutterMouseDown = false;
|
|
59
54
|
#isContentMouseDown = false;
|
|
60
55
|
#shiftKeyPressed = false;
|
|
61
56
|
#selectionStart;
|
|
62
57
|
#reservedSelections;
|
|
63
|
-
#selections;
|
|
64
58
|
#initSelections;
|
|
59
|
+
#selections;
|
|
65
60
|
#matches;
|
|
66
61
|
#scrollingToLine;
|
|
67
62
|
#scrollingToLineChar;
|
|
68
63
|
#scrollingToLineNoFocus = false;
|
|
69
64
|
#retainSearchPanelFocus = false;
|
|
70
|
-
#emitChange = debounce((fileContents, lineAnnotations) => {
|
|
71
|
-
this.#options.onChange?.(fileContents, lineAnnotations);
|
|
72
|
-
}, 500);
|
|
73
65
|
#onDeferTokenize = (lines, themeType) => {
|
|
74
|
-
this.#fileInstance?.
|
|
66
|
+
this.#fileInstance?.updateRenderCache(lines, themeType);
|
|
75
67
|
if (this.#renderRange !== void 0 && this.#renderRange.totalLines !== Infinity) {
|
|
76
68
|
const { startingLine, totalLines } = this.#renderRange;
|
|
77
69
|
const endLine = Math.min(startingLine + totalLines, this.#textDocument?.lineCount ?? 0);
|
|
@@ -85,15 +77,17 @@ var Editor = class {
|
|
|
85
77
|
this.#options = options;
|
|
86
78
|
}
|
|
87
79
|
edit(component) {
|
|
88
|
-
const { useTokenTransformer, enableGutterUtility, enableLineSelection, expandUnchanged, lineHoverHighlight,...rest } = component.options;
|
|
89
|
-
|
|
80
|
+
const { useTokenTransformer, enableGutterUtility, enableLineSelection, expandUnchanged, diffStyle, lineHoverHighlight,...rest } = component.options;
|
|
81
|
+
const isDiff = component.type === "file-diff";
|
|
82
|
+
if (useTokenTransformer !== true || enableGutterUtility === true || enableLineSelection === true || lineHoverHighlight !== "disabled" || expandUnchanged !== true && isDiff || diffStyle === "unified" && isDiff) {
|
|
90
83
|
component.setOptions({
|
|
91
84
|
...rest,
|
|
92
85
|
useTokenTransformer: true,
|
|
93
86
|
enableGutterUtility: false,
|
|
94
87
|
enableLineSelection: false,
|
|
88
|
+
lineHoverHighlight: "disabled",
|
|
95
89
|
expandUnchanged: true,
|
|
96
|
-
|
|
90
|
+
diffStyle: "split"
|
|
97
91
|
});
|
|
98
92
|
component.rerender();
|
|
99
93
|
}
|
|
@@ -102,60 +96,163 @@ var Editor = class {
|
|
|
102
96
|
this.#detach = component.attachEditor(this);
|
|
103
97
|
return () => this.cleanUp();
|
|
104
98
|
}
|
|
105
|
-
|
|
99
|
+
/**
|
|
100
|
+
* Apply edits to current attached file.
|
|
101
|
+
*/
|
|
102
|
+
applyEdits(edits, updateHistory = false) {
|
|
103
|
+
const textDocument = this.#textDocument;
|
|
104
|
+
if (textDocument == null) throw new Error("Editor is not attached");
|
|
105
|
+
const change = textDocument.applyEdits(edits, updateHistory, this.#selections);
|
|
106
|
+
if (change !== void 0) this.#applyChange(change, void 0, this.#applyChangeToLineAnnotations(change));
|
|
107
|
+
}
|
|
108
|
+
getState() {
|
|
109
|
+
const fileRef = this.#getFileRef();
|
|
110
|
+
if (fileRef === void 0) throw new Error("Editor is not attached");
|
|
111
|
+
return {
|
|
112
|
+
file: {
|
|
113
|
+
...fileRef,
|
|
114
|
+
cacheKey: "edited-at-" + Date.now()
|
|
115
|
+
},
|
|
116
|
+
selections: this.#selections,
|
|
117
|
+
lineAnnotations: this.#lineAnnotations,
|
|
118
|
+
renderRange: this.#renderRange
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
setState({ file, lineAnnotations, renderRange, selections }) {
|
|
122
|
+
this.#resetCache();
|
|
123
|
+
this.#resetState();
|
|
124
|
+
this.#initSelections = selections;
|
|
125
|
+
this.#fileInstance?.render({
|
|
126
|
+
file: {
|
|
127
|
+
...file,
|
|
128
|
+
cacheKey: "edited-at-" + Date.now()
|
|
129
|
+
},
|
|
130
|
+
lineAnnotations,
|
|
131
|
+
renderRange
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
setSelections(selections) {
|
|
135
|
+
const textDocument = this.#textDocument;
|
|
136
|
+
if (textDocument === void 0) throw new Error("Text document is not initialized");
|
|
137
|
+
const resolvedSelections = selections.map((selection) => {
|
|
138
|
+
const start = textDocument.normalizePosition(selection.start);
|
|
139
|
+
const end = textDocument.normalizePosition(selection.end);
|
|
140
|
+
return {
|
|
141
|
+
direction: selection.direction === "none" ? DirectionNone : selection.direction === "backward" ? DirectionBackward : DirectionForward,
|
|
142
|
+
start,
|
|
143
|
+
end
|
|
144
|
+
};
|
|
145
|
+
});
|
|
146
|
+
this.#updateSelections(resolvedSelections);
|
|
147
|
+
this.#scrollToPrimaryCaret(false, "center");
|
|
148
|
+
}
|
|
149
|
+
setMarkers(markers) {
|
|
150
|
+
const textDocument = this.#textDocument;
|
|
151
|
+
if (textDocument === void 0) throw new Error("Text document is not initialized");
|
|
152
|
+
if (markers.length === 0) {
|
|
153
|
+
this.#markerRenderer?.cleanup();
|
|
154
|
+
this.#markerRenderer = void 0;
|
|
155
|
+
this.#updateSelections(this.#selections ?? []);
|
|
156
|
+
return;
|
|
157
|
+
}
|
|
158
|
+
this.#markerRenderer ??= new MarkerRenderer({
|
|
159
|
+
getLineHeight: () => this.#metrics.lineHeight,
|
|
160
|
+
getFileContainer: () => this.#fileContainer,
|
|
161
|
+
getCharX: (line, character) => this.#getCharX(line, character),
|
|
162
|
+
getLineY: (line) => this.#getLineY(line),
|
|
163
|
+
isMouseDown: () => this.#isContentMouseDown || this.#isGutterMouseDown
|
|
164
|
+
});
|
|
165
|
+
this.#markerRenderer.setMarkers(markers, textDocument);
|
|
166
|
+
if (this.#contentElement !== void 0) this.#markerRenderer.listenHover(this.#contentElement);
|
|
167
|
+
this.#updateSelections(this.#selections ?? []);
|
|
168
|
+
}
|
|
169
|
+
focus(options) {
|
|
170
|
+
const preventScroll = options?.preventScroll ?? false;
|
|
171
|
+
const primarySelection = this.#selections?.at(-1);
|
|
172
|
+
if (primarySelection !== void 0) {
|
|
173
|
+
const pos = primarySelection.direction === DirectionBackward ? primarySelection.end : primarySelection.start;
|
|
174
|
+
this.#focus(pos, preventScroll);
|
|
175
|
+
} else this.#focus(void 0, preventScroll);
|
|
176
|
+
}
|
|
177
|
+
blur() {
|
|
178
|
+
this.#contentElement?.blur();
|
|
179
|
+
}
|
|
180
|
+
cleanUp() {
|
|
181
|
+
this.#tokenizer?.cleanUp();
|
|
182
|
+
this.#tokenizer = void 0;
|
|
183
|
+
this.#globalEventDisposes?.forEach((dispose) => dispose());
|
|
184
|
+
this.#globalEventDisposes = void 0;
|
|
185
|
+
this.#editorEventDisposes?.forEach((dispose) => dispose());
|
|
186
|
+
this.#editorEventDisposes = void 0;
|
|
187
|
+
this.#selectEventDisposes?.forEach((dispose) => dispose());
|
|
188
|
+
this.#selectEventDisposes = void 0;
|
|
189
|
+
this.#detach?.();
|
|
190
|
+
this.#detach = void 0;
|
|
191
|
+
this.#gutterWidthCache = void 0;
|
|
192
|
+
this.#contentWidthCache = void 0;
|
|
193
|
+
this.#lineYCache.clear();
|
|
194
|
+
this.#wrapLineOffsetsCache.clear();
|
|
195
|
+
this.#lastAccessedLineElement = void 0;
|
|
196
|
+
this.#lastAccessedCharX = void 0;
|
|
197
|
+
this.#globalStyleElement?.remove();
|
|
198
|
+
this.#globalStyleElement = void 0;
|
|
199
|
+
this.#editorStyleElement?.remove();
|
|
200
|
+
this.#editorStyleElement = void 0;
|
|
201
|
+
this.#themeStyleElement?.remove();
|
|
202
|
+
this.#themeStyleElement = void 0;
|
|
203
|
+
this.#spriteElement?.remove();
|
|
204
|
+
this.#spriteElement = void 0;
|
|
205
|
+
this.#fileContainer = void 0;
|
|
206
|
+
this.#gutterElement = void 0;
|
|
207
|
+
this.#contentElement?.removeAttribute("contentEditable");
|
|
208
|
+
this.#contentElement = void 0;
|
|
209
|
+
this.#overlayElement?.remove();
|
|
210
|
+
this.#overlayElement = void 0;
|
|
211
|
+
this.#resizeObserver?.disconnect();
|
|
212
|
+
this.#resizeObserver = void 0;
|
|
213
|
+
this.#resetState();
|
|
214
|
+
}
|
|
215
|
+
/** @internal */
|
|
216
|
+
__postponeBackgroundTokenizeToNextFrame() {
|
|
217
|
+
const tokenizer = this.#tokenizer;
|
|
218
|
+
if (tokenizer !== void 0) {
|
|
219
|
+
tokenizer.pauseBackgroundTokenize();
|
|
220
|
+
requestAnimationFrame(() => {
|
|
221
|
+
tokenizer.resumeBackgroundTokenize();
|
|
222
|
+
});
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
/** @internal */
|
|
226
|
+
__syncRenderView = (highlighter, fileContainer, fileContents, lineAnnotations, renderRange) => {
|
|
106
227
|
const shadowRoot = fileContainer.shadowRoot;
|
|
107
228
|
if (shadowRoot == null) {
|
|
108
229
|
console.error("[editor] Could not find the shadow root.");
|
|
109
230
|
return;
|
|
110
231
|
}
|
|
111
232
|
let codeElement;
|
|
233
|
+
let gutterEl;
|
|
234
|
+
let contentEl;
|
|
112
235
|
for (const el of shadowRoot.querySelectorAll("[data-code]")) if (el.dataset.deletions === void 0) {
|
|
113
236
|
codeElement = el;
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
this.#fileInstanceType = fileInstanceType;
|
|
120
|
-
this.#wrap = this.#fileInstance?.options.overflow === "wrap";
|
|
121
|
-
if (fileInstanceType === "diff" || lineAnnotations !== void 0 && lineAnnotations.length > 0) {
|
|
122
|
-
let startingLine;
|
|
123
|
-
let endLine;
|
|
124
|
-
for (const child of contentEl.children) {
|
|
125
|
-
const el = child;
|
|
126
|
-
const line = el.dataset.line;
|
|
127
|
-
const lineType = el.dataset.lineType;
|
|
128
|
-
if (line !== void 0) {
|
|
129
|
-
const lineNumber = parseInt(line, 10);
|
|
130
|
-
if (!Number.isNaN(lineNumber)) {
|
|
131
|
-
const lineIndex = lineNumber - 1;
|
|
132
|
-
startingLine ??= lineIndex;
|
|
133
|
-
endLine = lineIndex;
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
if (lineType === void 0 || !isLineEditable(lineType)) el.contentEditable = "false";
|
|
137
|
-
}
|
|
138
|
-
if (endLine !== void 0 && renderRange !== void 0) {
|
|
139
|
-
const { startingLine: startingLine$1, totalLines } = renderRange;
|
|
140
|
-
endLine = Math.max(endLine, startingLine$1 + totalLines);
|
|
237
|
+
for (const child of el.children) {
|
|
238
|
+
const el$1 = child;
|
|
239
|
+
const { gutter, content } = el$1.dataset;
|
|
240
|
+
if (gutter !== void 0) gutterEl = el$1;
|
|
241
|
+
else if (content !== void 0) contentEl = el$1;
|
|
141
242
|
}
|
|
142
|
-
|
|
143
|
-
startingLine,
|
|
144
|
-
totalLines: endLine - startingLine,
|
|
145
|
-
bufferBefore: 0,
|
|
146
|
-
bufferAfter: 0
|
|
147
|
-
};
|
|
243
|
+
break;
|
|
148
244
|
}
|
|
245
|
+
if (codeElement === void 0 || contentEl === void 0) return;
|
|
149
246
|
if (this.#fileContainer !== fileContainer) {
|
|
150
247
|
this.#fileContainer = fileContainer;
|
|
151
|
-
const codePaddingTop = parseInt(getComputedStyle(codeElement).paddingTop.slice(0, -2), 10);
|
|
152
|
-
this.#codePaddingTop = Number.isNaN(codePaddingTop) ? 0 : codePaddingTop;
|
|
153
248
|
if (this.#globalStyleElement !== void 0) fileContainer.appendChild(this.#globalStyleElement);
|
|
154
249
|
if (this.#editorStyleElement !== void 0) shadowRoot.appendChild(this.#editorStyleElement);
|
|
155
250
|
if (this.#themeStyleElement !== void 0) shadowRoot.appendChild(this.#themeStyleElement);
|
|
251
|
+
if (this.#spriteElement !== void 0) shadowRoot.prepend(this.#spriteElement);
|
|
156
252
|
}
|
|
157
|
-
if (this.#textDocument === void 0 || this.#fileContents === void 0 || this.#fileContents.name !== fileContents.name || this.#fileContents.lang !== fileContents.lang) {
|
|
158
|
-
const
|
|
253
|
+
if (this.#textDocument === void 0 || this.#fileContents === void 0 || this.#fileContents.name !== fileContents.name || this.#fileContents.contents !== fileContents.contents || this.#fileContents.lang !== fileContents.lang || this.#fileContents.cacheKey !== fileContents.cacheKey) {
|
|
254
|
+
const editStack = new EditStack({ maxEntries: this.#options.historyMaxEntries });
|
|
255
|
+
const textDocument = new TextDocument(fileContents.name, fileContents.contents, fileContents.lang ?? getFiletypeFromFileName(fileContents.name), 0, editStack);
|
|
159
256
|
this.#fileContents = fileContents;
|
|
160
257
|
this.#textDocument = textDocument;
|
|
161
258
|
this.#tokenizer?.cleanUp();
|
|
@@ -169,21 +266,13 @@ var Editor = class {
|
|
|
169
266
|
},
|
|
170
267
|
__debug: this.#options.__debug
|
|
171
268
|
});
|
|
172
|
-
this.#
|
|
173
|
-
this.#
|
|
174
|
-
this.#
|
|
175
|
-
this.#
|
|
176
|
-
this.#selectionElements = void 0;
|
|
177
|
-
this.#selections = void 0;
|
|
178
|
-
this.#scrollingToLine = void 0;
|
|
179
|
-
this.#reservedSelections = void 0;
|
|
180
|
-
this.#searchPanel?.cleanup();
|
|
181
|
-
this.#searchPanel = void 0;
|
|
182
|
-
this.#quickEdit?.cleanup();
|
|
183
|
-
this.#quickEdit = void 0;
|
|
269
|
+
this.#resetState();
|
|
270
|
+
this.#selections = this.#initSelections;
|
|
271
|
+
this.#options.onAttach?.(this, this.#fileInstance);
|
|
272
|
+
if (this.#textDocument !== void 0 && this.#options.__debug === true) console.log("[diffs/editor] text document changed !!!");
|
|
184
273
|
}
|
|
185
274
|
if (this.#contentElement !== contentEl) {
|
|
186
|
-
this.#
|
|
275
|
+
this.#gutterElement = gutterEl;
|
|
187
276
|
this.#contentElement = extend(contentEl, {
|
|
188
277
|
contentEditable: "true",
|
|
189
278
|
role: "textbox",
|
|
@@ -195,113 +284,50 @@ var Editor = class {
|
|
|
195
284
|
translate: false
|
|
196
285
|
});
|
|
197
286
|
if (this.#overlayElement !== void 0) contentEl.after(this.#overlayElement);
|
|
198
|
-
this.#
|
|
287
|
+
this.#metrics.init(contentEl);
|
|
288
|
+
this.#listenContentElement(contentEl, gutterEl);
|
|
289
|
+
if (this.#contentElement !== void 0 && this.#options.__debug === true) console.log("[diffs/editor] full re-render triggered !!!");
|
|
199
290
|
}
|
|
200
|
-
this.#
|
|
201
|
-
this.#
|
|
202
|
-
this.#lastCharX = void 0;
|
|
291
|
+
this.#resetCache();
|
|
292
|
+
this.#wrap = this.#fileInstance?.options.overflow === "wrap";
|
|
203
293
|
this.#lineAnnotations = lineAnnotations;
|
|
204
294
|
this.#renderRange = renderRange;
|
|
205
295
|
this.#tokenizer?.prebuildStateStack(renderRange);
|
|
206
|
-
if (this.#
|
|
207
|
-
|
|
208
|
-
this.#scrollToPrimaryCaret();
|
|
296
|
+
if (this.#selections !== void 0 || this.#matches !== void 0 || this.#markerRenderer !== void 0) this.#updateSelections(this.#selections ?? []);
|
|
297
|
+
if (this.#initSelections !== void 0 && this.#primaryCaretElement !== void 0) {
|
|
209
298
|
this.#initSelections = void 0;
|
|
210
|
-
|
|
299
|
+
this.#scrollToPrimaryCaret(false, "center");
|
|
300
|
+
} else if (this.#scrollingToLine !== void 0) this.#scrollToLine(this.#scrollingToLine, this.#scrollingToLineChar, this.#scrollingToLineNoFocus);
|
|
301
|
+
else if (this.#selections !== void 0 && this.#selections.length > 0 && !this.#retainSearchPanelFocus) this.focus({ preventScroll: true });
|
|
302
|
+
if (this.#retainSearchPanelFocus) this.#searchPanel?.focus();
|
|
303
|
+
if (this.#selectionAction !== void 0 && this.#isLineVisible(this.#selectionAction.line) && this.#contentElement !== void 0) this.#selectionAction.render(this.#contentElement);
|
|
211
304
|
if (this.#options.__debug === true && renderRange !== void 0) {
|
|
212
305
|
const { startingLine, totalLines } = renderRange;
|
|
213
306
|
console.log("[diffs/editor] render file:", fileContents.name, "RenderRange:", startingLine + "-" + (startingLine + totalLines), "of", this.#textDocument.lineCount, "lines");
|
|
214
307
|
}
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
if (this.#retainSearchPanelFocus) this.#searchPanel?.focus();
|
|
222
|
-
if (this.#quickEdit !== void 0 && this.#isLineVisible(this.#quickEdit.line) && this.#contentElement !== void 0) this.#quickEdit.render(this.#contentElement);
|
|
223
|
-
}
|
|
224
|
-
postponeBackgroundTokenizeToNextFrame() {
|
|
225
|
-
const tokenizer = this.#tokenizer;
|
|
226
|
-
if (tokenizer !== void 0) {
|
|
227
|
-
tokenizer.pauseBackgroundTokenize();
|
|
228
|
-
requestAnimationFrame(() => {
|
|
229
|
-
tokenizer.resumeBackgroundTokenize();
|
|
230
|
-
});
|
|
231
|
-
}
|
|
232
|
-
}
|
|
233
|
-
setSelections(selections) {
|
|
234
|
-
const textDocument = this.#textDocument;
|
|
235
|
-
if (textDocument !== void 0) {
|
|
236
|
-
const resolvedSelections = selections.map((selection) => {
|
|
237
|
-
const start = textDocument.normalizePosition(selection.start);
|
|
238
|
-
const end = textDocument.normalizePosition(selection.end);
|
|
239
|
-
return {
|
|
240
|
-
direction: selection.direction === "none" ? DirectionNone : selection.direction === "backward" ? DirectionBackward : DirectionForward,
|
|
241
|
-
start,
|
|
242
|
-
end
|
|
243
|
-
};
|
|
244
|
-
});
|
|
245
|
-
this.#updateSelections(resolvedSelections);
|
|
246
|
-
this.#scrollToPrimaryCaret();
|
|
247
|
-
} else this.#initSelections = selections;
|
|
248
|
-
}
|
|
249
|
-
focus(options) {
|
|
250
|
-
const preventScroll = options?.preventScroll ?? false;
|
|
251
|
-
const primarySelection = this.#selections?.at(-1);
|
|
252
|
-
if (primarySelection !== void 0) {
|
|
253
|
-
const pos = primarySelection.direction === DirectionBackward ? primarySelection.end : primarySelection.start;
|
|
254
|
-
this.#focus(pos, preventScroll);
|
|
255
|
-
} else this.#focus(void 0, preventScroll);
|
|
308
|
+
};
|
|
309
|
+
#resetCache() {
|
|
310
|
+
this.#lineYCache.clear();
|
|
311
|
+
this.#wrapLineOffsetsCache.clear();
|
|
312
|
+
this.#lastAccessedLineElement = void 0;
|
|
313
|
+
this.#lastAccessedCharX = void 0;
|
|
256
314
|
}
|
|
257
|
-
|
|
258
|
-
this.#tokenizer?.cleanUp();
|
|
259
|
-
this.#tokenizer = void 0;
|
|
260
|
-
this.#globalEventDisposes?.forEach((dispose) => dispose());
|
|
261
|
-
this.#globalEventDisposes = void 0;
|
|
262
|
-
this.#editorEventDisposes?.forEach((dispose) => dispose());
|
|
263
|
-
this.#editorEventDisposes = void 0;
|
|
264
|
-
this.#detach?.();
|
|
265
|
-
this.#detach = void 0;
|
|
266
|
-
this.#fileInstance?.setSelectedLines(null);
|
|
267
|
-
this.#fileInstance = void 0;
|
|
268
|
-
this.#fileContents = void 0;
|
|
269
|
-
this.#lineAnnotations = void 0;
|
|
270
|
-
this.#textDocument = void 0;
|
|
271
|
-
this.#renderRange = void 0;
|
|
315
|
+
#resetState() {
|
|
272
316
|
this.#gutterWidthCache = void 0;
|
|
273
317
|
this.#contentWidthCache = void 0;
|
|
274
|
-
this.#
|
|
275
|
-
this.#wrapLineOffsetsCache.clear();
|
|
276
|
-
this.#lastCharX = void 0;
|
|
277
|
-
this.#globalStyleElement?.remove();
|
|
278
|
-
this.#globalStyleElement = void 0;
|
|
279
|
-
this.#editorStyleElement?.remove();
|
|
280
|
-
this.#editorStyleElement = void 0;
|
|
281
|
-
this.#themeStyleElement?.remove();
|
|
282
|
-
this.#themeStyleElement = void 0;
|
|
283
|
-
this.#spriteElement?.remove();
|
|
284
|
-
this.#spriteElement = void 0;
|
|
285
|
-
this.#fileContainer = void 0;
|
|
286
|
-
this.#contentElement?.removeAttribute("contentEditable");
|
|
287
|
-
this.#contentElement = void 0;
|
|
288
|
-
this.#overlayElement?.remove();
|
|
289
|
-
this.#overlayElement = void 0;
|
|
290
|
-
this.#primaryCaretElement?.remove();
|
|
291
|
-
this.#primaryCaretElement = void 0;
|
|
292
|
-
this.#selectionElements?.forEach((el) => el.remove());
|
|
293
|
-
this.#selectionElements?.clear();
|
|
294
|
-
this.#selectionElements = void 0;
|
|
295
|
-
this.#searchPanel?.cleanup();
|
|
296
|
-
this.#searchPanel = void 0;
|
|
297
|
-
this.#quickEdit?.cleanup();
|
|
298
|
-
this.#quickEdit = void 0;
|
|
299
|
-
this.#resizeObserver?.disconnect();
|
|
300
|
-
this.#resizeObserver = void 0;
|
|
318
|
+
this.#fileInstance?.setSelectedLines(null);
|
|
301
319
|
this.#shouldIgnoreSelectionChange = false;
|
|
302
|
-
this.#
|
|
320
|
+
this.#overlayElements?.forEach((el) => el.remove());
|
|
321
|
+
this.#overlayElements = void 0;
|
|
303
322
|
this.#selections = void 0;
|
|
304
323
|
this.#reservedSelections = void 0;
|
|
324
|
+
this.#scrollingToLine = void 0;
|
|
325
|
+
this.#markerRenderer?.cleanup();
|
|
326
|
+
this.#markerRenderer = void 0;
|
|
327
|
+
this.#searchPanel?.cleanup();
|
|
328
|
+
this.#searchPanel = void 0;
|
|
329
|
+
this.#selectionAction?.cleanup();
|
|
330
|
+
this.#selectionAction = void 0;
|
|
305
331
|
}
|
|
306
332
|
#initialize() {
|
|
307
333
|
this.#globalStyleElement = h("style", {
|
|
@@ -318,10 +344,7 @@ var Editor = class {
|
|
|
318
344
|
textContent: editor_default
|
|
319
345
|
});
|
|
320
346
|
this.#themeStyleElement = h("style", { dataset: "editorThemeCss" });
|
|
321
|
-
|
|
322
|
-
fragment.innerHTML = SVGSpriteSheet;
|
|
323
|
-
const sprite = fragment.firstElementChild;
|
|
324
|
-
this.#spriteElement = sprite instanceof SVGSVGElement ? sprite : void 0;
|
|
347
|
+
this.#spriteElement = createSpriteElement();
|
|
325
348
|
this.#overlayElement = h("div", { dataset: "editorOverlay" });
|
|
326
349
|
this.#globalEventDisposes = [
|
|
327
350
|
addEventListener(document, "selectionchange", () => {
|
|
@@ -345,8 +368,8 @@ var Editor = class {
|
|
|
345
368
|
}, { passive: true }),
|
|
346
369
|
addEventListener(document, "pointerup", (e) => {
|
|
347
370
|
if (e.pointerType !== "mouse") return;
|
|
348
|
-
this.#
|
|
349
|
-
this.#
|
|
371
|
+
this.#selectEventDisposes?.forEach((dispose) => dispose());
|
|
372
|
+
this.#selectEventDisposes = void 0;
|
|
350
373
|
if (this.#isGutterMouseDown) {
|
|
351
374
|
this.#isGutterMouseDown = false;
|
|
352
375
|
this.#focus();
|
|
@@ -356,8 +379,8 @@ var Editor = class {
|
|
|
356
379
|
this.#shiftKeyPressed = false;
|
|
357
380
|
this.#selectionStart = void 0;
|
|
358
381
|
this.#reservedSelections = void 0;
|
|
359
|
-
this.#
|
|
360
|
-
if (key.startsWith("
|
|
382
|
+
this.#overlayElements?.forEach((el, key) => {
|
|
383
|
+
if (key.startsWith("selectionActionIcon-")) el.dataset.visible = "true";
|
|
361
384
|
});
|
|
362
385
|
}, { passive: true }),
|
|
363
386
|
addEventListener(document, "keydown", (e) => {
|
|
@@ -368,17 +391,17 @@ var Editor = class {
|
|
|
368
391
|
}, { passive: true })
|
|
369
392
|
];
|
|
370
393
|
}
|
|
371
|
-
#listenContentElement(contentEl) {
|
|
372
|
-
const gutterEl = contentEl.previousElementSibling;
|
|
394
|
+
#listenContentElement(contentEl, gutterEl) {
|
|
373
395
|
const targetIsContentElement = (e) => {
|
|
374
396
|
const target = e.composedPath()[0];
|
|
375
|
-
return target === contentEl || contentEl.contains(target);
|
|
397
|
+
return target !== void 0 && (target === contentEl || contentEl.contains(target));
|
|
376
398
|
};
|
|
377
399
|
this.#editorEventDisposes?.forEach((dispose) => dispose());
|
|
378
400
|
this.#editorEventDisposes = [
|
|
379
401
|
addEventListener(contentEl, "pointerdown", (e) => {
|
|
380
402
|
if (e.pointerType !== "mouse") return;
|
|
381
|
-
|
|
403
|
+
this.#markerRenderer?.removePopup();
|
|
404
|
+
if (isSafari() && this.#lineAnnotations !== void 0 && this.#lineAnnotations.length > 0) this.#selectEventDisposes = [...contentEl.querySelectorAll("[data-line-annotation]")].map((el) => [addEventListener(el, "mouseenter", () => {
|
|
382
405
|
this.#shouldIgnoreSelectionChange = true;
|
|
383
406
|
}), addEventListener(el, "mouseleave", () => {
|
|
384
407
|
this.#shouldIgnoreSelectionChange = false;
|
|
@@ -405,8 +428,8 @@ var Editor = class {
|
|
|
405
428
|
this.#searchPanel?.cleanup();
|
|
406
429
|
this.#searchPanel = void 0;
|
|
407
430
|
this.#retainSearchPanelFocus = false;
|
|
408
|
-
this.#
|
|
409
|
-
this.#
|
|
431
|
+
this.#selectionAction?.cleanup();
|
|
432
|
+
this.#selectionAction = void 0;
|
|
410
433
|
if (this.#selections !== void 0 && this.#selections.length > 0) {
|
|
411
434
|
const primarySelection = this.#selections.at(-1);
|
|
412
435
|
if (!isCollapsedSelection(primarySelection) || this.#selections.length > 1) {
|
|
@@ -459,6 +482,10 @@ var Editor = class {
|
|
|
459
482
|
e.preventDefault();
|
|
460
483
|
this.#handleInput(e.inputType, e.data);
|
|
461
484
|
}),
|
|
485
|
+
addEventListener(contentEl, "drop", (e) => {
|
|
486
|
+
if (!targetIsContentElement(e)) return;
|
|
487
|
+
e.preventDefault();
|
|
488
|
+
}),
|
|
462
489
|
addEventListener(contentEl, "compositionstart", (e) => {
|
|
463
490
|
if (!targetIsContentElement(e)) return;
|
|
464
491
|
this.#shouldIgnoreSelectionChange = true;
|
|
@@ -469,51 +496,53 @@ var Editor = class {
|
|
|
469
496
|
this.#handleInput("insertText", e.data);
|
|
470
497
|
}, { passive: true })
|
|
471
498
|
];
|
|
472
|
-
if (gutterEl !==
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
const lineType = target.dataset.lineType;
|
|
479
|
-
if (columnNumber === void 0 || lineType === void 0 || !isLineEditable(lineType)) return;
|
|
480
|
-
const lineNumber = parseInt(columnNumber, 10);
|
|
481
|
-
if (Number.isNaN(lineNumber)) return;
|
|
482
|
-
const line = lineNumber - 1;
|
|
483
|
-
const selection = {
|
|
484
|
-
start: {
|
|
485
|
-
line,
|
|
486
|
-
character: 0
|
|
487
|
-
},
|
|
488
|
-
end: {
|
|
489
|
-
line,
|
|
490
|
-
character: textDocument.getLineText(line).length
|
|
491
|
-
},
|
|
492
|
-
direction: DirectionForward
|
|
499
|
+
if (gutterEl !== void 0) {
|
|
500
|
+
const resolveGutterTarget = (eventTarget, includeContentLine = false) => {
|
|
501
|
+
let target = eventTarget;
|
|
502
|
+
if (target?.dataset.lineNumberContent !== void 0) target = target.parentElement ?? void 0;
|
|
503
|
+
else if (includeContentLine && target?.tagName === "SPAN") target = target.closest("[data-line]");
|
|
504
|
+
return target;
|
|
493
505
|
};
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
const
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
506
|
+
const resolveEditableLine = (target) => {
|
|
507
|
+
if (target === void 0) return;
|
|
508
|
+
const lineType = target.dataset.lineType;
|
|
509
|
+
const lineNumber = getLineNumberAttr(target) ?? getLineNumberAttr(target, "columnNumber");
|
|
510
|
+
if (lineNumber === void 0 || lineType === void 0 || !isLineEditable(lineType)) return;
|
|
511
|
+
return lineNumber - 1;
|
|
512
|
+
};
|
|
513
|
+
this.#editorEventDisposes.push(addEventListener(gutterEl, "pointerdown", (e) => {
|
|
514
|
+
const textDocument = this.#textDocument;
|
|
515
|
+
const lineIndex = resolveEditableLine(resolveGutterTarget(e.composedPath()[0]));
|
|
516
|
+
if (lineIndex === void 0 || textDocument === void 0) return;
|
|
517
|
+
this.#markerRenderer?.removePopup();
|
|
518
|
+
const selection = {
|
|
519
|
+
start: {
|
|
520
|
+
line: lineIndex,
|
|
521
|
+
character: 0
|
|
522
|
+
},
|
|
523
|
+
end: {
|
|
524
|
+
line: lineIndex,
|
|
525
|
+
character: textDocument.getLineText(lineIndex).length
|
|
526
|
+
},
|
|
527
|
+
direction: DirectionForward
|
|
528
|
+
};
|
|
529
|
+
this.#isGutterMouseDown = true;
|
|
530
|
+
this.#selectionStart = selection;
|
|
531
|
+
this.#updateSelections([selection]);
|
|
532
|
+
this.#focus(selection.end);
|
|
533
|
+
this.#selectEventDisposes = [addEventListener(document, "mousemove", (e$1) => {
|
|
534
|
+
if (!this.#isGutterMouseDown) return;
|
|
535
|
+
const textDocument$1 = this.#textDocument;
|
|
536
|
+
const lineIndex$1 = resolveEditableLine(resolveGutterTarget(e$1.composedPath()[0], true));
|
|
537
|
+
if (lineIndex$1 === void 0 || textDocument$1 === void 0) return;
|
|
509
538
|
let selection$1 = {
|
|
510
539
|
start: {
|
|
511
|
-
line: lineIndex,
|
|
540
|
+
line: lineIndex$1,
|
|
512
541
|
character: 0
|
|
513
542
|
},
|
|
514
543
|
end: {
|
|
515
|
-
line: lineIndex,
|
|
516
|
-
character:
|
|
544
|
+
line: lineIndex$1,
|
|
545
|
+
character: textDocument$1.getLineText(lineIndex$1).length
|
|
517
546
|
},
|
|
518
547
|
direction: DirectionForward
|
|
519
548
|
};
|
|
@@ -521,9 +550,10 @@ var Editor = class {
|
|
|
521
550
|
else this.#selectionStart = selection$1;
|
|
522
551
|
this.#updateSelections([selection$1]);
|
|
523
552
|
this.#focus(selection$1.end);
|
|
524
|
-
}
|
|
525
|
-
}, { passive: true })
|
|
526
|
-
}
|
|
553
|
+
}, { passive: true })];
|
|
554
|
+
}, { passive: true }));
|
|
555
|
+
}
|
|
556
|
+
this.#markerRenderer?.listenHover(contentEl);
|
|
527
557
|
this.#resizeObserver?.disconnect();
|
|
528
558
|
this.#resizeObserver = new ResizeObserver(() => {
|
|
529
559
|
this.#handleLayoutResize();
|
|
@@ -536,21 +566,23 @@ var Editor = class {
|
|
|
536
566
|
if (textDocument === void 0) return;
|
|
537
567
|
switch (command) {
|
|
538
568
|
case "openSearchPanel":
|
|
539
|
-
this.#
|
|
569
|
+
this.#openSearchPanel("find");
|
|
570
|
+
break;
|
|
571
|
+
case "openSearchReplacePanel":
|
|
572
|
+
this.#openSearchPanel("replace");
|
|
540
573
|
break;
|
|
541
574
|
case "findNextMatch": {
|
|
542
575
|
const selections = this.#selections;
|
|
543
|
-
|
|
544
|
-
if (selections === void 0 || textDocument$1 === void 0) break;
|
|
576
|
+
if (selections === void 0) break;
|
|
545
577
|
if (selections.some(isCollapsedSelection)) {
|
|
546
578
|
const expanded = selections.map((sel) => {
|
|
547
|
-
if (isCollapsedSelection(sel)) return expandCollapsedSelectionToWord(textDocument
|
|
579
|
+
if (isCollapsedSelection(sel)) return expandCollapsedSelectionToWord(textDocument, sel);
|
|
548
580
|
return sel;
|
|
549
581
|
});
|
|
550
582
|
this.#updateSelections(expanded);
|
|
551
583
|
this.focus();
|
|
552
584
|
} else {
|
|
553
|
-
const nextMatch = findNexMatch(textDocument
|
|
585
|
+
const nextMatch = findNexMatch(textDocument, selections);
|
|
554
586
|
if (nextMatch !== void 0) {
|
|
555
587
|
this.#updateSelections(nextMatch);
|
|
556
588
|
this.#scrollToPrimaryCaret();
|
|
@@ -628,66 +660,49 @@ var Editor = class {
|
|
|
628
660
|
const gutterWidthChanged = this.#getGutterWidth() !== prevGutterWidth;
|
|
629
661
|
const contentWidthChanged = this.#getContentWidth() !== prevContentWidth;
|
|
630
662
|
if (!gutterWidthChanged && !contentWidthChanged) return;
|
|
631
|
-
this.#
|
|
663
|
+
this.#lastAccessedLineElement = void 0;
|
|
664
|
+
this.#lastAccessedCharX = void 0;
|
|
632
665
|
if (contentWidthChanged && (this.#wrap || lineAnnotations > 0)) {
|
|
633
666
|
this.#lineYCache.clear();
|
|
634
667
|
this.#wrapLineOffsetsCache.clear();
|
|
635
668
|
}
|
|
636
|
-
if (this.#selections !== void 0) {
|
|
637
|
-
this.#updateSelections(this.#selections);
|
|
638
|
-
this.focus();
|
|
669
|
+
if (this.#selections !== void 0 || this.#matches !== void 0 || this.#markerRenderer !== void 0) {
|
|
670
|
+
this.#updateSelections(this.#selections ?? []);
|
|
671
|
+
if (this.#selections !== void 0) this.focus();
|
|
639
672
|
}
|
|
673
|
+
this.#markerRenderer?.removePopup();
|
|
640
674
|
}
|
|
641
675
|
#rerender(change, newLineAnnotations, renderRange = this.#renderRange, shouldUpdateBuffer) {
|
|
642
676
|
const tokenizer = this.#tokenizer;
|
|
643
|
-
const
|
|
677
|
+
const fileInstance = this.#fileInstance;
|
|
644
678
|
const fileContents = this.#fileContents;
|
|
645
679
|
const textDocument = this.#textDocument;
|
|
680
|
+
const gutterEl = this.#gutterElement;
|
|
646
681
|
const contentEl = this.#contentElement;
|
|
647
|
-
|
|
648
|
-
if (tokenizer === void 0 || component === void 0 || fileContents === void 0 || textDocument === void 0 || contentEl === void 0 || gutterEl === void 0 || !(gutterEl instanceof HTMLElement) || gutterEl.dataset.gutter === void 0) return;
|
|
682
|
+
if (tokenizer === void 0 || fileInstance === void 0 || fileContents === void 0 || textDocument === void 0 || contentEl === void 0) return;
|
|
649
683
|
tokenizer.stopBackgroundTokenize();
|
|
650
684
|
const t = performance.now();
|
|
651
|
-
const isFileDiff = this.#fileInstanceType === "diff";
|
|
652
685
|
const dirtyLines = tokenizer.tokenize(change, renderRange);
|
|
653
686
|
const t2 = performance.now();
|
|
654
687
|
if (dirtyLines.size > 0) {
|
|
655
688
|
const children = contentEl.children;
|
|
656
689
|
const dirtyLineIndexes = new Set(dirtyLines.keys());
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
const
|
|
660
|
-
if (
|
|
661
|
-
const lineNumber =
|
|
662
|
-
if (
|
|
690
|
+
const startingLine = renderRange?.startingLine ?? 0;
|
|
691
|
+
for (let i = change.startLine - startingLine; i < children.length; i++) {
|
|
692
|
+
const child = children[i];
|
|
693
|
+
if (child !== void 0) {
|
|
694
|
+
const lineNumber = getLineNumberAttr(child);
|
|
695
|
+
if (lineNumber !== void 0) {
|
|
663
696
|
const lineIndex = lineNumber - 1;
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
697
|
+
if (dirtyLines.has(lineIndex)) {
|
|
698
|
+
const tokens = dirtyLines.get(lineIndex);
|
|
699
|
+
child.replaceChildren(...renderLineTokens(tokens, tokenizer.themeType));
|
|
667
700
|
dirtyLineIndexes.delete(lineIndex);
|
|
668
701
|
if (dirtyLineIndexes.size === 0) break;
|
|
669
702
|
}
|
|
670
703
|
}
|
|
671
704
|
}
|
|
672
705
|
}
|
|
673
|
-
else {
|
|
674
|
-
const startingLine = renderRange?.startingLine ?? 0;
|
|
675
|
-
for (let i = change.startLine - startingLine; i < children.length; i++) {
|
|
676
|
-
const child = children[i];
|
|
677
|
-
if (child !== void 0 && child.dataset.line !== void 0) {
|
|
678
|
-
const lineNumber = parseInt(child.dataset.line, 10);
|
|
679
|
-
if (!Number.isNaN(lineNumber)) {
|
|
680
|
-
const lineIndex = lineNumber - 1;
|
|
681
|
-
if (dirtyLines.has(lineIndex)) {
|
|
682
|
-
const tokens = dirtyLines.get(lineIndex);
|
|
683
|
-
child.replaceChildren(...renderLineTokens(tokens, tokenizer.themeType));
|
|
684
|
-
dirtyLineIndexes.delete(lineIndex);
|
|
685
|
-
if (dirtyLineIndexes.size === 0) break;
|
|
686
|
-
}
|
|
687
|
-
}
|
|
688
|
-
}
|
|
689
|
-
}
|
|
690
|
-
}
|
|
691
706
|
if (dirtyLineIndexes.size > 0) for (const lineIndex of dirtyLineIndexes) {
|
|
692
707
|
const tokens = dirtyLines.get(lineIndex);
|
|
693
708
|
const lineNumber = String(lineIndex + 1);
|
|
@@ -699,7 +714,7 @@ var Editor = class {
|
|
|
699
714
|
},
|
|
700
715
|
children: renderLineTokens(tokens, tokenizer.themeType)
|
|
701
716
|
}, contentEl);
|
|
702
|
-
h("div", {
|
|
717
|
+
if (gutterEl !== void 0) h("div", {
|
|
703
718
|
dataset: {
|
|
704
719
|
lineType: "context",
|
|
705
720
|
columnNumber: lineNumber,
|
|
@@ -712,25 +727,30 @@ var Editor = class {
|
|
|
712
727
|
}, gutterEl);
|
|
713
728
|
}
|
|
714
729
|
}
|
|
715
|
-
if (change.lineDelta < 0) for (const
|
|
716
|
-
const
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
730
|
+
if (change.lineDelta < 0) for (const children of [contentEl.children, gutterEl?.children ?? []]) for (let i = children.length - 1; i >= 0; i--) {
|
|
731
|
+
const child = children[i];
|
|
732
|
+
const lineNumber = getLineNumberAttr(child) ?? getLineNumberAttr(child, "columnNumber");
|
|
733
|
+
if (lineNumber === void 0) continue;
|
|
734
|
+
if (lineNumber - 1 < change.lineCount) break;
|
|
735
|
+
child.remove();
|
|
736
|
+
}
|
|
737
|
+
const isDiff = Object.hasOwn(fileInstance, "fileDiff");
|
|
738
|
+
const didLineCountChange = change.lineDelta !== 0;
|
|
739
|
+
if (didLineCountChange) {
|
|
740
|
+
let gridRow = contentEl.children.length;
|
|
741
|
+
for (const child of contentEl.children) {
|
|
742
|
+
const { bufferSize } = child.dataset;
|
|
743
|
+
if (bufferSize !== void 0) gridRow += parseInt(bufferSize) - 1;
|
|
725
744
|
}
|
|
745
|
+
contentEl.style.gridRow = "span " + gridRow;
|
|
746
|
+
if (gutterEl !== void 0) gutterEl.style.gridRow = "span " + gridRow;
|
|
726
747
|
}
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
748
|
+
fileInstance.updateRenderCache(dirtyLines, tokenizer.themeType, isDiff ? !didLineCountChange : void 0);
|
|
749
|
+
if (didLineCountChange) fileInstance.applyDocumentChange(textDocument, newLineAnnotations, shouldUpdateBuffer);
|
|
750
|
+
if (newLineAnnotations !== void 0) {
|
|
751
|
+
this.#lineAnnotations = newLineAnnotations;
|
|
752
|
+
renderLineAnnotations(newLineAnnotations, contentEl, gutterEl);
|
|
730
753
|
}
|
|
731
|
-
component.applyLineChange?.(dirtyLines, tokenizer.themeType);
|
|
732
|
-
if (change.lineDelta !== 0 || isFileDiff) component.applyLayoutChange(textDocument, newLineAnnotations, shouldUpdateBuffer);
|
|
733
|
-
if (isFileDiff) this.#tokenizer?.stopBackgroundTokenize();
|
|
734
754
|
if (this.#options.__debug === true) console.log(`[diffs/editor] re-render in: ${round(performance.now() - t2)}ms,`, `tokenize in: ${round(t2 - t)}ms (${dirtyLines.size} dirty lines)`);
|
|
735
755
|
}
|
|
736
756
|
#handleInput(inputType, data) {
|
|
@@ -747,74 +767,38 @@ var Editor = class {
|
|
|
747
767
|
case "deleteContentForward":
|
|
748
768
|
this.#deleteSelectionText(true);
|
|
749
769
|
break;
|
|
770
|
+
case "deleteSoftLineBackward":
|
|
771
|
+
this.#deleteSoftLineBackward();
|
|
772
|
+
break;
|
|
750
773
|
case "deleteHardLineForward":
|
|
751
774
|
this.#deleteHardLineForward();
|
|
752
775
|
break;
|
|
776
|
+
case "deleteWordBackward":
|
|
777
|
+
this.#deleteWordBackward();
|
|
778
|
+
break;
|
|
753
779
|
case "insertTranspose":
|
|
754
780
|
this.#insertTranspose();
|
|
755
781
|
break;
|
|
756
782
|
default:
|
|
757
|
-
console.warn(`[diffs] Unknown input type: ${inputType}
|
|
783
|
+
console.warn(`[diffs] Unknown input type: ${inputType}`, data);
|
|
758
784
|
break;
|
|
759
785
|
}
|
|
760
786
|
}
|
|
761
|
-
#
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
}
|
|
774
|
-
const fragment = document.createDocumentFragment();
|
|
775
|
-
const renderCtx = {
|
|
776
|
-
fragment,
|
|
777
|
-
elements: /* @__PURE__ */ new Map()
|
|
778
|
-
};
|
|
779
|
-
if (selections.length > 0) {
|
|
780
|
-
const normalizedSelections = mergeOverlappingSelections(selections);
|
|
781
|
-
const primarySelection = normalizedSelections.at(-1);
|
|
782
|
-
this.#selections = normalizedSelections;
|
|
783
|
-
if (isCollapsedSelection(primarySelection)) {
|
|
784
|
-
const line = primarySelection.start.line + 1;
|
|
785
|
-
this.#fileInstance?.setSelectedLines({
|
|
786
|
-
start: line,
|
|
787
|
-
end: line
|
|
787
|
+
#focus(position, preventScroll = true) {
|
|
788
|
+
if (position !== void 0) {
|
|
789
|
+
this.#shouldIgnoreSelectionChange = true;
|
|
790
|
+
this.#setWindowSelection({
|
|
791
|
+
start: position,
|
|
792
|
+
end: position,
|
|
793
|
+
direction: DirectionNone
|
|
794
|
+
});
|
|
795
|
+
requestAnimationFrame(() => {
|
|
796
|
+
this.#contentElement?.focus({ preventScroll });
|
|
797
|
+
requestAnimationFrame(() => {
|
|
798
|
+
this.#shouldIgnoreSelectionChange = false;
|
|
788
799
|
});
|
|
789
|
-
}
|
|
790
|
-
|
|
791
|
-
gutterBuffer.querySelector(`[data-column-number="${pos.line + 1}"]`)?.setAttribute("data-active", "");
|
|
792
|
-
}
|
|
793
|
-
for (const selection of normalizedSelections) {
|
|
794
|
-
if (!isCollapsedSelection(selection)) this.#renderSelection(renderCtx, selection, "selection");
|
|
795
|
-
this.#renderCaret(renderCtx, selection, selection === primarySelection);
|
|
796
|
-
}
|
|
797
|
-
if (this.#options.enabledQuickEdit === true && !isCollapsedSelection(primarySelection)) this.#renderQuickEditIcon(renderCtx, primarySelection);
|
|
798
|
-
}
|
|
799
|
-
const textDocument = this.#textDocument;
|
|
800
|
-
if (this.#matches !== void 0 && textDocument !== void 0) {
|
|
801
|
-
const primarySelection = this.#selections?.at(-1);
|
|
802
|
-
const primaryStartOffset = primarySelection !== void 0 ? textDocument.offsetAt(primarySelection.start) : -1;
|
|
803
|
-
const primaryEndOffset = primarySelection !== void 0 ? textDocument.offsetAt(primarySelection.end) : -1;
|
|
804
|
-
for (const [startOffset, endOffset] of this.#matches) {
|
|
805
|
-
const selection = {
|
|
806
|
-
start: textDocument.positionAt(startOffset),
|
|
807
|
-
end: textDocument.positionAt(endOffset),
|
|
808
|
-
direction: DirectionNone
|
|
809
|
-
};
|
|
810
|
-
const isFocused = primaryStartOffset === startOffset && primaryEndOffset === endOffset;
|
|
811
|
-
this.#renderSelection(renderCtx, selection, "match", isFocused);
|
|
812
|
-
}
|
|
813
|
-
}
|
|
814
|
-
this.#overlayElement?.appendChild(fragment);
|
|
815
|
-
this.#selectionElements?.forEach((el) => el.remove());
|
|
816
|
-
this.#selectionElements?.clear();
|
|
817
|
-
this.#selectionElements = renderCtx.elements;
|
|
800
|
+
});
|
|
801
|
+
} else this.#contentElement?.focus({ preventScroll });
|
|
818
802
|
}
|
|
819
803
|
#setWindowSelection(selection) {
|
|
820
804
|
const winSelection = window.getSelection();
|
|
@@ -838,29 +822,13 @@ var Editor = class {
|
|
|
838
822
|
console.error("[diffs/editor] failed to update window selection:", err);
|
|
839
823
|
}
|
|
840
824
|
}
|
|
841
|
-
#
|
|
842
|
-
if (position !== void 0) {
|
|
843
|
-
this.#shouldIgnoreSelectionChange = true;
|
|
844
|
-
this.#setWindowSelection({
|
|
845
|
-
start: position,
|
|
846
|
-
end: position,
|
|
847
|
-
direction: DirectionNone
|
|
848
|
-
});
|
|
849
|
-
requestAnimationFrame(() => {
|
|
850
|
-
this.#contentElement?.focus({ preventScroll });
|
|
851
|
-
requestAnimationFrame(() => {
|
|
852
|
-
this.#shouldIgnoreSelectionChange = false;
|
|
853
|
-
});
|
|
854
|
-
});
|
|
855
|
-
} else this.#contentElement?.focus({ preventScroll });
|
|
856
|
-
}
|
|
857
|
-
#scrollToPrimaryCaret(noFocus = false) {
|
|
858
|
-
const primaryCaretElement = this.#primaryCaretElement;
|
|
825
|
+
#scrollToPrimaryCaret(noFocus = false, scrollPosition = "nearest") {
|
|
859
826
|
const primarySelection = this.#selections?.at(-1);
|
|
860
827
|
if (primarySelection === void 0) return;
|
|
828
|
+
const primaryCaretElement = this.#primaryCaretElement;
|
|
861
829
|
if (primaryCaretElement !== void 0) {
|
|
862
830
|
primaryCaretElement.scrollIntoView({
|
|
863
|
-
block:
|
|
831
|
+
block: scrollPosition,
|
|
864
832
|
inline: "nearest"
|
|
865
833
|
});
|
|
866
834
|
if (!noFocus) this.#focus(primarySelection.direction === DirectionBackward ? primarySelection.end : primarySelection.start);
|
|
@@ -877,7 +845,7 @@ var Editor = class {
|
|
|
877
845
|
return `${componentTop + top}px ${end}px 0 ${start}px`;
|
|
878
846
|
}
|
|
879
847
|
#scrollToLine(line, char = 0, noFocus = false) {
|
|
880
|
-
this.
|
|
848
|
+
this.__postponeBackgroundTokenizeToNextFrame();
|
|
881
849
|
const virtualCaret = h("div", { style: {
|
|
882
850
|
position: "absolute",
|
|
883
851
|
left: "0",
|
|
@@ -899,23 +867,98 @@ var Editor = class {
|
|
|
899
867
|
line,
|
|
900
868
|
character: char
|
|
901
869
|
});
|
|
870
|
+
this.#scrollingToLine = void 0;
|
|
871
|
+
this.#scrollingToLineChar = void 0;
|
|
872
|
+
this.#scrollingToLineNoFocus = false;
|
|
902
873
|
} else {
|
|
903
|
-
|
|
874
|
+
let yFix = 0;
|
|
875
|
+
if (this.#scrollingToLine === line && this.#contentElement !== void 0) for (let i = this.#contentElement.childElementCount - 1; i >= 0; i--) {
|
|
876
|
+
const child = this.#contentElement.children[i];
|
|
877
|
+
const lineType = child.dataset.lineType;
|
|
878
|
+
const lineNumber = getLineNumberAttr(child);
|
|
879
|
+
if (lineType !== void 0 && isLineEditable(lineType) && lineNumber !== void 0) {
|
|
880
|
+
yFix = (line - lineNumber) * this.#metrics.lineHeight;
|
|
881
|
+
break;
|
|
882
|
+
}
|
|
883
|
+
}
|
|
884
|
+
const approximateLineY = ((this.#lineAnnotations ?? []).filter((annotation) => annotation.lineNumber < line).length + line) * this.#metrics.lineHeight + yFix;
|
|
904
885
|
virtualCaret.style.top = approximateLineY + "px";
|
|
905
886
|
this.#fileContainer?.shadowRoot?.appendChild(virtualCaret);
|
|
906
|
-
this.#scrollingToLine = line;
|
|
907
|
-
this.#scrollingToLineChar = char;
|
|
908
|
-
this.#scrollingToLineNoFocus = noFocus;
|
|
909
887
|
virtualCaret.scrollIntoView({
|
|
910
888
|
block: "center",
|
|
911
889
|
inline: "nearest"
|
|
912
890
|
});
|
|
891
|
+
if (this.#scrollingToLine === line && yFix === 0) {
|
|
892
|
+
this.#scrollingToLine = void 0;
|
|
893
|
+
this.#scrollingToLineChar = void 0;
|
|
894
|
+
this.#scrollingToLineNoFocus = false;
|
|
895
|
+
} else {
|
|
896
|
+
this.#scrollingToLine = line;
|
|
897
|
+
this.#scrollingToLineChar = char;
|
|
898
|
+
this.#scrollingToLineNoFocus = noFocus;
|
|
899
|
+
}
|
|
913
900
|
}
|
|
914
901
|
virtualCaret.remove();
|
|
915
902
|
}
|
|
916
|
-
#
|
|
903
|
+
#updateSelections(selections) {
|
|
904
|
+
this.__postponeBackgroundTokenizeToNextFrame();
|
|
905
|
+
this.#primaryCaretElement = void 0;
|
|
906
|
+
this.#fileInstance?.setSelectedLines(null);
|
|
907
|
+
this.#gutterElement?.querySelectorAll("[data-active]").forEach((el) => el.removeAttribute("data-active"));
|
|
908
|
+
if (selections.length === 0 && this.#matches === void 0 && this.#markerRenderer === void 0) {
|
|
909
|
+
this.#selections = void 0;
|
|
910
|
+
this.#overlayElements?.forEach((el) => el.remove());
|
|
911
|
+
this.#overlayElements?.clear();
|
|
912
|
+
return;
|
|
913
|
+
}
|
|
914
|
+
const fragment = document.createDocumentFragment();
|
|
915
|
+
const renderCtx = {
|
|
916
|
+
fragment,
|
|
917
|
+
elements: /* @__PURE__ */ new Map()
|
|
918
|
+
};
|
|
919
|
+
if (selections.length > 0) {
|
|
920
|
+
const normalizedSelections = mergeOverlappingSelections(selections);
|
|
921
|
+
const primarySelection = normalizedSelections.at(-1);
|
|
922
|
+
this.#selections = normalizedSelections;
|
|
923
|
+
if (isCollapsedSelection(primarySelection)) {
|
|
924
|
+
const line = primarySelection.start.line + 1;
|
|
925
|
+
this.#fileInstance?.setSelectedLines({
|
|
926
|
+
start: line,
|
|
927
|
+
end: line
|
|
928
|
+
});
|
|
929
|
+
} else if (this.#gutterElement !== void 0) {
|
|
930
|
+
const pos = getCaretPosition(primarySelection);
|
|
931
|
+
this.#gutterElement.querySelector(`[data-column-number="${pos.line + 1}"]`)?.setAttribute("data-active", "");
|
|
932
|
+
}
|
|
933
|
+
for (const selection of normalizedSelections) {
|
|
934
|
+
if (!isCollapsedSelection(selection)) this.#renderSelection(renderCtx, "selection", selection);
|
|
935
|
+
this.#renderCaret(renderCtx, selection, selection === primarySelection);
|
|
936
|
+
}
|
|
937
|
+
if (this.#options.enabledSelectionAction === true && !isCollapsedSelection(primarySelection)) this.#renderSelectionActionIcon(renderCtx, primarySelection);
|
|
938
|
+
}
|
|
939
|
+
const textDocument = this.#textDocument;
|
|
940
|
+
if (this.#matches !== void 0 && textDocument !== void 0) {
|
|
941
|
+
const primarySelection = this.#selections?.at(-1);
|
|
942
|
+
const primaryStartOffset = primarySelection !== void 0 ? textDocument.offsetAt(primarySelection.start) : -1;
|
|
943
|
+
const primaryEndOffset = primarySelection !== void 0 ? textDocument.offsetAt(primarySelection.end) : -1;
|
|
944
|
+
for (const [startOffset, endOffset] of this.#matches) {
|
|
945
|
+
const range = {
|
|
946
|
+
start: textDocument.positionAt(startOffset),
|
|
947
|
+
end: textDocument.positionAt(endOffset)
|
|
948
|
+
};
|
|
949
|
+
const isFocused = primaryStartOffset === startOffset && primaryEndOffset === endOffset;
|
|
950
|
+
this.#renderSelection(renderCtx, "match", range, isFocused ? "focus" : void 0);
|
|
951
|
+
}
|
|
952
|
+
}
|
|
953
|
+
if (this.#markerRenderer !== void 0 && textDocument !== void 0) for (const marker of this.#markerRenderer.markers) this.#renderSelection(renderCtx, "marker", marker, markerSeverityDatasetKey(marker.severity));
|
|
954
|
+
this.#overlayElement?.appendChild(fragment);
|
|
955
|
+
this.#overlayElements?.forEach((el) => el.remove());
|
|
956
|
+
this.#overlayElements?.clear();
|
|
957
|
+
this.#overlayElements = renderCtx.elements;
|
|
958
|
+
}
|
|
959
|
+
#renderSelection(renderCtx, type, range, extraDataset) {
|
|
917
960
|
if (this.#textDocument === void 0) return;
|
|
918
|
-
const { start, end } =
|
|
961
|
+
const { start, end } = range;
|
|
919
962
|
for (let line = start.line; line <= end.line; line++) {
|
|
920
963
|
if (!this.#isLineVisible(line)) continue;
|
|
921
964
|
const isLastLine = line === end.line;
|
|
@@ -925,20 +968,22 @@ var Editor = class {
|
|
|
925
968
|
if (this.#wrap) {
|
|
926
969
|
const contentWidth = this.#getContentWidth();
|
|
927
970
|
if (2 * this.#metrics.ch + this.#metrics.measureTextWidth(lineText) > contentWidth) {
|
|
928
|
-
this.#renderWrappedSelection(renderCtx, line, lineText, startChar, endChar, isLastLine, type,
|
|
971
|
+
this.#renderWrappedSelection(renderCtx, line, lineText, startChar, endChar, isLastLine, type, extraDataset);
|
|
929
972
|
continue;
|
|
930
973
|
}
|
|
931
974
|
}
|
|
932
975
|
let left = 0;
|
|
933
976
|
let width = 0;
|
|
977
|
+
let paddingEnd = 0;
|
|
934
978
|
if (startChar === 0) left = this.#getGutterWidth() + this.#metrics.ch;
|
|
935
979
|
else left = this.#getCharX(line, startChar)[0];
|
|
936
|
-
if (
|
|
937
|
-
|
|
938
|
-
this.#
|
|
980
|
+
if (!isLastLine && type === "selection") paddingEnd = this.#metrics.ch;
|
|
981
|
+
if (startChar === endChar) width = paddingEnd;
|
|
982
|
+
else width = this.#getCharX(line, endChar)[0] - left + paddingEnd;
|
|
983
|
+
this.#renderSelectionBlock(renderCtx, type, line, 0, left, width, extraDataset);
|
|
939
984
|
}
|
|
940
985
|
}
|
|
941
|
-
#renderWrappedSelection(renderCtx, line, lineText, startChar, endChar, isLastLine, type,
|
|
986
|
+
#renderWrappedSelection(renderCtx, line, lineText, startChar, endChar, isLastLine, type, extraDataset) {
|
|
942
987
|
const wrapOffsets = this.#wrapLineText(line);
|
|
943
988
|
const segmentCount = wrapOffsets.length - 1;
|
|
944
989
|
const offsetLeft = this.#getGutterWidth() + this.#metrics.ch;
|
|
@@ -950,29 +995,31 @@ var Editor = class {
|
|
|
950
995
|
if (wrapStartChar > wrapEndChar) continue;
|
|
951
996
|
let segmentLeft;
|
|
952
997
|
let segmentWidth;
|
|
998
|
+
let paddingEnd = 0;
|
|
953
999
|
if (wrapStartChar === 0) segmentLeft = offsetLeft;
|
|
954
1000
|
else {
|
|
955
1001
|
const prefixInSegment = lineText.slice(segmentStart, wrapStartChar);
|
|
956
1002
|
const prefixAsciiColumns = getExpandedAsciiTextColumns(prefixInSegment, this.#metrics.tabSize);
|
|
957
1003
|
segmentLeft = offsetLeft + (prefixAsciiColumns !== -1 ? prefixAsciiColumns * this.#metrics.ch : this.#metrics.measureTextWidth(prefixInSegment));
|
|
958
1004
|
}
|
|
959
|
-
if (
|
|
1005
|
+
if (!isLastLine && wrapLine === segmentCount - 1 && type === "selection") paddingEnd = this.#metrics.ch;
|
|
1006
|
+
if (wrapStartChar === wrapEndChar) segmentWidth = paddingEnd;
|
|
960
1007
|
else {
|
|
961
1008
|
const selectionInSegment = lineText.slice(wrapStartChar, wrapEndChar);
|
|
962
1009
|
const selectionAsciiWidth = getExpandedAsciiTextColumns(selectionInSegment, this.#metrics.tabSize);
|
|
963
1010
|
segmentWidth = selectionAsciiWidth !== -1 ? selectionAsciiWidth * this.#metrics.ch : this.#metrics.measureTextWidth(selectionInSegment);
|
|
964
|
-
|
|
1011
|
+
segmentWidth += paddingEnd;
|
|
965
1012
|
}
|
|
966
|
-
this.#renderSelectionBlock(renderCtx, line, wrapLine, segmentLeft, segmentWidth,
|
|
1013
|
+
this.#renderSelectionBlock(renderCtx, type, line, wrapLine, segmentLeft, segmentWidth, extraDataset);
|
|
967
1014
|
}
|
|
968
1015
|
}
|
|
969
|
-
#renderSelectionBlock(renderCtx, line, wrapLine, left, width,
|
|
1016
|
+
#renderSelectionBlock(renderCtx, type, line, wrapLine, left, width, extraDataset) {
|
|
970
1017
|
if (width === 0) return;
|
|
971
1018
|
const { ch, lineHeight } = this.#metrics;
|
|
972
1019
|
const y = this.#getLineY(line) + wrapLine * lineHeight;
|
|
973
1020
|
const css = `width:${width}px;transform:translateX(${left}px) translateY(${y}px);`;
|
|
974
|
-
const cacheKey = `${type}
|
|
975
|
-
const
|
|
1021
|
+
const cacheKey = `${type}-${left}-${y}-${width}${extraDataset ?? ""}`;
|
|
1022
|
+
const overlayEls = this.#overlayElements;
|
|
976
1023
|
const rounded = (this.#options.roundedSelection ?? true) && type === "selection";
|
|
977
1024
|
const addRoundedCorner = (line$1, wrapLine$1, left$1, radius) => {
|
|
978
1025
|
const top = this.#getLineY(line$1) + wrapLine$1 * lineHeight;
|
|
@@ -995,9 +1042,9 @@ var Editor = class {
|
|
|
995
1042
|
}
|
|
996
1043
|
let cornerEl = renderCtx.elements.get(cacheKey$1);
|
|
997
1044
|
if (cornerEl !== void 0) return;
|
|
998
|
-
if (
|
|
999
|
-
cornerEl =
|
|
1000
|
-
|
|
1045
|
+
if (overlayEls?.has(cacheKey$1) === true) {
|
|
1046
|
+
cornerEl = overlayEls.get(cacheKey$1);
|
|
1047
|
+
overlayEls.delete(cacheKey$1);
|
|
1001
1048
|
} else cornerEl = h("div", {
|
|
1002
1049
|
dataset: "selectionRange",
|
|
1003
1050
|
style: { cssText: css$1 },
|
|
@@ -1050,16 +1097,13 @@ var Editor = class {
|
|
|
1050
1097
|
if (rounded) addRadiusStyle(rangeEl);
|
|
1051
1098
|
return;
|
|
1052
1099
|
}
|
|
1053
|
-
if (
|
|
1054
|
-
rangeEl =
|
|
1055
|
-
|
|
1056
|
-
} else {
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
}, renderCtx.fragment);
|
|
1061
|
-
if (type === "match" && isFocused === true) rangeEl.dataset.focus = "";
|
|
1062
|
-
}
|
|
1100
|
+
if (overlayEls?.has(cacheKey) === true) {
|
|
1101
|
+
rangeEl = overlayEls.get(cacheKey);
|
|
1102
|
+
overlayEls.delete(cacheKey);
|
|
1103
|
+
} else rangeEl = h("div", {
|
|
1104
|
+
dataset: extraDataset ? [type + "Range", extraDataset] : type + "Range",
|
|
1105
|
+
style: { cssText: css }
|
|
1106
|
+
}, renderCtx.fragment);
|
|
1063
1107
|
if (rounded) addRadiusStyle(rangeEl);
|
|
1064
1108
|
renderCtx.elements.set(cacheKey, rangeEl);
|
|
1065
1109
|
}
|
|
@@ -1079,43 +1123,40 @@ var Editor = class {
|
|
|
1079
1123
|
this.#primaryCaretElement = caretEl;
|
|
1080
1124
|
}
|
|
1081
1125
|
}
|
|
1082
|
-
#
|
|
1126
|
+
#renderSelectionActionIcon(renderCtx, selection) {
|
|
1083
1127
|
const line = getCaretPosition(selection).line;
|
|
1084
1128
|
if (!this.#isLineVisible(line)) return;
|
|
1085
1129
|
const [left, wrapLine] = this.#getCharX(line, 0);
|
|
1086
|
-
const cacheKey = "
|
|
1130
|
+
const cacheKey = "selectionActionIcon-" + line + "(" + wrapLine + ")";
|
|
1087
1131
|
if (renderCtx.elements.has(cacheKey)) return;
|
|
1088
|
-
const
|
|
1089
|
-
const
|
|
1090
|
-
this.#
|
|
1091
|
-
this.#
|
|
1132
|
+
const selectionActionIcon = SelectionActionWidget.renderIcon(left, this.#getLineY(line) + wrapLine * this.#metrics.lineHeight, renderCtx.fragment, () => {
|
|
1133
|
+
const cleanUp = () => {
|
|
1134
|
+
this.#selectionAction?.cleanup();
|
|
1135
|
+
this.#selectionAction = void 0;
|
|
1092
1136
|
};
|
|
1093
1137
|
const handleWidgetDomResize = () => {
|
|
1094
1138
|
this.#lineYCache.clear();
|
|
1095
1139
|
if (this.#selections !== void 0) this.#updateSelections(this.#selections);
|
|
1096
1140
|
};
|
|
1097
|
-
|
|
1141
|
+
cleanUp();
|
|
1098
1142
|
const textDocument = this.#textDocument;
|
|
1099
|
-
const
|
|
1143
|
+
const renderSelectionAction = this.#options.renderSelectionAction;
|
|
1100
1144
|
const fileContainer = this.#fileContainer;
|
|
1101
|
-
if (textDocument === void 0 ||
|
|
1145
|
+
if (textDocument === void 0 || renderSelectionAction === void 0 || fileContainer == null) return;
|
|
1102
1146
|
const line$1 = selection.end.line;
|
|
1103
1147
|
const lineText = textDocument.getLineText(line$1);
|
|
1104
|
-
const
|
|
1148
|
+
const selectionActionElement = renderSelectionAction({
|
|
1105
1149
|
textDocument,
|
|
1106
1150
|
selection,
|
|
1107
|
-
applyEdits: (edits) =>
|
|
1108
|
-
const change = textDocument.applyEdits(edits, true, this.#selections);
|
|
1109
|
-
if (change !== void 0) this.#applyChange(change);
|
|
1110
|
-
},
|
|
1151
|
+
applyEdits: (edits) => this.applyEdits(edits, true),
|
|
1111
1152
|
getSelectionText: () => {
|
|
1112
1153
|
return this.#textDocument?.getText(selection) ?? "";
|
|
1113
1154
|
},
|
|
1114
1155
|
replaceSelectionText: (text) => {
|
|
1115
|
-
this.#replaceSelectionText(text);
|
|
1156
|
+
this.#replaceSelectionText(text, [selection]);
|
|
1116
1157
|
},
|
|
1117
1158
|
close: () => {
|
|
1118
|
-
|
|
1159
|
+
cleanUp();
|
|
1119
1160
|
handleWidgetDomResize();
|
|
1120
1161
|
this.#scrollToPrimaryCaret();
|
|
1121
1162
|
}
|
|
@@ -1127,13 +1168,20 @@ var Editor = class {
|
|
|
1127
1168
|
else if (charCode === 9) leadingWhitespaces += this.#metrics.tabSize;
|
|
1128
1169
|
else break;
|
|
1129
1170
|
}
|
|
1130
|
-
this.#
|
|
1171
|
+
this.#selectionAction = new SelectionActionWidget(line$1, selectionActionElement, fileContainer, leadingWhitespaces, handleWidgetDomResize);
|
|
1131
1172
|
this.#updateSelections([selection]);
|
|
1132
|
-
if (this.#isLineVisible(line$1) && this.#contentElement !== void 0) this.#
|
|
1173
|
+
if (this.#isLineVisible(line$1) && this.#contentElement !== void 0) this.#selectionAction.render(this.#contentElement);
|
|
1133
1174
|
});
|
|
1134
|
-
renderCtx.elements.set(cacheKey,
|
|
1175
|
+
renderCtx.elements.set(cacheKey, selectionActionIcon);
|
|
1135
1176
|
}
|
|
1136
|
-
#
|
|
1177
|
+
#openSearchPanel(mode) {
|
|
1178
|
+
if (this.#searchPanel !== void 0) {
|
|
1179
|
+
this.#searchPanel.setMode(mode);
|
|
1180
|
+
return;
|
|
1181
|
+
}
|
|
1182
|
+
this.#renderSearchPanel(mode);
|
|
1183
|
+
}
|
|
1184
|
+
#renderSearchPanel(mode) {
|
|
1137
1185
|
this.#searchPanel?.cleanup();
|
|
1138
1186
|
const textDocument = this.#textDocument;
|
|
1139
1187
|
const preElement = this.#fileContainer?.shadowRoot?.querySelector("pre");
|
|
@@ -1163,15 +1211,37 @@ var Editor = class {
|
|
|
1163
1211
|
textDocument,
|
|
1164
1212
|
containerElement: preElement,
|
|
1165
1213
|
defaultQuery,
|
|
1214
|
+
mode,
|
|
1166
1215
|
initialMatch,
|
|
1167
1216
|
scrollToMatch,
|
|
1168
|
-
|
|
1217
|
+
applyReplace: (edits) => {
|
|
1218
|
+
if (edits.length === 0) return;
|
|
1219
|
+
const change = textDocument.applyEdits(edits.map((edit) => ({
|
|
1220
|
+
range: {
|
|
1221
|
+
start: textDocument.positionAt(edit.start),
|
|
1222
|
+
end: textDocument.positionAt(edit.end)
|
|
1223
|
+
},
|
|
1224
|
+
newText: edit.text
|
|
1225
|
+
})), true, this.#selections);
|
|
1226
|
+
if (change !== void 0) this.#applyChange(change, void 0, this.#applyChangeToLineAnnotations(change), { skipSearchRefresh: true });
|
|
1227
|
+
},
|
|
1228
|
+
onUpdate: (allMatches, options) => {
|
|
1169
1229
|
if (allMatches.length === 0) {
|
|
1170
1230
|
this.#matches = void 0;
|
|
1171
1231
|
this.#updateSelections(this.#selections ?? []);
|
|
1172
1232
|
return;
|
|
1173
1233
|
}
|
|
1174
1234
|
this.#matches = allMatches;
|
|
1235
|
+
if (options?.syncSelection === false) {
|
|
1236
|
+
this.#updateSelections(this.#selections ?? []);
|
|
1237
|
+
const primarySelection$1 = this.#selections?.at(-1);
|
|
1238
|
+
if (primarySelection$1 !== void 0) {
|
|
1239
|
+
const startOffset = textDocument.offsetAt(primarySelection$1.start);
|
|
1240
|
+
const endOffset = textDocument.offsetAt(primarySelection$1.end);
|
|
1241
|
+
for (const match of allMatches) if (match[0] === startOffset && match[1] === endOffset) return match;
|
|
1242
|
+
}
|
|
1243
|
+
return;
|
|
1244
|
+
}
|
|
1175
1245
|
const primarySelection = this.#selections?.at(-1);
|
|
1176
1246
|
let searchOffset = 0;
|
|
1177
1247
|
let nextMatch;
|
|
@@ -1181,8 +1251,7 @@ var Editor = class {
|
|
|
1181
1251
|
break;
|
|
1182
1252
|
}
|
|
1183
1253
|
if (nextMatch !== void 0) scrollToMatch(nextMatch, true);
|
|
1184
|
-
this.#
|
|
1185
|
-
this.#updateSelections(this.#selections ?? []);
|
|
1254
|
+
else this.#updateSelections(this.#selections ?? []);
|
|
1186
1255
|
return nextMatch;
|
|
1187
1256
|
},
|
|
1188
1257
|
onClose: () => {
|
|
@@ -1200,8 +1269,7 @@ var Editor = class {
|
|
|
1200
1269
|
if (textDocument === void 0 || selections === void 0) return "";
|
|
1201
1270
|
return getSelectionText(textDocument, selections);
|
|
1202
1271
|
}
|
|
1203
|
-
#replaceSelectionText(text) {
|
|
1204
|
-
const selections = this.#selections;
|
|
1272
|
+
#replaceSelectionText(text, selections = this.#selections) {
|
|
1205
1273
|
if (selections === void 0) return;
|
|
1206
1274
|
const textDocument = this.#textDocument;
|
|
1207
1275
|
const primarySelection = selections.at(-1);
|
|
@@ -1219,21 +1287,44 @@ var Editor = class {
|
|
|
1219
1287
|
if (selections === void 0 || textDocument === void 0) return;
|
|
1220
1288
|
const primarySelection = selections.at(-1);
|
|
1221
1289
|
if (primarySelection === void 0) return;
|
|
1222
|
-
|
|
1290
|
+
let edit;
|
|
1291
|
+
if (isCollapsedSelection(primarySelection)) {
|
|
1223
1292
|
const offset = textDocument.offsetAt(primarySelection.start);
|
|
1224
1293
|
const nextOffset = forward ? Math.min(textDocument.getText().length, offset + 1) : Math.max(0, offset - 1);
|
|
1225
|
-
|
|
1294
|
+
edit = {
|
|
1226
1295
|
start: Math.min(offset, nextOffset),
|
|
1227
1296
|
end: Math.max(offset, nextOffset),
|
|
1228
1297
|
text: ""
|
|
1229
1298
|
};
|
|
1230
|
-
}
|
|
1299
|
+
} else edit = {
|
|
1231
1300
|
start: textDocument.offsetAt(primarySelection.start),
|
|
1232
1301
|
end: textDocument.offsetAt(primarySelection.end),
|
|
1233
1302
|
text: ""
|
|
1234
1303
|
};
|
|
1235
1304
|
this.#applyResolvedTextEdit(edit);
|
|
1236
1305
|
}
|
|
1306
|
+
#deleteSoftLineBackward() {
|
|
1307
|
+
const selections = this.#selections;
|
|
1308
|
+
const textDocument = this.#textDocument;
|
|
1309
|
+
if (selections === void 0 || textDocument === void 0) return;
|
|
1310
|
+
const { nextSelections, change } = applyDeleteSoftLineBackwardToSelections(textDocument, selections, this.#wrap ? (line, character) => {
|
|
1311
|
+
const wrapOffsets = this.#wrapLineText(line);
|
|
1312
|
+
for (let w = 0; w + 1 < wrapOffsets.length; w++) {
|
|
1313
|
+
const segmentStart = wrapOffsets[w];
|
|
1314
|
+
const segmentEnd = wrapOffsets[w + 1];
|
|
1315
|
+
if (character >= segmentStart && character <= segmentEnd) return segmentStart;
|
|
1316
|
+
}
|
|
1317
|
+
return 0;
|
|
1318
|
+
} : void 0, this.#lineAnnotations);
|
|
1319
|
+
if (change !== void 0) this.#applyChange(change, nextSelections, this.#applyChangeToLineAnnotations(change));
|
|
1320
|
+
}
|
|
1321
|
+
#deleteWordBackward() {
|
|
1322
|
+
const selections = this.#selections;
|
|
1323
|
+
const textDocument = this.#textDocument;
|
|
1324
|
+
if (selections === void 0 || textDocument === void 0) return;
|
|
1325
|
+
const { nextSelections, change } = applyDeleteWordBackwardToSelections(textDocument, selections, this.#lineAnnotations);
|
|
1326
|
+
if (change !== void 0) this.#applyChange(change, nextSelections, this.#applyChangeToLineAnnotations(change));
|
|
1327
|
+
}
|
|
1237
1328
|
#deleteHardLineForward() {
|
|
1238
1329
|
const selections = this.#selections;
|
|
1239
1330
|
const textDocument = this.#textDocument;
|
|
@@ -1253,23 +1344,28 @@ var Editor = class {
|
|
|
1253
1344
|
const { nextSelections, change } = applyTextChangeToSelections(this.#textDocument, this.#selections, edit, this.#lineAnnotations, this.#metrics.tabSize);
|
|
1254
1345
|
if (change !== void 0) this.#applyChange(change, nextSelections, this.#applyChangeToLineAnnotations(change));
|
|
1255
1346
|
}
|
|
1256
|
-
#
|
|
1347
|
+
#getFileRef() {
|
|
1257
1348
|
const fileContents = this.#fileContents;
|
|
1258
1349
|
const textDocument = this.#textDocument;
|
|
1350
|
+
if (fileContents === void 0 || textDocument === void 0) return;
|
|
1351
|
+
const { contents: _,...file } = fileContents;
|
|
1352
|
+
Object.defineProperty(file, "contents", {
|
|
1353
|
+
enumerable: true,
|
|
1354
|
+
get: () => textDocument.getText()
|
|
1355
|
+
});
|
|
1356
|
+
return file;
|
|
1357
|
+
}
|
|
1358
|
+
#applyChange(change, selections, newLineAnnotations, options) {
|
|
1359
|
+
const fileRef = this.#getFileRef();
|
|
1259
1360
|
const onChange = this.#options.onChange;
|
|
1260
|
-
if (
|
|
1261
|
-
const { contents: _,...file } = fileContents;
|
|
1262
|
-
let contents;
|
|
1263
|
-
Object.defineProperty(file, "contents", { get: () => contents ??= textDocument.getText() });
|
|
1264
|
-
this.#emitChange(file, newLineAnnotations ?? this.#lineAnnotations);
|
|
1265
|
-
}
|
|
1361
|
+
if (fileRef !== void 0 && onChange !== void 0) onChange(fileRef, newLineAnnotations ?? this.#lineAnnotations);
|
|
1266
1362
|
if (change.lineDelta !== 0) {
|
|
1267
1363
|
for (const line of this.#lineYCache.keys()) if (line >= change.startLine) this.#lineYCache.delete(line);
|
|
1268
1364
|
}
|
|
1269
1365
|
if (this.#wrap) {
|
|
1270
1366
|
for (const line of this.#wrapLineOffsetsCache.keys()) if (line >= change.startLine) this.#wrapLineOffsetsCache.delete(line);
|
|
1271
1367
|
}
|
|
1272
|
-
this.#
|
|
1368
|
+
this.#lastAccessedCharX = void 0;
|
|
1273
1369
|
let renderRange = this.#renderRange;
|
|
1274
1370
|
let shouldUpdateBuffer;
|
|
1275
1371
|
if (renderRange !== void 0 && selections !== void 0 && selections.length > 0) {
|
|
@@ -1282,6 +1378,7 @@ var Editor = class {
|
|
|
1282
1378
|
else if (primarySelection.end.line > renderRangeEndLine) shouldUpdateBuffer = true;
|
|
1283
1379
|
}
|
|
1284
1380
|
this.#rerender(change, newLineAnnotations, renderRange, shouldUpdateBuffer);
|
|
1381
|
+
if (options?.skipSearchRefresh !== true && this.#searchPanel !== void 0 && this.#matches !== void 0) this.#searchPanel.updateMatches({ syncSelection: false });
|
|
1285
1382
|
if (selections !== void 0) {
|
|
1286
1383
|
this.#updateSelections(selections);
|
|
1287
1384
|
if (this.#primaryCaretElement !== void 0) this.#primaryCaretElement.scrollIntoView({
|
|
@@ -1305,28 +1402,40 @@ var Editor = class {
|
|
|
1305
1402
|
}
|
|
1306
1403
|
}
|
|
1307
1404
|
#getLineElement(line) {
|
|
1405
|
+
const lastAccessed = this.#lastAccessedLineElement;
|
|
1406
|
+
if (lastAccessed !== void 0 && lastAccessed[0] === line) return lastAccessed[1];
|
|
1308
1407
|
const contentElement = this.#contentElement;
|
|
1309
1408
|
if (contentElement === void 0) return;
|
|
1310
|
-
|
|
1409
|
+
let lineElement = null;
|
|
1410
|
+
if (this.#renderRange !== void 0) {
|
|
1311
1411
|
const { startingLine } = this.#renderRange;
|
|
1312
1412
|
const { children } = contentElement;
|
|
1313
1413
|
for (let i = line - startingLine; i <= children.length; i++) {
|
|
1314
1414
|
const child = children[i];
|
|
1315
|
-
|
|
1316
|
-
const
|
|
1317
|
-
|
|
1415
|
+
if (child === void 0) break;
|
|
1416
|
+
const lineNumber = getLineNumberAttr(child);
|
|
1417
|
+
const lineType = child.dataset.lineType;
|
|
1418
|
+
if (lineNumber !== void 0 && lineNumber === line + 1 && lineType !== void 0 && isLineEditable(lineType)) {
|
|
1419
|
+
lineElement = child;
|
|
1420
|
+
break;
|
|
1421
|
+
}
|
|
1318
1422
|
}
|
|
1319
1423
|
}
|
|
1320
|
-
|
|
1321
|
-
|
|
1424
|
+
lineElement ??= contentElement.querySelector(`[data-line="${line + 1}"]`);
|
|
1425
|
+
if (lineElement !== null) {
|
|
1426
|
+
if (lastAccessed !== void 0) {
|
|
1427
|
+
lastAccessed[0] = line;
|
|
1428
|
+
lastAccessed[1] = lineElement;
|
|
1429
|
+
} else this.#lastAccessedLineElement = [line, lineElement];
|
|
1430
|
+
return lineElement;
|
|
1431
|
+
}
|
|
1322
1432
|
}
|
|
1323
1433
|
#getGutterWidth() {
|
|
1324
|
-
|
|
1325
|
-
if (gutterElement == null || !(gutterElement instanceof HTMLElement) || !gutterElement.hasAttribute("data-gutter")) return 0;
|
|
1434
|
+
if (this.#gutterElement === void 0) return 0;
|
|
1326
1435
|
if (this.#gutterWidthCache === void 0) {
|
|
1327
1436
|
const diffsColumnNumberWidth = this.#contentElement?.parentElement?.style.getPropertyValue("--diffs-column-number-width");
|
|
1328
1437
|
if (diffsColumnNumberWidth !== void 0 && diffsColumnNumberWidth.length > 2 && diffsColumnNumberWidth.endsWith("px")) this.#gutterWidthCache = parseInt(diffsColumnNumberWidth.slice(0, -2), 10);
|
|
1329
|
-
else this.#gutterWidthCache = gutterElement.offsetWidth;
|
|
1438
|
+
else this.#gutterWidthCache = this.#gutterElement.offsetWidth;
|
|
1330
1439
|
}
|
|
1331
1440
|
return this.#gutterWidthCache;
|
|
1332
1441
|
}
|
|
@@ -1344,12 +1453,12 @@ var Editor = class {
|
|
|
1344
1453
|
if (cachedY !== void 0) return cachedY;
|
|
1345
1454
|
const lineElement = this.#getLineElement(line);
|
|
1346
1455
|
if (lineElement === void 0) return -1;
|
|
1347
|
-
const y = lineElement.offsetTop + this.#
|
|
1456
|
+
const y = lineElement.offsetTop + this.#metrics.paddingTop;
|
|
1348
1457
|
this.#lineYCache.set(line, y);
|
|
1349
1458
|
return y;
|
|
1350
1459
|
}
|
|
1351
1460
|
#getCharX(line, char) {
|
|
1352
|
-
if (this.#
|
|
1461
|
+
if (this.#lastAccessedCharX !== void 0 && this.#lastAccessedCharX[0] === line && this.#lastAccessedCharX[1] === char) return [this.#lastAccessedCharX[2], this.#lastAccessedCharX[3]];
|
|
1353
1462
|
const lineText = this.#textDocument?.getLineText(line);
|
|
1354
1463
|
const offsetLeft = this.#getGutterWidth() + this.#metrics.ch;
|
|
1355
1464
|
if (lineText === void 0 || lineText.length === 0 || char <= 0) return [offsetLeft, 0];
|
|
@@ -1377,12 +1486,12 @@ var Editor = class {
|
|
|
1377
1486
|
}
|
|
1378
1487
|
}
|
|
1379
1488
|
}
|
|
1380
|
-
if (this.#
|
|
1381
|
-
this.#
|
|
1382
|
-
this.#
|
|
1383
|
-
this.#
|
|
1384
|
-
this.#
|
|
1385
|
-
} else this.#
|
|
1489
|
+
if (this.#lastAccessedCharX !== void 0) {
|
|
1490
|
+
this.#lastAccessedCharX[0] = line;
|
|
1491
|
+
this.#lastAccessedCharX[1] = char;
|
|
1492
|
+
this.#lastAccessedCharX[2] = left;
|
|
1493
|
+
this.#lastAccessedCharX[3] = wrapLine;
|
|
1494
|
+
} else this.#lastAccessedCharX = [
|
|
1386
1495
|
line,
|
|
1387
1496
|
char,
|
|
1388
1497
|
left,
|