Du joli code dans les articles

Ceci est une ARCHIVE, peut-être périmée. Vérifiez bien les compatibilités !

Ou comment avoir du code coloré dans spip grâce aux nouveaux points d’entrée dans inc_texte. une démo ici.

Quand on insère du code dans un article avec les balises <code>, on peut avoir une présentation différente en ajustant le style css. Pourtant, pour des gros morceaux de code, ça fait vite mal aux yeux.

screenshot
un screenshot de la version complexe. On y voit du code php, java et html coloré.

Voici une utilisation des points d’entrée dans inc_texte.php3 pour faire du « syntax highlighting » du code inséré dans les articles. Ainsi, comme dans tout bon éditeur de code, on peut voir les mots clefs, nom de fonctions etc... dans des couleurs différentes. On a ainsi une lecture plus rapide.

-  La version « simple » utilise une fonction de php existante pour colorer du code php compris entre des balises <ccode> et </ccode>.

-  La version plus complexe nécessite l’installation d’un module php externe disponible ici ou en version améliorée par mes petites mains ici qui permet de colorer n’importe quel langage [1].

les codes spécifiques se trouvent après l’explication.

Méthode

A partir de la version 1.7.1 de SPIP deux points d’entrée dans inc_texte.php3 sont fournis [2]. Ce fichier est responsable du traitement des raccourcis typographiques que les rédacteurs utilisent quand ils écrivent un article (gras, italique, balises code, etc...) :
-  avant_propre permet de traiter le texte avant que SPIP ne le traite lui même et donc d’intercepter des raccourcis qui seraient modifiés par SPIP autrement.
-  apres_propre permet de traiter le texte après tous les traitements de SPIP.

Vous pouvez donc implémenter, dans votre propre fichier ecrire/mes_options.php des pré/post-traitements pour des nouveaux raccourcis. Voir par exemple cet article, ou ce wiki et cette explication de Fil.

Bon, je vous ment un tout petit peu. Spip, avant d’appeler avant_propre, va échapper (les enlever du texte) certaines parties du texte qui pourraient être sensibles. par exemple le code entre balises <code>. Une fois tout le traitement typographique fait (et donc après apres_propre), Spip réinsère le texte échappé au bon endroit. On verra ce que cela implique dans quelques instants.

La méthode que l’on va utilisée est la même : échapper le code entre les balises <ccode> </ccode> pour le réinsérer tout à la fin avec les informations de couleurs.

Version Simple

Ici, je dit version simple, mais elle implique la même utilisation des points d’entrée dans inc_texte. La seule différence est la technique de coloration du code, qui implique une toute petite différence dans le code de ecrire/mes_options.php3.

Coloration

PHP fournie, avec la fonction highlight_string un moyen de colorer du code. Il y a deux conditions :
-  il doit s’agir de code PHP [3],
-  le code doit être compris entre les balises php standards : <?php et ?> .

prétraitement du texte

dans ecrire/mes_options.php3

function avant_colorer_code($texte) {
   global $code_a_colorer;


   $regexp_echap = "(<ccode>(([^<]|<[^/]|</[^c]|</c[^c]|</cc[^o]|</cco[^d]|</ccod[^e]|</ccode[^>])*)<\/ccode>)";

   $colo_code_ech=0;
   //on échappe tout ce qui se trouve entre <ccode> et </ccode>
   while (preg_match($regexp_echap, $texte, $regs)) {
      //on stoque le code à colorer pour plus tard.
      $code_a_colorer[$colo_code_ech] = $regs[1];
      $pos = strpos($texte, $regs[0]);
     //on le remplace par une balise <@@colorercode_X@@>
     $texte = substr($texte,0,$pos).
                 "<@@colorercode_$colo_code_ech@@>".
                 substr($texte,$pos+strlen($regs[0]));
      $colo_code_ech++;
   }
   return $texte;
}

function avant_propre($texte) {
   $new_texte = avant_colorer_code($texte);
   return $new_texte;
}

}

Ce code permet d’échapper le code qui se trouve entre nos deux balises. On remplace cette partie du texte par une balise spéciale [4] <@@colorercode_..> qui comprend un index dans le tableau dans lequel on stoque temporairement le code escamoté.

post traitement

dans ecrire/mes_options.php3

