Fermer

octobre 9, 2018

Débuter avec Gutenberg en créant votre propre bloc


À propos de l'auteur

Muhammad Muhsin est cofondateur et développeur principal de Laccadive IO. Il est un ingénieur full stack, passionné par la technologie et, ces derniers temps, il…
Pour en savoir plus sur Mohammed

Gutenberg est le futur de WordPress, qui approche à grands pas. Préparez-vous à cela en apprenant à créer votre propre bloc Gutenberg personnalisé.

WordPress est de loin le système de gestion de contenu (CMS) le plus répandu, alimentant plus de 30% du Web. Il a subi une métamorphose énorme au cours de ses 15 années d'existence. Son dernier ajout est Gutenberg, qui sortira dans la version 5.0

Nommé d'après Johannes Gutenberg (l'inventeur de la presse à imprimer), Gutenberg va fondamentalement changer WordPress, contribuant ainsi à atteindre son objectif de démocratisation de l'édition.

WordPress publie généralement ses principales fonctionnalités sous forme de plugin permettant de tester les eaux avant de les intégrer au cœur. Gutenberg ne fait pas exception. Dans cet article, nous allons apprendre à construire votre premier bloc de Gutenberg. Nous allons créer un bloc Testimonials Slider tout en insistant sur les bases de Gutenberg.

Voici un aperçu de cet article:

  1. Installation du plug-in Gutenberg
  2. Installation du bloc Testimonials Slider
  3. Prise en main de la configuration
  4. Enregistrement d'un bloc
  5. Présentation de la syntaxe spécifique de Gutenberg
  6. Les attributs Object
  7. Le edit et save Functions
  8. Développement continu
  9. Création d'un nouveau bloc de Gutenberg
  10. Conclusion

Cet article suppose ce qui suit:

  • Quelques connaissances de WordPress telles que la façon dont le contenu est sauvegardé et le développement de plugins de base;
  • Compréhension de base de React et de ES6; 19659020] Connaissance de npm et de Webpack

Lectures recommandées : L'anatomie complète de Gutenberg WordPress Editor

Installation du Guten berg Plugin

Si vous utilisez WordPress, vous saurez que l’installation d’un plugin est assez simple. L'installation de Gutenberg ne fait pas exception.

Cependant, la méthode recommandée pour installer Gutenberg consiste à cloner la version de développement à partir du référentiel GitHub, car vous pouvez obtenir les dernières modifications. Rendez-vous sur le référentiel GitHub et clonez-le dans le dossier de vos plugins dans votre configuration WordPress locale. Vous pourrez effectuer des mises à jour de ce référentiel ultérieurement, lorsque le projet Gutenberg sera modifié.

Il existe deux façons de procéder:

  1. Cliquez sur Plugins dans votre tableau de bord WordPress, puis cliquez sur Ajoutez un nouveau . Recherchez “gutenberg” et cliquez sur Installer maintenant . Après l'installation, cliquez sur Activez .
  2. Ou vous pouvez vous diriger vers le référentiel de plug-in WordPress et rechercher «gutenberg». Cliquez sur le premier résultat qui apparaît et téléchargez-le. Extrayez le fichier zip et déplacez le dossier «gutenberg» dans wp-content / plugins . Allez dans le menu Plugins du tableau de bord et cliquez sur Activez pour le plugin Gutenberg.

Maintenant, lorsque vous créez une page ou un message, vous pourrez l'éditer. Utilisation de l'éditeur Gutenberg


 Démonstration de l'éditeur Gutenberg
Démonstration de l'éditeur Gutenberg ( Grand aperçu )

Comme cet article concerne la création d’un bloc Gutenberg, nous n’entrerons pas dans l’introduction au rédacteur en chef. Pour une compréhension complète de ce qu’est Gutenberg et de son utilisation, veuillez vous reporter à cet article relatif à Smashing Magazine.

Installation du bloc Testimonials Slider

Le plugin en question – celui que nous allons parcourir est déjà publié dans le référentiel WordPress

Veuillez installer le Testimonials Slider Block plugin à votre instance WordPress locale afin de vous familiariser avec le fonctionnement du plug-in.

Vous pouvez également copier ou dupliquer le projet à partir de GitHub .

Après avoir activé le plug-in, vous pouvez accéder à votre éditeur Gutenberg et ajoutez un curseur Témoignages à votre contenu:


 Bloc curseur Témoignages
Sélection du bloc curseur Témoignages ( Grand aperçu )

 Ajout de contenu au bloc de curseurs Témoignages
Ajout de contenu à un bloc de curseurs Témoignages ( Grand aperçu )

 Bloc-notes de témoignages dans l'interface
Bloc-notes de témoins dans le bloc ( Grand aperçu )

Maintenant, je vais vous expliquer comment j'ai construit le plugin et comment vous pouvez en créer un de même. Pour que l'article soit concis, je ne partagerai pas l'intégralité du code ici. Cependant, après avoir lu ceci, vous devriez pouvoir créer votre propre bloc Gutenberg.

Prise en main de la configuration

Un bloc Gutenberg est généralement créé dans le cadre d'un plug-in. Notre plugin ne sera pas différent.

Accédez au répertoire des plugins dans votre instance WordPress locale. Déplacer vers le testimonials-slider-block . Notez les fichiers et les dossiers suivants:

  1. gutenberg-testimonials-slider.php est le fichier principal qui contient les détails du plug-in, tels que le nom, la description, les détails de l'auteur et la licence. Ces détails seront utilisés dans la description du plugin dans le menu Plugins du tableau de bord. Vous verrez que ce fichier appelle le fichier init.php.
  2. Le fichier init.php met en file d'attente les différents fichiers JavaScript et CSS. Cela inclut à la fois les bibliothèques externes comme Bootstrap et Font Awesome, ainsi que nos fichiers de construction.
  3. Le fichier .babelrc indique à Webpack le type de fichiers JavaScript que nous écrivons.
  4. Le fichier . Le fichier contient tous les modules npm utilisés dans le plugin. Vous utiliserez la commande npm install pour installer tous ces packages.
  5. Le fichier webpack.config.js contient la configuration permettant à webpack de créer notre code JavaScript et CSS. si vous ne le saviez pas, webpack est un ensemble de paquets principalement utilisé pour regrouper nos modules JavaScript et les placer dans un fichier qui est ensuite mis en file d'attente par WordPress.

Il s'agissait de nombreux fichiers de configuration. Nous pouvons maintenant construire notre bloc de Gutenberg

Enregistrement d’un bloc

