@pierre/diffs 1.3.0-beta.3 → 1.3.0-beta.4
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.map +1 -1
- package/dist/components/File.d.ts +2 -2
- package/dist/components/File.d.ts.map +1 -1
- package/dist/components/File.js +11 -11
- package/dist/components/File.js.map +1 -1
- package/dist/components/FileDiff.d.ts +7 -4
- package/dist/components/FileDiff.d.ts.map +1 -1
- package/dist/components/FileDiff.js +56 -47
- package/dist/components/FileDiff.js.map +1 -1
- package/dist/components/UnresolvedFile.d.ts.map +1 -1
- package/dist/components/UnresolvedFile.js +1 -1
- package/dist/components/VirtualizedFile.d.ts +1 -1
- package/dist/components/VirtualizedFile.d.ts.map +1 -1
- package/dist/components/VirtualizedFile.js +7 -3
- package/dist/components/VirtualizedFile.js.map +1 -1
- package/dist/components/VirtualizedFileDiff.d.ts +2 -1
- package/dist/components/VirtualizedFileDiff.d.ts.map +1 -1
- package/dist/components/VirtualizedFileDiff.js +14 -0
- package/dist/components/VirtualizedFileDiff.js.map +1 -1
- package/dist/components/VirtulizerDevelopment.d.ts.map +1 -1
- package/dist/editor/editStack.d.ts +1 -1
- package/dist/editor/editor.d.ts +10 -8
- package/dist/editor/editor.d.ts.map +1 -1
- package/dist/editor/editor.js +386 -339
- 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/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 +2 -2
- package/dist/editor/pieceTable.d.ts.map +1 -1
- package/dist/editor/pieceTable.js +42 -11
- package/dist/editor/pieceTable.js.map +1 -1
- package/dist/editor/searchPanel.js +2 -2
- 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 +3 -2
- package/dist/editor/sprite.d.ts.map +1 -1
- package/dist/editor/sprite.js +9 -2
- 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/tokenzier.js +11 -3
- 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/react/index.d.ts +2 -2
- package/dist/react/jsx.d.ts.map +1 -1
- package/dist/react/utils/useFileDiffInstance.js +1 -0
- package/dist/react/utils/useFileDiffInstance.js.map +1 -1
- package/dist/renderers/DiffHunksRenderer.d.ts +4 -1
- package/dist/renderers/DiffHunksRenderer.d.ts.map +1 -1
- package/dist/renderers/DiffHunksRenderer.js +134 -10
- 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 +5 -5
- package/dist/renderers/FileRenderer.js.map +1 -1
- package/dist/ssr/index.d.ts +2 -2
- package/dist/types.d.ts +9 -7
- 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/parsePatchFiles.js +93 -4
- package/dist/utils/parsePatchFiles.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/worker-portable.js +727 -22
- package/dist/worker/worker-portable.js.map +1 -1
- package/dist/worker/worker.js +23 -15
- package/dist/worker/worker.js.map +1 -1
- package/package.json +2 -1
- package/dist/editor/quickEdit.d.ts.map +0 -1
- package/dist/editor/quickEdit.js.map +0 -1
package/dist/editor/editor.js
CHANGED
|
@@ -2,36 +2,29 @@ import { getFiletypeFromFileName } from "../utils/getFiletypeFromFileName.js";
|
|
|
2
2
|
import { isMoveCursorShortcut, isPrimaryModifier, isSafari } from "./platform.js";
|
|
3
3
|
import { resolveEditorCommandFromKeyboardEvent } from "./command.js";
|
|
4
4
|
import editor_default from "./editor2.js";
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
5
|
+
import { addEventListener, clampDomOffset, extend, getLineNumberAttr, h, round } from "./utils.js";
|
|
6
|
+
import { applyDocumentChangeToLineAnnotations, renderLineAnnotations } from "./lineAnnotations.js";
|
|
7
|
+
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";
|
|
8
|
+
import { MarkerManager, markerSeverityDatasetKey } from "./marker.js";
|
|
9
|
+
import { createSpriteElement } from "./sprite.js";
|
|
9
10
|
import { SearchPanelWidget } from "./searchPanel.js";
|
|
10
|
-
import {
|
|
11
|
+
import { SelectionActionWidget } from "./selectionAction.js";
|
|
11
12
|
import { TextDocument } from "./textDocument.js";
|
|
12
13
|
import { Metrics, getExpandedAsciiTextColumns, getUnicodeMeasurementOffsets, snapTextOffsetToUnicodeBoundary } from "./textMeasure.js";
|
|
13
14
|
import { EditorTokenizer, renderLineTokens } from "./tokenzier.js";
|
|
14
15
|
|
|
15
16
|
//#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
17
|
var Editor = class {
|
|
25
18
|
#options;
|
|
26
19
|
#wrap = false;
|
|
27
20
|
#metrics = new Metrics();
|
|
28
21
|
#tokenizer;
|
|
22
|
+
#markerManager;
|
|
29
23
|
#editorEventDisposes;
|
|
30
24
|
#globalEventDisposes;
|
|
31
|
-
#
|
|
25
|
+
#selectEventDisposes;
|
|
32
26
|
#detach;
|
|
33
27
|
#fileInstance;
|
|
34
|
-
#fileInstanceType;
|
|
35
28
|
#fileContents;
|
|
36
29
|
#lineAnnotations;
|
|
37
30
|
#textDocument;
|
|
@@ -41,17 +34,19 @@ var Editor = class {
|
|
|
41
34
|
#contentWidthCache;
|
|
42
35
|
#lineYCache = /* @__PURE__ */ new Map();
|
|
43
36
|
#wrapLineOffsetsCache = /* @__PURE__ */ new Map();
|
|
44
|
-
#
|
|
37
|
+
#lastAccessedLineElement;
|
|
38
|
+
#lastAccessedCharX;
|
|
45
39
|
#globalStyleElement;
|
|
46
40
|
#editorStyleElement;
|
|
47
41
|
#themeStyleElement;
|
|
48
42
|
#spriteElement;
|
|
49
43
|
#fileContainer;
|
|
44
|
+
#gutterElement;
|
|
50
45
|
#contentElement;
|
|
51
46
|
#overlayElement;
|
|
52
47
|
#primaryCaretElement;
|
|
53
|
-
#
|
|
54
|
-
#
|
|
48
|
+
#overlayElements;
|
|
49
|
+
#selectionAction;
|
|
55
50
|
#searchPanel;
|
|
56
51
|
#resizeObserver;
|
|
57
52
|
#shouldIgnoreSelectionChange = false;
|
|
@@ -67,11 +62,8 @@ var Editor = class {
|
|
|
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,14 +77,15 @@ 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
|
-
if (useTokenTransformer !== true || enableGutterUtility === true || enableLineSelection === true || expandUnchanged !== true && Object.hasOwn(component, "fileDiff") || lineHoverHighlight !== "disabled") {
|
|
80
|
+
const { useTokenTransformer, enableGutterUtility, enableLineSelection, expandUnchanged, diffStyle, lineHoverHighlight,...rest } = component.options;
|
|
81
|
+
if (useTokenTransformer !== true || enableGutterUtility === true || enableLineSelection === true || expandUnchanged !== true && Object.hasOwn(component, "fileDiff") || diffStyle === "unified" || lineHoverHighlight !== "disabled") {
|
|
90
82
|
component.setOptions({
|
|
91
83
|
...rest,
|
|
92
84
|
useTokenTransformer: true,
|
|
93
85
|
enableGutterUtility: false,
|
|
94
86
|
enableLineSelection: false,
|
|
95
87
|
expandUnchanged: true,
|
|
88
|
+
diffStyle: "split",
|
|
96
89
|
lineHoverHighlight: "disabled"
|
|
97
90
|
});
|
|
98
91
|
component.rerender();
|
|
@@ -102,59 +95,34 @@ var Editor = class {
|
|
|
102
95
|
this.#detach = component.attachEditor(this);
|
|
103
96
|
return () => this.cleanUp();
|
|
104
97
|
}
|
|
105
|
-
syncToRenderedView(highlighter,
|
|
98
|
+
syncToRenderedView(highlighter, fileContainer, fileContents, didFileChange, lineAnnotations, renderRange) {
|
|
106
99
|
const shadowRoot = fileContainer.shadowRoot;
|
|
107
100
|
if (shadowRoot == null) {
|
|
108
101
|
console.error("[editor] Could not find the shadow root.");
|
|
109
102
|
return;
|
|
110
103
|
}
|
|
111
104
|
let codeElement;
|
|
105
|
+
let gutterEl;
|
|
106
|
+
let contentEl;
|
|
112
107
|
for (const el of shadowRoot.querySelectorAll("[data-code]")) if (el.dataset.deletions === void 0) {
|
|
113
108
|
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);
|
|
109
|
+
for (const child of el.children) {
|
|
110
|
+
const el$1 = child;
|
|
111
|
+
const { gutter, content } = el$1.dataset;
|
|
112
|
+
if (gutter !== void 0) gutterEl = el$1;
|
|
113
|
+
else if (content !== void 0) contentEl = el$1;
|
|
141
114
|
}
|
|
142
|
-
|
|
143
|
-
startingLine,
|
|
144
|
-
totalLines: endLine - startingLine,
|
|
145
|
-
bufferBefore: 0,
|
|
146
|
-
bufferAfter: 0
|
|
147
|
-
};
|
|
115
|
+
break;
|
|
148
116
|
}
|
|
117
|
+
if (codeElement === void 0 || contentEl === void 0) return;
|
|
149
118
|
if (this.#fileContainer !== fileContainer) {
|
|
150
119
|
this.#fileContainer = fileContainer;
|
|
151
|
-
const codePaddingTop = parseInt(getComputedStyle(codeElement).paddingTop.slice(0, -2), 10);
|
|
152
|
-
this.#codePaddingTop = Number.isNaN(codePaddingTop) ? 0 : codePaddingTop;
|
|
153
120
|
if (this.#globalStyleElement !== void 0) fileContainer.appendChild(this.#globalStyleElement);
|
|
154
121
|
if (this.#editorStyleElement !== void 0) shadowRoot.appendChild(this.#editorStyleElement);
|
|
155
122
|
if (this.#themeStyleElement !== void 0) shadowRoot.appendChild(this.#themeStyleElement);
|
|
123
|
+
if (this.#spriteElement !== void 0) shadowRoot.prepend(this.#spriteElement);
|
|
156
124
|
}
|
|
157
|
-
if (this.#textDocument === void 0 || this.#fileContents === void 0 ||
|
|
125
|
+
if (this.#textDocument === void 0 || this.#fileContents === void 0 || didFileChange) {
|
|
158
126
|
const textDocument = new TextDocument(fileContents.name, fileContents.contents, fileContents.lang ?? getFiletypeFromFileName(fileContents.name));
|
|
159
127
|
this.#fileContents = fileContents;
|
|
160
128
|
this.#textDocument = textDocument;
|
|
@@ -169,21 +137,26 @@ var Editor = class {
|
|
|
169
137
|
},
|
|
170
138
|
__debug: this.#options.__debug
|
|
171
139
|
});
|
|
172
|
-
this.#shouldIgnoreSelectionChange = false;
|
|
173
|
-
this.#selectionElements?.forEach((el) => el.remove());
|
|
174
|
-
this.#selectionElements?.clear();
|
|
175
140
|
this.#fileInstance?.setSelectedLines(null);
|
|
176
|
-
this.#
|
|
141
|
+
this.#shouldIgnoreSelectionChange = false;
|
|
142
|
+
this.#overlayElements?.forEach((el) => el.remove());
|
|
143
|
+
this.#overlayElements?.clear();
|
|
144
|
+
this.#overlayElements = void 0;
|
|
177
145
|
this.#selections = void 0;
|
|
178
146
|
this.#scrollingToLine = void 0;
|
|
179
147
|
this.#reservedSelections = void 0;
|
|
180
148
|
this.#searchPanel?.cleanup();
|
|
181
149
|
this.#searchPanel = void 0;
|
|
182
|
-
this.#
|
|
183
|
-
this.#
|
|
150
|
+
this.#selectionAction?.cleanup();
|
|
151
|
+
this.#selectionAction = void 0;
|
|
184
152
|
}
|
|
185
153
|
if (this.#contentElement !== contentEl) {
|
|
186
|
-
this.#
|
|
154
|
+
if (this.#contentElement !== void 0 && this.#options.__debug === true) console.log("[diffs/editor] full re-render triggered !!!");
|
|
155
|
+
const codePaddingTop = parseInt(getComputedStyle(codeElement).paddingTop.slice(0, -2), 10);
|
|
156
|
+
this.#codePaddingTop = Number.isNaN(codePaddingTop) ? 0 : codePaddingTop;
|
|
157
|
+
this.#gutterWidthCache = void 0;
|
|
158
|
+
this.#contentWidthCache = void 0;
|
|
159
|
+
this.#gutterElement = gutterEl;
|
|
187
160
|
this.#contentElement = extend(contentEl, {
|
|
188
161
|
contentEditable: "true",
|
|
189
162
|
role: "textbox",
|
|
@@ -195,11 +168,14 @@ var Editor = class {
|
|
|
195
168
|
translate: false
|
|
196
169
|
});
|
|
197
170
|
if (this.#overlayElement !== void 0) contentEl.after(this.#overlayElement);
|
|
198
|
-
this.#
|
|
171
|
+
this.#metrics.init(contentEl);
|
|
172
|
+
this.#listenContentElement(contentEl, gutterEl);
|
|
199
173
|
}
|
|
200
174
|
this.#lineYCache.clear();
|
|
201
175
|
this.#wrapLineOffsetsCache.clear();
|
|
202
|
-
this.#
|
|
176
|
+
this.#lastAccessedLineElement = void 0;
|
|
177
|
+
this.#lastAccessedCharX = void 0;
|
|
178
|
+
this.#wrap = this.#fileInstance?.options.overflow === "wrap";
|
|
203
179
|
this.#lineAnnotations = lineAnnotations;
|
|
204
180
|
this.#renderRange = renderRange;
|
|
205
181
|
this.#tokenizer?.prebuildStateStack(renderRange);
|
|
@@ -207,19 +183,15 @@ var Editor = class {
|
|
|
207
183
|
this.setSelections(this.#initSelections);
|
|
208
184
|
this.#scrollToPrimaryCaret();
|
|
209
185
|
this.#initSelections = void 0;
|
|
210
|
-
} else if (this.#selections !== void 0
|
|
186
|
+
} else if (this.#selections !== void 0 || this.#matches !== void 0 || this.#markerManager !== void 0) this.#updateSelections(this.#selections ?? []);
|
|
211
187
|
if (this.#options.__debug === true && renderRange !== void 0) {
|
|
212
188
|
const { startingLine, totalLines } = renderRange;
|
|
213
189
|
console.log("[diffs/editor] render file:", fileContents.name, "RenderRange:", startingLine + "-" + (startingLine + totalLines), "of", this.#textDocument.lineCount, "lines");
|
|
214
190
|
}
|
|
215
|
-
if (this.#scrollingToLine !== void 0)
|
|
216
|
-
|
|
217
|
-
this.#scrollingToLine = void 0;
|
|
218
|
-
this.#scrollingToLineChar = void 0;
|
|
219
|
-
this.#scrollingToLineNoFocus = false;
|
|
220
|
-
} else if (this.#selections !== void 0 && this.#selections.length > 0 && !this.#retainSearchPanelFocus) this.focus({ preventScroll: true });
|
|
191
|
+
if (this.#scrollingToLine !== void 0) this.#scrollToLine(this.#scrollingToLine, this.#scrollingToLineChar, this.#scrollingToLineNoFocus);
|
|
192
|
+
else if (this.#selections !== void 0 && this.#selections.length > 0 && !this.#retainSearchPanelFocus) this.focus({ preventScroll: true });
|
|
221
193
|
if (this.#retainSearchPanelFocus) this.#searchPanel?.focus();
|
|
222
|
-
if (this.#
|
|
194
|
+
if (this.#selectionAction !== void 0 && this.#isLineVisible(this.#selectionAction.line) && this.#contentElement !== void 0) this.#selectionAction.render(this.#contentElement);
|
|
223
195
|
}
|
|
224
196
|
postponeBackgroundTokenizeToNextFrame() {
|
|
225
197
|
const tokenizer = this.#tokenizer;
|
|
@@ -246,6 +218,26 @@ var Editor = class {
|
|
|
246
218
|
this.#scrollToPrimaryCaret();
|
|
247
219
|
} else this.#initSelections = selections;
|
|
248
220
|
}
|
|
221
|
+
setMarkers(markers) {
|
|
222
|
+
const textDocument = this.#textDocument;
|
|
223
|
+
if (textDocument === void 0) throw new Error("Text document is not initialized");
|
|
224
|
+
if (markers.length === 0) {
|
|
225
|
+
this.#markerManager?.cleanup();
|
|
226
|
+
this.#markerManager = void 0;
|
|
227
|
+
this.#updateSelections(this.#selections ?? []);
|
|
228
|
+
return;
|
|
229
|
+
}
|
|
230
|
+
this.#markerManager ??= new MarkerManager({
|
|
231
|
+
getLineHeight: () => this.#metrics.lineHeight,
|
|
232
|
+
getFileContainer: () => this.#fileContainer,
|
|
233
|
+
getCharX: (line, character) => this.#getCharX(line, character),
|
|
234
|
+
getLineY: (line) => this.#getLineY(line),
|
|
235
|
+
isMouseDown: () => this.#isContentMouseDown || this.#isGutterMouseDown
|
|
236
|
+
});
|
|
237
|
+
this.#markerManager.setMarkers(markers, textDocument);
|
|
238
|
+
if (this.#contentElement !== void 0) this.#markerManager.listenHover(this.#contentElement);
|
|
239
|
+
this.#updateSelections(this.#selections ?? []);
|
|
240
|
+
}
|
|
249
241
|
focus(options) {
|
|
250
242
|
const preventScroll = options?.preventScroll ?? false;
|
|
251
243
|
const primarySelection = this.#selections?.at(-1);
|
|
@@ -261,6 +253,10 @@ var Editor = class {
|
|
|
261
253
|
this.#globalEventDisposes = void 0;
|
|
262
254
|
this.#editorEventDisposes?.forEach((dispose) => dispose());
|
|
263
255
|
this.#editorEventDisposes = void 0;
|
|
256
|
+
this.#selectEventDisposes?.forEach((dispose) => dispose());
|
|
257
|
+
this.#selectEventDisposes = void 0;
|
|
258
|
+
this.#markerManager?.cleanup();
|
|
259
|
+
this.#markerManager = void 0;
|
|
264
260
|
this.#detach?.();
|
|
265
261
|
this.#detach = void 0;
|
|
266
262
|
this.#fileInstance?.setSelectedLines(null);
|
|
@@ -273,7 +269,8 @@ var Editor = class {
|
|
|
273
269
|
this.#contentWidthCache = void 0;
|
|
274
270
|
this.#lineYCache.clear();
|
|
275
271
|
this.#wrapLineOffsetsCache.clear();
|
|
276
|
-
this.#
|
|
272
|
+
this.#lastAccessedLineElement = void 0;
|
|
273
|
+
this.#lastAccessedCharX = void 0;
|
|
277
274
|
this.#globalStyleElement?.remove();
|
|
278
275
|
this.#globalStyleElement = void 0;
|
|
279
276
|
this.#editorStyleElement?.remove();
|
|
@@ -283,19 +280,18 @@ var Editor = class {
|
|
|
283
280
|
this.#spriteElement?.remove();
|
|
284
281
|
this.#spriteElement = void 0;
|
|
285
282
|
this.#fileContainer = void 0;
|
|
283
|
+
this.#gutterElement = void 0;
|
|
286
284
|
this.#contentElement?.removeAttribute("contentEditable");
|
|
287
285
|
this.#contentElement = void 0;
|
|
288
286
|
this.#overlayElement?.remove();
|
|
289
287
|
this.#overlayElement = void 0;
|
|
290
|
-
this.#
|
|
288
|
+
this.#overlayElements?.forEach((el) => el.remove());
|
|
289
|
+
this.#overlayElements = void 0;
|
|
291
290
|
this.#primaryCaretElement = void 0;
|
|
292
|
-
this.#selectionElements?.forEach((el) => el.remove());
|
|
293
|
-
this.#selectionElements?.clear();
|
|
294
|
-
this.#selectionElements = void 0;
|
|
295
291
|
this.#searchPanel?.cleanup();
|
|
296
292
|
this.#searchPanel = void 0;
|
|
297
|
-
this.#
|
|
298
|
-
this.#
|
|
293
|
+
this.#selectionAction?.cleanup();
|
|
294
|
+
this.#selectionAction = void 0;
|
|
299
295
|
this.#resizeObserver?.disconnect();
|
|
300
296
|
this.#resizeObserver = void 0;
|
|
301
297
|
this.#shouldIgnoreSelectionChange = false;
|
|
@@ -318,10 +314,7 @@ var Editor = class {
|
|
|
318
314
|
textContent: editor_default
|
|
319
315
|
});
|
|
320
316
|
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;
|
|
317
|
+
this.#spriteElement = createSpriteElement();
|
|
325
318
|
this.#overlayElement = h("div", { dataset: "editorOverlay" });
|
|
326
319
|
this.#globalEventDisposes = [
|
|
327
320
|
addEventListener(document, "selectionchange", () => {
|
|
@@ -345,8 +338,8 @@ var Editor = class {
|
|
|
345
338
|
}, { passive: true }),
|
|
346
339
|
addEventListener(document, "pointerup", (e) => {
|
|
347
340
|
if (e.pointerType !== "mouse") return;
|
|
348
|
-
this.#
|
|
349
|
-
this.#
|
|
341
|
+
this.#selectEventDisposes?.forEach((dispose) => dispose());
|
|
342
|
+
this.#selectEventDisposes = void 0;
|
|
350
343
|
if (this.#isGutterMouseDown) {
|
|
351
344
|
this.#isGutterMouseDown = false;
|
|
352
345
|
this.#focus();
|
|
@@ -356,8 +349,8 @@ var Editor = class {
|
|
|
356
349
|
this.#shiftKeyPressed = false;
|
|
357
350
|
this.#selectionStart = void 0;
|
|
358
351
|
this.#reservedSelections = void 0;
|
|
359
|
-
this.#
|
|
360
|
-
if (key.startsWith("
|
|
352
|
+
this.#overlayElements?.forEach((el, key) => {
|
|
353
|
+
if (key.startsWith("selectionActionIcon-")) el.dataset.visible = "true";
|
|
361
354
|
});
|
|
362
355
|
}, { passive: true }),
|
|
363
356
|
addEventListener(document, "keydown", (e) => {
|
|
@@ -368,17 +361,17 @@ var Editor = class {
|
|
|
368
361
|
}, { passive: true })
|
|
369
362
|
];
|
|
370
363
|
}
|
|
371
|
-
#listenContentElement(contentEl) {
|
|
372
|
-
const gutterEl = contentEl.previousElementSibling;
|
|
364
|
+
#listenContentElement(contentEl, gutterEl) {
|
|
373
365
|
const targetIsContentElement = (e) => {
|
|
374
366
|
const target = e.composedPath()[0];
|
|
375
|
-
return target === contentEl || contentEl.contains(target);
|
|
367
|
+
return target !== void 0 && (target === contentEl || contentEl.contains(target));
|
|
376
368
|
};
|
|
377
369
|
this.#editorEventDisposes?.forEach((dispose) => dispose());
|
|
378
370
|
this.#editorEventDisposes = [
|
|
379
371
|
addEventListener(contentEl, "pointerdown", (e) => {
|
|
380
372
|
if (e.pointerType !== "mouse") return;
|
|
381
|
-
|
|
373
|
+
this.#markerManager?.removePopup();
|
|
374
|
+
if (isSafari() && this.#lineAnnotations !== void 0 && this.#lineAnnotations.length > 0) this.#selectEventDisposes = [...contentEl.querySelectorAll("[data-line-annotation]")].map((el) => [addEventListener(el, "mouseenter", () => {
|
|
382
375
|
this.#shouldIgnoreSelectionChange = true;
|
|
383
376
|
}), addEventListener(el, "mouseleave", () => {
|
|
384
377
|
this.#shouldIgnoreSelectionChange = false;
|
|
@@ -405,8 +398,8 @@ var Editor = class {
|
|
|
405
398
|
this.#searchPanel?.cleanup();
|
|
406
399
|
this.#searchPanel = void 0;
|
|
407
400
|
this.#retainSearchPanelFocus = false;
|
|
408
|
-
this.#
|
|
409
|
-
this.#
|
|
401
|
+
this.#selectionAction?.cleanup();
|
|
402
|
+
this.#selectionAction = void 0;
|
|
410
403
|
if (this.#selections !== void 0 && this.#selections.length > 0) {
|
|
411
404
|
const primarySelection = this.#selections.at(-1);
|
|
412
405
|
if (!isCollapsedSelection(primarySelection) || this.#selections.length > 1) {
|
|
@@ -459,6 +452,10 @@ var Editor = class {
|
|
|
459
452
|
e.preventDefault();
|
|
460
453
|
this.#handleInput(e.inputType, e.data);
|
|
461
454
|
}),
|
|
455
|
+
addEventListener(contentEl, "drop", (e) => {
|
|
456
|
+
if (!targetIsContentElement(e)) return;
|
|
457
|
+
e.preventDefault();
|
|
458
|
+
}),
|
|
462
459
|
addEventListener(contentEl, "compositionstart", (e) => {
|
|
463
460
|
if (!targetIsContentElement(e)) return;
|
|
464
461
|
this.#shouldIgnoreSelectionChange = true;
|
|
@@ -469,51 +466,53 @@ var Editor = class {
|
|
|
469
466
|
this.#handleInput("insertText", e.data);
|
|
470
467
|
}, { passive: true })
|
|
471
468
|
];
|
|
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
|
|
469
|
+
if (gutterEl !== void 0) {
|
|
470
|
+
const resolveGutterTarget = (eventTarget, includeContentLine = false) => {
|
|
471
|
+
let target = eventTarget;
|
|
472
|
+
if (target?.dataset.lineNumberContent !== void 0) target = target.parentElement ?? void 0;
|
|
473
|
+
else if (includeContentLine && target?.tagName === "SPAN") target = target.closest("[data-line]");
|
|
474
|
+
return target;
|
|
493
475
|
};
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
const
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
476
|
+
const resolveEditableLine = (target) => {
|
|
477
|
+
if (target === void 0) return;
|
|
478
|
+
const lineType = target.dataset.lineType;
|
|
479
|
+
const lineNumber = getLineNumberAttr(target) ?? getLineNumberAttr(target, "columnNumber");
|
|
480
|
+
if (lineNumber === void 0 || lineType === void 0 || !isLineEditable(lineType)) return;
|
|
481
|
+
return lineNumber - 1;
|
|
482
|
+
};
|
|
483
|
+
this.#editorEventDisposes.push(addEventListener(gutterEl, "pointerdown", (e) => {
|
|
484
|
+
const textDocument = this.#textDocument;
|
|
485
|
+
const lineIndex = resolveEditableLine(resolveGutterTarget(e.composedPath()[0]));
|
|
486
|
+
if (lineIndex === void 0 || textDocument === void 0) return;
|
|
487
|
+
this.#markerManager?.removePopup();
|
|
488
|
+
const selection = {
|
|
489
|
+
start: {
|
|
490
|
+
line: lineIndex,
|
|
491
|
+
character: 0
|
|
492
|
+
},
|
|
493
|
+
end: {
|
|
494
|
+
line: lineIndex,
|
|
495
|
+
character: textDocument.getLineText(lineIndex).length
|
|
496
|
+
},
|
|
497
|
+
direction: DirectionForward
|
|
498
|
+
};
|
|
499
|
+
this.#isGutterMouseDown = true;
|
|
500
|
+
this.#selectionStart = selection;
|
|
501
|
+
this.#updateSelections([selection]);
|
|
502
|
+
this.#focus(selection.end);
|
|
503
|
+
this.#selectEventDisposes = [addEventListener(document, "mousemove", (e$1) => {
|
|
504
|
+
if (!this.#isGutterMouseDown) return;
|
|
505
|
+
const textDocument$1 = this.#textDocument;
|
|
506
|
+
const lineIndex$1 = resolveEditableLine(resolveGutterTarget(e$1.composedPath()[0], true));
|
|
507
|
+
if (lineIndex$1 === void 0 || textDocument$1 === void 0) return;
|
|
509
508
|
let selection$1 = {
|
|
510
509
|
start: {
|
|
511
|
-
line: lineIndex,
|
|
510
|
+
line: lineIndex$1,
|
|
512
511
|
character: 0
|
|
513
512
|
},
|
|
514
513
|
end: {
|
|
515
|
-
line: lineIndex,
|
|
516
|
-
character:
|
|
514
|
+
line: lineIndex$1,
|
|
515
|
+
character: textDocument$1.getLineText(lineIndex$1).length
|
|
517
516
|
},
|
|
518
517
|
direction: DirectionForward
|
|
519
518
|
};
|
|
@@ -521,9 +520,10 @@ var Editor = class {
|
|
|
521
520
|
else this.#selectionStart = selection$1;
|
|
522
521
|
this.#updateSelections([selection$1]);
|
|
523
522
|
this.#focus(selection$1.end);
|
|
524
|
-
}
|
|
525
|
-
}, { passive: true })
|
|
526
|
-
}
|
|
523
|
+
}, { passive: true })];
|
|
524
|
+
}, { passive: true }));
|
|
525
|
+
}
|
|
526
|
+
this.#markerManager?.listenHover(contentEl);
|
|
527
527
|
this.#resizeObserver?.disconnect();
|
|
528
528
|
this.#resizeObserver = new ResizeObserver(() => {
|
|
529
529
|
this.#handleLayoutResize();
|
|
@@ -540,17 +540,16 @@ var Editor = class {
|
|
|
540
540
|
break;
|
|
541
541
|
case "findNextMatch": {
|
|
542
542
|
const selections = this.#selections;
|
|
543
|
-
|
|
544
|
-
if (selections === void 0 || textDocument$1 === void 0) break;
|
|
543
|
+
if (selections === void 0) break;
|
|
545
544
|
if (selections.some(isCollapsedSelection)) {
|
|
546
545
|
const expanded = selections.map((sel) => {
|
|
547
|
-
if (isCollapsedSelection(sel)) return expandCollapsedSelectionToWord(textDocument
|
|
546
|
+
if (isCollapsedSelection(sel)) return expandCollapsedSelectionToWord(textDocument, sel);
|
|
548
547
|
return sel;
|
|
549
548
|
});
|
|
550
549
|
this.#updateSelections(expanded);
|
|
551
550
|
this.focus();
|
|
552
551
|
} else {
|
|
553
|
-
const nextMatch = findNexMatch(textDocument
|
|
552
|
+
const nextMatch = findNexMatch(textDocument, selections);
|
|
554
553
|
if (nextMatch !== void 0) {
|
|
555
554
|
this.#updateSelections(nextMatch);
|
|
556
555
|
this.#scrollToPrimaryCaret();
|
|
@@ -628,66 +627,49 @@ var Editor = class {
|
|
|
628
627
|
const gutterWidthChanged = this.#getGutterWidth() !== prevGutterWidth;
|
|
629
628
|
const contentWidthChanged = this.#getContentWidth() !== prevContentWidth;
|
|
630
629
|
if (!gutterWidthChanged && !contentWidthChanged) return;
|
|
631
|
-
this.#
|
|
630
|
+
this.#lastAccessedLineElement = void 0;
|
|
631
|
+
this.#lastAccessedCharX = void 0;
|
|
632
632
|
if (contentWidthChanged && (this.#wrap || lineAnnotations > 0)) {
|
|
633
633
|
this.#lineYCache.clear();
|
|
634
634
|
this.#wrapLineOffsetsCache.clear();
|
|
635
635
|
}
|
|
636
|
-
if (this.#selections !== void 0) {
|
|
637
|
-
this.#updateSelections(this.#selections);
|
|
638
|
-
this.focus();
|
|
636
|
+
if (this.#selections !== void 0 || this.#matches !== void 0 || this.#markerManager !== void 0) {
|
|
637
|
+
this.#updateSelections(this.#selections ?? []);
|
|
638
|
+
if (this.#selections !== void 0) this.focus();
|
|
639
639
|
}
|
|
640
|
+
this.#markerManager?.removePopup();
|
|
640
641
|
}
|
|
641
642
|
#rerender(change, newLineAnnotations, renderRange = this.#renderRange, shouldUpdateBuffer) {
|
|
642
643
|
const tokenizer = this.#tokenizer;
|
|
643
|
-
const
|
|
644
|
+
const fileInstance = this.#fileInstance;
|
|
644
645
|
const fileContents = this.#fileContents;
|
|
645
646
|
const textDocument = this.#textDocument;
|
|
647
|
+
const gutterEl = this.#gutterElement;
|
|
646
648
|
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;
|
|
649
|
+
if (tokenizer === void 0 || fileInstance === void 0 || fileContents === void 0 || textDocument === void 0 || contentEl === void 0) return;
|
|
649
650
|
tokenizer.stopBackgroundTokenize();
|
|
650
651
|
const t = performance.now();
|
|
651
|
-
const isFileDiff = this.#fileInstanceType === "diff";
|
|
652
652
|
const dirtyLines = tokenizer.tokenize(change, renderRange);
|
|
653
653
|
const t2 = performance.now();
|
|
654
654
|
if (dirtyLines.size > 0) {
|
|
655
655
|
const children = contentEl.children;
|
|
656
656
|
const dirtyLineIndexes = new Set(dirtyLines.keys());
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
const
|
|
660
|
-
if (
|
|
661
|
-
const lineNumber =
|
|
662
|
-
if (
|
|
657
|
+
const startingLine = renderRange?.startingLine ?? 0;
|
|
658
|
+
for (let i = change.startLine - startingLine; i < children.length; i++) {
|
|
659
|
+
const child = children[i];
|
|
660
|
+
if (child !== void 0) {
|
|
661
|
+
const lineNumber = getLineNumberAttr(child);
|
|
662
|
+
if (lineNumber !== void 0) {
|
|
663
663
|
const lineIndex = lineNumber - 1;
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
664
|
+
if (dirtyLines.has(lineIndex)) {
|
|
665
|
+
const tokens = dirtyLines.get(lineIndex);
|
|
666
|
+
child.replaceChildren(...renderLineTokens(tokens, tokenizer.themeType));
|
|
667
667
|
dirtyLineIndexes.delete(lineIndex);
|
|
668
668
|
if (dirtyLineIndexes.size === 0) break;
|
|
669
669
|
}
|
|
670
670
|
}
|
|
671
671
|
}
|
|
672
672
|
}
|
|
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
673
|
if (dirtyLineIndexes.size > 0) for (const lineIndex of dirtyLineIndexes) {
|
|
692
674
|
const tokens = dirtyLines.get(lineIndex);
|
|
693
675
|
const lineNumber = String(lineIndex + 1);
|
|
@@ -699,7 +681,7 @@ var Editor = class {
|
|
|
699
681
|
},
|
|
700
682
|
children: renderLineTokens(tokens, tokenizer.themeType)
|
|
701
683
|
}, contentEl);
|
|
702
|
-
h("div", {
|
|
684
|
+
if (gutterEl !== void 0) h("div", {
|
|
703
685
|
dataset: {
|
|
704
686
|
lineType: "context",
|
|
705
687
|
columnNumber: lineNumber,
|
|
@@ -712,25 +694,30 @@ var Editor = class {
|
|
|
712
694
|
}, gutterEl);
|
|
713
695
|
}
|
|
714
696
|
}
|
|
715
|
-
if (change.lineDelta < 0) for (const
|
|
716
|
-
const
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
697
|
+
if (change.lineDelta < 0) for (const children of [contentEl.children, gutterEl?.children ?? []]) for (let i = children.length - 1; i >= 0; i--) {
|
|
698
|
+
const child = children[i];
|
|
699
|
+
const lineNumber = getLineNumberAttr(child) ?? getLineNumberAttr(child, "columnNumber");
|
|
700
|
+
if (lineNumber === void 0) continue;
|
|
701
|
+
if (lineNumber - 1 < change.lineCount) break;
|
|
702
|
+
child.remove();
|
|
703
|
+
}
|
|
704
|
+
const isDiff = Object.hasOwn(fileInstance, "fileDiff");
|
|
705
|
+
const didLineCountChange = change.lineDelta !== 0;
|
|
706
|
+
if (didLineCountChange) {
|
|
707
|
+
let gridRow = contentEl.children.length;
|
|
708
|
+
for (const child of contentEl.children) {
|
|
709
|
+
const { bufferSize } = child.dataset;
|
|
710
|
+
if (bufferSize !== void 0) gridRow += parseInt(bufferSize) - 1;
|
|
725
711
|
}
|
|
712
|
+
contentEl.style.gridRow = "span " + gridRow;
|
|
713
|
+
if (gutterEl !== void 0) gutterEl.style.gridRow = "span " + gridRow;
|
|
726
714
|
}
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
715
|
+
fileInstance.updateRenderCache(dirtyLines, tokenizer.themeType, isDiff ? !didLineCountChange : void 0);
|
|
716
|
+
if (didLineCountChange) fileInstance.applyDocumentChange(textDocument, newLineAnnotations, shouldUpdateBuffer);
|
|
717
|
+
if (newLineAnnotations !== void 0) {
|
|
718
|
+
this.#lineAnnotations = newLineAnnotations;
|
|
719
|
+
renderLineAnnotations(newLineAnnotations, contentEl, gutterEl);
|
|
730
720
|
}
|
|
731
|
-
component.applyLineChange?.(dirtyLines, tokenizer.themeType);
|
|
732
|
-
if (change.lineDelta !== 0 || isFileDiff) component.applyLayoutChange(textDocument, newLineAnnotations, shouldUpdateBuffer);
|
|
733
|
-
if (isFileDiff) this.#tokenizer?.stopBackgroundTokenize();
|
|
734
721
|
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
722
|
}
|
|
736
723
|
#handleInput(inputType, data) {
|
|
@@ -747,74 +734,38 @@ var Editor = class {
|
|
|
747
734
|
case "deleteContentForward":
|
|
748
735
|
this.#deleteSelectionText(true);
|
|
749
736
|
break;
|
|
737
|
+
case "deleteSoftLineBackward":
|
|
738
|
+
this.#deleteSoftLineBackward();
|
|
739
|
+
break;
|
|
750
740
|
case "deleteHardLineForward":
|
|
751
741
|
this.#deleteHardLineForward();
|
|
752
742
|
break;
|
|
743
|
+
case "deleteWordBackward":
|
|
744
|
+
this.#deleteWordBackward();
|
|
745
|
+
break;
|
|
753
746
|
case "insertTranspose":
|
|
754
747
|
this.#insertTranspose();
|
|
755
748
|
break;
|
|
756
749
|
default:
|
|
757
|
-
console.warn(`[diffs] Unknown input type: ${inputType}
|
|
750
|
+
console.warn(`[diffs] Unknown input type: ${inputType}`, data);
|
|
758
751
|
break;
|
|
759
752
|
}
|
|
760
753
|
}
|
|
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
|
|
754
|
+
#focus(position, preventScroll = true) {
|
|
755
|
+
if (position !== void 0) {
|
|
756
|
+
this.#shouldIgnoreSelectionChange = true;
|
|
757
|
+
this.#setWindowSelection({
|
|
758
|
+
start: position,
|
|
759
|
+
end: position,
|
|
760
|
+
direction: DirectionNone
|
|
761
|
+
});
|
|
762
|
+
requestAnimationFrame(() => {
|
|
763
|
+
this.#contentElement?.focus({ preventScroll });
|
|
764
|
+
requestAnimationFrame(() => {
|
|
765
|
+
this.#shouldIgnoreSelectionChange = false;
|
|
788
766
|
});
|
|
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;
|
|
767
|
+
});
|
|
768
|
+
} else this.#contentElement?.focus({ preventScroll });
|
|
818
769
|
}
|
|
819
770
|
#setWindowSelection(selection) {
|
|
820
771
|
const winSelection = window.getSelection();
|
|
@@ -838,22 +789,6 @@ var Editor = class {
|
|
|
838
789
|
console.error("[diffs/editor] failed to update window selection:", err);
|
|
839
790
|
}
|
|
840
791
|
}
|
|
841
|
-
#focus(position, preventScroll = true) {
|
|
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
792
|
#scrollToPrimaryCaret(noFocus = false) {
|
|
858
793
|
const primaryCaretElement = this.#primaryCaretElement;
|
|
859
794
|
const primarySelection = this.#selections?.at(-1);
|
|
@@ -899,23 +834,98 @@ var Editor = class {
|
|
|
899
834
|
line,
|
|
900
835
|
character: char
|
|
901
836
|
});
|
|
837
|
+
this.#scrollingToLine = void 0;
|
|
838
|
+
this.#scrollingToLineChar = void 0;
|
|
839
|
+
this.#scrollingToLineNoFocus = false;
|
|
902
840
|
} else {
|
|
903
|
-
|
|
841
|
+
let yFix = 0;
|
|
842
|
+
if (this.#scrollingToLine === line && this.#contentElement !== void 0) for (let i = this.#contentElement.childElementCount - 1; i >= 0; i--) {
|
|
843
|
+
const child = this.#contentElement.children[i];
|
|
844
|
+
const lineType = child.dataset.lineType;
|
|
845
|
+
const lineNumber = getLineNumberAttr(child);
|
|
846
|
+
if (lineType !== void 0 && isLineEditable(lineType) && lineNumber !== void 0) {
|
|
847
|
+
yFix = (line - lineNumber) * this.#metrics.lineHeight;
|
|
848
|
+
break;
|
|
849
|
+
}
|
|
850
|
+
}
|
|
851
|
+
const approximateLineY = ((this.#lineAnnotations ?? []).filter((annotation) => annotation.lineNumber < line).length + line) * this.#metrics.lineHeight + yFix;
|
|
904
852
|
virtualCaret.style.top = approximateLineY + "px";
|
|
905
853
|
this.#fileContainer?.shadowRoot?.appendChild(virtualCaret);
|
|
906
|
-
this.#scrollingToLine = line;
|
|
907
|
-
this.#scrollingToLineChar = char;
|
|
908
|
-
this.#scrollingToLineNoFocus = noFocus;
|
|
909
854
|
virtualCaret.scrollIntoView({
|
|
910
855
|
block: "center",
|
|
911
856
|
inline: "nearest"
|
|
912
857
|
});
|
|
858
|
+
if (this.#scrollingToLine === line && yFix === 0) {
|
|
859
|
+
this.#scrollingToLine = void 0;
|
|
860
|
+
this.#scrollingToLineChar = void 0;
|
|
861
|
+
this.#scrollingToLineNoFocus = false;
|
|
862
|
+
} else {
|
|
863
|
+
this.#scrollingToLine = line;
|
|
864
|
+
this.#scrollingToLineChar = char;
|
|
865
|
+
this.#scrollingToLineNoFocus = noFocus;
|
|
866
|
+
}
|
|
913
867
|
}
|
|
914
868
|
virtualCaret.remove();
|
|
915
869
|
}
|
|
916
|
-
#
|
|
870
|
+
#updateSelections(selections) {
|
|
871
|
+
this.postponeBackgroundTokenizeToNextFrame();
|
|
872
|
+
this.#primaryCaretElement = void 0;
|
|
873
|
+
this.#fileInstance?.setSelectedLines(null);
|
|
874
|
+
this.#gutterElement?.querySelectorAll("[data-active]").forEach((el) => el.removeAttribute("data-active"));
|
|
875
|
+
if (selections.length === 0 && this.#matches === void 0 && this.#markerManager === void 0) {
|
|
876
|
+
this.#selections = void 0;
|
|
877
|
+
this.#overlayElements?.forEach((el) => el.remove());
|
|
878
|
+
this.#overlayElements?.clear();
|
|
879
|
+
return;
|
|
880
|
+
}
|
|
881
|
+
const fragment = document.createDocumentFragment();
|
|
882
|
+
const renderCtx = {
|
|
883
|
+
fragment,
|
|
884
|
+
elements: /* @__PURE__ */ new Map()
|
|
885
|
+
};
|
|
886
|
+
if (selections.length > 0) {
|
|
887
|
+
const normalizedSelections = mergeOverlappingSelections(selections);
|
|
888
|
+
const primarySelection = normalizedSelections.at(-1);
|
|
889
|
+
this.#selections = normalizedSelections;
|
|
890
|
+
if (isCollapsedSelection(primarySelection)) {
|
|
891
|
+
const line = primarySelection.start.line + 1;
|
|
892
|
+
this.#fileInstance?.setSelectedLines({
|
|
893
|
+
start: line,
|
|
894
|
+
end: line
|
|
895
|
+
});
|
|
896
|
+
} else if (this.#gutterElement !== void 0) {
|
|
897
|
+
const pos = getCaretPosition(primarySelection);
|
|
898
|
+
this.#gutterElement.querySelector(`[data-column-number="${pos.line + 1}"]`)?.setAttribute("data-active", "");
|
|
899
|
+
}
|
|
900
|
+
for (const selection of normalizedSelections) {
|
|
901
|
+
if (!isCollapsedSelection(selection)) this.#renderSelection(renderCtx, "selection", selection);
|
|
902
|
+
this.#renderCaret(renderCtx, selection, selection === primarySelection);
|
|
903
|
+
}
|
|
904
|
+
if (this.#options.enabledSelectionAction === true && !isCollapsedSelection(primarySelection)) this.#renderSelectionActionIcon(renderCtx, primarySelection);
|
|
905
|
+
}
|
|
906
|
+
const textDocument = this.#textDocument;
|
|
907
|
+
if (this.#matches !== void 0 && textDocument !== void 0) {
|
|
908
|
+
const primarySelection = this.#selections?.at(-1);
|
|
909
|
+
const primaryStartOffset = primarySelection !== void 0 ? textDocument.offsetAt(primarySelection.start) : -1;
|
|
910
|
+
const primaryEndOffset = primarySelection !== void 0 ? textDocument.offsetAt(primarySelection.end) : -1;
|
|
911
|
+
for (const [startOffset, endOffset] of this.#matches) {
|
|
912
|
+
const range = {
|
|
913
|
+
start: textDocument.positionAt(startOffset),
|
|
914
|
+
end: textDocument.positionAt(endOffset)
|
|
915
|
+
};
|
|
916
|
+
const isFocused = primaryStartOffset === startOffset && primaryEndOffset === endOffset;
|
|
917
|
+
this.#renderSelection(renderCtx, "match", range, isFocused ? "focus" : void 0);
|
|
918
|
+
}
|
|
919
|
+
}
|
|
920
|
+
if (this.#markerManager !== void 0 && textDocument !== void 0) for (const marker of this.#markerManager.markers) this.#renderSelection(renderCtx, "marker", marker, markerSeverityDatasetKey(marker.severity));
|
|
921
|
+
this.#overlayElement?.appendChild(fragment);
|
|
922
|
+
this.#overlayElements?.forEach((el) => el.remove());
|
|
923
|
+
this.#overlayElements?.clear();
|
|
924
|
+
this.#overlayElements = renderCtx.elements;
|
|
925
|
+
}
|
|
926
|
+
#renderSelection(renderCtx, type, range, extraDataset) {
|
|
917
927
|
if (this.#textDocument === void 0) return;
|
|
918
|
-
const { start, end } =
|
|
928
|
+
const { start, end } = range;
|
|
919
929
|
for (let line = start.line; line <= end.line; line++) {
|
|
920
930
|
if (!this.#isLineVisible(line)) continue;
|
|
921
931
|
const isLastLine = line === end.line;
|
|
@@ -925,20 +935,22 @@ var Editor = class {
|
|
|
925
935
|
if (this.#wrap) {
|
|
926
936
|
const contentWidth = this.#getContentWidth();
|
|
927
937
|
if (2 * this.#metrics.ch + this.#metrics.measureTextWidth(lineText) > contentWidth) {
|
|
928
|
-
this.#renderWrappedSelection(renderCtx, line, lineText, startChar, endChar, isLastLine, type,
|
|
938
|
+
this.#renderWrappedSelection(renderCtx, line, lineText, startChar, endChar, isLastLine, type, extraDataset);
|
|
929
939
|
continue;
|
|
930
940
|
}
|
|
931
941
|
}
|
|
932
942
|
let left = 0;
|
|
933
943
|
let width = 0;
|
|
944
|
+
let paddingEnd = 0;
|
|
934
945
|
if (startChar === 0) left = this.#getGutterWidth() + this.#metrics.ch;
|
|
935
946
|
else left = this.#getCharX(line, startChar)[0];
|
|
936
|
-
if (
|
|
937
|
-
|
|
938
|
-
this.#
|
|
947
|
+
if (!isLastLine && type === "selection") paddingEnd = this.#metrics.ch;
|
|
948
|
+
if (startChar === endChar) width = paddingEnd;
|
|
949
|
+
else width = this.#getCharX(line, endChar)[0] - left + paddingEnd;
|
|
950
|
+
this.#renderSelectionBlock(renderCtx, type, line, 0, left, width, extraDataset);
|
|
939
951
|
}
|
|
940
952
|
}
|
|
941
|
-
#renderWrappedSelection(renderCtx, line, lineText, startChar, endChar, isLastLine, type,
|
|
953
|
+
#renderWrappedSelection(renderCtx, line, lineText, startChar, endChar, isLastLine, type, extraDataset) {
|
|
942
954
|
const wrapOffsets = this.#wrapLineText(line);
|
|
943
955
|
const segmentCount = wrapOffsets.length - 1;
|
|
944
956
|
const offsetLeft = this.#getGutterWidth() + this.#metrics.ch;
|
|
@@ -950,29 +962,31 @@ var Editor = class {
|
|
|
950
962
|
if (wrapStartChar > wrapEndChar) continue;
|
|
951
963
|
let segmentLeft;
|
|
952
964
|
let segmentWidth;
|
|
965
|
+
let paddingEnd = 0;
|
|
953
966
|
if (wrapStartChar === 0) segmentLeft = offsetLeft;
|
|
954
967
|
else {
|
|
955
968
|
const prefixInSegment = lineText.slice(segmentStart, wrapStartChar);
|
|
956
969
|
const prefixAsciiColumns = getExpandedAsciiTextColumns(prefixInSegment, this.#metrics.tabSize);
|
|
957
970
|
segmentLeft = offsetLeft + (prefixAsciiColumns !== -1 ? prefixAsciiColumns * this.#metrics.ch : this.#metrics.measureTextWidth(prefixInSegment));
|
|
958
971
|
}
|
|
959
|
-
if (
|
|
972
|
+
if (!isLastLine && wrapLine === segmentCount - 1 && type === "selection") paddingEnd = this.#metrics.ch;
|
|
973
|
+
if (wrapStartChar === wrapEndChar) segmentWidth = paddingEnd;
|
|
960
974
|
else {
|
|
961
975
|
const selectionInSegment = lineText.slice(wrapStartChar, wrapEndChar);
|
|
962
976
|
const selectionAsciiWidth = getExpandedAsciiTextColumns(selectionInSegment, this.#metrics.tabSize);
|
|
963
977
|
segmentWidth = selectionAsciiWidth !== -1 ? selectionAsciiWidth * this.#metrics.ch : this.#metrics.measureTextWidth(selectionInSegment);
|
|
964
|
-
|
|
978
|
+
segmentWidth += paddingEnd;
|
|
965
979
|
}
|
|
966
|
-
this.#renderSelectionBlock(renderCtx, line, wrapLine, segmentLeft, segmentWidth,
|
|
980
|
+
this.#renderSelectionBlock(renderCtx, type, line, wrapLine, segmentLeft, segmentWidth, extraDataset);
|
|
967
981
|
}
|
|
968
982
|
}
|
|
969
|
-
#renderSelectionBlock(renderCtx, line, wrapLine, left, width,
|
|
983
|
+
#renderSelectionBlock(renderCtx, type, line, wrapLine, left, width, extraDataset) {
|
|
970
984
|
if (width === 0) return;
|
|
971
985
|
const { ch, lineHeight } = this.#metrics;
|
|
972
986
|
const y = this.#getLineY(line) + wrapLine * lineHeight;
|
|
973
987
|
const css = `width:${width}px;transform:translateX(${left}px) translateY(${y}px);`;
|
|
974
|
-
const cacheKey = `${type}
|
|
975
|
-
const
|
|
988
|
+
const cacheKey = `${type}-${left}-${y}-${width}${extraDataset ?? ""}`;
|
|
989
|
+
const overlayEls = this.#overlayElements;
|
|
976
990
|
const rounded = (this.#options.roundedSelection ?? true) && type === "selection";
|
|
977
991
|
const addRoundedCorner = (line$1, wrapLine$1, left$1, radius) => {
|
|
978
992
|
const top = this.#getLineY(line$1) + wrapLine$1 * lineHeight;
|
|
@@ -995,9 +1009,9 @@ var Editor = class {
|
|
|
995
1009
|
}
|
|
996
1010
|
let cornerEl = renderCtx.elements.get(cacheKey$1);
|
|
997
1011
|
if (cornerEl !== void 0) return;
|
|
998
|
-
if (
|
|
999
|
-
cornerEl =
|
|
1000
|
-
|
|
1012
|
+
if (overlayEls?.has(cacheKey$1) === true) {
|
|
1013
|
+
cornerEl = overlayEls.get(cacheKey$1);
|
|
1014
|
+
overlayEls.delete(cacheKey$1);
|
|
1001
1015
|
} else cornerEl = h("div", {
|
|
1002
1016
|
dataset: "selectionRange",
|
|
1003
1017
|
style: { cssText: css$1 },
|
|
@@ -1050,16 +1064,13 @@ var Editor = class {
|
|
|
1050
1064
|
if (rounded) addRadiusStyle(rangeEl);
|
|
1051
1065
|
return;
|
|
1052
1066
|
}
|
|
1053
|
-
if (
|
|
1054
|
-
rangeEl =
|
|
1055
|
-
|
|
1056
|
-
} else {
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
}, renderCtx.fragment);
|
|
1061
|
-
if (type === "match" && isFocused === true) rangeEl.dataset.focus = "";
|
|
1062
|
-
}
|
|
1067
|
+
if (overlayEls?.has(cacheKey) === true) {
|
|
1068
|
+
rangeEl = overlayEls.get(cacheKey);
|
|
1069
|
+
overlayEls.delete(cacheKey);
|
|
1070
|
+
} else rangeEl = h("div", {
|
|
1071
|
+
dataset: extraDataset ? [type + "Range", extraDataset] : type + "Range",
|
|
1072
|
+
style: { cssText: css }
|
|
1073
|
+
}, renderCtx.fragment);
|
|
1063
1074
|
if (rounded) addRadiusStyle(rangeEl);
|
|
1064
1075
|
renderCtx.elements.set(cacheKey, rangeEl);
|
|
1065
1076
|
}
|
|
@@ -1079,29 +1090,29 @@ var Editor = class {
|
|
|
1079
1090
|
this.#primaryCaretElement = caretEl;
|
|
1080
1091
|
}
|
|
1081
1092
|
}
|
|
1082
|
-
#
|
|
1093
|
+
#renderSelectionActionIcon(renderCtx, selection) {
|
|
1083
1094
|
const line = getCaretPosition(selection).line;
|
|
1084
1095
|
if (!this.#isLineVisible(line)) return;
|
|
1085
1096
|
const [left, wrapLine] = this.#getCharX(line, 0);
|
|
1086
|
-
const cacheKey = "
|
|
1097
|
+
const cacheKey = "selectionActionIcon-" + line + "(" + wrapLine + ")";
|
|
1087
1098
|
if (renderCtx.elements.has(cacheKey)) return;
|
|
1088
|
-
const
|
|
1089
|
-
const
|
|
1090
|
-
this.#
|
|
1091
|
-
this.#
|
|
1099
|
+
const selectionActionIcon = SelectionActionWidget.renderIcon(left, this.#getLineY(line) + wrapLine * this.#metrics.lineHeight, renderCtx.fragment, () => {
|
|
1100
|
+
const cleanUpSelectionAction = () => {
|
|
1101
|
+
this.#selectionAction?.cleanup();
|
|
1102
|
+
this.#selectionAction = void 0;
|
|
1092
1103
|
};
|
|
1093
1104
|
const handleWidgetDomResize = () => {
|
|
1094
1105
|
this.#lineYCache.clear();
|
|
1095
1106
|
if (this.#selections !== void 0) this.#updateSelections(this.#selections);
|
|
1096
1107
|
};
|
|
1097
|
-
|
|
1108
|
+
cleanUpSelectionAction();
|
|
1098
1109
|
const textDocument = this.#textDocument;
|
|
1099
|
-
const
|
|
1110
|
+
const renderSelectionAction = this.#options.renderSelectionAction;
|
|
1100
1111
|
const fileContainer = this.#fileContainer;
|
|
1101
|
-
if (textDocument === void 0 ||
|
|
1112
|
+
if (textDocument === void 0 || renderSelectionAction === void 0 || fileContainer == null) return;
|
|
1102
1113
|
const line$1 = selection.end.line;
|
|
1103
1114
|
const lineText = textDocument.getLineText(line$1);
|
|
1104
|
-
const
|
|
1115
|
+
const selectionActionElement = renderSelectionAction({
|
|
1105
1116
|
textDocument,
|
|
1106
1117
|
selection,
|
|
1107
1118
|
applyEdits: (edits) => {
|
|
@@ -1115,7 +1126,7 @@ var Editor = class {
|
|
|
1115
1126
|
this.#replaceSelectionText(text);
|
|
1116
1127
|
},
|
|
1117
1128
|
close: () => {
|
|
1118
|
-
|
|
1129
|
+
cleanUpSelectionAction();
|
|
1119
1130
|
handleWidgetDomResize();
|
|
1120
1131
|
this.#scrollToPrimaryCaret();
|
|
1121
1132
|
}
|
|
@@ -1127,11 +1138,11 @@ var Editor = class {
|
|
|
1127
1138
|
else if (charCode === 9) leadingWhitespaces += this.#metrics.tabSize;
|
|
1128
1139
|
else break;
|
|
1129
1140
|
}
|
|
1130
|
-
this.#
|
|
1141
|
+
this.#selectionAction = new SelectionActionWidget(line$1, selectionActionElement, fileContainer, leadingWhitespaces, handleWidgetDomResize);
|
|
1131
1142
|
this.#updateSelections([selection]);
|
|
1132
|
-
if (this.#isLineVisible(line$1) && this.#contentElement !== void 0) this.#
|
|
1143
|
+
if (this.#isLineVisible(line$1) && this.#contentElement !== void 0) this.#selectionAction.render(this.#contentElement);
|
|
1133
1144
|
});
|
|
1134
|
-
renderCtx.elements.set(cacheKey,
|
|
1145
|
+
renderCtx.elements.set(cacheKey, selectionActionIcon);
|
|
1135
1146
|
}
|
|
1136
1147
|
#renderSearchPanel() {
|
|
1137
1148
|
this.#searchPanel?.cleanup();
|
|
@@ -1181,8 +1192,7 @@ var Editor = class {
|
|
|
1181
1192
|
break;
|
|
1182
1193
|
}
|
|
1183
1194
|
if (nextMatch !== void 0) scrollToMatch(nextMatch, true);
|
|
1184
|
-
this.#
|
|
1185
|
-
this.#updateSelections(this.#selections ?? []);
|
|
1195
|
+
else this.#updateSelections(this.#selections ?? []);
|
|
1186
1196
|
return nextMatch;
|
|
1187
1197
|
},
|
|
1188
1198
|
onClose: () => {
|
|
@@ -1219,21 +1229,44 @@ var Editor = class {
|
|
|
1219
1229
|
if (selections === void 0 || textDocument === void 0) return;
|
|
1220
1230
|
const primarySelection = selections.at(-1);
|
|
1221
1231
|
if (primarySelection === void 0) return;
|
|
1222
|
-
|
|
1232
|
+
let edit;
|
|
1233
|
+
if (isCollapsedSelection(primarySelection)) {
|
|
1223
1234
|
const offset = textDocument.offsetAt(primarySelection.start);
|
|
1224
1235
|
const nextOffset = forward ? Math.min(textDocument.getText().length, offset + 1) : Math.max(0, offset - 1);
|
|
1225
|
-
|
|
1236
|
+
edit = {
|
|
1226
1237
|
start: Math.min(offset, nextOffset),
|
|
1227
1238
|
end: Math.max(offset, nextOffset),
|
|
1228
1239
|
text: ""
|
|
1229
1240
|
};
|
|
1230
|
-
}
|
|
1241
|
+
} else edit = {
|
|
1231
1242
|
start: textDocument.offsetAt(primarySelection.start),
|
|
1232
1243
|
end: textDocument.offsetAt(primarySelection.end),
|
|
1233
1244
|
text: ""
|
|
1234
1245
|
};
|
|
1235
1246
|
this.#applyResolvedTextEdit(edit);
|
|
1236
1247
|
}
|
|
1248
|
+
#deleteSoftLineBackward() {
|
|
1249
|
+
const selections = this.#selections;
|
|
1250
|
+
const textDocument = this.#textDocument;
|
|
1251
|
+
if (selections === void 0 || textDocument === void 0) return;
|
|
1252
|
+
const { nextSelections, change } = applyDeleteSoftLineBackwardToSelections(textDocument, selections, this.#wrap ? (line, character) => {
|
|
1253
|
+
const wrapOffsets = this.#wrapLineText(line);
|
|
1254
|
+
for (let w = 0; w + 1 < wrapOffsets.length; w++) {
|
|
1255
|
+
const segmentStart = wrapOffsets[w];
|
|
1256
|
+
const segmentEnd = wrapOffsets[w + 1];
|
|
1257
|
+
if (character >= segmentStart && character <= segmentEnd) return segmentStart;
|
|
1258
|
+
}
|
|
1259
|
+
return 0;
|
|
1260
|
+
} : void 0, this.#lineAnnotations);
|
|
1261
|
+
if (change !== void 0) this.#applyChange(change, nextSelections, this.#applyChangeToLineAnnotations(change));
|
|
1262
|
+
}
|
|
1263
|
+
#deleteWordBackward() {
|
|
1264
|
+
const selections = this.#selections;
|
|
1265
|
+
const textDocument = this.#textDocument;
|
|
1266
|
+
if (selections === void 0 || textDocument === void 0) return;
|
|
1267
|
+
const { nextSelections, change } = applyDeleteWordBackwardToSelections(textDocument, selections, this.#lineAnnotations);
|
|
1268
|
+
if (change !== void 0) this.#applyChange(change, nextSelections, this.#applyChangeToLineAnnotations(change));
|
|
1269
|
+
}
|
|
1237
1270
|
#deleteHardLineForward() {
|
|
1238
1271
|
const selections = this.#selections;
|
|
1239
1272
|
const textDocument = this.#textDocument;
|
|
@@ -1259,9 +1292,11 @@ var Editor = class {
|
|
|
1259
1292
|
const onChange = this.#options.onChange;
|
|
1260
1293
|
if (fileContents !== void 0 && textDocument !== void 0 && onChange !== void 0) {
|
|
1261
1294
|
const { contents: _,...file } = fileContents;
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
1295
|
+
Object.defineProperty(file, "contents", {
|
|
1296
|
+
enumerable: true,
|
|
1297
|
+
get: () => textDocument.getText()
|
|
1298
|
+
});
|
|
1299
|
+
onChange(file, newLineAnnotations ?? this.#lineAnnotations);
|
|
1265
1300
|
}
|
|
1266
1301
|
if (change.lineDelta !== 0) {
|
|
1267
1302
|
for (const line of this.#lineYCache.keys()) if (line >= change.startLine) this.#lineYCache.delete(line);
|
|
@@ -1269,7 +1304,7 @@ var Editor = class {
|
|
|
1269
1304
|
if (this.#wrap) {
|
|
1270
1305
|
for (const line of this.#wrapLineOffsetsCache.keys()) if (line >= change.startLine) this.#wrapLineOffsetsCache.delete(line);
|
|
1271
1306
|
}
|
|
1272
|
-
this.#
|
|
1307
|
+
this.#lastAccessedCharX = void 0;
|
|
1273
1308
|
let renderRange = this.#renderRange;
|
|
1274
1309
|
let shouldUpdateBuffer;
|
|
1275
1310
|
if (renderRange !== void 0 && selections !== void 0 && selections.length > 0) {
|
|
@@ -1305,28 +1340,40 @@ var Editor = class {
|
|
|
1305
1340
|
}
|
|
1306
1341
|
}
|
|
1307
1342
|
#getLineElement(line) {
|
|
1343
|
+
const lastAccessed = this.#lastAccessedLineElement;
|
|
1344
|
+
if (lastAccessed !== void 0 && lastAccessed[0] === line) return lastAccessed[1];
|
|
1308
1345
|
const contentElement = this.#contentElement;
|
|
1309
1346
|
if (contentElement === void 0) return;
|
|
1310
|
-
|
|
1347
|
+
let lineElement = null;
|
|
1348
|
+
if (this.#renderRange !== void 0) {
|
|
1311
1349
|
const { startingLine } = this.#renderRange;
|
|
1312
1350
|
const { children } = contentElement;
|
|
1313
1351
|
for (let i = line - startingLine; i <= children.length; i++) {
|
|
1314
1352
|
const child = children[i];
|
|
1315
|
-
|
|
1316
|
-
const
|
|
1317
|
-
|
|
1353
|
+
if (child === void 0) break;
|
|
1354
|
+
const lineNumber = getLineNumberAttr(child);
|
|
1355
|
+
const lineType = child.dataset.lineType;
|
|
1356
|
+
if (lineNumber !== void 0 && lineNumber === line + 1 && lineType !== void 0 && isLineEditable(lineType)) {
|
|
1357
|
+
lineElement = child;
|
|
1358
|
+
break;
|
|
1359
|
+
}
|
|
1318
1360
|
}
|
|
1319
1361
|
}
|
|
1320
|
-
|
|
1321
|
-
|
|
1362
|
+
lineElement ??= contentElement.querySelector(`[data-line="${line + 1}"]`);
|
|
1363
|
+
if (lineElement !== null) {
|
|
1364
|
+
if (lastAccessed !== void 0) {
|
|
1365
|
+
lastAccessed[0] = line;
|
|
1366
|
+
lastAccessed[1] = lineElement;
|
|
1367
|
+
} else this.#lastAccessedLineElement = [line, lineElement];
|
|
1368
|
+
return lineElement;
|
|
1369
|
+
}
|
|
1322
1370
|
}
|
|
1323
1371
|
#getGutterWidth() {
|
|
1324
|
-
|
|
1325
|
-
if (gutterElement == null || !(gutterElement instanceof HTMLElement) || !gutterElement.hasAttribute("data-gutter")) return 0;
|
|
1372
|
+
if (this.#gutterElement === void 0) return 0;
|
|
1326
1373
|
if (this.#gutterWidthCache === void 0) {
|
|
1327
1374
|
const diffsColumnNumberWidth = this.#contentElement?.parentElement?.style.getPropertyValue("--diffs-column-number-width");
|
|
1328
1375
|
if (diffsColumnNumberWidth !== void 0 && diffsColumnNumberWidth.length > 2 && diffsColumnNumberWidth.endsWith("px")) this.#gutterWidthCache = parseInt(diffsColumnNumberWidth.slice(0, -2), 10);
|
|
1329
|
-
else this.#gutterWidthCache = gutterElement.offsetWidth;
|
|
1376
|
+
else this.#gutterWidthCache = this.#gutterElement.offsetWidth;
|
|
1330
1377
|
}
|
|
1331
1378
|
return this.#gutterWidthCache;
|
|
1332
1379
|
}
|
|
@@ -1349,7 +1396,7 @@ var Editor = class {
|
|
|
1349
1396
|
return y;
|
|
1350
1397
|
}
|
|
1351
1398
|
#getCharX(line, char) {
|
|
1352
|
-
if (this.#
|
|
1399
|
+
if (this.#lastAccessedCharX !== void 0 && this.#lastAccessedCharX[0] === line && this.#lastAccessedCharX[1] === char) return [this.#lastAccessedCharX[2], this.#lastAccessedCharX[3]];
|
|
1353
1400
|
const lineText = this.#textDocument?.getLineText(line);
|
|
1354
1401
|
const offsetLeft = this.#getGutterWidth() + this.#metrics.ch;
|
|
1355
1402
|
if (lineText === void 0 || lineText.length === 0 || char <= 0) return [offsetLeft, 0];
|
|
@@ -1377,12 +1424,12 @@ var Editor = class {
|
|
|
1377
1424
|
}
|
|
1378
1425
|
}
|
|
1379
1426
|
}
|
|
1380
|
-
if (this.#
|
|
1381
|
-
this.#
|
|
1382
|
-
this.#
|
|
1383
|
-
this.#
|
|
1384
|
-
this.#
|
|
1385
|
-
} else this.#
|
|
1427
|
+
if (this.#lastAccessedCharX !== void 0) {
|
|
1428
|
+
this.#lastAccessedCharX[0] = line;
|
|
1429
|
+
this.#lastAccessedCharX[1] = char;
|
|
1430
|
+
this.#lastAccessedCharX[2] = left;
|
|
1431
|
+
this.#lastAccessedCharX[3] = wrapLine;
|
|
1432
|
+
} else this.#lastAccessedCharX = [
|
|
1386
1433
|
line,
|
|
1387
1434
|
char,
|
|
1388
1435
|
left,
|