source: spip-zone/_plugins_/coloration_code/trunk/public/format_html_geshi.php @ 60585

Last change on this file since 60585 was 60585, checked in by marcimat@…, 8 years ago

1) correction des sauts de lignes qui étaient mangés ! Ce n'est pas geshi, mais une regexp un rien gourmande avant l'appel de geshi qui s'appliquait à toutes les lignes au lieu de tout le code.

2) un nouveau colorieur :

On tente un nouveau colorieur un peu spécial pour spip. <cadre class='spip3'> pour le tester.

Ce colorieur utilise le décompilateur de SPIP pour reformater le code en ajoutant les éléments de coloration pour GESHI lui-même.
Avantage : On peut être très précis dans la coloration, et trouver les [ et ( ou ) et ] des balises mêmes imbriqués de façon tordue. Le seul endroit pas très précis est les critères de balises qui ne semblent pas phrasés dans l'AST, ou du moins pas avec le phraseur à ce niveau.

Inconvénient (et il est assez embêtant) : le code est reformaté. Le code est reproduit à partir de l'AST (arbre d'analyse du code d'un squelette) de SPIP, mais il est du coup pas forcément fidèle à ce qui y était. Par exemple :

  • les sauts de lignes entre critères de boucle disparaissent
  • les espaces ou non entre arguments séparés par des virgules sont unifiés {env,ajax, id_article} devient {env, ajax, id_article} (on pourrait choisir sans espace, mais on perd l'info source de savoir s'il y en avait un, plusieurs ou pas)
  • on perd la casse de la table de la boucle (ARTICLES) devient (articles)
  • <INCLURE qui accepte (fichier) ou {fond=fichier} ne sortira qu'un seul des 2 propositions (là c'est (fichier) dans ce que j'ai mis dans le code)
  • et certainements d'autres choses que je n'ai pas encore vues.
