diff options
Diffstat (limited to 'bin/wiki/ImportarDesdeURL/node_modules/css-select/lib/compile.js')
-rw-r--r-- | bin/wiki/ImportarDesdeURL/node_modules/css-select/lib/compile.js | 192 |
1 files changed, 192 insertions, 0 deletions
diff --git a/bin/wiki/ImportarDesdeURL/node_modules/css-select/lib/compile.js b/bin/wiki/ImportarDesdeURL/node_modules/css-select/lib/compile.js new file mode 100644 index 00000000..91ac5925 --- /dev/null +++ b/bin/wiki/ImportarDesdeURL/node_modules/css-select/lib/compile.js @@ -0,0 +1,192 @@ +/* + compiles a selector to an executable function +*/ + +module.exports = compile; +module.exports.compileUnsafe = compileUnsafe; +module.exports.compileToken = compileToken; + +var parse = require("css-what"), + DomUtils = require("domutils"), + isTag = DomUtils.isTag, + Rules = require("./general.js"), + sortRules = require("./sort.js"), + BaseFuncs = require("boolbase"), + trueFunc = BaseFuncs.trueFunc, + falseFunc = BaseFuncs.falseFunc, + procedure = require("./procedure.json"); + +function compile(selector, options, context){ + var next = compileUnsafe(selector, options, context); + return wrap(next); +} + +function wrap(next){ + return function base(elem){ + return isTag(elem) && next(elem); + }; +} + +function compileUnsafe(selector, options, context){ + var token = parse(selector, options); + return compileToken(token, options, context); +} + +function includesScopePseudo(t){ + return t.type === "pseudo" && ( + t.name === "scope" || ( + Array.isArray(t.data) && + t.data.some(function(data){ + return data.some(includesScopePseudo); + }) + ) + ); +} + +var DESCENDANT_TOKEN = {type: "descendant"}, + SCOPE_TOKEN = {type: "pseudo", name: "scope"}, + PLACEHOLDER_ELEMENT = {}, + getParent = DomUtils.getParent; + +//CSS 4 Spec (Draft): 3.3.1. Absolutizing a Scope-relative Selector +//http://www.w3.org/TR/selectors4/#absolutizing +function absolutize(token, context){ + //TODO better check if context is document + var hasContext = !!context && !!context.length && context.every(function(e){ + return e === PLACEHOLDER_ELEMENT || !!getParent(e); + }); + + + token.forEach(function(t){ + if(t.length > 0 && isTraversal(t[0]) && t[0].type !== "descendant"){ + //don't return in else branch + } else if(hasContext && !includesScopePseudo(t)){ + t.unshift(DESCENDANT_TOKEN); + } else { + return; + } + + t.unshift(SCOPE_TOKEN); + }); +} + +function compileToken(token, options, context){ + token = token.filter(function(t){ return t.length > 0; }); + + token.forEach(sortRules); + + var isArrayContext = Array.isArray(context); + + context = (options && options.context) || context; + + if(context && !isArrayContext) context = [context]; + + absolutize(token, context); + + return token + .map(function(rules){ return compileRules(rules, options, context, isArrayContext); }) + .reduce(reduceRules, falseFunc); +} + +function isTraversal(t){ + return procedure[t.type] < 0; +} + +function compileRules(rules, options, context, isArrayContext){ + var acceptSelf = (isArrayContext && rules[0].name === "scope" && rules[1].type === "descendant"); + return rules.reduce(function(func, rule, index){ + if(func === falseFunc) return func; + return Rules[rule.type](func, rule, options, context, acceptSelf && index === 1); + }, options && options.rootFunc || trueFunc); +} + +function reduceRules(a, b){ + if(b === falseFunc || a === trueFunc){ + return a; + } + if(a === falseFunc || b === trueFunc){ + return b; + } + + return function combine(elem){ + return a(elem) || b(elem); + }; +} + +//:not, :has and :matches have to compile selectors +//doing this in lib/pseudos.js would lead to circular dependencies, +//so we add them here + +var Pseudos = require("./pseudos.js"), + filters = Pseudos.filters, + existsOne = DomUtils.existsOne, + isTag = DomUtils.isTag, + getChildren = DomUtils.getChildren; + + +function containsTraversal(t){ + return t.some(isTraversal); +} + +filters.not = function(next, token, options, context){ + var opts = { + xmlMode: !!(options && options.xmlMode), + strict: !!(options && options.strict) + }; + + if(opts.strict){ + if(token.length > 1 || token.some(containsTraversal)){ + throw new SyntaxError("complex selectors in :not aren't allowed in strict mode"); + } + } + + var func = compileToken(token, opts, context); + + if(func === falseFunc) return next; + if(func === trueFunc) return falseFunc; + + return function(elem){ + return !func(elem) && next(elem); + }; +}; + +filters.has = function(next, token, options){ + var opts = { + xmlMode: !!(options && options.xmlMode), + strict: !!(options && options.strict) + }; + + //FIXME: Uses an array as a pointer to the current element (side effects) + var context = token.some(containsTraversal) ? [PLACEHOLDER_ELEMENT] : null; + + var func = compileToken(token, opts, context); + + if(func === falseFunc) return falseFunc; + if(func === trueFunc) return function(elem){ + return getChildren(elem).some(isTag) && next(elem); + }; + + func = wrap(func); + + if(context){ + return function has(elem){ + return next(elem) && ( + (context[0] = elem), existsOne(func, getChildren(elem)) + ); + }; + } + + return function has(elem){ + return next(elem) && existsOne(func, getChildren(elem)); + }; +}; + +filters.matches = function(next, token, options, context){ + var opts = { + xmlMode: !!(options && options.xmlMode), + strict: !!(options && options.strict), + rootFunc: next + }; + + return compileToken(token, opts, context); +}; |