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.
@@ -522,6 +522,14 @@ function createScrollWatcherForEditor(ed, opts) {
522
522
  return api;
523
523
  }
524
524
 
525
+ //#endregion
526
+ //#region src/utils/textChunks.ts
527
+ function countLineBreaks(text) {
528
+ let count = 0;
529
+ for (let i = 0; i < text.length; i++) if (text.charCodeAt(i) === 10) count += 1;
530
+ return count;
531
+ }
532
+
525
533
  //#endregion
526
534
  //#region src/core/diffAppearance.ts
527
535
  function parseCssColorRgb(color) {
@@ -1748,6 +1756,23 @@ var DiffEditorManager = class DiffEditorManager {
1748
1756
  if (typeof direct === "function") return direct.call(model, lineNumber);
1749
1757
  return model.getValue().split(/\r?\n/)[lineNumber - 1] ?? "";
1750
1758
  }
1759
+ colorizeFallbackInlineDeletedLine(lineNode, model, lineText, tabSize) {
1760
+ var _model$getLanguageId;
1761
+ const language = (_model$getLanguageId = model.getLanguageId) === null || _model$getLanguageId === void 0 ? void 0 : _model$getLanguageId.call(model);
1762
+ const colorize = monaco_shim_exports.editor.colorize;
1763
+ if (!language || typeof colorize !== "function") return;
1764
+ const signature = `${language}:${lineText}`;
1765
+ lineNode.dataset.streamMonacoColorizeSignature = signature;
1766
+ colorize(lineText, language, { tabSize }).then((html) => {
1767
+ if (lineNode.dataset.streamMonacoColorizeSignature !== signature) return;
1768
+ lineNode.innerHTML = html;
1769
+ }).catch(() => {});
1770
+ }
1771
+ getModelTabSize(model) {
1772
+ var _model$getOptions;
1773
+ const tabSize = (_model$getOptions = model.getOptions) === null || _model$getOptions === void 0 ? void 0 : _model$getOptions.call(model).tabSize;
1774
+ return typeof tabSize === "number" && Number.isFinite(tabSize) ? tabSize : void 0;
1775
+ }
1751
1776
  hasVisibleNativeInlineDeleteNodes() {
1752
1777
  if (!this.lastContainer) return false;
1753
1778
  const querySelectorAll = typeof this.lastContainer.querySelectorAll === "function" ? this.lastContainer.querySelectorAll.bind(this.lastContainer) : null;
@@ -1786,6 +1811,7 @@ var DiffEditorManager = class DiffEditorManager {
1786
1811
  }
1787
1812
  const lineHeightOption = (_EditorOption = monaco_shim_exports.editor.EditorOption) === null || _EditorOption === void 0 ? void 0 : _EditorOption.lineHeight;
1788
1813
  const lineHeight = ((_modifiedEditor$getOp = modifiedEditor.getOption) === null || _modifiedEditor$getOp === void 0 ? void 0 : _modifiedEditor$getOp.call(modifiedEditor, lineHeightOption)) ?? 20;
1814
+ const originalTabSize = this.getModelTabSize(originalModel);
1789
1815
  const relevantChanges = lineChanges.filter((change) => hasOriginalLines(change));
1790
1816
  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) => {
1791
1817
  return node instanceof HTMLElement && !!node.querySelector(".view-lines.line-delete");
@@ -1830,12 +1856,14 @@ var DiffEditorManager = class DiffEditorManager {
1830
1856
  domNode.setAttribute("data-stream-monaco-native-wrapper", "true");
1831
1857
  (_modifiedEditor$apply = modifiedEditor.applyFontInfo) === null || _modifiedEditor$apply === void 0 || _modifiedEditor$apply.call(modifiedEditor, domNode);
1832
1858
  for (let line = change.originalStartLineNumber; line <= change.originalEndLineNumber; line++) {
1859
+ const lineText = this.readModelLineContent(originalModel, line);
1833
1860
  const lineNode = document.createElement("div");
1834
1861
  lineNode.className = "stream-monaco-fallback-inline-delete-line";
1835
- lineNode.textContent = this.readModelLineContent(originalModel, line);
1862
+ lineNode.textContent = lineText;
1836
1863
  lineNode.style.height = `${lineHeight}px`;
1837
1864
  lineNode.style.lineHeight = `${lineHeight}px`;
1838
1865
  domNode.append(lineNode);
1866
+ this.colorizeFallbackInlineDeletedLine(lineNode, originalModel, lineText, originalTabSize);
1839
1867
  }
1840
1868
  pair.viewWrapper.append(domNode);
1841
1869
  if (pair.marginWrapper) {
@@ -1862,12 +1890,14 @@ var DiffEditorManager = class DiffEditorManager {
1862
1890
  domNode.setAttribute("aria-hidden", "true");
1863
1891
  (_modifiedEditor$apply3 = modifiedEditor.applyFontInfo) === null || _modifiedEditor$apply3 === void 0 || _modifiedEditor$apply3.call(modifiedEditor, domNode);
1864
1892
  for (let line = change.originalStartLineNumber; line <= change.originalEndLineNumber; line++) {
1893
+ const lineText = this.readModelLineContent(originalModel, line);
1865
1894
  const lineNode = document.createElement("div");
1866
1895
  lineNode.className = "stream-monaco-fallback-inline-delete-line";
1867
- lineNode.textContent = this.readModelLineContent(originalModel, line);
1896
+ lineNode.textContent = lineText;
1868
1897
  lineNode.style.height = `${lineHeight}px`;
1869
1898
  lineNode.style.lineHeight = `${lineHeight}px`;
1870
1899
  domNode.append(lineNode);
1900
+ this.colorizeFallbackInlineDeletedLine(lineNode, originalModel, lineText, originalTabSize);
1871
1901
  }
1872
1902
  const marginDomNode = document.createElement("div");
1873
1903
  marginDomNode.className = "stream-monaco-fallback-inline-delete-margin";
@@ -4426,9 +4456,10 @@ var DiffEditorManager = class DiffEditorManager {
4426
4456
  shouldAutoScrollDiff: this.shouldAutoScrollDiff
4427
4457
  });
4428
4458
  if (!this.diffEditorView) return;
4459
+ if (!(this.diffAutoScroll && this.autoScrollOnUpdate && this.shouldAutoScrollDiff)) return;
4429
4460
  const hasV = this.hasVerticalScrollbarModified();
4430
4461
  log("diff", "hasVerticalScrollbarModified ->", hasV);
4431
- if (!(this.diffAutoScroll && this.autoScrollOnUpdate && this.shouldAutoScrollDiff && hasV)) return;
4462
+ if (!hasV) return;
4432
4463
  const me = this.diffEditorView.getModifiedEditor();
4433
4464
  const model = me.getModel();
4434
4465
  const currentLine = (model === null || model === void 0 ? void 0 : model.getLineCount()) ?? 1;
@@ -4650,7 +4681,7 @@ var DiffEditorManager = class DiffEditorManager {
4650
4681
  this.diffComputedVersions = null;
4651
4682
  this.diffPresentationDisposables.push(this.diffEditorView.onDidUpdateDiff(() => {
4652
4683
  this.diffComputedVersions = this.captureCurrentDiffVersions();
4653
- this.syncDiffEditorLayoutToContainer();
4684
+ this.scheduleSyncDiffEditorLayoutToContainer();
4654
4685
  this.scheduleSyncDiffPresentationDecorations();
4655
4686
  }));
4656
4687
  this.diffPresentationDisposables.push(oEditor.onDidChangeModelContent(() => {
@@ -4815,6 +4846,7 @@ var DiffEditorManager = class DiffEditorManager {
4815
4846
  }
4816
4847
  updateModified(newCode, codeLanguage) {
4817
4848
  if (!this.diffEditorView || !this.modifiedModel) return;
4849
+ this.syncLastKnownModified();
4818
4850
  if (codeLanguage) {
4819
4851
  const lang = processedLanguage(codeLanguage);
4820
4852
  if (lang && this.modifiedModel.getLanguageId() !== lang) monaco_shim_exports.editor.setModelLanguage(this.modifiedModel, lang);
@@ -4827,7 +4859,7 @@ var DiffEditorManager = class DiffEditorManager {
4827
4859
  if (tailAppend) this.appendModified(newCode.slice(prev.length), codeLanguage);
4828
4860
  else {
4829
4861
  this.flushModifiedAppendBufferSync();
4830
- const prevAfterFlush = this.modifiedModel.getValue();
4862
+ const prevAfterFlush = this.lastKnownModifiedCode ?? this.modifiedModel.getValue();
4831
4863
  const prevLine = this.modifiedModel.getLineCount();
4832
4864
  this.applyMinimalEditToModel(this.modifiedModel, prevAfterFlush, newCode);
4833
4865
  const newLine = this.modifiedModel.getLineCount();
@@ -5077,6 +5109,7 @@ var DiffEditorManager = class DiffEditorManager {
5077
5109
  }
5078
5110
  const { original, modified, lang } = this.pendingDiffUpdate;
5079
5111
  this.pendingDiffUpdate = null;
5112
+ this.syncLastKnownModified();
5080
5113
  this.flushOriginalAppendBufferSync();
5081
5114
  this.flushModifiedAppendBufferSync();
5082
5115
  if (lang) {
@@ -5097,7 +5130,7 @@ var DiffEditorManager = class DiffEditorManager {
5097
5130
  else this.applyMinimalEditToModel(o, prevO, original);
5098
5131
  this.lastKnownOriginalCode = original;
5099
5132
  }
5100
- const prevM = m.getValue();
5133
+ const prevM = this.lastKnownModifiedCode;
5101
5134
  const prevMLineCount = m.getLineCount();
5102
5135
  const modifiedTailAppend = prevM !== modified && modified.startsWith(prevM) && prevM.length < modified.length;
5103
5136
  const hasContentChange = prevO !== original || prevM !== modified;
@@ -5138,6 +5171,33 @@ var DiffEditorManager = class DiffEditorManager {
5138
5171
  this.preserveNativeDiffDecorationsOnStaleAppend = true;
5139
5172
  this.appendToModel(this.modifiedModel, text);
5140
5173
  }
5174
+ splitAppendTextForProgressiveFlush(text, maxChunkChars = 12e3, maxChunkLines = 200) {
5175
+ if (!text || text.length <= maxChunkChars) return [text];
5176
+ const chunks = [];
5177
+ let start = 0;
5178
+ let lineCount = 0;
5179
+ let lastSafeEnd = 0;
5180
+ for (let i = 0; i < text.length; i++) {
5181
+ if (text.charCodeAt(i) === 10) {
5182
+ lineCount += 1;
5183
+ lastSafeEnd = i + 1;
5184
+ }
5185
+ if (i - start + 1 < maxChunkChars && lineCount < maxChunkLines) continue;
5186
+ let end = lastSafeEnd > start ? lastSafeEnd : i + 1;
5187
+ if (end < text.length) {
5188
+ const prev = text.charCodeAt(end - 1);
5189
+ const next = text.charCodeAt(end);
5190
+ if (prev >= 55296 && prev <= 56319 && next >= 56320 && next <= 57343) end += 1;
5191
+ }
5192
+ chunks.push(text.slice(start, end));
5193
+ start = end;
5194
+ i = end - 1;
5195
+ lineCount = 0;
5196
+ lastSafeEnd = start;
5197
+ }
5198
+ if (start < text.length) chunks.push(text.slice(start));
5199
+ return chunks.length ? chunks : [text];
5200
+ }
5141
5201
  async flushAppendBufferDiff() {
5142
5202
  if (!this.diffEditorView) return;
5143
5203
  if (this.appendBufferOriginalDiff.length === 0 && this.appendBufferModifiedDiff.length === 0) return;
@@ -5158,17 +5218,16 @@ var DiffEditorManager = class DiffEditorManager {
5158
5218
  return;
5159
5219
  }
5160
5220
  let parts = this.appendBufferModifiedDiff.splice(0);
5221
+ if (parts.length === 0) {
5222
+ this.eagerlyGrowDiffContainerHeight();
5223
+ return;
5224
+ }
5161
5225
  const prevLineInit = model.getLineCount();
5162
5226
  const totalText = parts.join("");
5163
5227
  const totalChars = totalText.length;
5164
- if (parts.length === 1 && totalChars > 5e3) {
5165
- const lines = totalText.split(/\r?\n/);
5166
- const chunkSize = 200;
5167
- const chunks = [];
5168
- for (let i = 0; i < lines.length; i += chunkSize) chunks.push(`${lines.slice(i, i + chunkSize).join("\n")}\n`);
5169
- if (chunks.length > 1) parts = chunks;
5170
- }
5171
- const applyChunked = parts.length > 1 && (totalChars > 2e3 || model.getLineCount && model.getLineCount() + 0 - prevLineInit > 50);
5228
+ const totalLineBreaks = countLineBreaks(totalText);
5229
+ if (parts.length === 1 && totalChars > 5e3) parts = this.splitAppendTextForProgressiveFlush(totalText);
5230
+ const applyChunked = parts.length > 1 && (totalChars > 2e3 || totalLineBreaks > 50);
5172
5231
  log("diff", "flushAppendBufferDiff start", {
5173
5232
  partsCount: parts.length,
5174
5233
  totalChars,
@@ -5187,6 +5246,8 @@ var DiffEditorManager = class DiffEditorManager {
5187
5246
  } catch {}
5188
5247
  if (applyChunked) {
5189
5248
  log("diff", "flushAppendBufferDiff applying chunked", { partsLen: parts.length });
5249
+ if (this.lastKnownModifiedCode == null) this.lastKnownModifiedCode = model.getValue();
5250
+ let currentLength = this.lastKnownModifiedCode.length;
5190
5251
  let idx = 0;
5191
5252
  for (const part of parts) {
5192
5253
  if (!part) continue;
@@ -5196,17 +5257,9 @@ var DiffEditorManager = class DiffEditorManager {
5196
5257
  partLen: part.length,
5197
5258
  prevLine
5198
5259
  });
5199
- const lastColumn$1 = model.getLineMaxColumn(prevLine);
5200
- const range$1 = new monaco_shim_exports.Range(prevLine, lastColumn$1, prevLine, lastColumn$1);
5201
5260
  this.preserveNativeDiffDecorationsOnStaleAppend = true;
5202
- this.runAsProgrammaticModifiedContentChange(() => {
5203
- model.applyEdits([{
5204
- range: range$1,
5205
- text: part,
5206
- forceMoveMarkers: true
5207
- }]);
5208
- });
5209
- this.lastKnownModifiedCode = model.getValue();
5261
+ this.appendToModel(model, part, currentLength);
5262
+ currentLength += part.length;
5210
5263
  const newLine$1 = model.getLineCount();
5211
5264
  this.lastKnownModifiedLineCount = newLine$1;
5212
5265
  await new Promise((resolve) => typeof requestAnimationFrame !== "undefined" ? requestAnimationFrame(resolve) : setTimeout(resolve, 0));
@@ -5232,23 +5285,15 @@ var DiffEditorManager = class DiffEditorManager {
5232
5285
  newLine: newLine$1
5233
5286
  });
5234
5287
  }
5288
+ this.lastKnownModifiedCode = model.getValue();
5235
5289
  if (suppressedByFlush) watcherApi.setSuppressed(false);
5236
5290
  return;
5237
5291
  }
5238
5292
  const text = totalText;
5239
5293
  this.appendBufferModifiedDiff.length = 0;
5240
5294
  prevLine = model.getLineCount();
5241
- const lastColumn = model.getLineMaxColumn(prevLine);
5242
- const range = new monaco_shim_exports.Range(prevLine, lastColumn, prevLine, lastColumn);
5243
5295
  this.preserveNativeDiffDecorationsOnStaleAppend = true;
5244
- this.runAsProgrammaticModifiedContentChange(() => {
5245
- model.applyEdits([{
5246
- range,
5247
- text,
5248
- forceMoveMarkers: true
5249
- }]);
5250
- });
5251
- this.lastKnownModifiedCode = model.getValue();
5296
+ this.appendToModel(model, text);
5252
5297
  const newLine = model.getLineCount();
5253
5298
  this.lastKnownModifiedLineCount = newLine;
5254
5299
  this.eagerlyGrowDiffContainerHeight();
@@ -5291,8 +5336,30 @@ var DiffEditorManager = class DiffEditorManager {
5291
5336
  });
5292
5337
  if (model === this.modifiedModel) this.lastKnownModifiedLineCount = model.getLineCount();
5293
5338
  }
5294
- appendToModel(model, appendText) {
5339
+ getModelValueLength(model) {
5340
+ const getValueLength = model.getValueLength;
5341
+ if (typeof getValueLength === "function") try {
5342
+ return getValueLength.call(model);
5343
+ } catch {}
5344
+ return model.getValue().length;
5345
+ }
5346
+ mergeKnownAppend(known, appendText, previousLength, model) {
5347
+ if (known == null) return model.getValue();
5348
+ const nextLength = previousLength + appendText.length;
5349
+ if (known.length === previousLength) return known + appendText;
5350
+ if (known.length >= nextLength && known.slice(previousLength, nextLength) === appendText) return known;
5351
+ return model.getValue();
5352
+ }
5353
+ syncKnownCodeAfterAppend(model, appendText, previousLength) {
5354
+ if (model === this.originalModel) {
5355
+ this.lastKnownOriginalCode = this.mergeKnownAppend(this.lastKnownOriginalCode, appendText, previousLength, model);
5356
+ return;
5357
+ }
5358
+ if (model === this.modifiedModel) this.lastKnownModifiedCode = this.mergeKnownAppend(this.lastKnownModifiedCode, appendText, previousLength, model);
5359
+ }
5360
+ appendToModel(model, appendText, knownLength) {
5295
5361
  if (!appendText) return;
5362
+ const previousLength = knownLength != null ? knownLength : this.getModelValueLength(model);
5296
5363
  const lastLine = model.getLineCount();
5297
5364
  const lastColumn = model.getLineMaxColumn(lastLine);
5298
5365
  const range = new monaco_shim_exports.Range(lastLine, lastColumn, lastLine, lastColumn);
@@ -5304,6 +5371,7 @@ var DiffEditorManager = class DiffEditorManager {
5304
5371
  }]);
5305
5372
  });
5306
5373
  if (model === this.modifiedModel) this.lastKnownModifiedLineCount = model.getLineCount();
5374
+ this.syncKnownCodeAfterAppend(model, appendText, previousLength);
5307
5375
  }
5308
5376
  applyModelEdit(model, fn) {
5309
5377
  if (model === this.modifiedModel) {
@@ -5341,6 +5409,8 @@ var EditorManager = class {
5341
5409
  minimalEditMaxChangeRatioValue = minimalEditMaxChangeRatio;
5342
5410
  lastUpdateFlushTime = 0;
5343
5411
  updateThrottleTimer = null;
5412
+ lastAppendFlushTime = 0;
5413
+ appendFlushThrottleTimer = null;
5344
5414
  shouldAutoScroll = true;
5345
5415
  scrollWatcher = null;
5346
5416
  scrollWatcherSuppressionTimer = null;
@@ -5440,6 +5510,10 @@ var EditorManager = class {
5440
5510
  clearTimeout(this.updateThrottleTimer);
5441
5511
  this.updateThrottleTimer = null;
5442
5512
  }
5513
+ if (this.appendFlushThrottleTimer != null) {
5514
+ clearTimeout(this.appendFlushThrottleTimer);
5515
+ this.appendFlushThrottleTimer = null;
5516
+ }
5443
5517
  }
5444
5518
  initDebugFlag() {
5445
5519
  if (typeof window !== "undefined" && window.__STREAM_MONACO_DEBUG__ !== void 0) {
@@ -5536,6 +5610,14 @@ var EditorManager = class {
5536
5610
  }
5537
5611
  maybeScrollToBottom(targetLine) {
5538
5612
  this.rafScheduler.schedule("maybe-scroll", () => {
5613
+ if (!(this.autoScrollOnUpdate && this.shouldAutoScroll)) {
5614
+ this.dlog("maybeScrollToBottom skipped (auto-scroll disabled)", {
5615
+ autoScrollOnUpdate: this.autoScrollOnUpdate,
5616
+ shouldAutoScroll: this.shouldAutoScroll,
5617
+ targetLine
5618
+ });
5619
+ return;
5620
+ }
5539
5621
  const hasVS = this.hasVerticalScrollbar();
5540
5622
  this.dlog("maybeScrollToBottom called", {
5541
5623
  autoScrollOnUpdate: this.autoScrollOnUpdate,
@@ -5543,8 +5625,8 @@ var EditorManager = class {
5543
5625
  hasVerticalScrollbar: hasVS,
5544
5626
  targetLine
5545
5627
  });
5546
- if (!(this.autoScrollOnUpdate && this.shouldAutoScroll && this.hasVerticalScrollbar())) {
5547
- this.dlog("maybeScrollToBottom skipped (auto-scroll conditions not met)");
5628
+ if (!hasVS) {
5629
+ this.dlog("maybeScrollToBottom skipped (no vertical scrollbar)");
5548
5630
  return;
5549
5631
  }
5550
5632
  const model = this.editorView.getModel();
@@ -5804,7 +5886,7 @@ var EditorManager = class {
5804
5886
  this.lastScrollTop = v;
5805
5887
  }
5806
5888
  });
5807
- this.maybeScrollToBottom();
5889
+ if (this.shouldAutoScroll) this.maybeScrollToBottom();
5808
5890
  return this.editorView;
5809
5891
  }
5810
5892
  syncLastKnownCode() {
@@ -5975,10 +6057,31 @@ var EditorManager = class {
5975
6057
  this.appendBuffer.push(appendText);
5976
6058
  if (!this.appendBufferScheduled) {
5977
6059
  this.appendBufferScheduled = true;
5978
- this.rafScheduler.schedule("append", () => this.flushAppendBuffer());
6060
+ this.scheduleFlushAppendBuffer();
5979
6061
  }
5980
6062
  }
5981
6063
  }
6064
+ scheduleFlushAppendBuffer() {
6065
+ const schedule = () => {
6066
+ this.rafScheduler.schedule("append", () => this.flushAppendBuffer());
6067
+ };
6068
+ if (!this.updateThrottleMs) {
6069
+ schedule();
6070
+ return;
6071
+ }
6072
+ const now = Date.now();
6073
+ const since = now - this.lastAppendFlushTime;
6074
+ if (since >= this.updateThrottleMs) {
6075
+ schedule();
6076
+ return;
6077
+ }
6078
+ if (this.appendFlushThrottleTimer != null) return;
6079
+ const wait = this.updateThrottleMs - since;
6080
+ this.appendFlushThrottleTimer = setTimeout(() => {
6081
+ this.appendFlushThrottleTimer = null;
6082
+ schedule();
6083
+ }, wait);
6084
+ }
5982
6085
  applyMinimalEdit(prev, next) {
5983
6086
  if (!this.editorView) return;
5984
6087
  const model = this.editorView.getModel();
@@ -6019,6 +6122,7 @@ var EditorManager = class {
6019
6122
  if (!this.editorView) return;
6020
6123
  if (this.appendBuffer.length === 0) return;
6021
6124
  this.appendBufferScheduled = false;
6125
+ this.lastAppendFlushTime = Date.now();
6022
6126
  const model = this.editorView.getModel();
6023
6127
  if (!model) {
6024
6128
  this.appendBuffer.length = 0;
@@ -6073,6 +6177,11 @@ var EditorManager = class {
6073
6177
  this.updateThrottleTimer = null;
6074
6178
  this.rafScheduler.schedule("update", () => this.flushPendingUpdate());
6075
6179
  }
6180
+ if (!this.updateThrottleMs && this.appendFlushThrottleTimer != null) {
6181
+ clearTimeout(this.appendFlushThrottleTimer);
6182
+ this.appendFlushThrottleTimer = null;
6183
+ this.rafScheduler.schedule("append", () => this.flushAppendBuffer());
6184
+ }
6076
6185
  }
6077
6186
  getUpdateThrottleMs() {
6078
6187
  return this.updateThrottleMs;
@@ -6149,6 +6258,8 @@ function arraysEqual(a, b) {
6149
6258
  const LEGACY_ONIG_INIT_KEY = "__streamMonacoLegacyOnigurumaInit__";
6150
6259
  const LEGACY_ENGINE_KEY = "__streamMonacoLegacyShikiEngine__";
6151
6260
  const LEGACY_MONACO_LANGS_INIT_KEY = "__streamMonacoLegacyMonacoLangsInit__";
6261
+ const PERF_HOOKS_ENABLED_KEY = "__STREAM_MONACO_ENABLE_INTERNAL_PERF_HOOKS__";
6262
+ let instrumentedHighlighterCache = /* @__PURE__ */ new WeakMap();
6152
6263
  async function awaitLegacyOnigurumaInitIfPresent() {
6153
6264
  try {
6154
6265
  var _globalThis;
@@ -6199,9 +6310,109 @@ let lastPatchedHighlighter = null;
6199
6310
  let lastPatchedLanguages = /* @__PURE__ */ new Set();
6200
6311
  const monacoThemeByKey = /* @__PURE__ */ new Map();
6201
6312
  const monacoLanguageSet = /* @__PURE__ */ new Set();
6313
+ function nowMs() {
6314
+ return typeof performance !== "undefined" && typeof performance.now === "function" ? performance.now() : Date.now();
6315
+ }
6316
+ function isPerfHooksEnabled() {
6317
+ try {
6318
+ var _globalThis4;
6319
+ return typeof globalThis !== "undefined" && ((_globalThis4 = globalThis) === null || _globalThis4 === void 0 ? void 0 : _globalThis4[PERF_HOOKS_ENABLED_KEY]) === true;
6320
+ } catch {
6321
+ return false;
6322
+ }
6323
+ }
6324
+ function getPerfHook(name) {
6325
+ if (!isPerfHooksEnabled()) return null;
6326
+ try {
6327
+ var _STREAM_MONACO_PERF__;
6328
+ if (typeof globalThis === "undefined") return null;
6329
+ const hook = (_STREAM_MONACO_PERF__ = globalThis.__STREAM_MONACO_PERF__) === null || _STREAM_MONACO_PERF__ === void 0 ? void 0 : _STREAM_MONACO_PERF__[name];
6330
+ return typeof hook === "function" ? hook : null;
6331
+ } catch {
6332
+ return null;
6333
+ }
6334
+ }
6335
+ function getTokenizationPerfHook() {
6336
+ return getPerfHook("recordTokenize");
6337
+ }
6338
+ function getGrammarTokenizationPerfHook() {
6339
+ return getPerfHook("recordGrammarTokenize");
6340
+ }
6341
+ function getThemeRegistrationPerfHook() {
6342
+ return getPerfHook("recordThemeRegistration");
6343
+ }
6344
+ function recordTokenize(hook, language, durationMs, line, tokenCount, failed) {
6345
+ if (!hook) return;
6346
+ try {
6347
+ hook({
6348
+ language,
6349
+ durationMs,
6350
+ lineLength: line.length,
6351
+ lineSample: line.slice(0, 120),
6352
+ tokenCount,
6353
+ failed
6354
+ });
6355
+ } catch {}
6356
+ }
6357
+ function recordGrammarTokenize(language, durationMs, line, stoppedEarly, tokenCount) {
6358
+ const hook = getGrammarTokenizationPerfHook();
6359
+ if (!hook) return;
6360
+ try {
6361
+ hook({
6362
+ language,
6363
+ durationMs,
6364
+ lineLength: line.length,
6365
+ lineSample: line.slice(0, 120),
6366
+ stoppedEarly,
6367
+ tokenCount
6368
+ });
6369
+ } catch {}
6370
+ }
6371
+ function recordThemeRegistration(event) {
6372
+ const hook = getThemeRegistrationPerfHook();
6373
+ if (!hook) return;
6374
+ try {
6375
+ hook(event);
6376
+ } catch {}
6377
+ }
6378
+ function getProxyMember(target, prop) {
6379
+ const value = Reflect.get(target, prop, target);
6380
+ return typeof value === "function" ? value.bind(target) : value;
6381
+ }
6202
6382
  function themeKey(t) {
6203
6383
  return typeof t === "string" ? t : t.name ?? JSON.stringify(t);
6204
6384
  }
6385
+ function maybeInstrumentHighlighterGrammar(highlighter) {
6386
+ if (!getGrammarTokenizationPerfHook()) return highlighter;
6387
+ if (!highlighter || typeof highlighter !== "object" && typeof highlighter !== "function") return highlighter;
6388
+ const cached = instrumentedHighlighterCache.get(highlighter);
6389
+ if (cached) return cached;
6390
+ const grammarProxyCache = /* @__PURE__ */ new WeakMap();
6391
+ const instrumentedHighlighter = new Proxy(highlighter, { get(target, prop, _receiver) {
6392
+ if (prop !== "getLanguage") return getProxyMember(target, prop);
6393
+ return (language) => {
6394
+ const grammar = target.getLanguage(language);
6395
+ if (!grammar || typeof grammar !== "object" || typeof grammar.tokenizeLine2 !== "function") return grammar;
6396
+ const cachedGrammar = grammarProxyCache.get(grammar);
6397
+ if (cachedGrammar) return cachedGrammar;
6398
+ const instrumentedGrammar = new Proxy(grammar, { get(grammarTarget, grammarProp, _grammarReceiver) {
6399
+ if (grammarProp !== "tokenizeLine2") return getProxyMember(grammarTarget, grammarProp);
6400
+ const originalTokenizeLine2 = grammarTarget.tokenizeLine2.bind(grammarTarget);
6401
+ return (line, ruleStack, timeLimit) => {
6402
+ var _result$tokens;
6403
+ const startedAt = nowMs();
6404
+ const result = originalTokenizeLine2(line, ruleStack, timeLimit);
6405
+ 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);
6406
+ return result;
6407
+ };
6408
+ } });
6409
+ grammarProxyCache.set(grammar, instrumentedGrammar);
6410
+ return instrumentedGrammar;
6411
+ };
6412
+ } });
6413
+ instrumentedHighlighterCache.set(highlighter, instrumentedHighlighter);
6414
+ return instrumentedHighlighter;
6415
+ }
6205
6416
  async function ensureMonacoHighlighter(themes, languages$1) {
6206
6417
  for (const t of themes) monacoThemeByKey.set(themeKey(t), t);
6207
6418
  for (const l of languages$1) monacoLanguageSet.add(l);
@@ -6211,7 +6422,11 @@ async function ensureMonacoHighlighter(themes, languages$1) {
6211
6422
  monacoHighlighterPromise = createHighlighterWithLegacyEngineIfNeeded({
6212
6423
  themes: initialThemes,
6213
6424
  langs: initialLangs
6214
- }).then((h$1) => h$1);
6425
+ }).then((h$1) => {
6426
+ h$1.__streamMonacoLoadedThemes = new Set(initialThemes.map((t) => themeKey(t)));
6427
+ h$1.__streamMonacoLoadedLangs = new Set(initialLangs);
6428
+ return h$1;
6429
+ });
6215
6430
  }
6216
6431
  const h = await monacoHighlighterPromise;
6217
6432
  const wantsThemes = Array.from(monacoThemeByKey.values());
@@ -6239,7 +6454,11 @@ async function ensureMonacoHighlighter(themes, languages$1) {
6239
6454
  const p = createHighlighterWithLegacyEngineIfNeeded({
6240
6455
  themes: wantsThemes,
6241
6456
  langs: wantsLangs
6242
- }).then((hh) => hh);
6457
+ }).then((hh) => {
6458
+ hh.__streamMonacoLoadedThemes = new Set(wantsThemes.map((t) => themeKey(t)));
6459
+ hh.__streamMonacoLoadedLangs = new Set(wantsLangs);
6460
+ return hh;
6461
+ });
6243
6462
  monacoHighlighterPromise = p;
6244
6463
  return p;
6245
6464
  }
@@ -6258,6 +6477,7 @@ function clearHighlighterCache() {
6258
6477
  monacoThemeByKey.clear();
6259
6478
  monacoLanguageSet.clear();
6260
6479
  themeRegisterPromise = null;
6480
+ instrumentedHighlighterCache = /* @__PURE__ */ new WeakMap();
6261
6481
  languagesRegistered = false;
6262
6482
  currentLanguages = [];
6263
6483
  }
@@ -6324,9 +6544,15 @@ async function getOrCreateHighlighter(themes, languages$1) {
6324
6544
  */
6325
6545
  async function registerMonacoThemes(themes, languages$1) {
6326
6546
  return enqueueRegistration(async () => {
6547
+ const registrationStartedAt = nowMs();
6548
+ let ensureHighlighterMs = 0;
6549
+ let patchMonacoMs = 0;
6550
+ let patchedMonaco = false;
6327
6551
  registerMonacoLanguages(languages$1);
6328
6552
  const p = (async () => {
6553
+ const ensureHighlighterStartedAt = nowMs();
6329
6554
  const highlighter = await ensureMonacoHighlighter(themes, languages$1);
6555
+ ensureHighlighterMs = nowMs() - ensureHighlighterStartedAt;
6330
6556
  const wantsLangs = Array.from(monacoLanguageSet.values());
6331
6557
  const needsLanguagePatch = lastPatchedHighlighter !== highlighter || wantsLangs.some((l) => !lastPatchedLanguages.has(l));
6332
6558
  if (needsLanguagePatch) {
@@ -6347,9 +6573,17 @@ async function registerMonacoThemes(themes, languages$1) {
6347
6573
  provider = {
6348
6574
  ...provider,
6349
6575
  tokenize(line, state) {
6576
+ const hook = getTokenizationPerfHook();
6577
+ const startedAt = hook ? nowMs() : 0;
6578
+ let tokenCount = 0;
6579
+ let failed = false;
6350
6580
  try {
6351
- return originalTokenize(line, state);
6581
+ const result = originalTokenize(line, state);
6582
+ tokenCount = Array.isArray(result === null || result === void 0 ? void 0 : result.tokens) ? result.tokens.length : 0;
6583
+ return result;
6352
6584
  } catch {
6585
+ failed = true;
6586
+ tokenCount = 1;
6353
6587
  return {
6354
6588
  endState: state,
6355
6589
  tokens: [{
@@ -6357,6 +6591,8 @@ async function registerMonacoThemes(themes, languages$1) {
6357
6591
  scopes: ""
6358
6592
  }]
6359
6593
  };
6594
+ } finally {
6595
+ if (hook) recordTokenize(hook, lang, nowMs() - startedAt, line, tokenCount, failed);
6360
6596
  }
6361
6597
  }
6362
6598
  };
@@ -6365,7 +6601,10 @@ async function registerMonacoThemes(themes, languages$1) {
6365
6601
  }
6366
6602
  }
6367
6603
  };
6368
- shikiToMonaco(highlighter, monacoProxy);
6604
+ const patchMonacoStartedAt = nowMs();
6605
+ shikiToMonaco(maybeInstrumentHighlighterGrammar(highlighter), monacoProxy);
6606
+ patchMonacoMs = nowMs() - patchMonacoStartedAt;
6607
+ patchedMonaco = true;
6369
6608
  lastPatchedHighlighter = highlighter;
6370
6609
  lastPatchedLanguages = new Set(wantsLangs);
6371
6610
  }
@@ -6375,6 +6614,14 @@ async function registerMonacoThemes(themes, languages$1) {
6375
6614
  setThemeRegisterPromise(p);
6376
6615
  try {
6377
6616
  const res = await p;
6617
+ recordThemeRegistration({
6618
+ durationMs: nowMs() - registrationStartedAt,
6619
+ ensureHighlighterMs,
6620
+ patchMonacoMs,
6621
+ themes: themes.length,
6622
+ languages: languages$1.length,
6623
+ patchedMonaco
6624
+ });
6378
6625
  return res;
6379
6626
  } catch (e) {
6380
6627
  setThemeRegisterPromise(null);
@@ -6508,7 +6755,8 @@ function useMonaco(monacoOptions = {}) {
6508
6755
  let modifiedModel = null;
6509
6756
  const themes = monacoOptions.themes && ((_monacoOptions$themes = monacoOptions.themes) === null || _monacoOptions$themes === void 0 ? void 0 : _monacoOptions$themes.length) ? monacoOptions.themes : defaultThemes;
6510
6757
  if (!Array.isArray(themes) || themes.length < 2) throw new Error("Monaco themes must be an array with at least two themes: [darkTheme, lightTheme]");
6511
- const languages$1 = monacoOptions.languages ?? defaultLanguages;
6758
+ const explicitLanguages = monacoOptions.languages;
6759
+ const languages$1 = explicitLanguages ?? defaultLanguages;
6512
6760
  const MAX_HEIGHT = monacoOptions.MAX_HEIGHT ?? 500;
6513
6761
  const autoScrollOnUpdate = monacoOptions.autoScrollOnUpdate ?? true;
6514
6762
  const autoScrollInitial = monacoOptions.autoScrollInitial ?? true;
@@ -6597,10 +6845,27 @@ function useMonaco(monacoOptions = {}) {
6597
6845
  console.warn("onThemeChange callback threw an error:", err);
6598
6846
  }
6599
6847
  }
6600
- async function ensureThemeRegistered(themeName) {
6848
+ function normalizeLanguage(language) {
6849
+ if (!language) return null;
6850
+ return processedLanguage(language) || language;
6851
+ }
6852
+ function resolveCreateLanguages(primaryLanguage) {
6853
+ const primary = normalizeLanguage(primaryLanguage);
6854
+ if (Array.isArray(explicitLanguages) && explicitLanguages.length) {
6855
+ const set = /* @__PURE__ */ new Set();
6856
+ for (const language of explicitLanguages) {
6857
+ const normalized = normalizeLanguage(language);
6858
+ if (normalized) set.add(normalized);
6859
+ }
6860
+ if (primary) set.add(primary);
6861
+ return Array.from(set);
6862
+ }
6863
+ return primary ? [primary] : ["typescript"];
6864
+ }
6865
+ async function ensureThemeRegistered(themeName, requestedLanguages = languages$1) {
6601
6866
  const availableNames = themes.map((t) => typeof t === "string" ? t : t.name);
6602
6867
  const list = availableNames.includes(themeName) ? themes : themes.concat(themeName);
6603
- await registerMonacoThemes(list, languages$1);
6868
+ await registerMonacoThemes(list, requestedLanguages);
6604
6869
  }
6605
6870
  function resolveRequestedThemeName() {
6606
6871
  return requestedThemeName ?? globalRequestedThemeName ?? monacoOptions.theme ?? currentTheme.value;
@@ -6677,11 +6942,12 @@ function useMonaco(monacoOptions = {}) {
6677
6942
  queuedEditorUpdateDuringCreate = null;
6678
6943
  disposeAllPendingCreateDisposables();
6679
6944
  }
6680
- async function resolveCreateThemeName(requestId, kind) {
6945
+ async function resolveCreateThemeName(requestId, kind, primaryLanguage) {
6681
6946
  let themeName = resolveRequestedThemeName();
6947
+ const createLanguages = resolveCreateLanguages(primaryLanguage);
6682
6948
  while (true) {
6683
6949
  assertCreateStillActive(requestId, kind);
6684
- await ensureThemeRegistered(themeName);
6950
+ await ensureThemeRegistered(themeName, createLanguages);
6685
6951
  assertCreateStillActive(requestId, kind);
6686
6952
  const latestThemeName = resolveRequestedThemeName();
6687
6953
  if (latestThemeName === themeName) return themeName;
@@ -6700,7 +6966,7 @@ function useMonaco(monacoOptions = {}) {
6700
6966
  if (requestDisposables.length) pendingCreateDisposables.set(requestId, requestDisposables);
6701
6967
  let nextEditorMgr = null;
6702
6968
  try {
6703
- const initialThemeName = await resolveCreateThemeName(requestId, "editor");
6969
+ const initialThemeName = await resolveCreateThemeName(requestId, "editor", language);
6704
6970
  nextEditorMgr = new EditorManager(monacoOptions, maxHeightValue, maxHeightCSS, autoScrollOnUpdate, autoScrollInitial, autoScrollThresholdPx, autoScrollThresholdLines, monacoOptions.revealDebounceMs, monacoOptions.updateThrottleMs);
6705
6971
  const nextEditorView = await nextEditorMgr.createEditor(container, code, language, initialThemeName);
6706
6972
  assertCreateStillActive(requestId, "editor");
@@ -6747,7 +7013,7 @@ function useMonaco(monacoOptions = {}) {
6747
7013
  if (requestDisposables.length) pendingCreateDisposables.set(requestId, requestDisposables);
6748
7014
  let nextDiffMgr = null;
6749
7015
  try {
6750
- const initialThemeName = await resolveCreateThemeName(requestId, "diff");
7016
+ const initialThemeName = await resolveCreateThemeName(requestId, "diff", language);
6751
7017
  nextDiffMgr = new DiffEditorManager(monacoOptions, maxHeightValue, maxHeightCSS, autoScrollOnUpdate, autoScrollInitial, autoScrollThresholdPx, autoScrollThresholdLines, diffAutoScroll, monacoOptions.revealDebounceMs, monacoOptions.diffUpdateThrottleMs);
6752
7018
  const nextDiffEditorView = await nextDiffMgr.createDiffEditor(container, originalCode, modifiedCode, language, initialThemeName);
6753
7019
  assertCreateStillActive(requestId, "diff");