<?php 







$excludeFilesArrayTop = explode(',',$excludeFiles);

$excludeFilesArrayBottom = explode(',',$bottomexcludeFiles);





function getBrowser() {

/* If browser calls */

$br = strtolower($_SERVER['HTTP_USER_AGENT']);

$browser = "other";



if(strrpos($br,"msie 6") > 1) {

$browser = "ie6";} 



if(strrpos($br,"msie 7") > 1) {

$browser = "ie7";} 



if(strrpos($br,"msie 8") > 1) {

$browser = "ie8";} 



if(strrpos($br,"msie 9") > 1) {

$browser = "ie9";} 



if(strrpos($br,"opera") > 1) {

$browser = "opera";} 



return $browser;

}



function removepath($css){

	

	$css = str_replace('../../','../',$css);

	return $css;

}



function md5_of_dir($folder) {

  $dircontent = scandir($folder);

  $ret='';

  foreach($dircontent as $filename) {

    if ($filename != '.' && $filename != '..') {

      if (@filemtime($folder.$filename) === false) return false;

      $ret.=date("YmdHis", @filemtime($folder.$filename)).$filename;

    }

  }

  return md5($ret);

}



function delete_old_md5s($folder,$name,$cachetime = 3600) {

  $olddate=time()-$cachetime;

  if(!file_exists($folder.$name)) return true;

  if (@filemtime($folder.$name) && @filemtime($folder.$name)<$olddate) { 

	 unlink($folder.$name);	

	 return true;

  }	

  return false; 

}



  

	function getArray($content,$regex) {  

		preg_match_all($regex,$content,$jsfiles);

		return $jsfiles[1];     

	}  

	function removeblankLinks($content){

			

			

		$stringArray[] = '<link rel="stylesheet" href="/vertex/" type="text/css" />';

		

		$stringArray[] = '<link rel="stylesheet" href="" type="text/css" />';

		

		$stringArray[] = '<link href="" rel="stylesheet" type="text/css" />';

		

		$stringArray[] = '<link rel="stylesheet" type="text/css" href="" />';

		

		$stringArray[] = '<script type="text/javascript" src=""></script>';

		

		foreach($stringArray as $string){

			$content = str_replace($string,'',$content);	

		}

		$content = preg_replace('/^\s+|\s+$/m', '', $content);

	

	

	return $content;

	

	}

















class JSMin {

  const ORD_LF            = 10;

  const ORD_SPACE         = 32;

  const ACTION_KEEP_A     = 1;

  const ACTION_DELETE_A   = 2;

  const ACTION_DELETE_A_B = 3;



  protected $a           = '';

  protected $b           = '';

  protected $input       = '';

  protected $inputIndex  = 0;

  protected $inputLength = 0;

  protected $lookAhead   = null;

  protected $output      = '';



  // -- Public Static Methods --------------------------------------------------



  /**

   * Minify Javascript

   *

   * @uses __construct()

   * @uses min()

   * @param string $js Javascript to be minified

   * @return string

   */

  public static function minify($js) {

    $jsmin = new JSMin($js);

    return $jsmin->min();

  }



  // -- Public Instance Methods ------------------------------------------------



  /**

   * Constructor

   *

   * @param string $input Javascript to be minified

   */

  public function __construct($input) {

    $this->input       = str_replace("\r\n", "\n", $input);

    $this->inputLength = strlen($this->input);

  }



  // -- Protected Instance Methods ---------------------------------------------



  /**

   * Action -- do something! What to do is determined by the $command argument.

   *

   * action treats a string as a single character. Wow!

   * action recognizes a regular expression if it is preceded by ( or , or =.

   *

   * @uses next()

   * @uses get()

   * @throws JSMinException If parser errors are found:

   *         - Unterminated string literal

   *         - Unterminated regular expression set in regex literal

   *         - Unterminated regular expression literal

   * @param int $command One of class constants:

   *      ACTION_KEEP_A      Output A. Copy B to A. Get the next B.

   *      ACTION_DELETE_A    Copy B to A. Get the next B. (Delete A).

   *      ACTION_DELETE_A_B  Get the next B. (Delete B).

  */

  protected function action($command) {

    switch($command) {

      case self::ACTION_KEEP_A:

        $this->output .= $this->a;



      case self::ACTION_DELETE_A:

        $this->a = $this->b;



        if ($this->a === "'" || $this->a === '"') {

          for (;;) {

            $this->output .= $this->a;

            $this->a       = $this->get();



            if ($this->a === $this->b) {

              break;

            }



            if (ord($this->a) <= self::ORD_LF) {

              throw new JSMinException('Unterminated string literal.');

            }



            if ($this->a === '\\') {

              $this->output .= $this->a;

              $this->a       = $this->get();

            }

          }

        }



      case self::ACTION_DELETE_A_B:

        $this->b = $this->next();



        if ($this->b === '/' && (

            $this->a === '(' || $this->a === ',' || $this->a === '=' ||

            $this->a === ':' || $this->a === '[' || $this->a === '!' ||

            $this->a === '&' || $this->a === '|' || $this->a === '?' ||

            $this->a === '{' || $this->a === '}' || $this->a === ';' ||

            $this->a === "\n" )) {



          $this->output .= $this->a . $this->b;



          for (;;) {

            $this->a = $this->get();



            if ($this->a === '[') {

              /*

                inside a regex [...] set, which MAY contain a '/' itself. Example: mootools Form.Validator near line 460:

                  return Form.Validator.getValidator('IsEmpty').test(element) || (/^(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]\.?){0,63}[a-z0-9!#$%&'*+/=?^_`{|}~-]@(?:(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\.)*[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?|\[(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\])$/i).test(element.get('value'));

              */

              for (;;) {

                $this->output .= $this->a;

                $this->a = $this->get();



                if ($this->a === ']') {

                    break;

                } elseif ($this->a === '\\') {

                  $this->output .= $this->a;

                  $this->a       = $this->get();

                } elseif (ord($this->a) <= self::ORD_LF) {

                  throw new JSMinException('Unterminated regular expression set in regex literal.');

                }

              }

            } elseif ($this->a === '/') {

              break;

            } elseif ($this->a === '\\') {

              $this->output .= $this->a;

              $this->a       = $this->get();

            } elseif (ord($this->a) <= self::ORD_LF) {

              throw new JSMinException('Unterminated regular expression literal.');

            }



            $this->output .= $this->a;

          }



          $this->b = $this->next();

        }

    }

  }



  /**

   * Get next char. Convert ctrl char to space.

   *

   * @return string|null

   */

  protected function get() {

    $c = $this->lookAhead;

    $this->lookAhead = null;



    if ($c === null) {

      if ($this->inputIndex < $this->inputLength) {

        $c = substr($this->input, $this->inputIndex, 1);

        $this->inputIndex += 1;

      } else {

        $c = null;

      }

    }



    if ($c === "\r") {

      return "\n";

    }



    if ($c === null || $c === "\n" || ord($c) >= self::ORD_SPACE) {

      return $c;

    }



    return ' ';

  }



  /**

   * Is $c a letter, digit, underscore, dollar sign, or non-ASCII character.

   *

   * @return bool

   */

  protected function isAlphaNum($c) {

    return ord($c) > 126 || $c === '\\' || preg_match('/^[\w\$]$/', $c) === 1;

  }



  /**

   * Perform minification, return result

   *

   * @uses action()

   * @uses isAlphaNum()

   * @uses get()

   * @uses peek()

   * @return string

   */

  protected function min() {

    if (0 == strncmp($this->peek(), "\xef", 1)) {

        $this->get();

        $this->get();

        $this->get();

    } 



    $this->a = "\n";

    $this->action(self::ACTION_DELETE_A_B);



    while ($this->a !== null) {

      switch ($this->a) {

        case ' ':

          if ($this->isAlphaNum($this->b)) {

            $this->action(self::ACTION_KEEP_A);

          } else {

            $this->action(self::ACTION_DELETE_A);

          }

          break;



        case "\n":

          switch ($this->b) {

            case '{':

            case '[':

            case '(':

            case '+':

            case '-':

            case '!':

            case '~':

              $this->action(self::ACTION_KEEP_A);

              break;



            case ' ':

              $this->action(self::ACTION_DELETE_A_B);

              break;



            default:

              if ($this->isAlphaNum($this->b)) {

                $this->action(self::ACTION_KEEP_A);

              }

              else {

                $this->action(self::ACTION_DELETE_A);

              }

          }

          break;



        default:

          switch ($this->b) {

            case ' ':

              if ($this->isAlphaNum($this->a)) {

                $this->action(self::ACTION_KEEP_A);

                break;

              }



              $this->action(self::ACTION_DELETE_A_B);

              break;



            case "\n":

              switch ($this->a) {

                case '}':

                case ']':

                case ')':

                case '+':

                case '-':

                case '"':

                case "'":

                  $this->action(self::ACTION_KEEP_A);

                  break;



                default:

                  if ($this->isAlphaNum($this->a)) {

                    $this->action(self::ACTION_KEEP_A);

                  }

                  else {

                    $this->action(self::ACTION_DELETE_A_B);

                  }

              }

              break;



            default:

              $this->action(self::ACTION_KEEP_A);

              break;

          }

      }

    }



    return $this->output;

  }



  /**

   * Get the next character, skipping over comments. peek() is used to see

   *  if a '/' is followed by a '/' or '*'.

   *

   * @uses get()

   * @uses peek()

   * @throws JSMinException On unterminated comment.

   * @return string

   */

  protected function next() {

    $c = $this->get();



    if ($c === '/') {

      switch($this->peek()) {

        case '/':

          for (;;) {

            $c = $this->get();



            if (ord($c) <= self::ORD_LF) {

              return $c;

            }

          }



        case '*':

          $this->get();



          for (;;) {

            switch($this->get()) {

              case '*':

                if ($this->peek() === '/') {

                  $this->get();

                  return ' ';

                }

                break;



              case null:

                throw new JSMinException('Unterminated comment.');

            }

          }



        default:

          return $c;

      }

    }



    return $c;

  }



  /**

   * Get next char. If is ctrl character, translate to a space or newline.

   *

   * @uses get()

   * @return string|null

   */

  protected function peek() {

    $this->lookAhead = $this->get();

    return $this->lookAhead;

  }

}



// -- Exceptions ---------------------------------------------------------------

class JSMinException extends Exception {}





abstract class aCssToken

	{

	/**

	 * Returns the token as string.

	 * 

	 * @return string

	 */

	abstract public function __toString();

	}



/**

 * Abstract definition of a for a ruleset start token.

 *

 * @package		CssMin/Tokens

 * @link		http://code.google.com/p/cssmin/

 * @author		Joe Scylla <joe.scylla@gmail.com>

 * @copyright	2008 - 2011 Joe Scylla <joe.scylla@gmail.com>

 * @license		http://opensource.org/licenses/mit-license.php MIT License

 * @version		3.0.1

 */

abstract class aCssRulesetStartToken extends aCssToken

	{

	

	}



/**

 * Abstract definition of a for ruleset end token.

 *

 * @package		CssMin/Tokens

 * @link		http://code.google.com/p/cssmin/

 * @author		Joe Scylla <joe.scylla@gmail.com>

 * @copyright	2008 - 2011 Joe Scylla <joe.scylla@gmail.com>

 * @license		http://opensource.org/licenses/mit-license.php MIT License

 * @version		3.0.1

 */

abstract class aCssRulesetEndToken extends aCssToken

	{

	/**

	 * Implements {@link aCssToken::__toString()}.

	 * 

	 * @return string

	 */

	public function __toString()

		{

		return "}";

		}

	}



/**

 * Abstract definition of a parser plugin.

 * 

 * Every parser plugin have to extend this class. A parser plugin contains the logic to parse one or aspects of a 

 * stylesheet.

 * 

 * @package		CssMin/Parser/Plugins

 * @link		http://code.google.com/p/cssmin/

 * @author		Joe Scylla <joe.scylla@gmail.com>

 * @copyright	2008 - 2011 Joe Scylla <joe.scylla@gmail.com>

 * @license		http://opensource.org/licenses/mit-license.php MIT License

 * @version		3.0.1

 */

abstract class aCssParserPlugin

	{

	/**

	 * Plugin configuration.

	 * 

	 * @var array

	 */

	protected $configuration = array();

	/**

	 * The CssParser of the plugin.

	 * 

	 * @var CssParser

	 */

	protected $parser = null;

	/**

	 * Plugin buffer.

	 * 

	 * @var string

	 */

	protected $buffer = "";

	/**

	 * Constructor.

	 * 

	 * @param CssParser $parser The CssParser object of this plugin.

	 * @param array $configuration Plugin configuration [optional]

	 * @return void

	 */

	public function __construct(CssParser $parser, array $configuration = null)

		{

		$this->configuration	= $configuration;

		$this->parser			= $parser;

		}

	/**

	 * Returns the array of chars triggering the parser plugin.

	 * 

	 * @return array

	 */

	abstract public function getTriggerChars();

	/**

	 * Returns the array of states triggering the parser plugin or FALSE if every state will trigger the parser plugin.

	 * 

	 * @return array

	 */

	abstract public function getTriggerStates();

	/**

	 * Parser routine of the plugin.

	 * 

	 * @param integer $index Current index

	 * @param string $char Current char

	 * @param string $previousChar Previous char

	 * @return mixed TRUE will break the processing; FALSE continue with the next plugin; integer set a new index and break the processing

	 */

	abstract public function parse($index, $char, $previousChar, $state);

	}



/**

 * Abstract definition of a minifier plugin class. 

 * 

 * Minifier plugin process the parsed tokens one by one to apply changes to the token. Every minifier plugin has to 

 * extend this class.

 *

 * @package		CssMin/Minifier/Plugins

 * @link		http://code.google.com/p/cssmin/

 * @author		Joe Scylla <joe.scylla@gmail.com>

 * @copyright	2008 - 2011 Joe Scylla <joe.scylla@gmail.com>

 * @license		http://opensource.org/licenses/mit-license.php MIT License

 * @version		3.0.1

 */

abstract class aCssMinifierPlugin

	{

	/**

	 * Plugin configuration.

	 * 

	 * @var array

	 */

	protected $configuration = array();

	/**

	 * The CssMinifier of the plugin.

	 * 

	 * @var CssMinifier

	 */

	protected $minifier = null;

	/**

	 * Constructor.

	 * 

	 * @param CssMinifier $minifier The CssMinifier object of this plugin.

	 * @param array $configuration Plugin configuration [optional]

	 * @return void

	 */

	public function __construct(CssMinifier $minifier, array $configuration = array())

		{

		$this->configuration	= $configuration;

		$this->minifier			= $minifier;

		}

	/**



	 * Apply the plugin to the token.

	 * 

	 * @param aCssToken $token Token to process

	 * @return boolean Return TRUE to break the processing of this token; FALSE to continue

	 */

	abstract public function apply(aCssToken &$token);

	/**

	 * --

	 * 

	 * @return array

	 */

	abstract public function getTriggerTokens();

	}



/**

 * Abstract definition of a minifier filter class. 

 * 

 * Minifier filters allows a pre-processing of the parsed token to add, edit or delete tokens. Every minifier filter

 * has to extend this class.

 * 

 * @package		CssMin/Minifier/Filters

 * @link		http://code.google.com/p/cssmin/

 * @author		Joe Scylla <joe.scylla@gmail.com>

 * @copyright	2008 - 2011 Joe Scylla <joe.scylla@gmail.com>

 * @license		http://opensource.org/licenses/mit-license.php MIT License

 * @version		3.0.1

 */

abstract class aCssMinifierFilter

	{

	/**

	 * Filter configuration.

	 * 

	 * @var array

	 */

	protected $configuration = array();

	/**

	 * The CssMinifier of the filter.

	 * 

	 * @var CssMinifier

	 */

	protected $minifier = null;

	/**

	 * Constructor.

	 * 

	 * @param CssMinifier $minifier The CssMinifier object of this plugin.

	 * @param array $configuration Filter configuration [optional]

	 * @return void

	 */

	public function __construct(CssMinifier $minifier, array $configuration = array())

		{

		$this->configuration	= $configuration;

		$this->minifier			= $minifier;

		}

	/**

	 * Filter the tokens.

	 * 

	 * @param array $tokens Array of objects of type aCssToken

	 * @return integer Count of added, changed or removed tokens; a return value large than 0 will rebuild the array

	 */

	abstract public function apply(array &$tokens);

	}



/**

 * Abstract formatter definition.

 * 

 * Every formatter have to extend this class.

 * 

 * @package		CssMin/Formatter

 * @link		http://code.google.com/p/cssmin/

 * @author		Joe Scylla <joe.scylla@gmail.com>

 * @copyright	2008 - 2011 Joe Scylla <joe.scylla@gmail.com>

 * @license		http://opensource.org/licenses/mit-license.php MIT License

 * @version		3.0.1

 */

abstract class aCssFormatter

	{

	/**

	 * Indent string.

	 * 

	 * @var string

	 */

	protected $indent = "    ";

	/**

	 * Declaration padding.

	 * 

	 * @var integer

	 */

	protected $padding = 0;

	/**

	 * Tokens.

	 * 

	 * @var array

	 */

	protected $tokens = array();

	/**

	 * Constructor.

	 * 

	 * @param array $tokens Array of CssToken

	 * @param string $indent Indent string [optional]

	 * @param integer $padding Declaration value padding [optional]

	 */

	public function __construct(array $tokens, $indent = null, $padding = null)

		{

		$this->tokens	= $tokens;

		$this->indent	= !is_null($indent) ? $indent : $this->indent;

		$this->padding	= !is_null($padding) ? $padding : $this->padding;

		}

	/**

	 * Returns the array of aCssToken as formatted string.

	 * 

	 * @return string

	 */

	abstract public function __toString();

	}



/**

 * Abstract definition of a ruleset declaration token.

 *

 * @package		CssMin/Tokens

 * @link		http://code.google.com/p/cssmin/

 * @author		Joe Scylla <joe.scylla@gmail.com>

 * @copyright	2008 - 2011 Joe Scylla <joe.scylla@gmail.com>

 * @license		http://opensource.org/licenses/mit-license.php MIT License

 * @version		3.0.1

 */

abstract class aCssDeclarationToken extends aCssToken

	{

	/**

	 * Is the declaration flagged as important?

	 * 

	 * @var boolean

	 */

	public $IsImportant = false;

	/**

	 * Is the declaration flagged as last one of the ruleset?

	 * 

	 * @var boolean

	 */

	public $IsLast = false;

	/**

	 * Property name of the declaration.

	 * 

	 * @var string

	 */

	public $Property = "";

	/**

	 * Value of the declaration.

	 * 

	 * @var string

	 */

	public $Value = "";

	/**

	 * Set the properties of the @font-face declaration. 

	 * 

	 * @param string $property Property of the declaration

	 * @param string $value Value of the declaration

	 * @param boolean $isImportant Is the !important flag is set?

	 * @param boolean $IsLast Is the declaration the last one of the block?

	 * @return void

	 */

	public function __construct($property, $value, $isImportant = false, $isLast = false)

		{

		$this->Property		= $property;

		$this->Value		= $value;

		$this->IsImportant	= $isImportant;

		$this->IsLast		= $isLast;

		}

	/**

	 * Implements {@link aCssToken::__toString()}.

	 * 

	 * @return string

	 */

	public function __toString()

		{

		return $this->Property . ":" . $this->Value . ($this->IsImportant ? " !important" : "") . ($this->IsLast ? "" : ";");

		}

	}



/**

 * Abstract definition of a for at-rule block start token.

 *

 * @package		CssMin/Tokens

 * @link		http://code.google.com/p/cssmin/

 * @author		Joe Scylla <joe.scylla@gmail.com>

 * @copyright	2008 - 2011 Joe Scylla <joe.scylla@gmail.com>

 * @license		http://opensource.org/licenses/mit-license.php MIT License

 * @version		3.0.1

 */

abstract class aCssAtBlockStartToken extends aCssToken

	{

	

	}



/**

 * Abstract definition of a for at-rule block end token.

 *

 * @package		CssMin/Tokens

 * @link		http://code.google.com/p/cssmin/

 * @author		Joe Scylla <joe.scylla@gmail.com>

 * @copyright	2008 - 2011 Joe Scylla <joe.scylla@gmail.com>

 * @license		http://opensource.org/licenses/mit-license.php MIT License

 * @version		3.0.1

 */

abstract class aCssAtBlockEndToken extends aCssToken

	{

	/**

	 * Implements {@link aCssToken::__toString()}.

	 * 

	 * @return string

	 */

	public function __toString()

		{

		return "}";

		}

	}



/**

 * {@link aCssFromatter Formatter} returning the CSS source in {@link http://goo.gl/etzLs Whitesmiths indent style}.

 * 

 * @package		CssMin/Formatter

 * @link		http://code.google.com/p/cssmin/

 * @author		Joe Scylla <joe.scylla@gmail.com>

 * @copyright	2008 - 2011 Joe Scylla <joe.scylla@gmail.com>

 * @license		http://opensource.org/licenses/mit-license.php MIT License

 * @version		3.0.1

 */

class CssWhitesmithsFormatter extends aCssFormatter

	{

	/**

	 * Implements {@link aCssFormatter::__toString()}.

	 * 

	 * @return string

	 */

	public function __toString()

		{

		$r				= array();

		$level			= 0;

		for ($i = 0, $l = count($this->tokens); $i < $l; $i++)

			{

			$token		= $this->tokens[$i];

			$class		= get_class($token);

			$indent 	= str_repeat($this->indent, $level);

			if ($class === "CssCommentToken")

				{

				$lines = array_map("trim", explode("\n", $token->Comment));

				for ($ii = 0, $ll = count($lines); $ii < $ll; $ii++)

					{

					$r[] = $indent . (substr($lines[$ii], 0, 1) == "*" ? " " : "") . $lines[$ii];

					}

				}

			elseif ($class === "CssAtCharsetToken")

				{

				$r[] = $indent . "@charset " . $token->Charset . ";";

				}

			elseif ($class === "CssAtFontFaceStartToken")

				{

				$r[] = $indent . "@font-face";

				$r[] = $this->indent . $indent . "{";

				$level++;

				}

			elseif ($class === "CssAtImportToken")

				{

				$r[] = $indent . "@import " . $token->Import . " " . implode(", ", $token->MediaTypes) . ";";

				}

			elseif ($class === "CssAtKeyframesStartToken")

				{

				$r[] = $indent . "@keyframes \"" . $token->Name . "\"";

				$r[] = $this->indent . $indent . "{";

				$level++;

				}

			elseif ($class === "CssAtMediaStartToken")

				{

				$r[] = $indent . "@media " . implode(", ", $token->MediaTypes);

				$r[] = $this->indent . $indent . "{";

				$level++;

				}

			elseif ($class === "CssAtPageStartToken")

				{

				$r[] = $indent . "@page";

				$r[] = $this->indent . $indent . "{";

				$level++;

				}

			elseif ($class === "CssAtVariablesStartToken")

				{

				$r[] = $indent . "@variables " . implode(", ", $token->MediaTypes);

				$r[] = $this->indent . $indent . "{";

				$level++;

				}

			elseif ($class === "CssRulesetStartToken" || $class === "CssAtKeyframesRulesetStartToken")

				{

				$r[] = $indent . implode(", ", $token->Selectors);

				$r[] = $this->indent . $indent . "{";

				$level++;

				}

			elseif ($class == "CssAtFontFaceDeclarationToken"

				|| $class === "CssAtKeyframesRulesetDeclarationToken"

				|| $class === "CssAtPageDeclarationToken"

				|| $class == "CssAtVariablesDeclarationToken"

				|| $class === "CssRulesetDeclarationToken"

				)

				{

				$declaration = $indent . $token->Property . ": ";

				if ($this->padding)

					{

					$declaration = str_pad($declaration, $this->padding, " ", STR_PAD_RIGHT);

					}

				$r[] = $declaration . $token->Value . ($token->IsImportant ? " !important" : "") . ";";

				}

			elseif ($class === "CssAtFontFaceEndToken"

				|| $class === "CssAtMediaEndToken"

				|| $class === "CssAtKeyframesEndToken"

				|| $class === "CssAtKeyframesRulesetEndToken"

				|| $class === "CssAtPageEndToken"

				|| $class === "CssAtVariablesEndToken"

				|| $class === "CssRulesetEndToken"

				)

				{

				$r[] = $indent . "}";

				$level--;

				}

			}

		return implode("\n", $r);

		}

	}