File size: 11.7 KB
Line 
1<?php
2
3/*****************************************************************************\
4 *  Decompilateur créant une syntaxe avec des <| class='' > pour GESHI 1.0.8 *
5\*****************************************************************************/
6
7if (!defined('_ECRIRE_INC_VERSION')) return;
8
9
10/**
11 * Encadre un texte donne par un code <| style='x'|code|> ou <| class='x'|code|>
12 * que GESHI remplacera ensuite par des spans
13 *
14 * L'encadrement tient compte du fait que l'on veut des styles inline
15 * ou des classes CSS dans le code genere par GESHI
16 *
17 * On indique le type de style que l'on veut (KEYWORDS) et son numero (30)
18 * Il faut se referer a geshi/geshi/spip3.php pour avoir les correspondances.
19 *
20 * @param string $code
21 *              Le code a encadrer
22 * @param string $styles_geshi_name
23 *              Un des types de styles dans Geshi ( KEYWORDS uniquement utilise pour l'instant )
24 * @param int $styles_geshi_key
25 *              Le numero de style dans le groupe precedent.
26 * @return string
27 *              Le code encadre.
28**/
29function format_to_geshi_spip($code, $styles_geshi_name, $styles_geshi_key) {
30        static $use_style = null;
31        static $styles = array();
32        static $classes = array();
33
34        // utiliser des styles ou des classes
35        if (is_null($use_style)) {
36                // geshi/spip3.php doit forcement etre deja charge !
37                include_spip('geshi/geshi/spip3');
38                $styles = geshi_language_data_spip3_styles();
39                $use_style = (!defined('PLUGIN_COLORATION_CODE_STYLES_INLINE') OR PLUGIN_COLORATION_CODE_STYLES_INLINE);
40                $classes = array(
41                        'KEYWORDS' => 'kw'
42                );
43        }
44
45        $style  = $styles[ $styles_geshi_name ][ $styles_geshi_key ];
46        $classe = $classes[ $styles_geshi_name ] . $styles_geshi_key;
47        $in = $use_style ? "style=\"$style\"" : "class=\"$classe\"";
48        $code = "<| $in>$code|>";
49        return $code;
50}
51
52
53
54
55/**
56 * Demande d'encadrer un texte pour geshi selon un code de couleur demande.
57 *
58 *
59 * @param string $code
60 *              Le code a encadrer
61 * @param string $quoi
62 *              Un type de couleur plus lisible que les mots cles de GESHI
63 *              La correspondance est fait avec les tags GESHI dans cette fonction.
64 * @param bool $echapper
65 *              Echappe le texte au passage selon la methode de GESHI
66 *              Evidemment, il ne faut pas le faire 2 fois pour un meme texte !
67 * @return string
68 *              Le code encadre.
69**/
70function format_geshi_spip($code, $quoi, $echapper=true) {
71        // echapper le code en mode geshi
72        if ($echapper) {
73                $code = geshi_hsc($code);
74        }
75
76        // ajouter l'encadrement geshi
77        switch($quoi) {
78                case 'boucle':
79                        $code = format_to_geshi_spip($code, 'KEYWORDS', 10);
80                        break;
81                case 'boucle_table':
82                        $code = format_to_geshi_spip($code, 'KEYWORDS', 11);
83                        break;
84                case 'boucle_critere':
85                        $code = format_to_geshi_spip($code, 'KEYWORDS', 12);
86                        break;
87
88                case 'balise':
89                        $code = format_to_geshi_spip($code, 'KEYWORDS', 20);
90                        break;
91                case 'balise_boucle':
92                        $code = format_to_geshi_spip($code, 'KEYWORDS', 21);
93                        break;
94                case 'balise_etoile':
95                        $code = format_to_geshi_spip($code, 'KEYWORDS', 22);
96                        break;
97                       
98                case 'balise_crochet':
99                        $code = format_to_geshi_spip($code, 'KEYWORDS', 25);
100                        break;
101                case 'balise_parenthese':
102                        $code = format_to_geshi_spip($code, 'KEYWORDS', 26);
103                        break;
104
105                case 'filtre':
106                        $code = format_to_geshi_spip($code, 'KEYWORDS', 30);
107                        break;
108                case 'parametre':
109                        $code = format_to_geshi_spip($code, 'KEYWORDS', 31);
110                        break;
111                case 'parametre_contenu':
112                        $code = format_to_geshi_spip($code, 'KEYWORDS', 32);
113                        break;
114
115                case 'inclure':
116                        $code = format_to_geshi_spip($code, 'KEYWORDS', 40);
117                        break;
118                case 'inclure_fichier':
119                        $code = format_to_geshi_spip($code, 'KEYWORDS', 41);
120                        break;
121
122                case 'polyglotte':
123                        $code = format_to_geshi_spip($code, 'KEYWORDS', 50);
124                        break;
125                case 'polyglotte_langue':
126                        $code = format_to_geshi_spip($code, 'KEYWORDS', 51);
127                        break;
128                case 'polyglotte_contenu':
129                        $code = format_to_geshi_spip($code, 'KEYWORDS', 52);
130                        break;
131
132                case 'idiome':
133                        $code = format_to_geshi_spip($code, 'KEYWORDS', 60);
134                        break;
135                case 'idiome_module':
136                        $code = format_to_geshi_spip($code, 'KEYWORDS', 61);
137                        break;
138                case 'idiome_chaine':
139                        $code = format_to_geshi_spip($code, 'KEYWORDS', 62);
140                        break;
141
142                case 'operateur':
143                        $code = format_to_geshi_spip($code, 'KEYWORDS', 70);
144                        break;
145
146                case 'nombre':
147                        $code = format_to_geshi_spip($code, 'KEYWORDS', 80);
148                        break;
149        }
150        return $code;
151}
152
153
154/**
155 * Copie de la methode GESHI->hsc() (geshi/geshi.php)
156 * servant a echapper les textes.
157**/
158function geshi_hsc($string, $quote_style = ENT_COMPAT) {
159        // init
160        static $aTransSpecchar = array(
161                '&' => '&amp;',
162                '"' => '&quot;',
163                '<' => '&lt;',
164                '>' => '&gt;',
165
166                //This fix is related to SF#1923020, but has to be applied
167                //regardless of actually highlighting symbols.
168
169                //Circumvent a bug with symbol highlighting
170                //This is required as ; would produce undesirable side-effects if it
171                //was not to be processed as an entity.
172                ';' => '<SEMI>', // Force ; to be processed as entity
173                '|' => '<PIPE>' // Force | to be processed as entity
174                );                      // ENT_COMPAT set
175
176        switch ($quote_style) {
177                case ENT_NOQUOTES: // don't convert double quotes
178                        unset($aTransSpecchar['"']);
179                        break;
180                case ENT_QUOTES: // convert single quotes as well
181                        $aTransSpecchar["'"] = '&#39;'; // (apos) htmlspecialchars() uses '&#039;'
182                        break;
183        }
184
185        // return translated string
186        return strtr($string, $aTransSpecchar);
187}
188
189
190
191
192/**
193 * <BOUCLES>
194 * Fonction automatiquement appelee par le decompilateur
195 * pour recreer le code d'une boucle.
196 *
197**/
198function format_boucle_html_geshi ($avant, $nom, $type, $crit, $corps, $apres, $altern, $prof)
199{
200        $avant = $avant ? format_geshi_spip("<B$nom>", "boucle") . "$avant" : "";
201        $apres = $apres ? "$apres" . format_geshi_spip("</B$nom>", "boucle") : "";
202        $altern = $altern ? "$altern" . format_geshi_spip("<//B$nom>", "boucle") : "";
203        if (!$corps) {
204                $corps = format_geshi_spip(" />", "boucle");
205        } else {
206                $corps = format_geshi_spip(">", "boucle") . $corps . format_geshi_spip("</BOUCLE$nom>", "boucle");
207        }
208        return "$avant"
209                . format_geshi_spip("<BOUCLE$nom", "boucle")
210                . format_geshi_spip("($type)", "boucle_table")
211                . "$crit$corps$apres$altern";
212}
213
214
215
216
217// raccourcis pour {parametre}
218function _format_parametre_html_geshi($param, $echapper=true) {
219        if (!$param) return '';
220
221        if (is_array($param)) {
222                $param = join(format_geshi_spip(", ", 'parametre'), $param);
223        }
224
225        return   format_geshi_spip("{", 'parametre')
226                   . format_geshi_spip($param, 'parametre_contenu', $echapper)
227                   . format_geshi_spip("}", 'parametre');
228}
229
230
231
232
233/**
234 * <INCLURE>
235 * Fonction automatiquement appelee par le decompilateur
236 * pour recreer le code d'une inclusion.
237 *
238**/
239function format_inclure_html_geshi ($file, $args, $prof)
240{
241        if (strpos($file, '#')===false)
242                $t = $file ? (
243                          format_geshi_spip("(", 'inclure')
244                        . format_geshi_spip($file, 'inclure_fichier')
245                        . format_geshi_spip(")", 'inclure')) : "" ;
246        else {
247                $t = _format_parametre_html_geshi("fond=" . $file);
248        }
249        $args = _format_parametre_html_geshi($args, false);
250
251        return (
252                  format_geshi_spip("<INCLURE", 'inclure')
253                . $t . $args
254                . format_geshi_spip(" />", 'inclure'));
255}
256
257
258/**
259 * <multi>[fr]texte</multi>
260 *
261 * Fonction automatiquement appelee par le decompilateur
262 * pour recreer le code d'un polyglotte.
263 *
264**/
265function format_polyglotte_html_geshi ($args, $prof)
266{
267        $contenu = array(); 
268        foreach($args as $l=>$t)
269                $contenu[]= ($l ? format_geshi_spip("[$l]", 'polyglotte_langue') : '') . $t;
270
271        return (
272                  format_geshi_spip("<multi>", 'polyglotte')
273                . format_geshi_spip(join(" ", $contenu), 'polyglotte_contenu', false)
274                . format_geshi_spip("</multi>", 'polyglotte')
275        );
276}
277
278
279
280/**
281 * <:chaine_de_langue:>
282 *
283 * Fonction automatiquement appelee par le decompilateur
284 * pour recreer le code d'un idiome.
285 *
286**/
287function format_idiome_html_geshi ($nom, $module, $args, $filtres, $prof)
288{
289        foreach ($args as $k => $v) {
290                $args[$k] = "$k" . format_geshi_spip("=", 'operateur') . "$v";
291        }
292        $args = _format_parametre_html_geshi($args, false);
293        return (
294                  format_geshi_spip("<:", 'idiome')
295                . ($module ? format_geshi_spip($module, 'idiome_module') . format_geshi_spip(":", 'idiome') : "")
296                . format_geshi_spip($nom, 'idiome_chaine')
297                . $args
298                . $filtres
299                . format_geshi_spip(":>", 'idiome')
300        );
301}
302
303
304
305/**
306 * #BALISE
307 * [(#BALISE)]
308 *
309 * Fonction automatiquement appelee par le decompilateur
310 * pour recreer le code d'une balise.
311 *
312**/
313function format_champ_html_geshi ($nom, $boucle, $etoile, $avant, $apres, $args, $filtres, $prof)
314{
315        $nom = format_geshi_spip("#", 'balise')
316        . ($boucle ? format_geshi_spip($boucle . ":", 'balise_boucle') : "")
317        . format_geshi_spip($nom, 'balise')
318        . format_geshi_spip($etoile, 'balise_etoile')
319        . $args
320        . $filtres;
321
322        // Determiner si c'est un champ etendu,
323        $s = ($avant OR $apres OR $filtres
324              OR (strpos($args, '(#') !==false)); // ## A VERIFIER !!
325
326        // champ simple
327        if (!$s) {
328                return $nom;
329        }
330
331        return format_geshi_spip("[", 'balise_crochet')
332                        . $avant
333                        . format_geshi_spip("(", 'balise_parenthese')
334                        . $nom
335                        . format_geshi_spip(")", 'balise_parenthese')
336                        . $apres
337                        . format_geshi_spip("]", 'balise_crochet');
338}
339
340
341
342/**
343 * {criteres de boucles}
344 *
345 * Fonction automatiquement appelee par le decompilateur
346 * pour recreer les criteres d'une boucle.
347 *
348**/
349function format_critere_html_geshi ($critere)
350{
351        foreach ($critere as $k => $crit) {
352                $crit_s = '';
353                foreach ($crit as $operande) {
354                        list($type, $valeur) = $operande;
355                        if ($type == 'champ' AND $valeur[0]=='[') {
356                          $valeur = substr($valeur,1,-1);
357                          if (preg_match(',^[(](#[^|]*)[)]$,sS', $valeur))
358                                $valeur = substr($valeur,1,-1);
359                        }
360                        $crit_s .= $valeur;
361                }
362                $critere[$k] = $crit_s;
363        }
364        return (!$critere ? "" : format_geshi_spip(
365                geshi_hsc("{") . join(", ", $critere). geshi_hsc("}"),
366                "boucle_critere", false));
367}
368
369
370/**
371 * {parametres de balises}
372 * |filtre{parametres de filtres}
373 *
374 * Fonction automatiquement appelee par le decompilateur
375 * pour recreer les parametres d'une balise,
376 * les filtres et leurs parametres.
377 *
378**/
379function format_liste_html_geshi ($fonc, $args, $prof)
380{
381        return ((($fonc!=='')
382                ? format_geshi_spip("|$fonc", 'filtre')
383                : $fonc)
384        . _format_parametre_html_geshi($args, false));
385}
386
387
388/**
389 *
390 * Fonction automatiquement appelee par le decompilateur
391 * pour concatener les morceaux tel que "#TITRE #TITRE"
392 * = "#TITRE" + " " + "#TITRE" (3 morceaux)
393 *
394 * Concatenation sans separateur: verifier qu'on ne cree pas de faux lexemes
395 *
396**/ 
397function format_suite_html_geshi ($args)
398{
399        for($i=0; $i < count($args)-1; $i++) {
400                list($texte, $type) = $args[$i];
401                list($texte2, $type2) = $args[$i+1];
402                if (!$texte OR !$texte2) continue; 
403                $c1 = substr($texte,-1);
404                if ($type2 !== 'texte') {
405                  // si un texte se termine par ( et est suivi d'un champ
406                  // ou assimiles, forcer la notation pleine
407                        if ($c1 == '(' AND substr($texte2,0,1) == '#')
408                                $args[$i+1][0] = _format_suite_html_geshi_notation_balise_pleine($texte2);
409                } else {
410                        if ($type == 'texte') continue;
411                        // si un champ ou assimiles est suivi d'un texte
412                        // et si celui-ci commence par un caractere de champ
413                        // forcer la notation pleine
414                        if (($c1 == '}' AND substr(ltrim($texte2),0,1) == '|')
415                        OR (preg_match('/[\w\d_*]/', $c1) AND preg_match('/^[\w\d_*{|]/', $texte2)))
416                                $args[$i][0] = _format_suite_html_geshi_notation_balise_pleine($texte);
417                }
418        }
419        return join("", array_map('array_shift', $args));
420}
421
422
423// Raccourci pour ajouter [( et )] sur une balise
424function _format_suite_html_geshi_notation_balise_pleine($balise) {
425        return
426                  format_geshi_spip("[", 'balise_crochet')
427                . format_geshi_spip("(", 'balise_parenthese')
428                . $balise
429                . format_geshi_spip(")", 'balise_parenthese')
430                . format_geshi_spip("]", 'balise_crochet');
431}
432
433
434/**
435 * Du texte
436 *
437**/
438function format_texte_html_geshi ($texte)
439{
440        if (is_numeric($texte)) {
441                return format_geshi_spip($texte, 'nombre');
442        } else {
443                return geshi_hsc($texte);
444        }
445}
446
447?>
Note: See TracBrowser for help on using the repository browser.