Dans le dossier src, vous verrez le fichier index.js . C'est le fichier que Webpack recherche pour regrouper le code JavaScript. Vous pouvez voir que ce fichier importe le fichier slider.js dans le dossier du bloc.

Le style du dossier des blocs est le suivant:

  • slider.js : contient l'actuel code du bloc
  • editor.scss : le fichier de styles décrivant le bloc dans l'éditeur Gutenberg
  • style.scss : contient les styles relatifs à l'affichage du bloc.

Veuillez ouvrir le fichier slider.js dans votre éditeur

. Ce fichier importe d'abord les fichiers de l'éditeur et de style . Ensuite, il importe le composant d'internationalisation, registerBlockType et les composants MediaUpload et PlainText . Les deux derniers composants seront utilisés pour télécharger l'image de l'auteur et pour enregistrer les différentes entrées de texte à enregistrer dans la base de données.

Vous verrez ensuite comment un bloc est enregistré.

Il prend un nom comme premier nom. paramètre. Le nom doit être préfixé par un espace de nom spécifique à votre plug-in afin d'éviter tout conflit avec un autre bloc portant le même nom

Le deuxième paramètre est un tableau avec les propriétés et fonctions suivantes:

  • Title [19659068] Nom du bloc qui apparaîtra lorsque vous ajouterez un nouveau bloc dans l'éditeur de Gutenberg.
  • Icône
    L'icône du bloc qui sera récupérée à partir des dashicons . Vous pouvez également spécifier vos propres icônes SVG si vous le souhaitez.
  • Catégorie
    Sous quelle catégorie de blocs le bloc apparaîtra-t-il. Certaines des catégories sont les suivantes: commun, mise en forme, widgets de présentation et intégration.
  • Mots-clés
    Un tableau de chaînes qui décrit le bloc, semblable aux balises.
  • Attributs
    Un JavaScript objet contenant une description des données sauvegardées par le bloc.
  • Edit
    Fonction servant d'interface pour le bloc dans l'éditeur de Gutenberg.
  • Save
    Le fonction qui décrit comment le bloc sera rendu dans l'interface frontale.

Pour en savoir plus, reportez-vous à la présente documentation .

Présentation de la syntaxe spécifique de Gutenberg

Gutenberg est construit avec React et les blocs que nous construisons pour Gutenberg utilisent une syntaxe similaire.

Il est certainement utile de connaître un peu de React pour créer des blocs Gutenberg personnalisés, mais ce n'est pas le cas doivent être des experts.

Avant de commencer le développement du bloc, il est utile de connaître les éléments suivants:

  • La classe HTML est remplacée par className comme dans React.
  • Les méthodes d'édition et de sauvegarde return JSX, qui signifie JavaScript XML. Si vous vous le demandez, JSX a une syntaxe identique à HTML, sauf que vous pouvez utiliser des balises HTML et d'autres composants tels que PlainText et RichText .
  • Le setAttributes ] fonctionne de manière similaire à setState de React. Lorsque vous appelez setAttributes les données du bloc sont mises à jour et le bloc dans l'éditeur est actualisé.
  • Le bloc utilise les accessoires dans l'édition et . ] save fonctionne comme React. L'objet props contient les attributs l'objet la fonction setAttributes et une tonne d'autres données.

Les attributs Object

] L'objet d'attributs mentionné précédemment définit les données dans le bloc de Gutenberg. Le manuel WordPress Gutenberg indique:

Les sources d'attribut permettent de définir la stratégie selon laquelle les valeurs d'attribut de bloc sont extraites du contenu de l'article enregistré. Ils fournissent un mécanisme permettant de mapper du marquage enregistré vers la représentation JavaScript d'un bloc.

Chaque source accepte un sélecteur facultatif comme premier argument. Si un sélecteur est spécifié, le comportement de la source sera exécuté sur le ou les éléments correspondants contenus dans le bloc. Sinon, il sera exécuté sur le nœud racine du bloc.

Pour plus de détails sur l'utilisation des attributs, veuillez vous reporter à le présent guide .

Ce qui suit est l'objet d'attributs utilisé dans l'objet Témoignages Bloc curseur:

 attributs: {
   id: {
     source: "attribut",
     sélecteur: ".carousel.slide",
     attribut: "id"
   },
   témoignages: {
     source: "requête",
     défaut: [],
     sélecteur: "blockquote.testimonial",
     requête: {
       image: {
         source: "attribut",
         sélecteur: "img",
         attribut: "src"
       },
       index: {
         texte source",
         sélecteur: "span.testimonial-index"
       },
       contenu: {
         texte source",
         sélecteur: "span.testimonial-text"
       },
       auteur: {
         texte source",
         sélecteur: "span.testimonial-author span"
       },
       lien: {
         texte source",
         sélecteur: ".testimonial-author-link"
       }
     }
   }
 },

La source indique à Gutenberg où rechercher des données dans le balisage.

Utilisez l'attribut pour extraire la valeur d'un attribut du balisage, tel que le src de l'élément img . Les sélecteurs et indiquent les éléments à rechercher et les attributs exacts dans lesquels les données doivent être extraites. Notez que la chaîne de sélection récupère un élément HTML dans la fonction save .

Utilisez text pour vous extraire le texte intérieur du balisage et html pour en extraire le contenu. HTML interne à partir du balisage.

Utilisez la requête de la requête pour extraire un tableau de valeurs du balisage. Les entrées du tableau sont déterminées par l'argument selector où chaque élément mis en correspondance dans le bloc aura une entrée structurée correspondant à l'argument de la requête objet de l'attribut . ] et text sources.

Vous pouvez accéder aux attributs des fonctions edit et save via props.attributes .

. ] Lorsque vous utilisez console.log (props.attributes.testimonials) dans la fonction edit vous obtenez le résultat suivant:

   (2) [{...}, {...}]
     ▼ 0:
      auteur: "Muhammad"
      contenu: "Ceci est un témoignage"
      image: "http: //localhost/react-gutenberg/wp-content/uploads/2018/08/0.jpg"
      indice: 0
      lien: "https://twitter.com/muhsinlk"
    ▶ __proto__: objet
  ▼ 1:
    auteur: "Matt"
    contenu: "Ceci est un autre témoignage"
    image: "http: //localhost/react-gutenberg/wp-content/uploads/2018/08/767fc115a1b989744c755db47feb60.jpeg"
    indice: 1
    lien: "https://twitter.com/photomatt"
   ▶ __proto__: objet
   longueur: 2
  ▶ __proto__: Tableau (0)