/**

 * This {@link aCssMinifierPlugin} will process var-statement and sets the declaration value to the variable value. 

 * 

 * This plugin only apply the variable values. The variable values itself will get parsed by the

 * {@link CssVariablesMinifierFilter}.

 * 

 * Example:

 * <code>

 * @variables

 * 		{

 * 		defaultColor: black;

 * 		}

 * color: var(defaultColor);

 * </code>

 * 

 * Will get converted to:

 * <code>

 * color:black;

 * </code>

 *

 * @package		CssMin/Minifier/Plugins

 * @link		http://code.google.com/p/cssmin/

 * @author		Joe Scylla <joe.scylla@gmail.com>

 * @copyright	2008 - 2011 Joe Scylla <joe.scylla@gmail.com>

 * @license		http://opensource.org/licenses/mit-license.php MIT License

 * @version		3.0.1

 */

class CssVariablesMinifierPlugin extends aCssMinifierPlugin

	{

	/**

	 * Regular expression matching a value.

	 * 

	 * @var string

	 */

	private $reMatch = "/var\((.+)\)/iSU";

	/**

	 * Parsed variables.

	 * 

	 * @var array

	 */

	private $variables = null;

	/**

	 * Returns the variables.

	 * 

	 * @return array

	 */

	public function getVariables()

		{

		return $this->variables;

		}

	/**

	 * Implements {@link aCssMinifierPlugin::minify()}.

	 * 

	 * @param aCssToken $token Token to process

	 * @return boolean Return TRUE to break the processing of this token; FALSE to continue

	 */

	public function apply(aCssToken &$token)

		{

		if (stripos($token->Value, "var") !== false && preg_match_all($this->reMatch, $token->Value, $m))

			{

			$mediaTypes	= $token->MediaTypes;

			if (!in_array("all", $mediaTypes))

				{

				$mediaTypes[] = "all";

				}

			for ($i = 0, $l = count($m[0]); $i < $l; $i++)

				{

				$variable	= trim($m[1][$i]);

				foreach ($mediaTypes as $mediaType)

					{

					if (isset($this->variables[$mediaType], $this->variables[$mediaType][$variable]))

						{

						// Variable value found => set the declaration value to the variable value and return

						$token->Value = str_replace($m[0][$i], $this->variables[$mediaType][$variable], $token->Value);

						continue 2;

						}

					}

				// If no value was found trigger an error and replace the token with a CssNullToken

				CssMin::triggerError(new CssError(__FILE__, __LINE__, __METHOD__ . ": No value found for variable <code>" . $variable . "</code> in media types <code>" . implode(", ", $mediaTypes) . "</code>", (string) $token));

				$token = new CssNullToken();

				return true;

				}

			}

		return false;

		}

	/**

	 * Implements {@link aMinifierPlugin::getTriggerTokens()}

	 * 

	 * @return array

	 */

	public function getTriggerTokens()

		{

		return array

			(

			"CssAtFontFaceDeclarationToken",

			"CssAtPageDeclarationToken",

			"CssRulesetDeclarationToken"

			);

		}

	/**

	 * Sets the variables.

	 * 

	 * @param array $variables Variables to set

	 * @return void

	 */

	public function setVariables(array $variables)

		{

		$this->variables = $variables;

		}

	}



/**

 * This {@link aCssMinifierFilter minifier filter} will parse the variable declarations out of @variables at-rule 

 * blocks. The variables will get store in the {@link CssVariablesMinifierPlugin} that will apply the variables to 

 * declaration.

 * 

 * @package		CssMin/Minifier/Filters

 * @link		http://code.google.com/p/cssmin/

 * @author		Joe Scylla <joe.scylla@gmail.com>

 * @copyright	2008 - 2011 Joe Scylla <joe.scylla@gmail.com>

 * @license		http://opensource.org/licenses/mit-license.php MIT License

 * @version		3.0.1

 */

class CssVariablesMinifierFilter extends aCssMinifierFilter

	{

	/**

	 * Implements {@link aCssMinifierFilter::filter()}.

	 * 

	 * @param array $tokens Array of objects of type aCssToken

	 * @return integer Count of added, changed or removed tokens; a return value large than 0 will rebuild the array

	 */

	public function apply(array &$tokens)

		{

		$variables			= array();

		$defaultMediaTypes	= array("all");

		$mediaTypes			= array();

		$remove				= array();

		for($i = 0, $l = count($tokens); $i < $l; $i++)

			{

			// @variables at-rule block found

			if (get_class($tokens[$i]) === "CssAtVariablesStartToken")

				{

				$remove[] = $i;

				$mediaTypes = (count($tokens[$i]->MediaTypes) == 0 ? $defaultMediaTypes : $tokens[$i]->MediaTypes);

				foreach ($mediaTypes as $mediaType)

					{

					if (!isset($variables[$mediaType]))

						{

						$variables[$mediaType] = array();

						}

					}

				// Read the variable declaration tokens

				for($i = $i; $i < $l; $i++)

					{

					// Found a variable declaration => read the variable values

					if (get_class($tokens[$i]) === "CssAtVariablesDeclarationToken")

						{

						foreach ($mediaTypes as $mediaType)

							{

							$variables[$mediaType][$tokens[$i]->Property] = $tokens[$i]->Value;

							}

						$remove[] = $i;

						}

					// Found the variables end token => break;

					elseif (get_class($tokens[$i]) === "CssAtVariablesEndToken")

						{

						$remove[] = $i;

						break;

						}

					}

				}

			}

		// Variables in @variables at-rule blocks

		foreach($variables as $mediaType => $null)

			{

			foreach($variables[$mediaType] as $variable => $value)

				{

				// If a var() statement in a variable value found...

				if (stripos($value, "var") !== false && preg_match_all("/var\((.+)\)/iSU", $value, $m))

					{

					// ... then replace the var() statement with the variable values.

					for ($i = 0, $l = count($m[0]); $i < $l; $i++)

						{

						$variables[$mediaType][$variable] = str_replace($m[0][$i], (isset($variables[$mediaType][$m[1][$i]]) ? $variables[$mediaType][$m[1][$i]] : ""), $variables[$mediaType][$variable]);

						}

					}

				}

			}

		// Remove the complete @variables at-rule block

		foreach ($remove as $i)

			{

			$tokens[$i] = null;

			}

		if (!($plugin = $this->minifier->getPlugin("CssVariablesMinifierPlugin")))

			{

			CssMin::triggerError(new CssError(__FILE__, __LINE__, __METHOD__ . ": The plugin <code>CssVariablesMinifierPlugin</code> was not found but is required for <code>" . __CLASS__ . "</code>"));

			}

		else

			{

			$plugin->setVariables($variables);

			}

		return count($remove);

		}

	}



/**

 * {@link aCssParserPlugin Parser plugin} for preserve parsing url() values.

 * 

 * This plugin return no {@link aCssToken CssToken} but ensures that url() values will get parsed properly.

 * 

 * @package		CssMin/Parser/Plugins

 * @link		http://code.google.com/p/cssmin/

 * @author		Joe Scylla <joe.scylla@gmail.com>

 * @copyright	2008 - 2011 Joe Scylla <joe.scylla@gmail.com>

 * @license		http://opensource.org/licenses/mit-license.php MIT License

 * @version		3.0.1

 */

class CssUrlParserPlugin extends aCssParserPlugin

	{

	/**

	 * Implements {@link aCssParserPlugin::getTriggerChars()}.

	 * 

	 * @return array

	 */

	public function getTriggerChars()

		{

		return array("(", ")");

		}

	/**

	 * Implements {@link aCssParserPlugin::getTriggerStates()}.

	 * 

	 * @return array

	 */

	public function getTriggerStates()

		{

		return false;

		}

	/**

	 * Implements {@link aCssParserPlugin::parse()}.

	 * 

	 * @param integer $index Current index

	 * @param string $char Current char

	 * @param string $previousChar Previous char

	 * @return mixed TRUE will break the processing; FALSE continue with the next plugin; integer set a new index and break the processing

	 */

	public function parse($index, $char, $previousChar, $state)

		{

		// Start of string

		if ($char === "(" && strtolower(substr($this->parser->getSource(), $index - 3, 4)) === "url(" && $state !== "T_URL")

			{

			$this->parser->pushState("T_URL");

			$this->parser->setExclusive(__CLASS__);

			}

		// Escaped LF in url => remove escape backslash and LF

		elseif ($char === "\n" && $previousChar === "\\" && $state === "T_URL")

			{

			$this->parser->setBuffer(substr($this->parser->getBuffer(), 0, -2));

			}

		// Parse error: Unescaped LF in string literal

		elseif ($char === "\n" && $previousChar !== "\\" && $state === "T_URL")

			{

			$line = $this->parser->getBuffer();

			$this->parser->setBuffer(substr($this->parser->getBuffer(), 0, -1) . ")"); // Replace the LF with the url string delimiter

			$this->parser->popState();

			$this->parser->unsetExclusive();

			CssMin::triggerError(new CssError(__FILE__, __LINE__, __METHOD__ . ": Unterminated string literal", $line . "_"));

			}

		// End of string

		elseif ($char === ")" && $state === "T_URL")

			{

			$this->parser->popState();

			$this->parser->unsetExclusive();

			}

		else

			{

			return false;

			}

		return true;

		}

	}



/**

 * {@link aCssParserPlugin Parser plugin} for preserve parsing string values.

 * 

 * This plugin return no {@link aCssToken CssToken} but ensures that string values will get parsed properly.

 * 

 * @package		CssMin/Parser/Plugins

 * @link		http://code.google.com/p/cssmin/

 * @author		Joe Scylla <joe.scylla@gmail.com>

 * @copyright	2008 - 2011 Joe Scylla <joe.scylla@gmail.com>

 * @license		http://opensource.org/licenses/mit-license.php MIT License

 * @version		3.0.1

 */

class CssStringParserPlugin extends aCssParserPlugin

	{

	/**

	 * Current string delimiter char.

	 * 

	 * @var string

	 */

	private $delimiterChar = null;

	/**

	 * Implements {@link aCssParserPlugin::getTriggerChars()}.

	 * 

	 * @return array

	 */

	public function getTriggerChars()

		{

		return array("\"", "'", "\n");

		}

	/**

	 * Implements {@link aCssParserPlugin::getTriggerStates()}.

	 * 

	 * @return array

	 */

	public function getTriggerStates()

		{

		return false;

		}

	/**

	 * Implements {@link aCssParserPlugin::parse()}.

	 * 

	 * @param integer $index Current index

	 * @param string $char Current char

	 * @param string $previousChar Previous char

	 * @return mixed TRUE will break the processing; FALSE continue with the next plugin; integer set a new index and break the processing

	 */

	public function parse($index, $char, $previousChar, $state)

		{

		// Start of string

		if (($char === "\"" || $char === "'") && $state !== "T_STRING")

			{

			$this->delimiterChar = $char;

			$this->parser->pushState("T_STRING");

			$this->parser->setExclusive(__CLASS__);

			}

		// Escaped LF in string => remove escape backslash and LF

		elseif ($char === "\n" && $previousChar === "\\" && $state === "T_STRING")

			{

			$this->parser->setBuffer(substr($this->parser->getBuffer(), 0, -2));

			}

		// Parse error: Unescaped LF in string literal

		elseif ($char === "\n" && $previousChar !== "\\" && $state === "T_STRING")

			{

			$line = $this->parser->getBuffer();

			$this->parser->popState();

			$this->parser->unsetExclusive();

			$this->parser->setBuffer(substr($this->parser->getBuffer(), 0, -1) . $this->delimiterChar); // Replace the LF with the current string char

			CssMin::triggerError(new CssError(__FILE__, __LINE__, __METHOD__ . ": Unterminated string literal", $line . "_"));

			$this->delimiterChar = null;

			}

		// End of string

		elseif ($char === $this->delimiterChar && $state === "T_STRING")

			{

			// If the Previous char is a escape char count the amount of the previous escape chars. If the amount of 

			// escape chars is uneven do not end the string

			if ($previousChar == "\\")

				{

				$source	= $this->parser->getSource();

				$c		= 1;

				$i		= $index - 2;

				while (substr($source, $i, 1) === "\\")

					{

					$c++; $i--;

					}

				if ($c % 2)

					{

					return false;

					}

				}

			$this->parser->popState();

			$this->parser->unsetExclusive();

			$this->delimiterChar = null;

			}

		else

			{

			return false;

			}

		return true;

		}

	}



/**

 * This {@link aCssMinifierFilter minifier filter} sorts the ruleset declarations of a ruleset by name.

 * 

 * @package		CssMin/Minifier/Filters

 * @link		http://code.google.com/p/cssmin/

 * @author		Rowan Beentje <http://assanka.net>

 * @copyright	Rowan Beentje <http://assanka.net>

 * @license		http://opensource.org/licenses/mit-license.php MIT License

 * @version		3.0.1

 */

class CssSortRulesetPropertiesMinifierFilter extends aCssMinifierFilter

	{

	/**

	 * Implements {@link aCssMinifierFilter::filter()}.

	 * 

	 * @param array $tokens Array of objects of type aCssToken

	 * @return integer Count of added, changed or removed tokens; a return value larger than 0 will rebuild the array

	 */

	public function apply(array &$tokens)

		{

		$r = 0;

		for ($i = 0, $l = count($tokens); $i < $l; $i++)

			{

			// Only look for ruleset start rules

			if (get_class($tokens[$i]) !== "CssRulesetStartToken") { continue; }

			// Look for the corresponding ruleset end

			$endIndex = false;

			for ($ii = $i + 1; $ii < $l; $ii++)

				{

				if (get_class($tokens[$ii]) !== "CssRulesetEndToken") { continue; }

				$endIndex = $ii;

				break;

				}

			if (!$endIndex) { break; }

			$startIndex = $i;

			$i = $endIndex;

			// Skip if there's only one token in this ruleset

			if ($endIndex - $startIndex <= 2) { continue; }

			// Ensure that everything between the start and end is a declaration token, for safety

			for ($ii = $startIndex + 1; $ii < $endIndex; $ii++)

				{

				if (get_class($tokens[$ii]) !== "CssRulesetDeclarationToken") { continue(2); }

				}

			$declarations = array_slice($tokens, $startIndex + 1, $endIndex - $startIndex - 1);

			// Check whether a sort is required

			$sortRequired = $lastPropertyName = false;

			foreach ($declarations as $declaration)	

				{

				if ($lastPropertyName)

					{

					if (strcmp($lastPropertyName, $declaration->Property) > 0)

						{

						$sortRequired = true;

						break;

						}

					}

				$lastPropertyName = $declaration->Property;

				}

			if (!$sortRequired) { continue; }

			// Arrange the declarations alphabetically by name

			usort($declarations, array(__CLASS__, "userDefinedSort1"));

			// Update "IsLast" property

			for ($ii = 0, $ll = count($declarations) - 1; $ii <= $ll; $ii++)

				{

				if ($ii == $ll)

					{

					$declarations[$ii]->IsLast = true;

					}

				else

					{

					$declarations[$ii]->IsLast = false;

					}

				}

			// Splice back into the array.

			array_splice($tokens, $startIndex + 1, $endIndex - $startIndex - 1, $declarations);

			$r += $endIndex - $startIndex - 1;

			}

		return $r;

		}

	/**

	 * User defined sort function.

	 * 

	 * @return integer

	 */

	public static function userDefinedSort1($a, $b)

		{

		return strcmp($a->Property, $b->Property);

		}

	}



/**

 * This {@link aCssToken CSS token} represents the start of a ruleset.

 * 

 * @package		CssMin/Tokens

 * @link		http://code.google.com/p/cssmin/

 * @author		Joe Scylla <joe.scylla@gmail.com>

 * @copyright	2008 - 2011 Joe Scylla <joe.scylla@gmail.com>

 * @license		http://opensource.org/licenses/mit-license.php MIT License

 * @version		3.0.1

 */

class CssRulesetStartToken extends aCssRulesetStartToken

	{

	/**

	 * Array of selectors.

	 * 

	 * @var array

	 */

	public $Selectors = array();

	/**

	 * Set the properties of a ruleset token.

	 * 

	 * @param array $selectors Selectors of the ruleset 

	 * @return void

	 */

	public function __construct(array $selectors = array())

		{

		$this->Selectors = $selectors;

		}

	/**

	 * Implements {@link aCssToken::__toString()}.

	 * 

	 * @return string

	 */

	public function __toString()

		{

		return implode(",", $this->Selectors) . "{";

		}

	}



/**

 * {@link aCssParserPlugin Parser plugin} for parsing ruleset block with including declarations.

 * 

 * Found rulesets will add a {@link CssRulesetStartToken} and {@link CssRulesetEndToken} to the 

 * parser; including declarations as {@link CssRulesetDeclarationToken}.

 *

 * @package		CssMin/Parser/Plugins

 * @link		http://code.google.com/p/cssmin/

 * @author		Joe Scylla <joe.scylla@gmail.com>

 * @copyright	2008 - 2011 Joe Scylla <joe.scylla@gmail.com>

 * @license		http://opensource.org/licenses/mit-license.php MIT License

 * @version		3.0.1

 */

class CssRulesetParserPlugin extends aCssParserPlugin

	{

	/**

	 * Implements {@link aCssParserPlugin::getTriggerChars()}.

	 * 

	 * @return array

	 */

	public function getTriggerChars()

		{

		return array(",", "{", "}", ":", ";");

		}

	/**

	 * Implements {@link aCssParserPlugin::getTriggerStates()}.

	 * 

	 * @return array

	 */

	public function getTriggerStates()

		{

		return array("T_DOCUMENT", "T_AT_MEDIA", "T_RULESET::SELECTORS", "T_RULESET", "T_RULESET_DECLARATION");

		}

	/**

	 * Selectors.

	 * 

	 * @var array

	 */

	private $selectors = array();

	/**

	 * Implements {@link aCssParserPlugin::parse()}.

	 * 

	 * @param integer $index Current index

	 * @param string $char Current char

	 * @param string $previousChar Previous char

	 * @return mixed TRUE will break the processing; FALSE continue with the next plugin; integer set a new index and break the processing

	 */

	public function parse($index, $char, $previousChar, $state)

		{

		// Start of Ruleset and selectors

		if ($char === "," && ($state === "T_DOCUMENT" || $state === "T_AT_MEDIA" || $state === "T_RULESET::SELECTORS"))

			{

			if ($state !== "T_RULESET::SELECTORS")

				{

				$this->parser->pushState("T_RULESET::SELECTORS");

				}

			$this->selectors[] = $this->parser->getAndClearBuffer(",{");

			}

		// End of selectors and start of declarations

		elseif ($char === "{" && ($state === "T_DOCUMENT" || $state === "T_AT_MEDIA" || $state === "T_RULESET::SELECTORS"))

			{

			if ($this->parser->getBuffer() !== "")

				{

				$this->selectors[] = $this->parser->getAndClearBuffer(",{");

				if ($state == "T_RULESET::SELECTORS")

					{

					$this->parser->popState();

					}

				$this->parser->pushState("T_RULESET");

				$this->parser->appendToken(new CssRulesetStartToken($this->selectors));

				$this->selectors = array();

				}

			}

		// Start of declaration

		elseif ($char === ":" && $state === "T_RULESET")

			{

			$this->parser->pushState("T_RULESET_DECLARATION");

			$this->buffer = $this->parser->getAndClearBuffer(":;", true);

			}

		// Unterminated ruleset declaration

		elseif ($char === ":" && $state === "T_RULESET_DECLARATION")

			{

			// Ignore Internet Explorer filter declarations

			if ($this->buffer === "filter")

				{

				return false;

				}

			CssMin::triggerError(new CssError(__FILE__, __LINE__, __METHOD__ . ": Unterminated declaration", $this->buffer . ":" . $this->parser->getBuffer() . "_"));

			}

		// End of declaration

		elseif (($char === ";" || $char === "}") && $state === "T_RULESET_DECLARATION")

			{

			$value = $this->parser->getAndClearBuffer(";}");

			if (strtolower(substr($value, -10, 10)) === "!important")

				{

				$value = trim(substr($value, 0, -10));

				$isImportant = true;

				}

			else

				{

				$isImportant = false;

				}

			$this->parser->popState();

			$this->parser->appendToken(new CssRulesetDeclarationToken($this->buffer, $value, $this->parser->getMediaTypes(), $isImportant));

			// Declaration ends with a right curly brace; so we have to end the ruleset

			if ($char === "}")

				{

				$this->parser->appendToken(new CssRulesetEndToken());

				$this->parser->popState();

				}

			$this->buffer = "";

			}

		// End of ruleset

		elseif ($char === "}" && $state === "T_RULESET")

			{

			$this->parser->popState();

			$this->parser->clearBuffer();

			$this->parser->appendToken(new CssRulesetEndToken());

			$this->buffer = "";

			$this->selectors = array();

			}

		else

			{

			return false;

			}

		return true;

		}

	}



/**

 *  This {@link aCssToken CSS token} represents the end of a ruleset.

 *

 * @package		CssMin/Tokens

 * @link		http://code.google.com/p/cssmin/

 * @author		Joe Scylla <joe.scylla@gmail.com>

 * @copyright	2008 - 2011 Joe Scylla <joe.scylla@gmail.com>

 * @license		http://opensource.org/licenses/mit-license.php MIT License

 * @version		3.0.1

 */

