hast-util-select

utility to add `querySelector`, `querySelectorAll`, and `matches` support for hast

Showing:

Popularity

Downloads/wk

23.7K

GitHub Stars

20

Maintenance

Last Commit

20d ago

Contributors

0

Package

Dependencies

16

License

MIT

Type Definitions

Built-In

Tree-Shakeable

No?

Categories

Readme

hast-util-select

Build Coverage Downloads Size Sponsors Backers Chat

hast utility with equivalents querySelector, querySelectorAll, and matches.

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. This information is not stored in hast, so selectors like that don’t work.

View the list of supported selectors »

Install

This package is ESM only: Node 12+ is needed to use it and it must be imported instead of required.

npm:

npm install hast-util-select

API

This package exports the following identifiers: matches, select, and selectAll. There is no default export.

matches(selector, node[, space])

Check that the given node matches selector. Returns boolean, whether the node matches or not.

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.

Use
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
// ...
Parameters
  • selector (string) — CSS selectors (, is also supported)
  • node (Node) — Thing to check, could be anything, but should be an element
  • space (enum, 'svg' or 'html', default: 'html') — Which space the node exists in
Returns

boolean — Whether the node matches the selector.

select(selector, tree[, space])

Select the first node matching selector in the given tree (could be the tree itself). Searches the tree in preorder.

Use
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:

{ type: 'element',
  tagName: 'p',
  properties: {},
  children: [ { type: 'text', value: 'Delta' } ] }
Parameters
  • selector (string) — CSS selectors (, is also supported)
  • tree (Node) — Tree to search
  • space (enum, 'svg' or 'html', default: 'html') — Which space the tree exists in
Returns

Element? — The found element, if any.

selectAll(selector, tree[, space])

Select all nodes matching selector in the given tree (could include the tree itself). Searches the tree in preorder.

Use
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:

[ { type: 'element',
    tagName: 'p',
    properties: {},
    children: [ { type: 'text', value: 'Delta' } ] },
  { type: 'element',
    tagName: 'p',
    properties: {},
    children: [ { type: 'text', value: 'Foxtrot' } ] } ]
Parameters
  • selector (string) — CSS selectors (, is also supported)
  • tree (Node) — Tree to search
  • space (enum, 'svg' or 'html', default: 'html') — Which space the tree exists in
Returns

Array.<Element> — All found elements, if any.

Support

  • * (universal selector)
  • , (multiple selector)
  • p (type selector)
  • .class (class selector)
  • #id (id selector)
  • article p (combinator: descendant selector)
  • article > p (combinator: child selector)
  • h1 + p (combinator: next-sibling selector)
  • h1 ~ p (combinator: subsequent sibling selector)
  • [attr] (attribute existence)
  • [attr=value] (attribute equality)
  • [attr~=value] (attribute contains in space-separated list)
  • [attr|=value] (attribute equality or prefix)
  • [attr^=value] (attribute begins with)
  • [attr$=value] (attribute ends with)
  • [attr*=value] (attribute contains)
  • :any() (functional pseudo-class, use :matches instead)
  • :dir() (functional pseudo-class)
  • :has() (functional pseudo-class)
  • :lang() (functional pseudo-class)
  • :matches() (functional pseudo-class)
  • :not() (functional pseudo-class)
  • :any-link (pseudo-class)
  • :blank (pseudo-class)
  • :checked (pseudo-class)
  • :disabled (pseudo-class)
  • :empty (pseudo-class)
  • :enabled (pseudo-class)
  • :optional (pseudo-class)
  • :read-only (pseudo-class)
  • :read-write (pseudo-class)
  • :required (pseudo-class)
  • :root (pseudo-class)
  • :scope (pseudo-class):
  • * :first-child (pseudo-class)
  • * :first-of-type (pseudo-class)
  • * :last-child (pseudo-class)
  • * :last-of-type (pseudo-class)
  • * :only-child (pseudo-class)
  • * :only-of-type (pseudo-class)
  • * :nth-child() (functional pseudo-class)
  • * :nth-last-child() (functional pseudo-class)
  • * :nth-last-of-type() (functional pseudo-class)
  • * :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)
  • [attr=value i] (attribute case-insensitive)
  • :has() (functional pseudo-class). Relative selectors (:has(> img)) are not supported, but scope is (:has(:scope > img))
  • :nth-child(n of S) (functional pseudo-class). Scoping to parents is not supported
  • :nth-last-child(n of S) (scoped to parent S). Scoping to parents is not supported
  • :active (pseudo-class)
  • :current (pseudo-class)
  • :current() (functional pseudo-class)
  • :default (pseudo-class)
  • :defined (pseudo-class)
  • :drop (pseudo-class)
  • :drop() (functional 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)
  • :nth-column() (functional pseudo-class)
  • :nth-last-column() (functional pseudo-class)
  • § :out-of-range (pseudo-class)
  • :past (pseudo-class)
  • :paused (pseudo-class)
  • :placeholder-shown (pseudo-class)
  • :playing (pseudo-class)
  • :something() (functional pseudo-class)
  • :target (pseudo-class)
  • :target-within (pseudo-class)
  • :user-error (pseudo-class)
  • :user-invalid (pseudo-class)
  • § :valid (pseudo-class)
  • :visited (pseudo-class)
  • ::before (pseudo-elements: none are supported)
Notes
  • * — Not supported in matches
  • † — Needs a user, browser, interactivity, or scripting to make sense
  • ‡ — Not supported by the underlying algorithm
  • § — Not very interested in writing / including the code for this
  • ‖ — Too new, the spec is still changing

Security

hast-util-select does not change the syntax tree so there are no openings for cross-site scripting (XSS) attacks.

Contribute

See contributing.md in syntax-tree/.github for ways to get started. See support.md for ways to get help.

This project has a code of conduct. By interacting with this repository, organization, or community you agree to abide by its terms.

License

MIT © Titus Wormer

Rate & Review

Great Documentation0
Easy to Use0
Performant0
Highly Customizable0
Bleeding Edge0
Responsive Maintainers0
Poor Documentation0
Hard to Use0
Slow0
Buggy0
Abandoned0
Unwelcoming Community0
100