Portable Textレンダリングコンポーネント
このページで分かること
- プラグインが定義するPortable Textのブロックは、編集画面用の定義と公開サイト用のAstroコンポーネントの2つからなること
admin.portableTextBlocksでのブロックの定義と、各項目の働き- Astroコンポーネントの作成と登録(
blockComponents、componentsEntry)、描画コンポーネントの優先順位とサイト側での上書き
このページの目次
プラグインが定義するPortable Textのブロックは、2つの部分からなります。
- 宣言的なブロックの定義は、ブロックを挿入・編集する方法をEmDashのエディターに伝えます。
- Astroコンポーネントは、保存されたブロックを公開サイトで描画します。
ブロックの定義は共通のプラグインのランタイムを使い、サンドボックス型プラグインでも使えます。パッケージからAstroコンポーネントを読み込むには、ネイティブ型のディスクリプターが必要です。Astroがホストのサイトをビルドするときに、そのコンポーネントをインポートする必要があるためです。
やさしい解説
公式の対応表では、WordPressの the_content() は、EmDashの <PortableText /> にあたります。プラグインで独自のブロックを作る場合、エディターでの入力項目は admin.portableTextBlocks に宣言し、公開サイトでの見た目はAstroコンポーネントで作ります。入力項目の宣言はただのデータなのでサンドボックス型でも書けますが、Astroコンポーネントはサイトのビルド時に読み込む必要があるため、ネイティブ型でしか提供できません。
エディター用のブロックの定義
definePlugin() の中の admin.portableTextBlocks で、ブロックを宣言します。次の定義は、見出し、本文、トーンを持つコールアウトを追加します。
return definePlugin({
id: "plugin-callout",
version: "0.1.0",
admin: {
portableTextBlocks: [
{
type: "callout",
label: "Callout",
icon: "info",
description: "Highlight supporting information",
category: "Sections",
fields: [
{
type: "text_input",
action_id: "heading",
label: "Heading",
},
{
type: "text_input",
action_id: "body",
label: "Body",
multiline: true,
},
{
type: "select",
action_id: "tone",
label: "Tone",
options: [
{ value: "note", label: "Note" },
{ value: "warning", label: "Warning" },
],
initial_value: "note",
},
],
},
],
},
});
ブロックのフィールドは、スラッシュメニューと編集ダイアログでのブロックの表示を制御します。
| フィールド | 必須 | 動作 |
|---|---|---|
type |
はい | 保存されるPortable Textのブロックの _type と、描画コンポーネントの対応表のキーになる。有効なプラグイン全体で一意にする。 |
label |
はい | エディターでのブロックの名前。 |
icon |
いいえ | 一致するものがあれば、エディターが対応しているアイコンのキーを使う。ない場合、エディターは汎用のブロックのアイコンを表示する。 |
description |
いいえ | スラッシュメニューに補足のテキストを追加する。 |
category |
いいえ | スラッシュメニューでブロックをグループにまとめる。デフォルトのカテゴリーは Embeds。 |
placeholder |
いいえ | fields を省略したときの、シンプルなURL入力欄のプレースホルダーを設定する。 |
fields |
いいえ | シンプルなURL入力欄を、Block Kitのフォーム要素に置き換える。それぞれの action_id が、保存されるブロックのプロパティになる。 |
fields には、Block Kitで説明しているBlock Kitの要素の形を使います。この例では、次の値のような形のブロックが保存されます。
{
"_type": "callout",
"_key": "01JEXAMPLEKEY",
"heading": "Before you publish",
"body": "Check the preview on a small screen.",
"tone": "warning"
}
Astroコンポーネントの追加
-
保存されたブロックを
nodeとして受け取るAstroコンポーネントを作成します。src/astro/Callout.astro --- interface CalloutNode { _type: "callout"; _key: string; heading?: string; body?: string; tone?: "note" | "warning"; } interface Props { node: CalloutNode; } const { node } = Astro.props; --- <aside class:list={["callout", `callout--${node.tone ?? "note"}`]}> {node.heading && <p class="callout__heading"><strong>{node.heading}</strong></p>} {node.body && <p>{node.body}</p>} </aside>astro-portabletextは、独自のタイプのコンポーネントにnodeプロパティを渡します。ブロックをvalueとして渡すことはありません。この描画コンポーネントでは、省略可能な見出しに、スタイルを付けたテキストを使っています。ブロックはドキュメントのどの深さにも現れる可能性があるため、見出しの要素を固定すると、見出しのレベルが飛んだり重複したりする場合があるためです。 -
blockComponentsという名前の対応表で、コンポーネントをエクスポートします。src/astro/index.ts import Callout from "./Callout.astro"; export const blockComponents = { callout: Callout, };各キーは、ブロックの定義の
typeと一致している必要があります。 -
ディスクリプターのファクトリーに
componentsEntryを追加します。src/index.ts export function calloutPlugin(): PluginDescriptor { return { id: "plugin-callout", version: "0.1.0", format: "native", entrypoint: "@example/plugin-callout", componentsEntry: "@example/plugin-callout/astro", }; } -
npmパッケージから
./astroのエントリーをエクスポートします。このエントリーは、blockComponentsをエクスポートするモジュールを指している必要があります。パッケージの完全な定義は、ネイティブ型プラグインの配布にあります。
描画の優先順位と上書き
EmDashは、プラグインのコンポーネントを自動的に <PortableText> コンポーネントに追加します。コンポーネントは、次の順に統合されます。
- EmDashの組み込みのコンポーネント
- プラグインの
blockComponents - サイトが
<PortableText>に渡したコンポーネント
同じタイプのキーを持つものは、後のものが前のものを上書きします。そのため、サイトは、プラグインのエディター用の定義を有効にしたまま、コールアウトの描画コンポーネントだけを置き換えられます。
---
import { PortableText } from "emdash/ui";
import SiteCallout from "../components/SiteCallout.astro";
---
<PortableText
value={entry.body}
components={{
type: {
callout: SiteCallout,
},
}}
/>