class CssRulesetEndToken extends aCssRulesetEndToken

	{

	

	}



/**

 * This {@link aCssToken CSS token} represents a ruleset declaration.

 *

 * @package		CssMin/Tokens

 * @link		http://code.google.com/p/cssmin/

 * @author		Joe Scylla <joe.scylla@gmail.com>

 * @copyright	2008 - 2011 Joe Scylla <joe.scylla@gmail.com>

 * @license		http://opensource.org/licenses/mit-license.php MIT License

 * @version		3.0.1

 */

class CssRulesetDeclarationToken extends aCssDeclarationToken

	{

	/**

	 * Media types of the declaration.

	 * 

	 * @var array

	 */

	public $MediaTypes = array("all");

	/**

	 * Set the properties of a ddocument- or at-rule @media level declaration. 

	 * 

	 * @param string $property Property of the declaration

	 * @param string $value Value of the declaration

	 * @param mixed $mediaTypes Media types of the declaration

	 * @param boolean $isImportant Is the !important flag is set

	 * @param boolean $isLast Is the declaration the last one of the ruleset

	 * @return void

	 */

	public function __construct($property, $value, $mediaTypes = null, $isImportant = false, $isLast = false)

		{

		parent::__construct($property, $value, $isImportant, $isLast);

		$this->MediaTypes	= $mediaTypes ? $mediaTypes : array("all");

		}

	}



/**

 * This {@link aCssMinifierFilter minifier filter} sets the IsLast property of any last declaration in a ruleset, 

 * @font-face at-rule or @page at-rule block. If the property IsLast is TRUE the decrations will get stringified 

 * without tailing semicolon.

 * 

 * @package		CssMin/Minifier/Filters

 * @link		http://code.google.com/p/cssmin/

 * @author		Joe Scylla <joe.scylla@gmail.com>

 * @copyright	2008 - 2011 Joe Scylla <joe.scylla@gmail.com>

 * @license		http://opensource.org/licenses/mit-license.php MIT License

 * @version		3.0.1

 */

class CssRemoveLastDelarationSemiColonMinifierFilter extends aCssMinifierFilter

	{

	/**

	 * Implements {@link aCssMinifierFilter::filter()}.

	 * 

	 * @param array $tokens Array of objects of type aCssToken

	 * @return integer Count of added, changed or removed tokens; a return value large than 0 will rebuild the array

	 */

	public function apply(array &$tokens)

		{

		for ($i = 0, $l = count($tokens); $i < $l; $i++)

			{

			$current	= get_class($tokens[$i]);

			$next		= isset($tokens[$i+1]) ? get_class($tokens[$i+1]) : false;

			if (($current === "CssRulesetDeclarationToken" && $next === "CssRulesetEndToken") ||

				($current === "CssAtFontFaceDeclarationToken" && $next === "CssAtFontFaceEndToken") || 

				($current === "CssAtPageDeclarationToken" && $next === "CssAtPageEndToken"))

				{

				$tokens[$i]->IsLast = true;

				}

			}

		return 0;

		}

	}



/**

 * This {@link aCssMinifierFilter minifier filter} will remove any empty rulesets (including @keyframes at-rule block 

 * rulesets).

 *

 * @package		CssMin/Minifier/Filters

 * @link		http://code.google.com/p/cssmin/

 * @author		Joe Scylla <joe.scylla@gmail.com>

 * @copyright	2008 - 2011 Joe Scylla <joe.scylla@gmail.com>

 * @license		http://opensource.org/licenses/mit-license.php MIT License

 * @version		3.0.1

 */

class CssRemoveEmptyRulesetsMinifierFilter extends aCssMinifierFilter

	{

	/**

	 * Implements {@link aCssMinifierFilter::filter()}.

	 * 

	 * @param array $tokens Array of objects of type aCssToken

	 * @return integer Count of added, changed or removed tokens; a return value large than 0 will rebuild the array

	 */

	public function apply(array &$tokens)

		{

		$r = 0;

		for ($i = 0, $l = count($tokens); $i < $l; $i++)

			{

			$current	= get_class($tokens[$i]);

			$next		= isset($tokens[$i + 1]) ? get_class($tokens[$i + 1]) : false;

			if (($current === "CssRulesetStartToken" && $next === "CssRulesetEndToken") ||

				($current === "CssAtKeyframesRulesetStartToken" && $next === "CssAtKeyframesRulesetEndToken" && !array_intersect(array("from", "0%", "to", "100%"), array_map("strtolower", $tokens[$i]->Selectors)))

				)

				{

				$tokens[$i]		= null;

				$tokens[$i + 1]	= null;

				$i++;

				$r = $r + 2;

				}

			}

		return $r;

		}

	}



/**

 * This {@link aCssMinifierFilter minifier filter} will remove any empty @font-face, @keyframes, @media and @page 

 * at-rule blocks.

 * 

 * @package		CssMin/Minifier/Filters

 * @link		http://code.google.com/p/cssmin/

 * @author		Joe Scylla <joe.scylla@gmail.com>

 * @copyright	2008 - 2011 Joe Scylla <joe.scylla@gmail.com>

 * @license		http://opensource.org/licenses/mit-license.php MIT License

 * @version		3.0.1

 */

class CssRemoveEmptyAtBlocksMinifierFilter extends aCssMinifierFilter

	{

	/**

	 * Implements {@link aCssMinifierFilter::filter()}.

	 * 

	 * @param array $tokens Array of objects of type aCssToken

	 * @return integer Count of added, changed or removed tokens; a return value large than 0 will rebuild the array

	 */

	public function apply(array &$tokens)

		{

		$r = 0;

		for ($i = 0, $l = count($tokens); $i < $l; $i++)

			{

			$current	= get_class($tokens[$i]);

			$next		= isset($tokens[$i + 1]) ? get_class($tokens[$i + 1]) : false;

			if (($current === "CssAtFontFaceStartToken" && $next === "CssAtFontFaceEndToken") ||

				($current === "CssAtKeyframesStartToken" && $next === "CssAtKeyframesEndToken") ||

				($current === "CssAtPageStartToken" && $next === "CssAtPageEndToken") ||

				($current === "CssAtMediaStartToken" && $next === "CssAtMediaEndToken"))

				{

				$tokens[$i]		= null;

				$tokens[$i + 1]	= null;

				$i++;

				$r = $r + 2;

				}

			}

		return $r;

		}

	}



/**

 * This {@link aCssMinifierFilter minifier filter} will remove any comments from the array of parsed tokens.

 * 

 * @package		CssMin/Minifier/Filters

 * @link		http://code.google.com/p/cssmin/

 * @author		Joe Scylla <joe.scylla@gmail.com>

 * @copyright	2008 - 2011 Joe Scylla <joe.scylla@gmail.com>

 * @license		http://opensource.org/licenses/mit-license.php MIT License

 * @version		3.0.1

 */

class CssRemoveCommentsMinifierFilter extends aCssMinifierFilter

	{

	/**

	 * Implements {@link aCssMinifierFilter::filter()}.

	 * 

	 * @param array $tokens Array of objects of type aCssToken

	 * @return integer Count of added, changed or removed tokens; a return value large than 0 will rebuild the array

	 */

	public function apply(array &$tokens)

		{

		$r = 0;

		for ($i = 0, $l = count($tokens); $i < $l; $i++)

			{

			if (get_class($tokens[$i]) === "CssCommentToken")

				{

				$tokens[$i] = null;

				$r++;

				}

			}

		return $r;

		}

	}



/**

 * CSS Parser.

 * 

 * @package		CssMin/Parser

 * @link		http://code.google.com/p/cssmin/

 * @author		Joe Scylla <joe.scylla@gmail.com>

 * @copyright	2008 - 2011 Joe Scylla <joe.scylla@gmail.com>

 * @license		http://opensource.org/licenses/mit-license.php MIT License

 * @version		3.0.1

 */

class CssParser

	{

	/**

	 * Parse buffer.

	 * 

	 * @var string

	 */

	private $buffer = "";

	/**

	 * {@link aCssParserPlugin Plugins}.

	 * 

	 * @var array

	 */

	private $plugins = array();

	/**

	 * Source to parse.

	 * 

	 * @var string

	 */

	private $source = "";

	/**

	 * Current state.

	 * 

	 * @var integer

	 */

	private $state = "T_DOCUMENT";

	/**

	 * Exclusive state.

	 * 

	 * @var string

	 */

	private $stateExclusive = false;

	/**

	 * Media types state.

	 * 

	 * @var mixed

	 */

	private $stateMediaTypes = false;

	/**

	 * State stack.

	 * 

	 * @var array

	 */

	private $states = array("T_DOCUMENT");

	/**

	 * Parsed tokens.

	 * 

	 * @var array

	 */

	private $tokens = array();

	/**

	 * Constructer.

	 * 

	 *  Create instances of the used {@link aCssParserPlugin plugins}.

	 * 

	 * @param string $source CSS source [optional]

	 * @param array $plugins Plugin configuration [optional]

	 * @return void

	 */

	public function __construct($source = null, array $plugins = null)

		{

		$plugins = array_merge(array

			(

			"Comment"		=> true,

			"String"		=> true,

			"Url"			=> true,

			"Expression"	=> true,

			"Ruleset"		=> true,

			"AtCharset"		=> true,

			"AtFontFace"	=> true,

			"AtImport"		=> true,

			"AtKeyframes"	=> true,

			"AtMedia"		=> true,

			"AtPage"		=> true,

			"AtVariables"	=> true

			), is_array($plugins) ? $plugins : array());

		// Create plugin instances

		foreach ($plugins as $name => $config)

			{

			if ($config !== false)

				{

				$class	= "Css" . $name . "ParserPlugin";

				$config = is_array($config) ? $config : array();

				if (class_exists($class))

					{

					$this->plugins[] = new $class($this, $config);

					}

				else

					{

					CssMin::triggerError(new CssError(__FILE__, __LINE__, __METHOD__ . ": The plugin <code>" . $name . "</code> with the class name <code>" . $class . "</code> was not found"));

					}

				}

			}

		if (!is_null($source))

			{

			$this->parse($source);

			}

		}

	/**

	 * Append a token to the array of tokens.

	 * 

	 * @param aCssToken $token Token to append

	 * @return void

	 */

	public function appendToken(aCssToken $token)

		{

		$this->tokens[] = $token;

		}

	/**

	 * Clears the current buffer.

	 * 

	 * @return void

	 */

	public function clearBuffer()

		{

		$this->buffer = "";

		}

	/**

	 * Returns and clear the current buffer.

	 * 

	 * @param string $trim Chars to use to trim the returned buffer

	 * @param boolean $tolower if TRUE the returned buffer will get converted to lower case

	 * @return string

	 */

	public function getAndClearBuffer($trim = "", $tolower = false)

		{

		$r = $this->getBuffer($trim, $tolower);

		$this->buffer = "";

		return $r;

		}

	/**

	 * Returns the current buffer.

	 * 

	 * @param string $trim Chars to use to trim the returned buffer

	 * @param boolean $tolower if TRUE the returned buffer will get converted to lower case

	 * @return string

	 */

	public function getBuffer($trim = "", $tolower = false)

		{

		$r = $this->buffer;

		if ($trim)

			{

			$r = trim($r, " \t\n\r\0\x0B" . $trim);

			}

		if ($tolower)

			{

			$r = strtolower($r);

			}

		return $r;

		}

	/**

	 * Returns the current media types state.

	 * 

	 * @return array

	 */	

	public function getMediaTypes()

		{

		return $this->stateMediaTypes;

		}

	/**

	 * Returns the CSS source.

	 * 

	 * @return string

	 */

	public function getSource()

		{

		return $this->source;

		}

	/**

	 * Returns the current state.

	 * 

	 * @return integer The current state

	 */

	public function getState()

		{

		return $this->state;

		}

	/**

	 * Returns a plugin by class name.

	 * 

	 * @param string $name Class name of the plugin 

	 * @return aCssParserPlugin

	 */

	public function getPlugin($class)

		{

		static $index = null;

		if (is_null($index))

			{

			$index = array();

			for ($i = 0, $l = count($this->plugins); $i < $l; $i++)

				{

				$index[get_class($this->plugins[$i])] = $i;

				}

			}

		return isset($index[$class]) ? $this->plugins[$index[$class]] : false;

		}

	/**

	 * Returns the parsed tokens.

	 * 

	 * @return array

	 */

	public function getTokens()

		{

		return $this->tokens;

		}

	/**

	 * Returns if the current state equals the passed state.

	 * 

	 * @param integer $state State to compare with the current state

	 * @return boolean TRUE is the state equals to the passed state; FALSE if not

	 */

	public function isState($state)

		{

		return ($this->state == $state);

		}

	/**

	 * Parse the CSS source and return a array with parsed tokens.

	 * 

	 * @param string $source CSS source

	 * @return array Array with tokens

	 */

	public function parse($source)

		{

		// Reset

		$this->source = "";

		$this->tokens = array();

		// Create a global and plugin lookup table for trigger chars; set array of plugins as local variable and create 

		// several helper variables for plugin handling

		$globalTriggerChars		= "";

		$plugins				= $this->plugins;

		$pluginCount			= count($plugins);

		$pluginIndex			= array();

		$pluginTriggerStates	= array();

		$pluginTriggerChars		= array();

		for ($i = 0, $l = count($plugins); $i < $l; $i++)

			{

			$tPluginClassName				= get_class($plugins[$i]);

			$pluginTriggerChars[$i]			= implode("", $plugins[$i]->getTriggerChars());

			$tPluginTriggerStates			= $plugins[$i]->getTriggerStates();

			$pluginTriggerStates[$i]		= $tPluginTriggerStates === false ? false : "|" . implode("|", $tPluginTriggerStates) . "|";

			$pluginIndex[$tPluginClassName]	= $i;

			for ($ii = 0, $ll = strlen($pluginTriggerChars[$i]); $ii < $ll; $ii++)

				{

				$c = substr($pluginTriggerChars[$i], $ii, 1);

				if (strpos($globalTriggerChars, $c) === false)

					{

					$globalTriggerChars .= $c;

					}

				}

			}

		// Normalise line endings

		$source			= str_replace("\r\n", "\n", $source);	// Windows to Unix line endings

		$source			= str_replace("\r", "\n", $source);		// Mac to Unix line endings

		$this->source	= $source;

		// Variables

		$buffer			= &$this->buffer;

		$exclusive		= &$this->stateExclusive;

		$state			= &$this->state;

		$c = $p 		= null;

		// --

		for ($i = 0, $l = strlen($source); $i < $l; $i++)

			{

			// Set the current Char

			$c = $source[$i]; // Is faster than: $c = substr($source, $i, 1);

			// Normalize and filter double whitespace characters

			if ($exclusive === false)

				{

				if ($c === "\n" || $c === "\t")

					{

					$c = " ";

					}

				if ($c === " " && $p === " ")

					{

					continue;

					}

				}

			$buffer .= $c;

			// Extended processing only if the current char is a global trigger char

			if (strpos($globalTriggerChars, $c) !== false)

				{

				// Exclusive state is set; process with the exclusive plugin 

				if ($exclusive)

					{

					$tPluginIndex = $pluginIndex[$exclusive];

					if (strpos($pluginTriggerChars[$tPluginIndex], $c) !== false && ($pluginTriggerStates[$tPluginIndex] === false || strpos($pluginTriggerStates[$tPluginIndex], $state) !== false))

						{

						$r = $plugins[$tPluginIndex]->parse($i, $c, $p, $state);

						// Return value is TRUE => continue with next char

						if ($r === true)

							{

							continue;

							}

						// Return value is numeric => set new index and continue with next char

						elseif ($r !== false && $r != $i)

							{

							$i = $r;

							continue;

							}

						}

					}

				// Else iterate through the plugins

				else

					{

					$triggerState = "|" . $state . "|";

					for ($ii = 0, $ll = $pluginCount; $ii < $ll; $ii++)

						{

						// Only process if the current char is one of the plugin trigger chars

						if (strpos($pluginTriggerChars[$ii], $c) !== false && ($pluginTriggerStates[$ii] === false || strpos($pluginTriggerStates[$ii], $triggerState) !== false))

							{

							// Process with the plugin

							$r = $plugins[$ii]->parse($i, $c, $p, $state);

							// Return value is TRUE => break the plugin loop and and continue with next char

							if ($r === true)

								{

								break;

								}

							// Return value is numeric => set new index, break the plugin loop and and continue with next char

							elseif ($r !== false && $r != $i)

								{

								$i = $r;

								break;

								}

							}

						}

					}

				}

			$p = $c; // Set the parent char

			}

		return $this->tokens;

		}

	/**

	 * Remove the last state of the state stack and return the removed stack value.

	 * 

	 * @return integer Removed state value

	 */

	public function popState()

		{

		$r = array_pop($this->states);

		$this->state = $this->states[count($this->states) - 1];

		return $r;

		}

	/**

	 * Adds a new state onto the state stack.

	 * 

	 * @param integer $state State to add onto the state stack.

	 * @return integer The index of the added state in the state stacks

	 */

	public function pushState($state)

		{

		$r = array_push($this->states, $state);

		$this->state = $this->states[count($this->states) - 1];

		return $r;

		}

	/**

	 * Sets/restores the buffer.

	 * 

	 * @param string $buffer Buffer to set

	 * @return void

	 */	

	public function setBuffer($buffer)

		{

		$this->buffer = $buffer;

		}

	/**

	 * Set the exclusive state.

	 * 

	 * @param string $exclusive Exclusive state

	 * @return void

	 */	

	public function setExclusive($exclusive)

		{

		$this->stateExclusive = $exclusive; 

		}

	/**

	 * Set the media types state.

	 * 

	 * @param array $mediaTypes Media types state

	 * @return void

	 */	

	public function setMediaTypes(array $mediaTypes)

		{

		$this->stateMediaTypes = $mediaTypes; 

		}

	/**

	 * Sets the current state in the state stack; equals to {@link CssParser::popState()} + {@link CssParser::pushState()}.

	 * 

	 * @param integer $state State to set

	 * @return integer

	 */

	public function setState($state)

		{

		$r = array_pop($this->states);

		array_push($this->states, $state);

		$this->state = $this->states[count($this->states) - 1];

		return $r;

		}

	/**

	 * Removes the exclusive state.

	 * 

	 * @return void

	 */

	public function unsetExclusive()

		{

		$this->stateExclusive = false;

		}

	/**

	 * Removes the media types state.

	 * 

	 * @return void

	 */

	public function unsetMediaTypes()

		{

		$this->stateMediaTypes = false;

		}

	}



/**

 * {@link aCssFromatter Formatter} returning the CSS source in {@link http://goo.gl/j4XdU OTBS indent style} (The One True Brace Style).

 * 

 * @package		CssMin/Formatter

 * @link		http://code.google.com/p/cssmin/

 * @author		Joe Scylla <joe.scylla@gmail.com>

 * @copyright	2008 - 2011 Joe Scylla <joe.scylla@gmail.com>

 * @license		http://opensource.org/licenses/mit-license.php MIT License

 * @version		3.0.1

 */

class CssOtbsFormatter extends aCssFormatter

	{

	/**

	 * Implements {@link aCssFormatter::__toString()}.

	 * 

	 * @return string

	 */

	public function __toString()

		{

		$r				= array();

		$level			= 0;

		for ($i = 0, $l = count($this->tokens); $i < $l; $i++)

			{

			$token		= $this->tokens[$i];

			$class		= get_class($token);

			$indent 	= str_repeat($this->indent, $level);

			if ($class === "CssCommentToken")

				{

				$lines = array_map("trim", explode("\n", $token->Comment));

				for ($ii = 0, $ll = count($lines); $ii < $ll; $ii++)

					{

					$r[] = $indent . (substr($lines[$ii], 0, 1) == "*" ? " " : "") . $lines[$ii];

					}

				}

			elseif ($class === "CssAtCharsetToken")

				{

				$r[] = $indent . "@charset " . $token->Charset . ";";

				}

			elseif ($class === "CssAtFontFaceStartToken")

				{

				$r[] = $indent . "@font-face {";

				$level++;

				}

			elseif ($class === "CssAtImportToken")

				{

				$r[] = $indent . "@import " . $token->Import . " " . implode(", ", $token->MediaTypes) . ";";

				}

			elseif ($class === "CssAtKeyframesStartToken")

				{

				$r[] = $indent . "@keyframes \"" . $token->Name . "\" {";

				$level++;

				}

			elseif ($class === "CssAtMediaStartToken")

				{

				$r[] = $indent . "@media " . implode(", ", $token->MediaTypes) . " {";

				$level++;

				}

			elseif ($class === "CssAtPageStartToken")

				{

				$r[] = $indent . "@page {";

				$level++;

				}

			elseif ($class === "CssAtVariablesStartToken")

				{

				$r[] = $indent . "@variables " . implode(", ", $token->MediaTypes) . " {";

				$level++;

				}

			elseif ($class === "CssRulesetStartToken" || $class === "CssAtKeyframesRulesetStartToken")

				{

				$r[] = $indent . implode(", ", $token->Selectors) . " {";

				$level++;

				}

			elseif ($class == "CssAtFontFaceDeclarationToken"

				|| $class === "CssAtKeyframesRulesetDeclarationToken"

				|| $class === "CssAtPageDeclarationToken"

				|| $class == "CssAtVariablesDeclarationToken"

				|| $class === "CssRulesetDeclarationToken"

				)

				{

				$declaration = $indent . $token->Property . ": ";

				if ($this->padding)

					{

					$declaration = str_pad($declaration, $this->padding, " ", STR_PAD_RIGHT);

					}

				$r[] = $declaration . $token->Value . ($token->IsImportant ? " !important" : "") . ";";

				}

			elseif ($class === "CssAtFontFaceEndToken"

				|| $class === "CssAtMediaEndToken"

				|| $class === "CssAtKeyframesEndToken"

				|| $class === "CssAtKeyframesRulesetEndToken"

				|| $class === "CssAtPageEndToken"

				|| $class === "CssAtVariablesEndToken"

				|| $class === "CssRulesetEndToken"

				)

				{

				$level--;

				$r[] = str_repeat($indent, $level) . "}";

				}

			}

		return implode("\n", $r);

		}

	}



/**

 * This {@link aCssToken CSS token} is a utility token that extends {@link aNullToken} and returns only a empty string.

 *

 * @package		CssMin/Tokens

 * @link		http://code.google.com/p/cssmin/

 * @author		Joe Scylla <joe.scylla@gmail.com>

 * @copyright	2008 - 2011 Joe Scylla <joe.scylla@gmail.com>

 * @license		http://opensource.org/licenses/mit-license.php MIT License

 * @version		3.0.1

 */

class CssNullToken extends aCssToken

	{

	/**

	 * Implements {@link aCssToken::__toString()}.

	 * 

	 * @return string

	 */

	public function __toString()

		{

		return "";

		}

	}



