| "use strict"; | |
| Object.defineProperty(exports, "__esModule", { value: true }); | |
| exports.isTraversal = isTraversal; | |
| exports.sortRules = sortRules; | |
| exports.getQuality = getQuality; | |
| exports.includesScopePseudo = includesScopePseudo; | |
| const css_what_1 = require("css-what"); | |
| function isTraversal(token) { | |
| return token.type === "_flexibleDescendant" || (0, css_what_1.isTraversal)(token); | |
| } | |
| /** | |
| * Sort the parts of the passed selector, as there is potential for | |
| * optimization (some types of selectors are faster than others). | |
| * | |
| * @param arr Selector to sort | |
| */ | |
| function sortRules(arr) { | |
| const ratings = arr.map(getQuality); | |
| for (let i = 1; i < arr.length; i++) { | |
| const procNew = ratings[i]; | |
| if (procNew < 0) { | |
| continue; | |
| } | |
| // Use insertion sort to move the token to the correct position. | |
| for (let j = i; j > 0 && procNew < ratings[j - 1]; j--) { | |
| const token = arr[j]; | |
| arr[j] = arr[j - 1]; | |
| arr[j - 1] = token; | |
| ratings[j] = ratings[j - 1]; | |
| ratings[j - 1] = procNew; | |
| } | |
| } | |
| } | |
| function getAttributeQuality(token) { | |
| switch (token.action) { | |
| case css_what_1.AttributeAction.Exists: { | |
| return 10; | |
| } | |
| case css_what_1.AttributeAction.Equals: { | |
| // Prefer ID selectors (eg. #ID) | |
| return token.name === "id" ? 9 : 8; | |
| } | |
| case css_what_1.AttributeAction.Not: { | |
| return 7; | |
| } | |
| case css_what_1.AttributeAction.Start: { | |
| return 6; | |
| } | |
| case css_what_1.AttributeAction.End: { | |
| return 6; | |
| } | |
| case css_what_1.AttributeAction.Any: { | |
| return 5; | |
| } | |
| case css_what_1.AttributeAction.Hyphen: { | |
| return 4; | |
| } | |
| case css_what_1.AttributeAction.Element: { | |
| return 3; | |
| } | |
| } | |
| } | |
| /** | |
| * Determine the quality of the passed token. The higher the number, the | |
| * faster the token is to execute. | |
| * | |
| * @param token Token to get the quality of. | |
| * @returns The token's quality. | |
| */ | |
| function getQuality(token) { | |
| switch (token.type) { | |
| case css_what_1.SelectorType.Universal: { | |
| return 50; | |
| } | |
| case css_what_1.SelectorType.Tag: { | |
| return 30; | |
| } | |
| case css_what_1.SelectorType.Attribute: { | |
| return Math.floor(getAttributeQuality(token) / | |
| // `ignoreCase` adds some overhead, half the result if applicable. | |
| (token.ignoreCase ? 2 : 1)); | |
| } | |
| case css_what_1.SelectorType.Pseudo: { | |
| return !token.data | |
| ? 3 | |
| : token.name === "has" || | |
| token.name === "contains" || | |
| token.name === "icontains" | |
| ? // Expensive in any case — run as late as possible. | |
| 0 | |
| : Array.isArray(token.data) | |
| ? // Eg. `:is`, `:not` | |
| Math.max( | |
| // If we have traversals, try to avoid executing this selector | |
| 0, Math.min(...token.data.map((d) => Math.min(...d.map(getQuality))))) | |
| : 2; | |
| } | |
| default: { | |
| return -1; | |
| } | |
| } | |
| } | |
| function includesScopePseudo(t) { | |
| return (t.type === css_what_1.SelectorType.Pseudo && | |
| (t.name === "scope" || | |
| (Array.isArray(t.data) && | |
| t.data.some((data) => data.some(includesScopePseudo))))); | |
| } | |
| //# sourceMappingURL=selectors.js.map |