From a7e0fb78df95e2a0ac2dbed8febc9d625cd221b9 Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Wed, 10 Jun 2015 12:32:37 -0400
Subject: [PATCH 001/534] fixes #88: add --line-numbers and --debug-info style
annotations
---
bin/pscss | 39 +-
site/docs/index.md | 50 +-
src/Compiler.php | 432 +++++-----
src/Formatter.php | 9 +
src/Formatter/Compressed.php | 14 +-
src/Formatter/Crunched.php | 14 +-
src/Formatter/Expanded.php | 20 +
src/Formatter/Nested.php | 10 +-
src/Parser.php | 8 +-
tests/FailingTest.php | 2 +-
tests/InputTest.php | 78 +-
tests/ScssTest.php | 2 +-
tests/outputs_numbered/builtins.css | 139 +++
tests/outputs_numbered/comments.css | 33 +
tests/outputs_numbered/compass_extract.css | 29 +
tests/outputs_numbered/content.css | 36 +
.../content_with_function.css | 3 +
tests/outputs_numbered/default_args.css | 4 +
tests/outputs_numbered/directives.css | 85 ++
tests/outputs_numbered/extends.css | 127 +++
tests/outputs_numbered/filter_effects.css | 21 +
tests/outputs_numbered/functions.css | 27 +
tests/outputs_numbered/ie7.css | 9 +
tests/outputs_numbered/if.css | 22 +
tests/outputs_numbered/if_on_null.css | 3 +
tests/outputs_numbered/import.css | 32 +
tests/outputs_numbered/interpolation.css | 64 ++
tests/outputs_numbered/keyword_args.css | 7 +
tests/outputs_numbered/list.css | 8 +
tests/outputs_numbered/looping.css | 61 ++
tests/outputs_numbered/map.css | 13 +
tests/outputs_numbered/media.css | 128 +++
tests/outputs_numbered/mixins.css | 106 +++
tests/outputs_numbered/nesting.css | 24 +
tests/outputs_numbered/null.css | 22 +
tests/outputs_numbered/operators.css | 169 ++++
tests/outputs_numbered/parsing_comments.css | 55 ++
.../outputs_numbered/placeholder_selector.css | 16 +
tests/outputs_numbered/scss_css.css | 788 ++++++++++++++++++
tests/outputs_numbered/selectors.css | 359 ++++++++
tests/outputs_numbered/shorthand.css | 29 +
tests/outputs_numbered/values.css | 35 +
tests/outputs_numbered/variables.css | 33 +
43 files changed, 2939 insertions(+), 226 deletions(-)
create mode 100644 tests/outputs_numbered/builtins.css
create mode 100644 tests/outputs_numbered/comments.css
create mode 100644 tests/outputs_numbered/compass_extract.css
create mode 100644 tests/outputs_numbered/content.css
create mode 100644 tests/outputs_numbered/content_with_function.css
create mode 100644 tests/outputs_numbered/default_args.css
create mode 100644 tests/outputs_numbered/directives.css
create mode 100644 tests/outputs_numbered/extends.css
create mode 100644 tests/outputs_numbered/filter_effects.css
create mode 100644 tests/outputs_numbered/functions.css
create mode 100644 tests/outputs_numbered/ie7.css
create mode 100644 tests/outputs_numbered/if.css
create mode 100644 tests/outputs_numbered/if_on_null.css
create mode 100644 tests/outputs_numbered/import.css
create mode 100644 tests/outputs_numbered/interpolation.css
create mode 100644 tests/outputs_numbered/keyword_args.css
create mode 100644 tests/outputs_numbered/list.css
create mode 100644 tests/outputs_numbered/looping.css
create mode 100644 tests/outputs_numbered/map.css
create mode 100644 tests/outputs_numbered/media.css
create mode 100644 tests/outputs_numbered/mixins.css
create mode 100644 tests/outputs_numbered/nesting.css
create mode 100644 tests/outputs_numbered/null.css
create mode 100644 tests/outputs_numbered/operators.css
create mode 100644 tests/outputs_numbered/parsing_comments.css
create mode 100644 tests/outputs_numbered/placeholder_selector.css
create mode 100644 tests/outputs_numbered/scss_css.css
create mode 100644 tests/outputs_numbered/selectors.css
create mode 100644 tests/outputs_numbered/shorthand.css
create mode 100644 tests/outputs_numbered/values.css
create mode 100644 tests/outputs_numbered/variables.css
diff --git a/bin/pscss b/bin/pscss
index bcdf3378..10328d7b 100755
--- a/bin/pscss
+++ b/bin/pscss
@@ -28,6 +28,8 @@ $precision = null;
$dumpTree = false;
$inputFile = null;
$changeDir = false;
+$debugInfo = false;
+$lineNumbers = false;
function parseArgument($argument, $options) {
if (preg_match('/^(?:' . implode('|', (array) $options) . ')=?(.*)/', $argument, $matches)) {
@@ -44,9 +46,11 @@ Usage: $exe [options] [input-file]
Options include:
+ --debug-info Annotate selectors with CSS referring to the source file and line number
-h, --help Show this message
-f=format Set the output format (compact, compressed, crunched, expanded, or nested)
-i=path Set import path
+ --line-numbers Annotate selectors with comments referring to the source file and line number
-p=precision Set decimal number precision (default 5)
-T Dump formatted parse tree
-v, --version Print the version
@@ -55,13 +59,23 @@ EOT;
exit($HELP);
}
- if ($argv[$i] === '-T') {
- $dumpTree = true;
+ if ($argv[$i] === '-v' || $argv[$i] === '--version') {
+ exit(Version::VERSION . "\n");
+ }
+
+ if ($argv[$i] === '--debug-info') {
+ $debugInfo = true;
continue;
}
- if ($argv[$i] === '-v' || $argv[$i] === '--version') {
- exit(Version::VERSION . "\n");
+ if ($argv[$i] === '--line-numbers' || $argv[$i] === '--line-comments') {
+ $lineNumbers = true;
+ continue;
+ }
+
+ if ($argv[$i] === '-T') {
+ $dumpTree = true;
+ continue;
}
$value = parseArgument($argv[$i], array('-f', '--style'));
@@ -100,6 +114,7 @@ if ($inputFile) {
if ($oldWorkingDir !== $newWorkingDir) {
$changeDir = chdir($newWorkingDir);
+ $inputFile = basename($inputFile);
}
} else {
$data = '';
@@ -119,18 +134,26 @@ if ($dumpTree) {
$scss = new Compiler();
-if ($loadPaths) {
- $scss->setImportPaths(explode(PATH_SEPARATOR, $loadPaths));
+if ($debugInfo && $inputFile) {
+ $scss->setLineNumberStyle(Compiler::DEBUG_INFO);
}
-if ($style) {
- $scss->setFormatter('Leafo\\ScssPhp\\Formatter\\' . ucfirst($style));
+if ($lineNumbers && $inputFile) {
+ $scss->setLineNumberStyle(Compiler::LINE_COMMENTS);
+}
+
+if ($loadPaths) {
+ $scss->setImportPaths(explode(PATH_SEPARATOR, $loadPaths));
}
if ($precision) {
$scss->setNumberPrecision($precision);
}
+if ($style) {
+ $scss->setFormatter('Leafo\\ScssPhp\\Formatter\\' . ucfirst($style));
+}
+
echo $scss->compile($data, $inputFile ?: 'STDIN');
if ($changeDir) {
diff --git a/site/docs/index.md b/site/docs/index.md
index 29644a35..66a5a42b 100644
--- a/site/docs/index.md
+++ b/site/docs/index.md
@@ -27,8 +27,6 @@ options, then run the compiler with the `compile` method.
```php
setLineNumberStyle(Compiler::LINE_COMMENTS)` after creating a new instance of class `Compiler`.
+
+ ```php
+ use Leafo\ScssPhp\Server;
+ use Leafo\ScssPhp\Compiler;
+
+ $directory = 'css';
+
+ $scss = new Compiler();
+ $scss->setLineNumberStyle(Compiler::LINE_COMMENTS);
+
+ $server = new Server($directory, null, $scss);
+ $server->serve();
+ ```
+
+You can also call the `compile` method directly (without using an instance of `Server` like above)
+
+ ```php
+ use Leafo\ScssPhp\Server;
+ use Leafo\ScssPhp\Compiler;
+
+ $scss = new Compiler();
+ $scss->setLineNumberStyle(Compiler::LINE_COMMENTS);
+
+ echo $scss->compile('
+ $color: #abc;
+ div { color: lighten($color, 20%); }
+ ');
+ ```
+
### Custom Functions
It's possible to register custom functions written in PHP that can be called
@@ -266,8 +296,6 @@ For example, create a file `style.php`:
'add',
'-' => 'sub',
@@ -98,6 +101,7 @@ class Compiler
protected $registeredVars = array();
protected $numberPrecision = 5;
+ protected $lineNumberStyle = null;
protected $formatter = 'Leafo\ScssPhp\Formatter\Nested';
@@ -467,9 +471,33 @@ protected function compileBlock($block)
array_map(array($this, 'evalSelector'), $block->selectors);
$out = $this->makeOutputBlock(null, $this->multiplySelectors($env));
+
+ if (isset($this->lineNumberStyle) && count($env->selectors) && count($block->children)) {
+ $annotation = $this->makeOutputBlock('comment');
+ $annotation->depth = 0;
+
+ $file = $block->sourceParser->getSourceName();
+ $line = $block->sourceParser->getLineNo($block->sourcePosition);
+
+ switch ($this->lineNumberStyle) {
+ case self::LINE_COMMENTS:
+ $annotation->lines[] = '/* line ' . $line . ', ' . $file . ' */';
+ break;
+ case self::DEBUG_INFO:
+ $annotation->lines[] = '@media -sass-debug-info{filename{font-family:"' . $file
+ . '"}line{font-family:' . $line . '}}';
+ break;
+ }
+
+ $this->scope->children[] = $annotation;
+ }
+
$this->scope->children[] = $out;
+
$this->compileChildren($block->children, $out);
+ $this->formatter->stripSemicolon($out->lines);
+
$this->popEnv();
}
@@ -1273,6 +1301,11 @@ protected function reduce($value, $inExp = false)
}
}
+ protected function normalizeName($name)
+ {
+ return str_replace('-', '_', $name);
+ }
+
public function normalizeValue($value)
{
$value = $this->coerceForExpression($this->reduce($value));
@@ -1314,18 +1347,6 @@ protected function normalizeNumber($number)
return $number;
}
- // $number should be normalized
- protected function coerceUnit($number, $unit)
- {
- list(, $value, $baseUnit) = $number;
-
- if (isset(self::$unitTable[$baseUnit][$unit])) {
- $value = $value * self::$unitTable[$baseUnit][$unit];
- }
-
- return array('number', $value, $unit);
- }
-
protected function opAddNumberNumber($left, $right)
{
return array('number', $left[1] + $right[1], $left[2]);
@@ -1779,150 +1800,6 @@ protected function multiplyMedia($env, $childQueries = null)
return $this->multiplyMedia($env->parent, $childQueries);
}
- /**
- * Coerce something to map
- *
- * @param array $item
- *
- * @return array
- */
- protected function coerceMap($item)
- {
- if ($item[0] === 'map') {
- return $item;
- }
-
- if ($item == self::$emptyList) {
- return self::$emptyMap;
- }
-
- return array('map', array($item), array(self::$null));
- }
-
- /**
- * Coerce something to list
- *
- * @param array $item
- *
- * @return array
- */
- protected function coerceList($item, $delim = ',')
- {
- if (isset($item) && $item[0] == 'list') {
- return $item;
- }
-
- if (isset($item) && $item[0] == 'map') {
- $keys = $item[1];
- $values = $item[2];
- $list = array();
-
- for ($i = 0, $s = count($keys); $i < $s; $i++) {
- $key = $keys[$i];
- $value = $values[$i];
-
- $list[] = array('list', '', array(array('keyword', $this->compileValue($key)), $value));
- }
-
- return array('list', ',', $list);
- }
-
- return array('list', $delim, ! isset($item) ? array(): array($item));
- }
-
- protected function applyArguments($argDef, $argValues)
- {
- $storeEnv = $this->getStoreEnv();
-
- $env = new \stdClass;
- $env->store = $storeEnv->store;
-
- $hasVariable = false;
- $args = array();
-
- foreach ($argDef as $i => $arg) {
- list($name, $default, $isVariable) = $argDef[$i];
-
- $args[$name] = array($i, $name, $default, $isVariable);
- $hasVariable |= $isVariable;
- }
-
- $keywordArgs = array();
- $deferredKeywordArgs = array();
- $remaining = array();
-
- // assign the keyword args
- foreach ((array) $argValues as $arg) {
- if (! empty($arg[0])) {
- if (! isset($args[$arg[0][1]])) {
- if ($hasVariable) {
- $deferredKeywordArgs[$arg[0][1]] = $arg[1];
- } else {
- $this->throwError("Mixin or function doesn't have an argument named $%s.", $arg[0][1]);
- }
- } elseif ($args[$arg[0][1]][0] < count($remaining)) {
- $this->throwError("The argument $%s was passed both by position and by name.", $arg[0][1]);
- } else {
- $keywordArgs[$arg[0][1]] = $arg[1];
- }
- } elseif (count($keywordArgs)) {
- $this->throwError('Positional arguments must come before keyword arguments.');
- } elseif ($arg[2] == true) {
- $val = $this->reduce($arg[1], true);
-
- if ($val[0] == 'list') {
- foreach ($val[2] as $name => $item) {
- if (! is_numeric($name)) {
- $keywordArgs[$name] = $item;
- } else {
- $remaining[] = $item;
- }
- }
- } else {
- $remaining[] = $val;
- }
- } else {
- $remaining[] = $arg[1];
- }
- }
-
- foreach ($args as $arg) {
- list($i, $name, $default, $isVariable) = $arg;
-
- if ($isVariable) {
- $val = array('list', ',', array());
- for ($count = count($remaining); $i < $count; $i++) {
- $val[2][] = $remaining[$i];
- }
- foreach ($deferredKeywordArgs as $itemName => $item) {
- $val[2][$itemName] = $item;
- }
- } elseif (isset($remaining[$i])) {
- $val = $remaining[$i];
- } elseif (isset($keywordArgs[$name])) {
- $val = $keywordArgs[$name];
- } elseif (! empty($default)) {
- continue;
- } else {
- $this->throwError("Missing argument $name");
- }
-
- $this->set($name, $this->reduce($val, true), true, $env);
- }
-
- $storeEnv->store = $env->store;
-
- foreach ($args as $arg) {
- list($i, $name, $default, $isVariable) = $arg;
-
- if ($isVariable || isset($remaining[$i]) || isset($keywordArgs[$name]) || empty($default)) {
- continue;
- }
-
- $this->set($name, $this->reduce($default, true), true);
- }
- }
-
protected function pushEnv($block = null)
{
$env = new \stdClass;
@@ -1936,9 +1813,12 @@ protected function pushEnv($block = null)
return $env;
}
- protected function normalizeName($name)
+ protected function popEnv()
{
- return str_replace('-', '_', $name);
+ $env = $this->env;
+ $this->env = $this->env->parent;
+
+ return $env;
}
protected function getStoreEnv()
@@ -2050,14 +1930,6 @@ public function unsetVariable($name)
unset($this->registeredVars[$name]);
}
- protected function popEnv()
- {
- $env = $this->env;
- $this->env = $this->env->parent;
-
- return $env;
- }
-
public function getParsedFiles()
{
return $this->parsedFiles;
@@ -2085,6 +1957,11 @@ public function setFormatter($formatterName)
$this->formatter = $formatterName;
}
+ public function setLineNumberStyle($lineNumberStyle)
+ {
+ $this->lineNumberStyle = $lineNumberStyle;
+ }
+
public function registerFunction($name, $func)
{
$this->userFunctions[$this->normalizeName($name)] = $func;
@@ -2099,6 +1976,7 @@ protected function importFile($path, $out)
{
// see if tree is cached
$realPath = realpath($path);
+
if (isset($this->importCache[$realPath])) {
$tree = $this->importCache[$realPath];
} else {
@@ -2154,6 +2032,33 @@ public function findImport($url)
return null;
}
+ /**
+ * Throw error (exception)
+ *
+ * @param string $msg Message with optional sprintf()-style vararg parameters
+ *
+ * @throws \Exception
+ */
+ public function throwError($msg)
+ {
+ if (func_num_args() > 1) {
+ $msg = call_user_func_array('sprintf', func_get_args());
+ }
+
+ if ($this->sourcePos >= 0 && isset($this->sourceParser)) {
+ $this->sourceParser->throwParseError($msg, $this->sourcePos);
+ }
+
+ throw new \Exception($msg);
+ }
+
+ /**
+ * Does file exist?
+ *
+ * @param string $name
+ *
+ * @return boolean
+ */
protected function fileExists($name)
{
return is_file($name);
@@ -2282,6 +2187,162 @@ protected function sortArgs($prototype, $args)
return $finalArgs;
}
+ protected function applyArguments($argDef, $argValues)
+ {
+ $storeEnv = $this->getStoreEnv();
+
+ $env = new \stdClass;
+ $env->store = $storeEnv->store;
+
+ $hasVariable = false;
+ $args = array();
+
+ foreach ($argDef as $i => $arg) {
+ list($name, $default, $isVariable) = $argDef[$i];
+
+ $args[$name] = array($i, $name, $default, $isVariable);
+ $hasVariable |= $isVariable;
+ }
+
+ $keywordArgs = array();
+ $deferredKeywordArgs = array();
+ $remaining = array();
+
+ // assign the keyword args
+ foreach ((array) $argValues as $arg) {
+ if (! empty($arg[0])) {
+ if (! isset($args[$arg[0][1]])) {
+ if ($hasVariable) {
+ $deferredKeywordArgs[$arg[0][1]] = $arg[1];
+ } else {
+ $this->throwError("Mixin or function doesn't have an argument named $%s.", $arg[0][1]);
+ }
+ } elseif ($args[$arg[0][1]][0] < count($remaining)) {
+ $this->throwError("The argument $%s was passed both by position and by name.", $arg[0][1]);
+ } else {
+ $keywordArgs[$arg[0][1]] = $arg[1];
+ }
+ } elseif (count($keywordArgs)) {
+ $this->throwError('Positional arguments must come before keyword arguments.');
+ } elseif ($arg[2] == true) {
+ $val = $this->reduce($arg[1], true);
+
+ if ($val[0] == 'list') {
+ foreach ($val[2] as $name => $item) {
+ if (! is_numeric($name)) {
+ $keywordArgs[$name] = $item;
+ } else {
+ $remaining[] = $item;
+ }
+ }
+ } else {
+ $remaining[] = $val;
+ }
+ } else {
+ $remaining[] = $arg[1];
+ }
+ }
+
+ foreach ($args as $arg) {
+ list($i, $name, $default, $isVariable) = $arg;
+
+ if ($isVariable) {
+ $val = array('list', ',', array());
+ for ($count = count($remaining); $i < $count; $i++) {
+ $val[2][] = $remaining[$i];
+ }
+ foreach ($deferredKeywordArgs as $itemName => $item) {
+ $val[2][$itemName] = $item;
+ }
+ } elseif (isset($remaining[$i])) {
+ $val = $remaining[$i];
+ } elseif (isset($keywordArgs[$name])) {
+ $val = $keywordArgs[$name];
+ } elseif (! empty($default)) {
+ continue;
+ } else {
+ $this->throwError("Missing argument $name");
+ }
+
+ $this->set($name, $this->reduce($val, true), true, $env);
+ }
+
+ $storeEnv->store = $env->store;
+
+ foreach ($args as $arg) {
+ list($i, $name, $default, $isVariable) = $arg;
+
+ if ($isVariable || isset($remaining[$i]) || isset($keywordArgs[$name]) || empty($default)) {
+ continue;
+ }
+
+ $this->set($name, $this->reduce($default, true), true);
+ }
+ }
+
+ // $number should be normalized
+ protected function coerceUnit($number, $unit)
+ {
+ list(, $value, $baseUnit) = $number;
+
+ if (isset(self::$unitTable[$baseUnit][$unit])) {
+ $value = $value * self::$unitTable[$baseUnit][$unit];
+ }
+
+ return array('number', $value, $unit);
+ }
+
+ /**
+ * Coerce something to map
+ *
+ * @param array $item
+ *
+ * @return array
+ */
+ protected function coerceMap($item)
+ {
+ if ($item[0] === 'map') {
+ return $item;
+ }
+
+ if ($item == self::$emptyList) {
+ return self::$emptyMap;
+ }
+
+ return array('map', array($item), array(self::$null));
+ }
+
+ /**
+ * Coerce something to list
+ *
+ * @param array $item
+ *
+ * @return array
+ */
+ protected function coerceList($item, $delim = ',')
+ {
+ if (isset($item) && $item[0] == 'list') {
+ return $item;
+ }
+
+ if (isset($item) && $item[0] == 'map') {
+ $keys = $item[1];
+ $values = $item[2];
+ $list = array();
+
+ for ($i = 0, $s = count($keys); $i < $s; $i++) {
+ $key = $keys[$i];
+ $value = $values[$i];
+
+ $list[] = array('list', '', array(array('keyword', $this->compileValue($key)), $value));
+ }
+
+ return array('list', ',', $list);
+ }
+
+ return array('list', $delim, ! isset($item) ? array(): array($item));
+ }
+
protected function coerceForExpression($value)
{
if ($color = $this->coerceColor($value)) {
@@ -2325,6 +2386,19 @@ protected function coerceString($value)
return null;
}
+ protected function coercePercent($value)
+ {
+ if ($value[0] == 'number') {
+ if ($value[2] == '%') {
+ return $value[1] / 100;
+ }
+
+ return $value[1];
+ }
+
+ return 0;
+ }
+
public function assertMap($value)
{
$value = $this->coerceMap($value);
@@ -2363,19 +2437,6 @@ public function assertNumber($value)
return $value[1];
}
- protected function coercePercent($value)
- {
- if ($value[0] == 'number') {
- if ($value[2] == '%') {
- return $value[1] / 100;
- }
-
- return $value[1];
- }
-
- return 0;
- }
-
// make sure a color's components don't go out of bounds
protected function fixColor($c)
{
@@ -3423,17 +3484,4 @@ protected function libUniqueId()
return array('string', '', array('u' . str_pad(base_convert($id, 10, 36), 8, '0', STR_PAD_LEFT)));
}
-
- public function throwError($msg = null)
- {
- if (func_num_args() > 1) {
- $msg = call_user_func_array('sprintf', func_get_args());
- }
-
- if ($this->sourcePos >= 0 && isset($this->sourceParser)) {
- $this->sourceParser->throwParseError($msg, $this->sourcePos);
- }
-
- throw new \Exception($msg);
- }
}
diff --git a/src/Formatter.php b/src/Formatter.php
index 60e5c661..05c04b07 100644
--- a/src/Formatter.php
+++ b/src/Formatter.php
@@ -78,6 +78,15 @@ public function property($name, $value)
return $name . $this->assignSeparator . $value . ';';
}
+ /**
+ * Strip semi-colon appended by property(); it's a separator, not a terminator
+ *
+ * @param array $lines
+ */
+ public function stripSemicolon(&$lines)
+ {
+ }
+
/**
* Output lines inside a block
*
diff --git a/src/Formatter/Compressed.php b/src/Formatter/Compressed.php
index 3cddc63d..b40161b4 100644
--- a/src/Formatter/Compressed.php
+++ b/src/Formatter/Compressed.php
@@ -42,6 +42,18 @@ public function indentStr($n = 0)
return '';
}
+ /**
+ * {@inheritdoc}
+ */
+ public function stripSemicolon(&$lines)
+ {
+ if (($count = count($lines))
+ && substr($lines[$count - 1], -1) === ';'
+ ) {
+ $lines[$count - 1] = substr($lines[$count - 1], 0, -1);
+ }
+ }
+
/**
* {@inheritdoc}
*/
@@ -59,7 +71,7 @@ public function blockLines($inner, $block)
echo $inner . implode($glue, $block->lines);
- if (!empty($block->children)) {
+ if (! empty($block->children)) {
echo $this->break;
}
}
diff --git a/src/Formatter/Crunched.php b/src/Formatter/Crunched.php
index 09e2184c..c8170291 100644
--- a/src/Formatter/Crunched.php
+++ b/src/Formatter/Crunched.php
@@ -42,6 +42,18 @@ public function indentStr($n = 0)
return '';
}
+ /**
+ * {@inheritdoc}
+ */
+ public function stripSemicolon(&$lines)
+ {
+ if (($count = count($lines))
+ && substr($lines[$count - 1], -1) === ';'
+ ) {
+ $lines[$count - 1] = substr($lines[$count - 1], 0, -1);
+ }
+ }
+
/**
* {@inheritdoc}
*/
@@ -57,7 +69,7 @@ public function blockLines($inner, $block)
echo $inner . implode($glue, $block->lines);
- if (!empty($block->children)) {
+ if (! empty($block->children)) {
echo $this->break;
}
}
diff --git a/src/Formatter/Expanded.php b/src/Formatter/Expanded.php
index 7bb27576..a8fafc95 100644
--- a/src/Formatter/Expanded.php
+++ b/src/Formatter/Expanded.php
@@ -33,4 +33,24 @@ public function __construct()
$this->tagSeparator = ', ';
$this->assignSeparator = ': ';
}
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function blockLines($inner, $block)
+ {
+ $glue = $this->break . $inner;
+
+ foreach ($block->lines as $index => $line) {
+ if (substr($line, 0, 2) === '/*') {
+ $block->lines[$index] = preg_replace('/(\r|\n)+/', $glue, $line);
+ }
+ }
+
+ echo $inner . implode($glue, $block->lines);
+
+ if (empty($block->selectors) || ! empty($block->children)) {
+ echo $this->break;
+ }
+ }
}
diff --git a/src/Formatter/Nested.php b/src/Formatter/Nested.php
index 416bc2cf..084fa6bb 100644
--- a/src/Formatter/Nested.php
+++ b/src/Formatter/Nested.php
@@ -91,7 +91,7 @@ protected function blockLines($inner, $block)
echo $inner . implode($glue, $block->lines);
- if (!empty($block->children)) {
+ if (! empty($block->children)) {
echo $this->break;
}
}
@@ -106,7 +106,7 @@ protected function block($block)
}
$inner = $pre = $this->indentStr($block->depth - 1);
- if (!empty($block->selectors)) {
+ if (! empty($block->selectors)) {
echo $pre .
implode($this->tagSeparator, $block->selectors) .
$this->open . $this->break;
@@ -114,13 +114,13 @@ protected function block($block)
$inner = $this->indentStr($block->depth - 1);
}
- if (!empty($block->lines)) {
+ if (! empty($block->lines)) {
$this->blockLines($inner, $block);
}
foreach ($block->children as $i => $child) {
- // echo '*** block: ' . $block->depth . ' child: ' . $child->depth . "\n";
$this->block($child);
+
if ($i < count($block->children) - 1) {
echo $this->break;
@@ -133,7 +133,7 @@ protected function block($block)
}
}
- if (!empty($block->selectors)) {
+ if (! empty($block->selectors)) {
$this->indentLevel--;
echo $this->close;
}
diff --git a/src/Parser.php b/src/Parser.php
index fb1db351..5b357ea4 100644
--- a/src/Parser.php
+++ b/src/Parser.php
@@ -425,6 +425,12 @@ protected function parseChunk()
if (! isset($this->charset)) {
$statement = array('charset', $charset);
+ $statement[self::SOURCE_POSITION] = $s;
+
+ if (! $this->rootParser) {
+ $statement[self::SOURCE_PARSER] = $this;
+ }
+
$this->charset = $statement;
}
@@ -603,7 +609,7 @@ protected function literal($what, $eatWhitespace = null)
*
* @return \stdClass
*/
- protected function pushBlock($selectors, $pos = null)
+ protected function pushBlock($selectors, $pos = 0)
{
$b = new \stdClass;
$b->parent = $this->env; // not sure if we need this yet
diff --git a/tests/FailingTest.php b/tests/FailingTest.php
index 25552d9f..1343b5cc 100644
--- a/tests/FailingTest.php
+++ b/tests/FailingTest.php
@@ -52,7 +52,7 @@ public function testFailing($id, $scss, $expected)
$output = $this->compile($scss);
- $this->assertEquals($expected, $output, $id);
+ $this->assertEquals(rtrim($expected), rtrim($output), $id);
}
/**
diff --git a/tests/InputTest.php b/tests/InputTest.php
index ad5caba3..fa2b28cc 100644
--- a/tests/InputTest.php
+++ b/tests/InputTest.php
@@ -12,6 +12,7 @@
namespace Leafo\ScssPhp\Tests;
use Leafo\ScssPhp\Compiler;
+use Leafo\ScssPhp\LineCommentator;
function _dump($value)
{
@@ -32,11 +33,29 @@ class InputTest extends \PHPUnit_Framework_TestCase
{
protected static $inputDir = 'inputs';
protected static $outputDir = 'outputs';
+ protected static $outputNumberedDir = 'outputs_numbered';
- public function setUp()
+ private $saveDir;
+
+ /**
+ * {@inheritDoc}
+ */
+ protected function setUp()
{
$this->scss = new Compiler();
- $this->scss->addImportPath(__DIR__ . '/' . self::$inputDir);
+ $this->scss->addImportPath(self::$inputDir);
+
+ $this->saveDir = getcwd();
+
+ chdir(__DIR__);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ protected function tearDown()
+ {
+ chdir($this->saveDir);
}
/**
@@ -48,14 +67,37 @@ public function testInputFile($inFname, $outFname)
return $this->buildInput($inFname, $outFname);
}
- if (!is_readable($outFname)) {
+ if (! is_readable($outFname)) {
$this->fail("$outFname is missing, consider building tests with BUILD=1");
}
$input = file_get_contents($inFname);
$output = file_get_contents($outFname);
- $this->assertEquals($output, $this->scss->compile($input));
+ $this->assertEquals($output, $this->scss->compile($input, substr($inFname, strlen(__DIR__) + 1)));
+ }
+
+ /**
+ * Run all tests with line numbering
+ *
+ * @dataProvider numberedFileNameProvider
+ */
+ public function testLineNumbering($inFname, $outFname)
+ {
+ $this->scss->setLineNumberStyle(Compiler::LINE_COMMENTS);
+
+ if (getenv('BUILD')) {
+ return $this->buildInput($inFname, $outFname);
+ }
+
+ if (! is_readable($outFname)) {
+ $this->fail("$outFname is missing, consider building tests with BUILD=true");
+ }
+
+ $input = file_get_contents($inFname);
+ $output = file_get_contents($outFname);
+
+ $this->assertEquals($output, $this->scss->compile($input, substr($inFname, strlen(__DIR__) + 1)));
}
public function fileNameProvider()
@@ -68,10 +110,21 @@ function ($a) {
);
}
+ public function numberedFileNameProvider()
+ {
+ return array_map(
+ function ($a) {
+ return array($a, InputTest::outputNumberedNameFor($a));
+ },
+ self::findInputNames()
+ );
+ }
+
// only run when env is set
public function buildInput($inFname, $outFname)
{
- $css = $this->scss->compile(file_get_contents($inFname));
+ $css = $this->scss->compile(file_get_contents($inFname), substr($inFname, strlen(__DIR__) + 1));
+
file_put_contents($outFname, $css);
}
@@ -79,6 +132,7 @@ public static function findInputNames($pattern = '*')
{
$files = glob(__DIR__ . '/' . self::$inputDir . '/' . $pattern);
$files = array_filter($files, 'is_file');
+
if ($pattern = getenv('MATCH')) {
$files = array_filter($files, function ($fname) use ($pattern) {
return preg_match("/$pattern/", $fname);
@@ -95,7 +149,19 @@ public static function outputNameFor($input)
$in = _quote(self::$inputDir . '/');
$out = preg_replace("/$in/", self::$outputDir . '/', $out);
- $out = preg_replace("/.scss$/", '.css', $out);
+ $out = preg_replace('/.scss$/', '.css', $out);
+
+ return __DIR__ . '/' . $out;
+ }
+
+ public static function outputNumberedNameFor($input)
+ {
+ $front = _quote(__DIR__ . '/');
+ $out = preg_replace("/^$front/", '', $input);
+
+ $in = _quote(self::$inputDir . '/');
+ $out = preg_replace("/$in/", self::$outputNumberedDir . '/', $out);
+ $out = preg_replace('/.scss$/', '.css', $out);
return __DIR__ . '/' . $out;
}
diff --git a/tests/ScssTest.php b/tests/ScssTest.php
index f9b131df..e402511f 100644
--- a/tests/ScssTest.php
+++ b/tests/ScssTest.php
@@ -47,7 +47,7 @@ public function testTests($name, $scss, $css, $style)
$actual = $compiler->compile($scss);
- $this->assertEquals($css, $actual, $name);
+ $this->assertEquals(rtrim($css), rtrim($actual), $name);
// TODO: need to fix this in the formatters
//$this->assertEquals(trim($css), trim($actual), $name);
diff --git a/tests/outputs_numbered/builtins.css b/tests/outputs_numbered/builtins.css
new file mode 100644
index 00000000..e57b16e2
--- /dev/null
+++ b/tests/outputs_numbered/builtins.css
@@ -0,0 +1,139 @@
+/* line 2, inputs/builtins.scss */
+#color {
+ color: #22ea18;
+ red: 34;
+ green: 234;
+ blue: 24;
+ color: rgba(1, 2, 4, 0.5);
+ a1: 1;
+ a2: 0.5;
+ mix: #020304;
+ rgba: rgba(170, 119, 204, 0.4);
+ rgba: rgba(170, 119, 204, 0.4);
+ green: 139; }
+/* line 21, inputs/builtins.scss */
+#hsl {
+ color: #79c653;
+ color: rgba(121, 198, 83, 0.5);
+ hue: 100deg;
+ sat: 50%;
+ lig: 55%; }
+/* line 30, inputs/builtins.scss */
+#more-color {
+ light: #7e3d9e;
+ dark: #432154;
+ sat: #632782;
+ desat: #5e3871;
+ gray: #545454;
+ comp: #48792f;
+ inv: #9fd086; }
+/* line 44, inputs/builtins.scss */
+#more-more-color {
+ op: 0.5;
+ opacify: rgba(1, 2, 3, 0.6);
+ opacify: rgba(1, 2, 3, 0.6);
+ transparentize: rgba(1, 2, 3, 0.4);
+ transparentize: rgba(1, 2, 3, 0.4);
+ transparentize: rgba(52, 130, 3, 0.9); }
+/* line 56, inputs/builtins.scss */
+#more-more-more-color {
+ color: rgba(65, 110, 79, 0.4);
+ color: rgba(20, 255, 216, 0);
+ color: rgba(55, 100, 69, 0.4);
+ color: rgba(0, 255, 213, 0);
+ color: rgba(145, 10, 10, 0);
+ color: rgba(5, 10, 10, 0);
+ color: rgba(145, 145, 145, 0);
+ color: rgba(5, 5, 5, 0);
+ color: #000A0A0A;
+ color: #FFAABBCC; }
+/* line 74, inputs/builtins.scss */
+#string {
+ color: hello what is going on;
+ color: "yeah";
+ color: "I do?";
+ color: 2;
+ color: sinserttring;
+ color: 6;
+ color: tri;
+ color: 'string';
+ color: STRING; }
+/* line 87, inputs/builtins.scss */
+#number {
+ color: 250%;
+ color: 3;
+ color: 3;
+ color: 4;
+ top: 10px;
+ top: 1ex;
+ width: 200%;
+ bottom: 10px;
+ padding: 3em 1in 96px 72pt; }
+/* line 100, inputs/builtins.scss */
+#list {
+ len: 3;
+ len: 1;
+ n: hello;
+ hello: one, two, three, hello;
+ hello: one, two, three, hello, world, what, is, going;
+ hello: one, two, three, hello;
+ index: 2;
+ index: false;
+ index: 3;
+ index: 1;
+ index: false;
+ index: 1;
+ index: false;
+ index: 2;
+ index: 2;
+ index: 1;
+ world: one, two, three, great, job;
+ world: one, two, three, great job;
+ cool: one two three great job;
+ cool: great job one two three;
+ zip: 1px solid, 2px dashed;
+ zip: 1px solid red, 2px dashed green; }
+/* line 135, inputs/builtins.scss */
+#introspection {
+ t: number;
+ t: string;
+ t: string;
+ t: bool;
+ t: color;
+ t: color;
+ t: list;
+ u: "";
+ u: "px";
+ u: "em";
+ l: true;
+ l: false;
+ c: true;
+ c: false;
+ c: true;
+ c: true;
+ c: false;
+ c: true; }
+/* line 159, inputs/builtins.scss */
+#if {
+ color: yes;
+ color: no;
+ color: yes;
+ color: yes; }
+/* line 166, inputs/builtins.scss */
+.transparent {
+ r: 0;
+ g: 0;
+ b: 0;
+ a: 0; }
+/* line 173, inputs/builtins.scss */
+.alpha {
+ a: 1;
+ a: 1;
+ a: 1;
+ a: 0.5;
+ a: alpha(currentColor); }
+/* line 182, inputs/builtins.scss */
+#exists {
+ a: true;
+ b: true;
+ c: false; }
diff --git a/tests/outputs_numbered/comments.css b/tests/outputs_numbered/comments.css
new file mode 100644
index 00000000..6226d416
--- /dev/null
+++ b/tests/outputs_numbered/comments.css
@@ -0,0 +1,33 @@
+/** what the heck **/
+/**
+ Here is a block comment
+ **/
+/*hello*/
+/* line 16, inputs/comments.scss */
+div {
+ /*yeah*/
+ border: 1px solid red;
+ /* another property */
+ color: url('http://mage-page.com');
+ string: "hello /* this is not a comment */";
+ world: "// neither is this";
+ string: 'hello /* this is not a comment */';
+ /*what if this is a comment */
+ world: '// neither is this';
+ what-ever: 100px;
+ background: url();
+ /*this is not a comment?*/ }
+/* line 31, inputs/comments.scss */
+.dummy {
+ color: blue; }
+/* comment 1 */
+/* line 36, inputs/comments.scss */
+a {
+ /* comment 2 */
+ /* comment 3 */
+ color: red;
+ /* comment 4 */
+ background-color: red;
+ /* comment 5 */
+ /* comment 6 */ }
+/* comment 7 */
diff --git a/tests/outputs_numbered/compass_extract.css b/tests/outputs_numbered/compass_extract.css
new file mode 100644
index 00000000..2c6002d8
--- /dev/null
+++ b/tests/outputs_numbered/compass_extract.css
@@ -0,0 +1,29 @@
+/* line 224, inputs/compass_extract.scss */
+#test-0 {
+ unit: false;
+ unit: true;
+ rhythm: 1.5em;
+ size: 1;
+ size: 1;
+ size: 1;
+ size: 2;
+ size: 2; }
+/* line 236, inputs/compass_extract.scss */
+#test-1 {
+ margin-top: 7.5em;
+ padding-top: 9em;
+ padding-bottom: 10.5em;
+ margin-bottom: 0em; }
+/* line 240, inputs/compass_extract.scss */
+#test-2 {
+ border-style: solid;
+ border-width: 0.0625em;
+ padding: 1.4375em; }
+/* line 244, inputs/compass_extract.scss */
+#test-3 {
+ border-top-style: solid;
+ border-top-width: 0.0625em;
+ padding-top: 1.4375em;
+ border-bottom-style: solid;
+ border-bottom-width: 0.0625em;
+ padding-bottom: 1.4375em; }
diff --git a/tests/outputs_numbered/content.css b/tests/outputs_numbered/content.css
new file mode 100644
index 00000000..016b8946
--- /dev/null
+++ b/tests/outputs_numbered/content.css
@@ -0,0 +1,36 @@
+/* line 3, inputs/content.scss */
+/* line 8, inputs/content.scss */
+ * html #logo {
+ background-image: url(/logo.gif); }
+/* line 20, inputs/content.scss */
+.colors {
+ background-color: blue;
+ color: white;
+ border-color: blue; }
+
+@media only screen and (max-width: 480px) {
+ /* line 32, inputs/content.scss */
+ body {
+ color: red; } }
+/* line 36, inputs/content.scss */
+#sidebar {
+ width: 300px; }
+ @media only screen and (max-width: 480px) {
+ #sidebar {
+ width: 100px; } }
+
+@media only screen and (min-width: 40em) {
+ /* line 51, inputs/content.scss */
+ .grid-1 {
+ width: 100%; }
+/* line 51, inputs/content.scss */
+.grid-2 {
+ width: 100%; } }
+
+@media only screen and (min-width: 40em) {
+ /* line 58, inputs/content.scss */
+ .grid-1 {
+ width: 100%; }
+/* line 58, inputs/content.scss */
+.grid-2 {
+ width: 100%; } }
diff --git a/tests/outputs_numbered/content_with_function.css b/tests/outputs_numbered/content_with_function.css
new file mode 100644
index 00000000..864ff558
--- /dev/null
+++ b/tests/outputs_numbered/content_with_function.css
@@ -0,0 +1,3 @@
+/* line 13, inputs/content_with_function.scss */
+body {
+ padding: 1 px; }
diff --git a/tests/outputs_numbered/default_args.css b/tests/outputs_numbered/default_args.css
new file mode 100644
index 00000000..3ac81e14
--- /dev/null
+++ b/tests/outputs_numbered/default_args.css
@@ -0,0 +1,4 @@
+/* line 11, inputs/default_args.scss */
+div {
+ height: red;
+ margin: 100px; }
diff --git a/tests/outputs_numbered/directives.css b/tests/outputs_numbered/directives.css
new file mode 100644
index 00000000..7de43a31
--- /dev/null
+++ b/tests/outputs_numbered/directives.css
@@ -0,0 +1,85 @@
+@charset "hello-world";
+@page :left {
+/* line 3, inputs/directives.scss */
+div {
+ color: red; } }
+
+@page test {
+ @media yes {
+/* line 12, inputs/directives.scss */
+div {
+ color: red; } } }
+
+@media something {
+ @page {
+ @media else {
+/* line 29, inputs/directives.scss */
+div {
+ height: 200px; } } } }
+/* line 37, inputs/directives.scss */
+div {
+ color: red; }
+ @page yeah {
+/* line 40, inputs/directives.scss */
+div pre {
+height: 20px; } }
+
+@font-face {
+ color: red;
+ height: 20px; }
+
+@keyframes 'bounce' {
+/* line 53, inputs/directives.scss */
+from {
+ top: 100px;
+ animation-timing-function: ease-out; }
+/* line 58, inputs/directives.scss */
+25% {
+ top: 50px;
+ animation-timing-function: ease-in; }
+/* line 63, inputs/directives.scss */
+50% {
+ top: 100px;
+ animation-timing-function: ease-out; }
+/* line 68, inputs/directives.scss */
+75% {
+ top: 75px;
+ animation-timing-function: ease-in; }
+/* line 73, inputs/directives.scss */
+to {
+ top: 100px; } }
+
+@-webkit-keyframes flowouttoleft {
+/* line 79, inputs/directives.scss */
+0% {
+ -webkit-transform: translateX(0) scale(1); }
+/* line 80, inputs/directives.scss */
+60%, 70% {
+ -webkit-transform: translateX(0) scale(0.7); }
+/* line 81, inputs/directives.scss */
+100% {
+ -webkit-transform: translateX(-100%) scale(0.7); } }
+/* line 84, inputs/directives.scss */
+div {
+ animation-name: 'diagonal-slide';
+ animation-duration: 5s;
+ animation-iteration-count: 10; }
+
+@keyframes 'diagonal-slide' {
+/* line 92, inputs/directives.scss */
+from {
+ left: 0;
+ top: 0; }
+/* line 97, inputs/directives.scss */
+to {
+ left: 100px;
+ top: 100px; } }
+
+@document url(http://www.w3.org/),
+ url-prefix(http://www.w3.org/Style/),
+ domain(mozilla.org),
+ regexp("https:.*") {
+/* line 109, inputs/directives.scss */
+body {
+ color: purple;
+ background: yellow; } }
diff --git a/tests/outputs_numbered/extends.css b/tests/outputs_numbered/extends.css
new file mode 100644
index 00000000..885d42ad
--- /dev/null
+++ b/tests/outputs_numbered/extends.css
@@ -0,0 +1,127 @@
+/* line 2, inputs/extends.scss */
+error, pre seriousError, span seriousError, other, hello {
+ border: 1px #f00;
+ background-color: #fdd; }
+/* line 7, inputs/extends.scss */
+/* line 8, inputs/extends.scss */
+ pre seriousError, span seriousError {
+ font-size: 20px; }
+/* line 14, inputs/extends.scss */
+hello {
+ color: green; }
+/* line 17, inputs/extends.scss */
+hello div {
+ margin: 10px; }
+/* line 22, inputs/extends.scss */
+.cool, .me {
+ color: red; }
+/* line 26, inputs/extends.scss */
+.blue, .me {
+ color: purple; }
+/* line 30, inputs/extends.scss */
+/* line 34, inputs/extends.scss */
+
+/* line 35, inputs/extends.scss */
+
+a:hover, .hoverlink, #demo .overview .fakelink:hover {
+ text-decoration: underline; }
+/* line 40, inputs/extends.scss */
+div.hello.world.hmm, pre div.okay.span.world.hmm, pre #butt .umm div.sure.span.world.hmm, #butt .umm pre div.sure.span.world.hmm, code div.okay.span.world.hmm, code #butt .umm div.sure.span.world.hmm, #butt .umm code div.sure.span.world.hmm {
+ color: blue; }
+/* line 44, inputs/extends.scss */
+/* line 45, inputs/extends.scss */
+
+/* line 51, inputs/extends.scss */
+
+.xxxxx .xxxxx .xxxxx, code .xxxxx .xxxxx, code code .xxxxx, code code code, code .xxxxx code, .xxxxx code .xxxxx, .xxxxx code code, .xxxxx .xxxxx code {
+ color: green; }
+/* line 55, inputs/extends.scss */
+code {
+ color: red; }
+/* line 63, inputs/extends.scss */
+.alpha, .beta, .gama {
+ color: red; }
+/* line 67, inputs/extends.scss */
+.beta, .gama {
+ color: white; }
+/* line 72, inputs/extends.scss */
+.gama {
+ color: blue; }
+/* line 79, inputs/extends.scss */
+#admin .tabbar a, #admin .tabbar #demo .overview .fakelink, #demo .overview #admin .tabbar .fakelink {
+ font-weight: bold; }
+/* line 80, inputs/extends.scss */
+/* line 82, inputs/extends.scss */
+
+a1 b1 c1 d1, x1 y1 z1 w1 b1 c1 d1 {
+ color: red; }
+/* line 83, inputs/extends.scss */
+/* line 85, inputs/extends.scss */
+
+a2 b2 c2 d2, a2 x2 y2 z2 w2 c2 d2, x2 y2 z2 a2 w2 c2 d2 {
+ color: red; }
+/* line 86, inputs/extends.scss */
+/* line 89, inputs/extends.scss */
+
+a3 b3 c3 d3, a3 b3 x3 y3 z3 w3 d3, x3 y3 z3 a3 b3 w3 d3 {
+ color: red; }
+/* line 90, inputs/extends.scss */
+/* line 93, inputs/extends.scss */
+
+a4 b4 c4 d4, a4 b4 c4 x4 y4 z4 w4, x4 y4 z4 a4 b4 c4 w4 {
+ color: red; }
+/* line 94, inputs/extends.scss */
+/* line 98, inputs/extends.scss */
+
+#butt .yeah .okay, #butt .yeah .umm .sure, #butt .umm .yeah .sure {
+ font-weight: bold; }
+/* line 99, inputs/extends.scss */
+/* line 101, inputs/extends.scss */
+
+a9 b9 s9 t9 v9, a9 b9 s9 t9 x9 y9 z9, a9 b9 x9 y9 s9 t9 z9 {
+ color: red; }
+/* line 103, inputs/extends.scss */
+@media print {
+/* line 110, inputs/extends.scss */
+horse, man {
+ color: blue; } }
+/* line 115, inputs/extends.scss */
+man {
+ color: red; }
+/* line 123, inputs/extends.scss */
+wassup {
+ color: blue; }
+/* line 128, inputs/extends.scss */
+/* line 129, inputs/extends.scss */
+
+.foo .wassup {
+ color: blue; }
+/* line 137, inputs/extends.scss */
+#something, .x, .y {
+ color: red; }
+/* line 141, inputs/extends.scss */
+/* line 145, inputs/extends.scss */
+
+/* line 151, inputs/extends.scss */
+
+/* line 152, inputs/extends.scss */
+
+/* line 156, inputs/extends.scss */
+
+.nav-justified, .nav-tabs.nav-justified {
+ text-align: justify; }
+/* line 162, inputs/extends.scss */
+.btn:hover, .edit .actions button:hover, .edit .new .actions button:hover, .btn:active, .edit .actions button:active, .edit .new .actions button:active, .btn.active, .edit .actions button.active, .edit .new .actions button.active, .btn.disabled, .edit .actions button.disabled, .edit .new .actions button.disabled, .btn[disabled], .edit .actions button[disabled], .edit .new .actions button[disabled] {
+ color: red; }
+/* line 169, inputs/extends.scss */
+/* line 170, inputs/extends.scss */
+
+.edit .actions button {
+ float: right; }
+/* line 175, inputs/extends.scss */
+/* line 176, inputs/extends.scss */
+
+/* line 177, inputs/extends.scss */
+ .edit .new .actions {
+ padding: 0; }
+/* line 180, inputs/extends.scss */
diff --git a/tests/outputs_numbered/filter_effects.css b/tests/outputs_numbered/filter_effects.css
new file mode 100644
index 00000000..d40dbcd5
--- /dev/null
+++ b/tests/outputs_numbered/filter_effects.css
@@ -0,0 +1,21 @@
+/* line 1, inputs/filter_effects.scss */
+#number {
+ -webkit-filter: grayscale(1) sepia(0.5) saturate(0.1) invert(1) opacity(0.5) brightness(0.5) contrast(0.5); }
+/* line 11, inputs/filter_effects.scss */
+#percentage {
+ -webkit-filter: grayscale(100%) sepia(50%) saturate(10%) invert(100%) opacity(50%) brightness(50%) contrast(50%); }
+/* line 21, inputs/filter_effects.scss */
+#misc {
+ -webkit-filter: hue-rotate(90deg) blur(10px) drop-shadow(10px -16px 30px purple); }
+/* line 37, inputs/filter_effects.scss */
+#decimal {
+ opacity: 0.5;
+ filter: alpha(opacity=50, style=1); }
+/* line 41, inputs/filter_effects.scss */
+#percent {
+ opacity: 0.5;
+ filter: alpha(opacity=50); }
+/* line 45, inputs/filter_effects.scss */
+.row {
+ background-color: #071c23;
+ color: #2284a1; }
diff --git a/tests/outputs_numbered/functions.css b/tests/outputs_numbered/functions.css
new file mode 100644
index 00000000..504a3478
--- /dev/null
+++ b/tests/outputs_numbered/functions.css
@@ -0,0 +1,27 @@
+/* line 10, inputs/functions.scss */
+div {
+ color: 14px;
+ sum: 23; }
+/* line 33, inputs/functions.scss */
+div {
+ hello: 10 55;
+ hello: 1010 55;
+ hello: "hello 10 and 55"; }
+/* line 44, inputs/functions.scss */
+del {
+ color: 1000; }
+/* line 48, inputs/functions.scss */
+div {
+ hello: "hello foo and bar";
+ hello: "hello bar and default";
+ hello: "hello Alice, Bob, Tom"; }
+/* line 61, inputs/functions.scss */
+.foo {
+ test2: -moz-art; }
+/* line 77, inputs/functions.scss */
+/* line 67, inputs/functions.scss */
+ div span {
+ height: 3px; }
+/* line 87, inputs/functions.scss */
+div {
+ width: 2; }
diff --git a/tests/outputs_numbered/ie7.css b/tests/outputs_numbered/ie7.css
new file mode 100644
index 00000000..3935c7d3
--- /dev/null
+++ b/tests/outputs_numbered/ie7.css
@@ -0,0 +1,9 @@
+/* line 2, inputs/ie7.scss */
+#foo:before {
+ content: counter(item,".") ": "; }
+/* line 6, inputs/ie7.scss */
+#bar:before {
+ content: counter(item,"."); }
+/* line 10, inputs/ie7.scss */
+#fu:before {
+ content: counter(item); }
diff --git a/tests/outputs_numbered/if.css b/tests/outputs_numbered/if.css
new file mode 100644
index 00000000..154326a2
--- /dev/null
+++ b/tests/outputs_numbered/if.css
@@ -0,0 +1,22 @@
+/* line 10, inputs/if.scss */
+div {
+ color: blue; }
+/* line 16, inputs/if.scss */
+pre {
+ val-1: "red";
+ val-2: "blue";
+ val-3: "blue";
+ val-4: "red";
+ val-5: "red"; }
+/* line 25, inputs/if.scss */
+span {
+ color: blue;
+ height: 10px;
+ width: 20px; }
+/* line 47, inputs/if.scss */
+div {
+ color: blue;
+ border-color: green; }
+/* line 67, inputs/if.scss */
+del {
+ thing: no; }
diff --git a/tests/outputs_numbered/if_on_null.css b/tests/outputs_numbered/if_on_null.css
new file mode 100644
index 00000000..268bcae6
--- /dev/null
+++ b/tests/outputs_numbered/if_on_null.css
@@ -0,0 +1,3 @@
+/* line 6, inputs/if_on_null.scss */
+body {
+ background-color: "red"; }
diff --git a/tests/outputs_numbered/import.css b/tests/outputs_numbered/import.css
new file mode 100644
index 00000000..8bfe1380
--- /dev/null
+++ b/tests/outputs_numbered/import.css
@@ -0,0 +1,32 @@
+@import "foo.css";
+@import "foo" screen;
+@import "http://foo.com/bar";
+@import url(foo);
+/* line 1, inputs/imports/simple.scss */
+div {
+ height: 200px;
+ color: red; }
+/* line 9, inputs/import.scss */
+pre {
+ color: red; }
+/* line 1, inputs/imports/simple.scss */
+pre div {
+ height: 200px;
+ color: red; }
+/* line 14, inputs/import.scss */
+/* line 1, inputs/imports/simple.scss */
+
+code div {
+ height: 200px;
+ color: red; }
+/* line 1, inputs/imports/simple.scss */
+code div {
+ height: 200px;
+ color: red; }
+/* line 2, inputs/imports/_partial.scss */
+#partial {
+ color: blue; }
+/* line 20, inputs/import.scss */
+body {
+ color: #7c2;
+ background: gray; }
diff --git a/tests/outputs_numbered/interpolation.css b/tests/outputs_numbered/interpolation.css
new file mode 100644
index 00000000..53dd8c4a
--- /dev/null
+++ b/tests/outputs_numbered/interpolation.css
@@ -0,0 +1,64 @@
+/* line 2, inputs/interpolation.scss */
+div {
+ color: redwhite blue;
+ color: red white blue;
+ color: red whiteblue;
+ color: redwhiteblue;
+ color: ummyeahwhat;
+ color: stacked;
+ font-size: 10px/something;
+ font-size: 10px / something;
+ test: "whatworldwrong";
+ test: "whatworldwrong";
+ test: "whatworldwrong";
+ test: "what"world"wrong";
+ hi: "what is 16 end"; }
+/* line 24, inputs/interpolation.scss */
+/* line 27, inputs/interpolation.scss */
+ pre var {
+ color: red; }
+/* line 31, inputs/interpolation.scss */
+pre var dad {
+ color: red; }
+/* line 35, inputs/interpolation.scss */
+pre bedvardad {
+ color: red; }
+/* line 40, inputs/interpolation.scss */
+/* line 42, inputs/interpolation.scss */
+
+cool .thing-1 {
+ color: red; }
+/* line 42, inputs/interpolation.scss */
+cool .thing-2 {
+ color: red; }
+/* line 42, inputs/interpolation.scss */
+cool .thing-3 {
+ color: red; }
+/* line 42, inputs/interpolation.scss */
+cool .thing-4 {
+ color: red; }
+/* line 42, inputs/interpolation.scss */
+cool .thing-5 {
+ color: red; }
+/* line 48, inputs/interpolation.scss */
+abcde {
+ color: red; }
+/* line 52, inputs/interpolation.scss */
+#hello, .world {
+ color: red; }
+/* line 56, inputs/interpolation.scss */
+#abchelloyeah, .coolworldyes {
+ color: red; }
+/* line 62, inputs/interpolation.scss */
+div.element:nth-child(2n) {
+ display: none; }
+/* line 69, inputs/interpolation.scss */
+div {
+ hello: world;
+ coolhello: world;
+ helloone: world;
+ twohelloone: world;
+ oneabtwo: cool;
+ hello-world: red;
+ hello-mold: white;
+ hello-hello: blue; }
diff --git a/tests/outputs_numbered/keyword_args.css b/tests/outputs_numbered/keyword_args.css
new file mode 100644
index 00000000..5a6d7463
--- /dev/null
+++ b/tests/outputs_numbered/keyword_args.css
@@ -0,0 +1,7 @@
+/* line 8, inputs/keyword_args.scss */
+pre {
+ out: alpha fort three palace; }
+/* line 19, inputs/keyword_args.scss */
+div {
+ hello: 5;
+ world: -5; }
diff --git a/tests/outputs_numbered/list.css b/tests/outputs_numbered/list.css
new file mode 100644
index 00000000..f5259974
--- /dev/null
+++ b/tests/outputs_numbered/list.css
@@ -0,0 +1,8 @@
+/* line 4, inputs/list.scss */
+div {
+ padding: 10px 20px 30px 40px;
+ margin: 0 10px 10px 10px;
+ background: linear-gradient(black, white); }
+/* line 13, inputs/list.scss */
+p {
+ background: linear-gradient(red, blue); }
diff --git a/tests/outputs_numbered/looping.css b/tests/outputs_numbered/looping.css
new file mode 100644
index 00000000..89dcccfd
--- /dev/null
+++ b/tests/outputs_numbered/looping.css
@@ -0,0 +1,61 @@
+/* line 2, inputs/looping.scss */
+div {
+ color: what;
+ color: is;
+ color: this;
+ font: what;
+ font: is;
+ font: this;
+ background: what;
+ background: is;
+ background: this;
+ border: what;
+ border: is;
+ border: this;
+ background: what what;
+ background: is is;
+ background: this this;
+ background: what what;
+ background: is is;
+ background: this this; }
+/* line 30, inputs/looping.scss */
+div h1 {
+ font-size: 2em; }
+/* line 30, inputs/looping.scss */
+div h2 {
+ font-size: 1.5em; }
+/* line 30, inputs/looping.scss */
+div h3 {
+ font-size: 1.2em; }
+/* line 38, inputs/looping.scss */
+span {
+ color: 0;
+ color: 1;
+ color: 2;
+ color: 3;
+ color: 4;
+ color: 5;
+ color: 6;
+ color: 7;
+ color: 8;
+ color: 9;
+ color: 10; }
+/* line 46, inputs/looping.scss */
+pre {
+ color: 1;
+ color: 2;
+ color: 3;
+ color: 4;
+ height: 1;
+ height: 2;
+ height: 3;
+ height: 4;
+ height: 5;
+ cool: 10;
+ cool: 9;
+ cool: 8;
+ cool: 7;
+ cool: 6;
+ cool: 5;
+ cool: 4;
+ cool: 3; }
diff --git a/tests/outputs_numbered/map.css b/tests/outputs_numbered/map.css
new file mode 100644
index 00000000..124ace48
--- /dev/null
+++ b/tests/outputs_numbered/map.css
@@ -0,0 +1,13 @@
+/* line 11, inputs/map.scss */
+div {
+ color: black;
+ color: red;
+ foo: black, red, #0f0;
+ bar: color, length;
+ baz: (color: #fff, color2: red, 'color3': #0f0, length: 40em);
+ foo: (length: 40em);
+ bar: true; }
+/* line 22, inputs/map.scss */
+div {
+ foo: color black;
+ bar: color; }
diff --git a/tests/outputs_numbered/media.css b/tests/outputs_numbered/media.css
new file mode 100644
index 00000000..779bd31b
--- /dev/null
+++ b/tests/outputs_numbered/media.css
@@ -0,0 +1,128 @@
+@media {
+/* line 4, inputs/media.scss */
+div {
+ color: blue; } }
+
+@media what {
+/* line 7, inputs/media.scss */
+div {
+ color: blue; } }
+
+@media (cool) {
+/* line 11, inputs/media.scss */
+div {
+ color: blue; } }
+
+@media (cool: blue) {
+/* line 14, inputs/media.scss */
+div {
+ color: blue; } }
+
+@media hello and (world) and (butt: man) {
+/* line 18, inputs/media.scss */
+div {
+ color: blue; } }
+
+@media (max-width: 940px) {
+ color: red; }
+
+@media not hello and (world) {
+ color: blue;
+/* line 30, inputs/media.scss */
+pre {
+ color: blue; } }
+ @media butt and (world) {
+ color: red;
+/* line 36, inputs/media.scss */
+div {
+color: red; } }
+
+/* line 64, inputs/media.scss */
+
+div {
+ color: blue; }
+ @media screen and (-webkit-min-device-pixel-ratio: 1.5) {
+/* line 67, inputs/media.scss */
+div .sidebar {
+width: 500px; } }
+/* line 81, inputs/media.scss */
+div {
+ position: absolute; }
+ @media screen {
+ div {
+ top: 0;
+ bottom: 8em;
+ color: red; }
+/* line 87, inputs/media.scss */
+div p {
+margin: 5px; }
+/* line 76, inputs/media.scss */
+div .success {
+color: green; } }
+/* line 95, inputs/media.scss */
+.button {
+ width: 300px;
+ height: 100px;
+ background: #eee; }
+/* line 100, inputs/media.scss */
+.button :hover {
+ background: #aaa; }
+
+@media only screen and (max-width: 300px) {
+ .button {
+ width: 100px;
+ height: 100px; } }
+/* line 110, inputs/media.scss */
+code {
+ position: absolute; }
+
+@media screen {
+ code {
+ height: 10px; }
+/* line 113, inputs/media.scss */
+code pre {
+ height: 20px; } }
+/* line 120, inputs/media.scss */
+@media screen and (color: blue) {
+ dt {
+ height: 10px; } }
+
+@media screen {
+/* line 130, inputs/media.scss */
+.screen {
+ width: 12px; } }
+
+@media only screen {
+/* line 134, inputs/media.scss */
+.only-screen {
+ height: 11px; } }
+
+@media only screen {
+/* line 141, inputs/media.scss */
+.only-screen {
+ width: 14px; } }
+
+@media only screen {
+/* line 145, inputs/media.scss */
+.only-screen {
+ height: 16px; } }
+
+@media print {
+/* line 161, inputs/media.scss */
+.only-print {
+ height: 12px; } }
+
+@media screen {
+/* line 169, inputs/media.scss */
+.only-print {
+ height: 12px; } }
+
+@media not screen {
+/* line 185, inputs/media.scss */
+.not-screen {
+ height: 15px; } }
+
+@media only screen and (color: blue) and (width: 13) {
+/* line 202, inputs/media.scss */
+.only-screen {
+ height: 15px; } }
diff --git a/tests/outputs_numbered/mixins.css b/tests/outputs_numbered/mixins.css
new file mode 100644
index 00000000..b16f853b
--- /dev/null
+++ b/tests/outputs_numbered/mixins.css
@@ -0,0 +1,106 @@
+/* line 9, inputs/mixins.scss */
+div {
+ color: blue;
+ color: red; }
+/* line 4, inputs/mixins.scss */
+div pre {
+ height: 200px; }
+/* line 26, inputs/mixins.scss */
+span {
+ color: blue; }
+/* line 17, inputs/mixins.scss */
+span div {
+ height: 20px; }
+/* line 30, inputs/mixins.scss */
+html {
+ height: 43px; }
+/* line 39, inputs/mixins.scss */
+del {
+ height: 20px; }
+/* line 52, inputs/mixins.scss */
+div {
+ color: white;
+ color: blue;
+ color: white; }
+/* line 62, inputs/mixins.scss */
+div {
+ background-image: linear-gradient(left top, red, green); }
+/* line 72, inputs/mixins.scss */
+div {
+ -moz-box-shadow: 10px 10px 5px #888;
+ -webkit-box-shadow: 10px 10px 5px #888;
+ box-shadow: 10px 10px 5px #888;
+ -moz-box-shadow: inset 10px 10px #888, -10px -10px #f4f4f4;
+ -webkit-box-shadow: inset 10px 10px #888, -10px -10px #f4f4f4;
+ box-shadow: inset 10px 10px #888, -10px -10px #f4f4f4; }
+/* line 81, inputs/mixins.scss */
+/* line 82, inputs/mixins.scss */
+
+div p {
+ color: red;
+ color: blue; }
+/* line 83, inputs/mixins.scss */
+div p .class {
+ color: red; }
+/* line 17, inputs/mixins.scss */
+div p .class div {
+ height: 20px; }
+/* line 17, inputs/mixins.scss */
+div p div {
+ height: 20px; }
+/* line 89, inputs/mixins.scss */
+div p .top {
+ top: 0; }
+/* line 92, inputs/mixins.scss */
+div p .top div {
+ color: red; }
+/* line 103, inputs/mixins.scss */
+div.mixin-content-simple {
+ color: red; }
+/* line 109, inputs/mixins.scss */
+div.mixin-content-with-arg {
+ background: blue;
+ color: red; }
+/* line 109, inputs/mixins.scss */
+div.mixin-content-with-arg {
+ background: purple;
+ height: 20px; }
+/* line 103, inputs/mixins.scss */
+div.mixin-content-simple {
+ height: 43px; }
+/* line 103, inputs/mixins.scss */
+div.mixin-content-simple {
+ color: orange; }
+/* line 17, inputs/mixins.scss */
+div.mixin-content-simple div {
+ height: 20px; }
+/* line 109, inputs/mixins.scss */
+div.mixin-content-with-arg {
+ background: purple;
+ height: 43px; }
+/* line 109, inputs/mixins.scss */
+div.mixin-content-with-arg {
+ background: purple;
+ color: orange; }
+/* line 17, inputs/mixins.scss */
+div.mixin-content-with-arg div {
+ height: 20px; }
+/* line 156, inputs/mixins.scss */
+#please-wait {
+ background: url(/images/logo.png);
+ position: absolute;
+ top: 1em;
+ right: 0;
+ bottom: 3em;
+ left: 4em; }
+/* line 168, inputs/mixins.scss */
+div.parameter-name-scope {
+ -webkit-transform: translateX(50px); }
+
+@-webkit-keyframes change-color {
+/* line 181, inputs/mixins.scss */
+0% {
+ color: green; }
+/* line 182, inputs/mixins.scss */
+100% {
+ color: red; } }
diff --git a/tests/outputs_numbered/nesting.css b/tests/outputs_numbered/nesting.css
new file mode 100644
index 00000000..4400af51
--- /dev/null
+++ b/tests/outputs_numbered/nesting.css
@@ -0,0 +1,24 @@
+div: blue;
+/* line 3, inputs/nesting.scss */
+body {
+ color: red; }
+/* line 8, inputs/nesting.scss */
+div {
+ color: red;
+ height: yes; }
+/* line 12, inputs/nesting.scss */
+div pre {
+ color: blue; }
+/* line 21, inputs/nesting.scss */
+div {
+ font: 10px hello world;
+ font-size: 10px;
+ font-color: blue;
+ border-left: 1px solid blue;
+ border-right: 2px dashed green; }
+/* line 34, inputs/nesting.scss */
+#nested-nesting {
+ bar: baz;
+ bang-bop: bar;
+ bang-bip: 1px;
+ bang-blat-baf: bort; }
diff --git a/tests/outputs_numbered/null.css b/tests/outputs_numbered/null.css
new file mode 100644
index 00000000..90e4bf62
--- /dev/null
+++ b/tests/outputs_numbered/null.css
@@ -0,0 +1,22 @@
+/* line 2, inputs/null.scss */
+.div {
+ one: null;
+ one: world;
+ one: NULL world;
+ one: a, b;
+ two: a, b; }
+/* line 12, inputs/null.scss */
+p:before {
+ content: "I ate pies!"; }
+/* line 31, inputs/null.scss */
+.foo {
+ -webkit-border-radius: 10;
+ border-radius: 10; }
+/* line 35, inputs/null.scss */
+.fu {
+ -webkit-border-radius: 20;
+ border-radius: 20; }
+/* line 39, inputs/null.scss */
+.bar {
+ -webkit-border-top-left-radius: 30;
+ border-top-left-radius: 30; }
diff --git a/tests/outputs_numbered/operators.css b/tests/outputs_numbered/operators.css
new file mode 100644
index 00000000..0d35202f
--- /dev/null
+++ b/tests/outputs_numbered/operators.css
@@ -0,0 +1,169 @@
+/* line 3, inputs/operators.scss */
+body {
+ color: 8;
+ color: 16;
+ height: 10px/10px;
+ color: 6px;
+ color: 5px;
+ bottom: 2px;
+ top: 1.5em;
+ left: -1cm;
+ top: 6.29921; }
+/* line 15, inputs/operators.scss */
+div {
+ color: false;
+ color: true;
+ color: true;
+ color: false;
+ color: what > 3;
+ color: 0;
+ color: -1;
+ color: 1; }
+/* line 29, inputs/operators.scss */
+#units {
+ test: 2.5748in;
+ test: 13mm;
+ test: 4em;
+ test: 11mm;
+ test: 1.1cm; }
+/* line 37, inputs/operators.scss */
+#modulo {
+ test: 1;
+ test: 1cm; }
+/* line 42, inputs/operators.scss */
+#colors {
+ color: #ff0203;
+ color: #fe0000;
+ color: rgba(3, 8, 15, 0.5);
+ color: rgba(5, 7, 10, 0.5);
+ color: rgba(2, 4, 6, 0.5);
+ color: rgba(0, 1, 1, 0.5);
+ color: rgba(3, 4, 5, 0.5);
+ color: rgba(0, 0, 1, 0.5);
+ color: #22f;
+ color: false;
+ color: true;
+ color: true;
+ color: false; }
+/* line 63, inputs/operators.scss */
+#preserve {
+ hello: what -going;
+ hello: what - going; }
+/* line 68, inputs/operators.scss */
+#strings {
+ hello: what -going;
+ hello: whatgoing;
+ hello: whatgoing;
+ hello: whatgoing;
+ hello: whatgoing;
+ hello: "whatgoing";
+ hello: goingwhat;
+ hello: "whatwhat"; }
+/* line 81, inputs/operators.scss */
+#negation {
+ a: -60;
+ b: -90;
+ b: -90; }
+/* line 88, inputs/operators.scss */
+#bools-fail {
+ and: false and two;
+ and: one and two;
+ and: one and false;
+ or: false or two;
+ or: one or two;
+ or: one or false; }
+/* line 98, inputs/operators.scss */
+#bools {
+ and: false;
+ and: two;
+ and: false;
+ or: two;
+ or: one;
+ or: one; }
+/* line 109, inputs/operators.scss */
+#nots-fail {
+ not: false2;
+ not: not false;
+ not: not 0;
+ not: not 1;
+ not: not "";
+ not: not hello; }
+/* line 118, inputs/operators.scss */
+#nots {
+ not: false2;
+ not: true;
+ not: false;
+ not: false;
+ not: false;
+ not: false; }
+/* line 127, inputs/operators.scss */
+#string-test {
+ str: true;
+ str: false;
+ str: true;
+ str: true;
+ str: xhellohellofalse;
+ str: true; }
+/* line 143, inputs/operators.scss */
+#special {
+ cancel-unit: 1; }
+/* line 150, inputs/operators.scss */
+.row .a {
+ margin: -0.5em; }
+/* line 151, inputs/operators.scss */
+.row .b {
+ margin: -0.5em; }
+/* line 152, inputs/operators.scss */
+.row .c {
+ margin: -0.5em; }
+/* line 153, inputs/operators.scss */
+.row .d {
+ margin: -0.5em; }
+/* line 154, inputs/operators.scss */
+.row .e {
+ margin: 0 -0.5em; }
+/* line 156, inputs/operators.scss */
+.alt .a {
+ margin: -0.5em; }
+/* line 157, inputs/operators.scss */
+.alt .b {
+ margin: -0.5em; }
+/* line 158, inputs/operators.scss */
+.alt .c {
+ margin: -0.5em; }
+/* line 159, inputs/operators.scss */
+.alt .d {
+ margin: 0 -0.5em; }
+/* line 160, inputs/operators.scss */
+.alt .e {
+ margin: 0 -0.5em; }
+/* line 162, inputs/operators.scss */
+.row .f {
+ margin: -2em; }
+/* line 163, inputs/operators.scss */
+.row .g {
+ margin: -2em; }
+/* line 164, inputs/operators.scss */
+.row .h {
+ margin: -2em; }
+/* line 165, inputs/operators.scss */
+.row .i {
+ margin: -2em; }
+/* line 166, inputs/operators.scss */
+.row .j {
+ margin: 0 -2em; }
+/* line 168, inputs/operators.scss */
+.alt .f {
+ margin: -2em; }
+/* line 169, inputs/operators.scss */
+.alt .g {
+ margin: -2em; }
+/* line 170, inputs/operators.scss */
+.alt .h {
+ margin: -2em; }
+/* line 171, inputs/operators.scss */
+.alt .i {
+ margin: 0 -2em; }
+/* line 172, inputs/operators.scss */
+.alt .j {
+ margin: 0 -2em; }
diff --git a/tests/outputs_numbered/parsing_comments.css b/tests/outputs_numbered/parsing_comments.css
new file mode 100644
index 00000000..5e0ec76a
--- /dev/null
+++ b/tests/outputs_numbered/parsing_comments.css
@@ -0,0 +1,55 @@
+/* comment 1 */
+/* line 2, inputs/parsing_comments.scss */
+a {
+ /* comment 2 */
+ color: red;
+ /* comment 3 */
+ /* comment 4 */ }
+/* comment 5 */
+/*! comment 1 */
+/* line 10, inputs/parsing_comments.scss */
+b {
+ /*! comment 2 */
+ color: red;
+ /*! comment 3 */
+ /*! comment 4 */ }
+/*! comment 5 */
+/*
+ * multi-line comment 1
+ */
+/* line 20, inputs/parsing_comments.scss */
+c {
+ /*
+ * multi-line comment 2
+ */
+ color: red;
+ /*
+ * multi-line comment 3
+ */
+ /*
+ * multi-line comment 4
+ */ }
+/*
+ * multi-line comment 5
+ */
+/*!
+ * multi-line comment 1
+ */
+/* line 38, inputs/parsing_comments.scss */
+d {
+ /*!
+ * multi-line comment 2
+ */
+ color: red;
+ /*!
+ * multi-line comment 3
+ */
+ /*!
+ * multi-line comment 4
+ */ }
+/*!
+ * multi-line comment 5
+ */
+/* line 54, inputs/parsing_comments.scss */
+e {
+ color: red; }
diff --git a/tests/outputs_numbered/placeholder_selector.css b/tests/outputs_numbered/placeholder_selector.css
new file mode 100644
index 00000000..3eb4a6ea
--- /dev/null
+++ b/tests/outputs_numbered/placeholder_selector.css
@@ -0,0 +1,16 @@
+/* line 1, inputs/placeholder_selector.scss */
+p a.notice span, p a.error span, #context a.notice span, #context a.error span {
+ color: blue;
+ font-weight: bold;
+ font-size: 2em; }
+/* line 7, inputs/placeholder_selector.scss */
+/* line 9, inputs/placeholder_selector.scss */
+/* line 13, inputs/placeholder_selector.scss */
+p {
+ padding: 2em; }
+/* line 18, inputs/placeholder_selector.scss */
+/* line 22, inputs/placeholder_selector.scss */
+
+.layout {
+ color: red; }
+/* line 26, inputs/placeholder_selector.scss */
diff --git a/tests/outputs_numbered/scss_css.css b/tests/outputs_numbered/scss_css.css
new file mode 100644
index 00000000..770a4935
--- /dev/null
+++ b/tests/outputs_numbered/scss_css.css
@@ -0,0 +1,788 @@
+@charset "UTF-8";
+@import "foo.css";
+@import 'foo.css';
+@import url("foo.css");
+@import url('foo.css');
+@import url(foo.css);
+@import "foo.css" screen;
+@import "foo.css" screen, print;
+@import "foo.css" screen, print and (foo: 0);
+@import "foo.css" screen, only print, screen and (foo: 0);
+/* line 1, inputs/scss_css.scss */
+[foo~=bar] {
+ a: b; }
+/* line 5, inputs/scss_css.scss */
+[foo^=bar] {
+ a: b; }
+/* line 9, inputs/scss_css.scss */
+[foo$=bar] {
+ a: b; }
+/* line 13, inputs/scss_css.scss */
+[foo*=bar] {
+ a: b; }
+/* line 17, inputs/scss_css.scss */
+[foo|=en] {
+ a: b; }
+/* line 21, inputs/scss_css.scss */
+foo {
+ a: 2;
+ b: 2.3em;
+ c: 50%;
+ d: "fraz bran";
+ e: flanny-blanny-blan;
+ f: url(http://sass-lang.com);
+ h: #abc; }
+/* line 32, inputs/scss_css.scss */
+selector {
+ property: value;
+ property2: value; }
+/* line 37, inputs/scss_css.scss */
+sel {
+ p: v; }
+/* line 39, inputs/scss_css.scss */
+.foo {
+ /* Foo
+ Bar
+ Baz */
+ a: b; }
+/* line 46, inputs/scss_css.scss */
+.foo {
+ /* Foo
+ Bar
+ Baz */
+ a: b; }
+/* line 53, inputs/scss_css.scss */
+.foo {
+ /* Foo
+ Bar */
+ a: b; }
+/* line 58, inputs/scss_css.scss */
+.foo {
+ /* Foo
+ Bar
+ Baz */
+ a: b; }
+
+@foo {
+ a: b;
+/* line 65, inputs/scss_css.scss */
+rule {
+ a: b; } }
+
+@foo {
+ a: b; }
+
+@bar {
+ a: b; }
+
+@foo "bar"
+
+foo {
+ a: 12px calc(100%/3 - 2*1em - 2*1px);
+ b: 12px -moz-calc(100%/3 - 2*1em - 2*1px);
+ b: 12px -webkit-calc(100%/3 - 2*1em - 2*1px);
+ b: 12px -foobar-calc(100%/3 - 2*1em - 2*1px); }
+/* line 84, inputs/scss_css.scss */
+foo {
+ bar: baz; }
+/* line 86, inputs/scss_css.scss */
+bar {
+ bar: baz; }
+/* line 88, inputs/scss_css.scss */
+baz {
+ bar: baz; }
+/*
+ * foo
+ */
+/* line 94, inputs/scss_css.scss */
+bar {
+ baz: bang; }
+/* line 97, inputs/scss_css.scss */
+E, F {
+ a: b; }
+/* line 101, inputs/scss_css.scss */
+E F, G H {
+ a: b; }
+/* line 105, inputs/scss_css.scss */
+E > F, G > H {
+ a: b; }
+/* This is a CSS comment. */
+/* line 110, inputs/scss_css.scss */
+.one {
+ color: green; }
+/* Another comment */
+/* The following should not be used:
+ .two {color: red;} */
+/* line 113, inputs/scss_css.scss */
+.three {
+ color: green;
+ /* color: red; */ }
+/**
+ .four {color: red;} */
+/* line 116, inputs/scss_css.scss */
+.five {
+ color: green; }
+/**/
+/* line 118, inputs/scss_css.scss */
+.six {
+ color: green; }
+/*********/
+/* line 120, inputs/scss_css.scss */
+.seven {
+ color: green; }
+/* a comment **/
+/* line 122, inputs/scss_css.scss */
+.eight {
+ color: green; }
+/* line 125, inputs/scss_css.scss */
+foo {
+ a: \foo bar;
+ b: foo\ bar;
+ c: \2022 \0020;
+ d: foo\\bar;
+ e: foo\"\'bar; }
+/* line 133, inputs/scss_css.scss */
+foo {
+ a: "\foo bar";
+ b: "foo\ bar";
+ c: "\2022 \0020";
+ d: "foo\\bar";
+ e: "foo\"'bar"; }
+/* line 141, inputs/scss_css.scss */
+foo {
+ _name: val;
+ *name: val;
+ :name: val;
+ .name: val;
+ #name: val;
+ name/**/: val;
+ name/*\**/: val;
+ name: val; }
+
+@foo "bar" ;
+
+foo {
+ a: -moz-element(#foo);
+ b: -webkit-element(#foo);
+ b: -foobar-element(#foo); }
+
+@foo ;
+
+foo {
+ bar: baz; }
+
+/* line 179, inputs/scss_css.scss */
+
+0% {
+ a: b; }
+/* line 183, inputs/scss_css.scss */
+60% {
+ a: b; }
+/* line 187, inputs/scss_css.scss */
+100% {
+ a: b; }
+/* line 191, inputs/scss_css.scss */
+12px {
+ a: b; }
+/* line 195, inputs/scss_css.scss */
+"foo" {
+ a: b; }
+/* line 199, inputs/scss_css.scss */
+foo {
+ a: 12px expression(1 + (3 / Foo.bar("baz" + "bang") + function() {return 12;}) % 12); }
+/* line 203, inputs/scss_css.scss */
+:foo("bar") {
+ a: b; }
+/* line 207, inputs/scss_css.scss */
+:foo(bar) {
+ a: b; }
+/* line 211, inputs/scss_css.scss */
+:foo(12px) {
+ a: b; }
+/* line 215, inputs/scss_css.scss */
+:foo(+) {
+ a: b; }
+/* line 219, inputs/scss_css.scss */
+:foo(-) {
+ a: b; }
+/* line 223, inputs/scss_css.scss */
+:foo(+"bar") {
+ a: b; }
+/* line 227, inputs/scss_css.scss */
+:foo(-++--baz-"bar"12px) {
+ a: b; }
+/* line 231, inputs/scss_css.scss */
+foo {
+ a: foo-bar(12);
+ b: -foo-bar-baz(13, 14 15); }
+/* line 254, inputs/scss_css.scss */
+foo {
+ a: foo !important;
+ b: foo bar !important;
+ b: foo, bar !important; }
+/* line 260, inputs/scss_css.scss */
+foo {
+ a: -moz-bar-baz;
+ b: foo -o-bar-baz; }
+/* line 265, inputs/scss_css.scss */
+foo {
+ a: d;
+ /* b; c: */ }
+/* line 268, inputs/scss_css.scss */
+foo {
+ a : d;
+ /*: b; c */ }
+/* Foo
+ * Bar */
+/* line 275, inputs/scss_css.scss */
+.foo {
+ /* Foo
+ * Bar */ }
+/* line 280, inputs/scss_css.scss */
+[foo] {
+ a: b; }
+/* line 284, inputs/scss_css.scss */
+[foo="bar"] {
+ a: b; }
+/* line 288, inputs/scss_css.scss */
+[foo~="bar"] {
+ a: b; }
+/* line 292, inputs/scss_css.scss */
+[foo^="bar"] {
+ a: b; }
+/* line 296, inputs/scss_css.scss */
+[foo$="bar"] {
+ a: b; }
+/* line 300, inputs/scss_css.scss */
+[foo*="bar"] {
+ a: b; }
+/* line 304, inputs/scss_css.scss */
+[foo|="en"] {
+ a: b; }
+/* line 308, inputs/scss_css.scss */
+:root {
+ a: b; }
+/* line 312, inputs/scss_css.scss */
+:nth-child(n) {
+ a: b; }
+/* line 316, inputs/scss_css.scss */
+:nth-last-child(n) {
+ a: b; }
+/* line 320, inputs/scss_css.scss */
+:nth-of-type(n) {
+ a: b; }
+/* line 324, inputs/scss_css.scss */
+:nth-last-of-type(n) {
+ a: b; }
+/* line 328, inputs/scss_css.scss */
+:first-child {
+ a: b; }
+/* line 332, inputs/scss_css.scss */
+:last-child {
+ a: b; }
+/* line 336, inputs/scss_css.scss */
+:first-of-type {
+ a: b; }
+/* line 340, inputs/scss_css.scss */
+:last-of-type {
+ a: b; }
+/* line 344, inputs/scss_css.scss */
+:only-child {
+ a: b; }
+/* line 348, inputs/scss_css.scss */
+:only-of-type {
+ a: b; }
+/* line 352, inputs/scss_css.scss */
+:empty {
+ a: b; }
+/* line 356, inputs/scss_css.scss */
+:link {
+ a: b; }
+/* line 360, inputs/scss_css.scss */
+:visited {
+ a: b; }
+/* line 364, inputs/scss_css.scss */
+:active {
+ a: b; }
+/* line 368, inputs/scss_css.scss */
+:hover {
+ a: b; }
+/* line 372, inputs/scss_css.scss */
+:focus {
+ a: b; }
+/* line 376, inputs/scss_css.scss */
+:target {
+ a: b; }
+/* line 380, inputs/scss_css.scss */
+:lang(fr) {
+ a: b; }
+/* line 384, inputs/scss_css.scss */
+:enabled {
+ a: b; }
+/* line 388, inputs/scss_css.scss */
+:disabled {
+ a: b; }
+/* line 392, inputs/scss_css.scss */
+:checked {
+ a: b; }
+/* line 396, inputs/scss_css.scss */
+::first-line {
+ a: b; }
+/* line 400, inputs/scss_css.scss */
+::first-letter {
+ a: b; }
+/* line 404, inputs/scss_css.scss */
+::before {
+ a: b; }
+/* line 408, inputs/scss_css.scss */
+::after {
+ a: b; }
+/* line 412, inputs/scss_css.scss */
+.warning {
+ a: b; }
+/* line 416, inputs/scss_css.scss */
+#myid {
+ a: b; }
+/* line 420, inputs/scss_css.scss */
+:not(s) {
+ a: b; }
+
+@media all {
+/* line 425, inputs/scss_css.scss */
+rule1 {
+ prop: val; }
+/* line 428, inputs/scss_css.scss */
+rule2 {
+ prop: val; } }
+
+@media screen, print {
+/* line 433, inputs/scss_css.scss */
+rule1 {
+ prop: val; }
+/* line 436, inputs/scss_css.scss */
+rule2 {
+ prop: val; } }
+
+@media screen and (-webkit-min-device-pixel-ratio: 0) {
+ a: b; }
+
+@media only screen, print and (foo: 0px) and (bar: flam(12px solid)) {
+ a: b; }
+/* line 448, inputs/scss_css.scss */
+:-moz-any(h1, h2, h3) {
+ a: b; }
+/* line 452, inputs/scss_css.scss */
+:-moz-any(.foo) {
+ a: b; }
+/* line 456, inputs/scss_css.scss */
+:-moz-any(foo bar, .baz > .bang) {
+ a: b; }
+
+@-moz-document url(http://www.w3.org/),
+ url-prefix(http://www.w3.org/Style/),
+ domain(mozilla.org),
+ regexp("^https:.*") {
+/* line 464, inputs/scss_css.scss */
+.foo {
+ a: b; } }
+/* line 468, inputs/scss_css.scss */
+foo {
+ filter: progid:DXImageTransform.Microsoft.gradient(GradientType=1, startColorstr=#c0ff3300, endColorstr=#ff000000);
+ filter: progid:DXImageTransform.Microsoft.gradient(GradientType=1, startColorstr=#c0ff3300, endColorstr=#ff000000); }
+/* line 473, inputs/scss_css.scss */
+foo {
+ filter: alpha(opacity=20);
+ filter: alpha(opacity=20, enabled=true);
+ filter: blaznicate(foo=bar, baz=bang bip, bart=#fa4600); }
+
+@foo bar {
+ a: b; }
+
+@bar baz {
+ c: d; }
+
+@foo bar;
+@bar baz;
+
+
+/* Foo
+ * Bar */
+/* Baz
+ * Bang */
+
+
+.foo {
+ /* Foo
+ * Bar */
+ /* Baz
+ * Bang */ }
+/* line 503, inputs/scss_css.scss */
+.foo {
+ /* Foo Bar */
+ /* Baz Bang */ }
+
+@namespace "http://www.w3.org/Profiles/xhtml1-strict";
+
+@namespace url(http://www.w3.org/Profiles/xhtml1-strict);
+
+@namespace html url("http://www.w3.org/Profiles/xhtml1-strict");
+
+[foo|bar=baz] {
+ a: b; }
+/* line 517, inputs/scss_css.scss */
+[*|bar=baz] {
+ a: b; }
+/* line 521, inputs/scss_css.scss */
+[foo|bar|=baz] {
+ a: b; }
+/* line 525, inputs/scss_css.scss */
+foo|E {
+ a: b; }
+/* line 529, inputs/scss_css.scss */
+*|E {
+ a: b; }
+/* line 533, inputs/scss_css.scss */
+foo|* {
+ a: b; }
+/* line 537, inputs/scss_css.scss */
+*|* {
+ a: b; }
+/* line 541, inputs/scss_css.scss */
+:not(foo|bar) {
+ a: b; }
+/* line 545, inputs/scss_css.scss */
+:not(*|bar) {
+ a: b; }
+/* line 549, inputs/scss_css.scss */
+:not(foo|*) {
+ a: b; }
+/* line 553, inputs/scss_css.scss */
+:not(*|*) {
+ a: b; }
+/* line 557, inputs/scss_css.scss */
+:not(#blah) {
+ a: b; }
+/* line 561, inputs/scss_css.scss */
+:not(.blah) {
+ a: b; }
+/* line 565, inputs/scss_css.scss */
+:not([foo]) {
+ a: b; }
+/* line 569, inputs/scss_css.scss */
+:not([foo^="bar"]) {
+ a: b; }
+/* line 573, inputs/scss_css.scss */
+:not([baz|foo~="bar"]) {
+ a: b; }
+/* line 577, inputs/scss_css.scss */
+:not(:hover) {
+ a: b; }
+/* line 581, inputs/scss_css.scss */
+:not(:nth-child(2n + 3)) {
+ a: b; }
+/* line 585, inputs/scss_css.scss */
+:not(:not(#foo)) {
+ a: b; }
+/* line 589, inputs/scss_css.scss */
+:not(a#foo.bar) {
+ a: b; }
+/* line 593, inputs/scss_css.scss */
+:not(#foo .bar > baz) {
+ a: b; }
+/* line 597, inputs/scss_css.scss */
+:not(h1, h2, h3) {
+ a: b; }
+/* line 605, inputs/scss_css.scss */
+foo {
+ a: "bang 1 bar bip"; }
+/* line 609, inputs/scss_css.scss */
+:nth-child(-n) {
+ a: b; }
+/* line 613, inputs/scss_css.scss */
+:nth-child(+n) {
+ a: b; }
+/* line 617, inputs/scss_css.scss */
+:nth-child(even) {
+ a: b; }
+/* line 621, inputs/scss_css.scss */
+:nth-child(odd) {
+ a: b; }
+/* line 625, inputs/scss_css.scss */
+:nth-child(50) {
+ a: b; }
+/* line 629, inputs/scss_css.scss */
+:nth-child(-50) {
+ a: b; }
+/* line 633, inputs/scss_css.scss */
+:nth-child(+50) {
+ a: b; }
+/* line 637, inputs/scss_css.scss */
+:nth-child(2n+3) {
+ a: b; }
+/* line 641, inputs/scss_css.scss */
+:nth-child(2n-3) {
+ a: b; }
+/* line 645, inputs/scss_css.scss */
+:nth-child(+2n-3) {
+ a: b; }
+/* line 649, inputs/scss_css.scss */
+:nth-child(-2n+3) {
+ a: b; }
+/* line 653, inputs/scss_css.scss */
+:nth-child(-2n+ 3) {
+ a: b; }
+/* line 657, inputs/scss_css.scss */
+:nth-child( 2n + 3) {
+ a: b; }
+/* line 661, inputs/scss_css.scss */
+foo {
+ a: foo bar baz;
+ b: foo, #abc, -12;
+ c: 1px/2px/-3px;
+ d: foo bar, baz/bang; }
+
+@page {
+ prop1: val;
+ prop2: val; }
+
+@page flap {
+ prop1: val;
+ prop2: val; }
+
+@page :first {
+ prop1: val;
+ prop2: val; }
+
+@page flap:first {
+ prop1: val;
+ prop2: val; }
+/* line 688, inputs/scss_css.scss */
+.foo {
+ /* Foo */
+ a: b; }
+/* line 693, inputs/scss_css.scss */
+.foo {
+ /* Foo
+ * Bar */
+ a: b; }
+/* Foo */
+/* line 699, inputs/scss_css.scss */
+.foo {
+ a: b; }
+/* Foo
+ * Bar */
+/* line 704, inputs/scss_css.scss */
+.foo {
+ a: b; }
+/* line 708, inputs/scss_css.scss */
+.foo #bar:baz(/* bang )*/ bip) {
+ /* .a #foo */
+ a: b; }
+/* line 712, inputs/scss_css.scss */
+> E {
+ a: b; }
+/* line 716, inputs/scss_css.scss */
++ E {
+ a: b; }
+/* line 720, inputs/scss_css.scss */
+~ E {
+ a: b; }
+/* line 724, inputs/scss_css.scss */
+> > E {
+ a: b; }
+/* line 728, inputs/scss_css.scss */
+>> E {
+ a: b; }
+/* line 732, inputs/scss_css.scss */
+E* {
+ a: b; }
+/* line 736, inputs/scss_css.scss */
+E*.foo {
+ a: b; }
+/* line 740, inputs/scss_css.scss */
+E*:hover {
+ a: b; }
+/* line 744, inputs/scss_css.scss */
+E, F {
+ a: b; }
+/* line 749, inputs/scss_css.scss */
+E F {
+ a: b; }
+/* line 754, inputs/scss_css.scss */
+E, F G, H {
+ a: b; }
+/* line 759, inputs/scss_css.scss */
+body {
+ /*
+ //comment here
+ */ }
+/* line 766, inputs/scss_css.scss */
+E > F {
+ a: b; }
+/* line 768, inputs/scss_css.scss */
+E ~ F {
+ a: b; }
+/* line 770, inputs/scss_css.scss */
+E + F {
+ a: b; }
+/* line 772, inputs/scss_css.scss */
+* {
+ a: b; }
+/* line 776, inputs/scss_css.scss */
+E {
+ a: b; }
+/* line 780, inputs/scss_css.scss */
+E[foo] {
+ a: b; }
+/* line 784, inputs/scss_css.scss */
+E[foo="bar"] {
+ a: b; }
+/* line 788, inputs/scss_css.scss */
+E[foo~="bar"] {
+ a: b; }
+/* line 792, inputs/scss_css.scss */
+E[foo^="bar"] {
+ a: b; }
+/* line 796, inputs/scss_css.scss */
+E[foo$="bar"] {
+ a: b; }
+/* line 800, inputs/scss_css.scss */
+E[foo*="bar"] {
+ a: b; }
+/* line 804, inputs/scss_css.scss */
+E[foo|="en"] {
+ a: b; }
+/* line 808, inputs/scss_css.scss */
+E:root {
+ a: b; }
+/* line 812, inputs/scss_css.scss */
+E:nth-child(n) {
+ a: b; }
+/* line 816, inputs/scss_css.scss */
+E:nth-last-child(n) {
+ a: b; }
+/* line 820, inputs/scss_css.scss */
+E:nth-of-type(n) {
+ a: b; }
+/* line 824, inputs/scss_css.scss */
+E:nth-last-of-type(n) {
+ a: b; }
+/* line 828, inputs/scss_css.scss */
+E:first-child {
+ a: b; }
+/* line 832, inputs/scss_css.scss */
+E:last-child {
+ a: b; }
+/* line 836, inputs/scss_css.scss */
+E:first-of-type {
+ a: b; }
+/* line 840, inputs/scss_css.scss */
+E:last-of-type {
+ a: b; }
+/* line 844, inputs/scss_css.scss */
+E:only-child {
+ a: b; }
+/* line 848, inputs/scss_css.scss */
+E:only-of-type {
+ a: b; }
+/* line 852, inputs/scss_css.scss */
+E:empty {
+ a: b; }
+/* line 856, inputs/scss_css.scss */
+E:link {
+ a: b; }
+/* line 860, inputs/scss_css.scss */
+E:visited {
+ a: b; }
+/* line 864, inputs/scss_css.scss */
+E:active {
+ a: b; }
+/* line 868, inputs/scss_css.scss */
+E:hover {
+ a: b; }
+/* line 872, inputs/scss_css.scss */
+E:focus {
+ a: b; }
+/* line 876, inputs/scss_css.scss */
+E:target {
+ a: b; }
+/* line 880, inputs/scss_css.scss */
+E:lang(fr) {
+ a: b; }
+/* line 884, inputs/scss_css.scss */
+E:enabled {
+ a: b; }
+/* line 888, inputs/scss_css.scss */
+E:disabled {
+ a: b; }
+/* line 892, inputs/scss_css.scss */
+E:checked {
+ a: b; }
+/* line 896, inputs/scss_css.scss */
+E::first-line {
+ a: b; }
+/* line 900, inputs/scss_css.scss */
+E::first-letter {
+ a: b; }
+/* line 904, inputs/scss_css.scss */
+E::before {
+ a: b; }
+/* line 908, inputs/scss_css.scss */
+E::after {
+ a: b; }
+/* line 912, inputs/scss_css.scss */
+E.warning {
+ a: b; }
+/* line 916, inputs/scss_css.scss */
+E#myid {
+ a: b; }
+/* line 920, inputs/scss_css.scss */
+E:not(s) {
+ a: b; }
+/* line 924, inputs/scss_css.scss */
+E F {
+ a: b; }
+/* line 928, inputs/scss_css.scss */
+E > F {
+ a: b; }
+/* line 932, inputs/scss_css.scss */
+E + F {
+ a: b; }
+/* line 936, inputs/scss_css.scss */
+E ~ F {
+ a: b; }
+
+@supports (a: b) and (c: d) or (not (d: e)) and ((not (f: g)) or (not ((h: i) and (j: k)))) {
+/* line 941, inputs/scss_css.scss */
+.foo {
+ a: b; } }
+
+@-prefix-supports (a: b) and (c: d) or (not (d: e)) and ((not (f: g)) or (not ((h: i) and (j: k)))) {
+/* line 948, inputs/scss_css.scss */
+.foo {
+ a: b; } }
+/* line 954, inputs/scss_css.scss */
+foo {
+ foo: bar;
+ #baz: bang;
+ #bip: bop; }
+/* line 960, inputs/scss_css.scss */
+foo {
+ a: -2;
+ b: -2.3em;
+ c: -50%;
+ d: -foo(bar baz); }
+/* line 967, inputs/scss_css.scss */
+foo {
+ a: -0.5em;
+ b: 0.5em;
+ c: -foo(12px);
+ d: +foo(12px); }
+/* line 977, inputs/scss_css.scss */
+foo {
+ -moz-foo-bar: blat;
+ -o-flat-blang: wibble; }
+/* line 981, inputs/scss_css.scss */
+foo {
+ a: foo();
+ b: bar baz-bang() bip; }
diff --git a/tests/outputs_numbered/selectors.css b/tests/outputs_numbered/selectors.css
new file mode 100644
index 00000000..d4e2194e
--- /dev/null
+++ b/tests/outputs_numbered/selectors.css
@@ -0,0 +1,359 @@
+/* line 1, inputs/selectors.scss */
+* {
+ color: blue; }
+/* line 2, inputs/selectors.scss */
+E {
+ color: blue; }
+/* line 4, inputs/selectors.scss */
+E:not(:link) {
+ color: blue; }
+/* line 5, inputs/selectors.scss */
+E:not(:link):not(:visited) {
+ color: blue; }
+/* line 6, inputs/selectors.scss */
+E:not(:link, :visited) {
+ color: blue; }
+/* line 7, inputs/selectors.scss */
+E:matches(:hover, :focus) {
+ color: blue; }
+/* line 9, inputs/selectors.scss */
+E.warning {
+ color: blue; }
+/* line 10, inputs/selectors.scss */
+E#id {
+ color: blue; }
+/* line 11, inputs/selectors.scss */
+E[foo] {
+ color: blue; }
+/* line 12, inputs/selectors.scss */
+E[foo="barbar"] {
+ color: blue; }
+/* line 13, inputs/selectors.scss */
+E[foo="barbar" i] {
+ color: blue; }
+/* line 14, inputs/selectors.scss */
+E[foo~="hello#$@%@$#^"] {
+ color: blue; }
+/* line 15, inputs/selectors.scss */
+E[foo^="color: green;"] {
+ color: blue; }
+/* line 16, inputs/selectors.scss */
+E[foo$="239023"] {
+ color: blue; }
+/* line 17, inputs/selectors.scss */
+E[foo*="29302"] {
+ color: blue; }
+/* line 18, inputs/selectors.scss */
+E[foo|="239032"] {
+ color: blue; }
+/* line 20, inputs/selectors.scss */
+[foo] {
+ color: blue; }
+/* line 21, inputs/selectors.scss */
+[foo] .helloWorld {
+ color: blue; }
+/* line 22, inputs/selectors.scss */
+[foo].helloWorld {
+ color: blue; }
+/* line 23, inputs/selectors.scss */
+[foo="barbar"] {
+ color: blue; }
+/* line 24, inputs/selectors.scss */
+[foo~="hello#$@%@$#^"] {
+ color: blue; }
+/* line 25, inputs/selectors.scss */
+[foo^="color: green;"] {
+ color: blue; }
+/* line 26, inputs/selectors.scss */
+[foo$="239023"] {
+ color: blue; }
+/* line 27, inputs/selectors.scss */
+[foo*="29302"] {
+ color: blue; }
+/* line 28, inputs/selectors.scss */
+[foo|="239032"] {
+ color: blue; }
+/* line 30, inputs/selectors.scss */
+E:dir(ltr) {
+ color: blue; }
+/* line 31, inputs/selectors.scss */
+E:lang(en) {
+ color: blue; }
+/* line 32, inputs/selectors.scss */
+E:lang(en, fr) {
+ color: blue; }
+/* line 34, inputs/selectors.scss */
+E:any-link {
+ color: blue; }
+/* line 35, inputs/selectors.scss */
+E:link {
+ color: blue; }
+/* line 36, inputs/selectors.scss */
+E:visited {
+ color: blue; }
+/* line 37, inputs/selectors.scss */
+E:local-link {
+ color: blue; }
+/* line 38, inputs/selectors.scss */
+E:local-link(0) {
+ color: red; }
+/* line 39, inputs/selectors.scss */
+E:local-link(1) {
+ color: white; }
+/* line 40, inputs/selectors.scss */
+E:local-link(2) {
+ color: red; }
+/* line 41, inputs/selectors.scss */
+E:target {
+ color: blue; }
+/* line 42, inputs/selectors.scss */
+E:scope {
+ color: blue; }
+/* line 44, inputs/selectors.scss */
+E:current {
+ color: blue; }
+/* line 45, inputs/selectors.scss */
+E:current(:link) {
+ color: blue; }
+/* line 46, inputs/selectors.scss */
+E:past {
+ color: blue; }
+/* line 47, inputs/selectors.scss */
+E:future {
+ color: blue; }
+/* line 49, inputs/selectors.scss */
+E:active {
+ color: blue; }
+/* line 50, inputs/selectors.scss */
+E:hover {
+ color: blue; }
+/* line 51, inputs/selectors.scss */
+E:focus {
+ color: blue; }
+/* line 52, inputs/selectors.scss */
+E:enabled {
+ color: blue; }
+/* line 53, inputs/selectors.scss */
+E:disabled {
+ color: blue; }
+/* line 54, inputs/selectors.scss */
+E:indeterminate {
+ color: blue; }
+/* line 55, inputs/selectors.scss */
+E:default {
+ color: blue; }
+/* line 56, inputs/selectors.scss */
+E:in-range {
+ color: blue; }
+/* line 57, inputs/selectors.scss */
+E:out-of-range {
+ color: blue; }
+/* line 58, inputs/selectors.scss */
+E:required {
+ color: blue; }
+/* line 59, inputs/selectors.scss */
+E:optional {
+ color: blue; }
+/* line 60, inputs/selectors.scss */
+E:read-only {
+ color: blue; }
+/* line 61, inputs/selectors.scss */
+E:read-write {
+ color: blue; }
+/* line 63, inputs/selectors.scss */
+E:root {
+ color: blue; }
+/* line 64, inputs/selectors.scss */
+E:empty {
+ color: blue; }
+/* line 65, inputs/selectors.scss */
+E:first-child {
+ color: blue; }
+/* line 66, inputs/selectors.scss */
+E:nth-child(odd) {
+ color: blue; }
+/* line 67, inputs/selectors.scss */
+E:nth-child(2n+1) {
+ color: blue; }
+/* line 68, inputs/selectors.scss */
+E:nth-child(5) {
+ color: blue; }
+/* line 69, inputs/selectors.scss */
+E:last-child {
+ color: blue; }
+/* line 70, inputs/selectors.scss */
+E:nth-last-child(-n+2) {
+ color: blue; }
+/* line 71, inputs/selectors.scss */
+E:only-child {
+ color: blue; }
+/* line 72, inputs/selectors.scss */
+E:first-of-type {
+ color: blue; }
+/* line 73, inputs/selectors.scss */
+E:nth-of-type(2n) {
+ color: blue; }
+/* line 74, inputs/selectors.scss */
+E:last-of-type {
+ color: blue; }
+/* line 75, inputs/selectors.scss */
+E:nth-last-of-type(n) {
+ color: blue; }
+/* line 76, inputs/selectors.scss */
+E:only-of-type {
+ color: blue; }
+/* line 77, inputs/selectors.scss */
+E:nth-match(odd) {
+ color: blue; }
+/* line 78, inputs/selectors.scss */
+E:nth-last-match(odd) {
+ color: blue; }
+/* line 80, inputs/selectors.scss */
+E:column(n) {
+ color: blue; }
+/* line 81, inputs/selectors.scss */
+E:nth-column(n) {
+ color: blue; }
+/* line 82, inputs/selectors.scss */
+E:nth-last-column(n) {
+ color: blue; }
+/* line 84, inputs/selectors.scss */
+E F {
+ color: blue; }
+/* line 85, inputs/selectors.scss */
+E > F {
+ color: blue; }
+/* line 86, inputs/selectors.scss */
+E + F {
+ color: blue; }
+/* line 87, inputs/selectors.scss */
+E ~ F {
+ color: blue; }
+/* line 88, inputs/selectors.scss */
+E /foo/ F {
+ color: blue; }
+/* line 89, inputs/selectors.scss */
+E! > F {
+ color: blue; }
+/* line 92, inputs/selectors.scss */
+[foo|att=val] {
+ color: blue; }
+/* line 93, inputs/selectors.scss */
+[*|att] {
+ color: yellow; }
+/* line 94, inputs/selectors.scss */
+[|att] {
+ color: green; }
+/* line 95, inputs/selectors.scss */
+[att] {
+ color: green; }
+/* line 98, inputs/selectors.scss */
+E::first-line {
+ color: blue; }
+/* line 99, inputs/selectors.scss */
+E::first-letter {
+ color: blue; }
+/* line 100, inputs/selectors.scss */
+E::before {
+ color: blue; }
+/* line 101, inputs/selectors.scss */
+E::after {
+ color: blue; }
+/* line 104, inputs/selectors.scss */
+E::choices {
+ color: blue; }
+/* line 105, inputs/selectors.scss */
+E::value {
+ color: blue; }
+/* line 106, inputs/selectors.scss */
+E::repeat-index {
+ color: blue; }
+/* line 107, inputs/selectors.scss */
+E::repeat-item {
+ color: blue; }
+/* line 109, inputs/selectors.scss */
+E:first {
+ color: blue; }
+/* line 110, inputs/selectors.scss */
+E:first-line {
+ color: blue; }
+/* line 111, inputs/selectors.scss */
+E:first-letter {
+ color: blue; }
+/* line 112, inputs/selectors.scss */
+E:before {
+ color: blue; }
+/* line 113, inputs/selectors.scss */
+E:after {
+ color: blue; }
+/* line 114, inputs/selectors.scss */
+E:checked {
+ color: blue; }
+/* line 115, inputs/selectors.scss */
+E:invalid {
+ color: blue; }
+/* line 116, inputs/selectors.scss */
+E:valid {
+ color: blue; }
+/* line 117, inputs/selectors.scss */
+E:left {
+ color: blue; }
+/* line 118, inputs/selectors.scss */
+E:right {
+ color: blue; }
+/* line 121, inputs/selectors.scss */
+E:any(ol) {
+ color: blue; }
+/* line 122, inputs/selectors.scss */
+E::selection {
+ color: blue; }
+/* line 126, inputs/selectors.scss */
+div {
+ font: something;
+ font-size: 30em; }
+/* line 127, inputs/selectors.scss */
+div font:something {
+ size: 30em; }
+/* line 139, inputs/selectors.scss */
+/* line 140, inputs/selectors.scss */
+
+.something.world {
+ color: blue; }
+/* line 144, inputs/selectors.scss */
+.something .mold {
+ height: 200px; }
+/* line 148, inputs/selectors.scss */
+.dog .something {
+ color: blue; }
+/* line 153, inputs/selectors.scss */
+/* line 154, inputs/selectors.scss */
+
+.dad .simple .wolf {
+ color: blue; }
+/* line 158, inputs/selectors.scss */
+.rad.simple.bad {
+ color: blue; }
+/* line 164, inputs/selectors.scss */
+/* line 165, inputs/selectors.scss */
+
+/* line 166, inputs/selectors.scss */
+ .something div .what.world {
+ color: blue; }
+/* line 172, inputs/selectors.scss */
+/* line 173, inputs/selectors.scss */
+
+div.foo div {
+ color: blue; }
+/* line 178, inputs/selectors.scss */
+/* line 179, inputs/selectors.scss */
+
+/* line 180, inputs/selectors.scss */
+ /* line 181, inputs/selectors.scss */
+ .nice-fonts .main .message div .title, .nice-fonts div .message div .title {
+ font-size: 24px; }
+/* line 189, inputs/selectors.scss */
+.escape\% {
+ color: red; }
+/* line 193, inputs/selectors.scss */
+.escape-plan\% {
+ color: green; }
diff --git a/tests/outputs_numbered/shorthand.css b/tests/outputs_numbered/shorthand.css
new file mode 100644
index 00000000..7dbeb488
--- /dev/null
+++ b/tests/outputs_numbered/shorthand.css
@@ -0,0 +1,29 @@
+/* short-hand properties */
+/* line 2, inputs/shorthand.scss */
+div {
+ background: 0px 0px / 12px;
+ background: 25% 75% / cover;
+ background: center / 50%;
+ background: left / 3em;
+ background: right / auto;
+ background: top / contain;
+ background: 0px 0px, center / 50% auto;
+ background: 0px 0px, center / 3em 25%;
+ font: 0.8em / normal;
+ font: 12px / normal;
+ font: 80% / normal;
+ font: large / 34%;
+ font: large / 3.5;
+ font: large / 3em;
+ font: larger / normal;
+ font: 0.8em / 3.5;
+ font: 12px / 3em;
+ font: 80% / 34%;
+ /* size | family */
+ font: 2em "Open Sans", sans-serif;
+ /* style | size | family */
+ font: italic 2em "Open Sans", sans-serif;
+ /* style | variant | weight | size/line-height | family */
+ font: italic small-caps bolder 16px/3 cursive;
+ /* The font used in system dialogs */
+ font: message-box; }
diff --git a/tests/outputs_numbered/values.css b/tests/outputs_numbered/values.css
new file mode 100644
index 00000000..d78e3938
--- /dev/null
+++ b/tests/outputs_numbered/values.css
@@ -0,0 +1,35 @@
+/* line 2, inputs/values.scss */
+#values {
+ color: #eee;
+ color: #eee;
+ height: 20px;
+ width: 80%;
+ color: "hello world";
+ height: url("http://google.com");
+ dads: url(http://leafo.net);
+ padding: 10px 10px 10px 10px, 3px 3px 3px;
+ textblock: "This is a \
+multiline block \
+#not { color: #eee;}";
+ margin: 4, 3, 1;
+ content: "This is a \
+multiline string.";
+ border-radius: -1px -1px -1px black; }
+/* line 20, inputs/values.scss */
+#subtraction {
+ lit: 10 -11;
+ lit: -1;
+ lit: -1;
+ lit: -1;
+ var: -90;
+ var: -90;
+ var: -90;
+ var: -90; }
+/* line 34, inputs/values.scss */
+#special {
+ a: 12px expression(1 + (3 / Foo.bar("baz" + "bang") + function() {return 12;}) % 12); }
+/* line 38, inputs/values.scss */
+#unary {
+ b: 0.5em;
+ c: -foo(12px);
+ d: +foo(12px); }
diff --git a/tests/outputs_numbered/variables.css b/tests/outputs_numbered/variables.css
new file mode 100644
index 00000000..5aae49d1
--- /dev/null
+++ b/tests/outputs_numbered/variables.css
@@ -0,0 +1,33 @@
+cool: 100px;
+/* line 4, inputs/variables.scss */
+div {
+ height: red, two, three; }
+/* line 10, inputs/variables.scss */
+div {
+ num: 1000; }
+/* line 15, inputs/variables.scss */
+div {
+ num: 2000; }
+/* line 23, inputs/variables.scss */
+pre {
+ color: blue; }
+/* line 31, inputs/variables.scss */
+del {
+ color: red; }
+/* line 34, inputs/variables.scss */
+/* line 36, inputs/variables.scss */
+ del div pre {
+ color: red; }
+/* line 50, inputs/variables.scss */
+body {
+ font-family: Arial;
+ font-family: Helvetica Neue;
+ font-family: "Helvetica Neue";
+ font-family: Helvetica, Arial, sans-serif;
+ font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; }
+/* line 58, inputs/variables.scss */
+#main {
+ width: 5em; }
+/* line 63, inputs/variables.scss */
+#sidebar {
+ width: 5em; }
From 429f5b1b338a431d9e07c08263e9a0c3d1e6b06b Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Sat, 27 Jun 2015 14:36:11 -0400
Subject: [PATCH 002/534] internals: refactor alterColor() helpers
---
src/Compiler.php | 80 +++++++++++++++++++++++-------------------------
1 file changed, 38 insertions(+), 42 deletions(-)
diff --git a/src/Compiler.php b/src/Compiler.php
index 6085e74a..081e5023 100644
--- a/src/Compiler.php
+++ b/src/Compiler.php
@@ -2603,8 +2603,7 @@ protected function alterColor($args, $fn)
if (isset($args[$i])) {
$val = $this->assertNumber($args[$i]);
$ii = $i == 7 ? 4 : $i; // alpha
- $color[$ii] =
- $this->$fn(isset($color[$ii]) ? $color[$ii] : 0, $val, $i);
+ $color[$ii] = call_user_func($fn, isset($color[$ii]) ? $color[$ii] : 0, $val, $i);
}
}
@@ -2614,7 +2613,7 @@ protected function alterColor($args, $fn)
foreach (array(4, 5, 6) as $i) {
if (isset($args[$i])) {
$val = $this->assertNumber($args[$i]);
- $hsl[$i - 3] = $this->$fn($hsl[$i - 3], $val, $i);
+ $hsl[$i - 3] = call_user_func($fn, $hsl[$i - 3], $val, $i);
}
}
@@ -2634,64 +2633,61 @@ protected function alterColor($args, $fn)
'color', 'red', 'green', 'blue',
'hue', 'saturation', 'lightness', 'alpha'
);
- protected function adjustColorHelper($base, $alter, $i)
- {
- return $base += $alter;
- }
protected function libAdjustColor($args)
{
- return $this->alterColor($args, 'adjustColorHelper');
+ return $this->alterColor($args, function ($base, $alter, $i) {
+ return $base + $alter;
+ });
}
protected static $libChangeColor = array(
'color', 'red', 'green', 'blue',
'hue', 'saturation', 'lightness', 'alpha'
);
- protected function changeColorHelper($base, $alter, $i)
- {
- return $alter;
- }
protected function libChangeColor($args)
{
- return $this->alterColor($args, 'changeColorHelper');
+ return $this->alterColor($args, function ($base, $alter, $i) {
+ return $alter;
+ });
}
protected static $libScaleColor = array(
'color', 'red', 'green', 'blue',
'hue', 'saturation', 'lightness', 'alpha'
);
- protected function scaleColorHelper($base, $scale, $i)
- {
- // 1, 2, 3 - rgb
- // 4, 5, 6 - hsl
- // 7 - a
- switch ($i) {
- case 1:
- case 2:
- case 3:
- $max = 255;
- break;
- case 4:
- $max = 360;
- break;
- case 7:
- $max = 1;
- break;
- default:
- $max = 100;
- }
+ protected function libScaleColor($args)
+ {
+ return $this->alterColor($args, function ($base, $scale, $i) {
+ // 1, 2, 3 - rgb
+ // 4, 5, 6 - hsl
+ // 7 - a
+ switch ($i) {
+ case 1:
+ case 2:
+ case 3:
+ $max = 255;
+ break;
- $scale = $scale / 100;
+ case 4:
+ $max = 360;
+ break;
- if ($scale < 0) {
- return $base * $scale + $base;
- }
+ case 7:
+ $max = 1;
+ break;
- return ($max - $base) * $scale + $base;
- }
- protected function libScaleColor($args)
- {
- return $this->alterColor($args, 'scaleColorHelper');
+ default:
+ $max = 100;
+ }
+
+ $scale = $scale / 100;
+
+ if ($scale < 0) {
+ return $base * $scale + $base;
+ }
+
+ return ($max - $base) * $scale + $base;
+ });
}
protected static $libIeHexStr = array('color');
From 3c662c8f00bdfd21d0cbc7c911ff4d190f30ed5e Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Wed, 1 Jul 2015 21:26:25 -0400
Subject: [PATCH 003/534] Parser: deprecated show() and to() methods
---
src/Parser.php | 15 ++++++++++++---
1 file changed, 12 insertions(+), 3 deletions(-)
diff --git a/src/Parser.php b/src/Parser.php
index 5b357ea4..f35a18a3 100644
--- a/src/Parser.php
+++ b/src/Parser.php
@@ -1784,9 +1784,15 @@ protected function end()
return false;
}
- // advance counter to next occurrence of $what
- // $until - don't include $what in advance
- // $allowNewline, if string, will be used as valid char set
+ /**
+ * @deprecated
+ *
+ * {@internal
+ * advance counter to next occurrence of $what
+ * $until - don't include $what in advance
+ * $allowNewline, if string, will be used as valid char set
+ * }}
+ */
protected function to($what, &$out, $until = false, $allowNewline = false)
{
if (is_string($allowNewline)) {
@@ -1959,6 +1965,9 @@ public static function pregQuote($what)
return preg_quote($what, '/');
}
+ /**
+ * @deprecated
+ */
protected function show()
{
if ($this->peek("(.*?)(\n|$)", $m, $this->count)) {
From 59e7ee0eb46ee531afa1723c143c45d696a3519e Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Wed, 1 Jul 2015 21:33:11 -0400
Subject: [PATCH 004/534] bump version to 0.1.7
---
README.md | 2 +-
site/index.md | 6 ++++++
site/site.moon | 2 +-
src/Version.php | 2 +-
4 files changed, 9 insertions(+), 3 deletions(-)
diff --git a/README.md b/README.md
index e989ccc9..5216d2bf 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,4 @@
-# scssphp v0.1.6
+# scssphp v0.1.7
###
[](http://travis-ci.org/leafo/scssphp)
diff --git a/site/index.md b/site/index.md
index 55e8a056..a146feec 100644
--- a/site/index.md
+++ b/site/index.md
@@ -111,6 +111,12 @@ Find any issues? I'd love to fix them for you, post about them on [the issues tr
## Changelog
+* **0.1.7** -- July 1, 2015
+ * bin/pscss: added --line-numbers and --debug-info options
+ * Compiler: added setLineCommentStyle() and 'q' unit
+ * Parser: deprecated show() and to() methods
+ * simplified licensing (MIT)
+ * refactoring internals and misc bug fixes (maps, empty list, function-exists())
* **0.1.6** -- June 22, 2015
* !global
* more built-in functions
diff --git a/site/site.moon b/site/site.moon
index 9e42ad47..b7354b82 100644
--- a/site/site.moon
+++ b/site/site.moon
@@ -3,7 +3,7 @@ require "sitegen"
tools = require "sitegen.tools"
sitegen.create_site =>
- @current_version = "0.1.6"
+ @current_version = "0.1.7"
@title = "SCSS Compiler in PHP"
scssphp = tools.system_command "bin/pscss < %s > %s", "css"
diff --git a/src/Version.php b/src/Version.php
index 1eed63c0..95e7b5f2 100644
--- a/src/Version.php
+++ b/src/Version.php
@@ -18,5 +18,5 @@
*/
class Version
{
- const VERSION = 'v0.1.6';
+ const VERSION = 'v0.1.7';
}
From 62591150323beff348ced4a5be5345665e8979e9 Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Wed, 1 Jul 2015 22:14:34 -0400
Subject: [PATCH 005/534] Fix typo in docs; update Travis CI badge
---
README.md | 2 +-
site/index.md | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/README.md b/README.md
index 5216d2bf..08b765da 100644
--- a/README.md
+++ b/README.md
@@ -1,7 +1,7 @@
# scssphp v0.1.7
###
-[](http://travis-ci.org/leafo/scssphp)
+[](http://travis-ci.org/leafo/scssphp)
`scssphp` is a compiler for SCSS written in PHP.
diff --git a/site/index.md b/site/index.md
index a146feec..21c46388 100644
--- a/site/index.md
+++ b/site/index.md
@@ -113,7 +113,7 @@ Find any issues? I'd love to fix them for you, post about them on [the issues tr
* **0.1.7** -- July 1, 2015
* bin/pscss: added --line-numbers and --debug-info options
- * Compiler: added setLineCommentStyle() and 'q' unit
+ * Compiler: added setLineNumberStyle() and 'q' unit
* Parser: deprecated show() and to() methods
* simplified licensing (MIT)
* refactoring internals and misc bug fixes (maps, empty list, function-exists())
From 28d9f1cd077b7cbd76e991dd2c4552eb1c7f88db Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Sun, 5 Jul 2015 08:26:39 -0400
Subject: [PATCH 006/534] Update README.md
---
README.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/README.md b/README.md
index 08b765da..94a8b78b 100644
--- a/README.md
+++ b/README.md
@@ -5,7 +5,7 @@
`scssphp` is a compiler for SCSS written in PHP.
-It implements SCSS 3.2.12. It does not implement the SASS syntax, only the SCSS
+It primarily implements SCSS 3.2.16, with some 3.3.x/3.4.x compatibility. It does not implement the SASS syntax, only the SCSS
syntax.
Checkout the homepage, , for directions on how to use.
From 9ad912abd983dfeed00895f0e5d03203aadc5f21 Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Thu, 2 Jul 2015 08:35:44 -0400
Subject: [PATCH 007/534] Remove leafo.net/scssphp site content
---
site/.gitignore | 2 -
site/composer.html | 6 -
site/docs/index.md | 390 ---------------------------
site/index.md | 255 ------------------
site/site.moon | 15 --
site/style.scss | 303 ---------------------
site/templates/index.html | 81 ------
site/www/.gitignore | 2 -
site/www/img/tile.png | Bin 244 -> 0 bytes
site/www/style/normalize.css | 500 -----------------------------------
10 files changed, 1554 deletions(-)
delete mode 100644 site/.gitignore
delete mode 100644 site/composer.html
delete mode 100644 site/docs/index.md
delete mode 100644 site/index.md
delete mode 100644 site/site.moon
delete mode 100644 site/style.scss
delete mode 100644 site/templates/index.html
delete mode 100644 site/www/.gitignore
delete mode 100644 site/www/img/tile.png
delete mode 100644 site/www/style/normalize.css
diff --git a/site/.gitignore b/site/.gitignore
deleted file mode 100644
index 6cff4227..00000000
--- a/site/.gitignore
+++ /dev/null
@@ -1,2 +0,0 @@
-.sitegen_cache
-.tup
diff --git a/site/composer.html b/site/composer.html
deleted file mode 100644
index 40d6b7a1..00000000
--- a/site/composer.html
+++ /dev/null
@@ -1,6 +0,0 @@
-{
- "require" : {
- "leafo/scssphp" : "$current_version"
- }
-}
-
diff --git a/site/docs/index.md b/site/docs/index.md
deleted file mode 100644
index 66a5a42b..00000000
--- a/site/docs/index.md
+++ /dev/null
@@ -1,390 +0,0 @@
- title: Documentation
---
-
-scssphp $current_version Documentation
-
-$index
-
-## PHP Interface
-
-### Including
-
-The project can be loaded through a `composer` generated auto-loader.
-
-Alternatively, the entire project can be loaded through a utility file.
-Just include it somewhere to start using it:
-
- ```php
- compile('
- $color: #abc;
- div { color: lighten($color, 20%); }
- ');
- ```
-
-* `compile($scssCode)` will attempt to compile a string of SCSS code. If it
- succeeds then the CSS will be returned as a string. If there is any error, an
- exception is thrown with an appropriate error message.
-
-
-### Import Paths
-
-When you import a file using the `@import` directive, the current path of your
-PHP script is used as the search path by default. This is often not what
-you want, so there are two methods for manipulating the import path:
-`addImportPath`, and `setImportPaths`.
-
-* `addImportPath($path)` will append `$path` to the list of the import
- paths that are searched.
-
-* `setImportPaths($pathArray)` will replace the entire import path with
- `$pathArray`. The value of `$pathArray` will be converted to an array if it
- isn't one already.
-
-If the import path is set to `array()` then importing is effectively disabled.
-The default import path is `array('')`, which means the current directory.
-
- ```php
- setImportPaths('assets/stylesheets/');
-
- // will search for `assets/stylesheets/mixins.scss'
- echo $scss->compile('@import "mixins.scss";');
- ```
-
-Besides adding static import paths, it's also possible to add custom import
-functions. This allows you to load paths from a database, or HTTP, or using
-files that SCSS would otherwise not process (such as vanilla CSS imports).
-
- ```php
- addImportPath(function($path) {
- if (!file_exists('stylesheets/'.$path)) return null;
- return 'stylesheets/'.$path;
- });
-
- // will import `stylesheets/vanilla.css'
- echo $scss->compile('@import "vanilla.css";');
- ```
-
-### Output Formatting
-
-It's possible to customize the formatting of the output CSS by changing the
-default formatter.
-
-Five formatters are included:
-
-* `Leafo\ScssPhp\Formatter\Expanded`
-* `Leafo\ScssPhp\Formatter\Nested` *(default)*
-* `Leafo\ScssPhp\Formatter\Compressed`
-* `Leafo\ScssPhp\Formatter\Compact`
-* `Leafo\ScssPhp\Formatter\Crunched`
-
-We can change the formatting using the `setFormatter` method.
-
-* `setFormatter($formatterName)` sets the current formatter to `$formatterName`,
- the name of a class as a string that implements the formatting interface. See
- the source for `Leafo\ScssPhp\Formatter\Expanded` for an example.
-
-
-Given the following SCSS:
-
- ```scss
- /*! Comment */
- .navigation {
- ul {
- line-height: 20px;
- color: blue;
- a {
- color: red;
- }
- }
- }
-
- .footer {
- .copyright {
- color: silver;
- }
- }
- ```
-
-The formatters output the following:
-
-`Leafo\ScssPhp\Formatter\Expanded`:
-
- ```css
- /*! Comment */
- .navigation ul {
- line-height: 20px;
- color: blue;
- }
- .navigation ul a {
- color: red;
- }
- .footer .copyright {
- color: silver;
- }
- ```
-
-`Leafo\ScssPhp\Formatter\Nested`:
-
- ```css
- /*! Comment */
- .navigation ul {
- line-height: 20px;
- color: blue; }
- .navigation ul a {
- color: red; }
-
- .footer .copyright {
- color: silver; }
- ```
-
-`Leafo\ScssPhp\Formatter\Compact`:
-
- ```css
- /*! Comment */
- .navigation ul { line-height:20px; color:blue; }
-
- .navigation ul a { color:red; }
-
- .footer .copyright { color:silver; }
- ```
-
-`Leafo\ScssPhp\Formatter\Compressed`:
-
- ```css
- /* Comment*/.navigation ul{line-height:20px;color:blue;}.navigation ul a{color:red;}.footer .copyright{color:silver;}
- ```
-
-`Leafo\ScssPhp\Formatter\Crunched`:
-
- ```css
- .navigation ul{line-height:20px;color:blue;}.navigation ul a{color:red;}.footer .copyright{color:silver;}
- ```
-
-### Source Line Debugging
-
-You can output the original SCSS line numbers within the compiled CSS file for better frontend debugging.
-
-This works well in combination with frontend debugging tools such as https://addons.mozilla.org/de/firefox/addon/firecompass-for-firebug/
-
-To activate this feature, call `->setLineNumberStyle(Compiler::LINE_COMMENTS)` after creating a new instance of class `Compiler`.
-
- ```php
- use Leafo\ScssPhp\Server;
- use Leafo\ScssPhp\Compiler;
-
- $directory = 'css';
-
- $scss = new Compiler();
- $scss->setLineNumberStyle(Compiler::LINE_COMMENTS);
-
- $server = new Server($directory, null, $scss);
- $server->serve();
- ```
-
-You can also call the `compile` method directly (without using an instance of `Server` like above)
-
- ```php
- use Leafo\ScssPhp\Server;
- use Leafo\ScssPhp\Compiler;
-
- $scss = new Compiler();
- $scss->setLineNumberStyle(Compiler::LINE_COMMENTS);
-
- echo $scss->compile('
- $color: #abc;
- div { color: lighten($color, 20%); }
- ');
- ```
-
-### Custom Functions
-
-It's possible to register custom functions written in PHP that can be called
-from SCSS. Some possible applications include appending your assets directory
-to a URL with an `asset-url` function, or converting image URLs to an embedded
-data URI to reduce the number of requests on a page with a `data-uri` function.
-
-We can add and remove functions using the methods `registerFunction` and
-`unregisterFunction`.
-
-* `registerFunction($functionName, $callable)` assigns the callable value to
- the name `$functionName`. The name is normalized using the rules of SCSS.
- Meaning underscores and dashes are interchangeable. If a function with the
- same name already exists then it is replaced.
-
-* `unregisterFunction($functionName)` removes `$functionName` from the list of
- available functions.
-
-
-The `$callable` can be anything that PHP knows how to call using
-`call_user_func`. The function receives two arguments when invoked. The first
-is an array of SCSS typed arguments that the function was sent. The second is a
-reference to the current `scss` instance.
-
-The *SCSS typed arguments* are actually just arrays that represent SCSS values.
-SCSS has different types than PHP, and this is how **scssphp** represents them
-internally.
-
-For example, the value `10px` in PHP would be `array('number', 1, 'px')`. There
-is a large variety of types. Experiment with a debugging function like `print_r`
-to examine the possible inputs.
-
-The return value of the custom function can either be a SCSS type or a basic
-PHP type. (such as a string or a number) If it's a PHP type, it will be converted
-automatically to the corresponding SCSS type.
-
-As an example, a function called `add-two` is registered, which adds two numbers
-together. PHP's anonymous function syntax is used to define the function.
-
- ```php
- registerFunction('add-two', function($args) {
- list($a, $b) = $args;
- return $a[1] + $b[1];
- });
-
- $scss->compile('.ex1 { result: add-two(10, 10); }');
- ```
-
-It's worth noting that in this example we lose the units of the number, and we
-also don't do any type checking. This will have undefined results if we give it
-anything other than two numbers.
-
-
-## SCSS Server
-
-The SCSS server is a small class that helps with automatically compiling SCSS.
-
-It's an endpoint for your web application that searches for SCSS files in a
-directory then compiles and serves them as CSS. It will only compile
-files if they've been modified (or one of the imports has been modified).
-
-### Using `serveFrom`
-
-`Server::serveFrom` is a simple to use function that should handle most cases.
-
-For example, create a file `style.php`:
-
- ```php
- `Server::serveFrom($directory)` will serve SCSS files out of
- `$directory`. It will attempt to get the path to the file out of
- `$_SERVER['PATH_INFO']`. (It also looks at the GET parameter `p`)
-
-
-If it can not find the file it will return an HTTP 404 page:
-
- ```text
- /* INPUT NOT FOUND scss v0.0.1 */
- ```
-
-If the file can't be compiled due to an error, then an HTTP 500 page is
-returned. Similar to the following:
-
- ```text
- Parse error: parse error: failed at `height: ;` stylesheets/test.scss on line 8
- ```
-
-By default , the SCSS server must have write access to the style sheet
-directory. It writes its cache in a special directory called `scss_cache`.
-
-Also, because SCSS server writes headers, make sure no output is written before
-it runs.
-
-### Using `Leafo\ScssPhp\Server`
-
-Creating an instance of `Server` is just another way of accomplishing what
-`serveFrom` does. It lets us customize the cache directory and the instance
-of the `Compiler` that is used to compile
-
-
-* `new Server($sourceDir, $cacheDir, $scss)` creates a new server that
- serves files from `$sourceDir`. The cache dir is where the cached compiled
- files are placed. When `null`, `$sourceDir . '/scss_cache'` is used. `$scss`
- is the instance of `scss` that is used to compile.
-
-
-Just call the `serve` method to let it render its output.
-
-Here's an example of creating a SCSS server that outputs compressed CSS:
-
- ```php
- setFormatter('Leafo\ScssPhp\Formatter\Compressed');
-
- $server = new Server('stylesheets', null, $scss);
- $server->serve();
- ```
-
-
-## Command Line Tool
-
-A really basic command line tool is included for integration with scripts. It
-is called `pscss`. It reads SCSS from either a named input file or standard in,
-and returns the CSS to standard out.
-
-Usage: bin/pscss [options] [input-file]
-
-### Options
-
-If passed the flag `-h` (or `--help`), input is ignored and a summary of the command's usage is returned.
-
-If passed the flag `-v` (or `--version`), input is ignored and the current version is returned.
-
-If passed the flag `-T`, a formatted parse tree is returned instead of the compiled CSS..
-
-The flag `-f` (or `--style`) can be used to set the [formatter](#Output_formatting):
-
- ```bash
- $ bin/pscss -f compressed < styles.scss
- ```
-
-The flag `-i` (or `--load_paths`) can be used to set import paths for the loader. On Unix/Linux systems,
-the paths are colon separated.
-
-The flag `-p` (or `--precision`) can be used to set the decimal number precision. The default is 5.
-
-The flag `--debug-info` can be used to annotate the selectors with CSS @media queries that identify the source file and line number.
-
-The flag `--line-comments` (or `--line-numbers`) can be used to annotate the selectors with comments that identify the source file and line number.
diff --git a/site/index.md b/site/index.md
deleted file mode 100644
index 21c46388..00000000
--- a/site/index.md
+++ /dev/null
@@ -1,255 +0,0 @@
-**scssphp** is a compiler for [SCSS][0] written in PHP.
-
-SCSS is a CSS preprocessor that adds many features like variables, mixins,
-imports, color manipulation, functions, and tons of other powerful features.
-
-The entire compiler comes in a single class file ready for including in any
-kind of project in addition to a command line tool for running the compiler
-from the terminal.
-
-**scssphp** implements SCSS (3.2.12). It does not implement the SASS syntax,
-only the SCSS syntax.
-
-Follow the author on twitter: [@moonscript](http://twitter.com/moonscript).
-
-
-
-
-
-
-
-## Installing
-
-You can always download the latest version here:
-scssphp-$current_version.tar.gz
-
-You can also find the latest source online:
-
-
-If you use [Packagist][2] for installing packages, then you can update your `composer.json` like so:
-
-$render{[[composer]]}
-
-
-## Language Reference
-
-For a complete guide to the syntax of SCSS, consult the [official documentation][1].
-
-## PHP Reference
-
-Complete documentation for **scssphp** is located at http://leafo.net/scssphp/docs/ .
-
-### Quickstart
-
-If you just want to start serving compiled `scss` files as quick as possible
-then start here.
-
-**scssphp** comes with a easy to use class that automatically compiles modified
-`scss` files and serves them from a directory you specify.
-
-Create a file, like `style.php`:
-
- ```php
- compile('
- $color: #abc;
- div { color: lighten($color, 20%); }
- ');
-
- ```
-
-The `compile` method takes `SCSS` as a string, and returns the `CSS`. If there
-is an error when compiling then an exception is thrown with an appropriate
-message.
-
-
-For a more detailed guide consult http://leafo.net/scssphp/docs/ .
-
-
-## Issues
-
-Find any issues? I'd love to fix them for you, post about them on [the issues tracker][3].
-
-
-## Changelog
-
-* **0.1.7** -- July 1, 2015
- * bin/pscss: added --line-numbers and --debug-info options
- * Compiler: added setLineNumberStyle() and 'q' unit
- * Parser: deprecated show() and to() methods
- * simplified licensing (MIT)
- * refactoring internals and misc bug fixes (maps, empty list, function-exists())
-* **0.1.6** -- June 22, 2015
- * !global
- * more built-in functions
- * Server: checkedCachedCompile() (zimzat)
- * Server: showErrorsAsCSS() to display errors in a pseudo-element (khamer)
- * misc bug fixes
-* **0.1.5** -- June 2, 2015
- * misc bug fixes
-* **0.1.4** -- June 2, 2015
- * add new string functions (okj579)
- * add compileFile() and checkCompile() (NoxNebula, saas786, panique)
- * fix regular expression in findImport() (lucvn)
- * needsCompile() shouldn't compare meta-etag with browser etag (edwinveldhuizen)
-* **0.1.3** -- May 31, 2015
- * map support (okj579)
- * misc bug fixes (etu, bgarret, aaukt)
-* **0.1.1** -- Aug 12, 2014
- * add stub classes -- a backward compatibility layer (vladimmi)
-* **0.1.0** -- Aug 9, 2014
- * raise PHP requirement (5.3+)
- * reformat/reorganize source files to be PSR-2 compliant
-* **0.0.15** -- Aug 6, 2014
- * fix regression with default values in functions (torkiljohnsen)
-* **0.0.14** -- Aug 5, 2014
- * @keyframes $name - didn't work inside mixin (sergeylukin)
- * Bourbon transform(translateX()) didn't work (dovy and greynor)
-* **0.0.13** -- Aug 4, 2014
- * handle If-None-Match in client request, and send ETag in response (NSmithUK)
- * normalize quotation marks (NoxNebula)
- * improve handling of escape sequence in selectors (matt3224)
- * add "scss_formatter_crunched" which strips comments
- * internal: generate more accurate parse tree
-* **0.0.12** -- July 6, 2014
- * revert erroneous import-partials-fix (smuuf)
- * handle If-Modified-Since in client request, and send Last-Modified in response (braver)
- * add hhvm to travis-ci testing
-* **0.0.11** -- July 5, 2014
- * support multi-line continuation character (backslash)per CSS2.1 and CSS3 spec (caiosm1005)
- * imported partials should not be compiled (squarestar)
- * add setVariables() and unsetVariable() to interface (leafo/lessphp)
- * micro-optimizing is_null() (Yahasana)
-* **0.0.10** -- April 14, 2014
- * fix media query merging (timonbaetz)
- * inline if should treat null as false (wonderslug)
- * optimizing toHSL() (jfsullivan)
-* **0.0.9** -- December 23, 2013
- * fix @for/@while inside @content block (sergeylukin)
- * fix functions in mixin_content (timonbaetz)
- * fix infinite loop when target extends itself (oscherler)
- * fix function arguments are lost inside of @content block
- * allow setting number precision (kasperisager)
- * add public function helpers (toBool, get, findImport, assertList, assertColor, assertNumber, throwError) (Burgov, atdt)
- * add optional cache buster prefix to serve() method (iMoses)
-* **0.0.8** -- September 16, 2013
- * Avoid IE7 content: counter bug
- * Support transparent as color name
- * Recursively create cache dir (turksheadsw)
- * Fix for INPUT NOT FOUND (morgen32)
-* **0.0.7** -- May 24, 2013
- * Port various fixes from leafo/lessphp.
- * Improve filter precision.
- * Parsing large image data-urls does not work.
- * Add == and != ops for colors.
- * @if and @while directives should treat null like false.
- * Add pscss as bin in composer.json (Christian Lück).
- * Fix !default bug (James Shannon, Alberto Aldegheri).
- * Fix mixin content includes (James Shannon, Christian Brandt).
- * Fix passing of varargs to another mixin.
- * Fix interpolation bug in expToString() (Matti Jarvinen).
-* **0.0.5** -- March 11, 2013
- * Better compile time errors
- * Fix top level properties inside of a nested `@media` (Anthon Pang)
- * Fix some issues with `@extends` (Anthon Pang)
- * Enhanced handling of `null` (Anthon Pang)
- * Helper functions shouldn't mix with css builtins (Anthon Pang)
- * Enhance selector parsing (Guilherme Blanco, Anthon Pang)
- * Add Placeholder selector support (Martin Hasoň)
- * Add variable argument support (Martin Hasoň)
- * Add zip, index, comparable functions (Martin Hasoň)
- * A bunch of parser and bug fixes
-* **0.0.4** -- Nov 3nd, 2012
- * [Import path can be a function](docs/#import_paths) (Christian Lück).
- * Correctly parse media queries with more than one item (Christian Lück).
- * Add `ie_hex_str`, `abs`, `min`, `max` functions (Martin Hasoň)
- * Ignore expressions inside of `calc()` (Martin Hasoň)
- * Improve operator evaluation (Martin Hasoň)
- * Add [`@content`](http://sass-lang.com/docs/yardoc/file.SASS_REFERENCE.html#mixin-content) support.
- * Misc bug fixes.
-* **0.0.3** -- August 2nd, 2012
- * Add missing and/or/not operators.
- * Expression evaluation happens correctly.
- * Import file caching and _partial filename support.
- * Misc bug fixes.
-* **0.0.2** -- July 30th, 2012
- * SCSS server is aware of imports
- * added custom function interface
- * compressed formatter
- * wrote documentation
-* Initial Release v0.0.1 -- July 29th, 2012
-
-
-
-
-
-## Comments
-
-
-
-
-
- [0]: http://sass-lang.com/
- [1]: http://sass-lang.com/docs/yardoc/file.SASS_REFERENCE.html#css_extensions
- [2]: http://packagist.org/
- [3]: https://github.com/leafo/scssphp/issues
- [4]: https://github.com/leafo/scssphp/
diff --git a/site/site.moon b/site/site.moon
deleted file mode 100644
index b7354b82..00000000
--- a/site/site.moon
+++ /dev/null
@@ -1,15 +0,0 @@
-require "sitegen"
-
-tools = require "sitegen.tools"
-
-sitegen.create_site =>
- @current_version = "0.1.7"
- @title = "SCSS Compiler in PHP"
-
- scssphp = tools.system_command "bin/pscss < %s > %s", "css"
- build scssphp, "style.scss", "style/style.css"
-
- deploy_to "leaf@leafo.net", "www/scssphp/"
-
- add "docs/index.md"
-
diff --git a/site/style.scss b/site/style.scss
deleted file mode 100644
index 18ecc092..00000000
--- a/site/style.scss
+++ /dev/null
@@ -1,303 +0,0 @@
-
-$site_width: 640px;
-
-$light_teal: #7FC7AF;
-$teal: desaturate(#3FB8AF, 10%);
-$brown: #DAD8A7;
-$pink: darken(#FF9E9D, 10%);
-$btn_color: desaturate(#FF3D7F, 10%);
-
-::selection {
- background: red;
- color: white;
-}
-
-@mixin unselectable {
- -moz-user-select: none;
- -webkit-user-select: none;
- user-select: none;
-}
-
-@mixin grad($top, $bottom) {
- background-color: mix($top, $bottom);
- background-image: linear-gradient(bottom, $bottom 0%, $top 100%);
- background-image: -webkit-linear-gradient(bottom, $bottom 0%, $top 100%);
- background-image: -moz-linear-gradient(bottom, $bottom 0%, $top 100%);
- background-image: -o-linear-gradient(bottom, $bottom 0%, $top 100%);
- background-image: -ms-linear-gradient(bottom, $bottom 0%, $top 100%);
-}
-
-@mixin autograd($color, $amount: 10%) {
- @include grad($color, darken($color, $amount));
-}
-
-body {
- background: $pink;
- font-family: Lato, sans-serif;
-}
-
-.header, .footer, .body {
- .inner {
- width: $site_width;
- margin: 0 auto;
- }
-}
-
-.header {
- text-shadow: 0px -1px 0px darken($teal, 15%);
-
- .color {
- background: $teal url(../img/tile.png);
- border-top: 4px solid $light_teal;
- box-shadow: inset 0px 1px 0px rgba(255,255,255, 0.5), inset 0px 8px 8px -8px #37505A, inset 0px -1px 0px rgba(255,255,255, 0.3);
- }
-
- h1 {
- font-family: 'Quicksand', sans-serif;
- font-size: 40px;
- line-height: 100px;
- font-weight: normal;
- margin: 0;
-
- a {
- text-decoration: none;
- color: #EDFFF9;
-
- &:active {
- position: relative;
- top: 1px;
- }
- }
- }
-
- .nav {
- padding: 8px 0;
- font-size: 17px;
- text-shadow: none;
- background: darken($teal, 30%);
- color: $teal;
- box-shadow: inset 0px 4px 8px -4px rgba(0,0,0,0.9), inset 0px -1px 0px rgba(255,255,255, 0.8);
-
- a {
- color: lighten($teal, 40%);
- text-decoration: none;
-
- &:hover {
- text-decoration: underline;
- }
- }
-
- .social {
- float: right;
- margin-top: -2px;
- }
- }
-
- .download-area {
- float: right;
- margin-top: 25px;
- background: rgba(255,255,255, 0.3);
- border-radius: 8px;
- padding: 5px;
-
- a {
- text-decoration: none;
- }
-
- .download-button {
- $height: 8px;
- $depress: 4px;
-
- @include unselectable;
-
- color: white;
- text-align: center;
-
- @include autograd($btn_color);
-
- position: relative;
- top: -1 * $height;
-
- padding: 8px 20px;
- border-radius: 8px;
- text-shadow: none;
-
- box-shadow: 0px $height 0px darken($btn_color, 30%), inset 0px -1px 0px rgba(255,255,255, 0.2), inset 0px 1px 0px rgba(0,0,0, 0.2);
- text-shadow: 0px 1px 2px darken($btn_color, 40%);
-
- cursor: pointer;
-
- -webkit-transition: all 0.05s ease-in-out;
- -moz-transition: all 0.05s ease-in-out;
- transition: all 0.05s ease-in-out;
-
- &:hover {
- @include autograd(lighten($btn_color, 3%));
- }
-
- &:active {
- box-shadow: 0px $height - $depress 0px darken($btn_color, 30%), inset 0px -1px 0px rgba(255,255,255, 0.2), inset 0px 1px 0px rgba(0,0,0, 0.2);
- top: -1 * ($height - $depress);
- }
-
- .top {
- font-weight: bold;
- font-size: 16px;
- }
-
- .sub {
- font-size: 14px;
- }
- }
- }
-
-}
-
-.body {
- $bg_color: #FEFFED;
- $text_color: darken($brown, 60%);
- box-shadow: inset 0px 4px 8px -4px rgba(0,0,0,0.7), inset 0px -4px 8px -4px rgba(0,0,0,0.4);
- background: $bg_color;
- overflow: hidden;
- color: $text_color;
- font-size: 18px;
- padding-bottom: 20px;
-
- .inner {
- background: white;
- margin-top: 20px;
- padding: 30px 50px;
- border: 1px solid lightGrey;
- box-shadow: 0px 4px 20px rgba(0, 0, 0, 0.19);
-
- h1, h2, h3 {
- margin: 0 0 20px 0;
- }
- }
-
- h1, h2, h3 {
- text-shadow: 1px 1px 0px $bg_color, 2px 2px 0px rgba($text_color, 0.3);
- letter-spacing: -1px;
- }
-
- h3 {
- color: #4D4C3D;
- }
-
- p {
- margin: 0 0 15px 0;
- }
-
- a {
- color: #DB1C4A;
- &:hover {
- color: lighten(#DB1C4A, 10%);
- }
- }
-
- pre {
- margin: 20px 0;
- }
-}
-
-.footer {
- font-size: 16px;
- color: lighten($pink, 20%);
- text-shadow: 0px 1px 0px darken($pink, 20%);
-
- border-top: 1px dashed darken($pink, 50%);
- box-shadow: inset 0px 1px 0px rgba(255,255,255, 0.5);
- padding: 8px 0 20px 0;
-
- line-height: 150%;
-
- a {
- color: white;
- font-weight: bold;
- text-decoration: none;
- padding: 0 4px;
- border-radius: 4px;
- border: 1px solid lighten($pink, 4%);
-
- &:hover {
- background: darken($pink, 3%);
- border: 1px solid lighten($pink, 4%);
- }
- }
-}
-
-
-p {
- line-height: 150%;
- code {
- background: rgba(0,0,0, 0.1);
- border-radius: 4px;
- padding: 1px 4px;
- }
-}
-
-.comments {
- font-size: 12px;
-}
-
-.index {
- line-height: 150%;
- margin-bottom: 20px;
-
- ul {
- margin: 0;
- }
-}
-
-.highlight {
- background: #333;
- color: white;
- font-size: 14px;
- padding: 10px;
- box-shadow: 0px 1px 3px rgba(0,0,0, 0.7), inset 0px 0px 0px 1px rgba(255,255,255,0.3);
- border-radius: 2px;
- border: 1px solid #222;
-
-
- // builtins
- .nb {
- color: #FFA67C;
- }
-
- // strings
- .s, .s1, .s2, .se, .nt {
- color: #ffe898;
- }
-
- // proper names
- .nc, .vc, .bp {
- color: #98d9ff;
- }
-
- // true, false, nil
- .kc {
- color: #acfff0;
- }
-
- // function lit, braces, parens
- .nf, .kt {
- color: #9fff98;
- }
-
- .nv {
- color: #ff9898;
- }
-
- // keywords
- .k, .kd, .na {
- color: #cb98ff;
- }
-
- .c1, .c2 {
- color: #929292;
- }
-
- .m, .mi, .mf, .mh, .o {
- color: #9495ff;
- }
-}
diff --git a/site/templates/index.html b/site/templates/index.html
deleted file mode 100644
index b69e8cf9..00000000
--- a/site/templates/index.html
+++ /dev/null
@@ -1,81 +0,0 @@
-
-
-
-
- $if{"title"}[[$title - ]]scssphp
-
-
-
- $analytics{"UA-136625-1"}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/site/www/.gitignore b/site/www/.gitignore
deleted file mode 100644
index e8217972..00000000
--- a/site/www/.gitignore
+++ /dev/null
@@ -1,2 +0,0 @@
-docs/index.html
-index.html
\ No newline at end of file
diff --git a/site/www/img/tile.png b/site/www/img/tile.png
deleted file mode 100644
index ecb7149dc6e07dae7f0d8914934990ef05724d73..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001
literal 244
zcmeAS@N?(olHy`uVBq!ia0vp^93afW1|*O0@9PFqY)RhkE)4%caKYZ?lYt_f1s;*b
z3=G`DAk4@xYmNj^kiEpy*OmPayNrmS^x=@jAa$~tArU3c`MJ5Nc_lzD1A}u>YGO%h
zib8p2Nrr;Er*A-tUMf3KJi^n(F+}2W@3}y(Lke5Raw8wpPSUJuBp7`l{tC*%AJj89QNf(9B9+NRVe%W`3bYE
djp3nx7K_KUN$MMF6@mQ4;OXk;vd$@?2>=OJP@w<-
diff --git a/site/www/style/normalize.css b/site/www/style/normalize.css
deleted file mode 100644
index 8fa27e0b..00000000
--- a/site/www/style/normalize.css
+++ /dev/null
@@ -1,500 +0,0 @@
-/*! normalize.css 2012-07-07T09:50 UTC - http://github.com/necolas/normalize.css */
-
-/* ==========================================================================
- HTML5 display definitions
- ========================================================================== */
-
-/*
- * Corrects `block` display not defined in IE6/7/8/9 & FF3.
- */
-
-article,
-aside,
-details,
-figcaption,
-figure,
-footer,
-header,
-hgroup,
-nav,
-section,
-summary {
- display: block;
-}
-
-/*
- * Corrects `inline-block` display not defined in IE6/7/8/9 & FF3.
- */
-
-audio,
-canvas,
-video {
- display: inline-block;
- *display: inline;
- *zoom: 1;
-}
-
-/*
- * Prevents modern browsers from displaying `audio` without controls.
- * Remove excess height in iOS5 devices.
- */
-
-audio:not([controls]) {
- display: none;
- height: 0;
-}
-
-/*
- * Addresses styling for `hidden` attribute not present in IE7/8/9, FF3, S4.
- * Known issue: no IE6 support.
- */
-
-[hidden] {
- display: none;
-}
-
-/* ==========================================================================
- Base
- ========================================================================== */
-
-/*
- * 1. Corrects text resizing oddly in IE6/7 when body `font-size` is set using
- * `em` units.
- * 2. Prevents iOS text size adjust after orientation change, without disabling
- * user zoom.
- */
-
-html {
- font-size: 100%; /* 1 */
- -webkit-text-size-adjust: 100%; /* 2 */
- -ms-text-size-adjust: 100%; /* 2 */
-}
-
-/*
- * Addresses `font-family` inconsistency between `textarea` and other form
- * elements.
- */
-
-html,
-button,
-input,
-select,
-textarea {
- font-family: sans-serif;
-}
-
-/*
- * Addresses margins handled incorrectly in IE6/7.
- */
-
-body {
- margin: 0;
-}
-
-/* ==========================================================================
- Links
- ========================================================================== */
-
-/*
- * Addresses `outline` inconsistency between Chrome and other browsers.
- */
-
-a:focus {
- outline: thin dotted;
-}
-
-/*
- * Improves readability when focused and also mouse hovered in all browsers.
- * people.opera.com/patrickl/experiments/keyboard/test
- */
-
-a:active,
-a:hover {
- outline: 0;
-}
-
-/* ==========================================================================
- Typography
- ========================================================================== */
-
-/*
- * Addresses font sizes and margins set differently in IE6/7.
- * Addresses font sizes within `section` and `article` in FF4+, Chrome, S5.
- */
-
-h1 {
- font-size: 2em;
- margin: 0.67em 0;
-}
-
-h2 {
- font-size: 1.5em;
- margin: 0.83em 0;
-}
-
-h3 {
- font-size: 1.17em;
- margin: 1em 0;
-}
-
-h4 {
- font-size: 1em;
- margin: 1.33em 0;
-}
-
-h5 {
- font-size: 0.83em;
- margin: 1.67em 0;
-}
-
-h6 {
- font-size: 0.75em;
- margin: 2.33em 0;
-}
-
-/*
- * Addresses styling not present in IE7/8/9, S5, Chrome.
- */
-
-abbr[title] {
- border-bottom: 1px dotted;
-}
-
-/*
- * Addresses style set to `bolder` in FF3+, S4/5, Chrome.
- */
-
-b,
-strong {
- font-weight: bold;
-}
-
-blockquote {
- margin: 1em 40px;
-}
-
-/*
- * Addresses styling not present in S5, Chrome.
- */
-
-dfn {
- font-style: italic;
-}
-
-/*
- * Addresses styling not present in IE6/7/8/9.
- */
-
-mark {
- background: #ff0;
- color: #000;
-}
-
-/*
- * Addresses margins set differently in IE6/7.
- */
-
-p,
-pre {
- margin: 1em 0;
-}
-
-/*
- * Corrects font family set oddly in IE6, S4/5, Chrome.
- * en.wikipedia.org/wiki/User:Davidgothberg/Test59
- */
-
-code,
-kbd,
-pre,
-samp {
- font-family: monospace, serif;
- _font-family: 'courier new', monospace;
- font-size: 1em;
-}
-
-/*
- * Improves readability of pre-formatted text in all browsers.
- */
-
-pre {
- white-space: pre;
- white-space: pre-wrap;
- word-wrap: break-word;
-}
-
-/*
- * Addresses CSS quotes not supported in IE6/7.
- */
-
-q {
- quotes: none;
-}
-
-/*
- * Addresses `quotes` property not supported in S4.
- */
-
-q:before,
-q:after {
- content: '';
- content: none;
-}
-
-small {
- font-size: 75%;
-}
-
-/*
- * Prevents `sub` and `sup` affecting `line-height` in all browsers.
- * gist.github.com/413930
- */
-
-sub,
-sup {
- font-size: 75%;
- line-height: 0;
- position: relative;
- vertical-align: baseline;
-}
-
-sup {
- top: -0.5em;
-}
-
-sub {
- bottom: -0.25em;
-}
-
-/* ==========================================================================
- Lists
- ========================================================================== */
-
-/*
- * Addresses margins set differently in IE6/7.
- */
-
-dl,
-menu,
-ol,
-ul {
- margin: 1em 0;
-}
-
-dd {
- margin: 0 0 0 40px;
-}
-
-/*
- * Addresses paddings set differently in IE6/7.
- */
-
-menu,
-ol,
-ul {
- padding: 0 0 0 40px;
-}
-
-/*
- * Corrects list images handled incorrectly in IE7.
- */
-
-nav ul,
-nav ol {
- list-style: none;
- list-style-image: none;
-}
-
-/* ==========================================================================
- Embedded content
- ========================================================================== */
-
-/*
- * 1. Removes border when inside `a` element in IE6/7/8/9, FF3.
- * 2. Improves image quality when scaled in IE7.
- * code.flickr.com/blog/2008/11/12/on-ui-quality-the-little-things-client-side-image-resizing/
- */
-
-img {
- border: 0; /* 1 */
- -ms-interpolation-mode: bicubic; /* 2 */
-}
-
-/*
- * Corrects overflow displayed oddly in IE9.
- */
-
-svg:not(:root) {
- overflow: hidden;
-}
-
-/* ==========================================================================
- Figures
- ========================================================================== */
-
-/*
- * Addresses margin not present in IE6/7/8/9, S5, O11.
- */
-
-figure {
- margin: 0;
-}
-
-/* ==========================================================================
- Forms
- ========================================================================== */
-
-/*
- * Corrects margin displayed oddly in IE6/7.
- */
-
-form {
- margin: 0;
-}
-
-/*
- * Define consistent border, margin, and padding.
- */
-
-fieldset {
- border: 1px solid #c0c0c0;
- margin: 0 2px;
- padding: 0.35em 0.625em 0.75em;
-}
-
-/*
- * 1. Corrects color not being inherited in IE6/7/8/9.
- * 2. Corrects text not wrapping in FF3.
- * 3. Corrects alignment displayed oddly in IE6/7.
- */
-
-legend {
- border: 0; /* 1 */
- padding: 0;
- white-space: normal; /* 2 */
- *margin-left: -7px; /* 3 */
-}
-
-/*
- * 1. Corrects font size not being inherited in all browsers.
- * 2. Addresses margins set differently in IE6/7, FF3+, S5, Chrome.
- * 3. Improves appearance and consistency in all browsers.
- */
-
-button,
-input,
-select,
-textarea {
- font-size: 100%; /* 1 */
- margin: 0; /* 2 */
- vertical-align: baseline; /* 3 */
- *vertical-align: middle; /* 3 */
-}
-
-/*
- * Addresses FF3/4 setting `line-height` on `input` using `!important` in the
- * UA stylesheet.
- */
-
-button,
-input {
- line-height: normal;
-}
-
-/*
- * 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio`
- * and `video` controls.
- * 2. Corrects inability to style clickable `input` types in iOS.
- * 3. Improves usability and consistency of cursor style between image-type
- * `input` and others.
- * 4. Removes inner spacing in IE7 without affecting normal text inputs.
- * Known issue: inner spacing remains in IE6.
- */
-
-button,
-html input[type="button"], /* 1 */
-input[type="reset"],
-input[type="submit"] {
- -webkit-appearance: button; /* 2 */
- cursor: pointer; /* 3 */
- *overflow: visible; /* 4 */
-}
-
-/*
- * Re-set default cursor for disabled elements.
- */
-
-button[disabled],
-input[disabled] {
- cursor: default;
-}
-
-/*
- * 1. Addresses box sizing set to content-box in IE8/9.
- * 2. Removes excess padding in IE8/9.
- * 3. Removes excess padding in IE7.
- * Known issue: excess padding remains in IE6.
- */
-
-input[type="checkbox"],
-input[type="radio"] {
- box-sizing: border-box; /* 1 */
- padding: 0; /* 2 */
- *height: 13px; /* 3 */
- *width: 13px; /* 3 */
-}
-
-/*
- * 1. Addresses `appearance` set to `searchfield` in S5, Chrome.
- * 2. Addresses `box-sizing` set to `border-box` in S5, Chrome (include `-moz`
- * to future-proof).
- */
-
-input[type="search"] {
- -webkit-appearance: textfield; /* 1 */
- -moz-box-sizing: content-box;
- -webkit-box-sizing: content-box; /* 2 */
- box-sizing: content-box;
-}
-
-/*
- * Removes inner padding and search cancel button in S5, Chrome on OS X.
- */
-
-input[type="search"]::-webkit-search-cancel-button,
-input[type="search"]::-webkit-search-decoration {
- -webkit-appearance: none;
-}
-
-/*
- * Removes inner padding and border in FF3+.
- */
-
-button::-moz-focus-inner,
-input::-moz-focus-inner {
- border: 0;
- padding: 0;
-}
-
-/*
- * 1. Removes default vertical scrollbar in IE6/7/8/9.
- * 2. Improves readability and alignment in all browsers.
- */
-
-textarea {
- overflow: auto; /* 1 */
- vertical-align: top; /* 2 */
-}
-
-/* ==========================================================================
- Tables
- ========================================================================== */
-
-/*
- * Remove most spacing between table cells.
- */
-
-table {
- border-collapse: collapse;
- border-spacing: 0;
-}
From 5c78dec0be6c128014f9799df91942cfef1c80e3 Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Sun, 5 Jul 2015 09:49:25 -0400
Subject: [PATCH 008/534] Update links
---
.gitignore | 7 +++++--
LICENSE.md | 2 +-
README.md | 4 ++--
bin/pscss | 2 +-
classmap.php | 2 +-
composer.json | 2 +-
src/Colors.php | 2 +-
src/Compiler.php | 2 +-
src/Formatter.php | 2 +-
src/Formatter/Compact.php | 2 +-
src/Formatter/Compressed.php | 2 +-
src/Formatter/Crunched.php | 2 +-
src/Formatter/Expanded.php | 2 +-
src/Formatter/Nested.php | 2 +-
src/Parser.php | 2 +-
src/Server.php | 2 +-
src/Version.php | 2 +-
tests/ApiTest.php | 2 +-
tests/ExceptionTest.php | 2 +-
tests/FailingTest.php | 2 +-
tests/InputTest.php | 2 +-
tests/ScssTest.php | 2 +-
tests/ServerTest.php | 2 +-
23 files changed, 28 insertions(+), 25 deletions(-)
diff --git a/.gitignore b/.gitignore
index 6eec948a..abc73877 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,6 +1,9 @@
-/*.scss
-/*.css
.sass-cache
+composer.lock
+serve.sh
+/*.css
+/*.scss
+/_site/
/sass/
/compass/
/vendor/
diff --git a/LICENSE.md b/LICENSE.md
index 03f8a426..2f5412f9 100644
--- a/LICENSE.md
+++ b/LICENSE.md
@@ -1,4 +1,4 @@
-Copyright (c) 2012 Leaf Corcoran, http://leafo.net/scssphp
+Copyright (c) 2015 Leaf Corcoran, http://leafo.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/README.md b/README.md
index 94a8b78b..84d81598 100644
--- a/README.md
+++ b/README.md
@@ -1,5 +1,5 @@
# scssphp v0.1.7
-###
+###
[](http://travis-ci.org/leafo/scssphp)
@@ -8,7 +8,7 @@
It primarily implements SCSS 3.2.16, with some 3.3.x/3.4.x compatibility. It does not implement the SASS syntax, only the SCSS
syntax.
-Checkout the homepage, , for directions on how to use.
+Checkout the homepage, , for directions on how to use.
## Running Tests
diff --git a/bin/pscss b/bin/pscss
index 10328d7b..8aaf96d4 100755
--- a/bin/pscss
+++ b/bin/pscss
@@ -7,7 +7,7 @@
*
* @license http://opensource.org/licenses/MIT MIT
*
- * @link http://leafo.net/scssphp
+ * @link http://leafo.github.io/scssphp
*/
error_reporting(E_ALL);
diff --git a/classmap.php b/classmap.php
index 89b881cd..267eecd6 100644
--- a/classmap.php
+++ b/classmap.php
@@ -8,7 +8,7 @@
*
* @license http://opensource.org/licenses/MIT MIT
*
- * @link http://leafo.net/scssphp
+ * @link http://leafo.github.io/scssphp
*/
/**
diff --git a/composer.json b/composer.json
index 9cd473be..b933680b 100644
--- a/composer.json
+++ b/composer.json
@@ -3,7 +3,7 @@
"type": "library",
"description": "scssphp is a compiler for SCSS written in PHP.",
"keywords": ["css", "stylesheet", "scss", "sass", "less"],
- "homepage": "http://leafo.net/scssphp/",
+ "homepage": "http://leafo.github.io/scssphp/",
"license": [
"MIT"
],
diff --git a/src/Colors.php b/src/Colors.php
index 20ac7c87..dd32be21 100644
--- a/src/Colors.php
+++ b/src/Colors.php
@@ -6,7 +6,7 @@
*
* @license http://opensource.org/licenses/MIT MIT
*
- * @link http://leafo.net/scssphp
+ * @link http://leafo.github.io/scssphp
*/
namespace Leafo\ScssPhp;
diff --git a/src/Compiler.php b/src/Compiler.php
index 081e5023..7c4d3431 100644
--- a/src/Compiler.php
+++ b/src/Compiler.php
@@ -6,7 +6,7 @@
*
* @license http://opensource.org/licenses/MIT MIT
*
- * @link http://leafo.net/scssphp
+ * @link http://leafo.github.io/scssphp
*/
namespace Leafo\ScssPhp;
diff --git a/src/Formatter.php b/src/Formatter.php
index 05c04b07..b9fb18f8 100644
--- a/src/Formatter.php
+++ b/src/Formatter.php
@@ -6,7 +6,7 @@
*
* @license http://opensource.org/licenses/MIT MIT
*
- * @link http://leafo.net/scssphp
+ * @link http://leafo.github.io/scssphp
*/
namespace Leafo\ScssPhp;
diff --git a/src/Formatter/Compact.php b/src/Formatter/Compact.php
index fc5f3013..29874c96 100644
--- a/src/Formatter/Compact.php
+++ b/src/Formatter/Compact.php
@@ -6,7 +6,7 @@
*
* @license http://opensource.org/licenses/MIT MIT
*
- * @link http://leafo.net/scssphp
+ * @link http://leafo.github.io/scssphp
*/
namespace Leafo\ScssPhp\Formatter;
diff --git a/src/Formatter/Compressed.php b/src/Formatter/Compressed.php
index b40161b4..c95b68b3 100644
--- a/src/Formatter/Compressed.php
+++ b/src/Formatter/Compressed.php
@@ -6,7 +6,7 @@
*
* @license http://opensource.org/licenses/MIT MIT
*
- * @link http://leafo.net/scssphp
+ * @link http://leafo.github.io/scssphp
*/
namespace Leafo\ScssPhp\Formatter;
diff --git a/src/Formatter/Crunched.php b/src/Formatter/Crunched.php
index c8170291..1227c122 100644
--- a/src/Formatter/Crunched.php
+++ b/src/Formatter/Crunched.php
@@ -6,7 +6,7 @@
*
* @license http://opensource.org/licenses/MIT MIT
*
- * @link http://leafo.net/scssphp
+ * @link http://leafo.github.io/scssphp
*/
namespace Leafo\ScssPhp\Formatter;
diff --git a/src/Formatter/Expanded.php b/src/Formatter/Expanded.php
index a8fafc95..fbf85c1e 100644
--- a/src/Formatter/Expanded.php
+++ b/src/Formatter/Expanded.php
@@ -6,7 +6,7 @@
*
* @license http://opensource.org/licenses/MIT MIT
*
- * @link http://leafo.net/scssphp
+ * @link http://leafo.github.io/scssphp
*/
namespace Leafo\ScssPhp\Formatter;
diff --git a/src/Formatter/Nested.php b/src/Formatter/Nested.php
index 084fa6bb..1bad2f27 100644
--- a/src/Formatter/Nested.php
+++ b/src/Formatter/Nested.php
@@ -6,7 +6,7 @@
*
* @license http://opensource.org/licenses/MIT MIT
*
- * @link http://leafo.net/scssphp
+ * @link http://leafo.github.io/scssphp
*/
namespace Leafo\ScssPhp\Formatter;
diff --git a/src/Parser.php b/src/Parser.php
index f35a18a3..cb37332e 100644
--- a/src/Parser.php
+++ b/src/Parser.php
@@ -6,7 +6,7 @@
*
* @license http://opensource.org/licenses/MIT MIT
*
- * @link http://leafo.net/scssphp
+ * @link http://leafo.github.io/scssphp
*/
namespace Leafo\ScssPhp;
diff --git a/src/Server.php b/src/Server.php
index 8a764dd5..c2304dd4 100644
--- a/src/Server.php
+++ b/src/Server.php
@@ -6,7 +6,7 @@
*
* @license http://opensource.org/licenses/MIT MIT
*
- * @link http://leafo.net/scssphp
+ * @link http://leafo.github.io/scssphp
*/
namespace Leafo\ScssPhp;
diff --git a/src/Version.php b/src/Version.php
index 95e7b5f2..e457776a 100644
--- a/src/Version.php
+++ b/src/Version.php
@@ -6,7 +6,7 @@
*
* @license http://opensource.org/licenses/MIT MIT
*
- * @link http://leafo.net/scssphp
+ * @link http://leafo.github.io/scssphp
*/
namespace Leafo\ScssPhp;
diff --git a/tests/ApiTest.php b/tests/ApiTest.php
index 17fc9815..c4f18ba7 100644
--- a/tests/ApiTest.php
+++ b/tests/ApiTest.php
@@ -6,7 +6,7 @@
*
* @license http://opensource.org/licenses/MIT MIT
*
- * @link http://leafo.net/scssphp
+ * @link http://leafo.github.io/scssphp
*/
namespace Leafo\ScssPhp\Tests;
diff --git a/tests/ExceptionTest.php b/tests/ExceptionTest.php
index 3b58d01e..50255f40 100644
--- a/tests/ExceptionTest.php
+++ b/tests/ExceptionTest.php
@@ -6,7 +6,7 @@
*
* @license http://opensource.org/licenses/MIT MIT
*
- * @link http://leafo.net/scssphp
+ * @link http://leafo.github.io/scssphp
*/
namespace Leafo\ScssPhp\Tests;
diff --git a/tests/FailingTest.php b/tests/FailingTest.php
index 1343b5cc..c71556ee 100644
--- a/tests/FailingTest.php
+++ b/tests/FailingTest.php
@@ -6,7 +6,7 @@
*
* @license http://opensource.org/licenses/MIT MIT
*
- * @link http://leafo.net/scssphp
+ * @link http://leafo.github.io/scssphp
*/
namespace Leafo\ScssPhp\Tests;
diff --git a/tests/InputTest.php b/tests/InputTest.php
index fa2b28cc..709a9596 100644
--- a/tests/InputTest.php
+++ b/tests/InputTest.php
@@ -6,7 +6,7 @@
*
* @license http://opensource.org/licenses/MIT MIT
*
- * @link http://leafo.net/scssphp
+ * @link http://leafo.github.io/scssphp
*/
namespace Leafo\ScssPhp\Tests;
diff --git a/tests/ScssTest.php b/tests/ScssTest.php
index e402511f..f4d518ad 100644
--- a/tests/ScssTest.php
+++ b/tests/ScssTest.php
@@ -6,7 +6,7 @@
*
* @license http://opensource.org/licenses/MIT MIT
*
- * @link http://leafo.net/scssphp
+ * @link http://leafo.github.io/scssphp
*/
namespace Leafo\ScssPhp\Tests;
diff --git a/tests/ServerTest.php b/tests/ServerTest.php
index 88a1da69..2cecdd97 100644
--- a/tests/ServerTest.php
+++ b/tests/ServerTest.php
@@ -6,7 +6,7 @@
*
* @license http://opensource.org/licenses/MIT MIT
*
- * @link http://leafo.net/scssphp
+ * @link http://leafo.github.io/scssphp
*/
namespace Leafo\ScssPhp\Tests;
From a561fe7d969ff30ad7db51aacb1f4ffc5ccfa930 Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Mon, 6 Jul 2015 00:24:08 -0400
Subject: [PATCH 009/534] fixes 288 - add .phar (box) support
---
.gitignore | 2 +-
Makefile | 3 +++
README.md | 3 ++-
box.json.dist | 13 +++++++++++++
composer.json | 3 ++-
package.sh | 24 ------------------------
6 files changed, 21 insertions(+), 27 deletions(-)
create mode 100644 box.json.dist
delete mode 100755 package.sh
diff --git a/.gitignore b/.gitignore
index abc73877..4ffba003 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,6 +1,6 @@
.sass-cache
composer.lock
-serve.sh
+pscss.phar
/*.css
/*.scss
/_site/
diff --git a/Makefile b/Makefile
index 03d0bf03..44bf8c9e 100644
--- a/Makefile
+++ b/Makefile
@@ -1,2 +1,5 @@
test:
vendor/bin/phpunit --colors tests
+
+phar:
+ vendor/bin/box build -v
diff --git a/README.md b/README.md
index 84d81598..86b0b262 100644
--- a/README.md
+++ b/README.md
@@ -1,7 +1,8 @@
# scssphp v0.1.7
###
-[](http://travis-ci.org/leafo/scssphp)
+[](http://travis-ci.org/leafo/scssphp)
+[](https://packagist.org/packages/leafo/scssphp)
`scssphp` is a compiler for SCSS written in PHP.
diff --git a/box.json.dist b/box.json.dist
new file mode 100644
index 00000000..9e61a65e
--- /dev/null
+++ b/box.json.dist
@@ -0,0 +1,13 @@
+{
+ "chmod": "0755",
+ "files": [
+ "LICENSE.md",
+ "classmap.php",
+ "scss.inc.php"
+ ],
+ "directories": ["src"],
+ "main": "bin/pscss",
+ "output": "pscss.phar",
+ "compactors": "Herrera\\Box\\Compactor\\Php",
+ "stub": true
+}
diff --git a/composer.json b/composer.json
index b933680b..3c6ef843 100644
--- a/composer.json
+++ b/composer.json
@@ -26,7 +26,8 @@
},
"require-dev": {
"squizlabs/php_codesniffer": "~2.3",
- "phpunit/phpunit": "3.7.*"
+ "phpunit/phpunit": "~3.7",
+ "kherge/box": "~2.5"
},
"bin": ["bin/pscss"]
}
diff --git a/package.sh b/package.sh
deleted file mode 100755
index 02a528da..00000000
--- a/package.sh
+++ /dev/null
@@ -1,24 +0,0 @@
-#!/bin/sh
-
-# creates tar.gz for current version
-
-TARGET_DIR="site/www/src"
-
-VERSION=`./pscss -v | sed -n 's/^v\(.*\)$/\1/p'`
-OUT_DIR="tmp/scssphp"
-TMP=`dirname $OUT_DIR`
-
-mkdir -p $OUT_DIR
-tar -c `git ls-files` | tar -C $OUT_DIR -x
-
-rm $OUT_DIR/.gitignore
-rm $OUT_DIR/package.sh
-rm $OUT_DIR/todo
-rm -r $OUT_DIR/site
-
-OUT_PATH="$TARGET_DIR/scssphp-$VERSION.tar.gz"
-tar -czf "$OUT_PATH" -C $TMP scssphp/
-echo "Wrote $OUT_PATH"
-
-rm -r $TMP
-
From 6f322792af08f6336f210b4448f80e592a4ac97d Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Mon, 6 Jul 2015 10:14:21 -0400
Subject: [PATCH 010/534] Delete "todo"; moved items into Github issues
---
todo | 47 -----------------------------------------------
1 file changed, 47 deletions(-)
delete mode 100644 todo
diff --git a/todo b/todo
deleted file mode 100644
index ab271c5e..00000000
--- a/todo
+++ /dev/null
@@ -1,47 +0,0 @@
-
-* change all calls to reduce to not suppress division where appropriate
-* store count in elements so we can have position of compile time errors
-* failed parsing paths can add comments early
-
-* fix indentation for @content, see @content tests
-
-misc:
-
-# sequence merging:
-
-a b c d { color: red; }
-x y z w { @extend a; }
-
- a b c d, x y z w b c d { color: red; }
-
-
-a b c d { color: red; }
-x y z w { @extend b; }
-
- a b c d, a x y z w c d, x y z a w c d { color: red; }
-
-
-a b c d { color: red; }
-x y z w { @extend c; }
-
- a b c d, a b x y z w d, x y z a b w d { color: red; }
-
- x y z a b w d
-
- before: a b
- after: d
- new: x y z w
-
-
-a b c d { color: red; }
-x y z w { @extend d; }
-
- a b c d, a b c x y z w, x y z a b c w { color: red; }
-
-
-->> new[:-1] . before . new[-1] . after
-
- new.len > 1
- before not empty
-
-
From 08ab020a04c396601dadd471b0b1938aea3f4266 Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Wed, 8 Jul 2015 08:42:10 -0400
Subject: [PATCH 011/534] #288 - build phar even phar.readonly
---
Makefile | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Makefile b/Makefile
index 44bf8c9e..c608f8e1 100644
--- a/Makefile
+++ b/Makefile
@@ -2,4 +2,4 @@ test:
vendor/bin/phpunit --colors tests
phar:
- vendor/bin/box build -v
+ php -dphar.readonly=0 vendor/bin/box build -v
From eae2783776e83d02987294c4d5c3752bdfbe508d Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Wed, 8 Jul 2015 08:43:23 -0400
Subject: [PATCH 012/534] #294 pscss parseArgument() enhancement
---
bin/pscss | 33 +++++++++++++++++++++++++++------
1 file changed, 27 insertions(+), 6 deletions(-)
diff --git a/bin/pscss b/bin/pscss
index 8aaf96d4..ef8f2fc4 100755
--- a/bin/pscss
+++ b/bin/pscss
@@ -31,9 +31,30 @@ $changeDir = false;
$debugInfo = false;
$lineNumbers = false;
-function parseArgument($argument, $options) {
- if (preg_match('/^(?:' . implode('|', (array) $options) . ')=?(.*)/', $argument, $matches)) {
- return $matches[1] === '' ? false : $matches[1];
+/**
+ * Parse argument
+ *
+ * @param integer $i
+ * @param array $options
+ *
+ * @return string|false|null
+ */
+function parseArgument(&$i, $options) {
+ global $argc;
+ global $argv;
+
+ if (! preg_match('/^(?:' . implode('|', (array) $options) . ')=?(.*)/', $argv[$i], $matches)) {
+ return;
+ }
+
+ if (strlen($matches[1])) {
+ return $matches[1];
+ }
+
+ if ($i + 1 < $argc) {
+ $i++;
+
+ return $argv[$i];
}
}
@@ -78,21 +99,21 @@ EOT;
continue;
}
- $value = parseArgument($argv[$i], array('-f', '--style'));
+ $value = parseArgument($i, array('-f', '--style'));
if (isset($value)) {
$style = $value;
continue;
}
- $value = parseArgument($argv[$i], array('-i', '--load_paths'));
+ $value = parseArgument($i, array('-i', '--load_paths'));
if (isset($value)) {
$loadPaths = $value;
continue;
}
- $value = parseArgument($argv[$i], array('-p', '--precision'));
+ $value = parseArgument($i, array('-p', '--precision'));
if (isset($value)) {
$precision = $value;
From e6582d9ae67a86c670e2770934976166876bf807 Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Fri, 10 Jul 2015 20:16:19 -0400
Subject: [PATCH 013/534] bin/pscss: update docblock
---
bin/pscss | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/bin/pscss b/bin/pscss
index ef8f2fc4..9ef230f8 100755
--- a/bin/pscss
+++ b/bin/pscss
@@ -37,7 +37,7 @@ $lineNumbers = false;
* @param integer $i
* @param array $options
*
- * @return string|false|null
+ * @return string|null
*/
function parseArgument(&$i, $options) {
global $argc;
From 1164b841f039df25ee6fd88a35bf1aadfece1454 Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Fri, 17 Jul 2015 09:09:16 -0400
Subject: [PATCH 014/534] Fixes #296 lighten() and darken() compatibility
update
---
scss.inc.php | 2 ++
src/Compat/Range.php | 47 ++++++++++++++++++++++++++++++++++++++
src/Compiler.php | 17 +++++++++-----
src/Util.php | 54 ++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 114 insertions(+), 6 deletions(-)
create mode 100644 src/Compat/Range.php
create mode 100644 src/Util.php
diff --git a/scss.inc.php b/scss.inc.php
index a49f7c9f..7d2192fe 100644
--- a/scss.inc.php
+++ b/scss.inc.php
@@ -5,6 +5,7 @@
if ( ! class_exists('scssc')) {
include_once __DIR__ . '/src/Colors.php';
+ include_once __DIR__ . '/src/Compat/Range.php';
include_once __DIR__ . '/src/Compiler.php';
include_once __DIR__ . '/src/Formatter.php';
include_once __DIR__ . '/src/Formatter/Compact.php';
@@ -13,6 +14,7 @@
include_once __DIR__ . '/src/Formatter/Expanded.php';
include_once __DIR__ . '/src/Formatter/Nested.php';
include_once __DIR__ . '/src/Parser.php';
+ include_once __DIR__ . '/src/Util.php';
include_once __DIR__ . '/src/Version.php';
include_once __DIR__ . '/src/Server.php';
include_once __DIR__ . '/classmap.php';
diff --git a/src/Compat/Range.php b/src/Compat/Range.php
new file mode 100644
index 00000000..b1752878
--- /dev/null
+++ b/src/Compat/Range.php
@@ -0,0 +1,47 @@
+
+ */
+class Range
+{
+ public $first;
+ public $last;
+
+ /**
+ * Initialize range
+ *
+ * @param integer|float $first
+ * @param integer|float $last
+ */
+ public function __construct($first, $last)
+ {
+ $this->first = $first;
+ $this->last = $last;
+ }
+
+ /**
+ * Test for inclusion in range
+ *
+ * @param integer|float $value
+ *
+ * @return boolean
+ */
+ public function includes($value)
+ {
+ return $value >= $this->first && $value <= $this->last;
+ }
+}
diff --git a/src/Compiler.php b/src/Compiler.php
index 7c4d3431..665ef6ae 100644
--- a/src/Compiler.php
+++ b/src/Compiler.php
@@ -12,7 +12,9 @@
namespace Leafo\ScssPhp;
use Leafo\ScssPhp\Colors;
+use Leafo\ScssPhp\Compat\Range;
use Leafo\ScssPhp\Parser;
+use Leafo\ScssPhp\Util;
/**
* The scss compiler and parser.
@@ -725,7 +727,7 @@ protected function mergeMediaTypes($type1, $type2)
}
if ($m1 == 'not' && $m2 == 'not') {
- # CSS has no way of representing "neither screen nor print"
+ // CSS has no way of representing "neither screen nor print"
if ($t1 != $t2) {
return null;
}
@@ -986,7 +988,8 @@ protected function compileChild($child, $out)
$this->compileChildren($prefixed, $out);
break;
- case 'include': // including a mixin
+ case 'include':
+ // including a mixin
list(, $name, $argValues, $content) = $child;
$mixin = $this->get(self::$namespaces['mixin'] . $name, false);
@@ -1639,7 +1642,8 @@ public function compileValue($value)
});
return '(' . implode(', ', $filtered) . ')';
- case 'interpolated': # node created by extractInterpolation
+ case 'interpolated':
+ // node created by extractInterpolation
list(, $interpolate, $left, $right) = $value;
list(,, $whiteLeft, $whiteRight) = $interpolate;
@@ -1651,7 +1655,8 @@ public function compileValue($value)
return $left . $this->compileValue($interpolate) . $right;
- case 'interpolate': # raw parse node
+ case 'interpolate':
+ // raw parse node
list(, $exp) = $value;
// strip quotes if it's a string
@@ -2855,7 +2860,7 @@ protected function libAdjustHue($args)
protected function libLighten($args)
{
$color = $this->assertColor($args[0]);
- $amount = 100*$this->coercePercent($args[1]);
+ $amount = Util::checkRange('amount', new Range(0, 100), $args[1], '%');
return $this->adjustHsl($color, 3, $amount);
}
@@ -2864,7 +2869,7 @@ protected function libLighten($args)
protected function libDarken($args)
{
$color = $this->assertColor($args[0]);
- $amount = 100*$this->coercePercent($args[1]);
+ $amount = Util::checkRange('amount', new Range(0, 100), $args[1], '%');
return $this->adjustHsl($color, 3, -$amount);
}
diff --git a/src/Util.php b/src/Util.php
new file mode 100644
index 00000000..a3187457
--- /dev/null
+++ b/src/Util.php
@@ -0,0 +1,54 @@
+
+ */
+class Util
+{
+ /**
+ * Asserts that `value` falls within `range` (inclusive), leaving
+ * room for slight floating-point errors.
+ *
+ * @param string $name The name of the value. Used in the error message.
+ * @param 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.
+ */
+ public static function checkRange($name, Range $range, $value, $unit = '')
+ {
+ $val = $value[1];
+ $grace = new Range(-0.00001, 0.00001);
+
+ if ($range->includes($val)) {
+ return $val;
+ }
+
+ if ($grace->includes($val - $range->first)) {
+ return $range->first;
+ }
+
+ if ($grace->includes($val - $range->last)) {
+ return $range->last;
+ }
+
+ throw new \Exception("$name {$val} must be between {$range->first} and {$range->last}$unit");
+ }
+}
From 8a1931574e4f1303acdf0f3803db483ee1be0b61 Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Fri, 17 Jul 2015 13:59:41 -0400
Subject: [PATCH 015/534] quick fixes #298
---
bin/pscss | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/bin/pscss b/bin/pscss
index 9ef230f8..4ef6d389 100755
--- a/bin/pscss
+++ b/bin/pscss
@@ -148,7 +148,7 @@ if ($inputFile) {
if ($dumpTree) {
$parser = new Parser($inputFile ?: 'STDIN');
- print_r($parser->parse($data));
+ print_r(json_decode(json_encode($parser->parse($data)), true));
exit();
}
From 2ad26c0dae96099e46c8b528444055496832a464 Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Fri, 17 Jul 2015 15:43:55 -0400
Subject: [PATCH 016/534] fix phpcs errors
---
tests/ScssTest.php | 21 ++++++++++++++-------
1 file changed, 14 insertions(+), 7 deletions(-)
diff --git a/tests/ScssTest.php b/tests/ScssTest.php
index f4d518ad..96f0d76e 100644
--- a/tests/ScssTest.php
+++ b/tests/ScssTest.php
@@ -70,7 +70,8 @@ public function provideTests()
$line = trim($lines[$i]);
switch ($state) {
- case 0: // outside of function
+ case 0:
+ // outside of function
if (preg_match('/^\s*def test_([a-z_]+)/', $line, $matches)) {
$state = 1; // enter function
$name = $matches[1];
@@ -79,7 +80,8 @@ public function provideTests()
break;
- case 1: // inside function
+ case 1:
+ // inside function
if ($line === '' || $line[0] === '#') {
continue;
}
@@ -173,7 +175,8 @@ public function provideTests()
break;
- case 2: // get css
+ case 2:
+ // get css
if (preg_match('/^CSS\s*$/', $line)) {
$state = 3; // get scss
continue;
@@ -183,7 +186,8 @@ public function provideTests()
break;
- case 3: // get scss
+ case 3:
+ // get scss
if (preg_match('/^SCSS\s*$/', $line)) {
$state = 1; // end of parameter list
continue;
@@ -193,7 +197,8 @@ public function provideTests()
break;
- case 4: // inside block
+ case 4:
+ // inside block
if (preg_match('/^\s*end\s*$/', $line)) {
$state = 1; // end block
continue;
@@ -206,7 +211,8 @@ public function provideTests()
break;
- case 5: // consume parameters
+ case 5:
+ // consume parameters
if (preg_match('/^SCSS\s*$/', $line)) {
$state = 4; // end of parameter list
continue;
@@ -214,7 +220,8 @@ public function provideTests()
break;
- case 6: // consume parameters
+ case 6:
+ // consume parameters
if (preg_match('/^S[AC]SS\s*$/', $line)) {
$state = 1; // end of parameter list
continue;
From a3bab0dd9046da2c1537ddbee8b205d7b02c9880 Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Fri, 17 Jul 2015 15:44:24 -0400
Subject: [PATCH 017/534] str-slice() compatibility when start-at or ends-at
are 0; Sass strings start at index 1
---
src/Compiler.php | 11 ++++++++---
1 file changed, 8 insertions(+), 3 deletions(-)
diff --git a/src/Compiler.php b/src/Compiler.php
index 665ef6ae..a145c85b 100644
--- a/src/Compiler.php
+++ b/src/Compiler.php
@@ -96,6 +96,7 @@ class Compiler
static public $selfSelector = array('self');
static public $emptyList = array('list', '', array());
static public $emptyMap = array('map', array(), array());
+ static public $emptyString = array('string', '"', array());
protected $importPaths = array('');
protected $importCache = array();
@@ -3350,13 +3351,17 @@ protected function libStrLength($args)
protected static $libStrSlice = array('string', 'start-at', 'end-at');
protected function libStrSlice($args)
{
+ if ($args[2][1] == 0) {
+ return self::$emptyString;
+ }
+
$string = $this->coerceString($args[0]);
$stringContent = $this->compileStringContent($string);
- list(, $start) = $args[1];
- list(, $end) = $args[2];
+ $start = (int) $args[1][1] ?: 1;
+ $end = (int) $args[2][1];
- $string[2] = array(substr($stringContent, $start - 1, $end - $start + 1));
+ $string[2] = array(substr($stringContent, $start - 1, $end < 0 ? $end : $end - $start + 1));
return $string;
}
From 358260af3f3bb761bbecbdd377d3fb499038e660 Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Fri, 17 Jul 2015 15:48:12 -0400
Subject: [PATCH 018/534] opNeq (!=) compatibility
---
src/Compiler.php | 11 ++++++++++-
1 file changed, 10 insertions(+), 1 deletion(-)
diff --git a/src/Compiler.php b/src/Compiler.php
index a145c85b..d673c7fd 100644
--- a/src/Compiler.php
+++ b/src/Compiler.php
@@ -1503,7 +1503,8 @@ protected function opEq($left, $right)
$lStr[1] = '';
$rStr[1] = '';
- return $this->toBool($this->compileValue($lStr) == $this->compileValue($rStr));
+ $left = $this->compileValue($lStr);
+ $right = $this->compileValue($rStr);
}
return $this->toBool($left == $right);
@@ -1511,6 +1512,14 @@ protected function opEq($left, $right)
protected function opNeq($left, $right)
{
+ if (($lStr = $this->coerceString($left)) && ($rStr = $this->coerceString($right))) {
+ $lStr[1] = '';
+ $rStr[1] = '';
+
+ $left = $this->compileValue($lStr);
+ $right = $this->compileValue($rStr);
+ }
+
return $this->toBool($left != $right);
}
From 06972a323ae778b5830c7e0a5ca56a31680decd9 Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Fri, 17 Jul 2015 15:50:07 -0400
Subject: [PATCH 019/534] increase compatibility when function call is an
argument
---
src/Compiler.php | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/src/Compiler.php b/src/Compiler.php
index d673c7fd..0c651bc5 100644
--- a/src/Compiler.php
+++ b/src/Compiler.php
@@ -1688,6 +1688,12 @@ public function compileValue($value)
}
}
+ protected function flattenList($list)
+ {
+ // temporary
+ return $this->compileValue($list);
+ }
+
protected function compileStringContent($string)
{
$parts = array();
@@ -2395,6 +2401,8 @@ protected function coerceString($value)
switch ($value[0]) {
case 'string':
return $value;
+ case 'function':
+ return array('string', '', array($value[1] . '(' . $this->flattenList($value[2]) . ')'));
case 'keyword':
return array('string', '', array($value[1]));
}
@@ -3277,6 +3285,8 @@ protected function libTypeOf($args)
return 'color';
}
+ // fall-thru
+ case 'function':
return 'string';
default:
return $value[0];
From f987527895167de36ae63b0a9d874a5c18b45fe2 Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Fri, 17 Jul 2015 16:51:42 -0400
Subject: [PATCH 020/534] @return inside of @each wasn't handled; fixes
Bourbon's contains() mixin
---
src/Compiler.php | 13 +++++++++++--
tests/inputs/looping.scss | 20 ++++++++++++++++++++
tests/outputs/looping.css | 6 ++++++
tests/outputs_numbered/looping.css | 6 ++++++
4 files changed, 43 insertions(+), 2 deletions(-)
diff --git a/src/Compiler.php b/src/Compiler.php
index 0c651bc5..da42ea59 100644
--- a/src/Compiler.php
+++ b/src/Compiler.php
@@ -919,6 +919,7 @@ protected function compileChild($child, $out)
$list = $this->coerceList($this->reduce($each->list));
foreach ($list[2] as $item) {
$this->pushEnv();
+
if (count($each->vars) == 1) {
$this->set($each->vars[0], $item);
} else {
@@ -927,9 +928,13 @@ protected function compileChild($child, $out)
$this->set($var, isset($values[$i]) ? $values[$i] : self::$null);
}
}
- // TODO: allow return from here?
- $this->compileChildren($each->children, $out);
+
+ $ret = $this->compileChildren($each->children, $out);
$this->popEnv();
+
+ if ($ret) {
+ return $ret;
+ }
}
break;
case 'while':
@@ -937,6 +942,7 @@ protected function compileChild($child, $out)
while ($this->isTruthy($this->reduce($while->cond, true))) {
$ret = $this->compileChildren($while->children, $out);
+
if ($ret) {
return $ret;
}
@@ -1329,6 +1335,9 @@ public function normalizeValue($value)
return $value;
+ case 'string':
+ return array($value[0], '"', $value[2]);
+
case 'number':
return $this->normalizeNumber($value);
diff --git a/tests/inputs/looping.scss b/tests/inputs/looping.scss
index 98091a04..d0325dc0 100644
--- a/tests/inputs/looping.scss
+++ b/tests/inputs/looping.scss
@@ -64,3 +64,23 @@ $j: null;
.item { width: 2em; }
$j: false;
}
+
+@function contains($list, $values...) {
+ @each $value in $values {
+ @if type-of(index($list, $value)) != "number" {
+ @return false;
+ }
+ }
+ @return true;
+}
+
+@function is-number($value) {
+ @return contains("0" "1" "2" "3" "4" "5" "6" "7" "8" "9" 0 1 2 3 4 5 6 7 8 9, $value);
+}
+
+div {
+ a: is-number('red');
+ b: is-number('1');
+ c: is-number("3");
+ c: is-number(5);
+}
diff --git a/tests/outputs/looping.css b/tests/outputs/looping.css
index 05c0eab6..2836f70d 100644
--- a/tests/outputs/looping.css
+++ b/tests/outputs/looping.css
@@ -55,3 +55,9 @@ pre {
cool: 5;
cool: 4;
cool: 3; }
+
+div {
+ a: false;
+ b: true;
+ c: true;
+ c: true; }
diff --git a/tests/outputs_numbered/looping.css b/tests/outputs_numbered/looping.css
index 89dcccfd..98838286 100644
--- a/tests/outputs_numbered/looping.css
+++ b/tests/outputs_numbered/looping.css
@@ -59,3 +59,9 @@ pre {
cool: 5;
cool: 4;
cool: 3; }
+/* line 81, inputs/looping.scss */
+div {
+ a: false;
+ b: true;
+ c: true;
+ c: true; }
From 1ddf53910e6d51fe3b7687bcdef8dd37448e2a95 Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Fri, 17 Jul 2015 19:10:44 -0400
Subject: [PATCH 021/534] index() - 3.4 compatibility (note: compat-buster)
---
src/Compiler.php | 10 +++++++++-
tests/inputs/list.scss | 8 +++++++-
tests/outputs/builtins.css | 3 ---
tests/outputs/list.css | 4 ++++
tests/outputs_numbered/builtins.css | 3 ---
tests/outputs_numbered/list.css | 4 ++++
6 files changed, 24 insertions(+), 8 deletions(-)
diff --git a/src/Compiler.php b/src/Compiler.php
index da42ea59..6e90ee68 100644
--- a/src/Compiler.php
+++ b/src/Compiler.php
@@ -2579,6 +2579,14 @@ protected function libIndex($args)
{
list($list, $value) = $args;
+ if ($value[0] == 'map') {
+ return self::$null;
+ }
+
+ if ($list[0] === 'map') {
+ $list = $this->coerceList($list, ' ');
+ }
+
if ($list[0] !== 'list') {
return self::$null;
}
@@ -2591,7 +2599,7 @@ protected function libIndex($args)
$key = array_search($this->normalizeValue($value), $values);
- return false === $key ? false : $key + 1;
+ return false === $key ? self::$null : $key + 1;
}
protected static $libRgb = array('red', 'green', 'blue');
diff --git a/tests/inputs/list.scss b/tests/inputs/list.scss
index afeb7426..04b825c2 100644
--- a/tests/inputs/list.scss
+++ b/tests/inputs/list.scss
@@ -12,4 +12,10 @@ $list: join($list, (red, blue), comma);
p {
background: linear-gradient($list);
-}
\ No newline at end of file
+}
+
+div {
+x: index(1px solid red, solid);
+y: index(1px solid red, dashed);
+z: index((width: 10px, height: 20px), (height 20px));
+}
diff --git a/tests/outputs/builtins.css b/tests/outputs/builtins.css
index c7b5366c..84c6de27 100644
--- a/tests/outputs/builtins.css
+++ b/tests/outputs/builtins.css
@@ -77,12 +77,9 @@
hello: one, two, three, hello, world, what, is, going;
hello: one, two, three, hello;
index: 2;
- index: false;
index: 3;
index: 1;
- index: false;
index: 1;
- index: false;
index: 2;
index: 2;
index: 1;
diff --git a/tests/outputs/list.css b/tests/outputs/list.css
index 4e547296..aa891ab8 100644
--- a/tests/outputs/list.css
+++ b/tests/outputs/list.css
@@ -5,3 +5,7 @@ div {
p {
background: linear-gradient(red, blue); }
+
+div {
+ x: 2;
+ z: 2; }
diff --git a/tests/outputs_numbered/builtins.css b/tests/outputs_numbered/builtins.css
index e57b16e2..954e77d4 100644
--- a/tests/outputs_numbered/builtins.css
+++ b/tests/outputs_numbered/builtins.css
@@ -78,12 +78,9 @@
hello: one, two, three, hello, world, what, is, going;
hello: one, two, three, hello;
index: 2;
- index: false;
index: 3;
index: 1;
- index: false;
index: 1;
- index: false;
index: 2;
index: 2;
index: 1;
diff --git a/tests/outputs_numbered/list.css b/tests/outputs_numbered/list.css
index f5259974..97aaafa5 100644
--- a/tests/outputs_numbered/list.css
+++ b/tests/outputs_numbered/list.css
@@ -6,3 +6,7 @@ div {
/* line 13, inputs/list.scss */
p {
background: linear-gradient(red, blue); }
+/* line 17, inputs/list.scss */
+div {
+ x: 2;
+ z: 2; }
From 977e8783df581da97c0677fe496af4e2befb29cd Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Fri, 17 Jul 2015 23:03:31 -0400
Subject: [PATCH 022/534] Namespace renaming for Range class.
---
scss.inc.php | 2 +-
src/{Compat => Base}/Range.php | 2 +-
src/Compiler.php | 2 +-
src/Util.php | 2 +-
4 files changed, 4 insertions(+), 4 deletions(-)
rename src/{Compat => Base}/Range.php (95%)
diff --git a/scss.inc.php b/scss.inc.php
index 7d2192fe..a60cd472 100644
--- a/scss.inc.php
+++ b/scss.inc.php
@@ -4,8 +4,8 @@
}
if ( ! class_exists('scssc')) {
+ include_once __DIR__ . '/src/Base/Range.php';
include_once __DIR__ . '/src/Colors.php';
- include_once __DIR__ . '/src/Compat/Range.php';
include_once __DIR__ . '/src/Compiler.php';
include_once __DIR__ . '/src/Formatter.php';
include_once __DIR__ . '/src/Formatter/Compact.php';
diff --git a/src/Compat/Range.php b/src/Base/Range.php
similarity index 95%
rename from src/Compat/Range.php
rename to src/Base/Range.php
index b1752878..76920556 100644
--- a/src/Compat/Range.php
+++ b/src/Base/Range.php
@@ -9,7 +9,7 @@
* @link http://leafo.github.io/scssphp
*/
-namespace Leafo\ScssPhp\Compat;
+namespace Leafo\ScssPhp\Base;
/**
* Range class
diff --git a/src/Compiler.php b/src/Compiler.php
index 6e90ee68..12502eae 100644
--- a/src/Compiler.php
+++ b/src/Compiler.php
@@ -11,8 +11,8 @@
namespace Leafo\ScssPhp;
+use Leafo\ScssPhp\Base\Range;
use Leafo\ScssPhp\Colors;
-use Leafo\ScssPhp\Compat\Range;
use Leafo\ScssPhp\Parser;
use Leafo\ScssPhp\Util;
diff --git a/src/Util.php b/src/Util.php
index a3187457..1764c21e 100644
--- a/src/Util.php
+++ b/src/Util.php
@@ -11,7 +11,7 @@
namespace Leafo\ScssPhp;
-use Leafo\ScssPhp\Compat\Range;
+use Leafo\ScssPhp\Base\Range;
/**
* SCSS utilties
From 7afc4e9877129dd067c00c79e00f69a088ebf130 Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Sat, 18 Jul 2015 00:21:35 -0400
Subject: [PATCH 023/534] Fixes #112 - variable arguments' type should be
"arglist" not "list"
---
src/Compiler.php | 8 +++++++-
tests/FailingTest.php | 15 ---------------
tests/inputs/functions.scss | 8 ++++++++
tests/outputs/functions.css | 3 +++
tests/outputs_numbered/functions.css | 3 +++
5 files changed, 21 insertions(+), 16 deletions(-)
diff --git a/src/Compiler.php b/src/Compiler.php
index 12502eae..0b84eff7 100644
--- a/src/Compiler.php
+++ b/src/Compiler.php
@@ -2277,7 +2277,7 @@ protected function applyArguments($argDef, $argValues)
list($i, $name, $default, $isVariable) = $arg;
if ($isVariable) {
- $val = array('list', ',', array());
+ $val = array('list', ',', array(), $isVariable);
for ($count = count($remaining); $i < $count; $i++) {
$val[2][] = $remaining[$i];
}
@@ -3305,6 +3305,12 @@ protected function libTypeOf($args)
// fall-thru
case 'function':
return 'string';
+ case 'list':
+ if (isset($value[3]) && $value[3]) {
+ return 'arglist';
+ }
+
+ // fall-thru
default:
return $value[0];
}
diff --git a/tests/FailingTest.php b/tests/FailingTest.php
index c71556ee..a1d0939c 100644
--- a/tests/FailingTest.php
+++ b/tests/FailingTest.php
@@ -177,21 +177,6 @@ public function provideFailing()
, <<
Date: Sat, 18 Jul 2015 09:59:07 -0400
Subject: [PATCH 024/534] Bump version to v0.1.8
---
src/Version.php | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/Version.php b/src/Version.php
index e457776a..5fcd71e2 100644
--- a/src/Version.php
+++ b/src/Version.php
@@ -18,5 +18,5 @@
*/
class Version
{
- const VERSION = 'v0.1.7';
+ const VERSION = 'v0.1.8';
}
From 07e2fc9ad47d92ee6b7c19132d0c748a7e4fdd29 Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Sat, 18 Jul 2015 14:29:41 -0400
Subject: [PATCH 025/534] Bump README version
---
README.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/README.md b/README.md
index 86b0b262..c0564a5e 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,4 @@
-# scssphp v0.1.7
+# scssphp v0.1.8
###
[](http://travis-ci.org/leafo/scssphp)
From 24e4328892be952a08d5b488165c80dfaaba4201 Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Sat, 18 Jul 2015 23:53:51 -0400
Subject: [PATCH 026/534] Fixes #111 - Interpolated string is not the same as
regular string
---
src/Compiler.php | 2 +-
src/Formatter.php | 2 +-
tests/FailingTest.php | 12 ------------
tests/inputs/interpolation.scss | 5 ++++-
tests/outputs/interpolation.css | 3 +++
tests/outputs/scss_css.css | 2 +-
tests/outputs_numbered/interpolation.css | 3 +++
tests/outputs_numbered/scss_css.css | 2 +-
8 files changed, 14 insertions(+), 17 deletions(-)
diff --git a/src/Compiler.php b/src/Compiler.php
index 0b84eff7..0bcc7758 100644
--- a/src/Compiler.php
+++ b/src/Compiler.php
@@ -1336,7 +1336,7 @@ public function normalizeValue($value)
return $value;
case 'string':
- return array($value[0], '"', $value[2]);
+ return array($type, '"', $this->compileStringContent($value));
case 'number':
return $this->normalizeNumber($value);
diff --git a/src/Formatter.php b/src/Formatter.php
index b9fb18f8..f2ccf3e7 100644
--- a/src/Formatter.php
+++ b/src/Formatter.php
@@ -75,7 +75,7 @@ protected function indentStr($n = 0)
*/
public function property($name, $value)
{
- return $name . $this->assignSeparator . $value . ';';
+ return rtrim($name) . $this->assignSeparator . $value . ';';
}
/**
diff --git a/tests/FailingTest.php b/tests/FailingTest.php
index a1d0939c..1d7b43a5 100644
--- a/tests/FailingTest.php
+++ b/tests/FailingTest.php
@@ -165,18 +165,6 @@ public function provideFailing()
, <<
Date: Sun, 19 Jul 2015 00:17:27 -0400
Subject: [PATCH 027/534] [internals] @debug - remove redundant source position
in block
---
src/Compiler.php | 4 ++--
src/Parser.php | 2 +-
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/src/Compiler.php b/src/Compiler.php
index 0bcc7758..01e91742 100644
--- a/src/Compiler.php
+++ b/src/Compiler.php
@@ -1053,9 +1053,9 @@ protected function compileChild($child, $out)
unset($this->storeEnv);
break;
case 'debug':
- list(, $value, $pos) = $child;
+ list(, $value) = $child;
- $line = $this->parser->getLineNo($pos);
+ $line = $this->parser->getLineNo($this->sourcePos);
$value = $this->compileValue($this->reduce($value, true));
fwrite($this->stderr, "Line $line DEBUG: $value\n");
break;
diff --git a/src/Parser.php b/src/Parser.php
index cb37332e..050d7e83 100644
--- a/src/Parser.php
+++ b/src/Parser.php
@@ -380,7 +380,7 @@ protected function parseChunk()
if (($this->literal('@debug') || $this->literal('@warn')) &&
$this->valueList($value) &&
$this->end()) {
- $this->append(array('debug', $value, $s), $s);
+ $this->append(array('debug', $value), $s);
return true;
}
From 82f5f01858a77c461721c9707ce5c38497a7d8d9 Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Sun, 19 Jul 2015 01:24:11 -0400
Subject: [PATCH 028/534] set-nth() - added support
---
src/Compiler.php | 15 +++++++++++++++
tests/inputs/list.scss | 7 +++++++
tests/outputs/list.css | 5 +++++
tests/outputs_numbered/list.css | 5 +++++
4 files changed, 32 insertions(+)
diff --git a/src/Compiler.php b/src/Compiler.php
index 01e91742..4115813e 100644
--- a/src/Compiler.php
+++ b/src/Compiler.php
@@ -3145,6 +3145,21 @@ protected function libNth($args)
return isset($list[2][$n]) ? $list[2][$n] : self::$defaultValue;
}
+ protected static $libSetNth = array('list', 'n', 'value');
+ protected function libSetNth($args)
+ {
+ $list = $this->coerceList($args[0]);
+ $n = $this->assertNumber($args[1]) - 1;
+
+ if (! isset($list[2][$n])) {
+ $this->throwError('Invalid argument for "n"');
+ }
+
+ $list[2][$n] = $args[2];
+
+ return $list;
+ }
+
protected static $libMapGet = array('map', 'key');
protected function libMapGet($args)
{
diff --git a/tests/inputs/list.scss b/tests/inputs/list.scss
index 04b825c2..4c2e790d 100644
--- a/tests/inputs/list.scss
+++ b/tests/inputs/list.scss
@@ -19,3 +19,10 @@ x: index(1px solid red, solid);
y: index(1px solid red, dashed);
z: index((width: 10px, height: 20px), (height 20px));
}
+
+$list: set-nth($list: 10px 20px 30px, $n: 2, $value: -20px);
+div {
+ a: nth($list, 1);
+ b: nth($list, 2);
+ c: nth($list, 3);
+}
diff --git a/tests/outputs/list.css b/tests/outputs/list.css
index aa891ab8..7c1d2809 100644
--- a/tests/outputs/list.css
+++ b/tests/outputs/list.css
@@ -9,3 +9,8 @@ p {
div {
x: 2;
z: 2; }
+
+div {
+ a: 10px;
+ b: -20px;
+ c: 30px; }
diff --git a/tests/outputs_numbered/list.css b/tests/outputs_numbered/list.css
index 97aaafa5..f356d29d 100644
--- a/tests/outputs_numbered/list.css
+++ b/tests/outputs_numbered/list.css
@@ -10,3 +10,8 @@ p {
div {
x: 2;
z: 2; }
+/* line 24, inputs/list.scss */
+div {
+ a: 10px;
+ b: -20px;
+ c: 30px; }
From 41586bf97c6e66dac91f3e216a9929c4bdb91360 Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Sun, 19 Jul 2015 01:53:25 -0400
Subject: [PATCH 029/534] list-separator - added support
---
src/Compiler.php | 21 +++++++++++++++++++++
tests/inputs/list.scss | 6 ++++++
tests/outputs/list.css | 5 +++++
tests/outputs_numbered/list.css | 5 +++++
4 files changed, 37 insertions(+)
diff --git a/src/Compiler.php b/src/Compiler.php
index 4115813e..04d8699d 100644
--- a/src/Compiler.php
+++ b/src/Compiler.php
@@ -3136,6 +3136,27 @@ protected function libLength($args)
return count($list[2]);
}
+ // TODO: need a way to declare this built-in as varargs
+ //protected static $libListSeparator = array('list...');
+ protected function libListSeparator($args)
+ {
+ if (count($args) > 1) {
+ return 'comma';
+ }
+
+ $list = $this->coerceList($args[0]);
+
+ if (count($list[2]) <= 1) {
+ return 'space';
+ }
+
+ if ($list[1] === ',') {
+ return 'comma';
+ }
+
+ return 'space';
+ }
+
protected static $libNth = array('list', 'n');
protected function libNth($args)
{
diff --git a/tests/inputs/list.scss b/tests/inputs/list.scss
index 4c2e790d..483292d3 100644
--- a/tests/inputs/list.scss
+++ b/tests/inputs/list.scss
@@ -26,3 +26,9 @@ div {
b: nth($list, 2);
c: nth($list, 3);
}
+
+div {
+x:list-separator(1px 2px 3px);
+y:list-separator(1px, 2px, 3px);
+z:list-separator('foo');
+}
diff --git a/tests/outputs/list.css b/tests/outputs/list.css
index 7c1d2809..aed03cea 100644
--- a/tests/outputs/list.css
+++ b/tests/outputs/list.css
@@ -14,3 +14,8 @@ div {
a: 10px;
b: -20px;
c: 30px; }
+
+div {
+ x: space;
+ y: comma;
+ z: space; }
diff --git a/tests/outputs_numbered/list.css b/tests/outputs_numbered/list.css
index f356d29d..90cc8576 100644
--- a/tests/outputs_numbered/list.css
+++ b/tests/outputs_numbered/list.css
@@ -15,3 +15,8 @@ div {
a: 10px;
b: -20px;
c: 30px; }
+/* line 30, inputs/list.scss */
+div {
+ x: space;
+ y: comma;
+ z: space; }
From a26770de74d95356fefb2712d5c715021c5705a7 Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Sun, 19 Jul 2015 16:32:52 -0400
Subject: [PATCH 030/534] quick fixes #300 - @debug, @warn, and @error
functionality
---
src/Compiler.php | 14 ++++++++++++++
src/Parser.php | 27 +++++++++++++++++++++++++--
2 files changed, 39 insertions(+), 2 deletions(-)
diff --git a/src/Compiler.php b/src/Compiler.php
index 04d8699d..c0af8d18 100644
--- a/src/Compiler.php
+++ b/src/Compiler.php
@@ -1059,6 +1059,20 @@ protected function compileChild($child, $out)
$value = $this->compileValue($this->reduce($value, true));
fwrite($this->stderr, "Line $line DEBUG: $value\n");
break;
+ case 'warn':
+ list(, $value) = $child;
+
+ $line = $this->parser->getLineNo($this->sourcePos);
+ $value = $this->compileValue($this->reduce($value, true));
+ echo "Line $line WARN: $value\n";
+ break;
+ case 'error':
+ list(, $value) = $child;
+
+ $line = $this->parser->getLineNo($this->sourcePos);
+ $value = $this->compileValue($this->reduce($value, true));
+ $this->throwError("Line $line ERROR: $value\n");
+ break;
default:
$this->throwError("unknown child type: $child[0]");
}
diff --git a/src/Parser.php b/src/Parser.php
index 050d7e83..86ec98b7 100644
--- a/src/Parser.php
+++ b/src/Parser.php
@@ -377,9 +377,10 @@ protected function parseChunk()
$this->seek($s);
- if (($this->literal('@debug') || $this->literal('@warn')) &&
+ if ($this->literal('@debug') &&
$this->valueList($value) &&
- $this->end()) {
+ $this->end()
+ ) {
$this->append(array('debug', $value), $s);
return true;
@@ -387,6 +388,28 @@ protected function parseChunk()
$this->seek($s);
+ if ($this->literal('@warn') &&
+ $this->valueList($value) &&
+ $this->end()
+ ) {
+ $this->append(array('warn', $value), $s);
+
+ return true;
+ }
+
+ $this->seek($s);
+
+ if ($this->literal('@error') &&
+ $this->valueList($value) &&
+ $this->end()
+ ) {
+ $this->append(array('error', $value), $s);
+
+ return true;
+ }
+
+ $this->seek($s);
+
if ($this->literal('@content') && $this->end()) {
$this->append(array('mixin_content'), $s);
From 3b1a663a4b5d261f844f537e8f5e4ffcf4274e83 Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Sun, 19 Jul 2015 21:05:03 -0400
Subject: [PATCH 031/534] Only run travis on the master branch
---
.travis.yml | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/.travis.yml b/.travis.yml
index 14d28bb9..4b497d9b 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -10,3 +10,7 @@ php:
script:
- phpunit tests
+
+branches:
+ only:
+ - master
From 6f1d1e01f5b9d4825fb4840903370f97e25d6bb9 Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Tue, 21 Jul 2015 20:52:45 -0400
Subject: [PATCH 032/534] Remove version number from README
---
README.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/README.md b/README.md
index c0564a5e..763341a2 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,4 @@
-# scssphp v0.1.8
+# scssphp
###
[](http://travis-ci.org/leafo/scssphp)
From f2f74120b65ffa549dba96774ffb455b913f341a Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Wed, 22 Jul 2015 06:56:30 -0400
Subject: [PATCH 033/534] Yank the <=> operator until approved for reference
implementation
---
src/Compiler.php | 19 --------
src/Parser.php | 2 -
tests/inputs/operators.scss | 4 --
tests/outputs/operators.css | 5 +-
tests/outputs_numbered/operators.css | 69 +++++++++++++---------------
5 files changed, 34 insertions(+), 65 deletions(-)
diff --git a/src/Compiler.php b/src/Compiler.php
index c0af8d18..5acd4bc7 100644
--- a/src/Compiler.php
+++ b/src/Compiler.php
@@ -67,8 +67,6 @@ class Compiler
'<=' => 'lte',
'>=' => 'gte',
-
- '<=>' => 'cmp',
);
static protected $namespaces = array(
@@ -1566,23 +1564,6 @@ protected function opLtNumberNumber($left, $right)
return $this->toBool($left[1] < $right[1]);
}
- /**
- * Three-way comparison, aka spaceship operator
- *
- * @param array $left
- * @param array $right
- *
- * @return array
- */
- protected function opCmpNumberNumber($left, $right)
- {
- $n = $left[1] - $right[1];
-
- return array('number', $n ? $n / abs($n) : 0, '');
-
- // PHP7: return array('number', $left[1] <=> $right[1], '');
- }
-
public function toBool($thing)
{
return $thing ? self::$true : self::$false;
diff --git a/src/Parser.php b/src/Parser.php
index 86ec98b7..10a85996 100644
--- a/src/Parser.php
+++ b/src/Parser.php
@@ -32,7 +32,6 @@ class Parser
'and' => 2,
'==' => 3,
'!=' => 3,
- '<=>' => 3,
'<=' => 4,
'>=' => 4,
'<' => 4,
@@ -55,7 +54,6 @@ class Parser
'%',
'==',
'!=',
- '<=>',
'<=',
'>=',
'<',
diff --git a/tests/inputs/operators.scss b/tests/inputs/operators.scss
index 2b4fea4f..98ae7cb0 100644
--- a/tests/inputs/operators.scss
+++ b/tests/inputs/operators.scss
@@ -19,10 +19,6 @@ div {
color: 4 > 3;
color: 4 < 3;
color: what > 3;
-
- color: 0 <=> 0;
- color: 1 <=> 2;
- color: 2 <=> 1;
}
diff --git a/tests/outputs/operators.css b/tests/outputs/operators.css
index 3a236c57..c592c08e 100644
--- a/tests/outputs/operators.css
+++ b/tests/outputs/operators.css
@@ -14,10 +14,7 @@ div {
color: true;
color: true;
color: false;
- color: what > 3;
- color: 0;
- color: -1;
- color: 1; }
+ color: what > 3; }
#units {
test: 2.5748in;
diff --git a/tests/outputs_numbered/operators.css b/tests/outputs_numbered/operators.css
index 0d35202f..c379809d 100644
--- a/tests/outputs_numbered/operators.css
+++ b/tests/outputs_numbered/operators.css
@@ -15,22 +15,19 @@ div {
color: true;
color: true;
color: false;
- color: what > 3;
- color: 0;
- color: -1;
- color: 1; }
-/* line 29, inputs/operators.scss */
+ color: what > 3; }
+/* line 25, inputs/operators.scss */
#units {
test: 2.5748in;
test: 13mm;
test: 4em;
test: 11mm;
test: 1.1cm; }
-/* line 37, inputs/operators.scss */
+/* line 33, inputs/operators.scss */
#modulo {
test: 1;
test: 1cm; }
-/* line 42, inputs/operators.scss */
+/* line 38, inputs/operators.scss */
#colors {
color: #ff0203;
color: #fe0000;
@@ -45,11 +42,11 @@ div {
color: true;
color: true;
color: false; }
-/* line 63, inputs/operators.scss */
+/* line 59, inputs/operators.scss */
#preserve {
hello: what -going;
hello: what - going; }
-/* line 68, inputs/operators.scss */
+/* line 64, inputs/operators.scss */
#strings {
hello: what -going;
hello: whatgoing;
@@ -59,12 +56,12 @@ div {
hello: "whatgoing";
hello: goingwhat;
hello: "whatwhat"; }
-/* line 81, inputs/operators.scss */
+/* line 77, inputs/operators.scss */
#negation {
a: -60;
b: -90;
b: -90; }
-/* line 88, inputs/operators.scss */
+/* line 84, inputs/operators.scss */
#bools-fail {
and: false and two;
and: one and two;
@@ -72,7 +69,7 @@ div {
or: false or two;
or: one or two;
or: one or false; }
-/* line 98, inputs/operators.scss */
+/* line 94, inputs/operators.scss */
#bools {
and: false;
and: two;
@@ -80,7 +77,7 @@ div {
or: two;
or: one;
or: one; }
-/* line 109, inputs/operators.scss */
+/* line 105, inputs/operators.scss */
#nots-fail {
not: false2;
not: not false;
@@ -88,7 +85,7 @@ div {
not: not 1;
not: not "";
not: not hello; }
-/* line 118, inputs/operators.scss */
+/* line 114, inputs/operators.scss */
#nots {
not: false2;
not: true;
@@ -96,7 +93,7 @@ div {
not: false;
not: false;
not: false; }
-/* line 127, inputs/operators.scss */
+/* line 123, inputs/operators.scss */
#string-test {
str: true;
str: false;
@@ -104,66 +101,66 @@ div {
str: true;
str: xhellohellofalse;
str: true; }
-/* line 143, inputs/operators.scss */
+/* line 139, inputs/operators.scss */
#special {
cancel-unit: 1; }
-/* line 150, inputs/operators.scss */
+/* line 146, inputs/operators.scss */
.row .a {
margin: -0.5em; }
-/* line 151, inputs/operators.scss */
+/* line 147, inputs/operators.scss */
.row .b {
margin: -0.5em; }
-/* line 152, inputs/operators.scss */
+/* line 148, inputs/operators.scss */
.row .c {
margin: -0.5em; }
-/* line 153, inputs/operators.scss */
+/* line 149, inputs/operators.scss */
.row .d {
margin: -0.5em; }
-/* line 154, inputs/operators.scss */
+/* line 150, inputs/operators.scss */
.row .e {
margin: 0 -0.5em; }
-/* line 156, inputs/operators.scss */
+/* line 152, inputs/operators.scss */
.alt .a {
margin: -0.5em; }
-/* line 157, inputs/operators.scss */
+/* line 153, inputs/operators.scss */
.alt .b {
margin: -0.5em; }
-/* line 158, inputs/operators.scss */
+/* line 154, inputs/operators.scss */
.alt .c {
margin: -0.5em; }
-/* line 159, inputs/operators.scss */
+/* line 155, inputs/operators.scss */
.alt .d {
margin: 0 -0.5em; }
-/* line 160, inputs/operators.scss */
+/* line 156, inputs/operators.scss */
.alt .e {
margin: 0 -0.5em; }
-/* line 162, inputs/operators.scss */
+/* line 158, inputs/operators.scss */
.row .f {
margin: -2em; }
-/* line 163, inputs/operators.scss */
+/* line 159, inputs/operators.scss */
.row .g {
margin: -2em; }
-/* line 164, inputs/operators.scss */
+/* line 160, inputs/operators.scss */
.row .h {
margin: -2em; }
-/* line 165, inputs/operators.scss */
+/* line 161, inputs/operators.scss */
.row .i {
margin: -2em; }
-/* line 166, inputs/operators.scss */
+/* line 162, inputs/operators.scss */
.row .j {
margin: 0 -2em; }
-/* line 168, inputs/operators.scss */
+/* line 164, inputs/operators.scss */
.alt .f {
margin: -2em; }
-/* line 169, inputs/operators.scss */
+/* line 165, inputs/operators.scss */
.alt .g {
margin: -2em; }
-/* line 170, inputs/operators.scss */
+/* line 166, inputs/operators.scss */
.alt .h {
margin: -2em; }
-/* line 171, inputs/operators.scss */
+/* line 167, inputs/operators.scss */
.alt .i {
margin: 0 -2em; }
-/* line 172, inputs/operators.scss */
+/* line 168, inputs/operators.scss */
.alt .j {
margin: 0 -2em; }
From 1409169a44abba3f6ba4674321cb1523b8ad0b1c Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Wed, 29 Jul 2015 14:17:05 -0400
Subject: [PATCH 034/534] fix selector lists #127, #160, #244
---
src/Compiler.php | 22 +++++++++-
tests/FailingTest.php | 62 ----------------------------
tests/inputs/selectors.scss | 41 ++++++++++++++++++
tests/outputs/selectors.css | 9 ++++
tests/outputs_numbered/selectors.css | 15 +++++++
5 files changed, 85 insertions(+), 64 deletions(-)
diff --git a/src/Compiler.php b/src/Compiler.php
index 5acd4bc7..138c6f0a 100644
--- a/src/Compiler.php
+++ b/src/Compiler.php
@@ -468,8 +468,7 @@ protected function compileBlock($block)
{
$env = $this->pushEnv($block);
- $env->selectors =
- array_map(array($this, 'evalSelector'), $block->selectors);
+ $env->selectors = $this->evalSelectors($block->selectors);
$out = $this->makeOutputBlock(null, $this->multiplySelectors($env));
@@ -539,6 +538,25 @@ protected function evalSelector($selector)
return array_map(array($this, 'evalSelectorPart'), $selector);
}
+ protected function evalSelectors($selectors)
+ {
+ $selectors = array_map(array($this, 'evalSelector'), $selectors);
+
+ $newSelectors = array();
+
+ foreach ($selectors as $selector) {
+ if (is_array($selector[0][0]) || strpos($selector[0][0], ',') === false) {
+ $newSelectors[] = $selector;
+ } else {
+ foreach (array_map('trim', explode(',', $selector[0][0])) as $newSelectorPart) {
+ $newSelectors[] = array(array($newSelectorPart));
+ }
+ }
+ }
+
+ return $newSelectors;
+ }
+
protected function evalSelectorPart($piece)
{
foreach ($piece as &$p) {
diff --git a/tests/FailingTest.php b/tests/FailingTest.php
index 1d7b43a5..c41eefa1 100644
--- a/tests/FailingTest.php
+++ b/tests/FailingTest.php
@@ -181,19 +181,6 @@ public function provideFailing()
, <<
Date: Wed, 29 Jul 2015 14:31:47 -0400
Subject: [PATCH 035/534] fixes #240 selector lists with interpolation
---
src/Compiler.php | 2 +-
tests/FailingTest.php | 20 --------------------
tests/inputs/selectors.scss | 12 ++++++++++++
tests/outputs/selectors.css | 3 +++
tests/outputs_numbered/selectors.css | 5 +++++
5 files changed, 21 insertions(+), 21 deletions(-)
diff --git a/src/Compiler.php b/src/Compiler.php
index 138c6f0a..9aff681e 100644
--- a/src/Compiler.php
+++ b/src/Compiler.php
@@ -548,7 +548,7 @@ protected function evalSelectors($selectors)
if (is_array($selector[0][0]) || strpos($selector[0][0], ',') === false) {
$newSelectors[] = $selector;
} else {
- foreach (array_map('trim', explode(',', $selector[0][0])) as $newSelectorPart) {
+ foreach (array_map(function ($s) { return trim($s, " \t\n\r\0\x0b'\""); }, explode(',', $selector[0][0])) as $newSelectorPart) {
$newSelectors[] = array(array($newSelectorPart));
}
}
diff --git a/tests/FailingTest.php b/tests/FailingTest.php
index c41eefa1..3bc8b127 100644
--- a/tests/FailingTest.php
+++ b/tests/FailingTest.php
@@ -255,26 +255,6 @@ public function provideFailing()
small {
font-weight: italic; }
-END_OF_EXPECTED
- ),
- array(
- '#240 - variable interpolation not working correctly', <<<'END_OF_SCSS'
-$span: 'span';
-$p: 'p';
-$div: 'div';
-
-$all: $span, $p, $div;
-
-#{$all} {
- a {
- color: red;
- }
-}
-END_OF_SCSS
- , <<
Date: Wed, 29 Jul 2015 19:01:53 -0400
Subject: [PATCH 036/534] Fixes #149 - parent selector in string
---
src/Compiler.php | 14 ++++++++++++--
tests/FailingTest.php | 25 -------------------------
tests/inputs/selectors.scss | 21 +++++++++++++++++++++
tests/outputs/selectors.css | 10 ++++++++++
tests/outputs_numbered/selectors.css | 16 ++++++++++++++++
5 files changed, 59 insertions(+), 27 deletions(-)
diff --git a/src/Compiler.php b/src/Compiler.php
index 9aff681e..3254fa20 100644
--- a/src/Compiler.php
+++ b/src/Compiler.php
@@ -545,11 +545,21 @@ protected function evalSelectors($selectors)
$newSelectors = array();
foreach ($selectors as $selector) {
- if (is_array($selector[0][0]) || strpos($selector[0][0], ',') === false) {
+ if (is_array($selector[0][0])) {
+ $newSelectors[] = $selector;
+ } elseif (strpos($selector[0][0], ',') === false) {
+ if ($selector[0][0][0] === '&') {
+ $selector = array(array(array('self'), substr($selector[0][0], 1)));
+ }
+
$newSelectors[] = $selector;
} else {
foreach (array_map(function ($s) { return trim($s, " \t\n\r\0\x0b'\""); }, explode(',', $selector[0][0])) as $newSelectorPart) {
- $newSelectors[] = array(array($newSelectorPart));
+ if ($newSelectorPart[0] === '&') {
+ $newSelectors[] = array(array(array('self'), substr($newSelectorPart, 1)));
+ } else {
+ $newSelectors[] = array(array($newSelectorPart));
+ }
}
}
}
diff --git a/tests/FailingTest.php b/tests/FailingTest.php
index 3bc8b127..fd7f280f 100644
--- a/tests/FailingTest.php
+++ b/tests/FailingTest.php
@@ -181,31 +181,6 @@ public function provideFailing()
, <<
Date: Thu, 30 Jul 2015 13:30:58 -0400
Subject: [PATCH 037/534] Bump version in preparation for 0.1.9 release
---
src/Version.php | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/Version.php b/src/Version.php
index 5fcd71e2..6f9285b0 100644
--- a/src/Version.php
+++ b/src/Version.php
@@ -18,5 +18,5 @@
*/
class Version
{
- const VERSION = 'v0.1.8';
+ const VERSION = 'v0.1.9';
}
From be55b9e9c1be68bbdfb5bf8beff702097b7ed394 Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Fri, 31 Jul 2015 14:28:04 -0400
Subject: [PATCH 038/534] Fixes #311 add more parent selector tests
---
tests/inputs/selectors.scss | 13 ++++++++
tests/outputs/selectors.css | 6 ++++
tests/outputs_numbered/selectors.css | 47 +++++++++++++++++-----------
3 files changed, 47 insertions(+), 19 deletions(-)
diff --git a/tests/inputs/selectors.scss b/tests/inputs/selectors.scss
index fa8e6888..4c902820 100644
--- a/tests/inputs/selectors.scss
+++ b/tests/inputs/selectors.scss
@@ -173,6 +173,9 @@ div {
&.foo & {
color: blue;
}
+ & + & {
+ color: green;
+ }
}
.main, div {
@@ -266,4 +269,14 @@ $all: $span, $p, $div;
#{$selfMultiple} {
content: "should match .parent.self1, .parent.self2";
}
+
+ $trailingSelf: unquote(".self1 &");
+ #{$trailingSelf} {
+ content: "should match .self1 .parent";
+ }
+
+ $doubleSelf: unquote("& + &");
+ #{$doubleSelf} {
+ content: "should match .parent + .parent";
+ }
}
diff --git a/tests/outputs/selectors.css b/tests/outputs/selectors.css
index 1ec9561d..f2c202e4 100644
--- a/tests/outputs/selectors.css
+++ b/tests/outputs/selectors.css
@@ -330,6 +330,8 @@ div {
div.foo div {
color: blue; }
+ div + div {
+ color: green; }
.nice-fonts .main .message div .title, .nice-fonts div .message div .title {
font-size: 24px; }
@@ -361,3 +363,7 @@ span a, p a, div a {
.parent.self1, .parent.self2 {
content: "should match .parent.self1, .parent.self2"; }
+.self1 .parent {
+ content: "should match .self1 .parent"; }
+.parent + .parent {
+ content: "should match .parent + .parent"; }
diff --git a/tests/outputs_numbered/selectors.css b/tests/outputs_numbered/selectors.css
index 0d070cb2..56fdbfa6 100644
--- a/tests/outputs_numbered/selectors.css
+++ b/tests/outputs_numbered/selectors.css
@@ -344,52 +344,61 @@ div font:something {
div.foo div {
color: blue; }
-/* line 178, inputs/selectors.scss */
-/* line 179, inputs/selectors.scss */
+/* line 176, inputs/selectors.scss */
+div + div {
+ color: green; }
+/* line 181, inputs/selectors.scss */
+/* line 182, inputs/selectors.scss */
-/* line 180, inputs/selectors.scss */
- /* line 181, inputs/selectors.scss */
+/* line 183, inputs/selectors.scss */
+ /* line 184, inputs/selectors.scss */
.nice-fonts .main .message div .title, .nice-fonts div .message div .title {
font-size: 24px; }
-/* line 189, inputs/selectors.scss */
+/* line 192, inputs/selectors.scss */
.escape\% {
color: red; }
-/* line 193, inputs/selectors.scss */
+/* line 196, inputs/selectors.scss */
.escape-plan\% {
color: green; }
-/* line 197, inputs/selectors.scss */
-/* line 198, inputs/selectors.scss */
+/* line 200, inputs/selectors.scss */
+/* line 201, inputs/selectors.scss */
.element .one, .element .two {
property: value; }
-/* line 225, inputs/selectors.scss */
-/* line 220, inputs/selectors.scss */
+/* line 228, inputs/selectors.scss */
+/* line 223, inputs/selectors.scss */
#secondary h1, #secondary h2, #secondary h3, #secondary h4, #secondary h5, #secondary h6 {
color: #e6e6e6; }
-/* line 232, inputs/selectors.scss */
-/* line 233, inputs/selectors.scss */
+/* line 235, inputs/selectors.scss */
+/* line 236, inputs/selectors.scss */
.test foo, .test bar {
border: 1px dashed red; }
-/* line 244, inputs/selectors.scss */
-/* line 245, inputs/selectors.scss */
+/* line 247, inputs/selectors.scss */
+/* line 248, inputs/selectors.scss */
span a, p a, div a {
color: red; }
-/* line 250, inputs/selectors.scss */
/* line 253, inputs/selectors.scss */
+/* line 256, inputs/selectors.scss */
.parent.self {
content: "should match .parent.self"; }
-/* line 256, inputs/selectors.scss */
+/* line 259, inputs/selectors.scss */
.parent .child {
content: "should match .parent .child"; }
-/* line 259, inputs/selectors.scss */
+/* line 262, inputs/selectors.scss */
.parent.self2 {
content: "should match .parent.self2"; }
-/* line 264, inputs/selectors.scss */
-/* line 266, inputs/selectors.scss */
+/* line 267, inputs/selectors.scss */
+/* line 269, inputs/selectors.scss */
.parent.self1, .parent.self2 {
content: "should match .parent.self1, .parent.self2"; }
+/* line 274, inputs/selectors.scss */
+.self1 .parent {
+ content: "should match .self1 .parent"; }
+/* line 279, inputs/selectors.scss */
+.parent + .parent {
+ content: "should match .parent + .parent"; }
From 609c08586d583fc7d1db78b7edd8b4ac57fa5137 Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Sat, 1 Aug 2015 12:04:21 -0400
Subject: [PATCH 039/534] Replace buggy selector tree rewriting with 2-pass
compilation
---
src/Compiler.php | 108 +++++++++++++++-------------
src/Parser.php | 19 +++++
tests/outputs/scss_css.css | 2 +-
tests/outputs/selectors.css | 8 +--
tests/outputs_numbered/scss_css.css | 2 +-
5 files changed, 82 insertions(+), 57 deletions(-)
diff --git a/src/Compiler.php b/src/Compiler.php
index 3254fa20..43262368 100644
--- a/src/Compiler.php
+++ b/src/Compiler.php
@@ -119,6 +119,7 @@ class Compiler
private $storeEnv;
private $charsetSeen;
private $stderr;
+ private $shouldEvaluate;
/**
* Compile scss
@@ -509,82 +510,87 @@ protected function compileComment($block)
$this->scope->children[] = $out;
}
- // joins together .classes and #ids
- protected function flattenSelectorSingle($single)
+ protected function evalSelectors($selectors)
{
- $joined = array();
- foreach ($single as $part) {
- if (empty($joined) ||
- ! is_string($part) ||
- preg_match('/[\[.:#%]/', $part)
- ) {
- $joined[] = $part;
- continue;
- }
+ $this->shouldEvaluate = false;
- if (is_array(end($joined))) {
- $joined[] = $part;
- } else {
- $joined[count($joined) - 1] .= $part;
+ $selectors = array_map(array($this, 'evalSelector'), $selectors);
+
+ // after evaluating interpolates, we might need a second pass
+ if ($this->shouldEvaluate) {
+ $buffer = $this->collapseSelectors($selectors);
+ $parser = new Parser(__METHOD__, false);
+
+ if ($parser->parseSelector($buffer, $newSelectors)) {
+ $selectors = array_map(array($this, 'evalSelector'), $newSelectors);
}
}
- return $joined;
+ return $selectors;
}
- // replaces all the interpolates
protected function evalSelector($selector)
{
return array_map(array($this, 'evalSelectorPart'), $selector);
}
- protected function evalSelectors($selectors)
+ // replaces all the interpolates, stripping quotes
+ protected function evalSelectorPart($part)
{
- $selectors = array_map(array($this, 'evalSelector'), $selectors);
-
- $newSelectors = array();
-
- foreach ($selectors as $selector) {
- if (is_array($selector[0][0])) {
- $newSelectors[] = $selector;
- } elseif (strpos($selector[0][0], ',') === false) {
- if ($selector[0][0][0] === '&') {
- $selector = array(array(array('self'), substr($selector[0][0], 1)));
- }
+ foreach ($part as &$p) {
+ if (is_array($p) && ($p[0] === 'interpolate' || $p[0] === 'string')) {
+ $p = $this->compileValue($p);
- $newSelectors[] = $selector;
- } else {
- foreach (array_map(function ($s) { return trim($s, " \t\n\r\0\x0b'\""); }, explode(',', $selector[0][0])) as $newSelectorPart) {
- if ($newSelectorPart[0] === '&') {
- $newSelectors[] = array(array(array('self'), substr($newSelectorPart, 1)));
- } else {
- $newSelectors[] = array(array($newSelectorPart));
- }
+ // force re-evaluation
+ if (strpos($p, '&') !== false || strpos($p, ',') !== false) {
+ $this->shouldEvaluate = true;
}
+ } elseif (is_string($p) && strlen($p) >= 2 &&
+ ($first = $p[0]) && ($first === '"' || $first === "'") &&
+ substr($p, -1) === $first
+ ) {
+ $p = substr($p, 1, -1);
}
}
- return $newSelectors;
+ return $this->flattenSelectorSingle($part);
}
- protected function evalSelectorPart($piece)
+ protected function collapseSelectors($selectors)
{
- foreach ($piece as &$p) {
- if (! is_array($p)) {
+ $output = '';
+
+ array_walk_recursive(
+ $selectors,
+ function ($value, $key) use (&$output) {
+ $output .= $value;
+ }
+ );
+
+ return $output;
+ }
+
+ // joins together .classes and #ids
+ protected function flattenSelectorSingle($single)
+ {
+ $joined = array();
+ foreach ($single as $part) {
+ if (empty($joined) ||
+ ! is_string($part) ||
+ preg_match('/[\[.:#%]/', $part)
+ ) {
+ $joined[] = $part;
continue;
}
- switch ($p[0]) {
- case 'interpolate':
- $p = $this->compileValue($p);
- break;
- case 'string':
- $p = $this->compileValue($p);
- break;
+ if (is_array(end($joined))) {
+ $joined[] = $part;
+ } else {
+ $joined[count($joined) - 1] .= $part;
}
}
- return $this->flattenSelectorSingle($piece);
+ return $joined;
}
// compiles to string
@@ -918,8 +924,8 @@ protected function compileChild($child, $out)
foreach ($selectors as $sel) {
// only use the first one
- $sel = current($this->evalSelector($sel));
- $this->pushExtends($sel, $out->selectors);
+ $result = $this->evalSelectors(array($sel));
+ $this->pushExtends(current($result[0]), $out->selectors);
}
break;
case 'if':
diff --git a/src/Parser.php b/src/Parser.php
index 10a85996..c9f80f43 100644
--- a/src/Parser.php
+++ b/src/Parser.php
@@ -170,6 +170,25 @@ public function parseValue($buffer, &$out)
return $this->valueList($out);
}
+ /**
+ * Parse a selector or selector list
+ *
+ * @param string $buffer
+ * @param string $out
+ *
+ * @return boolean
+ */
+ public function parseSelector($buffer, &$out)
+ {
+ $this->count = 0;
+ $this->env = null;
+ $this->inParens = false;
+ $this->eatWhiteDefault = true;
+ $this->buffer = (string) $buffer;
+
+ return $this->selectors($out);
+ }
+
/**
* Parse a single chunk off the head of the buffer and append it to the
* current parse environment.
diff --git a/tests/outputs/scss_css.css b/tests/outputs/scss_css.css
index 847c6132..b26a1c5b 100644
--- a/tests/outputs/scss_css.css
+++ b/tests/outputs/scss_css.css
@@ -174,7 +174,7 @@ foo {
12px {
a: b; }
-"foo" {
+foo {
a: b; }
foo {
diff --git a/tests/outputs/selectors.css b/tests/outputs/selectors.css
index f2c202e4..a08b904f 100644
--- a/tests/outputs/selectors.css
+++ b/tests/outputs/selectors.css
@@ -363,7 +363,7 @@ span a, p a, div a {
.parent.self1, .parent.self2 {
content: "should match .parent.self1, .parent.self2"; }
-.self1 .parent {
- content: "should match .self1 .parent"; }
-.parent + .parent {
- content: "should match .parent + .parent"; }
+ .self1 .parent {
+ content: "should match .self1 .parent"; }
+ .parent + .parent {
+ content: "should match .parent + .parent"; }
diff --git a/tests/outputs_numbered/scss_css.css b/tests/outputs_numbered/scss_css.css
index cf1b08f4..6da0ddac 100644
--- a/tests/outputs_numbered/scss_css.css
+++ b/tests/outputs_numbered/scss_css.css
@@ -185,7 +185,7 @@ foo {
12px {
a: b; }
/* line 195, inputs/scss_css.scss */
-"foo" {
+foo {
a: b; }
/* line 199, inputs/scss_css.scss */
foo {
From b4b43b8c5e198dee671828f90dbc2199d89bb863 Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Thu, 6 Aug 2015 20:36:50 -0400
Subject: [PATCH 040/534] Travis-CI: move to container infrastructure
---
.travis.yml | 1 +
1 file changed, 1 insertion(+)
diff --git a/.travis.yml b/.travis.yml
index 4b497d9b..8c3a2996 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,4 +1,5 @@
language: php
+sudo: false
php:
- 5.3
From f059d513b9a3d721edf9fc4533cc805ac1998aa0 Mon Sep 17 00:00:00 2001
From: David Sveningsson
Date: Tue, 11 Aug 2015 15:08:14 +0200
Subject: [PATCH 041/534] don't call autoloader
stupid autoloaders might log "errors" about missing files.
---
scss.inc.php | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/scss.inc.php b/scss.inc.php
index a60cd472..c93a46a9 100644
--- a/scss.inc.php
+++ b/scss.inc.php
@@ -3,7 +3,7 @@
die('Requires PHP 5.3 or above');
}
-if ( ! class_exists('scssc')) {
+if ( ! class_exists('scssc', false)) {
include_once __DIR__ . '/src/Base/Range.php';
include_once __DIR__ . '/src/Colors.php';
include_once __DIR__ . '/src/Compiler.php';
From 9227d4cebddd56e631550d04d95e45c96888eaaa Mon Sep 17 00:00:00 2001
From: jason_alan_kennedy
Date: Wed, 19 Aug 2015 22:49:08 +0000
Subject: [PATCH 042/534] Add gitattributes w/ export-ignore
This will allow for a production ready version of scssphp when archived/exported for release(s) and still allowing a development version within the repository.
The `export-ignore` excludes un-needed files and directories when a branch is archived for release but these files are still included when the repo is cloned/forked.
This would be very useful because releases are intended for production use and when users are using a package (via composer or zip), they most likely are not interested in downloading the source code as a whole into production, thus saving server disk space and meeting security protocol. Think of it as a .gitignore for releases.
- e.g. /tests folder, or your .travis.yml file, etc. will not be included in the release zip(s)
See: [git-scm.com - Exporting-Your-Repository](http://git-scm.com/book/en/v2/Customizing-Git-Git-Attributes#Exporting-Your-Repository)
---
.gitattributes | 12 ++++++++++++
1 file changed, 12 insertions(+)
create mode 100644 .gitattributes
diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 00000000..35c78edd
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1,12 @@
+# Ignore un-needed files and directories for export of production releases
+# Keeps src/
+#
+# See: http://git-scm.com/book/en/v2/Customizing-Git-Git-Attributes#Exporting-Your-Repository
+
+tests export-ignore
+.gitattributes export-ignore
+.gitignore export-ignore
+.travis.yml export-ignore
+box.json.dist export-ignore
+Makefile export-ignore
+phpunit.xml.dist export-ignore
\ No newline at end of file
From c943bbed12c59f7cd6b52791ac8ddfce326f92ae Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Wed, 19 Aug 2015 20:05:27 -0400
Subject: [PATCH 043/534] internals - reorg Compiler methods
---
src/Compiler.php | 170 +++++++++++++++++++++++------------------------
1 file changed, 85 insertions(+), 85 deletions(-)
diff --git a/src/Compiler.php b/src/Compiler.php
index 43262368..bb4196c1 100644
--- a/src/Compiler.php
+++ b/src/Compiler.php
@@ -204,79 +204,54 @@ protected function makeOutputBlock($type, $selectors = null)
return $out;
}
- protected function matchExtendsSingle($single, &$outOrigin)
+ protected function compileRoot($rootBlock)
{
- $counts = array();
- foreach ($single as $part) {
- if (! is_string($part)) {
- return false; // hmm
- }
+ $this->scope = $this->makeOutputBlock('root');
- if (isset($this->extendsMap[$part])) {
- foreach ($this->extendsMap[$part] as $idx) {
- $counts[$idx] =
- isset($counts[$idx]) ? $counts[$idx] + 1 : 1;
- }
- }
- }
+ $this->compileChildren($rootBlock->children, $this->scope);
+ $this->flattenSelectors($this->scope);
+ }
- $outOrigin = array();
- $found = false;
+ protected function flattenSelectors($block, $parentKey = null)
+ {
+ if ($block->selectors) {
+ $selectors = array();
- foreach ($counts as $idx => $count) {
- list($target, $origin) = $this->extends[$idx];
+ foreach ($block->selectors as $s) {
+ $selectors[] = $s;
- // check count
- if ($count != count($target)) {
- continue;
- }
+ if (! is_array($s)) {
+ continue;
+ }
- // check if target is subset of single
- if (array_diff(array_intersect($single, $target), $target)) {
- continue;
+ // check extends
+ if (! empty($this->extendsMap)) {
+ $this->matchExtends($s, $selectors);
+ }
}
- $rem = array_diff($single, $target);
+ $block->selectors = array();
+ $placeholderSelector = false;
- foreach ($origin as $j => $new) {
- // prevent infinite loop when target extends itself
- foreach ($new as $new_selector) {
- if (! array_diff($single, $new_selector)) {
- continue 2;
- }
+ foreach ($selectors as $selector) {
+ if ($this->hasSelectorPlaceholder($selector)) {
+ $placeholderSelector = true;
+ continue;
}
- $origin[$j][count($origin[$j]) - 1] = $this->combineSelectorSingle(end($new), $rem);
+ $block->selectors[] = $this->compileSelector($selector);
}
- $outOrigin = array_merge($outOrigin, $origin);
-
- $found = true;
- }
-
- return $found;
- }
-
- protected function combineSelectorSingle($base, $other)
- {
- $tag = null;
- $out = array();
+ if ($placeholderSelector && 0 == count($block->selectors) && null !== $parentKey) {
+ unset($block->parent->children[$parentKey]);
- foreach (array($base, $other) as $single) {
- foreach ($single as $part) {
- if (preg_match('/^[^\[.#:]/', $part)) {
- $tag = $part;
- } else {
- $out[] = $part;
- }
+ return;
}
}
- if ($tag) {
- array_unshift($out, $tag);
+ foreach ($block->children as $key => $child) {
+ $this->flattenSelectors($child, $key);
}
-
- return $out;
}
protected function matchExtends($selector, &$out, $from = 0, $initial = true)
@@ -333,54 +308,79 @@ protected function matchExtends($selector, &$out, $from = 0, $initial = true)
}
}
- protected function flattenSelectors($block, $parentKey = null)
+ protected function matchExtendsSingle($single, &$outOrigin)
{
- if ($block->selectors) {
- $selectors = array();
-
- foreach ($block->selectors as $s) {
- $selectors[] = $s;
+ $counts = array();
+ foreach ($single as $part) {
+ if (! is_string($part)) {
+ return false; // hmm
+ }
- if (! is_array($s)) {
- continue;
+ if (isset($this->extendsMap[$part])) {
+ foreach ($this->extendsMap[$part] as $idx) {
+ $counts[$idx] =
+ isset($counts[$idx]) ? $counts[$idx] + 1 : 1;
}
+ }
+ }
- // check extends
- if (! empty($this->extendsMap)) {
- $this->matchExtends($s, $selectors);
- }
+ $outOrigin = array();
+ $found = false;
+
+ foreach ($counts as $idx => $count) {
+ list($target, $origin) = $this->extends[$idx];
+
+ // check count
+ if ($count != count($target)) {
+ continue;
}
- $block->selectors = array();
- $placeholderSelector = false;
+ // check if target is subset of single
+ if (array_diff(array_intersect($single, $target), $target)) {
+ continue;
+ }
- foreach ($selectors as $selector) {
- if ($this->hasSelectorPlaceholder($selector)) {
- $placeholderSelector = true;
- continue;
+ $rem = array_diff($single, $target);
+
+ foreach ($origin as $j => $new) {
+ // prevent infinite loop when target extends itself
+ foreach ($new as $new_selector) {
+ if (! array_diff($single, $new_selector)) {
+ continue 2;
+ }
}
- $block->selectors[] = $this->compileSelector($selector);
+ $origin[$j][count($origin[$j]) - 1] = $this->combineSelectorSingle(end($new), $rem);
}
- if ($placeholderSelector && 0 == count($block->selectors) && null !== $parentKey) {
- unset($block->parent->children[$parentKey]);
+ $outOrigin = array_merge($outOrigin, $origin);
- return;
- }
+ $found = true;
}
- foreach ($block->children as $key => $child) {
- $this->flattenSelectors($child, $key);
- }
+ return $found;
}
- protected function compileRoot($rootBlock)
+ protected function combineSelectorSingle($base, $other)
{
- $this->scope = $this->makeOutputBlock('root');
+ $tag = null;
+ $out = array();
- $this->compileChildren($rootBlock->children, $this->scope);
- $this->flattenSelectors($this->scope);
+ foreach (array($base, $other) as $single) {
+ foreach ($single as $part) {
+ if (preg_match('/^[^\[.#:]/', $part)) {
+ $tag = $part;
+ } else {
+ $out[] = $part;
+ }
+ }
+ }
+
+ if ($tag) {
+ array_unshift($out, $tag);
+ }
+
+ return $out;
}
protected function compileMedia($media)
From 8d610a68156022272615b842406bbd97a6386a32 Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Wed, 19 Aug 2015 21:14:24 -0400
Subject: [PATCH 044/534] internals - style
---
bin/pscss | 2 +-
scss.inc.php | 2 +-
src/Compiler.php | 94 +++++++++++++++++++++++++++++++++++++++++++-----
src/Parser.php | 29 ++++++++++-----
4 files changed, 108 insertions(+), 19 deletions(-)
diff --git a/bin/pscss b/bin/pscss
index 4ef6d389..8a21393e 100755
--- a/bin/pscss
+++ b/bin/pscss
@@ -140,7 +140,7 @@ if ($inputFile) {
} else {
$data = '';
- while ( ! feof(STDIN)) {
+ while (! feof(STDIN)) {
$data .= fread(STDIN, 8192);
}
}
diff --git a/scss.inc.php b/scss.inc.php
index c93a46a9..51ae57e5 100644
--- a/scss.inc.php
+++ b/scss.inc.php
@@ -3,7 +3,7 @@
die('Requires PHP 5.3 or above');
}
-if ( ! class_exists('scssc', false)) {
+if (! class_exists('scssc', false)) {
include_once __DIR__ . '/src/Base/Range.php';
include_once __DIR__ . '/src/Colors.php';
include_once __DIR__ . '/src/Compiler.php';
diff --git a/src/Compiler.php b/src/Compiler.php
index bb4196c1..b99a28f4 100644
--- a/src/Compiler.php
+++ b/src/Compiler.php
@@ -311,6 +311,7 @@ protected function matchExtends($selector, &$out, $from = 0, $initial = true)
protected function matchExtendsSingle($single, &$outOrigin)
{
$counts = array();
+
foreach ($single as $part) {
if (! is_string($part)) {
return false; // hmm
@@ -400,6 +401,7 @@ protected function compileMedia($media)
foreach ($media->children as $child) {
$type = $child[0];
+
if ($type !== 'block' && $type !== 'media' && $type !== 'directive') {
$needsWrap = true;
break;
@@ -484,6 +486,7 @@ protected function compileBlock($block)
case self::LINE_COMMENTS:
$annotation->lines[] = '/* line ' . $line . ', ' . $file . ' */';
break;
+
case self::DEBUG_INFO:
$annotation->lines[] = '@media -sass-debug-info{filename{font-family:"' . $file
. '"}line{font-family:' . $line . '}}';
@@ -574,6 +577,7 @@ function ($value, $key) use (&$output) {
protected function flattenSelectorSingle($single)
{
$joined = array();
+
foreach ($single as $part) {
if (empty($joined) ||
! is_string($part) ||
@@ -621,6 +625,7 @@ protected function compileSelectorPart($piece)
case 'self':
$p = '&';
break;
+
default:
$p = $this->compileValue($p);
break;
@@ -683,6 +688,7 @@ protected function compileMediaQuery($queryList)
$type = array_map(array($this, 'compileValue'), array_slice($q, 1));
}
break;
+
case 'mediaExp':
if (isset($q[2])) {
$parts[] = '('
@@ -790,6 +796,7 @@ protected function compileImport($rawPath, $out)
return false;
}
+
if ($rawPath[0] == 'list') {
// handle a list of strings
if (count($rawPath[2]) == 0) {
@@ -823,25 +830,32 @@ protected function compileChild($child, $out)
list(, $rawPath) = $child;
$rawPath = $this->reduce($rawPath);
+
if (! $this->compileImport($rawPath, $out)) {
$out->lines[] = '@import ' . $this->compileValue($rawPath) . ';';
}
break;
+
case 'directive':
list(, $directive) = $child;
$s = '@' . $directive->name;
+
if (! empty($directive->value)) {
$s .= ' ' . $this->compileValue($directive->value);
}
+
$this->compileNestedBlock($directive, array($s));
break;
+
case 'media':
$this->compileMedia($child[1]);
break;
+
case 'block':
$this->compileBlock($child[1]);
break;
+
case 'charset':
if (! $this->charsetSeen) {
$this->charsetSeen = true;
@@ -849,6 +863,7 @@ protected function compileChild($child, $out)
$out->lines[] = '@charset ' . $this->compileValue($child[1]) . ';';
}
break;
+
case 'assign':
list(, $name, $value) = $child;
@@ -893,6 +908,7 @@ protected function compileChild($child, $out)
// the property should be discarded
if ($value[0] != 'null') {
$value = $this->reduce($value);
+
if ($value[0] == 'null') {
break;
}
@@ -905,6 +921,7 @@ protected function compileChild($child, $out)
$compiledValue
);
break;
+
case 'comment':
if ($out->type == 'root') {
$this->compileComment($child);
@@ -913,12 +930,14 @@ protected function compileChild($child, $out)
$out->lines[] = $child[1];
break;
+
case 'mixin':
case 'function':
list(, $block) = $child;
$this->set(self::$namespaces[$block->type] . $block->name, $block);
break;
+
case 'extend':
list(, $selectors) = $child;
@@ -928,27 +947,31 @@ protected function compileChild($child, $out)
$this->pushExtends(current($result[0]), $out->selectors);
}
break;
+
case 'if':
list(, $if) = $child;
if ($this->isTruthy($this->reduce($if->cond, true))) {
return $this->compileChildren($if->children, $out);
- } else {
- foreach ($if->cases as $case) {
- if ($case->type == 'else' ||
- $case->type == 'elseif' && $this->isTruthy($this->reduce($case->cond))
- ) {
- return $this->compileChildren($case->children, $out);
- }
+ }
+
+ foreach ($if->cases as $case) {
+ if ($case->type == 'else' ||
+ $case->type == 'elseif' && $this->isTruthy($this->reduce($case->cond))
+ ) {
+ return $this->compileChildren($case->children, $out);
}
}
break;
+
case 'return':
return $this->reduce($child[1], true);
+
case 'each':
list(, $each) = $child;
$list = $this->coerceList($this->reduce($each->list));
+
foreach ($list[2] as $item) {
$this->pushEnv();
@@ -956,6 +979,7 @@ protected function compileChild($child, $out)
$this->set($each->vars[0], $item);
} else {
list(,, $values) = $this->coerceList($item);
+
foreach ($each->vars as $i => $var) {
$this->set($var, isset($values[$i]) ? $values[$i] : self::$null);
}
@@ -969,6 +993,7 @@ protected function compileChild($child, $out)
}
}
break;
+
case 'while':
list(, $while) = $child;
@@ -980,6 +1005,7 @@ protected function compileChild($child, $out)
}
}
break;
+
case 'for':
list(, $for) = $child;
@@ -1007,6 +1033,7 @@ protected function compileChild($child, $out)
}
break;
+
case 'nestedprop':
list(, $prop) = $child;
@@ -1027,6 +1054,7 @@ protected function compileChild($child, $out)
$this->compileChildren($prefixed, $out);
break;
+
case 'include':
// including a mixin
list(, $name, $argValues, $content) = $child;
@@ -1061,6 +1089,7 @@ protected function compileChild($child, $out)
$this->popEnv();
break;
+
case 'mixin_content':
$content = $this->get(self::$namespaces['special'] . 'content');
@@ -1084,6 +1113,7 @@ protected function compileChild($child, $out)
unset($this->storeEnv);
break;
+
case 'debug':
list(, $value) = $child;
@@ -1091,6 +1121,7 @@ protected function compileChild($child, $out)
$value = $this->compileValue($this->reduce($value, true));
fwrite($this->stderr, "Line $line DEBUG: $value\n");
break;
+
case 'warn':
list(, $value) = $child;
@@ -1098,6 +1129,7 @@ protected function compileChild($child, $out)
$value = $this->compileValue($this->reduce($value, true));
echo "Line $line WARN: $value\n";
break;
+
case 'error':
list(, $value) = $child;
@@ -1105,6 +1137,7 @@ protected function compileChild($child, $out)
$value = $this->compileValue($this->reduce($value, true));
$this->throwError("Line $line ERROR: $value\n");
break;
+
default:
$this->throwError("unknown child type: $child[0]");
}
@@ -1150,12 +1183,14 @@ protected function shouldEval($value)
case 'fncall':
return true;
}
+
return false;
}
protected function reduce($value, $inExp = false)
{
list($type) = $value;
+
switch ($type) {
case 'exp':
list(, $op, $left, $right, $inParens) = $value;
@@ -1186,6 +1221,7 @@ protected function reduce($value, $inExp = false)
// 2. op[left type][right type] (passing the op as first arg
// 3. op[op name]
$fn = "op${ucOpName}${ucLType}${ucRType}";
+
if (is_callable(array($this, $fn)) ||
(($fn = "op${ucLType}${ucRType}") &&
is_callable(array($this, $fn)) &&
@@ -1248,6 +1284,7 @@ protected function reduce($value, $inExp = false)
}
return $this->expToString($value);
+
case 'unary':
list(, $op, $exp, $inParens) = $value;
@@ -1258,6 +1295,7 @@ protected function reduce($value, $inExp = false)
switch ($op) {
case '+':
return $exp;
+
case '-':
$exp[1] *= -1;
@@ -1272,22 +1310,25 @@ protected function reduce($value, $inExp = false)
}
return self::$false;
- } else {
- $op = $op . ' ';
}
+
+ $op = $op . ' ';
}
return array('string', '', array($op, $exp));
+
case 'var':
list(, $name) = $value;
return $this->reduce($this->get($name));
+
case 'list':
foreach ($value[2] as &$item) {
$item = $this->reduce($item);
}
return $value;
+
case 'map':
foreach ($value[1] as &$item) {
$item = $this->reduce($item);
@@ -1298,6 +1339,7 @@ protected function reduce($value, $inExp = false)
}
return $value;
+
case 'string':
foreach ($value[2] as &$item) {
if (is_array($item)) {
@@ -1306,10 +1348,12 @@ protected function reduce($value, $inExp = false)
}
return $value;
+
case 'interpolate':
$value[1] = $this->reduce($value[1]);
return $value;
+
case 'fncall':
list(, $name, $argValues) = $value;
@@ -1352,6 +1396,7 @@ protected function reduce($value, $inExp = false)
}
return array('function', $name, array('list', ',', $listArgs));
+
default:
return $value;
}
@@ -1497,25 +1542,33 @@ protected function opColorColor($op, $left, $right)
case '+':
$out[] = $lval + $rval;
break;
+
case '-':
$out[] = $lval - $rval;
break;
+
case '*':
$out[] = $lval * $rval;
break;
+
case '%':
$out[] = $lval % $rval;
break;
+
case '/':
if ($rval == 0) {
$this->throwError("color: Can't divide by zero");
}
+
$out[] = (int) ($lval / $rval);
break;
+
case '==':
return $this->opEq($left, $right);
+
case '!=':
return $this->opNeq($left, $right);
+
default:
$this->throwError("color: unknown op $op");
}
@@ -1627,6 +1680,7 @@ public function compileValue($value)
switch ($type) {
case 'keyword':
return $value[1];
+
case 'color':
// [1] - red component (either number for a %)
// [2] - green component
@@ -1650,13 +1704,18 @@ public function compileValue($value)
}
return $h;
+
case 'number':
return round($value[1], $this->numberPrecision) . $value[2];
+
case 'string':
return $value[1] . $this->compileStringContent($value) . $value[1];
+
case 'function':
$args = ! empty($value[2]) ? $this->compileValue($value[2]) : '';
+
return "$value[1]($args)";
+
case 'list':
$value = $this->extractInterpolation($value);
@@ -1667,6 +1726,7 @@ public function compileValue($value)
list(, $delim, $items) = $value;
$filtered = array();
+
foreach ($items as $item) {
if ($item[0] == 'null') {
continue;
@@ -1676,6 +1736,7 @@ public function compileValue($value)
}
return implode("$delim ", $filtered);
+
case 'map':
$keys = $value[1];
$values = $value[2];
@@ -1690,6 +1751,7 @@ public function compileValue($value)
});
return '(' . implode(', ', $filtered) . ')';
+
case 'interpolated':
// node created by extractInterpolation
list(, $interpolate, $left, $right) = $value;
@@ -1719,8 +1781,10 @@ public function compileValue($value)
}
return $this->compileValue($reduced);
+
case 'null':
return 'null';
+
default:
$this->throwError("unknown value type: $type");
}
@@ -2209,7 +2273,9 @@ protected function sortArgs($prototype, $args)
foreach ($args as $arg) {
list($key, $value) = $arg;
+
$key = $key[1];
+
if (empty($key)) {
$posArgs[] = $value;
} else {
@@ -2230,6 +2296,7 @@ protected function sortArgs($prototype, $args)
}
$set = false;
+
foreach ((array)$names as $name) {
if (isset($keyArgs[$name])) {
$finalArgs[] = $keyArgs[$name];
@@ -2307,9 +2374,11 @@ protected function applyArguments($argDef, $argValues)
if ($isVariable) {
$val = array('list', ',', array(), $isVariable);
+
for ($count = count($remaining); $i < $count; $i++) {
$val[2][] = $remaining[$i];
}
+
foreach ($deferredKeywordArgs as $itemName => $item) {
$val[2][$itemName] = $item;
}
@@ -2439,11 +2508,14 @@ protected function coerceString($value)
switch ($value[0]) {
case 'string':
return $value;
+
case 'function':
return array('string', '', array($value[1] . '(' . $this->flattenList($value[2]) . ')'));
+
case 'keyword':
return array('string', '', array($value[1]));
}
+
return null;
}
@@ -2820,6 +2892,7 @@ protected function libOpacity($args)
protected function libMix($args)
{
list($first, $second, $weight) = $args;
+
$first = $this->assertColor($first);
$second = $this->assertColor($second);
@@ -3297,8 +3370,10 @@ protected function listSeparatorForJoin($list1, $sep)
switch ($this->compileValue($sep)) {
case 'comma':
return ',';
+
case 'space':
return '';
+
default:
return $list1[1];
}
@@ -3370,6 +3445,7 @@ protected function libTypeOf($args)
// fall-thru
case 'function':
return 'string';
+
case 'list':
if (isset($value[3]) && $value[3]) {
return 'arglist';
diff --git a/src/Parser.php b/src/Parser.php
index c9f80f43..3f3afee2 100644
--- a/src/Parser.php
+++ b/src/Parser.php
@@ -342,9 +342,11 @@ protected function parseChunk()
$this->literal('{')
) {
$each = $this->pushSpecialBlock('each', $s);
+
foreach ($varNames[2] as $varName) {
$each->vars[] = $varName[1];
}
+
$each->list = $list;
return true;
@@ -436,6 +438,7 @@ protected function parseChunk()
$this->seek($s);
$last = $this->last();
+
if (isset($last) && $last[0] == 'if') {
list(, $if) = $last;
@@ -545,6 +548,7 @@ protected function parseChunk()
// property assign, or nested assign
if ($this->propertyName($name) && $this->literal(':')) {
$foundSomething = false;
+
if ($this->valueList($value)) {
$this->append(array('assign', $name, $value), $s);
$foundSomething = true;
@@ -731,6 +735,7 @@ protected function append($statement, $pos = null)
$this->env->children[] = $statement;
$comments = $this->env->comments;
+
if (count($comments)) {
$this->env->children = array_merge($this->env->children, $comments);
$this->env->comments = array();
@@ -841,6 +846,7 @@ protected function argValue(&$out)
$s = $this->seek();
$keyword = null;
+
if (! $this->variable($keyword) || ! $this->literal(':')) {
$this->seek($s);
$keyword = null;
@@ -1082,6 +1088,7 @@ protected function progid(&$out)
$this->literal('(')
) {
$this->openString(')', $args, '(');
+
if ($this->literal(')')) {
$out = array('string', '', array(
'progid:', $fn, '(', $args, ')'
@@ -1407,9 +1414,11 @@ protected function openString($end, &$out, $nestingOpen = null)
$nestingLevel = 0;
$content = array();
+
while ($this->match($patt, $m, false)) {
if (isset($m[1]) && $m[1] !== '') {
$content[] = $m[1];
+
if ($nestingOpen) {
$nestingLevel += substr_count($m[1], $nestingOpen);
}
@@ -1418,12 +1427,9 @@ protected function openString($end, &$out, $nestingOpen = null)
$tok = $m[2];
$this->count-= strlen($tok);
- if ($tok == $end) {
- if ($nestingLevel == 0) {
- break;
- } else {
- $nestingLevel--;
- }
+
+ if ($tok == $end && ! $nestingLevel--) {
+ break;
}
if (($tok == '\'' || $tok == '"') && $this->string($str)) {
@@ -1463,6 +1469,7 @@ protected function interpolation(&$out, $lookWhite = true)
$this->eatWhiteDefault = true;
$s = $this->seek();
+
if ($this->literal('#{') && $this->valueList($value) && $this->literal('}', false)) {
// TODO: don't error if out of bounds
@@ -1475,6 +1482,7 @@ protected function interpolation(&$out, $lookWhite = true)
$out = array('interpolate', $value, $left, $right);
$this->eatWhiteDefault = $oldWhite;
+
if ($this->eatWhiteDefault) {
$this->whitespace();
}
@@ -1511,6 +1519,7 @@ protected function propertyName(&$out)
}
$this->eatWhiteDefault = $oldWhite;
+
if (count($parts) == 0) {
return false;
}
@@ -1613,6 +1622,7 @@ protected function selectorSingle(&$out)
}
$s = $this->seek();
+
// self
if ($this->literal('&', false)) {
$parts[] = Compiler::$selfSelector;
@@ -1664,6 +1674,7 @@ protected function selectorSingle(&$out)
// a pseudo selector
if ($this->match('::?', $m) && $this->mixedKeyword($nameParts)) {
$parts[] = $m[0];
+
foreach ($nameParts as $sub) {
$parts[] = $sub;
}
@@ -1686,14 +1697,15 @@ protected function selectorSingle(&$out)
}
continue;
- } else {
- $this->seek($s);
}
+ $this->seek($s);
+
// attribute selector
// TODO: replace with open string?
if ($this->literal('[', false)) {
$attrParts = array('[');
+
// keyword, string, operator
while (true) {
if ($this->literal(']', false)) {
@@ -1705,6 +1717,7 @@ protected function selectorSingle(&$out)
$attrParts[] = ' ';
continue;
}
+
if ($this->string($str)) {
$attrParts[] = $str;
continue;
From b6826881d595e0447f85f0dc132995799624cea0 Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Wed, 19 Aug 2015 22:59:45 -0400
Subject: [PATCH 045/534] Add TODO
---
src/Compiler.php | 1 +
1 file changed, 1 insertion(+)
diff --git a/src/Compiler.php b/src/Compiler.php
index b99a28f4..a0de34e3 100644
--- a/src/Compiler.php
+++ b/src/Compiler.php
@@ -336,6 +336,7 @@ protected function matchExtendsSingle($single, &$outOrigin)
continue;
}
+ // TODO: this conditional is always false...
// check if target is subset of single
if (array_diff(array_intersect($single, $target), $target)) {
continue;
From 172d51161fc0fe764e4924f538b0e63feff0c3ad Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Thu, 20 Aug 2015 07:32:08 -0400
Subject: [PATCH 046/534] Remove awkward version/syntax statement.
---
README.md | 3 ---
1 file changed, 3 deletions(-)
diff --git a/README.md b/README.md
index 763341a2..53a4c7a4 100644
--- a/README.md
+++ b/README.md
@@ -6,9 +6,6 @@
`scssphp` is a compiler for SCSS written in PHP.
-It primarily implements SCSS 3.2.16, with some 3.3.x/3.4.x compatibility. It does not implement the SASS syntax, only the SCSS
-syntax.
-
Checkout the homepage, , for directions on how to use.
## Running Tests
From 58281d941d00dbb3850cbb1694930e26950ff5ed Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Sun, 23 Aug 2015 11:51:10 -0400
Subject: [PATCH 047/534] 3 year old extend bug - fixes #28, #117, #158
---
src/Compiler.php | 24 +++----
tests/FailingTest.php | 106 -----------------------------
tests/inputs/extends.scss | 67 ++++++++++++++++++
tests/outputs/extends.css | 31 +++++++++
tests/outputs_numbered/extends.css | 51 ++++++++++++++
5 files changed, 159 insertions(+), 120 deletions(-)
diff --git a/src/Compiler.php b/src/Compiler.php
index a0de34e3..5c65ca47 100644
--- a/src/Compiler.php
+++ b/src/Compiler.php
@@ -227,6 +227,11 @@ protected function flattenSelectors($block, $parentKey = null)
// check extends
if (! empty($this->extendsMap)) {
$this->matchExtends($s, $selectors);
+
+ // remove duplicates
+ array_walk($selectors, function (&$value) { $value = json_encode($value); });
+ $selectors = array_unique($selectors);
+ array_walk($selectors, function (&$value) { $value = json_decode($value); });
}
}
@@ -270,10 +275,8 @@ protected function matchExtends($selector, &$out, $from = 0, $initial = true)
// remove shared parts
if ($initial) {
- foreach ($before as $k => $val) {
- if (! isset($new[$k]) || $val != $new[$k]) {
- break;
- }
+ while (isset($new[$k]) && $before[$k] === $new[$k]) {
+ $k++;
}
}
@@ -319,8 +322,7 @@ protected function matchExtendsSingle($single, &$outOrigin)
if (isset($this->extendsMap[$part])) {
foreach ($this->extendsMap[$part] as $idx) {
- $counts[$idx] =
- isset($counts[$idx]) ? $counts[$idx] + 1 : 1;
+ $counts[$idx] = isset($counts[$idx]) ? $counts[$idx] + 1 : 1;
}
}
}
@@ -336,19 +338,13 @@ protected function matchExtendsSingle($single, &$outOrigin)
continue;
}
- // TODO: this conditional is always false...
- // check if target is subset of single
- if (array_diff(array_intersect($single, $target), $target)) {
- continue;
- }
-
$rem = array_diff($single, $target);
foreach ($origin as $j => $new) {
// prevent infinite loop when target extends itself
foreach ($new as $new_selector) {
- if (! array_diff($single, $new_selector)) {
- continue 2;
+ if ($single === $new_selector) {
+ return false;
}
}
diff --git a/tests/FailingTest.php b/tests/FailingTest.php
index fd7f280f..f6ec0ffc 100644
--- a/tests/FailingTest.php
+++ b/tests/FailingTest.php
@@ -62,73 +62,6 @@ public function provideFailing()
{
// @codingStandardsIgnoreStart
return array(
- array(
- '#28 - @extend working unexpected', <<<'END_OF_SCSS'
-#content {
-
- .social-login {
- display: block;
- float: right;
- margin-right: 15px;
- width: 250px;
-
- .facebook {
- display: block;
- width: 255px;
- height: 42px;
- background: transparent url('images/login-btns.png') no-repeat;
- background-position: 0 0;
-
- &:hover {
- background-position: 0 -43px;
- }
-
- &:focus, &:active {
- background-position: 0 -86px;
- }
- }
-
- .twitter {
-
- @extend .facebook;
- background-position: 0 -129px;
-
- &:hover {
- background-position: 0 -172px;
- }
-
- &:active, &:focus {
- background-position: 0 -215px;
- }
- }
-
- }
-}
-END_OF_SCSS
- , <<
Date: Sun, 23 Aug 2015 12:12:31 -0400
Subject: [PATCH 048/534] bump version to 0.1.10
---
src/Version.php | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/Version.php b/src/Version.php
index 6f9285b0..0f419fa9 100644
--- a/src/Version.php
+++ b/src/Version.php
@@ -18,5 +18,5 @@
*/
class Version
{
- const VERSION = 'v0.1.9';
+ const VERSION = 'v0.1.10';
}
From 8a37178de2ff86006915188677b73f78634d6ef7 Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Sun, 23 Aug 2015 12:26:31 -0400
Subject: [PATCH 049/534] add guard to the loop
---
src/Compiler.php | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/src/Compiler.php b/src/Compiler.php
index 5c65ca47..1527af07 100644
--- a/src/Compiler.php
+++ b/src/Compiler.php
@@ -269,13 +269,14 @@ protected function matchExtends($selector, &$out, $from = 0, $initial = true)
if ($this->matchExtendsSingle($part, $origin)) {
$before = array_slice($selector, 0, $i);
$after = array_slice($selector, $i + 1);
+ $s = count($before);
foreach ($origin as $new) {
$k = 0;
// remove shared parts
if ($initial) {
- while (isset($new[$k]) && $before[$k] === $new[$k]) {
+ while ($k < $s && isset($new[$k]) && $before[$k] === $new[$k]) {
$k++;
}
}
From e67f9cb33c4296763834d48d5cc8ca8363438211 Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Sun, 23 Aug 2015 16:33:08 -0400
Subject: [PATCH 050/534] class documentation complete! fixes #83
---
classmap.php | 2 +
src/Compiler.php | 749 ++++++++++++++++++++++++++++++++++++++++++++--
src/Formatter.php | 3 +
src/Parser.php | 334 +++++++++++++++++++--
src/Util.php | 5 +-
5 files changed, 1049 insertions(+), 44 deletions(-)
diff --git a/classmap.php b/classmap.php
index 267eecd6..2d8a52b8 100644
--- a/classmap.php
+++ b/classmap.php
@@ -11,6 +11,7 @@
* @link http://leafo.github.io/scssphp
*/
+// @codingStandardsIgnoreStart
/**
* @deprecated since 0.1.0
*/
@@ -59,3 +60,4 @@ class scss_formatter_crunched extends \Leafo\ScssPhp\Formatter\Crunched
class scss_server extends \Leafo\ScssPhp\Server
{
}
+// @codingStandardsIgnoreEnd
diff --git a/src/Compiler.php b/src/Compiler.php
index 1527af07..85879c44 100644
--- a/src/Compiler.php
+++ b/src/Compiler.php
@@ -53,6 +53,9 @@ class Compiler
const LINE_COMMENTS = 1;
const DEBUG_INFO = 2;
+ /**
+ * @var array
+ */
static protected $operatorNames = array(
'+' => 'add',
'-' => 'sub',
@@ -69,12 +72,18 @@ class Compiler
'>=' => 'gte',
);
+ /**
+ * @var array
+ */
static protected $namespaces = array(
'special' => '%',
'mixin' => '@',
'function' => '^',
);
+ /**
+ * @var array
+ */
static protected $unitTable = array(
'in' => array(
'in' => 1,
@@ -124,6 +133,8 @@ class Compiler
/**
* Compile scss
*
+ * @api
+ *
* @param string $code
* @param string $name
*
@@ -162,6 +173,14 @@ public function compile($code, $name = null)
return $out;
}
+ /**
+ * Is self extend?
+ *
+ * @param array $target
+ * @param array $origin
+ *
+ * @return boolean
+ */
protected function isSelfExtend($target, $origin)
{
foreach ($origin as $sel) {
@@ -173,6 +192,12 @@ protected function isSelfExtend($target, $origin)
return false;
}
+ /**
+ * Push extends
+ *
+ * @param array $target
+ * @param array $origin
+ */
protected function pushExtends($target, $origin)
{
if ($this->isSelfExtend($target, $origin)) {
@@ -191,6 +216,14 @@ protected function pushExtends($target, $origin)
}
}
+ /**
+ * Make output block
+ *
+ * @param string $type
+ * @param array $selectors
+ *
+ * @return \stdClass
+ */
protected function makeOutputBlock($type, $selectors = null)
{
$out = new \stdClass;
@@ -204,6 +237,11 @@ protected function makeOutputBlock($type, $selectors = null)
return $out;
}
+ /**
+ * Compile root
+ *
+ * @param \stdClass $rootBlock
+ */
protected function compileRoot($rootBlock)
{
$this->scope = $this->makeOutputBlock('root');
@@ -212,6 +250,12 @@ protected function compileRoot($rootBlock)
$this->flattenSelectors($this->scope);
}
+ /**
+ * Flatten selectors
+ *
+ * @param \stdClass $block
+ * @parent string $parentKey
+ */
protected function flattenSelectors($block, $parentKey = null)
{
if ($block->selectors) {
@@ -229,9 +273,13 @@ protected function flattenSelectors($block, $parentKey = null)
$this->matchExtends($s, $selectors);
// remove duplicates
- array_walk($selectors, function (&$value) { $value = json_encode($value); });
+ array_walk($selectors, function (&$value) {
+ $value = json_encode($value);
+ });
$selectors = array_unique($selectors);
- array_walk($selectors, function (&$value) { $value = json_decode($value); });
+ array_walk($selectors, function (&$value) {
+ $value = json_decode($value);
+ });
}
}
@@ -259,6 +307,14 @@ protected function flattenSelectors($block, $parentKey = null)
}
}
+ /**
+ * Match extends
+ *
+ * @param array $selector
+ * @param array $out
+ * @param integer $from
+ * @param boolean $initial
+ */
protected function matchExtends($selector, &$out, $from = 0, $initial = true)
{
foreach ($selector as $i => $part) {
@@ -312,6 +368,14 @@ protected function matchExtends($selector, &$out, $from = 0, $initial = true)
}
}
+ /**
+ * Match extends single
+ *
+ * @param array $single
+ * @param array $outOrigin
+ *
+ * @return boolean
+ */
protected function matchExtendsSingle($single, &$outOrigin)
{
$counts = array();
@@ -360,6 +424,14 @@ protected function matchExtendsSingle($single, &$outOrigin)
return $found;
}
+ /**
+ * Combine selector single
+ *
+ * @param array $base
+ * @param array $other
+ *
+ * @return array
+ */
protected function combineSelectorSingle($base, $other)
{
$tag = null;
@@ -382,6 +454,11 @@ protected function combineSelectorSingle($base, $other)
return $out;
}
+ /**
+ * Compile media
+ *
+ * @param \stdClass $media
+ */
protected function compileMedia($media)
{
$this->pushEnv($media);
@@ -422,19 +499,34 @@ protected function compileMedia($media)
$this->popEnv();
}
+ /**
+ * Media parent
+ *
+ * @param \stdClass $scope
+ *
+ * @return \stdClass
+ */
protected function mediaParent($scope)
{
while (! empty($scope->parent)) {
if (! empty($scope->type) && $scope->type != 'media') {
break;
}
+
$scope = $scope->parent;
}
return $scope;
}
- // TODO: refactor compileNestedBlock and compileMedia into same thing?
+ /**
+ * Compile nested block
+ *
+ * @todo refactor compileNestedBlock and compileMedia into same thing?
+ *
+ * @param \stdClass $block
+ * @param array $selectors
+ */
protected function compileNestedBlock($block, $selectors)
{
$this->pushEnv($block);
@@ -503,7 +595,11 @@ protected function compileBlock($block)
$this->popEnv();
}
- // root level comment
+ /**
+ * Compile root level comment
+ *
+ * @param array $block
+ */
protected function compileComment($block)
{
$out = $this->makeOutputBlock('comment');
@@ -511,6 +607,13 @@ protected function compileComment($block)
$this->scope->children[] = $out;
}
+ /**
+ * Evaluate selectors
+ *
+ * @param array $selectors
+ *
+ * @return array
+ */
protected function evalSelectors($selectors)
{
$this->shouldEvaluate = false;
@@ -530,12 +633,25 @@ protected function evalSelectors($selectors)
return $selectors;
}
+ /**
+ * Evaluate selector
+ *
+ * @param array $selector
+ *
+ * @return array
+ */
protected function evalSelector($selector)
{
return array_map(array($this, 'evalSelectorPart'), $selector);
}
- // replaces all the interpolates, stripping quotes
+ /**
+ * Evaluate selector part; replaces all the interpolates, stripping quotes
+ *
+ * @param array $part
+ *
+ * @return array
+ */
protected function evalSelectorPart($part)
{
foreach ($part as &$p) {
@@ -557,6 +673,13 @@ protected function evalSelectorPart($part)
return $this->flattenSelectorSingle($part);
}
+ /**
+ * Collapse selectors
+ *
+ * @param array $selectors
+ *
+ * @return string
+ */
protected function collapseSelectors($selectors)
{
$output = '';
@@ -571,7 +694,13 @@ function ($value, $key) use (&$output) {
return $output;
}
- // joins together .classes and #ids
+ /**
+ * Flatten selector single; joins together .classes and #ids
+ *
+ * @param array $single
+ *
+ * @return array
+ */
protected function flattenSelectorSingle($single)
{
$joined = array();
@@ -595,8 +724,13 @@ protected function flattenSelectorSingle($single)
return $joined;
}
- // compiles to string
- // self(&) should have been replaced by now
+ /**
+ * Compile selector to string; self(&) should have been replaced by now
+ *
+ * @param array $selector
+ *
+ * @return string
+ */
protected function compileSelector($selector)
{
if (! is_array($selector)) {
@@ -612,6 +746,13 @@ protected function compileSelector($selector)
);
}
+ /**
+ * Compile selector part
+ *
+ * @param arary $piece
+ *
+ * @return string
+ */
protected function compileSelectorPart($piece)
{
foreach ($piece as &$p) {
@@ -633,6 +774,13 @@ protected function compileSelectorPart($piece)
return implode($piece);
}
+ /**
+ * Has selector placeholder?
+ *
+ * @param array $selector
+ *
+ * @return boolean
+ */
protected function hasSelectorPlaceholder($selector)
{
if (! is_array($selector)) {
@@ -650,6 +798,14 @@ protected function hasSelectorPlaceholder($selector)
return false;
}
+ /**
+ * Compile children
+ *
+ * @param array $stms
+ * @param array $out
+ *
+ * @return array
+ */
protected function compileChildren($stms, $out)
{
foreach ($stms as $stm) {
@@ -661,6 +817,13 @@ protected function compileChildren($stms, $out)
}
}
+ /**
+ * Compile media query
+ *
+ * @param array $queryList
+ *
+ * @return string
+ */
protected function compileMediaQuery($queryList)
{
$out = '@media';
@@ -722,6 +885,14 @@ protected function compileMediaQuery($queryList)
return $out;
}
+ /**
+ * Merge media types
+ *
+ * @param array $type1
+ * @param array $type2
+ *
+ * @return array|null
+ */
protected function mergeMediaTypes($type1, $type2)
{
if (empty($type1)) {
@@ -780,7 +951,14 @@ protected function mergeMediaTypes($type1, $type2)
return array(empty($m1)? $m2 : $m1, $t1);
}
- // returns true if the value was something that could be imported
+ /**
+ * Compile import; returns true if the value was something that could be imported
+ *
+ * @param array $rawPath
+ * @param array $out
+ *
+ * @return boolean
+ */
protected function compileImport($rawPath, $out)
{
if ($rawPath[0] == 'string') {
@@ -817,7 +995,14 @@ protected function compileImport($rawPath, $out)
return false;
}
- // return a value to halt execution
+ /**
+ * Compile child; returns a value to halt execution
+ *
+ * @param array $child
+ * @param \stdClass $out
+ *
+ * @return array
+ */
protected function compileChild($child, $out)
{
$this->sourcePos = isset($child[Parser::SOURCE_POSITION]) ? $child[Parser::SOURCE_POSITION] : -1;
@@ -1141,6 +1326,13 @@ protected function compileChild($child, $out)
}
}
+ /**
+ * Reduce expression to string
+ *
+ * @param array $exp
+ *
+ * @return array
+ */
protected function expToString($exp)
{
list(, $op, $left, $right, $inParens, $whiteLeft, $whiteRight) = $exp;
@@ -1162,12 +1354,25 @@ protected function expToString($exp)
return array('string', '', $content);
}
+ /**
+ * Is truthy?
+ *
+ * @param array $value
+ *
+ * @return array
+ */
protected function isTruthy($value)
{
return $value != self::$false && $value != self::$null;
}
- // should $value cause its operand to eval
+ /**
+ * Should $value cause its operand to eval
+ *
+ * @param array $value
+ *
+ * @return boolean
+ */
protected function shouldEval($value)
{
switch ($value[0]) {
@@ -1185,6 +1390,14 @@ protected function shouldEval($value)
return false;
}
+ /**
+ * Reduce value
+ *
+ * @param array $value
+ * @param boolean $inExp
+ *
+ * @return array
+ */
protected function reduce($value, $inExp = false)
{
list($type) = $value;
@@ -1400,11 +1613,25 @@ protected function reduce($value, $inExp = false)
}
}
+ /**
+ * Normalize name
+ *
+ * @param string $name
+ *
+ * @return string
+ */
protected function normalizeName($name)
{
return str_replace('-', '_', $name);
}
+ /**
+ * Normalize value
+ *
+ * @param array $value
+ *
+ * @return array
+ */
public function normalizeValue($value)
{
$value = $this->coerceForExpression($this->reduce($value));
@@ -1435,7 +1662,13 @@ public function normalizeValue($value)
}
}
- // just does physical lengths for now
+ /**
+ * Normalize number; just does physical lengths for now
+ *
+ * @param array $number
+ *
+ * @return array
+ */
protected function normalizeNumber($number)
{
list(, $value, $unit) = $number;
@@ -1449,21 +1682,53 @@ protected function normalizeNumber($number)
return $number;
}
+ /**
+ * Add numbers
+ *
+ * @param array $left
+ * @param array $right
+ *
+ * @return array
+ */
protected function opAddNumberNumber($left, $right)
{
return array('number', $left[1] + $right[1], $left[2]);
}
+ /**
+ * Multiply numbers
+ *
+ * @param array $left
+ * @param array $right
+ *
+ * @return array
+ */
protected function opMulNumberNumber($left, $right)
{
return array('number', $left[1] * $right[1], $left[2]);
}
+ /**
+ * Subtract numbers
+ *
+ * @param array $left
+ * @param array $right
+ *
+ * @return array
+ */
protected function opSubNumberNumber($left, $right)
{
return array('number', $left[1] - $right[1], $left[2]);
}
+ /**
+ * Divide numbers
+ *
+ * @param array $left
+ * @param array $right
+ *
+ * @return array
+ */
protected function opDivNumberNumber($left, $right)
{
if ($right[1] == 0) {
@@ -1473,12 +1738,27 @@ protected function opDivNumberNumber($left, $right)
return array('number', $left[1] / $right[1], $left[2]);
}
+ /**
+ * Mod numbers
+ *
+ * @param array $left
+ * @param array $right
+ *
+ * @return array
+ */
protected function opModNumberNumber($left, $right)
{
return array('number', $left[1] % $right[1], $left[2]);
}
- // adding strings
+ /**
+ * Add strings
+ *
+ * @param array $left
+ * @param array $right
+ *
+ * @return array
+ */
protected function opAdd($left, $right)
{
if ($strLeft = $this->coerceString($left)) {
@@ -1502,6 +1782,15 @@ protected function opAdd($left, $right)
}
}
+ /**
+ * Boolean and
+ *
+ * @param array $left
+ * @param array $right
+ * @param boolean $shouldEval
+ *
+ * @return array
+ */
protected function opAnd($left, $right, $shouldEval)
{
if (! $shouldEval) {
@@ -1515,6 +1804,15 @@ protected function opAnd($left, $right, $shouldEval)
return $left;
}
+ /**
+ * Boolean or
+ *
+ * @param array $left
+ * @param array $right
+ * @param boolean $shouldEval
+ *
+ * @return array
+ */
protected function opOr($left, $right, $shouldEval)
{
if (! $shouldEval) {
@@ -1528,6 +1826,15 @@ protected function opOr($left, $right, $shouldEval)
return $right;
}
+ /**
+ * Compare colors
+ *
+ * @param string $op
+ * @param array $left
+ * @param array $right
+ *
+ * @return array
+ */
protected function opColorColor($op, $left, $right)
{
$out = array('color');
@@ -1581,6 +1888,15 @@ protected function opColorColor($op, $left, $right)
return $this->fixColor($out);
}
+ /**
+ * Compare color and number
+ *
+ * @param string $op
+ * @param array $left
+ * @param array $right
+ *
+ * @return array
+ */
protected function opColorNumber($op, $left, $right)
{
$value = $right[1];
@@ -1592,6 +1908,15 @@ protected function opColorNumber($op, $left, $right)
);
}
+ /**
+ * Compare number and color
+ *
+ * @param string $op
+ * @param array $left
+ * @param array $right
+ *
+ * @return array
+ */
protected function opNumberColor($op, $left, $right)
{
$value = $left[1];
@@ -1603,6 +1928,14 @@ protected function opNumberColor($op, $left, $right)
);
}
+ /**
+ * Compare number1 == number2
+ *
+ * @param array $left
+ * @param array $right
+ *
+ * @return array
+ */
protected function opEq($left, $right)
{
if (($lStr = $this->coerceString($left)) && ($rStr = $this->coerceString($right))) {
@@ -1616,6 +1949,14 @@ protected function opEq($left, $right)
return $this->toBool($left == $right);
}
+ /**
+ * Compare number1 != number2
+ *
+ * @param array $left
+ * @param array $right
+ *
+ * @return array
+ */
protected function opNeq($left, $right)
{
if (($lStr = $this->coerceString($left)) && ($rStr = $this->coerceString($right))) {
@@ -1629,26 +1970,67 @@ protected function opNeq($left, $right)
return $this->toBool($left != $right);
}
+ /**
+ * Compare number1 >= number2
+ *
+ * @param array $left
+ * @param array $right
+ *
+ * @return array
+ */
protected function opGteNumberNumber($left, $right)
{
return $this->toBool($left[1] >= $right[1]);
}
+ /**
+ * Compare number1 > number2
+ *
+ * @param array $left
+ * @param array $right
+ *
+ * @return array
+ */
protected function opGtNumberNumber($left, $right)
{
return $this->toBool($left[1] > $right[1]);
}
+ /**
+ * Compare number1 <= number2
+ *
+ * @param array $left
+ * @param array $right
+ *
+ * @return array
+ */
protected function opLteNumberNumber($left, $right)
{
return $this->toBool($left[1] <= $right[1]);
}
+ /**
+ * Compare number1 < number2
+ *
+ * @param array $left
+ * @param array $right
+ *
+ * @return array
+ */
protected function opLtNumberNumber($left, $right)
{
return $this->toBool($left[1] < $right[1]);
}
+ /**
+ * Cast to boolean
+ *
+ * @api
+ *
+ * @param mixed $thing
+ *
+ * @return array
+ */
public function toBool($thing)
{
return $thing ? self::$true : self::$false;
@@ -1665,6 +2047,8 @@ public function toBool($thing)
* The input is expected to be reduced. This function will not work on
* things like expressions and variables.
*
+ * @api
+ *
* @param array $value
*
* @return string
@@ -1788,12 +2172,25 @@ public function compileValue($value)
}
}
+ /**
+ * Flatten list
+ *
+ * @param array $list
+ *
+ * @return string
+ */
protected function flattenList($list)
{
- // temporary
return $this->compileValue($list);
}
+ /**
+ * Compile string content
+ *
+ * @param array $string
+ *
+ * @return string
+ */
protected function compileStringContent($string)
{
$parts = array();
@@ -1809,7 +2206,13 @@ protected function compileStringContent($string)
return implode($parts);
}
- // doesn't need to be recursive, compileValue will handle that
+ /**
+ * Extract interpolation; it doesn't need to be recursive, compileValue will handle that
+ *
+ * @param array $list
+ *
+ * @return array
+ */
protected function extractInterpolation($list)
{
$items = $list[2];
@@ -1826,7 +2229,13 @@ protected function extractInterpolation($list)
return $list;
}
- // find the final set of selectors
+ /**
+ * Find the final set of selectors
+ *
+ * @param \stdClass $env
+ *
+ * @return array
+ */
protected function multiplySelectors($env)
{
$envs = array();
@@ -1857,7 +2266,14 @@ protected function multiplySelectors($env)
return $selectors;
}
- // looks for & to replace, or append parent before child
+ /**
+ * Join selectors; looks for & to replace, or append parent before child
+ *
+ * @param array $parent
+ * @param array $child
+ *
+ * @return array
+ */
protected function joinSelectors($parent, $child)
{
$setSelf = false;
@@ -1891,6 +2307,14 @@ protected function joinSelectors($parent, $child)
return $setSelf ? $out : array_merge($parent, $child);
}
+ /**
+ * Multiply media
+ *
+ * @param \stdClass $env
+ * @param array $childQueries
+ *
+ * @return array
+ */
protected function multiplyMedia($env, $childQueries = null)
{
if (! isset($env) ||
@@ -1921,6 +2345,13 @@ protected function multiplyMedia($env, $childQueries = null)
return $this->multiplyMedia($env->parent, $childQueries);
}
+ /**
+ * Push environment
+ *
+ * @param \stdClass $block
+ *
+ * @return \stdClass
+ */
protected function pushEnv($block = null)
{
$env = new \stdClass;
@@ -1934,6 +2365,9 @@ protected function pushEnv($block = null)
return $env;
}
+ /**
+ * Pop environment
+ */
protected function popEnv()
{
$env = $this->env;
@@ -1942,11 +2376,24 @@ protected function popEnv()
return $env;
}
+ /**
+ * Get store environment
+ *
+ * @return \stdClass
+ */
protected function getStoreEnv()
{
return isset($this->storeEnv) ? $this->storeEnv : $this->env;
}
+ /**
+ * Set variable
+ *
+ * @param string $name
+ * @param mixed $value
+ * @param boolean $shadow
+ * @param \stdClass $env
+ */
protected function set($name, $value, $shadow = false, $env = null)
{
$name = $this->normalizeName($name);
@@ -1958,6 +2405,13 @@ protected function set($name, $value, $shadow = false, $env = null)
}
}
+ /**
+ * Set existing variable
+ *
+ * @param string $name
+ * @param mixed $value
+ * @param \stdClass $env
+ */
protected function setExisting($name, $value, $env = null)
{
if (! isset($env)) {
@@ -1971,6 +2425,13 @@ protected function setExisting($name, $value, $env = null)
}
}
+ /**
+ * Set raw variable
+ *
+ * @param string $name
+ * @param mixed $value
+ * @param \stdClass $env
+ */
protected function setRaw($name, $value, $env = null)
{
if (! isset($env)) {
@@ -1980,6 +2441,17 @@ protected function setRaw($name, $value, $env = null)
$env->store[$name] = $value;
}
+ /**
+ * Get variable
+ *
+ * @api
+ *
+ * @param string $name
+ * @param mixed $defaultValue
+ * @param \stdClass $env
+ *
+ * @return mixed
+ */
public function get($name, $defaultValue = null, $env = null)
{
$name = $this->normalizeName($name);
@@ -2003,6 +2475,14 @@ public function get($name, $defaultValue = null, $env = null)
return $defaultValue; // found nothing
}
+ /**
+ * Has variable?
+ *
+ * @param string $name
+ * @param \stdClass $env
+ *
+ * @return boolean
+ */
protected function has($name, $env = null)
{
$value = $this->get($name, false, $env);
@@ -2010,6 +2490,11 @@ protected function has($name, $env = null)
return $value !== false;
}
+ /**
+ * Inject variables
+ *
+ * @param array $args
+ */
protected function injectVariables(array $args)
{
if (empty($args)) {
@@ -2034,6 +2519,8 @@ protected function injectVariables(array $args)
/**
* Set variables
*
+ * @api
+ *
* @param array $variables
*/
public function setVariables(array $variables)
@@ -2044,6 +2531,8 @@ public function setVariables(array $variables)
/**
* Unset variable
*
+ * @api
+ *
* @param string $name
*/
public function unsetVariable($name)
@@ -2051,11 +2540,25 @@ public function unsetVariable($name)
unset($this->registeredVars[$name]);
}
+ /**
+ * Returns list of parsed files
+ *
+ * @api
+ *
+ * @return array
+ */
public function getParsedFiles()
{
return $this->parsedFiles;
}
+ /**
+ * Add import path
+ *
+ * @api
+ *
+ * @param string $path
+ */
public function addImportPath($path)
{
if (! in_array($path, $this->importPaths)) {
@@ -2063,36 +2566,85 @@ public function addImportPath($path)
}
}
+ /**
+ * Set import paths
+ *
+ * @api
+ *
+ * @param string|array $path
+ */
public function setImportPaths($path)
{
$this->importPaths = (array)$path;
}
+ /**
+ * Set number precision
+ *
+ * @api
+ *
+ * @param integer $numberPrecision
+ */
public function setNumberPrecision($numberPrecision)
{
$this->numberPrecision = $numberPrecision;
}
+ /**
+ * Set formatter
+ *
+ * @api
+ *
+ * @param string $formatterName
+ */
public function setFormatter($formatterName)
{
$this->formatter = $formatterName;
}
+ /**
+ * Set line number style
+ *
+ * @api
+ *
+ * @param string $lineNumberStyle
+ */
public function setLineNumberStyle($lineNumberStyle)
{
$this->lineNumberStyle = $lineNumberStyle;
}
+ /**
+ * Register function
+ *
+ * @api
+ *
+ * @param string $name
+ * @param callable $func
+ */
public function registerFunction($name, $func)
{
$this->userFunctions[$this->normalizeName($name)] = $func;
}
+ /**
+ * Unregister function
+ *
+ * @api
+ *
+ * @param string $name
+ */
public function unregisterFunction($name)
{
unset($this->userFunctions[$this->normalizeName($name)]);
}
+ /**
+ * Import file
+ *
+ * @param string $path
+ * @param array $out
+ */
protected function importFile($path, $out)
{
// see if tree is cached
@@ -2115,7 +2667,15 @@ protected function importFile($path, $out)
array_shift($this->importPaths);
}
- // results the file path for an import url if it exists
+ /**
+ * Return the file path for an import url if it exists
+ *
+ * @api
+ *
+ * @param string $url
+ *
+ * @return string|null
+ */
public function findImport($url)
{
$urls = array();
@@ -2156,6 +2716,8 @@ public function findImport($url)
/**
* Throw error (exception)
*
+ * @api
+ *
* @param string $msg Message with optional sprintf()-style vararg parameters
*
* @throws \Exception
@@ -2261,9 +2823,16 @@ function ($m) {
return array($this, $libName);
}
-
- // sorts any keyword arguments
- // TODO: merge with apply arguments?
+ /**
+ * Sorts keyword arguments
+ *
+ * @todo Merge with applyArguments()?
+ *
+ * @param array $prototype
+ * @param array $args
+ *
+ * @return array
+ */
protected function sortArgs($prototype, $args)
{
$keyArgs = array();
@@ -2311,6 +2880,14 @@ protected function sortArgs($prototype, $args)
return $finalArgs;
}
+ /**
+ * Apply argument values per definition
+ *
+ * @param array $argDef
+ * @param array $argValues
+ *
+ * @throws \Exception
+ */
protected function applyArguments($argDef, $argValues)
{
$storeEnv = $this->getStoreEnv();
@@ -2406,7 +2983,14 @@ protected function applyArguments($argDef, $argValues)
}
}
- // $number should be normalized
+ /**
+ * Coerce unit on number to be normalized
+ *
+ * @param array $number
+ * @param string $unit
+ *
+ * @return array
+ */
protected function coerceUnit($number, $unit)
{
list(, $value, $baseUnit) = $number;
@@ -2469,6 +3053,13 @@ protected function coerceList($item, $delim = ',')
return array('list', $delim, ! isset($item) ? array(): array($item));
}
+ /**
+ * Coerce color for expression
+ *
+ * @param array $value
+ *
+ * @return array|null
+ */
protected function coerceForExpression($value)
{
if ($color = $this->coerceColor($value)) {
@@ -2478,6 +3069,13 @@ protected function coerceForExpression($value)
return $value;
}
+ /**
+ * Coerce value to color
+ *
+ * @param array $value
+ *
+ * @return array|null
+ */
protected function coerceColor($value)
{
switch ($value[0]) {
@@ -2501,6 +3099,13 @@ protected function coerceColor($value)
return null;
}
+ /**
+ * Coerce value to string
+ *
+ * @param array $value
+ *
+ * @return array|null
+ */
protected function coerceString($value)
{
switch ($value[0]) {
@@ -2517,6 +3122,13 @@ protected function coerceString($value)
return null;
}
+ /**
+ * Coerce value to a percentage
+ *
+ * @param array $value
+ *
+ * @return integer|float
+ */
protected function coercePercent($value)
{
if ($value[0] == 'number') {
@@ -2530,6 +3142,17 @@ protected function coercePercent($value)
return 0;
}
+ /**
+ * Assert value is a map
+ *
+ * @api
+ *
+ * @param array $value
+ *
+ * @return array
+ *
+ * @throws \Exception
+ */
public function assertMap($value)
{
$value = $this->coerceMap($value);
@@ -2541,6 +3164,17 @@ public function assertMap($value)
return $value;
}
+ /**
+ * Assert value is a list
+ *
+ * @api
+ *
+ * @param array $value
+ *
+ * @return array
+ *
+ * @throws \Exception
+ */
public function assertList($value)
{
if ($value[0] != 'list') {
@@ -2550,6 +3184,17 @@ public function assertList($value)
return $value;
}
+ /**
+ * Assert value is a color
+ *
+ * @api
+ *
+ * @param array $value
+ *
+ * @return array
+ *
+ * @throws \Exception
+ */
public function assertColor($value)
{
if ($color = $this->coerceColor($value)) {
@@ -2559,6 +3204,17 @@ public function assertColor($value)
$this->throwError('expecting color');
}
+ /**
+ * Assert value is a number
+ *
+ * @api
+ *
+ * @param array $value
+ *
+ * @return integer|float
+ *
+ * @throws \Exception
+ */
public function assertNumber($value)
{
if ($value[0] != 'number') {
@@ -2568,7 +3224,13 @@ public function assertNumber($value)
return $value[1];
}
- // make sure a color's components don't go out of bounds
+ /**
+ * Make sure a color's components don't go out of bounds
+ *
+ * @param array $c
+ *
+ * @return array
+ */
protected function fixColor($c)
{
foreach (range(1, 3) as $i) {
@@ -2584,6 +3246,17 @@ protected function fixColor($c)
return $c;
}
+ /**
+ * Convert RGB to HSL
+ *
+ * @api
+ *
+ * @param integer $red
+ * @param integer $green
+ * @param integer $blue
+ *
+ * @return array
+ */
public function toHSL($red, $green, $blue)
{
$min = min($red, $green, $blue);
@@ -2613,7 +3286,16 @@ public function toHSL($red, $green, $blue)
return array('hsl', fmod($h, 360), $s * 100, $l / 5.1);
}
- public function hueToRGB($m1, $m2, $h)
+ /**
+ * Hue to RGB helper
+ *
+ * @param float $m1
+ * @param float $m2
+ * @param float $h
+ *
+ * @return float
+ */
+ private function hueToRGB($m1, $m2, $h)
{
if ($h < 0) {
$h += 1;
@@ -2636,7 +3318,17 @@ public function hueToRGB($m1, $m2, $h)
return $m1;
}
- // H from 0 to 360, S and L from 0 to 100
+ /**
+ * Convert HSL to RGB
+ *
+ * @api
+ *
+ * @param integer $hue H from 0 to 360
+ * @param integer $saturation S from 0 to 100
+ * @param integer $lightness L from 0 to 100
+ *
+ * @return array
+ */
public function toRGB($hue, $saturation, $lightness)
{
if ($hue < 0) {
@@ -3202,6 +3894,13 @@ protected function libMax($args)
return $args[$max[0]];
}
+ /**
+ * Helper to normalize args containing numbers
+ *
+ * @param array $args
+ *
+ * @return array
+ */
protected function getNormalizedNumbers($args)
{
$unit = null;
diff --git a/src/Formatter.php b/src/Formatter.php
index f2ccf3e7..5b035e1c 100644
--- a/src/Formatter.php
+++ b/src/Formatter.php
@@ -59,6 +59,7 @@ abstract public function __construct();
* Return indentation (whitespace)
*
* @param integer $n
+ *
* @return string
*/
protected function indentStr($n = 0)
@@ -71,6 +72,7 @@ protected function indentStr($n = 0)
*
* @param string $name
* @param mixed $value
+ *
* @return string
*/
public function property($name, $value)
@@ -149,6 +151,7 @@ protected function block($block)
* Entry point to formatting a block
*
* @param \stdClass $block An abstract syntax tree
+ *
* @return string
*/
public function format($block)
diff --git a/src/Parser.php b/src/Parser.php
index 3f3afee2..bb085a5f 100644
--- a/src/Parser.php
+++ b/src/Parser.php
@@ -102,6 +102,13 @@ public function __construct($sourceName = null, $rootParser = true)
}
}
+ /**
+ * Make operator regex
+ *
+ * @param array $operators
+ *
+ * @return string
+ */
protected static function makeOperatorStr($operators)
{
return '('
@@ -622,6 +629,14 @@ protected function stripAssignmentFlag(&$value)
return false;
}
+ /**
+ * Match literal string
+ *
+ * @param string $what
+ * @param boolean $eatWhitespace
+ *
+ * @return boolean
+ */
protected function literal($what, $eatWhitespace = null)
{
if (! isset($eatWhitespace)) {
@@ -695,6 +710,13 @@ protected function pushSpecialBlock($type, $pos)
return $block;
}
+ /**
+ * Pop scope and return last block
+ *
+ * @return \stdClass
+ *
+ * @throws \Exception
+ */
protected function popBlock()
{
$block = $this->env;
@@ -715,6 +737,11 @@ protected function popBlock()
return $block;
}
+ /**
+ * Append comment to current block
+ *
+ * @param array $comment
+ */
protected function appendComment($comment)
{
$comment[1] = substr(preg_replace(array('/^\s+/m', '/^(.)/m'), array('', ' \1'), $comment[1]), 1);
@@ -722,6 +749,12 @@ protected function appendComment($comment)
$this->env->comments[] = $comment;
}
+ /**
+ * Append statement to current block
+ *
+ * @param array $statement
+ * @param integer $pos
+ */
protected function append($statement, $pos = null)
{
if ($pos !== null) {
@@ -742,7 +775,11 @@ protected function append($statement, $pos = null)
}
}
- // last child that was appended
+ /**
+ * Returns last child was appended
+ *
+ * @return array|null
+ */
protected function last()
{
$i = count($this->env->children) - 1;
@@ -752,13 +789,25 @@ protected function last()
}
}
- // high level parsers (they return parts of ast)
-
+ /**
+ * Parse media query list
+ *
+ * @param array $out
+ *
+ * @return boolean
+ */
protected function mediaQueryList(&$out)
{
return $this->genericList($out, 'mediaQuery', ',', false);
}
+ /**
+ * Parse media query
+ *
+ * @param array $out
+ *
+ * @return boolean
+ */
protected function mediaQuery(&$out)
{
$s = $this->seek();
@@ -806,6 +855,13 @@ protected function mediaQuery(&$out)
return true;
}
+ /**
+ * Parse media expression
+ *
+ * @param array $out
+ *
+ * @return boolean
+ */
protected function mediaExpression(&$out)
{
$s = $this->seek();
@@ -830,6 +886,13 @@ protected function mediaExpression(&$out)
return false;
}
+ /**
+ * Parse argument values
+ *
+ * @param array $out
+ *
+ * @return boolean
+ */
protected function argValues(&$out)
{
if ($this->genericList($list, 'argValue', ',', false)) {
@@ -841,6 +904,13 @@ protected function argValues(&$out)
return false;
}
+ /**
+ * Parse argument value
+ *
+ * @param array $out
+ *
+ * @return boolean
+ */
protected function argValue(&$out)
{
$s = $this->seek();
@@ -880,11 +950,28 @@ protected function valueList(&$out)
return $this->genericList($out, 'spaceList', ',');
}
+ /**
+ * Parse space list
+ *
+ * @param array $out
+ *
+ * @return boolean
+ */
protected function spaceList(&$out)
{
return $this->genericList($out, 'expression');
}
+ /**
+ * Parse generic list
+ *
+ * @param array $out
+ * @param callable $parseItem
+ * @param string $delim
+ * @param boolean $flatten
+ *
+ * @return boolean
+ */
protected function genericList(&$out, $parseItem, $delim = '', $flatten = true)
{
$s = $this->seek();
@@ -915,6 +1002,13 @@ protected function genericList(&$out, $parseItem, $delim = '', $flatten = true)
return true;
}
+ /**
+ * Parse expression
+ *
+ * @param array $out
+ *
+ * @return boolean
+ */
protected function expression(&$out)
{
$s = $this->seek();
@@ -948,6 +1042,14 @@ protected function expression(&$out)
return false;
}
+ /**
+ * Parse left-hand side of subexpression
+ *
+ * @param array $lhs
+ * @param integer $minP
+ *
+ * @return array
+ */
protected function expHelper($lhs, $minP)
{
$opstr = self::$operatorStr;
@@ -991,6 +1093,13 @@ protected function expHelper($lhs, $minP)
return $lhs;
}
+ /**
+ * Parse value
+ *
+ * @param array $out
+ *
+ * @return boolean
+ */
protected function value(&$out)
{
$s = $this->seek();
@@ -1049,7 +1158,13 @@ protected function value(&$out)
return false;
}
- // value wrappen in parentheses
+ /**
+ * Parse parenthesized value
+ *
+ * @param array $out
+ *
+ * @return boolean
+ */
protected function parenValue(&$out)
{
$s = $this->seek();
@@ -1079,6 +1194,13 @@ protected function parenValue(&$out)
return false;
}
+ /**
+ * Parse "progid:"
+ *
+ * @param array $out
+ *
+ * @return boolean
+ */
protected function progid(&$out)
{
$s = $this->seek();
@@ -1103,6 +1225,13 @@ protected function progid(&$out)
return false;
}
+ /**
+ * Parse function call
+ *
+ * @param array $out
+ *
+ * @return boolean
+ */
protected function func(&$func)
{
$s = $this->seek();
@@ -1148,6 +1277,13 @@ protected function func(&$func)
return false;
}
+ /**
+ * Parse function call argument list
+ *
+ * @param array $out
+ *
+ * @return boolean
+ */
protected function argumentList(&$out)
{
$s = $this->seek();
@@ -1185,6 +1321,13 @@ protected function argumentList(&$out)
return true;
}
+ /**
+ * Parse mixin/function definition argument list
+ *
+ * @param array $out
+ *
+ * @return boolean
+ */
protected function argumentDef(&$out)
{
$s = $this->seek();
@@ -1236,6 +1379,13 @@ protected function argumentDef(&$out)
return true;
}
+ /**
+ * Parse map
+ *
+ * @param array $out
+ *
+ * @return boolean
+ */
protected function map(&$out)
{
$s = $this->seek();
@@ -1267,6 +1417,13 @@ protected function map(&$out)
return true;
}
+ /**
+ * Parse color
+ *
+ * @param array $out
+ *
+ * @return boolean
+ */
protected function color(&$out)
{
$color = array('color');
@@ -1297,6 +1454,13 @@ protected function color(&$out)
return false;
}
+ /**
+ * Parse number with unit
+ *
+ * @param array $out
+ *
+ * @return boolean
+ */
protected function unit(&$unit)
{
if ($this->match('([0-9]*(\.)?[0-9]+)([%a-zA-Z]+)?', $m)) {
@@ -1308,6 +1472,13 @@ protected function unit(&$unit)
return false;
}
+ /**
+ * Parse string
+ *
+ * @param array $out
+ *
+ * @return boolean
+ */
protected function string(&$out)
{
$s = $this->seek();
@@ -1361,6 +1532,13 @@ protected function string(&$out)
return false;
}
+ /**
+ * Parse keyword or interpolation
+ *
+ * @param array $out
+ *
+ * @return boolean
+ */
protected function mixedKeyword(&$out)
{
$s = $this->seek();
@@ -1399,7 +1577,15 @@ protected function mixedKeyword(&$out)
return true;
}
- // an unbounded string stopped by $end
+ /**
+ * Parse an unbounded string stopped by $end
+ *
+ * @param string $end
+ * @param array $out
+ * @param string $nestingOpen
+ *
+ * @return boolean
+ */
protected function openString($end, &$out, $nestingOpen = null)
{
$oldWhite = $this->eatWhiteDefault;
@@ -1462,7 +1648,14 @@ protected function openString($end, &$out, $nestingOpen = null)
return true;
}
- // $lookWhite: save information about whitespace before and after
+ /**
+ * Parser interpolation
+ *
+ * @param array $out
+ * @param boolean $lookWhite save information about whitespace before and after
+ *
+ * @return boolean
+ */
protected function interpolation(&$out, $lookWhite = true)
{
$oldWhite = $this->eatWhiteDefault;
@@ -1494,9 +1687,13 @@ protected function interpolation(&$out, $lookWhite = true)
return false;
}
- // low level parsers
-
- // returns an array of parts or a string
+ /**
+ * Parse property name (as an array of parts or a string)
+ *
+ * @param array $out
+ *
+ * @return boolean
+ */
protected function propertyName(&$out)
{
$s = $this->seek();
@@ -1545,7 +1742,13 @@ protected function propertyName(&$out)
return true;
}
- // comma separated list of selectors
+ /**
+ * Parse comma separated selector list
+ *
+ * @param array $out
+ *
+ * @return boolean
+ */
protected function selectors(&$out)
{
$s = $this->seek();
@@ -1574,7 +1777,13 @@ protected function selectors(&$out)
return true;
}
- // whitespace separated list of selectorSingle
+ /**
+ * Parse whitespace separated selector list
+ *
+ * @param array $out
+ *
+ * @return boolean
+ */
protected function selector(&$out)
{
$selector = array();
@@ -1601,8 +1810,17 @@ protected function selector(&$out)
return true;
}
- // the parts that make up
- // div[yes=no]#something.hello.world:nth-child(-2n+1)%placeholder
+ /**
+ * Parse the parts that make up a selector
+ *
+ * {@internal
+ * div[yes=no]#something.hello.world:nth-child(-2n+1)%placeholder
+ * }}
+ *
+ * @param array $out
+ *
+ * @return boolean
+ */
protected function selectorSingle(&$out)
{
$oldWhite = $this->eatWhiteDefault;
@@ -1770,6 +1988,13 @@ protected function selectorSingle(&$out)
return true;
}
+ /**
+ * Parse a variable
+ *
+ * @param array $out
+ *
+ * @return boolean
+ */
protected function variable(&$out)
{
$s = $this->seek();
@@ -1785,6 +2010,14 @@ protected function variable(&$out)
return false;
}
+ /**
+ * Parse a keyword
+ *
+ * @param string $word
+ * @param boolean $eatWhitespace
+ *
+ * @return boolean
+ */
protected function keyword(&$word, $eatWhitespace = null)
{
if ($this->match(
@@ -1800,6 +2033,13 @@ protected function keyword(&$word, $eatWhitespace = null)
return false;
}
+ /**
+ * Parse a placeholder
+ *
+ * @param string $placeholder
+ *
+ * @return boolean
+ */
protected function placeholder(&$placeholder)
{
if ($this->match('([\w\-_]+|#[{][$][\w\-_]+[}])', $m)) {
@@ -1811,6 +2051,13 @@ protected function placeholder(&$placeholder)
return false;
}
+ /**
+ * Parse a url
+ *
+ * @param array $out
+ *
+ * @return boolean
+ */
protected function url(&$out)
{
if ($this->match('(url\(\s*(["\']?)([^)]+)\2\s*\))', $m)) {
@@ -1822,7 +2069,11 @@ protected function url(&$out)
return false;
}
- // consume an end of statement delimiter
+ /**
+ * Consume an end of statement delimiter
+ *
+ * @return boolean
+ */
protected function end()
{
if ($this->literal(';')) {
@@ -1867,6 +2118,14 @@ protected function to($what, &$out, $until = false, $allowNewline = false)
return true;
}
+ /**
+ * Throw parser error
+ *
+ * @param string $msg
+ * @param integer $count
+ *
+ * @throws \Exception
+ */
public function throwParseError($msg = 'parse error', $count = null)
{
$count = ! isset($count) ? $this->count : $count;
@@ -1949,7 +2208,15 @@ protected function matchString(&$m, $delim)
return true;
}
- // try to match something on head of buffer
+ /**
+ * Try to match something on head of buffer
+ *
+ * @param string $regex
+ * @param array $out
+ * @param boolean $eatWhitespace
+ *
+ * @return boolean
+ */
protected function match($regex, &$out, $eatWhitespace = null)
{
if (! isset($eatWhitespace)) {
@@ -1971,7 +2238,11 @@ protected function match($regex, &$out, $eatWhitespace = null)
return false;
}
- // match some whitespace
+ /**
+ * Match some whitespace
+ *
+ * @return boolean
+ */
protected function whitespace()
{
$gotWhite = false;
@@ -1990,6 +2261,15 @@ protected function whitespace()
return $gotWhite;
}
+ /**
+ * Peek input stream
+ *
+ * @param string $regex
+ * @param array $out
+ * @param integer $from
+ *
+ * @return integer
+ */
protected function peek($regex, &$out, $from = null)
{
if (! isset($from)) {
@@ -2002,6 +2282,13 @@ protected function peek($regex, &$out, $from = null)
return $result;
}
+ /**
+ * Seek to position in input stream (or return current position in input stream)
+ *
+ * @param integer $where
+ *
+ * @return integer
+ */
protected function seek($where = null)
{
if ($where === null) {
@@ -2013,6 +2300,13 @@ protected function seek($where = null)
return true;
}
+ /**
+ * Quote regular expression
+ *
+ * @param string $what
+ *
+ * @return string
+ */
public static function pregQuote($what)
{
return preg_quote($what, '/');
@@ -2030,7 +2324,13 @@ protected function show()
return '';
}
- // turn list of length 1 into value type
+ /**
+ * Turn list of length 1 into value type
+ *
+ * @param array $value
+ *
+ * @return array
+ */
protected function flattenList($value)
{
if ($value[0] == 'list' && count($value[2]) == 1) {
diff --git a/src/Util.php b/src/Util.php
index 1764c21e..714acdb8 100644
--- a/src/Util.php
+++ b/src/Util.php
@@ -29,8 +29,9 @@ class Util
* @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.
+ * @return mixed `value` adjusted to fall within range, if it was outside by a floating-point margin.
+ *
+ * @throws \Exception
*/
public static function checkRange($name, Range $range, $value, $unit = '')
{
From 9fff16c6e431396f4f51e78143e2118826cea66b Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Sun, 23 Aug 2015 16:33:31 -0400
Subject: [PATCH 051/534] minor refactoring
---
src/Compiler.php | 6 ++----
1 file changed, 2 insertions(+), 4 deletions(-)
diff --git a/src/Compiler.php b/src/Compiler.php
index 85879c44..be7b0ff6 100644
--- a/src/Compiler.php
+++ b/src/Compiler.php
@@ -407,10 +407,8 @@ protected function matchExtendsSingle($single, &$outOrigin)
foreach ($origin as $j => $new) {
// prevent infinite loop when target extends itself
- foreach ($new as $new_selector) {
- if ($single === $new_selector) {
- return false;
- }
+ if ($this->isSelfExtend($single, $origin)) {
+ return false;
}
$origin[$j][count($origin[$j]) - 1] = $this->combineSelectorSingle(end($new), $rem);
From aa5089c142c754613f490d0afa223d870c8972e9 Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Mon, 24 Aug 2015 10:42:18 -0400
Subject: [PATCH 052/534] composer.json: satis support to exclude files from
dist archives
---
.gitattributes | 11 +++--------
composer.json | 13 ++++++++++++-
2 files changed, 15 insertions(+), 9 deletions(-)
diff --git a/.gitattributes b/.gitattributes
index 35c78edd..a116ff23 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -1,12 +1,7 @@
-# Ignore un-needed files and directories for export of production releases
-# Keeps src/
-#
-# See: http://git-scm.com/book/en/v2/Customizing-Git-Git-Attributes#Exporting-Your-Repository
-
-tests export-ignore
+Makefile export-ignore
.gitattributes export-ignore
.gitignore export-ignore
.travis.yml export-ignore
box.json.dist export-ignore
-Makefile export-ignore
-phpunit.xml.dist export-ignore
\ No newline at end of file
+phpunit.xml.dist export-ignore
+tests/ export-ignore
diff --git a/composer.json b/composer.json
index 3c6ef843..c63339c3 100644
--- a/composer.json
+++ b/composer.json
@@ -29,5 +29,16 @@
"phpunit/phpunit": "~3.7",
"kherge/box": "~2.5"
},
- "bin": ["bin/pscss"]
+ "bin": ["bin/pscss"],
+ "archive": {
+ "exclude": [
+ "/Makefile",
+ "/.gitattributes",
+ "/.gitignore",
+ "/.travis.yml",
+ "/box.json.dist",
+ "/phpunit.xml.dist",
+ "/tests"
+ ]
+ }
}
From cb81ccee517d347aecb80e6a469785971ae0f828 Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Tue, 25 Aug 2015 11:29:01 -0400
Subject: [PATCH 053/534] detect @import loop; fixes #315
---
src/Compiler.php | 24 ++++++++++++++++++++++++
1 file changed, 24 insertions(+)
diff --git a/src/Compiler.php b/src/Compiler.php
index be7b0ff6..41598a57 100644
--- a/src/Compiler.php
+++ b/src/Compiler.php
@@ -2649,6 +2649,8 @@ protected function importFile($path, $out)
$realPath = realpath($path);
if (isset($this->importCache[$realPath])) {
+ $this->handleImportLoop($realPath);
+
$tree = $this->importCache[$realPath];
} else {
$code = file_get_contents($path);
@@ -2733,6 +2735,28 @@ public function throwError($msg)
throw new \Exception($msg);
}
+ /**
+ * Handle import loop
+ *
+ * @param string $name
+ *
+ * @throws \Exception
+ */
+ private function handleImportLoop($name)
+ {
+ for ($env = $this->env; $env; $env = $env->parent) {
+ $file = $env->block->sourceParser->getSourceName();
+
+ if (realpath($file) === $name) {
+ $this->throwError(
+ 'An @import loop has been found: %s imports %s',
+ $this->env->block->sourceParser->getSourceName(),
+ basename($file)
+ );
+ }
+ }
+ }
+
/**
* Does file exist?
*
From 7df0b8c0d14cdb99fc4a0f32d919faabdd2dda64 Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Tue, 25 Aug 2015 11:37:56 -0400
Subject: [PATCH 054/534] Bump version to 0.2.0
---
src/Version.php | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/Version.php b/src/Version.php
index 0f419fa9..5d3ce31e 100644
--- a/src/Version.php
+++ b/src/Version.php
@@ -18,5 +18,5 @@
*/
class Version
{
- const VERSION = 'v0.1.10';
+ const VERSION = 'v0.2.0';
}
From caae09d55e3af9b30cae0bb973d755e5ddf78b1a Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Tue, 25 Aug 2015 12:15:39 -0400
Subject: [PATCH 055/534] phpcs: fix source indentation
---
src/Compiler.php | 22 +++++++++++-----------
1 file changed, 11 insertions(+), 11 deletions(-)
diff --git a/src/Compiler.php b/src/Compiler.php
index 41598a57..9ecfffbf 100644
--- a/src/Compiler.php
+++ b/src/Compiler.php
@@ -2744,17 +2744,17 @@ public function throwError($msg)
*/
private function handleImportLoop($name)
{
- for ($env = $this->env; $env; $env = $env->parent) {
- $file = $env->block->sourceParser->getSourceName();
-
- if (realpath($file) === $name) {
- $this->throwError(
- 'An @import loop has been found: %s imports %s',
- $this->env->block->sourceParser->getSourceName(),
- basename($file)
- );
- }
- }
+ for ($env = $this->env; $env; $env = $env->parent) {
+ $file = $env->block->sourceParser->getSourceName();
+
+ if (realpath($file) === $name) {
+ $this->throwError(
+ 'An @import loop has been found: %s imports %s',
+ $this->env->block->sourceParser->getSourceName(),
+ basename($file)
+ );
+ }
+ }
}
/**
From 323d86e11490123fcfa4052fce6e45ffeaca7866 Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Fri, 28 Aug 2015 10:19:02 -0400
Subject: [PATCH 056/534] add failing test from #316
---
tests/FailingTest.php | 11 +++++++++++
1 file changed, 11 insertions(+)
diff --git a/tests/FailingTest.php b/tests/FailingTest.php
index f6ec0ffc..850513a2 100644
--- a/tests/FailingTest.php
+++ b/tests/FailingTest.php
@@ -153,6 +153,17 @@ public function provideFailing()
transform: scale(0.5); }
to {
transform: scale(1); } }
+END_OF_EXPECTED
+ ),
+ array(
+ '#316 - swallowed comma before interpolation', <<<'END_OF_SCSS'
+foo, #{x, y} {
+ color: #abc;
+}
+END_OF_SCSS
+ , <<
Date: Fri, 28 Aug 2015 10:36:50 -0400
Subject: [PATCH 057/534] collapseSelector regression; fixes #316
---
src/Compiler.php | 22 ++++++++++++++--------
tests/FailingTest.php | 11 -----------
tests/inputs/interpolation.scss | 4 ++++
tests/outputs/interpolation.css | 3 +++
tests/outputs_numbered/interpolation.css | 3 +++
5 files changed, 24 insertions(+), 19 deletions(-)
diff --git a/src/Compiler.php b/src/Compiler.php
index 9ecfffbf..0b84398d 100644
--- a/src/Compiler.php
+++ b/src/Compiler.php
@@ -680,16 +680,22 @@ protected function evalSelectorPart($part)
*/
protected function collapseSelectors($selectors)
{
- $output = '';
+ $parts = array();
- array_walk_recursive(
- $selectors,
- function ($value, $key) use (&$output) {
- $output .= $value;
- }
- );
+ foreach ($selectors as $selector) {
+ $output = '';
+
+ array_walk_recursive(
+ $selector,
+ function ($value, $key) use (&$output) {
+ $output .= $value;
+ }
+ );
+
+ $parts[] = $output;
+ }
- return $output;
+ return implode(', ', $parts);;
}
/**
diff --git a/tests/FailingTest.php b/tests/FailingTest.php
index 850513a2..f6ec0ffc 100644
--- a/tests/FailingTest.php
+++ b/tests/FailingTest.php
@@ -153,17 +153,6 @@ public function provideFailing()
transform: scale(0.5); }
to {
transform: scale(1); } }
-END_OF_EXPECTED
- ),
- array(
- '#316 - swallowed comma before interpolation', <<<'END_OF_SCSS'
-foo, #{x, y} {
- color: #abc;
-}
-END_OF_SCSS
- , <<
Date: Thu, 3 Sep 2015 10:17:37 -0400
Subject: [PATCH 058/534] fix map-get(null)
---
src/Compiler.php | 10 ++++++++--
1 file changed, 8 insertions(+), 2 deletions(-)
diff --git a/src/Compiler.php b/src/Compiler.php
index 0b84398d..e0ac8da7 100644
--- a/src/Compiler.php
+++ b/src/Compiler.php
@@ -2159,9 +2159,9 @@ public function compileValue($value)
$reduced = $this->reduce($exp);
switch ($reduced[0]) {
case 'string':
- $reduced = array('keyword',
- $this->compileStringContent($reduced));
+ $reduced = array('keyword', $this->compileStringContent($reduced));
break;
+
case 'null':
$reduced = array('keyword', '');
}
@@ -3145,6 +3145,12 @@ protected function coerceString($value)
case 'keyword':
return array('string', '', array($value[1]));
+
+ case 'number':
+ return array('string', '', array(round($value[1], $this->numberPrecision) . $value[2]));
+
+ case 'null':
+ return array('string', '', array(''));
}
return null;
From 10a9e9976e530de3dfed01b3fb9c49bdb54bc9b5 Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Thu, 3 Sep 2015 10:37:04 -0400
Subject: [PATCH 059/534] add tests
---
src/Compiler.php | 2 +-
tests/inputs/map.scss | 1 +
tests/outputs_numbered/map.css | 2 +-
3 files changed, 3 insertions(+), 2 deletions(-)
diff --git a/src/Compiler.php b/src/Compiler.php
index e0ac8da7..d8145dbf 100644
--- a/src/Compiler.php
+++ b/src/Compiler.php
@@ -4027,7 +4027,7 @@ protected function libMapGet($args)
}
}
- return self::$defaultValue;
+ return self::$null;
}
protected static $libMapKeys = array('map');
diff --git a/tests/inputs/map.scss b/tests/inputs/map.scss
index 91fe1ad5..8284151f 100644
--- a/tests/inputs/map.scss
+++ b/tests/inputs/map.scss
@@ -16,6 +16,7 @@ div {
baz: map_merge($map, $map2);
foo: map_remove($map2, color);
bar: if(map_has_key($map, color), true, false);
+ suppress: map_get($map, null);
}
// List functions
diff --git a/tests/outputs_numbered/map.css b/tests/outputs_numbered/map.css
index 124ace48..48658216 100644
--- a/tests/outputs_numbered/map.css
+++ b/tests/outputs_numbered/map.css
@@ -7,7 +7,7 @@ div {
baz: (color: #fff, color2: red, 'color3': #0f0, length: 40em);
foo: (length: 40em);
bar: true; }
-/* line 22, inputs/map.scss */
+/* line 23, inputs/map.scss */
div {
foo: color black;
bar: color; }
From 8da198fc641d61b1f37ed341d055b9e7df9525aa Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Thu, 3 Sep 2015 10:47:48 -0400
Subject: [PATCH 060/534] Add failing test for #318
---
tests/FailingTest.php | 12 ++++++++++++
1 file changed, 12 insertions(+)
diff --git a/tests/FailingTest.php b/tests/FailingTest.php
index f6ec0ffc..c3e228c7 100644
--- a/tests/FailingTest.php
+++ b/tests/FailingTest.php
@@ -153,6 +153,18 @@ public function provideFailing()
transform: scale(0.5); }
to {
transform: scale(1); } }
+END_OF_EXPECTED
+ ),
+ array(
+ '#318 - BEM + parent selector @extend', <<<'END_OF_SCSS'
+.foo{
+ &__bar{background:red;}
+}
+input{@extend .foo__bar;}
+END_OF_SCSS
+ , <<
Date: Thu, 3 Sep 2015 11:10:13 -0400
Subject: [PATCH 061/534] add partial test for #295
---
tests/FailingTest.php | 17 +++++++++++++++++
1 file changed, 17 insertions(+)
diff --git a/tests/FailingTest.php b/tests/FailingTest.php
index c3e228c7..ac66c41e 100644
--- a/tests/FailingTest.php
+++ b/tests/FailingTest.php
@@ -153,6 +153,23 @@ public function provideFailing()
transform: scale(0.5); }
to {
transform: scale(1); } }
+END_OF_EXPECTED
+ ),
+ array(
+ '#295 - variable scope bug', <<<'END_OF_SCSS'
+@mixin example {
+ $color: red;
+}
+
+A {
+ $color: green;
+ @include example;
+ color: $color;
+}
+END_OF_SCSS
+ , <<
Date: Thu, 3 Sep 2015 18:18:43 -0400
Subject: [PATCH 062/534] minor refactoring
---
src/Compiler.php | 19 +++----------------
1 file changed, 3 insertions(+), 16 deletions(-)
diff --git a/src/Compiler.php b/src/Compiler.php
index d8145dbf..52278566 100644
--- a/src/Compiler.php
+++ b/src/Compiler.php
@@ -3136,24 +3136,11 @@ protected function coerceColor($value)
*/
protected function coerceString($value)
{
- switch ($value[0]) {
- case 'string':
- return $value;
-
- case 'function':
- return array('string', '', array($value[1] . '(' . $this->flattenList($value[2]) . ')'));
-
- case 'keyword':
- return array('string', '', array($value[1]));
-
- case 'number':
- return array('string', '', array(round($value[1], $this->numberPrecision) . $value[2]));
-
- case 'null':
- return array('string', '', array(''));
+ if ($value[0] === 'string') {
+ return $value;
}
- return null;
+ return array('string', '', array($this->compileValue($value)));
}
/**
From 5245d42cc93b1c50a3e2af2eda97f7026a80f960 Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Sat, 5 Sep 2015 18:09:03 -0400
Subject: [PATCH 063/534] internals: cleanup
---
src/Compiler.php | 170 ++++++++++++++++++++-------------------
src/Formatter/Nested.php | 6 +-
src/Parser.php | 48 +++++------
3 files changed, 113 insertions(+), 111 deletions(-)
diff --git a/src/Compiler.php b/src/Compiler.php
index 52278566..eb74c5c8 100644
--- a/src/Compiler.php
+++ b/src/Compiler.php
@@ -295,7 +295,7 @@ protected function flattenSelectors($block, $parentKey = null)
$block->selectors[] = $this->compileSelector($selector);
}
- if ($placeholderSelector && 0 == count($block->selectors) && null !== $parentKey) {
+ if ($placeholderSelector && 0 === count($block->selectors) && null !== $parentKey) {
unset($block->parent->children[$parentKey]);
return;
@@ -343,7 +343,7 @@ protected function matchExtends($selector, &$out, $from = 0, $initial = true)
$after
);
- if ($result == $selector) {
+ if ($result === $selector) {
continue;
}
@@ -399,7 +399,7 @@ protected function matchExtendsSingle($single, &$outOrigin)
list($target, $origin) = $this->extends[$idx];
// check count
- if ($count != count($target)) {
+ if ($count !== count($target)) {
continue;
}
@@ -507,7 +507,7 @@ protected function compileMedia($media)
protected function mediaParent($scope)
{
while (! empty($scope->parent)) {
- if (! empty($scope->type) && $scope->type != 'media') {
+ if (! empty($scope->type) && $scope->type !== 'media') {
break;
}
@@ -793,7 +793,7 @@ protected function hasSelectorPlaceholder($selector)
foreach ($selector as $parts) {
foreach ($parts as $part) {
- if ('%' == $part[0]) {
+ if ('%' === $part[0]) {
return true;
}
}
@@ -927,27 +927,27 @@ protected function mergeMediaTypes($type1, $type2)
$t2 = strtolower($type2[0]);
}
- if (($m1 == 'not') ^ ($m2 == 'not')) {
- if ($t1 == $t2) {
+ if (($m1 === 'not') ^ ($m2 === 'not')) {
+ if ($t1 === $t2) {
return null;
}
return array(
- $m1 == 'not' ? $m2 : $m1,
- $m1 == 'not' ? $t2 : $t1
+ $m1 === 'not' ? $m2 : $m1,
+ $m1 === 'not' ? $t2 : $t1
);
}
- if ($m1 == 'not' && $m2 == 'not') {
+ if ($m1 === 'not' && $m2 === 'not') {
// CSS has no way of representing "neither screen nor print"
- if ($t1 != $t2) {
+ if ($t1 !== $t2) {
return null;
}
return array('not', $t1);
}
- if ($t1 != $t2) {
+ if ($t1 !== $t2) {
return null;
}
@@ -965,7 +965,7 @@ protected function mergeMediaTypes($type1, $type2)
*/
protected function compileImport($rawPath, $out)
{
- if ($rawPath[0] == 'string') {
+ if ($rawPath[0] === 'string') {
$path = $this->compileStringContent($rawPath);
if ($path = $this->findImport($path)) {
@@ -977,14 +977,14 @@ protected function compileImport($rawPath, $out)
return false;
}
- if ($rawPath[0] == 'list') {
+ if ($rawPath[0] === 'list') {
// handle a list of strings
- if (count($rawPath[2]) == 0) {
+ if (count($rawPath[2]) === 0) {
return false;
}
foreach ($rawPath[2] as $path) {
- if ($path[0] != 'string') {
+ if ($path[0] !== 'string') {
return false;
}
}
@@ -1054,7 +1054,7 @@ protected function compileChild($child, $out)
case 'assign':
list(, $name, $value) = $child;
- if ($name[0] == 'var') {
+ if ($name[0] === 'var') {
$flag = isset($child[3]) ? $child[3] : null;
$isDefault = $flag === '!default';
$isGlobal = $flag === '!global';
@@ -1067,7 +1067,7 @@ protected function compileChild($child, $out)
if ($isDefault) {
$existingValue = $this->get($name[1], true);
- $shouldSet = $existingValue === true || $existingValue == self::$null;
+ $shouldSet = $existingValue === true || $existingValue === self::$null;
}
if (! $isDefault || $shouldSet) {
@@ -1093,10 +1093,10 @@ protected function compileChild($child, $out)
// if the value reduces to null from something else then
// the property should be discarded
- if ($value[0] != 'null') {
+ if ($value[0] !== 'null') {
$value = $this->reduce($value);
- if ($value[0] == 'null') {
+ if ($value[0] === 'null') {
break;
}
}
@@ -1110,7 +1110,7 @@ protected function compileChild($child, $out)
break;
case 'comment':
- if ($out->type == 'root') {
+ if ($out->type === 'root') {
$this->compileComment($child);
break;
}
@@ -1131,7 +1131,9 @@ protected function compileChild($child, $out)
foreach ($selectors as $sel) {
// only use the first one
$result = $this->evalSelectors(array($sel));
- $this->pushExtends(current($result[0]), $out->selectors);
+ $result = current($result[0]);
+
+ $this->pushExtends($result, $out->selectors);
}
break;
@@ -1143,8 +1145,8 @@ protected function compileChild($child, $out)
}
foreach ($if->cases as $case) {
- if ($case->type == 'else' ||
- $case->type == 'elseif' && $this->isTruthy($this->reduce($case->cond))
+ if ($case->type === 'else' ||
+ $case->type === 'elseif' && $this->isTruthy($this->reduce($case->cond))
) {
return $this->compileChildren($case->children, $out);
}
@@ -1162,7 +1164,7 @@ protected function compileChild($child, $out)
foreach ($list[2] as $item) {
$this->pushEnv();
- if (count($each->vars) == 1) {
+ if (count($each->vars) === 1) {
$this->set($each->vars[0], $item);
} else {
list(,, $values) = $this->coerceList($item);
@@ -1228,11 +1230,11 @@ protected function compileChild($child, $out)
$prefix = $this->compileValue($prop->prefix) . '-';
foreach ($prop->children as $child) {
- if ($child[0] == 'assign') {
+ if ($child[0] === 'assign') {
array_unshift($child[1][2], $prefix);
}
- if ($child[0] == 'nestedprop') {
+ if ($child[0] === 'nestedprop') {
array_unshift($child[1]->prefix[2], $prefix);
}
@@ -1367,7 +1369,7 @@ protected function expToString($exp)
*/
protected function isTruthy($value)
{
- return $value != self::$false && $value != self::$null;
+ return $value !== self::$false && $value !== self::$null;
}
/**
@@ -1381,7 +1383,7 @@ protected function shouldEval($value)
{
switch ($value[0]) {
case 'exp':
- if ($value[1] == '/') {
+ if ($value[1] === '/') {
return $this->shouldEval($value[2], $value[3]);
}
@@ -1417,7 +1419,7 @@ protected function reduce($value, $inExp = false)
$right = $this->reduce($right, true);
// special case: looks like css short-hand
- if ($opName == 'div' && ! $inParens && ! $inExp && isset($right[2]) && $right[2] != '') {
+ if ($opName === 'div' && ! $inParens && ! $inExp && isset($right[2]) && $right[2] !== '') {
return $this->expToString($value);
}
@@ -1448,34 +1450,34 @@ protected function reduce($value, $inExp = false)
$unitChange = false;
if (! isset($genOp) &&
- $left[0] == 'number' && $right[0] == 'number'
+ $left[0] === 'number' && $right[0] === 'number'
) {
- if ($opName == 'mod' && $right[2] != '') {
+ if ($opName === 'mod' && $right[2] !== '') {
$this->throwError("Cannot modulo by a number with units: $right[1]$right[2].");
}
$unitChange = true;
- $emptyUnit = $left[2] == '' || $right[2] == '';
- $targetUnit = '' != $left[2] ? $left[2] : $right[2];
+ $emptyUnit = $left[2] === '' || $right[2] === '';
+ $targetUnit = '' !== $left[2] ? $left[2] : $right[2];
- if ($opName != 'mul') {
- $left[2] = '' != $left[2] ? $left[2] : $targetUnit;
- $right[2] = '' != $right[2] ? $right[2] : $targetUnit;
+ if ($opName !== 'mul') {
+ $left[2] = '' !== $left[2] ? $left[2] : $targetUnit;
+ $right[2] = '' !== $right[2] ? $right[2] : $targetUnit;
}
- if ($opName != 'mod') {
+ if ($opName !== 'mod') {
$left = $this->normalizeNumber($left);
$right = $this->normalizeNumber($right);
}
- if ($opName == 'div' && ! $emptyUnit && $left[2] == $right[2]) {
+ if ($opName === 'div' && ! $emptyUnit && $left[2] === $right[2]) {
$targetUnit = '';
}
- if ($opName == 'mul') {
- $left[2] = '' != $left[2] ? $left[2] : $right[2];
- $right[2] = '' != $right[2] ? $right[2] : $left[2];
- } elseif ($opName == 'div' && $left[2] == $right[2]) {
+ if ($opName === 'mul') {
+ $left[2] = '' !== $left[2] ? $left[2] : $right[2];
+ $right[2] = '' !== $right[2] ? $right[2] : $left[2];
+ } elseif ($opName === 'div' && $left[2] === $right[2]) {
$left[2] = '';
$right[2] = '';
}
@@ -1490,7 +1492,7 @@ protected function reduce($value, $inExp = false)
}
if (isset($out)) {
- if ($unitChange && $out[0] == 'number') {
+ if ($unitChange && $out[0] === 'number') {
$out = $this->coerceUnit($out, $targetUnit);
}
@@ -1506,7 +1508,7 @@ protected function reduce($value, $inExp = false)
$inExp = $inExp || $this->shouldEval($exp);
$exp = $this->reduce($exp);
- if ($exp[0] == 'number') {
+ if ($exp[0] === 'number') {
switch ($op) {
case '+':
return $exp;
@@ -1518,9 +1520,9 @@ protected function reduce($value, $inExp = false)
}
}
- if ($op == 'not') {
+ if ($op === 'not') {
if ($inExp || $inParens) {
- if ($exp == self::$false) {
+ if ($exp === self::$false) {
return self::$true;
}
@@ -1645,7 +1647,7 @@ public function normalizeValue($value)
case 'list':
$value = $this->extractInterpolation($value);
- if ($value[0] != 'list') {
+ if ($value[0] !== 'list') {
return array('keyword', $this->compileValue($value));
}
@@ -1766,7 +1768,7 @@ protected function opModNumberNumber($left, $right)
protected function opAdd($left, $right)
{
if ($strLeft = $this->coerceString($left)) {
- if ($right[0] == 'string') {
+ if ($right[0] === 'string') {
$right[1] = '';
}
@@ -1776,7 +1778,7 @@ protected function opAdd($left, $right)
}
if ($strRight = $this->coerceString($right)) {
- if ($left[0] == 'string') {
+ if ($left[0] === 'string') {
$left[1] = '';
}
@@ -1801,7 +1803,7 @@ protected function opAnd($left, $right, $shouldEval)
return;
}
- if ($left != self::$false) {
+ if ($left !== self::$false) {
return $right;
}
@@ -1823,7 +1825,7 @@ protected function opOr($left, $right, $shouldEval)
return;
}
- if ($left != self::$false) {
+ if ($left !== self::$false) {
return $left;
}
@@ -1950,7 +1952,7 @@ protected function opEq($left, $right)
$right = $this->compileValue($rStr);
}
- return $this->toBool($left == $right);
+ return $this->toBool($left === $right);
}
/**
@@ -1971,7 +1973,7 @@ protected function opNeq($left, $right)
$right = $this->compileValue($rStr);
}
- return $this->toBool($left != $right);
+ return $this->toBool($left !== $right);
}
/**
@@ -2078,7 +2080,7 @@ public function compileValue($value)
$g = round($g);
$b = round($b);
- if (count($value) == 5 && $value[4] != 1) { // rgba
+ if (count($value) === 5 && $value[4] !== 1) { // rgba
return 'rgba(' . $r . ', ' . $g . ', ' . $b . ', ' . $value[4] . ')';
}
@@ -2105,7 +2107,7 @@ public function compileValue($value)
case 'list':
$value = $this->extractInterpolation($value);
- if ($value[0] != 'list') {
+ if ($value[0] !== 'list') {
return $this->compileValue($value);
}
@@ -2114,7 +2116,7 @@ public function compileValue($value)
$filtered = array();
foreach ($items as $item) {
- if ($item[0] == 'null') {
+ if ($item[0] === 'null') {
continue;
}
@@ -2222,7 +2224,7 @@ protected function extractInterpolation($list)
$items = $list[2];
foreach ($items as $i => $item) {
- if ($item[0] == 'interpolate') {
+ if ($item[0] === 'interpolate') {
$before = array('list', $list[1], array_slice($items, 0, $i));
$after = array('list', $list[1], array_slice($items, $i + 1));
@@ -2287,7 +2289,7 @@ protected function joinSelectors($parent, $child)
$newPart = array();
foreach ($part as $p) {
- if ($p == self::$selfSelector) {
+ if ($p === self::$selfSelector) {
$setSelf = true;
foreach ($parent as $i => $parentPart) {
@@ -2322,7 +2324,7 @@ protected function joinSelectors($parent, $child)
protected function multiplyMedia($env, $childQueries = null)
{
if (! isset($env) ||
- ! empty($env->block->type) && $env->block->type != 'media'
+ ! empty($env->block->type) && $env->block->type !== 'media'
) {
return $childQueries;
}
@@ -2333,7 +2335,7 @@ protected function multiplyMedia($env, $childQueries = null)
}
$parentQueries = $env->block->queryList;
- if ($childQueries == null) {
+ if ($childQueries === null) {
$childQueries = $parentQueries;
} else {
$originalQueries = $childQueries;
@@ -2697,7 +2699,7 @@ public function findImport($url)
// check urls for normal import paths
foreach ($urls as $full) {
$full = $dir .
- (! empty($dir) && substr($dir, -1) != '/' ? '/' : '') .
+ (! empty($dir) && substr($dir, -1) !== '/' ? '/' : '') .
$full;
if ($this->fileExists($file = $full . '.scss') ||
@@ -2953,10 +2955,10 @@ protected function applyArguments($argDef, $argValues)
}
} elseif (count($keywordArgs)) {
$this->throwError('Positional arguments must come before keyword arguments.');
- } elseif ($arg[2] == true) {
+ } elseif ($arg[2] === true) {
$val = $this->reduce($arg[1], true);
- if ($val[0] == 'list') {
+ if ($val[0] === 'list') {
foreach ($val[2] as $name => $item) {
if (! is_numeric($name)) {
$keywordArgs[$name] = $item;
@@ -3043,7 +3045,7 @@ protected function coerceMap($item)
return $item;
}
- if ($item == self::$emptyList) {
+ if ($item === self::$emptyList) {
return self::$emptyMap;
}
@@ -3059,11 +3061,11 @@ protected function coerceMap($item)
*/
protected function coerceList($item, $delim = ',')
{
- if (isset($item) && $item[0] == 'list') {
+ if (isset($item) && $item[0] === 'list') {
return $item;
}
- if (isset($item) && $item[0] == 'map') {
+ if (isset($item) && $item[0] === 'map') {
$keys = $item[1];
$values = $item[2];
$list = array();
@@ -3152,8 +3154,8 @@ protected function coerceString($value)
*/
protected function coercePercent($value)
{
- if ($value[0] == 'number') {
- if ($value[2] == '%') {
+ if ($value[0] === 'number') {
+ if ($value[2] === '%') {
return $value[1] / 100;
}
@@ -3178,7 +3180,7 @@ public function assertMap($value)
{
$value = $this->coerceMap($value);
- if ($value[0] != 'map') {
+ if ($value[0] !== 'map') {
$this->throwError('expecting map');
}
@@ -3198,7 +3200,7 @@ public function assertMap($value)
*/
public function assertList($value)
{
- if ($value[0] != 'list') {
+ if ($value[0] !== 'list') {
$this->throwError('expecting list');
}
@@ -3238,7 +3240,7 @@ public function assertColor($value)
*/
public function assertNumber($value)
{
- if ($value[0] != 'number') {
+ if ($value[0] !== 'number') {
$this->throwError('expecting number');
}
@@ -3286,7 +3288,7 @@ public function toHSL($red, $green, $blue)
$l = $min + $max;
$d = $max - $min;
- if ((int) $d == 0) {
+ if ((int) $d === 0) {
$h = $s = 0;
} else {
if ($l < 255) {
@@ -3391,7 +3393,7 @@ protected function libIndex($args)
{
list($list, $value) = $args;
- if ($value[0] == 'map') {
+ if ($value[0] === 'map') {
return self::$null;
}
@@ -3454,7 +3456,7 @@ protected function alterColor($args, $fn)
foreach (array(1, 2, 3, 7) as $i) {
if (isset($args[$i])) {
$val = $this->assertNumber($args[$i]);
- $ii = $i == 7 ? 4 : $i; // alpha
+ $ii = $i === 7 ? 4 : $i; // alpha
$color[$ii] = call_user_func($fn, isset($color[$ii]) ? $color[$ii] : 0, $val, $i);
}
}
@@ -3619,7 +3621,7 @@ protected function libMix($args)
$w = $weight * 2 - 1;
$a = $firstAlpha - $secondAlpha;
- $w1 = (($w * $a == -1 ? $w : ($w + $a) / (1 + $w * $a)) + 1) / 2.0;
+ $w1 = (($w * $a === -1 ? $w : ($w + $a) / (1 + $w * $a)) + 1) / 2.0;
$w2 = 1.0 - $w1;
$new = array('color',
@@ -3824,7 +3826,7 @@ protected function libUnquote($args)
{
$str = $args[0];
- if ($str[0] == 'string') {
+ if ($str[0] === 'string') {
$str[1] = '';
}
@@ -3836,7 +3838,7 @@ protected function libQuote($args)
{
$value = $args[0];
- if ($value[0] == 'string' && ! empty($value[1])) {
+ if ($value[0] === 'string' && ! empty($value[1])) {
return $value;
}
@@ -3929,7 +3931,7 @@ protected function getNormalizedNumbers($args)
$numbers = array();
foreach ($args as $key => $item) {
- if ('number' != $item[0]) {
+ if ('number' !== $item[0]) {
$this->throwError('%s is not a number', $item[0]);
}
@@ -4152,7 +4154,7 @@ protected function libTypeOf($args)
switch ($value[0]) {
case 'keyword':
- if ($value == self::$true || $value == self::$false) {
+ if ($value === self::$true || $value === self::$false) {
return 'bool';
}
@@ -4180,7 +4182,7 @@ protected function libUnit($args)
{
$num = $args[0];
- if ($num[0] == 'number') {
+ if ($num[0] === 'number') {
return array('string', '"', array($num[2]));
}
@@ -4192,7 +4194,7 @@ protected function libUnitless($args)
{
$value = $args[0];
- return $value[0] == 'number' && empty($value[2]);
+ return $value[0] === 'number' && empty($value[2]);
}
protected static $libComparable = array('number-1', 'number-2');
@@ -4200,14 +4202,14 @@ protected function libComparable($args)
{
list($number1, $number2) = $args;
- if (! isset($number1[0]) || $number1[0] != 'number' || ! isset($number2[0]) || $number2[0] != 'number') {
+ if (! isset($number1[0]) || $number1[0] !== 'number' || ! isset($number2[0]) || $number2[0] !== 'number') {
$this->throwError('Invalid argument(s) for "comparable"');
}
$number1 = $this->normalizeNumber($number1);
$number2 = $this->normalizeNumber($number2);
- return $number1[2] == $number2[2] || $number1[2] == '' || $number2[2] == '';
+ return $number1[2] === $number2[2] || $number1[2] === '' || $number2[2] === '';
}
protected static $libStrIndex = array('string', 'substring');
diff --git a/src/Formatter/Nested.php b/src/Formatter/Nested.php
index 1bad2f27..bd2c4d21 100644
--- a/src/Formatter/Nested.php
+++ b/src/Formatter/Nested.php
@@ -101,7 +101,7 @@ protected function blockLines($inner, $block)
*/
protected function block($block)
{
- if ($block->type == 'root') {
+ if ($block->type === 'root') {
$this->adjustAllChildren($block);
}
@@ -126,7 +126,7 @@ protected function block($block)
if (isset($block->children[$i + 1])) {
$next = $block->children[$i + 1];
- if ($next->depth == max($block->depth, 1) && $child->depth >= $next->depth) {
+ if ($next->depth === max($block->depth, 1) && $child->depth >= $next->depth) {
echo $this->break;
}
}
@@ -138,7 +138,7 @@ protected function block($block)
echo $this->close;
}
- if ($block->type == 'root') {
+ if ($block->type === 'root') {
echo $this->break;
}
}
diff --git a/src/Parser.php b/src/Parser.php
index bb085a5f..16b4b177 100644
--- a/src/Parser.php
+++ b/src/Parser.php
@@ -141,7 +141,7 @@ public function parse($buffer)
;
}
- if ($this->count != strlen($this->buffer)) {
+ if ($this->count !== strlen($this->buffer)) {
$this->throwParseError();
}
@@ -240,7 +240,7 @@ protected function parseChunk()
$s = $this->seek();
// the directives
- if (isset($this->buffer[$this->count]) && $this->buffer[$this->count] == '@') {
+ if (isset($this->buffer[$this->count]) && $this->buffer[$this->count] === '@') {
if ($this->literal('@media') && $this->mediaQueryList($mediaQueryList) && $this->literal('{')) {
$media = $this->pushSpecialBlock('media', $s);
$media->queryList = $mediaQueryList[2];
@@ -446,7 +446,7 @@ protected function parseChunk()
$last = $this->last();
- if (isset($last) && $last[0] == 'if') {
+ if (isset($last) && $last[0] === 'if') {
list(, $if) = $last;
if ($this->literal('@else')) {
@@ -580,7 +580,7 @@ protected function parseChunk()
if ($this->literal('}')) {
$block = $this->popBlock();
- if (isset($block->type) && $block->type == 'include') {
+ if (isset($block->type) && $block->type === 'include') {
$include = $block->child;
unset($block->child);
$include[3] = $block;
@@ -645,7 +645,7 @@ protected function literal($what, $eatWhitespace = null)
// shortcut on single letter
if (! isset($what[1]) && isset($this->buffer[$this->count])) {
- if ($this->buffer[$this->count] == $what) {
+ if ($this->buffer[$this->count] === $what) {
if (! $eatWhitespace) {
$this->count++;
@@ -987,13 +987,13 @@ protected function genericList(&$out, $parseItem, $delim = '', $flatten = true)
}
}
- if (count($items) == 0) {
+ if (count($items) === 0) {
$this->seek($s);
return false;
}
- if ($flatten && count($items) == 1) {
+ if ($flatten && count($items) === 1) {
$out = $items[0];
} else {
$out = array('list', $delim, $items);
@@ -1146,7 +1146,7 @@ protected function value(&$out)
}
if ($this->keyword($keyword)) {
- if ($keyword == 'null') {
+ if ($keyword === 'null') {
$out = array('null');
} else {
$out = array('keyword', $keyword);
@@ -1239,13 +1239,13 @@ protected function func(&$func)
if ($this->keyword($name, false) &&
$this->literal('(')
) {
- if ($name == 'alpha' && $this->argumentList($args)) {
+ if ($name === 'alpha' && $this->argumentList($args)) {
$func = array('function', $name, array('string', '', $args));
return true;
}
- if ($name != 'expression' && ! preg_match('/^(-[a-z]+-)?calc$/', $name)) {
+ if ($name !== 'expression' && ! preg_match('/^(-[a-z]+-)?calc$/', $name)) {
$ss = $this->seek();
if ($this->argValues($args) && $this->literal(')')) {
@@ -1498,7 +1498,7 @@ protected function string(&$out)
while ($this->matchString($m, $delim)) {
$content[] = $m[1];
- if ($m[2] == '#{') {
+ if ($m[2] === '#{') {
$this->count -= strlen($m[2]);
if ($this->interpolation($inter, false)) {
@@ -1507,7 +1507,7 @@ protected function string(&$out)
$this->count += strlen($m[2]);
$content[] = '#{'; // ignore it
}
- } elseif ($m[2] == '\\') {
+ } elseif ($m[2] === '\\') {
$content[] = $m[2];
if ($this->literal($delim, false)) {
@@ -1564,7 +1564,7 @@ protected function mixedKeyword(&$out)
$this->eatWhiteDefault = $oldWhite;
- if (count($parts) == 0) {
+ if (count($parts) === 0) {
return false;
}
@@ -1614,16 +1614,16 @@ protected function openString($end, &$out, $nestingOpen = null)
$this->count-= strlen($tok);
- if ($tok == $end && ! $nestingLevel--) {
+ if ($tok === $end && ! $nestingLevel--) {
break;
}
- if (($tok == '\'' || $tok == '"') && $this->string($str)) {
+ if (($tok === '\'' || $tok === '"') && $this->string($str)) {
$content[] = $str;
continue;
}
- if ($tok == '#{' && $this->interpolation($inter)) {
+ if ($tok === '#{' && $this->interpolation($inter)) {
$content[] = $inter;
continue;
}
@@ -1634,7 +1634,7 @@ protected function openString($end, &$out, $nestingOpen = null)
$this->eatWhiteDefault = $oldWhite;
- if (count($content) == 0) {
+ if (count($content) === 0) {
return false;
}
@@ -1707,7 +1707,7 @@ protected function propertyName(&$out)
$parts[] = $inter;
} elseif ($this->keyword($text)) {
$parts[] = $text;
- } elseif (count($parts) == 0 && $this->match('[:.#]', $m, false)) {
+ } elseif (count($parts) === 0 && $this->match('[:.#]', $m, false)) {
// css hacks
$parts[] = $m[0];
} else {
@@ -1717,7 +1717,7 @@ protected function propertyName(&$out)
$this->eatWhiteDefault = $oldWhite;
- if (count($parts) == 0) {
+ if (count($parts) === 0) {
return false;
}
@@ -1766,7 +1766,7 @@ protected function selectors(&$out)
}
}
- if (count($selectors) == 0) {
+ if (count($selectors) === 0) {
$this->seek($s);
return false;
@@ -1802,7 +1802,7 @@ protected function selector(&$out)
}
- if (count($selector) == 0) {
+ if (count($selector) === 0) {
return false;
}
@@ -1979,7 +1979,7 @@ protected function selectorSingle(&$out)
$this->eatWhiteDefault = $oldWhite;
- if (count($parts) == 0) {
+ if (count($parts) === 0) {
return false;
}
@@ -2080,7 +2080,7 @@ protected function end()
return true;
}
- if ($this->count == strlen($this->buffer) || $this->buffer[$this->count] == '}') {
+ if ($this->count === strlen($this->buffer) || $this->buffer[$this->count] === '}') {
// if there is end of file or a closing block next then we don't need a ;
return true;
}
@@ -2333,7 +2333,7 @@ protected function show()
*/
protected function flattenList($value)
{
- if ($value[0] == 'list' && count($value[2]) == 1) {
+ if ($value[0] === 'list' && count($value[2]) === 1) {
return $this->flattenList($value[2][0]);
}
From 064ac6d572adca51c3df72a300c6fe4b197b18e5 Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Sat, 5 Sep 2015 18:15:49 -0400
Subject: [PATCH 064/534] fix nested_function_def from scss_test.rb
---
src/Compiler.php | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/src/Compiler.php b/src/Compiler.php
index eb74c5c8..a211f686 100644
--- a/src/Compiler.php
+++ b/src/Compiler.php
@@ -2424,10 +2424,10 @@ protected function setExisting($name, $value, $env = null)
$env = $this->getStoreEnv();
}
- if (isset($env->store[$name]) || ! isset($env->parent)) {
- $env->store[$name] = $value;
- } else {
+ if (! isset($env->store[$name]) && isset($env->parent) && $this->has($name, $env->parent)) {
$this->setExisting($name, $value, $env->parent);
+ } else {
+ $env->store[$name] = $value;
}
}
From 9c769106419797d9b39213b2e69fe740f00e83fc Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Sat, 5 Sep 2015 19:11:19 -0400
Subject: [PATCH 065/534] fixes #319 - don't throw exception in Compiler
injectVariables by coercing values
---
src/Compiler.php | 45 +++++++++++++++++++++++++++++++++++----------
1 file changed, 35 insertions(+), 10 deletions(-)
diff --git a/src/Compiler.php b/src/Compiler.php
index a211f686..9faf8bdb 100644
--- a/src/Compiler.php
+++ b/src/Compiler.php
@@ -695,7 +695,7 @@ function ($value, $key) use (&$output) {
$parts[] = $output;
}
- return implode(', ', $parts);;
+ return implode(', ', $parts);
}
/**
@@ -2515,7 +2515,7 @@ protected function injectVariables(array $args)
}
if (! $parser->parseValue($strValue, $value)) {
- throw new \Exception("failed to parse passed in variable $name: $strValue");
+ $value = $this->coerceValue($strValue);
}
$this->set($name, $value);
@@ -2818,14 +2818,7 @@ protected function callBuiltin($name, $args, &$returnValue)
}
if (isset($returnValue)) {
- // coerce a php value into a scss one
- if (is_numeric($returnValue)) {
- $returnValue = array('number', $returnValue, '');
- } elseif (is_bool($returnValue)) {
- $returnValue = $returnValue ? self::$true : self::$false;
- } elseif (! is_array($returnValue)) {
- $returnValue = array('keyword', $returnValue);
- }
+ $returnValue = $this->coerceValue($returnValue);
return true;
}
@@ -3013,6 +3006,38 @@ protected function applyArguments($argDef, $argValues)
}
}
+ /**
+ * Coerce a php value into a scss one
+ *
+ * @param mixed $value
+ *
+ * @return array
+ */
+ private function coerceValue($value)
+ {
+ if (is_array($value)) {
+ return $value;
+ }
+
+ if (is_bool($value)) {
+ return $value ? self::$true : self::$false;
+ }
+
+ if ($value === null) {
+ $value = self::$null;
+ }
+
+ if (is_numeric($value)) {
+ return array('number', $value, '');
+ }
+
+ if ($value === '') {
+ return self::$emptyString;
+ }
+
+ return array('keyword', $value);
+ }
+
/**
* Coerce unit on number to be normalized
*
From 94efd300fd5ac35ffe39e538eba6727e2e6e5fef Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Sat, 5 Sep 2015 21:19:45 -0400
Subject: [PATCH 066/534] internals: unreachable code
---
src/Compiler.php | 4 ----
1 file changed, 4 deletions(-)
diff --git a/src/Compiler.php b/src/Compiler.php
index 9faf8bdb..bdfb1bf5 100644
--- a/src/Compiler.php
+++ b/src/Compiler.php
@@ -381,10 +381,6 @@ protected function matchExtendsSingle($single, &$outOrigin)
$counts = array();
foreach ($single as $part) {
- if (! is_string($part)) {
- return false; // hmm
- }
-
if (isset($this->extendsMap[$part])) {
foreach ($this->extendsMap[$part] as $idx) {
$counts[$idx] = isset($counts[$idx]) ? $counts[$idx] + 1 : 1;
From 72475fabb53bb1fc79bed0b3a975f4362b36a891 Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Sat, 5 Sep 2015 22:19:51 -0400
Subject: [PATCH 067/534] fixes #318 (more or less)
---
src/Compiler.php | 13 +++++++++++--
tests/FailingTest.php | 12 ------------
tests/inputs/extends.scss | 5 +++++
tests/outputs/extends.css | 2 ++
tests/outputs_numbered/extends.css | 7 +++++++
5 files changed, 25 insertions(+), 14 deletions(-)
diff --git a/src/Compiler.php b/src/Compiler.php
index bdfb1bf5..1b6f5034 100644
--- a/src/Compiler.php
+++ b/src/Compiler.php
@@ -371,14 +371,23 @@ protected function matchExtends($selector, &$out, $from = 0, $initial = true)
/**
* Match extends single
*
- * @param array $single
+ * @param array $rawSingle
* @param array $outOrigin
*
* @return boolean
*/
- protected function matchExtendsSingle($single, &$outOrigin)
+ protected function matchExtendsSingle($rawSingle, &$outOrigin)
{
$counts = array();
+ $single = array();
+
+ foreach ($rawSingle as $part) {
+ if (! preg_match('/^[\[.:#%]/', $part) && count($single)) {
+ $single[count($single) - 1] .= $part;
+ } else {
+ $single[] = $part;
+ }
+ }
foreach ($single as $part) {
if (isset($this->extendsMap[$part])) {
diff --git a/tests/FailingTest.php b/tests/FailingTest.php
index ac66c41e..cf4677d3 100644
--- a/tests/FailingTest.php
+++ b/tests/FailingTest.php
@@ -170,18 +170,6 @@ public function provideFailing()
, <<
Date: Sat, 5 Sep 2015 23:15:44 -0400
Subject: [PATCH 068/534] Bump version to 0.2.1
---
src/Version.php | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/Version.php b/src/Version.php
index 5d3ce31e..32f0bf74 100644
--- a/src/Version.php
+++ b/src/Version.php
@@ -18,5 +18,5 @@
*/
class Version
{
- const VERSION = 'v0.2.0';
+ const VERSION = 'v0.2.1';
}
From 3fb23ddc146d85244d0f1ca3d23d83a298bb8f90 Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Sat, 5 Sep 2015 23:18:49 -0400
Subject: [PATCH 069/534] fixes #320 - Compiler getParsedFiles() compat-buster
---
src/Compiler.php | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/Compiler.php b/src/Compiler.php
index 1b6f5034..e30f6306 100644
--- a/src/Compiler.php
+++ b/src/Compiler.php
@@ -2669,8 +2669,8 @@ protected function importFile($path, $out)
$code = file_get_contents($path);
$parser = new Parser($path, false);
$tree = $parser->parse($code);
- $this->parsedFiles[] = $path;
+ $this->parsedFiles[realPath] = filemtime($path);
$this->importCache[$realPath] = $tree;
}
From 1dbd589e19d6978ff0e007a4d89c254748d2cc82 Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Sun, 6 Sep 2015 00:02:08 -0400
Subject: [PATCH 070/534] fix unit test
---
src/Server.php | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/Server.php b/src/Server.php
index c2304dd4..5bd9bef0 100644
--- a/src/Server.php
+++ b/src/Server.php
@@ -138,8 +138,8 @@ protected function needsCompile($in, $out, &$etag)
if (is_readable($metadataName)) {
$metadata = unserialize(file_get_contents($metadataName));
- foreach ($metadata['imports'] as $import) {
- if (filemtime($import) > $mtime) {
+ foreach ($metadata['imports'] as $import => $importMtime) {
+ if ($importMtime > $mtime) {
return true;
}
}
From e86ae9c10bd04107e9e102839deebe0f6a33c071 Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Sun, 6 Sep 2015 03:05:54 -0400
Subject: [PATCH 071/534] fix @each scope
---
src/Compiler.php | 15 ++++++++++-----
tests/inputs/looping.scss | 4 ++++
tests/outputs/looping.css | 3 ++-
tests/outputs_numbered/looping.css | 15 ++++++++-------
4 files changed, 24 insertions(+), 13 deletions(-)
diff --git a/src/Compiler.php b/src/Compiler.php
index e30f6306..598171d6 100644
--- a/src/Compiler.php
+++ b/src/Compiler.php
@@ -536,9 +536,11 @@ protected function compileNestedBlock($block, $selectors)
$this->scope = $this->makeOutputBlock($block->type, $selectors);
$this->scope->parent->children[] = $this->scope;
+
$this->compileChildren($block->children, $this->scope);
$this->scope = $this->scope->parent;
+
$this->popEnv();
}
@@ -1166,26 +1168,29 @@ protected function compileChild($child, $out)
$list = $this->coerceList($this->reduce($each->list));
- foreach ($list[2] as $item) {
- $this->pushEnv();
+ $this->pushEnv();
+ foreach ($list[2] as $item) {
if (count($each->vars) === 1) {
- $this->set($each->vars[0], $item);
+ $this->set($each->vars[0], $item, true);
} else {
list(,, $values) = $this->coerceList($item);
foreach ($each->vars as $i => $var) {
- $this->set($var, isset($values[$i]) ? $values[$i] : self::$null);
+ $this->set($var, isset($values[$i]) ? $values[$i] : self::$null, true);
}
}
$ret = $this->compileChildren($each->children, $out);
- $this->popEnv();
if ($ret) {
+ $this->popEnv();
+
return $ret;
}
}
+
+ $this->popEnv();
break;
case 'while':
diff --git a/tests/inputs/looping.scss b/tests/inputs/looping.scss
index d0325dc0..dd96b12c 100644
--- a/tests/inputs/looping.scss
+++ b/tests/inputs/looping.scss
@@ -1,5 +1,7 @@
div {
+ $var: red;
+
@each $var in what is this {
color: $var;
}
@@ -32,6 +34,8 @@ div {
border: $nonexistent;
}
}
+
+ color: $var;
}
diff --git a/tests/outputs/looping.css b/tests/outputs/looping.css
index 2836f70d..1dd81d68 100644
--- a/tests/outputs/looping.css
+++ b/tests/outputs/looping.css
@@ -16,7 +16,8 @@ div {
background: this this;
background: what what;
background: is is;
- background: this this; }
+ background: this this;
+ color: red; }
div h1 {
font-size: 2em; }
div h2 {
diff --git a/tests/outputs_numbered/looping.css b/tests/outputs_numbered/looping.css
index 98838286..921e978f 100644
--- a/tests/outputs_numbered/looping.css
+++ b/tests/outputs_numbered/looping.css
@@ -17,17 +17,18 @@ div {
background: this this;
background: what what;
background: is is;
- background: this this; }
-/* line 30, inputs/looping.scss */
+ background: this this;
+ color: red; }
+/* line 32, inputs/looping.scss */
div h1 {
font-size: 2em; }
-/* line 30, inputs/looping.scss */
+/* line 32, inputs/looping.scss */
div h2 {
font-size: 1.5em; }
-/* line 30, inputs/looping.scss */
+/* line 32, inputs/looping.scss */
div h3 {
font-size: 1.2em; }
-/* line 38, inputs/looping.scss */
+/* line 42, inputs/looping.scss */
span {
color: 0;
color: 1;
@@ -40,7 +41,7 @@ span {
color: 8;
color: 9;
color: 10; }
-/* line 46, inputs/looping.scss */
+/* line 50, inputs/looping.scss */
pre {
color: 1;
color: 2;
@@ -59,7 +60,7 @@ pre {
cool: 5;
cool: 4;
cool: 3; }
-/* line 81, inputs/looping.scss */
+/* line 85, inputs/looping.scss */
div {
a: false;
b: true;
From da33429c3525c0cf5858ef01bf0ad1df113b7924 Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Sun, 6 Sep 2015 06:28:05 -0400
Subject: [PATCH 072/534] internals: remove recursion from Compiler
setExisting() and get()
---
src/Compiler.php | 62 +++++++++++++++++++++++++++++-------------------
1 file changed, 37 insertions(+), 25 deletions(-)
diff --git a/src/Compiler.php b/src/Compiler.php
index 598171d6..7a2a8cd5 100644
--- a/src/Compiler.php
+++ b/src/Compiler.php
@@ -1068,14 +1068,12 @@ protected function compileChild($child, $out)
if ($isGlobal) {
$this->set($name[1], $this->reduce($value), false, $this->rootEnv);
-
break;
}
- if ($isDefault) {
- $existingValue = $this->get($name[1], true);
- $shouldSet = $existingValue === true || $existingValue === self::$null;
- }
+ $shouldSet = $isDefault &&
+ (($result = $this->get($name[1], false)) === null
+ || $result === self::$null);
if (! $isDefault || $shouldSet) {
$this->set($name[1], $this->reduce($value));
@@ -1230,7 +1228,6 @@ protected function compileChild($child, $out)
return $ret;
}
}
-
break;
case 'nestedprop':
@@ -1290,9 +1287,9 @@ protected function compileChild($child, $out)
break;
case 'mixin_content':
- $content = $this->get(self::$namespaces['special'] . 'content');
+ $content = $this->get(self::$namespaces['special'] . 'content', false);
- if (! isset($content)) {
+ if (! $content) {
$this->throwError('Expected @content inside of mixin');
}
@@ -2434,11 +2431,22 @@ protected function setExisting($name, $value, $env = null)
$env = $this->getStoreEnv();
}
- if (! isset($env->store[$name]) && isset($env->parent) && $this->has($name, $env->parent)) {
- $this->setExisting($name, $value, $env->parent);
- } else {
- $env->store[$name] = $value;
+ $storeEnv = $env;
+
+ for (;;) {
+ if (array_key_exists($name, $env->store)) {
+ break;
+ }
+
+ if (! isset($env->parent)) {
+ $env = $storeEnv;
+ break;
+ }
+
+ $env = $env->parent;
}
+
+ $env->store[$name] = $value;
}
/**
@@ -2463,12 +2471,12 @@ protected function setRaw($name, $value, $env = null)
* @api
*
* @param string $name
- * @param mixed $defaultValue
+ * @param boolean $shouldThrow
* @param \stdClass $env
*
* @return mixed
*/
- public function get($name, $defaultValue = null, $env = null)
+ public function get($name, $shouldThrow = true, $env = null)
{
$name = $this->normalizeName($name);
@@ -2476,19 +2484,25 @@ public function get($name, $defaultValue = null, $env = null)
$env = $this->getStoreEnv();
}
- if (! isset($defaultValue)) {
- $defaultValue = self::$defaultValue;
- }
+ $hasNamespace = $name[0] === '^' || $name[0] === '@' || $name[0] === '%';
+
+ for (;;) {
+ if (array_key_exists($name, $env->store)) {
+ return $env->store[$name];
+ }
- if (isset($env->store[$name])) {
- return $env->store[$name];
+ if (! isset($env->parent)) {
+ break;
+ }
+
+ $env = $env->parent;
}
- if (isset($env->parent)) {
- return $this->get($name, $defaultValue, $env->parent);
+ if ($shouldThrow) {
+ $this->throwError('undefined variable $' . $name);
}
- return $defaultValue; // found nothing
+ // found nothing
}
/**
@@ -2501,9 +2515,7 @@ public function get($name, $defaultValue = null, $env = null)
*/
protected function has($name, $env = null)
{
- $value = $this->get($name, false, $env);
-
- return $value !== false;
+ return $this->get($name, false, $env) !== null;
}
/**
From f88ecf10d3e1a460a9e04100756243251409f0e5 Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Sun, 6 Sep 2015 06:37:35 -0400
Subject: [PATCH 073/534] fix fix
---
src/Compiler.php | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/Compiler.php b/src/Compiler.php
index 7a2a8cd5..16ed3bf8 100644
--- a/src/Compiler.php
+++ b/src/Compiler.php
@@ -2687,7 +2687,7 @@ protected function importFile($path, $out)
$parser = new Parser($path, false);
$tree = $parser->parse($code);
- $this->parsedFiles[realPath] = filemtime($path);
+ $this->parsedFiles[$realPath] = filemtime($path);
$this->importCache[$realPath] = $tree;
}
From 73c403dccbbab3f5ba8a9257bd624d0e322923b2 Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Sun, 6 Sep 2015 18:04:22 -0400
Subject: [PATCH 074/534] fixes #295 - multiple variable scoping bugs
---
src/Compiler.php | 17 ++++++++++++++++-
tests/ExceptionTest.php | 26 ++++++++++++++++++++++++++
tests/FailingTest.php | 17 -----------------
tests/inputs/variables.scss | 10 ++++++++++
tests/outputs/variables.css | 3 +++
tests/outputs_numbered/variables.css | 3 +++
6 files changed, 58 insertions(+), 18 deletions(-)
diff --git a/src/Compiler.php b/src/Compiler.php
index 16ed3bf8..f02a4b7e 100644
--- a/src/Compiler.php
+++ b/src/Compiler.php
@@ -1272,6 +1272,7 @@ protected function compileChild($child, $out)
if (isset($content)) {
$content->scope = $callingScope;
+
$this->setRaw(self::$namespaces['special'] . 'content', $content);
}
@@ -1279,6 +1280,8 @@ protected function compileChild($child, $out)
$this->applyArguments($mixin->args, $argValues);
}
+ $this->env->marker = 'mixin';
+
foreach ($mixin->children as $child) {
$this->compileChild($child, $out);
}
@@ -2433,11 +2436,18 @@ protected function setExisting($name, $value, $env = null)
$storeEnv = $env;
+ $hasNamespace = $name[0] === '^' || $name[0] === '@' || $name[0] === '%';
+
for (;;) {
if (array_key_exists($name, $env->store)) {
break;
}
+ if (! $hasNamespace && isset($env->marker)) {
+ $env = $storeEnv;
+ break;
+ }
+
if (! isset($env->parent)) {
$env = $storeEnv;
break;
@@ -2491,6 +2501,11 @@ public function get($name, $shouldThrow = true, $env = null)
return $env->store[$name];
}
+ if (! $hasNamespace && isset($env->marker)) {
+ $env = $this->rootEnv;
+ continue;
+ }
+
if (! isset($env->parent)) {
break;
}
@@ -2499,7 +2514,7 @@ public function get($name, $shouldThrow = true, $env = null)
}
if ($shouldThrow) {
- $this->throwError('undefined variable $' . $name);
+ $this->throwError("Undefined variable \$$name");
}
// found nothing
diff --git a/tests/ExceptionTest.php b/tests/ExceptionTest.php
index 50255f40..12ec165f 100644
--- a/tests/ExceptionTest.php
+++ b/tests/ExceptionTest.php
@@ -103,6 +103,32 @@ public function provideScss()
,
'expecting color'
),
+ array(<<<'END_OF_SCSS'
+BODY {
+ DIV {
+ $bg: red;
+ }
+
+ background: $bg;
+}
+END_OF_SCSS
+ ,
+ 'Undefined variable $bg'
+ ),
+ array(<<<'END_OF_SCSS'
+@mixin example {
+ background: $bg;
+}
+
+P {
+ $bg: red;
+
+ @include example;
+}
+END_OF_SCSS
+ ,
+ 'Undefined variable $bg'
+ ),
);
}
diff --git a/tests/FailingTest.php b/tests/FailingTest.php
index cf4677d3..f6ec0ffc 100644
--- a/tests/FailingTest.php
+++ b/tests/FailingTest.php
@@ -153,23 +153,6 @@ public function provideFailing()
transform: scale(0.5); }
to {
transform: scale(1); } }
-END_OF_EXPECTED
- ),
- array(
- '#295 - variable scope bug', <<<'END_OF_SCSS'
-@mixin example {
- $color: red;
-}
-
-A {
- $color: green;
- @include example;
- color: $color;
-}
-END_OF_SCSS
- , <<
Date: Sun, 6 Sep 2015 20:27:37 -0400
Subject: [PATCH 075/534] Reverts 94efd300; fixes #323
---
src/Compiler.php | 5 +++++
tests/inputs/directives.scss | 17 +++++++++++++++++
tests/outputs/directives.css | 10 ++++++++++
tests/outputs_numbered/directives.css | 12 ++++++++++++
4 files changed, 44 insertions(+)
diff --git a/src/Compiler.php b/src/Compiler.php
index f02a4b7e..ac7b56fe 100644
--- a/src/Compiler.php
+++ b/src/Compiler.php
@@ -382,6 +382,11 @@ protected function matchExtendsSingle($rawSingle, &$outOrigin)
$single = array();
foreach ($rawSingle as $part) {
+ // matches Number
+ if (! is_string($part)) {
+ return false;
+ }
+
if (! preg_match('/^[\[.:#%]/', $part) && count($single)) {
$single[count($single) - 1] .= $part;
} else {
diff --git a/tests/inputs/directives.scss b/tests/inputs/directives.scss
index 10e39422..14b89cb7 100644
--- a/tests/inputs/directives.scss
+++ b/tests/inputs/directives.scss
@@ -108,3 +108,20 @@ div {
{
body { color: purple; background: yellow; }
}
+
+@keyframes anim-rotate {
+ 0% {
+ transform: rotate(0);
+ }
+ 100% {
+ transform: rotate(360deg);
+ }
+}
+
+.bold {
+ font-weight: 700;
+}
+
+.icon-ajax {
+ @extend .bold;
+}
diff --git a/tests/outputs/directives.css b/tests/outputs/directives.css
index 2b715582..4a1ced6e 100644
--- a/tests/outputs/directives.css
+++ b/tests/outputs/directives.css
@@ -75,3 +75,13 @@ div {
body {
color: purple;
background: yellow; } }
+
+@keyframes anim-rotate {
+ 0% {
+ transform: rotate(0); }
+
+ 100% {
+ transform: rotate(360deg); } }
+
+.bold, .icon-ajax {
+ font-weight: 700; }
diff --git a/tests/outputs_numbered/directives.css b/tests/outputs_numbered/directives.css
index 7de43a31..9b77350e 100644
--- a/tests/outputs_numbered/directives.css
+++ b/tests/outputs_numbered/directives.css
@@ -83,3 +83,15 @@ to {
body {
color: purple;
background: yellow; } }
+
+@keyframes anim-rotate {
+/* line 113, inputs/directives.scss */
+0% {
+ transform: rotate(0); }
+/* line 116, inputs/directives.scss */
+100% {
+ transform: rotate(360deg); } }
+/* line 121, inputs/directives.scss */
+.bold, .icon-ajax {
+ font-weight: 700; }
+/* line 125, inputs/directives.scss */
From 4bcaed23664897db093a50e99b93e078f3a31a2d Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Sun, 6 Sep 2015 21:04:49 -0400
Subject: [PATCH 076/534] bump version to 0.3.0
---
src/Version.php | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/Version.php b/src/Version.php
index 32f0bf74..c650a26d 100644
--- a/src/Version.php
+++ b/src/Version.php
@@ -18,5 +18,5 @@
*/
class Version
{
- const VERSION = 'v0.2.1';
+ const VERSION = 'v0.3.0';
}
From e688a85898c3a9e33199276252cf0ed4b1073640 Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Sun, 6 Sep 2015 22:46:01 -0400
Subject: [PATCH 077/534] temporary: partially revert 73c403dc to work with
bootstrap v4-dev
---
src/Compiler.php | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/Compiler.php b/src/Compiler.php
index ac7b56fe..a95e69f3 100644
--- a/src/Compiler.php
+++ b/src/Compiler.php
@@ -1285,7 +1285,7 @@ protected function compileChild($child, $out)
$this->applyArguments($mixin->args, $argValues);
}
- $this->env->marker = 'mixin';
+ //$this->env->marker = 'mixin';
foreach ($mixin->children as $child) {
$this->compileChild($child, $out);
From 92514e267989690264312553828e70fa127a191c Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Thu, 10 Sep 2015 11:29:51 -0400
Subject: [PATCH 078/534] Remove deprecated "strict" option from
phpunit.xml.dist
---
phpunit.xml.dist | 1 -
1 file changed, 1 deletion(-)
diff --git a/phpunit.xml.dist b/phpunit.xml.dist
index 57219d25..c007930c 100644
--- a/phpunit.xml.dist
+++ b/phpunit.xml.dist
@@ -4,7 +4,6 @@
Date: Fri, 11 Sep 2015 21:41:46 -0400
Subject: [PATCH 079/534] Fix docblock
---
src/Parser.php | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/Parser.php b/src/Parser.php
index 16b4b177..8b27a27e 100644
--- a/src/Parser.php
+++ b/src/Parser.php
@@ -697,7 +697,7 @@ protected function pushBlock($selectors, $pos = 0)
/**
* Push special (named) block onto parse tree
*
- * @param array $selectors
+ * @param string $type
* @param integer $pos
*
* @return \stdClass
From 2977aa444415787e931c048989b8c9195fd5b344 Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Fri, 11 Sep 2015 21:42:27 -0400
Subject: [PATCH 080/534] Fixes #324 bootstrap v4-dev regression
---
src/Compiler.php | 16 +++++-----------
1 file changed, 5 insertions(+), 11 deletions(-)
diff --git a/src/Compiler.php b/src/Compiler.php
index a95e69f3..bef345bc 100644
--- a/src/Compiler.php
+++ b/src/Compiler.php
@@ -1270,10 +1270,7 @@ protected function compileChild($child, $out)
// push scope, apply args
$this->pushEnv();
-
- if ($this->env->depth > 0) {
- $this->env->depth--;
- }
+ $this->env->depth--;
if (isset($content)) {
$content->scope = $callingScope;
@@ -1285,7 +1282,7 @@ protected function compileChild($child, $out)
$this->applyArguments($mixin->args, $argValues);
}
- //$this->env->marker = 'mixin';
+ $this->env->marker = 'mixin';
foreach ($mixin->children as $child) {
$this->compileChild($child, $out);
@@ -1305,17 +1302,14 @@ protected function compileChild($child, $out)
break;
}
- $strongTypes = array('include', 'block', 'for', 'while');
+ $this->storeEnv = $content->scope;
foreach ($content->children as $child) {
- $this->storeEnv = (in_array($child[0], $strongTypes))
- ? null
- : $content->scope;
-
$this->compileChild($child, $out);
}
- unset($this->storeEnv);
+ $this->storeEnv = null;
+
break;
case 'debug':
From 18fccbd309f250fd5fe34cd9c6d6f5da67aed958 Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Fri, 11 Sep 2015 23:11:09 -0400
Subject: [PATCH 081/534] Bump version to 0.3.1
---
src/Version.php | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/Version.php b/src/Version.php
index c650a26d..efd45ca0 100644
--- a/src/Version.php
+++ b/src/Version.php
@@ -18,5 +18,5 @@
*/
class Version
{
- const VERSION = 'v0.3.0';
+ const VERSION = 'v0.3.1';
}
From 18773ccdff5d322665567d85930d8f2a48a3c60f Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Sun, 13 Sep 2015 12:02:56 -0400
Subject: [PATCH 082/534] internals: adjustAllChildren() scope
---
src/Formatter/Nested.php | 95 ++++++++++++++++++++++------------------
1 file changed, 53 insertions(+), 42 deletions(-)
diff --git a/src/Formatter/Nested.php b/src/Formatter/Nested.php
index bd2c4d21..1f709b95 100644
--- a/src/Formatter/Nested.php
+++ b/src/Formatter/Nested.php
@@ -34,48 +34,6 @@ public function __construct()
$this->assignSeparator = ': ';
}
- /**
- * Adjust the depths of all children, depth first
- *
- * @param \stdClass $block
- */
- public function adjustAllChildren($block)
- {
- // flatten empty nested blocks
- $children = array();
- foreach ($block->children as $i => $child) {
- if (empty($child->lines) && empty($child->children)) {
- if (isset($block->children[$i + 1])) {
- $block->children[$i + 1]->depth = $child->depth;
- }
- continue;
- }
- $children[] = $child;
- }
-
- $count = count($children);
- for ($i = 0; $i < $count; $i++) {
- $depth = $children[$i]->depth;
- $j = $i + 1;
- if (isset($children[$j]) && $depth < $children[$j]->depth) {
- $childDepth = $children[$j]->depth;
- for (; $j < $count; $j++) {
- if ($depth < $children[$j]->depth && $childDepth >= $children[$j]->depth) {
- $children[$j]->depth = $depth + 1;
- }
- }
- }
- }
-
- $block->children = $children;
-
- // make relative to parent
- foreach ($block->children as $child) {
- $this->adjustAllChildren($child);
- $child->depth = $child->depth - $block->depth;
- }
- }
-
/**
* {@inheritdoc}
*/
@@ -110,7 +68,9 @@ protected function block($block)
echo $pre .
implode($this->tagSeparator, $block->selectors) .
$this->open . $this->break;
+
$this->indentLevel++;
+
$inner = $this->indentStr($block->depth - 1);
}
@@ -126,6 +86,7 @@ protected function block($block)
if (isset($block->children[$i + 1])) {
$next = $block->children[$i + 1];
+
if ($next->depth === max($block->depth, 1) && $child->depth >= $next->depth) {
echo $this->break;
}
@@ -135,6 +96,7 @@ protected function block($block)
if (! empty($block->selectors)) {
$this->indentLevel--;
+
echo $this->close;
}
@@ -142,4 +104,53 @@ protected function block($block)
echo $this->break;
}
}
+
+ /**
+ * Adjust the depths of all children, depth first
+ *
+ * @param \stdClass $block
+ */
+ private function adjustAllChildren($block)
+ {
+ // flatten empty nested blocks
+ $children = array();
+
+ foreach ($block->children as $i => $child) {
+ if (empty($child->lines) && empty($child->children)) {
+ if (isset($block->children[$i + 1])) {
+ $block->children[$i + 1]->depth = $child->depth;
+ }
+
+ continue;
+ }
+
+ $children[] = $child;
+ }
+
+ $count = count($children);
+
+ for ($i = 0; $i < $count; $i++) {
+ $depth = $children[$i]->depth;
+ $j = $i + 1;
+
+ if (isset($children[$j]) && $depth < $children[$j]->depth) {
+ $childDepth = $children[$j]->depth;
+
+ for (; $j < $count; $j++) {
+ if ($depth < $children[$j]->depth && $childDepth >= $children[$j]->depth) {
+ $children[$j]->depth = $depth + 1;
+ }
+ }
+ }
+ }
+
+ $block->children = $children;
+
+ // make relative to parent
+ foreach ($block->children as $child) {
+ $this->adjustAllChildren($child);
+
+ $child->depth = $child->depth - $block->depth;
+ }
+ }
}
From f9431a4c8aa0aacb2c369c1f583e3349093d06eb Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Sun, 13 Sep 2015 15:11:48 -0400
Subject: [PATCH 083/534] internals: add debug formatter
---
scss.inc.php | 1 +
src/Compiler.php | 8 ++--
src/Formatter.php | 30 +++++++++-----
src/Formatter/Compressed.php | 4 +-
src/Formatter/Crunched.php | 4 +-
src/Formatter/Debug.php | 77 ++++++++++++++++++++++++++++++++++++
src/Formatter/Expanded.php | 4 +-
src/Formatter/Nested.php | 25 ++++++++----
8 files changed, 130 insertions(+), 23 deletions(-)
create mode 100644 src/Formatter/Debug.php
diff --git a/scss.inc.php b/scss.inc.php
index 51ae57e5..da641f7c 100644
--- a/scss.inc.php
+++ b/scss.inc.php
@@ -11,6 +11,7 @@
include_once __DIR__ . '/src/Formatter/Compact.php';
include_once __DIR__ . '/src/Formatter/Compressed.php';
include_once __DIR__ . '/src/Formatter/Crunched.php';
+ include_once __DIR__ . '/src/Formatter/Debug.php';
include_once __DIR__ . '/src/Formatter/Expanded.php';
include_once __DIR__ . '/src/Formatter/Nested.php';
include_once __DIR__ . '/src/Parser.php';
diff --git a/src/Compiler.php b/src/Compiler.php
index bef345bc..620821c9 100644
--- a/src/Compiler.php
+++ b/src/Compiler.php
@@ -1303,11 +1303,13 @@ protected function compileChild($child, $out)
}
$this->storeEnv = $content->scope;
+ //$this->pushEnv();
foreach ($content->children as $child) {
$this->compileChild($child, $out);
}
+ //$this->popEnv();
$this->storeEnv = null;
break;
@@ -2734,9 +2736,9 @@ public function findImport($url)
if (is_string($dir)) {
// check urls for normal import paths
foreach ($urls as $full) {
- $full = $dir .
- (! empty($dir) && substr($dir, -1) !== '/' ? '/' : '') .
- $full;
+ $full = $dir
+ . (! empty($dir) && substr($dir, -1) !== '/' ? '/' : '')
+ . $full;
if ($this->fileExists($file = $full . '.scss') ||
$this->fileExists($file = $full)
diff --git a/src/Formatter.php b/src/Formatter.php
index 5b035e1c..f08cdfe7 100644
--- a/src/Formatter.php
+++ b/src/Formatter.php
@@ -92,12 +92,14 @@ public function stripSemicolon(&$lines)
/**
* Output lines inside a block
*
- * @param string $inner
* @param \stdClass $block
*/
- protected function blockLines($inner, $block)
+ protected function blockLines($block)
{
+ $inner = $this->indentStr();
+
$glue = $this->break . $inner;
+
echo $inner . implode($glue, $block->lines);
if (! empty($block->children)) {
@@ -105,6 +107,20 @@ protected function blockLines($inner, $block)
}
}
+ /**
+ * Output block selectors
+ *
+ * @param \stdClass $block
+ */
+ protected function blockSelectors($block)
+ {
+ $inner = $this->indentStr();
+
+ echo $inner
+ . implode($this->tagSeparator, $block->selectors)
+ . $this->open . $this->break;
+ }
+
/**
* Output non-empty block
*
@@ -116,20 +132,16 @@ protected function block($block)
return;
}
- $inner = $pre = $this->indentStr();
+ $pre = $this->indentStr();
if (! empty($block->selectors)) {
- echo $pre
- . implode($this->tagSeparator, $block->selectors)
- . $this->open . $this->break;
+ $this->blockSelectors($block);
$this->indentLevel++;
-
- $inner = $this->indentStr();
}
if (! empty($block->lines)) {
- $this->blockLines($inner, $block);
+ $this->blockLines($block);
}
foreach ($block->children as $child) {
diff --git a/src/Formatter/Compressed.php b/src/Formatter/Compressed.php
index c95b68b3..2ab2eaae 100644
--- a/src/Formatter/Compressed.php
+++ b/src/Formatter/Compressed.php
@@ -57,8 +57,10 @@ public function stripSemicolon(&$lines)
/**
* {@inheritdoc}
*/
- public function blockLines($inner, $block)
+ public function blockLines($block)
{
+ $inner = $this->indentStr();
+
$glue = $this->break . $inner;
foreach ($block->lines as $index => $line) {
diff --git a/src/Formatter/Crunched.php b/src/Formatter/Crunched.php
index 1227c122..ad52c464 100644
--- a/src/Formatter/Crunched.php
+++ b/src/Formatter/Crunched.php
@@ -57,8 +57,10 @@ public function stripSemicolon(&$lines)
/**
* {@inheritdoc}
*/
- public function blockLines($inner, $block)
+ public function blockLines($block)
{
+ $inner = $this->indentStr();
+
$glue = $this->break . $inner;
foreach ($block->lines as $index => $line) {
diff --git a/src/Formatter/Debug.php b/src/Formatter/Debug.php
new file mode 100644
index 00000000..7e227b48
--- /dev/null
+++ b/src/Formatter/Debug.php
@@ -0,0 +1,77 @@
+
+ */
+class Debug extends Formatter
+{
+ /**
+ * {@inheritdoc}
+ */
+ public function __construct()
+ {
+ $this->indentLevel = 0;
+ $this->indentChar = '';
+ $this->break = "\n";
+ $this->open = ' {';
+ $this->close = ' }';
+ $this->tagSeparator = ', ';
+ $this->assignSeparator = ': ';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function blockLines($block)
+ {
+ foreach ($block->lines as $index => $line) {
+ echo "block->lines[{$index}]: $line\n";
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function blockSelectors($block)
+ {
+ foreach ($block->selectors as $index => $selector) {
+ echo "block->selectors[{$index}]: $selector\n";
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function block($block)
+ {
+ echo "block->type: {$block->type}\n" .
+ "block->depth: {$block->depth}\n";
+
+ if (! empty($block->selectors)) {
+ $this->blockSelectors($block);
+ }
+
+ if (! empty($block->lines)) {
+ $this->blockLines($block);
+ }
+
+ foreach ($block->children as $i => $child) {
+ $this->block($child);
+ }
+ }
+}
diff --git a/src/Formatter/Expanded.php b/src/Formatter/Expanded.php
index fbf85c1e..89ecfffb 100644
--- a/src/Formatter/Expanded.php
+++ b/src/Formatter/Expanded.php
@@ -37,8 +37,10 @@ public function __construct()
/**
* {@inheritdoc}
*/
- protected function blockLines($inner, $block)
+ protected function blockLines($block)
{
+ $inner = $this->indentStr();
+
$glue = $this->break . $inner;
foreach ($block->lines as $index => $line) {
diff --git a/src/Formatter/Nested.php b/src/Formatter/Nested.php
index 1f709b95..bf2c4a67 100644
--- a/src/Formatter/Nested.php
+++ b/src/Formatter/Nested.php
@@ -37,8 +37,10 @@ public function __construct()
/**
* {@inheritdoc}
*/
- protected function blockLines($inner, $block)
+ protected function blockLines($block)
{
+ $inner = $this->indentStr($block->depth - 1);
+
$glue = $this->break . $inner;
foreach ($block->lines as $index => $line) {
@@ -54,6 +56,18 @@ protected function blockLines($inner, $block)
}
}
+ /**
+ * {@inheritdoc}
+ */
+ protected function blockSelectors($block)
+ {
+ $inner = $this->indentStr($block->depth - 1);
+
+ echo $inner
+ . implode($this->tagSeparator, $block->selectors)
+ . $this->open . $this->break;
+ }
+
/**
* {@inheritdoc}
*/
@@ -63,19 +77,14 @@ protected function block($block)
$this->adjustAllChildren($block);
}
- $inner = $pre = $this->indentStr($block->depth - 1);
if (! empty($block->selectors)) {
- echo $pre .
- implode($this->tagSeparator, $block->selectors) .
- $this->open . $this->break;
+ $this->blockSelectors($block);
$this->indentLevel++;
-
- $inner = $this->indentStr($block->depth - 1);
}
if (! empty($block->lines)) {
- $this->blockLines($inner, $block);
+ $this->blockLines($block);
}
foreach ($block->children as $i => $child) {
From 108219502ea7ec4664c37eb149c1c33e175cd433 Mon Sep 17 00:00:00 2001
From: Andre Mohren
Date: Tue, 22 Sep 2015 09:05:02 +0200
Subject: [PATCH 084/534] @importOnce support - while not an official feature,
this allows modules to specify dependencies which have to be loaded if not
already loaded without loading them twice.
---
src/Compiler.php | 58 ++++++++++++++++++++++++++++++++++++++++++++++++
src/Parser.php | 11 +++++++++
2 files changed, 69 insertions(+)
diff --git a/src/Compiler.php b/src/Compiler.php
index 620821c9..c46a217e 100644
--- a/src/Compiler.php
+++ b/src/Compiler.php
@@ -107,6 +107,7 @@ class Compiler
protected $importPaths = array('');
protected $importCache = array();
+ protected $importedFiles = array();
protected $userFunctions = array();
protected $registeredVars = array();
@@ -982,6 +983,53 @@ protected function compileImport($rawPath, $out)
if ($path = $this->findImport($path)) {
$this->importFile($path, $out);
+ $this->importedFiles[] = $path;
+
+ return true;
+ }
+
+ return false;
+ }
+
+ if ($rawPath[0] === 'list') {
+ // handle a list of strings
+ if (count($rawPath[2]) === 0) {
+ return false;
+ }
+
+ foreach ($rawPath[2] as $path) {
+ if ($path[0] !== 'string') {
+ return false;
+ }
+ }
+
+ foreach ($rawPath[2] as $path) {
+ $this->compileImport($path, $out);
+ }
+
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * Compile importOnce; returns true if the value was something that could be imported
+ *
+ * @param array $rawPath
+ * @param array $out
+ *
+ * @return boolean
+ */
+ protected function compileImportOnce($rawPath, $out)
+ {
+ if ($rawPath[0] === 'string') {
+ $path = $this->compileStringContent($rawPath);
+ if ($path = $this->findImport($path)) {
+ if (!in_array($path, $this->importedFiles)) {
+ $this->importFile($path, $out);
+ $this->importedFiles[] = $path;
+ }
return true;
}
@@ -1025,6 +1073,16 @@ protected function compileChild($child, $out)
$this->sourceParser = isset($child[Parser::SOURCE_PARSER]) ? $child[Parser::SOURCE_PARSER] : $this->parser;
switch ($child[0]) {
+ case 'importOnce':
+ list(, $rawPath) = $child;
+
+ $rawPath = $this->reduce($rawPath);
+
+ if (! $this->compileImportOnce($rawPath, $out)) {
+ $out->lines[] = '@importOnce ' . $this->compileValue($rawPath) . ';';
+ }
+ break;
+
case 'import':
list(, $rawPath) = $child;
diff --git a/src/Parser.php b/src/Parser.php
index 8b27a27e..0cf6a3cc 100644
--- a/src/Parser.php
+++ b/src/Parser.php
@@ -287,6 +287,17 @@ protected function parseChunk()
$this->seek($s);
+ if ($this->literal('@importOnce') &&
+ $this->valueList($importPath) &&
+ $this->end()
+ ) {
+ $this->append(array('importOnce', $importPath), $s);
+
+ return true;
+ }
+
+ $this->seek($s);
+
if ($this->literal('@import') &&
$this->valueList($importPath) &&
$this->end()
From b6c40f2238a41aacb9fe47daf38a41b58e99c4c0 Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Tue, 22 Sep 2015 15:58:26 -0400
Subject: [PATCH 085/534] add #336 test
---
tests/FailingTest.php | 25 +++++++++++++++++++++++++
1 file changed, 25 insertions(+)
diff --git a/tests/FailingTest.php b/tests/FailingTest.php
index f6ec0ffc..858a0ad5 100644
--- a/tests/FailingTest.php
+++ b/tests/FailingTest.php
@@ -153,6 +153,31 @@ public function provideFailing()
transform: scale(0.5); }
to {
transform: scale(1); } }
+END_OF_EXPECTED
+ ),
+ array(
+ '#336 - @extend with interpolation of list', <<<'END_OF_SCSS'
+.selector1 {
+ color: blue;
+}
+
+.selector2 {
+ background: #ccc;
+}
+
+$var: ".selector1, .selector2";
+
+.master-class {
+ // interpolation of the variable is needed since we have a selector in $var
+ @extend #{$var};
+}
+END_OF_SCSS
+ , <<
Date: Wed, 23 Sep 2015 08:35:48 +0200
Subject: [PATCH 086/534] Renamed @importOnce to @scssphp-import-once to follow
sass naming conventions and use vendor-prefixes.
---
src/Compiler.php | 4 ++--
src/Parser.php | 4 ++--
2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/src/Compiler.php b/src/Compiler.php
index c46a217e..6346e28e 100644
--- a/src/Compiler.php
+++ b/src/Compiler.php
@@ -1073,13 +1073,13 @@ protected function compileChild($child, $out)
$this->sourceParser = isset($child[Parser::SOURCE_PARSER]) ? $child[Parser::SOURCE_PARSER] : $this->parser;
switch ($child[0]) {
- case 'importOnce':
+ case 'scssphp-import-once':
list(, $rawPath) = $child;
$rawPath = $this->reduce($rawPath);
if (! $this->compileImportOnce($rawPath, $out)) {
- $out->lines[] = '@importOnce ' . $this->compileValue($rawPath) . ';';
+ $out->lines[] = '@scssphp-import-once ' . $this->compileValue($rawPath) . ';';
}
break;
diff --git a/src/Parser.php b/src/Parser.php
index 0cf6a3cc..f74fdbd8 100644
--- a/src/Parser.php
+++ b/src/Parser.php
@@ -287,11 +287,11 @@ protected function parseChunk()
$this->seek($s);
- if ($this->literal('@importOnce') &&
+ if ($this->literal('@scssphp-import-once') &&
$this->valueList($importPath) &&
$this->end()
) {
- $this->append(array('importOnce', $importPath), $s);
+ $this->append(array('scssphp-import-once', $importPath), $s);
return true;
}
From d1c5336236ca7498ef6eefd69d293696c35c6cd1 Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Wed, 23 Sep 2015 13:11:43 -0400
Subject: [PATCH 087/534] fixes #336
---
src/Compiler.php | 11 +++++++----
tests/FailingTest.php | 25 -------------------------
tests/inputs/extends.scss | 15 +++++++++++++++
tests/outputs/extends.css | 6 ++++++
tests/outputs_numbered/extends.css | 8 ++++++++
5 files changed, 36 insertions(+), 29 deletions(-)
diff --git a/src/Compiler.php b/src/Compiler.php
index 620821c9..010f430d 100644
--- a/src/Compiler.php
+++ b/src/Compiler.php
@@ -1139,11 +1139,14 @@ protected function compileChild($child, $out)
list(, $selectors) = $child;
foreach ($selectors as $sel) {
- // only use the first one
- $result = $this->evalSelectors(array($sel));
- $result = current($result[0]);
+ $results = $this->evalSelectors(array($sel));
- $this->pushExtends($result, $out->selectors);
+ foreach ($results as $result) {
+ // only use the first one
+ $result = current($result);
+
+ $this->pushExtends($result, $out->selectors);
+ }
}
break;
diff --git a/tests/FailingTest.php b/tests/FailingTest.php
index 858a0ad5..f6ec0ffc 100644
--- a/tests/FailingTest.php
+++ b/tests/FailingTest.php
@@ -153,31 +153,6 @@ public function provideFailing()
transform: scale(0.5); }
to {
transform: scale(1); } }
-END_OF_EXPECTED
- ),
- array(
- '#336 - @extend with interpolation of list', <<<'END_OF_SCSS'
-.selector1 {
- color: blue;
-}
-
-.selector2 {
- background: #ccc;
-}
-
-$var: ".selector1, .selector2";
-
-.master-class {
- // interpolation of the variable is needed since we have a selector in $var
- @extend #{$var};
-}
-END_OF_SCSS
- , <<
Date: Mon, 21 Sep 2015 15:48:42 -0400
Subject: [PATCH 088/534] More efficient solution to adding base scss file into
allParseFiles variable pushing logic into new public method for Compiler
---
src/Compiler.php | 17 ++++++++++++++++-
1 file changed, 16 insertions(+), 1 deletion(-)
diff --git a/src/Compiler.php b/src/Compiler.php
index 010f430d..e706b240 100644
--- a/src/Compiler.php
+++ b/src/Compiler.php
@@ -161,6 +161,8 @@ public function compile($code, $name = null)
$this->formatter = new $this->formatter();
+ $this->addParsedFile($name);
+
$this->rootEnv = $this->pushEnv($tree);
$this->injectVariables($this->registeredVars);
$this->compileRoot($tree);
@@ -2587,6 +2589,19 @@ public function unsetVariable($name)
unset($this->registeredVars[$name]);
}
+ /**
+ * Adds to list of parsed files
+ *
+ * @api
+ *
+ * @param string $file
+ */
+ public function addParsedFile($file) {
+ if (!empty($file)) {
+ $this->parsedFiles[realpath($file)] = filemtime($file);
+ }
+ }
+
/**
* Returns list of parsed files
*
@@ -2706,7 +2721,7 @@ protected function importFile($path, $out)
$parser = new Parser($path, false);
$tree = $parser->parse($code);
- $this->parsedFiles[$realPath] = filemtime($path);
+ $this->addParsedFile($path);
$this->importCache[$realPath] = $tree;
}
From 7db57eb7bc3c80a418d066524bd9e5d8b294b8eb Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Wed, 23 Sep 2015 14:17:32 -0400
Subject: [PATCH 089/534] fixes #339; closes #340
---
bin/pscss | 4 ++--
src/Compiler.php | 19 ++++++++++---------
src/Parser.php | 2 +-
3 files changed, 13 insertions(+), 12 deletions(-)
diff --git a/bin/pscss b/bin/pscss
index 8a21393e..f4b7ba8f 100755
--- a/bin/pscss
+++ b/bin/pscss
@@ -146,7 +146,7 @@ if ($inputFile) {
}
if ($dumpTree) {
- $parser = new Parser($inputFile ?: 'STDIN');
+ $parser = new Parser($inputFile);
print_r(json_decode(json_encode($parser->parse($data)), true));
@@ -175,7 +175,7 @@ if ($style) {
$scss->setFormatter('Leafo\\ScssPhp\\Formatter\\' . ucfirst($style));
}
-echo $scss->compile($data, $inputFile ?: 'STDIN');
+echo $scss->compile($data, $inputFile);
if ($changeDir) {
chdir($oldWorkingDir);
diff --git a/src/Compiler.php b/src/Compiler.php
index e706b240..2488cebd 100644
--- a/src/Compiler.php
+++ b/src/Compiler.php
@@ -136,11 +136,11 @@ class Compiler
* @api
*
* @param string $code
- * @param string $name
+ * @param string $path
*
* @return string
*/
- public function compile($code, $name = null)
+ public function compile($code, $path = null)
{
$this->indentLevel = -1;
$this->commentsSeen = array();
@@ -155,13 +155,13 @@ public function compile($code, $name = null)
$locale = setlocale(LC_NUMERIC, 0);
setlocale(LC_NUMERIC, 'C');
- $this->parser = new Parser($name);
+ $this->parser = new Parser($path);
$tree = $this->parser->parse($code);
$this->formatter = new $this->formatter();
- $this->addParsedFile($name);
+ $this->addParsedFile($path);
$this->rootEnv = $this->pushEnv($tree);
$this->injectVariables($this->registeredVars);
@@ -2594,13 +2594,14 @@ public function unsetVariable($name)
*
* @api
*
- * @param string $file
+ * @param string $path
*/
- public function addParsedFile($file) {
- if (!empty($file)) {
- $this->parsedFiles[realpath($file)] = filemtime($file);
+ public function addParsedFile($path)
+ {
+ if (isset($path)) {
+ $this->parsedFiles[realpath($path)] = filemtime($path);
}
- }
+ }
/**
* Returns list of parsed files
diff --git a/src/Parser.php b/src/Parser.php
index 8b27a27e..80926060 100644
--- a/src/Parser.php
+++ b/src/Parser.php
@@ -87,7 +87,7 @@ class Parser
*/
public function __construct($sourceName = null, $rootParser = true)
{
- $this->sourceName = $sourceName;
+ $this->sourceName = $sourceName ?: '(stdin)';
$this->rootParser = $rootParser;
$this->charset = null;
From ad9875274d83e3387d62cffc6ac856837a5dc8f7 Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Wed, 23 Sep 2015 22:34:22 -0400
Subject: [PATCH 090/534] Parser: parent is needed
---
src/Parser.php | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/Parser.php b/src/Parser.php
index 80926060..815ea09d 100644
--- a/src/Parser.php
+++ b/src/Parser.php
@@ -671,7 +671,7 @@ protected function literal($what, $eatWhitespace = null)
protected function pushBlock($selectors, $pos = 0)
{
$b = new \stdClass;
- $b->parent = $this->env; // not sure if we need this yet
+ $b->parent = $this->env;
$b->sourcePosition = $pos;
$b->sourceParser = $this;
From ceadeabdb9112996d45939d94ed4d7f38c281237 Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Wed, 23 Sep 2015 22:47:57 -0400
Subject: [PATCH 091/534] Formatter: factoring out blockChildren()
---
src/Formatter.php | 16 ++++++++++++++--
src/Formatter/Debug.php | 38 +++++++++++++++++++++++++++++---------
src/Formatter/Nested.php | 38 ++++++++++++++++++++++++--------------
3 files changed, 67 insertions(+), 25 deletions(-)
diff --git a/src/Formatter.php b/src/Formatter.php
index f08cdfe7..c341f1d7 100644
--- a/src/Formatter.php
+++ b/src/Formatter.php
@@ -121,6 +121,18 @@ protected function blockSelectors($block)
. $this->open . $this->break;
}
+ /**
+ * Output block children
+ *
+ * @param \stdClass $block
+ */
+ protected function blockChildren($block)
+ {
+ foreach ($block->children as $child) {
+ $this->block($child);
+ }
+ }
+
/**
* Output non-empty block
*
@@ -144,8 +156,8 @@ protected function block($block)
$this->blockLines($block);
}
- foreach ($block->children as $child) {
- $this->block($child);
+ if (! empty($block->children)) {
+ $this->blockChildren($block);
}
if (! empty($block->selectors)) {
diff --git a/src/Formatter/Debug.php b/src/Formatter/Debug.php
index 7e227b48..1aae1dab 100644
--- a/src/Formatter/Debug.php
+++ b/src/Formatter/Debug.php
@@ -39,6 +39,12 @@ public function __construct()
*/
protected function blockLines($block)
{
+ if (empty($block->lines)) {
+ echo "block->lines: []\n";
+
+ return;
+ }
+
foreach ($block->lines as $index => $line) {
echo "block->lines[{$index}]: $line\n";
}
@@ -49,6 +55,12 @@ protected function blockLines($block)
*/
protected function blockSelectors($block)
{
+ if (empty($block->selectors)) {
+ echo "block->selectors: []\n";
+
+ return;
+ }
+
foreach ($block->selectors as $index => $selector) {
echo "block->selectors[{$index}]: $selector\n";
}
@@ -57,21 +69,29 @@ protected function blockSelectors($block)
/**
* {@inheritdoc}
*/
- protected function block($block)
+ protected function blockChildren($block)
{
- echo "block->type: {$block->type}\n" .
- "block->depth: {$block->depth}\n";
-
- if (! empty($block->selectors)) {
- $this->blockSelectors($block);
- }
+ if (empty($block->children)) {
+ echo "block->children: []\n";
- if (! empty($block->lines)) {
- $this->blockLines($block);
+ return;
}
foreach ($block->children as $i => $child) {
$this->block($child);
}
}
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function block($block)
+ {
+ echo "block->type: {$block->type}\n" .
+ "block->depth: {$block->depth}\n";
+
+ $this->blockSelectors($block);
+ $this->blockLines($block);
+ $this->blockChildren($block);
+ }
}
diff --git a/src/Formatter/Nested.php b/src/Formatter/Nested.php
index bf2c4a67..3897419b 100644
--- a/src/Formatter/Nested.php
+++ b/src/Formatter/Nested.php
@@ -68,6 +68,28 @@ protected function blockSelectors($block)
. $this->open . $this->break;
}
+ /**
+ * {@inheritdoc}
+ */
+ protected function blockChildren($block)
+ {
+ foreach ($block->children as $i => $child) {
+ $this->block($child);
+
+ if ($i < count($block->children) - 1) {
+ echo $this->break;
+
+ if (isset($block->children[$i + 1])) {
+ $next = $block->children[$i + 1];
+
+ if ($next->depth === max($block->depth, 1) && $child->depth >= $next->depth) {
+ echo $this->break;
+ }
+ }
+ }
+ }
+ }
+
/**
* {@inheritdoc}
*/
@@ -87,20 +109,8 @@ protected function block($block)
$this->blockLines($block);
}
- foreach ($block->children as $i => $child) {
- $this->block($child);
-
- if ($i < count($block->children) - 1) {
- echo $this->break;
-
- if (isset($block->children[$i + 1])) {
- $next = $block->children[$i + 1];
-
- if ($next->depth === max($block->depth, 1) && $child->depth >= $next->depth) {
- echo $this->break;
- }
- }
- }
+ if (! empty($block->children)) {
+ $this->blockChildren($block);
}
if (! empty($block->selectors)) {
From f50a8cefd1dff241841e0c3ef66aecf17e9b6b6f Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Wed, 23 Sep 2015 22:52:02 -0400
Subject: [PATCH 092/534] Compiler: cleanup
---
src/Compiler.php | 17 +++++++++--------
1 file changed, 9 insertions(+), 8 deletions(-)
diff --git a/src/Compiler.php b/src/Compiler.php
index 2488cebd..45c4c1aa 100644
--- a/src/Compiler.php
+++ b/src/Compiler.php
@@ -93,7 +93,7 @@ class Compiler
'mm' => 25.4,
'px' => 96,
'q' => 101.6,
- )
+ ),
);
static public $true = array('keyword', 'true');
@@ -494,10 +494,11 @@ protected function compileMedia($media)
}
if ($needsWrap) {
- $wrapped = (object)array(
+ $wrapped = (object) array(
'selectors' => array(),
- 'children' => $media->children
+ 'children' => $media->children,
);
+
$media->children = array(array('block', $wrapped));
}
@@ -819,8 +820,8 @@ protected function hasSelectorPlaceholder($selector)
/**
* Compile children
*
- * @param array $stms
- * @param array $out
+ * @param array $stms
+ * @param \stdClass $out
*
* @return array
*/
@@ -948,7 +949,7 @@ protected function mergeMediaTypes($type1, $type2)
return array(
$m1 === 'not' ? $m2 : $m1,
- $m1 === 'not' ? $t2 : $t1
+ $m1 === 'not' ? $t2 : $t1,
);
}
@@ -1602,9 +1603,9 @@ protected function reduce($value, $inExp = false)
}
// throw away lines and children
- $tmp = (object)array(
+ $tmp = (object) array(
'lines' => array(),
- 'children' => array()
+ 'children' => array(),
);
$ret = $this->compileChildren($func->children, $tmp);
From fb8ae6392338a1bcf7fa7dfef3730e578957f667 Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Wed, 23 Sep 2015 22:55:30 -0400
Subject: [PATCH 093/534] Compiler: compileBlock() optimization - calls
multiplySelectors() only if block has children
---
src/Compiler.php | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/src/Compiler.php b/src/Compiler.php
index 45c4c1aa..3641ac26 100644
--- a/src/Compiler.php
+++ b/src/Compiler.php
@@ -576,7 +576,7 @@ protected function compileBlock($block)
$env->selectors = $this->evalSelectors($block->selectors);
- $out = $this->makeOutputBlock(null, $this->multiplySelectors($env));
+ $out = $this->makeOutputBlock(null);
if (isset($this->lineNumberStyle) && count($env->selectors) && count($block->children)) {
$annotation = $this->makeOutputBlock('comment');
@@ -601,7 +601,11 @@ protected function compileBlock($block)
$this->scope->children[] = $out;
- $this->compileChildren($block->children, $out);
+ if (! empty($block->children)) {
+ $out->selectors = $this->multiplySelectors($env);
+
+ $this->compileChildren($block->children, $out);
+ }
$this->formatter->stripSemicolon($out->lines);
From 4faf52646b9edd1f4f0b9939669983cbe723cfad Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Wed, 23 Sep 2015 23:02:34 -0400
Subject: [PATCH 094/534] code tweak
---
src/Compiler.php | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/src/Compiler.php b/src/Compiler.php
index 3641ac26..47da5a8b 100644
--- a/src/Compiler.php
+++ b/src/Compiler.php
@@ -533,8 +533,6 @@ protected function mediaParent($scope)
/**
* Compile nested block
*
- * @todo refactor compileNestedBlock and compileMedia into same thing?
- *
* @param \stdClass $block
* @param array $selectors
*/
@@ -601,7 +599,7 @@ protected function compileBlock($block)
$this->scope->children[] = $out;
- if (! empty($block->children)) {
+ if (count($block->children)) {
$out->selectors = $this->multiplySelectors($env);
$this->compileChildren($block->children, $out);
From 01a63e3e300ab8badfdb3f6ff288c9b29c97f491 Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Thu, 24 Sep 2015 00:26:57 -0400
Subject: [PATCH 095/534] Use original test case
---
tests/FailingTest.php | 18 ++++++++++++++++++
1 file changed, 18 insertions(+)
diff --git a/tests/FailingTest.php b/tests/FailingTest.php
index f6ec0ffc..bd68a99b 100644
--- a/tests/FailingTest.php
+++ b/tests/FailingTest.php
@@ -133,6 +133,17 @@ public function provideFailing()
& {
color:blue;
}
+
+@-webkit-keyframes zoomer {
+ from {
+ transform:scale(0.5);
+ }
+
+ to {
+ transform:scale(1);
+ }
+}
+
@keyframes zoomer {
from {
transform:scale(0.5);
@@ -148,6 +159,13 @@ public function provideFailing()
, <<
Date: Thu, 24 Sep 2015 00:33:28 -0400
Subject: [PATCH 096/534] code tweak
---
src/Parser.php | 13 ++++++++-----
1 file changed, 8 insertions(+), 5 deletions(-)
diff --git a/src/Parser.php b/src/Parser.php
index 815ea09d..1a092a9b 100644
--- a/src/Parser.php
+++ b/src/Parser.php
@@ -470,7 +470,8 @@ protected function parseChunk()
// only retain the first @charset directive encountered
if ($this->literal('@charset') &&
- $this->valueList($charset) && $this->end()
+ $this->valueList($charset) &&
+ $this->end()
) {
if (! isset($this->charset)) {
$statement = array('charset', $charset);
@@ -490,7 +491,8 @@ protected function parseChunk()
$this->seek($s);
// doesn't match built in directive, do generic one
- if ($this->literal('@', false) && $this->keyword($dirName) &&
+ if ($this->literal('@', false) &&
+ $this->keyword($dirName) &&
($this->variable($dirValue) || $this->openString('{', $dirValue) || true) &&
$this->literal('{')
) {
@@ -527,7 +529,8 @@ protected function parseChunk()
// variable assigns
if ($this->variable($name) &&
$this->literal(':') &&
- $this->valueList($value) && $this->end()
+ $this->valueList($value) &&
+ $this->end()
) {
// check for '!flag'
$assignmentFlag = $this->stripAssignmentFlag($value);
@@ -1395,8 +1398,8 @@ protected function map(&$out)
$keys = array();
$values = array();
- while ($this->genericList($key, 'expression') && $this->literal(':')
- && $this->genericList($value, 'expression')
+ while ($this->genericList($key, 'expression') && $this->literal(':') &&
+ $this->genericList($value, 'expression')
) {
$keys[] = $key;
$values[] = $value;
From 6163f8646a74caa5515b3b30373aedea6b5d86a6 Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Thu, 24 Sep 2015 02:52:40 -0400
Subject: [PATCH 097/534] loop review
---
src/Compiler.php | 10 +++-------
src/Parser.php | 12 ++++++------
2 files changed, 9 insertions(+), 13 deletions(-)
diff --git a/src/Compiler.php b/src/Compiler.php
index 47da5a8b..554bb966 100644
--- a/src/Compiler.php
+++ b/src/Compiler.php
@@ -2263,15 +2263,11 @@ protected function extractInterpolation($list)
*/
protected function multiplySelectors($env)
{
- $envs = array();
-
- while (null !== $env) {
- if (! empty($env->selectors)) {
+ for ($envs = array(); $env; $env = $env->parent) {
+ if (count($env->selectors)) {
$envs[] = $env;
}
-
- $env = $env->parent;
- };
+ }
$selectors = array();
$parentSelectors = array(array());
diff --git a/src/Parser.php b/src/Parser.php
index 1a092a9b..9b6a8dfa 100644
--- a/src/Parser.php
+++ b/src/Parser.php
@@ -137,7 +137,7 @@ public function parse($buffer)
$this->pushBlock(null);
$this->popBlock();
- while (false !== $this->parseChunk()) {
+ while ($this->parseChunk()) {
;
}
@@ -1551,7 +1551,7 @@ protected function mixedKeyword(&$out)
$oldWhite = $this->eatWhiteDefault;
$this->eatWhiteDefault = false;
- while (true) {
+ for (;;) {
if ($this->keyword($key)) {
$parts[] = $key;
continue;
@@ -1705,7 +1705,7 @@ protected function propertyName(&$out)
$oldWhite = $this->eatWhiteDefault;
$this->eatWhiteDefault = false;
- while (true) {
+ for (;;) {
if ($this->interpolation($inter)) {
$parts[] = $inter;
} elseif ($this->keyword($text)) {
@@ -1791,7 +1791,7 @@ protected function selector(&$out)
{
$selector = array();
- while (true) {
+ for (;;) {
if ($this->match('[>+~]+', $m)) {
$selector[] = array($m[0]);
} elseif ($this->selectorSingle($part)) {
@@ -1835,7 +1835,7 @@ protected function selectorSingle(&$out)
$parts[] = '*';
}
- while (true) {
+ for (;;) {
// see if we can stop early
if ($this->match('\s*[{,]', $m)) {
$this->count--;
@@ -1928,7 +1928,7 @@ protected function selectorSingle(&$out)
$attrParts = array('[');
// keyword, string, operator
- while (true) {
+ for (;;) {
if ($this->literal(']', false)) {
$this->count--;
break; // get out early
From a8e987c70fde8eab8b53b2369beb703234ee05b6 Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Fri, 25 Sep 2015 00:49:04 -0400
Subject: [PATCH 098/534] fixes #281
---
src/Compiler.php | 82 ++++++++++++++++++++++++---
tests/FailingTest.php | 47 ---------------
tests/inputs/directives.scss | 28 +++++++++
tests/outputs/directives.css | 15 +++++
tests/outputs_numbered/directives.css | 21 +++++++
5 files changed, 137 insertions(+), 56 deletions(-)
diff --git a/src/Compiler.php b/src/Compiler.php
index 554bb966..a91db34b 100644
--- a/src/Compiler.php
+++ b/src/Compiler.php
@@ -530,6 +530,34 @@ protected function mediaParent($scope)
return $scope;
}
+ /**
+ * Compile keyframe block
+ *
+ * @param \stdClass $block
+ * @param array $selectors
+ */
+ protected function compileKeyframeBlock($block, $selectors)
+ {
+ $env = $this->pushEnv($block);
+
+ $envs = $this->compactEnv($env);
+
+ $this->env = $this->extractEnv(array_filter($envs, function ($e) {
+ return ! isset($e->block->selectors);
+ }));
+
+ $this->scope = $this->makeOutputBlock($block->type, $selectors);
+ $this->scope->depth = 1;
+ $this->scope->parent->children[] = $this->scope;
+
+ $this->compileChildren($block->children, $this->scope);
+
+ $this->scope = $this->scope->parent;
+ $this->env = $this->extractEnv($envs);
+
+ $this->popEnv();
+ }
+
/**
* Compile nested block
*
@@ -1049,7 +1077,11 @@ protected function compileChild($child, $out)
$s .= ' ' . $this->compileValue($directive->value);
}
- $this->compileNestedBlock($directive, array($s));
+ if ($directive->name === 'keyframes' || substr($directive->name, -10) === '-keyframes') {
+ $this->compileKeyframeBlock($directive, array($s));
+ } else {
+ $this->compileNestedBlock($directive, array($s));
+ }
break;
case 'media':
@@ -2245,7 +2277,7 @@ protected function extractInterpolation($list)
foreach ($items as $i => $item) {
if ($item[0] === 'interpolate') {
$before = array('list', $list[1], array_slice($items, 0, $i));
- $after = array('list', $list[1], array_slice($items, $i + 1));
+ $after = array('list', $list[1], array_slice($items, $i + 1));
return array('interpolated', $item, $before, $after);
}
@@ -2263,16 +2295,15 @@ protected function extractInterpolation($list)
*/
protected function multiplySelectors($env)
{
- for ($envs = array(); $env; $env = $env->parent) {
- if (count($env->selectors)) {
- $envs[] = $env;
- }
- }
-
- $selectors = array();
+ $envs = $this->compactEnv($env);
+ $selectors = array();
$parentSelectors = array(array());
while ($env = array_pop($envs)) {
+ if (empty($env->selectors)) {
+ continue;
+ }
+
$selectors = array();
foreach ($env->selectors as $selector) {
@@ -2366,6 +2397,39 @@ protected function multiplyMedia($env, $childQueries = null)
return $this->multiplyMedia($env->parent, $childQueries);
}
+ /**
+ * Convert env linked list to stack
+ *
+ * @param \stdClass $env
+ *
+ * @return array
+ */
+ private function compactEnv($env)
+ {
+ for ($envs = array(); $env; $env = $env->parent) {
+ $envs[] = $env;
+ }
+
+ return $envs;
+ }
+
+ /**
+ * Convert env stack to singly linked list
+ *
+ * @param array $envs
+ *
+ * @return \stdClass
+ */
+ private function extractEnv($envs)
+ {
+ for ($env = null; $e = array_pop($envs);) {
+ $e->parent = $env;
+ $env = $e;
+ }
+
+ return $env;
+ }
+
/**
* Push environment
*
diff --git a/tests/FailingTest.php b/tests/FailingTest.php
index bd68a99b..7a074a77 100644
--- a/tests/FailingTest.php
+++ b/tests/FailingTest.php
@@ -124,53 +124,6 @@ public function provideFailing()
small {
font-weight: italic; }
-END_OF_EXPECTED
- ),
- array(
- '#281 - nested animation selector', <<<'END_OF_SCSS'
-.custom-selector {
-
-& {
- color:blue;
-}
-
-@-webkit-keyframes zoomer {
- from {
- transform:scale(0.5);
- }
-
- to {
- transform:scale(1);
- }
-}
-
-@keyframes zoomer {
- from {
- transform:scale(0.5);
- }
-
- to {
- transform:scale(1);
- }
-}
-
-}
-END_OF_SCSS
- , <<
Date: Mon, 20 Jul 2015 20:03:46 -0400
Subject: [PATCH 099/534] partial @at-root support (#193)
---
src/Compiler.php | 34 ++++++++++++++++++++++++++++++
src/Parser.php | 18 +++++++++++++++-
tests/inputs/at_root.scss | 24 +++++++++++++++++++++
tests/outputs/at_root.css | 15 +++++++++++++
tests/outputs_numbered/at_root.css | 19 +++++++++++++++++
5 files changed, 109 insertions(+), 1 deletion(-)
create mode 100644 tests/inputs/at_root.scss
create mode 100644 tests/outputs/at_root.css
create mode 100644 tests/outputs_numbered/at_root.css
diff --git a/src/Compiler.php b/src/Compiler.php
index a91db34b..e578b8fa 100644
--- a/src/Compiler.php
+++ b/src/Compiler.php
@@ -530,6 +530,36 @@ protected function mediaParent($scope)
return $scope;
}
+ /**
+ * Compile at-root
+ *
+ * @param \stdClass $block
+ */
+ protected function compileAtRoot($block)
+ {
+ $env = $this->pushEnv($block);
+
+ $envs = $this->compactEnv($env);
+
+ if (isset($block->with)) {
+ // @todo move outside of nested directives, e.g., (without: all), (without: media supports), (with: rule)
+ } else {
+ // exclude selectors by default
+ $this->env->parent = $this->rootEnv;
+ }
+
+ $this->scope = $this->makeOutputBlock('at-root');
+ $this->scope->depth = 1;
+ $this->scope->parent->children[] = $this->scope;
+
+ $this->compileChildren($block->children, $this->scope);
+
+ $this->scope = $this->scope->parent;
+ $this->env = $this->extractEnv($envs);
+
+ $this->popEnv();
+ }
+
/**
* Compile keyframe block
*
@@ -1084,6 +1114,10 @@ protected function compileChild($child, $out)
}
break;
+ case 'at-root':
+ $this->compileAtRoot($child[1]);
+ break;
+
case 'media':
$this->compileMedia($child[1]);
break;
diff --git a/src/Parser.php b/src/Parser.php
index 9b6a8dfa..5e7370b2 100644
--- a/src/Parser.php
+++ b/src/Parser.php
@@ -241,6 +241,20 @@ protected function parseChunk()
// the directives
if (isset($this->buffer[$this->count]) && $this->buffer[$this->count] === '@') {
+ if ($this->literal('@at-root') &&
+ ($this->selectors($selector) || true) &&
+ ($this->map($with) || true) &&
+ $this->literal('{')
+ ) {
+ $atRoot = $this->pushSpecialBlock('at-root', $s);
+ $atRoot->selector = $selector;
+ $atRoot->with = $with;
+
+ return true;
+ }
+
+ $this->seek($s);
+
if ($this->literal('@media') && $this->mediaQueryList($mediaQueryList) && $this->literal('{')) {
$media = $this->pushSpecialBlock('media', $s);
$media->queryList = $mediaQueryList[2];
@@ -1393,7 +1407,9 @@ protected function map(&$out)
{
$s = $this->seek();
- $this->literal('(');
+ if (! $this->literal('(')) {
+ return false;
+ }
$keys = array();
$values = array();
diff --git a/tests/inputs/at_root.scss b/tests/inputs/at_root.scss
new file mode 100644
index 00000000..aa4f6584
--- /dev/null
+++ b/tests/inputs/at_root.scss
@@ -0,0 +1,24 @@
+.first {
+ color: red;
+}
+body{
+.second {
+ color: white;
+
+ @at-root {
+ .nested1 {
+ color: blue;
+ @at-root {
+ .nested2 {
+ color: yellow;
+ }
+ }
+ color: orange;
+ }
+ }
+ color: black;
+}
+}
+.third {
+ color: green;
+}
diff --git a/tests/outputs/at_root.css b/tests/outputs/at_root.css
new file mode 100644
index 00000000..86edb772
--- /dev/null
+++ b/tests/outputs/at_root.css
@@ -0,0 +1,15 @@
+.first {
+ color: red; }
+
+body .second {
+ color: white;
+ color: black; }
+
+ .nested1 {
+ color: blue;
+ color: orange; }
+ .nested2 {
+ color: yellow; }
+
+.third {
+ color: green; }
diff --git a/tests/outputs_numbered/at_root.css b/tests/outputs_numbered/at_root.css
new file mode 100644
index 00000000..873218f2
--- /dev/null
+++ b/tests/outputs_numbered/at_root.css
@@ -0,0 +1,19 @@
+/* line 1, inputs/at_root.scss */
+.first {
+ color: red; }
+/* line 4, inputs/at_root.scss */
+/* line 5, inputs/at_root.scss */
+ body .second {
+ color: white;
+ color: black; }
+
+/* line 9, inputs/at_root.scss */
+.nested1 {
+color: blue;
+color: orange; }
+/* line 12, inputs/at_root.scss */
+.nested2 {
+color: yellow; }
+/* line 22, inputs/at_root.scss */
+.third {
+ color: green; }
From 9992440b533b97e9d6b22f78bfb0d9c79f8cd70c Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Fri, 25 Sep 2015 03:58:17 -0400
Subject: [PATCH 100/534] internals: formatter indentStr()
---
src/Compiler.php | 3 ---
src/Formatter.php | 6 ++----
src/Formatter/Compact.php | 2 +-
src/Formatter/Compressed.php | 8 --------
src/Formatter/Crunched.php | 8 --------
src/Formatter/Expanded.php | 8 ++++++++
src/Formatter/Nested.php | 21 +++++++++++++++++++--
7 files changed, 30 insertions(+), 26 deletions(-)
diff --git a/src/Compiler.php b/src/Compiler.php
index e578b8fa..5dca4476 100644
--- a/src/Compiler.php
+++ b/src/Compiler.php
@@ -629,7 +629,6 @@ protected function compileNestedBlock($block, $selectors)
protected function compileBlock($block)
{
$env = $this->pushEnv($block);
-
$env->selectors = $this->evalSelectors($block->selectors);
$out = $this->makeOutputBlock(null);
@@ -1377,13 +1376,11 @@ protected function compileChild($child, $out)
}
$this->storeEnv = $content->scope;
- //$this->pushEnv();
foreach ($content->children as $child) {
$this->compileChild($child, $out);
}
- //$this->popEnv();
$this->storeEnv = null;
break;
diff --git a/src/Formatter.php b/src/Formatter.php
index c341f1d7..90f79e90 100644
--- a/src/Formatter.php
+++ b/src/Formatter.php
@@ -58,13 +58,11 @@ abstract public function __construct();
/**
* Return indentation (whitespace)
*
- * @param integer $n
- *
* @return string
*/
- protected function indentStr($n = 0)
+ protected function indentStr()
{
- return str_repeat($this->indentChar, max($this->indentLevel + $n, 0));
+ return '';
}
/**
diff --git a/src/Formatter/Compact.php b/src/Formatter/Compact.php
index 29874c96..eda6ec24 100644
--- a/src/Formatter/Compact.php
+++ b/src/Formatter/Compact.php
@@ -37,7 +37,7 @@ public function __construct()
/**
* {@inheritdoc}
*/
- public function indentStr($n = 0)
+ public function indentStr()
{
return ' ';
}
diff --git a/src/Formatter/Compressed.php b/src/Formatter/Compressed.php
index 2ab2eaae..21def797 100644
--- a/src/Formatter/Compressed.php
+++ b/src/Formatter/Compressed.php
@@ -34,14 +34,6 @@ public function __construct()
$this->assignSeparator = ':';
}
- /**
- * {@inheritdoc}
- */
- public function indentStr($n = 0)
- {
- return '';
- }
-
/**
* {@inheritdoc}
*/
diff --git a/src/Formatter/Crunched.php b/src/Formatter/Crunched.php
index ad52c464..1e930b4f 100644
--- a/src/Formatter/Crunched.php
+++ b/src/Formatter/Crunched.php
@@ -34,14 +34,6 @@ public function __construct()
$this->assignSeparator = ':';
}
- /**
- * {@inheritdoc}
- */
- public function indentStr($n = 0)
- {
- return '';
- }
-
/**
* {@inheritdoc}
*/
diff --git a/src/Formatter/Expanded.php b/src/Formatter/Expanded.php
index 89ecfffb..25e6639d 100644
--- a/src/Formatter/Expanded.php
+++ b/src/Formatter/Expanded.php
@@ -34,6 +34,14 @@ public function __construct()
$this->assignSeparator = ': ';
}
+ /**
+ * {@inheritdoc}
+ */
+ protected function indentStr()
+ {
+ return str_repeat($this->indentChar, $this->indentLevel);
+ }
+
/**
* {@inheritdoc}
*/
diff --git a/src/Formatter/Nested.php b/src/Formatter/Nested.php
index 3897419b..45866ca9 100644
--- a/src/Formatter/Nested.php
+++ b/src/Formatter/Nested.php
@@ -20,6 +20,11 @@
*/
class Nested extends Formatter
{
+ /**
+ * @var integer
+ */
+ private $depth;
+
/**
* {@inheritdoc}
*/
@@ -34,12 +39,22 @@ public function __construct()
$this->assignSeparator = ': ';
}
+ /**
+ * {@inheritdoc}
+ */
+ protected function indentStr()
+ {
+ $n = $this->depth - 1;
+
+ return str_repeat($this->indentChar, max($this->indentLevel + $n, 0));
+ }
+
/**
* {@inheritdoc}
*/
protected function blockLines($block)
{
- $inner = $this->indentStr($block->depth - 1);
+ $inner = $this->indentStr();
$glue = $this->break . $inner;
@@ -61,7 +76,7 @@ protected function blockLines($block)
*/
protected function blockSelectors($block)
{
- $inner = $this->indentStr($block->depth - 1);
+ $inner = $this->indentStr();
echo $inner
. implode($this->tagSeparator, $block->selectors)
@@ -99,6 +114,8 @@ protected function block($block)
$this->adjustAllChildren($block);
}
+ $this->depth = $block->depth;
+
if (! empty($block->selectors)) {
$this->blockSelectors($block);
From 2356983ad1234972014eed68a23b5b3c1a47b53f Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Sun, 27 Sep 2015 17:29:50 -0400
Subject: [PATCH 101/534] @at-root inline selector
---
src/Compiler.php | 14 ++++++++++++++
1 file changed, 14 insertions(+)
diff --git a/src/Compiler.php b/src/Compiler.php
index 5dca4476..def09836 100644
--- a/src/Compiler.php
+++ b/src/Compiler.php
@@ -552,6 +552,20 @@ protected function compileAtRoot($block)
$this->scope->depth = 1;
$this->scope->parent->children[] = $this->scope;
+ // wrap inline selector
+ if ($block->selector) {
+ $wrapped = (object) array(
+ 'parent' => $block,
+ 'sourcePosition' => $block->sourcePosition,
+ 'sourceParser' => $block->sourceParser,
+ 'selectors' => $block->selector,
+ 'comments' => array(),
+ 'children' => $block->children,
+ );
+
+ $block->children = array(array('block', $wrapped));
+ }
+
$this->compileChildren($block->children, $this->scope);
$this->scope = $this->scope->parent;
From ab533fd945c59001b99c183f577a94dd375abbe3 Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Sat, 3 Oct 2015 19:14:32 -0400
Subject: [PATCH 102/534] fixes #343
---
src/Compiler.php | 16 ++++++----------
1 file changed, 6 insertions(+), 10 deletions(-)
diff --git a/src/Compiler.php b/src/Compiler.php
index def09836..0413d4c4 100644
--- a/src/Compiler.php
+++ b/src/Compiler.php
@@ -2255,6 +2255,7 @@ public function compileValue($value)
// strip quotes if it's a string
$reduced = $this->reduce($exp);
+
switch ($reduced[0]) {
case 'string':
$reduced = array('keyword', $this->compileStringContent($reduced));
@@ -3835,8 +3836,7 @@ protected function libHsl($args)
return $this->toRGB($h[1], $s[1], $l[1]);
}
- protected static $libHsla = array('hue', 'saturation',
- 'lightness', 'alpha');
+ protected static $libHsla = array('hue', 'saturation', 'lightness', 'alpha');
protected function libHsla($args)
{
list($h, $s, $l, $a) = $args;
@@ -4197,11 +4197,10 @@ protected function libSetNth($args)
protected function libMapGet($args)
{
$map = $this->assertMap($args[0]);
-
$key = $this->compileStringContent($this->coerceString($args[1]));
for ($i = count($map[1]) - 1; $i >= 0; $i--) {
- if ($key === $this->compileValue($map[1][$i])) {
+ if ($key === $this->compileStringContent($this->coerceString($map[1][$i]))) {
return $map[2][$i];
}
}
@@ -4213,7 +4212,6 @@ protected function libMapGet($args)
protected function libMapKeys($args)
{
$map = $this->assertMap($args[0]);
-
$keys = $map[1];
return array('list', ',', $keys);
@@ -4223,7 +4221,6 @@ protected function libMapKeys($args)
protected function libMapValues($args)
{
$map = $this->assertMap($args[0]);
-
$values = $map[2];
return array('list', ',', $values);
@@ -4233,11 +4230,10 @@ protected function libMapValues($args)
protected function libMapRemove($args)
{
$map = $this->assertMap($args[0]);
-
$key = $this->compileStringContent($this->coerceString($args[1]));
for ($i = count($map[1]) - 1; $i >= 0; $i--) {
- if ($key === $this->compileValue($map[1][$i])) {
+ if ($key === $this->compileStringContent($this->coerceString($map[1][$i]))) {
array_splice($map[1], $i, 1);
array_splice($map[2], $i, 1);
}
@@ -4250,11 +4246,10 @@ protected function libMapRemove($args)
protected function libMapHasKey($args)
{
$map = $this->assertMap($args[0]);
-
$key = $this->compileStringContent($this->coerceString($args[1]));
for ($i = count($map[1]) - 1; $i >= 0; $i--) {
- if ($key === $this->compileValue($map[1][$i])) {
+ if ($key === $this->compileStringContent($this->coerceString($map[1][$i]))) {
return self::$true;
}
}
@@ -4331,6 +4326,7 @@ protected function libZip($args)
break 2;
}
}
+
$lists[] = $list;
}
From 5de607bc5ea7a62740be49368d62ef6c34af4ed7 Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Sat, 3 Oct 2015 20:56:34 -0400
Subject: [PATCH 103/534] not(value) === not (value)
---
src/Parser.php | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/src/Parser.php b/src/Parser.php
index 5e7370b2..d2b4b99a 100644
--- a/src/Parser.php
+++ b/src/Parser.php
@@ -1129,6 +1129,14 @@ protected function value(&$out)
$this->seek($s);
+ if ($this->literal('not', false) && $this->parenValue($inner)) {
+ $out = array('unary', 'not', $inner, $this->inParens);
+
+ return true;
+ }
+
+ $this->seek($s);
+
if ($this->literal('+') && $this->value($inner)) {
$out = array('unary', '+', $inner, $this->inParens);
From a891c167987bb7453508cf1eba0271190c49d39a Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Sat, 3 Oct 2015 22:10:02 -0400
Subject: [PATCH 104/534] fix short circuit evaluation -- it should delay
evaluation of right side
---
src/Compiler.php | 9 ++++++---
1 file changed, 6 insertions(+), 3 deletions(-)
diff --git a/src/Compiler.php b/src/Compiler.php
index 0413d4c4..880b946a 100644
--- a/src/Compiler.php
+++ b/src/Compiler.php
@@ -1512,7 +1512,10 @@ protected function reduce($value, $inExp = false)
$inExp = $inExp || $this->shouldEval($left) || $this->shouldEval($right);
$left = $this->reduce($left, true);
- $right = $this->reduce($right, true);
+
+ if ($op !== 'and' && $op !== 'or') {
+ $right = $this->reduce($right, true);
+ }
// special case: looks like css short-hand
if ($opName === 'div' && ! $inParens && ! $inExp && isset($right[2]) && $right[2] !== '') {
@@ -1900,7 +1903,7 @@ protected function opAnd($left, $right, $shouldEval)
}
if ($left !== self::$false) {
- return $right;
+ return $this->reduce($right, true);
}
return $left;
@@ -1925,7 +1928,7 @@ protected function opOr($left, $right, $shouldEval)
return $left;
}
- return $right;
+ return $this->reduce($right, true);
}
/**
From 4ed0142ff2ddabe1be2c2305dd21b8076a3bd746 Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Sun, 4 Oct 2015 10:22:03 -0400
Subject: [PATCH 105/534] Bump version to 0.3.2
---
src/Version.php | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/Version.php b/src/Version.php
index efd45ca0..fffc751b 100644
--- a/src/Version.php
+++ b/src/Version.php
@@ -18,5 +18,5 @@
*/
class Version
{
- const VERSION = 'v0.3.1';
+ const VERSION = 'v0.3.2';
}
From 93f4d16398d73538a37a172c738440da2ff61cc2 Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Sun, 4 Oct 2015 10:41:29 -0400
Subject: [PATCH 106/534] fixes #345
---
src/Compiler.php | 18 +++++++++++-------
1 file changed, 11 insertions(+), 7 deletions(-)
diff --git a/src/Compiler.php b/src/Compiler.php
index 880b946a..8b4de85c 100644
--- a/src/Compiler.php
+++ b/src/Compiler.php
@@ -2964,8 +2964,10 @@ protected function callBuiltin($name, $args, &$returnValue)
// see if we can find a user function
$fn = $this->userFunctions[$name];
- foreach ($args as &$val) {
- $val = $this->reduce($val[1], true);
+ if ($name !== 'if') {
+ foreach ($args as &$val) {
+ $val = $this->reduce($val[1], true);
+ }
}
$returnValue = call_user_func($fn, $args, $this);
@@ -2978,8 +2980,10 @@ protected function callBuiltin($name, $args, &$returnValue)
$prototype = isset(self::$$libName) ? self::$$libName : null;
$sorted = $this->sortArgs($prototype, $args);
- foreach ($sorted as &$val) {
- $val = $this->reduce($val, true);
+ if ($name !== 'if') {
+ foreach ($sorted as &$val) {
+ $val = $this->reduce($val, true);
+ }
}
$returnValue = call_user_func($f, $sorted, $this);
@@ -3575,11 +3579,11 @@ protected function libIf($args)
{
list($cond, $t, $f) = $args;
- if (! $this->isTruthy($cond)) {
- return $f;
+ if (! $this->isTruthy($this->reduce($cond, true))) {
+ return $this->reduce($f, true);
}
- return $t;
+ return $this->reduce($t, true);
}
protected static $libIndex = array('list', 'value');
From 14d7295ac3defadbf5b8aa767ed132867bf83108 Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Sun, 4 Oct 2015 10:45:13 -0400
Subject: [PATCH 107/534] add unit tests
---
tests/inputs/short_circuit.scss | 3 +++
tests/outputs/short_circuit.css | 1 +
tests/outputs_numbered/short_circuit.css | 1 +
3 files changed, 5 insertions(+)
create mode 100644 tests/inputs/short_circuit.scss
create mode 100644 tests/outputs/short_circuit.css
create mode 100644 tests/outputs_numbered/short_circuit.css
diff --git a/tests/inputs/short_circuit.scss b/tests/inputs/short_circuit.scss
new file mode 100644
index 00000000..84f317a7
--- /dev/null
+++ b/tests/inputs/short_circuit.scss
@@ -0,0 +1,3 @@
+$test: if(true, 1, $undefined);
+$test: false and $undefined;
+$test: true or $undefined;
diff --git a/tests/outputs/short_circuit.css b/tests/outputs/short_circuit.css
new file mode 100644
index 00000000..8b137891
--- /dev/null
+++ b/tests/outputs/short_circuit.css
@@ -0,0 +1 @@
+
diff --git a/tests/outputs_numbered/short_circuit.css b/tests/outputs_numbered/short_circuit.css
new file mode 100644
index 00000000..8b137891
--- /dev/null
+++ b/tests/outputs_numbered/short_circuit.css
@@ -0,0 +1 @@
+
From c0ffbc6d5b65772ee1c101e8b2e7ae1716630490 Mon Sep 17 00:00:00 2001
From: hitok
Date: Sun, 4 Oct 2015 10:55:16 -0400
Subject: [PATCH 108/534] fixes #344
---
src/Compiler.php | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/Compiler.php b/src/Compiler.php
index 8b4de85c..1176470f 100644
--- a/src/Compiler.php
+++ b/src/Compiler.php
@@ -487,7 +487,7 @@ protected function compileMedia($media)
foreach ($media->children as $child) {
$type = $child[0];
- if ($type !== 'block' && $type !== 'media' && $type !== 'directive') {
+ if ($type !== 'block' && $type !== 'media' && $type !== 'directive' && $type !== 'import') {
$needsWrap = true;
break;
}
From 27b70ca5e3cc73014d4cae859a52f1567a461266 Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Sun, 4 Oct 2015 12:22:47 -0400
Subject: [PATCH 109/534] #302 - partial call() support; doesn't support kwargs
yet
---
src/Compiler.php | 12 ++++++++++--
tests/inputs/builtins.scss | 6 ++++++
tests/outputs/builtins.css | 4 ++++
tests/outputs_numbered/builtins.css | 4 ++++
4 files changed, 24 insertions(+), 2 deletions(-)
diff --git a/src/Compiler.php b/src/Compiler.php
index 1176470f..b783c4f1 100644
--- a/src/Compiler.php
+++ b/src/Compiler.php
@@ -2964,7 +2964,7 @@ protected function callBuiltin($name, $args, &$returnValue)
// see if we can find a user function
$fn = $this->userFunctions[$name];
- if ($name !== 'if') {
+ if ($name !== 'if' && $name !== 'call') {
foreach ($args as &$val) {
$val = $this->reduce($val[1], true);
}
@@ -2980,7 +2980,7 @@ protected function callBuiltin($name, $args, &$returnValue)
$prototype = isset(self::$$libName) ? self::$$libName : null;
$sorted = $this->sortArgs($prototype, $args);
- if ($name !== 'if') {
+ if ($name !== 'if' && $name !== 'call') {
foreach ($sorted as &$val) {
$val = $this->reduce($val, true);
}
@@ -3574,6 +3574,14 @@ public function toRGB($hue, $saturation, $lightness)
// Built in functions
+ //protected static $libCall = array('name', 'args...');
+ protected function libCall($args)
+ {
+ $name = $this->compileStringContent($this->coerceString($this->reduce(array_shift($args), true)));
+
+ return $this->reduce(array('fncall', $name, array_map(function ($a) { return array(null, $a); }, $args)));
+ }
+
protected static $libIf = array('condition', 'if-true', 'if-false');
protected function libIf($args)
{
diff --git a/tests/inputs/builtins.scss b/tests/inputs/builtins.scss
index 37487a08..1b8bffb4 100644
--- a/tests/inputs/builtins.scss
+++ b/tests/inputs/builtins.scss
@@ -185,3 +185,9 @@ $a-false-value: false;
c: variable-exists(nonexistent);
}
+$fn: nth;
+div.call-tests {
+ a: call(rgb, 10, 100, 255);
+ //b: call(scale-color, #0a64ff, $lightness: -10%);
+ c: call($fn, (a b c), 2);
+}
diff --git a/tests/outputs/builtins.css b/tests/outputs/builtins.css
index 84c6de27..7778777e 100644
--- a/tests/outputs/builtins.css
+++ b/tests/outputs/builtins.css
@@ -133,3 +133,7 @@
a: true;
b: true;
c: false; }
+
+div.call-tests {
+ a: #0a64ff;
+ c: b; }
diff --git a/tests/outputs_numbered/builtins.css b/tests/outputs_numbered/builtins.css
index 954e77d4..b62b42c6 100644
--- a/tests/outputs_numbered/builtins.css
+++ b/tests/outputs_numbered/builtins.css
@@ -134,3 +134,7 @@
a: true;
b: true;
c: false; }
+/* line 189, inputs/builtins.scss */
+div.call-tests {
+ a: #0a64ff;
+ c: b; }
From 033dd027dfc8e1905ce782a687160d66d3bd65ee Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Sun, 4 Oct 2015 12:25:29 -0400
Subject: [PATCH 110/534] phpcs
---
src/Compiler.php | 13 ++++++++++++-
1 file changed, 12 insertions(+), 1 deletion(-)
diff --git a/src/Compiler.php b/src/Compiler.php
index b783c4f1..a916f85c 100644
--- a/src/Compiler.php
+++ b/src/Compiler.php
@@ -3579,7 +3579,18 @@ protected function libCall($args)
{
$name = $this->compileStringContent($this->coerceString($this->reduce(array_shift($args), true)));
- return $this->reduce(array('fncall', $name, array_map(function ($a) { return array(null, $a); }, $args)));
+ return $this->reduce(
+ array(
+ 'fncall',
+ $name,
+ array_map(
+ function ($a) {
+ return array(null, $a);
+ },
+ $args
+ )
+ )
+ );
}
protected static $libIf = array('condition', 'if-true', 'if-false');
From 2c5b40e9787879e5c50887e214c0ab5ffa53043c Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Mon, 5 Oct 2015 14:05:53 -0400
Subject: [PATCH 111/534] Compiler: coerceList(map) fixes #343
---
src/Compiler.php | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/Compiler.php b/src/Compiler.php
index a916f85c..8cf5fac0 100644
--- a/src/Compiler.php
+++ b/src/Compiler.php
@@ -3272,7 +3272,7 @@ protected function coerceList($item, $delim = ',')
$key = $keys[$i];
$value = $values[$i];
- $list[] = array('list', '', array(array('keyword', $this->compileValue($key)), $value));
+ $list[] = array('list', '', array(array('keyword', $this->compileStringContent($this->coerceString($key))), $value));
}
return array('list', ',', $list);
From d8ee4e9b77e55b891ec975a37c487c890f8c482e Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Mon, 5 Oct 2015 14:08:27 -0400
Subject: [PATCH 112/534] update unit tests
---
src/Compiler.php | 6 +++++-
tests/inputs/map.scss | 8 ++++++++
tests/outputs/map.css | 2 ++
tests/outputs_numbered/map.css | 3 +++
4 files changed, 18 insertions(+), 1 deletion(-)
diff --git a/src/Compiler.php b/src/Compiler.php
index 8cf5fac0..43a30bb4 100644
--- a/src/Compiler.php
+++ b/src/Compiler.php
@@ -3272,7 +3272,11 @@ protected function coerceList($item, $delim = ',')
$key = $keys[$i];
$value = $values[$i];
- $list[] = array('list', '', array(array('keyword', $this->compileStringContent($this->coerceString($key))), $value));
+ $list[] = array(
+ 'list',
+ '',
+ array(array('keyword', $this->compileStringContent($this->coerceString($key))), $value)
+ );
}
return array('list', ',', $list);
diff --git a/tests/inputs/map.scss b/tests/inputs/map.scss
index 8284151f..ecaf29d1 100644
--- a/tests/inputs/map.scss
+++ b/tests/inputs/map.scss
@@ -24,3 +24,11 @@ div {
foo: nth($map, 1);
bar: nth(nth($map, 1), 1);
}
+
+$color: ("black" : #000000);
+
+@each $color_name, $color_value in $color {
+ .#{$color_name} {
+ background-color: $color_value !important;
+ }
+}
diff --git a/tests/outputs/map.css b/tests/outputs/map.css
index 5beeeef5..5dad9b77 100644
--- a/tests/outputs/map.css
+++ b/tests/outputs/map.css
@@ -10,3 +10,5 @@ div {
div {
foo: color black;
bar: color; }
+ .black {
+ background-color: #000 !important; }
diff --git a/tests/outputs_numbered/map.css b/tests/outputs_numbered/map.css
index 48658216..81366a16 100644
--- a/tests/outputs_numbered/map.css
+++ b/tests/outputs_numbered/map.css
@@ -11,3 +11,6 @@ div {
div {
foo: color black;
bar: color; }
+/* line 31, inputs/map.scss */
+.black {
+ background-color: #000 !important; }
From 73c9f33ad92f68e0472e245c6adcc28ad8bc179c Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Mon, 5 Oct 2015 14:45:32 -0400
Subject: [PATCH 113/534] ignore /frameworks/ folder
---
.gitignore | 1 +
1 file changed, 1 insertion(+)
diff --git a/.gitignore b/.gitignore
index 4ffba003..dbff826d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -7,3 +7,4 @@ pscss.phar
/sass/
/compass/
/vendor/
+/frameworks/
From ce2607c66985a38cece865e91a1962cb0ccbac56 Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Mon, 5 Oct 2015 20:18:35 -0400
Subject: [PATCH 114/534] add unit tests for #346
---
tests/inputs/map.scss | 27 ++++++++++++++++++++++++---
tests/outputs/map.css | 6 ++++++
tests/outputs_numbered/map.css | 6 ++++++
3 files changed, 36 insertions(+), 3 deletions(-)
diff --git a/tests/inputs/map.scss b/tests/inputs/map.scss
index ecaf29d1..0fb6be19 100644
--- a/tests/inputs/map.scss
+++ b/tests/inputs/map.scss
@@ -28,7 +28,28 @@ div {
$color: ("black" : #000000);
@each $color_name, $color_value in $color {
- .#{$color_name} {
- background-color: $color_value !important;
- }
+ .#{$color_name} {
+ background-color: $color_value !important;
+ }
+}
+
+$args: ('a': 1, 'b': 2);
+
+@mixin output($args) {
+ @each $k, $v in $args {
+ #{$k}: $v;
+ }
+}
+
+@mixin output-varargs(
+ $a,
+ $b
+) {
+ color: $a;
+ background-color: $b;
+}
+
+div {
+ @include output($args);
+ @include output-varargs($args...);
}
diff --git a/tests/outputs/map.css b/tests/outputs/map.css
index 5dad9b77..9c38094a 100644
--- a/tests/outputs/map.css
+++ b/tests/outputs/map.css
@@ -12,3 +12,9 @@ div {
bar: color; }
.black {
background-color: #000 !important; }
+
+div {
+ a: 1;
+ b: 2;
+ color: 1;
+ background-color: 2; }
diff --git a/tests/outputs_numbered/map.css b/tests/outputs_numbered/map.css
index 81366a16..16de52b9 100644
--- a/tests/outputs_numbered/map.css
+++ b/tests/outputs_numbered/map.css
@@ -14,3 +14,9 @@ div {
/* line 31, inputs/map.scss */
.black {
background-color: #000 !important; }
+/* line 52, inputs/map.scss */
+div {
+ a: 1;
+ b: 2;
+ color: 1;
+ background-color: 2; }
From 8e9d689603c6ec31c0e8074d81bf9a6cc2425c3c Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Mon, 5 Oct 2015 20:32:18 -0400
Subject: [PATCH 115/534] fixes #346
---
src/Compiler.php | 11 +++++++++++
src/Parser.php | 1 +
2 files changed, 12 insertions(+)
diff --git a/src/Compiler.php b/src/Compiler.php
index 43a30bb4..d2901119 100644
--- a/src/Compiler.php
+++ b/src/Compiler.php
@@ -3126,6 +3126,17 @@ protected function applyArguments($argDef, $argValues)
if ($val[0] === 'list') {
foreach ($val[2] as $name => $item) {
+ if (! is_numeric($name)) {
+ $keywordArgs[$name] = $item;
+ } else {
+ $remaining[] = $item;
+ }
+ }
+ } elseif ($val[0] === 'map') {
+ foreach ($val[1] as $i => $name) {
+ $name = $this->compileStringContent($this->coerceString($name));
+ $item = $val[2][$i];
+
if (! is_numeric($name)) {
$keywordArgs[$name] = $item;
} else {
diff --git a/src/Parser.php b/src/Parser.php
index d2b4b99a..5312a64d 100644
--- a/src/Parser.php
+++ b/src/Parser.php
@@ -668,6 +668,7 @@ protected function literal($what, $eatWhitespace = null)
return true;
}
+
// goes below...
} else {
return false;
From 12f27ee83a3493d9e235e15a0682d7c26d00a877 Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Mon, 5 Oct 2015 21:31:15 -0400
Subject: [PATCH 116/534] fixes #347
---
src/Compiler.php | 14 ++++++++++++--
tests/inputs/list.scss | 1 +
tests/outputs/list.css | 3 ++-
tests/outputs_numbered/list.css | 5 +++--
4 files changed, 18 insertions(+), 5 deletions(-)
diff --git a/src/Compiler.php b/src/Compiler.php
index d2901119..a8b6b2c3 100644
--- a/src/Compiler.php
+++ b/src/Compiler.php
@@ -2212,6 +2212,10 @@ public function compileValue($value)
list(, $delim, $items) = $value;
+ if ($delim !== ' ') {
+ $delim .= ' ';
+ }
+
$filtered = array();
foreach ($items as $item) {
@@ -2222,7 +2226,7 @@ public function compileValue($value)
$filtered[] = $this->compileValue($item);
}
- return implode("$delim ", $filtered);
+ return implode("$delim", $filtered);
case 'map':
$keys = $value[1];
@@ -4214,7 +4218,13 @@ protected function libListSeparator($args)
protected function libNth($args)
{
$list = $this->coerceList($args[0]);
- $n = $this->assertNumber($args[1]) - 1;
+ $n = $this->assertNumber($args[1]);
+
+ if ($n > 0) {
+ $n--;
+ } elseif ($n < 0) {
+ $n += count($list[2]);
+ }
return isset($list[2][$n]) ? $list[2][$n] : self::$defaultValue;
}
diff --git a/tests/inputs/list.scss b/tests/inputs/list.scss
index 483292d3..8d290e9f 100644
--- a/tests/inputs/list.scss
+++ b/tests/inputs/list.scss
@@ -25,6 +25,7 @@ div {
a: nth($list, 1);
b: nth($list, 2);
c: nth($list, 3);
+ d: nth($list, -1);
}
div {
diff --git a/tests/outputs/list.css b/tests/outputs/list.css
index aed03cea..7358b340 100644
--- a/tests/outputs/list.css
+++ b/tests/outputs/list.css
@@ -13,7 +13,8 @@ div {
div {
a: 10px;
b: -20px;
- c: 30px; }
+ c: 30px;
+ d: 30px; }
div {
x: space;
diff --git a/tests/outputs_numbered/list.css b/tests/outputs_numbered/list.css
index 90cc8576..d80d6150 100644
--- a/tests/outputs_numbered/list.css
+++ b/tests/outputs_numbered/list.css
@@ -14,8 +14,9 @@ div {
div {
a: 10px;
b: -20px;
- c: 30px; }
-/* line 30, inputs/list.scss */
+ c: 30px;
+ d: 30px; }
+/* line 31, inputs/list.scss */
div {
x: space;
y: comma;
From a763e28ed14cd5d5478d754cece0b9ad726b9661 Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Mon, 5 Oct 2015 21:34:27 -0400
Subject: [PATCH 117/534] refs #347 - fixes negative index with set-nth() too
---
src/Compiler.php | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/src/Compiler.php b/src/Compiler.php
index a8b6b2c3..68ef704f 100644
--- a/src/Compiler.php
+++ b/src/Compiler.php
@@ -4233,7 +4233,13 @@ protected function libNth($args)
protected function libSetNth($args)
{
$list = $this->coerceList($args[0]);
- $n = $this->assertNumber($args[1]) - 1;
+ $n = $this->assertNumber($args[1]);
+
+ if ($n > 0) {
+ $n--;
+ } elseif ($n < 0) {
+ $n += count($list[2]);
+ }
if (! isset($list[2][$n])) {
$this->throwError('Invalid argument for "n"');
From d88972e42dee2a9c16368ab973d052f99c0412e0 Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Tue, 6 Oct 2015 21:03:56 -0400
Subject: [PATCH 118/534] refs #349 - nested mixin @content
---
src/Compiler.php | 24 +++++++++++-------------
1 file changed, 11 insertions(+), 13 deletions(-)
diff --git a/src/Compiler.php b/src/Compiler.php
index 68ef704f..300e1e31 100644
--- a/src/Compiler.php
+++ b/src/Compiler.php
@@ -1362,7 +1362,7 @@ protected function compileChild($child, $out)
if (isset($content)) {
$content->scope = $callingScope;
- $this->setRaw(self::$namespaces['special'] . 'content', $content);
+ $this->setRaw(self::$namespaces['special'] . 'content', $content, $this->env);
}
if (isset($mixin->args)) {
@@ -1379,13 +1379,15 @@ protected function compileChild($child, $out)
break;
case 'mixin_content':
- $content = $this->get(self::$namespaces['special'] . 'content', false);
+ $content = $this->get(self::$namespaces['special'] . 'content', false, $this->env);
if (! $content) {
$this->throwError('Expected @content inside of mixin');
}
- if (! isset($content->children)) {
+ if (! isset($content->children) ||
+ $this->storeEnv === $content->scope
+ ) {
break;
}
@@ -2536,6 +2538,10 @@ protected function set($name, $value, $shadow = false, $env = null)
{
$name = $this->normalizeName($name);
+ if (! isset($env)) {
+ $env = $this->getStoreEnv();
+ }
+
if ($shadow) {
$this->setRaw($name, $value, $env);
} else {
@@ -2550,12 +2556,8 @@ protected function set($name, $value, $shadow = false, $env = null)
* @param mixed $value
* @param \stdClass $env
*/
- protected function setExisting($name, $value, $env = null)
+ protected function setExisting($name, $value, $env)
{
- if (! isset($env)) {
- $env = $this->getStoreEnv();
- }
-
$storeEnv = $env;
$hasNamespace = $name[0] === '^' || $name[0] === '@' || $name[0] === '%';
@@ -2588,12 +2590,8 @@ protected function setExisting($name, $value, $env = null)
* @param mixed $value
* @param \stdClass $env
*/
- protected function setRaw($name, $value, $env = null)
+ protected function setRaw($name, $value, $env)
{
- if (! isset($env)) {
- $env = $this->getStoreEnv();
- }
-
$env->store[$name] = $value;
}
From 00088be53b3a4917b7d9398be65facbffec521a0 Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Fri, 9 Oct 2015 00:27:56 -0400
Subject: [PATCH 119/534] add tests
---
src/Compiler.php | 8 +++-----
tests/inputs/content.scss | 20 ++++++++++++++++++++
tests/outputs/content.css | 3 +++
tests/outputs_numbered/content.css | 5 +++++
4 files changed, 31 insertions(+), 5 deletions(-)
diff --git a/src/Compiler.php b/src/Compiler.php
index 300e1e31..ca6df8fb 100644
--- a/src/Compiler.php
+++ b/src/Compiler.php
@@ -1362,7 +1362,7 @@ protected function compileChild($child, $out)
if (isset($content)) {
$content->scope = $callingScope;
- $this->setRaw(self::$namespaces['special'] . 'content', $content, $this->env);
+ $this->setRaw(self::$namespaces['special'] . 'content', $content, $this->getStoreEnv());
}
if (isset($mixin->args)) {
@@ -1379,15 +1379,13 @@ protected function compileChild($child, $out)
break;
case 'mixin_content':
- $content = $this->get(self::$namespaces['special'] . 'content', false, $this->env);
+ $content = $this->get(self::$namespaces['special'] . 'content', false, $this->getStoreEnv());
if (! $content) {
$this->throwError('Expected @content inside of mixin');
}
- if (! isset($content->children) ||
- $this->storeEnv === $content->scope
- ) {
+ if (! isset($content->children)) {
break;
}
diff --git a/tests/inputs/content.scss b/tests/inputs/content.scss
index 55ca04e8..a56acae3 100644
--- a/tests/inputs/content.scss
+++ b/tests/inputs/content.scss
@@ -59,3 +59,23 @@ $color: white;
$i: $i + 1;
}
}
+
+@mixin nested {
+ * body {
+ @content;
+ }
+}
+
+@mixin top($args) {
+ * html {
+ @include nested($args) {
+ @content;
+ }
+ }
+}
+
+@include top('hello' 'world') {
+ #logo {
+ background-image: url(/logo.gif);
+ }
+}
diff --git a/tests/outputs/content.css b/tests/outputs/content.css
index 6657a216..89a1ad9e 100644
--- a/tests/outputs/content.css
+++ b/tests/outputs/content.css
@@ -27,3 +27,6 @@
width: 100%; }
.grid-2 {
width: 100%; } }
+
+* html * body #logo {
+ background-image: url(/logo.gif); }
diff --git a/tests/outputs_numbered/content.css b/tests/outputs_numbered/content.css
index 016b8946..7948df35 100644
--- a/tests/outputs_numbered/content.css
+++ b/tests/outputs_numbered/content.css
@@ -34,3 +34,8 @@
/* line 58, inputs/content.scss */
.grid-2 {
width: 100%; } }
+/* line 70, inputs/content.scss */
+/* line 64, inputs/content.scss */
+ /* line 78, inputs/content.scss */
+ * html * body #logo {
+ background-image: url(/logo.gif); }
From f30b7221bf7d38ab64c306d85c16a51f19e5bbf6 Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Tue, 13 Oct 2015 13:31:57 -0400
Subject: [PATCH 120/534] partial revert 00088be5; fixes #350
---
src/Server.php | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/Server.php b/src/Server.php
index 5bd9bef0..d85a9190 100644
--- a/src/Server.php
+++ b/src/Server.php
@@ -139,7 +139,7 @@ protected function needsCompile($in, $out, &$etag)
$metadata = unserialize(file_get_contents($metadataName));
foreach ($metadata['imports'] as $import => $importMtime) {
- if ($importMtime > $mtime) {
+ if (filemtime($import) > $mtime) {
return true;
}
}
From e5c40d02d9c5d287337e9ca316c76725deaf1a63 Mon Sep 17 00:00:00 2001
From: jk
Date: Tue, 13 Oct 2015 22:39:39 +0200
Subject: [PATCH 121/534] quick check to needsCompile for changed
registeredVars with a crc32 hash
---
src/Compiler.php | 12 ++++++++++++
src/Server.php | 6 ++++++
2 files changed, 18 insertions(+)
diff --git a/src/Compiler.php b/src/Compiler.php
index ca6df8fb..d14e0875 100644
--- a/src/Compiler.php
+++ b/src/Compiler.php
@@ -2701,6 +2701,18 @@ public function unsetVariable($name)
unset($this->registeredVars[$name]);
}
+ /**
+ * Returns list of variables
+ *
+ * @api
+ *
+ * @return array
+ */
+ public function getVariables()
+ {
+ return $this->registeredVars;
+ }
+
/**
* Adds to list of parsed files
*
diff --git a/src/Server.php b/src/Server.php
index d85a9190..6b2a7003 100644
--- a/src/Server.php
+++ b/src/Server.php
@@ -143,6 +143,11 @@ protected function needsCompile($in, $out, &$etag)
return true;
}
}
+
+ $metaVars = crc32(serialize($this->scss->getVariables()));
+ if ($metaVars!=$metadata['vars']) {
+ return true;
+ }
$etag = $metadata['etag'];
@@ -213,6 +218,7 @@ protected function compile($in, $out)
serialize(array(
'etag' => $etag,
'imports' => $this->scss->getParsedFiles(),
+ 'vars' => crc32(serialize($this->scss->getVariables())),
))
);
From fed68815b1b6e7d2c7cb056303333c12f7940eaa Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Wed, 14 Oct 2015 13:11:34 -0400
Subject: [PATCH 122/534] refs #333 - phpcs
---
Makefile | 5 ++++-
src/Compiler.php | 2 +-
src/Server.php | 7 ++++---
3 files changed, 9 insertions(+), 5 deletions(-)
diff --git a/Makefile b/Makefile
index c608f8e1..0d64cb3c 100644
--- a/Makefile
+++ b/Makefile
@@ -1,5 +1,8 @@
-test:
+tests:
vendor/bin/phpunit --colors tests
+standard:
+ vendor/bin/phpcs --standard=PSR2 bin src tests *.php
+
phar:
php -dphar.readonly=0 vendor/bin/box build -v
diff --git a/src/Compiler.php b/src/Compiler.php
index d14e0875..6ef519b0 100644
--- a/src/Compiler.php
+++ b/src/Compiler.php
@@ -1379,7 +1379,7 @@ protected function compileChild($child, $out)
break;
case 'mixin_content':
- $content = $this->get(self::$namespaces['special'] . 'content', false, $this->getStoreEnv());
+ $content = $this->get(self::$namespaces['special'] . 'content', false, $this->getStoreEnv());
if (! $content) {
$this->throwError('Expected @content inside of mixin');
diff --git a/src/Server.php b/src/Server.php
index 6b2a7003..ff0d7285 100644
--- a/src/Server.php
+++ b/src/Server.php
@@ -143,9 +143,10 @@ protected function needsCompile($in, $out, &$etag)
return true;
}
}
-
+
$metaVars = crc32(serialize($this->scss->getVariables()));
- if ($metaVars!=$metadata['vars']) {
+
+ if ($metaVars !== $metadata['vars']) {
return true;
}
@@ -218,7 +219,7 @@ protected function compile($in, $out)
serialize(array(
'etag' => $etag,
'imports' => $this->scss->getParsedFiles(),
- 'vars' => crc32(serialize($this->scss->getVariables())),
+ 'vars' => crc32(serialize($this->scss->getVariables())),
))
);
From 408e75e82135ac600ff7a203ebcfec50d314800e Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Wed, 14 Oct 2015 13:17:21 -0400
Subject: [PATCH 123/534] compat tests
---
Makefile | 3 +++
1 file changed, 3 insertions(+)
diff --git a/Makefile b/Makefile
index 0d64cb3c..d08ee190 100644
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,9 @@
tests:
vendor/bin/phpunit --colors tests
+compat:
+ TEST_SCSS_COMPAT=1 vendor/bin/phpunit --colors tests | tail -2
+
standard:
vendor/bin/phpcs --standard=PSR2 bin src tests *.php
From fbf5864004eb188571a7f78db65b921175a307e1 Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Wed, 14 Oct 2015 15:13:05 -0400
Subject: [PATCH 124/534] add .editorconfig (per #353)
---
.editorconfig | 14 ++++++++++++++
1 file changed, 14 insertions(+)
create mode 100644 .editorconfig
diff --git a/.editorconfig b/.editorconfig
new file mode 100644
index 00000000..31dd6aa4
--- /dev/null
+++ b/.editorconfig
@@ -0,0 +1,14 @@
+root = true
+
+[*]
+end_of_line = lf
+insert_final_newline = true
+trim_trailing_whitespace = true
+charset = utf-8
+
+[Makefile]
+indent_style = tab
+
+[*.php]
+indent_style = space
+indent_size = 4
From ef676cd8b6c83c2acdda43bd5701d776f6f0fea7 Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Fri, 16 Oct 2015 17:03:27 -0400
Subject: [PATCH 125/534] Compiler: addFeature(); fixes #342
---
src/Compiler.php | 30 ++++++++++++++++++++++--------
1 file changed, 22 insertions(+), 8 deletions(-)
diff --git a/src/Compiler.php b/src/Compiler.php
index 6ef519b0..c1eb83e4 100644
--- a/src/Compiler.php
+++ b/src/Compiler.php
@@ -109,6 +109,12 @@ class Compiler
protected $importCache = array();
protected $userFunctions = array();
protected $registeredVars = array();
+ protected $features = array(
+ 'extend-selector-pseudoclass' => false,
+ 'at-error' => true,
+ 'units-level-3' => false,
+ 'global-variable-shadowing' => false,
+ );
protected $numberPrecision = 5;
protected $lineNumberStyle = null;
@@ -2826,6 +2832,18 @@ public function unregisterFunction($name)
unset($this->userFunctions[$this->normalizeName($name)]);
}
+ /**
+ * Add feature
+ *
+ * @api
+ *
+ * @param string $name
+ */
+ public function addFeature($name)
+ {
+ $this->features[$name] = true;
+ }
+
/**
* Import file
*
@@ -4545,14 +4563,10 @@ protected function libToUpperCase($args)
protected static $libFeatureExists = array('feature');
protected function libFeatureExists($args)
{
- /*
- * The following features not not (yet) supported:
- * - global-variable-shadowing
- * - extend-selector-pseudoclass
- * - units-level-3
- * - at-error
- */
- return self::$false;
+ $string = $this->coerceString($args[0]);
+ $name = $this->compileStringContent($string);
+
+ return $this->toBool(array_key_exists($name, $this->feature) ? $this->features[$name] : false);
}
protected static $libFunctionExists = array('name');
From 16bd233cfa821fbbb972892ad1815d62d9d44eb4 Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Fri, 16 Oct 2015 17:14:33 -0400
Subject: [PATCH 126/534] Server: handle more file timestamp edge cases
---
src/Server.php | 10 ++++------
1 file changed, 4 insertions(+), 6 deletions(-)
diff --git a/src/Server.php b/src/Server.php
index ff0d7285..9095e357 100644
--- a/src/Server.php
+++ b/src/Server.php
@@ -129,17 +129,15 @@ protected function needsCompile($in, $out, &$etag)
$mtime = filemtime($out);
- if (filemtime($in) > $mtime) {
- return true;
- }
-
$metadataName = $this->metadataName($out);
if (is_readable($metadataName)) {
$metadata = unserialize(file_get_contents($metadataName));
- foreach ($metadata['imports'] as $import => $importMtime) {
- if (filemtime($import) > $mtime) {
+ foreach ($metadata['imports'] as $import => $originalMtime) {
+ $currentMtime = filemtime($import);
+
+ if ($currentMtime !== $originalMtime || $currentMtime > $mtime) {
return true;
}
}
From 6252bedccc3d1c46e4b7075d3512ec4eaa2a9fc0 Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Fri, 16 Oct 2015 18:14:52 -0400
Subject: [PATCH 127/534] phpcs
---
src/Compiler.php | 1 +
1 file changed, 1 insertion(+)
diff --git a/src/Compiler.php b/src/Compiler.php
index c1eb83e4..7a3ff57b 100644
--- a/src/Compiler.php
+++ b/src/Compiler.php
@@ -2440,6 +2440,7 @@ protected function multiplyMedia($env, $childQueries = null)
}
$parentQueries = $env->block->queryList;
+
if ($childQueries === null) {
$childQueries = $parentQueries;
} else {
From c968e998869b285a671dcbc5c27682fed0040bd5 Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Wed, 21 Oct 2015 12:44:18 -0400
Subject: [PATCH 128/534] ignore .editorconfig in git archives
---
.gitattributes | 1 +
1 file changed, 1 insertion(+)
diff --git a/.gitattributes b/.gitattributes
index a116ff23..73d1a258 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -1,4 +1,5 @@
Makefile export-ignore
+.editorconfig export-ignore
.gitattributes export-ignore
.gitignore export-ignore
.travis.yml export-ignore
From 3301bc53f51d449e25fdf904a3b4939f33a5a911 Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Wed, 21 Oct 2015 16:14:32 -0400
Subject: [PATCH 129/534] declare rootEnv and rootBlock; rename features to
registeredFeatures
---
src/Compiler.php | 11 +++++++----
1 file changed, 7 insertions(+), 4 deletions(-)
diff --git a/src/Compiler.php b/src/Compiler.php
index 7a3ff57b..f4765e79 100644
--- a/src/Compiler.php
+++ b/src/Compiler.php
@@ -109,7 +109,7 @@ class Compiler
protected $importCache = array();
protected $userFunctions = array();
protected $registeredVars = array();
- protected $features = array(
+ protected $registeredFeatures = array(
'extend-selector-pseudoclass' => false,
'at-error' => true,
'units-level-3' => false,
@@ -121,6 +121,9 @@ class Compiler
protected $formatter = 'Leafo\ScssPhp\Formatter\Nested';
+ protected $rootEnv;
+ protected $rootBlock;
+
private $indentLevel;
private $commentsSeen;
private $extends;
@@ -252,7 +255,7 @@ protected function makeOutputBlock($type, $selectors = null)
*/
protected function compileRoot($rootBlock)
{
- $this->scope = $this->makeOutputBlock('root');
+ $this->rootBlock = $this->scope = $this->makeOutputBlock('root');
$this->compileChildren($rootBlock->children, $this->scope);
$this->flattenSelectors($this->scope);
@@ -2842,7 +2845,7 @@ public function unregisterFunction($name)
*/
public function addFeature($name)
{
- $this->features[$name] = true;
+ $this->registeredFeatures[$name] = true;
}
/**
@@ -4567,7 +4570,7 @@ protected function libFeatureExists($args)
$string = $this->coerceString($args[0]);
$name = $this->compileStringContent($string);
- return $this->toBool(array_key_exists($name, $this->feature) ? $this->features[$name] : false);
+ return $this->toBool(array_key_exists($name, $this->registeredFeatures) ? $this->registeredFeatures[$name] : false);
}
protected static $libFunctionExists = array('name');
From 9c488fd601d253e279f6b12fe59486c63250aeec Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Wed, 21 Oct 2015 22:18:08 -0400
Subject: [PATCH 130/534] refs #328 - change sourceParser to an index,
minimizing self-referencing recursion in the parse tree
---
src/Compiler.php | 83 ++++++++++++++++++++++++++++--------------------
src/Parser.php | 21 ++++++------
2 files changed, 61 insertions(+), 43 deletions(-)
diff --git a/src/Compiler.php b/src/Compiler.php
index f4765e79..529fdac0 100644
--- a/src/Compiler.php
+++ b/src/Compiler.php
@@ -133,7 +133,8 @@ class Compiler
private $scope;
private $parser;
private $sourcePos;
- private $sourceParser;
+ private $sourceParsers;
+ private $sourceIndex;
private $storeEnv;
private $charsetSeen;
private $stderr;
@@ -151,27 +152,25 @@ class Compiler
*/
public function compile($code, $path = null)
{
- $this->indentLevel = -1;
- $this->commentsSeen = array();
- $this->extends = array();
- $this->extendsMap = array();
- $this->parsedFiles = array();
- $this->env = null;
- $this->scope = null;
-
- $this->stderr = fopen('php://stderr', 'w');
-
$locale = setlocale(LC_NUMERIC, 0);
setlocale(LC_NUMERIC, 'C');
- $this->parser = new Parser($path);
-
+ $this->indentLevel = -1;
+ $this->commentsSeen = array();
+ $this->extends = array();
+ $this->extendsMap = array();
+ $this->parsedFiles = array();
+ $this->sourceParsers = array();
+ $this->sourceIndex = null;
+ $this->env = null;
+ $this->scope = null;
+ $this->stderr = fopen('php://stderr', 'w');
+
+ $this->parser = $this->parserFactory($path);
$tree = $this->parser->parse($code);
$this->formatter = new $this->formatter();
- $this->addParsedFile($path);
-
$this->rootEnv = $this->pushEnv($tree);
$this->injectVariables($this->registeredVars);
$this->compileRoot($tree);
@@ -184,6 +183,24 @@ public function compile($code, $path = null)
return $out;
}
+ /**
+ * Instantiate parser
+ *
+ * @param string $path
+ * @param boolean $isRoot
+ *
+ * @return \Leafo\Parser
+ */
+ private function parserFactory($path, $isRoot = true)
+ {
+ $parser = new Parser($path, count($this->sourceParsers), $isRoot);
+
+ $this->sourceParsers[] = $parser;
+ $this->addParsedFile($path);
+
+ return $parser;
+ }
+
/**
* Is self extend?
*
@@ -566,7 +583,7 @@ protected function compileAtRoot($block)
$wrapped = (object) array(
'parent' => $block,
'sourcePosition' => $block->sourcePosition,
- 'sourceParser' => $block->sourceParser,
+ 'sourceIndex' => $block->sourceIndex,
'selectors' => $block->selector,
'comments' => array(),
'children' => $block->children,
@@ -660,8 +677,9 @@ protected function compileBlock($block)
$annotation = $this->makeOutputBlock('comment');
$annotation->depth = 0;
- $file = $block->sourceParser->getSourceName();
- $line = $block->sourceParser->getLineNo($block->sourcePosition);
+ $parser = $this->sourceParsers[$block->sourceIndex];
+ $file = $parser->getSourceName();
+ $line = $parser->getLineNo($block->sourcePosition);
switch ($this->lineNumberStyle) {
case self::LINE_COMMENTS:
@@ -718,7 +736,7 @@ protected function evalSelectors($selectors)
// after evaluating interpolates, we might need a second pass
if ($this->shouldEvaluate) {
$buffer = $this->collapseSelectors($selectors);
- $parser = new Parser(__METHOD__, false);
+ $parser = $this->parserFactory(__METHOD__, false);
if ($parser->parseSelector($buffer, $newSelectors)) {
$selectors = array_map(array($this, 'evalSelector'), $newSelectors);
@@ -1106,8 +1124,8 @@ protected function compileImport($rawPath, $out)
*/
protected function compileChild($child, $out)
{
+ $this->sourceIndex = isset($child[Parser::SOURCE_INDEX]) ? $child[Parser::SOURCE_INDEX] : null;
$this->sourcePos = isset($child[Parser::SOURCE_POSITION]) ? $child[Parser::SOURCE_POSITION] : -1;
- $this->sourceParser = isset($child[Parser::SOURCE_PARSER]) ? $child[Parser::SOURCE_PARSER] : $this->parser;
switch ($child[0]) {
case 'import':
@@ -2672,7 +2690,7 @@ protected function injectVariables(array $args)
return;
}
- $parser = new Parser(__METHOD__, false);
+ $parser = $this->parserFactory(__METHOD__, false);
foreach ($args as $name => $strValue) {
if ($name[0] === '$') {
@@ -2732,7 +2750,7 @@ public function getVariables()
*/
public function addParsedFile($path)
{
- if (isset($path)) {
+ if (isset($path) && file_exists($path)) {
$this->parsedFiles[realpath($path)] = filemtime($path);
}
}
@@ -2864,11 +2882,10 @@ protected function importFile($path, $out)
$tree = $this->importCache[$realPath];
} else {
- $code = file_get_contents($path);
- $parser = new Parser($path, false);
- $tree = $parser->parse($code);
+ $code = file_get_contents($path);
+ $parser = $this->parserFactory($path, false);
+ $tree = $parser->parse($code);
- $this->addParsedFile($path);
$this->importCache[$realPath] = $tree;
}
@@ -2939,8 +2956,9 @@ public function throwError($msg)
$msg = call_user_func_array('sprintf', func_get_args());
}
- if ($this->sourcePos >= 0 && isset($this->sourceParser)) {
- $this->sourceParser->throwParseError($msg, $this->sourcePos);
+ if ($this->sourcePos >= 0 && isset($this->sourceIndex)) {
+ $parser = $this->sourceParsers[$this->sourceIndex];
+ $parser->throwParseError($msg, $this->sourcePos);
}
throw new \Exception($msg);
@@ -2956,14 +2974,11 @@ public function throwError($msg)
private function handleImportLoop($name)
{
for ($env = $this->env; $env; $env = $env->parent) {
- $file = $env->block->sourceParser->getSourceName();
+ $parser = $this->sourceParsers[$env->block->sourceIndex];
+ $file = $parser->getSourceName();
if (realpath($file) === $name) {
- $this->throwError(
- 'An @import loop has been found: %s imports %s',
- $this->env->block->sourceParser->getSourceName(),
- basename($file)
- );
+ $this->throwError('An @import loop has been found: %s imports %s', $file, basename($file));
}
}
}
diff --git a/src/Parser.php b/src/Parser.php
index 5312a64d..b2028f80 100644
--- a/src/Parser.php
+++ b/src/Parser.php
@@ -20,8 +20,8 @@
*/
class Parser
{
- const SOURCE_POSITION = -1;
- const SOURCE_PARSER = -2;
+ const SOURCE_INDEX = -1;
+ const SOURCE_POSITION = -2;
/**
* @var array
@@ -71,6 +71,7 @@ class Parser
protected static $commentMultiRight = '*/';
private $sourceName;
+ private $sourceIndex;
private $rootParser;
private $charset;
private $count;
@@ -83,13 +84,15 @@ class Parser
* Constructor
*
* @param string $sourceName
+ * @param integer $sourceIndex
* @param boolean $rootParser
*/
- public function __construct($sourceName = null, $rootParser = true)
+ public function __construct($sourceName = null, $sourceIndex = null, $rootParser = true)
{
- $this->sourceName = $sourceName ?: '(stdin)';
- $this->rootParser = $rootParser;
- $this->charset = null;
+ $this->sourceName = $sourceName ?: '(stdin)';
+ $this->sourceIndex = $sourceIndex;
+ $this->rootParser = $rootParser;
+ $this->charset = null;
if (empty(self::$operatorStr)) {
self::$operatorStr = $this->makeOperatorStr(self::$operators);
@@ -493,7 +496,7 @@ protected function parseChunk()
$statement[self::SOURCE_POSITION] = $s;
if (! $this->rootParser) {
- $statement[self::SOURCE_PARSER] = $this;
+ $statement[self::SOURCE_INDEX] = $this->sourceIndex;
}
$this->charset = $statement;
@@ -692,7 +695,7 @@ protected function pushBlock($selectors, $pos = 0)
$b->parent = $this->env;
$b->sourcePosition = $pos;
- $b->sourceParser = $this;
+ $b->sourceIndex = $this->sourceIndex;
$b->selectors = $selectors;
$b->comments = array();
@@ -779,7 +782,7 @@ protected function append($statement, $pos = null)
$statement[self::SOURCE_POSITION] = $pos;
if (! $this->rootParser) {
- $statement[self::SOURCE_PARSER] = $this;
+ $statement[self::SOURCE_INDEX] = $this->sourceIndex;
}
}
From 0424688cb34e94e49098cff3159985c73f1c3b26 Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Wed, 21 Oct 2015 22:19:37 -0400
Subject: [PATCH 131/534] phpcs
---
src/Compiler.php | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/src/Compiler.php b/src/Compiler.php
index 529fdac0..68dca586 100644
--- a/src/Compiler.php
+++ b/src/Compiler.php
@@ -4585,7 +4585,9 @@ protected function libFeatureExists($args)
$string = $this->coerceString($args[0]);
$name = $this->compileStringContent($string);
- return $this->toBool(array_key_exists($name, $this->registeredFeatures) ? $this->registeredFeatures[$name] : false);
+ return $this->toBool(
+ array_key_exists($name, $this->registeredFeatures) ? $this->registeredFeatures[$name] : false
+ );
}
protected static $libFunctionExists = array('name');
From 604bf3b91caeb14b7d1676ec146b6e8a9b31ca3b Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Thu, 22 Oct 2015 00:23:21 -0400
Subject: [PATCH 132/534] Nested formatter output optimization
---
src/Formatter/Nested.php | 4 ++++
tests/outputs/short_circuit.css | 1 -
tests/outputs_numbered/short_circuit.css | 1 -
3 files changed, 4 insertions(+), 2 deletions(-)
diff --git a/src/Formatter/Nested.php b/src/Formatter/Nested.php
index 45866ca9..c8e3decd 100644
--- a/src/Formatter/Nested.php
+++ b/src/Formatter/Nested.php
@@ -114,6 +114,10 @@ protected function block($block)
$this->adjustAllChildren($block);
}
+ if (empty($block->lines) && empty($block->children)) {
+ return;
+ }
+
$this->depth = $block->depth;
if (! empty($block->selectors)) {
diff --git a/tests/outputs/short_circuit.css b/tests/outputs/short_circuit.css
index 8b137891..e69de29b 100644
--- a/tests/outputs/short_circuit.css
+++ b/tests/outputs/short_circuit.css
@@ -1 +0,0 @@
-
diff --git a/tests/outputs_numbered/short_circuit.css b/tests/outputs_numbered/short_circuit.css
index 8b137891..e69de29b 100644
--- a/tests/outputs_numbered/short_circuit.css
+++ b/tests/outputs_numbered/short_circuit.css
@@ -1 +0,0 @@
-
From 81ec424d1f8561e07039435a13506032700bff81 Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Thu, 22 Oct 2015 01:07:12 -0400
Subject: [PATCH 133/534] Debug Formatter - add indent
---
src/Formatter/Debug.php | 34 +++++++++++++++++++++++++++-------
1 file changed, 27 insertions(+), 7 deletions(-)
diff --git a/src/Formatter/Debug.php b/src/Formatter/Debug.php
index 1aae1dab..7082909d 100644
--- a/src/Formatter/Debug.php
+++ b/src/Formatter/Debug.php
@@ -34,19 +34,29 @@ public function __construct()
$this->assignSeparator = ': ';
}
+ /**
+ * {@inheritdoc}
+ */
+ protected function indentStr()
+ {
+ return str_repeat(' ', $this->indentLevel);
+ }
+
/**
* {@inheritdoc}
*/
protected function blockLines($block)
{
+ $indent = $this->indentStr();
+
if (empty($block->lines)) {
- echo "block->lines: []\n";
+ echo "{$indent}block->lines: []\n";
return;
}
foreach ($block->lines as $index => $line) {
- echo "block->lines[{$index}]: $line\n";
+ echo "{$indent}block->lines[{$index}]: $line\n";
}
}
@@ -55,14 +65,16 @@ protected function blockLines($block)
*/
protected function blockSelectors($block)
{
+ $indent = $this->indentStr();
+
if (empty($block->selectors)) {
- echo "block->selectors: []\n";
+ echo "{$indent}block->selectors: []\n";
return;
}
foreach ($block->selectors as $index => $selector) {
- echo "block->selectors[{$index}]: $selector\n";
+ echo "{$indent}block->selectors[{$index}]: $selector\n";
}
}
@@ -71,15 +83,21 @@ protected function blockSelectors($block)
*/
protected function blockChildren($block)
{
+ $indent = $this->indentStr();
+
if (empty($block->children)) {
- echo "block->children: []\n";
+ echo "{$indent}block->children: []\n";
return;
}
+ $this->indentLevel++;
+
foreach ($block->children as $i => $child) {
$this->block($child);
}
+
+ $this->indentLevel--;
}
/**
@@ -87,8 +105,10 @@ protected function blockChildren($block)
*/
protected function block($block)
{
- echo "block->type: {$block->type}\n" .
- "block->depth: {$block->depth}\n";
+ $indent = $this->indentStr();
+
+ echo "{$indent}block->type: {$block->type}\n" .
+ "{$indent}block->depth: {$block->depth}\n";
$this->blockSelectors($block);
$this->blockLines($block);
From 8c10ce2e233330c4c85d1d122778ae0b286ceaaa Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Thu, 22 Oct 2015 01:44:03 -0400
Subject: [PATCH 134/534] internals: Parser::$rootParser removal
---
src/Compiler.php | 15 +++++++--------
src/Parser.php | 15 +++------------
2 files changed, 10 insertions(+), 20 deletions(-)
diff --git a/src/Compiler.php b/src/Compiler.php
index 68dca586..97667ff3 100644
--- a/src/Compiler.php
+++ b/src/Compiler.php
@@ -186,14 +186,13 @@ public function compile($code, $path = null)
/**
* Instantiate parser
*
- * @param string $path
- * @param boolean $isRoot
+ * @param string $path
*
- * @return \Leafo\Parser
+ * @return \Leafo\ScssPhp\Parser
*/
- private function parserFactory($path, $isRoot = true)
+ private function parserFactory($path)
{
- $parser = new Parser($path, count($this->sourceParsers), $isRoot);
+ $parser = new Parser($path, count($this->sourceParsers));
$this->sourceParsers[] = $parser;
$this->addParsedFile($path);
@@ -736,7 +735,7 @@ protected function evalSelectors($selectors)
// after evaluating interpolates, we might need a second pass
if ($this->shouldEvaluate) {
$buffer = $this->collapseSelectors($selectors);
- $parser = $this->parserFactory(__METHOD__, false);
+ $parser = $this->parserFactory(__METHOD__);
if ($parser->parseSelector($buffer, $newSelectors)) {
$selectors = array_map(array($this, 'evalSelector'), $newSelectors);
@@ -2690,7 +2689,7 @@ protected function injectVariables(array $args)
return;
}
- $parser = $this->parserFactory(__METHOD__, false);
+ $parser = $this->parserFactory(__METHOD__);
foreach ($args as $name => $strValue) {
if ($name[0] === '$') {
@@ -2883,7 +2882,7 @@ protected function importFile($path, $out)
$tree = $this->importCache[$realPath];
} else {
$code = file_get_contents($path);
- $parser = $this->parserFactory($path, false);
+ $parser = $this->parserFactory($path);
$tree = $parser->parse($code);
$this->importCache[$realPath] = $tree;
diff --git a/src/Parser.php b/src/Parser.php
index b2028f80..14198a0f 100644
--- a/src/Parser.php
+++ b/src/Parser.php
@@ -72,7 +72,6 @@ class Parser
private $sourceName;
private $sourceIndex;
- private $rootParser;
private $charset;
private $count;
private $env;
@@ -85,13 +84,11 @@ class Parser
*
* @param string $sourceName
* @param integer $sourceIndex
- * @param boolean $rootParser
*/
- public function __construct($sourceName = null, $sourceIndex = null, $rootParser = true)
+ public function __construct($sourceName, $sourceIndex = 0)
{
$this->sourceName = $sourceName ?: '(stdin)';
$this->sourceIndex = $sourceIndex;
- $this->rootParser = $rootParser;
$this->charset = null;
if (empty(self::$operatorStr)) {
@@ -494,10 +491,7 @@ protected function parseChunk()
$statement = array('charset', $charset);
$statement[self::SOURCE_POSITION] = $s;
-
- if (! $this->rootParser) {
- $statement[self::SOURCE_INDEX] = $this->sourceIndex;
- }
+ $statement[self::SOURCE_INDEX] = $this->sourceIndex;
$this->charset = $statement;
}
@@ -780,10 +774,7 @@ protected function append($statement, $pos = null)
{
if ($pos !== null) {
$statement[self::SOURCE_POSITION] = $pos;
-
- if (! $this->rootParser) {
- $statement[self::SOURCE_INDEX] = $this->sourceIndex;
- }
+ $statement[self::SOURCE_INDEX] = $this->sourceIndex;
}
$this->env->children[] = $statement;
From 375e39768e598a31c95935d2544b229fc3d1560b Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Fri, 23 Oct 2015 12:36:44 -0400
Subject: [PATCH 135/534] Compiler: refactor compileDirective()
---
src/Compiler.php | 34 +++++++++++++++++++++-------------
1 file changed, 21 insertions(+), 13 deletions(-)
diff --git a/src/Compiler.php b/src/Compiler.php
index 97667ff3..d541207e 100644
--- a/src/Compiler.php
+++ b/src/Compiler.php
@@ -555,6 +555,26 @@ protected function mediaParent($scope)
return $scope;
}
+ /**
+ * Compile directive
+ *
+ * @param \stdClass $block
+ */
+ protected function compileDirective($block)
+ {
+ $s = '@' . $block->name;
+
+ if (! empty($block->value)) {
+ $s .= ' ' . $this->compileValue($block->value);
+ }
+
+ if ($block->name === 'keyframes' || substr($block->name, -10) === '-keyframes') {
+ $this->compileKeyframeBlock($block, array($s));
+ } else {
+ $this->compileNestedBlock($block, array($s));
+ }
+ }
+
/**
* Compile at-root
*
@@ -1138,19 +1158,7 @@ protected function compileChild($child, $out)
break;
case 'directive':
- list(, $directive) = $child;
-
- $s = '@' . $directive->name;
-
- if (! empty($directive->value)) {
- $s .= ' ' . $this->compileValue($directive->value);
- }
-
- if ($directive->name === 'keyframes' || substr($directive->name, -10) === '-keyframes') {
- $this->compileKeyframeBlock($directive, array($s));
- } else {
- $this->compileNestedBlock($directive, array($s));
- }
+ $this->compileDirective($child[1]);
break;
case 'at-root':
From 1995cc145d1e776ba38e3eae1e18211a43f0ba56 Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Sat, 26 Sep 2015 21:16:18 -0400
Subject: [PATCH 136/534] Compiler: add spliceTree() to flesh out @at-root
support; fixes #193, #354
---
src/Compiler.php | 233 ++++++++++++++++++++++++++---
tests/inputs/at_root.scss | 147 ++++++++++++++++--
tests/outputs/at_root.css | 73 ++++++++-
tests/outputs_numbered/at_root.css | 118 +++++++++++++--
4 files changed, 517 insertions(+), 54 deletions(-)
diff --git a/src/Compiler.php b/src/Compiler.php
index d541207e..8171ff06 100644
--- a/src/Compiler.php
+++ b/src/Compiler.php
@@ -53,6 +53,11 @@ class Compiler
const LINE_COMMENTS = 1;
const DEBUG_INFO = 2;
+ const WITH_RULE = 1;
+ const WITH_MEDIA = 2;
+ const WITH_SUPPORTS = 4;
+ const WITH_ALL = 7;
+
/**
* @var array
*/
@@ -104,6 +109,8 @@ class Compiler
static public $emptyList = array('list', '', array());
static public $emptyMap = array('map', array(), array());
static public $emptyString = array('string', '"', array());
+ static public $with = array('keyword', 'with');
+ static public $without = array('keyword', 'without');
protected $importPaths = array('');
protected $importCache = array();
@@ -582,20 +589,9 @@ protected function compileDirective($block)
*/
protected function compileAtRoot($block)
{
- $env = $this->pushEnv($block);
-
- $envs = $this->compactEnv($env);
-
- if (isset($block->with)) {
- // @todo move outside of nested directives, e.g., (without: all), (without: media supports), (with: rule)
- } else {
- // exclude selectors by default
- $this->env->parent = $this->rootEnv;
- }
-
- $this->scope = $this->makeOutputBlock('at-root');
- $this->scope->depth = 1;
- $this->scope->parent->children[] = $this->scope;
+ $env = $this->pushEnv($block);
+ $envs = $this->compactEnv($env);
+ $without = isset($block->with) ? $this->compileWith($block->with) : self::WITH_RULE;
// wrap inline selector
if ($block->selector) {
@@ -611,14 +607,207 @@ protected function compileAtRoot($block)
$block->children = array(array('block', $wrapped));
}
- $this->compileChildren($block->children, $this->scope);
+ $this->env = $this->filterWithout($envs, $without);
+ $newBlock = $this->spliceTree($envs, $block, $without);
- $this->scope = $this->scope->parent;
+ $saveScope = $this->scope;
+ $this->scope = $this->rootBlock;
+
+ $this->compileChild($newBlock, $this->scope);
+
+ $this->scope = $saveScope;
$this->env = $this->extractEnv($envs);
$this->popEnv();
}
+ /**
+ * Splice parse tree
+ *
+ * @param array $envs
+ * @param \stdClass $block
+ * @param integer $without
+ *
+ * @return \stdClass
+ */
+ private function spliceTree($envs, $block, $without)
+ {
+ $newBlock = null;
+
+ foreach ($envs as $e) {
+ if (! isset($e->block)) {
+ continue;
+ }
+
+ if (isset($e->block) && $e->block === $block) {
+ continue;
+ }
+
+ if (isset($e->block->type) && $e->block->type === 'at-root') {
+ continue;
+ }
+
+ if (($without & self::WITH_RULE) && isset($e->block->selectors)) {
+ continue;
+ }
+
+ if (($without & self::WITH_MEDIA) &&
+ isset($e->block->type) && $e->block->type === 'media'
+ ) {
+ continue;
+ }
+
+ if (($without & self::WITH_SUPPORTS) &&
+ isset($e->block->type) && $e->block->type === 'directive' &&
+ isset($e->block->name) && $e->block->name === 'supports'
+ ) {
+ continue;
+ }
+
+ $b = new \stdClass;
+
+ if (isset($e->block->sourcePosition)) {
+ $b->sourcePosition = $e->block->sourcePosition;
+ }
+
+ if (isset($e->block->sourceIndex)) {
+ $b->sourceIndex = $e->block->sourceIndex;
+ }
+
+ $b->selectors = array();
+
+ if (isset($e->block->comments)) {
+ $b->comments = $e->block->comments;
+ }
+
+ if (isset($e->block->type)) {
+ $b->type = $e->block->type;
+ }
+
+ if (isset($e->block->name)) {
+ $b->name = $e->block->name;
+ }
+
+ if (isset($e->block->queryList)) {
+ $b->queryList = $e->block->queryList;
+ }
+
+ if (isset($e->block->value)) {
+ $b->value = $e->block->value;
+ }
+
+ if ($newBlock) {
+ $type = isset($newBlock->type) ? $newBlock->type : 'block';
+
+ $b->children = array(array($type, $newBlock));
+
+ $newBlock->parent = $b;
+ } elseif (count($block->children)) {
+ foreach ($block->children as $child) {
+ if ($child[0] === 'block') {
+ $child[1]->parent = $b;
+ }
+ }
+
+ $b->children = $block->children;
+ }
+
+ $b->parent = null;
+
+ $newBlock = $b;
+ }
+
+ $type = isset($newBlock->type) ? $newBlock->type : 'block';
+
+ return array($type, $newBlock);
+ }
+
+ /**
+ * Compile @at-root's with: inclusion / without: exclusion into filter flags
+ *
+ * @param array $with
+ *
+ * @return integer
+ */
+ private function compileWith($with)
+ {
+ static $mapping = array(
+ 'rule' => self::WITH_RULE,
+ 'media' => self::WITH_MEDIA,
+ 'supports' => self::WITH_SUPPORTS,
+ 'all' => self::WITH_ALL,
+ );
+
+ // exclude selectors by default
+ $without = self::WITH_RULE;
+
+ if ($this->libMapHasKey(array($with, self::$with))) {
+ $without = self::WITH_ALL;
+
+ $list = $this->coerceList($this->libMapGet(array($with, self::$with)));
+
+ foreach ($list[2] as $item) {
+ $keyword = $this->compileStringContent($this->coerceString($item));
+
+ if (array_key_exists($keyword, $mapping)) {
+ $without &= ~($mapping[$keyword]);
+ }
+ }
+ }
+
+ if ($this->libMapHasKey(array($with, self::$without))) {
+ $without = 0;
+
+ $list = $this->coerceList($this->libMapGet(array($with, self::$without)));
+
+ foreach ($list[2] as $item) {
+ $keyword = $this->compileStringContent($this->coerceString($item));
+
+ if (array_key_exists($keyword, $mapping)) {
+ $without |= $mapping[$keyword];
+ }
+ }
+ }
+
+ return $without;
+ }
+
+ /**
+ * Filter env stack
+ *
+ * @param array $envs
+ * @param integer $without
+ *
+ * @return \stdClass
+ */
+ private function filterWithout($envs, $without)
+ {
+ $filtered = array();
+
+ foreach ($envs as $e) {
+ if (($without & self::WITH_RULE) && isset($e->block->selectors)) {
+ continue;
+ }
+
+ if (($without & self::WITH_MEDIA) &&
+ isset($e->block->type) && $e->block->type === 'media'
+ ) {
+ continue;
+ }
+
+ if (($without & self::WITH_SUPPORTS) &&
+ isset($e->block->type) && $e->block->type === 'directive' &&
+ isset($e->block->name) && $e->block->name === 'supports'
+ ) {
+ continue;
+ }
+
+ $filtered[] = $e;
+ }
+
+ return $this->extractEnv($filtered);
+ }
+
/**
* Compile keyframe block
*
@@ -4135,9 +4324,7 @@ protected function libQuote($args)
protected static $libPercentage = array('value');
protected function libPercentage($args)
{
- return array('number',
- $this->coercePercent($args[0]) * 100,
- '%');
+ return array('number', $this->coercePercent($args[0]) * 100, '%');
}
protected static $libRound = array('value');
@@ -4359,11 +4546,11 @@ protected function libMapHasKey($args)
for ($i = count($map[1]) - 1; $i >= 0; $i--) {
if ($key === $this->compileStringContent($this->coerceString($map[1][$i]))) {
- return self::$true;
+ return true;
}
}
- return self::$false;
+ return false;
}
protected static $libMapMerge = array('map-1', 'map-2');
@@ -4605,13 +4792,13 @@ protected function libFunctionExists($args)
// user defined functions
if ($this->has(self::$namespaces['function'] . $name)) {
- return self::$true;
+ return true;
}
$name = $this->normalizeName($name);
if (isset($this->userFunctions[$name])) {
- return self::$true;
+ return true;
}
// built-in functions
diff --git a/tests/inputs/at_root.scss b/tests/inputs/at_root.scss
index aa4f6584..1f00c727 100644
--- a/tests/inputs/at_root.scss
+++ b/tests/inputs/at_root.scss
@@ -1,24 +1,149 @@
+.parent-inline-selector {
+ color: white;
+ @at-root .child { color: black; }
+}
+
+.parent-block {
+ color: white;
+ @at-root {
+ .child1 { color: green; }
+ .child2 { color: blue; }
+ }
+ .step-child { color: black; }
+}
+
.first {
color: red;
}
body{
-.second {
- color: white;
+ .second {
+ color: white;
- @at-root {
- .nested1 {
- color: blue;
- @at-root {
- .nested2 {
- color: yellow;
+ @at-root {
+ .nested1 {
+ color: blue;
+ @at-root {
+ .nested2 {
+ color: yellow;
+ }
}
+ color: orange;
}
- color: orange;
}
+ color: black;
}
- color: black;
-}
}
.third {
color: green;
}
+
+@media print {
+ .page {
+ width: 8in;
+ @at-root (without: media) {
+ color: red;
+ }
+ }
+}
+
+.my-widget {
+ @media (min-width: 300px) {
+ .inside-mq {
+ inside-style: mq;
+ }
+ @at-root (without: media){
+ //this without:media tells the screen what to bust out of
+ .outside-mq {
+ outside-style: mq;
+ }
+ }
+ // using (without:all) forces all nested selectors outside of all media
+ // queries, hence color:blue only in the .outside-everything class in generated css
+ @at-root (without:all){
+ .outside-class {
+ color: blue;
+ }
+ }
+
+ // using the (with:media) keeps .with-only inside media query hence .with-only selector
+ // inside @media ()min-width:300px
+ @at-root (with: media) {
+ .with-only {
+ // do this ONLY inside mq
+ color: pink;
+ }
+ }
+ }
+}
+
+// without: rule - default - outside of all css rules, but inside directives
+@media screen and (max-width:320px) {
+ .foo {
+ margin: 0;
+
+ @at-root (without: rule) {
+ .bar {
+ padding: 0;
+ }
+ }
+ @at-root (without: media rule) {
+ .baar {
+ padding: 0;
+ }
+ }
+ @at-root (without: media) {
+ .barr {
+ padding: 0;
+ }
+ }
+ }
+}
+
+// with: rule - outside of all directives but preserve any css rules
+@media screen and (max-width:640px) {
+ .foo {
+ @supports ( display: flex ) {
+ @at-root (with: rule) {
+ .bar {
+ width: 0;
+ }
+ }
+ @at-root (with: supports) {
+ .baz {
+ height: 0;
+ }
+ }
+ @at-root (with: media) {
+ .qux {
+ margin: 0;
+ }
+ }
+ @at-root (with: media rule) {
+ .quux {
+ padding: 0;
+ }
+ }
+ @at-root (with: rule) {
+ .quix {
+ padding: 0;
+ }
+ }
+ }
+ }
+}
+
+$table-padding: 10px !default;
+
+@mixin table($padding: $table-padding) {
+ @at-root {
+ tbody {
+ padding: $padding;
+ }
+ }
+}
+.test{
+ .test2{
+ padding: 0px;
+ @include table;
+ }
+}
diff --git a/tests/outputs/at_root.css b/tests/outputs/at_root.css
index 86edb772..5383eaab 100644
--- a/tests/outputs/at_root.css
+++ b/tests/outputs/at_root.css
@@ -1,15 +1,76 @@
+.parent-inline-selector {
+ color: white; }
+ .child {
+ color: black; }
+
+.parent-block {
+ color: white; }
+ .child1 {
+ color: green; }
+ .child2 {
+ color: blue; }
+ .parent-block .step-child {
+ color: black; }
+
.first {
color: red; }
body .second {
color: white;
color: black; }
-
- .nested1 {
- color: blue;
- color: orange; }
- .nested2 {
- color: yellow; }
+ .nested1 {
+ color: blue;
+ color: orange; }
+ .nested2 {
+ color: yellow; }
.third {
color: green; }
+
+@media print {
+ .page {
+ width: 8in; } }
+ .page {
+ color: red; }
+
+@media (min-width: 300px) {
+ .my-widget .inside-mq {
+ inside-style: mq; } }
+ .my-widget .outside-mq {
+ outside-style: mq; }
+ .outside-class {
+ color: blue; }
+ @media (min-width: 300px) {
+ .with-only {
+ color: pink; } }
+
+@media screen and (max-width: 320px) {
+ .foo {
+ margin: 0; } }
+ @media screen and (max-width: 320px) {
+ .bar {
+ padding: 0; } }
+ .baar {
+ padding: 0; }
+ .foo .barr {
+ padding: 0; }
+
+
+ .foo .bar {
+ width: 0; }
+ @supports ( display: flex ) {
+ .baz {
+ height: 0; } }
+ @media screen and (max-width: 640px) {
+ .qux {
+ margin: 0; } }
+ @media screen and (max-width: 640px) {
+ .foo .quux {
+ padding: 0; } }
+ .foo .quix {
+ padding: 0; }
+
+.test .test2 {
+ padding: 0px; }
+ tbody {
+ padding: 10px; }
diff --git a/tests/outputs_numbered/at_root.css b/tests/outputs_numbered/at_root.css
index 873218f2..2ac5a07e 100644
--- a/tests/outputs_numbered/at_root.css
+++ b/tests/outputs_numbered/at_root.css
@@ -1,19 +1,109 @@
/* line 1, inputs/at_root.scss */
+.parent-inline-selector {
+ color: white; }
+ /* line 3, inputs/at_root.scss */
+ .child {
+ color: black; }
+/* line 6, inputs/at_root.scss */
+.parent-block {
+ color: white; }
+ /* line 9, inputs/at_root.scss */
+ .child1 {
+ color: green; }
+/* line 10, inputs/at_root.scss */
+.child2 {
+ color: blue; }
+/* line 12, inputs/at_root.scss */
+.parent-block .step-child {
+ color: black; }
+/* line 15, inputs/at_root.scss */
.first {
color: red; }
-/* line 4, inputs/at_root.scss */
-/* line 5, inputs/at_root.scss */
- body .second {
- color: white;
- color: black; }
-
-/* line 9, inputs/at_root.scss */
-.nested1 {
-color: blue;
-color: orange; }
-/* line 12, inputs/at_root.scss */
-.nested2 {
-color: yellow; }
-/* line 22, inputs/at_root.scss */
+/* line 18, inputs/at_root.scss */
+/* line 19, inputs/at_root.scss */
+
+body .second {
+ color: white;
+ color: black; }
+
+/* line 23, inputs/at_root.scss */
+ .nested1 {
+ color: blue;
+ color: orange; }
+ /* line 26, inputs/at_root.scss */
+ .nested2 {
+ color: yellow; }
+/* line 36, inputs/at_root.scss */
.third {
color: green; }
+
+@media print {
+/* line 41, inputs/at_root.scss */
+.page {
+ width: 8in; } }
+
+.page {
+ color: red; }
+/* line 49, inputs/at_root.scss */
+@media (min-width: 300px) {
+ /* line 51, inputs/at_root.scss */
+ .my-widget .inside-mq {
+ inside-style: mq; } }
+ /* line 56, inputs/at_root.scss */
+ .my-widget .outside-mq {
+ outside-style: mq; }
+ /* line 63, inputs/at_root.scss */
+ .outside-class {
+ color: blue; }
+ @media (min-width: 300px) {
+/* line 71, inputs/at_root.scss */
+.with-only {
+color: pink; } }
+
+@media screen and (max-width: 320px) {
+/* line 81, inputs/at_root.scss */
+.foo {
+ margin: 0; } }
+
+@media screen and (max-width: 320px) {
+/* line 85, inputs/at_root.scss */
+.bar {
+ padding: 0; } }
+
+/* line 90, inputs/at_root.scss */
+ .baar {
+ padding: 0; }
+
+/* line 95, inputs/at_root.scss */
+ .foo .barr {
+ padding: 0; }
+
+@media screen and (max-width: 640px) {
+/* line 104, inputs/at_root.scss */ }
+ /* line 107, inputs/at_root.scss */
+ .foo .bar {
+ width: 0; }
+ @supports ( display: flex ) {
+/* line 112, inputs/at_root.scss */
+.baz {
+height: 0; } }
+ @media screen and (max-width: 640px) {
+/* line 117, inputs/at_root.scss */
+.qux {
+margin: 0; } }
+ @media screen and (max-width: 640px) {
+ /* line 122, inputs/at_root.scss */
+ .foo .quux {
+ padding: 0; } }
+ /* line 127, inputs/at_root.scss */
+ .foo .quix {
+ padding: 0; }
+/* line 144, inputs/at_root.scss */
+/* line 145, inputs/at_root.scss */
+
+.test .test2 {
+ padding: 0px; }
+
+/* line 139, inputs/at_root.scss */
+ tbody {
+ padding: 10px; }
From e89391b29b5eb66e211ce4d20ccb2bb519137c08 Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Fri, 23 Oct 2015 13:15:30 -0400
Subject: [PATCH 137/534] Bump version for next release
---
src/Version.php | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/Version.php b/src/Version.php
index fffc751b..f5769285 100644
--- a/src/Version.php
+++ b/src/Version.php
@@ -18,5 +18,5 @@
*/
class Version
{
- const VERSION = 'v0.3.2';
+ const VERSION = 'v0.3.3';
}
From a8df1b945732bc4fadffa4f09d9d39af955113f6 Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Fri, 23 Oct 2015 20:01:14 -0400
Subject: [PATCH 138/534] Compiler: index($list, $value) problem when $list is
a string/keyword/interpolate (fixes #362)
---
src/Compiler.php | 5 ++++-
tests/inputs/builtins.scss | 1 +
tests/outputs/builtins.css | 1 +
tests/outputs_numbered/builtins.css | 13 +++++++------
4 files changed, 13 insertions(+), 7 deletions(-)
diff --git a/src/Compiler.php b/src/Compiler.php
index 8171ff06..8f0a0d89 100644
--- a/src/Compiler.php
+++ b/src/Compiler.php
@@ -1985,6 +1985,9 @@ public function normalizeValue($value)
case 'number':
return $this->normalizeNumber($value);
+ case 'interpolate':
+ return array('keyword', $this->compileValue($value));
+
default:
return $value;
}
@@ -3874,7 +3877,7 @@ protected function libIndex($args)
return self::$null;
}
- if ($list[0] === 'map') {
+ if ($list[0] === 'map' || $list[0] === 'string' || $list[0] === 'keyword' || $list[0] === 'interpolate') {
$list = $this->coerceList($list, ' ');
}
diff --git a/tests/inputs/builtins.scss b/tests/inputs/builtins.scss
index 1b8bffb4..07a571c7 100644
--- a/tests/inputs/builtins.scss
+++ b/tests/inputs/builtins.scss
@@ -119,6 +119,7 @@
index: index(1px 3px + 3px, 4+2px);
$var: oo;
index: index(foo bar, f#{$var});
+ display: index(nest, nest);
$yes: one, two, three;
$no: great job;
diff --git a/tests/outputs/builtins.css b/tests/outputs/builtins.css
index 7778777e..811700b7 100644
--- a/tests/outputs/builtins.css
+++ b/tests/outputs/builtins.css
@@ -83,6 +83,7 @@
index: 2;
index: 2;
index: 1;
+ display: 1;
world: one, two, three, great, job;
world: one, two, three, great job;
cool: one two three great job;
diff --git a/tests/outputs_numbered/builtins.css b/tests/outputs_numbered/builtins.css
index b62b42c6..a256ec0f 100644
--- a/tests/outputs_numbered/builtins.css
+++ b/tests/outputs_numbered/builtins.css
@@ -84,13 +84,14 @@
index: 2;
index: 2;
index: 1;
+ display: 1;
world: one, two, three, great, job;
world: one, two, three, great job;
cool: one two three great job;
cool: great job one two three;
zip: 1px solid, 2px dashed;
zip: 1px solid red, 2px dashed green; }
-/* line 135, inputs/builtins.scss */
+/* line 136, inputs/builtins.scss */
#introspection {
t: number;
t: string;
@@ -110,31 +111,31 @@
c: true;
c: false;
c: true; }
-/* line 159, inputs/builtins.scss */
+/* line 160, inputs/builtins.scss */
#if {
color: yes;
color: no;
color: yes;
color: yes; }
-/* line 166, inputs/builtins.scss */
+/* line 167, inputs/builtins.scss */
.transparent {
r: 0;
g: 0;
b: 0;
a: 0; }
-/* line 173, inputs/builtins.scss */
+/* line 174, inputs/builtins.scss */
.alpha {
a: 1;
a: 1;
a: 1;
a: 0.5;
a: alpha(currentColor); }
-/* line 182, inputs/builtins.scss */
+/* line 183, inputs/builtins.scss */
#exists {
a: true;
b: true;
c: false; }
-/* line 189, inputs/builtins.scss */
+/* line 190, inputs/builtins.scss */
div.call-tests {
a: #0a64ff;
c: b; }
From 3644540d4d9c6de75bf0d31b0a91e39710dc25d8 Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Fri, 23 Oct 2015 22:54:19 -0400
Subject: [PATCH 139/534] Rewrite generic media directive as @media directive;
fixes #364
---
src/Compiler.php | 8 +++++++-
src/Parser.php | 8 ++++++--
tests/inputs/mixins.scss | 9 +++++++++
tests/outputs/mixins.css | 4 ++++
tests/outputs_numbered/mixins.css | 4 ++++
5 files changed, 30 insertions(+), 3 deletions(-)
diff --git a/src/Compiler.php b/src/Compiler.php
index 8f0a0d89..ed2ca8a7 100644
--- a/src/Compiler.php
+++ b/src/Compiler.php
@@ -505,7 +505,13 @@ protected function compileMedia($media)
{
$this->pushEnv($media);
- $mediaQuery = $this->compileMediaQuery($this->multiplyMedia($this->env));
+ $queryList = $this->multiplyMedia($this->env);
+
+ $mediaQuery = $queryList
+ ? $this->compileMediaQuery($queryList)
+ : (isset($media->value)
+ ? '@media ' . $this->compileStringContent($media->value)
+ : null);
if (! empty($mediaQuery)) {
$this->scope = $this->makeOutputBlock('media', array($mediaQuery));
diff --git a/src/Parser.php b/src/Parser.php
index 14198a0f..d193849f 100644
--- a/src/Parser.php
+++ b/src/Parser.php
@@ -507,8 +507,12 @@ protected function parseChunk()
($this->variable($dirValue) || $this->openString('{', $dirValue) || true) &&
$this->literal('{')
) {
- $directive = $this->pushSpecialBlock('directive', $s);
- $directive->name = $dirName;
+ if ($dirName === 'media') {
+ $directive = $this->pushSpecialBlock('media', $s);
+ } else {
+ $directive = $this->pushSpecialBlock('directive', $s);
+ $directive->name = $dirName;
+ }
if (isset($dirValue)) {
$directive->value = $dirValue;
diff --git a/tests/inputs/mixins.scss b/tests/inputs/mixins.scss
index 1b6550cf..63f9007b 100644
--- a/tests/inputs/mixins.scss
+++ b/tests/inputs/mixins.scss
@@ -181,3 +181,12 @@ div.parameter-name-scope {
0% { color: green; }
100% { color: red; }
}
+
+@mixin test-mixin($color: #000) {
+ @media screen and (min-width:0\0) {
+ color: $color;
+ }
+}
+.test{
+ @include test-mixin();
+}
diff --git a/tests/outputs/mixins.css b/tests/outputs/mixins.css
index 55feee4e..e2004a07 100644
--- a/tests/outputs/mixins.css
+++ b/tests/outputs/mixins.css
@@ -91,3 +91,7 @@ div.parameter-name-scope {
100% {
color: red; } }
+
+@media screen and (min-width:0\0) {
+ .test {
+ color: #000; } }
diff --git a/tests/outputs_numbered/mixins.css b/tests/outputs_numbered/mixins.css
index b16f853b..2df05142 100644
--- a/tests/outputs_numbered/mixins.css
+++ b/tests/outputs_numbered/mixins.css
@@ -104,3 +104,7 @@ div.parameter-name-scope {
/* line 182, inputs/mixins.scss */
100% {
color: red; } }
+/* line 190, inputs/mixins.scss */
+@media screen and (min-width:0\0) {
+ .test {
+ color: #000; } }
From 0d1855985c37833731c5dd703a6d69b950e6c2ab Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Fri, 23 Oct 2015 23:23:47 -0400
Subject: [PATCH 140/534] code tweaks
---
src/Compiler.php | 16 ++++++++--------
1 file changed, 8 insertions(+), 8 deletions(-)
diff --git a/src/Compiler.php b/src/Compiler.php
index ed2ca8a7..4fc0bade 100644
--- a/src/Compiler.php
+++ b/src/Compiler.php
@@ -505,13 +505,7 @@ protected function compileMedia($media)
{
$this->pushEnv($media);
- $queryList = $this->multiplyMedia($this->env);
-
- $mediaQuery = $queryList
- ? $this->compileMediaQuery($queryList)
- : (isset($media->value)
- ? '@media ' . $this->compileStringContent($media->value)
- : null);
+ $mediaQuery = $this->compileMediaQuery($this->multiplyMedia($this->env));
if (! empty($mediaQuery)) {
$this->scope = $this->makeOutputBlock('media', array($mediaQuery));
@@ -1196,6 +1190,10 @@ protected function compileMediaQuery($queryList)
. ')';
}
break;
+
+ case 'mediaValue':
+ $parts[] = $this->compileValue($q[1]);
+ break;
}
}
@@ -2665,7 +2663,9 @@ protected function multiplyMedia($env, $childQueries = null)
return $this->multiplyMedia($env->parent, $childQueries);
}
- $parentQueries = $env->block->queryList;
+ $parentQueries = isset($env->block->queryList)
+ ? $env->block->queryList
+ : array(array(array('mediaValue', $env->block->value)));
if ($childQueries === null) {
$childQueries = $parentQueries;
From ebb6269951efb2c0f2cd0cd2d950ff83ef34b7e2 Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Sat, 24 Oct 2015 16:06:58 -0400
Subject: [PATCH 141/534] fix str-slice() when end-at <= 0; fixes #366
---
src/Compiler.php | 4 ++--
tests/inputs/builtins.scss | 2 ++
tests/outputs/builtins.css | 1 +
tests/outputs_numbered/builtins.css | 17 +++++++++--------
4 files changed, 14 insertions(+), 10 deletions(-)
diff --git a/src/Compiler.php b/src/Compiler.php
index 4fc0bade..044fff34 100644
--- a/src/Compiler.php
+++ b/src/Compiler.php
@@ -4746,7 +4746,7 @@ protected function libStrLength($args)
protected function libStrSlice($args)
{
if ($args[2][1] == 0) {
- return self::$emptyString;
+ return self::$null;
}
$string = $this->coerceString($args[0]);
@@ -4755,7 +4755,7 @@ protected function libStrSlice($args)
$start = (int) $args[1][1] ?: 1;
$end = (int) $args[2][1];
- $string[2] = array(substr($stringContent, $start - 1, $end < 0 ? $end : $end - $start + 1));
+ $string[2] = array(substr($stringContent, $start - 1, ($end < 0 ? $end : $end - $start) + 1));
return $string;
}
diff --git a/tests/inputs/builtins.scss b/tests/inputs/builtins.scss
index 07a571c7..3c898a30 100644
--- a/tests/inputs/builtins.scss
+++ b/tests/inputs/builtins.scss
@@ -80,6 +80,8 @@
color: str_insert(string, insert, 2);
color: str_length(string);
color: str_slice(string, 2, 4);
+ color: str-slice(string, 2, 0);
+ color: str-slice(string, 2, -2);
color: to_lower_case('StRiNg');
color: to_upper_case(StRiNg);
}
diff --git a/tests/outputs/builtins.css b/tests/outputs/builtins.css
index 811700b7..ff6f6f9c 100644
--- a/tests/outputs/builtins.css
+++ b/tests/outputs/builtins.css
@@ -55,6 +55,7 @@
color: sinserttring;
color: 6;
color: tri;
+ color: trin;
color: 'string';
color: STRING; }
diff --git a/tests/outputs_numbered/builtins.css b/tests/outputs_numbered/builtins.css
index a256ec0f..d0e22471 100644
--- a/tests/outputs_numbered/builtins.css
+++ b/tests/outputs_numbered/builtins.css
@@ -56,9 +56,10 @@
color: sinserttring;
color: 6;
color: tri;
+ color: trin;
color: 'string';
color: STRING; }
-/* line 87, inputs/builtins.scss */
+/* line 89, inputs/builtins.scss */
#number {
color: 250%;
color: 3;
@@ -69,7 +70,7 @@
width: 200%;
bottom: 10px;
padding: 3em 1in 96px 72pt; }
-/* line 100, inputs/builtins.scss */
+/* line 102, inputs/builtins.scss */
#list {
len: 3;
len: 1;
@@ -91,7 +92,7 @@
cool: great job one two three;
zip: 1px solid, 2px dashed;
zip: 1px solid red, 2px dashed green; }
-/* line 136, inputs/builtins.scss */
+/* line 138, inputs/builtins.scss */
#introspection {
t: number;
t: string;
@@ -111,31 +112,31 @@
c: true;
c: false;
c: true; }
-/* line 160, inputs/builtins.scss */
+/* line 162, inputs/builtins.scss */
#if {
color: yes;
color: no;
color: yes;
color: yes; }
-/* line 167, inputs/builtins.scss */
+/* line 169, inputs/builtins.scss */
.transparent {
r: 0;
g: 0;
b: 0;
a: 0; }
-/* line 174, inputs/builtins.scss */
+/* line 176, inputs/builtins.scss */
.alpha {
a: 1;
a: 1;
a: 1;
a: 0.5;
a: alpha(currentColor); }
-/* line 183, inputs/builtins.scss */
+/* line 185, inputs/builtins.scss */
#exists {
a: true;
b: true;
c: false; }
-/* line 190, inputs/builtins.scss */
+/* line 192, inputs/builtins.scss */
div.call-tests {
a: #0a64ff;
c: b; }
From 1cbf6723ae5e991a3f919b3b5ee98a49b461f855 Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Thu, 29 Oct 2015 13:19:33 -0400
Subject: [PATCH 142/534] refs #260 - output literal string instead of throwing
exception
---
src/Compiler.php | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/Compiler.php b/src/Compiler.php
index 044fff34..3acc1f05 100644
--- a/src/Compiler.php
+++ b/src/Compiler.php
@@ -2067,7 +2067,7 @@ protected function opSubNumberNumber($left, $right)
protected function opDivNumberNumber($left, $right)
{
if ($right[1] == 0) {
- $this->throwError('Division by zero');
+ return array('string', '', $left[1] . $left[2] . '/' . $right[1] . $right[2]);
}
return array('number', $left[1] / $right[1], $left[2]);
From 237644f1d5f53643a5872326b534778769c755c3 Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Thu, 29 Oct 2015 23:29:12 -0400
Subject: [PATCH 143/534] refs #260 update unit tests
---
src/Compiler.php | 4 ++--
tests/ExceptionTest.php | 6 ------
2 files changed, 2 insertions(+), 8 deletions(-)
diff --git a/src/Compiler.php b/src/Compiler.php
index 3acc1f05..09918cf8 100644
--- a/src/Compiler.php
+++ b/src/Compiler.php
@@ -1984,7 +1984,7 @@ public function normalizeValue($value)
return $value;
case 'string':
- return array($type, '"', $this->compileStringContent($value));
+ return array($type, '"', array($this->compileStringContent($value)));
case 'number':
return $this->normalizeNumber($value);
@@ -2067,7 +2067,7 @@ protected function opSubNumberNumber($left, $right)
protected function opDivNumberNumber($left, $right)
{
if ($right[1] == 0) {
- return array('string', '', $left[1] . $left[2] . '/' . $right[1] . $right[2]);
+ return array('string', '', array($left[1] . $left[2] . '/' . $right[1] . $right[2]));
}
return array('number', $left[1] / $right[1], $left[2]);
diff --git a/tests/ExceptionTest.php b/tests/ExceptionTest.php
index 12ec165f..4df1bae3 100644
--- a/tests/ExceptionTest.php
+++ b/tests/ExceptionTest.php
@@ -71,12 +71,6 @@ public function provideScss()
'color: Can\'t divide by zero'
),
array(<<<'END_OF_SCSS'
-.test { left: 300px/0; }
-END_OF_SCSS
- ,
- 'Division by zero'
- ),
- array(<<<'END_OF_SCSS'
.test {
@include foo();
}
From 35999817cf080c724635fd89714c914dd68fb1d6 Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Sat, 24 Oct 2015 18:18:12 -0400
Subject: [PATCH 144/534] Add scope tests from #367
---
tests/inputs/content.scss | 18 ++++++++++++++++++
tests/outputs/content.css | 3 +++
tests/outputs_numbered/content.css | 3 +++
3 files changed, 24 insertions(+)
diff --git a/tests/inputs/content.scss b/tests/inputs/content.scss
index a56acae3..7fef7800 100644
--- a/tests/inputs/content.scss
+++ b/tests/inputs/content.scss
@@ -79,3 +79,21 @@ $color: white;
background-image: url(/logo.gif);
}
}
+
+@mixin foo {
+ @content;
+}
+
+@mixin bar {
+ @content;
+}
+
+A {
+ @include foo {
+ $top: 10px;
+
+ @include bar {
+ top: $top;
+ }
+ }
+}
diff --git a/tests/outputs/content.css b/tests/outputs/content.css
index 89a1ad9e..93ed1372 100644
--- a/tests/outputs/content.css
+++ b/tests/outputs/content.css
@@ -30,3 +30,6 @@
* html * body #logo {
background-image: url(/logo.gif); }
+
+A {
+ top: 10px; }
diff --git a/tests/outputs_numbered/content.css b/tests/outputs_numbered/content.css
index 7948df35..ace5a98a 100644
--- a/tests/outputs_numbered/content.css
+++ b/tests/outputs_numbered/content.css
@@ -39,3 +39,6 @@
/* line 78, inputs/content.scss */
* html * body #logo {
background-image: url(/logo.gif); }
+/* line 91, inputs/content.scss */
+A {
+ top: 10px; }
From 09cd9403ae28df53936940865ae34b022e4726be Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Mon, 26 Oct 2015 11:23:29 -0400
Subject: [PATCH 145/534] Add scope tests from #365
---
tests/inputs/functions.scss | 19 +++++++++++++++++++
tests/outputs/functions.css | 6 ++++++
tests/outputs_numbered/functions.css | 6 ++++++
3 files changed, 31 insertions(+)
diff --git a/tests/inputs/functions.scss b/tests/inputs/functions.scss
index c0204040..4886a6e5 100644
--- a/tests/inputs/functions.scss
+++ b/tests/inputs/functions.scss
@@ -95,3 +95,22 @@ div {
p{
color: test("a", "s", "d", "f");
}
+
+@function test-function() {
+ $str: 'test-function';
+ @return $str;
+}
+
+@mixin test-mixin {
+ $str: 'test-mixin';
+ display: $str;
+ $new-bp: test-function();
+ display: $str;
+}
+
+$str: 'global';
+.test{
+ display: $str;
+ @include test-mixin;
+ display: $str;
+}
diff --git a/tests/outputs/functions.css b/tests/outputs/functions.css
index a0130b62..9604accb 100644
--- a/tests/outputs/functions.css
+++ b/tests/outputs/functions.css
@@ -26,3 +26,9 @@ div {
p {
color: arglist; }
+
+.test {
+ display: 'global';
+ display: 'test-mixin';
+ display: 'test-mixin';
+ display: 'global'; }
diff --git a/tests/outputs_numbered/functions.css b/tests/outputs_numbered/functions.css
index 8fdcdecc..4949511a 100644
--- a/tests/outputs_numbered/functions.css
+++ b/tests/outputs_numbered/functions.css
@@ -28,3 +28,9 @@ div {
/* line 95, inputs/functions.scss */
p {
color: arglist; }
+/* line 112, inputs/functions.scss */
+.test {
+ display: 'global';
+ display: 'test-mixin';
+ display: 'test-mixin';
+ display: 'global'; }
From 1e1b0be6d9d546384cf9e81fcabd887d57e4ff27 Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Fri, 30 Oct 2015 13:49:01 -0400
Subject: [PATCH 146/534] fixes #295, #365, #367 - multiple scope compatibility
issues
---
src/Compiler.php | 55 ++++++++++++++++++++++++++++++------------------
1 file changed, 35 insertions(+), 20 deletions(-)
diff --git a/src/Compiler.php b/src/Compiler.php
index 09918cf8..ba21a31b 100644
--- a/src/Compiler.php
+++ b/src/Compiler.php
@@ -171,6 +171,7 @@ public function compile($code, $path = null)
$this->sourceIndex = null;
$this->env = null;
$this->scope = null;
+ $this->storeEnv = null;
$this->stderr = fopen('php://stderr', 'w');
$this->parser = $this->parserFactory($path);
@@ -280,7 +281,7 @@ protected function compileRoot($rootBlock)
{
$this->rootBlock = $this->scope = $this->makeOutputBlock('root');
- $this->compileChildren($rootBlock->children, $this->scope);
+ $this->compileChildrenNoReturn($rootBlock->children, $this->scope);
$this->flattenSelectors($this->scope);
}
@@ -534,7 +535,7 @@ protected function compileMedia($media)
$media->children = array(array('block', $wrapped));
}
- $this->compileChildren($media->children, $this->scope);
+ $this->compileChildrenNoReturn($media->children, $this->scope);
$this->scope = $this->scope->parent;
}
@@ -828,7 +829,7 @@ protected function compileKeyframeBlock($block, $selectors)
$this->scope->depth = 1;
$this->scope->parent->children[] = $this->scope;
- $this->compileChildren($block->children, $this->scope);
+ $this->compileChildrenNoReturn($block->children, $this->scope);
$this->scope = $this->scope->parent;
$this->env = $this->extractEnv($envs);
@@ -849,7 +850,7 @@ protected function compileNestedBlock($block, $selectors)
$this->scope = $this->makeOutputBlock($block->type, $selectors);
$this->scope->parent->children[] = $this->scope;
- $this->compileChildren($block->children, $this->scope);
+ $this->compileChildrenNoReturn($block->children, $this->scope);
$this->scope = $this->scope->parent;
@@ -908,7 +909,7 @@ protected function compileBlock($block)
if (count($block->children)) {
$out->selectors = $this->multiplySelectors($env);
- $this->compileChildren($block->children, $out);
+ $this->compileChildrenNoReturn($block->children, $out);
}
$this->formatter->stripSemicolon($out->lines);
@@ -1126,7 +1127,7 @@ protected function hasSelectorPlaceholder($selector)
}
/**
- * Compile children
+ * Compile children and return result
*
* @param array $stms
* @param \stdClass $out
@@ -1144,6 +1145,25 @@ protected function compileChildren($stms, $out)
}
}
+ /**
+ * Compile children and throw exception if unexpected @return
+ *
+ * @param array $stms
+ * @param \stdClass $out
+ *
+ * @throws \Exception
+ */
+ protected function compileChildrenNoReturn($stms, $out)
+ {
+ foreach ($stms as $stm) {
+ $ret = $this->compileChild($stm, $out);
+
+ if (isset($ret)) {
+ $this->throwError('@return may only be used within a function');
+ }
+ }
+ }
+
/**
* Compile media query
*
@@ -1567,7 +1587,7 @@ protected function compileChild($child, $out)
$prefixed[] = $child;
}
- $this->compileChildren($prefixed, $out);
+ $this->compileChildrenNoReturn($prefixed, $out);
break;
case 'include':
@@ -1587,7 +1607,7 @@ protected function compileChild($child, $out)
$this->env->depth--;
if (isset($content)) {
- $content->scope = $callingScope;
+ $content->scope = $this->storeEnv ? $this->storeEnv : $callingScope;
$this->setRaw(self::$namespaces['special'] . 'content', $content, $this->getStoreEnv());
}
@@ -1598,9 +1618,7 @@ protected function compileChild($child, $out)
$this->env->marker = 'mixin';
- foreach ($mixin->children as $child) {
- $this->compileChild($child, $out);
- }
+ $this->compileChildrenNoReturn($mixin->children, $out);
$this->popEnv();
break;
@@ -1616,14 +1634,12 @@ protected function compileChild($child, $out)
break;
}
+ $storeEnv = $this->storeEnv;
$this->storeEnv = $content->scope;
- foreach ($content->children as $child) {
- $this->compileChild($child, $out);
- }
-
- $this->storeEnv = null;
+ $this->compileChildrenNoReturn($content->children, $out);
+ $this->storeEnv = $storeEnv;
break;
case 'debug':
@@ -1917,6 +1933,8 @@ protected function reduce($value, $inExp = false)
'children' => array(),
);
+ $this->env->marker = 'function';
+
$ret = $this->compileChildren($func->children, $tmp);
$this->popEnv();
@@ -2741,10 +2759,7 @@ protected function pushEnv($block = null)
*/
protected function popEnv()
{
- $env = $this->env;
$this->env = $this->env->parent;
-
- return $env;
}
/**
@@ -3096,7 +3111,7 @@ protected function importFile($path, $out)
$pi = pathinfo($path);
array_unshift($this->importPaths, $pi['dirname']);
- $this->compileChildren($tree->children, $out);
+ $this->compileChildrenNoReturn($tree->children, $out);
array_shift($this->importPaths);
}
From 59112355fa985c8b420cd3320d0d12e88112969e Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Fri, 30 Oct 2015 14:31:40 -0400
Subject: [PATCH 147/534] Compiler: refactor to use getStoreEnv() method
---
src/Compiler.php | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/Compiler.php b/src/Compiler.php
index ba21a31b..3958470f 100644
--- a/src/Compiler.php
+++ b/src/Compiler.php
@@ -1600,14 +1600,14 @@ protected function compileChild($child, $out)
$this->throwError("Undefined mixin $name");
}
- $callingScope = $this->env;
+ $callingScope = $this->getStoreEnv();
// push scope, apply args
$this->pushEnv();
$this->env->depth--;
if (isset($content)) {
- $content->scope = $this->storeEnv ? $this->storeEnv : $callingScope;
+ $content->scope = $callingScope;
$this->setRaw(self::$namespaces['special'] . 'content', $content, $this->getStoreEnv());
}
From 6118d5fff7df236fdb9336a3953f23c2cac9e482 Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Thu, 5 Nov 2015 10:50:26 -0500
Subject: [PATCH 148/534] refactor fncall
---
src/Compiler.php | 97 +++++++++++++++++++++++++++---------------------
1 file changed, 55 insertions(+), 42 deletions(-)
diff --git a/src/Compiler.php b/src/Compiler.php
index 3958470f..dd1d7c2d 100644
--- a/src/Compiler.php
+++ b/src/Compiler.php
@@ -1916,51 +1916,64 @@ protected function reduce($value, $inExp = false)
case 'fncall':
list(, $name, $argValues) = $value;
- // user defined function?
- $func = $this->get(self::$namespaces['function'] . $name, false);
+ return $this->fncall($name, $argValues);
- if ($func) {
- $this->pushEnv();
+ default:
+ return $value;
+ }
+ }
- // set the args
- if (isset($func->args)) {
- $this->applyArguments($func->args, $argValues);
- }
+ /**
+ * Function caller
+ *
+ * @param string $name
+ * @param array $argValues
+ *
+ * @return array|null
+ */
+ private function fncall($name, $argValues)
+ {
+ // user defined function?
+ $func = $this->get(self::$namespaces['function'] . $name, false);
- // throw away lines and children
- $tmp = (object) array(
- 'lines' => array(),
- 'children' => array(),
- );
+ if ($func) {
+ $this->pushEnv();
- $this->env->marker = 'function';
+ // set the args
+ if (isset($func->args)) {
+ $this->applyArguments($func->args, $argValues);
+ }
- $ret = $this->compileChildren($func->children, $tmp);
+ // throw away lines and children
+ $tmp = (object) array(
+ 'lines' => array(),
+ 'children' => array(),
+ );
- $this->popEnv();
+ $this->env->marker = 'function';
- return ! isset($ret) ? self::$defaultValue : $ret;
- }
+ $ret = $this->compileChildren($func->children, $tmp);
- // built in function
- if ($this->callBuiltin($name, $argValues, $returnValue)) {
- return $returnValue;
- }
+ $this->popEnv();
- // need to flatten the arguments into a list
- $listArgs = array();
+ return ! isset($ret) ? self::$defaultValue : $ret;
+ }
- foreach ((array)$argValues as $arg) {
- if (empty($arg[0])) {
- $listArgs[] = $this->reduce($arg[1]);
- }
- }
+ // built in function
+ if ($this->callBuiltin($name, $argValues, $returnValue)) {
+ return $returnValue;
+ }
- return array('function', $name, array('list', ',', $listArgs));
+ // need to flatten the arguments into a list
+ $listArgs = array();
- default:
- return $value;
+ foreach ((array) $argValues as $arg) {
+ if (empty($arg[0])) {
+ $listArgs[] = $this->reduce($arg[1]);
+ }
}
+
+ return array('function', $name, array('list', ',', $listArgs));
}
/**
@@ -3010,7 +3023,7 @@ public function addImportPath($path)
*/
public function setImportPaths($path)
{
- $this->importPaths = (array)$path;
+ $this->importPaths = (array) $path;
}
/**
@@ -3150,7 +3163,7 @@ public function findImport($url)
}
} elseif (is_callable($dir)) {
// check custom callback for import path
- $file = call_user_func($dir, $url, $this);
+ $file = call_user_func($dir, $url);
if ($file !== null) {
return $file;
@@ -3239,7 +3252,7 @@ protected function callBuiltin($name, $args, &$returnValue)
}
}
- $returnValue = call_user_func($fn, $args, $this);
+ $returnValue = call_user_func($fn, $args);
} else {
$f = $this->getBuiltinFunction($name);
@@ -3255,17 +3268,17 @@ protected function callBuiltin($name, $args, &$returnValue)
}
}
- $returnValue = call_user_func($f, $sorted, $this);
+ $returnValue = call_user_func($f, $sorted);
}
}
- if (isset($returnValue)) {
- $returnValue = $this->coerceValue($returnValue);
-
- return true;
+ if (! isset($returnValue)) {
+ return false;
}
- return false;
+ $returnValue = $this->coerceValue($returnValue);
+
+ return true;
}
/**
@@ -3329,7 +3342,7 @@ protected function sortArgs($prototype, $args)
$set = false;
- foreach ((array)$names as $name) {
+ foreach ((array) $names as $name) {
if (isset($keyArgs[$name])) {
$finalArgs[] = $keyArgs[$name];
$set = true;
From fb09e949c709f39cf6de682c864665006ed12c22 Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Thu, 5 Nov 2015 10:50:38 -0500
Subject: [PATCH 149/534] add kwargs unit test
---
tests/inputs/builtins.scss | 2 +-
tests/outputs/builtins.css | 1 +
tests/outputs_numbered/builtins.css | 1 +
3 files changed, 3 insertions(+), 1 deletion(-)
diff --git a/tests/inputs/builtins.scss b/tests/inputs/builtins.scss
index 3c898a30..7f54d41e 100644
--- a/tests/inputs/builtins.scss
+++ b/tests/inputs/builtins.scss
@@ -191,6 +191,6 @@ $a-false-value: false;
$fn: nth;
div.call-tests {
a: call(rgb, 10, 100, 255);
- //b: call(scale-color, #0a64ff, $lightness: -10%);
+ b: call(scale-color, #0a64ff, $lightness: -10%);
c: call($fn, (a b c), 2);
}
diff --git a/tests/outputs/builtins.css b/tests/outputs/builtins.css
index ff6f6f9c..f7bc1f12 100644
--- a/tests/outputs/builtins.css
+++ b/tests/outputs/builtins.css
@@ -138,4 +138,5 @@
div.call-tests {
a: #0a64ff;
+ b: #0058ef;
c: b; }
diff --git a/tests/outputs_numbered/builtins.css b/tests/outputs_numbered/builtins.css
index d0e22471..08cbb0be 100644
--- a/tests/outputs_numbered/builtins.css
+++ b/tests/outputs_numbered/builtins.css
@@ -139,4 +139,5 @@
/* line 192, inputs/builtins.scss */
div.call-tests {
a: #0a64ff;
+ b: #0058ef;
c: b; }
From ee89fefa5f1954ba5795d2c8292c47021b45054e Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Thu, 5 Nov 2015 12:23:09 -0500
Subject: [PATCH 150/534] Further refactoring of fncall
---
src/Compiler.php | 83 ++++++++++++++++++++++++++++++------------------
1 file changed, 52 insertions(+), 31 deletions(-)
diff --git a/src/Compiler.php b/src/Compiler.php
index dd1d7c2d..e05160d3 100644
--- a/src/Compiler.php
+++ b/src/Compiler.php
@@ -1933,38 +1933,17 @@ protected function reduce($value, $inExp = false)
*/
private function fncall($name, $argValues)
{
- // user defined function?
- $func = $this->get(self::$namespaces['function'] . $name, false);
-
- if ($func) {
- $this->pushEnv();
-
- // set the args
- if (isset($func->args)) {
- $this->applyArguments($func->args, $argValues);
- }
-
- // throw away lines and children
- $tmp = (object) array(
- 'lines' => array(),
- 'children' => array(),
- );
-
- $this->env->marker = 'function';
-
- $ret = $this->compileChildren($func->children, $tmp);
-
- $this->popEnv();
-
- return ! isset($ret) ? self::$defaultValue : $ret;
+ // SCSS @function
+ if ($this->callScssFunction($name, $argValues, $returnValue)) {
+ return $returnValue;
}
- // built in function
- if ($this->callBuiltin($name, $argValues, $returnValue)) {
+ // native PHP functions
+ if ($this->callNativeFunction($name, $argValues, $returnValue)) {
return $returnValue;
}
- // need to flatten the arguments into a list
+ // for CSS functions, simply flatten the arguments into a list
$listArgs = array();
foreach ((array) $argValues as $arg) {
@@ -3069,10 +3048,11 @@ public function setLineNumberStyle($lineNumberStyle)
*
* @param string $name
* @param callable $func
+ * @param array $prototype
*/
- public function registerFunction($name, $func)
+ public function registerFunction($name, $func, $prototype = null)
{
- $this->userFunctions[$this->normalizeName($name)] = $func;
+ $this->userFunctions[$this->normalizeName($name)] = array($func, $prototype);
}
/**
@@ -3228,6 +3208,47 @@ protected function fileExists($name)
return is_file($name);
}
+ /**
+ * Call SCSS @function
+ *
+ * @param string $name
+ * @param array $args
+ * @param array $returnValue
+ *
+ * @return boolean Returns true if returnValue is set; otherwise, false
+ */
+ protected function callScssFunction($name, $argValues, &$returnValue)
+ {
+ $func = $this->get(self::$namespaces['function'] . $name, false);
+
+ if (! $func) {
+ return false;
+ }
+
+ $this->pushEnv();
+
+ // set the args
+ if (isset($func->args)) {
+ $this->applyArguments($func->args, $argValues);
+ }
+
+ // throw away lines and children
+ $tmp = (object) array(
+ 'lines' => array(),
+ 'children' => array(),
+ );
+
+ $this->env->marker = 'function';
+
+ $ret = $this->compileChildren($func->children, $tmp);
+
+ $this->popEnv();
+
+ $returnValue = ! isset($ret) ? self::$defaultValue : $ret;
+
+ return true;
+ }
+
/**
* Call built-in and registered (PHP) functions
*
@@ -3237,14 +3258,14 @@ protected function fileExists($name)
*
* @return boolean Returns true if returnValue is set; otherwise, false
*/
- protected function callBuiltin($name, $args, &$returnValue)
+ protected function callNativeFunction($name, $args, &$returnValue)
{
// try a lib function
$name = $this->normalizeName($name);
if (isset($this->userFunctions[$name])) {
// see if we can find a user function
- $fn = $this->userFunctions[$name];
+ list($fn, $prototype) = $this->userFunctions[$name];
if ($name !== 'if' && $name !== 'call') {
foreach ($args as &$val) {
From d37386bb4bfdc248ea6c0a9417becdf7b63f67b1 Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Thu, 5 Nov 2015 13:10:31 -0500
Subject: [PATCH 151/534] Refactoring callNativeFunction
---
src/Compiler.php | 58 ++++++++++++++++--------------------------------
1 file changed, 19 insertions(+), 39 deletions(-)
diff --git a/src/Compiler.php b/src/Compiler.php
index e05160d3..fabc33c6 100644
--- a/src/Compiler.php
+++ b/src/Compiler.php
@@ -3265,34 +3265,24 @@ protected function callNativeFunction($name, $args, &$returnValue)
if (isset($this->userFunctions[$name])) {
// see if we can find a user function
- list($fn, $prototype) = $this->userFunctions[$name];
-
- if ($name !== 'if' && $name !== 'call') {
- foreach ($args as &$val) {
- $val = $this->reduce($val[1], true);
- }
- }
-
- $returnValue = call_user_func($fn, $args);
+ list($f, $prototype) = $this->userFunctions[$name];
+ } elseif (($f = $this->getBuiltinFunction($name)) && is_callable($f)) {
+ $libName = $f[1];
+ $prototype = isset(self::$$libName) ? self::$$libName : null;
} else {
- $f = $this->getBuiltinFunction($name);
-
- if (is_callable($f)) {
- $libName = $f[1];
-
- $prototype = isset(self::$$libName) ? self::$$libName : null;
- $sorted = $this->sortArgs($prototype, $args);
+ return false;
+ }
- if ($name !== 'if' && $name !== 'call') {
- foreach ($sorted as &$val) {
- $val = $this->reduce($val, true);
- }
- }
+ list($sorted, $kwargs) = $this->sortArgs($prototype, $args);
- $returnValue = call_user_func($f, $sorted);
+ if ($name !== 'if' && $name !== 'call') {
+ foreach ($sorted as &$val) {
+ $val = $this->reduce($val, true);
}
}
+ $returnValue = call_user_func($f, $sorted, $kwargs);
+
if (! isset($returnValue)) {
return false;
}
@@ -3337,6 +3327,7 @@ protected function sortArgs($prototype, $args)
$keyArgs = array();
$posArgs = array();
+ // separate positional and keyword arguments
foreach ($args as $arg) {
list($key, $value) = $arg;
@@ -3350,33 +3341,22 @@ protected function sortArgs($prototype, $args)
}
if (! isset($prototype)) {
- return $posArgs;
+ return array($posArgs, $keyArgs);
}
- $finalArgs = array();
+ // copy positional args
+ $finalArgs = array_pad($posArgs, count($prototype), null);
+ // overwrite positional args with keyword args
foreach ($prototype as $i => $names) {
- if (isset($posArgs[$i])) {
- $finalArgs[] = $posArgs[$i];
- continue;
- }
-
- $set = false;
-
foreach ((array) $names as $name) {
if (isset($keyArgs[$name])) {
- $finalArgs[] = $keyArgs[$name];
- $set = true;
- break;
+ $finalArgs[$i] = $keyArgs[$name];
}
}
-
- if (! $set) {
- $finalArgs[] = null;
- }
}
- return $finalArgs;
+ return array($finalArgs, $keyArgs);
}
/**
From e641a274a76a58e4e23126b90cd99f3eb88e5178 Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Thu, 5 Nov 2015 13:54:14 -0500
Subject: [PATCH 152/534] Pass kwargs to built-ins
---
src/Compiler.php | 26 ++++++++++++++------------
1 file changed, 14 insertions(+), 12 deletions(-)
diff --git a/src/Compiler.php b/src/Compiler.php
index fabc33c6..baebdf35 100644
--- a/src/Compiler.php
+++ b/src/Compiler.php
@@ -3873,22 +3873,24 @@ public function toRGB($hue, $saturation, $lightness)
// Built in functions
//protected static $libCall = array('name', 'args...');
- protected function libCall($args)
+ protected function libCall($args, $kwargs)
{
$name = $this->compileStringContent($this->coerceString($this->reduce(array_shift($args), true)));
- return $this->reduce(
- array(
- 'fncall',
- $name,
- array_map(
- function ($a) {
- return array(null, $a);
- },
- $args
- )
- )
+ $args = array_map(
+ function ($a) {
+ return array(null, $a, false);
+ },
+ $args
);
+
+ if (count($kwargs)) {
+ foreach ($kwargs as $key => $value) {
+ $args[] = array(array('var', $key), $value, false);
+ }
+ }
+
+ return $this->reduce(array('fncall', $name, $args));
}
protected static $libIf = array('condition', 'if-true', 'if-false');
From f8baeab695bcd55c99a086bb1a4f567f14866f67 Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Thu, 5 Nov 2015 14:03:42 -0500
Subject: [PATCH 153/534] fixes #143 - adds unit test for named arguments
passed to user registered function
---
tests/ApiTest.php | 16 ++++++++++++++++
1 file changed, 16 insertions(+)
diff --git a/tests/ApiTest.php b/tests/ApiTest.php
index c4f18ba7..ca5f3a28 100644
--- a/tests/ApiTest.php
+++ b/tests/ApiTest.php
@@ -38,6 +38,22 @@ public function testUserFunction()
);
}
+ public function testUserFunctionKwargs()
+ {
+ $this->scss->registerFunction(
+ 'divide',
+ function ($args, $kwargs) {
+ return $kwargs['dividend'][1] / $kwargs['divisor'][1];
+ },
+ array('dividend', 'divisor')
+ );
+
+ $this->assertEquals(
+ 'result: 15;',
+ $this->compile('result: divide($divisor: 2, $dividend: 30);')
+ );
+ }
+
public function testImportMissing()
{
$this->assertEquals(
From 22921dfb0b72b06991eff07c4a8a68117f363a31 Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Thu, 5 Nov 2015 14:54:00 -0500
Subject: [PATCH 154/534] update docblocks
---
src/Colors.php | 2 ++
src/Formatter.php | 11 +++++++++++
2 files changed, 13 insertions(+)
diff --git a/src/Colors.php b/src/Colors.php
index dd32be21..0227fbe0 100644
--- a/src/Colors.php
+++ b/src/Colors.php
@@ -22,6 +22,8 @@ class Colors
* CSS Colors
*
* @see http://www.w3.org/TR/css3-color
+ *
+ * @var array
*/
public static $cssColors = array(
'aliceblue' => '240,248,255',
diff --git a/src/Formatter.php b/src/Formatter.php
index 90f79e90..bf62c4c6 100644
--- a/src/Formatter.php
+++ b/src/Formatter.php
@@ -53,6 +53,11 @@ abstract class Formatter
*/
public $assignSeparator;
+ /**
+ * Initialize formatter
+ *
+ * @api
+ */
abstract public function __construct();
/**
@@ -68,6 +73,8 @@ protected function indentStr()
/**
* Return property assignment
*
+ * @api
+ *
* @param string $name
* @param mixed $value
*
@@ -81,6 +88,8 @@ public function property($name, $value)
/**
* Strip semi-colon appended by property(); it's a separator, not a terminator
*
+ * @api
+ *
* @param array $lines
*/
public function stripSemicolon(&$lines)
@@ -172,6 +181,8 @@ protected function block($block)
/**
* Entry point to formatting a block
*
+ * @api
+ *
* @param \stdClass $block An abstract syntax tree
*
* @return string
From eb5f43fc140b49d4209e8df7852720dcfec9efca Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Thu, 5 Nov 2015 18:47:37 -0500
Subject: [PATCH 155/534] Convert stdClass to more explicit abstractions
---
scss.inc.php | 3 +
src/Block.php | 72 +++++++++++++
src/Compiler.php | 196 +++++++++++++++++-----------------
src/Compiler/Environment.php | 42 ++++++++
src/Formatter.php | 22 ++--
src/Formatter/Compressed.php | 5 +-
src/Formatter/Crunched.php | 3 +-
src/Formatter/Debug.php | 9 +-
src/Formatter/Expanded.php | 3 +-
src/Formatter/Nested.php | 13 +--
src/Formatter/OutputBlock.php | 50 +++++++++
src/Parser.php | 11 +-
12 files changed, 302 insertions(+), 127 deletions(-)
create mode 100644 src/Block.php
create mode 100644 src/Compiler/Environment.php
create mode 100644 src/Formatter/OutputBlock.php
diff --git a/scss.inc.php b/scss.inc.php
index da641f7c..4c142973 100644
--- a/scss.inc.php
+++ b/scss.inc.php
@@ -5,8 +5,10 @@
if (! class_exists('scssc', false)) {
include_once __DIR__ . '/src/Base/Range.php';
+ include_once __DIR__ . '/src/Block.php';
include_once __DIR__ . '/src/Colors.php';
include_once __DIR__ . '/src/Compiler.php';
+ include_once __DIR__ . '/src/Compiler/Environment.php';
include_once __DIR__ . '/src/Formatter.php';
include_once __DIR__ . '/src/Formatter/Compact.php';
include_once __DIR__ . '/src/Formatter/Compressed.php';
@@ -14,6 +16,7 @@
include_once __DIR__ . '/src/Formatter/Debug.php';
include_once __DIR__ . '/src/Formatter/Expanded.php';
include_once __DIR__ . '/src/Formatter/Nested.php';
+ include_once __DIR__ . '/src/Formatter/OutputBlock.php';
include_once __DIR__ . '/src/Parser.php';
include_once __DIR__ . '/src/Util.php';
include_once __DIR__ . '/src/Version.php';
diff --git a/src/Block.php b/src/Block.php
new file mode 100644
index 00000000..9e3483ba
--- /dev/null
+++ b/src/Block.php
@@ -0,0 +1,72 @@
+
+ */
+class Block
+{
+ const T_MEDIA = 'media';
+ const T_MIXIN = 'mixin';
+ const T_INCLUDE = 'include';
+ const T_FUNCTION = 'function';
+ const T_EACH = 'each';
+ const T_WHILE = 'while';
+ const T_FOR = 'for';
+ const T_IF = 'if';
+ const T_ELSE = 'else';
+ const T_ELSEIF = 'elseif';
+ const T_DIRECTIVE = 'directive';
+ const T_NESTED_PROPERTY = 'nestedprop';
+ const T_BLOCK = 'block';
+ const T_ROOT = 'root';
+ const T_NULL = null;
+ const T_COMMENT = 'comment';
+
+ /**
+ * @var string
+ */
+ public $type;
+
+ /**
+ * @var \Leafo\ScssPhp\Block
+ */
+ public $parent;
+
+ /**
+ * @var integer
+ */
+ public $sourcePosition;
+
+ /**
+ * @var integer
+ */
+ public $sourceIndex;
+
+ /**
+ * @var array
+ */
+ public $selectors;
+
+ /**
+ * @var array
+ */
+ public $comments;
+
+ /**
+ * @var array
+ */
+ public $children;
+}
diff --git a/src/Compiler.php b/src/Compiler.php
index baebdf35..110f4c7b 100644
--- a/src/Compiler.php
+++ b/src/Compiler.php
@@ -12,7 +12,10 @@
namespace Leafo\ScssPhp;
use Leafo\ScssPhp\Base\Range;
+use Leafo\ScssPhp\Block;
use Leafo\ScssPhp\Colors;
+use Leafo\ScssPhp\Compiler\Environment;
+use Leafo\ScssPhp\Formatter\OutputBlock;
use Leafo\ScssPhp\Parser;
use Leafo\ScssPhp\Util;
@@ -257,17 +260,17 @@ protected function pushExtends($target, $origin)
* @param string $type
* @param array $selectors
*
- * @return \stdClass
+ * @return \Leafo\ScssPhp\Formatter\OutputBlock
*/
protected function makeOutputBlock($type, $selectors = null)
{
- $out = new \stdClass;
- $out->type = $type;
- $out->lines = array();
- $out->children = array();
- $out->parent = $this->scope;
+ $out = new OutputBlock;
+ $out->type = $type;
+ $out->lines = array();
+ $out->children = array();
+ $out->parent = $this->scope;
$out->selectors = $selectors;
- $out->depth = $this->env->depth;
+ $out->depth = $this->env->depth;
return $out;
}
@@ -275,9 +278,9 @@ protected function makeOutputBlock($type, $selectors = null)
/**
* Compile root
*
- * @param \stdClass $rootBlock
+ * @param \Leafo\ScssPhp\Block $rootBlock
*/
- protected function compileRoot($rootBlock)
+ protected function compileRoot(Block $rootBlock)
{
$this->rootBlock = $this->scope = $this->makeOutputBlock('root');
@@ -288,10 +291,10 @@ protected function compileRoot($rootBlock)
/**
* Flatten selectors
*
- * @param \stdClass $block
- * @parent string $parentKey
+ * @param \Leafo\ScssPhp\Formatter\OutputBlock $block
+ * @param string $parentKey
*/
- protected function flattenSelectors($block, $parentKey = null)
+ protected function flattenSelectors(OutputBlock $block, $parentKey = null)
{
if ($block->selectors) {
$selectors = array();
@@ -500,9 +503,9 @@ protected function combineSelectorSingle($base, $other)
/**
* Compile media
*
- * @param \stdClass $media
+ * @param \Leafo\ScssPhp\Block $media
*/
- protected function compileMedia($media)
+ protected function compileMedia(Block $media)
{
$this->pushEnv($media);
@@ -527,10 +530,9 @@ protected function compileMedia($media)
}
if ($needsWrap) {
- $wrapped = (object) array(
- 'selectors' => array(),
- 'children' => $media->children,
- );
+ $wrapped = new Block;
+ $wrapped->selectors = array();
+ $wrapped->children = $media->children;
$media->children = array(array('block', $wrapped));
}
@@ -546,11 +548,11 @@ protected function compileMedia($media)
/**
* Media parent
*
- * @param \stdClass $scope
+ * @param \Leafo\ScssPhp\Formatter\OutputBlock $scope
*
- * @return \stdClass
+ * @return \Leafo\ScssPhp\Formatter\OutputBlock
*/
- protected function mediaParent($scope)
+ protected function mediaParent(OutputBlock $scope)
{
while (! empty($scope->parent)) {
if (! empty($scope->type) && $scope->type !== 'media') {
@@ -566,9 +568,9 @@ protected function mediaParent($scope)
/**
* Compile directive
*
- * @param \stdClass $block
+ * @param \Leafo\ScssPhp\Block $block
*/
- protected function compileDirective($block)
+ protected function compileDirective(Block $block)
{
$s = '@' . $block->name;
@@ -586,9 +588,9 @@ protected function compileDirective($block)
/**
* Compile at-root
*
- * @param \stdClass $block
+ * @param \Leafo\ScssPhp\Block $block
*/
- protected function compileAtRoot($block)
+ protected function compileAtRoot(Block $block)
{
$env = $this->pushEnv($block);
$envs = $this->compactEnv($env);
@@ -596,14 +598,13 @@ protected function compileAtRoot($block)
// wrap inline selector
if ($block->selector) {
- $wrapped = (object) array(
- 'parent' => $block,
- 'sourcePosition' => $block->sourcePosition,
- 'sourceIndex' => $block->sourceIndex,
- 'selectors' => $block->selector,
- 'comments' => array(),
- 'children' => $block->children,
- );
+ $wrapped = new Block;
+ $wrapped->parent = $block;
+ $wrapped->sourcePosition = $block->sourcePosition;
+ $wrapped->sourceIndex = $block->sourceIndex;
+ $wrapped->selectors = $block->selector;
+ $wrapped->comments = array();
+ $wrapped->children = $block->children;
$block->children = array(array('block', $wrapped));
}
@@ -625,13 +626,13 @@ protected function compileAtRoot($block)
/**
* Splice parse tree
*
- * @param array $envs
- * @param \stdClass $block
- * @param integer $without
+ * @param array $envs
+ * @param \Leafo\ScssPhp\Block $block
+ * @param integer $without
*
- * @return \stdClass
+ * @return array
*/
- private function spliceTree($envs, $block, $without)
+ private function spliceTree($envs, Block $block, $without)
{
$newBlock = null;
@@ -665,7 +666,7 @@ private function spliceTree($envs, $block, $without)
continue;
}
- $b = new \stdClass;
+ $b = new Block;
if (isset($e->block->sourcePosition)) {
$b->sourcePosition = $e->block->sourcePosition;
@@ -779,7 +780,7 @@ private function compileWith($with)
* @param array $envs
* @param integer $without
*
- * @return \stdClass
+ * @return \Leafo\ScssPhp\Compiler\Environment
*/
private function filterWithout($envs, $without)
{
@@ -812,10 +813,10 @@ private function filterWithout($envs, $without)
/**
* Compile keyframe block
*
- * @param \stdClass $block
- * @param array $selectors
+ * @param \Leafo\ScssPhp\Block $block
+ * @param array $selectors
*/
- protected function compileKeyframeBlock($block, $selectors)
+ protected function compileKeyframeBlock(Block $block, $selectors)
{
$env = $this->pushEnv($block);
@@ -840,10 +841,10 @@ protected function compileKeyframeBlock($block, $selectors)
/**
* Compile nested block
*
- * @param \stdClass $block
- * @param array $selectors
+ * @param \Leafo\ScssPhp\Block $block
+ * @param array $selectors
*/
- protected function compileNestedBlock($block, $selectors)
+ protected function compileNestedBlock(Block $block, $selectors)
{
$this->pushEnv($block);
@@ -873,9 +874,9 @@ protected function compileNestedBlock($block, $selectors)
*
* @see Compiler::compileChild()
*
- * @param \stdClass $block
+ * @param \Leafo\ScssPhp\Block $block
*/
- protected function compileBlock($block)
+ protected function compileBlock(Block $block)
{
$env = $this->pushEnv($block);
$env->selectors = $this->evalSelectors($block->selectors);
@@ -1129,12 +1130,12 @@ protected function hasSelectorPlaceholder($selector)
/**
* Compile children and return result
*
- * @param array $stms
- * @param \stdClass $out
+ * @param array $stms
+ * @param \Leafo\ScssPhp\Formatter\OutputBlock $out
*
* @return array
*/
- protected function compileChildren($stms, $out)
+ protected function compileChildren($stms, OutputBlock $out)
{
foreach ($stms as $stm) {
$ret = $this->compileChild($stm, $out);
@@ -1148,12 +1149,12 @@ protected function compileChildren($stms, $out)
/**
* Compile children and throw exception if unexpected @return
*
- * @param array $stms
- * @param \stdClass $out
+ * @param array $stms
+ * @param \Leafo\ScssPhp\Formatter\OutputBlock $out
*
* @throws \Exception
*/
- protected function compileChildrenNoReturn($stms, $out)
+ protected function compileChildrenNoReturn($stms, OutputBlock $out)
{
foreach ($stms as $stm) {
$ret = $this->compileChild($stm, $out);
@@ -1349,12 +1350,12 @@ protected function compileImport($rawPath, $out)
/**
* Compile child; returns a value to halt execution
*
- * @param array $child
- * @param \stdClass $out
+ * @param array $child
+ * @param \Leafo\ScssPhp\Formatter\OutputBlock $out
*
* @return array
*/
- protected function compileChild($child, $out)
+ protected function compileChild($child, OutputBlock $out)
{
$this->sourceIndex = isset($child[Parser::SOURCE_INDEX]) ? $child[Parser::SOURCE_INDEX] : null;
$this->sourcePos = isset($child[Parser::SOURCE_POSITION]) ? $child[Parser::SOURCE_POSITION] : -1;
@@ -2582,11 +2583,11 @@ protected function extractInterpolation($list)
/**
* Find the final set of selectors
*
- * @param \stdClass $env
+ * @param \Leafo\ScssPhp\Compiler\Environment $env
*
* @return array
*/
- protected function multiplySelectors($env)
+ protected function multiplySelectors(Environment $env)
{
$envs = $this->compactEnv($env);
$selectors = array();
@@ -2655,12 +2656,12 @@ protected function joinSelectors($parent, $child)
/**
* Multiply media
*
- * @param \stdClass $env
- * @param array $childQueries
+ * @param \Leafo\ScssPhp\Compiler\Environment $env
+ * @param array $childQueries
*
* @return array
*/
- protected function multiplyMedia($env, $childQueries = null)
+ protected function multiplyMedia(Environment $env = null, $childQueries = null)
{
if (! isset($env) ||
! empty($env->block->type) && $env->block->type !== 'media'
@@ -2696,11 +2697,11 @@ protected function multiplyMedia($env, $childQueries = null)
/**
* Convert env linked list to stack
*
- * @param \stdClass $env
+ * @param \Leafo\ScssPhp\Compiler\Environment $env
*
* @return array
*/
- private function compactEnv($env)
+ private function compactEnv(Environment $env)
{
for ($envs = array(); $env; $env = $env->parent) {
$envs[] = $env;
@@ -2714,7 +2715,7 @@ private function compactEnv($env)
*
* @param array $envs
*
- * @return \stdClass
+ * @return \Leafo\ScssPhp\Compiler\Environment
*/
private function extractEnv($envs)
{
@@ -2729,17 +2730,17 @@ private function extractEnv($envs)
/**
* Push environment
*
- * @param \stdClass $block
+ * @param \Leafo\ScssPhp\Block $block
*
- * @return \stdClass
+ * @return \Leafo\ScssPhp\Compiler\Environment
*/
- protected function pushEnv($block = null)
+ protected function pushEnv(Block $block = null)
{
- $env = new \stdClass;
+ $env = new Environment;
$env->parent = $this->env;
- $env->store = array();
- $env->block = $block;
- $env->depth = isset($this->env->depth) ? $this->env->depth + 1 : 0;
+ $env->store = array();
+ $env->block = $block;
+ $env->depth = isset($this->env->depth) ? $this->env->depth + 1 : 0;
$this->env = $env;
@@ -2757,7 +2758,7 @@ protected function popEnv()
/**
* Get store environment
*
- * @return \stdClass
+ * @return \Leafo\ScssPhp\Compiler\Environment
*/
protected function getStoreEnv()
{
@@ -2767,12 +2768,12 @@ protected function getStoreEnv()
/**
* Set variable
*
- * @param string $name
- * @param mixed $value
- * @param boolean $shadow
- * @param \stdClass $env
+ * @param string $name
+ * @param mixed $value
+ * @param boolean $shadow
+ * @param \Leafo\ScssPhp\Compiler\Environment $env
*/
- protected function set($name, $value, $shadow = false, $env = null)
+ protected function set($name, $value, $shadow = false, Environment $env = null)
{
$name = $this->normalizeName($name);
@@ -2790,11 +2791,11 @@ protected function set($name, $value, $shadow = false, $env = null)
/**
* Set existing variable
*
- * @param string $name
- * @param mixed $value
- * @param \stdClass $env
+ * @param string $name
+ * @param mixed $value
+ * @param \Leafo\ScssPhp\Compiler\Environment $env
*/
- protected function setExisting($name, $value, $env)
+ protected function setExisting($name, $value, Environment $env)
{
$storeEnv = $env;
@@ -2824,11 +2825,11 @@ protected function setExisting($name, $value, $env)
/**
* Set raw variable
*
- * @param string $name
- * @param mixed $value
- * @param \stdClass $env
+ * @param string $name
+ * @param mixed $value
+ * @param \Leafo\ScssPhp\Compiler\Environment $env
*/
- protected function setRaw($name, $value, $env)
+ protected function setRaw($name, $value, Environment $env)
{
$env->store[$name] = $value;
}
@@ -2838,13 +2839,13 @@ protected function setRaw($name, $value, $env)
*
* @api
*
- * @param string $name
- * @param boolean $shouldThrow
- * @param \stdClass $env
+ * @param string $name
+ * @param boolean $shouldThrow
+ * @param \Leafo\ScssPhp\Compiler\Environment $env
*
* @return mixed
*/
- public function get($name, $shouldThrow = true, $env = null)
+ public function get($name, $shouldThrow = true, Environment $env = null)
{
$name = $this->normalizeName($name);
@@ -2881,12 +2882,12 @@ public function get($name, $shouldThrow = true, $env = null)
/**
* Has variable?
*
- * @param string $name
- * @param \stdClass $env
+ * @param string $name
+ * @param \Leafo\ScssPhp\Compiler\Environment $env
*
* @return boolean
*/
- protected function has($name, $env = null)
+ protected function has($name, Environment $env = null)
{
return $this->get($name, false, $env) !== null;
}
@@ -3233,10 +3234,9 @@ protected function callScssFunction($name, $argValues, &$returnValue)
}
// throw away lines and children
- $tmp = (object) array(
- 'lines' => array(),
- 'children' => array(),
- );
+ $tmp = new OutputBlock;
+ $tmp->lines = array();
+ $tmp->children = array();
$this->env->marker = 'function';
@@ -3371,7 +3371,7 @@ protected function applyArguments($argDef, $argValues)
{
$storeEnv = $this->getStoreEnv();
- $env = new \stdClass;
+ $env = new Environment;
$env->store = $storeEnv->store;
$hasVariable = false;
diff --git a/src/Compiler/Environment.php b/src/Compiler/Environment.php
new file mode 100644
index 00000000..f929c74c
--- /dev/null
+++ b/src/Compiler/Environment.php
@@ -0,0 +1,42 @@
+
+ */
+class Environment
+{
+ /**
+ * @var \Leafo\ScssPhp\Block
+ */
+ public $block;
+
+ /**
+ * @var \Leafo\ScssPhp\Compiler\Environment
+ */
+ public $parent;
+
+ /**
+ * @var array
+ */
+ public $store;
+
+ /**
+ * @var integer
+ */
+ public $depth;
+}
diff --git a/src/Formatter.php b/src/Formatter.php
index bf62c4c6..88b7d867 100644
--- a/src/Formatter.php
+++ b/src/Formatter.php
@@ -11,6 +11,8 @@
namespace Leafo\ScssPhp;
+use Leafo\ScssPhp\Formatter\OutputBlock;
+
/**
* SCSS base formatter
*
@@ -99,9 +101,9 @@ public function stripSemicolon(&$lines)
/**
* Output lines inside a block
*
- * @param \stdClass $block
+ * @param \Leafo\ScssPhp\Formatter\OutputBlock $block
*/
- protected function blockLines($block)
+ protected function blockLines(OutputBlock $block)
{
$inner = $this->indentStr();
@@ -117,9 +119,9 @@ protected function blockLines($block)
/**
* Output block selectors
*
- * @param \stdClass $block
+ * @param \Leafo\ScssPhp\Formatter\OutputBlock $block
*/
- protected function blockSelectors($block)
+ protected function blockSelectors(OutputBlock $block)
{
$inner = $this->indentStr();
@@ -131,9 +133,9 @@ protected function blockSelectors($block)
/**
* Output block children
*
- * @param \stdClass $block
+ * @param \Leafo\ScssPhp\Formatter\OutputBlock $block
*/
- protected function blockChildren($block)
+ protected function blockChildren(OutputBlock $block)
{
foreach ($block->children as $child) {
$this->block($child);
@@ -143,9 +145,9 @@ protected function blockChildren($block)
/**
* Output non-empty block
*
- * @param \stdClass $block
+ * @param \Leafo\ScssPhp\Formatter\OutputBlock $block
*/
- protected function block($block)
+ protected function block(OutputBlock $block)
{
if (empty($block->lines) && empty($block->children)) {
return;
@@ -183,11 +185,11 @@ protected function block($block)
*
* @api
*
- * @param \stdClass $block An abstract syntax tree
+ * @param \Leafo\ScssPhp\Formatter\OutputBlock $block An abstract syntax tree
*
* @return string
*/
- public function format($block)
+ public function format(OutputBlock $block)
{
ob_start();
diff --git a/src/Formatter/Compressed.php b/src/Formatter/Compressed.php
index 21def797..c51bb26b 100644
--- a/src/Formatter/Compressed.php
+++ b/src/Formatter/Compressed.php
@@ -12,6 +12,7 @@
namespace Leafo\ScssPhp\Formatter;
use Leafo\ScssPhp\Formatter;
+use Leafo\ScssPhp\Formatter\OutputBlock;
/**
* SCSS compressed formatter
@@ -49,7 +50,7 @@ public function stripSemicolon(&$lines)
/**
* {@inheritdoc}
*/
- public function blockLines($block)
+ public function blockLines(OutputBlock $block)
{
$inner = $this->indentStr();
@@ -73,7 +74,7 @@ public function blockLines($block)
/**
* {@inherit}
*/
- public function format($block)
+ public function format(OutputBlock $block)
{
return parent::format($block);
diff --git a/src/Formatter/Crunched.php b/src/Formatter/Crunched.php
index 1e930b4f..29120cc9 100644
--- a/src/Formatter/Crunched.php
+++ b/src/Formatter/Crunched.php
@@ -12,6 +12,7 @@
namespace Leafo\ScssPhp\Formatter;
use Leafo\ScssPhp\Formatter;
+use Leafo\ScssPhp\Formatter\OutputBlock;
/**
* SCSS crunched formatter
@@ -49,7 +50,7 @@ public function stripSemicolon(&$lines)
/**
* {@inheritdoc}
*/
- public function blockLines($block)
+ public function blockLines(OutputBlock $block)
{
$inner = $this->indentStr();
diff --git a/src/Formatter/Debug.php b/src/Formatter/Debug.php
index 7082909d..e330b2d6 100644
--- a/src/Formatter/Debug.php
+++ b/src/Formatter/Debug.php
@@ -12,6 +12,7 @@
namespace Leafo\ScssPhp\Formatter;
use Leafo\ScssPhp\Formatter;
+use Leafo\ScssPhp\Formatter\OutputBlock;
/**
* SCSS debug formatter
@@ -45,7 +46,7 @@ protected function indentStr()
/**
* {@inheritdoc}
*/
- protected function blockLines($block)
+ protected function blockLines(OutputBlock $block)
{
$indent = $this->indentStr();
@@ -63,7 +64,7 @@ protected function blockLines($block)
/**
* {@inheritdoc}
*/
- protected function blockSelectors($block)
+ protected function blockSelectors(OutputBlock $block)
{
$indent = $this->indentStr();
@@ -81,7 +82,7 @@ protected function blockSelectors($block)
/**
* {@inheritdoc}
*/
- protected function blockChildren($block)
+ protected function blockChildren(OutputBlock $block)
{
$indent = $this->indentStr();
@@ -103,7 +104,7 @@ protected function blockChildren($block)
/**
* {@inheritdoc}
*/
- protected function block($block)
+ protected function block(OutputBlock $block)
{
$indent = $this->indentStr();
diff --git a/src/Formatter/Expanded.php b/src/Formatter/Expanded.php
index 25e6639d..477318b4 100644
--- a/src/Formatter/Expanded.php
+++ b/src/Formatter/Expanded.php
@@ -12,6 +12,7 @@
namespace Leafo\ScssPhp\Formatter;
use Leafo\ScssPhp\Formatter;
+use Leafo\ScssPhp\Formatter\OutputBlock;
/**
* SCSS expanded formatter
@@ -45,7 +46,7 @@ protected function indentStr()
/**
* {@inheritdoc}
*/
- protected function blockLines($block)
+ protected function blockLines(OutputBlock $block)
{
$inner = $this->indentStr();
diff --git a/src/Formatter/Nested.php b/src/Formatter/Nested.php
index c8e3decd..8040adab 100644
--- a/src/Formatter/Nested.php
+++ b/src/Formatter/Nested.php
@@ -12,6 +12,7 @@
namespace Leafo\ScssPhp\Formatter;
use Leafo\ScssPhp\Formatter;
+use Leafo\ScssPhp\Formatter\OutputBlock;
/**
* SCSS nested formatter
@@ -52,7 +53,7 @@ protected function indentStr()
/**
* {@inheritdoc}
*/
- protected function blockLines($block)
+ protected function blockLines(OutputBlock $block)
{
$inner = $this->indentStr();
@@ -74,7 +75,7 @@ protected function blockLines($block)
/**
* {@inheritdoc}
*/
- protected function blockSelectors($block)
+ protected function blockSelectors(OutputBlock $block)
{
$inner = $this->indentStr();
@@ -86,7 +87,7 @@ protected function blockSelectors($block)
/**
* {@inheritdoc}
*/
- protected function blockChildren($block)
+ protected function blockChildren(OutputBlock $block)
{
foreach ($block->children as $i => $child) {
$this->block($child);
@@ -108,7 +109,7 @@ protected function blockChildren($block)
/**
* {@inheritdoc}
*/
- protected function block($block)
+ protected function block(OutputBlock $block)
{
if ($block->type === 'root') {
$this->adjustAllChildren($block);
@@ -148,9 +149,9 @@ protected function block($block)
/**
* Adjust the depths of all children, depth first
*
- * @param \stdClass $block
+ * @param \Leafo\ScssPhp\Formatter\OutputBlock $block
*/
- private function adjustAllChildren($block)
+ private function adjustAllChildren(OutputBlock $block)
{
// flatten empty nested blocks
$children = array();
diff --git a/src/Formatter/OutputBlock.php b/src/Formatter/OutputBlock.php
new file mode 100644
index 00000000..bfc383e2
--- /dev/null
+++ b/src/Formatter/OutputBlock.php
@@ -0,0 +1,50 @@
+
+ */
+class OutputBlock
+{
+ /**
+ * @var string
+ */
+ public $type;
+
+ /**
+ * @var integer
+ */
+ public $depth;
+
+ /**
+ * @var array
+ */
+ public $selectors;
+
+ /**
+ * @var array
+ */
+ public $lines;
+
+ /**
+ * @var array
+ */
+ public $children;
+
+ /**
+ * @var \Leafo\ScssPhp\Formatter\OutputBlock
+ */
+ public $parent;
+}
diff --git a/src/Parser.php b/src/Parser.php
index d193849f..f0e486d7 100644
--- a/src/Parser.php
+++ b/src/Parser.php
@@ -11,6 +11,7 @@
namespace Leafo\ScssPhp;
+use Leafo\ScssPhp\Block;
use Leafo\ScssPhp\Compiler;
/**
@@ -121,7 +122,7 @@ protected static function makeOperatorStr($operators)
*
* @param string $buffer;
*
- * @return \stdClass
+ * @return \Leafo\ScssPhp\Block
*/
public function parse($buffer)
{
@@ -685,11 +686,11 @@ protected function literal($what, $eatWhitespace = null)
* @param array $selectors
* @param integer $pos
*
- * @return \stdClass
+ * @return \Leafo\ScssPhp\Block
*/
protected function pushBlock($selectors, $pos = 0)
{
- $b = new \stdClass;
+ $b = new Block;
$b->parent = $this->env;
$b->sourcePosition = $pos;
@@ -719,7 +720,7 @@ protected function pushBlock($selectors, $pos = 0)
* @param string $type
* @param integer $pos
*
- * @return \stdClass
+ * @return \Leafo\ScssPhp\Block
*/
protected function pushSpecialBlock($type, $pos)
{
@@ -732,7 +733,7 @@ protected function pushSpecialBlock($type, $pos)
/**
* Pop scope and return last block
*
- * @return \stdClass
+ * @return \Leafo\ScssPhp\Block
*
* @throws \Exception
*/
From e0f519b2c1abe1b85fe35d405987561e9e802148 Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Thu, 5 Nov 2015 22:03:24 -0500
Subject: [PATCH 156/534] Add (parser) node types
---
scss.inc.php | 2 +
src/Block.php | 17 --
src/Compiler.php | 397 ++++++++++++++++++++++++-----------------------
src/Node.php | 21 +++
src/Parser.php | 137 ++++++++--------
src/Type.php | 65 ++++++++
6 files changed, 357 insertions(+), 282 deletions(-)
create mode 100644 src/Node.php
create mode 100644 src/Type.php
diff --git a/scss.inc.php b/scss.inc.php
index 4c142973..a8fe358d 100644
--- a/scss.inc.php
+++ b/scss.inc.php
@@ -17,7 +17,9 @@
include_once __DIR__ . '/src/Formatter/Expanded.php';
include_once __DIR__ . '/src/Formatter/Nested.php';
include_once __DIR__ . '/src/Formatter/OutputBlock.php';
+ include_once __DIR__ . '/src/Node.php';
include_once __DIR__ . '/src/Parser.php';
+ include_once __DIR__ . '/src/Type.php';
include_once __DIR__ . '/src/Util.php';
include_once __DIR__ . '/src/Version.php';
include_once __DIR__ . '/src/Server.php';
diff --git a/src/Block.php b/src/Block.php
index 9e3483ba..16f4a968 100644
--- a/src/Block.php
+++ b/src/Block.php
@@ -18,23 +18,6 @@
*/
class Block
{
- const T_MEDIA = 'media';
- const T_MIXIN = 'mixin';
- const T_INCLUDE = 'include';
- const T_FUNCTION = 'function';
- const T_EACH = 'each';
- const T_WHILE = 'while';
- const T_FOR = 'for';
- const T_IF = 'if';
- const T_ELSE = 'else';
- const T_ELSEIF = 'elseif';
- const T_DIRECTIVE = 'directive';
- const T_NESTED_PROPERTY = 'nestedprop';
- const T_BLOCK = 'block';
- const T_ROOT = 'root';
- const T_NULL = null;
- const T_COMMENT = 'comment';
-
/**
* @var string
*/
diff --git a/src/Compiler.php b/src/Compiler.php
index 110f4c7b..8991d05f 100644
--- a/src/Compiler.php
+++ b/src/Compiler.php
@@ -16,6 +16,7 @@
use Leafo\ScssPhp\Colors;
use Leafo\ScssPhp\Compiler\Environment;
use Leafo\ScssPhp\Formatter\OutputBlock;
+use Leafo\ScssPhp\Type;
use Leafo\ScssPhp\Parser;
use Leafo\ScssPhp\Util;
@@ -104,16 +105,16 @@ class Compiler
),
);
- static public $true = array('keyword', 'true');
- static public $false = array('keyword', 'false');
- static public $null = array('null');
- static public $defaultValue = array('keyword', '');
- static public $selfSelector = array('self');
- static public $emptyList = array('list', '', array());
- static public $emptyMap = array('map', array(), array());
- static public $emptyString = array('string', '"', array());
- static public $with = array('keyword', 'with');
- static public $without = array('keyword', 'without');
+ static public $true = array(Type::T_KEYWORD, 'true');
+ static public $false = array(Type::T_KEYWORD, 'false');
+ static public $null = array(Type::T_NULL);
+ static public $defaultValue = array(Type::T_KEYWORD, '');
+ static public $selfSelector = array(Type::T_SELF);
+ static public $emptyList = array(Type::T_LIST, '', array());
+ static public $emptyMap = array(Type::T_MAP, array(), array());
+ static public $emptyString = array(Type::T_STRING, '"', array());
+ static public $with = array(Type::T_KEYWORD, 'with');
+ static public $without = array(Type::T_KEYWORD, 'without');
protected $importPaths = array('');
protected $importCache = array();
@@ -282,7 +283,7 @@ protected function makeOutputBlock($type, $selectors = null)
*/
protected function compileRoot(Block $rootBlock)
{
- $this->rootBlock = $this->scope = $this->makeOutputBlock('root');
+ $this->rootBlock = $this->scope = $this->makeOutputBlock(Type::T_ROOT);
$this->compileChildrenNoReturn($rootBlock->children, $this->scope);
$this->flattenSelectors($this->scope);
@@ -314,7 +315,9 @@ protected function flattenSelectors(OutputBlock $block, $parentKey = null)
array_walk($selectors, function (&$value) {
$value = json_encode($value);
});
+
$selectors = array_unique($selectors);
+
array_walk($selectors, function (&$value) {
$value = json_decode($value);
});
@@ -512,7 +515,7 @@ protected function compileMedia(Block $media)
$mediaQuery = $this->compileMediaQuery($this->multiplyMedia($this->env));
if (! empty($mediaQuery)) {
- $this->scope = $this->makeOutputBlock('media', array($mediaQuery));
+ $this->scope = $this->makeOutputBlock(Type::T_MEDIA, array($mediaQuery));
$parentScope = $this->mediaParent($this->scope);
$parentScope->children[] = $this->scope;
@@ -523,7 +526,7 @@ protected function compileMedia(Block $media)
foreach ($media->children as $child) {
$type = $child[0];
- if ($type !== 'block' && $type !== 'media' && $type !== 'directive' && $type !== 'import') {
+ if ($type !== Type::T_BLOCK && $type !== Type::T_MEDIA && $type !== Type::T_DIRECTIVE && $type !== Type::T_IMPORT) {
$needsWrap = true;
break;
}
@@ -534,7 +537,7 @@ protected function compileMedia(Block $media)
$wrapped->selectors = array();
$wrapped->children = $media->children;
- $media->children = array(array('block', $wrapped));
+ $media->children = array(array(Type::T_BLOCK, $wrapped));
}
$this->compileChildrenNoReturn($media->children, $this->scope);
@@ -555,7 +558,7 @@ protected function compileMedia(Block $media)
protected function mediaParent(OutputBlock $scope)
{
while (! empty($scope->parent)) {
- if (! empty($scope->type) && $scope->type !== 'media') {
+ if (! empty($scope->type) && $scope->type !== Type::T_MEDIA) {
break;
}
@@ -606,7 +609,7 @@ protected function compileAtRoot(Block $block)
$wrapped->comments = array();
$wrapped->children = $block->children;
- $block->children = array(array('block', $wrapped));
+ $block->children = array(array(Type::T_BLOCK, $wrapped));
}
$this->env = $this->filterWithout($envs, $without);
@@ -645,7 +648,7 @@ private function spliceTree($envs, Block $block, $without)
continue;
}
- if (isset($e->block->type) && $e->block->type === 'at-root') {
+ if (isset($e->block->type) && $e->block->type === Type::T_AT_ROOT) {
continue;
}
@@ -654,13 +657,13 @@ private function spliceTree($envs, Block $block, $without)
}
if (($without & self::WITH_MEDIA) &&
- isset($e->block->type) && $e->block->type === 'media'
+ isset($e->block->type) && $e->block->type === Type::T_MEDIA
) {
continue;
}
if (($without & self::WITH_SUPPORTS) &&
- isset($e->block->type) && $e->block->type === 'directive' &&
+ isset($e->block->type) && $e->block->type === Type::T_DIRECTIVE &&
isset($e->block->name) && $e->block->name === 'supports'
) {
continue;
@@ -699,14 +702,14 @@ private function spliceTree($envs, Block $block, $without)
}
if ($newBlock) {
- $type = isset($newBlock->type) ? $newBlock->type : 'block';
+ $type = isset($newBlock->type) ? $newBlock->type : Type::T_BLOCK;
$b->children = array(array($type, $newBlock));
$newBlock->parent = $b;
} elseif (count($block->children)) {
foreach ($block->children as $child) {
- if ($child[0] === 'block') {
+ if ($child[0] === Type::T_BLOCK) {
$child[1]->parent = $b;
}
}
@@ -719,7 +722,7 @@ private function spliceTree($envs, Block $block, $without)
$newBlock = $b;
}
- $type = isset($newBlock->type) ? $newBlock->type : 'block';
+ $type = isset($newBlock->type) ? $newBlock->type : Type::T_BLOCK;
return array($type, $newBlock);
}
@@ -792,13 +795,13 @@ private function filterWithout($envs, $without)
}
if (($without & self::WITH_MEDIA) &&
- isset($e->block->type) && $e->block->type === 'media'
+ isset($e->block->type) && $e->block->type === Type::T_MEDIA
) {
continue;
}
if (($without & self::WITH_SUPPORTS) &&
- isset($e->block->type) && $e->block->type === 'directive' &&
+ isset($e->block->type) && $e->block->type === Type::T_DIRECTIVE &&
isset($e->block->name) && $e->block->name === 'supports'
) {
continue;
@@ -884,7 +887,7 @@ protected function compileBlock(Block $block)
$out = $this->makeOutputBlock(null);
if (isset($this->lineNumberStyle) && count($env->selectors) && count($block->children)) {
- $annotation = $this->makeOutputBlock('comment');
+ $annotation = $this->makeOutputBlock(Type::T_COMMENT);
$annotation->depth = 0;
$parser = $this->sourceParsers[$block->sourceIndex];
@@ -925,7 +928,7 @@ protected function compileBlock(Block $block)
*/
protected function compileComment($block)
{
- $out = $this->makeOutputBlock('comment');
+ $out = $this->makeOutputBlock(Type::T_COMMENT);
$out->lines[] = $block[1];
$this->scope->children[] = $out;
}
@@ -978,7 +981,7 @@ protected function evalSelector($selector)
protected function evalSelectorPart($part)
{
foreach ($part as &$p) {
- if (is_array($p) && ($p[0] === 'interpolate' || $p[0] === 'string')) {
+ if (is_array($p) && ($p[0] === Type::T_INTERPOLATE || $p[0] === Type::T_STRING)) {
$p = $this->compileValue($p);
// force re-evaluation
@@ -1090,7 +1093,7 @@ protected function compileSelectorPart($piece)
}
switch ($p[0]) {
- case 'self':
+ case Type::T_SELF:
$p = '&';
break;
@@ -1183,7 +1186,7 @@ protected function compileMediaQuery($queryList)
foreach ($query as $q) {
switch ($q[0]) {
- case 'mediaType':
+ case Type::T_MEDIA_TYPE:
if ($type) {
$type = $this->mergeMediaTypes(
$type,
@@ -1198,7 +1201,7 @@ protected function compileMediaQuery($queryList)
}
break;
- case 'mediaExp':
+ case Type::T_MEDIA_EXPRESSION:
if (isset($q[2])) {
$parts[] = '('
. $this->compileValue($q[1])
@@ -1212,7 +1215,7 @@ protected function compileMediaQuery($queryList)
}
break;
- case 'mediaValue':
+ case Type::T_MEDIA_VALUE:
$parts[] = $this->compileValue($q[1]);
break;
}
@@ -1275,24 +1278,24 @@ protected function mergeMediaTypes($type1, $type2)
$t2 = strtolower($type2[0]);
}
- if (($m1 === 'not') ^ ($m2 === 'not')) {
+ if (($m1 === Type::T_NOT) ^ ($m2 === Type::T_NOT)) {
if ($t1 === $t2) {
return null;
}
return array(
- $m1 === 'not' ? $m2 : $m1,
- $m1 === 'not' ? $t2 : $t1,
+ $m1 === Type::T_NOT ? $m2 : $m1,
+ $m1 === Type::T_NOT ? $t2 : $t1,
);
}
- if ($m1 === 'not' && $m2 === 'not') {
+ if ($m1 === Type::T_NOT && $m2 === Type::T_NOT) {
// CSS has no way of representing "neither screen nor print"
if ($t1 !== $t2) {
return null;
}
- return array('not', $t1);
+ return array(Type::T_NOT, $t1);
}
if ($t1 !== $t2) {
@@ -1313,7 +1316,7 @@ protected function mergeMediaTypes($type1, $type2)
*/
protected function compileImport($rawPath, $out)
{
- if ($rawPath[0] === 'string') {
+ if ($rawPath[0] === Type::T_STRING) {
$path = $this->compileStringContent($rawPath);
if ($path = $this->findImport($path)) {
@@ -1325,14 +1328,14 @@ protected function compileImport($rawPath, $out)
return false;
}
- if ($rawPath[0] === 'list') {
+ if ($rawPath[0] === Type::T_LIST) {
// handle a list of strings
if (count($rawPath[2]) === 0) {
return false;
}
foreach ($rawPath[2] as $path) {
- if ($path[0] !== 'string') {
+ if ($path[0] !== Type::T_STRING) {
return false;
}
}
@@ -1361,7 +1364,7 @@ protected function compileChild($child, OutputBlock $out)
$this->sourcePos = isset($child[Parser::SOURCE_POSITION]) ? $child[Parser::SOURCE_POSITION] : -1;
switch ($child[0]) {
- case 'import':
+ case Type::T_IMPORT:
list(, $rawPath) = $child;
$rawPath = $this->reduce($rawPath);
@@ -1371,23 +1374,23 @@ protected function compileChild($child, OutputBlock $out)
}
break;
- case 'directive':
+ case Type::T_DIRECTIVE:
$this->compileDirective($child[1]);
break;
- case 'at-root':
+ case Type::T_AT_ROOT:
$this->compileAtRoot($child[1]);
break;
- case 'media':
+ case Type::T_MEDIA:
$this->compileMedia($child[1]);
break;
- case 'block':
+ case Type::T_BLOCK:
$this->compileBlock($child[1]);
break;
- case 'charset':
+ case Type::T_CHARSET:
if (! $this->charsetSeen) {
$this->charsetSeen = true;
@@ -1395,10 +1398,10 @@ protected function compileChild($child, OutputBlock $out)
}
break;
- case 'assign':
+ case Type::T_ASSIGN:
list(, $name, $value) = $child;
- if ($name[0] === 'var') {
+ if ($name[0] === Type::T_VARIABLE) {
$flag = isset($child[3]) ? $child[3] : null;
$isDefault = $flag === '!default';
$isGlobal = $flag === '!global';
@@ -1422,11 +1425,11 @@ protected function compileChild($child, OutputBlock $out)
// handle shorthand syntax: size / line-height
if ($compiledName === 'font') {
- if ($value[0] === 'exp' && $value[1] === '/') {
+ if ($value[0] === Type::T_EXPRESSION && $value[1] === '/') {
$value = $this->expToString($value);
- } elseif ($value[0] === 'list') {
+ } elseif ($value[0] === Type::T_LIST) {
foreach ($value[2] as &$item) {
- if ($item[0] === 'exp' && $item[1] === '/') {
+ if ($item[0] === Type::T_EXPRESSION && $item[1] === '/') {
$item = $this->expToString($item);
}
}
@@ -1435,10 +1438,10 @@ protected function compileChild($child, OutputBlock $out)
// if the value reduces to null from something else then
// the property should be discarded
- if ($value[0] !== 'null') {
+ if ($value[0] !== Type::T_NULL) {
$value = $this->reduce($value);
- if ($value[0] === 'null') {
+ if ($value[0] === Type::T_NULL) {
break;
}
}
@@ -1451,8 +1454,8 @@ protected function compileChild($child, OutputBlock $out)
);
break;
- case 'comment':
- if ($out->type === 'root') {
+ case Type::T_COMMENT:
+ if ($out->type === Type::T_ROOT) {
$this->compileComment($child);
break;
}
@@ -1460,14 +1463,14 @@ protected function compileChild($child, OutputBlock $out)
$out->lines[] = $child[1];
break;
- case 'mixin':
- case 'function':
+ case Type::T_MIXIN:
+ case Type::T_FUNCTION:
list(, $block) = $child;
$this->set(self::$namespaces[$block->type] . $block->name, $block);
break;
- case 'extend':
+ case Type::T_EXTEND:
list(, $selectors) = $child;
foreach ($selectors as $sel) {
@@ -1482,7 +1485,7 @@ protected function compileChild($child, OutputBlock $out)
}
break;
- case 'if':
+ case Type::T_IF:
list(, $if) = $child;
if ($this->isTruthy($this->reduce($if->cond, true))) {
@@ -1490,18 +1493,18 @@ protected function compileChild($child, OutputBlock $out)
}
foreach ($if->cases as $case) {
- if ($case->type === 'else' ||
- $case->type === 'elseif' && $this->isTruthy($this->reduce($case->cond))
+ if ($case->type === Type::T_ELSE ||
+ $case->type === Type::T_ELSEIF && $this->isTruthy($this->reduce($case->cond))
) {
return $this->compileChildren($case->children, $out);
}
}
break;
- case 'return':
+ case Type::T_RETURN:
return $this->reduce($child[1], true);
- case 'each':
+ case Type::T_EACH:
list(, $each) = $child;
$list = $this->coerceList($this->reduce($each->list));
@@ -1531,7 +1534,7 @@ protected function compileChild($child, OutputBlock $out)
$this->popEnv();
break;
- case 'while':
+ case Type::T_WHILE:
list(, $while) = $child;
while ($this->isTruthy($this->reduce($while->cond, true))) {
@@ -1543,7 +1546,7 @@ protected function compileChild($child, OutputBlock $out)
}
break;
- case 'for':
+ case Type::T_FOR:
list(, $for) = $child;
$start = $this->reduce($for->start, true);
@@ -1559,7 +1562,7 @@ protected function compileChild($child, OutputBlock $out)
break;
}
- $this->set($for->var, array('number', $start, ''));
+ $this->set($for->var, array(Type::T_NUMBER, $start, ''));
$start += $d;
$ret = $this->compileChildren($for->children, $out);
@@ -1570,18 +1573,18 @@ protected function compileChild($child, OutputBlock $out)
}
break;
- case 'nestedprop':
+ case Type::T_NESTED_PROPERTY:
list(, $prop) = $child;
$prefixed = array();
$prefix = $this->compileValue($prop->prefix) . '-';
foreach ($prop->children as $child) {
- if ($child[0] === 'assign') {
+ if ($child[0] === Type::T_ASSIGN) {
array_unshift($child[1][2], $prefix);
}
- if ($child[0] === 'nestedprop') {
+ if ($child[0] === Type::T_NESTED_PROPERTY) {
array_unshift($child[1]->prefix[2], $prefix);
}
@@ -1591,7 +1594,7 @@ protected function compileChild($child, OutputBlock $out)
$this->compileChildrenNoReturn($prefixed, $out);
break;
- case 'include':
+ case Type::T_INCLUDE:
// including a mixin
list(, $name, $argValues, $content) = $child;
@@ -1624,7 +1627,7 @@ protected function compileChild($child, OutputBlock $out)
$this->popEnv();
break;
- case 'mixin_content':
+ case Type::T_MIXIN_CONTENT:
$content = $this->get(self::$namespaces['special'] . 'content', false, $this->getStoreEnv());
if (! $content) {
@@ -1643,7 +1646,7 @@ protected function compileChild($child, OutputBlock $out)
$this->storeEnv = $storeEnv;
break;
- case 'debug':
+ case Type::T_DEBUG:
list(, $value) = $child;
$line = $this->parser->getLineNo($this->sourcePos);
@@ -1651,7 +1654,7 @@ protected function compileChild($child, OutputBlock $out)
fwrite($this->stderr, "Line $line DEBUG: $value\n");
break;
- case 'warn':
+ case Type::T_WARN:
list(, $value) = $child;
$line = $this->parser->getLineNo($this->sourcePos);
@@ -1659,7 +1662,7 @@ protected function compileChild($child, OutputBlock $out)
echo "Line $line WARN: $value\n";
break;
- case 'error':
+ case Type::T_ERROR:
list(, $value) = $child;
$line = $this->parser->getLineNo($this->sourcePos);
@@ -1697,7 +1700,7 @@ protected function expToString($exp)
$content[] = $this->reduce($right);
- return array('string', '', $content);
+ return array(Type::T_STRING, '', $content);
}
/**
@@ -1722,14 +1725,14 @@ protected function isTruthy($value)
protected function shouldEval($value)
{
switch ($value[0]) {
- case 'exp':
+ case Type::T_EXPRESSION:
if ($value[1] === '/') {
return $this->shouldEval($value[2], $value[3]);
}
// fall-thru
- case 'var':
- case 'fncall':
+ case Type::T_VARIABLE:
+ case Type::T_FUNCTION_CALL:
return true;
}
@@ -1749,7 +1752,7 @@ protected function reduce($value, $inExp = false)
list($type) = $value;
switch ($type) {
- case 'exp':
+ case Type::T_EXPRESSION:
list(, $op, $left, $right, $inParens) = $value;
$opName = isset(self::$operatorNames[$op]) ? self::$operatorNames[$op] : $op;
@@ -1793,7 +1796,7 @@ protected function reduce($value, $inExp = false)
$unitChange = false;
if (! isset($genOp) &&
- $left[0] === 'number' && $right[0] === 'number'
+ $left[0] === Type::T_NUMBER && $right[0] === Type::T_NUMBER
) {
if ($opName === 'mod' && $right[2] !== '') {
$this->throwError("Cannot modulo by a number with units: $right[1]$right[2].");
@@ -1835,7 +1838,7 @@ protected function reduce($value, $inExp = false)
}
if (isset($out)) {
- if ($unitChange && $out[0] === 'number') {
+ if ($unitChange && $out[0] === Type::T_NUMBER) {
$out = $this->coerceUnit($out, $targetUnit);
}
@@ -1845,13 +1848,13 @@ protected function reduce($value, $inExp = false)
return $this->expToString($value);
- case 'unary':
+ case Type::T_UNARY:
list(, $op, $exp, $inParens) = $value;
$inExp = $inExp || $this->shouldEval($exp);
$exp = $this->reduce($exp);
- if ($exp[0] === 'number') {
+ if ($exp[0] === Type::T_NUMBER) {
switch ($op) {
case '+':
return $exp;
@@ -1875,21 +1878,21 @@ protected function reduce($value, $inExp = false)
$op = $op . ' ';
}
- return array('string', '', array($op, $exp));
+ return array(Type::T_STRING, '', array($op, $exp));
- case 'var':
+ case Type::T_VARIABLE:
list(, $name) = $value;
return $this->reduce($this->get($name));
- case 'list':
+ case Type::T_LIST:
foreach ($value[2] as &$item) {
$item = $this->reduce($item);
}
return $value;
- case 'map':
+ case Type::T_MAP:
foreach ($value[1] as &$item) {
$item = $this->reduce($item);
}
@@ -1900,7 +1903,7 @@ protected function reduce($value, $inExp = false)
return $value;
- case 'string':
+ case Type::T_STRING:
foreach ($value[2] as &$item) {
if (is_array($item)) {
$item = $this->reduce($item);
@@ -1909,12 +1912,12 @@ protected function reduce($value, $inExp = false)
return $value;
- case 'interpolate':
+ case Type::T_INTERPOLATE:
$value[1] = $this->reduce($value[1]);
return $value;
- case 'fncall':
+ case Type::T_FUNCTION_CALL:
list(, $name, $argValues) = $value;
return $this->fncall($name, $argValues);
@@ -1953,7 +1956,7 @@ private function fncall($name, $argValues)
}
}
- return array('function', $name, array('list', ',', $listArgs));
+ return array(Type::T_FUNCTION, $name, array(Type::T_LIST, ',', $listArgs));
}
/**
@@ -1981,11 +1984,11 @@ public function normalizeValue($value)
list($type) = $value;
switch ($type) {
- case 'list':
+ case Type::T_LIST:
$value = $this->extractInterpolation($value);
- if ($value[0] !== 'list') {
- return array('keyword', $this->compileValue($value));
+ if ($value[0] !== Type::T_LIST) {
+ return array(Type::T_KEYWORD, $this->compileValue($value));
}
foreach ($value[2] as $key => $item) {
@@ -1994,14 +1997,14 @@ public function normalizeValue($value)
return $value;
- case 'string':
+ case Type::T_STRING:
return array($type, '"', array($this->compileStringContent($value)));
- case 'number':
+ case Type::T_NUMBER:
return $this->normalizeNumber($value);
- case 'interpolate':
- return array('keyword', $this->compileValue($value));
+ case Type::T_INTERPOLATE:
+ return array(Type::T_KEYWORD, $this->compileValue($value));
default:
return $value;
@@ -2022,7 +2025,7 @@ protected function normalizeNumber($number)
if (isset(self::$unitTable['in'][$unit])) {
$conv = self::$unitTable['in'][$unit];
- return array('number', $value / $conv, 'in');
+ return array(Type::T_NUMBER, $value / $conv, 'in');
}
return $number;
@@ -2038,7 +2041,7 @@ protected function normalizeNumber($number)
*/
protected function opAddNumberNumber($left, $right)
{
- return array('number', $left[1] + $right[1], $left[2]);
+ return array(Type::T_NUMBER, $left[1] + $right[1], $left[2]);
}
/**
@@ -2051,7 +2054,7 @@ protected function opAddNumberNumber($left, $right)
*/
protected function opMulNumberNumber($left, $right)
{
- return array('number', $left[1] * $right[1], $left[2]);
+ return array(Type::T_NUMBER, $left[1] * $right[1], $left[2]);
}
/**
@@ -2064,7 +2067,7 @@ protected function opMulNumberNumber($left, $right)
*/
protected function opSubNumberNumber($left, $right)
{
- return array('number', $left[1] - $right[1], $left[2]);
+ return array(Type::T_NUMBER, $left[1] - $right[1], $left[2]);
}
/**
@@ -2078,10 +2081,10 @@ protected function opSubNumberNumber($left, $right)
protected function opDivNumberNumber($left, $right)
{
if ($right[1] == 0) {
- return array('string', '', array($left[1] . $left[2] . '/' . $right[1] . $right[2]));
+ return array(Type::T_STRING, '', array($left[1] . $left[2] . '/' . $right[1] . $right[2]));
}
- return array('number', $left[1] / $right[1], $left[2]);
+ return array(Type::T_NUMBER, $left[1] / $right[1], $left[2]);
}
/**
@@ -2094,7 +2097,7 @@ protected function opDivNumberNumber($left, $right)
*/
protected function opModNumberNumber($left, $right)
{
- return array('number', $left[1] % $right[1], $left[2]);
+ return array(Type::T_NUMBER, $left[1] % $right[1], $left[2]);
}
/**
@@ -2108,7 +2111,7 @@ protected function opModNumberNumber($left, $right)
protected function opAdd($left, $right)
{
if ($strLeft = $this->coerceString($left)) {
- if ($right[0] === 'string') {
+ if ($right[0] === Type::T_STRING) {
$right[1] = '';
}
@@ -2118,7 +2121,7 @@ protected function opAdd($left, $right)
}
if ($strRight = $this->coerceString($right)) {
- if ($left[0] === 'string') {
+ if ($left[0] === Type::T_STRING) {
$left[1] = '';
}
@@ -2183,7 +2186,7 @@ protected function opOr($left, $right, $shouldEval)
*/
protected function opColorColor($op, $left, $right)
{
- $out = array('color');
+ $out = array(Type::T_COLOR);
foreach (range(1, 3) as $i) {
$lval = isset($left[$i]) ? $left[$i] : 0;
@@ -2250,7 +2253,7 @@ protected function opColorNumber($op, $left, $right)
return $this->opColorColor(
$op,
$left,
- array('color', $value, $value, $value)
+ array(Type::T_COLOR, $value, $value, $value)
);
}
@@ -2269,7 +2272,7 @@ protected function opNumberColor($op, $left, $right)
return $this->opColorColor(
$op,
- array('color', $value, $value, $value),
+ array(Type::T_COLOR, $value, $value, $value),
$right
);
}
@@ -2406,10 +2409,10 @@ public function compileValue($value)
list($type) = $value;
switch ($type) {
- case 'keyword':
+ case Type::T_KEYWORD:
return $value[1];
- case 'color':
+ case Type::T_COLOR:
// [1] - red component (either number for a %)
// [2] - green component
// [3] - blue component
@@ -2433,21 +2436,21 @@ public function compileValue($value)
return $h;
- case 'number':
+ case Type::T_NUMBER:
return round($value[1], $this->numberPrecision) . $value[2];
- case 'string':
+ case Type::T_STRING:
return $value[1] . $this->compileStringContent($value) . $value[1];
- case 'function':
+ case Type::T_FUNCTION:
$args = ! empty($value[2]) ? $this->compileValue($value[2]) : '';
return "$value[1]($args)";
- case 'list':
+ case Type::T_LIST:
$value = $this->extractInterpolation($value);
- if ($value[0] !== 'list') {
+ if ($value[0] !== Type::T_LIST) {
return $this->compileValue($value);
}
@@ -2460,7 +2463,7 @@ public function compileValue($value)
$filtered = array();
foreach ($items as $item) {
- if ($item[0] === 'null') {
+ if ($item[0] === Type::T_NULL) {
continue;
}
@@ -2469,7 +2472,7 @@ public function compileValue($value)
return implode("$delim", $filtered);
- case 'map':
+ case Type::T_MAP:
$keys = $value[1];
$values = $value[2];
$filtered = array();
@@ -2484,7 +2487,7 @@ public function compileValue($value)
return '(' . implode(', ', $filtered) . ')';
- case 'interpolated':
+ case Type::T_INTERPOLATED:
// node created by extractInterpolation
list(, $interpolate, $left, $right) = $value;
list(,, $whiteLeft, $whiteRight) = $interpolate;
@@ -2497,7 +2500,7 @@ public function compileValue($value)
return $left . $this->compileValue($interpolate) . $right;
- case 'interpolate':
+ case Type::T_INTERPOLATE:
// raw parse node
list(, $exp) = $value;
@@ -2505,17 +2508,17 @@ public function compileValue($value)
$reduced = $this->reduce($exp);
switch ($reduced[0]) {
- case 'string':
- $reduced = array('keyword', $this->compileStringContent($reduced));
+ case Type::T_STRING:
+ $reduced = array(Type::T_KEYWORD, $this->compileStringContent($reduced));
break;
- case 'null':
- $reduced = array('keyword', '');
+ case Type::T_NULL:
+ $reduced = array(Type::T_KEYWORD, '');
}
return $this->compileValue($reduced);
- case 'null':
+ case Type::T_NULL:
return 'null';
default:
@@ -2569,11 +2572,11 @@ protected function extractInterpolation($list)
$items = $list[2];
foreach ($items as $i => $item) {
- if ($item[0] === 'interpolate') {
- $before = array('list', $list[1], array_slice($items, 0, $i));
- $after = array('list', $list[1], array_slice($items, $i + 1));
+ if ($item[0] === Type::T_INTERPOLATE) {
+ $before = array(Type::T_LIST, $list[1], array_slice($items, 0, $i));
+ $after = array(Type::T_LIST, $list[1], array_slice($items, $i + 1));
- return array('interpolated', $item, $before, $after);
+ return array(Type::T_INTERPOLATED, $item, $before, $after);
}
}
@@ -2664,7 +2667,7 @@ protected function joinSelectors($parent, $child)
protected function multiplyMedia(Environment $env = null, $childQueries = null)
{
if (! isset($env) ||
- ! empty($env->block->type) && $env->block->type !== 'media'
+ ! empty($env->block->type) && $env->block->type !== Type::T_MEDIA
) {
return $childQueries;
}
@@ -2676,7 +2679,7 @@ protected function multiplyMedia(Environment $env = null, $childQueries = null)
$parentQueries = isset($env->block->queryList)
? $env->block->queryList
- : array(array(array('mediaValue', $env->block->value)));
+ : array(array(array(Type::T_MEDIA_VALUE, $env->block->value)));
if ($childQueries === null) {
$childQueries = $parentQueries;
@@ -3407,7 +3410,7 @@ protected function applyArguments($argDef, $argValues)
} elseif ($arg[2] === true) {
$val = $this->reduce($arg[1], true);
- if ($val[0] === 'list') {
+ if ($val[0] === Type::T_LIST) {
foreach ($val[2] as $name => $item) {
if (! is_numeric($name)) {
$keywordArgs[$name] = $item;
@@ -3415,7 +3418,7 @@ protected function applyArguments($argDef, $argValues)
$remaining[] = $item;
}
}
- } elseif ($val[0] === 'map') {
+ } elseif ($val[0] === Type::T_MAP) {
foreach ($val[1] as $i => $name) {
$name = $this->compileStringContent($this->coerceString($name));
$item = $val[2][$i];
@@ -3438,7 +3441,7 @@ protected function applyArguments($argDef, $argValues)
list($i, $name, $default, $isVariable) = $arg;
if ($isVariable) {
- $val = array('list', ',', array(), $isVariable);
+ $val = array(Type::T_LIST, ',', array(), $isVariable);
for ($count = count($remaining); $i < $count; $i++) {
$val[2][] = $remaining[$i];
@@ -3495,14 +3498,14 @@ private function coerceValue($value)
}
if (is_numeric($value)) {
- return array('number', $value, '');
+ return array(Type::T_NUMBER, $value, '');
}
if ($value === '') {
return self::$emptyString;
}
- return array('keyword', $value);
+ return array(Type::T_KEYWORD, $value);
}
/**
@@ -3521,7 +3524,7 @@ protected function coerceUnit($number, $unit)
$value = $value * self::$unitTable[$baseUnit][$unit];
}
- return array('number', $value, $unit);
+ return array(Type::T_NUMBER, $value, $unit);
}
/**
@@ -3533,7 +3536,7 @@ protected function coerceUnit($number, $unit)
*/
protected function coerceMap($item)
{
- if ($item[0] === 'map') {
+ if ($item[0] === Type::T_MAP) {
return $item;
}
@@ -3541,7 +3544,7 @@ protected function coerceMap($item)
return self::$emptyMap;
}
- return array('map', array($item), array(self::$null));
+ return array(Type::T_MAP, array($item), array(self::$null));
}
/**
@@ -3553,11 +3556,11 @@ protected function coerceMap($item)
*/
protected function coerceList($item, $delim = ',')
{
- if (isset($item) && $item[0] === 'list') {
+ if (isset($item) && $item[0] === Type::T_LIST) {
return $item;
}
- if (isset($item) && $item[0] === 'map') {
+ if (isset($item) && $item[0] === Type::T_MAP) {
$keys = $item[1];
$values = $item[2];
$list = array();
@@ -3567,16 +3570,16 @@ protected function coerceList($item, $delim = ',')
$value = $values[$i];
$list[] = array(
- 'list',
+ Type::T_LIST,
'',
- array(array('keyword', $this->compileStringContent($this->coerceString($key))), $value)
+ array(array(Type::T_KEYWORD, $this->compileStringContent($this->coerceString($key))), $value)
);
}
- return array('list', ',', $list);
+ return array(Type::T_LIST, ',', $list);
}
- return array('list', $delim, ! isset($item) ? array(): array($item));
+ return array(Type::T_LIST, $delim, ! isset($item) ? array(): array($item));
}
/**
@@ -3605,18 +3608,18 @@ protected function coerceForExpression($value)
protected function coerceColor($value)
{
switch ($value[0]) {
- case 'color':
+ case Type::T_COLOR:
return $value;
- case 'keyword':
+ case Type::T_KEYWORD:
$name = strtolower($value[1]);
if (isset(Colors::$cssColors[$name])) {
$rgba = explode(',', Colors::$cssColors[$name]);
return isset($rgba[3])
- ? array('color', (int) $rgba[0], (int) $rgba[1], (int) $rgba[2], (int) $rgba[3])
- : array('color', (int) $rgba[0], (int) $rgba[1], (int) $rgba[2]);
+ ? array(Type::T_COLOR, (int) $rgba[0], (int) $rgba[1], (int) $rgba[2], (int) $rgba[3])
+ : array(Type::T_COLOR, (int) $rgba[0], (int) $rgba[1], (int) $rgba[2]);
}
return null;
@@ -3634,11 +3637,11 @@ protected function coerceColor($value)
*/
protected function coerceString($value)
{
- if ($value[0] === 'string') {
+ if ($value[0] === Type::T_STRING) {
return $value;
}
- return array('string', '', array($this->compileValue($value)));
+ return array(Type::T_STRING, '', array($this->compileValue($value)));
}
/**
@@ -3650,7 +3653,7 @@ protected function coerceString($value)
*/
protected function coercePercent($value)
{
- if ($value[0] === 'number') {
+ if ($value[0] === Type::T_NUMBER) {
if ($value[2] === '%') {
return $value[1] / 100;
}
@@ -3676,7 +3679,7 @@ public function assertMap($value)
{
$value = $this->coerceMap($value);
- if ($value[0] !== 'map') {
+ if ($value[0] !== Type::T_MAP) {
$this->throwError('expecting map');
}
@@ -3696,7 +3699,7 @@ public function assertMap($value)
*/
public function assertList($value)
{
- if ($value[0] !== 'list') {
+ if ($value[0] !== Type::T_LIST) {
$this->throwError('expecting list');
}
@@ -3736,7 +3739,7 @@ public function assertColor($value)
*/
public function assertNumber($value)
{
- if ($value[0] !== 'number') {
+ if ($value[0] !== Type::T_NUMBER) {
$this->throwError('expecting number');
}
@@ -3802,7 +3805,7 @@ public function toHSL($red, $green, $blue)
}
}
- return array('hsl', fmod($h, 360), $s * 100, $l / 5.1);
+ return array(Type::T_HSL, fmod($h, 360), $s * 100, $l / 5.1);
}
/**
@@ -3865,7 +3868,7 @@ public function toRGB($hue, $saturation, $lightness)
$g = $this->hueToRGB($m1, $m2, $h) * 255;
$b = $this->hueToRGB($m1, $m2, $h - 1/3) * 255;
- $out = array('color', $r, $g, $b);
+ $out = array(Type::T_COLOR, $r, $g, $b);
return $out;
}
@@ -3886,11 +3889,11 @@ function ($a) {
if (count($kwargs)) {
foreach ($kwargs as $key => $value) {
- $args[] = array(array('var', $key), $value, false);
+ $args[] = array(array(Type::T_VARIABLE, $key), $value, false);
}
}
- return $this->reduce(array('fncall', $name, $args));
+ return $this->reduce(array(Type::T_FUNCTION_CALL, $name, $args));
}
protected static $libIf = array('condition', 'if-true', 'if-false');
@@ -3910,15 +3913,15 @@ protected function libIndex($args)
{
list($list, $value) = $args;
- if ($value[0] === 'map') {
+ if ($value[0] === Type::T_MAP) {
return self::$null;
}
- if ($list[0] === 'map' || $list[0] === 'string' || $list[0] === 'keyword' || $list[0] === 'interpolate') {
+ if ($list[0] === Type::T_MAP || $list[0] === Type::T_STRING || $list[0] === Type::T_KEYWORD || $list[0] === Type::T_INTERPOLATE) {
$list = $this->coerceList($list, ' ');
}
- if ($list[0] !== 'list') {
+ if ($list[0] !== Type::T_LIST) {
return self::$null;
}
@@ -3938,7 +3941,7 @@ protected function libRgb($args)
{
list($r, $g, $b) = $args;
- return array('color', $r[1], $g[1], $b[1]);
+ return array(Type::T_COLOR, $r[1], $g[1], $b[1]);
}
protected static $libRgba = array(
@@ -3959,7 +3962,7 @@ protected function libRgba($args)
list($r, $g, $b, $a) = $args;
- return array('color', $r[1], $g[1], $b[1], $a[1]);
+ return array(Type::T_COLOR, $r[1], $g[1], $b[1], $a[1]);
}
// helper function for adjust_color, change_color, and scale_color
@@ -4110,7 +4113,7 @@ protected function libOpacity($args)
{
$value = $args[0];
- if ($value[0] === 'number') {
+ if ($value[0] === Type::T_NUMBER) {
return null;
}
@@ -4141,7 +4144,7 @@ protected function libMix($args)
$w1 = (($w * $a === -1 ? $w : ($w + $a) / (1 + $w * $a)) + 1) / 2.0;
$w2 = 1.0 - $w1;
- $new = array('color',
+ $new = array(Type::T_COLOR,
$w1 * $first[1] + $w2 * $second[1],
$w1 * $first[2] + $w2 * $second[2],
$w1 * $first[3] + $w2 * $second[3],
@@ -4179,7 +4182,7 @@ protected function libHue($args)
$color = $this->assertColor($args[0]);
$hsl = $this->toHSL($color[1], $color[2], $color[3]);
- return array('number', $hsl[1], 'deg');
+ return array(Type::T_NUMBER, $hsl[1], 'deg');
}
protected static $libSaturation = array('color');
@@ -4188,7 +4191,7 @@ protected function libSaturation($args)
$color = $this->assertColor($args[0]);
$hsl = $this->toHSL($color[1], $color[2], $color[3]);
- return array('number', $hsl[2], '%');
+ return array(Type::T_NUMBER, $hsl[2], '%');
}
protected static $libLightness = array('color');
@@ -4197,7 +4200,7 @@ protected function libLightness($args)
$color = $this->assertColor($args[0]);
$hsl = $this->toHSL($color[1], $color[2], $color[3]);
- return array('number', $hsl[3], '%');
+ return array(Type::T_NUMBER, $hsl[3], '%');
}
protected function adjustHsl($color, $idx, $amount)
@@ -4245,7 +4248,7 @@ protected function libSaturate($args)
{
$value = $args[0];
- if ($value[0] === 'number') {
+ if ($value[0] === Type::T_NUMBER) {
return null;
}
@@ -4269,7 +4272,7 @@ protected function libGrayscale($args)
{
$value = $args[0];
- if ($value[0] === 'number') {
+ if ($value[0] === Type::T_NUMBER) {
return null;
}
@@ -4287,7 +4290,7 @@ protected function libInvert($args)
{
$value = $args[0];
- if ($value[0] === 'number') {
+ if ($value[0] === Type::T_NUMBER) {
return null;
}
@@ -4342,7 +4345,7 @@ protected function libUnquote($args)
{
$str = $args[0];
- if ($str[0] === 'string') {
+ if ($str[0] === Type::T_STRING) {
$str[1] = '';
}
@@ -4354,17 +4357,17 @@ protected function libQuote($args)
{
$value = $args[0];
- if ($value[0] === 'string' && ! empty($value[1])) {
+ if ($value[0] === Type::T_STRING && ! empty($value[1])) {
return $value;
}
- return array('string', '"', array($value));
+ return array(Type::T_STRING, '"', array($value));
}
protected static $libPercentage = array('value');
protected function libPercentage($args)
{
- return array('number', $this->coercePercent($args[0]) * 100, '%');
+ return array(Type::T_NUMBER, $this->coercePercent($args[0]) * 100, '%');
}
protected static $libRound = array('value');
@@ -4445,7 +4448,7 @@ protected function getNormalizedNumbers($args)
$numbers = array();
foreach ($args as $key => $item) {
- if ('number' !== $item[0]) {
+ if ($item[0] !== Type::T_NUMBER) {
$this->throwError('%s is not a number', $item[0]);
}
@@ -4550,7 +4553,7 @@ protected function libMapKeys($args)
$map = $this->assertMap($args[0]);
$keys = $map[1];
- return array('list', ',', $keys);
+ return array(Type::T_LIST, ',', $keys);
}
protected static $libMapValues = array('map');
@@ -4559,7 +4562,7 @@ protected function libMapValues($args)
$map = $this->assertMap($args[0]);
$values = $map[2];
- return array('list', ',', $values);
+ return array(Type::T_LIST, ',', $values);
}
protected static $libMapRemove = array('map', 'key');
@@ -4599,7 +4602,7 @@ protected function libMapMerge($args)
$map1 = $this->assertMap($args[0]);
$map2 = $this->assertMap($args[1]);
- return array('map', array_merge($map1[1], $map2[1]), array_merge($map1[2], $map2[2]));
+ return array(Type::T_MAP, array_merge($map1[1], $map2[1]), array_merge($map1[2], $map2[2]));
}
protected function listSeparatorForJoin($list1, $sep)
@@ -4629,7 +4632,7 @@ protected function libJoin($args)
$list2 = $this->coerceList($list2, ' ');
$sep = $this->listSeparatorForJoin($list1, $sep);
- return array('list', $sep, array_merge($list1[2], $list2[2]));
+ return array(Type::T_LIST, $sep, array_merge($list1[2], $list2[2]));
}
protected static $libAppend = array('list', 'val', 'separator');
@@ -4640,7 +4643,7 @@ protected function libAppend($args)
$list1 = $this->coerceList($list1, ' ');
$sep = $this->listSeparatorForJoin($list1, $sep);
- return array('list', $sep, array_merge($list1[2], array($value)));
+ return array(Type::T_LIST, $sep, array_merge($list1[2], array($value)));
}
protected function libZip($args)
@@ -4653,7 +4656,7 @@ protected function libZip($args)
$firstList = array_shift($args);
foreach ($firstList[2] as $key => $item) {
- $list = array('list', '', array($item));
+ $list = array(Type::T_LIST, '', array($item));
foreach ($args as $arg) {
if (isset($arg[2][$key])) {
@@ -4666,7 +4669,7 @@ protected function libZip($args)
$lists[] = $list;
}
- return array('list', ',', $lists);
+ return array(Type::T_LIST, ',', $lists);
}
protected static $libTypeOf = array('value');
@@ -4675,7 +4678,7 @@ protected function libTypeOf($args)
$value = $args[0];
switch ($value[0]) {
- case 'keyword':
+ case Type::T_KEYWORD:
if ($value === self::$true || $value === self::$false) {
return 'bool';
}
@@ -4685,10 +4688,10 @@ protected function libTypeOf($args)
}
// fall-thru
- case 'function':
+ case Type::T_FUNCTION:
return 'string';
- case 'list':
+ case Type::T_LIST:
if (isset($value[3]) && $value[3]) {
return 'arglist';
}
@@ -4704,8 +4707,8 @@ protected function libUnit($args)
{
$num = $args[0];
- if ($num[0] === 'number') {
- return array('string', '"', array($num[2]));
+ if ($num[0] === Type::T_NUMBER) {
+ return array(Type::T_STRING, '"', array($num[2]));
}
return '';
@@ -4716,7 +4719,7 @@ protected function libUnitless($args)
{
$value = $args[0];
- return $value[0] === 'number' && empty($value[2]);
+ return $value[0] === Type::T_NUMBER && empty($value[2]);
}
protected static $libComparable = array('number-1', 'number-2');
@@ -4724,7 +4727,7 @@ protected function libComparable($args)
{
list($number1, $number2) = $args;
- if (! isset($number1[0]) || $number1[0] !== 'number' || ! isset($number2[0]) || $number2[0] !== 'number') {
+ if (! isset($number1[0]) || $number1[0] !== Type::T_NUMBER || ! isset($number2[0]) || $number2[0] !== Type::T_NUMBER) {
$this->throwError('Invalid argument(s) for "comparable"');
}
@@ -4745,7 +4748,7 @@ protected function libStrIndex($args)
$result = strpos($stringContent, $substringContent);
- return $result === false ? self::$null : array('number', $result + 1, '');
+ return $result === false ? self::$null : array(Type::T_NUMBER, $result + 1, '');
}
protected static $libStrInsert = array('string', 'insert', 'index');
@@ -4770,7 +4773,7 @@ protected function libStrLength($args)
$string = $this->coerceString($args[0]);
$stringContent = $this->compileStringContent($string);
- return array('number', strlen($stringContent), '');
+ return array(Type::T_NUMBER, strlen($stringContent), '');
}
protected static $libStrSlice = array('string', 'start-at', 'end-at');
@@ -4883,7 +4886,7 @@ protected function libCounter($args)
{
$list = array_map(array($this, 'compileValue'), $args);
- return array('string', '', array('counter(' . implode(',', $list) . ')'));
+ return array(Type::T_STRING, '', array('counter(' . implode(',', $list) . ')'));
}
protected function libRandom($args)
@@ -4895,10 +4898,10 @@ protected function libRandom($args)
$this->throwError("limit must be greater than or equal to 1");
}
- return array('number', mt_rand(1, $n), '');
+ return array(Type::T_NUMBER, mt_rand(1, $n), '');
}
- return array('number', mt_rand(1, mt_getrandmax()), '');
+ return array(Type::T_NUMBER, mt_rand(1, mt_getrandmax()), '');
}
protected function libUniqueId()
@@ -4911,6 +4914,6 @@ protected function libUniqueId()
$id += mt_rand(0, 10) + 1;
- return array('string', '', array('u' . str_pad(base_convert($id, 10, 36), 8, '0', STR_PAD_LEFT)));
+ return array(Type::T_STRING, '', array('u' . str_pad(base_convert($id, 10, 36), 8, '0', STR_PAD_LEFT)));
}
}
diff --git a/src/Node.php b/src/Node.php
new file mode 100644
index 00000000..107ee574
--- /dev/null
+++ b/src/Node.php
@@ -0,0 +1,21 @@
+
+ */
+abstract class Node
+{
+}
diff --git a/src/Parser.php b/src/Parser.php
index f0e486d7..bbfbfd2d 100644
--- a/src/Parser.php
+++ b/src/Parser.php
@@ -13,6 +13,7 @@
use Leafo\ScssPhp\Block;
use Leafo\ScssPhp\Compiler;
+use Leafo\ScssPhp\Type;
/**
* SCSS parser
@@ -247,7 +248,7 @@ protected function parseChunk()
($this->map($with) || true) &&
$this->literal('{')
) {
- $atRoot = $this->pushSpecialBlock('at-root', $s);
+ $atRoot = $this->pushSpecialBlock(Type::T_AT_ROOT, $s);
$atRoot->selector = $selector;
$atRoot->with = $with;
@@ -257,7 +258,7 @@ protected function parseChunk()
$this->seek($s);
if ($this->literal('@media') && $this->mediaQueryList($mediaQueryList) && $this->literal('{')) {
- $media = $this->pushSpecialBlock('media', $s);
+ $media = $this->pushSpecialBlock(Type::T_MEDIA, $s);
$media->queryList = $mediaQueryList[2];
return true;
@@ -270,7 +271,7 @@ protected function parseChunk()
($this->argumentDef($args) || true) &&
$this->literal('{')
) {
- $mixin = $this->pushSpecialBlock('mixin', $s);
+ $mixin = $this->pushSpecialBlock(Type::T_MIXIN, $s);
$mixin->name = $mixinName;
$mixin->args = $args;
@@ -287,11 +288,11 @@ protected function parseChunk()
($this->end() ||
$this->literal('{') && $hasBlock = true)
) {
- $child = array('include',
+ $child = array(Type::T_INCLUDE,
$mixinName, isset($argValues) ? $argValues : null, null);
if (! empty($hasBlock)) {
- $include = $this->pushSpecialBlock('include', $s);
+ $include = $this->pushSpecialBlock(Type::T_INCLUDE, $s);
$include->child = $child;
} else {
$this->append($child, $s);
@@ -306,7 +307,7 @@ protected function parseChunk()
$this->valueList($importPath) &&
$this->end()
) {
- $this->append(array('import', $importPath), $s);
+ $this->append(array(Type::T_IMPORT, $importPath), $s);
return true;
}
@@ -317,7 +318,7 @@ protected function parseChunk()
$this->url($importPath) &&
$this->end()
) {
- $this->append(array('import', $importPath), $s);
+ $this->append(array(Type::T_IMPORT, $importPath), $s);
return true;
}
@@ -328,7 +329,7 @@ protected function parseChunk()
$this->selectors($selector) &&
$this->end()
) {
- $this->append(array('extend', $selector), $s);
+ $this->append(array(Type::T_EXTEND, $selector), $s);
return true;
}
@@ -340,7 +341,7 @@ protected function parseChunk()
$this->argumentDef($args) &&
$this->literal('{')
) {
- $func = $this->pushSpecialBlock('function', $s);
+ $func = $this->pushSpecialBlock(Type::T_FUNCTION, $s);
$func->name = $fnName;
$func->args = $args;
@@ -350,7 +351,7 @@ protected function parseChunk()
$this->seek($s);
if ($this->literal('@return') && $this->valueList($retVal) && $this->end()) {
- $this->append(array('return', $retVal), $s);
+ $this->append(array(Type::T_RETURN, $retVal), $s);
return true;
}
@@ -363,7 +364,7 @@ protected function parseChunk()
$this->valueList($list) &&
$this->literal('{')
) {
- $each = $this->pushSpecialBlock('each', $s);
+ $each = $this->pushSpecialBlock(Type::T_EACH, $s);
foreach ($varNames[2] as $varName) {
$each->vars[] = $varName[1];
@@ -380,7 +381,7 @@ protected function parseChunk()
$this->expression($cond) &&
$this->literal('{')
) {
- $while = $this->pushSpecialBlock('while', $s);
+ $while = $this->pushSpecialBlock(Type::T_WHILE, $s);
$while->cond = $cond;
return true;
@@ -397,7 +398,7 @@ protected function parseChunk()
$this->expression($end) &&
$this->literal('{')
) {
- $for = $this->pushSpecialBlock('for', $s);
+ $for = $this->pushSpecialBlock(Type::T_FOR, $s);
$for->var = $varName[1];
$for->start = $start;
$for->end = $end;
@@ -409,7 +410,7 @@ protected function parseChunk()
$this->seek($s);
if ($this->literal('@if') && $this->valueList($cond) && $this->literal('{')) {
- $if = $this->pushSpecialBlock('if', $s);
+ $if = $this->pushSpecialBlock(Type::T_IF, $s);
$if->cond = $cond;
$if->cases = array();
@@ -422,7 +423,7 @@ protected function parseChunk()
$this->valueList($value) &&
$this->end()
) {
- $this->append(array('debug', $value), $s);
+ $this->append(array(Type::T_DEBUG, $value), $s);
return true;
}
@@ -433,7 +434,7 @@ protected function parseChunk()
$this->valueList($value) &&
$this->end()
) {
- $this->append(array('warn', $value), $s);
+ $this->append(array(Type::T_WARN, $value), $s);
return true;
}
@@ -444,7 +445,7 @@ protected function parseChunk()
$this->valueList($value) &&
$this->end()
) {
- $this->append(array('error', $value), $s);
+ $this->append(array(Type::T_ERROR, $value), $s);
return true;
}
@@ -452,7 +453,7 @@ protected function parseChunk()
$this->seek($s);
if ($this->literal('@content') && $this->end()) {
- $this->append(array('mixin_content'), $s);
+ $this->append(array(Type::T_MIXIN_CONTENT), $s);
return true;
}
@@ -461,14 +462,14 @@ protected function parseChunk()
$last = $this->last();
- if (isset($last) && $last[0] === 'if') {
+ if (isset($last) && $last[0] === Type::T_IF) {
list(, $if) = $last;
if ($this->literal('@else')) {
if ($this->literal('{')) {
- $else = $this->pushSpecialBlock('else', $s);
+ $else = $this->pushSpecialBlock(Type::T_ELSE, $s);
} elseif ($this->literal('if') && $this->valueList($cond) && $this->literal('{')) {
- $else = $this->pushSpecialBlock('elseif', $s);
+ $else = $this->pushSpecialBlock(Type::T_ELSEIF, $s);
$else->cond = $cond;
}
@@ -489,7 +490,7 @@ protected function parseChunk()
$this->end()
) {
if (! isset($this->charset)) {
- $statement = array('charset', $charset);
+ $statement = array(Type::T_CHARSET, $charset);
$statement[self::SOURCE_POSITION] = $s;
$statement[self::SOURCE_INDEX] = $this->sourceIndex;
@@ -509,9 +510,9 @@ protected function parseChunk()
$this->literal('{')
) {
if ($dirName === 'media') {
- $directive = $this->pushSpecialBlock('media', $s);
+ $directive = $this->pushSpecialBlock(Type::T_MEDIA, $s);
} else {
- $directive = $this->pushSpecialBlock('directive', $s);
+ $directive = $this->pushSpecialBlock(Type::T_DIRECTIVE, $s);
$directive->name = $dirName;
}
@@ -534,8 +535,8 @@ protected function parseChunk()
$this->valueList($value) &&
$this->end()
) {
- $name = array('string', '', array($name));
- $this->append(array('assign', $name, $value), $s);
+ $name = array(Type::T_STRING, '', array($name));
+ $this->append(array(Type::T_ASSIGN, $name, $value), $s);
return true;
}
@@ -550,7 +551,7 @@ protected function parseChunk()
) {
// check for '!flag'
$assignmentFlag = $this->stripAssignmentFlag($value);
- $this->append(array('assign', $name, $value, $assignmentFlag), $s);
+ $this->append(array(Type::T_ASSIGN, $name, $value, $assignmentFlag), $s);
return true;
}
@@ -576,12 +577,12 @@ protected function parseChunk()
$foundSomething = false;
if ($this->valueList($value)) {
- $this->append(array('assign', $name, $value), $s);
+ $this->append(array(Type::T_ASSIGN, $name, $value), $s);
$foundSomething = true;
}
if ($this->literal('{')) {
- $propBlock = $this->pushSpecialBlock('nestedprop', $s);
+ $propBlock = $this->pushSpecialBlock(Type::T_NESTED_PROPERTY, $s);
$propBlock->prefix = $name;
$foundSomething = true;
} elseif ($foundSomething) {
@@ -599,13 +600,13 @@ protected function parseChunk()
if ($this->literal('}')) {
$block = $this->popBlock();
- if (isset($block->type) && $block->type === 'include') {
+ if (isset($block->type) && $block->type === Type::T_INCLUDE) {
$include = $block->child;
unset($block->child);
$include[3] = $block;
$this->append($include, $s);
} elseif (empty($block->dontAppend)) {
- $type = isset($block->type) ? $block->type : 'block';
+ $type = isset($block->type) ? $block->type : Type::T_BLOCK;
$this->append(array($type, $block), $s);
}
@@ -633,10 +634,10 @@ protected function stripAssignmentFlag(&$value)
{
$token = &$value;
- for ($token = &$value; $token[0] === 'list' && ($s = count($token[2])); $token = &$lastNode) {
+ for ($token = &$value; $token[0] === Type::T_LIST && ($s = count($token[2])); $token = &$lastNode) {
$lastNode = &$token[2][$s - 1];
- if ($lastNode[0] === 'keyword' && in_array($lastNode[1], array('!default', '!global'))) {
+ if ($lastNode[0] === Type::T_KEYWORD && in_array($lastNode[1], array('!default', '!global'))) {
array_pop($token[2]);
$token = $this->flattenList($token);
@@ -835,23 +836,23 @@ protected function mediaQuery(&$out)
if (($this->literal('only') && ($only = true) || $this->literal('not') && ($not = true) || true) &&
$this->mixedKeyword($mediaType)
) {
- $prop = array('mediaType');
+ $prop = array(Type::T_MEDIA_TYPE);
if (isset($only)) {
- $prop[] = array('keyword', 'only');
+ $prop[] = array(Type::T_KEYWORD, 'only');
}
if (isset($not)) {
- $prop[] = array('keyword', 'not');
+ $prop[] = array(Type::T_KEYWORD, 'not');
}
- $media = array('list', '', array());
+ $media = array(Type::T_LIST, '', array());
foreach ((array)$mediaType as $type) {
if (is_array($type)) {
$media[2][] = $type;
} else {
- $media[2][] = array('keyword', $type);
+ $media[2][] = array(Type::T_KEYWORD, $type);
}
}
@@ -889,7 +890,7 @@ protected function mediaExpression(&$out)
($this->literal(':') && $this->expression($value) || true) &&
$this->literal(')')
) {
- $out = array('mediaExp', $feature);
+ $out = array(Type::T_MEDIA_EXPRESSION, $feature);
if ($value) {
$out[] = $value;
@@ -1013,7 +1014,7 @@ protected function genericList(&$out, $parseItem, $delim = '', $flatten = true)
if ($flatten && count($items) === 1) {
$out = $items[0];
} else {
- $out = array('list', $delim, $items);
+ $out = array(Type::T_LIST, $delim, $items);
}
return true;
@@ -1032,12 +1033,12 @@ protected function expression(&$out)
if ($this->literal('(')) {
if ($this->literal(')')) {
- $out = array('list', '', array());
+ $out = array(Type::T_LIST, '', array());
return true;
}
- if ($this->valueList($out) && $this->literal(')') && $out[0] === 'list') {
+ if ($this->valueList($out) && $this->literal(')') && $out[0] === Type::T_LIST) {
return true;
}
@@ -1099,7 +1100,7 @@ protected function expHelper($lhs, $minP)
$rhs = $this->expHelper($rhs, self::$precedence[$next[1]]);
}
- $lhs = array('exp', $op, $lhs, $rhs, $this->inParens, $whiteBefore, $whiteAfter);
+ $lhs = array(Type::T_EXPRESSION, $op, $lhs, $rhs, $this->inParens, $whiteBefore, $whiteAfter);
$ss = $this->seek();
$whiteBefore = isset($this->buffer[$this->count - 1]) &&
ctype_space($this->buffer[$this->count - 1]);
@@ -1122,7 +1123,7 @@ protected function value(&$out)
$s = $this->seek();
if ($this->literal('not', false) && $this->whitespace() && $this->value($inner)) {
- $out = array('unary', 'not', $inner, $this->inParens);
+ $out = array(Type::T_UNARY, 'not', $inner, $this->inParens);
return true;
}
@@ -1130,7 +1131,7 @@ protected function value(&$out)
$this->seek($s);
if ($this->literal('not', false) && $this->parenValue($inner)) {
- $out = array('unary', 'not', $inner, $this->inParens);
+ $out = array(Type::T_UNARY, 'not', $inner, $this->inParens);
return true;
}
@@ -1138,7 +1139,7 @@ protected function value(&$out)
$this->seek($s);
if ($this->literal('+') && $this->value($inner)) {
- $out = array('unary', '+', $inner, $this->inParens);
+ $out = array(Type::T_UNARY, '+', $inner, $this->inParens);
return true;
}
@@ -1151,7 +1152,7 @@ protected function value(&$out)
$this->unit($inner) ||
$this->parenValue($inner))
) {
- $out = array('unary', '-', $inner, $this->inParens);
+ $out = array(Type::T_UNARY, '-', $inner, $this->inParens);
return true;
}
@@ -1172,9 +1173,9 @@ protected function value(&$out)
if ($this->keyword($keyword)) {
if ($keyword === 'null') {
- $out = array('null');
+ $out = array(Type::T_NULL);
} else {
- $out = array('keyword', $keyword);
+ $out = array(Type::T_KEYWORD, $keyword);
}
return true;
@@ -1198,7 +1199,7 @@ protected function parenValue(&$out)
if ($this->literal('(')) {
if ($this->literal(')')) {
- $out = array('list', '', array());
+ $out = array(Type::T_LIST, '', array());
return true;
}
@@ -1237,7 +1238,7 @@ protected function progid(&$out)
$this->openString(')', $args, '(');
if ($this->literal(')')) {
- $out = array('string', '', array(
+ $out = array(Type::T_STRING, '', array(
'progid:', $fn, '(', $args, ')'
));
@@ -1265,7 +1266,7 @@ protected function func(&$func)
$this->literal('(')
) {
if ($name === 'alpha' && $this->argumentList($args)) {
- $func = array('function', $name, array('string', '', $args));
+ $func = array(Type::T_FUNCTION, $name, array(Type::T_STRING, '', $args));
return true;
}
@@ -1274,7 +1275,7 @@ protected function func(&$func)
$ss = $this->seek();
if ($this->argValues($args) && $this->literal(')')) {
- $func = array('fncall', $name, $args);
+ $func = array(Type::T_FUNCTION_CALL, $name, $args);
return true;
}
@@ -1288,10 +1289,10 @@ protected function func(&$func)
$args = array();
if (! empty($str)) {
- $args[] = array(null, array('string', '', array($str)));
+ $args[] = array(null, array(Type::T_STRING, '', array($str)));
}
- $func = array('fncall', $name, $args);
+ $func = array(Type::T_FUNCTION_CALL, $name, $args);
return true;
}
@@ -1320,7 +1321,7 @@ protected function argumentList(&$out)
$ss = $this->seek();
if ($this->literal('=') && $this->expression($exp)) {
- $args[] = array('string', '', array($var . '='));
+ $args[] = array(Type::T_STRING, '', array($var . '='));
$arg = $exp;
} else {
break;
@@ -1332,7 +1333,7 @@ protected function argumentList(&$out)
break;
}
- $args[] = array('string', '', array(', '));
+ $args[] = array(Type::T_STRING, '', array(', '));
}
if (! $this->literal(')') || ! count($args)) {
@@ -1439,7 +1440,7 @@ protected function map(&$out)
return false;
}
- $out = array('map', $keys, $values);
+ $out = array(Type::T_MAP, $keys, $values);
return true;
}
@@ -1453,7 +1454,7 @@ protected function map(&$out)
*/
protected function color(&$out)
{
- $color = array('color');
+ $color = array(Type::T_COLOR);
if ($this->match('(#([0-9a-f]{6})|#([0-9a-f]{3}))', $m)) {
if (isset($m[3])) {
@@ -1491,7 +1492,7 @@ protected function color(&$out)
protected function unit(&$unit)
{
if ($this->match('([0-9]*(\.)?[0-9]+)([%a-zA-Z]+)?', $m)) {
- $unit = array('number', $m[1], empty($m[3]) ? '' : $m[3]);
+ $unit = array(Type::T_NUMBER, $m[1], empty($m[3]) ? '' : $m[3]);
return true;
}
@@ -1549,7 +1550,7 @@ protected function string(&$out)
$this->eatWhiteDefault = $oldWhite;
if ($this->literal($delim)) {
- $out = array('string', $delim, $content);
+ $out = array(Type::T_STRING, $delim, $content);
return true;
}
@@ -1670,7 +1671,7 @@ protected function openString($end, &$out, $nestingOpen = null)
$content[count($content) - 1] = rtrim(end($content));
}
- $out = array('string', '', $content);
+ $out = array(Type::T_STRING, '', $content);
return true;
}
@@ -1700,7 +1701,7 @@ protected function interpolation(&$out, $lookWhite = true)
$left = $right = false;
}
- $out = array('interpolate', $value, $left, $right);
+ $out = array(Type::T_INTERPOLATE, $value, $left, $right);
$this->eatWhiteDefault = $oldWhite;
if ($this->eatWhiteDefault) {
@@ -1764,7 +1765,7 @@ protected function propertyName(&$out)
$this->whitespace(); // get any extra whitespace
- $out = array('string', '', $parts);
+ $out = array(Type::T_STRING, '', $parts);
return true;
}
@@ -2027,7 +2028,7 @@ protected function variable(&$out)
$s = $this->seek();
if ($this->literal('$', false) && $this->keyword($name)) {
- $out = array('var', $name);
+ $out = array(Type::T_VARIABLE, $name);
return true;
}
@@ -2088,7 +2089,7 @@ protected function placeholder(&$placeholder)
protected function url(&$out)
{
if ($this->match('(url\(\s*(["\']?)([^)]+)\2\s*\))', $m)) {
- $out = array('string', '', array('url(' . $m[2] . $m[3] . $m[2] . ')'));
+ $out = array(Type::T_STRING, '', array('url(' . $m[2] . $m[3] . $m[2] . ')'));
return true;
}
@@ -2276,7 +2277,7 @@ protected function whitespace()
while (preg_match(self::$whitePattern, $this->buffer, $m, null, $this->count)) {
if (isset($m[1]) && empty($this->commentsSeen[$this->count])) {
- $this->appendComment(array('comment', $m[1]));
+ $this->appendComment(array(Type::T_COMMENT, $m[1]));
$this->commentsSeen[$this->count] = true;
}
@@ -2360,7 +2361,7 @@ protected function show()
*/
protected function flattenList($value)
{
- if ($value[0] === 'list' && count($value[2]) === 1) {
+ if ($value[0] === Type::T_LIST && count($value[2]) === 1) {
return $this->flattenList($value[2][0]);
}
diff --git a/src/Type.php b/src/Type.php
new file mode 100644
index 00000000..2402f7a4
--- /dev/null
+++ b/src/Type.php
@@ -0,0 +1,65 @@
+
+ */
+class Type
+{
+ const T_ASSIGN = 'assign';
+ const T_AT_ROOT = 'at-root';
+ const T_BLOCK = 'block';
+ const T_CHARSET = 'charset';
+ const T_COLOR = 'color';
+ const T_COMMENT = 'comment';
+ const T_DEBUG = 'debug';
+ const T_DIRECTIVE = 'directive';
+ const T_EACH = 'each';
+ const T_ELSE = 'else';
+ const T_ELSEIF = 'elseif';
+ const T_ERROR = 'error';
+ const T_EXPRESSION = 'exp';
+ const T_EXTEND = 'extend';
+ const T_FOR = 'for';
+ const T_FUNCTION = 'function';
+ const T_FUNCTION_CALL = 'fncall';
+ const T_HSL = 'hsl';
+ const T_IF = 'if';
+ const T_IMPORT = 'import';
+ const T_INCLUDE = 'include';
+ const T_INTERPOLATE = 'interpolate';
+ const T_INTERPOLATED = 'interpolated';
+ const T_KEYWORD = 'keyword';
+ const T_LIST = 'list';
+ const T_MAP = 'map';
+ const T_MEDIA = 'media';
+ const T_MEDIA_EXPRESSION = 'mediaExp';
+ const T_MEDIA_TYPE = 'mediaType';
+ const T_MEDIA_VALUE = 'mediaValue';
+ const T_MIXIN = 'mixin';
+ const T_MIXIN_CONTENT = 'mixin_content';
+ const T_NESTED_PROPERTY = 'nestedprop';
+ const T_NOT = 'not';
+ const T_NULL = 'null';
+ const T_NUMBER = 'number';
+ const T_RETURN = 'return';
+ const T_ROOT = 'root';
+ const T_SELF = 'self';
+ const T_STRING = 'string';
+ const T_UNARY = 'unary';
+ const T_VARIABLE = 'var';
+ const T_WARN = 'warn';
+ const T_WHILE = 'while';
+}
From 63ffea74d80047f79ea95679fce83d8cab370432 Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Fri, 6 Nov 2015 10:00:40 -0500
Subject: [PATCH 157/534] Reorganize methods in Parser
---
src/Parser.php | 574 +++++++++++++++++++++++++------------------------
1 file changed, 294 insertions(+), 280 deletions(-)
diff --git a/src/Parser.php b/src/Parser.php
index bbfbfd2d..1b3498b4 100644
--- a/src/Parser.php
+++ b/src/Parser.php
@@ -84,6 +84,8 @@ class Parser
/**
* Constructor
*
+ * @api
+ *
* @param string $sourceName
* @param integer $sourceIndex
*/
@@ -105,23 +107,66 @@ public function __construct($sourceName, $sourceIndex = 0)
}
/**
- * Make operator regex
+ * Get source file name
*
- * @param array $operators
+ * @api
*
* @return string
*/
- protected static function makeOperatorStr($operators)
+ public function getSourceName()
{
- return '('
- . implode('|', array_map(array('Leafo\ScssPhp\Parser', 'pregQuote'), $operators))
- . ')';
+ return $this->sourceName;
+ }
+
+ /**
+ * Get source line number (given character position in the buffer)
+ *
+ * @api
+ *
+ * @param integer $pos
+ *
+ * @return integer
+ */
+ public function getLineNo($pos)
+ {
+ return 1 + substr_count(substr($this->buffer, 0, $pos), "\n");
+ }
+
+ /**
+ * Throw parser error
+ *
+ * @api
+ *
+ * @param string $msg
+ * @param integer $count
+ *
+ * @throws \Exception
+ */
+ public function throwParseError($msg = 'parse error', $count = null)
+ {
+ $count = ! isset($count) ? $this->count : $count;
+
+ $line = $this->getLineNo($count);
+
+ if (! empty($this->sourceName)) {
+ $loc = "$this->sourceName on line $line";
+ } else {
+ $loc = "line: $line";
+ }
+
+ if ($this->peek("(.*?)(\n|$)", $m, $count)) {
+ throw new \Exception("$msg: failed at `$m[1]` $loc");
+ }
+
+ throw new \Exception("$msg: $loc");
}
/**
* Parser buffer
*
- * @param string $buffer;
+ * @api
+ *
+ * @param string $buffer
*
* @return \Leafo\ScssPhp\Block
*/
@@ -163,6 +208,8 @@ public function parse($buffer)
/**
* Parse a value or value list
*
+ * @api
+ *
* @param string $buffer
* @param string $out
*
@@ -182,6 +229,8 @@ public function parseValue($buffer, &$out)
/**
* Parse a selector or selector list
*
+ * @api
+ *
* @param string $buffer
* @param string $out
*
@@ -198,6 +247,32 @@ public function parseSelector($buffer, &$out)
return $this->selectors($out);
}
+ /**
+ * Quote regular expression
+ *
+ * @param string $what
+ *
+ * @return string
+ */
+ public static function pregQuote($what)
+ {
+ return preg_quote($what, '/');
+ }
+
+ /**
+ * Make operator regex
+ *
+ * @param array $operators
+ *
+ * @return string
+ */
+ protected static function makeOperatorStr($operators)
+ {
+ return '('
+ . implode('|', array_map(array('Leafo\ScssPhp\Parser', 'pregQuote'), $operators))
+ . ')';
+ }
+
/**
* Parse a single chunk off the head of the buffer and append it to the
* current parse environment.
@@ -623,64 +698,6 @@ protected function parseChunk()
return false;
}
- /**
- * Strip assignment flag from the list
- *
- * @param array $value
- *
- * @return string
- */
- protected function stripAssignmentFlag(&$value)
- {
- $token = &$value;
-
- for ($token = &$value; $token[0] === Type::T_LIST && ($s = count($token[2])); $token = &$lastNode) {
- $lastNode = &$token[2][$s - 1];
-
- if ($lastNode[0] === Type::T_KEYWORD && in_array($lastNode[1], array('!default', '!global'))) {
- array_pop($token[2]);
-
- $token = $this->flattenList($token);
-
- return $lastNode[1];
- }
- }
-
- return false;
- }
-
- /**
- * Match literal string
- *
- * @param string $what
- * @param boolean $eatWhitespace
- *
- * @return boolean
- */
- protected function literal($what, $eatWhitespace = null)
- {
- if (! isset($eatWhitespace)) {
- $eatWhitespace = $this->eatWhiteDefault;
- }
-
- // shortcut on single letter
- if (! isset($what[1]) && isset($this->buffer[$this->count])) {
- if ($this->buffer[$this->count] === $what) {
- if (! $eatWhitespace) {
- $this->count++;
-
- return true;
- }
-
- // goes below...
- } else {
- return false;
- }
- }
-
- return $this->match($this->pregQuote($what), $m, $eatWhitespace);
- }
-
/**
* Push block onto parse tree
*
@@ -740,22 +757,187 @@ protected function pushSpecialBlock($type, $pos)
*/
protected function popBlock()
{
- $block = $this->env;
+ $block = $this->env;
+
+ if (empty($block->parent)) {
+ $this->throwParseError('unexpected }');
+ }
+
+ $this->env = $block->parent;
+ unset($block->parent);
+
+ $comments = $block->comments;
+ if (count($comments)) {
+ $this->env->comments = $comments;
+ unset($block->comments);
+ }
+
+ return $block;
+ }
+
+ /**
+ * Peek input stream
+ *
+ * @param string $regex
+ * @param array $out
+ * @param integer $from
+ *
+ * @return integer
+ */
+ protected function peek($regex, &$out, $from = null)
+ {
+ if (! isset($from)) {
+ $from = $this->count;
+ }
+
+ $r = '/' . $regex . '/Ais';
+ $result = preg_match($r, $this->buffer, $out, null, $from);
+
+ return $result;
+ }
+
+ /**
+ * Seek to position in input stream (or return current position in input stream)
+ *
+ * @param integer $where
+ *
+ * @return integer
+ */
+ protected function seek($where = null)
+ {
+ if ($where === null) {
+ return $this->count;
+ }
+
+ $this->count = $where;
+
+ return true;
+ }
+
+ /**
+ * Match string looking for either ending delim, escape, or string interpolation
+ *
+ * {@internal This is a workaround for preg_match's 250K string match limit. }}
+ *
+ * @param array $m Matches (passed by reference)
+ * @param string $delim Delimeter
+ *
+ * @return boolean True if match; false otherwise
+ */
+ protected function matchString(&$m, $delim)
+ {
+ $token = null;
+
+ $end = strlen($this->buffer);
+
+ // look for either ending delim, escape, or string interpolation
+ foreach (array('#{', '\\', $delim) as $lookahead) {
+ $pos = strpos($this->buffer, $lookahead, $this->count);
+
+ if ($pos !== false && $pos < $end) {
+ $end = $pos;
+ $token = $lookahead;
+ }
+ }
+
+ if (! isset($token)) {
+ return false;
+ }
+
+ $match = substr($this->buffer, $this->count, $end - $this->count);
+ $m = array(
+ $match . $token,
+ $match,
+ $token
+ );
+ $this->count = $end + strlen($token);
+
+ return true;
+ }
+
+ /**
+ * Try to match something on head of buffer
+ *
+ * @param string $regex
+ * @param array $out
+ * @param boolean $eatWhitespace
+ *
+ * @return boolean
+ */
+ protected function match($regex, &$out, $eatWhitespace = null)
+ {
+ if (! isset($eatWhitespace)) {
+ $eatWhitespace = $this->eatWhiteDefault;
+ }
+
+ $r = '/' . $regex . '/Ais';
+
+ if (preg_match($r, $this->buffer, $out, null, $this->count)) {
+ $this->count += strlen($out[0]);
+
+ if ($eatWhitespace) {
+ $this->whitespace();
+ }
+
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * Match literal string
+ *
+ * @param string $what
+ * @param boolean $eatWhitespace
+ *
+ * @return boolean
+ */
+ protected function literal($what, $eatWhitespace = null)
+ {
+ if (! isset($eatWhitespace)) {
+ $eatWhitespace = $this->eatWhiteDefault;
+ }
+
+ // shortcut on single letter
+ if (! isset($what[1]) && isset($this->buffer[$this->count])) {
+ if ($this->buffer[$this->count] === $what) {
+ if (! $eatWhitespace) {
+ $this->count++;
+
+ return true;
+ }
+
+ // goes below...
+ } else {
+ return false;
+ }
+ }
+
+ return $this->match($this->pregQuote($what), $m, $eatWhitespace);
+ }
+
+ /**
+ * Match some whitespace
+ *
+ * @return boolean
+ */
+ protected function whitespace()
+ {
+ $gotWhite = false;
- if (empty($block->parent)) {
- $this->throwParseError('unexpected }');
- }
+ while (preg_match(self::$whitePattern, $this->buffer, $m, null, $this->count)) {
+ if (isset($m[1]) && empty($this->commentsSeen[$this->count])) {
+ $this->appendComment(array(Type::T_COMMENT, $m[1]));
- $this->env = $block->parent;
- unset($block->parent);
+ $this->commentsSeen[$this->count] = true;
+ }
- $comments = $block->comments;
- if (count($comments)) {
- $this->env->comments = $comments;
- unset($block->comments);
+ $this->count += strlen($m[0]);
+ $gotWhite = true;
}
- return $block;
+ return $gotWhite;
}
/**
@@ -957,7 +1139,7 @@ protected function argValue(&$out)
}
/**
- * Parse list
+ * Parse comma separated value list
*
* @param string $out
*
@@ -969,7 +1151,7 @@ protected function valueList(&$out)
}
/**
- * Parse space list
+ * Parse space separated value list
*
* @param array $out
*
@@ -2117,229 +2299,77 @@ protected function end()
}
/**
- * @deprecated
- *
- * {@internal
- * advance counter to next occurrence of $what
- * $until - don't include $what in advance
- * $allowNewline, if string, will be used as valid char set
- * }}
- */
- protected function to($what, &$out, $until = false, $allowNewline = false)
- {
- if (is_string($allowNewline)) {
- $validChars = $allowNewline;
- } else {
- $validChars = $allowNewline ? '.' : "[^\n]";
- }
-
- if (! $this->match('(' . $validChars . '*?)' . $this->pregQuote($what), $m, ! $until)) {
- return false;
- }
-
- if ($until) {
- $this->count -= strlen($what); // give back $what
- }
-
- $out = $m[1];
-
- return true;
- }
-
- /**
- * Throw parser error
- *
- * @param string $msg
- * @param integer $count
+ * Strip assignment flag from the list
*
- * @throws \Exception
- */
- public function throwParseError($msg = 'parse error', $count = null)
- {
- $count = ! isset($count) ? $this->count : $count;
-
- $line = $this->getLineNo($count);
-
- if (! empty($this->sourceName)) {
- $loc = "$this->sourceName on line $line";
- } else {
- $loc = "line: $line";
- }
-
- if ($this->peek("(.*?)(\n|$)", $m, $count)) {
- throw new \Exception("$msg: failed at `$m[1]` $loc");
- }
-
- throw new \Exception("$msg: $loc");
- }
-
- /**
- * Get source file name
+ * @param array $value
*
* @return string
*/
- public function getSourceName()
- {
- return $this->sourceName;
- }
-
- /**
- * Get source line number (given character position in the buffer)
- *
- * @param integer $pos
- *
- * @return integer
- */
- public function getLineNo($pos)
+ protected function stripAssignmentFlag(&$value)
{
- return 1 + substr_count(substr($this->buffer, 0, $pos), "\n");
- }
+ $token = &$value;
- /**
- * Match string looking for either ending delim, escape, or string interpolation
- *
- * {@internal This is a workaround for preg_match's 250K string match limit. }}
- *
- * @param array $m Matches (passed by reference)
- * @param string $delim Delimeter
- *
- * @return boolean True if match; false otherwise
- */
- protected function matchString(&$m, $delim)
- {
- $token = null;
+ for ($token = &$value; $token[0] === Type::T_LIST && ($s = count($token[2])); $token = &$lastNode) {
+ $lastNode = &$token[2][$s - 1];
- $end = strlen($this->buffer);
+ if ($lastNode[0] === Type::T_KEYWORD && in_array($lastNode[1], array('!default', '!global'))) {
+ array_pop($token[2]);
- // look for either ending delim, escape, or string interpolation
- foreach (array('#{', '\\', $delim) as $lookahead) {
- $pos = strpos($this->buffer, $lookahead, $this->count);
+ $token = $this->flattenList($token);
- if ($pos !== false && $pos < $end) {
- $end = $pos;
- $token = $lookahead;
+ return $lastNode[1];
}
}
- if (! isset($token)) {
- return false;
- }
-
- $match = substr($this->buffer, $this->count, $end - $this->count);
- $m = array(
- $match . $token,
- $match,
- $token
- );
- $this->count = $end + strlen($token);
-
- return true;
+ return false;
}
/**
- * Try to match something on head of buffer
+ * Turn list of length 1 into value type
*
- * @param string $regex
- * @param array $out
- * @param boolean $eatWhitespace
+ * @param array $value
*
- * @return boolean
+ * @return array
*/
- protected function match($regex, &$out, $eatWhitespace = null)
+ protected function flattenList($value)
{
- if (! isset($eatWhitespace)) {
- $eatWhitespace = $this->eatWhiteDefault;
- }
-
- $r = '/' . $regex . '/Ais';
-
- if (preg_match($r, $this->buffer, $out, null, $this->count)) {
- $this->count += strlen($out[0]);
-
- if ($eatWhitespace) {
- $this->whitespace();
- }
-
- return true;
+ if ($value[0] === Type::T_LIST && count($value[2]) === 1) {
+ return $this->flattenList($value[2][0]);
}
- return false;
+ return $value;
}
/**
- * Match some whitespace
+ * @deprecated
*
- * @return boolean
+ * {@internal
+ * advance counter to next occurrence of $what
+ * $until - don't include $what in advance
+ * $allowNewline, if string, will be used as valid char set
+ * }}
*/
- protected function whitespace()
+ protected function to($what, &$out, $until = false, $allowNewline = false)
{
- $gotWhite = false;
-
- while (preg_match(self::$whitePattern, $this->buffer, $m, null, $this->count)) {
- if (isset($m[1]) && empty($this->commentsSeen[$this->count])) {
- $this->appendComment(array(Type::T_COMMENT, $m[1]));
-
- $this->commentsSeen[$this->count] = true;
- }
-
- $this->count += strlen($m[0]);
- $gotWhite = true;
+ if (is_string($allowNewline)) {
+ $validChars = $allowNewline;
+ } else {
+ $validChars = $allowNewline ? '.' : "[^\n]";
}
- return $gotWhite;
- }
-
- /**
- * Peek input stream
- *
- * @param string $regex
- * @param array $out
- * @param integer $from
- *
- * @return integer
- */
- protected function peek($regex, &$out, $from = null)
- {
- if (! isset($from)) {
- $from = $this->count;
+ if (! $this->match('(' . $validChars . '*?)' . $this->pregQuote($what), $m, ! $until)) {
+ return false;
}
- $r = '/' . $regex . '/Ais';
- $result = preg_match($r, $this->buffer, $out, null, $from);
-
- return $result;
- }
-
- /**
- * Seek to position in input stream (or return current position in input stream)
- *
- * @param integer $where
- *
- * @return integer
- */
- protected function seek($where = null)
- {
- if ($where === null) {
- return $this->count;
+ if ($until) {
+ $this->count -= strlen($what); // give back $what
}
- $this->count = $where;
+ $out = $m[1];
return true;
}
- /**
- * Quote regular expression
- *
- * @param string $what
- *
- * @return string
- */
- public static function pregQuote($what)
- {
- return preg_quote($what, '/');
- }
-
/**
* @deprecated
*/
@@ -2351,20 +2381,4 @@ protected function show()
return '';
}
-
- /**
- * Turn list of length 1 into value type
- *
- * @param array $value
- *
- * @return array
- */
- protected function flattenList($value)
- {
- if ($value[0] === Type::T_LIST && count($value[2]) === 1) {
- return $this->flattenList($value[2][0]);
- }
-
- return $value;
- }
}
From c876d82ea6c45775a5f5eb5149a9ac2bc9158730 Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Fri, 6 Nov 2015 10:20:13 -0500
Subject: [PATCH 158/534] phpcs
---
src/Compiler.php | 64 ++++++++++++++++++++++++++++--------------------
src/Parser.php | 49 ++++++++++++++++++------------------
2 files changed, 61 insertions(+), 52 deletions(-)
diff --git a/src/Compiler.php b/src/Compiler.php
index 8991d05f..47a9c476 100644
--- a/src/Compiler.php
+++ b/src/Compiler.php
@@ -57,36 +57,36 @@ class Compiler
const LINE_COMMENTS = 1;
const DEBUG_INFO = 2;
- const WITH_RULE = 1;
- const WITH_MEDIA = 2;
+ const WITH_RULE = 1;
+ const WITH_MEDIA = 2;
const WITH_SUPPORTS = 4;
- const WITH_ALL = 7;
+ const WITH_ALL = 7;
/**
* @var array
*/
static protected $operatorNames = array(
- '+' => 'add',
- '-' => 'sub',
- '*' => 'mul',
- '/' => 'div',
- '%' => 'mod',
-
- '==' => 'eq',
- '!=' => 'neq',
- '<' => 'lt',
- '>' => 'gt',
-
- '<=' => 'lte',
- '>=' => 'gte',
+ '+' => 'add',
+ '-' => 'sub',
+ '*' => 'mul',
+ '/' => 'div',
+ '%' => 'mod',
+
+ '==' => 'eq',
+ '!=' => 'neq',
+ '<' => 'lt',
+ '>' => 'gt',
+
+ '<=' => 'lte',
+ '>=' => 'gte',
);
/**
* @var array
*/
static protected $namespaces = array(
- 'special' => '%',
- 'mixin' => '@',
+ 'special' => '%',
+ 'mixin' => '@',
'function' => '^',
);
@@ -122,9 +122,9 @@ class Compiler
protected $registeredVars = array();
protected $registeredFeatures = array(
'extend-selector-pseudoclass' => false,
- 'at-error' => true,
- 'units-level-3' => false,
- 'global-variable-shadowing' => false,
+ 'at-error' => true,
+ 'units-level-3' => false,
+ 'global-variable-shadowing' => false,
);
protected $numberPrecision = 5;
@@ -526,7 +526,11 @@ protected function compileMedia(Block $media)
foreach ($media->children as $child) {
$type = $child[0];
- if ($type !== Type::T_BLOCK && $type !== Type::T_MEDIA && $type !== Type::T_DIRECTIVE && $type !== Type::T_IMPORT) {
+ if ($type !== Type::T_BLOCK &&
+ $type !== Type::T_MEDIA &&
+ $type !== Type::T_DIRECTIVE &&
+ $type !== Type::T_IMPORT
+ ) {
$needsWrap = true;
break;
}
@@ -737,10 +741,10 @@ private function spliceTree($envs, Block $block, $without)
private function compileWith($with)
{
static $mapping = array(
- 'rule' => self::WITH_RULE,
- 'media' => self::WITH_MEDIA,
+ 'rule' => self::WITH_RULE,
+ 'media' => self::WITH_MEDIA,
'supports' => self::WITH_SUPPORTS,
- 'all' => self::WITH_ALL,
+ 'all' => self::WITH_ALL,
);
// exclude selectors by default
@@ -3917,7 +3921,11 @@ protected function libIndex($args)
return self::$null;
}
- if ($list[0] === Type::T_MAP || $list[0] === Type::T_STRING || $list[0] === Type::T_KEYWORD || $list[0] === Type::T_INTERPOLATE) {
+ if ($list[0] === Type::T_MAP ||
+ $list[0] === Type::T_STRING ||
+ $list[0] === Type::T_KEYWORD ||
+ $list[0] === Type::T_INTERPOLATE
+ ) {
$list = $this->coerceList($list, ' ');
}
@@ -4727,7 +4735,9 @@ protected function libComparable($args)
{
list($number1, $number2) = $args;
- if (! isset($number1[0]) || $number1[0] !== Type::T_NUMBER || ! isset($number2[0]) || $number2[0] !== Type::T_NUMBER) {
+ if (! isset($number1[0]) || $number1[0] !== Type::T_NUMBER ||
+ ! isset($number2[0]) || $number2[0] !== Type::T_NUMBER
+ ) {
$this->throwError('Invalid argument(s) for "comparable"');
}
diff --git a/src/Parser.php b/src/Parser.php
index 1b3498b4..205cda6d 100644
--- a/src/Parser.php
+++ b/src/Parser.php
@@ -29,20 +29,20 @@ class Parser
* @var array
*/
protected static $precedence = array(
- '=' => 0,
- 'or' => 1,
+ '=' => 0,
+ 'or' => 1,
'and' => 2,
- '==' => 3,
- '!=' => 3,
- '<=' => 4,
- '>=' => 4,
- '<' => 4,
- '>' => 4,
- '+' => 5,
- '-' => 5,
- '*' => 6,
- '/' => 6,
- '%' => 6,
+ '==' => 3,
+ '!=' => 3,
+ '<=' => 4,
+ '>=' => 4,
+ '<' => 4,
+ '>' => 4,
+ '+' => 5,
+ '-' => 5,
+ '*' => 6,
+ '/' => 6,
+ '%' => 6,
);
/**
@@ -98,9 +98,9 @@ public function __construct($sourceName, $sourceIndex = 0)
if (empty(self::$operatorStr)) {
self::$operatorStr = $this->makeOperatorStr(self::$operators);
- $commentSingle = $this->pregQuote(self::$commentSingle);
- $commentMultiLeft = $this->pregQuote(self::$commentMultiLeft);
- $commentMultiRight = $this->pregQuote(self::$commentMultiRight);
+ $commentSingle = $this->pregQuote(self::$commentSingle);
+ $commentMultiLeft = $this->pregQuote(self::$commentMultiLeft);
+ $commentMultiRight = $this->pregQuote(self::$commentMultiRight);
self::$commentMulti = $commentMultiLeft . '.*?' . $commentMultiRight;
self::$whitePattern = '/' . $commentSingle . '[^\n]*\s*|(' . self::$commentMulti . ')\s*|\s+/Ais';
}
@@ -709,12 +709,11 @@ protected function parseChunk()
protected function pushBlock($selectors, $pos = 0)
{
$b = new Block;
- $b->parent = $this->env;
-
+ $b->parent = $this->env;
$b->sourcePosition = $pos;
- $b->sourceIndex = $this->sourceIndex;
- $b->selectors = $selectors;
- $b->comments = array();
+ $b->sourceIndex = $this->sourceIndex;
+ $b->selectors = $selectors;
+ $b->comments = array();
if (! $this->env) {
$b->children = array();
@@ -962,7 +961,7 @@ protected function append($statement, $pos = null)
{
if ($pos !== null) {
$statement[self::SOURCE_POSITION] = $pos;
- $statement[self::SOURCE_INDEX] = $this->sourceIndex;
+ $statement[self::SOURCE_INDEX] = $this->sourceIndex;
}
$this->env->children[] = $statement;
@@ -1038,7 +1037,7 @@ protected function mediaQuery(&$out)
}
}
- $prop[] = $media;
+ $prop[] = $media;
$parts[] = $prop;
}
@@ -1801,8 +1800,8 @@ protected function openString($end, &$out, $nestingOpen = null)
$oldWhite = $this->eatWhiteDefault;
$this->eatWhiteDefault = false;
- $stop = array('\'', '"', '#{', $end);
- $stop = array_map(array($this, 'pregQuote'), $stop);
+ $stop = array('\'', '"', '#{', $end);
+ $stop = array_map(array($this, 'pregQuote'), $stop);
$stop[] = self::$commentMulti;
$patt = '(.*?)(' . implode('|', $stop) . ')';
From e36c909f61afb4c92909073cad1317ca73602120 Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Fri, 6 Nov 2015 11:14:57 -0500
Subject: [PATCH 159/534] internals: cleanup
---
src/Compiler.php | 8 ++++----
src/Parser.php | 16 +---------------
2 files changed, 5 insertions(+), 19 deletions(-)
diff --git a/src/Compiler.php b/src/Compiler.php
index 47a9c476..0f412c42 100644
--- a/src/Compiler.php
+++ b/src/Compiler.php
@@ -3494,7 +3494,7 @@ private function coerceValue($value)
}
if (is_bool($value)) {
- return $value ? self::$true : self::$false;
+ return $this->toBool($value);
}
if ($value === null) {
@@ -4866,7 +4866,7 @@ protected function libGlobalVariableExists($args)
$string = $this->coerceString($args[0]);
$name = $this->compileStringContent($string);
- return $this->has($name, $this->rootEnv) ? self::$true : self::$false;
+ return $this->has($name, $this->rootEnv);
}
protected static $libMixinExists = array('name');
@@ -4875,7 +4875,7 @@ protected function libMixinExists($args)
$string = $this->coerceString($args[0]);
$name = $this->compileStringContent($string);
- return $this->has(self::$namespaces['mixin'] . $name) ? self::$true : self::$false;
+ return $this->has(self::$namespaces['mixin'] . $name);
}
protected static $libVariableExists = array('name');
@@ -4884,7 +4884,7 @@ protected function libVariableExists($args)
$string = $this->coerceString($args[0]);
$name = $this->compileStringContent($string);
- return $this->has($name) ? self::$true : self::$false;
+ return $this->has($name);
}
/**
diff --git a/src/Parser.php b/src/Parser.php
index 205cda6d..6729a68c 100644
--- a/src/Parser.php
+++ b/src/Parser.php
@@ -96,7 +96,7 @@ public function __construct($sourceName, $sourceIndex = 0)
$this->charset = null;
if (empty(self::$operatorStr)) {
- self::$operatorStr = $this->makeOperatorStr(self::$operators);
+ self::$operatorStr = '(' . implode('|', array_map(array($this, 'pregQuote'), self::$operators)) . ')';
$commentSingle = $this->pregQuote(self::$commentSingle);
$commentMultiLeft = $this->pregQuote(self::$commentMultiLeft);
@@ -259,20 +259,6 @@ public static function pregQuote($what)
return preg_quote($what, '/');
}
- /**
- * Make operator regex
- *
- * @param array $operators
- *
- * @return string
- */
- protected static function makeOperatorStr($operators)
- {
- return '('
- . implode('|', array_map(array('Leafo\ScssPhp\Parser', 'pregQuote'), $operators))
- . ')';
- }
-
/**
* Parse a single chunk off the head of the buffer and append it to the
* current parse environment.
From c9fdc3d0945b76ea77e90b0ef590ea6dc55ac68e Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Fri, 6 Nov 2015 11:28:11 -0500
Subject: [PATCH 160/534] Experimental features: spaceship <=> operator,
@break, @continue
---
src/Compiler.php | 58 ++++++++++++++++++++---
src/Parser.php | 23 +++++++++-
src/Type.php | 3 ++
tests/inputs/looping.scss | 63 +++++++++++++++++++++++++
tests/inputs/operators.scss | 4 ++
tests/outputs/looping.css | 21 +++++++++
tests/outputs/operators.css | 5 +-
tests/outputs_numbered/looping.css | 21 +++++++++
tests/outputs_numbered/operators.css | 69 +++++++++++++++-------------
9 files changed, 224 insertions(+), 43 deletions(-)
diff --git a/src/Compiler.php b/src/Compiler.php
index 0f412c42..68be1725 100644
--- a/src/Compiler.php
+++ b/src/Compiler.php
@@ -79,6 +79,7 @@ class Compiler
'<=' => 'lte',
'>=' => 'gte',
+ '<=>' => 'cmp',
);
/**
@@ -1505,9 +1506,6 @@ protected function compileChild($child, OutputBlock $out)
}
break;
- case Type::T_RETURN:
- return $this->reduce($child[1], true);
-
case Type::T_EACH:
list(, $each) = $child;
@@ -1529,9 +1527,15 @@ protected function compileChild($child, OutputBlock $out)
$ret = $this->compileChildren($each->children, $out);
if ($ret) {
- $this->popEnv();
+ if ($ret[0] !== Type::T_CONTROL) {
+ $this->popEnv();
+
+ return $ret;
+ }
- return $ret;
+ if ($ret[1]) {
+ break;
+ }
}
}
@@ -1545,7 +1549,13 @@ protected function compileChild($child, OutputBlock $out)
$ret = $this->compileChildren($while->children, $out);
if ($ret) {
- return $ret;
+ if ($ret[0] !== Type::T_CONTROL) {
+ return $ret;
+ }
+
+ if ($ret[1]) {
+ break;
+ }
}
}
break;
@@ -1572,11 +1582,26 @@ protected function compileChild($child, OutputBlock $out)
$ret = $this->compileChildren($for->children, $out);
if ($ret) {
- return $ret;
+ if ($ret[0] !== Type::T_CONTROL) {
+ return $ret;
+ }
+
+ if ($ret[1]) {
+ break;
+ }
}
}
break;
+ case Type::T_BREAK:
+ return array(Type::T_CONTROL, true);
+
+ case Type::T_CONTINUE:
+ return array(Type::T_CONTROL, false);
+
+ case Type::T_RETURN:
+ return $this->reduce($child[1], true);
+
case Type::T_NESTED_PROPERTY:
list(, $prop) = $child;
@@ -1674,6 +1699,10 @@ protected function compileChild($child, OutputBlock $out)
$this->throwError("Line $line ERROR: $value\n");
break;
+ case Type::T_CONTROL:
+ $this->throwError('@break/@continue not permitted in this scope');
+ break;
+
default:
$this->throwError("unknown child type: $child[0]");
}
@@ -2375,6 +2404,21 @@ protected function opLtNumberNumber($left, $right)
return $this->toBool($left[1] < $right[1]);
}
+ /**
+ * Three-way comparison, aka spaceship operator
+ *
+ * @param array $left
+ * @param array $right
+ *
+ * @return array
+ */
+ protected function opCmpNumberNumber($left, $right)
+ {
+ $n = $left[1] - $right[1];
+
+ return array(Type::T_NUMBER, $n ? $n / abs($n) : 0, '');
+ }
+
/**
* Cast to boolean
*
diff --git a/src/Parser.php b/src/Parser.php
index 6729a68c..573f5c30 100644
--- a/src/Parser.php
+++ b/src/Parser.php
@@ -34,6 +34,7 @@ class Parser
'and' => 2,
'==' => 3,
'!=' => 3,
+ '<=>' => 3,
'<=' => 4,
'>=' => 4,
'<' => 4,
@@ -56,6 +57,7 @@ class Parser
'%',
'==',
'!=',
+ '<=>',
'<=',
'>=',
'<',
@@ -411,8 +413,25 @@ protected function parseChunk()
$this->seek($s);
- if ($this->literal('@return') && $this->valueList($retVal) && $this->end()) {
- $this->append(array(Type::T_RETURN, $retVal), $s);
+ if ($this->literal('@break') && $this->end()) {
+ $this->append(array(Type::T_BREAK), $s);
+
+ return true;
+ }
+
+ $this->seek($s);
+
+ if ($this->literal('@continue') && $this->end()) {
+ $this->append(array(Type::T_CONTINUE), $s);
+
+ return true;
+ }
+
+ $this->seek($s);
+
+
+ if ($this->literal('@return') && ($this->valueList($retVal) || true) && $this->end()) {
+ $this->append(array(Type::T_RETURN, isset($retVal) ? $retVal : array(Type::T_NULL)), $s);
return true;
}
diff --git a/src/Type.php b/src/Type.php
index 2402f7a4..b750bbe4 100644
--- a/src/Type.php
+++ b/src/Type.php
@@ -21,9 +21,12 @@ class Type
const T_ASSIGN = 'assign';
const T_AT_ROOT = 'at-root';
const T_BLOCK = 'block';
+ const T_BREAK = 'break';
const T_CHARSET = 'charset';
const T_COLOR = 'color';
const T_COMMENT = 'comment';
+ const T_CONTINUE = 'continue';
+ const T_CONTROL = 'control';
const T_DEBUG = 'debug';
const T_DIRECTIVE = 'directive';
const T_EACH = 'each';
diff --git a/tests/inputs/looping.scss b/tests/inputs/looping.scss
index dd96b12c..665bce99 100644
--- a/tests/inputs/looping.scss
+++ b/tests/inputs/looping.scss
@@ -88,3 +88,66 @@ div {
c: is-number("3");
c: is-number(5);
}
+
+body.each {
+ @each $x in 1 2 3 4 5 {
+ @if $x == 2 or $x == 4 {
+ background-color: $x;
+ @continue;
+ }
+
+ color: $x;
+
+ @if $x == 5 {
+ @break;
+ }
+ @else {
+ @continue;
+ }
+
+ color: "not reached";
+ }
+}
+
+body.for {
+ @for $x from 1 through 5 {
+ @if $x == 2 or $x == 4 {
+ background-color: $x;
+ @continue;
+ }
+
+ color: $x;
+
+ @if $x == 5 {
+ @break;
+ }
+ @else {
+ @continue;
+ }
+
+ color: "not reached";
+ }
+}
+
+body.while {
+ $x: 0;
+ @while $x <= 5 {
+ $x: $x+1;
+
+ @if $x == 2 or $x == 4 {
+ background-color: $x;
+ @continue;
+ }
+
+ color: $x;
+
+ @if $x == 5 {
+ @break;
+ }
+ @else {
+ @continue;
+ }
+
+ color: "not reached";
+ }
+}
diff --git a/tests/inputs/operators.scss b/tests/inputs/operators.scss
index 98ae7cb0..2b4fea4f 100644
--- a/tests/inputs/operators.scss
+++ b/tests/inputs/operators.scss
@@ -19,6 +19,10 @@ div {
color: 4 > 3;
color: 4 < 3;
color: what > 3;
+
+ color: 0 <=> 0;
+ color: 1 <=> 2;
+ color: 2 <=> 1;
}
diff --git a/tests/outputs/looping.css b/tests/outputs/looping.css
index 1dd81d68..2d313b1f 100644
--- a/tests/outputs/looping.css
+++ b/tests/outputs/looping.css
@@ -62,3 +62,24 @@ div {
b: true;
c: true;
c: true; }
+
+body.each {
+ color: 1;
+ background-color: 2;
+ color: 3;
+ background-color: 4;
+ color: 5; }
+
+body.for {
+ color: 1;
+ background-color: 2;
+ color: 3;
+ background-color: 4;
+ color: 5; }
+
+body.while {
+ color: 1;
+ background-color: 2;
+ color: 3;
+ background-color: 4;
+ color: 5; }
diff --git a/tests/outputs/operators.css b/tests/outputs/operators.css
index c592c08e..3a236c57 100644
--- a/tests/outputs/operators.css
+++ b/tests/outputs/operators.css
@@ -14,7 +14,10 @@ div {
color: true;
color: true;
color: false;
- color: what > 3; }
+ color: what > 3;
+ color: 0;
+ color: -1;
+ color: 1; }
#units {
test: 2.5748in;
diff --git a/tests/outputs_numbered/looping.css b/tests/outputs_numbered/looping.css
index 921e978f..3ca7273c 100644
--- a/tests/outputs_numbered/looping.css
+++ b/tests/outputs_numbered/looping.css
@@ -66,3 +66,24 @@ div {
b: true;
c: true;
c: true; }
+/* line 92, inputs/looping.scss */
+body.each {
+ color: 1;
+ background-color: 2;
+ color: 3;
+ background-color: 4;
+ color: 5; }
+/* line 112, inputs/looping.scss */
+body.for {
+ color: 1;
+ background-color: 2;
+ color: 3;
+ background-color: 4;
+ color: 5; }
+/* line 132, inputs/looping.scss */
+body.while {
+ color: 1;
+ background-color: 2;
+ color: 3;
+ background-color: 4;
+ color: 5; }
diff --git a/tests/outputs_numbered/operators.css b/tests/outputs_numbered/operators.css
index c379809d..0d35202f 100644
--- a/tests/outputs_numbered/operators.css
+++ b/tests/outputs_numbered/operators.css
@@ -15,19 +15,22 @@ div {
color: true;
color: true;
color: false;
- color: what > 3; }
-/* line 25, inputs/operators.scss */
+ color: what > 3;
+ color: 0;
+ color: -1;
+ color: 1; }
+/* line 29, inputs/operators.scss */
#units {
test: 2.5748in;
test: 13mm;
test: 4em;
test: 11mm;
test: 1.1cm; }
-/* line 33, inputs/operators.scss */
+/* line 37, inputs/operators.scss */
#modulo {
test: 1;
test: 1cm; }
-/* line 38, inputs/operators.scss */
+/* line 42, inputs/operators.scss */
#colors {
color: #ff0203;
color: #fe0000;
@@ -42,11 +45,11 @@ div {
color: true;
color: true;
color: false; }
-/* line 59, inputs/operators.scss */
+/* line 63, inputs/operators.scss */
#preserve {
hello: what -going;
hello: what - going; }
-/* line 64, inputs/operators.scss */
+/* line 68, inputs/operators.scss */
#strings {
hello: what -going;
hello: whatgoing;
@@ -56,12 +59,12 @@ div {
hello: "whatgoing";
hello: goingwhat;
hello: "whatwhat"; }
-/* line 77, inputs/operators.scss */
+/* line 81, inputs/operators.scss */
#negation {
a: -60;
b: -90;
b: -90; }
-/* line 84, inputs/operators.scss */
+/* line 88, inputs/operators.scss */
#bools-fail {
and: false and two;
and: one and two;
@@ -69,7 +72,7 @@ div {
or: false or two;
or: one or two;
or: one or false; }
-/* line 94, inputs/operators.scss */
+/* line 98, inputs/operators.scss */
#bools {
and: false;
and: two;
@@ -77,7 +80,7 @@ div {
or: two;
or: one;
or: one; }
-/* line 105, inputs/operators.scss */
+/* line 109, inputs/operators.scss */
#nots-fail {
not: false2;
not: not false;
@@ -85,7 +88,7 @@ div {
not: not 1;
not: not "";
not: not hello; }
-/* line 114, inputs/operators.scss */
+/* line 118, inputs/operators.scss */
#nots {
not: false2;
not: true;
@@ -93,7 +96,7 @@ div {
not: false;
not: false;
not: false; }
-/* line 123, inputs/operators.scss */
+/* line 127, inputs/operators.scss */
#string-test {
str: true;
str: false;
@@ -101,66 +104,66 @@ div {
str: true;
str: xhellohellofalse;
str: true; }
-/* line 139, inputs/operators.scss */
+/* line 143, inputs/operators.scss */
#special {
cancel-unit: 1; }
-/* line 146, inputs/operators.scss */
+/* line 150, inputs/operators.scss */
.row .a {
margin: -0.5em; }
-/* line 147, inputs/operators.scss */
+/* line 151, inputs/operators.scss */
.row .b {
margin: -0.5em; }
-/* line 148, inputs/operators.scss */
+/* line 152, inputs/operators.scss */
.row .c {
margin: -0.5em; }
-/* line 149, inputs/operators.scss */
+/* line 153, inputs/operators.scss */
.row .d {
margin: -0.5em; }
-/* line 150, inputs/operators.scss */
+/* line 154, inputs/operators.scss */
.row .e {
margin: 0 -0.5em; }
-/* line 152, inputs/operators.scss */
+/* line 156, inputs/operators.scss */
.alt .a {
margin: -0.5em; }
-/* line 153, inputs/operators.scss */
+/* line 157, inputs/operators.scss */
.alt .b {
margin: -0.5em; }
-/* line 154, inputs/operators.scss */
+/* line 158, inputs/operators.scss */
.alt .c {
margin: -0.5em; }
-/* line 155, inputs/operators.scss */
+/* line 159, inputs/operators.scss */
.alt .d {
margin: 0 -0.5em; }
-/* line 156, inputs/operators.scss */
+/* line 160, inputs/operators.scss */
.alt .e {
margin: 0 -0.5em; }
-/* line 158, inputs/operators.scss */
+/* line 162, inputs/operators.scss */
.row .f {
margin: -2em; }
-/* line 159, inputs/operators.scss */
+/* line 163, inputs/operators.scss */
.row .g {
margin: -2em; }
-/* line 160, inputs/operators.scss */
+/* line 164, inputs/operators.scss */
.row .h {
margin: -2em; }
-/* line 161, inputs/operators.scss */
+/* line 165, inputs/operators.scss */
.row .i {
margin: -2em; }
-/* line 162, inputs/operators.scss */
+/* line 166, inputs/operators.scss */
.row .j {
margin: 0 -2em; }
-/* line 164, inputs/operators.scss */
+/* line 168, inputs/operators.scss */
.alt .f {
margin: -2em; }
-/* line 165, inputs/operators.scss */
+/* line 169, inputs/operators.scss */
.alt .g {
margin: -2em; }
-/* line 166, inputs/operators.scss */
+/* line 170, inputs/operators.scss */
.alt .h {
margin: -2em; }
-/* line 167, inputs/operators.scss */
+/* line 171, inputs/operators.scss */
.alt .i {
margin: 0 -2em; }
-/* line 168, inputs/operators.scss */
+/* line 172, inputs/operators.scss */
.alt .j {
margin: 0 -2em; }
From 7099e1f69dac59f34d2dec1aff54e55bb53911c1 Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Fri, 6 Nov 2015 23:08:04 -0500
Subject: [PATCH 161/534] probably fixes #372 - strip unprintables from buffer
---
src/Parser.php | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/Parser.php b/src/Parser.php
index 573f5c30..0a64e241 100644
--- a/src/Parser.php
+++ b/src/Parser.php
@@ -178,7 +178,7 @@ public function parse($buffer)
$this->env = null;
$this->inParens = false;
$this->eatWhiteDefault = true;
- $this->buffer = $buffer;
+ $this->buffer = rtrim($buffer, "\x00..\x1f");
$this->pushBlock(null); // root block
From e485594b658cd10eec3b30e4ad3e7c20664c9c1e Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Fri, 6 Nov 2015 14:34:52 -0500
Subject: [PATCH 162/534] Node\Number abstraction
---
scss.inc.php | 1 +
src/Compiler.php | 159 ++++++++++-------------------
src/Node.php | 14 +++
src/Node/Number.php | 236 ++++++++++++++++++++++++++++++++++++++++++++
src/Parser.php | 3 +-
5 files changed, 306 insertions(+), 107 deletions(-)
create mode 100644 src/Node/Number.php
diff --git a/scss.inc.php b/scss.inc.php
index a8fe358d..d2871155 100644
--- a/scss.inc.php
+++ b/scss.inc.php
@@ -18,6 +18,7 @@
include_once __DIR__ . '/src/Formatter/Nested.php';
include_once __DIR__ . '/src/Formatter/OutputBlock.php';
include_once __DIR__ . '/src/Node.php';
+ include_once __DIR__ . '/src/Node/Number.php';
include_once __DIR__ . '/src/Parser.php';
include_once __DIR__ . '/src/Type.php';
include_once __DIR__ . '/src/Util.php';
diff --git a/src/Compiler.php b/src/Compiler.php
index 68be1725..8df83575 100644
--- a/src/Compiler.php
+++ b/src/Compiler.php
@@ -16,6 +16,7 @@
use Leafo\ScssPhp\Colors;
use Leafo\ScssPhp\Compiler\Environment;
use Leafo\ScssPhp\Formatter\OutputBlock;
+use Leafo\ScssPhp\Node;
use Leafo\ScssPhp\Type;
use Leafo\ScssPhp\Parser;
use Leafo\ScssPhp\Util;
@@ -91,21 +92,6 @@ class Compiler
'function' => '^',
);
- /**
- * @var array
- */
- static protected $unitTable = array(
- 'in' => array(
- 'in' => 1,
- 'pt' => 72,
- 'pc' => 6,
- 'cm' => 2.54,
- 'mm' => 25.4,
- 'px' => 96,
- 'q' => 101.6,
- ),
- );
-
static public $true = array(Type::T_KEYWORD, 'true');
static public $false = array(Type::T_KEYWORD, 'false');
static public $null = array(Type::T_NULL);
@@ -128,7 +114,6 @@ class Compiler
'global-variable-shadowing' => false,
);
- protected $numberPrecision = 5;
protected $lineNumberStyle = null;
protected $formatter = 'Leafo\ScssPhp\Formatter\Nested';
@@ -314,13 +299,13 @@ protected function flattenSelectors(OutputBlock $block, $parentKey = null)
// remove duplicates
array_walk($selectors, function (&$value) {
- $value = json_encode($value);
+ $value = serialize($value);
});
$selectors = array_unique($selectors);
array_walk($selectors, function (&$value) {
- $value = json_decode($value);
+ $value = unserialize($value);
});
}
}
@@ -1576,7 +1561,7 @@ protected function compileChild($child, OutputBlock $out)
break;
}
- $this->set($for->var, array(Type::T_NUMBER, $start, ''));
+ $this->set($for->var, new Node\Number($start, ''));
$start += $d;
$ret = $this->compileChildren($for->children, $out);
@@ -1797,8 +1782,11 @@ protected function reduce($value, $inExp = false)
$right = $this->reduce($right, true);
}
- // special case: looks like css short-hand
- if ($opName === 'div' && ! $inParens && ! $inExp && isset($right[2]) && $right[2] !== '') {
+ // special case: looks like css shorthand
+ if ($opName == 'div' && ! $inParens && ! $inExp && isset($right[2])
+ && (($right[0] !== Type::T_NUMBER && $right[2] != '')
+ || ($right[0] === Type::T_NUMBER && ! $right->unitless()))
+ ) {
return $this->expToString($value);
}
@@ -1831,22 +1819,22 @@ protected function reduce($value, $inExp = false)
if (! isset($genOp) &&
$left[0] === Type::T_NUMBER && $right[0] === Type::T_NUMBER
) {
- if ($opName === 'mod' && $right[2] !== '') {
- $this->throwError("Cannot modulo by a number with units: $right[1]$right[2].");
+ if ($opName === 'mod' && ! $right->unitless()) {
+ $this->throwError("Cannot modulo by a number with units: %s%s", $right[1], $right->unitStr());
}
$unitChange = true;
- $emptyUnit = $left[2] === '' || $right[2] === '';
- $targetUnit = '' !== $left[2] ? $left[2] : $right[2];
+ $emptyUnit = $left->unitless() || $right->unitless();
+ $targetUnit = $left->unitless() ? $right[2] : $left[2];
if ($opName !== 'mul') {
- $left[2] = '' !== $left[2] ? $left[2] : $targetUnit;
- $right[2] = '' !== $right[2] ? $right[2] : $targetUnit;
+ $left[2] = $left->unitless() ? $targetUnit : $left[2];
+ $right[2] = $right->unitless() ? $targetUnit : $right[2];
}
if ($opName !== 'mod') {
- $left = $this->normalizeNumber($left);
- $right = $this->normalizeNumber($right);
+ $left = $left->normalize();
+ $right = $right->normalize();
}
if ($opName === 'div' && ! $emptyUnit && $left[2] === $right[2]) {
@@ -1854,8 +1842,8 @@ protected function reduce($value, $inExp = false)
}
if ($opName === 'mul') {
- $left[2] = '' !== $left[2] ? $left[2] : $right[2];
- $right[2] = '' !== $right[2] ? $right[2] : $left[2];
+ $left[2] = $left->unitless() ? $right[2] : $left[2];
+ $right[2] = $right->unitless() ? $left[2] : $right[2];
} elseif ($opName === 'div' && $left[2] === $right[2]) {
$left[2] = '';
$right[2] = '';
@@ -1872,7 +1860,7 @@ protected function reduce($value, $inExp = false)
if (isset($out)) {
if ($unitChange && $out[0] === Type::T_NUMBER) {
- $out = $this->coerceUnit($out, $targetUnit);
+ $out = $out->coerce($targetUnit);
}
return $out;
@@ -1890,12 +1878,10 @@ protected function reduce($value, $inExp = false)
if ($exp[0] === Type::T_NUMBER) {
switch ($op) {
case '+':
- return $exp;
+ return new Node\Number($exp[1], $exp[2]);
case '-':
- $exp[1] *= -1;
-
- return $exp;
+ return new Node\Number(-$exp[1], $exp[2]);
}
}
@@ -1938,7 +1924,7 @@ protected function reduce($value, $inExp = false)
case Type::T_STRING:
foreach ($value[2] as &$item) {
- if (is_array($item)) {
+ if (is_array($item) || $item instanceof \ArrayAccess) {
$item = $this->reduce($item);
}
}
@@ -2034,7 +2020,7 @@ public function normalizeValue($value)
return array($type, '"', array($this->compileStringContent($value)));
case Type::T_NUMBER:
- return $this->normalizeNumber($value);
+ return $value->normalize();
case Type::T_INTERPOLATE:
return array(Type::T_KEYWORD, $this->compileValue($value));
@@ -2044,26 +2030,6 @@ public function normalizeValue($value)
}
}
- /**
- * Normalize number; just does physical lengths for now
- *
- * @param array $number
- *
- * @return array
- */
- protected function normalizeNumber($number)
- {
- list(, $value, $unit) = $number;
-
- if (isset(self::$unitTable['in'][$unit])) {
- $conv = self::$unitTable['in'][$unit];
-
- return array(Type::T_NUMBER, $value / $conv, 'in');
- }
-
- return $number;
- }
-
/**
* Add numbers
*
@@ -2074,7 +2040,7 @@ protected function normalizeNumber($number)
*/
protected function opAddNumberNumber($left, $right)
{
- return array(Type::T_NUMBER, $left[1] + $right[1], $left[2]);
+ return new Node\Number($left[1] + $right[1], $left[2]);
}
/**
@@ -2087,7 +2053,7 @@ protected function opAddNumberNumber($left, $right)
*/
protected function opMulNumberNumber($left, $right)
{
- return array(Type::T_NUMBER, $left[1] * $right[1], $left[2]);
+ return new Node\Number($left[1] * $right[1], $left[2]);
}
/**
@@ -2100,7 +2066,7 @@ protected function opMulNumberNumber($left, $right)
*/
protected function opSubNumberNumber($left, $right)
{
- return array(Type::T_NUMBER, $left[1] - $right[1], $left[2]);
+ return new Node\Number($left[1] - $right[1], $left[2]);
}
/**
@@ -2117,7 +2083,7 @@ protected function opDivNumberNumber($left, $right)
return array(Type::T_STRING, '', array($left[1] . $left[2] . '/' . $right[1] . $right[2]));
}
- return array(Type::T_NUMBER, $left[1] / $right[1], $left[2]);
+ return new Node\Number($left[1] / $right[1], $left[2]);
}
/**
@@ -2130,7 +2096,7 @@ protected function opDivNumberNumber($left, $right)
*/
protected function opModNumberNumber($left, $right)
{
- return array(Type::T_NUMBER, $left[1] % $right[1], $left[2]);
+ return new Node\Number($left[1] % $right[1], $left[2]);
}
/**
@@ -2416,7 +2382,7 @@ protected function opCmpNumberNumber($left, $right)
{
$n = $left[1] - $right[1];
- return array(Type::T_NUMBER, $n ? $n / abs($n) : 0, '');
+ return new Node\Number($n ? $n / abs($n) : 0, '');
}
/**
@@ -2485,7 +2451,7 @@ public function compileValue($value)
return $h;
case Type::T_NUMBER:
- return round($value[1], $this->numberPrecision) . $value[2];
+ return (string) $value;
case Type::T_STRING:
return $value[1] . $this->compileStringContent($value) . $value[1];
@@ -2598,7 +2564,7 @@ protected function compileStringContent($string)
$parts = array();
foreach ($string[2] as $part) {
- if (is_array($part)) {
+ if (is_array($part) || $part instanceof \ArrayAccess) {
$parts[] = $this->compileValue($part);
} else {
$parts[] = $part;
@@ -3066,7 +3032,7 @@ public function setImportPaths($path)
*/
public function setNumberPrecision($numberPrecision)
{
- $this->numberPrecision = $numberPrecision;
+ Node\Number::$precision = $numberPrecision;
}
/**
@@ -3533,7 +3499,7 @@ protected function applyArguments($argDef, $argValues)
*/
private function coerceValue($value)
{
- if (is_array($value)) {
+ if (is_array($value) || $value instanceof \ArrayAccess) {
return $value;
}
@@ -3546,7 +3512,7 @@ private function coerceValue($value)
}
if (is_numeric($value)) {
- return array(Type::T_NUMBER, $value, '');
+ return new Node\Number($value, '');
}
if ($value === '') {
@@ -3556,25 +3522,6 @@ private function coerceValue($value)
return array(Type::T_KEYWORD, $value);
}
- /**
- * Coerce unit on number to be normalized
- *
- * @param array $number
- * @param string $unit
- *
- * @return array
- */
- protected function coerceUnit($number, $unit)
- {
- list(, $value, $baseUnit) = $number;
-
- if (isset(self::$unitTable[$baseUnit][$unit])) {
- $value = $value * self::$unitTable[$baseUnit][$unit];
- }
-
- return array(Type::T_NUMBER, $value, $unit);
- }
-
/**
* Coerce something to map
*
@@ -4234,7 +4181,7 @@ protected function libHue($args)
$color = $this->assertColor($args[0]);
$hsl = $this->toHSL($color[1], $color[2], $color[3]);
- return array(Type::T_NUMBER, $hsl[1], 'deg');
+ return new Node\Number($hsl[1], 'deg');
}
protected static $libSaturation = array('color');
@@ -4243,7 +4190,7 @@ protected function libSaturation($args)
$color = $this->assertColor($args[0]);
$hsl = $this->toHSL($color[1], $color[2], $color[3]);
- return array(Type::T_NUMBER, $hsl[2], '%');
+ return new Node\Number($hsl[2], '%');
}
protected static $libLightness = array('color');
@@ -4252,7 +4199,7 @@ protected function libLightness($args)
$color = $this->assertColor($args[0]);
$hsl = $this->toHSL($color[1], $color[2], $color[3]);
- return array(Type::T_NUMBER, $hsl[3], '%');
+ return new Node\Number($hsl[3], '%');
}
protected function adjustHsl($color, $idx, $amount)
@@ -4305,7 +4252,7 @@ protected function libSaturate($args)
}
$color = $this->assertColor($value);
- $amount = 100*$this->coercePercent($args[1]);
+ $amount = 100 * $this->coercePercent($args[1]);
return $this->adjustHsl($color, 2, $amount);
}
@@ -4314,7 +4261,7 @@ protected function libSaturate($args)
protected function libDesaturate($args)
{
$color = $this->assertColor($args[0]);
- $amount = 100*$this->coercePercent($args[1]);
+ $amount = 100 * $this->coercePercent($args[1]);
return $this->adjustHsl($color, 2, -$amount);
}
@@ -4419,7 +4366,7 @@ protected function libQuote($args)
protected static $libPercentage = array('value');
protected function libPercentage($args)
{
- return array(Type::T_NUMBER, $this->coercePercent($args[0]) * 100, '%');
+ return new Node\Number($this->coercePercent($args[0]) * 100, '%');
}
protected static $libRound = array('value');
@@ -4504,13 +4451,13 @@ protected function getNormalizedNumbers($args)
$this->throwError('%s is not a number', $item[0]);
}
- $number = $this->normalizeNumber($item);
+ $number = $item->normalize();
if (null === $unit) {
$unit = $number[2];
- $originalUnit = $item[2];
+ $originalUnit = $item->unitStr();
} elseif ($unit !== $number[2]) {
- $this->throwError('Incompatible units: "%s" and "%s".', $originalUnit, $item[2]);
+ $this->throwError('Incompatible units: "%s" and "%s".', $originalUnit, $item->unitStr());
}
$numbers[$key] = $number;
@@ -4760,7 +4707,7 @@ protected function libUnit($args)
$num = $args[0];
if ($num[0] === Type::T_NUMBER) {
- return array(Type::T_STRING, '"', array($num[2]));
+ return array(Type::T_STRING, '"', array($num->unitStr()));
}
return '';
@@ -4771,7 +4718,7 @@ protected function libUnitless($args)
{
$value = $args[0];
- return $value[0] === Type::T_NUMBER && empty($value[2]);
+ return $value[0] === Type::T_NUMBER && $value->unitless();
}
protected static $libComparable = array('number-1', 'number-2');
@@ -4785,10 +4732,10 @@ protected function libComparable($args)
$this->throwError('Invalid argument(s) for "comparable"');
}
- $number1 = $this->normalizeNumber($number1);
- $number2 = $this->normalizeNumber($number2);
+ $number1 = $number1->normalize();
+ $number2 = $number2->normalize();
- return $number1[2] === $number2[2] || $number1[2] === '' || $number2[2] === '';
+ return $number1[2] === $number2[2] || $number1->unitless() || $number2->unitless();
}
protected static $libStrIndex = array('string', 'substring');
@@ -4802,7 +4749,7 @@ protected function libStrIndex($args)
$result = strpos($stringContent, $substringContent);
- return $result === false ? self::$null : array(Type::T_NUMBER, $result + 1, '');
+ return $result === false ? self::$null : new Node\Number($result + 1, '');
}
protected static $libStrInsert = array('string', 'insert', 'index');
@@ -4827,7 +4774,7 @@ protected function libStrLength($args)
$string = $this->coerceString($args[0]);
$stringContent = $this->compileStringContent($string);
- return array(Type::T_NUMBER, strlen($stringContent), '');
+ return new Node\Number(strlen($stringContent), '');
}
protected static $libStrSlice = array('string', 'start-at', 'end-at');
@@ -4952,10 +4899,10 @@ protected function libRandom($args)
$this->throwError("limit must be greater than or equal to 1");
}
- return array(Type::T_NUMBER, mt_rand(1, $n), '');
+ return new Node\Number(mt_rand(1, $n), '');
}
- return array(Type::T_NUMBER, mt_rand(1, mt_getrandmax()), '');
+ return new Node\Number(mt_rand(1, mt_getrandmax()), '');
}
protected function libUniqueId()
diff --git a/src/Node.php b/src/Node.php
index 107ee574..d09f597e 100644
--- a/src/Node.php
+++ b/src/Node.php
@@ -18,4 +18,18 @@
*/
abstract class Node
{
+ /**
+ * @var string
+ */
+ public $type;
+
+ /**
+ * @var integer
+ */
+ public $sourcePosition;
+
+ /**
+ * @var integer
+ */
+ public $sourceIndex;
}
diff --git a/src/Node/Number.php b/src/Node/Number.php
new file mode 100644
index 00000000..a0abcd2b
--- /dev/null
+++ b/src/Node/Number.php
@@ -0,0 +1,236 @@
+
+ */
+class Number extends Node implements \ArrayAccess
+{
+ /**
+ * @var integer
+ */
+ static public $precision = 5;
+
+ /**
+ * @see http://www.w3.org/TR/2012/WD-css3-values-20120308/
+ *
+ * @var array
+ */
+ static protected $unitTable = array(
+ 'in' => array(
+ 'in' => 1,
+ 'pc' => 6,
+ 'pt' => 72,
+ 'px' => 96,
+ 'cm' => 2.54,
+ 'mm' => 25.4,
+ 'q' => 101.6,
+ ),
+ 'turn' => array(
+ 'deg' => 180,
+ 'grad' => 200,
+ 'rad' => M_PI,
+ 'turn' => 0.5,
+ ),
+ 's' => array(
+ 's' => 1,
+ 'ms' => 1000,
+ ),
+ 'Hz' => array(
+ 'Hz' => 1,
+ 'kHz' => 0.001,
+ ),
+ 'dpi' => array(
+ 'dpi' => 1,
+ 'dpcm' => 2.54,
+ 'dppx' => 96,
+ ),
+ );
+
+ /**
+ * @var integer|float
+ */
+ public $dimension;
+
+ /**
+ * @var string
+ */
+ public $units;
+
+ /**
+ * Initialize number
+ *
+ * @param mixed $dimension
+ * @param string $initialUnit
+ */
+ public function __construct($dimension, $initialUnit)
+ {
+ $this->type = Type::T_NUMBER;
+ $this->dimension = $dimension;
+ $this->units = $initialUnit;
+ }
+
+ /**
+ * Coerce number to target units
+ *
+ * @param array $units
+ *
+ * @return \Leafo\ScssPhp\Node\Number
+ */
+ public function coerce($units)
+ {
+ $value = $this->dimension;
+
+ if (isset(self::$unitTable[$this->units][$units])) {
+ $value *= self::$unitTable[$this->units][$units];
+ }
+
+ return new Number($value, $units);
+ }
+
+ /**
+ * Normalize number
+ *
+ * @return \Leafo\ScssPhp\Node\Number
+ */
+ public function normalize()
+ {
+ if (isset(self::$unitTable['in'][$this->units])) {
+ $conv = self::$unitTable['in'][$this->units];
+
+ return new Number($this->dimension / $conv, 'in');
+ }
+
+ return new Number($this->dimension, $this->units);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function offsetExists($offset)
+ {
+ if ($offset === -2) {
+ return $sourceIndex !== null;
+ }
+
+ if ($offset === -1
+ || $offset === 0
+ || $offset === 1
+ || $offset === 2
+ ) {
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function offsetGet($offset)
+ {
+ switch ($offset) {
+ case -2:
+ return $this->sourceIndex;
+
+ case -1:
+ return $this->sourcePosition;
+
+ case 0:
+ return $this->type;
+
+ case 1:
+ return $this->dimension;
+
+ case 2:
+ return $this->units;
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function offsetSet($offset, $value)
+ {
+ if ($offset === 1) {
+ $this->dimension = $value;
+ } elseif ($offset === 2) {
+ $this->units = $value;
+ } elseif ($offset == -1) {
+ $this->sourcePosition = $value;
+ } elseif ($offset == -2) {
+ $this->sourceIndex = $value;
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function offsetUnset($offset)
+ {
+ if ($offset === 1) {
+ $this->dimension = null;
+ } elseif ($offset === 2) {
+ $this->units = null;
+ } elseif ($offset === -1) {
+ $this->sourcePosition = null;
+ } elseif ($offset === -2) {
+ $this->sourceIndex = null;
+ }
+ }
+
+ /**
+ * Returns true if the number is unitless
+ *
+ * @return boolean
+ */
+ public function unitless()
+ {
+ return empty($this->units);
+ }
+
+ /**
+ * Returns unit(s) as the product of numerator units divided by the product of denominator units
+ *
+ * @return string
+ */
+ public function unitStr()
+ {
+ return $this->units;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function __toString()
+ {
+ $value = round($this->dimension, self::$precision);
+
+ if (empty($this->units)) {
+ return (string) $value;
+ }
+
+ return (string) $value . $this->units;
+ }
+}
diff --git a/src/Parser.php b/src/Parser.php
index 0a64e241..f613a6a6 100644
--- a/src/Parser.php
+++ b/src/Parser.php
@@ -13,6 +13,7 @@
use Leafo\ScssPhp\Block;
use Leafo\ScssPhp\Compiler;
+use Leafo\ScssPhp\Node;
use Leafo\ScssPhp\Type;
/**
@@ -1678,7 +1679,7 @@ protected function color(&$out)
protected function unit(&$unit)
{
if ($this->match('([0-9]*(\.)?[0-9]+)([%a-zA-Z]+)?', $m)) {
- $unit = array(Type::T_NUMBER, $m[1], empty($m[3]) ? '' : $m[3]);
+ $unit = new Node\Number($m[1], empty($m[3]) ? '' : $m[3]);
return true;
}
From 4d25d6dee8285b768ad6064c876184786b570565 Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Sat, 7 Nov 2015 12:20:56 -0500
Subject: [PATCH 163/534] phpcs
---
src/Compiler.php | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/src/Compiler.php b/src/Compiler.php
index 8df83575..e547fa05 100644
--- a/src/Compiler.php
+++ b/src/Compiler.php
@@ -1820,7 +1820,11 @@ protected function reduce($value, $inExp = false)
$left[0] === Type::T_NUMBER && $right[0] === Type::T_NUMBER
) {
if ($opName === 'mod' && ! $right->unitless()) {
- $this->throwError("Cannot modulo by a number with units: %s%s", $right[1], $right->unitStr());
+ $this->throwError(
+ 'Cannot modulo by a number with units: %s%s',
+ $right[1],
+ $right->unitStr()
+ );
}
$unitChange = true;
From e969f521d3fdcc618cb23858bdd32853987d6fcb Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Sat, 7 Nov 2015 12:42:27 -0500
Subject: [PATCH 164/534] update scss_test.rb from sass/sass
---
tests/scss_test.rb | 28 ++++++++++++++++++++++++++++
1 file changed, 28 insertions(+)
diff --git a/tests/scss_test.rb b/tests/scss_test.rb
index de3e90e6..3d849d8a 100644
--- a/tests/scss_test.rb
+++ b/tests/scss_test.rb
@@ -457,6 +457,15 @@ def test_line_comment_in_script
SCSS
end
+ def test_static_hyphenated_unit
+ assert_equal < :compressed))
+@import url("fallback-layout.css") supports(not (display: flex))
+CSS
+$display-type: flex;
+@import url("fallback-layout.css") supports(not (display: #{$display-type}));
+SASS
+ end
+
+ def test_import_with_supports_clause
+ assert_equal(< :compressed))
+@import url("fallback-layout.css") supports(not (display: flex));.foo{bar:baz}
+CSS
+@import url("fallback-layout.css") supports(not (display: flex));
+.foo { bar: baz; }
+SASS
+ end
+
end
From bec3a7ac2182b830f8dedc8146ce09d20786c5fb Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Sun, 8 Nov 2015 14:41:35 -0500
Subject: [PATCH 165/534] fixes #361 - remove deprecated classmap.php file
---
box.json.dist | 1 -
classmap.php | 63 ---------------------------------------------------
composer.json | 1 -
scss.inc.php | 1 -
4 files changed, 66 deletions(-)
delete mode 100644 classmap.php
diff --git a/box.json.dist b/box.json.dist
index 9e61a65e..63d13baf 100644
--- a/box.json.dist
+++ b/box.json.dist
@@ -2,7 +2,6 @@
"chmod": "0755",
"files": [
"LICENSE.md",
- "classmap.php",
"scss.inc.php"
],
"directories": ["src"],
diff --git a/classmap.php b/classmap.php
deleted file mode 100644
index 2d8a52b8..00000000
--- a/classmap.php
+++ /dev/null
@@ -1,63 +0,0 @@
-
Date: Sun, 8 Nov 2015 14:59:36 -0500
Subject: [PATCH 166/534] fixes #360 - raise php requirement to 5.4
---
.travis.yml | 1 -
bin/pscss | 4 ++--
composer.json | 2 +-
scss.inc.php | 4 ++--
4 files changed, 5 insertions(+), 6 deletions(-)
diff --git a/.travis.yml b/.travis.yml
index 8c3a2996..aa251129 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -2,7 +2,6 @@ language: php
sudo: false
php:
- - 5.3
- 5.4
- 5.5
- 5.6
diff --git a/bin/pscss b/bin/pscss
index f4b7ba8f..4dd5136a 100755
--- a/bin/pscss
+++ b/bin/pscss
@@ -12,8 +12,8 @@
error_reporting(E_ALL);
-if (version_compare(PHP_VERSION, '5.3') < 0) {
- die('Requires PHP 5.3 or above');
+if (version_compare(PHP_VERSION, '5.4') < 0) {
+ die('Requires PHP 5.4 or above');
}
include __DIR__ . '/../scss.inc.php';
diff --git a/composer.json b/composer.json
index 4a1a4e13..691a68a2 100644
--- a/composer.json
+++ b/composer.json
@@ -21,7 +21,7 @@
"psr-4": { "Leafo\\ScssPhp\\Test\\": "tests/" }
},
"require": {
- "php": ">=5.3.0"
+ "php": ">=5.4.0"
},
"require-dev": {
"squizlabs/php_codesniffer": "~2.3",
diff --git a/scss.inc.php b/scss.inc.php
index 4d2e6152..b7409a48 100644
--- a/scss.inc.php
+++ b/scss.inc.php
@@ -1,6 +1,6 @@
Date: Sun, 8 Nov 2015 16:15:14 -0500
Subject: [PATCH 167/534] prep for 0.4.0 release
---
src/Version.php | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/Version.php b/src/Version.php
index f5769285..9216885a 100644
--- a/src/Version.php
+++ b/src/Version.php
@@ -18,5 +18,5 @@
*/
class Version
{
- const VERSION = 'v0.3.3';
+ const VERSION = 'v0.4.0';
}
From 61448e5b75020b496064b0a240e87fbe9767db39 Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Sun, 8 Nov 2015 17:16:36 -0500
Subject: [PATCH 168/534] internals: minor refactoring
---
src/Compiler.php | 4 ++--
src/Parser.php | 55 ++++++++++++++++++++++++++++++------------------
2 files changed, 37 insertions(+), 22 deletions(-)
diff --git a/src/Compiler.php b/src/Compiler.php
index e547fa05..7cf11465 100644
--- a/src/Compiler.php
+++ b/src/Compiler.php
@@ -2191,7 +2191,7 @@ protected function opColorColor($op, $left, $right)
{
$out = array(Type::T_COLOR);
- foreach (range(1, 3) as $i) {
+ foreach (array(1, 2, 3) as $i) {
$lval = isset($left[$i]) ? $left[$i] : 0;
$rval = isset($right[$i]) ? $right[$i] : 0;
@@ -3754,7 +3754,7 @@ public function assertNumber($value)
*/
protected function fixColor($c)
{
- foreach (range(1, 3) as $i) {
+ foreach (array(1, 2, 3) as $i) {
if ($c[$i] < 0) {
$c[$i] = 0;
}
diff --git a/src/Parser.php b/src/Parser.php
index f613a6a6..3679f6da 100644
--- a/src/Parser.php
+++ b/src/Parser.php
@@ -1645,20 +1645,20 @@ protected function color(&$out)
if ($this->match('(#([0-9a-f]{6})|#([0-9a-f]{3}))', $m)) {
if (isset($m[3])) {
- $num = $m[3];
- $width = 16;
- } else {
- $num = $m[2];
- $width = 256;
- }
+ $num = hexdec($m[3]);
- $num = hexdec($num);
-
- foreach (array(3, 2, 1) as $i) {
- $t = $num % $width;
- $num /= $width;
+ foreach (array(3, 2, 1) as $i) {
+ $t = $num & 0xf;
+ $color[$i] = $t << 4 | $t;
+ $num >>= 4;
+ }
+ } else {
+ $num = hexdec($m[2]);
- $color[$i] = $t * (256/$width) + $t * floor(16/$width);
+ foreach (array(3, 2, 1) as $i) {
+ $color[$i] = $num & 0xff;
+ $num >>= 8;
+ }
}
$out = $color;
@@ -1894,11 +1894,13 @@ protected function interpolation(&$out, $lookWhite = true)
if ($this->eatWhiteDefault) {
$this->whitespace();
}
+
return true;
}
$this->seek($s);
$this->eatWhiteDefault = $oldWhite;
+
return false;
}
@@ -1920,14 +1922,21 @@ protected function propertyName(&$out)
for (;;) {
if ($this->interpolation($inter)) {
$parts[] = $inter;
- } elseif ($this->keyword($text)) {
+ continue;
+ }
+
+ if ($this->keyword($text)) {
$parts[] = $text;
- } elseif (count($parts) === 0 && $this->match('[:.#]', $m, false)) {
+ continue;
+ }
+
+ if (count($parts) === 0 && $this->match('[:.#]', $m, false)) {
// css hacks
$parts[] = $m[0];
- } else {
- break;
+ continue;
}
+
+ break;
}
$this->eatWhiteDefault = $oldWhite;
@@ -2006,15 +2015,21 @@ protected function selector(&$out)
for (;;) {
if ($this->match('[>+~]+', $m)) {
$selector[] = array($m[0]);
- } elseif ($this->selectorSingle($part)) {
+ continue;
+ }
+
+ if ($this->selectorSingle($part)) {
$selector[] = $part;
$this->match('\s+', $m);
- } elseif ($this->match('\/[^\/]+\/', $m)) {
+ continue;
+ }
+
+ if ($this->match('\/[^\/]+\/', $m)) {
$selector[] = array($m[0]);
- } else {
- break;
+ continue;
}
+ break;
}
if (count($selector) === 0) {
From c96cd5fe32154e3e7dfa6a86fbcad125df2e01de Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Sun, 8 Nov 2015 21:02:18 -0500
Subject: [PATCH 169/534] internals: reduce pregQuote() use
---
src/Parser.php | 79 +++++++++++++++++---------------------------------
1 file changed, 26 insertions(+), 53 deletions(-)
diff --git a/src/Parser.php b/src/Parser.php
index 3679f6da..cbf86829 100644
--- a/src/Parser.php
+++ b/src/Parser.php
@@ -47,33 +47,9 @@ class Parser
'%' => 6,
);
- /**
- * @var array
- */
- protected static $operators = array(
- '+',
- '-',
- '*',
- '/',
- '%',
- '==',
- '!=',
- '<=>',
- '<=',
- '>=',
- '<',
- '>',
- 'and',
- 'or',
- );
-
- protected static $operatorStr;
+ protected static $commentPattern;
+ protected static $operatorPattern;
protected static $whitePattern;
- protected static $commentMulti;
-
- protected static $commentSingle = '//';
- protected static $commentMultiLeft = '/*';
- protected static $commentMultiRight = '*/';
private $sourceName;
private $sourceIndex;
@@ -98,14 +74,15 @@ public function __construct($sourceName, $sourceIndex = 0)
$this->sourceIndex = $sourceIndex;
$this->charset = null;
- if (empty(self::$operatorStr)) {
- self::$operatorStr = '(' . implode('|', array_map(array($this, 'pregQuote'), self::$operators)) . ')';
+ if (empty(self::$operatorPattern)) {
+ self::$operatorPattern = '([*\/%+-]|[!=]\=|\>\=?|\<\=\>|\<\=?|and|or)';
- $commentSingle = $this->pregQuote(self::$commentSingle);
- $commentMultiLeft = $this->pregQuote(self::$commentMultiLeft);
- $commentMultiRight = $this->pregQuote(self::$commentMultiRight);
- self::$commentMulti = $commentMultiLeft . '.*?' . $commentMultiRight;
- self::$whitePattern = '/' . $commentSingle . '[^\n]*\s*|(' . self::$commentMulti . ')\s*|\s+/Ais';
+ $commentSingle = '\/\/';
+ $commentMultiLeft = '\/\*';
+ $commentMultiRight = '\*\/';
+
+ self::$commentPattern = $commentMultiLeft . '.*?' . $commentMultiRight;
+ self::$whitePattern = '/' . $commentSingle . '[^\n]*\s*|(' . self::$commentPattern . ')\s*|\s+/Ais';
}
}
@@ -250,18 +227,6 @@ public function parseSelector($buffer, &$out)
return $this->selectors($out);
}
- /**
- * Quote regular expression
- *
- * @param string $what
- *
- * @return string
- */
- public static function pregQuote($what)
- {
- return preg_quote($what, '/');
- }
-
/**
* Parse a single chunk off the head of the buffer and append it to the
* current parse environment.
@@ -1257,13 +1222,13 @@ protected function expression(&$out)
*/
protected function expHelper($lhs, $minP)
{
- $opstr = self::$operatorStr;
+ $operators = self::$operatorPattern;
$ss = $this->seek();
$whiteBefore = isset($this->buffer[$this->count - 1]) &&
ctype_space($this->buffer[$this->count - 1]);
- while ($this->match($opstr, $m, false) && self::$precedence[$m[1]] >= $minP) {
+ while ($this->match($operators, $m, false) && self::$precedence[$m[1]] >= $minP) {
$whiteAfter = isset($this->buffer[$this->count]) &&
ctype_space($this->buffer[$this->count]);
$varAfter = isset($this->buffer[$this->count]) &&
@@ -1283,7 +1248,7 @@ protected function expHelper($lhs, $minP)
}
// peek and see if rhs belongs to next operator
- if ($this->peek($opstr, $next) && self::$precedence[$next[1]] > self::$precedence[$op]) {
+ if ($this->peek($operators, $next) && self::$precedence[$next[1]] > self::$precedence[$op]) {
$rhs = $this->expHelper($rhs, self::$precedence[$next[1]]);
}
@@ -1806,11 +1771,7 @@ protected function openString($end, &$out, $nestingOpen = null)
$oldWhite = $this->eatWhiteDefault;
$this->eatWhiteDefault = false;
- $stop = array('\'', '"', '#{', $end);
- $stop = array_map(array($this, 'pregQuote'), $stop);
- $stop[] = self::$commentMulti;
-
- $patt = '(.*?)(' . implode('|', $stop) . ')';
+ $patt = '(.*?)([\'"]|#\{|' . $this->pregQuote($end) . '|' . self::$commentPattern . ')';
$nestingLevel = 0;
@@ -2401,4 +2362,16 @@ protected function show()
return '';
}
+
+ /**
+ * Quote regular expression
+ *
+ * @param string $what
+ *
+ * @return string
+ */
+ private function pregQuote($what)
+ {
+ return preg_quote($what, '/');
+ }
}
From 1323ac596fc7443768c6ab3c7fd4342288b67ca0 Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Mon, 9 Nov 2015 09:44:00 -0500
Subject: [PATCH 170/534] Revert "fixes #361 - remove deprecated classmap.php
file"
This reverts commit bec3a7ac2182b830f8dedc8146ce09d20786c5fb.
---
box.json.dist | 1 +
classmap.php | 63 +++++++++++++++++++++++++++++++++++++++++++++++++++
composer.json | 1 +
scss.inc.php | 1 +
4 files changed, 66 insertions(+)
create mode 100644 classmap.php
diff --git a/box.json.dist b/box.json.dist
index 63d13baf..9e61a65e 100644
--- a/box.json.dist
+++ b/box.json.dist
@@ -2,6 +2,7 @@
"chmod": "0755",
"files": [
"LICENSE.md",
+ "classmap.php",
"scss.inc.php"
],
"directories": ["src"],
diff --git a/classmap.php b/classmap.php
new file mode 100644
index 00000000..2d8a52b8
--- /dev/null
+++ b/classmap.php
@@ -0,0 +1,63 @@
+
Date: Mon, 9 Nov 2015 09:44:09 -0500
Subject: [PATCH 171/534] Revert "fixes #360 - raise php requirement to 5.4"
This reverts commit 90996f57ea08cf12003c4292714bc60dcf081ee7.
---
.travis.yml | 1 +
bin/pscss | 4 ++--
composer.json | 2 +-
scss.inc.php | 4 ++--
4 files changed, 6 insertions(+), 5 deletions(-)
diff --git a/.travis.yml b/.travis.yml
index aa251129..8c3a2996 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -2,6 +2,7 @@ language: php
sudo: false
php:
+ - 5.3
- 5.4
- 5.5
- 5.6
diff --git a/bin/pscss b/bin/pscss
index 4dd5136a..f4b7ba8f 100755
--- a/bin/pscss
+++ b/bin/pscss
@@ -12,8 +12,8 @@
error_reporting(E_ALL);
-if (version_compare(PHP_VERSION, '5.4') < 0) {
- die('Requires PHP 5.4 or above');
+if (version_compare(PHP_VERSION, '5.3') < 0) {
+ die('Requires PHP 5.3 or above');
}
include __DIR__ . '/../scss.inc.php';
diff --git a/composer.json b/composer.json
index cd386f82..c63339c3 100644
--- a/composer.json
+++ b/composer.json
@@ -22,7 +22,7 @@
"psr-4": { "Leafo\\ScssPhp\\Test\\": "tests/" }
},
"require": {
- "php": ">=5.4.0"
+ "php": ">=5.3.0"
},
"require-dev": {
"squizlabs/php_codesniffer": "~2.3",
diff --git a/scss.inc.php b/scss.inc.php
index de741d06..d2871155 100644
--- a/scss.inc.php
+++ b/scss.inc.php
@@ -1,6 +1,6 @@
Date: Tue, 10 Nov 2015 15:04:59 -0500
Subject: [PATCH 172/534] fix: ! null === true
---
src/Compiler.php | 2 +-
tests/inputs/operators.scss | 1 +
tests/outputs/operators.css | 3 +-
tests/outputs_numbered/operators.css | 47 ++++++++++++++--------------
4 files changed, 28 insertions(+), 25 deletions(-)
diff --git a/src/Compiler.php b/src/Compiler.php
index 7cf11465..b6f4953c 100644
--- a/src/Compiler.php
+++ b/src/Compiler.php
@@ -1891,7 +1891,7 @@ protected function reduce($value, $inExp = false)
if ($op === 'not') {
if ($inExp || $inParens) {
- if ($exp === self::$false) {
+ if ($exp === self::$false || $exp === self::$null) {
return self::$true;
}
diff --git a/tests/inputs/operators.scss b/tests/inputs/operators.scss
index 2b4fea4f..0d881c09 100644
--- a/tests/inputs/operators.scss
+++ b/tests/inputs/operators.scss
@@ -122,6 +122,7 @@ div {
not: (not 1);
not: (not "");
not: (not hello);
+ not: (not null);
}
#string-test {
diff --git a/tests/outputs/operators.css b/tests/outputs/operators.css
index 3a236c57..3c63406e 100644
--- a/tests/outputs/operators.css
+++ b/tests/outputs/operators.css
@@ -94,7 +94,8 @@ div {
not: false;
not: false;
not: false;
- not: false; }
+ not: false;
+ not: true; }
#string-test {
str: true;
diff --git a/tests/outputs_numbered/operators.css b/tests/outputs_numbered/operators.css
index 0d35202f..5dc5bef8 100644
--- a/tests/outputs_numbered/operators.css
+++ b/tests/outputs_numbered/operators.css
@@ -95,8 +95,9 @@ div {
not: false;
not: false;
not: false;
- not: false; }
-/* line 127, inputs/operators.scss */
+ not: false;
+ not: true; }
+/* line 128, inputs/operators.scss */
#string-test {
str: true;
str: false;
@@ -104,66 +105,66 @@ div {
str: true;
str: xhellohellofalse;
str: true; }
-/* line 143, inputs/operators.scss */
+/* line 144, inputs/operators.scss */
#special {
cancel-unit: 1; }
-/* line 150, inputs/operators.scss */
+/* line 151, inputs/operators.scss */
.row .a {
margin: -0.5em; }
-/* line 151, inputs/operators.scss */
+/* line 152, inputs/operators.scss */
.row .b {
margin: -0.5em; }
-/* line 152, inputs/operators.scss */
+/* line 153, inputs/operators.scss */
.row .c {
margin: -0.5em; }
-/* line 153, inputs/operators.scss */
+/* line 154, inputs/operators.scss */
.row .d {
margin: -0.5em; }
-/* line 154, inputs/operators.scss */
+/* line 155, inputs/operators.scss */
.row .e {
margin: 0 -0.5em; }
-/* line 156, inputs/operators.scss */
+/* line 157, inputs/operators.scss */
.alt .a {
margin: -0.5em; }
-/* line 157, inputs/operators.scss */
+/* line 158, inputs/operators.scss */
.alt .b {
margin: -0.5em; }
-/* line 158, inputs/operators.scss */
+/* line 159, inputs/operators.scss */
.alt .c {
margin: -0.5em; }
-/* line 159, inputs/operators.scss */
+/* line 160, inputs/operators.scss */
.alt .d {
margin: 0 -0.5em; }
-/* line 160, inputs/operators.scss */
+/* line 161, inputs/operators.scss */
.alt .e {
margin: 0 -0.5em; }
-/* line 162, inputs/operators.scss */
+/* line 163, inputs/operators.scss */
.row .f {
margin: -2em; }
-/* line 163, inputs/operators.scss */
+/* line 164, inputs/operators.scss */
.row .g {
margin: -2em; }
-/* line 164, inputs/operators.scss */
+/* line 165, inputs/operators.scss */
.row .h {
margin: -2em; }
-/* line 165, inputs/operators.scss */
+/* line 166, inputs/operators.scss */
.row .i {
margin: -2em; }
-/* line 166, inputs/operators.scss */
+/* line 167, inputs/operators.scss */
.row .j {
margin: 0 -2em; }
-/* line 168, inputs/operators.scss */
+/* line 169, inputs/operators.scss */
.alt .f {
margin: -2em; }
-/* line 169, inputs/operators.scss */
+/* line 170, inputs/operators.scss */
.alt .g {
margin: -2em; }
-/* line 170, inputs/operators.scss */
+/* line 171, inputs/operators.scss */
.alt .h {
margin: -2em; }
-/* line 171, inputs/operators.scss */
+/* line 172, inputs/operators.scss */
.alt .i {
margin: 0 -2em; }
-/* line 172, inputs/operators.scss */
+/* line 173, inputs/operators.scss */
.alt .j {
margin: 0 -2em; }
From 61bf507f69ff91c1591629520b7c9665b66d514b Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Tue, 10 Nov 2015 17:18:45 -0500
Subject: [PATCH 173/534] str-slice() compatibility fixes
---
src/Compiler.php | 36 +++++++++++++++++++++--------
tests/inputs/builtins.scss | 16 +++++++++++++
tests/outputs/builtins.css | 17 +++++++++++++-
tests/outputs_numbered/builtins.css | 33 ++++++++++++++++++--------
4 files changed, 82 insertions(+), 20 deletions(-)
diff --git a/src/Compiler.php b/src/Compiler.php
index b6f4953c..3f0c3ac3 100644
--- a/src/Compiler.php
+++ b/src/Compiler.php
@@ -95,6 +95,7 @@ class Compiler
static public $true = array(Type::T_KEYWORD, 'true');
static public $false = array(Type::T_KEYWORD, 'false');
static public $null = array(Type::T_NULL);
+ static public $nullString = array(Type::T_STRING, '', array());
static public $defaultValue = array(Type::T_KEYWORD, '');
static public $selfSelector = array(Type::T_SELF);
static public $emptyList = array(Type::T_LIST, '', array());
@@ -1431,7 +1432,7 @@ protected function compileChild($child, OutputBlock $out)
if ($value[0] !== Type::T_NULL) {
$value = $this->reduce($value);
- if ($value[0] === Type::T_NULL) {
+ if ($value[0] === Type::T_NULL || $value === self::$nullString) {
break;
}
}
@@ -1594,12 +1595,14 @@ protected function compileChild($child, OutputBlock $out)
$prefix = $this->compileValue($prop->prefix) . '-';
foreach ($prop->children as $child) {
- if ($child[0] === Type::T_ASSIGN) {
- array_unshift($child[1][2], $prefix);
- }
+ switch ($child[0]) {
+ case Type::T_ASSIGN:
+ array_unshift($child[1][2], $prefix);
+ break;
- if ($child[0] === Type::T_NESTED_PROPERTY) {
- array_unshift($child[1]->prefix[2], $prefix);
+ case Type::T_NESTED_PROPERTY:
+ array_unshift($child[1]->prefix[2], $prefix);
+ break;
}
$prefixed[] = $child;
@@ -4784,17 +4787,30 @@ protected function libStrLength($args)
protected static $libStrSlice = array('string', 'start-at', 'end-at');
protected function libStrSlice($args)
{
- if ($args[2][1] == 0) {
- return self::$null;
+ if (isset($args[2]) && $args[2][1] == 0) {
+ return self::$nullString;
}
$string = $this->coerceString($args[0]);
$stringContent = $this->compileStringContent($string);
- $start = (int) $args[1][1] ?: 1;
+ $start = (int) $args[1][1];
+ if ($start > 0) {
+ $start--;
+ }
+
$end = (int) $args[2][1];
+ if ($end < 0) {
+ $end++;
+ } elseif ($end > 0) {
+ $end -= $start;
+ }
+
+ if ($end === 0 || $end > strlen($stringContent)) {
+ $end = strlen($stringContent);
+ }
- $string[2] = array(substr($stringContent, $start - 1, ($end < 0 ? $end : $end - $start) + 1));
+ $string[2] = array(substr($stringContent, $start, $end));
return $string;
}
diff --git a/tests/inputs/builtins.scss b/tests/inputs/builtins.scss
index 7f54d41e..32066b40 100644
--- a/tests/inputs/builtins.scss
+++ b/tests/inputs/builtins.scss
@@ -84,6 +84,22 @@
color: str-slice(string, 2, -2);
color: to_lower_case('StRiNg');
color: to_upper_case(StRiNg);
+ color: str-slice(string, 0);
+ color: str-slice(string, 1);
+ color: str-slice(string, 2);
+ color: str-slice(string, 3);
+ color: str-slice(string, 4);
+ color: str-slice(string, 5);
+ color: str-slice(string, -1);
+ color: str-slice(string, -2);
+ color: str-slice(string, -3);
+ color: str-slice(string, -4);
+ color: str-slice(string, -5);
+ color: str-slice(string, 1, 0);
+ color: str-slice(string, 1, 1);
+ color: str-slice(string, 1, 2);
+ color: str-slice(string, 1, -1);
+ color: str-slice(string, 1, -2);
}
#number {
diff --git a/tests/outputs/builtins.css b/tests/outputs/builtins.css
index f7bc1f12..4d3ef6d8 100644
--- a/tests/outputs/builtins.css
+++ b/tests/outputs/builtins.css
@@ -57,7 +57,22 @@
color: tri;
color: trin;
color: 'string';
- color: STRING; }
+ color: STRING;
+ color: string;
+ color: string;
+ color: tring;
+ color: ring;
+ color: ing;
+ color: ng;
+ color: g;
+ color: ng;
+ color: ing;
+ color: ring;
+ color: tring;
+ color: s;
+ color: st;
+ color: string;
+ color: strin; }
#number {
color: 250%;
diff --git a/tests/outputs_numbered/builtins.css b/tests/outputs_numbered/builtins.css
index 08cbb0be..95bc7759 100644
--- a/tests/outputs_numbered/builtins.css
+++ b/tests/outputs_numbered/builtins.css
@@ -58,8 +58,23 @@
color: tri;
color: trin;
color: 'string';
- color: STRING; }
-/* line 89, inputs/builtins.scss */
+ color: STRING;
+ color: string;
+ color: string;
+ color: tring;
+ color: ring;
+ color: ing;
+ color: ng;
+ color: g;
+ color: ng;
+ color: ing;
+ color: ring;
+ color: tring;
+ color: s;
+ color: st;
+ color: string;
+ color: strin; }
+/* line 105, inputs/builtins.scss */
#number {
color: 250%;
color: 3;
@@ -70,7 +85,7 @@
width: 200%;
bottom: 10px;
padding: 3em 1in 96px 72pt; }
-/* line 102, inputs/builtins.scss */
+/* line 118, inputs/builtins.scss */
#list {
len: 3;
len: 1;
@@ -92,7 +107,7 @@
cool: great job one two three;
zip: 1px solid, 2px dashed;
zip: 1px solid red, 2px dashed green; }
-/* line 138, inputs/builtins.scss */
+/* line 154, inputs/builtins.scss */
#introspection {
t: number;
t: string;
@@ -112,31 +127,31 @@
c: true;
c: false;
c: true; }
-/* line 162, inputs/builtins.scss */
+/* line 178, inputs/builtins.scss */
#if {
color: yes;
color: no;
color: yes;
color: yes; }
-/* line 169, inputs/builtins.scss */
+/* line 185, inputs/builtins.scss */
.transparent {
r: 0;
g: 0;
b: 0;
a: 0; }
-/* line 176, inputs/builtins.scss */
+/* line 192, inputs/builtins.scss */
.alpha {
a: 1;
a: 1;
a: 1;
a: 0.5;
a: alpha(currentColor); }
-/* line 185, inputs/builtins.scss */
+/* line 201, inputs/builtins.scss */
#exists {
a: true;
b: true;
c: false; }
-/* line 192, inputs/builtins.scss */
+/* line 208, inputs/builtins.scss */
div.call-tests {
a: #0a64ff;
b: #0058ef;
From 8cb681f99c55c44a284142265b36b9c194aae2b0 Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Tue, 10 Nov 2015 20:09:54 -0500
Subject: [PATCH 174/534] Remove hhvm support/hacks
---
.travis.yml | 1 -
src/Compiler.php | 6 ------
2 files changed, 7 deletions(-)
diff --git a/.travis.yml b/.travis.yml
index 8c3a2996..1c727fcd 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -7,7 +7,6 @@ php:
- 5.5
- 5.6
- nightly
- - hhvm
script:
- phpunit tests
diff --git a/src/Compiler.php b/src/Compiler.php
index 3f0c3ac3..50cb6237 100644
--- a/src/Compiler.php
+++ b/src/Compiler.php
@@ -3956,9 +3956,6 @@ protected function libRgb($args)
protected function libRgba($args)
{
if ($color = $this->coerceColor($args[0])) {
- // workaround https://github.com/facebook/hhvm/issues/5457
- reset($args);
-
$num = ! isset($args[1]) ? $args[3] : $args[1];
$alpha = $this->assertNumber($num);
$color[4] = $alpha;
@@ -3976,9 +3973,6 @@ protected function alterColor($args, $fn)
{
$color = $this->assertColor($args[0]);
- // workaround https://github.com/facebook/hhvm/issues/5457
- reset($args);
-
foreach (array(1, 2, 3, 7) as $i) {
if (isset($args[$i])) {
$val = $this->assertNumber($args[$i]);
From 626cd788e350e9a7265750caa464af4e7c957d9c Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Tue, 10 Nov 2015 20:29:20 -0500
Subject: [PATCH 175/534] internals: code tweaks to libStrSlice()
---
src/Compiler.php | 17 ++++++-----------
1 file changed, 6 insertions(+), 11 deletions(-)
diff --git a/src/Compiler.php b/src/Compiler.php
index 50cb6237..96262659 100644
--- a/src/Compiler.php
+++ b/src/Compiler.php
@@ -4789,22 +4789,17 @@ protected function libStrSlice($args)
$stringContent = $this->compileStringContent($string);
$start = (int) $args[1][1];
+
if ($start > 0) {
$start--;
}
- $end = (int) $args[2][1];
- if ($end < 0) {
- $end++;
- } elseif ($end > 0) {
- $end -= $start;
- }
-
- if ($end === 0 || $end > strlen($stringContent)) {
- $end = strlen($stringContent);
- }
+ $end = (int) $args[2][1];
+ $length = $end < 0 ? $end + 1 : ($end > 0 ? $end - $start : $end);
- $string[2] = array(substr($stringContent, $start, $end));
+ $string[2] = $length
+ ? array(substr($stringContent, $start, $length))
+ : array(substr($stringContent, $start));
return $string;
}
From 91d857f8226a52bf1b62199d236a6dfc48df805a Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Mon, 9 Nov 2015 00:28:45 -0500
Subject: [PATCH 176/534] fixes #107 - incompatible units
---
src/Compiler.php | 62 ++++++------
src/Node/Number.php | 136 +++++++++++++++++++++------
tests/ExceptionTest.php | 6 ++
tests/FailingTest.php | 14 ---
tests/inputs/operators.scss | 20 +++-
tests/outputs/operators.css | 7 +-
tests/outputs_numbered/operators.css | 7 +-
7 files changed, 175 insertions(+), 77 deletions(-)
diff --git a/src/Compiler.php b/src/Compiler.php
index 96262659..1b666d08 100644
--- a/src/Compiler.php
+++ b/src/Compiler.php
@@ -1817,43 +1817,41 @@ protected function reduce($value, $inExp = false)
is_callable(array($this, $fn)) &&
$genOp = true)
) {
- $unitChange = false;
+ $coerceUnit = false;
if (! isset($genOp) &&
$left[0] === Type::T_NUMBER && $right[0] === Type::T_NUMBER
) {
- if ($opName === 'mod' && ! $right->unitless()) {
- $this->throwError(
- 'Cannot modulo by a number with units: %s%s',
- $right[1],
- $right->unitStr()
- );
- }
+ $coerceUnit = true;
- $unitChange = true;
- $emptyUnit = $left->unitless() || $right->unitless();
- $targetUnit = $left->unitless() ? $right[2] : $left[2];
+ switch ($opName) {
+ case 'mul':
+ $targetUnit = $left[2];
- if ($opName !== 'mul') {
- $left[2] = $left->unitless() ? $targetUnit : $left[2];
- $right[2] = $right->unitless() ? $targetUnit : $right[2];
- }
+ foreach ($right[2] as $unit => $exp) {
+ @$targetUnit[$unit] += $exp;
+ }
+ break;
- if ($opName !== 'mod') {
- $left = $left->normalize();
- $right = $right->normalize();
- }
+ case 'div':
+ $targetUnit = $left[2];
- if ($opName === 'div' && ! $emptyUnit && $left[2] === $right[2]) {
- $targetUnit = '';
+ foreach ($right[2] as $unit => $exp) {
+ @$targetUnit[$unit] -= $exp;
+ }
+ break;
+
+ case 'mod':
+ $targetUnit = $left[2];
+ break;
+
+ default:
+ $targetUnit = $left->unitless() ? $right[2] : $left[2];
}
- if ($opName === 'mul') {
- $left[2] = $left->unitless() ? $right[2] : $left[2];
- $right[2] = $right->unitless() ? $left[2] : $right[2];
- } elseif ($opName === 'div' && $left[2] === $right[2]) {
- $left[2] = '';
- $right[2] = '';
+ if (! $left->unitless() && ! $right->unitless()) {
+ $left = $left->normalize();
+ $right = $right->normalize();
}
}
@@ -1866,7 +1864,7 @@ protected function reduce($value, $inExp = false)
}
if (isset($out)) {
- if ($unitChange && $out[0] === Type::T_NUMBER) {
+ if ($coerceUnit && $out[0] === Type::T_NUMBER) {
$out = $out->coerce($targetUnit);
}
@@ -2458,7 +2456,7 @@ public function compileValue($value)
return $h;
case Type::T_NUMBER:
- return (string) $value;
+ return $value->output($this);
case Type::T_STRING:
return $value[1] . $this->compileStringContent($value) . $value[1];
@@ -3339,8 +3337,6 @@ function ($m) {
/**
* Sorts keyword arguments
*
- * @todo Merge with applyArguments()?
- *
* @param array $prototype
* @param array $args
*
@@ -3656,7 +3652,7 @@ protected function coerceString($value)
protected function coercePercent($value)
{
if ($value[0] === Type::T_NUMBER) {
- if ($value[2] === '%') {
+ if (isset($value[2]['%'])) {
return $value[1] / 100;
}
@@ -4068,7 +4064,7 @@ protected function libScaleColor($args)
protected function libIeHexStr($args)
{
$color = $this->coerceColor($args[0]);
- $color[4] = isset($color[4]) ? round(255*$color[4]) : 255;
+ $color[4] = isset($color[4]) ? round(255 * $color[4]) : 255;
return sprintf('#%02X%02X%02X%02X', $color[4], $color[1], $color[2], $color[3]);
}
diff --git a/src/Node/Number.php b/src/Node/Number.php
index a0abcd2b..929d816d 100644
--- a/src/Node/Number.php
+++ b/src/Node/Number.php
@@ -11,6 +11,7 @@
namespace Leafo\ScssPhp\Node;
+use Leafo\ScssPhp\Compiler;
use Leafo\ScssPhp\Node;
use Leafo\ScssPhp\Type;
@@ -48,21 +49,21 @@ class Number extends Node implements \ArrayAccess
'q' => 101.6,
),
'turn' => array(
- 'deg' => 180,
- 'grad' => 200,
- 'rad' => M_PI,
- 'turn' => 0.5,
+ 'deg' => 360,
+ 'grad' => 400,
+ 'rad' => 6.28318530717958647692528676, // 2 * M_PI
+ 'turn' => 1,
),
's' => array(
- 's' => 1,
+ 's' => 1,
'ms' => 1000,
),
'Hz' => array(
- 'Hz' => 1,
+ 'Hz' => 1,
'kHz' => 0.001,
),
'dpi' => array(
- 'dpi' => 1,
+ 'dpi' => 1,
'dpcm' => 2.54,
'dppx' => 96,
),
@@ -74,21 +75,24 @@ class Number extends Node implements \ArrayAccess
public $dimension;
/**
- * @var string
+ * @var array
*/
public $units;
/**
* Initialize number
*
- * @param mixed $dimension
- * @param string $initialUnit
+ * @param mixed $dimension
+ * @param mixed $initialUnit
*/
public function __construct($dimension, $initialUnit)
{
$this->type = Type::T_NUMBER;
$this->dimension = $dimension;
- $this->units = $initialUnit;
+ $this->units = is_array($initialUnit)
+ ? $initialUnit
+ : ($initialUnit ? array($initialUnit => 1)
+ : array());
}
/**
@@ -100,13 +104,19 @@ public function __construct($dimension, $initialUnit)
*/
public function coerce($units)
{
- $value = $this->dimension;
+ if ($this->unitless()) {
+ return new Number($this->dimension, $units);
+ }
+
+ $dimension = $this->dimension;
- if (isset(self::$unitTable[$this->units][$units])) {
- $value *= self::$unitTable[$this->units][$units];
+ foreach (self::$unitTable['in'] as $unit => $conv) {
+ $exp = @$this->units[$unit] - @$units[$unit];
+ $factor = pow($conv, $exp);
+ $dimension /= $factor;
}
- return new Number($value, $units);
+ return new Number($dimension, $units);
}
/**
@@ -116,13 +126,12 @@ public function coerce($units)
*/
public function normalize()
{
- if (isset(self::$unitTable['in'][$this->units])) {
- $conv = self::$unitTable['in'][$this->units];
+ $dimension = $this->dimension;
+ $units = array();
- return new Number($this->dimension / $conv, 'in');
- }
+ $this->normalizeUnits($dimension, $units, 'in');
- return new Number($this->dimension, $this->units);
+ return new Number($dimension, $units);
}
/**
@@ -207,7 +216,7 @@ public function offsetUnset($offset)
*/
public function unitless()
{
- return empty($this->units);
+ return ! array_sum($this->units);
}
/**
@@ -217,7 +226,62 @@ public function unitless()
*/
public function unitStr()
{
- return $this->units;
+ $numerators = array();
+ $denominators = array();
+
+ foreach ($this->units as $unit => $unitSize) {
+ if ($unitSize > 0) {
+ $numerators = array_pad($numerators, count($numerators) + $unitSize, $unit);
+ continue;
+ }
+
+ if ($unitSize < 0) {
+ $denominators = array_pad($denominators, count($denominators) + $unitSize, $unit);
+ continue;
+ }
+ }
+
+ return implode('*', $numerators) . (count($denominators) ? '/' . implode('*', $denominators) : '');
+ }
+
+ /**
+ * Output number
+ *
+ * @param \Leafo\ScssPhp\Compiler $compiler
+ *
+ * @return string
+ */
+ public function output(Compiler $compiler = null)
+ {
+ $dimension = round($this->dimension, self::$precision);
+
+ $units = array_filter($this->units, function ($unitSize) {
+ return $unitSize;
+ });
+
+ // @todo refactor normalize()
+ if (count($units) > 1 && array_sum($units) === 0) {
+ $dimension = $this->dimension;
+ $units = array();
+
+ $this->normalizeUnits($dimension, $units, 'in');
+
+ $dimension = round($dimension, self::$precision);
+ $units = array_filter($units, function ($unitSize) {
+ return $unitSize;
+ });
+ }
+
+ $unitSize = array_sum($units);
+
+ if ($compiler && ($unitSize > 1 || $unitSize < 0 || count($units) > 1)) {
+ $compiler->throwError((string) $dimension . $this->unitStr() . " isn't a valid CSS value.");
+ }
+
+ reset($units);
+ list($unit, ) = each($units);
+
+ return (string) $dimension . $unit;
}
/**
@@ -225,12 +289,30 @@ public function unitStr()
*/
public function __toString()
{
- $value = round($this->dimension, self::$precision);
+ return $this->output();
+ }
- if (empty($this->units)) {
- return (string) $value;
- }
+ /**
+ * Normalize units
+ *
+ * @param integer|float $dimension
+ * @param array $units
+ * @param string $baseUnit
+ */
+ private function normalizeUnits(&$dimension, &$units, $baseUnit = 'in')
+ {
+ $dimension = $this->dimension;
+ $units = array();
+
+ foreach ($this->units as $unit => $exp) {
+ if (isset(self::$unitTable[$baseUnit][$unit])) {
+ $factor = pow(self::$unitTable[$baseUnit][$unit], $exp);
- return (string) $value . $this->units;
+ $unit = $baseUnit;
+ $dimension /= $factor;
+ }
+
+ @$units[$unit] += $exp;
+ }
}
}
diff --git a/tests/ExceptionTest.php b/tests/ExceptionTest.php
index 4df1bae3..ea17abb5 100644
--- a/tests/ExceptionTest.php
+++ b/tests/ExceptionTest.php
@@ -123,6 +123,12 @@ public function provideScss()
,
'Undefined variable $bg'
),
+ array(<<<'END_OF_SCSS'
+div { bottom: (4/2px); }
+END_OF_SCSS
+ ,
+ 'isn\'t a valid CSS value'
+ ),
);
}
diff --git a/tests/FailingTest.php b/tests/FailingTest.php
index 7a074a77..863ffe00 100644
--- a/tests/FailingTest.php
+++ b/tests/FailingTest.php
@@ -84,20 +84,6 @@ public function provideFailing()
background: #eee; }
.nav-bar > .item, header ul > .item, header ul > li {
margin: 0 10px; }
-END_OF_EXPECTED
- ),
- array(
- '#107 - incompatible units (example 2)', <<<'END_OF_SCSS'
-$gridRowWidth: 20px;
-
-.foo
-{
-width: (2.5 / $gridRowWidth * 100px * 1% );
-}
-END_OF_SCSS
- , <<
Date: Sun, 8 Nov 2015 14:41:35 -0500
Subject: [PATCH 177/534] fixes #361 - remove deprecated classmap.php file
---
box.json.dist | 1 -
classmap.php | 63 ---------------------------------------------------
composer.json | 1 -
scss.inc.php | 1 -
4 files changed, 66 deletions(-)
delete mode 100644 classmap.php
diff --git a/box.json.dist b/box.json.dist
index 9e61a65e..63d13baf 100644
--- a/box.json.dist
+++ b/box.json.dist
@@ -2,7 +2,6 @@
"chmod": "0755",
"files": [
"LICENSE.md",
- "classmap.php",
"scss.inc.php"
],
"directories": ["src"],
diff --git a/classmap.php b/classmap.php
deleted file mode 100644
index 2d8a52b8..00000000
--- a/classmap.php
+++ /dev/null
@@ -1,63 +0,0 @@
-
Date: Sun, 8 Nov 2015 14:59:36 -0500
Subject: [PATCH 178/534] fixes #360 - raise php requirement to 5.4
---
.travis.yml | 1 -
bin/pscss | 4 ++--
composer.json | 2 +-
scss.inc.php | 4 ++--
4 files changed, 5 insertions(+), 6 deletions(-)
diff --git a/.travis.yml b/.travis.yml
index 1c727fcd..80b481f1 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -2,7 +2,6 @@ language: php
sudo: false
php:
- - 5.3
- 5.4
- 5.5
- 5.6
diff --git a/bin/pscss b/bin/pscss
index f4b7ba8f..4dd5136a 100755
--- a/bin/pscss
+++ b/bin/pscss
@@ -12,8 +12,8 @@
error_reporting(E_ALL);
-if (version_compare(PHP_VERSION, '5.3') < 0) {
- die('Requires PHP 5.3 or above');
+if (version_compare(PHP_VERSION, '5.4') < 0) {
+ die('Requires PHP 5.4 or above');
}
include __DIR__ . '/../scss.inc.php';
diff --git a/composer.json b/composer.json
index 4a1a4e13..691a68a2 100644
--- a/composer.json
+++ b/composer.json
@@ -21,7 +21,7 @@
"psr-4": { "Leafo\\ScssPhp\\Test\\": "tests/" }
},
"require": {
- "php": ">=5.3.0"
+ "php": ">=5.4.0"
},
"require-dev": {
"squizlabs/php_codesniffer": "~2.3",
diff --git a/scss.inc.php b/scss.inc.php
index 4d2e6152..b7409a48 100644
--- a/scss.inc.php
+++ b/scss.inc.php
@@ -1,6 +1,6 @@
Date: Wed, 11 Nov 2015 00:06:44 -0500
Subject: [PATCH 179/534] Bump version to 0.5.0
---
src/Version.php | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/Version.php b/src/Version.php
index 9216885a..fb19a731 100644
--- a/src/Version.php
+++ b/src/Version.php
@@ -18,5 +18,5 @@
*/
class Version
{
- const VERSION = 'v0.4.0';
+ const VERSION = 'v0.5.0';
}
From 27ac88271586743de9d3bb09e11a59607b8c2dff Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Wed, 11 Nov 2015 00:38:05 -0500
Subject: [PATCH 180/534] merges #341 - @scssphp-import-once
---
src/Compiler.php | 57 ++++++------------------------------------------
src/Parser.php | 2 +-
src/Type.php | 1 +
3 files changed, 9 insertions(+), 51 deletions(-)
diff --git a/src/Compiler.php b/src/Compiler.php
index 693359ab..15df21d6 100644
--- a/src/Compiler.php
+++ b/src/Compiler.php
@@ -1301,62 +1301,19 @@ protected function mergeMediaTypes($type1, $type2)
/**
* Compile import; returns true if the value was something that could be imported
*
- * @param array $rawPath
- * @param array $out
+ * @param array $rawPath
+ * @param array $out
+ * @param boolean $once
*
* @return boolean
*/
- protected function compileImport($rawPath, $out)
+ protected function compileImport($rawPath, $out, $once = false)
{
if ($rawPath[0] === Type::T_STRING) {
$path = $this->compileStringContent($rawPath);
if ($path = $this->findImport($path)) {
- $this->importFile($path, $out);
- $this->importedFiles[] = $path;
-
- return true;
- }
-
- return false;
- }
-
- if ($rawPath[0] === 'list') {
- // handle a list of strings
- if (count($rawPath[2]) === 0) {
- return false;
- }
-
- foreach ($rawPath[2] as $path) {
- if ($path[0] !== 'string') {
- return false;
- }
- }
-
- foreach ($rawPath[2] as $path) {
- $this->compileImport($path, $out);
- }
-
- return true;
- }
-
- return false;
- }
-
- /**
- * Compile importOnce; returns true if the value was something that could be imported
- *
- * @param array $rawPath
- * @param array $out
- *
- * @return boolean
- */
- protected function compileImportOnce($rawPath, $out)
- {
- if ($rawPath[0] === 'string') {
- $path = $this->compileStringContent($rawPath);
- if ($path = $this->findImport($path)) {
- if (!in_array($path, $this->importedFiles)) {
+ if (! $once || ! in_array($path, $this->importedFiles)) {
$this->importFile($path, $out);
$this->importedFiles[] = $path;
}
@@ -1403,13 +1360,13 @@ protected function compileChild($child, OutputBlock $out)
$this->sourcePos = isset($child[Parser::SOURCE_POSITION]) ? $child[Parser::SOURCE_POSITION] : -1;
switch ($child[0]) {
- case 'scssphp-import-once':
+ case Type::T_SCSSPHP_IMPORT_ONCE:
list(, $rawPath) = $child;
$rawPath = $this->reduce($rawPath);
if (! $this->compileImportOnce($rawPath, $out)) {
- $out->lines[] = '@scssphp-import-once ' . $this->compileValue($rawPath) . ';';
+ $out->lines[] = '@import ' . $this->compileValue($rawPath) . ';';
}
break;
diff --git a/src/Parser.php b/src/Parser.php
index 66e21a4f..9249878e 100644
--- a/src/Parser.php
+++ b/src/Parser.php
@@ -336,7 +336,7 @@ protected function parseChunk()
$this->valueList($importPath) &&
$this->end()
) {
- $this->append(array('scssphp-import-once', $importPath), $s);
+ $this->append(array(Type::T_SCSSPHP_IMPORT_ONCE, $importPath), $s);
return true;
}
diff --git a/src/Type.php b/src/Type.php
index b750bbe4..80b53258 100644
--- a/src/Type.php
+++ b/src/Type.php
@@ -59,6 +59,7 @@ class Type
const T_NUMBER = 'number';
const T_RETURN = 'return';
const T_ROOT = 'root';
+ const T_SCSSPHP_IMPORT_ONCE = 'scssphp-import-once';
const T_SELF = 'self';
const T_STRING = 'string';
const T_UNARY = 'unary';
From cb0c57ec553da73f8f01255225c189c3fa05409a Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Wed, 11 Nov 2015 01:18:49 -0500
Subject: [PATCH 181/534] refs #341 - call refactored compileImport()
---
src/Compiler.php | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/Compiler.php b/src/Compiler.php
index 15df21d6..56567e04 100644
--- a/src/Compiler.php
+++ b/src/Compiler.php
@@ -1365,7 +1365,7 @@ protected function compileChild($child, OutputBlock $out)
$rawPath = $this->reduce($rawPath);
- if (! $this->compileImportOnce($rawPath, $out)) {
+ if (! $this->compileImport($rawPath, $out, true)) {
$out->lines[] = '@import ' . $this->compileValue($rawPath) . ';';
}
break;
From 9e0bda70b230418c854e85da4c8c29fcea8c96cc Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Wed, 11 Nov 2015 17:12:40 -0500
Subject: [PATCH 182/534] fixes #378 - avoid notices in custom error handlers
that ignore @ operator
---
src/Compiler.php | 4 ++--
src/Node/Number.php | 7 ++++---
2 files changed, 6 insertions(+), 5 deletions(-)
diff --git a/src/Compiler.php b/src/Compiler.php
index 56567e04..03190c71 100644
--- a/src/Compiler.php
+++ b/src/Compiler.php
@@ -1844,7 +1844,7 @@ protected function reduce($value, $inExp = false)
$targetUnit = $left[2];
foreach ($right[2] as $unit => $exp) {
- @$targetUnit[$unit] += $exp;
+ $targetUnit[$unit] = (isset($targetUnit[$unit]) ? $targetUnit[$unit] : 0) + $exp;
}
break;
@@ -1852,7 +1852,7 @@ protected function reduce($value, $inExp = false)
$targetUnit = $left[2];
foreach ($right[2] as $unit => $exp) {
- @$targetUnit[$unit] -= $exp;
+ $targetUnit[$unit] = (isset($targetUnit[$unit]) ? $targetUnit[$unit] : 0) - $exp;
}
break;
diff --git a/src/Node/Number.php b/src/Node/Number.php
index 929d816d..3727a768 100644
--- a/src/Node/Number.php
+++ b/src/Node/Number.php
@@ -111,8 +111,9 @@ public function coerce($units)
$dimension = $this->dimension;
foreach (self::$unitTable['in'] as $unit => $conv) {
- $exp = @$this->units[$unit] - @$units[$unit];
- $factor = pow($conv, $exp);
+ $from = isset($this->units[$unit]) ? $this->units[$unit] : 0;
+ $to = isset($units[$unit]) ? $units[$unit] : 0;
+ $factor = pow($conv, $from - $to);
$dimension /= $factor;
}
@@ -312,7 +313,7 @@ private function normalizeUnits(&$dimension, &$units, $baseUnit = 'in')
$dimension /= $factor;
}
- @$units[$unit] += $exp;
+ $units[$unit] = $exp + (isset($units[$unit]) ? $units[$unit] : 0);
}
}
}
From 251cd10c1c86d9df20d54d3856ba30acdbdaab5b Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Wed, 11 Nov 2015 17:15:07 -0500
Subject: [PATCH 183/534] bump version to 0.5.1
---
src/Version.php | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/Version.php b/src/Version.php
index fb19a731..76f37eb3 100644
--- a/src/Version.php
+++ b/src/Version.php
@@ -18,5 +18,5 @@
*/
class Version
{
- const VERSION = 'v0.5.0';
+ const VERSION = 'v0.5.1';
}
From cafe9b9113a7fefbdecba79ee7b58a5ff84627b4 Mon Sep 17 00:00:00 2001
From: Oleksandr Savchenko
Date: Fri, 13 Nov 2015 10:15:46 +0200
Subject: [PATCH 184/534] refactor exceptions
---
scss.inc.php | 2 ++
src/Compiler.php | 6 ++++--
src/Exception/CompilerException.php | 10 ++++++++++
src/Exception/ParseException.php | 10 ++++++++++
src/Parser.php | 7 ++++---
5 files changed, 30 insertions(+), 5 deletions(-)
create mode 100644 src/Exception/CompilerException.php
create mode 100644 src/Exception/ParseException.php
diff --git a/scss.inc.php b/scss.inc.php
index b7409a48..86e41b83 100644
--- a/scss.inc.php
+++ b/scss.inc.php
@@ -9,6 +9,8 @@
include_once __DIR__ . '/src/Colors.php';
include_once __DIR__ . '/src/Compiler.php';
include_once __DIR__ . '/src/Compiler/Environment.php';
+ include_once __DIR__ . '/src/Exception/CompilerException.php';
+ include_once __DIR__ . '/src/Exception/ParseException.php';
include_once __DIR__ . '/src/Formatter.php';
include_once __DIR__ . '/src/Formatter/Compact.php';
include_once __DIR__ . '/src/Formatter/Compressed.php';
diff --git a/src/Compiler.php b/src/Compiler.php
index 03190c71..5d45a206 100644
--- a/src/Compiler.php
+++ b/src/Compiler.php
@@ -15,6 +15,7 @@
use Leafo\ScssPhp\Block;
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\Type;
@@ -3199,7 +3200,8 @@ public function findImport($url)
*
* @param string $msg Message with optional sprintf()-style vararg parameters
*
- * @throws \Exception
+ * @throws \Leafo\ScssPhp\Exception\CompilerException
+ * @throws \Leafo\ScssPhp\Exception\ParseException
*/
public function throwError($msg)
{
@@ -3212,7 +3214,7 @@ public function throwError($msg)
$parser->throwParseError($msg, $this->sourcePos);
}
- throw new \Exception($msg);
+ throw new CompilerException($msg);
}
/**
diff --git a/src/Exception/CompilerException.php b/src/Exception/CompilerException.php
new file mode 100644
index 00000000..b52bbb95
--- /dev/null
+++ b/src/Exception/CompilerException.php
@@ -0,0 +1,10 @@
+peek("(.*?)(\n|$)", $m, $count)) {
- throw new \Exception("$msg: failed at `$m[1]` $loc");
+ throw new ParseException("$msg: failed at `$m[1]` $loc");
}
- throw new \Exception("$msg: $loc");
+ throw new ParseException("$msg: $loc");
}
/**
From e9f44a5d1c850ac33edb0d2226887a597455ee8d Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Fri, 20 Nov 2015 05:46:54 -0500
Subject: [PATCH 185/534] internals: improve consistency of new blocks
---
src/Compiler.php | 55 +++++++++++++++++++++---------------------------
src/Parser.php | 2 +-
2 files changed, 25 insertions(+), 32 deletions(-)
diff --git a/src/Compiler.php b/src/Compiler.php
index 03190c71..7ed511dd 100644
--- a/src/Compiler.php
+++ b/src/Compiler.php
@@ -526,8 +526,12 @@ protected function compileMedia(Block $media)
if ($needsWrap) {
$wrapped = new Block;
- $wrapped->selectors = array();
- $wrapped->children = $media->children;
+ $wrapped->sourcePosition = $media->sourcePosition;
+ $wrapped->sourceIndex = $media->sourceIndex;
+ $wrapped->selectors = array();
+ $wrapped->comments = array();
+ $wrapped->parent = $media;
+ $wrapped->children = $media->children;
$media->children = array(array(Type::T_BLOCK, $wrapped));
}
@@ -594,11 +598,11 @@ protected function compileAtRoot(Block $block)
// wrap inline selector
if ($block->selector) {
$wrapped = new Block;
- $wrapped->parent = $block;
$wrapped->sourcePosition = $block->sourcePosition;
$wrapped->sourceIndex = $block->sourceIndex;
$wrapped->selectors = $block->selector;
$wrapped->comments = array();
+ $wrapped->parent = $block;
$wrapped->children = $block->children;
$block->children = array(array(Type::T_BLOCK, $wrapped));
@@ -636,7 +640,7 @@ private function spliceTree($envs, Block $block, $without)
continue;
}
- if (isset($e->block) && $e->block === $block) {
+ if ($e->block === $block) {
continue;
}
@@ -662,19 +666,26 @@ private function spliceTree($envs, Block $block, $without)
}
$b = new Block;
+ $b->sourcePosition = $e->block->sourcePosition;
+ $b->sourceIndex = $e->block->sourceIndex;
+ $b->selectors = array();
+ $b->comments = $e->block->comments;
+ $b->parent = null;
- if (isset($e->block->sourcePosition)) {
- $b->sourcePosition = $e->block->sourcePosition;
- }
+ if ($newBlock) {
+ $type = isset($newBlock->type) ? $newBlock->type : Type::T_BLOCK;
- if (isset($e->block->sourceIndex)) {
- $b->sourceIndex = $e->block->sourceIndex;
- }
+ $b->children = array(array($type, $newBlock));
- $b->selectors = array();
+ $newBlock->parent = $b;
+ } elseif (count($block->children)) {
+ foreach ($block->children as $child) {
+ if ($child[0] === Type::T_BLOCK) {
+ $child[1]->parent = $b;
+ }
+ }
- if (isset($e->block->comments)) {
- $b->comments = $e->block->comments;
+ $b->children = $block->children;
}
if (isset($e->block->type)) {
@@ -693,24 +704,6 @@ private function spliceTree($envs, Block $block, $without)
$b->value = $e->block->value;
}
- if ($newBlock) {
- $type = isset($newBlock->type) ? $newBlock->type : Type::T_BLOCK;
-
- $b->children = array(array($type, $newBlock));
-
- $newBlock->parent = $b;
- } elseif (count($block->children)) {
- foreach ($block->children as $child) {
- if ($child[0] === Type::T_BLOCK) {
- $child[1]->parent = $b;
- }
- }
-
- $b->children = $block->children;
- }
-
- $b->parent = null;
-
$newBlock = $b;
}
diff --git a/src/Parser.php b/src/Parser.php
index 9249878e..afb6956f 100644
--- a/src/Parser.php
+++ b/src/Parser.php
@@ -691,11 +691,11 @@ protected function parseChunk()
protected function pushBlock($selectors, $pos = 0)
{
$b = new Block;
- $b->parent = $this->env;
$b->sourcePosition = $pos;
$b->sourceIndex = $this->sourceIndex;
$b->selectors = $selectors;
$b->comments = array();
+ $b->parent = $this->env;
if (! $this->env) {
$b->children = array();
From d1d7f8211b3901a89aae2c0d2a1d5a20b2977a68 Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Sun, 22 Nov 2015 19:31:03 -0500
Subject: [PATCH 186/534] internals: reinitialize Compiler properties on
subsequent compile() calls
---
src/Compiler.php | 28 ++++++++++++++++------------
1 file changed, 16 insertions(+), 12 deletions(-)
diff --git a/src/Compiler.php b/src/Compiler.php
index 7ed511dd..f6c999f4 100644
--- a/src/Compiler.php
+++ b/src/Compiler.php
@@ -154,24 +154,28 @@ public function compile($code, $path = null)
$locale = setlocale(LC_NUMERIC, 0);
setlocale(LC_NUMERIC, 'C');
- $this->indentLevel = -1;
- $this->commentsSeen = array();
- $this->extends = array();
- $this->extendsMap = array();
- $this->parsedFiles = array();
- $this->sourceParsers = array();
- $this->sourceIndex = null;
- $this->env = null;
- $this->scope = null;
- $this->storeEnv = null;
- $this->stderr = fopen('php://stderr', 'w');
+ $this->indentLevel = -1;
+ $this->commentsSeen = array();
+ $this->extends = array();
+ $this->extendsMap = array();
+ $this->parsedFiles = array();
+ $this->sourceParsers = array();
+ $this->sourceIndex = null;
+ $this->sourcePos = null;
+ $this->env = null;
+ $this->scope = null;
+ $this->storeEnv = null;
+ $this->charsetSeen = null;
+ $this->shouldEvaluate = null;
+ $this->stderr = fopen('php://stderr', 'w');
$this->parser = $this->parserFactory($path);
$tree = $this->parser->parse($code);
$this->formatter = new $this->formatter();
+ $this->rootBlock = null;
+ $this->rootEnv = $this->pushEnv($tree);
- $this->rootEnv = $this->pushEnv($tree);
$this->injectVariables($this->registeredVars);
$this->compileRoot($tree);
$this->popEnv();
From fe37dc2b4d83e8ac68acb2aa823b562829af6f58 Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Sat, 28 Nov 2015 15:28:00 -0500
Subject: [PATCH 187/534] Fixes #383; undefined sourceParsers when reusing a
single Compiler instance
---
src/Compiler.php | 11 +++++++++--
1 file changed, 9 insertions(+), 2 deletions(-)
diff --git a/src/Compiler.php b/src/Compiler.php
index f6c999f4..76e70e8b 100644
--- a/src/Compiler.php
+++ b/src/Compiler.php
@@ -139,6 +139,15 @@ class Compiler
private $stderr;
private $shouldEvaluate;
+ /**
+ * Constructor
+ */
+ public function __construct()
+ {
+ $this->parsedFiles = array();
+ $this->sourceParsers = array();
+ }
+
/**
* Compile scss
*
@@ -158,8 +167,6 @@ public function compile($code, $path = null)
$this->commentsSeen = array();
$this->extends = array();
$this->extendsMap = array();
- $this->parsedFiles = array();
- $this->sourceParsers = array();
$this->sourceIndex = null;
$this->sourcePos = null;
$this->env = null;
From 1f5c1eeba750f09653432511876613eba3dd2242 Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Sat, 28 Nov 2015 21:43:31 -0500
Subject: [PATCH 188/534] fixes #385 - replace sourcePosition with sourceLine;
also, eliminate sourceParsers[]
---
src/Compiler.php | 71 +++++++++++++++---------------
src/Parser.php | 110 +++++++++++++++++++++++++++++------------------
2 files changed, 102 insertions(+), 79 deletions(-)
diff --git a/src/Compiler.php b/src/Compiler.php
index 76e70e8b..77a4fa79 100644
--- a/src/Compiler.php
+++ b/src/Compiler.php
@@ -131,8 +131,8 @@ class Compiler
private $env;
private $scope;
private $parser;
- private $sourcePos;
- private $sourceParsers;
+ private $sourceNames;
+ private $sourceLine;
private $sourceIndex;
private $storeEnv;
private $charsetSeen;
@@ -144,8 +144,8 @@ class Compiler
*/
public function __construct()
{
- $this->parsedFiles = array();
- $this->sourceParsers = array();
+ $this->parsedFiles = array();
+ $this->sourceNames = array();
}
/**
@@ -168,7 +168,7 @@ public function compile($code, $path = null)
$this->extends = array();
$this->extendsMap = array();
$this->sourceIndex = null;
- $this->sourcePos = null;
+ $this->sourceLine = null;
$this->env = null;
$this->scope = null;
$this->storeEnv = null;
@@ -178,6 +178,7 @@ public function compile($code, $path = null)
$this->parser = $this->parserFactory($path);
$tree = $this->parser->parse($code);
+ $this->parser = null;
$this->formatter = new $this->formatter();
$this->rootBlock = null;
@@ -203,9 +204,9 @@ public function compile($code, $path = null)
*/
private function parserFactory($path)
{
- $parser = new Parser($path, count($this->sourceParsers));
+ $parser = new Parser($path, count($this->sourceNames));
- $this->sourceParsers[] = $parser;
+ $this->sourceNames[] = $path;
$this->addParsedFile($path);
return $parser;
@@ -537,12 +538,12 @@ protected function compileMedia(Block $media)
if ($needsWrap) {
$wrapped = new Block;
- $wrapped->sourcePosition = $media->sourcePosition;
- $wrapped->sourceIndex = $media->sourceIndex;
- $wrapped->selectors = array();
- $wrapped->comments = array();
- $wrapped->parent = $media;
- $wrapped->children = $media->children;
+ $wrapped->sourceLine = $media->sourceLine;
+ $wrapped->sourceIndex = $media->sourceIndex;
+ $wrapped->selectors = array();
+ $wrapped->comments = array();
+ $wrapped->parent = $media;
+ $wrapped->children = $media->children;
$media->children = array(array(Type::T_BLOCK, $wrapped));
}
@@ -609,12 +610,12 @@ protected function compileAtRoot(Block $block)
// wrap inline selector
if ($block->selector) {
$wrapped = new Block;
- $wrapped->sourcePosition = $block->sourcePosition;
- $wrapped->sourceIndex = $block->sourceIndex;
- $wrapped->selectors = $block->selector;
- $wrapped->comments = array();
- $wrapped->parent = $block;
- $wrapped->children = $block->children;
+ $wrapped->sourceLine = $block->sourceLine;
+ $wrapped->sourceIndex = $block->sourceIndex;
+ $wrapped->selectors = $block->selector;
+ $wrapped->comments = array();
+ $wrapped->parent = $block;
+ $wrapped->children = $block->children;
$block->children = array(array(Type::T_BLOCK, $wrapped));
}
@@ -677,11 +678,11 @@ private function spliceTree($envs, Block $block, $without)
}
$b = new Block;
- $b->sourcePosition = $e->block->sourcePosition;
- $b->sourceIndex = $e->block->sourceIndex;
- $b->selectors = array();
- $b->comments = $e->block->comments;
- $b->parent = null;
+ $b->sourceLine = $e->block->sourceLine;
+ $b->sourceIndex = $e->block->sourceIndex;
+ $b->selectors = array();
+ $b->comments = $e->block->comments;
+ $b->parent = null;
if ($newBlock) {
$type = isset($newBlock->type) ? $newBlock->type : Type::T_BLOCK;
@@ -886,9 +887,8 @@ protected function compileBlock(Block $block)
$annotation = $this->makeOutputBlock(Type::T_COMMENT);
$annotation->depth = 0;
- $parser = $this->sourceParsers[$block->sourceIndex];
- $file = $parser->getSourceName();
- $line = $parser->getLineNo($block->sourcePosition);
+ $file = $this->sourceNames[$block->sourceIndex];
+ $line = $block->sourceLine;
switch ($this->lineNumberStyle) {
case self::LINE_COMMENTS:
@@ -1361,7 +1361,7 @@ protected function compileImport($rawPath, $out, $once = false)
protected function compileChild($child, OutputBlock $out)
{
$this->sourceIndex = isset($child[Parser::SOURCE_INDEX]) ? $child[Parser::SOURCE_INDEX] : null;
- $this->sourcePos = isset($child[Parser::SOURCE_POSITION]) ? $child[Parser::SOURCE_POSITION] : -1;
+ $this->sourceLine = isset($child[Parser::SOURCE_LINE]) ? $child[Parser::SOURCE_LINE] : -1;
switch ($child[0]) {
case Type::T_SCSSPHP_IMPORT_ONCE:
@@ -1685,7 +1685,7 @@ protected function compileChild($child, OutputBlock $out)
case Type::T_DEBUG:
list(, $value) = $child;
- $line = $this->parser->getLineNo($this->sourcePos);
+ $line = $this->sourceLine;
$value = $this->compileValue($this->reduce($value, true));
fwrite($this->stderr, "Line $line DEBUG: $value\n");
break;
@@ -1693,7 +1693,7 @@ protected function compileChild($child, OutputBlock $out)
case Type::T_WARN:
list(, $value) = $child;
- $line = $this->parser->getLineNo($this->sourcePos);
+ $line = $this->sourceLine;
$value = $this->compileValue($this->reduce($value, true));
echo "Line $line WARN: $value\n";
break;
@@ -1701,7 +1701,7 @@ protected function compileChild($child, OutputBlock $out)
case Type::T_ERROR:
list(, $value) = $child;
- $line = $this->parser->getLineNo($this->sourcePos);
+ $line = $this->sourceLine;
$value = $this->compileValue($this->reduce($value, true));
$this->throwError("Line $line ERROR: $value\n");
break;
@@ -3211,10 +3211,8 @@ public function throwError($msg)
$msg = call_user_func_array('sprintf', func_get_args());
}
- if ($this->sourcePos >= 0 && isset($this->sourceIndex)) {
- $parser = $this->sourceParsers[$this->sourceIndex];
- $parser->throwParseError($msg, $this->sourcePos);
- }
+ $line = $this->sourceLine;
+ $msg = "$msg: line: $line";
throw new \Exception($msg);
}
@@ -3229,8 +3227,7 @@ public function throwError($msg)
private function handleImportLoop($name)
{
for ($env = $this->env; $env; $env = $env->parent) {
- $parser = $this->sourceParsers[$env->block->sourceIndex];
- $file = $parser->getSourceName();
+ $file = $this->sourceNames[$env->block->sourceIndex];
if (realpath($file) === $name) {
$this->throwError('An @import loop has been found: %s imports %s', $file, basename($file));
diff --git a/src/Parser.php b/src/Parser.php
index afb6956f..c072cc11 100644
--- a/src/Parser.php
+++ b/src/Parser.php
@@ -23,8 +23,8 @@
*/
class Parser
{
- const SOURCE_INDEX = -1;
- const SOURCE_POSITION = -2;
+ const SOURCE_INDEX = -1;
+ const SOURCE_LINE = -2;
/**
* @var array
@@ -53,6 +53,7 @@ class Parser
private $sourceName;
private $sourceIndex;
+ private $sourcePositions;
private $charset;
private $count;
private $env;
@@ -98,47 +99,22 @@ public function getSourceName()
return $this->sourceName;
}
- /**
- * Get source line number (given character position in the buffer)
- *
- * @api
- *
- * @param integer $pos
- *
- * @return integer
- */
- public function getLineNo($pos)
- {
- return 1 + substr_count(substr($this->buffer, 0, $pos), "\n");
- }
-
/**
* Throw parser error
*
* @api
*
- * @param string $msg
- * @param integer $count
+ * @param string $msg
*
* @throws \Exception
*/
- public function throwParseError($msg = 'parse error', $count = null)
+ public function throwParseError($msg = 'parse error')
{
- $count = ! isset($count) ? $this->count : $count;
-
- $line = $this->getLineNo($count);
+ $line = $this->getSourceLineNumber($this->count);
+ $loc = empty($this->sourceName) ? "line: $line" : "$this->sourceName on line $line";
- if (! empty($this->sourceName)) {
- $loc = "$this->sourceName on line $line";
- } else {
- $loc = "line: $line";
- }
-
- if ($this->peek("(.*?)(\n|$)", $m, $count)) {
- throw new \Exception("$msg: failed at `$m[1]` $loc");
- }
-
- throw new \Exception("$msg: $loc");
+ throw new \Exception("$msg: failed at `$m[1]` $loc");
+ //throw new \Exception("$msg: $loc");
}
/**
@@ -158,8 +134,9 @@ public function parse($buffer)
$this->eatWhiteDefault = true;
$this->buffer = rtrim($buffer, "\x00..\x1f");
- $this->pushBlock(null); // root block
+ $this->extractLineNumbers($buffer);
+ $this->pushBlock(null); // root block
$this->whitespace();
$this->pushBlock(null);
$this->popBlock();
@@ -549,7 +526,7 @@ protected function parseChunk()
if (! isset($this->charset)) {
$statement = array(Type::T_CHARSET, $charset);
- $statement[self::SOURCE_POSITION] = $s;
+ $statement[self::SOURCE_LINE] = $this->getSourceLineNumber($s);
$statement[self::SOURCE_INDEX] = $this->sourceIndex;
$this->charset = $statement;
@@ -691,11 +668,11 @@ protected function parseChunk()
protected function pushBlock($selectors, $pos = 0)
{
$b = new Block;
- $b->sourcePosition = $pos;
- $b->sourceIndex = $this->sourceIndex;
- $b->selectors = $selectors;
- $b->comments = array();
- $b->parent = $this->env;
+ $b->sourceLine = $this->getSourceLineNumber($pos);
+ $b->sourceIndex = $this->sourceIndex;
+ $b->selectors = $selectors;
+ $b->comments = array();
+ $b->parent = $this->env;
if (! $this->env) {
$b->children = array();
@@ -942,8 +919,8 @@ protected function appendComment($comment)
protected function append($statement, $pos = null)
{
if ($pos !== null) {
- $statement[self::SOURCE_POSITION] = $pos;
- $statement[self::SOURCE_INDEX] = $this->sourceIndex;
+ $statement[self::SOURCE_LINE] = $this->getSourceLineNumber($pos);
+ $statement[self::SOURCE_INDEX] = $this->sourceIndex;
}
$this->env->children[] = $statement;
@@ -2385,4 +2362,53 @@ private function pregQuote($what)
{
return preg_quote($what, '/');
}
+
+ /**
+ * Extract line numbers from buffer
+ *
+ * @param string $buffer
+ */
+ private function extractLineNumbers($buffer)
+ {
+ $this->sourcePositions = array(0 => 0);
+ $pos = 0;
+
+ while (($pos = strpos($buffer, "\n", $prev)) !== false) {
+ $this->sourcePositions[] = $pos;
+ $prev = $pos + 1;
+ }
+
+ $this->sourcePositions[] = strlen($buffer);
+ }
+
+ /**
+ * Get source line number (given character position in the buffer)
+ *
+ * @param integer $pos
+ *
+ * @return integer
+ */
+ private function getSourceLineNumber($pos)
+ {
+ $low = 0;
+ $high = count($this->sourcePositions);
+
+ while ($low < $high) {
+ $mid = (int) (($high + $low) / 2);
+
+ if ($pos < $this->sourcePositions[$mid]) {
+ $high = $mid - 1;
+ continue;
+ }
+
+ if ($pos >= $this->sourcePositions[$mid + 1]) {
+ $low = $mid + 1;
+ continue;
+ }
+
+ return $mid + 1;
+ }
+
+ return $low + 1;
+ }
}
From 33ad8789de77741798de76f946f5b9076c697cbc Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Sat, 28 Nov 2015 21:55:02 -0500
Subject: [PATCH 189/534] Fix throwParseError()
---
src/Parser.php | 9 ++++++---
1 file changed, 6 insertions(+), 3 deletions(-)
diff --git a/src/Parser.php b/src/Parser.php
index c072cc11..c5fc442c 100644
--- a/src/Parser.php
+++ b/src/Parser.php
@@ -113,8 +113,11 @@ public function throwParseError($msg = 'parse error')
$line = $this->getSourceLineNumber($this->count);
$loc = empty($this->sourceName) ? "line: $line" : "$this->sourceName on line $line";
- throw new \Exception("$msg: failed at `$m[1]` $loc");
- //throw new \Exception("$msg: $loc");
+ if ($this->peek("(.*?)(\n|$)", $m, $this->count)) {
+ throw new \Exception("$msg: failed at `$m[1]` $loc");
+ }
+
+ throw new \Exception("$msg: $loc");
}
/**
@@ -2371,7 +2374,7 @@ private function pregQuote($what)
private function extractLineNumbers($buffer)
{
$this->sourcePositions = array(0 => 0);
- $pos = 0;
+ $prev = 0;
while (($pos = strpos($buffer, "\n", $prev)) !== false) {
$this->sourcePositions[] = $pos;
From 113311ada3a824ebade489463968914e81fbf9ae Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Sat, 28 Nov 2015 22:52:35 -0500
Subject: [PATCH 190/534] debug broken travis unit tests
---
tests/ExceptionTest.php | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)
diff --git a/tests/ExceptionTest.php b/tests/ExceptionTest.php
index ea17abb5..4406c523 100644
--- a/tests/ExceptionTest.php
+++ b/tests/ExceptionTest.php
@@ -36,9 +36,11 @@ public function testThrowError($scss, $expectedExceptionMessage)
try {
$this->compile($scss);
} catch (\Exception $e) {
- if (strpos($e->getMessage(), $expectedExceptionMessage) !== false) {
- return;
- };
+ if (strpos($e->getMessage(), $expectedExceptionMessage) === false) {
+ $this->fail('Unexpected exception raised: ' . $e->getMessage() . ' vs ' . $expectedExceptionMessage);
+ }
+
+ return;
}
$this->fail('Expected exception to be raised: ' . $expectedExceptionMessage);
From 9e422ba034dd723ab36fc1d1295a6b27d8dc621a Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Sat, 28 Nov 2015 22:58:44 -0500
Subject: [PATCH 191/534] more travis debugging
---
src/Parser.php | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/src/Parser.php b/src/Parser.php
index c5fc442c..7596afb7 100644
--- a/src/Parser.php
+++ b/src/Parser.php
@@ -2382,6 +2382,10 @@ private function extractLineNumbers($buffer)
}
$this->sourcePositions[] = strlen($buffer);
+
+ if (substr($buffer, -1) !== "\n") {
+ $this->sourcePositions[] = strlen(buffer) + 1;
+ }
}
/**
From 1fd71902452efcabfe8a67b0a51fc37217745caf Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Sat, 28 Nov 2015 22:59:52 -0500
Subject: [PATCH 192/534] fix typo
---
src/Parser.php | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/Parser.php b/src/Parser.php
index 7596afb7..eca8d20d 100644
--- a/src/Parser.php
+++ b/src/Parser.php
@@ -2384,7 +2384,7 @@ private function extractLineNumbers($buffer)
$this->sourcePositions[] = strlen($buffer);
if (substr($buffer, -1) !== "\n") {
- $this->sourcePositions[] = strlen(buffer) + 1;
+ $this->sourcePositions[] = strlen($buffer) + 1;
}
}
From 62da8881d43562d9c47ad9c2434415d713b0c120 Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Sat, 28 Nov 2015 23:27:17 -0500
Subject: [PATCH 193/534] Add sourceColumn (needed for future sourcemap
support)
---
src/Block.php | 9 +++++++--
src/Compiler.php | 46 +++++++++++++++++++++++++--------------------
src/Node.php | 9 +++++++--
src/Node/Number.php | 25 +++++++++++++++++-------
src/Parser.php | 43 ++++++++++++++++++++++++++----------------
5 files changed, 85 insertions(+), 47 deletions(-)
diff --git a/src/Block.php b/src/Block.php
index 16f4a968..b44f4bd9 100644
--- a/src/Block.php
+++ b/src/Block.php
@@ -31,12 +31,17 @@ class Block
/**
* @var integer
*/
- public $sourcePosition;
+ public $sourceIndex;
/**
* @var integer
*/
- public $sourceIndex;
+ public $sourceLine;
+
+ /**
+ * @var integer
+ */
+ public $sourceColumn;
/**
* @var array
diff --git a/src/Compiler.php b/src/Compiler.php
index 77a4fa79..5ccf4fed 100644
--- a/src/Compiler.php
+++ b/src/Compiler.php
@@ -132,8 +132,9 @@ class Compiler
private $scope;
private $parser;
private $sourceNames;
- private $sourceLine;
private $sourceIndex;
+ private $sourceLine;
+ private $sourceColumn;
private $storeEnv;
private $charsetSeen;
private $stderr;
@@ -169,6 +170,7 @@ public function compile($code, $path = null)
$this->extendsMap = array();
$this->sourceIndex = null;
$this->sourceLine = null;
+ $this->sourceColumn = null;
$this->env = null;
$this->scope = null;
$this->storeEnv = null;
@@ -538,12 +540,13 @@ protected function compileMedia(Block $media)
if ($needsWrap) {
$wrapped = new Block;
- $wrapped->sourceLine = $media->sourceLine;
- $wrapped->sourceIndex = $media->sourceIndex;
- $wrapped->selectors = array();
- $wrapped->comments = array();
- $wrapped->parent = $media;
- $wrapped->children = $media->children;
+ $wrapped->sourceIndex = $media->sourceIndex;
+ $wrapped->sourceLine = $media->sourceLine;
+ $wrapped->sourceColumn = $media->sourceColumn;
+ $wrapped->selectors = array();
+ $wrapped->comments = array();
+ $wrapped->parent = $media;
+ $wrapped->children = $media->children;
$media->children = array(array(Type::T_BLOCK, $wrapped));
}
@@ -610,12 +613,13 @@ protected function compileAtRoot(Block $block)
// wrap inline selector
if ($block->selector) {
$wrapped = new Block;
- $wrapped->sourceLine = $block->sourceLine;
- $wrapped->sourceIndex = $block->sourceIndex;
- $wrapped->selectors = $block->selector;
- $wrapped->comments = array();
- $wrapped->parent = $block;
- $wrapped->children = $block->children;
+ $wrapped->sourceIndex = $block->sourceIndex;
+ $wrapped->sourceLine = $block->sourceLine;
+ $wrapped->sourceColumn = $block->sourceColumn;
+ $wrapped->selectors = $block->selector;
+ $wrapped->comments = array();
+ $wrapped->parent = $block;
+ $wrapped->children = $block->children;
$block->children = array(array(Type::T_BLOCK, $wrapped));
}
@@ -678,11 +682,12 @@ private function spliceTree($envs, Block $block, $without)
}
$b = new Block;
- $b->sourceLine = $e->block->sourceLine;
- $b->sourceIndex = $e->block->sourceIndex;
- $b->selectors = array();
- $b->comments = $e->block->comments;
- $b->parent = null;
+ $b->sourceIndex = $e->block->sourceIndex;
+ $b->sourceLine = $e->block->sourceLine;
+ $b->sourceColumn = $e->block->sourceColumn;
+ $b->selectors = array();
+ $b->comments = $e->block->comments;
+ $b->parent = null;
if ($newBlock) {
$type = isset($newBlock->type) ? $newBlock->type : Type::T_BLOCK;
@@ -1360,8 +1365,9 @@ protected function compileImport($rawPath, $out, $once = false)
*/
protected function compileChild($child, OutputBlock $out)
{
- $this->sourceIndex = isset($child[Parser::SOURCE_INDEX]) ? $child[Parser::SOURCE_INDEX] : null;
- $this->sourceLine = isset($child[Parser::SOURCE_LINE]) ? $child[Parser::SOURCE_LINE] : -1;
+ $this->sourceIndex = isset($child[Parser::SOURCE_INDEX]) ? $child[Parser::SOURCE_INDEX] : null;
+ $this->sourceLine = isset($child[Parser::SOURCE_LINE]) ? $child[Parser::SOURCE_LINE] : -1;
+ $this->sourceColumn = isset($child[Parser::SOURCE_COLUMN]) ? $child[Parser::SOURCE_COLUMN] : -1;
switch ($child[0]) {
case Type::T_SCSSPHP_IMPORT_ONCE:
diff --git a/src/Node.php b/src/Node.php
index d09f597e..2b55419e 100644
--- a/src/Node.php
+++ b/src/Node.php
@@ -26,10 +26,15 @@ abstract class Node
/**
* @var integer
*/
- public $sourcePosition;
+ public $sourceIndex;
/**
* @var integer
*/
- public $sourceIndex;
+ public $sourceLine;
+
+ /**
+ * @var integer
+ */
+ public $sourceColumn;
}
diff --git a/src/Node/Number.php b/src/Node/Number.php
index 3727a768..f5356bfb 100644
--- a/src/Node/Number.php
+++ b/src/Node/Number.php
@@ -140,8 +140,12 @@ public function normalize()
*/
public function offsetExists($offset)
{
+ if ($offset === -3) {
+ return $this->sourceColumn !== null;
+ }
+
if ($offset === -2) {
- return $sourceIndex !== null;
+ return $this->sourceLine !== null;
}
if ($offset === -1
@@ -161,11 +165,14 @@ public function offsetExists($offset)
public function offsetGet($offset)
{
switch ($offset) {
+ case -3:
+ return $this->sourceColumn;
+
case -2:
- return $this->sourceIndex;
+ return $this->sourceLine;
case -1:
- return $this->sourcePosition;
+ return $this->sourceIndex;
case 0:
return $this->type;
@@ -188,9 +195,11 @@ public function offsetSet($offset, $value)
} elseif ($offset === 2) {
$this->units = $value;
} elseif ($offset == -1) {
- $this->sourcePosition = $value;
- } elseif ($offset == -2) {
$this->sourceIndex = $value;
+ } elseif ($offset == -2) {
+ $this->sourceLine = $value;
+ } elseif ($offset == -3) {
+ $this->sourceColumn = $value;
}
}
@@ -204,9 +213,11 @@ public function offsetUnset($offset)
} elseif ($offset === 2) {
$this->units = null;
} elseif ($offset === -1) {
- $this->sourcePosition = null;
- } elseif ($offset === -2) {
$this->sourceIndex = null;
+ } elseif ($offset === -2) {
+ $this->sourceLine = null;
+ } elseif ($offset === -3) {
+ $this->sourceColumn = null;
}
}
diff --git a/src/Parser.php b/src/Parser.php
index eca8d20d..5fe92e96 100644
--- a/src/Parser.php
+++ b/src/Parser.php
@@ -23,8 +23,9 @@
*/
class Parser
{
- const SOURCE_INDEX = -1;
- const SOURCE_LINE = -2;
+ const SOURCE_INDEX = -1;
+ const SOURCE_LINE = -2;
+ const SOURCE_COLUMN = -3;
/**
* @var array
@@ -110,7 +111,8 @@ public function getSourceName()
*/
public function throwParseError($msg = 'parse error')
{
- $line = $this->getSourceLineNumber($this->count);
+ list($line, $column) = $this->getSourcePosition($this->count);
+
$loc = empty($this->sourceName) ? "line: $line" : "$this->sourceName on line $line";
if ($this->peek("(.*?)(\n|$)", $m, $this->count)) {
@@ -529,8 +531,11 @@ protected function parseChunk()
if (! isset($this->charset)) {
$statement = array(Type::T_CHARSET, $charset);
- $statement[self::SOURCE_LINE] = $this->getSourceLineNumber($s);
- $statement[self::SOURCE_INDEX] = $this->sourceIndex;
+ list($line, $column) = $this->getSourcePosition($s);
+
+ $statement[self::SOURCE_LINE] = $line;
+ $statement[self::SOURCE_COLUMN] = $column;
+ $statement[self::SOURCE_INDEX] = $this->sourceIndex;
$this->charset = $statement;
}
@@ -670,12 +675,15 @@ protected function parseChunk()
*/
protected function pushBlock($selectors, $pos = 0)
{
+ list($line, $column) = $this->getSourcePosition($pos);
+
$b = new Block;
- $b->sourceLine = $this->getSourceLineNumber($pos);
- $b->sourceIndex = $this->sourceIndex;
- $b->selectors = $selectors;
- $b->comments = array();
- $b->parent = $this->env;
+ $b->sourceLine = $line;
+ $b->sourceColumn = $column;
+ $b->sourceIndex = $this->sourceIndex;
+ $b->selectors = $selectors;
+ $b->comments = array();
+ $b->parent = $this->env;
if (! $this->env) {
$b->children = array();
@@ -922,8 +930,11 @@ protected function appendComment($comment)
protected function append($statement, $pos = null)
{
if ($pos !== null) {
- $statement[self::SOURCE_LINE] = $this->getSourceLineNumber($pos);
- $statement[self::SOURCE_INDEX] = $this->sourceIndex;
+ list($line, $column) = $this->getSourcePosition($pos);
+
+ $statement[self::SOURCE_LINE] = $line;
+ $statement[self::SOURCE_COLUMN] = $column;
+ $statement[self::SOURCE_INDEX] = $this->sourceIndex;
}
$this->env->children[] = $statement;
@@ -2389,13 +2400,13 @@ private function extractLineNumbers($buffer)
}
/**
- * Get source line number (given character position in the buffer)
+ * Get source line number and column (given character position in the buffer)
*
* @param integer $pos
*
* @return integer
*/
- private function getSourceLineNumber($pos)
+ private function getSourcePosition($pos)
{
$low = 0;
$high = count($this->sourcePositions);
@@ -2413,9 +2424,9 @@ private function getSourceLineNumber($pos)
continue;
}
- return $mid + 1;
+ return array($mid + 1, $pos - $this->sourcePosition[$mid]);
}
- return $low + 1;
+ return array($low + 1, $pos - $this->sourcePosition[$low]);
}
}
From 68881cf7d64e19f52f295d078694ab3da365609a Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Sat, 28 Nov 2015 23:29:43 -0500
Subject: [PATCH 194/534] fix typo
---
src/Parser.php | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/Parser.php b/src/Parser.php
index 5fe92e96..89c3a93d 100644
--- a/src/Parser.php
+++ b/src/Parser.php
@@ -2424,9 +2424,9 @@ private function getSourcePosition($pos)
continue;
}
- return array($mid + 1, $pos - $this->sourcePosition[$mid]);
+ return array($mid + 1, $pos - $this->sourcePositions[$mid]);
}
- return array($low + 1, $pos - $this->sourcePosition[$low]);
+ return array($low + 1, $pos - $this->sourcePositions[$low]);
}
}
From c727c14ddd0de785af5dcc26c90422f361adf5f3 Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Thu, 3 Dec 2015 23:51:15 -0500
Subject: [PATCH 195/534] fix single quoting issue reported with
zurb/foundation 6.0.4
---
src/Parser.php | 12 ++++++------
tests/inputs/builtins.scss | 5 +++++
tests/outputs/builtins.css | 3 +++
tests/outputs_numbered/builtins.css | 3 +++
4 files changed, 17 insertions(+), 6 deletions(-)
diff --git a/src/Parser.php b/src/Parser.php
index 89c3a93d..f208585b 100644
--- a/src/Parser.php
+++ b/src/Parser.php
@@ -1667,8 +1667,8 @@ protected function string(&$out)
if ($this->literal('"', false)) {
$delim = '"';
- } elseif ($this->literal('\'', false)) {
- $delim = '\'';
+ } elseif ($this->literal("'", false)) {
+ $delim = "'";
} else {
return false;
}
@@ -1690,10 +1690,10 @@ protected function string(&$out)
$content[] = '#{'; // ignore it
}
} elseif ($m[2] === '\\') {
- $content[] = $m[2];
-
if ($this->literal($delim, false)) {
- $content[] = $delim;
+ $content[] = $delim === '"' ? $m[2] . $delim : $delim;
+ } else {
+ $content[] = $m[2];
}
} else {
$this->count -= strlen($delim);
@@ -1796,7 +1796,7 @@ protected function openString($end, &$out, $nestingOpen = null)
break;
}
- if (($tok === '\'' || $tok === '"') && $this->string($str)) {
+ if (($tok === "'" || $tok === '"') && $this->string($str)) {
$content[] = $str;
continue;
}
diff --git a/tests/inputs/builtins.scss b/tests/inputs/builtins.scss
index 32066b40..70ec3012 100644
--- a/tests/inputs/builtins.scss
+++ b/tests/inputs/builtins.scss
@@ -210,3 +210,8 @@ div.call-tests {
b: call(scale-color, #0a64ff, $lightness: -10%);
c: call($fn, (a b c), 2);
}
+
+$type: text;
+div.unquote-test {
+ a: unquote('[type=\'#{$type}\']');
+}
diff --git a/tests/outputs/builtins.css b/tests/outputs/builtins.css
index 4d3ef6d8..fa74c1e2 100644
--- a/tests/outputs/builtins.css
+++ b/tests/outputs/builtins.css
@@ -155,3 +155,6 @@ div.call-tests {
a: #0a64ff;
b: #0058ef;
c: b; }
+
+div.unquote-test {
+ a: [type='text']; }
diff --git a/tests/outputs_numbered/builtins.css b/tests/outputs_numbered/builtins.css
index 95bc7759..b0170c8d 100644
--- a/tests/outputs_numbered/builtins.css
+++ b/tests/outputs_numbered/builtins.css
@@ -156,3 +156,6 @@ div.call-tests {
a: #0a64ff;
b: #0058ef;
c: b; }
+/* line 215, inputs/builtins.scss */
+div.unquote-test {
+ a: [type='text']; }
From 70e80a5f40c9e6e162c872384806292354b7ddc1 Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Fri, 4 Dec 2015 00:42:37 -0500
Subject: [PATCH 196/534] more quoting issues
---
src/Parser.php | 28 +++++++++++++++++++++++-----
1 file changed, 23 insertions(+), 5 deletions(-)
diff --git a/src/Parser.php b/src/Parser.php
index f208585b..d6cfb86e 100644
--- a/src/Parser.php
+++ b/src/Parser.php
@@ -1676,22 +1676,28 @@ protected function string(&$out)
$content = array();
$oldWhite = $this->eatWhiteDefault;
$this->eatWhiteDefault = false;
+ $hasInterpolation = false;
while ($this->matchString($m, $delim)) {
- $content[] = $m[1];
+ if ($m[1] !== '') {
+ $content[] = $m[1];
+ }
if ($m[2] === '#{') {
$this->count -= strlen($m[2]);
if ($this->interpolation($inter, false)) {
$content[] = $inter;
+ $hasInterpolation = true;
} else {
$this->count += strlen($m[2]);
$content[] = '#{'; // ignore it
}
} elseif ($m[2] === '\\') {
- if ($this->literal($delim, false)) {
- $content[] = $delim === '"' ? $m[2] . $delim : $delim;
+ if ($this->literal('"', false)) {
+ $content[] = $m[2] . '"';
+ } elseif ($this->literal("'", false)) {
+ $content[] = $m[2] . "'";
} else {
$content[] = $m[2];
}
@@ -1704,6 +1710,18 @@ protected function string(&$out)
$this->eatWhiteDefault = $oldWhite;
if ($this->literal($delim)) {
+ if ($hasInterpolation) {
+ $delim = '"';
+
+ foreach ($content as &$string) {
+ if ($string === "\\'") {
+ $string = "'";
+ } elseif ($string === '\\"') {
+ $string = '"';
+ }
+ }
+ }
+
$out = array(Type::T_STRING, $delim, $content);
return true;
@@ -2394,9 +2412,9 @@ private function extractLineNumbers($buffer)
$this->sourcePositions[] = strlen($buffer);
- if (substr($buffer, -1) !== "\n") {
+ if (substr($buffer, -1) !== "\n") {
$this->sourcePositions[] = strlen($buffer) + 1;
- }
+ }
}
/**
From e7d382952c4dffc29ae832a7a37ddc0f37e66e68 Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Fri, 4 Dec 2015 00:49:08 -0500
Subject: [PATCH 197/534] Bump to version 0.6.0
---
src/Version.php | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/Version.php b/src/Version.php
index 76f37eb3..a47062b1 100644
--- a/src/Version.php
+++ b/src/Version.php
@@ -18,5 +18,5 @@
*/
class Version
{
- const VERSION = 'v0.5.1';
+ const VERSION = 'v0.6.0';
}
From 1fcb031ca1377449a0a0dbfd86d41f8e79e9c6ef Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Sun, 6 Dec 2015 18:25:49 -0500
Subject: [PATCH 198/534] Update doc blocks
---
scss.inc.php | 2 +-
src/Base/Range.php | 2 +-
src/Block.php | 2 +-
src/Compiler.php | 7 +++----
src/Compiler/Environment.php | 2 +-
src/Exception/CompileException.php | 21 +++++++++++++++++++++
src/Exception/CompilerException.php | 10 ----------
src/Exception/ParseException.php | 13 ++++++++++++-
src/Formatter.php | 2 +-
src/Formatter/Compact.php | 2 +-
src/Formatter/Compressed.php | 2 +-
src/Formatter/Crunched.php | 2 +-
src/Formatter/Debug.php | 2 +-
src/Formatter/Expanded.php | 2 +-
src/Formatter/Nested.php | 2 +-
src/Formatter/OutputBlock.php | 2 +-
src/Node.php | 2 +-
src/Node/Number.php | 2 +-
src/Parser.php | 2 +-
src/Server.php | 2 +-
src/Type.php | 2 +-
src/Util.php | 2 +-
22 files changed, 54 insertions(+), 33 deletions(-)
create mode 100644 src/Exception/CompileException.php
delete mode 100644 src/Exception/CompilerException.php
diff --git a/scss.inc.php b/scss.inc.php
index 86e41b83..aaeddcad 100644
--- a/scss.inc.php
+++ b/scss.inc.php
@@ -9,7 +9,7 @@
include_once __DIR__ . '/src/Colors.php';
include_once __DIR__ . '/src/Compiler.php';
include_once __DIR__ . '/src/Compiler/Environment.php';
- include_once __DIR__ . '/src/Exception/CompilerException.php';
+ include_once __DIR__ . '/src/Exception/CompileException.php';
include_once __DIR__ . '/src/Exception/ParseException.php';
include_once __DIR__ . '/src/Formatter.php';
include_once __DIR__ . '/src/Formatter/Compact.php';
diff --git a/src/Base/Range.php b/src/Base/Range.php
index 76920556..a591d7b0 100644
--- a/src/Base/Range.php
+++ b/src/Base/Range.php
@@ -12,7 +12,7 @@
namespace Leafo\ScssPhp\Base;
/**
- * Range class
+ * Range
*
* @author Anthon Pang
*/
diff --git a/src/Block.php b/src/Block.php
index b44f4bd9..6b972a1b 100644
--- a/src/Block.php
+++ b/src/Block.php
@@ -12,7 +12,7 @@
namespace Leafo\ScssPhp;
/**
- * SCSS block
+ * Block
*
* @author Anthon Pang
*/
diff --git a/src/Compiler.php b/src/Compiler.php
index 02adcf36..f986c831 100644
--- a/src/Compiler.php
+++ b/src/Compiler.php
@@ -15,7 +15,7 @@
use Leafo\ScssPhp\Block;
use Leafo\ScssPhp\Colors;
use Leafo\ScssPhp\Compiler\Environment;
-use Leafo\ScssPhp\Exception\CompilerException;
+use Leafo\ScssPhp\Exception\CompileException;
use Leafo\ScssPhp\Formatter\OutputBlock;
use Leafo\ScssPhp\Node;
use Leafo\ScssPhp\Type;
@@ -3210,8 +3210,7 @@ public function findImport($url)
*
* @param string $msg Message with optional sprintf()-style vararg parameters
*
- * @throws \Leafo\ScssPhp\Exception\CompilerException
- * @throws \Leafo\ScssPhp\Exception\ParseException
+ * @throws \Leafo\ScssPhp\Exception\CompileException
*/
public function throwError($msg)
{
@@ -3222,7 +3221,7 @@ public function throwError($msg)
$line = $this->sourceLine;
$msg = "$msg: line: $line";
- throw new CompilerException($msg);
+ throw new CompileException($msg);
}
/**
diff --git a/src/Compiler/Environment.php b/src/Compiler/Environment.php
index f929c74c..e6314cbe 100644
--- a/src/Compiler/Environment.php
+++ b/src/Compiler/Environment.php
@@ -14,7 +14,7 @@
use Leafo\ScssPhp\Block;
/**
- * SCSS compiler environment
+ * Compiler environment
*
* @author Anthon Pang
*/
diff --git a/src/Exception/CompileException.php b/src/Exception/CompileException.php
new file mode 100644
index 00000000..dbb554ed
--- /dev/null
+++ b/src/Exception/CompileException.php
@@ -0,0 +1,21 @@
+
+ */
+class CompileException extends \Exception
+{
+}
diff --git a/src/Exception/CompilerException.php b/src/Exception/CompilerException.php
deleted file mode 100644
index b52bbb95..00000000
--- a/src/Exception/CompilerException.php
+++ /dev/null
@@ -1,10 +0,0 @@
-
*/
class ParseException extends \Exception
{
diff --git a/src/Formatter.php b/src/Formatter.php
index 88b7d867..caa9d660 100644
--- a/src/Formatter.php
+++ b/src/Formatter.php
@@ -14,7 +14,7 @@
use Leafo\ScssPhp\Formatter\OutputBlock;
/**
- * SCSS base formatter
+ * Base formatter
*
* @author Leaf Corcoran
*/
diff --git a/src/Formatter/Compact.php b/src/Formatter/Compact.php
index eda6ec24..721390d7 100644
--- a/src/Formatter/Compact.php
+++ b/src/Formatter/Compact.php
@@ -14,7 +14,7 @@
use Leafo\ScssPhp\Formatter;
/**
- * SCSS compact formatter
+ * Compact formatter
*
* @author Leaf Corcoran
*/
diff --git a/src/Formatter/Compressed.php b/src/Formatter/Compressed.php
index c51bb26b..1e27240a 100644
--- a/src/Formatter/Compressed.php
+++ b/src/Formatter/Compressed.php
@@ -15,7 +15,7 @@
use Leafo\ScssPhp\Formatter\OutputBlock;
/**
- * SCSS compressed formatter
+ * Compressed formatter
*
* @author Leaf Corcoran
*/
diff --git a/src/Formatter/Crunched.php b/src/Formatter/Crunched.php
index 29120cc9..5e80a824 100644
--- a/src/Formatter/Crunched.php
+++ b/src/Formatter/Crunched.php
@@ -15,7 +15,7 @@
use Leafo\ScssPhp\Formatter\OutputBlock;
/**
- * SCSS crunched formatter
+ * Crunched formatter
*
* @author Anthon Pang
*/
diff --git a/src/Formatter/Debug.php b/src/Formatter/Debug.php
index e330b2d6..e4555bb3 100644
--- a/src/Formatter/Debug.php
+++ b/src/Formatter/Debug.php
@@ -15,7 +15,7 @@
use Leafo\ScssPhp\Formatter\OutputBlock;
/**
- * SCSS debug formatter
+ * Debug formatter
*
* @author Anthon Pang
*/
diff --git a/src/Formatter/Expanded.php b/src/Formatter/Expanded.php
index 477318b4..b1a0bf24 100644
--- a/src/Formatter/Expanded.php
+++ b/src/Formatter/Expanded.php
@@ -15,7 +15,7 @@
use Leafo\ScssPhp\Formatter\OutputBlock;
/**
- * SCSS expanded formatter
+ * Expanded formatter
*
* @author Leaf Corcoran
*/
diff --git a/src/Formatter/Nested.php b/src/Formatter/Nested.php
index 8040adab..6fab43dc 100644
--- a/src/Formatter/Nested.php
+++ b/src/Formatter/Nested.php
@@ -15,7 +15,7 @@
use Leafo\ScssPhp\Formatter\OutputBlock;
/**
- * SCSS nested formatter
+ * Nested formatter
*
* @author Leaf Corcoran
*/
diff --git a/src/Formatter/OutputBlock.php b/src/Formatter/OutputBlock.php
index bfc383e2..bb8d99b4 100644
--- a/src/Formatter/OutputBlock.php
+++ b/src/Formatter/OutputBlock.php
@@ -12,7 +12,7 @@
namespace Leafo\ScssPhp\Formatter;
/**
- * SCSS output block
+ * Output block
*
* @author Anthon Pang
*/
diff --git a/src/Node.php b/src/Node.php
index 2b55419e..e6ed178c 100644
--- a/src/Node.php
+++ b/src/Node.php
@@ -12,7 +12,7 @@
namespace Leafo\ScssPhp;
/**
- * SCSS node
+ * Base node
*
* @author Anthon Pang
*/
diff --git a/src/Node/Number.php b/src/Node/Number.php
index f5356bfb..17e856db 100644
--- a/src/Node/Number.php
+++ b/src/Node/Number.php
@@ -16,7 +16,7 @@
use Leafo\ScssPhp\Type;
/**
- * SCSS dimension + optional units
+ * Dimension + optional units
*
* {@internal
* This is a work-in-progress.
diff --git a/src/Parser.php b/src/Parser.php
index c7f3553c..f5789729 100644
--- a/src/Parser.php
+++ b/src/Parser.php
@@ -18,7 +18,7 @@
use Leafo\ScssPhp\Type;
/**
- * SCSS parser
+ * Parser
*
* @author Leaf Corcoran
*/
diff --git a/src/Server.php b/src/Server.php
index 9095e357..de4e8830 100644
--- a/src/Server.php
+++ b/src/Server.php
@@ -15,7 +15,7 @@
use Leafo\ScssPhp\Version;
/**
- * SCSS server
+ * Server
*
* @author Leaf Corcoran
*/
diff --git a/src/Type.php b/src/Type.php
index 80b53258..8c3886c8 100644
--- a/src/Type.php
+++ b/src/Type.php
@@ -12,7 +12,7 @@
namespace Leafo\ScssPhp;
/**
- * SCSS block/node types
+ * Block/node types
*
* @author Anthon Pang
*/
diff --git a/src/Util.php b/src/Util.php
index 714acdb8..9f47c1d7 100644
--- a/src/Util.php
+++ b/src/Util.php
@@ -14,7 +14,7 @@
use Leafo\ScssPhp\Base\Range;
/**
- * SCSS utilties
+ * Utilties
*
* @author Anthon Pang
*/
From 038518b1dab60d39a96bfa8dd99dcd41d654679a Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Sun, 6 Dec 2015 18:45:00 -0500
Subject: [PATCH 199/534] Add ServerException
---
scss.inc.php | 5 +++--
src/Compiler.php | 6 +++---
...ileException.php => CompilerException.php} | 2 +-
...ParseException.php => ParserException.php} | 4 ++--
src/Exception/ServerException.php | 21 +++++++++++++++++++
src/Parser.php | 8 +++----
src/Server.php | 15 ++++++-------
7 files changed, 42 insertions(+), 19 deletions(-)
rename src/Exception/{CompileException.php => CompilerException.php} (87%)
rename src/Exception/{ParseException.php => ParserException.php} (81%)
create mode 100644 src/Exception/ServerException.php
diff --git a/scss.inc.php b/scss.inc.php
index aaeddcad..d3720eb7 100644
--- a/scss.inc.php
+++ b/scss.inc.php
@@ -9,8 +9,9 @@
include_once __DIR__ . '/src/Colors.php';
include_once __DIR__ . '/src/Compiler.php';
include_once __DIR__ . '/src/Compiler/Environment.php';
- include_once __DIR__ . '/src/Exception/CompileException.php';
- include_once __DIR__ . '/src/Exception/ParseException.php';
+ include_once __DIR__ . '/src/Exception/CompilerException.php';
+ include_once __DIR__ . '/src/Exception/ParserException.php';
+ include_once __DIR__ . '/src/Exception/ServerException.php';
include_once __DIR__ . '/src/Formatter.php';
include_once __DIR__ . '/src/Formatter/Compact.php';
include_once __DIR__ . '/src/Formatter/Compressed.php';
diff --git a/src/Compiler.php b/src/Compiler.php
index f986c831..8f8ff830 100644
--- a/src/Compiler.php
+++ b/src/Compiler.php
@@ -15,7 +15,7 @@
use Leafo\ScssPhp\Block;
use Leafo\ScssPhp\Colors;
use Leafo\ScssPhp\Compiler\Environment;
-use Leafo\ScssPhp\Exception\CompileException;
+use Leafo\ScssPhp\Exception\CompilerException;
use Leafo\ScssPhp\Formatter\OutputBlock;
use Leafo\ScssPhp\Node;
use Leafo\ScssPhp\Type;
@@ -3210,7 +3210,7 @@ public function findImport($url)
*
* @param string $msg Message with optional sprintf()-style vararg parameters
*
- * @throws \Leafo\ScssPhp\Exception\CompileException
+ * @throws \Leafo\ScssPhp\Exception\CompilerException
*/
public function throwError($msg)
{
@@ -3221,7 +3221,7 @@ public function throwError($msg)
$line = $this->sourceLine;
$msg = "$msg: line: $line";
- throw new CompileException($msg);
+ throw new CompilerException($msg);
}
/**
diff --git a/src/Exception/CompileException.php b/src/Exception/CompilerException.php
similarity index 87%
rename from src/Exception/CompileException.php
rename to src/Exception/CompilerException.php
index dbb554ed..777e40ac 100644
--- a/src/Exception/CompileException.php
+++ b/src/Exception/CompilerException.php
@@ -16,6 +16,6 @@
*
* @author Oleksandr Savchenko
*/
-class CompileException extends \Exception
+class CompilerException extends \Exception
{
}
diff --git a/src/Exception/ParseException.php b/src/Exception/ParserException.php
similarity index 81%
rename from src/Exception/ParseException.php
rename to src/Exception/ParserException.php
index 5737e142..fbe6388f 100644
--- a/src/Exception/ParseException.php
+++ b/src/Exception/ParserException.php
@@ -12,10 +12,10 @@
namespace Leafo\ScssPhp\Exception;
/**
- * Parse Exception
+ * Parser Exception
*
* @author Oleksandr Savchenko
*/
-class ParseException extends \Exception
+class ParserException extends \Exception
{
}
diff --git a/src/Exception/ServerException.php b/src/Exception/ServerException.php
new file mode 100644
index 00000000..5a878d2f
--- /dev/null
+++ b/src/Exception/ServerException.php
@@ -0,0 +1,21 @@
+
+ */
+class ServerException extends \Exception
+{
+}
diff --git a/src/Parser.php b/src/Parser.php
index f5789729..7bf6c8f3 100644
--- a/src/Parser.php
+++ b/src/Parser.php
@@ -13,7 +13,7 @@
use Leafo\ScssPhp\Block;
use Leafo\ScssPhp\Compiler;
-use Leafo\ScssPhp\Exception\ParseException;
+use Leafo\ScssPhp\Exception\ParserException;
use Leafo\ScssPhp\Node;
use Leafo\ScssPhp\Type;
@@ -108,7 +108,7 @@ public function getSourceName()
*
* @param string $msg
*
- * @throws \Leafo\ScssPhp\Exception\ParseException
+ * @throws \Leafo\ScssPhp\Exception\ParserException
*/
public function throwParseError($msg = 'parse error')
{
@@ -117,10 +117,10 @@ public function throwParseError($msg = 'parse error')
$loc = empty($this->sourceName) ? "line: $line" : "$this->sourceName on line $line";
if ($this->peek("(.*?)(\n|$)", $m, $this->count)) {
- throw new ParseException("$msg: failed at `$m[1]` $loc");
+ throw new ParserException("$msg: failed at `$m[1]` $loc");
}
- throw new ParseException("$msg: $loc");
+ throw new ParserException("$msg: $loc");
}
/**
diff --git a/src/Server.php b/src/Server.php
index de4e8830..cada00e0 100644
--- a/src/Server.php
+++ b/src/Server.php
@@ -12,6 +12,7 @@
namespace Leafo\ScssPhp;
use Leafo\ScssPhp\Compiler;
+use Leafo\ScssPhp\Exception\ServerException;
use Leafo\ScssPhp\Version;
/**
@@ -231,7 +232,7 @@ protected function compile($in, $out)
*
* @return string
*/
- protected function createErrorCSS($error)
+ protected function createErrorCSS(\Exception $error)
{
$message = str_replace(
array("'", "\n"),
@@ -269,11 +270,13 @@ public function showErrorsAsCSS($show = true)
* @param string $out Output file (.css) optional
*
* @return string|bool
+ *
+ * @throws \Leafo\ScssPhp\Exception\ServerException
*/
public function compileFile($in, $out = null)
{
if (! is_readable($in)) {
- throw new \Exception('load error: failed to find ' . $in);
+ throw new ServerException('load error: failed to find ' . $in);
}
$pi = pathinfo($in);
@@ -334,7 +337,6 @@ public function serve($salt = '')
header('ETag: "' . $etag . '"');
echo $css;
-
} catch (\Exception $e) {
if ($this->showErrorsAsCSS) {
header('Content-type: text/css');
@@ -346,7 +348,6 @@ public function serve($salt = '')
echo 'Parse error: ' . $e->getMessage() . "\n";
}
-
}
return;
@@ -395,16 +396,16 @@ public function serve($salt = '')
*
* @return string Compiled CSS results
*
- * @throws \Exception
+ * @throws \Leafo\ScssPhp\Exception\ServerException
*/
public function checkedCachedCompile($in, $out, $force = false)
{
if (! is_file($in) || ! is_readable($in)) {
- throw new \Exception('Invalid or unreadable input file specified.');
+ throw new ServerException('Invalid or unreadable input file specified.');
}
if (is_dir($out) || ! is_writable(file_exists($out) ? $out : dirname($out))) {
- throw new \Exception('Invalid or unwritable output file specified.');
+ throw new ServerException('Invalid or unwritable output file specified.');
}
if ($force || $this->needsCompile($in, $out, $etag)) {
From 53e68de07034da565793495027c1dd27835a421c Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Sun, 6 Dec 2015 20:15:59 -0500
Subject: [PATCH 200/534] add more failing tests
---
tests/FailingTest.php | 26 ++++++++++++++++++++++++++
1 file changed, 26 insertions(+)
diff --git a/tests/FailingTest.php b/tests/FailingTest.php
index 863ffe00..3cdf0a04 100644
--- a/tests/FailingTest.php
+++ b/tests/FailingTest.php
@@ -110,6 +110,32 @@ public function provideFailing()
small {
font-weight: italic; }
+END_OF_EXPECTED
+ ),
+ array(
+ '#368 - self in selector', <<<'END_OF_SCSS'
+.test {
+ &:last-child:not(+ &:first-child) {
+ padding-left: 10px;
+ }
+}
+END_OF_SCSS
+ , <<
Date: Fri, 13 Nov 2015 10:12:06 +0200
Subject: [PATCH 201/534] ignore errors
---
src/Compiler.php | 35 +++++++++++++++++++++++++++++++++++
1 file changed, 35 insertions(+)
diff --git a/src/Compiler.php b/src/Compiler.php
index 8f8ff830..cb25ba26 100644
--- a/src/Compiler.php
+++ b/src/Compiler.php
@@ -141,6 +141,11 @@ class Compiler
private $stderr;
private $shouldEvaluate;
+ /**
+ * @var boolean ignore SCSS errors or throw an error
+ */
+ private $ignoreErrors;
+
/**
* Constructor
*/
@@ -3214,6 +3219,10 @@ public function findImport($url)
*/
public function throwError($msg)
{
+ if ($this->isIgnoreErrors()) {
+ return;
+ }
+
if (func_num_args() > 1) {
$msg = call_user_func_array('sprintf', func_get_args());
}
@@ -4945,4 +4954,30 @@ protected function libUniqueId()
return array(Type::T_STRING, '', array('u' . str_pad(base_convert($id, 10, 36), 8, '0', STR_PAD_LEFT)));
}
+
+ /**
+ * is IgnoreErrors
+ *
+ * @return boolean
+ */
+ private function isIgnoreErrors()
+ {
+ return $this->ignoreErrors;
+ }
+
+ /**
+ * Set IgnoreErrors
+ *
+ * @api
+ *
+ * @param boolean $ignoreErrors
+ *
+ * @return \Leafo\ScssPhp\Compiler
+ */
+ public function setIgnoreErrors($ignoreErrors)
+ {
+ $this->ignoreErrors = $ignoreErrors;
+
+ return $this;
+ }
}
From 990fbea30cb55dc37f69e2b143d652f6b81dda12 Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Tue, 8 Dec 2015 12:08:15 -0500
Subject: [PATCH 202/534] bin/pscss: add --continue-on-error
---
bin/pscss | 27 +++++++++++++++++++--------
src/Compiler.php | 46 +++++++++++++++-------------------------------
2 files changed, 34 insertions(+), 39 deletions(-)
diff --git a/bin/pscss b/bin/pscss
index 4dd5136a..16a12039 100755
--- a/bin/pscss
+++ b/bin/pscss
@@ -30,6 +30,7 @@ $inputFile = null;
$changeDir = false;
$debugInfo = false;
$lineNumbers = false;
+$ignoreErrors = false;
/**
* Parse argument
@@ -67,14 +68,15 @@ Usage: $exe [options] [input-file]
Options include:
- --debug-info Annotate selectors with CSS referring to the source file and line number
- -h, --help Show this message
- -f=format Set the output format (compact, compressed, crunched, expanded, or nested)
- -i=path Set import path
- --line-numbers Annotate selectors with comments referring to the source file and line number
- -p=precision Set decimal number precision (default 5)
- -T Dump formatted parse tree
- -v, --version Print the version
+ -h, --help Show this message
+ --continue-on-error Continue compilation (as best as possible) when error encountered
+ --debug-info Annotate selectors with CSS referring to the source file and line number
+ -f=format Set the output format (compact, compressed, crunched, expanded, or nested)
+ -i=path Set import path
+ --line-numbers Annotate selectors with comments referring to the source file and line number
+ -p=precision Set decimal number precision (default 5)
+ -T Dump formatted parse tree
+ -v, --version Print the version
EOT;
exit($HELP);
@@ -84,6 +86,11 @@ EOT;
exit(Version::VERSION . "\n");
}
+ if ($argv[$i] === '--continue-on-error') {
+ $ignoreErrors = true;
+ continue;
+ }
+
if ($argv[$i] === '--debug-info') {
$debugInfo = true;
continue;
@@ -163,6 +170,10 @@ if ($lineNumbers && $inputFile) {
$scss->setLineNumberStyle(Compiler::LINE_COMMENTS);
}
+if ($ignoreErrors) {
+ $scss->setIgnoreErrors($ignoreErrors);
+}
+
if ($loadPaths) {
$scss->setImportPaths(explode(PATH_SEPARATOR, $loadPaths));
}
diff --git a/src/Compiler.php b/src/Compiler.php
index cb25ba26..6140ffef 100644
--- a/src/Compiler.php
+++ b/src/Compiler.php
@@ -140,10 +140,6 @@ class Compiler
private $charsetSeen;
private $stderr;
private $shouldEvaluate;
-
- /**
- * @var boolean ignore SCSS errors or throw an error
- */
private $ignoreErrors;
/**
@@ -3208,6 +3204,20 @@ public function findImport($url)
return null;
}
+ /**
+ * Ignore errors?
+ *
+ * @api
+ *
+ * @param boolean $ignoreErrors
+ *
+ * @return \Leafo\ScssPhp\Compiler
+ */
+ public function setIgnoreErrors($ignoreErrors)
+ {
+ $this->ignoreErrors = $ignoreErrors;
+ }
+
/**
* Throw error (exception)
*
@@ -3219,7 +3229,7 @@ public function findImport($url)
*/
public function throwError($msg)
{
- if ($this->isIgnoreErrors()) {
+ if ($this->ignoreErrors) {
return;
}
@@ -4954,30 +4964,4 @@ protected function libUniqueId()
return array(Type::T_STRING, '', array('u' . str_pad(base_convert($id, 10, 36), 8, '0', STR_PAD_LEFT)));
}
-
- /**
- * is IgnoreErrors
- *
- * @return boolean
- */
- private function isIgnoreErrors()
- {
- return $this->ignoreErrors;
- }
-
- /**
- * Set IgnoreErrors
- *
- * @api
- *
- * @param boolean $ignoreErrors
- *
- * @return \Leafo\ScssPhp\Compiler
- */
- public function setIgnoreErrors($ignoreErrors)
- {
- $this->ignoreErrors = $ignoreErrors;
-
- return $this;
- }
}
From 48ccb0dc4a6af0bd2654b28e2dd7ac4dbbc6e64e Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Tue, 8 Dec 2015 23:17:36 -0500
Subject: [PATCH 203/534] Refs #388 - yet another BEM fix
---
src/Compiler.php | 6 +++++-
tests/inputs/extends.scss | 12 ++++++++++++
tests/outputs/extends.css | 5 +++++
tests/outputs_numbered/extends.css | 9 +++++++++
4 files changed, 31 insertions(+), 1 deletion(-)
diff --git a/src/Compiler.php b/src/Compiler.php
index 6140ffef..84d0b99f 100644
--- a/src/Compiler.php
+++ b/src/Compiler.php
@@ -466,7 +466,11 @@ protected function matchExtendsSingle($rawSingle, &$outOrigin)
return false;
}
- $origin[$j][count($origin[$j]) - 1] = $this->combineSelectorSingle(end($new), $rem);
+ $combined = $this->combineSelectorSingle(end($new), $rem);
+
+ if (count(array_diff($combined, $origin[$j][count($origin[$j]) - 1]))) {
+ $origin[$j][count($origin[$j]) - 1] = $combined;
+ }
}
$outOrigin = array_merge($outOrigin, $origin);
diff --git a/tests/inputs/extends.scss b/tests/inputs/extends.scss
index fe93cab8..315f25ea 100644
--- a/tests/inputs/extends.scss
+++ b/tests/inputs/extends.scss
@@ -269,3 +269,15 @@ $var: ".selector1, .selector2";
// interpolation of the variable is needed since we have a selector in $var
@extend #{$var};
}
+
+// scss
+.main {
+ .block__element {
+ font-size: 14px;
+
+ &--modifier {
+ @extend .block__element;
+ font-weight: bold;
+ }
+ }
+}
diff --git a/tests/outputs/extends.css b/tests/outputs/extends.css
index cd101158..82a65823 100644
--- a/tests/outputs/extends.css
+++ b/tests/outputs/extends.css
@@ -124,3 +124,8 @@ body .to-extend, body .test {
.selector2, .master-class {
background: #ccc; }
+
+.main .block__element, .main .block__element--modifier {
+ font-size: 14px; }
+ .main .block__element--modifier {
+ font-weight: bold; }
diff --git a/tests/outputs_numbered/extends.css b/tests/outputs_numbered/extends.css
index cfaa646b..935d1033 100644
--- a/tests/outputs_numbered/extends.css
+++ b/tests/outputs_numbered/extends.css
@@ -191,3 +191,12 @@ body .to-extend, body .test {
.selector2, .master-class {
background: #ccc; }
/* line 268, inputs/extends.scss */
+/* line 274, inputs/extends.scss */
+
+/* line 275, inputs/extends.scss */
+
+.main .block__element, .main .block__element--modifier {
+ font-size: 14px; }
+/* line 278, inputs/extends.scss */
+.main .block__element--modifier {
+ font-weight: bold; }
From 9f71d901bf56a08072a11a59940bb7ab216bedee Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Wed, 9 Dec 2015 12:33:23 -0500
Subject: [PATCH 204/534] refs #379 - break/return if throwError returns (i.e.,
continue-on-error)
---
src/Compiler.php | 21 ++++++++++++++++++---
1 file changed, 18 insertions(+), 3 deletions(-)
diff --git a/src/Compiler.php b/src/Compiler.php
index 84d0b99f..9a0429d3 100644
--- a/src/Compiler.php
+++ b/src/Compiler.php
@@ -1171,6 +1171,8 @@ protected function compileChildrenNoReturn($stms, OutputBlock $out)
if (isset($ret)) {
$this->throwError('@return may only be used within a function');
+
+ return;
}
}
}
@@ -1650,6 +1652,7 @@ protected function compileChild($child, OutputBlock $out)
if (! $mixin) {
$this->throwError("Undefined mixin $name");
+ break;
}
$callingScope = $this->getStoreEnv();
@@ -1680,9 +1683,6 @@ protected function compileChild($child, OutputBlock $out)
if (! $content) {
$this->throwError('Expected @content inside of mixin');
- }
-
- if (! isset($content->children)) {
break;
}
@@ -2247,6 +2247,7 @@ protected function opColorColor($op, $left, $right)
case '/':
if ($rval == 0) {
$this->throwError("color: Can't divide by zero");
+ break 2;
}
$out[] = (int) ($lval / $rval);
@@ -2260,6 +2261,7 @@ protected function opColorColor($op, $left, $right)
default:
$this->throwError("color: unknown op $op");
+ break 2;
}
}
@@ -3261,6 +3263,7 @@ private function handleImportLoop($name)
if (realpath($file) === $name) {
$this->throwError('An @import loop has been found: %s imports %s', $file, basename($file));
+ break;
}
}
}
@@ -3462,14 +3465,17 @@ protected function applyArguments($argDef, $argValues)
$deferredKeywordArgs[$arg[0][1]] = $arg[1];
} else {
$this->throwError("Mixin or function doesn't have an argument named $%s.", $arg[0][1]);
+ break;
}
} elseif ($args[$arg[0][1]][0] < count($remaining)) {
$this->throwError("The argument $%s was passed both by position and by name.", $arg[0][1]);
+ break;
} else {
$keywordArgs[$arg[0][1]] = $arg[1];
}
} elseif (count($keywordArgs)) {
$this->throwError('Positional arguments must come before keyword arguments.');
+ break;
} elseif ($arg[2] === true) {
$val = $this->reduce($arg[1], true);
@@ -3521,6 +3527,7 @@ protected function applyArguments($argDef, $argValues)
continue;
} else {
$this->throwError("Missing argument $name");
+ break;
}
$this->set($name, $this->reduce($val, true), true, $env);
@@ -4492,6 +4499,7 @@ protected function getNormalizedNumbers($args)
foreach ($args as $key => $item) {
if ($item[0] !== Type::T_NUMBER) {
$this->throwError('%s is not a number', $item[0]);
+ break;
}
$number = $item->normalize();
@@ -4501,6 +4509,7 @@ protected function getNormalizedNumbers($args)
$originalUnit = $item->unitStr();
} elseif ($unit !== $number[2]) {
$this->throwError('Incompatible units: "%s" and "%s".', $originalUnit, $item->unitStr());
+ break;
}
$numbers[$key] = $number;
@@ -4567,6 +4576,8 @@ protected function libSetNth($args)
if (! isset($list[2][$n])) {
$this->throwError('Invalid argument for "n"');
+
+ return;
}
$list[2][$n] = $args[2];
@@ -4773,6 +4784,8 @@ protected function libComparable($args)
! isset($number2[0]) || $number2[0] !== Type::T_NUMBER
) {
$this->throwError('Invalid argument(s) for "comparable"');
+
+ return;
}
$number1 = $number1->normalize();
@@ -4948,6 +4961,8 @@ protected function libRandom($args)
if ($n < 1) {
$this->throwError("limit must be greater than or equal to 1");
+
+ return;
}
return new Node\Number(mt_rand(1, $n), '');
From f642956291be38aa6627c9fb61386160bc181e46 Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Wed, 9 Dec 2015 13:29:03 -0500
Subject: [PATCH 205/534] fix another potential notice
---
src/Compiler.php | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/Compiler.php b/src/Compiler.php
index 9a0429d3..a08f1ba6 100644
--- a/src/Compiler.php
+++ b/src/Compiler.php
@@ -1128,7 +1128,7 @@ protected function hasSelectorPlaceholder($selector)
foreach ($selector as $parts) {
foreach ($parts as $part) {
- if ('%' === $part[0]) {
+ if (strlen($part) && '%' === $part[0]) {
return true;
}
}
From a070856a488e19df6b65e83b1ac5c71e37c19d83 Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Sun, 13 Dec 2015 01:24:06 -0500
Subject: [PATCH 206/534] fixes #304 - implement @extend !optional
---
src/Compiler.php | 41 +++++++++++++++++++++++++-----
src/Parser.php | 29 +++++++++++++++++++--
tests/ExceptionTest.php | 8 ++++++
tests/inputs/extends.scss | 4 +++
tests/outputs_numbered/extends.css | 1 +
5 files changed, 75 insertions(+), 8 deletions(-)
diff --git a/src/Compiler.php b/src/Compiler.php
index a08f1ba6..5e6c11d5 100644
--- a/src/Compiler.php
+++ b/src/Compiler.php
@@ -238,17 +238,18 @@ protected function isSelfExtend($target, $origin)
/**
* Push extends
*
- * @param array $target
- * @param array $origin
+ * @param array $target
+ * @param array $origin
+ * @param \stdClass $block
*/
- protected function pushExtends($target, $origin)
+ protected function pushExtends($target, $origin, $block)
{
if ($this->isSelfExtend($target, $origin)) {
return;
}
$i = count($this->extends);
- $this->extends[] = array($target, $origin);
+ $this->extends[] = array($target, $origin, $block);
foreach ($target as $part) {
if (isset($this->extendsMap[$part])) {
@@ -291,6 +292,32 @@ protected function compileRoot(Block $rootBlock)
$this->compileChildrenNoReturn($rootBlock->children, $this->scope);
$this->flattenSelectors($this->scope);
+ $this->missingSelectors();
+ }
+
+ /**
+ * Report missing selectors
+ */
+ protected function missingSelectors()
+ {
+ foreach ($this->extends as $extend) {
+ if (isset($extend[3])) {
+ continue;
+ }
+
+ list($target, $origin, $block) = $extend;
+
+ // ignore if !optional
+ if ($block[2]) {
+ continue;
+ }
+
+ $target = implode(' ', $target);
+ $origin = $this->collapseSelectors($origin);
+
+ $this->sourceLine = $block[Parser::SOURCE_LINE];
+ $this->throwError("\"$origin\" failed to @extend \"$target\". The selector \"$target\" was not found.");
+ }
}
/**
@@ -451,13 +478,15 @@ protected function matchExtendsSingle($rawSingle, &$outOrigin)
$found = false;
foreach ($counts as $idx => $count) {
- list($target, $origin) = $this->extends[$idx];
+ list($target, $origin, $block) = $this->extends[$idx];
// check count
if ($count !== count($target)) {
continue;
}
+ $this->extends[$idx][3] = true;
+
$rem = array_diff($single, $target);
foreach ($origin as $j => $new) {
@@ -1504,7 +1533,7 @@ protected function compileChild($child, OutputBlock $out)
// only use the first one
$result = current($result);
- $this->pushExtends($result, $out->selectors);
+ $this->pushExtends($result, $out->selectors, $child);
}
}
break;
diff --git a/src/Parser.php b/src/Parser.php
index 7bf6c8f3..b543f182 100644
--- a/src/Parser.php
+++ b/src/Parser.php
@@ -349,10 +349,12 @@ protected function parseChunk()
$this->seek($s);
if ($this->literal('@extend') &&
- $this->selectors($selector) &&
+ $this->selectors($selectors) &&
$this->end()
) {
- $this->append(array(Type::T_EXTEND, $selector), $s);
+ // check for '!flag'
+ $optional = $this->stripOptionalFlag($selectors);
+ $this->append(array(Type::T_EXTEND, $selectors, $optional), $s);
return true;
}
@@ -2326,6 +2328,29 @@ protected function stripAssignmentFlag(&$value)
return false;
}
+ /**
+ * Strip optional flag from selector list
+ *
+ * @param array $selectors
+ *
+ * @return string
+ */
+ protected function stripOptionalFlag(&$selectors)
+ {
+ $optional = false;
+
+ $selector = end($selectors);
+ $part = end($selector);
+
+ if ($part === array('!optional')) {
+ array_pop($selectors[count($selectors) - 1]);
+
+ $optional = true;
+ }
+
+ return $optional;
+ }
+
/**
* Turn list of length 1 into value type
*
diff --git a/tests/ExceptionTest.php b/tests/ExceptionTest.php
index 4406c523..f5fa17a5 100644
--- a/tests/ExceptionTest.php
+++ b/tests/ExceptionTest.php
@@ -131,6 +131,14 @@ public function provideScss()
,
'isn\'t a valid CSS value'
),
+ array(<<<'END_OF_SCSS'
+a.important {
+ @extend .notice;
+}
+END_OF_SCSS
+ ,
+ 'was not found'
+ ),
);
}
diff --git a/tests/inputs/extends.scss b/tests/inputs/extends.scss
index 315f25ea..9da03502 100644
--- a/tests/inputs/extends.scss
+++ b/tests/inputs/extends.scss
@@ -281,3 +281,7 @@ $var: ".selector1, .selector2";
}
}
}
+
+a.important {
+ @extend .notice !optional;
+}
diff --git a/tests/outputs_numbered/extends.css b/tests/outputs_numbered/extends.css
index 935d1033..5d76d9d3 100644
--- a/tests/outputs_numbered/extends.css
+++ b/tests/outputs_numbered/extends.css
@@ -200,3 +200,4 @@ body .to-extend, body .test {
/* line 278, inputs/extends.scss */
.main .block__element--modifier {
font-weight: bold; }
+/* line 285, inputs/extends.scss */
From adfc2cf537e3fbe07d1d48fcf184c13460e1f218 Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Sun, 13 Dec 2015 02:30:32 -0500
Subject: [PATCH 207/534] fixes #301 - implement keywords()
---
src/Compiler.php | 16 ++++++++++++++++
1 file changed, 16 insertions(+)
diff --git a/src/Compiler.php b/src/Compiler.php
index 5e6c11d5..2eac200b 100644
--- a/src/Compiler.php
+++ b/src/Compiler.php
@@ -4687,6 +4687,22 @@ protected function libMapMerge($args)
return array(Type::T_MAP, array_merge($map1[1], $map2[1]), array_merge($map1[2], $map2[2]));
}
+ protected static $libKeywords = array('args');
+ protected function libKeywords($args)
+ {
+ $this->assertList($args[0]);
+
+ $keys = array();
+ $values = array();
+
+ foreach ($args[0][2] as $name => $arg) {
+ $keys[] = array(Type::T_KEYWORD, $name);
+ $values[] = $arg;
+ }
+
+ return array(Type::T_MAP, $keys, $values);
+ }
+
protected function listSeparatorForJoin($list1, $sep)
{
if (! isset($sep)) {
From fc8c73b7955b22b40792d716d42c8daa5b43a777 Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Sun, 13 Dec 2015 03:03:38 -0500
Subject: [PATCH 208/534] Bump version to v0.6.1
---
src/Version.php | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/Version.php b/src/Version.php
index a47062b1..ef096e94 100644
--- a/src/Version.php
+++ b/src/Version.php
@@ -18,5 +18,5 @@
*/
class Version
{
- const VERSION = 'v0.6.0';
+ const VERSION = 'v0.6.1';
}
From 317a7b31b49ae442cb70706456d36a5eef45d38b Mon Sep 17 00:00:00 2001
From: Marat Tanalin
Date: Mon, 14 Dec 2015 01:10:30 +0300
Subject: [PATCH 209/534] Added `rebeccapurple` named color
It is supported by all current major browsers.
Some details:
* https://drafts.csswg.org/css-color/#valdef-color-rebeccapurple
* http://codepen.io/trezy/post/honoring-a-great-man
---
src/Colors.php | 1 +
1 file changed, 1 insertion(+)
diff --git a/src/Colors.php b/src/Colors.php
index 0227fbe0..d1a75949 100644
--- a/src/Colors.php
+++ b/src/Colors.php
@@ -145,6 +145,7 @@ class Colors
'plum' => '221,160,221',
'powderblue' => '176,224,230',
'purple' => '128,0,128',
+ 'rebeccapurple' => '102,51,153',
'red' => '255,0,0',
'rosybrown' => '188,143,143',
'royalblue' => '65,105,225',
From d27d49229c17b42f4d9b055d41984b62df9fcbb3 Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Sun, 13 Dec 2015 20:03:25 -0500
Subject: [PATCH 210/534] phpcs tweak
---
src/Colors.php | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/Colors.php b/src/Colors.php
index d1a75949..e3936a5f 100644
--- a/src/Colors.php
+++ b/src/Colors.php
@@ -174,6 +174,6 @@ class Colors
'white' => '255,255,255',
'whitesmoke' => '245,245,245',
'yellow' => '255,255,0',
- 'yellowgreen' => '154,205,50'
+ 'yellowgreen' => '154,205,50',
);
}
From 3eaa3f8df021f3dcbe19f814540c941308a9668f Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Sun, 13 Dec 2015 20:43:36 -0500
Subject: [PATCH 211/534] fixes #303 - implement inspect($value) built-in
---
src/Compiler.php | 11 +++++++++++
tests/inputs/functions.scss | 14 ++++++++++++++
tests/outputs/functions.css | 13 +++++++++++++
tests/outputs_numbered/functions.css | 13 +++++++++++++
4 files changed, 51 insertions(+)
diff --git a/src/Compiler.php b/src/Compiler.php
index 2eac200b..57ec4d65 100644
--- a/src/Compiler.php
+++ b/src/Compiler.php
@@ -4999,6 +4999,7 @@ protected function libCounter($args)
return array(Type::T_STRING, '', array('counter(' . implode(',', $list) . ')'));
}
+ protected static $libRandom = array('limit');
protected function libRandom($args)
{
if (isset($args[0])) {
@@ -5028,4 +5029,14 @@ protected function libUniqueId()
return array(Type::T_STRING, '', array('u' . str_pad(base_convert($id, 10, 36), 8, '0', STR_PAD_LEFT)));
}
+
+ protected static $libInspect = array('value');
+ protected function libInspect($args)
+ {
+ if ($args[0] === self::$null) {
+ return array(Type::T_KEYWORD, 'null');
+ }
+
+ return $args[0];
+ }
}
diff --git a/tests/inputs/functions.scss b/tests/inputs/functions.scss
index 4886a6e5..bcceaffd 100644
--- a/tests/inputs/functions.scss
+++ b/tests/inputs/functions.scss
@@ -114,3 +114,17 @@ $str: 'global';
@include test-mixin;
display: $str;
}
+
+.test-inspect {
+ n: inspect(null);
+ b1: inspect(true);
+ b2: inspect(false);
+ n1: inspect(0);
+ s1: inspect('');
+ s2: inspect('hello');
+ l1: inspect(1 2);
+ l2: inspect((3 4));
+ l3: inspect((5,6));
+ l4: inspect((a: 1, b: 2));
+ l5: inspect($value: (a: 1, b: 2));
+}
diff --git a/tests/outputs/functions.css b/tests/outputs/functions.css
index 9604accb..252e3909 100644
--- a/tests/outputs/functions.css
+++ b/tests/outputs/functions.css
@@ -32,3 +32,16 @@ p {
display: 'test-mixin';
display: 'test-mixin';
display: 'global'; }
+
+.test-inspect {
+ n: null;
+ b1: true;
+ b2: false;
+ n1: 0;
+ s1: '';
+ s2: 'hello';
+ l1: 1 2;
+ l2: 3 4;
+ l3: 5, 6;
+ l4: (a: 1, b: 2);
+ l5: (a: 1, b: 2); }
diff --git a/tests/outputs_numbered/functions.css b/tests/outputs_numbered/functions.css
index 4949511a..9b525e8d 100644
--- a/tests/outputs_numbered/functions.css
+++ b/tests/outputs_numbered/functions.css
@@ -34,3 +34,16 @@ p {
display: 'test-mixin';
display: 'test-mixin';
display: 'global'; }
+/* line 118, inputs/functions.scss */
+.test-inspect {
+ n: null;
+ b1: true;
+ b2: false;
+ n1: 0;
+ s1: '';
+ s2: 'hello';
+ l1: 1 2;
+ l2: 3 4;
+ l3: 5, 6;
+ l4: (a: 1, b: 2);
+ l5: (a: 1, b: 2); }
From 493e05a95431e0cbb3ed6cbca65e07e6e443e19e Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Tue, 15 Dec 2015 13:41:21 -0500
Subject: [PATCH 212/534] support unicode characters in scss indentifers
---
src/Parser.php | 10 +++++-----
tests/inputs/variables.scss | 7 +++++++
tests/outputs/variables.css | 3 +++
tests/outputs_numbered/variables.css | 3 +++
4 files changed, 18 insertions(+), 5 deletions(-)
diff --git a/src/Parser.php b/src/Parser.php
index b543f182..a0986136 100644
--- a/src/Parser.php
+++ b/src/Parser.php
@@ -85,7 +85,7 @@ public function __construct($sourceName, $sourceIndex = 0)
$commentMultiRight = '\*\/';
self::$commentPattern = $commentMultiLeft . '.*?' . $commentMultiRight;
- self::$whitePattern = '/' . $commentSingle . '[^\n]*\s*|(' . self::$commentPattern . ')\s*|\s+/Ais';
+ self::$whitePattern = '/' . $commentSingle . '[^\n]*\s*|(' . self::$commentPattern . ')\s*|\s+/AisuS';
}
}
@@ -762,7 +762,7 @@ protected function peek($regex, &$out, $from = null)
$from = $this->count;
}
- $r = '/' . $regex . '/Ais';
+ $r = '/' . $regex . '/Aisu';
$result = preg_match($r, $this->buffer, $out, null, $from);
return $result;
@@ -842,7 +842,7 @@ protected function match($regex, &$out, $eatWhitespace = null)
$eatWhitespace = $this->eatWhiteDefault;
}
- $r = '/' . $regex . '/Ais';
+ $r = '/' . $regex . '/Aisu';
if (preg_match($r, $this->buffer, $out, null, $this->count)) {
$this->count += strlen($out[0]);
@@ -2235,7 +2235,7 @@ protected function variable(&$out)
protected function keyword(&$word, $eatWhitespace = null)
{
if ($this->match(
- '(([\w_\-\*!"\']|[\\\\].)([\w\-_"\']|[\\\\].)*)',
+ '(([\pL\w_\-\*!"\']|[\\\\].)([\pL\w\-_"\']|[\\\\].)*)',
$m,
$eatWhitespace
)) {
@@ -2256,7 +2256,7 @@ protected function keyword(&$word, $eatWhitespace = null)
*/
protected function placeholder(&$placeholder)
{
- if ($this->match('([\w\-_]+|#[{][$][\w\-_]+[}])', $m)) {
+ if ($this->match('([\pL\w\-_]+|#[{][$][\pL\w\-_]+[}])', $m)) {
$placeholder = $m[1];
return true;
diff --git a/tests/inputs/variables.scss b/tests/inputs/variables.scss
index 367416fc..53149e6e 100644
--- a/tests/inputs/variables.scss
+++ b/tests/inputs/variables.scss
@@ -73,3 +73,10 @@ A {
@include example;
color: $color;
}
+
+$коммент : #000;
+
+body
+{
+ color: $коммент ;
+}
diff --git a/tests/outputs/variables.css b/tests/outputs/variables.css
index 693ee6ef..ed3e6b21 100644
--- a/tests/outputs/variables.css
+++ b/tests/outputs/variables.css
@@ -31,3 +31,6 @@ body {
A {
color: green; }
+
+body {
+ color: #000; }
diff --git a/tests/outputs_numbered/variables.css b/tests/outputs_numbered/variables.css
index f341c52f..206fa249 100644
--- a/tests/outputs_numbered/variables.css
+++ b/tests/outputs_numbered/variables.css
@@ -34,3 +34,6 @@ body {
/* line 71, inputs/variables.scss */
A {
color: green; }
+/* line 79, inputs/variables.scss */
+body {
+ color: #000; }
From 4ac664e32bd68833e69d88f0f1568239f7731113 Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Tue, 15 Dec 2015 13:51:36 -0500
Subject: [PATCH 213/534] tweak tests
---
tests/inputs/comments.scss | 4 ++++
tests/inputs/variables.scss | 4 ++--
tests/outputs/comments.css | 1 +
tests/outputs_numbered/comments.css | 1 +
4 files changed, 8 insertions(+), 2 deletions(-)
diff --git a/tests/inputs/comments.scss b/tests/inputs/comments.scss
index 80ab6c73..3e641cc1 100644
--- a/tests/inputs/comments.scss
+++ b/tests/inputs/comments.scss
@@ -41,4 +41,8 @@ a {
}
/* comment 7 */
+/* коммент */
+
+// коммент
+
// end
diff --git a/tests/inputs/variables.scss b/tests/inputs/variables.scss
index 53149e6e..5212c385 100644
--- a/tests/inputs/variables.scss
+++ b/tests/inputs/variables.scss
@@ -74,9 +74,9 @@ A {
color: $color;
}
-$коммент : #000;
+$цвет : #000;
body
{
- color: $коммент ;
+ color: $цвет;
}
diff --git a/tests/outputs/comments.css b/tests/outputs/comments.css
index 6535554c..f6f8d184 100644
--- a/tests/outputs/comments.css
+++ b/tests/outputs/comments.css
@@ -29,3 +29,4 @@ a {
/* comment 5 */
/* comment 6 */ }
/* comment 7 */
+/* коммент */
diff --git a/tests/outputs_numbered/comments.css b/tests/outputs_numbered/comments.css
index 6226d416..3669d1d8 100644
--- a/tests/outputs_numbered/comments.css
+++ b/tests/outputs_numbered/comments.css
@@ -31,3 +31,4 @@ a {
/* comment 5 */
/* comment 6 */ }
/* comment 7 */
+/* коммент */
From dbca8da31c3cfd5cfd9c7b2c5a0a74310fc248ae Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Tue, 15 Dec 2015 16:56:25 -0500
Subject: [PATCH 214/534] fixes #395 - bin/pscss: add --iso8859-1 option;
defaults to utf-8 (slower but more compatible with ruby scss)
---
bin/pscss | 11 +++++++++++
src/Compiler.php | 15 ++++++++++++++-
src/Parser.php | 24 ++++++++++++++++++------
3 files changed, 43 insertions(+), 7 deletions(-)
diff --git a/bin/pscss b/bin/pscss
index 16a12039..3175ea0b 100755
--- a/bin/pscss
+++ b/bin/pscss
@@ -31,6 +31,7 @@ $changeDir = false;
$debugInfo = false;
$lineNumbers = false;
$ignoreErrors = false;
+$encoding = false;
/**
* Parse argument
@@ -73,6 +74,7 @@ Options include:
--debug-info Annotate selectors with CSS referring to the source file and line number
-f=format Set the output format (compact, compressed, crunched, expanded, or nested)
-i=path Set import path
+ --iso8859-1 Use iso8859-1 encoding instead of utf-8 (default utf-8)
--line-numbers Annotate selectors with comments referring to the source file and line number
-p=precision Set decimal number precision (default 5)
-T Dump formatted parse tree
@@ -96,6 +98,11 @@ EOT;
continue;
}
+ if ($argv[$i] === '--iso8859-1') {
+ $encoding = 'iso8859-1';
+ continue;
+ }
+
if ($argv[$i] === '--line-numbers' || $argv[$i] === '--line-comments') {
$lineNumbers = true;
continue;
@@ -186,6 +193,10 @@ if ($style) {
$scss->setFormatter('Leafo\\ScssPhp\\Formatter\\' . ucfirst($style));
}
+if ($encoding) {
+ $scss->setEncoding($encoding);
+}
+
echo $scss->compile($data, $inputFile);
if ($changeDir) {
diff --git a/src/Compiler.php b/src/Compiler.php
index 57ec4d65..f55e1d7c 100644
--- a/src/Compiler.php
+++ b/src/Compiler.php
@@ -117,6 +117,7 @@ class Compiler
'global-variable-shadowing' => false,
);
+ protected $encoding = null;
protected $lineNumberStyle = null;
protected $formatter = 'Leafo\ScssPhp\Formatter\Nested';
@@ -208,7 +209,7 @@ public function compile($code, $path = null)
*/
private function parserFactory($path)
{
- $parser = new Parser($path, count($this->sourceNames));
+ $parser = new Parser($path, count($this->sourceNames), $this->encoding);
$this->sourceNames[] = $path;
$this->addParsedFile($path);
@@ -3239,6 +3240,18 @@ public function findImport($url)
return null;
}
+ /**
+ * Set encoding
+ *
+ * @api
+ *
+ * @param string $encoding
+ */
+ public function setEncoding($encoding)
+ {
+ $this->encoding = $encoding;
+ }
+
/**
* Ignore errors?
*
diff --git a/src/Parser.php b/src/Parser.php
index a0986136..ac542dc4 100644
--- a/src/Parser.php
+++ b/src/Parser.php
@@ -62,6 +62,7 @@ class Parser
private $inParens;
private $eatWhiteDefault;
private $buffer;
+ private $utf8;
/**
* Constructor
@@ -70,12 +71,14 @@ class Parser
*
* @param string $sourceName
* @param integer $sourceIndex
+ * @param string $encoding
*/
- public function __construct($sourceName, $sourceIndex = 0)
+ public function __construct($sourceName, $sourceIndex = 0, $encoding = 'utf-8')
{
$this->sourceName = $sourceName ?: '(stdin)';
$this->sourceIndex = $sourceIndex;
$this->charset = null;
+ $this->utf8 = ! $encoding || strtolower($encoding) === 'utf-8';
if (empty(self::$operatorPattern)) {
self::$operatorPattern = '([*\/%+-]|[!=]\=|\>\=?|\<\=\>|\<\=?|and|or)';
@@ -85,7 +88,9 @@ public function __construct($sourceName, $sourceIndex = 0)
$commentMultiRight = '\*\/';
self::$commentPattern = $commentMultiLeft . '.*?' . $commentMultiRight;
- self::$whitePattern = '/' . $commentSingle . '[^\n]*\s*|(' . self::$commentPattern . ')\s*|\s+/AisuS';
+ self::$whitePattern = $this->utf8
+ ? '/' . $commentSingle . '[^\n]*\s*|(' . self::$commentPattern . ')\s*|\s+/AisuS'
+ : '/' . $commentSingle . '[^\n]*\s*|(' . self::$commentPattern . ')\s*|\s+/AisS';
}
}
@@ -762,7 +767,7 @@ protected function peek($regex, &$out, $from = null)
$from = $this->count;
}
- $r = '/' . $regex . '/Aisu';
+ $r = $this->utf8 ? '/' . $regex . '/Aisu' : '/' . $regex . '/Ais';
$result = preg_match($r, $this->buffer, $out, null, $from);
return $result;
@@ -842,7 +847,7 @@ protected function match($regex, &$out, $eatWhitespace = null)
$eatWhitespace = $this->eatWhiteDefault;
}
- $r = '/' . $regex . '/Aisu';
+ $r = $this->utf8 ? '/' . $regex . '/Aisu' : '/' . $regex . '/Ais';
if (preg_match($r, $this->buffer, $out, null, $this->count)) {
$this->count += strlen($out[0]);
@@ -2235,7 +2240,9 @@ protected function variable(&$out)
protected function keyword(&$word, $eatWhitespace = null)
{
if ($this->match(
- '(([\pL\w_\-\*!"\']|[\\\\].)([\pL\w\-_"\']|[\\\\].)*)',
+ $this->utf8
+ ? '(([\pL\w_\-\*!"\']|[\\\\].)([\pL\w\-_"\']|[\\\\].)*)'
+ : '(([\w_\-\*!"\']|[\\\\].)([\w\-_"\']|[\\\\].)*)',
$m,
$eatWhitespace
)) {
@@ -2256,7 +2263,12 @@ protected function keyword(&$word, $eatWhitespace = null)
*/
protected function placeholder(&$placeholder)
{
- if ($this->match('([\pL\w\-_]+|#[{][$][\pL\w\-_]+[}])', $m)) {
+ if ($this->match(
+ $this->utf8
+ ? '([\pL\w\-_]+|#[{][$][\pL\w\-_]+[}])'
+ : '([\w\-_]+|#[{][$][\w\-_]+[}])',
+ $m
+ )) {
$placeholder = $m[1];
return true;
From 361faee948a150d4bb3623a67bb8efb98de2d33d Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Tue, 15 Dec 2015 17:03:18 -0500
Subject: [PATCH 215/534] rename Makefile target (conflict with tests/ folder)
---
Makefile | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Makefile b/Makefile
index d08ee190..b42e4a2b 100644
--- a/Makefile
+++ b/Makefile
@@ -1,4 +1,4 @@
-tests:
+test:
vendor/bin/phpunit --colors tests
compat:
From b948673438b95e4bbf3fc55d3c1fec2d6f1cd8f4 Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Wed, 16 Dec 2015 00:09:30 -0500
Subject: [PATCH 216/534] change die() to throw exception instead
---
scss.inc.php | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/scss.inc.php b/scss.inc.php
index d3720eb7..b6892fec 100644
--- a/scss.inc.php
+++ b/scss.inc.php
@@ -1,6 +1,6 @@
Date: Wed, 16 Dec 2015 00:41:13 -0500
Subject: [PATCH 217/534] fixes #394 - parser exception with
mbstring.func_overload=2 and mbstring.internal_encoding=utf-8
---
src/Parser.php | 44 +++++++++++++++++++++++++++++++++++++++++---
1 file changed, 41 insertions(+), 3 deletions(-)
diff --git a/src/Parser.php b/src/Parser.php
index ac542dc4..68f205ae 100644
--- a/src/Parser.php
+++ b/src/Parser.php
@@ -63,6 +63,7 @@ class Parser
private $eatWhiteDefault;
private $buffer;
private $utf8;
+ private $encoding;
/**
* Constructor
@@ -119,7 +120,7 @@ public function throwParseError($msg = 'parse error')
{
list($line, $column) = $this->getSourcePosition($this->count);
- $loc = empty($this->sourceName) ? "line: $line" : "$this->sourceName on line $line";
+ $loc = empty($this->sourceName) ? "line: $line" : "$this->sourceName on line $line";
if ($this->peek("(.*?)(\n|$)", $m, $this->count)) {
throw new ParserException("$msg: failed at `$m[1]` $loc");
@@ -145,6 +146,7 @@ public function parse($buffer)
$this->eatWhiteDefault = true;
$this->buffer = rtrim($buffer, "\x00..\x1f");
+ $this->saveEncoding();
$this->extractLineNumbers($buffer);
$this->pushBlock(null); // root block
@@ -170,6 +172,8 @@ public function parse($buffer)
$this->env->isRoot = true;
+ $this->restoreEncoding();
+
return $this->env;
}
@@ -191,7 +195,13 @@ public function parseValue($buffer, &$out)
$this->eatWhiteDefault = true;
$this->buffer = (string) $buffer;
- return $this->valueList($out);
+ $this->saveEncoding();
+
+ $list = $this->valueList($out);
+
+ $this->restoreEncoding();
+
+ return $list;
}
/**
@@ -212,7 +222,13 @@ public function parseSelector($buffer, &$out)
$this->eatWhiteDefault = true;
$this->buffer = (string) $buffer;
- return $this->selectors($out);
+ $this->saveEncoding();
+
+ $selector = $this->selectors($out);
+
+ $this->restoreEncoding();
+
+ return $selector;
}
/**
@@ -2485,4 +2501,26 @@ private function getSourcePosition($pos)
return array($low + 1, $pos - $this->sourcePositions[$low]);
}
+
+ /**
+ * Save internal encoding
+ */
+ private function saveEncoding()
+ {
+ if (ini_get('mbstring.func_overload') & 2) {
+ $this->encoding = mb_internal_encoding();
+
+ mb_internal_encoding('iso-8859-1');
+ }
+ }
+
+ /**
+ * Restore internal encoding
+ */
+ private function restoreEncoding()
+ {
+ if ($this->encoding) {
+ mb_internal_encoding($this->encoding);
+ }
+ }
}
From e7fa252c35a24d5a1beb418fc0f2360848edc812 Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Wed, 16 Dec 2015 00:58:24 -0500
Subject: [PATCH 218/534] optimze attribute selector code
---
src/Parser.php | 63 +++++++++++---------------------------------------
1 file changed, 13 insertions(+), 50 deletions(-)
diff --git a/src/Parser.php b/src/Parser.php
index 68f205ae..5b72dafb 100644
--- a/src/Parser.php
+++ b/src/Parser.php
@@ -1461,7 +1461,7 @@ protected function func(&$func)
$this->seek($ss);
}
- if (($this->openString(')', $str, '(') || true ) &&
+ if (($this->openString(')', $str, '(') || true) &&
$this->literal(')')
) {
$args = array();
@@ -2135,7 +2135,7 @@ protected function selectorSingle(&$out)
$ss = $this->seek();
if ($this->literal('(') &&
- ($this->openString(')', $str, '(') || true ) &&
+ ($this->openString(')', $str, '(') || true) &&
$this->literal(')')
) {
$parts[] = '(';
@@ -2155,60 +2155,23 @@ protected function selectorSingle(&$out)
$this->seek($s);
// attribute selector
- // TODO: replace with open string?
- if ($this->literal('[', false)) {
- $attrParts = array('[');
-
- // keyword, string, operator
- for (;;) {
- if ($this->literal(']', false)) {
- $this->count--;
- break; // get out early
- }
-
- if ($this->match('\s+', $m)) {
- $attrParts[] = ' ';
- continue;
- }
-
- if ($this->string($str)) {
- $attrParts[] = $str;
- continue;
- }
-
- if ($this->keyword($word)) {
- $attrParts[] = $word;
- continue;
- }
-
- if ($this->interpolation($inter, false)) {
- $attrParts[] = $inter;
- continue;
- }
-
- // operator, handles attr namespace too
- if ($this->match('[|-~\$\*\^=]+', $m)) {
- $attrParts[] = $m[0];
- continue;
- }
+ if ($this->literal('[') &&
+ ($this->openString(']', $str, '[') || true) &&
+ $this->literal(']')
+ ) {
+ $parts[] = '[';
- break;
+ if (! empty($str)) {
+ $parts[] = $str;
}
- if ($this->literal(']', false)) {
- $attrParts[] = ']';
+ $parts[] = ']';
- foreach ($attrParts as $part) {
- $parts[] = $part;
- }
-
- continue;
- }
-
- $this->seek($s);
- // TODO: should just break here?
+ continue;
}
+ $this->seek($s);
+
break;
}
From 0f52e57cadd1d52a3d4c00ce27fd74f3df638dbc Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Wed, 16 Dec 2015 01:13:15 -0500
Subject: [PATCH 219/534] unused "use"
---
src/Compiler/Environment.php | 2 --
1 file changed, 2 deletions(-)
diff --git a/src/Compiler/Environment.php b/src/Compiler/Environment.php
index e6314cbe..d44bff76 100644
--- a/src/Compiler/Environment.php
+++ b/src/Compiler/Environment.php
@@ -11,8 +11,6 @@
namespace Leafo\ScssPhp\Compiler;
-use Leafo\ScssPhp\Block;
-
/**
* Compiler environment
*
From 7edbcf499498f5376fa82da26a76b34f955b59e6 Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Wed, 16 Dec 2015 01:13:43 -0500
Subject: [PATCH 220/534] add typehint
---
src/Compiler.php | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/Compiler.php b/src/Compiler.php
index f55e1d7c..524a3c41 100644
--- a/src/Compiler.php
+++ b/src/Compiler.php
@@ -863,7 +863,7 @@ protected function compileKeyframeBlock(Block $block, $selectors)
$envs = $this->compactEnv($env);
- $this->env = $this->extractEnv(array_filter($envs, function ($e) {
+ $this->env = $this->extractEnv(array_filter($envs, function (Environment $e) {
return ! isset($e->block->selectors);
}));
From 5951a597fe330179009abbd49afe717c92f1ee5f Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Wed, 16 Dec 2015 01:14:08 -0500
Subject: [PATCH 221/534] unused variables
---
src/Parser.php | 9 +--------
1 file changed, 1 insertion(+), 8 deletions(-)
diff --git a/src/Parser.php b/src/Parser.php
index 5b72dafb..19bd9319 100644
--- a/src/Parser.php
+++ b/src/Parser.php
@@ -631,7 +631,7 @@ protected function parseChunk()
// opening css block
if ($this->selectors($selectors) && $this->literal('{')) {
- $b = $this->pushBlock($selectors, $s);
+ $this->pushBlock($selectors, $s);
return true;
}
@@ -1006,8 +1006,6 @@ protected function mediaQueryList(&$out)
*/
protected function mediaQuery(&$out)
{
- $s = $this->seek();
-
$expressions = null;
$parts = array();
@@ -1496,8 +1494,6 @@ protected function argumentList(&$out)
$args = array();
while ($this->keyword($var)) {
- $ss = $this->seek();
-
if ($this->literal('=') && $this->expression($exp)) {
$args[] = array(Type::T_STRING, '', array($var . '='));
$arg = $exp;
@@ -1765,8 +1761,6 @@ protected function string(&$out)
*/
protected function mixedKeyword(&$out)
{
- $s = $this->seek();
-
$parts = array();
$oldWhite = $this->eatWhiteDefault;
@@ -1918,7 +1912,6 @@ protected function interpolation(&$out, $lookWhite = true)
*/
protected function propertyName(&$out)
{
- $s = $this->seek();
$parts = array();
$oldWhite = $this->eatWhiteDefault;
From fc1b22ca74bae384d36e9a1e771d66153ef22f46 Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Wed, 16 Dec 2015 15:19:58 -0500
Subject: [PATCH 222/534] Remove the compressed patch -- it no longer makes any
difference
---
src/Formatter/Compressed.php | 11 -----------
1 file changed, 11 deletions(-)
diff --git a/src/Formatter/Compressed.php b/src/Formatter/Compressed.php
index 1e27240a..a54b3e3a 100644
--- a/src/Formatter/Compressed.php
+++ b/src/Formatter/Compressed.php
@@ -70,15 +70,4 @@ public function blockLines(OutputBlock $block)
echo $this->break;
}
}
-
- /**
- * {@inherit}
- */
- public function format(OutputBlock $block)
- {
- return parent::format($block);
-
- // TODO: we need to fix the 2 "compressed" tests where the "close" is applied
- return trim(str_replace(';}', '}', parent::format($block)));
- }
}
From 8443d11ad3c54c44a94a28aee2761e649de9bfda Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Wed, 16 Dec 2015 15:21:30 -0500
Subject: [PATCH 223/534] remove orphaned @todo
---
src/Node/Number.php | 1 -
1 file changed, 1 deletion(-)
diff --git a/src/Node/Number.php b/src/Node/Number.php
index 17e856db..6549f495 100644
--- a/src/Node/Number.php
+++ b/src/Node/Number.php
@@ -271,7 +271,6 @@ public function output(Compiler $compiler = null)
return $unitSize;
});
- // @todo refactor normalize()
if (count($units) > 1 && array_sum($units) === 0) {
$dimension = $this->dimension;
$units = array();
From 1a95d89f15ba4cf876b9c6f331c7abe9a0bbf024 Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Wed, 16 Dec 2015 15:26:28 -0500
Subject: [PATCH 224/534] remove unused variable declarations
---
src/Compiler.php | 4 ++--
src/Parser.php | 2 +-
src/Server.php | 7 +++----
3 files changed, 6 insertions(+), 7 deletions(-)
diff --git a/src/Compiler.php b/src/Compiler.php
index 524a3c41..46ba6aa7 100644
--- a/src/Compiler.php
+++ b/src/Compiler.php
@@ -479,7 +479,7 @@ protected function matchExtendsSingle($rawSingle, &$outOrigin)
$found = false;
foreach ($counts as $idx => $count) {
- list($target, $origin, $block) = $this->extends[$idx];
+ list($target, $origin, /* $block */) = $this->extends[$idx];
// check count
if ($count !== count($target)) {
@@ -1766,7 +1766,7 @@ protected function compileChild($child, OutputBlock $out)
*/
protected function expToString($exp)
{
- list(, $op, $left, $right, $inParens, $whiteLeft, $whiteRight) = $exp;
+ list(, $op, $left, $right, /* $inParens */, $whiteLeft, $whiteRight) = $exp;
$content = array($this->reduce($left));
diff --git a/src/Parser.php b/src/Parser.php
index 19bd9319..cd815900 100644
--- a/src/Parser.php
+++ b/src/Parser.php
@@ -118,7 +118,7 @@ public function getSourceName()
*/
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";
diff --git a/src/Server.php b/src/Server.php
index cada00e0..cbbdae15 100644
--- a/src/Server.php
+++ b/src/Server.php
@@ -116,13 +116,12 @@ protected function metadataName($out)
/**
* Determine whether .scss file needs to be re-compiled.
*
- * @param string $in Input path
* @param string $out Output path
* @param string $etag ETag
*
* @return boolean True if compile required.
*/
- protected function needsCompile($in, $out, &$etag)
+ protected function needsCompile($out, &$etag)
{
if (! is_file($out)) {
return true;
@@ -326,7 +325,7 @@ public function serve($salt = '')
$output = $this->cacheName($salt . $input);
$etag = $noneMatch = trim($this->getIfNoneMatchHeader(), '"');
- if ($this->needsCompile($input, $output, $etag)) {
+ if ($this->needsCompile($output, $etag)) {
try {
list($css, $etag) = $this->compile($input, $output);
@@ -408,7 +407,7 @@ public function checkedCachedCompile($in, $out, $force = false)
throw new ServerException('Invalid or unwritable output file specified.');
}
- if ($force || $this->needsCompile($in, $out, $etag)) {
+ if ($force || $this->needsCompile($out, $etag)) {
list($css, $etag) = $this->compile($in, $out);
} else {
$css = file_get_contents($out);
From 1152ca9c27f65da8e31abf26e1dff7d961abbb9d Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Wed, 16 Dec 2015 15:29:01 -0500
Subject: [PATCH 225/534] remove more TODOs
---
src/Compiler.php | 1 -
src/Parser.php | 2 --
2 files changed, 3 deletions(-)
diff --git a/src/Compiler.php b/src/Compiler.php
index 46ba6aa7..ecdb8c97 100644
--- a/src/Compiler.php
+++ b/src/Compiler.php
@@ -4568,7 +4568,6 @@ protected function libLength($args)
return count($list[2]);
}
- // TODO: need a way to declare this built-in as varargs
//protected static $libListSeparator = array('list...');
protected function libListSeparator($args)
{
diff --git a/src/Parser.php b/src/Parser.php
index cd815900..562ea701 100644
--- a/src/Parser.php
+++ b/src/Parser.php
@@ -1878,8 +1878,6 @@ protected function interpolation(&$out, $lookWhite = true)
$s = $this->seek();
if ($this->literal('#{') && $this->valueList($value) && $this->literal('}', false)) {
- // TODO: don't error if out of bounds
-
if ($lookWhite) {
$left = preg_match('/\s/', $this->buffer[$s - 1]) ? ' ' : '';
$right = preg_match('/\s/', $this->buffer[$this->count]) ? ' ': '';
From 4c6e8be425c6cc53c70a641a8cc097ad06727826 Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Wed, 16 Dec 2015 15:34:14 -0500
Subject: [PATCH 226/534] refactoring (for size)
---
src/Formatter/Compressed.php | 30 ++----------------------------
1 file changed, 2 insertions(+), 28 deletions(-)
diff --git a/src/Formatter/Compressed.php b/src/Formatter/Compressed.php
index a54b3e3a..4a2bb41a 100644
--- a/src/Formatter/Compressed.php
+++ b/src/Formatter/Compressed.php
@@ -11,7 +11,7 @@
namespace Leafo\ScssPhp\Formatter;
-use Leafo\ScssPhp\Formatter;
+use Leafo\ScssPhp\Formatter\Crunched;
use Leafo\ScssPhp\Formatter\OutputBlock;
/**
@@ -19,34 +19,8 @@
*
* @author Leaf Corcoran
*/
-class Compressed extends Formatter
+class Compressed extends Crunched
{
- /**
- * {@inheritdoc}
- */
- public function __construct()
- {
- $this->indentLevel = 0;
- $this->indentChar = ' ';
- $this->break = '';
- $this->open = '{';
- $this->close = '}';
- $this->tagSeparator = ',';
- $this->assignSeparator = ':';
- }
-
- /**
- * {@inheritdoc}
- */
- public function stripSemicolon(&$lines)
- {
- if (($count = count($lines))
- && substr($lines[$count - 1], -1) === ';'
- ) {
- $lines[$count - 1] = substr($lines[$count - 1], 0, -1);
- }
- }
-
/**
* {@inheritdoc}
*/
From ca57dd3e57859de6599a2ed4a769591fc5ca0501 Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Wed, 16 Dec 2015 15:53:30 -0500
Subject: [PATCH 227/534] Compiler: refactoring duplicated code
---
src/Compiler.php | 55 +++++++++++++++++++++++-------------------------
1 file changed, 26 insertions(+), 29 deletions(-)
diff --git a/src/Compiler.php b/src/Compiler.php
index ecdb8c97..93c581ba 100644
--- a/src/Compiler.php
+++ b/src/Compiler.php
@@ -697,23 +697,10 @@ private function spliceTree($envs, Block $block, $without)
}
if (isset($e->block->type) && $e->block->type === Type::T_AT_ROOT) {
- continue;
- }
-
- if (($without & self::WITH_RULE) && isset($e->block->selectors)) {
- continue;
+ continue;
}
- if (($without & self::WITH_MEDIA) &&
- isset($e->block->type) && $e->block->type === Type::T_MEDIA
- ) {
- continue;
- }
-
- if (($without & self::WITH_SUPPORTS) &&
- isset($e->block->type) && $e->block->type === Type::T_DIRECTIVE &&
- isset($e->block->name) && $e->block->name === 'supports'
- ) {
+ if ($this->isWithout($without, $e->block)) {
continue;
}
@@ -828,20 +815,7 @@ private function filterWithout($envs, $without)
$filtered = array();
foreach ($envs as $e) {
- if (($without & self::WITH_RULE) && isset($e->block->selectors)) {
- continue;
- }
-
- if (($without & self::WITH_MEDIA) &&
- isset($e->block->type) && $e->block->type === Type::T_MEDIA
- ) {
- continue;
- }
-
- if (($without & self::WITH_SUPPORTS) &&
- isset($e->block->type) && $e->block->type === Type::T_DIRECTIVE &&
- isset($e->block->name) && $e->block->name === 'supports'
- ) {
+ if ($this->isWithout($without, $e->block)) {
continue;
}
@@ -851,6 +825,29 @@ private function filterWithout($envs, $without)
return $this->extractEnv($filtered);
}
+ /**
+ * Filter WITH rules
+ *
+ * @param integer $without
+ * @param \stdClass $block
+ *
+ * @return boolean
+ */
+ private function isWithout($without, $block)
+ {
+ if ((($without & self::WITH_RULE) && isset($block->selectors)) ||
+ (($without & self::WITH_MEDIA) &&
+ isset($block->type) && $block->type === Type::T_MEDIA) ||
+ (($without & self::WITH_SUPPORTS) &&
+ isset($block->type) && $block->type === Type::T_DIRECTIVE &&
+ isset($block->name) && $block->name === 'supports')
+ ) {
+ return true;
+ }
+
+ return false;
+ }
+
/**
* Compile keyframe block
*
From 2996d07d16d53b2e6fe222b20a67e3322bbec43a Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Wed, 16 Dec 2015 15:57:07 -0500
Subject: [PATCH 228/534] Server: remove @ operator on date functions
---
src/Server.php | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/src/Server.php b/src/Server.php
index cbbdae15..e34ff5c3 100644
--- a/src/Server.php
+++ b/src/Server.php
@@ -207,7 +207,7 @@ protected function compile($in, $out)
$elapsed = round((microtime(true) - $start), 4);
$v = Version::VERSION;
- $t = @date('r');
+ $t = date('r');
$css = "/* compiled by scssphp $v on $t (${elapsed}s) */\n\n" . $css;
$etag = md5($css);
@@ -365,7 +365,7 @@ public function serve($salt = '')
$modifiedSince = $this->getIfModifiedSinceHeader();
$mtime = filemtime($output);
- if (@strtotime($modifiedSince) === $mtime) {
+ if (strtotime($modifiedSince) === $mtime) {
header($protocol . ' 304 Not Modified');
return;
@@ -444,6 +444,10 @@ public function __construct($dir, $cacheDir = null, $scss = null)
$this->scss = $scss;
$this->showErrorsAsCSS = false;
+
+ if (! ini_get('date.timezone')) {
+ date_default_timezone_set('UTC');
+ }
}
/**
From 2e1f5bd062faa2c7cf23519d6d171287663bae59 Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Wed, 16 Dec 2015 16:03:40 -0500
Subject: [PATCH 229/534] Compiler: add typehint to isWithout()
---
src/Compiler.php | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/src/Compiler.php b/src/Compiler.php
index 93c581ba..04c1af01 100644
--- a/src/Compiler.php
+++ b/src/Compiler.php
@@ -700,7 +700,7 @@ private function spliceTree($envs, Block $block, $without)
continue;
}
- if ($this->isWithout($without, $e->block)) {
+ if ($e->block && $this->isWithout($without, $e->block)) {
continue;
}
@@ -815,7 +815,7 @@ private function filterWithout($envs, $without)
$filtered = array();
foreach ($envs as $e) {
- if ($this->isWithout($without, $e->block)) {
+ if ($e->block && $this->isWithout($without, $e->block)) {
continue;
}
@@ -828,12 +828,12 @@ private function filterWithout($envs, $without)
/**
* Filter WITH rules
*
- * @param integer $without
- * @param \stdClass $block
+ * @param integer $without
+ * @param \Leafo\ScssPhp\Block $block
*
* @return boolean
*/
- private function isWithout($without, $block)
+ private function isWithout($without, Block $block)
{
if ((($without & self::WITH_RULE) && isset($block->selectors)) ||
(($without & self::WITH_MEDIA) &&
From 9177e859a01ca1395fbede153d1eb93ab86645d4 Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Wed, 16 Dec 2015 16:22:06 -0500
Subject: [PATCH 230/534] composition via trait
---
scss.inc.php | 1 +
src/Formatter/Compressed.php | 6 ++--
src/Formatter/Crunched.php | 26 +----------------
src/Formatter/StripSemiColons.php | 46 +++++++++++++++++++++++++++++++
4 files changed, 52 insertions(+), 27 deletions(-)
create mode 100644 src/Formatter/StripSemiColons.php
diff --git a/scss.inc.php b/scss.inc.php
index b6892fec..ddfd1297 100644
--- a/scss.inc.php
+++ b/scss.inc.php
@@ -20,6 +20,7 @@
include_once __DIR__ . '/src/Formatter/Expanded.php';
include_once __DIR__ . '/src/Formatter/Nested.php';
include_once __DIR__ . '/src/Formatter/OutputBlock.php';
+ include_once __DIR__ . '/src/Formatter/StripSemiColons.php';
include_once __DIR__ . '/src/Node.php';
include_once __DIR__ . '/src/Node/Number.php';
include_once __DIR__ . '/src/Parser.php';
diff --git a/src/Formatter/Compressed.php b/src/Formatter/Compressed.php
index 4a2bb41a..af55da02 100644
--- a/src/Formatter/Compressed.php
+++ b/src/Formatter/Compressed.php
@@ -11,7 +11,7 @@
namespace Leafo\ScssPhp\Formatter;
-use Leafo\ScssPhp\Formatter\Crunched;
+use Leafo\ScssPhp\Formatter;
use Leafo\ScssPhp\Formatter\OutputBlock;
/**
@@ -19,8 +19,10 @@
*
* @author Leaf Corcoran
*/
-class Compressed extends Crunched
+class Compressed extends Formatter
{
+ use StripSemiColons;
+
/**
* {@inheritdoc}
*/
diff --git a/src/Formatter/Crunched.php b/src/Formatter/Crunched.php
index 5e80a824..c31cac56 100644
--- a/src/Formatter/Crunched.php
+++ b/src/Formatter/Crunched.php
@@ -21,31 +21,7 @@
*/
class Crunched extends Formatter
{
- /**
- * {@inheritdoc}
- */
- public function __construct()
- {
- $this->indentLevel = 0;
- $this->indentChar = ' ';
- $this->break = '';
- $this->open = '{';
- $this->close = '}';
- $this->tagSeparator = ',';
- $this->assignSeparator = ':';
- }
-
- /**
- * {@inheritdoc}
- */
- public function stripSemicolon(&$lines)
- {
- if (($count = count($lines))
- && substr($lines[$count - 1], -1) === ';'
- ) {
- $lines[$count - 1] = substr($lines[$count - 1], 0, -1);
- }
- }
+ use StripSemiColons;
/**
* {@inheritdoc}
diff --git a/src/Formatter/StripSemiColons.php b/src/Formatter/StripSemiColons.php
new file mode 100644
index 00000000..8e42c16e
--- /dev/null
+++ b/src/Formatter/StripSemiColons.php
@@ -0,0 +1,46 @@
+
+ */
+trait StripSemiColons
+{
+ /**
+ * {@inheritdoc}
+ */
+ public function __construct()
+ {
+ $this->indentLevel = 0;
+ $this->indentChar = ' ';
+ $this->break = '';
+ $this->open = '{';
+ $this->close = '}';
+ $this->tagSeparator = ',';
+ $this->assignSeparator = ':';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function stripSemicolon(&$lines)
+ {
+ if (($count = count($lines))
+ && substr($lines[$count - 1], -1) === ';'
+ ) {
+ $lines[$count - 1] = substr($lines[$count - 1], 0, -1);
+ }
+ }
+}
From 183412ca18111b2484bca0f2327df6ee8af97945 Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Wed, 16 Dec 2015 16:22:20 -0500
Subject: [PATCH 231/534] errant tabs
---
src/Compiler.php | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/Compiler.php b/src/Compiler.php
index 04c1af01..3039a704 100644
--- a/src/Compiler.php
+++ b/src/Compiler.php
@@ -697,7 +697,7 @@ private function spliceTree($envs, Block $block, $without)
}
if (isset($e->block->type) && $e->block->type === Type::T_AT_ROOT) {
- continue;
+ continue;
}
if ($e->block && $this->isWithout($without, $e->block)) {
From 7f2ae8d1a8d324052460be2061143a3663f1f479 Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Wed, 16 Dec 2015 17:18:28 -0500
Subject: [PATCH 232/534] Update codesniffer to 2.5.0
---
composer.json | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/composer.json b/composer.json
index 691a68a2..112a6bde 100644
--- a/composer.json
+++ b/composer.json
@@ -24,7 +24,7 @@
"php": ">=5.4.0"
},
"require-dev": {
- "squizlabs/php_codesniffer": "~2.3",
+ "squizlabs/php_codesniffer": "~2.5",
"phpunit/phpunit": "~3.7",
"kherge/box": "~2.5"
},
From 69e49077ed9d4c16d2bfd2b74cb6b9b6d00dcd3d Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Wed, 16 Dec 2015 17:19:22 -0500
Subject: [PATCH 233/534] php5.4: Use shorthand array() syntax
---
src/Colors.php | 4 +-
src/Compiler.php | 498 +++++++++++++++++++--------------------
src/Formatter/Nested.php | 2 +-
src/Node/Number.php | 38 +--
src/Parser.php | 181 +++++++-------
src/Server.php | 10 +-
6 files changed, 366 insertions(+), 367 deletions(-)
diff --git a/src/Colors.php b/src/Colors.php
index e3936a5f..ff48c199 100644
--- a/src/Colors.php
+++ b/src/Colors.php
@@ -25,7 +25,7 @@ class Colors
*
* @var array
*/
- public static $cssColors = array(
+ public static $cssColors = [
'aliceblue' => '240,248,255',
'antiquewhite' => '250,235,215',
'aqua' => '0,255,255',
@@ -175,5 +175,5 @@ class Colors
'whitesmoke' => '245,245,245',
'yellow' => '255,255,0',
'yellowgreen' => '154,205,50',
- );
+ ];
}
diff --git a/src/Compiler.php b/src/Compiler.php
index 3039a704..64dfb8b3 100644
--- a/src/Compiler.php
+++ b/src/Compiler.php
@@ -67,7 +67,7 @@ class Compiler
/**
* @var array
*/
- static protected $operatorNames = array(
+ static protected $operatorNames = [
'+' => 'add',
'-' => 'sub',
'*' => 'mul',
@@ -82,40 +82,40 @@ class Compiler
'<=' => 'lte',
'>=' => 'gte',
'<=>' => 'cmp',
- );
+ ];
/**
* @var array
*/
- static protected $namespaces = array(
+ static protected $namespaces = [
'special' => '%',
'mixin' => '@',
'function' => '^',
- );
-
- static public $true = array(Type::T_KEYWORD, 'true');
- static public $false = array(Type::T_KEYWORD, 'false');
- static public $null = array(Type::T_NULL);
- static public $nullString = array(Type::T_STRING, '', array());
- static public $defaultValue = array(Type::T_KEYWORD, '');
- static public $selfSelector = array(Type::T_SELF);
- static public $emptyList = array(Type::T_LIST, '', array());
- static public $emptyMap = array(Type::T_MAP, array(), array());
- static public $emptyString = array(Type::T_STRING, '"', array());
- static public $with = array(Type::T_KEYWORD, 'with');
- static public $without = array(Type::T_KEYWORD, 'without');
-
- protected $importPaths = array('');
- protected $importCache = array();
- protected $importedFiles = array();
- protected $userFunctions = array();
- protected $registeredVars = array();
- protected $registeredFeatures = array(
+ ];
+
+ static public $true = [Type::T_KEYWORD, 'true'];
+ static public $false = [Type::T_KEYWORD, 'false'];
+ static public $null = [Type::T_NULL];
+ static public $nullString = [Type::T_STRING, '', []];
+ static public $defaultValue = [Type::T_KEYWORD, ''];
+ static public $selfSelector = [Type::T_SELF];
+ static public $emptyList = [Type::T_LIST, '', []];
+ static public $emptyMap = [Type::T_MAP, [], []];
+ static public $emptyString = [Type::T_STRING, '"', []];
+ static public $with = [Type::T_KEYWORD, 'with'];
+ static public $without = [Type::T_KEYWORD, 'without'];
+
+ protected $importPaths = [''];
+ protected $importCache = [];
+ protected $importedFiles = [];
+ protected $userFunctions = [];
+ protected $registeredVars = [];
+ protected $registeredFeatures = [
'extend-selector-pseudoclass' => false,
'at-error' => true,
'units-level-3' => false,
'global-variable-shadowing' => false,
- );
+ ];
protected $encoding = null;
protected $lineNumberStyle = null;
@@ -148,8 +148,8 @@ class Compiler
*/
public function __construct()
{
- $this->parsedFiles = array();
- $this->sourceNames = array();
+ $this->parsedFiles = [];
+ $this->sourceNames = [];
}
/**
@@ -168,9 +168,9 @@ public function compile($code, $path = null)
setlocale(LC_NUMERIC, 'C');
$this->indentLevel = -1;
- $this->commentsSeen = array();
- $this->extends = array();
- $this->extendsMap = array();
+ $this->commentsSeen = [];
+ $this->extends = [];
+ $this->extendsMap = [];
$this->sourceIndex = null;
$this->sourceLine = null;
$this->sourceColumn = null;
@@ -250,13 +250,13 @@ protected function pushExtends($target, $origin, $block)
}
$i = count($this->extends);
- $this->extends[] = array($target, $origin, $block);
+ $this->extends[] = [$target, $origin, $block];
foreach ($target as $part) {
if (isset($this->extendsMap[$part])) {
$this->extendsMap[$part][] = $i;
} else {
- $this->extendsMap[$part] = array($i);
+ $this->extendsMap[$part] = [$i];
}
}
}
@@ -273,8 +273,8 @@ protected function makeOutputBlock($type, $selectors = null)
{
$out = new OutputBlock;
$out->type = $type;
- $out->lines = array();
- $out->children = array();
+ $out->lines = [];
+ $out->children = [];
$out->parent = $this->scope;
$out->selectors = $selectors;
$out->depth = $this->env->depth;
@@ -330,7 +330,7 @@ protected function missingSelectors()
protected function flattenSelectors(OutputBlock $block, $parentKey = null)
{
if ($block->selectors) {
- $selectors = array();
+ $selectors = [];
foreach ($block->selectors as $s) {
$selectors[] = $s;
@@ -356,7 +356,7 @@ protected function flattenSelectors(OutputBlock $block, $parentKey = null)
}
}
- $block->selectors = array();
+ $block->selectors = [];
$placeholderSelector = false;
foreach ($selectors as $selector) {
@@ -451,8 +451,8 @@ protected function matchExtends($selector, &$out, $from = 0, $initial = true)
*/
protected function matchExtendsSingle($rawSingle, &$outOrigin)
{
- $counts = array();
- $single = array();
+ $counts = [];
+ $single = [];
foreach ($rawSingle as $part) {
// matches Number
@@ -475,7 +475,7 @@ protected function matchExtendsSingle($rawSingle, &$outOrigin)
}
}
- $outOrigin = array();
+ $outOrigin = [];
$found = false;
foreach ($counts as $idx => $count) {
@@ -522,9 +522,9 @@ protected function matchExtendsSingle($rawSingle, &$outOrigin)
protected function combineSelectorSingle($base, $other)
{
$tag = null;
- $out = array();
+ $out = [];
- foreach (array($base, $other) as $single) {
+ foreach ([$base, $other] as $single) {
foreach ($single as $part) {
if (preg_match('/^[^\[.#:]/', $part)) {
$tag = $part;
@@ -553,7 +553,7 @@ protected function compileMedia(Block $media)
$mediaQuery = $this->compileMediaQuery($this->multiplyMedia($this->env));
if (! empty($mediaQuery)) {
- $this->scope = $this->makeOutputBlock(Type::T_MEDIA, array($mediaQuery));
+ $this->scope = $this->makeOutputBlock(Type::T_MEDIA, [$mediaQuery]);
$parentScope = $this->mediaParent($this->scope);
$parentScope->children[] = $this->scope;
@@ -579,12 +579,12 @@ protected function compileMedia(Block $media)
$wrapped->sourceIndex = $media->sourceIndex;
$wrapped->sourceLine = $media->sourceLine;
$wrapped->sourceColumn = $media->sourceColumn;
- $wrapped->selectors = array();
- $wrapped->comments = array();
+ $wrapped->selectors = [];
+ $wrapped->comments = [];
$wrapped->parent = $media;
$wrapped->children = $media->children;
- $media->children = array(array(Type::T_BLOCK, $wrapped));
+ $media->children = [[Type::T_BLOCK, $wrapped]];
}
$this->compileChildrenNoReturn($media->children, $this->scope);
@@ -629,9 +629,9 @@ protected function compileDirective(Block $block)
}
if ($block->name === 'keyframes' || substr($block->name, -10) === '-keyframes') {
- $this->compileKeyframeBlock($block, array($s));
+ $this->compileKeyframeBlock($block, [$s]);
} else {
- $this->compileNestedBlock($block, array($s));
+ $this->compileNestedBlock($block, [$s]);
}
}
@@ -653,11 +653,11 @@ protected function compileAtRoot(Block $block)
$wrapped->sourceLine = $block->sourceLine;
$wrapped->sourceColumn = $block->sourceColumn;
$wrapped->selectors = $block->selector;
- $wrapped->comments = array();
+ $wrapped->comments = [];
$wrapped->parent = $block;
$wrapped->children = $block->children;
- $block->children = array(array(Type::T_BLOCK, $wrapped));
+ $block->children = [[Type::T_BLOCK, $wrapped]];
}
$this->env = $this->filterWithout($envs, $without);
@@ -708,14 +708,14 @@ private function spliceTree($envs, Block $block, $without)
$b->sourceIndex = $e->block->sourceIndex;
$b->sourceLine = $e->block->sourceLine;
$b->sourceColumn = $e->block->sourceColumn;
- $b->selectors = array();
+ $b->selectors = [];
$b->comments = $e->block->comments;
$b->parent = null;
if ($newBlock) {
$type = isset($newBlock->type) ? $newBlock->type : Type::T_BLOCK;
- $b->children = array(array($type, $newBlock));
+ $b->children = [[$type, $newBlock]];
$newBlock->parent = $b;
} elseif (count($block->children)) {
@@ -749,7 +749,7 @@ private function spliceTree($envs, Block $block, $without)
$type = isset($newBlock->type) ? $newBlock->type : Type::T_BLOCK;
- return array($type, $newBlock);
+ return [$type, $newBlock];
}
/**
@@ -761,20 +761,20 @@ private function spliceTree($envs, Block $block, $without)
*/
private function compileWith($with)
{
- static $mapping = array(
+ static $mapping = [
'rule' => self::WITH_RULE,
'media' => self::WITH_MEDIA,
'supports' => self::WITH_SUPPORTS,
'all' => self::WITH_ALL,
- );
+ ];
// exclude selectors by default
$without = self::WITH_RULE;
- if ($this->libMapHasKey(array($with, self::$with))) {
+ if ($this->libMapHasKey([$with, self::$with])) {
$without = self::WITH_ALL;
- $list = $this->coerceList($this->libMapGet(array($with, self::$with)));
+ $list = $this->coerceList($this->libMapGet([$with, self::$with]));
foreach ($list[2] as $item) {
$keyword = $this->compileStringContent($this->coerceString($item));
@@ -785,10 +785,10 @@ private function compileWith($with)
}
}
- if ($this->libMapHasKey(array($with, self::$without))) {
+ if ($this->libMapHasKey([$with, self::$without])) {
$without = 0;
- $list = $this->coerceList($this->libMapGet(array($with, self::$without)));
+ $list = $this->coerceList($this->libMapGet([$with, self::$without]));
foreach ($list[2] as $item) {
$keyword = $this->compileStringContent($this->coerceString($item));
@@ -812,7 +812,7 @@ private function compileWith($with)
*/
private function filterWithout($envs, $without)
{
- $filtered = array();
+ $filtered = [];
foreach ($envs as $e) {
if ($e->block && $this->isWithout($without, $e->block)) {
@@ -978,7 +978,7 @@ protected function evalSelectors($selectors)
{
$this->shouldEvaluate = false;
- $selectors = array_map(array($this, 'evalSelector'), $selectors);
+ $selectors = array_map([$this, 'evalSelector'], $selectors);
// after evaluating interpolates, we might need a second pass
if ($this->shouldEvaluate) {
@@ -986,7 +986,7 @@ protected function evalSelectors($selectors)
$parser = $this->parserFactory(__METHOD__);
if ($parser->parseSelector($buffer, $newSelectors)) {
- $selectors = array_map(array($this, 'evalSelector'), $newSelectors);
+ $selectors = array_map([$this, 'evalSelector'], $newSelectors);
}
}
@@ -1002,7 +1002,7 @@ protected function evalSelectors($selectors)
*/
protected function evalSelector($selector)
{
- return array_map(array($this, 'evalSelectorPart'), $selector);
+ return array_map([$this, 'evalSelectorPart'], $selector);
}
/**
@@ -1042,7 +1042,7 @@ protected function evalSelectorPart($part)
*/
protected function collapseSelectors($selectors)
{
- $parts = array();
+ $parts = [];
foreach ($selectors as $selector) {
$output = '';
@@ -1069,7 +1069,7 @@ function ($value, $key) use (&$output) {
*/
protected function flattenSelectorSingle($single)
{
- $joined = array();
+ $joined = [];
foreach ($single as $part) {
if (empty($joined) ||
@@ -1106,7 +1106,7 @@ protected function compileSelector($selector)
return implode(
' ',
array_map(
- array($this, 'compileSelectorPart'),
+ [$this, 'compileSelectorPart'],
$selector
)
);
@@ -1218,7 +1218,7 @@ protected function compileMediaQuery($queryList)
foreach ($queryList as $query) {
$type = null;
- $parts = array();
+ $parts = [];
foreach ($query as $q) {
switch ($q[0]) {
@@ -1226,14 +1226,14 @@ protected function compileMediaQuery($queryList)
if ($type) {
$type = $this->mergeMediaTypes(
$type,
- array_map(array($this, 'compileValue'), array_slice($q, 1))
+ array_map([$this, 'compileValue'], array_slice($q, 1))
);
if (empty($type)) { // merge failed
return null;
}
} else {
- $type = array_map(array($this, 'compileValue'), array_slice($q, 1));
+ $type = array_map([$this, 'compileValue'], array_slice($q, 1));
}
break;
@@ -1319,10 +1319,10 @@ protected function mergeMediaTypes($type1, $type2)
return null;
}
- return array(
+ return [
$m1 === Type::T_NOT ? $m2 : $m1,
$m1 === Type::T_NOT ? $t2 : $t1,
- );
+ ];
}
if ($m1 === Type::T_NOT && $m2 === Type::T_NOT) {
@@ -1331,7 +1331,7 @@ protected function mergeMediaTypes($type1, $type2)
return null;
}
- return array(Type::T_NOT, $t1);
+ return [Type::T_NOT, $t1];
}
if ($t1 !== $t2) {
@@ -1339,7 +1339,7 @@ protected function mergeMediaTypes($type1, $type2)
}
// t1 == t2, neither m1 nor m2 are "not"
- return array(empty($m1)? $m2 : $m1, $t1);
+ return [empty($m1)? $m2 : $m1, $t1];
}
/**
@@ -1525,7 +1525,7 @@ protected function compileChild($child, OutputBlock $out)
list(, $selectors) = $child;
foreach ($selectors as $sel) {
- $results = $this->evalSelectors(array($sel));
+ $results = $this->evalSelectors([$sel]);
foreach ($results as $result) {
// only use the first one
@@ -1640,10 +1640,10 @@ protected function compileChild($child, OutputBlock $out)
break;
case Type::T_BREAK:
- return array(Type::T_CONTROL, true);
+ return [Type::T_CONTROL, true];
case Type::T_CONTINUE:
- return array(Type::T_CONTROL, false);
+ return [Type::T_CONTROL, false];
case Type::T_RETURN:
return $this->reduce($child[1], true);
@@ -1651,7 +1651,7 @@ protected function compileChild($child, OutputBlock $out)
case Type::T_NESTED_PROPERTY:
list(, $prop) = $child;
- $prefixed = array();
+ $prefixed = [];
$prefix = $this->compileValue($prop->prefix) . '-';
foreach ($prop->children as $child) {
@@ -1765,7 +1765,7 @@ protected function expToString($exp)
{
list(, $op, $left, $right, /* $inParens */, $whiteLeft, $whiteRight) = $exp;
- $content = array($this->reduce($left));
+ $content = [$this->reduce($left)];
if ($whiteLeft) {
$content[] = ' ';
@@ -1779,7 +1779,7 @@ protected function expToString($exp)
$content[] = $this->reduce($right);
- return array(Type::T_STRING, '', $content);
+ return [Type::T_STRING, '', $content];
}
/**
@@ -1867,12 +1867,12 @@ protected function reduce($value, $inExp = false)
// 3. op[op name]
$fn = "op${ucOpName}${ucLType}${ucRType}";
- if (is_callable(array($this, $fn)) ||
+ if (is_callable([$this, $fn]) ||
(($fn = "op${ucLType}${ucRType}") &&
- is_callable(array($this, $fn)) &&
+ is_callable([$this, $fn]) &&
$passOp = true) ||
(($fn = "op${ucOpName}") &&
- is_callable(array($this, $fn)) &&
+ is_callable([$this, $fn]) &&
$genOp = true)
) {
$coerceUnit = false;
@@ -1960,7 +1960,7 @@ protected function reduce($value, $inExp = false)
$op = $op . ' ';
}
- return array(Type::T_STRING, '', array($op, $exp));
+ return [Type::T_STRING, '', [$op, $exp]];
case Type::T_VARIABLE:
list(, $name) = $value;
@@ -2030,7 +2030,7 @@ private function fncall($name, $argValues)
}
// for CSS functions, simply flatten the arguments into a list
- $listArgs = array();
+ $listArgs = [];
foreach ((array) $argValues as $arg) {
if (empty($arg[0])) {
@@ -2038,7 +2038,7 @@ private function fncall($name, $argValues)
}
}
- return array(Type::T_FUNCTION, $name, array(Type::T_LIST, ',', $listArgs));
+ return [Type::T_FUNCTION, $name, [Type::T_LIST, ',', $listArgs]];
}
/**
@@ -2070,7 +2070,7 @@ public function normalizeValue($value)
$value = $this->extractInterpolation($value);
if ($value[0] !== Type::T_LIST) {
- return array(Type::T_KEYWORD, $this->compileValue($value));
+ return [Type::T_KEYWORD, $this->compileValue($value)];
}
foreach ($value[2] as $key => $item) {
@@ -2080,13 +2080,13 @@ public function normalizeValue($value)
return $value;
case Type::T_STRING:
- return array($type, '"', array($this->compileStringContent($value)));
+ return [$type, '"', [$this->compileStringContent($value)]];
case Type::T_NUMBER:
return $value->normalize();
case Type::T_INTERPOLATE:
- return array(Type::T_KEYWORD, $this->compileValue($value));
+ return [Type::T_KEYWORD, $this->compileValue($value)];
default:
return $value;
@@ -2143,7 +2143,7 @@ protected function opSubNumberNumber($left, $right)
protected function opDivNumberNumber($left, $right)
{
if ($right[1] == 0) {
- return array(Type::T_STRING, '', array($left[1] . $left[2] . '/' . $right[1] . $right[2]));
+ return [Type::T_STRING, '', [$left[1] . $left[2] . '/' . $right[1] . $right[2]]];
}
return new Node\Number($left[1] / $right[1], $left[2]);
@@ -2248,9 +2248,9 @@ protected function opOr($left, $right, $shouldEval)
*/
protected function opColorColor($op, $left, $right)
{
- $out = array(Type::T_COLOR);
+ $out = [Type::T_COLOR];
- foreach (array(1, 2, 3) as $i) {
+ foreach ([1, 2, 3] as $i) {
$lval = isset($left[$i]) ? $left[$i] : 0;
$rval = isset($right[$i]) ? $right[$i] : 0;
@@ -2317,7 +2317,7 @@ protected function opColorNumber($op, $left, $right)
return $this->opColorColor(
$op,
$left,
- array(Type::T_COLOR, $value, $value, $value)
+ [Type::T_COLOR, $value, $value, $value]
);
}
@@ -2336,7 +2336,7 @@ protected function opNumberColor($op, $left, $right)
return $this->opColorColor(
$op,
- array(Type::T_COLOR, $value, $value, $value),
+ [Type::T_COLOR, $value, $value, $value],
$right
);
}
@@ -2539,7 +2539,7 @@ public function compileValue($value)
$delim .= ' ';
}
- $filtered = array();
+ $filtered = [];
foreach ($items as $item) {
if ($item[0] === Type::T_NULL) {
@@ -2554,7 +2554,7 @@ public function compileValue($value)
case Type::T_MAP:
$keys = $value[1];
$values = $value[2];
- $filtered = array();
+ $filtered = [];
for ($i = 0, $s = count($keys); $i < $s; $i++) {
$filtered[$this->compileValue($keys[$i])] = $this->compileValue($values[$i]);
@@ -2588,11 +2588,11 @@ public function compileValue($value)
switch ($reduced[0]) {
case Type::T_STRING:
- $reduced = array(Type::T_KEYWORD, $this->compileStringContent($reduced));
+ $reduced = [Type::T_KEYWORD, $this->compileStringContent($reduced)];
break;
case Type::T_NULL:
- $reduced = array(Type::T_KEYWORD, '');
+ $reduced = [Type::T_KEYWORD, ''];
}
return $this->compileValue($reduced);
@@ -2626,7 +2626,7 @@ protected function flattenList($list)
*/
protected function compileStringContent($string)
{
- $parts = array();
+ $parts = [];
foreach ($string[2] as $part) {
if (is_array($part) || $part instanceof \ArrayAccess) {
@@ -2652,10 +2652,10 @@ protected function extractInterpolation($list)
foreach ($items as $i => $item) {
if ($item[0] === Type::T_INTERPOLATE) {
- $before = array(Type::T_LIST, $list[1], array_slice($items, 0, $i));
- $after = array(Type::T_LIST, $list[1], array_slice($items, $i + 1));
+ $before = [Type::T_LIST, $list[1], array_slice($items, 0, $i)];
+ $after = [Type::T_LIST, $list[1], array_slice($items, $i + 1)];
- return array(Type::T_INTERPOLATED, $item, $before, $after);
+ return [Type::T_INTERPOLATED, $item, $before, $after];
}
}
@@ -2672,15 +2672,15 @@ protected function extractInterpolation($list)
protected function multiplySelectors(Environment $env)
{
$envs = $this->compactEnv($env);
- $selectors = array();
- $parentSelectors = array(array());
+ $selectors = [];
+ $parentSelectors = [[]];
while ($env = array_pop($envs)) {
if (empty($env->selectors)) {
continue;
}
- $selectors = array();
+ $selectors = [];
foreach ($env->selectors as $selector) {
foreach ($parentSelectors as $parent) {
@@ -2705,10 +2705,10 @@ protected function multiplySelectors(Environment $env)
protected function joinSelectors($parent, $child)
{
$setSelf = false;
- $out = array();
+ $out = [];
foreach ($child as $part) {
- $newPart = array();
+ $newPart = [];
foreach ($part as $p) {
if ($p === self::$selfSelector) {
@@ -2717,7 +2717,7 @@ protected function joinSelectors($parent, $child)
foreach ($parent as $i => $parentPart) {
if ($i > 0) {
$out[] = $newPart;
- $newPart = array();
+ $newPart = [];
}
foreach ($parentPart as $pp) {
@@ -2758,13 +2758,13 @@ protected function multiplyMedia(Environment $env = null, $childQueries = null)
$parentQueries = isset($env->block->queryList)
? $env->block->queryList
- : array(array(array(Type::T_MEDIA_VALUE, $env->block->value)));
+ : [[[Type::T_MEDIA_VALUE, $env->block->value]]];
if ($childQueries === null) {
$childQueries = $parentQueries;
} else {
$originalQueries = $childQueries;
- $childQueries = array();
+ $childQueries = [];
foreach ($parentQueries as $parentQuery) {
foreach ($originalQueries as $childQuery) {
@@ -2785,7 +2785,7 @@ protected function multiplyMedia(Environment $env = null, $childQueries = null)
*/
private function compactEnv(Environment $env)
{
- for ($envs = array(); $env; $env = $env->parent) {
+ for ($envs = []; $env; $env = $env->parent) {
$envs[] = $env;
}
@@ -2820,7 +2820,7 @@ protected function pushEnv(Block $block = null)
{
$env = new Environment;
$env->parent = $this->env;
- $env->store = array();
+ $env->store = [];
$env->block = $block;
$env->depth = isset($this->env->depth) ? $this->env->depth + 1 : 0;
@@ -3135,7 +3135,7 @@ public function setLineNumberStyle($lineNumberStyle)
*/
public function registerFunction($name, $func, $prototype = null)
{
- $this->userFunctions[$this->normalizeName($name)] = array($func, $prototype);
+ $this->userFunctions[$this->normalizeName($name)] = [$func, $prototype];
}
/**
@@ -3202,12 +3202,12 @@ protected function importFile($path, $out)
*/
public function findImport($url)
{
- $urls = array();
+ $urls = [];
// for "normal" scss imports (ignore vanilla css and external requests)
if (! preg_match('/\.css$|^https?:\/\//', $url)) {
// try both normal and the _partial filename
- $urls = array($url, preg_replace('/[^\/]+$/', '_\0', $url));
+ $urls = [$url, preg_replace('/[^\/]+$/', '_\0', $url)];
}
foreach ($this->importPaths as $dir) {
@@ -3345,8 +3345,8 @@ protected function callScssFunction($name, $argValues, &$returnValue)
// throw away lines and children
$tmp = new OutputBlock;
- $tmp->lines = array();
- $tmp->children = array();
+ $tmp->lines = [];
+ $tmp->children = [];
$this->env->marker = 'function';
@@ -3419,7 +3419,7 @@ function ($m) {
ucfirst($name)
);
- return array($this, $libName);
+ return [$this, $libName];
}
/**
@@ -3432,8 +3432,8 @@ function ($m) {
*/
protected function sortArgs($prototype, $args)
{
- $keyArgs = array();
- $posArgs = array();
+ $keyArgs = [];
+ $posArgs = [];
// separate positional and keyword arguments
foreach ($args as $arg) {
@@ -3449,7 +3449,7 @@ protected function sortArgs($prototype, $args)
}
if (! isset($prototype)) {
- return array($posArgs, $keyArgs);
+ return [$posArgs, $keyArgs];
}
// copy positional args
@@ -3464,7 +3464,7 @@ protected function sortArgs($prototype, $args)
}
}
- return array($finalArgs, $keyArgs);
+ return [$finalArgs, $keyArgs];
}
/**
@@ -3483,18 +3483,18 @@ protected function applyArguments($argDef, $argValues)
$env->store = $storeEnv->store;
$hasVariable = false;
- $args = array();
+ $args = [];
foreach ($argDef as $i => $arg) {
list($name, $default, $isVariable) = $argDef[$i];
- $args[$name] = array($i, $name, $default, $isVariable);
+ $args[$name] = [$i, $name, $default, $isVariable];
$hasVariable |= $isVariable;
}
- $keywordArgs = array();
- $deferredKeywordArgs = array();
- $remaining = array();
+ $keywordArgs = [];
+ $deferredKeywordArgs = [];
+ $remaining = [];
// assign the keyword args
foreach ((array) $argValues as $arg) {
@@ -3549,7 +3549,7 @@ protected function applyArguments($argDef, $argValues)
list($i, $name, $default, $isVariable) = $arg;
if ($isVariable) {
- $val = array(Type::T_LIST, ',', array(), $isVariable);
+ $val = [Type::T_LIST, ',', [], $isVariable];
for ($count = count($remaining); $i < $count; $i++) {
$val[2][] = $remaining[$i];
@@ -3614,7 +3614,7 @@ private function coerceValue($value)
return self::$emptyString;
}
- return array(Type::T_KEYWORD, $value);
+ return [Type::T_KEYWORD, $value];
}
/**
@@ -3634,7 +3634,7 @@ protected function coerceMap($item)
return self::$emptyMap;
}
- return array(Type::T_MAP, array($item), array(self::$null));
+ return [Type::T_MAP, [$item], [self::$null]];
}
/**
@@ -3653,23 +3653,23 @@ protected function coerceList($item, $delim = ',')
if (isset($item) && $item[0] === Type::T_MAP) {
$keys = $item[1];
$values = $item[2];
- $list = array();
+ $list = [];
for ($i = 0, $s = count($keys); $i < $s; $i++) {
$key = $keys[$i];
$value = $values[$i];
- $list[] = array(
+ $list[] = [
Type::T_LIST,
'',
- array(array(Type::T_KEYWORD, $this->compileStringContent($this->coerceString($key))), $value)
- );
+ [[Type::T_KEYWORD, $this->compileStringContent($this->coerceString($key))], $value]
+ ];
}
- return array(Type::T_LIST, ',', $list);
+ return [Type::T_LIST, ',', $list];
}
- return array(Type::T_LIST, $delim, ! isset($item) ? array(): array($item));
+ return [Type::T_LIST, $delim, ! isset($item) ? []: [$item]];
}
/**
@@ -3708,8 +3708,8 @@ protected function coerceColor($value)
$rgba = explode(',', Colors::$cssColors[$name]);
return isset($rgba[3])
- ? array(Type::T_COLOR, (int) $rgba[0], (int) $rgba[1], (int) $rgba[2], (int) $rgba[3])
- : array(Type::T_COLOR, (int) $rgba[0], (int) $rgba[1], (int) $rgba[2]);
+ ? [Type::T_COLOR, (int) $rgba[0], (int) $rgba[1], (int) $rgba[2], (int) $rgba[3]]
+ : [Type::T_COLOR, (int) $rgba[0], (int) $rgba[1], (int) $rgba[2]];
}
return null;
@@ -3731,7 +3731,7 @@ protected function coerceString($value)
return $value;
}
- return array(Type::T_STRING, '', array($this->compileValue($value)));
+ return [Type::T_STRING, '', [$this->compileValue($value)]];
}
/**
@@ -3845,7 +3845,7 @@ public function assertNumber($value)
*/
protected function fixColor($c)
{
- foreach (array(1, 2, 3) as $i) {
+ foreach ([1, 2, 3] as $i) {
if ($c[$i] < 0) {
$c[$i] = 0;
}
@@ -3895,7 +3895,7 @@ public function toHSL($red, $green, $blue)
}
}
- return array(Type::T_HSL, fmod($h, 360), $s * 100, $l / 5.1);
+ return [Type::T_HSL, fmod($h, 360), $s * 100, $l / 5.1];
}
/**
@@ -3958,35 +3958,35 @@ public function toRGB($hue, $saturation, $lightness)
$g = $this->hueToRGB($m1, $m2, $h) * 255;
$b = $this->hueToRGB($m1, $m2, $h - 1/3) * 255;
- $out = array(Type::T_COLOR, $r, $g, $b);
+ $out = [Type::T_COLOR, $r, $g, $b];
return $out;
}
// Built in functions
- //protected static $libCall = array('name', 'args...');
+ //protected static $libCall = ['name', 'args...'];
protected function libCall($args, $kwargs)
{
$name = $this->compileStringContent($this->coerceString($this->reduce(array_shift($args), true)));
$args = array_map(
function ($a) {
- return array(null, $a, false);
+ return [null, $a, false];
},
$args
);
if (count($kwargs)) {
foreach ($kwargs as $key => $value) {
- $args[] = array(array(Type::T_VARIABLE, $key), $value, false);
+ $args[] = [[Type::T_VARIABLE, $key], $value, false];
}
}
- return $this->reduce(array(Type::T_FUNCTION_CALL, $name, $args));
+ return $this->reduce([Type::T_FUNCTION_CALL, $name, $args]);
}
- protected static $libIf = array('condition', 'if-true', 'if-false');
+ protected static $libIf = ['condition', 'if-true', 'if-false'];
protected function libIf($args)
{
list($cond, $t, $f) = $args;
@@ -3998,7 +3998,7 @@ protected function libIf($args)
return $this->reduce($t, true);
}
- protected static $libIndex = array('list', 'value');
+ protected static $libIndex = ['list', 'value'];
protected function libIndex($args)
{
list($list, $value) = $args;
@@ -4019,7 +4019,7 @@ protected function libIndex($args)
return self::$null;
}
- $values = array();
+ $values = [];
foreach ($list[2] as $item) {
$values[] = $this->normalizeValue($item);
@@ -4030,17 +4030,17 @@ protected function libIndex($args)
return false === $key ? self::$null : $key + 1;
}
- protected static $libRgb = array('red', 'green', 'blue');
+ protected static $libRgb = ['red', 'green', 'blue'];
protected function libRgb($args)
{
list($r, $g, $b) = $args;
- return array(Type::T_COLOR, $r[1], $g[1], $b[1]);
+ return [Type::T_COLOR, $r[1], $g[1], $b[1]];
}
- protected static $libRgba = array(
- array('red', 'color'),
- 'green', 'blue', 'alpha');
+ protected static $libRgba = [
+ ['red', 'color'],
+ 'green', 'blue', 'alpha'];
protected function libRgba($args)
{
if ($color = $this->coerceColor($args[0])) {
@@ -4053,7 +4053,7 @@ protected function libRgba($args)
list($r, $g, $b, $a) = $args;
- return array(Type::T_COLOR, $r[1], $g[1], $b[1], $a[1]);
+ return [Type::T_COLOR, $r[1], $g[1], $b[1], $a[1]];
}
// helper function for adjust_color, change_color, and scale_color
@@ -4061,7 +4061,7 @@ protected function alterColor($args, $fn)
{
$color = $this->assertColor($args[0]);
- foreach (array(1, 2, 3, 7) as $i) {
+ foreach ([1, 2, 3, 7] as $i) {
if (isset($args[$i])) {
$val = $this->assertNumber($args[$i]);
$ii = $i === 7 ? 4 : $i; // alpha
@@ -4072,7 +4072,7 @@ protected function alterColor($args, $fn)
if (isset($args[4]) || isset($args[5]) || isset($args[6])) {
$hsl = $this->toHSL($color[1], $color[2], $color[3]);
- foreach (array(4, 5, 6) as $i) {
+ foreach ([4, 5, 6] as $i) {
if (isset($args[$i])) {
$val = $this->assertNumber($args[$i]);
$hsl[$i - 3] = call_user_func($fn, $hsl[$i - 3], $val, $i);
@@ -4091,10 +4091,10 @@ protected function alterColor($args, $fn)
return $color;
}
- protected static $libAdjustColor = array(
+ protected static $libAdjustColor = [
'color', 'red', 'green', 'blue',
'hue', 'saturation', 'lightness', 'alpha'
- );
+ ];
protected function libAdjustColor($args)
{
return $this->alterColor($args, function ($base, $alter, $i) {
@@ -4102,10 +4102,10 @@ protected function libAdjustColor($args)
});
}
- protected static $libChangeColor = array(
+ protected static $libChangeColor = [
'color', 'red', 'green', 'blue',
'hue', 'saturation', 'lightness', 'alpha'
- );
+ ];
protected function libChangeColor($args)
{
return $this->alterColor($args, function ($base, $alter, $i) {
@@ -4113,10 +4113,10 @@ protected function libChangeColor($args)
});
}
- protected static $libScaleColor = array(
+ protected static $libScaleColor = [
'color', 'red', 'green', 'blue',
'hue', 'saturation', 'lightness', 'alpha'
- );
+ ];
protected function libScaleColor($args)
{
return $this->alterColor($args, function ($base, $scale, $i) {
@@ -4152,7 +4152,7 @@ protected function libScaleColor($args)
});
}
- protected static $libIeHexStr = array('color');
+ protected static $libIeHexStr = ['color'];
protected function libIeHexStr($args)
{
$color = $this->coerceColor($args[0]);
@@ -4161,7 +4161,7 @@ protected function libIeHexStr($args)
return sprintf('#%02X%02X%02X%02X', $color[4], $color[1], $color[2], $color[3]);
}
- protected static $libRed = array('color');
+ protected static $libRed = ['color'];
protected function libRed($args)
{
$color = $this->coerceColor($args[0]);
@@ -4169,7 +4169,7 @@ protected function libRed($args)
return $color[1];
}
- protected static $libGreen = array('color');
+ protected static $libGreen = ['color'];
protected function libGreen($args)
{
$color = $this->coerceColor($args[0]);
@@ -4177,7 +4177,7 @@ protected function libGreen($args)
return $color[2];
}
- protected static $libBlue = array('color');
+ protected static $libBlue = ['color'];
protected function libBlue($args)
{
$color = $this->coerceColor($args[0]);
@@ -4185,7 +4185,7 @@ protected function libBlue($args)
return $color[3];
}
- protected static $libAlpha = array('color');
+ protected static $libAlpha = ['color'];
protected function libAlpha($args)
{
if ($color = $this->coerceColor($args[0])) {
@@ -4196,7 +4196,7 @@ protected function libAlpha($args)
return null;
}
- protected static $libOpacity = array('color');
+ protected static $libOpacity = ['color'];
protected function libOpacity($args)
{
$value = $args[0];
@@ -4209,7 +4209,7 @@ protected function libOpacity($args)
}
// mix two colors
- protected static $libMix = array('color-1', 'color-2', 'weight');
+ protected static $libMix = ['color-1', 'color-2', 'weight'];
protected function libMix($args)
{
list($first, $second, $weight) = $args;
@@ -4232,11 +4232,11 @@ protected function libMix($args)
$w1 = (($w * $a === -1 ? $w : ($w + $a) / (1 + $w * $a)) + 1) / 2.0;
$w2 = 1.0 - $w1;
- $new = array(Type::T_COLOR,
+ $new = [Type::T_COLOR,
$w1 * $first[1] + $w2 * $second[1],
$w1 * $first[2] + $w2 * $second[2],
$w1 * $first[3] + $w2 * $second[3],
- );
+ ];
if ($firstAlpha != 1.0 || $secondAlpha != 1.0) {
$new[] = $firstAlpha * $weight + $secondAlpha * ($weight - 1);
@@ -4245,7 +4245,7 @@ protected function libMix($args)
return $this->fixColor($new);
}
- protected static $libHsl = array('hue', 'saturation', 'lightness');
+ protected static $libHsl = ['hue', 'saturation', 'lightness'];
protected function libHsl($args)
{
list($h, $s, $l) = $args;
@@ -4253,7 +4253,7 @@ protected function libHsl($args)
return $this->toRGB($h[1], $s[1], $l[1]);
}
- protected static $libHsla = array('hue', 'saturation', 'lightness', 'alpha');
+ protected static $libHsla = ['hue', 'saturation', 'lightness', 'alpha'];
protected function libHsla($args)
{
list($h, $s, $l, $a) = $args;
@@ -4264,7 +4264,7 @@ protected function libHsla($args)
return $color;
}
- protected static $libHue = array('color');
+ protected static $libHue = ['color'];
protected function libHue($args)
{
$color = $this->assertColor($args[0]);
@@ -4273,7 +4273,7 @@ protected function libHue($args)
return new Node\Number($hsl[1], 'deg');
}
- protected static $libSaturation = array('color');
+ protected static $libSaturation = ['color'];
protected function libSaturation($args)
{
$color = $this->assertColor($args[0]);
@@ -4282,7 +4282,7 @@ protected function libSaturation($args)
return new Node\Number($hsl[2], '%');
}
- protected static $libLightness = array('color');
+ protected static $libLightness = ['color'];
protected function libLightness($args)
{
$color = $this->assertColor($args[0]);
@@ -4304,7 +4304,7 @@ protected function adjustHsl($color, $idx, $amount)
return $out;
}
- protected static $libAdjustHue = array('color', 'degrees');
+ protected static $libAdjustHue = ['color', 'degrees'];
protected function libAdjustHue($args)
{
$color = $this->assertColor($args[0]);
@@ -4313,7 +4313,7 @@ protected function libAdjustHue($args)
return $this->adjustHsl($color, 1, $degrees);
}
- protected static $libLighten = array('color', 'amount');
+ protected static $libLighten = ['color', 'amount'];
protected function libLighten($args)
{
$color = $this->assertColor($args[0]);
@@ -4322,7 +4322,7 @@ protected function libLighten($args)
return $this->adjustHsl($color, 3, $amount);
}
- protected static $libDarken = array('color', 'amount');
+ protected static $libDarken = ['color', 'amount'];
protected function libDarken($args)
{
$color = $this->assertColor($args[0]);
@@ -4331,7 +4331,7 @@ protected function libDarken($args)
return $this->adjustHsl($color, 3, -$amount);
}
- protected static $libSaturate = array('color', 'amount');
+ protected static $libSaturate = ['color', 'amount'];
protected function libSaturate($args)
{
$value = $args[0];
@@ -4346,7 +4346,7 @@ protected function libSaturate($args)
return $this->adjustHsl($color, 2, $amount);
}
- protected static $libDesaturate = array('color', 'amount');
+ protected static $libDesaturate = ['color', 'amount'];
protected function libDesaturate($args)
{
$color = $this->assertColor($args[0]);
@@ -4355,7 +4355,7 @@ protected function libDesaturate($args)
return $this->adjustHsl($color, 2, -$amount);
}
- protected static $libGrayscale = array('color');
+ protected static $libGrayscale = ['color'];
protected function libGrayscale($args)
{
$value = $args[0];
@@ -4367,13 +4367,13 @@ protected function libGrayscale($args)
return $this->adjustHsl($this->assertColor($value), 2, -100);
}
- protected static $libComplement = array('color');
+ protected static $libComplement = ['color'];
protected function libComplement($args)
{
return $this->adjustHsl($this->assertColor($args[0]), 1, 180);
}
- protected static $libInvert = array('color');
+ protected static $libInvert = ['color'];
protected function libInvert($args)
{
$value = $args[0];
@@ -4391,7 +4391,7 @@ protected function libInvert($args)
}
// increases opacity by amount
- protected static $libOpacify = array('color', 'amount');
+ protected static $libOpacify = ['color', 'amount'];
protected function libOpacify($args)
{
$color = $this->assertColor($args[0]);
@@ -4403,14 +4403,14 @@ protected function libOpacify($args)
return $color;
}
- protected static $libFadeIn = array('color', 'amount');
+ protected static $libFadeIn = ['color', 'amount'];
protected function libFadeIn($args)
{
return $this->libOpacify($args);
}
// decreases opacity by amount
- protected static $libTransparentize = array('color', 'amount');
+ protected static $libTransparentize = ['color', 'amount'];
protected function libTransparentize($args)
{
$color = $this->assertColor($args[0]);
@@ -4422,13 +4422,13 @@ protected function libTransparentize($args)
return $color;
}
- protected static $libFadeOut = array('color', 'amount');
+ protected static $libFadeOut = ['color', 'amount'];
protected function libFadeOut($args)
{
return $this->libTransparentize($args);
}
- protected static $libUnquote = array('string');
+ protected static $libUnquote = ['string'];
protected function libUnquote($args)
{
$str = $args[0];
@@ -4440,7 +4440,7 @@ protected function libUnquote($args)
return $str;
}
- protected static $libQuote = array('string');
+ protected static $libQuote = ['string'];
protected function libQuote($args)
{
$value = $args[0];
@@ -4449,16 +4449,16 @@ protected function libQuote($args)
return $value;
}
- return array(Type::T_STRING, '"', array($value));
+ return [Type::T_STRING, '"', [$value]];
}
- protected static $libPercentage = array('value');
+ protected static $libPercentage = ['value'];
protected function libPercentage($args)
{
return new Node\Number($this->coercePercent($args[0]) * 100, '%');
}
- protected static $libRound = array('value');
+ protected static $libRound = ['value'];
protected function libRound($args)
{
$num = $args[0];
@@ -4467,7 +4467,7 @@ protected function libRound($args)
return $num;
}
- protected static $libFloor = array('value');
+ protected static $libFloor = ['value'];
protected function libFloor($args)
{
$num = $args[0];
@@ -4476,7 +4476,7 @@ protected function libFloor($args)
return $num;
}
- protected static $libCeil = array('value');
+ protected static $libCeil = ['value'];
protected function libCeil($args)
{
$num = $args[0];
@@ -4485,7 +4485,7 @@ protected function libCeil($args)
return $num;
}
- protected static $libAbs = array('value');
+ protected static $libAbs = ['value'];
protected function libAbs($args)
{
$num = $args[0];
@@ -4501,7 +4501,7 @@ protected function libMin($args)
foreach ($numbers as $key => $number) {
if (null === $min || $number[1] <= $min[1]) {
- $min = array($key, $number[1]);
+ $min = [$key, $number[1]];
}
}
@@ -4515,7 +4515,7 @@ protected function libMax($args)
foreach ($numbers as $key => $number) {
if (null === $max || $number[1] >= $max[1]) {
- $max = array($key, $number[1]);
+ $max = [$key, $number[1]];
}
}
@@ -4533,7 +4533,7 @@ protected function getNormalizedNumbers($args)
{
$unit = null;
$originalUnit = null;
- $numbers = array();
+ $numbers = [];
foreach ($args as $key => $item) {
if ($item[0] !== Type::T_NUMBER) {
@@ -4557,7 +4557,7 @@ protected function getNormalizedNumbers($args)
return $numbers;
}
- protected static $libLength = array('list');
+ protected static $libLength = ['list'];
protected function libLength($args)
{
$list = $this->coerceList($args[0]);
@@ -4565,7 +4565,7 @@ protected function libLength($args)
return count($list[2]);
}
- //protected static $libListSeparator = array('list...');
+ //protected static $libListSeparator = ['list...'];
protected function libListSeparator($args)
{
if (count($args) > 1) {
@@ -4585,7 +4585,7 @@ protected function libListSeparator($args)
return 'space';
}
- protected static $libNth = array('list', 'n');
+ protected static $libNth = ['list', 'n'];
protected function libNth($args)
{
$list = $this->coerceList($args[0]);
@@ -4600,7 +4600,7 @@ protected function libNth($args)
return isset($list[2][$n]) ? $list[2][$n] : self::$defaultValue;
}
- protected static $libSetNth = array('list', 'n', 'value');
+ protected static $libSetNth = ['list', 'n', 'value'];
protected function libSetNth($args)
{
$list = $this->coerceList($args[0]);
@@ -4623,7 +4623,7 @@ protected function libSetNth($args)
return $list;
}
- protected static $libMapGet = array('map', 'key');
+ protected static $libMapGet = ['map', 'key'];
protected function libMapGet($args)
{
$map = $this->assertMap($args[0]);
@@ -4638,25 +4638,25 @@ protected function libMapGet($args)
return self::$null;
}
- protected static $libMapKeys = array('map');
+ protected static $libMapKeys = ['map'];
protected function libMapKeys($args)
{
$map = $this->assertMap($args[0]);
$keys = $map[1];
- return array(Type::T_LIST, ',', $keys);
+ return [Type::T_LIST, ',', $keys];
}
- protected static $libMapValues = array('map');
+ protected static $libMapValues = ['map'];
protected function libMapValues($args)
{
$map = $this->assertMap($args[0]);
$values = $map[2];
- return array(Type::T_LIST, ',', $values);
+ return [Type::T_LIST, ',', $values];
}
- protected static $libMapRemove = array('map', 'key');
+ protected static $libMapRemove = ['map', 'key'];
protected function libMapRemove($args)
{
$map = $this->assertMap($args[0]);
@@ -4672,7 +4672,7 @@ protected function libMapRemove($args)
return $map;
}
- protected static $libMapHasKey = array('map', 'key');
+ protected static $libMapHasKey = ['map', 'key'];
protected function libMapHasKey($args)
{
$map = $this->assertMap($args[0]);
@@ -4687,29 +4687,29 @@ protected function libMapHasKey($args)
return false;
}
- protected static $libMapMerge = array('map-1', 'map-2');
+ protected static $libMapMerge = ['map-1', 'map-2'];
protected function libMapMerge($args)
{
$map1 = $this->assertMap($args[0]);
$map2 = $this->assertMap($args[1]);
- return array(Type::T_MAP, array_merge($map1[1], $map2[1]), array_merge($map1[2], $map2[2]));
+ return [Type::T_MAP, array_merge($map1[1], $map2[1]), array_merge($map1[2], $map2[2])];
}
- protected static $libKeywords = array('args');
+ protected static $libKeywords = ['args'];
protected function libKeywords($args)
{
$this->assertList($args[0]);
- $keys = array();
- $values = array();
+ $keys = [];
+ $values = [];
foreach ($args[0][2] as $name => $arg) {
- $keys[] = array(Type::T_KEYWORD, $name);
+ $keys[] = [Type::T_KEYWORD, $name];
$values[] = $arg;
}
- return array(Type::T_MAP, $keys, $values);
+ return [Type::T_MAP, $keys, $values];
}
protected function listSeparatorForJoin($list1, $sep)
@@ -4730,7 +4730,7 @@ protected function listSeparatorForJoin($list1, $sep)
}
}
- protected static $libJoin = array('list1', 'list2', 'separator');
+ protected static $libJoin = ['list1', 'list2', 'separator'];
protected function libJoin($args)
{
list($list1, $list2, $sep) = $args;
@@ -4739,10 +4739,10 @@ protected function libJoin($args)
$list2 = $this->coerceList($list2, ' ');
$sep = $this->listSeparatorForJoin($list1, $sep);
- return array(Type::T_LIST, $sep, array_merge($list1[2], $list2[2]));
+ return [Type::T_LIST, $sep, array_merge($list1[2], $list2[2])];
}
- protected static $libAppend = array('list', 'val', 'separator');
+ protected static $libAppend = ['list', 'val', 'separator'];
protected function libAppend($args)
{
list($list1, $value, $sep) = $args;
@@ -4750,7 +4750,7 @@ protected function libAppend($args)
$list1 = $this->coerceList($list1, ' ');
$sep = $this->listSeparatorForJoin($list1, $sep);
- return array(Type::T_LIST, $sep, array_merge($list1[2], array($value)));
+ return [Type::T_LIST, $sep, array_merge($list1[2], [$value])];
}
protected function libZip($args)
@@ -4759,11 +4759,11 @@ protected function libZip($args)
$this->assertList($arg);
}
- $lists = array();
+ $lists = [];
$firstList = array_shift($args);
foreach ($firstList[2] as $key => $item) {
- $list = array(Type::T_LIST, '', array($item));
+ $list = [Type::T_LIST, '', [$item]];
foreach ($args as $arg) {
if (isset($arg[2][$key])) {
@@ -4776,10 +4776,10 @@ protected function libZip($args)
$lists[] = $list;
}
- return array(Type::T_LIST, ',', $lists);
+ return [Type::T_LIST, ',', $lists];
}
- protected static $libTypeOf = array('value');
+ protected static $libTypeOf = ['value'];
protected function libTypeOf($args)
{
$value = $args[0];
@@ -4809,19 +4809,19 @@ protected function libTypeOf($args)
}
}
- protected static $libUnit = array('number');
+ protected static $libUnit = ['number'];
protected function libUnit($args)
{
$num = $args[0];
if ($num[0] === Type::T_NUMBER) {
- return array(Type::T_STRING, '"', array($num->unitStr()));
+ return [Type::T_STRING, '"', [$num->unitStr()]];
}
return '';
}
- protected static $libUnitless = array('number');
+ protected static $libUnitless = ['number'];
protected function libUnitless($args)
{
$value = $args[0];
@@ -4829,7 +4829,7 @@ protected function libUnitless($args)
return $value[0] === Type::T_NUMBER && $value->unitless();
}
- protected static $libComparable = array('number-1', 'number-2');
+ protected static $libComparable = ['number-1', 'number-2'];
protected function libComparable($args)
{
list($number1, $number2) = $args;
@@ -4848,7 +4848,7 @@ protected function libComparable($args)
return $number1[2] === $number2[2] || $number1->unitless() || $number2->unitless();
}
- protected static $libStrIndex = array('string', 'substring');
+ protected static $libStrIndex = ['string', 'substring'];
protected function libStrIndex($args)
{
$string = $this->coerceString($args[0]);
@@ -4862,7 +4862,7 @@ protected function libStrIndex($args)
return $result === false ? self::$null : new Node\Number($result + 1, '');
}
- protected static $libStrInsert = array('string', 'insert', 'index');
+ protected static $libStrInsert = ['string', 'insert', 'index'];
protected function libStrInsert($args)
{
$string = $this->coerceString($args[0]);
@@ -4873,12 +4873,12 @@ protected function libStrInsert($args)
list(, $index) = $args[2];
- $string[2] = array(substr_replace($stringContent, $insertContent, $index - 1, 0));
+ $string[2] = [substr_replace($stringContent, $insertContent, $index - 1, 0)];
return $string;
}
- protected static $libStrLength = array('string');
+ protected static $libStrLength = ['string'];
protected function libStrLength($args)
{
$string = $this->coerceString($args[0]);
@@ -4887,7 +4887,7 @@ protected function libStrLength($args)
return new Node\Number(strlen($stringContent), '');
}
- protected static $libStrSlice = array('string', 'start-at', 'end-at');
+ protected static $libStrSlice = ['string', 'start-at', 'end-at'];
protected function libStrSlice($args)
{
if (isset($args[2]) && $args[2][1] == 0) {
@@ -4907,35 +4907,35 @@ protected function libStrSlice($args)
$length = $end < 0 ? $end + 1 : ($end > 0 ? $end - $start : $end);
$string[2] = $length
- ? array(substr($stringContent, $start, $length))
- : array(substr($stringContent, $start));
+ ? [substr($stringContent, $start, $length)]
+ : [substr($stringContent, $start)];
return $string;
}
- protected static $libToLowerCase = array('string');
+ protected static $libToLowerCase = ['string'];
protected function libToLowerCase($args)
{
$string = $this->coerceString($args[0]);
$stringContent = $this->compileStringContent($string);
- $string[2] = array(mb_strtolower($stringContent));
+ $string[2] = [mb_strtolower($stringContent)];
return $string;
}
- protected static $libToUpperCase = array('string');
+ protected static $libToUpperCase = ['string'];
protected function libToUpperCase($args)
{
$string = $this->coerceString($args[0]);
$stringContent = $this->compileStringContent($string);
- $string[2] = array(mb_strtoupper($stringContent));
+ $string[2] = [mb_strtoupper($stringContent)];
return $string;
}
- protected static $libFeatureExists = array('feature');
+ protected static $libFeatureExists = ['feature'];
protected function libFeatureExists($args)
{
$string = $this->coerceString($args[0]);
@@ -4946,7 +4946,7 @@ protected function libFeatureExists($args)
);
}
- protected static $libFunctionExists = array('name');
+ protected static $libFunctionExists = ['name'];
protected function libFunctionExists($args)
{
$string = $this->coerceString($args[0]);
@@ -4969,7 +4969,7 @@ protected function libFunctionExists($args)
return $this->toBool(is_callable($f));
}
- protected static $libGlobalVariableExists = array('name');
+ protected static $libGlobalVariableExists = ['name'];
protected function libGlobalVariableExists($args)
{
$string = $this->coerceString($args[0]);
@@ -4978,7 +4978,7 @@ protected function libGlobalVariableExists($args)
return $this->has($name, $this->rootEnv);
}
- protected static $libMixinExists = array('name');
+ protected static $libMixinExists = ['name'];
protected function libMixinExists($args)
{
$string = $this->coerceString($args[0]);
@@ -4987,7 +4987,7 @@ protected function libMixinExists($args)
return $this->has(self::$namespaces['mixin'] . $name);
}
- protected static $libVariableExists = array('name');
+ protected static $libVariableExists = ['name'];
protected function libVariableExists($args)
{
$string = $this->coerceString($args[0]);
@@ -5003,12 +5003,12 @@ protected function libVariableExists($args)
*/
protected function libCounter($args)
{
- $list = array_map(array($this, 'compileValue'), $args);
+ $list = array_map([$this, 'compileValue'], $args);
- return array(Type::T_STRING, '', array('counter(' . implode(',', $list) . ')'));
+ return [Type::T_STRING, '', ['counter(' . implode(',', $list) . ')']];
}
- protected static $libRandom = array('limit');
+ protected static $libRandom = ['limit'];
protected function libRandom($args)
{
if (isset($args[0])) {
@@ -5036,14 +5036,14 @@ protected function libUniqueId()
$id += mt_rand(0, 10) + 1;
- return array(Type::T_STRING, '', array('u' . str_pad(base_convert($id, 10, 36), 8, '0', STR_PAD_LEFT)));
+ return [Type::T_STRING, '', ['u' . str_pad(base_convert($id, 10, 36), 8, '0', STR_PAD_LEFT)]];
}
- protected static $libInspect = array('value');
+ protected static $libInspect = ['value'];
protected function libInspect($args)
{
if ($args[0] === self::$null) {
- return array(Type::T_KEYWORD, 'null');
+ return [Type::T_KEYWORD, 'null'];
}
return $args[0];
diff --git a/src/Formatter/Nested.php b/src/Formatter/Nested.php
index 6fab43dc..ed9f075b 100644
--- a/src/Formatter/Nested.php
+++ b/src/Formatter/Nested.php
@@ -154,7 +154,7 @@ protected function block(OutputBlock $block)
private function adjustAllChildren(OutputBlock $block)
{
// flatten empty nested blocks
- $children = array();
+ $children = [];
foreach ($block->children as $i => $child) {
if (empty($child->lines) && empty($child->children)) {
diff --git a/src/Node/Number.php b/src/Node/Number.php
index 6549f495..a803a6ca 100644
--- a/src/Node/Number.php
+++ b/src/Node/Number.php
@@ -38,8 +38,8 @@ class Number extends Node implements \ArrayAccess
*
* @var array
*/
- static protected $unitTable = array(
- 'in' => array(
+ static protected $unitTable = [
+ 'in' => [
'in' => 1,
'pc' => 6,
'pt' => 72,
@@ -47,27 +47,27 @@ class Number extends Node implements \ArrayAccess
'cm' => 2.54,
'mm' => 25.4,
'q' => 101.6,
- ),
- 'turn' => array(
+ ],
+ 'turn' => [
'deg' => 360,
'grad' => 400,
'rad' => 6.28318530717958647692528676, // 2 * M_PI
'turn' => 1,
- ),
- 's' => array(
+ ],
+ 's' => [
's' => 1,
'ms' => 1000,
- ),
- 'Hz' => array(
+ ],
+ 'Hz' => [
'Hz' => 1,
'kHz' => 0.001,
- ),
- 'dpi' => array(
+ ],
+ 'dpi' => [
'dpi' => 1,
'dpcm' => 2.54,
'dppx' => 96,
- ),
- );
+ ],
+ ];
/**
* @var integer|float
@@ -91,8 +91,8 @@ public function __construct($dimension, $initialUnit)
$this->dimension = $dimension;
$this->units = is_array($initialUnit)
? $initialUnit
- : ($initialUnit ? array($initialUnit => 1)
- : array());
+ : ($initialUnit ? [$initialUnit => 1]
+ : []);
}
/**
@@ -128,7 +128,7 @@ public function coerce($units)
public function normalize()
{
$dimension = $this->dimension;
- $units = array();
+ $units = [];
$this->normalizeUnits($dimension, $units, 'in');
@@ -238,8 +238,8 @@ public function unitless()
*/
public function unitStr()
{
- $numerators = array();
- $denominators = array();
+ $numerators = [];
+ $denominators = [];
foreach ($this->units as $unit => $unitSize) {
if ($unitSize > 0) {
@@ -273,7 +273,7 @@ public function output(Compiler $compiler = null)
if (count($units) > 1 && array_sum($units) === 0) {
$dimension = $this->dimension;
- $units = array();
+ $units = [];
$this->normalizeUnits($dimension, $units, 'in');
@@ -313,7 +313,7 @@ public function __toString()
private function normalizeUnits(&$dimension, &$units, $baseUnit = 'in')
{
$dimension = $this->dimension;
- $units = array();
+ $units = [];
foreach ($this->units as $unit => $exp) {
if (isset(self::$unitTable[$baseUnit][$unit])) {
diff --git a/src/Parser.php b/src/Parser.php
index 562ea701..95e26049 100644
--- a/src/Parser.php
+++ b/src/Parser.php
@@ -31,7 +31,7 @@ class Parser
/**
* @var array
*/
- protected static $precedence = array(
+ protected static $precedence = [
'=' => 0,
'or' => 1,
'and' => 2,
@@ -47,7 +47,7 @@ class Parser
'*' => 6,
'/' => 6,
'%' => 6,
- );
+ ];
protected static $commentPattern;
protected static $operatorPattern;
@@ -321,8 +321,7 @@ protected function parseChunk()
($this->end() ||
$this->literal('{') && $hasBlock = true)
) {
- $child = array(Type::T_INCLUDE,
- $mixinName, isset($argValues) ? $argValues : null, null);
+ $child = [Type::T_INCLUDE, $mixinName, isset($argValues) ? $argValues : null, null];
if (! empty($hasBlock)) {
$include = $this->pushSpecialBlock(Type::T_INCLUDE, $s);
@@ -340,7 +339,7 @@ protected function parseChunk()
$this->valueList($importPath) &&
$this->end()
) {
- $this->append(array(Type::T_SCSSPHP_IMPORT_ONCE, $importPath), $s);
+ $this->append([Type::T_SCSSPHP_IMPORT_ONCE, $importPath], $s);
return true;
}
@@ -351,7 +350,7 @@ protected function parseChunk()
$this->valueList($importPath) &&
$this->end()
) {
- $this->append(array(Type::T_IMPORT, $importPath), $s);
+ $this->append([Type::T_IMPORT, $importPath], $s);
return true;
}
@@ -362,7 +361,7 @@ protected function parseChunk()
$this->url($importPath) &&
$this->end()
) {
- $this->append(array(Type::T_IMPORT, $importPath), $s);
+ $this->append([Type::T_IMPORT, $importPath], $s);
return true;
}
@@ -375,7 +374,7 @@ protected function parseChunk()
) {
// check for '!flag'
$optional = $this->stripOptionalFlag($selectors);
- $this->append(array(Type::T_EXTEND, $selectors, $optional), $s);
+ $this->append([Type::T_EXTEND, $selectors, $optional], $s);
return true;
}
@@ -397,7 +396,7 @@ protected function parseChunk()
$this->seek($s);
if ($this->literal('@break') && $this->end()) {
- $this->append(array(Type::T_BREAK), $s);
+ $this->append([Type::T_BREAK], $s);
return true;
}
@@ -405,7 +404,7 @@ protected function parseChunk()
$this->seek($s);
if ($this->literal('@continue') && $this->end()) {
- $this->append(array(Type::T_CONTINUE), $s);
+ $this->append([Type::T_CONTINUE], $s);
return true;
}
@@ -414,7 +413,7 @@ protected function parseChunk()
if ($this->literal('@return') && ($this->valueList($retVal) || true) && $this->end()) {
- $this->append(array(Type::T_RETURN, isset($retVal) ? $retVal : array(Type::T_NULL)), $s);
+ $this->append([Type::T_RETURN, isset($retVal) ? $retVal : [Type::T_NULL]], $s);
return true;
}
@@ -475,7 +474,7 @@ protected function parseChunk()
if ($this->literal('@if') && $this->valueList($cond) && $this->literal('{')) {
$if = $this->pushSpecialBlock(Type::T_IF, $s);
$if->cond = $cond;
- $if->cases = array();
+ $if->cases = [];
return true;
}
@@ -486,7 +485,7 @@ protected function parseChunk()
$this->valueList($value) &&
$this->end()
) {
- $this->append(array(Type::T_DEBUG, $value), $s);
+ $this->append([Type::T_DEBUG, $value], $s);
return true;
}
@@ -497,7 +496,7 @@ protected function parseChunk()
$this->valueList($value) &&
$this->end()
) {
- $this->append(array(Type::T_WARN, $value), $s);
+ $this->append([Type::T_WARN, $value], $s);
return true;
}
@@ -508,7 +507,7 @@ protected function parseChunk()
$this->valueList($value) &&
$this->end()
) {
- $this->append(array(Type::T_ERROR, $value), $s);
+ $this->append([Type::T_ERROR, $value], $s);
return true;
}
@@ -516,7 +515,7 @@ protected function parseChunk()
$this->seek($s);
if ($this->literal('@content') && $this->end()) {
- $this->append(array(Type::T_MIXIN_CONTENT), $s);
+ $this->append([Type::T_MIXIN_CONTENT], $s);
return true;
}
@@ -553,7 +552,7 @@ protected function parseChunk()
$this->end()
) {
if (! isset($this->charset)) {
- $statement = array(Type::T_CHARSET, $charset);
+ $statement = [Type::T_CHARSET, $charset];
list($line, $column) = $this->getSourcePosition($s);
@@ -601,8 +600,8 @@ protected function parseChunk()
$this->valueList($value) &&
$this->end()
) {
- $name = array(Type::T_STRING, '', array($name));
- $this->append(array(Type::T_ASSIGN, $name, $value), $s);
+ $name = [Type::T_STRING, '', [$name]];
+ $this->append([Type::T_ASSIGN, $name, $value], $s);
return true;
}
@@ -617,7 +616,7 @@ protected function parseChunk()
) {
// check for '!flag'
$assignmentFlag = $this->stripAssignmentFlag($value);
- $this->append(array(Type::T_ASSIGN, $name, $value, $assignmentFlag), $s);
+ $this->append([Type::T_ASSIGN, $name, $value, $assignmentFlag], $s);
return true;
}
@@ -643,7 +642,7 @@ protected function parseChunk()
$foundSomething = false;
if ($this->valueList($value)) {
- $this->append(array(Type::T_ASSIGN, $name, $value), $s);
+ $this->append([Type::T_ASSIGN, $name, $value], $s);
$foundSomething = true;
}
@@ -673,7 +672,7 @@ protected function parseChunk()
$this->append($include, $s);
} elseif (empty($block->dontAppend)) {
$type = isset($block->type) ? $block->type : Type::T_BLOCK;
- $this->append(array($type, $block), $s);
+ $this->append([$type, $block], $s);
}
return true;
@@ -706,18 +705,18 @@ protected function pushBlock($selectors, $pos = 0)
$b->sourceColumn = $column;
$b->sourceIndex = $this->sourceIndex;
$b->selectors = $selectors;
- $b->comments = array();
+ $b->comments = [];
$b->parent = $this->env;
if (! $this->env) {
- $b->children = array();
+ $b->children = [];
} elseif (empty($this->env->children)) {
$this->env->children = $this->env->comments;
- $b->children = array();
- $this->env->comments = array();
+ $b->children = [];
+ $this->env->comments = [];
} else {
$b->children = $this->env->comments;
- $this->env->comments = array();
+ $this->env->comments = [];
}
$this->env = $b;
@@ -824,7 +823,7 @@ protected function matchString(&$m, $delim)
$end = strlen($this->buffer);
// look for either ending delim, escape, or string interpolation
- foreach (array('#{', '\\', $delim) as $lookahead) {
+ foreach (['#{', '\\', $delim] as $lookahead) {
$pos = strpos($this->buffer, $lookahead, $this->count);
if ($pos !== false && $pos < $end) {
@@ -838,11 +837,11 @@ protected function matchString(&$m, $delim)
}
$match = substr($this->buffer, $this->count, $end - $this->count);
- $m = array(
+ $m = [
$match . $token,
$match,
$token
- );
+ ];
$this->count = $end + strlen($token);
return true;
@@ -921,7 +920,7 @@ protected function whitespace()
while (preg_match(self::$whitePattern, $this->buffer, $m, null, $this->count)) {
if (isset($m[1]) && empty($this->commentsSeen[$this->count])) {
- $this->appendComment(array(Type::T_COMMENT, $m[1]));
+ $this->appendComment([Type::T_COMMENT, $m[1]]);
$this->commentsSeen[$this->count] = true;
}
@@ -940,7 +939,7 @@ protected function whitespace()
*/
protected function appendComment($comment)
{
- $comment[1] = substr(preg_replace(array('/^\s+/m', '/^(.)/m'), array('', ' \1'), $comment[1]), 1);
+ $comment[1] = substr(preg_replace(['/^\s+/m', '/^(.)/m'], ['', ' \1'], $comment[1]), 1);
$this->env->comments[] = $comment;
}
@@ -967,7 +966,7 @@ protected function append($statement, $pos = null)
if (count($comments)) {
$this->env->children = array_merge($this->env->children, $comments);
- $this->env->comments = array();
+ $this->env->comments = [];
}
}
@@ -1007,28 +1006,28 @@ protected function mediaQueryList(&$out)
protected function mediaQuery(&$out)
{
$expressions = null;
- $parts = array();
+ $parts = [];
if (($this->literal('only') && ($only = true) || $this->literal('not') && ($not = true) || true) &&
$this->mixedKeyword($mediaType)
) {
- $prop = array(Type::T_MEDIA_TYPE);
+ $prop = [Type::T_MEDIA_TYPE];
if (isset($only)) {
- $prop[] = array(Type::T_KEYWORD, 'only');
+ $prop[] = [Type::T_KEYWORD, 'only'];
}
if (isset($not)) {
- $prop[] = array(Type::T_KEYWORD, 'not');
+ $prop[] = [Type::T_KEYWORD, 'not'];
}
- $media = array(Type::T_LIST, '', array());
+ $media = [Type::T_LIST, '', []];
- foreach ((array)$mediaType as $type) {
+ foreach ((array) $mediaType as $type) {
if (is_array($type)) {
$media[2][] = $type;
} else {
- $media[2][] = array(Type::T_KEYWORD, $type);
+ $media[2][] = [Type::T_KEYWORD, $type];
}
}
@@ -1066,7 +1065,7 @@ protected function mediaExpression(&$out)
($this->literal(':') && $this->expression($value) || true) &&
$this->literal(')')
) {
- $out = array(Type::T_MEDIA_EXPRESSION, $feature);
+ $out = [Type::T_MEDIA_EXPRESSION, $feature];
if ($value) {
$out[] = $value;
@@ -1117,7 +1116,7 @@ protected function argValue(&$out)
}
if ($this->genericList($value, 'expression')) {
- $out = array($keyword, $value, false);
+ $out = [$keyword, $value, false];
$s = $this->seek();
if ($this->literal('...')) {
@@ -1169,7 +1168,7 @@ protected function spaceList(&$out)
protected function genericList(&$out, $parseItem, $delim = '', $flatten = true)
{
$s = $this->seek();
- $items = array();
+ $items = [];
while ($this->$parseItem($value)) {
$items[] = $value;
@@ -1190,7 +1189,7 @@ protected function genericList(&$out, $parseItem, $delim = '', $flatten = true)
if ($flatten && count($items) === 1) {
$out = $items[0];
} else {
- $out = array(Type::T_LIST, $delim, $items);
+ $out = [Type::T_LIST, $delim, $items];
}
return true;
@@ -1209,7 +1208,7 @@ protected function expression(&$out)
if ($this->literal('(')) {
if ($this->literal(')')) {
- $out = array(Type::T_LIST, '', array());
+ $out = [Type::T_LIST, '', []];
return true;
}
@@ -1276,7 +1275,7 @@ protected function expHelper($lhs, $minP)
$rhs = $this->expHelper($rhs, self::$precedence[$next[1]]);
}
- $lhs = array(Type::T_EXPRESSION, $op, $lhs, $rhs, $this->inParens, $whiteBefore, $whiteAfter);
+ $lhs = [Type::T_EXPRESSION, $op, $lhs, $rhs, $this->inParens, $whiteBefore, $whiteAfter];
$ss = $this->seek();
$whiteBefore = isset($this->buffer[$this->count - 1]) &&
ctype_space($this->buffer[$this->count - 1]);
@@ -1299,7 +1298,7 @@ protected function value(&$out)
$s = $this->seek();
if ($this->literal('not', false) && $this->whitespace() && $this->value($inner)) {
- $out = array(Type::T_UNARY, 'not', $inner, $this->inParens);
+ $out = [Type::T_UNARY, 'not', $inner, $this->inParens];
return true;
}
@@ -1307,7 +1306,7 @@ protected function value(&$out)
$this->seek($s);
if ($this->literal('not', false) && $this->parenValue($inner)) {
- $out = array(Type::T_UNARY, 'not', $inner, $this->inParens);
+ $out = [Type::T_UNARY, 'not', $inner, $this->inParens];
return true;
}
@@ -1315,7 +1314,7 @@ protected function value(&$out)
$this->seek($s);
if ($this->literal('+') && $this->value($inner)) {
- $out = array(Type::T_UNARY, '+', $inner, $this->inParens);
+ $out = [Type::T_UNARY, '+', $inner, $this->inParens];
return true;
}
@@ -1328,7 +1327,7 @@ protected function value(&$out)
$this->unit($inner) ||
$this->parenValue($inner))
) {
- $out = array(Type::T_UNARY, '-', $inner, $this->inParens);
+ $out = [Type::T_UNARY, '-', $inner, $this->inParens];
return true;
}
@@ -1349,9 +1348,9 @@ protected function value(&$out)
if ($this->keyword($keyword)) {
if ($keyword === 'null') {
- $out = array(Type::T_NULL);
+ $out = [Type::T_NULL];
} else {
- $out = array(Type::T_KEYWORD, $keyword);
+ $out = [Type::T_KEYWORD, $keyword];
}
return true;
@@ -1375,7 +1374,7 @@ protected function parenValue(&$out)
if ($this->literal('(')) {
if ($this->literal(')')) {
- $out = array(Type::T_LIST, '', array());
+ $out = [Type::T_LIST, '', []];
return true;
}
@@ -1414,9 +1413,9 @@ protected function progid(&$out)
$this->openString(')', $args, '(');
if ($this->literal(')')) {
- $out = array(Type::T_STRING, '', array(
+ $out = [Type::T_STRING, '', [
'progid:', $fn, '(', $args, ')'
- ));
+ ]];
return true;
}
@@ -1442,7 +1441,7 @@ protected function func(&$func)
$this->literal('(')
) {
if ($name === 'alpha' && $this->argumentList($args)) {
- $func = array(Type::T_FUNCTION, $name, array(Type::T_STRING, '', $args));
+ $func = [Type::T_FUNCTION, $name, [Type::T_STRING, '', $args]];
return true;
}
@@ -1451,7 +1450,7 @@ protected function func(&$func)
$ss = $this->seek();
if ($this->argValues($args) && $this->literal(')')) {
- $func = array(Type::T_FUNCTION_CALL, $name, $args);
+ $func = [Type::T_FUNCTION_CALL, $name, $args];
return true;
}
@@ -1462,13 +1461,13 @@ protected function func(&$func)
if (($this->openString(')', $str, '(') || true) &&
$this->literal(')')
) {
- $args = array();
+ $args = [];
if (! empty($str)) {
- $args[] = array(null, array(Type::T_STRING, '', array($str)));
+ $args[] = [null, [Type::T_STRING, '', [$str]]];
}
- $func = array(Type::T_FUNCTION_CALL, $name, $args);
+ $func = [Type::T_FUNCTION_CALL, $name, $args];
return true;
}
@@ -1491,11 +1490,11 @@ protected function argumentList(&$out)
$s = $this->seek();
$this->literal('(');
- $args = array();
+ $args = [];
while ($this->keyword($var)) {
if ($this->literal('=') && $this->expression($exp)) {
- $args[] = array(Type::T_STRING, '', array($var . '='));
+ $args[] = [Type::T_STRING, '', [$var . '=']];
$arg = $exp;
} else {
break;
@@ -1507,7 +1506,7 @@ protected function argumentList(&$out)
break;
}
- $args[] = array(Type::T_STRING, '', array(', '));
+ $args[] = [Type::T_STRING, '', [', ']];
}
if (! $this->literal(')') || ! count($args)) {
@@ -1533,10 +1532,10 @@ protected function argumentDef(&$out)
$s = $this->seek();
$this->literal('(');
- $args = array();
+ $args = [];
while ($this->variable($var)) {
- $arg = array($var[1], null, false);
+ $arg = [$var[1], null, false];
$ss = $this->seek();
@@ -1594,8 +1593,8 @@ protected function map(&$out)
return false;
}
- $keys = array();
- $values = array();
+ $keys = [];
+ $values = [];
while ($this->genericList($key, 'expression') && $this->literal(':') &&
$this->genericList($value, 'expression')
@@ -1614,7 +1613,7 @@ protected function map(&$out)
return false;
}
- $out = array(Type::T_MAP, $keys, $values);
+ $out = [Type::T_MAP, $keys, $values];
return true;
}
@@ -1628,13 +1627,13 @@ protected function map(&$out)
*/
protected function color(&$out)
{
- $color = array(Type::T_COLOR);
+ $color = [Type::T_COLOR];
if ($this->match('(#([0-9a-f]{6})|#([0-9a-f]{3}))', $m)) {
if (isset($m[3])) {
$num = hexdec($m[3]);
- foreach (array(3, 2, 1) as $i) {
+ foreach ([3, 2, 1] as $i) {
$t = $num & 0xf;
$color[$i] = $t << 4 | $t;
$num >>= 4;
@@ -1642,7 +1641,7 @@ protected function color(&$out)
} else {
$num = hexdec($m[2]);
- foreach (array(3, 2, 1) as $i) {
+ foreach ([3, 2, 1] as $i) {
$color[$i] = $num & 0xff;
$num >>= 8;
}
@@ -1693,7 +1692,7 @@ protected function string(&$out)
return false;
}
- $content = array();
+ $content = [];
$oldWhite = $this->eatWhiteDefault;
$this->eatWhiteDefault = false;
$hasInterpolation = false;
@@ -1742,7 +1741,7 @@ protected function string(&$out)
}
}
- $out = array(Type::T_STRING, $delim, $content);
+ $out = [Type::T_STRING, $delim, $content];
return true;
}
@@ -1761,7 +1760,7 @@ protected function string(&$out)
*/
protected function mixedKeyword(&$out)
{
- $parts = array();
+ $parts = [];
$oldWhite = $this->eatWhiteDefault;
$this->eatWhiteDefault = false;
@@ -1813,7 +1812,7 @@ protected function openString($end, &$out, $nestingOpen = null)
$nestingLevel = 0;
- $content = array();
+ $content = [];
while ($this->match($patt, $m, false)) {
if (isset($m[1]) && $m[1] !== '') {
@@ -1857,7 +1856,7 @@ protected function openString($end, &$out, $nestingOpen = null)
$content[count($content) - 1] = rtrim(end($content));
}
- $out = array(Type::T_STRING, '', $content);
+ $out = [Type::T_STRING, '', $content];
return true;
}
@@ -1885,7 +1884,7 @@ protected function interpolation(&$out, $lookWhite = true)
$left = $right = false;
}
- $out = array(Type::T_INTERPOLATE, $value, $left, $right);
+ $out = [Type::T_INTERPOLATE, $value, $left, $right];
$this->eatWhiteDefault = $oldWhite;
if ($this->eatWhiteDefault) {
@@ -1910,7 +1909,7 @@ protected function interpolation(&$out, $lookWhite = true)
*/
protected function propertyName(&$out)
{
- $parts = array();
+ $parts = [];
$oldWhite = $this->eatWhiteDefault;
$this->eatWhiteDefault = false;
@@ -1957,7 +1956,7 @@ protected function propertyName(&$out)
$this->whitespace(); // get any extra whitespace
- $out = array(Type::T_STRING, '', $parts);
+ $out = [Type::T_STRING, '', $parts];
return true;
}
@@ -1972,7 +1971,7 @@ protected function propertyName(&$out)
protected function selectors(&$out)
{
$s = $this->seek();
- $selectors = array();
+ $selectors = [];
while ($this->selector($sel)) {
$selectors[] = $sel;
@@ -2006,11 +2005,11 @@ protected function selectors(&$out)
*/
protected function selector(&$out)
{
- $selector = array();
+ $selector = [];
for (;;) {
if ($this->match('[>+~]+', $m)) {
- $selector[] = array($m[0]);
+ $selector[] = [$m[0]];
continue;
}
@@ -2021,7 +2020,7 @@ protected function selector(&$out)
}
if ($this->match('\/[^\/]+\/', $m)) {
- $selector[] = array($m[0]);
+ $selector[] = [$m[0]];
continue;
}
@@ -2052,7 +2051,7 @@ protected function selectorSingle(&$out)
$oldWhite = $this->eatWhiteDefault;
$this->eatWhiteDefault = false;
- $parts = array();
+ $parts = [];
if ($this->literal('*', false)) {
$parts[] = '*';
@@ -2189,7 +2188,7 @@ protected function variable(&$out)
$s = $this->seek();
if ($this->literal('$', false) && $this->keyword($name)) {
- $out = array(Type::T_VARIABLE, $name);
+ $out = [Type::T_VARIABLE, $name];
return true;
}
@@ -2257,7 +2256,7 @@ protected function placeholder(&$placeholder)
protected function url(&$out)
{
if ($this->match('(url\(\s*(["\']?)([^)]+)\2\s*\))', $m)) {
- $out = array(Type::T_STRING, '', array('url(' . $m[2] . $m[3] . $m[2] . ')'));
+ $out = [Type::T_STRING, '', ['url(' . $m[2] . $m[3] . $m[2] . ')']];
return true;
}
@@ -2298,7 +2297,7 @@ protected function stripAssignmentFlag(&$value)
for ($token = &$value; $token[0] === Type::T_LIST && ($s = count($token[2])); $token = &$lastNode) {
$lastNode = &$token[2][$s - 1];
- if ($lastNode[0] === Type::T_KEYWORD && in_array($lastNode[1], array('!default', '!global'))) {
+ if ($lastNode[0] === Type::T_KEYWORD && in_array($lastNode[1], ['!default', '!global'])) {
array_pop($token[2]);
$token = $this->flattenList($token);
@@ -2324,7 +2323,7 @@ protected function stripOptionalFlag(&$selectors)
$selector = end($selectors);
$part = end($selector);
- if ($part === array('!optional')) {
+ if ($part === ['!optional']) {
array_pop($selectors[count($selectors) - 1]);
$optional = true;
@@ -2410,7 +2409,7 @@ private function pregQuote($what)
*/
private function extractLineNumbers($buffer)
{
- $this->sourcePositions = array(0 => 0);
+ $this->sourcePositions = [0 => 0];
$prev = 0;
while (($pos = strpos($buffer, "\n", $prev)) !== false) {
@@ -2450,10 +2449,10 @@ private function getSourcePosition($pos)
continue;
}
- return array($mid + 1, $pos - $this->sourcePositions[$mid]);
+ return [$mid + 1, $pos - $this->sourcePositions[$mid]];
}
- return array($low + 1, $pos - $this->sourcePositions[$low]);
+ return [$low + 1, $pos - $this->sourcePositions[$low]];
}
/**
diff --git a/src/Server.php b/src/Server.php
index e34ff5c3..221655ca 100644
--- a/src/Server.php
+++ b/src/Server.php
@@ -214,14 +214,14 @@ protected function compile($in, $out)
file_put_contents($out, $css);
file_put_contents(
$this->metadataName($out),
- serialize(array(
+ serialize([
'etag' => $etag,
'imports' => $this->scss->getParsedFiles(),
'vars' => crc32(serialize($this->scss->getVariables())),
- ))
+ ])
);
- return array($css, $etag);
+ return [$css, $etag];
}
/**
@@ -234,8 +234,8 @@ protected function compile($in, $out)
protected function createErrorCSS(\Exception $error)
{
$message = str_replace(
- array("'", "\n"),
- array("\\'", "\\A"),
+ ["'", "\n"],
+ ["\\'", "\\A"],
$error->getfile() . ":\n\n" . $error->getMessage()
);
From 05369ac7ff3ce06b89dca0913da560aa7dcdba6c Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Wed, 16 Dec 2015 17:29:58 -0500
Subject: [PATCH 234/534] refactor semi-colon stripping (again)
---
scss.inc.php | 1 -
src/Formatter.php | 14 ++++++++++
src/Formatter/Compact.php | 1 +
src/Formatter/Compressed.php | 15 +++++++++-
src/Formatter/Crunched.php | 15 +++++++++-
src/Formatter/Debug.php | 1 +
src/Formatter/Expanded.php | 1 +
src/Formatter/Nested.php | 1 +
src/Formatter/StripSemiColons.php | 46 -------------------------------
9 files changed, 46 insertions(+), 49 deletions(-)
delete mode 100644 src/Formatter/StripSemiColons.php
diff --git a/scss.inc.php b/scss.inc.php
index ddfd1297..b6892fec 100644
--- a/scss.inc.php
+++ b/scss.inc.php
@@ -20,7 +20,6 @@
include_once __DIR__ . '/src/Formatter/Expanded.php';
include_once __DIR__ . '/src/Formatter/Nested.php';
include_once __DIR__ . '/src/Formatter/OutputBlock.php';
- include_once __DIR__ . '/src/Formatter/StripSemiColons.php';
include_once __DIR__ . '/src/Node.php';
include_once __DIR__ . '/src/Node/Number.php';
include_once __DIR__ . '/src/Parser.php';
diff --git a/src/Formatter.php b/src/Formatter.php
index caa9d660..2770bb2d 100644
--- a/src/Formatter.php
+++ b/src/Formatter.php
@@ -55,6 +55,11 @@ abstract class Formatter
*/
public $assignSeparator;
+ /**
+ * @var boolea
+ */
+ public $keepSemicolons;
+
/**
* Initialize formatter
*
@@ -96,6 +101,15 @@ public function property($name, $value)
*/
public function stripSemicolon(&$lines)
{
+ if ($this->keepSemicolons) {
+ return;
+ }
+
+ if (($count = count($lines))
+ && substr($lines[$count - 1], -1) === ';'
+ ) {
+ $lines[$count - 1] = substr($lines[$count - 1], 0, -1);
+ }
}
/**
diff --git a/src/Formatter/Compact.php b/src/Formatter/Compact.php
index 721390d7..94abe329 100644
--- a/src/Formatter/Compact.php
+++ b/src/Formatter/Compact.php
@@ -32,6 +32,7 @@ public function __construct()
$this->close = "}\n\n";
$this->tagSeparator = ',';
$this->assignSeparator = ':';
+ $this->keepSemicolons = true;
}
/**
diff --git a/src/Formatter/Compressed.php b/src/Formatter/Compressed.php
index af55da02..df7bc75f 100644
--- a/src/Formatter/Compressed.php
+++ b/src/Formatter/Compressed.php
@@ -21,7 +21,20 @@
*/
class Compressed extends Formatter
{
- use StripSemiColons;
+ /**
+ * {@inheritdoc}
+ */
+ public function __construct()
+ {
+ $this->indentLevel = 0;
+ $this->indentChar = ' ';
+ $this->break = '';
+ $this->open = '{';
+ $this->close = '}';
+ $this->tagSeparator = ',';
+ $this->assignSeparator = ':';
+ $this->keepSemicolons = false;
+ }
/**
* {@inheritdoc}
diff --git a/src/Formatter/Crunched.php b/src/Formatter/Crunched.php
index c31cac56..ccba1333 100644
--- a/src/Formatter/Crunched.php
+++ b/src/Formatter/Crunched.php
@@ -21,7 +21,20 @@
*/
class Crunched extends Formatter
{
- use StripSemiColons;
+ /**
+ * {@inheritdoc}
+ */
+ public function __construct()
+ {
+ $this->indentLevel = 0;
+ $this->indentChar = ' ';
+ $this->break = '';
+ $this->open = '{';
+ $this->close = '}';
+ $this->tagSeparator = ',';
+ $this->assignSeparator = ':';
+ $this->keepSemicolons = false;
+ }
/**
* {@inheritdoc}
diff --git a/src/Formatter/Debug.php b/src/Formatter/Debug.php
index e4555bb3..855742e7 100644
--- a/src/Formatter/Debug.php
+++ b/src/Formatter/Debug.php
@@ -33,6 +33,7 @@ public function __construct()
$this->close = ' }';
$this->tagSeparator = ', ';
$this->assignSeparator = ': ';
+ $this->keepSemicolons = true;
}
/**
diff --git a/src/Formatter/Expanded.php b/src/Formatter/Expanded.php
index b1a0bf24..54db742f 100644
--- a/src/Formatter/Expanded.php
+++ b/src/Formatter/Expanded.php
@@ -33,6 +33,7 @@ public function __construct()
$this->close = '}';
$this->tagSeparator = ', ';
$this->assignSeparator = ': ';
+ $this->keepSemicolons = true;
}
/**
diff --git a/src/Formatter/Nested.php b/src/Formatter/Nested.php
index ed9f075b..9fdb4dd0 100644
--- a/src/Formatter/Nested.php
+++ b/src/Formatter/Nested.php
@@ -38,6 +38,7 @@ public function __construct()
$this->close = ' }';
$this->tagSeparator = ', ';
$this->assignSeparator = ': ';
+ $this->keepSemicolons = true;
}
/**
diff --git a/src/Formatter/StripSemiColons.php b/src/Formatter/StripSemiColons.php
deleted file mode 100644
index 8e42c16e..00000000
--- a/src/Formatter/StripSemiColons.php
+++ /dev/null
@@ -1,46 +0,0 @@
-
- */
-trait StripSemiColons
-{
- /**
- * {@inheritdoc}
- */
- public function __construct()
- {
- $this->indentLevel = 0;
- $this->indentChar = ' ';
- $this->break = '';
- $this->open = '{';
- $this->close = '}';
- $this->tagSeparator = ',';
- $this->assignSeparator = ':';
- }
-
- /**
- * {@inheritdoc}
- */
- public function stripSemicolon(&$lines)
- {
- if (($count = count($lines))
- && substr($lines[$count - 1], -1) === ';'
- ) {
- $lines[$count - 1] = substr($lines[$count - 1], 0, -1);
- }
- }
-}
From feecdbe1defcd89089e51bf89bf77e0332658517 Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Wed, 16 Dec 2015 17:46:24 -0500
Subject: [PATCH 235/534] Bump version to v0.6.2
---
src/Version.php | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/Version.php b/src/Version.php
index ef096e94..0d54dd51 100644
--- a/src/Version.php
+++ b/src/Version.php
@@ -18,5 +18,5 @@
*/
class Version
{
- const VERSION = 'v0.6.1';
+ const VERSION = 'v0.6.2';
}
From aa18ff29729691ccbececb52d839c5a517505980 Mon Sep 17 00:00:00 2001
From: Anthon Pang
Date: Thu, 24 Dec 2015 12:33:50 -0500
Subject: [PATCH 236/534] fixes #396 extend+parent+placeholder
---
src/Compiler.php | 19 +++++++++++++------
tests/inputs/extends.scss | 20 ++++++++++++++++++++
tests/outputs/extends.css | 9 +++++++++
tests/outputs_numbered/extends.css | 14 ++++++++++++++
4 files changed, 56 insertions(+), 6 deletions(-)
diff --git a/src/Compiler.php b/src/Compiler.php
index 64dfb8b3..8c14d36d 100644
--- a/src/Compiler.php
+++ b/src/Compiler.php
@@ -521,21 +521,28 @@ protected function matchExtendsSingle($rawSingle, &$outOrigin)
*/
protected function combineSelectorSingle($base, $other)
{
- $tag = null;
+ $tag = [];
$out = [];
+ $wasTag = true;
foreach ([$base, $other] as $single) {
foreach ($single as $part) {
- if (preg_match('/^[^\[.#:]/', $part)) {
- $tag = $part;
- } else {
+ if (preg_match('/^[\[.:#]/', $part)) {
$out[] = $part;
+ $wasTag = false;
+ } elseif (preg_match('/^[^_-]/', $part)) {
+ $tag[] = $part;
+ $wasTag = true;
+ } elseif ($wasTag) {
+ $tag[count($tag) - 1] .= $part;
+ } else {
+ $out[count($out) - 1] .= $part;
}
}
}
- if ($tag) {
- array_unshift($out, $tag);
+ if (count($tag)) {
+ array_unshift($out, $tag[0]);
}
return $out;
diff --git a/tests/inputs/extends.scss b/tests/inputs/extends.scss
index 9da03502..467d3624 100644
--- a/tests/inputs/extends.scss
+++ b/tests/inputs/extends.scss
@@ -285,3 +285,23 @@ $var: ".selector1, .selector2";
a.important {
@extend .notice !optional;
}
+
+$color-base: white;
+
+%pagination-bullet {
+ width: 6px;
+ height: 6px;
+ margin-left: 5px;
+ &:first-child {
+ margin-left: 0;
+ }
+ &.is-active {
+ background-color: $color-base;
+ }
+}
+
+.pagination {
+ &-bullet {
+ @extend %pagination-bullet;
+ }
+}
diff --git a/tests/outputs/extends.css b/tests/outputs/extends.css
index 82a65823..8e2916a3 100644
--- a/tests/outputs/extends.css
+++ b/tests/outputs/extends.css
@@ -129,3 +129,12 @@ body .to-extend, body .test {
font-size: 14px; }
.main .block__element--modifier {
font-weight: bold; }
+
+.pagination-bullet {
+ width: 6px;
+ height: 6px;
+ margin-left: 5px; }
+ .pagination-bullet:first-child {
+ margin-left: 0; }
+ .pagination-bullet.is-active {
+ background-color: white; }
diff --git a/tests/outputs_numbered/extends.css b/tests/outputs_numbered/extends.css
index 5d76d9d3..e32f01b7 100644
--- a/tests/outputs_numbered/extends.css
+++ b/tests/outputs_numbered/extends.css
@@ -201,3 +201,17 @@ body .to-extend, body .test {
.main .block__element--modifier {
font-weight: bold; }
/* line 285, inputs/extends.scss */
+/* line 291, inputs/extends.scss */
+
+.pagination-bullet {
+ width: 6px;
+ height: 6px;
+ margin-left: 5px; }
+/* line 295, inputs/extends.scss */
+.pagination-bullet:first-child {
+ margin-left: 0; }
+/* line 298, inputs/extends.scss */
+.pagination-bullet.is-active {
+ background-color: white; }
+/* line 303, inputs/extends.scss */
+/* line 304, inputs/extends.scss */
From 3eef90cd8ecff0790713090d1cfd17e1cced589f Mon Sep 17 00:00:00 2001
From: josh