/**

 * CSS Minifier.

 * 

 * @package		CssMin/Minifier

 * @link		http://code.google.com/p/cssmin/

 * @author		Joe Scylla <joe.scylla@gmail.com>

 * @copyright	2008 - 2011 Joe Scylla <joe.scylla@gmail.com>

 * @license		http://opensource.org/licenses/mit-license.php MIT License

 * @version		3.0.1

 */

class CssMinifier

	{

	/**

	 * {@link aCssMinifierFilter Filters}.

	 *  

	 * @var array

	 */

	private $filters = array();

	/**

	 * {@link aCssMinifierPlugin Plugins}.

	 * 

	 * @var array

	 */

	private $plugins = array();

	/**

	 * Minified source.

	 * 

	 * @var string

	 */

	private $minified = "";

	/**

	 * Constructer.

	 * 

	 * Creates instances of {@link aCssMinifierFilter filters} and {@link aCssMinifierPlugin plugins}.

	 * 

	 * @param string $source CSS source [optional]

	 * @param array $filters Filter configuration [optional]

	 * @param array $plugins Plugin configuration [optional]

	 * @return void

	 */

	public function __construct($source = null, array $filters = null, array $plugins = null)

		{

		$filters = array_merge(array

			(

			"ImportImports"					=> false,

			"RemoveComments"				=> true, 

			"RemoveEmptyRulesets"			=> true,

			"RemoveEmptyAtBlocks"			=> true,

			"ConvertLevel3Properties"		=> false,

			"ConvertLevel3AtKeyframes"		=> false,

			"Variables"						=> true,

			"RemoveLastDelarationSemiColon"	=> true

			), is_array($filters) ? $filters : array());

		$plugins = array_merge(array

			(

			"Variables"						=> true,

			"ConvertFontWeight"				=> false,

			"ConvertHslColors"				=> false,

			"ConvertRgbColors"				=> false,

			"ConvertNamedColors"			=> false,

			"CompressColorValues"			=> false,

			"CompressUnitValues"			=> false,

			"CompressExpressionValues"		=> false

			), is_array($plugins) ? $plugins : array());

		// Filters

		foreach ($filters as $name => $config)

			{

			if ($config !== false)

				{

				$class	= "Css" . $name . "MinifierFilter";

				$config = is_array($config) ? $config : array();

				if (class_exists($class))

					{

					$this->filters[] = new $class($this, $config);

					}

				else

					{

					CssMin::triggerError(new CssError(__FILE__, __LINE__, __METHOD__ . ": The filter <code>" . $name . "</code> with the class name <code>" . $class . "</code> was not found"));

					}

				}

			}

		// Plugins

		foreach ($plugins as $name => $config)

			{

			if ($config !== false)

				{

				$class	= "Css" . $name . "MinifierPlugin";

				$config = is_array($config) ? $config : array();

				if (class_exists($class))

					{

					$this->plugins[] = new $class($this, $config);

					}

				else

					{

					CssMin::triggerError(new CssError(__FILE__, __LINE__, __METHOD__ . ": The plugin <code>" . $name . "</code> with the class name <code>" . $class . "</code> was not found"));

					}

				}

			}

		// --

		if (!is_null($source))

			{

			$this->minify($source);

			}

		}

	/**

	 * Returns the minified Source.

	 * 

	 * @return string

	 */

	public function getMinified()

		{

		return $this->minified;

		}

	/**

	 * Returns a plugin by class name.

	 * 

	 * @param string $name Class name of the plugin

	 * @return aCssMinifierPlugin

	 */

	public function getPlugin($class)

		{

		static $index = null;

		if (is_null($index))

			{

			$index = array();

			for ($i = 0, $l = count($this->plugins); $i < $l; $i++)

				{

				$index[get_class($this->plugins[$i])] = $i;

				}

			}

		return isset($index[$class]) ? $this->plugins[$index[$class]] : false;

		}

	/**

	 * Minifies the CSS source.

	 * 

	 * @param string $source CSS source

	 * @return string

	 */

	public function minify($source)

		{

		// Variables

		$r						= "";

		$parser					= new CssParser($source);

		$tokens					= $parser->getTokens();

		$filters 				= $this->filters;

		$filterCount			= count($this->filters);

		$plugins				= $this->plugins;

		$pluginCount			= count($plugins);

		$pluginIndex			= array();

		$pluginTriggerTokens	= array();

		$globalTriggerTokens	= array();

		for ($i = 0, $l = count($plugins); $i < $l; $i++)

			{

			$tPluginClassName				= get_class($plugins[$i]);

			$pluginTriggerTokens[$i]		= $plugins[$i]->getTriggerTokens();

			foreach ($pluginTriggerTokens[$i] as $v)

				{

				if (!in_array($v, $globalTriggerTokens))

					{

					$globalTriggerTokens[] = $v;

					}

				}

			$pluginTriggerTokens[$i] = "|" . implode("|", $pluginTriggerTokens[$i]) . "|";

			$pluginIndex[$tPluginClassName]	= $i;

			}

		$globalTriggerTokens = "|" . implode("|", $globalTriggerTokens) . "|";

		/*

		 * Apply filters

		 */

		for($i = 0; $i < $filterCount; $i++)

			{

			// Apply the filter; if the return value is larger than 0...

			if ($filters[$i]->apply($tokens) > 0)

				{

				// ...then filter null values and rebuild the token array

				$tokens = array_values(array_filter($tokens));

				}

			}

		$tokenCount = count($tokens);

		/*

		 * Apply plugins

		 */

		for($i = 0; $i < $tokenCount; $i++)

			{

			$triggerToken = "|" . get_class($tokens[$i]) . "|";

			if (strpos($globalTriggerTokens, $triggerToken) !== false)

				{

				for($ii = 0; $ii < $pluginCount; $ii++)

					{

					if (strpos($pluginTriggerTokens[$ii], $triggerToken) !== false || $pluginTriggerTokens[$ii] === false)

						{

						// Apply the plugin; if the return value is TRUE continue to the next token

						if ($plugins[$ii]->apply($tokens[$i]) === true)

							{

							continue 2;

							}

						}

					}

				}

			}

		// Stringify the tokens

		for($i = 0; $i < $tokenCount; $i++)

			{

			$r .= (string) $tokens[$i];

			}

		$this->minified = $r;

		return $r;

		}

	}



/**

 * CssMin - A (simple) css minifier with benefits

 * 

 * --

 * Copyright (c) 2011 Joe Scylla <joe.scylla@gmail.com>

 *

 * Permission is hereby granted, free of charge, to any person obtaining a copy

 * of this software and associated documentation files (the "Software"), to deal

 * in the Software without restriction, including without limitation the rights

 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell

 * copies of the Software, and to permit persons to whom the Software is

 * furnished to do so, subject to the following conditions:

 * 

 * The above copyright notice and this permission notice shall be included in

 * all copies or substantial portions of the Software.

 * 

 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR

 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,

 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE

 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER

 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,

 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN

 * THE SOFTWARE.

 * --

 * 

 * @package		CssMin

 * @link		http://code.google.com/p/cssmin/

 * @author		Joe Scylla <joe.scylla@gmail.com>

 * @copyright	2008 - 2011 Joe Scylla <joe.scylla@gmail.com>

 * @license		http://opensource.org/licenses/mit-license.php MIT License

 * @version		3.0.1

 */

class CssMin

	{

	/**

	 * Index of classes

	 * 

	 * @var array

	 */

	private static $classIndex = array();

	/**

	 * Parse/minify errors

	 * 

	 * @var array

	 */

	private static $errors = array();

	/**

	 * Verbose output.

	 * 

	 * @var boolean

	 */

	private static $isVerbose = false;

	/**

	 * {@link http://goo.gl/JrW54 Autoload} function of CssMin.

	 * 

	 * @param string $class Name of the class

	 * @return void

	 */

	public static function autoload($class)

		{

		if (isset(self::$classIndex[$class]))

			{

			require(self::$classIndex[$class]);

			}

		}

	/**

	 * Return errors

	 * 

	 * @return array of {CssError}.

	 */

	public static function getErrors()

		{

		return self::$errors;

		}

	/**

	 * Returns if there were errors.

	 * 

	 * @return boolean

	 */

	public static function hasErrors()

		{

		return count(self::$errors) > 0;

		}

	/**

	 * Initialises CssMin.

	 * 

	 * @return void

	 */

	public static function initialise()

		{

		// Create the class index for autoloading or including

		$paths = array(dirname(__FILE__));

		while (list($i, $path) = each($paths))

			{

			$subDirectorys = glob($path . "*", GLOB_MARK | GLOB_ONLYDIR | GLOB_NOSORT);

			if (is_array($subDirectorys))

				{

				foreach ($subDirectorys as $subDirectory)

					{

					$paths[] = $subDirectory;

					}

				}

			$files = glob($path . "*.php", 0);

			if (is_array($files))

				{

				foreach ($files as $file)

					{

					$class = substr(basename($file), 0, -4);

					self::$classIndex[$class] = $file;

					}

				}

			}

		krsort(self::$classIndex);

		// Only use autoloading if spl_autoload_register() is available and no __autoload() is defined (because 

		// __autoload() breaks if spl_autoload_register() is used. 

		if (function_exists("spl_autoload_register") && !is_callable("__autoload"))

			{

			spl_autoload_register(array(__CLASS__, "autoload"));

			}

		// Otherwise include all class files

		else

			{

			foreach (self::$classIndex as $class => $file)

				{

				if (!class_exists($class))

					{

					require_once($file);

					}

				}

			}

		}

	/**

	 * Minifies CSS source.

	 * 

	 * @param string $source CSS source

	 * @param array $filters Filter configuration [optional]

	 * @param array $plugins Plugin configuration [optional]

	 * @return string Minified CSS

	 */

	public static function minify($source, array $filters = null, array $plugins = null)

		{

		self::$errors = array();

		$minifier = new CssMinifier($source, $filters, $plugins);

		return $minifier->getMinified();

		}

	/**

	 * Parse the CSS source.

	 * 

	 * @param string $source CSS source

	 * @param array $plugins Plugin configuration [optional]

	 * @return array Array of aCssToken

	 */

	public static function parse($source, array $plugins = null)

		{

		self::$errors = array();

		$parser = new CssParser($source, $plugins);

		return $parser->getTokens();

		}

	/**

	 * --

	 * 

	 * @param boolean $to

	 * @return boolean

	 */

	public static function setVerbose($to)

		{

		self::$isVerbose = (boolean) $to;

		return self::$isVerbose;

		}

	/**

	 * --

	 * 

	 * @param CssError $error

	 * @return void

	 */

	public static function triggerError(CssError $error)

		{

		self::$errors[] = $error;

		if (self::$isVerbose)

			{

			trigger_error((string) $error, E_USER_WARNING);

			}

		}

	}

// Initialises CssMin

CssMin::initialise();



/**

 * This {@link aCssMinifierFilter minifier filter} import external css files defined with the @import at-rule into the 

 * current stylesheet. 

 * 

 * @package		CssMin/Minifier/Filters

 * @link		http://code.google.com/p/cssmin/

 * @author		Joe Scylla <joe.scylla@gmail.com>

 * @copyright	2008 - 2011 Joe Scylla <joe.scylla@gmail.com>

 * @license		http://opensource.org/licenses/mit-license.php MIT License

 * @version		3.0.1

 */

class CssImportImportsMinifierFilter extends aCssMinifierFilter

	{

	/**

	 * Array with already imported external stylesheets.

	 * 

	 * @var array

	 */

	private $imported = array();

	/**

	 * Implements {@link aCssMinifierFilter::filter()}.

	 * 

	 * @param array $tokens Array of objects of type aCssToken

	 * @return integer Count of added, changed or removed tokens; a return value large than 0 will rebuild the array

	 */

	public function apply(array &$tokens)

		{

		if (!isset($this->configuration["BasePath"]) || !is_dir($this->configuration["BasePath"]))

			{

			CssMin::triggerError(new CssError(__FILE__, __LINE__, __METHOD__ . ": Base path <code>" . ($this->configuration["BasePath"] ? $this->configuration["BasePath"] : "null"). "</code> is not a directory"));

			return 0;

			}

		for ($i = 0, $l = count($tokens); $i < $l; $i++)

			{

			if (get_class($tokens[$i]) === "CssAtImportToken")

				{

				$import = $this->configuration["BasePath"] . "/" . $tokens[$i]->Import;

				// Import file was not found/is not a file

				if (!is_file($import))

					{

					CssMin::triggerError(new CssError(__FILE__, __LINE__, __METHOD__ . ": Import file <code>" . $import. "</code> was not found.", (string) $tokens[$i]));

					}

				// Import file already imported; remove this @import at-rule to prevent recursions

				elseif (in_array($import, $this->imported))

					{

					CssMin::triggerError(new CssError(__FILE__, __LINE__, __METHOD__ . ": Import file <code>" . $import. "</code> was already imported.", (string) $tokens[$i]));

					$tokens[$i] = null;

					}

				else

					{

					$this->imported[] = $import;

					$parser = new CssParser(file_get_contents($import));

					$import = $parser->getTokens();

					// The @import at-rule has media types defined requiring special handling

					if (count($tokens[$i]->MediaTypes) > 0 && !(count($tokens[$i]->MediaTypes) == 1 && $tokens[$i]->MediaTypes[0] == "all"))

						{

						$blocks = array();

						/*

						 * Filter or set media types of @import at-rule or remove the @import at-rule if no media type is matching the parent @import at-rule

						 */

						for($ii = 0, $ll = count($import); $ii < $ll; $ii++)

							{

							if (get_class($import[$ii]) === "CssAtImportToken")

								{

								// @import at-rule defines no media type or only the "all" media type; set the media types to the one defined in the parent @import at-rule

								if (count($import[$ii]->MediaTypes) == 0 || (count($import[$ii]->MediaTypes) == 1 && $import[$ii]->MediaTypes[0] == "all"))

									{

									$import[$ii]->MediaTypes = $tokens[$i]->MediaTypes;

									}

								// @import at-rule defineds one or more media types; filter out media types not matching with the  parent @import at-rule

								elseif (count($import[$ii]->MediaTypes > 0))

									{

									foreach ($import[$ii]->MediaTypes as $index => $mediaType)

										{

										if (!in_array($mediaType, $tokens[$i]->MediaTypes))

											{

											unset($import[$ii]->MediaTypes[$index]);

											}

										}

									$import[$ii]->MediaTypes = array_values($import[$ii]->MediaTypes);

									// If there are no media types left in the @import at-rule remove the @import at-rule

									if (count($import[$ii]->MediaTypes) == 0)

										{

										$import[$ii] = null;

										}

									}

								}

							}

						/*

						 * Remove media types of @media at-rule block not defined in the @import at-rule

						 */

						for($ii = 0, $ll = count($import); $ii < $ll; $ii++)

							{

							if (get_class($import[$ii]) === "CssAtMediaStartToken")

								{

								foreach ($import[$ii]->MediaTypes as $index => $mediaType)

									{

									if (!in_array($mediaType, $tokens[$i]->MediaTypes))

										{

										unset($import[$ii]->MediaTypes[$index]);

										}

									$import[$ii]->MediaTypes = array_values($import[$ii]->MediaTypes);

									}

								}

							}

						/*

						 * If no media types left of the @media at-rule block remove the complete block

						 */

						for($ii = 0, $ll = count($import); $ii < $ll; $ii++)

							{

							if (get_class($import[$ii]) === "CssAtMediaStartToken")

								{

								if (count($import[$ii]->MediaTypes) === 0)

									{

									for ($iii = $ii; $iii < $ll; $iii++)

										{

										if (get_class($import[$iii]) === "CssAtMediaEndToken")

											{

											break;

											}

										}

									if (get_class($import[$iii]) === "CssAtMediaEndToken")

										{

										array_splice($import, $ii, $iii - $ii + 1, array());

										$ll = count($import);

										}

									}

								}

							}

						/*

						 * If the media types of the @media at-rule equals the media types defined in the @import 

						 * at-rule remove the CssAtMediaStartToken and CssAtMediaEndToken token

						 */ 

						for($ii = 0, $ll = count($import); $ii < $ll; $ii++)

							{

							if (get_class($import[$ii]) === "CssAtMediaStartToken" && count(array_diff($tokens[$i]->MediaTypes, $import[$ii]->MediaTypes)) === 0)

								{

								for ($iii = $ii; $iii < $ll; $iii++)

									{

									if (get_class($import[$iii]) == "CssAtMediaEndToken")

										{

										break;

										}

									}

								if (get_class($import[$iii]) == "CssAtMediaEndToken")

									{

									unset($import[$ii]);

									unset($import[$iii]);

									$import = array_values($import);

									$ll = count($import);

									}

								}

							}

						/**

						 * Extract CssAtImportToken and CssAtCharsetToken tokens

						 */

						for($ii = 0, $ll = count($import); $ii < $ll; $ii++)

							{

							$class = get_class($import[$ii]);

							if ($class === "CssAtImportToken" || $class === "CssAtCharsetToken")

								{

								$blocks = array_merge($blocks, array_splice($import, $ii, 1, array()));

								$ll = count($import);

								}

							}

						/*

						 * Extract the @font-face, @media and @page at-rule block

						 */

						for($ii = 0, $ll = count($import); $ii < $ll; $ii++)

							{

							$class = get_class($import[$ii]);

							if ($class === "CssAtFontFaceStartToken" || $class === "CssAtMediaStartToken" || $class === "CssAtPageStartToken" || $class === "CssAtVariablesStartToken")

								{

								for ($iii = $ii; $iii < $ll; $iii++)

									{

									$class = get_class($import[$iii]);

									if ($class === "CssAtFontFaceEndToken" || $class === "CssAtMediaEndToken" || $class === "CssAtPageEndToken" || $class === "CssAtVariablesEndToken")

										{

										break;

										}

									}

								$class = get_class($import[$iii]);

								if (isset($import[$iii]) && ($class === "CssAtFontFaceEndToken" || $class === "CssAtMediaEndToken" || $class === "CssAtPageEndToken" || $class === "CssAtVariablesEndToken"))

									{

									$blocks = array_merge($blocks, array_splice($import, $ii, $iii - $ii + 1, array()));

									$ll = count($import);

									}

								}

							}

						// Create the import array with extracted tokens and the rulesets wrapped into a @media at-rule block

						$import = array_merge($blocks, array(new CssAtMediaStartToken($tokens[$i]->MediaTypes)), $import, array(new CssAtMediaEndToken()));

						}

					// Insert the imported tokens

					array_splice($tokens, $i, 1, $import);

					// Modify parameters of the for-loop

					$i--;

					$l = count($tokens);

					}

				}

			}

		}

	}



/**

 * {@link aCssParserPlugin Parser plugin} for preserve parsing expression() declaration values.

 * 

 * This plugin return no {@link aCssToken CssToken} but ensures that expression() declaration values will get parsed 

 * properly.

 * 

 * @package		CssMin/Parser/Plugins

 * @link		http://code.google.com/p/cssmin/

 * @author		Joe Scylla <joe.scylla@gmail.com>

 * @copyright	2008 - 2011 Joe Scylla <joe.scylla@gmail.com>

 * @license		http://opensource.org/licenses/mit-license.php MIT License

 * @version		3.0.1

 */

class CssExpressionParserPlugin extends aCssParserPlugin

	{

	/**

	 * Count of left braces.

	 * 

	 * @var integer

	 */

	private $leftBraces = 0;

	/**

	 * Count of right braces.

	 * 

	 * @var integer

	 */

	private $rightBraces = 0;

	/**

	 * Implements {@link aCssParserPlugin::getTriggerChars()}.

	 * 

	 * @return array

	 */

	public function getTriggerChars()

		{

		return array("(", ")", ";", "}");

		}

	/**

	 * Implements {@link aCssParserPlugin::getTriggerStates()}.

	 * 

	 * @return array

	 */

	public function getTriggerStates()

		{

		return false;

		}

	/**

	 * Implements {@link aCssParserPlugin::parse()}.

	 * 

	 * @param integer $index Current index

	 * @param string $char Current char

	 * @param string $previousChar Previous char

	 * @return mixed TRUE will break the processing; FALSE continue with the next plugin; integer set a new index and break the processing

	 */

	public function parse($index, $char, $previousChar, $state)

		{

		// Start of expression

		if ($char === "(" && strtolower(substr($this->parser->getSource(), $index - 10, 11)) === "expression(" && $state !== "T_EXPRESSION")

			{

			$this->parser->pushState("T_EXPRESSION");

			$this->leftBraces++;

			}

		// Count left braces

		elseif ($char === "(" && $state === "T_EXPRESSION")

			{

			$this->leftBraces++;

			}

		// Count right braces

		elseif ($char === ")" && $state === "T_EXPRESSION")

			{

			$this->rightBraces++;

			}

		// Possible end of expression; if left and right braces are equal the expressen ends

		elseif (($char === ";" || $char === "}") && $state === "T_EXPRESSION" && $this->leftBraces === $this->rightBraces)

			{

			$this->leftBraces = $this->rightBraces = 0;

			$this->parser->popState();

			return $index - 1;

			}

		else

			{

			return false;

			}

		return true;

		}

	}



/**

 * CSS Error.

 * 

 * @package		CssMin

 * @link		http://code.google.com/p/cssmin/

 * @author		Joe Scylla <joe.scylla@gmail.com>

 * @copyright	2008 - 2011 Joe Scylla <joe.scylla@gmail.com>

 * @license		http://opensource.org/licenses/mit-license.php MIT License

 * @version		3.0.1

 */

class CssError

	{

	/**

	 * File.

	 * 

	 * @var string

	 */

	public $File = "";

	/**

	 * Line.

	 * 

	 * @var integer

	 */

	public $Line = 0;

	/**

	 * Error message.

	 * 

	 * @var string

	 */

	public $Message = "";

	/**

	 * Source.

	 * 

	 * @var string

	 */

	public $Source = "";

	/**

	 * Constructor triggering the error.

	 * 

	 * @param string $message Error message

	 * @param string $source Corresponding line [optional]

	 * @return void

	 */

	public function __construct($file, $line, $message, $source = "")

		{

		$this->File		= $file;

		$this->Line		= $line;

		$this->Message	= $message;

		$this->Source	= $source;

		}

	/**

	 * Returns the error as formatted string.

	 * 

	 * @return string

	 */	

	public function __toString()

		{

		return $this->Message . ($this->Source ? ": <br /><code>" . $this->Source . "</code>": "") . "<br />in file " . $this->File . " at line " . $this->Line;

		}

	}



