From b5e3ad3e5b75bc6e83483ac927e2c40fad05829b Mon Sep 17 00:00:00 2001 From: Anthon Pang Date: Wed, 27 Feb 2013 19:56:42 +0000 Subject: [PATCH 1/5] apply @nessy patch and add test case --- scss.inc.php | 9 ++++++--- tests/inputs/extends.scss | 12 ++++++++++++ tests/outputs/extends.css | 3 +++ 3 files changed, 21 insertions(+), 3 deletions(-) diff --git a/scss.inc.php b/scss.inc.php index 47db2d57..d9737e5e 100644 --- a/scss.inc.php +++ b/scss.inc.php @@ -130,6 +130,9 @@ protected function matchExtendsSingle($single, &$out_origin, &$out_rem) { } } + $out_origin = array(); + $found = false; + foreach ($counts as $idx => $count) { list($target, $origin) = $this->extends[$idx]; // check count @@ -137,13 +140,13 @@ protected function matchExtendsSingle($single, &$out_origin, &$out_rem) { // check if target is subset of single if (array_diff(array_intersect($single, $target), $target)) continue; - $out_origin = $origin; + $out_origin = array_merge($out_origin, $origin); $out_rem = array_diff($single, $target); - return true; + $found = true; } - return false; + return $found; } protected function combineSelectorSingle($base, $other) { diff --git a/tests/inputs/extends.scss b/tests/inputs/extends.scss index cd6ad526..3503ec86 100644 --- a/tests/inputs/extends.scss +++ b/tests/inputs/extends.scss @@ -131,3 +131,15 @@ wassup { color: blue; } } + +#something { + color: red; +} + +.x { + @extend #something; +} + +.y { + @extend #something; +} diff --git a/tests/outputs/extends.css b/tests/outputs/extends.css index 724cb5e8..e18da2db 100644 --- a/tests/outputs/extends.css +++ b/tests/outputs/extends.css @@ -70,3 +70,6 @@ wassup { .foo .wassup { color: blue; } + +#something, .x, .y { + color: red; } From 441dd7c669984cced15452b3b04525e4f4700b9d Mon Sep 17 00:00:00 2001 From: Anthon Pang Date: Wed, 27 Feb 2013 23:03:49 +0000 Subject: [PATCH 2/5] update expected results (this test currently fails) --- tests/outputs/extends.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/outputs/extends.css b/tests/outputs/extends.css index e18da2db..c3cf7b24 100644 --- a/tests/outputs/extends.css +++ b/tests/outputs/extends.css @@ -16,7 +16,7 @@ hello { .blue, .me { color: purple; } -a:hover, .hoverlink { +:hover, .hoverlink, #demo .overview .fakelink:hover { text-decoration: underline; } 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 { From 9ae2f82b7cc220e07c7a99f9d8821efa69a1f98e Mon Sep 17 00:00:00 2001 From: Anthon Pang Date: Wed, 27 Feb 2013 23:12:59 +0000 Subject: [PATCH 3/5] add test case for multi-extends with nesting (another failing test) --- tests/inputs/extends.scss | 28 ++++++++++++++++++++++++++++ tests/outputs/extends.css | 11 ++++++++++- 2 files changed, 38 insertions(+), 1 deletion(-) diff --git a/tests/inputs/extends.scss b/tests/inputs/extends.scss index 3503ec86..c6b1bde8 100644 --- a/tests/inputs/extends.scss +++ b/tests/inputs/extends.scss @@ -132,6 +132,8 @@ wassup { } } +// multi-extend + #something { color: red; } @@ -143,3 +145,29 @@ wassup { .y { @extend #something; } + +// multi-extend with nesting + +.btn:hover, +.btn:active, +.btn.active, +.btn.disabled, +.btn[disabled] { + color: red; +} +.edit .actions { + button { + float: right; + @extend .btn; + } +} +.edit { + .new { + .actions { + padding: 0; + } + .actions button { + @extend .btn; + } + } +} diff --git a/tests/outputs/extends.css b/tests/outputs/extends.css index c3cf7b24..23d04243 100644 --- a/tests/outputs/extends.css +++ b/tests/outputs/extends.css @@ -16,7 +16,7 @@ hello { .blue, .me { color: purple; } -:hover, .hoverlink, #demo .overview .fakelink:hover { +a:hover, .hoverlink, #demo .overview .fakelink:hover { text-decoration: underline; } 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 { @@ -73,3 +73,12 @@ wassup { #something, .x, .y { color: red; } + +.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; } + +.edit .actions button { + float: right; } + +.edit .new .actions { + padding: 0; } From 7b564f53eb4e8a1b507fad161540811391817105 Mon Sep 17 00:00:00 2001 From: Anthon Pang Date: Thu, 28 Feb 2013 15:17:51 +0000 Subject: [PATCH 4/5] upcase references to Exception class --- scss.inc.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scss.inc.php b/scss.inc.php index d9737e5e..13c98db4 100644 --- a/scss.inc.php +++ b/scss.inc.php @@ -1538,7 +1538,7 @@ protected function coerceString($value) { protected function assertList($value) { if ($value[0] != "list") - throw new exception("expecting list"); + throw new Exception("expecting list"); return $value; } @@ -3924,7 +3924,7 @@ public function serve() { if ($this->needsCompile($input, $output)) { try { echo $this->compile($input, $output); - } catch (exception $e) { + } catch (Exception $e) { header('HTTP/1.1 500 Internal Server Error'); echo "Parse error: " . $e->getMessage() . "\n"; } From 45efd5b5f81c10766b39285134ee843f68ebe0a9 Mon Sep 17 00:00:00 2001 From: Anthon Pang Date: Thu, 28 Feb 2013 18:49:20 +0000 Subject: [PATCH 5/5] fixing @extend combineSelectorSingle() --- scss.inc.php | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/scss.inc.php b/scss.inc.php index 13c98db4..2c50706a 100644 --- a/scss.inc.php +++ b/scss.inc.php @@ -117,7 +117,7 @@ protected function makeOutputBlock($type, $selectors = null) { return $out; } - protected function matchExtendsSingle($single, &$out_origin, &$out_rem) { + protected function matchExtendsSingle($single, &$out_origin) { $counts = array(); foreach ($single as $part) { if (!is_string($part)) return false; // hmm @@ -135,13 +135,20 @@ protected function matchExtendsSingle($single, &$out_origin, &$out_rem) { foreach ($counts as $idx => $count) { list($target, $origin) = $this->extends[$idx]; + // check count if ($count != count($target)) continue; + // 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) { + $origin[$j][count($origin[$j]) - 1] = $this->combineSelectorSingle(end($new), $rem); + } + $out_origin = array_merge($out_origin, $origin); - $out_rem = array_diff($single, $target); $found = true; } @@ -155,7 +162,7 @@ protected function combineSelectorSingle($base, $other) { foreach (array($base, $other) as $single) { foreach ($single as $part) { - if (preg_match('/^[^.#:]/', $part)) { + if (preg_match('/^[^\[.#:]/', $part)) { $tag = $part; } else { $out[] = $part; @@ -174,15 +181,13 @@ protected function matchExtends($selector, &$out, $from = 0, $initial=true) { foreach ($selector as $i => $part) { if ($i < $from) continue; - if ($this->matchExtendsSingle($part, $origin, $rem)) { + if ($this->matchExtendsSingle($part, $origin)) { $before = array_slice($selector, 0, $i); $after = array_slice($selector, $i + 1); foreach ($origin as $new) { - $new[count($new) - 1] = - $this->combineSelectorSingle(end($new), $rem); - $k = 0; + // remove shared parts if ($initial) { foreach ($before as $k => $val) { @@ -320,7 +325,7 @@ protected function flattenSelectorSingle($single) { foreach ($single as $part) { if (empty($joined) || !is_string($part) || - preg_match('/[.:#%]/', $part)) + preg_match('/[\[.:#%]/', $part)) { $joined[] = $part; continue;