stream-monaco 0.0.1 → 0.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,5 +1,6 @@
1
1
  import { __export, __reExport } from "./chunk-CHLpw0oG.js";
2
2
  import * as _monaco from "monaco-editor";
3
+ import nodeProcess from "node:process";
3
4
  import { computed, effect, signal } from "alien-signals";
4
5
  import { shikiToMonaco } from "@shikijs/monaco";
5
6
  import { createHighlighter } from "shiki";
@@ -199,34 +200,107 @@ import * as import_monaco_editor from "monaco-editor";
199
200
  __reExport(monaco_shim_exports, import_monaco_editor);
200
201
  const monaco = _monaco;
201
202
 
203
+ //#endregion
204
+ //#region src/utils/logger.ts
205
+ let seq = 0;
206
+ const ENABLED = (() => {
207
+ try {
208
+ if (typeof window !== "undefined" && window.__STREAM_MONACO_DEBUG__ !== void 0) return Boolean(window.__STREAM_MONACO_DEBUG__);
209
+ try {
210
+ const proc = nodeProcess;
211
+ if (proc && proc.env && proc.env.NODE_ENV !== "production") return true;
212
+ } catch {}
213
+ } catch {}
214
+ return false;
215
+ })();
216
+ function log(tag, ...args) {
217
+ if (!ENABLED) return;
218
+ try {
219
+ seq += 1;
220
+ const id = `#${seq}`;
221
+ const ts = typeof performance !== "undefined" && performance.now ? performance.now().toFixed(1) : Date.now();
222
+ console.warn(`${id} [${tag}] @${ts}ms`, ...args);
223
+ } catch (err) {
224
+ try {
225
+ console.warn("[logger] fallback", tag, ...args, err);
226
+ } catch {}
227
+ }
228
+ }
229
+ function error(tag, ...args) {
230
+ if (!ENABLED) return;
231
+ try {
232
+ console.error(`[${tag}]`, ...args);
233
+ } catch (err) {
234
+ try {
235
+ console.error("[logger] fallback error", tag, ...args, err);
236
+ } catch {}
237
+ }
238
+ }
239
+
202
240
  //#endregion
203
241
  //#region src/utils/height.ts