/**

 * This {@link aCssMinifierPlugin} will convert a color value in rgb notation to hexadecimal notation.

 * 

 * Example:

 * <code>

 * color: rgb(200,60%,5);

 * </code>

 * 

 * Will get converted to:

 * <code>

 * color:#c89905;

 * </code>

 *

 * @package		CssMin/Minifier/Plugins

 * @link		http://code.google.com/p/cssmin/

 * @author		Joe Scylla <joe.scylla@gmail.com>

 * @copyright	2008 - 2011 Joe Scylla <joe.scylla@gmail.com>

 * @license		http://opensource.org/licenses/mit-license.php MIT License

 * @version		3.0.1

 */

class CssConvertRgbColorsMinifierPlugin extends aCssMinifierPlugin

	{

	/**

	 * Regular expression matching the value.

	 * 

	 * @var string

	 */

	private $reMatch = "/rgb\s*\(\s*([0-9%]+)\s*,\s*([0-9%]+)\s*,\s*([0-9%]+)\s*\)/iS";

	/**

	 * Implements {@link aCssMinifierPlugin::minify()}.

	 * 

	 * @param aCssToken $token Token to process

	 * @return boolean Return TRUE to break the processing of this token; FALSE to continue

	 */

	public function apply(aCssToken &$token)

		{

		if (stripos($token->Value, "rgb") !== false && preg_match($this->reMatch, $token->Value, $m))

			{

			for ($i = 1, $l = count($m); $i < $l; $i++)

				{

				if (strpos("%", $m[$i]) !== false)

					{

					$m[$i] = substr($m[$i], 0, -1);

					$m[$i] = (int) (256 * ($m[$i] / 100));

					}

				$m[$i] = str_pad(dechex($m[$i]),  2, "0", STR_PAD_LEFT);

				}

			$token->Value = str_replace($m[0], "#" . $m[1] . $m[2] . $m[3], $token->Value);

			}

		return false;

		}

	/**

	 * Implements {@link aMinifierPlugin::getTriggerTokens()}

	 * 

	 * @return array

	 */

	public function getTriggerTokens()

		{

		return array

			(

			"CssAtFontFaceDeclarationToken",

			"CssAtPageDeclarationToken",

			"CssRulesetDeclarationToken"

			);

		}

	}



/**

 * This {@link aCssMinifierPlugin} will convert named color values to hexadecimal notation.

 * 

 * Example:

 * <code>

 * color: black;

 * border: 1px solid indigo;

 * </code>

 * 

 * Will get converted to:

 * <code>

 * color:#000;

 * border:1px solid #4b0082;

 * </code>

 * 

 * @package		CssMin/Minifier/Plugins

 * @link		http://code.google.com/p/cssmin/

 * @author		Joe Scylla <joe.scylla@gmail.com>

 * @copyright	2008 - 2011 Joe Scylla <joe.scylla@gmail.com>

 * @license		http://opensource.org/licenses/mit-license.php MIT License

 * @version		3.0.1

 */

class CssConvertNamedColorsMinifierPlugin extends aCssMinifierPlugin

	{

	

	/**

	 * Regular expression matching the value.

	 * 

	 * @var string

	 */

	private $reMatch = null;

	/**

	 * Regular expression replacing the value.

	 * 

	 * @var string

	 */

	private $reReplace = "\"\${1}\" . \$this->transformation[strtolower(\"\${2}\")] . \"\${3}\"";

	/**

	 * Transformation table used by the {@link CssConvertNamedColorsMinifierPlugin::$reReplace replace regular expression}.

	 * 

	 * @var array

	 */

	private $transformation = array

		( 

		"aliceblue"						=> "#f0f8ff",

		"antiquewhite"					=> "#faebd7",

		"aqua"							=> "#0ff",

		"aquamarine"					=> "#7fffd4",

		"azure"							=> "#f0ffff",

		"beige"							=> "#f5f5dc",

		"black"							=> "#000",

		"blue"							=> "#00f",

		"blueviolet"					=> "#8a2be2",

		"brown"							=> "#a52a2a",

		"burlywood"						=> "#deb887",

		"cadetblue"						=> "#5f9ea0",

		"chartreuse"					=> "#7fff00",

		"chocolate"						=> "#d2691e",

		"coral"							=> "#ff7f50",

		"cornflowerblue"				=> "#6495ed",

		"cornsilk"						=> "#fff8dc",

		"crimson"						=> "#dc143c",

		"darkblue"						=> "#00008b",

		"darkcyan"						=> "#008b8b",

		"darkgoldenrod"					=> "#b8860b",

		"darkgray"						=> "#a9a9a9",

		"darkgreen"						=> "#006400",

		"darkkhaki"						=> "#bdb76b",

		"darkmagenta"					=> "#8b008b",

		"darkolivegreen"				=> "#556b2f",

		"darkorange"					=> "#ff8c00",

		"darkorchid"					=> "#9932cc",

		"darkred"						=> "#8b0000",

		"darksalmon"					=> "#e9967a",

		"darkseagreen"					=> "#8fbc8f",

		"darkslateblue"					=> "#483d8b",

		"darkslategray"					=> "#2f4f4f",

		"darkturquoise"					=> "#00ced1",

		"darkviolet"					=> "#9400d3",

		"deeppink"						=> "#ff1493",

		"deepskyblue"					=> "#00bfff",

		"dimgray"						=> "#696969",

		"dodgerblue"					=> "#1e90ff",

		"firebrick"						=> "#b22222",

		"floralwhite"					=> "#fffaf0",

		"forestgreen"					=> "#228b22",

		"fuchsia"						=> "#f0f",

		"gainsboro"						=> "#dcdcdc",

		"ghostwhite"					=> "#f8f8ff",

		"gold"							=> "#ffd700",

		"goldenrod"						=> "#daa520",

		"gray"							=> "#808080",

		"green"							=> "#008000",

		"greenyellow"					=> "#adff2f",

		"honeydew"						=> "#f0fff0",

		"hotpink"						=> "#ff69b4",

		"indianred"						=> "#cd5c5c",

		"indigo"						=> "#4b0082",

		"ivory"							=> "#fffff0",

		"khaki"							=> "#f0e68c",

		"lavender"						=> "#e6e6fa",

		"lavenderblush"					=> "#fff0f5",

		"lawngreen"						=> "#7cfc00",

		"lemonchiffon"					=> "#fffacd",

		"lightblue"						=> "#add8e6",

		"lightcoral"					=> "#f08080",

		"lightcyan"						=> "#e0ffff",

		"lightgoldenrodyellow"			=> "#fafad2",

		"lightgreen"					=> "#90ee90",

		"lightgrey"						=> "#d3d3d3",

		"lightpink"						=> "#ffb6c1",

		"lightsalmon"					=> "#ffa07a",

		"lightseagreen"					=> "#20b2aa",

		"lightskyblue"					=> "#87cefa",

		"lightslategray"				=> "#789",

		"lightsteelblue"				=> "#b0c4de",

		"lightyellow"					=> "#ffffe0",

		"lime"							=> "#0f0",

		"limegreen"						=> "#32cd32",

		"linen"							=> "#faf0e6",

		"maroon"						=> "#800000",

		"mediumaquamarine"				=> "#66cdaa",

		"mediumblue"					=> "#0000cd",

		"mediumorchid"					=> "#ba55d3",

		"mediumpurple"					=> "#9370db",

		"mediumseagreen"				=> "#3cb371",

		"mediumslateblue"				=> "#7b68ee",

		"mediumspringgreen"				=> "#00fa9a",

		"mediumturquoise"				=> "#48d1cc",

		"mediumvioletred"				=> "#c71585",

		"midnightblue"					=> "#191970",

		"mintcream"						=> "#f5fffa",

		"mistyrose"						=> "#ffe4e1",

		"moccasin"						=> "#ffe4b5",

		"navajowhite"					=> "#ffdead",

		"navy"							=> "#000080",

		"oldlace"						=> "#fdf5e6",

		"olive"							=> "#808000",

		"olivedrab"						=> "#6b8e23",

		"orange"						=> "#ffa500",

		"orangered"						=> "#ff4500",

		"orchid"						=> "#da70d6",

		"palegoldenrod"					=> "#eee8aa",

		"palegreen"						=> "#98fb98",

		"paleturquoise"					=> "#afeeee",

		"palevioletred"					=> "#db7093",

		"papayawhip"					=> "#ffefd5",

		"peachpuff"						=> "#ffdab9",

		"peru"							=> "#cd853f",

		"pink"							=> "#ffc0cb",

		"plum"							=> "#dda0dd",

		"powderblue"					=> "#b0e0e6",

		"purple"						=> "#800080",

		"red"							=> "#f00",

		"rosybrown"						=> "#bc8f8f",

		"royalblue"						=> "#4169e1",

		"saddlebrown"					=> "#8b4513",

		"salmon"						=> "#fa8072",

		"sandybrown"					=> "#f4a460",

		"seagreen"						=> "#2e8b57",

		"seashell"						=> "#fff5ee",

		"sienna"						=> "#a0522d",

		"silver"						=> "#c0c0c0",

		"skyblue"						=> "#87ceeb",

		"slateblue"						=> "#6a5acd",

		"slategray"						=> "#708090",

		"snow"							=> "#fffafa",

		"springgreen"					=> "#00ff7f",

		"steelblue"						=> "#4682b4",

		"tan"							=> "#d2b48c",

		"teal"							=> "#008080",

		"thistle"						=> "#d8bfd8",

		"tomato"						=> "#ff6347",

		"turquoise"						=> "#40e0d0",

		"violet"						=> "#ee82ee",

		"wheat"							=> "#f5deb3",

		"white"							=> "#fff",

		"whitesmoke"					=> "#f5f5f5",

		"yellow"						=> "#ff0",

		"yellowgreen"					=> "#9acd32"

		);

	/**

	 * Overwrites {@link aCssMinifierPlugin::__construct()}.

	 * 

	 * The constructor will create the {@link CssConvertNamedColorsMinifierPlugin::$reReplace replace regular expression}

	 * based on the {@link CssConvertNamedColorsMinifierPlugin::$transformation transformation table}.

	 * 

	 * @param CssMinifier $minifier The CssMinifier object of this plugin.

	 * @param array $configuration Plugin configuration [optional]

	 * @return void

	 */

	public function __construct(CssMinifier $minifier, array $configuration = array())

		{

		$this->reMatch = "/(^|\s)+(" . implode("|", array_keys($this->transformation)) . ")(\s|$)+/eiS";

		parent::__construct($minifier, $configuration);

		}

	/**

	 * Implements {@link aCssMinifierPlugin::minify()}.

	 * 

	 * @param aCssToken $token Token to process

	 * @return boolean Return TRUE to break the processing of this token; FALSE to continue

	 */

	public function apply(aCssToken &$token)

		{

		$lcValue = strtolower($token->Value);

		// Declaration value equals a value in the transformation table => simple replace

		if (isset($this->transformation[$lcValue]))

			{

			$token->Value = $this->transformation[$lcValue];

			}

		// Declaration value contains a value in the transformation table => regular expression replace

		elseif (preg_match($this->reMatch, $token->Value))

			{

			$token->Value = preg_replace($this->reMatch, $this->reReplace, $token->Value);

			}

		return false;

		}

	/**

	 * Implements {@link aMinifierPlugin::getTriggerTokens()}

	 * 

	 * @return array

	 */

	public function getTriggerTokens()

		{

		return array

			(

			"CssAtFontFaceDeclarationToken",

			"CssAtPageDeclarationToken",

			"CssRulesetDeclarationToken"

			);

		}

	}



/**

 * This {@link aCssMinifierFilter minifier filter} triggers on CSS Level 3 properties and will add declaration tokens

 * with browser-specific properties.

 * 

 * @package		CssMin/Minifier/Filters

 * @link		http://code.google.com/p/cssmin/

 * @author		Joe Scylla <joe.scylla@gmail.com>

 * @copyright	2008 - 2011 Joe Scylla <joe.scylla@gmail.com>

 * @license		http://opensource.org/licenses/mit-license.php MIT License

 * @version		3.0.1

 */

class CssConvertLevel3PropertiesMinifierFilter extends aCssMinifierFilter

	{

	/**

	 * Css property transformations table. Used to convert CSS3 and proprietary properties to the browser-specific 

	 * counterparts.

	 * 

	 * @var array

	 */

	private $transformations = array

		(

		// Property						Array(Mozilla, Webkit, Opera, Internet Explorer); NULL values are placeholders and will get ignored

		"animation"						=> array(null, "-webkit-animation", null, null),

		"animation-delay"				=> array(null, "-webkit-animation-delay", null, null),

		"animation-direction" 			=> array(null, "-webkit-animation-direction", null, null),

		"animation-duration"			=> array(null, "-webkit-animation-duration", null, null),

		"animation-fill-mode"			=> array(null, "-webkit-animation-fill-mode", null, null),

		"animation-iteration-count"		=> array(null, "-webkit-animation-iteration-count", null, null),

		"animation-name"				=> array(null, "-webkit-animation-name", null, null),

		"animation-play-state"			=> array(null, "-webkit-animation-play-state", null, null),

		"animation-timing-function"		=> array(null, "-webkit-animation-timing-function", null, null),

		"appearance"					=> array("-moz-appearance", "-webkit-appearance", null, null),

		"backface-visibility"			=> array(null, "-webkit-backface-visibility", null, null),

		"background-clip"				=> array(null, "-webkit-background-clip", null, null),

		"background-composite"			=> array(null, "-webkit-background-composite", null, null),

		"background-inline-policy"		=> array("-moz-background-inline-policy", null, null, null),

		"background-origin"				=> array(null, "-webkit-background-origin", null, null),

		"background-position-x"			=> array(null, null, null, "-ms-background-position-x"),

		"background-position-y"			=> array(null, null, null, "-ms-background-position-y"),

		"background-size"				=> array(null, "-webkit-background-size", null, null),

		"behavior"						=> array(null, null, null, "-ms-behavior"),

		"binding"						=> array("-moz-binding", null, null, null),

		"border-after"					=> array(null, "-webkit-border-after", null, null),

		"border-after-color"			=> array(null, "-webkit-border-after-color", null, null),

		"border-after-style"			=> array(null, "-webkit-border-after-style", null, null),

		"border-after-width"			=> array(null, "-webkit-border-after-width", null, null),

		"border-before"					=> array(null, "-webkit-border-before", null, null),

		"border-before-color"			=> array(null, "-webkit-border-before-color", null, null),

		"border-before-style"			=> array(null, "-webkit-border-before-style", null, null),

		"border-before-width"			=> array(null, "-webkit-border-before-width", null, null),

		"border-border-bottom-colors"	=> array("-moz-border-bottom-colors", null, null, null),

		"border-bottom-left-radius"		=> array("-moz-border-radius-bottomleft", "-webkit-border-bottom-left-radius", null, null),

		"border-bottom-right-radius"	=> array("-moz-border-radius-bottomright", "-webkit-border-bottom-right-radius", null, null),

		"border-end"					=> array("-moz-border-end", "-webkit-border-end", null, null),

		"border-end-color"				=> array("-moz-border-end-color", "-webkit-border-end-color", null, null),

		"border-end-style"				=> array("-moz-border-end-style", "-webkit-border-end-style", null, null),

		"border-end-width"				=> array("-moz-border-end-width", "-webkit-border-end-width", null, null),

		"border-fit"					=> array(null, "-webkit-border-fit", null, null),

		"border-horizontal-spacing"		=> array(null, "-webkit-border-horizontal-spacing", null, null),

		"border-image"					=> array("-moz-border-image", "-webkit-border-image", null, null),

		"border-left-colors"			=> array("-moz-border-left-colors", null, null, null),

		"border-radius"					=> array("-moz-border-radius", "-webkit-border-radius", null, null),

		"border-border-right-colors"	=> array("-moz-border-right-colors", null, null, null),

		"border-start"					=> array("-moz-border-start", "-webkit-border-start", null, null),

		"border-start-color"			=> array("-moz-border-start-color", "-webkit-border-start-color", null, null),

		"border-start-style"			=> array("-moz-border-start-style", "-webkit-border-start-style", null, null),

		"border-start-width"			=> array("-moz-border-start-width", "-webkit-border-start-width", null, null),

		"border-top-colors"				=> array("-moz-border-top-colors", null, null, null),

		"border-top-left-radius"		=> array("-moz-border-radius-topleft", "-webkit-border-top-left-radius", null, null),

		"border-top-right-radius"		=> array("-moz-border-radius-topright", "-webkit-border-top-right-radius", null, null),

		"border-vertical-spacing"		=> array(null, "-webkit-border-vertical-spacing", null, null),

		"box-align"						=> array("-moz-box-align", "-webkit-box-align", null, null),

		"box-direction"					=> array("-moz-box-direction", "-webkit-box-direction", null, null),

		"box-flex"						=> array("-moz-box-flex", "-webkit-box-flex", null, null),

		"box-flex-group"				=> array(null, "-webkit-box-flex-group", null, null),

		"box-flex-lines"				=> array(null, "-webkit-box-flex-lines", null, null),

		"box-ordinal-group"				=> array("-moz-box-ordinal-group", "-webkit-box-ordinal-group", null, null),

		"box-orient"					=> array("-moz-box-orient", "-webkit-box-orient", null, null),

		"box-pack"						=> array("-moz-box-pack", "-webkit-box-pack", null, null),

		"box-reflect"					=> array(null, "-webkit-box-reflect", null, null),

		"box-shadow"					=> array("-moz-box-shadow", "-webkit-box-shadow", null, null),

		"box-sizing"					=> array("-moz-box-sizing", null, null, null),

		"color-correction"				=> array(null, "-webkit-color-correction", null, null),

		"column-break-after"			=> array(null, "-webkit-column-break-after", null, null),

		"column-break-before"			=> array(null, "-webkit-column-break-before", null, null),

		"column-break-inside"			=> array(null, "-webkit-column-break-inside", null, null),

		"column-count"					=> array("-moz-column-count", "-webkit-column-count", null, null),

		"column-gap"					=> array("-moz-column-gap", "-webkit-column-gap", null, null),

		"column-rule"					=> array("-moz-column-rule", "-webkit-column-rule", null, null),

		"column-rule-color"				=> array("-moz-column-rule-color", "-webkit-column-rule-color", null, null),

		"column-rule-style"				=> array("-moz-column-rule-style", "-webkit-column-rule-style", null, null),

		"column-rule-width"				=> array("-moz-column-rule-width", "-webkit-column-rule-width", null, null),

		"column-span"					=> array(null, "-webkit-column-span", null, null),

		"column-width"					=> array("-moz-column-width", "-webkit-column-width", null, null),

		"columns"						=> array(null, "-webkit-columns", null, null),

		"filter"						=> array(__CLASS__, "filter"),

		"float-edge"					=> array("-moz-float-edge", null, null, null),

		"font-feature-settings"			=> array("-moz-font-feature-settings", null, null, null),

		"font-language-override"		=> array("-moz-font-language-override", null, null, null),

		"font-size-delta"				=> array(null, "-webkit-font-size-delta", null, null),

		"font-smoothing"				=> array(null, "-webkit-font-smoothing", null, null),

		"force-broken-image-icon"		=> array("-moz-force-broken-image-icon", null, null, null),

		"highlight"						=> array(null, "-webkit-highlight", null, null),

		"hyphenate-character"			=> array(null, "-webkit-hyphenate-character", null, null),

		"hyphenate-locale"				=> array(null, "-webkit-hyphenate-locale", null, null),

		"hyphens"						=> array(null, "-webkit-hyphens", null, null),

		"force-broken-image-icon"		=> array("-moz-image-region", null, null, null),

		"ime-mode"						=> array(null, null, null, "-ms-ime-mode"),

		"interpolation-mode"			=> array(null, null, null, "-ms-interpolation-mode"),

		"layout-flow"					=> array(null, null, null, "-ms-layout-flow"),

		"layout-grid"					=> array(null, null, null, "-ms-layout-grid"),

		"layout-grid-char"				=> array(null, null, null, "-ms-layout-grid-char"),

		"layout-grid-line"				=> array(null, null, null, "-ms-layout-grid-line"),

		"layout-grid-mode"				=> array(null, null, null, "-ms-layout-grid-mode"),

		"layout-grid-type"				=> array(null, null, null, "-ms-layout-grid-type"),

		"line-break"					=> array(null, "-webkit-line-break", null, "-ms-line-break"),

		"line-clamp"					=> array(null, "-webkit-line-clamp", null, null),

		"line-grid-mode"				=> array(null, null, null, "-ms-line-grid-mode"),

		"logical-height"				=> array(null, "-webkit-logical-height", null, null),

		"logical-width"					=> array(null, "-webkit-logical-width", null, null),

		"margin-after"					=> array(null, "-webkit-margin-after", null, null),

		"margin-after-collapse"			=> array(null, "-webkit-margin-after-collapse", null, null),

		"margin-before"					=> array(null, "-webkit-margin-before", null, null),

		"margin-before-collapse"		=> array(null, "-webkit-margin-before-collapse", null, null),

		"margin-bottom-collapse"		=> array(null, "-webkit-margin-bottom-collapse", null, null),

		"margin-collapse"				=> array(null, "-webkit-margin-collapse", null, null),

		"margin-end"					=> array("-moz-margin-end", "-webkit-margin-end", null, null),

		"margin-start"					=> array("-moz-margin-start", "-webkit-margin-start", null, null),

		"margin-top-collapse"			=> array(null, "-webkit-margin-top-collapse", null, null),

		"marquee "						=> array(null, "-webkit-marquee", null, null),

		"marquee-direction"				=> array(null, "-webkit-marquee-direction", null, null),

		"marquee-increment"				=> array(null, "-webkit-marquee-increment", null, null),

		"marquee-repetition"			=> array(null, "-webkit-marquee-repetition", null, null),

		"marquee-speed"					=> array(null, "-webkit-marquee-speed", null, null),

		"marquee-style"					=> array(null, "-webkit-marquee-style", null, null),

		"mask"							=> array(null, "-webkit-mask", null, null),

		"mask-attachment"				=> array(null, "-webkit-mask-attachment", null, null),

		"mask-box-image"				=> array(null, "-webkit-mask-box-image", null, null),

		"mask-clip"						=> array(null, "-webkit-mask-clip", null, null),

		"mask-composite"				=> array(null, "-webkit-mask-composite", null, null),

		"mask-image"					=> array(null, "-webkit-mask-image", null, null),

		"mask-origin"					=> array(null, "-webkit-mask-origin", null, null),

		"mask-position"					=> array(null, "-webkit-mask-position", null, null),

		"mask-position-x"				=> array(null, "-webkit-mask-position-x", null, null),

		"mask-position-y"				=> array(null, "-webkit-mask-position-y", null, null),

		"mask-repeat"					=> array(null, "-webkit-mask-repeat", null, null),

		"mask-repeat-x"					=> array(null, "-webkit-mask-repeat-x", null, null),

		"mask-repeat-y"					=> array(null, "-webkit-mask-repeat-y", null, null),

		"mask-size"						=> array(null, "-webkit-mask-size", null, null),

		"match-nearest-mail-blockquote-color" => array(null, "-webkit-match-nearest-mail-blockquote-color", null, null),

		"max-logical-height"			=> array(null, "-webkit-max-logical-height", null, null),

		"max-logical-width"				=> array(null, "-webkit-max-logical-width", null, null),

		"min-logical-height"			=> array(null, "-webkit-min-logical-height", null, null),

		"min-logical-width"				=> array(null, "-webkit-min-logical-width", null, null),

		"object-fit"					=> array(null, null, "-o-object-fit", null),

		"object-position"				=> array(null, null, "-o-object-position", null),

		"opacity"						=> array(__CLASS__, "opacity"),

		"outline-radius"				=> array("-moz-outline-radius", null, null, null),

		"outline-bottom-left-radius"	=> array("-moz-outline-radius-bottomleft", null, null, null),

		"outline-bottom-right-radius"	=> array("-moz-outline-radius-bottomright", null, null, null),

		"outline-top-left-radius"		=> array("-moz-outline-radius-topleft", null, null, null),

		"outline-top-right-radius"		=> array("-moz-outline-radius-topright", null, null, null),

		"padding-after"					=> array(null, "-webkit-padding-after", null, null),

		"padding-before"				=> array(null, "-webkit-padding-before", null, null),

		"padding-end"					=> array("-moz-padding-end", "-webkit-padding-end", null, null),

		"padding-start"					=> array("-moz-padding-start", "-webkit-padding-start", null, null),

		"perspective"					=> array(null, "-webkit-perspective", null, null),

		"perspective-origin"			=> array(null, "-webkit-perspective-origin", null, null),

		"perspective-origin-x"			=> array(null, "-webkit-perspective-origin-x", null, null),

		"perspective-origin-y"			=> array(null, "-webkit-perspective-origin-y", null, null),

		"rtl-ordering"					=> array(null, "-webkit-rtl-ordering", null, null),

		"scrollbar-3dlight-color"		=> array(null, null, null, "-ms-scrollbar-3dlight-color"),

		"scrollbar-arrow-color"			=> array(null, null, null, "-ms-scrollbar-arrow-color"),

		"scrollbar-base-color"			=> array(null, null, null, "-ms-scrollbar-base-color"),

		"scrollbar-darkshadow-color"	=> array(null, null, null, "-ms-scrollbar-darkshadow-color"),

		"scrollbar-face-color"			=> array(null, null, null, "-ms-scrollbar-face-color"),

		"scrollbar-highlight-color"		=> array(null, null, null, "-ms-scrollbar-highlight-color"),

		"scrollbar-shadow-color"		=> array(null, null, null, "-ms-scrollbar-shadow-color"),

		"scrollbar-track-color"			=> array(null, null, null, "-ms-scrollbar-track-color"),

		"stack-sizing"					=> array("-moz-stack-sizing", null, null, null),

		"svg-shadow"					=> array(null, "-webkit-svg-shadow", null, null),

		"tab-size"						=> array("-moz-tab-size", null, "-o-tab-size", null),

		"table-baseline"				=> array(null, null, "-o-table-baseline", null),

		"text-align-last"				=> array(null, null, null, "-ms-text-align-last"),

		"text-autospace"				=> array(null, null, null, "-ms-text-autospace"),

		"text-combine"					=> array(null, "-webkit-text-combine", null, null),

		"text-decorations-in-effect"	=> array(null, "-webkit-text-decorations-in-effect", null, null),

		"text-emphasis"					=> array(null, "-webkit-text-emphasis", null, null),

		"text-emphasis-color"			=> array(null, "-webkit-text-emphasis-color", null, null),

		"text-emphasis-position"		=> array(null, "-webkit-text-emphasis-position", null, null),

		"text-emphasis-style"			=> array(null, "-webkit-text-emphasis-style", null, null),

		"text-fill-color"				=> array(null, "-webkit-text-fill-color", null, null),

		"text-justify"					=> array(null, null, null, "-ms-text-justify"),

		"text-kashida-space"			=> array(null, null, null, "-ms-text-kashida-space"),

		"text-overflow"					=> array(null, null, "-o-text-overflow", "-ms-text-overflow"),

		"text-security"					=> array(null, "-webkit-text-security", null, null),

		"text-size-adjust"				=> array(null, "-webkit-text-size-adjust", null, "-ms-text-size-adjust"),

		"text-stroke"					=> array(null, "-webkit-text-stroke", null, null),

		"text-stroke-color"				=> array(null, "-webkit-text-stroke-color", null, null),

		"text-stroke-width"				=> array(null, "-webkit-text-stroke-width", null, null),

		"text-underline-position"		=> array(null, null, null, "-ms-text-underline-position"),

		"transform"						=> array("-moz-transform", "-webkit-transform", "-o-transform", null),

		"transform-origin"				=> array("-moz-transform-origin", "-webkit-transform-origin", "-o-transform-origin", null),

		"transform-origin-x"			=> array(null, "-webkit-transform-origin-x", null, null),

		"transform-origin-y"			=> array(null, "-webkit-transform-origin-y", null, null),

		"transform-origin-z"			=> array(null, "-webkit-transform-origin-z", null, null),

		"transform-style"				=> array(null, "-webkit-transform-style", null, null),

		"transition"					=> array("-moz-transition", "-webkit-transition", "-o-transition", null),

		"transition-delay"				=> array("-moz-transition-delay", "-webkit-transition-delay", "-o-transition-delay", null),

		"transition-duration"			=> array("-moz-transition-duration", "-webkit-transition-duration", "-o-transition-duration", null),

		"transition-property"			=> array("-moz-transition-property", "-webkit-transition-property", "-o-transition-property", null),

		"transition-timing-function"	=> array("-moz-transition-timing-function", "-webkit-transition-timing-function", "-o-transition-timing-function", null),

		"user-drag"						=> array(null, "-webkit-user-drag", null, null),

		"user-focus"					=> array("-moz-user-focus", null, null, null),

		"user-input"					=> array("-moz-user-input", null, null, null),

		"user-modify"					=> array("-moz-user-modify", "-webkit-user-modify", null, null),

		"user-select"					=> array("-moz-user-select", "-webkit-user-select", null, null),

		"white-space"					=> array(__CLASS__, "whiteSpace"),

		"window-shadow"					=> array("-moz-window-shadow", null, null, null),

		"word-break"					=> array(null, null, null, "-ms-word-break"),

		"word-wrap"						=> array(null, null, null, "-ms-word-wrap"),

		"writing-mode"					=> array(null, "-webkit-writing-mode", null, "-ms-writing-mode"),

		"zoom"							=> array(null, null, null, "-ms-zoom")

		);

	/**

	 * Implements {@link aCssMinifierFilter::filter()}.

	 * 

	 * @param array $tokens Array of objects of type aCssToken

	 * @return integer Count of added, changed or removed tokens; a return value large than 0 will rebuild the array

	 */

	public function apply(array &$tokens)

		{

		$r = 0;

		$transformations = &$this->transformations;

		for ($i = 0, $l = count($tokens); $i < $l; $i++)

			{

			if (get_class($tokens[$i]) === "CssRulesetDeclarationToken")

				{

				$tProperty = $tokens[$i]->Property;

				if (isset($transformations[$tProperty]))

					{

					$result = array();

					if (is_callable($transformations[$tProperty]))

						{

						$result = call_user_func_array($transformations[$tProperty], array($tokens[$i]));

						if (!is_array($result) && is_object($result))

							{

							$result = array($result);

							}

						}

					else

						{

						$tValue			= $tokens[$i]->Value;

						$tMediaTypes	= $tokens[$i]->MediaTypes;

						foreach ($transformations[$tProperty] as $property)

							{

							if ($property !== null)

								{

								$result[] = new CssRulesetDeclarationToken($property, $tValue, $tMediaTypes);

								}

							}

						}

					if (count($result) > 0)

						{

						array_splice($tokens, $i + 1, 0, $result);

						$i += count($result);

						$l += count($result);

						}

					}

				}

			}

		return $r;

		}

	/**

	 * Transforms the Internet Explorer specific declaration property "filter" to Internet Explorer 8+ compatible 

	 * declaratiopn property "-ms-filter". 

	 * 

	 * @param aCssToken $token

	 * @return array

	 */

	private static function filter($token)

		{

		$r = array

			(

			new CssRulesetDeclarationToken("-ms-filter", "\"" . $token->Value . "\"", $token->MediaTypes),

			);

		return $r;

		}

	/**

	 * Transforms "opacity: {value}" into browser specific counterparts.

	 * 

	 * @param aCssToken $token

	 * @return array

	 */

	private static function opacity($token)

		{

		// Calculate the value for Internet Explorer filter statement

		$ieValue = (int) ((float) $token->Value * 100);

		$r = array

			(

			// Internet Explorer >= 8

			new CssRulesetDeclarationToken("-ms-filter", "\"alpha(opacity=" . $ieValue . ")\"", $token->MediaTypes),

			// Internet Explorer >= 4 <= 7

			new CssRulesetDeclarationToken("filter", "alpha(opacity=" . $ieValue . ")", $token->MediaTypes),

			new CssRulesetDeclarationToken("zoom", "1", $token->MediaTypes)

			);

		return $r;

		}

	/**

	 * Transforms "white-space: pre-wrap" into browser specific counterparts.

	 * 

	 * @param aCssToken $token

	 * @return array

	 */

	private static function whiteSpace($token)

		{

		if (strtolower($token->Value) === "pre-wrap")

			{

			$r = array

				(

				// Firefox < 3

				new CssRulesetDeclarationToken("white-space", "-moz-pre-wrap", $token->MediaTypes),

				// Webkit

				new CssRulesetDeclarationToken("white-space", "-webkit-pre-wrap", $token->MediaTypes),

				// Opera >= 4 <= 6

				new CssRulesetDeclarationToken("white-space", "-pre-wrap", $token->MediaTypes),

				// Opera >= 7

				new CssRulesetDeclarationToken("white-space", "-o-pre-wrap", $token->MediaTypes),

				// Internet Explorer >= 5.5

				new CssRulesetDeclarationToken("word-wrap", "break-word", $token->MediaTypes)

				);

			return $r;

			}

		else

			{

			return array();

			}

		}

	}



