feat: migrate to starlight

This commit is contained in:
DuroCodes
2024-05-06 17:15:30 -04:00
parent 767acedea7
commit bb190f2d81
15140 changed files with 2828326 additions and 35408 deletions

2
node_modules/hast-util-select/index.d.ts generated vendored Normal file
View File

@@ -0,0 +1,2 @@
export type Space = import('./lib/index.js').Space;
export { matches, select, selectAll } from "./lib/index.js";

5
node_modules/hast-util-select/index.js generated vendored Normal file
View File

@@ -0,0 +1,5 @@
/**
* @typedef {import('./lib/index.js').Space} Space
*/
export {matches, select, selectAll} from './lib/index.js'

16
node_modules/hast-util-select/lib/attribute.d.ts generated vendored Normal file
View File

@@ -0,0 +1,16 @@
/**
* @param {AstAttribute} query
* Query.
* @param {Element} element
* Element.
* @param {Schema} schema
* Schema of element.
* @returns {boolean}
* Whether `element` matches `query`.
*/
export function attribute(query: AstAttribute, element: Element, schema: Schema): boolean;
export type AstAttribute = import('css-selector-parser').AstAttribute;
export type Element = import('hast').Element;
export type Properties = import('hast').Properties;
export type Info = import('property-information').Info;
export type Schema = import('property-information').Schema;

118
node_modules/hast-util-select/lib/attribute.js generated vendored Normal file
View File

@@ -0,0 +1,118 @@
/**
* @typedef {import('css-selector-parser').AstAttribute} AstAttribute
*
* @typedef {import('hast').Element} Element
* @typedef {import('hast').Properties} Properties
*
* @typedef {import('property-information').Info} Info
* @typedef {import('property-information').Schema} Schema
*/
import {stringify as commas} from 'comma-separated-tokens'
import {ok as assert} from 'devlop'
import {find} from 'property-information'
import * as spaces from 'space-separated-tokens'
/**
* @param {AstAttribute} query
* Query.
* @param {Element} element
* Element.
* @param {Schema} schema
* Schema of element.
* @returns {boolean}
* Whether `element` matches `query`.
*/
export function attribute(query, element, schema) {
const info = find(schema, query.name)
const propertyValue = element.properties[info.property]
let value = normalizeValue(propertyValue, info)
// Exists.
if (!query.value) {
return value !== undefined
}
assert(query.value.type === 'String', 'expected plain string')
let key = query.value.value
// Case-sensitivity.
if (query.caseSensitivityModifier === 'i') {
key = key.toLowerCase()
if (value) {
value = value.toLowerCase()
}
}
if (value !== undefined) {
switch (query.operator) {
// Exact.
case '=': {
return key === value
}
// Ends.
case '$=': {
return key === value.slice(-key.length)
}
// Contains.
case '*=': {
return value.includes(key)
}
// Begins.
case '^=': {
return key === value.slice(0, key.length)
}
// Exact or prefix.
case '|=': {
return (
key === value ||
(key === value.slice(0, key.length) &&
value.charAt(key.length) === '-')
)
}
// Space-separated list.
case '~=': {
return (
// For all other values (including comma-separated lists), return whether this
// is an exact match.
key === value ||
// If this is a space-separated list, and the query is contained in it, return
// true.
spaces.parse(value).includes(key)
)
}
// Other values are not yet supported by CSS.
// No default
}
}
return false
}
/**
*
* @param {Properties[keyof Properties]} value
* @param {Info} info
* @returns {string | undefined}
*/
function normalizeValue(value, info) {
if (value === null || value === undefined) {
// Empty.
} else if (typeof value === 'boolean') {
if (value) {
return info.attribute
}
} else if (Array.isArray(value)) {
if (value.length > 0) {
return (info.commaSeparated ? commas : spaces.stringify)(value)
}
} else {
return String(value)
}
}

13
node_modules/hast-util-select/lib/class-name.d.ts generated vendored Normal file
View File

@@ -0,0 +1,13 @@
/**
* Check whether an element has all class names.
*
* @param {AstClassName} query
* AST rule (with `classNames`).
* @param {Element} element
* Element.
* @returns {boolean}
* Whether `element` matches `query`.
*/
export function className(query: AstClassName, element: Element): boolean;
export type AstClassName = import('css-selector-parser').AstClassName;
export type Element = import('hast').Element;

26
node_modules/hast-util-select/lib/class-name.js generated vendored Normal file
View File

@@ -0,0 +1,26 @@
/**
* @typedef {import('css-selector-parser').AstClassName} AstClassName
* @typedef {import('hast').Element} Element
*/
/** @type {Array<never>} */
const emptyClassNames = []
/**
* Check whether an element has all class names.
*
* @param {AstClassName} query
* AST rule (with `classNames`).
* @param {Element} element
* Element.
* @returns {boolean}
* Whether `element` matches `query`.
*/
export function className(query, element) {
// Assume array.
const value = /** @type {Readonly<Array<string>>} */ (
element.properties.className || emptyClassNames
)
return value.includes(query.name)
}

20
node_modules/hast-util-select/lib/enter-state.d.ts generated vendored Normal file
View File

@@ -0,0 +1,20 @@
/**
* Enter a node.
*
* The caller is responsible for calling the return value `exit`.
*
* @param {State} state
* Current state.
*
* Will be mutated: `exit` undos the changes.
* @param {Nodes} node
* Node to enter.
* @returns {() => undefined}
* Call to exit.
*/
export function enterState(state: State, node: Nodes): () => undefined;
export type ElementContent = import('hast').ElementContent;
export type Nodes = import('hast').Nodes;
export type Visitor = import('unist-util-visit').Visitor<ElementContent>;
export type Direction = import('./index.js').Direction;
export type State = import('./index.js').State;

164
node_modules/hast-util-select/lib/enter-state.js generated vendored Normal file
View File

@@ -0,0 +1,164 @@
/**
* @typedef {import('hast').ElementContent} ElementContent
* @typedef {import('hast').Nodes} Nodes
*
* @typedef {import('unist-util-visit').Visitor<ElementContent>} Visitor
*
* @typedef {import('./index.js').Direction} Direction
* @typedef {import('./index.js').State} State
*/
import {direction} from 'direction'
import {toString} from 'hast-util-to-string'
import {svg} from 'property-information'
import {EXIT, SKIP, visit} from 'unist-util-visit'
/**
* Enter a node.
*
* The caller is responsible for calling the return value `exit`.
*
* @param {State} state
* Current state.
*
* Will be mutated: `exit` undos the changes.
* @param {Nodes} node
* Node to enter.
* @returns {() => undefined}
* Call to exit.
*/
// eslint-disable-next-line complexity
export function enterState(state, node) {
const schema = state.schema
const language = state.language
const currentDirection = state.direction
const editableOrEditingHost = state.editableOrEditingHost
/** @type {Direction | undefined} */
let dirInferred
if (node.type === 'element') {
const lang = node.properties.xmlLang || node.properties.lang
const type = node.properties.type || 'text'
const dir = dirProperty(node)
if (lang !== null && lang !== undefined) {
state.language = String(lang)
}
if (schema && schema.space === 'html') {
if (node.properties.contentEditable === 'true') {
state.editableOrEditingHost = true
}
if (node.tagName === 'svg') {
state.schema = svg
}
// See: <https://html.spec.whatwg.org/#the-directionality>.
// Explicit `[dir=rtl]`.
if (dir === 'rtl') {
dirInferred = dir
} else if (
// Explicit `[dir=ltr]`.
dir === 'ltr' ||
// HTML with an invalid or no `[dir]`.
(dir !== 'auto' && node.tagName === 'html') ||
// `input[type=tel]` with an invalid or no `[dir]`.
(dir !== 'auto' && node.tagName === 'input' && type === 'tel')
) {
dirInferred = 'ltr'
// `[dir=auto]` or `bdi` with an invalid or no `[dir]`.
} else if (dir === 'auto' || node.tagName === 'bdi') {
if (node.tagName === 'textarea') {
// Check contents of `<textarea>`.
dirInferred = dirBidi(toString(node))
} else if (
node.tagName === 'input' &&
(type === 'email' ||
type === 'search' ||
type === 'tel' ||
type === 'text')
) {
// Check value of `<input>`.
dirInferred = node.properties.value
? dirBidi(String(node.properties.value))
: 'ltr'
} else {
// Check text nodes in `node`.
visit(node, inferDirectionality)
}
}
if (dirInferred) {
state.direction = dirInferred
}
}
// Turn off editing mode in non-HTML spaces.
else if (state.editableOrEditingHost) {
state.editableOrEditingHost = false
}
}
return reset
/**
* @returns {undefined}
* Nothing.
*/
function reset() {
state.schema = schema
state.language = language
state.direction = currentDirection
state.editableOrEditingHost = editableOrEditingHost
}
/** @type {Visitor} */
function inferDirectionality(child) {
if (child.type === 'text') {
dirInferred = dirBidi(child.value)
return dirInferred ? EXIT : undefined
}
if (
child !== node &&
child.type === 'element' &&
(child.tagName === 'bdi' ||
child.tagName === 'script' ||
child.tagName === 'style' ||
child.tagName === 'textare' ||
dirProperty(child))
) {
return SKIP
}
}
}
/**
* See `wooorm/direction`.
*
* @param {string} value
* Value to check.
* @returns {Exclude<Direction, 'auto'> | undefined}
* Directionality.
*/
function dirBidi(value) {
const result = direction(value)
return result === 'neutral' ? undefined : result
}
/**
* @param {ElementContent} node
* Node to check.
* @returns {Direction | undefined}
* Directionality.
*/
function dirProperty(node) {
const value =
node.type === 'element' && typeof node.properties.dir === 'string'
? node.properties.dir.toLowerCase()
: undefined
return value === 'auto' || value === 'ltr' || value === 'rtl'
? value
: undefined
}

