/wp-content/plugins/woocommerce/includes/libraries/class-cssmin.php
https://bitbucket.org/theshipswakecreative/psw · PHP · 5087 lines · 3031 code · 67 blank · 1989 comment · 320 complexity · 505456bb6263c93d2ec6ecddedc9afff MD5 · raw file
Large files are truncated click here to view the full file
- <?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
- */
- if ( ! defined( 'ABSPATH' ) ) {
- exit; // Exit if accessed directly
- }
- /**
- * 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], 0, 1) == "*" ? " " : "") . $lines[$ii];
- }
- }
- elseif ($class === "CssAtCharsetToken")
- {
- $r[] = $indent . "@charset " . $token->Charset . ";";
- }
- elseif ($class === "CssAtFontFaceStartToken")
- {
- $r[] = $indent . "@font-face";
- $r[] = $this->indent . $indent . "{";
- $level++;
- }
- elseif ($class === "CssAtImportToken")
- {
- $r[] = $indent . "@import " . $token->Import . " " . implode(", ", $token->MediaTypes) . ";";
- }
- elseif ($class === "CssAtKeyframesStartToken")
- {
- $r[] = $indent . "@keyframes \"" . $token->Name . "\"";
- $r[] = $this->indent . $indent . "{";
- $level++;
- }
- elseif ($class === "CssAtMediaStartToken")
- {
- $r[] = $indent . "@media " . implode(", ", $token->MediaTypes);
- $r[] = $this->indent . $indent . "{";
- $level++;
- }
- elseif ($class === "CssAtPageStartToken")
- {
- $r[] = $indent . "@page";
- $r[] = $this->indent . $indent . "{";
- $level++;
- }
- elseif ($class === "CssAtVariablesStartToken")
- {
- $r[] = $indent . "@variables " . implode(", ", $token->MediaTypes);
- $r[] = $this->indent . $indent . "{";
- $level++;
- }
- elseif ($class === "CssRulesetStartToken" || $class === "CssAtKeyframesRulesetStartToken")
- {
- $r[] = $indent . implode(", ", $token->Selectors);
- $r[] = $this->indent . $indent . "{";
- $level++;
- }
- elseif ($class == "CssAtFontFaceDeclarationToken"
- || $class === "CssAtKeyframesRulesetDeclarationToken"
- || $class === "CssAtPageDeclarationToken"
- || $class == "CssAtVariablesDeclarationToken"
- || $class === "CssRulesetDeclarationToken"
- )
- {
- $declaration = $indent . $token->Property . ": ";
- if ($this->padding)
- {
- $declaration = str_pad($declaration, $this->padding, " ", STR_PAD_RIGHT);
- }
- $r[] = $declaration . $token->Value . ($token->IsImportant ? " !important" : "") . ";";
- }
- elseif ($class === "CssAtFontFaceEndToken"
- || $class === "CssAtMediaEndToken"
- || $class === "CssAtKeyframesEndToken"
- || $class === "CssAtKeyframesRulesetEndToken"
- || $class === "CssAtPageEndToken"
- || $class === "CssAtVariablesEndToken"
- || $class === "CssRulesetEndToken"
- )
- {
- $r[] = $indent . "}";
- $level--;
- }
- }
- return implode("\n", $r);
- }
- }
- /**
- * This {@link aCssMinifierPlugin} will process var-statement and sets the declaration value to the variable value.
- *
- * This plugin only apply the variable values. The variable values itself will get parsed by the
- * {@link CssVariablesMinifierFilter}.
- *
- * Example:
- * <code>
- * @variables
- * {
- * defaultColor: black;
- * }
- * color: var(defaultColor);
- * </code>
- *
- * Will get converted to:
- * <code>
- * color:black;
- * </code>
- *
- * @package CssMin/Minifier/Plugins
- * @link http://code.google.com/p/cssmin/
- * @author Joe Scylla <joe.scylla@gmail.com>
- * @copyright 2008 - 2011 Joe Scylla <joe.scylla@gmail.com>
- * @license http://opensource.org/licenses/mit-license.php MIT License
- * @version 3.0.1
- */
- class CssVariablesMinifierPlugin extends aCssMinifierPlugin
- {
- /**
- * Regular expression matching a value.
- *
- * @var string
- */
- private $reMatch = "/var\((.+)\)/iSU";
- /**
- * Parsed variables.
- *
- * @var array
- */
- private $variables = null;
- /**
- * Returns the variables.
- *
- * @return array
- */
- public function getVariables()
- {
- return $this->variables;
- }
- /**
- * Implements {@link aCssMinifierPlugin::minify()}.
- *
- * @param aCssToken $token Token to process
- * @return boolean Return TRUE to break the processing of this token; FALSE to continue
- */
- public function apply(aCssToken &$token)
- {
- if (stripos($token->Value, "var") !== false && preg_match_all($this->reMatch, $token->Value, $m))
- {
- $mediaTypes = $token->MediaTypes;
- if (!in_array("all", $mediaTypes))
- {
- $mediaTypes[] = "all";
- }
- for ($i = 0, $l = count($m[0]); $i < $l; $i++)
- {
- $variable = trim($m[1][$i]);
- foreach ($mediaTypes as $mediaType)
- {
- if (isset($this->variables[$mediaType], $this->variables[$mediaType][$variable]))
- {
- // Variable value found => set the declaration value to the variable value and return
- $token->Value = str_replace($m[0][$i], $this->variables[$mediaType][$variable], $token->Value);
- continue 2;
- }
- }
- // If no value was found trigger an error and replace the token with a CssNullToken
- CssMin::triggerError(new CssError(__FILE__, __LINE__, __METHOD__ . ": No value found for variable <code>" . $variable . "</code> in media types <code>" . implode(", ", $mediaTypes) . "</code>", (string) $token));
- $token = new CssNullToken();
- return true;
- }
- }
- return false;
- }
- /**
- * Implements {@link aMinifierPlugin::getTriggerTokens()}
- *
- * @return array
- */
- public function getTriggerTokens()
- {
- return array
- (
- "CssAtFontFaceDeclarationToken",
- "CssAtPageDeclarationToken",
- "CssRulesetDeclarationToken"
- );
- }
- /**
- * Sets the variables.
- *
- * @param array $variables Variables to set
- * @return void
- */
- public function setVariables(array $variables)
- {
- $this->variables = $variables;
- }
- }
- /**
- * This {@link aCssMinifierFilter minifier filter} will parse the variable declarations out of @variables at-rule
- * blocks. The variables will get store in the {@link CssVariablesMinifierPlugin} that will apply the variables to
- * declaration.
- *
- * @package CssMin/Minifier/Filters
- * @link http://code.google.com/p/cssmin/
- * @author Joe Scylla <joe.scylla@gmail.com>
- * @copyright 2008 - 2011 Joe Scylla <joe.scylla@gmail.com>
- * @license http://opensource.org/licenses/mit-license.php MIT License
- * @version 3.0.1
- */
- class CssVariablesMinifierFilter extends aCssMinifierFilter
- {
- /**
- * Implements {@link aCssMinifierFilter::filter()}.
- *
- * @param array $tokens Array of objects of type aCssToken
- * @return integer Count of added, changed or removed tokens; a return value large than 0 will rebuild the array
- */
- public function apply(array &$tokens)
- {
- $variables = array();
- $defaultMediaTypes = array("all");
- $mediaTypes = array();
- $remove = array();
- for($i = 0, $l = count($tokens); $i < $l; $i++)
- {
- // @variables at-rule block found
- if (get_class($tokens[$i]) === "CssAtVariablesStartToken")
- {
- $remove[] = $i;
- $mediaTypes = (count($tokens[$i]->MediaTypes) == 0 ? $defaultMediaTypes : $tokens[$i]->MediaTypes);
- foreach ($mediaTypes as $mediaType)
- {
- if (!isset($variables[$mediaType]))
- {
- $variables[$mediaType] = array();
- }
- }
- // Read the variable declaration tokens
- for($i = $i; $i < $l; $i++)
- {
- // Found a variable declaration => read the variable values
- if (get_class($tokens[$i]) === "CssAtVariablesDeclarationToken")
- {
- foreach ($mediaTypes as $mediaType)
- {
- $variables[$mediaType][$tokens[$i]->Property] = $tokens[$i]->Value;
- }
- $remove[] = $i;
- }
- // Found the variables end token => break;
- elseif (get_class($tokens[$i]) === "CssAtVariablesEndToken")
- {
- $remove[] = $i;
- break;
- }
- }
- }
- }
- // Variables in @variables at-rule blocks
- foreach($variables as $mediaType => $null)
- {
- foreach($variables[$mediaType] as $variable => $value)
- {
- // If a var() statement in a variable value found...
- if (stripos($value, "var") !== false && preg_match_all("/var\((.+)\)/iSU", $value, $m))
- {
- // ... then replace the var() statement with the variable values.
- for ($i = 0, $l = count($m[0]); $i < $l; $i++)
- {
- $variables[$mediaType][$variable] = str_replace($m[0][$i], (isset($variables[$mediaType][$m[1][$i]]) ? $variables[$mediaType][$m[1][$i]] : ""), $variables[$mediaType][$variable]);
- }
- }
- }
- }
- // Remove the complete @variables at-rule block
- foreach ($remove as $i)
- {
- $tokens[$i] = null;
- }
- if (!($plugin = $this->minifier->getPlugin("CssVariablesMinifierPlugin")))
- {
- CssMin::triggerError(new CssError(__FILE__, __LINE__, __METHOD__ . ": The plugin <code>CssVariablesMinifierPlugin</code> was not found but is required for <code>" . __CLASS__ . "</code>"));
- }
- else
- {
- $plugin->setVariables($variables);
- }
- return count($remove);
- }
- }
- /**
- * {@link aCssParserPlugin Parser plugin} for preserve parsing url() values.
- *
- * This plugin return no {@link aCssToken CssToken} but ensures that url() values will get parsed properly.
- *
- * @package CssMin/Parser/Plugins
- * @link http://code.google.com/p/cssmin/
- * @author Joe Scylla <joe.scylla@gmail.com>
- * @copyright 2008 - 2011 Joe Scylla <joe.scylla@gmail.com>
- * @license http://opensource.org/licenses/mit-license.php MIT License
- * @version 3.0.1
- */
- class CssUrlParserPlugin extends aCssParserPlugin
- {
- /**
- * Implements {@link aCssParserPlugin::getTriggerChars()}.
- *
- * @return array
- */
- public function getTriggerChars()
- {
- return array("(", ")");
- }
- /**
- * Implements {@link aCssParserPlugin::getTriggerStates()}.
- *
- * @return array
- */
- public function getTriggerStates()
- {
- return false;
- }
- /**
- * Implements {@link aCssParserPlugin::parse()}.
- *
- * @param integer $index Current index
- * @param string $char Current char
- * @param string $previousChar Previous char
- * @return mixed TRUE will break the processing; FALSE continue with the next plugin; integer set a new index and break the processing
- */
- public function parse($index, $char, $previousChar, $state)
- {
- // Start of string
- if ($char === "(" && strtolower(substr($this->parser->getSource(), $index - 3, 4)) === "url(" && $state !== "T_URL")
- {
- $this->parser->pushState("T_URL");
- $this->parser->setExclusive(__CLASS__);
- }
- // Escaped LF in url => remove escape backslash and LF
- elseif ($char === "\n" && $previousChar === "\\" && $state === "T_URL")
- {
- $this->parser->setBuffer(substr($this->parser->getBuffer(), 0, -2));
- }
- // Parse error: Unescaped LF in string literal
- elseif ($char === "\n" && $previousChar !== "\\" && $state === "T_URL")
- {
- $line = $this->parser->getBuffer();
- $this->parser->setBuffer(substr($this->parser->getBuffer(), 0, -1) . ")"); // Replace the LF with the url string delimiter
- $this->parser->popState();
- $this->parser->unsetExclusive();
- CssMin::triggerError(new CssError(__FILE__, __LINE__, __METHOD__ . ": Unterminated string literal", $line . "_"));
- }
- // End of string
- elseif ($char === ")" && $state === "T_URL")
- {
- $this->parser->popState();
- $this->parser->unsetExclusive();
- }
- else
- {
- return false;
- }
- return true;
- }
- }
- /**
- * {@link aCssParserPlugin Parser plugin} for preserve parsing string values.
- *
- * This plugin return no {@link aCssToken CssToken} but ensures that string values will get parsed properly.
- *
- * @package CssMin/Parser/Plugins
- * @link http://code.google.com/p/cssmin/
- * @author Joe Scylla <joe.scylla@gmail.com>
- * @copyright 2008 - 2011 Joe Scylla <joe.scylla@gmail.com>
- * @license http://opensource.org/licenses/mit-license.php MIT License
- * @version 3.0.1
- */
- class CssStringParserPlugin extends aCssParserPlugin
- {
- /**
- * Current string delimiter char.
- *
- * @var string
- */
- private $delimiterChar = null;
- /**
- * Implements {@link aCssParserPlugin::getTriggerChars()}.
- *
- * @return array
- */
- public function getTriggerChars()
- {
- return array("\"", "'", "\n");
- }
- /**
- * Implements {@link aCssParserPlugin::getTriggerStates()}.
- *
- * @return array
- */
- public function getTriggerStates()
- {
- return false;
- }
- /**
- * Implements {@link aCssParserPlugin::parse()}.
- *
- * @param integer $index Current index
- * @param string $char Current char
- * @param string $previousChar Previous char
- * @return mixed TRUE will break the processing; FALSE continue with the next plugin; integer set a new index and break the processing
- */
- public function parse($index, $char, $previousChar, $state)
- {
- // Start of string
- if (($char === "\"" || $char === "'") && $state !== "T_STRING")
- {
- $this->delimiterChar = $char;
- $this->parser->pushState("T_STRING");
- $this->parser->setExclusive(__CLASS__);
- }
- // Escaped LF in string => remove escape backslash and LF
- elseif ($char === "\n" && $previousChar === "\\" && $state === "T_STRING")
- {
- $this->parser->setBuffer(substr($this->parser->getBuffer(), 0, -2));
- }
- // Parse error: Unescaped LF in string literal
- elseif ($char === "\n" && $previousChar !== "\\" && $state === "T_STRING")
- {
- $line = $this->parser->getBuffer();
- $this->parser->popState();
- $this->parser->unsetExclusive();
- $this->parser->setBuffer(substr($this->parser->getBuffer(), 0, -1) . $this->delimiterChar); // Replace the LF with the current string char
- CssMin::triggerError(new CssError(__FILE__, __LINE__, __METHOD__ . ": Unterminated string literal", $line . "_"));
- $this->delimiterChar = null;
- }
- // End of string
- elseif ($char === $this->delimiterChar && $state === "T_STRING")
- {
- // If the Previous char is a escape char count the amount of the previous escape chars. If the amount of
- // escape chars is uneven do not end the string
- if ($previousChar == "\\")
- {
- $source = $this->parser->getSource();
- $c = 1;
- $i = $index - 2;
- while (substr($source, $i, 1) === "\\")
- {
- $c++; $i--;
- }
- if ($c % 2)
- {
- return false;
- }
- }
- $this->parser->popState();
- $this->parser->unsetExclusive();
- $this->delimiterChar = null;
- }
- else
- {
- return false;
- }
- return true;
- }
- }
- /**
- * This {@link aCssMinifierFilter minifier filter} sorts the ruleset declarations of a ruleset by name.
- *
- * @package CssMin/Minifier/Filters
- * @link http://code.google.com/p/cssmin/
- * @author Rowan Beentje <http://assanka.net>
- * @copyright Rowan Beentje <http://assanka.net>
- * @license http://opensource.org/licenses/mit-license.php MIT License
- * @version 3.0.1
- */
- class CssSortRulesetPropertiesMinifierFilter extends aCssMinifierFilter
- {
- /**
- * Implements {@link aCssMinifierFilter::filter()}.
- *
- * @param array $tokens Array of objects of type aCssToken
- * @return integer Count of added, changed or removed tokens; a return value larger than 0 will rebuild the array
- */
- public function apply(array &$tokens)
- {
- $r = 0;
- for ($i = 0, $l = count($tokens); $i < $l; $i++)
- {
- // Only look for ruleset start rules
- if (get_class($tokens[$i]) !== "CssRulesetStartToken") { continue; }
- // Look for the corresponding ruleset end
- $endIndex = false;
- for ($ii = $i + 1; $ii < $l; $ii++)
- {
- if (get_class($tokens[$ii]) !== "CssRulesetEndToken") { continue; }
- $endIndex = $ii;
- break;
- }
- if (!$endIndex) { break; }
- $startIndex = $i;
- $i = $endIndex;
- // Skip if there's only one token in this ruleset
- if ($endIndex - $startIndex <= 2) { continue; }
- // Ensure that everything between the start and end is a declaration token, for safety
- for ($ii = $startIndex + 1; $ii < $endIndex; $ii++)
- {
- if (get_class($tokens[$ii]) !== "CssRulesetDeclarationToken") { continue(2); }
- }
- $declarations = array_slice($tokens, $startIndex + 1, $endIndex - $startIndex - 1);
- // Check whether a sort is required
- $sortRequired = $lastPropertyName = false;
- foreach ($declarations as $declaration)
- {
- if ($lastPropertyName)
- {
- if (strcmp($lastPropertyName, $declaration->Property) > 0)
- {
- $sortRequired = true;
- break;
- }
- }
- $lastPropertyName = $declaration->Property;
- }
- if (!$sortRequired) { continue; }
- // Arrange the declarations alphabetically by name
- usort($declarations, array(__CLASS__, "userDefinedSort1"));
- // Update "IsLast" property
- for ($ii = 0, $ll = count($declarations) - 1; $ii <= $ll; $ii++)
- {
- if ($ii == $ll)
- {
- $declarations[$ii]->IsLast = true;
- }
- else
- {
- $declarations[$ii]->IsLast = false;
- }
- }
- // Splice back into the array.
- array_splice($tokens, $startIndex + 1, $endIndex - $startIndex - 1, $declarations);
- $r += $endIndex - $startIndex - 1;
- }
- return $r;
- }
- /**
- * User defined sort function.
- *
- * @return integer
- */
- public static function userDefinedSort1($a, $b)
- {
- return strcmp($a->Property, $b->Property);
- }
- }
- /**
- * This {@link aCssToken CSS token} represents the start of a ruleset.
- *
- * @package CssMin/Tokens
- * @link http://code.google.com/p/cssmin/
- * @author Joe Scylla <joe.scylla@gmail.com>
- * @copyright 2008 - 2011 Joe Scylla <joe.scylla@gmail.com>
- * @license http://opensource.org/licenses/mit-license.php MIT License
- * @version 3.0.1
- */
- class CssRulesetStartToken extends aCssRulesetStartToken
- {
- /**
- * Array of selectors.
- *
- * @var array
- */
- public $Selectors = array();
- /**
- * Set the properties of a ruleset token.
- *
- * @param array $selectors Selectors of the ruleset
- * @return void
- */
- public function __construct(array $selectors = array())
- {
- $this->Selectors = $selectors;
- }
- /**
- * Implements {@link aCssToken::__toString()}.
- *
- * @return string
- */
- public function __toString()
- {
- return implode(",", $this->Selectors) . "{";
- }
- }
- /**
- * {@link aCssParserPlugin Parser plugin} for parsing ruleset block with including declarations.
- *
- * Found rulesets will add a {@link CssRulesetStartToken} and {@link CssRulesetEndToken} to the
- * parser; including declarations as {@link CssRulesetDeclarationToken}.
- *
- * @package CssMin/Parser/Plugins
- * @link http://code.google.com/p/cssmin/
- * @author Joe Scylla <joe.scylla@gmail.com>
- * @copyright 2008 - 2011 Joe Scylla <joe.scylla@gmail.com>
- * @license http://opensource.org/licenses/mit-license.php MIT License
- * @version 3.0.1
- */
- class CssRulesetParserPlugin extends aCssParserPlugin
- {
- /**
- * Implements {@link aCssParserPlugin::getTriggerChars()}.
- *
- * @return array
- */
- public function getTriggerChars()
- {
- return array(",", "{", "}", ":", ";");
- }
- /**
- * Implements {@link aCssParserPlugin::getTriggerStates()}.
- *
- * @return array
- */
- public function getTriggerStates()
- {
- return array("T_DOCUMENT", "T_AT_MEDIA", "T_RULESET::SELECTORS", "T_RULESET", "T_RULESET_DECLARATION");
- }
- /**
- * Selectors.
- *
- * @var array
- */
- private $selectors = array();
- /**
- * Implements {@link aCssParserPlugin::parse()}.
- *
- * @param integer $index Current index
- * @param string $char Current char
- * @param string $previousChar Previous char
- * @return mixed TRUE will break the processing; FALSE continue with the next plugin; integer set a new index and break the processing
- */
- public function parse($index, $char, $previousChar, $state)
- {
- // Start of Ruleset and selectors
- if ($char === "," && ($state === "T_DOCUMENT" || $state === "T_AT_MEDIA" || $state === "T_RULESET::SELECTORS"))
- {
- if ($state !== "T_RULESET::SELECTORS")
- {
- $this->parser->pushState("T_RULESET::SELECTORS");
- }
- $this->selectors[] = $this->parser->getAndClearBuffer(",{");
- }
- // End of selectors and start of declarations
- elseif ($char === "{" && ($state === "T_DOCUMENT" || $state === "T_AT_MEDIA" || $state === "T_RULESET::SELECTORS"))
- {
- if ($this->parser->getBuffer() !== "")
- {
- $this->selectors[] = $this->parser->getAndClearBuffer(",{");
- if ($state == "T_RULESET::SELECTORS")
- {
- $this->parser->popState();
- }
- $this->parser->pushState("T_RULESET");
- $this->parser->appendToken(new CssRulesetStartToken($this->selectors));
- $this->selectors = array();
- }
- }
- // Start of declaration
- elseif ($char === ":" && $state === "T_RULESET")
- {
- $this->parser->pushState("T_RULESET_DECLARATION");
- $this->buffer = $this->parser->getAndClearBuffer(":;", true);
- }
- // Unterminated ruleset declaration
- elseif ($char === ":" && $state === "T_RULESET_DECLARATION")
- {
- // Ignore Internet Explorer filter declarations
- if ($this->buffer === "filter")
- {
- return false;
- }
- CssMin::triggerError(new CssError(__FILE__, __LINE__, __METHOD__ . ": Unterminated declaration", $this->buffer . ":" . $this->parser->getBuffer() . "_"));
- }
- // End of declaration
- elseif (($char === ";" || $char === "}") && $state === "T_RULESET_DECLARATION")
- {
- $value = $this->parser->getAndClearBuffer(";}");
- if (strtolower(substr($value, -10, 10)) === "!important")
- {
- $value = trim(substr($value, 0, -10));
- $isImportant = true;
- }
- else
- {
- $isImportant = false;
- }
- $this->parser->popState();
- $this->parser->appendToken(new CssRulesetDeclarationToken($this->buffer, $value, $this->parser->getMediaTypes(), $isImportant));
- // Declaration ends with a right curly brace; so we have to end the ruleset
- if ($char === "}")
- {
- $this->parser->appendToken(new CssRulesetEndToken());
- $this->parser->popState();
- }
- $this->buffer = "";
- }
- // End of ruleset
- elseif ($char === "}" && $state === "T_RULESET")
- {
- $this->parser->popState();
- $this->parser->clearBuffer();
- $this->parser->appendToken(new CssRulesetEndToken());
- $this->buffer = "";
- $this->selectors = array();
- }
- else
- {
- return false;
- }
- return true;
- }
- }
- /**
- * This {@link aCssToken CSS token} represents the end of a ruleset.
- *
- * @package CssMin/Tokens
- * @link http://code.google.com/p/cssmin/
- * @author Joe Scylla <joe.scylla@gmail.com>
- * @copyright 2008 - 2011 Joe Scylla <joe.scylla@gmail.com>
- * @license http://opensource.org/licenses/mit-license.php MIT License
- * @version 3.0.1
- */
- class CssRulesetEndToken extends aCssRulesetEndToken
- {
- }
- /**
- * This {@link aCssToken CSS token} represents a ruleset declaration.
- *
- * @package CssMin/Tokens
- * @link http://code.google.com/p/cssmin/
- * @author Joe Scylla <joe.scylla@gmail.com>
- * @copyright 2008 - 2011 Joe Scylla <joe.scylla@gmail.com>
- * @license http://opensource.org/licenses/mit-license.php MIT License
- * @version 3.0.1
- */
- class CssRulesetDeclarationToken extends aCssDeclarationToken
- {
- /**
- * Media types of the declaration.
- *
- * @var array
- */
- public $MediaTypes = array("all");
- /**
- * Set the properties of a ddocument- or at-rule @media level declaration.
- *
- * @param string $property Property of the declaration
- * @param string $value Value of the declaration
- * @param mixed $mediaTypes Media types of the declaration
- * @param boolean $isImportant Is the !important flag is set
- * @param boolean $isLast Is the declaration the last one of the ruleset
- * @return void
- */
- public function __construct($property, $value, $mediaTypes = null, $isImportant = false, $isLast = false)
- {
- parent::__construct($property, $value, $isImportant, $isLast);
- $this->MediaTypes = $mediaTypes ? $mediaTypes : array("all");
- }
- }
- /**
- * This {@link aCssMinifierFilter minifier filter} sets the IsLast property of any last declaration in a ruleset,
- * @font-face at-rule or @page at-rule block. If the property IsLast is TRUE the decrations will get stringified
- * without tailing semicolon.
- *
- * @package CssMin/Minifier/Filters
- * @link http://code.google.com/p/cssmin/
- * @author Joe Scylla <joe.scylla@gmail.com>
- * @copyright 2008 - 2011 Joe Scylla <joe.scylla@gmail.com>
- * @license http://opensource.org/licenses/mit-license.php MIT License
- * @version 3.0.1
- */
- class CssRemoveLastDelarationSemiColonMinifierFilter extends aCssMinifierFilter
- {
- /**
- * Implements {@link aCssMinifierFilter::filter()}.
- *
- * @param array $tokens Array of objects of type aCssToken
- * @return integer Count of added, changed or removed tokens; a return value large than 0 will rebuild the array
- */
- public function apply(array &$tokens)
- {
- for ($i = 0, $l = count($tokens); $i < $l; $i++)
- {
- $current = get_class($tokens[$i]);
- $next = isset($tokens[$i+1]) ? get_class($tokens[$i+1]) : false;
- if (($current === "CssRulesetDeclarationToken" && $next === "CssRulesetEndToken") ||
- ($current === "CssAtFontFaceDeclarationToken" && $next === "CssAtFontFaceEndToken") ||
- ($current === "CssAtPageDeclarationToken" && $next === "CssAtPageEndToken"))
- {
- $tokens[$i]->IsLast = true;
- }
- }
- return 0;
- }
- }
- /**
- * This {@link aCssMinifierFilter minifier filter} will remove any empty rulesets (including @keyframes at-rule block
- * rulesets).
- *
- * @package CssMin/Minifier/Filters
- * @link http://code.google.com/p/cssmin/
- * @author Joe Scylla <joe.scylla@gmail.com>
- * @copyright 2008 - 2011 Joe Scylla <joe.scylla@gmail.com>
- * @license http://opensource.org/licenses/mit-license.php MIT License
- * @version 3.0.1
- */
- class CssRemoveEmptyRulesetsMinifierFilter extends aCssMinifierFilter
- {
- /**
- * Implements {@link aCssMinifierFilter::filter()}.
- *
- * @param array $tokens Array of objects of type aCssToken
- * @return integer Count of added, changed or removed tokens; a return value large than 0 will rebuild the array
- */
- public function apply(array &$tokens)
- {
- $r = 0;
- for ($i = 0, $l = count($tokens); $i < $l; $i++)
- {
- $current = get_class($tokens[$i]);
- $next = isset($tokens[$i + 1]) ? get_class($tokens[$i + 1]) : false;
- if (($current === "CssRulesetStartToken" && $next === "CssRulesetEndToken") ||
- ($current === "CssAtKeyframesRulesetStartToken" && $next === "CssAtKeyframesRulesetEndToken" && !array_intersect(array("from", "0%", "to", "100%"), array_map("strtolower", $tokens[$i]->Selectors)))
- )
- {
- $tokens[$i] = null;
- $tokens[$i + 1] = null;
- $i++;
- $r = $r + 2;
- }
- }
- return $r;
- }
- }
- /**
- * This {@link aCssMinifierFilter minifier filter} will remove any empty @font-face, @keyframes, @media and @page
- * at-rule blocks.
- *
- * @package CssMin/Minifier/Filters
- * @link http://code.google.com/p/cssmin/
- * @author Joe Scylla <joe.scylla@gmail.com>
- * @copyright 2008 - 2011 Joe Scylla <joe.scylla@gmail.com>
- * @license http://opensource.org/licenses/mit-license.php MIT License
- * @version 3.0.1
- */
- class CssRemoveEmptyAtBlocksMinifierFilter extends aCssMinifierFilter
- {
- /**
- * Implements {@link aCssMinifierFilter::filter()}.
- *
- * @param array $tokens Array of objects of type aCssToken
- * @return integer Count of added, changed or removed tokens; a return value large than 0 will rebuild the array
- */
- public function apply(array &$tokens)
- {
- $r = 0;
- for ($i = 0, $l = count($tokens); $i < $l; $i++)
- {
- $current = get_class($tokens[$i]);
- $next = isset($tokens[$i + 1]) ? get_class($tokens[$i + 1]) : false;
- if (($current === "CssAtFontFaceStartToken" && $next === "CssAtFontFaceEndToken") ||
- ($current === "CssAtKeyframesStartToken" && $next === "CssAtKeyframesEndToken") ||
- ($current === "CssAtPageStartToken" && $next === "CssAtPageEndToken") ||
- ($current === "CssAtMediaStartToken" && $next === "CssAtMediaEndToken"))
- {
- $tokens[$i] = null;
- $tokens[$i + 1] = null;
- $i++;
- $r = $r + 2;
- }
- }
- return $r;
- }
- }
- /**
- * This {@link aCssMinifierFilter minifier filter} will remove any comments from the array of parsed tokens.
- *
- * @package CssMin/Minifier/Filters
- * @link http://code.google.com/p/cssmin/
- * @author Joe Scylla <joe.scylla@gmail.com>
- * @copyright 2008 - 2011 Joe Scylla <joe.scylla@gmail.com>
- * @license http://opensource.org/licenses/mit-license.php MIT License
- * @version 3.0.1
- */
- class CssRemoveCommentsMinifierFilter extends aCssMinifierFilter
- {
- /**
- * Implements {@link aCssMinifierFilter::filter()}.
- *
- * @param array $tokens Array of objects of type aCssToken
- * @return integer Count of added, changed or removed tokens; a return value large than 0 will rebuild the array
- */
- public function apply(array &$tokens)
- {
- $r = 0;
- for ($i = 0, $l = count($tokens); $i < $l; $i++)
- {
- if (get_class($tokens[$i]) === "CssCommentToken")
- {
- $tokens[$i] = null;
- $r++;
- }
- }
- return $r;
- }
- }
- /**
- * CSS Parser.
- *
- * @package CssMin/Parser
- * @link http://code.google.com/p/cssmin/
- * @author Joe Scylla <joe.scylla@gmail.com>
- * @copyright 2008 - 2011 Joe Scylla <joe.scylla@gmail.com>
- * @license http://opensource.org/licenses/mit-license.php MIT License
- * @version 3.0.1
- */
- class CssParser
- {
- /**
- * Parse buffer.
- *
- * @var string
- */
- private $buffer = "";
- /**
- * {@link aCssParserPlugin Plugins}.
- *
- * @var array
- */
- private $plugins = array();
- /**
- * Source to parse.
- *
- * @var string
- */
- private $source = "";
- /**
- * Current state.
- *
- * @var integer
- */
- private $state = "T_DOCUMENT";
- /**
- * Exclusive state.
- *
- * @var string
- */
- private $stateExclusive = false;
- /**
- * Media types state.
- *
- * @var mixed
- */
- private $stateMediaTypes = false;
- /**
- * State stack.
- *
- * @var array
- */
- private $states = array("T_DOCUMENT");
- /**
- * Parsed tokens.
- *
- * @var array
- */
- private $tokens = array();
- /**
- * Constructer.
- *
- * Create instances of the used {@link aCssParserPlugin plugins}.
- *
- * @param string $source CSS source [optional]
- * @param array $plugins Plugin configuration [optional]
- * @return void
- */
- public function __construct($source = null, array $plugins = null)
- {
- $plugins = array_merge(array
- (
- "Comment" => true,
- "String" => true,
- "Url" => true,
- "Expression" => true,
- "Ruleset" => true,
- "AtCharset" => true,
- "AtFontFace" => true,
- "AtImport" => true,
- "AtKeyframes" => true,
- "AtMedia" => true,
- "AtPage" => true,
- "AtVariables" => true
- ), is_array($plugins) ? $plugins : array());
- // Create plugin instances
- foreach ($plugins as $name => $config)
- {
- if ($config !== false)
- {
- $class = "Css" . $name . "ParserPlugin";
- $config = is_array($config) ? $config : array();
- if (class_exists($class))
- {
- $this->plugins[] = new $class($this, $config);
- }
- else
- {
- CssMin::triggerError(new CssError(__FILE__, __LINE__, __METHOD__ . ": The plugin <code>" . $name . "</code> with the class name <code>" . $class . "</code> was not found"));
- }
- }
- }
- if (!is_null($source))
- {
- $this->parse($source);
- }
- }
- /**
- * Append a token to the array of tokens.
- *
- * @param aCssToken $token Token to append
- * @return void
- */
- public function appendToken(aCssToken $token)
- {
- $this->tokens[] = $token;
- }
- /**
- * Clears the current buffer.
- *
- * @return void
- */
- public function clearBuffer()
- {
- $this->buffer = "";
- }
- /**
- * Returns and clear the current buffer.
- *
- * @param string $trim Chars to use to trim the returned buffer
- * @param boolean $tolower if TRUE the returned buffer will get converted to lower case
- * @return string
- */
- public function getAndClearBuffer($trim = "", $tolower = false)
- {
- $r = $this->getBuffer($trim, $tolower);
- $this->buffer = "";
- return $r;
- }
- /**
- * Returns the current buffer.
- *
- * @param string $trim Chars to use to trim the returned buffer
- * @param boolean $tolower if TRUE the returned buffer will get converted to lower case
- * @return string
- */
- public function getBuffer($trim = "", $tolower = false)
- {
- $r = $this->buffer;
- if ($trim)
- {
- $r = trim($r, " \t\n\r\0\x0B" . $trim);
- }
- if ($tolower)
- {
- $r = strtolower($r);
- }
- return $r;
- }
- /**
- * Returns the current media types state.
- *
- * @return array
- */
- public function getMediaTypes()
- {
- return $this->stateMediaTypes;
- }
- /**
- * Returns the CSS source.
- *
- * @return string
- */
- public function getSource()
- {
- return $this->source;
- }
- /**
- * Returns the current state.
- *
- * @return integer The current state
- */
- public function getState()
- {
- return $this->state;
- }
- /**
- * Returns a plugin by class name.
- *
- * @param string $name Class name of the plugin
- * @return aCssParserPlugin
- */
- public function getPlugin($class)
- {
- static $index = null;
- if (is_null($index))
- {
- $index = array();
- for ($i = 0, $l = count($this->plugins); $i < $l; $i++)
- {
- $index[get_class($this->plugins[$i])] = $i;
- }
- }
- return isset($index[$class]) ? $this->plugins[$index[$class]] : false;
- }
- /**
- * Returns the parsed tokens.
- *
- * @return array
- */
- public function getTokens()
- {
- return $this->tokens;
- }
- /**
- * Returns if the current state equals the passed state.
- *
- * @param integer $state State to compare with the current state
- * @return boolean TRUE is the state equals to the passed state; FALSE if not
- */
- public function isState($state)
- {
- return ($this->state == $state);
- }
- /**
- * Parse the CSS source and return a array with parsed tokens.
- *
- * @param string $source CSS source
- * @return array Array with tokens
- */
- public function parse($source)
- {
- // Reset
- $this->source = "";
- $this->tokens = array();
- // Create a global and plugin lookup table for trigger chars; set array of plugins as local variable and create
- // several helper variables for plugin handling
- $globalTriggerChars = "";
- $plugins = $this->plugins;
- $pluginCount = count($plugins);
- $pluginIndex = array();
- $pluginTriggerStates = array();
- $pluginTriggerChars = array();
- for ($i = 0, $l = count($plugins); $i < $l; $i++)
- {
- $tPluginClassName = get_class($plugins[$i]);
- $pluginTriggerChars[$i] = implode("", $plugins[$i]->getTriggerChars());
- $tPluginTriggerStates = $plugins[$i]->getTriggerStates();
- $pluginTriggerStates[$i] = $tPluginTriggerStates === false ? false : "|" . implode("|", $tPluginTriggerStates) . "|";
- $pluginIndex[$tPluginClassName] = $i;
- for ($ii = 0, $ll = strlen($pluginTriggerChars[$i]); $ii < $ll; $ii++)
- {
- $c = substr($pluginTriggerChars[$i], $ii, 1);
- if (strpos($globalTriggerChars, $c) === false)
- {
- $globalTriggerChars .= $c;
- }
- }
- }
- // Normalise line endings
- $source = str_replace("\r\n", "\n", $source); // Windows to Unix line endings
- $source = str_replace("\r", "\n", $source); // Mac to Unix line endings
- $this->source = $source;
- // Variables
- $buffer = &$this->buffer;
- $exclusive = &$this->stateExclusive;
- $state = &$this->state;
- $c = $p = null;
- // --
- for ($i = 0, $l = strlen($source); $i < $l; $i++)
- {
- // Set the current Char
- $c = $source[$i]; // Is faster than: $c = substr($source, $i, 1);
- // Normalize and filter double whitespace characters
- if ($exclusive === false)
- {
- if ($c === "\n" || $c === "\t")
- {
- $c = " ";
- }
- if ($c === " " && $p === " ")
- {
- continue;
- }
- }
- $buffer .= $c;
- // Extended processing only if the current char is a global trigger char
- if (strpos($globalTriggerChars, $c) !== false)
- {
- // Exclusive state is set; process with the exclusive plugin
- if ($exclusive)
- {
- $tPluginIndex = $pluginIndex[$exclusive];
- if (strpos($pluginTriggerChars[$tPluginIndex], $c) !== false && ($pluginTriggerStates[$tPluginIndex] === false || strpos($pluginTriggerStates[$tPluginIndex], $state) !== false))
- {
- $r = $plugins[$tPluginIndex]->parse($i, $c, $p, $state);
- // Return value is TRUE => continue with next char
- if ($r === true)
- {
- continue;
- }
- // Return value is numeric => set new index and continue with next char
- elseif ($r !== false && $r != $i)
- {
- $i = $r;
- continue;
- }
- }
- }
- // Else iterate through the plugins
- else
- {
- $triggerState = "|" . $state . "|";
- for ($ii = 0, $ll = $pluginCount; $ii < $ll; $ii++)
- {
- // Only process if the current char is one of the plugin trigger chars
- if (strpos($pluginTriggerChars[$ii], $c) !== false && ($pluginTriggerStates[$ii] === false || strpos($pluginTriggerStates[$ii], $triggerState) !== false))
- {
- // Process with the plugin
- $r = $plugins[$ii]->parse($i, $c, $p, $state);
- // Return value is TRUE => break the plugin loop and and continue with next char
- if ($r === true)
- {
- break;
- }
- // Return value is numeric => set new index, break the plugin loop and and continue with next char
- elseif ($r !== false && $r != $i)
- {
- $i = $r;
- break;
- }
- }
- }
- }
- }
- $p = $c; // Set the parent char
- }
- return $this->tokens;
- }
- /**
- * Remove the last state of the state stack and return the removed stack value.
- *
- * @return integer Removed state value
- */
- public function popState()
- {
- $r = array_pop($this->states);
- $this->state = $this->states[count($this->states) - 1];
- return $r;
- }
- /**
- * Adds a new state onto the state stack.
- *
- * @param integer $state State to add onto the state stack.
- * @return integer The index of the added state in the state stacks
- */
- public function pushState($state)
- {
- $r = array_push($this->states, $state);
- $this->state = $this->states[count($this->states) - 1];
- return $r;
- }
- /**
- * Sets/restores the buffer.
- *
- * @param string $buffer Buffer to set
- * @return void
- */
- public function setBuffer($buffer)
- {
- $this->buffer = $buffer;
- }
- /**
- * Set the exclusive state.
- *
- * @param string $exclusive Exclusive state
- * @return void
- */
- public function setExclusive($exclusive)
- {
- $this->stateExclusive = $exclusive;
- }
- /**
- * Set the media types state.
- *
- * @param array $mediaTypes Media types state
- * @return void
- */
- public function setMediaTypes(array $mediaTypes)
- {
- $this->stateMediaTypes = $mediaTypes;
- }
- /**
- * Sets the current state in the state stack; equals to {@link CssParser::popState()} + {@link CssParser::pushState()}.
- *
- * @param integer $state State to set
- * @return integer
- */
- public function setState($state)
- {
- $r = array_pop($this->states);
- array_push($this->stat…