/**

 * This {@link aCssMinifierFilter minifier filter} will convert @keyframes at-rule block to browser specific counterparts.

 * 

 * @package		CssMin/Minifier/Filters

 * @link		http://code.google.com/p/cssmin/

 * @author		Joe Scylla <joe.scylla@gmail.com>

 * @copyright	2008 - 2011 Joe Scylla <joe.scylla@gmail.com>

 * @license		http://opensource.org/licenses/mit-license.php MIT License

 * @version		3.0.1

 */

class CssConvertLevel3AtKeyframesMinifierFilter extends aCssMinifierFilter

	{

	/**

	 * Implements {@link aCssMinifierFilter::filter()}.

	 * 

	 * @param array $tokens Array of objects of type aCssToken

	 * @return integer Count of added, changed or removed tokens; a return value larger than 0 will rebuild the array

	 */

	public function apply(array &$tokens)

		{

		$r = 0;

		$transformations = array("-moz-keyframes", "-webkit-keyframes");

		for ($i = 0, $l = count($tokens); $i < $l; $i++)

			{

			if (get_class($tokens[$i]) === "CssAtKeyframesStartToken")

				{

				for ($ii = $i; $ii < $l; $ii++)

					{

					if (get_class($tokens[$ii]) === "CssAtKeyframesEndToken")

						{

						break;

						}

					}

				if (get_class($tokens[$ii]) === "CssAtKeyframesEndToken")

					{

					$add	= array();

					$source	= array();

					for ($iii = $i; $iii <= $ii; $iii++)

						{

						$source[] = clone($tokens[$iii]);

						}

					foreach ($transformations as $transformation)

						{

						$t = array();

						foreach ($source as $token)

							{

							$t[] = clone($token);

							}

						$t[0]->AtRuleName = $transformation;

						$add = array_merge($add, $t);

						}

					if (isset($this->configuration["RemoveSource"]) && $this->configuration["RemoveSource"] === true)

						{

						array_splice($tokens, $i, $ii - $i + 1, $add);

						}

					else

						{

						array_splice($tokens, $ii + 1, 0, $add);

						}

					$l = count($tokens);

					$i = $ii + count($add);

					$r += count($add);

					}

				}

			}

		return $r;

		}

	}



/**

 * This {@link aCssMinifierPlugin} will convert a color value in hsl notation to hexadecimal notation.

 * 

 * Example:

 * <code>

 * color: hsl(232,36%,48%);

 * </code>

 * 

 * Will get converted to:

 * <code>

 * color:#4e5aa7;

 * </code>

 * 

 * @package		CssMin/Minifier/Plugins

 * @link		http://code.google.com/p/cssmin/

 * @author		Joe Scylla <joe.scylla@gmail.com>

 * @copyright	2008 - 2011 Joe Scylla <joe.scylla@gmail.com>

 * @license		http://opensource.org/licenses/mit-license.php MIT License

 * @version		3.0.1

 */

class CssConvertHslColorsMinifierPlugin extends aCssMinifierPlugin

	{

	/**

	 * Regular expression matching the value.

	 * 

	 * @var string

	 */

	private $reMatch = "/^hsl\s*\(\s*([0-9]+)\s*,\s*([0-9]+)\s*%\s*,\s*([0-9]+)\s*%\s*\)/iS";

	/**

	 * Implements {@link aCssMinifierPlugin::minify()}.

	 * 

	 * @param aCssToken $token Token to process

	 * @return boolean Return TRUE to break the processing of this token; FALSE to continue

	 */

	public function apply(aCssToken &$token)

		{

		if (stripos($token->Value, "hsl") !== false && preg_match($this->reMatch, $token->Value, $m))

			{

			$token->Value = str_replace($m[0], $this->hsl2hex($m[1], $m[2], $m[3]), $token->Value);

			}

		return false;

		}

	/**

	 * Implements {@link aMinifierPlugin::getTriggerTokens()}

	 * 

	 * @return array

	 */

	public function getTriggerTokens()

		{

		return array

			(

			"CssAtFontFaceDeclarationToken",

			"CssAtPageDeclarationToken",

			"CssRulesetDeclarationToken"

			);

		}

	/**

	 * Convert a HSL value to hexadecimal notation.

	 * 

	 * Based on: {@link http://www.easyrgb.com/index.php?X=MATH&H=19#text19}.

	 * 

	 * @param integer $hue Hue

	 * @param integer $saturation Saturation

	 * @param integer $lightness Lightnesss

	 * @return string

	 */

	private function hsl2hex($hue, $saturation, $lightness)

		{

		$hue		= $hue / 360;

		$saturation	= $saturation / 100;

		$lightness	= $lightness / 100;

		if ($saturation == 0)

			{

			$red	= $lightness * 255;

			$green	= $lightness * 255;

			$blue	= $lightness * 255;

			}

		else

			{

			if ($lightness < 0.5 )

				{

				$v2 = $lightness * (1 + $saturation);

				}

			else

				{

				$v2 = ($lightness + $saturation) - ($saturation * $lightness);

				}

			$v1		= 2 * $lightness - $v2;

			$red	= 255 * self::hue2rgb($v1, $v2, $hue + (1 / 3));

			$green	= 255 * self::hue2rgb($v1, $v2, $hue);

			$blue	= 255 * self::hue2rgb($v1, $v2, $hue - (1 / 3));

			}

		return "#" . str_pad(dechex(round($red)), 2, "0", STR_PAD_LEFT) . str_pad(dechex(round($green)), 2, "0", STR_PAD_LEFT) . str_pad(dechex(round($blue)), 2, "0", STR_PAD_LEFT);

		}

	/**

	 * Apply hue to a rgb color value.

	 * 

	 * @param integer $v1 Value 1

	 * @param integer $v2 Value 2

	 * @param integer $hue Hue

	 * @return integer

	 */

	private function hue2rgb($v1, $v2, $hue)

		{

		if ($hue < 0)

			{

			$hue += 1;

			}

		if ($hue > 1)

			{

			$hue -= 1;

			}

		if ((6 * $hue) < 1)

			{

			return ($v1 + ($v2 - $v1) * 6 * $hue);

			}

		if ((2 * $hue) < 1)

			{

			return ($v2);

			}

		if ((3 * $hue) < 2)

			{

			return ($v1 + ($v2 - $v1) * (( 2 / 3) - $hue) * 6);

			}

		return $v1;

		}

	}



/**

 * This {@link aCssMinifierPlugin} will convert the font-weight values normal and bold to their numeric notation.

 * 

 * Example:

 * <code>

 * font-weight: normal;

 * font: bold 11px monospace;

 * </code>

 * 

 * Will get converted to:

 * <code>

 * font-weight:400;

 * font:700 11px monospace;

 * </code>

 *

 * @package		CssMin/Minifier/Pluginsn

 * @link		http://code.google.com/p/cssmin/

 * @author		Joe Scylla <joe.scylla@gmail.com>

 * @copyright	2008 - 2011 Joe Scylla <joe.scylla@gmail.com>

 * @license		http://opensource.org/licenses/mit-license.php MIT License

 * @version		3.0.1

 */

class CssConvertFontWeightMinifierPlugin extends aCssMinifierPlugin

	{

	/**

	 * Array of included declaration properties this plugin will process; others declaration properties will get

	 * ignored. 

	 * 

	 * @var array

	 */

	private $include = array

		(

		"font",

		"font-weight"

		);

	/**

	 * Regular expression matching the value.

	 * 

	 * @var string

	 */

	private $reMatch = null;

	/**

	 * Regular expression replace the value.

	 * 

	 * @var string

	 */

	private $reReplace = "\"\${1}\" . \$this->transformation[\"\${2}\"] . \"\${3}\"";

	/**

	 * Transformation table used by the {@link CssConvertFontWeightMinifierPlugin::$reReplace replace regular expression}.

	 * 

	 * @var array

	 */

	private $transformation = array

		(

		"normal"	=> "400",

 		"bold"		=> "700"

		);

	/**

	 * Overwrites {@link aCssMinifierPlugin::__construct()}.

	 * 

	 * The constructor will create the {@link CssConvertFontWeightMinifierPlugin::$reReplace replace regular expression}

	 * based on the {@link CssConvertFontWeightMinifierPlugin::$transformation transformation table}.

	 * 

	 * @param CssMinifier $minifier The CssMinifier object of this plugin.

	 * @return void

	 */

	public function __construct(CssMinifier $minifier)

		{

		$this->reMatch = "/(^|\s)+(" . implode("|", array_keys($this->transformation)). ")(\s|$)+/eiS";

		parent::__construct($minifier);

		}

	/**

	 * Implements {@link aCssMinifierPlugin::minify()}.

	 * 

	 * @param aCssToken $token Token to process

	 * @return boolean Return TRUE to break the processing of this token; FALSE to continue

	 */

	public function apply(aCssToken &$token)

		{

		if (in_array($token->Property, $this->include) && preg_match($this->reMatch, $token->Value, $m))

			{

			$token->Value = preg_replace($this->reMatch, $this->reReplace, $token->Value);

			}

		return false;

		}

	/**

	 * Implements {@link aMinifierPlugin::getTriggerTokens()}

	 * 

	 * @return array

	 */

	public function getTriggerTokens()

		{

		return array

			(

			"CssAtFontFaceDeclarationToken",

			"CssAtPageDeclarationToken",

			"CssRulesetDeclarationToken"

			);

		}

	}



/**

 * This {@link aCssMinifierPlugin} will compress several unit values to their short notations. Examples:

 * 

 * <code>

 * padding: 0.5em;

 * border: 0px;

 * margin: 0 0 0 0;

 * </code>

 * 

 * Will get compressed to:

 * 

 * <code>

 * padding:.5px;

 * border:0;

 * margin:0;

 * </code>

 * 

 * --

 *

 * @package		CssMin/Minifier/Plugins

 * @link		http://code.google.com/p/cssmin/

 * @author		Joe Scylla <joe.scylla@gmail.com>

 * @copyright	2008 - 2011 Joe Scylla <joe.scylla@gmail.com>

 * @license		http://opensource.org/licenses/mit-license.php MIT License

 * @version		3.0.1

 */

class CssCompressUnitValuesMinifierPlugin extends aCssMinifierPlugin

	{

	/**

	 * Regular expression used for matching and replacing unit values.

	 * 

	 * @var array

	 */

	private $re = array

		(

		"/(^| |-)0\.([0-9]+?)(0+)?(%|em|ex|px|in|cm|mm|pt|pc)/iS" => "\${1}.\${2}\${4}",

		"/(^| )-?(\.?)0(%|em|ex|px|in|cm|mm|pt|pc)/iS" => "\${1}0",

		"/(^0\s0\s0\s0)|(^0\s0\s0$)|(^0\s0$)/iS" => "0"

		);

	/**

	 * Regular expression matching the value.

	 * 

	 * @var string

	 */

	private $reMatch = "/(^| |-)0\.([0-9]+?)(0+)?(%|em|ex|px|in|cm|mm|pt|pc)|(^| )-?(\.?)0(%|em|ex|px|in|cm|mm|pt|pc)|(^0\s0\s0\s0$)|(^0\s0\s0$)|(^0\s0$)/iS";

	/**

	 * Implements {@link aCssMinifierPlugin::minify()}.

	 * 

	 * @param aCssToken $token Token to process

	 * @return boolean Return TRUE to break the processing of this token; FALSE to continue

	 */

	public function apply(aCssToken &$token)

		{

		if (preg_match($this->reMatch, $token->Value))

			{

			foreach ($this->re as $reMatch => $reReplace)

				{

				$token->Value = preg_replace($reMatch, $reReplace, $token->Value);

				}

			}

		return false;

		}

	/**

	 * Implements {@link aMinifierPlugin::getTriggerTokens()}

	 * 

	 * @return array

	 */

	public function getTriggerTokens()

		{

		return array

			(

			"CssAtFontFaceDeclarationToken",

			"CssAtPageDeclarationToken",

			"CssRulesetDeclarationToken"

			);

		}

	}



/**

 * This {@link aCssMinifierPlugin} compress the content of expresssion() declaration values.

 * 

 * For compression of expressions {@link https://github.com/rgrove/jsmin-php/ JSMin} will get used. JSMin have to be 

 * already included or loadable via {@link http://goo.gl/JrW54 PHP autoloading}. 

 * 

 * @package		CssMin/Minifier/Plugins

 * @link		http://code.google.com/p/cssmin/

 * @author		Joe Scylla <joe.scylla@gmail.com>

 * @copyright	2008 - 2011 Joe Scylla <joe.scylla@gmail.com>

 * @license		http://opensource.org/licenses/mit-license.php MIT License

 * @version		3.0.1

 */

