stream-monaco 0.0.19 → 0.0.20
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 +163 -58
- package/README.zh-CN.md +135 -66
- package/dist/{index.base-9QTN8hPV.d.cts → index.base-Bt_RWV_F.d.ts} +93 -51
- package/dist/{index.base-D0lzInae.d.ts → index.base-DMJ2aLjO.d.cts} +93 -50
- package/dist/index.cjs +1 -1
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +1 -1
- package/dist/index.legacy.cjs +1 -1
- package/dist/index.legacy.d.cts +2 -2
- package/dist/index.legacy.d.ts +2 -2
- package/dist/index.legacy.js +1 -1
- package/dist/{preloadMonacoWorkers.shared-DMvZ1HUs.cjs → preloadMonacoWorkers.shared-B2kXtXTi.cjs} +2307 -276
- package/dist/{preloadMonacoWorkers.shared-DQ17-Bwz.js → preloadMonacoWorkers.shared-C-OxtyGI.js} +2331 -277
- package/package.json +12 -1
- package/dist/chunk-CHLpw0oG.js +0 -25
package/README.md
CHANGED
|
@@ -37,6 +37,7 @@ The package exports helpers around theme/highlighter for advanced use:
|
|
|
37
37
|
- `getOrCreateHighlighter(themes, languages): Promise<Highlighter>` — get or create a highlighter (managed by internal cache). If you need to call `codeToHtml` or `setTheme` manually, use this and handle loading/errors.
|
|
38
38
|
|
|
39
39
|
Note:
|
|
40
|
+
|
|
40
41
|
- If the target theme is already included in the `themes` you passed to `useMonaco()`, calling `monaco.editor.setTheme(themeName)` is fine.
|
|
41
42
|
- If you switch to a theme that was not pre-registered (e.g. dynamic theme name like `andromeeda`), prefer `await setTheme(themeName)` from `useMonaco()`. It will ensure the theme is registered, and when possible it will also try to `loadTheme` on the underlying Shiki highlighter to avoid "Theme not found, you may need to load it first" errors.
|
|
42
43
|
|
|
@@ -44,49 +45,98 @@ Config: `useMonaco()` does not auto-sync an external Shiki highlighter; if you n
|
|
|
44
45
|
|
|
45
46
|
### API Reference
|
|
46
47
|
|
|
47
|
-
#### useMonaco()
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
48
|
+
#### useMonaco(options?)
|
|
49
|
+
|
|
50
|
+
##### Parameters
|
|
51
|
+
|
|
52
|
+
| Parameter | Type | Default | Description |
|
|
53
|
+
| --------------------------- | ------------------------------------------------------------ | ----------------------------------- | ------------------------------------------------------------------------------------------ |
|
|
54
|
+
| `MAX_HEIGHT` | `number \| string` | `500` | Maximum editor height |
|
|
55
|
+
| `readOnly` | `boolean` | `true` | Whether the editor is read-only |
|
|
56
|
+
| `themes` | `MonacoTheme[]` | `['vitesse-dark', 'vitesse-light']` | Theme list; should include at least one dark and one light theme |
|
|
57
|
+
| `languages` | `MonacoLanguage[]` | built-in default language list | Languages to register |
|
|
58
|
+
| `theme` | `string` | - | Initial theme name |
|
|
59
|
+
| `isCleanOnBeforeCreate` | `boolean` | `true` | Whether to dispose previously registered resources before creating a new editor |
|
|
60
|
+
| `onBeforeCreate` | `function` | - | Hook called before editor creation |
|
|
61
|
+
| `autoScrollOnUpdate` | `boolean` | `true` | Auto-scroll when content updates and the viewport is already near the bottom |
|
|
62
|
+
| `autoScrollInitial` | `boolean` | `true` | Whether auto-scroll starts enabled |
|
|
63
|
+
| `autoScrollThresholdPx` | `number` | `32` | Pixel threshold for considering the viewport "near bottom" |
|
|
64
|
+
| `autoScrollThresholdLines` | `number` | `2` | Line-based threshold for considering the viewport "near bottom" |
|
|
65
|
+
| `diffAutoScroll` | `boolean` | `true` | Whether diff auto-scroll is enabled for the modified side |
|
|
66
|
+
| `diffHideUnchangedRegions` | `boolean \| object` | `true` | Fold unchanged regions in diff mode; accepts Monaco `hideUnchangedRegions` config too |
|
|
67
|
+
| `diffLineStyle` | `'background' \| 'bar'` | `'background'` | Controls whether changed lines are emphasized more as filled blocks or review-style bars |
|
|
68
|
+
| `diffAppearance` | `'auto' \| 'light' \| 'dark'` | `'auto'` | Controls the diff shell chrome appearance while token colors still follow the active theme |
|
|
69
|
+
| `diffUnchangedRegionStyle` | `'line-info' \| 'line-info-basic' \| 'metadata' \| 'simple'` | `'line-info'` | Controls how collapsed unchanged regions are rendered |
|
|
70
|
+
| `diffHunkActionsOnHover` | `boolean` | `false` | Enables split upper/lower hunk hover actions: `Revert` / `Stage` |
|
|
71
|
+
| `diffHunkHoverHideDelayMs` | `number` | `160` | Hide delay for hunk hover action widgets |
|
|
72
|
+
| `onDiffHunkAction` | `function` | - | Hunk action callback; return `false` to skip built-in edits |
|
|
73
|
+
| `revealDebounceMs` | `number` | `75` | Debounce for auto-reveal during streaming updates |
|
|
74
|
+
| `revealStrategy` | `'bottom' \| 'centerIfOutside' \| 'center'` | `'centerIfOutside'` | Reveal strategy used when auto-scrolling |
|
|
75
|
+
| `revealBatchOnIdleMs` | `number \| undefined` | - | Final idle-time reveal window for append-heavy scenarios |
|
|
76
|
+
| `updateThrottleMs` | `number` | `50` | Time-based throttle for `updateCode` |
|
|
77
|
+
| `diffUpdateThrottleMs` | `number` | `50` | Time-based throttle for diff streaming updates |
|
|
78
|
+
| `minimalEditMaxChars` | `number` | built-in constant | Fallback to `setValue` when documents are too large for minimal-edit diffing |
|
|
79
|
+
| `minimalEditMaxChangeRatio` | `number` | built-in constant | Fallback to `setValue` when the change ratio is too large |
|
|
80
|
+
|
|
81
|
+
`MonacoOptions` also includes Monaco's native editor and diff-editor construction options, so you can pass options such as `renderSideBySide`, `ignoreTrimWhitespace`, `originalEditable`, or `enableSplitViewResizing` directly.
|
|
82
|
+
|
|
83
|
+
##### Returns
|
|
84
|
+
|
|
85
|
+
| Method / property | Type | Description |
|
|
86
|
+
| ------------------------- | --------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------- |
|
|
87
|
+
| `createEditor` | `(container: HTMLElement, code: string, language: string) => Promise<MonacoEditorInstance>` | Create and mount a standalone editor |
|
|
88
|
+
| `createDiffEditor` | `(container: HTMLElement, original: string, modified: string, language: string) => Promise<MonacoDiffEditorInstance>` | Create and mount a diff editor |
|
|
89
|
+
| `cleanupEditor` | `() => void` | Dispose editor instances and cleanup resources |
|
|
90
|
+
| `safeClean` | `() => void` | Cancel pending update queues/RAFs without fully tearing down the integration |
|
|
91
|
+
| `updateCode` | `(newCode: string, codeLanguage: string) => void` | Update single-editor content and language |
|
|
92
|
+
| `appendCode` | `(appendText: string, codeLanguage?: string) => void` | Append to the single editor, optimized for streaming |
|
|
93
|
+
| `updateDiff` | `(original: string, modified: string, codeLanguage?: string) => void` | Update both sides of a diff editor |
|
|
94
|
+
| `updateOriginal` | `(newCode: string, codeLanguage?: string) => void` | Update only the original side |
|
|
95
|
+
| `updateModified` | `(newCode: string, codeLanguage?: string) => void` | Update only the modified side |
|
|
96
|
+
| `appendOriginal` | `(appendText: string, codeLanguage?: string) => void` | Append to the original side |
|
|
97
|
+
| `appendModified` | `(appendText: string, codeLanguage?: string) => void` | Append to the modified side |
|
|
98
|
+
| `setDiffModels` | `(models: DiffModelPair, options?: DiffModelTransitionOptions) => Promise<void>` | Swap the whole diff model pair in place; same-content swaps prewarm Monaco's diff view model and preserve view state by default |
|
|
99
|
+
| `setTheme` | `(theme: MonacoTheme, force?: boolean) => Promise<void>` | Switch editor theme; `force=true` re-applies even if the theme is already active |
|
|
100
|
+
| `refreshDiffPresentation` | `() => void` | Recompute diff chrome / unchanged overlay presentation without remounting |
|
|
101
|
+
| `setLanguage` | `(language: MonacoLanguage) => void` | Switch editor language |
|
|
102
|
+
| `getCurrentTheme` | `() => string` | Get the current theme name |
|
|
103
|
+
| `getEditor` | `() => typeof monaco.editor` | Get Monaco's static editor API |
|
|
104
|
+
| `getEditorView` | `() => MonacoEditorInstance \| null` | Get the current standalone editor instance |
|
|
105
|
+
| `getDiffEditorView` | `() => MonacoDiffEditorInstance \| null` | Get the current diff editor instance |
|
|
106
|
+
| `getDiffModels` | `() => DiffModels` | Get both diff models |
|
|
107
|
+
| `getMonacoInstance` | `() => typeof monaco` | Get the Monaco module instance |
|
|
108
|
+
| `setUpdateThrottleMs` | `(ms: number) => void` | Change `updateCode` throttling at runtime |
|
|
109
|
+
| `getUpdateThrottleMs` | `() => number` | Get the current `updateCode` throttle value |
|
|
110
|
+
| `getCode` | `() => MonacoCodeValue` | Get the latest code value from the current editor or diff editor |
|
|
111
|
+
|
|
112
|
+
##### Exported TypeScript helpers
|
|
113
|
+
|
|
114
|
+
The package exports named types for diff integration too:
|
|
115
|
+
|
|
116
|
+
- `UseMonacoReturn`
|
|
117
|
+
- `MonacoOptions`
|
|
118
|
+
- `MonacoTheme`
|
|
119
|
+
- `MonacoLanguage`
|
|
120
|
+
- `DiffHideUnchangedRegions`
|
|
121
|
+
- `DiffLineStyle`
|
|
122
|
+
- `DiffAppearance`
|
|
123
|
+
- `DiffUnchangedRegionStyle`
|
|
124
|
+
- `DiffModels`
|
|
125
|
+
- `DiffModelPair`
|
|
126
|
+
- `DiffModelTransitionOptions`
|
|
127
|
+
- `DiffCodeValue`
|
|
128
|
+
- `MonacoCodeValue`
|
|
129
|
+
- `DiffHunkActionContext`
|
|
130
|
+
|
|
131
|
+
For a more complete integration walkthrough, see [Diff Integration Guide](docs/diff-integration.md).
|
|
84
132
|
|
|
85
133
|
#### Diff streaming highlight tip
|
|
86
134
|
|
|
87
135
|
Monaco's diff computation is async and cancels/restarts when models change. If you stream updates too frequently (e.g. per token / every frame), the diff may only finish once streaming stops, so the difference highlights appear "at the end".
|
|
88
136
|
|
|
89
|
-
- Set `diffUpdateThrottleMs`
|
|
137
|
+
- Set `diffUpdateThrottleMs` to let the diff worker complete intermediate computations during streaming.
|
|
138
|
+
- The library defaults to `50ms`.
|
|
139
|
+
- When `diffHideUnchangedRegions` is enabled, unchanged-region folding is deferred until diff streaming goes idle to avoid collapsing and re-expanding while content is still arriving.
|
|
90
140
|
- Set it to `0` to restore pure RAF batching (most responsive, but may delay diff highlights under heavy streaming).
|
|
91
141
|
|
|
92
142
|
### Install
|
|
@@ -162,12 +212,22 @@ export function MonacoEditor() {
|
|
|
162
212
|
})
|
|
163
213
|
|
|
164
214
|
useEffect(() => {
|
|
165
|
-
if (containerRef.current)
|
|
166
|
-
createEditor(
|
|
215
|
+
if (containerRef.current) {
|
|
216
|
+
createEditor(
|
|
217
|
+
containerRef.current,
|
|
218
|
+
'console.log("Hello, Monaco!")',
|
|
219
|
+
'typescript',
|
|
220
|
+
)
|
|
221
|
+
}
|
|
167
222
|
return () => cleanupEditor()
|
|
168
223
|
}, [])
|
|
169
224
|
|
|
170
|
-
return
|
|
225
|
+
return (
|
|
226
|
+
<div
|
|
227
|
+
ref={containerRef}
|
|
228
|
+
style={{ height: 500, border: '1px solid #e0e0e0' }}
|
|
229
|
+
/>
|
|
230
|
+
)
|
|
171
231
|
}
|
|
172
232
|
```
|
|
173
233
|
|
|
@@ -262,18 +322,10 @@ function getCurrentCode() {
|
|
|
262
322
|
<template>
|
|
263
323
|
<div>
|
|
264
324
|
<div class="controls">
|
|
265
|
-
<button @click="switchTheme('github-dark')">
|
|
266
|
-
|
|
267
|
-
</button>
|
|
268
|
-
<button @click="
|
|
269
|
-
Light
|
|
270
|
-
</button>
|
|
271
|
-
<button @click="switchLanguage('typescript')">
|
|
272
|
-
TypeScript
|
|
273
|
-
</button>
|
|
274
|
-
<button @click="switchLanguage('python')">
|
|
275
|
-
Python
|
|
276
|
-
</button>
|
|
325
|
+
<button @click="switchTheme('github-dark')">Dark</button>
|
|
326
|
+
<button @click="switchTheme('github-light')">Light</button>
|
|
327
|
+
<button @click="switchLanguage('typescript')">TypeScript</button>
|
|
328
|
+
<button @click="switchLanguage('python')">Python</button>
|
|
277
329
|
</div>
|
|
278
330
|
<div ref="editorContainer" class="editor" />
|
|
279
331
|
</div>
|
|
@@ -387,8 +439,17 @@ onMounted(async () => {
|
|
|
387
439
|
Diff UX options:
|
|
388
440
|
|
|
389
441
|
- `diffHideUnchangedRegions` (default `true`): fold unchanged ranges (can pass Monaco `hideUnchangedRegions` object).
|
|
442
|
+
- `diffLineStyle` (default `background`): choose the changed-line emphasis style. Use `bar` for a subtler review-style leading bar treatment.
|
|
443
|
+
- `diffAppearance` (default `auto`): controls the diff shell chrome; use `light` / `dark` to force the surface style while keeping token colors theme-driven.
|
|
444
|
+
- `diffUnchangedRegionStyle` (default `line-info`): choose collapsed unchanged-region rendering: `line-info`, `line-info-basic`, and `metadata` use compact 32px rows, while `line-info-basic` keeps the wider legacy rail and `simple` uses a tighter 28px row.
|
|
390
445
|
- `diffHunkActionsOnHover` (default `false`): explicitly set `true` to enable split upper/lower `Revert` and `Stage` on hunk hover.
|
|
391
446
|
- `onDiffHunkAction(context)` (optional): return `false` to intercept and skip built-in model edits.
|
|
447
|
+
- Built-in `Revert` / `Stage` only edit Monaco models locally. They do not run `git revert`, `git add`, or `git stash` unless you intercept `onDiffHunkAction` and connect your own backend flow.
|
|
448
|
+
|
|
449
|
+
Full integration guide:
|
|
450
|
+
|
|
451
|
+
- [Diff Integration Guide](docs/diff-integration.md)
|
|
452
|
+
- exported TS helpers include `UseMonacoReturn`, `DiffLineStyle`, `DiffAppearance`, `DiffUnchangedRegionStyle`, `DiffModels`, and `DiffHunkActionContext`
|
|
392
453
|
|
|
393
454
|
Example 1: enable unchanged folding + hover Revert/Stage
|
|
394
455
|
|
|
@@ -403,13 +464,14 @@ const { createDiffEditor } = useMonaco({
|
|
|
403
464
|
minimumLineCount: 4,
|
|
404
465
|
revealLineCount: 2,
|
|
405
466
|
},
|
|
467
|
+
diffLineStyle: 'bar',
|
|
406
468
|
diffHunkActionsOnHover: true,
|
|
407
469
|
})
|
|
408
470
|
|
|
409
471
|
await createDiffEditor(container, original, modified, 'typescript')
|
|
410
472
|
```
|
|
411
473
|
|
|
412
|
-
Example 2: fully intercept Revert/Stage and handle your own stash/patch flow
|
|
474
|
+
Example 2: fully intercept Revert/Stage and handle your own Git/stash/patch flow
|
|
413
475
|
|
|
414
476
|
```ts
|
|
415
477
|
useMonaco({
|
|
@@ -439,6 +501,47 @@ useMonaco({
|
|
|
439
501
|
})
|
|
440
502
|
```
|
|
441
503
|
|
|
504
|
+
Example 3: backend returns refreshed file contents, then the client calls `updateDiff(...)`
|
|
505
|
+
|
|
506
|
+
```ts
|
|
507
|
+
const monaco = useMonaco({
|
|
508
|
+
diffHideUnchangedRegions: true,
|
|
509
|
+
diffHunkActionsOnHover: true,
|
|
510
|
+
onDiffHunkAction: async (ctx) => {
|
|
511
|
+
const response = await fetch('/api/git/hunks/apply', {
|
|
512
|
+
method: 'POST',
|
|
513
|
+
headers: { 'content-type': 'application/json' },
|
|
514
|
+
body: JSON.stringify({
|
|
515
|
+
action: ctx.action,
|
|
516
|
+
side: ctx.side,
|
|
517
|
+
range: ctx.lineChange,
|
|
518
|
+
original: ctx.originalModel.getValue(),
|
|
519
|
+
modified: ctx.modifiedModel.getValue(),
|
|
520
|
+
}),
|
|
521
|
+
})
|
|
522
|
+
|
|
523
|
+
const next = await response.json()
|
|
524
|
+
monaco.updateDiff(next.original, next.modified, 'typescript')
|
|
525
|
+
return false
|
|
526
|
+
},
|
|
527
|
+
})
|
|
528
|
+
```
|
|
529
|
+
|
|
530
|
+
Important:
|
|
531
|
+
|
|
532
|
+
- Hover `Revert` is hunk-level undo, not `git revert <commit>`.
|
|
533
|
+
- Hover `Stage` is closer to `git add -p` / `git apply --cached`.
|
|
534
|
+
- If you want a stash flow, treat `onDiffHunkAction` as a patch-intent callback and hand the selected half-hunk to your backend stash or patch queue.
|
|
535
|
+
- If your backend returns refreshed file contents, `updateDiff(...)` is the most direct way to reflect the Git-applied result in the diff UI. The repo includes `pnpm run validate:diff-hunk-update-diff-flow` for that pattern.
|
|
536
|
+
- See [Diff Integration Guide](docs/diff-integration.md) for a concrete Git binding pattern.
|
|
537
|
+
|
|
538
|
+
Visual review helpers:
|
|
539
|
+
|
|
540
|
+
- `pnpm run shot:diff-ux -- background /tmp/stream-monaco-diff-reference.png pierre-reference`
|
|
541
|
+
Captures the Pierre-like reference scene with a fixed viewport, file chrome, and `-1 / +1` single-hunk diff. Pass an optional fourth argument such as `snazzy-light`.
|
|
542
|
+
- `pnpm run compare:diff-ux -- /tmp/stream-monaco-diff-reference.png background pierre-reference`
|
|
543
|
+
Re-captures the same scene and prints screenshot metrics such as `diffPixels`, `mismatchRatio`, and `exactMatch`. Pass an optional final theme argument to compare the exact same palette.
|
|
544
|
+
|
|
442
545
|
### Shiki highlighter (advanced)
|
|
443
546
|
|
|
444
547
|
If you also render Shiki snippets outside Monaco:
|
|
@@ -480,7 +583,7 @@ For pure tail-append, prefer explicit `appendCode` / `appendOriginal` / `appendM
|
|
|
480
583
|
|
|
481
584
|
### Best practices
|
|
482
585
|
|
|
483
|
-
1
|
|
586
|
+
1. Performance: only load required languages
|
|
484
587
|
|
|
485
588
|
```ts
|
|
486
589
|
const { createEditor } = useMonaco({
|
|
@@ -489,7 +592,7 @@ const { createEditor } = useMonaco({
|
|
|
489
592
|
})
|
|
490
593
|
```
|
|
491
594
|
|
|
492
|
-
2
|
|
595
|
+
2. Memory management: dispose on unmount
|
|
493
596
|
|
|
494
597
|
```vue
|
|
495
598
|
<script setup>
|
|
@@ -504,7 +607,7 @@ onUnmounted(() => {
|
|
|
504
607
|
</script>
|
|
505
608
|
```
|
|
506
609
|
|
|
507
|
-
3
|
|
610
|
+
3. Follow system theme (via your own dark state) and call `setTheme` accordingly.
|
|
508
611
|
|
|
509
612
|
### Use without Vue (Vanilla)
|
|
510
613
|
|
|
@@ -584,7 +687,9 @@ If you load Monaco via CDN/AMD (e.g. `<script src=".../vs/loader.js">`), `stream
|
|
|
584
687
|
```ts
|
|
585
688
|
import { ensureMonacoWorkersLegacy } from 'stream-monaco/legacy'
|
|
586
689
|
|
|
587
|
-
ensureMonacoWorkersLegacy({
|
|
690
|
+
ensureMonacoWorkersLegacy({
|
|
691
|
+
baseUrl: 'https://cdn.jsdelivr.net/npm/monaco-editor@0.52.2/min/',
|
|
692
|
+
})
|
|
588
693
|
```
|
|
589
694
|
|
|
590
695
|
### Development
|