Par conséquent, dans le code ci-dessus, id est un texte qui décrit de manière unique chaque bloc testimonial, tandis que testimonials est un tableau d'objets dans lequel chaque objet a les propriétés indiquées dans la capture d'écran ci-dessus. edit Et save Fonctions

Comme mentionné ci-dessus, ces deux fonctions décrivent comment le bloc est rendu dans l'éditeur ainsi que dans l'interface.

Veuillez lire le texte intégral. description ici .

Fonction edit

Si vous regardez la fonction edit vous remarquerez ce qui suit:

  1. le tableau props.attributes.testimonials à une variable const. Observez la destruction d'objet ES6 pour définir la valeur const.
  2. Générez ensuite un identifiant pour le bloc, qui sera utilisé pour rendre chaque bloc unique lorsque vous ajoutez plus d'un bloc de curseurs Témoignages à votre contenu.
  3. Ensuite, le ] testimonialsList est générée. Elle est obtenue en triant puis en mappant le tableau de témoignages que nous avons obtenu à l'étape 1.
  4. Ensuite, la fonction de retour renvoie JSX, dont nous avons déjà parlé. La testimonialsList que nous avons construite à l'étape 3, est rendue. Le bouton + est également rendu, en appuyant sur ce qui créera un nouveau témoignage à l'intérieur du bloc.

Si vous creusez dans testimonialsList vous verrez qu'il contient les PlainText et . ] Composants MediaUpload . Celles-ci fournissent l'interface permettant de saisir les différents textes et de télécharger l'image de l'auteur, respectivement.

Le composant PlainText se présente comme suit:

  {
  const newObject = Object.assign ({}, testimonial, {
    contenu: contenu
  });
  props.setAttributes ({
    témoignages: [
      ...testimonials.filter(
        item => item.index != testimonial.index
      ),
      newObject
    ]
    });
  }}
