Todo plugin em sandbox tem um arquivo emdash-plugin.jsonc em seu diretório raiz. Ele fica ao lado de package.json quando o plugin também é um pacote npm. O manifesto identifica o plugin, declara o acesso e o armazenamento de que ele precisa e fornece informações para sua listagem no registro e para suas releases. A CLI de plugins o lê ao validar, compilar, empacotar, publicar e preparar releases automatizadas.
O arquivo usa JSON com comentários (JSONC), então comentários e vírgulas finais são válidos. Mantenha a propriedade $schema criada por emdash-plugin init; os editores usam o esquema gerado para o preenchimento automático, enquanto emdash-plugin validate faz a verificação completa.
O exemplo a seguir inclui cada grupo de campos:
{
"$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" }],
},
},
}
Identidade e versão
| Campo | Obrigatório | Regras |
|---|---|---|
slug | Sim | Começa com uma letra minúscula e depois usa letras minúsculas, dígitos, - ou _; no máximo 64 caracteres. |
publisher | Sim | DID ou handle da conta Atmosphere. Recomenda-se um DID, porque os handles podem mudar de dono. |
version | Às vezes | Semver 2.0 sem metadados de build. Omita quando o package.json fornecer a versão. |
O publisher e o slug identificam o pacote no registro. O slug também é usado nas URLs das rotas do plugin, portanto não é o nome do pacote npm: use gallery para um pacote como @example/plugin-gallery.
Mantenha um único valor de versão
O build concilia version com package.json#version:
- Se os dois arquivos definirem a versão, os valores devem coincidir.
- Se apenas um arquivo definir a versão, o build a usa.
- Se nenhum dos dois arquivos definir a versão, o build falha.
Para um pacote npm, mantenha a versão no package.json e omita-a do manifesto. Um plugin apenas de registro, sem package.json, deve definir version no manifesto.
Perfil do pacote
O perfil do pacote fornece as informações estáveis exibidas em todas as releases.
| Campo | Obrigatório | Regras |
|---|---|---|
license | Sim | Expressão SPDX não vazia, com até 256 caracteres. |
author ou authors | Sim | Use uma das formas. author tem um name de até 64 grafemas e um url ou email opcional; authors aceita de 1 a 32 entradas. |
security ou securityContacts | Sim | Use uma das formas. Cada contato deve conter um email, um url ou ambos; a lista aceita de 1 a 8 entradas. |
name | Não | Nome de exibição, com até 100 grafemas. O slug é usado quando ele está ausente. |
description | Não | Descrição curta, com até 140 grafemas. |
keywords | Não | Até cinco strings não vazias, cada uma com no máximo 64 grafemas. |
sections | Não | Seções longas em CommonMark para description, installation, faq, changelog e security. |
Cada seção pode ser uma string em linha ou uma referência de arquivo relativa ao manifesto:
"sections": {
"description": "A longer description written in CommonMark.",
"installation": { "file": "./docs/installation.md" },
"security": { "file": "./SECURITY.md" },
}
Cada seção resolvida é limitada a 20.000 bytes e 2.000 grafemas. Uma referência de arquivo deve permanecer dentro do diretório do manifesto; caminhos absolutos e caminhos com .. que saiam dele são rejeitados.
publish cria o perfil do pacote na primeira release. As releases seguintes não substituem seus campos de perfil. Edite um perfil publicado com emdash-plugin update-package: por padrão, o comando mostra uma prévia das alterações e só as grava com --yes.
Contrato de confiança
O contrato de confiança consiste em capabilities, allowedHosts e storage. Esses campos informam a um operador o que o plugin pode acessar e quais collections próprias ele cria.
A declaração a seguir permite leituras de conteúdo, permite requisições a uma API e aos seus subdomínios e cria uma collection de armazenamento:
"capabilities": ["content:read", "network:request"],
"allowedHosts": ["api.example.com", "*.cdn.example.com"],
"storage": {
"events": {
"indexes": ["savedAt", ["collection", "savedAt"]],
"uniqueIndexes": ["eventId"],
},
}
Capabilities e hosts
Os três campos são vazios por padrão. O scaffold escreve explicitamente os valores vazios para que quem revisa veja que o plugin não pede acesso nem collections adicionais.
network:request exige pelo menos um hostname simples em allowedHosts. network:request:unrestricted exige uma lista vazia, porque permite deliberadamente qualquer host público. Capabilities e segurança é a referência canônica de cada capability, suas implicações, os padrões de host e a aplicação em runtime.
Armazenamento
Cada chave em storage nomeia uma collection própria do plugin. Seus indexes e uniqueIndexes determinam por quais campos o plugin pode filtrar ou ordenar. Storage explica os nomes das collections, o design de índices, as consultas e a paginação.
Alterar qualquer parte do contrato de confiança exige uma nova versão do plugin, porque os sites instalados consentiram com a declaração anterior. Use uma versão major quando o contrato for ampliado.
Páginas de administração e widgets
Os plugins em sandbox renderizam páginas de administração e widgets do painel com o Block Kit. O manifesto declara onde eles aparecem:
"admin": {
"pages": [{ "path": "/settings", "label": "Settings", "icon": "settings" }],
"widgets": [{ "id": "recent-events", "title": "Recent events", "size": "half" }],
}
Os caminhos de página começam com / e contêm letras, dígitos, /, _ ou -. Os IDs de widget usam os mesmos caracteres de identificador em minúsculas dos slugs de plugin. Os tamanhos de widget são full, half ou third.
Uma página também pode definir group para entrar em uma pasta recolhível da barra lateral. A correspondência diferencia maiúsculas de minúsculas e os espaços ao redor são ignorados. Um grupo que corresponde ao grupo de uma coleção exibida na barra lateral coloca a página nessa pasta; as páginas que compartilham qualquer outro grupo, de qualquer plugin, formam uma pasta com esse rótulo na seção Plugins.
Um plugin que declara uma página ou um widget deve definir uma rota chamada admin em src/plugin.ts. A verificação do bundle falha se essa rota estiver ausente, porque o EmDash não teria o que chamar para obter a resposta do Block Kit.
Campos de release
release descreve uma versão específica. A URL repo de nível superior é gravada nos registros de release e também é usada pela configuração de releases automatizadas para vincular o perfil do pacote ao seu repositório do GitHub.
| Campo | Finalidade |
|---|---|
repo | URL HTTPS do repositório do código-fonte. A configuração de releases automatizadas exige uma URL canônica de um repositório público do GitHub. |
release.requires | Requisitos do host, com env:<name> ou um DID de pacote como chave e intervalos semver como valores. |
release.artifacts.icon | Imagem exibida como ícone da release. |
release.artifacts.banner | Imagem de banner para a listagem da release. |
release.artifacts.screenshots | Galeria ordenada de capturas de tela com até oito entradas. |
Use env:emdash e env:astro para definir os intervalos de versão do EmDash e do Astro que podem instalar a release:
"release": {
"requires": {
"env:emdash": ">=0.37.0",
"env:astro": ">=5.0.0 <7.0.0",
},
}
O EmDash verifica esses requisitos antes da instalação. Um intervalo inválido faz a validação do manifesto falhar; uma release incompatível não é instalada.
Os caminhos dos arquivos de artefatos são relativos ao manifesto e devem permanecer dentro do diretório dele. PNG, JPEG e WebP são suportados. Cada arquivo é limitado a 1 MiB e a 8.192 pixels em qualquer dimensão. Uma propriedade opcional lang identifica uma imagem localizada com uma tag de idioma BCP 47. A publicação envia esses arquivos separadamente do bundle do plugin e registra o tipo medido, as dimensões, o checksum e a referência de blob no servidor de dados pessoais (PDS).
Fixação do publisher
publisher evita uma publicação acidental a partir da conta Atmosphere errada. Prefira o DID da conta:
"publisher": "did:plc:abc123def456", // jane.example.com
Antes de publicar ou preparar releases automatizadas, a CLI compara o publisher do manifesto com a sessão ativa. Um handle é resolvido para o DID atual na comparação. Uma divergência falha com MANIFEST_PUBLISHER_MISMATCH; não há flag para forçar.
Se a sessão errada estiver ativa, execute emdash-plugin whoami e depois troque para a conta fixada:
emdash-plugin switch did:plc:abc123def456
Altere o publisher do manifesto somente ao transferir o pacote para outra conta.
Validar o manifesto
Valide o manifesto antes de compilar ou publicar:
emdash-plugin validate
Passe um arquivo ou diretório para validar um manifesto diferente:
emdash-plugin validate ./packages/plugin-gallery
A validação é offline. Ela informa propriedades duplicadas, campos desconhecidos, valores inválidos, formas mutuamente exclusivas e erros entre campos, como network:request sem uma lista allowedHosts não vazia.
Continue com a CLI de plugins para os comandos de build ou com Empacotar e publicar para o fluxo de release.