Plugin de coloration syntaxique
La coloration syntaxique manquait sur Dotclear 2, je me suis donc lancé dans la réalisation d'un plugin remplissant cette fonction. A travers cette article, je vous propose de découvrir la création de plugin pour Dotclear 2.
Pour réaliser la coloration, nous utiliserons tout simplement GeShi, une classe qui remplit admirablement bien cette fonction. Il s'agit donc d'intégrer le travaille de cette classe à Dotclear sous la forme d'un plugin.
J'ai choisi de reprendre le nom de l'ancien plugin qui fournissait la coloration syntaxique ,SyntaxeHl pour syntaxe highlight je présume.
Un répertoire avec GeShi pour le plugin
La première étape, très simple, consiste à créer un répertoire pour accueillir les fichiers de votre plugin. Pour cela, il suffit de créer un sous répertoire dans le répertoire plugins de votre Dotclear. Nommons le par exemple syntaxehl. Il vous faudra ensuite télécharger la dernière version de GeShi. Décompressez l'archive que vous venez de récupérer dans le répertoire que vous venez de créer. Ainsi vous devez obtenir un nouveau répertoire /plugins/syntaxehl/geshi/. Dans ce répertoire, vous pouvez supprimer les répertoires contrib et doc qui ne nous serons pas utile.
Informations relatives au plugin
Nous allons maintenant définir les différentes informations relatives à notre plugin. Pour cela, vous devez créer un fichier _define.php dans le répertoire /plugins/syntaxehl/. Le contenu de ce fichier sera le suivant :
<?php $this->registerModule( /* Name */ "SyntaxeHl", /* Description*/ "Plugin de coloration syntaxique", /* Author */ "Votre Nom", /* Version */ '1', /* Permissions */ 'usage,contentadmin' ); ?>
Les commentaires accompagnant chacun des paramètres sont suffisamment clair pour comprendre de quoi il s'agit. Nous ne nous arrêterons que sur le champ concernant les permissions. Il s'agit ici de définir quel type d'utilisateur peut activer le plugin. Dans cet exemple, nous avons choisit d'autoriser tous les utilisateurs mais on aurait également pu se limiter aux administrateurs en indiquant seulement admin.
Enregistrez les modifications puis rendez vous sur la page listant les plugin installés sur votre blog. Vous constaterez avec joie que le plugin que vous venez de créer apparaît bien dans la liste. Pour l'instant, ce plugin est totalement inutile puisqu'il ne fait absolument rien. Nous allons donc lui ajouter ses fonctionnalités.
Intercepter le code à mettre en forme
Pour mettre en forme le code inséré dans un billet, j'ai choisi d'exploiter la classe wiki2xhtml qui est employée, comme son nom l'indique, pour transformer la syntaxe Wiki d'un billet en (X)HTML.Ce choix peut être discutable puisqu'il ne permet pas de mettre en forme du code inséré dans un billet écrit directement en HTML.Cela-dit, je part du principe qu'un billet écrit en HTML directement ne devrait pas faire l'objet de modifications par un plugin puisqu'en principe il est déjà écrit dans sa version finale.
Pour mettre en forme les codes sources, nous allons exploiter une des fonctionnalités offertes par wiki2xhtml : les macros. Pour cela, nous utiliserons la fonction registerFunction de wiki2xhtml qui attend deux paramètres : le type de fonction que l'on souhaite enregistrer et la fonction en question. Pour le type, on indiquera simplement macro:nom_de_la_macro. Le fait d'enregistrer une fonction en tant que macro va déclencher l'appel à notre fonction lorsque la classe rencontrera dans le contenu du billet le texte suivant :
///nom_de_la_macro du texte ///
Ici, notre fonction recevra du texte en paramètre, il nous suffira alors d'effectuer toutes les modifications souhaitées puis de retourner la version modifié du texte pour qu'elle remplace l'originale.
Enregistrer notre macro pour wiki2xhtml
Nous n'avons pour le moment qu'un bout de la solution finale. En effet, même si on sait comment procéder pour obtenir le code à mettre en forme, on ne sait pas vraiment comment procéder pour enregistrer notre fonction auprès de la classe wiki2xhtml aux bons moments.
Le système des behavior
Depuis la version 2, Dotclear intègre un tout nouveau système : les behavior. Terme qui peut être traduit littéralement par comportement. C'est un système très simple à utiliser qui propose une gestion événementielle. En fait, un plugin peut enregistrer une fonction pour tel ou tel événement. Lorsque cet événement se produit, Dotclear appel la ou les fonctions qui ont été enregistrées pour cet événement. En plus, ces fonctions recevront un certain nombre de paramètres différents en fonction du behavior concerné.
Parmi la liste des behavior diponibles, on trouve coreWikiPostInit qui est appelé lors de l'initialisation de la classe wiki2xhtml. La fonction qui sera enregistrée pour cette événement recevra une référence vers l'instance de wiki2xhtml en paramètre. Il sera donc très facile d'y enregistrer notre macro.
Quelques fichiers
Nous avons toutes les solutions en main pour la création de notre plugin. Nous allons maintenant pouvoir entamer le codage. Il faudra bien sur placer notre code dans certains fichiers. Comme vous pouvez l'imaginer, le fait de créer un fichier nommé n'importe comment ne sera pas forcément pris en compte par Dotclear. Le nommage est important pour le bon fonctionnement de notre plugin.
Ce qui va déterminer le nom du fichier que nous allons utiliser, c'est la partie de Dotclear dans laquelle on souhaite agir, la partie publique ou la partie administration. Pour agir sur la partie publique, on créera un fichier nommé _public.php ou alors un fichier _admin.php pour agir dans la partie administration.
Pour notre pugin, c'est dans la partie admin que nous voulons agir. En effet, les billets rédigés en syntaxe Wiki sont transformés en (X)HTML dans la partie administration. Nous allons donc créer un fichier _admin.php dans le répertoire /plugins/syntaxehl/.
Codage du plugin
Il ne nous reste maintenant plus qu'à coder notre plugin. Placez le code suivant dans le fichier _admin.php que nous venons de créer.
<?php // Protège contre les accès directes au fichier if (!defined('DC_CONTEXT_ADMIN')) exit; // Require façon Dotclear require(dirname(__FILE__).'/geshi/geshi.php'); // On enregistre notre behavior $core->addBehavior('coreInitWikiPost',array('syntaxeHl','registerFunc')); class syntaxeHl { // Fonction correspondant à notre behavior public static function registerFunc(&$wiki2xhtml) { // On lit de répertoire de GeShi pour connaître // la liste des langages diponibles $dir = dirname(__FILE__).'/geshi/geshi/'; $od = opendir($dir); while($f = readdir($od)) { // Si c'est bien un fichier portant l'extension .php if(is_file($dir.$f) && substr($f,-4,4)=='.php') { // On enregistre une nouvelle macro pour ce langage $lang = str_replace('.php','',$f); $wiki2xhtml->registerFunction('macro:['.$lang.']',array('syntaxeHl','parse')); } } } // Fonction appelée par Wiki2Xhtml public static function parse($text,$args) { // On supprime les caractères blancs en // en début et fin de chaîne (optionnel) $text = trim($text); // Création d'une instance de GeShi $geshi =& new GeSHi($text,$args); // On désactive les liens sur les mots clés (optionnel) $geshi->enable_keyword_links(false); // On retourne le code mis en forme, coloré return $geshi->parse_code(); } } ?>
Ayant déjà bien expliqué les solutions employées ci-dessus, je ne m'attarderais pas sur ce code. Vous pouvez consulter la documentation de Dotclear pour en savoir plus sur les méthodes utilisées.
Notez simplement que l'on utilise pas directement le nom du langage pour nommer nos macro, mais qu'on le place entre crochets ([ et ]). Il y a deux raisons à cela, d'une part le plugin qui assurait la coloration syntaxique pour Dotclear 1 utilisait lui aussi les crochets (rétro compatibilité) et d'autre part cela permet de ne pas interférer avec d'autres macros comme html par exemple qui permet d'insérer du code html dans un billet lorsqu'on est en syntaxe Wiki.
Un test ?
Si vous avez correctement suivit cet article, votre plugin est maintenant fonctionnel. Vous pouvez le tester en créant un nouveau billet et en insérant le code suivant (en syntaxe Wiki):
///[php] <?php echo 'Hello world!'; ?> ///
et vous obtiendrez normalement le résultat suivant :
<?php echo 'Hello world!'; ?>
Vous remarquerez peut-être que ce plugin n'est pas rétro actif, c'est à dire que les anciens billets contenant du code sources ne seront pas colorés. Pour chacun d'entre eux, il vous faudra les éditer et enregistrer les modifications.
Packager votre plugin
Maintenant que votre plugin fonctionne, il pourrait être intéressant de le distribuer. Le meilleur moyen pour cela est de créer un package. Le moyen le plus simple est d'utiliser le plugin Packager dont c'est la seule et unique fonction.
Version finale
Pour ceux qui souhaitent simplement installer ce plugin sur leur blog, vous pouvez consulter le dépôt de plugin de Code-Web.org où vous trouverez les paquets directement installables sur Dotclear. Si vous avez des questions qui concernent ce plugin, rendez-vous sur le billet traitant de la dernière version disponible.



