ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

Slidev Monaco Runner 完全指南:在演示文稿编辑器里直接运行代码并实时查看输出

Slidev Monaco Runner 完全指南:在演示文稿编辑器里直接运行代码并实时查看输出 Slidev Monaco Runner 完全指南在演示文稿编辑器里直接运行代码并实时查看输出【免费下载链接】slidevPresentation Slides for Developers项目地址: https://gitcode.com/GitHub_Trending/sl/slidev导读Monaco Runner 是 Slidev 提供的一类特殊代码块只要在代码块的语言标记后追加{monaco-run}就能把静态代码片段升级为内置 Monaco 编辑器的可运行演示页面上会出现 Run 按钮并在编辑器下方实时展示执行结果。本文以 编辑器参考文档 与 官方功能文档 为主线结合 Monaco 组件源码、CodeRunner 实现 与 客户端运行时 等仓库证据带你掌握其基础用法、配置项、内置语言运行机制以及为任意语言编写自定义 Runner 的方法。Monaco Runner 是什么Slidev 内置的 Monaco 编辑器ts {monaco}让观众可以直接在幻灯片上编辑代码Monaco Runner 在其基础上再进一步把编辑器的运行能力也带到了浏览器中。它满足典型的技术演讲、工作坊、在线教学场景讲者可以先跑一遍示例再在台上实时修改参数重新执行观众能立刻看到结果变化而无需切换页面或打开开发者工具。该能力最早随 v0.48.0 引入见 features/monaco-run.md 的 frontmatter并自动集成在 Slidev 的代码块转换管线里源码层面由 codeblock/monaco.ts 的 transformer 负责识别并改写。基本用法把代码块变成可运行编辑器将monaco换成monaco-run一段普通的代码块就变成了 Monaco Runner Editorts {monaco-run} function distance(x: number, y: number) { return Math.sqrt(x ** 2 y ** 2) } console.log(distance(3, 4)) Slidev 会为这段代码渲染一个编辑器并提供一个 Run 按钮执行结果会显示在代码块下方代码块 monaco transformer 负责把该代码块编译为runnable的Monaco组件。代码可编辑、结果实时刷新与静态代码块不同Monaco Runner 里的代码是可编辑的编辑器内容通过code-lzlz-string 压缩注入创建时被解压进 Monaco 的 modelmodel.onDidChangeContent会把用户每一次修改同步回code状态Monaco.vue在默认开启自动运行的前提下只要修改代码就会触发一次新的运行输出结果随之刷新CodeRunner.vue 使用watch(code, triggerRun, { immediate: true })监听变化triggerRun内部做了 200ms 防抖debounce(200, ...)连续输入不会导致频繁执行CodeRunner.vue。编辑器右上方会固定显示一个播放图标按钮对应i-carbon:play见 CodeRunner.vue供手动触发运行。输出区还带有data-waitfor.slidev-runner-output标记这意味着导出与截图等自动化流程可以等待运行完成后再捕获页面CodeRunner.vue。运行时机控制autorun默认情况下Monaco Runner在代码块所在幻灯片加载时就自动执行一次。参考文档提供了关闭自动运行的写法ts {monaco-run} {autorun:false} console.log(Click the play button to run me) 设置autorun: false后幻灯片加载时不会执行任何代码只有用户点击 Run 按钮才会真正运行。关于 autorun 的类型与语义可从 CodeRunner.vue 的 props 定义确认它是boolean | oncetrue默认代码变化即运行加载即运行一次once只运行一次autorun once时直接调用triggerRun()false不自动运行等待点击播放按钮。有一个值得一提的实现细节打印模式print/导出下 autorun 会被强制覆盖为once见 CodeRunner.vue 的const autorun isPrintMode.value ? once : props.autorun。这样导出的 PDF/截图里会包含代码运行后的结果而不是空白的 Click the play button to run the code 占位提示。点击步进控制输出showOutputAt如果希望输出不在一开始就展示而是在演讲推进到特定 click 时才出现可以使用showOutputAt其取值语义与v-click完全一致ts {monaco-run} {showOutputAt:1} console.log(Shown after 1 click) 上例表示按下一次1后输出才会显示。showOutputAt的值类型为RawAtValue底层会通过$clicksContext.calculate(props.showOutputAt)将其注册为 Slidev click 系统的一部分并配合watchSyncEffect实时切换hidden状态CodeRunner.vue。利用这一特性你可以做出先让观众思考再按一次按键揭晓运行结果的互动节奏。该用法也用于演示控制例如运行结果结合v-click动画逐步揭示。内置支持的运行语言与真实运行机制参考文档明确指出开箱即用支持JavaScript和TypeScript两种语言。在仓库中这一注册关系写死在客户端运行时初始化函数中code-runners.tsconst runners: Recordstring, CodeRunner { javascript: runTypeScript, js: runTypeScript, typescript: runTypeScript, ts: runTypeScript, }注意js、ts简写也做了映射且 js 与 ts 共用同一套runTypeScript管线TypeScript 是 JavaScript 的超集。执行流程大致如下TypeScript 转译runTypeScript用内置typescript包的transpileModule把代码编译为module: ESNext, target: ES2022并用自定义 transformertransformImports把静态import语句改写为await import(...)动态导入code-runners.ts。注入式执行runJavaScript把代码包进new Function创建的工厂函数中执行并注入一个vmConsole对象接管console.log/info/warn/error/debug从而把输出逐条捕获进结果数组code-runners.ts。格式化打印printObject负责把字符串、Error、数组、Set、Map、RegExp、普通对象等类型渲染成可读文本对象与数组等复合类型会被标注highlightLang: javascript由 Shiki 高亮后展示code-runners.ts。错误捕获外层run()会捕获任意异常并返回{ error }结构CodeRunner 的模板会将其渲染为红色错误文本CodeRunner.vue。重要限制无沙箱环境官方文档明确提醒默认的 JS/TS Runner在浏览器中直接运行、不带任何沙箱环境见 config-code-runners.md。也就是说被运行代码拥有与当前页面同等的浏览器权限因此请只运行你信任的代码不要在公开站点上用它执行不可信的第三方输入。严格模式开关 monacoRunUseStrict默认情况下Monaco Runner 运行代码时会附加use strict;见 code-runners.ts 中基于configs.monacoRunUseStrict的前缀拼接。该行为可被 headmatter 关闭适用于依赖非严格模式行为的代码文档见 config-monaco.md 的 Strict Mode 一节--- monacoRunUseStrict: false ---对应类型定义的默认值为truefrontmatter.ts。运行时依赖与模块导入在 Monaco Runner 中代码可以直接使用 ES 模块import语法。得益于 transformImports 与虚拟模块#slidev/monaco-run-depsSlidev 会为你在代码块中 import 过的本地依赖提供真实的运行时模块实现。虚拟模块的生成逻辑位于 virtual/monaco-deps.ts它合并三类依赖来源后去重uniqconst deps uniq([ ...data.features.monaco.deps, // 扫描幻灯片 Monaco 代码块得到的 import 依赖 ...(data.config.monacoTypesAdditionalPackages || []), ...(data.config.monacoRunAdditionalDeps || []), ])随后把每个依赖import * as vendored{i}后按 specifier 导出。如果你在代码里import { useMouse } from vueuse/core运行时就会从该映射里取出对应模块实例。补充运行时依赖 monacoRunAdditionalDeps默认情况下 Slidev 会扫描 Markdown 源码自动导入代码 Runner 需要的依赖。若某次扫描漏掉了运行时所需模块可在 headmatter 用monacoRunAdditionalDeps手动声明--- monacoRunAdditionalDeps: - ./path/to/dependency - lodash-es ---关于该选项有三点需要注意官方文档 config-code-runners.md 明确说明./开头的本地路径相对于snippets目录解析虚拟模块的 resolver 正是以userRoot/snippets/__importer__.ts为 importer 进行模块解析见 monaco-deps.ts包名如lodash-es与代码中 import 的 specifier 必须完全一致否则找不到模块类型层面该配置默认值为空数组frontmatter.ts。与此配套的类型加载选项还包括monacoTypesSourcecdn/local/none默认local、monacoTypesAdditionalPackages与monacoTypesIgnorePackages见 frontmatter.ts它们决定编辑器的自动补全与类型检查从何处获取.d.ts具体细节可参考 Monaco 配置文档。为其他语言编写自定义 Code Runner参考文档在 Supported Languages 一节给出的扩展入口是/custom/config-code-runners仓库内对应 docs/custom/config-code-runners.md。核心思路Runner 的注册表按语言 id 作为 keySlidev 允许你提供一个返回对象Recordstring, CodeRunner的 setup 文件key 就是代码块的 language id。在项目根目录创建setup/code-runners.tsimport { defineCodeRunnersSetup } from slidev/types export default defineCodeRunnersSetup(() { return { async python(code, ctx) { // 例如把 code 发送到远程服务器执行后取回结果 const result await executePythonCodeRemotely(code) return { text: result, } }, // key 即语言 id其余语言照此注册 } })初始化时客户端代码会遍历这些 setup用Object.assign(runners, result)把自定义 runner 合并进默认注册表code-runners.ts因此自定义 runner 会覆盖同名内置语言或新增全新语言。自定义 runner 并不局限于发到远程服务器。仓库自带的演示项目 demo/vue-runner/setup/code-runners.ts 展示了一个非常完整的范例它注册了vuerunner把 Vue 单文件组件源码交给vue/compiler-sfc编译用new Function求值出组件定义Vue.createApp挂载后把 DOM 元素作为输出返回——实现在 Monaco 编辑器里实时渲染一个 Vue 组件。其代码注释也一再强调这种方式没有沙箱、不安全仅适合演示。Runner Context第二个参数每个 runner 收到(code, ctx)两个参数ctx的类型为CodeRunnerContext定义见 code-runner.ts包含三个能力属性类型说明optionsRecordstring, unknown通过runnerOptionsprop 传给 runner 的选项highlight(code, lang, options?) string用 Shiki 高亮代码返回 HTML 字符串run(code, lang) PromiseCodeRunnerOutputs复用其他code runner 去运行代码Runner 返回的输出类型runner 返回值的类型为CodeRunnerOutputsMaybeRefOrGetterArrayableCodeRunnerOutput即可以是单个输出、数组、ref或 getter。每个输出项支持四种形态code-runner.ts输出形态结构渲染方式纯文本{ text, class?, highlightLang? }或CodeRunnerOutputText[]以输出行形式展示带highlightLang时用 Shiki 高亮内嵌HTML{ html }通过v-html直接注入。Slidev 不会替你清洗 HTML务必只传可信来源或先消毒源码注释同样强调这一点DOM 元素{ element }通过 DomElement.vue 挂载真实节点vue-runner demo 即返回element错误{ error }渲染为红色错误信息运行中的 UI 状态Running… / 点击播放运行 / 输出的切换与具体渲染位置可以查阅 CodeRunner.vue。相关前置配置开启与关闭 Monaco{monaco-run}依赖 Monaco 编辑器整体开关monacoheadmatter 配置默认开启且按需打包。若在某一页临时关闭编辑器类代码块可写--- monaco: false # 也可为 dev 或 build按开发/构建模式条件启用 ---Monaco transformer 正是在这里做闸门判断config.monaco true || config.monaco mode不满足时直接返回、不做任何转换codeblock/monaco.ts。想调整 Monaco 编辑器的字号、自动换行、代码行号等细节可参考 Monaco 配置文档editorOptions、defineMonacoSetup等。典型场景与注意事项小结代码走查 / 教学默认自动运行 可实时改写代码适合演示算法如distance(3, 4)与 API 用法互动提问{autorun:false}让观众先预测再手动点击播放揭示答案逐步揭示{showOutputAt:1}让输出跟随演讲 click 节奏出现仅限 JS/TS 开箱即用其他语言需在 setup/code-runners.ts 自行注册仓库的 vue-runner 演示 是最佳参考模板非沙箱JS/TS 在浏览器页面内直接执行HTML 输出不做消毒运行不可信代码有安全风险导出兼容打印模式下自动运行被强制为once保证 PDF/截图包含输出结果。若要进一步了解相关主题可继续阅读仓库内这些文档Monaco 编辑器基础用法、编辑器编辑文件 monaco-write、代码行高亮 以及 内置组件总览。【免费下载链接】slidevPresentation Slides for Developers项目地址: https://gitcode.com/GitHub_Trending/sl/slidev创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进