| "use strict"; |
| var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) { |
| if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) { |
| if (ar || !(i in from)) { |
| if (!ar) ar = Array.prototype.slice.call(from, 0, i); |
| ar[i] = from[i]; |
| } |
| } |
| return to.concat(ar || Array.prototype.slice.call(from)); |
| }; |
| Object.defineProperty(exports, "__esModule", { value: true }); |
| exports.isTraversal = void 0; |
| var reName = /^[^\\#]?(?:\\(?:[\da-f]{1,6}\s?|.)|[\w\-\u00b0-\uFFFF])+/; |
| var reEscape = /\\([\da-f]{1,6}\s?|(\s)|.)/gi; |
| var actionTypes = new Map([ |
| ["~", "element"], |
| ["^", "start"], |
| ["$", "end"], |
| ["*", "any"], |
| ["!", "not"], |
| ["|", "hyphen"], |
| ]); |
| var Traversals = { |
| ">": "child", |
| "<": "parent", |
| "~": "sibling", |
| "+": "adjacent", |
| }; |
| var attribSelectors = { |
| "#": ["id", "equals"], |
| ".": ["class", "element"], |
| }; |
| // Pseudos, whose data property is parsed as well. |
| var unpackPseudos = new Set([ |
| "has", |
| "not", |
| "matches", |
| "is", |
| "where", |
| "host", |
| "host-context", |
| ]); |
| var traversalNames = new Set(__spreadArray([ |
| "descendant" |
| ], Object.keys(Traversals).map(function (k) { return Traversals[k]; }), true)); |
| /** |
| * Attributes that are case-insensitive in HTML. |
| * |
| * @private |
| * @see https://html.spec.whatwg.org/multipage/semantics-other.html#case-sensitivity-of-selectors |
| */ |
| var caseInsensitiveAttributes = new Set([ |
| "accept", |
| "accept-charset", |
| "align", |
| "alink", |
| "axis", |
| "bgcolor", |
| "charset", |
| "checked", |
| "clear", |
| "codetype", |
| "color", |
| "compact", |
| "declare", |
| "defer", |
| "dir", |
| "direction", |
| "disabled", |
| "enctype", |
| "face", |
| "frame", |
| "hreflang", |
| "http-equiv", |
| "lang", |
| "language", |
| "link", |
| "media", |
| "method", |
| "multiple", |
| "nohref", |
| "noresize", |
| "noshade", |
| "nowrap", |
| "readonly", |
| "rel", |
| "rev", |
| "rules", |
| "scope", |
| "scrolling", |
| "selected", |
| "shape", |
| "target", |
| "text", |
| "type", |
| "valign", |
| "valuetype", |
| "vlink", |
| ]); |
| /** |
| * Checks whether a specific selector is a traversal. |
| * This is useful eg. in swapping the order of elements that |
| * are not traversals. |
| * |
| * @param selector Selector to check. |
| */ |
| function isTraversal(selector) { |
| return traversalNames.has(selector.type); |
| } |
| exports.isTraversal = isTraversal; |
| var stripQuotesFromPseudos = new Set(["contains", "icontains"]); |
| var quotes = new Set(['"', "'"]); |
| // Unescape function taken from https://github.com/jquery/sizzle/blob/master/src/sizzle.js#L152 |
| function funescape(_, escaped, escapedWhitespace) { |
| var high = parseInt(escaped, 16) - 0x10000; |
| // NaN means non-codepoint |
| return high !== high || escapedWhitespace |
| ? escaped |
| : high < 0 |
| ? // BMP codepoint |
| String.fromCharCode(high + 0x10000) |
| : // Supplemental Plane codepoint (surrogate pair) |
| String.fromCharCode((high >> 10) | 0xd800, (high & 0x3ff) | 0xdc00); |
| } |
| function unescapeCSS(str) { |
| return str.replace(reEscape, funescape); |
| } |
| function isWhitespace(c) { |
| return c === " " || c === "\n" || c === "\t" || c === "\f" || c === "\r"; |
| } |
| /** |
| * Parses `selector`, optionally with the passed `options`. |
| * |
| * @param selector Selector to parse. |
| * @param options Options for parsing. |
| * @returns Returns a two-dimensional array. |
| * The first dimension represents selectors separated by commas (eg. `sub1, sub2`), |
| * the second contains the relevant tokens for that selector. |
| */ |
| function parse(selector, options) { |
| var subselects = []; |
| var endIndex = parseSelector(subselects, "" + selector, options, 0); |
| if (endIndex < selector.length) { |
| throw new Error("Unmatched selector: " + selector.slice(endIndex)); |
| } |
| return subselects; |
| } |
| exports.default = parse; |
| function parseSelector(subselects, selector, options, selectorIndex) { |
| var _a, _b; |
| if (options === void 0) { options = {}; } |
| var tokens = []; |
| var sawWS = false; |
| function getName(offset) { |
| var match = selector.slice(selectorIndex + offset).match(reName); |
| if (!match) { |
| throw new Error("Expected name, found " + selector.slice(selectorIndex)); |
| } |
| var name = match[0]; |
| selectorIndex += offset + name.length; |
| return unescapeCSS(name); |
| } |
| function stripWhitespace(offset) { |
| while (isWhitespace(selector.charAt(selectorIndex + offset))) |
| offset++; |
| selectorIndex += offset; |
| } |
| function isEscaped(pos) { |
| var slashCount = 0; |
| while (selector.charAt(--pos) === "\\") |
| slashCount++; |
| return (slashCount & 1) === 1; |
| } |
| function ensureNotTraversal() { |
| if (tokens.length > 0 && isTraversal(tokens[tokens.length - 1])) { |
| throw new Error("Did not expect successive traversals."); |
| } |
| } |
| stripWhitespace(0); |
| while (selector !== "") { |
| var firstChar = selector.charAt(selectorIndex); |
| if (isWhitespace(firstChar)) { |
| sawWS = true; |
| stripWhitespace(1); |
| } |
| else if (firstChar in Traversals) { |
| ensureNotTraversal(); |
| tokens.push({ type: Traversals[firstChar] }); |
| sawWS = false; |
| stripWhitespace(1); |
| } |
| else if (firstChar === ",") { |
| if (tokens.length === 0) { |
| throw new Error("Empty sub-selector"); |
| } |
| subselects.push(tokens); |
| tokens = []; |
| sawWS = false; |
| stripWhitespace(1); |
| } |
| else if (selector.startsWith("/*", selectorIndex)) { |
| var endIndex = selector.indexOf("*/", selectorIndex + 2); |
| if (endIndex < 0) { |
| throw new Error("Comment was not terminated"); |
| } |
| selectorIndex = endIndex + 2; |
| } |
| else { |
| if (sawWS) { |
| ensureNotTraversal(); |
| tokens.push({ type: "descendant" }); |
| sawWS = false; |
| } |
| if (firstChar in attribSelectors) { |
| var _c = attribSelectors[firstChar], name_1 = _c[0], action = _c[1]; |
| tokens.push({ |
| type: "attribute", |
| name: name_1, |
| action: action, |
| value: getName(1), |
| namespace: null, |
| // TODO: Add quirksMode option, which makes `ignoreCase` `true` for HTML. |
| ignoreCase: options.xmlMode ? null : false, |
| }); |
| } |
| else if (firstChar === "[") { |
| stripWhitespace(1); |
| // Determine attribute name and namespace |
| var namespace = null; |
| if (selector.charAt(selectorIndex) === "|") { |
| namespace = ""; |
| selectorIndex += 1; |
| } |
| if (selector.startsWith("*|", selectorIndex)) { |
| namespace = "*"; |
| selectorIndex += 2; |
| } |
| var name_2 = getName(0); |
| if (namespace === null && |
| selector.charAt(selectorIndex) === "|" && |
| selector.charAt(selectorIndex + 1) !== "=") { |
| namespace = name_2; |
| name_2 = getName(1); |
| } |
| if ((_a = options.lowerCaseAttributeNames) !== null && _a !== void 0 ? _a : !options.xmlMode) { |
| name_2 = name_2.toLowerCase(); |
| } |
| stripWhitespace(0); |
| // Determine comparison operation |
| var action = "exists"; |
| var possibleAction = actionTypes.get(selector.charAt(selectorIndex)); |
| if (possibleAction) { |
| action = possibleAction; |
| if (selector.charAt(selectorIndex + 1) !== "=") { |
| throw new Error("Expected `=`"); |
| } |
| stripWhitespace(2); |
| } |
| else if (selector.charAt(selectorIndex) === "=") { |
| action = "equals"; |
| stripWhitespace(1); |
| } |
| // Determine value |
| var value = ""; |
| var ignoreCase = null; |
| if (action !== "exists") { |
| if (quotes.has(selector.charAt(selectorIndex))) { |
| var quote = selector.charAt(selectorIndex); |
| var sectionEnd = selectorIndex + 1; |
| while (sectionEnd < selector.length && |
| (selector.charAt(sectionEnd) !== quote || |
| isEscaped(sectionEnd))) { |
| sectionEnd += 1; |
| } |
| if (selector.charAt(sectionEnd) !== quote) { |
| throw new Error("Attribute value didn't end"); |
| } |
| value = unescapeCSS(selector.slice(selectorIndex + 1, sectionEnd)); |
| selectorIndex = sectionEnd + 1; |
| } |
| else { |
| var valueStart = selectorIndex; |
| while (selectorIndex < selector.length && |
| ((!isWhitespace(selector.charAt(selectorIndex)) && |
| selector.charAt(selectorIndex) !== "]") || |
| isEscaped(selectorIndex))) { |
| selectorIndex += 1; |
| } |
| value = unescapeCSS(selector.slice(valueStart, selectorIndex)); |
| } |
| stripWhitespace(0); |
| // See if we have a force ignore flag |
| var forceIgnore = selector.charAt(selectorIndex); |
| // If the forceIgnore flag is set (either `i` or `s`), use that value |
| if (forceIgnore === "s" || forceIgnore === "S") { |
| ignoreCase = false; |
| stripWhitespace(1); |
| } |
| else if (forceIgnore === "i" || forceIgnore === "I") { |
| ignoreCase = true; |
| stripWhitespace(1); |
| } |
| } |
| // If `xmlMode` is set, there are no rules; otherwise, use the `caseInsensitiveAttributes` list. |
| if (!options.xmlMode) { |
| // TODO: Skip this for `exists`, as there is no value to compare to. |
| ignoreCase !== null && ignoreCase !== void 0 ? ignoreCase : (ignoreCase = caseInsensitiveAttributes.has(name_2)); |
| } |
| if (selector.charAt(selectorIndex) !== "]") { |
| throw new Error("Attribute selector didn't terminate"); |
| } |
| selectorIndex += 1; |
| var attributeSelector = { |
| type: "attribute", |
| name: name_2, |
| action: action, |
| value: value, |
| namespace: namespace, |
| ignoreCase: ignoreCase, |
| }; |
| tokens.push(attributeSelector); |
| } |
| else if (firstChar === ":") { |
| if (selector.charAt(selectorIndex + 1) === ":") { |
| tokens.push({ |
| type: "pseudo-element", |
| name: getName(2).toLowerCase(), |
| }); |
| continue; |
| } |
| var name_3 = getName(1).toLowerCase(); |
| var data = null; |
| if (selector.charAt(selectorIndex) === "(") { |
| if (unpackPseudos.has(name_3)) { |
| if (quotes.has(selector.charAt(selectorIndex + 1))) { |
| throw new Error("Pseudo-selector " + name_3 + " cannot be quoted"); |
| } |
| data = []; |
| selectorIndex = parseSelector(data, selector, options, selectorIndex + 1); |
| if (selector.charAt(selectorIndex) !== ")") { |
| throw new Error("Missing closing parenthesis in :" + name_3 + " (" + selector + ")"); |
| } |
| selectorIndex += 1; |
| } |
| else { |
| selectorIndex += 1; |
| var start = selectorIndex; |
| var counter = 1; |
| for (; counter > 0 && selectorIndex < selector.length; selectorIndex++) { |
| if (selector.charAt(selectorIndex) === "(" && |
| !isEscaped(selectorIndex)) { |
| counter++; |
| } |
| else if (selector.charAt(selectorIndex) === ")" && |
| !isEscaped(selectorIndex)) { |
| counter--; |
| } |
| } |
| if (counter) { |
| throw new Error("Parenthesis not matched"); |
| } |
| data = selector.slice(start, selectorIndex - 1); |
| if (stripQuotesFromPseudos.has(name_3)) { |
| var quot = data.charAt(0); |
| if (quot === data.slice(-1) && quotes.has(quot)) { |
| data = data.slice(1, -1); |
| } |
| data = unescapeCSS(data); |
| } |
| } |
| } |
| tokens.push({ type: "pseudo", name: name_3, data: data }); |
| } |
| else { |
| var namespace = null; |
| var name_4 = void 0; |
| if (firstChar === "*") { |
| selectorIndex += 1; |
| name_4 = "*"; |
| } |
| else if (reName.test(selector.slice(selectorIndex))) { |
| if (selector.charAt(selectorIndex) === "|") { |
| namespace = ""; |
| selectorIndex += 1; |
| } |
| name_4 = getName(0); |
| } |
| else { |
| /* |
| * We have finished parsing the selector. |
| * Remove descendant tokens at the end if they exist, |
| * and return the last index, so that parsing can be |
| * picked up from here. |
| */ |
| if (tokens.length && |
| tokens[tokens.length - 1].type === "descendant") { |
| tokens.pop(); |
| } |
| addToken(subselects, tokens); |
| return selectorIndex; |
| } |
| if (selector.charAt(selectorIndex) === "|") { |
| namespace = name_4; |
| if (selector.charAt(selectorIndex + 1) === "*") { |
| name_4 = "*"; |
| selectorIndex += 2; |
| } |
| else { |
| name_4 = getName(1); |
| } |
| } |
| if (name_4 === "*") { |
| tokens.push({ type: "universal", namespace: namespace }); |
| } |
| else { |
| if ((_b = options.lowerCaseTags) !== null && _b !== void 0 ? _b : !options.xmlMode) { |
| name_4 = name_4.toLowerCase(); |
| } |
| tokens.push({ type: "tag", name: name_4, namespace: namespace }); |
| } |
| } |
| } |
| } |
| addToken(subselects, tokens); |
| return selectorIndex; |
| } |
| function addToken(subselects, tokens) { |
| if (subselects.length > 0 && tokens.length === 0) { |
| throw new Error("Empty sub-selector"); |
| } |
| subselects.push(tokens); |
| } |