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 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 des types de blocs

Les plugins sandboxed et natifs peuvent tous deux 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 placeholder d’entrée.
  • fields — champs de formulaire Block Kit pour l’édition. Si omis, une simple entrée URL est affichée.

Rendu sur le site public

Pour rendre les types de blocs sur le site public, exportez les 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 des plugins dans <PortableText> — les auteurs de sites n’ont rien besoin d’importer. Les composants fournis par l’utilisateur (déclarés dans la prop components du site sur <PortableText>) ont la priorité sur les valeurs par défaut du plugin.

Exportations de 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 regroupés pour différents environnements.

Variantes adaptées au sandbox

Si vous souhaitez qu’un plugin soit sandboxed mais qu’il offre tout de 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 exécutent npm install du package compagnon pour le rendu.

Cela échange une installation en une étape contre le maintien du côté éditeur sandboxed. Devenir entièrement natif est plus simple lorsque le rendu de blocs est impliqué, mais cette division reste une option.