From 6d4858fadbe4ff1660c4ec30904f8b842fb221c8 Mon Sep 17 00:00:00 2001 From: GoalSmashers Date: Mon, 18 Nov 2013 22:01:37 +0100 Subject: [PATCH] Fixes #177 - processing incorrect content should not break CSS. * Adds a warning on an incorrect content or a closing parenthesis. --- History.md | 5 +++++ lib/clean.js | 2 +- lib/selectors/optimizer.js | 4 ++-- lib/selectors/tokenizer.js | 12 +++++++++--- test/module-test.js | 34 ++++++++++++++++++++++++++++++++++ 5 files changed, 51 insertions(+), 6 deletions(-) diff --git a/History.md b/History.md index 36b1c915..887ba297 100644 --- a/History.md +++ b/History.md @@ -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) ================== diff --git a/lib/clean.js b/lib/clean.js index bb277b2d..fdbf67a8 100644 --- a/lib/clean.js +++ b/lib/clean.js @@ -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 diff --git a/lib/selectors/optimizer.js b/lib/selectors/optimizer.js index ed683ea1..256baa67 100644 --- a/lib/selectors/optimizer.js +++ b/lib/selectors/optimizer.js @@ -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); } diff --git a/lib/selectors/tokenizer.js b/lib/selectors/tokenizer.js index 8edaf756..a7f09b04 100644 --- a/lib/selectors/tokenizer.js +++ b/lib/selectors/tokenizer.js @@ -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; } diff --git a/test/module-test.js b/test/module-test.js index eac87a4b..4e831088 100644 --- a/test/module-test.js +++ b/test/module-test.js @@ -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(); -- 2.34.1