/>
</plaintext></code></pre><p> Les attributs que j'ai utilis&eacute;s pour le composant <code> PlainText </code> sont les suivants:</p><ul><li> <code> className </code><br> La classe CSS du composant afin de le nommer.</li><li> <code> style [19659120] Donner une hauteur minimale pour que le contenu ne ressemble pas &agrave; un texte d'une ligne. La sp&eacute;cification de la hauteur &agrave; l'aide du s&eacute;lecteur de classe n'a pas fonctionn&eacute;. </code></li><li> <code> espace r&eacute;serv&eacute; </code><br> Le texte qui s'affiche lorsque aucun contenu n'est ajout&eacute;.</li><li> <code> value </code><br> La valeur du composant de la objet dans la matrice de t&eacute;moignages.</li><li> <code> autoFocus </code><br> Indiquer au navigateur de se concentrer sur ce composant (champ de saisie) d&egrave;s que l'utilisateur ajoute un nouveau t&eacute;moignage en cliquant sur le bouton +.</li><li> <code> onChange </code><br> Ce qui ressemble &agrave; l'attribut le plus complexe de cette liste. Cette fonction obtient d&rsquo;abord une copie du t&eacute;moignage actuel et affecte le contenu modifi&eacute; &agrave; newObject. Ensuite, il &eacute;tale le tableau d'objets, filtre l'objet actuel &agrave; l'aide de l'index, puis remplace l'objet newObject dans le tableau. Cette fonction est d&eacute;finie &agrave; l'aide de la fonction props.setAttributes du tableau testimonials.</li></ul><h4> La fonction <code> save </code></h4><p> Cette fonction effectue les op&eacute;rations suivantes:</p><ol><li> J'obtiens d'abord le <code> props.attributes. testimonials </code> array et <code> props.attributes.id </code> cha&icirc;ne en variables const. Notez &agrave; nouveau que la destruction d'objets ES6 est utilis&eacute;e pour d&eacute;finir les valeurs des deux variables const id et testimonials.</li><li> Ensuite, je cr&eacute;e la variable <code> carouselIndicators </code>qui est essentiellement JSX construite &agrave; partir du tableau testimonials. ] Ensuite, la <code> testimonialsList </code> est cr&eacute;&eacute;e &agrave; partir du tableau de t&eacute;moignages. L'extrait ci-dessous provient du retour de rappel de fonction mapp&eacute;e.<pre class="break-out"><code class="language-css"> {testimonial.content &amp;&amp; (
&nbsp;&nbsp;<p classname="testimonial-text-container">
    <i classname="fa fa-quote-left pull-left" aria-hidden="true"></i>
    <span classname="testimonial-text"> {testimonial.content} </span>
    <i class="fa fa-quote-right pull-right" aria-hidden="true"></i>
  </p>
)}
</code></pre><p> Remarquez le rendu conditionnel. Le balisage ne sera pas rendu pour le contenu si le contenu n'est pas d&eacute;fini.</p></li><li> Ensuite, si le tableau testimonials contient des objets, le code HTML est rendu. C'est ce qui sera s&eacute;rialis&eacute; et sauvegard&eacute; dans la base de donn&eacute;es, et ce qui sera montr&eacute; dans le frontal (pas textuellement).</li></ol><h3 id="continuing-development"> D&eacute;veloppement continu</h3><p> Je suis s&ucirc;r que vous voulez modifier ce plugin et voir ce qui se passe. . Vous pouvez continuer &agrave; d&eacute;velopper le plug-in:</p><ol><li> Ouvrez le terminal</li><li> Acc&eacute;dez au r&eacute;pertoire racine du plug-in</li><li> <code> npm install </code></li><li> <code> npm start </code></li></ol><p> installez tous les packages, construisez les fichiers et surveillez les modifications. Chaque fois que vous modifiez les fichiers, Webpack reconstruit les fichiers JS et CSS.</p><p> <strong> Remarque: </strong> Les modifications de balisage apport&eacute;es aux blocs g&acirc;cheront le bloc dans l'&eacute;diteur Gutenberg si vous l'aviez ajout&eacute;. avant. Ne vous inqui&eacute;tez pas - vous devez simplement supprimer le bloc et l'ajouter &agrave; nouveau.</p><p> Si vous avez termin&eacute; de d&eacute;velopper, vous pouvez <code> npm ex&eacute;cuter build </code> pour r&eacute;duire le nombre de fichiers afin de le rendre pr&ecirc;t pour la production! 19659005] J'esp&egrave;re que vous &ecirc;tes maintenant convaincu que le d&eacute;veloppement de blocs de Gutenberg est plus abordable qu'il n'y para&icirc;t.</p><p> J'ai les plans suivants en t&ecirc;te pour ce plugin:</p><ul><li> Permet aux utilisateurs de s&eacute;lectionner la couleur du texte, de l'arri&egrave;re-plan et de l'accent.</li><li> Autorisez les utilisateurs &agrave; s&eacute;lectionner la taille du curseur et de la police.</li><li> &Eacute;vitez de vous fier &agrave; des biblioth&egrave;ques telles que Bootstrap et Font Awesome.</li></ul><p> Je vous encourage &agrave; <a href="https://github.com/laccadive-io/testimonials-slider-block"> de faire une demande de tirage </a> avec vos am&eacute;liorations et fonctionnalit&eacute;s suppl&eacute;mentaires. [19659156] Commencer un nouveau bloc de Gutenberg</p><p> Il existe plusieurs fa&ccedil;ons de d&eacute;velopper un bloc de Gutenberg. L'une des m&eacute;thodes recommand&eacute;es consiste &agrave; utiliser <code><a href="https://github.com/ahmadawais/create-guten-block"> create-guten-block </a></code> cr&eacute;&eacute; par <a href="https://twitter.com/mrahmadawais"> Ahmad Awais </a>. En fait, ce projet a &eacute;t&eacute; construit sur la base du <code><a href="https://github.com/laccadive-io/guten-testimonial-block"> guten-testimonial-block </a></code> qui a &eacute;t&eacute; d&eacute;marr&eacute; &agrave; partir du <code> create-guten-block </code>.</p><p> Vous pouvez &eacute;galement consulter le r&eacute;pertoire <a href="https://github.com/zgordon/gutenberg-course"> de Zac Gordon. </a> o&ugrave; il montre comment utiliser les diff&eacute;rents composants de Gutenberg dans votre nouveau bloc.</p><h3 id="conclusion"> Conclusion</h3><p> Nous avons couvert les &eacute;l&eacute;ments suivants dans l'article d'aujourd'hui:</p><ul><li> Installation et utilisation des plugins Slider Block de Gutenberg et Testimonials</li><li> Configuration pour un plugin de bloc Gutenberg typique</li><li> Enregistrement d'un bloc Gutenberg</li><li> Comment utiliser l'objet attributs</li><li> Les fonctions <code> edit </code> et <code> save </code> et leur utilisation.</li></ul><p> J'esp&egrave;re que cet article vous a &eacute;t&eacute; utile. Je suis impatient de voir ce que vous construirez avec et pour Gutenberg!</p><div class="signature"> <img decoding="async" src="https://i0.wp.com/blog.arcoptimizer.com/wp-content/uploads/2018/04/1523030185_12_frappez-le-terrain-en-courant-avec-vue-js-et-firestore-smashing-magazine.png?w=660" alt=" &Eacute;ditorial &eacute;clatant " data-recalc-dims="1"><span> (dm, ra, yk, il) </span></div></div><p><script defer src="http://platform.twitter.com/widgets.js" charset="utf-8"></script><br> <br></p><div class="clearfix button-collection container text-center "></div><div class="clearfix button-collection container text-center "></div><div class="clearfix button-collection container text-center "><a id="layers-widget-layers-pro-call-to-action-3-buttons-554" class="button " href="https://arcoptimizer.com/botinstagram?utm_source=bottom_article_blog&amp;utm_medium=cta&amp;utm_campaign=corporate_estimation"> Le meilleur outil 2023 pour ta croissance Instagram ! </a></div><div class="clearfix text-center "> <button class="circle-action-btn"><div class="circle-action-btn__icon"><i class="ion-speedometer"></i></div> </button></div> <br> <script async src="//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script> <ins class="adsbygoogle" style="display:block; text-align:center;" data-ad-layout="in-article" data-ad-format="fluid" data-ad-client="ca-pub-2247171909266990" data-ad-slot="5039287111"></ins> <script>(adsbygoogle = window.adsbygoogle || []).push({});</script><br> <br><a href="https://www.smashingmagazine.com/2018/10/gutenberg-testimonials-sliderblock/">Source link </a><div class="sharedaddy sd-sharing-enabled"><div class="robots-nocontent sd-block sd-social sd-social-icon sd-sharing"><h3 class="sd-title">Partager&nbsp;:</h3><div class="sd-content"><ul><li class="share-twitter"><a rel="nofollow noopener noreferrer" data-shared="sharing-twitter-13143" class="share-twitter sd-button share-icon no-text" href="https://blog.arcoptimizer.com/debuter-avec-gutenberg-en-creant-votre-propre-bloc?share=twitter" target="_blank" title="Cliquez pour partager sur Twitter"><span></span><span class="sharing-screen-reader-text">Cliquez pour partager sur Twitter(ouvre dans une nouvelle fen&ecirc;tre)</span></a></li><li class="share-facebook"><a rel="nofollow noopener noreferrer" data-shared="sharing-facebook-13143" class="share-facebook sd-button share-icon no-text" href="https://blog.arcoptimizer.com/debuter-avec-gutenberg-en-creant-votre-propre-bloc?share=facebook" target="_blank" title="Cliquez pour partager sur Facebook"><span></span><span class="sharing-screen-reader-text">Cliquez pour partager sur Facebook(ouvre dans une nouvelle fen&ecirc;tre)</span></a></li><li class="share-end"></ul></div></div></div></body></html><div id='jp-relatedposts' class='jp-relatedposts' ><h3 class="jp-relatedposts-headline"><em>Articles similaires</em></h3></div></div><footer class="meta-info"><p><span class="meta-item meta-date"><i class="l-clock-o"></i> octobre 9, 2018</span> <span class="meta-item meta-tags"><i class="l-tags"></i> <a href="https://blog.arcoptimizer.com/tag/bloc" title="View all posts tagged bloc">bloc</a>, <a href="https://blog.arcoptimizer.com/tag/creant" title="View all posts tagged créant">créant</a>, <a href="https://blog.arcoptimizer.com/tag/debuter" title="View all posts tagged débuter">débuter</a>, <a href="https://blog.arcoptimizer.com/tag/gutenberg" title="View all posts tagged Gutenberg">Gutenberg</a></span></p></footer></article></div></div><div id="back-to-top"> <a href="#top">Revenir vers le haut</a></div></section><footer id="footer" class="footer-site invert"><div class="container content clearfix"><div class="row copyright"><div class="column span-6"><p class="site-text">Copyright arcoptimizer.com <script>document.write(new Date().getFullYear())</script> article@arcoptimizer.com</p></div><div class="column span-6 clearfix t-right"><nav class="nav nav-horizontal pull-right"><ul id="menu-menu_footer" class="menu"><li id="menu-item-142202" class="menu-item menu-item-type-custom menu-item-object-custom menu-item-142202"><a href="mailto:article@arcoptimizer.com"><i class='fa fa-envelope'></i></a></li><li id="menu-item-142203" class="menu-item menu-item-type-custom menu-item-object-custom menu-item-142203"><a href="http://article@arcoptimizer.com">article@arcoptimizer.com</a></li></ul></nav></div></div></div></footer><div class="search-interface-overlay"><form role="search" method="get" class="search-interface-holder" action="https://blog.arcoptimizer.com/"> <label class="search-text"> Search: </label> <input
 type="text"
 id="layers-modal-search-field"
 class="search-field"
 placeholder="Type Something"
 value=""
 name="s"
 title="Search for:"
 autocomplete="off"
 autocapitalize="off"
 ></form> <a href="#" class="search-close"> <i class="l-close"></i> </a></div></section><style type="text/css">@media (max-width: 480px) {  .ednpro_main_wrapper{display:none; }   }</style><div class="ednpro_main_wrapper ednpro_section"><div class="edn-close-section" id="apex_cookie_0" ><div class="edn-notify-bar edn-position-bottom edn-visibility-show-time edn-custom-template edn_no_close_button" id="edn_custom_template" data-barid="apexbar-0" data-postid="13143"> <input type="hidden" id='effect_type0' value="edn_pro_static"/> <input type="hidden" class='edn_social_optons' value="0"/> <input type="hidden" class='edn_right_optons' value="1"/><div class="edn-container apexnb-bartypeedn_pro_static"><style type="text/css">.edn-notify-bar .edn-custom-design-wrapper .ticker-wrapper .ticker, .edn-notify-bar .ticker-wrapper .ticker{
        font-family: default;
                         font-size: 22px;
                                  background-color: #1e73be;
            }
    /*added custom css*/
    .edn-custom-template[data-barid=apexbar-0] .edn-custom-design-wrapper,
     .edn-custom-template[data-barid=apexbar-0],
    .edn-custom-template[data-barid=apexbar-0] .edn-contact-lightbox .edn-contact-lightbox-inner-wrap,
    .edn-custom-template[data-barid=apexbar-0] .edn-contact-close,
    .edn-custom-template[data-barid=apexbar-0] .edn-contact-lightbox-inner-wrap{
                font-family: default;
                         font-size: 22px;
                                  background-color: #1e73be;
        
    }
    .edn-custom-template[data-barid=apexbar-0] .edn-contact-lightbox-inner-wrap label{
             }
    .edn-custom-template[data-barid=apexbar-0] .edn-mulitple-text-content,
    .edn-custom-template[data-barid=apexbar-0] .edn_static_text, 
    .slider_template_wrapper .edn-tweet-content, .edn-post-title-wrap .edn-post-title li,
    .edn-custom-template[data-barid=apexbar-0] .edn_static_text, 
    .slider_template_wrapper .edn-tweet-content, .edn-post-title-wrap .edn-post-title li,
    .edn-custom-template[data-barid=apexbar-0] .edn-tweet-content,
    .edn-custom-template[data-barid=apexbar-0] .edn-tweet-content a,
    .edn-custom-template[data-barid=apexbar-0] .ticker-content,
    .edn-custom-template[data-barid=apexbar-0] a,
     .edn-custom-template[data-barid=apexbar-0] .ticker-wrapper .ticker-content a, 
    .edn-custom-template[data-barid=apexbar-0] .ticker-wrapper .ticker-content .edn-tweet-content, 
    .edn-custom-template[data-barid=apexbar-0] .ticker-wrapper .edn-mulitple-text-content{
                 font-family: default;
                        font-size: 22px;
                     }
    .edn-custom-template[data-barid=apexbar-0] .edn-contact-form-wrap .edn-contact-close{
                            background-color: #1e73be;
            }
    /*tweets*/

    .edn-custom-template[data-barid=apexbar-0] .ticker-wrapper .edn-post-title-readmore{
                font-family: default;
                          font-size: 22px;
                               }
    /*ticker custom design start*/

    .edn-custom-template[data-barid=apexbar-0] .ticker-wrapper .ticker-content a{
        margin-left: 8px;
    }
    .edn-custom-template[data-barid=apexbar-0] .ticker_pattern .edn-ticker-wrapper  .ticker-wrapper  .ticker-swipe{
                  background-color: #1e73be;
            }

    /*ticker custom design end*/
    .edn-custom-template[data-barid=apexbar-0] .edn-contact-close,input[type="button"].edn-contact-submit{
                   background-color: #1e73be;
            }
    .edn-custom-template[data-barid=apexbar-0] a.edn-controls-close,input[type="button"].edn-contact-submit{
               color: #000000;
             }

    .edn-custom-template[data-barid=apexbar-0] .edn-social-heading-title{
                   font-size: 22px;
            }
    /*Custom Subscribe Form CSS ADDED*/
    .edn-custom-template[data-barid=apexbar-0] h1,
    .edn-custom-template[data-barid=apexbar-0] h2,
    .edn-custom-template[data-barid=apexbar-0] h3,
    .edn-custom-template[data-barid=apexbar-0] h4,
    .edn-custom-template[data-barid=apexbar-0] h5,
    .edn-custom-template[data-barid=apexbar-0] h6,
    .edn-custom-template[data-barid=apexbar-0] .edn-subscribe-form .edn-front-title h3{
                       font-size: 22px;
            }
    .edn-custom-template[data-barid=apexbar-0] .edn-subscribe-form .edn-front-title h3 span{
                }
    .edn-custom-template[data-barid=apexbar-0] .edn-subscribe-form .edn-front-title .show_icon i{
               }
    

    /*Constant Contact Subscribe Form CSS END*/
    /* For all  CUstom buttons start */
    .edn-custom-template[data-barid=apexbar-0] .edn-form-field .constant_subscribe, 
    .edn-custom-template[data-barid=apexbar-0] .edn-subscribe-form .edn-form-field .edn_subs_submit_ajax,   
    .edn-custom-template[data-barid=apexbar-0] .edn-custom-contact-link, 
    .edn-custom-template[data-barid=apexbar-0] .edn-temp1-static-button,
    .edn-custom-template[data-barid=apexbar-0] .apexnb-search-layout1 .apex-search-right-section .btn-search-now,
    .edn-custom-template[data-barid=apexbar-0] .edn_static_text .edn-call-action-button a, 
    .edn-custom-template[data-barid=apexbar-0] .edn-call-action-button a,
    .edn-custom-template[data-barid=apexbar-0] .edn-contact-lightbox .edn-form-field .edn-field input.edn-contact-submit{
               background: #eeee22;
                 color: #000000;
                 font-family: default;
            }
   
         .edn-custom-template[data-barid=apexbar-0] .edn_static_text .edn-call-action-button a:hover,
        .edn-custom-template.edn-notify-bar .edn-custom-contact-link:hover,
        .edn-custom-template[data-barid=apexbar-0] .apexnb-search-layout1 .apex-search-right-section .btn-search-now:hover,
        .edn-custom-template[data-barid=apexbar-0] .edn-subscribe-form .edn-form-field .edn_subs_submit_ajax:hover,
        .edn-custom-template[data-barid=apexbar-0] .edn-form-field .edn_mailchimp_submit_ajax:hover,
        .edn-custom-template[data-barid=apexbar-0] .edn-form-field .constant_subscribe:hover 
        {
            color: #ffffff;
            background: #81d742;
        }

        
        .edn-custom-template[data-barid=apexbar-0] .edn_static_text .edn-text-link a, 
        .edn-custom-template[data-barid=apexbar-0] .edn_multiple_text .edn-mulitple-text-content a,
        edn-custom-template[data-barid=apexbar-0] .edn-multiple-content .edn-mulitple-text-content a,
        .edn-custom-template[data-barid=apexbar-0] .edn-post-title-wrap .edn-post-title li a{
            color: #000000;
            background: ;
        }
        
    /* close button custom css */
       .edn-custom-template[data-barid=apexbar-0]  .edn-top-up-arrow.open,
    .edn-custom-template[data-barid=apexbar-0]  .edn-bottom-down-arrow.open,
    .edn-custom-template[data-barid=apexbar-0]  .edn-bottom-down-arrow.open,
    .edn-custom-template[data-barid=apexbar-0] .edn-left-arrow,
    .edn-custom-template[data-barid=apexbar-0] .edn-right-arrow,
    .edn-custom-template[data-barid=apexbar-0] .edn-cntrol-wrap.ednpro_user-can-close {
               background-image:  url("../../images/showhidetoggledown.png") no-repeat scroll 0 0;

    }
    .edn-custom-template[data-barid=apexbar-0] .edn-cntrol-wrap.ednpro_user-can-close .fa-close{
           }

    .edn-custom-template[data-barid=apexbar-0] .edn-top-up-arrow {
                background-image: url("../../images/showhidetoggletop.png") no-repeat scroll 0 0;
        border-radius: 14px;
    }
    .edn-custom-template[data-barid=apexbar-0] .edn-bottom-down-arrow{
                  border-radius: 14px;
        background-image: url("../../images/showhidetoggledown.png") no-repeat scroll 0 0;
    }
    /* close button custom css */


    .edn-custom-template[data-barid=apexbar-0] .edn_error,.edn-error,
    .edn-constant-error
    .edn-custom-template[data-barid=apexbar-0] .edn-success,
    .edn-constant-success{
               font-family: default;
                   }


    /*social icons custom design start*/
    
        .edn-custom-template[data-barid=apexbar-0] .edn-post-title-wrap .edn-post-title li{
                  }

        
    .edn-custom-template[data-barid=apexbar-0].edn-visibility-show-time{
        display: none;
    }
    .edn-custom-template[data-barid=apexbar-0] .visibility_show-time{
        display: none;
    }
               .edn-notify-bar .edn-custom-design-wrapper .edn-post-title-readmore{
            color: #000000 !important;
            background: #eeee22 !important;
            padding: 2px 8px;
            font-size: 35px !important;             font-weight: bolder !important;         }
            .edn-notify-bar .edn-custom-design-wrapper .edn-post-title-readmore:hover{
            color: #ffffff !important;
            background: #81d742 !important;
        }</style><div class="edn-temp-design-wrapper edn-custom-design-wrapper"><div class="edn_middle_content edn_pro_static_pattern"><div class="edn-text-content-wrap"><div class="edn_static_text"><div class="edn-text-link">L’Outil Surpuissant pour Exploser ton Chiffre d'Affaires en 2024 !</div> <span class="edn-call-action-button"> <span class="edn-ca-custom"> <a class="edn-static-button" href="https://allleads.arcoptimizer.com/fr" target='_blank'> <span class="edn-ca-static-button">Essai Gratuit Aujourd&#039;hui</span> </a> </span> </span></div></div></div></div></div> <input type="hidden" class="edn-ticker-option" id="apexnb-ticker-0"
 data-ticker-speed=""
 data-ticker-direction="vertical"
 data-ticker-title=""
 data-ticker-hover=""
 data-slider-controls=""
 data-slider-animation="horizontal"
 data-slider-duration=""
 data-slider-auto="true"
 data-slider-transition=""
 data-slider-adaptive-height="true"
 data-scroll-controls=""
 data-scroll-direction="ltr"
 data-scroll-animation="reveal"
 data-scroll-speed=""
 data-scroll-title=""
