Fixes #177 - processing incorrect content should not break CSS.
authorGoalSmashers <jakub@goalsmashers.com>
Mon, 18 Nov 2013 21:01:37 +0000 (22:01 +0100)
committerGoalSmashers <jakub@goalsmashers.com>
Mon, 18 Nov 2013 21:51:21 +0000 (22:51 +0100)
* Adds a warning on an incorrect content or a closing parenthesis.

History.md
lib/clean.js
lib/selectors/optimizer.js
lib/selectors/tokenizer.js
test/module-test.js

index 36b1c91..887ba29 100644 (file)
@@ -7,6 +7,11 @@
 * Fixed issue [#163](https://github.com/GoalSmashers/clean-css/issues/163) - round pixels to 2nd decimal place.
 * Fixed issue [#165](https://github.com/GoalSmashers/clean-css/issues/165) - extra space after trailing parenthesis.
 
+[2.0.2 / 2013-xx-xx (UNRELEASED)](https://github.com/GoalSmashers/clean-css/compare/v2.0.1...HEAD)
+==================
+
+* Fixed issue [#177](https://github.com/GoalSmashers/clean-css/issues/177) - process broken content correctly.
+
 [2.0.1 / 2013-11-14](https://github.com/GoalSmashers/clean-css/compare/v2.0.0...v2.0.1)
 ==================
 
index bb277b2..fdbf67a 100644 (file)
@@ -265,7 +265,7 @@ module.exports = function(options) {
 
     if (!options.noAdvanced) {
       replace(function optimizeSelectors() {
-        data = new SelectorsOptimizer(data, {
+        data = new SelectorsOptimizer(data, context, {
           keepBreaks: options.keepBreaks,
           lineBreak: lineBreak,
           selectorsMergeMode: options.selectorsMergeMode
index ed683ea..256baa6 100644 (file)
@@ -1,7 +1,7 @@
 var Tokenizer = require('./tokenizer');
 var PropertyOptimizer = require('../properties/optimizer');
 
-module.exports = function Optimizer(data, options) {
+module.exports = function Optimizer(data, context, options) {
   var specialSelectors = {
     '*': /\-(moz|ms|o|webkit)\-/,
     'ie8': /(\-moz\-|\-ms\-|\-o\-|\-webkit\-|:not|:target|:visited|:empty|:first\-of|:last|:nth|:only|:root)/
@@ -257,7 +257,7 @@ module.exports = function Optimizer(data, options) {
 
   return {
     process: function() {
-      var tokenized = new Tokenizer(data).process();
+      var tokenized = new Tokenizer(data, context).process();
       optimize(tokenized);
       return rebuild(tokenized);
     }
index 8edaf75..a7f09b0 100644 (file)
@@ -1,6 +1,6 @@
 /* jshint latedef: false */
 
-module.exports = function Tokenizer(data) {
+module.exports = function Tokenizer(data, minifyContext) {
   var chunker = new Chunker(data, 128);
   var chunk = chunker.next();
 
@@ -109,8 +109,14 @@ module.exports = function Tokenizer(data) {
         tokenized.push({ selector: selector, body: body });
       } else if (what == 'bodyEnd') {
         // extra closing brace at the top level can be safely ignored
-        if (context.mode == 'top' && data[context.cursor] == '}') {
-          context.cursor += 1;
+        if (context.mode == 'top') {
+          var at = context.cursor;
+          var warning = chunk[context.cursor] == '}' ?
+            'Unexpected \'}\' in \'' + chunk.substring(at - 20, at + 20) + '\'. Ignoring.' :
+            'Unexpected content: \'' + chunk.substring(at, nextSpecial + 1) + '\'. Ignoring.';
+
+          minifyContext.warnings.push(warning);
+          context.cursor = nextSpecial + 1;
           continue;
         }
 
index eac87a4..4e83108 100644 (file)
@@ -64,6 +64,40 @@ vows.describe('module tests').addBatch({
       assert.match(minifier.warnings[0], /Both 'root' and output file given/);
     }
   },
+  'warnings on extra closing brace': {
+    topic: function() {
+      var minifier = new CleanCSS();
+      var minified = minifier.minify('a{display:block}}');
+      this.callback(null, minified, minifier);
+    },
+    'should minify correctly': function(error, minified) {
+      assert.equal(minified, 'a{display:block}');
+    },
+    'should raise no errors': function(error, minified, minifier) {
+      assert.equal(minifier.errors.length, 0);
+    },
+    'should raise one warning': function(error, minified, minifier) {
+      assert.equal(minifier.warnings.length, 1);
+      assert.equal(minifier.warnings[0], 'Unexpected \'}\' in \'a{display:block}}\'. Ignoring.');
+    }
+  },
+  'warnings on unexpected body': {
+    topic: function() {
+      var minifier = new CleanCSS();
+      var minified = minifier.minify('a{display:block}color:#535353}p{color:red}');
+      this.callback(null, minified, minifier);
+    },
+    'should minify correctly': function(error, minified) {
+      assert.equal(minified, 'a{display:block}p{color:red}');
+    },
+    'should raise no errors': function(error, minified, minifier) {
+      assert.equal(minifier.errors.length, 0);
+    },
+    'should raise one warning': function(error, minified, minifier) {
+      assert.equal(minifier.warnings.length, 1);
+      assert.equal(minifier.warnings[0], 'Unexpected content: \'color:#535353}\'. Ignoring.');
+    }
+  },
   'no errors': {
     topic: function() {
       var minifier = new CleanCSS();