first
This commit is contained in:
61
node_modules/clean-css/lib/optimizer/level-2/extract-properties.js
generated
vendored
Normal file
61
node_modules/clean-css/lib/optimizer/level-2/extract-properties.js
generated
vendored
Normal file
@ -0,0 +1,61 @@
|
||||
// This extractor is used in level 2 optimizations
|
||||
// IMPORTANT: Mind Token class and this code is not related!
|
||||
// Properties will be tokenized in one step, see #429
|
||||
|
||||
var Token = require('../../tokenizer/token');
|
||||
var serializeRules = require('../../writer/one-time').rules;
|
||||
var serializeValue = require('../../writer/one-time').value;
|
||||
|
||||
function extractProperties(token) {
|
||||
var properties = [];
|
||||
var inSpecificSelector;
|
||||
var property;
|
||||
var name;
|
||||
var value;
|
||||
var i, l;
|
||||
|
||||
if (token[0] == Token.RULE) {
|
||||
inSpecificSelector = !/[.+>~]/.test(serializeRules(token[1]));
|
||||
|
||||
for (i = 0, l = token[2].length; i < l; i++) {
|
||||
property = token[2][i];
|
||||
|
||||
if (property[0] != Token.PROPERTY) { continue; }
|
||||
|
||||
name = property[1][1];
|
||||
if (name.length === 0) { continue; }
|
||||
|
||||
value = serializeValue(property, i);
|
||||
|
||||
properties.push([
|
||||
name,
|
||||
value,
|
||||
findNameRoot(name),
|
||||
token[2][i],
|
||||
name + ':' + value,
|
||||
token[1],
|
||||
inSpecificSelector
|
||||
]);
|
||||
}
|
||||
} else if (token[0] == Token.NESTED_BLOCK) {
|
||||
for (i = 0, l = token[2].length; i < l; i++) {
|
||||
properties = properties.concat(extractProperties(token[2][i]));
|
||||
}
|
||||
}
|
||||
|
||||
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; }
|
||||
if (name == '-chrome-') { return name; }
|
||||
|
||||
return name.replace(/^-\w+-/, '').match(/([a-zA-Z]+)/)[0].toLowerCase();
|
||||
}
|
||||
|
||||
module.exports = extractProperties;
|
273
node_modules/clean-css/lib/optimizer/level-2/is-mergeable.js
generated
vendored
Normal file
273
node_modules/clean-css/lib/optimizer/level-2/is-mergeable.js
generated
vendored
Normal file
@ -0,0 +1,273 @@
|
||||
var Marker = require('../../tokenizer/marker');
|
||||
var split = require('../../utils/split');
|
||||
|
||||
var DEEP_SELECTOR_PATTERN = /\/deep\//;
|
||||
var DOUBLE_COLON_PATTERN = /^::/;
|
||||
var VENDOR_PREFIXED_PATTERN = /:(-moz-|-ms-|-o-|-webkit-)/;
|
||||
|
||||
var NOT_PSEUDO = ':not';
|
||||
var PSEUDO_CLASSES_WITH_ARGUMENTS = [
|
||||
':dir',
|
||||
':lang',
|
||||
':not',
|
||||
':nth-child',
|
||||
':nth-last-child',
|
||||
':nth-last-of-type',
|
||||
':nth-of-type'
|
||||
];
|
||||
var RELATION_PATTERN = /[>+~]/;
|
||||
var UNMIXABLE_PSEUDO_CLASSES = [
|
||||
':after',
|
||||
':before',
|
||||
':first-letter',
|
||||
':first-line',
|
||||
':lang'
|
||||
];
|
||||
var UNMIXABLE_PSEUDO_ELEMENTS = [
|
||||
'::after',
|
||||
'::before',
|
||||
'::first-letter',
|
||||
'::first-line'
|
||||
];
|
||||
|
||||
var Level = {
|
||||
DOUBLE_QUOTE: 'double-quote',
|
||||
SINGLE_QUOTE: 'single-quote',
|
||||
ROOT: 'root'
|
||||
};
|
||||
|
||||
function isMergeable(selector, mergeablePseudoClasses, mergeablePseudoElements, multiplePseudoMerging) {
|
||||
var singleSelectors = split(selector, Marker.COMMA);
|
||||
var singleSelector;
|
||||
var i, l;
|
||||
|
||||
for (i = 0, l = singleSelectors.length; i < l; i++) {
|
||||
singleSelector = singleSelectors[i];
|
||||
|
||||
if (singleSelector.length === 0
|
||||
|| isDeepSelector(singleSelector)
|
||||
|| isVendorPrefixed(singleSelector)
|
||||
|| (singleSelector.indexOf(Marker.COLON) > -1
|
||||
&& !areMergeable(
|
||||
singleSelector,
|
||||
extractPseudoFrom(singleSelector),
|
||||
mergeablePseudoClasses,
|
||||
mergeablePseudoElements,
|
||||
multiplePseudoMerging
|
||||
))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
function isDeepSelector(selector) {
|
||||
return DEEP_SELECTOR_PATTERN.test(selector);
|
||||
}
|
||||
|
||||
function isVendorPrefixed(selector) {
|
||||
return VENDOR_PREFIXED_PATTERN.test(selector);
|
||||
}
|
||||
|
||||
function extractPseudoFrom(selector) {
|
||||
var list = [];
|
||||
var character;
|
||||
var buffer = [];
|
||||
var level = Level.ROOT;
|
||||
var roundBracketLevel = 0;
|
||||
var isQuoted;
|
||||
var isEscaped;
|
||||
var isPseudo = false;
|
||||
var isRelation;
|
||||
var wasColon = false;
|
||||
var index;
|
||||
var len;
|
||||
|
||||
for (index = 0, len = selector.length; index < len; index++) {
|
||||
character = selector[index];
|
||||
|
||||
isRelation = !isEscaped && RELATION_PATTERN.test(character);
|
||||
isQuoted = level == Level.DOUBLE_QUOTE || level == Level.SINGLE_QUOTE;
|
||||
|
||||
if (isEscaped) {
|
||||
buffer.push(character);
|
||||
} else if (character == Marker.DOUBLE_QUOTE && level == Level.ROOT) {
|
||||
buffer.push(character);
|
||||
level = Level.DOUBLE_QUOTE;
|
||||
} else if (character == Marker.DOUBLE_QUOTE && level == Level.DOUBLE_QUOTE) {
|
||||
buffer.push(character);
|
||||
level = Level.ROOT;
|
||||
} else if (character == Marker.SINGLE_QUOTE && level == Level.ROOT) {
|
||||
buffer.push(character);
|
||||
level = Level.SINGLE_QUOTE;
|
||||
} else if (character == Marker.SINGLE_QUOTE && level == Level.SINGLE_QUOTE) {
|
||||
buffer.push(character);
|
||||
level = Level.ROOT;
|
||||
} else if (isQuoted) {
|
||||
buffer.push(character);
|
||||
} else if (character == Marker.OPEN_ROUND_BRACKET) {
|
||||
buffer.push(character);
|
||||
roundBracketLevel++;
|
||||
} else if (character == Marker.CLOSE_ROUND_BRACKET && roundBracketLevel == 1 && isPseudo) {
|
||||
buffer.push(character);
|
||||
list.push(buffer.join(''));
|
||||
roundBracketLevel--;
|
||||
buffer = [];
|
||||
isPseudo = false;
|
||||
} else if (character == Marker.CLOSE_ROUND_BRACKET) {
|
||||
buffer.push(character);
|
||||
roundBracketLevel--;
|
||||
} else if (character == Marker.COLON && roundBracketLevel === 0 && isPseudo && !wasColon) {
|
||||
list.push(buffer.join(''));
|
||||
buffer = [];
|
||||
buffer.push(character);
|
||||
} else if (character == Marker.COLON && roundBracketLevel === 0 && !wasColon) {
|
||||
buffer = [];
|
||||
buffer.push(character);
|
||||
isPseudo = true;
|
||||
} else if (character == Marker.SPACE && roundBracketLevel === 0 && isPseudo) {
|
||||
list.push(buffer.join(''));
|
||||
buffer = [];
|
||||
isPseudo = false;
|
||||
} else if (isRelation && roundBracketLevel === 0 && isPseudo) {
|
||||
list.push(buffer.join(''));
|
||||
buffer = [];
|
||||
isPseudo = false;
|
||||
} else {
|
||||
buffer.push(character);
|
||||
}
|
||||
|
||||
isEscaped = character == Marker.BACK_SLASH;
|
||||
wasColon = character == Marker.COLON;
|
||||
}
|
||||
|
||||
if (buffer.length > 0 && isPseudo) {
|
||||
list.push(buffer.join(''));
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
function areMergeable(selector, matches, mergeablePseudoClasses, mergeablePseudoElements, multiplePseudoMerging) {
|
||||
return areAllowed(matches, mergeablePseudoClasses, mergeablePseudoElements)
|
||||
&& needArguments(matches)
|
||||
&& (matches.length < 2 || !someIncorrectlyChained(selector, matches))
|
||||
&& (matches.length < 2 || multiplePseudoMerging && allMixable(matches));
|
||||
}
|
||||
|
||||
function areAllowed(matches, mergeablePseudoClasses, mergeablePseudoElements) {
|
||||
var match;
|
||||
var name;
|
||||
var i, l;
|
||||
|
||||
for (i = 0, l = matches.length; i < l; i++) {
|
||||
match = matches[i];
|
||||
name = match.indexOf(Marker.OPEN_ROUND_BRACKET) > -1
|
||||
? match.substring(0, match.indexOf(Marker.OPEN_ROUND_BRACKET))
|
||||
: match;
|
||||
|
||||
if (mergeablePseudoClasses.indexOf(name) === -1 && mergeablePseudoElements.indexOf(name) === -1) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
function needArguments(matches) {
|
||||
var match;
|
||||
var name;
|
||||
var bracketOpensAt;
|
||||
var hasArguments;
|
||||
var i, l;
|
||||
|
||||
for (i = 0, l = matches.length; i < l; i++) {
|
||||
match = matches[i];
|
||||
|
||||
bracketOpensAt = match.indexOf(Marker.OPEN_ROUND_BRACKET);
|
||||
hasArguments = bracketOpensAt > -1;
|
||||
name = hasArguments
|
||||
? match.substring(0, bracketOpensAt)
|
||||
: match;
|
||||
|
||||
if (hasArguments && PSEUDO_CLASSES_WITH_ARGUMENTS.indexOf(name) == -1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!hasArguments && PSEUDO_CLASSES_WITH_ARGUMENTS.indexOf(name) > -1) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
function someIncorrectlyChained(selector, matches) {
|
||||
var positionInSelector = 0;
|
||||
var match;
|
||||
var matchAt;
|
||||
var nextMatch;
|
||||
var nextMatchAt;
|
||||
var name;
|
||||
var nextName;
|
||||
var areChained;
|
||||
var i, l;
|
||||
|
||||
for (i = 0, l = matches.length; i < l; i++) {
|
||||
match = matches[i];
|
||||
nextMatch = matches[i + 1];
|
||||
|
||||
if (!nextMatch) {
|
||||
break;
|
||||
}
|
||||
|
||||
matchAt = selector.indexOf(match, positionInSelector);
|
||||
nextMatchAt = selector.indexOf(match, matchAt + 1);
|
||||
positionInSelector = nextMatchAt;
|
||||
areChained = matchAt + match.length == nextMatchAt;
|
||||
|
||||
if (areChained) {
|
||||
name = match.indexOf(Marker.OPEN_ROUND_BRACKET) > -1
|
||||
? match.substring(0, match.indexOf(Marker.OPEN_ROUND_BRACKET))
|
||||
: match;
|
||||
nextName = nextMatch.indexOf(Marker.OPEN_ROUND_BRACKET) > -1
|
||||
? nextMatch.substring(0, nextMatch.indexOf(Marker.OPEN_ROUND_BRACKET))
|
||||
: nextMatch;
|
||||
|
||||
if (name != NOT_PSEUDO || nextName != NOT_PSEUDO) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function allMixable(matches) {
|
||||
var unmixableMatches = 0;
|
||||
var match;
|
||||
var i, l;
|
||||
|
||||
for (i = 0, l = matches.length; i < l; i++) {
|
||||
match = matches[i];
|
||||
|
||||
if (isPseudoElement(match)) {
|
||||
unmixableMatches += UNMIXABLE_PSEUDO_ELEMENTS.indexOf(match) > -1 ? 1 : 0;
|
||||
} else {
|
||||
unmixableMatches += UNMIXABLE_PSEUDO_CLASSES.indexOf(match) > -1 ? 1 : 0;
|
||||
}
|
||||
|
||||
if (unmixableMatches > 1) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
function isPseudoElement(pseudo) {
|
||||
return DOUBLE_COLON_PATTERN.test(pseudo);
|
||||
}
|
||||
|
||||
module.exports = isMergeable;
|
55
node_modules/clean-css/lib/optimizer/level-2/merge-adjacent.js
generated
vendored
Normal file
55
node_modules/clean-css/lib/optimizer/level-2/merge-adjacent.js
generated
vendored
Normal file
@ -0,0 +1,55 @@
|
||||
var isMergeable = require('./is-mergeable');
|
||||
|
||||
var optimizeProperties = require('./properties/optimize');
|
||||
|
||||
var sortSelectors = require('../level-1/sort-selectors');
|
||||
var tidyRules = require('../level-1/tidy-rules');
|
||||
|
||||
var OptimizationLevel = require('../../options/optimization-level').OptimizationLevel;
|
||||
|
||||
var serializeBody = require('../../writer/one-time').body;
|
||||
var serializeRules = require('../../writer/one-time').rules;
|
||||
|
||||
var Token = require('../../tokenizer/token');
|
||||
|
||||
function mergeAdjacent(tokens, context) {
|
||||
var lastToken = [null, [], []];
|
||||
var options = context.options;
|
||||
var adjacentSpace = options.compatibility.selectors.adjacentSpace;
|
||||
var selectorsSortingMethod = options.level[OptimizationLevel.One].selectorsSortingMethod;
|
||||
var mergeablePseudoClasses = options.compatibility.selectors.mergeablePseudoClasses;
|
||||
var mergeablePseudoElements = options.compatibility.selectors.mergeablePseudoElements;
|
||||
var mergeLimit = options.compatibility.selectors.mergeLimit;
|
||||
var multiplePseudoMerging = options.compatibility.selectors.multiplePseudoMerging;
|
||||
|
||||
for (var i = 0, l = tokens.length; i < l; i++) {
|
||||
var token = tokens[i];
|
||||
|
||||
if (token[0] != Token.RULE) {
|
||||
lastToken = [null, [], []];
|
||||
continue;
|
||||
}
|
||||
|
||||
if (lastToken[0] == Token.RULE && serializeRules(token[1]) == serializeRules(lastToken[1])) {
|
||||
Array.prototype.push.apply(lastToken[2], token[2]);
|
||||
optimizeProperties(lastToken[2], true, true, context);
|
||||
token[2] = [];
|
||||
} else if (lastToken[0] == Token.RULE && serializeBody(token[2]) == serializeBody(lastToken[2])
|
||||
&& isMergeable(serializeRules(token[1]), mergeablePseudoClasses, mergeablePseudoElements, multiplePseudoMerging)
|
||||
&& isMergeable(
|
||||
serializeRules(lastToken[1]),
|
||||
mergeablePseudoClasses,
|
||||
mergeablePseudoElements,
|
||||
multiplePseudoMerging
|
||||
)
|
||||
&& lastToken[1].length < mergeLimit) {
|
||||
lastToken[1] = tidyRules(lastToken[1].concat(token[1]), false, adjacentSpace, false, context.warnings);
|
||||
lastToken[1] = lastToken.length > 1 ? sortSelectors(lastToken[1], selectorsSortingMethod) : lastToken[1];
|
||||
token[2] = [];
|
||||
} else {
|
||||
lastToken = token;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = mergeAdjacent;
|
105
node_modules/clean-css/lib/optimizer/level-2/merge-media-queries.js
generated
vendored
Normal file
105
node_modules/clean-css/lib/optimizer/level-2/merge-media-queries.js
generated
vendored
Normal file
@ -0,0 +1,105 @@
|
||||
var canReorder = require('./reorderable').canReorder;
|
||||
var canReorderSingle = require('./reorderable').canReorderSingle;
|
||||
var extractProperties = require('./extract-properties');
|
||||
var rulesOverlap = require('./rules-overlap');
|
||||
|
||||
var serializeRules = require('../../writer/one-time').rules;
|
||||
var OptimizationLevel = require('../../options/optimization-level').OptimizationLevel;
|
||||
var Token = require('../../tokenizer/token');
|
||||
|
||||
function mergeMediaQueries(tokens, context) {
|
||||
var mergeSemantically = context.options.level[OptimizationLevel.Two].mergeSemantically;
|
||||
var specificityCache = context.cache.specificity;
|
||||
var candidates = {};
|
||||
var reduced = [];
|
||||
|
||||
for (var i = tokens.length - 1; i >= 0; i--) {
|
||||
var token = tokens[i];
|
||||
if (token[0] != Token.NESTED_BLOCK) {
|
||||
continue;
|
||||
}
|
||||
|
||||
var key = serializeRules(token[1]);
|
||||
var candidate = candidates[key];
|
||||
if (!candidate) {
|
||||
candidate = [];
|
||||
candidates[key] = 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 (mergeSemantically
|
||||
&& allSameRulePropertiesCanBeReordered(movedProperties, traversedProperties, specificityCache)
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!canReorder(movedProperties, traversedProperties, specificityCache)) { continue directionLoop; }
|
||||
}
|
||||
|
||||
target[2] = topToBottom
|
||||
? source[2].concat(target[2])
|
||||
: target[2].concat(source[2]);
|
||||
source[2] = [];
|
||||
|
||||
reduced.push(target);
|
||||
continue positionLoop;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return reduced;
|
||||
}
|
||||
|
||||
function allSameRulePropertiesCanBeReordered(movedProperties, traversedProperties, specificityCache) {
|
||||
var movedProperty;
|
||||
var movedRule;
|
||||
var traversedProperty;
|
||||
var traversedRule;
|
||||
var i, l;
|
||||
var j, m;
|
||||
|
||||
for (i = 0, l = movedProperties.length; i < l; i++) {
|
||||
movedProperty = movedProperties[i];
|
||||
movedRule = movedProperty[5];
|
||||
|
||||
for (j = 0, m = traversedProperties.length; j < m; j++) {
|
||||
traversedProperty = traversedProperties[j];
|
||||
traversedRule = traversedProperty[5];
|
||||
|
||||
if (rulesOverlap(movedRule, traversedRule, true)
|
||||
&& !canReorderSingle(movedProperty, traversedProperty, specificityCache)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
module.exports = mergeMediaQueries;
|
88
node_modules/clean-css/lib/optimizer/level-2/merge-non-adjacent-by-body.js
generated
vendored
Normal file
88
node_modules/clean-css/lib/optimizer/level-2/merge-non-adjacent-by-body.js
generated
vendored
Normal file
@ -0,0 +1,88 @@
|
||||
var isMergeable = require('./is-mergeable');
|
||||
|
||||
var sortSelectors = require('../level-1/sort-selectors');
|
||||
var tidyRules = require('../level-1/tidy-rules');
|
||||
|
||||
var OptimizationLevel = require('../../options/optimization-level').OptimizationLevel;
|
||||
|
||||
var serializeBody = require('../../writer/one-time').body;
|
||||
var serializeRules = require('../../writer/one-time').rules;
|
||||
|
||||
var Token = require('../../tokenizer/token');
|
||||
|
||||
function unsafeSelector(value) {
|
||||
return /\.|\*| :/.test(value);
|
||||
}
|
||||
|
||||
function isBemElement(token) {
|
||||
var asString = serializeRules(token[1]);
|
||||
return asString.indexOf('__') > -1 || asString.indexOf('--') > -1;
|
||||
}
|
||||
|
||||
function withoutModifier(selector) {
|
||||
return selector.replace(/--[^ ,>+~:]+/g, '');
|
||||
}
|
||||
|
||||
function removeAnyUnsafeElements(left, candidates) {
|
||||
var leftSelector = withoutModifier(serializeRules(left[1]));
|
||||
|
||||
for (var body in candidates) {
|
||||
var right = candidates[body];
|
||||
var rightSelector = withoutModifier(serializeRules(right[1]));
|
||||
|
||||
if (rightSelector.indexOf(leftSelector) > -1 || leftSelector.indexOf(rightSelector) > -1) {
|
||||
delete candidates[body];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function mergeNonAdjacentByBody(tokens, context) {
|
||||
var options = context.options;
|
||||
var mergeSemantically = options.level[OptimizationLevel.Two].mergeSemantically;
|
||||
var adjacentSpace = options.compatibility.selectors.adjacentSpace;
|
||||
var selectorsSortingMethod = options.level[OptimizationLevel.One].selectorsSortingMethod;
|
||||
var mergeablePseudoClasses = options.compatibility.selectors.mergeablePseudoClasses;
|
||||
var mergeablePseudoElements = options.compatibility.selectors.mergeablePseudoElements;
|
||||
var multiplePseudoMerging = options.compatibility.selectors.multiplePseudoMerging;
|
||||
var candidates = {};
|
||||
|
||||
for (var i = tokens.length - 1; i >= 0; i--) {
|
||||
var token = tokens[i];
|
||||
if (token[0] != Token.RULE) { continue; }
|
||||
|
||||
if (token[2].length > 0 && (!mergeSemantically && unsafeSelector(serializeRules(token[1])))) { candidates = {}; }
|
||||
|
||||
if (token[2].length > 0 && mergeSemantically && isBemElement(token)) { removeAnyUnsafeElements(token, candidates); }
|
||||
|
||||
var candidateBody = serializeBody(token[2]);
|
||||
var oldToken = candidates[candidateBody];
|
||||
if (oldToken
|
||||
&& isMergeable(
|
||||
serializeRules(token[1]),
|
||||
mergeablePseudoClasses,
|
||||
mergeablePseudoElements,
|
||||
multiplePseudoMerging
|
||||
)
|
||||
&& isMergeable(
|
||||
serializeRules(oldToken[1]),
|
||||
mergeablePseudoClasses,
|
||||
mergeablePseudoElements,
|
||||
multiplePseudoMerging
|
||||
)
|
||||
) {
|
||||
if (token[2].length > 0) {
|
||||
token[1] = tidyRules(oldToken[1].concat(token[1]), false, adjacentSpace, false, context.warnings);
|
||||
token[1] = token[1].length > 1 ? sortSelectors(token[1], selectorsSortingMethod) : token[1];
|
||||
} else {
|
||||
token[1] = oldToken[1].concat(token[1]);
|
||||
}
|
||||
|
||||
oldToken[2] = [];
|
||||
candidates[candidateBody] = null;
|
||||
}
|
||||
|
||||
candidates[serializeBody(token[2])] = token;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = mergeNonAdjacentByBody;
|
73
node_modules/clean-css/lib/optimizer/level-2/merge-non-adjacent-by-selector.js
generated
vendored
Normal file
73
node_modules/clean-css/lib/optimizer/level-2/merge-non-adjacent-by-selector.js
generated
vendored
Normal file
@ -0,0 +1,73 @@
|
||||
var canReorder = require('./reorderable').canReorder;
|
||||
var extractProperties = require('./extract-properties');
|
||||
|
||||
var optimizeProperties = require('./properties/optimize');
|
||||
|
||||
var serializeRules = require('../../writer/one-time').rules;
|
||||
|
||||
var Token = require('../../tokenizer/token');
|
||||
|
||||
function mergeNonAdjacentBySelector(tokens, context) {
|
||||
var specificityCache = context.cache.specificity;
|
||||
var allSelectors = {};
|
||||
var repeatedSelectors = [];
|
||||
var i;
|
||||
|
||||
for (i = tokens.length - 1; i >= 0; i--) {
|
||||
if (tokens[i][0] != Token.RULE) { continue; }
|
||||
if (tokens[i][2].length === 0) { continue; }
|
||||
|
||||
var selector = serializeRules(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);
|
||||
|
||||
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, specificityCache)
|
||||
: canReorder(traversedProperties, movedProperties, specificityCache);
|
||||
|
||||
if (!reorderable && !topToBottom) { continue selectorIterator; }
|
||||
if (!reorderable && topToBottom) { continue directionIterator; }
|
||||
}
|
||||
|
||||
if (topToBottom) {
|
||||
Array.prototype.push.apply(moved[2], target[2]);
|
||||
target[2] = moved[2];
|
||||
} else {
|
||||
Array.prototype.push.apply(target[2], moved[2]);
|
||||
}
|
||||
|
||||
optimizeProperties(target[2], true, true, context);
|
||||
moved[2] = [];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = mergeNonAdjacentBySelector;
|
139
node_modules/clean-css/lib/optimizer/level-2/optimize.js
generated
vendored
Normal file
139
node_modules/clean-css/lib/optimizer/level-2/optimize.js
generated
vendored
Normal file
@ -0,0 +1,139 @@
|
||||
var mergeAdjacent = require('./merge-adjacent');
|
||||
var mergeMediaQueries = require('./merge-media-queries');
|
||||
var mergeNonAdjacentByBody = require('./merge-non-adjacent-by-body');
|
||||
var mergeNonAdjacentBySelector = require('./merge-non-adjacent-by-selector');
|
||||
var reduceNonAdjacent = require('./reduce-non-adjacent');
|
||||
var removeDuplicateFontAtRules = require('./remove-duplicate-font-at-rules');
|
||||
var removeDuplicateMediaQueries = require('./remove-duplicate-media-queries');
|
||||
var removeDuplicates = require('./remove-duplicates');
|
||||
var removeUnusedAtRules = require('./remove-unused-at-rules');
|
||||
var restructure = require('./restructure');
|
||||
|
||||
var optimizeProperties = require('./properties/optimize');
|
||||
|
||||
var OptimizationLevel = require('../../options/optimization-level').OptimizationLevel;
|
||||
|
||||
var Token = require('../../tokenizer/token');
|
||||
|
||||
function removeEmpty(tokens) {
|
||||
for (var i = 0, l = tokens.length; i < l; i++) {
|
||||
var token = tokens[i];
|
||||
var isEmpty = false;
|
||||
|
||||
switch (token[0]) {
|
||||
case Token.RULE:
|
||||
isEmpty = token[1].length === 0 || token[2].length === 0;
|
||||
break;
|
||||
case Token.NESTED_BLOCK:
|
||||
removeEmpty(token[2]);
|
||||
isEmpty = token[2].length === 0;
|
||||
break;
|
||||
case Token.AT_RULE:
|
||||
isEmpty = token[1].length === 0;
|
||||
break;
|
||||
case Token.AT_RULE_BLOCK:
|
||||
isEmpty = token[2].length === 0;
|
||||
}
|
||||
|
||||
if (isEmpty) {
|
||||
tokens.splice(i, 1);
|
||||
i--;
|
||||
l--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function recursivelyOptimizeBlocks(tokens, context) {
|
||||
for (var i = 0, l = tokens.length; i < l; i++) {
|
||||
var token = tokens[i];
|
||||
|
||||
if (token[0] == Token.NESTED_BLOCK) {
|
||||
var isKeyframes = /@(-moz-|-o-|-webkit-)?keyframes/.test(token[1][0][1]);
|
||||
level2Optimize(token[2], context, !isKeyframes);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function recursivelyOptimizeProperties(tokens, context) {
|
||||
for (var i = 0, l = tokens.length; i < l; i++) {
|
||||
var token = tokens[i];
|
||||
|
||||
switch (token[0]) {
|
||||
case Token.RULE:
|
||||
optimizeProperties(token[2], true, true, context);
|
||||
break;
|
||||
case Token.NESTED_BLOCK:
|
||||
recursivelyOptimizeProperties(token[2], context);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function level2Optimize(tokens, context, withRestructuring) {
|
||||
var levelOptions = context.options.level[OptimizationLevel.Two];
|
||||
var level2Plugins = context.options.plugins.level2Block;
|
||||
var reduced;
|
||||
var i;
|
||||
|
||||
recursivelyOptimizeBlocks(tokens, context);
|
||||
recursivelyOptimizeProperties(tokens, context);
|
||||
|
||||
if (levelOptions.removeDuplicateRules) {
|
||||
removeDuplicates(tokens, context);
|
||||
}
|
||||
|
||||
if (levelOptions.mergeAdjacentRules) {
|
||||
mergeAdjacent(tokens, context);
|
||||
}
|
||||
|
||||
if (levelOptions.reduceNonAdjacentRules) {
|
||||
reduceNonAdjacent(tokens, context);
|
||||
}
|
||||
|
||||
if (levelOptions.mergeNonAdjacentRules && levelOptions.mergeNonAdjacentRules != 'body') {
|
||||
mergeNonAdjacentBySelector(tokens, context);
|
||||
}
|
||||
|
||||
if (levelOptions.mergeNonAdjacentRules && levelOptions.mergeNonAdjacentRules != 'selector') {
|
||||
mergeNonAdjacentByBody(tokens, context);
|
||||
}
|
||||
|
||||
if (levelOptions.restructureRules && levelOptions.mergeAdjacentRules && withRestructuring) {
|
||||
restructure(tokens, context);
|
||||
mergeAdjacent(tokens, context);
|
||||
}
|
||||
|
||||
if (levelOptions.restructureRules && !levelOptions.mergeAdjacentRules && withRestructuring) {
|
||||
restructure(tokens, context);
|
||||
}
|
||||
|
||||
if (levelOptions.removeDuplicateFontRules) {
|
||||
removeDuplicateFontAtRules(tokens, context);
|
||||
}
|
||||
|
||||
if (levelOptions.removeDuplicateMediaBlocks) {
|
||||
removeDuplicateMediaQueries(tokens, context);
|
||||
}
|
||||
|
||||
if (levelOptions.removeUnusedAtRules) {
|
||||
removeUnusedAtRules(tokens, context);
|
||||
}
|
||||
|
||||
if (levelOptions.mergeMedia) {
|
||||
reduced = mergeMediaQueries(tokens, context);
|
||||
for (i = reduced.length - 1; i >= 0; i--) {
|
||||
level2Optimize(reduced[i][2], context, false);
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < level2Plugins.length; i++) {
|
||||
level2Plugins[i](tokens);
|
||||
}
|
||||
|
||||
if (levelOptions.removeEmpty) {
|
||||
removeEmpty(tokens);
|
||||
}
|
||||
|
||||
return tokens;
|
||||
}
|
||||
|
||||
module.exports = level2Optimize;
|
28
node_modules/clean-css/lib/optimizer/level-2/properties/every-values-pair.js
generated
vendored
Normal file
28
node_modules/clean-css/lib/optimizer/level-2/properties/every-values-pair.js
generated
vendored
Normal file
@ -0,0 +1,28 @@
|
||||
var Marker = require('../../../tokenizer/marker');
|
||||
|
||||
function everyValuesPair(fn, left, right) {
|
||||
var leftSize = left.value.length;
|
||||
var rightSize = right.value.length;
|
||||
var total = Math.max(leftSize, rightSize);
|
||||
var lowerBound = Math.min(leftSize, rightSize) - 1;
|
||||
var leftValue;
|
||||
var rightValue;
|
||||
var position;
|
||||
|
||||
for (position = 0; position < total; position++) {
|
||||
leftValue = left.value[position] && left.value[position][1] || leftValue;
|
||||
rightValue = right.value[position] && right.value[position][1] || rightValue;
|
||||
|
||||
if (leftValue == Marker.COMMA || rightValue == Marker.COMMA) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!fn(leftValue, rightValue, position, position <= lowerBound)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
module.exports = everyValuesPair;
|
38
node_modules/clean-css/lib/optimizer/level-2/properties/find-component-in.js
generated
vendored
Normal file
38
node_modules/clean-css/lib/optimizer/level-2/properties/find-component-in.js
generated
vendored
Normal file
@ -0,0 +1,38 @@
|
||||
var configuration = require('../../configuration');
|
||||
|
||||
function findComponentIn(shorthand, longhand) {
|
||||
var comparator = nameComparator(longhand);
|
||||
|
||||
return findInDirectComponents(shorthand, comparator) || findInSubComponents(shorthand, comparator);
|
||||
}
|
||||
|
||||
function nameComparator(to) {
|
||||
return function(property) {
|
||||
return to.name === property.name;
|
||||
};
|
||||
}
|
||||
|
||||
function findInDirectComponents(shorthand, comparator) {
|
||||
return shorthand.components.filter(comparator)[0];
|
||||
}
|
||||
|
||||
function findInSubComponents(shorthand, comparator) {
|
||||
var shorthandComponent;
|
||||
var longhandMatch;
|
||||
var i, l;
|
||||
|
||||
if (!configuration[shorthand.name].shorthandComponents) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0, l = shorthand.components.length; i < l; i++) {
|
||||
shorthandComponent = shorthand.components[i];
|
||||
longhandMatch = findInDirectComponents(shorthandComponent, comparator);
|
||||
|
||||
if (longhandMatch) {
|
||||
return longhandMatch;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = findComponentIn;
|
9
node_modules/clean-css/lib/optimizer/level-2/properties/has-inherit.js
generated
vendored
Normal file
9
node_modules/clean-css/lib/optimizer/level-2/properties/has-inherit.js
generated
vendored
Normal file
@ -0,0 +1,9 @@
|
||||
function hasInherit(property) {
|
||||
for (var i = property.value.length - 1; i >= 0; i--) {
|
||||
if (property.value[i][1] == 'inherit') { return true; }
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
module.exports = hasInherit;
|
14
node_modules/clean-css/lib/optimizer/level-2/properties/has-same-values.js
generated
vendored
Normal file
14
node_modules/clean-css/lib/optimizer/level-2/properties/has-same-values.js
generated
vendored
Normal file
@ -0,0 +1,14 @@
|
||||
function hasSameValues(property) {
|
||||
var firstValue = property.value[0][1];
|
||||
var i, l;
|
||||
|
||||
for (i = 1, l = property.value.length; i < l; i++) {
|
||||
if (property.value[i][1] != firstValue) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
module.exports = hasSameValues;
|
9
node_modules/clean-css/lib/optimizer/level-2/properties/has-unset.js
generated
vendored
Normal file
9
node_modules/clean-css/lib/optimizer/level-2/properties/has-unset.js
generated
vendored
Normal file
@ -0,0 +1,9 @@
|
||||
function hasUnset(property) {
|
||||
for (var i = property.value.length - 1; i >= 0; i--) {
|
||||
if (property.value[i][1] == 'unset') { return true; }
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
module.exports = hasUnset;
|
22
node_modules/clean-css/lib/optimizer/level-2/properties/is-component-of.js
generated
vendored
Normal file
22
node_modules/clean-css/lib/optimizer/level-2/properties/is-component-of.js
generated
vendored
Normal file
@ -0,0 +1,22 @@
|
||||
var configuration = require('../../configuration');
|
||||
|
||||
function isComponentOf(property1, property2, shallow) {
|
||||
return isDirectComponentOf(property1, property2)
|
||||
|| !shallow && !!configuration[property1.name].shorthandComponents && isSubComponentOf(property1, property2);
|
||||
}
|
||||
|
||||
function isDirectComponentOf(property1, property2) {
|
||||
var descriptor = configuration[property1.name];
|
||||
|
||||
return 'components' in descriptor && descriptor.components.indexOf(property2.name) > -1;
|
||||
}
|
||||
|
||||
function isSubComponentOf(property1, property2) {
|
||||
return property1
|
||||
.components
|
||||
.some(function(component) {
|
||||
return isDirectComponentOf(component, property2);
|
||||
});
|
||||
}
|
||||
|
||||
module.exports = isComponentOf;
|
11
node_modules/clean-css/lib/optimizer/level-2/properties/is-mergeable-shorthand.js
generated
vendored
Normal file
11
node_modules/clean-css/lib/optimizer/level-2/properties/is-mergeable-shorthand.js
generated
vendored
Normal file
@ -0,0 +1,11 @@
|
||||
var Marker = require('../../../tokenizer/marker');
|
||||
|
||||
function isMergeableShorthand(shorthand) {
|
||||
if (shorthand.name != 'font') {
|
||||
return true;
|
||||
}
|
||||
|
||||
return shorthand.value[0][1].indexOf(Marker.INTERNAL) == -1;
|
||||
}
|
||||
|
||||
module.exports = isMergeableShorthand;
|
496
node_modules/clean-css/lib/optimizer/level-2/properties/merge-into-shorthands.js
generated
vendored
Normal file
496
node_modules/clean-css/lib/optimizer/level-2/properties/merge-into-shorthands.js
generated
vendored
Normal file
@ -0,0 +1,496 @@
|
||||
var everyValuesPair = require('./every-values-pair');
|
||||
var hasInherit = require('./has-inherit');
|
||||
var hasSameValues = require('./has-same-values');
|
||||
var populateComponents = require('./populate-components');
|
||||
|
||||
var configuration = require('../../configuration');
|
||||
var deepClone = require('../../clone').deep;
|
||||
var restoreWithComponents = require('../restore-with-components');
|
||||
|
||||
var restoreFromOptimizing = require('../../restore-from-optimizing');
|
||||
var wrapSingle = require('../../wrap-for-optimizing').single;
|
||||
|
||||
var serializeBody = require('../../../writer/one-time').body;
|
||||
var Token = require('../../../tokenizer/token');
|
||||
|
||||
function mergeIntoShorthands(properties, validator) {
|
||||
var candidates = {};
|
||||
var descriptor;
|
||||
var componentOf;
|
||||
var property;
|
||||
var i, l;
|
||||
var j, m;
|
||||
|
||||
// there is no shorthand property made up of less than 3 longhands
|
||||
if (properties.length < 3) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0, l = properties.length; i < l; i++) {
|
||||
property = properties[i];
|
||||
descriptor = configuration[property.name];
|
||||
|
||||
if (property.dynamic) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (property.unused) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (property.hack) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (property.block) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (descriptor && descriptor.singleTypeComponents && !hasSameValues(property)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
invalidateOrCompact(properties, i, candidates, validator);
|
||||
|
||||
if (descriptor && descriptor.componentOf) {
|
||||
for (j = 0, m = descriptor.componentOf.length; j < m; j++) {
|
||||
componentOf = descriptor.componentOf[j];
|
||||
|
||||
candidates[componentOf] = candidates[componentOf] || {};
|
||||
candidates[componentOf][property.name] = property;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
invalidateOrCompact(properties, i, candidates, validator);
|
||||
}
|
||||
|
||||
function invalidateOrCompact(properties, position, candidates, validator) {
|
||||
var invalidatedBy = properties[position];
|
||||
var shorthandName;
|
||||
var shorthandDescriptor;
|
||||
var candidateComponents;
|
||||
var replacedCandidates = [];
|
||||
var i;
|
||||
|
||||
for (shorthandName in candidates) {
|
||||
if (undefined !== invalidatedBy && shorthandName == invalidatedBy.name) {
|
||||
continue;
|
||||
}
|
||||
|
||||
shorthandDescriptor = configuration[shorthandName];
|
||||
candidateComponents = candidates[shorthandName];
|
||||
if (invalidatedBy && invalidates(candidates, shorthandName, invalidatedBy)) {
|
||||
delete candidates[shorthandName];
|
||||
continue;
|
||||
}
|
||||
|
||||
if (shorthandDescriptor.components.length > Object.keys(candidateComponents).length) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (mixedImportance(candidateComponents)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!overridable(candidateComponents, shorthandName, validator)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!mergeable(candidateComponents)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (mixedInherit(candidateComponents)) {
|
||||
replaceWithInheritBestFit(properties, candidateComponents, shorthandName, validator);
|
||||
} else {
|
||||
replaceWithShorthand(properties, candidateComponents, shorthandName, validator);
|
||||
}
|
||||
|
||||
replacedCandidates.push(shorthandName);
|
||||
}
|
||||
|
||||
for (i = replacedCandidates.length - 1; i >= 0; i--) {
|
||||
delete candidates[replacedCandidates[i]];
|
||||
}
|
||||
}
|
||||
|
||||
function invalidates(candidates, shorthandName, invalidatedBy) {
|
||||
var shorthandDescriptor = configuration[shorthandName];
|
||||
var invalidatedByDescriptor = configuration[invalidatedBy.name];
|
||||
var componentName;
|
||||
|
||||
if ('overridesShorthands' in shorthandDescriptor && shorthandDescriptor.overridesShorthands.indexOf(invalidatedBy.name) > -1) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (invalidatedByDescriptor && 'componentOf' in invalidatedByDescriptor) {
|
||||
for (componentName in candidates[shorthandName]) {
|
||||
if (invalidatedByDescriptor.componentOf.indexOf(componentName) > -1) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function mixedImportance(components) {
|
||||
var important;
|
||||
var componentName;
|
||||
|
||||
for (componentName in components) {
|
||||
if (undefined !== important && components[componentName].important != important) {
|
||||
return true;
|
||||
}
|
||||
|
||||
important = components[componentName].important;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function overridable(components, shorthandName, validator) {
|
||||
var descriptor = configuration[shorthandName];
|
||||
var newValuePlaceholder = [
|
||||
Token.PROPERTY,
|
||||
[Token.PROPERTY_NAME, shorthandName],
|
||||
[Token.PROPERTY_VALUE, descriptor.defaultValue]
|
||||
];
|
||||
var newProperty = wrapSingle(newValuePlaceholder);
|
||||
var component;
|
||||
var mayOverride;
|
||||
var i, l;
|
||||
|
||||
populateComponents([newProperty], validator, []);
|
||||
|
||||
for (i = 0, l = descriptor.components.length; i < l; i++) {
|
||||
component = components[descriptor.components[i]];
|
||||
mayOverride = configuration[component.name].canOverride || sameValue;
|
||||
|
||||
if (!everyValuesPair(mayOverride.bind(null, validator), newProperty.components[i], component)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
function sameValue(_validator, value1, value2) {
|
||||
return value1 === value2;
|
||||
}
|
||||
|
||||
function mergeable(components) {
|
||||
var lastCount = null;
|
||||
var currentCount;
|
||||
var componentName;
|
||||
var component;
|
||||
var descriptor;
|
||||
var values;
|
||||
|
||||
for (componentName in components) {
|
||||
component = components[componentName];
|
||||
descriptor = configuration[componentName];
|
||||
|
||||
if (!('restore' in descriptor)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
restoreFromOptimizing([component.all[component.position]], restoreWithComponents);
|
||||
values = descriptor.restore(component, configuration);
|
||||
|
||||
currentCount = values.length;
|
||||
|
||||
if (lastCount !== null && currentCount !== lastCount) {
|
||||
return false;
|
||||
}
|
||||
|
||||
lastCount = currentCount;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
function mixedInherit(components) {
|
||||
var componentName;
|
||||
var lastValue = null;
|
||||
var currentValue;
|
||||
|
||||
for (componentName in components) {
|
||||
currentValue = hasInherit(components[componentName]);
|
||||
|
||||
if (lastValue !== null && lastValue !== currentValue) {
|
||||
return true;
|
||||
}
|
||||
|
||||
lastValue = currentValue;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function replaceWithInheritBestFit(properties, candidateComponents, shorthandName, validator) {
|
||||
var viaLonghands = buildSequenceWithInheritLonghands(candidateComponents, shorthandName, validator);
|
||||
var viaShorthand = buildSequenceWithInheritShorthand(candidateComponents, shorthandName, validator);
|
||||
var longhandTokensSequence = viaLonghands[0];
|
||||
var shorthandTokensSequence = viaShorthand[0];
|
||||
var isLonghandsShorter = serializeBody(longhandTokensSequence).length < serializeBody(shorthandTokensSequence).length;
|
||||
var newTokensSequence = isLonghandsShorter ? longhandTokensSequence : shorthandTokensSequence;
|
||||
var newProperty = isLonghandsShorter ? viaLonghands[1] : viaShorthand[1];
|
||||
var newComponents = isLonghandsShorter ? viaLonghands[2] : viaShorthand[2];
|
||||
var lastComponent = candidateComponents[Object.keys(candidateComponents).pop()];
|
||||
var all = lastComponent.all;
|
||||
var insertAt = lastComponent.position;
|
||||
var componentName;
|
||||
var oldComponent;
|
||||
var newComponent;
|
||||
var newToken;
|
||||
|
||||
newProperty.position = insertAt;
|
||||
newProperty.shorthand = true;
|
||||
newProperty.important = lastComponent.important;
|
||||
newProperty.multiplex = false;
|
||||
newProperty.dirty = true;
|
||||
newProperty.all = all;
|
||||
newProperty.all[insertAt] = newTokensSequence[0];
|
||||
|
||||
properties.splice(insertAt, 1, newProperty);
|
||||
|
||||
for (componentName in candidateComponents) {
|
||||
oldComponent = candidateComponents[componentName];
|
||||
oldComponent.unused = true;
|
||||
|
||||
newProperty.multiplex = newProperty.multiplex || oldComponent.multiplex;
|
||||
|
||||
if (oldComponent.name in newComponents) {
|
||||
newComponent = newComponents[oldComponent.name];
|
||||
newToken = findTokenIn(newTokensSequence, componentName);
|
||||
|
||||
newComponent.position = all.length;
|
||||
newComponent.all = all;
|
||||
newComponent.all.push(newToken);
|
||||
|
||||
properties.push(newComponent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function buildSequenceWithInheritLonghands(components, shorthandName, validator) {
|
||||
var tokensSequence = [];
|
||||
var inheritComponents = {};
|
||||
var nonInheritComponents = {};
|
||||
var descriptor = configuration[shorthandName];
|
||||
var shorthandToken = [
|
||||
Token.PROPERTY,
|
||||
[Token.PROPERTY_NAME, shorthandName],
|
||||
[Token.PROPERTY_VALUE, descriptor.defaultValue]
|
||||
];
|
||||
var newProperty = wrapSingle(shorthandToken);
|
||||
var component;
|
||||
var longhandToken;
|
||||
var newComponent;
|
||||
var nameMetadata;
|
||||
var i, l;
|
||||
|
||||
populateComponents([newProperty], validator, []);
|
||||
|
||||
for (i = 0, l = descriptor.components.length; i < l; i++) {
|
||||
component = components[descriptor.components[i]];
|
||||
|
||||
if (hasInherit(component)) {
|
||||
longhandToken = component.all[component.position].slice(0, 2);
|
||||
Array.prototype.push.apply(longhandToken, component.value);
|
||||
tokensSequence.push(longhandToken);
|
||||
|
||||
newComponent = deepClone(component);
|
||||
newComponent.value = inferComponentValue(components, newComponent.name);
|
||||
|
||||
newProperty.components[i] = newComponent;
|
||||
inheritComponents[component.name] = deepClone(component);
|
||||
} else {
|
||||
newComponent = deepClone(component);
|
||||
newComponent.all = component.all;
|
||||
newProperty.components[i] = newComponent;
|
||||
|
||||
nonInheritComponents[component.name] = component;
|
||||
}
|
||||
}
|
||||
|
||||
newProperty.important = components[Object.keys(components).pop()].important;
|
||||
|
||||
nameMetadata = joinMetadata(nonInheritComponents, 1);
|
||||
shorthandToken[1].push(nameMetadata);
|
||||
|
||||
restoreFromOptimizing([newProperty], restoreWithComponents);
|
||||
|
||||
shorthandToken = shorthandToken.slice(0, 2);
|
||||
Array.prototype.push.apply(shorthandToken, newProperty.value);
|
||||
|
||||
tokensSequence.unshift(shorthandToken);
|
||||
|
||||
return [tokensSequence, newProperty, inheritComponents];
|
||||
}
|
||||
|
||||
function inferComponentValue(components, propertyName) {
|
||||
var descriptor = configuration[propertyName];
|
||||
|
||||
if ('oppositeTo' in descriptor) {
|
||||
return components[descriptor.oppositeTo].value;
|
||||
}
|
||||
return [[Token.PROPERTY_VALUE, descriptor.defaultValue]];
|
||||
}
|
||||
|
||||
function joinMetadata(components, at) {
|
||||
var metadata = [];
|
||||
var component;
|
||||
var originalValue;
|
||||
var componentMetadata;
|
||||
var componentName;
|
||||
|
||||
for (componentName in components) {
|
||||
component = components[componentName];
|
||||
originalValue = component.all[component.position];
|
||||
componentMetadata = originalValue[at][originalValue[at].length - 1];
|
||||
|
||||
Array.prototype.push.apply(metadata, componentMetadata);
|
||||
}
|
||||
|
||||
return metadata.sort(metadataSorter);
|
||||
}
|
||||
|
||||
function metadataSorter(metadata1, metadata2) {
|
||||
var line1 = metadata1[0];
|
||||
var line2 = metadata2[0];
|
||||
var column1 = metadata1[1];
|
||||
var column2 = metadata2[1];
|
||||
|
||||
if (line1 < line2) {
|
||||
return -1;
|
||||
} if (line1 === line2) {
|
||||
return column1 < column2 ? -1 : 1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
function buildSequenceWithInheritShorthand(components, shorthandName, validator) {
|
||||
var tokensSequence = [];
|
||||
var inheritComponents = {};
|
||||
var nonInheritComponents = {};
|
||||
var descriptor = configuration[shorthandName];
|
||||
var shorthandToken = [
|
||||
Token.PROPERTY,
|
||||
[Token.PROPERTY_NAME, shorthandName],
|
||||
[Token.PROPERTY_VALUE, 'inherit']
|
||||
];
|
||||
var newProperty = wrapSingle(shorthandToken);
|
||||
var component;
|
||||
var longhandToken;
|
||||
var nameMetadata;
|
||||
var valueMetadata;
|
||||
var i, l;
|
||||
|
||||
populateComponents([newProperty], validator, []);
|
||||
|
||||
for (i = 0, l = descriptor.components.length; i < l; i++) {
|
||||
component = components[descriptor.components[i]];
|
||||
|
||||
if (hasInherit(component)) {
|
||||
inheritComponents[component.name] = component;
|
||||
} else {
|
||||
longhandToken = component.all[component.position].slice(0, 2);
|
||||
Array.prototype.push.apply(longhandToken, component.value);
|
||||
tokensSequence.push(longhandToken);
|
||||
|
||||
nonInheritComponents[component.name] = deepClone(component);
|
||||
}
|
||||
}
|
||||
|
||||
nameMetadata = joinMetadata(inheritComponents, 1);
|
||||
shorthandToken[1].push(nameMetadata);
|
||||
|
||||
valueMetadata = joinMetadata(inheritComponents, 2);
|
||||
shorthandToken[2].push(valueMetadata);
|
||||
|
||||
tokensSequence.unshift(shorthandToken);
|
||||
|
||||
return [tokensSequence, newProperty, nonInheritComponents];
|
||||
}
|
||||
|
||||
function findTokenIn(tokens, componentName) {
|
||||
var i, l;
|
||||
|
||||
for (i = 0, l = tokens.length; i < l; i++) {
|
||||
if (tokens[i][1][1] == componentName) {
|
||||
return tokens[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function replaceWithShorthand(properties, candidateComponents, shorthandName, validator) {
|
||||
var descriptor = configuration[shorthandName];
|
||||
var nameMetadata;
|
||||
var valueMetadata;
|
||||
var newValuePlaceholder = [
|
||||
Token.PROPERTY,
|
||||
[Token.PROPERTY_NAME, shorthandName],
|
||||
[Token.PROPERTY_VALUE, descriptor.defaultValue]
|
||||
];
|
||||
var all;
|
||||
var insertAt = inferInsertAtFrom(properties, candidateComponents, shorthandName);
|
||||
|
||||
var newProperty = wrapSingle(newValuePlaceholder);
|
||||
newProperty.shorthand = true;
|
||||
newProperty.dirty = true;
|
||||
newProperty.multiplex = false;
|
||||
|
||||
populateComponents([newProperty], validator, []);
|
||||
|
||||
for (var i = 0, l = descriptor.components.length; i < l; i++) {
|
||||
var component = candidateComponents[descriptor.components[i]];
|
||||
|
||||
newProperty.components[i] = deepClone(component);
|
||||
newProperty.important = component.important;
|
||||
newProperty.multiplex = newProperty.multiplex || component.multiplex;
|
||||
|
||||
all = component.all;
|
||||
}
|
||||
|
||||
for (var componentName in candidateComponents) {
|
||||
candidateComponents[componentName].unused = true;
|
||||
}
|
||||
|
||||
nameMetadata = joinMetadata(candidateComponents, 1);
|
||||
newValuePlaceholder[1].push(nameMetadata);
|
||||
|
||||
valueMetadata = joinMetadata(candidateComponents, 2);
|
||||
newValuePlaceholder[2].push(valueMetadata);
|
||||
|
||||
newProperty.position = insertAt;
|
||||
newProperty.all = all;
|
||||
newProperty.all[insertAt] = newValuePlaceholder;
|
||||
|
||||
properties.splice(insertAt, 1, newProperty);
|
||||
}
|
||||
|
||||
function inferInsertAtFrom(properties, candidateComponents, shorthandName) {
|
||||
var candidateComponentNames = Object.keys(candidateComponents);
|
||||
var firstCandidatePosition = candidateComponents[candidateComponentNames[0]].position;
|
||||
var lastCandidatePosition = candidateComponents[candidateComponentNames[candidateComponentNames.length - 1]].position;
|
||||
|
||||
if (shorthandName == 'border' && traversesVia(properties.slice(firstCandidatePosition, lastCandidatePosition), 'border-image')) {
|
||||
return firstCandidatePosition;
|
||||
}
|
||||
return lastCandidatePosition;
|
||||
}
|
||||
|
||||
function traversesVia(properties, propertyName) {
|
||||
for (var i = properties.length - 1; i >= 0; i--) {
|
||||
if (properties[i].name == propertyName) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
module.exports = mergeIntoShorthands;
|
40
node_modules/clean-css/lib/optimizer/level-2/properties/optimize.js
generated
vendored
Normal file
40
node_modules/clean-css/lib/optimizer/level-2/properties/optimize.js
generated
vendored
Normal file
@ -0,0 +1,40 @@
|
||||
var mergeIntoShorthands = require('./merge-into-shorthands');
|
||||
var overrideProperties = require('./override-properties');
|
||||
var populateComponents = require('./populate-components');
|
||||
|
||||
var restoreWithComponents = require('../restore-with-components');
|
||||
|
||||
var wrapForOptimizing = require('../../wrap-for-optimizing').all;
|
||||
var removeUnused = require('../../remove-unused');
|
||||
var restoreFromOptimizing = require('../../restore-from-optimizing');
|
||||
|
||||
var OptimizationLevel = require('../../../options/optimization-level').OptimizationLevel;
|
||||
|
||||
function optimizeProperties(properties, withOverriding, withMerging, context) {
|
||||
var levelOptions = context.options.level[OptimizationLevel.Two];
|
||||
var _properties = wrapForOptimizing(properties, levelOptions.skipProperties);
|
||||
var _property;
|
||||
var i, l;
|
||||
|
||||
populateComponents(_properties, context.validator, context.warnings);
|
||||
|
||||
for (i = 0, l = _properties.length; i < l; i++) {
|
||||
_property = _properties[i];
|
||||
if (_property.block) {
|
||||
optimizeProperties(_property.value[0][1], withOverriding, withMerging, context);
|
||||
}
|
||||
}
|
||||
|
||||
if (withMerging && levelOptions.mergeIntoShorthands) {
|
||||
mergeIntoShorthands(_properties, context.validator);
|
||||
}
|
||||
|
||||
if (withOverriding && levelOptions.overrideProperties) {
|
||||
overrideProperties(_properties, withMerging, context.options.compatibility, context.validator);
|
||||
}
|
||||
|
||||
restoreFromOptimizing(_properties, restoreWithComponents);
|
||||
removeUnused(_properties);
|
||||
}
|
||||
|
||||
module.exports = optimizeProperties;
|
461
node_modules/clean-css/lib/optimizer/level-2/properties/override-properties.js
generated
vendored
Normal file
461
node_modules/clean-css/lib/optimizer/level-2/properties/override-properties.js
generated
vendored
Normal file
@ -0,0 +1,461 @@
|
||||
var hasInherit = require('./has-inherit');
|
||||
var hasUnset = require('./has-unset');
|
||||
var everyValuesPair = require('./every-values-pair');
|
||||
var findComponentIn = require('./find-component-in');
|
||||
var isComponentOf = require('./is-component-of');
|
||||
var isMergeableShorthand = require('./is-mergeable-shorthand');
|
||||
var overridesNonComponentShorthand = require('./overrides-non-component-shorthand');
|
||||
var sameVendorPrefixesIn = require('./../../vendor-prefixes').same;
|
||||
|
||||
var configuration = require('../../configuration');
|
||||
var deepClone = require('../../clone').deep;
|
||||
var restoreWithComponents = require('../restore-with-components');
|
||||
var shallowClone = require('../../clone').shallow;
|
||||
|
||||
var restoreFromOptimizing = require('../../restore-from-optimizing');
|
||||
|
||||
var Token = require('../../../tokenizer/token');
|
||||
var Marker = require('../../../tokenizer/marker');
|
||||
|
||||
var serializeProperty = require('../../../writer/one-time').property;
|
||||
|
||||
function sameValue(_validator, value1, value2) {
|
||||
return value1 === value2;
|
||||
}
|
||||
|
||||
function wouldBreakCompatibility(property, validator) {
|
||||
for (var i = 0; i < property.components.length; i++) {
|
||||
var component = property.components[i];
|
||||
var descriptor = configuration[component.name];
|
||||
var canOverride = descriptor && descriptor.canOverride || sameValue;
|
||||
|
||||
var _component = shallowClone(component);
|
||||
_component.value = [[Token.PROPERTY_VALUE, descriptor.defaultValue]];
|
||||
|
||||
if (!everyValuesPair(canOverride.bind(null, validator), _component, component)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function overrideIntoMultiplex(property, by) {
|
||||
by.unused = true;
|
||||
|
||||
turnIntoMultiplex(by, multiplexSize(property));
|
||||
property.value = by.value;
|
||||
}
|
||||
|
||||
function overrideByMultiplex(property, by) {
|
||||
by.unused = true;
|
||||
property.multiplex = true;
|
||||
property.value = by.value;
|
||||
}
|
||||
|
||||
function overrideSimple(property, by) {
|
||||
by.unused = true;
|
||||
property.value = by.value;
|
||||
}
|
||||
|
||||
function override(property, by) {
|
||||
if (by.multiplex) {
|
||||
overrideByMultiplex(property, by);
|
||||
} else if (property.multiplex) {
|
||||
overrideIntoMultiplex(property, by);
|
||||
} else {
|
||||
overrideSimple(property, by);
|
||||
}
|
||||
}
|
||||
|
||||
function overrideShorthand(property, by) {
|
||||
by.unused = true;
|
||||
|
||||
for (var i = 0, l = property.components.length; i < l; i++) {
|
||||
override(property.components[i], by.components[i]);
|
||||
}
|
||||
}
|
||||
|
||||
function turnIntoMultiplex(property, size) {
|
||||
property.multiplex = true;
|
||||
|
||||
if (configuration[property.name].shorthand) {
|
||||
turnShorthandValueIntoMultiplex(property, size);
|
||||
} else {
|
||||
turnLonghandValueIntoMultiplex(property, size);
|
||||
}
|
||||
}
|
||||
|
||||
function turnShorthandValueIntoMultiplex(property, size) {
|
||||
var component;
|
||||
var i, l;
|
||||
|
||||
for (i = 0, l = property.components.length; i < l; i++) {
|
||||
component = property.components[i];
|
||||
|
||||
if (!component.multiplex) {
|
||||
turnLonghandValueIntoMultiplex(component, size);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function turnLonghandValueIntoMultiplex(property, size) {
|
||||
var descriptor = configuration[property.name];
|
||||
var withRealValue = descriptor.intoMultiplexMode == 'real';
|
||||
var withValue = descriptor.intoMultiplexMode == 'real'
|
||||
? property.value.slice(0)
|
||||
: (descriptor.intoMultiplexMode == 'placeholder' ? descriptor.placeholderValue : descriptor.defaultValue);
|
||||
var i = multiplexSize(property);
|
||||
var j;
|
||||
var m = withValue.length;
|
||||
|
||||
for (; i < size; i++) {
|
||||
property.value.push([Token.PROPERTY_VALUE, Marker.COMMA]);
|
||||
|
||||
if (Array.isArray(withValue)) {
|
||||
for (j = 0; j < m; j++) {
|
||||
property.value.push(withRealValue ? withValue[j] : [Token.PROPERTY_VALUE, withValue[j]]);
|
||||
}
|
||||
} else {
|
||||
property.value.push(withRealValue ? withValue : [Token.PROPERTY_VALUE, withValue]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function multiplexSize(component) {
|
||||
var size = 0;
|
||||
|
||||
for (var i = 0, l = component.value.length; i < l; i++) {
|
||||
if (component.value[i][1] == Marker.COMMA) { size++; }
|
||||
}
|
||||
|
||||
return size + 1;
|
||||
}
|
||||
|
||||
function lengthOf(property) {
|
||||
var fakeAsArray = [
|
||||
Token.PROPERTY,
|
||||
[Token.PROPERTY_NAME, property.name]
|
||||
].concat(property.value);
|
||||
return serializeProperty([fakeAsArray], 0).length;
|
||||
}
|
||||
|
||||
function moreSameShorthands(properties, startAt, name) {
|
||||
// Since we run the main loop in `compactOverrides` backwards, at this point some
|
||||
// properties may not be marked as unused.
|
||||
// We should consider reverting the order if possible
|
||||
var count = 0;
|
||||
|
||||
for (var i = startAt; i >= 0; i--) {
|
||||
if (properties[i].name == name && !properties[i].unused) { count++; }
|
||||
if (count > 1) { break; }
|
||||
}
|
||||
|
||||
return count > 1;
|
||||
}
|
||||
|
||||
function overridingFunction(shorthand, validator) {
|
||||
for (var i = 0, l = shorthand.components.length; i < l; i++) {
|
||||
if (!anyValue(validator.isUrl, shorthand.components[i])
|
||||
&& anyValue(validator.isFunction, shorthand.components[i])) { return true; }
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function anyValue(fn, property) {
|
||||
for (var i = 0, l = property.value.length; i < l; i++) {
|
||||
if (property.value[i][1] == Marker.COMMA) { continue; }
|
||||
|
||||
if (fn(property.value[i][1])) { return true; }
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function wouldResultInLongerValue(left, right) {
|
||||
if (!left.multiplex && !right.multiplex || left.multiplex && right.multiplex) { return false; }
|
||||
|
||||
var multiplex = left.multiplex ? left : right;
|
||||
var simple = left.multiplex ? right : left;
|
||||
var component;
|
||||
|
||||
var multiplexClone = deepClone(multiplex);
|
||||
restoreFromOptimizing([multiplexClone], restoreWithComponents);
|
||||
|
||||
var simpleClone = deepClone(simple);
|
||||
restoreFromOptimizing([simpleClone], restoreWithComponents);
|
||||
|
||||
var lengthBefore = lengthOf(multiplexClone) + 1 + lengthOf(simpleClone);
|
||||
|
||||
if (left.multiplex) {
|
||||
component = findComponentIn(multiplexClone, simpleClone);
|
||||
overrideIntoMultiplex(component, simpleClone);
|
||||
} else {
|
||||
component = findComponentIn(simpleClone, multiplexClone);
|
||||
turnIntoMultiplex(simpleClone, multiplexSize(multiplexClone));
|
||||
overrideByMultiplex(component, multiplexClone);
|
||||
}
|
||||
|
||||
restoreFromOptimizing([simpleClone], restoreWithComponents);
|
||||
|
||||
var lengthAfter = lengthOf(simpleClone);
|
||||
|
||||
return lengthBefore <= lengthAfter;
|
||||
}
|
||||
|
||||
function isCompactable(property) {
|
||||
return property.name in configuration;
|
||||
}
|
||||
|
||||
function noneOverrideHack(left, right) {
|
||||
return !left.multiplex
|
||||
&& (left.name == 'background' || left.name == 'background-image')
|
||||
&& right.multiplex
|
||||
&& (right.name == 'background' || right.name == 'background-image')
|
||||
&& anyLayerIsNone(right.value);
|
||||
}
|
||||
|
||||
function anyLayerIsNone(values) {
|
||||
var layers = intoLayers(values);
|
||||
|
||||
for (var i = 0, l = layers.length; i < l; i++) {
|
||||
if (layers[i].length == 1 && layers[i][0][1] == 'none') { return true; }
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function intoLayers(values) {
|
||||
var layers = [];
|
||||
|
||||
for (var i = 0, layer = [], l = values.length; i < l; i++) {
|
||||
var value = values[i];
|
||||
if (value[1] == Marker.COMMA) {
|
||||
layers.push(layer);
|
||||
layer = [];
|
||||
} else {
|
||||
layer.push(value);
|
||||
}
|
||||
}
|
||||
|
||||
layers.push(layer);
|
||||
return layers;
|
||||
}
|
||||
|
||||
function overrideProperties(properties, withMerging, compatibility, validator) {
|
||||
var mayOverride, right, left, component;
|
||||
var overriddenComponents;
|
||||
var overriddenComponent;
|
||||
var overridingComponent;
|
||||
var overridable;
|
||||
var i, j, k;
|
||||
|
||||
propertyLoop:
|
||||
for (i = properties.length - 1; i >= 0; i--) {
|
||||
right = properties[i];
|
||||
|
||||
if (!isCompactable(right)) { continue; }
|
||||
|
||||
if (right.block) { continue; }
|
||||
|
||||
mayOverride = configuration[right.name].canOverride || sameValue;
|
||||
|
||||
traverseLoop:
|
||||
for (j = i - 1; j >= 0; j--) {
|
||||
left = properties[j];
|
||||
|
||||
if (!isCompactable(left)) { continue; }
|
||||
|
||||
if (left.block) { continue; }
|
||||
|
||||
if (left.dynamic || right.dynamic) { continue; }
|
||||
|
||||
if (left.unused || right.unused) { continue; }
|
||||
|
||||
if (left.hack && !right.hack && !right.important || !left.hack && !left.important && right.hack) { continue; }
|
||||
|
||||
if (left.important == right.important && left.hack[0] != right.hack[0]) { continue; }
|
||||
|
||||
if (left.important == right.important
|
||||
&& (left.hack[0] != right.hack[0] || (left.hack[1] && left.hack[1] != right.hack[1]))) { continue; }
|
||||
|
||||
if (hasInherit(right)) { continue; }
|
||||
|
||||
if (noneOverrideHack(left, right)) { continue; }
|
||||
|
||||
if (right.shorthand && isComponentOf(right, left)) {
|
||||
// maybe `left` can be overridden by `right` which is a shorthand?
|
||||
if (!right.important && left.important) { continue; }
|
||||
|
||||
if (!sameVendorPrefixesIn([left], right.components)) { continue; }
|
||||
|
||||
if (!anyValue(validator.isFunction, left) && overridingFunction(right, validator)) { continue; }
|
||||
|
||||
if (!isMergeableShorthand(right)) {
|
||||
left.unused = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
component = findComponentIn(right, left);
|
||||
mayOverride = configuration[left.name].canOverride || sameValue;
|
||||
if (everyValuesPair(mayOverride.bind(null, validator), left, component)) {
|
||||
left.unused = true;
|
||||
}
|
||||
} else if (right.shorthand && overridesNonComponentShorthand(right, left)) {
|
||||
// `right` is a shorthand while `left` can be overriden by it, think `border` and `border-top`
|
||||
if (!right.important && left.important) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!sameVendorPrefixesIn([left], right.components)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!anyValue(validator.isFunction, left) && overridingFunction(right, validator)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
overriddenComponents = left.shorthand
|
||||
? left.components
|
||||
: [left];
|
||||
|
||||
for (k = overriddenComponents.length - 1; k >= 0; k--) {
|
||||
overriddenComponent = overriddenComponents[k];
|
||||
overridingComponent = findComponentIn(right, overriddenComponent);
|
||||
mayOverride = configuration[overriddenComponent.name].canOverride || sameValue;
|
||||
|
||||
if (!everyValuesPair(mayOverride.bind(null, validator), left, overridingComponent)) {
|
||||
continue traverseLoop;
|
||||
}
|
||||
}
|
||||
|
||||
left.unused = true;
|
||||
} else if (withMerging && left.shorthand && !right.shorthand && isComponentOf(left, right, true)) {
|
||||
// maybe `right` can be pulled into `left` which is a shorthand?
|
||||
if (right.important && !left.important) { continue; }
|
||||
|
||||
if (!right.important && left.important) {
|
||||
right.unused = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Pending more clever algorithm in #527
|
||||
if (moreSameShorthands(properties, i - 1, left.name)) { continue; }
|
||||
|
||||
if (overridingFunction(left, validator)) { continue; }
|
||||
|
||||
if (!isMergeableShorthand(left)) { continue; }
|
||||
|
||||
if (hasUnset(left) || hasUnset(right)) { continue; }
|
||||
|
||||
component = findComponentIn(left, right);
|
||||
if (everyValuesPair(mayOverride.bind(null, validator), component, right)) {
|
||||
var disabledBackgroundMerging = !compatibility.properties.backgroundClipMerging && component.name.indexOf('background-clip') > -1
|
||||
|| !compatibility.properties.backgroundOriginMerging && component.name.indexOf('background-origin') > -1
|
||||
|| !compatibility.properties.backgroundSizeMerging && component.name.indexOf('background-size') > -1;
|
||||
var nonMergeableValue = configuration[right.name].nonMergeableValue === right.value[0][1];
|
||||
|
||||
if (disabledBackgroundMerging || nonMergeableValue) { continue; }
|
||||
|
||||
if (!compatibility.properties.merging && wouldBreakCompatibility(left, validator)) { continue; }
|
||||
|
||||
if (component.value[0][1] != right.value[0][1] && (hasInherit(left) || hasInherit(right))) { continue; }
|
||||
|
||||
if (wouldResultInLongerValue(left, right)) { continue; }
|
||||
|
||||
if (!left.multiplex && right.multiplex) { turnIntoMultiplex(left, multiplexSize(right)); }
|
||||
|
||||
override(component, right);
|
||||
left.dirty = true;
|
||||
}
|
||||
} else if (withMerging && left.shorthand && right.shorthand && left.name == right.name) {
|
||||
// merge if all components can be merged
|
||||
|
||||
if (!left.multiplex && right.multiplex) { continue; }
|
||||
|
||||
if (!right.important && left.important) {
|
||||
right.unused = true;
|
||||
continue propertyLoop;
|
||||
}
|
||||
|
||||
if (right.important && !left.important) {
|
||||
left.unused = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!isMergeableShorthand(right)) {
|
||||
left.unused = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
for (k = left.components.length - 1; k >= 0; k--) {
|
||||
var leftComponent = left.components[k];
|
||||
var rightComponent = right.components[k];
|
||||
|
||||
mayOverride = configuration[leftComponent.name].canOverride || sameValue;
|
||||
if (!everyValuesPair(mayOverride.bind(null, validator), leftComponent, rightComponent)) {
|
||||
continue propertyLoop;
|
||||
}
|
||||
}
|
||||
|
||||
overrideShorthand(left, right);
|
||||
left.dirty = true;
|
||||
} else if (withMerging && left.shorthand && right.shorthand && isComponentOf(left, right)) {
|
||||
// border is a shorthand but any of its components is a shorthand too
|
||||
|
||||
if (!left.important && right.important) { continue; }
|
||||
|
||||
component = findComponentIn(left, right);
|
||||
mayOverride = configuration[right.name].canOverride || sameValue;
|
||||
if (!everyValuesPair(mayOverride.bind(null, validator), component, right)) { continue; }
|
||||
|
||||
if (left.important && !right.important) {
|
||||
right.unused = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
var rightRestored = configuration[right.name].restore(right, configuration);
|
||||
if (rightRestored.length > 1) { continue; }
|
||||
|
||||
component = findComponentIn(left, right);
|
||||
override(component, right);
|
||||
right.dirty = true;
|
||||
} else if (left.name == right.name) {
|
||||
// two non-shorthands should be merged based on understandability
|
||||
overridable = true;
|
||||
|
||||
if (right.shorthand) {
|
||||
for (k = right.components.length - 1; k >= 0 && overridable; k--) {
|
||||
overriddenComponent = left.components[k];
|
||||
overridingComponent = right.components[k];
|
||||
mayOverride = configuration[overridingComponent.name].canOverride || sameValue;
|
||||
|
||||
overridable = everyValuesPair(mayOverride.bind(null, validator), overriddenComponent, overridingComponent);
|
||||
}
|
||||
} else {
|
||||
mayOverride = configuration[right.name].canOverride || sameValue;
|
||||
overridable = everyValuesPair(mayOverride.bind(null, validator), left, right);
|
||||
}
|
||||
|
||||
if (left.important && !right.important && overridable) {
|
||||
right.unused = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!left.important && right.important && overridable) {
|
||||
left.unused = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!overridable) {
|
||||
continue;
|
||||
}
|
||||
|
||||
left.unused = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = overrideProperties;
|
9
node_modules/clean-css/lib/optimizer/level-2/properties/overrides-non-component-shorthand.js
generated
vendored
Normal file
9
node_modules/clean-css/lib/optimizer/level-2/properties/overrides-non-component-shorthand.js
generated
vendored
Normal file
@ -0,0 +1,9 @@
|
||||
var configuration = require('../../configuration');
|
||||
|
||||
function overridesNonComponentShorthand(property1, property2) {
|
||||
return property1.name in configuration
|
||||
&& 'overridesShorthands' in configuration[property1.name]
|
||||
&& configuration[property1.name].overridesShorthands.indexOf(property2.name) > -1;
|
||||
}
|
||||
|
||||
module.exports = overridesNonComponentShorthand;
|
61
node_modules/clean-css/lib/optimizer/level-2/properties/populate-components.js
generated
vendored
Normal file
61
node_modules/clean-css/lib/optimizer/level-2/properties/populate-components.js
generated
vendored
Normal file
@ -0,0 +1,61 @@
|
||||
var configuration = require('../../configuration');
|
||||
var InvalidPropertyError = require('../../invalid-property-error');
|
||||
|
||||
function populateComponents(properties, validator, warnings) {
|
||||
var component;
|
||||
var j, m;
|
||||
|
||||
for (var i = properties.length - 1; i >= 0; i--) {
|
||||
var property = properties[i];
|
||||
var descriptor = configuration[property.name];
|
||||
|
||||
if (!property.dynamic && descriptor && descriptor.shorthand) {
|
||||
if (onlyValueIsVariable(property, validator) || moreThanOneValueIsVariable(property, validator)) {
|
||||
property.optimizable = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
property.shorthand = true;
|
||||
property.dirty = true;
|
||||
|
||||
try {
|
||||
property.components = descriptor.breakUp(property, configuration, validator);
|
||||
|
||||
if (descriptor.shorthandComponents) {
|
||||
for (j = 0, m = property.components.length; j < m; j++) {
|
||||
component = property.components[j];
|
||||
component.components = configuration[component.name].breakUp(component, configuration, validator);
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
if (e instanceof InvalidPropertyError) {
|
||||
property.components = []; // this will set property.unused to true below
|
||||
warnings.push(e.message);
|
||||
} else {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
if (property.components.length > 0) {
|
||||
property.multiplex = property.components[0].multiplex;
|
||||
} else {
|
||||
property.unused = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function onlyValueIsVariable(property, validator) {
|
||||
return property.value.length == 1 && validator.isVariable(property.value[0][1]);
|
||||
}
|
||||
|
||||
function moreThanOneValueIsVariable(property, validator) {
|
||||
return property.value.length > 1
|
||||
&& property.value.filter(
|
||||
function(value) {
|
||||
return validator.isVariable(value[1]);
|
||||
}
|
||||
).length > 1;
|
||||
}
|
||||
|
||||
module.exports = populateComponents;
|
174
node_modules/clean-css/lib/optimizer/level-2/reduce-non-adjacent.js
generated
vendored
Normal file
174
node_modules/clean-css/lib/optimizer/level-2/reduce-non-adjacent.js
generated
vendored
Normal file
@ -0,0 +1,174 @@
|
||||
var isMergeable = require('./is-mergeable');
|
||||
|
||||
var optimizeProperties = require('./properties/optimize');
|
||||
|
||||
var cloneArray = require('../../utils/clone-array');
|
||||
|
||||
var Token = require('../../tokenizer/token');
|
||||
|
||||
var serializeBody = require('../../writer/one-time').body;
|
||||
var serializeRules = require('../../writer/one-time').rules;
|
||||
|
||||
function reduceNonAdjacent(tokens, context) {
|
||||
var options = context.options;
|
||||
var mergeablePseudoClasses = options.compatibility.selectors.mergeablePseudoClasses;
|
||||
var mergeablePseudoElements = options.compatibility.selectors.mergeablePseudoElements;
|
||||
var multiplePseudoMerging = options.compatibility.selectors.multiplePseudoMerging;
|
||||
var candidates = {};
|
||||
var repeated = [];
|
||||
|
||||
for (var i = tokens.length - 1; i >= 0; i--) {
|
||||
var token = tokens[i];
|
||||
|
||||
if (token[0] != Token.RULE) {
|
||||
continue;
|
||||
} else if (token[2].length === 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
var selectorAsString = serializeRules(token[1]);
|
||||
var isComplexAndNotSpecial = token[1].length > 1
|
||||
&& isMergeable(selectorAsString, mergeablePseudoClasses, mergeablePseudoElements, multiplePseudoMerging);
|
||||
var wrappedSelectors = wrappedSelectorsFrom(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][1]]);
|
||||
}
|
||||
|
||||
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, data, {
|
||||
filterOut: filterOut,
|
||||
callback: reduceBody
|
||||
}, options, context);
|
||||
}
|
||||
}
|
||||
|
||||
function reduceComplexNonAdjacentCases(tokens, candidates, options, context) {
|
||||
var mergeablePseudoClasses = options.compatibility.selectors.mergeablePseudoClasses;
|
||||
var mergeablePseudoElements = options.compatibility.selectors.mergeablePseudoElements;
|
||||
var multiplePseudoMerging = options.compatibility.selectors.multiplePseudoMerging;
|
||||
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 = isMergeable(complexSelector, mergeablePseudoClasses, mergeablePseudoElements, multiplePseudoMerging)
|
||||
? into[0].list
|
||||
: [complexSelector];
|
||||
|
||||
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, data, {
|
||||
filterOut: filterOut,
|
||||
callback: collectReducedBodies
|
||||
}, options, context);
|
||||
|
||||
if (serializeBody(reducedBodies[reducedBodies.length - 1]) != serializeBody(reducedBodies[0])) {
|
||||
continue allSelectors;
|
||||
}
|
||||
}
|
||||
|
||||
intoToken[2] = reducedBodies[0];
|
||||
}
|
||||
}
|
||||
|
||||
function reduceSelector(tokens, data, context, options, outerContext) {
|
||||
var bodies = [];
|
||||
var bodiesAsList = [];
|
||||
var processedTokens = [];
|
||||
|
||||
for (var j = data.length - 1; 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);
|
||||
}
|
||||
|
||||
optimizeProperties(bodies, true, false, 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;
|
30
node_modules/clean-css/lib/optimizer/level-2/remove-duplicate-font-at-rules.js
generated
vendored
Normal file
30
node_modules/clean-css/lib/optimizer/level-2/remove-duplicate-font-at-rules.js
generated
vendored
Normal file
@ -0,0 +1,30 @@
|
||||
var Token = require('../../tokenizer/token');
|
||||
|
||||
var serializeAll = require('../../writer/one-time').all;
|
||||
|
||||
var FONT_FACE_SCOPE = '@font-face';
|
||||
|
||||
function removeDuplicateFontAtRules(tokens) {
|
||||
var fontAtRules = [];
|
||||
var token;
|
||||
var key;
|
||||
var i, l;
|
||||
|
||||
for (i = 0, l = tokens.length; i < l; i++) {
|
||||
token = tokens[i];
|
||||
|
||||
if (token[0] != Token.AT_RULE_BLOCK && token[1][0][1] != FONT_FACE_SCOPE) {
|
||||
continue;
|
||||
}
|
||||
|
||||
key = serializeAll([token]);
|
||||
|
||||
if (fontAtRules.indexOf(key) > -1) {
|
||||
token[2] = [];
|
||||
} else {
|
||||
fontAtRules.push(key);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = removeDuplicateFontAtRules;
|
30
node_modules/clean-css/lib/optimizer/level-2/remove-duplicate-media-queries.js
generated
vendored
Normal file
30
node_modules/clean-css/lib/optimizer/level-2/remove-duplicate-media-queries.js
generated
vendored
Normal file
@ -0,0 +1,30 @@
|
||||
var Token = require('../../tokenizer/token');
|
||||
|
||||
var serializeAll = require('../../writer/one-time').all;
|
||||
var serializeRules = require('../../writer/one-time').rules;
|
||||
|
||||
function removeDuplicateMediaQueries(tokens) {
|
||||
var candidates = {};
|
||||
var candidate;
|
||||
var token;
|
||||
var key;
|
||||
var i, l;
|
||||
|
||||
for (i = 0, l = tokens.length; i < l; i++) {
|
||||
token = tokens[i];
|
||||
if (token[0] != Token.NESTED_BLOCK) {
|
||||
continue;
|
||||
}
|
||||
|
||||
key = serializeRules(token[1]) + '%' + serializeAll(token[2]);
|
||||
candidate = candidates[key];
|
||||
|
||||
if (candidate) {
|
||||
candidate[2] = [];
|
||||
}
|
||||
|
||||
candidates[key] = token;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = removeDuplicateMediaQueries;
|
36
node_modules/clean-css/lib/optimizer/level-2/remove-duplicates.js
generated
vendored
Normal file
36
node_modules/clean-css/lib/optimizer/level-2/remove-duplicates.js
generated
vendored
Normal file
@ -0,0 +1,36 @@
|
||||
var Token = require('../../tokenizer/token');
|
||||
|
||||
var serializeBody = require('../../writer/one-time').body;
|
||||
var serializeRules = require('../../writer/one-time').rules;
|
||||
|
||||
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] != Token.RULE) { continue; }
|
||||
|
||||
id = serializeRules(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 = serializeBody(token[2]);
|
||||
|
||||
if (bodies.indexOf(body) > -1) { token[2] = []; } else { bodies.push(body); }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = removeDuplicates;
|
249
node_modules/clean-css/lib/optimizer/level-2/remove-unused-at-rules.js
generated
vendored
Normal file
249
node_modules/clean-css/lib/optimizer/level-2/remove-unused-at-rules.js
generated
vendored
Normal file
@ -0,0 +1,249 @@
|
||||
var populateComponents = require('./properties/populate-components');
|
||||
|
||||
var wrapForOptimizing = require('../wrap-for-optimizing').single;
|
||||
var restoreFromOptimizing = require('../restore-from-optimizing');
|
||||
|
||||
var Token = require('../../tokenizer/token');
|
||||
|
||||
var animationNameRegex = /^(-moz-|-o-|-webkit-)?animation-name$/;
|
||||
var animationRegex = /^(-moz-|-o-|-webkit-)?animation$/;
|
||||
var keyframeRegex = /^@(-moz-|-o-|-webkit-)?keyframes /;
|
||||
var importantRegex = /\s{0,31}!important$/;
|
||||
var optionalMatchingQuotesRegex = /^(['"]?)(.*)\1$/;
|
||||
|
||||
function normalize(value) {
|
||||
return value
|
||||
.replace(optionalMatchingQuotesRegex, '$2')
|
||||
.replace(importantRegex, '');
|
||||
}
|
||||
|
||||
function removeUnusedAtRules(tokens, context) {
|
||||
removeUnusedAtRule(tokens, matchCounterStyle, markCounterStylesAsUsed, context);
|
||||
removeUnusedAtRule(tokens, matchFontFace, markFontFacesAsUsed, context);
|
||||
removeUnusedAtRule(tokens, matchKeyframe, markKeyframesAsUsed, context);
|
||||
removeUnusedAtRule(tokens, matchNamespace, markNamespacesAsUsed, context);
|
||||
}
|
||||
|
||||
function removeUnusedAtRule(tokens, matchCallback, markCallback, context) {
|
||||
var atRules = {};
|
||||
var atRule;
|
||||
var atRuleTokens;
|
||||
var atRuleToken;
|
||||
var zeroAt;
|
||||
var i, l;
|
||||
|
||||
for (i = 0, l = tokens.length; i < l; i++) {
|
||||
matchCallback(tokens[i], atRules);
|
||||
}
|
||||
|
||||
if (Object.keys(atRules).length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
markUsedAtRules(tokens, markCallback, atRules, context);
|
||||
|
||||
for (atRule in atRules) {
|
||||
atRuleTokens = atRules[atRule];
|
||||
|
||||
for (i = 0, l = atRuleTokens.length; i < l; i++) {
|
||||
atRuleToken = atRuleTokens[i];
|
||||
zeroAt = atRuleToken[0] == Token.AT_RULE ? 1 : 2;
|
||||
atRuleToken[zeroAt] = [];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function markUsedAtRules(tokens, markCallback, atRules, context) {
|
||||
var boundMarkCallback = markCallback(atRules);
|
||||
var i, l;
|
||||
|
||||
for (i = 0, l = tokens.length; i < l; i++) {
|
||||
switch (tokens[i][0]) {
|
||||
case Token.RULE:
|
||||
boundMarkCallback(tokens[i], context);
|
||||
break;
|
||||
case Token.NESTED_BLOCK:
|
||||
markUsedAtRules(tokens[i][2], markCallback, atRules, context);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function matchCounterStyle(token, atRules) {
|
||||
var match;
|
||||
|
||||
if (token[0] == Token.AT_RULE_BLOCK && token[1][0][1].indexOf('@counter-style') === 0) {
|
||||
match = token[1][0][1].split(' ')[1];
|
||||
atRules[match] = atRules[match] || [];
|
||||
atRules[match].push(token);
|
||||
}
|
||||
}
|
||||
|
||||
function markCounterStylesAsUsed(atRules) {
|
||||
return function(token, context) {
|
||||
var property;
|
||||
var wrappedProperty;
|
||||
var i, l;
|
||||
|
||||
for (i = 0, l = token[2].length; i < l; i++) {
|
||||
property = token[2][i];
|
||||
|
||||
if (property[1][1] == 'list-style') {
|
||||
wrappedProperty = wrapForOptimizing(property);
|
||||
populateComponents([wrappedProperty], context.validator, context.warnings);
|
||||
|
||||
if (wrappedProperty.components[0].value[0][1] in atRules) {
|
||||
delete atRules[property[2][1]];
|
||||
}
|
||||
|
||||
restoreFromOptimizing([wrappedProperty]);
|
||||
}
|
||||
|
||||
if (property[1][1] == 'list-style-type' && property[2][1] in atRules) {
|
||||
delete atRules[property[2][1]];
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function matchFontFace(token, atRules) {
|
||||
var property;
|
||||
var match;
|
||||
var i, l;
|
||||
|
||||
if (token[0] == Token.AT_RULE_BLOCK && token[1][0][1] == '@font-face') {
|
||||
for (i = 0, l = token[2].length; i < l; i++) {
|
||||
property = token[2][i];
|
||||
|
||||
if (property[1][1] == 'font-family') {
|
||||
match = normalize(property[2][1].toLowerCase());
|
||||
atRules[match] = atRules[match] || [];
|
||||
atRules[match].push(token);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function markFontFacesAsUsed(atRules) {
|
||||
return function(token, context) {
|
||||
var property;
|
||||
var wrappedProperty;
|
||||
var component;
|
||||
var normalizedMatch;
|
||||
var i, l;
|
||||
var j, m;
|
||||
|
||||
for (i = 0, l = token[2].length; i < l; i++) {
|
||||
property = token[2][i];
|
||||
|
||||
if (property[1][1] == 'font') {
|
||||
wrappedProperty = wrapForOptimizing(property);
|
||||
populateComponents([wrappedProperty], context.validator, context.warnings);
|
||||
component = wrappedProperty.components[6];
|
||||
|
||||
for (j = 0, m = component.value.length; j < m; j++) {
|
||||
normalizedMatch = normalize(component.value[j][1].toLowerCase());
|
||||
|
||||
if (normalizedMatch in atRules) {
|
||||
delete atRules[normalizedMatch];
|
||||
}
|
||||
}
|
||||
|
||||
restoreFromOptimizing([wrappedProperty]);
|
||||
}
|
||||
|
||||
if (property[1][1] == 'font-family') {
|
||||
for (j = 2, m = property.length; j < m; j++) {
|
||||
normalizedMatch = normalize(property[j][1].toLowerCase());
|
||||
|
||||
if (normalizedMatch in atRules) {
|
||||
delete atRules[normalizedMatch];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function matchKeyframe(token, atRules) {
|
||||
var match;
|
||||
|
||||
if (token[0] == Token.NESTED_BLOCK && keyframeRegex.test(token[1][0][1])) {
|
||||
match = token[1][0][1].split(' ')[1];
|
||||
atRules[match] = atRules[match] || [];
|
||||
atRules[match].push(token);
|
||||
}
|
||||
}
|
||||
|
||||
function markKeyframesAsUsed(atRules) {
|
||||
return function(token, context) {
|
||||
var property;
|
||||
var wrappedProperty;
|
||||
var component;
|
||||
var i, l;
|
||||
var j, m;
|
||||
|
||||
for (i = 0, l = token[2].length; i < l; i++) {
|
||||
property = token[2][i];
|
||||
|
||||
if (animationRegex.test(property[1][1])) {
|
||||
wrappedProperty = wrapForOptimizing(property);
|
||||
populateComponents([wrappedProperty], context.validator, context.warnings);
|
||||
component = wrappedProperty.components[7];
|
||||
|
||||
for (j = 0, m = component.value.length; j < m; j++) {
|
||||
if (component.value[j][1] in atRules) {
|
||||
delete atRules[component.value[j][1]];
|
||||
}
|
||||
}
|
||||
|
||||
restoreFromOptimizing([wrappedProperty]);
|
||||
}
|
||||
|
||||
if (animationNameRegex.test(property[1][1])) {
|
||||
for (j = 2, m = property.length; j < m; j++) {
|
||||
if (property[j][1] in atRules) {
|
||||
delete atRules[property[j][1]];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function matchNamespace(token, atRules) {
|
||||
var match;
|
||||
|
||||
if (token[0] == Token.AT_RULE && token[1].indexOf('@namespace') === 0) {
|
||||
match = token[1].split(' ')[1];
|
||||
atRules[match] = atRules[match] || [];
|
||||
atRules[match].push(token);
|
||||
}
|
||||
}
|
||||
|
||||
function markNamespacesAsUsed(atRules) {
|
||||
var namespaceRegex = new RegExp(Object.keys(atRules).join('\\||') + '\\|', 'g');
|
||||
|
||||
return function(token) {
|
||||
var match;
|
||||
var scope;
|
||||
var normalizedMatch;
|
||||
var i, l;
|
||||
var j, m;
|
||||
|
||||
for (i = 0, l = token[1].length; i < l; i++) {
|
||||
scope = token[1][i];
|
||||
match = scope[1].match(namespaceRegex);
|
||||
|
||||
for (j = 0, m = match.length; j < m; j++) {
|
||||
normalizedMatch = match[j].substring(0, match[j].length - 1);
|
||||
|
||||
if (normalizedMatch in atRules) {
|
||||
delete atRules[normalizedMatch];
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
module.exports = removeUnusedAtRules;
|
93
node_modules/clean-css/lib/optimizer/level-2/reorderable.js
generated
vendored
Normal file
93
node_modules/clean-css/lib/optimizer/level-2/reorderable.js
generated
vendored
Normal file
@ -0,0 +1,93 @@
|
||||
// TODO: it'd be great to merge it with the other canReorder functionality
|
||||
|
||||
var rulesOverlap = require('./rules-overlap');
|
||||
var specificitiesOverlap = require('./specificities-overlap');
|
||||
|
||||
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, cache) {
|
||||
for (var i = right.length - 1; i >= 0; i--) {
|
||||
for (var j = left.length - 1; j >= 0; j--) {
|
||||
if (!canReorderSingle(left[j], right[i], cache)) { return false; }
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
function canReorderSingle(left, right, cache) {
|
||||
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)
|
||||
&& !rulesOverlap(rightSelector, leftSelector, false)) { return true; }
|
||||
if (!specificitiesOverlap(leftSelector, rightSelector, cache)) { 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 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
|
||||
};
|
12
node_modules/clean-css/lib/optimizer/level-2/restore-with-components.js
generated
vendored
Normal file
12
node_modules/clean-css/lib/optimizer/level-2/restore-with-components.js
generated
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
var configuration = require('../configuration');
|
||||
|
||||
function restoreWithComponents(property) {
|
||||
var descriptor = configuration[property.name];
|
||||
|
||||
if (descriptor && descriptor.shorthand) {
|
||||
return descriptor.restore(property, configuration);
|
||||
}
|
||||
return property.value;
|
||||
}
|
||||
|
||||
module.exports = restoreWithComponents;
|
392
node_modules/clean-css/lib/optimizer/level-2/restructure.js
generated
vendored
Normal file
392
node_modules/clean-css/lib/optimizer/level-2/restructure.js
generated
vendored
Normal file
@ -0,0 +1,392 @@
|
||||
var canReorderSingle = require('./reorderable').canReorderSingle;
|
||||
var extractProperties = require('./extract-properties');
|
||||
var isMergeable = require('./is-mergeable');
|
||||
var tidyRuleDuplicates = require('./tidy-rule-duplicates');
|
||||
|
||||
var Token = require('../../tokenizer/token');
|
||||
|
||||
var cloneArray = require('../../utils/clone-array');
|
||||
|
||||
var serializeBody = require('../../writer/one-time').body;
|
||||
var serializeRules = require('../../writer/one-time').rules;
|
||||
|
||||
function naturalSorter(a, b) {
|
||||
return a > b ? 1 : -1;
|
||||
}
|
||||
|
||||
function cloneAndMergeSelectors(propertyA, propertyB) {
|
||||
var cloned = cloneArray(propertyA);
|
||||
cloned[5] = cloned[5].concat(propertyB[5]);
|
||||
|
||||
return cloned;
|
||||
}
|
||||
|
||||
function restructure(tokens, context) {
|
||||
var options = context.options;
|
||||
var mergeablePseudoClasses = options.compatibility.selectors.mergeablePseudoClasses;
|
||||
var mergeablePseudoElements = options.compatibility.selectors.mergeablePseudoElements;
|
||||
var mergeLimit = options.compatibility.selectors.mergeLimit;
|
||||
var multiplePseudoMerging = options.compatibility.selectors.multiplePseudoMerging;
|
||||
var specificityCache = context.cache.specificity;
|
||||
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(serializeRules(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 (!isMergeable(
|
||||
serializeRules(sourceTokens[i][1]),
|
||||
mergeablePseudoClasses,
|
||||
mergeablePseudoElements,
|
||||
multiplePseudoMerging
|
||||
)) {
|
||||
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 = tidyRuleDuplicates(allSelectors);
|
||||
dropAsNewTokenAt(position, [movedProperty], allSelectors, qualifiedTokens);
|
||||
}
|
||||
|
||||
function fitSorter(fit1, fit2) {
|
||||
return fit1[1] > fit2[1] ? 1 : (fit1[1] == fit2[1] ? 0 : -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
|
||||
? serializeRules(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[1][1];
|
||||
var propertyName = property[0];
|
||||
var propertyBody = property[4];
|
||||
if (mergeablePropertyName == propertyName && serializeBody([mergeableProperty]) == propertyBody) {
|
||||
mergeableToken[2].splice(j, 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (i = properties.length - 1; i >= 0; i--) {
|
||||
allProperties.unshift(properties[i][3]);
|
||||
}
|
||||
|
||||
var newToken = [Token.RULE, 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 = tidyRuleDuplicates(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 isRule;
|
||||
var j, k, m;
|
||||
var samePropertyAt;
|
||||
|
||||
if (token[0] == Token.RULE) {
|
||||
isRule = true;
|
||||
} else if (token[0] == Token.NESTED_BLOCK) {
|
||||
isRule = 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], specificityCache)) {
|
||||
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, specificityCache)
|
||||
&& !boundToAnotherPropertyInCurrrentToken(property, movedProperty, token)
|
||||
|| movableTokens[movedProperty[4]] && movableTokens[movedProperty[4]].length === mergeLimit)
|
||||
) {
|
||||
dropPropertiesAt(i + 1, movedProperty);
|
||||
|
||||
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 (!isRule || unmovableInCurrentToken.indexOf(j) > -1) { continue; }
|
||||
|
||||
var key = property[4];
|
||||
|
||||
if (movedSameProperty && movedProperties[samePropertyAt][5].length + property[5].length > mergeLimit) {
|
||||
dropPropertiesAt(i + 1, movedProperties[samePropertyAt]);
|
||||
movedProperties.splice(samePropertyAt, 1);
|
||||
movableTokens[key] = [token];
|
||||
movedSameProperty = false;
|
||||
} else {
|
||||
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] == Token.AT_RULE && tokens[0][1].indexOf('@charset') === 0 ? 1 : 0;
|
||||
for (; position < tokens.length - 1; position++) {
|
||||
var isImportRule = tokens[position][0] === Token.AT_RULE && tokens[position][1].indexOf('@import') === 0;
|
||||
var isComment = tokens[position][0] === Token.COMMENT;
|
||||
if (!(isImportRule || isComment)) { break; }
|
||||
}
|
||||
|
||||
for (i = 0; i < movedProperties.length; i++) {
|
||||
dropPropertiesAt(position, movedProperties[i]);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = restructure;
|
32
node_modules/clean-css/lib/optimizer/level-2/rules-overlap.js
generated
vendored
Normal file
32
node_modules/clean-css/lib/optimizer/level-2/rules-overlap.js
generated
vendored
Normal file
@ -0,0 +1,32 @@
|
||||
var MODIFIER_PATTERN = /--.+$/;
|
||||
|
||||
function rulesOverlap(rule1, rule2, bemMode) {
|
||||
var scope1;
|
||||
var scope2;
|
||||
var i, l;
|
||||
var j, m;
|
||||
|
||||
for (i = 0, l = rule1.length; i < l; i++) {
|
||||
scope1 = rule1[i][1];
|
||||
|
||||
for (j = 0, m = rule2.length; j < m; j++) {
|
||||
scope2 = rule2[j][1];
|
||||
|
||||
if (scope1 == scope2) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (bemMode && withoutModifiers(scope1) == withoutModifiers(scope2)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function withoutModifiers(scope) {
|
||||
return scope.replace(MODIFIER_PATTERN, '');
|
||||
}
|
||||
|
||||
module.exports = rulesOverlap;
|
36
node_modules/clean-css/lib/optimizer/level-2/specificities-overlap.js
generated
vendored
Normal file
36
node_modules/clean-css/lib/optimizer/level-2/specificities-overlap.js
generated
vendored
Normal file
@ -0,0 +1,36 @@
|
||||
var specificity = require('./specificity');
|
||||
|
||||
function specificitiesOverlap(selector1, selector2, cache) {
|
||||
var specificity1;
|
||||
var specificity2;
|
||||
var i, l;
|
||||
var j, m;
|
||||
|
||||
for (i = 0, l = selector1.length; i < l; i++) {
|
||||
specificity1 = findSpecificity(selector1[i][1], cache);
|
||||
|
||||
for (j = 0, m = selector2.length; j < m; j++) {
|
||||
specificity2 = findSpecificity(selector2[j][1], cache);
|
||||
|
||||
if (specificity1[0] === specificity2[0]
|
||||
&& specificity1[1] === specificity2[1]
|
||||
&& specificity1[2] === specificity2[2]) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function findSpecificity(selector, cache) {
|
||||
var value;
|
||||
|
||||
if (!(selector in cache)) {
|
||||
cache[selector] = value = specificity(selector);
|
||||
}
|
||||
|
||||
return value || cache[selector];
|
||||
}
|
||||
|
||||
module.exports = specificitiesOverlap;
|
77
node_modules/clean-css/lib/optimizer/level-2/specificity.js
generated
vendored
Normal file
77
node_modules/clean-css/lib/optimizer/level-2/specificity.js
generated
vendored
Normal file
@ -0,0 +1,77 @@
|
||||
var Marker = require('../../tokenizer/marker');
|
||||
|
||||
var Selector = {
|
||||
ADJACENT_SIBLING: '+',
|
||||
DESCENDANT: '>',
|
||||
DOT: '.',
|
||||
HASH: '#',
|
||||
NON_ADJACENT_SIBLING: '~',
|
||||
PSEUDO: ':'
|
||||
};
|
||||
|
||||
var LETTER_PATTERN = /[a-zA-Z]/;
|
||||
var NOT_PREFIX = ':not(';
|
||||
var SEPARATOR_PATTERN = /[\s,(>~+]/;
|
||||
|
||||
function specificity(selector) {
|
||||
var result = [0, 0, 0];
|
||||
var character;
|
||||
var isEscaped;
|
||||
var isSingleQuoted;
|
||||
var isDoubleQuoted;
|
||||
var roundBracketLevel = 0;
|
||||
var couldIntroduceNewTypeSelector;
|
||||
var withinNotPseudoClass = false;
|
||||
var wasPseudoClass = false;
|
||||
var i, l;
|
||||
|
||||
for (i = 0, l = selector.length; i < l; i++) {
|
||||
character = selector[i];
|
||||
|
||||
if (isEscaped) {
|
||||
// noop
|
||||
} else if (character == Marker.SINGLE_QUOTE && !isDoubleQuoted && !isSingleQuoted) {
|
||||
isSingleQuoted = true;
|
||||
} else if (character == Marker.SINGLE_QUOTE && !isDoubleQuoted && isSingleQuoted) {
|
||||
isSingleQuoted = false;
|
||||
} else if (character == Marker.DOUBLE_QUOTE && !isDoubleQuoted && !isSingleQuoted) {
|
||||
isDoubleQuoted = true;
|
||||
} else if (character == Marker.DOUBLE_QUOTE && isDoubleQuoted && !isSingleQuoted) {
|
||||
isDoubleQuoted = false;
|
||||
} else if (isSingleQuoted || isDoubleQuoted) {
|
||||
continue;
|
||||
} else if (roundBracketLevel > 0 && !withinNotPseudoClass) {
|
||||
// noop
|
||||
} else if (character == Marker.OPEN_ROUND_BRACKET) {
|
||||
roundBracketLevel++;
|
||||
} else if (character == Marker.CLOSE_ROUND_BRACKET && roundBracketLevel == 1) {
|
||||
roundBracketLevel--;
|
||||
withinNotPseudoClass = false;
|
||||
} else if (character == Marker.CLOSE_ROUND_BRACKET) {
|
||||
roundBracketLevel--;
|
||||
} else if (character == Selector.HASH) {
|
||||
result[0]++;
|
||||
} else if (character == Selector.DOT || character == Marker.OPEN_SQUARE_BRACKET) {
|
||||
result[1]++;
|
||||
} else if (character == Selector.PSEUDO && !wasPseudoClass && !isNotPseudoClass(selector, i)) {
|
||||
result[1]++;
|
||||
withinNotPseudoClass = false;
|
||||
} else if (character == Selector.PSEUDO) {
|
||||
withinNotPseudoClass = true;
|
||||
} else if ((i === 0 || couldIntroduceNewTypeSelector) && LETTER_PATTERN.test(character)) {
|
||||
result[2]++;
|
||||
}
|
||||
|
||||
isEscaped = character == Marker.BACK_SLASH;
|
||||
wasPseudoClass = character == Selector.PSEUDO;
|
||||
couldIntroduceNewTypeSelector = !isEscaped && SEPARATOR_PATTERN.test(character);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
function isNotPseudoClass(selector, index) {
|
||||
return selector.indexOf(NOT_PREFIX, index) === index;
|
||||
}
|
||||
|
||||
module.exports = specificity;
|
21
node_modules/clean-css/lib/optimizer/level-2/tidy-rule-duplicates.js
generated
vendored
Normal file
21
node_modules/clean-css/lib/optimizer/level-2/tidy-rule-duplicates.js
generated
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
function ruleSorter(s1, s2) {
|
||||
return s1[1] > s2[1] ? 1 : -1;
|
||||
}
|
||||
|
||||
function tidyRuleDuplicates(rules) {
|
||||
var list = [];
|
||||
var repeated = [];
|
||||
|
||||
for (var i = 0, l = rules.length; i < l; i++) {
|
||||
var rule = rules[i];
|
||||
|
||||
if (repeated.indexOf(rule[1]) == -1) {
|
||||
repeated.push(rule[1]);
|
||||
list.push(rule);
|
||||
}
|
||||
}
|
||||
|
||||
return list.sort(ruleSorter);
|
||||
}
|
||||
|
||||
module.exports = tidyRuleDuplicates;
|
Reference in New Issue
Block a user