75 lines
1.6 KiB
JavaScript
75 lines
1.6 KiB
JavaScript
'use strict';
|
|
|
|
var walkers = require('./ast-walkers'),
|
|
matchNode = require('./match-node'),
|
|
Collector = require('./collector');
|
|
|
|
var select = exports;
|
|
|
|
|
|
select.selectors = function (selectors, ast) {
|
|
var collect = Collector();
|
|
selectors.selectors.forEach(function (ruleSet) {
|
|
collect(select.ruleSet(ruleSet, ast));
|
|
});
|
|
return collect.result;
|
|
};
|
|
|
|
|
|
select.ruleSet = function (ruleSet, ast) {
|
|
return select.rule(ruleSet.rule, ast);
|
|
};
|
|
|
|
|
|
select.rule = function (rule, ast) {
|
|
var collect = Collector();
|
|
search(rule, ast, 0, null);
|
|
return collect.result;
|
|
|
|
function search (rule, node, nodeIndex, parent) {
|
|
({
|
|
// `undefined` is the operator on the top rule selector.
|
|
undefined: walkers.topScan,
|
|
// `null` stands for the descendant combinator.
|
|
null: walkers.descendant,
|
|
'>': walkers.child,
|
|
'+': walkers.adjacentSibling,
|
|
'~': walkers.generalSibling
|
|
})[rule.nestingOperator](
|
|
node,
|
|
nodeIndex,
|
|
parent,
|
|
searchOpts({ iterator: match.bind(null, rule) }, rule)
|
|
);
|
|
}
|
|
|
|
function match (rule, node, nodeIndex, parent, props) {
|
|
if (matchNode.apply(this, arguments)) {
|
|
if (rule.rule) {
|
|
search(rule.rule, node, nodeIndex, parent);
|
|
}
|
|
else {
|
|
collect(node);
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
|
|
function searchOpts (opts, rule) {
|
|
rule.pseudos && rule.pseudos.forEach(function (pseudo) {
|
|
switch (pseudo.name) {
|
|
case 'nth-last-of-type':
|
|
case 'last-of-type':
|
|
case 'only-of-type':
|
|
opts.typeCount = true;
|
|
|
|
case 'nth-of-type':
|
|
case 'first-of-type':
|
|
opts.typeIndex = true;
|
|
}
|
|
});
|
|
|
|
return opts;
|
|
}
|