class CssCompressExpressionValuesMinifierPlugin extends aCssMinifierPlugin

	{

	/**

	 * Implements {@link aCssMinifierPlugin::minify()}.

	 * 

	 * @param aCssToken $token Token to process

	 * @return boolean Return TRUE to break the processing of this token; FALSE to continue

	 */

	public function apply(aCssToken &$token)

		{

		if (class_exists("JSMin") && stripos($token->Value, "expression(") !== false)

			{

			$value	= $token->Value;

			$value	= substr($token->Value, stripos($token->Value, "expression(") + 10);

			$value	= trim(JSMin::minify($value));

			$token->Value = "expression(" . $value . ")";

			}

		return false;

		}

	/**

	 * Implements {@link aMinifierPlugin::getTriggerTokens()}

	 * 

	 * @return array

	 */

	public function getTriggerTokens()

		{

		return array

			(

			"CssAtFontFaceDeclarationToken",

			"CssAtPageDeclarationToken",

			"CssRulesetDeclarationToken"

			);

		}

	}



/**

 * This {@link aCssMinifierPlugin} will convert hexadecimal color value with 6 chars to their 3 char hexadecimal 

 * notation (if possible). 

 * 

 * Example:

 * <code>

 * color: #aabbcc;

 * </code>

 * 

 * Will get converted to:

 * <code>

 * color:#abc;

 * </code>

 * 

 * @package		CssMin/Minifier/Plugins

 * @link		http://code.google.com/p/cssmin/

 * @author		Joe Scylla <joe.scylla@gmail.com>

 * @copyright	2008 - 2011 Joe Scylla <joe.scylla@gmail.com>

 * @license		http://opensource.org/licenses/mit-license.php MIT License

 * @version		3.0.1

 */

class CssCompressColorValuesMinifierPlugin extends aCssMinifierPlugin

	{

	/**

	 * Regular expression matching 6 char hexadecimal color values.

	 * 

	 * @var string

	 */

	private $reMatch = "/\#([0-9a-f]{6})/iS";

	/**

	 * Implements {@link aCssMinifierPlugin::minify()}.

	 * 

	 * @param aCssToken $token Token to process

	 * @return boolean Return TRUE to break the processing of this token; FALSE to continue

	 */

	public function apply(aCssToken &$token)

		{

		if (strpos($token->Value, "#") !== false && preg_match($this->reMatch, $token->Value, $m))

			{

			$value = strtolower($m[1]);

			if ($value[0] == $value[1] && $value[2] == $value[3] && $value[4] == $value[5])

				{

				$token->Value = str_replace($m[0], "#" . $value[0] . $value[2] . $value[4], $token->Value);

				}

			}

		return false;

		}

	/**

	 * Implements {@link aMinifierPlugin::getTriggerTokens()}

	 * 

	 * @return array

	 */

	public function getTriggerTokens()

		{

		return array

			(

			"CssAtFontFaceDeclarationToken",

			"CssAtPageDeclarationToken",

			"CssRulesetDeclarationToken"

			);

		}

	}



/**

 * This {@link aCssToken CSS token} represents a CSS comment.

 * 

 * @package		CssMin/Tokens

 * @link		http://code.google.com/p/cssmin/

 * @author		Joe Scylla <joe.scylla@gmail.com>

 * @copyright	2008 - 2011 Joe Scylla <joe.scylla@gmail.com>

 * @license		http://opensource.org/licenses/mit-license.php MIT License

 * @version		3.0.1

 */

class CssCommentToken extends aCssToken

	{

	/**

	 * Comment as Text.

	 * 

	 * @var string

	 */

	public $Comment = "";

	/**

	 * Set the properties of a comment token.

	 * 

	 * @param string $comment Comment including comment delimiters 

	 * @return void

	 */

	public function __construct($comment)

		{

		$this->Comment = $comment;

		}

	/**

	 * Implements {@link aCssToken::__toString()}.

	 * 

	 * @return string

	 */

	public function __toString()

		{

		return $this->Comment;

		}

	}



/**

 * {@link aCssParserPlugin Parser plugin} for parsing comments.

 * 

 * Adds a {@link CssCommentToken} to the parser if a comment was found.

 * 

 * @package		CssMin/Parser/Plugins

 * @link		http://code.google.com/p/cssmin/

 * @author		Joe Scylla <joe.scylla@gmail.com>

 * @copyright	2008 - 2011 Joe Scylla <joe.scylla@gmail.com>

 * @license		http://opensource.org/licenses/mit-license.php MIT License

 * @version		3.0.1

 */

class CssCommentParserPlugin extends aCssParserPlugin

	{

	/**

	 * Implements {@link aCssParserPlugin::getTriggerChars()}.

	 * 

	 * @return array

	 */

	public function getTriggerChars()

		{

		return array("*", "/");

		}

	/**

	 * Implements {@link aCssParserPlugin::getTriggerStates()}.

	 * 

	 * @return array

	 */

	public function getTriggerStates()

		{

		return false;

		}

	/**

	 * Stored buffer for restore.

	 * 

	 * @var string

	 */

	private $restoreBuffer = "";

	/**

	 * Implements {@link aCssParserPlugin::parse()}.

	 * 

	 * @param integer $index Current index

	 * @param string $char Current char

	 * @param string $previousChar Previous char

	 * @return mixed TRUE will break the processing; FALSE continue with the next plugin; integer set a new index and break the processing

	 */

	public function parse($index, $char, $previousChar, $state)

		{

		if ($char === "*" && $previousChar === "/" && $state !== "T_COMMENT")

			{

			$this->parser->pushState("T_COMMENT");

			$this->parser->setExclusive(__CLASS__);

			$this->restoreBuffer = substr($this->parser->getAndClearBuffer(), 0, -2);

			}

		elseif ($char === "/" && $previousChar === "*" && $state === "T_COMMENT")

			{

			$this->parser->popState();

			$this->parser->unsetExclusive();

			$this->parser->appendToken(new CssCommentToken("/*" . $this->parser->getAndClearBuffer()));

			$this->parser->setBuffer($this->restoreBuffer);

			}

		else

			{

			return false;

			}

		return true;

		}

	}



/**

 * This {@link aCssToken CSS token} represents the start of a @variables at-rule block.

 *

 * @package		CssMin/Tokens

 * @link		http://code.google.com/p/cssmin/

 * @author		Joe Scylla <joe.scylla@gmail.com>

 * @copyright	2008 - 2011 Joe Scylla <joe.scylla@gmail.com>

 * @license		http://opensource.org/licenses/mit-license.php MIT License

 * @version		3.0.1

 */

class CssAtVariablesStartToken extends aCssAtBlockStartToken

	{

	/**

	 * Media types of the @variables at-rule block.

	 * 

	 * @var array

	 */

	public $MediaTypes = array();

	/**

	 * Set the properties of a @variables at-rule token.

	 * 

	 * @param array $mediaTypes Media types

	 * @return void

	 */

	public function __construct($mediaTypes = null)

		{

		$this->MediaTypes = $mediaTypes ? $mediaTypes : array("all");

		}

	/**

	 * Implements {@link aCssToken::__toString()}.

	 * 

	 * @return string

	 */

	public function __toString()

		{

		return "";

		}

	}



/**

 * {@link aCssParserPlugin Parser plugin} for parsing @variables at-rule block with including declarations.

 * 

 * Found @variables at-rule blocks will add a {@link CssAtVariablesStartToken} and {@link CssAtVariablesEndToken} to the 

 * parser; including declarations as {@link CssAtVariablesDeclarationToken}.

 * 

 * @package		CssMin/Parser/Plugins

 * @link		http://code.google.com/p/cssmin/

 * @author		Joe Scylla <joe.scylla@gmail.com>

 * @copyright	2008 - 2011 Joe Scylla <joe.scylla@gmail.com>

 * @license		http://opensource.org/licenses/mit-license.php MIT License

 * @version		3.0.1

 */

class CssAtVariablesParserPlugin extends aCssParserPlugin

	{

	/**

	 * Implements {@link aCssParserPlugin::getTriggerChars()}.

	 * 

	 * @return array

	 */

	public function getTriggerChars()

		{

		return array("@", "{", "}", ":", ";");

		}

	/**

	 * Implements {@link aCssParserPlugin::getTriggerStates()}.

	 * 

	 * @return array

	 */

	public function getTriggerStates()

		{

		return array("T_DOCUMENT", "T_AT_VARIABLES::PREPARE", "T_AT_VARIABLES", "T_AT_VARIABLES_DECLARATION");

		}

	/**

	 * Implements {@link aCssParserPlugin::parse()}.

	 * 

	 * @param integer $index Current index

	 * @param string $char Current char

	 * @param string $previousChar Previous char

	 * @return mixed TRUE will break the processing; FALSE continue with the next plugin; integer set a new index and break the processing

	 */

	public function parse($index, $char, $previousChar, $state)

		{

		// Start of @variables at-rule block

		if ($char === "@" && $state === "T_DOCUMENT" && strtolower(substr($this->parser->getSource(), $index, 10)) === "@variables")

			{

			$this->parser->pushState("T_AT_VARIABLES::PREPARE");

			$this->parser->clearBuffer();

			return $index + 10;

			}

		// Start of @variables declarations

		elseif ($char === "{" && $state === "T_AT_VARIABLES::PREPARE")

			{

			$this->parser->setState("T_AT_VARIABLES");

			$mediaTypes = array_filter(array_map("trim", explode(",", $this->parser->getAndClearBuffer("{"))));

			$this->parser->appendToken(new CssAtVariablesStartToken($mediaTypes));

			}

		// Start of @variables declaration

		if ($char === ":" && $state === "T_AT_VARIABLES")

			{

			$this->buffer = $this->parser->getAndClearBuffer(":");

			$this->parser->pushState("T_AT_VARIABLES_DECLARATION");

			}

		// Unterminated @variables declaration

		elseif ($char === ":" && $state === "T_AT_VARIABLES_DECLARATION")

			{

			// Ignore Internet Explorer filter declarations

			if ($this->buffer === "filter")

				{

				return false;

				}

			CssMin::triggerError(new CssError(__FILE__, __LINE__, __METHOD__ . ": Unterminated @variables declaration", $this->buffer . ":" . $this->parser->getBuffer() . "_"));

			}

		// End of @variables declaration

		elseif (($char === ";" || $char === "}") && $state === "T_AT_VARIABLES_DECLARATION")

			{

			$value = $this->parser->getAndClearBuffer(";}");

			if (strtolower(substr($value, -10, 10)) === "!important")

				{

				$value = trim(substr($value, 0, -10));

				$isImportant = true;

				}

			else

				{

				$isImportant = false;

				}

			$this->parser->popState();

			$this->parser->appendToken(new CssAtVariablesDeclarationToken($this->buffer, $value, $isImportant));

			$this->buffer = "";

			}

		// End of @variables at-rule block

		elseif ($char === "}" && $state === "T_AT_VARIABLES")

			{

			$this->parser->popState();

			$this->parser->clearBuffer();

			$this->parser->appendToken(new CssAtVariablesEndToken());

			}

		else

			{

			return false;

			}

		return true;

		}

	}



/**

 * This {@link aCssToken CSS token} represents the end of a @variables at-rule block.

 *

 * @package		CssMin/Tokens

 * @link		http://code.google.com/p/cssmin/

 * @author		Joe Scylla <joe.scylla@gmail.com>

 * @copyright	2008 - 2011 Joe Scylla <joe.scylla@gmail.com>

 * @license		http://opensource.org/licenses/mit-license.php MIT License

 * @version		3.0.1

 */

class CssAtVariablesEndToken extends aCssAtBlockEndToken

	{

	/**

	 * Implements {@link aCssToken::__toString()}.

	 * 

	 * @return string

	 */

	public function __toString()

		{

		return "";

		}

	}



/**

 * This {@link aCssToken CSS token} represents a declaration of a @variables at-rule block.

 * 

 * @package		CssMin/Tokens

 * @link		http://code.google.com/p/cssmin/

 * @author		Joe Scylla <joe.scylla@gmail.com>

 * @copyright	2008 - 2011 Joe Scylla <joe.scylla@gmail.com>

 * @license		http://opensource.org/licenses/mit-license.php MIT License

 * @version		3.0.1

 */

class CssAtVariablesDeclarationToken extends aCssDeclarationToken

	{

	/**

	 * Implements {@link aCssToken::__toString()}.

	 * 

	 * @return string

	 */

	public function __toString()

		{

		return "";

		}

	}



/**

* This {@link aCssToken CSS token} represents the start of a @page at-rule block.

 *

 * @package		CssMin/Tokens

 * @link		http://code.google.com/p/cssmin/

 * @author		Joe Scylla <joe.scylla@gmail.com>

 * @copyright	2008 - 2011 Joe Scylla <joe.scylla@gmail.com>

 * @license		http://opensource.org/licenses/mit-license.php MIT License

 * @version		3.0.1

 */

class CssAtPageStartToken extends aCssAtBlockStartToken

	{

	/**

	 * Selector.

	 * 

	 * @var string

	 */

	public $Selector = "";

	/**

	 * Sets the properties of the @page at-rule.

	 * 

	 * @param string $selector Selector

	 * @return void

	 */

	public function __construct($selector = "")

		{

		$this->Selector = $selector;

		}

	/**

	 * Implements {@link aCssToken::__toString()}.

	 * 

	 * @return string

	 */

	public function __toString()

		{

		return "@page" . ($this->Selector ? " " . $this->Selector : "") . "{";

		}

	}



/**

 * {@link aCssParserPlugin Parser plugin} for parsing @page at-rule block with including declarations.

 * 

 * Found @page at-rule blocks will add a {@link CssAtPageStartToken} and {@link CssAtPageEndToken} to the 

 * parser; including declarations as {@link CssAtPageDeclarationToken}.

 * 

 * @package		CssMin/Parser/Plugins

 * @link		http://code.google.com/p/cssmin/

 * @author		Joe Scylla <joe.scylla@gmail.com>

 * @copyright	2008 - 2011 Joe Scylla <joe.scylla@gmail.com>

 * @license		http://opensource.org/licenses/mit-license.php MIT License

 * @version		3.0.1

 */

class CssAtPageParserPlugin extends aCssParserPlugin

	{

	/**

	 * Implements {@link aCssParserPlugin::getTriggerChars()}.

	 * 

	 * @return array

	 */

	public function getTriggerChars()

		{

		return array("@", "{", "}", ":", ";");

		}

	/**

	 * Implements {@link aCssParserPlugin::getTriggerStates()}.

	 * 

	 * @return array

	 */

	public function getTriggerStates()

		{

		return array("T_DOCUMENT", "T_AT_PAGE::SELECTOR", "T_AT_PAGE", "T_AT_PAGE_DECLARATION");

		}

	/**

	 * Implements {@link aCssParserPlugin::parse()}.

	 * 

	 * @param integer $index Current index

	 * @param string $char Current char

	 * @param string $previousChar Previous char

	 * @return mixed TRUE will break the processing; FALSE continue with the next plugin; integer set a new index and break the processing

	 */

	public function parse($index, $char, $previousChar, $state)

		{

		// Start of @page at-rule block

		if ($char === "@" && $state === "T_DOCUMENT" && strtolower(substr($this->parser->getSource(), $index, 5)) === "@page")

			{

			$this->parser->pushState("T_AT_PAGE::SELECTOR");

			$this->parser->clearBuffer();

			return $index + 5;

			}

		// Start of @page declarations

		elseif ($char === "{" && $state === "T_AT_PAGE::SELECTOR")

			{

			$selector = $this->parser->getAndClearBuffer("{");

			$this->parser->setState("T_AT_PAGE");

			$this->parser->clearBuffer();

			$this->parser->appendToken(new CssAtPageStartToken($selector));

			}

		// Start of @page declaration

		elseif ($char === ":" && $state === "T_AT_PAGE")

			{

			$this->parser->pushState("T_AT_PAGE_DECLARATION");

			$this->buffer = $this->parser->getAndClearBuffer(":", true);

			}

		// Unterminated @font-face declaration

		elseif ($char === ":" && $state === "T_AT_PAGE_DECLARATION")

			{

			// Ignore Internet Explorer filter declarations

			if ($this->buffer === "filter")

				{

				return false;

				}

			CssMin::triggerError(new CssError(__FILE__, __LINE__, __METHOD__ . ": Unterminated @page declaration", $this->buffer . ":" . $this->parser->getBuffer() . "_"));

			}

		// End of @page declaration

		elseif (($char === ";" || $char === "}") && $state == "T_AT_PAGE_DECLARATION")

			{

			$value = $this->parser->getAndClearBuffer(";}");

			if (strtolower(substr($value, -10, 10)) == "!important")

				{

				$value = trim(substr($value, 0, -10));

				$isImportant = true;

				}

			else

				{

				$isImportant = false;

				}

			$this->parser->popState();

			$this->parser->appendToken(new CssAtPageDeclarationToken($this->buffer, $value, $isImportant));

			// --

			if ($char === "}")

				{

				$this->parser->popState();

				$this->parser->appendToken(new CssAtPageEndToken());

				}

			$this->buffer = "";

			}

		// End of @page at-rule block

		elseif ($char === "}" && $state === "T_AT_PAGE")

			{

			$this->parser->popState();

			$this->parser->clearBuffer();

			$this->parser->appendToken(new CssAtPageEndToken());

			}

		else

			{

			return false;

			}

		return true;

		}

	}



/**

 * This {@link aCssToken CSS token} represents the end of a @page at-rule block.

 *

 * @package		CssMin/Tokens

 * @link		http://code.google.com/p/cssmin/

 * @author		Joe Scylla <joe.scylla@gmail.com>

 * @copyright	2008 - 2011 Joe Scylla <joe.scylla@gmail.com>

 * @license		http://opensource.org/licenses/mit-license.php MIT License

 * @version		3.0.1

 */

class CssAtPageEndToken extends aCssAtBlockEndToken

	{

	

	}



/**

 * This {@link aCssToken CSS token} represents a declaration of a @page at-rule block.

 * 

 * @package		CssMin/Tokens

 * @link		http://code.google.com/p/cssmin/

 * @author		Joe Scylla <joe.scylla@gmail.com>

 * @copyright	2008 - 2011 Joe Scylla <joe.scylla@gmail.com>

 * @license		http://opensource.org/licenses/mit-license.php MIT License

 * @version		3.0.1

 */

class CssAtPageDeclarationToken extends aCssDeclarationToken

	{

	

	}



/**

 * This {@link aCssToken CSS token} represents the start of a @media at-rule block.

 *

 * @package		CssMin/Tokens

 * @link		http://code.google.com/p/cssmin/

 * @author		Joe Scylla <joe.scylla@gmail.com>

 * @copyright	2008 - 2011 Joe Scylla <joe.scylla@gmail.com>

 * @license		http://opensource.org/licenses/mit-license.php MIT License

 * @version		3.0.1

 */

class CssAtMediaStartToken extends aCssAtBlockStartToken

	{

	/**

	 * Sets the properties of the @media at-rule.

	 * 

	 * @param array $mediaTypes Media types

	 * @return void

	 */

	public function __construct(array $mediaTypes = array())

		{

		$this->MediaTypes = $mediaTypes;

		}

	/**

	 * Implements {@link aCssToken::__toString()}.

	 * 

	 * @return string

	 */

	public function __toString()

		{

		return "@media " . implode(",", $this->MediaTypes) . "{";

		}

	}



/**

 * {@link aCssParserPlugin Parser plugin} for parsing @media at-rule block.

 * 

 * Found @media at-rule blocks will add a {@link CssAtMediaStartToken} and {@link CssAtMediaEndToken} to the parser. 

 * This plugin will also set the the current media types using {@link CssParser::setMediaTypes()} and

 * {@link CssParser::unsetMediaTypes()}.

 *

 * @package		CssMin/Parser/Plugins

 * @link		http://code.google.com/p/cssmin/

 * @author		Joe Scylla <joe.scylla@gmail.com>

 * @copyright	2008 - 2011 Joe Scylla <joe.scylla@gmail.com>

 * @license		http://opensource.org/licenses/mit-license.php MIT License

 * @version		3.0.1

 */

class CssAtMediaParserPlugin extends aCssParserPlugin

	{

	/**

	 * Implements {@link aCssParserPlugin::getTriggerChars()}.

	 * 

	 * @return array

	 */

	public function getTriggerChars()

		{

		return array("@", "{", "}");

		}

	/**

	 * Implements {@link aCssParserPlugin::getTriggerStates()}.

	 * 

	 * @return array

	 */

	public function getTriggerStates()

		{

		return array("T_DOCUMENT", "T_AT_MEDIA::PREPARE", "T_AT_MEDIA");

		}

	/**

	 * Implements {@link aCssParserPlugin::parse()}.

	 * 

	 * @param integer $index Current index

	 * @param string $char Current char

	 * @param string $previousChar Previous char

	 * @return mixed TRUE will break the processing; FALSE continue with the next plugin; integer set a new index and break the processing

	 */

	public function parse($index, $char, $previousChar, $state)

		{

		if ($char === "@" && $state === "T_DOCUMENT" && strtolower(substr($this->parser->getSource(), $index, 6)) === "@media")

			{

			$this->parser->pushState("T_AT_MEDIA::PREPARE");

			$this->parser->clearBuffer();

			return $index + 6;

			}

		elseif ($char === "{" && $state === "T_AT_MEDIA::PREPARE")

			{

			$mediaTypes = array_filter(array_map("trim", explode(",", $this->parser->getAndClearBuffer("{"))));

			$this->parser->setMediaTypes($mediaTypes);

			$this->parser->setState("T_AT_MEDIA");

			$this->parser->appendToken(new CssAtMediaStartToken($mediaTypes));

			}

		elseif ($char === "}" && $state === "T_AT_MEDIA")

			{

			$this->parser->appendToken(new CssAtMediaEndToken());

			$this->parser->clearBuffer();

			$this->parser->unsetMediaTypes();

			$this->parser->popState();

			}

		else

			{

			return false;

			}

		return true;

		}

	}



/**

 * This {@link aCssToken CSS token} represents the end of a @media at-rule block.

 *

 * @package		CssMin/Tokens

 * @link		http://code.google.com/p/cssmin/

 * @author		Joe Scylla <joe.scylla@gmail.com>

 * @copyright	2008 - 2011 Joe Scylla <joe.scylla@gmail.com>

 * @license		http://opensource.org/licenses/mit-license.php MIT License

 * @version		3.0.1

 */

class CssAtMediaEndToken extends aCssAtBlockEndToken

	{

	

	}



/**

 * This {@link aCssToken CSS token} represents the start of a @keyframes at-rule block.

 *

 * @package		CssMin/Tokens

 * @link		http://code.google.com/p/cssmin/

 * @author		Joe Scylla <joe.scylla@gmail.com>

 * @copyright	2008 - 2011 Joe Scylla <joe.scylla@gmail.com>

 * @license		http://opensource.org/licenses/mit-license.php MIT License

 * @version		3.0.1

 */

