diff options
author | RaindropsSys <contact@minteck.org> | 2023-04-06 22:18:28 +0200 |
---|---|---|
committer | RaindropsSys <contact@minteck.org> | 2023-04-06 22:18:28 +0200 |
commit | 83354b2b88218090988dd6e526b0a2505b57e0f1 (patch) | |
tree | e3c73c38a122a78bb7e66fbb99056407edd9d4b9 /includes/external/addressbook/node_modules/css-what/lib/es/parse.js | |
parent | 47b8f2299a483024c4a6a8876af825a010954caa (diff) | |
download | pluralconnect-83354b2b88218090988dd6e526b0a2505b57e0f1.tar.gz pluralconnect-83354b2b88218090988dd6e526b0a2505b57e0f1.tar.bz2 pluralconnect-83354b2b88218090988dd6e526b0a2505b57e0f1.zip |
Updated 5 files and added 1110 files (automated)
Diffstat (limited to 'includes/external/addressbook/node_modules/css-what/lib/es/parse.js')
-rw-r--r-- | includes/external/addressbook/node_modules/css-what/lib/es/parse.js | 420 |
1 files changed, 420 insertions, 0 deletions
diff --git a/includes/external/addressbook/node_modules/css-what/lib/es/parse.js b/includes/external/addressbook/node_modules/css-what/lib/es/parse.js new file mode 100644 index 0000000..fe6ea9a --- /dev/null +++ b/includes/external/addressbook/node_modules/css-what/lib/es/parse.js @@ -0,0 +1,420 @@ +import { SelectorType, AttributeAction, } from "./types"; +const reName = /^[^\\#]?(?:\\(?:[\da-f]{1,6}\s?|.)|[\w\-\u00b0-\uFFFF])+/; +const reEscape = /\\([\da-f]{1,6}\s?|(\s)|.)/gi; +const actionTypes = new Map([ + [126 /* Tilde */, AttributeAction.Element], + [94 /* Circumflex */, AttributeAction.Start], + [36 /* Dollar */, AttributeAction.End], + [42 /* Asterisk */, AttributeAction.Any], + [33 /* ExclamationMark */, AttributeAction.Not], + [124 /* Pipe */, AttributeAction.Hyphen], +]); +// Pseudos, whose data property is parsed as well. +const unpackPseudos = new Set([ + "has", + "not", + "matches", + "is", + "where", + "host", + "host-context", +]); +/** + * 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. + */ +export function isTraversal(selector) { + switch (selector.type) { + case SelectorType.Adjacent: + case SelectorType.Child: + case SelectorType.Descendant: + case SelectorType.Parent: + case SelectorType.Sibling: + case SelectorType.ColumnCombinator: + return true; + default: + return false; + } +} +const stripQuotesFromPseudos = new Set(["contains", "icontains"]); +// Unescape function taken from https://github.com/jquery/sizzle/blob/master/src/sizzle.js#L152 +function funescape(_, escaped, escapedWhitespace) { + const 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 isQuote(c) { + return c === 39 /* SingleQuote */ || c === 34 /* DoubleQuote */; +} +function isWhitespace(c) { + return (c === 32 /* Space */ || + c === 9 /* Tab */ || + c === 10 /* NewLine */ || + c === 12 /* FormFeed */ || + c === 13 /* CarriageReturn */); +} +/** + * 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. + */ +export function parse(selector) { + const subselects = []; + const endIndex = parseSelector(subselects, `${selector}`, 0); + if (endIndex < selector.length) { + throw new Error(`Unmatched selector: ${selector.slice(endIndex)}`); + } + return subselects; +} +function parseSelector(subselects, selector, selectorIndex) { + let tokens = []; + function getName(offset) { + const match = selector.slice(selectorIndex + offset).match(reName); + if (!match) { + throw new Error(`Expected name, found ${selector.slice(selectorIndex)}`); + } + const [name] = match; + selectorIndex += offset + name.length; + return unescapeCSS(name); + } + function stripWhitespace(offset) { + selectorIndex += offset; + while (selectorIndex < selector.length && + isWhitespace(selector.charCodeAt(selectorIndex))) { + selectorIndex++; + } + } + function readValueWithParenthesis() { + selectorIndex += 1; + const start = selectorIndex; + let counter = 1; + for (; counter > 0 && selectorIndex < selector.length; selectorIndex++) { + if (selector.charCodeAt(selectorIndex) === + 40 /* LeftParenthesis */ && + !isEscaped(selectorIndex)) { + counter++; + } + else if (selector.charCodeAt(selectorIndex) === + 41 /* RightParenthesis */ && + !isEscaped(selectorIndex)) { + counter--; + } + } + if (counter) { + throw new Error("Parenthesis not matched"); + } + return unescapeCSS(selector.slice(start, selectorIndex - 1)); + } + function isEscaped(pos) { + let slashCount = 0; + while (selector.charCodeAt(--pos) === 92 /* BackSlash */) + slashCount++; + return (slashCount & 1) === 1; + } + function ensureNotTraversal() { + if (tokens.length > 0 && isTraversal(tokens[tokens.length - 1])) { + throw new Error("Did not expect successive traversals."); + } + } + function addTraversal(type) { + if (tokens.length > 0 && + tokens[tokens.length - 1].type === SelectorType.Descendant) { + tokens[tokens.length - 1].type = type; + return; + } + ensureNotTraversal(); + tokens.push({ type }); + } + function addSpecialAttribute(name, action) { + tokens.push({ + type: SelectorType.Attribute, + name, + action, + value: getName(1), + namespace: null, + ignoreCase: "quirks", + }); + } + /** + * We have finished parsing the current part of 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. + */ + function finalizeSubselector() { + if (tokens.length && + tokens[tokens.length - 1].type === SelectorType.Descendant) { + tokens.pop(); + } + if (tokens.length === 0) { + throw new Error("Empty sub-selector"); + } + subselects.push(tokens); + } + stripWhitespace(0); + if (selector.length === selectorIndex) { + return selectorIndex; + } + loop: while (selectorIndex < selector.length) { + const firstChar = selector.charCodeAt(selectorIndex); + switch (firstChar) { + // Whitespace + case 32 /* Space */: + case 9 /* Tab */: + case 10 /* NewLine */: + case 12 /* FormFeed */: + case 13 /* CarriageReturn */: { + if (tokens.length === 0 || + tokens[0].type !== SelectorType.Descendant) { + ensureNotTraversal(); + tokens.push({ type: SelectorType.Descendant }); + } + stripWhitespace(1); + break; + } + // Traversals + case 62 /* GreaterThan */: { + addTraversal(SelectorType.Child); + stripWhitespace(1); + break; + } + case 60 /* LessThan */: { + addTraversal(SelectorType.Parent); + stripWhitespace(1); + break; + } + case 126 /* Tilde */: { + addTraversal(SelectorType.Sibling); + stripWhitespace(1); + break; + } + case 43 /* Plus */: { + addTraversal(SelectorType.Adjacent); + stripWhitespace(1); + break; + } + // Special attribute selectors: .class, #id + case 46 /* Period */: { + addSpecialAttribute("class", AttributeAction.Element); + break; + } + case 35 /* Hash */: { + addSpecialAttribute("id", AttributeAction.Equals); + break; + } + case 91 /* LeftSquareBracket */: { + stripWhitespace(1); + // Determine attribute name and namespace + let name; + let namespace = null; + if (selector.charCodeAt(selectorIndex) === 124 /* Pipe */) { + // Equivalent to no namespace + name = getName(1); + } + else if (selector.startsWith("*|", selectorIndex)) { + namespace = "*"; + name = getName(2); + } + else { + name = getName(0); + if (selector.charCodeAt(selectorIndex) === 124 /* Pipe */ && + selector.charCodeAt(selectorIndex + 1) !== + 61 /* Equal */) { + namespace = name; + name = getName(1); + } + } + stripWhitespace(0); + // Determine comparison operation + let action = AttributeAction.Exists; + const possibleAction = actionTypes.get(selector.charCodeAt(selectorIndex)); + if (possibleAction) { + action = possibleAction; + if (selector.charCodeAt(selectorIndex + 1) !== + 61 /* Equal */) { + throw new Error("Expected `=`"); + } + stripWhitespace(2); + } + else if (selector.charCodeAt(selectorIndex) === 61 /* Equal */) { + action = AttributeAction.Equals; + stripWhitespace(1); + } + // Determine value + let value = ""; + let ignoreCase = null; + if (action !== "exists") { + if (isQuote(selector.charCodeAt(selectorIndex))) { + const quote = selector.charCodeAt(selectorIndex); + let sectionEnd = selectorIndex + 1; + while (sectionEnd < selector.length && + (selector.charCodeAt(sectionEnd) !== quote || + isEscaped(sectionEnd))) { + sectionEnd += 1; + } + if (selector.charCodeAt(sectionEnd) !== quote) { + throw new Error("Attribute value didn't end"); + } + value = unescapeCSS(selector.slice(selectorIndex + 1, sectionEnd)); + selectorIndex = sectionEnd + 1; + } + else { + const valueStart = selectorIndex; + while (selectorIndex < selector.length && + ((!isWhitespace(selector.charCodeAt(selectorIndex)) && + selector.charCodeAt(selectorIndex) !== + 93 /* RightSquareBracket */) || + isEscaped(selectorIndex))) { + selectorIndex += 1; + } + value = unescapeCSS(selector.slice(valueStart, selectorIndex)); + } + stripWhitespace(0); + // See if we have a force ignore flag + const forceIgnore = selector.charCodeAt(selectorIndex) | 0x20; + // If the forceIgnore flag is set (either `i` or `s`), use that value + if (forceIgnore === 115 /* LowerS */) { + ignoreCase = false; + stripWhitespace(1); + } + else if (forceIgnore === 105 /* LowerI */) { + ignoreCase = true; + stripWhitespace(1); + } + } + if (selector.charCodeAt(selectorIndex) !== + 93 /* RightSquareBracket */) { + throw new Error("Attribute selector didn't terminate"); + } + selectorIndex += 1; + const attributeSelector = { + type: SelectorType.Attribute, + name, + action, + value, + namespace, + ignoreCase, + }; + tokens.push(attributeSelector); + break; + } + case 58 /* Colon */: { + if (selector.charCodeAt(selectorIndex + 1) === 58 /* Colon */) { + tokens.push({ + type: SelectorType.PseudoElement, + name: getName(2).toLowerCase(), + data: selector.charCodeAt(selectorIndex) === + 40 /* LeftParenthesis */ + ? readValueWithParenthesis() + : null, + }); + continue; + } + const name = getName(1).toLowerCase(); + let data = null; + if (selector.charCodeAt(selectorIndex) === + 40 /* LeftParenthesis */) { + if (unpackPseudos.has(name)) { + if (isQuote(selector.charCodeAt(selectorIndex + 1))) { + throw new Error(`Pseudo-selector ${name} cannot be quoted`); + } + data = []; + selectorIndex = parseSelector(data, selector, selectorIndex + 1); + if (selector.charCodeAt(selectorIndex) !== + 41 /* RightParenthesis */) { + throw new Error(`Missing closing parenthesis in :${name} (${selector})`); + } + selectorIndex += 1; + } + else { + data = readValueWithParenthesis(); + if (stripQuotesFromPseudos.has(name)) { + const quot = data.charCodeAt(0); + if (quot === data.charCodeAt(data.length - 1) && + isQuote(quot)) { + data = data.slice(1, -1); + } + } + data = unescapeCSS(data); + } + } + tokens.push({ type: SelectorType.Pseudo, name, data }); + break; + } + case 44 /* Comma */: { + finalizeSubselector(); + tokens = []; + stripWhitespace(1); + break; + } + default: { + if (selector.startsWith("/*", selectorIndex)) { + const endIndex = selector.indexOf("*/", selectorIndex + 2); + if (endIndex < 0) { + throw new Error("Comment was not terminated"); + } + selectorIndex = endIndex + 2; + // Remove leading whitespace + if (tokens.length === 0) { + stripWhitespace(0); + } + break; + } + let namespace = null; + let name; + if (firstChar === 42 /* Asterisk */) { + selectorIndex += 1; + name = "*"; + } + else if (firstChar === 124 /* Pipe */) { + name = ""; + if (selector.charCodeAt(selectorIndex + 1) === 124 /* Pipe */) { + addTraversal(SelectorType.ColumnCombinator); + stripWhitespace(2); + break; + } + } + else if (reName.test(selector.slice(selectorIndex))) { + name = getName(0); + } + else { + break loop; + } + if (selector.charCodeAt(selectorIndex) === 124 /* Pipe */ && + selector.charCodeAt(selectorIndex + 1) !== 124 /* Pipe */) { + namespace = name; + if (selector.charCodeAt(selectorIndex + 1) === + 42 /* Asterisk */) { + name = "*"; + selectorIndex += 2; + } + else { + name = getName(1); + } + } + tokens.push(name === "*" + ? { type: SelectorType.Universal, namespace } + : { type: SelectorType.Tag, name, namespace }); + } + } + } + finalizeSubselector(); + return selectorIndex; +} |