stream-monaco 0.0.12 → 0.0.14

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/README.md CHANGED
@@ -473,6 +473,7 @@ cleanupEditor()
473
473
  ### Troubleshooting
474
474
 
475
475
  - Editor invisible after build: configure Monaco web workers correctly.
476
+ - Diff editor renders blank during early mount/streaming: ensure Monaco workers are configured before `createEditor`/`createDiffEditor` (e.g. call `preloadMonacoWorkers()` as early as possible).
476
477
  - Theme not applied: ensure theme name is included in `themes`.
477
478
  - Language highlighting missing: ensure the language is included and supported by Shiki.
478
479
 
package/README.zh-CN.md CHANGED
@@ -720,11 +720,15 @@ onUnmounted(() => {
720
720
 
721
721
  确保正确配置了 Monaco Editor 的 Web Workers(参考上面的 Vite/Webpack 配置)。
722
722
 
723
- #### 2. 主题不生效
723
+ #### 2. Diff 编辑器流式更新时内容区空白
724
+
725
+ 确保在调用 `createEditor` / `createDiffEditor` 之前已正确配置 Monaco 的 workers(建议尽早调用 `preloadMonacoWorkers()`)。
726
+
727
+ #### 3. 主题不生效
724
728
 
725
729
  检查主题名称是否正确,确保主题已在 `themes` 数组中注册。
726
730
 
727
- #### 3. 语言高亮不工作
731
+ #### 4. 语言高亮不工作
728
732
 
729
733
  确保语言已在 `languages` 数组中包含,并且 Shiki 支持该语言。
730
734
 
package/dist/index.cjs CHANGED
@@ -899,11 +899,9 @@ var DiffEditorManager = class {
899
899
  didImmediate = true;
900
900
  }
901
901
  if (modifiedCode !== prevM && modifiedCode.startsWith(prevM)) {
902
- const prevLine = this.modifiedModel.getLineCount();
903
- this.appendToModel(this.modifiedModel, modifiedCode.slice(prevM.length));
902
+ this.appendModified(modifiedCode.slice(prevM.length));
904
903
  this.lastKnownModifiedCode = modifiedCode;
905
904
  didImmediate = true;
906
- this.maybeScrollDiffToBottom(this.modifiedModel.getLineCount(), prevLine);
907
905
  }
908
906
  if (originalCode !== this.lastKnownOriginalCode || modifiedCode !== this.lastKnownModifiedCode) {
909
907
  this.pendingDiffUpdate = {
@@ -933,12 +931,12 @@ var DiffEditorManager = class {
933
931
  }
934
932
  const prev = this.lastKnownModifiedCode ?? this.modifiedModel.getValue();
935
933
  if (prev === newCode) return;
936
- const prevLine = this.modifiedModel.getLineCount();
937
- if (newCode.startsWith(prev) && prev.length < newCode.length) {
938
- this.appendToModel(this.modifiedModel, newCode.slice(prev.length));
939
- this.maybeScrollDiffToBottom(this.modifiedModel.getLineCount(), prevLine);
940
- } else {
941
- this.applyMinimalEditToModel(this.modifiedModel, prev, newCode);
934
+ if (newCode.startsWith(prev) && prev.length < newCode.length) this.appendModified(newCode.slice(prev.length), codeLanguage);
935
+ else {
936
+ this.flushModifiedAppendBufferSync();
937
+ const prevAfterFlush = this.modifiedModel.getValue();
938
+ const prevLine = this.modifiedModel.getLineCount();
939
+ this.applyMinimalEditToModel(this.modifiedModel, prevAfterFlush, newCode);
942
940
  const newLine = this.modifiedModel.getLineCount();
943
941
  if (newLine !== prevLine) {
944
942
  const shouldImmediate = this.shouldPerformImmediateRevealDiff();
@@ -1056,6 +1054,9 @@ var DiffEditorManager = class {
1056
1054
  safeClean() {
1057
1055
  this.rafScheduler.cancel("diff");
1058
1056
  this.pendingDiffUpdate = null;
1057
+ this.rafScheduler.cancel("appendDiff");
1058
+ this.appendBufferDiffScheduled = false;
1059
+ this.appendBufferDiff.length = 0;
1059
1060
  if (this.diffScrollWatcher) {
1060
1061
  this.diffScrollWatcher.dispose();
1061
1062
  this.diffScrollWatcher = null;
@@ -1107,6 +1108,7 @@ var DiffEditorManager = class {
1107
1108
  }
1108
1109
  const { original, modified, lang } = this.pendingDiffUpdate;
1109
1110
  this.pendingDiffUpdate = null;
1111
+ this.flushModifiedAppendBufferSync();
1110
1112
  if (lang) {
1111
1113
  const plang = processedLanguage(lang);
1112
1114
  if (plang) {
@@ -1124,14 +1126,7 @@ var DiffEditorManager = class {
1124
1126
  else this.applyMinimalEditToModel(o, prevO, original);
1125
1127
  this.lastKnownOriginalCode = original;
1126
1128
  }
1127
- let prevM = this.lastKnownModifiedCode;
1128
- const buffered = this.appendBufferDiff.length > 0 ? this.appendBufferDiff.join("") : "";
1129
- if (this.appendBufferDiff.length > 0) try {
1130
- prevM = m.getValue() + buffered;
1131
- this.lastKnownModifiedCode = prevM;
1132
- } catch {
1133
- prevM = (this.lastKnownModifiedCode ?? "") + buffered;
1134
- }
1129
+ const prevM = m.getValue();
1135
1130
  const prevMLineCount = m.getLineCount();
1136
1131
  if (prevM !== modified) {
1137
1132
  if (modified.startsWith(prevM) && prevM.length < modified.length) this.appendToModel(m, modified.slice(prevM.length));
@@ -1151,6 +1146,16 @@ var DiffEditorManager = class {
1151
1146
  }
1152
1147
  }
1153
1148
  }
1149
+ flushModifiedAppendBufferSync() {
1150
+ if (!this.modifiedModel) return;
1151
+ if (this.appendBufferDiff.length === 0) return;
1152
+ this.rafScheduler.cancel("appendDiff");
1153
+ this.appendBufferDiffScheduled = false;
1154
+ const text = this.appendBufferDiff.join("");
1155
+ this.appendBufferDiff.length = 0;
1156
+ if (!text) return;
1157
+ this.appendToModel(this.modifiedModel, text);
1158
+ }
1154
1159
  async flushAppendBufferDiff() {
1155
1160
  if (!this.diffEditorView) return;
1156
1161
  if (this.appendBufferDiff.length === 0) return;
@@ -1956,15 +1961,17 @@ async function preloadMonacoWorkers() {
1956
1961
  javascript: workerUrlTs
1957
1962
  };
1958
1963
  try {
1959
- await Promise.all(unique.map((u) => fetch(u, {
1960
- method: "GET",
1961
- cache: "force-cache"
1962
- }).catch(() => void 0)));
1963
1964
  self.MonacoEnvironment = { getWorker(_, label) {
1964
1965
  const url = workerUrlByLabel[label] ?? workerUrlEditor;
1965
1966
  return new Worker(url, { type: "module" });
1966
1967
  } };
1967
1968
  } catch {}
1969
+ try {
1970
+ await Promise.all(unique.map((u) => fetch(u, {
1971
+ method: "GET",
1972
+ cache: "force-cache"
1973
+ }).catch(() => void 0)));
1974
+ } catch {}
1968
1975
  }
1969
1976
 
1970
1977
  //#endregion
@@ -2343,14 +2350,12 @@ function useMonaco(monacoOptions = {}) {
2343
2350
  if (token !== globalThemeRequestSeq) return;
2344
2351
  try {
2345
2352
  monaco_shim_exports.editor.setTheme(themeName);
2346
- lastAppliedTheme = themeName;
2347
2353
  globalAppliedThemeName = themeName;
2348
2354
  } catch {
2349
2355
  try {
2350
2356
  const maybeHighlighter = await registerMonacoThemes(themes, languages$1);
2351
2357
  if (token !== globalThemeRequestSeq) return;
2352
2358
  monaco_shim_exports.editor.setTheme(themeName);
2353
- lastAppliedTheme = themeName;
2354
2359
  globalAppliedThemeName = themeName;
2355
2360
  await tryLoadAndSetShikiTheme(maybeHighlighter, themeName).catch(() => void 0);
2356
2361
  } catch (err2) {
@@ -2414,7 +2419,6 @@ function useMonaco(monacoOptions = {}) {
2414
2419
  await ensureThemeRegistered(initialThemeName);
2415
2420
  editorMgr = new EditorManager(monacoOptions, maxHeightValue, maxHeightCSS, autoScrollOnUpdate, autoScrollInitial, autoScrollThresholdPx, autoScrollThresholdLines, monacoOptions.revealDebounceMs);
2416
2421
  editorView = await editorMgr.createEditor(container, code, language, initialThemeName);
2417
- lastAppliedTheme = initialThemeName;
2418
2422
  if (pendingUpdate && editorMgr) {
2419
2423
  const { code: queuedCode, lang: queuedLang } = pendingUpdate;
2420
2424
  pendingUpdate = null;
@@ -2446,7 +2450,6 @@ function useMonaco(monacoOptions = {}) {
2446
2450
  await ensureThemeRegistered(initialThemeName);
2447
2451
  try {
2448
2452
  monaco_shim_exports.editor.setTheme(initialThemeName);
2449
- lastAppliedTheme = initialThemeName;
2450
2453
  } catch {}
2451
2454
  diffMgr = new DiffEditorManager(monacoOptions, maxHeightValue, maxHeightCSS, autoScrollOnUpdate, autoScrollInitial, autoScrollThresholdPx, autoScrollThresholdLines, diffAutoScroll, monacoOptions.revealDebounceMs);
2452
2455
  diffEditorView = await diffMgr.createDiffEditor(container, originalCode, modifiedCode, language, initialThemeName);
package/dist/index.js CHANGED
@@ -871,11 +871,9 @@ var DiffEditorManager = class {
871
871
  didImmediate = true;
872
872
  }
873
873
  if (modifiedCode !== prevM && modifiedCode.startsWith(prevM)) {
874
- const prevLine = this.modifiedModel.getLineCount();
875
- this.appendToModel(this.modifiedModel, modifiedCode.slice(prevM.length));
874
+ this.appendModified(modifiedCode.slice(prevM.length));
876
875
  this.lastKnownModifiedCode = modifiedCode;
877
876
  didImmediate = true;
878
- this.maybeScrollDiffToBottom(this.modifiedModel.getLineCount(), prevLine);
879
877
  }
880
878
  if (originalCode !== this.lastKnownOriginalCode || modifiedCode !== this.lastKnownModifiedCode) {
881
879
  this.pendingDiffUpdate = {
@@ -905,12 +903,12 @@ var DiffEditorManager = class {
905
903
  }
906
904
  const prev = this.lastKnownModifiedCode ?? this.modifiedModel.getValue();
907
905
  if (prev === newCode) return;
908
- const prevLine = this.modifiedModel.getLineCount();
909
- if (newCode.startsWith(prev) && prev.length < newCode.length) {
910
- this.appendToModel(this.modifiedModel, newCode.slice(prev.length));
911
- this.maybeScrollDiffToBottom(this.modifiedModel.getLineCount(), prevLine);
912
- } else {
913
- this.applyMinimalEditToModel(this.modifiedModel, prev, newCode);
906
+ if (newCode.startsWith(prev) && prev.length < newCode.length) this.appendModified(newCode.slice(prev.length), codeLanguage);
907
+ else {
908
+ this.flushModifiedAppendBufferSync();
909
+ const prevAfterFlush = this.modifiedModel.getValue();
910
+ const prevLine = this.modifiedModel.getLineCount();
911
+ this.applyMinimalEditToModel(this.modifiedModel, prevAfterFlush, newCode);
914
912
  const newLine = this.modifiedModel.getLineCount();
915
913
  if (newLine !== prevLine) {
916
914
  const shouldImmediate = this.shouldPerformImmediateRevealDiff();
@@ -1028,6 +1026,9 @@ var DiffEditorManager = class {
1028
1026
  safeClean() {
1029
1027
  this.rafScheduler.cancel("diff");
1030
1028
  this.pendingDiffUpdate = null;
1029
+ this.rafScheduler.cancel("appendDiff");
1030
+ this.appendBufferDiffScheduled = false;
1031
+ this.appendBufferDiff.length = 0;
1031
1032
  if (this.diffScrollWatcher) {
1032
1033
  this.diffScrollWatcher.dispose();
1033
1034
  this.diffScrollWatcher = null;
@@ -1079,6 +1080,7 @@ var DiffEditorManager = class {
1079
1080
  }
1080
1081
  const { original, modified, lang } = this.pendingDiffUpdate;
1081
1082
  this.pendingDiffUpdate = null;
1083
+ this.flushModifiedAppendBufferSync();
1082
1084
  if (lang) {
1083
1085
  const plang = processedLanguage(lang);
1084
1086
  if (plang) {
@@ -1096,14 +1098,7 @@ var DiffEditorManager = class {
1096
1098
  else this.applyMinimalEditToModel(o, prevO, original);
1097
1099
  this.lastKnownOriginalCode = original;
1098
1100
  }
1099
- let prevM = this.lastKnownModifiedCode;
1100
- const buffered = this.appendBufferDiff.length > 0 ? this.appendBufferDiff.join("") : "";
1101
- if (this.appendBufferDiff.length > 0) try {
1102
- prevM = m.getValue() + buffered;
1103
- this.lastKnownModifiedCode = prevM;
1104
- } catch {
1105
- prevM = (this.lastKnownModifiedCode ?? "") + buffered;
1106
- }
1101
+ const prevM = m.getValue();
1107
1102
  const prevMLineCount = m.getLineCount();
1108
1103
  if (prevM !== modified) {
1109
1104
  if (modified.startsWith(prevM) && prevM.length < modified.length) this.appendToModel(m, modified.slice(prevM.length));
@@ -1123,6 +1118,16 @@ var DiffEditorManager = class {
1123
1118
  }
1124
1119
  }
1125
1120
  }
1121
+ flushModifiedAppendBufferSync() {
1122
+ if (!this.modifiedModel) return;
1123
+ if (this.appendBufferDiff.length === 0) return;
1124
+ this.rafScheduler.cancel("appendDiff");
1125
+ this.appendBufferDiffScheduled = false;
1126
+ const text = this.appendBufferDiff.join("");
1127
+ this.appendBufferDiff.length = 0;
1128
+ if (!text) return;
1129
+ this.appendToModel(this.modifiedModel, text);
1130
+ }
1126
1131
  async flushAppendBufferDiff() {
1127
1132
  if (!this.diffEditorView) return;
1128
1133
  if (this.appendBufferDiff.length === 0) return;
@@ -1928,15 +1933,17 @@ async function preloadMonacoWorkers() {
1928
1933
  javascript: workerUrlTs
1929
1934
  };
1930
1935
  try {
1931
- await Promise.all(unique.map((u) => fetch(u, {
1932
- method: "GET",
1933
- cache: "force-cache"
1934
- }).catch(() => void 0)));
1935
1936
  self.MonacoEnvironment = { getWorker(_, label) {
1936
1937
  const url = workerUrlByLabel[label] ?? workerUrlEditor;
1937
1938
  return new Worker(url, { type: "module" });
1938
1939
  } };
1939
1940
  } catch {}
1941
+ try {
1942
+ await Promise.all(unique.map((u) => fetch(u, {
1943
+ method: "GET",
1944
+ cache: "force-cache"
1945
+ }).catch(() => void 0)));
1946
+ } catch {}
1940
1947
  }
1941
1948
 
1942
1949
  //#endregion
@@ -2315,14 +2322,12 @@ function useMonaco(monacoOptions = {}) {
2315
2322
  if (token !== globalThemeRequestSeq) return;
2316
2323
  try {
2317
2324
  monaco_shim_exports.editor.setTheme(themeName);
2318
- lastAppliedTheme = themeName;
2319
2325
  globalAppliedThemeName = themeName;
2320
2326
  } catch {
2321
2327
  try {
2322
2328
  const maybeHighlighter = await registerMonacoThemes(themes, languages$1);
2323
2329
  if (token !== globalThemeRequestSeq) return;
2324
2330
  monaco_shim_exports.editor.setTheme(themeName);
2325
- lastAppliedTheme = themeName;
2326
2331
  globalAppliedThemeName = themeName;
2327
2332
  await tryLoadAndSetShikiTheme(maybeHighlighter, themeName).catch(() => void 0);
2328
2333
  } catch (err2) {
@@ -2386,7 +2391,6 @@ function useMonaco(monacoOptions = {}) {
2386
2391
  await ensureThemeRegistered(initialThemeName);
2387
2392
  editorMgr = new EditorManager(monacoOptions, maxHeightValue, maxHeightCSS, autoScrollOnUpdate, autoScrollInitial, autoScrollThresholdPx, autoScrollThresholdLines, monacoOptions.revealDebounceMs);
2388
2393
  editorView = await editorMgr.createEditor(container, code, language, initialThemeName);
2389
- lastAppliedTheme = initialThemeName;
2390
2394
  if (pendingUpdate && editorMgr) {
2391
2395
  const { code: queuedCode, lang: queuedLang } = pendingUpdate;
2392
2396
  pendingUpdate = null;
@@ -2418,7 +2422,6 @@ function useMonaco(monacoOptions = {}) {
2418
2422
  await ensureThemeRegistered(initialThemeName);
2419
2423
  try {
2420
2424
  monaco_shim_exports.editor.setTheme(initialThemeName);
2421
- lastAppliedTheme = initialThemeName;
2422
2425
  } catch {}
2423
2426
  diffMgr = new DiffEditorManager(monacoOptions, maxHeightValue, maxHeightCSS, autoScrollOnUpdate, autoScrollInitial, autoScrollThresholdPx, autoScrollThresholdLines, diffAutoScroll, monacoOptions.revealDebounceMs);
2424
2427
  diffEditorView = await diffMgr.createDiffEditor(container, originalCode, modifiedCode, language, initialThemeName);
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "stream-monaco",
3
3
  "type": "module",
4
- "version": "0.0.12",
4
+ "version": "0.0.14",
5
5
  "description": "A framework-agnostic library for integrating Monaco Editor with Shiki highlighting, optimized for streaming updates.",
6
6
  "author": "Simon He",
7
7
  "license": "MIT",
@@ -92,6 +92,7 @@
92
92
  "start": "esno src/index.ts",
93
93
  "bench": "node scripts/stream-benchmark.mjs",
94
94
  "bench:playwright": "node scripts/playwright-bench.mjs",
95
+ "smoke:diff": "node scripts/playwright-diff-smoke.mjs",
95
96
  "test": "vitest",
96
97
  "typecheck": "tsc --noEmit"
97
98
  }