S’il y a une et une seule fonctionnalité qui a fait gagner 30% de la part de marché du Web à WordPress, cette fonctionnalité serait l’extensibilité . Qu’est-ce que WordPress sans Yoast? Qu’est-ce que WordPress sans ACF? Sans JetPack? WooCommerce? Sans Akismet? Sans contact form 7 ? Qu’est-ce que WordPress sans Hello Dolly? Ce ne serait rien qu’une autre niche CMS avec beaucoup moins de part de marché qu’actuellement.

Donc, oui, l’extensibilité est la clé, et nous ne pouvons pas construire la prochaine génération de l’éditeur WordPress sans le rendre extensible. Que signifie “rendre extensible”? Cela signifie-t-il fournir des hooks et des filtres en JavaScript comme nous le faisons en PHP? Cela signifie-t-il que les plugins peuvent étendre et modifier tout composant d’interface utilisateur utilisé par Gutenberg? Est-ce que cela veut dire ajouter des filtres à l’API REST? Cela signifie-t-il Donner accès à un objet Editor pour manipuler le contenu de l’éditeur?

Il n’y a pas de réponse claire à toutes ces questions. L’extensibilité est un problème très difficile et si vous ne le construisez pas avec des cas d’utilisation réels, vous risquez de vous tromper. (et être coincé avec lui pendant une longue période).

Examinons de plus près l’Extensibilité dans Gutenberg et ce que nous pouvons réaliser avec lui en ce moment.

Créer des blocs

Comme vous l’avez peut-être entendu, Gutenberg parle de blocs (ou de blocs de contenu) que vous combinez pour composer du contenu. Un bloc qui peut représenter n’importe quel élément visuel: un en-tête, un paragraphe, une image, un embed, une table, une liste, un formulaire, une liste dynamique de posts, …

Wordpress : 1001 façons d'étendre Gutenberg aujourd'hui

Vous pouvez penser aux blocs en tant que shortcodes v2 avec une meilleure interface utilisateur pour les ajouter et les modifier. Les blocs peuvent être statiques (il suffit de rendre un peu de HTML statique) ou dynamiques (changement au fil du temps et rendu côté serveur).

Si l’éditeur est constitué de blocs, la manière la plus naturelle de l’étendre est de créer des blocs.

1- Créer un bloc statique

Donc, notre premier exemple sera d’ajouter un nouveau bloc statique, nous l’appellerons «Alerte» affichant un message d’alerte. L’alerte peut avoir trois états (avertissement, erreur ou succès) et un message.

Ce bloc pourrait ressembler à ceci (moins le contrôle pour changer de type, juste pour le rendre plus simple) :

// myblock.js

var el = wp.element.createElement,
	registerBlockType = wp.blocks.registerBlockType;

registerBlockType( 'riad/alert', {
	title: 'Alert Block',
	icon: 'warning',
	category: 'common',

	attributes: {
		type: {
			type: 'string',
			default: 'danger',
		},
		message: {
			type: 'string',
			source: 'html',
			selector: 'div',
		},
	},

	edit: function( props ) {
		var className = props.className;
		var type = props.attributes.type;
		var message = props.attributes.message;
		function updateMessage( event ) {
			props.setAttributes( { message: event.target.value } );
		}

		return el(
			'p', 
			{ className: className + ' alert-' + type },
			el(
				'textarea',
				{ value: message, onChange: updateMessage }
			) 
		);
	},

	save: function( props ) {
		var = props.attributes.type;
		var message = props.attributes.message;


		return el(
			'p', 
			{ className: 'alert-' + type },
			message
		);
	},
} );

Avec une feuille de style comme ceci :

/* myblock.css */

.wp-block-riad-alert.alert-danger { color: red; }
.wp-block-riad-alert.alert-success { color: green; }
.wp-block-riad-alert.alert-warning { color: orange; }

Et on charge ce bloc dans le plugin :

<?php
// plugin.php

function riad_enqueue_blocks() {
	wp_enqueue_script(
		'riad-block',
		plugins_url( 'block.js', __FILE__ ),
		array( 'wp-blocks', 'wp-element' )
	);
}
add_action( 'enqueue_block_editor_assets', 'riad_enqueue_blocks' );

