Merge pull request #12 from winstonewert/master

Fixes a bug in the CSS string escape handling.
diff --git a/CHANGELOG.md b/CHANGELOG.md
index b8c2a6d..4d14f0b 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,7 @@
+## 0.12.1
+
+ * Fix to handling of escapes in strings.
+
 ## 0.12.0+1
 
 * Allow the lastest version of `logging` package.
diff --git a/lib/parser.dart b/lib/parser.dart
index 1ca391c..8692693 100644
--- a/lib/parser.dart
+++ b/lib/parser.dart
@@ -2363,8 +2363,8 @@
 
     // Note: disable skipping whitespace tokens inside a string.
     // TODO(jmesserly): the layering here feels wrong.
-    var skipWhitespace = tokenizer._skipWhitespace;
-    tokenizer._skipWhitespace = false;
+    var inString = tokenizer._inString;
+    tokenizer._inString = false;
 
     switch (_peek()) {
       case TokenKind.SINGLE_QUOTE:
@@ -2396,7 +2396,7 @@
       stringValue.write(_next().text);
     }
 
-    tokenizer._skipWhitespace = skipWhitespace;
+    tokenizer._inString = inString;
 
     // All characters between quotes is the string.
     if (stopToken != TokenKind.RPAREN) {
diff --git a/lib/src/tokenizer.dart b/lib/src/tokenizer.dart
index f5c5210..d423104 100644
--- a/lib/src/tokenizer.dart
+++ b/lib/src/tokenizer.dart
@@ -273,7 +273,7 @@
       // if followed by hexadecimal digits, create the appropriate character.
       // otherwise, include the character in the identifier and don't treat it
       // specially.
-      if (ch == 92 /*\*/) {
+      if (ch == 92 /*\*/ && _inString) {
         int startHex = ++_index;
         eatHexDigits(startHex + 6);
         if (_index != startHex) {
@@ -395,7 +395,7 @@
         return _finishToken(TokenKind.INCOMPLETE_COMMENT);
       } else if (ch == 42 /*'*'*/) {
         if (_maybeEatChar(47 /*'/'*/)) {
-          if (_skipWhitespace) {
+          if (_inString) {
             return next();
           } else {
             return _finishToken(TokenKind.COMMENT);
@@ -405,7 +405,7 @@
         /* Check if close part of Comment Definition --> (CDC). */
         if (_maybeEatChar(TokenChar.MINUS)) {
           if (_maybeEatChar(TokenChar.GREATER)) {
-            if (_skipWhitespace) {
+            if (_inString) {
               return next();
             } else {
               return _finishToken(TokenKind.HTML_COMMENT);
diff --git a/lib/src/tokenizer_base.dart b/lib/src/tokenizer_base.dart
index 8c52fb0..663c987 100644
--- a/lib/src/tokenizer_base.dart
+++ b/lib/src/tokenizer_base.dart
@@ -27,7 +27,7 @@
   final SourceFile _file;
   final String _text;
 
-  bool _skipWhitespace;
+  bool _inString;
 
   /**
    * Changes tokenization when in a pseudo function expression.  If true then
@@ -55,7 +55,7 @@
   int _index = 0;
   int _startIndex = 0;
 
-  TokenizerBase(this._file, this._text, this._skipWhitespace,
+  TokenizerBase(this._file, this._text, this._inString,
       [this._index = 0]);
 
   Token next();
@@ -119,12 +119,12 @@
           ch == TokenChar.RETURN) {
         // do nothing
       } else if (ch == TokenChar.NEWLINE) {
-        if (!_skipWhitespace) {
+        if (!_inString) {
           return _finishToken(TokenKind.WHITESPACE); // note the newline?
         }
       } else {
         _index--;
-        if (_skipWhitespace) {
+        if (_inString) {
           return next();
         } else {
           return _finishToken(TokenKind.WHITESPACE);
@@ -151,7 +151,7 @@
       }
     } while (nesting > 0);
 
-    if (_skipWhitespace) {
+    if (_inString) {
       return next();
     } else {
       return _finishToken(TokenKind.COMMENT);
diff --git a/pubspec.yaml b/pubspec.yaml
index 01051d3..70923da 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -1,5 +1,5 @@
 name: csslib
-version: 0.12.0+1
+version: 0.12.1
 author: Polymer.dart Team <web-ui-dev@dartlang.org>
 description: A library for parsing CSS.
 homepage: https://github.com/dart-lang/csslib
diff --git a/test/compiler_test.dart b/test/compiler_test.dart
index 88b7a2d..df5a44a 100644
--- a/test/compiler_test.dart
+++ b/test/compiler_test.dart
@@ -677,6 +677,19 @@
 }''');
 }
 
+void testStringEscape() {
+  var errors = [];
+  var input = r'''a { foo: '{"text" : "a\\\""}' }''';
+  var stylesheet = parseCss(input, errors: errors, opts: simpleOptions);
+  expect(stylesheet != null, true);
+  expect(errors.isEmpty, true, reason: errors.toString());
+
+  expect(prettyPrint(stylesheet), r'''
+a {
+  foo: '{"text" : "a\\\""}';
+}''');
+}
+
 // TODO(terry): Move to emitter_test.dart when real emitter exist.
 void testEmitter() {
   var errors = [];
@@ -721,6 +734,7 @@
   test('Attributes', testAttribute);
   test('Negation', testNegation);
   test('@host', testHost);
+  test('stringEscape', testStringEscape);
   test('Parse List<int> as input', testArrayOfChars);
   test('Simple Emitter', testEmitter);
 }