13
node_modules/hast-util-select/lib/id.d.ts generated vendored Normal file
View File

@@ -0,0 +1,13 @@
/**
* Check whether an element has an ID.
*
* @param {AstId} query
* AST rule (with `ids`).
* @param {Element} element
* Element.
* @returns {boolean}
* Whether `element` matches `query`.
*/
export function id(query: AstId, element: Element): boolean;
export type AstId = import('css-selector-parser').AstId;
export type Element = import('hast').Element;

22
node_modules/hast-util-select/lib/id.js generated vendored Normal file
View File

@@ -0,0 +1,22 @@
/**
* @typedef {import('css-selector-parser').AstId} AstId
*
* @typedef {import('hast').Element} Element
*/
// Workaround to show references to above types in VS Code.
''
/**
* Check whether an element has an ID.
*
* @param {AstId} query
* AST rule (with `ids`).
* @param {Element} element
* Element.
* @returns {boolean}
* Whether `element` matches `query`.
*/
export function id(query, element) {
return element.properties.id === query.name
}

123
node_modules/hast-util-select/lib/index.d.ts generated vendored Normal file
View File

@@ -0,0 +1,123 @@
/**
* Check that the given `node` matches `selector`.
*
* This only checks the element itself, not the surrounding tree.
* Thus, nesting in selectors is not supported (`p b`, `p > b`), neither are
* selectors like `:first-child`, etc.
* This only checks that the given element matches the selector.
*
* @param {string} selector
* CSS selector, such as (`h1`, `a, b`).
* @param {Nodes | null | undefined} [node]
* Node that might match `selector`, should be an element (optional).
* @param {Space | null | undefined} [space='html']
* Name of namespace (default: `'html'`).
* @returns {boolean}
* Whether `node` matches `selector`.
*/
export function matches(selector: string, node?: Nodes | null | undefined, space?: Space | null | undefined): boolean;
/**
* Select the first element that matches `selector` in the given `tree`.
* Searches the tree in *preorder*.
*
* @param {string} selector
* CSS selector, such as (`h1`, `a, b`).
* @param {Nodes | null | undefined} [tree]
* Tree to search (optional).
* @param {Space | null | undefined} [space='html']
* Name of namespace (default: `'html'`).
* @returns {Element | undefined}
* First element in `tree` that matches `selector` or `undefined` if nothing
* is found; this could be `tree` itself.
*/
export function select(selector: string, tree?: Nodes | null | undefined, space?: Space | null | undefined): Element | undefined;
/**
* Select all elements that match `selector` in the given `tree`.
* Searches the tree in *preorder*.
*
* @param {string} selector
* CSS selector, such as (`h1`, `a, b`).
* @param {Nodes | null | undefined} [tree]
* Tree to search (optional).
* @param {Space | null | undefined} [space='html']
* Name of namespace (default: `'html'`).
* @returns {Array<Element>}
* Elements in `tree` that match `selector`.
* This could include `tree` itself.
*/
export function selectAll(selector: string, tree?: Nodes | null | undefined, space?: Space | null | undefined): Array<Element>;
export type AstSelector = import('css-selector-parser').AstSelector;
export type Element = import('hast').Element;
export type Nodes = import('hast').Nodes;
export type RootContent = import('hast').RootContent;
export type Schema = import('property-information').Schema;
/**
* Name of namespace.
*/
export type Space = 'html' | 'svg';
/**
* Direction.
*/
export type Direction = 'auto' | 'ltr' | 'rtl';
/**
* Current state.
*/
export type State = {
/**
* Current direction.
*/
direction: Direction;
/**
* Whether were in `contentEditable`.
*/
editableOrEditingHost: boolean;
/**
* Track siblings: there are `n` siblings.
*/
elementCount: number | undefined;
/**
* Track siblings: this current element has `n` elements before it.
*/
elementIndex: number | undefined;
/**
* Whether we found at least one match.
*/
found: boolean;
/**
* Current language.
*/
language: string | undefined;
/**
* Whether we can stop looking after we found one element.
*/
one: boolean;
/**
* Matches.
*/
results: Array<Element>;
/**
* Original root selectors.
*/
rootQuery: AstSelector;
/**
* Current schema.
*/
schema: Schema;
/**
* Elements in scope.
*/
scopeElements: Array<RootContent>;
/**
* Whether we only allow selectors without nesting.
*/
shallow: boolean;
/**
* Track siblings: there are `n` siblings with this elements tag name.
*/
typeCount: number | undefined;
/**
* Track siblings: this current element has `n` elements with its tag name
* before it.
*/
typeIndex: number | undefined;
};

149
node_modules/hast-util-select/lib/index.js generated vendored Normal file
View File

@@ -0,0 +1,149 @@
/**
* @typedef {import('css-selector-parser').AstSelector} AstSelector
*
* @typedef {import('hast').Element} Element
* @typedef {import('hast').Nodes} Nodes
* @typedef {import('hast').RootContent} RootContent
*
* @typedef {import('property-information').Schema} Schema
*/
/**
* @typedef {'html' | 'svg'} Space
* Name of namespace.
*
* @typedef {'auto' | 'ltr' | 'rtl'} Direction
* Direction.
*
* @typedef State
* Current state.
* @property {Direction} direction
* Current direction.
* @property {boolean} editableOrEditingHost
* Whether were in `contentEditable`.
* @property {number | undefined} elementCount
* Track siblings: there are `n` siblings.
* @property {number | undefined} elementIndex
* Track siblings: this current element has `n` elements before it.
* @property {boolean} found
* Whether we found at least one match.
* @property {string | undefined} language
* Current language.
* @property {boolean} one
* Whether we can stop looking after we found one element.
* @property {Array<Element>} results
* Matches.
* @property {AstSelector} rootQuery
* Original root selectors.
* @property {Schema} schema
* Current schema.
* @property {Array<RootContent>} scopeElements
* Elements in scope.
* @property {boolean} shallow
* Whether we only allow selectors without nesting.
* @property {number | undefined} typeCount
* Track siblings: there are `n` siblings with this elements tag name.
* @property {number | undefined} typeIndex
* Track siblings: this current element has `n` elements with its tag name
* before it.
*/
import {html, svg} from 'property-information'
import {parse} from './parse.js'
import {walk} from './walk.js'
/**
* Check that the given `node` matches `selector`.
*
* This only checks the element itself, not the surrounding tree.
* Thus, nesting in selectors is not supported (`p b`, `p > b`), neither are
* selectors like `:first-child`, etc.
* This only checks that the given element matches the selector.
*
* @param {string} selector
* CSS selector, such as (`h1`, `a, b`).
* @param {Nodes | null | undefined} [node]
* Node that might match `selector`, should be an element (optional).
* @param {Space | null | undefined} [space='html']
* Name of namespace (default: `'html'`).
* @returns {boolean}
* Whether `node` matches `selector`.
*/
export function matches(selector, node, space) {
const state = createState(selector, node, space)
state.one = true
state.shallow = true
walk(state, node || undefined)
return state.results.length > 0
}
/**
* Select the first element that matches `selector` in the given `tree`.
* Searches the tree in *preorder*.
*
* @param {string} selector
* CSS selector, such as (`h1`, `a, b`).
* @param {Nodes | null | undefined} [tree]
* Tree to search (optional).
* @param {Space | null | undefined} [space='html']
* Name of namespace (default: `'html'`).
* @returns {Element | undefined}
* First element in `tree` that matches `selector` or `undefined` if nothing
* is found; this could be `tree` itself.
*/
export function select(selector, tree, space) {
const state = createState(selector, tree, space)
state.one = true
walk(state, tree || undefined)
return state.results[0]
}
/**
* Select all elements that match `selector` in the given `tree`.
* Searches the tree in *preorder*.
*
* @param {string} selector
* CSS selector, such as (`h1`, `a, b`).
* @param {Nodes | null | undefined} [tree]
* Tree to search (optional).
* @param {Space | null | undefined} [space='html']
* Name of namespace (default: `'html'`).
* @returns {Array<Element>}
* Elements in `tree` that match `selector`.
* This could include `tree` itself.
*/
export function selectAll(selector, tree, space) {
const state = createState(selector, tree, space)
walk(state, tree || undefined)
return state.results
}
/**
* @param {string} selector
* CSS selector, such as (`h1`, `a, b`).
* @param {Nodes | null | undefined} [tree]
* Tree to search (optional).
* @param {Space | null | undefined} [space='html']
* Name of namespace (default: `'html'`).
* @returns {State} State
* State.
*/
function createState(selector, tree, space) {
return {
direction: 'ltr',
editableOrEditingHost: false,
elementCount: undefined,
elementIndex: undefined,
found: false,
language: undefined,
one: false,
// State of the query.
results: [],
rootQuery: parse(selector),
schema: space === 'svg' ? svg : html,
scopeElements: tree ? (tree.type === 'root' ? tree.children : [tree]) : [],
shallow: false,
typeIndex: undefined,
typeCount: undefined
}
}

