插件格式(.kgpg)
Kabegame 插件以 .kgpg 文件分发,本质上是一个 ZIP 压缩包,内部包含自描述清单、爬取脚本与可选资源。本页说明格式的心智模型与每类条目的用途;字段的完整定义见 插件清单字段。
文件格式概述
.kgpg 只支持 KGPG v3(固定头部 + ZIP):文件前面是只含 meta 与 icon 的固定头部,用于无需解压或通过 HTTP Range 读取 icon;后面是标准 ZIP body(SFX 兼容)。插件清单由 ZIP 内 package.json 提供——元数据、后端、表单、标签全部内联在这一个文件里(不再有独立的 manifest.json 或 config.json,那是已废弃的 v2 模型)。
ZIP 内部结构
plugin-name.kgpg ├── package.json # v3 自描述清单(必需) ├── dist/main.js / crawl.js # package.json.main 指向的脚本(必需) ├── icon.png # 插件图标源文件(可选;打包后另存于固定头部) ├── configs/*.json # 推荐运行配置预设(可选) ├── providers/*.json5 # PathQL provider DSL(可选) ├── metadata_migrations/ │ └── migrate.js # 图片 metadata 迁移脚本(可选,单文件) ├── doc_root/ # 插件文档目录(可选) │ ├── doc.md # 默认语言文档(GFM Markdown) │ ├── doc.<lang>.md # 其它语言,如 doc.zh.md / doc.en.md │ └── <image> # kbAssets 显式导入的资源(jpg/jpeg/png/gif/webp/bmp) ├── CHANGELOG.md # kbChangelog 默认更新日志(可选) └── templates/ └── description.ejs # 图片详情页 HTML 模板(可选)package.json 用 kb* 指针字段声明这些文件的路径(main / kbIcon / kbDoc / kbChangelog / kbAssets / kbRecommendedConfigs / kbPathQLProviders / kbMetadataMigration / kbDescriptionTemplate)。解析器只读清单明确引用的条目,其余文件忽略。
| 条目 | 必需 | 由哪个字段引用 | 作用 |
|---|---|---|---|
package.json | 是 | — | v3 自描述清单(name / version / kbBackend / main / kbConfig / engines.kabegame 等) |
main 指向的脚本 | 是 | main | 爬取脚本;kbBackend 为 v8(自包含 ES module)或 webview(crawl.js) |
icon.png | 否 | kbIcon | 插件图标源文件;打包时转换为固定头部内的 RGB 数据 |
configs/*.json | 否 | kbRecommendedConfigs | 一组推荐预设,供用户一键应用 |
providers/*.json5 | 否 | kbPathQLProviders | PathQL provider DSL(后端用,不下发前端) |
metadata_migrations/migrate.js | 否 | kbMetadataMigration | 历史图片 metadata 迁移脚本(单文件,见下) |
templates/description.ejs | 否 | kbDescriptionTemplate | 图片详情区 HTML 模板;缺失时降级为原始 metadata 列表 |
doc_root/doc.md·doc.<lang>.md | 否 | kbDoc | 插件文档,多语言按键区分(default / zh / en / ja / ko / zhtw) |
CHANGELOG.md·CHANGELOG.<lang>.md | 否 | kbChangelog | 插件更新日志;与 kbDoc 使用相同的多语言映射 |
<image> | 否 | kbAssets | 文档与更新日志共用的图片资源;数组项是插件根相对路径 |
所有 kb* 路径和 kbAssets 数组项都做安全校验:必须是包根相对路径,禁越界的 ..、禁绝对路径 / 盘符 / 前导 /。
kbAssets 数组项、kbDoc / kbChangelog Markdown 引用和运行时 assets[].key 共用一个插件根坐标系与同一套归一化规则:标题后缀、query/fragment、前导 / 会被去掉,反斜杠改为 /,百分号按 UTF-8 解码,. / .. 按段折叠且越过插件根时判非法;HTTP(S)、data: 与 // 外链不注册。键大小写敏感。Markdown 所在目录不参与解析,因此 doc_root/doc.md 引用同目录图片时要写 doc_root/images/a.png;Markdown 原文不会被加载器改写。运行时 assets 是 { key, dataBase64 }[],顺序与 kbAssets 声明顺序一致。
Markdown 的每个本地图片引用都必须在 kbAssets 声明;未引用项只警告,允许预留。字段缺失或空数组都表示零资源。
package.json 最小示例
{ "name": "my-plugin", "version": "1.0.0", "private": true, "name.zh": "我的插件", "description": "插件描述", "author": "作者名", "kbPackageVersion": 3, "engines": { "kabegame": ">=4.3.0" }, "main": "dist/main.js", "kbBackend": "v8", "kbBaseUrl": "https://example.com", "kbConfig": []}完整字段(多语言 name/description、kbLabels 4.4.0、kbIcon / kbDoc / kbChangelog / kbAssets 等)见 插件清单字段。
metadata_migrations/migrate.js
单一 metadata 迁移脚本,由 kbMetadataMigration 引用。ES module,可导出 migrate(metadata)(入参与返回值都是 JSON 字符串)、provideLabels(metadata)(给历史图片补标签)与 provideSearchTextList(metadata)(给历史图片提供搜索片段),至少导出一个;运行在裸 V8(无 import、无宿主 API)。搜索片段应覆盖 description.ejs 展示原文,可增加 <插件>_<字段>_<值> 前缀,不收录键名、不可见链接或过期文字。按 metadata 里的 schema 自检、幂等、一步到位;每行无论成败只处理一次。契约与示例见 V8 脚本 · 元数据迁移。
templates/description.ejs
由前端用 EJS 把图片的 metadata 渲染为 HTML 后写入 iframe srcdoc。metadata 来源是爬虫 downloadImage(url, { metadata }) 写入的 metadata 行;模板随插件元数据一起加载到内存,由前端直接消费。
模板渲染时只有一个变量 metadata:
<h3><%= metadata.title %></h3><p>作者:<a href="<%= metadata.authorUrl %>"><%= metadata.author %></a></p>框架在模板内容之前自动注入脚本,提供以下全局能力(无需手写 postMessage):
| API | 说明 |
|---|---|
window.__bridge.fetch(url, options) | 跨域 HTTP GET,走宿主 proxy_fetch 绕过浏览器 CORS;options.headers 可传 Referer 等,options.json: true 返回已解析 JSON,否则返回 { base64, contentType }(适合图片字节)。单响应上限约 3 MB。 |
window.__bridge.getLocale() | 返回应用当前语言(en / zh / ja / ko / zhtw),用于与远端 API 的 lang 参数对齐。 |
window.__bridge.openUrl(url) | 在系统浏览器打开;仅支持 http:// / https://。 |
<a href="https://..."> / <a data-url="..."> | 自动桥接为 openUrl,点击即在外部浏览器打开。 |
若插件未提供 description.ejs,或 metadata 为空,详情区回退到原始 k-v 列表显示。
WebView 页面原生下载:Kabegame.onNativeDownload
仅 WebView 后端提供 Kabegame.onNativeDownload(callback): () => void。它用于接收页面自身触发、且无法由插件直接 fetch / downloadImage 的浏览器原生下载终态;V8 后端没有浏览器窗口,不适用此 API。返回值是取消监听函数。WebView 每次导航都会重跑 bootstrap 并重建监听集合,因此插件必须在每页 crawl.js 顶层重新注册。
页面原生下载会落到当前任务 VFS 的 tmp/Downloads/<sha256(url) 前 16 位 hex>-<安全文件名>。路径由 URL 与浏览器建议文件名纯函数生成,同一 URL 重复下载覆盖写入固定位置;Rust 不保存 waiter。下载成功、失败或取消都会触发回调,Requested 阶段分配 VFS 路径失败也会触发失败回调。
| payload 字段 | 类型 | 说明 |
|---|---|---|
url | string | 页面原生下载的原始 URL。 |
success | boolean | 是否下载成功。 |
path | string? | 仅成功时提供;当前任务 VFS 虚拟路径,可直接传给 Kabegame.downloadImage。 |
name | string? | 可取得时提供的下载文件名。 |
error | string? | 失败或取消时提供的可读错误。 |
// crawl.js 顶层:每次页面导航都会重跑脚本,因此每页都要重新注册。Kabegame.onNativeDownload((payload) => { if (!payload.success) { Kabegame.warn(payload.error || "页面下载失败"); return; } void Kabegame.downloadImage(payload.path, { name: payload.name, url: payload.url, });});KGPG v3 固定头部规范
固定头部总大小:49216 bytes
| 区域 | 大小 | 说明 |
|---|---|---|
| meta | 64 bytes | 偏移 0..64;文件魔数、版本、偏移等 |
| icon | 49152 bytes | 偏移 64..49216;128×128 RGB24 图像,行优先 |
| ZIP body | 其余字节 | 从偏移 49216 开始 |
meta(64 bytes,小端)
| 字段 | 偏移 | 说明 |
|---|---|---|
magic | 0..4 | 4B,固定 "KGPG" |
version | 4..6 | u16,固定 3 |
meta_size | 6..8 | u16,固定 64 |
icon_w | 8..10 | u16,固定 128 |
icon_h | 10..12 | u16,固定 128 |
pixel_format | 12 | u8,固定 1(RGB24) |
flags | 13 | u8,bit0: icon_present |
| 保留 | 14..16 | u16,填 0 |
zip_offset | 16..24 | u64,固定等于 49216 |
| 其余 | 24..64 | 保留,填 0 |
HTTP Range 读取
| 用途 | Range |
|---|---|
| 拉取完整头部(meta + icon) | bytes=0-49215 |
| 仅拉取 icon | bytes=64-49215 |
v3 优势
- 无需解压即可取 icon:客户端只需读取固定偏移的数据块。
- 支持 HTTP Range:商店列表可只拉取头部,不再依赖额外的
<id>.icon.png资产。 - 保持 ZIP 兼容:插件清单从 ZIP 内
package.json读取,通用 ZIP 工具也能直接打开。
延伸阅读
- 打包与发布 —— 如何把目录打成
.kgpg。 - 插件清单字段 ——
package.json/kbConfig完整字段与默认值。 - V8 脚本 / WebView 脚本 —— 两种后端脚本的写法。
- 插件使用方法 —— 用户如何安装、启用与配置插件。