function apres_colorer_code($texte) {
   global $code_a_colorer;

   //on remplace toutes les balises qu'on a insérées par le code coloré.
   while (ereg('<@@colorercode_([0-9]+)@@>', $texte, $regs)) {
      //on récupère l'indexe du code dans le tableau.
      $lenum = $regs[1];
      $lecode = highlight_string("<?php".$code_a_colorer[$lenum]."?>",true);

      $pos = strpos($texte, $regs[0]);
      //on enlève les balises que highlight a ajouté
      $lecode = preg_replace("/(<code>|<\/code>)/","",$lecode);

      //on insère une nouvelle balise avec un style css.
      $texte = substr($texte, 0, $pos).
                    "<tt><div class='spip_ccode' dir='ltr'>". 
                    $lecode .
                    "</div></tt>". 
                   substr($texte, $pos + strlen($regs[0]));
   }
   //on corrige les balises d'échappement de spip qui ont été transformée par highlight.
   $find = "/&lt;@@SPIP_(SOURCEPROPRE|SOURCETYPO)([0-9]+)@@&gt;/";
   $replace = "<@@SPIP_\\1\\2@@>";
   $texte = preg_replace($find,$replace,$texte);

   return $texte;
}

function apres_propre($texte) {
   $new_texte = apres_colorer_code($texte);
   return $new_texte;
}

Cette fonction est donc appelée à la fin du traitement. On y remplace toutes les balises d’échappement (<@@colorercode_..>) par le code coloré.

On récupère l’index dans le tableau, puis on appelle la fonction highlight sur le code. Il faut ensuite lui faire un petit traitement :
-  on ajoute le code de formatage, qui met le code coloré dans un DIV de classe spip_ccode [5],
-  on enléve les balises code (html cette fois, pas spip) ajoutées par la fonction highlight,

La dernière étape nécessite quelques explication. Comme mentionné plus tôt, SPIP échappe un certain nombre de chose avant d’appeler avant_propre, et le remplace par des balises spéciales. Si dans notre code, spip a trouvé quelque chose à échappé (par exemple certain code html au milieu du code php), alors il le fera [6].

Mais les balises spéciales spip sont ensuite traitées par l’highlighter, ainsi les < et > sont remplacés par &lt; et &gt;. On doit donc les retransformer pour avoir des < et >.

Cela pose un deuxième problème, prenons un exemple : Si votre code php contient une balise d’image

$reg = "/<img src='IMG\/([^']+)'.+alt=(.+) title=([^>]+)>/";

,
alors spip va l’échapper :
$reg = "<@@SPIPSOURCEPROPREX@@>";
et le remettre en place après votre traitement du code php. Ainsi la chaine de caractéres ne sera pas colorée, mais prise comme une vraie balise html [7]. il faut donc mettre tout le code html qui se trouve dans votre code php entre balises spip <code>, sous peine d’avoir de mauvaises surprises. Ainsi notre exemple devra être écrit :
$reg = "/<code><img src='IMG\/([^']+)'.+alt=(.+) title=([^>]+)></code>/";

il faut ensuite faire attention au style. Insérez ce code [8] :

dans habillage.css par exemple

.spip_ccode .spip_code{

border: 0px;
padding: 0px;
margin-left: 0px;
background: transparent;

}

dans votre fichier css [9], pour annuler le style .spip_code à l’intérieur d’un bloc .spip_ccode.

Méthode « complexe »

Ici je décris l’installation du code Beautifier et donne un code adapté d’avant_propre et apres_propre. La technique utilisée dans ces deux méthode n’étant pas différente, je ne la redécris pas.

Beautifier

Je vous conseille d’utiliser l’adaptation du beautifier disponible ici [10].

Le beautifier est simple à installer :
- télécharger les fichiers de base,
- télécharger aussi les fichiers de formatages pour les langages qui vous intéressent.
- décompresser les packages où vous voulez dans votre repertoire spip (par exemple dans ecrire/)
- adapté le chemin dans le fichier Beautifier/Init.php
- adapté le chemin dans la fonction décrite ici.

On va donc appeler depuis spip la fonction du beautifier de cette façon :

dans ecrire/mes_options.php3

function my_highlight_string($texte, $file='php3') {
//ajuster le chemin ici
  $m8_path = '/users/mortimer/ecrire/beautifier';
  require_once "$m8_path/Beautifier/Init.php";
  $class_name = "HFile_$file";
  require_once "$m8_path/HFile/$class_name.php";
  require_once "$m8_path/Output/Output_css.php";
  $highlighter = new Core(new $class_name(), new Output_css());
  $lecode = nl2br($highlighter->highlight_text($texte));
  $lecode = ereg_replace("\t", "&nbsp; &nbsp; &nbsp; &nbsp; ", $lecode);
  $lecode = ereg_replace("  ", " &nbsp;", $lecode);
  return $lecode;
}

elle prend deux paramètre : le code à colorer, et le type du fichier (langage).

il vous faudra aussi ajouter ces styles à votre css [9] [11] :

dans habillage.css par exemple

.beautifier_linecomment {
	color: green;
}

.beautifier_blockcomment {
	color: green;
}

.beautifier_prepro {
	color: lightgreen;
}

.beautifier_select {
	color: red;
 font-weight: bold;
}

.beautifier_quote {
	color: coral;
}

.beautifier_1 {
	color: blue;
}