13
node_modules/hast-util-select/lib/name.d.ts generated vendored Normal file
View File

@@ -0,0 +1,13 @@
/**
* Check whether an element has a tag name.
*
* @param {AstTagName} query
* AST rule (with `tag`).
* @param {Element} element
* Element.
* @returns {boolean}
* Whether `element` matches `query`.
*/
export function name(query: AstTagName, element: Element): boolean;
export type AstTagName = import('css-selector-parser').AstTagName;
export type Element = import('hast').Element;

22
node_modules/hast-util-select/lib/name.js generated vendored Normal file
View File

@@ -0,0 +1,22 @@
/**
* @typedef {import('css-selector-parser').AstTagName} AstTagName
*
* @typedef {import('hast').Element} Element
*/
// Workaround to show references to above types in VS Code.
''
/**
* Check whether an element has a tag name.
*
* @param {AstTagName} query
* AST rule (with `tag`).
* @param {Element} element
* Element.
* @returns {boolean}
* Whether `element` matches `query`.
*/
export function name(query, element) {
return query.name === element.tagName
}

8
node_modules/hast-util-select/lib/parse.d.ts generated vendored Normal file
View File

@@ -0,0 +1,8 @@
/**
* @param {string} selector
* Selector to parse.
* @returns {AstSelector}
* Parsed selector.
*/
export function parse(selector: string): AstSelector;
export type AstSelector = import('css-selector-parser').AstSelector;

21
node_modules/hast-util-select/lib/parse.js generated vendored Normal file
View File

@@ -0,0 +1,21 @@
/**
* @typedef {import('css-selector-parser').AstSelector} AstSelector
*/
import {createParser} from 'css-selector-parser'
const cssSelectorParse = createParser({syntax: 'selectors-4'})
/**
* @param {string} selector
* Selector to parse.
* @returns {AstSelector}
* Parsed selector.
*/
export function parse(selector) {
if (typeof selector !== 'string') {
throw new TypeError('Expected `string` as selector, not `' + selector + '`')
}
return cssSelectorParse(selector)
}

7
node_modules/hast-util-select/lib/pseudo.d.ts generated vendored Normal file
View File

@@ -0,0 +1,7 @@
/** @type {(rule: AstPseudoClass, element: Element, index: number | undefined, parent: Parents | undefined, state: State) => boolean} */
export const pseudo: (rule: AstPseudoClass, element: Element, index: number | undefined, parent: Parents | undefined, state: State) => boolean;
export type AstPseudoClass = import('css-selector-parser').AstPseudoClass;
export type Element = import('hast').Element;
export type ElementContent = import('hast').ElementContent;
export type Parents = import('hast').Parents;
export type State = import('./index.js').State;

761
node_modules/hast-util-select/lib/pseudo.js generated vendored Normal file
View File

