插件可以向 Portable Text 編輯器添加自訂區塊類型 — YouTube 嵌入、程式碼片段、圖片畫廊,任何預設區塊集未涵蓋的內容。沙盒化插件可以宣告這些區塊的編輯介面(使用 Block Kit 欄位),但在公開網站上渲染它們的 Astro 元件必須在建置時從 npm 載入。這就是需要原生插件的部分。
如果你的插件只需要編輯側欄位,並且其他人正在提供渲染元件(或網站在本地提供它們),你可以保持沙盒化。如果插件也應該提供渲染元件,則需要是原生的。
宣告區塊類型
沙盒化和原生插件都可以宣告區塊類型。原生插件在 definePlugin() 的 admin.portableTextBlocks 下執行此操作:
admin: {
portableTextBlocks: [
{
type: "youtube",
label: "YouTube Video",
icon: "video", // video, code, link, link-external
placeholder: "Paste YouTube URL...",
fields: [ // Block Kit fields for the editing UI
{ type: "text_input", action_id: "id", label: "YouTube URL" },
{ type: "text_input", action_id: "title", label: "Title" },
{ type: "text_input", action_id: "poster", label: "Poster Image URL" },
],
},
],
},
每個區塊類型定義:
type— 區塊類型名稱(在 Portable Text_type中使用)。label— 編輯器斜線命令選單中的顯示名稱。icon—video、code、link或link-external。預設回退到通用立方體。placeholder— 輸入佔位符文字。fields— 用於編輯的 Block Kit 表單欄位。如果省略,則顯示簡單的 URL 輸入。
在公開網站上渲染
要在公開網站上渲染區塊類型,從 componentsEntry 匯出 Astro 元件。匯出名稱必須是 blockComponents:
import YouTube from "./YouTube.astro";
import CodePen from "./CodePen.astro";
export const blockComponents = {
youtube: YouTube,
codepen: CodePen,
};
在描述符上設定 componentsEntry:
export function myPlugin(): PluginDescriptor {
return {
id: "embeds",
version: "1.0.0",
format: "native",
entrypoint: "@my-org/embeds",
componentsEntry: "@my-org/embeds/astro",
};
}
EmDash 會自動將插件區塊元件合併到 <PortableText> 中 — 網站作者無需匯入任何內容。使用者提供的元件(在網站的 <PortableText> 的 components 屬性中宣告)優先於插件預設值。
套件匯出
將 ./astro 匯出新增到 package.json:
{
"exports": {
".": { "types": "./dist/index.d.ts", "import": "./dist/index.js" },
"./admin": { "types": "./dist/admin.d.ts", "import": "./dist/admin.js" },
"./astro": { "types": "./dist/astro/index.d.ts", "import": "./dist/astro/index.js" }
}
}
./astro 匯出是伺服器端(Astro SSR),./admin 匯出是瀏覽器端(React),"." 匯出是描述符 + createPlugin。將它們保存在單獨的檔案中,因為它們為不同的環境打包。
沙盒友善的變體
如果你希望插件是沙盒化的,但仍然提供預設的渲染體驗,通常的模式是:
- 在市場上發布沙盒化插件(僅編輯欄位)。
- 在 npm 上發布一個單獨的配套原生套件,提供 Astro 渲染元件。
- 記錄兩者:最終使用者從市場安裝沙盒化插件,並使用
npm install安裝用於渲染的配套套件。
這將一步安裝換成保持編輯器端的沙盒化。當涉及區塊渲染時,大多數插件作者更喜歡直接使用原生 — 但該選項是存在的。