Mon premier bloc Gutenberg
1. Pourquoi créer un bloc Gutenberg ?
Quelques lignes pour expliquer qu’un bloc permet d’ajouter une fonctionnalité sur mesure à l’éditeur WordPress sans avoir à écrire du HTML à chaque fois.
Dans ce tutoriel, nous allons créer un bloc qui affichera la date et le saint du jour, pour ne jamais oublier de souhaitez leur fête à nos amis.
2. Les prérequis
Préparez votre environnement de développement. Il est probable que vous ayez déjà un environnement de développement pour le web installé, n’hésitez pas à garder vos outils préférés. Pour les grands débutants, voici une liste d’outils gratuits et très facile à installer sous Windows.
- Un environnement de développement Php / MySQL, par exemple WampServer.
- WordPress installé
- L’environnement de développement Node.js
- Un éditeur de code, par exemple Notepad++
3. Créer le plugin
Pour créer un bloc Gutenberg, nous allons utiliser l’outil officiel fourni par WordPress. Il génère automatiquement la structure du plugin et tous les fichiers nécessaires.
Se placer dans le dossier des extensions
Ouvrez un terminale de commande en mode administrateur, par un clique droit sur l’icône Windows.
Ouvrez le dossier des plugins. Le chemin devrait ressembler à :
cd C:\wamp64\www\monsite\wp-content\plugins
Générer le plugin
Dans le terminal, exécutez la commande suivante :
npx @wordpress/create-block mon-premier-bloc
Vous pouvez remplacer
mon-premier-blocpar le nom de votre choix. Ce nom sera également utilisé pour créer le dossier du plugin.
L’outil télécharge automatiquement les fichiers nécessaires, crée le dossier du plugin et installe les dépendances.
À la fin de l’opération, un nouveau dossier apparaît :
wp-content/
└── plugins/
└── mon-premier-bloc/
Découvrir la structure du projet
Ouvrez ce dossier dans votre éditeur de code. Vous devriez obtenir une structure proche de celle-ci, avec des fichiers supplémentaires pour la gestion du projet :
mon-premier-bloc/
├── build/
├── node_modules/
├── src/
│ └── mon-premier-bloc/
│ ├── block.json
│ ├── edit.js
│ ├── editor.scss
│ ├── index.js
│ ├── save.js
│ ├── style.scss
│ └── view.js
├── mon-premier-bloc.php
├── package.json
└── readme.txt
Nous allons essentiellement nous concentrer sur les fichiers présents dans le répertoire src.
| Fichier | Rôle |
|---|---|
| block.json | Décrit le bloc (nom, catégorie, icône, scripts et styles). C’est le fichier de configuration principal. |
| edit.js | Définit l’interface du bloc dans l’éditeur Gutenberg. C’est ici que l’utilisateur interagit avec le bloc. |
| save.js | Génère le HTML qui sera enregistré dans le contenu de l’article. |
| index.js | Enregistre le bloc auprès de WordPress et importe les autres fichiers nécessaires à son fonctionnement. |
| editor.scss | Contient les styles appliqués uniquement dans l’éditeur Gutenberg. |
| style.scss | Contient les styles appliqués aussi bien dans l’éditeur que sur le site. |
| view.js | Permet d’ajouter du JavaScript côté visiteur si le bloc en a besoin. Nous ne l’utiliserons pas dans ce tutoriel. |
| package.json | Liste les dépendances du projet et les commandes npm disponibles. |
| mon-premier-bloc.php | Fichier principal du plugin. Il permet à WordPress de détecter et de charger automatiquement le bloc. |
4. Structurer les données
Dans le fichier block.json nous allons définir les données que nous souhaitons paramétrer/sauvegarder dans le plugin en rajoutant des attributs juste après la définition du text-domain. Ici nous allons choisir d’affiche ou non la date.
{
"$schema": "https://schemas.wp.org/trunk/block.json",
"apiVersion": 3,
"name": "create-block/mon-premier-bloc",
"version": "0.1.0",
"title": "Mon Premier Bloc",
"category": "widgets",
"icon": "smiley",
"description": "Example block",
"example": {},
"supports": {
"html": false
},
"textdomain": "mon-premier-bloc",
"attributes": {
"showDate": {
"type": "boolean",
"default": true
}
},
"editorScript": "file:./index.js",
"editorStyle": "file:./index.css",
"style": "file:./style-index.css",
"viewScript": "file:./view.js"
}
Ces données seront stockées directement dans la page qui héberge le bloc. Si on regarde le code source on vera :
<!-- wp:create-block/mon-premier-bloc -->
<div class="wp-block-create-block-mon-premier-bloc"><div class="saint-du-jour"><p>📅 20/07</p><h4>Saint du jour</h4><p>✨ Marina</p></div></div>
<!-- /wp:create-block/mon-premier-bloc -->
5. Construire notre premier bloc
Nous allons ensuite créer un nouveau fichier saints.js dans le répertoire source. Nous pouvons ajouter autant de scripts au code que nécessaire pour garder un projet organisé et facile à maintenir. Il contiendra dans notre exemple la liste des prénoms que nous allons utiliser :
export const saints = {
"01-01": "Marie",
"02-01": "Basile",
"03-01": "Geneviève",
// ...
"31-12": "Sylvestre",
};
Voici une liste complète si vous souhaitez copier-coller pour tester
export const saints = {
// Janvier
"01-01": "Marie",
"02-01": "Basile",
"03-01": "Geneviève",
"04-01": "Odilon",
"05-01": "Édouard",
"06-01": "Mélaine",
"07-01": "Raymond",
"08-01": "Lucien",
"09-01": "Alix",
"10-01": "Guillaume",
"11-01": "Paulin",
"12-01": "Tatiana",
"13-01": "Yvette",
"14-01": "Nina",
"15-01": "Rémi",
"16-01": "Marcel",
"17-01": "Roseline",
"18-01": "Prisca",
"19-01": "Marius",
"20-01": "Sébastien",
"21-01": "Agnès",
"22-01": "Vincent",
"23-01": "Barnard",
"24-01": "François",
"25-01": "Artemis",
"26-01": "Paule",
"27-01": "Angèle",
"28-01": "Thomas",
"29-01": "Gildas",
"30-01": "Martine",
"31-01": "Marcelle",
// Février
"01-02": "Ella",
"02-02": "Théophane",
"03-02": "Blaise",
"04-02": "Véronique",
"05-02": "Agathe",
"06-02": "Gaston",
"07-02": "Eugénie",
"08-02": "Jacqueline",
"09-02": "Apolline",
"10-02": "Arnaud",
"11-02": "Héloïse",
"12-02": "Félix",
"13-02": "Béatrice",
"14-02": "Valentin",
"15-02": "Claude",
"16-02": "Julienne",
"17-02": "Alexis",
"18-02": "Bernadette",
"19-02": "Gabin",
"20-02": "Aimée",
"21-02": "Gwen",
"22-02": "Isabelle",
"23-02": "Lazare",
"24-02": "Modeste",
"25-02": "Roméo",
"26-02": "Nestor",
"27-02": "Honorine",
"28-02": "Romain",
"29-02": "Auguste",
// Mars
"01-03": "Aubin",
"02-03": "Charles",
"03-03": "Guénolé",
"04-03": "Casimir",
"05-03": "Olive",
"06-03": "Colette",
"07-03": "Félicité",
"08-03": "Jean",
"09-03": "Françoise",
"10-03": "Vivien",
"11-03": "Rosine",
"12-03": "Justine",
"13-03": "Rodrigue",
"14-03": "Mathilde",
"15-03": "Louise",
"16-03": "Bénédicte",
"17-03": "Patrice",
"18-03": "Cyrille",
"19-03": "Joseph",
"20-03": "Herbert",
"21-03": "Clémence",
"22-03": "Léa",
"23-03": "Victorien",
"24-03": "Catherine",
"25-03": "Humbert",
"26-03": "Larissa",
"27-03": "Habib",
"28-03": "Gontran",
"29-03": "Gwladys",
"30-03": "Amédée",
"31-03": "Benjamin",
// Avril
"01-04": "Hugues",
"02-04": "Sandrine",
"03-04": "Richard",
"04-04": "Isidore",
"05-04": "Irène",
"06-04": "Marcellin",
"07-04": "Jean-Baptiste",
"08-04": "Julie",
"09-04": "Gauthier",
"10-04": "Fulbert",
"11-04": "Stanislas",
"12-04": "Jules",
"13-04": "Ida",
"14-04": "Maxime",
"15-04": "Paterne",
"16-04": "Benoît-Joseph",
"17-04": "Anicet",
"18-04": "Parfait",
"19-04": "Emma",
"20-04": "Odette",
"21-04": "Anselme",
"22-04": "Alexandre",
"23-04": "Georges",
"24-04": "Fidèle",
"25-04": "Marc",
"26-04": "Alida",
"27-04": "Zita",
"28-04": "Valérie",
"29-04": "Catherine",
"30-04": "Robert",
// Mai
"01-05": "Jérémie",
"02-05": "Boris",
"03-05": "Philippe",
"04-05": "Sylvain",
"05-05": "Judith",
"06-05": "Prudence",
"07-05": "Gisèle",
"08-05": "Désiré",
"09-05": "Pacôme",
"10-05": "Solange",
"11-05": "Estelle",
"12-05": "Achille",
"13-05": "Rolande",
"14-05": "Matthias",
"15-05": "Denise",
"16-05": "Honoré",
"17-05": "Pascal",
"18-05": "Éric",
"19-05": "Yves",
"20-05": "Bernardin",
"21-05": "Constantin",
"22-05": "Émile",
"23-05": "Didier",
"24-05": "Donatien",
"25-05": "Sophie",
"26-05": "Bérenger",
"27-05": "Augustin",
"28-05": "Germain",
"29-05": "Aymard",
"30-05": "Ferdinand",
"31-05": "Perrine",
// Juin
"01-06": "Justin",
"02-06": "Blandine",
"03-06": "Kévin",
"04-06": "Clotilde",
"05-06": "Igor",
"06-06": "Norbert",
"07-06": "Gilbert",
"08-06": "Médard",
"09-06": "Diane",
"10-06": "Landry",
"11-06": "Barnabé",
"12-06": "Guy",
"13-06": "Antoine",
"14-06": "Élisée",
"15-06": "Germaine",
"16-06": "Jean-François",
"17-06": "Hervé",
"18-06": "Léonce",
"19-06": "Romuald",
"20-06": "Silvère",
"21-06": "Rodolphe",
"22-06": "Alban",
"23-06": "Audrey",
"24-06": "Jean-Baptiste",
"25-06": "Prosper",
"26-06": "Anthelme",
"27-06": "Fernand",
"28-06": "Irénée",
"29-06": "Pierre et Paul",
"30-06": "Martial",
// Juillet
"01-07": "Thierry",
"02-07": "Martinien",
"03-07": "Thomas",
"04-07": "Florent",
"05-07": "Antoine",
"06-07": "Mariette",
"07-07": "Raoul",
"08-07": "Thibaut",
"09-07": "Amandine",
"10-07": "Ulrich",
"11-07": "Benoît",
"12-07": "Olivier",
"13-07": "Henri",
"14-07": "Camille",
"15-07": "Donald",
"16-07": "Carmen",
"17-07": "Charlotte",
"18-07": "Frédéric",
"19-07": "Arsène",
"20-07": "Marina",
"21-07": "Victor",
"22-07": "Marie-Madeleine",
"23-07": "Brigitte",
"24-07": "Christine",
"25-07": "Jacques",
"26-07": "Anne",
"27-07": "Nathalie",
"28-07": "Samson",
"29-07": "Marthe",
"30-07": "Juliette",
"31-07": "Ignace",
// Août
"01-08": "Alphonse",
"02-08": "Julien",
"03-08": "Lydie",
"04-08": "Jean-Marie",
"05-08": "Abel",
"06-08": "Octavien",
"07-08": "Gaétan",
"08-08": "Dominique",
"09-08": "Amour",
"10-08": "Laurent",
"11-08": "Claire",
"12-08": "Jeanne",
"13-08": "Hippolyte",
"14-08": "Évrard",
"15-08": "Marie, Assomption",
"16-08": "Armel",
"17-08": "Hyacinthe",
"18-08": "Hélène",
"19-08": "Jean-Eudes",
"20-08": "Bernard",
"21-08": "Christophe",
"22-08": "Fabrice",
"23-08": "Rose",
"24-08": "Barthélémy",
"25-08": "Louis",
"26-08": "Adrien",
"27-08": "Monique",
"28-08": "Augustin",
"29-08": "Sabine",
"30-08": "Fiacre",
"31-08": "Aristide",
// Septembre
"01-09": "Gilles",
"02-09": "Ingrid",
"03-09": "Grégoire",
"04-09": "Rosalie",
"05-09": "Raïssa",
"06-09": "Bertrand",
"07-09": "Reine",
"08-09": "Adrien",
"09-09": "Alain",
"10-09": "Inès",
"11-09": "Adelphe",
"12-09": "Apollinaire",
"13-09": "Aimé",
"14-09": "Cyprien",
"15-09": "Roland",
"16-09": "Édith",
"17-09": "Renaud",
"18-09": "Nadège",
"19-09": "Émilie",
"20-09": "Davy",
"21-09": "Matthieu",
"22-09": "Maurice",
"23-09": "Constant",
"24-09": "Thècle",
"25-09": "Hermann",
"26-09": "Damien",
"27-09": "Vincent",
"28-09": "Venceslas",
"29-09": "Michel",
"30-09": "Jérôme",
// Octobre
"01-10": "Thérèse",
"02-10": "Léger",
"03-10": "Gérard",
"04-10": "François",
"05-10": "Fleur",
"06-10": "Bruno",
"07-10": "Serge",
"08-10": "Pélagie",
"09-10": "Denis",
"10-10": "Ghislain",
"11-10": "Firmin",
"12-10": "Wilfried",
"13-10": "Géraud",
"14-10": "Juste",
"15-10": "Thérèse",
"16-10": "Edwige",
"17-10": "Baudouin",
"18-10": "Luc",
"19-10": "René",
"20-10": "Adeline",
"21-10": "Céline",
"22-10": "Élodie",
"23-10": "Jean",
"24-10": "Florentin",
"25-10": "Enguerrand",
"26-10": "Dimitri",
"27-10": "Émeline",
"28-10": "Simon",
"29-10": "Narcisse",
"30-10": "Bienvenue",
"31-10": "Quentin",
// Novembre
"01-11": "Toussaint",
"02-11": "Défunts",
"03-11": "Hubert",
"04-11": "Charles",
"05-11": "Sylvie",
"06-11": "Bertille",
"07-11": "Carine",
"08-11": "Geoffroy",
"09-11": "Théodore",
"10-11": "Léon",
"11-11": "Martin",
"12-11": "Christian",
"13-11": "Brice",
"14-11": "Sidoine",
"15-11": "Albert",
"16-11": "Marguerite",
"17-11": "Élisabeth",
"18-11": "Aude",
"19-11": "Tanguy",
"20-11": "Edmond",
"21-11": "Rufus",
"22-11": "Cécile",
"23-11": "Clément",
"24-11": "Flora",
"25-11": "Catherine",
"26-11": "Delphine",
"27-11": "Séverin",
"28-11": "Jacques",
"29-11": "Saturnin",
"30-11": "André",
// Décembre
"01-12": "Florence",
"02-12": "Viviane",
"03-12": "Xavier",
"04-12": "Barbara",
"05-12": "Gérald",
"06-12": "Nicolas",
"07-12": "Ambroise",
"08-12": "Elfried",
"09-12": "Pierre",
"10-12": "Romaric",
"11-12": "Daniel",
"12-12": "Corentin",
"13-12": "Lucie",
"14-12": "Odile",
"15-12": "Ninon",
"16-12": "Alice",
"17-12": "Gaël",
"18-12": "Gatien",
"19-12": "Urbain",
"20-12": "Théophile",
"21-12": "Pierre",
"22-12": "Françoise-Xavière",
"23-12": "Armand",
"24-12": "Adèle",
"25-12": "Emmanuel",
"26-12": "Étienne",
"27-12": "Jean",
"28-12": "Gaspard",
"29-12": "David",
"30-12": "Roger",
"31-12": "Sylvestre"
};
Nous allons l’importer et l’utiliser dans le fichier edit.js :
import { __ } from '@wordpress/i18n';
import {
useBlockProps,
InspectorControls
} from '@wordpress/block-editor';
import {
PanelBody,
ToggleControl
} from '@wordpress/components';
import './editor.scss';
import { saints } from './saints.js';
export default function Edit({ attributes, setAttributes }) {
const { showDate } = attributes;
const aujourdHui = new Date();
const jour = String(aujourdHui.getDate()).padStart(2, '0');
const mois = String(aujourdHui.getMonth() + 1).padStart(2, '0');
const cle = `${jour}-${mois}`;
const saint = saints[cle] || __('Aucun saint trouvé', 'mon-premier-bloc');
return (
<>
<InspectorControls>
<PanelBody
title={__('Réglages du bloc', 'mon-premier-bloc')}
>
<ToggleControl
label={__('Afficher la date', 'mon-premier-bloc')}
checked={showDate}
onChange={(value) =>
setAttributes({ showDate: value })
}
/>
</PanelBody>
</InspectorControls>
<div { ...useBlockProps() }>
<div className="saint-du-jour">
{showDate && (
<p>
{jour}/{mois}
</p>
)}
<h4>
{__('Saint du jour', 'mon-premier-bloc')}
</h4>
<p>
{saint}
</p>
</div>
</div>
</>
);
}
Les imports WordPress
Au début de notre fichier edit.js, nous trouvons :
import { __ } from '@wordpress/i18n';
La fonction __() vient du module d’internationalisation de WordPress (i18n signifie internationalization).
Elle sert à rendre les textes de notre bloc traduisibles.
Par exemple :
__('Saint du jour', 'mon-premier-bloc')
affichera simplement Saint du jour, mais WordPress sait qu’il pourra remplacer cette phrase par sa traduction si une traduction existe.
Le deuxième paramètre correspond au text domain du plugin. C’est un identifiant utilisé par WordPress pour associer une traduction au bon plugin. Il doit être unique afin d’éviter les conflits avec d’autres extensions installées sur le site. Utiliser le nom du plugin (ou le nom du dossier du plugin) comme text domain est une pratique courante, car cela garantit généralement un identifiant simple et facilement identifiable.
Employer __() est une bonne habitude à prendre dès le départ, même si vous ne créer pas de traduction dans votre première version.
Nous trouvons également :
import {
useBlockProps,
InspectorControls
} from '@wordpress/block-editor';
import {
PanelBody,
ToggleControl
} from '@wordpress/components';
Ces fonctions permettent à notre bloc de récupérer automatiquement les propriétés nécessaires à son intégration dans l’éditeur Gutenberg, et d’afficher des contrôles dans la barre d’outil à droite.
Elle ajoute notamment les classes CSS et les attributs utilisés par WordPress pour gérer correctement les blocs. En les utilisant, notre bloc respecte les mêmes conventions que les blocs natifs de Gutenberg et s’intègre naturellement dans l’interface d’administration.
6. Personnaliser le rendu
Le rendu du bloc dans le site est défini par le fichier save.js
import { __ } from '@wordpress/i18n';
import { useBlockProps } from '@wordpress/block-editor';
import { saints } from './saints.js';
export default function save({ attributes }) {
const { showDate } = attributes;
const aujourdHui = new Date();
const jour = String(aujourdHui.getDate()).padStart(2, '0');
const mois = String(aujourdHui.getMonth() + 1).padStart(2, '0');
const cle = `${jour}-${mois}`;
const saint = saints[cle] || __('Aucun saint trouvé', 'mon-premier-bloc');
return (
<div { ...useBlockProps.save() }>
<div className="saint-du-jour">
{showDate && (
<p>
📅 {jour}/{mois}
</p>
)}
<h4>
{__('Saint du jour', 'mon-premier-bloc')}
</h4>
<p>
✨ {saint}
</p>
</div>
</div>
);
}
Le style contenu dans style.scss sera automatiquement importé. Pour celui dans l’administration, ce sont les directives présentes dans editor.scss qui seront prises en compte. Vous pouvez par exemple utiliser ceci dans style.scss et laisser editor inchangé (par défaut il affiche une petite bordure rouge autour du bloc éditable) :
.wp-block-create-block-mon-premier-bloc {
padding: 1rem 1.5rem;
border: 1px solid grey;
}
.wp-block-create-block-mon-premier-bloc p {
margin: 0;
}
.wp-block-create-block-mon-premier-bloc h4 {
margin: 0;
font-size: 1.25rem;
}
7. Déploiement
Dans notre Terminal, nous allons à présent entrer dans le répertoire du projet.
cd .\mon-premier-bloc\
Puis démarrer l’outil avec :
npm start
A chaque modification d’un fichier, l’outil recompile automatiquement les sources. Vérifiez bien qu’aucune erreur n’apparaît.
Vous pouvez maintenant vous rendre dans votre administration WordPress, activer le pluggin et le tester sur une page !
8. Distribution
Une fois le projet terminé, dans le répertoire ou vous aviez lancé start pour démarrer le mode développement, vous pourrez utiliser à la place la commande :
npm run build
Cela créera un zip facile à installer sur n’importe quel WordPress 🙂