unist-util-select
Advanced tools
Comparing version 1.1.0 to 1.2.0
'use strict'; | ||
var parseSelector = require('./lib/selector')(), | ||
var parseSelector = require('./lib/selector'), | ||
select = require('./lib/select'); | ||
@@ -5,0 +5,0 @@ |
'use strict'; | ||
var walkers = require('./ast-walkers'), | ||
matchNode = require('./match-node'), | ||
Collector = require('./collector'); | ||
var select = exports; | ||
select.selectors = function (selector, ast) { | ||
var result = []; | ||
selector.selectors.forEach(function (selector) { | ||
append(result, select.ruleSet(selector, ast)); | ||
select.selectors = function (selectors, ast) { | ||
var collect = Collector(); | ||
selectors.selectors.forEach(function (ruleSet) { | ||
collect(select.ruleSet(ruleSet, ast)); | ||
}); | ||
return result; | ||
return collect.result; | ||
}; | ||
select.ruleSet = function (selector, ast) { | ||
return select.rule(selector.rule, ast); | ||
select.ruleSet = function (ruleSet, ast) { | ||
return select.rule(ruleSet.rule, ast); | ||
}; | ||
select.rule = function (selector, ast) { | ||
var result = []; | ||
select.rule = function (rule, ast) { | ||
var collect = Collector(); | ||
search(rule, ast, 0, null); | ||
return collect.result; | ||
switch (selector.nestingOperator) { | ||
case null: | ||
case undefined: | ||
case '>': | ||
walk(ast); | ||
break; | ||
case '+': | ||
if (ast.children && ast.children.length) { | ||
walk(ast.children[0], ast); | ||
} | ||
break; | ||
case '~': | ||
(ast.children || []).forEach(function (node) { | ||
walk(node, ast); | ||
}); | ||
break; | ||
default: | ||
throw Error('Undefined nesting operator: ' + selector.nestingOperator); | ||
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, match.bind(null, rule) | ||
); | ||
} | ||
return result; | ||
function walk (node, parent) { | ||
if (matches(selector, node)) { | ||
if (!selector.rule) { | ||
append(result, [node]); | ||
function match (rule, node, nodeIndex, parent) { | ||
if (matchNode(rule, node, nodeIndex, parent)) { | ||
if (rule.rule) { | ||
search(rule.rule, node, nodeIndex, parent); | ||
} | ||
else if (!selector.rule.nestingOperator || | ||
selector.rule.nestingOperator == '>') { | ||
if (node.children) { | ||
node.children.forEach(function (childNode) { | ||
append(result, select.rule(selector.rule, childNode)); | ||
}); | ||
} | ||
} | ||
else { | ||
if (parent) { | ||
append(result, select.rule(selector.rule, { | ||
children: parent.children.slice(parent.children.indexOf(node) + 1) | ||
})); | ||
} | ||
collect(node); | ||
} | ||
} | ||
if (!selector.nestingOperator && node.children) { | ||
node.children.forEach(function (child) { | ||
walk(child, node); | ||
}); | ||
} | ||
} | ||
}; | ||
// True if node matches head of selector rule. | ||
function matches (rule, node) { | ||
var match = true; | ||
// Match type. | ||
match = match && (!rule.tagName || rule.tagName == '*' || | ||
rule.tagName == node.type); | ||
// Match attributes. | ||
match = match && (rule.attrs || []).every(function (attr) { | ||
switch (attr.operator) { | ||
case undefined: | ||
return attr.name in node; | ||
case '=': | ||
// First, check for special values. | ||
switch (attr.value) { | ||
case 'null': | ||
if (attr.name in node && node[attr.name] == null) return true; | ||
break; | ||
case 'true': | ||
if (node[attr.name] === true) return true; | ||
break; | ||
case 'false': | ||
if (node[attr.name] === false) return true; | ||
break; | ||
} | ||
return node[attr.name] == attr.value; | ||
case '^=': | ||
return typeof node[attr.name] == 'string' && | ||
node[attr.name].slice(0, attr.value.length) == attr.value; | ||
case '*=': | ||
return typeof node[attr.name] == 'string' && | ||
node[attr.name].indexOf(attr.value) >= 0; | ||
case '$=': | ||
return typeof node[attr.name] == 'string' && | ||
node[attr.name].slice(-attr.value.length) == attr.value; | ||
default: | ||
throw Error('Undefined attribute operator: ' + attr.operator); | ||
} | ||
}); | ||
// Match pseudo classes. | ||
match = match && (rule.pseudos || []).every(function (pseudo) { | ||
switch (pseudo.name) { | ||
case 'not': | ||
return !matches(pseudo.value.rule, node); | ||
default: | ||
throw Error('Undefined pseudo-class: ' + pseudo.name); | ||
} | ||
}); | ||
return match; | ||
} | ||
function append (array, elements) { | ||
elements.forEach(function (el) { | ||
if (array.indexOf(el) < 0) { | ||
array.push(el); | ||
} | ||
}); | ||
} |
'use strict'; | ||
var Parser = require('css-selector-parser').CssSelectorParser; | ||
var Parser = require('css-selector-parser').CssSelectorParser, | ||
nthCheck = require('nth-check'); | ||
module.exports = function SelectorParser () { | ||
module.exports = function parseSelector (selector) { | ||
var parser = new Parser; | ||
@@ -11,3 +12,39 @@ parser.registerNestingOperators('>', '+', '~'); | ||
parser.registerSelectorPseudos('not'); | ||
return parser.parse.bind(parser); | ||
return compileNthChecks(parser.parse(selector)); | ||
}; | ||
function compileNthChecks (ast) { | ||
if (ast == null) { | ||
return ast; | ||
} | ||
switch (ast.type) { | ||
case 'selectors': | ||
ast.selectors.forEach(compileNthChecks); | ||
break; | ||
case 'ruleSet': | ||
compileNthChecks(ast.rule); | ||
break; | ||
case 'rule': | ||
if (ast.pseudos) { | ||
ast.pseudos.forEach(function (pseudo) { | ||
if (pseudo.name == 'nth-child' || pseudo.name == 'nth-last-child') { | ||
pseudo.value = nthCheck(pseudo.value); | ||
pseudo.valueType = 'function'; | ||
} | ||
}); | ||
} | ||
if (ast.rule) { | ||
compileNthChecks(ast.rule); | ||
} | ||
break; | ||
default: | ||
throw Error('Undefined AST node: ' + ast.type); | ||
} | ||
return ast; | ||
} |
{ | ||
"name": "unist-util-select", | ||
"version": "1.1.0", | ||
"version": "1.2.0", | ||
"description": "Select unist nodes using css-like selectors", | ||
@@ -44,3 +44,4 @@ "author": "Eugene Sharygin <eush77@gmail.com>", | ||
"css-selector-parser": "^1.1.0", | ||
"debug": "^2.2.0" | ||
"debug": "^2.2.0", | ||
"nth-check": "^1.0.1" | ||
}, | ||
@@ -47,0 +48,0 @@ "devDependencies": { |
@@ -62,2 +62,15 @@ [![npm](https://nodei.co/npm/unist-util-select.png)](https://npmjs.com/package/unist-util-select) | ||
- [x] Ends with: `[value$="suffix"]` | ||
- [ ] Structural pseudo-classes: `paragraph:first-of-type` | ||
- [x] `:root` | ||
- [x] `:nth-child(2n+1)` | ||
- [x] `:nth-last-child(2n+1)` | ||
- [ ] `:nth-of-type(2n+1)` | ||
- [ ] `:nth-last-of-type(2n+1)` | ||
- [x] `:first-child` | ||
- [x] `:last-child` | ||
- [ ] `:first-of-type` | ||
- [ ] `:last-of-type` | ||
- [x] `:only-child` | ||
- [ ] `:only-of-type` | ||
- [ ] `:empty` | ||
- [x] Negation pseudo-class: `*:not(paragraph)` | ||
@@ -64,0 +77,0 @@ |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
11134
9
219
92
3
1
+ Addednth-check@^1.0.1
+ Addedboolbase@1.0.0(transitive)
+ Addednth-check@1.0.2(transitive)