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.cjs CHANGED
@@ -29,6 +29,7 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
29
29
 
30
30
  //#endregion
31
31
  const monaco_editor = __toESM(require("monaco-editor"));
32
+ const node_process = __toESM(require("node:process"));
32
33
  const alien_signals = __toESM(require("alien-signals"));
33
34
  const __shikijs_monaco = __toESM(require("@shikijs/monaco"));
34
35
  const shiki = __toESM(require("shiki"));
@@ -227,34 +228,107 @@ __export(monaco_shim_exports, { default: () => monaco });
227
228
  __reExport(monaco_shim_exports, require("monaco-editor"));
228
229
  const monaco = monaco_editor;
229
230
 
231
+ //#endregion
232
+ //#region src/utils/logger.ts
233
+ let seq = 0;
234
+ const ENABLED = (() => {
235
+ try {
236
+ if (typeof window !== "undefined" && window.__STREAM_MONACO_DEBUG__ !== void 0) return Boolean(window.__STREAM_MONACO_DEBUG__);
237
+ try {
238
+ const proc = node_process.default;
239
+ if (proc && proc.env && proc.env.NODE_ENV !== "production") return true;
240
+ } catch {}
241
+ } catch {}
242
+ return false;
243
+ })();
244
+ function log(tag, ...args) {
245
+ if (!ENABLED) return;
246
+ try {
247
+ seq += 1;
248
+ const id = `#${seq}`;
249
+ const ts = typeof performance !== "undefined" && performance.now ? performance.now().toFixed(1) : Date.now();
250
+ console.warn(`${id} [${tag}] @${ts}ms`, ...args);
251
+ } catch (err) {
252
+ try {
253
+ console.warn("[logger] fallback", tag, ...args, err);
254
+ } catch {}
255
+ }
256
+ }
257
+ function error(tag, ...args) {
258
+ if (!ENABLED) return;
259
+ try {
260
+ console.error(`[${tag}]`, ...args);
261
+ } catch (err) {
262
+ try {
263
+ console.error("[logger] fallback error", tag, ...args, err);
264
+ } catch {}
265
+ }
266
+ }
267
+
230
268
  //#endregion
231
269
  //#region src/utils/height.ts