function riad_enqueue_styles() {
	wp_enqueue_style(
		'riad-block-style',
		plugins_url( 'myblock.css', __FILE__ ),
		array( 'wp-blocks' ),
		filemtime( plugin_dir_path( __FILE__ ) . 'myblock.css' )
	);
}
add_action( 'enqueue_block_assets', 'riad_enqueue_styles' );

Alors, que se passe-t-il ici?

  • Un fichier javascript pour enregistrer le bloc fournissant des informations générales (une icône, une catégorie et un titre), une fonction d’édition représentant l’état visuel du bloc dans l’éditeur et une fonction d’enregistrement représentant la sortie HTML par ce bloc,
  • Une feuille de style ajoutant quelques styles par défaut à ce bloc, extensible par les thèmes,
  • Et juste un hook de plugin classique pour tout lier ensemble.

Je n’irai pas trop dans les détails ici, si c’est comme ça que vous voulez prolonger Gutenberg, je vous encourage à jeter un coup d’oeil aux documents de Gutenberg car cela est fortement abordé.

2- Créer un bloc dynamique

Le deuxième type de blocs que vous pouvez ajouter à Gutenberg sont les blocs dynamiques. Disons que nous voulons mettre en évidence le dernier post publié dans plusieurs autres pages / posts. Pour ce faire, nous allons créer un bloc dynamique affichant le titre et un lien vers le dernier post.

// myblock.js

var el = wp.element.createElement,
	registerBlockType = wp.blocks.registerBlockType,
	withAPIData = wp.components.withAPIData;

registerBlockType( 'riad/latest-post', {
	title: 'Latest Post',
	icon: 'megaphone',
	category: 'widgets',

	edit: withAPIData( function() {
		return {
			posts: '/wp/v2/posts?per_page=1'
		};
	} )( function( props ) {
		if ( ! props.posts.data ) {
			return "loading !";
		}
		if ( props.posts.data.length === 0 ) {
			return "No posts";
		}
		var className = props.className;
		var post = props.posts.data[ 0 ];
		
		return el(
			'a', 
			{ className: className, href: post.link },
			post.title.rendered
		);
	} ),

	save: function() {
		// Rendering in PHP
		return null;
	},
} );

Et ajouter le rendu côté serveur comme cela

<?php
// block.php

function riad_render_block_latest_post( $attribites ) {
	$recent_posts = wp_get_recent_posts( array(
		'numberposts' => 1,
		'post_status' => 'publish',
	) );
	if ( count( $recent_posts ) === 0 ) {
		return 'No posts';
	}
	$post = $recent_posts[ 0 ];
	$post_id = $post['ID'];
	return sprintf(
		'<a class="wp-block-riad-latest-post" href="%1$s">%2$s</a>',
		esc_url( get_permalink( $post_id ) ),
		esc_html( get_the_title( $post_id ) )
	);
}

register_block_type( 'riad/latest-post', array(
	'render_callback' => 'riad_render_block_latest_post',
) );

Et c’est tout ! Remarquez:

  • La fonction d’édition affiche toujours une représentation du bloc dans le contexte de l’éditeur (cela peut être très différent de la version rendue, comme le bloc auteur)
  • la fonction d’enregistrement retourne null car le rendu est effectué côté serveur.
  • Le rendu côté serveur est une fonction qui prend les attributs du bloc en argument et renvoie le balisage (assez similaire aux shortcodes)

3- Enregistrer dans le message Meta

“Ok ! Maintenant je comprends, créer des blocs c’est cool, ça remplace les shortcodes statiques et dynamiques ! Mais qu’en est-il des métaboxes ?”

Les Métaboxes sont utilisées pour tout dans l’éditeur actuel de WordPress. L’un de ces cas d’utilisation (le plus fréquent) consiste à ajouter un custom post meta.

Les blocs traitent très bien ce cas d’utilisation en permettant aux auteurs de plugins de déclarer les méta-attributs, récupérer les blocs d’attributs et les sauvegarder dans un post meta:

// myblock.js

