site/node_modules/unist-util-find-after/lib/index.js
2024-10-14 08:09:33 +02:00

131 lines
3.5 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* @typedef {import('unist').Node} UnistNode
* @typedef {import('unist').Parent} UnistParent
*/
/**
* @typedef {Exclude<import('unist-util-is').Test, undefined> | undefined} Test
* Test from `unist-util-is`.
*
* Note: we have remove and add `undefined`, because otherwise when generating
* automatic `.d.ts` files, TS tries to flatten paths from a local perspective,
* which doesnt work when publishing on npm.
*/
/**
* @typedef {(
* Fn extends (value: any) => value is infer Thing
* ? Thing
* : Fallback
* )} Predicate
* Get the value of a type guard `Fn`.
* @template Fn
* Value; typically function that is a type guard (such as `(x): x is Y`).
* @template Fallback
* Value to yield if `Fn` is not a type guard.
*/
/**
* @typedef {(
* Check extends null | undefined // No test.
* ? Value
* : Value extends {type: Check} // String (type) test.
* ? Value
* : Value extends Check // Partial test.
* ? Value
* : Check extends Function // Function test.
* ? Predicate<Check, Value> extends Value
* ? Predicate<Check, Value>
* : never
* : never // Some other test?
* )} MatchesOne
* Check whether a node matches a primitive check in the type system.
* @template Value
* Value; typically unist `Node`.
* @template Check
* Value; typically `unist-util-is`-compatible test, but not arrays.
*/
/**
* @typedef {(
* Check extends Array<any>
* ? MatchesOne<Value, Check[keyof Check]>
* : MatchesOne<Value, Check>
* )} Matches
* Check whether a node matches a check in the type system.
* @template Value
* Value; typically unist `Node`.
* @template Check
* Value; typically `unist-util-is`-compatible test.
*/
/**
* @typedef {(
* Kind extends {children: Array<infer Child>}
* ? Child
* : never
* )} Child
* Collect nodes that can be parents of `Child`.
* @template {UnistNode} Kind
* All node types.
*/
import {convert} from 'unist-util-is'
/**
* Find the first node in `parent` after another `node` or after an index,
* that passes `test`.
*
* @param parent
* Parent node.
* @param index
* Child node or index.
* @param [test=undefined]
* Test for child to look for (optional).
* @returns
* A child (matching `test`, if given) or `undefined`.
*/
export const findAfter =
// Note: overloads like this are needed to support optional generics.
/**
* @type {(
* (<Kind extends UnistParent, Check extends Test>(parent: Kind, index: Child<Kind> | number, test: Check) => Matches<Child<Kind>, Check> | undefined) &
* (<Kind extends UnistParent>(parent: Kind, index: Child<Kind> | number, test?: null | undefined) => Child<Kind> | undefined)
* )}
*/
(
/**
* @param {UnistParent} parent
* @param {UnistNode | number} index
* @param {Test} [test]
* @returns {UnistNode | undefined}
*/
function (parent, index, test) {
const is = convert(test)
if (!parent || !parent.type || !parent.children) {
throw new Error('Expected parent node')
}
if (typeof index === 'number') {
if (index < 0 || index === Number.POSITIVE_INFINITY) {
throw new Error('Expected positive finite number as index')
}
} else {
index = parent.children.indexOf(index)
if (index < 0) {
throw new Error('Expected child node or index')
}
}
while (++index < parent.children.length) {
if (is(parent.children[index], index, parent)) {
return parent.children[index]
}
}
return undefined
}
)