From: Jakub Pawlowicz Date: Mon, 24 Aug 2015 04:36:37 +0000 (+0100) Subject: Refactors Splitter class into a split function. X-Git-Url: https://git.ndcode.org/public/gitweb.cgi?a=commitdiff_plain;h=dcd2e67187ae9de145e69884a7770f7847a259e0;p=clean-css.git Refactors Splitter class into a split function. --- diff --git a/lib/imports/inliner.js b/lib/imports/inliner.js index 5d4da388..e4ffad33 100644 --- a/lib/imports/inliner.js +++ b/lib/imports/inliner.js @@ -5,7 +5,7 @@ var https = require('https'); var url = require('url'); var rewriteUrls = require('../urls/rewrite'); -var Splitter = require('../utils/splitter.js'); +var split = require('../utils/split'); var override = require('../utils/object.js').override; var MAP_MARKER = /\/\*# sourceMappingURL=(\S+) \*\//; @@ -178,7 +178,7 @@ function inline(data, nextStart, nextEnd, context) { var isQuoted = /^['"]/.exec(importDeclaration.substring(urlStartsAt, urlStartsAt + 2)); var urlEndsAt = isQuoted ? importDeclaration.indexOf(isQuoted[0], urlStartsAt + 1) : - new Splitter(' ').split(importDeclaration)[0].length - (viaUrl ? 1 : 0); + split(importDeclaration, ' ')[0].length - (viaUrl ? 1 : 0); var importedFile = importDeclaration .substring(urlStartsAt, urlEndsAt) diff --git a/lib/properties/break-up.js b/lib/properties/break-up.js index f1535585..9bb49409 100644 --- a/lib/properties/break-up.js +++ b/lib/properties/break-up.js @@ -1,6 +1,6 @@ var wrapSingle = require('./wrap-for-optimizing').single; -var Splitter = require('../utils/splitter'); +var split = require('../utils/split'); var MULTIPLEX_SEPARATOR = ','; function _colorFilter(validator) { @@ -79,7 +79,7 @@ function background(property, compactable, validator) { var previousValue = values[i - 1]; if (previousValue[0].indexOf('/') > 0) { - var twoParts = new Splitter('/').split(previousValue[0]); + var twoParts = split(previousValue[0], '/'); // NOTE: we do this slicing as value may contain metadata too, like for source maps size.value = [[twoParts.pop()].concat(previousValue.slice(1)), value]; values[i - 1] = [twoParts.pop()].concat(previousValue.slice(1)); @@ -103,7 +103,7 @@ function background(property, compactable, validator) { positionSet = true; } } else if (validator.isValidBackgroundPositionAndSize(value[0])) { - var sizeValue = new Splitter('/').split(value[0]); + var sizeValue = split(value[0], '/'); // NOTE: we do this slicing as value may contain metadata too, like for source maps size.value = [[sizeValue.pop()].concat(value.slice(1))]; position.value = [[sizeValue.pop()].concat(value.slice(1))]; diff --git a/lib/properties/validator.js b/lib/properties/validator.js index 346a36aa..2e8356cf 100644 --- a/lib/properties/validator.js +++ b/lib/properties/validator.js @@ -1,6 +1,6 @@ // Validates various CSS property values -var Splitter = require('../utils/splitter'); +var split = require('../utils/split'); var widthKeywords = ['thin', 'thick', 'medium', 'inherit', 'initial']; var allUnits = ['px', '%', 'em', 'in', 'cm', 'mm', 'ex', 'pt', 'pc', 'ch', 'rem', 'vh', 'vm', 'vmin', 'vmax', 'vw']; @@ -146,7 +146,7 @@ Validator.prototype.isValidBackgroundPositionAndSize = function (s) { if (s.indexOf('/') < 0) return false; - var twoParts = new Splitter('/').split(s); + var twoParts = split(s, '/'); return this.isValidBackgroundSizePart(twoParts.pop()) && this.isValidBackgroundPositionPart(twoParts.pop()); }; diff --git a/lib/selectors/simple.js b/lib/selectors/simple.js index f431321c..da586ab3 100644 --- a/lib/selectors/simple.js +++ b/lib/selectors/simple.js @@ -1,7 +1,7 @@ var cleanUpSelectors = require('./clean-up').selectors; var cleanUpBlock = require('./clean-up').block; var cleanUpAtRule = require('./clean-up').atRule; -var Splitter = require('../utils/splitter'); +var split = require('../utils/split'); var RGB = require('../colors/rgb'); var HSL = require('../colors/hsl'); @@ -163,7 +163,7 @@ function colorMininifier(_, value, compatibility) { if (compatibility.colors.opacity) { value = value.replace(/(?:rgba|hsla)\(0,0%?,0%?,0\)/g, function (match) { - if (new Splitter(',').split(value).pop().indexOf('gradient(') > -1) + if (split(value, ',').pop().indexOf('gradient(') > -1) return match; return 'transparent'; diff --git a/lib/tokenizer/extract-properties.js b/lib/tokenizer/extract-properties.js index 25484493..2eca69c9 100644 --- a/lib/tokenizer/extract-properties.js +++ b/lib/tokenizer/extract-properties.js @@ -1,4 +1,4 @@ -var Splitter = require('../utils/splitter'); +var split = require('../utils/split'); var COMMA = ','; var FORWARD_SLASH = '/'; @@ -46,7 +46,7 @@ function trackComments(comments, into, context) { function extractProperties(string, selectors, context) { var list = []; var innerComments = []; - var splitter = new Splitter(/[ ,\/]/); + var valueSeparator = /[ ,\/]/; if (typeof string != 'string') return []; @@ -98,7 +98,7 @@ function extractProperties(string, selectors, context) { trackComments(innerComments, list, context); - var values = splitter.split(candidate.substring(firstColonAt + 1), true); + var values = split(candidate.substring(firstColonAt + 1), valueSeparator, true); if (values.length == 1 && values[0] === '') { context.warnings.push('Empty property \'' + name + '\' inside \'' + selectors.filter(selectorName).join(',') + '\' selector. Ignoring.'); diff --git a/lib/tokenizer/extract-selectors.js b/lib/tokenizer/extract-selectors.js index cbdf367f..dc8a47fa 100644 --- a/lib/tokenizer/extract-selectors.js +++ b/lib/tokenizer/extract-selectors.js @@ -1,9 +1,9 @@ -var Splitter = require('../utils/splitter'); +var split = require('../utils/split'); function extractSelectors(string, context) { var list = []; var metadata; - var selectors = new Splitter(',').split(string); + var selectors = split(string, ','); for (var i = 0, l = selectors.length; i < l; i++) { metadata = context.track(selectors[i], true, i); diff --git a/lib/utils/split.js b/lib/utils/split.js new file mode 100644 index 00000000..c39ed7ce --- /dev/null +++ b/lib/utils/split.js @@ -0,0 +1,36 @@ +function split(value, separator, includeSeparator) { + var withRegex = typeof separator != 'string'; + var hasSeparator = withRegex ? + separator.test(value) : + value.indexOf(separator); + + if (!hasSeparator) + return [value]; + + if (value.indexOf('(') === -1 && !includeSeparator) + return value.split(separator); + + var level = 0; + var cursor = 0; + var lastStart = 0; + var len = value.length; + var tokens = []; + + while (cursor++ < len) { + if (value[cursor] == '(') { + level++; + } else if (value[cursor] == ')') { + level--; + } else if ((withRegex ? separator.test(value[cursor]) : value[cursor] == separator) && level === 0) { + tokens.push(value.substring(lastStart, cursor + (includeSeparator ? 1 : 0))); + lastStart = cursor + 1; + } + } + + if (lastStart < cursor + 1) + tokens.push(value.substring(lastStart)); + + return tokens; +} + +module.exports = split; diff --git a/lib/utils/splitter.js b/lib/utils/splitter.js deleted file mode 100644 index a8560702..00000000 --- a/lib/utils/splitter.js +++ /dev/null @@ -1,39 +0,0 @@ -function Splitter(separator) { - this.separator = separator; - this.withRegex = typeof separator != 'string'; -} - -Splitter.prototype.split = function (value, withSeparator) { - var hasSeparator = this.withRegex ? - this.separator.test(value) : - value.indexOf(this.separator); - if (!hasSeparator) - return [value]; - - if (value.indexOf('(') === -1 && !withSeparator) - return value.split(this.separator); - - var level = 0; - var cursor = 0; - var lastStart = 0; - var len = value.length; - var tokens = []; - - while (cursor++ < len) { - if (value[cursor] == '(') { - level++; - } else if (value[cursor] == ')') { - level--; - } else if ((this.withRegex ? this.separator.test(value[cursor]) : value[cursor] == this.separator) && level === 0) { - tokens.push(value.substring(lastStart, cursor + (withSeparator ? 1 : 0))); - lastStart = cursor + 1; - } - } - - if (lastStart < cursor + 1) - tokens.push(value.substring(lastStart)); - - return tokens; -}; - -module.exports = Splitter; diff --git a/test/utils/split-test.js b/test/utils/split-test.js new file mode 100644 index 00000000..8221aed1 --- /dev/null +++ b/test/utils/split-test.js @@ -0,0 +1,88 @@ +var vows = require('vows'); +var assert = require('assert'); +var split = require('../../lib/utils/split'); + +vows.describe(split) + .addBatch({ + 'empty': { + topic: '', + split: function (input) { + assert.deepEqual(split(input, ','), ['']); + } + }, + 'simple': { + topic: 'none', + split: function (input) { + assert.deepEqual(split(input, ','), ['none']); + } + }, + 'comma separated - level 0': { + topic: '#000,#fff,#0f0', + split: function (input) { + assert.deepEqual(split(input, ','), ['#000', '#fff', '#0f0']); + } + }, + 'comma separated - level 1': { + topic: 'rgb(0,0,0),#fff', + split: function (input) { + assert.deepEqual(split(input, ','), ['rgb(0,0,0)', '#fff']); + } + }, + 'comma separated - level 2': { + topic: 'linear-gradient(0,#fff,rgba(0,0,0)),red', + split: function (input) { + assert.deepEqual(split(input, ','), ['linear-gradient(0,#fff,rgba(0,0,0))', 'red']); + } + }, + 'space separated - level 0': { + topic: '#000 #fff #0f0', + split: function (input) { + assert.deepEqual(split(input, ' '), ['#000', '#fff', '#0f0']); + } + }, + 'space separated - level 1': { + topic: 'rgb(0, 0, 0) #fff', + split: function (input) { + assert.deepEqual(split(input, ' '), ['rgb(0, 0, 0)', '#fff']); + } + }, + 'space separated - level 2': { + topic: 'linear-gradient(0, #fff, rgba(0, 0, 0)) red', + split: function (input) { + assert.deepEqual(split(input, ' '), ['linear-gradient(0, #fff, rgba(0, 0, 0))', 'red']); + } + }, + 'with regex': { + topic: 'no-repeat,0/0', + split: function (input) { + assert.deepEqual(split(input, /[ ,\/]/), ['no-repeat', '0', '0']); + } + } + }) + .addBatch({ + 'including separator - leading space and quote': { + topic: ' "Font"', + split: function (input) { + assert.deepEqual(split(input, ' ', true), [' "Font"']); + } + }, + 'including separator - comma separated - level 2': { + topic: 'linear-gradient(0,#fff,rgba(0,0,0)),red', + split: function (input) { + assert.deepEqual(split(input, ',', true), ['linear-gradient(0,#fff,rgba(0,0,0)),', 'red']); + } + }, + 'including separator - space separated - level 2 with spaces': { + topic: 'linear-gradient(0, #fff, rgba(0, 0, 0)) red', + split: function (input) { + assert.deepEqual(split(input, ' ', true), ['linear-gradient(0, #fff, rgba(0, 0, 0)) ', 'red']); + } + }, + 'including separator - with regex': { + topic: 'no-repeat,0/0', + split: function (input) { + assert.deepEqual(split(input, /[ ,\/]/, true), ['no-repeat,', '0/', '0']); + } + } + }) + .export(module); diff --git a/test/utils/splitter-test.js b/test/utils/splitter-test.js deleted file mode 100644 index 5dd5fa79..00000000 --- a/test/utils/splitter-test.js +++ /dev/null @@ -1,29 +0,0 @@ -var vows = require('vows'); -var assert = require('assert'); -var Splitter = require('../../lib/utils/splitter'); - -function split(value, expectedValue, separator, withSeparator) { - return function () { - assert.deepEqual(new Splitter(separator).split(value, withSeparator), expectedValue); - }; -} - -vows.describe(Splitter) - .addBatch({ - 'empty': split('', [''], ','), - 'simple': split('none', ['none'], ','), - 'comma separated - level 0': split('#000,#fff,#0f0', ['#000', '#fff', '#0f0'], ','), - 'comma separated - level 1': split('rgb(0,0,0),#fff', ['rgb(0,0,0)', '#fff'], ','), - 'comma separated - level 2': split('linear-gradient(0,#fff,rgba(0,0,0)),red', ['linear-gradient(0,#fff,rgba(0,0,0))', 'red'], ','), - 'space separated - level 0': split('#000 #fff #0f0', ['#000', '#fff', '#0f0'], ' '), - 'space separated - level 1': split('rgb(0, 0, 0) #fff', ['rgb(0, 0, 0)', '#fff'], ' '), - 'space separated - level 2': split('linear-gradient(0, #fff, rgba(0, 0, 0)) red', ['linear-gradient(0, #fff, rgba(0, 0, 0))', 'red'], ' '), - 'with regex': split('no-repeat,0/0', ['no-repeat', '0', '0'], /[ ,\/]/) - }) - .addBatch({ - 'leading space and quote with separator': split(' "Font"', [' "Font"'], ' ', true), - 'comma separated - level 2 - with separator': split('linear-gradient(0,#fff,rgba(0,0,0)),red', ['linear-gradient(0,#fff,rgba(0,0,0)),', 'red'], ',', true), - 'space separated - level 2 - with separator': split('linear-gradient(0, #fff, rgba(0, 0, 0)) red', ['linear-gradient(0, #fff, rgba(0, 0, 0)) ', 'red'], ' ', true), - 'with regex': split('no-repeat,0/0', ['no-repeat,', '0/', '0'], /[ ,\/]/, true) - }) - .export(module);