# 从 Monaco 迁到 lite-monaco

> 嵌入式代码框 / Diff 场景。**不是** `monaco.editor.*` drop-in。

## 最小替换

### 单编辑器

```ts
// 前：monaco.editor.create(dom, { value, language, theme, readOnly })
import { createHighlighter } from 'shiki'
import { litcodeCM7, core } from 'lite-monaco'

const hl = await createHighlighter({ themes: ['dark-plus'], langs: ['typescript'] })
const cfg = litcodeCM7(hl, { lang: 'typescript', theme: 'dark-plus' })
document.head.appendChild(Object.assign(document.createElement('style'), { textContent: cfg.themeCSS }))

const view = new core.EditorView({
  state: core.EditorState.create({ doc: value, extensions: cfg.extensions }),
  parent: dom,
  decorationProviders: cfg.decorationProviders,
  overlays: cfg.overlays,
  keymap: cfg.keymap,
  drawSelection: cfg.drawSelection,
  lineNumbers: cfg.lineNumbers,
  lineWrapping: cfg.lineWrapping,
})
for (const a of cfg.overlays) a(view)

// 读/写
view.state.sliceDoc()
view.dispatch(view.state.update({ changes: { from: 0, to: view.state.doc.length, insert: next } }))
// 变更
view.onTransaction(tr => { if (tr.docChanged) onChange(view.state.sliceDoc()) })
```

### Diff

```ts
// 前：monaco.editor.createDiffEditor(dom, { … })
import { DiffEditor, diffEditorCSS } from 'lite-monaco'
document.head.appendChild(Object.assign(document.createElement('style'), { textContent: diffEditorCSS(true) }))
const diff = new DiffEditor({
  parent: dom,
  original, modified,
  dark: true,
  onModifiedChange: text => { /* save */ },
})
```

### 可选薄 shim

```ts
import { create, createDiffEditor } from 'lite-monaco/monaco-shim'
// 覆盖 create / setValue / getValue / onDidChangeModelContent / dispose
// 与 createDiffEditor 主路径；未实现的 API 会 throw
```

## 概念对照

| Monaco | lite-monaco |
|---|---|
| `IStandaloneCodeEditor` | `core.EditorView` |
| `ITextModel` / `setValue` | `EditorState` + `dispatch` changes |
| `onDidChangeModelContent` | `view.onTransaction` + `tr.docChanged` |
| `monaco.editor.createDiffEditor` | `DiffEditor` |
| TextMate / monacoworker 高亮 | Shiki peer（宿主 `createHighlighter`） |
| TS worker | 可选 peer `typescript`，主线程 LanguageService |
| themes 名 | Shiki 主题名（如 `dark-plus`） |
| `options` 大海 | `LitCodeFeatures` 布尔开关（默认全开） |

## 快捷键（主路径对齐）

| 键 | 两边都有 |
|---|---|
| ⌘/Ctrl+F / H | 查找 / 替换 |
| ⌘/Ctrl+G | 跳行 |
| ⌘/Ctrl+D | 选下一处 |
| ⌘/Ctrl+Space | 补全 |
| ⌘/Ctrl+. | Quick Fix（TS） |
| Alt+F12 | Peek |
| F1 | 命令面板 |
| Mod-Alt-↑/↓ | 多光标上下 |

## 摩擦清单（迁移时常见）

1. **高亮异步**：须先 `await createHighlighter`，没有 Monaco 内置同步 theme。  
2. **无 `ITextModel` 多模型服务**：一页一个 `EditorView`；多 tab 宿主自管。  
3. **无 URI / 语言中心**：`lang` 字符串喂 Shiki + TS。  
4. **配置面更小**：用 `features: { minimap: false }` 关能力，不要找 `editor.*` 百项。  
5. **事件模型**：`onTransaction` 而非 `onDidChangeModelContent` 细事件全集。  
6. **布局**：宿主给 `parent` 明确高度；`view.dom` 需 `height:100%`。  
7. **Diff 无 inline / moved blocks**（0.2）。  
8. **只读**：`EditorState.readOnly` 或 Diff original；编辑只读侧有 Monaco 风格 tip。  
9. **React**：见 `examples/react-basic.tsx`（peer 可选）。  
10. **包名**：`lite-monaco`（非 `monaco-editor`）。  
11. **体积**：runtime 不内嵌 typescript/shiki；peer 自装。  
12. **无 contribution / 插件 API**。  
13. **SSR**：可 SSR 高亮 token（Shiki）；编辑器本身浏览器挂载。  
14. **Worker**：默认 0-worker；TS 在主线程（有预算降级）。  
15. **对照 demo**：`npm run dev` → `/diff.html` 左 Monaco 右 lite-monaco。

## 明确不支持（不要迁完才发现）

- `monaco.languages.*` 注册 / provider 生态  
- 完整 semantic tokens / 调试 / 终端  
- multi-model tab 服务  
- IE11 / Emacs 键位  
- 像素级 Monaco DOM class 兼容  

## 建议步骤

1. 新页用 `litcodeCM7` 并行挂，不删 Monaco。  
2. 对表快捷键与 Diff。  
3. 卸 Monaco 依赖，体积对比。  
4. 有旧代码死磕 API → 试 `monaco-shim`，缺的再映射，勿扩内核。  
