From: Jakub Pawlowicz Date: Sun, 1 Feb 2015 11:52:54 +0000 (+0000) Subject: Fixes #449 - missing close brace in a selector. X-Git-Url: https://git.ndcode.org/public/gitweb.cgi?a=commitdiff_plain;h=e23659fc03e6e5ec1a38f456519ab477e971e469;p=clean-css.git Fixes #449 - missing close brace in a selector. Adds proper handling of missing closing brace in selectory body: * warning is raised; * extra content is ignored. --- diff --git a/History.md b/History.md index e70067fc..d279e015 100644 --- a/History.md +++ b/History.md @@ -13,6 +13,7 @@ * Fixed issue [#439](https://github.com/GoalSmashers/clean-css/issues/439) - `background-origin` in shorthand. * Fixed issue [#442](https://github.com/GoalSmashers/clean-css/issues/442) - space before adjacent `nav`. * Fixed issue [#445](https://github.com/GoalSmashers/clean-css/issues/445) - regression issue in url processor. +* Fixed issue [#449](https://github.com/GoalSmashers/clean-css/issues/449) - warns of missing close braces. [3.0.8 / 2015-01-31](https://github.com/jakubpawlowicz/clean-css/compare/v3.0.7...v3.0.8) ================== diff --git a/lib/selectors/tokenizer.js b/lib/selectors/tokenizer.js index 9839a5c6..79e49474 100644 --- a/lib/selectors/tokenizer.js +++ b/lib/selectors/tokenizer.js @@ -96,7 +96,11 @@ function tokenize(context) { if (!next) { var whatsLeft = context.chunk.substring(context.cursor); if (whatsLeft.trim().length > 0) { - tokenized.push({ kind: 'text', value: whatsLeft }); + if (context.mode == 'body') { + context.outer.warnings.push('Missing \'}\' after \'' + whatsLeft + '\'. Ignoring.'); + } else { + tokenized.push({ kind: 'text', value: whatsLeft }); + } context.cursor += whatsLeft.length; } break; diff --git a/lib/utils/extractors.js b/lib/utils/extractors.js index d8b4c47a..e19c7681 100644 --- a/lib/utils/extractors.js +++ b/lib/utils/extractors.js @@ -50,12 +50,14 @@ var Extractors = { buffer.pop(); if (buffer.length > 0) { property = buffer.join(''); - token = { value: property }; - tokenized.push(token); - list.push(property); + if (property.indexOf('{') === -1) { + token = { value: property }; + tokenized.push(token); + list.push(property); - if (addSourceMap) - token.metadata = SourceMaps.saveAndTrack(all.join(''), context, !isEscape); + if (addSourceMap) + token.metadata = SourceMaps.saveAndTrack(all.join(''), context, !isEscape); + } } buffer = []; all = []; @@ -89,12 +91,14 @@ var Extractors = { buffer.pop(); if (buffer.length > 0) { property = buffer.join(''); - token = { value: property }; - tokenized.push(token); - list.push(property); + if (property.indexOf('{') === -1) { + token = { value: property }; + tokenized.push(token); + list.push(property); - if (addSourceMap) - token.metadata = SourceMaps.saveAndTrack(all.join(''), context, false); + if (addSourceMap) + token.metadata = SourceMaps.saveAndTrack(all.join(''), context, false); + } } else if (all.indexOf('\n') > -1) { SourceMaps.track(all.join(''), context); } diff --git a/test/integration-test.js b/test/integration-test.js index bf637b19..31ce082f 100644 --- a/test/integration-test.js +++ b/test/integration-test.js @@ -919,7 +919,7 @@ vows.describe('integration tests').addBatch({ ], 'cut off url content on top level': [ '@font-face{src:url(data:application/x-font-woff;base64,d09GRk9UVE8AAENAAA0AAAAA', - '@font-face{src:url(data:application/x-font-woff;base64,d09GRk9UVE8AAENAAA0AAAAA}' + '' ], 'strip single parentheses': [ "a{background:url('/images/blank.png')}", diff --git a/test/module-test.js b/test/module-test.js index ab4a8234..3e32f2a3 100644 --- a/test/module-test.js +++ b/test/module-test.js @@ -116,6 +116,19 @@ vows.describe('module tests').addBatch({ assert.equal(minified.warnings[0], 'Unexpected \'}\' in \'a{display:block}}\'. Ignoring.'); } }, + 'warnings on missing closing brace': { + 'topic': new CleanCSS().minify('a{display:block'), + 'should minify correctly': function (error, minified) { + assert.equal(minified.styles, ''); + }, + 'should raise no errors': function (error, minified) { + assert.isEmpty(minified.errors); + }, + 'should raise one warning': function (error, minified) { + assert.lengthOf(minified.warnings, 1); + assert.equal(minified.warnings[0], 'Missing \'}\' after \'display:block\'. Ignoring.'); + } + }, 'warnings on unexpected body': { 'topic': new CleanCSS().minify('a{display:block}color:#535353}p{color:red}'), 'should minify correctly': function (error, minified) { diff --git a/test/selectors/tokenizer-test.js b/test/selectors/tokenizer-test.js index 153e719c..f3be5223 100644 --- a/test/selectors/tokenizer-test.js +++ b/test/selectors/tokenizer-test.js @@ -8,7 +8,7 @@ function tokenizerContext(name, specs, addMetadata) { function tokenized(target) { return function (source) { - var tokenized = new Tokenizer({ sourceTracker: new SourceTracker() }, addMetadata).toTokens(source); + var tokenized = new Tokenizer({ sourceTracker: new SourceTracker(), warnings: [] }, addMetadata).toTokens(source); assert.deepEqual(target, tokenized); }; } @@ -230,6 +230,26 @@ vows.describe(Tokenizer) ] }) ) + .addBatch( + tokenizerContext('broken', { + 'missing end brace': [ + 'a{display:block', + [{ + kind: 'selector', + value: [{ value: 'a' }], + body: [] + }] + ], + 'missing end brace in the middle': [ + 'body{color:red;a{color:blue;}', + [{ + kind: 'selector', + value: [{ value: 'body' }], + body: [{ value: 'color:red' }] + }] + ] + }) + ) .addBatch( tokenizerContext('metadata', { 'no content': [