diff --git a/lib/adminlib.php b/lib/adminlib.php index fdb999b33db60..45b991830845c 100644 --- a/lib/adminlib.php +++ b/lib/adminlib.php @@ -10861,9 +10861,9 @@ public function validate($data) { $scss = new core_scss(); try { $scss->compile($data); - } catch (Leafo\ScssPhp\Exception\ParserException $e) { + } catch (ScssPhp\ScssPhp\Exception\ParserException $e) { return get_string('scssinvalid', 'admin', $e->getMessage()); - } catch (Leafo\ScssPhp\Exception\CompilerException $e) { + } catch (ScssPhp\ScssPhp\Exception\CompilerException $e) { // Silently ignore this - it could be a scss variable defined from somewhere // else which we are not examining here. return true; diff --git a/lib/classes/component.php b/lib/classes/component.php index 187fde8d5557d..22edb6ba780c9 100644 --- a/lib/classes/component.php +++ b/lib/classes/component.php @@ -80,7 +80,7 @@ class core_component { 'GeoIp2' => 'lib/maxmind/GeoIp2', 'Sabberworm\\CSS' => 'lib/php-css-parser', 'MoodleHQ\\RTLCSS' => 'lib/rtlcss', - 'Leafo\\ScssPhp' => 'lib/scssphp', + 'ScssPhp\\ScssPhp' => 'lib/scssphp', 'Box\\Spout' => 'lib/spout/src/Spout', 'MatthiasMullie\\Minify' => 'lib/minify/matthiasmullie-minify/src/', 'MatthiasMullie\\PathConverter' => 'lib/minify/matthiasmullie-pathconverter/src/', diff --git a/lib/classes/scss.php b/lib/classes/scss.php index 22810801e15e2..a196105b702ac 100644 --- a/lib/classes/scss.php +++ b/lib/classes/scss.php @@ -31,7 +31,7 @@ * @copyright 2016 Frédéric Massart * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class core_scss extends \Leafo\ScssPhp\Compiler { +class core_scss extends \ScssPhp\ScssPhp\Compiler { /** @var string The path to the SCSS file. */ protected $scssfile; @@ -150,14 +150,14 @@ public function compile($code, $path = null) { * Compile child; returns a value to halt execution * * @param array $child - * @param \Leafo\ScssPhp\Formatter\OutputBlock $out + * @param \ScssPhp\ScssPhp\Formatter\OutputBlock $out * * @return array|null */ - protected function compileChild($child, \Leafo\ScssPhp\Formatter\OutputBlock $out) { + protected function compileChild($child, \ScssPhp\ScssPhp\Formatter\OutputBlock $out) { switch($child[0]) { - case \Leafo\ScssPhp\Type::T_SCSSPHP_IMPORT_ONCE: - case \Leafo\ScssPhp\Type::T_IMPORT: + case \ScssPhp\ScssPhp\Type::T_SCSSPHP_IMPORT_ONCE: + case \ScssPhp\ScssPhp\Type::T_IMPORT: list(, $rawpath) = $child; $rawpath = $this->reduce($rawpath); $path = $this->compileStringContent($rawpath); diff --git a/lib/scssphp/Base/Range.php b/lib/scssphp/Base/Range.php index 8bcc6ecf35f9f..094e9030398d6 100644 --- a/lib/scssphp/Base/Range.php +++ b/lib/scssphp/Base/Range.php @@ -2,14 +2,14 @@ /** * SCSSPHP * - * @copyright 2015-2018 Leaf Corcoran + * @copyright 2015-2019 Leaf Corcoran * * @license http://opensource.org/licenses/MIT MIT * - * @link http://leafo.github.io/scssphp + * @link http://scssphp.github.io/scssphp */ -namespace Leafo\ScssPhp\Base; +namespace ScssPhp\ScssPhp\Base; /** * Range diff --git a/lib/scssphp/Block.php b/lib/scssphp/Block.php index 41abf01a8cd9c..bb1afdd4bc7ef 100644 --- a/lib/scssphp/Block.php +++ b/lib/scssphp/Block.php @@ -2,14 +2,14 @@ /** * SCSSPHP * - * @copyright 2012-2018 Leaf Corcoran + * @copyright 2012-2019 Leaf Corcoran * * @license http://opensource.org/licenses/MIT MIT * - * @link http://leafo.github.io/scssphp + * @link http://scssphp.github.io/scssphp */ -namespace Leafo\ScssPhp; +namespace ScssPhp\ScssPhp; /** * Block @@ -24,7 +24,7 @@ class Block public $type; /** - * @var \Leafo\ScssPhp\Block + * @var \ScssPhp\ScssPhp\Block */ public $parent; @@ -64,7 +64,7 @@ class Block public $children; /** - * @var \Leafo\ScssPhp\Block + * @var \ScssPhp\ScssPhp\Block */ public $selfParent; } diff --git a/lib/scssphp/Cache.php b/lib/scssphp/Cache.php index 49cf631b3f28f..33112640440ed 100644 --- a/lib/scssphp/Cache.php +++ b/lib/scssphp/Cache.php @@ -2,14 +2,14 @@ /** * SCSSPHP * - * @copyright 2012-2018 Leaf Corcoran + * @copyright 2012-2019 Leaf Corcoran * * @license http://opensource.org/licenses/MIT MIT * - * @link http://leafo.github.io/scssphp + * @link http://scssphp.github.io/scssphp */ -namespace Leafo\ScssPhp; +namespace ScssPhp\ScssPhp; use Exception; diff --git a/lib/scssphp/Colors.php b/lib/scssphp/Colors.php index 2314ea58d1995..ad459246a20b7 100644 --- a/lib/scssphp/Colors.php +++ b/lib/scssphp/Colors.php @@ -2,14 +2,14 @@ /** * SCSSPHP * - * @copyright 2012-2018 Leaf Corcoran + * @copyright 2012-2019 Leaf Corcoran * * @license http://opensource.org/licenses/MIT MIT * - * @link http://leafo.github.io/scssphp + * @link http://scssphp.github.io/scssphp */ -namespace Leafo\ScssPhp; +namespace ScssPhp\ScssPhp; /** * CSS Colors diff --git a/lib/scssphp/Compiler.php b/lib/scssphp/Compiler.php index 782799d1f9eae..3446aeab9dba5 100644 --- a/lib/scssphp/Compiler.php +++ b/lib/scssphp/Compiler.php @@ -2,27 +2,27 @@ /** * SCSSPHP * - * @copyright 2012-2018 Leaf Corcoran + * @copyright 2012-2019 Leaf Corcoran * * @license http://opensource.org/licenses/MIT MIT * - * @link http://leafo.github.io/scssphp + * @link http://scssphp.github.io/scssphp */ -namespace Leafo\ScssPhp; - -use Leafo\ScssPhp\Base\Range; -use Leafo\ScssPhp\Block; -use Leafo\ScssPhp\Cache; -use Leafo\ScssPhp\Colors; -use Leafo\ScssPhp\Compiler\Environment; -use Leafo\ScssPhp\Exception\CompilerException; -use Leafo\ScssPhp\Formatter\OutputBlock; -use Leafo\ScssPhp\Node; -use Leafo\ScssPhp\SourceMap\SourceMapGenerator; -use Leafo\ScssPhp\Type; -use Leafo\ScssPhp\Parser; -use Leafo\ScssPhp\Util; +namespace ScssPhp\ScssPhp; + +use ScssPhp\ScssPhp\Base\Range; +use ScssPhp\ScssPhp\Block; +use ScssPhp\ScssPhp\Cache; +use ScssPhp\ScssPhp\Colors; +use ScssPhp\ScssPhp\Compiler\Environment; +use ScssPhp\ScssPhp\Exception\CompilerException; +use ScssPhp\ScssPhp\Formatter\OutputBlock; +use ScssPhp\ScssPhp\Node; +use ScssPhp\ScssPhp\SourceMap\SourceMapGenerator; +use ScssPhp\ScssPhp\Type; +use ScssPhp\ScssPhp\Parser; +use ScssPhp\ScssPhp\Util; /** * The scss compiler and parser. @@ -130,15 +130,15 @@ class Compiler protected $sourceMapOptions = []; /** - * @var string|\Leafo\ScssPhp\Formatter + * @var string|\ScssPhp\ScssPhp\Formatter */ - protected $formatter = 'Leafo\ScssPhp\Formatter\Nested'; + protected $formatter = 'ScssPhp\ScssPhp\Formatter\Nested'; protected $rootEnv; protected $rootBlock; /** - * @var \Leafo\ScssPhp\Compiler\Environment + * @var \ScssPhp\ScssPhp\Compiler\Environment */ protected $env; protected $scope; @@ -300,7 +300,7 @@ public function compile($code, $path = null) * * @param string $path * - * @return \Leafo\ScssPhp\Parser + * @return \ScssPhp\ScssPhp\Parser */ protected function parserFactory($path) { @@ -362,7 +362,7 @@ protected function pushExtends($target, $origin, $block) * @param string $type * @param array $selectors * - * @return \Leafo\ScssPhp\Formatter\OutputBlock + * @return \ScssPhp\ScssPhp\Formatter\OutputBlock */ protected function makeOutputBlock($type, $selectors = null) { @@ -390,7 +390,7 @@ protected function makeOutputBlock($type, $selectors = null) /** * Compile root * - * @param \Leafo\ScssPhp\Block $rootBlock + * @param \ScssPhp\ScssPhp\Block $rootBlock */ protected function compileRoot(Block $rootBlock) { @@ -429,8 +429,8 @@ protected function missingSelectors() /** * Flatten selectors * - * @param \Leafo\ScssPhp\Formatter\OutputBlock $block - * @param string $parentKey + * @param \ScssPhp\ScssPhp\Formatter\OutputBlock $block + * @param string $parentKey */ protected function flattenSelectors(OutputBlock $block, $parentKey = null) { @@ -796,7 +796,7 @@ protected function combineSelectorSingle($base, $other) /** * Compile media * - * @param \Leafo\ScssPhp\Block $media + * @param \ScssPhp\ScssPhp\Block $media */ protected function compileMedia(Block $media) { @@ -879,9 +879,9 @@ protected function compileMedia(Block $media) /** * Media parent * - * @param \Leafo\ScssPhp\Formatter\OutputBlock $scope + * @param \ScssPhp\ScssPhp\Formatter\OutputBlock $scope * - * @return \Leafo\ScssPhp\Formatter\OutputBlock + * @return \ScssPhp\ScssPhp\Formatter\OutputBlock */ protected function mediaParent(OutputBlock $scope) { @@ -899,7 +899,7 @@ protected function mediaParent(OutputBlock $scope) /** * Compile directive * - * @param \Leafo\ScssPhp\Block $block + * @param \ScssPhp\ScssPhp\Block $block */ protected function compileDirective(Block $block) { @@ -919,7 +919,7 @@ protected function compileDirective(Block $block) /** * Compile at-root * - * @param \Leafo\ScssPhp\Block $block + * @param \ScssPhp\ScssPhp\Block $block */ protected function compileAtRoot(Block $block) { @@ -970,8 +970,8 @@ protected function compileAtRoot(Block $block) /** * Filter at-root scope depending of with/without option * - * @param \Leafo\ScssPhp\Formatter\OutputBlock $scope - * @param mixed $without + * @param \ScssPhp\ScssPhp\Formatter\OutputBlock $scope + * @param mixed $without * * @return mixed */ @@ -1038,8 +1038,8 @@ protected function filterScopeWithout($scope, $without) * found missing selector from a at-root compilation in the previous scope * (if at-root is just enclosing a property, the selector is in the parent tree) * - * @param \Leafo\ScssPhp\Formatter\OutputBlock $scope - * @param \Leafo\ScssPhp\Formatter\OutputBlock $previousScope + * @param \ScssPhp\ScssPhp\Formatter\OutputBlock $scope + * @param \ScssPhp\ScssPhp\Formatter\OutputBlock $previousScope * * @return mixed */ @@ -1061,8 +1061,8 @@ protected function completeScope($scope, $previousScope) /** * Find a selector by the depth node in the scope * - * @param \Leafo\ScssPhp\Formatter\OutputBlock $scope - * @param integer $depth + * @param \ScssPhp\ScssPhp\Formatter\OutputBlock $scope + * @param integer $depth * * @return array */ @@ -1139,7 +1139,7 @@ protected function compileWith($with) * @param array $envs * @param integer $without * - * @return \Leafo\ScssPhp\Compiler\Environment + * @return \ScssPhp\ScssPhp\Compiler\Environment */ protected function filterWithout($envs, $without) { @@ -1147,10 +1147,13 @@ protected function filterWithout($envs, $without) foreach ($envs as $e) { if ($e->block && $this->isWithout($without, $e->block)) { - continue; + $ec = clone $e; + $ec->block = null; + $ec->selectors = []; + $filtered[] = $ec; + } else { + $filtered[] = $e; } - - $filtered[] = $e; } return $this->extractEnv($filtered); @@ -1159,8 +1162,8 @@ protected function filterWithout($envs, $without) /** * Filter WITH rules * - * @param integer $without - * @param \Leafo\ScssPhp\Block|\Leafo\ScssPhp\Formatter\OutputBlock $block + * @param integer $without + * @param \ScssPhp\ScssPhp\Block|\ScssPhp\ScssPhp\Formatter\OutputBlock $block * * @return boolean */ @@ -1192,8 +1195,8 @@ protected function isWithout($without, $block) /** * Compile keyframe block * - * @param \Leafo\ScssPhp\Block $block - * @param array $selectors + * @param \ScssPhp\ScssPhp\Block $block + * @param array $selectors */ protected function compileKeyframeBlock(Block $block, $selectors) { @@ -1220,8 +1223,8 @@ protected function compileKeyframeBlock(Block $block, $selectors) /** * Compile nested block * - * @param \Leafo\ScssPhp\Block $block - * @param array $selectors + * @param \ScssPhp\ScssPhp\Block $block + * @param array $selectors */ protected function compileNestedBlock(Block $block, $selectors) { @@ -1282,7 +1285,7 @@ protected function compileNestedBlock(Block $block, $selectors) * * @see Compiler::compileChild() * - * @param \Leafo\ScssPhp\Block $block + * @param \ScssPhp\ScssPhp\Block $block */ protected function compileBlock(Block $block) { @@ -1349,7 +1352,7 @@ protected function compileBlock(Block $block) protected function compileComment($block) { $out = $this->makeOutputBlock(Type::T_COMMENT); - $out->lines[] = $block[1]; + $out->lines[] = is_string($block[1]) ? $block[1] : $this->compileValue($block[1]); $this->scope->children[] = $out; } @@ -1637,9 +1640,9 @@ protected function popCallStack() /** * Compile children and return result * - * @param array $stms - * @param \Leafo\ScssPhp\Formatter\OutputBlock $out - * @param string $traceName + * @param array $stms + * @param \ScssPhp\ScssPhp\Formatter\OutputBlock $out + * @param string $traceName * * @return array|null */ @@ -1663,10 +1666,10 @@ protected function compileChildren($stms, OutputBlock $out, $traceName = '') /** * Compile children and throw exception if unexpected @return * - * @param array $stms - * @param \Leafo\ScssPhp\Formatter\OutputBlock $out - * @param \Leafo\ScssPhp\Block $selfParent - * @param string $traceName + * @param array $stms + * @param \ScssPhp\ScssPhp\Formatter\OutputBlock $out + * @param \ScssPhp\ScssPhp\Block $selfParent + * @param string $traceName * * @throws \Exception */ @@ -1990,9 +1993,9 @@ protected function mergeMediaTypes($type1, $type2) /** * Compile import; returns true if the value was something that could be imported * - * @param array $rawPath - * @param \Leafo\ScssPhp\Formatter\OutputBlock $out - * @param boolean $once + * @param array $rawPath + * @param \ScssPhp\ScssPhp\Formatter\OutputBlock $out + * @param boolean $once * * @return boolean */ @@ -2038,8 +2041,8 @@ protected function compileImport($rawPath, OutputBlock $out, $once = false) /** * Compile child; returns a value to halt execution * - * @param array $child - * @param \Leafo\ScssPhp\Formatter\OutputBlock $out + * @param array $child + * @param \ScssPhp\ScssPhp\Formatter\OutputBlock $out * * @return array */ @@ -2545,7 +2548,7 @@ protected function shouldEval($value) * @param array $value * @param boolean $inExp * - * @return array|\Leafo\ScssPhp\Node\Number + * @return array|\ScssPhp\ScssPhp\Node\Number */ protected function reduce($value, $inExp = false) { @@ -2822,7 +2825,7 @@ public function normalizeValue($value) * @param array $left * @param array $right * - * @return \Leafo\ScssPhp\Node\Number + * @return \ScssPhp\ScssPhp\Node\Number */ protected function opAddNumberNumber($left, $right) { @@ -2835,7 +2838,7 @@ protected function opAddNumberNumber($left, $right) * @param array $left * @param array $right * - * @return \Leafo\ScssPhp\Node\Number + * @return \ScssPhp\ScssPhp\Node\Number */ protected function opMulNumberNumber($left, $right) { @@ -2848,7 +2851,7 @@ protected function opMulNumberNumber($left, $right) * @param array $left * @param array $right * - * @return \Leafo\ScssPhp\Node\Number + * @return \ScssPhp\ScssPhp\Node\Number */ protected function opSubNumberNumber($left, $right) { @@ -2861,7 +2864,7 @@ protected function opSubNumberNumber($left, $right) * @param array $left * @param array $right * - * @return array|\Leafo\ScssPhp\Node\Number + * @return array|\ScssPhp\ScssPhp\Node\Number */ protected function opDivNumberNumber($left, $right) { @@ -2878,7 +2881,7 @@ protected function opDivNumberNumber($left, $right) * @param array $left * @param array $right * - * @return \Leafo\ScssPhp\Node\Number + * @return \ScssPhp\ScssPhp\Node\Number */ protected function opModNumberNumber($left, $right) { @@ -2929,8 +2932,14 @@ protected function opAdd($left, $right) */ protected function opAnd($left, $right, $shouldEval) { + $truthy = ($left === static::$null || $right === static::$null) || + ($left === static::$false || $left === static::$true) && + ($right === static::$false || $right === static::$true); + if (! $shouldEval) { - return null; + if (! $truthy) { + return null; + } } if ($left !== static::$false && $left !== static::$null) { @@ -2951,8 +2960,14 @@ protected function opAnd($left, $right, $shouldEval) */ protected function opOr($left, $right, $shouldEval) { + $truthy = ($left === static::$null || $right === static::$null) || + ($left === static::$false || $left === static::$true) && + ($right === static::$false || $right === static::$true); + if (! $shouldEval) { - return null; + if (! $truthy) { + return null; + } } if ($left !== static::$false && $left !== static::$null) { @@ -3166,7 +3181,7 @@ protected function opLtNumberNumber($left, $right) * @param array $left * @param array $right * - * @return \Leafo\ScssPhp\Node\Number + * @return \ScssPhp\ScssPhp\Node\Number */ protected function opCmpNumberNumber($left, $right) { @@ -3420,8 +3435,8 @@ protected function extractInterpolation($list) /** * Find the final set of selectors * - * @param \Leafo\ScssPhp\Compiler\Environment $env - * @param \Leafo\ScssPhp\Block $selfParent + * @param \ScssPhp\ScssPhp\Compiler\Environment $env + * @param \ScssPhp\ScssPhp\Block $selfParent * * @return array */ @@ -3536,8 +3551,8 @@ protected function joinSelectors($parent, $child, &$stillHasSelf, $selfParentSel /** * Multiply media * - * @param \Leafo\ScssPhp\Compiler\Environment $env - * @param array $childQueries + * @param \ScssPhp\ScssPhp\Compiler\Environment $env + * @param array $childQueries * * @return array */ @@ -3587,7 +3602,7 @@ protected function multiplyMedia(Environment $env = null, $childQueries = null) /** * Convert env linked list to stack * - * @param \Leafo\ScssPhp\Compiler\Environment $env + * @param \ScssPhp\ScssPhp\Compiler\Environment $env * * @return array */ @@ -3605,7 +3620,7 @@ protected function compactEnv(Environment $env) * * @param array $envs * - * @return \Leafo\ScssPhp\Compiler\Environment + * @return \ScssPhp\ScssPhp\Compiler\Environment */ protected function extractEnv($envs) { @@ -3620,9 +3635,9 @@ protected function extractEnv($envs) /** * Push environment * - * @param \Leafo\ScssPhp\Block $block + * @param \ScssPhp\ScssPhp\Block $block * - * @return \Leafo\ScssPhp\Compiler\Environment + * @return \ScssPhp\ScssPhp\Compiler\Environment */ protected function pushEnv(Block $block = null) { @@ -3648,7 +3663,7 @@ protected function popEnv() /** * Get store environment * - * @return \Leafo\ScssPhp\Compiler\Environment + * @return \ScssPhp\ScssPhp\Compiler\Environment */ protected function getStoreEnv() { @@ -3658,11 +3673,11 @@ protected function getStoreEnv() /** * Set variable * - * @param string $name - * @param mixed $value - * @param boolean $shadow - * @param \Leafo\ScssPhp\Compiler\Environment $env - * @param mixed $valueUnreduced + * @param string $name + * @param mixed $value + * @param boolean $shadow + * @param \ScssPhp\ScssPhp\Compiler\Environment $env + * @param mixed $valueUnreduced */ protected function set($name, $value, $shadow = false, Environment $env = null, $valueUnreduced = null) { @@ -3682,10 +3697,10 @@ protected function set($name, $value, $shadow = false, Environment $env = null, /** * Set existing variable * - * @param string $name - * @param mixed $value - * @param \Leafo\ScssPhp\Compiler\Environment $env - * @param mixed $valueUnreduced + * @param string $name + * @param mixed $value + * @param \ScssPhp\ScssPhp\Compiler\Environment $env + * @param mixed $valueUnreduced */ protected function setExisting($name, $value, Environment $env, $valueUnreduced = null) { @@ -3721,10 +3736,10 @@ protected function setExisting($name, $value, Environment $env, $valueUnreduced /** * Set raw variable * - * @param string $name - * @param mixed $value - * @param \Leafo\ScssPhp\Compiler\Environment $env - * @param mixed $valueUnreduced + * @param string $name + * @param mixed $value + * @param \ScssPhp\ScssPhp\Compiler\Environment $env + * @param mixed $valueUnreduced */ protected function setRaw($name, $value, Environment $env, $valueUnreduced = null) { @@ -3740,10 +3755,10 @@ protected function setRaw($name, $value, Environment $env, $valueUnreduced = nul * * @api * - * @param string $name - * @param boolean $shouldThrow - * @param \Leafo\ScssPhp\Compiler\Environment $env - * @param boolean $unreduced + * @param string $name + * @param boolean $shouldThrow + * @param \ScssPhp\ScssPhp\Compiler\Environment $env + * @param boolean $unreduced * * @return mixed|null */ @@ -3802,8 +3817,8 @@ public function get($name, $shouldThrow = true, Environment $env = null, $unredu /** * Has variable? * - * @param string $name - * @param \Leafo\ScssPhp\Compiler\Environment $env + * @param string $name + * @param \ScssPhp\ScssPhp\Compiler\Environment $env * * @return boolean */ @@ -4027,8 +4042,8 @@ public function addFeature($name) /** * Import file * - * @param string $path - * @param \Leafo\ScssPhp\Formatter\OutputBlock $out + * @param string $path + * @param \ScssPhp\ScssPhp\Formatter\OutputBlock $out */ protected function importFile($path, OutputBlock $out) { @@ -4123,7 +4138,7 @@ public function setEncoding($encoding) * * @param boolean $ignoreErrors * - * @return \Leafo\ScssPhp\Compiler + * @return \ScssPhp\ScssPhp\Compiler */ public function setIgnoreErrors($ignoreErrors) { @@ -4139,7 +4154,7 @@ public function setIgnoreErrors($ignoreErrors) * * @param string $msg Message with optional sprintf()-style vararg parameters * - * @throws \Leafo\ScssPhp\Exception\CompilerException + * @throws \ScssPhp\ScssPhp\Exception\CompilerException */ public function throwError($msg) { @@ -4147,14 +4162,17 @@ public function throwError($msg) return; } + $line = $this->sourceLine; + $column = $this->sourceColumn; + + $loc = isset($this->sourceNames[$this->sourceIndex]) + ? $this->sourceNames[$this->sourceIndex] . " on line $line, at column $column" + : "line: $line, column: $column"; + if (func_num_args() > 1) { $msg = call_user_func_array('sprintf', func_get_args()); } - $line = $this->sourceLine; - $loc = isset($this->sourceNames[$this->sourceIndex]) - ? $this->sourceNames[$this->sourceIndex] . " on line $line" - : "line: $line"; $msg = "$msg: $loc"; $callStackMsg = $this->callStackMessage(); @@ -4506,7 +4524,7 @@ protected function applyArguments($argDef, $argValues) * * @param mixed $value * - * @return array|\Leafo\ScssPhp\Node\Number + * @return array|\ScssPhp\ScssPhp\Node\Number */ protected function coerceValue($value) { @@ -6018,4 +6036,624 @@ protected function libInspect($args) return $args[0]; } + + /** + * Preprocess selector args + * + * @param array $arg + * + * @return array|boolean + */ + protected function getSelectorArg($arg) + { + static $parser = null; + + if (is_null($parser)) { + $parser = $this->parserFactory(__METHOD__); + } + + $arg = $this->libUnquote([$arg]); + $arg = $this->compileValue($arg); + + $parsedSelector = []; + + if ($parser->parseSelector($arg, $parsedSelector)) { + $selector = $this->evalSelectors($parsedSelector); + $gluedSelector = $this->glueFunctionSelectors($selector); + + return $gluedSelector; + } + + return false; + } + + /** + * Postprocess selector to output in right format + * + * @param array $selectors + * + * @return string + */ + protected function formatOutputSelector($selectors) + { + $selectors = $this->collapseSelectors($selectors, true); + + return $selectors; + } + + protected static $libIsSuperselector = ['super', 'sub']; + protected function libIsSuperselector($args) + { + list($super, $sub) = $args; + + $super = $this->getSelectorArg($super); + $sub = $this->getSelectorArg($sub); + + return $this->isSuperSelector($super, $sub); + } + + /** + * Test a $super selector again $sub + * + * @param array $super + * @param array $sub + * + * @return boolean + */ + protected function isSuperSelector($super, $sub) + { + // one and only one selector for each arg + if (! $super || count($super) !== 1) { + $this->throwError("Invalid super selector for isSuperSelector()"); + } + + if (! $sub || count($sub) !== 1) { + $this->throwError("Invalid sub selector for isSuperSelector()"); + } + + $super = reset($super); + $sub = reset($sub); + + $i = 0; + $nextMustMatch = false; + + foreach ($super as $node) { + $compound = ''; + + array_walk_recursive( + $node, + function ($value, $key) use (&$compound) { + $compound .= $value; + } + ); + + if ($this->isImmediateRelationshipCombinator($compound)) { + if ($node !== $sub[$i]) { + return false; + } + + $nextMustMatch = true; + $i++; + } else { + while ($i < count($sub) && ! $this->isSuperPart($node, $sub[$i])) { + if ($nextMustMatch) { + return false; + } + + $i++; + } + + if ($i >= count($sub)) { + return false; + } + + $nextMustMatch = false; + $i++; + } + } + + return true; + } + + /** + * Test a part of super selector again a part of sub selector + * + * @param array $superParts + * @param array $subParts + * + * @return boolean + */ + protected function isSuperPart($superParts, $subParts) + { + $i = 0; + + foreach ($superParts as $superPart) { + while ($i < count($subParts) && $subParts[$i] !== $superPart) { + $i++; + } + + if ($i >= count($subParts)) { + return false; + } + + $i++; + } + + return true; + } + + //protected static $libSelectorAppend = ['selector...']; + protected function libSelectorAppend($args) + { + if (count($args) < 1) { + $this->throwError("selector-append() needs at least 1 argument"); + } + + $selectors = array_map([$this, 'getSelectorArg'], $args); + + return $this->formatOutputSelector($this->selectorAppend($selectors)); + } + + /** + * Append parts of the last selector in the list to the previous, recursively + * + * @param array $selectors + * + * @return array + * + * @throws \ScssPhp\ScssPhp\Exception\CompilerException + */ + protected function selectorAppend($selectors) + { + $lastSelectors = array_pop($selectors); + + if (! $lastSelectors) { + $this->throwError("Invalid selector list in selector-append()"); + } + + while (count($selectors)) { + $previousSelectors = array_pop($selectors); + + if (! $previousSelectors) { + $this->throwError("Invalid selector list in selector-append()"); + } + + // do the trick, happening $lastSelector to $previousSelector + $appended = []; + + foreach ($lastSelectors as $lastSelector) { + $previous = $previousSelectors; + + foreach ($lastSelector as $lastSelectorParts) { + foreach ($lastSelectorParts as $lastSelectorPart) { + foreach ($previous as $i => $previousSelector) { + foreach ($previousSelector as $j => $previousSelectorParts) { + $previous[$i][$j][] = $lastSelectorPart; + } + } + } + } + + foreach ($previous as $ps) { + $appended[] = $ps; + } + } + + $lastSelectors = $appended; + } + + return $lastSelectors; + } + + protected static $libSelectorExtend = ['selectors', 'extendee', 'extender']; + protected function libSelectorExtend($args) + { + list($selectors, $extendee, $extender) = $args; + + $selectors = $this->getSelectorArg($selectors); + $extendee = $this->getSelectorArg($extendee); + $extender = $this->getSelectorArg($extender); + + if (! $selectors || ! $extendee || ! $extender) { + $this->throwError("selector-extend() invalid arguments"); + } + + $extended = $this->extendOrReplaceSelectors($selectors, $extendee, $extender); + + return $this->formatOutputSelector($extended); + } + + protected static $libSelectorReplace = ['selectors', 'original', 'replacement']; + protected function libSelectorReplace($args) + { + list($selectors, $original, $replacement) = $args; + + $selectors = $this->getSelectorArg($selectors); + $original = $this->getSelectorArg($original); + $replacement = $this->getSelectorArg($replacement); + + if (! $selectors || ! $original || ! $replacement) { + $this->throwError("selector-replace() invalid arguments"); + } + + $replaced = $this->extendOrReplaceSelectors($selectors, $original, $replacement, true); + + return $this->formatOutputSelector($replaced); + } + + /** + * Extend/replace in selectors + * used by selector-extend and selector-replace that use the same logic + * + * @param array $selectors + * @param array $extendee + * @param array $extender + * @param boolean $replace + * + * @return array + */ + protected function extendOrReplaceSelectors($selectors, $extendee, $extender, $replace = false) + { + $saveExtends = $this->extends; + $saveExtendsMap = $this->extendsMap; + + $this->extends = []; + $this->extendsMap = []; + + foreach ($extendee as $es) { + // only use the first one + $this->pushExtends(reset($es), $extender, null); + } + + $extended = []; + + foreach ($selectors as $selector) { + if (! $replace) { + $extended[] = $selector; + } + + $n = count($extended); + + $this->matchExtends($selector, $extended); + + // if didnt match, keep the original selector if we are in a replace operation + if ($replace and count($extended) === $n) { + $extended[] = $selector; + } + } + + $this->extends = $saveExtends; + $this->extendsMap = $saveExtendsMap; + + return $extended; + } + + //protected static $libSelectorNest = ['selector...']; + protected function libSelectorNest($args) + { + if (count($args) < 1) { + $this->throwError("selector-nest() needs at least 1 argument"); + } + + $selectorsMap = array_map([$this, 'getSelectorArg'], $args); + + $envs = []; + foreach ($selectorsMap as $selectors) { + $env = new Environment(); + $env->selectors = $selectors; + + $envs[] = $env; + } + + $envs = array_reverse($envs); + $env = $this->extractEnv($envs); + $outputSelectors = $this->multiplySelectors($env); + + return $this->formatOutputSelector($outputSelectors); + } + + protected static $libSelectorParse = ['selectors']; + protected function libSelectorParse($args) + { + $selectors = reset($args); + $selectors = $this->getSelectorArg($selectors); + + return $this->formatOutputSelector($selectors); + } + + protected static $libSelectorUnify = ['selectors1', 'selectors2']; + protected function libSelectorUnify($args) + { + list($selectors1, $selectors2) = $args; + + $selectors1 = $this->getSelectorArg($selectors1); + $selectors2 = $this->getSelectorArg($selectors2); + + if (! $selectors1 || ! $selectors2) { + $this->throwError("selector-unify() invalid arguments"); + } + + // only consider the first compound of each + $compound1 = reset($selectors1); + $compound2 = reset($selectors2); + + // unify them and that's it + $unified = $this->unifyCompoundSelectors($compound1, $compound2); + + return $this->formatOutputSelector($unified); + } + + /** + * The selector-unify magic as its best + * (at least works as expected on test cases) + * + * @param array $compound1 + * @param array $compound2 + * @return array|mixed + */ + protected function unifyCompoundSelectors($compound1, $compound2) + { + if (! count($compound1)) { + return $compound2; + } + + if (! count($compound2)) { + return $compound1; + } + + // check that last part are compatible + $lastPart1 = array_pop($compound1); + $lastPart2 = array_pop($compound2); + $last = $this->mergeParts($lastPart1, $lastPart2); + + if (! $last) { + return [[]]; + } + + $unifiedCompound = [$last]; + $unifiedSelectors = [$unifiedCompound]; + + // do the rest + while (count($compound1) || count($compound2)) { + $part1 = end($compound1); + $part2 = end($compound2); + + if ($part1 && ($match2 = $this->matchPartInCompound($part1, $compound2))) { + list($compound2, $part2, $after2) = $match2; + + if ($after2) { + $unifiedSelectors = $this->prependSelectors($unifiedSelectors, $after2); + } + + $c = $this->mergeParts($part1, $part2); + $unifiedSelectors = $this->prependSelectors($unifiedSelectors, [$c]); + $part1 = $part2 = null; + + array_pop($compound1); + } + + if ($part2 && ($match1 = $this->matchPartInCompound($part2, $compound1))) { + list($compound1, $part1, $after1) = $match1; + + if ($after1) { + $unifiedSelectors = $this->prependSelectors($unifiedSelectors, $after1); + } + + $c = $this->mergeParts($part2, $part1); + $unifiedSelectors = $this->prependSelectors($unifiedSelectors, [$c]); + $part1 = $part2 = null; + + array_pop($compound2); + } + + $new = []; + + if ($part1 && $part2) { + array_pop($compound1); + array_pop($compound2); + + $s = $this->prependSelectors($unifiedSelectors, [$part2]); + $new = array_merge($new, $this->prependSelectors($s, [$part1])); + $s = $this->prependSelectors($unifiedSelectors, [$part1]); + $new = array_merge($new, $this->prependSelectors($s, [$part2])); + } elseif ($part1) { + array_pop($compound1); + + $new = array_merge($new, $this->prependSelectors($unifiedSelectors, [$part1])); + } elseif ($part2) { + array_pop($compound2); + + $new = array_merge($new, $this->prependSelectors($unifiedSelectors, [$part2])); + } + + if ($new) { + $unifiedSelectors = $new; + } + } + + return $unifiedSelectors; + } + + /** + * Prepend each selector from $selectors with $parts + * + * @param array $selectors + * @param array $parts + * + * @return array + */ + protected function prependSelectors($selectors, $parts) + { + $new = []; + + foreach ($selectors as $compoundSelector) { + array_unshift($compoundSelector, $parts); + + $new[] = $compoundSelector; + } + + return $new; + } + + /** + * Try to find a matching part in a compound: + * - with same html tag name + * - with some class or id or something in common + * + * @param array $part + * @param array $compound + * + * @return array|boolean + */ + protected function matchPartInCompound($part, $compound) + { + $partTag = $this->findTagName($part); + $before = $compound; + $after = []; + + // try to find a match by tag name first + while (count($before)) { + $p = array_pop($before); + + if ($partTag && $partTag !== '*' && $partTag == $this->findTagName($p)) { + return [$before, $p, $after]; + } + + $after[] = $p; + } + + // try again matching a non empty intersection and a compatible tagname + $before = $compound; + $after = []; + + while (count($before)) { + $p = array_pop($before); + + if ($this->checkCompatibleTags($partTag, $this->findTagName($p))) { + if (count(array_intersect($part, $p))) { + return [$before, $p, $after]; + } + } + + $after[] = $p; + } + + return false; + } + + /** + * Merge two part list taking care that + * - the html tag is coming first - if any + * - the :something are coming last + * + * @param array $parts1 + * @param array $parts2 + * + * @return array + */ + protected function mergeParts($parts1, $parts2) + { + $tag1 = $this->findTagName($parts1); + $tag2 = $this->findTagName($parts2); + $tag = $this->checkCompatibleTags($tag1, $tag2); + + // not compatible tags + if ($tag === false) { + return []; + } + + if ($tag) { + if ($tag1) { + $parts1 = array_diff($parts1, [$tag1]); + } + + if ($tag2) { + $parts2 = array_diff($parts2, [$tag2]); + } + } + + $mergedParts = array_merge($parts1, $parts2); + $mergedOrderedParts = []; + + foreach ($mergedParts as $part) { + if (strpos($part, ':') === 0) { + $mergedOrderedParts[] = $part; + } + } + + $mergedParts = array_diff($mergedParts, $mergedOrderedParts); + $mergedParts = array_merge($mergedParts, $mergedOrderedParts); + + if ($tag) { + array_unshift($mergedParts, $tag); + } + + return $mergedParts; + } + + /** + * Check the compatibility between two tag names: + * if both are defined they should be identical or one has to be '*' + * + * @param string $tag1 + * @param string $tag2 + * + * @return array|boolean + */ + protected function checkCompatibleTags($tag1, $tag2) + { + $tags = [$tag1, $tag2]; + $tags = array_unique($tags); + $tags = array_filter($tags); + + if (count($tags)>1) { + $tags = array_diff($tags, ['*']); + } + + // not compatible nodes + if (count($tags)>1) { + return false; + } + + return $tags; + } + + /** + * Find the html tag name in a selector parts list + * + * @param array $parts + * + * @return mixed|string + */ + protected function findTagName($parts) + { + foreach ($parts as $part) { + if (! preg_match('/^[\[.:#%_-]/', $part)) { + return $part; + } + } + + return ''; + } + + protected static $libSimpleSelectors = ['selector']; + protected function libSimpleSelectors($args) + { + $selector = reset($args); + $selector = $this->getSelectorArg($selector); + + // remove selectors list layer, keeping the first one + $selector = reset($selector); + + // remove parts list layer, keeping the first part + $part = reset($selector); + + $listParts = []; + + foreach ($part as $p) { + $listParts[] = [Type::T_STRING, '', [$p]]; + } + + return [Type::T_LIST, ',', $listParts]; + } } diff --git a/lib/scssphp/Compiler/Environment.php b/lib/scssphp/Compiler/Environment.php index 99231f3682a8f..03eb86a5d5713 100644 --- a/lib/scssphp/Compiler/Environment.php +++ b/lib/scssphp/Compiler/Environment.php @@ -2,14 +2,14 @@ /** * SCSSPHP * - * @copyright 2012-2018 Leaf Corcoran + * @copyright 2012-2019 Leaf Corcoran * * @license http://opensource.org/licenses/MIT MIT * - * @link http://leafo.github.io/scssphp + * @link http://scssphp.github.io/scssphp */ -namespace Leafo\ScssPhp\Compiler; +namespace ScssPhp\ScssPhp\Compiler; /** * Compiler environment @@ -19,12 +19,12 @@ class Environment { /** - * @var \Leafo\ScssPhp\Block + * @var \ScssPhp\ScssPhp\Block */ public $block; /** - * @var \Leafo\ScssPhp\Compiler\Environment + * @var \ScssPhp\ScssPhp\Compiler\Environment */ public $parent; diff --git a/lib/scssphp/Exception/CompilerException.php b/lib/scssphp/Exception/CompilerException.php index 7ca2e2b3bb9c1..a9d134fca0993 100644 --- a/lib/scssphp/Exception/CompilerException.php +++ b/lib/scssphp/Exception/CompilerException.php @@ -2,14 +2,14 @@ /** * SCSSPHP * - * @copyright 2012-2018 Leaf Corcoran + * @copyright 2012-2019 Leaf Corcoran * * @license http://opensource.org/licenses/MIT MIT * - * @link http://leafo.github.io/scssphp + * @link http://scssphp.github.io/scssphp */ -namespace Leafo\ScssPhp\Exception; +namespace ScssPhp\ScssPhp\Exception; /** * Compiler exception diff --git a/lib/scssphp/Exception/ParserException.php b/lib/scssphp/Exception/ParserException.php index 6d64335fe7c27..2fa12dd7a8a90 100644 --- a/lib/scssphp/Exception/ParserException.php +++ b/lib/scssphp/Exception/ParserException.php @@ -2,14 +2,14 @@ /** * SCSSPHP * - * @copyright 2012-2018 Leaf Corcoran + * @copyright 2012-2019 Leaf Corcoran * * @license http://opensource.org/licenses/MIT MIT * - * @link http://leafo.github.io/scssphp + * @link http://scssphp.github.io/scssphp */ -namespace Leafo\ScssPhp\Exception; +namespace ScssPhp\ScssPhp\Exception; /** * Parser Exception diff --git a/lib/scssphp/Exception/RangeException.php b/lib/scssphp/Exception/RangeException.php index 3ba6bf143b1a9..ee36c97e18629 100644 --- a/lib/scssphp/Exception/RangeException.php +++ b/lib/scssphp/Exception/RangeException.php @@ -2,14 +2,14 @@ /** * SCSSPHP * - * @copyright 2012-2018 Leaf Corcoran + * @copyright 2012-2019 Leaf Corcoran * * @license http://opensource.org/licenses/MIT MIT * - * @link http://leafo.github.io/scssphp + * @link http://scssphp.github.io/scssphp */ -namespace Leafo\ScssPhp\Exception; +namespace ScssPhp\ScssPhp\Exception; /** * Range exception diff --git a/lib/scssphp/Exception/ServerException.php b/lib/scssphp/Exception/ServerException.php index d0ed0842739be..d4a207aff8d38 100644 --- a/lib/scssphp/Exception/ServerException.php +++ b/lib/scssphp/Exception/ServerException.php @@ -2,14 +2,14 @@ /** * SCSSPHP * - * @copyright 2012-2018 Leaf Corcoran + * @copyright 2012-2019 Leaf Corcoran * * @license http://opensource.org/licenses/MIT MIT * - * @link http://leafo.github.io/scssphp + * @link http://scssphp.github.io/scssphp */ -namespace Leafo\ScssPhp\Exception; +namespace ScssPhp\ScssPhp\Exception; /** * Server Exception diff --git a/lib/scssphp/Formatter.php b/lib/scssphp/Formatter.php index 1403859db62f6..b2efc2dcb4cc4 100644 --- a/lib/scssphp/Formatter.php +++ b/lib/scssphp/Formatter.php @@ -2,17 +2,17 @@ /** * SCSSPHP * - * @copyright 2012-2018 Leaf Corcoran + * @copyright 2012-2019 Leaf Corcoran * * @license http://opensource.org/licenses/MIT MIT * - * @link http://leafo.github.io/scssphp + * @link http://scssphp.github.io/scssphp */ -namespace Leafo\ScssPhp; +namespace ScssPhp\ScssPhp; -use Leafo\ScssPhp\Formatter\OutputBlock; -use Leafo\ScssPhp\SourceMap\SourceMapGenerator; +use ScssPhp\ScssPhp\Formatter\OutputBlock; +use ScssPhp\ScssPhp\SourceMap\SourceMapGenerator; /** * Base formatter @@ -62,7 +62,7 @@ abstract class Formatter public $keepSemicolons; /** - * @var \Leafo\ScssPhp\Formatter\OutputBlock + * @var \ScssPhp\ScssPhp\Formatter\OutputBlock */ protected $currentBlock; @@ -77,7 +77,7 @@ abstract class Formatter protected $currentColumn; /** - * @var \Leafo\ScssPhp\SourceMap\SourceMapGenerator + * @var \ScssPhp\ScssPhp\SourceMap\SourceMapGenerator */ protected $sourceMapGenerator; @@ -136,7 +136,7 @@ public function stripSemicolon(&$lines) /** * Output lines inside a block * - * @param \Leafo\ScssPhp\Formatter\OutputBlock $block + * @param \ScssPhp\ScssPhp\Formatter\OutputBlock $block */ protected function blockLines(OutputBlock $block) { @@ -154,7 +154,7 @@ protected function blockLines(OutputBlock $block) /** * Output block selectors * - * @param \Leafo\ScssPhp\Formatter\OutputBlock $block + * @param \ScssPhp\ScssPhp\Formatter\OutputBlock $block */ protected function blockSelectors(OutputBlock $block) { @@ -168,7 +168,7 @@ protected function blockSelectors(OutputBlock $block) /** * Output block children * - * @param \Leafo\ScssPhp\Formatter\OutputBlock $block + * @param \ScssPhp\ScssPhp\Formatter\OutputBlock $block */ protected function blockChildren(OutputBlock $block) { @@ -180,7 +180,7 @@ protected function blockChildren(OutputBlock $block) /** * Output non-empty block * - * @param \Leafo\ScssPhp\Formatter\OutputBlock $block + * @param \ScssPhp\ScssPhp\Formatter\OutputBlock $block */ protected function block(OutputBlock $block) { @@ -222,8 +222,8 @@ protected function block(OutputBlock $block) * * @api * - * @param \Leafo\ScssPhp\Formatter\OutputBlock $block An abstract syntax tree - * @param \Leafo\ScssPhp\SourceMap\SourceMapGenerator|null $sourceMapGenerator Optional source map generator + * @param \ScssPhp\ScssPhp\Formatter\OutputBlock $block An abstract syntax tree + * @param \ScssPhp\ScssPhp\SourceMap\SourceMapGenerator|null $sourceMapGenerator Optional source map generator * * @return string */ diff --git a/lib/scssphp/Formatter/Compact.php b/lib/scssphp/Formatter/Compact.php index 4efa1a089a396..591f0c92ef9a8 100644 --- a/lib/scssphp/Formatter/Compact.php +++ b/lib/scssphp/Formatter/Compact.php @@ -2,16 +2,16 @@ /** * SCSSPHP * - * @copyright 2012-2018 Leaf Corcoran + * @copyright 2012-2019 Leaf Corcoran * * @license http://opensource.org/licenses/MIT MIT * - * @link http://leafo.github.io/scssphp + * @link http://scssphp.github.io/scssphp */ -namespace Leafo\ScssPhp\Formatter; +namespace ScssPhp\ScssPhp\Formatter; -use Leafo\ScssPhp\Formatter; +use ScssPhp\ScssPhp\Formatter; /** * Compact formatter diff --git a/lib/scssphp/Formatter/Compressed.php b/lib/scssphp/Formatter/Compressed.php index ab38529dda065..ec4722eaf4b91 100644 --- a/lib/scssphp/Formatter/Compressed.php +++ b/lib/scssphp/Formatter/Compressed.php @@ -2,17 +2,17 @@ /** * SCSSPHP * - * @copyright 2012-2018 Leaf Corcoran + * @copyright 2012-2019 Leaf Corcoran * * @license http://opensource.org/licenses/MIT MIT * - * @link http://leafo.github.io/scssphp + * @link http://scssphp.github.io/scssphp */ -namespace Leafo\ScssPhp\Formatter; +namespace ScssPhp\ScssPhp\Formatter; -use Leafo\ScssPhp\Formatter; -use Leafo\ScssPhp\Formatter\OutputBlock; +use ScssPhp\ScssPhp\Formatter; +use ScssPhp\ScssPhp\Formatter\OutputBlock; /** * Compressed formatter @@ -63,7 +63,7 @@ public function blockLines(OutputBlock $block) /** * Output block selectors * - * @param \Leafo\ScssPhp\Formatter\OutputBlock $block + * @param \ScssPhp\ScssPhp\Formatter\OutputBlock $block */ protected function blockSelectors(OutputBlock $block) { diff --git a/lib/scssphp/Formatter/Crunched.php b/lib/scssphp/Formatter/Crunched.php index da740ccd110e7..51ccb516d843e 100644 --- a/lib/scssphp/Formatter/Crunched.php +++ b/lib/scssphp/Formatter/Crunched.php @@ -2,17 +2,17 @@ /** * SCSSPHP * - * @copyright 2012-2018 Leaf Corcoran + * @copyright 2012-2019 Leaf Corcoran * * @license http://opensource.org/licenses/MIT MIT * - * @link http://leafo.github.io/scssphp + * @link http://scssphp.github.io/scssphp */ -namespace Leafo\ScssPhp\Formatter; +namespace ScssPhp\ScssPhp\Formatter; -use Leafo\ScssPhp\Formatter; -use Leafo\ScssPhp\Formatter\OutputBlock; +use ScssPhp\ScssPhp\Formatter; +use ScssPhp\ScssPhp\Formatter\OutputBlock; /** * Crunched formatter @@ -61,7 +61,7 @@ public function blockLines(OutputBlock $block) /** * Output block selectors * - * @param \Leafo\ScssPhp\Formatter\OutputBlock $block + * @param \ScssPhp\ScssPhp\Formatter\OutputBlock $block */ protected function blockSelectors(OutputBlock $block) { diff --git a/lib/scssphp/Formatter/Debug.php b/lib/scssphp/Formatter/Debug.php index bfcbf41ad7fad..94e70c815df7f 100644 --- a/lib/scssphp/Formatter/Debug.php +++ b/lib/scssphp/Formatter/Debug.php @@ -2,17 +2,17 @@ /** * SCSSPHP * - * @copyright 2012-2018 Leaf Corcoran + * @copyright 2012-2019 Leaf Corcoran * * @license http://opensource.org/licenses/MIT MIT * - * @link http://leafo.github.io/scssphp + * @link http://scssphp.github.io/scssphp */ -namespace Leafo\ScssPhp\Formatter; +namespace ScssPhp\ScssPhp\Formatter; -use Leafo\ScssPhp\Formatter; -use Leafo\ScssPhp\Formatter\OutputBlock; +use ScssPhp\ScssPhp\Formatter; +use ScssPhp\ScssPhp\Formatter\OutputBlock; /** * Debug formatter diff --git a/lib/scssphp/Formatter/Expanded.php b/lib/scssphp/Formatter/Expanded.php index d8c1e8879e815..8eec475878a79 100644 --- a/lib/scssphp/Formatter/Expanded.php +++ b/lib/scssphp/Formatter/Expanded.php @@ -2,17 +2,17 @@ /** * SCSSPHP * - * @copyright 2012-2018 Leaf Corcoran + * @copyright 2012-2019 Leaf Corcoran * * @license http://opensource.org/licenses/MIT MIT * - * @link http://leafo.github.io/scssphp + * @link http://scssphp.github.io/scssphp */ -namespace Leafo\ScssPhp\Formatter; +namespace ScssPhp\ScssPhp\Formatter; -use Leafo\ScssPhp\Formatter; -use Leafo\ScssPhp\Formatter\OutputBlock; +use ScssPhp\ScssPhp\Formatter; +use ScssPhp\ScssPhp\Formatter\OutputBlock; /** * Expanded formatter diff --git a/lib/scssphp/Formatter/Nested.php b/lib/scssphp/Formatter/Nested.php index 8f72206fd16d0..260ae8e7aa920 100644 --- a/lib/scssphp/Formatter/Nested.php +++ b/lib/scssphp/Formatter/Nested.php @@ -2,17 +2,17 @@ /** * SCSSPHP * - * @copyright 2012-2018 Leaf Corcoran + * @copyright 2012-2019 Leaf Corcoran * * @license http://opensource.org/licenses/MIT MIT * - * @link http://leafo.github.io/scssphp + * @link http://scssphp.github.io/scssphp */ -namespace Leafo\ScssPhp\Formatter; +namespace ScssPhp\ScssPhp\Formatter; -use Leafo\ScssPhp\Formatter; -use Leafo\ScssPhp\Formatter\OutputBlock; +use ScssPhp\ScssPhp\Formatter; +use ScssPhp\ScssPhp\Formatter\OutputBlock; /** * Nested formatter @@ -153,7 +153,7 @@ protected function block(OutputBlock $block) /** * Adjust the depths of all children, depth first * - * @param \Leafo\ScssPhp\Formatter\OutputBlock $block + * @param \ScssPhp\ScssPhp\Formatter\OutputBlock $block */ private function adjustAllChildren(OutputBlock $block) { diff --git a/lib/scssphp/Formatter/OutputBlock.php b/lib/scssphp/Formatter/OutputBlock.php index 5eb589c94590e..3e6fd9289d152 100644 --- a/lib/scssphp/Formatter/OutputBlock.php +++ b/lib/scssphp/Formatter/OutputBlock.php @@ -2,14 +2,14 @@ /** * SCSSPHP * - * @copyright 2012-2018 Leaf Corcoran + * @copyright 2012-2019 Leaf Corcoran * * @license http://opensource.org/licenses/MIT MIT * - * @link http://leafo.github.io/scssphp + * @link http://scssphp.github.io/scssphp */ -namespace Leafo\ScssPhp\Formatter; +namespace ScssPhp\ScssPhp\Formatter; /** * Output block @@ -44,7 +44,7 @@ class OutputBlock public $children; /** - * @var \Leafo\ScssPhp\Formatter\OutputBlock + * @var \ScssPhp\ScssPhp\Formatter\OutputBlock */ public $parent; diff --git a/lib/scssphp/LICENSE.md b/lib/scssphp/LICENSE.md index 2f5412f9b536e..afcfdfb264eea 100644 --- a/lib/scssphp/LICENSE.md +++ b/lib/scssphp/LICENSE.md @@ -1,4 +1,4 @@ -Copyright (c) 2015 Leaf Corcoran, http://leafo.github.io/scssphp +Copyright (c) 2015 Leaf Corcoran, http://scssphp.github.io/scssphp Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the diff --git a/lib/scssphp/Node.php b/lib/scssphp/Node.php index b9f7945a353ad..dab565a63c156 100644 --- a/lib/scssphp/Node.php +++ b/lib/scssphp/Node.php @@ -2,14 +2,14 @@ /** * SCSSPHP * - * @copyright 2012-2018 Leaf Corcoran + * @copyright 2012-2019 Leaf Corcoran * * @license http://opensource.org/licenses/MIT MIT * - * @link http://leafo.github.io/scssphp + * @link http://scssphp.github.io/scssphp */ -namespace Leafo\ScssPhp; +namespace ScssPhp\ScssPhp; /** * Base node diff --git a/lib/scssphp/Node/Number.php b/lib/scssphp/Node/Number.php index 42c168037fac8..e184ca193c4b3 100644 --- a/lib/scssphp/Node/Number.php +++ b/lib/scssphp/Node/Number.php @@ -2,18 +2,18 @@ /** * SCSSPHP * - * @copyright 2012-2018 Leaf Corcoran + * @copyright 2012-2019 Leaf Corcoran * * @license http://opensource.org/licenses/MIT MIT * - * @link http://leafo.github.io/scssphp + * @link http://scssphp.github.io/scssphp */ -namespace Leafo\ScssPhp\Node; +namespace ScssPhp\ScssPhp\Node; -use Leafo\ScssPhp\Compiler; -use Leafo\ScssPhp\Node; -use Leafo\ScssPhp\Type; +use ScssPhp\ScssPhp\Compiler; +use ScssPhp\ScssPhp\Node; +use ScssPhp\ScssPhp\Type; /** * Dimension + optional units @@ -100,7 +100,7 @@ public function __construct($dimension, $initialUnit) * * @param array $units * - * @return \Leafo\ScssPhp\Node\Number + * @return \ScssPhp\ScssPhp\Node\Number */ public function coerce($units) { @@ -123,7 +123,7 @@ public function coerce($units) /** * Normalize number * - * @return \Leafo\ScssPhp\Node\Number + * @return \ScssPhp\ScssPhp\Node\Number */ public function normalize() { @@ -259,7 +259,7 @@ public function unitStr() /** * Output number * - * @param \Leafo\ScssPhp\Compiler $compiler + * @param \ScssPhp\ScssPhp\Compiler $compiler * * @return string */ diff --git a/lib/scssphp/Parser.php b/lib/scssphp/Parser.php index 9f8cb2e8716fa..b8091313b4c27 100644 --- a/lib/scssphp/Parser.php +++ b/lib/scssphp/Parser.php @@ -2,21 +2,21 @@ /** * SCSSPHP * - * @copyright 2012-2018 Leaf Corcoran + * @copyright 2012-2019 Leaf Corcoran * * @license http://opensource.org/licenses/MIT MIT * - * @link http://leafo.github.io/scssphp + * @link http://scssphp.github.io/scssphp */ -namespace Leafo\ScssPhp; +namespace ScssPhp\ScssPhp; -use Leafo\ScssPhp\Block; -use Leafo\ScssPhp\Cache; -use Leafo\ScssPhp\Compiler; -use Leafo\ScssPhp\Exception\ParserException; -use Leafo\ScssPhp\Node; -use Leafo\ScssPhp\Type; +use ScssPhp\ScssPhp\Block; +use ScssPhp\ScssPhp\Cache; +use ScssPhp\ScssPhp\Compiler; +use ScssPhp\ScssPhp\Exception\ParserException; +use ScssPhp\ScssPhp\Node; +use ScssPhp\ScssPhp\Type; /** * Parser @@ -75,10 +75,10 @@ class Parser * * @api * - * @param string $sourceName - * @param integer $sourceIndex - * @param string $encoding - * @param \Leafo\ScssPhp\Cache $cache + * @param string $sourceName + * @param integer $sourceIndex + * @param string $encoding + * @param \ScssPhp\ScssPhp\Cache $cache */ public function __construct($sourceName, $sourceIndex = 0, $encoding = 'utf-8', $cache = null) { @@ -126,13 +126,15 @@ public function getSourceName() * * @param string $msg * - * @throws \Leafo\ScssPhp\Exception\ParserException + * @throws \ScssPhp\ScssPhp\Exception\ParserException */ public function throwParseError($msg = 'parse error') { - list($line, /* $column */) = $this->getSourcePosition($this->count); + list($line, $column) = $this->getSourcePosition($this->count); - $loc = empty($this->sourceName) ? "line: $line" : "$this->sourceName on line $line"; + $loc = empty($this->sourceName) + ? "line: $line, column: $column" + : "$this->sourceName on line $line, at column $column"; if ($this->peek("(.*?)(\n|$)", $m, $this->count)) { throw new ParserException("$msg: failed at `$m[1]` $loc"); @@ -148,7 +150,7 @@ public function throwParseError($msg = 'parse error') * * @param string $buffer * - * @return \Leafo\ScssPhp\Block + * @return \ScssPhp\ScssPhp\Block */ public function parse($buffer) { @@ -200,8 +202,6 @@ public function parse($buffer) array_unshift($this->env->children, $this->charset); } - $this->env->isRoot = true; - $this->restoreEncoding(); if ($this->cache) { @@ -662,9 +662,14 @@ protected function parseChunk() } // opening css block - if ($this->selectors($selectors) && $this->matchChar('{')) { + if ($this->selectors($selectors) && $this->matchChar('{', false)) { $this->pushBlock($selectors, $s); + if ($this->eatWhiteDefault) { + $this->whitespace(); + $this->append(null); // collect comments at the begining if needed + } + return true; } @@ -675,6 +680,10 @@ protected function parseChunk() $foundSomething = false; if ($this->valueList($value)) { + if (empty($this->env->parent)) { + $this->throwParseError('expected "{"'); + } + $this->append([Type::T_ASSIGN, $name, $value], $s); $foundSomething = true; } @@ -727,7 +736,7 @@ protected function parseChunk() * @param array $selectors * @param integer $pos * - * @return \Leafo\ScssPhp\Block + * @return \ScssPhp\ScssPhp\Block */ protected function pushBlock($selectors, $pos = 0) { @@ -764,7 +773,7 @@ protected function pushBlock($selectors, $pos = 0) * @param string $type * @param integer $pos * - * @return \Leafo\ScssPhp\Block + * @return \ScssPhp\ScssPhp\Block */ protected function pushSpecialBlock($type, $pos) { @@ -777,7 +786,7 @@ protected function pushSpecialBlock($type, $pos) /** * Pop scope and return last block * - * @return \Leafo\ScssPhp\Block + * @return \ScssPhp\ScssPhp\Block * * @throws \Exception */ @@ -976,12 +985,57 @@ protected function whitespace() while (preg_match(static::$whitePattern, $this->buffer, $m, null, $this->count)) { if (isset($m[1]) && empty($this->commentsSeen[$this->count])) { - $this->appendComment([Type::T_COMMENT, $m[1]]); + // comment that are kept in the output CSS + $comment = []; + $endCommentCount = $this->count + strlen($m[1]); + + // find interpolations in comment + $p = strpos($this->buffer, '#{', $this->count); + + while ($p !== false && $p < $endCommentCount) { + $c = substr($this->buffer, $this->count, $p - $this->count); + $comment[] = $c; + $this->count = $p; + $out = null; + + if ($this->interpolation($out)) { + // keep right spaces in the following string part + if ($out[3]) { + while ($this->buffer[$this->count-1] !== '}') { + $this->count--; + } + + $out[3] = ''; + } + + $comment[] = $out; + } else { + $comment[] = substr($this->buffer, $this->count, 2); + + $this->count += 2; + } + + $p = strpos($this->buffer, '#{', $this->count); + } + + // remaining part + $c = substr($this->buffer, $this->count, $endCommentCount - $this->count); + + if (! $comment) { + // single part static comment + $this->appendComment([Type::T_COMMENT, $c]); + } else { + $comment[] = $c; + $this->appendComment([Type::T_COMMENT, [Type::T_STRING, '', $comment]]); + } $this->commentsSeen[$this->count] = true; + $this->count = $endCommentCount; + } else { + // comment that are ignored and not kept in the output css + $this->count += strlen($m[0]); } - $this->count += strlen($m[0]); $gotWhite = true; } @@ -995,7 +1049,9 @@ protected function whitespace() */ protected function appendComment($comment) { - $comment[1] = substr(preg_replace(['/^\s+/m', '/^(.)/m'], ['', ' \1'], $comment[1]), 1); + if ($comment[0] === Type::T_COMMENT && is_string($comment[1])) { + $comment[1] = substr(preg_replace(['/^\s+/m', '/^(.)/m'], ['', ' \1'], $comment[1]), 1); + } $this->env->comments[] = $comment; } @@ -1008,15 +1064,17 @@ protected function appendComment($comment) */ protected function append($statement, $pos = null) { - if ($pos !== null) { - list($line, $column) = $this->getSourcePosition($pos); + if (! is_null($statement)) { + if ($pos !== null) { + list($line, $column) = $this->getSourcePosition($pos); - $statement[static::SOURCE_LINE] = $line; - $statement[static::SOURCE_COLUMN] = $column; - $statement[static::SOURCE_INDEX] = $this->sourceIndex; - } + $statement[static::SOURCE_LINE] = $line; + $statement[static::SOURCE_COLUMN] = $column; + $statement[static::SOURCE_INDEX] = $this->sourceIndex; + } - $this->env->children[] = $statement; + $this->env->children[] = $statement; + } $comments = $this->env->comments; @@ -1409,6 +1467,19 @@ protected function value(&$out) $this->seek($s); + if ($this->literal('url(', 4, false) && $this->match('\s*(\/\/\S+)\s*', $m)) { + $content = 'url(' . $m[1]; + + if ($this->matchChar(')')) { + $content .= ')'; + $out = [Type::T_KEYWORD, $content]; + + return true; + } + } + + $this->seek($s); + // not if ($char === 'n' && $this->literal('not', 3, false)) { if ($this->whitespace() && $this->value($inner)) { @@ -1489,6 +1560,12 @@ protected function value(&$out) return true; } + // unicode range with wildcards + if ($this->literal('U+', 2) && $this->match('([0-9A-F]+\?*)(-([0-9A-F]+))?', $m, false)) { + $out = [Type::T_KEYWORD, 'U+' . $m[0]]; + return true; + } + if ($this->keyword($keyword, false)) { if ($this->func($keyword, $out)) { return true; @@ -1901,6 +1978,11 @@ protected function string(&$out) $content[] = $m[2] . "'"; } elseif ($this->literal("\\", 1, false)) { $content[] = $m[2] . "\\"; + } elseif ($this->literal("\r\n", 2, false) + || $this->matchChar("\r", false) + || $this->matchChar("\n", false) + || $this->matchChar("\f", false)) { + // this is a continuation escaping, to be ignored } else { $content[] = $m[2]; } @@ -2460,7 +2542,7 @@ protected function keyword(&$word, $eatWhitespace = null) { if ($this->match( $this->utf8 - ? '(([\pL\w_\-\*!"\']|[\\\\].)([\pL\w\-_"\']|[\\\\].)*)' + ? '(([\pL\w\x{00A0}-\x{10FFFF}_\-\*!"\']|[\\\\].)([\pL\w\x{00A0}-\x{10FFFF}\-_"\']|[\\\\].)*)' : '(([\w_\-\*!"\']|[\\\\].)([\w\-_"\']|[\\\\].)*)', $m, $eatWhitespace diff --git a/lib/scssphp/SourceMap/Base64.php b/lib/scssphp/SourceMap/Base64.php index 54015bb9164a6..93c6c1b47f46f 100644 --- a/lib/scssphp/SourceMap/Base64.php +++ b/lib/scssphp/SourceMap/Base64.php @@ -2,14 +2,14 @@ /** * SCSSPHP * - * @copyright 2012-2015 Leaf Corcoran + * @copyright 2012-2019 Leaf Corcoran * * @license http://opensource.org/licenses/MIT MIT * - * @link http://leafo.github.io/scssphp + * @link http://scssphp.github.io/scssphp */ -namespace Leafo\ScssPhp\SourceMap; +namespace ScssPhp\ScssPhp\SourceMap; /** * Base 64 Encode/Decode diff --git a/lib/scssphp/SourceMap/Base64VLQ.php b/lib/scssphp/SourceMap/Base64VLQ.php index 6de3b5ee06e62..d6f6452b5c525 100644 --- a/lib/scssphp/SourceMap/Base64VLQ.php +++ b/lib/scssphp/SourceMap/Base64VLQ.php @@ -2,16 +2,16 @@ /** * SCSSPHP * - * @copyright 2012-2015 Leaf Corcoran + * @copyright 2012-2019 Leaf Corcoran * * @license http://opensource.org/licenses/MIT MIT * - * @link http://leafo.github.io/scssphp + * @link http://scssphp.github.io/scssphp */ -namespace Leafo\ScssPhp\SourceMap; +namespace ScssPhp\ScssPhp\SourceMap; -use Leafo\ScssPhp\SourceMap\Base64; +use ScssPhp\ScssPhp\SourceMap\Base64; /** * Base 64 VLQ diff --git a/lib/scssphp/SourceMap/Base64VLQEncoder.php b/lib/scssphp/SourceMap/Base64VLQEncoder.php index caf56c7716e85..365b4d9304211 100644 --- a/lib/scssphp/SourceMap/Base64VLQEncoder.php +++ b/lib/scssphp/SourceMap/Base64VLQEncoder.php @@ -2,14 +2,14 @@ /** * SCSSPHP * - * @copyright 2012-2018 Leaf Corcoran + * @copyright 2012-2019 Leaf Corcoran * * @license http://opensource.org/licenses/MIT MIT * - * @link http://leafo.github.io/scssphp + * @link http://scssphp.github.io/scssphp */ -namespace Leafo\ScssPhp\SourceMap; +namespace ScssPhp\ScssPhp\SourceMap; /** * Base64 VLQ Encoder diff --git a/lib/scssphp/SourceMap/SourceMapGenerator.php b/lib/scssphp/SourceMap/SourceMapGenerator.php index fb11a0bfa1951..d0231b49d35c8 100644 --- a/lib/scssphp/SourceMap/SourceMapGenerator.php +++ b/lib/scssphp/SourceMap/SourceMapGenerator.php @@ -2,16 +2,16 @@ /** * SCSSPHP * - * @copyright 2012-2018 Leaf Corcoran + * @copyright 2012-2019 Leaf Corcoran * * @license http://opensource.org/licenses/MIT MIT * - * @link http://leafo.github.io/scssphp + * @link http://scssphp.github.io/scssphp */ -namespace Leafo\ScssPhp\SourceMap; +namespace ScssPhp\ScssPhp\SourceMap; -use Leafo\ScssPhp\Exception\CompilerException; +use ScssPhp\ScssPhp\Exception\CompilerException; /** * Source Map Generator @@ -61,7 +61,7 @@ class SourceMapGenerator /** * The base64 VLQ encoder * - * @var \Leafo\ScssPhp\SourceMap\Base64VLQ + * @var \ScssPhp\ScssPhp\SourceMap\Base64VLQ */ protected $encoder; @@ -127,7 +127,7 @@ public function addMapping($generatedLine, $generatedColumn, $originalLine, $ori * * @return string * - * @throws \Leafo\ScssPhp\Exception\CompilerException If the file could not be saved + * @throws \ScssPhp\ScssPhp\Exception\CompilerException If the file could not be saved */ public function saveMap($content) { diff --git a/lib/scssphp/Type.php b/lib/scssphp/Type.php index e84c47e4032f5..a12da72f2bbe5 100644 --- a/lib/scssphp/Type.php +++ b/lib/scssphp/Type.php @@ -2,14 +2,14 @@ /** * SCSSPHP * - * @copyright 2012-2018 Leaf Corcoran + * @copyright 2012-2019 Leaf Corcoran * * @license http://opensource.org/licenses/MIT MIT * - * @link http://leafo.github.io/scssphp + * @link http://scssphp.github.io/scssphp */ -namespace Leafo\ScssPhp; +namespace ScssPhp\ScssPhp; /** * Block/node types diff --git a/lib/scssphp/Util.php b/lib/scssphp/Util.php index a1e50658876bb..b0b76fdb42eaa 100644 --- a/lib/scssphp/Util.php +++ b/lib/scssphp/Util.php @@ -2,17 +2,17 @@ /** * SCSSPHP * - * @copyright 2012-2018 Leaf Corcoran + * @copyright 2012-2019 Leaf Corcoran * * @license http://opensource.org/licenses/MIT MIT * - * @link http://leafo.github.io/scssphp + * @link http://scssphp.github.io/scssphp */ -namespace Leafo\ScssPhp; +namespace ScssPhp\ScssPhp; -use Leafo\ScssPhp\Base\Range; -use Leafo\ScssPhp\Exception\RangeException; +use ScssPhp\ScssPhp\Base\Range; +use ScssPhp\ScssPhp\Exception\RangeException; /** * Utilty functions @@ -26,13 +26,13 @@ class Util * room for slight floating-point errors. * * @param string $name The name of the value. Used in the error message. - * @param \Leafo\ScssPhp\Base\Range $range Range of values. + * @param \ScssPhp\ScssPhp\Base\Range $range Range of values. * @param array $value The value to check. * @param string $unit The unit of the value. Used in error reporting. * * @return mixed `value` adjusted to fall within range, if it was outside by a floating-point margin. * - * @throws \Leafo\ScssPhp\Exception\RangeException + * @throws \ScssPhp\ScssPhp\Exception\RangeException */ public static function checkRange($name, Range $range, $value, $unit = '') { diff --git a/lib/scssphp/Version.php b/lib/scssphp/Version.php index 46ffedf2bff2b..56c7165efd5fa 100644 --- a/lib/scssphp/Version.php +++ b/lib/scssphp/Version.php @@ -2,14 +2,14 @@ /** * SCSSPHP * - * @copyright 2012-2018 Leaf Corcoran + * @copyright 2012-2019 Leaf Corcoran * * @license http://opensource.org/licenses/MIT MIT * - * @link http://leafo.github.io/scssphp + * @link http://scssphp.github.io/scssphp */ -namespace Leafo\ScssPhp; +namespace ScssPhp\ScssPhp; /** * SCSSPHP version @@ -18,5 +18,5 @@ */ class Version { - const VERSION = 'v0.8.3'; + const VERSION = 'v1.0.0'; } diff --git a/lib/scssphp/moodle_readme.txt b/lib/scssphp/moodle_readme.txt index 44fd815da8415..592a0663ca88a 100644 --- a/lib/scssphp/moodle_readme.txt +++ b/lib/scssphp/moodle_readme.txt @@ -1,7 +1,7 @@ scssphp ------- -Downloaded from: https://github.com/leafo/scssphp +Downloaded from: https://github.com/scssphp/scssphp Import procedure: diff --git a/lib/thirdpartylibs.xml b/lib/thirdpartylibs.xml index 1b19dd38947a6..0fd029e4119d4 100644 --- a/lib/thirdpartylibs.xml +++ b/lib/thirdpartylibs.xml @@ -222,7 +222,7 @@ scssphp scssphp MIT - 0.8.3 + 1.0.0 spout diff --git a/lib/upgrade.txt b/lib/upgrade.txt index 3c5e180c8d17a..a1b1003ecd6b5 100644 --- a/lib/upgrade.txt +++ b/lib/upgrade.txt @@ -14,6 +14,7 @@ information provided here is intended especially for developers. * allow_switch() * Remove duplicate font-awesome SCSS, Please see /theme/boost/scss/fontawesome for usage (MDL-65936) * Remove lib/pear/Crypt/CHAP.php (MDL-65747) +* Upgrade scssphp to v1.0.0, This involves renaming classes from Leafo => ScssPhp as the repo has changed. === 3.7 ===