1*7d666900SdWiGhT<?php 2*7d666900SdWiGhT 3*7d666900SdWiGhT/** 4*7d666900SdWiGhT * CSSTidy - CSS Parser and Optimiser 5*7d666900SdWiGhT * 6*7d666900SdWiGhT * CSS Printing class 7*7d666900SdWiGhT * This class prints CSS data generated by csstidy. 8*7d666900SdWiGhT * 9*7d666900SdWiGhT * Copyright 2005, 2006, 2007 Florian Schmitz 10*7d666900SdWiGhT * 11*7d666900SdWiGhT * This file is part of CSSTidy. 12*7d666900SdWiGhT * 13*7d666900SdWiGhT * CSSTidy is free software; you can redistribute it and/or modify 14*7d666900SdWiGhT * it under the terms of the GNU Lesser General Public License as published by 15*7d666900SdWiGhT * the Free Software Foundation; either version 2.1 of the License, or 16*7d666900SdWiGhT * (at your option) any later version. 17*7d666900SdWiGhT * 18*7d666900SdWiGhT * CSSTidy is distributed in the hope that it will be useful, 19*7d666900SdWiGhT * but WITHOUT ANY WARRANTY; without even the implied warranty of 20*7d666900SdWiGhT * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 21*7d666900SdWiGhT * GNU Lesser General Public License for more details. 22*7d666900SdWiGhT * 23*7d666900SdWiGhT * You should have received a copy of the GNU Lesser General Public License 24*7d666900SdWiGhT * along with this program. If not, see <http://www.gnu.org/licenses/>. 25*7d666900SdWiGhT * 26*7d666900SdWiGhT * @license http://opensource.org/licenses/lgpl-license.php GNU Lesser General Public License 27*7d666900SdWiGhT * @package csstidy 28*7d666900SdWiGhT * @author Florian Schmitz (floele at gmail dot com) 2005-2007 29*7d666900SdWiGhT * @author Brett Zamir (brettz9 at yahoo dot com) 2007 30*7d666900SdWiGhT * @author Cedric Morin (cedric at yterium dot com) 2010-2012 31*7d666900SdWiGhT */ 32*7d666900SdWiGhT 33*7d666900SdWiGhT/** 34*7d666900SdWiGhT * CSS Printing class 35*7d666900SdWiGhT * 36*7d666900SdWiGhT * This class prints CSS data generated by csstidy. 37*7d666900SdWiGhT * 38*7d666900SdWiGhT * @package csstidy 39*7d666900SdWiGhT * @author Florian Schmitz (floele at gmail dot com) 2005-2006 40*7d666900SdWiGhT * @version 1.1.0 41*7d666900SdWiGhT */ 42*7d666900SdWiGhTclass csstidy_print { 43*7d666900SdWiGhT 44*7d666900SdWiGhT /** 45*7d666900SdWiGhT * csstidy object 46*7d666900SdWiGhT * @var object 47*7d666900SdWiGhT */ 48*7d666900SdWiGhT public $parser; 49*7d666900SdWiGhT 50*7d666900SdWiGhT /** 51*7d666900SdWiGhT * Saves the input CSS string 52*7d666900SdWiGhT * @var string 53*7d666900SdWiGhT * @access private 54*7d666900SdWiGhT */ 55*7d666900SdWiGhT public $input_css = ''; 56*7d666900SdWiGhT /** 57*7d666900SdWiGhT * Saves the formatted CSS string 58*7d666900SdWiGhT * @var string 59*7d666900SdWiGhT * @access public 60*7d666900SdWiGhT */ 61*7d666900SdWiGhT public $output_css = ''; 62*7d666900SdWiGhT /** 63*7d666900SdWiGhT * Saves the formatted CSS string (plain text) 64*7d666900SdWiGhT * @var string 65*7d666900SdWiGhT * @access public 66*7d666900SdWiGhT */ 67*7d666900SdWiGhT public $output_css_plain = ''; 68*7d666900SdWiGhT 69*7d666900SdWiGhT public $css; 70*7d666900SdWiGhT public $template; 71*7d666900SdWiGhT public $tokens; 72*7d666900SdWiGhT public $charset; 73*7d666900SdWiGhT public $import; 74*7d666900SdWiGhT public $namespace; 75*7d666900SdWiGhT 76*7d666900SdWiGhT /** 77*7d666900SdWiGhT * Constructor 78*7d666900SdWiGhT * @param array $css contains the class csstidy 79*7d666900SdWiGhT * @access private 80*7d666900SdWiGhT * @version 1.0 81*7d666900SdWiGhT */ 82*7d666900SdWiGhT public function __construct($css) { 83*7d666900SdWiGhT $this->parser = $css; 84*7d666900SdWiGhT $this->css = & $css->css; 85*7d666900SdWiGhT $this->template = & $css->template; 86*7d666900SdWiGhT $this->tokens = & $css->tokens; 87*7d666900SdWiGhT $this->charset = & $css->charset; 88*7d666900SdWiGhT $this->import = & $css->import; 89*7d666900SdWiGhT $this->namespace = & $css->namespace; 90*7d666900SdWiGhT } 91*7d666900SdWiGhT 92*7d666900SdWiGhT /** 93*7d666900SdWiGhT * Resets output_css and output_css_plain (new css code) 94*7d666900SdWiGhT * @access private 95*7d666900SdWiGhT * @version 1.0 96*7d666900SdWiGhT */ 97*7d666900SdWiGhT public function _reset() { 98*7d666900SdWiGhT $this->output_css = ''; 99*7d666900SdWiGhT $this->output_css_plain = ''; 100*7d666900SdWiGhT } 101*7d666900SdWiGhT 102*7d666900SdWiGhT /** 103*7d666900SdWiGhT * Returns the CSS code as plain text 104*7d666900SdWiGhT * @param string $default_media default @media to add to selectors without any @media 105*7d666900SdWiGhT * @return string 106*7d666900SdWiGhT * @access public 107*7d666900SdWiGhT * @version 1.0 108*7d666900SdWiGhT */ 109*7d666900SdWiGhT public function plain($default_media='') { 110*7d666900SdWiGhT $this->_print(true, $default_media); 111*7d666900SdWiGhT return $this->output_css_plain; 112*7d666900SdWiGhT } 113*7d666900SdWiGhT 114*7d666900SdWiGhT /** 115*7d666900SdWiGhT * Returns the formatted CSS code 116*7d666900SdWiGhT * @param string $default_media default @media to add to selectors without any @media 117*7d666900SdWiGhT * @return string 118*7d666900SdWiGhT * @access public 119*7d666900SdWiGhT * @version 1.0 120*7d666900SdWiGhT */ 121*7d666900SdWiGhT public function formatted($default_media='') { 122*7d666900SdWiGhT $this->_print(false, $default_media); 123*7d666900SdWiGhT return $this->output_css; 124*7d666900SdWiGhT } 125*7d666900SdWiGhT 126*7d666900SdWiGhT /** 127*7d666900SdWiGhT * Returns the formatted CSS code to make a complete webpage 128*7d666900SdWiGhT * @param string $doctype shorthand for the document type 129*7d666900SdWiGhT * @param bool $externalcss indicates whether styles to be attached internally or as an external stylesheet 130*7d666900SdWiGhT * @param string $title title to be added in the head of the document 131*7d666900SdWiGhT * @param string $lang two-letter language code to be added to the output 132*7d666900SdWiGhT * @return string 133*7d666900SdWiGhT * @access public 134*7d666900SdWiGhT * @version 1.4 135*7d666900SdWiGhT */ 136*7d666900SdWiGhT public function formatted_page($doctype='html5', $externalcss=true, $title='', $lang='en') { 137*7d666900SdWiGhT switch ($doctype) { 138*7d666900SdWiGhT case 'html5': 139*7d666900SdWiGhT $doctype_output = '<!DOCTYPE html>'; 140*7d666900SdWiGhT break; 141*7d666900SdWiGhT case 'xhtml1.0strict': 142*7d666900SdWiGhT $doctype_output = '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" 143*7d666900SdWiGhT "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">'; 144*7d666900SdWiGhT break; 145*7d666900SdWiGhT case 'xhtml1.1': 146*7d666900SdWiGhT default: 147*7d666900SdWiGhT $doctype_output = '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" 148*7d666900SdWiGhT "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">'; 149*7d666900SdWiGhT break; 150*7d666900SdWiGhT } 151*7d666900SdWiGhT 152*7d666900SdWiGhT $output = $cssparsed = ''; 153*7d666900SdWiGhT $this->output_css_plain = & $output; 154*7d666900SdWiGhT 155*7d666900SdWiGhT $output .= $doctype_output . "\n" . '<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="' . $lang . '"'; 156*7d666900SdWiGhT $output .= ( $doctype === 'xhtml1.1') ? '>' : ' lang="' . $lang . '">'; 157*7d666900SdWiGhT $output .= "\n<head>\n <title>$title</title>"; 158*7d666900SdWiGhT 159*7d666900SdWiGhT if ($externalcss) { 160*7d666900SdWiGhT $output .= "\n <style type=\"text/css\">\n"; 161*7d666900SdWiGhT $cssparsed = file_get_contents('cssparsed.css'); 162*7d666900SdWiGhT $output .= $cssparsed; // Adds an invisible BOM or something, but not in css_optimised.php 163*7d666900SdWiGhT $output .= "\n</style>"; 164*7d666900SdWiGhT } else { 165*7d666900SdWiGhT $output .= "\n" . ' <link rel="stylesheet" type="text/css" href="cssparsed.css" />'; 166*7d666900SdWiGhT } 167*7d666900SdWiGhT $output .= "\n</head>\n<body><code id=\"copytext\">"; 168*7d666900SdWiGhT $output .= $this->formatted(); 169*7d666900SdWiGhT $output .= '</code>' . "\n" . '</body></html>'; 170*7d666900SdWiGhT return $this->output_css_plain; 171*7d666900SdWiGhT } 172*7d666900SdWiGhT 173*7d666900SdWiGhT /** 174*7d666900SdWiGhT * Returns the formatted CSS Code and saves it into $this->output_css and $this->output_css_plain 175*7d666900SdWiGhT * @param bool $plain plain text or not 176*7d666900SdWiGhT * @param string $default_media default @media to add to selectors without any @media 177*7d666900SdWiGhT * @access private 178*7d666900SdWiGhT * @version 2.0 179*7d666900SdWiGhT */ 180*7d666900SdWiGhT public function _print($plain = false, $default_media='') { 181*7d666900SdWiGhT if ($this->output_css && $this->output_css_plain) { 182*7d666900SdWiGhT return; 183*7d666900SdWiGhT } 184*7d666900SdWiGhT 185*7d666900SdWiGhT $output = ''; 186*7d666900SdWiGhT if (!$this->parser->get_cfg('preserve_css')) { 187*7d666900SdWiGhT $this->_convert_raw_css($default_media); 188*7d666900SdWiGhT } 189*7d666900SdWiGhT 190*7d666900SdWiGhT $template = & $this->template; 191*7d666900SdWiGhT 192*7d666900SdWiGhT if ($plain) { 193*7d666900SdWiGhT $template = array_map('strip_tags', $template); 194*7d666900SdWiGhT } 195*7d666900SdWiGhT 196*7d666900SdWiGhT if ($this->parser->get_cfg('timestamp')) { 197*7d666900SdWiGhT array_unshift($this->tokens, array(COMMENT, ' CSSTidy ' . $this->parser->version . ': ' . date('r') . ' ')); 198*7d666900SdWiGhT } 199*7d666900SdWiGhT 200*7d666900SdWiGhT if (!empty($this->charset)) { 201*7d666900SdWiGhT $output .= $template[0] . '@charset ' . $template[5] . $this->charset . $template[6] . $template[13]; 202*7d666900SdWiGhT } 203*7d666900SdWiGhT 204*7d666900SdWiGhT if (!empty($this->import)) { 205*7d666900SdWiGhT for ($i = 0, $size = count($this->import); $i < $size; $i++) { 206*7d666900SdWiGhT if (substr($this->import[$i], 0, 4) === 'url(' && substr($this->import[$i], -1, 1) === ')') { 207*7d666900SdWiGhT $this->import[$i] = '"' . substr($this->import[$i], 4, -1) . '"'; 208*7d666900SdWiGhT $this->parser->log('Optimised @import : Removed "url("', 'Information'); 209*7d666900SdWiGhT } 210*7d666900SdWiGhT else if (!preg_match('/^".+"$/',$this->import[$i])) { 211*7d666900SdWiGhT // fixes a bug for @import ".." instead of the expected @import url("..") 212*7d666900SdWiGhT // If it comes in due to @import ".." the "" will be missing and the output will become @import .. (which is an error) 213*7d666900SdWiGhT $this->import[$i] = '"' . $this->import[$i] . '"'; 214*7d666900SdWiGhT } 215*7d666900SdWiGhT 216*7d666900SdWiGhT $output .= $template[0] . '@import ' . $template[5] . $this->import[$i] . $template[6] . $template[13]; 217*7d666900SdWiGhT } 218*7d666900SdWiGhT } 219*7d666900SdWiGhT 220*7d666900SdWiGhT if (!empty($this->namespace)) { 221*7d666900SdWiGhT if (($p=strpos($this->namespace,"url("))!==false && substr($this->namespace, -1, 1) === ')') { 222*7d666900SdWiGhT $this->namespace = substr_replace($this->namespace,'"',$p,4); 223*7d666900SdWiGhT $this->namespace = substr($this->namespace, 0, -1) . '"'; 224*7d666900SdWiGhT $this->parser->log('Optimised @namespace : Removed "url("', 'Information'); 225*7d666900SdWiGhT } 226*7d666900SdWiGhT $output .= $template[0] . '@namespace ' . $template[5] . $this->namespace . $template[6] . $template[13]; 227*7d666900SdWiGhT } 228*7d666900SdWiGhT 229*7d666900SdWiGhT $in_at_out = []; 230*7d666900SdWiGhT $out = & $output; 231*7d666900SdWiGhT $indent_level = 0; 232*7d666900SdWiGhT 233*7d666900SdWiGhT foreach ($this->tokens as $key => $token) { 234*7d666900SdWiGhT switch ($token[0]) { 235*7d666900SdWiGhT case AT_START: 236*7d666900SdWiGhT $out .= $template[0] . $this->_htmlsp($token[1], $plain) . $template[1]; 237*7d666900SdWiGhT $indent_level++; 238*7d666900SdWiGhT if (!isset($in_at_out[$indent_level])) { 239*7d666900SdWiGhT $in_at_out[$indent_level] = ''; 240*7d666900SdWiGhT } 241*7d666900SdWiGhT $out = & $in_at_out[$indent_level]; 242*7d666900SdWiGhT break; 243*7d666900SdWiGhT 244*7d666900SdWiGhT case SEL_START: 245*7d666900SdWiGhT if ($this->parser->get_cfg('lowercase_s')) 246*7d666900SdWiGhT $token[1] = strtolower($token[1]); 247*7d666900SdWiGhT $out .= ( $token[1][0] !== '@') ? $template[2] . $this->_htmlsp($token[1], $plain) : $template[0] . $this->_htmlsp($token[1], $plain); 248*7d666900SdWiGhT $out .= $template[3]; 249*7d666900SdWiGhT break; 250*7d666900SdWiGhT 251*7d666900SdWiGhT case PROPERTY: 252*7d666900SdWiGhT if ($this->parser->get_cfg('case_properties') === 2) { 253*7d666900SdWiGhT $token[1] = strtoupper($token[1]); 254*7d666900SdWiGhT } elseif ($this->parser->get_cfg('case_properties') === 1) { 255*7d666900SdWiGhT $token[1] = strtolower($token[1]); 256*7d666900SdWiGhT } 257*7d666900SdWiGhT $out .= $template[4] . $this->_htmlsp($token[1], $plain) . ':' . $template[5]; 258*7d666900SdWiGhT break; 259*7d666900SdWiGhT 260*7d666900SdWiGhT case VALUE: 261*7d666900SdWiGhT $out .= $this->_htmlsp($token[1], $plain); 262*7d666900SdWiGhT if ($this->_seeknocomment($key, 1) == SEL_END && $this->parser->get_cfg('remove_last_;')) { 263*7d666900SdWiGhT $out .= str_replace(';', '', $template[6]); 264*7d666900SdWiGhT } else { 265*7d666900SdWiGhT $out .= $template[6]; 266*7d666900SdWiGhT } 267*7d666900SdWiGhT break; 268*7d666900SdWiGhT 269*7d666900SdWiGhT case SEL_END: 270*7d666900SdWiGhT $out .= $template[7]; 271*7d666900SdWiGhT if ($this->_seeknocomment($key, 1) != AT_END) 272*7d666900SdWiGhT $out .= $template[8]; 273*7d666900SdWiGhT break; 274*7d666900SdWiGhT 275*7d666900SdWiGhT case AT_END: 276*7d666900SdWiGhT if (strlen($template[10])) { 277*7d666900SdWiGhT // indent the bloc we are closing 278*7d666900SdWiGhT $out = str_replace("\n\n", "\r\n", $out); // don't fill empty lines 279*7d666900SdWiGhT $out = str_replace("\n", "\n" . $template[10], $out); 280*7d666900SdWiGhT $out = str_replace("\r\n", "\n\n", $out); 281*7d666900SdWiGhT } 282*7d666900SdWiGhT if ($indent_level > 1) { 283*7d666900SdWiGhT $out = & $in_at_out[$indent_level-1]; 284*7d666900SdWiGhT } 285*7d666900SdWiGhT else { 286*7d666900SdWiGhT $out = & $output; 287*7d666900SdWiGhT } 288*7d666900SdWiGhT $out .= $template[10] . $in_at_out[$indent_level]; 289*7d666900SdWiGhT if ($this->_seeknocomment($key, 1) != AT_END) { 290*7d666900SdWiGhT $out .= $template[9]; 291*7d666900SdWiGhT } 292*7d666900SdWiGhT else { 293*7d666900SdWiGhT $out .= rtrim($template[9]); 294*7d666900SdWiGhT } 295*7d666900SdWiGhT 296*7d666900SdWiGhT unset($in_at_out[$indent_level]); 297*7d666900SdWiGhT $indent_level--; 298*7d666900SdWiGhT break; 299*7d666900SdWiGhT 300*7d666900SdWiGhT case IMPORTANT_COMMENT: 301*7d666900SdWiGhT case COMMENT: 302*7d666900SdWiGhT $out .= $template[11] . '/*' . $this->_htmlsp($token[1], $plain) . '*/' . $template[12]; 303*7d666900SdWiGhT break; 304*7d666900SdWiGhT } 305*7d666900SdWiGhT } 306*7d666900SdWiGhT 307*7d666900SdWiGhT $output = trim($output); 308*7d666900SdWiGhT 309*7d666900SdWiGhT if (!$plain) { 310*7d666900SdWiGhT $this->output_css = $output; 311*7d666900SdWiGhT $this->_print(true); 312*7d666900SdWiGhT } else { 313*7d666900SdWiGhT // If using spaces in the template, don't want these to appear in the plain output 314*7d666900SdWiGhT $this->output_css_plain = str_replace(' ', '', $output); 315*7d666900SdWiGhT } 316*7d666900SdWiGhT } 317*7d666900SdWiGhT 318*7d666900SdWiGhT /** 319*7d666900SdWiGhT * Gets the next token type which is $move away from $key, excluding comments 320*7d666900SdWiGhT * @param integer $key current position 321*7d666900SdWiGhT * @param integer $move move this far 322*7d666900SdWiGhT * @return mixed a token type 323*7d666900SdWiGhT * @access private 324*7d666900SdWiGhT * @version 1.0 325*7d666900SdWiGhT */ 326*7d666900SdWiGhT public function _seeknocomment($key, $move) { 327*7d666900SdWiGhT $go = ($move > 0) ? 1 : -1; 328*7d666900SdWiGhT for ($i = $key + 1; abs($key - $i) - 1 < abs($move); $i += $go) { 329*7d666900SdWiGhT if (!isset($this->tokens[$i])) { 330*7d666900SdWiGhT return; 331*7d666900SdWiGhT } 332*7d666900SdWiGhT if ($this->tokens[$i][0] == COMMENT) { 333*7d666900SdWiGhT $move += 1; 334*7d666900SdWiGhT continue; 335*7d666900SdWiGhT } 336*7d666900SdWiGhT return $this->tokens[$i][0]; 337*7d666900SdWiGhT } 338*7d666900SdWiGhT } 339*7d666900SdWiGhT 340*7d666900SdWiGhT /** 341*7d666900SdWiGhT * Converts $this->css array to a raw array ($this->tokens) 342*7d666900SdWiGhT * @param string $default_media default @media to add to selectors without any @media 343*7d666900SdWiGhT * @access private 344*7d666900SdWiGhT * @version 1.0 345*7d666900SdWiGhT */ 346*7d666900SdWiGhT public function _convert_raw_css($default_media='') { 347*7d666900SdWiGhT $this->tokens = array(); 348*7d666900SdWiGhT $sort_selectors = $this->parser->get_cfg('sort_selectors'); 349*7d666900SdWiGhT $sort_properties = $this->parser->get_cfg('sort_properties'); 350*7d666900SdWiGhT 351*7d666900SdWiGhT // important comment section ? 352*7d666900SdWiGhT if (isset($this->css['!'])) { 353*7d666900SdWiGhT $this->parser->_add_token(IMPORTANT_COMMENT, rtrim($this->css['!']), true); 354*7d666900SdWiGhT unset($this->css['!']); 355*7d666900SdWiGhT } 356*7d666900SdWiGhT 357*7d666900SdWiGhT foreach ($this->css as $medium => $val) { 358*7d666900SdWiGhT if ($sort_selectors) 359*7d666900SdWiGhT ksort($val); 360*7d666900SdWiGhT if (intval($medium) < DEFAULT_AT) { 361*7d666900SdWiGhT // un medium vide (contenant @font-face ou autre @) ne produit aucun conteneur 362*7d666900SdWiGhT if (strlen(trim($medium))) { 363*7d666900SdWiGhT $parts_to_open = explode('{', $medium); 364*7d666900SdWiGhT foreach ($parts_to_open as $part) { 365*7d666900SdWiGhT $this->parser->_add_token(AT_START, $part, true); 366*7d666900SdWiGhT } 367*7d666900SdWiGhT } 368*7d666900SdWiGhT } elseif ($default_media) { 369*7d666900SdWiGhT $this->parser->_add_token(AT_START, $default_media, true); 370*7d666900SdWiGhT } 371*7d666900SdWiGhT 372*7d666900SdWiGhT foreach ($val as $selector => $vali) { 373*7d666900SdWiGhT if ($sort_properties) 374*7d666900SdWiGhT ksort($vali); 375*7d666900SdWiGhT $this->parser->_add_token(SEL_START, $selector, true); 376*7d666900SdWiGhT 377*7d666900SdWiGhT $invalid = array( 378*7d666900SdWiGhT '*' => array(), // IE7 hacks first 379*7d666900SdWiGhT '_' => array(), // IE6 hacks 380*7d666900SdWiGhT '/' => array(), // IE6 hacks 381*7d666900SdWiGhT '-' => array() // IE6 hacks 382*7d666900SdWiGhT ); 383*7d666900SdWiGhT foreach ($vali as $property => $valj) { 384*7d666900SdWiGhT if (strncmp($property,"//",2)!==0) { 385*7d666900SdWiGhT $matches = array(); 386*7d666900SdWiGhT if ($sort_properties && preg_match('/^(\*|_|\/|-)(?!(ms|moz|o\b|xv|atsc|wap|khtml|webkit|ah|hp|ro|rim|tc)-)/', $property, $matches)) { 387*7d666900SdWiGhT $invalid[$matches[1]][$property] = $valj; 388*7d666900SdWiGhT } else { 389*7d666900SdWiGhT $this->parser->_add_token(PROPERTY, $property, true); 390*7d666900SdWiGhT $this->parser->_add_token(VALUE, $valj, true); 391*7d666900SdWiGhT } 392*7d666900SdWiGhT } 393*7d666900SdWiGhT } 394*7d666900SdWiGhT foreach ($invalid as $prefix => $props) { 395*7d666900SdWiGhT foreach ($props as $property => $valj) { 396*7d666900SdWiGhT $this->parser->_add_token(PROPERTY, $property, true); 397*7d666900SdWiGhT $this->parser->_add_token(VALUE, $valj, true); 398*7d666900SdWiGhT } 399*7d666900SdWiGhT } 400*7d666900SdWiGhT $this->parser->_add_token(SEL_END, $selector, true); 401*7d666900SdWiGhT } 402*7d666900SdWiGhT 403*7d666900SdWiGhT if (intval($medium) < DEFAULT_AT) { 404*7d666900SdWiGhT // un medium vide (contenant @font-face ou autre @) ne produit aucun conteneur 405*7d666900SdWiGhT if (strlen(trim($medium))) { 406*7d666900SdWiGhT $parts_to_close = explode('{', $medium); 407*7d666900SdWiGhT foreach (array_reverse($parts_to_close) as $part) { 408*7d666900SdWiGhT $this->parser->_add_token(AT_END, $part, true); 409*7d666900SdWiGhT } 410*7d666900SdWiGhT } 411*7d666900SdWiGhT } elseif ($default_media) { 412*7d666900SdWiGhT $this->parser->_add_token(AT_END, $default_media, true); 413*7d666900SdWiGhT } 414*7d666900SdWiGhT } 415*7d666900SdWiGhT } 416*7d666900SdWiGhT 417*7d666900SdWiGhT /** 418*7d666900SdWiGhT * Same as htmlspecialchars, only that chars are not replaced if $plain !== true. This makes print_code() cleaner. 419*7d666900SdWiGhT * @param string $string 420*7d666900SdWiGhT * @param bool $plain 421*7d666900SdWiGhT * @return string 422*7d666900SdWiGhT * @see csstidy_print::_print() 423*7d666900SdWiGhT * @access private 424*7d666900SdWiGhT * @version 1.0 425*7d666900SdWiGhT */ 426*7d666900SdWiGhT public function _htmlsp($string, $plain) { 427*7d666900SdWiGhT if (!$plain) { 428*7d666900SdWiGhT return htmlspecialchars($string, ENT_QUOTES, 'utf-8'); 429*7d666900SdWiGhT } 430*7d666900SdWiGhT return $string; 431*7d666900SdWiGhT } 432*7d666900SdWiGhT 433*7d666900SdWiGhT /** 434*7d666900SdWiGhT * Get compression ratio 435*7d666900SdWiGhT * @access public 436*7d666900SdWiGhT * @return float 437*7d666900SdWiGhT * @version 1.2 438*7d666900SdWiGhT */ 439*7d666900SdWiGhT public function get_ratio() { 440*7d666900SdWiGhT if (!$this->output_css_plain) { 441*7d666900SdWiGhT $this->formatted(); 442*7d666900SdWiGhT } 443*7d666900SdWiGhT return round((strlen($this->input_css) - strlen($this->output_css_plain)) / strlen($this->input_css), 3) * 100; 444*7d666900SdWiGhT } 445*7d666900SdWiGhT 446*7d666900SdWiGhT /** 447*7d666900SdWiGhT * Get difference between the old and new code in bytes and prints the code if necessary. 448*7d666900SdWiGhT * @access public 449*7d666900SdWiGhT * @return string 450*7d666900SdWiGhT * @version 1.1 451*7d666900SdWiGhT */ 452*7d666900SdWiGhT public function get_diff() { 453*7d666900SdWiGhT if (!$this->output_css_plain) { 454*7d666900SdWiGhT $this->formatted(); 455*7d666900SdWiGhT } 456*7d666900SdWiGhT 457*7d666900SdWiGhT $diff = strlen($this->output_css_plain) - strlen($this->input_css); 458*7d666900SdWiGhT 459*7d666900SdWiGhT if ($diff > 0) { 460*7d666900SdWiGhT return '+' . $diff; 461*7d666900SdWiGhT } elseif ($diff == 0) { 462*7d666900SdWiGhT return '+-' . $diff; 463*7d666900SdWiGhT } 464*7d666900SdWiGhT 465*7d666900SdWiGhT return $diff; 466*7d666900SdWiGhT } 467*7d666900SdWiGhT 468*7d666900SdWiGhT /** 469*7d666900SdWiGhT * Get the size of either input or output CSS in KB 470*7d666900SdWiGhT * @param string $loc default is "output" 471*7d666900SdWiGhT * @access public 472*7d666900SdWiGhT * @return integer 473*7d666900SdWiGhT * @version 1.0 474*7d666900SdWiGhT */ 475*7d666900SdWiGhT public function size($loc = 'output') { 476*7d666900SdWiGhT if ($loc === 'output' && !$this->output_css) { 477*7d666900SdWiGhT $this->formatted(); 478*7d666900SdWiGhT } 479*7d666900SdWiGhT 480*7d666900SdWiGhT if ($loc === 'input') { 481*7d666900SdWiGhT return (strlen($this->input_css) / 1000); 482*7d666900SdWiGhT } else { 483*7d666900SdWiGhT return (strlen($this->output_css_plain) / 1000); 484*7d666900SdWiGhT } 485*7d666900SdWiGhT } 486*7d666900SdWiGhT 487*7d666900SdWiGhT} 488