3 if (!defined("_ECRIRE_INC_VERSION")) return;
5 function compacte_ecrire_balise_script_dist($src){
6 return "<script type='text/javascript' src='$src'></script>";
8 function compacte_ecrire_balise_link_dist($src,$media=""){
9 return "<link rel='stylesheet'".($media?
" media='$media'":"")." href='$src' type='text/css' />";
13 // http://doc.spip.org/@compacte_css
14 function compacte_css ($contenu) {
15 // nettoyer la css de tout ce qui sert pas
16 $contenu = preg_replace(",/\*.*\*/,Ums","",$contenu); // pas de commentaires
17 $contenu = preg_replace(",\s(?=\s),Ums","",$contenu); // pas d'espaces consecutifs
18 $contenu = preg_replace("/\s?({|;|,|:)\s?/ms","$1",$contenu); // pas d'espaces dans les declarations css
19 $contenu = preg_replace("/\s}/ms","}",$contenu); // pas d'espaces dans les declarations css
20 // passser les codes couleurs en 3 car si possible
21 // uniquement si non precedees d'un [="'] ce qui indique qu'on est dans un filter(xx=#?...)
22 $contenu = preg_replace(";([:\s,(])#([0-9a-f])(\\2)([0-9a-f])(\\4)([0-9a-f])(\\6)(?=[^\w\-]);i","$1#$2$4$6",$contenu);
23 // supprimer les declarations vides
24 $contenu = preg_replace(",(^|})([^{}]*){},Ums","$1",$contenu);
25 $contenu = trim($contenu);
30 // Compacte du javascript grace a Dean Edward's JavaScriptPacker
31 // utile pour prive/jquery.js par exemple
32 // http://doc.spip.org/@compacte_js
33 function compacte_js($flux) {
34 // si la closure est demandee, on pourrait zapper cette etape
35 // mais avec le risque, en localhost, de depasser 200ko et d'echec
36 #if ($GLOBALS['meta']['auto_compress_closure'] == 'oui')
41 include_spip('lib/JavascriptPacker/class.JavaScriptPacker');
42 $packer = new JavaScriptPacker($flux, 0, true, false);
44 // en cas d'echec (?) renvoyer l'original
45 if (!strlen($t = $packer->pack())) {
46 spip_log('erreur de compacte_js');
54 // Appelee par compacte_head() si le webmestre le desire, cette fonction
55 // compacte les scripts js dans un fichier statique pose dans local/
56 // en entree : un <head> html.
57 // http://doc.spip.org/@compacte_head_js
58 function compacte_head_js($flux) {
59 $url_base = url_de_base();
60 $url_page = substr(generer_url_public('A'), 0, -1);
61 $dir = preg_quote($url_page,',').'|'.preg_quote(preg_replace(",^$url_base,",_DIR_RACINE
,$url_page),',');
64 $flux_nocomment = preg_replace(",<!--.*-->,Uims","",$flux);
65 foreach (extraire_balises($flux_nocomment,'script') as $s) {
66 if (extraire_attribut($s, 'type') === 'text/javascript'
67 AND is_null(extraire_attribut($s, 'id')) # script avec un id : pas touche
68 AND $src = extraire_attribut($s, 'src')
69 AND !strlen(strip_tags($s))
71 preg_match(',^('.$dir.')(.*)$,', $src, $r)
73 // ou si c'est un fichier
74 $src = preg_replace(',^'.preg_quote(url_de_base(),',').',', '', $src)
75 // enlever un timestamp eventuel derriere un nom de fichier statique
76 AND $src2 = preg_replace(",[.]js[?].+$,",'.js',$src)
77 // verifier qu'il n'y a pas de ../ ni / au debut (securite)
78 AND !preg_match(',(^/|\.\.),', substr($src,strlen(_DIR_RACINE
)))
79 // et si il est lisible
80 AND @is_readable
($src2)
84 $scripts[$s] = explode('&',
85 str_replace('&', '&', $r[2]), 2);
91 if (list($src,$comms) = filtre_cache_static($scripts,'js')){
92 $compacte_ecrire_balise_script = charger_fonction('compacte_ecrire_balise_script','');
93 $scripts = array_keys($scripts);
94 $flux = str_replace(reset($scripts),
95 $comms .$compacte_ecrire_balise_script($src)."\n",
97 $flux = str_replace($scripts,"",$flux);
103 // Appelee par compacte_head() si le webmestre le desire, cette fonction
104 // compacte les feuilles de style css dans un fichier statique pose dans local/
105 // en entree : un <head> html.
106 // http://doc.spip.org/@compacte_head_css
107 function compacte_head_css($flux) {
108 $url_base = url_de_base();
109 $url_page = substr(generer_url_public('A'), 0, -1);
110 $dir = preg_quote($url_page,',').'|'.preg_quote(preg_replace(",^$url_base,",_DIR_RACINE
,$url_page),',');
113 $flux_nocomment = preg_replace(",<!--.*-->,Uims","",$flux);
114 foreach (extraire_balises($flux_nocomment, 'link') as $s) {
115 if (extraire_attribut($s, 'rel') === 'stylesheet'
116 AND (!($type = extraire_attribut($s, 'type'))
117 OR $type == 'text/css')
118 AND is_null(extraire_attribut($s, 'name')) # css nommee : pas touche
119 AND is_null(extraire_attribut($s, 'id')) # idem
120 AND !strlen(strip_tags($s))
121 AND $src = preg_replace(",^$url_base,",_DIR_RACINE
,extraire_attribut($s, 'href'))
123 // regarder si c'est du format spip.php?page=xxx
124 preg_match(',^('.$dir.')(.*)$,', $src, $r)
126 // ou si c'est un fichier
127 // enlever un timestamp eventuel derriere un nom de fichier statique
128 $src2 = preg_replace(",[.]css[?].+$,",'.css',$src)
129 // verifier qu'il n'y a pas de ../ ni / au debut (securite)
130 AND !preg_match(',(^/|\.\.),', substr($src2,strlen(_DIR_RACINE
)))
131 // et si il est lisible
132 AND @is_readable
($src2)
135 $media = strval(extraire_attribut($s, 'media'));
136 if ($media==='') $media='all';
138 $css[$media][$s] = explode('&',
139 str_replace('&', '&', $r[2]), 2);
141 $css[$media][$s] = $src;
145 // et mettre le tout dans un cache statique
146 foreach($css as $m=>$s){
147 // si plus d'une css pour ce media ou si c'est une css dynamique
148 if (count($s)>1 OR is_array(reset($s))){
149 if (list($src,$comms) = filtre_cache_static($s,'css')){
150 $compacte_ecrire_balise_link = charger_fonction('compacte_ecrire_balise_link','');
152 $flux = str_replace(reset($s),
153 $comms . $compacte_ecrire_balise_link($src,$m)."\n",
155 $flux = str_replace($s,"",$flux);
164 // http://doc.spip.org/@filtre_cache_static
165 function filtre_cache_static($scripts,$type='js'){
167 if (!is_array($scripts) && $scripts) $scripts = array($scripts);
168 if (count($scripts)){
169 $dir = sous_repertoire(_DIR_VAR
,'cache-'.$type);
170 $nom = $dir . md5(serialize($scripts)) . ".$type";
172 $GLOBALS['var_mode']=='recalcul'
173 OR !file_exists($nom)
178 foreach($scripts as $script){
179 if (!is_array($script)) {
182 // enlever le timestamp si besoin
183 $script = preg_replace(",[?].+$,",'',$script);
185 $fonctions = array('urls_absolues_css');
186 if (isset($GLOBALS['compresseur_filtres_css']) AND is_array($GLOBALS['compresseur_filtres_css']))
187 $fonctions = $GLOBALS['compresseur_filtres_css'] +
$fonctions;
188 $script = appliquer_fonctions_css_fichier($fonctions, $script);
190 lire_fichier($script, $contenu);
193 // c'est un squelette
194 $comm = _SPIP_PAGE
. "=$script[0]"
195 . (strlen($script[1])?
"($script[1])":'');
196 parse_str($script[1],$contexte);
197 $contenu = recuperer_fond($script[0],$contexte);
199 $fonctions = array('urls_absolues_css');
200 if (isset($GLOBALS['compresseur_filtres_css']) AND is_array($GLOBALS['compresseur_filtres_css']))
201 $fonctions = $GLOBALS['compresseur_filtres_css'] +
$fonctions;
202 $contenu = appliquer_fonctions_css_contenu($fonctions, $contenu, self('&'));
205 $f = 'compacte_'.$type;
206 $fichier .= "/* $comm */\n". $f($contenu) . "\n\n";
208 $total +
= strlen($contenu);
211 // calcul du % de compactage
212 $pc = ($total?
intval(1000*strlen($fichier)/$total)/10:0);
213 $comms = "compact [\n\t".join("\n\t", $comms)."\n] $pc%";
214 $fichier = "/* $comms */\n\n".$fichier;
217 ecrire_fichier($nom,$fichier,true);
218 // ecrire une version .gz pour content-negociation par apache, cf. [11539]
219 ecrire_fichier("$nom.gz",$fichier,true);
222 // closure compiler ou autre super-compresseurs
223 compresse_encore($nom, $type);
227 // Le commentaire detaille n'apparait qu'au recalcul, pour debug
228 return array($nom, (isset($comms) AND $comms) ?
"<!-- $comms -->\n" : '');
231 // experimenter le Closure Compiler de Google
232 function compresse_encore (&$nom, $type) {
233 # Closure Compiler n'accepte pas des POST plus gros que 200 000 octets
234 # au-dela il faut stocker dans un fichier, et envoyer l'url du fichier
235 # dans code_url ; en localhost ca ne marche evidemment pas
237 $GLOBALS['meta']['auto_compress_closure'] == 'oui'
240 lire_fichier($nom, $fichier);
241 $dest = dirname($nom).'/'.md5($fichier).'.js';
242 if (!@file_exists
($dest)) {
243 include_spip('inc/distant');
246 'output_format' => 'text',
247 'output_info' => 'compiled_code',
248 'compilation_level' => 'SIMPLE_OPTIMIZATIONS', // 'SIMPLE_OPTIMIZATIONS', 'WHITESPACE_ONLY', 'ADVANCED_OPTIMIZATIONS'
250 if (strlen($fichier) < 200000)
251 $datas['js_code'] = $fichier;
253 $datas['url_code'] = url_absolue($nom);
255 $cc = recuperer_page('http://closure-compiler.appspot.com/compile',
256 $trans=false, $get_headers=false,
260 if ($cc AND !preg_match(',^\s*Error,', $cc)) {
261 spip_log('Closure Compiler: success');
262 $cc = "/* $nom + Closure Compiler */\n".$cc;
263 ecrire_fichier ($dest, $cc, true);
264 ecrire_fichier ("$dest.gz", $cc, true);
266 ecrire_fichier ($dest, '', true);
268 if (@filesize
($dest))
273 function appliquer_fonctions_css_fichier($fonctions,$css) {
274 if (!preg_match(',\.css$,i', $css, $r)) return $css;
276 $url_absolue_css = url_absolue($css);
278 // verifier qu'on a un array
279 if (is_string($fonctions))
280 $fonctions = array($fonctions);
282 $sign = implode(",",$fonctions);
283 $sign = substr(md5("$css-$sign"), 0,8);
285 $file = basename($css,'.css');
286 $file = sous_repertoire (_DIR_VAR
, 'cache-css')
287 . preg_replace(",(.*?)(_rtl|_ltr)?$,","\\1-f-" . $sign . "\\2",$file)
290 if ((@filemtime
($f) > @filemtime
($css))
291 AND ($GLOBALS['var_mode'] != 'recalcul'))
294 if ($url_absolue_css==$css){
295 if (strncmp($GLOBALS['meta']['adresse_site'],$css,$l=strlen($GLOBALS['meta']['adresse_site']))!=0
296 OR !lire_fichier(_DIR_RACINE
. substr($css,$l), $contenu)){
297 include_spip('inc/distant');
298 if (!$contenu = recuperer_page($css))
302 elseif (!lire_fichier($css, $contenu))
305 $contenu = appliquer_fonctions_css_contenu($fonctions, $contenu, $css);
308 if (!ecrire_fichier($file, $contenu))
314 function appliquer_fonctions_css_contenu($fonctions, &$contenu, $base) {
315 foreach($fonctions as $f)
316 if (function_exists($f))
317 $contenu = $f($contenu, $base);
322 function compresseur_embarquer_images_css($contenu, $source){
323 #$path = suivre_lien(url_absolue($source),'./');
324 $base = ((substr($source,-1)=='/')?
$source:(dirname($source).'/'));
326 return preg_replace_callback(
327 ",url\s*\(\s*['\"]?([^'\"/][^:]*[.](png|gif|jpg))['\"]?\s*\),Uims",
328 create_function('$x',
329 'return "url(\"".filtre_embarque_fichier($x[1],"'.$base.'")."\")";'