Documentation Guides pratiques
Blocs personnalisés
Définissez les champs et le rendu de vos propres blocs dans votre application.
Sur cette page
Définir un bloc
Passez un tableau customBlocks. Les fonctions de rendu s’exécutent dans votre application et renvoient du HTML, directement ou via une promesse. L’iframe reçoit uniquement du JSON et un fragment HTML. Le SDK ne dépend pas de React.
<script src="https://weavour.com/editor/sdk/0.1.12/editor.js"></script>
<div id="email-editor" style="height: 800px"></div>
<script>
const escapeHTML = value => String(value).replace(/[&<>"']/g, char =>
({ '&': '&', '<': '<', '>': '>', '"': '"', "'": ''' }[char]));
const editor = Weavour.mount('#email-editor', {
editorKey: 'YOUR_PUBLIC_EDITOR_KEY',
userId: 'user-123', organizationId: 'org-456',
customBlocks: [{
id: 'product-card', version: 1, label: 'Product card',
defaultProps: { title: 'New product', href: 'https://example.com/product' },
controls: {
title: { type: 'text', label: 'Product name', required: true },
href: { type: 'url', label: 'Product link' },
},
render: props => '<table role="presentation" width="100%"><tbody><tr>' +
'<td style="padding:24px"><h2>' + escapeHTML(props.title) + '</h2>' +
'<a href="' + escapeHTML(props.href) + '">View product</a></td></tr></tbody></table>',
}],
onDocumentChange(document) { /* Save the complete envelope in your backend. */ },
});
</script>Référence d’une définition
| Propriété | Contrat |
|---|---|
| id | Identifiant stable : une lettre initiale, puis lettres, chiffres, tirets ou tirets bas ; 64 caractères au maximum. |
| version | Entier positif. Avec id, désigne précisément le rendu et les contrôles. |
| label | Nom affiché, limité à 200 caractères. Les libellés de votre application ne sont pas traduits par l’éditeur. |
| defaultProps | Objet JSON copié à l’insertion ; les propriétés déjà enregistrées restent intactes. |
| controls | Champs indexés par nom de propriété, chacun avec un libellé et une valeur initiale compatible. |
| render(props) | Renvoie un fragment HTML avec styles en ligne, ou Promise<string> ; s’exécute dans votre application. |
| iconSvg | Chaîne SVG statique facultative, remplaçant la miniature automatique de la palette. |
Utiliser React Email
Installez React, @react-email/components et @react-email/render dans votre application. Combinaisons testées : components 1.0.12, render 2.2.0 et React 19.3.1, avec Section, Row, Column, Text, Button et Img. Renvoyez un fragment autonome, sans Html, Head, Body ni styles d’en-tête.
import { defineCustomBlock } from '@weavour/editor';
import { WeavourEditor } from '@weavour/react';
import { Section, Text, Button } from '@react-email/components';
import { render } from '@react-email/render';
export const productCard = defineCustomBlock({
id: 'product-card', version: 1, label: 'Product card',
defaultProps: { title: 'New product', href: 'https://example.com/product' },
controls: {
title: { type: 'text', label: 'Product name', required: true },
href: { type: 'url', label: 'Product link' },
},
async render(props) {
const html = await render(
<Section><Text>{props.title}</Text>
<Button href={props.href} style={{ padding: '12px 24px' }}>View product</Button>
</Section>
);
// React Email adds a doctype even when rendering a body fragment.
return html.replace(/^<!doctype[^>]*>/i, '');
},
});
export function CampaignEditor() {
return <WeavourEditor
editorKey="YOUR_PUBLIC_EDITOR_KEY"
userId="user-123" organizationId="org-456"
customBlocks={[productCard]} style={{ height: 800 }}
/>;
}Champs et images
Chaque contrôle exige un libellé et une valeur par défaut compatible. Les images se choisissent dans la bibliothèque du périmètre courant, avec recadrage. Leur descripteur est { src, assetId, width, height, alt } : utilisez src et alt pour le rendu. Un assetId n’accorde aucun accès. D’autres propriétés JSON bornées peuvent conserver vos données.
| Type | Valeur | Options |
|---|---|---|
| text / textarea | string | placeholder, required, maxLength |
| url | string | required; merge tags |
| image | descriptor | null | required; src, assetId, width, height, alt |
| number | number | min, max, step |
| select | string | options: [{ label, value }] |
| boolean | boolean | |
| color | string | #rrggbb |
Insérer et modifier
Les blocs personnalisés suivent les blocs standard dans la même grille Blocs, sans titre ni séparateur. Les blocs d’organisation enregistrés suivent les blocs personnalisés dans cette même grille. Le champ Rechercher des blocs filtre les trois types par nom ; videz-le ou appuyez sur Échap pour tout réafficher. Cliquez, glissez un bloc ou sélectionnez sa tuile au clavier puis appuyez sur Entrée. Le panneau Bloc génère les champs de votre définition ; les listes de choix reprennent le menu et le thème des contrôles standard. Déplacement, duplication, suppression et annulation restent disponibles. Pendant le rendu, un nouveau bloc réserve une zone de sélection vide ; une mise à jour conserve l’aperçu précédent et affiche un indicateur animé dans le panneau. Les erreurs et la relance restent dans ce panneau, hors du contenu de l’e-mail.
Icônes de la palette
Sans iconSvg, la palette trace une miniature filaire à partir de la mise en page de render(defaultProps). Un aperçu enregistré correspondant est réutilisé ; sinon, la fonction est appelée une fois par définition et génération du registre, dans les limites de rendu communes. Les icônes restent en cache lors des changements d’onglet ou de thème. La mesure ne charge aucune ressource externe ; les images sans dimensions utilisent un cadre indicatif. En cas d’échec, une icône générique permet toujours l’insertion. Pour remplacer la miniature et éviter cet appel, fournissez iconSvg : une chaîne SVG statique avec viewBox. Géométrie acceptée : g, path, rect, circle, ellipse, line, polyline et polygon. Les couleurs suivent le thème, en conservant none. Scripts, événements, styles, texte, références et contenu intégré sont refusés. Limites : 16 KiB UTF-8, 128 éléments, 12 niveaux. Les icônes ne modifient ni document, ni historique, ni export.
// Optional property on a custom-block definition. Omit for an automatic outline.
const iconSvg = '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6">' +
'<rect x="3" y="3" width="18" height="18" rx="2"/>' +
'<path d="M7 8h10M7 12h6M7 16h8"/></svg>';
// Keep the renderer and controls; replace only the palette icon.
editor.updateConfig({ customBlocks: [{ ...productCard, iconSvg }] });Versions et configuration dynamique
Enregistrez les couples exacts (id, version). La palette insère la version la plus récente. Incrémentez la version si le rendu, les valeurs par défaut ou les contrôles changent. Conservez les anciennes versions pour modifier les anciens blocs. Les propriétés et aperçus existants restent intacts. customBlocks au premier niveau prime sur editorConfig.customBlocks. updateConfig({ customBlocks }) remplace le registre ; [] le vide ; l’omission le conserve. Les propriétés React se mettent à jour sans remonter l’éditeur.
// productCard is the definition from the React Email example above.
editor.updateConfig({ customBlocks: [productCard] });
// Include each custom ID when supplying an explicit insertion allowlist.
editor.updateConfig({
allowedBlocks: ['text', 'heading', 'section', 'custom:product-card'],
});
// Remove registrations without deleting existing email content.
editor.updateConfig({ customBlocks: [] });Sauvegarde, aperçu et export
Conservez l’enveloppe complète onDocumentChange de schéma 3 et rechargez-la avec emailDocument. Elle contient les références, propriétés et aperçus HTML validés ; les fonctions et icônes ne sont pas enregistrées. Les brouillons gardent les modifications dont le rendu reste incomplet. Export, e-mail de test et création de modèles ou blocs d’organisation attendent le rendu actuel. Sans fonction correspondante, les aperçus valides restent visibles et exportables ; les champs ne sont pas modifiables. Rouvrir un aperçu valide ne relance pas le rendu de ce bloc ; la palette peut séparément évaluer les valeurs initiales pour son icône. Le tableau de bord utilise les aperçus enregistrés. Les blocs d’organisation sont des mises en page réutilisables contenant des blocs standard ou personnalisés ; leur sauvegarde exige organizationId.
HTML et personnalisation
Renvoyez tableaux, liens, texte et images avec des styles en ligne. Les commentaires Outlook pris en charge sont conservés. Scripts, événements, formulaires, iframes, objets, éléments de document, CSS d’en-tête et URL CSS sont refusés. Échappez les valeurs. Les variables connues restent littérales dans le rendu ; utilisez les variables et conditions de mise en page pour personnaliser les destinataires. Weavour ne récupère pas leurs données.
Restrictions de blocs
Une liste allowedBlocks explicite doit inclure custom:product-card pour insérer cet exemple. Sans liste, les blocs enregistrés sont disponibles. Les restrictions conservent les blocs existants. Le transport du code personnalisé est désactivé dans la démo publique. Mettez à jour le SDK et les lecteurs hébergés avant d’activer l’écriture du schéma 3 ; les anciens clients refusent explicitement ce contenu.
Limites et résolution des erreurs
Par montage : 50 versions, 32 contrôles par version, 100 blocs, 32 Kio de propriétés UTF-8 et 100 Kio de HTML par bloc, quatre rendus actifs et 100 requêtes en attente. Délai de saisie : 150 ms ; expiration : cinq secondes. Le schéma 3 est limité à 1 000 000 octets cumulés, aperçus compris ; les limites de transport s’appliquent aussi. Les fonctions doivent terminer rapidement, sans effets de bord. Le JavaScript synchrone ne peut pas être interrompu. Conservez les données résolues dans les propriétés. Relancez le rendu, rétablissez la version exacte ou réduisez sa taille. L’IA de remplacement complet est indisponible avec ces blocs.