scancss
Version:
A robust CSS stylesheet statistics collector and analyzer
135 lines (97 loc) • 4.56 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.handleSelector = handleSelector;
var _postcssSelectorParser = require('postcss-selector-parser');
var _postcssSelectorParser2 = _interopRequireDefault(_postcssSelectorParser);
var _cssPseudoClasses = require('../../constants/cssPseudoClasses');
var _cssPseudoElements = require('../../constants/cssPseudoElements');
var _rePrefixedString = require('../../constants/rePrefixedString');
var _reLeadingColons = require('../../constants/reLeadingColons');
var _calculateSpecificity = require('../../calculators/calculateSpecificity');
var _compareSpecificities = require('../../calculators/compareSpecificities');
var _countUsage = require('../../calculators/countUsage');
var _mergeSpecificities = require('../../converters/mergeSpecificities');
var _handleVendorPrefix = require('../handleVendorPrefix');
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
let processedSelectors = null;
function selectorsProcessor(selectors) {
processedSelectors = selectors;
}
const selectorParser = (0, _postcssSelectorParser2.default)(selectorsProcessor);
function handlePseudoSelector(selectorObj, report) {
const pseudoName = selectorObj.value.replace(_reLeadingColons.reLeadingColons, '');
if (_rePrefixedString.rePrefixedString.test(pseudoName)) {
(0, _handleVendorPrefix.handleVendorPrefix)(pseudoName, report);
}
if (_cssPseudoElements.cssPseudoElements.some(name => pseudoName === name)) {
(0, _countUsage.countUsage)('pseudoElement', report.selectors.baseUsage);
(0, _countUsage.countUsage)(selectorObj.value.replace(_reLeadingColons.reLeadingColons, '::'), report.selectors.pseudoElementsUsage);
} else if (_cssPseudoClasses.cssPseudoClasses.some(name => pseudoName === name)) {
(0, _countUsage.countUsage)('pseudoClass', report.selectors.baseUsage);
(0, _countUsage.countUsage)(selectorObj.value.replace(_reLeadingColons.reLeadingColons, ':'), report.selectors.pseudoClassesUsage);
}
}
const combinatorsMap = {
'+': 'adjacentSibling',
'>': 'child',
' ': 'descendant',
'~': 'generalSibling'
};
function isAllowedSelectorType(type) {
return ['attribute', 'class', 'id', 'pseudo', 'tag', 'universal'].includes(type);
}
function countSelectors(selectors, report, options) {
let tmpSpecificity = [0, 0, 0];
let baseSelectorsWithoutCombinators = 0;
selectors.walk(selector => {
if (selector.type === 'combinator') {
report.selectors.combinators.total++;
report.selectors.combinators[combinatorsMap[selector.value]]++;
}
if (isAllowedSelectorType(selector.type)) {
baseSelectorsWithoutCombinators++;
if (selector.type === 'pseudo') {
handlePseudoSelector(selector, report);
} else {
(0, _countUsage.countUsage)(selector.type, report.selectors.baseUsage);
if (selector.type === 'attribute' && options.attributesUsage) {
(0, _countUsage.countUsage)(String(selector), report.selectors.attributesUsage);
}
}
const specificity = (0, _calculateSpecificity.calculateSpecificity)(selector);
tmpSpecificity = (0, _mergeSpecificities.mergeSpecificities)(tmpSpecificity, specificity);
report.selectors.specificity.total = (0, _mergeSpecificities.mergeSpecificities)(report.selectors.specificity.total, specificity);
}
});
if (options.specificityGraph) {
report.selectors.specificity.graphData.push(tmpSpecificity);
}
report.selectors.specificity.highest10.push({
selector: String(selectors),
specificity: tmpSpecificity
});
report.selectors.specificity.highest10 = report.selectors.specificity.highest10.sort((a, b) => (0, _compareSpecificities.compareSpecificities)(a.specificity, b.specificity));
if (report.selectors.specificity.highest10.length > 10) {
report.selectors.specificity.highest10.pop();
}
if (baseSelectorsWithoutCombinators > options.selectorComplexityThreshold) {
report.selectors.complex++;
}
}
function handleSelector(selector, report, options) {
report.selectors.total++;
(0, _countUsage.countUsage)(selector, report.selectors.usage);
const selectorByteLength = Buffer.byteLength(selector, 'utf8');
report.selectors.length.total += selectorByteLength;
if (report.selectors.length.longest < selectorByteLength) {
report.selectors.length.longest = selectorByteLength;
report.selectors.length.longestSelector = selector;
}
selectorParser.processSync(selector);
/* istanbul ignore else */
if (processedSelectors !== null) {
countSelectors(processedSelectors, report, options);
}
}