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.
101 lines
2.7 KiB
101 lines
2.7 KiB
'use strict'; |
|
|
|
const cssTree = require('css-tree'); |
|
const specificity = require('./specificity.cjs'); |
|
|
|
const nonFreezePseudoElements = new Set([ |
|
'first-letter', |
|
'first-line', |
|
'after', |
|
'before' |
|
]); |
|
const nonFreezePseudoClasses = new Set([ |
|
'link', |
|
'visited', |
|
'hover', |
|
'active', |
|
'first-letter', |
|
'first-line', |
|
'after', |
|
'before' |
|
]); |
|
|
|
function processSelector(node, usageData) { |
|
const pseudos = new Set(); |
|
|
|
node.prelude.children.forEach(function(simpleSelector) { |
|
let tagName = '*'; |
|
let scope = 0; |
|
|
|
simpleSelector.children.forEach(function(node) { |
|
switch (node.type) { |
|
case 'ClassSelector': |
|
if (usageData && usageData.scopes) { |
|
const classScope = usageData.scopes[node.name] || 0; |
|
|
|
if (scope !== 0 && classScope !== scope) { |
|
throw new Error('Selector can\'t has classes from different scopes: ' + cssTree.generate(simpleSelector)); |
|
} |
|
|
|
scope = classScope; |
|
} |
|
|
|
break; |
|
|
|
case 'PseudoClassSelector': { |
|
const name = node.name.toLowerCase(); |
|
|
|
if (!nonFreezePseudoClasses.has(name)) { |
|
pseudos.add(`:${name}`); |
|
} |
|
|
|
break; |
|
} |
|
|
|
case 'PseudoElementSelector': { |
|
const name = node.name.toLowerCase(); |
|
|
|
if (!nonFreezePseudoElements.has(name)) { |
|
pseudos.add(`::${name}`); |
|
} |
|
|
|
break; |
|
} |
|
|
|
case 'TypeSelector': |
|
tagName = node.name.toLowerCase(); |
|
break; |
|
|
|
case 'AttributeSelector': |
|
if (node.flags) { |
|
pseudos.add(`[${node.flags.toLowerCase()}]`); |
|
} |
|
|
|
break; |
|
|
|
case 'Combinator': |
|
tagName = '*'; |
|
break; |
|
} |
|
}); |
|
|
|
simpleSelector.compareMarker = specificity(simpleSelector).toString(); |
|
simpleSelector.id = null; // pre-init property to avoid multiple hidden class |
|
simpleSelector.id = cssTree.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 = pseudos.size > 0 |
|
? [...pseudos].sort().join(',') |
|
: false; |
|
} |
|
|
|
module.exports = processSelector;
|
|
|