# 插件开发指南 > rust-blog 支持两种插件运行时:**WASM**(Rust 编写)和 **JavaScript**(QuickJS)。 > 本文档聚焦 JS 插件开发。 --- ## 快速开始 ### 1. 创建插件目录 ``` plugins/my-plugin/ ├── plugin.toml # 插件清单 └── index.js # JS 入口 ``` ### 2. 编写 plugin.toml ```toml [plugin] id = "com.example.my-plugin" # 全局唯一 ID(反向域名格式) name = "My Plugin" # 显示名称 version = "1.0.0" # 语义化版本 description = "插件描述" author = "Your Name" license = "MIT" runtime = "js" # 必须设为 "js" language = "javascript" # 或 "typescript" entry = "index.js" # JS 入口文件名(默认 index.js) [permissions] max_memory_mb = 8 # 内存限制(默认 32MB) timeout_ms = 2000 # 单次 Hook 执行超时(默认 5000ms) [hooks.on_post_creating] # 注册的 Hook,key 用下划线或短横线均可 priority = 10 # 优先级,数字越小越先执行 [hooks.filter_html] priority = 20 ``` ### 3. 编写 index.js ```javascript var Plugin = { on_post_creating: function(inputJson) { var input = JSON.parse(inputJson); // 修改输入数据 input.title = input.title.trim(); return JSON.stringify(input); }, filter_html: function(html) { // 在
后注入 OG 标签 return html.replace("", ''); } }; ``` ### 4. 部署 ```bash # 手动复制 cp -r plugins-examples-js/my-plugin/ plugins/my-plugin/ # 或用 justfile(需添加到 justfile) just plugins-js-build ``` --- ## Hook 类型 ### JSON Filter — 修改数据 接收 JSON 字符串,返回修改后的 JSON 字符串。 | Hook | 触发时机 | 数据内容 | |------|----------|----------| | `on_post_creating` | 文章创建前 | `{ title, content, excerpt, category_id, ... }` | | `on_post_updating` | 文章更新前 | 同上 + `id` | | `on_comment_creating` | 评论创建前 | `{ content, post_id, parent_id, ... }` | ```javascript on_post_creating: function(inputJson) { var input = JSON.parse(inputJson); input.excerpt = input.content.substring(0, 200); return JSON.stringify(input); // 必须返回 JSON 字符串 } ``` ### JSON Action — 通知/副作用 接收 JSON 字符串,无返回值。适合日志、通知、缓存清理等。 | Hook | 触发时机 | 数据内容 | |------|----------|----------| | `on_post_created` | 文章创建后 | `{ id, title, slug, ... }` | | `on_post_updated` | 文章更新后 | 同上 | | `on_post_deleted` | 文章删除后 | `{ id }` | | `on_comment_created` | 评论创建后 | `{ id, content, post_id, ... }` | | `on_login` | 用户登录后 | `{ email, success }` | ```javascript on_post_created: function(dataJson) { var data = JSON.parse(dataJson); Host.log("info", "New post: " + data.title); } ``` ### String Filter — 修改原始字符串 | Hook | 触发时机 | 输入 | 返回 | |------|----------|------|------| | `render_markdown` | Markdown 渲染(替代默认渲染器) | Markdown 原文 | HTML 字符串 | | `filter_html` | HTML 后处理 | HTML 字符串 | 修改后的 HTML | ```javascript render_markdown: function(content) { // 自定义渲染逻辑 return "" + content + "
"; } ``` ### Route Handler — 自定义路由 ```javascript handle_route: function(routeJson) { var route = JSON.parse(routeJson); // route.path, route.method return JSON.stringify({ status: 200, body: JSON.stringify({ message: "Hello from plugin!" }) }); } ``` 需要在 `plugin.toml` 中配置 `match` 模式: ```toml [hooks.handle_route] match = "/api/v1/custom/*" # glob 风格,* 匹配单段路径 priority = 5 ``` --- ## 宿主 API 插件通过全局 `Host` 对象与宿主交互。 ### Host.log(level, message) 写入宿主日志。 ```javascript Host.log("info", "这条消息会出现在宿主日志中"); Host.log("warn", "警告信息"); Host.log("error", "错误信息"); ``` ### Host.getConfig(key) 读取宿主配置。返回字符串或 `null`。 ```javascript var env = Host.getConfig("app.env"); // "development" / "production" var port = Host.getConfig("app.port"); // "3000" var baseUrl = Host.getConfig("app.base_url"); // "http://localhost:3000" var maxSize = Host.getConfig("upload.max_size"); ``` 支持的 key: | Key | 说明 | |-----|------| | `app.host` | 监听地址 | | `app.port` | 监听端口 | | `app.env` | 运行环境 | | `app.base_url` | 站点 URL | | `jwt.access_expires` | Access Token 过期时间(秒) | | `jwt.refresh_expires` | Refresh Token 过期时间(秒) | | `upload.dir` | 上传目录 | | `upload.max_size` | 上传大小限制(字节) | | `plugin.max_memory_mb` | 插件内存限制 | | `plugin.default_timeout_ms` | 插件超时时间 | > 注意:`jwt.secret` 和 `database_url` 等敏感配置不暴露给插件。 --- ## TypeScript 开发 ### 1. 安装 SDK 类型定义 在插件目录创建 `tsconfig.json`: ```json { "compilerOptions": { "target": "ES2021", "module": "ES2020", "strict": true, "noEmit": true, "baseUrl": "..", "paths": { "rust-blog-plugin-sdk": ["plugins-sdk-js"] } } } ``` ### 2. 编写 TypeScript ```typescript ///