Modules d’extension de moteur de rendu
Présentation
Section intitulée « Présentation »Les modules d’extension de moteur de rendu de StudioCMS offrent un moyen d’étendre et de personnaliser le processus de rendu de votre application StudioCMS. Ils vous permettent de modifier la façon dont le contenu est rendu côté client en ajoutant des composants personnalisés, des enveloppes ou d’autres modifications au pipeline de rendu.
Création d’un module d’extension de moteur de rendu
Section intitulée « Création d’un module d’extension de moteur de rendu »Le fichier principal du module d’extension
Section intitulée « Le fichier principal du module d’extension »Pour créer un module d’extension de moteur de rendu, vous devez définir un module d’extension pour StudioCMS qui enregistre votre type de page personnalisé et le composant associé à son moteur de rendu. Vous trouverez ci-dessous un exemple de création d’un module d’extension de moteur de rendu simple qui ajoute un type de page personnalisé avec un moteur de rendu et un composant d’édition.
import { function definePlugin(options: StudioCMSPlugin): StudioCMSPlugin
Defines a plugin for StudioCMS.
definePlugin } from 'studiocms/plugins';import { const createResolver: (_base: string) => { resolve: (...path: Array<string>) => string;}
Allows resolving paths relatively to the integration folder easily. Call it like this:
createResolver } from 'astro-integration-kit';import { (alias) interface AstroIntegrationimport AstroIntegration
AstroIntegration } from 'astro';
const { const resolve: (...path: Array<string>) => string
resolve } = function createResolver(_base: string): { resolve: (...path: Array<string>) => string;}
Allows resolving paths relatively to the integration folder easily. Call it like this:
createResolver(import.
The type of import.meta.
If you need to declare that a given property exists on import.meta,
this type may be augmented via interface merging.
meta.ImportMeta.url: string
The absolute file: URL of the module.
This is defined exactly the same as it is in browsers providing the URL of the
current module file.
This enables useful patterns such as relative file loading:
import { readFileSync } from 'node:fs';const buffer = readFileSync(new URL('./data.proto', import.meta.url));
url);
// Définit le module d’extension pour StudioCMSexport const const myPlugin: () => StudioCMSPlugin
myPlugin = () => function definePlugin(options: StudioCMSPlugin): StudioCMSPlugin
Defines a plugin for StudioCMS.
definePlugin({ StudioCMSPlugin.identifier: string
The identifier of the plugin, usually the package name.
identifier: 'mon-module-extension', StudioCMSPlugin.name: string
The name of the plugin, displayed in the StudioCMS Dashboard.
name: 'Mon module d’extension', StudioCMSPlugin.studiocmsMinimumVersion: string
The minimum version of StudioCMS required for this plugin to function correctly.
This is used to ensure compatibility between the plugin and the StudioCMS core.
It should be a semantic version string (e.g., "1.0.0").
If the plugin is not compatible with the current version of StudioCMS, it should not be loaded.
This is a required field.
studiocmsMinimumVersion: '0.1.0', StudioCMSPlugin.hooks: { 'studiocms:astro-config'?: PluginHook<{ logger: AstroIntegrationLogger; addIntegrations: (args_0: AstroIntegration | AstroIntegration[]) => void; }>; ... 5 more ...; 'studiocms:sitemap'?: PluginHook<...>;} & Partial<...>
hooks: { 'studiocms:rendering': ({ setRendering: (args_0: { pageTypes?: { label: string; identifier: string; fields?: ({ name: string; label: string; input: "checkbox"; required?: boolean | undefined; readOnly?: boolean | undefined; color?: "primary" | "success" | "warning" | "danger" | "info" | "mono" | undefined; defaultChecked?: boolean | undefined; size?: "sm" | "md" | "lg" | undefined; } | { name: string; label: string; input: "input"; type?: "number" | "password" | "text" | "email" | "tel" | "url" | "search" | undefined; required?: boolean | undefined; readOnly?: boolean | undefined; placeholder?: string | undefined; defaultValue?: string | undefined; } | { name: string; label: string; input: "textarea"; required?: boolean | undefined; readOnly?: boolean | undefined; placeholder?: string | undefined; defaultValue?: string | undefined; } | { options: { value: string; label: string; disabled?: boolean | undefined; }[]; name: string; label: string; input: "radio"; required?: boolean | undefined; readOnly?: boolean | undefined; color?: "primary" | "success" | "warning" | "danger" | "info" | "mono" | undefined; defaultValue?: string | undefined; direction?: "horizontal" | "vertical" | undefined; } | { options: { value: string; label: string; disabled?: boolean | undefined; }[]; name: string; label: string; input: "select"; type?: "search" | "basic" | undefined; required?: boolean | undefined; readOnly?: boolean | undefined; placeholder?: string | undefined; defaultValue?: string | undefined; } | { name: string; label: string; input: "row"; fields: ({ name: string; label: string; input: "checkbox"; required?: boolean | undefined; readOnly?: boolean | undefined; color?: "primary" | "success" | "warning" | "danger" | "info" | "mono" | undefined; defaultChecked?: boolean | undefined; size?: "sm" | "md" | "lg" | undefined; } | { name: string; label: string; input: "input"; type?: "number" | "password" | "text" | "email" | "tel" | "url" | "search" | undefined; required?: boolean | undefined; readOnly?: boolean | undefined; placeholder?: string | undefined; defaultValue?: string | undefined; } | { name: string; label: string; input: "textarea"; required?: boolean | undefined; readOnly?: boolean | undefined; placeholder?: string | undefined; defaultValue?: string | undefined; } | { options: { value: string; label: string; disabled?: boolean | undefined; }[]; name: string; label: string; input: "radio"; required?: boolean | undefined; readOnly?: boolean | undefined; color?: "primary" | "success" | "warning" | "danger" | "info" | "mono" | undefined; defaultValue?: string | undefined; direction?: "horizontal" | "vertical" | undefined; } | { options: { value: string; label: string; disabled?: boolean | undefined; }[]; name: string; label: string; input: "select"; type?: "search" | "basic" | undefined; required?: boolean | undefined; readOnly?: boolean | undefined; placeholder?: string | undefined; defaultValue?: string | undefined; })[]; required?: boolean | undefined; readOnly?: boolean | undefined; alignCenter?: boolean | undefined; gapSize?: "sm" | "md" | "lg" | undefined; })[] | undefined; description?: string | undefined; pageContentComponent?: string | undefined; rendererComponent?: string | undefined; apiEndpoint?: string | undefined; }[] | undefined; augments?: ({ type: "component"; components ...
setRendering }) => { setRendering: (args_0: { pageTypes?: { label: string; identifier: string; fields?: ({ name: string; label: string; input: "checkbox"; required?: boolean | undefined; readOnly?: boolean | undefined; color?: "primary" | "success" | "warning" | "danger" | "info" | "mono" | undefined; defaultChecked?: boolean | undefined; size?: "sm" | "md" | "lg" | undefined; } | { name: string; label: string; input: "input"; type?: "number" | "password" | "text" | "email" | "tel" | "url" | "search" | undefined; required?: boolean | undefined; readOnly?: boolean | undefined; placeholder?: string | undefined; defaultValue?: string | undefined; } | { name: string; label: string; input: "textarea"; required?: boolean | undefined; readOnly?: boolean | undefined; placeholder?: string | undefined; defaultValue?: string | undefined; } | { options: { value: string; label: string; disabled?: boolean | undefined; }[]; name: string; label: string; input: "radio"; required?: boolean | undefined; readOnly?: boolean | undefined; color?: "primary" | "success" | "warning" | "danger" | "info" | "mono" | undefined; defaultValue?: string | undefined; direction?: "horizontal" | "vertical" | undefined; } | { options: { value: string; label: string; disabled?: boolean | undefined; }[]; name: string; label: string; input: "select"; type?: "search" | "basic" | undefined; required?: boolean | undefined; readOnly?: boolean | undefined; placeholder?: string | undefined; defaultValue?: string | undefined; } | { name: string; label: string; input: "row"; fields: ({ name: string; label: string; input: "checkbox"; required?: boolean | undefined; readOnly?: boolean | undefined; color?: "primary" | "success" | "warning" | "danger" | "info" | "mono" | undefined; defaultChecked?: boolean | undefined; size?: "sm" | "md" | "lg" | undefined; } | { name: string; label: string; input: "input"; type?: "number" | "password" | "text" | "email" | "tel" | "url" | "search" | undefined; required?: boolean | undefined; readOnly?: boolean | undefined; placeholder?: string | undefined; defaultValue?: string | undefined; } | { name: string; label: string; input: "textarea"; required?: boolean | undefined; readOnly?: boolean | undefined; placeholder?: string | undefined; defaultValue?: string | undefined; } | { options: { value: string; label: string; disabled?: boolean | undefined; }[]; name: string; label: string; input: "radio"; required?: boolean | undefined; readOnly?: boolean | undefined; color?: "primary" | "success" | "warning" | "danger" | "info" | "mono" | undefined; defaultValue?: string | undefined; direction?: "horizontal" | "vertical" | undefined; } | { options: { value: string; label: string; disabled?: boolean | undefined; }[]; name: string; label: string; input: "select"; type?: "search" | "basic" | undefined; required?: boolean | undefined; readOnly?: boolean | undefined; placeholder?: string | undefined; defaultValue?: string | undefined; })[]; required?: boolean | undefined; readOnly?: boolean | undefined; alignCenter?: boolean | undefined; gapSize?: "sm" | "md" | "lg" | undefined; })[] | undefined; description?: string | undefined; pageContentComponent?: string | undefined; rendererComponent?: string | undefined; apiEndpoint?: string | undefined; }[] | undefined; augments?: ({ type: "component"; components ...
setRendering({ pageTypes?: { label: string; identifier: string; fields?: ({ name: string; label: string; input: "checkbox"; required?: boolean | undefined; readOnly?: boolean | undefined; color?: "primary" | "success" | "warning" | "danger" | "info" | "mono" | undefined; defaultChecked?: boolean | undefined; size?: "sm" | "md" | "lg" | undefined; } | { name: string; label: string; input: "input"; type?: "number" | "password" | "text" | "email" | "tel" | "url" | "search" | undefined; required?: boolean | undefined; readOnly?: boolean | undefined; placeholder?: string | undefined; defaultValue?: string | undefined; } | { name: string; label: string; input: "textarea"; required?: boolean | undefined; readOnly?: boolean | undefined; placeholder?: string | undefined; defaultValue?: string | undefined; } | { options: { value: string; label: string; disabled?: boolean | undefined; }[]; name: string; label: string; input: "radio"; required?: boolean | undefined; readOnly?: boolean | undefined; color?: "primary" | "success" | "warning" | "danger" | "info" | "mono" | undefined; defaultValue?: string | undefined; direction?: "horizontal" | "vertical" | undefined; } | { options: { value: string; label: string; disabled?: boolean | undefined; }[]; name: string; label: string; input: "select"; type?: "search" | "basic" | undefined; required?: boolean | undefined; readOnly?: boolean | undefined; placeholder?: string | undefined; defaultValue?: string | undefined; } | { name: string; label: string; input: "row"; fields: ({ name: string; label: string; input: "checkbox"; required?: boolean | undefined; readOnly?: boolean | undefined; color?: "primary" | "success" | "warning" | "danger" | "info" | "mono" | undefined; defaultChecked?: boolean | undefined; size?: "sm" | "md" | "lg" | undefined; } | { name: string; label: string; input: "input"; type?: "number" | "password" | "text" | "email" | "tel" | "url" | "search" | undefined; required?: boolean | undefined; readOnly?: boolean | undefined; placeholder?: string | undefined; defaultValue?: string | undefined; } | { name: string; label: string; input: "textarea"; required?: boolean | undefined; readOnly?: boolean | undefined; placeholder?: string | undefined; defaultValue?: string | undefined; } | { options: { value: string; label: string; disabled?: boolean | undefined; }[]; name: string; label: string; input: "radio"; required?: boolean | undefined; readOnly?: boolean | undefined; color?: "primary" | "success" | "warning" | "danger" | "info" | "mono" | undefined; defaultValue?: string | undefined; direction?: "horizontal" | "vertical" | undefined; } | { options: { value: string; label: string; disabled?: boolean | undefined; }[]; name: string; label: string; input: "select"; type?: "search" | "basic" | undefined; required?: boolean | undefined; readOnly?: boolean | undefined; placeholder?: string | undefined; defaultValue?: string | undefined; })[]; required?: boolean | undefined; readOnly?: boolean | undefined; alignCenter?: boolean | undefined; gapSize?: "sm" | "md" | "lg" | undefined; })[] | undefined; description?: string | undefined; pageContentComponent?: string | undefined; rendererComponent?: string | undefined; apiEndpoint?: string | undefined;}[] | undefined
pageTypes: [ { identifier: string
identifier: 'mon-type-page-personnalise', label: string
label: 'Mon type de page personnalisé', rendererComponent?: string | undefined
rendererComponent: const resolve: (...path: Array<string>) => string
resolve('./components/render.js'), pageContentComponent?: string | undefined
pageContentComponent: const resolve: (...path: Array<string>) => string
resolve('./components/Editor.astro') } ] }) } }});Le composant de moteur de rendu
Section intitulée « Le composant de moteur de rendu »Pour le composant de moteur de rendu, vous devez créer un fichier JavaScript ou TypeScript (si vous avez une étape de compilation) qui exporte un objet conforme au type PluginRenderer. Cet objet doit inclure la logique de rendu de votre type de page personnalisé.
import type { (alias) interface PluginRendererimport PluginRenderer
Represents a plugin renderer with optional sanitization and rendering logic.
PluginRenderer } from 'studiocms/types';
const const render: { name: string; renderer: (content: string) => Promise<string>; sanitizeOpts: {};}
render = { PluginRenderer.name: string
name: 'mon-moteur-rendu-personnalise', PluginRenderer.renderer?: GenericAsyncFn<string, string>
renderer: async (content: string
content: string) => { // La logique de rendu personnalisée se trouve ici return content: string
content; }, PluginRenderer.sanitizeOpts?: SanitizeOptions
sanitizeOpts: {},} satisfies (alias) interface PluginRendererimport PluginRenderer
Represents a plugin renderer with optional sanitization and rendering logic.
PluginRenderer;
export default const render: { name: string; renderer: (content: string) => Promise<string>; sanitizeOpts: {};}
render;Le composant d’édition
Section intitulée « Le composant d’édition »Pour le composant d’édition, vous devez créer un composant Astro qui fournit une interface utilisateur pour modifier le contenu de votre type de page personnalisé. Ce composant recevra le contenu actuel en tant que propriété et devra émettre des mises à jour du contenu au fur et à mesure que l’utilisateur effectue des modifications. La zone de texte <textarea> ci-dessous est utilisée dans le formulaire d’édition de la page finale, permettant aux utilisateurs de modifier directement le contenu. Par conséquent, toute modification effectuée dans un composant d’édition personnalisé doit mettre à jour la valeur de ce champ <textarea> afin de garantir que le contenu soit correctement enregistré.
---import type { PluginPageTypeEditorProps } from 'studiocms/types';
interface Props extends PluginPageTypeEditorProps {}
const { content } = Astro.props;---<div class="editor-container"> <textarea id="page-content" name="page-content">{content}</textarea></div>Lectures complémentaires
Section intitulée « Lectures complémentaires »Si vous souhaitez créer un frontend personnalisé pour votre projet StudioCMS, vous pouvez utiliser le composant Renderer et le SDK de StudioCMS pour afficher le contenu de StudioCMS à l’aide de vos modules d’extension de rendu personnalisés.