@@ -0,0 +1,761 @@
/**
* @typedef {import('css-selector-parser').AstPseudoClass} AstPseudoClass
*
* @typedef {import('hast').Element} Element
* @typedef {import('hast').ElementContent} ElementContent
* @typedef {import('hast').Parents} Parents
*
* @typedef {import('./index.js').State} State
*/
import {extendedFilter} from 'bcp-47-match'
import {parse as commas} from 'comma-separated-tokens'
import {ok as assert, unreachable} from 'devlop'
import {hasProperty} from 'hast-util-has-property'
import {whitespace} from 'hast-util-whitespace'
import fauxEsmNthCheck from 'nth-check'
import {zwitch} from 'zwitch'
import {walk} from './walk.js'
/** @type {import('nth-check').default} */
// @ts-expect-error: types are broken.
const nthCheck = fauxEsmNthCheck.default || fauxEsmNthCheck
/** @type {(rule: AstPseudoClass, element: Element, index: number | undefined, parent: Parents | undefined, state: State) => boolean} */
export const pseudo = zwitch('name', {
handlers: {
'any-link': anyLink,
blank,
checked,
dir,
disabled,
empty,
enabled,
'first-child': firstChild,
'first-of-type': firstOfType,
has,
is,
lang,
'last-child': lastChild,
'last-of-type': lastOfType,
not,
'nth-child': nthChild,
'nth-last-child': nthLastChild,
'nth-last-of-type': nthLastOfType,
'nth-of-type': nthOfType,
'only-child': onlyChild,
'only-of-type': onlyOfType,
optional,
'read-only': readOnly,
'read-write': readWrite,
required,
root,
scope
},
invalid: invalidPseudo,
unknown: unknownPseudo
})
/**
* Check whether an element matches an `:any-link` pseudo.
*
* @param {AstPseudoClass} _
* Query.
* @param {Element} element
* Element.
* @returns {boolean}
* Whether `element` matches `query`.
*/
function anyLink(_, element) {
return (
(element.tagName === 'a' ||
element.tagName === 'area' ||
element.tagName === 'link') &&
hasProperty(element, 'href')
)
}
/**
* @param {State} state
* State.
* @param {AstPseudoClass} query
* Query.
*/
function assertDeep(state, query) {
if (state.shallow) {
throw new Error('Cannot use `:' + query.name + '` without parent')
}
}
/**
* Check whether an element matches a `:blank` pseudo.
*
* @param {AstPseudoClass} _
* Query.
* @param {Element} element
* Element.
* @returns {boolean}
* Whether `element` matches `query`.
*/
function blank(_, element) {
return !someChildren(element, check)
/**
* @param {ElementContent} child
* @returns {boolean}
*/
function check(child) {
return (
child.type === 'element' || (child.type === 'text' && !whitespace(child))
)
}
}
/**
* Check whether an element matches a `:checked` pseudo.
*
* @param {AstPseudoClass} _
* Query.
* @param {Element} element
* Element.
* @returns {boolean}
* Whether `element` matches `query`.
*/
function checked(_, element) {
if (element.tagName === 'input' || element.tagName === 'menuitem') {
return Boolean(
(element.properties.type === 'checkbox' ||
element.properties.type === 'radio') &&
hasProperty(element, 'checked')
)
}
if (element.tagName === 'option') {
return hasProperty(element, 'selected')
}
return false
}
/**
* Check whether an element matches a `:dir()` pseudo.
*
* @param {AstPseudoClass} query
* Query.
* @param {Element} _1
* Element.
* @param {number | undefined} _2
* Index of `element` in `parent`.
* @param {Parents | undefined} _3
* Parent of `element`.
* @param {State} state
* State.
* @returns {boolean}
* Whether `element` matches `query`.
*/
function dir(query, _1, _2, _3, state) {
assert(query.argument, 'expected `argument`')
assert(query.argument.type === 'String', 'expected plain text')
return state.direction === query.argument.value
}
/**
* Check whether an element matches a `:disabled` pseudo.
*
* @param {AstPseudoClass} _
* Query.
* @param {Element} element
* Element.
* @returns {boolean}
* Whether `element` matches `query`.
*/
function disabled(_, element) {
return (
(element.tagName === 'button' ||
element.tagName === 'input' ||
element.tagName === 'select' ||
element.tagName === 'textarea' ||
element.tagName === 'optgroup' ||
element.tagName === 'option' ||
element.tagName === 'menuitem' ||
element.tagName === 'fieldset') &&
hasProperty(element, 'disabled')
)
}
/**
* Check whether an element matches an `:empty` pseudo.
*
* @param {AstPseudoClass} _
* Query.
* @param {Element} element
* Element.
* @returns {boolean}
* Whether `element` matches `query`.
*/
function empty(_, element) {
return !someChildren(element, check)
/**
* @param {ElementContent} child
* @returns {boolean}
*/
function check(child) {
return child.type === 'element' || child.type === 'text'
}
}
/**
* Check whether an element matches an `:enabled` pseudo.
*
* @param {AstPseudoClass} query
* Query.
* @param {Element} element
* Element.
* @returns {boolean}
* Whether `element` matches `query`.
*/
function enabled(query, element) {
return !disabled(query, element)
}
/**
* Check whether an element matches a `:first-child` pseudo.
*
* @param {AstPseudoClass} query
* Query.
* @param {Element} _1
* Element.
* @param {number | undefined} _2
* Index of `element` in `parent`.
* @param {Parents | undefined} _3
* Parent of `element`.
* @param {State} state
* State.
* @returns {boolean}
* Whether `element` matches `query`.
*/
function firstChild(query, _1, _2, _3, state) {
assertDeep(state, query)
return state.elementIndex === 0
}
/**
* Check whether an element matches a `:first-of-type` pseudo.
*
* @param {AstPseudoClass} query
* Query.
* @param {Element} _1
* Element.
* @param {number | undefined} _2
* Index of `element` in `parent`.
* @param {Parents | undefined} _3
* Parent of `element`.
* @param {State} state
* State.
* @returns {boolean}
* Whether `element` matches `query`.
*/
function firstOfType(query, _1, _2, _3, state) {
assertDeep(state, query)
return state.typeIndex === 0
}
/**
* @param {AstPseudoClass} query
* Query.
* @returns {(value: number) => boolean}
* N.
*/
function getCachedNthCheck(query) {
/** @type {(value: number) => boolean} */
// @ts-expect-error: cache.
let fn = query._cachedFn
if (!fn) {
const value = query.argument
assert(value, 'expected `argument`')
if (value.type !== 'Formula') {
throw new Error(
'Expected `nth` formula, such as `even` or `2n+1` (`of` is not yet supported)'
)
}
fn = nthCheck(value.a + 'n+' + value.b)
// @ts-expect-error: cache.
query._cachedFn = fn
}
return fn
}
/**
* @param {AstPseudoClass} query
* Query.
* @param {Element} element
* Element.
* @param {number | undefined} _1
* Index of `element` in `parent`.
* @param {Parents | undefined} _2
* Parent of `element`.
* @param {State} state
* State.
* @returns {boolean}
* Whether `element` matches `query`.
*/
function has(query, element, _1, _2, state) {
assert(query.argument, 'expected `argument`')
assert(query.argument.type === 'Selector', 'expected selector')
/** @type {State} */
const childState = {
...state,
// Not found yet.
found: false,
// One result is enough.
one: true,
results: [],
rootQuery: query.argument,
scopeElements: [element],
// Do walk deep.
shallow: false
}
walk(childState, {type: 'root', children: element.children})
return childState.results.length > 0
}
// Shouldnt be called, parser gives correct data.
/* c8 ignore next 3 */
function invalidPseudo() {
unreachable('Invalid pseudo-selector')
}
/**
* Check whether an element `:is` further selectors.
*
* @param {AstPseudoClass} query
* Query.
* @param {Element} element
* Element.
* @param {number | undefined} _1
* Index of `element` in `parent`.
* @param {Parents | undefined} _2
* Parent of `element`.
* @param {State} state
* State.
* @returns {boolean}
* Whether `element` matches `query`.
*/
function is(query, element, _1, _2, state) {
assert(query.argument, 'expected `argument`')
assert(query.argument.type === 'Selector', 'expected selector')
/** @type {State} */
const childState = {
...state,
// Not found yet.
found: false,
// One result is enough.
one: true,
results: [],
rootQuery: query.argument,
scopeElements: [element],
// Do walk deep.
shallow: false
}
walk(childState, element)
return childState.results[0] === element
}
/**
* Check whether an element matches a `:lang()` pseudo.
*
* @param {AstPseudoClass} query
* Query.
* @param {Element} _1
* Element.
* @param {number | undefined} _2
* Index of `element` in `parent`.
* @param {Parents | undefined} _3
* Parent of `element`.
* @param {State} state
* State.
* @returns {boolean}
* Whether `element` matches `query`.
*/
function lang(query, _1, _2, _3, state) {
assert(query.argument, 'expected `argument`')
assert(query.argument.type === 'String', 'expected string')
return (
state.language !== '' &&
state.language !== undefined &&
extendedFilter(state.language, commas(query.argument.value)).length > 0
)
}
/**
* Check whether an element matches a `:last-child` pseudo.
*
* @param {AstPseudoClass} query
* Query.
* @param {Element} _1
* Element.
* @param {number | undefined} _2
* Index of `element` in `parent`.
* @param {Parents | undefined} _3
* Parent of `element`.
* @param {State} state
* State.
* @returns {boolean}
* Whether `element` matches `query`.
*/
function lastChild(query, _1, _2, _3, state) {
assertDeep(state, query)
return Boolean(
state.elementCount && state.elementIndex === state.elementCount - 1
)
}
/**
* Check whether an element matches a `:last-of-type` pseudo.
*
* @param {AstPseudoClass} query
* Query.
* @param {Element} _1
* Element.
* @param {number | undefined} _2
* Index of `element` in `parent`.
* @param {Parents | undefined} _3
* Parent of `element`.
* @param {State} state
* State.
* @returns {boolean}
* Whether `element` matches `query`.
*/
function lastOfType(query, _1, _2, _3, state) {
assertDeep(state, query)
return (
typeof state.typeIndex === 'number' &&
typeof state.typeCount === 'number' &&
state.typeIndex === state.typeCount - 1
)
}
/**
* Check whether an element does `:not` match further selectors.
*
* @param {AstPseudoClass} query
* Query.
* @param {Element} element
* Element.
* @param {number | undefined} index
* Index of `element` in `parent`.
* @param {Parents | undefined} parent
* Parent of `element`.
* @param {State} state
* State.
* @returns {boolean}
* Whether `element` matches `query`.
*/
function not(query, element, index, parent, state) {
return !is(query, element, index, parent, state)
}
/**
* Check whether an element matches an `:nth-child` pseudo.
*
* @param {AstPseudoClass} query
* Query.
* @param {Element} _1
* Element.
* @param {number | undefined} _2
* Index of `element` in `parent`.
* @param {Parents | undefined} _3
* Parent of `element`.
* @param {State} state
* State.
* @returns {boolean}
* Whether `element` matches `query`.
*/
function nthChild(query, _1, _2, _3, state) {
const fn = getCachedNthCheck(query)
assertDeep(state, query)
return typeof state.elementIndex === 'number' && fn(state.elementIndex)
}
/**
* Check whether an element matches an `:nth-last-child` pseudo.
*
* @param {AstPseudoClass} query
* Query.
* @param {Element} _1
* Element.
* @param {number | undefined} _2
* Index of `element` in `parent`.
* @param {Parents | undefined} _3
* Parent of `element`.
* @param {State} state
* State.
* @returns {boolean}
* Whether `element` matches `query`.
*/
function nthLastChild(query, _1, _2, _3, state) {
const fn = getCachedNthCheck(query)
assertDeep(state, query)
return Boolean(
typeof state.elementCount === 'number' &&
typeof state.elementIndex === 'number' &&
fn(state.elementCount - state.elementIndex - 1)
)
}
/**
* Check whether an element matches a `:nth-last-of-type` pseudo.
*
* @param {AstPseudoClass} query
* Query.
* @param {Element} _1
* Element.
* @param {number | undefined} _2
* Index of `element` in `parent`.
* @param {Parents | undefined} _3
* Parent of `element`.
* @param {State} state
* State.
* @returns {boolean}
* Whether `element` matches `query`.
*/
function nthLastOfType(query, _1, _2, _3, state) {
const fn = getCachedNthCheck(query)
assertDeep(state, query)
return (
typeof state.typeCount === 'number' &&
typeof state.typeIndex === 'number' &&
fn(state.typeCount - 1 - state.typeIndex)
)
}
/**
* Check whether an element matches an `:nth-of-type` pseudo.
*
* @param {AstPseudoClass} query
* Query.
* @param {Element} _1
* Element.
* @param {number | undefined} _2
* Index of `element` in `parent`.
* @param {Parents | undefined} _3
* Parent of `element`.
* @param {State} state
* State.
* @returns {boolean}
* Whether `element` matches `query`.
*/
function nthOfType(query, _1, _2, _3, state) {
const fn = getCachedNthCheck(query)
assertDeep(state, query)
return typeof state.typeIndex === 'number' && fn(state.typeIndex)
}
/**
* Check whether an element matches an `:only-child` pseudo.
*
* @param {AstPseudoClass} query
* Query.
* @param {Element} _1
* Element.
* @param {number | undefined} _2
* Index of `element` in `parent`.
* @param {Parents | undefined} _3
* Parent of `element`.
* @param {State} state
* State.
* @returns {boolean}
* Whether `element` matches `query`.
*/
function onlyChild(query, _1, _2, _3, state) {
assertDeep(state, query)
return state.elementCount === 1
}
/**
* Check whether an element matches an `:only-of-type` pseudo.
*
* @param {AstPseudoClass} query
* Query.
* @param {Element} _1
* Element.
* @param {number | undefined} _2
* Index of `element` in `parent`.
* @param {Parents | undefined} _3
* Parent of `element`.
* @param {State} state
* State.
* @returns {boolean}
* Whether `element` matches `query`.
*/
function onlyOfType(query, _1, _2, _3, state) {
assertDeep(state, query)
return state.typeCount === 1
}
/**
* Check whether an element matches an `:optional` pseudo.
*
* @param {AstPseudoClass} query
* Query.
* @param {Element} element
* Element.
* @returns {boolean}
* Whether `element` matches `query`.
*/
function optional(query, element) {
return !required(query, element)
}
/**
* Check whether an element matches a `:read-only` pseudo.
*
* @param {AstPseudoClass} query
* Query.
* @param {Element} element
* Element.
* @param {number | undefined} index
* Index of `element` in `parent`.
* @param {Parents | undefined} parent
* Parent of `element`.
* @param {State} state
* State.
* @returns {boolean}
* Whether `element` matches `query`.
*/
function readOnly(query, element, index, parent, state) {
return !readWrite(query, element, index, parent, state)
}
/**
* Check whether an element matches a `:read-write` pseudo.
*
* @param {AstPseudoClass} _
* Query.
* @param {Element} element
* Element.
* @param {number | undefined} _1
* Index of `element` in `parent`.
* @param {Parents | undefined} _2
* Parent of `element`.
* @param {State} state
* State.
* @returns {boolean}
* Whether `element` matches `query`.
*/
function readWrite(_, element, _1, _2, state) {
return element.tagName === 'input' || element.tagName === 'textarea'
? !hasProperty(element, 'readOnly') && !hasProperty(element, 'disabled')
: Boolean(state.editableOrEditingHost)
}
/**
* Check whether an element matches a `:required` pseudo.
*
* @param {AstPseudoClass} _
* Query.
* @param {Element} element
* Element.
* @returns {boolean}
* Whether `element` matches `query`.
*/
function required(_, element) {
return (
(element.tagName === 'input' ||
element.tagName === 'textarea' ||
element.tagName === 'select') &&
hasProperty(element, 'required')
)
}
/**
* Check whether an element matches a `:root` pseudo.
*
* @param {AstPseudoClass} _1
* Query.
* @param {Element} element
* Element.
* @param {number | undefined} _2
* Index of `element` in `parent`.
* @param {Parents | undefined} parent
* Parent of `element`.
* @param {State} state
* State.
* @returns {boolean}
* Whether `element` matches `query`.
*/
function root(_1, element, _2, parent, state) {
return Boolean(
(!parent || parent.type === 'root') &&
state.schema &&
(state.schema.space === 'html' || state.schema.space === 'svg') &&
(element.tagName === 'html' || element.tagName === 'svg')
)
}
/**
* Check whether an element matches a `:scope` pseudo.
*
* @param {AstPseudoClass} _1
* Query.
* @param {Element} element
* Element.
* @param {number | undefined} _2
* Index of `element` in `parent`.
* @param {Parents | undefined} _3
* Parent of `element`.
* @param {State} state
* State.
* @returns {boolean}
* Whether `element` matches `query`.
*/
function scope(_1, element, _2, _3, state) {
return state.scopeElements.includes(element)
}
/**
* Check children.
*
* @param {Element} element
* Element.
* @param {(child: ElementContent) => boolean} check
* Check.
* @returns {boolean}
* Whether a child of `element` matches `check`.
*/
function someChildren(element, check) {
const children = element.children
let index = -1
while (++index < children.length) {
if (check(children[index])) return true
}
return false
}
/**
* @param {unknown} query_
* Query-like value.
* @returns {never}
* Nothing.
* @throws
* Exception.
*/
function unknownPseudo(query_) {
// Runtime JS guarantees it has a `name`.
const query = /** @type {AstPseudoClass} */ (query_)
throw new Error('Unknown pseudo-selector `' + query.name + '`')
}

