From 2bd984ff76c2a12124ca9d9cb7e024e7ff03eaf7 Mon Sep 17 00:00:00 2001 From: Jakub Pawlowicz Date: Fri, 19 Jun 2015 09:11:15 +0100 Subject: [PATCH] Moves files around. * lib/selectors/optimizer.js is no more (inlined into lib/clean.js); * Simple and advanced modules go to lib/selectors; * Simple and advanced tests are separated. --- lib/clean.js | 35 +++-- lib/selectors/{optimizers => }/advanced.js | 14 +- lib/selectors/{optimizers => }/clean-up.js | 0 lib/selectors/optimizer.js | 23 ---- lib/selectors/{optimizers => }/simple.js | 8 +- .../{optimizer-test.js => advanced-test.js} | 128 ++---------------- .../selectors/{optimizers => }/simple-test.js | 76 ++++++++++- 7 files changed, 116 insertions(+), 168 deletions(-) rename lib/selectors/{optimizers => }/advanced.js (98%) rename lib/selectors/{optimizers => }/clean-up.js (100%) delete mode 100644 lib/selectors/optimizer.js rename lib/selectors/{optimizers => }/simple.js (98%) rename test/selectors/{optimizer-test.js => advanced-test.js} (77%) rename test/selectors/{optimizers => }/simple-test.js (89%) diff --git a/lib/clean.js b/lib/clean.js index 6c4afbc8..b3c0a44d 100644 --- a/lib/clean.js +++ b/lib/clean.js @@ -7,7 +7,11 @@ var ImportInliner = require('./imports/inliner'); var rebaseUrls = require('./urls/rebase'); -var SelectorsOptimizer = require('./selectors/optimizer'); + +var tokenize = require('./tokenizer/tokenize'); +var SimpleOptimizer = require('./selectors/simple'); +var AdvancedOptimizer = require('./selectors/advanced'); +var addOptimizationMetadata = require('./selectors/optimization-metadata'); var simpleStringify = require('./stringifier/simple'); var sourceMapStringify = require('./stringifier/source-maps'); @@ -165,14 +169,12 @@ function benchmark(runner) { function minify(context, data) { var options = context.options; - var sourceMapTracker = context.inputSourceMapTracker; var commentsProcessor = new CommentsProcessor(context, options.keepSpecialComments, options.keepBreaks, options.sourceMap); var expressionsProcessor = new ExpressionsProcessor(options.sourceMap); var freeTextProcessor = new FreeTextProcessor(options.sourceMap); var urlsProcessor = new UrlsProcessor(context, options.sourceMap, options.compatibility.properties.urlQuotes); - var selectorsOptimizer = new SelectorsOptimizer(options, context); var stringify = options.sourceMap ? sourceMapStringify : simpleStringify; var run = function (processor, action) { @@ -189,15 +191,22 @@ function minify(context, data) { run(urlsProcessor, 'escape'); run(freeTextProcessor, 'escape'); - run(function () { - return selectorsOptimizer.process(data, stringify, function (data) { - data = freeTextProcessor.restore(data); - data = urlsProcessor.restore(data); - data = options.rebase ? rebaseUrls(data, context) : data; - data = expressionsProcessor.restore(data); - return commentsProcessor.restore(data); - }, sourceMapTracker); - }); + function restoreEscapes(data) { + data = freeTextProcessor.restore(data); + data = urlsProcessor.restore(data); + data = options.rebase ? rebaseUrls(data, context) : data; + data = expressionsProcessor.restore(data); + return commentsProcessor.restore(data); + } + + var tokens = tokenize(data, context); - return data; + addOptimizationMetadata(tokens); + + new SimpleOptimizer(options).optimize(tokens); + + if (options.advanced) + new AdvancedOptimizer(options, context).optimize(tokens); + + return stringify(tokens, options, restoreEscapes, context.inputSourceMapTracker); } diff --git a/lib/selectors/optimizers/advanced.js b/lib/selectors/advanced.js similarity index 98% rename from lib/selectors/optimizers/advanced.js rename to lib/selectors/advanced.js index f4f9f51e..b78d63b4 100644 --- a/lib/selectors/optimizers/advanced.js +++ b/lib/selectors/advanced.js @@ -1,12 +1,12 @@ -var optimizeProperties = require('../../properties/optimizer'); +var optimizeProperties = require('../properties/optimizer'); var CleanUp = require('./clean-up'); -var extractProperties = require('../extractor'); -var canReorder = require('../reorderable').canReorder; -var canReorderSingle = require('../reorderable').canReorderSingle; -var stringifyAll = require('../../stringifier/one-time').all; -var stringifyBody = require('../../stringifier/one-time').body; -var stringifySelectors = require('../../stringifier/one-time').selectors; +var extractProperties = require('./extractor'); +var canReorder = require('./reorderable').canReorder; +var canReorderSingle = require('./reorderable').canReorderSingle; +var stringifyAll = require('../stringifier/one-time').all; +var stringifyBody = require('../stringifier/one-time').body; +var stringifySelectors = require('../stringifier/one-time').selectors; function AdvancedOptimizer(options, context) { this.options = options; diff --git a/lib/selectors/optimizers/clean-up.js b/lib/selectors/clean-up.js similarity index 100% rename from lib/selectors/optimizers/clean-up.js rename to lib/selectors/clean-up.js diff --git a/lib/selectors/optimizer.js b/lib/selectors/optimizer.js deleted file mode 100644 index c804230a..00000000 --- a/lib/selectors/optimizer.js +++ /dev/null @@ -1,23 +0,0 @@ -var tokenize = require('../tokenizer/tokenize'); -var SimpleOptimizer = require('./optimizers/simple'); -var AdvancedOptimizer = require('./optimizers/advanced'); -var addOptimizationMetadata = require('./optimization-metadata'); - -function SelectorsOptimizer(options, context) { - this.options = options || {}; - this.context = context || {}; -} - -SelectorsOptimizer.prototype.process = function (data, stringify, restoreCallback, sourceMapTracker) { - var tokens = tokenize(data, this.context); - - addOptimizationMetadata(tokens); - - new SimpleOptimizer(this.options).optimize(tokens); - if (this.options.advanced) - new AdvancedOptimizer(this.options, this.context).optimize(tokens); - - return stringify(tokens, this.options, restoreCallback, sourceMapTracker); -}; - -module.exports = SelectorsOptimizer; diff --git a/lib/selectors/optimizers/simple.js b/lib/selectors/simple.js similarity index 98% rename from lib/selectors/optimizers/simple.js rename to lib/selectors/simple.js index 2c768e91..45acecfd 100644 --- a/lib/selectors/optimizers/simple.js +++ b/lib/selectors/simple.js @@ -1,9 +1,9 @@ var CleanUp = require('./clean-up'); -var Splitter = require('../../utils/splitter'); +var Splitter = require('../utils/splitter'); -var RGB = require('../../colors/rgb'); -var HSL = require('../../colors/hsl'); -var HexNameShortener = require('../../colors/hex-name-shortener'); +var RGB = require('../colors/rgb'); +var HSL = require('../colors/hsl'); +var HexNameShortener = require('../colors/hex-name-shortener'); var DEFAULT_ROUNDING_PRECISION = 2; var CHARSET_TOKEN = '@charset'; diff --git a/test/selectors/optimizer-test.js b/test/selectors/advanced-test.js similarity index 77% rename from test/selectors/optimizer-test.js rename to test/selectors/advanced-test.js index d2c2c08a..d1f8ed97 100644 --- a/test/selectors/optimizer-test.js +++ b/test/selectors/advanced-test.js @@ -1,30 +1,16 @@ var vows = require('vows'); var assert = require('assert'); -var SelectorsOptimizer = require('../../lib/selectors/optimizer'); -var stringify = require('../../lib/stringifier/simple'); -var Compatibility = require('../../lib/utils/compatibility'); -var Validator = require('../../lib/properties/validator'); -var SourceTracker = require('../../lib/utils/source-tracker'); +var CleanCSS = require('../../lib/clean'); function optimizerContext(group, specs, options) { - function restoreCallback(data) { - return data; - } - var context = {}; options = options || {}; options.shorthandCompacting = true; options.restructuring = true; - options.compatibility = new Compatibility(options.compatibility).toOptions(); - var outerContext = { - options: {}, - sourceTracker: new SourceTracker(), - validator: new Validator(options.compatibility) - }; function optimized(target) { return function (source) { - assert.equal(new SelectorsOptimizer(options, outerContext).process(source, stringify, restoreCallback).styles, target); + assert.equal(new CleanCSS(options).minify(source).styles, target); }; } @@ -38,67 +24,7 @@ function optimizerContext(group, specs, options) { return context; } -vows.describe(SelectorsOptimizer) - .addBatch( - optimizerContext('selectors', { - 'whitespace - heading & trailing': [ - ' a {color:red}', - 'a{color:red}' - ], - 'whitespace - descendant selector': [ - 'div > a{color:red}', - 'div>a{color:red}' - ], - 'whitespace - next selector': [ - 'div + a{color:red}', - 'div+a{color:red}' - ], - 'whitespace - sibling selector': [ - 'div ~ a{color:red}', - 'div~a{color:red}' - ], - 'whitespace - pseudo classes': [ - 'div :first-child{color:red}', - 'div :first-child{color:red}' - ], - 'whitespace - line breaks': [ - '\r\ndiv\n{color:red}', - 'div{color:red}' - ], - 'whitespace - tabs': [ - 'div\t\t{color:red}', - 'div{color:red}' - ], - 'universal selector - id, class, and property': [ - '* > *#id > *.class > *[property]{color:red}', - '*>#id>.class>[property]{color:red}' - ], - 'universal selector - pseudo': [ - '*:first-child{color:red}', - ':first-child{color:red}' - ], - 'universal selector - standalone': [ - 'label ~ * + span{color:red}', - 'label~*+span{color:red}' - ], - 'order': [ - 'b,div,a{color:red}', - 'a,b,div{color:red}' - ], - 'duplicates': [ - 'a,div,.class,.class,a ,div > a{color:red}', - '.class,a,div,div>a{color:red}' - ], - 'mixed': [ - ' label ~ \n* + span , div>*.class, section\n\n{color:red}', - 'div>.class,label~*+span,section{color:red}' - ], - 'calc': [ - 'a{width:-moz-calc(100% - 1em);width:calc(100% - 1em)}', - 'a{width:-moz-calc(100% - 1em);width:calc(100% - 1em)}' - ] - }) - ) +vows.describe('advanced optimizer') .addBatch( optimizerContext('selectors - restructuring', { 'up until changed': [ @@ -210,24 +136,24 @@ vows.describe(SelectorsOptimizer) '@-moz-keyframes test{0%{transform:scale3d(1,1,1);opacity:1}100%{transform:scale3d(.5,.5,.5);opacity:1}}' ], 'with one important comment': [ - '__ESCAPED_COMMENT_SPECIAL_CLEAN_CSS0__a{width:100px}div{color:red}.one{display:block}.two{display:inline;color:red}', - '__ESCAPED_COMMENT_SPECIAL_CLEAN_CSS0__.two,div{color:red}a{width:100px}.one{display:block}.two{display:inline}' + '/*! comment */a{width:100px}div{color:red}.one{display:block}.two{display:inline;color:red}', + '/*! comment */.two,div{color:red}a{width:100px}.one{display:block}.two{display:inline}' ], 'with many important comments': [ - '__ESCAPED_COMMENT_SPECIAL_CLEAN_CSS0____ESCAPED_COMMENT_SPECIAL_CLEAN_CSS1__a{width:100px}div{color:red}.one{display:block}.two{display:inline;color:red}', - '__ESCAPED_COMMENT_SPECIAL_CLEAN_CSS0____ESCAPED_COMMENT_SPECIAL_CLEAN_CSS1__.two,div{color:red}a{width:100px}.one{display:block}.two{display:inline}' + '/*! comment 1 *//*! comment 2 */a{width:100px}div{color:red}.one{display:block}.two{display:inline;color:red}', + '/*! comment 1 *//*! comment 2 */.two,div{color:red}a{width:100px}.one{display:block}.two{display:inline}' ], 'with important comment and charset': [ - '@charset "utf-8";__ESCAPED_COMMENT_SPECIAL_CLEAN_CSS0__a{width:100px}div{color:red}.one{display:block}.two{display:inline;color:red}', - '@charset "utf-8";__ESCAPED_COMMENT_SPECIAL_CLEAN_CSS0__.two,div{color:red}a{width:100px}.one{display:block}.two{display:inline}' + '@charset "utf-8";/*! comment */a{width:100px}div{color:red}.one{display:block}.two{display:inline;color:red}', + '@charset "utf-8";/*! comment */.two,div{color:red}a{width:100px}.one{display:block}.two{display:inline}' ], 'with charset and import': [ '@charset "UTF-8";@import url(http://fonts.googleapis.com/css?family=Lora:400,700);a{width:100px}div{color:red}.one{display:block}.two{display:inline;color:red}', '@charset "UTF-8";@import url(http://fonts.googleapis.com/css?family=Lora:400,700);.two,div{color:red}a{width:100px}.one{display:block}.two{display:inline}' ], 'with charset and import and comments': [ - '@charset "UTF-8";@import url(http://fonts.googleapis.com/css?family=Lora:400,700);__ESCAPED_COMMENT_SPECIAL_CLEAN_CSS0__a{width:100px}div{color:red}.one{display:block}.two{display:inline;color:red}', - '@charset "UTF-8";@import url(http://fonts.googleapis.com/css?family=Lora:400,700);__ESCAPED_COMMENT_SPECIAL_CLEAN_CSS0__.two,div{color:red}a{width:100px}.one{display:block}.two{display:inline}' + '@charset "UTF-8";@import url(http://fonts.googleapis.com/css?family=Lora:400,700);/*! comment */a{width:100px}div{color:red}.one{display:block}.two{display:inline;color:red}', + '@charset "UTF-8";@import url(http://fonts.googleapis.com/css?family=Lora:400,700);/*! comment */.two,div{color:red}a{width:100px}.one{display:block}.two{display:inline}' ], 'with vendor prefixed value group': [ 'a{-moz-box-sizing:content-box;box-sizing:content-box}div{color:red}p{-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box}', @@ -272,22 +198,6 @@ vows.describe(SelectorsOptimizer) ] }, { advanced: true, semanticMerging: true }) ) - .addBatch( - optimizerContext('properties', { - 'empty body': [ - 'a{}', - '' - ], - 'whitespace body': [ - 'a{ \n }', - '' - ], - 'whitespace after calc()': [ - 'div{margin:calc(100% - 20px) 1px}', - 'div{margin:calc(100% - 20px) 1px}' - ] - }) - ) .addBatch( optimizerContext('@media', { 'empty': [ @@ -388,22 +298,6 @@ vows.describe(SelectorsOptimizer) ] }, { advanced: false }) ) - .addBatch( - optimizerContext('@charset', { - 'multiple': [ - '@charset \'utf-8\';a{color:red}@charset \'utf-8\';', - '@charset \'utf-8\';a{color:red}' - ], - 'not at beginning': [ - 'a{color:red}@charset \'utf-8\';', - '@charset \'utf-8\';a{color:red}' - ], - 'different case': [ - 'a{color:red}@ChArSeT \'utf-8\';', - 'a{color:red}' - ] - }) - ) .addBatch( optimizerContext('@font-face', { 'rebuilding': [ diff --git a/test/selectors/optimizers/simple-test.js b/test/selectors/simple-test.js similarity index 89% rename from test/selectors/optimizers/simple-test.js rename to test/selectors/simple-test.js index a992eefc..ee399fd6 100644 --- a/test/selectors/optimizers/simple-test.js +++ b/test/selectors/simple-test.js @@ -1,10 +1,10 @@ var vows = require('vows'); var assert = require('assert'); -var tokenize = require('../../../lib/tokenizer/tokenize'); -var SimpleOptimizer = require('../../../lib/selectors/optimizers/simple'); -var Compatibility = require('../../../lib/utils/compatibility'); -var addOptimizationMetadata = require('../../../lib/selectors/optimization-metadata'); +var tokenize = require('../../lib/tokenizer/tokenize'); +var SimpleOptimizer = require('../../lib/selectors/simple'); +var Compatibility = require('../../lib/utils/compatibility'); +var addOptimizationMetadata = require('../../lib/selectors/optimization-metadata'); function selectorContext(group, specs, options) { var context = {}; @@ -78,6 +78,10 @@ vows.describe(SimpleOptimizer) ' div >\n\r\n span{color:red}', [['div>span']] ], + 'more line breaks': [ + '\r\ndiv\n{color:red}', + [['div']] + ], '+html': [ '*+html .foo{display:inline}', null @@ -85,6 +89,54 @@ vows.describe(SimpleOptimizer) 'adjacent nav': [ 'div + nav{color:red}', [['div+nav']] + ], + 'heading & trailing': [ + ' a {color:red}', + [['a']] + ], + 'descendant selector': [ + 'div > a{color:red}', + [['div>a']] + ], + 'next selector': [ + 'div + a{color:red}', + [['div+a']] + ], + 'sibling selector': [ + 'div ~ a{color:red}', + [['div~a']] + ], + 'pseudo classes': [ + 'div :first-child{color:red}', + [['div :first-child']] + ], + 'tabs': [ + 'div\t\t{color:red}', + [['div']] + ], + 'universal selector - id, class, and property': [ + '* > *#id > *.class > *[property]{color:red}', + [['*>#id>.class>[property]']] + ], + 'universal selector - pseudo': [ + '*:first-child{color:red}', + [[':first-child']] + ], + 'universal selector - standalone': [ + 'label ~ * + span{color:red}', + [['label~*+span']] + ], + 'order': [ + 'b,div,a{color:red}', + [['a'], ['b'], ['div']] + ], + 'duplicates': [ + 'a,div,.class,.class,a ,div > a{color:red}', + [['.class'], ['a'], ['div'], ['div>a']] + ], + 'mixed': [ + ' label ~ \n* + span , div>*.class, section\n\n{color:red}', + [['div>.class'], ['label~*+span'], ['section']] ] }) ) @@ -657,6 +709,22 @@ vows.describe(SimpleOptimizer) 'stripped spaces': [ 'div{text-shadow:rgba(255,1,1,.5) 1px}', [['text-shadow', 'rgba(255,1,1,.5)', '1px']] + ], + 'calc': [ + 'a{width:-moz-calc(100% - 1em);width:calc(100% - 1em)}', + [['width', '-moz-calc(100% - 1em)'], ['width', 'calc(100% - 1em)']] + ], + 'empty body': [ + 'a{}', + null + ], + 'in a body': [ + 'a{ \n }', + null + ], + 'after calc()': [ + 'div{margin:calc(100% - 20px) 1px}', + [['margin', 'calc(100% - 20px)', '1px']] ] }) ) -- 2.34.1