232
270
  function createHeightManager(container, computeNext) {
233
271
  let raf = null;
272
+ let debounceTimer = null;
234
273
  let lastApplied = -1;
235
274
  let suppressed = false;
275
+ const HYSTERESIS_PX = 12;
276
+ const DEBOUNCE_MS = 0;
236
277
  function apply() {
237
278
  const next = computeNext();
279
+ if (next == null) return;
280
+ log("heightManager", "computeNext ->", {
281
+ next,
282
+ lastApplied
283
+ });
284
+ if (!Number.isFinite(next) || next <= 0) {
285
+ log("heightManager", "invalid next height, ignoring", next);
286
+ return;
287
+ }
288
+ if (lastApplied !== -1 && Math.abs(next - lastApplied) <= HYSTERESIS_PX) return;
238
289
  if (next === lastApplied) return;
239
290
  suppressed = true;
240
291
  container.style.height = `${next}px`;
241
292
  lastApplied = next;
293
+ log("heightManager", "applied height ->", next);
242
294
  queueMicrotask(() => {
243
295
  suppressed = false;
244
296
  });
245
297
  }
298
+ function scheduleApply() {
299
+ if (debounceTimer != null) {
300
+ clearTimeout(debounceTimer);
301
+ debounceTimer = null;
302
+ }
303
+ if (DEBOUNCE_MS === 0) {
304
+ if (raf != null) return;
305
+ raf = requestAnimationFrame(() => {
306
+ raf = null;
307
+ apply();
308
+ });
309
+ return;
310
+ }
311
+ debounceTimer = setTimeout(() => {
312
+ debounceTimer = null;
313
+ if (raf != null) return;
314
+ raf = requestAnimationFrame(() => {
315
+ raf = null;
316
+ apply();
317
+ });
318
+ }, DEBOUNCE_MS);
319
+ }
246
320
  function update() {
247
- if (raf != null) return;
248
- raf = requestAnimationFrame(() => {
249
- raf = null;
250
- apply();
251
- });
321
+ scheduleApply();
252
322
  }
253
323
  function dispose() {
254
324
  if (raf != null) {
255
325
  cancelAnimationFrame(raf);
256
326
  raf = null;
257
327
  }
328
+ if (debounceTimer != null) {
329
+ clearTimeout(debounceTimer);
330
+ debounceTimer = null;
331
+ }
258
332
  }
259
333
  function isSuppressed() {
260
334
  return suppressed;
@@ -308,20 +382,58 @@ function createRafScheduler(timeSource) {
308
382
  //#region src/utils/scroll.ts
309
383
  function createScrollWatcherForEditor(ed, opts) {
310
384
  var _ed$getScrollTop, _ed$onDidScrollChange;
385
+ const DEBUG = (() => {
386
+ try {
387
+ if (typeof window !== "undefined" && window.__STREAM_MONACO_DEBUG__ !== void 0) return Boolean(window.__STREAM_MONACO_DEBUG__);
388
+ try {
389
+ const proc = node_process.default;
390
+ if (proc && proc.env && proc.env.NODE_ENV === "production") return false;
391
+ } catch {}
392
+ } catch {}
393
+ return true;
394
+ })();
311
395
  const initial = ((_ed$getScrollTop = ed.getScrollTop) === null || _ed$getScrollTop === void 0 ? void 0 : _ed$getScrollTop.call(ed)) ?? 0;
312
396
  opts.setLast(initial);
313
- const disp = ((_ed$onDidScrollChange = ed.onDidScrollChange) === null || _ed$onDidScrollChange === void 0 ? void 0 : _ed$onDidScrollChange.call(ed, (e) => {
397
+ if (DEBUG) log("scrollWatcher", "initial scrollTop=", initial);
398
+ let suppressedExternally = false;
399
+ const THRESHOLD_PX = 6;
400
+ const listener = (e) => {
314
401
  var _ed$getScrollTop2;
402
+ if (suppressedExternally) {
403
+ if (DEBUG) log("scrollWatcher", "suppressedExternally, ignoring event");
404
+ return;
405
+ }
315
406
  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;
316
407
  const delta = currentTop - opts.getLast();
317
408
  opts.setLast(currentTop);
409
+ if (Math.abs(delta) < THRESHOLD_PX) {
410
+ if (DEBUG) log("scrollWatcher", "small delta ignored", delta);
411
+ return;
412
+ }
413
+ if (DEBUG) log("scrollWatcher", "delta=", delta, "currentTop=", currentTop);
318
414
  if (delta < 0) {
415
+ if (DEBUG) log("scrollWatcher", "pause detected delta=", delta);
319
416
  opts.onPause();
320
417
  return;
321
418
  }
419
+ if (DEBUG) log("scrollWatcher", "maybe resume delta=", delta);
322
420
  opts.onMaybeResume();
323
- })) ?? null;
324
- return disp;
421
+ };
422
+ const disp = ((_ed$onDidScrollChange = ed.onDidScrollChange) === null || _ed$onDidScrollChange === void 0 ? void 0 : _ed$onDidScrollChange.call(ed, listener)) ?? null;
423
+ const api = {
424
+ dispose() {
425
+ try {
426
+ if (disp && typeof disp.dispose === "function") disp.dispose();
427
+ else if (typeof disp === "function") disp();
428
+ } catch {}
429
+ if (DEBUG) log("scrollWatcher", "dispose");
430
+ },
431
+ setSuppressed(v) {
432
+ suppressedExternally = !!v;
433
+ if (DEBUG) log("scrollWatcher", "setSuppressed =>", suppressedExternally);
434
+ }
435
+ };
436
+ return api;
325
437
  }
326
438
 
327
439
  //#endregion
@@ -775,7 +887,13 @@ var DiffEditorManager = class {
775
887
  else this.applyMinimalEditToModel(o, prevO, original);
776
888
  this.lastKnownOriginalCode = original;
777
889
  }
778
- const prevM = this.lastKnownModifiedCode;
890
+ let prevM = this.lastKnownModifiedCode;
891
+ if (this.appendBufferDiff.length > 0) try {
892
+ prevM = m.getValue();
893
+ this.lastKnownModifiedCode = prevM;
894
+ } catch {
895
+ prevM = this.lastKnownModifiedCode ?? "";
896
+ }
779
897
  const prevMLineCount = m.getLineCount();
780
898
  if (prevM !== modified) {
781
899
  if (modified.startsWith(prevM) && prevM.length < modified.length) this.appendToModel(m, modified.slice(prevM.length));
@@ -869,12 +987,14 @@ var EditorManager = class {
869
987
  _hasScrollBar = false;
870
988
  shouldAutoScroll = true;
871
989
  scrollWatcher = null;
990
+ scrollWatcherSuppressionTimer = null;
872
991
  lastScrollTop = 0;
873
992
  cachedScrollHeight = null;
874
993
  cachedLineHeight = null;
875
994
  cachedComputedHeight = null;
876
995
  cachedLineCount = null;
877
996
  lastKnownCodeDirty = false;
997
+ debug = false;
878
998
  measureViewport() {
879
999
  var _this$editorView$getL, _this$editorView, _this$editorView$getS, _this$editorView2, _this$editorView$getS2, _this$editorView3;
880
1000
  if (!this.editorView) return null;
@@ -902,8 +1022,10 @@ var EditorManager = class {
902
1022
  revealDebounceId = null;
903
1023
  revealDebounceMs = defaultRevealDebounceMs;
904
1024
  revealIdleTimerId = null;
1025
+ revealTicket = 0;
905
1026
  revealStrategyOption;
906
1027
  revealBatchOnIdleMsOption;
1028
+ scrollWatcherSuppressionMs = 500;
907
1029
  constructor(options, maxHeightValue, maxHeightCSS, autoScrollOnUpdate, autoScrollInitial, autoScrollThresholdPx, autoScrollThresholdLines, revealDebounceMsOption) {
908
1030
  this.options = options;
909
1031
  this.maxHeightValue = maxHeightValue;
@@ -914,6 +1036,21 @@ var EditorManager = class {
914
1036
  this.autoScrollThresholdLines = autoScrollThresholdLines;
915
1037
  this.revealDebounceMsOption = revealDebounceMsOption;
916
1038
  }
1039
+ initDebugFlag() {
1040
+ if (typeof window !== "undefined" && window.__STREAM_MONACO_DEBUG__ !== void 0) {
1041
+ this.debug = Boolean(window.__STREAM_MONACO_DEBUG__);
1042
+ return;
1043
+ }
1044
+ if (this.options && this.options.debug !== void 0) {
1045
+ this.debug = Boolean(this.options.debug);
1046
+ return;
1047
+ }
1048
+ this.debug = false;
1049
+ }
1050
+ dlog(...args) {
1051
+ if (!this.debug) return;
1052
+ log("EditorManager", ...args);
1053
+ }
917
1054
  hasVerticalScrollbar() {
918
1055
  if (!this.editorView) return false;
919
1056
  if (this._hasScrollBar) return true;
@@ -935,19 +1072,40 @@ var EditorManager = class {
935
1072
  const lineCount = this.cachedLineCount ?? ((_editorView$getModel = editorView.getModel()) === null || _editorView$getModel === void 0 ? void 0 : _editorView$getModel.getLineCount()) ?? 1;
936
1073
  const lineHeight = editorView.getOption(monaco_shim_exports.editor.EditorOption.lineHeight);
937
1074
  const height = Math.min(lineCount * lineHeight + padding, this.maxHeightValue);
1075
+ try {
1076
+ log("EditorManager.computedHeight", {
1077
+ lineCount,
1078
+ lineHeight,
1079
+ computed: height,
1080
+ maxHeightValue: this.maxHeightValue
1081
+ });
1082
+ } catch {}
938
1083
  return height;
939
1084
  }
940
1085
  maybeScrollToBottom(targetLine) {
941
1086
  this.rafScheduler.schedule("maybe-scroll", () => {
942
- if (!(this.autoScrollOnUpdate && this.shouldAutoScroll && this.hasVerticalScrollbar())) return;
1087
+ const hasVS = this.hasVerticalScrollbar();
1088
+ this.dlog("maybeScrollToBottom called", {
1089
+ autoScrollOnUpdate: this.autoScrollOnUpdate,
1090
+ shouldAutoScroll: this.shouldAutoScroll,
1091
+ hasVerticalScrollbar: hasVS,
1092
+ targetLine
1093
+ });
1094
+ if (!(this.autoScrollOnUpdate && this.shouldAutoScroll && this.hasVerticalScrollbar())) {
1095
+ this.dlog("maybeScrollToBottom skipped (auto-scroll conditions not met)");
1096
+ return;
1097
+ }
943
1098
  const model = this.editorView.getModel();
944
1099
  const line = targetLine ?? (model === null || model === void 0 ? void 0 : model.getLineCount()) ?? 1;
945
1100
  const batchMs = this.revealBatchOnIdleMsOption ?? this.options.revealBatchOnIdleMs ?? defaultRevealBatchOnIdleMs;
946
1101
  if (typeof batchMs === "number" && batchMs > 0) {
947
1102
  if (this.revealIdleTimerId != null) clearTimeout(this.revealIdleTimerId);
1103
+ const ticket = ++this.revealTicket;
1104
+ this.dlog("scheduled idle reveal ticket=", ticket, "line=", line, "batchMs=", batchMs);
948
1105
  this.revealIdleTimerId = setTimeout(() => {
949
1106
  this.revealIdleTimerId = null;
950
- this.performReveal(line);
1107
+ this.dlog("idle reveal timer firing, ticket=", ticket, "line=", line);
1108
+ this.performReveal(line, ticket);
951
1109
  }, batchMs);
952
1110
  return;
953
1111
  }
@@ -958,14 +1116,23 @@ var EditorManager = class {
958
1116
  const ms = typeof this.revealDebounceMs === "number" && this.revealDebounceMs > 0 ? this.revealDebounceMs : typeof this.revealDebounceMsOption === "number" && this.revealDebounceMsOption > 0 ? this.revealDebounceMsOption : this.revealDebounceMs;
959
1117
  this.revealDebounceId = setTimeout(() => {
960
1118
  this.revealDebounceId = null;
961
- this.performReveal(line);
1119
+ const ticket = ++this.revealTicket;
1120
+ this.dlog("scheduled debounce reveal ticket=", ticket, "line=", line, "ms=", ms);
1121
+ this.performReveal(line, ticket);
962
1122
  }, ms);
963
1123
  });
964
1124
  }
965
- performReveal(line) {
1125
+ performReveal(line, ticket) {
966
1126
  this.rafScheduler.schedule("reveal", () => {
967
1127
  var _editor;
1128
+ if (ticket !== this.revealTicket) {
1129
+ this.dlog("performReveal skipped, stale ticket", ticket, "current", this.revealTicket);
1130
+ return;
1131
+ }
1132
+ this.dlog("performReveal executing, ticket=", ticket, "line=", line);
1133
+ this.lastPerformedRevealTicket = ticket;
968
1134
  const strategy = this.revealStrategyOption ?? this.options.revealStrategy ?? "centerIfOutside";
1135
+ this.dlog("performReveal strategy=", strategy);
969
1136
  const ScrollType = monaco_shim_exports.ScrollType || ((_editor = monaco_shim_exports.editor) === null || _editor === void 0 ? void 0 : _editor.ScrollType);
970
1137
  const smooth = ScrollType && typeof ScrollType.Smooth !== "undefined" ? ScrollType.Smooth : void 0;
971
1138
  try {
@@ -982,11 +1149,60 @@ var EditorManager = class {
982
1149
  }
983
1150
  });
984
1151
  }
1152
+ performImmediateReveal(line, ticket) {
1153
+ this.dlog("performImmediateReveal line=", line, "ticket=", ticket);
1154
+ try {
1155
+ var _editor2;
1156
+ if (!this.editorView) return;
1157
+ if (ticket !== this.revealTicket) {
1158
+ this.dlog("performImmediateReveal skipped, stale ticket", ticket, "current", this.revealTicket);
1159
+ return;
1160
+ }
1161
+ this.lastPerformedRevealTicket = ticket;
1162
+ const ScrollType = monaco_shim_exports.ScrollType || ((_editor2 = monaco_shim_exports.editor) === null || _editor2 === void 0 ? void 0 : _editor2.ScrollType);
1163
+ const immediate = ScrollType && typeof ScrollType.Immediate !== "undefined" ? ScrollType.Immediate : void 0;
1164
+ if (typeof immediate !== "undefined") this.editorView.revealLine(line, immediate);
1165
+ else this.editorView.revealLine(line);
1166
+ } catch {}
1167
+ try {
1168
+ this.measureViewport();
1169
+ } catch {}
1170
+ }
1171
+ forceReveal(line) {
1172
+ try {
1173
+ var _editor3;
1174
+ if (!this.editorView) return;
1175
+ const ScrollType = monaco_shim_exports.ScrollType || ((_editor3 = monaco_shim_exports.editor) === null || _editor3 === void 0 ? void 0 : _editor3.ScrollType);
1176
+ const immediate = ScrollType && typeof ScrollType.Immediate !== "undefined" ? ScrollType.Immediate : void 0;
1177
+ if (typeof immediate !== "undefined") this.editorView.revealLine(line, immediate);
1178
+ else this.editorView.revealLine(line);
1179
+ } catch {}
1180
+ try {
1181
+ this.measureViewport();
1182
+ } catch {}
1183
+ try {
1184
+ var _this$editorView4, _this$editorView4$get;
1185
+ this.shouldAutoScroll = true;
1186
+ 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;
1187
+ } catch {}
1188
+ }
1189
+ isOverflowAuto() {
1190
+ try {
1191
+ return !!this.lastContainer && this.lastContainer.style.overflow === "auto";
1192
+ } catch {
1193
+ return false;
1194
+ }
1195
+ }
1196
+ shouldPerformImmediateReveal() {
1197
+ return this.autoScrollOnUpdate && this.shouldAutoScroll && this.hasVerticalScrollbar() && this.isOverflowAuto();
1198
+ }
985
1199
  async createEditor(container, code, language, currentTheme) {
986
- var _this$editorView$getS3, _this$editorView4, _this$editorView$getO, _this$editorView5, _this$editorView$getM, _this$editorView$onDi, _this$editorView6;
1200
+ var _this$editorView$getS3, _this$editorView5, _this$editorView$getO, _this$editorView6, _this$editorView$getM, _this$editorView$onDi, _this$editorView7;
987
1201
  this.cleanup();
988
1202
  this.lastContainer = container;
989
- container.style.overflow = "auto";
1203
+ this.initDebugFlag();
1204
+ this.dlog("createEditor container, maxHeight", this.maxHeightValue);
1205
+ container.style.overflow = "hidden";
990
1206
  container.style.maxHeight = this.maxHeightCSS;
991
1207
  this.editorView = monaco_shim_exports.editor.create(container, {
992
1208
  value: code,
@@ -1017,22 +1233,51 @@ var EditorManager = class {
1017
1233
  }
1018
1234
  if (this.revealIdleTimerId != null) clearTimeout(this.revealIdleTimerId);
1019
1235
  this.revealIdleTimerId = null;
1020
- this.editorHeightManager = createHeightManager(container, () => this.computedHeight(this.editorView));
1236
+ const MIN_VISIBLE_HEIGHT = Math.min(120, this.maxHeightValue);
1237
+ container.style.minHeight = `${MIN_VISIBLE_HEIGHT}px`;
1238
+ this.editorHeightManager = createHeightManager(container, () => {
1239
+ const computed$1 = this.computedHeight(this.editorView);
1240
+ const clamped = Math.min(computed$1, this.maxHeightValue);
1241
+ return Math.max(clamped, MIN_VISIBLE_HEIGHT);
1242
+ });
1021
1243
  this.editorHeightManager.update();
1022
- 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;
1023
- 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;
1244
+ const initialComputed = this.computedHeight(this.editorView);
1245
+ if (initialComputed >= this.maxHeightValue - 1) {
1246
+ container.style.height = `${this.maxHeightValue}px`;
1247
+ container.style.overflow = "auto";
1248
+ this.dlog("applied immediate maxHeight on createEditor", this.maxHeightValue);
1249
+ }
1250
+ 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;
1251
+ 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;
1024
1252
  this.cachedComputedHeight = this.computedHeight(this.editorView);
1025
1253
  this.cachedLineCount = ((_this$editorView$getM = this.editorView.getModel()) === null || _this$editorView$getM === void 0 ? void 0 : _this$editorView$getM.getLineCount()) ?? null;
1026
- (_this$editorView$onDi = (_this$editorView6 = this.editorView).onDidContentSizeChange) === null || _this$editorView$onDi === void 0 || _this$editorView$onDi.call(_this$editorView6, () => {
1254
+ (_this$editorView$onDi = (_this$editorView7 = this.editorView).onDidContentSizeChange) === null || _this$editorView$onDi === void 0 || _this$editorView$onDi.call(_this$editorView7, () => {
1027
1255
  this._hasScrollBar = false;
1028
1256
  this.rafScheduler.schedule("content-size-change", () => {
1029
1257
  try {
1030
- var _this$editorView7, _this$editorHeightMan, _this$editorHeightMan2;
1031
- this.measureViewport();
1032
- 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;
1033
- if ((_this$editorHeightMan = this.editorHeightManager) === null || _this$editorHeightMan === void 0 ? void 0 : _this$editorHeightMan.isSuppressed()) return;
1258
+ var _this$editorView8, _this$editorHeightMan, _this$editorHeightMan2;
1259
+ this.dlog("content-size-change frame");
1260
+ const m = this.measureViewport();
1261
+ this.dlog("content-size-change measure", m);
1262
+ 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;
1263
+ if ((_this$editorHeightMan = this.editorHeightManager) === null || _this$editorHeightMan === void 0 ? void 0 : _this$editorHeightMan.isSuppressed()) {
1264
+ this.dlog("content-size-change skipped height update (suppressed)");
1265
+ return;
1266
+ }
1267
+ this.dlog("content-size-change calling heightManager.update");
1034
1268
  (_this$editorHeightMan2 = this.editorHeightManager) === null || _this$editorHeightMan2 === void 0 || _this$editorHeightMan2.update();
1035
- } catch {}
1269
+ const computed$1 = this.computedHeight(this.editorView);
1270
+ if (this.lastContainer) {
1271
+ const prevOverflow = this.lastContainer.style.overflow;
1272
+ const newOverflow = computed$1 >= this.maxHeightValue - 1 ? "auto" : "hidden";
1273
+ if (prevOverflow !== newOverflow) {
1274
+ this.lastContainer.style.overflow = newOverflow;
1275
+ if (newOverflow === "auto" && this.shouldAutoScroll) this.maybeScrollToBottom();
1276
+ }
1277
+ }
1278
+ } catch (err) {
1279
+ error("EditorManager", "content-size-change error", err);
1280
+ }
1036
1281
  });
1037
1282
  });
1038
1283
  this.editorView.onDidChangeModelContent(() => {
@@ -1073,6 +1318,65 @@ var EditorManager = class {
1073
1318
  this.lastKnownCodeDirty = false;
1074
1319
  }
1075
1320
  }
1321
+ suppressScrollWatcher(ms) {
1322
+ try {
1323
+ if (!this.scrollWatcher || typeof this.scrollWatcher.setSuppressed !== "function") return;
1324
+ this.dlog("suppressScrollWatcher", ms);
1325
+ if (this.scrollWatcherSuppressionTimer != null) {
1326
+ clearTimeout(this.scrollWatcherSuppressionTimer);
1327
+ this.scrollWatcherSuppressionTimer = null;
1328
+ }
1329
+ this.scrollWatcher.setSuppressed(true);
1330
+ this.scrollWatcherSuppressionTimer = setTimeout(() => {
1331
+ try {
1332
+ if (this.scrollWatcher && typeof this.scrollWatcher.setSuppressed === "function") {
1333
+ this.scrollWatcher.setSuppressed(false);
1334
+ this.dlog("suppressScrollWatcher cleared");
1335
+ }
1336
+ } catch {}
1337
+ this.scrollWatcherSuppressionTimer = null;
1338
+ }, ms);
1339
+ } catch {}
1340
+ }
1341
+ scheduleImmediateRevealAfterLayout(line) {
1342
+ const ticket = ++this.revealTicket;
1343
+ this.dlog("scheduleImmediateRevealAfterLayout ticket=", ticket, "line=", line);
1344
+ this.rafScheduler.schedule("immediate-reveal", async () => {
1345
+ try {
1346
+ const target = this.editorView && this.editorHeightManager ? Math.min(this.computedHeight(this.editorView), this.maxHeightValue) : -1;
1347
+ if (target !== -1 && this.editorHeightManager) await this.waitForHeightApplied(target, 500);
1348
+ else await new Promise((r) => requestAnimationFrame(() => requestAnimationFrame(() => r())));
1349
+ this.dlog("running delayed immediate reveal", "ticket=", ticket, "line=", line);
1350
+ this.performImmediateReveal(line, ticket);
1351
+ } catch (err) {
1352
+ error("EditorManager", "scheduleImmediateRevealAfterLayout error", err);
1353
+ }
1354
+ });
1355
+ }
1356
+ waitForHeightApplied(target, timeoutMs = 500) {
1357
+ return new Promise((resolve) => {
1358
+ const start = typeof performance !== "undefined" && performance.now ? performance.now() : Date.now();
1359
+ const check = () => {
1360
+ try {
1361
+ var _this$editorHeightMan3, _this$editorHeightMan4;
1362
+ 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;
1363
+ if (last !== -1 && Math.abs(last - target) <= 12) {
1364
+ this.dlog("waitForHeightApplied satisfied", last, "target=", target);
1365
+ resolve();
1366
+ return;
1367
+ }
1368
+ const now = typeof performance !== "undefined" && performance.now ? performance.now() : Date.now();
1369
+ if (now - start > timeoutMs) {
1370
+ log("EditorManager", "waitForHeightApplied timeout", last, "target=", target);
1371
+ resolve();
1372
+ return;
1373
+ }
1374
+ } catch {}
1375
+ requestAnimationFrame(check);
1376
+ };
1377
+ check();
1378
+ });
1379
+ }
1076
1380
  updateCode(newCode, codeLanguage) {
1077
1381
  this.pendingUpdate = {
1078
1382
  code: newCode,
@@ -1095,10 +1399,21 @@ var EditorManager = class {
1095
1399
  this.lastKnownCode = newCode;
1096
1400
  const newLineCount$1 = model.getLineCount();
1097
1401
  this.cachedLineCount = newLineCount$1;
1098
- if (newLineCount$1 !== prevLineCount$1) this.maybeScrollToBottom(newLineCount$1);
1402
+ if (newLineCount$1 !== prevLineCount$1) {
1403
+ const shouldImmediate = this.shouldPerformImmediateReveal();
1404
+ if (shouldImmediate) this.suppressScrollWatcher(this.scrollWatcherSuppressionMs);
1405
+ try {
1406
+ const computed$1 = this.computedHeight(this.editorView);
1407
+ if (computed$1 >= this.maxHeightValue - 1 && this.lastContainer) this.lastContainer.style.height = `${this.maxHeightValue}px`;
1408
+ } catch {}
1409
+ if (shouldImmediate) try {
1410
+ this.forceReveal(newLineCount$1);
1411
+ } catch {}
1412
+ else this.maybeScrollToBottom(newLineCount$1);
1413
+ }
1099
1414
  return;
1100
1415
  }
1101
- const prevCode = this.lastKnownCode ?? this.editorView.getValue();
1416
+ const prevCode = this.appendBuffer.length > 0 ? this.editorView.getValue() : this.lastKnownCode ?? this.editorView.getValue();
1102
1417
  if (prevCode === newCode) return;
1103
1418
  if (newCode.startsWith(prevCode) && prevCode.length < newCode.length) {
1104
1419
  const suffix = newCode.slice(prevCode.length);
@@ -1111,7 +1426,12 @@ var EditorManager = class {
1111
1426
  this.lastKnownCode = newCode;
1112
1427
  const newLineCount = model.getLineCount();
1113
1428
  this.cachedLineCount = newLineCount;
1114
- if (newLineCount !== prevLineCount) this.maybeScrollToBottom(newLineCount);
1429
+ if (newLineCount !== prevLineCount) {
1430
+ const shouldImmediate = this.shouldPerformImmediateReveal();
1431
+ if (shouldImmediate) this.suppressScrollWatcher(this.scrollWatcherSuppressionMs);
1432
+ if (shouldImmediate) this.scheduleImmediateRevealAfterLayout(newLineCount);
1433
+ else this.maybeScrollToBottom(newLineCount);
1434
+ }
1115
1435
  }
1116
1436
  appendCode(appendText, codeLanguage) {
1117
1437
  if (!this.editorView) return;
@@ -1189,7 +1509,16 @@ var EditorManager = class {
1189
1509
  const newLineCount = model.getLineCount();
1190
1510
  if (lastLine !== newLineCount) {
1191
1511
  this.cachedLineCount = newLineCount;
1192
- this.maybeScrollToBottom(newLineCount);
1512
+ const shouldImmediate = this.shouldPerformImmediateReveal();
1513
+ if (shouldImmediate) this.suppressScrollWatcher(this.scrollWatcherSuppressionMs);
1514
+ try {
1515
+ const computed$1 = this.computedHeight(this.editorView);
1516
+ if (computed$1 >= this.maxHeightValue - 1 && this.lastContainer) this.lastContainer.style.height = `${this.maxHeightValue}px`;
1517
+ } catch {}
1518
+ if (shouldImmediate) try {
1519
+ this.forceReveal(newLineCount);
1520
+ } catch {}
1521
+ else this.maybeScrollToBottom(newLineCount);
1193
1522
  }
1194
1523
  }
1195
1524
  setLanguage(language, languages$1) {
@@ -1207,16 +1536,33 @@ var EditorManager = class {
1207
1536
  this.rafScheduler.cancel("update");
1208
1537
  this.rafScheduler.cancel("sync-last-known");
1209
1538
  this.rafScheduler.cancel("content-size-change");
1539
+ this.rafScheduler.cancel("maybe-scroll");
1540
+ this.rafScheduler.cancel("reveal");
1541
+ this.rafScheduler.cancel("immediate-reveal");
1542
+ this.rafScheduler.cancel("maybe-resume");
1210
1543
  this.pendingUpdate = null;
1211
1544
  this.rafScheduler.cancel("append");
1212
1545
  this.appendBufferScheduled = false;
1213
1546
  this.appendBuffer.length = 0;
1547
+ if (this.revealDebounceId != null) {
1548
+ clearTimeout(this.revealDebounceId);
1549
+ this.revealDebounceId = null;
1550
+ }
1551
+ if (this.revealIdleTimerId != null) {
1552
+ clearTimeout(this.revealIdleTimerId);
1553
+ this.revealIdleTimerId = null;
1554
+ }
1555
+ if (this.scrollWatcherSuppressionTimer != null) {
1556
+ clearTimeout(this.scrollWatcherSuppressionTimer);
1557
+ this.scrollWatcherSuppressionTimer = null;
1558
+ }
1214
1559
  if (this.editorView) {
1215
1560
  this.editorView.dispose();
1216
1561
  this.editorView = null;
1217
1562
  }
1218
1563
  this.lastKnownCode = null;
1219
1564
  if (this.lastContainer) {
1565
+ this.lastContainer.style.minHeight = "";
1220
1566
  this.lastContainer.innerHTML = "";
1221
1567
  this.lastContainer = null;
1222
1568
  }
@@ -1234,13 +1580,27 @@ var EditorManager = class {
1234
1580
  this.pendingUpdate = null;
1235
1581
  this.rafScheduler.cancel("sync-last-known");
1236
1582
  if (this.scrollWatcher) {
1237
- this.scrollWatcher.dispose();
1583
+ try {
1584
+ this.scrollWatcher.dispose();
1585
+ } catch {}
1238
1586
  this.scrollWatcher = null;
1239
1587
  }
1240
1588
  if (this.revealDebounceId != null) {
1241
1589
  clearTimeout(this.revealDebounceId);
1242
1590
  this.revealDebounceId = null;
1243
1591
  }
1592
+ if (this.revealIdleTimerId != null) {
1593
+ clearTimeout(this.revealIdleTimerId);
1594
+ this.revealIdleTimerId = null;
1595
+ }
1596
+ if (this.scrollWatcherSuppressionTimer != null) {
1597
+ clearTimeout(this.scrollWatcherSuppressionTimer);
1598
+ this.scrollWatcherSuppressionTimer = null;
1599
+ }
1600
+ this.rafScheduler.cancel("maybe-scroll");
1601
+ this.rafScheduler.cancel("reveal");
1602
+ this.rafScheduler.cancel("immediate-reveal");
1603
+ this.rafScheduler.cancel("maybe-resume");
1244
1604
  this._hasScrollBar = false;
1245
1605
  this.shouldAutoScroll = !!this.autoScrollInitial;
1246
1606
  this.lastScrollTop = 0;
@@ -1547,6 +1907,7 @@ let RevealStrategy = /* @__PURE__ */ function(RevealStrategy$1) {
1547
1907
  * getEditorView: () => monaco.editor.IStandaloneCodeEditor | null,
1548
1908
  * getDiffEditorView: () => monaco.editor.IStandaloneDiffEditor | null,
1549
1909
  * getDiffModels: () => { original: monaco.editor.ITextModel | null, modified: monaco.editor.ITextModel | null },
1910
+ * getCode: () => string | { original: string, modified: string } | null,
1550
1911
  * }} 返回对象包含以下方法和属性:
1551
1912
  *
1552
1913
  * @property {Function} createEditor - 创建并挂载 Monaco 编辑器到指定容器
@@ -1566,6 +1927,7 @@ let RevealStrategy = /* @__PURE__ */ function(RevealStrategy$1) {
1566
1927
  * @property {Function} getEditorView - 获取当前编辑器实例
1567
1928
  * @property {Function} getDiffEditorView - 获取当前 Diff 编辑器实例
1568
1929
  * @property {Function} getDiffModels - 获取 Diff 的 original/modified 两个模型
1930
+ * @property {Function} getCode - 获取当前编辑器或 Diff 编辑器中的代码内容
1569
1931
  *
1570
1932
  * @throws {Error} 当主题数组不是数组或长度小于2时抛出错误
1571
1933
  *
@@ -1865,13 +2227,22 @@ function useMonaco(monacoOptions = {}) {
1865
2227
  const { code: newCode, lang: codeLanguage } = pendingUpdate;
1866
2228
  pendingUpdate = null;
1867
2229
  const processedCodeLanguage = processedLanguage(codeLanguage);
1868
- let prevCode = lastKnownCode;
1869
- if (prevCode == null) try {
2230
+ let prevCode = null;
2231
+ if (appendBuffer.length > 0) try {
1870
2232
  prevCode = model.getValue();
1871
2233
  lastKnownCode = prevCode;
1872
2234
  } catch {
1873
2235
  prevCode = "";
1874
2236
  }
2237
+ else {
2238
+ prevCode = lastKnownCode;
2239
+ if (prevCode == null) try {
2240
+ prevCode = model.getValue();
2241
+ lastKnownCode = prevCode;
2242
+ } catch {
2243
+ prevCode = "";
2244
+ }
2245
+ }
1875
2246
  if (prevCode === newCode) return;
1876
2247
  const languageId = model.getLanguageId();
1877
2248
  if (languageId !== processedCodeLanguage) {
@@ -2063,7 +2434,26 @@ function useMonaco(monacoOptions = {}) {
2063
2434
  return monaco_shim_exports;
2064
2435
  },
2065
2436
  setUpdateThrottleMs,
2066
- getUpdateThrottleMs
2437
+ getUpdateThrottleMs,
2438
+ getCode() {
2439
+ if (editorView) try {
2440
+ var _editorView$getModel;
2441
+ return ((_editorView$getModel = editorView.getModel()) === null || _editorView$getModel === void 0 ? void 0 : _editorView$getModel.getValue()) ?? null;
2442
+ } catch {
2443
+ return null;
2444
+ }
2445
+ if (diffEditorView || originalModel && modifiedModel) try {
2446
+ const original = (originalModel === null || originalModel === void 0 ? void 0 : originalModel.getValue()) ?? "";
2447
+ const modified = (modifiedModel === null || modifiedModel === void 0 ? void 0 : modifiedModel.getValue()) ?? "";
2448
+ return {
2449
+ original,
2450
+ modified
2451
+ };
2452
+ } catch {
2453
+ return null;
2454
+ }
2455
+ return null;
2456
+ }
2067
2457
  };
2068
2458
  }
2069
2459