21
node_modules/hast-util-select/lib/test.d.ts generated vendored Normal file
View File

@@ -0,0 +1,21 @@
/**
* Test a rule.
*
* @param {AstRule} query
* AST rule (with `pseudoClasses`).
* @param {Element} element
* Element.
* @param {number | undefined} index
* Index of `element` in `parent`.
* @param {Parents | undefined} parent
* Parent of `element`.
* @param {State} state
* State.
* @returns {boolean}
* Whether `element` matches `query`.
*/
export function test(query: AstRule, element: Element, index: number | undefined, parent: Parents | undefined, state: State): boolean;
export type AstRule = import('css-selector-parser').AstRule;
export type Element = import('hast').Element;
export type Parents = import('hast').Parents;
export type State = import('./index.js').State;

53
node_modules/hast-util-select/lib/test.js generated vendored Normal file
View File

@@ -0,0 +1,53 @@
/**
* @typedef {import('css-selector-parser').AstRule} AstRule
*
* @typedef {import('hast').Element} Element
* @typedef {import('hast').Parents} Parents
*
* @typedef {import('./index.js').State} State
*/
import {attribute} from './attribute.js'
import {className} from './class-name.js'
import {id} from './id.js'
import {name} from './name.js'
import {pseudo} from './pseudo.js'
/**
* Test a rule.
*
* @param {AstRule} query
* AST rule (with `pseudoClasses`).
* @param {Element} element
* Element.
* @param {number | undefined} index
* Index of `element` in `parent`.
* @param {Parents | undefined} parent
* Parent of `element`.
* @param {State} state
* State.
* @returns {boolean}
* Whether `element` matches `query`.
*/
export function test(query, element, index, parent, state) {
for (const item of query.items) {
// eslint-disable-next-line unicorn/prefer-switch
if (item.type === 'Attribute') {
if (!attribute(item, element, state.schema)) return false
} else if (item.type === 'Id') {
if (!id(item, element)) return false
} else if (item.type === 'ClassName') {
if (!className(item, element)) return false
} else if (item.type === 'PseudoClass') {
if (!pseudo(item, element, index, parent, state)) return false
} else if (item.type === 'PseudoElement') {
throw new Error('Invalid selector: `::' + item.name + '`')
} else if (item.type === 'TagName') {
if (!name(item, element)) return false
} else {
// Otherwise `item.type` is `WildcardTag`, which matches.
}
}
return true
}

48
node_modules/hast-util-select/lib/walk.d.ts generated vendored Normal file
View File

@@ -0,0 +1,48 @@
/**
* Walk a tree.
*
* @param {State} state
* State.
* @param {Nodes | undefined} tree
* Tree.
*/
export function walk(state: State, tree: Nodes | undefined): void;
export type AstRule = import('css-selector-parser').AstRule;
export type Element = import('hast').Element;
export type Nodes = import('hast').Nodes;
export type Parents = import('hast').Parents;
export type State = import('./index.js').State;
/**
* Info on elements in a parent.
*/
export type Counts = {
/**
* Number of elements.
*/
count: number;
/**
* Number of elements by tag name.
*/
types: Map<string, number>;
};
/**
* Rule sets by nesting.
*/
export type Nest = {
/**
* `a + b`
*/
adjacentSibling: Array<AstRule> | undefined;
/**
* `a b`
*/
descendant: Array<AstRule> | undefined;
/**
* `a > b`
*/
directChild: Array<AstRule> | undefined;
/**
* `a ~ b`
*/
generalSibling: Array<AstRule> | undefined;
};

329
node_modules/hast-util-select/lib/walk.js generated vendored Normal file
View File

