From: Jakub Pawlowicz Date: Sun, 2 Nov 2014 16:20:53 +0000 (+0000) Subject: Extracts rebuilding tokens into Stringifier class. X-Git-Url: https://git.ndcode.org/public/gitweb.cgi?a=commitdiff_plain;h=739d60ac7e5a7bafaa5924328335b07f2bfb5573;p=clean-css.git Extracts rebuilding tokens into Stringifier class. --- diff --git a/lib/clean.js b/lib/clean.js index f3f4b930..b716ecbe 100644 --- a/lib/clean.js +++ b/lib/clean.js @@ -8,6 +8,7 @@ var ImportInliner = require('./imports/inliner'); var UrlRebase = require('./images/url-rebase'); var SelectorsOptimizer = require('./selectors/optimizer'); +var Stringifier = require('./selectors/stringifier'); var CommentsProcessor = require('./text/comments-processor'); var ExpressionsProcessor = require('./text/expressions-processor'); @@ -120,11 +121,10 @@ function minify(data) { var urlRebase = new UrlRebase(options, context); var selectorsOptimizer = new SelectorsOptimizer(options, context); - var run = function (processor, action, enabled) { - if (enabled === false) - return; - - data = processor[action](data); + var run = function (processor, action) { + data = typeof processor == 'function' ? + processor(data) : + processor[action](data); }; if (options.benchmark) @@ -134,12 +134,18 @@ function minify(data) { run(expressionsProcessor, 'escape'); run(urlsProcessor, 'escape'); run(freeTextProcessor, 'escape'); - run(selectorsOptimizer, 'process'); - run(freeTextProcessor, 'restore'); - run(urlsProcessor, 'restore'); - run(urlRebase, 'process', options.rebase); - run(expressionsProcessor, 'restore'); - run(commentsProcessor, 'restore'); + + run(function() { + var stringifier = new Stringifier(options.keepBreaks, function (data) { + data = freeTextProcessor.restore(data); + data = urlsProcessor.restore(data); + data = options.rebase ? urlRebase.process(data) : data; + data = expressionsProcessor.restore(data); + return commentsProcessor.restore(data); + }); + + return selectorsOptimizer.process(data, stringifier); + }); return data; } diff --git a/lib/selectors/optimizer.js b/lib/selectors/optimizer.js index 98d5e0a2..3f6abf4e 100644 --- a/lib/selectors/optimizer.js +++ b/lib/selectors/optimizer.js @@ -2,64 +2,19 @@ var Tokenizer = require('./tokenizer'); var SimpleOptimizer = require('./optimizers/simple'); var AdvancedOptimizer = require('./optimizers/advanced'); -var lineBreak = require('os').EOL; - function SelectorsOptimizer(options, context) { this.options = options || {}; this.context = context || {}; } -function valueRebuilder(list, separator) { - var merged = ''; - - for (var i = 0, l = list.length; i < l; i++) - merged += list[i].value + (i < l - 1 ? separator : ''); - - return merged; -} - -function rebuild(tokens, keepBreaks, isFlatBlock) { - var joinCharacter = isFlatBlock ? ';' : (keepBreaks ? lineBreak : ''); - var parts = []; - var body; - var selector; - - for (var i = 0, l = tokens.length; i < l; i++) { - var token = tokens[i]; - - if (token.kind === 'text' || token.kind == 'at-rule') { - parts.push(token.value); - continue; - } - - // FIXME: broken due to joining/splitting - if (token.body && (token.body.length === 0 || (token.body.length == 1 && token.body[0].value === ''))) - continue; - - if (token.kind == 'block') { - body = token.isFlatBlock ? - valueRebuilder(token.body, ';') : - rebuild(token.body, keepBreaks, token.isFlatBlock); - if (body.length > 0) - parts.push(token.value + '{' + body + '}'); - } else { - selector = valueRebuilder(token.value, ','); - body = valueRebuilder(token.body, ';'); - parts.push(selector + '{' + body + '}'); - } - } - - return parts.join(joinCharacter); -} - -SelectorsOptimizer.prototype.process = function (data) { +SelectorsOptimizer.prototype.process = function (data, stringifier) { var tokens = new Tokenizer(this.context, this.options.advanced).toTokens(data); new SimpleOptimizer(this.options).optimize(tokens); if (this.options.advanced) new AdvancedOptimizer(this.options, this.context).optimize(tokens); - return rebuild(tokens, this.options.keepBreaks, false).trim(); + return stringifier.toString(tokens); }; module.exports = SelectorsOptimizer; diff --git a/lib/selectors/stringifier.js b/lib/selectors/stringifier.js new file mode 100644 index 00000000..c89f50a6 --- /dev/null +++ b/lib/selectors/stringifier.js @@ -0,0 +1,56 @@ +var lineBreak = require('os').EOL; + +function Stringifier(keepBreaks, restoreCallback) { + this.keepBreaks = keepBreaks; + this.restoreCallback = restoreCallback; +} + +function valueRebuilder(list, separator) { + var merged = ''; + + for (var i = 0, l = list.length; i < l; i++) + merged += list[i].value + (i < l - 1 ? separator : ''); + + return merged; +} + +function rebuild(tokens, keepBreaks, isFlatBlock) { + var joinCharacter = isFlatBlock ? ';' : (keepBreaks ? lineBreak : ''); + var parts = []; + var body; + var selector; + + for (var i = 0, l = tokens.length; i < l; i++) { + var token = tokens[i]; + + if (token.kind === 'text' || token.kind == 'at-rule') { + parts.push(token.value); + continue; + } + + // FIXME: broken due to joining/splitting + if (token.body && (token.body.length === 0 || (token.body.length == 1 && token.body[0].value === ''))) + continue; + + if (token.kind == 'block') { + body = token.isFlatBlock ? + valueRebuilder(token.body, ';') : + rebuild(token.body, keepBreaks, token.isFlatBlock); + if (body.length > 0) + parts.push(token.value + '{' + body + '}'); + } else { + selector = valueRebuilder(token.value, ','); + body = valueRebuilder(token.body, ';'); + parts.push(selector + '{' + body + '}'); + } + } + + return parts.join(joinCharacter); +} + +Stringifier.prototype.toString = function (tokens) { + var rebuilt = rebuild(tokens, this.keepBreaks, false); + return this.restoreCallback(rebuilt).trim(); +}; + +module.exports = Stringifier; diff --git a/test/selectors/optimizer-test.js b/test/selectors/optimizer-test.js index 1f5bf50e..d3160380 100644 --- a/test/selectors/optimizer-test.js +++ b/test/selectors/optimizer-test.js @@ -1,16 +1,19 @@ var vows = require('vows'); var assert = require('assert'); var SelectorsOptimizer = require('../../lib/selectors/optimizer'); +var Stringifier = require('../../lib/selectors/stringifier'); var Compatibility = require('../../lib/utils/compatibility'); function optimizerContext(group, specs, options) { + var stringifier = new Stringifier(false, function (data) { return data; }); + var context = {}; options = options || {}; options.compatibility = new Compatibility(options.compatibility).toOptions(); function optimized(target) { return function (source) { - assert.equal(new SelectorsOptimizer(options).process(source), target); + assert.equal(new SelectorsOptimizer(options).process(source, stringifier), target); }; }