Catégories
Astuces et Design

Transformations de blocs WordPress | Astuces CSS

Ce fut l'année de Gutenberg pour nous ici à CSS-Tricks. En fait, c'est un objectif que nous nous étions fixé à la fin de l'année dernière. Nous sommes beaucoup plus avancés que je pensais que nous serions, en écrivant tous Nouveau contenu dans l'éditeur de blocs¹, permettant à l'éditeur de blocs tout contenu maintenant. Cela signifie que lorsque nous ouvrons la plupart des anciens messages, nous voyons tout le contenu dans le bloc "Classique". Cela ressemble à ceci:

Un article écrit sur CSS-Tricks avant d'utiliser l'éditeur de blocs.

Le contenu entier de la publication est dans un seul bloc, donc ne fait pas exactement usage de l'éditeur de blocs. Il est toujours "visuel", comme l'éditeur de blocs, mais il ressemble plus à l'ancien éditeur visuel utilisant TinyMCE. Je ne l'ai jamais utilisé car il a un peu déformé le HTML d'une manière que je n'aimais pas.

C'est la première chose qui m'inquiétait

Transformer un bloc classique en nouveaux blocs est aussi simple que de sélectionner le bloc classique et de sélectionner l'option «Convertir en blocs».

Sélectionnez l'option et le bloc devient plusieurs blocs.

Comment l'éditeur de blocs gère-t-il le vieux contenu en blocs, lorsque nous lui demandons de le faire à partir de l'option «Convertir en blocs»? Que se passe-t-il s'il fout complètement le contenu lors de la conversion? Allons-nous déjà être en mesure de changer?

La réponse: il fait un sacré bon travail. Mais… il y a encore des problèmes. Pas des "bugs" mais des situations où nous avons du HTML personnalisé dans notre ancien contenu et il ne sait pas quoi en faire – et encore moins comment le convertir en blocs exactement comme nous le souhaitons. Il y a un moyen!

Transformations de bloc de base

C’est là que cette idée de «Transformations de blocs» entre en jeu. Tous (enfin, la plupart?) Des blocs natifs ont des transformations «vers» et «depuis». Vous savez probablement déjà comment cela se manifeste dans l'interface utilisateur. Comme un paragraphe peut se transformer «en» une citation et vice versa. Voici une super méta capture d'écran de ce paragraphe:

Ces transformations ne sont pas magiques; ils sont très explicitement codés. Lorsque vous enregistrez un bloc, vous spécifiez les transformations. Supposons que vous enregistriez votre propre bloc de code personnalisé. Vous voulez vous assurer de pouvoir le transformer…

  • De et au bloc de code intégré par défaut, et probablement une poignée d'autres qui pourraient être utiles.
  • Retour à le bloc de code intégré.

Cela pourrait ressembler à:

