每个沙箱插件的根目录下都有一个 emdash-plugin.jsonc 文件。当插件同时是 npm 包时,它与 package.json 放在一起。清单用于标识插件、声明它需要的访问权限和存储,并提供其注册表条目和发布版本所需的信息。插件 CLI 在校验、构建、打包、发布以及准备自动化发布时都会读取它。
该文件使用带注释的 JSON(JSONC),因此可以写注释,也允许尾随逗号。请保留 emdash-plugin init 创建的 $schema 属性;编辑器会使用生成的 schema 提供补全,而 emdash-plugin validate 会执行完整检查。
下面的示例包含了每一组字段:
{
"$schema": "./node_modules/@emdash-cms/plugin-cli/schemas/emdash-plugin.schema.json",
"slug": "gallery",
"publisher": "did:plc:abc123def456",
"license": "MIT",
"author": { "name": "Jane Doe", "url": "https://example.com" },
"security": { "email": "[email protected]" },
"name": "Gallery",
"description": "Image galleries for EmDash content.",
"keywords": ["gallery", "images"],
"sections": {
"installation": { "file": "./docs/installation.md" },
"faq": { "file": "./docs/faq.md" },
},
"capabilities": ["content:read"],
"allowedHosts": [],
"storage": {
"galleries": { "indexes": ["contentId"] },
},
"admin": {
"pages": [{ "path": "/gallery", "label": "Gallery", "icon": "image" }],
},
"repo": "https://github.com/example/plugin-gallery",
"release": {
"requires": { "env:emdash": ">=0.37.0" },
"artifacts": {
"icon": { "file": "./images/icon.png" },
"screenshots": [{ "file": "./images/editor.png", "lang": "en" }],
},
},
}
身份与版本
| 字段 | 是否必填 | 规则 |
|---|---|---|
slug | 是 | 以小写字母开头,其后可使用小写字母、数字、- 或 _;最多 64 个字符。 |
publisher | 是 | Atmosphere 账号的 DID 或 handle。建议使用 DID,因为 handle 可能易主。 |
version | 视情况 | 不含构建元数据的 Semver 2.0。当 package.json 已提供版本时可以省略。 |
发布者和 slug 共同标识注册表中的包。slug 还会用在插件路由的 URL 中,因此它不是 npm 包名:对于 @example/plugin-gallery 这样的包,请使用 gallery。
只保留一处版本号
构建时会让 version 与 package.json#version 保持一致:
- 如果两个文件都设置了版本,两者的值必须一致。
- 如果只有一个文件设置了版本,构建会使用它。
- 如果两个文件都没有设置版本,构建会失败。
对于 npm 包,请把版本保存在 package.json 中,并在清单里省略它。没有 package.json 的纯注册表插件,必须在清单中设置 version。
包资料
包资料提供各个发布版本中都会显示的稳定信息。
| 字段 | 是否必填 | 规则 |
|---|---|---|
license | 是 | 非空的 SPDX 表达式,最多 256 个字符。 |
author 或 authors | 是 | 二选一。author 包含最多 64 个字素的 name,以及可选的 url 或 email;authors 接受 1–32 个条目。 |
security 或 securityContacts | 是 | 二选一。每个联系人必须包含 email、url 或两者;列表接受 1–8 个条目。 |
name | 否 | 显示名称,最多 100 个字素。缺省时使用 slug。 |
description | 否 | 简短描述,最多 140 个字素。 |
keywords | 否 | 最多五个非空字符串,每个不超过 64 个字素。 |
sections | 否 | 面向 description、installation、faq、changelog 和 security 的长篇 CommonMark 段落。 |
每个段落既可以是内联字符串,也可以是相对于清单的文件引用:
"sections": {
"description": "A longer description written in CommonMark.",
"installation": { "file": "./docs/installation.md" },
"security": { "file": "./SECURITY.md" },
}
解析后的每个段落限制为 20,000 字节和 2,000 个字素。文件引用必须位于清单所在目录之内;绝对路径以及会跳出该目录的 .. 路径都会被拒绝。
publish 会在首次发布时创建包资料。之后的发布不会替换其中的资料字段。如需编辑已发布的资料,请使用 emdash-plugin update-package:该命令默认只预览变更,只有加上 --yes 才会写入。
信任契约
信任契约由 capabilities、allowedHosts 和 storage 组成。这些字段会告诉运维人员,插件可以访问什么,以及它会创建哪些归插件所有的 collection。
下面的声明允许读取内容、允许向一个 API 及其子域名发出请求,并创建一个存储 collection:
"capabilities": ["content:read", "network:request"],
"allowedHosts": ["api.example.com", "*.cdn.example.com"],
"storage": {
"events": {
"indexes": ["savedAt", ["collection", "savedAt"]],
"uniqueIndexes": ["eventId"],
},
}
Capability 与主机
这三个字段默认都为空。脚手架会显式写出这些空值,方便审阅者看出该插件没有请求任何额外的访问权限或 collection。
network:request 要求 allowedHosts 中至少有一个裸主机名。network:request:unrestricted 要求该列表为空,因为它有意允许访问任何公共主机。能力与安全是关于每一项能力、其影响、主机模式和运行时强制执行的权威参考。
存储
storage 中的每个键都命名一个归插件所有的 collection。它的 indexes 和 uniqueIndexes 决定了插件可以按哪些字段筛选或排序。存储说明了 collection 命名、索引设计、查询和分页。
信任契约的任何部分发生变化,都需要发布新的插件版本,因为已安装的站点同意的是之前的声明。对于扩大了范围的契约,请使用主版本号。
管理页面和小工具
沙箱插件使用 Block Kit 渲染管理页面和仪表板小工具。清单声明它们出现在哪里:
"admin": {
"pages": [{ "path": "/settings", "label": "Settings", "icon": "settings" }],
"widgets": [{ "id": "recent-events", "title": "Recent events", "size": "half" }],
}
页面路径以 / 开头,可包含字母、数字、/、_ 或 -。小工具 ID 使用与插件 slug 相同的小写标识符字符。小工具尺寸为 full、half 或 third。
页面还可以设置 group,以加入侧边栏中可折叠的文件夹。匹配区分大小写,并忽略前后空白。如果某个分组与侧边栏中显示的某个集合的分组相同,该页面就会放入那个文件夹;共享其他任何分组的页面(无论来自哪个插件)会在 Plugins 部分中组成一个以该标签命名的文件夹。
声明了页面或小工具的插件,必须在 src/plugin.ts 中定义一个名为 admin 的路由。如果缺少该路由,打包检查会失败,因为 EmDash 将没有任何东西可以调用来获取 Block Kit 响应。
发布字段
release 描述某个特定版本。顶层的 repo URL 会写入发布记录,自动化发布设置也会用它把包资料绑定到对应的 GitHub 仓库。
| 字段 | 用途 |
|---|---|
repo | 源代码仓库的 HTTPS URL。自动化发布设置要求使用规范的公开 GitHub 仓库 URL。 |
release.requires | 宿主要求,以 env:<name> 或包 DID 为键,以 semver 范围为值。 |
release.artifacts.icon | 用作发布版本图标的图片。 |
release.artifacts.banner | 发布列表使用的横幅图片。 |
release.artifacts.screenshots | 有序的截图图库,最多八项。 |
使用 env:emdash 和 env:astro 来设置可以安装该发布版本的 EmDash 和 Astro 版本范围:
"release": {
"requires": {
"env:emdash": ">=0.37.0",
"env:astro": ">=5.0.0 <7.0.0",
},
}
EmDash 会在安装之前检查这些要求。无效的范围会导致清单校验失败;不兼容的发布版本不会被安装。
制品文件路径相对于清单,且必须位于其目录之内。支持 PNG、JPEG 和 WebP。每个文件限制为 1 MiB,且任一边不超过 8,192 像素。可选的 lang 属性用 BCP 47 语言标签标明本地化的图片。发布时,这些文件会与插件包分开上传,并记录它们实测的类型、尺寸、校验和以及个人数据服务器(PDS)的 blob 引用。
发布者固定
publisher 可以防止从错误的 Atmosphere 账号误发布。建议使用账号的 DID:
"publisher": "did:plc:abc123def456", // jane.example.com
在发布或准备自动化发布之前,CLI 会将清单中的发布者与当前会话进行比较。如果填写的是 handle,会先解析为其当前的 DID 再比较。不匹配时会以 MANIFEST_PUBLISHER_MISMATCH 失败;没有可以绕过的覆盖标志。
如果当前使用的会话不对,请运行 emdash-plugin whoami,然后切换到被固定的账号:
emdash-plugin switch did:plc:abc123def456
只有在把包转移给另一个账号时,才应修改清单中的发布者。
验证清单
在构建或发布之前先验证清单:
emdash-plugin validate
传入文件或目录即可验证另一份清单:
emdash-plugin validate ./packages/plugin-gallery
验证在离线状态下进行。它会报告重复的属性、未知字段、无效值、互斥的写法,以及跨字段错误,例如设置了 network:request 却没有非空的 allowedHosts 列表。