var el = wp.element.createElement,
	registerBlockType = wp.blocks.registerBlockType;

registerBlockType( 'riad/book-title', {
	title: 'Book Title',
	icon: 'book',
	category: 'common',

	attributes: {
		title: {
			type: 'string',
			meta: 'book-title'
		},
	}

	edit: function( props ) {
		var className = props.className;
		var title = props.attributes.title;
		function updateTitle( event ) {
			props.setAttributes( { title: event.target.value } );
		}

		return el(
			'p', 
			{ className: className },
			el(
				'textarea',
				{ value: title, onChange: updateTitle }
			) 
		);
	},

	save: function() {
		return null;
	},
} );

En raison de certaines limitations de l’API REST, vous devez également enregistrer la méta personnalisée sur votre type de post.

function gutenberg_my_block_init() {
	register_meta( 'post', 'book-title', array(
		'show_in_rest' => true,
		'single' => true,
	) );
}
add_action( 'init', 'gutenberg_my_block_init' );

Terminé ! nous avons un bloc qui sauvegarde un titre de livre dans un custom post meta.

Suppression de blocs

L’ajout de blocs est assez facile, mais l’une des préoccupations que nous entendons beaucoup est que Gutenberg donne beaucoup de pouvoir aux utilisateurs et qu’ils ne seront pas en mesure de contrôler les balises produites en utilisant Gutenberg.

Je pense que cette préoccupation n’est pas pertinente. Gutenberg offre exactement cela : une façon d’avoir un ensemble contrôlé de blocs. Nous ne pouvons pas abimer le contenu du message aussi facilement que dans l’éditeur actuel.

1- Liste noire

Quoi qu’il en soit, si vous pensez qu’un bloc n’est pas pertinent pour vous ou pour un type de bloc spécifique, il suffit de le désinscrire . Par exemple, si je n’aime pas le bloc “verset” parce que je ne suis pas un poète, je peux le supprimer comme ceci:

// myplugin.js 

wp.blocks.unregisterBlockType( 'core/verse' );

Pour charger mon script dans Gutenberg

<?php
// myplugin.php

function riad_blacklist_blocks() {
	wp_enqueue_script(
		'riad-blacklist',
		plugins_url( 'myplugin.js', __FILE__ ),
		array( 'wp-blocks' )
	);
}
add_action( 'enqueue_block_editor_assets', 'riad_blacklist_blocks' );

Plutot simple non ?

2- Liste blanche

Certaines personnes veulent un meilleur contrôle sur les blocs autorisés, mettons à jour notre code ci-dessus pour utiliser une liste blanche à la place :

// myplugin.js
var allowedBlocks = [
  'core/paragraph',
  'core/image',
  'core/html',
  'core/freeform'
];

wp.blocks.getBlockTypes().forEach( function( blockType ) {
  if ( allowedBlocks.indexOf( blockType.name ) === -1 ) {
    wp.blocks.unregisterBlockType( blockType.name );
  }
} );

Modification de blocs

Puisque nous pouvons enregistrer et désinscrire un bloc, cela signifie également que pour modifier un bloc existant, nous pouvons le désinscrire, le modifier et le réenregistrer.

1- Changer le titre d’un bloc

Je n’aime pas le titre du bloc «paragraphe», je veux que ce soit «texte», je peux le faire :

// extend-block.js

var paragraphBlock = wp.blocks.unregisterBlockType( 'core/paragraph' );
paragraphBlock.title = "Texte";
wp.blocks.registerBlockType( 'core/paragraph', paragraphBlock );

2- Ajout d’une légende

Maintenant que vous avez le principal, faisons de plus grandes modifications. Et si nous voulons ajouter une “légende” au bloc “code”. Pour y parvenir, nous pouvons “décorer”
“edit, save et attributes” comme ainsi:

// extend-block.js

