You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

240 lines
8.9 KiB

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.default = parse;
var reName = /^[^\\]?(?:\\(?:[\da-f]{1,6}\s?|.)|[\w\-\u00b0-\uFFFF])+/;
var reEscape = /\\([\da-f]{1,6}\s?|(\s)|.)/gi;
// Modified version of https://github.com/jquery/sizzle/blob/master/src/sizzle.js#L87
var reAttr = /^\s*((?:\\.|[\w\u00b0-\uFFFF-])+)\s*(?:(\S?)=\s*(?:(['"])((?:[^\\]|\\[^])*?)\3|(#?(?:\\.|[\w\u00b0-\uFFFF-])*)|)|)\s*(i)?\]/;
var actionTypes = {
undefined: "exists",
"": "equals",
"~": "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",
"host",
"host-context",
]);
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";
}
function parse(selector, options) {
var subselects = [];
selector = parseSelector(subselects, "" + selector, options);
if (selector !== "") {
throw new Error("Unmatched selector: " + selector);
}
return subselects;
}
function parseSelector(subselects, selector, options) {
var _a, _b;
if (options === void 0) { options = {}; }
var tokens = [];
var sawWS = false;
function getName() {
var match = selector.match(reName);
if (!match) {
throw new Error("Expected name, found " + selector);
}
var sub = match[0];
selector = selector.substr(sub.length);
return unescapeCSS(sub);
}
function stripWhitespace(start) {
while (isWhitespace(selector.charAt(start)))
start++;
selector = selector.substr(start);
}
function isEscaped(pos) {
var slashCount = 0;
while (selector.charAt(--pos) === "\\")
slashCount++;
return (slashCount & 1) === 1;
}
stripWhitespace(0);
while (selector !== "") {
var firstChar = selector.charAt(0);
if (isWhitespace(firstChar)) {
sawWS = true;
stripWhitespace(1);
}
else if (firstChar in Traversals) {
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 (sawWS) {
if (tokens.length > 0) {
tokens.push({ type: "descendant" });
}
sawWS = false;
}
if (firstChar === "*") {
selector = selector.substr(1);
tokens.push({ type: "universal" });
}
else if (firstChar in attribSelectors) {
var _c = attribSelectors[firstChar], name_1 = _c[0], action = _c[1];
selector = selector.substr(1);
tokens.push({
type: "attribute",
name: name_1,
action: action,
value: getName(),
ignoreCase: false,
});
}
else if (firstChar === "[") {
selector = selector.substr(1);
var attributeMatch = selector.match(reAttr);
if (!attributeMatch) {
throw new Error("Malformed attribute selector: " + selector);
}
var completeSelector = attributeMatch[0], baseName = attributeMatch[1], actionType = attributeMatch[2], _d = attributeMatch[4], quotedValue = _d === void 0 ? "" : _d, _e = attributeMatch[5], value = _e === void 0 ? quotedValue : _e, ignoreCase = attributeMatch[6];
selector = selector.substr(completeSelector.length);
var name_2 = unescapeCSS(baseName);
if ((_a = options.lowerCaseAttributeNames) !== null && _a !== void 0 ? _a : !options.xmlMode) {
name_2 = name_2.toLowerCase();
}
tokens.push({
type: "attribute",
name: name_2,
action: actionTypes[actionType],
value: unescapeCSS(value),
ignoreCase: !!ignoreCase,
});
}
else if (firstChar === ":") {
if (selector.charAt(1) === ":") {
selector = selector.substr(2);
tokens.push({
type: "pseudo-element",
name: getName().toLowerCase(),
});
continue;
}
selector = selector.substr(1);
var name_3 = getName().toLowerCase();
var data = null;
if (selector.startsWith("(")) {
if (unpackPseudos.has(name_3)) {
var quot = selector.charAt(1);
var quoted = quotes.has(quot);
selector = selector.substr(quoted ? 2 : 1);
data = [];
selector = parseSelector(data, selector, options);
if (quoted) {
if (!selector.startsWith(quot)) {
throw new Error("Unmatched quotes in :" + name_3);
}
else {
selector = selector.substr(1);
}
}
if (!selector.startsWith(")")) {
throw new Error("Missing closing parenthesis in :" + name_3 + " (" + selector + ")");
}
selector = selector.substr(1);
}
else {
var pos = 1;
var counter = 1;
for (; counter > 0 && pos < selector.length; pos++) {
if (selector.charAt(pos) === "(" &&
!isEscaped(pos)) {
counter++;
}
else if (selector.charAt(pos) === ")" &&
!isEscaped(pos)) {
counter--;
}
}
if (counter) {
throw new Error("Parenthesis not matched");
}
data = selector.substr(1, pos - 2);
selector = selector.substr(pos);
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 if (reName.test(selector)) {
var name_4 = getName();
if ((_b = options.lowerCaseTags) !== null && _b !== void 0 ? _b : !options.xmlMode) {
name_4 = name_4.toLowerCase();
}
tokens.push({ type: "tag", name: name_4 });
}
else {
if (tokens.length &&
tokens[tokens.length - 1].type === "descendant") {
tokens.pop();
}
addToken(subselects, tokens);
return selector;
}
}
}
addToken(subselects, tokens);
return selector;
}
function addToken(subselects, tokens) {
if (subselects.length > 0 && tokens.length === 0) {
throw new Error("Empty sub-selector");
}
subselects.push(tokens);
}