@@ -0,0 +1,329 @@
/**
* @typedef {import('css-selector-parser').AstRule} AstRule
*
* @typedef {import('hast').Element} Element
* @typedef {import('hast').Nodes} Nodes
* @typedef {import('hast').Parents} Parents
*
* @typedef {import('./index.js').State} State
*/
/**
* @typedef Counts
* Info on elements in a parent.
* @property {number} count
* Number of elements.
* @property {Map<string, number>} types
* Number of elements by tag name.
*
* @typedef Nest
* Rule sets by nesting.
* @property {Array<AstRule> | undefined} adjacentSibling
* `a + b`
* @property {Array<AstRule> | undefined} descendant
* `a b`
* @property {Array<AstRule> | undefined} directChild
* `a > b`
* @property {Array<AstRule> | undefined} generalSibling
* `a ~ b`
*/
import {enterState} from './enter-state.js'
import {test} from './test.js'
/** @type {Array<never>} */
const empty = []
/**
* Walk a tree.
*
* @param {State} state
* State.
* @param {Nodes | undefined} tree
* Tree.
*/
export function walk(state, tree) {
if (tree) {
one(state, [], tree, undefined, undefined, tree)
}
}
/**
* Add a rule to a nesting map.
*
* @param {Nest} nest
* Nesting.
* @param {keyof Nest} field
* Field.
* @param {AstRule} rule
* Rule.
*/
function add(nest, field, rule) {
const list = nest[field]
if (list) {
list.push(rule)
} else {
nest[field] = [rule]
}
}
/**
* Check in a parent.
*
* @param {State} state
* State.
* @param {Nest} nest
* Nesting.
* @param {Parents} node
* Parent.
* @param {Nodes} tree
* Tree.
* @returns {undefined}
* Nothing.
*/
function all(state, nest, node, tree) {
const fromParent = combine(nest.descendant, nest.directChild)
/** @type {Array<AstRule> | undefined} */
let fromSibling
let index = -1
/**
* Total counts.
* @type {Counts}
*/
const total = {count: 0, types: new Map()}
/**
* Counts of previous siblings.
* @type {Counts}
*/
const before = {count: 0, types: new Map()}
while (++index < node.children.length) {
count(total, node.children[index])
}
index = -1
while (++index < node.children.length) {
const child = node.children[index]
// Uppercase to prevent prototype polution, injecting `constructor` or so.
// Normalize because HTML is insensitive.
const name =
child.type === 'element' ? child.tagName.toUpperCase() : undefined
// Before counting further elements:
state.elementIndex = before.count
state.typeIndex = name ? before.types.get(name) || 0 : 0
// After counting all elements.
state.elementCount = total.count
state.typeCount = name ? total.types.get(name) : 0
// Only apply if this is a parent, this should be an element, but we check
// for parents so that we delve into custom nodes too.
if ('children' in child) {
const forSibling = combine(fromParent, fromSibling)
const nest = one(
state,
forSibling,
node.children[index],
index,
node,
tree
)
fromSibling = combine(nest.generalSibling, nest.adjacentSibling)
}
// We found one thing, and one is enough.
if (state.one && state.found) {
break
}
count(before, node.children[index])
}
}
/**
* Apply selectors to an element.
*
* @param {State} state
* Current state.
* @param {Array<AstRule>} rules
* Rules to apply.
* @param {Element} node
* Element to apply rules to.
* @param {number | undefined} index
* Index of `node` in `parent`.
* @param {Parents | undefined} parent
* Parent of `node`.
* @returns {Nest}
* Further rules.
*/
function applySelectors(state, rules, node, index, parent) {
/** @type {Nest} */
const nestResult = {
adjacentSibling: undefined,
descendant: undefined,
directChild: undefined,
generalSibling: undefined
}
let selectorIndex = -1
while (++selectorIndex < rules.length) {
const rule = rules[selectorIndex]
// We found one thing, and one is enough.
if (state.one && state.found) {
break
}
// When shallow, we dont allow nested rules.
// Idea: we could allow a stack of parents?
// Might get quite complex though.
if (state.shallow && rule.nestedRule) {
throw new Error('Expected selector without nesting')
}
// If this rule matches:
if (test(rule, node, index, parent, state)) {
const nest = rule.nestedRule
// Are there more?
if (nest) {
/** @type {keyof Nest} */
const label =
nest.combinator === '+'
? 'adjacentSibling'
: nest.combinator === '~'
? 'generalSibling'
: nest.combinator === '>'
? 'directChild'
: 'descendant'
add(nestResult, label, nest)
} else {
// We have a match!
state.found = true
if (!state.results.includes(node)) {
state.results.push(node)
}
}
}
// Descendant.
if (rule.combinator === undefined) {
add(nestResult, 'descendant', rule)
}
// Adjacent.
else if (rule.combinator === '~') {
add(nestResult, 'generalSibling', rule)
}
// Drop direct child (`>`), adjacent sibling (`+`).
}
return nestResult
}
/**
* Combine two lists, if needed.
*
* This is optimized to create as few lists as possible.
*
* @param {Array<AstRule> | undefined} left
* Rules.
* @param {Array<AstRule> | undefined} right
* Rules.
* @returns {Array<AstRule>}
* Rules.
*/
function combine(left, right) {
return left && right && left.length > 0 && right.length > 0
? [...left, ...right]
: left && left.length > 0
? left
: right && right.length > 0
? right
: empty
}
/**
* Count a node.
*
* @param {Counts} counts
* Counts.
* @param {Nodes} node
* Node (were looking for elements).
* @returns {undefined}
* Nothing.
*/
function count(counts, node) {
if (node.type === 'element') {
// Uppercase to prevent prototype polution, injecting `constructor` or so.
// Normalize because HTML is insensitive.
const name = node.tagName.toUpperCase()
const count = (counts.types.get(name) || 0) + 1
counts.count++
counts.types.set(name, count)
}
}
/**
* Check a node.
*
* @param {State} state
* State.
* @param {Array<AstRule>} currentRules
* Rules.
* @param {Nodes} node
* Node.
* @param {number | undefined} index
* Index of `node` in `parent`.
* @param {Parents | undefined} parent
* Parent of `node`.
* @param {Nodes} tree
* Tree.
* @returns {Nest}
* Nesting.
*/
function one(state, currentRules, node, index, parent, tree) {
/** @type {Nest} */
let nestResult = {
adjacentSibling: undefined,
descendant: undefined,
directChild: undefined,
generalSibling: undefined
}
const exit = enterState(state, node)
if (node.type === 'element') {
let rootRules = state.rootQuery.rules
// Remove direct child rules if this is the root.
// This only happens for a `:has()` rule, which can be like
// `a:has(> b)`.
if (parent && parent !== tree) {
rootRules = state.rootQuery.rules.filter(
(d) =>
d.combinator === undefined ||
(d.combinator === '>' && parent === tree)
)
}
nestResult = applySelectors(
state,
// Try the root rules for this element too.
combine(currentRules, rootRules),
node,
index,
parent
)
}
// If this is a parent, and we want to delve into them, and we havent found
// our single result yet.
if ('children' in node && !state.shallow && !(state.one && state.found)) {
all(state, nestResult, node, tree)
}
exit()
return nestResult
}

22
node_modules/hast-util-select/license generated vendored Normal file
View File

@@ -0,0 +1,22 @@
(The MIT License)
Copyright (c) 2017 Titus Wormer <tituswormer@gmail.com>
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
'Software'), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

115
node_modules/hast-util-select/package.json generated vendored Normal file
View File