.beautifier_2 {
	color: cornflowerblue;
}

.beautifier_3 {
	color: #e5b23b;
}

.beautifier_4 {
	color: gray;
}

code de traitement du raccourcis

avant_propre et apres_propre ne changent pas beaucoup ici, on les adapte juste pour utiliser des balises au format
<ccode(nom_du_langage)> code à colorer </ccode>

le nom du langage etant le nom dans le fichier HFile, par exemple pour du php3, on a un fichier HFile_php3.php, on donnera donc le nom de langage php3.

dans ecrire/mes_options.php3

function avant_colorer_code($texte) {
   global $code_a_colorer;

   $regexp_echap = "(<ccode\\(([^\\)]+)\\)>(([^<]|<[^/]|</[^c]|</c[^c]|</cc[^o]|</cco[^d]|</ccod[^e]|</ccode[^>])*)<\/ccode>)";

   $colo_code_ech=0;
   while (preg_match($regexp_echap, $texte, $regs)) {
      $code_a_colorer[$colo_code_ech] = $regs[2];
      $langage = $regs[1];
      $pos = strpos($texte, $regs[0]);
      $texte = substr($texte,0,$pos).
                  "<@@colorercode_".
                  $langage.
                  "_$colo_code_ech@@>"
                  .substr($texte,$pos+strlen($regs[0]));
      $colo_code_ech++;
   }
   return $texte;
}

function apres_colorer_code($texte) {
   global $code_a_colorer;

   while (ereg('<@@colorercode_([^_]+)_([0-9]+)@@>', $texte, $regs)) {
      $lenum = $regs[2];
      $lecode = my_highlight_string($code_a_colorer[$lenum],$regs[1]);

      $pos = strpos($texte, $regs[0]);

      $texte = substr($texte, 0, $pos).
                    "<tt><div class='spip_ccode' dir='ltr'>". 
                    $lecode.
                    "</div></tt>".
                    substr($texte, $pos + strlen($regs[0]));
   }

   $find = "/&lt;@@SPIP_(SOURCEPROPRE|SOURCETYPO)([0-9]+)@@&gt;/";
   $replace = "<@@SPIP_\\1\\2@@>";
   $texte = preg_replace($find,$replace,$texte);

   return $texte;
}

Notes

[1Plus de 200 fichiers de configuration sont déjà disponibles.

[2voir l’annonce dans les archives de spip-core

[3du code perl ou C passe à peut pret, vue la similitude.

[4cette technique est justement celle utilisée par SPIP

[5à ajouter à votre fichier css

[6SPIP échappe le texte avec des expressions régulières. Il échappe tout ce qui se trouve entre balise html, code, cadre et poesie. Mais aussi tout code html qui pourrait être mal interprété par le moteur de typographie, soit, tout code html qui ressemble à <[a-zA-Z!][^<>!':;\?]*[!':;\?][^<>]*>

[7i.e. le navigateur cherchera à afficher une image appelée $source.

[8adapté à votre style

[9habillage.css par exemple

[10la condition d’utilisation est de mettre un lien sur votre site vers les sources.

[11et à ecrire/spip_style.php si vous voulez voir la tête du texte dans la partie privée du site.

Discussion

Aucune discussion

Ajouter un commentaire

Avant de faire part d’un problème sur un plugin X, merci de lire ce qui suit :

  • Désactiver tous les plugins que vous ne voulez pas tester afin de vous assurer que le bug vient bien du plugin X. Cela vous évitera d’écrire sur le forum d’une contribution qui n’est finalement pas en cause.
  • Cherchez et notez les numéros de version de tout ce qui est en place au moment du test :
    • version de SPIP, en bas de la partie privée
    • version du plugin testé et des éventuels plugins nécessités
    • version de PHP (exec=info en partie privée)
    • version de MySQL / SQLite
  • Si votre problème concerne la partie publique de votre site, donnez une URL où le bug est visible, pour que les gens puissent voir par eux-mêmes.
  • En cas de page blanche, merci d’activer l’affichage des erreurs, et d’indiquer ensuite l’erreur qui apparaît.

Merci d’avance pour les personnes qui vous aideront !

Par ailleurs, n’oubliez pas que les contributeurs et contributrices ont une vie en dehors de SPIP.

Qui êtes-vous ?
[Se connecter]

Pour afficher votre trombine avec votre message, enregistrez-la d’abord sur gravatar.com (gratuit et indolore) et n’oubliez pas d’indiquer votre adresse e-mail ici.

Ajoutez votre commentaire ici

Ce champ accepte les raccourcis SPIP {{gras}} {italique} -*liste [texte->url] <quote> <code> et le code HTML <q> <del> <ins>. Pour créer des paragraphes, laissez simplement des lignes vides.

Ajouter un document

Suivre les commentaires : RSS 2.0 | Atom