| var attributes = require("./attributes.js"); |
| var Pseudos = require("./pseudos"); |
| |
| /* |
| all available rules |
| */ |
| module.exports = { |
| __proto__: null, |
| |
| attribute: attributes.compile, |
| pseudo: Pseudos.compile, |
| |
| //tags |
| tag: function(next, data, options) { |
| var name = data.name; |
| var adapter = options.adapter; |
| |
| return function tag(elem) { |
| return adapter.getName(elem) === name && next(elem); |
| }; |
| }, |
| |
| //traversal |
| descendant: function(next, data, options) { |
| // eslint-disable-next-line no-undef |
| var isFalseCache = typeof WeakSet !== "undefined" ? new WeakSet() : null; |
| var adapter = options.adapter; |
| |
| return function descendant(elem) { |
| var found = false; |
| |
| while (!found && (elem = adapter.getParent(elem))) { |
| if (!isFalseCache || !isFalseCache.has(elem)) { |
| found = next(elem); |
| if (!found && isFalseCache) { |
| isFalseCache.add(elem); |
| } |
| } |
| } |
| |
| return found; |
| }; |
| }, |
| _flexibleDescendant: function(next, data, options) { |
| var adapter = options.adapter; |
| |
| // Include element itself, only used while querying an array |
| return function descendant(elem) { |
| var found = next(elem); |
| |
| while (!found && (elem = adapter.getParent(elem))) { |
| found = next(elem); |
| } |
| |
| return found; |
| }; |
| }, |
| parent: function(next, data, options) { |
| if (options && options.strict) { |
| throw new Error("Parent selector isn't part of CSS3"); |
| } |
| |
| var adapter = options.adapter; |
| |
| return function parent(elem) { |
| return adapter.getChildren(elem).some(test); |
| }; |
| |
| function test(elem) { |
| return adapter.isTag(elem) && next(elem); |
| } |
| }, |
| child: function(next, data, options) { |
| var adapter = options.adapter; |
| |
| return function child(elem) { |
| var parent = adapter.getParent(elem); |
| return !!parent && next(parent); |
| }; |
| }, |
| sibling: function(next, data, options) { |
| var adapter = options.adapter; |
| |
| return function sibling(elem) { |
| var siblings = adapter.getSiblings(elem); |
| |
| for (var i = 0; i < siblings.length; i++) { |
| if (adapter.isTag(siblings[i])) { |
| if (siblings[i] === elem) break; |
| if (next(siblings[i])) return true; |
| } |
| } |
| |
| return false; |
| }; |
| }, |
| adjacent: function(next, data, options) { |
| var adapter = options.adapter; |
| |
| return function adjacent(elem) { |
| var siblings = adapter.getSiblings(elem), |
| lastElement; |
| |
| for (var i = 0; i < siblings.length; i++) { |
| if (adapter.isTag(siblings[i])) { |
| if (siblings[i] === elem) break; |
| lastElement = siblings[i]; |
| } |
| } |
| |
| return !!lastElement && next(lastElement); |
| }; |
| }, |
| universal: function(next) { |
| return next; |
| } |
| }; |