stream-monaco 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +399 -0
- package/README.zh-CN.md +714 -0
- package/cli.mjs +2 -0
- package/dist/chunk-CHLpw0oG.js +25 -0
- package/dist/index.cjs +2079 -0
- package/dist/index.d.cts +282 -0
- package/dist/index.d.ts +281 -0
- package/dist/index.js +2043 -0
- package/license +21 -0
- package/package.json +100 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,2043 @@
|
|
|
1
|
+
import { __export, __reExport } from "./chunk-CHLpw0oG.js";
|
|
2
|
+
import * as _monaco from "monaco-editor";
|
|
3
|
+
import { computed, effect, signal } from "alien-signals";
|
|
4
|
+
import { shikiToMonaco } from "@shikijs/monaco";
|
|
5
|
+
import { createHighlighter } from "shiki";
|
|
6
|
+
|
|
7
|
+
//#region src/code.detect.ts
|
|
8
|
+
/**
|
|
9
|
+
* Language detection definitions
|
|
10
|
+
*/
|
|
11
|
+
const languages = [
|
|
12
|
+
[
|
|
13
|
+
"bash",
|
|
14
|
+
[/#!(\/usr)?\/bin\/bash/g, 500],
|
|
15
|
+
[/\b(if|elif|then|fi|echo)\b|\$/g, 10]
|
|
16
|
+
],
|
|
17
|
+
[
|
|
18
|
+
"html",
|
|
19
|
+
[/<\/?[a-z-][^\n>]*>/g, 10],
|
|
20
|
+
[/^\s+<!DOCTYPE\s+html/g, 500]
|
|
21
|
+
],
|
|
22
|
+
["http", [/^(GET|HEAD|POST|PUT|DELETE|PATCH|HTTP)\b/g, 500]],
|
|
23
|
+
["js", [/\b(console|await|async|function|export|import|this|class|for|let|const|map|join|require)\b/g, 10]],
|
|
24
|
+
["ts", [/\b(console|await|async|function|export|import|this|class|for|let|const|map|join|require|implements|interface|namespace)\b/g, 10]],
|
|
25
|
+
["py", [/\b(def|print|class|and|or|lambda)\b/g, 10]],
|
|
26
|
+
["sql", [/\b(SELECT|INSERT|FROM)\b/g, 50]],
|
|
27
|
+
[
|
|
28
|
+
"pl",
|
|
29
|
+
[/#!(\/usr)?\/bin\/perl/g, 500],
|
|
30
|
+
[/\b(use|print)\b|\$/g, 10]
|
|
31
|
+
],
|
|
32
|
+
["lua", [/#!(\/usr)?\/bin\/lua/g, 500]],
|
|
33
|
+
["make", [/\b(ifneq|endif|if|elif|then|fi|echo|.PHONY|^[a-z]+ ?:$)\b|\$/gm, 10]],
|
|
34
|
+
["uri", [/https?:|mailto:|tel:|ftp:/g, 30]],
|
|
35
|
+
["css", [/^(@import|@page|@media|(\.|#)[a-z]+)/gm, 20]],
|
|
36
|
+
[
|
|
37
|
+
"diff",
|
|
38
|
+
[/^[+><-]/gm, 10],
|
|
39
|
+
[/^@@[-+,0-9 ]+@@/gm, 25]
|
|
40
|
+
],
|
|
41
|
+
[
|
|
42
|
+
"md",
|
|
43
|
+
[/^(>|\t\*|\t\d+.|#{1,6} |-\s+|\*\s+)/gm, 25],
|
|
44
|
+
[/\[.*\](.*)/g, 10]
|
|
45
|
+
],
|
|
46
|
+
["docker", [/^(FROM|ENTRYPOINT|RUN)/gm, 500]],
|
|
47
|
+
[
|
|
48
|
+
"xml",
|
|
49
|
+
[/<\/?[a-z-][^\n>]*>/g, 10],
|
|
50
|
+
[/^<\?xml/g, 500]
|
|
51
|
+
],
|
|
52
|
+
["c", [/#include\b|\bprintf\s+\(/g, 100]],
|
|
53
|
+
["rs", [/^\s+(use|fn|mut|match)\b/gm, 100]],
|
|
54
|
+
["go", [/\b(func|fmt|package)\b/g, 100]],
|
|
55
|
+
["java", [/^import\s+java/gm, 500]],
|
|
56
|
+
["asm", [/^(section|global main|extern|\t(call|mov|ret))/gm, 100]],
|
|
57
|
+
["css", [/^(@import|@page|@media|(\.|#)[a-z]+)/gm, 20]],
|
|
58
|
+
["json", [/\b(true|false|null|\{\})\b|"[^"]+":/g, 10]],
|
|
59
|
+
["yaml", [/^(\s+)?[a-z][a-z0-9]*:/gim, 10]],
|
|
60
|
+
[
|
|
61
|
+
"toml",
|
|
62
|
+
[/^\s*\[.*\]\s*$/gm, 100],
|
|
63
|
+
[/^\s*[\w-]+ *= */gm, 20]
|
|
64
|
+
],
|
|
65
|
+
[
|
|
66
|
+
"mermaid",
|
|
67
|
+
[/^(graph|flowchart|sequenceDiagram|classDiagram|stateDiagram|erDiagram|gantt|pie|mindmap)/gm, 500],
|
|
68
|
+
[/\b(-->|--o|--x|=>|\[\]|[{}])\b/g, 10]
|
|
69
|
+
]
|
|
70
|
+
];
|
|
71
|
+
/**
|
|
72
|
+
* Try to find the language the given code belongs to
|
|
73
|
+
*
|
|
74
|
+
* @param {string} code The code to analyze
|
|
75
|
+
* @param {LanguageDefinition[]} [additionalLanguages] Additional language definitions to supplement the built-in ones
|
|
76
|
+
* @returns {CodeLanguage} The detected language of the code
|
|
77
|
+
*/
|
|
78
|
+
function detectLanguage(code, additionalLanguages) {
|
|
79
|
+
var _allLanguages$map$fil;
|
|
80
|
+
const allLanguages = additionalLanguages ? [...languages, ...additionalLanguages] : languages;
|
|
81
|
+
return ((_allLanguages$map$fil = allLanguages.map(([lang, ...features]) => [lang, features.reduce((acc, [match, score]) => acc + [...code.matchAll(match)].length * score, 0)]).filter(([, score]) => score > 20).sort((a, b) => b[1] - a[1])[0]) === null || _allLanguages$map$fil === void 0 ? void 0 : _allLanguages$map$fil[0]) || "plain";
|
|
82
|
+
}
|
|
83
|
+
function processedLanguage(language) {
|
|
84
|
+
if (/^(?:shellscript|bash|sh|shell|zsh)/i.test(language)) return "shell";
|
|
85
|
+
if (/^(?:powershell|ps1?)/i.test(language)) return "powershell";
|
|
86
|
+
return language.split(":")[0];
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* 使用示例:
|
|
90
|
+
*
|
|
91
|
+
* // 基本用法
|
|
92
|
+
* const language1 = detectLanguage('console.log("hello")') // 'js'
|
|
93
|
+
*
|
|
94
|
+
* // 使用自定义语言检测规则
|
|
95
|
+
* const customLanguages: LanguageDefinition[] = [
|
|
96
|
+
* ['vue', [/<template>/g, 100], [/<script>/g, 50], [/<style>/g, 50]],
|
|
97
|
+
* ['kotlin', [/\b(fun|class|val|var)\b/g, 20]]
|
|
98
|
+
* ]
|
|
99
|
+
*
|
|
100
|
+
* const language2 = detectLanguage(`
|
|
101
|
+
* <template>
|
|
102
|
+
* <div>Hello Vue</div>
|
|
103
|
+
* </template>
|
|
104
|
+
* `, customLanguages) // 'vue'
|
|
105
|
+
*
|
|
106
|
+
* const language3 = detectLanguage(`
|
|
107
|
+
* fun main() {
|
|
108
|
+
* val name = "Kotlin"
|
|
109
|
+
* println("Hello $name")
|
|
110
|
+
* }
|
|
111
|
+
* `, customLanguages) // 'kotlin'
|
|
112
|
+
*/
|
|
113
|
+
|
|
114
|
+
//#endregion
|
|
115
|
+
//#region src/constant.ts
|
|
116
|
+
const defaultLanguages = [
|
|
117
|
+
"jsx",
|
|
118
|
+
"tsx",
|
|
119
|
+
"vue",
|
|
120
|
+
"csharp",
|
|
121
|
+
"python",
|
|
122
|
+
"java",
|
|
123
|
+
"c",
|
|
124
|
+
"cpp",
|
|
125
|
+
"rust",
|
|
126
|
+
"go",
|
|
127
|
+
"powershell",
|
|
128
|
+
"sql",
|
|
129
|
+
"json",
|
|
130
|
+
"html",
|
|
131
|
+
"javascript",
|
|
132
|
+
"typescript",
|
|
133
|
+
"css",
|
|
134
|
+
"markdown",
|
|
135
|
+
"xml",
|
|
136
|
+
"yaml",
|
|
137
|
+
"toml",
|
|
138
|
+
"dockerfile",
|
|
139
|
+
"kotlin",
|
|
140
|
+
"objective-c",
|
|
141
|
+
"objective-cpp",
|
|
142
|
+
"php",
|
|
143
|
+
"ruby",
|
|
144
|
+
"scala",
|
|
145
|
+
"svelte",
|
|
146
|
+
"swift",
|
|
147
|
+
"erlang",
|
|
148
|
+
"angular-html",
|
|
149
|
+
"angular-ts",
|
|
150
|
+
"dart",
|
|
151
|
+
"lua",
|
|
152
|
+
"mermaid",
|
|
153
|
+
"cmake",
|
|
154
|
+
"nginx"
|
|
155
|
+
];
|
|
156
|
+
const defaultThemes = ["vitesse-dark", "vitesse-light"];
|
|
157
|
+
const defaultScrollbar = {
|
|
158
|
+
verticalScrollbarSize: 8,
|
|
159
|
+
horizontalScrollbarSize: 8,
|
|
160
|
+
handleMouseWheel: true,
|
|
161
|
+
alwaysConsumeMouseWheel: false
|
|
162
|
+
};
|
|
163
|
+
const padding = 16;
|
|
164
|
+
const defaultRevealDebounceMs = 75;
|
|
165
|
+
const defaultRevealBatchOnIdleMs = 200;
|
|
166
|
+
const minimalEditMaxChars = 2e5;
|
|
167
|
+
const minimalEditMaxChangeRatio = .5;
|
|
168
|
+
|
|
169
|
+
//#endregion
|
|
170
|
+
//#region src/minimalEdit.ts
|
|
171
|
+
/**
|
|
172
|
+
* Compute the minimal middle replacement between two UTF-16 strings.
|
|
173
|
+
* Returns null when prev === next (no edits required).
|
|
174
|
+
*/
|
|
175
|
+
function computeMinimalEdit(prev, next) {
|
|
176
|
+
if (prev === next) return null;
|
|
177
|
+
let start = 0;
|
|
178
|
+
const minLen = Math.min(prev.length, next.length);
|
|
179
|
+
while (start < minLen && prev.charCodeAt(start) === next.charCodeAt(start)) start++;
|
|
180
|
+
let endPrev = prev.length - 1;
|
|
181
|
+
let endNext = next.length - 1;
|
|
182
|
+
while (endPrev >= start && endNext >= start && prev.charCodeAt(endPrev) === next.charCodeAt(endNext)) {
|
|
183
|
+
endPrev--;
|
|
184
|
+
endNext--;
|
|
185
|
+
}
|
|
186
|
+
return {
|
|
187
|
+
start,
|
|
188
|
+
endPrevIncl: endPrev,
|
|
189
|
+
endNextIncl: endNext,
|
|
190
|
+
replaceText: next.slice(start, endNext + 1)
|
|
191
|
+
};
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
//#endregion
|
|
195
|
+
//#region src/monaco-shim.ts
|
|
196
|
+
var monaco_shim_exports = {};
|
|
197
|
+
__export(monaco_shim_exports, { default: () => monaco });
|
|
198
|
+
import * as import_monaco_editor from "monaco-editor";
|
|
199
|
+
__reExport(monaco_shim_exports, import_monaco_editor);
|
|
200
|
+
const monaco = _monaco;
|
|
201
|
+
|
|
202
|
+
//#endregion
|
|
203
|
+
//#region src/utils/height.ts
|
|
204
|
+
function createHeightManager(container, computeNext) {
|
|
205
|
+
let raf = null;
|
|
206
|
+
let lastApplied = -1;
|
|
207
|
+
let suppressed = false;
|
|
208
|
+
function apply() {
|
|
209
|
+
const next = computeNext();
|
|
210
|
+
if (next === lastApplied) return;
|
|
211
|
+
suppressed = true;
|
|
212
|
+
container.style.height = `${next}px`;
|
|
213
|
+
lastApplied = next;
|
|
214
|
+
queueMicrotask(() => {
|
|
215
|
+
suppressed = false;
|
|
216
|
+
});
|
|
217
|
+
}
|
|
218
|
+
function update() {
|
|
219
|
+
if (raf != null) return;
|
|
220
|
+
raf = requestAnimationFrame(() => {
|
|
221
|
+
raf = null;
|
|
222
|
+
apply();
|
|
223
|
+
});
|
|
224
|
+
}
|
|
225
|
+
function dispose() {
|
|
226
|
+
if (raf != null) {
|
|
227
|
+
cancelAnimationFrame(raf);
|
|
228
|
+
raf = null;
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
function isSuppressed() {
|
|
232
|
+
return suppressed;
|
|
233
|
+
}
|
|
234
|
+
function getLastApplied() {
|
|
235
|
+
return lastApplied;
|
|
236
|
+
}
|
|
237
|
+
return {
|
|
238
|
+
update,
|
|
239
|
+
dispose,
|
|
240
|
+
isSuppressed,
|
|
241
|
+
getLastApplied
|
|
242
|
+
};
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
//#endregion
|
|
246
|
+
//#region src/utils/raf.ts
|
|
247
|
+
/**
|
|
248
|
+
* Create a per-instance RAF scheduler that coalesces tasks by "kind" within
|
|
249
|
+
* the same instance. Instances are isolated so different editors won't
|
|
250
|
+
* cancel each other's scheduled work.
|
|
251
|
+
*/
|
|
252
|
+
function createRafScheduler(timeSource) {
|
|
253
|
+
const ids = {};
|
|
254
|
+
const ts = timeSource ?? {
|
|
255
|
+
requestAnimationFrame: (cb) => requestAnimationFrame(cb),
|
|
256
|
+
cancelAnimationFrame: (id) => cancelAnimationFrame(id)
|
|
257
|
+
};
|
|
258
|
+
function schedule(kind, cb) {
|
|
259
|
+
const existing = ids[kind];
|
|
260
|
+
if (existing != null) ts.cancelAnimationFrame(existing);
|
|
261
|
+
ids[kind] = ts.requestAnimationFrame((t) => {
|
|
262
|
+
ids[kind] = null;
|
|
263
|
+
cb(t);
|
|
264
|
+
});
|
|
265
|
+
}
|
|
266
|
+
function cancel(kind) {
|
|
267
|
+
const id = ids[kind];
|
|
268
|
+
if (id != null) {
|
|
269
|
+
ts.cancelAnimationFrame(id);
|
|
270
|
+
ids[kind] = null;
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
return {
|
|
274
|
+
schedule,
|
|
275
|
+
cancel
|
|
276
|
+
};
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
//#endregion
|
|
280
|
+
//#region src/utils/scroll.ts
|
|
281
|
+
function createScrollWatcherForEditor(ed, opts) {
|
|
282
|
+
var _ed$getScrollTop, _ed$onDidScrollChange;
|
|
283
|
+
const initial = ((_ed$getScrollTop = ed.getScrollTop) === null || _ed$getScrollTop === void 0 ? void 0 : _ed$getScrollTop.call(ed)) ?? 0;
|
|
284
|
+
opts.setLast(initial);
|
|
285
|
+
const disp = ((_ed$onDidScrollChange = ed.onDidScrollChange) === null || _ed$onDidScrollChange === void 0 ? void 0 : _ed$onDidScrollChange.call(ed, (e) => {
|
|
286
|
+
var _ed$getScrollTop2;
|
|
287
|
+
const currentTop = e && typeof e.scrollTop === "number" ? e.scrollTop : ((_ed$getScrollTop2 = ed.getScrollTop) === null || _ed$getScrollTop2 === void 0 ? void 0 : _ed$getScrollTop2.call(ed)) ?? 0;
|
|
288
|
+
const delta = currentTop - opts.getLast();
|
|
289
|
+
opts.setLast(currentTop);
|
|
290
|
+
if (delta < 0) {
|
|
291
|
+
opts.onPause();
|
|
292
|
+
return;
|
|
293
|
+
}
|
|
294
|
+
opts.onMaybeResume();
|
|
295
|
+
})) ?? null;
|
|
296
|
+
return disp;
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
//#endregion
|
|
300
|
+
//#region src/core/DiffEditorManager.ts
|
|
301
|
+
var DiffEditorManager = class {
|
|
302
|
+
diffEditorView = null;
|
|
303
|
+
originalModel = null;
|
|
304
|
+
modifiedModel = null;
|
|
305
|
+
lastContainer = null;
|
|
306
|
+
lastKnownOriginalCode = null;
|
|
307
|
+
lastKnownModifiedCode = null;
|
|
308
|
+
lastKnownModifiedLineCount = null;
|
|
309
|
+
pendingDiffUpdate = null;
|
|
310
|
+
shouldAutoScrollDiff = true;
|
|
311
|
+
diffScrollWatcher = null;
|
|
312
|
+
lastScrollTopDiff = 0;
|
|
313
|
+
_hasScrollBar = false;
|
|
314
|
+
cachedScrollHeightDiff = null;
|
|
315
|
+
cachedLineHeightDiff = null;
|
|
316
|
+
cachedComputedHeightDiff = null;
|
|
317
|
+
lastKnownModifiedDirty = false;
|
|
318
|
+
measureViewportDiff() {
|
|
319
|
+
var _me$getLayoutInfo, _me$getScrollTop, _me$getScrollHeight;
|
|
320
|
+
if (!this.diffEditorView) return null;
|
|
321
|
+
const me = this.diffEditorView.getModifiedEditor();
|
|
322
|
+
const li = ((_me$getLayoutInfo = me.getLayoutInfo) === null || _me$getLayoutInfo === void 0 ? void 0 : _me$getLayoutInfo.call(me)) ?? null;
|
|
323
|
+
const lineHeight = this.cachedLineHeightDiff ?? me.getOption(monaco_shim_exports.editor.EditorOption.lineHeight);
|
|
324
|
+
const scrollTop = ((_me$getScrollTop = me.getScrollTop) === null || _me$getScrollTop === void 0 ? void 0 : _me$getScrollTop.call(me)) ?? this.lastScrollTopDiff ?? 0;
|
|
325
|
+
const scrollHeight = ((_me$getScrollHeight = me.getScrollHeight) === null || _me$getScrollHeight === void 0 ? void 0 : _me$getScrollHeight.call(me)) ?? this.cachedScrollHeightDiff ?? (li === null || li === void 0 ? void 0 : li.height) ?? 0;
|
|
326
|
+
const computedHeight = this.cachedComputedHeightDiff ?? this.computedHeight();
|
|
327
|
+
this.cachedLineHeightDiff = lineHeight;
|
|
328
|
+
this.cachedScrollHeightDiff = scrollHeight;
|
|
329
|
+
this.cachedComputedHeightDiff = computedHeight;
|
|
330
|
+
this.lastScrollTopDiff = scrollTop;
|
|
331
|
+
return {
|
|
332
|
+
me,
|
|
333
|
+
li,
|
|
334
|
+
lineHeight,
|
|
335
|
+
scrollTop,
|
|
336
|
+
scrollHeight,
|
|
337
|
+
computedHeight
|
|
338
|
+
};
|
|
339
|
+
}
|
|
340
|
+
lastRevealLineDiff = null;
|
|
341
|
+
revealDebounceIdDiff = null;
|
|
342
|
+
revealDebounceMs = defaultRevealDebounceMs;
|
|
343
|
+
revealIdleTimerIdDiff = null;
|
|
344
|
+
revealStrategyOption;
|
|
345
|
+
revealBatchOnIdleMsOption;
|
|
346
|
+
appendBufferDiff = [];
|
|
347
|
+
appendBufferDiffScheduled = false;
|
|
348
|
+
rafScheduler = createRafScheduler();
|
|
349
|
+
diffHeightManager = null;
|
|
350
|
+
constructor(options, maxHeightValue, maxHeightCSS, autoScrollOnUpdate, autoScrollInitial, autoScrollThresholdPx, autoScrollThresholdLines, diffAutoScroll, revealDebounceMsOption) {
|
|
351
|
+
this.options = options;
|
|
352
|
+
this.maxHeightValue = maxHeightValue;
|
|
353
|
+
this.maxHeightCSS = maxHeightCSS;
|
|
354
|
+
this.autoScrollOnUpdate = autoScrollOnUpdate;
|
|
355
|
+
this.autoScrollInitial = autoScrollInitial;
|
|
356
|
+
this.autoScrollThresholdPx = autoScrollThresholdPx;
|
|
357
|
+
this.autoScrollThresholdLines = autoScrollThresholdLines;
|
|
358
|
+
this.diffAutoScroll = diffAutoScroll;
|
|
359
|
+
this.revealDebounceMsOption = revealDebounceMsOption;
|
|
360
|
+
}
|
|
361
|
+
computedHeight() {
|
|
362
|
+
var _originalEditor$getMo, _modifiedEditor$getMo, _originalEditor$getSc, _modifiedEditor$getSc;
|
|
363
|
+
if (!this.diffEditorView) return Math.min(1 * 18 + padding, this.maxHeightValue);
|
|
364
|
+
const modifiedEditor = this.diffEditorView.getModifiedEditor();
|
|
365
|
+
const originalEditor = this.diffEditorView.getOriginalEditor();
|
|
366
|
+
const lineHeight = modifiedEditor.getOption(monaco_shim_exports.editor.EditorOption.lineHeight);
|
|
367
|
+
const oCount = ((_originalEditor$getMo = originalEditor.getModel()) === null || _originalEditor$getMo === void 0 ? void 0 : _originalEditor$getMo.getLineCount()) ?? 1;
|
|
368
|
+
const mCount = ((_modifiedEditor$getMo = modifiedEditor.getModel()) === null || _modifiedEditor$getMo === void 0 ? void 0 : _modifiedEditor$getMo.getLineCount()) ?? 1;
|
|
369
|
+
const lineCount = Math.max(oCount, mCount);
|
|
370
|
+
const fromLines = lineCount * lineHeight + padding;
|
|
371
|
+
const scrollH = Math.max(((_originalEditor$getSc = originalEditor.getScrollHeight) === null || _originalEditor$getSc === void 0 ? void 0 : _originalEditor$getSc.call(originalEditor)) ?? 0, ((_modifiedEditor$getSc = modifiedEditor.getScrollHeight) === null || _modifiedEditor$getSc === void 0 ? void 0 : _modifiedEditor$getSc.call(modifiedEditor)) ?? 0);
|
|
372
|
+
const desired = Math.max(fromLines, scrollH);
|
|
373
|
+
return Math.min(desired, this.maxHeightValue);
|
|
374
|
+
}
|
|
375
|
+
hasVerticalScrollbarModified() {
|
|
376
|
+
if (!this.diffEditorView) return false;
|
|
377
|
+
if (this._hasScrollBar) return true;
|
|
378
|
+
const m = this.measureViewportDiff();
|
|
379
|
+
if (!m) return false;
|
|
380
|
+
const epsilon = Math.max(2, Math.round(m.lineHeight / 8));
|
|
381
|
+
return this._hasScrollBar = m.scrollHeight > m.computedHeight + Math.max(padding / 2, epsilon);
|
|
382
|
+
}
|
|
383
|
+
userIsNearBottomDiff() {
|
|
384
|
+
if (!this.diffEditorView) return true;
|
|
385
|
+
const m = this.measureViewportDiff();
|
|
386
|
+
if (!m || !m.li) return true;
|
|
387
|
+
const lineThreshold = (this.autoScrollThresholdLines ?? 0) * m.lineHeight;
|
|
388
|
+
const threshold = Math.max(lineThreshold || 0, this.autoScrollThresholdPx || 0);
|
|
389
|
+
const distance = m.scrollHeight - (m.scrollTop + m.li.height);
|
|
390
|
+
return distance <= threshold;
|
|
391
|
+
}
|
|
392
|
+
maybeScrollDiffToBottom(targetLine, prevLineOverride) {
|
|
393
|
+
this.rafScheduler.schedule("maybe-scroll-diff", () => {
|
|
394
|
+
if (!this.diffEditorView) return;
|
|
395
|
+
if (!(this.diffAutoScroll && this.autoScrollOnUpdate && this.shouldAutoScrollDiff && this.hasVerticalScrollbarModified())) return;
|
|
396
|
+
const me = this.diffEditorView.getModifiedEditor();
|
|
397
|
+
const model = me.getModel();
|
|
398
|
+
const currentLine = (model === null || model === void 0 ? void 0 : model.getLineCount()) ?? 1;
|
|
399
|
+
const line = targetLine ?? currentLine;
|
|
400
|
+
const prevLine = typeof prevLineOverride === "number" ? prevLineOverride : this.lastKnownModifiedLineCount ?? -1;
|
|
401
|
+
if (prevLine !== -1 && prevLine === currentLine && line === currentLine) return;
|
|
402
|
+
if (this.lastRevealLineDiff !== null && this.lastRevealLineDiff === line) return;
|
|
403
|
+
const batchMs = this.revealBatchOnIdleMsOption ?? this.options.revealBatchOnIdleMs ?? defaultRevealBatchOnIdleMs;
|
|
404
|
+
if (typeof batchMs === "number" && batchMs > 0) {
|
|
405
|
+
if (this.revealIdleTimerIdDiff != null) clearTimeout(this.revealIdleTimerIdDiff);
|
|
406
|
+
this.revealIdleTimerIdDiff = setTimeout(() => {
|
|
407
|
+
this.revealIdleTimerIdDiff = null;
|
|
408
|
+
this.performRevealDiff(line);
|
|
409
|
+
}, batchMs);
|
|
410
|
+
return;
|
|
411
|
+
}
|
|
412
|
+
if (this.revealDebounceIdDiff != null) {
|
|
413
|
+
clearTimeout(this.revealDebounceIdDiff);
|
|
414
|
+
this.revealDebounceIdDiff = null;
|
|
415
|
+
}
|
|
416
|
+
const ms = typeof this.revealDebounceMs === "number" && this.revealDebounceMs > 0 ? this.revealDebounceMs : typeof this.revealDebounceMsOption === "number" && this.revealDebounceMsOption > 0 ? this.revealDebounceMsOption : this.revealDebounceMs;
|
|
417
|
+
this.revealDebounceIdDiff = setTimeout(() => {
|
|
418
|
+
this.revealDebounceIdDiff = null;
|
|
419
|
+
this.performRevealDiff(line);
|
|
420
|
+
}, ms);
|
|
421
|
+
this.lastKnownModifiedLineCount = currentLine;
|
|
422
|
+
});
|
|
423
|
+
}
|
|
424
|
+
performRevealDiff(line) {
|
|
425
|
+
this.rafScheduler.schedule("revealDiff", () => {
|
|
426
|
+
var _editor;
|
|
427
|
+
const strategy = this.revealStrategyOption ?? this.options.revealStrategy ?? "centerIfOutside";
|
|
428
|
+
const ScrollType = monaco_shim_exports.ScrollType || ((_editor = monaco_shim_exports.editor) === null || _editor === void 0 ? void 0 : _editor.ScrollType);
|
|
429
|
+
const smooth = ScrollType && typeof ScrollType.Smooth !== "undefined" ? ScrollType.Smooth : void 0;
|
|
430
|
+
try {
|
|
431
|
+
const me = this.diffEditorView.getModifiedEditor();
|
|
432
|
+
if (strategy === "bottom") if (typeof smooth !== "undefined") me.revealLine(line, smooth);
|
|
433
|
+
else me.revealLine(line);
|
|
434
|
+
else if (strategy === "center") if (typeof smooth !== "undefined") me.revealLineInCenter(line, smooth);
|
|
435
|
+
else me.revealLineInCenter(line);
|
|
436
|
+
else if (typeof smooth !== "undefined") me.revealLineInCenterIfOutsideViewport(line, smooth);
|
|
437
|
+
else me.revealLineInCenterIfOutsideViewport(line);
|
|
438
|
+
} catch {
|
|
439
|
+
try {
|
|
440
|
+
this.diffEditorView.getModifiedEditor().revealLine(line);
|
|
441
|
+
} catch {}
|
|
442
|
+
}
|
|
443
|
+
this.lastRevealLineDiff = line;
|
|
444
|
+
});
|
|
445
|
+
}
|
|
446
|
+
async createDiffEditor(container, originalCode, modifiedCode, language, currentTheme) {
|
|
447
|
+
var _me$getScrollHeight2, _me$getOption, _oEditor$onDidContent, _mEditor$onDidContent;
|
|
448
|
+
this.cleanup();
|
|
449
|
+
this.lastContainer = container;
|
|
450
|
+
container.style.overflow = "auto";
|
|
451
|
+
container.style.maxHeight = this.maxHeightCSS;
|
|
452
|
+
const lang = processedLanguage(language) || language;
|
|
453
|
+
this.originalModel = monaco_shim_exports.editor.createModel(originalCode, lang);
|
|
454
|
+
this.modifiedModel = monaco_shim_exports.editor.createModel(modifiedCode, lang);
|
|
455
|
+
this.diffEditorView = monaco_shim_exports.editor.createDiffEditor(container, {
|
|
456
|
+
automaticLayout: true,
|
|
457
|
+
scrollBeyondLastLine: false,
|
|
458
|
+
renderSideBySide: true,
|
|
459
|
+
originalEditable: false,
|
|
460
|
+
readOnly: this.options.readOnly ?? true,
|
|
461
|
+
minimap: { enabled: false },
|
|
462
|
+
theme: currentTheme,
|
|
463
|
+
contextmenu: false,
|
|
464
|
+
scrollbar: {
|
|
465
|
+
...defaultScrollbar,
|
|
466
|
+
...this.options.scrollbar || {}
|
|
467
|
+
},
|
|
468
|
+
...this.options
|
|
469
|
+
});
|
|
470
|
+
monaco_shim_exports.editor.setTheme(currentTheme);
|
|
471
|
+
this.diffEditorView.setModel({
|
|
472
|
+
original: this.originalModel,
|
|
473
|
+
modified: this.modifiedModel
|
|
474
|
+
});
|
|
475
|
+
this.lastKnownOriginalCode = originalCode;
|
|
476
|
+
this.lastKnownModifiedCode = modifiedCode;
|
|
477
|
+
this.shouldAutoScrollDiff = !!(this.autoScrollInitial && this.diffAutoScroll);
|
|
478
|
+
if (this.diffScrollWatcher) {
|
|
479
|
+
this.diffScrollWatcher.dispose();
|
|
480
|
+
this.diffScrollWatcher = null;
|
|
481
|
+
}
|
|
482
|
+
if (this.diffAutoScroll) {
|
|
483
|
+
const me$1 = this.diffEditorView.getModifiedEditor();
|
|
484
|
+
this.diffScrollWatcher = createScrollWatcherForEditor(me$1, {
|
|
485
|
+
onPause: () => {
|
|
486
|
+
this.shouldAutoScrollDiff = false;
|
|
487
|
+
},
|
|
488
|
+
onMaybeResume: () => {
|
|
489
|
+
this.rafScheduler.schedule("maybe-resume-diff", () => {
|
|
490
|
+
this.shouldAutoScrollDiff = this.userIsNearBottomDiff();
|
|
491
|
+
});
|
|
492
|
+
},
|
|
493
|
+
getLast: () => this.lastScrollTopDiff,
|
|
494
|
+
setLast: (v) => {
|
|
495
|
+
this.lastScrollTopDiff = v;
|
|
496
|
+
}
|
|
497
|
+
});
|
|
498
|
+
}
|
|
499
|
+
this.maybeScrollDiffToBottom(this.modifiedModel.getLineCount(), this.lastKnownModifiedLineCount ?? void 0);
|
|
500
|
+
if (this.diffHeightManager) {
|
|
501
|
+
this.diffHeightManager.dispose();
|
|
502
|
+
this.diffHeightManager = null;
|
|
503
|
+
}
|
|
504
|
+
this.diffHeightManager = createHeightManager(container, () => this.computedHeight());
|
|
505
|
+
this.diffHeightManager.update();
|
|
506
|
+
const me = this.diffEditorView.getModifiedEditor();
|
|
507
|
+
this.cachedScrollHeightDiff = ((_me$getScrollHeight2 = me.getScrollHeight) === null || _me$getScrollHeight2 === void 0 ? void 0 : _me$getScrollHeight2.call(me)) ?? null;
|
|
508
|
+
this.cachedLineHeightDiff = ((_me$getOption = me.getOption) === null || _me$getOption === void 0 ? void 0 : _me$getOption.call(me, monaco_shim_exports.editor.EditorOption.lineHeight)) ?? null;
|
|
509
|
+
this.cachedComputedHeightDiff = this.computedHeight();
|
|
510
|
+
const oEditor = this.diffEditorView.getOriginalEditor();
|
|
511
|
+
const mEditor = this.diffEditorView.getModifiedEditor();
|
|
512
|
+
(_oEditor$onDidContent = oEditor.onDidContentSizeChange) === null || _oEditor$onDidContent === void 0 || _oEditor$onDidContent.call(oEditor, () => {
|
|
513
|
+
this._hasScrollBar = false;
|
|
514
|
+
this.rafScheduler.schedule("content-size-change-diff", () => {
|
|
515
|
+
try {
|
|
516
|
+
var _oEditor$getScrollHei, _oEditor$getOption, _this$diffHeightManag, _this$diffHeightManag2;
|
|
517
|
+
this.cachedScrollHeightDiff = ((_oEditor$getScrollHei = oEditor.getScrollHeight) === null || _oEditor$getScrollHei === void 0 ? void 0 : _oEditor$getScrollHei.call(oEditor)) ?? this.cachedScrollHeightDiff;
|
|
518
|
+
this.cachedLineHeightDiff = ((_oEditor$getOption = oEditor.getOption) === null || _oEditor$getOption === void 0 ? void 0 : _oEditor$getOption.call(oEditor, monaco_shim_exports.editor.EditorOption.lineHeight)) ?? this.cachedLineHeightDiff;
|
|
519
|
+
this.cachedComputedHeightDiff = this.computedHeight();
|
|
520
|
+
if ((_this$diffHeightManag = this.diffHeightManager) === null || _this$diffHeightManag === void 0 ? void 0 : _this$diffHeightManag.isSuppressed()) return;
|
|
521
|
+
(_this$diffHeightManag2 = this.diffHeightManager) === null || _this$diffHeightManag2 === void 0 || _this$diffHeightManag2.update();
|
|
522
|
+
} catch {}
|
|
523
|
+
});
|
|
524
|
+
});
|
|
525
|
+
(_mEditor$onDidContent = mEditor.onDidContentSizeChange) === null || _mEditor$onDidContent === void 0 || _mEditor$onDidContent.call(mEditor, () => {
|
|
526
|
+
this._hasScrollBar = false;
|
|
527
|
+
this.rafScheduler.schedule("content-size-change-diff", () => {
|
|
528
|
+
try {
|
|
529
|
+
var _mEditor$getScrollHei, _mEditor$getOption, _this$diffHeightManag3, _this$diffHeightManag4;
|
|
530
|
+
this.cachedScrollHeightDiff = ((_mEditor$getScrollHei = mEditor.getScrollHeight) === null || _mEditor$getScrollHei === void 0 ? void 0 : _mEditor$getScrollHei.call(mEditor)) ?? this.cachedScrollHeightDiff;
|
|
531
|
+
this.cachedLineHeightDiff = ((_mEditor$getOption = mEditor.getOption) === null || _mEditor$getOption === void 0 ? void 0 : _mEditor$getOption.call(mEditor, monaco_shim_exports.editor.EditorOption.lineHeight)) ?? this.cachedLineHeightDiff;
|
|
532
|
+
this.cachedComputedHeightDiff = this.computedHeight();
|
|
533
|
+
if ((_this$diffHeightManag3 = this.diffHeightManager) === null || _this$diffHeightManag3 === void 0 ? void 0 : _this$diffHeightManag3.isSuppressed()) return;
|
|
534
|
+
(_this$diffHeightManag4 = this.diffHeightManager) === null || _this$diffHeightManag4 === void 0 || _this$diffHeightManag4.update();
|
|
535
|
+
} catch {}
|
|
536
|
+
});
|
|
537
|
+
});
|
|
538
|
+
mEditor.onDidChangeModelContent(() => {
|
|
539
|
+
this.lastKnownModifiedDirty = true;
|
|
540
|
+
this.rafScheduler.schedule("sync-last-known-modified", () => this.syncLastKnownModified());
|
|
541
|
+
});
|
|
542
|
+
return this.diffEditorView;
|
|
543
|
+
}
|
|
544
|
+
updateDiff(originalCode, modifiedCode, codeLanguage) {
|
|
545
|
+
if (!this.diffEditorView || !this.originalModel || !this.modifiedModel) return;
|
|
546
|
+
const plang = codeLanguage ? processedLanguage(codeLanguage) : void 0;
|
|
547
|
+
if (plang && (this.originalModel.getLanguageId() !== plang || this.modifiedModel.getLanguageId() !== plang)) {
|
|
548
|
+
this.pendingDiffUpdate = {
|
|
549
|
+
original: originalCode,
|
|
550
|
+
modified: modifiedCode,
|
|
551
|
+
lang: codeLanguage
|
|
552
|
+
};
|
|
553
|
+
this.rafScheduler.schedule("diff", () => this.flushPendingDiffUpdate());
|
|
554
|
+
return;
|
|
555
|
+
}
|
|
556
|
+
if (this.lastKnownOriginalCode == null) this.lastKnownOriginalCode = this.originalModel.getValue();
|
|
557
|
+
if (this.lastKnownModifiedCode == null) this.lastKnownModifiedCode = this.modifiedModel.getValue();
|
|
558
|
+
const prevO = this.lastKnownOriginalCode;
|
|
559
|
+
const prevM = this.lastKnownModifiedCode;
|
|
560
|
+
let didImmediate = false;
|
|
561
|
+
if (originalCode !== prevO && originalCode.startsWith(prevO)) {
|
|
562
|
+
this.appendToModel(this.originalModel, originalCode.slice(prevO.length));
|
|
563
|
+
this.lastKnownOriginalCode = originalCode;
|
|
564
|
+
didImmediate = true;
|
|
565
|
+
}
|
|
566
|
+
if (modifiedCode !== prevM && modifiedCode.startsWith(prevM)) {
|
|
567
|
+
const prevLine = this.modifiedModel.getLineCount();
|
|
568
|
+
this.appendToModel(this.modifiedModel, modifiedCode.slice(prevM.length));
|
|
569
|
+
this.lastKnownModifiedCode = modifiedCode;
|
|
570
|
+
didImmediate = true;
|
|
571
|
+
this.maybeScrollDiffToBottom(this.modifiedModel.getLineCount(), prevLine);
|
|
572
|
+
}
|
|
573
|
+
if (originalCode !== this.lastKnownOriginalCode || modifiedCode !== this.lastKnownModifiedCode) {
|
|
574
|
+
this.pendingDiffUpdate = {
|
|
575
|
+
original: originalCode,
|
|
576
|
+
modified: modifiedCode
|
|
577
|
+
};
|
|
578
|
+
this.rafScheduler.schedule("diff", () => this.flushPendingDiffUpdate());
|
|
579
|
+
} else if (didImmediate) {}
|
|
580
|
+
}
|
|
581
|
+
updateOriginal(newCode, codeLanguage) {
|
|
582
|
+
if (!this.diffEditorView || !this.originalModel) return;
|
|
583
|
+
if (codeLanguage) {
|
|
584
|
+
const lang = processedLanguage(codeLanguage);
|
|
585
|
+
if (lang && this.originalModel.getLanguageId() !== lang) monaco_shim_exports.editor.setModelLanguage(this.originalModel, lang);
|
|
586
|
+
}
|
|
587
|
+
const prev = this.lastKnownOriginalCode ?? this.originalModel.getValue();
|
|
588
|
+
if (prev === newCode) return;
|
|
589
|
+
if (newCode.startsWith(prev) && prev.length < newCode.length) this.appendToModel(this.originalModel, newCode.slice(prev.length));
|
|
590
|
+
else this.applyMinimalEditToModel(this.originalModel, prev, newCode);
|
|
591
|
+
this.lastKnownOriginalCode = newCode;
|
|
592
|
+
}
|
|
593
|
+
updateModified(newCode, codeLanguage) {
|
|
594
|
+
if (!this.diffEditorView || !this.modifiedModel) return;
|
|
595
|
+
if (codeLanguage) {
|
|
596
|
+
const lang = processedLanguage(codeLanguage);
|
|
597
|
+
if (lang && this.modifiedModel.getLanguageId() !== lang) monaco_shim_exports.editor.setModelLanguage(this.modifiedModel, lang);
|
|
598
|
+
}
|
|
599
|
+
const prev = this.lastKnownModifiedCode ?? this.modifiedModel.getValue();
|
|
600
|
+
if (prev === newCode) return;
|
|
601
|
+
if (newCode.startsWith(prev) && prev.length < newCode.length) {
|
|
602
|
+
const prevLine = this.modifiedModel.getLineCount();
|
|
603
|
+
this.appendToModel(this.modifiedModel, newCode.slice(prev.length));
|
|
604
|
+
this.maybeScrollDiffToBottom(this.modifiedModel.getLineCount(), prevLine);
|
|
605
|
+
} else this.applyMinimalEditToModel(this.modifiedModel, prev, newCode);
|
|
606
|
+
this.lastKnownModifiedCode = newCode;
|
|
607
|
+
}
|
|
608
|
+
appendOriginal(appendText, codeLanguage) {
|
|
609
|
+
if (!this.diffEditorView || !this.originalModel || !appendText) return;
|
|
610
|
+
if (codeLanguage) {
|
|
611
|
+
const lang = processedLanguage(codeLanguage);
|
|
612
|
+
if (lang && this.originalModel.getLanguageId() !== lang) monaco_shim_exports.editor.setModelLanguage(this.originalModel, lang);
|
|
613
|
+
}
|
|
614
|
+
this.appendToModel(this.originalModel, appendText);
|
|
615
|
+
try {
|
|
616
|
+
this.lastKnownOriginalCode = this.originalModel.getValue();
|
|
617
|
+
} catch {}
|
|
618
|
+
}
|
|
619
|
+
appendModified(appendText, codeLanguage) {
|
|
620
|
+
if (!this.diffEditorView || !this.modifiedModel || !appendText) return;
|
|
621
|
+
if (codeLanguage) {
|
|
622
|
+
const lang = processedLanguage(codeLanguage);
|
|
623
|
+
if (lang && this.modifiedModel.getLanguageId() !== lang) monaco_shim_exports.editor.setModelLanguage(this.modifiedModel, lang);
|
|
624
|
+
}
|
|
625
|
+
this.appendBufferDiff.push(appendText);
|
|
626
|
+
if (!this.appendBufferDiffScheduled) {
|
|
627
|
+
this.appendBufferDiffScheduled = true;
|
|
628
|
+
this.rafScheduler.schedule("appendDiff", () => this.flushAppendBufferDiff());
|
|
629
|
+
}
|
|
630
|
+
}
|
|
631
|
+
setLanguage(language, languages$1) {
|
|
632
|
+
if (!languages$1.includes(language)) {
|
|
633
|
+
console.warn(`Language "${language}" is not registered. Available languages: ${languages$1.join(", ")}`);
|
|
634
|
+
return;
|
|
635
|
+
}
|
|
636
|
+
if (this.originalModel && this.originalModel.getLanguageId() !== language) monaco_shim_exports.editor.setModelLanguage(this.originalModel, language);
|
|
637
|
+
if (this.modifiedModel && this.modifiedModel.getLanguageId() !== language) monaco_shim_exports.editor.setModelLanguage(this.modifiedModel, language);
|
|
638
|
+
}
|
|
639
|
+
getDiffEditorView() {
|
|
640
|
+
return this.diffEditorView;
|
|
641
|
+
}
|
|
642
|
+
getDiffModels() {
|
|
643
|
+
return {
|
|
644
|
+
original: this.originalModel,
|
|
645
|
+
modified: this.modifiedModel
|
|
646
|
+
};
|
|
647
|
+
}
|
|
648
|
+
cleanup() {
|
|
649
|
+
this.rafScheduler.cancel("diff");
|
|
650
|
+
this.pendingDiffUpdate = null;
|
|
651
|
+
this.rafScheduler.cancel("appendDiff");
|
|
652
|
+
this.appendBufferDiffScheduled = false;
|
|
653
|
+
this.appendBufferDiff.length = 0;
|
|
654
|
+
this.rafScheduler.cancel("content-size-change-diff");
|
|
655
|
+
this.rafScheduler.cancel("sync-last-known-modified");
|
|
656
|
+
if (this.diffScrollWatcher) {
|
|
657
|
+
this.diffScrollWatcher.dispose();
|
|
658
|
+
this.diffScrollWatcher = null;
|
|
659
|
+
}
|
|
660
|
+
if (this.diffHeightManager) {
|
|
661
|
+
this.diffHeightManager.dispose();
|
|
662
|
+
this.diffHeightManager = null;
|
|
663
|
+
}
|
|
664
|
+
if (this.diffEditorView) {
|
|
665
|
+
this.diffEditorView.dispose();
|
|
666
|
+
this.diffEditorView = null;
|
|
667
|
+
}
|
|
668
|
+
if (this.originalModel) {
|
|
669
|
+
this.originalModel.dispose();
|
|
670
|
+
this.originalModel = null;
|
|
671
|
+
}
|
|
672
|
+
if (this.modifiedModel) {
|
|
673
|
+
this.modifiedModel.dispose();
|
|
674
|
+
this.modifiedModel = null;
|
|
675
|
+
}
|
|
676
|
+
this.lastKnownOriginalCode = null;
|
|
677
|
+
this.lastKnownModifiedCode = null;
|
|
678
|
+
if (this.lastContainer) {
|
|
679
|
+
this.lastContainer.innerHTML = "";
|
|
680
|
+
this.lastContainer = null;
|
|
681
|
+
}
|
|
682
|
+
if (this.revealDebounceIdDiff != null) {
|
|
683
|
+
clearTimeout(this.revealDebounceIdDiff);
|
|
684
|
+
this.revealDebounceIdDiff = null;
|
|
685
|
+
}
|
|
686
|
+
this.lastRevealLineDiff = null;
|
|
687
|
+
}
|
|
688
|
+
safeClean() {
|
|
689
|
+
this.rafScheduler.cancel("diff");
|
|
690
|
+
this.pendingDiffUpdate = null;
|
|
691
|
+
if (this.diffScrollWatcher) {
|
|
692
|
+
this.diffScrollWatcher.dispose();
|
|
693
|
+
this.diffScrollWatcher = null;
|
|
694
|
+
}
|
|
695
|
+
this._hasScrollBar = false;
|
|
696
|
+
this.shouldAutoScrollDiff = !!(this.autoScrollInitial && this.diffAutoScroll);
|
|
697
|
+
this.lastScrollTopDiff = 0;
|
|
698
|
+
if (this.diffHeightManager) {
|
|
699
|
+
this.diffHeightManager.dispose();
|
|
700
|
+
this.diffHeightManager = null;
|
|
701
|
+
}
|
|
702
|
+
if (this.revealDebounceIdDiff != null) {
|
|
703
|
+
clearTimeout(this.revealDebounceIdDiff);
|
|
704
|
+
this.revealDebounceIdDiff = null;
|
|
705
|
+
}
|
|
706
|
+
this.lastRevealLineDiff = null;
|
|
707
|
+
this.rafScheduler.cancel("content-size-change-diff");
|
|
708
|
+
this.rafScheduler.cancel("sync-last-known-modified");
|
|
709
|
+
}
|
|
710
|
+
syncLastKnownModified() {
|
|
711
|
+
if (!this.diffEditorView || !this.lastKnownModifiedDirty) return;
|
|
712
|
+
try {
|
|
713
|
+
const me = this.diffEditorView.getModifiedEditor();
|
|
714
|
+
const model = me.getModel();
|
|
715
|
+
if (model) {
|
|
716
|
+
this.lastKnownModifiedCode = model.getValue();
|
|
717
|
+
this.lastKnownModifiedLineCount = model.getLineCount();
|
|
718
|
+
}
|
|
719
|
+
} catch {} finally {
|
|
720
|
+
this.lastKnownModifiedDirty = false;
|
|
721
|
+
}
|
|
722
|
+
}
|
|
723
|
+
flushPendingDiffUpdate() {
|
|
724
|
+
if (!this.pendingDiffUpdate || !this.diffEditorView) return;
|
|
725
|
+
const o = this.originalModel;
|
|
726
|
+
const m = this.modifiedModel;
|
|
727
|
+
if (!o || !m) {
|
|
728
|
+
this.pendingDiffUpdate = null;
|
|
729
|
+
return;
|
|
730
|
+
}
|
|
731
|
+
const { original, modified, lang } = this.pendingDiffUpdate;
|
|
732
|
+
this.pendingDiffUpdate = null;
|
|
733
|
+
if (lang) {
|
|
734
|
+
const plang = processedLanguage(lang);
|
|
735
|
+
if (plang) {
|
|
736
|
+
if (o.getLanguageId() !== plang) {
|
|
737
|
+
monaco_shim_exports.editor.setModelLanguage(o, plang);
|
|
738
|
+
monaco_shim_exports.editor.setModelLanguage(m, plang);
|
|
739
|
+
}
|
|
740
|
+
}
|
|
741
|
+
}
|
|
742
|
+
if (this.lastKnownOriginalCode == null) this.lastKnownOriginalCode = o.getValue();
|
|
743
|
+
if (this.lastKnownModifiedCode == null) this.lastKnownModifiedCode = m.getValue();
|
|
744
|
+
const prevO = this.lastKnownOriginalCode;
|
|
745
|
+
if (prevO !== original) {
|
|
746
|
+
if (original.startsWith(prevO) && prevO.length < original.length) this.appendToModel(o, original.slice(prevO.length));
|
|
747
|
+
else this.applyMinimalEditToModel(o, prevO, original);
|
|
748
|
+
this.lastKnownOriginalCode = original;
|
|
749
|
+
}
|
|
750
|
+
const prevM = this.lastKnownModifiedCode;
|
|
751
|
+
const prevMLineCount = m.getLineCount();
|
|
752
|
+
if (prevM !== modified) {
|
|
753
|
+
if (modified.startsWith(prevM) && prevM.length < modified.length) this.appendToModel(m, modified.slice(prevM.length));
|
|
754
|
+
else this.applyMinimalEditToModel(m, prevM, modified);
|
|
755
|
+
this.lastKnownModifiedCode = modified;
|
|
756
|
+
const newMLineCount = m.getLineCount();
|
|
757
|
+
if (newMLineCount !== prevMLineCount) this.maybeScrollDiffToBottom(newMLineCount, prevMLineCount);
|
|
758
|
+
}
|
|
759
|
+
}
|
|
760
|
+
flushAppendBufferDiff() {
|
|
761
|
+
if (!this.diffEditorView) return;
|
|
762
|
+
if (this.appendBufferDiff.length === 0) return;
|
|
763
|
+
this.appendBufferDiffScheduled = false;
|
|
764
|
+
const me = this.diffEditorView.getModifiedEditor();
|
|
765
|
+
const model = me.getModel();
|
|
766
|
+
if (!model) {
|
|
767
|
+
this.appendBufferDiff.length = 0;
|
|
768
|
+
return;
|
|
769
|
+
}
|
|
770
|
+
const text = this.appendBufferDiff.join("");
|
|
771
|
+
this.appendBufferDiff.length = 0;
|
|
772
|
+
try {
|
|
773
|
+
const prevLine = model.getLineCount();
|
|
774
|
+
const lastColumn = model.getLineMaxColumn(prevLine);
|
|
775
|
+
const range = new monaco_shim_exports.Range(prevLine, lastColumn, prevLine, lastColumn);
|
|
776
|
+
model.applyEdits([{
|
|
777
|
+
range,
|
|
778
|
+
text,
|
|
779
|
+
forceMoveMarkers: true
|
|
780
|
+
}]);
|
|
781
|
+
try {
|
|
782
|
+
this.lastKnownModifiedCode = model.getValue();
|
|
783
|
+
} catch {}
|
|
784
|
+
const newLine = model.getLineCount();
|
|
785
|
+
this.maybeScrollDiffToBottom(newLine, prevLine);
|
|
786
|
+
this.lastKnownModifiedLineCount = newLine;
|
|
787
|
+
} catch {}
|
|
788
|
+
}
|
|
789
|
+
applyMinimalEditToModel(model, prev, next) {
|
|
790
|
+
try {
|
|
791
|
+
const maxChars = minimalEditMaxChars;
|
|
792
|
+
const ratio = minimalEditMaxChangeRatio;
|
|
793
|
+
const maxLen = Math.max(prev.length, next.length);
|
|
794
|
+
const changeRatio = maxLen > 0 ? Math.abs(next.length - prev.length) / maxLen : 0;
|
|
795
|
+
if (prev.length + next.length > maxChars || changeRatio > ratio) {
|
|
796
|
+
model.setValue(next);
|
|
797
|
+
try {
|
|
798
|
+
if (model === this.modifiedModel) this.lastKnownModifiedLineCount = model.getLineCount();
|
|
799
|
+
} catch {}
|
|
800
|
+
return;
|
|
801
|
+
}
|
|
802
|
+
} catch {}
|
|
803
|
+
const res = computeMinimalEdit(prev, next);
|
|
804
|
+
if (!res) return;
|
|
805
|
+
const { start, endPrevIncl, replaceText } = res;
|
|
806
|
+
const rangeStart = model.getPositionAt(start);
|
|
807
|
+
const rangeEnd = model.getPositionAt(endPrevIncl + 1);
|
|
808
|
+
const range = new monaco_shim_exports.Range(rangeStart.lineNumber, rangeStart.column, rangeEnd.lineNumber, rangeEnd.column);
|
|
809
|
+
model.applyEdits([{
|
|
810
|
+
range,
|
|
811
|
+
text: replaceText,
|
|
812
|
+
forceMoveMarkers: true
|
|
813
|
+
}]);
|
|
814
|
+
try {
|
|
815
|
+
if (model === this.modifiedModel) this.lastKnownModifiedLineCount = model.getLineCount();
|
|
816
|
+
} catch {}
|
|
817
|
+
}
|
|
818
|
+
appendToModel(model, appendText) {
|
|
819
|
+
if (!appendText) return;
|
|
820
|
+
const lastLine = model.getLineCount();
|
|
821
|
+
const lastColumn = model.getLineMaxColumn(lastLine);
|
|
822
|
+
const range = new monaco_shim_exports.Range(lastLine, lastColumn, lastLine, lastColumn);
|
|
823
|
+
model.applyEdits([{
|
|
824
|
+
range,
|
|
825
|
+
text: appendText,
|
|
826
|
+
forceMoveMarkers: true
|
|
827
|
+
}]);
|
|
828
|
+
try {
|
|
829
|
+
if (model === this.modifiedModel) this.lastKnownModifiedLineCount = model.getLineCount();
|
|
830
|
+
} catch {}
|
|
831
|
+
}
|
|
832
|
+
};
|
|
833
|
+
|
|
834
|
+
//#endregion
|
|
835
|
+
//#region src/core/EditorManager.ts
|
|
836
|
+
var EditorManager = class {
|
|
837
|
+
editorView = null;
|
|
838
|
+
lastContainer = null;
|
|
839
|
+
lastKnownCode = null;
|
|
840
|
+
pendingUpdate = null;
|
|
841
|
+
_hasScrollBar = false;
|
|
842
|
+
shouldAutoScroll = true;
|
|
843
|
+
scrollWatcher = null;
|
|
844
|
+
lastScrollTop = 0;
|
|
845
|
+
cachedScrollHeight = null;
|
|
846
|
+
cachedLineHeight = null;
|
|
847
|
+
cachedComputedHeight = null;
|
|
848
|
+
cachedLineCount = null;
|
|
849
|
+
lastKnownCodeDirty = false;
|
|
850
|
+
measureViewport() {
|
|
851
|
+
var _this$editorView$getL, _this$editorView, _this$editorView$getS, _this$editorView2, _this$editorView$getS2, _this$editorView3;
|
|
852
|
+
if (!this.editorView) return null;
|
|
853
|
+
const li = ((_this$editorView$getL = (_this$editorView = this.editorView).getLayoutInfo) === null || _this$editorView$getL === void 0 ? void 0 : _this$editorView$getL.call(_this$editorView)) ?? null;
|
|
854
|
+
const lineHeight = this.cachedLineHeight ?? this.editorView.getOption(monaco_shim_exports.editor.EditorOption.lineHeight);
|
|
855
|
+
const scrollTop = ((_this$editorView$getS = (_this$editorView2 = this.editorView).getScrollTop) === null || _this$editorView$getS === void 0 ? void 0 : _this$editorView$getS.call(_this$editorView2)) ?? this.lastScrollTop ?? 0;
|
|
856
|
+
const scrollHeight = ((_this$editorView$getS2 = (_this$editorView3 = this.editorView).getScrollHeight) === null || _this$editorView$getS2 === void 0 ? void 0 : _this$editorView$getS2.call(_this$editorView3)) ?? this.cachedScrollHeight ?? (li === null || li === void 0 ? void 0 : li.height) ?? 0;
|
|
857
|
+
const computedHeight = this.cachedComputedHeight ?? this.computedHeight(this.editorView);
|
|
858
|
+
this.cachedLineHeight = lineHeight;
|
|
859
|
+
this.cachedScrollHeight = scrollHeight;
|
|
860
|
+
this.cachedComputedHeight = computedHeight;
|
|
861
|
+
this.lastScrollTop = scrollTop;
|
|
862
|
+
return {
|
|
863
|
+
li,
|
|
864
|
+
lineHeight,
|
|
865
|
+
scrollTop,
|
|
866
|
+
scrollHeight,
|
|
867
|
+
computedHeight
|
|
868
|
+
};
|
|
869
|
+
}
|
|
870
|
+
appendBuffer = [];
|
|
871
|
+
appendBufferScheduled = false;
|
|
872
|
+
rafScheduler = createRafScheduler();
|
|
873
|
+
editorHeightManager = null;
|
|
874
|
+
revealDebounceId = null;
|
|
875
|
+
revealDebounceMs = defaultRevealDebounceMs;
|
|
876
|
+
revealIdleTimerId = null;
|
|
877
|
+
revealStrategyOption;
|
|
878
|
+
revealBatchOnIdleMsOption;
|
|
879
|
+
constructor(options, maxHeightValue, maxHeightCSS, autoScrollOnUpdate, autoScrollInitial, autoScrollThresholdPx, autoScrollThresholdLines, revealDebounceMsOption) {
|
|
880
|
+
this.options = options;
|
|
881
|
+
this.maxHeightValue = maxHeightValue;
|
|
882
|
+
this.maxHeightCSS = maxHeightCSS;
|
|
883
|
+
this.autoScrollOnUpdate = autoScrollOnUpdate;
|
|
884
|
+
this.autoScrollInitial = autoScrollInitial;
|
|
885
|
+
this.autoScrollThresholdPx = autoScrollThresholdPx;
|
|
886
|
+
this.autoScrollThresholdLines = autoScrollThresholdLines;
|
|
887
|
+
this.revealDebounceMsOption = revealDebounceMsOption;
|
|
888
|
+
}
|
|
889
|
+
hasVerticalScrollbar() {
|
|
890
|
+
if (!this.editorView) return false;
|
|
891
|
+
if (this._hasScrollBar) return true;
|
|
892
|
+
const m = this.measureViewport();
|
|
893
|
+
if (!m) return false;
|
|
894
|
+
return this._hasScrollBar = m.scrollHeight > m.computedHeight + padding / 2;
|
|
895
|
+
}
|
|
896
|
+
userIsNearBottom() {
|
|
897
|
+
if (!this.editorView) return true;
|
|
898
|
+
const m = this.measureViewport();
|
|
899
|
+
if (!m || !m.li) return true;
|
|
900
|
+
const lineThreshold = (this.autoScrollThresholdLines ?? 0) * m.lineHeight;
|
|
901
|
+
const threshold = Math.max(lineThreshold || 0, this.autoScrollThresholdPx || 0);
|
|
902
|
+
const distance = m.scrollHeight - (m.scrollTop + m.li.height);
|
|
903
|
+
return distance <= threshold;
|
|
904
|
+
}
|
|
905
|
+
computedHeight(editorView) {
|
|
906
|
+
var _editorView$getModel;
|
|
907
|
+
const lineCount = this.cachedLineCount ?? ((_editorView$getModel = editorView.getModel()) === null || _editorView$getModel === void 0 ? void 0 : _editorView$getModel.getLineCount()) ?? 1;
|
|
908
|
+
const lineHeight = editorView.getOption(monaco_shim_exports.editor.EditorOption.lineHeight);
|
|
909
|
+
const height = Math.min(lineCount * lineHeight + padding, this.maxHeightValue);
|
|
910
|
+
return height;
|
|
911
|
+
}
|
|
912
|
+
maybeScrollToBottom(targetLine) {
|
|
913
|
+
this.rafScheduler.schedule("maybe-scroll", () => {
|
|
914
|
+
if (!(this.autoScrollOnUpdate && this.shouldAutoScroll && this.hasVerticalScrollbar())) return;
|
|
915
|
+
const model = this.editorView.getModel();
|
|
916
|
+
const line = targetLine ?? (model === null || model === void 0 ? void 0 : model.getLineCount()) ?? 1;
|
|
917
|
+
const batchMs = this.revealBatchOnIdleMsOption ?? this.options.revealBatchOnIdleMs ?? defaultRevealBatchOnIdleMs;
|
|
918
|
+
if (typeof batchMs === "number" && batchMs > 0) {
|
|
919
|
+
if (this.revealIdleTimerId != null) clearTimeout(this.revealIdleTimerId);
|
|
920
|
+
this.revealIdleTimerId = setTimeout(() => {
|
|
921
|
+
this.revealIdleTimerId = null;
|
|
922
|
+
this.performReveal(line);
|
|
923
|
+
}, batchMs);
|
|
924
|
+
return;
|
|
925
|
+
}
|
|
926
|
+
if (this.revealDebounceId != null) {
|
|
927
|
+
clearTimeout(this.revealDebounceId);
|
|
928
|
+
this.revealDebounceId = null;
|
|
929
|
+
}
|
|
930
|
+
const ms = typeof this.revealDebounceMs === "number" && this.revealDebounceMs > 0 ? this.revealDebounceMs : typeof this.revealDebounceMsOption === "number" && this.revealDebounceMsOption > 0 ? this.revealDebounceMsOption : this.revealDebounceMs;
|
|
931
|
+
this.revealDebounceId = setTimeout(() => {
|
|
932
|
+
this.revealDebounceId = null;
|
|
933
|
+
this.performReveal(line);
|
|
934
|
+
}, ms);
|
|
935
|
+
});
|
|
936
|
+
}
|
|
937
|
+
performReveal(line) {
|
|
938
|
+
this.rafScheduler.schedule("reveal", () => {
|
|
939
|
+
var _editor;
|
|
940
|
+
const strategy = this.revealStrategyOption ?? this.options.revealStrategy ?? "centerIfOutside";
|
|
941
|
+
const ScrollType = monaco_shim_exports.ScrollType || ((_editor = monaco_shim_exports.editor) === null || _editor === void 0 ? void 0 : _editor.ScrollType);
|
|
942
|
+
const smooth = ScrollType && typeof ScrollType.Smooth !== "undefined" ? ScrollType.Smooth : void 0;
|
|
943
|
+
try {
|
|
944
|
+
if (strategy === "bottom") if (typeof smooth !== "undefined") this.editorView.revealLine(line, smooth);
|
|
945
|
+
else this.editorView.revealLine(line);
|
|
946
|
+
else if (strategy === "center") if (typeof smooth !== "undefined") this.editorView.revealLineInCenter(line, smooth);
|
|
947
|
+
else this.editorView.revealLineInCenter(line);
|
|
948
|
+
else if (typeof smooth !== "undefined") this.editorView.revealLineInCenterIfOutsideViewport(line, smooth);
|
|
949
|
+
else this.editorView.revealLineInCenterIfOutsideViewport(line);
|
|
950
|
+
} catch {
|
|
951
|
+
try {
|
|
952
|
+
this.editorView.revealLine(line);
|
|
953
|
+
} catch {}
|
|
954
|
+
}
|
|
955
|
+
});
|
|
956
|
+
}
|
|
957
|
+
async createEditor(container, code, language, currentTheme) {
|
|
958
|
+
var _this$editorView$getS3, _this$editorView4, _this$editorView$getO, _this$editorView5, _this$editorView$getM, _this$editorView$onDi, _this$editorView6;
|
|
959
|
+
this.cleanup();
|
|
960
|
+
this.lastContainer = container;
|
|
961
|
+
container.style.overflow = "auto";
|
|
962
|
+
container.style.maxHeight = this.maxHeightCSS;
|
|
963
|
+
this.editorView = monaco_shim_exports.editor.create(container, {
|
|
964
|
+
value: code,
|
|
965
|
+
language: processedLanguage(language) || language,
|
|
966
|
+
theme: currentTheme,
|
|
967
|
+
scrollBeyondLastLine: false,
|
|
968
|
+
minimap: { enabled: false },
|
|
969
|
+
automaticLayout: true,
|
|
970
|
+
readOnly: this.options.readOnly ?? true,
|
|
971
|
+
contextmenu: false,
|
|
972
|
+
scrollbar: {
|
|
973
|
+
...defaultScrollbar,
|
|
974
|
+
...this.options.scrollbar || {}
|
|
975
|
+
},
|
|
976
|
+
...this.options
|
|
977
|
+
});
|
|
978
|
+
monaco_shim_exports.editor.setTheme(currentTheme);
|
|
979
|
+
this.lastKnownCode = this.editorView.getValue();
|
|
980
|
+
if (this.editorHeightManager) {
|
|
981
|
+
try {
|
|
982
|
+
this.editorHeightManager.dispose();
|
|
983
|
+
} catch {}
|
|
984
|
+
this.editorHeightManager = null;
|
|
985
|
+
}
|
|
986
|
+
if (this.revealDebounceId != null) {
|
|
987
|
+
clearTimeout(this.revealDebounceId);
|
|
988
|
+
this.revealDebounceId = null;
|
|
989
|
+
}
|
|
990
|
+
if (this.revealIdleTimerId != null) clearTimeout(this.revealIdleTimerId);
|
|
991
|
+
this.revealIdleTimerId = null;
|
|
992
|
+
this.editorHeightManager = createHeightManager(container, () => this.computedHeight(this.editorView));
|
|
993
|
+
this.editorHeightManager.update();
|
|
994
|
+
this.cachedScrollHeight = ((_this$editorView$getS3 = (_this$editorView4 = this.editorView).getScrollHeight) === null || _this$editorView$getS3 === void 0 ? void 0 : _this$editorView$getS3.call(_this$editorView4)) ?? null;
|
|
995
|
+
this.cachedLineHeight = ((_this$editorView$getO = (_this$editorView5 = this.editorView).getOption) === null || _this$editorView$getO === void 0 ? void 0 : _this$editorView$getO.call(_this$editorView5, monaco_shim_exports.editor.EditorOption.lineHeight)) ?? null;
|
|
996
|
+
this.cachedComputedHeight = this.computedHeight(this.editorView);
|
|
997
|
+
this.cachedLineCount = ((_this$editorView$getM = this.editorView.getModel()) === null || _this$editorView$getM === void 0 ? void 0 : _this$editorView$getM.getLineCount()) ?? null;
|
|
998
|
+
(_this$editorView$onDi = (_this$editorView6 = this.editorView).onDidContentSizeChange) === null || _this$editorView$onDi === void 0 || _this$editorView$onDi.call(_this$editorView6, () => {
|
|
999
|
+
this._hasScrollBar = false;
|
|
1000
|
+
this.rafScheduler.schedule("content-size-change", () => {
|
|
1001
|
+
try {
|
|
1002
|
+
var _this$editorView7, _this$editorHeightMan, _this$editorHeightMan2;
|
|
1003
|
+
this.measureViewport();
|
|
1004
|
+
this.cachedLineCount = ((_this$editorView7 = this.editorView) === null || _this$editorView7 === void 0 || (_this$editorView7 = _this$editorView7.getModel()) === null || _this$editorView7 === void 0 ? void 0 : _this$editorView7.getLineCount()) ?? this.cachedLineCount;
|
|
1005
|
+
if ((_this$editorHeightMan = this.editorHeightManager) === null || _this$editorHeightMan === void 0 ? void 0 : _this$editorHeightMan.isSuppressed()) return;
|
|
1006
|
+
(_this$editorHeightMan2 = this.editorHeightManager) === null || _this$editorHeightMan2 === void 0 || _this$editorHeightMan2.update();
|
|
1007
|
+
} catch {}
|
|
1008
|
+
});
|
|
1009
|
+
});
|
|
1010
|
+
this.editorView.onDidChangeModelContent(() => {
|
|
1011
|
+
this.lastKnownCodeDirty = true;
|
|
1012
|
+
this.rafScheduler.schedule("sync-last-known", () => this.syncLastKnownCode());
|
|
1013
|
+
});
|
|
1014
|
+
this.shouldAutoScroll = !!this.autoScrollInitial;
|
|
1015
|
+
if (this.scrollWatcher) {
|
|
1016
|
+
this.scrollWatcher.dispose();
|
|
1017
|
+
this.scrollWatcher = null;
|
|
1018
|
+
}
|
|
1019
|
+
this.scrollWatcher = createScrollWatcherForEditor(this.editorView, {
|
|
1020
|
+
onPause: () => {
|
|
1021
|
+
this.shouldAutoScroll = false;
|
|
1022
|
+
},
|
|
1023
|
+
onMaybeResume: () => {
|
|
1024
|
+
this.rafScheduler.schedule("maybe-resume", () => {
|
|
1025
|
+
this.shouldAutoScroll = this.userIsNearBottom();
|
|
1026
|
+
});
|
|
1027
|
+
},
|
|
1028
|
+
getLast: () => this.lastScrollTop,
|
|
1029
|
+
setLast: (v) => {
|
|
1030
|
+
this.lastScrollTop = v;
|
|
1031
|
+
}
|
|
1032
|
+
});
|
|
1033
|
+
this.maybeScrollToBottom();
|
|
1034
|
+
return this.editorView;
|
|
1035
|
+
}
|
|
1036
|
+
syncLastKnownCode() {
|
|
1037
|
+
if (!this.editorView || !this.lastKnownCodeDirty) return;
|
|
1038
|
+
try {
|
|
1039
|
+
const model = this.editorView.getModel();
|
|
1040
|
+
if (model) {
|
|
1041
|
+
this.lastKnownCode = model.getValue();
|
|
1042
|
+
this.cachedLineCount = model.getLineCount() ?? this.cachedLineCount;
|
|
1043
|
+
}
|
|
1044
|
+
} catch {} finally {
|
|
1045
|
+
this.lastKnownCodeDirty = false;
|
|
1046
|
+
}
|
|
1047
|
+
}
|
|
1048
|
+
updateCode(newCode, codeLanguage) {
|
|
1049
|
+
this.pendingUpdate = {
|
|
1050
|
+
code: newCode,
|
|
1051
|
+
lang: codeLanguage
|
|
1052
|
+
};
|
|
1053
|
+
this.rafScheduler.schedule("update", () => this.flushPendingUpdate());
|
|
1054
|
+
}
|
|
1055
|
+
flushPendingUpdate() {
|
|
1056
|
+
if (!this.pendingUpdate || !this.editorView) return;
|
|
1057
|
+
const model = this.editorView.getModel();
|
|
1058
|
+
if (!model) return;
|
|
1059
|
+
const { code: newCode, lang: codeLanguage } = this.pendingUpdate;
|
|
1060
|
+
this.pendingUpdate = null;
|
|
1061
|
+
const processedCodeLanguage = processedLanguage(codeLanguage);
|
|
1062
|
+
const languageId = model.getLanguageId();
|
|
1063
|
+
if (languageId !== processedCodeLanguage) {
|
|
1064
|
+
if (processedCodeLanguage) monaco_shim_exports.editor.setModelLanguage(model, processedCodeLanguage);
|
|
1065
|
+
const prevLineCount$1 = model.getLineCount();
|
|
1066
|
+
model.setValue(newCode);
|
|
1067
|
+
this.lastKnownCode = newCode;
|
|
1068
|
+
const newLineCount$1 = model.getLineCount();
|
|
1069
|
+
this.cachedLineCount = newLineCount$1;
|
|
1070
|
+
if (newLineCount$1 !== prevLineCount$1) this.maybeScrollToBottom(newLineCount$1);
|
|
1071
|
+
return;
|
|
1072
|
+
}
|
|
1073
|
+
const prevCode = this.lastKnownCode ?? this.editorView.getValue();
|
|
1074
|
+
if (prevCode === newCode) return;
|
|
1075
|
+
if (newCode.startsWith(prevCode) && prevCode.length < newCode.length) {
|
|
1076
|
+
const suffix = newCode.slice(prevCode.length);
|
|
1077
|
+
if (suffix) this.appendCode(suffix, codeLanguage);
|
|
1078
|
+
this.lastKnownCode = newCode;
|
|
1079
|
+
return;
|
|
1080
|
+
}
|
|
1081
|
+
const prevLineCount = model.getLineCount();
|
|
1082
|
+
this.applyMinimalEdit(prevCode, newCode);
|
|
1083
|
+
this.lastKnownCode = newCode;
|
|
1084
|
+
const newLineCount = model.getLineCount();
|
|
1085
|
+
this.cachedLineCount = newLineCount;
|
|
1086
|
+
if (newLineCount !== prevLineCount) this.maybeScrollToBottom(newLineCount);
|
|
1087
|
+
}
|
|
1088
|
+
appendCode(appendText, codeLanguage) {
|
|
1089
|
+
if (!this.editorView) return;
|
|
1090
|
+
const model = this.editorView.getModel();
|
|
1091
|
+
if (!model) return;
|
|
1092
|
+
const processedCodeLanguage = codeLanguage ? processedLanguage(codeLanguage) : model.getLanguageId();
|
|
1093
|
+
if (processedCodeLanguage && model.getLanguageId() !== processedCodeLanguage) monaco_shim_exports.editor.setModelLanguage(model, processedCodeLanguage);
|
|
1094
|
+
if (appendText) {
|
|
1095
|
+
this.appendBuffer.push(appendText);
|
|
1096
|
+
if (!this.appendBufferScheduled) {
|
|
1097
|
+
this.appendBufferScheduled = true;
|
|
1098
|
+
this.rafScheduler.schedule("append", () => this.flushAppendBuffer());
|
|
1099
|
+
}
|
|
1100
|
+
}
|
|
1101
|
+
}
|
|
1102
|
+
applyMinimalEdit(prev, next) {
|
|
1103
|
+
if (!this.editorView) return;
|
|
1104
|
+
const model = this.editorView.getModel();
|
|
1105
|
+
if (!model) return;
|
|
1106
|
+
try {
|
|
1107
|
+
const maxChars = minimalEditMaxChars;
|
|
1108
|
+
const ratio = minimalEditMaxChangeRatio;
|
|
1109
|
+
const maxLen = Math.max(prev.length, next.length);
|
|
1110
|
+
const changeRatio = maxLen > 0 ? Math.abs(next.length - prev.length) / maxLen : 0;
|
|
1111
|
+
if (prev.length + next.length > maxChars || changeRatio > ratio) {
|
|
1112
|
+
const prevLineCount = model.getLineCount();
|
|
1113
|
+
model.setValue(next);
|
|
1114
|
+
this.lastKnownCode = next;
|
|
1115
|
+
const newLineCount = model.getLineCount();
|
|
1116
|
+
this.cachedLineCount = newLineCount;
|
|
1117
|
+
if (newLineCount !== prevLineCount) this.maybeScrollToBottom(newLineCount);
|
|
1118
|
+
return;
|
|
1119
|
+
}
|
|
1120
|
+
} catch {}
|
|
1121
|
+
const res = computeMinimalEdit(prev, next);
|
|
1122
|
+
if (!res) return;
|
|
1123
|
+
const { start, endPrevIncl, replaceText } = res;
|
|
1124
|
+
const rangeStart = model.getPositionAt(start);
|
|
1125
|
+
const rangeEnd = model.getPositionAt(endPrevIncl + 1);
|
|
1126
|
+
const range = new monaco_shim_exports.Range(rangeStart.lineNumber, rangeStart.column, rangeEnd.lineNumber, rangeEnd.column);
|
|
1127
|
+
const isReadOnly = this.editorView.getOption(monaco_shim_exports.editor.EditorOption.readOnly);
|
|
1128
|
+
const edit = [{
|
|
1129
|
+
range,
|
|
1130
|
+
text: replaceText,
|
|
1131
|
+
forceMoveMarkers: true
|
|
1132
|
+
}];
|
|
1133
|
+
if (isReadOnly) model.applyEdits(edit);
|
|
1134
|
+
else this.editorView.executeEdits("minimal-replace", edit);
|
|
1135
|
+
}
|
|
1136
|
+
flushAppendBuffer() {
|
|
1137
|
+
if (!this.editorView) return;
|
|
1138
|
+
if (this.appendBuffer.length === 0) return;
|
|
1139
|
+
this.appendBufferScheduled = false;
|
|
1140
|
+
const model = this.editorView.getModel();
|
|
1141
|
+
if (!model) {
|
|
1142
|
+
this.appendBuffer.length = 0;
|
|
1143
|
+
return;
|
|
1144
|
+
}
|
|
1145
|
+
const text = this.appendBuffer.join("");
|
|
1146
|
+
this.appendBuffer.length = 0;
|
|
1147
|
+
const lastLine = model.getLineCount();
|
|
1148
|
+
const lastColumn = model.getLineMaxColumn(lastLine);
|
|
1149
|
+
const range = new monaco_shim_exports.Range(lastLine, lastColumn, lastLine, lastColumn);
|
|
1150
|
+
const isReadOnly = this.editorView.getOption(monaco_shim_exports.editor.EditorOption.readOnly);
|
|
1151
|
+
if (isReadOnly) model.applyEdits([{
|
|
1152
|
+
range,
|
|
1153
|
+
text,
|
|
1154
|
+
forceMoveMarkers: true
|
|
1155
|
+
}]);
|
|
1156
|
+
else this.editorView.executeEdits("append", [{
|
|
1157
|
+
range,
|
|
1158
|
+
text,
|
|
1159
|
+
forceMoveMarkers: true
|
|
1160
|
+
}]);
|
|
1161
|
+
const newLineCount = model.getLineCount();
|
|
1162
|
+
if (lastLine !== newLineCount) {
|
|
1163
|
+
this.cachedLineCount = newLineCount;
|
|
1164
|
+
this.maybeScrollToBottom(newLineCount);
|
|
1165
|
+
}
|
|
1166
|
+
}
|
|
1167
|
+
setLanguage(language, languages$1) {
|
|
1168
|
+
if (languages$1.includes(language)) {
|
|
1169
|
+
if (this.editorView) {
|
|
1170
|
+
const model = this.editorView.getModel();
|
|
1171
|
+
if (model && model.getLanguageId() !== language) monaco_shim_exports.editor.setModelLanguage(model, language);
|
|
1172
|
+
}
|
|
1173
|
+
} else console.warn(`Language "${language}" is not registered. Available languages: ${languages$1.join(", ")}`);
|
|
1174
|
+
}
|
|
1175
|
+
getEditorView() {
|
|
1176
|
+
return this.editorView;
|
|
1177
|
+
}
|
|
1178
|
+
cleanup() {
|
|
1179
|
+
this.rafScheduler.cancel("update");
|
|
1180
|
+
this.rafScheduler.cancel("sync-last-known");
|
|
1181
|
+
this.rafScheduler.cancel("content-size-change");
|
|
1182
|
+
this.pendingUpdate = null;
|
|
1183
|
+
this.rafScheduler.cancel("append");
|
|
1184
|
+
this.appendBufferScheduled = false;
|
|
1185
|
+
this.appendBuffer.length = 0;
|
|
1186
|
+
if (this.editorView) {
|
|
1187
|
+
this.editorView.dispose();
|
|
1188
|
+
this.editorView = null;
|
|
1189
|
+
}
|
|
1190
|
+
this.lastKnownCode = null;
|
|
1191
|
+
if (this.lastContainer) {
|
|
1192
|
+
this.lastContainer.innerHTML = "";
|
|
1193
|
+
this.lastContainer = null;
|
|
1194
|
+
}
|
|
1195
|
+
if (this.scrollWatcher) {
|
|
1196
|
+
this.scrollWatcher.dispose();
|
|
1197
|
+
this.scrollWatcher = null;
|
|
1198
|
+
}
|
|
1199
|
+
if (this.editorHeightManager) {
|
|
1200
|
+
this.editorHeightManager.dispose();
|
|
1201
|
+
this.editorHeightManager = null;
|
|
1202
|
+
}
|
|
1203
|
+
}
|
|
1204
|
+
safeClean() {
|
|
1205
|
+
this.rafScheduler.cancel("update");
|
|
1206
|
+
this.pendingUpdate = null;
|
|
1207
|
+
this.rafScheduler.cancel("sync-last-known");
|
|
1208
|
+
if (this.scrollWatcher) {
|
|
1209
|
+
this.scrollWatcher.dispose();
|
|
1210
|
+
this.scrollWatcher = null;
|
|
1211
|
+
}
|
|
1212
|
+
if (this.revealDebounceId != null) {
|
|
1213
|
+
clearTimeout(this.revealDebounceId);
|
|
1214
|
+
this.revealDebounceId = null;
|
|
1215
|
+
}
|
|
1216
|
+
this._hasScrollBar = false;
|
|
1217
|
+
this.shouldAutoScroll = !!this.autoScrollInitial;
|
|
1218
|
+
this.lastScrollTop = 0;
|
|
1219
|
+
if (this.editorHeightManager) {
|
|
1220
|
+
this.editorHeightManager.dispose();
|
|
1221
|
+
this.editorHeightManager = null;
|
|
1222
|
+
}
|
|
1223
|
+
}
|
|
1224
|
+
};
|
|
1225
|
+
|
|
1226
|
+
//#endregion
|
|
1227
|
+
//#region src/reactivity.ts
|
|
1228
|
+
function ref(initial) {
|
|
1229
|
+
const s = signal(initial);
|
|
1230
|
+
return Object.defineProperty({}, "value", {
|
|
1231
|
+
get() {
|
|
1232
|
+
return s();
|
|
1233
|
+
},
|
|
1234
|
+
set(v) {
|
|
1235
|
+
s(v);
|
|
1236
|
+
},
|
|
1237
|
+
enumerable: true,
|
|
1238
|
+
configurable: false
|
|
1239
|
+
});
|
|
1240
|
+
}
|
|
1241
|
+
function computed$1(getter) {
|
|
1242
|
+
const c = computed(() => getter());
|
|
1243
|
+
return Object.defineProperty({}, "value", {
|
|
1244
|
+
get() {
|
|
1245
|
+
return c();
|
|
1246
|
+
},
|
|
1247
|
+
set(_) {},
|
|
1248
|
+
enumerable: true,
|
|
1249
|
+
configurable: false
|
|
1250
|
+
});
|
|
1251
|
+
}
|
|
1252
|
+
function watch(source, cb, options = {}) {
|
|
1253
|
+
let initialized = false;
|
|
1254
|
+
let oldVal;
|
|
1255
|
+
const stop = effect(() => {
|
|
1256
|
+
const newVal = source();
|
|
1257
|
+
if (!initialized) {
|
|
1258
|
+
initialized = true;
|
|
1259
|
+
if (options.immediate) if (options.flush === "post") queueMicrotask(() => cb(newVal, oldVal));
|
|
1260
|
+
else cb(newVal, oldVal);
|
|
1261
|
+
} else if (!Object.is(newVal, oldVal)) if (options.flush === "post") queueMicrotask(() => cb(newVal, oldVal));
|
|
1262
|
+
else cb(newVal, oldVal);
|
|
1263
|
+
oldVal = newVal;
|
|
1264
|
+
});
|
|
1265
|
+
return stop;
|
|
1266
|
+
}
|
|
1267
|
+
|
|
1268
|
+
//#endregion
|
|
1269
|
+
//#region src/isDark.ts
|
|
1270
|
+
const isDark = ref(false);
|
|
1271
|
+
function computeIsDark() {
|
|
1272
|
+
var _el$classList, _window$matchMedia, _window;
|
|
1273
|
+
if (typeof window === "undefined" || typeof document === "undefined") return false;
|
|
1274
|
+
const el = document.documentElement;
|
|
1275
|
+
const hasClass = ((_el$classList = el.classList) === null || _el$classList === void 0 ? void 0 : _el$classList.contains("dark")) ?? false;
|
|
1276
|
+
const mql = (_window$matchMedia = (_window = window).matchMedia) === null || _window$matchMedia === void 0 ? void 0 : _window$matchMedia.call(_window, "(prefers-color-scheme: dark)");
|
|
1277
|
+
const prefersDark = !!(mql === null || mql === void 0 ? void 0 : mql.matches);
|
|
1278
|
+
return hasClass || prefersDark;
|
|
1279
|
+
}
|
|
1280
|
+
if (typeof window !== "undefined" && typeof document !== "undefined") {
|
|
1281
|
+
var _window$matchMedia2, _window2;
|
|
1282
|
+
const el = document.documentElement;
|
|
1283
|
+
const mql = (_window$matchMedia2 = (_window2 = window).matchMedia) === null || _window$matchMedia2 === void 0 ? void 0 : _window$matchMedia2.call(_window2, "(prefers-color-scheme: dark)");
|
|
1284
|
+
const update = () => {
|
|
1285
|
+
isDark.value = computeIsDark();
|
|
1286
|
+
};
|
|
1287
|
+
update();
|
|
1288
|
+
const onMqlChange = () => update();
|
|
1289
|
+
if (mql) mql.addEventListener ? mql.addEventListener("change", onMqlChange) : mql.addListener(onMqlChange);
|
|
1290
|
+
const mo = new MutationObserver(update);
|
|
1291
|
+
mo.observe(el, {
|
|
1292
|
+
attributes: true,
|
|
1293
|
+
attributeFilter: ["class"]
|
|
1294
|
+
});
|
|
1295
|
+
const cleanup = () => {
|
|
1296
|
+
if (mql) mql.removeEventListener ? mql.removeEventListener("change", onMqlChange) : mql.removeListener(onMqlChange);
|
|
1297
|
+
mo.disconnect();
|
|
1298
|
+
window.removeEventListener("pagehide", cleanup);
|
|
1299
|
+
window.removeEventListener("beforeunload", cleanup);
|
|
1300
|
+
};
|
|
1301
|
+
window.addEventListener("pagehide", cleanup);
|
|
1302
|
+
window.addEventListener("beforeunload", cleanup);
|
|
1303
|
+
}
|
|
1304
|
+
|
|
1305
|
+
//#endregion
|
|
1306
|
+
//#region src/preloadMonacoWorkers.ts
|
|
1307
|
+
async function preloadMonacoWorkers() {
|
|
1308
|
+
if (typeof window === "undefined" || typeof document === "undefined") return;
|
|
1309
|
+
const workerUrlJson = new URL("monaco-editor/esm/vs/language/json/json.worker.js", import.meta.url);
|
|
1310
|
+
const workerUrlCss = new URL("monaco-editor/esm/vs/language/css/css.worker.js", import.meta.url);
|
|
1311
|
+
const workerUrlHtml = new URL("monaco-editor/esm/vs/language/html/html.worker.js", import.meta.url);
|
|
1312
|
+
const workerUrlTs = new URL("monaco-editor/esm/vs/language/typescript/ts.worker.js", import.meta.url);
|
|
1313
|
+
const workerUrlEditor = new URL("monaco-editor/esm/vs/editor/editor.worker.js", import.meta.url);
|
|
1314
|
+
const unique = Array.from(new Set([
|
|
1315
|
+
String(workerUrlJson),
|
|
1316
|
+
String(workerUrlCss),
|
|
1317
|
+
String(workerUrlHtml),
|
|
1318
|
+
String(workerUrlTs),
|
|
1319
|
+
String(workerUrlEditor)
|
|
1320
|
+
]));
|
|
1321
|
+
const workerUrlByLabel = {
|
|
1322
|
+
json: workerUrlJson,
|
|
1323
|
+
css: workerUrlCss,
|
|
1324
|
+
scss: workerUrlCss,
|
|
1325
|
+
less: workerUrlCss,
|
|
1326
|
+
html: workerUrlHtml,
|
|
1327
|
+
handlebars: workerUrlHtml,
|
|
1328
|
+
razor: workerUrlHtml,
|
|
1329
|
+
typescript: workerUrlTs,
|
|
1330
|
+
javascript: workerUrlTs
|
|
1331
|
+
};
|
|
1332
|
+
try {
|
|
1333
|
+
await Promise.all(unique.map((u) => fetch(u, {
|
|
1334
|
+
method: "GET",
|
|
1335
|
+
cache: "force-cache"
|
|
1336
|
+
}).catch(() => void 0)));
|
|
1337
|
+
self.MonacoEnvironment = { getWorker(_, label) {
|
|
1338
|
+
const url = workerUrlByLabel[label] ?? workerUrlEditor;
|
|
1339
|
+
return new Worker(url, { type: "module" });
|
|
1340
|
+
} };
|
|
1341
|
+
} catch {}
|
|
1342
|
+
}
|
|
1343
|
+
|
|
1344
|
+
//#endregion
|
|
1345
|
+
//#region src/utils/arraysEqual.ts
|
|
1346
|
+
function arraysEqual(a, b) {
|
|
1347
|
+
if (a === b) return true;
|
|
1348
|
+
if (!a || !b) return false;
|
|
1349
|
+
if (a.length !== b.length) return false;
|
|
1350
|
+
for (let i = 0; i < a.length; i++) if (a[i] !== b[i]) return false;
|
|
1351
|
+
return true;
|
|
1352
|
+
}
|
|
1353
|
+
|
|
1354
|
+
//#endregion
|
|
1355
|
+
//#region src/utils/registerMonacoThemes.ts
|
|
1356
|
+
let themesRegistered = false;
|
|
1357
|
+
let languagesRegistered = false;
|
|
1358
|
+
let currentThemes = [];
|
|
1359
|
+
let currentLanguages = [];
|
|
1360
|
+
let themeRegisterPromise = null;
|
|
1361
|
+
function setThemeRegisterPromise(p) {
|
|
1362
|
+
return themeRegisterPromise = p;
|
|
1363
|
+
}
|
|
1364
|
+
const highlighterCache = /* @__PURE__ */ new Map();
|
|
1365
|
+
/**
|
|
1366
|
+
* Clear all cached shiki highlighters.
|
|
1367
|
+
*
|
|
1368
|
+
* Useful for long-running apps that dynamically create many theme combinations,
|
|
1369
|
+
* or in tests to ensure a clean state. Call this when you know the highlighters
|
|
1370
|
+
* are no longer needed (for example on app shutdown) to free memory.
|
|
1371
|
+
*/
|
|
1372
|
+
function clearHighlighterCache() {
|
|
1373
|
+
highlighterCache.clear();
|
|
1374
|
+
}
|
|
1375
|
+
function serializeThemes(themes) {
|
|
1376
|
+
return JSON.stringify(themes.map((t) => typeof t === "string" ? t : t.name ?? JSON.stringify(t)).sort());
|
|
1377
|
+
}
|
|
1378
|
+
async function getOrCreateHighlighter(themes, languages$1) {
|
|
1379
|
+
const key = serializeThemes(themes);
|
|
1380
|
+
const requestedSet = new Set(languages$1);
|
|
1381
|
+
let existing = highlighterCache.get(key);
|
|
1382
|
+
if (existing) {
|
|
1383
|
+
let allIncluded = true;
|
|
1384
|
+
for (const l of requestedSet) if (!existing.languages.has(l)) {
|
|
1385
|
+
allIncluded = false;
|
|
1386
|
+
break;
|
|
1387
|
+
}
|
|
1388
|
+
if (allIncluded) return existing.promise;
|
|
1389
|
+
const prev = existing;
|
|
1390
|
+
const current = highlighterCache.get(key);
|
|
1391
|
+
if (current && current !== prev) {
|
|
1392
|
+
let allIncludedCurrent = true;
|
|
1393
|
+
for (const l of requestedSet) if (!current.languages.has(l)) {
|
|
1394
|
+
allIncludedCurrent = false;
|
|
1395
|
+
break;
|
|
1396
|
+
}
|
|
1397
|
+
if (allIncludedCurrent) return current.promise;
|
|
1398
|
+
existing = current;
|
|
1399
|
+
}
|
|
1400
|
+
const union = new Set([...existing.languages, ...requestedSet]);
|
|
1401
|
+
const langsArray = Array.from(union);
|
|
1402
|
+
const p$1 = createHighlighter({
|
|
1403
|
+
themes,
|
|
1404
|
+
langs: langsArray
|
|
1405
|
+
});
|
|
1406
|
+
const newEntry = {
|
|
1407
|
+
promise: p$1,
|
|
1408
|
+
languages: union
|
|
1409
|
+
};
|
|
1410
|
+
highlighterCache.set(key, newEntry);
|
|
1411
|
+
p$1.catch(() => {
|
|
1412
|
+
if (highlighterCache.get(key) === newEntry && prev) highlighterCache.set(key, prev);
|
|
1413
|
+
});
|
|
1414
|
+
return p$1;
|
|
1415
|
+
}
|
|
1416
|
+
const p = createHighlighter({
|
|
1417
|
+
themes,
|
|
1418
|
+
langs: Array.from(requestedSet)
|
|
1419
|
+
});
|
|
1420
|
+
const entry = {
|
|
1421
|
+
promise: p,
|
|
1422
|
+
languages: requestedSet
|
|
1423
|
+
};
|
|
1424
|
+
highlighterCache.set(key, entry);
|
|
1425
|
+
p.catch(() => {
|
|
1426
|
+
if (highlighterCache.get(key) === entry) highlighterCache.delete(key);
|
|
1427
|
+
});
|
|
1428
|
+
return p;
|
|
1429
|
+
}
|
|
1430
|
+
/**
|
|
1431
|
+
* Update the theme used by the shiki highlighter for a given themes+languages
|
|
1432
|
+
* combination. Useful when Monaco themes are already registered (so switching
|
|
1433
|
+
* Monaco only requires `monaco.editor.setTheme`) but you also want shiki's
|
|
1434
|
+
* standalone renderer to use the new theme without recreating everything.
|
|
1435
|
+
*/
|
|
1436
|
+
async function registerMonacoThemes(themes, languages$1) {
|
|
1437
|
+
registerMonacoLanguages(languages$1);
|
|
1438
|
+
if (themesRegistered && arraysEqual(themes, currentThemes) && arraysEqual(languages$1, currentLanguages)) {
|
|
1439
|
+
const existing = highlighterCache.get(serializeThemes(themes));
|
|
1440
|
+
return existing ? existing.promise : Promise.resolve(null);
|
|
1441
|
+
}
|
|
1442
|
+
const p = (async () => {
|
|
1443
|
+
const highlighter = await getOrCreateHighlighter(themes, languages$1);
|
|
1444
|
+
shikiToMonaco(highlighter, monaco_shim_exports);
|
|
1445
|
+
themesRegistered = true;
|
|
1446
|
+
currentThemes = themes;
|
|
1447
|
+
currentLanguages = languages$1;
|
|
1448
|
+
return highlighter;
|
|
1449
|
+
})();
|
|
1450
|
+
setThemeRegisterPromise(p);
|
|
1451
|
+
try {
|
|
1452
|
+
const res = await p;
|
|
1453
|
+
return res;
|
|
1454
|
+
} catch (e) {
|
|
1455
|
+
setThemeRegisterPromise(null);
|
|
1456
|
+
throw e;
|
|
1457
|
+
}
|
|
1458
|
+
}
|
|
1459
|
+
function registerMonacoLanguages(languages$1) {
|
|
1460
|
+
if (languagesRegistered && arraysEqual(languages$1, currentLanguages)) return;
|
|
1461
|
+
const existing = new Set(monaco_shim_exports.languages.getLanguages().map((l) => l.id));
|
|
1462
|
+
for (const lang of languages$1) if (!existing.has(lang)) try {
|
|
1463
|
+
monaco_shim_exports.languages.register({ id: lang });
|
|
1464
|
+
} catch {}
|
|
1465
|
+
languagesRegistered = true;
|
|
1466
|
+
currentLanguages = languages$1;
|
|
1467
|
+
}
|
|
1468
|
+
|
|
1469
|
+
//#endregion
|
|
1470
|
+
//#region src/type.ts
|
|
1471
|
+
let RevealStrategy = /* @__PURE__ */ function(RevealStrategy$1) {
|
|
1472
|
+
RevealStrategy$1["Bottom"] = "bottom";
|
|
1473
|
+
RevealStrategy$1["CenterIfOutside"] = "centerIfOutside";
|
|
1474
|
+
RevealStrategy$1["Center"] = "center";
|
|
1475
|
+
return RevealStrategy$1;
|
|
1476
|
+
}({});
|
|
1477
|
+
|
|
1478
|
+
//#endregion
|
|
1479
|
+
//#region src/index.ts
|
|
1480
|
+
/**
|
|
1481
|
+
* useMonaco 组合式函数
|
|
1482
|
+
*
|
|
1483
|
+
* 提供 Monaco 编辑器的创建、销毁、内容/主题/语言更新等能力。
|
|
1484
|
+
* 支持主题自动切换、语言高亮、代码更新等功能。
|
|
1485
|
+
*
|
|
1486
|
+
* @param {MonacoOptions} [monacoOptions] - 编辑器初始化配置,支持 Monaco 原生配置及扩展项
|
|
1487
|
+
* @param {number | string} [monacoOptions.MAX_HEIGHT] - 编辑器最大高度,可以是数字(像素)或 CSS 字符串(如 '100%', 'calc(100vh - 100px)')
|
|
1488
|
+
* @param {boolean} [monacoOptions.readOnly] - 是否为只读模式
|
|
1489
|
+
* @param {MonacoTheme[]} [monacoOptions.themes] - 主题数组,至少包含两个主题:[暗色主题, 亮色主题]
|
|
1490
|
+
* @param {MonacoLanguage[]} [monacoOptions.languages] - 支持的编程语言数组
|
|
1491
|
+
* @param {string} [monacoOptions.theme] - 初始主题名称
|
|
1492
|
+
* @param {boolean} [monacoOptions.isCleanOnBeforeCreate] - 是否在创建前清理之前注册的资源, 默认为 true
|
|
1493
|
+
* @param {(monaco: typeof import('monaco-editor')) => monaco.IDisposable[]} [monacoOptions.onBeforeCreate] - 编辑器创建前的钩子函数
|
|
1494
|
+
*
|
|
1495
|
+
* @returns {{
|
|
1496
|
+
* createEditor: (container: HTMLElement, code: string, language: string) => Promise<monaco.editor.IStandaloneCodeEditor>,
|
|
1497
|
+
* createDiffEditor: (
|
|
1498
|
+
* container: HTMLElement,
|
|
1499
|
+
* originalCode: string,
|
|
1500
|
+
* modifiedCode: string,
|
|
1501
|
+
* language: string,
|
|
1502
|
+
* ) => Promise<monaco.editor.IStandaloneDiffEditor>,
|
|
1503
|
+
* cleanupEditor: () => void,
|
|
1504
|
+
* updateCode: (newCode: string, codeLanguage: string) => void,
|
|
1505
|
+
* appendCode: (appendText: string, codeLanguage?: string) => void,
|
|
1506
|
+
* updateDiff: (
|
|
1507
|
+
* originalCode: string,
|
|
1508
|
+
* modifiedCode: string,
|
|
1509
|
+
* codeLanguage?: string,
|
|
1510
|
+
* ) => void,
|
|
1511
|
+
* updateOriginal: (newCode: string, codeLanguage?: string) => void,
|
|
1512
|
+
* updateModified: (newCode: string, codeLanguage?: string) => void,
|
|
1513
|
+
* appendOriginal: (appendText: string, codeLanguage?: string) => void,
|
|
1514
|
+
* appendModified: (appendText: string, codeLanguage?: string) => void,
|
|
1515
|
+
* setTheme: (theme: MonacoTheme) => Promise<void>,
|
|
1516
|
+
* setLanguage: (language: MonacoLanguage) => void,
|
|
1517
|
+
* getCurrentTheme: () => string,
|
|
1518
|
+
* getEditor: () => typeof monaco.editor,
|
|
1519
|
+
* getEditorView: () => monaco.editor.IStandaloneCodeEditor | null,
|
|
1520
|
+
* getDiffEditorView: () => monaco.editor.IStandaloneDiffEditor | null,
|
|
1521
|
+
* getDiffModels: () => { original: monaco.editor.ITextModel | null, modified: monaco.editor.ITextModel | null },
|
|
1522
|
+
* }} 返回对象包含以下方法和属性:
|
|
1523
|
+
*
|
|
1524
|
+
* @property {Function} createEditor - 创建并挂载 Monaco 编辑器到指定容器
|
|
1525
|
+
* @property {Function} cleanupEditor - 销毁编辑器并清理容器
|
|
1526
|
+
* @property {Function} updateCode - 更新编辑器内容和语言,必要时滚动到底部
|
|
1527
|
+
* @property {Function} appendCode - 在编辑器末尾追加文本,必要时滚动到底部
|
|
1528
|
+
* @property {Function} createDiffEditor - 创建并挂载 Diff 编辑器
|
|
1529
|
+
* @property {Function} updateDiff - 更新 Diff 编辑器的 original/modified 内容(RAF 合并、增量更新)
|
|
1530
|
+
* @property {Function} updateOriginal - 仅更新 Diff 的 original 内容(增量更新)
|
|
1531
|
+
* @property {Function} updateModified - 仅更新 Diff 的 modified 内容(增量更新)
|
|
1532
|
+
* @property {Function} appendOriginal - 在 Diff 的 original 末尾追加(显式流式场景)
|
|
1533
|
+
* @property {Function} appendModified - 在 Diff 的 modified 末尾追加(显式流式场景)
|
|
1534
|
+
* @property {Function} setTheme - 切换编辑器主题,返回 Promise,在主题应用完成时 resolve
|
|
1535
|
+
* @property {Function} setLanguage - 切换编辑器语言
|
|
1536
|
+
* @property {Function} getCurrentTheme - 获取当前主题名称
|
|
1537
|
+
* @property {Function} getEditor - 获取 Monaco 的静态 editor 对象(用于静态方法调用)
|
|
1538
|
+
* @property {Function} getEditorView - 获取当前编辑器实例
|
|
1539
|
+
* @property {Function} getDiffEditorView - 获取当前 Diff 编辑器实例
|
|
1540
|
+
* @property {Function} getDiffModels - 获取 Diff 的 original/modified 两个模型
|
|
1541
|
+
*
|
|
1542
|
+
* @throws {Error} 当主题数组不是数组或长度小于2时抛出错误
|
|
1543
|
+
*
|
|
1544
|
+
* @example
|
|
1545
|
+
* ```typescript
|
|
1546
|
+
* import { useMonaco } from 'stream-monaco'
|
|
1547
|
+
*
|
|
1548
|
+
* const { createEditor, updateCode, setTheme } = useMonaco({
|
|
1549
|
+
* themes: ['vitesse-dark', 'vitesse-light'],
|
|
1550
|
+
* languages: ['javascript', 'typescript'],
|
|
1551
|
+
* readOnly: false
|
|
1552
|
+
* })
|
|
1553
|
+
*
|
|
1554
|
+
* // 创建编辑器
|
|
1555
|
+
* const editor = await createEditor(containerRef.value, 'console.log("hello")', 'javascript')
|
|
1556
|
+
*
|
|
1557
|
+
* // 更新代码
|
|
1558
|
+
* updateCode('console.log("world")', 'javascript')
|
|
1559
|
+
*
|
|
1560
|
+
* // 切换主题
|
|
1561
|
+
* setTheme('vitesse-light')
|
|
1562
|
+
* ```
|
|
1563
|
+
*/
|
|
1564
|
+
function useMonaco(monacoOptions = {}) {
|
|
1565
|
+
var _monacoOptions$themes;
|
|
1566
|
+
const disposals = [];
|
|
1567
|
+
if (monacoOptions.isCleanOnBeforeCreate ?? true) disposals.forEach((d) => d.dispose());
|
|
1568
|
+
if (monacoOptions.isCleanOnBeforeCreate ?? true) disposals.length = 0;
|
|
1569
|
+
let editorView = null;
|
|
1570
|
+
let editorMgr = null;
|
|
1571
|
+
let diffEditorView = null;
|
|
1572
|
+
let diffMgr = null;
|
|
1573
|
+
let originalModel = null;
|
|
1574
|
+
let modifiedModel = null;
|
|
1575
|
+
let _hasScrollBar = false;
|
|
1576
|
+
const themes = monacoOptions.themes && ((_monacoOptions$themes = monacoOptions.themes) === null || _monacoOptions$themes === void 0 ? void 0 : _monacoOptions$themes.length) ? monacoOptions.themes : defaultThemes;
|
|
1577
|
+
if (!Array.isArray(themes) || themes.length < 2) throw new Error("Monaco themes must be an array with at least two themes: [darkTheme, lightTheme]");
|
|
1578
|
+
const languages$1 = monacoOptions.languages ?? defaultLanguages;
|
|
1579
|
+
const MAX_HEIGHT = monacoOptions.MAX_HEIGHT ?? 500;
|
|
1580
|
+
const autoScrollOnUpdate = monacoOptions.autoScrollOnUpdate ?? true;
|
|
1581
|
+
const autoScrollInitial = monacoOptions.autoScrollInitial ?? true;
|
|
1582
|
+
const autoScrollThresholdPx = monacoOptions.autoScrollThresholdPx ?? 32;
|
|
1583
|
+
const autoScrollThresholdLines = monacoOptions.autoScrollThresholdLines ?? 2;
|
|
1584
|
+
const diffAutoScroll = monacoOptions.diffAutoScroll ?? true;
|
|
1585
|
+
const getMaxHeightValue = () => {
|
|
1586
|
+
if (typeof MAX_HEIGHT === "number") return MAX_HEIGHT;
|
|
1587
|
+
const match = MAX_HEIGHT.match(/^(\d+(?:\.\d+)?)/);
|
|
1588
|
+
return match ? Number.parseFloat(match[1]) : 500;
|
|
1589
|
+
};
|
|
1590
|
+
const getMaxHeightCSS = () => {
|
|
1591
|
+
if (typeof MAX_HEIGHT === "number") return `${MAX_HEIGHT}px`;
|
|
1592
|
+
return MAX_HEIGHT;
|
|
1593
|
+
};
|
|
1594
|
+
const maxHeightValue = getMaxHeightValue();
|
|
1595
|
+
const maxHeightCSS = getMaxHeightCSS();
|
|
1596
|
+
let lastContainer = null;
|
|
1597
|
+
let lastKnownCode = null;
|
|
1598
|
+
const minimalEditMaxCharsLocal = monacoOptions.minimalEditMaxChars ?? minimalEditMaxChars;
|
|
1599
|
+
const minimalEditMaxChangeRatioLocal = monacoOptions.minimalEditMaxChangeRatio ?? minimalEditMaxChangeRatio;
|
|
1600
|
+
let updateThrottleMs = monacoOptions.updateThrottleMs ?? 50;
|
|
1601
|
+
let lastFlushTime = 0;
|
|
1602
|
+
let updateThrottleTimer = null;
|
|
1603
|
+
let pendingUpdate = null;
|
|
1604
|
+
let shouldAutoScroll = true;
|
|
1605
|
+
const cachedComputedHeight = null;
|
|
1606
|
+
const appendBuffer = [];
|
|
1607
|
+
let appendBufferScheduled = false;
|
|
1608
|
+
let lastAppliedTheme = null;
|
|
1609
|
+
const currentTheme = computed$1(() => monacoOptions.theme ?? (isDark.value ? typeof themes[0] === "string" ? themes[0] : themes[0].name : typeof themes[1] === "string" ? themes[1] : themes[1].name));
|
|
1610
|
+
let themeWatcher = null;
|
|
1611
|
+
const rafScheduler = createRafScheduler();
|
|
1612
|
+
async function setThemeInternal(theme, force = false) {
|
|
1613
|
+
const themeName = typeof theme === "string" ? theme : theme.name;
|
|
1614
|
+
if (!force && themeName === lastAppliedTheme) return;
|
|
1615
|
+
const _p = setThemeRegisterPromise(registerMonacoThemes(themes, languages$1));
|
|
1616
|
+
if (_p) await _p.catch(() => void 0);
|
|
1617
|
+
const availableNames = themes.map((t) => typeof t === "string" ? t : t.name);
|
|
1618
|
+
if (!availableNames.includes(themeName)) try {
|
|
1619
|
+
const extended = availableNames.concat(themeName);
|
|
1620
|
+
const maybeHighlighter = await setThemeRegisterPromise(registerMonacoThemes(extended, languages$1));
|
|
1621
|
+
if (maybeHighlighter && typeof maybeHighlighter.setTheme === "function") try {
|
|
1622
|
+
await maybeHighlighter.setTheme(themeName);
|
|
1623
|
+
} catch {}
|
|
1624
|
+
} catch {
|
|
1625
|
+
console.warn(`Theme "${themeName}" is not registered and automatic registration failed. Available themes: ${availableNames.join(", ")}`);
|
|
1626
|
+
return;
|
|
1627
|
+
}
|
|
1628
|
+
try {
|
|
1629
|
+
monaco_shim_exports.editor.setTheme(themeName);
|
|
1630
|
+
lastAppliedTheme = themeName;
|
|
1631
|
+
} catch {
|
|
1632
|
+
try {
|
|
1633
|
+
const maybeHighlighter = await registerMonacoThemes(themes, languages$1);
|
|
1634
|
+
monaco_shim_exports.editor.setTheme(themeName);
|
|
1635
|
+
lastAppliedTheme = themeName;
|
|
1636
|
+
if (maybeHighlighter && typeof maybeHighlighter.setTheme === "function") await maybeHighlighter.setTheme(themeName).catch(() => void 0);
|
|
1637
|
+
} catch (err2) {
|
|
1638
|
+
console.warn(`Failed to set theme "${themeName}":`, err2);
|
|
1639
|
+
return;
|
|
1640
|
+
}
|
|
1641
|
+
}
|
|
1642
|
+
try {
|
|
1643
|
+
if (typeof monacoOptions.onThemeChange === "function") await monacoOptions.onThemeChange(themeName);
|
|
1644
|
+
} catch (err) {
|
|
1645
|
+
console.warn("onThemeChange callback threw an error:", err);
|
|
1646
|
+
}
|
|
1647
|
+
}
|
|
1648
|
+
function hasVerticalScrollbar() {
|
|
1649
|
+
if (!editorView) return false;
|
|
1650
|
+
if (_hasScrollBar) return true;
|
|
1651
|
+
const ch = cachedComputedHeight ?? computedHeight(editorView);
|
|
1652
|
+
return _hasScrollBar = editorView.getScrollHeight() > ch + padding / 2;
|
|
1653
|
+
}
|
|
1654
|
+
let revealDebounceId = null;
|
|
1655
|
+
const revealDebounceMs = 75;
|
|
1656
|
+
function maybeScrollToBottom(targetLine) {
|
|
1657
|
+
if (autoScrollOnUpdate && shouldAutoScroll && hasVerticalScrollbar()) {
|
|
1658
|
+
const model = editorView.getModel();
|
|
1659
|
+
const line = targetLine ?? (model === null || model === void 0 ? void 0 : model.getLineCount()) ?? 1;
|
|
1660
|
+
if (revealDebounceId != null) {
|
|
1661
|
+
clearTimeout(revealDebounceId);
|
|
1662
|
+
revealDebounceId = null;
|
|
1663
|
+
}
|
|
1664
|
+
revealDebounceId = setTimeout(() => {
|
|
1665
|
+
revealDebounceId = null;
|
|
1666
|
+
rafScheduler.schedule("reveal", () => {
|
|
1667
|
+
try {
|
|
1668
|
+
var _editor;
|
|
1669
|
+
const ScrollType = monaco_shim_exports.ScrollType || ((_editor = monaco_shim_exports.editor) === null || _editor === void 0 ? void 0 : _editor.ScrollType);
|
|
1670
|
+
if (ScrollType && typeof ScrollType.Smooth !== "undefined") editorView.revealLineInCenterIfOutsideViewport(line, ScrollType.Smooth);
|
|
1671
|
+
else editorView.revealLineInCenterIfOutsideViewport(line);
|
|
1672
|
+
} catch {}
|
|
1673
|
+
});
|
|
1674
|
+
}, revealDebounceMs);
|
|
1675
|
+
}
|
|
1676
|
+
}
|
|
1677
|
+
async function createEditor(container, code, language) {
|
|
1678
|
+
cleanupEditor();
|
|
1679
|
+
lastContainer = container;
|
|
1680
|
+
if (monacoOptions.isCleanOnBeforeCreate ?? true) {
|
|
1681
|
+
disposals.forEach((d) => d.dispose());
|
|
1682
|
+
disposals.length = 0;
|
|
1683
|
+
}
|
|
1684
|
+
if (monacoOptions.onBeforeCreate) {
|
|
1685
|
+
const ds = monacoOptions.onBeforeCreate(monaco_shim_exports);
|
|
1686
|
+
if (ds) disposals.push(...ds);
|
|
1687
|
+
}
|
|
1688
|
+
await setThemeRegisterPromise(registerMonacoThemes(themes, languages$1));
|
|
1689
|
+
const initialThemeName = monacoOptions.theme ?? currentTheme.value;
|
|
1690
|
+
lastAppliedTheme = initialThemeName;
|
|
1691
|
+
editorMgr = new EditorManager(monacoOptions, maxHeightValue, maxHeightCSS, autoScrollOnUpdate, autoScrollInitial, autoScrollThresholdPx, autoScrollThresholdLines, monacoOptions.revealDebounceMs);
|
|
1692
|
+
editorView = await editorMgr.createEditor(container, code, language, initialThemeName);
|
|
1693
|
+
if (typeof monacoOptions.onThemeChange === "function") monacoOptions.onThemeChange(initialThemeName);
|
|
1694
|
+
if (!monacoOptions.theme) themeWatcher = watch(() => isDark.value, () => {
|
|
1695
|
+
const t = currentTheme.value;
|
|
1696
|
+
if (t !== lastAppliedTheme) setThemeInternal(t);
|
|
1697
|
+
}, {
|
|
1698
|
+
flush: "post",
|
|
1699
|
+
immediate: true
|
|
1700
|
+
});
|
|
1701
|
+
try {
|
|
1702
|
+
if (editorView) lastKnownCode = editorView.getValue();
|
|
1703
|
+
} catch {}
|
|
1704
|
+
return editorView;
|
|
1705
|
+
}
|
|
1706
|
+
function computedHeight(editorView$1) {
|
|
1707
|
+
var _getModel;
|
|
1708
|
+
const lineCount = ((_getModel = editorView$1.getModel()) === null || _getModel === void 0 ? void 0 : _getModel.getLineCount()) ?? 1;
|
|
1709
|
+
const lineHeight = editorView$1.getOption(monaco_shim_exports.editor.EditorOption.lineHeight);
|
|
1710
|
+
const height = Math.min(lineCount * lineHeight + padding, maxHeightValue);
|
|
1711
|
+
return height;
|
|
1712
|
+
}
|
|
1713
|
+
async function createDiffEditor(container, originalCode, modifiedCode, language) {
|
|
1714
|
+
cleanupEditor();
|
|
1715
|
+
lastContainer = container;
|
|
1716
|
+
if (monacoOptions.isCleanOnBeforeCreate ?? true) {
|
|
1717
|
+
disposals.forEach((d) => d.dispose());
|
|
1718
|
+
disposals.length = 0;
|
|
1719
|
+
}
|
|
1720
|
+
if (monacoOptions.onBeforeCreate) {
|
|
1721
|
+
const ds = monacoOptions.onBeforeCreate(monaco_shim_exports);
|
|
1722
|
+
if (ds) disposals.push(...ds);
|
|
1723
|
+
}
|
|
1724
|
+
await setThemeRegisterPromise(registerMonacoThemes(themes, languages$1));
|
|
1725
|
+
const initialThemeName = monacoOptions.theme ?? currentTheme.value;
|
|
1726
|
+
try {
|
|
1727
|
+
monaco_shim_exports.editor.setTheme(initialThemeName);
|
|
1728
|
+
lastAppliedTheme = initialThemeName;
|
|
1729
|
+
} catch {}
|
|
1730
|
+
diffMgr = new DiffEditorManager(monacoOptions, maxHeightValue, maxHeightCSS, autoScrollOnUpdate, autoScrollInitial, autoScrollThresholdPx, autoScrollThresholdLines, diffAutoScroll, monacoOptions.revealDebounceMs);
|
|
1731
|
+
diffEditorView = await diffMgr.createDiffEditor(container, originalCode, modifiedCode, language, initialThemeName);
|
|
1732
|
+
if (typeof monacoOptions.onThemeChange === "function") monacoOptions.onThemeChange(initialThemeName);
|
|
1733
|
+
if (!monacoOptions.theme) themeWatcher = watch(() => isDark.value, () => {
|
|
1734
|
+
const t = currentTheme.value;
|
|
1735
|
+
if (t !== lastAppliedTheme) setThemeInternal(t);
|
|
1736
|
+
}, {
|
|
1737
|
+
flush: "post",
|
|
1738
|
+
immediate: true
|
|
1739
|
+
});
|
|
1740
|
+
const models = diffMgr.getDiffModels();
|
|
1741
|
+
originalModel = models.original;
|
|
1742
|
+
modifiedModel = models.modified;
|
|
1743
|
+
return diffEditorView;
|
|
1744
|
+
}
|
|
1745
|
+
function cleanupEditor() {
|
|
1746
|
+
if (editorMgr) {
|
|
1747
|
+
editorMgr.cleanup();
|
|
1748
|
+
editorMgr = null;
|
|
1749
|
+
}
|
|
1750
|
+
if (diffMgr) {
|
|
1751
|
+
diffMgr.cleanup();
|
|
1752
|
+
diffMgr = null;
|
|
1753
|
+
}
|
|
1754
|
+
rafScheduler.cancel("update");
|
|
1755
|
+
pendingUpdate = null;
|
|
1756
|
+
rafScheduler.cancel("append");
|
|
1757
|
+
appendBufferScheduled = false;
|
|
1758
|
+
appendBuffer.length = 0;
|
|
1759
|
+
if (!editorMgr && editorView) {
|
|
1760
|
+
editorView.dispose();
|
|
1761
|
+
editorView = null;
|
|
1762
|
+
}
|
|
1763
|
+
lastKnownCode = null;
|
|
1764
|
+
if (lastContainer) {
|
|
1765
|
+
lastContainer.innerHTML = "";
|
|
1766
|
+
lastContainer = null;
|
|
1767
|
+
}
|
|
1768
|
+
if (themeWatcher) {
|
|
1769
|
+
themeWatcher();
|
|
1770
|
+
themeWatcher = null;
|
|
1771
|
+
}
|
|
1772
|
+
if (updateThrottleTimer != null) {
|
|
1773
|
+
clearTimeout(updateThrottleTimer);
|
|
1774
|
+
updateThrottleTimer = null;
|
|
1775
|
+
}
|
|
1776
|
+
diffEditorView = null;
|
|
1777
|
+
originalModel = null;
|
|
1778
|
+
modifiedModel = null;
|
|
1779
|
+
}
|
|
1780
|
+
function appendCode(appendText, codeLanguage) {
|
|
1781
|
+
if (editorMgr) editorMgr.appendCode(appendText, codeLanguage);
|
|
1782
|
+
else {
|
|
1783
|
+
if (!editorView) return;
|
|
1784
|
+
const model = editorView.getModel();
|
|
1785
|
+
if (!model) return;
|
|
1786
|
+
const processedCodeLanguage = codeLanguage ? processedLanguage(codeLanguage) : model.getLanguageId();
|
|
1787
|
+
if (processedCodeLanguage && model.getLanguageId() !== processedCodeLanguage) monaco_shim_exports.editor.setModelLanguage(model, processedCodeLanguage);
|
|
1788
|
+
if (appendText && lastKnownCode != null) lastKnownCode = lastKnownCode + appendText;
|
|
1789
|
+
if (appendText) {
|
|
1790
|
+
appendBuffer.push(appendText);
|
|
1791
|
+
if (!appendBufferScheduled) {
|
|
1792
|
+
appendBufferScheduled = true;
|
|
1793
|
+
rafScheduler.schedule("append", flushAppendBuffer);
|
|
1794
|
+
}
|
|
1795
|
+
}
|
|
1796
|
+
}
|
|
1797
|
+
}
|
|
1798
|
+
function applyMinimalEdit(prev, next) {
|
|
1799
|
+
if (!editorView) return;
|
|
1800
|
+
const model = editorView.getModel();
|
|
1801
|
+
if (!model) return;
|
|
1802
|
+
try {
|
|
1803
|
+
const maxChars = minimalEditMaxCharsLocal;
|
|
1804
|
+
const ratio = minimalEditMaxChangeRatioLocal;
|
|
1805
|
+
const maxLen = Math.max(prev.length, next.length);
|
|
1806
|
+
const changeRatio = maxLen > 0 ? Math.abs(next.length - prev.length) / maxLen : 0;
|
|
1807
|
+
if (prev.length + next.length > maxChars || changeRatio > ratio) {
|
|
1808
|
+
const prevLineCount = model.getLineCount();
|
|
1809
|
+
model.setValue(next);
|
|
1810
|
+
lastKnownCode = next;
|
|
1811
|
+
const newLineCount = model.getLineCount();
|
|
1812
|
+
if (newLineCount !== prevLineCount) maybeScrollToBottom(newLineCount);
|
|
1813
|
+
return;
|
|
1814
|
+
}
|
|
1815
|
+
} catch {}
|
|
1816
|
+
const res = computeMinimalEdit(prev, next);
|
|
1817
|
+
if (!res) return;
|
|
1818
|
+
const { start, endPrevIncl, replaceText } = res;
|
|
1819
|
+
const rangeStart = model.getPositionAt(start);
|
|
1820
|
+
const rangeEnd = model.getPositionAt(endPrevIncl + 1);
|
|
1821
|
+
const range = new monaco_shim_exports.Range(rangeStart.lineNumber, rangeStart.column, rangeEnd.lineNumber, rangeEnd.column);
|
|
1822
|
+
const isReadOnly = editorView.getOption(monaco_shim_exports.editor.EditorOption.readOnly);
|
|
1823
|
+
const edit = [{
|
|
1824
|
+
range,
|
|
1825
|
+
text: replaceText,
|
|
1826
|
+
forceMoveMarkers: true
|
|
1827
|
+
}];
|
|
1828
|
+
if (isReadOnly) model.applyEdits(edit);
|
|
1829
|
+
else editorView.executeEdits("minimal-replace", edit);
|
|
1830
|
+
}
|
|
1831
|
+
function flushPendingUpdate() {
|
|
1832
|
+
if (!pendingUpdate) return;
|
|
1833
|
+
lastFlushTime = Date.now();
|
|
1834
|
+
if (!editorView) return;
|
|
1835
|
+
const model = editorView.getModel();
|
|
1836
|
+
if (!model) return;
|
|
1837
|
+
const { code: newCode, lang: codeLanguage } = pendingUpdate;
|
|
1838
|
+
pendingUpdate = null;
|
|
1839
|
+
const processedCodeLanguage = processedLanguage(codeLanguage);
|
|
1840
|
+
let prevCode = lastKnownCode;
|
|
1841
|
+
if (prevCode == null) try {
|
|
1842
|
+
prevCode = model.getValue();
|
|
1843
|
+
lastKnownCode = prevCode;
|
|
1844
|
+
} catch {
|
|
1845
|
+
prevCode = "";
|
|
1846
|
+
}
|
|
1847
|
+
if (prevCode === newCode) return;
|
|
1848
|
+
const languageId = model.getLanguageId();
|
|
1849
|
+
if (languageId !== processedCodeLanguage) {
|
|
1850
|
+
if (processedCodeLanguage) monaco_shim_exports.editor.setModelLanguage(model, processedCodeLanguage);
|
|
1851
|
+
const prevLineCount = model.getLineCount();
|
|
1852
|
+
model.setValue(newCode);
|
|
1853
|
+
lastKnownCode = newCode;
|
|
1854
|
+
const newLineCount = model.getLineCount();
|
|
1855
|
+
if (newLineCount !== prevLineCount) maybeScrollToBottom(newLineCount);
|
|
1856
|
+
return;
|
|
1857
|
+
}
|
|
1858
|
+
if (newCode.startsWith(prevCode) && prevCode.length < newCode.length) {
|
|
1859
|
+
const suffix = newCode.slice(prevCode.length);
|
|
1860
|
+
if (suffix) appendCode(suffix, codeLanguage);
|
|
1861
|
+
lastKnownCode = newCode;
|
|
1862
|
+
return;
|
|
1863
|
+
}
|
|
1864
|
+
try {
|
|
1865
|
+
const maxChars = minimalEditMaxCharsLocal;
|
|
1866
|
+
const ratio = minimalEditMaxChangeRatioLocal;
|
|
1867
|
+
const maxLen = Math.max(prevCode.length, newCode.length);
|
|
1868
|
+
const changeRatio = maxLen > 0 ? Math.abs(newCode.length - prevCode.length) / maxLen : 0;
|
|
1869
|
+
if (prevCode.length + newCode.length > maxChars || changeRatio > ratio) {
|
|
1870
|
+
const prevLineCount = model.getLineCount();
|
|
1871
|
+
model.setValue(newCode);
|
|
1872
|
+
lastKnownCode = newCode;
|
|
1873
|
+
const newLineCount = model.getLineCount();
|
|
1874
|
+
if (newLineCount !== prevLineCount) maybeScrollToBottom(newLineCount);
|
|
1875
|
+
return;
|
|
1876
|
+
}
|
|
1877
|
+
} catch {}
|
|
1878
|
+
try {
|
|
1879
|
+
applyMinimalEdit(prevCode, newCode);
|
|
1880
|
+
lastKnownCode = newCode;
|
|
1881
|
+
const newLineCount = model.getLineCount();
|
|
1882
|
+
const prevLineCount = (prevCode ? prevCode.split("\n").length : 0) || model.getLineCount();
|
|
1883
|
+
if (newLineCount !== prevLineCount) maybeScrollToBottom(newLineCount);
|
|
1884
|
+
} catch {
|
|
1885
|
+
try {
|
|
1886
|
+
const prevLineCount = model.getLineCount();
|
|
1887
|
+
model.setValue(newCode);
|
|
1888
|
+
lastKnownCode = newCode;
|
|
1889
|
+
const newLineCount = model.getLineCount();
|
|
1890
|
+
if (newLineCount !== prevLineCount) maybeScrollToBottom(newLineCount);
|
|
1891
|
+
} catch {}
|
|
1892
|
+
}
|
|
1893
|
+
}
|
|
1894
|
+
function flushAppendBuffer() {
|
|
1895
|
+
if (!editorView) return;
|
|
1896
|
+
if (appendBuffer.length === 0) return;
|
|
1897
|
+
appendBufferScheduled = false;
|
|
1898
|
+
const model = editorView.getModel();
|
|
1899
|
+
if (!model) {
|
|
1900
|
+
appendBuffer.length = 0;
|
|
1901
|
+
return;
|
|
1902
|
+
}
|
|
1903
|
+
const text = appendBuffer.join("");
|
|
1904
|
+
appendBuffer.length = 0;
|
|
1905
|
+
try {
|
|
1906
|
+
const lastLine = model.getLineCount();
|
|
1907
|
+
const lastColumn = model.getLineMaxColumn(lastLine);
|
|
1908
|
+
const range = new monaco_shim_exports.Range(lastLine, lastColumn, lastLine, lastColumn);
|
|
1909
|
+
const isReadOnly = editorView.getOption(monaco_shim_exports.editor.EditorOption.readOnly);
|
|
1910
|
+
if (isReadOnly) model.applyEdits([{
|
|
1911
|
+
range,
|
|
1912
|
+
text,
|
|
1913
|
+
forceMoveMarkers: true
|
|
1914
|
+
}]);
|
|
1915
|
+
else editorView.executeEdits("append", [{
|
|
1916
|
+
range,
|
|
1917
|
+
text,
|
|
1918
|
+
forceMoveMarkers: true
|
|
1919
|
+
}]);
|
|
1920
|
+
if (lastKnownCode != null) lastKnownCode = lastKnownCode + text;
|
|
1921
|
+
try {
|
|
1922
|
+
if (lastLine !== model.getLineCount()) maybeScrollToBottom(model.getLineCount());
|
|
1923
|
+
} catch {}
|
|
1924
|
+
} catch {}
|
|
1925
|
+
}
|
|
1926
|
+
function updateCode(newCode, codeLanguage) {
|
|
1927
|
+
if (editorMgr) editorMgr.updateCode(newCode, codeLanguage);
|
|
1928
|
+
else {
|
|
1929
|
+
pendingUpdate = {
|
|
1930
|
+
code: newCode,
|
|
1931
|
+
lang: codeLanguage
|
|
1932
|
+
};
|
|
1933
|
+
rafScheduler.schedule("update", () => {
|
|
1934
|
+
if (!updateThrottleMs) {
|
|
1935
|
+
flushPendingUpdate();
|
|
1936
|
+
return;
|
|
1937
|
+
}
|
|
1938
|
+
const now = Date.now();
|
|
1939
|
+
const since = now - lastFlushTime;
|
|
1940
|
+
if (since >= updateThrottleMs) {
|
|
1941
|
+
flushPendingUpdate();
|
|
1942
|
+
return;
|
|
1943
|
+
}
|
|
1944
|
+
if (updateThrottleTimer != null) return;
|
|
1945
|
+
const wait = updateThrottleMs - since;
|
|
1946
|
+
updateThrottleTimer = setTimeout(() => {
|
|
1947
|
+
updateThrottleTimer = null;
|
|
1948
|
+
rafScheduler.schedule("update", () => flushPendingUpdate());
|
|
1949
|
+
}, wait);
|
|
1950
|
+
});
|
|
1951
|
+
}
|
|
1952
|
+
}
|
|
1953
|
+
function setUpdateThrottleMs(ms) {
|
|
1954
|
+
updateThrottleMs = ms;
|
|
1955
|
+
}
|
|
1956
|
+
function getUpdateThrottleMs() {
|
|
1957
|
+
return updateThrottleMs;
|
|
1958
|
+
}
|
|
1959
|
+
function updateDiff(originalCode, modifiedCode, codeLanguage) {
|
|
1960
|
+
if (diffMgr) diffMgr.updateDiff(originalCode, modifiedCode, codeLanguage);
|
|
1961
|
+
}
|
|
1962
|
+
function updateOriginal(newCode, codeLanguage) {
|
|
1963
|
+
if (diffMgr) diffMgr.updateOriginal(newCode, codeLanguage);
|
|
1964
|
+
}
|
|
1965
|
+
function updateModified(newCode, codeLanguage) {
|
|
1966
|
+
if (diffMgr) diffMgr.updateModified(newCode, codeLanguage);
|
|
1967
|
+
}
|
|
1968
|
+
function appendOriginal(appendText, codeLanguage) {
|
|
1969
|
+
if (diffMgr) diffMgr.appendOriginal(appendText, codeLanguage);
|
|
1970
|
+
}
|
|
1971
|
+
function appendModified(appendText, codeLanguage) {
|
|
1972
|
+
if (diffMgr) diffMgr.appendModified(appendText, codeLanguage);
|
|
1973
|
+
}
|
|
1974
|
+
return {
|
|
1975
|
+
createEditor,
|
|
1976
|
+
createDiffEditor,
|
|
1977
|
+
cleanupEditor,
|
|
1978
|
+
safeClean() {
|
|
1979
|
+
rafScheduler.cancel("update");
|
|
1980
|
+
pendingUpdate = null;
|
|
1981
|
+
if (editorMgr) try {
|
|
1982
|
+
editorMgr.safeClean();
|
|
1983
|
+
} catch {}
|
|
1984
|
+
if (diffMgr) try {
|
|
1985
|
+
diffMgr.safeClean();
|
|
1986
|
+
} catch {}
|
|
1987
|
+
_hasScrollBar = false;
|
|
1988
|
+
shouldAutoScroll = !!autoScrollInitial;
|
|
1989
|
+
},
|
|
1990
|
+
updateCode,
|
|
1991
|
+
appendCode,
|
|
1992
|
+
updateDiff,
|
|
1993
|
+
updateOriginal,
|
|
1994
|
+
updateModified,
|
|
1995
|
+
appendOriginal,
|
|
1996
|
+
appendModified,
|
|
1997
|
+
setTheme: setThemeInternal,
|
|
1998
|
+
setLanguage(language) {
|
|
1999
|
+
if (editorMgr) {
|
|
2000
|
+
editorMgr.setLanguage(language, languages$1);
|
|
2001
|
+
return;
|
|
2002
|
+
}
|
|
2003
|
+
if (diffMgr) {
|
|
2004
|
+
diffMgr.setLanguage(language, languages$1);
|
|
2005
|
+
return;
|
|
2006
|
+
}
|
|
2007
|
+
if (languages$1.includes(language)) {
|
|
2008
|
+
if (editorView) {
|
|
2009
|
+
const model = editorView.getModel();
|
|
2010
|
+
if (model && model.getLanguageId() !== language) monaco_shim_exports.editor.setModelLanguage(model, language);
|
|
2011
|
+
}
|
|
2012
|
+
if (originalModel && originalModel.getLanguageId() !== language) monaco_shim_exports.editor.setModelLanguage(originalModel, language);
|
|
2013
|
+
if (modifiedModel && modifiedModel.getLanguageId() !== language) monaco_shim_exports.editor.setModelLanguage(modifiedModel, language);
|
|
2014
|
+
} else console.warn(`Language "${language}" is not registered. Available languages: ${languages$1.join(", ")}`);
|
|
2015
|
+
},
|
|
2016
|
+
getCurrentTheme() {
|
|
2017
|
+
return currentTheme.value;
|
|
2018
|
+
},
|
|
2019
|
+
getEditor() {
|
|
2020
|
+
return monaco_shim_exports.editor;
|
|
2021
|
+
},
|
|
2022
|
+
getEditorView() {
|
|
2023
|
+
return editorView;
|
|
2024
|
+
},
|
|
2025
|
+
getDiffEditorView() {
|
|
2026
|
+
return diffEditorView;
|
|
2027
|
+
},
|
|
2028
|
+
getDiffModels() {
|
|
2029
|
+
return {
|
|
2030
|
+
original: originalModel,
|
|
2031
|
+
modified: modifiedModel
|
|
2032
|
+
};
|
|
2033
|
+
},
|
|
2034
|
+
getMonacoInstance() {
|
|
2035
|
+
return monaco_shim_exports;
|
|
2036
|
+
},
|
|
2037
|
+
setUpdateThrottleMs,
|
|
2038
|
+
getUpdateThrottleMs
|
|
2039
|
+
};
|
|
2040
|
+
}
|
|
2041
|
+
|
|
2042
|
+
//#endregion
|
|
2043
|
+
export { RevealStrategy, clearHighlighterCache, defaultRevealDebounceMs, detectLanguage, getOrCreateHighlighter, isDark, preloadMonacoWorkers, registerMonacoThemes, useMonaco };
|