var stringifySelectors = require('../stringifier/one-time').selectors;
var removeDuplicates = require('./remove-duplicates');
+var mergeAdjacent = require('./merge-adjacent');
function AdvancedOptimizer(options, context) {
this.options = options;
return this.options.compatibility.selectors.special.test(selector);
};
-AdvancedOptimizer.prototype.mergeAdjacent = function (tokens) {
- var lastToken = [null, [], []];
- var adjacentSpace = this.options.compatibility.selectors.adjacentSpace;
-
- for (var i = 0, l = tokens.length; i < l; i++) {
- var token = tokens[i];
-
- if (token[0] != 'selector') {
- lastToken = [null, [], []];
- continue;
- }
-
- if (lastToken[0] == 'selector' && stringifySelectors(token[1]) == stringifySelectors(lastToken[1])) {
- var joinAt = [lastToken[2].length];
- Array.prototype.push.apply(lastToken[2], token[2]);
- optimizeProperties(token[1], lastToken[2], joinAt, true, this.options, this.validator);
- token[2] = [];
- } else if (lastToken[0] == 'selector' && stringifyBody(token[2]) == stringifyBody(lastToken[2]) &&
- !this.isSpecial(stringifySelectors(token[1])) && !this.isSpecial(stringifySelectors(lastToken[1]))) {
- lastToken[1] = CleanUp.selectors(lastToken[1].concat(token[1]), false, adjacentSpace);
- token[2] = [];
- } else {
- lastToken = token;
- }
- }
-};
-
AdvancedOptimizer.prototype.reduceNonAdjacent = function (tokens) {
var candidates = {};
var repeated = [];
recursivelyOptimizeProperties(tokens, self.options, self.validator);
removeDuplicates(tokens);
- self.mergeAdjacent(tokens);
+ mergeAdjacent(tokens, self.options, self.validator);
self.reduceNonAdjacent(tokens);
self.mergeNonAdjacentBySelector(tokens);
if (self.options.restructuring && withRestructuring) {
self.restructure(tokens);
- self.mergeAdjacent(tokens);
+ mergeAdjacent(tokens, self.options, self.validator);
}
if (self.options.mediaMerging) {
--- /dev/null
+function isSpecial(options, selector) {
+ return options.compatibility.selectors.special.test(selector);
+}
+
+module.exports = isSpecial;
--- /dev/null
+var optimizeProperties = require('../properties/optimizer');
+
+var stringifyBody = require('../stringifier/one-time').body;
+var stringifySelectors = require('../stringifier/one-time').selectors;
+var cleanUpSelectors = require('./clean-up').selectors;
+var isSpecial = require('./is-special');
+
+function mergeAdjacent(tokens, options, validator) {
+ var lastToken = [null, [], []];
+ var adjacentSpace = options.compatibility.selectors.adjacentSpace;
+
+ for (var i = 0, l = tokens.length; i < l; i++) {
+ var token = tokens[i];
+
+ if (token[0] != 'selector') {
+ lastToken = [null, [], []];
+ continue;
+ }
+
+ if (lastToken[0] == 'selector' && stringifySelectors(token[1]) == stringifySelectors(lastToken[1])) {
+ var joinAt = [lastToken[2].length];
+ Array.prototype.push.apply(lastToken[2], token[2]);
+ optimizeProperties(token[1], lastToken[2], joinAt, true, options, validator);
+ token[2] = [];
+ } else if (lastToken[0] == 'selector' && stringifyBody(token[2]) == stringifyBody(lastToken[2]) &&
+ !isSpecial(options, stringifySelectors(token[1])) && !isSpecial(options, stringifySelectors(lastToken[1]))) {
+ lastToken[1] = cleanUpSelectors(lastToken[1].concat(token[1]), false, adjacentSpace);
+ token[2] = [];
+ } else {
+ lastToken = token;
+ }
+ }
+}
+
+module.exports = mergeAdjacent;
]
}, { aggressiveMerging: false })
)
- .addBatch(
- optimizerContext('same selectors', {
- 'of two non-adjacent selectors': [
- '.one{color:red}.two{color:#00f}.one{font-weight:700}',
- '.one{color:red;font-weight:700}.two{color:#00f}'
- ],
- 'of two adjacent single selectors': [
- '.one{color:red}.one{font-weight:700}',
- '.one{color:red;font-weight:700}'
- ],
- 'of three adjacent single selectors': [
- '.one{color:red}.one{font-weight:700}.one{font-size:12px}',
- '.one{color:red;font-weight:700;font-size:12px}'
- ],
- 'of two adjacent single, complex selectors': [
- '#box>.one{color:red}#box>.one{font-weight:700}',
- '#box>.one{color:red;font-weight:700}'
- ],
- 'of two adjacent multiple, complex selectors': [
- '#box>.one,.zero{color:red}#box>.one,.zero{font-weight:700}',
- '#box>.one,.zero{color:red;font-weight:700}'
- ],
- 'of two adjacent selectors with duplicate properties #1': [
- '.one{color:red}.one{color:#fff}',
- '.one{color:#fff}'
- ],
- 'of two adjacent selectors with duplicate properties #2': [
- '.one{color:red;font-weight:bold}.one{color:#fff;font-weight:400}',
- '.one{color:#fff;font-weight:400}'
- ],
- 'of two adjacent complex selectors with different selector order': [
- '.one,.two{color:red}.two,.one{line-height:1em}',
- '.one,.two{color:red;line-height:1em}'
- ],
- 'two adjacent with hex color definitions': [
- 'a:link,a:visited{color:#fff}.one{display:block}a:link,a:visited{color:red}',
- '.one{display:block}a:link,a:visited{color:red}'
- ],
- 'in two passes': [
- 'a{color:red}a{background:red}b{color:red}b{background:red}',
- 'a,b{color:red;background:red}'
- ],
- 'when overriden with a browser specific selector': [
- 'a{color:red}::-webkit-scrollbar,a{color:#fff}',
- 'a{color:red}::-webkit-scrollbar,a{color:#fff}'
- ],
- 'two same selectors over a block': [
- '.one{color:red}@media print{.two{display:block}}.one{display:none}',
- '@media print{.two{display:block}}.one{color:red;display:none}'
- ],
- 'two same bodies over a block': [
- '.one{color:red}@media print{.two{display:block}}.three{color:red}',
- '.one,.three{color:red}@media print{.two{display:block}}'
- ]
- })
- )
.addBatch(
optimizerContext('same non-adjacent selectors', {
'with one redefined property': [
'a{color:red;color:red}',
'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}'
- ],
'non-adjacent': [
'a{color:red;display:block}.one{margin:12px}a{color:#fff;margin:2px}',
'.one{margin:12px}a{display:block;color:#fff;margin:2px}'
'a{color:red;color:red}',
'a{color:red;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}'
- ],
'non-adjacent': [
'a{color:red;display:block}.one{font-size:12px}a{color:#fff;margin:2px}',
'a{color:red;display:block}.one{font-size:12px}a{color:#fff;margin:2px}'
--- /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}a{display:block;width:100px}div{color:#fff}',
+ 'a{color:red;display:block;width:100px}div{color:#fff}'
+ ],
+ 'of two non-adjacent selectors': [
+ '.one{color:red}.two{color:#00f}.one{font-weight:700}',
+ '.one{color:red;font-weight:700}.two{color:#00f}'
+ ],
+ 'of two adjacent single selectors': [
+ '.one{color:red}.one{font-weight:700}',
+ '.one{color:red;font-weight:700}'
+ ],
+ 'of three adjacent single selectors': [
+ '.one{color:red}.one{font-weight:700}.one{font-size:12px}',
+ '.one{color:red;font-weight:700;font-size:12px}'
+ ],
+ 'of two adjacent single, complex selectors': [
+ '#box>.one{color:red}#box>.one{font-weight:700}',
+ '#box>.one{color:red;font-weight:700}'
+ ],
+ 'of two adjacent multiple, complex selectors': [
+ '#box>.one,.zero{color:red}#box>.one,.zero{font-weight:700}',
+ '#box>.one,.zero{color:red;font-weight:700}'
+ ],
+ 'of two adjacent selectors with duplicate properties #1': [
+ '.one{color:red}.one{color:#fff}',
+ '.one{color:#fff}'
+ ],
+ 'of two adjacent selectors with duplicate properties #2': [
+ '.one{color:red;font-weight:bold}.one{color:#fff;font-weight:400}',
+ '.one{color:#fff;font-weight:400}'
+ ],
+ 'of two adjacent complex selectors with different selector order': [
+ '.one,.two{color:red}.two,.one{line-height:1em}',
+ '.one,.two{color:red;line-height:1em}'
+ ],
+ 'two adjacent with hex color definitions': [
+ 'a:link,a:visited{color:#fff}.one{display:block}a:link,a:visited{color:red}',
+ '.one{display:block}a:link,a:visited{color:red}'
+ ],
+ 'in two passes': [
+ 'a{color:red}a{background:red}b{color:red}b{background:red}',
+ 'a,b{color:red;background:red}'
+ ],
+ 'when overriden with a browser specific selector': [
+ 'a{color:red}::-webkit-scrollbar,a{color:#fff}',
+ 'a{color:red}::-webkit-scrollbar,a{color:#fff}'
+ ],
+ 'two same selectors over a block': [
+ '.one{color:red}@media print{.two{display:block}}.one{display:none}',
+ '@media print{.two{display:block}}.one{color:red;display:none}'
+ ],
+ 'two same bodies over a block': [
+ '.one{color:red}@media print{.two{display:block}}.three{color:red}',
+ '.one,.three{color:red}@media print{.two{display:block}}'
+ ]
+ })
+ )
+ .addBatch(
+ optimizerContext('advanced off', {
+ 'same context': [
+ 'a{color:red}a{display:block;width:100px}div{color:#fff}',
+ 'a{color:red}a{display:block;width:100px}div{color:#fff}'
+ ],
+ }, { advanced: false })
+ )
+ .export(module);