@@ -0,0 +1,115 @@
{
"name": "hast-util-select",
"version": "6.0.2",
"description": "hast utility for `querySelector`, `querySelectorAll`, and `matches`",
"license": "MIT",
"keywords": [
"unist",
"hast",
"hast-util",
"util",
"utility",
"html",
"css",
"select",
"selectall",
"selector",
"query",
"match",
"matches"
],
"repository": "syntax-tree/hast-util-select",
"bugs": "https://github.com/syntax-tree/hast-util-select/issues",
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/unified"
},
"author": "Titus Wormer <tituswormer@gmail.com> (https://wooorm.com)",
"contributors": [
"Titus Wormer <tituswormer@gmail.com> (https://wooorm.com)"
],
"sideEffects": false,
"type": "module",
"exports": "./index.js",
"files": [
"lib/",
"index.d.ts",
"index.js"
],
"dependencies": {
"@types/hast": "^3.0.0",
"@types/unist": "^3.0.0",
"bcp-47-match": "^2.0.0",
"comma-separated-tokens": "^2.0.0",
"css-selector-parser": "^3.0.0",
"devlop": "^1.0.0",
"direction": "^2.0.0",
"hast-util-has-property": "^3.0.0",
"hast-util-to-string": "^3.0.0",
"hast-util-whitespace": "^3.0.0",
"not": "^0.1.0",
"nth-check": "^2.0.0",
"property-information": "^6.0.0",
"space-separated-tokens": "^2.0.0",
"unist-util-visit": "^5.0.0",
"zwitch": "^2.0.0"
},
"devDependencies": {
"@types/node": "^20.0.0",
"c8": "^8.0.0",
"hastscript": "^8.0.0",
"prettier": "^3.0.0",
"remark-cli": "^11.0.0",
"remark-preset-wooorm": "^9.0.0",
"type-coverage": "^2.0.0",
"typescript": "^5.0.0",
"unist-builder": "^4.0.0",
"xo": "^0.56.0"
},
"scripts": {
"prepack": "npm run build && npm run format",
"build": "tsc --build --clean && tsc --build && type-coverage",
"format": "remark . -qfo && prettier . -w --log-level warn && xo --fix",
"test-api": "node --conditions development test/index.js",
"test-coverage": "c8 --100 --reporter lcov npm run test-api",
"test": "npm run build && npm run format && npm run test-coverage"
},
"prettier": {
"bracketSpacing": false,
"semi": false,
"singleQuote": true,
"tabWidth": 2,
"trailingComma": "none",
"useTabs": false
},
"remarkConfig": {
"plugins": [
"remark-preset-wooorm"
]
},
"typeCoverage": {
"atLeast": 100,
"detail": true,
"ignoreCatch": true,
"strict": true
},
"xo": {
"overrides": [
{
"files": [
"test/**/*.js"
],
"rules": {
"import/no-unassigned-import": "off",
"max-nested-callbacks": "off",
"no-await-in-loop": "off"
}
}
],
"prettier": true,
"rules": {
"max-params": "off",
"unicorn/prefer-at": "off"
}
}
}

484
node_modules/hast-util-select/readme.md generated vendored Normal file
View File