class CssAtKeyframesStartToken extends aCssAtBlockStartToken

	{

	/**

	 * Name of the at-rule.

	 * 

	 * @var string

	 */

	public $AtRuleName = "keyframes";

	/**

	 * Name

	 * 

	 * @var string

	 */

	public $Name = "";

	/**

	 * Sets the properties of the @page at-rule.

	 * 

	 * @param string $selector Selector

	 * @return void

	 */

	public function __construct($name, $atRuleName = null)

		{

		$this->Name = $name;

		if (!is_null($atRuleName))

			{

			$this->AtRuleName = $atRuleName;

			}

		}

	/**

	 * Implements {@link aCssToken::__toString()}.

	 * 

	 * @return string

	 */

	public function __toString()

		{

		return "@" . $this->AtRuleName . " \"" . $this->Name . "\"{";

		}

	}



/**

 * This {@link aCssToken CSS token} represents the start of a ruleset of a @keyframes at-rule block.

 * 

 * @package		CssMin/Tokens

 * @link		http://code.google.com/p/cssmin/

 * @author		Joe Scylla <joe.scylla@gmail.com>

 * @copyright	2008 - 2011 Joe Scylla <joe.scylla@gmail.com>

 * @license		http://opensource.org/licenses/mit-license.php MIT License

 * @version		3.0.1

 */

class CssAtKeyframesRulesetStartToken extends aCssRulesetStartToken

	{

	/**

	 * Array of selectors.

	 * 

	 * @var array

	 */

	public $Selectors = array();

	/**

	 * Set the properties of a ruleset token.

	 * 

	 * @param array $selectors Selectors of the ruleset 

	 * @return void

	 */

	public function __construct(array $selectors = array())

		{

		$this->Selectors = $selectors;

		}

	/**

	 * Implements {@link aCssToken::__toString()}.

	 * 

	 * @return string

	 */

	public function __toString()

		{

		return implode(",", $this->Selectors) . "{";

		}

	}



/**

 * This {@link aCssToken CSS token} represents the end of a ruleset of a @keyframes at-rule block.

 * 

 * @package		CssMin/Tokens

 * @link		http://code.google.com/p/cssmin/

 * @author		Joe Scylla <joe.scylla@gmail.com>

 * @copyright	2008 - 2011 Joe Scylla <joe.scylla@gmail.com>

 * @license		http://opensource.org/licenses/mit-license.php MIT License

 * @version		3.0.1

 */

class CssAtKeyframesRulesetEndToken extends aCssRulesetEndToken

	{

	

	}



/**

 * This {@link aCssToken CSS token} represents a ruleset declaration of a @keyframes at-rule block.

 *

 * @package		CssMin/Tokens

 * @link		http://code.google.com/p/cssmin/

 * @author		Joe Scylla <joe.scylla@gmail.com>

 * @copyright	2008 - 2011 Joe Scylla <joe.scylla@gmail.com>

 * @license		http://opensource.org/licenses/mit-license.php MIT License

 * @version		3.0.1

 */

class CssAtKeyframesRulesetDeclarationToken extends aCssDeclarationToken

	{

	

	}



/**

 * {@link aCssParserPlugin Parser plugin} for parsing @keyframes at-rule blocks, rulesets and declarations.

 * 

 * @package		CssMin/Parser/Plugins

 * @link		http://code.google.com/p/cssmin/

 * @author		Joe Scylla <joe.scylla@gmail.com>

 * @copyright	2008 - 2011 Joe Scylla <joe.scylla@gmail.com>

 * @license		http://opensource.org/licenses/mit-license.php MIT License

 * @version		3.0.1

 */

class CssAtKeyframesParserPlugin extends aCssParserPlugin

	{

	/**

	 * @var string Keyword

	 */

	private $atRuleName = "";

	/**

	 * Selectors.

	 * 

	 * @var array

	 */

	private $selectors = array();

	/**

	 * Implements {@link aCssParserPlugin::getTriggerChars()}.

	 * 

	 * @return array

	 */

	public function getTriggerChars()

		{

		return array("@", "{", "}", ":", ",", ";");

		}

	/**

	 * Implements {@link aCssParserPlugin::getTriggerStates()}.

	 * 

	 * @return array

	 */

	public function getTriggerStates()

		{

		return array("T_DOCUMENT", "T_AT_KEYFRAMES::NAME", "T_AT_KEYFRAMES", "T_AT_KEYFRAMES_RULESETS", "T_AT_KEYFRAMES_RULESET", "T_AT_KEYFRAMES_RULESET_DECLARATION");

		}

	/**

	 * Implements {@link aCssParserPlugin::parse()}.

	 * 

	 * @param integer $index Current index

	 * @param string $char Current char

	 * @param string $previousChar Previous char

	 * @return mixed TRUE will break the processing; FALSE continue with the next plugin; integer set a new index and break the processing

	 */

	public function parse($index, $char, $previousChar, $state)

		{

		// Start of @keyframes at-rule block

		if ($char === "@" && $state === "T_DOCUMENT" && strtolower(substr($this->parser->getSource(), $index, 10)) === "@keyframes") 

			{

			$this->atRuleName = "keyframes";

			$this->parser->pushState("T_AT_KEYFRAMES::NAME");

			$this->parser->clearBuffer();

			return $index + 10;

			}

		// Start of @keyframes at-rule block (@-moz-keyframes)

		elseif ($char === "@" && $state === "T_DOCUMENT" && strtolower(substr($this->parser->getSource(), $index, 15)) === "@-moz-keyframes")

			{

			$this->atRuleName = "-moz-keyframes";

			$this->parser->pushState("T_AT_KEYFRAMES::NAME");

			$this->parser->clearBuffer();

			return $index + 15;

			}

		// Start of @keyframes at-rule block (@-webkit-keyframes)

		elseif ($char === "@" && $state === "T_DOCUMENT" && strtolower(substr($this->parser->getSource(), $index, 18)) === "@-webkit-keyframes")

			{

			$this->atRuleName = "-webkit-keyframes";

			$this->parser->pushState("T_AT_KEYFRAMES::NAME");

			$this->parser->clearBuffer();

			return $index + 18;

			}

		// Start of @keyframes rulesets

		elseif ($char === "{" && $state === "T_AT_KEYFRAMES::NAME")

			{

			$name = $this->parser->getAndClearBuffer("{\"'");

			$this->parser->setState("T_AT_KEYFRAMES_RULESETS");

			$this->parser->clearBuffer();

			$this->parser->appendToken(new CssAtKeyframesStartToken($name, $this->atRuleName));

			}

		// Start of @keyframe ruleset and selectors

		if ($char === "," && $state === "T_AT_KEYFRAMES_RULESETS")

			{

			$this->selectors[] = $this->parser->getAndClearBuffer(",{");

			}

		// Start of a @keyframes ruleset

		elseif ($char === "{" && $state === "T_AT_KEYFRAMES_RULESETS")

			{

			if ($this->parser->getBuffer() !== "")

				{

				$this->selectors[] = $this->parser->getAndClearBuffer(",{");

				$this->parser->pushState("T_AT_KEYFRAMES_RULESET");

				$this->parser->appendToken(new CssAtKeyframesRulesetStartToken($this->selectors));

				$this->selectors = array();

				}

			}

		// Start of @keyframes ruleset declaration

		elseif ($char === ":" && $state === "T_AT_KEYFRAMES_RULESET")

			{

			$this->parser->pushState("T_AT_KEYFRAMES_RULESET_DECLARATION");

			$this->buffer = $this->parser->getAndClearBuffer(":;", true);

			}

		// Unterminated @keyframes ruleset declaration

		elseif ($char === ":" && $state === "T_AT_KEYFRAMES_RULESET_DECLARATION")

			{

			// Ignore Internet Explorer filter declarations

			if ($this->buffer === "filter")

				{

				return false;

				}

			CssMin::triggerError(new CssError(__FILE__, __LINE__, __METHOD__ . ": Unterminated @keyframes ruleset declaration", $this->buffer . ":" . $this->parser->getBuffer() . "_"));

			}

		// End of declaration

		elseif (($char === ";" || $char === "}") && $state === "T_AT_KEYFRAMES_RULESET_DECLARATION")

			{

			$value = $this->parser->getAndClearBuffer(";}");

			if (strtolower(substr($value, -10, 10)) === "!important")

				{

				$value = trim(substr($value, 0, -10));

				$isImportant = true;

				}

			else

				{

				$isImportant = false;

				}

			$this->parser->popState();

			$this->parser->appendToken(new CssAtKeyframesRulesetDeclarationToken($this->buffer, $value, $isImportant));

			// Declaration ends with a right curly brace; so we have to end the ruleset

			if ($char === "}")

				{

				$this->parser->appendToken(new CssAtKeyframesRulesetEndToken());

				$this->parser->popState();

				}

			$this->buffer = "";

			}

		// End of @keyframes ruleset

		elseif ($char === "}" && $state === "T_AT_KEYFRAMES_RULESET")

			{

			$this->parser->clearBuffer();

			

			$this->parser->popState();

			$this->parser->appendToken(new CssAtKeyframesRulesetEndToken());

			}

		// End of @keyframes rulesets

		elseif ($char === "}" && $state === "T_AT_KEYFRAMES_RULESETS")

			{

			$this->parser->clearBuffer();

			$this->parser->popState();

			$this->parser->appendToken(new CssAtKeyframesEndToken());

			}

		else

			{

			return false;

			}

		return true;

		}

	}



/**

 * This {@link aCssToken CSS token} represents the end of a @keyframes at-rule block.

 *

 * @package		CssMin/Tokens

 * @link		http://code.google.com/p/cssmin/

 * @author		Joe Scylla <joe.scylla@gmail.com>

 * @copyright	2008 - 2011 Joe Scylla <joe.scylla@gmail.com>

 * @license		http://opensource.org/licenses/mit-license.php MIT License

 * @version		3.0.1

 */

class CssAtKeyframesEndToken extends aCssAtBlockEndToken

	{

	

	}



/**

 * This {@link aCssToken CSS token} represents a @import at-rule.

 * 

 * @package		CssMin/Tokens

 * @link		http://code.google.com/p/cssmin/

 * @author		Joe Scylla <joe.scylla@gmail.com>

 * @copyright	2008 - 2011 Joe Scylla <joe.scylla@gmail.com>

 * @license		http://opensource.org/licenses/mit-license.php MIT License

 * @version		3.0.1.b1 (2001-02-22)

 */

class CssAtImportToken extends aCssToken

	{

	/**

	 * Import path of the @import at-rule.

	 * 

	 * @var string

	 */

	public $Import = "";

	/**

	 * Media types of the @import at-rule.

	 * 

	 * @var array

	 */

	public $MediaTypes = array();

	/**

	 * Set the properties of a @import at-rule token.

	 * 

	 * @param string $import Import path

	 * @param array $mediaTypes Media types

	 * @return void

	 */

	public function __construct($import, $mediaTypes)

		{

		$this->Import		= $import;

		$this->MediaTypes	= $mediaTypes ? $mediaTypes : array();

		}

	/**

	 * Implements {@link aCssToken::__toString()}.

	 * 

	 * @return string

	 */

	public function __toString()

		{

		return "@import \"" . $this->Import . "\"" . (count($this->MediaTypes) > 0 ? " "  . implode(",", $this->MediaTypes) : ""). ";";

		}

	}



/**

 * {@link aCssParserPlugin Parser plugin} for parsing @import at-rule.

 * 

 * If a @import at-rule was found this plugin will add a {@link CssAtImportToken} to the parser.

 * 

 * @package		CssMin/Parser/Plugins

 * @link		http://code.google.com/p/cssmin/

 * @author		Joe Scylla <joe.scylla@gmail.com>

 * @copyright	2008 - 2011 Joe Scylla <joe.scylla@gmail.com>

 * @license		http://opensource.org/licenses/mit-license.php MIT License

 * @version		3.0.1

 */

class CssAtImportParserPlugin extends aCssParserPlugin

	{

	/**

	 * Implements {@link aCssParserPlugin::getTriggerChars()}.

	 * 

	 * @return array

	 */

	public function getTriggerChars()

		{

		return array("@", ";", ",", "\n");

		}

	/**

	 * Implements {@link aCssParserPlugin::getTriggerStates()}.

	 * 

	 * @return array

	 */

	public function getTriggerStates()

		{

		return array("T_DOCUMENT", "T_AT_IMPORT");

		}

	/**

	 * Implements {@link aCssParserPlugin::parse()}.

	 * 

	 * @param integer $index Current index

	 * @param string $char Current char

	 * @param string $previousChar Previous char

	 * @return mixed TRUE will break the processing; FALSE continue with the next plugin; integer set a new index and break the processing

	 */

	public function parse($index, $char, $previousChar, $state)

		{

		if ($char === "@" && $state === "T_DOCUMENT" && strtolower(substr($this->parser->getSource(), $index, 7)) === "@import")

			{

			$this->parser->pushState("T_AT_IMPORT");

			$this->parser->clearBuffer();

			return $index + 7;

			}

		elseif (($char === ";" || $char === "\n") && $state === "T_AT_IMPORT")

			{

			$this->buffer = $this->parser->getAndClearBuffer(";");

			$pos = false;

			foreach (array(")", "\"", "'") as $needle)

				{

				if (($pos = strrpos($this->buffer, $needle)) !== false)

					{

					break;

					}

				}

			$import = substr($this->buffer, 0, $pos + 1);

			if (stripos($import, "url(") === 0)

				{

				$import = substr($import, 4, -1);

				}

			$import = trim($import, " \t\n\r\0\x0B'\"");

			$mediaTypes = array_filter(array_map("trim", explode(",", trim(substr($this->buffer, $pos + 1), " \t\n\r\0\x0B{"))));

			if ($pos)

				{

				$this->parser->appendToken(new CssAtImportToken($import, $mediaTypes));

				}

			else

				{

				CssMin::triggerError(new CssError(__FILE__, __LINE__, __METHOD__ . ": Invalid @import at-rule syntax", $this->parser->buffer));

				}

			$this->parser->popState();

			}

		else

			{

			return false;

			}

		return true;

		}

	}



/**

 * This {@link aCssToken CSS token} represents the start of a @font-face at-rule block.

 *

 * @package		CssMin/Tokens

 * @link		http://code.google.com/p/cssmin/

 * @author		Joe Scylla <joe.scylla@gmail.com>

 * @copyright	2008 - 2011 Joe Scylla <joe.scylla@gmail.com>

 * @license		http://opensource.org/licenses/mit-license.php MIT License

 * @version		3.0.1

 */

class CssAtFontFaceStartToken extends aCssAtBlockStartToken

	{

	/**

	 * Implements {@link aCssToken::__toString()}.

	 * 

	 * @return string

	 */

	public function __toString()

		{

		return "@font-face{";

		}

	}



/**

 * {@link aCssParserPlugin Parser plugin} for parsing @font-face at-rule block with including declarations.

 * 

 * Found @font-face at-rule blocks will add a {@link CssAtFontFaceStartToken} and {@link CssAtFontFaceEndToken} to the 

 * parser; including declarations as {@link CssAtFontFaceDeclarationToken}.

 * 

 * @package		CssMin/Parser/Plugins

 * @link		http://code.google.com/p/cssmin/

 * @author		Joe Scylla <joe.scylla@gmail.com>

 * @copyright	2008 - 2011 Joe Scylla <joe.scylla@gmail.com>

 * @license		http://opensource.org/licenses/mit-license.php MIT License

 * @version		3.0.1

 */

class CssAtFontFaceParserPlugin extends aCssParserPlugin

	{



	/**

	 * Implements {@link aCssParserPlugin::getTriggerChars()}.

	 * 

	 * @return array

	 */

	public function getTriggerChars()

		{

		return array("@", "{", "}", ":", ";");

		}

	/**

	 * Implements {@link aCssParserPlugin::getTriggerStates()}.

	 * 

	 * @return array

	 */

	public function getTriggerStates()

		{

		return array("T_DOCUMENT", "T_AT_FONT_FACE::PREPARE", "T_AT_FONT_FACE", "T_AT_FONT_FACE_DECLARATION");

		}

	/**

	 * Implements {@link aCssParserPlugin::parse()}.

	 * 

	 * @param integer $index Current index

	 * @param string $char Current char

	 * @param string $previousChar Previous char

	 * @return mixed TRUE will break the processing; FALSE continue with the next plugin; integer set a new index and break the processing

	 */

	public function parse($index, $char, $previousChar, $state)

		{

		// Start of @font-face at-rule block

		if ($char === "@" && $state === "T_DOCUMENT" && strtolower(substr($this->parser->getSource(), $index, 10)) === "@font-face")

			{

			$this->parser->pushState("T_AT_FONT_FACE::PREPARE");

			$this->parser->clearBuffer();

			return $index + 10;

			}

		// Start of @font-face declarations

		elseif ($char === "{" && $state === "T_AT_FONT_FACE::PREPARE")

			{

			$this->parser->setState("T_AT_FONT_FACE");

			$this->parser->clearBuffer();

			$this->parser->appendToken(new CssAtFontFaceStartToken());

			}

		// Start of @font-face declaration

		elseif ($char === ":" && $state === "T_AT_FONT_FACE")

			{

			$this->parser->pushState("T_AT_FONT_FACE_DECLARATION");

			$this->buffer = $this->parser->getAndClearBuffer(":", true);

			}

		// Unterminated @font-face declaration

		elseif ($char === ":" && $state === "T_AT_FONT_FACE_DECLARATION")

			{

			// Ignore Internet Explorer filter declarations

			if ($this->buffer === "filter")

				{

				return false;

				}

			CssMin::triggerError(new CssError(__FILE__, __LINE__, __METHOD__ . ": Unterminated @font-face declaration", $this->buffer . ":" . $this->parser->getBuffer() . "_"));

			}

		// End of @font-face declaration

		elseif (($char === ";" || $char === "}") && $state === "T_AT_FONT_FACE_DECLARATION")

			{

			$value = $this->parser->getAndClearBuffer(";}");

			if (strtolower(substr($value, -10, 10)) === "!important")

				{

				$value = trim(substr($value, 0, -10));

				$isImportant = true;

				}

			else

				{

				$isImportant = false;

				}

			$this->parser->popState();

			$this->parser->appendToken(new CssAtFontFaceDeclarationToken($this->buffer, $value, $isImportant));

			$this->buffer = "";

			// --

			if ($char === "}")

				{

				$this->parser->appendToken(new CssAtFontFaceEndToken());

				$this->parser->popState();

				}

			}

		// End of @font-face at-rule block

		elseif ($char === "}" && $state === "T_AT_FONT_FACE")

			{

			$this->parser->appendToken(new CssAtFontFaceEndToken());

			$this->parser->clearBuffer();

			$this->parser->popState();

			}

		else

			{

			return false;

			}

		return true;

		}

	}



/**

 * This {@link aCssToken CSS token} represents the end of a @font-face at-rule block.

 *

 * @package		CssMin/Tokens

 * @link		http://code.google.com/p/cssmin/

 * @author		Joe Scylla <joe.scylla@gmail.com>

 * @copyright	2008 - 2011 Joe Scylla <joe.scylla@gmail.com>

 * @license		http://opensource.org/licenses/mit-license.php MIT License

 * @version		3.0.1

 */

class CssAtFontFaceEndToken extends aCssAtBlockEndToken

	{

	

	}



/**

 * This {@link aCssToken CSS token} represents a declaration of a @font-face at-rule block.

 *

 * @package		CssMin/Tokens

 * @link		http://code.google.com/p/cssmin/

 * @author		Joe Scylla <joe.scylla@gmail.com>

 * @copyright	2008 - 2011 Joe Scylla <joe.scylla@gmail.com>

 * @license		http://opensource.org/licenses/mit-license.php MIT License

 * @version		3.0.1

 */

class CssAtFontFaceDeclarationToken extends aCssDeclarationToken

	{

	

	}



/**

 * This {@link aCssToken CSS token} represents a @charset at-rule.

 * 

 * @package		CssMin/Tokens

 * @link		http://code.google.com/p/cssmin/

 * @author		Joe Scylla <joe.scylla@gmail.com>

 * @copyright	2008 - 2011 Joe Scylla <joe.scylla@gmail.com>

 * @license		http://opensource.org/licenses/mit-license.php MIT License

 * @version		3.0.1

 */

class CssAtCharsetToken extends aCssToken

	{

	/**

	 * Charset of the @charset at-rule.

	 * 

	 * @var string

	 */

	public $Charset = "";

	/**

	 * Set the properties of @charset at-rule token. 

	 * 

	 * @param string $charset Charset of the @charset at-rule token

	 * @return void

	 */

	public function __construct($charset)

		{

		$this->Charset = $charset;

		}

	/**

	 * Implements {@link aCssToken::__toString()}.

	 * 

	 * @return string

	 */

	public function __toString()

		{

		return "@charset " . $this->Charset . ";";

		}

	}



/**

 * {@link aCssParserPlugin Parser plugin} for parsing @charset at-rule.

 * 

 * If a @charset at-rule was found this plugin will add a {@link CssAtCharsetToken} to the parser.

 *

 * @package		CssMin/Parser/Plugins

 * @link		http://code.google.com/p/cssmin/

 * @author		Joe Scylla <joe.scylla@gmail.com>

 * @copyright	2008 - 2011 Joe Scylla <joe.scylla@gmail.com>

 * @license		http://opensource.org/licenses/mit-license.php MIT License

 * @version		3.0.1

 */

class CssAtCharsetParserPlugin extends aCssParserPlugin

	{

	/**

	 * Implements {@link aCssParserPlugin::getTriggerChars()}.

	 * 

	 * @return array

	 */

	public function getTriggerChars()

		{

		return array("@", ";", "\n");

		}

	/**

	 * Implements {@link aCssParserPlugin::getTriggerStates()}.

	 * 

	 * @return array

	 */

	public function getTriggerStates()

		{

		return array("T_DOCUMENT", "T_AT_CHARSET");

		}

	/**

	 * Implements {@link aCssParserPlugin::parse()}.

	 * 

	 * @param integer $index Current index

	 * @param string $char Current char

	 * @param string $previousChar Previous char

	 * @return mixed TRUE will break the processing; FALSE continue with the next plugin; integer set a new index and break the processing

	 */

	public function parse($index, $char, $previousChar, $state)

		{

		if ($char === "@" && $state === "T_DOCUMENT" && strtolower(substr($this->parser->getSource(), $index, 8)) === "@charset")

			{

			$this->parser->pushState("T_AT_CHARSET");

			$this->parser->clearBuffer();

			return $index + 8;

			}

		elseif (($char === ";" || $char === "\n") && $state === "T_AT_CHARSET")

			{

			$charset = $this->parser->getAndClearBuffer(";");

			$this->parser->popState();

			$this->parser->appendToken(new CssAtCharsetToken($charset));

			}

		else

			{

			return false;

			}

		return true;

		}

	}



 

?> 