/> <input type="hidden" class="edn-visibility-bar-options edn-visibility-option-0" id="apexnb-0"
 data-show-time-duration="200"
 data-hide-time-duration=""
 data-visibility-type = "show-time"
 data-close-type = "disable"
 data-close-once = ""
 data-duration-close = "" 
 data-show_once_hideshow = ""
 data-notification_bar_id = "0"
/><div class="apexnb-ccform edn-template-3 edn-popup-form" data-formtype="apexnb-static-custom" data-barid="0"><div class="edn-contact-lightbox" id="edn-static-cf-btn-0-lightbox" style="display: none;"><div class="ednpro_overlay"></div><div class="edn-contact-lightbox-inner-wrap " id="edn-contact-lightbox-inner-wrap-0"><div class="edn-contact-lightbox-inner-content edn-contact-lightbox-inner-wrap apexnb-ccustomform-wrapper "></div></div></div></div></div></div></div><script defer src="data:text/javascript;base64,PGFtcC1hdXRvLWFkcyB0eXBlPSJhZHNlbnNlIgogICAgICAgIGRhdGEtYWQtY2xpZW50PSJjYS1wdWItMjI0NzE3MTkwOTI2Njk5MCI+CjwvYW1wLWF1dG8tYWRzPg=="></script> <script defer src="data:text/javascript;base64,CgkJd2luZG93LldQQ09NX3NoYXJpbmdfY291bnRzID0geyJodHRwczpcL1wvYmxvZy5hcmNvcHRpbWl6ZXIuY29tXC9kZWJ1dGVyLWF2ZWMtZ3V0ZW5iZXJnLWVuLWNyZWFudC12b3RyZS1wcm9wcmUtYmxvYyI6MTMxNDN9OwoJ"></script> <link rel='stylesheet' id='aal_style-css' href='https://blog.arcoptimizer.com/wp-content/cache/autoptimize/css/autoptimize_single_4c15efd49114c121de9d8db67a23db93.css' type='text/css' media='all' /> <script defer type='text/javascript' src='https://blog.arcoptimizer.com/wp-content/cache/autoptimize/js/autoptimize_single_328b8123661abdd5f4a0c695e7aa9dcc.js?minify=false&#038;ver=132249e245926ae3e188' id='jetpack-photon-js'></script> <script defer type='text/javascript' src='https://blog.arcoptimizer.com/wp-content/themes/defaut_theme3/assets/js/wow.min.js' id='layers-child-wow-js'></script> <script defer type='text/javascript' src='https://stats.wp.com/e-202416.js' id='jetpack-stats-js'></script> <script type='text/javascript' id='jetpack-stats-js-after'>_stq = window._stq || [];
_stq.push([ "view", {v:'ext',blog:'146388461',post:'13143',tz:'0',srv:'blog.arcoptimizer.com',j:'1:12.8.1'} ]);
_stq.push([ "clickTrackerInit", "146388461", "13143" ]);</script> <script defer type='text/javascript' src='https://blog.arcoptimizer.com/wp-content/cache/autoptimize/js/autoptimize_single_f4c0e5d883b22cceae0e8fbf05d26b3c.js' id='quads-ads-js'></script> <script defer id="sharing-js-js-extra" src="data:text/javascript;base64,Ci8qIDwhW0NEQVRBWyAqLwp2YXIgc2hhcmluZ19qc19vcHRpb25zID0geyJsYW5nIjoiZW4iLCJjb3VudHMiOiIxIiwiaXNfc3RhdHNfYWN0aXZlIjoiMSJ9OwovKiBdXT4gKi8K"></script> <script defer type='text/javascript' src='https://blog.arcoptimizer.com/wp-content/plugins/jetpack/_inc/build/sharedaddy/sharing.min.js' id='sharing-js-js'></script> <script defer id="sharing-js-js-after" src="data:text/javascript;base64,CnZhciB3aW5kb3dPcGVuOwoJCQkoIGZ1bmN0aW9uICgpIHsKCQkJCWZ1bmN0aW9uIG1hdGNoZXMoIGVsLCBzZWwgKSB7CgkJCQkJcmV0dXJuICEhICgKCQkJCQkJZWwubWF0Y2hlcyAmJiBlbC5tYXRjaGVzKCBzZWwgKSB8fAoJCQkJCQllbC5tc01hdGNoZXNTZWxlY3RvciAmJiBlbC5tc01hdGNoZXNTZWxlY3Rvciggc2VsICkKCQkJCQkpOwoJCQkJfQoKCQkJCWRvY3VtZW50LmJvZHkuYWRkRXZlbnRMaXN0ZW5lciggJ2NsaWNrJywgZnVuY3Rpb24gKCBldmVudCApIHsKCQkJCQlpZiAoICEgZXZlbnQudGFyZ2V0ICkgewoJCQkJCQlyZXR1cm47CgkJCQkJfQoKCQkJCQl2YXIgZWw7CgkJCQkJaWYgKCBtYXRjaGVzKCBldmVudC50YXJnZXQsICdhLnNoYXJlLXR3aXR0ZXInICkgKSB7CgkJCQkJCWVsID0gZXZlbnQudGFyZ2V0OwoJCQkJCX0gZWxzZSBpZiAoIGV2ZW50LnRhcmdldC5wYXJlbnROb2RlICYmIG1hdGNoZXMoIGV2ZW50LnRhcmdldC5wYXJlbnROb2RlLCAnYS5zaGFyZS10d2l0dGVyJyApICkgewoJCQkJCQllbCA9IGV2ZW50LnRhcmdldC5wYXJlbnROb2RlOwoJCQkJCX0KCgkJCQkJaWYgKCBlbCApIHsKCQkJCQkJZXZlbnQucHJldmVudERlZmF1bHQoKTsKCgkJCQkJCS8vIElmIHRoZXJlJ3MgYW5vdGhlciBzaGFyaW5nIHdpbmRvdyBvcGVuLCBjbG9zZSBpdC4KCQkJCQkJaWYgKCB0eXBlb2Ygd2luZG93T3BlbiAhPT0gJ3VuZGVmaW5lZCcgKSB7CgkJCQkJCQl3aW5kb3dPcGVuLmNsb3NlKCk7CgkJCQkJCX0KCQkJCQkJd2luZG93T3BlbiA9IHdpbmRvdy5vcGVuKCBlbC5nZXRBdHRyaWJ1dGUoICdocmVmJyApLCAnd3Bjb210d2l0dGVyJywgJ21lbnViYXI9MSxyZXNpemFibGU9MSx3aWR0aD02MDAsaGVpZ2h0PTM1MCcgKTsKCQkJCQkJcmV0dXJuIGZhbHNlOwoJCQkJCX0KCQkJCX0gKTsKCQkJfSApKCk7CnZhciB3aW5kb3dPcGVuOwoJCQkoIGZ1bmN0aW9uICgpIHsKCQkJCWZ1bmN0aW9uIG1hdGNoZXMoIGVsLCBzZWwgKSB7CgkJCQkJcmV0dXJuICEhICgKCQkJCQkJZWwubWF0Y2hlcyAmJiBlbC5tYXRjaGVzKCBzZWwgKSB8fAoJCQkJCQllbC5tc01hdGNoZXNTZWxlY3RvciAmJiBlbC5tc01hdGNoZXNTZWxlY3Rvciggc2VsICkKCQkJCQkpOwoJCQkJfQoKCQkJCWRvY3VtZW50LmJvZHkuYWRkRXZlbnRMaXN0ZW5lciggJ2NsaWNrJywgZnVuY3Rpb24gKCBldmVudCApIHsKCQkJCQlpZiAoICEgZXZlbnQudGFyZ2V0ICkgewoJCQkJCQlyZXR1cm47CgkJCQkJfQoKCQkJCQl2YXIgZWw7CgkJCQkJaWYgKCBtYXRjaGVzKCBldmVudC50YXJnZXQsICdhLnNoYXJlLWZhY2Vib29rJyApICkgewoJCQkJCQllbCA9IGV2ZW50LnRhcmdldDsKCQkJCQl9IGVsc2UgaWYgKCBldmVudC50YXJnZXQucGFyZW50Tm9kZSAmJiBtYXRjaGVzKCBldmVudC50YXJnZXQucGFyZW50Tm9kZSwgJ2Euc2hhcmUtZmFjZWJvb2snICkgKSB7CgkJCQkJCWVsID0gZXZlbnQudGFyZ2V0LnBhcmVudE5vZGU7CgkJCQkJfQoKCQkJCQlpZiAoIGVsICkgewoJCQkJCQlldmVudC5wcmV2ZW50RGVmYXVsdCgpOwoKCQkJCQkJLy8gSWYgdGhlcmUncyBhbm90aGVyIHNoYXJpbmcgd2luZG93IG9wZW4sIGNsb3NlIGl0LgoJCQkJCQlpZiAoIHR5cGVvZiB3aW5kb3dPcGVuICE9PSAndW5kZWZpbmVkJyApIHsKCQkJCQkJCXdpbmRvd09wZW4uY2xvc2UoKTsKCQkJCQkJfQoJCQkJCQl3aW5kb3dPcGVuID0gd2luZG93Lm9wZW4oIGVsLmdldEF0dHJpYnV0ZSggJ2hyZWYnICksICd3cGNvbWZhY2Vib29rJywgJ21lbnViYXI9MSxyZXNpemFibGU9MSx3aWR0aD02MDAsaGVpZ2h0PTQwMCcgKTsKCQkJCQkJcmV0dXJuIGZhbHNlOwoJCQkJCX0KCQkJCX0gKTsKCQkJfSApKCk7Cg=="></script> <script defer src="data:text/javascript;base64,DQogd293ID0gbmV3IFdPVygNCiB7DQogLy9ib3hDbGFzczogICAgICd3b3cnLCAgICAgIC8vIGRlZmF1bHQNCiAvL2FuaW1hdGVDbGFzczogJ2FuaW1hdGVkJywgLy8gZGVmYXVsdA0KIG9mZnNldDogICAgICAgMTAwLCAgICAgICAgICAvLyBkZWZhdWx0DQogLy9tb2JpbGU6ICAgICAgIHRydWUsICAgICAgIC8vIGRlZmF1bHQNCiAvL2xpdmU6ICAgICAgICAgdHJ1ZSAgICAgICAgLy8gZGVmYXVsdA0KIH0NCiApDQogd293LmluaXQoKTsNCiA="></script> <script defer src="data:text/javascript;base64,DQogICAgICAgIGpRdWVyeShkb2N1bWVudCkucmVhZHkoZnVuY3Rpb24gKCQpIHsNCg0KICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBkb2N1bWVudC5mb3Jtcy5sZW5ndGg7ICsraSkgew0KICAgICAgICAgICAgICAgIGxldCBmb3JtID0gZG9jdW1lbnQuZm9ybXNbaV07DQoJCQkJaWYgKCQoZm9ybSkuYXR0cigibWV0aG9kIikgIT0gImdldCIpIHsgJChmb3JtKS5hcHBlbmQoJzxpbnB1dCB0eXBlPSJoaWRkZW4iIG5hbWU9ImdxZUtwQ04tVHNWUHgiIHZhbHVlPSJWOUBKW1hfOGFxTCIgLz4nKTsgfQppZiAoJChmb3JtKS5hdHRyKCJtZXRob2QiKSAhPSAiZ2V0IikgeyAkKGZvcm0pLmFwcGVuZCgnPGlucHV0IHR5cGU9ImhpZGRlbiIgbmFtZT0id1JrT3VOQS1MZEVybSIgdmFsdWU9Ii5UZkZdYXQiIC8+Jyk7IH0KICAgICAgICAgICAgfQ0KDQogICAgICAgICAgICAkKGRvY3VtZW50KS5vbignc3VibWl0JywgJ2Zvcm0nLCBmdW5jdGlvbiAoKSB7DQoJCQkJaWYgKCQodGhpcykuYXR0cigibWV0aG9kIikgIT0gImdldCIpIHsgJCh0aGlzKS5hcHBlbmQoJzxpbnB1dCB0eXBlPSJoaWRkZW4iIG5hbWU9ImdxZUtwQ04tVHNWUHgiIHZhbHVlPSJWOUBKW1hfOGFxTCIgLz4nKTsgfQppZiAoJCh0aGlzKS5hdHRyKCJtZXRob2QiKSAhPSAiZ2V0IikgeyAkKHRoaXMpLmFwcGVuZCgnPGlucHV0IHR5cGU9ImhpZGRlbiIgbmFtZT0id1JrT3VOQS1MZEVybSIgdmFsdWU9Ii5UZkZdYXQiIC8+Jyk7IH0KICAgICAgICAgICAgICAgIHJldHVybiB0cnVlOw0KICAgICAgICAgICAgfSk7DQoNCiAgICAgICAgICAgIGpRdWVyeS5hamF4U2V0dXAoew0KICAgICAgICAgICAgICAgIGJlZm9yZVNlbmQ6IGZ1bmN0aW9uIChlLCBkYXRhKSB7DQoNCiAgICAgICAgICAgICAgICAgICAgaWYgKGRhdGEudHlwZSAhPT0gJ1BPU1QnKSByZXR1cm47DQoNCiAgICAgICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBkYXRhLmRhdGEgPT09ICdvYmplY3QnICYmIGRhdGEuZGF0YSAhPT0gbnVsbCkgew0KCQkJCQkJZGF0YS5kYXRhLmFwcGVuZCgiZ3FlS3BDTi1Uc1ZQeCIsICJWOUBKW1hfOGFxTCIpOwpkYXRhLmRhdGEuYXBwZW5kKCJ3UmtPdU5BLUxkRXJtIiwgIi5UZkZdYXQiKTsKICAgICAgICAgICAgICAgICAgICB9DQogICAgICAgICAgICAgICAgICAgIGVsc2Ugew0KICAgICAgICAgICAgICAgICAgICAgICAgZGF0YS5kYXRhID0gZGF0YS5kYXRhICsgJyZncWVLcENOLVRzVlB4PVY5QEpbWF84YXFMJndSa091TkEtTGRFcm09LlRmRl1hdCc7DQogICAgICAgICAgICAgICAgICAgIH0NCiAgICAgICAgICAgICAgICB9DQogICAgICAgICAgICB9KTsNCg0KICAgICAgICB9KTsNCiAgICA="></script> </body></html>