registerBlockType("my/code-block", {
  title: __("My Code Block"),
  ...
  transforms: {
    from: (
      {
        type: "block",
        priority: 7,
        blocks: ("core/code", "core/paragraph", "core/preformatted"),
        transform: function (attributes) {
          return createBlock("my/code-block", {
            content: attributes.content,
          });
        },
      },
    ),
    to: (
      {
        type: "block",
        blocks: ("core/code"),
        transform: ({ content }) => createBlock("core/code", { content }),
      },
    ),
   
   ...

Ce sont des transformations vers et depuis d'autres blocs. Heureusement, il s'agit d'un bloc assez simple où nous mélangeons simplement content environ. Des blocs plus complexes peuvent avoir besoin de faire circuler plus de données, mais je n'ai pas encore eu à m'en occuper.

Le truc le plus magique: les transformations de bloc à partir du code brut

Voici le moment de vérité pour l'ancien contenu:

L'option «Convertir en blocs».

Dans cette situation, les blocs sont créés non pas à partir d'autres blocs, mais à partir du code brut. Littéralement, le HTML est examiné et des choix sont faits sur les blocs à faire à partir de morceaux de ce HTML. C'est où il est étonnant que l'éditeur de blocs fasse un si bon travail avec les choix, et aussi où les choses peuvent mal tourner et peuvent échouer, faire de mauvais choix de blocs ou modifier le contenu.

Dans notre ancien contenu, un bloc de code (un super très important chose) dans un message ressemblerait à ceci:


  let html = `
cool
`;

Parfois, la conversion de bloc ferait OK sur ceux-ci, la transformant en un bloc de code natif. Mais il y avait un certain nombre de problèmes:

  1. Je ne veux pas d'un bloc de code natif. Je veux que cela se transforme en notre propre Nouveau bloc de code (blogué à ce sujet ici).
  2. J'ai besoin de certaines informations dans ces attributs pour informer les paramètres du nouveau bloc, comme le type de code qu'il s'agit.
  3. Le code HTML de nos anciens blocs de code était pas échappé et j'en ai besoin pour ne pas m'étouffer avec ça.

Je n'ai pas toutes les réponses ici, car c'est un processus évolutif, mais j'ai maintenant des transformations de blocs en place qui fonctionnent plutôt bien. Voici à quoi ressemble une transformation «brute» (par opposition à une transformation «bloc»):

registerBlockType("my/code-block", {
  title: __("My Code Block"),
  // ...
  transforms: {
    from: (
      {
        type: "block",
        priority: 7,
        // ...
      },
      {
        type: "raw",
        priority: 8,
        isMatch: (node) =>
          node.nodeName === "PRE" &&
          node.children.length === 1 &&
          node.firstChild.nodeName === "CODE",
        transform: function (node) {
          let pre = node;
          let code = node.querySelector("code");

          let codeType = "html";
          if (pre.classList.contains("language-css")) {
            codeType = "css";
          }
          if (pre.getAttribute("rel") === "CSS") {
            codeType = "css";
          }
          if (pre.classList.contains("language-javascript")) {
            codeType = "javascript";
          }
          if (code.classList.contains("language-javascript")) {
            codeType = "javascript";
          }
          // ... other data wrangling...

          return createBlock("csstricks/code-block", {
            content: code.innerHTML,
            codeType: codeType,
          });
        },
      },
    ),
    to: (
      // ... 
    ),
   
   // ...

}

Cette isMatch fonctionne sur tous les nœuds dans le code HTML qu'il trouve, c'est donc la grande opportunité de revenir true de cela dans les situations spéciales dont vous avez besoin. Notez dans le code ci-dessus que je recherche spécifiquement du code HTML qui ressemble à

. When that matches, the transform runs, and I can return a createBlock call that passes in data and content I extract from the node with JavaScript. 

Another example: Pasting a URL

“Raw” transforms don’t only happen when you “Convert to Blocks.” They happen when you paste content into the block editor too. You’ve probably experienced this before. Say you have copied some table markup from somewhere and paste it into the block editor -— it will probably paste as a table. A YouTube URL might paste into an embed. This kind of thing is why copy/pasting from Word documents and the like tend to work so well with the block editor.

Say you want some special behavior when a certain type of URL is pasted into the editor. This was the situation I was in with our custom CodePen Embed block. I wanted it so if you pasted a codepen.io URL, it would use this custom block, instead of the default embed.

This is a “from” transform that looks like this:

{
  type: "raw",
  priority: 8, // higher number to beat out default
  isMatch: (node) =>
    node.nodeName === "P" &&
    node.innerText.startsWith("https://codepen.io/"),

  transform: function (node) {
    return createBlock("cp/codepen-gutenberg-embed-block", {
      penURL: node.innerText,
      penID: getPenID(node.innerText), // helper function
    });
  },
}

Donc…

C'est désordonné? Un peu. Mais il est aussi puissant que vous en avez besoin. Si vous avez un ancien site avec beaucoup de code HTML et de shortcodes sur mesure, alors entrer dans les transformations de bloc est le seul ticket.

Je suis content d’être allé sur WPBlockTalk et d’avoir pris la parole de K. Adam White sur les shortcodes car il n’y avait qu’une diapositive qui m’a permis de comprendre que cela était même possible. Il y a un peu de documentation dessus.

Je voudrais savoir s'il est possible d'exécuter ces transformations sur tout ancien contenu de la base de données. Semble un peu effrayant, mais aussi comme cela pourrait être une bonne idée dans certaines situations. Une fois que mes transformations sont vraiment solides, je pouvais voir faire ainsi tout ancien contenu prêt à l'emploi dans l'éditeur de blocs lors de son ouverture. Je n'ai aucune idée de comment procéder.

Je suis heureux d'être un peu au dessus de cela cependant, car j'aime vraiment l'éditeur de blocs en ce moment. C’est un plaisir d’écrire et de créer du contenu avec. J'aime ce que Justin Tadlock a dit:

Le système de blocs ne va nulle part. WordPress a dépassé le point où nous devrions considérer l'éditeur de blocs comme une entité distincte. Il fait partie intégrante de WordPress et finira par toucher de plus en plus de zones en dehors de l'écran d'édition.

Il est là pour rester. Embrasser l'éditeur de blocs et le plier à notre volonté est la clé.

Laisser un commentaire

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