Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

html.selector

import html.selector

html lifts part of this module out to its own top level; each name below is shown with the path that reaches it. Anything still spelled html.selector.* needs import html.selector.

A small, deliberately bounded CSS selector engine: enough to find things in a parsed document, and no more.

Supported syntax

FormExample
typediv
universal*
id#main
class.warning
attribute presence[disabled]
attribute equality[type="text"]
descendantarticle p
childul > li
next siblingh2 + p
subsequent siblingh2 ~ p
first childli:first-child
last childli:last-child
nth childli:nth-child(2n+1)
selector listh1, h2, h3

Compound selectors combine freely: ul.menu > li[data-id]:first-child is valid, as is any comma-separated list of those.

Deliberately not supported

Everything else, and the parser says so rather than quietly ignoring it. :not(), :has(), :nth-of-type(), ::before, namespace prefixes, and the substring attribute operators (^=, $=, *=, ~=, |=) all raise a SelectorError. A selector that silently matches nothing is far worse to debug than one that refuses to compile.

Case sensitivity

Type selectors and attribute names fold ASCII case, matching how HTML itself treats them. Ids, class names and attribute values are compared exactly, which is what standards-mode HTML does.

Functions

compile()

html.compile(source: string) -> Selector

Compiles source into a reusable Selector.

Compiled selectors are cached by source text, so calling this with the same string repeatedly costs a dictionary lookup rather than a parse. The cache holds at most 256 selectors and is dropped wholesale when it fills, so a program that builds selector strings dynamically cannot grow it without bound.

%> import html
%> var s = html.selector.compile('ul.menu > li:first-child')
%> s.matches(element)
true

Parameters

  • source (string)

Returns Selector

Raises SelectorError when source is empty, malformed, or uses syntax outside the supported subset.

Classes

SelectorError

class html.SelectorError < Error

Raised when a selector cannot be parsed, or uses syntax this module deliberately does not support. The message names the offending part of the selector.

Constructor

html.SelectorError(message)

Parameters

  • message (string)

AttributeTest

class html.selector.AttributeTest

One name/=value test from a [...] block.

Fields

FieldTypeDescription
nameThe attribute name, lowercased.
valueThe value the attribute must equal, or nil when the test is a bare presence check.

Constructor

html.selector.AttributeTest(name: string, value: ?string)

Parameters

  • name (string)
  • value (?string)

AttributeTest.matches()

html.selector.AttributeTest.matches(element) -> bool

True when element satisfies this test.

Parameters

  • element (any)

Returns bool

PseudoTest

class html.selector.PseudoTest

One :pseudo or :pseudo(...) test.

Fields

FieldTypeDescription
nameThe pseudo-class name, lowercased and without its colon.
stepThe a of the an+b argument, for nth-child.
offsetThe b of the an+b argument, for nth-child.

Constructor

html.selector.PseudoTest(name: string, step: ?number, offset: ?number)

Parameters

  • name (string)
  • step (?number)
  • offset (?number)

PseudoTest.matches()

html.selector.PseudoTest.matches(element) -> bool

True when element satisfies this test.

Parameters

  • element (any)

Returns bool

CompoundSelector

class html.selector.CompoundSelector

A run of simple selectors with nothing between them, such as div#main.active[data-x]:first-child. Every part has to match the same element.

Fields

FieldTypeDescription
tag_nameThe type selector’s tag name in lowercase, or nil when the compound has none or uses *.
idThe id the element must carry, or nil.
classesClass names the element must all carry.
attributesAttributeTest instances the element must all satisfy.
pseudosPseudoTest instances the element must all satisfy.

Constructor

html.selector.CompoundSelector()

CompoundSelector.matches()

html.selector.CompoundSelector.matches(element) -> bool

True when element satisfies every part of this compound.

Parameters

  • element (any)

Returns bool

ComplexSelector

class html.selector.ComplexSelector

One selector from a comma-separated list: a chain of compounds joined by combinators, such as ul > li + li.

Fields

FieldTypeDescription
compoundsThe compounds, leftmost first.
combinatorsHow each compound relates to the one before it.

Constructor

html.selector.ComplexSelector()

ComplexSelector.matches()

html.selector.ComplexSelector.matches(element) -> bool

True when element matches this selector.

Matching runs right to left, which is what makes a selector like body div span cheap: the rightmost compound rejects almost every element outright, and only survivors pay for the walk up the tree.

Parameters

  • element (any)

Returns bool

Selector

class html.Selector

A compiled selector list: h1, h2 is one of these holding two ComplexSelector instances.

Instances are immutable once compiled and safe to reuse, which is why compile() caches them.

Fields

FieldTypeDescription
sourceThe selector text this was compiled from, kept for error messages and for to_string().
alternativesThe alternatives, in the order they were written.

Constructor

html.Selector(source: string, alternatives: list)

Parameters

  • source (string)
  • alternatives (list)

Selector.matches()

html.Selector.matches(element) -> bool

True when element matches any alternative in this selector.

Parameters

  • element (any)

Returns bool

Selector.to_string()

html.Selector.to_string() -> string

The selector text this was compiled from.

Returns string


2026, Richard Ore and The Zuri Contributors