source: spip-zone/_plugins_/coloration_code/trunk/coloration_code_fonctions.php @ 119826

Last change on this file since 119826 was 119826, checked in by nicod@…, 2 years ago

Corriger un bug de coloration_code + precode : les blocs de code ne contenant qu'une seule ligne n'étaient pas traités par precode

File size: 7.2 KB
Line 
1<?php
2/**
3 * Plugin coloration code
4 * Fonctions spécifiques au plugin
5 *
6 * @package SPIP\Coloration_code\Fonctions
7 */
8
9if (!defined('_ECRIRE_INC_VERSION')) {
10        return;
11}
12
13include_spip('inc/plugin');
14
15// pour interdire globalement et optionnellement le téléchargement associé
16if (!defined('PLUGIN_COLORATION_CODE_TELECHARGE')) {
17        define('PLUGIN_COLORATION_CODE_TELECHARGE', true);
18}
19
20// pour utiliser des styles inline (ou des classes css)
21if (!defined('PLUGIN_COLORATION_CODE_STYLES_INLINE')) {
22        define('PLUGIN_COLORATION_CODE_STYLES_INLINE', true); // false mettra des class et une css associe
23}
24
25// pour mettre des classes css MAIS ne mettre aucun style correspondant
26// cela suppose donc qu'une CSS externe a ce plugin s'occupe de les styler
27if (!defined('PLUGIN_COLORATION_CODE_SANS_STYLES')) {
28        define('PLUGIN_COLORATION_CODE_SANS_STYLES', false); // true mettra des class mais pas de css associe
29}
30
31// pouvoir definir la taille des tablations (defaut de geshi : 8)
32// define('PLUGIN_COLORATION_CODE_TAB_WIDTH', 4);
33
34// Liens externes sur les mots cles de langage (defaut de geshi : true)
35if (!defined('PLUGIN_COLORATION_CODE_LIENS_LANGAGE')) {
36        define('PLUGIN_COLORATION_CODE_LIENS_LANGAGE', true); // false pour les eviter
37}
38
39if (!defined('PLUGIN_COLORATION_CODE_COLORIEUR_SPIP')) {
40        define('PLUGIN_COLORATION_CODE_COLORIEUR_SPIP', 'spip');
41}
42
43function coloration_code_color($code, $language, $cadre = 'cadre', $englobant = 'div') {
44
45        // On ajoute une argument a la fonction pour permettre d'afficher du code dans des <span>
46        // plutot que dans un <div>. Par contre, cette option de span est a utiliser avec la balise <code>
47        // et pas <cadre> pour des raisons de validite et de presentation.
48        // En outre, le bouton telecharger n'est pas affiche.
49        if ($cadre == 'cadre') {
50                $englobant = 'div';
51        }
52        $balise_code = ($englobant == 'div' ? "div" : "code");
53
54        // conserver une version du code reçu avant nettoyage
55        $code_avant_nettoyage = $code;
56        // Supprime le premier et le dernier retour chariot
57        $code = preg_replace("/^(\r\n|\n|\r)*/", "", $code);
58        $code = preg_replace("/(\r\n|\n|\r)*$/", "", $code);
59
60        $params   = explode(' ', $language);
61        $language = strtolower(array_shift($params));
62
63        if ($language == 'spip') {
64                $language = PLUGIN_COLORATION_CODE_COLORIEUR_SPIP;
65        }
66        if ($language == 'bibtex' and _COLORATION_BIBTEX_COMME_BIBLATEX == 1) {
67                $language = 'biblatex';
68        }
69        include_spip('inc/spip_geshi');
70        //
71        // Create a GeSHi object
72        //
73        $geshi = new SPIP_GeSHi($code, $language);
74        if ($geshi->error()) {
75                return false;
76        }
77        global $spip_lang_right;
78
79        // eviter des ajouts abusifs de CSS par Geshy
80        // qui pose des 'font-family: monospace;' un peu partout
81        // et que FF ne gere pas comme les autres navigateurs (va comprendre).
82        $geshi->set_overall_style('');
83        $geshi->set_code_style('');
84
85        $stylecss = "";
86        if (!PLUGIN_COLORATION_CODE_STYLES_INLINE OR PLUGIN_COLORATION_CODE_SANS_STYLES) {
87                $geshi->enable_classes();
88                if (!PLUGIN_COLORATION_CODE_SANS_STYLES) {
89                        $stylecss = "<style type='text/css'>" . $geshi->get_stylesheet() . "</style>";
90                }
91        }
92
93        if (defined('PLUGIN_COLORATION_CODE_TAB_WIDTH') and PLUGIN_COLORATION_CODE_TAB_WIDTH) {
94                $geshi->set_tab_width(PLUGIN_COLORATION_CODE_TAB_WIDTH);
95        }
96
97        // permettre de supprimer les liens vers les documentations sur les mots cles de langage
98        if (!PLUGIN_COLORATION_CODE_LIENS_LANGAGE) {
99                $geshi->enable_keyword_links(false);
100        }
101
102        include_spip('inc/texte');
103        $code = echappe_retour($code);
104
105        $telecharge = ($englobant == 'div')
106                && (PLUGIN_COLORATION_CODE_TELECHARGE || in_array('telechargement', $params))
107                && (strpos($code, "\n") !== false) && !in_array('sans_telechargement', $params);
108        if ($telecharge) {
109                // Gerer le fichier contenant le code au format texte
110                $nom_fichier = md5($code);
111                $dossier     = sous_repertoire(_DIR_VAR, 'cache-code');
112                $fichier     = "$dossier$nom_fichier.txt";
113
114                if (!file_exists($fichier)) {
115                        ecrire_fichier($fichier, $code);
116                }
117        }
118
119        /**
120         * On insère un attribut data-clipboard-text si on n'a pas le lien de téléchargement car pas de saut de ligne
121         */
122        $datatext         = !$telecharge && PLUGIN_COLORATION_CODE_TELECHARGE;
123        $datatext_content = "";
124        if ($datatext) {
125                $datatext_content = ' data-clipboard-text="' . attribut_html($code) . '"';
126        }
127
128        $traitement_par_precode = false;
129        if (defined('_DIR_PLUGIN_PRECODE') && _DIR_PLUGIN_PRECODE) {
130                // si le plugin PRECODE est activé, on utilise son balisage moderne
131                // header <pre> pour ne pas générer de <br>
132                $geshi->set_header_type(GESHI_HEADER_PRE);
133                $geshi->enable_line_numbers(GESHI_NO_LINE_NUMBERS);
134                $code_corps = $geshi->parse_code();
135                // si le code est sur plusieurs lignes, on passe le traitement à precode
136                // sinon, c'est du code inline que precode ne gère pas
137                if (strpos($code_avant_nettoyage, "\n") !== false) {
138                        $traitement_par_precode = true;
139                        // supprimer le <pre> englobant, qui sera ajouté par PRECODE
140                        $code_corps = trim(preg_replace('!^<pre[^>]*>|</pre>$!', '', $code_corps), "\n\r");
141                        $rempl      = precode_balisage_code('class="' . $language . '"', $code_corps);
142                }
143        }
144
145        if ($cadre == 'cadre' OR $englobant == "div") {
146                $geshi->set_header_type(GESHI_HEADER_DIV);
147                $geshi->enable_line_numbers(GESHI_NORMAL_LINE_NUMBERS);
148        } else {
149                $geshi->set_header_type(GESHI_HEADER_NONE);
150                $geshi->enable_line_numbers(GESHI_NO_LINE_NUMBERS);
151        }
152       
153        if(!$traitement_par_precode) {
154                $rempl = $stylecss . '<' . $englobant . ' class="coloration_code ' . $cadre . '"><' . $balise_code . ' class="spip_' . $language . ' ' . $cadre. '"' . $datatext_content . '>' . $geshi->parse_code() . '</' . $balise_code . '>';
155                if ($telecharge) {
156                        $rempl .= "<p class='download " . $cadre . "_download'><a href='$fichier'>" . _T('bouton_download') . "</a></p>";
157                }
158                $rempl .= '</' . $englobant . '>';
159        }
160
161        return $rempl;
162}
163
164/**
165 * Est-ce à Geshi de traiter les codes et cadres ou on utilise les fonctions natives de SPIP
166 *
167 * @param array $regs
168 *
169 * @return string $ret
170 */
171function cadre_ou_code($regs) {
172
173        // pour l'instant, on oublie $matches[1] et $matches[4] les attributs autour de class="machin"
174        if (preg_match(',^(.*)class=("|\')(.*)\2(.*)$,Uims', $regs[2], $matches)) {
175                $englobant = "div";
176                if ($regs[1] == "code" AND strpos($regs[3], "\n") === false) {
177                        $englobant = "span";
178                }
179                if ($ret = coloration_code_color($regs[3], $matches[3], $regs[1], $englobant)) {
180                        return $ret;
181                }
182        } else {
183                // traiter les <cadre> sans class par precode pour ne pas générer de <textarea>
184                if ($regs[1] == "cadre" && defined('_DIR_PLUGIN_PRECODE') && _DIR_PLUGIN_PRECODE) {
185                        return precode_balisage_code('class=""', trim(entites_html($regs[3])));
186                }
187        }
188
189        if ($regs[1] == 'code') {
190                return defined('_DIR_PLUGIN_PRECODE') && _DIR_PLUGIN_PRECODE ?
191                        precode_traiter_echap_code($regs) : traiter_echap_code_dist($regs);
192        }
193       
194        return defined('_DIR_PLUGIN_PRECODE') && _DIR_PLUGIN_PRECODE ?
195                precode_traiter_echap_cadre($regs) : traiter_echap_cadre_dist($regs);
196}
197
198/**
199 * Surcharge de la fonction traiter_echap_code_dist native de SPIP
200 * cf : ecrire/inc/texte_mini
201 *
202 * @param array $regs
203 *
204 * @return string
205 */
206function traiter_echap_code($regs) {
207        return cadre_ou_code($regs);
208}
209
210/**
211 * Surcharge de la fonction traiter_echap_cadre_dist native de SPIP
212 * cf : ecrire/inc/texte_mini
213 *
214 * @param array $regs
215 *
216 * @return string
217 */
218function traiter_echap_cadre($regs) {
219        return cadre_ou_code($regs);
220}
Note: See TracBrowser for help on using the repository browser.