@@ -0,0 +1,484 @@
# hast-util-select
[![Build][build-badge]][build]
[![Coverage][coverage-badge]][coverage]
[![Downloads][downloads-badge]][downloads]
[![Size][size-badge]][size]
[![Sponsors][sponsors-badge]][collective]
[![Backers][backers-badge]][collective]
[![Chat][chat-badge]][chat]
[hast][] utility with equivalents for `matches`, `querySelector`,
and `querySelectorAll`.
## Contents
* [What is this?](#what-is-this)
* [When should I use this?](#when-should-i-use-this)
* [Install](#install)
* [Use](#use)
* [API](#api)
* [`matches(selector, node[, space])`](#matchesselector-node-space)
* [`select(selector, tree[, space])`](#selectselector-tree-space)
* [`selectAll(selector, tree[, space])`](#selectallselector-tree-space)
* [`Space`](#space)
* [Support](#support)
* [Unsupported](#unsupported)
* [Types](#types)
* [Compatibility](#compatibility)
* [Security](#security)
* [Related](#related)
* [Contribute](#contribute)
* [License](#license)
## What is this?
This package lets you find nodes in a tree, similar to how `matches`,
`querySelector`, and `querySelectorAll` work with the DOM.
One notable difference between DOM and hast is that DOM nodes have references
to their parents, meaning that `document.body.matches(':last-child')` can
be evaluated to check whether the body is the last child of its parent.
This information is not stored in hast, so selectors like that dont work.
## When should I use this?
This is a small utility that is quite useful, but is rather slow if you use it a
lot.
For each call, it has to walk the entire tree.
In some cases, walking the tree once with [`unist-util-visit`][unist-util-visit]
is smarter, such as when you want to change certain nodes.
On the other hand, this is quite powerful and fast enough for many other cases.
This utility is similar to [`unist-util-select`][unist-util-select], which can
find and match any unist node.
## Install
This package is [ESM only][esm].
In Node.js (version 16+), install with [npm][]:
```sh
npm install hast-util-select
```
In Deno with [`esm.sh`][esmsh]:
```js
import {matches, select, selectAll} from "https://esm.sh/hast-util-select@6"
```
In browsers with [`esm.sh`][esmsh]:
```html
<script type="module">
import {matches, select, selectAll} from "https://esm.sh/hast-util-select@6?bundle"
</script>
```
## Use
```js
import {h} from 'hastscript'
import {matches, select, selectAll} from 'hast-util-select'
const tree = h('section', [
h('p', 'Alpha'),
h('p', 'Bravo'),
h('h1', 'Charlie'),
h('p', 'Delta'),
h('p', 'Echo'),
h('p', 'Foxtrot'),
h('p', 'Golf')
])
console.log(matches('section', tree)) // `true`
console.log(select('h1 ~ :nth-child(even)', tree))
// The paragraph with `Delta`
console.log(selectAll('h1 ~ :nth-child(even)', tree))
// The paragraphs with `Delta` and `Foxtrot`
```
## API
This package exports the identifiers [`matches`][api-matches],
[`select`][api-select], and [`selectAll`][api-select-all].
There is no default export.
### `matches(selector, node[, space])`
Check that the given `node` matches `selector`.
This only checks the element itself, not the surrounding tree.
Thus, nesting in selectors is not supported (`p b`, `p > b`), neither are
selectors like `:first-child`, etc.
This only checks that the given element matches the selector.
###### Parameters
* `selector` (`string`)
— CSS selector, such as (`h1`, `a, b`)
* `node` ([`Node`][node], optional)
— node that might match `selector`, should be an element
* `space` ([`Space`][api-space], default: `'html'`)
— name of namespace
###### Returns
Whether `node` matches `selector` (`boolean`).
###### Example
```js
import {h} from 'hastscript'
import {matches} from 'hast-util-select'
matches('b, i', h('b')) // => true
matches(':any-link', h('a')) // => false
matches(':any-link', h('a', {href: '#'})) // => true
matches('.classy', h('a', {className: ['classy']})) // => true
matches('#id', h('a', {id: 'id'})) // => true
matches('[lang|=en]', h('a', {lang: 'en'})) // => true
matches('[lang|=en]', h('a', {lang: 'en-GB'})) // => true
```
### `select(selector, tree[, space])`
Select the first element that matches `selector` in the given `tree`.
Searches the tree in *[preorder][]*.
###### Parameters
* `selector` (`string`)
— CSS selector, such as (`h1`, `a, b`)
* `tree` ([`Node`][node], optional)
— tree to search
* `space` ([`Space`][api-space], default: `'html'`)
— name of namespace
###### Returns
First element in `tree` that matches `selector` or `undefined` if nothing is
found.
This could be `tree` itself.
###### Example
```js
import {h} from 'hastscript'
import {select} from 'hast-util-select'
console.log(
select(
'h1 ~ :nth-child(even)',
h('section', [
h('p', 'Alpha'),
h('p', 'Bravo'),
h('h1', 'Charlie'),
h('p', 'Delta'),
h('p', 'Echo')
])
)
)
```
Yields:
```js
{ type: 'element',
tagName: 'p',
properties: {},
children: [ { type: 'text', value: 'Delta' } ] }
```
### `selectAll(selector, tree[, space])`
Select all elements that match `selector` in the given `tree`.
Searches the tree in *[preorder][]*.
###### Parameters
* `selector` (`string`)
— CSS selector, such as (`h1`, `a, b`)
* `tree` ([`Node`][node], optional)
— tree to search
* `space` ([`Space`][api-space], default: `'html'`)
— name of namespace
###### Returns
Elements in `tree` that match `selector`.
This could include `tree` itself.
###### Example
```js
import {h} from 'hastscript'
import {selectAll} from 'hast-util-select'
console.log(
selectAll(
'h1 ~ :nth-child(even)',
h('section', [
h('p', 'Alpha'),
h('p', 'Bravo'),
h('h1', 'Charlie'),
h('p', 'Delta'),
h('p', 'Echo'),
h('p', 'Foxtrot'),
h('p', 'Golf')
])
)
)
```
Yields:
```js
[ { type: 'element',
tagName: 'p',
properties: {},
children: [ { type: 'text', value: 'Delta' } ] },
{ type: 'element',
tagName: 'p',
properties: {},
children: [ { type: 'text', value: 'Foxtrot' } ] } ]
```
### `Space`
Namespace (TypeScript type).
###### Type
```ts
type Space = 'html' | 'svg'
```
## Support
* [x] `*` (universal selector)
* [x] `,` (multiple selector)
* [x] `p` (type selector)
* [x] `.class` (class selector)
* [x] `#id` (id selector)
* [x] `article p` (combinator: descendant selector)
* [x] `article > p` (combinator: child selector)
* [x] `h1 + p` (combinator: next-sibling selector)
* [x] `h1 ~ p` (combinator: subsequent sibling selector)
* [x] `[attr]` (attribute existence)
* [x] `[attr… i]` (attribute case-insensitive)
* [x] `[attr… s]` (attribute case-sensitive) (useless, default)
* [x] `[attr=value]` (attribute equality)
* [x] `[attr~=value]` (attribute contains in space-separated list)
* [x] `[attr|=value]` (attribute equality or prefix)
* [x] `[attr^=value]` (attribute begins with)
* [x] `[attr$=value]` (attribute ends with)
* [x] `[attr*=value]` (attribute contains)
* [x] `:dir()` (functional pseudo-class)
* [x] `:has()` (functional pseudo-class; also supports `a:has(> b)`)
* [x] `:is()` (functional pseudo-class)
* [x] `:lang()` (functional pseudo-class)
* [x] `:not()` (functional pseudo-class)
* [x] `:any-link` (pseudo-class)
* [x] `:blank` (pseudo-class)
* [x] `:checked` (pseudo-class)
* [x] `:disabled` (pseudo-class)
* [x] `:empty` (pseudo-class)
* [x] `:enabled` (pseudo-class)
* [x] `:optional` (pseudo-class)
* [x] `:read-only` (pseudo-class)
* [x] `:read-write` (pseudo-class)
* [x] `:required` (pseudo-class)
* [x] `:root` (pseudo-class)
* [x] `:scope` (pseudo-class):
* [x] \* `:first-child` (pseudo-class)
* [x] \* `:first-of-type` (pseudo-class)
* [x] \* `:last-child` (pseudo-class)
* [x] \* `:last-of-type` (pseudo-class)
* [x] \* `:only-child` (pseudo-class)
* [x] \* `:only-of-type` (pseudo-class)
* [x] \* `:nth-child()` (functional pseudo-class)
* [x] \* `:nth-last-child()` (functional pseudo-class)
* [x] \* `:nth-last-of-type()` (functional pseudo-class)
* [x] \* `:nth-of-type()` (functional pseudo-class)
## Unsupported
* [ ] † `||` (column combinator)
* [ ] † `ns|E` (namespace type selector)
* [ ] † `*|E` (any namespace type selector)
* [ ] † `|E` (no namespace type selector)
* [ ] † `[ns|attr]` (namespace attribute)
* [ ] † `[*|attr]` (any namespace attribute)
* [ ] † `[|attr]` (no namespace attribute)
* [ ] ‖ `:nth-child(n of S)` (functional pseudo-class, note: scoping to
parents is not supported)
* [ ] ‖ `:nth-last-child(n of S)` (functional pseudo-class, note: scoping to
parents is not supported)
* [ ] † `:active` (pseudo-class)
* [ ] † `:autofill` (pseudo-class)
* [ ] † `:buffering` (pseudo-class)
* [ ] § `:closed` (pseudo-class)
* [ ] † `:current` (pseudo-class)
* [ ] † `:current()` (functional pseudo-class)
* [ ] † `:default` (pseudo-class)
* [ ] † `:defined` (pseudo-class)
* [ ] † `:focus` (pseudo-class)
* [ ] † `:focus-visible` (pseudo-class)
* [ ] † `:focus-within` (pseudo-class)
* [ ] † `:fullscreen` (pseudo-class)
* [ ] † `:future` (pseudo-class)
* [ ] § `:host()` (functional pseudo-class)
* [ ] § `:host-context()` (functional pseudo-class)
* [ ] † `:hover` (pseudo-class)
* [ ] ‡ `:in-range` (pseudo-class)
* [ ] † `:indeterminate` (pseudo-class)
* [ ] ‡ `:invalid` (pseudo-class)
* [ ] † `:link` (pseudo-class)
* [ ] † `:local-link` (pseudo-class)
* [ ] † `:modal` (pseudo-class)
* [ ] † `:muted` (pseudo-class)
* [ ] † `:nth-col()` (functional pseudo-class)
* [ ] † `:nth-last-col()` (functional pseudo-class)
* [ ] § `:open` (pseudo-class)
* [ ] ‡ `:out-of-range` (pseudo-class)
* [ ] † `:past` (pseudo-class)
* [ ] † `:paused` (pseudo-class)
* [ ] † `:placeholder-shown` (pseudo-class)
* [ ] † `:playing` (pseudo-class)
* [ ] † `:seeking` (pseudo-class)
* [ ] † `:stalled` (pseudo-class)
* [ ] † `:target` (pseudo-class)
* [ ] † `:target-within` (pseudo-class)
* [ ] † `:user-invalid` (pseudo-class)
* [ ] ‡ `:valid` (pseudo-class)
* [ ] † `:visited` (pseudo-class)
* [ ] † `:volume-locked` (pseudo-class)
* [ ] § `:where()` (functional pseudo-class)
* [ ] † `::before` (pseudo-elements: none are supported)
###### Notes
* \* — not supported in `matches`
* † — needs a user, browser, interactivity, scripting, or whole CSS to make
sense
* ‡ — not very interested in writing / including the code for this
* § — too new, the spec is still changing
* ‖ — pr wanted!
* `:any()` and `:matches()` are renamed to `:is()` in CSS.
## Types
This package is fully typed with [TypeScript][].
It exports the additional type [`Space`][api-space].
## Compatibility
Projects maintained by the unified collective are compatible with maintained
versions of Node.js.
When we cut a new major release, we drop support for unmaintained versions of
Node.
This means we try to keep the current release line, `hast-util-select@^6`,
compatible with Node.js 16.
## Security
This package does not change the syntax tree so there are no openings for
[cross-site scripting (XSS)][xss] attacks.
## Related
* [`unist-util-select`](https://github.com/syntax-tree/unist-util-select)
— select unist nodes with CSS-like selectors
* [`hast-util-find-and-replace`](https://github.com/syntax-tree/hast-util-find-and-replace)
— find and replace text in a hast tree
* [`hast-util-parse-selector`](https://github.com/syntax-tree/hast-util-parse-selector)
— create an element from a simple CSS selector
* [`hast-util-from-selector`](https://github.com/syntax-tree/hast-util-from-selector)
— create an element from a complex CSS selector
## Contribute
See [`contributing.md`][contributing] in [`syntax-tree/.github`][health] for
ways to get started.
See [`support.md`][help] for ways to get help.
This project has a [code of conduct][coc].
By interacting with this repository, organization, or community you agree to
abide by its terms.
## License
[MIT][license] © [Titus Wormer][author]
<!-- Definitions -->
[build-badge]: https://github.com/syntax-tree/hast-util-select/workflows/main/badge.svg
[build]: https://github.com/syntax-tree/hast-util-select/actions
[coverage-badge]: https://img.shields.io/codecov/c/github/syntax-tree/hast-util-select.svg
[coverage]: https://codecov.io/github/syntax-tree/hast-util-select
[downloads-badge]: https://img.shields.io/npm/dm/hast-util-select.svg
[downloads]: https://www.npmjs.com/package/hast-util-select
[size-badge]: https://img.shields.io/badge/dynamic/json?label=minzipped%20size&query=$.size.compressedSize&url=https://deno.bundlejs.com/?q=hast-util-select
[size]: https://bundlejs.com/?q=hast-util-select
[sponsors-badge]: https://opencollective.com/unified/sponsors/badge.svg
[backers-badge]: https://opencollective.com/unified/backers/badge.svg
[collective]: https://opencollective.com/unified
[chat-badge]: https://img.shields.io/badge/chat-discussions-success.svg
[chat]: https://github.com/syntax-tree/unist/discussions
[npm]: https://docs.npmjs.com/cli/install
[esm]: https://gist.github.com/sindresorhus/a39789f98801d908bbc7ff3ecc99d99c
[esmsh]: https://esm.sh
[typescript]: https://www.typescriptlang.org
[license]: license
[author]: https://wooorm.com
[health]: https://github.com/syntax-tree/.github
[contributing]: https://github.com/syntax-tree/.github/blob/main/contributing.md
[help]: https://github.com/syntax-tree/.github/blob/main/support.md
[coc]: https://github.com/syntax-tree/.github/blob/main/code-of-conduct.md
[preorder]: https://github.com/syntax-tree/unist#preorder
[hast]: https://github.com/syntax-tree/hast
[node]: https://github.com/syntax-tree/hast#nodes
[xss]: https://en.wikipedia.org/wiki/Cross-site_scripting
[unist-util-visit]: https://github.com/syntax-tree/unist-util-visit
[unist-util-select]: https://github.com/syntax-tree/unist-util-select
[api-matches]: #matchesselector-node-space
[api-select]: #selectselector-tree-space
[api-select-all]: #selectallselector-tree-space
[api-space]: #space