Slidev Monaco 编辑器完整配置指南:setup 文件、自动类型、Shiki 主题与代码运行选项
本篇围绕 Slidev 的 Monaco 编辑器定制能力展开:如何编写 setup/monaco.ts 接入 defineMonacoSetup、如何让编辑器自动获取依赖类型、如何复用 Shiki 主题保持一致的视觉风格,以及如何通过 frontmatter 控制启用范围与严格模式。读完后可在 Slidev 幻灯片中直接落地一个类型提示完整、主题统一、行为可控的 Monaco 代码编辑环境。
编写 Monaco 配置文件 setup/monaco.ts
Slidev 允许在客户端通过一个独立的 setup 文件对 Monaco 进行全局定制。在项目根目录创建 ./setup/monaco.ts,从 @slidev/types 导入 defineMonacoSetup 并导出一个接收 monaco 实例的函数:
import { defineMonacoSetup } from '@slidev/types'
export default defineMonacoSetup(async (monaco) => {
// use `monaco` to configure
})
defineMonacoSetup 本质上是一个类型包装函数,定义在 setups.ts:
// client side
export type MonacoSetup = (m: typeof monaco) => Awaitable<MonacoSetupReturn | void>
function defineSetup<Fn>(fn: Fn) {
return fn
}
export const defineMonacoSetup = defineSetup<MonacoSetup>
其返回值类型 MonacoSetupReturn 目前仅包含可选的 editorOptions 字段(setups.ts):
export interface MonacoSetupReturn {
editorOptions?: monaco.editor.IEditorOptions
}
仓库内的实际示例位于 demo/composable-vue/setup/monaco.ts,演示了如何用 typescriptDefaults.addExtraLib 注入一段虚拟类型声明,让编辑器识别自定义的 InjectionKey:
import { defineMonacoSetup } from '@slidev/types'
export default defineMonacoSetup((monaco) => {
monaco.typescript.typescriptDefaults.addExtraLib(
`
import { InjectionKey } from 'vue'
export interface UserInfo { id: number; name: string }
export const injectKeyUser: InjectionKey<UserInfo> = Symbol()
`,
'file:///root/context.ts',
)
})
从源码结构看,该 setup 文件的执行时机在 packages/client/setup/monaco.ts 中被统一管理。整个 Monaco 初始化被封装为单例 Promise(monaco.ts),流程大致为:
- 先注册
MonacoEnvironmentworker 路由:json使用JsonWorker、css/scss/less使用CssWorker、html/handlebars/razor使用HtmlWorker、typescript/javascript使用TsWorker,其余语言回退到EditorWorker(L26-L38); - 设置 TypeScript 编译器默认选项:
strict: true、moduleResolution: NodeJs、module: ESNext(L59-L65); - 依次执行所有用户
setups/monaco.ts,并把各自返回的editorOptions合并进全局配置(L98-L102); - 注册 Shiki 高亮(后文详述)。
此外还有一处细节:编辑器获得焦点时会调用 lockShortcuts() 锁定 Slidev 的全局快捷键,失焦时释放,避免在 Monaco 中输入时误触翻页等快捷键(L104-L114)。
TypeScript 类型:自动加载依赖类型
在幻灯片中使用 {monaco} 标记的代码块时,Slidev 会自动为代码中引用的依赖安装类型。例如:
```ts {monaco}
import { ref } from 'vue'
import { useMouse } from '@vueuse/core'
const counter = ref(0)
```
前提是确保 vue 和 @vueuse/core 已作为依赖 / devDependencies 安装在本地,Slidev 会自动完成编辑器类型的工作。当项目以 SPA 形式部署时,这些类型也会被打入产物用于静态托管。
自动扫描的实现原理
这一能力由解析层与虚拟模块协作完成:
- 解析阶段,packages/parser/src/core.ts 用正则
/\{monaco.*\}/检测页面是否包含 Monaco 代码块,并在命中时调用scanMonacoReferencedMods(code)扫描其中 import 的模块名(L163); - 构建阶段,虚拟模块
/@slidev/monaco-types由 monaco-types.ts 生成。它会:- 扫描用户项目
snippets/目录下所有*.ts、*.mts、*.cts文件,通过addFile()注入为额外 lib; - 把扫描到的依赖与 frontmatter 中
monacoTypesAdditionalPackages合并、去重; - 通过
mapModuleNameToModule做归一化:node:前缀与 Node 内置模块统一映射为node,lodash/identity这类子路径取主包名(@scope/pkg保留两段); - 过滤掉
monacoTypesIgnorePackages中列出的包,最后为每个包生成对/@slidev-monaco-types/resolve?pkg=...的动态 import,由服务端在请求时解析本地node_modules中的类型并下发。
- 扫描用户项目
也就是说,类型来源默认是“本地 node_modules 扫描”,无需任何额外配置。
补充额外类型 monacoTypesAdditionalPackages
Slidev 会扫描幻灯片中所有 Monaco 代码块并自动导入被引用库的类型。若它遗漏了某些包(例如类型是通过间接方式引用),可以显式声明额外需要导入类型的包:
---
monacoTypesAdditionalPackages:
- lodash-es
- foo
---
与类型加载相关的前置项还包括 monacoTypesIgnorePackages(忽略某些包,避免误注入)与 monacoRunAdditionalDeps(为可运行代码补充本地依赖模块),二者在 frontmatter.ts 中均有类型定义,VS Code 扩展的 JSON Schema headmatter.json 也对其提供了完整的补全与说明。
自动类型获取 monacoTypesSource
可以切换到从 CDN 加载类型的模式,对应配置:
---
monacoTypesSource: 'cdn'
---
该配置取值为 'local' | 'cdn' | 'none'(默认 'local',见 config.ts 中的默认值与 headmatter.json 的枚举定义)。cdn 模式由 @typescript/ata 驱动,且完全运行在客户端:在 packages/client/setup/monaco.ts 中,仅当 configs.monacoTypesSource === 'cdn' 时才调用 setupTypeAcquisition,其 receivedFile 回调把拉取到的声明文件通过 defaults.addExtraLib 注入 Monaco 的 TypeScript 默认实例,并用 monaco.editor.createModel 建立对应模型;progress 回调还会以 [Typescript ATA] downloaded / total 的形式在控制台输出下载进度。本地模式下则直接由 monaco-types.ts 虚拟模块按包解析注入(前述流程)。
主题配置:复用 Shiki 主题
自 v0.48.0 起,Monaco 会复用你在 Shiki 配置文件 中配置的 Shiki 主题,由 @shikijs/monaco 驱动,无需单独为编辑器指定主题,从而保证 Monaco 编辑区与其余代码块高亮风格一致。
源码印证见 packages/client/setup/monaco.ts:初始化时会先通过 getEagerHighlighter() 获取 Shiki 高亮器并调用 shikiToMonaco(highlighter, monaco) 完成主题映射;随后根据 themeOption 的类型决定行为——
- 若主题是一个固定字符串,直接
monaco.editor.setTheme(themeOption); - 若是 light/dark 双主题对象,则用
watchEffect监听isDark状态变化,在深浅色间自动切换,缺省回退到vitesse-dark/vitesse-light。
因此你只需要维护 docs/custom/config-highlighter.md 中的 Shiki 主题配置,Monaco 编辑器的配色会自动跟随。
配置编辑器行为 editorOptions
自 v0.43.0 可用
如需自定义 Monaco 编辑器行为,可以传入一个符合 Monaco IEditorOptions 定义的 editorOptions 对象,作用范围有两种:
1. 单个代码块级别
直接在 Markdown 代码块的内联选项中声明:
```ts {monaco} { editorOptions: { wordWrap:'on'} }
console.log('HelloWorld')
```
2. 全局级别
希望所有 Monaco 实例都应用这些选项时,在 defineMonacoSetup 函数中返回它们:
import { defineMonacoSetup } from '@slidev/types'
export default defineMonacoSetup(() => {
return {
editorOptions: {
wordWrap: 'on'
}
}
})
从源码看,全局 editorOptions 的合并在客户端初始化时进行:setup 循环中执行 Object.assign(editorOptions, result?.editorOptions)(monaco.ts),最终随单例 setup 的返回值一同导出,供 Monaco.vue 等内置组件在创建编辑器实例时使用。
启用与禁用
自 v0.48.0 起,Monaco 编辑器默认启用,且仅在幻灯片中实际使用时才会被打包(按需引入,未使用 {monaco} 代码块时不会增加产物体积)。若想禁用它,可在幻灯片 frontmatter 中把 monaco 设为 false:
---
monaco: false # can also be `dev` or `build` to conditionally enable it
---
monaco 的完整类型是 boolean | 'dev' | 'build'(frontmatter.ts),默认为 true(config.ts):
true:开发与服务端渲染/构建均启用;false:完全禁用;'dev':仅在开发模式启用;'build':仅在构建产物中启用。
严格模式 monacoRunUseStrict
自 v0.52.0 可用
默认情况下,Monaco 可运行代码以严格模式("use strict")执行。如果你的代码依赖非严格模式行为(例如隐式 this 或全局变量绑定差异),可以关闭:
---
monacoRunUseStrict: false
---
该选项的默认值为 true(config.ts 的解析默认值,以及 headmatter.json 中的 Schema 默认值一致)。配合前文提到的编辑器端编译器选项 strict: true,整个“编辑提示 + 实际运行”链路在默认配置下都保持严格的 TypeScript 语义。
配置代码运行器 Code Runners
关于 Monaco Runner 如何执行代码、以及如何为自定义语言添加运行支持,见 配置 Code Runners。可运行的本地代码块还可配合 monacoRunAdditionalDeps 选项注入额外的本地模块依赖(frontmatter.ts)。
Frontmatter 配置项速查
汇总当前仓库中 Monaco 相关的全部 frontmatter 配置项(依据 frontmatter.ts 的类型定义与 config.ts 的默认值):
| 配置项 | 类型 | 默认值 | 说明 |
|---|---|---|---|
monaco |
boolean | 'dev' | 'build' |
true |
是否启用 Monaco,可按 dev/build 条件启用;未使用时代码不会被打包 |
monacoTypesSource |
'local' | 'cdn' | 'none' |
'local' |
类型来源:本地 node_modules 或经 @typescript/ata 从 CDN 获取 |
monacoTypesAdditionalPackages |
string[] |
[] |
自动扫描遗漏时,显式补充需要导入类型的包 |
monacoTypesIgnorePackages |
string[] |
[] |
类型加载时需要忽略的包 |
monacoRunAdditionalDeps |
string[] |
[] |
为可运行代码块补充的本地依赖模块 |
monacoRunUseStrict |
boolean |
true |
可运行代码是否以严格模式执行 |
小结与延伸阅读
- 全局定制入口:
setup/monaco.ts+defineMonacoSetup(packages/types/src/setups.ts 定义了各 setup 的类型签名); - 客户端初始化与类型注入逻辑:packages/client/setup/monaco.ts;
- 类型解析虚拟模块:packages/slidev/node/virtual/monaco-types.ts;
- 解析默认值:packages/parser/src/config.ts;
- 实际使用示例:demo/composable-vue/setup/monaco.ts;
- 主题复用:docs/custom/config-highlighter.md;
- 代码运行器:docs/custom/config-code-runners.md。
掌握以上内容后,你可以按需组合:用 setup/monaco.ts 做全局行为定制与额外类型声明,用 {monaco} 内联 editorOptions 做单块微调,用 monacoTypesSource / monacoTypesAdditionalPackages 精确控制类型来源,用 monaco 与 monacoRunUseStrict 管理启用范围与运行语义,从而得到一套与幻灯片其余代码块视觉统一、提示完整的 Monaco 编辑环境。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0623
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00