From 847f9f2d6cb64042ed6ca91938f8aa7d20dcadba Mon Sep 17 00:00:00 2001 From: Anthon Pang Date: Thu, 19 Apr 2018 11:42:23 -0400 Subject: [PATCH 001/215] fixes #568 example/Server: set default timezone to UTC --- example/Server.php | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/example/Server.php b/example/Server.php index a8dc0457..6ea97018 100644 --- a/example/Server.php +++ b/example/Server.php @@ -207,7 +207,7 @@ protected function compile($in, $out) $elapsed = round((microtime(true) - $start), 4); $v = Version::VERSION; - $t = date('r'); + $t = gmdate('r'); $css = "/* compiled by scssphp $v on $t (${elapsed}s) */\n\n" . $css; $etag = md5($css); @@ -329,7 +329,7 @@ public function serve($salt = '') try { list($css, $etag) = $this->compile($input, $output); - $lastModified = gmdate('D, d M Y H:i:s', filemtime($output)) . ' GMT'; + $lastModified = gmdate('r', filemtime($output)); header('Last-Modified: ' . $lastModified); header('Content-type: text/css'); @@ -371,7 +371,7 @@ public function serve($salt = '') return; } - $lastModified = gmdate('D, d M Y H:i:s', $mtime) . ' GMT'; + $lastModified = gmdate('r', $mtime); header('Last-Modified: ' . $lastModified); echo file_get_contents($output); @@ -510,8 +510,6 @@ public function __construct($dir, $cacheDir = null, $scss = null) $this->scss = $scss; $this->showErrorsAsCSS = false; - if (! ini_get('date.timezone')) { - throw new ServerException('Default date.timezone not set'); - } + date_default_timezone_set('UTC'); } } From 53bb5275a7e3fad3676f1e01f3014d39a0c6d675 Mon Sep 17 00:00:00 2001 From: AzJezz Date: Sun, 29 Apr 2018 16:32:07 +0100 Subject: [PATCH 002/215] Update Compiler.php --- src/Compiler.php | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/Compiler.php b/src/Compiler.php index 698d4d89..32e9b774 100644 --- a/src/Compiler.php +++ b/src/Compiler.php @@ -316,10 +316,15 @@ protected function makeOutputBlock($type, $selectors = null) $out->parent = $this->scope; $out->selectors = $selectors; $out->depth = $this->env->depth; - $out->sourceName = $this->env->block->sourceName; - $out->sourceLine = $this->env->block->sourceLine; - $out->sourceColumn = $this->env->block->sourceColumn; - + if($this->env->block instanceof Block) { + $out->sourceName = $this->env->block->sourceName; + $out->sourceLine = $this->env->block->sourceLine; + $out->sourceColumn = $this->env->block->sourceColumn; + } else { + $out->sourceName = null; + $out->sourceLine = null; + $out->sourceColum = null; + } return $out; } From ddebe1a68a53c4b8524c03f8cb2c24174cb028dc Mon Sep 17 00:00:00 2001 From: Anthon Pang Date: Fri, 18 May 2018 14:48:28 -0400 Subject: [PATCH 003/215] Fix #573 --- src/Compiler.php | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/Compiler.php b/src/Compiler.php index 32e9b774..1aad621b 100644 --- a/src/Compiler.php +++ b/src/Compiler.php @@ -2699,7 +2699,9 @@ public function compileValue($value) $b = round($b); if (count($value) === 5 && $value[4] !== 1) { // rgba - return 'rgba(' . $r . ', ' . $g . ', ' . $b . ', ' . $value[4] . ')'; + $a = new Node\Number($value[4]); + + return 'rgba(' . $r . ', ' . $g . ', ' . $b . ', ' . $a . ')'; } $h = sprintf('#%02x%02x%02x', $r, $g, $b); @@ -4336,7 +4338,7 @@ protected function libRgb($args) protected function libRgba($args) { if ($color = $this->coerceColor($args[0])) { - $num = ! isset($args[1]) ? $args[3] : $args[1]; + $num = isset($args[3]) ? $args[3] : $args[1]; $alpha = $this->assertNumber($num); $color[4] = $alpha; From 57292fba51af83b0e812bc1cb31c7816b3f61936 Mon Sep 17 00:00:00 2001 From: Tim Elsass Date: Sun, 20 May 2018 00:52:50 -0400 Subject: [PATCH 004/215] Fix #575 --- src/Compiler.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Compiler.php b/src/Compiler.php index 1aad621b..746c6422 100644 --- a/src/Compiler.php +++ b/src/Compiler.php @@ -2699,7 +2699,7 @@ public function compileValue($value) $b = round($b); if (count($value) === 5 && $value[4] !== 1) { // rgba - $a = new Node\Number($value[4]); + $a = new Node\Number($value[4],''); return 'rgba(' . $r . ', ' . $g . ', ' . $b . ', ' . $a . ')'; } From 04482345fc0dd1b5305bcd5032ac4deb8a9ebbeb Mon Sep 17 00:00:00 2001 From: Anthon Pang Date: Sun, 20 May 2018 10:11:19 -0400 Subject: [PATCH 005/215] Update Compiler.php --- src/Compiler.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Compiler.php b/src/Compiler.php index 746c6422..b727f178 100644 --- a/src/Compiler.php +++ b/src/Compiler.php @@ -2699,7 +2699,7 @@ public function compileValue($value) $b = round($b); if (count($value) === 5 && $value[4] !== 1) { // rgba - $a = new Node\Number($value[4],''); + $a = new Node\Number($value[4], ''); return 'rgba(' . $r . ', ' . $g . ', ' . $b . ', ' . $a . ')'; } From 1a819c3b926c251891ede7c6bd12d91e403dc384 Mon Sep 17 00:00:00 2001 From: Anthon Pang Date: Wed, 23 May 2018 18:05:54 -0400 Subject: [PATCH 006/215] Fix phpcs warnings --- src/Compiler.php | 4 ++-- src/Parser.php | 15 +++++++++++++++ 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/src/Compiler.php b/src/Compiler.php index b727f178..bfda455f 100644 --- a/src/Compiler.php +++ b/src/Compiler.php @@ -316,14 +316,14 @@ protected function makeOutputBlock($type, $selectors = null) $out->parent = $this->scope; $out->selectors = $selectors; $out->depth = $this->env->depth; - if($this->env->block instanceof Block) { + if ($this->env->block instanceof Block) { $out->sourceName = $this->env->block->sourceName; $out->sourceLine = $this->env->block->sourceLine; $out->sourceColumn = $this->env->block->sourceColumn; } else { $out->sourceName = null; $out->sourceLine = null; - $out->sourceColum = null; + $out->sourceColum = null; } return $out; } diff --git a/src/Parser.php b/src/Parser.php index 6fdea3e2..b8bfdc36 100644 --- a/src/Parser.php +++ b/src/Parser.php @@ -1302,6 +1302,21 @@ protected function value(&$out) { $s = $this->seek(); + if ($this->literal('url(') && $this->match('data:image\/([a-z0-9+-]+);base64,', $m, false)) { + $len = strspn($this->buffer, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwyxz0123456789+/=', $this->count); + + $this->count += $len; + + if ($this->literal(')')) { + $content = substr($this->buffer, $s, $this->count - $s); + $out = [Type::T_KEYWORD, $content]; + + return true; + } + } + + $this->seek($s); + if ($this->literal('not', false) && $this->whitespace() && $this->value($inner)) { $out = [Type::T_UNARY, 'not', $inner, $this->inParens]; From e94a5c21addf8541a710d5ac6507532118ba3295 Mon Sep 17 00:00:00 2001 From: Anthon Pang Date: Wed, 23 May 2018 18:12:08 -0400 Subject: [PATCH 007/215] Refs #527 - parsing base64 --- src/Parser.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Parser.php b/src/Parser.php index b8bfdc36..de86f094 100644 --- a/src/Parser.php +++ b/src/Parser.php @@ -1302,7 +1302,7 @@ protected function value(&$out) { $s = $this->seek(); - if ($this->literal('url(') && $this->match('data:image\/([a-z0-9+-]+);base64,', $m, false)) { + if ($this->literal('url(') && $this->match('data:([a-z]+)\/([a-z0-9.+-]+);base64,', $m, false)) { $len = strspn($this->buffer, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwyxz0123456789+/=', $this->count); $this->count += $len; From deaf1dede19347fed905931ad80b495b077e4220 Mon Sep 17 00:00:00 2001 From: Anthon Pang Date: Wed, 23 May 2018 21:33:11 -0400 Subject: [PATCH 008/215] Fix typo --- src/Compiler.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Compiler.php b/src/Compiler.php index bfda455f..72df991e 100644 --- a/src/Compiler.php +++ b/src/Compiler.php @@ -316,6 +316,7 @@ protected function makeOutputBlock($type, $selectors = null) $out->parent = $this->scope; $out->selectors = $selectors; $out->depth = $this->env->depth; + if ($this->env->block instanceof Block) { $out->sourceName = $this->env->block->sourceName; $out->sourceLine = $this->env->block->sourceLine; @@ -323,8 +324,9 @@ protected function makeOutputBlock($type, $selectors = null) } else { $out->sourceName = null; $out->sourceLine = null; - $out->sourceColum = null; + $out->sourceColumn = null; } + return $out; } From 585f6ae84de62ffecf69c23805f25d78d7e4b794 Mon Sep 17 00:00:00 2001 From: Anthon Pang Date: Wed, 23 May 2018 22:18:53 -0400 Subject: [PATCH 009/215] Bump version --- src/Version.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Version.php b/src/Version.php index 3b8dcd00..c8a56a5b 100644 --- a/src/Version.php +++ b/src/Version.php @@ -18,5 +18,5 @@ */ class Version { - const VERSION = 'v0.7.5'; + const VERSION = 'v0.7.6'; } From 0b94ebc2b0e61e797bfc0cb74acab5f3e95a09fd Mon Sep 17 00:00:00 2001 From: Stephan Date: Sun, 10 Jun 2018 01:09:50 +0200 Subject: [PATCH 010/215] Actually merge maps instead of just concatenating --- src/Compiler.php | 12 +++++++++++- tests/inputs/map.scss | 5 +++-- tests/outputs/map.css | 4 ++++ tests/outputs_numbered/map.css | 10 ++++++++-- 4 files changed, 26 insertions(+), 5 deletions(-) diff --git a/src/Compiler.php b/src/Compiler.php index 72df991e..8551f001 100644 --- a/src/Compiler.php +++ b/src/Compiler.php @@ -4985,7 +4985,17 @@ protected function libMapMerge($args) $map1 = $this->assertMap($args[0]); $map2 = $this->assertMap($args[1]); - return [Type::T_MAP, array_merge($map1[1], $map2[1]), array_merge($map1[2], $map2[2])]; + foreach ($map2[1] as $i2 => $key2) { + foreach ($map1[1] as $i1 => $key1) { + if ($this->compileStringContent($this->coerceString($key1)) === $this->compileStringContent($this->coerceString($key2))) { + $map1[2][$i1] = $map2[2][$i2]; + continue 2; + } + } + $map1[1][] = $map2[1][$i2]; + $map1[2][] = $map2[2][$i2]; + } + return $map1; } protected static $libKeywords = ['args']; diff --git a/tests/inputs/map.scss b/tests/inputs/map.scss index 0fb6be19..7f8adeba 100644 --- a/tests/inputs/map.scss +++ b/tests/inputs/map.scss @@ -25,9 +25,10 @@ div { bar: nth(nth($map, 1), 1); } -$color: ("black" : #000000); +$color: ("black" : #000000, "grey" : #777777); +$color2: ("grey" : #888888, "white" : #ffffff); -@each $color_name, $color_value in $color { +@each $color_name, $color_value in map_merge( $color, $color2 ) { .#{$color_name} { background-color: $color_value !important; } diff --git a/tests/outputs/map.css b/tests/outputs/map.css index 9c38094a..a8898915 100644 --- a/tests/outputs/map.css +++ b/tests/outputs/map.css @@ -12,6 +12,10 @@ div { bar: color; } .black { background-color: #000 !important; } + .grey { + background-color: #888 !important; } + .white { + background-color: #fff !important; } div { a: 1; diff --git a/tests/outputs_numbered/map.css b/tests/outputs_numbered/map.css index 16de52b9..23c144fb 100644 --- a/tests/outputs_numbered/map.css +++ b/tests/outputs_numbered/map.css @@ -11,10 +11,16 @@ div { div { foo: color black; bar: color; } -/* line 31, inputs/map.scss */ +/* line 32, inputs/map.scss */ .black { background-color: #000 !important; } -/* line 52, inputs/map.scss */ +/* line 32, inputs/map.scss */ +.grey { + background-color: #888 !important; } +/* line 32, inputs/map.scss */ +.white { + background-color: #fff !important; } +/* line 53, inputs/map.scss */ div { a: 1; b: 2; From 4963903c0a88db128026f1a78de205a7153d4b48 Mon Sep 17 00:00:00 2001 From: Anthon Pang Date: Tue, 19 Jun 2018 18:06:25 -0400 Subject: [PATCH 011/215] #569 attempt to fix call() with ellipsis --- src/Compiler.php | 38 +++++++++++++++++++++-------- tests/inputs/builtins.scss | 20 +++++++++++++++ tests/outputs/builtins.css | 12 +++++++++ tests/outputs_numbered/builtins.css | 12 +++++++++ 4 files changed, 72 insertions(+), 10 deletions(-) diff --git a/src/Compiler.php b/src/Compiler.php index 72df991e..7d8db736 100644 --- a/src/Compiler.php +++ b/src/Compiler.php @@ -3655,7 +3655,7 @@ protected function callNativeFunction($name, $args, &$returnValue) return false; } - list($sorted, $kwargs) = $this->sortArgs($prototype, $args); + @list($sorted, $kwargs) = $this->sortArgs($prototype, $args); if ($name !== 'if' && $name !== 'call') { foreach ($sorted as &$val) { @@ -3714,7 +3714,7 @@ protected function sortArgs($prototype, $args) $key = $key[1]; if (empty($key)) { - $posArgs[] = $value; + $posArgs[] = empty($arg[2]) ? $value : $arg; } else { $keyArgs[$key] = $value; } @@ -4266,20 +4266,38 @@ protected function libCall($args, $kwargs) { $name = $this->compileStringContent($this->coerceString($this->reduce(array_shift($args), true))); - $args = array_map( - function ($a) { - return [null, $a, false]; - }, - $args - ); + $posArgs = []; + + foreach ($args as $arg) { + if (empty($arg[0])) { + if ($arg[2] === true) { + $tmp = $this->reduce($arg[1]); + + if ($tmp[0] === Type::T_LIST) { + foreach ($tmp[2] as $item) { + $posArgs[] = [null, $item, false]; + } + } else { + $posArgs[] = [null, $tmp, true]; + } + + continue; + } + + $posArgs[] = [null, $this->reduce($arg), false]; + continue; + } + + $posArgs[] = [null, $arg, false]; + } if (count($kwargs)) { foreach ($kwargs as $key => $value) { - $args[] = [[Type::T_VARIABLE, $key], $value, false]; + $posArgs[] = [[Type::T_VARIABLE, $key], $value, false]; } } - return $this->reduce([Type::T_FUNCTION_CALL, $name, $args]); + return $this->reduce([Type::T_FUNCTION_CALL, $name, $posArgs]); } protected static $libIf = ['condition', 'if-true', 'if-false']; diff --git a/tests/inputs/builtins.scss b/tests/inputs/builtins.scss index a80db5b1..00cd3c63 100644 --- a/tests/inputs/builtins.scss +++ b/tests/inputs/builtins.scss @@ -216,3 +216,23 @@ $type: text; div.unquote-test { a: unquote('[type=\'#{$type}\']'); } + +.does-compile-1 { + color: call(lighten, #000, 40%); +} + +.does-compile-2 { + $color: #000; + $percent: 40%; + color: call(lighten, $color, $percent); +} + +.does-compile-3 { + $args: (#000, 40%); + color: call(lighten, nth($args, 1), nth($args, 2)); +} + +.does-compile-4 { + $args: (#000, 40%); + color: call(lighten, $args...); +} diff --git a/tests/outputs/builtins.css b/tests/outputs/builtins.css index 50e2a82e..db43727d 100644 --- a/tests/outputs/builtins.css +++ b/tests/outputs/builtins.css @@ -159,3 +159,15 @@ div.call-tests { div.unquote-test { a: [type='text']; } + +.does-compile-1 { + color: #666; } + +.does-compile-2 { + color: #666; } + +.does-compile-3 { + color: #666; } + +.does-compile-4 { + color: #666; } diff --git a/tests/outputs_numbered/builtins.css b/tests/outputs_numbered/builtins.css index 722c6af4..e84d727c 100644 --- a/tests/outputs_numbered/builtins.css +++ b/tests/outputs_numbered/builtins.css @@ -160,3 +160,15 @@ div.call-tests { /* line 216, inputs/builtins.scss */ div.unquote-test { a: [type='text']; } +/* line 220, inputs/builtins.scss */ +.does-compile-1 { + color: #666; } +/* line 224, inputs/builtins.scss */ +.does-compile-2 { + color: #666; } +/* line 230, inputs/builtins.scss */ +.does-compile-3 { + color: #666; } +/* line 235, inputs/builtins.scss */ +.does-compile-4 { + color: #666; } From 3d3fd508102242ab5744b91e51ff78e262db9467 Mon Sep 17 00:00:00 2001 From: Anthon Pang Date: Tue, 19 Jun 2018 23:10:38 -0400 Subject: [PATCH 012/215] refs #548 - treat 0 as a special unitless number --- src/Compiler.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Compiler.php b/src/Compiler.php index 7d8db736..62d125d8 100644 --- a/src/Compiler.php +++ b/src/Compiler.php @@ -4856,7 +4856,7 @@ protected function getNormalizedNumbers($args) if (null === $unit) { $unit = $number[2]; $originalUnit = $item->unitStr(); - } elseif ($unit !== $number[2]) { + } elseif ($number[1] && $unit !== $number[2]) { $this->throwError('Incompatible units: "%s" and "%s".', $originalUnit, $item->unitStr()); break; } From 1d656f8c02a3a69404bba6b28ec4e06edddf0f49 Mon Sep 17 00:00:00 2001 From: Anthon Pang Date: Sat, 21 Jul 2018 21:22:08 -0400 Subject: [PATCH 013/215] refs #578 peephole optimization --- src/Compiler.php | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/Compiler.php b/src/Compiler.php index 414e4401..637f1c1c 100644 --- a/src/Compiler.php +++ b/src/Compiler.php @@ -5004,15 +5004,19 @@ protected function libMapMerge($args) $map2 = $this->assertMap($args[1]); foreach ($map2[1] as $i2 => $key2) { + $key = $this->compileStringContent($this->coerceString($key2)); + foreach ($map1[1] as $i1 => $key1) { - if ($this->compileStringContent($this->coerceString($key1)) === $this->compileStringContent($this->coerceString($key2))) { + if ($key === $this->compileStringContent($this->coerceString($key1))) { $map1[2][$i1] = $map2[2][$i2]; continue 2; } } + $map1[1][] = $map2[1][$i2]; $map1[2][] = $map2[2][$i2]; } + return $map1; } From b72d613f682b714f498412483aff353cde977c00 Mon Sep 17 00:00:00 2001 From: Jiong Ye Date: Fri, 17 Aug 2018 16:24:08 -0400 Subject: [PATCH 014/215] leafo/scssphp#581 generate inline sourcemap in commandline --- bin/pscss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/pscss b/bin/pscss index be1cb51c..ce80e6a9 100755 --- a/bin/pscss +++ b/bin/pscss @@ -201,7 +201,7 @@ if ($style) { } if ($sourceMap) { - $scss->setSourceMap(Compiler::SOURCE_MAP_FILE); + $scss->setSourceMap(Compiler::SOURCE_MAP_INLINE); } if ($encoding) { From a7be38d3dabb6d3c15e28073541163428ad819ab Mon Sep 17 00:00:00 2001 From: Bastian Rihm Date: Thu, 30 Aug 2018 14:43:47 +0200 Subject: [PATCH 015/215] #515 Fix backslash escape --- src/Parser.php | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/Parser.php b/src/Parser.php index de86f094..748d38ae 100644 --- a/src/Parser.php +++ b/src/Parser.php @@ -1737,6 +1737,8 @@ protected function string(&$out) $content[] = $m[2] . '"'; } elseif ($this->literal("'", false)) { $content[] = $m[2] . "'"; + } elseif ($this->literal("\\", false)) { + $content[] = $m[2] . "\\"; } else { $content[] = $m[2]; } @@ -1753,7 +1755,9 @@ protected function string(&$out) $delim = '"'; foreach ($content as &$string) { - if ($string === "\\'") { + if ($string === "\\\\") { + $string = "\\"; + } elseif ($string === "\\'") { $string = "'"; } elseif ($string === '\\"') { $string = '"'; From 0b589890bfbdd2e14d272f78d9d49038c051f12c Mon Sep 17 00:00:00 2001 From: Anthon Pang Date: Tue, 24 Jul 2018 10:47:05 -0400 Subject: [PATCH 016/215] Bump version --- src/Version.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Version.php b/src/Version.php index c8a56a5b..ec0fee6f 100644 --- a/src/Version.php +++ b/src/Version.php @@ -18,5 +18,5 @@ */ class Version { - const VERSION = 'v0.7.6'; + const VERSION = 'v0.7.8'; } From 2a88d3e9ba903e1568cda7cd33add91d093a639c Mon Sep 17 00:00:00 2001 From: Anthon Pang Date: Wed, 26 Sep 2018 16:46:29 -0400 Subject: [PATCH 017/215] Update unit tests (fixes #515) --- tests/inputs/builtins.scss | 1 + tests/outputs/builtins.css | 1 + tests/outputs_numbered/builtins.css | 27 ++++++++++++++------------- 3 files changed, 16 insertions(+), 13 deletions(-) diff --git a/tests/inputs/builtins.scss b/tests/inputs/builtins.scss index 00cd3c63..c75a854e 100644 --- a/tests/inputs/builtins.scss +++ b/tests/inputs/builtins.scss @@ -78,6 +78,7 @@ color: quote("I do?"); color: str_index(abc, b); color: str_insert(string, insert, 2); + color: str_insert(string, "\\", 2); color: str_length(string); color: str_slice(string, 2, 4); color: str-slice(string, 2, 0); diff --git a/tests/outputs/builtins.css b/tests/outputs/builtins.css index db43727d..94f29b4e 100644 --- a/tests/outputs/builtins.css +++ b/tests/outputs/builtins.css @@ -53,6 +53,7 @@ color: "I do?"; color: 2; color: sinserttring; + color: s\\tring; color: 6; color: tri; color: trin; diff --git a/tests/outputs_numbered/builtins.css b/tests/outputs_numbered/builtins.css index e84d727c..559b6a30 100644 --- a/tests/outputs_numbered/builtins.css +++ b/tests/outputs_numbered/builtins.css @@ -54,6 +54,7 @@ color: "I do?"; color: 2; color: sinserttring; + color: s\\tring; color: 6; color: tri; color: trin; @@ -74,7 +75,7 @@ color: st; color: string; color: strin; } -/* line 105, inputs/builtins.scss */ +/* line 106, inputs/builtins.scss */ #number { color: 250%; color: 50%; @@ -86,7 +87,7 @@ width: 200%; bottom: 10px; padding: 3em 1in 96px 72pt; } -/* line 119, inputs/builtins.scss */ +/* line 120, inputs/builtins.scss */ #list { len: 3; len: 1; @@ -108,7 +109,7 @@ cool: great job one two three; zip: 1px solid, 2px dashed; zip: 1px solid red, 2px dashed green; } -/* line 155, inputs/builtins.scss */ +/* line 156, inputs/builtins.scss */ #introspection { t: number; t: string; @@ -128,47 +129,47 @@ c: true; c: false; c: true; } -/* line 179, inputs/builtins.scss */ +/* line 180, inputs/builtins.scss */ #if { color: yes; color: no; color: yes; color: yes; } -/* line 186, inputs/builtins.scss */ +/* line 187, inputs/builtins.scss */ .transparent { r: 0; g: 0; b: 0; a: 0; } -/* line 193, inputs/builtins.scss */ +/* line 194, inputs/builtins.scss */ .alpha { a: 1; a: 1; a: 1; a: 0.5; a: alpha(currentColor); } -/* line 202, inputs/builtins.scss */ +/* line 203, inputs/builtins.scss */ #exists { a: true; b: true; c: false; } -/* line 209, inputs/builtins.scss */ +/* line 210, inputs/builtins.scss */ div.call-tests { a: #0a64ff; b: #0058ef; c: b; } -/* line 216, inputs/builtins.scss */ +/* line 217, inputs/builtins.scss */ div.unquote-test { a: [type='text']; } -/* line 220, inputs/builtins.scss */ +/* line 221, inputs/builtins.scss */ .does-compile-1 { color: #666; } -/* line 224, inputs/builtins.scss */ +/* line 225, inputs/builtins.scss */ .does-compile-2 { color: #666; } -/* line 230, inputs/builtins.scss */ +/* line 231, inputs/builtins.scss */ .does-compile-3 { color: #666; } -/* line 235, inputs/builtins.scss */ +/* line 236, inputs/builtins.scss */ .does-compile-4 { color: #666; } From f893748cd4482051bc503064c6a4396b10280957 Mon Sep 17 00:00:00 2001 From: Anthon Pang Date: Wed, 26 Sep 2018 17:15:59 -0400 Subject: [PATCH 018/215] Add Base64VLQ encoder test (refs #600) --- tests/Base64VLQTest.php | 54 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 tests/Base64VLQTest.php diff --git a/tests/Base64VLQTest.php b/tests/Base64VLQTest.php new file mode 100644 index 00000000..21b373b8 --- /dev/null +++ b/tests/Base64VLQTest.php @@ -0,0 +1,54 @@ + + */ +class Base64VLQTest extends \PHPUnit_Framework_TestCase +{ + /** + * Test encode + * + * param string $expected + * param string $value + * + * @dataProvider getEncode + */ + public function testEncode($expected, $value) + { + $encoder = new Base64VLQEncoder; + + $this->assertEquals($expected, $encoder->encode($value)); + } + + /** + * Data provider for testEncode + * + * @return array + */ + public static function getEncode() + { + return [ + ['A', 0], + ['C', 1], + ['D', -1], + ['2H', 123], + ['qxmvrH', 123456789], + ['+/////D', 2147483647], // 2^31-1 + ]; + } +} From 0fcbdf599f9f8289d033f327532b6a2230b1d77f Mon Sep 17 00:00:00 2001 From: Anthon Pang Date: Sun, 30 Sep 2018 20:57:13 -0400 Subject: [PATCH 019/215] Fixes #600 - change Base64 VLQ encoder/decoder implementtion --- scss.inc.php | 3 +- src/SourceMap/Base64.php | 184 +++++++++++++++++++++++++++ src/SourceMap/Base64VLQ.php | 137 ++++++++++++++++++++ src/SourceMap/SourceMapGenerator.php | 4 +- tests/Base64VLQTest.php | 4 +- 5 files changed, 327 insertions(+), 5 deletions(-) create mode 100644 src/SourceMap/Base64.php create mode 100644 src/SourceMap/Base64VLQ.php diff --git a/scss.inc.php b/scss.inc.php index 13c84bf5..d75ecb55 100644 --- a/scss.inc.php +++ b/scss.inc.php @@ -24,7 +24,8 @@ include_once __DIR__ . '/src/Node.php'; include_once __DIR__ . '/src/Node/Number.php'; include_once __DIR__ . '/src/Parser.php'; - include_once __DIR__ . '/src/SourceMap/Base64VLQEncoder.php'; + include_once __DIR__ . '/src/SourceMap/Base64.php'; + include_once __DIR__ . '/src/SourceMap/Base64VLQ.php'; include_once __DIR__ . '/src/SourceMap/SourceMapGenerator.php'; include_once __DIR__ . '/src/Type.php'; include_once __DIR__ . '/src/Util.php'; diff --git a/src/SourceMap/Base64.php b/src/SourceMap/Base64.php new file mode 100644 index 00000000..9d17e6f0 --- /dev/null +++ b/src/SourceMap/Base64.php @@ -0,0 +1,184 @@ + + */ +class Base64 +{ + /** + * @var array + */ + private static $encodingMap = array ( + 0 => 'A', + 1 => 'B', + 2 => 'C', + 3 => 'D', + 4 => 'E', + 5 => 'F', + 6 => 'G', + 7 => 'H', + 8 => 'I', + 9 => 'J', + 10 => 'K', + 11 => 'L', + 12 => 'M', + 13 => 'N', + 14 => 'O', + 15 => 'P', + 16 => 'Q', + 17 => 'R', + 18 => 'S', + 19 => 'T', + 20 => 'U', + 21 => 'V', + 22 => 'W', + 23 => 'X', + 24 => 'Y', + 25 => 'Z', + 26 => 'a', + 27 => 'b', + 28 => 'c', + 29 => 'd', + 30 => 'e', + 31 => 'f', + 32 => 'g', + 33 => 'h', + 34 => 'i', + 35 => 'j', + 36 => 'k', + 37 => 'l', + 38 => 'm', + 39 => 'n', + 40 => 'o', + 41 => 'p', + 42 => 'q', + 43 => 'r', + 44 => 's', + 45 => 't', + 46 => 'u', + 47 => 'v', + 48 => 'w', + 49 => 'x', + 50 => 'y', + 51 => 'z', + 52 => '0', + 53 => '1', + 54 => '2', + 55 => '3', + 56 => '4', + 57 => '5', + 58 => '6', + 59 => '7', + 60 => '8', + 61 => '9', + 62 => '+', + 63 => '/', + ); + + /** + * @var array + */ + private static $decodingMap = array( + 'A' => 0, + 'B' => 1, + 'C' => 2, + 'D' => 3, + 'E' => 4, + 'F' => 5, + 'G' => 6, + 'H' => 7, + 'I' => 8, + 'J' => 9, + 'K' => 10, + 'L' => 11, + 'M' => 12, + 'N' => 13, + 'O' => 14, + 'P' => 15, + 'Q' => 16, + 'R' => 17, + 'S' => 18, + 'T' => 19, + 'U' => 20, + 'V' => 21, + 'W' => 22, + 'X' => 23, + 'Y' => 24, + 'Z' => 25, + 'a' => 26, + 'b' => 27, + 'c' => 28, + 'd' => 29, + 'e' => 30, + 'f' => 31, + 'g' => 32, + 'h' => 33, + 'i' => 34, + 'j' => 35, + 'k' => 36, + 'l' => 37, + 'm' => 38, + 'n' => 39, + 'o' => 40, + 'p' => 41, + 'q' => 42, + 'r' => 43, + 's' => 44, + 't' => 45, + 'u' => 46, + 'v' => 47, + 'w' => 48, + 'x' => 49, + 'y' => 50, + 'z' => 51, + 0 => 52, + 1 => 53, + 2 => 54, + 3 => 55, + 4 => 56, + 5 => 57, + 6 => 58, + 7 => 59, + 8 => 60, + 9 => 61, + '+' => 62, + '/' => 63, + ); + + /** + * Convert to base64 + * + * @param integer $value + * + * @return string + */ + public static function encode($value) + { + return self::$encodingMap[$value]; + } + + /** + * Convert from base64 + * + * @param string $value + * + * @return integer + */ + public static function decode($value) + { + return self::$decodingMap[$value]; + } +} diff --git a/src/SourceMap/Base64VLQ.php b/src/SourceMap/Base64VLQ.php new file mode 100644 index 00000000..6de3b5ee --- /dev/null +++ b/src/SourceMap/Base64VLQ.php @@ -0,0 +1,137 @@ + + * @author Anthon Pang + */ +class Base64VLQ +{ + // A Base64 VLQ digit can represent 5 bits, so it is base-32. + const VLQ_BASE_SHIFT = 5; + + // A mask of bits for a VLQ digit (11111), 31 decimal. + const VLQ_BASE_MASK = 31; + + // The continuation bit is the 6th bit. + const VLQ_CONTINUATION_BIT = 32; + + /** + * Returns the VLQ encoded value. + * + * @param integer $value + * + * @return string + */ + public static function encode($value) + { + $encoded = ''; + $vlq = self::toVLQSigned($value); + + do { + $digit = $vlq & self::VLQ_BASE_MASK; + $vlq >>= self::VLQ_BASE_SHIFT; + + if ($vlq > 0) { + $digit |= self::VLQ_CONTINUATION_BIT; + } + + $encoded .= Base64::encode($digit); + } while ($vlq > 0); + + return $encoded; + } + + /** + * Decodes VLQValue. + * + * @param string $str + * @param integer $index + * + * @return integer + */ + public static function decode($str, &$index) + { + $result = 0; + $shift = 0; + + do { + $c = $str[$index++]; + $digit = Base64::decode($c); + $continuation = ($digit & self::VLQ_CONTINUATION_BIT) != 0; + $digit &= self::VLQ_BASE_MASK; + $result = $result + ($digit << $shift); + $shift = $shift + self::VLQ_BASE_SHIFT; + } while ($continuation); + + return self::fromVLQSigned($result); + } + + /** + * Converts from a two-complement value to a value where the sign bit is + * is placed in the least significant bit. For example, as decimals: + * 1 becomes 2 (10 binary), -1 becomes 3 (11 binary) + * 2 becomes 4 (100 binary), -2 becomes 5 (101 binary) + * + * @param integer $value + * + * @return integer + */ + private static function toVLQSigned($value) + { + if ($value < 0) { + return ((-$value) << 1) + 1; + } + + return ($value << 1) + 0; + } + + /** + * Converts to a two-complement value from a value where the sign bit is + * is placed in the least significant bit. For example, as decimals: + * 2 (10 binary) becomes 1, 3 (11 binary) becomes -1 + * 4 (100 binary) becomes 2, 5 (101 binary) becomes -2 + * + * @param integer $value + * + * @return integer + */ + private static function fromVLQSigned($value) + { + $negate = ($value & 1) === 1; + $value = $value >> 1; + + return $negate ? -$value : $value; + } +} diff --git a/src/SourceMap/SourceMapGenerator.php b/src/SourceMap/SourceMapGenerator.php index 70b47cdc..6e969cae 100644 --- a/src/SourceMap/SourceMapGenerator.php +++ b/src/SourceMap/SourceMapGenerator.php @@ -61,7 +61,7 @@ class SourceMapGenerator /** * The base64 VLQ encoder * - * @var \Leafo\ScssPhp\SourceMap\Base64VLQEncoder + * @var \Leafo\ScssPhp\SourceMap\Base64VLQ */ protected $encoder; @@ -95,7 +95,7 @@ class SourceMapGenerator public function __construct(array $options = []) { $this->options = array_merge($this->defaultOptions, $options); - $this->encoder = new Base64VLQEncoder(); + $this->encoder = new Base64VLQ(); } /** diff --git a/tests/Base64VLQTest.php b/tests/Base64VLQTest.php index 21b373b8..a3b638de 100644 --- a/tests/Base64VLQTest.php +++ b/tests/Base64VLQTest.php @@ -11,7 +11,7 @@ namespace Leafo\ScssPhp\Tests; -use Leafo\ScssPhp\SourceMap\Base64VLQEncoder; +use Leafo\ScssPhp\SourceMap\Base64VLQ; /** * Base64VLQ encoder test @@ -30,7 +30,7 @@ class Base64VLQTest extends \PHPUnit_Framework_TestCase */ public function testEncode($expected, $value) { - $encoder = new Base64VLQEncoder; + $encoder = new Base64VLQ; $this->assertEquals($expected, $encoder->encode($value)); } From c1ca4095952a431d4847862e048715bc6fa331fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Nguyen?= Date: Thu, 11 Oct 2018 13:27:55 +0200 Subject: [PATCH 020/215] fix doc for addImportPath, should also accept callable as input --- src/Compiler.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Compiler.php b/src/Compiler.php index 637f1c1c..ed80d8d3 100644 --- a/src/Compiler.php +++ b/src/Compiler.php @@ -3308,7 +3308,7 @@ public function getParsedFiles() * * @api * - * @param string $path + * @param string|callable $path */ public function addImportPath($path) { From b931793663ac56d57d5f87f9f6f3f50cf6b73aa0 Mon Sep 17 00:00:00 2001 From: Geoff Willings Date: Tue, 23 Oct 2018 23:12:14 +0100 Subject: [PATCH 021/215] Bug fix error thrown from strpos if needle (basePath) is empty and ignore PhpStorm .idea IDE directory --- .gitignore | 1 + src/SourceMap/SourceMapGenerator.php | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index be6e5ecf..999984a4 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ +.idea .sass-cache scss_cache composer.lock diff --git a/src/SourceMap/SourceMapGenerator.php b/src/SourceMap/SourceMapGenerator.php index 6e969cae..39bfac1c 100644 --- a/src/SourceMap/SourceMapGenerator.php +++ b/src/SourceMap/SourceMapGenerator.php @@ -303,7 +303,7 @@ protected function normalizeFilename($filename) $basePath = $this->options['sourceMapBasepath']; // "Trim" the 'sourceMapBasepath' from the output filename. - if (strpos($filename, $basePath) === 0) { + if (strlen($basePath) && strpos($filename, $basePath) === 0) { $filename = substr($filename, strlen($basePath)); } From a0e5590e65e33ad6c10e4c98e4aa7c8563779ee8 Mon Sep 17 00:00:00 2001 From: Geoff Willings Date: Wed, 24 Oct 2018 00:41:31 +0100 Subject: [PATCH 022/215] Fix bug where rooted SCSS URIs aren't normalised properly with baseUri provided --- src/Compiler.php | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/Compiler.php b/src/Compiler.php index ed80d8d3..ee4efc96 100644 --- a/src/Compiler.php +++ b/src/Compiler.php @@ -3481,9 +3481,12 @@ 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; + $separator = ( + !empty($dir) && + substr($dir, -1) !== '/' && + substr($full, 0, 1) !== '/' + ) ? '/' : ''; + $full = $dir . $separator . $full; if ($this->fileExists($file = $full . '.scss') || ($hasExtension && $this->fileExists($file = $full)) From 51041822ae0e8b646e7d86de6c6f81100345f939 Mon Sep 17 00:00:00 2001 From: Geoff Willings Date: Wed, 24 Oct 2018 00:42:04 +0100 Subject: [PATCH 023/215] Json preference to not escape slashes (opinionated) --- src/SourceMap/SourceMapGenerator.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/SourceMap/SourceMapGenerator.php b/src/SourceMap/SourceMapGenerator.php index 39bfac1c..7bb005c4 100644 --- a/src/SourceMap/SourceMapGenerator.php +++ b/src/SourceMap/SourceMapGenerator.php @@ -202,7 +202,7 @@ public function generateJson() unset($sourceMap['sourceRoot']); } - return json_encode($sourceMap); + return json_encode($sourceMap, JSON_UNESCAPED_SLASHES); } /** From 94261339c3b11fdec1d230c57a54084c34a8c824 Mon Sep 17 00:00:00 2001 From: Vince Date: Wed, 13 Mar 2019 14:54:47 -0700 Subject: [PATCH 024/215] Fix for "continue" causing a warning in PHP 7.3 "continue statements targeting switch control flow structures will now generate a warning. In PHP such continue statements are equivalent to break, while they behave as continue 2 in other languages." http://php.net/manual/en/migration73.incompatible.php "In PHP the switch statement is considered a looping structure for the purposes of continue. continue behaves like break (when no arguments are passed). If a switch is inside a loop, continue 2 will continue with the next iteration of the outer loop." http://php.net/manual/en/control-structures.continue.php Signed-off-by: Vince --- tests/ScssTest.php | 42 +++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/tests/ScssTest.php b/tests/ScssTest.php index 96f0d76e..9c412fe3 100644 --- a/tests/ScssTest.php +++ b/tests/ScssTest.php @@ -75,7 +75,7 @@ public function provideTests() if (preg_match('/^\s*def test_([a-z_]+)/', $line, $matches)) { $state = 1; // enter function $name = $matches[1]; - continue; + continue 2; } break; @@ -83,7 +83,7 @@ public function provideTests() case 1: // inside function if ($line === '' || $line[0] === '#') { - continue; + continue 2; } if (preg_match('/= <<([A-Z_]+)\s*$/', $line, $matches) @@ -95,14 +95,14 @@ public function provideTests() ; } - continue; + continue 2; } if (preg_match('/^\s*assert_equal\(< e' ) { - continue; + continue 2; } if (preg_match('/^\s*end\s*$/', $line)) { @@ -168,7 +168,7 @@ public function provideTests() $scss = array(); $css = array(); $style = null; - continue; + continue 2; } $skipped[] = $line; @@ -179,9 +179,9 @@ public function provideTests() // get css if (preg_match('/^CSS\s*$/', $line)) { $state = 3; // get scss - continue; + continue 2; } - + $css[] = $lines[$i]; break; @@ -190,9 +190,9 @@ public function provideTests() // get scss if (preg_match('/^SCSS\s*$/', $line)) { $state = 1; // end of parameter list - continue; + continue 2; } - + $scss[] = $lines[$i]; break; @@ -201,12 +201,12 @@ public function provideTests() // inside block if (preg_match('/^\s*end\s*$/', $line)) { $state = 1; // end block - continue; + continue 2; } if (preg_match('/^\s*assert_equal < Date: Sun, 17 Mar 2019 23:23:12 +0200 Subject: [PATCH 025/215] Avoid infinitely duplicating parts when extending selector --- src/Compiler.php | 7 ++++++- tests/inputs/extending_compound_selector.scss | 19 +++++++++++++++++++ tests/outputs/extending_compound_selector.css | 4 ++++ .../extending_compound_selector.css | 11 +++++++++++ 4 files changed, 40 insertions(+), 1 deletion(-) create mode 100644 tests/inputs/extending_compound_selector.scss create mode 100644 tests/outputs/extending_compound_selector.css create mode 100644 tests/outputs_numbered/extending_compound_selector.css diff --git a/src/Compiler.php b/src/Compiler.php index ed80d8d3..c73f5b02 100644 --- a/src/Compiler.php +++ b/src/Compiler.php @@ -463,7 +463,12 @@ protected function matchExtends($selector, &$out, $from = 0, $initial = true) $tempReplacement = $k > 0 ? array_slice($new, $k) : $new; for ($l = count($tempReplacement) - 1; $l >= 0; $l--) { - $slice = $tempReplacement[$l]; + $slice = []; + foreach ($tempReplacement[$l] as $chunk) { + if (!in_array($chunk, $slice)) { + $slice[] = $chunk; + } + } array_unshift($replacement, $slice); if (! $this->isImmediateRelationshipCombinator(end($slice))) { diff --git a/tests/inputs/extending_compound_selector.scss b/tests/inputs/extending_compound_selector.scss new file mode 100644 index 00000000..669591fd --- /dev/null +++ b/tests/inputs/extending_compound_selector.scss @@ -0,0 +1,19 @@ +.foo { + &:after { + color: red; + } + &:hover:after { + color: blue; + } +} + +.bar { + @extend .foo; + &:before { + @extend .bar:after; + } +} + +.baz.bar:before { + @extend .bar:before; +} diff --git a/tests/outputs/extending_compound_selector.css b/tests/outputs/extending_compound_selector.css new file mode 100644 index 00000000..7e8cb599 --- /dev/null +++ b/tests/outputs/extending_compound_selector.css @@ -0,0 +1,4 @@ +.foo:after, .bar:after, .bar:before, .baz.bar:before { + color: red; } + .foo:hover:after, .bar:hover:after, .bar:before:hover, .baz.bar:before:hover { + color: blue; } diff --git a/tests/outputs_numbered/extending_compound_selector.css b/tests/outputs_numbered/extending_compound_selector.css new file mode 100644 index 00000000..50685dcf --- /dev/null +++ b/tests/outputs_numbered/extending_compound_selector.css @@ -0,0 +1,11 @@ +/* line 1, inputs/extending_compound_selector.scss */ +/* line 2, inputs/extending_compound_selector.scss */ + .foo:after, .bar:after, .bar:before, .baz.bar:before { + color: red; } +/* line 5, inputs/extending_compound_selector.scss */ +.foo:hover:after, .bar:hover:after, .bar:before:hover, .baz.bar:before:hover { + color: blue; } +/* line 10, inputs/extending_compound_selector.scss */ +/* line 12, inputs/extending_compound_selector.scss */ + +/* line 17, inputs/extending_compound_selector.scss */ From 405ebd336c86b397841eb3d17af1aa9200ca2b41 Mon Sep 17 00:00:00 2001 From: Vjacheslav Trushkin Date: Sun, 17 Mar 2019 23:56:10 +0200 Subject: [PATCH 026/215] Change private properties to protected in compiler --- src/Compiler.php | 42 +++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/src/Compiler.php b/src/Compiler.php index ed80d8d3..f9934aa2 100644 --- a/src/Compiler.php +++ b/src/Compiler.php @@ -145,18 +145,18 @@ class Compiler protected $charsetSeen; protected $sourceNames; - private $indentLevel; - private $commentsSeen; - private $extends; - private $extendsMap; - private $parsedFiles; - private $parser; - private $sourceIndex; - private $sourceLine; - private $sourceColumn; - private $stderr; - private $shouldEvaluate; - private $ignoreErrors; + protected $indentLevel; + protected $commentsSeen; + protected $extends; + protected $extendsMap; + protected $parsedFiles; + protected $parser; + protected $sourceIndex; + protected $sourceLine; + protected $sourceColumn; + protected $stderr; + protected $shouldEvaluate; + protected $ignoreErrors; /** * Constructor @@ -817,7 +817,7 @@ protected function compileAtRoot(Block $block) * * @return array */ - private function spliceTree($envs, Block $block, $without) + protected function spliceTree($envs, Block $block, $without) { $newBlock = null; @@ -894,7 +894,7 @@ private function spliceTree($envs, Block $block, $without) * * @return integer */ - private function compileWith($with) + protected function compileWith($with) { static $mapping = [ 'rule' => self::WITH_RULE, @@ -945,7 +945,7 @@ private function compileWith($with) * * @return \Leafo\ScssPhp\Compiler\Environment */ - private function filterWithout($envs, $without) + protected function filterWithout($envs, $without) { $filtered = []; @@ -968,7 +968,7 @@ private function filterWithout($envs, $without) * * @return boolean */ - private function isWithout($without, Block $block) + protected function isWithout($without, Block $block) { if ((($without & static::WITH_RULE) && isset($block->selectors)) || (($without & static::WITH_MEDIA) && @@ -2215,7 +2215,7 @@ protected function reduce($value, $inExp = false) * * @return array|null */ - private function fncall($name, $argValues) + protected function fncall($name, $argValues) { // SCSS @function if ($this->callScssFunction($name, $argValues, $returnValue)) { @@ -3016,7 +3016,7 @@ protected function multiplyMedia(Environment $env = null, $childQueries = null) * * @return array */ - private function compactEnv(Environment $env) + protected function compactEnv(Environment $env) { for ($envs = []; $env; $env = $env->parent) { $envs[] = $env; @@ -3032,7 +3032,7 @@ private function compactEnv(Environment $env) * * @return \Leafo\ScssPhp\Compiler\Environment */ - private function extractEnv($envs) + protected function extractEnv($envs) { for ($env = null; $e = array_pop($envs);) { $e->parent = $env; @@ -3864,7 +3864,7 @@ protected function applyArguments($argDef, $argValues) * * @return array|\Leafo\ScssPhp\Node\Number */ - private function coerceValue($value) + protected function coerceValue($value) { if (is_array($value) || $value instanceof \ArrayAccess) { return $value; @@ -4203,7 +4203,7 @@ public function toHSL($red, $green, $blue) * * @return float */ - private function hueToRGB($m1, $m2, $h) + protected function hueToRGB($m1, $m2, $h) { if ($h < 0) { $h += 1; From 20d88db8a832429c2a4cac035c32a63b968cb6f4 Mon Sep 17 00:00:00 2001 From: josh Date: Sun, 27 Dec 2015 13:30:27 -0700 Subject: [PATCH 027/215] add matchChar() --- src/Parser.php | 168 ++++++++++++++++++++++++++++--------------------- 1 file changed, 98 insertions(+), 70 deletions(-) diff --git a/src/Parser.php b/src/Parser.php index 748d38ae..5114cdab 100644 --- a/src/Parser.php +++ b/src/Parser.php @@ -286,7 +286,7 @@ protected function parseChunk() if ($this->literal('@at-root') && ($this->selectors($selector) || true) && ($this->map($with) || true) && - $this->literal('{') + $this->matchChar('{') ) { $atRoot = $this->pushSpecialBlock(Type::T_AT_ROOT, $s); $atRoot->selector = $selector; @@ -297,7 +297,7 @@ protected function parseChunk() $this->seek($s); - if ($this->literal('@media') && $this->mediaQueryList($mediaQueryList) && $this->literal('{')) { + if ($this->literal('@media') && $this->mediaQueryList($mediaQueryList) && $this->matchChar('{')) { $media = $this->pushSpecialBlock(Type::T_MEDIA, $s); $media->queryList = $mediaQueryList[2]; @@ -309,7 +309,7 @@ protected function parseChunk() if ($this->literal('@mixin') && $this->keyword($mixinName) && ($this->argumentDef($args) || true) && - $this->literal('{') + $this->matchChar('{') ) { $mixin = $this->pushSpecialBlock(Type::T_MIXIN, $s); $mixin->name = $mixinName; @@ -322,11 +322,11 @@ protected function parseChunk() if ($this->literal('@include') && $this->keyword($mixinName) && - ($this->literal('(') && + ($this->matchChar('(') && ($this->argValues($argValues) || true) && - $this->literal(')') || true) && + $this->matchChar(')') || true) && ($this->end() || - $this->literal('{') && $hasBlock = true) + $this->matchChar('{') && $hasBlock = true) ) { $child = [Type::T_INCLUDE, $mixinName, isset($argValues) ? $argValues : null, null]; @@ -391,7 +391,7 @@ protected function parseChunk() if ($this->literal('@function') && $this->keyword($fnName) && $this->argumentDef($args) && - $this->literal('{') + $this->matchChar('{') ) { $func = $this->pushSpecialBlock(Type::T_FUNCTION, $s); $func->name = $fnName; @@ -431,7 +431,7 @@ protected function parseChunk() $this->genericList($varNames, 'variable', ',', false) && $this->literal('in') && $this->valueList($list) && - $this->literal('{') + $this->matchChar('{') ) { $each = $this->pushSpecialBlock(Type::T_EACH, $s); @@ -448,7 +448,7 @@ protected function parseChunk() if ($this->literal('@while') && $this->expression($cond) && - $this->literal('{') + $this->matchChar('{') ) { $while = $this->pushSpecialBlock(Type::T_WHILE, $s); $while->cond = $cond; @@ -465,7 +465,7 @@ protected function parseChunk() ($this->literal('through') || ($forUntil = true && $this->literal('to'))) && $this->expression($end) && - $this->literal('{') + $this->matchChar('{') ) { $for = $this->pushSpecialBlock(Type::T_FOR, $s); $for->var = $varName[1]; @@ -478,7 +478,7 @@ protected function parseChunk() $this->seek($s); - if ($this->literal('@if') && $this->valueList($cond) && $this->literal('{')) { + if ($this->literal('@if') && $this->valueList($cond) && $this->matchChar('{')) { $if = $this->pushSpecialBlock(Type::T_IF, $s); $if->cond = $cond; $if->cases = []; @@ -535,9 +535,9 @@ protected function parseChunk() list(, $if) = $last; if ($this->literal('@else')) { - if ($this->literal('{')) { + if ($this->matchChar('{')) { $else = $this->pushSpecialBlock(Type::T_ELSE, $s); - } elseif ($this->literal('if') && $this->valueList($cond) && $this->literal('{')) { + } elseif ($this->literal('if') && $this->valueList($cond) && $this->matchChar('{')) { $else = $this->pushSpecialBlock(Type::T_ELSEIF, $s); $else->cond = $cond; } @@ -576,10 +576,10 @@ protected function parseChunk() $this->seek($s); // doesn't match built in directive, do generic one - if ($this->literal('@', false) && + if ($this->matchChar('@', false) && $this->keyword($dirName) && ($this->variable($dirValue) || $this->openString('{', $dirValue) || true) && - $this->literal('{') + $this->matchChar('{') ) { if ($dirName === 'media') { $directive = $this->pushSpecialBlock(Type::T_MEDIA, $s); @@ -617,7 +617,7 @@ protected function parseChunk() // variable assigns if ($this->variable($name) && - $this->literal(':') && + $this->matchChar(':') && $this->valueList($value) && $this->end() ) { @@ -636,7 +636,7 @@ protected function parseChunk() } // opening css block - if ($this->selectors($selectors) && $this->literal('{')) { + if ($this->selectors($selectors) && $this->matchChar('{')) { $this->pushBlock($selectors, $s); return true; @@ -645,7 +645,7 @@ protected function parseChunk() $this->seek($s); // property assign, or nested assign - if ($this->propertyName($name) && $this->literal(':')) { + if ($this->propertyName($name) && $this->matchChar(':')) { $foundSomething = false; if ($this->valueList($value)) { @@ -653,7 +653,7 @@ protected function parseChunk() $foundSomething = true; } - if ($this->literal('{')) { + if ($this->matchChar('{')) { $propBlock = $this->pushSpecialBlock(Type::T_NESTED_PROPERTY, $s); $propBlock->prefix = $name; $foundSomething = true; @@ -669,7 +669,7 @@ protected function parseChunk() $this->seek($s); // closing a block - if ($this->literal('}')) { + if ($this->matchChar('}')) { $block = $this->popBlock(); if (isset($block->type) && $block->type === Type::T_INCLUDE) { @@ -686,7 +686,7 @@ protected function parseChunk() } // extra stuff - if ($this->literal(';') || + if ($this->matchChar(';') || $this->literal('')) { + if ($this->literal('-->', 3)) { return true; } @@ -687,7 +687,7 @@ protected function parseChunk() // extra stuff if ($this->matchChar(';') || - $this->literal('