stream-monaco 0.0.42 → 0.0.45

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.
@@ -527,6 +527,14 @@ function createScrollWatcherForEditor(ed, opts) {
527
527
  return api;
528
528
  }
529
529
 
530
+ //#endregion
531
+ //#region src/utils/textChunks.ts
532
+ function countLineBreaks(text) {
533
+ let count = 0;
534
+ for (let i = 0; i < text.length; i++) if (text.charCodeAt(i) === 10) count += 1;
535
+ return count;
536
+ }
537
+
530
538
  //#endregion
531
539
  //#region src/core/diffAppearance.ts
532
540
  function parseCssColorRgb(color) {
@@ -1753,6 +1761,23 @@ var DiffEditorManager = class DiffEditorManager {
1753
1761
  if (typeof direct === "function") return direct.call(model, lineNumber);
1754
1762
  return model.getValue().split(/\r?\n/)[lineNumber - 1] ?? "";
1755
1763
  }
1764
+ colorizeFallbackInlineDeletedLine(lineNode, model, lineText, tabSize) {
1765
+ var _model$getLanguageId;
1766
+ const language = (_model$getLanguageId = model.getLanguageId) === null || _model$getLanguageId === void 0 ? void 0 : _model$getLanguageId.call(model);
1767
+ const colorize = monaco_shim_exports.editor.colorize;
1768
+ if (!language || typeof colorize !== "function") return;
1769
+ const signature = `${language}:${lineText}`;
1770
+ lineNode.dataset.streamMonacoColorizeSignature = signature;
1771
+ colorize(lineText, language, { tabSize }).then((html) => {
1772
+ if (lineNode.dataset.streamMonacoColorizeSignature !== signature) return;
1773
+ lineNode.innerHTML = html;
1774
+ }).catch(() => {});
1775
+ }
1776
+ getModelTabSize(model) {
1777
+ var _model$getOptions;
1778
+ const tabSize = (_model$getOptions = model.getOptions) === null || _model$getOptions === void 0 ? void 0 : _model$getOptions.call(model).tabSize;
1779
+ return typeof tabSize === "number" && Number.isFinite(tabSize) ? tabSize : void 0;
1780
+ }
1756
1781
  hasVisibleNativeInlineDeleteNodes() {
1757
1782
  if (!this.lastContainer) return false;
1758
1783
  const querySelectorAll = typeof this.lastContainer.querySelectorAll === "function" ? this.lastContainer.querySelectorAll.bind(this.lastContainer) : null;
@@ -1791,6 +1816,7 @@ var DiffEditorManager = class DiffEditorManager {
1791
1816
  }
1792
1817
  const lineHeightOption = (_EditorOption = monaco_shim_exports.editor.EditorOption) === null || _EditorOption === void 0 ? void 0 : _EditorOption.lineHeight;
1793
1818
  const lineHeight = ((_modifiedEditor$getOp = modifiedEditor.getOption) === null || _modifiedEditor$getOp === void 0 ? void 0 : _modifiedEditor$getOp.call(modifiedEditor, lineHeightOption)) ?? 20;
1819
+ const originalTabSize = this.getModelTabSize(originalModel);
1794
1820
  const relevantChanges = lineChanges.filter((change) => hasOriginalLines(change));
1795
1821
  const nativeViewWrappers = Array.from(((_this$lastContainer3 = this.lastContainer) === null || _this$lastContainer3 === void 0 || (_this$lastContainer3$ = _this$lastContainer3.querySelectorAll) === null || _this$lastContainer3$ === void 0 ? void 0 : _this$lastContainer3$.call(_this$lastContainer3, ".editor.modified .view-zones [monaco-view-zone]")) ?? []).filter((node) => {
1796
1822
  return node instanceof HTMLElement && !!node.querySelector(".view-lines.line-delete");
@@ -1835,12 +1861,14 @@ var DiffEditorManager = class DiffEditorManager {
1835
1861
  domNode.setAttribute("data-stream-monaco-native-wrapper", "true");
1836
1862
  (_modifiedEditor$apply = modifiedEditor.applyFontInfo) === null || _modifiedEditor$apply === void 0 || _modifiedEditor$apply.call(modifiedEditor, domNode);
1837
1863
  for (let line = change.originalStartLineNumber; line <= change.originalEndLineNumber; line++) {
1864
+ const lineText = this.readModelLineContent(originalModel, line);
1838
1865
  const lineNode = document.createElement("div");
1839
1866
  lineNode.className = "stream-monaco-fallback-inline-delete-line";
1840
- lineNode.textContent = this.readModelLineContent(originalModel, line);
1867
+ lineNode.textContent = lineText;
1841
1868
  lineNode.style.height = `${lineHeight}px`;
1842
1869
  lineNode.style.lineHeight = `${lineHeight}px`;
1843
1870
  domNode.append(lineNode);
1871
+ this.colorizeFallbackInlineDeletedLine(lineNode, originalModel, lineText, originalTabSize);
1844
1872
  }
1845
1873
  pair.viewWrapper.append(domNode);
1846
1874
  if (pair.marginWrapper) {
@@ -1867,12 +1895,14 @@ var DiffEditorManager = class DiffEditorManager {
1867
1895
  domNode.setAttribute("aria-hidden", "true");
1868
1896
  (_modifiedEditor$apply3 = modifiedEditor.applyFontInfo) === null || _modifiedEditor$apply3 === void 0 || _modifiedEditor$apply3.call(modifiedEditor, domNode);
1869
1897
  for (let line = change.originalStartLineNumber; line <= change.originalEndLineNumber; line++) {
1898
+ const lineText = this.readModelLineContent(originalModel, line);
1870
1899
  const lineNode = document.createElement("div");
1871
1900
  lineNode.className = "stream-monaco-fallback-inline-delete-line";
1872
- lineNode.textContent = this.readModelLineContent(originalModel, line);
1901
+ lineNode.textContent = lineText;
1873
1902
  lineNode.style.height = `${lineHeight}px`;
1874
1903
  lineNode.style.lineHeight = `${lineHeight}px`;
1875
1904
  domNode.append(lineNode);
1905
+ this.colorizeFallbackInlineDeletedLine(lineNode, originalModel, lineText, originalTabSize);
1876
1906
  }
1877
1907
  const marginDomNode = document.createElement("div");
1878
1908
  marginDomNode.className = "stream-monaco-fallback-inline-delete-margin";
@@ -4431,9 +4461,10 @@ var DiffEditorManager = class DiffEditorManager {
4431
4461
  shouldAutoScrollDiff: this.shouldAutoScrollDiff
4432
4462
  });
4433
4463
  if (!this.diffEditorView) return;
4464
+ if (!(this.diffAutoScroll && this.autoScrollOnUpdate && this.shouldAutoScrollDiff)) return;
4434
4465
  const hasV = this.hasVerticalScrollbarModified();
4435
4466
  log("diff", "hasVerticalScrollbarModified ->", hasV);
4436
- if (!(this.diffAutoScroll && this.autoScrollOnUpdate && this.shouldAutoScrollDiff && hasV)) return;
4467
+ if (!hasV) return;
4437
4468
  const me = this.diffEditorView.getModifiedEditor();
4438
4469
  const model = me.getModel();
4439
4470
  const currentLine = (model === null || model === void 0 ? void 0 : model.getLineCount()) ?? 1;
@@ -4655,7 +4686,7 @@ var DiffEditorManager = class DiffEditorManager {
4655
4686
  this.diffComputedVersions = null;
4656
4687
  this.diffPresentationDisposables.push(this.diffEditorView.onDidUpdateDiff(() => {
4657
4688
  this.diffComputedVersions = this.captureCurrentDiffVersions();
4658
- this.syncDiffEditorLayoutToContainer();
4689
+ this.scheduleSyncDiffEditorLayoutToContainer();
4659
4690
  this.scheduleSyncDiffPresentationDecorations();
4660
4691
  }));
4661
4692
  this.diffPresentationDisposables.push(oEditor.onDidChangeModelContent(() => {
@@ -4820,6 +4851,7 @@ var DiffEditorManager = class DiffEditorManager {
4820
4851
  }
4821
4852
  updateModified(newCode, codeLanguage) {
4822
4853
  if (!this.diffEditorView || !this.modifiedModel) return;
4854
+ this.syncLastKnownModified();
4823
4855
  if (codeLanguage) {
4824
4856
  const lang = processedLanguage(codeLanguage);
4825
4857
  if (lang && this.modifiedModel.getLanguageId() !== lang) monaco_shim_exports.editor.setModelLanguage(this.modifiedModel, lang);
@@ -4832,7 +4864,7 @@ var DiffEditorManager = class DiffEditorManager {
4832
4864
  if (tailAppend) this.appendModified(newCode.slice(prev.length), codeLanguage);
4833
4865
  else {
4834
4866
  this.flushModifiedAppendBufferSync();
4835
- const prevAfterFlush = this.modifiedModel.getValue();
4867
+ const prevAfterFlush = this.lastKnownModifiedCode ?? this.modifiedModel.getValue();
4836
4868
  const prevLine = this.modifiedModel.getLineCount();
4837
4869
  this.applyMinimalEditToModel(this.modifiedModel, prevAfterFlush, newCode);
4838
4870
  const newLine = this.modifiedModel.getLineCount();
@@ -5082,6 +5114,7 @@ var DiffEditorManager = class DiffEditorManager {
5082
5114
  }
5083
5115
  const { original, modified, lang } = this.pendingDiffUpdate;
5084
5116
  this.pendingDiffUpdate = null;
5117
+ this.syncLastKnownModified();
5085
5118
  this.flushOriginalAppendBufferSync();
5086
5119
  this.flushModifiedAppendBufferSync();
5087
5120
  if (lang) {
@@ -5102,7 +5135,7 @@ var DiffEditorManager = class DiffEditorManager {
5102
5135
  else this.applyMinimalEditToModel(o, prevO, original);
5103
5136
  this.lastKnownOriginalCode = original;
5104
5137
  }
5105
- const prevM = m.getValue();
5138
+ const prevM = this.lastKnownModifiedCode;
5106
5139
  const prevMLineCount = m.getLineCount();
5107
5140
  const modifiedTailAppend = prevM !== modified && modified.startsWith(prevM) && prevM.length < modified.length;
5108
5141
  const hasContentChange = prevO !== original || prevM !== modified;
@@ -5143,6 +5176,33 @@ var DiffEditorManager = class DiffEditorManager {
5143
5176
  this.preserveNativeDiffDecorationsOnStaleAppend = true;
5144
5177
  this.appendToModel(this.modifiedModel, text);
5145
5178
  }
5179
+ splitAppendTextForProgressiveFlush(text, maxChunkChars = 12e3, maxChunkLines = 200) {
5180
+ if (!text || text.length <= maxChunkChars) return [text];
5181
+ const chunks = [];
5182
+ let start = 0;
5183
+ let lineCount = 0;
5184
+ let lastSafeEnd = 0;
5185
+ for (let i = 0; i < text.length; i++) {
5186
+ if (text.charCodeAt(i) === 10) {
5187
+ lineCount += 1;
5188
+ lastSafeEnd = i + 1;
5189
+ }
5190
+ if (i - start + 1 < maxChunkChars && lineCount < maxChunkLines) continue;
5191
+ let end = lastSafeEnd > start ? lastSafeEnd : i + 1;
5192
+ if (end < text.length) {
5193
+ const prev = text.charCodeAt(end - 1);
5194
+ const next = text.charCodeAt(end);
5195
+ if (prev >= 55296 && prev <= 56319 && next >= 56320 && next <= 57343) end += 1;
5196
+ }
5197
+ chunks.push(text.slice(start, end));
5198
+ start = end;
5199
+ i = end - 1;
5200
+ lineCount = 0;
5201
+ lastSafeEnd = start;
5202
+ }
5203
+ if (start < text.length) chunks.push(text.slice(start));
5204
+ return chunks.length ? chunks : [text];
5205
+ }
5146
5206
  async flushAppendBufferDiff() {
5147
5207
  if (!this.diffEditorView) return;
5148
5208
  if (this.appendBufferOriginalDiff.length === 0 && this.appendBufferModifiedDiff.length === 0) return;
@@ -5163,17 +5223,16 @@ var DiffEditorManager = class DiffEditorManager {
5163
5223
  return;
5164
5224
  }
5165
5225
  let parts = this.appendBufferModifiedDiff.splice(0);
5226
+ if (parts.length === 0) {
5227
+ this.eagerlyGrowDiffContainerHeight();
5228
+ return;
5229
+ }
5166
5230
  const prevLineInit = model.getLineCount();
5167
5231
  const totalText = parts.join("");
5168
5232
  const totalChars = totalText.length;
5169
- if (parts.length === 1 && totalChars > 5e3) {
5170
- const lines = totalText.split(/\r?\n/);
5171
- const chunkSize = 200;
5172
- const chunks = [];
5173
- for (let i = 0; i < lines.length; i += chunkSize) chunks.push(`${lines.slice(i, i + chunkSize).join("\n")}\n`);
5174
- if (chunks.length > 1) parts = chunks;
5175
- }
5176
- const applyChunked = parts.length > 1 && (totalChars > 2e3 || model.getLineCount && model.getLineCount() + 0 - prevLineInit > 50);
5233
+ const totalLineBreaks = countLineBreaks(totalText);
5234
+ if (parts.length === 1 && totalChars > 5e3) parts = this.splitAppendTextForProgressiveFlush(totalText);
5235
+ const applyChunked = parts.length > 1 && (totalChars > 2e3 || totalLineBreaks > 50);
5177
5236
  log("diff", "flushAppendBufferDiff start", {
5178
5237
  partsCount: parts.length,
5179
5238
  totalChars,
@@ -5192,6 +5251,8 @@ var DiffEditorManager = class DiffEditorManager {
5192
5251
  } catch {}
5193
5252
  if (applyChunked) {
5194
5253
  log("diff", "flushAppendBufferDiff applying chunked", { partsLen: parts.length });
5254
+ if (this.lastKnownModifiedCode == null) this.lastKnownModifiedCode = model.getValue();
5255
+ let currentLength = this.lastKnownModifiedCode.length;
5195
5256
  let idx = 0;
5196
5257
  for (const part of parts) {
5197
5258
  if (!part) continue;
@@ -5201,17 +5262,9 @@ var DiffEditorManager = class DiffEditorManager {
5201
5262
  partLen: part.length,
5202
5263
  prevLine
5203
5264
  });
5204
- const lastColumn$1 = model.getLineMaxColumn(prevLine);
5205
- const range$1 = new monaco_shim_exports.Range(prevLine, lastColumn$1, prevLine, lastColumn$1);
5206
5265
  this.preserveNativeDiffDecorationsOnStaleAppend = true;
5207
- this.runAsProgrammaticModifiedContentChange(() => {
5208
- model.applyEdits([{
5209
- range: range$1,
5210
- text: part,
5211
- forceMoveMarkers: true
5212
- }]);
5213
- });
5214
- this.lastKnownModifiedCode = model.getValue();
5266
+ this.appendToModel(model, part, currentLength);
5267
+ currentLength += part.length;
5215
5268
  const newLine$1 = model.getLineCount();
5216
5269
  this.lastKnownModifiedLineCount = newLine$1;
5217
5270
  await new Promise((resolve) => typeof requestAnimationFrame !== "undefined" ? requestAnimationFrame(resolve) : setTimeout(resolve, 0));
@@ -5237,23 +5290,15 @@ var DiffEditorManager = class DiffEditorManager {
5237
5290
  newLine: newLine$1
5238
5291
  });
5239
5292
  }
5293
+ this.lastKnownModifiedCode = model.getValue();
5240
5294
  if (suppressedByFlush) watcherApi.setSuppressed(false);
5241
5295
  return;
5242
5296
  }
5243
5297
  const text = totalText;
5244
5298
  this.appendBufferModifiedDiff.length = 0;
5245
5299
  prevLine = model.getLineCount();
5246
- const lastColumn = model.getLineMaxColumn(prevLine);
5247
- const range = new monaco_shim_exports.Range(prevLine, lastColumn, prevLine, lastColumn);
5248
5300
  this.preserveNativeDiffDecorationsOnStaleAppend = true;
5249
- this.runAsProgrammaticModifiedContentChange(() => {
5250
- model.applyEdits([{
5251
- range,
5252
- text,
5253
- forceMoveMarkers: true
5254
- }]);
5255
- });
5256
- this.lastKnownModifiedCode = model.getValue();
5301
+ this.appendToModel(model, text);
5257
5302
  const newLine = model.getLineCount();
5258
5303
  this.lastKnownModifiedLineCount = newLine;
5259
5304
  this.eagerlyGrowDiffContainerHeight();
@@ -5296,8 +5341,30 @@ var DiffEditorManager = class DiffEditorManager {
5296
5341
  });
5297
5342
  if (model === this.modifiedModel) this.lastKnownModifiedLineCount = model.getLineCount();
5298
5343
  }
5299
- appendToModel(model, appendText) {
5344
+ getModelValueLength(model) {
5345
+ const getValueLength = model.getValueLength;
5346
+ if (typeof getValueLength === "function") try {
5347
+ return getValueLength.call(model);
5348
+ } catch {}
5349
+ return model.getValue().length;
5350
+ }
5351
+ mergeKnownAppend(known, appendText, previousLength, model) {
5352
+ if (known == null) return model.getValue();
5353
+ const nextLength = previousLength + appendText.length;
5354
+ if (known.length === previousLength) return known + appendText;
5355
+ if (known.length >= nextLength && known.slice(previousLength, nextLength) === appendText) return known;
5356
+ return model.getValue();
5357
+ }
5358
+ syncKnownCodeAfterAppend(model, appendText, previousLength) {
5359
+ if (model === this.originalModel) {
5360
+ this.lastKnownOriginalCode = this.mergeKnownAppend(this.lastKnownOriginalCode, appendText, previousLength, model);
5361
+ return;
5362
+ }
5363
+ if (model === this.modifiedModel) this.lastKnownModifiedCode = this.mergeKnownAppend(this.lastKnownModifiedCode, appendText, previousLength, model);
5364
+ }
5365
+ appendToModel(model, appendText, knownLength) {
5300
5366
  if (!appendText) return;
5367
+ const previousLength = knownLength != null ? knownLength : this.getModelValueLength(model);
5301
5368
  const lastLine = model.getLineCount();
5302
5369
  const lastColumn = model.getLineMaxColumn(lastLine);
5303
5370
  const range = new monaco_shim_exports.Range(lastLine, lastColumn, lastLine, lastColumn);
@@ -5309,6 +5376,7 @@ var DiffEditorManager = class DiffEditorManager {
5309
5376
  }]);
5310
5377
  });
5311
5378
  if (model === this.modifiedModel) this.lastKnownModifiedLineCount = model.getLineCount();
5379
+ this.syncKnownCodeAfterAppend(model, appendText, previousLength);
5312
5380
  }
5313
5381
  applyModelEdit(model, fn) {
5314
5382
  if (model === this.modifiedModel) {
@@ -5346,6 +5414,8 @@ var EditorManager = class {
5346
5414
  minimalEditMaxChangeRatioValue = minimalEditMaxChangeRatio;
5347
5415
  lastUpdateFlushTime = 0;
5348
5416
  updateThrottleTimer = null;
5417
+ lastAppendFlushTime = 0;
5418
+ appendFlushThrottleTimer = null;
5349
5419
  shouldAutoScroll = true;
5350
5420
  scrollWatcher = null;
5351
5421
  scrollWatcherSuppressionTimer = null;
@@ -5445,6 +5515,10 @@ var EditorManager = class {
5445
5515
  clearTimeout(this.updateThrottleTimer);
5446
5516
  this.updateThrottleTimer = null;
5447
5517
  }
5518
+ if (this.appendFlushThrottleTimer != null) {
5519
+ clearTimeout(this.appendFlushThrottleTimer);
5520
+ this.appendFlushThrottleTimer = null;
5521
+ }
5448
5522
  }
5449
5523
  initDebugFlag() {
5450
5524
  if (typeof window !== "undefined" && window.__STREAM_MONACO_DEBUG__ !== void 0) {
@@ -5541,6 +5615,14 @@ var EditorManager = class {
5541
5615
  }
5542
5616
  maybeScrollToBottom(targetLine) {
5543
5617
  this.rafScheduler.schedule("maybe-scroll", () => {
5618
+ if (!(this.autoScrollOnUpdate && this.shouldAutoScroll)) {
5619
+ this.dlog("maybeScrollToBottom skipped (auto-scroll disabled)", {
5620
+ autoScrollOnUpdate: this.autoScrollOnUpdate,
5621
+ shouldAutoScroll: this.shouldAutoScroll,
5622
+ targetLine
5623
+ });
5624
+ return;
5625
+ }
5544
5626
  const hasVS = this.hasVerticalScrollbar();
5545
5627
  this.dlog("maybeScrollToBottom called", {
5546
5628
  autoScrollOnUpdate: this.autoScrollOnUpdate,
@@ -5548,8 +5630,8 @@ var EditorManager = class {
5548
5630
  hasVerticalScrollbar: hasVS,
5549
5631
  targetLine
5550
5632
  });
5551
- if (!(this.autoScrollOnUpdate && this.shouldAutoScroll && this.hasVerticalScrollbar())) {
5552
- this.dlog("maybeScrollToBottom skipped (auto-scroll conditions not met)");
5633
+ if (!hasVS) {
5634
+ this.dlog("maybeScrollToBottom skipped (no vertical scrollbar)");
5553
5635
  return;
5554
5636
  }
5555
5637
  const model = this.editorView.getModel();
@@ -5809,7 +5891,7 @@ var EditorManager = class {
5809
5891
  this.lastScrollTop = v;
5810
5892
  }
5811
5893
  });
5812
- this.maybeScrollToBottom();
5894
+ if (this.shouldAutoScroll) this.maybeScrollToBottom();
5813
5895
  return this.editorView;
5814
5896
  }
5815
5897
  syncLastKnownCode() {
@@ -5980,10 +6062,31 @@ var EditorManager = class {
5980
6062
  this.appendBuffer.push(appendText);
5981
6063
  if (!this.appendBufferScheduled) {
5982
6064
  this.appendBufferScheduled = true;
5983
- this.rafScheduler.schedule("append", () => this.flushAppendBuffer());
6065
+ this.scheduleFlushAppendBuffer();
5984
6066
  }
5985
6067
  }
5986
6068
  }
6069
+ scheduleFlushAppendBuffer() {
6070
+ const schedule = () => {
6071
+ this.rafScheduler.schedule("append", () => this.flushAppendBuffer());
6072
+ };
6073
+ if (!this.updateThrottleMs) {
6074
+ schedule();
6075
+ return;
6076
+ }
6077
+ const now = Date.now();
6078
+ const since = now - this.lastAppendFlushTime;
6079
+ if (since >= this.updateThrottleMs) {
6080
+ schedule();
6081
+ return;
6082
+ }
6083
+ if (this.appendFlushThrottleTimer != null) return;
6084
+ const wait = this.updateThrottleMs - since;
6085
+ this.appendFlushThrottleTimer = setTimeout(() => {
6086
+ this.appendFlushThrottleTimer = null;
6087
+ schedule();
6088
+ }, wait);
6089
+ }
5987
6090
  applyMinimalEdit(prev, next) {
5988
6091
  if (!this.editorView) return;
5989
6092
  const model = this.editorView.getModel();
@@ -6024,6 +6127,7 @@ var EditorManager = class {
6024
6127
  if (!this.editorView) return;
6025
6128
  if (this.appendBuffer.length === 0) return;
6026
6129
  this.appendBufferScheduled = false;
6130
+ this.lastAppendFlushTime = Date.now();
6027
6131
  const model = this.editorView.getModel();
6028
6132
  if (!model) {
6029
6133
  this.appendBuffer.length = 0;
@@ -6078,6 +6182,11 @@ var EditorManager = class {
6078
6182
  this.updateThrottleTimer = null;
6079
6183
  this.rafScheduler.schedule("update", () => this.flushPendingUpdate());
6080
6184
  }
6185
+ if (!this.updateThrottleMs && this.appendFlushThrottleTimer != null) {
6186
+ clearTimeout(this.appendFlushThrottleTimer);
6187
+ this.appendFlushThrottleTimer = null;
6188
+ this.rafScheduler.schedule("append", () => this.flushAppendBuffer());
6189
+ }
6081
6190
  }
6082
6191
  getUpdateThrottleMs() {
6083
6192
  return this.updateThrottleMs;
@@ -6154,6 +6263,8 @@ function arraysEqual(a, b) {
6154
6263
  const LEGACY_ONIG_INIT_KEY = "__streamMonacoLegacyOnigurumaInit__";
6155
6264
  const LEGACY_ENGINE_KEY = "__streamMonacoLegacyShikiEngine__";
6156
6265
  const LEGACY_MONACO_LANGS_INIT_KEY = "__streamMonacoLegacyMonacoLangsInit__";
6266
+ const PERF_HOOKS_ENABLED_KEY = "__STREAM_MONACO_ENABLE_INTERNAL_PERF_HOOKS__";
6267
+ let instrumentedHighlighterCache = /* @__PURE__ */ new WeakMap();
6157
6268
  async function awaitLegacyOnigurumaInitIfPresent() {
6158
6269
  try {
6159
6270
  var _globalThis;
@@ -6204,9 +6315,109 @@ let lastPatchedHighlighter = null;
6204
6315
  let lastPatchedLanguages = /* @__PURE__ */ new Set();
6205
6316
  const monacoThemeByKey = /* @__PURE__ */ new Map();
6206
6317
  const monacoLanguageSet = /* @__PURE__ */ new Set();
6318
+ function nowMs() {
6319
+ return typeof performance !== "undefined" && typeof performance.now === "function" ? performance.now() : Date.now();
6320
+ }
6321
+ function isPerfHooksEnabled() {
6322
+ try {
6323
+ var _globalThis4;
6324
+ return typeof globalThis !== "undefined" && ((_globalThis4 = globalThis) === null || _globalThis4 === void 0 ? void 0 : _globalThis4[PERF_HOOKS_ENABLED_KEY]) === true;
6325
+ } catch {
6326
+ return false;
6327
+ }
6328
+ }
6329
+ function getPerfHook(name) {
6330
+ if (!isPerfHooksEnabled()) return null;
6331
+ try {
6332
+ var _STREAM_MONACO_PERF__;
6333
+ if (typeof globalThis === "undefined") return null;
6334
+ const hook = (_STREAM_MONACO_PERF__ = globalThis.__STREAM_MONACO_PERF__) === null || _STREAM_MONACO_PERF__ === void 0 ? void 0 : _STREAM_MONACO_PERF__[name];
6335
+ return typeof hook === "function" ? hook : null;
6336
+ } catch {
6337
+ return null;
6338
+ }
6339
+ }
6340
+ function getTokenizationPerfHook() {
6341
+ return getPerfHook("recordTokenize");
6342
+ }
6343
+ function getGrammarTokenizationPerfHook() {
6344
+ return getPerfHook("recordGrammarTokenize");
6345
+ }
6346
+ function getThemeRegistrationPerfHook() {
6347
+ return getPerfHook("recordThemeRegistration");
6348
+ }
6349
+ function recordTokenize(hook, language, durationMs, line, tokenCount, failed) {
6350
+ if (!hook) return;
6351
+ try {
6352
+ hook({
6353
+ language,
6354
+ durationMs,
6355
+ lineLength: line.length,
6356
+ lineSample: line.slice(0, 120),
6357
+ tokenCount,
6358
+ failed
6359
+ });
6360
+ } catch {}
6361
+ }
6362
+ function recordGrammarTokenize(language, durationMs, line, stoppedEarly, tokenCount) {
6363
+ const hook = getGrammarTokenizationPerfHook();
6364
+ if (!hook) return;
6365
+ try {
6366
+ hook({
6367
+ language,
6368
+ durationMs,
6369
+ lineLength: line.length,
6370
+ lineSample: line.slice(0, 120),
6371
+ stoppedEarly,
6372
+ tokenCount
6373
+ });
6374
+ } catch {}
6375
+ }
6376
+ function recordThemeRegistration(event) {
6377
+ const hook = getThemeRegistrationPerfHook();
6378
+ if (!hook) return;
6379
+ try {
6380
+ hook(event);
6381
+ } catch {}
6382
+ }
6383
+ function getProxyMember(target, prop) {
6384
+ const value = Reflect.get(target, prop, target);
6385
+ return typeof value === "function" ? value.bind(target) : value;
6386
+ }
6207
6387
  function themeKey(t) {
6208
6388
  return typeof t === "string" ? t : t.name ?? JSON.stringify(t);
6209
6389
  }
6390
+ function maybeInstrumentHighlighterGrammar(highlighter) {
6391
+ if (!getGrammarTokenizationPerfHook()) return highlighter;
6392
+ if (!highlighter || typeof highlighter !== "object" && typeof highlighter !== "function") return highlighter;
6393
+ const cached = instrumentedHighlighterCache.get(highlighter);
6394
+ if (cached) return cached;
6395
+ const grammarProxyCache = /* @__PURE__ */ new WeakMap();
6396
+ const instrumentedHighlighter = new Proxy(highlighter, { get(target, prop, _receiver) {
6397
+ if (prop !== "getLanguage") return getProxyMember(target, prop);
6398
+ return (language) => {
6399
+ const grammar = target.getLanguage(language);
6400
+ if (!grammar || typeof grammar !== "object" || typeof grammar.tokenizeLine2 !== "function") return grammar;
6401
+ const cachedGrammar = grammarProxyCache.get(grammar);
6402
+ if (cachedGrammar) return cachedGrammar;
6403
+ const instrumentedGrammar = new Proxy(grammar, { get(grammarTarget, grammarProp, _grammarReceiver) {
6404
+ if (grammarProp !== "tokenizeLine2") return getProxyMember(grammarTarget, grammarProp);
6405
+ const originalTokenizeLine2 = grammarTarget.tokenizeLine2.bind(grammarTarget);
6406
+ return (line, ruleStack, timeLimit) => {
6407
+ var _result$tokens;
6408
+ const startedAt = nowMs();
6409
+ const result = originalTokenizeLine2(line, ruleStack, timeLimit);
6410
+ recordGrammarTokenize(language, nowMs() - startedAt, line, !!(result === null || result === void 0 ? void 0 : result.stoppedEarly), typeof (result === null || result === void 0 || (_result$tokens = result.tokens) === null || _result$tokens === void 0 ? void 0 : _result$tokens.length) === "number" ? result.tokens.length / 2 : 0);
6411
+ return result;
6412
+ };
6413
+ } });
6414
+ grammarProxyCache.set(grammar, instrumentedGrammar);
6415
+ return instrumentedGrammar;
6416
+ };
6417
+ } });
6418
+ instrumentedHighlighterCache.set(highlighter, instrumentedHighlighter);
6419
+ return instrumentedHighlighter;
6420
+ }
6210
6421
  async function ensureMonacoHighlighter(themes, languages$1) {
6211
6422
  for (const t of themes) monacoThemeByKey.set(themeKey(t), t);
6212
6423
  for (const l of languages$1) monacoLanguageSet.add(l);
@@ -6216,7 +6427,11 @@ async function ensureMonacoHighlighter(themes, languages$1) {
6216
6427
  monacoHighlighterPromise = createHighlighterWithLegacyEngineIfNeeded({
6217
6428
  themes: initialThemes,
6218
6429
  langs: initialLangs
6219
- }).then((h$1) => h$1);
6430
+ }).then((h$1) => {
6431
+ h$1.__streamMonacoLoadedThemes = new Set(initialThemes.map((t) => themeKey(t)));
6432
+ h$1.__streamMonacoLoadedLangs = new Set(initialLangs);
6433
+ return h$1;
6434
+ });
6220
6435
  }
6221
6436
  const h = await monacoHighlighterPromise;
6222
6437
  const wantsThemes = Array.from(monacoThemeByKey.values());
@@ -6244,7 +6459,11 @@ async function ensureMonacoHighlighter(themes, languages$1) {
6244
6459
  const p = createHighlighterWithLegacyEngineIfNeeded({
6245
6460
  themes: wantsThemes,
6246
6461
  langs: wantsLangs
6247
- }).then((hh) => hh);
6462
+ }).then((hh) => {
6463
+ hh.__streamMonacoLoadedThemes = new Set(wantsThemes.map((t) => themeKey(t)));
6464
+ hh.__streamMonacoLoadedLangs = new Set(wantsLangs);
6465
+ return hh;
6466
+ });
6248
6467
  monacoHighlighterPromise = p;
6249
6468
  return p;
6250
6469
  }
@@ -6263,6 +6482,7 @@ function clearHighlighterCache() {
6263
6482
  monacoThemeByKey.clear();
6264
6483
  monacoLanguageSet.clear();
6265
6484
  themeRegisterPromise = null;
6485
+ instrumentedHighlighterCache = /* @__PURE__ */ new WeakMap();
6266
6486
  languagesRegistered = false;
6267
6487
  currentLanguages = [];
6268
6488
  }
@@ -6329,9 +6549,15 @@ async function getOrCreateHighlighter(themes, languages$1) {
6329
6549
  */
6330
6550
  async function registerMonacoThemes(themes, languages$1) {
6331
6551
  return enqueueRegistration(async () => {
6552
+ const registrationStartedAt = nowMs();
6553
+ let ensureHighlighterMs = 0;
6554
+ let patchMonacoMs = 0;
6555
+ let patchedMonaco = false;
6332
6556
  registerMonacoLanguages(languages$1);
6333
6557
  const p = (async () => {
6558
+ const ensureHighlighterStartedAt = nowMs();
6334
6559
  const highlighter = await ensureMonacoHighlighter(themes, languages$1);
6560
+ ensureHighlighterMs = nowMs() - ensureHighlighterStartedAt;
6335
6561
  const wantsLangs = Array.from(monacoLanguageSet.values());
6336
6562
  const needsLanguagePatch = lastPatchedHighlighter !== highlighter || wantsLangs.some((l) => !lastPatchedLanguages.has(l));
6337
6563
  if (needsLanguagePatch) {
@@ -6352,9 +6578,17 @@ async function registerMonacoThemes(themes, languages$1) {
6352
6578
  provider = {
6353
6579
  ...provider,
6354
6580
  tokenize(line, state) {
6581
+ const hook = getTokenizationPerfHook();
6582
+ const startedAt = hook ? nowMs() : 0;
6583
+ let tokenCount = 0;
6584
+ let failed = false;
6355
6585
  try {
6356
- return originalTokenize(line, state);
6586
+ const result = originalTokenize(line, state);
6587
+ tokenCount = Array.isArray(result === null || result === void 0 ? void 0 : result.tokens) ? result.tokens.length : 0;
6588
+ return result;
6357
6589
  } catch {
6590
+ failed = true;
6591
+ tokenCount = 1;
6358
6592
  return {
6359
6593
  endState: state,
6360
6594
  tokens: [{
@@ -6362,6 +6596,8 @@ async function registerMonacoThemes(themes, languages$1) {
6362
6596
  scopes: ""
6363
6597
  }]
6364
6598
  };
6599
+ } finally {
6600
+ if (hook) recordTokenize(hook, lang, nowMs() - startedAt, line, tokenCount, failed);
6365
6601
  }
6366
6602
  }
6367
6603
  };
@@ -6370,7 +6606,10 @@ async function registerMonacoThemes(themes, languages$1) {
6370
6606
  }
6371
6607
  }
6372
6608
  };
6373
- (0, __shikijs_monaco.shikiToMonaco)(highlighter, monacoProxy);
6609
+ const patchMonacoStartedAt = nowMs();
6610
+ (0, __shikijs_monaco.shikiToMonaco)(maybeInstrumentHighlighterGrammar(highlighter), monacoProxy);
6611
+ patchMonacoMs = nowMs() - patchMonacoStartedAt;
6612
+ patchedMonaco = true;
6374
6613
  lastPatchedHighlighter = highlighter;
6375
6614
  lastPatchedLanguages = new Set(wantsLangs);
6376
6615
  }
@@ -6380,6 +6619,14 @@ async function registerMonacoThemes(themes, languages$1) {
6380
6619
  setThemeRegisterPromise(p);
6381
6620
  try {
6382
6621
  const res = await p;
6622
+ recordThemeRegistration({
6623
+ durationMs: nowMs() - registrationStartedAt,
6624
+ ensureHighlighterMs,
6625
+ patchMonacoMs,
6626
+ themes: themes.length,
6627
+ languages: languages$1.length,
6628
+ patchedMonaco
6629
+ });
6383
6630
  return res;
6384
6631
  } catch (e) {
6385
6632
  setThemeRegisterPromise(null);
@@ -6513,7 +6760,8 @@ function useMonaco(monacoOptions = {}) {
6513
6760
  let modifiedModel = null;
6514
6761
  const themes = monacoOptions.themes && ((_monacoOptions$themes = monacoOptions.themes) === null || _monacoOptions$themes === void 0 ? void 0 : _monacoOptions$themes.length) ? monacoOptions.themes : defaultThemes;
6515
6762
  if (!Array.isArray(themes) || themes.length < 2) throw new Error("Monaco themes must be an array with at least two themes: [darkTheme, lightTheme]");
6516
- const languages$1 = monacoOptions.languages ?? defaultLanguages;
6763
+ const explicitLanguages = monacoOptions.languages;
6764
+ const languages$1 = explicitLanguages ?? defaultLanguages;
6517
6765
  const MAX_HEIGHT = monacoOptions.MAX_HEIGHT ?? 500;
6518
6766
  const autoScrollOnUpdate = monacoOptions.autoScrollOnUpdate ?? true;
6519
6767
  const autoScrollInitial = monacoOptions.autoScrollInitial ?? true;
@@ -6602,10 +6850,27 @@ function useMonaco(monacoOptions = {}) {
6602
6850
  console.warn("onThemeChange callback threw an error:", err);
6603
6851
  }
6604
6852
  }
6605
- async function ensureThemeRegistered(themeName) {
6853
+ function normalizeLanguage(language) {
6854
+ if (!language) return null;
6855
+ return processedLanguage(language) || language;
6856
+ }
6857
+ function resolveCreateLanguages(primaryLanguage) {
6858
+ const primary = normalizeLanguage(primaryLanguage);
6859
+ if (Array.isArray(explicitLanguages) && explicitLanguages.length) {
6860
+ const set = /* @__PURE__ */ new Set();
6861
+ for (const language of explicitLanguages) {
6862
+ const normalized = normalizeLanguage(language);
6863
+ if (normalized) set.add(normalized);
6864
+ }
6865
+ if (primary) set.add(primary);
6866
+ return Array.from(set);
6867
+ }
6868
+ return primary ? [primary] : ["typescript"];
6869
+ }
6870
+ async function ensureThemeRegistered(themeName, requestedLanguages = languages$1) {
6606
6871
  const availableNames = themes.map((t) => typeof t === "string" ? t : t.name);
6607
6872
  const list = availableNames.includes(themeName) ? themes : themes.concat(themeName);
6608
- await registerMonacoThemes(list, languages$1);
6873
+ await registerMonacoThemes(list, requestedLanguages);
6609
6874
  }
6610
6875
  function resolveRequestedThemeName() {
6611
6876
  return requestedThemeName ?? globalRequestedThemeName ?? monacoOptions.theme ?? currentTheme.value;
@@ -6682,11 +6947,12 @@ function useMonaco(monacoOptions = {}) {
6682
6947
  queuedEditorUpdateDuringCreate = null;
6683
6948
  disposeAllPendingCreateDisposables();
6684
6949
  }
6685
- async function resolveCreateThemeName(requestId, kind) {
6950
+ async function resolveCreateThemeName(requestId, kind, primaryLanguage) {
6686
6951
  let themeName = resolveRequestedThemeName();
6952
+ const createLanguages = resolveCreateLanguages(primaryLanguage);
6687
6953
  while (true) {
6688
6954
  assertCreateStillActive(requestId, kind);
6689
- await ensureThemeRegistered(themeName);
6955
+ await ensureThemeRegistered(themeName, createLanguages);
6690
6956
  assertCreateStillActive(requestId, kind);
6691
6957
  const latestThemeName = resolveRequestedThemeName();
6692
6958
  if (latestThemeName === themeName) return themeName;
@@ -6705,7 +6971,7 @@ function useMonaco(monacoOptions = {}) {
6705
6971
  if (requestDisposables.length) pendingCreateDisposables.set(requestId, requestDisposables);
6706
6972
  let nextEditorMgr = null;
6707
6973
  try {
6708
- const initialThemeName = await resolveCreateThemeName(requestId, "editor");
6974
+ const initialThemeName = await resolveCreateThemeName(requestId, "editor", language);
6709
6975
  nextEditorMgr = new EditorManager(monacoOptions, maxHeightValue, maxHeightCSS, autoScrollOnUpdate, autoScrollInitial, autoScrollThresholdPx, autoScrollThresholdLines, monacoOptions.revealDebounceMs, monacoOptions.updateThrottleMs);
6710
6976
  const nextEditorView = await nextEditorMgr.createEditor(container, code, language, initialThemeName);
6711
6977
  assertCreateStillActive(requestId, "editor");
@@ -6752,7 +7018,7 @@ function useMonaco(monacoOptions = {}) {
6752
7018
  if (requestDisposables.length) pendingCreateDisposables.set(requestId, requestDisposables);
6753
7019
  let nextDiffMgr = null;
6754
7020
  try {
6755
- const initialThemeName = await resolveCreateThemeName(requestId, "diff");
7021
+ const initialThemeName = await resolveCreateThemeName(requestId, "diff", language);
6756
7022
  nextDiffMgr = new DiffEditorManager(monacoOptions, maxHeightValue, maxHeightCSS, autoScrollOnUpdate, autoScrollInitial, autoScrollThresholdPx, autoScrollThresholdLines, diffAutoScroll, monacoOptions.revealDebounceMs, monacoOptions.diffUpdateThrottleMs);
6757
7023
  const nextDiffEditorView = await nextDiffMgr.createDiffEditor(container, originalCode, modifiedCode, language, initialThemeName);
6758
7024
  assertCreateStillActive(requestId, "diff");