Вход Регистрация
Файл: concrete5.7.5.6/concrete/vendor/natxet/CssMin/src/CssMin.php
Строк: 6183
<?php
/**
 * 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
 */
/**
 * Abstract definition of a CSS token class.
 *
 * Every token has to extend this class.
 *
 * @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 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], 01) == "*" " " "") . $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) == $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 34)) === "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, -1010)) === "!important")
            {
                
$value trim(substr($value0, -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" tnrx0B" $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], $ii1);
                if (
strpos($globalTriggerChars$c) === false)
                {
                    
$globalTriggerChars .= $c;
                }
            }
        }
        
// Normalise line endings
        
$source            str_replace("rn""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], 01) == "*" " " "") . $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) $errorE_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) > && !(count($tokens[$i]->MediaTypes) == && $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) == || (count($import[$ii]->MediaTypes) == && $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($blocksarray_splice($import$ii1, 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($blocksarray_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$i1$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 1011)) === "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 "/rgbs*(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;
    
/**
     * Transformation table used by the {@link CssConvertNamedColorsMinifierPlugin::reReplace() replacement method}.
     *
     * @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::$reMatch 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|$)+/iS";
        
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_callback($this->reMatch, array($this'reReplace'), $token->Value);
        }
        return 
false;
    }
    
/**
     * Callback for replacement value.
     *
     * @param array $match
     * @return string
     */
    
private function reReplace($match)
    {
        return 
$match[1] . $this->transformation[strtolower($match[2])] . $match[3];
    }
    
