var stringifyBody = require('../stringifier/one-time').body;
var stringifySelectors = require('../stringifier/one-time').selectors;
+var removeDuplicates = require('./remove-duplicates');
+
function AdvancedOptimizer(options, context) {
this.options = options;
this.validator = context.validator;
return this.options.compatibility.selectors.special.test(selector);
};
-AdvancedOptimizer.prototype.removeDuplicates = function (tokens) {
- var matched = {};
- var moreThanOnce = [];
- var id, token;
- var body, bodies;
-
- for (var i = 0, l = tokens.length; i < l; i++) {
- token = tokens[i];
- if (token[0] != 'selector')
- continue;
-
- id = stringifySelectors(token[1]);
-
- if (matched[id] && matched[id].length == 1)
- moreThanOnce.push(id);
- else
- matched[id] = matched[id] || [];
-
- matched[id].push(i);
- }
-
- for (i = 0, l = moreThanOnce.length; i < l; i++) {
- id = moreThanOnce[i];
- bodies = [];
-
- for (var j = matched[id].length - 1; j >= 0; j--) {
- token = tokens[matched[id][j]];
- body = stringifyBody(token[2]);
-
- if (bodies.indexOf(body) > -1)
- token[2] = [];
- else
- bodies.push(body);
- }
- }
-};
-
AdvancedOptimizer.prototype.mergeAdjacent = function (tokens) {
var lastToken = [null, [], []];
var adjacentSpace = this.options.compatibility.selectors.adjacentSpace;
recursivelyOptimizeProperties(tokens, self.options, self.validator);
- self.removeDuplicates(tokens);
+ removeDuplicates(tokens);
self.mergeAdjacent(tokens);
self.reduceNonAdjacent(tokens);
--- /dev/null
+var stringifyBody = require('../stringifier/one-time').body;
+var stringifySelectors = require('../stringifier/one-time').selectors;
+
+function removeDuplicates(tokens) {
+ var matched = {};
+ var moreThanOnce = [];
+ var id, token;
+ var body, bodies;
+
+ for (var i = 0, l = tokens.length; i < l; i++) {
+ token = tokens[i];
+ if (token[0] != 'selector')
+ continue;
+
+ id = stringifySelectors(token[1]);
+
+ if (matched[id] && matched[id].length == 1)
+ moreThanOnce.push(id);
+ else
+ matched[id] = matched[id] || [];
+
+ matched[id].push(i);
+ }
+
+ for (i = 0, l = moreThanOnce.length; i < l; i++) {
+ id = moreThanOnce[i];
+ bodies = [];
+
+ for (var j = matched[id].length - 1; j >= 0; j--) {
+ token = tokens[matched[id][j]];
+ body = stringifyBody(token[2]);
+
+ if (bodies.indexOf(body) > -1)
+ token[2] = [];
+ else
+ bodies.push(body);
+ }
+ }
+}
+
+module.exports = removeDuplicates;
]
})
)
- .addBatch(
- optimizerContext('duplicate selectors in a scope', {
- 'of two successive selectors': [
- 'a{color:red}a{color:red}',
- 'a{color:red}'
- ],
- 'of two successive selectors with different body': [
- 'a{color:red}a{display:block}',
- 'a{color:red;display:block}'
- ],
- 'of many successive selectors': [
- 'a{color:red}a{color:red}a{color:red}a{color:red}',
- 'a{color:red}'
- ],
- 'of two non-successive selectors': [
- 'a{color:red}p{color:#fff}a{color:red}',
- 'p{color:#fff}a{color:red}'
- ],
- 'of many non-successive selectors': [
- 'div{width:100%}a{color:red}a{color:red}p{color:#fff}div{width:100%}ol{margin:0}p{color:#fff}',
- 'a{color:red}div{width:100%}ol{margin:0}p{color:#fff}'
- ],
- 'with global and media scope': [
- 'a{color:red}@media screen{a{color:red}p{width:100px}a{color:red}}',
- 'a{color:red}@media screen{p{width:100px}a{color:red}}'
- ],
- 'with two media scopes': [
- '@media (min-width:100px){a{color:red}}@media screen{a{color:red}p{width:100px}a{color:red}}',
- '@media (min-width:100px){a{color:red}}@media screen{p{width:100px}a{color:red}}'
- ]
- })
- )
.addBatch(
optimizerContext('duplicate properties with aggressive merging disabled', {
'of (yet) unmergeable properties': [
'a{color:red;color:red}',
'a{color:red}'
],
- 'duplicates - same context': [
- 'a{color:red}div{color:blue}a{color:red}',
- 'div{color:#00f}a{color:red}'
- ],
- 'duplicates - different contexts': [
- 'a{color:red}div{color:blue}@media screen{a{color:red}}',
- 'a{color:red}div{color:#00f}@media screen{a{color:red}}'
- ],
'adjacent': [
'a{color:red}a{display:block;width:100px}div{color:#fff}',
'a{color:red;display:block;width:100px}div{color:#fff}'
'a{color:red;color:red}',
'a{color:red;color:red}'
],
- 'duplicates - same context': [
- 'a{color:red}div{color:blue}a{color:red}',
- 'a{color:red}div{color:#00f}a{color:red}'
- ],
- 'duplicates - different contexts': [
- 'a{color:red}div{color:blue}@media screen{a{color:red}}',
- 'a{color:red}div{color:#00f}@media screen{a{color:red}}'
- ],
'adjacent': [
'a{color:red}a{display:block;width:100px}div{color:#fff}',
'a{color:red}a{display:block;width:100px}div{color:#fff}'
--- /dev/null
+var vows = require('vows');
+var optimizerContext = require('../test-helper').optimizerContext;
+
+vows.describe('remove duplicates')
+ .addBatch(
+ optimizerContext('advanced on', {
+ 'same context': [
+ 'a{color:red}div{color:blue}a{color:red}',
+ 'div{color:#00f}a{color:red}'
+ ],
+ 'different contexts': [
+ 'a{color:red}div{color:blue}@media screen{a{color:red}}',
+ 'a{color:red}div{color:#00f}@media screen{a{color:red}}'
+ ],
+ 'of two successive selectors': [
+ 'a{color:red}a{color:red}',
+ 'a{color:red}'
+ ],
+ 'of two successive selectors with different body': [
+ 'a{color:red}a{display:block}',
+ 'a{color:red;display:block}'
+ ],
+ 'of many successive selectors': [
+ 'a{color:red}a{color:red}a{color:red}a{color:red}',
+ 'a{color:red}'
+ ],
+ 'of two non-successive selectors': [
+ 'a{color:red}p{color:#fff}a{color:red}',
+ 'p{color:#fff}a{color:red}'
+ ],
+ 'of many non-successive selectors': [
+ 'div{width:100%}a{color:red}a{color:red}p{color:#fff}div{width:100%}ol{margin:0}p{color:#fff}',
+ 'a{color:red}div{width:100%}ol{margin:0}p{color:#fff}'
+ ],
+ 'with global and media scope': [
+ 'a{color:red}@media screen{a{color:red}p{width:100px}a{color:red}}',
+ 'a{color:red}@media screen{p{width:100px}a{color:red}}'
+ ],
+ 'with two media scopes': [
+ '@media (min-width:100px){a{color:red}}@media screen{a{color:red}p{width:100px}a{color:red}}',
+ '@media (min-width:100px){a{color:red}}@media screen{p{width:100px}a{color:red}}'
+ ]
+ })
+ )
+ .addBatch(
+ optimizerContext('advanced off', {
+ 'same context': [
+ 'a{color:red}div{color:blue}a{color:red}',
+ 'a{color:red}div{color:#00f}a{color:red}'
+ ],
+ 'different contexts': [
+ 'a{color:red}div{color:blue}@media screen{a{color:red}}',
+ 'a{color:red}div{color:#00f}@media screen{a{color:red}}'
+ ],
+ }, { advanced: false })
+ )
+ .export(module);