You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
95 lines
2.9 KiB
95 lines
2.9 KiB
1 month ago
|
var generate = require('css-tree').generate;
|
||
|
var specificity = require('./specificity');
|
||
|
|
||
|
var nonFreezePseudoElements = {
|
||
|
'first-letter': true,
|
||
|
'first-line': true,
|
||
|
'after': true,
|
||
|
'before': true
|
||
|
};
|
||
|
var nonFreezePseudoClasses = {
|
||
|
'link': true,
|
||
|
'visited': true,
|
||
|
'hover': true,
|
||
|
'active': true,
|
||
|
'first-letter': true,
|
||
|
'first-line': true,
|
||
|
'after': true,
|
||
|
'before': true
|
||
|
};
|
||
|
|
||
|
module.exports = function freeze(node, usageData) {
|
||
|
var pseudos = Object.create(null);
|
||
|
var hasPseudo = false;
|
||
|
|
||
|
node.prelude.children.each(function(simpleSelector) {
|
||
|
var tagName = '*';
|
||
|
var scope = 0;
|
||
|
|
||
|
simpleSelector.children.each(function(node) {
|
||
|
switch (node.type) {
|
||
|
case 'ClassSelector':
|
||
|
if (usageData && usageData.scopes) {
|
||
|
var classScope = usageData.scopes[node.name] || 0;
|
||
|
|
||
|
if (scope !== 0 && classScope !== scope) {
|
||
|
throw new Error('Selector can\'t has classes from different scopes: ' + generate(simpleSelector));
|
||
|
}
|
||
|
|
||
|
scope = classScope;
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case 'PseudoClassSelector':
|
||
|
var name = node.name.toLowerCase();
|
||
|
|
||
|
if (!nonFreezePseudoClasses.hasOwnProperty(name)) {
|
||
|
pseudos[':' + name] = true;
|
||
|
hasPseudo = true;
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case 'PseudoElementSelector':
|
||
|
var name = node.name.toLowerCase();
|
||
|
|
||
|
if (!nonFreezePseudoElements.hasOwnProperty(name)) {
|
||
|
pseudos['::' + name] = true;
|
||
|
hasPseudo = true;
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case 'TypeSelector':
|
||
|
tagName = node.name.toLowerCase();
|
||
|
break;
|
||
|
|
||
|
case 'AttributeSelector':
|
||
|
if (node.flags) {
|
||
|
pseudos['[' + node.flags.toLowerCase() + ']'] = true;
|
||
|
hasPseudo = true;
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case 'WhiteSpace':
|
||
|
case 'Combinator':
|
||
|
tagName = '*';
|
||
|
break;
|
||
|
}
|
||
|
});
|
||
|
|
||
|
simpleSelector.compareMarker = specificity(simpleSelector).toString();
|
||
|
simpleSelector.id = null; // pre-init property to avoid multiple hidden class
|
||
|
simpleSelector.id = generate(simpleSelector);
|
||
|
|
||
|
if (scope) {
|
||
|
simpleSelector.compareMarker += ':' + scope;
|
||
|
}
|
||
|
|
||
|
if (tagName !== '*') {
|
||
|
simpleSelector.compareMarker += ',' + tagName;
|
||
|
}
|
||
|
});
|
||
|
|
||
|
// add property to all rule nodes to avoid multiple hidden class
|
||
|
node.pseudoSignature = hasPseudo && Object.keys(pseudos).sort().join(',');
|
||
|
};
|