/**
     * 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"nullnull),
        
"animation-delay"                => array(null"-webkit-animation-delay"nullnull),
        
"animation-direction"             => array(null"-webkit-animation-direction"nullnull),
        
"animation-duration"            => array(null"-webkit-animation-duration"nullnull),
        
"animation-fill-mode"            => array(null"-webkit-animation-fill-mode"nullnull),
        
"animation-iteration-count"        => array(null"-webkit-animation-iteration-count"nullnull),
        
"animation-name"                => array(null"-webkit-animation-name"nullnull),
        
"animation-play-state"            => array(null"-webkit-animation-play-state"nullnull),
        
"animation-timing-function"        => array(null"-webkit-animation-timing-function"nullnull),
        
"appearance"                    => array("-moz-appearance""-webkit-appearance"nullnull),
        
"backface-visibility"            => array(null"-webkit-backface-visibility"nullnull),
        
"background-clip"                => array(null"-webkit-background-clip"nullnull),
        
"background-composite"            => array(null"-webkit-background-composite"nullnull),
        
"background-inline-policy"        => array("-moz-background-inline-policy"nullnullnull),
        
"background-origin"                => array(null"-webkit-background-origin"nullnull),
        
"background-position-x"            => array(nullnullnull"-ms-background-position-x"),
        
"background-position-y"            => array(nullnullnull"-ms-background-position-y"),
        
"background-size"                => array(null"-webkit-background-size"nullnull),
        
"behavior"                        => array(nullnullnull"-ms-behavior"),
        
"binding"                        => array("-moz-binding"nullnullnull),
        
"border-after"                    => array(null"-webkit-border-after"nullnull),
        
"border-after-color"            => array(null"-webkit-border-after-color"nullnull),
        
"border-after-style"            => array(null"-webkit-border-after-style"nullnull),
        
"border-after-width"            => array(null"-webkit-border-after-width"nullnull),
        
"border-before"                    => array(null"-webkit-border-before"nullnull),
        
"border-before-color"            => array(null"-webkit-border-before-color"nullnull),
        
"border-before-style"            => array(null"-webkit-border-before-style"nullnull),
        
"border-before-width"            => array(null"-webkit-border-before-width"nullnull),
        
"border-border-bottom-colors"    => array("-moz-border-bottom-colors"nullnullnull),
        
"border-bottom-left-radius"        => array("-moz-border-radius-bottomleft""-webkit-border-bottom-left-radius"nullnull),
        
"border-bottom-right-radius"    => array("-moz-border-radius-bottomright""-webkit-border-bottom-right-radius"nullnull),
        
"border-end"                    => array("-moz-border-end""-webkit-border-end"nullnull),
        
"border-end-color"                => array("-moz-border-end-color""-webkit-border-end-color"nullnull),
        
"border-end-style"                => array("-moz-border-end-style""-webkit-border-end-style"nullnull),
        
"border-end-width"                => array("-moz-border-end-width""-webkit-border-end-width"nullnull),
        
"border-fit"                    => array(null"-webkit-border-fit"nullnull),
        
"border-horizontal-spacing"        => array(null"-webkit-border-horizontal-spacing"nullnull),
        
"border-image"                    => array("-moz-border-image""-webkit-border-image"nullnull),
        
"border-left-colors"            => array("-moz-border-left-colors"nullnullnull),
        
"border-radius"                    => array("-moz-border-radius""-webkit-border-radius"nullnull),
        
"border-border-right-colors"    => array("-moz-border-right-colors"nullnullnull),
        
"border-start"                    => array("-moz-border-start""-webkit-border-start"nullnull),
        
"border-start-color"            => array("-moz-border-start-color""-webkit-border-start-color"nullnull),
        
"border-start-style"            => array("-moz-border-start-style""-webkit-border-start-style"nullnull),
        
"border-start-width"            => array("-moz-border-start-width""-webkit-border-start-width"nullnull),
        
"border-top-colors"                => array("-moz-border-top-colors"nullnullnull),
        
"border-top-left-radius"        => array("-moz-border-radius-topleft""-webkit-border-top-left-radius"nullnull),
        
"border-top-right-radius"        => array("-moz-border-radius-topright""-webkit-border-top-right-radius"nullnull),
        
"border-vertical-spacing"        => array(null"-webkit-border-vertical-spacing"nullnull),
        
"box-align"                        => array("-moz-box-align""-webkit-box-align"nullnull),
        
"box-direction"                    => array("-moz-box-direction""-webkit-box-direction"nullnull),
        
"box-flex"                        => array("-moz-box-flex""-webkit-box-flex"nullnull),
        
"box-flex-group"                => array(null"-webkit-box-flex-group"nullnull),
        
"box-flex-lines"                => array(null"-webkit-box-flex-lines"nullnull),
        
"box-ordinal-group"                => array("-moz-box-ordinal-group""-webkit-box-ordinal-group"nullnull),
        
"box-orient"                    => array("-moz-box-orient""-webkit-box-orient"nullnull),
        
"box-pack"                        => array("-moz-box-pack""-webkit-box-pack"nullnull),
        
"box-reflect"                    => array(null"-webkit-box-reflect"nullnull),
        
"box-shadow"                    => array("-moz-box-shadow""-webkit-box-shadow"nullnull),
        
"box-sizing"                    => array("-moz-box-sizing"nullnullnull),
        
"color-correction"                => array(null"-webkit-color-correction"nullnull),
        
"column-break-after"            => array(null"-webkit-column-break-after"nullnull),
        
"column-break-before"            => array(null"-webkit-column-break-before"nullnull),
        
"column-break-inside"            => array(null"-webkit-column-break-inside"nullnull),
        
"column-count"                    => array("-moz-column-count""-webkit-column-count"nullnull),
        
"column-gap"                    => array("-moz-column-gap""-webkit-column-gap"nullnull),
        
"column-rule"                    => array("-moz-column-rule""-webkit-column-rule"nullnull),
        
"column-rule-color"                => array("-moz-column-rule-color""-webkit-column-rule-color"nullnull),
        
"column-rule-style"                => array("-moz-column-rule-style""-webkit-column-rule-style"nullnull),
        
"column-rule-width"                => array("-moz-column-rule-width""-webkit-column-rule-width"nullnull),
        
"column-span"                    => array(null"-webkit-column-span"nullnull),
        
"column-width"                    => array("-moz-column-width""-webkit-column-width"nullnull),
        
"columns"                        => array(null"-webkit-columns"nullnull),
        
"filter"                        => array(__CLASS__"filter"),
        
"float-edge"                    => array("-moz-float-edge"nullnullnull),
        
"font-feature-settings"            => array("-moz-font-feature-settings"nullnullnull),
        
"font-language-override"        => array("-moz-font-language-override"nullnullnull),
        
"font-size-delta"                => array(null"-webkit-font-size-delta"nullnull),
        
"font-smoothing"                => array(null"-webkit-font-smoothing"nullnull),
        
"force-broken-image-icon"        => array("-moz-force-broken-image-icon"nullnullnull),
        
"highlight"                        => array(null"-webkit-highlight"nullnull),
        
"hyphenate-character"            => array(null"-webkit-hyphenate-character"nullnull),
        
"hyphenate-locale"                => array(null"-webkit-hyphenate-locale"nullnull),
        
"hyphens"                        => array(null"-webkit-hyphens"nullnull),
        
"force-broken-image-icon"        => array("-moz-image-region"nullnullnull),
        
"ime-mode"                        => array(nullnullnull"-ms-ime-mode"),
        
"interpolation-mode"            => array(nullnullnull"-ms-interpolation-mode"),
        
"layout-flow"                    => array(nullnullnull"-ms-layout-flow"),
        
"layout-grid"                    => array(nullnullnull"-ms-layout-grid"),
        
"layout-grid-char"                => array(nullnullnull"-ms-layout-grid-char"),
        
"layout-grid-line"                => array(nullnullnull"-ms-layout-grid-line"),
        
"layout-grid-mode"                => array(nullnullnull"-ms-layout-grid-mode"),
        
"layout-grid-type"                => array(nullnullnull"-ms-layout-grid-type"),
        
"line-break"                    => array(null"-webkit-line-break"null"-ms-line-break"),
        
"line-clamp"                    => array(null"-webkit-line-clamp"nullnull),
        
"line-grid-mode"                => array(nullnullnull"-ms-line-grid-mode"),
        
"logical-height"                => array(null"-webkit-logical-height"nullnull),
        
"logical-width"                    => array(null"-webkit-logical-width"nullnull),
        
"margin-after"                    => array(null"-webkit-margin-after"nullnull),
        
"margin-after-collapse"            => array(null"-webkit-margin-after-collapse"nullnull),
        
"margin-before"                    => array(null"-webkit-margin-before"nullnull),
        
"margin-before-collapse"        => array(null"-webkit-margin-before-collapse"nullnull),
        
"margin-bottom-collapse"        => array(null"-webkit-margin-bottom-collapse"nullnull),
        
"margin-collapse"                => array(null"-webkit-margin-collapse"nullnull),
        
"margin-end"                    => array("-moz-margin-end""-webkit-margin-end"nullnull),
        
"margin-start"                    => array("-moz-margin-start""-webkit-margin-start"nullnull),
        
"margin-top-collapse"            => array(null"-webkit-margin-top-collapse"nullnull),
        
"marquee "                        => array(null"-webkit-marquee"nullnull),
        
"marquee-direction"                => array(null"-webkit-marquee-direction"nullnull),
        
"marquee-increment"                => array(null"-webkit-marquee-increment"nullnull),
        
"marquee-repetition"            => array(null"-webkit-marquee-repetition"nullnull),
        
"marquee-speed"                    => array(null"-webkit-marquee-speed"nullnull),
        
"marquee-style"                    => array(null"-webkit-marquee-style"nullnull),
        
"mask"                            => array(null"-webkit-mask"nullnull),
        
"mask-attachment"                => array(null"-webkit-mask-attachment"nullnull),
        
"mask-box-image"                => array(null"-webkit-mask-box-image"nullnull),
        
"mask-clip"                        => array(null"-webkit-mask-clip"nullnull),
        
"mask-composite"                => array(null"-webkit-mask-composite"nullnull),
        
"mask-image"                    => array(null"-webkit-mask-image"nullnull),
        
"mask-origin"                    => array(null"-webkit-mask-origin"nullnull),
        
"mask-position"                    => array(null"-webkit-mask-position"nullnull),
        
"mask-position-x"                => array(null"-webkit-mask-position-x"nullnull),
        
"mask-position-y"                => array(null"-webkit-mask-position-y"nullnull),
        
"mask-repeat"                    => array(null"-webkit-mask-repeat"nullnull),
        
"mask-repeat-x"                    => array(null"-webkit-mask-repeat-x"nullnull),
        
"mask-repeat-y"                    => array(null"-webkit-mask-repeat-y"nullnull),
        
"mask-size"                        => array(null"-webkit-mask-size"nullnull),
        
"match-nearest-mail-blockquote-color" => array(null"-webkit-match-nearest-mail-blockquote-color"nullnull),
        
"max-logical-height"            => array(null"-webkit-max-logical-height"nullnull),
        
"max-logical-width"                => array(null"-webkit-max-logical-width"nullnull),
        
"min-logical-height"            => array(null"-webkit-min-logical-height"nullnull),
        
"min-logical-width"                => array(null"-webkit-min-logical-width"nullnull),
        
"object-fit"                    => array(nullnull"-o-object-fit"null),
        
"object-position"                => array(nullnull"-o-object-position"null),
        
"opacity"                        => array(__CLASS__"opacity"),
        
"outline-radius"                => array("-moz-outline-radius"nullnullnull),
        
"outline-bottom-left-radius"    => array("-moz-outline-radius-bottomleft"nullnullnull),
        
"outline-bottom-right-radius"    => array("-moz-outline-radius-bottomright"nullnullnull),
        
"outline-top-left-radius"        => array("-moz-outline-radius-topleft"nullnullnull),
        
"outline-top-right-radius"        => array("-moz-outline-radius-topright"nullnullnull),
        
"padding-after"                    => array(null"-webkit-padding-after"nullnull),
        
"padding-before"                => array(null"-webkit-padding-before"nullnull),
        
"padding-end"                    => array("-moz-padding-end""-webkit-padding-end"nullnull),
        
"padding-start"                    => array("-moz-padding-start""-webkit-padding-start"nullnull),
        
"perspective"                    => array(null"-webkit-perspective"nullnull),
        
"perspective-origin"            => array(null"-webkit-perspective-origin"nullnull),
        
"perspective-origin-x"            => array(null"-webkit-perspective-origin-x"nullnull),
        
"perspective-origin-y"            => array(null"-webkit-perspective-origin-y"nullnull),
        
"rtl-ordering"                    => array(null"-webkit-rtl-ordering"nullnull),
        
"scrollbar-3dlight-color"        => array(nullnullnull"-ms-scrollbar-3dlight-color"),
        
"scrollbar-arrow-color"            => array(nullnullnull"-ms-scrollbar-arrow-color"),
        
"scrollbar-base-color"            => array(nullnullnull"-ms-scrollbar-base-color"),
        
"scrollbar-darkshadow-color"    => array(nullnullnull"-ms-scrollbar-darkshadow-color"),
        
"scrollbar-face-color"            => array(nullnullnull"-ms-scrollbar-face-color"),
        
"scrollbar-highlight-color"        => array(nullnullnull"-ms-scrollbar-highlight-color"),
        
"scrollbar-shadow-color"        => array(nullnullnull"-ms-scrollbar-shadow-color"),
        
"scrollbar-track-color"            => array(nullnullnull"-ms-scrollbar-track-color"),
        
"stack-sizing"                    => array("-moz-stack-sizing"nullnullnull),
        
"svg-shadow"                    => array(null"-webkit-svg-shadow"nullnull),
        
"tab-size"                        => array("-moz-tab-size"null"-o-tab-size"null),
        
"table-baseline"                => array(nullnull"-o-table-baseline"null),
        
"text-align-last"                => array(nullnullnull"-ms-text-align-last"),
        
"text-autospace"                => array(nullnullnull"-ms-text-autospace"),
        
"text-combine"                    => array(null"-webkit-text-combine"nullnull),
        
"text-decorations-in-effect"    => array(null"-webkit-text-decorations-in-effect"nullnull),
        
"text-emphasis"                    => array(null"-webkit-text-emphasis"nullnull),
        
"text-emphasis-color"            => array(null"-webkit-text-emphasis-color"nullnull),
        
"text-emphasis-position"        => array(null"-webkit-text-emphasis-position"nullnull),
        
"text-emphasis-style"            => array(null"-webkit-text-emphasis-style"nullnull),
        
"text-fill-color"                => array(null"-webkit-text-fill-color"nullnull),
        
"text-justify"                    => array(nullnullnull"-ms-text-justify"),
        
"text-kashida-space"            => array(nullnullnull"-ms-text-kashida-space"),
        
"text-overflow"                    => array(nullnull"-o-text-overflow""-ms-text-overflow"),
        
"text-security"                    => array(null"-webkit-text-security"nullnull),
        
"text-size-adjust"                => array(null"-webkit-text-size-adjust"null"-ms-text-size-adjust"),
        
"text-stroke"                    => array(null"-webkit-text-stroke"nullnull),
        
"text-stroke-color"                => array(null"-webkit-text-stroke-color"nullnull),
        
"text-stroke-width"                => array(null"-webkit-text-stroke-width"nullnull),
        
"text-underline-position"        => array(nullnullnull"-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"nullnull),
        
"transform-origin-y"            => array(null"-webkit-transform-origin-y"nullnull),
        
"transform-origin-z"            => array(null"-webkit-transform-origin-z"nullnull),
        
"transform-style"                => array(null"-webkit-transform-style"nullnull),
        
"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"nullnull),
        
"user-focus"                    => array("-moz-user-focus"nullnullnull),
        
"user-input"                    => array("-moz-user-input"nullnullnull),
        
"user-modify"                    => array("-moz-user-modify""-webkit-user-modify"nullnull),
        
"user-select"                    => array("-moz-user-select""-webkit-user-select"nullnull),
        
"white-space"                    => array(__CLASS__"whiteSpace"),
        
"window-shadow"                    => array("-moz-window-shadow"nullnullnull),
        
"word-break"                    => array(nullnullnull"-ms-word-break"),
        
"word-wrap"                        => array(nullnullnull"-ms-word-wrap"),
        
"writing-mode"                    => array(null"-webkit-writing-mode"null"-ms-writing-mode"),
        
"zoom"                            => array(nullnullnull"-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 10$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 10$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 "/^hsls*(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 * ($saturation);
            }
            else
            {
                
$v2 = ($lightness $saturation) - ($saturation $lightness);
            }
            
$v1        $lightness $v2;
            
$red    255 self::hue2rgb($v1$v2$hue + (3));
            
$green    255 self::hue2rgb($v1$v2$hue);
            
$blue    255 self::hue2rgb($v1$v2$hue - (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 ((
$hue) < 1)
        {
            return (
$v1 + ($v2 $v1) * $hue);
        }
        if ((
$hue) < 1)
        {
            return (
$v2);
        }
        if ((
$hue) < 2)
        {
            return (
$v1 + ($v2 $v1) * (( 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;
    
/**
     * Transformation table used by the {@link CssConvertFontWeightMinifierPlugin::reReplace() replacement method}.
     *
     * @var array
     */
    