var el = wp.element.createElement;
var Editable = wp.blocks.Editable;
var codeBlock = wp.blocks.unregisterBlockType( 'core/code' );
codeBlock.attributes.caption = { source: 'children', selector: '.my-caption' };
var OriginalBlockEdit = codeBlock.edit;
var OriginalBlockSave = codeBlock.save;
codeBlock.edit = function( props ) {
  return [
    el( OriginalBlockEdit, Object.assign( props, { key: 'original' } ) ),
    el( Editable, {
      key: 'caption',
      className: 'my-caption',
      value: props.attributes.caption,
      onChange: function( value ) {
        props.setAttributes( { caption: value } );
      },
    } ),
  ];
};
codeBlock.save = function( props ) {
  return [
    el( OriginalBlockSave, Object.assign( props, { key: 'original' } ) ),
    el( 'div', {
      key: 'caption',
      className: 'my-caption',
    }, props.attributes.caption ),
  ];
};
wp.blocks.registerBlockType( 'core/code', codeBlock );

Avec cette technique, vous pouvez imaginer améliorer n’importe quel bloc existant facilement.

3- Transformer des blocs

Gutenberg a une API de transformation intégrée permettant aux plugins tiers de créer des blocs et de définir comment ces blocs pourraient être transformés en (ou à partir de) tout autre bloc, y compris les blocs de base.

A titre d’exemple, ajoutons une transformation au bloc “alert” que nous avons créé ci-dessus pour permettre de le transformer en un bloc de paragraphe régulier

// myblock.js

registerBlockType( 'riad/alert', {
  // ...
  transforms: {
    to: {
      type: 'block',
      blocks: [ 'core/paragraph' ],
      transform: function( attrs ) => {
        return wp.blocks.createBlock( 'riad/paragraph', {
          content: attrs.message,
        } );
      },
    },
  },
} );

L’API des transformations n’est pas encore documentée car elle est toujours sujette à changement mais c’est une API puissante, elle permet bien plus que cela. Certains des cas d’utilisation couverts par cette API sont :

  • Transformations de collage : transformation du contenu collé en un bloc spécifique en fonction du contenu collé
  • Transformations de patterns: Autoriser les raccourcis: Par exemple, en tapant `#` dans un paragraphe vide, vous créez un bloc de titre, ce comportement peut être étendu à tout autre préfixe et bloc.
  • Glisser-déposer des transformations: Glisser-déposer un fichier PDF dans l’éditeur crée un bloc PDF personnalisé

Styliser

1- Blocs de style

L’une des questions les plus fréquemment posées est la suivante: comment Gutenberg affecte-t-il les thèmes existants et comment les auteurs de thèmes peuvent-ils améliorer l’expérience de Gutenberg?

Les blocs sont livrés avec des styles non optimisés intégrés. Cela rend fondamentalement n’importe quel thème WordPress compatible avec Gutenberg sans aucun changement.

Cependant, pour leur donner plus de personnalité les thèmes pourraient facilement modifier le style de tous les blocs et Gutenberg rend cela facile en ayant un balisage de sortie bien défini pour chaque bloc et un nom de classe généré pour la plupart des blocs.

Disons que je veux donner le bloc “pullquote” un design spécifique dans mon thème, c’est juste une question de style de la classe `wp-block-pullquote`

/* theme.css */

.wp-block-pullquote {
  background: #EEE;
  border: none;
}

2- Styliser l’éditeur

Mais que dois-je faire pour imiter les styles d’un frontend et faire en sorte que l’éditeur montre exactement comment mon thème le ferait ? Pour cela, il suffit d’isoler les styles spécifiques du contenu dans une feuille de style blocks.css chargée à la fois par les pages du frontend et de l’éditeur et de charger cette feuille de style dans l’éditeur de Gutenberg comme ceci:

// functions.php

function my_theme_editor_styles() {
    wp_enqueue_style( 'theme-blocks-style', get_template_directory_uri() . '/blocks.css');
}
add_action( 'enqueue_block_editor_assets', 'my_theme_editor_styles' );

Support thématique

Les thèmes peuvent également étendre Gutenberg en utilisant l’API “theme support”. Pour l’instant, deux options sont disponibles: fournir une palette de couleurs et activer les alignements larges.

Plusieurs types de blocs utilisent des «couleurs» et assurent une expérience “neutre” à travers les blocs, définissez une palette de couleurs comme ceci:

// functions.php

