Spaces:
Running
Running
CRISPRTool
/
igv_component
/node_modules
/clean-css
/lib
/optimizer
/level-2
/remove-unused-at-rules.js
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; | |