private $transformation = array
    (
        
"normal"    => "400",
        
"bold"        => "700"
    
);
    
/**
     * Overwrites {@link aCssMinifierPlugin::__construct()}.
     *
     * The constructor will create the {@link CssConvertFontWeightMinifierPlugin::$reMatch 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|$)+/iS";
        
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_callback($this->reMatch, array($this'reReplace'), $token->Value);
        }
        return 
false;
    }
    
/**
     * Callback for replacement value.
     *
     * @param array $match
     * @return string
     */
    
private function reReplace($match)
    {
        return 
$match[1] . $this->transformation[strtolower($match[2])] . $match[3];
    }
    
/**
     * 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",
    );
    
/**
     * Regular expression used for matching and replacing unit values only for non-blacklisted declarations.
     *
     * @var array
     */
    
private $reBlacklisted = array(
        
"/(^0s0s0s0)|(^0s0s0$)|(^0s0$)/iS" => "0",
    );
    
/**
     * Blacklisted properties for the above regular expression.
     *
     * @var array
     */
    
private $propertiesBlacklist = array('background-position');
    
/**
     * 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)|(^0s0s0s0$)|(^0s0s0$)|(^0s0$)/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);
            }
            if (!
in_array($token->Property$this->propertiesBlacklist))
            {
                foreach (
$this->reBlacklisted 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->Valuestripos($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(), $index10)) === "@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, -1010)) === "!important")
            {
                
$value trim(substr($value0, -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(), $index5)) === "@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, -1010)) == "!important")
            {
                
$value trim(substr($value0, -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(), $index6)) === "@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()
    {
        if (
$this->AtRuleName === "-moz-keyframes")
        {
            return 
"@-moz-keyframes " $this->Name " {";
        }
        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(), $index10)) === "@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(), $index15)) === "@-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(), $index18)) === "@-webkit-keyframes")
        {
            
$this->atRuleName "-webkit-keyframes";
            
$this->parser->pushState("T_AT_KEYFRAMES::NAME");
            
$this->parser->clearBuffer();
            return 
$index 18;
        }
        
// Start of @keyframes at-rule block (@-o-keyframes)
        
elseif ($char === "@" && $state === "T_DOCUMENT" && strtolower(substr($this->parser->getSource(), $index13)) === "@-o-keyframes")
        {
            
$this->atRuleName "-o-keyframes";
            
$this->parser->pushState("T_AT_KEYFRAMES::NAME");
            
$this->parser->clearBuffer();
            return 
$index 13;
        }
        
// Start of @keyframes at-rule block (@-ms-keyframes)
        
elseif ($char === "@" && $state === "T_DOCUMENT" && strtolower(substr($this->parser->getSource(), $index14)) === "@-ms-keyframes")
        {
            
$this->atRuleName "-ms-keyframes";
            
$this->parser->pushState("T_AT_KEYFRAMES::NAME");
            
$this->parser->clearBuffer();
            return 
$index 14;
        }
        
// 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, " tnrx0B'"");
            $mediaTypes = array_filter(array_map("trim", explode(",", trim(substr($this->buffer, $pos + 1), " tnrx0B{"))));
            if ($pos)
            {
                $this->parser->appendToken(new CssAtImportToken($import, $mediaTypes));
            }
            else
            {
                CssMin::triggerError(new CssError(__FILE__, __LINE__, __METHOD__ . ": Invalid @import at-rule syntax", $this->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 - 1;
        }
        // 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;
    }
}

?>
Онлайн: 1
Реклама