From 97f62d266d461723395e25de966d17a72b19bc09 Mon Sep 17 00:00:00 2001 From: Anthon Pang Date: Fri, 29 Mar 2013 09:30:22 +0000 Subject: [PATCH] build more accurate parse tree containing comment nodes --- scss.inc.php | 79 +++++++++++++++++++------- tests/inputs/comments.scss | 16 ++++++ tests/outputs/comments.css | 22 ++++++-- tests/outputs/scss_css.css | 110 +++++++++++++++++++++++-------------- 4 files changed, 163 insertions(+), 64 deletions(-) diff --git a/scss.inc.php b/scss.inc.php index cc2ba60a..4e649741 100644 --- a/scss.inc.php +++ b/scss.inc.php @@ -351,6 +351,13 @@ protected function compileBlock($block) { $this->popEnv(); } + // root level comment + protected function compileComment($block) { + $out = $this->makeOutputBlock('comment'); + $out->lines[] = $block[1]; + $this->scope->children[] = $out; + } + // joins together .classes and #ids protected function flattenSelectorSingle($single) { $joined = array(); @@ -563,6 +570,11 @@ protected function compileChild($child, $out) { $compiledValue); break; case "comment": + if ($out->type == 'root') { + $this->compileComment($child); + break; + } + $out->lines[] = $child[1]; break; case "mixin": @@ -2496,7 +2508,6 @@ function parse($buffer) { $this->inParens = false; $this->pushBlock(null); // root block $this->eatWhiteDefault = true; - $this->insertComments = true; $this->buffer = $buffer; @@ -2758,16 +2769,12 @@ protected function parseChunk() { } // opening css block - $oldComments = $this->insertComments; - $this->insertComments = false; if ($this->selectors($selectors) && $this->literal("{")) { - $this->pushBlock($selectors); - $this->insertComments = $oldComments; + $b = $this->pushBlock($selectors); return true; } else { $this->seek($s); } - $this->insertComments = $oldComments; // property assign, or nested assign if ($this->propertyName($name) && $this->literal(":")) { @@ -2845,7 +2852,18 @@ protected function pushBlock($selectors) { $b->parent = $this->env; // not sure if we need this yet $b->selectors = $selectors; - $b->children = array(); + $b->comments = array(); + + if (!$this->env) { + $b->children = array(); + } elseif (empty($this->env->children)) { + $this->env->children = $this->env->comments; + $b->children = array(); + $this->env->comments = array(); + } else { + $b->children = $this->env->comments; + $this->env->comments = array(); + } $this->env = $b; return $b; @@ -2858,14 +2876,26 @@ protected function pushSpecialBlock($type) { } protected function popBlock() { - if (empty($this->env->parent)) { + $block = $this->env; + + if (empty($block->parent)) { $this->throwParseError("unexpected }"); } - $old = $this->env; - $this->env = $this->env->parent; - unset($old->parent); - return $old; + $this->env = $block->parent; + unset($block->parent); + + $comments = $block->comments; + if (count($comments)) { + $this->env->comments = $comments; + unset($block->comments); + } + + return $block; + } + + protected function appendComment($comment) { + $this->env->comments[] = $comment; } protected function append($statement, $pos=null) { @@ -2873,7 +2903,14 @@ protected function append($statement, $pos=null) { $statement[-1] = $pos; if (!$this->rootParser) $statement[-2] = $this; } + $this->env->children[] = $statement; + + $comments = $this->env->comments; + if (count($comments)) { + $this->env->children = array_merge($this->env->children, $comments); + $this->env->comments = array(); + } } // last child that was appended @@ -3455,7 +3492,9 @@ protected function interpolation(&$out, $lookWhite=true) { $out = array("interpolate", $value, $left, $right); $this->eatWhiteDefault = $oldWhite; - if ($this->eatWhiteDefault) $this->whitespace(); + if ($this->eatWhiteDefault) { + $this->whitespace(); + } return true; } @@ -3534,7 +3573,7 @@ protected function selector(&$out) { $selector[] = array($m[0]); } elseif ($this->selectorSingle($part)) { $selector[] = $part; - $this->whitespace(); + $this->match('\s+', $m); } elseif ($this->match('\/[^\/]+\/', $m)) { $selector[] = array($m[0]); } else { @@ -3782,7 +3821,9 @@ protected function match($regex, &$out, $eatWhitespace = null) { $r = '/'.$regex.'/Ais'; if (preg_match($r, $this->buffer, $out, null, $this->count)) { $this->count += strlen($out[0]); - if ($eatWhitespace) $this->whitespace(); + if ($eatWhitespace) { + $this->whitespace(); + } return true; } return false; @@ -3792,11 +3833,9 @@ protected function match($regex, &$out, $eatWhitespace = null) { protected function whitespace() { $gotWhite = false; while (preg_match(self::$whitePattern, $this->buffer, $m, null, $this->count)) { - if ($this->insertComments) { - if (isset($m[1]) && empty($this->commentsSeen[$this->count])) { - $this->append(array("comment", $m[1])); - $this->commentsSeen[$this->count] = true; - } + if (isset($m[1]) && empty($this->commentsSeen[$this->count])) { + $this->appendComment(array("comment", $m[1])); + $this->commentsSeen[$this->count] = true; } $this->count += strlen($m[0]); $gotWhite = true; diff --git a/tests/inputs/comments.scss b/tests/inputs/comments.scss index 513281b4..ddea43e6 100644 --- a/tests/inputs/comments.scss +++ b/tests/inputs/comments.scss @@ -25,3 +25,19 @@ Here is a block comment background: url(/*this is not a comment?*/); // uhh what happens here } +// begin + +.dummy { + color: blue; +} + +/* comment 1 */ +a { + /* comment 2 */ + /* comment 3 */ color: red; /* comment 4 */ + background-color: red; /* comment 5 */ + /* comment 6 */ +} +/* comment 7 */ + +// end diff --git a/tests/outputs/comments.css b/tests/outputs/comments.css index 751ddfe4..fb789b5e 100644 --- a/tests/outputs/comments.css +++ b/tests/outputs/comments.css @@ -5,15 +5,29 @@ Here is a block comment **/ /*hello*/ +/*yeah*/ div { - /* another property */ border: 1px solid red; + /* another property */ color: url('http://mage-page.com'); string: "hello /* this is not a comment */"; world: "// neither is this"; - /*what if this is a comment */ string: 'hello /* this is not a comment */'; + /*what if this is a comment */ world: '// neither is this'; what-ever: 100px; - /*this is not a comment?*/ - background: url(); } + background: url(); + /*this is not a comment?*/ } + +.dummy { + color: blue; } +/* comment 1 */ +a { + /* comment 2 */ + /* comment 3 */ + color: red; + /* comment 4 */ + background-color: red; + /* comment 5 */ + /* comment 6 */ } +/* comment 7 */ diff --git a/tests/outputs/scss_css.css b/tests/outputs/scss_css.css index 21af8e6b..485d3e25 100644 --- a/tests/outputs/scss_css.css +++ b/tests/outputs/scss_css.css @@ -5,10 +5,6 @@ @import url(foo.css); @import "foo.css" screen; @import "foo.css" screen, print; -/* Foo - * Bar */ -/* Baz - * Bang */ @charset "UTF-8"; [foo~=bar] { a: b; } @@ -42,15 +38,26 @@ sel { p: v; } .foo { + /* Foo +Bar + Baz */ a: b; } .foo { + /* Foo +Bar + Baz */ a: b; } .foo { + /* Foo + Bar */ a: b; } .foo { + /* Foo + Bar + Baz */ a: b; } @foo { @@ -79,11 +86,10 @@ bar { bar: baz; } baz { - bar: baz; - /* + bar: baz; } +/* * foo - */ } - + */ bar { baz: bang; } @@ -94,33 +100,27 @@ E F, G H { a: b; } E > F, G > H { - a: b; - /* This is a CSS comment. */ } - + a: b; } +/* This is a CSS comment. */ .one { - color: green; - /* Another comment */ - /* The following should not be used: -.two {color: red;} */ } - + color: green; } +/* Another comment */ +/* The following should not be used: +.two {color: red;} */ .three { - /* color: red; */ color: green; - /** -.four {color: red;} */ } - + /* color: red; */ } +/** +.four {color: red;} */ .five { - color: green; - /**/ } - + color: green; } +/**/ .six { - color: green; - /*********/ } - + color: green; } +/*********/ .seven { - color: green; - /* a comment **/ } - + color: green; } +/* a comment **/ .eight { color: green; } @@ -217,14 +217,17 @@ foo { b: foo -o-bar-baz; } foo { - /* b; c: */ - a: d; } + a: d; + /* b; c: */ } foo { - /*: b; c */ a : d; + /*: b; c */ } +/* Foo + * Bar */ +.foo { /* Foo - * Bar */ } + * Bar */ } [foo] { a: b; } @@ -385,6 +388,26 @@ foo { @bar baz { c: d; } +@foo bar; +@bar baz; + + +/* Foo + * Bar */ +/* Baz + * Bang */ + + +.foo { + /* Foo + * Bar */ + /* Baz + * Bang */ } + +.foo { + /* Foo Bar */ + /* Baz Bang */ } + @namespace "http://www.w3.org/Profiles/xhtml1-strict"; @namespace url(http://www.w3.org/Profiles/xhtml1-strict); @@ -522,21 +545,23 @@ foo { prop2: val; } .foo { + /* Foo */ a: b; } .foo { - a: b; - /* Foo */ } - -.foo { - a: b; /* Foo - * Bar */ } - + * Bar */ + a: b; } +/* Foo */ +.foo { + a: b; } +/* Foo + * Bar */ .foo { a: b; } .foo #bar:baz(/* bang )*/ bip) { + /* .a #foo */ a: b; } > E { @@ -572,6 +597,11 @@ E F { E, F G, H { a: b; } +body { + /* + //comment here + */ } + E > F { a: b; }