stream-monaco 0.0.19 → 0.0.21

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.zh-CN.md CHANGED
@@ -21,11 +21,12 @@ IMPORTANT: Since v0.0.32 the library enables a default time-based throttle for `
21
21
  - 🔁 **可用于任意框架**:Vue、React、Svelte、Solid、Preact,或纯 JS/TS
22
22
 
23
23
  说明:内部响应式基于 `alien-signals` 的轻薄适配层实现,因此核心逻辑不再强依赖 Vue。Vue 仍然完全支持,但被标记为可选的 peer 依赖,使库在非 Vue 环境也可复用核心能力,且对现有 API 无破坏。
24
+
24
25
  - 🎨 **Shiki 高亮** - 使用 Shiki 实现高效的语法高亮,支持 TextMate 语法和 VS Code 主题
25
26
  - 📝 **流式更新** - 支持流式输入更新,实时响应代码变化
26
27
 
27
28
  - `registerMonacoThemes(themes, languages): Promise<Highlighter>` — 使用 shiki 创建或获取高亮器并把主题注册到 Monaco,返回解析为 shiki highlighter 的 Promise,便于复用(例如渲染页面片段)。
28
- `getOrCreateHighlighter(themes, languages): Promise<Highlighter>` — 直接获取或创建一个 highlighter(并受内部缓存管理)。如需直接控制 shiki highlighter(例如调用 `codeToHtml` 或 `setTheme`),请使用此方法并自行处理加载/错误逻辑。
29
+ `getOrCreateHighlighter(themes, languages): Promise<Highlighter>` — 直接获取或创建一个 highlighter(并受内部缓存管理)。如需直接控制 shiki highlighter(例如调用 `codeToHtml` 或 `setTheme`),请使用此方法并自行处理加载/错误逻辑。
29
30
 
30
31
  注意:如果你只使用 Monaco 编辑器并在 `createEditor` 时传入了全量 `themes`,通常只需调用 `monaco.editor.setTheme(themeName)` 即可。
31
32
 
@@ -224,18 +225,10 @@ function getCurrentCode() {
224
225
  <template>
225
226
  <div>
226
227
  <div class="controls">
227
- <button @click="switchTheme('github-dark')">
228
- 暗色主题
229
- </button>
230
- <button @click="switchTheme('github-light')">
231
- 亮色主题
232
- </button>
233
- <button @click="switchLanguage('typescript')">
234
- TypeScript
235
- </button>
236
- <button @click="switchLanguage('python')">
237
- Python
238
- </button>
228
+ <button @click="switchTheme('github-dark')">暗色主题</button>
229
+ <button @click="switchTheme('github-light')">亮色主题</button>
230
+ <button @click="switchLanguage('typescript')">TypeScript</button>
231
+ <button @click="switchLanguage('python')">Python</button>
239
232
  </div>
240
233
  <div ref="editorContainer" class="editor" />
241
234
  </div>
@@ -283,12 +276,22 @@ export function MonacoEditor() {
283
276
  })
284
277
 
285
278
  useEffect(() => {
286
- if (containerRef.current)
287
- createEditor(containerRef.current, 'console.log("Hello, Monaco!")', 'typescript')
279
+ if (containerRef.current) {
280
+ createEditor(
281
+ containerRef.current,
282
+ 'console.log("Hello, Monaco!")',
283
+ 'typescript',
284
+ )
285
+ }
288
286
  return () => cleanupEditor()
289
287
  }, [])
290
288
 
291
- return <div ref={containerRef} style={{ height: 500, border: '1px solid #e0e0e0' }} />
289
+ return (
290
+ <div
291
+ ref={containerRef}
292
+ style={{ height: 500, border: '1px solid #e0e0e0' }}
293
+ />
294
+ )
292
295
  }
293
296
  ```
294
297
 
