stream-monaco 0.0.18 → 0.0.20

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.
@@ -1,2871 +0,0 @@
1
- import { __export, __reExport } from "./chunk-CHLpw0oG.js";
2
- import * as _monaco from "monaco-editor/esm/vs/editor/editor.api";
3
- import { computed } 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
- try {
85
- var _globalThis;
86
- if (((_globalThis = globalThis) === null || _globalThis === void 0 ? void 0 : _globalThis.__streamMonacoLegacy__) && /^vue$/i.test(language)) return "html";
87
- } catch {}
88
- if (/^(?:shellscript|bash|sh|shell|zsh)/i.test(language)) return "shellscript";
89
- if (/^(?:powershell|ps1?)/i.test(language)) return "powershell";
90
- return language.split(":")[0];
91
- }
92
- /**
93
- * 使用示例:
94
- *
95
- * // 基本用法
96
- * const language1 = detectLanguage('console.log("hello")') // 'js'
97
- *
98
- * // 使用自定义语言检测规则
99
- * const customLanguages: LanguageDefinition[] = [
100
- * ['vue', [/<template>/g, 100], [/<script>/g, 50], [/<style>/g, 50]],
101
- * ['kotlin', [/\b(fun|class|val|var)\b/g, 20]]
102
- * ]
103
- *
104
- * const language2 = detectLanguage(`
105
- * <template>
106
- * <div>Hello Vue</div>
107
- * </template>
108
- * `, customLanguages) // 'vue'
109
- *
110
- * const language3 = detectLanguage(`
111
- * fun main() {
112
- * val name = "Kotlin"
113
- * println("Hello $name")
114
- * }
115
- * `, customLanguages) // 'kotlin'
116
- */
117
-
118
- //#endregion
119
- //#region src/constant.ts
120
- const defaultLanguages = [
121
- "jsx",
122
- "tsx",
123
- "vue",
124
- "csharp",
125
- "python",
126
- "java",
127
- "c",
128
- "cpp",
129
- "rust",
130
- "go",
131
- "shell",
132
- "shellscript",
133
- "powershell",
134
- "sql",
135
- "json",
136
- "html",
137
- "javascript",
138
- "typescript",
139
- "css",
140
- "markdown",
141
- "xml",
142
- "yaml",
143
- "toml",
144
- "dockerfile",
145
- "kotlin",
146
- "objective-c",
147
- "objective-cpp",
148
- "php",
149
- "ruby",
150
- "scala",
151
- "svelte",
152
- "swift",
153
- "erlang",
154
- "angular-html",
155
- "angular-ts",
156
- "dart",
157
- "lua",
158
- "mermaid",
159
- "cmake",
160
- "nginx"
161
- ];
162
- const defaultThemes = ["vitesse-dark", "vitesse-light"];
163
- const defaultScrollbar = {
164
- verticalScrollbarSize: 8,
165
- horizontalScrollbarSize: 8,
166
- handleMouseWheel: true,
167
- alwaysConsumeMouseWheel: false
168
- };
169
- const padding = 16;
170
- const defaultRevealDebounceMs = 75;
171
- const defaultRevealBatchOnIdleMs = 200;
172
- const minimalEditMaxChars = 2e5;
173
- const minimalEditMaxChangeRatio = .5;
174
-
175
- //#endregion
176
- //#region src/minimalEdit.ts
177
- /**
178
- * Compute the minimal middle replacement between two UTF-16 strings.
179
- * Returns null when prev === next (no edits required).
180
- */
181
- function computeMinimalEdit(prev, next) {
182
- if (prev === next) return null;
183
- let start = 0;
184
- const minLen = Math.min(prev.length, next.length);
185
- while (start < minLen && prev.charCodeAt(start) === next.charCodeAt(start)) start++;
186
- let endPrev = prev.length - 1;
187
- let endNext = next.length - 1;
188
- while (endPrev >= start && endNext >= start && prev.charCodeAt(endPrev) === next.charCodeAt(endNext)) {
189
- endPrev--;
190
- endNext--;
191
- }
192
- return {
193
- start,
194
- endPrevIncl: endPrev,
195
- endNextIncl: endNext,
196
- replaceText: next.slice(start, endNext + 1)
197
- };
198
- }
199
-
200
- //#endregion
201
- //#region src/monaco-shim.ts
202
- var monaco_shim_exports = {};
203
- __export(monaco_shim_exports, { default: () => monaco });
204
- import * as import_monaco_editor_esm_vs_editor_editor_api from "monaco-editor/esm/vs/editor/editor.api";
205
- __reExport(monaco_shim_exports, import_monaco_editor_esm_vs_editor_editor_api);
206
- const monaco = _monaco;
207
-
208
- //#endregion
209
- //#region src/utils/logger.ts
210
- let seq = 0;
211
- const DEBUG = (() => {
212
- if (typeof window !== "undefined" && window.__STREAM_MONACO_DEBUG__ !== void 0) return Boolean(window.__STREAM_MONACO_DEBUG__);
213
- return false;
214
- })();
215
- function log(tag, ...args) {
216
- if (!DEBUG) return;
217
- seq += 1;
218
- const id = `#${seq}`;
219
- const ts = typeof performance !== "undefined" && performance.now ? performance.now().toFixed(1) : Date.now();
220
- console.warn(`${id} [${tag}] @${ts}ms`, ...args);
221
- }
222
- function error(tag, ...args) {
223
- if (!DEBUG) return;
224
- console.error(`[${tag}]`, ...args);
225
- }
226
-
227
- //#endregion
228
- //#region src/utils/height.ts
229
- function createHeightManager(container, computeNext) {
230
- let raf = null;
231
- let debounceTimer = null;
232
- let lastApplied = -1;
233
- let suppressed = false;
234
- const HYSTERESIS_PX = 12;
235
- const DEBOUNCE_MS = 0;
236
- function apply() {
237
- const next = computeNext();
238
- if (next == null) return;
239
- log("heightManager", "computeNext ->", {
240
- next,
241
- lastApplied
242
- });
243
- if (!Number.isFinite(next) || next <= 0) {
244
- log("heightManager", "invalid next height, ignoring", next);
245
- return;
246
- }
247
- if (lastApplied !== -1 && Math.abs(next - lastApplied) <= HYSTERESIS_PX) return;
248
- if (next === lastApplied) return;
249
- suppressed = true;
250
- container.style.height = `${next}px`;
251
- lastApplied = next;
252
- log("heightManager", "applied height ->", next);
253
- queueMicrotask(() => {
254
- suppressed = false;
255
- });
256
- }
257
- function scheduleApply() {
258
- if (debounceTimer != null) {
259
- clearTimeout(debounceTimer);
260
- debounceTimer = null;
261
- }
262
- if (DEBOUNCE_MS === 0) {
263
- if (raf != null) return;
264
- raf = requestAnimationFrame(() => {
265
- raf = null;
266
- apply();
267
- });
268
- return;
269
- }
270
- debounceTimer = setTimeout(() => {
271
- debounceTimer = null;
272
- if (raf != null) return;
273
- raf = requestAnimationFrame(() => {
274
- raf = null;
275
- apply();
276
- });
277
- }, DEBOUNCE_MS);
278
- }
279
- function update() {
280
- scheduleApply();
281
- }
282
- function dispose() {
283
- if (raf != null) {
284
- cancelAnimationFrame(raf);
285
- raf = null;
286
- }
287
- if (debounceTimer != null) {
288
- clearTimeout(debounceTimer);
289
- debounceTimer = null;
290
- }
291
- }
292
- function isSuppressed() {
293
- return suppressed;
294
- }
295
- function getLastApplied() {
296
- return lastApplied;
297
- }
298
- return {
299
- update,
300
- dispose,
301
- isSuppressed,
302
- getLastApplied
303
- };
304
- }
305
-
306
- //#endregion
307
- //#region src/utils/raf.ts
308
- /**
309
- * Create a per-instance RAF scheduler that coalesces tasks by "kind" within
310
- * the same instance. Instances are isolated so different editors won't
311
- * cancel each other's scheduled work.
312
- */
313
- function createRafScheduler(timeSource) {
314
- const ids = {};
315
- const ts = timeSource ?? {
316
- requestAnimationFrame: (cb) => requestAnimationFrame(cb),
317
- cancelAnimationFrame: (id) => cancelAnimationFrame(id)
318
- };
319
- function schedule(kind, cb) {
320
- const existing = ids[kind];
321
- if (existing != null) ts.cancelAnimationFrame(existing);
322
- ids[kind] = ts.requestAnimationFrame((t) => {
323
- ids[kind] = null;
324
- cb(t);
325
- });
326
- }
327
- function cancel(kind) {
328
- const id = ids[kind];
329
- if (id != null) {
330
- ts.cancelAnimationFrame(id);
331
- ids[kind] = null;
332
- }
333
- }
334
- return {
335
- schedule,
336
- cancel
337
- };
338
- }
339
-
340
- //#endregion
341
- //#region src/utils/scroll.ts
342
- function createScrollWatcherForEditor(ed, opts) {
343
- var _ed$getScrollTop, _ed$onDidScrollChange;
344
- const initial = ((_ed$getScrollTop = ed.getScrollTop) === null || _ed$getScrollTop === void 0 ? void 0 : _ed$getScrollTop.call(ed)) ?? 0;
345
- opts.setLast(initial);
346
- log("scrollWatcher", "initial scrollTop=", initial);
347
- let suppressedExternally = false;
348
- const THRESHOLD_PX = 6;
349
- let domNode = null;
350
- let interactionListener = null;
351
- const listener = (e) => {
352
- var _ed$getScrollTop2;
353
- if (suppressedExternally) {
354
- log("scrollWatcher", "suppressedExternally, ignoring event");
355
- return;
356
- }
357
- 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;
358
- const delta = currentTop - opts.getLast();
359
- opts.setLast(currentTop);
360
- if (Math.abs(delta) < THRESHOLD_PX) {
361
- log("scrollWatcher", "small delta ignored", delta);
362
- try {
363
- const scrollHeight = typeof ed.getScrollHeight === "function" ? ed.getScrollHeight() : void 0;
364
- const li = typeof ed.getLayoutInfo === "function" ? ed.getLayoutInfo() : void 0;
365
- const viewportH = (li === null || li === void 0 ? void 0 : li.height) ?? void 0;
366
- if (typeof scrollHeight === "number" && typeof viewportH === "number") {
367
- const distance = scrollHeight - (currentTop + viewportH);
368
- if (distance <= Math.max(THRESHOLD_PX, 0)) {
369
- log("scrollWatcher", "small delta but at bottom, maybe resume", { distance });
370
- opts.onMaybeResume();
371
- }
372
- }
373
- } catch {}
374
- return;
375
- }
376
- log("scrollWatcher", "delta=", delta, "currentTop=", currentTop);
377
- if (delta < 0) {
378
- log("scrollWatcher", "pause detected delta=", delta);
379
- opts.onPause();
380
- return;
381
- }
382
- log("scrollWatcher", "maybe resume delta=", delta);
383
- opts.onMaybeResume();
384
- };
385
- const disp = ((_ed$onDidScrollChange = ed.onDidScrollChange) === null || _ed$onDidScrollChange === void 0 ? void 0 : _ed$onDidScrollChange.call(ed, listener)) ?? null;
386
- const api = {
387
- dispose() {
388
- try {
389
- if (disp && typeof disp.dispose === "function") disp.dispose();
390
- else if (typeof disp === "function") disp();
391
- } catch {}
392
- log("scrollWatcher", "dispose");
393
- },
394
- setSuppressed(v) {
395
- const newVal = !!v;
396
- if (newVal === suppressedExternally) return;
397
- suppressedExternally = newVal;
398
- log("scrollWatcher", "setSuppressed =>", suppressedExternally);
399
- try {
400
- if (!domNode && typeof ed.getDomNode === "function") domNode = ed.getDomNode();
401
- if (suppressedExternally && domNode) {
402
- if (!interactionListener) {
403
- interactionListener = () => {
404
- try {
405
- var _ed$getScrollTop3;
406
- log("scrollWatcher", "user interaction detected while suppressed, cancelling suppression");
407
- opts.onPause();
408
- suppressedExternally = false;
409
- const cur = ((_ed$getScrollTop3 = ed.getScrollTop) === null || _ed$getScrollTop3 === void 0 ? void 0 : _ed$getScrollTop3.call(ed)) ?? 0;
410
- opts.setLast(cur);
411
- try {
412
- const scrollHeight = typeof ed.getScrollHeight === "function" ? ed.getScrollHeight() : void 0;
413
- const li = typeof ed.getLayoutInfo === "function" ? ed.getLayoutInfo() : void 0;
414
- const viewportH = (li === null || li === void 0 ? void 0 : li.height) ?? void 0;
415
- if (typeof scrollHeight === "number" && typeof viewportH === "number") {
416
- const distance = scrollHeight - (cur + viewportH);
417
- if (distance <= Math.max(THRESHOLD_PX, 0)) {
418
- log("scrollWatcher", "interaction moved to bottom, maybe resume", { distance });
419
- opts.onMaybeResume();
420
- }
421
- }
422
- } catch {}
423
- if (domNode && interactionListener) {
424
- domNode.removeEventListener("wheel", interactionListener, { passive: true });
425
- domNode.removeEventListener("pointerdown", interactionListener);
426
- domNode.removeEventListener("touchstart", interactionListener);
427
- }
428
- interactionListener = null;
429
- } catch {}
430
- };
431
- domNode.addEventListener("wheel", interactionListener, { passive: true });
432
- domNode.addEventListener("pointerdown", interactionListener);
433
- domNode.addEventListener("touchstart", interactionListener);
434
- }
435
- } else if (domNode && interactionListener) {
436
- domNode.removeEventListener("wheel", interactionListener, { passive: true });
437
- domNode.removeEventListener("pointerdown", interactionListener);
438
- domNode.removeEventListener("touchstart", interactionListener);
439
- interactionListener = null;
440
- }
441
- } catch {}
442
- }
443
- };
444
- return api;
445
- }
446
-
447
- //#endregion
448
- //#region src/core/DiffEditorManager.ts
449
- var DiffEditorManager = class {
450
- diffEditorView = null;
451
- originalModel = null;
452
- modifiedModel = null;
453
- lastContainer = null;
454
- lastKnownOriginalCode = null;
455
- lastKnownModifiedCode = null;
456
- lastKnownModifiedLineCount = null;
457
- pendingDiffUpdate = null;
458
- shouldAutoScrollDiff = true;
459
- diffScrollWatcher = null;
460
- lastScrollTopDiff = 0;
461
- _hasScrollBar = false;
462
- cachedScrollHeightDiff = null;
463
- cachedLineHeightDiff = null;
464
- cachedComputedHeightDiff = null;
465
- lastKnownModifiedDirty = false;
466
- measureViewportDiff() {
467
- var _me$getLayoutInfo, _me$getScrollTop, _me$getScrollHeight;
468
- if (!this.diffEditorView) return null;
469
- const me = this.diffEditorView.getModifiedEditor();
470
- const li = ((_me$getLayoutInfo = me.getLayoutInfo) === null || _me$getLayoutInfo === void 0 ? void 0 : _me$getLayoutInfo.call(me)) ?? null;
471
- const lineHeight = this.cachedLineHeightDiff ?? me.getOption(monaco_shim_exports.editor.EditorOption.lineHeight);
472
- const scrollTop = ((_me$getScrollTop = me.getScrollTop) === null || _me$getScrollTop === void 0 ? void 0 : _me$getScrollTop.call(me)) ?? this.lastScrollTopDiff ?? 0;
473
- 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;
474
- const computedHeight = this.cachedComputedHeightDiff ?? this.computedHeight();
475
- this.cachedLineHeightDiff = lineHeight;
476
- this.cachedScrollHeightDiff = scrollHeight;
477
- this.cachedComputedHeightDiff = computedHeight;
478
- this.lastScrollTopDiff = scrollTop;
479
- return {
480
- me,
481
- li,
482
- lineHeight,
483
- scrollTop,
484
- scrollHeight,
485
- computedHeight
486
- };
487
- }
488
- lastRevealLineDiff = null;
489
- revealTicketDiff = 0;
490
- revealDebounceIdDiff = null;
491
- revealDebounceMs = defaultRevealDebounceMs;
492
- revealIdleTimerIdDiff = null;
493
- revealStrategyOption;
494
- revealBatchOnIdleMsOption;
495
- scrollWatcherSuppressionMs = 500;
496
- diffScrollWatcherSuppressionTimer = null;
497
- appendBufferOriginalDiff = [];
498
- appendBufferModifiedDiff = [];
499
- appendBufferDiffScheduled = false;
500
- diffUpdateThrottleMs = 50;
501
- lastAppendFlushTimeDiff = 0;
502
- appendFlushThrottleTimerDiff = null;
503
- rafScheduler = createRafScheduler();
504
- diffHeightManager = null;
505
- constructor(options, maxHeightValue, maxHeightCSS, autoScrollOnUpdate, autoScrollInitial, autoScrollThresholdPx, autoScrollThresholdLines, diffAutoScroll, revealDebounceMsOption) {
506
- this.options = options;
507
- this.maxHeightValue = maxHeightValue;
508
- this.maxHeightCSS = maxHeightCSS;
509
- this.autoScrollOnUpdate = autoScrollOnUpdate;
510
- this.autoScrollInitial = autoScrollInitial;
511
- this.autoScrollThresholdPx = autoScrollThresholdPx;
512
- this.autoScrollThresholdLines = autoScrollThresholdLines;
513
- this.diffAutoScroll = diffAutoScroll;
514
- this.revealDebounceMsOption = revealDebounceMsOption;
515
- }
516
- scheduleFlushAppendBufferDiff() {
517
- if (this.appendBufferDiffScheduled) return;
518
- this.appendBufferDiffScheduled = true;
519
- const schedule = () => {
520
- this.rafScheduler.schedule("appendDiff", () => this.flushAppendBufferDiff());
521
- };
522
- const throttle = this.diffUpdateThrottleMs;
523
- if (!throttle) {
524
- schedule();
525
- return;
526
- }
527
- const now = Date.now();
528
- const since = now - this.lastAppendFlushTimeDiff;
529
- if (since >= throttle) {
530
- schedule();
531
- return;
532
- }
533
- if (this.appendFlushThrottleTimerDiff != null) return;
534
- const wait = throttle - since;
535
- this.appendFlushThrottleTimerDiff = setTimeout(() => {
536
- this.appendFlushThrottleTimerDiff = null;
537
- schedule();
538
- }, wait);
539
- }
540
- flushOriginalAppendBufferSync() {
541
- if (!this.originalModel) return;
542
- if (this.appendBufferOriginalDiff.length === 0) return;
543
- this.rafScheduler.cancel("appendDiff");
544
- this.appendBufferDiffScheduled = false;
545
- const text = this.appendBufferOriginalDiff.join("");
546
- this.appendBufferOriginalDiff.length = 0;
547
- if (!text) return;
548
- this.appendToModel(this.originalModel, text);
549
- }
550
- computedHeight() {
551
- var _originalEditor$getMo, _modifiedEditor$getMo, _originalEditor$getSc, _modifiedEditor$getSc;
552
- if (!this.diffEditorView) return Math.min(1 * 18 + padding, this.maxHeightValue);
553
- const modifiedEditor = this.diffEditorView.getModifiedEditor();
554
- const originalEditor = this.diffEditorView.getOriginalEditor();
555
- const lineHeight = modifiedEditor.getOption(monaco_shim_exports.editor.EditorOption.lineHeight);
556
- const oCount = ((_originalEditor$getMo = originalEditor.getModel()) === null || _originalEditor$getMo === void 0 ? void 0 : _originalEditor$getMo.getLineCount()) ?? 1;
557
- const mCount = ((_modifiedEditor$getMo = modifiedEditor.getModel()) === null || _modifiedEditor$getMo === void 0 ? void 0 : _modifiedEditor$getMo.getLineCount()) ?? 1;
558
- const lineCount = Math.max(oCount, mCount);
559
- const fromLines = lineCount * lineHeight + padding;
560
- 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);
561
- const desired = Math.max(fromLines, scrollH);
562
- return Math.min(desired, this.maxHeightValue);
563
- }
564
- isOverflowAutoDiff() {
565
- return !!this.lastContainer && this.lastContainer.style.overflow === "auto";
566
- }
567
- shouldPerformImmediateRevealDiff() {
568
- return this.autoScrollOnUpdate && this.shouldAutoScrollDiff && this.hasVerticalScrollbarModified() && this.isOverflowAutoDiff();
569
- }
570
- suppressScrollWatcherDiff(ms) {
571
- if (!this.diffScrollWatcher || typeof this.diffScrollWatcher.setSuppressed !== "function") return;
572
- if (this.diffScrollWatcherSuppressionTimer != null) {
573
- clearTimeout(this.diffScrollWatcherSuppressionTimer);
574
- this.diffScrollWatcherSuppressionTimer = null;
575
- }
576
- this.diffScrollWatcher.setSuppressed(true);
577
- this.diffScrollWatcherSuppressionTimer = setTimeout(() => {
578
- try {
579
- this.diffScrollWatcher.setSuppressed(false);
580
- } catch {}
581
- this.diffScrollWatcherSuppressionTimer = null;
582
- }, ms);
583
- }
584
- hasVerticalScrollbarModified() {
585
- if (!this.diffEditorView) return false;
586
- if (this._hasScrollBar) return true;
587
- const m = this.measureViewportDiff();
588
- if (!m) return false;
589
- const epsilon = Math.max(2, Math.round(m.lineHeight / 8));
590
- return this._hasScrollBar = m.scrollHeight > m.computedHeight + Math.max(padding / 2, epsilon);
591
- }
592
- userIsNearBottomDiff() {
593
- if (!this.diffEditorView) return true;
594
- const m = this.measureViewportDiff();
595
- if (!m || !m.li) return true;
596
- const lineThreshold = (this.autoScrollThresholdLines ?? 0) * m.lineHeight;
597
- const threshold = Math.max(lineThreshold || 0, this.autoScrollThresholdPx || 0);
598
- const distance = m.scrollHeight - (m.scrollTop + m.li.height);
599
- return distance <= threshold;
600
- }
601
- maybeScrollDiffToBottom(targetLine, prevLineOverride) {
602
- this.rafScheduler.schedule("maybe-scroll-diff", () => {
603
- log("diff", "maybeScrollDiffToBottom called", {
604
- targetLine,
605
- prevLineOverride,
606
- diffAutoScroll: this.diffAutoScroll,
607
- autoScrollOnUpdate: this.autoScrollOnUpdate,
608
- shouldAutoScrollDiff: this.shouldAutoScrollDiff
609
- });
610
- if (!this.diffEditorView) return;
611
- const hasV = this.hasVerticalScrollbarModified();
612
- log("diff", "hasVerticalScrollbarModified ->", hasV);
613
- if (!(this.diffAutoScroll && this.autoScrollOnUpdate && this.shouldAutoScrollDiff && hasV)) return;
614
- const me = this.diffEditorView.getModifiedEditor();
615
- const model = me.getModel();
616
- const currentLine = (model === null || model === void 0 ? void 0 : model.getLineCount()) ?? 1;
617
- const line = targetLine ?? currentLine;
618
- const prevLine = typeof prevLineOverride === "number" ? prevLineOverride : this.lastKnownModifiedLineCount ?? -1;
619
- log("diff", "scroll metrics", {
620
- prevLine,
621
- currentLine,
622
- line,
623
- lastRevealLineDiff: this.lastRevealLineDiff
624
- });
625
- if (prevLine !== -1 && prevLine === currentLine && line === currentLine) return;
626
- if (this.lastRevealLineDiff !== null && this.lastRevealLineDiff === line) return;
627
- const batchMs = this.revealBatchOnIdleMsOption ?? this.options.revealBatchOnIdleMs ?? defaultRevealBatchOnIdleMs;
628
- log("diff", "reveal timing", {
629
- batchMs,
630
- revealDebounceMs: this.revealDebounceMs,
631
- revealDebounceMsOption: this.revealDebounceMsOption
632
- });
633
- if (typeof batchMs === "number" && batchMs > 0) {
634
- if (hasV) {
635
- const ticket$1 = ++this.revealTicketDiff;
636
- log("diff", "has scrollbar -> immediate ticketed reveal", {
637
- ticket: ticket$1,
638
- line
639
- });
640
- this.performRevealDiffTicketed(line, ticket$1);
641
- return;
642
- }
643
- if (this.revealIdleTimerIdDiff != null) clearTimeout(this.revealIdleTimerIdDiff);
644
- const ticket = ++this.revealTicketDiff;
645
- log("diff", "scheduling idle reveal", {
646
- ticket,
647
- batchMs,
648
- line
649
- });
650
- this.revealIdleTimerIdDiff = setTimeout(() => {
651
- this.revealIdleTimerIdDiff = null;
652
- this.performRevealDiffTicketed(line, ticket);
653
- }, batchMs);
654
- return;
655
- }
656
- if (this.revealDebounceIdDiff != null) {
657
- clearTimeout(this.revealDebounceIdDiff);
658
- this.revealDebounceIdDiff = null;
659
- }
660
- const ms = typeof this.revealDebounceMs === "number" && this.revealDebounceMs > 0 ? this.revealDebounceMs : typeof this.revealDebounceMsOption === "number" && this.revealDebounceMsOption > 0 ? this.revealDebounceMsOption : this.revealDebounceMs;
661
- this.revealDebounceIdDiff = setTimeout(() => {
662
- this.revealDebounceIdDiff = null;
663
- const ticket = ++this.revealTicketDiff;
664
- log("diff", "debounced reveal firing", {
665
- ticket,
666
- line
667
- });
668
- this.performRevealDiffTicketed(line, ticket);
669
- }, ms);
670
- this.lastKnownModifiedLineCount = currentLine;
671
- });
672
- }
673
- performRevealDiffTicketed(line, ticket) {
674
- this.rafScheduler.schedule("revealDiff", () => {
675
- var _editor;
676
- if (this.diffScrollWatcher) {
677
- log("diff", "performRevealDiffTicketed - suppressing watcher", {
678
- ticket,
679
- line,
680
- ms: this.scrollWatcherSuppressionMs
681
- });
682
- this.suppressScrollWatcherDiff(this.scrollWatcherSuppressionMs);
683
- }
684
- if (ticket !== this.revealTicketDiff) return;
685
- log("diff", "performRevealDiffTicketed - performing reveal", {
686
- ticket,
687
- line
688
- });
689
- const strategy = this.revealStrategyOption ?? this.options.revealStrategy ?? "centerIfOutside";
690
- const ScrollType = monaco_shim_exports.ScrollType || ((_editor = monaco_shim_exports.editor) === null || _editor === void 0 ? void 0 : _editor.ScrollType);
691
- const smooth = ScrollType && typeof ScrollType.Smooth !== "undefined" ? ScrollType.Smooth : void 0;
692
- try {
693
- const me = this.diffEditorView.getModifiedEditor();
694
- if (strategy === "bottom") if (typeof smooth !== "undefined") me.revealLine(line, smooth);
695
- else me.revealLine(line);
696
- else if (strategy === "center") if (typeof smooth !== "undefined") me.revealLineInCenter(line, smooth);
697
- else me.revealLineInCenter(line);
698
- else if (typeof smooth !== "undefined") me.revealLineInCenterIfOutsideViewport(line, smooth);
699
- else me.revealLineInCenterIfOutsideViewport(line);
700
- } catch {
701
- try {
702
- this.diffEditorView.getModifiedEditor().revealLine(line);
703
- } catch {}
704
- }
705
- this.lastRevealLineDiff = line;
706
- log("diff", "performRevealDiffTicketed - revealed", {
707
- line,
708
- lastRevealLineDiff: this.lastRevealLineDiff
709
- });
710
- try {
711
- var _this$diffEditorView, _this$diffEditorView$, _this$diffEditorView$2;
712
- this.shouldAutoScrollDiff = true;
713
- this.lastScrollTopDiff = ((_this$diffEditorView = this.diffEditorView) === null || _this$diffEditorView === void 0 || (_this$diffEditorView$2 = (_this$diffEditorView$ = _this$diffEditorView.getModifiedEditor()).getScrollTop) === null || _this$diffEditorView$2 === void 0 ? void 0 : _this$diffEditorView$2.call(_this$diffEditorView$)) ?? this.lastScrollTopDiff;
714
- } catch {}
715
- });
716
- }
717
- performImmediateRevealDiff(line, ticket) {
718
- var _editor2;
719
- if (!this.diffEditorView) return;
720
- if (ticket !== this.revealTicketDiff) return;
721
- const ScrollType = monaco_shim_exports.ScrollType || ((_editor2 = monaco_shim_exports.editor) === null || _editor2 === void 0 ? void 0 : _editor2.ScrollType);
722
- const immediate = ScrollType && typeof ScrollType.Immediate !== "undefined" ? ScrollType.Immediate : void 0;
723
- const me = this.diffEditorView.getModifiedEditor();
724
- if (typeof immediate !== "undefined") me.revealLine(line, immediate);
725
- else me.revealLine(line);
726
- this.measureViewportDiff();
727
- log("diff", "performImmediateRevealDiff", {
728
- line,
729
- ticket
730
- });
731
- try {
732
- var _this$diffEditorView2, _this$diffEditorView3, _this$diffEditorView4;
733
- this.shouldAutoScrollDiff = true;
734
- this.lastScrollTopDiff = ((_this$diffEditorView2 = this.diffEditorView) === null || _this$diffEditorView2 === void 0 || (_this$diffEditorView4 = (_this$diffEditorView3 = _this$diffEditorView2.getModifiedEditor()).getScrollTop) === null || _this$diffEditorView4 === void 0 ? void 0 : _this$diffEditorView4.call(_this$diffEditorView3)) ?? this.lastScrollTopDiff;
735
- } catch {}
736
- }
737
- scheduleImmediateRevealAfterLayoutDiff(line) {
738
- const ticket = ++this.revealTicketDiff;
739
- this.rafScheduler.schedule("immediate-reveal-diff", async () => {
740
- const target = this.diffEditorView && this.diffHeightManager ? Math.min(this.computedHeight(), this.maxHeightValue) : -1;
741
- if (target !== -1 && this.diffHeightManager) {
742
- if (this.lastContainer) this.lastContainer.style.height = `${target}px`;
743
- await this.waitForHeightAppliedDiff(target);
744
- }
745
- this.performImmediateRevealDiff(line, ticket);
746
- });
747
- }
748
- waitForHeightAppliedDiff(target, timeoutMs = 500) {
749
- return new Promise((resolve) => {
750
- const start = typeof performance !== "undefined" && performance.now ? performance.now() : Date.now();
751
- const check = () => {
752
- const applied = this.lastContainer ? Number.parseFloat((this.lastContainer.style.height || "").replace("px", "")) || 0 : -1;
753
- if (applied >= target - 1) {
754
- resolve();
755
- return;
756
- }
757
- if ((typeof performance !== "undefined" && performance.now ? performance.now() : Date.now()) - start > timeoutMs) {
758
- resolve();
759
- return;
760
- }
761
- requestAnimationFrame(check);
762
- };
763
- check();
764
- });
765
- }
766
- async createDiffEditor(container, originalCode, modifiedCode, language, currentTheme) {
767
- var _me$getScrollHeight2, _me$getOption, _oEditor$onDidContent, _mEditor$onDidContent;
768
- this.cleanup();
769
- this.lastContainer = container;
770
- container.style.overflow = "hidden";
771
- container.style.maxHeight = this.maxHeightCSS;
772
- const lang = processedLanguage(language) || language;
773
- this.originalModel = monaco_shim_exports.editor.createModel(originalCode, lang);
774
- this.modifiedModel = monaco_shim_exports.editor.createModel(modifiedCode, lang);
775
- this.diffEditorView = monaco_shim_exports.editor.createDiffEditor(container, {
776
- automaticLayout: true,
777
- scrollBeyondLastLine: false,
778
- renderSideBySide: true,
779
- originalEditable: false,
780
- readOnly: this.options.readOnly ?? true,
781
- minimap: { enabled: false },
782
- theme: currentTheme,
783
- contextmenu: false,
784
- scrollbar: {
785
- ...defaultScrollbar,
786
- ...this.options.scrollbar || {}
787
- },
788
- ...this.options
789
- });
790
- monaco_shim_exports.editor.setTheme(currentTheme);
791
- this.diffEditorView.setModel({
792
- original: this.originalModel,
793
- modified: this.modifiedModel
794
- });
795
- this.lastKnownOriginalCode = originalCode;
796
- this.lastKnownModifiedCode = modifiedCode;
797
- this.diffUpdateThrottleMs = this.options.diffUpdateThrottleMs ?? 50;
798
- this.shouldAutoScrollDiff = !!(this.autoScrollInitial && this.diffAutoScroll);
799
- if (this.diffScrollWatcher) {
800
- this.diffScrollWatcher.dispose();
801
- this.diffScrollWatcher = null;
802
- }
803
- if (this.diffAutoScroll) {
804
- const me$1 = this.diffEditorView.getModifiedEditor();
805
- this.diffScrollWatcher = createScrollWatcherForEditor(me$1, {
806
- onPause: () => {
807
- this.shouldAutoScrollDiff = false;
808
- },
809
- onMaybeResume: () => {
810
- this.rafScheduler.schedule("maybe-resume-diff", () => {
811
- this.shouldAutoScrollDiff = this.userIsNearBottomDiff();
812
- });
813
- },
814
- getLast: () => this.lastScrollTopDiff,
815
- setLast: (v) => {
816
- this.lastScrollTopDiff = v;
817
- }
818
- });
819
- }
820
- log("diff", "createDiffEditor", {
821
- autoScrollInitial: this.autoScrollInitial,
822
- diffAutoScroll: this.diffAutoScroll
823
- });
824
- const MIN_VISIBLE_HEIGHT = Math.min(120, this.maxHeightValue);
825
- container.style.minHeight = `${MIN_VISIBLE_HEIGHT}px`;
826
- if (this.diffHeightManager) {
827
- this.diffHeightManager.dispose();
828
- this.diffHeightManager = null;
829
- }
830
- this.diffHeightManager = createHeightManager(container, () => this.computedHeight());
831
- this.diffHeightManager.update();
832
- const initialComputed = this.computedHeight();
833
- if (initialComputed >= this.maxHeightValue - 1) {
834
- container.style.height = `${this.maxHeightValue}px`;
835
- container.style.overflow = "auto";
836
- }
837
- const me = this.diffEditorView.getModifiedEditor();
838
- this.cachedScrollHeightDiff = ((_me$getScrollHeight2 = me.getScrollHeight) === null || _me$getScrollHeight2 === void 0 ? void 0 : _me$getScrollHeight2.call(me)) ?? null;
839
- this.cachedLineHeightDiff = ((_me$getOption = me.getOption) === null || _me$getOption === void 0 ? void 0 : _me$getOption.call(me, monaco_shim_exports.editor.EditorOption.lineHeight)) ?? null;
840
- this.cachedComputedHeightDiff = this.computedHeight();
841
- const oEditor = this.diffEditorView.getOriginalEditor();
842
- const mEditor = this.diffEditorView.getModifiedEditor();
843
- (_oEditor$onDidContent = oEditor.onDidContentSizeChange) === null || _oEditor$onDidContent === void 0 || _oEditor$onDidContent.call(oEditor, () => {
844
- this._hasScrollBar = false;
845
- this.rafScheduler.schedule("content-size-change-diff", () => {
846
- var _oEditor$getScrollHei, _oEditor$getOption, _this$diffHeightManag, _this$diffHeightManag2;
847
- this.cachedScrollHeightDiff = ((_oEditor$getScrollHei = oEditor.getScrollHeight) === null || _oEditor$getScrollHei === void 0 ? void 0 : _oEditor$getScrollHei.call(oEditor)) ?? this.cachedScrollHeightDiff;
848
- 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;
849
- this.cachedComputedHeightDiff = this.computedHeight();
850
- if ((_this$diffHeightManag = this.diffHeightManager) === null || _this$diffHeightManag === void 0 ? void 0 : _this$diffHeightManag.isSuppressed()) return;
851
- (_this$diffHeightManag2 = this.diffHeightManager) === null || _this$diffHeightManag2 === void 0 || _this$diffHeightManag2.update();
852
- const computed$2 = this.computedHeight();
853
- if (this.lastContainer) {
854
- const prevOverflow = this.lastContainer.style.overflow;
855
- const newOverflow = computed$2 >= this.maxHeightValue - 1 ? "auto" : "hidden";
856
- if (prevOverflow !== newOverflow) {
857
- this.lastContainer.style.overflow = newOverflow;
858
- if (newOverflow === "auto" && this.shouldAutoScrollDiff) {
859
- var _this$modifiedModel;
860
- this.maybeScrollDiffToBottom((_this$modifiedModel = this.modifiedModel) === null || _this$modifiedModel === void 0 ? void 0 : _this$modifiedModel.getLineCount());
861
- }
862
- }
863
- }
864
- });
865
- });
866
- (_mEditor$onDidContent = mEditor.onDidContentSizeChange) === null || _mEditor$onDidContent === void 0 || _mEditor$onDidContent.call(mEditor, () => {
867
- this._hasScrollBar = false;
868
- this.rafScheduler.schedule("content-size-change-diff", () => {
869
- var _mEditor$getScrollHei, _mEditor$getOption, _this$diffHeightManag3, _this$diffHeightManag4;
870
- this.cachedScrollHeightDiff = ((_mEditor$getScrollHei = mEditor.getScrollHeight) === null || _mEditor$getScrollHei === void 0 ? void 0 : _mEditor$getScrollHei.call(mEditor)) ?? this.cachedScrollHeightDiff;
871
- 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;
872
- this.cachedComputedHeightDiff = this.computedHeight();
873
- if ((_this$diffHeightManag3 = this.diffHeightManager) === null || _this$diffHeightManag3 === void 0 ? void 0 : _this$diffHeightManag3.isSuppressed()) return;
874
- (_this$diffHeightManag4 = this.diffHeightManager) === null || _this$diffHeightManag4 === void 0 || _this$diffHeightManag4.update();
875
- const computed$2 = this.computedHeight();
876
- if (this.lastContainer) {
877
- const prevOverflow = this.lastContainer.style.overflow;
878
- const newOverflow = computed$2 >= this.maxHeightValue - 1 ? "auto" : "hidden";
879
- if (prevOverflow !== newOverflow) {
880
- this.lastContainer.style.overflow = newOverflow;
881
- if (newOverflow === "auto" && this.shouldAutoScrollDiff) {
882
- var _this$modifiedModel2;
883
- this.maybeScrollDiffToBottom((_this$modifiedModel2 = this.modifiedModel) === null || _this$modifiedModel2 === void 0 ? void 0 : _this$modifiedModel2.getLineCount());
884
- }
885
- }
886
- }
887
- });
888
- });
889
- mEditor.onDidChangeModelContent(() => {
890
- this.lastKnownModifiedDirty = true;
891
- this.rafScheduler.schedule("sync-last-known-modified", () => this.syncLastKnownModified());
892
- });
893
- this.maybeScrollDiffToBottom(this.modifiedModel.getLineCount(), this.lastKnownModifiedLineCount ?? void 0);
894
- return this.diffEditorView;
895
- }
896
- updateDiff(originalCode, modifiedCode, codeLanguage) {
897
- if (!this.diffEditorView || !this.originalModel || !this.modifiedModel) return;
898
- const plang = codeLanguage ? processedLanguage(codeLanguage) : void 0;
899
- if (plang && (this.originalModel.getLanguageId() !== plang || this.modifiedModel.getLanguageId() !== plang)) {
900
- this.pendingDiffUpdate = {
901
- original: originalCode,
902
- modified: modifiedCode,
903
- lang: codeLanguage
904
- };
905
- this.rafScheduler.schedule("diff", () => this.flushPendingDiffUpdate());
906
- return;
907
- }
908
- if (this.lastKnownOriginalCode == null) this.lastKnownOriginalCode = this.originalModel.getValue();
909
- if (this.lastKnownModifiedCode == null) this.lastKnownModifiedCode = this.modifiedModel.getValue();
910
- const prevO = this.lastKnownOriginalCode;
911
- const prevM = this.lastKnownModifiedCode;
912
- let didImmediate = false;
913
- if (originalCode !== prevO && originalCode.startsWith(prevO)) {
914
- this.appendOriginal(originalCode.slice(prevO.length));
915
- this.lastKnownOriginalCode = originalCode;
916
- didImmediate = true;
917
- }
918
- if (modifiedCode !== prevM && modifiedCode.startsWith(prevM)) {
919
- this.appendModified(modifiedCode.slice(prevM.length));
920
- this.lastKnownModifiedCode = modifiedCode;
921
- didImmediate = true;
922
- }
923
- if (originalCode !== this.lastKnownOriginalCode || modifiedCode !== this.lastKnownModifiedCode) {
924
- this.pendingDiffUpdate = {
925
- original: originalCode,
926
- modified: modifiedCode
927
- };
928
- this.rafScheduler.schedule("diff", () => this.flushPendingDiffUpdate());
929
- } else if (didImmediate) {}
930
- }
931
- updateOriginal(newCode, codeLanguage) {
932
- if (!this.diffEditorView || !this.originalModel) return;
933
- if (codeLanguage) {
934
- const lang = processedLanguage(codeLanguage);
935
- if (lang && this.originalModel.getLanguageId() !== lang) monaco_shim_exports.editor.setModelLanguage(this.originalModel, lang);
936
- }
937
- const prev = this.lastKnownOriginalCode ?? this.originalModel.getValue();
938
- if (prev === newCode) return;
939
- if (newCode.startsWith(prev) && prev.length < newCode.length) this.appendOriginal(newCode.slice(prev.length), codeLanguage);
940
- else {
941
- this.flushOriginalAppendBufferSync();
942
- this.applyMinimalEditToModel(this.originalModel, prev, newCode);
943
- }
944
- this.lastKnownOriginalCode = newCode;
945
- }
946
- updateModified(newCode, codeLanguage) {
947
- if (!this.diffEditorView || !this.modifiedModel) return;
948
- if (codeLanguage) {
949
- const lang = processedLanguage(codeLanguage);
950
- if (lang && this.modifiedModel.getLanguageId() !== lang) monaco_shim_exports.editor.setModelLanguage(this.modifiedModel, lang);
951
- }
952
- const prev = this.lastKnownModifiedCode ?? this.modifiedModel.getValue();
953
- if (prev === newCode) return;
954
- if (newCode.startsWith(prev) && prev.length < newCode.length) this.appendModified(newCode.slice(prev.length), codeLanguage);
955
- else {
956
- this.flushModifiedAppendBufferSync();
957
- const prevAfterFlush = this.modifiedModel.getValue();
958
- const prevLine = this.modifiedModel.getLineCount();
959
- this.applyMinimalEditToModel(this.modifiedModel, prevAfterFlush, newCode);
960
- const newLine = this.modifiedModel.getLineCount();
961
- if (newLine !== prevLine) {
962
- const shouldImmediate = this.shouldPerformImmediateRevealDiff();
963
- if (shouldImmediate) this.suppressScrollWatcherDiff(this.scrollWatcherSuppressionMs + 800);
964
- const computed$2 = this.computedHeight();
965
- if (computed$2 >= this.maxHeightValue - 1 && this.lastContainer) {
966
- this.lastContainer.style.height = `${this.maxHeightValue}px`;
967
- this.lastContainer.style.overflow = "auto";
968
- }
969
- if (shouldImmediate) this.scheduleImmediateRevealAfterLayoutDiff(newLine);
970
- else this.maybeScrollDiffToBottom(newLine, prevLine);
971
- if (this.autoScrollOnUpdate && this.shouldAutoScrollDiff) try {
972
- var _editor3, _me2$getModel, _me2$getScrollTop;
973
- const ScrollType = monaco_shim_exports.ScrollType || ((_editor3 = monaco_shim_exports.editor) === null || _editor3 === void 0 ? void 0 : _editor3.ScrollType);
974
- const immediate = ScrollType && typeof ScrollType.Immediate !== "undefined" ? ScrollType.Immediate : void 0;
975
- const me2 = this.diffEditorView.getModifiedEditor();
976
- const targetLine = ((_me2$getModel = me2.getModel()) === null || _me2$getModel === void 0 ? void 0 : _me2$getModel.getLineCount()) ?? newLine;
977
- if (typeof immediate !== "undefined") me2.revealLine(targetLine, immediate);
978
- else me2.revealLine(targetLine);
979
- this.lastRevealLineDiff = targetLine;
980
- this.shouldAutoScrollDiff = true;
981
- this.lastScrollTopDiff = ((_me2$getScrollTop = me2.getScrollTop) === null || _me2$getScrollTop === void 0 ? void 0 : _me2$getScrollTop.call(me2)) ?? this.lastScrollTopDiff;
982
- } catch {}
983
- }
984
- }
985
- this.lastKnownModifiedCode = newCode;
986
- }
987
- appendOriginal(appendText, codeLanguage) {
988
- if (!this.diffEditorView || !this.originalModel || !appendText) return;
989
- if (codeLanguage) {
990
- const lang = processedLanguage(codeLanguage);
991
- if (lang && this.originalModel.getLanguageId() !== lang) monaco_shim_exports.editor.setModelLanguage(this.originalModel, lang);
992
- }
993
- this.appendBufferOriginalDiff.push(appendText);
994
- this.scheduleFlushAppendBufferDiff();
995
- }
996
- appendModified(appendText, codeLanguage) {
997
- if (!this.diffEditorView || !this.modifiedModel || !appendText) return;
998
- if (codeLanguage) {
999
- const lang = processedLanguage(codeLanguage);
1000
- if (lang && this.modifiedModel.getLanguageId() !== lang) monaco_shim_exports.editor.setModelLanguage(this.modifiedModel, lang);
1001
- }
1002
- this.appendBufferModifiedDiff.push(appendText);
1003
- this.scheduleFlushAppendBufferDiff();
1004
- }
1005
- setLanguage(language, languages$1) {
1006
- if (!languages$1.includes(language)) {
1007
- console.warn(`Language "${language}" is not registered. Available languages: ${languages$1.join(", ")}`);
1008
- return;
1009
- }
1010
- if (this.originalModel && this.originalModel.getLanguageId() !== language) monaco_shim_exports.editor.setModelLanguage(this.originalModel, language);
1011
- if (this.modifiedModel && this.modifiedModel.getLanguageId() !== language) monaco_shim_exports.editor.setModelLanguage(this.modifiedModel, language);
1012
- }
1013
- getDiffEditorView() {
1014
- return this.diffEditorView;
1015
- }
1016
- getDiffModels() {
1017
- return {
1018
- original: this.originalModel,
1019
- modified: this.modifiedModel
1020
- };
1021
- }
1022
- cleanup() {
1023
- this.rafScheduler.cancel("diff");
1024
- this.pendingDiffUpdate = null;
1025
- this.rafScheduler.cancel("appendDiff");
1026
- this.appendBufferDiffScheduled = false;
1027
- this.appendBufferOriginalDiff.length = 0;
1028
- this.appendBufferModifiedDiff.length = 0;
1029
- if (this.appendFlushThrottleTimerDiff != null) {
1030
- clearTimeout(this.appendFlushThrottleTimerDiff);
1031
- this.appendFlushThrottleTimerDiff = null;
1032
- }
1033
- this.rafScheduler.cancel("content-size-change-diff");
1034
- this.rafScheduler.cancel("sync-last-known-modified");
1035
- if (this.diffScrollWatcher) {
1036
- this.diffScrollWatcher.dispose();
1037
- this.diffScrollWatcher = null;
1038
- }
1039
- if (this.diffHeightManager) {
1040
- this.diffHeightManager.dispose();
1041
- this.diffHeightManager = null;
1042
- }
1043
- if (this.diffEditorView) {
1044
- this.diffEditorView.dispose();
1045
- this.diffEditorView = null;
1046
- }
1047
- if (this.originalModel) {
1048
- this.originalModel.dispose();
1049
- this.originalModel = null;
1050
- }
1051
- if (this.modifiedModel) {
1052
- this.modifiedModel.dispose();
1053
- this.modifiedModel = null;
1054
- }
1055
- this.lastKnownOriginalCode = null;
1056
- this.lastKnownModifiedCode = null;
1057
- if (this.lastContainer) {
1058
- this.lastContainer.innerHTML = "";
1059
- this.lastContainer = null;
1060
- }
1061
- if (this.revealDebounceIdDiff != null) {
1062
- clearTimeout(this.revealDebounceIdDiff);
1063
- this.revealDebounceIdDiff = null;
1064
- }
1065
- if (this.revealIdleTimerIdDiff != null) {
1066
- clearTimeout(this.revealIdleTimerIdDiff);
1067
- this.revealIdleTimerIdDiff = null;
1068
- }
1069
- if (this.diffScrollWatcherSuppressionTimer != null) {
1070
- clearTimeout(this.diffScrollWatcherSuppressionTimer);
1071
- this.diffScrollWatcherSuppressionTimer = null;
1072
- }
1073
- this.revealTicketDiff = 0;
1074
- this.lastRevealLineDiff = null;
1075
- }
1076
- safeClean() {
1077
- this.rafScheduler.cancel("diff");
1078
- this.pendingDiffUpdate = null;
1079
- this.rafScheduler.cancel("appendDiff");
1080
- this.appendBufferDiffScheduled = false;
1081
- this.appendBufferOriginalDiff.length = 0;
1082
- this.appendBufferModifiedDiff.length = 0;
1083
- if (this.appendFlushThrottleTimerDiff != null) {
1084
- clearTimeout(this.appendFlushThrottleTimerDiff);
1085
- this.appendFlushThrottleTimerDiff = null;
1086
- }
1087
- if (this.diffScrollWatcher) {
1088
- this.diffScrollWatcher.dispose();
1089
- this.diffScrollWatcher = null;
1090
- }
1091
- this._hasScrollBar = false;
1092
- this.shouldAutoScrollDiff = !!(this.autoScrollInitial && this.diffAutoScroll);
1093
- this.lastScrollTopDiff = 0;
1094
- if (this.diffHeightManager) {
1095
- this.diffHeightManager.dispose();
1096
- this.diffHeightManager = null;
1097
- }
1098
- if (this.revealDebounceIdDiff != null) {
1099
- clearTimeout(this.revealDebounceIdDiff);
1100
- this.revealDebounceIdDiff = null;
1101
- }
1102
- if (this.revealIdleTimerIdDiff != null) {
1103
- clearTimeout(this.revealIdleTimerIdDiff);
1104
- this.revealIdleTimerIdDiff = null;
1105
- }
1106
- if (this.diffScrollWatcherSuppressionTimer != null) {
1107
- clearTimeout(this.diffScrollWatcherSuppressionTimer);
1108
- this.diffScrollWatcherSuppressionTimer = null;
1109
- }
1110
- this.revealTicketDiff = 0;
1111
- this.lastRevealLineDiff = null;
1112
- this.rafScheduler.cancel("content-size-change-diff");
1113
- this.rafScheduler.cancel("sync-last-known-modified");
1114
- }
1115
- syncLastKnownModified() {
1116
- if (!this.diffEditorView || !this.lastKnownModifiedDirty) return;
1117
- try {
1118
- const me = this.diffEditorView.getModifiedEditor();
1119
- const model = me.getModel();
1120
- if (model) {
1121
- this.lastKnownModifiedCode = model.getValue();
1122
- this.lastKnownModifiedLineCount = model.getLineCount();
1123
- }
1124
- } finally {
1125
- this.lastKnownModifiedDirty = false;
1126
- }
1127
- }
1128
- flushPendingDiffUpdate() {
1129
- if (!this.pendingDiffUpdate || !this.diffEditorView) return;
1130
- const o = this.originalModel;
1131
- const m = this.modifiedModel;
1132
- if (!o || !m) {
1133
- this.pendingDiffUpdate = null;
1134
- return;
1135
- }
1136
- const { original, modified, lang } = this.pendingDiffUpdate;
1137
- this.pendingDiffUpdate = null;
1138
- this.flushOriginalAppendBufferSync();
1139
- this.flushModifiedAppendBufferSync();
1140
- if (lang) {
1141
- const plang = processedLanguage(lang);
1142
- if (plang) {
1143
- if (o.getLanguageId() !== plang) {
1144
- monaco_shim_exports.editor.setModelLanguage(o, plang);
1145
- monaco_shim_exports.editor.setModelLanguage(m, plang);
1146
- }
1147
- }
1148
- }
1149
- if (this.lastKnownOriginalCode == null) this.lastKnownOriginalCode = o.getValue();
1150
- if (this.lastKnownModifiedCode == null) this.lastKnownModifiedCode = m.getValue();
1151
- const prevO = this.lastKnownOriginalCode;
1152
- if (prevO !== original) {
1153
- if (original.startsWith(prevO) && prevO.length < original.length) this.appendToModel(o, original.slice(prevO.length));
1154
- else this.applyMinimalEditToModel(o, prevO, original);
1155
- this.lastKnownOriginalCode = original;
1156
- }
1157
- const prevM = m.getValue();
1158
- const prevMLineCount = m.getLineCount();
1159
- if (prevM !== modified) {
1160
- if (modified.startsWith(prevM) && prevM.length < modified.length) this.appendToModel(m, modified.slice(prevM.length));
1161
- else this.applyMinimalEditToModel(m, prevM, modified);
1162
- this.lastKnownModifiedCode = modified;
1163
- const newMLineCount = m.getLineCount();
1164
- if (newMLineCount !== prevMLineCount) {
1165
- const shouldImmediate = this.shouldPerformImmediateRevealDiff();
1166
- if (shouldImmediate) this.suppressScrollWatcherDiff(this.scrollWatcherSuppressionMs + 800);
1167
- const computed$2 = this.computedHeight();
1168
- if (computed$2 >= this.maxHeightValue - 1 && this.lastContainer) {
1169
- this.lastContainer.style.height = `${this.maxHeightValue}px`;
1170
- this.lastContainer.style.overflow = "auto";
1171
- }
1172
- if (shouldImmediate) this.scheduleImmediateRevealAfterLayoutDiff(newMLineCount);
1173
- else this.maybeScrollDiffToBottom(newMLineCount, prevMLineCount);
1174
- }
1175
- }
1176
- }
1177
- flushModifiedAppendBufferSync() {
1178
- if (!this.modifiedModel) return;
1179
- if (this.appendBufferModifiedDiff.length === 0) return;
1180
- this.rafScheduler.cancel("appendDiff");
1181
- this.appendBufferDiffScheduled = false;
1182
- const text = this.appendBufferModifiedDiff.join("");
1183
- this.appendBufferModifiedDiff.length = 0;
1184
- if (!text) return;
1185
- this.appendToModel(this.modifiedModel, text);
1186
- }
1187
- async flushAppendBufferDiff() {
1188
- if (!this.diffEditorView) return;
1189
- if (this.appendBufferOriginalDiff.length === 0 && this.appendBufferModifiedDiff.length === 0) return;
1190
- this.lastAppendFlushTimeDiff = Date.now();
1191
- this.appendBufferDiffScheduled = false;
1192
- if (this.originalModel && this.appendBufferOriginalDiff.length > 0) {
1193
- const oText = this.appendBufferOriginalDiff.join("");
1194
- this.appendBufferOriginalDiff.length = 0;
1195
- if (oText) this.appendToModel(this.originalModel, oText);
1196
- }
1197
- const me = this.diffEditorView.getModifiedEditor();
1198
- const model = me.getModel();
1199
- if (!model) {
1200
- this.appendBufferModifiedDiff.length = 0;
1201
- return;
1202
- }
1203
- let parts = this.appendBufferModifiedDiff.splice(0);
1204
- const prevLineInit = model.getLineCount();
1205
- const totalText = parts.join("");
1206
- const totalChars = totalText.length;
1207
- if (parts.length === 1 && totalChars > 5e3) {
1208
- const lines = totalText.split(/\r?\n/);
1209
- const chunkSize = 200;
1210
- const chunks = [];
1211
- for (let i = 0; i < lines.length; i += chunkSize) chunks.push(`${lines.slice(i, i + chunkSize).join("\n")}\n`);
1212
- if (chunks.length > 1) parts = chunks;
1213
- }
1214
- const applyChunked = parts.length > 1 && (totalChars > 2e3 || model.getLineCount && model.getLineCount() + 0 - prevLineInit > 50);
1215
- log("diff", "flushAppendBufferDiff start", {
1216
- partsCount: parts.length,
1217
- totalChars,
1218
- applyChunked
1219
- });
1220
- let prevLine = prevLineInit;
1221
- const watcherApi = this.diffScrollWatcher;
1222
- let suppressedByFlush = false;
1223
- if (watcherApi && typeof watcherApi.setSuppressed === "function") try {
1224
- if (this.diffScrollWatcherSuppressionTimer != null) {
1225
- clearTimeout(this.diffScrollWatcherSuppressionTimer);
1226
- this.diffScrollWatcherSuppressionTimer = null;
1227
- }
1228
- watcherApi.setSuppressed(true);
1229
- suppressedByFlush = true;
1230
- } catch {}
1231
- if (applyChunked) {
1232
- log("diff", "flushAppendBufferDiff applying chunked", { partsLen: parts.length });
1233
- let idx = 0;
1234
- for (const part of parts) {
1235
- if (!part) continue;
1236
- idx += 1;
1237
- log("diff", "flushAppendBufferDiff chunk", {
1238
- idx,
1239
- partLen: part.length,
1240
- prevLine
1241
- });
1242
- const lastColumn$1 = model.getLineMaxColumn(prevLine);
1243
- const range$1 = new monaco_shim_exports.Range(prevLine, lastColumn$1, prevLine, lastColumn$1);
1244
- model.applyEdits([{
1245
- range: range$1,
1246
- text: part,
1247
- forceMoveMarkers: true
1248
- }]);
1249
- this.lastKnownModifiedCode = model.getValue();
1250
- const newLine$1 = model.getLineCount();
1251
- this.lastKnownModifiedLineCount = newLine$1;
1252
- await new Promise((resolve) => typeof requestAnimationFrame !== "undefined" ? requestAnimationFrame(resolve) : setTimeout(resolve, 0));
1253
- const shouldImmediate$1 = this.shouldPerformImmediateRevealDiff();
1254
- log("diff", "flushAppendBufferDiff chunk metrics", {
1255
- idx,
1256
- newLine: newLine$1,
1257
- prevLine,
1258
- shouldImmediate: shouldImmediate$1
1259
- });
1260
- if (shouldImmediate$1) this.suppressScrollWatcherDiff(this.scrollWatcherSuppressionMs + 800);
1261
- const computed$3 = this.computedHeight();
1262
- if (computed$3 >= this.maxHeightValue - 1 && this.lastContainer) {
1263
- this.lastContainer.style.height = `${this.maxHeightValue}px`;
1264
- this.lastContainer.style.overflow = "auto";
1265
- }
1266
- if (shouldImmediate$1) this.scheduleImmediateRevealAfterLayoutDiff(newLine$1);
1267
- else this.maybeScrollDiffToBottom(newLine$1, prevLine);
1268
- prevLine = newLine$1;
1269
- log("diff", "flushAppendBufferDiff chunk applied", {
1270
- idx,
1271
- newLine: newLine$1
1272
- });
1273
- }
1274
- if (suppressedByFlush) watcherApi.setSuppressed(false);
1275
- return;
1276
- }
1277
- const text = totalText;
1278
- this.appendBufferModifiedDiff.length = 0;
1279
- prevLine = model.getLineCount();
1280
- const lastColumn = model.getLineMaxColumn(prevLine);
1281
- const range = new monaco_shim_exports.Range(prevLine, lastColumn, prevLine, lastColumn);
1282
- model.applyEdits([{
1283
- range,
1284
- text,
1285
- forceMoveMarkers: true
1286
- }]);
1287
- this.lastKnownModifiedCode = model.getValue();
1288
- const newLine = model.getLineCount();
1289
- this.lastKnownModifiedLineCount = newLine;
1290
- const shouldImmediate = this.shouldPerformImmediateRevealDiff();
1291
- if (shouldImmediate) this.suppressScrollWatcherDiff(this.scrollWatcherSuppressionMs + 800);
1292
- const computed$2 = this.computedHeight();
1293
- if (computed$2 >= this.maxHeightValue - 1 && this.lastContainer) this.lastContainer.style.height = `${this.maxHeightValue}px`;
1294
- if (shouldImmediate) this.scheduleImmediateRevealAfterLayoutDiff(newLine);
1295
- else this.maybeScrollDiffToBottom(newLine, prevLine);
1296
- if (this.autoScrollOnUpdate && this.shouldAutoScrollDiff) try {
1297
- var _editor4, _me2$getModel2, _me2$getScrollTop2;
1298
- const ScrollType = monaco_shim_exports.ScrollType || ((_editor4 = monaco_shim_exports.editor) === null || _editor4 === void 0 ? void 0 : _editor4.ScrollType);
1299
- const immediate = ScrollType && typeof ScrollType.Immediate !== "undefined" ? ScrollType.Immediate : void 0;
1300
- const me2 = this.diffEditorView.getModifiedEditor();
1301
- const targetLine = ((_me2$getModel2 = me2.getModel()) === null || _me2$getModel2 === void 0 ? void 0 : _me2$getModel2.getLineCount()) ?? newLine;
1302
- if (typeof immediate !== "undefined") me2.revealLine(targetLine, immediate);
1303
- else me2.revealLine(targetLine);
1304
- this.lastRevealLineDiff = targetLine;
1305
- this.shouldAutoScrollDiff = true;
1306
- this.lastScrollTopDiff = ((_me2$getScrollTop2 = me2.getScrollTop) === null || _me2$getScrollTop2 === void 0 ? void 0 : _me2$getScrollTop2.call(me2)) ?? this.lastScrollTopDiff;
1307
- } catch {}
1308
- if (suppressedByFlush) watcherApi.setSuppressed(false);
1309
- try {
1310
- var _this$diffEditorView5, _this$diffEditorView6, _this$diffEditorView7;
1311
- this.shouldAutoScrollDiff = true;
1312
- this.lastScrollTopDiff = ((_this$diffEditorView5 = this.diffEditorView) === null || _this$diffEditorView5 === void 0 || (_this$diffEditorView7 = (_this$diffEditorView6 = _this$diffEditorView5.getModifiedEditor()).getScrollTop) === null || _this$diffEditorView7 === void 0 ? void 0 : _this$diffEditorView7.call(_this$diffEditorView6)) ?? this.lastScrollTopDiff;
1313
- } catch {}
1314
- }
1315
- applyMinimalEditToModel(model, prev, next) {
1316
- const maxChars = minimalEditMaxChars;
1317
- const ratio = minimalEditMaxChangeRatio;
1318
- const maxLen = Math.max(prev.length, next.length);
1319
- const changeRatio = maxLen > 0 ? Math.abs(next.length - prev.length) / maxLen : 0;
1320
- if (prev.length + next.length > maxChars || changeRatio > ratio) {
1321
- model.setValue(next);
1322
- if (model === this.modifiedModel) this.lastKnownModifiedLineCount = model.getLineCount();
1323
- return;
1324
- }
1325
- const res = computeMinimalEdit(prev, next);
1326
- if (!res) return;
1327
- const { start, endPrevIncl, replaceText } = res;
1328
- const rangeStart = model.getPositionAt(start);
1329
- const rangeEnd = model.getPositionAt(endPrevIncl + 1);
1330
- const range = new monaco_shim_exports.Range(rangeStart.lineNumber, rangeStart.column, rangeEnd.lineNumber, rangeEnd.column);
1331
- model.applyEdits([{
1332
- range,
1333
- text: replaceText,
1334
- forceMoveMarkers: true
1335
- }]);
1336
- if (model === this.modifiedModel) this.lastKnownModifiedLineCount = model.getLineCount();
1337
- }
1338
- appendToModel(model, appendText) {
1339
- if (!appendText) return;
1340
- const lastLine = model.getLineCount();
1341
- const lastColumn = model.getLineMaxColumn(lastLine);
1342
- const range = new monaco_shim_exports.Range(lastLine, lastColumn, lastLine, lastColumn);
1343
- model.applyEdits([{
1344
- range,
1345
- text: appendText,
1346
- forceMoveMarkers: true
1347
- }]);
1348
- if (model === this.modifiedModel) this.lastKnownModifiedLineCount = model.getLineCount();
1349
- }
1350
- };
1351
-
1352
- //#endregion
1353
- //#region src/core/EditorManager.ts
1354
- var EditorManager = class {
1355
- editorView = null;
1356
- lastContainer = null;
1357
- lastKnownCode = null;
1358
- pendingUpdate = null;
1359
- _hasScrollBar = false;
1360
- shouldAutoScroll = true;
1361
- scrollWatcher = null;
1362
- scrollWatcherSuppressionTimer = null;
1363
- lastScrollTop = 0;
1364
- cachedScrollHeight = null;
1365
- cachedLineHeight = null;
1366
- cachedComputedHeight = null;
1367
- cachedLineCount = null;
1368
- lastKnownCodeDirty = false;
1369
- debug = false;
1370
- measureViewport() {
1371
- var _this$editorView$getL, _this$editorView, _this$editorView$getS, _this$editorView2, _this$editorView$getS2, _this$editorView3;
1372
- if (!this.editorView) return null;
1373
- 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;
1374
- const lineHeight = this.cachedLineHeight ?? this.editorView.getOption(monaco_shim_exports.editor.EditorOption.lineHeight);
1375
- 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;
1376
- 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;
1377
- const computedHeight = this.cachedComputedHeight ?? this.computedHeight(this.editorView);
1378
- this.cachedLineHeight = lineHeight;
1379
- this.cachedScrollHeight = scrollHeight;
1380
- this.cachedComputedHeight = computedHeight;
1381
- this.lastScrollTop = scrollTop;
1382
- return {
1383
- li,
1384
- lineHeight,
1385
- scrollTop,
1386
- scrollHeight,
1387
- computedHeight
1388
- };
1389
- }
1390
- appendBuffer = [];
1391
- appendBufferScheduled = false;
1392
- rafScheduler = createRafScheduler();
1393
- editorHeightManager = null;
1394
- revealDebounceId = null;
1395
- revealDebounceMs = defaultRevealDebounceMs;
1396
- revealIdleTimerId = null;
1397
- revealTicket = 0;
1398
- revealStrategyOption;
1399
- revealBatchOnIdleMsOption;
1400
- scrollWatcherSuppressionMs = 500;
1401
- constructor(options, maxHeightValue, maxHeightCSS, autoScrollOnUpdate, autoScrollInitial, autoScrollThresholdPx, autoScrollThresholdLines, revealDebounceMsOption) {
1402
- this.options = options;
1403
- this.maxHeightValue = maxHeightValue;
1404
- this.maxHeightCSS = maxHeightCSS;
1405
- this.autoScrollOnUpdate = autoScrollOnUpdate;
1406
- this.autoScrollInitial = autoScrollInitial;
1407
- this.autoScrollThresholdPx = autoScrollThresholdPx;
1408
- this.autoScrollThresholdLines = autoScrollThresholdLines;
1409
- this.revealDebounceMsOption = revealDebounceMsOption;
1410
- }
1411
- initDebugFlag() {
1412
- if (typeof window !== "undefined" && window.__STREAM_MONACO_DEBUG__ !== void 0) {
1413
- this.debug = Boolean(window.__STREAM_MONACO_DEBUG__);
1414
- return;
1415
- }
1416
- if (this.options && this.options.debug !== void 0) {
1417
- this.debug = Boolean(this.options.debug);
1418
- return;
1419
- }
1420
- this.debug = false;
1421
- }
1422
- dlog(...args) {
1423
- if (!this.debug) return;
1424
- log("EditorManager", ...args);
1425
- }
1426
- hasVerticalScrollbar() {
1427
- if (!this.editorView) return false;
1428
- if (this._hasScrollBar) return true;
1429
- const m = this.measureViewport();
1430
- if (!m) return false;
1431
- return this._hasScrollBar = m.scrollHeight > m.computedHeight + padding / 2;
1432
- }
1433
- userIsNearBottom() {
1434
- if (!this.editorView) return true;
1435
- const m = this.measureViewport();
1436
- if (!m || !m.li) return true;
1437
- const lineThreshold = (this.autoScrollThresholdLines ?? 0) * m.lineHeight;
1438
- const threshold = Math.max(lineThreshold || 0, this.autoScrollThresholdPx || 0);
1439
- const distance = m.scrollHeight - (m.scrollTop + m.li.height);
1440
- return distance <= threshold;
1441
- }
1442
- computedHeight(editorView) {
1443
- var _editorView$getModel;
1444
- const lineCount = this.cachedLineCount ?? ((_editorView$getModel = editorView.getModel()) === null || _editorView$getModel === void 0 ? void 0 : _editorView$getModel.getLineCount()) ?? 1;
1445
- const lineHeight = editorView.getOption(monaco_shim_exports.editor.EditorOption.lineHeight);
1446
- const height = Math.min(lineCount * lineHeight + padding, this.maxHeightValue);
1447
- log("EditorManager.computedHeight", {
1448
- lineCount,
1449
- lineHeight,
1450
- computed: height,
1451
- maxHeightValue: this.maxHeightValue
1452
- });
1453
- return height;
1454
- }
1455
- maybeScrollToBottom(targetLine) {
1456
- this.rafScheduler.schedule("maybe-scroll", () => {
1457
- const hasVS = this.hasVerticalScrollbar();
1458
- this.dlog("maybeScrollToBottom called", {
1459
- autoScrollOnUpdate: this.autoScrollOnUpdate,
1460
- shouldAutoScroll: this.shouldAutoScroll,
1461
- hasVerticalScrollbar: hasVS,
1462
- targetLine
1463
- });
1464
- if (!(this.autoScrollOnUpdate && this.shouldAutoScroll && this.hasVerticalScrollbar())) {
1465
- this.dlog("maybeScrollToBottom skipped (auto-scroll conditions not met)");
1466
- return;
1467
- }
1468
- const model = this.editorView.getModel();
1469
- const line = targetLine ?? (model === null || model === void 0 ? void 0 : model.getLineCount()) ?? 1;
1470
- const batchMs = this.revealBatchOnIdleMsOption ?? this.options.revealBatchOnIdleMs ?? defaultRevealBatchOnIdleMs;
1471
- if (typeof batchMs === "number" && batchMs > 0) {
1472
- if (this.revealIdleTimerId != null) clearTimeout(this.revealIdleTimerId);
1473
- const ticket = ++this.revealTicket;
1474
- this.dlog("scheduled idle reveal ticket=", ticket, "line=", line, "batchMs=", batchMs);
1475
- this.revealIdleTimerId = setTimeout(() => {
1476
- this.revealIdleTimerId = null;
1477
- this.dlog("idle reveal timer firing, ticket=", ticket, "line=", line);
1478
- this.performReveal(line, ticket);
1479
- }, batchMs);
1480
- return;
1481
- }
1482
- if (this.revealDebounceId != null) {
1483
- clearTimeout(this.revealDebounceId);
1484
- this.revealDebounceId = null;
1485
- }
1486
- const ms = typeof this.revealDebounceMs === "number" && this.revealDebounceMs > 0 ? this.revealDebounceMs : typeof this.revealDebounceMsOption === "number" && this.revealDebounceMsOption > 0 ? this.revealDebounceMsOption : this.revealDebounceMs;
1487
- this.revealDebounceId = setTimeout(() => {
1488
- this.revealDebounceId = null;
1489
- const ticket = ++this.revealTicket;
1490
- this.dlog("scheduled debounce reveal ticket=", ticket, "line=", line, "ms=", ms);
1491
- this.performReveal(line, ticket);
1492
- }, ms);
1493
- });
1494
- }
1495
- performReveal(line, ticket) {
1496
- this.rafScheduler.schedule("reveal", () => {
1497
- var _editor;
1498
- if (ticket !== this.revealTicket) {
1499
- this.dlog("performReveal skipped, stale ticket", ticket, "current", this.revealTicket);
1500
- return;
1501
- }
1502
- this.dlog("performReveal executing, ticket=", ticket, "line=", line);
1503
- const strategy = this.revealStrategyOption ?? this.options.revealStrategy ?? "centerIfOutside";
1504
- this.dlog("performReveal strategy=", strategy);
1505
- const ScrollType = monaco_shim_exports.ScrollType || ((_editor = monaco_shim_exports.editor) === null || _editor === void 0 ? void 0 : _editor.ScrollType);
1506
- const smooth = ScrollType && typeof ScrollType.Smooth !== "undefined" ? ScrollType.Smooth : void 0;
1507
- try {
1508
- if (strategy === "bottom") if (typeof smooth !== "undefined") this.editorView.revealLine(line, smooth);
1509
- else this.editorView.revealLine(line);
1510
- else if (strategy === "center") if (typeof smooth !== "undefined") this.editorView.revealLineInCenter(line, smooth);
1511
- else this.editorView.revealLineInCenter(line);
1512
- else if (typeof smooth !== "undefined") this.editorView.revealLineInCenterIfOutsideViewport(line, smooth);
1513
- else this.editorView.revealLineInCenterIfOutsideViewport(line);
1514
- } catch {
1515
- try {
1516
- this.editorView.revealLine(line);
1517
- } catch {}
1518
- }
1519
- });
1520
- }
1521
- performImmediateReveal(line, ticket) {
1522
- this.dlog("performImmediateReveal line=", line, "ticket=", ticket);
1523
- try {
1524
- var _editor2;
1525
- if (!this.editorView) return;
1526
- if (ticket !== this.revealTicket) {
1527
- this.dlog("performImmediateReveal skipped, stale ticket", ticket, "current", this.revealTicket);
1528
- return;
1529
- }
1530
- const ScrollType = monaco_shim_exports.ScrollType || ((_editor2 = monaco_shim_exports.editor) === null || _editor2 === void 0 ? void 0 : _editor2.ScrollType);
1531
- const immediate = ScrollType && typeof ScrollType.Immediate !== "undefined" ? ScrollType.Immediate : void 0;
1532
- if (typeof immediate !== "undefined") this.editorView.revealLine(line, immediate);
1533
- else this.editorView.revealLine(line);
1534
- } catch {}
1535
- try {
1536
- this.measureViewport();
1537
- } catch {}
1538
- }
1539
- forceReveal(line) {
1540
- try {
1541
- var _editor3;
1542
- if (!this.editorView) return;
1543
- const ScrollType = monaco_shim_exports.ScrollType || ((_editor3 = monaco_shim_exports.editor) === null || _editor3 === void 0 ? void 0 : _editor3.ScrollType);
1544
- const immediate = ScrollType && typeof ScrollType.Immediate !== "undefined" ? ScrollType.Immediate : void 0;
1545
- if (typeof immediate !== "undefined") this.editorView.revealLine(line, immediate);
1546
- else this.editorView.revealLine(line);
1547
- } catch {}
1548
- try {
1549
- this.measureViewport();
1550
- } catch {}
1551
- try {
1552
- var _this$editorView4, _this$editorView4$get;
1553
- this.shouldAutoScroll = true;
1554
- this.lastScrollTop = ((_this$editorView4 = this.editorView) === null || _this$editorView4 === void 0 || (_this$editorView4$get = _this$editorView4.getScrollTop) === null || _this$editorView4$get === void 0 ? void 0 : _this$editorView4$get.call(_this$editorView4)) ?? this.lastScrollTop;
1555
- } catch {}
1556
- }
1557
- isOverflowAuto() {
1558
- try {
1559
- return !!this.lastContainer && this.lastContainer.style.overflow === "auto";
1560
- } catch {
1561
- return false;
1562
- }
1563
- }
1564
- shouldPerformImmediateReveal() {
1565
- return this.autoScrollOnUpdate && this.shouldAutoScroll && this.hasVerticalScrollbar() && this.isOverflowAuto();
1566
- }
1567
- async createEditor(container, code, language, currentTheme) {
1568
- var _this$editorView$getS3, _this$editorView5, _this$editorView$getO, _this$editorView6, _this$editorView$getM, _this$editorView$onDi, _this$editorView7;
1569
- this.cleanup();
1570
- this.lastContainer = container;
1571
- this.initDebugFlag();
1572
- this.dlog("createEditor container, maxHeight", this.maxHeightValue);
1573
- container.style.overflow = "hidden";
1574
- container.style.maxHeight = this.maxHeightCSS;
1575
- this.editorView = monaco_shim_exports.editor.create(container, {
1576
- value: code,
1577
- language: processedLanguage(language) || language,
1578
- theme: currentTheme,
1579
- scrollBeyondLastLine: false,
1580
- minimap: { enabled: false },
1581
- automaticLayout: true,
1582
- readOnly: this.options.readOnly ?? true,
1583
- contextmenu: false,
1584
- scrollbar: {
1585
- ...defaultScrollbar,
1586
- ...this.options.scrollbar || {}
1587
- },
1588
- ...this.options
1589
- });
1590
- monaco_shim_exports.editor.setTheme(currentTheme);
1591
- this.lastKnownCode = this.editorView.getValue();
1592
- if (this.editorHeightManager) {
1593
- try {
1594
- this.editorHeightManager.dispose();
1595
- } catch {}
1596
- this.editorHeightManager = null;
1597
- }
1598
- if (this.revealDebounceId != null) {
1599
- clearTimeout(this.revealDebounceId);
1600
- this.revealDebounceId = null;
1601
- }
1602
- if (this.revealIdleTimerId != null) clearTimeout(this.revealIdleTimerId);
1603
- this.revealIdleTimerId = null;
1604
- const MIN_VISIBLE_HEIGHT = Math.min(120, this.maxHeightValue);
1605
- container.style.minHeight = `${MIN_VISIBLE_HEIGHT}px`;
1606
- this.editorHeightManager = createHeightManager(container, () => {
1607
- const computed$2 = this.computedHeight(this.editorView);
1608
- const clamped = Math.min(computed$2, this.maxHeightValue);
1609
- return Math.max(clamped, MIN_VISIBLE_HEIGHT);
1610
- });
1611
- this.editorHeightManager.update();
1612
- const initialComputed = this.computedHeight(this.editorView);
1613
- if (initialComputed >= this.maxHeightValue - 1) {
1614
- container.style.height = `${this.maxHeightValue}px`;
1615
- container.style.overflow = "auto";
1616
- this.dlog("applied immediate maxHeight on createEditor", this.maxHeightValue);
1617
- }
1618
- this.cachedScrollHeight = ((_this$editorView$getS3 = (_this$editorView5 = this.editorView).getScrollHeight) === null || _this$editorView$getS3 === void 0 ? void 0 : _this$editorView$getS3.call(_this$editorView5)) ?? null;
1619
- this.cachedLineHeight = ((_this$editorView$getO = (_this$editorView6 = this.editorView).getOption) === null || _this$editorView$getO === void 0 ? void 0 : _this$editorView$getO.call(_this$editorView6, monaco_shim_exports.editor.EditorOption.lineHeight)) ?? null;
1620
- this.cachedComputedHeight = this.computedHeight(this.editorView);
1621
- this.cachedLineCount = ((_this$editorView$getM = this.editorView.getModel()) === null || _this$editorView$getM === void 0 ? void 0 : _this$editorView$getM.getLineCount()) ?? null;
1622
- (_this$editorView$onDi = (_this$editorView7 = this.editorView).onDidContentSizeChange) === null || _this$editorView$onDi === void 0 || _this$editorView$onDi.call(_this$editorView7, () => {
1623
- this._hasScrollBar = false;
1624
- this.rafScheduler.schedule("content-size-change", () => {
1625
- try {
1626
- var _this$editorView8, _this$editorHeightMan, _this$editorHeightMan2;
1627
- this.dlog("content-size-change frame");
1628
- const m = this.measureViewport();
1629
- this.dlog("content-size-change measure", m);
1630
- this.cachedLineCount = ((_this$editorView8 = this.editorView) === null || _this$editorView8 === void 0 || (_this$editorView8 = _this$editorView8.getModel()) === null || _this$editorView8 === void 0 ? void 0 : _this$editorView8.getLineCount()) ?? this.cachedLineCount;
1631
- if ((_this$editorHeightMan = this.editorHeightManager) === null || _this$editorHeightMan === void 0 ? void 0 : _this$editorHeightMan.isSuppressed()) {
1632
- this.dlog("content-size-change skipped height update (suppressed)");
1633
- return;
1634
- }
1635
- this.dlog("content-size-change calling heightManager.update");
1636
- (_this$editorHeightMan2 = this.editorHeightManager) === null || _this$editorHeightMan2 === void 0 || _this$editorHeightMan2.update();
1637
- const computed$2 = this.computedHeight(this.editorView);
1638
- if (this.lastContainer) {
1639
- const prevOverflow = this.lastContainer.style.overflow;
1640
- const newOverflow = computed$2 >= this.maxHeightValue - 1 ? "auto" : "hidden";
1641
- if (prevOverflow !== newOverflow) {
1642
- this.lastContainer.style.overflow = newOverflow;
1643
- if (newOverflow === "auto" && this.shouldAutoScroll) this.maybeScrollToBottom();
1644
- }
1645
- }
1646
- } catch (err) {
1647
- error("EditorManager", "content-size-change error", err);
1648
- }
1649
- });
1650
- });
1651
- this.editorView.onDidChangeModelContent(() => {
1652
- this.lastKnownCodeDirty = true;
1653
- this.rafScheduler.schedule("sync-last-known", () => this.syncLastKnownCode());
1654
- });
1655
- this.shouldAutoScroll = !!this.autoScrollInitial;
1656
- if (this.scrollWatcher) {
1657
- this.scrollWatcher.dispose();
1658
- this.scrollWatcher = null;
1659
- }
1660
- this.scrollWatcher = createScrollWatcherForEditor(this.editorView, {
1661
- onPause: () => {
1662
- this.shouldAutoScroll = false;
1663
- },
1664
- onMaybeResume: () => {
1665
- this.rafScheduler.schedule("maybe-resume", () => {
1666
- this.shouldAutoScroll = this.userIsNearBottom();
1667
- });
1668
- },
1669
- getLast: () => this.lastScrollTop,
1670
- setLast: (v) => {
1671
- this.lastScrollTop = v;
1672
- }
1673
- });
1674
- this.maybeScrollToBottom();
1675
- return this.editorView;
1676
- }
1677
- syncLastKnownCode() {
1678
- if (!this.editorView || !this.lastKnownCodeDirty) return;
1679
- const model = this.editorView.getModel();
1680
- if (model) {
1681
- this.lastKnownCode = model.getValue();
1682
- this.cachedLineCount = model.getLineCount() ?? this.cachedLineCount;
1683
- }
1684
- this.lastKnownCodeDirty = false;
1685
- }
1686
- suppressScrollWatcher(ms) {
1687
- if (!this.scrollWatcher || typeof this.scrollWatcher.setSuppressed !== "function") return;
1688
- this.dlog("suppressScrollWatcher", ms);
1689
- if (this.scrollWatcherSuppressionTimer != null) {
1690
- clearTimeout(this.scrollWatcherSuppressionTimer);
1691
- this.scrollWatcherSuppressionTimer = null;
1692
- }
1693
- this.scrollWatcher.setSuppressed(true);
1694
- this.scrollWatcherSuppressionTimer = setTimeout(() => {
1695
- if (this.scrollWatcher && typeof this.scrollWatcher.setSuppressed === "function") {
1696
- this.scrollWatcher.setSuppressed(false);
1697
- this.dlog("suppressScrollWatcher cleared");
1698
- }
1699
- this.scrollWatcherSuppressionTimer = null;
1700
- }, ms);
1701
- }
1702
- scheduleImmediateRevealAfterLayout(line) {
1703
- const ticket = ++this.revealTicket;
1704
- this.dlog("scheduleImmediateRevealAfterLayout ticket=", ticket, "line=", line);
1705
- this.rafScheduler.schedule("immediate-reveal", async () => {
1706
- try {
1707
- const target = this.editorView && this.editorHeightManager ? Math.min(this.computedHeight(this.editorView), this.maxHeightValue) : -1;
1708
- if (target !== -1 && this.editorHeightManager) await this.waitForHeightApplied(target, 500);
1709
- else await new Promise((r) => requestAnimationFrame(() => requestAnimationFrame(() => r())));
1710
- this.dlog("running delayed immediate reveal", "ticket=", ticket, "line=", line);
1711
- this.performImmediateReveal(line, ticket);
1712
- } catch (err) {
1713
- error("EditorManager", "scheduleImmediateRevealAfterLayout error", err);
1714
- }
1715
- });
1716
- }
1717
- waitForHeightApplied(target, timeoutMs = 500) {
1718
- return new Promise((resolve) => {
1719
- const start = typeof performance !== "undefined" && performance.now ? performance.now() : Date.now();
1720
- const check = () => {
1721
- try {
1722
- var _this$editorHeightMan3, _this$editorHeightMan4;
1723
- const last = ((_this$editorHeightMan3 = this.editorHeightManager) === null || _this$editorHeightMan3 === void 0 || (_this$editorHeightMan4 = _this$editorHeightMan3.getLastApplied) === null || _this$editorHeightMan4 === void 0 ? void 0 : _this$editorHeightMan4.call(_this$editorHeightMan3)) ?? -1;
1724
- if (last !== -1 && Math.abs(last - target) <= 12) {
1725
- this.dlog("waitForHeightApplied satisfied", last, "target=", target);
1726
- resolve();
1727
- return;
1728
- }
1729
- const now = typeof performance !== "undefined" && performance.now ? performance.now() : Date.now();
1730
- if (now - start > timeoutMs) {
1731
- log("EditorManager", "waitForHeightApplied timeout", last, "target=", target);
1732
- resolve();
1733
- return;
1734
- }
1735
- } catch {}
1736
- requestAnimationFrame(check);
1737
- };
1738
- check();
1739
- });
1740
- }
1741
- updateCode(newCode, codeLanguage) {
1742
- this.pendingUpdate = {
1743
- code: newCode,
1744
- lang: codeLanguage
1745
- };
1746
- this.rafScheduler.schedule("update", () => this.flushPendingUpdate());
1747
- }
1748
- flushPendingUpdate() {
1749
- if (!this.pendingUpdate || !this.editorView) return;
1750
- const model = this.editorView.getModel();
1751
- if (!model) return;
1752
- const { code: newCode, lang: codeLanguage } = this.pendingUpdate;
1753
- this.pendingUpdate = null;
1754
- const processedCodeLanguage = processedLanguage(codeLanguage);
1755
- const languageId = model.getLanguageId();
1756
- if (languageId !== processedCodeLanguage) {
1757
- if (processedCodeLanguage) monaco_shim_exports.editor.setModelLanguage(model, processedCodeLanguage);
1758
- const prevLineCount$1 = model.getLineCount();
1759
- model.setValue(newCode);
1760
- this.lastKnownCode = newCode;
1761
- const newLineCount$1 = model.getLineCount();
1762
- this.cachedLineCount = newLineCount$1;
1763
- if (newLineCount$1 !== prevLineCount$1) {
1764
- const shouldImmediate = this.shouldPerformImmediateReveal();
1765
- if (shouldImmediate) this.suppressScrollWatcher(this.scrollWatcherSuppressionMs);
1766
- const computed$2 = this.computedHeight(this.editorView);
1767
- if (computed$2 >= this.maxHeightValue - 1 && this.lastContainer) this.lastContainer.style.height = `${this.maxHeightValue}px`;
1768
- this.forceReveal(newLineCount$1);
1769
- }
1770
- return;
1771
- }
1772
- const buffered = this.appendBuffer.length > 0 ? this.appendBuffer.join("") : "";
1773
- const prevCode = this.appendBuffer.length > 0 ? this.editorView.getValue() + buffered : this.lastKnownCode ?? this.editorView.getValue();
1774
- if (prevCode === newCode) return;
1775
- if (newCode.startsWith(prevCode) && prevCode.length < newCode.length) {
1776
- const suffix = newCode.slice(prevCode.length);
1777
- if (suffix) this.appendCode(suffix, codeLanguage);
1778
- this.lastKnownCode = newCode;
1779
- return;
1780
- }
1781
- const prevLineCount = model.getLineCount();
1782
- this.applyMinimalEdit(prevCode, newCode);
1783
- this.lastKnownCode = newCode;
1784
- const newLineCount = model.getLineCount();
1785
- this.cachedLineCount = newLineCount;
1786
- if (newLineCount !== prevLineCount) {
1787
- const shouldImmediate = this.shouldPerformImmediateReveal();
1788
- if (shouldImmediate) this.suppressScrollWatcher(this.scrollWatcherSuppressionMs);
1789
- if (shouldImmediate) this.scheduleImmediateRevealAfterLayout(newLineCount);
1790
- else this.maybeScrollToBottom(newLineCount);
1791
- }
1792
- }
1793
- appendCode(appendText, codeLanguage) {
1794
- if (!this.editorView) return;
1795
- const model = this.editorView.getModel();
1796
- if (!model) return;
1797
- const processedCodeLanguage = codeLanguage ? processedLanguage(codeLanguage) : model.getLanguageId();
1798
- if (processedCodeLanguage && model.getLanguageId() !== processedCodeLanguage) monaco_shim_exports.editor.setModelLanguage(model, processedCodeLanguage);
1799
- if (appendText) {
1800
- this.appendBuffer.push(appendText);
1801
- if (!this.appendBufferScheduled) {
1802
- this.appendBufferScheduled = true;
1803
- this.rafScheduler.schedule("append", () => this.flushAppendBuffer());
1804
- }
1805
- }
1806
- }
1807
- applyMinimalEdit(prev, next) {
1808
- if (!this.editorView) return;
1809
- const model = this.editorView.getModel();
1810
- if (!model) return;
1811
- const maxChars = minimalEditMaxChars;
1812
- const ratio = minimalEditMaxChangeRatio;
1813
- const maxLen = Math.max(prev.length, next.length);
1814
- const changeRatio = maxLen > 0 ? Math.abs(next.length - prev.length) / maxLen : 0;
1815
- if (prev.length + next.length > maxChars || changeRatio > ratio) {
1816
- const prevLineCount = model.getLineCount();
1817
- model.setValue(next);
1818
- this.lastKnownCode = next;
1819
- const newLineCount = model.getLineCount();
1820
- this.cachedLineCount = newLineCount;
1821
- if (newLineCount !== prevLineCount) this.maybeScrollToBottom(newLineCount);
1822
- return;
1823
- }
1824
- const res = computeMinimalEdit(prev, next);
1825
- if (!res) return;
1826
- const { start, endPrevIncl, replaceText } = res;
1827
- const rangeStart = model.getPositionAt(start);
1828
- const rangeEnd = model.getPositionAt(endPrevIncl + 1);
1829
- const range = new monaco_shim_exports.Range(rangeStart.lineNumber, rangeStart.column, rangeEnd.lineNumber, rangeEnd.column);
1830
- const isReadOnly = this.editorView.getOption(monaco_shim_exports.editor.EditorOption.readOnly);
1831
- const edit = [{
1832
- range,
1833
- text: replaceText,
1834
- forceMoveMarkers: true
1835
- }];
1836
- if (isReadOnly) model.applyEdits(edit);
1837
- else this.editorView.executeEdits("minimal-replace", edit);
1838
- }
1839
- flushAppendBuffer() {
1840
- if (!this.editorView) return;
1841
- if (this.appendBuffer.length === 0) return;
1842
- this.appendBufferScheduled = false;
1843
- const model = this.editorView.getModel();
1844
- if (!model) {
1845
- this.appendBuffer.length = 0;
1846
- return;
1847
- }
1848
- const text = this.appendBuffer.join("");
1849
- this.appendBuffer.length = 0;
1850
- const lastLine = model.getLineCount();
1851
- const lastColumn = model.getLineMaxColumn(lastLine);
1852
- const range = new monaco_shim_exports.Range(lastLine, lastColumn, lastLine, lastColumn);
1853
- const isReadOnly = this.editorView.getOption(monaco_shim_exports.editor.EditorOption.readOnly);
1854
- if (isReadOnly) model.applyEdits([{
1855
- range,
1856
- text,
1857
- forceMoveMarkers: true
1858
- }]);
1859
- else this.editorView.executeEdits("append", [{
1860
- range,
1861
- text,
1862
- forceMoveMarkers: true
1863
- }]);
1864
- try {
1865
- this.lastKnownCode = model.getValue();
1866
- } catch {}
1867
- const newLineCount = model.getLineCount();
1868
- if (lastLine !== newLineCount) {
1869
- this.cachedLineCount = newLineCount;
1870
- const shouldImmediate = this.shouldPerformImmediateReveal();
1871
- if (shouldImmediate) this.suppressScrollWatcher(this.scrollWatcherSuppressionMs);
1872
- const computed$2 = this.computedHeight(this.editorView);
1873
- if (computed$2 >= this.maxHeightValue - 1 && this.lastContainer) this.lastContainer.style.height = `${this.maxHeightValue}px`;
1874
- if (shouldImmediate) try {
1875
- this.forceReveal(newLineCount);
1876
- } catch {}
1877
- else this.maybeScrollToBottom(newLineCount);
1878
- }
1879
- }
1880
- setLanguage(language, languages$1) {
1881
- if (languages$1.includes(language)) {
1882
- if (this.editorView) {
1883
- const model = this.editorView.getModel();
1884
- if (model && model.getLanguageId() !== language) monaco_shim_exports.editor.setModelLanguage(model, language);
1885
- }
1886
- } else console.warn(`Language "${language}" is not registered. Available languages: ${languages$1.join(", ")}`);
1887
- }
1888
- getEditorView() {
1889
- return this.editorView;
1890
- }
1891
- cleanup() {
1892
- this.rafScheduler.cancel("update");
1893
- this.rafScheduler.cancel("sync-last-known");
1894
- this.rafScheduler.cancel("content-size-change");
1895
- this.rafScheduler.cancel("maybe-scroll");
1896
- this.rafScheduler.cancel("reveal");
1897
- this.rafScheduler.cancel("immediate-reveal");
1898
- this.rafScheduler.cancel("maybe-resume");
1899
- this.pendingUpdate = null;
1900
- this.rafScheduler.cancel("append");
1901
- this.appendBufferScheduled = false;
1902
- this.appendBuffer.length = 0;
1903
- if (this.revealDebounceId != null) {
1904
- clearTimeout(this.revealDebounceId);
1905
- this.revealDebounceId = null;
1906
- }
1907
- if (this.revealIdleTimerId != null) {
1908
- clearTimeout(this.revealIdleTimerId);
1909
- this.revealIdleTimerId = null;
1910
- }
1911
- if (this.scrollWatcherSuppressionTimer != null) {
1912
- clearTimeout(this.scrollWatcherSuppressionTimer);
1913
- this.scrollWatcherSuppressionTimer = null;
1914
- }
1915
- if (this.editorView) {
1916
- this.editorView.dispose();
1917
- this.editorView = null;
1918
- }
1919
- this.lastKnownCode = null;
1920
- if (this.lastContainer) {
1921
- this.lastContainer.style.minHeight = "";
1922
- this.lastContainer.innerHTML = "";
1923
- this.lastContainer = null;
1924
- }
1925
- if (this.scrollWatcher) {
1926
- this.scrollWatcher.dispose();
1927
- this.scrollWatcher = null;
1928
- }
1929
- if (this.editorHeightManager) {
1930
- this.editorHeightManager.dispose();
1931
- this.editorHeightManager = null;
1932
- }
1933
- }
1934
- safeClean() {
1935
- this.rafScheduler.cancel("update");
1936
- this.pendingUpdate = null;
1937
- this.rafScheduler.cancel("sync-last-known");
1938
- if (this.scrollWatcher) {
1939
- try {
1940
- this.scrollWatcher.dispose();
1941
- } catch {}
1942
- this.scrollWatcher = null;
1943
- }
1944
- if (this.revealDebounceId != null) {
1945
- clearTimeout(this.revealDebounceId);
1946
- this.revealDebounceId = null;
1947
- }
1948
- if (this.revealIdleTimerId != null) {
1949
- clearTimeout(this.revealIdleTimerId);
1950
- this.revealIdleTimerId = null;
1951
- }
1952
- if (this.scrollWatcherSuppressionTimer != null) {
1953
- clearTimeout(this.scrollWatcherSuppressionTimer);
1954
- this.scrollWatcherSuppressionTimer = null;
1955
- }
1956
- this.rafScheduler.cancel("maybe-scroll");
1957
- this.rafScheduler.cancel("reveal");
1958
- this.rafScheduler.cancel("immediate-reveal");
1959
- this.rafScheduler.cancel("maybe-resume");
1960
- this._hasScrollBar = false;
1961
- this.shouldAutoScroll = !!this.autoScrollInitial;
1962
- this.lastScrollTop = 0;
1963
- if (this.editorHeightManager) {
1964
- this.editorHeightManager.dispose();
1965
- this.editorHeightManager = null;
1966
- }
1967
- }
1968
- };
1969
-
1970
- //#endregion
1971
- //#region src/reactivity.ts
1972
- function computed$1(getter) {
1973
- const c = computed(() => getter());
1974
- return Object.defineProperty({}, "value", {
1975
- get() {
1976
- return c();
1977
- },
1978
- set(_) {},
1979
- enumerable: true,
1980
- configurable: false
1981
- });
1982
- }
1983
-
1984
- //#endregion
1985
- //#region src/utils/arraysEqual.ts
1986
- function arraysEqual(a, b) {
1987
- if (a === b) return true;
1988
- if (!a || !b) return false;
1989
- if (a.length !== b.length) return false;
1990
- for (let i = 0; i < a.length; i++) if (a[i] !== b[i]) return false;
1991
- return true;
1992
- }
1993
-
1994
- //#endregion
1995
- //#region src/utils/registerMonacoThemes.ts
1996
- const LEGACY_ONIG_INIT_KEY = "__streamMonacoLegacyOnigurumaInit__";
1997
- const LEGACY_ENGINE_KEY = "__streamMonacoLegacyShikiEngine__";
1998
- const LEGACY_MONACO_LANGS_INIT_KEY = "__streamMonacoLegacyMonacoLangsInit__";
1999
- async function awaitLegacyOnigurumaInitIfPresent() {
2000
- try {
2001
- var _globalThis;
2002
- const p = (_globalThis = globalThis) === null || _globalThis === void 0 ? void 0 : _globalThis[LEGACY_ONIG_INIT_KEY];
2003
- if (p && typeof p.then === "function") await p;
2004
- } catch {}
2005
- }
2006
- async function awaitLegacyMonacoLanguageContributionsIfPresent() {
2007
- try {
2008
- var _globalThis2;
2009
- const p = (_globalThis2 = globalThis) === null || _globalThis2 === void 0 ? void 0 : _globalThis2[LEGACY_MONACO_LANGS_INIT_KEY];
2010
- if (p && typeof p.then === "function") await p;
2011
- } catch {}
2012
- }
2013
- async function getLegacyShikiEngineIfPresent() {
2014
- try {
2015
- var _globalThis3;
2016
- const p = (_globalThis3 = globalThis) === null || _globalThis3 === void 0 ? void 0 : _globalThis3[LEGACY_ENGINE_KEY];
2017
- if (p && typeof p.then === "function") return await p;
2018
- } catch {}
2019
- return null;
2020
- }
2021
- async function createHighlighterWithLegacyEngineIfNeeded(options) {
2022
- await awaitLegacyOnigurumaInitIfPresent();
2023
- await awaitLegacyMonacoLanguageContributionsIfPresent();
2024
- const engine = await getLegacyShikiEngineIfPresent();
2025
- if (engine) return createHighlighter({
2026
- ...options,
2027
- engine
2028
- });
2029
- return createHighlighter(options);
2030
- }
2031
- let languagesRegistered = false;
2032
- let currentLanguages = [];
2033
- let themeRegisterPromise = null;
2034
- let registrationQueue = Promise.resolve();
2035
- function enqueueRegistration(task) {
2036
- const next = registrationQueue.then(task, task);
2037
- registrationQueue = next.then(() => void 0, () => void 0);
2038
- return next;
2039
- }
2040
- function setThemeRegisterPromise(p) {
2041
- return themeRegisterPromise = p;
2042
- }
2043
- const highlighterCache = /* @__PURE__ */ new Map();
2044
- let monacoHighlighterPromise = null;
2045
- let lastPatchedHighlighter = null;
2046
- let lastPatchedLanguages = /* @__PURE__ */ new Set();
2047
- const monacoThemeByKey = /* @__PURE__ */ new Map();
2048
- const monacoLanguageSet = /* @__PURE__ */ new Set();
2049
- function themeKey(t) {
2050
- return typeof t === "string" ? t : t.name ?? JSON.stringify(t);
2051
- }
2052
- async function ensureMonacoHighlighter(themes, languages$1) {
2053
- for (const t of themes) monacoThemeByKey.set(themeKey(t), t);
2054
- for (const l of languages$1) monacoLanguageSet.add(l);
2055
- if (!monacoHighlighterPromise) {
2056
- const initialThemes = Array.from(monacoThemeByKey.values());
2057
- const initialLangs = Array.from(monacoLanguageSet.values());
2058
- monacoHighlighterPromise = createHighlighterWithLegacyEngineIfNeeded({
2059
- themes: initialThemes,
2060
- langs: initialLangs
2061
- }).then((h$1) => h$1);
2062
- }
2063
- const h = await monacoHighlighterPromise;
2064
- const wantsThemes = Array.from(monacoThemeByKey.values());
2065
- const wantsLangs = Array.from(monacoLanguageSet.values());
2066
- const canLoadTheme = typeof h.loadTheme === "function";
2067
- const canLoadLanguage = typeof h.loadLanguage === "function";
2068
- if (canLoadTheme || canLoadLanguage) {
2069
- if (canLoadTheme) for (const t of themes) {
2070
- const k = themeKey(t);
2071
- if (!h.__streamMonacoLoadedThemes) h.__streamMonacoLoadedThemes = /* @__PURE__ */ new Set();
2072
- const loaded = h.__streamMonacoLoadedThemes;
2073
- if (loaded.has(k)) continue;
2074
- await h.loadTheme(t);
2075
- loaded.add(k);
2076
- }
2077
- if (canLoadLanguage) for (const l of languages$1) {
2078
- if (!h.__streamMonacoLoadedLangs) h.__streamMonacoLoadedLangs = /* @__PURE__ */ new Set();
2079
- const loaded = h.__streamMonacoLoadedLangs;
2080
- if (loaded.has(l)) continue;
2081
- await h.loadLanguage(l);
2082
- loaded.add(l);
2083
- }
2084
- return h;
2085
- }
2086
- const p = createHighlighterWithLegacyEngineIfNeeded({
2087
- themes: wantsThemes,
2088
- langs: wantsLangs
2089
- }).then((hh) => hh);
2090
- monacoHighlighterPromise = p;
2091
- return p;
2092
- }
2093
- /**
2094
- * Clear all cached shiki highlighters.
2095
- *
2096
- * Useful for long-running apps that dynamically create many theme combinations,
2097
- * or in tests to ensure a clean state. Call this when you know the highlighters
2098
- * are no longer needed (for example on app shutdown) to free memory.
2099
- */
2100
- function clearHighlighterCache() {
2101
- highlighterCache.clear();
2102
- }
2103
- function serializeThemes(themes) {
2104
- return JSON.stringify(themes.map((t) => typeof t === "string" ? t : t.name ?? JSON.stringify(t)).sort());
2105
- }
2106
- async function getOrCreateHighlighter(themes, languages$1) {
2107
- const key = serializeThemes(themes);
2108
- const requestedSet = new Set(languages$1);
2109
- let existing = highlighterCache.get(key);
2110
- if (existing) {
2111
- let allIncluded = true;
2112
- for (const l of requestedSet) if (!existing.languages.has(l)) {
2113
- allIncluded = false;
2114
- break;
2115
- }
2116
- if (allIncluded) return existing.promise;
2117
- const prev = existing;
2118
- const current = highlighterCache.get(key);
2119
- if (current && current !== prev) {
2120
- let allIncludedCurrent = true;
2121
- for (const l of requestedSet) if (!current.languages.has(l)) {
2122
- allIncludedCurrent = false;
2123
- break;
2124
- }
2125
- if (allIncludedCurrent) return current.promise;
2126
- existing = current;
2127
- }
2128
- const union = new Set([...existing.languages, ...requestedSet]);
2129
- const langsArray = Array.from(union);
2130
- const p$1 = createHighlighterWithLegacyEngineIfNeeded({
2131
- themes,
2132
- langs: langsArray
2133
- });
2134
- const newEntry = {
2135
- promise: p$1,
2136
- languages: union
2137
- };
2138
- highlighterCache.set(key, newEntry);
2139
- p$1.catch(() => {
2140
- if (highlighterCache.get(key) === newEntry && prev) highlighterCache.set(key, prev);
2141
- });
2142
- return p$1;
2143
- }
2144
- const p = createHighlighterWithLegacyEngineIfNeeded({
2145
- themes,
2146
- langs: Array.from(requestedSet)
2147
- });
2148
- const entry = {
2149
- promise: p,
2150
- languages: requestedSet
2151
- };
2152
- highlighterCache.set(key, entry);
2153
- p.catch(() => {
2154
- if (highlighterCache.get(key) === entry) highlighterCache.delete(key);
2155
- });
2156
- return p;
2157
- }
2158
- /**
2159
- * Update the theme used by the shiki highlighter for a given themes+languages
2160
- * combination. Useful when Monaco themes are already registered (so switching
2161
- * Monaco only requires `monaco.editor.setTheme`) but you also want shiki's
2162
- * standalone renderer to use the new theme without recreating everything.
2163
- */
2164
- async function registerMonacoThemes(themes, languages$1) {
2165
- return enqueueRegistration(async () => {
2166
- registerMonacoLanguages(languages$1);
2167
- const p = (async () => {
2168
- const highlighter = await ensureMonacoHighlighter(themes, languages$1);
2169
- const wantsLangs = Array.from(monacoLanguageSet.values());
2170
- const needsLanguagePatch = lastPatchedHighlighter !== highlighter || wantsLangs.some((l) => !lastPatchedLanguages.has(l));
2171
- if (needsLanguagePatch) {
2172
- if (lastPatchedHighlighter !== highlighter) lastPatchedLanguages = /* @__PURE__ */ new Set();
2173
- const realLanguages = monaco_shim_exports.languages;
2174
- const realEditor = monaco_shim_exports.editor;
2175
- const setTokensProvider = typeof (realLanguages === null || realLanguages === void 0 ? void 0 : realLanguages.setTokensProvider) === "function" ? realLanguages.setTokensProvider.bind(realLanguages) : null;
2176
- const getLanguages = typeof (realLanguages === null || realLanguages === void 0 ? void 0 : realLanguages.getLanguages) === "function" ? realLanguages.getLanguages.bind(realLanguages) : null;
2177
- const monacoProxy = {
2178
- __proto__: monaco_shim_exports,
2179
- editor: realEditor,
2180
- languages: {
2181
- __proto__: realLanguages,
2182
- getLanguages,
2183
- setTokensProvider(lang, provider) {
2184
- if (provider && typeof provider.tokenize === "function") {
2185
- const originalTokenize = provider.tokenize.bind(provider);
2186
- provider = {
2187
- ...provider,
2188
- tokenize(line, state) {
2189
- try {
2190
- return originalTokenize(line, state);
2191
- } catch {
2192
- return {
2193
- endState: state,
2194
- tokens: [{
2195
- startIndex: 0,
2196
- scopes: ""
2197
- }]
2198
- };
2199
- }
2200
- }
2201
- };
2202
- }
2203
- return setTokensProvider === null || setTokensProvider === void 0 ? void 0 : setTokensProvider(lang, provider);
2204
- }
2205
- }
2206
- };
2207
- shikiToMonaco(highlighter, monacoProxy);
2208
- lastPatchedHighlighter = highlighter;
2209
- lastPatchedLanguages = new Set(wantsLangs);
2210
- }
2211
- currentLanguages = languages$1.slice();
2212
- return highlighter;
2213
- })();
2214
- setThemeRegisterPromise(p);
2215
- try {
2216
- const res = await p;
2217
- return res;
2218
- } catch (e) {
2219
- setThemeRegisterPromise(null);
2220
- throw e;
2221
- }
2222
- });
2223
- }
2224
- function registerMonacoLanguages(languages$1) {
2225
- if (languagesRegistered && arraysEqual(languages$1, currentLanguages)) return;
2226
- const existing = new Set(monaco_shim_exports.languages.getLanguages().map((l) => l.id));
2227
- for (const lang of languages$1) if (!existing.has(lang)) try {
2228
- monaco_shim_exports.languages.register({ id: lang });
2229
- } catch {}
2230
- languagesRegistered = true;
2231
- currentLanguages = languages$1;
2232
- }
2233
-
2234
- //#endregion
2235
- //#region src/type.ts
2236
- let RevealStrategy = /* @__PURE__ */ function(RevealStrategy$1) {
2237
- RevealStrategy$1["Bottom"] = "bottom";
2238
- RevealStrategy$1["CenterIfOutside"] = "centerIfOutside";
2239
- RevealStrategy$1["Center"] = "center";
2240
- return RevealStrategy$1;
2241
- }({});
2242
-
2243
- //#endregion
2244
- //#region src/index.base.ts
2245
- let globalRequestedThemeName = null;
2246
- let globalThemeRequestSeq = 0;
2247
- let globalAppliedThemeName = null;
2248
- /**
2249
- * useMonaco 组合式函数
2250
- *
2251
- * 提供 Monaco 编辑器的创建、销毁、内容/主题/语言更新等能力。
2252
- * 支持主题自动切换、语言高亮、代码更新等功能。
2253
- *
2254
- * @param {MonacoOptions} [monacoOptions] - 编辑器初始化配置,支持 Monaco 原生配置及扩展项
2255
- * @param {number | string} [monacoOptions.MAX_HEIGHT] - 编辑器最大高度,可以是数字(像素)或 CSS 字符串(如 '100%', 'calc(100vh - 100px)')
2256
- * @param {boolean} [monacoOptions.readOnly] - 是否为只读模式
2257
- * @param {MonacoTheme[]} [monacoOptions.themes] - 主题数组,至少包含两个主题:[暗色主题, 亮色主题]
2258
- * @param {MonacoLanguage[]} [monacoOptions.languages] - 支持的编程语言数组
2259
- * @param {string} [monacoOptions.theme] - 初始主题名称
2260
- * @param {boolean} [monacoOptions.isCleanOnBeforeCreate] - 是否在创建前清理之前注册的资源, 默认为 true
2261
- * @param {(monaco: typeof import('monaco-editor')) => monaco.IDisposable[]} [monacoOptions.onBeforeCreate] - 编辑器创建前的钩子函数
2262
- *
2263
- * @returns {{
2264
- * createEditor: (container: HTMLElement, code: string, language: string) => Promise<monaco.editor.IStandaloneCodeEditor>,
2265
- * createDiffEditor: (
2266
- * container: HTMLElement,
2267
- * originalCode: string,
2268
- * modifiedCode: string,
2269
- * language: string,
2270
- * ) => Promise<monaco.editor.IStandaloneDiffEditor>,
2271
- * cleanupEditor: () => void,
2272
- * updateCode: (newCode: string, codeLanguage: string) => void,
2273
- * appendCode: (appendText: string, codeLanguage?: string) => void,
2274
- * updateDiff: (
2275
- * originalCode: string,
2276
- * modifiedCode: string,
2277
- * codeLanguage?: string,
2278
- * ) => void,
2279
- * updateOriginal: (newCode: string, codeLanguage?: string) => void,
2280
- * updateModified: (newCode: string, codeLanguage?: string) => void,
2281
- * appendOriginal: (appendText: string, codeLanguage?: string) => void,
2282
- * appendModified: (appendText: string, codeLanguage?: string) => void,
2283
- * setTheme: (theme: MonacoTheme) => Promise<void>,
2284
- * setLanguage: (language: MonacoLanguage) => void,
2285
- * getCurrentTheme: () => string,
2286
- * getEditor: () => typeof monaco.editor,
2287
- * getEditorView: () => monaco.editor.IStandaloneCodeEditor | null,
2288
- * getDiffEditorView: () => monaco.editor.IStandaloneDiffEditor | null,
2289
- * getDiffModels: () => { original: monaco.editor.ITextModel | null, modified: monaco.editor.ITextModel | null },
2290
- * getCode: () => string | { original: string, modified: string } | null,
2291
- * }} 返回对象包含以下方法和属性:
2292
- *
2293
- * @property {Function} createEditor - 创建并挂载 Monaco 编辑器到指定容器
2294
- * @property {Function} cleanupEditor - 销毁编辑器并清理容器
2295
- * @property {Function} updateCode - 更新编辑器内容和语言,必要时滚动到底部
2296
- * @property {Function} appendCode - 在编辑器末尾追加文本,必要时滚动到底部
2297
- * @property {Function} createDiffEditor - 创建并挂载 Diff 编辑器
2298
- * @property {Function} updateDiff - 更新 Diff 编辑器的 original/modified 内容(RAF 合并、增量更新)
2299
- * @property {Function} updateOriginal - 仅更新 Diff 的 original 内容(增量更新)
2300
- * @property {Function} updateModified - 仅更新 Diff 的 modified 内容(增量更新)
2301
- * @property {Function} appendOriginal - 在 Diff 的 original 末尾追加(显式流式场景)
2302
- * @property {Function} appendModified - 在 Diff 的 modified 末尾追加(显式流式场景)
2303
- * @property {Function} setTheme - 切换编辑器主题,返回 Promise,在主题应用完成时 resolve
2304
- * @property {Function} setLanguage - 切换编辑器语言
2305
- * @property {Function} getCurrentTheme - 获取当前主题名称
2306
- * @property {Function} getEditor - 获取 Monaco 的静态 editor 对象(用于静态方法调用)
2307
- * @property {Function} getEditorView - 获取当前编辑器实例
2308
- * @property {Function} getDiffEditorView - 获取当前 Diff 编辑器实例
2309
- * @property {Function} getDiffModels - 获取 Diff 的 original/modified 两个模型
2310
- * @property {Function} getCode - 获取当前编辑器或 Diff 编辑器中的代码内容
2311
- *
2312
- * @throws {Error} 当主题数组不是数组或长度小于2时抛出错误
2313
- *
2314
- * @example
2315
- * ```typescript
2316
- * import { useMonaco } from 'stream-monaco'
2317
- *
2318
- * const { createEditor, updateCode, setTheme } = useMonaco({
2319
- * themes: ['vitesse-dark', 'vitesse-light'],
2320
- * languages: ['javascript', 'typescript'],
2321
- * readOnly: false
2322
- * })
2323
- *
2324
- * // 创建编辑器
2325
- * const editor = await createEditor(containerRef.value, 'console.log("hello")', 'javascript')
2326
- *
2327
- * // 更新代码
2328
- * updateCode('console.log("world")', 'javascript')
2329
- *
2330
- * // 切换主题
2331
- * setTheme('vitesse-light')
2332
- * ```
2333
- */
2334
- function useMonaco(monacoOptions = {}) {
2335
- var _monacoOptions$themes;
2336
- const disposals = [];
2337
- if (monacoOptions.isCleanOnBeforeCreate ?? true) disposals.forEach((d) => d.dispose());
2338
- if (monacoOptions.isCleanOnBeforeCreate ?? true) disposals.length = 0;
2339
- let editorView = null;
2340
- let editorMgr = null;
2341
- let diffEditorView = null;
2342
- let diffMgr = null;
2343
- let originalModel = null;
2344
- let modifiedModel = null;
2345
- let _hasScrollBar = false;
2346
- const themes = monacoOptions.themes && ((_monacoOptions$themes = monacoOptions.themes) === null || _monacoOptions$themes === void 0 ? void 0 : _monacoOptions$themes.length) ? monacoOptions.themes : defaultThemes;
2347
- if (!Array.isArray(themes) || themes.length < 2) throw new Error("Monaco themes must be an array with at least two themes: [darkTheme, lightTheme]");
2348
- const languages$1 = monacoOptions.languages ?? defaultLanguages;
2349
- const MAX_HEIGHT = monacoOptions.MAX_HEIGHT ?? 500;
2350
- const autoScrollOnUpdate = monacoOptions.autoScrollOnUpdate ?? true;
2351
- const autoScrollInitial = monacoOptions.autoScrollInitial ?? true;
2352
- const autoScrollThresholdPx = monacoOptions.autoScrollThresholdPx ?? 32;
2353
- const autoScrollThresholdLines = monacoOptions.autoScrollThresholdLines ?? 2;
2354
- const diffAutoScroll = monacoOptions.diffAutoScroll ?? true;
2355
- const getMaxHeightValue = () => {
2356
- if (typeof MAX_HEIGHT === "number") return MAX_HEIGHT;
2357
- const match = MAX_HEIGHT.match(/^(\d+(?:\.\d+)?)/);
2358
- return match ? Number.parseFloat(match[1]) : 500;
2359
- };
2360
- const getMaxHeightCSS = () => {
2361
- if (typeof MAX_HEIGHT === "number") return `${MAX_HEIGHT}px`;
2362
- return MAX_HEIGHT;
2363
- };
2364
- const maxHeightValue = getMaxHeightValue();
2365
- const maxHeightCSS = getMaxHeightCSS();
2366
- let lastContainer = null;
2367
- let lastKnownCode = null;
2368
- const minimalEditMaxCharsLocal = monacoOptions.minimalEditMaxChars ?? minimalEditMaxChars;
2369
- const minimalEditMaxChangeRatioLocal = monacoOptions.minimalEditMaxChangeRatio ?? minimalEditMaxChangeRatio;
2370
- let updateThrottleMs = monacoOptions.updateThrottleMs ?? 50;
2371
- let lastFlushTime = 0;
2372
- let updateThrottleTimer = null;
2373
- let pendingUpdate = null;
2374
- let shouldAutoScroll = true;
2375
- const cachedComputedHeight = null;
2376
- const appendBuffer = [];
2377
- let appendBufferScheduled = false;
2378
- const currentTheme = computed$1(() => monacoOptions.theme ?? (typeof themes[0] === "string" ? themes[0] : themes[0].name));
2379
- let requestedThemeName = monacoOptions.theme ?? globalRequestedThemeName ?? currentTheme.value;
2380
- let themeWatcher = null;
2381
- const rafScheduler = createRafScheduler();
2382
- async function tryLoadAndSetShikiTheme(highlighter, themeName) {
2383
- if (!highlighter || typeof highlighter.setTheme !== "function") return;
2384
- try {
2385
- await highlighter.setTheme(themeName);
2386
- } catch (err) {
2387
- const message = (err === null || err === void 0 ? void 0 : err.message) ? String(err.message) : String(err);
2388
- const lower = message.toLowerCase();
2389
- const looksLikeMissingThemeError = lower.includes("theme") && lower.includes("not found");
2390
- if (typeof highlighter.loadTheme === "function" && looksLikeMissingThemeError) {
2391
- await highlighter.loadTheme(themeName);
2392
- await highlighter.setTheme(themeName);
2393
- return;
2394
- }
2395
- throw err;
2396
- }
2397
- }
2398
- async function setThemeInternal(theme, force = false) {
2399
- const themeName = typeof theme === "string" ? theme : theme.name;
2400
- globalThemeRequestSeq += 1;
2401
- const token = globalThemeRequestSeq;
2402
- requestedThemeName = themeName;
2403
- globalRequestedThemeName = themeName;
2404
- if (!force && themeName === globalAppliedThemeName) return;
2405
- if (token !== globalThemeRequestSeq) return;
2406
- await registerMonacoThemes(themes, languages$1).catch(() => void 0);
2407
- if (token !== globalThemeRequestSeq) return;
2408
- const availableNames = themes.map((t) => typeof t === "string" ? t : t.name);
2409
- if (!availableNames.includes(themeName)) try {
2410
- const extended = availableNames.concat(themeName);
2411
- const maybeHighlighter = await registerMonacoThemes(extended, languages$1);
2412
- await tryLoadAndSetShikiTheme(maybeHighlighter, themeName).catch(() => void 0);
2413
- } catch {
2414
- console.warn(`Theme "${themeName}" is not registered and automatic registration failed. Available themes: ${availableNames.join(", ")}`);
2415
- return;
2416
- }
2417
- if (token !== globalThemeRequestSeq) return;
2418
- try {
2419
- monaco_shim_exports.editor.setTheme(themeName);
2420
- globalAppliedThemeName = themeName;
2421
- } catch {
2422
- try {
2423
- const maybeHighlighter = await registerMonacoThemes(themes, languages$1);
2424
- if (token !== globalThemeRequestSeq) return;
2425
- monaco_shim_exports.editor.setTheme(themeName);
2426
- globalAppliedThemeName = themeName;
2427
- await tryLoadAndSetShikiTheme(maybeHighlighter, themeName).catch(() => void 0);
2428
- } catch (err2) {
2429
- console.warn(`Failed to set theme "${themeName}":`, err2);
2430
- return;
2431
- }
2432
- }
2433
- if (token !== globalThemeRequestSeq) return;
2434
- try {
2435
- if (typeof monacoOptions.onThemeChange === "function") await monacoOptions.onThemeChange(themeName);
2436
- } catch (err) {
2437
- console.warn("onThemeChange callback threw an error:", err);
2438
- }
2439
- }
2440
- async function ensureThemeRegistered(themeName) {
2441
- const availableNames = themes.map((t) => typeof t === "string" ? t : t.name);
2442
- const list = availableNames.includes(themeName) ? themes : themes.concat(themeName);
2443
- await registerMonacoThemes(list, languages$1);
2444
- }
2445
- function hasVerticalScrollbar() {
2446
- if (!editorView) return false;
2447
- if (_hasScrollBar) return true;
2448
- const ch = cachedComputedHeight ?? computedHeight(editorView);
2449
- return _hasScrollBar = editorView.getScrollHeight() > ch + padding / 2;
2450
- }
2451
- let revealDebounceId = null;
2452
- const revealDebounceMs = 75;
2453
- function maybeScrollToBottom(targetLine) {
2454
- if (autoScrollOnUpdate && shouldAutoScroll && hasVerticalScrollbar()) {
2455
- const model = editorView.getModel();
2456
- const line = targetLine ?? (model === null || model === void 0 ? void 0 : model.getLineCount()) ?? 1;
2457
- if (revealDebounceId != null) {
2458
- clearTimeout(revealDebounceId);
2459
- revealDebounceId = null;
2460
- }
2461
- revealDebounceId = setTimeout(() => {
2462
- revealDebounceId = null;
2463
- rafScheduler.schedule("reveal", () => {
2464
- try {
2465
- var _editor;
2466
- const ScrollType = monaco_shim_exports.ScrollType || ((_editor = monaco_shim_exports.editor) === null || _editor === void 0 ? void 0 : _editor.ScrollType);
2467
- if (ScrollType && typeof ScrollType.Smooth !== "undefined") editorView.revealLineInCenterIfOutsideViewport(line, ScrollType.Smooth);
2468
- else editorView.revealLineInCenterIfOutsideViewport(line);
2469
- } catch {}
2470
- });
2471
- }, revealDebounceMs);
2472
- }
2473
- }
2474
- async function createEditor(container, code, language) {
2475
- cleanupEditor();
2476
- lastContainer = container;
2477
- if (monacoOptions.isCleanOnBeforeCreate ?? true) {
2478
- disposals.forEach((d) => d.dispose());
2479
- disposals.length = 0;
2480
- }
2481
- if (monacoOptions.onBeforeCreate) {
2482
- const ds = monacoOptions.onBeforeCreate(monaco_shim_exports);
2483
- if (ds) disposals.push(...ds);
2484
- }
2485
- const initialThemeName = requestedThemeName ?? monacoOptions.theme ?? globalRequestedThemeName ?? currentTheme.value;
2486
- await ensureThemeRegistered(initialThemeName);
2487
- editorMgr = new EditorManager(monacoOptions, maxHeightValue, maxHeightCSS, autoScrollOnUpdate, autoScrollInitial, autoScrollThresholdPx, autoScrollThresholdLines, monacoOptions.revealDebounceMs);
2488
- editorView = await editorMgr.createEditor(container, code, language, initialThemeName);
2489
- if (pendingUpdate && editorMgr) {
2490
- const { code: queuedCode, lang: queuedLang } = pendingUpdate;
2491
- pendingUpdate = null;
2492
- editorMgr.updateCode(queuedCode, queuedLang);
2493
- }
2494
- if (typeof monacoOptions.onThemeChange === "function") monacoOptions.onThemeChange(initialThemeName);
2495
- if (editorView) lastKnownCode = editorView.getValue();
2496
- return editorView;
2497
- }
2498
- function computedHeight(editorView$1) {
2499
- var _getModel;
2500
- const lineCount = ((_getModel = editorView$1.getModel()) === null || _getModel === void 0 ? void 0 : _getModel.getLineCount()) ?? 1;
2501
- const lineHeight = editorView$1.getOption(monaco_shim_exports.editor.EditorOption.lineHeight);
2502
- const height = Math.min(lineCount * lineHeight + padding, maxHeightValue);
2503
- return height;
2504
- }
2505
- async function createDiffEditor(container, originalCode, modifiedCode, language) {
2506
- cleanupEditor();
2507
- lastContainer = container;
2508
- if (monacoOptions.isCleanOnBeforeCreate ?? true) {
2509
- disposals.forEach((d) => d.dispose());
2510
- disposals.length = 0;
2511
- }
2512
- if (monacoOptions.onBeforeCreate) {
2513
- const ds = monacoOptions.onBeforeCreate(monaco_shim_exports);
2514
- if (ds) disposals.push(...ds);
2515
- }
2516
- const initialThemeName = requestedThemeName ?? monacoOptions.theme ?? globalRequestedThemeName ?? currentTheme.value;
2517
- await ensureThemeRegistered(initialThemeName);
2518
- try {
2519
- monaco_shim_exports.editor.setTheme(initialThemeName);
2520
- } catch {}
2521
- diffMgr = new DiffEditorManager(monacoOptions, maxHeightValue, maxHeightCSS, autoScrollOnUpdate, autoScrollInitial, autoScrollThresholdPx, autoScrollThresholdLines, diffAutoScroll, monacoOptions.revealDebounceMs, monacoOptions.diffUpdateThrottleMs);
2522
- diffEditorView = await diffMgr.createDiffEditor(container, originalCode, modifiedCode, language, initialThemeName);
2523
- if (typeof monacoOptions.onThemeChange === "function") monacoOptions.onThemeChange(initialThemeName);
2524
- const models = diffMgr.getDiffModels();
2525
- originalModel = models.original;
2526
- modifiedModel = models.modified;
2527
- return diffEditorView;
2528
- }
2529
- function cleanupEditor() {
2530
- if (editorMgr) {
2531
- editorMgr.cleanup();
2532
- editorMgr = null;
2533
- }
2534
- if (diffMgr) {
2535
- diffMgr.cleanup();
2536
- diffMgr = null;
2537
- }
2538
- rafScheduler.cancel("update");
2539
- pendingUpdate = null;
2540
- rafScheduler.cancel("append");
2541
- appendBufferScheduled = false;
2542
- appendBuffer.length = 0;
2543
- if (!editorMgr && editorView) {
2544
- editorView.dispose();
2545
- editorView = null;
2546
- }
2547
- lastKnownCode = null;
2548
- if (lastContainer) {
2549
- lastContainer.innerHTML = "";
2550
- lastContainer = null;
2551
- }
2552
- if (themeWatcher) {
2553
- themeWatcher();
2554
- themeWatcher = null;
2555
- }
2556
- if (updateThrottleTimer != null) {
2557
- clearTimeout(updateThrottleTimer);
2558
- updateThrottleTimer = null;
2559
- }
2560
- diffEditorView = null;
2561
- originalModel = null;
2562
- modifiedModel = null;
2563
- }
2564
- function appendCode(appendText, codeLanguage) {
2565
- if (editorMgr) editorMgr.appendCode(appendText, codeLanguage);
2566
- else {
2567
- if (!editorView) return;
2568
- const model = editorView.getModel();
2569
- if (!model) return;
2570
- const processedCodeLanguage = codeLanguage ? processedLanguage(codeLanguage) : model.getLanguageId();
2571
- if (processedCodeLanguage && model.getLanguageId() !== processedCodeLanguage) monaco_shim_exports.editor.setModelLanguage(model, processedCodeLanguage);
2572
- if (appendText && lastKnownCode != null) lastKnownCode = lastKnownCode + appendText;
2573
- if (appendText) {
2574
- appendBuffer.push(appendText);
2575
- if (!appendBufferScheduled) {
2576
- appendBufferScheduled = true;
2577
- rafScheduler.schedule("append", flushAppendBuffer);
2578
- }
2579
- }
2580
- }
2581
- }
2582
- function applyMinimalEdit(prev, next) {
2583
- if (!editorView) return;
2584
- const model = editorView.getModel();
2585
- if (!model) return;
2586
- try {
2587
- const maxChars = minimalEditMaxCharsLocal;
2588
- const ratio = minimalEditMaxChangeRatioLocal;
2589
- const maxLen = Math.max(prev.length, next.length);
2590
- const changeRatio = maxLen > 0 ? Math.abs(next.length - prev.length) / maxLen : 0;
2591
- if (prev.length + next.length > maxChars || changeRatio > ratio) {
2592
- const prevLineCount = model.getLineCount();
2593
- model.setValue(next);
2594
- lastKnownCode = next;
2595
- const newLineCount = model.getLineCount();
2596
- if (newLineCount !== prevLineCount) maybeScrollToBottom(newLineCount);
2597
- return;
2598
- }
2599
- } catch {}
2600
- const res = computeMinimalEdit(prev, next);
2601
- if (!res) return;
2602
- const { start, endPrevIncl, replaceText } = res;
2603
- const rangeStart = model.getPositionAt(start);
2604
- const rangeEnd = model.getPositionAt(endPrevIncl + 1);
2605
- const range = new monaco_shim_exports.Range(rangeStart.lineNumber, rangeStart.column, rangeEnd.lineNumber, rangeEnd.column);
2606
- const isReadOnly = editorView.getOption(monaco_shim_exports.editor.EditorOption.readOnly);
2607
- const edit = [{
2608
- range,
2609
- text: replaceText,
2610
- forceMoveMarkers: true
2611
- }];
2612
- if (isReadOnly) model.applyEdits(edit);
2613
- else editorView.executeEdits("minimal-replace", edit);
2614
- }
2615
- function flushPendingUpdate() {
2616
- if (!pendingUpdate) return;
2617
- lastFlushTime = Date.now();
2618
- if (!editorView) return;
2619
- const model = editorView.getModel();
2620
- if (!model) return;
2621
- const { code: newCode, lang: codeLanguage } = pendingUpdate;
2622
- pendingUpdate = null;
2623
- const processedCodeLanguage = processedLanguage(codeLanguage);
2624
- let prevCode = null;
2625
- if (appendBuffer.length > 0) try {
2626
- prevCode = model.getValue();
2627
- lastKnownCode = prevCode;
2628
- } catch {
2629
- prevCode = "";
2630
- }
2631
- else {
2632
- prevCode = lastKnownCode;
2633
- if (prevCode == null) try {
2634
- prevCode = model.getValue();
2635
- lastKnownCode = prevCode;
2636
- } catch {
2637
- prevCode = "";
2638
- }
2639
- }
2640
- if (prevCode === newCode) return;
2641
- const languageId = model.getLanguageId();
2642
- if (languageId !== processedCodeLanguage) {
2643
- if (processedCodeLanguage) monaco_shim_exports.editor.setModelLanguage(model, processedCodeLanguage);
2644
- const prevLineCount = model.getLineCount();
2645
- model.setValue(newCode);
2646
- lastKnownCode = newCode;
2647
- const newLineCount = model.getLineCount();
2648
- if (newLineCount !== prevLineCount) maybeScrollToBottom(newLineCount);
2649
- return;
2650
- }
2651
- if (newCode.startsWith(prevCode) && prevCode.length < newCode.length) {
2652
- const suffix = newCode.slice(prevCode.length);
2653
- if (suffix) appendCode(suffix, codeLanguage);
2654
- lastKnownCode = newCode;
2655
- return;
2656
- }
2657
- try {
2658
- const maxChars = minimalEditMaxCharsLocal;
2659
- const ratio = minimalEditMaxChangeRatioLocal;
2660
- const maxLen = Math.max(prevCode.length, newCode.length);
2661
- const changeRatio = maxLen > 0 ? Math.abs(newCode.length - prevCode.length) / maxLen : 0;
2662
- if (prevCode.length + newCode.length > maxChars || changeRatio > ratio) {
2663
- const prevLineCount = model.getLineCount();
2664
- model.setValue(newCode);
2665
- lastKnownCode = newCode;
2666
- const newLineCount = model.getLineCount();
2667
- if (newLineCount !== prevLineCount) maybeScrollToBottom(newLineCount);
2668
- return;
2669
- }
2670
- } catch {}
2671
- try {
2672
- applyMinimalEdit(prevCode, newCode);
2673
- lastKnownCode = newCode;
2674
- const newLineCount = model.getLineCount();
2675
- const prevLineCount = (prevCode ? prevCode.split("\n").length : 0) || model.getLineCount();
2676
- if (newLineCount !== prevLineCount) maybeScrollToBottom(newLineCount);
2677
- } catch {
2678
- try {
2679
- const prevLineCount = model.getLineCount();
2680
- model.setValue(newCode);
2681
- lastKnownCode = newCode;
2682
- const newLineCount = model.getLineCount();
2683
- if (newLineCount !== prevLineCount) maybeScrollToBottom(newLineCount);
2684
- } catch {}
2685
- }
2686
- }
2687
- function flushAppendBuffer() {
2688
- if (!editorView) return;
2689
- if (appendBuffer.length === 0) return;
2690
- appendBufferScheduled = false;
2691
- const model = editorView.getModel();
2692
- if (!model) {
2693
- appendBuffer.length = 0;
2694
- return;
2695
- }
2696
- const text = appendBuffer.join("");
2697
- appendBuffer.length = 0;
2698
- try {
2699
- const lastLine = model.getLineCount();
2700
- const lastColumn = model.getLineMaxColumn(lastLine);
2701
- const range = new monaco_shim_exports.Range(lastLine, lastColumn, lastLine, lastColumn);
2702
- const isReadOnly = editorView.getOption(monaco_shim_exports.editor.EditorOption.readOnly);
2703
- if (isReadOnly) model.applyEdits([{
2704
- range,
2705
- text,
2706
- forceMoveMarkers: true
2707
- }]);
2708
- else editorView.executeEdits("append", [{
2709
- range,
2710
- text,
2711
- forceMoveMarkers: true
2712
- }]);
2713
- if (lastKnownCode != null) lastKnownCode = lastKnownCode + text;
2714
- try {
2715
- if (lastLine !== model.getLineCount()) maybeScrollToBottom(model.getLineCount());
2716
- } catch {}
2717
- } catch {}
2718
- }
2719
- function updateCode(newCode, codeLanguage) {
2720
- if (editorMgr) editorMgr.updateCode(newCode, codeLanguage);
2721
- else {
2722
- pendingUpdate = {
2723
- code: newCode,
2724
- lang: codeLanguage
2725
- };
2726
- rafScheduler.schedule("update", () => {
2727
- if (!updateThrottleMs) {
2728
- flushPendingUpdate();
2729
- return;
2730
- }
2731
- const now = Date.now();
2732
- const since = now - lastFlushTime;
2733
- if (since >= updateThrottleMs) {
2734
- flushPendingUpdate();
2735
- return;
2736
- }
2737
- if (updateThrottleTimer != null) return;
2738
- const wait = updateThrottleMs - since;
2739
- updateThrottleTimer = setTimeout(() => {
2740
- updateThrottleTimer = null;
2741
- rafScheduler.schedule("update", () => flushPendingUpdate());
2742
- }, wait);
2743
- });
2744
- }
2745
- }
2746
- function setUpdateThrottleMs(ms) {
2747
- updateThrottleMs = ms;
2748
- }
2749
- function getUpdateThrottleMs() {
2750
- return updateThrottleMs;
2751
- }
2752
- function updateDiff(originalCode, modifiedCode, codeLanguage) {
2753
- if (diffMgr) diffMgr.updateDiff(originalCode, modifiedCode, codeLanguage);
2754
- }
2755
- function updateOriginal(newCode, codeLanguage) {
2756
- if (diffMgr) diffMgr.updateOriginal(newCode, codeLanguage);
2757
- }
2758
- function updateModified(newCode, codeLanguage) {
2759
- if (diffMgr) diffMgr.updateModified(newCode, codeLanguage);
2760
- }
2761
- function appendOriginal(appendText, codeLanguage) {
2762
- if (diffMgr) diffMgr.appendOriginal(appendText, codeLanguage);
2763
- }
2764
- function appendModified(appendText, codeLanguage) {
2765
- if (diffMgr) diffMgr.appendModified(appendText, codeLanguage);
2766
- }
2767
- return {
2768
- createEditor,
2769
- createDiffEditor,
2770
- cleanupEditor,
2771
- safeClean() {
2772
- rafScheduler.cancel("update");
2773
- pendingUpdate = null;
2774
- if (editorMgr) try {
2775
- editorMgr.safeClean();
2776
- } catch {}
2777
- if (diffMgr) try {
2778
- diffMgr.safeClean();
2779
- } catch {}
2780
- _hasScrollBar = false;
2781
- shouldAutoScroll = !!autoScrollInitial;
2782
- },
2783
- updateCode,
2784
- appendCode,
2785
- updateDiff,
2786
- updateOriginal,
2787
- updateModified,
2788
- appendOriginal,
2789
- appendModified,
2790
- setTheme: setThemeInternal,
2791
- setLanguage(language) {
2792
- if (editorMgr) {
2793
- editorMgr.setLanguage(language, languages$1);
2794
- return;
2795
- }
2796
- if (diffMgr) {
2797
- diffMgr.setLanguage(language, languages$1);
2798
- return;
2799
- }
2800
- if (languages$1.includes(language)) {
2801
- if (editorView) {
2802
- const model = editorView.getModel();
2803
- if (model && model.getLanguageId() !== language) monaco_shim_exports.editor.setModelLanguage(model, language);
2804
- }
2805
- if (originalModel && originalModel.getLanguageId() !== language) monaco_shim_exports.editor.setModelLanguage(originalModel, language);
2806
- if (modifiedModel && modifiedModel.getLanguageId() !== language) monaco_shim_exports.editor.setModelLanguage(modifiedModel, language);
2807
- } else console.warn(`Language "${language}" is not registered. Available languages: ${languages$1.join(", ")}`);
2808
- },
2809
- getCurrentTheme() {
2810
- return globalAppliedThemeName ?? requestedThemeName ?? globalRequestedThemeName ?? currentTheme.value;
2811
- },
2812
- getEditor() {
2813
- return monaco_shim_exports.editor;
2814
- },
2815
- getEditorView() {
2816
- return editorView;
2817
- },
2818
- getDiffEditorView() {
2819
- return diffEditorView;
2820
- },
2821
- getDiffModels() {
2822
- return {
2823
- original: originalModel,
2824
- modified: modifiedModel
2825
- };
2826
- },
2827
- getMonacoInstance() {
2828
- return monaco_shim_exports;
2829
- },
2830
- setUpdateThrottleMs,
2831
- getUpdateThrottleMs,
2832
- getCode() {
2833
- if (editorView) try {
2834
- var _editorView$getModel;
2835
- return ((_editorView$getModel = editorView.getModel()) === null || _editorView$getModel === void 0 ? void 0 : _editorView$getModel.getValue()) ?? null;
2836
- } catch {
2837
- return null;
2838
- }
2839
- if (diffEditorView || originalModel && modifiedModel) try {
2840
- const original = (originalModel === null || originalModel === void 0 ? void 0 : originalModel.getValue()) ?? "";
2841
- const modified = (modifiedModel === null || modifiedModel === void 0 ? void 0 : modifiedModel.getValue()) ?? "";
2842
- return {
2843
- original,
2844
- modified
2845
- };
2846
- } catch {
2847
- return null;
2848
- }
2849
- return null;
2850
- }
2851
- };
2852
- }
2853
-
2854
- //#endregion
2855
- //#region src/preloadMonacoWorkers.shared.ts
2856
- const editorWorkerPath = "monaco-editor/esm/vs/editor/editor.worker.js";
2857
- const workerPathByLabel = {
2858
- json: "monaco-editor/esm/vs/language/json/json.worker.js",
2859
- css: "monaco-editor/esm/vs/language/css/css.worker.js",
2860
- scss: "monaco-editor/esm/vs/language/css/css.worker.js",
2861
- less: "monaco-editor/esm/vs/language/css/css.worker.js",
2862
- html: "monaco-editor/esm/vs/language/html/html.worker.js",
2863
- handlebars: "monaco-editor/esm/vs/language/html/html.worker.js",
2864
- razor: "monaco-editor/esm/vs/language/html/html.worker.js",
2865
- typescript: "monaco-editor/esm/vs/language/typescript/ts.worker.js",
2866
- javascript: "monaco-editor/esm/vs/language/typescript/ts.worker.js"
2867
- };
2868
- const uniqueWorkerPaths = Array.from(new Set([editorWorkerPath, ...Object.values(workerPathByLabel)]));
2869
-
2870
- //#endregion
2871
- export { RevealStrategy, clearHighlighterCache, defaultRevealDebounceMs, detectLanguage, editorWorkerPath, getOrCreateHighlighter, monaco_shim_exports, processedLanguage, registerMonacoThemes, uniqueWorkerPaths, useMonaco, workerPathByLabel };