204
242
  function createHeightManager(container, computeNext) {
205
243
  let raf = null;
244
+ let debounceTimer = null;
206
245
  let lastApplied = -1;
207
246
  let suppressed = false;
247
+ const HYSTERESIS_PX = 12;
248
+ const DEBOUNCE_MS = 0;
208
249
  function apply() {
209
250
  const next = computeNext();
251
+ if (next == null) return;
252
+ log("heightManager", "computeNext ->", {
253
+ next,
254
+ lastApplied
255
+ });
256
+ if (!Number.isFinite(next) || next <= 0) {
257
+ log("heightManager", "invalid next height, ignoring", next);
258
+ return;
259
+ }
260
+ if (lastApplied !== -1 && Math.abs(next - lastApplied) <= HYSTERESIS_PX) return;
210
261
  if (next === lastApplied) return;
211
262
  suppressed = true;
212
263
  container.style.height = `${next}px`;
213
264
  lastApplied = next;
265
+ log("heightManager", "applied height ->", next);
214
266
  queueMicrotask(() => {
215
267
  suppressed = false;
216
268
  });
217
269
  }
270
+ function scheduleApply() {
271
+ if (debounceTimer != null) {
272
+ clearTimeout(debounceTimer);
273
+ debounceTimer = null;
274
+ }
275
+ if (DEBOUNCE_MS === 0) {
276
+ if (raf != null) return;
277
+ raf = requestAnimationFrame(() => {
278
+ raf = null;
279
+ apply();
280
+ });
281
+ return;
282
+ }
283
+ debounceTimer = setTimeout(() => {
284
+ debounceTimer = null;
285
+ if (raf != null) return;
286
+ raf = requestAnimationFrame(() => {
287
+ raf = null;
288
+ apply();
289
+ });
290
+ }, DEBOUNCE_MS);
291
+ }
218
292
  function update() {
219
- if (raf != null) return;
220
- raf = requestAnimationFrame(() => {
221
- raf = null;
222
- apply();
223
- });
293
+ scheduleApply();
224
294
  }
225
295
  function dispose() {
226
296
  if (raf != null) {
227
297
  cancelAnimationFrame(raf);
228
298
  raf = null;
229
299
  }
300
+ if (debounceTimer != null) {
301
+ clearTimeout(debounceTimer);
302
+ debounceTimer = null;
303
+ }
230
304
  }
231
305
  function isSuppressed() {
232
306
  return suppressed;
@@ -280,20 +354,58 @@ function createRafScheduler(timeSource) {
280
354
  //#region src/utils/scroll.ts
281
355
  function createScrollWatcherForEditor(ed, opts) {
282
356
  var _ed$getScrollTop, _ed$onDidScrollChange;
357
+ const DEBUG = (() => {
358
+ try {
359
+ if (typeof window !== "undefined" && window.__STREAM_MONACO_DEBUG__ !== void 0) return Boolean(window.__STREAM_MONACO_DEBUG__);
360
+ try {
361
+ const proc = nodeProcess;
362
+ if (proc && proc.env && proc.env.NODE_ENV === "production") return false;
363
+ } catch {}
364
+ } catch {}
365
+ return true;
366
+ })();
283
367
  const initial = ((_ed$getScrollTop = ed.getScrollTop) === null || _ed$getScrollTop === void 0 ? void 0 : _ed$getScrollTop.call(ed)) ?? 0;
284
368
  opts.setLast(initial);
285
- const disp = ((_ed$onDidScrollChange = ed.onDidScrollChange) === null || _ed$onDidScrollChange === void 0 ? void 0 : _ed$onDidScrollChange.call(ed, (e) => {
369
+ if (DEBUG) log("scrollWatcher", "initial scrollTop=", initial);
370
+ let suppressedExternally = false;
371
+ const THRESHOLD_PX = 6;
372
+ const listener = (e) => {
286
373
  var _ed$getScrollTop2;
374
+ if (suppressedExternally) {
375
+ if (DEBUG) log("scrollWatcher", "suppressedExternally, ignoring event");
376
+ return;
377
+ }
287
378
  const currentTop = e && typeof e.scrollTop === "number" ? e.scrollTop : ((_ed$getScrollTop2 = ed.getScrollTop) === null || _ed$getScrollTop2 === void 0 ? void 0 : _ed$getScrollTop2.call(ed)) ?? 0;
288
379
  const delta = currentTop - opts.getLast();
289
380
  opts.setLast(currentTop);
381
+ if (Math.abs(delta) < THRESHOLD_PX) {
382
+ if (DEBUG) log("scrollWatcher", "small delta ignored", delta);
383
+ return;
384
+ }
385
+ if (DEBUG) log("scrollWatcher", "delta=", delta, "currentTop=", currentTop);
290
386
  if (delta < 0) {
387
+ if (DEBUG) log("scrollWatcher", "pause detected delta=", delta);
291
388
  opts.onPause();
292
389
  return;
293
390
  }
391
+ if (DEBUG) log("scrollWatcher", "maybe resume delta=", delta);
294
392
  opts.onMaybeResume();
295
- })) ?? null;
296
- return disp;
393
+ };
394
+ const disp = ((_ed$onDidScrollChange = ed.onDidScrollChange) === null || _ed$onDidScrollChange === void 0 ? void 0 : _ed$onDidScrollChange.call(ed, listener)) ?? null;
395
+ const api = {
396
+ dispose() {
397
+ try {
398
+ if (disp && typeof disp.dispose === "function") disp.dispose();
399
+ else if (typeof disp === "function") disp();
400
+ } catch {}
401
+ if (DEBUG) log("scrollWatcher", "dispose");
402
+ },
403
+ setSuppressed(v) {
404
+ suppressedExternally = !!v;
405
+ if (DEBUG) log("scrollWatcher", "setSuppressed =>", suppressedExternally);
406
+ }
407
+ };
408
+ return api;
297
409
  }
298
410
 
299
411
  //#endregion
@@ -747,7 +859,13 @@ var DiffEditorManager = class {
747
859
  else this.applyMinimalEditToModel(o, prevO, original);
748
860
  this.lastKnownOriginalCode = original;
749
861
  }
750
- const prevM = this.lastKnownModifiedCode;
862
+ let prevM = this.lastKnownModifiedCode;
863
+ if (this.appendBufferDiff.length > 0) try {
864
+ prevM = m.getValue();
865
+ this.lastKnownModifiedCode = prevM;
866
+ } catch {
867
+ prevM = this.lastKnownModifiedCode ?? "";
868
+ }
751
869
  const prevMLineCount = m.getLineCount();
752
870
  if (prevM !== modified) {
753
871
  if (modified.startsWith(prevM) && prevM.length < modified.length) this.appendToModel(m, modified.slice(prevM.length));
@@ -841,12 +959,14 @@ var EditorManager = class {
841
959
  _hasScrollBar = false;
842
960
  shouldAutoScroll = true;
843
961
  scrollWatcher = null;
962
+ scrollWatcherSuppressionTimer = null;
844
963
  lastScrollTop = 0;
845
964
  cachedScrollHeight = null;
846
965
  cachedLineHeight = null;
847
966
  cachedComputedHeight = null;
848
967
  cachedLineCount = null;
849
968
  lastKnownCodeDirty = false;
969
+ debug = false;
850
970
  measureViewport() {
851
971
  var _this$editorView$getL, _this$editorView, _this$editorView$getS, _this$editorView2, _this$editorView$getS2, _this$editorView3;
852
972
  if (!this.editorView) return null;
@@ -874,8 +994,10 @@ var EditorManager = class {
874
994
  revealDebounceId = null;
875
995
  revealDebounceMs = defaultRevealDebounceMs;
876
996
  revealIdleTimerId = null;
997
+ revealTicket = 0;
877
998
  revealStrategyOption;
878
999
  revealBatchOnIdleMsOption;
1000
+ scrollWatcherSuppressionMs = 500;
879
1001
  constructor(options, maxHeightValue, maxHeightCSS, autoScrollOnUpdate, autoScrollInitial, autoScrollThresholdPx, autoScrollThresholdLines, revealDebounceMsOption) {
880
1002
  this.options = options;
881
1003
  this.maxHeightValue = maxHeightValue;
@@ -886,6 +1008,21 @@ var EditorManager = class {
886
1008
  this.autoScrollThresholdLines = autoScrollThresholdLines;
887
1009
  this.revealDebounceMsOption = revealDebounceMsOption;
888
1010
  }
1011
+ initDebugFlag() {
1012
+ if (typeof window !== "undefined" && window.__STREAM_MONACO_DEBUG__ !== void 0) {
1013
+ this.debug = Boolean(window.__STREAM_MONACO_DEBUG__);
1014
+ return;
1015
+ }
1016
+ if (this.options && this.options.debug !== void 0) {
1017
+ this.debug = Boolean(this.options.debug);
1018
+ return;
1019
+ }
1020
+ this.debug = false;
1021
+ }
1022
+ dlog(...args) {
1023
+ if (!this.debug) return;
1024
+ log("EditorManager", ...args);
1025
+ }
889
1026
  hasVerticalScrollbar() {
890
1027
  if (!this.editorView) return false;
891
1028
  if (this._hasScrollBar) return true;
@@ -907,19 +1044,40 @@ var EditorManager = class {
907
1044
  const lineCount = this.cachedLineCount ?? ((_editorView$getModel = editorView.getModel()) === null || _editorView$getModel === void 0 ? void 0 : _editorView$getModel.getLineCount()) ?? 1;
908
1045
  const lineHeight = editorView.getOption(monaco_shim_exports.editor.EditorOption.lineHeight);
909
1046
  const height = Math.min(lineCount * lineHeight + padding, this.maxHeightValue);
1047
+ try {
1048
+ log("EditorManager.computedHeight", {
1049
+ lineCount,
1050
+ lineHeight,
1051
+ computed: height,
1052
+ maxHeightValue: this.maxHeightValue
1053
+ });
1054
+ } catch {}
910
1055
  return height;
911
1056
  }
912
1057
  maybeScrollToBottom(targetLine) {
913
1058
  this.rafScheduler.schedule("maybe-scroll", () => {
914
- if (!(this.autoScrollOnUpdate && this.shouldAutoScroll && this.hasVerticalScrollbar())) return;
1059
+ const hasVS = this.hasVerticalScrollbar();
1060
+ this.dlog("maybeScrollToBottom called", {
1061
+ autoScrollOnUpdate: this.autoScrollOnUpdate,
1062
+ shouldAutoScroll: this.shouldAutoScroll,
1063
+ hasVerticalScrollbar: hasVS,
1064
+ targetLine
1065
+ });
1066
+ if (!(this.autoScrollOnUpdate && this.shouldAutoScroll && this.hasVerticalScrollbar())) {
1067
+ this.dlog("maybeScrollToBottom skipped (auto-scroll conditions not met)");
1068
+ return;
1069
+ }
915
1070
  const model = this.editorView.getModel();
916
1071
  const line = targetLine ?? (model === null || model === void 0 ? void 0 : model.getLineCount()) ?? 1;
917
1072
  const batchMs = this.revealBatchOnIdleMsOption ?? this.options.revealBatchOnIdleMs ?? defaultRevealBatchOnIdleMs;
918
1073
  if (typeof batchMs === "number" && batchMs > 0) {
919
1074
  if (this.revealIdleTimerId != null) clearTimeout(this.revealIdleTimerId);
1075
+ const ticket = ++this.revealTicket;
1076
+ this.dlog("scheduled idle reveal ticket=", ticket, "line=", line, "batchMs=", batchMs);
920
1077
  this.revealIdleTimerId = setTimeout(() => {
921
1078
  this.revealIdleTimerId = null;
922
- this.performReveal(line);
1079
+ this.dlog("idle reveal timer firing, ticket=", ticket, "line=", line);
1080
+ this.performReveal(line, ticket);
923
1081
  }, batchMs);
924
1082
  return;
925
1083
  }
@@ -930,14 +1088,23 @@ var EditorManager = class {
930
1088
  const ms = typeof this.revealDebounceMs === "number" && this.revealDebounceMs > 0 ? this.revealDebounceMs : typeof this.revealDebounceMsOption === "number" && this.revealDebounceMsOption > 0 ? this.revealDebounceMsOption : this.revealDebounceMs;
931
1089
  this.revealDebounceId = setTimeout(() => {
932
1090
  this.revealDebounceId = null;
933
- this.performReveal(line);
1091
+ const ticket = ++this.revealTicket;
1092
+ this.dlog("scheduled debounce reveal ticket=", ticket, "line=", line, "ms=", ms);
1093
+ this.performReveal(line, ticket);
934
1094
  }, ms);
935
1095
  });
936
1096
  }
937
- performReveal(line) {
1097
+ performReveal(line, ticket) {
938
1098
  this.rafScheduler.schedule("reveal", () => {
939
1099
  var _editor;
1100
+ if (ticket !== this.revealTicket) {
1101
+ this.dlog("performReveal skipped, stale ticket", ticket, "current", this.revealTicket);
1102
+ return;
1103
+ }
1104
+ this.dlog("performReveal executing, ticket=", ticket, "line=", line);
1105
+ this.lastPerformedRevealTicket = ticket;
940
1106
  const strategy = this.revealStrategyOption ?? this.options.revealStrategy ?? "centerIfOutside";
1107
+ this.dlog("performReveal strategy=", strategy);
941
1108
  const ScrollType = monaco_shim_exports.ScrollType || ((_editor = monaco_shim_exports.editor) === null || _editor === void 0 ? void 0 : _editor.ScrollType);
942
1109
  const smooth = ScrollType && typeof ScrollType.Smooth !== "undefined" ? ScrollType.Smooth : void 0;
943
1110
  try {
@@ -954,11 +1121,60 @@ var EditorManager = class {
954
1121
  }
955
1122
  });
956
1123
  }
1124
+ performImmediateReveal(line, ticket) {
1125
+ this.dlog("performImmediateReveal line=", line, "ticket=", ticket);
1126
+ try {
1127
+ var _editor2;
1128
+ if (!this.editorView) return;
1129
+ if (ticket !== this.revealTicket) {
1130
+ this.dlog("performImmediateReveal skipped, stale ticket", ticket, "current", this.revealTicket);
1131
+ return;
1132
+ }
1133
+ this.lastPerformedRevealTicket = ticket;
1134
+ const ScrollType = monaco_shim_exports.ScrollType || ((_editor2 = monaco_shim_exports.editor) === null || _editor2 === void 0 ? void 0 : _editor2.ScrollType);
1135
+ const immediate = ScrollType && typeof ScrollType.Immediate !== "undefined" ? ScrollType.Immediate : void 0;
1136
+ if (typeof immediate !== "undefined") this.editorView.revealLine(line, immediate);
1137
+ else this.editorView.revealLine(line);
1138
+ } catch {}
1139
+ try {
1140
+ this.measureViewport();
1141
+ } catch {}
1142
+ }
1143
+ forceReveal(line) {
1144
+ try {
1145
+ var _editor3;
1146
+ if (!this.editorView) return;
1147
+ const ScrollType = monaco_shim_exports.ScrollType || ((_editor3 = monaco_shim_exports.editor) === null || _editor3 === void 0 ? void 0 : _editor3.ScrollType);
1148
+ const immediate = ScrollType && typeof ScrollType.Immediate !== "undefined" ? ScrollType.Immediate : void 0;
1149
+ if (typeof immediate !== "undefined") this.editorView.revealLine(line, immediate);
1150
+ else this.editorView.revealLine(line);
1151
+ } catch {}
1152
+ try {
1153
+ this.measureViewport();
1154
+ } catch {}
1155
+ try {
1156
+ var _this$editorView4, _this$editorView4$get;
1157
+ this.shouldAutoScroll = true;
1158
+ 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;
1159
+ } catch {}
1160
+ }
1161
+ isOverflowAuto() {
1162
+ try {
1163
+ return !!this.lastContainer && this.lastContainer.style.overflow === "auto";
1164
+ } catch {
1165
+ return false;
1166
+ }
1167
+ }
1168
+ shouldPerformImmediateReveal() {
1169
+ return this.autoScrollOnUpdate && this.shouldAutoScroll && this.hasVerticalScrollbar() && this.isOverflowAuto();
1170
+ }
957
1171
  async createEditor(container, code, language, currentTheme) {
958
- var _this$editorView$getS3, _this$editorView4, _this$editorView$getO, _this$editorView5, _this$editorView$getM, _this$editorView$onDi, _this$editorView6;
1172
+ var _this$editorView$getS3, _this$editorView5, _this$editorView$getO, _this$editorView6, _this$editorView$getM, _this$editorView$onDi, _this$editorView7;
959
1173
  this.cleanup();
960
1174
  this.lastContainer = container;
961
- container.style.overflow = "auto";
1175
+ this.initDebugFlag();
1176
+ this.dlog("createEditor container, maxHeight", this.maxHeightValue);
1177
+ container.style.overflow = "hidden";
962
1178
  container.style.maxHeight = this.maxHeightCSS;
963
1179
  this.editorView = monaco_shim_exports.editor.create(container, {
964
1180
  value: code,
@@ -989,22 +1205,51 @@ var EditorManager = class {
989
1205
  }
990
1206
  if (this.revealIdleTimerId != null) clearTimeout(this.revealIdleTimerId);
991
1207
  this.revealIdleTimerId = null;
992
- this.editorHeightManager = createHeightManager(container, () => this.computedHeight(this.editorView));
1208
+ const MIN_VISIBLE_HEIGHT = Math.min(120, this.maxHeightValue);
1209
+ container.style.minHeight = `${MIN_VISIBLE_HEIGHT}px`;
1210
+ this.editorHeightManager = createHeightManager(container, () => {
1211
+ const computed$2 = this.computedHeight(this.editorView);
1212
+ const clamped = Math.min(computed$2, this.maxHeightValue);
1213
+ return Math.max(clamped, MIN_VISIBLE_HEIGHT);
1214
+ });
993
1215
  this.editorHeightManager.update();
994
- this.cachedScrollHeight = ((_this$editorView$getS3 = (_this$editorView4 = this.editorView).getScrollHeight) === null || _this$editorView$getS3 === void 0 ? void 0 : _this$editorView$getS3.call(_this$editorView4)) ?? null;
995
- this.cachedLineHeight = ((_this$editorView$getO = (_this$editorView5 = this.editorView).getOption) === null || _this$editorView$getO === void 0 ? void 0 : _this$editorView$getO.call(_this$editorView5, monaco_shim_exports.editor.EditorOption.lineHeight)) ?? null;
1216
+ const initialComputed = this.computedHeight(this.editorView);
1217
+ if (initialComputed >= this.maxHeightValue - 1) {
1218
+ container.style.height = `${this.maxHeightValue}px`;
1219
+ container.style.overflow = "auto";
1220
+ this.dlog("applied immediate maxHeight on createEditor", this.maxHeightValue);
1221
+ }
1222
+ 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;
1223
+ 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;
996
1224
  this.cachedComputedHeight = this.computedHeight(this.editorView);
997
1225
  this.cachedLineCount = ((_this$editorView$getM = this.editorView.getModel()) === null || _this$editorView$getM === void 0 ? void 0 : _this$editorView$getM.getLineCount()) ?? null;
998
- (_this$editorView$onDi = (_this$editorView6 = this.editorView).onDidContentSizeChange) === null || _this$editorView$onDi === void 0 || _this$editorView$onDi.call(_this$editorView6, () => {
1226
+ (_this$editorView$onDi = (_this$editorView7 = this.editorView).onDidContentSizeChange) === null || _this$editorView$onDi === void 0 || _this$editorView$onDi.call(_this$editorView7, () => {
999
1227
  this._hasScrollBar = false;
1000
1228
  this.rafScheduler.schedule("content-size-change", () => {
1001
1229
  try {
1002
- var _this$editorView7, _this$editorHeightMan, _this$editorHeightMan2;
1003
- this.measureViewport();
1004
- this.cachedLineCount = ((_this$editorView7 = this.editorView) === null || _this$editorView7 === void 0 || (_this$editorView7 = _this$editorView7.getModel()) === null || _this$editorView7 === void 0 ? void 0 : _this$editorView7.getLineCount()) ?? this.cachedLineCount;
1005
- if ((_this$editorHeightMan = this.editorHeightManager) === null || _this$editorHeightMan === void 0 ? void 0 : _this$editorHeightMan.isSuppressed()) return;
1230
+ var _this$editorView8, _this$editorHeightMan, _this$editorHeightMan2;
1231
+ this.dlog("content-size-change frame");
1232
+ const m = this.measureViewport();
1233
+ this.dlog("content-size-change measure", m);
1234
+ 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;
1235
+ if ((_this$editorHeightMan = this.editorHeightManager) === null || _this$editorHeightMan === void 0 ? void 0 : _this$editorHeightMan.isSuppressed()) {
1236
+ this.dlog("content-size-change skipped height update (suppressed)");
1237
+ return;
1238
+ }
1239
+ this.dlog("content-size-change calling heightManager.update");
1006
1240
  (_this$editorHeightMan2 = this.editorHeightManager) === null || _this$editorHeightMan2 === void 0 || _this$editorHeightMan2.update();
1007
- } catch {}
1241
+ const computed$2 = this.computedHeight(this.editorView);
1242
+ if (this.lastContainer) {
1243
+ const prevOverflow = this.lastContainer.style.overflow;
1244
+ const newOverflow = computed$2 >= this.maxHeightValue - 1 ? "auto" : "hidden";
1245
+ if (prevOverflow !== newOverflow) {
1246
+ this.lastContainer.style.overflow = newOverflow;
1247
+ if (newOverflow === "auto" && this.shouldAutoScroll) this.maybeScrollToBottom();
1248
+ }
1249
+ }
1250
+ } catch (err) {
1251
+ error("EditorManager", "content-size-change error", err);
1252
+ }
1008
1253
  });
1009
1254
  });
1010
1255
  this.editorView.onDidChangeModelContent(() => {
@@ -1045,6 +1290,65 @@ var EditorManager = class {
1045
1290
  this.lastKnownCodeDirty = false;
1046
1291
  }
1047
1292
  }
1293
+ suppressScrollWatcher(ms) {
1294
+ try {
1295
+ if (!this.scrollWatcher || typeof this.scrollWatcher.setSuppressed !== "function") return;
1296
+ this.dlog("suppressScrollWatcher", ms);
1297
+ if (this.scrollWatcherSuppressionTimer != null) {
1298
+ clearTimeout(this.scrollWatcherSuppressionTimer);
1299
+ this.scrollWatcherSuppressionTimer = null;
1300
+ }
1301
+ this.scrollWatcher.setSuppressed(true);
1302
+ this.scrollWatcherSuppressionTimer = setTimeout(() => {
1303
+ try {
1304
+ if (this.scrollWatcher && typeof this.scrollWatcher.setSuppressed === "function") {
1305
+ this.scrollWatcher.setSuppressed(false);
1306
+ this.dlog("suppressScrollWatcher cleared");
1307
+ }
1308
+ } catch {}
1309
+ this.scrollWatcherSuppressionTimer = null;
1310
+ }, ms);
1311
+ } catch {}
1312
+ }
1313
+ scheduleImmediateRevealAfterLayout(line) {
1314
+ const ticket = ++this.revealTicket;
1315
+ this.dlog("scheduleImmediateRevealAfterLayout ticket=", ticket, "line=", line);
1316
+ this.rafScheduler.schedule("immediate-reveal", async () => {
1317
+ try {
1318
+ const target = this.editorView && this.editorHeightManager ? Math.min(this.computedHeight(this.editorView), this.maxHeightValue) : -1;
1319
+ if (target !== -1 && this.editorHeightManager) await this.waitForHeightApplied(target, 500);
1320
+ else await new Promise((r) => requestAnimationFrame(() => requestAnimationFrame(() => r())));
1321
+ this.dlog("running delayed immediate reveal", "ticket=", ticket, "line=", line);
1322
+ this.performImmediateReveal(line, ticket);
1323
+ } catch (err) {
1324
+ error("EditorManager", "scheduleImmediateRevealAfterLayout error", err);
1325
+ }
1326
+ });
1327
+ }
1328
+ waitForHeightApplied(target, timeoutMs = 500) {
1329
+ return new Promise((resolve) => {
1330
+ const start = typeof performance !== "undefined" && performance.now ? performance.now() : Date.now();
1331
+ const check = () => {
1332
+ try {
1333
+ var _this$editorHeightMan3, _this$editorHeightMan4;
1334
+ 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;
1335
+ if (last !== -1 && Math.abs(last - target) <= 12) {
1336
+ this.dlog("waitForHeightApplied satisfied", last, "target=", target);
1337
+ resolve();
1338
+ return;
1339
+ }
1340
+ const now = typeof performance !== "undefined" && performance.now ? performance.now() : Date.now();
1341
+ if (now - start > timeoutMs) {
1342
+ log("EditorManager", "waitForHeightApplied timeout", last, "target=", target);
1343
+ resolve();
1344
+ return;
1345
+ }
1346
+ } catch {}
1347
+ requestAnimationFrame(check);
1348
+ };
1349
+ check();
1350
+ });
1351
+ }
1048
1352
  updateCode(newCode, codeLanguage) {
1049
1353
  this.pendingUpdate = {
1050
1354
  code: newCode,
@@ -1067,10 +1371,21 @@ var EditorManager = class {
1067
1371
  this.lastKnownCode = newCode;
1068
1372
  const newLineCount$1 = model.getLineCount();
1069
1373
  this.cachedLineCount = newLineCount$1;
1070
- if (newLineCount$1 !== prevLineCount$1) this.maybeScrollToBottom(newLineCount$1);
1374
+ if (newLineCount$1 !== prevLineCount$1) {
1375
+ const shouldImmediate = this.shouldPerformImmediateReveal();
1376
+ if (shouldImmediate) this.suppressScrollWatcher(this.scrollWatcherSuppressionMs);
1377
+ try {
1378
+ const computed$2 = this.computedHeight(this.editorView);
1379
+ if (computed$2 >= this.maxHeightValue - 1 && this.lastContainer) this.lastContainer.style.height = `${this.maxHeightValue}px`;
1380
+ } catch {}
1381
+ if (shouldImmediate) try {
1382
+ this.forceReveal(newLineCount$1);
1383
+ } catch {}
1384
+ else this.maybeScrollToBottom(newLineCount$1);
1385
+ }
1071
1386
  return;
1072
1387
  }
1073
- const prevCode = this.lastKnownCode ?? this.editorView.getValue();
1388
+ const prevCode = this.appendBuffer.length > 0 ? this.editorView.getValue() : this.lastKnownCode ?? this.editorView.getValue();
1074
1389
  if (prevCode === newCode) return;
1075
1390
  if (newCode.startsWith(prevCode) && prevCode.length < newCode.length) {
1076
1391
  const suffix = newCode.slice(prevCode.length);
@@ -1083,7 +1398,12 @@ var EditorManager = class {
1083
1398
  this.lastKnownCode = newCode;
1084
1399
  const newLineCount = model.getLineCount();
1085
1400
  this.cachedLineCount = newLineCount;
1086
- if (newLineCount !== prevLineCount) this.maybeScrollToBottom(newLineCount);
1401
+ if (newLineCount !== prevLineCount) {
1402
+ const shouldImmediate = this.shouldPerformImmediateReveal();
1403
+ if (shouldImmediate) this.suppressScrollWatcher(this.scrollWatcherSuppressionMs);
1404
+ if (shouldImmediate) this.scheduleImmediateRevealAfterLayout(newLineCount);
1405
+ else this.maybeScrollToBottom(newLineCount);
1406
+ }
1087
1407
  }
1088
1408
  appendCode(appendText, codeLanguage) {
1089
1409
  if (!this.editorView) return;
@@ -1161,7 +1481,16 @@ var EditorManager = class {
1161
1481
  const newLineCount = model.getLineCount();
1162
1482
  if (lastLine !== newLineCount) {
1163
1483
  this.cachedLineCount = newLineCount;
1164
- this.maybeScrollToBottom(newLineCount);
1484
+ const shouldImmediate = this.shouldPerformImmediateReveal();
1485
+ if (shouldImmediate) this.suppressScrollWatcher(this.scrollWatcherSuppressionMs);
1486
+ try {
1487
+ const computed$2 = this.computedHeight(this.editorView);
1488
+ if (computed$2 >= this.maxHeightValue - 1 && this.lastContainer) this.lastContainer.style.height = `${this.maxHeightValue}px`;
1489
+ } catch {}
1490
+ if (shouldImmediate) try {
1491
+ this.forceReveal(newLineCount);
1492
+ } catch {}
1493
+ else this.maybeScrollToBottom(newLineCount);
1165
1494
  }
1166
1495
  }
1167
1496
  setLanguage(language, languages$1) {
@@ -1179,16 +1508,33 @@ var EditorManager = class {
1179
1508
  this.rafScheduler.cancel("update");
1180
1509
  this.rafScheduler.cancel("sync-last-known");
1181
1510
  this.rafScheduler.cancel("content-size-change");
1511
+ this.rafScheduler.cancel("maybe-scroll");
1512
+ this.rafScheduler.cancel("reveal");
1513
+ this.rafScheduler.cancel("immediate-reveal");
1514
+ this.rafScheduler.cancel("maybe-resume");
1182
1515
  this.pendingUpdate = null;
1183
1516
  this.rafScheduler.cancel("append");
1184
1517
  this.appendBufferScheduled = false;
1185
1518
  this.appendBuffer.length = 0;
1519
+ if (this.revealDebounceId != null) {
1520
+ clearTimeout(this.revealDebounceId);
1521
+ this.revealDebounceId = null;
1522
+ }
1523
+ if (this.revealIdleTimerId != null) {
1524
+ clearTimeout(this.revealIdleTimerId);
1525
+ this.revealIdleTimerId = null;
1526
+ }
1527
+ if (this.scrollWatcherSuppressionTimer != null) {
1528
+ clearTimeout(this.scrollWatcherSuppressionTimer);
1529
+ this.scrollWatcherSuppressionTimer = null;
1530
+ }
1186
1531
  if (this.editorView) {
1187
1532
  this.editorView.dispose();
1188
1533
  this.editorView = null;
1189
1534
  }
1190
1535
  this.lastKnownCode = null;
1191
1536
  if (this.lastContainer) {
1537
+ this.lastContainer.style.minHeight = "";
1192
1538
  this.lastContainer.innerHTML = "";
1193
1539
  this.lastContainer = null;
1194
1540
  }
@@ -1206,13 +1552,27 @@ var EditorManager = class {
1206
1552
  this.pendingUpdate = null;
1207
1553
  this.rafScheduler.cancel("sync-last-known");
1208
1554
  if (this.scrollWatcher) {
1209
- this.scrollWatcher.dispose();
1555
+ try {
1556
+ this.scrollWatcher.dispose();
1557
+ } catch {}
1210
1558
  this.scrollWatcher = null;
1211
1559
  }
1212
1560
  if (this.revealDebounceId != null) {
1213
1561
  clearTimeout(this.revealDebounceId);
1214
1562
  this.revealDebounceId = null;
1215
1563
  }
1564
+ if (this.revealIdleTimerId != null) {
1565
+ clearTimeout(this.revealIdleTimerId);
1566
+ this.revealIdleTimerId = null;
1567
+ }
1568
+ if (this.scrollWatcherSuppressionTimer != null) {
1569
+ clearTimeout(this.scrollWatcherSuppressionTimer);
1570
+ this.scrollWatcherSuppressionTimer = null;
1571
+ }
1572
+ this.rafScheduler.cancel("maybe-scroll");
1573
+ this.rafScheduler.cancel("reveal");
1574
+ this.rafScheduler.cancel("immediate-reveal");
1575
+ this.rafScheduler.cancel("maybe-resume");
1216
1576
  this._hasScrollBar = false;
1217
1577
  this.shouldAutoScroll = !!this.autoScrollInitial;
1218
1578
  this.lastScrollTop = 0;
@@ -1519,6 +1879,7 @@ let RevealStrategy = /* @__PURE__ */ function(RevealStrategy$1) {
1519
1879
  * getEditorView: () => monaco.editor.IStandaloneCodeEditor | null,
1520
1880
  * getDiffEditorView: () => monaco.editor.IStandaloneDiffEditor | null,
1521
1881
  * getDiffModels: () => { original: monaco.editor.ITextModel | null, modified: monaco.editor.ITextModel | null },
1882
+ * getCode: () => string | { original: string, modified: string } | null,
1522
1883
  * }} 返回对象包含以下方法和属性:
1523
1884
  *
1524
1885
  * @property {Function} createEditor - 创建并挂载 Monaco 编辑器到指定容器
@@ -1538,6 +1899,7 @@ let RevealStrategy = /* @__PURE__ */ function(RevealStrategy$1) {
1538
1899
  * @property {Function} getEditorView - 获取当前编辑器实例
1539
1900
  * @property {Function} getDiffEditorView - 获取当前 Diff 编辑器实例
1540
1901
  * @property {Function} getDiffModels - 获取 Diff 的 original/modified 两个模型
1902
+ * @property {Function} getCode - 获取当前编辑器或 Diff 编辑器中的代码内容
1541
1903
  *
1542
1904
  * @throws {Error} 当主题数组不是数组或长度小于2时抛出错误
1543
1905
  *
@@ -1837,13 +2199,22 @@ function useMonaco(monacoOptions = {}) {
1837
2199
  const { code: newCode, lang: codeLanguage } = pendingUpdate;
1838
2200
  pendingUpdate = null;
1839
2201
  const processedCodeLanguage = processedLanguage(codeLanguage);
1840
- let prevCode = lastKnownCode;
1841
- if (prevCode == null) try {
2202
+ let prevCode = null;
2203
+ if (appendBuffer.length > 0) try {
1842
2204
  prevCode = model.getValue();
1843
2205
  lastKnownCode = prevCode;
1844
2206
  } catch {
1845
2207
  prevCode = "";
1846
2208
  }
2209
+ else {
2210
+ prevCode = lastKnownCode;
2211
+ if (prevCode == null) try {
2212
+ prevCode = model.getValue();
2213
+ lastKnownCode = prevCode;
2214
+ } catch {
2215
+ prevCode = "";
2216
+ }
2217
+ }
1847
2218
  if (prevCode === newCode) return;
1848
2219
  const languageId = model.getLanguageId();
1849
2220
  if (languageId !== processedCodeLanguage) {
@@ -2035,7 +2406,26 @@ function useMonaco(monacoOptions = {}) {
2035
2406
  return monaco_shim_exports;
2036
2407
  },
2037
2408
  setUpdateThrottleMs,
2038
- getUpdateThrottleMs
2409
+ getUpdateThrottleMs,
2410
+ getCode() {
2411
+ if (editorView) try {
2412
+ var _editorView$getModel;
2413
+ return ((_editorView$getModel = editorView.getModel()) === null || _editorView$getModel === void 0 ? void 0 : _editorView$getModel.getValue()) ?? null;
2414
+ } catch {
2415
+ return null;
2416
+ }
2417
+ if (diffEditorView || originalModel && modifiedModel) try {
2418
+ const original = (originalModel === null || originalModel === void 0 ? void 0 : originalModel.getValue()) ?? "";
2419
+ const modified = (modifiedModel === null || modifiedModel === void 0 ? void 0 : modifiedModel.getValue()) ?? "";
2420
+ return {
2421
+ original,
2422
+ modified
2423
+ };
2424
+ } catch {
2425
+ return null;
2426
+ }
2427
+ return null;
2428
+ }
2039
2429
  };
2040
2430
  }
2041
2431