@@ -399,8 +402,17 @@ onMounted(async () => {
399
402
  Diff 体验增强相关配置:
400
403
 
401
404
  - `diffHideUnchangedRegions`(默认 `true`):折叠未改动区块;也支持直接传 Monaco 的 `hideUnchangedRegions` 对象。
405
+ - `diffLineStyle`(默认 `background`):控制变更行的强调方式;传 `bar` 可切换到更克制的 review 风格竖条表现。
406
+ - `diffAppearance`(默认 `auto`):控制 diff 外层 chrome 的明暗风格;可强制 `light` / `dark`,代码 token 仍跟随当前主题。
407
+ - `diffUnchangedRegionStyle`(默认 `line-info`):控制折叠未改动区块的展示方式;`line-info`、`line-info-basic`、`metadata` 都使用更紧凑的 `32px` 折叠行,其中 `line-info-basic` 仍保留更宽的 legacy rail,`simple` 则是更紧的 `28px` 占位行。
402
408
  - `diffHunkActionsOnHover`(默认 `false`):仅在显式传 `true` 时,hover 变更 hunk 才会显示上下分区的 `Revert` / `Stage`。
403
409
  - `onDiffHunkAction(context)`(可选):返回 `false` 可拦截并跳过内置模型编辑逻辑。
410
+ - 内置的 `Revert` / `Stage` 默认只会改 Monaco model,不会直接执行 `git revert`、`git add` 或 `git stash`;如果你要接真实 Git,需要通过 `onDiffHunkAction` 接到自己的后端流程。
411
+
412
+ 完整接入文档:
413
+
414
+ - [Diff 接入指南](docs/diff-integration.zh-CN.md)
415
+ - 已导出的 TS 类型包括 `UseMonacoReturn`、`DiffLineStyle`、`DiffAppearance`、`DiffUnchangedRegionStyle`、`DiffModels`、`DiffModelPair`、`DiffModelTransitionOptions`、`DiffHunkActionContext`
404
416
 
405
417
  示例 1:开启 hidden 区折叠 + hover Revert/Stage(可理解为局部回退与暂存)
406
418
 
@@ -415,13 +427,14 @@ const { createDiffEditor } = useMonaco({
415
427
  minimumLineCount: 4,
416
428
  revealLineCount: 2,
417
429
  },
430
+ diffLineStyle: 'bar',
418
431
  diffHunkActionsOnHover: true,
419
432
  })
420
433
 
421
434
  await createDiffEditor(container, original, modified, 'typescript')
422
435
  ```
423
436
 
424
- 示例 2:完全接管 Revert/Stage 事件(接你自己的 stash / patch API)
437
+ 示例 2:完全接管 Revert/Stage 事件(接你自己的 Git / stash / patch API)
425
438
 
426
439
  ```ts
427
440
  useMonaco({
@@ -452,6 +465,47 @@ useMonaco({
452
465
  })
453
466
  ```
454
467
 
468
+ 示例 3:服务端返回刷新后的文件内容,前端再调用 `updateDiff(...)`
469
+
470
+ ```ts
471
+ const monaco = useMonaco({
472
+ diffHideUnchangedRegions: true,
473
+ diffHunkActionsOnHover: true,
474
+ onDiffHunkAction: async (ctx) => {
475
+ const response = await fetch('/api/git/hunks/apply', {
476
+ method: 'POST',
477
+ headers: { 'content-type': 'application/json' },
478
+ body: JSON.stringify({
479
+ action: ctx.action,
480
+ side: ctx.side,
481
+ range: ctx.lineChange,
482
+ original: ctx.originalModel.getValue(),
483
+ modified: ctx.modifiedModel.getValue(),
484
+ }),
485
+ })
486
+
487
+ const next = await response.json()
488
+ monaco.updateDiff(next.original, next.modified, 'typescript')
489
+ return false
490
+ },
491
+ })
492
+ ```
493
+
494
+ 注意:
495
+
496
+ - hover `Revert` 表示 hunk 级别的局部回退,不等于 `git revert <commit>`。
497
+ - hover `Stage` 更接近 `git add -p` / `git apply --cached`。
498
+ - 如果你想做 stash 流程,建议把 `onDiffHunkAction` 当成“生成 patch 意图”的回调,把选中的 half-hunk 交给后端 stash 或 patch 队列。
499
+ - 如果你的后端会返回刷新后的整份文件内容,前端最直接的做法就是调用 `updateDiff(...)` 把 Git 已应用后的结果回灌到 diff UI。仓库里也提供了 `pnpm run validate:diff-hunk-update-diff-flow` 来覆盖这条模式。
500
+ - 更完整的 Git 绑定方式见 [Diff 接入指南](docs/diff-integration.zh-CN.md)。
501
+
502
+ 视觉校验辅助命令:
503
+
504
+ - `pnpm run shot:diff-ux -- background /tmp/stream-monaco-diff-reference.png pierre-reference`
505
+ 抓取 Pierre 风格参考场景,固定视口、文件头和 `-1 / +1` 的单 hunk diff;第四个参数可额外指定 `snazzy-light` 这类 theme。
506
+ - `pnpm run compare:diff-ux -- /tmp/stream-monaco-diff-reference.png background pierre-reference`
507
+ 重新抓取同一场景并输出截图指标,例如 `diffPixels`、`mismatchRatio`、`exactMatch`;最后一个参数可指定同一套 theme 做对比。
508
+
455
509
  ### Shiki 高亮器(高级说明)
456
510
 
457
511
  如果你在页面上除了 Monaco 编辑器外还使用 Shiki 的 highlighter 单独渲染代码片段(例如静态 HTML 片段),推荐的做法是:
@@ -469,6 +523,7 @@ const highlighter = await registerMonacoThemes(allThemes, allLanguages)
469
523
 
470
524
  // 创建编辑器
471
525
  ```
526
+
472
527
  ### 浏览器级基准(更接近真实 Monaco)
473
528
 
474
529
  仓库内还提供了一个 Playwright 脚本 `scripts/playwright-bench.mjs`,它将在 headless Chromium 中加载 Monaco(通过 CDN)并运行高频更新,从而测量真实编辑器下的耗时与 long-task 计数。
@@ -531,12 +586,12 @@ pnpm run bench
531
586
 
532
587
  // 批量(同帧)更新,两侧同时变化时更方便
533
588
  function pushNewDiff(newOriginal: string, newModified: string) {
534
- updateDiff(newOriginal, newModified, 'typescript')
589
+ updateDiff(newOriginal, newModified, 'typescript')
535
590
  }
536
591
 
537
592
  // 仅更新其中一侧(即时增量)
538
593
  function pushModifiedChunk(chunk: string) {
539
- updateModified(chunk)
594
+ updateModified(chunk)
540
595
  }
541
596
  </script>
542
597
 
@@ -559,7 +614,8 @@ function pushModifiedChunk(chunk: string) {
559
614
  border-radius: 4px;
560
615
  }
561
616
  </style>
562
- ```
617
+
618
+ ````
563
619
 
564
620
  ### 流式追加 + 语言切换(快速示例)
565
621
 
@@ -626,7 +682,7 @@ onMounted(async () => {
626
682
  <p>当内容接近底部时自动滚动(可通过 autoScroll* 选项进行控制)。</p>
627
683
  <p>若是纯末尾追加,内部会走追加快路径,避免全量替换。</p>
628
684
  </template>
629
- ```
685
+ ````
630
686
 
631
687
  更多完整示例请见 examples/ 目录。
632
688
 
@@ -636,18 +692,17 @@ onMounted(async () => {
636
692
  - 当新内容以旧内容为前缀时,采用“仅追加”的策略,避免全量替换带来的性能损耗。
637
693
  - 其他情况下执行“最小中段替换”,在模型上计算公共前后缀,只替换中间变化段,减少编辑器刷新范围。
638
694
  - `updateOriginal` / `updateModified` 为即时增量更新,适合单侧独立流式场景。
639
- - 可通过 options.diffAutoScroll 关闭 Diff 编辑器 modified 侧的自动滚动;默认开启以保持与单编辑器一致的体验。
695
+ - 可通过 options.diffAutoScroll 关闭 Diff 编辑器 modified 侧的自动滚动;默认开启以保持与单编辑器一致的体验。
640
696
 
641
697
  #### 显式流式追加(推荐)
642
698
 
643
699
  当你是标准的“持续在末尾追加”场景,建议直接使用显式追加 API,可减少 diff 计算并获得最佳实时性:
644
700
 
645
701
  ```ts
646
- const {
647
- createDiffEditor,
648
- appendOriginal,
649
- appendModified,
650
- } = useMonaco({ themes: ['vitesse-dark', 'vitesse-light'], languages: ['typescript'] })
702
+ const { createDiffEditor, appendOriginal, appendModified } = useMonaco({
703
+ themes: ['vitesse-dark', 'vitesse-light'],
704
+ languages: ['typescript'],
705
+ })
651
706
 
652
707
  await createDiffEditor(container, '', '', 'typescript')
653
708
 
@@ -679,8 +734,12 @@ getDiffEditorView()?.updateOptions({ renderSideBySide: false })
679
734
 
680
735
  // 获取模型:你可以自行订阅内容变化等底层行为
681
736
  const { original, modified } = getDiffModels()
682
- original?.onDidChangeContent?.(() => { /* ... */ })
683
- modified?.onDidChangeContent?.(() => { /* ... */ })
737
+ original?.onDidChangeContent?.(() => {
738
+ /* ... */
739
+ })
740
+ modified?.onDidChangeContent?.(() => {
741
+ /* ... */
742
+ })
684
743
  ```
685
744
 
686
745
  ### API 参考
@@ -689,46 +748,56 @@ modified?.onDidChangeContent?.(() => { /* ... */ })
689
748
 
690
749
  ##### 参数
691
750
 
692
- | 参数 | 类型 | 默认值 | 描述 |
693
- | ----------------------- | ------------------ | ----------------------------------- | ------------------------------ |
694
- | `MAX_HEIGHT` | `number` | `500` | 编辑器最大高度(像素) |
695
- | `readOnly` | `boolean` | `true` | 是否为只读模式 |
696
- | `themes` | `MonacoTheme[]` | `['vitesse-dark', 'vitesse-light']` | 主题数组,至少包含两个主题 |
697
- | `languages` | `MonacoLanguage[]` | 见默认语言列表 | 支持的编程语言数组 |
698
- | `theme` | `string` | - | 初始主题名称 |
699
- | `isCleanOnBeforeCreate` | `boolean` | `true` | 是否在创建前清理之前注册的资源 |
700
- | `onBeforeCreate` | `function` | - | 编辑器创建前的钩子函数 |
701
- | `autoScrollOnUpdate` | `boolean` | `true` | 更新内容时若接近底部则自动滚动 |
702
- | `autoScrollInitial` | `boolean` | `true` | 是否默认启用自动滚动 |
703
- | `autoScrollThresholdPx` | `number` | `32` | 自动滚动的像素阈值 |
704
- | `autoScrollThresholdLines` | `number` | `2` | 自动滚动的行数阈值 |
705
- | `diffAutoScroll` | `boolean` | `true` | 是否启用 Diff modified 侧自动滚动 |
706
- | `diffHideUnchangedRegions` | `boolean \| object` | `true` | 是否折叠 Diff 中未改动区块(支持传 Monaco 配置对象) |
707
- | `diffHunkActionsOnHover` | `boolean` | `false` | 是否启用 hover hunk 的上下分区局部 Revert / Stage(需显式开启) |
708
- | `diffHunkHoverHideDelayMs` | `number` | `160` | hover 操作浮层离开后的隐藏延迟(毫秒) |
709
- | `onDiffHunkAction` | `function` | - | hunk 操作回调(返回 `false` 可阻止默认编辑) |
751
+ | 参数 | 类型 | 默认值 | 描述 |
752
+ | -------------------------- | ------------------------------------------------------------ | ----------------------------------- | --------------------------------------------------------------- |
753
+ | `MAX_HEIGHT` | `number` | `500` | 编辑器最大高度(像素) |
754
+ | `readOnly` | `boolean` | `true` | 是否为只读模式 |
755
+ | `themes` | `MonacoTheme[]` | `['vitesse-dark', 'vitesse-light']` | 主题数组,至少包含两个主题 |
756
+ | `languages` | `MonacoLanguage[]` | 见默认语言列表 | 支持的编程语言数组 |
757
+ | `theme` | `string` | - | 初始主题名称 |
758
+ | `isCleanOnBeforeCreate` | `boolean` | `true` | 是否在创建前清理之前注册的资源 |
759
+ | `onBeforeCreate` | `function` | - | 编辑器创建前的钩子函数 |
760
+ | `autoScrollOnUpdate` | `boolean` | `true` | 更新内容时若接近底部则自动滚动 |
761
+ | `autoScrollInitial` | `boolean` | `true` | 是否默认启用自动滚动 |
762
+ | `autoScrollThresholdPx` | `number` | `32` | 自动滚动的像素阈值 |
763
+ | `autoScrollThresholdLines` | `number` | `2` | 自动滚动的行数阈值 |
764
+ | `diffAutoScroll` | `boolean` | `true` | 是否启用 Diff modified 侧自动滚动 |
765
+ | `diffHideUnchangedRegions` | `boolean \| object` | `true` | 是否折叠 Diff 中未改动区块(支持传 Monaco 配置对象) |
766
+ | `diffLineStyle` | `'background' \| 'bar'` | `'background'` | 控制变更行是偏背景块还是偏 review 竖条风格 |
767
+ | `diffAppearance` | `'auto' \| 'light' \| 'dark'` | `'auto'` | 控制 diff 外层 chrome 明暗,代码 token 仍跟随当前主题 |
768
+ | `diffUnchangedRegionStyle` | `'line-info' \| 'line-info-basic' \| 'metadata' \| 'simple'` | `'line-info'` | 控制折叠未改动区块的展示方式 |
769
+ | `diffHunkActionsOnHover` | `boolean` | `false` | 是否启用 hover hunk 的上下分区局部 Revert / Stage(需显式开启) |
770
+ | `diffHunkHoverHideDelayMs` | `number` | `160` | hover 操作浮层离开后的隐藏延迟(毫秒) |
771
+ | `onDiffHunkAction` | `function` | - | hunk 操作回调(返回 `false` 可阻止默认编辑) |
772
+ | `diffUpdateThrottleMs` | `number` | `50` | Diff 流式更新节流时间(毫秒) |
710
773
 
711
774
  ##### 返回值
712
775
 
713
- | 方法/属性 | 类型 | 描述 |
714
- | ---------------------- | ---------------------------------------------------------------------------------------------------- | ---------------------------------------------- |
715
- | `createEditor` | `(container: HTMLElement, code: string, language: string) => Promise<MonacoEditor>` | 创建并挂载编辑器到指定容器 |
716
- | `createDiffEditor` | `(container: HTMLElement, original: string, modified: string, language: string) => Promise<MonacoDiffEditor>` | 创建并挂载 Diff 编辑器 |
717
- | `cleanupEditor` | `() => void` | 销毁编辑器并清理容器 |
718
- | `updateCode` | `(newCode: string, codeLanguage: string) => void` | 更新编辑器内容和语言(RAF 合并、增量优化) |
719
- | `appendCode` | `(appendText: string, codeLanguage?: string) => void` | 在编辑器末尾追加文本 |
720
- | `updateDiff` | `(original: string, modified: string, codeLanguage?: string) => void` | 批量更新 Diff 内容(RAF 合并、增量优化) |
721
- | `updateOriginal` | `(newCode: string, codeLanguage?: string) => void` | 仅更新 original(即时增量) |
722
- | `updateModified` | `(newCode: string, codeLanguage?: string) => void` | 仅更新 modified(即时增量) |
723
- | `setTheme` | `(theme: MonacoTheme) => void` | 切换编辑器主题 |
724
- | `setLanguage` | `(language: MonacoLanguage) => void` | 切换编辑器语言 |
725
- | `getCurrentTheme` | `() => string` | 获取当前主题名称 |
726
- | `getEditor` | `() => typeof monaco.editor` | 获取 Monaco 的静态 editor 对象 |
727
- | `getEditorView` | `() => MonacoEditor \| null` | 获取当前编辑器实例 |
728
- | `getDiffEditorView` | `() => MonacoDiffEditor \| null` | 获取当前 Diff 编辑器实例 |
729
- | `getCode` | `() => string \| { original: string, modified: string } \| null` | **获取编辑器当前代码**<br>- 普通编辑器返回 `string`<br>- Diff 编辑器返回 `{ original, modified }`<br>- 无编辑器返回 `null`<br>**用途**:获取用户手动编辑后的最新代码或程序更新后的内容 |
730
- | `appendOriginal` | `(appendText: string, codeLanguage?: string) => void` | original 末尾追加(显式流式) |
731
- | `appendModified` | `(appendText: string, codeLanguage?: string) => void` | modified 末尾追加(显式流式) |
776
+ | 方法/属性 | 类型 | 描述 |
777
+ | ------------------------- | --------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
778
+ | `createEditor` | `(container: HTMLElement, code: string, language: string) => Promise<MonacoEditorInstance>` | 创建并挂载编辑器到指定容器 |
779
+ | `createDiffEditor` | `(container: HTMLElement, original: string, modified: string, language: string) => Promise<MonacoDiffEditorInstance>` | 创建并挂载 Diff 编辑器 |
780
+ | `cleanupEditor` | `() => void` | 销毁编辑器并清理容器 |
781
+ | `updateCode` | `(newCode: string, codeLanguage: string) => void` | 更新编辑器内容和语言(RAF 合并、增量优化) |
782
+ | `appendCode` | `(appendText: string, codeLanguage?: string) => void` | 在编辑器末尾追加文本 |
783
+ | `updateDiff` | `(original: string, modified: string, codeLanguage?: string) => void` | 批量更新 Diff 内容(RAF 合并、增量优化) |
784
+ | `updateOriginal` | `(newCode: string, codeLanguage?: string) => void` | 仅更新 original(即时增量) |
785
+ | `updateModified` | `(newCode: string, codeLanguage?: string) => void` | 仅更新 modified(即时增量) |
786
+ | `setDiffModels` | `(models: DiffModelPair, options?: DiffModelTransitionOptions) => Promise<void>` | 原地切换整对 Diff models;当新旧内容相同,会先预热 Monaco 的 diff view model,再走保留视图状态的低抖动切换 |
787
+ | `setTheme` | `(theme: MonacoTheme, force?: boolean) => Promise<void>` | 切换编辑器主题;`force=true` 时即使当前主题相同也会强制重应用 |
788
+ | `refreshDiffPresentation` | `() => void` | 在不 remount 的情况下,重算 diff chrome / unchanged overlay 的表现层 |
789
+ | `setLanguage` | `(language: MonacoLanguage) => void` | 切换编辑器语言 |
790
+ | `getCurrentTheme` | `() => string` | 获取当前主题名称 |
791
+ | `getEditor` | `() => typeof monaco.editor` | 获取 Monaco 的静态 editor 对象 |
792
+ | `getEditorView` | `() => MonacoEditorInstance \| null` | 获取当前编辑器实例 |
793
+ | `getDiffEditorView` | `() => MonacoDiffEditorInstance \| null` | 获取当前 Diff 编辑器实例 |
794
+ | `getDiffModels` | `() => DiffModels` | 获取 Diff 两侧模型 |
795
+ | `getMonacoInstance` | `() => typeof monaco` | 获取 Monaco 模块实例 |
796
+ | `setUpdateThrottleMs` | `(ms: number) => void` | 动态调整 `updateCode` 的时间节流 |
797
+ | `getUpdateThrottleMs` | `() => number` | 获取当前 `updateCode` 节流值 |
798
+ | `getCode` | `() => MonacoCodeValue` | **获取编辑器当前代码**<br>- 普通编辑器返回 `string`<br>- Diff 编辑器返回 `{ original, modified }`<br>- 无编辑器返回 `null`<br>**用途**:获取用户手动编辑后的最新代码或程序更新后的内容 |
799
+ | `appendOriginal` | `(appendText: string, codeLanguage?: string) => void` | 在 original 末尾追加(显式流式) |
800
+ | `appendModified` | `(appendText: string, codeLanguage?: string) => void` | 在 modified 末尾追加(显式流式) |
732
801
 
733
802
  #### 支持的主题
734
803
 
@@ -1,17 +1,35 @@
1
- import * as monaco_editor0 from "monaco-editor";
2
- import * as monaco$1 from "monaco-editor";
3
1
  import { Highlighter, SpecialTheme, ThemeInput } from "shiki";
4
- import * as _monaco from "monaco-editor/esm/vs/editor/editor.api";
2
+ import * as monaco_editor0 from "monaco-editor";
3
+ import * as monaco from "monaco-editor";
5
4
 
6
- //#region rolldown:runtime
7
- //#endregion
8
5
  //#region src/type.d.ts
9
6
  type ShikiHighlighter = Highlighter | any;
10
- type MonacoEditorInstance = monaco$1.editor.IStandaloneCodeEditor;
11
- type MonacoDiffEditorInstance = monaco$1.editor.IStandaloneDiffEditor;
7
+ type MonacoEditorInstance = monaco.editor.IStandaloneCodeEditor;
8
+ type MonacoDiffEditorInstance = monaco.editor.IStandaloneDiffEditor;
12
9
  type MonacoTheme = 'andromeeda' | 'aurora-x' | 'ayu-dark' | 'catppuccin-frappe' | 'catppuccin-latte' | 'catppuccin-macchiato' | 'catppuccin-mocha' | 'dark-plus' | 'dracula' | 'dracula-soft' | 'everforest-dark' | 'everforest-light' | 'github-dark' | 'github-dark-default' | 'github-dark-dimmed' | 'github-dark-high-contrast' | 'github-light' | 'github-light-default' | 'github-light-high-contrast' | 'gruvbox-dark-hard' | 'gruvbox-dark-medium' | 'gruvbox-dark-soft' | 'gruvbox-light-hard' | 'gruvbox-light-medium' | 'gruvbox-light-soft' | 'houston' | 'kanagawa-dragon' | 'kanagawa-lotus' | 'kanagawa-wave' | 'laserwave' | 'light-plus' | 'material-theme' | 'material-theme-darker' | 'material-theme-lighter' | 'material-theme-ocean' | 'material-theme-palenight' | 'min-dark' | 'min-light' | 'monokai' | 'night-owl' | 'nord' | 'one-dark-pro' | 'one-light' | 'plastic' | 'poimandres' | 'red' | 'rose-pine' | 'rose-pine-dawn' | 'rose-pine-moon' | 'slack-dark' | 'slack-ochin' | 'snazzy-light' | 'solarized-dark' | 'solarized-light' | 'synthwave-84' | 'tokyo-night' | 'vesper' | 'vitesse-black' | 'vitesse-dark' | 'vitesse-light' | ThemeInput | string | SpecialTheme;
13
10
  type MonacoLanguage = 'abap' | 'actionscript-3' | 'ada' | 'angular-html' | 'angular-ts' | 'apache' | 'apex' | 'apl' | 'applescript' | 'ara' | 'asciidoc' | 'asm' | 'astro' | 'awk' | 'ballerina' | 'bat' | 'beancount' | 'berry' | 'bibtex' | 'bicep' | 'blade' | 'bsl' | 'c' | 'cadence' | 'cairo' | 'clarity' | 'clojure' | 'cmake' | 'cobol' | 'codeowners' | 'codeql' | 'coffee' | 'common-lisp' | 'coq' | 'cpp' | 'crystal' | 'csharp' | 'css' | 'csv' | 'cue' | 'cypher' | 'd' | 'dart' | 'dax' | 'desktop' | 'diff' | 'docker' | 'dotenv' | 'dream-maker' | 'edge' | 'elixir' | 'elm' | 'emacs-lisp' | 'erb' | 'erlang' | 'fennel' | 'fish' | 'fluent' | 'fortran-fixed-form' | 'fortran-free-form' | 'fsharp' | 'gdresource' | 'gdscript' | 'gdshader' | 'genie' | 'gherkin' | 'git-commit' | 'git-rebase' | 'gleam' | 'glimmer-js' | 'glimmer-ts' | 'glsl' | 'gnuplot' | 'go' | 'graphql' | 'groovy' | 'hack' | 'haml' | 'handlebars' | 'haskell' | 'haxe' | 'hcl' | 'hjson' | 'hlsl' | 'html' | 'html-derivative' | 'http' | 'hxml' | 'hy' | 'imba' | 'ini' | 'java' | 'javascript' | 'jinja' | 'jison' | 'json' | 'json5' | 'jsonc' | 'jsonl' | 'jsonnet' | 'jssm' | 'jsx' | 'julia' | 'kotlin' | 'kusto' | 'latex' | 'lean' | 'less' | 'liquid' | 'llvm' | 'log' | 'logo' | 'lua' | 'luau' | 'make' | 'markdown' | 'marko' | 'matlab' | 'mdc' | 'mdx' | 'mermaid' | 'mipsasm' | 'mojo' | 'move' | 'narrat' | 'nextflow' | 'nginx' | 'nim' | 'nix' | 'nushell' | 'objective-c' | 'objective-cpp' | 'ocaml' | 'pascal' | 'perl' | 'php' | 'plsql' | 'po' | 'polar' | 'postcss' | 'powerquery' | 'powershell' | 'prisma' | 'prolog' | 'proto' | 'pug' | 'puppet' | 'purescript' | 'python' | 'qml' | 'qmldir' | 'qss' | 'r' | 'racket' | 'raku' | 'razor' | 'reg' | 'regexp' | 'rel' | 'riscv' | 'rst' | 'ruby' | 'rust' | 'sas' | 'sass' | 'scala' | 'scheme' | 'scss' | 'sdbl' | 'shaderlab' | 'shellscript' | 'shellsession' | 'smalltalk' | 'solidity' | 'soy' | 'sparql' | 'splunk' | 'sql' | 'ssh-config' | 'stata' | 'stylus' | 'svelte' | 'swift' | 'system-verilog' | 'systemd' | 'talonscript' | 'tasl' | 'tcl' | 'templ' | 'terraform' | 'tex' | 'toml' | 'ts-tags' | 'tsv' | 'tsx' | 'turtle' | 'twig' | 'typescript' | 'typespec' | 'typst' | 'v' | 'vala' | 'vb' | 'verilog' | 'vhdl' | 'viml' | 'vue' | 'vue-html' | 'vyper' | 'wasm' | 'wenyan' | 'wgsl' | 'wikitext' | 'wit' | 'wolfram' | 'xml' | 'xsl' | 'yaml' | 'zenscript' | 'zig' | string;
14
- interface MonacoOptions extends monaco$1.editor.IStandaloneEditorConstructionOptions {
11
+ type DiffHideUnchangedRegions = boolean | NonNullable<monaco.editor.IDiffEditorConstructionOptions['hideUnchangedRegions']>;
12
+ type DiffLineStyle = 'background' | 'bar';
13
+ type DiffAppearance = 'auto' | 'light' | 'dark';
14
+ type DiffUnchangedRegionStyle = 'line-info' | 'line-info-basic' | 'metadata' | 'simple';
15
+ interface DiffModels {
16
+ original: monaco.editor.ITextModel | null;
17
+ modified: monaco.editor.ITextModel | null;
18
+ }
19
+ interface DiffModelPair {
20
+ original: monaco.editor.ITextModel;
21
+ modified: monaco.editor.ITextModel;
22
+ }
23
+ interface DiffModelTransitionOptions {
24
+ codeLanguage?: MonacoLanguage;
25
+ preserveViewState?: boolean;
26
+ }
27
+ interface DiffCodeValue {
28
+ original: string;
29
+ modified: string;
30
+ }
31
+ type MonacoCodeValue = string | DiffCodeValue | null;
32
+ interface MonacoOptions extends monaco.editor.IStandaloneEditorConstructionOptions, monaco.editor.IDiffEditorConstructionOptions {
15
33
  MAX_HEIGHT?: number | string;
16
34
  readOnly?: boolean;
17
35
  themes?: MonacoTheme[];
@@ -53,7 +71,36 @@ interface MonacoOptions extends monaco$1.editor.IStandaloneEditorConstructionOpt
53
71
  *
54
72
  * Default: `true`
55
73
  */
56
- diffHideUnchangedRegions?: boolean | NonNullable<monaco$1.editor.IDiffEditorConstructionOptions['hideUnchangedRegions']>;
74
+ diffHideUnchangedRegions?: DiffHideUnchangedRegions;
75
+ /**
76
+ * Controls how changed lines are visually emphasized in the diff editor.
77
+ * - `background`: richer filled blocks for added/removed lines
78
+ * - `bar`: subtler fill with stronger leading bars, closer to review UIs
79
+ *
80
+ * Default: `background`
81
+ */
82
+ diffLineStyle?: DiffLineStyle;
83
+ /**
84
+ * Controls the overall chrome appearance of the diff editor shell.
85
+ * - `auto`: infer light/dark appearance from the active Monaco theme
86
+ * - `light`: force light diff chrome
87
+ * - `dark`: force dark diff chrome
88
+ *
89
+ * Token colors still follow the active Monaco/Shiki theme.
90
+ *
91
+ * Default: `auto`
92
+ */
93
+ diffAppearance?: DiffAppearance;
94
+ /**
95
+ * Controls how collapsed unchanged regions are rendered in the diff editor.
96
+ * - `line-info`: line-info bars with line-number-width reveal buttons
97
+ * - `line-info-basic`: legacy line-info bars with full-width reveal rail
98
+ * - `metadata`: unified-diff-style hunk metadata such as `@@ -59,9 +59,11 @@`
99
+ * - `simple`: minimal gray placeholder bar without text
100
+ *
101
+ * Default: `line-info`
102
+ */
103
+ diffUnchangedRegionStyle?: DiffUnchangedRegionStyle;
57
104
  /**
58
105
  * Enable hover actions for each diff hunk split part (upper/lower):
59
106
  * local `revert` and `stage`.
@@ -69,7 +116,7 @@ interface MonacoOptions extends monaco$1.editor.IStandaloneEditorConstructionOpt
69
116
  * Optional interception callback for hunk hover actions.
70
117
  * Return `false` to prevent the built-in model edit behavior.
71
118
  */
72
- onDiffHunkAction?: (context: DiffHunkActionContext) => void | boolean;
119
+ onDiffHunkAction?: (context: DiffHunkActionContext) => void | boolean | Promise<void | boolean>;
73
120
  /**
74
121
  * Debounce time (ms) to coalesce multiple reveal requests into a single
75
122
  * reveal. Useful for streaming/append scenarios. Default: 75
@@ -117,7 +164,7 @@ interface MonacoOptions extends monaco$1.editor.IStandaloneEditorConstructionOpt
117
164
  * library will fall back to full `setValue` instead of attempting minimal edit.
118
165
  */
119
166
  minimalEditMaxChangeRatio?: number;
120
- onBeforeCreate?: (monaco: typeof monaco_editor0) => monaco$1.IDisposable[];
167
+ onBeforeCreate?: (monaco: typeof monaco_editor0) => monaco.IDisposable[];
121
168
  /**
122
169
  * Optional callback that is invoked after a theme change has been applied.
123
170
  * This callback will be awaited when possible so callers can track completion
@@ -135,9 +182,35 @@ type DiffHunkSide = 'upper' | 'lower';
135
182
  interface DiffHunkActionContext {
136
183
  action: DiffHunkActionKind;
137
184
  side: DiffHunkSide;
138
- lineChange: monaco$1.editor.ILineChange;
139
- originalModel: monaco$1.editor.ITextModel;
140
- modifiedModel: monaco$1.editor.ITextModel;
185
+ lineChange: monaco.editor.ILineChange;
186
+ originalModel: monaco.editor.ITextModel;
187
+ modifiedModel: monaco.editor.ITextModel;
188
+ }
189
+ interface UseMonacoReturn {
190
+ createEditor: (container: HTMLElement, code: string, language: string) => Promise<monaco.editor.IStandaloneCodeEditor>;
191
+ createDiffEditor: (container: HTMLElement, originalCode: string, modifiedCode: string, language: string) => Promise<monaco.editor.IStandaloneDiffEditor>;
192
+ cleanupEditor: () => void;
193
+ safeClean: () => void;
194
+ updateCode: (newCode: string, codeLanguage: string) => void;
195
+ appendCode: (appendText: string, codeLanguage?: string) => void;
196
+ updateDiff: (originalCode: string, modifiedCode: string, codeLanguage?: string) => void;
197
+ updateOriginal: (newCode: string, codeLanguage?: string) => void;
198
+ updateModified: (newCode: string, codeLanguage?: string) => void;
199
+ appendOriginal: (appendText: string, codeLanguage?: string) => void;
200
+ appendModified: (appendText: string, codeLanguage?: string) => void;
201
+ setDiffModels: (models: DiffModelPair, options?: DiffModelTransitionOptions) => Promise<void>;
202
+ setTheme: (theme: MonacoTheme, force?: boolean) => Promise<void>;
203
+ refreshDiffPresentation: () => void;
204
+ setLanguage: (language: MonacoLanguage) => void;
205
+ getCurrentTheme: () => string;
206
+ getEditor: () => typeof monaco.editor;
207
+ getEditorView: () => monaco.editor.IStandaloneCodeEditor | null;
208
+ getDiffEditorView: () => monaco.editor.IStandaloneDiffEditor | null;
209
+ getDiffModels: () => DiffModels;
210
+ getMonacoInstance: () => typeof monaco;
211
+ setUpdateThrottleMs: (ms: number) => void;
212
+ getUpdateThrottleMs: () => number;
213
+ getCode: () => MonacoCodeValue;
141
214
  }
142
215
  //#endregion
143
216
  //#region src/code.detect.d.ts
@@ -172,12 +245,6 @@ declare function detectLanguage(code: string, additionalLanguages?: LanguageDefi
172
245
  //#endregion
173
246
  //#region src/constant.d.ts
174
247
  declare const defaultRevealDebounceMs = 75;
175
- declare namespace monaco_shim_d_exports {
176
- export { monaco as default };
177
- }
178
- import * as import_monaco_editor_esm_vs_editor_editor_api from "monaco-editor/esm/vs/editor/editor.api";
179
- __reExport(monaco_shim_d_exports, import_monaco_editor_esm_vs_editor_editor_api);
180
- declare const monaco: typeof _monaco;
181
248
  //#endregion
182
249
  //#region src/utils/registerMonacoThemes.d.ts
183
250
  /**
@@ -238,7 +305,9 @@ declare function registerMonacoThemes(themes: (ThemeInput | string | SpecialThem
238
305
  * updateModified: (newCode: string, codeLanguage?: string) => void,
239
306
  * appendOriginal: (appendText: string, codeLanguage?: string) => void,
240
307
  * appendModified: (appendText: string, codeLanguage?: string) => void,
308
+ * setDiffModels: (models: DiffModelPair, options?: DiffModelTransitionOptions) => Promise<void>,
241
309
  * setTheme: (theme: MonacoTheme) => Promise<void>,
310
+ * refreshDiffPresentation: () => void,
242
311
  * setLanguage: (language: MonacoLanguage) => void,
243
312
  * getCurrentTheme: () => string,
244
313
  * getEditor: () => typeof monaco.editor,
@@ -258,7 +327,9 @@ declare function registerMonacoThemes(themes: (ThemeInput | string | SpecialThem
258
327
  * @property {Function} updateModified - 仅更新 Diff 的 modified 内容(增量更新)
259
328
  * @property {Function} appendOriginal - 在 Diff 的 original 末尾追加(显式流式场景)
260
329
  * @property {Function} appendModified - 在 Diff 的 modified 末尾追加(显式流式场景)
330
+ * @property {Function} setDiffModels - 切换为一对新的 Diff models;当内容未变化时自动走保留视图状态的无抖动路径
261
331
  * @property {Function} setTheme - 切换编辑器主题,返回 Promise,在主题应用完成时 resolve
332
+ * @property {Function} refreshDiffPresentation - 在不 remount 的情况下,重算 diff chrome / unchanged overlay 的表现层
262
333
  * @property {Function} setLanguage - 切换编辑器语言
263
334
  * @property {Function} getCurrentTheme - 获取当前主题名称
264
335
  * @property {Function} getEditor - 获取 Monaco 的静态 editor 对象(用于静态方法调用)
@@ -289,35 +360,6 @@ declare function registerMonacoThemes(themes: (ThemeInput | string | SpecialThem
289
360
  * setTheme('vitesse-light')
290
361
  * ```
291
362
  */
292
- declare function useMonaco(monacoOptions?: MonacoOptions): {
293
- createEditor: (container: HTMLElement, code: string, language: string) => Promise<monaco_shim_d_exports.editor.IStandaloneCodeEditor>;
294
- createDiffEditor: (container: HTMLElement, originalCode: string, modifiedCode: string, language: string) => Promise<monaco_shim_d_exports.editor.IStandaloneDiffEditor>;
295
- cleanupEditor: () => void;
296
- safeClean(): void;
297
- updateCode: (newCode: string, codeLanguage: string) => void;
298
- appendCode: (appendText: string, codeLanguage?: string) => void;
299
- updateDiff: (originalCode: string, modifiedCode: string, codeLanguage?: string) => void;
300
- updateOriginal: (newCode: string, codeLanguage?: string) => void;
301
- updateModified: (newCode: string, codeLanguage?: string) => void;
302
- appendOriginal: (appendText: string, codeLanguage?: string) => void;
303
- appendModified: (appendText: string, codeLanguage?: string) => void;
304
- setTheme: (theme: MonacoTheme, force?: boolean) => Promise<void>;
305
- setLanguage(language: MonacoLanguage): void;
306
- getCurrentTheme(): string;
307
- getEditor(): typeof monaco_shim_d_exports.editor;
308
- getEditorView(): monaco_shim_d_exports.editor.IStandaloneCodeEditor | null;
309
- getDiffEditorView(): monaco_shim_d_exports.editor.IStandaloneDiffEditor | null;
310
- getDiffModels(): {
311
- original: monaco_shim_d_exports.editor.ITextModel | null;
312
- modified: monaco_shim_d_exports.editor.ITextModel | null;
313
- };
314
- getMonacoInstance(): typeof monaco_shim_d_exports;
315
- setUpdateThrottleMs: (ms: number) => void;
316
- getUpdateThrottleMs: () => number;
317
- getCode(): string | {
318
- original: string;
319
- modified: string;
320
- } | null;
321
- };
363
+ declare function useMonaco(monacoOptions?: MonacoOptions): UseMonacoReturn;
322
364
  //#endregion
323
- export { DiffHunkActionContext, DiffHunkActionKind, DiffHunkSide, MonacoDiffEditorInstance, MonacoEditorInstance, MonacoLanguage, MonacoOptions, MonacoTheme, RevealStrategy, ShikiHighlighter, clearHighlighterCache, defaultRevealDebounceMs, detectLanguage, getOrCreateHighlighter, registerMonacoThemes, useMonaco };
365
+ export { DiffAppearance, DiffCodeValue, DiffHideUnchangedRegions, DiffHunkActionContext, DiffHunkActionKind, DiffHunkSide, DiffLineStyle, DiffModelPair, DiffModelTransitionOptions, DiffModels, DiffUnchangedRegionStyle, MonacoCodeValue, MonacoDiffEditorInstance, MonacoEditorInstance, MonacoLanguage, MonacoOptions, MonacoTheme, RevealStrategy, ShikiHighlighter, UseMonacoReturn, clearHighlighterCache, defaultRevealDebounceMs, detectLanguage, getOrCreateHighlighter, registerMonacoThemes, useMonaco };