Bonjour, pour information il existait déjà un
Moe | lundi 31 mars 2008 | 16:22Bonjour,
pour information il existait déjà un plugin Geshi pour Dotclear 2 : http://blog.clashdesign.net/index.p...
Mais celui-ci était un peu à l'abandon et il avait un défaut : il coloriait le code source lors de l'affichage et non lors de l'enregistrement du billet. Pas terrible niveau performance ... Ton plugin comble donc un vide, félicitations.
En effet je suis passé à côté, mais, comme tu l'as
Thierry | lundi 31 mars 2008 | 16:48En effet je suis passé à côté, mais, comme tu l'as dit, niveau performances on a vu mieux.
Quoiqu'il en soit, je compte bien maintenir ce plugin parce que je tourne avec des Dotclear à jour et que j'en aurais toujours besoin!
Me revoilà avec une requête : est-ce qu'il est
Moe | lundi 31 mars 2008 | 17:06Me revoilà avec une requête : est-ce qu'il est possible d'avoir un <pre> avec la classe highlight ou code ou autre chose qui permette de distinguer ?
Actuellement le code est sous la forme <pre class="php"> donc je le style comme ça :
/* syntaxeHl */
pre.php, pre.html4strict {
margin-bottom:1em;
padding:0.25em;
display:block;
width:100%;
overflow:auto;
text-align:left;
white-space:nowrap;
background-color:White;
}
Du coup il faut ajouter une règle pour chaque langage, avec <pre class="php code"> on pourrait styler les blocs avec pre.code {}.
Ça fait justement parti des choses que je pensais
Thierry | lundi 31 mars 2008 | 17:15Ça fait justement parti des choses que je pensais ajouter dans une future version. En fait toutes les options qui concernent GeShi peuvent être ajouté avant la ligne où en renvoit le code parsé.
Donc pour avoir une seule class pour tous les langages c'est simple :
$geshi->set_overall_class('ma-class');
http://qbnz.com/highlighter/geshi-d...
Edit : Tiens maintenant que j'y pense, et pour reprendre ton idée, à mon avis on doit aussi pouvoir ajouter la ligne suivante (avant le return) :
$geshi->set_overall_class($args.' code');
comme ça on obtiendrait bien les deux classes, l'une spécifique au langage et l'autre globale.
Bonjour Bravo pour votre plugin ! Est-ce possible
Lio | dimanche 6 avril 2008 | 20:51Bonjour
Bravo pour votre plugin !
Est-ce possible d'obtenir la coloration mais avec le format du texte en xhtml ?
J'aimerais ne pas utiliser le mode wiki avec l'éditeur de texte.
Merci
Lio
Bonjour,je pensais intégrer la coloration
Thierry | lundi 7 avril 2008 | 11:43Bonjour,
je pensais intégrer la coloration syntaxique du code dans un billet rédigé en XHTML. Cela-dit, ça n'est pas vraiment possible pour des raisons techniques bien sûr.
En fait, le soucis c'est que Dotclear (un des élément qui traite le post_content en tout cas) modifie le contenu d'un billet. Par exemple, du code entre les balises <pre> et </pre>. Les retours à la ligne sont transformés en <br />. Je crois que c'est l'éditeur qui rajoute cela, en mode WYSIWYG. Quoi qu'il en soit, c'est forcément problématique puisqu'à la coloration ces <br /> vont ressortir (ça fait bien au milieu de code en C++).
Et puis je reviens également sur ce que j'ai dis dans ce billet, un billet publié en HTML ne devrait pas être modifié par la suite. En principe c'est déjà sa version finale et on ne devrait donc pas le modifier. C'est peut être un point de vue discutable mais quoi que vous en pensiez je n'ai pas la solution pour mettre en place ce vous demandez!
Alors ''Longue vie à la syntaxe Wiki!'' et servez-vous en!C'est génial ! Merci
Lio | lundi 7 avril 2008 | 13:45C'est génial !
Merci
Merci pour ce joli plugin, ça marche très bien
Oum | vendredi 11 avril 2008 | 13:25Merci pour ce joli plugin, ça marche très bien pour la partie publique, néanmoins depuis que je l'ai installé j'ai de vilaines erreurs php dans l'admin de DC.
J'utilise Dotclear 2 beta7.3, toujours la dernière svn, sur OVH mutualisé, Php 5.2.5, MySQL v 5.0.44
Il y a cette erreur en permanence :
Strict Standards: Assigning the return value of new by reference is deprecated in /xxx/xxx/plugins/syntaxehl/_admin.php on line 30
Warning: Cannot modify header information - headers already sent by (output started at /xxx/xxx/plugins/syntaxehl/_admin.php:30) in /xxx/xxx/inc/admin/lib.dc.page.php on line 90
et celle-ci quand je valide toutes sortes de choses (enregistrement d'un billet, mise à jour des widgets, etc...) :
Strict Standards: Assigning the return value of new by reference is deprecated in /xxx/xxx/plugins/syntaxehl/_admin.php on line 30
Warning: Cannot modify header information - headers already sent by (output started at /xxx/xxx/plugins/syntaxehl/_admin.php:30) in /xxx/xxx/inc/clearbricks/common/lib.http.php on line 98
J'ai besoin d'un petit coup de main, merci
En effet une petit erreur de programmation s'est
Thierry | samedi 12 avril 2008 | 01:19En effet une petit erreur de programmation s'est glissée dans le fichier _admin.php.
Voici une version corrigée (1.0.1) : http://www.nostalgeek.org/plugin-dc...
En attendant que je mette à jour la version dispo sur dotaddict.
Pour l'installation de cette nouvelle version, mieux vaut supprimer l'ancienne puis installer celle-ci.
Et puis me dire aussi si ça fonctionne mieux!
les dernières svn de DC2b7 n'ouvrent pas les
Oum | samedi 12 avril 2008 | 13:03les dernières svn de DC2b7 n'ouvrent pas les pkg.gz, peux-tu mettre un zip à disposition s'il te plaît ? (le plugin packager est à jour pour créer des zip en plus ^^ )
Je l'ai mis à dispo également, suffit de changer
Thierry | samedi 12 avril 2008 | 18:54Je l'ai mis à dispo également, suffit de changer l'extension
http://www.nostalgeek.org/plugin-dc...
Ou pour la liste de tous les packages dispo :
http://www.nostalgeek.org/plugin-dc...
ça marche parfaitement bien, merci
Oum | samedi 12 avril 2008 | 20:44ça marche parfaitement bien, merci