clear
This commit is contained in:
86
node_modules/clean-css/lib/selectors/advanced.js
generated
vendored
Normal file
86
node_modules/clean-css/lib/selectors/advanced.js
generated
vendored
Normal file
@@ -0,0 +1,86 @@
|
||||
var optimizeProperties = require('../properties/optimizer');
|
||||
|
||||
var removeDuplicates = require('./remove-duplicates');
|
||||
var mergeAdjacent = require('./merge-adjacent');
|
||||
var reduceNonAdjacent = require('./reduce-non-adjacent');
|
||||
var mergeNonAdjacentBySelector = require('./merge-non-adjacent-by-selector');
|
||||
var mergeNonAdjacentByBody = require('./merge-non-adjacent-by-body');
|
||||
var restructure = require('./restructure');
|
||||
var removeDuplicateMediaQueries = require('./remove-duplicate-media-queries');
|
||||
var mergeMediaQueries = require('./merge-media-queries');
|
||||
|
||||
function removeEmpty(tokens) {
|
||||
for (var i = 0, l = tokens.length; i < l; i++) {
|
||||
var token = tokens[i];
|
||||
var isEmpty = false;
|
||||
|
||||
switch (token[0]) {
|
||||
case 'selector':
|
||||
isEmpty = token[1].length === 0 || token[2].length === 0;
|
||||
break;
|
||||
case 'block':
|
||||
removeEmpty(token[2]);
|
||||
isEmpty = token[2].length === 0;
|
||||
}
|
||||
|
||||
if (isEmpty) {
|
||||
tokens.splice(i, 1);
|
||||
i--;
|
||||
l--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function recursivelyOptimizeBlocks(tokens, options, context) {
|
||||
for (var i = 0, l = tokens.length; i < l; i++) {
|
||||
var token = tokens[i];
|
||||
|
||||
if (token[0] == 'block') {
|
||||
var isKeyframes = /@(-moz-|-o-|-webkit-)?keyframes/.test(token[1][0]);
|
||||
optimize(token[2], options, context, !isKeyframes);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function recursivelyOptimizeProperties(tokens, options, context) {
|
||||
for (var i = 0, l = tokens.length; i < l; i++) {
|
||||
var token = tokens[i];
|
||||
|
||||
switch (token[0]) {
|
||||
case 'selector':
|
||||
optimizeProperties(token[1], token[2], false, true, options, context);
|
||||
break;
|
||||
case 'block':
|
||||
recursivelyOptimizeProperties(token[2], options, context);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function optimize(tokens, options, context, withRestructuring) {
|
||||
recursivelyOptimizeBlocks(tokens, options, context);
|
||||
recursivelyOptimizeProperties(tokens, options, context);
|
||||
|
||||
removeDuplicates(tokens);
|
||||
mergeAdjacent(tokens, options, context);
|
||||
reduceNonAdjacent(tokens, options, context);
|
||||
|
||||
mergeNonAdjacentBySelector(tokens, options, context);
|
||||
mergeNonAdjacentByBody(tokens, options);
|
||||
|
||||
if (options.restructuring && withRestructuring) {
|
||||
restructure(tokens, options);
|
||||
mergeAdjacent(tokens, options, context);
|
||||
}
|
||||
|
||||
if (options.mediaMerging) {
|
||||
removeDuplicateMediaQueries(tokens);
|
||||
var reduced = mergeMediaQueries(tokens);
|
||||
for (var i = reduced.length - 1; i >= 0; i--) {
|
||||
optimize(reduced[i][2], options, context, false);
|
||||
}
|
||||
}
|
||||
|
||||
removeEmpty(tokens);
|
||||
}
|
||||
|
||||
module.exports = optimize;
|
||||
89
node_modules/clean-css/lib/selectors/clean-up.js
generated
vendored
Normal file
89
node_modules/clean-css/lib/selectors/clean-up.js
generated
vendored
Normal file
@@ -0,0 +1,89 @@
|
||||
function removeWhitespace(match, value) {
|
||||
return '[' + value.replace(/ /g, '') + ']';
|
||||
}
|
||||
|
||||
function selectorSorter(s1, s2) {
|
||||
return s1[0] > s2[0] ? 1 : -1;
|
||||
}
|
||||
|
||||
function whitespaceReplacements(_, p1, p2, p3) {
|
||||
if (p1 && p2 && p3.length)
|
||||
return p1 + p2 + ' ';
|
||||
else if (p1 && p2)
|
||||
return p1 + p2;
|
||||
else
|
||||
return p2;
|
||||
}
|
||||
|
||||
var CleanUp = {
|
||||
selectors: function (selectors, removeUnsupported, adjacentSpace) {
|
||||
var list = [];
|
||||
var repeated = [];
|
||||
|
||||
for (var i = 0, l = selectors.length; i < l; i++) {
|
||||
var selector = selectors[i];
|
||||
var reduced = selector[0]
|
||||
.replace(/\s+/g, ' ')
|
||||
.replace(/ ?, ?/g, ',')
|
||||
.replace(/\s*(\\)?([>+~])(\s*)/g, whitespaceReplacements)
|
||||
.trim();
|
||||
|
||||
if (adjacentSpace && reduced.indexOf('nav') > 0)
|
||||
reduced = reduced.replace(/\+nav(\S|$)/, '+ nav$1');
|
||||
|
||||
if (removeUnsupported && (reduced.indexOf('*+html ') != -1 || reduced.indexOf('*:first-child+html ') != -1))
|
||||
continue;
|
||||
|
||||
if (reduced.indexOf('*') > -1) {
|
||||
reduced = reduced
|
||||
.replace(/\*([:#\.\[])/g, '$1')
|
||||
.replace(/^(\:first\-child)?\+html/, '*$1+html');
|
||||
}
|
||||
|
||||
if (reduced.indexOf('[') > -1)
|
||||
reduced = reduced.replace(/\[([^\]]+)\]/g, removeWhitespace);
|
||||
|
||||
if (repeated.indexOf(reduced) == -1) {
|
||||
selector[0] = reduced;
|
||||
repeated.push(reduced);
|
||||
list.push(selector);
|
||||
}
|
||||
}
|
||||
|
||||
return list.sort(selectorSorter);
|
||||
},
|
||||
|
||||
selectorDuplicates: function (selectors) {
|
||||
var list = [];
|
||||
var repeated = [];
|
||||
|
||||
for (var i = 0, l = selectors.length; i < l; i++) {
|
||||
var selector = selectors[i];
|
||||
|
||||
if (repeated.indexOf(selector[0]) == -1) {
|
||||
repeated.push(selector[0]);
|
||||
list.push(selector);
|
||||
}
|
||||
}
|
||||
|
||||
return list.sort(selectorSorter);
|
||||
},
|
||||
|
||||
block: function (values, spaceAfterClosingBrace) {
|
||||
values[0] = values[0]
|
||||
.replace(/\s+/g, ' ')
|
||||
.replace(/(,|:|\() /g, '$1')
|
||||
.replace(/ \)/g, ')');
|
||||
|
||||
if (!spaceAfterClosingBrace)
|
||||
values[0] = values[0].replace(/\) /g, ')');
|
||||
},
|
||||
|
||||
atRule: function (values) {
|
||||
values[0] = values[0]
|
||||
.replace(/\s+/g, ' ')
|
||||
.trim();
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = CleanUp;
|
||||
69
node_modules/clean-css/lib/selectors/extractor.js
generated
vendored
Normal file
69
node_modules/clean-css/lib/selectors/extractor.js
generated
vendored
Normal file
@@ -0,0 +1,69 @@
|
||||
// This extractor is used in advanced optimizations
|
||||
// IMPORTANT: Mind Token class and this code is not related!
|
||||
// Properties will be tokenized in one step, see #429
|
||||
|
||||
var stringifySelectors = require('../stringifier/one-time').selectors;
|
||||
var stringifyValue = require('../stringifier/one-time').value;
|
||||
|
||||
var AT_RULE = 'at-rule';
|
||||
|
||||
function extract(token) {
|
||||
var properties = [];
|
||||
|
||||
if (token[0] == 'selector') {
|
||||
var inSpecificSelector = !/[\.\+>~]/.test(stringifySelectors(token[1]));
|
||||
for (var i = 0, l = token[2].length; i < l; i++) {
|
||||
var property = token[2][i];
|
||||
|
||||
if (property.indexOf('__ESCAPED') === 0)
|
||||
continue;
|
||||
|
||||
if (property[0] == AT_RULE)
|
||||
continue;
|
||||
|
||||
var name = token[2][i][0][0];
|
||||
if (name.length === 0)
|
||||
continue;
|
||||
|
||||
if (name.indexOf('--') === 0)
|
||||
continue;
|
||||
|
||||
var value = stringifyValue(token[2], i);
|
||||
|
||||
properties.push([
|
||||
name,
|
||||
value,
|
||||
findNameRoot(name),
|
||||
token[2][i],
|
||||
name + ':' + value,
|
||||
token[1],
|
||||
inSpecificSelector
|
||||
]);
|
||||
}
|
||||
} else if (token[0] == 'block') {
|
||||
for (var j = 0, k = token[2].length; j < k; j++) {
|
||||
properties = properties.concat(extract(token[2][j]));
|
||||
}
|
||||
}
|
||||
|
||||
return properties;
|
||||
}
|
||||
|
||||
function findNameRoot(name) {
|
||||
if (name == 'list-style')
|
||||
return name;
|
||||
if (name.indexOf('-radius') > 0)
|
||||
return 'border-radius';
|
||||
if (name == 'border-collapse' || name == 'border-spacing' || name == 'border-image')
|
||||
return name;
|
||||
if (name.indexOf('border-') === 0 && /^border\-\w+\-\w+$/.test(name))
|
||||
return name.match(/border\-\w+/)[0];
|
||||
if (name.indexOf('border-') === 0 && /^border\-\w+$/.test(name))
|
||||
return 'border';
|
||||
if (name.indexOf('text-') === 0)
|
||||
return name;
|
||||
|
||||
return name.replace(/^\-\w+\-/, '').match(/([a-zA-Z]+)/)[0].toLowerCase();
|
||||
}
|
||||
|
||||
module.exports = extract;
|
||||
5
node_modules/clean-css/lib/selectors/is-special.js
generated
vendored
Normal file
5
node_modules/clean-css/lib/selectors/is-special.js
generated
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
function isSpecial(options, selector) {
|
||||
return options.compatibility.selectors.special.test(selector);
|
||||
}
|
||||
|
||||
module.exports = isSpecial;
|
||||
35
node_modules/clean-css/lib/selectors/merge-adjacent.js
generated
vendored
Normal file
35
node_modules/clean-css/lib/selectors/merge-adjacent.js
generated
vendored
Normal file
@@ -0,0 +1,35 @@
|
||||
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, context) {
|
||||
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, context);
|
||||
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;
|
||||
64
node_modules/clean-css/lib/selectors/merge-media-queries.js
generated
vendored
Normal file
64
node_modules/clean-css/lib/selectors/merge-media-queries.js
generated
vendored
Normal file
@@ -0,0 +1,64 @@
|
||||
var canReorder = require('./reorderable').canReorder;
|
||||
var extractProperties = require('./extractor');
|
||||
|
||||
function mergeMediaQueries(tokens) {
|
||||
var candidates = {};
|
||||
var reduced = [];
|
||||
|
||||
for (var i = tokens.length - 1; i >= 0; i--) {
|
||||
var token = tokens[i];
|
||||
if (token[0] != 'block')
|
||||
continue;
|
||||
|
||||
var candidate = candidates[token[1][0]];
|
||||
if (!candidate) {
|
||||
candidate = [];
|
||||
candidates[token[1][0]] = candidate;
|
||||
}
|
||||
|
||||
candidate.push(i);
|
||||
}
|
||||
|
||||
for (var name in candidates) {
|
||||
var positions = candidates[name];
|
||||
|
||||
positionLoop:
|
||||
for (var j = positions.length - 1; j > 0; j--) {
|
||||
var positionOne = positions[j];
|
||||
var tokenOne = tokens[positionOne];
|
||||
var positionTwo = positions[j - 1];
|
||||
var tokenTwo = tokens[positionTwo];
|
||||
|
||||
directionLoop:
|
||||
for (var direction = 1; direction >= -1; direction -= 2) {
|
||||
var topToBottom = direction == 1;
|
||||
var from = topToBottom ? positionOne + 1 : positionTwo - 1;
|
||||
var to = topToBottom ? positionTwo : positionOne;
|
||||
var delta = topToBottom ? 1 : -1;
|
||||
var source = topToBottom ? tokenOne : tokenTwo;
|
||||
var target = topToBottom ? tokenTwo : tokenOne;
|
||||
var movedProperties = extractProperties(source);
|
||||
|
||||
while (from != to) {
|
||||
var traversedProperties = extractProperties(tokens[from]);
|
||||
from += delta;
|
||||
|
||||
if (!canReorder(movedProperties, traversedProperties))
|
||||
continue directionLoop;
|
||||
}
|
||||
|
||||
target[2] = topToBottom ?
|
||||
source[2].concat(target[2]) :
|
||||
target[2].concat(source[2]);
|
||||
source[2] = [];
|
||||
|
||||
reduced.push(target);
|
||||
continue positionLoop;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return reduced;
|
||||
}
|
||||
|
||||
module.exports = mergeMediaQueries;
|
||||
61
node_modules/clean-css/lib/selectors/merge-non-adjacent-by-body.js
generated
vendored
Normal file
61
node_modules/clean-css/lib/selectors/merge-non-adjacent-by-body.js
generated
vendored
Normal file
@@ -0,0 +1,61 @@
|
||||
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 unsafeSelector(value) {
|
||||
return /\.|\*| :/.test(value);
|
||||
}
|
||||
|
||||
function isBemElement(token) {
|
||||
var asString = stringifySelectors(token[1]);
|
||||
return asString.indexOf('__') > -1 || asString.indexOf('--') > -1;
|
||||
}
|
||||
|
||||
function withoutModifier(selector) {
|
||||
return selector.replace(/--[^ ,>\+~:]+/g, '');
|
||||
}
|
||||
|
||||
function removeAnyUnsafeElements(left, candidates) {
|
||||
var leftSelector = withoutModifier(stringifySelectors(left[1]));
|
||||
|
||||
for (var body in candidates) {
|
||||
var right = candidates[body];
|
||||
var rightSelector = withoutModifier(stringifySelectors(right[1]));
|
||||
|
||||
if (rightSelector.indexOf(leftSelector) > -1 || leftSelector.indexOf(rightSelector) > -1)
|
||||
delete candidates[body];
|
||||
}
|
||||
}
|
||||
|
||||
function mergeNonAdjacentByBody(tokens, options) {
|
||||
var candidates = {};
|
||||
var adjacentSpace = options.compatibility.selectors.adjacentSpace;
|
||||
|
||||
for (var i = tokens.length - 1; i >= 0; i--) {
|
||||
var token = tokens[i];
|
||||
if (token[0] != 'selector')
|
||||
continue;
|
||||
|
||||
if (token[2].length > 0 && (!options.semanticMerging && unsafeSelector(stringifySelectors(token[1]))))
|
||||
candidates = {};
|
||||
|
||||
if (token[2].length > 0 && options.semanticMerging && isBemElement(token))
|
||||
removeAnyUnsafeElements(token, candidates);
|
||||
|
||||
var candidateBody = stringifyBody(token[2]);
|
||||
var oldToken = candidates[candidateBody];
|
||||
if (oldToken && !isSpecial(options, stringifySelectors(token[1])) && !isSpecial(options, stringifySelectors(oldToken[1]))) {
|
||||
token[1] = token[2].length > 0 ?
|
||||
cleanUpSelectors(oldToken[1].concat(token[1]), false, adjacentSpace) :
|
||||
oldToken[1].concat(token[1]);
|
||||
|
||||
oldToken[2] = [];
|
||||
candidates[candidateBody] = null;
|
||||
}
|
||||
|
||||
candidates[stringifyBody(token[2])] = token;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = mergeNonAdjacentByBody;
|
||||
76
node_modules/clean-css/lib/selectors/merge-non-adjacent-by-selector.js
generated
vendored
Normal file
76
node_modules/clean-css/lib/selectors/merge-non-adjacent-by-selector.js
generated
vendored
Normal file
@@ -0,0 +1,76 @@
|
||||
var optimizeProperties = require('../properties/optimizer');
|
||||
var stringifySelectors = require('../stringifier/one-time').selectors;
|
||||
var extractProperties = require('./extractor');
|
||||
var canReorder = require('./reorderable').canReorder;
|
||||
|
||||
function mergeNonAdjacentBySelector(tokens, options, context) {
|
||||
var allSelectors = {};
|
||||
var repeatedSelectors = [];
|
||||
var i;
|
||||
|
||||
for (i = tokens.length - 1; i >= 0; i--) {
|
||||
if (tokens[i][0] != 'selector')
|
||||
continue;
|
||||
if (tokens[i][2].length === 0)
|
||||
continue;
|
||||
|
||||
var selector = stringifySelectors(tokens[i][1]);
|
||||
allSelectors[selector] = [i].concat(allSelectors[selector] || []);
|
||||
|
||||
if (allSelectors[selector].length == 2)
|
||||
repeatedSelectors.push(selector);
|
||||
}
|
||||
|
||||
for (i = repeatedSelectors.length - 1; i >= 0; i--) {
|
||||
var positions = allSelectors[repeatedSelectors[i]];
|
||||
|
||||
selectorIterator:
|
||||
for (var j = positions.length - 1; j > 0; j--) {
|
||||
var positionOne = positions[j - 1];
|
||||
var tokenOne = tokens[positionOne];
|
||||
var positionTwo = positions[j];
|
||||
var tokenTwo = tokens[positionTwo];
|
||||
|
||||
directionIterator:
|
||||
for (var direction = 1; direction >= -1; direction -= 2) {
|
||||
var topToBottom = direction == 1;
|
||||
var from = topToBottom ? positionOne + 1 : positionTwo - 1;
|
||||
var to = topToBottom ? positionTwo : positionOne;
|
||||
var delta = topToBottom ? 1 : -1;
|
||||
var moved = topToBottom ? tokenOne : tokenTwo;
|
||||
var target = topToBottom ? tokenTwo : tokenOne;
|
||||
var movedProperties = extractProperties(moved);
|
||||
var joinAt;
|
||||
|
||||
while (from != to) {
|
||||
var traversedProperties = extractProperties(tokens[from]);
|
||||
from += delta;
|
||||
|
||||
// traversed then moved as we move selectors towards the start
|
||||
var reorderable = topToBottom ?
|
||||
canReorder(movedProperties, traversedProperties) :
|
||||
canReorder(traversedProperties, movedProperties);
|
||||
|
||||
if (!reorderable && !topToBottom)
|
||||
continue selectorIterator;
|
||||
if (!reorderable && topToBottom)
|
||||
continue directionIterator;
|
||||
}
|
||||
|
||||
if (topToBottom) {
|
||||
joinAt = [moved[2].length];
|
||||
Array.prototype.push.apply(moved[2], target[2]);
|
||||
target[2] = moved[2];
|
||||
} else {
|
||||
joinAt = [target[2].length];
|
||||
Array.prototype.push.apply(target[2], moved[2]);
|
||||
}
|
||||
|
||||
optimizeProperties(target[1], target[2], joinAt, true, options, context);
|
||||
moved[2] = [];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = mergeNonAdjacentBySelector;
|
||||
172
node_modules/clean-css/lib/selectors/reduce-non-adjacent.js
generated
vendored
Normal file
172
node_modules/clean-css/lib/selectors/reduce-non-adjacent.js
generated
vendored
Normal file
@@ -0,0 +1,172 @@
|
||||
var optimizeProperties = require('../properties/optimizer');
|
||||
var stringifyBody = require('../stringifier/one-time').body;
|
||||
var stringifySelectors = require('../stringifier/one-time').selectors;
|
||||
var isSpecial = require('./is-special');
|
||||
var cloneArray = require('../utils/clone-array');
|
||||
|
||||
function reduceNonAdjacent(tokens, options, context) {
|
||||
var candidates = {};
|
||||
var repeated = [];
|
||||
|
||||
for (var i = tokens.length - 1; i >= 0; i--) {
|
||||
var token = tokens[i];
|
||||
|
||||
if (token[0] != 'selector')
|
||||
continue;
|
||||
if (token[2].length === 0)
|
||||
continue;
|
||||
|
||||
var selectorAsString = stringifySelectors(token[1]);
|
||||
var isComplexAndNotSpecial = token[1].length > 1 && !isSpecial(options, selectorAsString);
|
||||
var wrappedSelectors = options.sourceMap ? wrappedSelectorsFrom(token[1]) : token[1];
|
||||
var selectors = isComplexAndNotSpecial ?
|
||||
[selectorAsString].concat(wrappedSelectors) :
|
||||
[selectorAsString];
|
||||
|
||||
for (var j = 0, m = selectors.length; j < m; j++) {
|
||||
var selector = selectors[j];
|
||||
|
||||
if (!candidates[selector])
|
||||
candidates[selector] = [];
|
||||
else
|
||||
repeated.push(selector);
|
||||
|
||||
candidates[selector].push({
|
||||
where: i,
|
||||
list: wrappedSelectors,
|
||||
isPartial: isComplexAndNotSpecial && j > 0,
|
||||
isComplex: isComplexAndNotSpecial && j === 0
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
reduceSimpleNonAdjacentCases(tokens, repeated, candidates, options, context);
|
||||
reduceComplexNonAdjacentCases(tokens, candidates, options, context);
|
||||
}
|
||||
|
||||
function wrappedSelectorsFrom(list) {
|
||||
var wrapped = [];
|
||||
|
||||
for (var i = 0; i < list.length; i++) {
|
||||
wrapped.push([list[i][0]]);
|
||||
}
|
||||
|
||||
return wrapped;
|
||||
}
|
||||
|
||||
function reduceSimpleNonAdjacentCases(tokens, repeated, candidates, options, context) {
|
||||
function filterOut(idx, bodies) {
|
||||
return data[idx].isPartial && bodies.length === 0;
|
||||
}
|
||||
|
||||
function reduceBody(token, newBody, processedCount, tokenIdx) {
|
||||
if (!data[processedCount - tokenIdx - 1].isPartial)
|
||||
token[2] = newBody;
|
||||
}
|
||||
|
||||
for (var i = 0, l = repeated.length; i < l; i++) {
|
||||
var selector = repeated[i];
|
||||
var data = candidates[selector];
|
||||
|
||||
reduceSelector(tokens, selector, data, {
|
||||
filterOut: filterOut,
|
||||
callback: reduceBody
|
||||
}, options, context);
|
||||
}
|
||||
}
|
||||
|
||||
function reduceComplexNonAdjacentCases(tokens, candidates, options, context) {
|
||||
var localContext = {};
|
||||
|
||||
function filterOut(idx) {
|
||||
return localContext.data[idx].where < localContext.intoPosition;
|
||||
}
|
||||
|
||||
function collectReducedBodies(token, newBody, processedCount, tokenIdx) {
|
||||
if (tokenIdx === 0)
|
||||
localContext.reducedBodies.push(newBody);
|
||||
}
|
||||
|
||||
allSelectors:
|
||||
for (var complexSelector in candidates) {
|
||||
var into = candidates[complexSelector];
|
||||
if (!into[0].isComplex)
|
||||
continue;
|
||||
|
||||
var intoPosition = into[into.length - 1].where;
|
||||
var intoToken = tokens[intoPosition];
|
||||
var reducedBodies = [];
|
||||
|
||||
var selectors = isSpecial(options, complexSelector) ?
|
||||
[complexSelector] :
|
||||
into[0].list;
|
||||
|
||||
localContext.intoPosition = intoPosition;
|
||||
localContext.reducedBodies = reducedBodies;
|
||||
|
||||
for (var j = 0, m = selectors.length; j < m; j++) {
|
||||
var selector = selectors[j];
|
||||
var data = candidates[selector];
|
||||
|
||||
if (data.length < 2)
|
||||
continue allSelectors;
|
||||
|
||||
localContext.data = data;
|
||||
|
||||
reduceSelector(tokens, selector, data, {
|
||||
filterOut: filterOut,
|
||||
callback: collectReducedBodies
|
||||
}, options, context);
|
||||
|
||||
if (stringifyBody(reducedBodies[reducedBodies.length - 1]) != stringifyBody(reducedBodies[0]))
|
||||
continue allSelectors;
|
||||
}
|
||||
|
||||
intoToken[2] = reducedBodies[0];
|
||||
}
|
||||
}
|
||||
|
||||
function reduceSelector(tokens, selector, data, context, options, outerContext) {
|
||||
var bodies = [];
|
||||
var bodiesAsList = [];
|
||||
var joinsAt = [];
|
||||
var processedTokens = [];
|
||||
|
||||
for (var j = data.length - 1, m = 0; j >= 0; j--) {
|
||||
if (context.filterOut(j, bodies))
|
||||
continue;
|
||||
|
||||
var where = data[j].where;
|
||||
var token = tokens[where];
|
||||
var clonedBody = cloneArray(token[2]);
|
||||
|
||||
bodies = bodies.concat(clonedBody);
|
||||
bodiesAsList.push(clonedBody);
|
||||
processedTokens.push(where);
|
||||
}
|
||||
|
||||
for (j = 0, m = bodiesAsList.length; j < m; j++) {
|
||||
if (bodiesAsList[j].length > 0)
|
||||
joinsAt.push((joinsAt.length > 0 ? joinsAt[joinsAt.length - 1] : 0) + bodiesAsList[j].length);
|
||||
}
|
||||
|
||||
optimizeProperties(selector, bodies, joinsAt, false, options, outerContext);
|
||||
|
||||
var processedCount = processedTokens.length;
|
||||
var propertyIdx = bodies.length - 1;
|
||||
var tokenIdx = processedCount - 1;
|
||||
|
||||
while (tokenIdx >= 0) {
|
||||
if ((tokenIdx === 0 || (bodies[propertyIdx] && bodiesAsList[tokenIdx].indexOf(bodies[propertyIdx]) > -1)) && propertyIdx > -1) {
|
||||
propertyIdx--;
|
||||
continue;
|
||||
}
|
||||
|
||||
var newBody = bodies.splice(propertyIdx + 1);
|
||||
context.callback(tokens[processedTokens[tokenIdx]], newBody, processedCount, tokenIdx);
|
||||
|
||||
tokenIdx--;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = reduceNonAdjacent;
|
||||
21
node_modules/clean-css/lib/selectors/remove-duplicate-media-queries.js
generated
vendored
Normal file
21
node_modules/clean-css/lib/selectors/remove-duplicate-media-queries.js
generated
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
var stringifyAll = require('../stringifier/one-time').all;
|
||||
|
||||
function removeDuplicateMediaQueries(tokens) {
|
||||
var candidates = {};
|
||||
|
||||
for (var i = 0, l = tokens.length; i < l; i++) {
|
||||
var token = tokens[i];
|
||||
if (token[0] != 'block')
|
||||
continue;
|
||||
|
||||
var key = token[1][0] + '%' + stringifyAll(token[2]);
|
||||
var candidate = candidates[key];
|
||||
|
||||
if (candidate)
|
||||
candidate[2] = [];
|
||||
|
||||
candidates[key] = token;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = removeDuplicateMediaQueries;
|
||||
41
node_modules/clean-css/lib/selectors/remove-duplicates.js
generated
vendored
Normal file
41
node_modules/clean-css/lib/selectors/remove-duplicates.js
generated
vendored
Normal file
@@ -0,0 +1,41 @@
|
||||
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;
|
||||
99
node_modules/clean-css/lib/selectors/reorderable.js
generated
vendored
Normal file
99
node_modules/clean-css/lib/selectors/reorderable.js
generated
vendored
Normal file
@@ -0,0 +1,99 @@
|
||||
// TODO: it'd be great to merge it with the other canReorder functionality
|
||||
|
||||
var FLEX_PROPERTIES = /align\-items|box\-align|box\-pack|flex|justify/;
|
||||
var BORDER_PROPERTIES = /^border\-(top|right|bottom|left|color|style|width|radius)/;
|
||||
|
||||
function canReorder(left, right) {
|
||||
for (var i = right.length - 1; i >= 0; i--) {
|
||||
for (var j = left.length - 1; j >= 0; j--) {
|
||||
if (!canReorderSingle(left[j], right[i]))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
function canReorderSingle(left, right) {
|
||||
var leftName = left[0];
|
||||
var leftValue = left[1];
|
||||
var leftNameRoot = left[2];
|
||||
var leftSelector = left[5];
|
||||
var leftInSpecificSelector = left[6];
|
||||
var rightName = right[0];
|
||||
var rightValue = right[1];
|
||||
var rightNameRoot = right[2];
|
||||
var rightSelector = right[5];
|
||||
var rightInSpecificSelector = right[6];
|
||||
|
||||
if (leftName == 'font' && rightName == 'line-height' || rightName == 'font' && leftName == 'line-height')
|
||||
return false;
|
||||
if (FLEX_PROPERTIES.test(leftName) && FLEX_PROPERTIES.test(rightName))
|
||||
return false;
|
||||
if (leftNameRoot == rightNameRoot && unprefixed(leftName) == unprefixed(rightName) && (vendorPrefixed(leftName) ^ vendorPrefixed(rightName)))
|
||||
return false;
|
||||
if (leftNameRoot == 'border' && BORDER_PROPERTIES.test(rightNameRoot) && (leftName == 'border' || leftName == rightNameRoot || (leftValue != rightValue && sameBorderComponent(leftName, rightName))))
|
||||
return false;
|
||||
if (rightNameRoot == 'border' && BORDER_PROPERTIES.test(leftNameRoot) && (rightName == 'border' || rightName == leftNameRoot || (leftValue != rightValue && sameBorderComponent(leftName, rightName))))
|
||||
return false;
|
||||
if (leftNameRoot == 'border' && rightNameRoot == 'border' && leftName != rightName && (isSideBorder(leftName) && isStyleBorder(rightName) || isStyleBorder(leftName) && isSideBorder(rightName)))
|
||||
return false;
|
||||
if (leftNameRoot != rightNameRoot)
|
||||
return true;
|
||||
if (leftName == rightName && leftNameRoot == rightNameRoot && (leftValue == rightValue || withDifferentVendorPrefix(leftValue, rightValue)))
|
||||
return true;
|
||||
if (leftName != rightName && leftNameRoot == rightNameRoot && leftName != leftNameRoot && rightName != rightNameRoot)
|
||||
return true;
|
||||
if (leftName != rightName && leftNameRoot == rightNameRoot && leftValue == rightValue)
|
||||
return true;
|
||||
if (rightInSpecificSelector && leftInSpecificSelector && !inheritable(leftNameRoot) && !inheritable(rightNameRoot) && selectorsDoNotOverlap(rightSelector, leftSelector))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function vendorPrefixed(name) {
|
||||
return /^\-(?:moz|webkit|ms|o)\-/.test(name);
|
||||
}
|
||||
|
||||
function unprefixed(name) {
|
||||
return name.replace(/^\-(?:moz|webkit|ms|o)\-/, '');
|
||||
}
|
||||
|
||||
function sameBorderComponent(name1, name2) {
|
||||
return name1.split('-').pop() == name2.split('-').pop();
|
||||
}
|
||||
|
||||
function isSideBorder(name) {
|
||||
return name == 'border-top' || name == 'border-right' || name == 'border-bottom' || name == 'border-left';
|
||||
}
|
||||
|
||||
function isStyleBorder(name) {
|
||||
return name == 'border-color' || name == 'border-style' || name == 'border-width';
|
||||
}
|
||||
|
||||
function withDifferentVendorPrefix(value1, value2) {
|
||||
return vendorPrefixed(value1) && vendorPrefixed(value2) && value1.split('-')[1] != value2.split('-')[2];
|
||||
}
|
||||
|
||||
function selectorsDoNotOverlap(s1, s2) {
|
||||
for (var i = 0, l = s1.length; i < l; i++) {
|
||||
for (var j = 0, m = s2.length; j < m; j++) {
|
||||
if (s1[i][0] == s2[j][0])
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
function inheritable(name) {
|
||||
// According to http://www.w3.org/TR/CSS21/propidx.html
|
||||
// Others will be catched by other, preceeding rules
|
||||
return name == 'font' || name == 'line-height' || name == 'list-style';
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
canReorder: canReorder,
|
||||
canReorderSingle: canReorderSingle
|
||||
};
|
||||
369
node_modules/clean-css/lib/selectors/restructure.js
generated
vendored
Normal file
369
node_modules/clean-css/lib/selectors/restructure.js
generated
vendored
Normal file
@@ -0,0 +1,369 @@
|
||||
var extractProperties = require('./extractor');
|
||||
var canReorderSingle = require('./reorderable').canReorderSingle;
|
||||
var stringifyBody = require('../stringifier/one-time').body;
|
||||
var stringifySelectors = require('../stringifier/one-time').selectors;
|
||||
var cleanUpSelectorDuplicates = require('./clean-up').selectorDuplicates;
|
||||
var isSpecial = require('./is-special');
|
||||
var cloneArray = require('../utils/clone-array');
|
||||
|
||||
function naturalSorter(a, b) {
|
||||
return a > b;
|
||||
}
|
||||
|
||||
function cloneAndMergeSelectors(propertyA, propertyB) {
|
||||
var cloned = cloneArray(propertyA);
|
||||
cloned[5] = cloned[5].concat(propertyB[5]);
|
||||
|
||||
return cloned;
|
||||
}
|
||||
|
||||
function restructure(tokens, options) {
|
||||
var movableTokens = {};
|
||||
var movedProperties = [];
|
||||
var multiPropertyMoveCache = {};
|
||||
var movedToBeDropped = [];
|
||||
var maxCombinationsLevel = 2;
|
||||
var ID_JOIN_CHARACTER = '%';
|
||||
|
||||
function sendToMultiPropertyMoveCache(position, movedProperty, allFits) {
|
||||
for (var i = allFits.length - 1; i >= 0; i--) {
|
||||
var fit = allFits[i][0];
|
||||
var id = addToCache(movedProperty, fit);
|
||||
|
||||
if (multiPropertyMoveCache[id].length > 1 && processMultiPropertyMove(position, multiPropertyMoveCache[id])) {
|
||||
removeAllMatchingFromCache(id);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function addToCache(movedProperty, fit) {
|
||||
var id = cacheId(fit);
|
||||
multiPropertyMoveCache[id] = multiPropertyMoveCache[id] || [];
|
||||
multiPropertyMoveCache[id].push([movedProperty, fit]);
|
||||
return id;
|
||||
}
|
||||
|
||||
function removeAllMatchingFromCache(matchId) {
|
||||
var matchSelectors = matchId.split(ID_JOIN_CHARACTER);
|
||||
var forRemoval = [];
|
||||
var i;
|
||||
|
||||
for (var id in multiPropertyMoveCache) {
|
||||
var selectors = id.split(ID_JOIN_CHARACTER);
|
||||
for (i = selectors.length - 1; i >= 0; i--) {
|
||||
if (matchSelectors.indexOf(selectors[i]) > -1) {
|
||||
forRemoval.push(id);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (i = forRemoval.length - 1; i >= 0; i--) {
|
||||
delete multiPropertyMoveCache[forRemoval[i]];
|
||||
}
|
||||
}
|
||||
|
||||
function cacheId(cachedTokens) {
|
||||
var id = [];
|
||||
for (var i = 0, l = cachedTokens.length; i < l; i++) {
|
||||
id.push(stringifySelectors(cachedTokens[i][1]));
|
||||
}
|
||||
return id.join(ID_JOIN_CHARACTER);
|
||||
}
|
||||
|
||||
function tokensToMerge(sourceTokens) {
|
||||
var uniqueTokensWithBody = [];
|
||||
var mergeableTokens = [];
|
||||
|
||||
for (var i = sourceTokens.length - 1; i >= 0; i--) {
|
||||
if (isSpecial(options, stringifySelectors(sourceTokens[i][1])))
|
||||
continue;
|
||||
|
||||
mergeableTokens.unshift(sourceTokens[i]);
|
||||
if (sourceTokens[i][2].length > 0 && uniqueTokensWithBody.indexOf(sourceTokens[i]) == -1)
|
||||
uniqueTokensWithBody.push(sourceTokens[i]);
|
||||
}
|
||||
|
||||
return uniqueTokensWithBody.length > 1 ?
|
||||
mergeableTokens :
|
||||
[];
|
||||
}
|
||||
|
||||
function shortenIfPossible(position, movedProperty) {
|
||||
var name = movedProperty[0];
|
||||
var value = movedProperty[1];
|
||||
var key = movedProperty[4];
|
||||
var valueSize = name.length + value.length + 1;
|
||||
var allSelectors = [];
|
||||
var qualifiedTokens = [];
|
||||
|
||||
var mergeableTokens = tokensToMerge(movableTokens[key]);
|
||||
if (mergeableTokens.length < 2)
|
||||
return;
|
||||
|
||||
var allFits = findAllFits(mergeableTokens, valueSize, 1);
|
||||
var bestFit = allFits[0];
|
||||
if (bestFit[1] > 0)
|
||||
return sendToMultiPropertyMoveCache(position, movedProperty, allFits);
|
||||
|
||||
for (var i = bestFit[0].length - 1; i >=0; i--) {
|
||||
allSelectors = bestFit[0][i][1].concat(allSelectors);
|
||||
qualifiedTokens.unshift(bestFit[0][i]);
|
||||
}
|
||||
|
||||
allSelectors = cleanUpSelectorDuplicates(allSelectors);
|
||||
dropAsNewTokenAt(position, [movedProperty], allSelectors, qualifiedTokens);
|
||||
}
|
||||
|
||||
function fitSorter(fit1, fit2) {
|
||||
return fit1[1] > fit2[1];
|
||||
}
|
||||
|
||||
function findAllFits(mergeableTokens, propertySize, propertiesCount) {
|
||||
var combinations = allCombinations(mergeableTokens, propertySize, propertiesCount, maxCombinationsLevel - 1);
|
||||
return combinations.sort(fitSorter);
|
||||
}
|
||||
|
||||
function allCombinations(tokensVariant, propertySize, propertiesCount, level) {
|
||||
var differenceVariants = [[tokensVariant, sizeDifference(tokensVariant, propertySize, propertiesCount)]];
|
||||
if (tokensVariant.length > 2 && level > 0) {
|
||||
for (var i = tokensVariant.length - 1; i >= 0; i--) {
|
||||
var subVariant = Array.prototype.slice.call(tokensVariant, 0);
|
||||
subVariant.splice(i, 1);
|
||||
differenceVariants = differenceVariants.concat(allCombinations(subVariant, propertySize, propertiesCount, level - 1));
|
||||
}
|
||||
}
|
||||
|
||||
return differenceVariants;
|
||||
}
|
||||
|
||||
function sizeDifference(tokensVariant, propertySize, propertiesCount) {
|
||||
var allSelectorsSize = 0;
|
||||
for (var i = tokensVariant.length - 1; i >= 0; i--) {
|
||||
allSelectorsSize += tokensVariant[i][2].length > propertiesCount ? stringifySelectors(tokensVariant[i][1]).length : -1;
|
||||
}
|
||||
return allSelectorsSize - (tokensVariant.length - 1) * propertySize + 1;
|
||||
}
|
||||
|
||||
function dropAsNewTokenAt(position, properties, allSelectors, mergeableTokens) {
|
||||
var i, j, k, m;
|
||||
var allProperties = [];
|
||||
|
||||
for (i = mergeableTokens.length - 1; i >= 0; i--) {
|
||||
var mergeableToken = mergeableTokens[i];
|
||||
|
||||
for (j = mergeableToken[2].length - 1; j >= 0; j--) {
|
||||
var mergeableProperty = mergeableToken[2][j];
|
||||
|
||||
for (k = 0, m = properties.length; k < m; k++) {
|
||||
var property = properties[k];
|
||||
|
||||
var mergeablePropertyName = mergeableProperty[0][0];
|
||||
var propertyName = property[0];
|
||||
var propertyBody = property[4];
|
||||
if (mergeablePropertyName == propertyName && stringifyBody([mergeableProperty]) == propertyBody) {
|
||||
mergeableToken[2].splice(j, 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (i = properties.length - 1; i >= 0; i--) {
|
||||
allProperties.unshift(properties[i][3]);
|
||||
}
|
||||
|
||||
var newToken = ['selector', allSelectors, allProperties];
|
||||
tokens.splice(position, 0, newToken);
|
||||
}
|
||||
|
||||
function dropPropertiesAt(position, movedProperty) {
|
||||
var key = movedProperty[4];
|
||||
var toMove = movableTokens[key];
|
||||
|
||||
if (toMove && toMove.length > 1) {
|
||||
if (!shortenMultiMovesIfPossible(position, movedProperty))
|
||||
shortenIfPossible(position, movedProperty);
|
||||
}
|
||||
}
|
||||
|
||||
function shortenMultiMovesIfPossible(position, movedProperty) {
|
||||
var candidates = [];
|
||||
var propertiesAndMergableTokens = [];
|
||||
var key = movedProperty[4];
|
||||
var j, k;
|
||||
|
||||
var mergeableTokens = tokensToMerge(movableTokens[key]);
|
||||
if (mergeableTokens.length < 2)
|
||||
return;
|
||||
|
||||
movableLoop:
|
||||
for (var value in movableTokens) {
|
||||
var tokensList = movableTokens[value];
|
||||
|
||||
for (j = mergeableTokens.length - 1; j >= 0; j--) {
|
||||
if (tokensList.indexOf(mergeableTokens[j]) == -1)
|
||||
continue movableLoop;
|
||||
}
|
||||
|
||||
candidates.push(value);
|
||||
}
|
||||
|
||||
if (candidates.length < 2)
|
||||
return false;
|
||||
|
||||
for (j = candidates.length - 1; j >= 0; j--) {
|
||||
for (k = movedProperties.length - 1; k >= 0; k--) {
|
||||
if (movedProperties[k][4] == candidates[j]) {
|
||||
propertiesAndMergableTokens.unshift([movedProperties[k], mergeableTokens]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return processMultiPropertyMove(position, propertiesAndMergableTokens);
|
||||
}
|
||||
|
||||
function processMultiPropertyMove(position, propertiesAndMergableTokens) {
|
||||
var valueSize = 0;
|
||||
var properties = [];
|
||||
var property;
|
||||
|
||||
for (var i = propertiesAndMergableTokens.length - 1; i >= 0; i--) {
|
||||
property = propertiesAndMergableTokens[i][0];
|
||||
var fullValue = property[4];
|
||||
valueSize += fullValue.length + (i > 0 ? 1 : 0);
|
||||
|
||||
properties.push(property);
|
||||
}
|
||||
|
||||
var mergeableTokens = propertiesAndMergableTokens[0][1];
|
||||
var bestFit = findAllFits(mergeableTokens, valueSize, properties.length)[0];
|
||||
if (bestFit[1] > 0)
|
||||
return false;
|
||||
|
||||
var allSelectors = [];
|
||||
var qualifiedTokens = [];
|
||||
for (i = bestFit[0].length - 1; i >= 0; i--) {
|
||||
allSelectors = bestFit[0][i][1].concat(allSelectors);
|
||||
qualifiedTokens.unshift(bestFit[0][i]);
|
||||
}
|
||||
|
||||
allSelectors = cleanUpSelectorDuplicates(allSelectors);
|
||||
dropAsNewTokenAt(position, properties, allSelectors, qualifiedTokens);
|
||||
|
||||
for (i = properties.length - 1; i >= 0; i--) {
|
||||
property = properties[i];
|
||||
var index = movedProperties.indexOf(property);
|
||||
|
||||
delete movableTokens[property[4]];
|
||||
|
||||
if (index > -1 && movedToBeDropped.indexOf(index) == -1)
|
||||
movedToBeDropped.push(index);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
function boundToAnotherPropertyInCurrrentToken(property, movedProperty, token) {
|
||||
var propertyName = property[0];
|
||||
var movedPropertyName = movedProperty[0];
|
||||
if (propertyName != movedPropertyName)
|
||||
return false;
|
||||
|
||||
var key = movedProperty[4];
|
||||
var toMove = movableTokens[key];
|
||||
return toMove && toMove.indexOf(token) > -1;
|
||||
}
|
||||
|
||||
for (var i = tokens.length - 1; i >= 0; i--) {
|
||||
var token = tokens[i];
|
||||
var isSelector;
|
||||
var j, k, m;
|
||||
var samePropertyAt;
|
||||
|
||||
if (token[0] == 'selector') {
|
||||
isSelector = true;
|
||||
} else if (token[0] == 'block') {
|
||||
isSelector = false;
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
|
||||
// We cache movedProperties.length as it may change in the loop
|
||||
var movedCount = movedProperties.length;
|
||||
|
||||
var properties = extractProperties(token);
|
||||
movedToBeDropped = [];
|
||||
|
||||
var unmovableInCurrentToken = [];
|
||||
for (j = properties.length - 1; j >= 0; j--) {
|
||||
for (k = j - 1; k >= 0; k--) {
|
||||
if (!canReorderSingle(properties[j], properties[k])) {
|
||||
unmovableInCurrentToken.push(j);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (j = properties.length - 1; j >= 0; j--) {
|
||||
var property = properties[j];
|
||||
var movedSameProperty = false;
|
||||
|
||||
for (k = 0; k < movedCount; k++) {
|
||||
var movedProperty = movedProperties[k];
|
||||
|
||||
if (movedToBeDropped.indexOf(k) == -1 && !canReorderSingle(property, movedProperty) && !boundToAnotherPropertyInCurrrentToken(property, movedProperty, token)) {
|
||||
dropPropertiesAt(i + 1, movedProperty, token);
|
||||
|
||||
if (movedToBeDropped.indexOf(k) == -1) {
|
||||
movedToBeDropped.push(k);
|
||||
delete movableTokens[movedProperty[4]];
|
||||
}
|
||||
}
|
||||
|
||||
if (!movedSameProperty) {
|
||||
movedSameProperty = property[0] == movedProperty[0] && property[1] == movedProperty[1];
|
||||
|
||||
if (movedSameProperty) {
|
||||
samePropertyAt = k;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!isSelector || unmovableInCurrentToken.indexOf(j) > -1)
|
||||
continue;
|
||||
|
||||
var key = property[4];
|
||||
movableTokens[key] = movableTokens[key] || [];
|
||||
movableTokens[key].push(token);
|
||||
|
||||
if (movedSameProperty) {
|
||||
movedProperties[samePropertyAt] = cloneAndMergeSelectors(movedProperties[samePropertyAt], property);
|
||||
} else {
|
||||
movedProperties.push(property);
|
||||
}
|
||||
}
|
||||
|
||||
movedToBeDropped = movedToBeDropped.sort(naturalSorter);
|
||||
for (j = 0, m = movedToBeDropped.length; j < m; j++) {
|
||||
var dropAt = movedToBeDropped[j] - j;
|
||||
movedProperties.splice(dropAt, 1);
|
||||
}
|
||||
}
|
||||
|
||||
var position = tokens[0] && tokens[0][0] == 'at-rule' && tokens[0][1][0].indexOf('@charset') === 0 ? 1 : 0;
|
||||
for (; position < tokens.length - 1; position++) {
|
||||
var isImportRule = tokens[position][0] === 'at-rule' && tokens[position][1][0].indexOf('@import') === 0;
|
||||
var isEscapedCommentSpecial = tokens[position][0] === 'text' && tokens[position][1][0].indexOf('__ESCAPED_COMMENT_SPECIAL') === 0;
|
||||
if (!(isImportRule || isEscapedCommentSpecial))
|
||||
break;
|
||||
}
|
||||
|
||||
for (i = 0; i < movedProperties.length; i++) {
|
||||
dropPropertiesAt(position, movedProperties[i]);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = restructure;
|
||||
454
node_modules/clean-css/lib/selectors/simple.js
generated
vendored
Normal file
454
node_modules/clean-css/lib/selectors/simple.js
generated
vendored
Normal file
@@ -0,0 +1,454 @@
|
||||
var cleanUpSelectors = require('./clean-up').selectors;
|
||||
var cleanUpBlock = require('./clean-up').block;
|
||||
var cleanUpAtRule = require('./clean-up').atRule;
|
||||
var split = require('../utils/split');
|
||||
|
||||
var RGB = require('../colors/rgb');
|
||||
var HSL = require('../colors/hsl');
|
||||
var HexNameShortener = require('../colors/hex-name-shortener');
|
||||
|
||||
var wrapForOptimizing = require('../properties/wrap-for-optimizing').all;
|
||||
var restoreFromOptimizing = require('../properties/restore-from-optimizing');
|
||||
var removeUnused = require('../properties/remove-unused');
|
||||
|
||||
var DEFAULT_ROUNDING_PRECISION = 2;
|
||||
var CHARSET_TOKEN = '@charset';
|
||||
var CHARSET_REGEXP = new RegExp('^' + CHARSET_TOKEN, 'i');
|
||||
var IMPORT_REGEXP = /^@import["'\s]/i;
|
||||
|
||||
var FONT_NUMERAL_WEIGHTS = ['100', '200', '300', '400', '500', '600', '700', '800', '900'];
|
||||
var FONT_NAME_WEIGHTS = ['normal', 'bold', 'bolder', 'lighter'];
|
||||
var FONT_NAME_WEIGHTS_WITHOUT_NORMAL = ['bold', 'bolder', 'lighter'];
|
||||
|
||||
var WHOLE_PIXEL_VALUE = /(?:^|\s|\()(-?\d+)px/;
|
||||
var TIME_VALUE = /^(\-?[\d\.]+)(m?s)$/;
|
||||
|
||||
var valueMinifiers = {
|
||||
'background': function (value, index, total) {
|
||||
return index === 0 && total == 1 && (value == 'none' || value == 'transparent') ? '0 0' : value;
|
||||
},
|
||||
'font-weight': function (value) {
|
||||
if (value == 'normal')
|
||||
return '400';
|
||||
else if (value == 'bold')
|
||||
return '700';
|
||||
else
|
||||
return value;
|
||||
},
|
||||
'outline': function (value, index, total) {
|
||||
return index === 0 && total == 1 && value == 'none' ? '0' : value;
|
||||
}
|
||||
};
|
||||
|
||||
function isNegative(property, idx) {
|
||||
return property.value[idx] && property.value[idx][0][0] == '-' && parseFloat(property.value[idx][0]) < 0;
|
||||
}
|
||||
|
||||
function zeroMinifier(name, value) {
|
||||
if (value.indexOf('0') == -1)
|
||||
return value;
|
||||
|
||||
if (value.indexOf('-') > -1) {
|
||||
value = value
|
||||
.replace(/([^\w\d\-]|^)\-0([^\.]|$)/g, '$10$2')
|
||||
.replace(/([^\w\d\-]|^)\-0([^\.]|$)/g, '$10$2');
|
||||
}
|
||||
|
||||
return value
|
||||
.replace(/(^|\s)0+([1-9])/g, '$1$2')
|
||||
.replace(/(^|\D)\.0+(\D|$)/g, '$10$2')
|
||||
.replace(/(^|\D)\.0+(\D|$)/g, '$10$2')
|
||||
.replace(/\.([1-9]*)0+(\D|$)/g, function (match, nonZeroPart, suffix) {
|
||||
return (nonZeroPart.length > 0 ? '.' : '') + nonZeroPart + suffix;
|
||||
})
|
||||
.replace(/(^|\D)0\.(\d)/g, '$1.$2');
|
||||
}
|
||||
|
||||
function zeroDegMinifier(_, value) {
|
||||
if (value.indexOf('0deg') == -1)
|
||||
return value;
|
||||
|
||||
return value.replace(/\(0deg\)/g, '(0)');
|
||||
}
|
||||
|
||||
function whitespaceMinifier(name, value) {
|
||||
if (name.indexOf('filter') > -1 || value.indexOf(' ') == -1)
|
||||
return value;
|
||||
|
||||
value = value.replace(/\s+/g, ' ');
|
||||
|
||||
if (value.indexOf('calc') > -1)
|
||||
value = value.replace(/\) ?\/ ?/g, ')/ ');
|
||||
|
||||
return value
|
||||
.replace(/\( /g, '(')
|
||||
.replace(/ \)/g, ')')
|
||||
.replace(/, /g, ',');
|
||||
}
|
||||
|
||||
function precisionMinifier(_, value, precisionOptions) {
|
||||
if (precisionOptions.value === -1 || value.indexOf('.') === -1)
|
||||
return value;
|
||||
|
||||
return value
|
||||
.replace(precisionOptions.regexp, function (match, number) {
|
||||
return Math.round(parseFloat(number) * precisionOptions.multiplier) / precisionOptions.multiplier + 'px';
|
||||
})
|
||||
.replace(/(\d)\.($|\D)/g, '$1$2');
|
||||
}
|
||||
|
||||
function unitMinifier(name, value, unitsRegexp) {
|
||||
if (/^(?:\-moz\-calc|\-webkit\-calc|calc)\(/.test(value))
|
||||
return value;
|
||||
|
||||
if (name == 'flex' || name == '-ms-flex' || name == '-webkit-flex' || name == 'flex-basis' || name == '-webkit-flex-basis')
|
||||
return value;
|
||||
|
||||
if (value.indexOf('%') > 0 && (name == 'height' || name == 'max-height'))
|
||||
return value;
|
||||
|
||||
return value
|
||||
.replace(unitsRegexp, '$1' + '0' + '$2')
|
||||
.replace(unitsRegexp, '$1' + '0' + '$2');
|
||||
}
|
||||
|
||||
function multipleZerosMinifier(property) {
|
||||
var values = property.value;
|
||||
var spliceAt;
|
||||
|
||||
if (values.length == 4 && values[0][0] === '0' && values[1][0] === '0' && values[2][0] === '0' && values[3][0] === '0') {
|
||||
if (property.name.indexOf('box-shadow') > -1)
|
||||
spliceAt = 2;
|
||||
else
|
||||
spliceAt = 1;
|
||||
}
|
||||
|
||||
if (spliceAt) {
|
||||
property.value.splice(spliceAt);
|
||||
property.dirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
function colorMininifier(name, value, compatibility) {
|
||||
if (value.indexOf('#') === -1 && value.indexOf('rgb') == -1 && value.indexOf('hsl') == -1)
|
||||
return HexNameShortener.shorten(value);
|
||||
|
||||
value = value
|
||||
.replace(/rgb\((\-?\d+),(\-?\d+),(\-?\d+)\)/g, function (match, red, green, blue) {
|
||||
return new RGB(red, green, blue).toHex();
|
||||
})
|
||||
.replace(/hsl\((-?\d+),(-?\d+)%?,(-?\d+)%?\)/g, function (match, hue, saturation, lightness) {
|
||||
return new HSL(hue, saturation, lightness).toHex();
|
||||
})
|
||||
.replace(/(^|[^='"])#([0-9a-f]{6})/gi, function (match, prefix, color) {
|
||||
if (color[0] == color[1] && color[2] == color[3] && color[4] == color[5])
|
||||
return prefix + '#' + color[0] + color[2] + color[4];
|
||||
else
|
||||
return prefix + '#' + color;
|
||||
})
|
||||
.replace(/(rgb|rgba|hsl|hsla)\(([^\)]+)\)/g, function (match, colorFunction, colorDef) {
|
||||
var tokens = colorDef.split(',');
|
||||
var applies = (colorFunction == 'hsl' && tokens.length == 3) ||
|
||||
(colorFunction == 'hsla' && tokens.length == 4) ||
|
||||
(colorFunction == 'rgb' && tokens.length == 3 && colorDef.indexOf('%') > 0) ||
|
||||
(colorFunction == 'rgba' && tokens.length == 4 && colorDef.indexOf('%') > 0);
|
||||
if (!applies)
|
||||
return match;
|
||||
|
||||
if (tokens[1].indexOf('%') == -1)
|
||||
tokens[1] += '%';
|
||||
if (tokens[2].indexOf('%') == -1)
|
||||
tokens[2] += '%';
|
||||
return colorFunction + '(' + tokens.join(',') + ')';
|
||||
});
|
||||
|
||||
if (compatibility.colors.opacity && name.indexOf('background') == -1) {
|
||||
value = value.replace(/(?:rgba|hsla)\(0,0%?,0%?,0\)/g, function (match) {
|
||||
if (split(value, ',').pop().indexOf('gradient(') > -1)
|
||||
return match;
|
||||
|
||||
return 'transparent';
|
||||
});
|
||||
}
|
||||
|
||||
return HexNameShortener.shorten(value);
|
||||
}
|
||||
|
||||
function pixelLengthMinifier(_, value, compatibility) {
|
||||
if (!WHOLE_PIXEL_VALUE.test(value))
|
||||
return value;
|
||||
|
||||
return value.replace(WHOLE_PIXEL_VALUE, function (match, val) {
|
||||
var newValue;
|
||||
var intVal = parseInt(val);
|
||||
|
||||
if (intVal === 0)
|
||||
return match;
|
||||
|
||||
if (compatibility.properties.shorterLengthUnits && compatibility.units.pt && intVal * 3 % 4 === 0)
|
||||
newValue = intVal * 3 / 4 + 'pt';
|
||||
|
||||
if (compatibility.properties.shorterLengthUnits && compatibility.units.pc && intVal % 16 === 0)
|
||||
newValue = intVal / 16 + 'pc';
|
||||
|
||||
if (compatibility.properties.shorterLengthUnits && compatibility.units.in && intVal % 96 === 0)
|
||||
newValue = intVal / 96 + 'in';
|
||||
|
||||
if (newValue)
|
||||
newValue = match.substring(0, match.indexOf(val)) + newValue;
|
||||
|
||||
return newValue && newValue.length < match.length ? newValue : match;
|
||||
});
|
||||
}
|
||||
|
||||
function timeUnitMinifier(_, value) {
|
||||
if (!TIME_VALUE.test(value))
|
||||
return value;
|
||||
|
||||
return value.replace(TIME_VALUE, function (match, val, unit) {
|
||||
var newValue;
|
||||
|
||||
if (unit == 'ms') {
|
||||
newValue = parseInt(val) / 1000 + 's';
|
||||
} else if (unit == 's') {
|
||||
newValue = parseFloat(val) * 1000 + 'ms';
|
||||
}
|
||||
|
||||
return newValue.length < match.length ? newValue : match;
|
||||
});
|
||||
}
|
||||
|
||||
function minifyBorderRadius(property) {
|
||||
var values = property.value;
|
||||
var spliceAt;
|
||||
|
||||
if (values.length == 3 && values[1][0] == '/' && values[0][0] == values[2][0])
|
||||
spliceAt = 1;
|
||||
else if (values.length == 5 && values[2][0] == '/' && values[0][0] == values[3][0] && values[1][0] == values[4][0])
|
||||
spliceAt = 2;
|
||||
else if (values.length == 7 && values[3][0] == '/' && values[0][0] == values[4][0] && values[1][0] == values[5][0] && values[2][0] == values[6][0])
|
||||
spliceAt = 3;
|
||||
else if (values.length == 9 && values[4][0] == '/' && values[0][0] == values[5][0] && values[1][0] == values[6][0] && values[2][0] == values[7][0] && values[3][0] == values[8][0])
|
||||
spliceAt = 4;
|
||||
|
||||
if (spliceAt) {
|
||||
property.value.splice(spliceAt);
|
||||
property.dirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
function minifyFilter(property) {
|
||||
if (property.value.length == 1) {
|
||||
property.value[0][0] = property.value[0][0].replace(/progid:DXImageTransform\.Microsoft\.(Alpha|Chroma)(\W)/, function (match, filter, suffix) {
|
||||
return filter.toLowerCase() + suffix;
|
||||
});
|
||||
}
|
||||
|
||||
property.value[0][0] = property.value[0][0]
|
||||
.replace(/,(\S)/g, ', $1')
|
||||
.replace(/ ?= ?/g, '=');
|
||||
}
|
||||
|
||||
function minifyFont(property) {
|
||||
var values = property.value;
|
||||
var hasNumeral = FONT_NUMERAL_WEIGHTS.indexOf(values[0][0]) > -1 ||
|
||||
values[1] && FONT_NUMERAL_WEIGHTS.indexOf(values[1][0]) > -1 ||
|
||||
values[2] && FONT_NUMERAL_WEIGHTS.indexOf(values[2][0]) > -1;
|
||||
|
||||
if (hasNumeral)
|
||||
return;
|
||||
|
||||
if (values[1] == '/')
|
||||
return;
|
||||
|
||||
var normalCount = 0;
|
||||
if (values[0][0] == 'normal')
|
||||
normalCount++;
|
||||
if (values[1] && values[1][0] == 'normal')
|
||||
normalCount++;
|
||||
if (values[2] && values[2][0] == 'normal')
|
||||
normalCount++;
|
||||
|
||||
if (normalCount > 1)
|
||||
return;
|
||||
|
||||
var toOptimize;
|
||||
if (FONT_NAME_WEIGHTS_WITHOUT_NORMAL.indexOf(values[0][0]) > -1)
|
||||
toOptimize = 0;
|
||||
else if (values[1] && FONT_NAME_WEIGHTS_WITHOUT_NORMAL.indexOf(values[1][0]) > -1)
|
||||
toOptimize = 1;
|
||||
else if (values[2] && FONT_NAME_WEIGHTS_WITHOUT_NORMAL.indexOf(values[2][0]) > -1)
|
||||
toOptimize = 2;
|
||||
else if (FONT_NAME_WEIGHTS.indexOf(values[0][0]) > -1)
|
||||
toOptimize = 0;
|
||||
else if (values[1] && FONT_NAME_WEIGHTS.indexOf(values[1][0]) > -1)
|
||||
toOptimize = 1;
|
||||
else if (values[2] && FONT_NAME_WEIGHTS.indexOf(values[2][0]) > -1)
|
||||
toOptimize = 2;
|
||||
|
||||
if (toOptimize !== undefined) {
|
||||
property.value[toOptimize][0] = valueMinifiers['font-weight'](values[toOptimize][0]);
|
||||
property.dirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
function optimizeBody(properties, options) {
|
||||
var property, name, value;
|
||||
var _properties = wrapForOptimizing(properties);
|
||||
|
||||
for (var i = 0, l = _properties.length; i < l; i++) {
|
||||
property = _properties[i];
|
||||
name = property.name;
|
||||
|
||||
if (property.hack && (
|
||||
(property.hack == 'star' || property.hack == 'underscore') && !options.compatibility.properties.iePrefixHack ||
|
||||
property.hack == 'backslash' && !options.compatibility.properties.ieSuffixHack ||
|
||||
property.hack == 'bang' && !options.compatibility.properties.ieBangHack))
|
||||
property.unused = true;
|
||||
|
||||
if (name.indexOf('padding') === 0 && (isNegative(property, 0) || isNegative(property, 1) || isNegative(property, 2) || isNegative(property, 3)))
|
||||
property.unused = true;
|
||||
|
||||
if (property.unused)
|
||||
continue;
|
||||
|
||||
if (property.variable) {
|
||||
if (property.block)
|
||||
optimizeBody(property.value[0], options);
|
||||
continue;
|
||||
}
|
||||
|
||||
for (var j = 0, m = property.value.length; j < m; j++) {
|
||||
value = property.value[j][0];
|
||||
|
||||
if (valueMinifiers[name])
|
||||
value = valueMinifiers[name](value, j, m);
|
||||
|
||||
value = whitespaceMinifier(name, value);
|
||||
value = precisionMinifier(name, value, options.precision);
|
||||
value = pixelLengthMinifier(name, value, options.compatibility);
|
||||
value = timeUnitMinifier(name, value);
|
||||
value = zeroMinifier(name, value);
|
||||
if (options.compatibility.properties.zeroUnits) {
|
||||
value = zeroDegMinifier(name, value);
|
||||
value = unitMinifier(name, value, options.unitsRegexp);
|
||||
}
|
||||
if (options.compatibility.properties.colors)
|
||||
value = colorMininifier(name, value, options.compatibility);
|
||||
|
||||
property.value[j][0] = value;
|
||||
}
|
||||
|
||||
multipleZerosMinifier(property);
|
||||
|
||||
if (name.indexOf('border') === 0 && name.indexOf('radius') > 0)
|
||||
minifyBorderRadius(property);
|
||||
else if (name == 'filter')
|
||||
minifyFilter(property);
|
||||
else if (name == 'font')
|
||||
minifyFont(property);
|
||||
}
|
||||
|
||||
restoreFromOptimizing(_properties, true);
|
||||
removeUnused(_properties);
|
||||
}
|
||||
|
||||
function cleanupCharsets(tokens) {
|
||||
var hasCharset = false;
|
||||
|
||||
for (var i = 0, l = tokens.length; i < l; i++) {
|
||||
var token = tokens[i];
|
||||
|
||||
if (token[0] != 'at-rule')
|
||||
continue;
|
||||
|
||||
if (!CHARSET_REGEXP.test(token[1][0]))
|
||||
continue;
|
||||
|
||||
if (hasCharset || token[1][0].indexOf(CHARSET_TOKEN) == -1) {
|
||||
tokens.splice(i, 1);
|
||||
i--;
|
||||
l--;
|
||||
} else {
|
||||
hasCharset = true;
|
||||
tokens.splice(i, 1);
|
||||
tokens.unshift(['at-rule', [token[1][0].replace(CHARSET_REGEXP, CHARSET_TOKEN)]]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function buildUnitRegexp(options) {
|
||||
var units = ['px', 'em', 'ex', 'cm', 'mm', 'in', 'pt', 'pc', '%'];
|
||||
var otherUnits = ['ch', 'rem', 'vh', 'vm', 'vmax', 'vmin', 'vw'];
|
||||
|
||||
otherUnits.forEach(function (unit) {
|
||||
if (options.compatibility.units[unit])
|
||||
units.push(unit);
|
||||
});
|
||||
|
||||
return new RegExp('(^|\\s|\\(|,)0(?:' + units.join('|') + ')(\\W|$)', 'g');
|
||||
}
|
||||
|
||||
function buildPrecision(options) {
|
||||
var precision = {};
|
||||
|
||||
precision.value = options.roundingPrecision === undefined ?
|
||||
DEFAULT_ROUNDING_PRECISION :
|
||||
options.roundingPrecision;
|
||||
precision.multiplier = Math.pow(10, precision.value);
|
||||
precision.regexp = new RegExp('(\\d*\\.\\d{' + (precision.value + 1) + ',})px', 'g');
|
||||
|
||||
return precision;
|
||||
}
|
||||
|
||||
function optimize(tokens, options, context) {
|
||||
var ie7Hack = options.compatibility.selectors.ie7Hack;
|
||||
var adjacentSpace = options.compatibility.selectors.adjacentSpace;
|
||||
var spaceAfterClosingBrace = options.compatibility.properties.spaceAfterClosingBrace;
|
||||
var mayHaveCharset = false;
|
||||
var afterContent = false;
|
||||
|
||||
options.unitsRegexp = buildUnitRegexp(options);
|
||||
options.precision = buildPrecision(options);
|
||||
|
||||
for (var i = 0, l = tokens.length; i < l; i++) {
|
||||
var token = tokens[i];
|
||||
|
||||
switch (token[0]) {
|
||||
case 'selector':
|
||||
token[1] = cleanUpSelectors(token[1], !ie7Hack, adjacentSpace);
|
||||
optimizeBody(token[2], options);
|
||||
afterContent = true;
|
||||
break;
|
||||
case 'block':
|
||||
cleanUpBlock(token[1], spaceAfterClosingBrace);
|
||||
optimize(token[2], options, context);
|
||||
afterContent = true;
|
||||
break;
|
||||
case 'flat-block':
|
||||
cleanUpBlock(token[1], spaceAfterClosingBrace);
|
||||
optimizeBody(token[2], options);
|
||||
afterContent = true;
|
||||
break;
|
||||
case 'at-rule':
|
||||
cleanUpAtRule(token[1]);
|
||||
mayHaveCharset = true;
|
||||
}
|
||||
|
||||
if (token[0] == 'at-rule' && IMPORT_REGEXP.test(token[1]) && afterContent) {
|
||||
context.warnings.push('Ignoring @import rule "' + token[1] + '" as it appears after rules thus browsers will ignore them.');
|
||||
token[1] = '';
|
||||
}
|
||||
|
||||
if (token[1].length === 0 || (token[2] && token[2].length === 0)) {
|
||||
tokens.splice(i, 1);
|
||||
i--;
|
||||
l--;
|
||||
}
|
||||
}
|
||||
|
||||
if (mayHaveCharset)
|
||||
cleanupCharsets(tokens);
|
||||
}
|
||||
|
||||
module.exports = optimize;
|
||||
Reference in New Issue
Block a user