Composants de rendu Portable Text

Sur cette page

Les plugins peuvent ajouter des types de blocs personnalisés à l’éditeur Portable Text — intégrations YouTube, extraits de code, galeries d’images, tout ce qui n’est pas couvert par l’ensemble de blocs par défaut. Les plugins sandboxed peuvent déclarer l’interface utilisateur d’édition pour ces blocs (en utilisant des champs Block Kit), mais les composants Astro qui les rendent sur le site public doivent être chargés au moment de la compilation depuis npm. C’est la partie qui nécessite un plugin natif.

Si votre plugin n’a besoin que de champs côté édition et que quelqu’un d’autre fournit les composants de rendu (ou que le site les fournit localement), vous pouvez rester sandboxed. Si le plugin doit également fournir les composants de rendu, vous devez être natif.

Déclarer les types de blocs

Les plugins sandboxed et natifs peuvent déclarer des types de blocs. Les plugins natifs le font à l’intérieur de definePlugin() sous 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" },
			],
		},
	],
},

Chaque type de bloc définit:

  • type — nom du type de bloc (utilisé dans Portable Text _type).
  • label — nom d’affichage dans le menu de commandes slash de l’éditeur.
  • iconvideo, code, link ou link-external. Revient à un cube générique par défaut.
  • placeholder — texte de l’espace réservé de saisie.
  • fields — champs de formulaire Block Kit pour l’édition. Si omis, une simple saisie d’URL est affichée.

Rendu sur le site public

Pour rendre les types de blocs sur le site public, exportez des composants Astro depuis un componentsEntry. Le nom d’exportation doit être blockComponents:

import YouTube from "./YouTube.astro";
import CodePen from "./CodePen.astro";

export const blockComponents = {
	youtube: YouTube,
	codepen: CodePen,
};

Définissez componentsEntry sur le descripteur:

export function myPlugin(): PluginDescriptor {
	return {
		id: "embeds",
		version: "1.0.0",
		format: "native",
		entrypoint: "@my-org/embeds",
		componentsEntry: "@my-org/embeds/astro",
	};
}

EmDash fusionne automatiquement les composants de blocs de plugins dans <PortableText> — les auteurs de sites n’ont rien à importer. Les composants fournis par l’utilisateur (déclarés dans la prop components de <PortableText> du site) ont la priorité sur les valeurs par défaut des plugins.

Exportations du package

Ajoutez l’exportation ./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" }
	}
}

L’exportation ./astro est côté serveur (Astro SSR), l’exportation ./admin est côté navigateur (React), et l’exportation "." est le descripteur + createPlugin. Gardez-les dans des fichiers séparés car ils sont empaquetés pour différents environnements.

Variantes compatibles avec le sandbox

Si vous voulez qu’un plugin soit sandboxed mais qu’il fournisse quand même une expérience de rendu par défaut, le modèle habituel est:

  1. Distribuez le plugin sandboxed (champs d’édition uniquement) sur le marketplace.
  2. Distribuez un package natif compagnon séparé sur npm qui fournit les composants de rendu Astro.
  3. Documentez les deux: les utilisateurs finaux installent le plugin sandboxed depuis le marketplace et utilisent npm install pour le package compagnon de rendu.

Cela échange une installation en une étape contre le maintien du côté éditeur en sandbox. La plupart des auteurs de plugins préfèrent simplement devenir natifs lorsque le rendu de blocs est impliqué — mais l’option existe.