function mytheme_setup_theme_supported_features() {
  add_theme_support( 'gutenberg', array(
   'colors' => array(
     '#a156b4',
     '#d0a5db',
     '#eee',
     '#444',
   ),
  ) );
}

add_action( 'after_setup_theme', 'mytheme_setup_theme_supported_features' );

Et après?

Lors de l’extension de Gutenberg, la première question que vous devez vous poser est la suivante : cela pourrait-il être fait dans un bloc? Dans la plupart des cas, la réponse à cette question est OUI . Mais cela ne signifie pas que Gutenberg n’autorisera pas les développeurs à étendre d’autres éléments de l’interface utilisateur.

Jetons un coup d’oeil aux différentes API d’extension envisagées dans Gutenberg.

1- Blocs extensibles

Comme je vous l’ai montré plus tôt, il est possible de modifier des blocs existants en les désenregistrant et en les enregistrant avec une version modifiée. À l’avenir, l’enregistrement des blocs de base par des plugins tiers peut être interdit et une API plus simple pour étendre les blocs sera fournie.

2- Slots

En interne, Gutenberg fait un usage intensif de ” Slots “. Les emplacements sont des zones d’interface utilisateur enfichables. À l’avenir, Gutenberg exposera plus probablement ces slots à des plugins tiers pour permettre l’extension de zones comme la barre latérale et l’en-tête permettant des cas d’utilisation comme:

  • Ajout d’un panneau à la barre latérale des paramètres de publication.
  • Ajout d’un bouton à l’en-tête de l’éditeur.
  • Ajout d’un élément au sélecteur de mode de l’éditeur
  • menu déroulant .

3- Décorateurs

Alors que les slots sont parfaits pour permettre l’ajout d’éléments à l’interface utilisateur, ils ne permettent pas de modifier les composants de l’interface utilisateur existants. Gutenberg est construit en utilisant des composants réutilisables et un moyen d’étendre le comportement de plusieurs éléments d’interface utilisateur de Gutenberg pourrait être de modifier ces éléments utilisables. Les décorateurs sont un modèle générique explosé à Gutenberg permettant des extensions à n’importe quel composant. Les décorateurs peuvent être utilisés pour permettre les cas d’utilisation suivants:

  • Étendre le composant `Editable` pour ajouter des notes de bas de page à tous les blocs basés sur le texte
  • Étendre le bouton de publication et modifier son arrière-plan si le contenu du message n’est pas valide HTML (ou tout autre contrôle)
  • Retirer certains composants en les étendant avec des composants “vides”.

4- Autres extensions de niveau supérieur

En plus de manipuler des blocs (ajout, suppression, extension), Gutenberg autorisera probablement des API de plus haut niveau comme l’ enregistrement de nouvelles catégories de blocs , l’ extension des modèles de texte …

5- Modèles de blocs

C’est l’une de mes extensions d’API favorites, les modèles de blocs. Les modèles de blocs sont une liste de blocs pré-remplis avec des espaces réservés, certains de ces blocs sont “verrouillés”, ils ne peuvent pas être déplacés ou supprimés. Imaginez un type de post personnalisé “produit” définissant un modèle avec un bloc d’image, un bloc de texte pour la description, un bloc de prix. Et lorsqu’un utilisateur décide d’ajouter un nouveau produit, l’éditeur est déjà pré-rempli avec ces blocs. Tout ce qu’il reste à faire est de remplir les espaces réservés. N’est-ce pas une expérience formidable pour les types de messages personnalisés?

Conclusion

Construire des API d’extensibilité est difficile et répliquer les actions et les filtres que nous utilisons dans les plugins PHP peut ne pas être la meilleure option pour une viabilité à plus long terme. S’appuyer sur des cas d’utilisation réels et construire des modèles génériques autour d’eux est ce qui conduirait à la meilleure API d’extensibilité possible pour Gutenberg et l’avenir des plugins WordPress basés sur JavaScript.

Si vous êtes un développeur / développeur de thème, je vous encourage à essayer les conseils exposés dans ce post et à partager vos cas d’utilisation avec l’équipe Gutenberg en répondant à des problèmes existants ou en en créant de nouveaux


Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *