Module Cascade.ResolveSource

Resolve a stylesheet against the nodes of a tree: selector matching and the cascade, decoupled from any particular DOM.

A caller supplies its node type through NODE; Make then matches selectors and resolves the winning declarations per node. Nesting is flattened with Flatten, so a stylesheet produced by the optimiser resolves the same as the authored form.

Sourcemodule type NODE = sig ... end
Sourcetype match_result =
  1. | Matches
    (*

    The selector matches the node.

    *)
  2. | No_match
    (*

    The selector is modelled and does not match the node.

    *)
  3. | Unsupported
    (*

    The selector is outside what the matcher models, so neither answer is available, for any node.

    *)

What the matcher can say about a selector and a node.

Selectors 4 describes far more than a matcher with no document behind it can decide, so the negative answer is split in two. Unsupported is not "does not match": it says this library has no model for the selector, and a caller must not read it as the selector having been ruled out.

Sourceval supported : Selector.t -> bool

supported sel is whether the matcher has a model for sel, that is, whether Make.match_selector answers it with something other than Unsupported. The answer is a fact about sel alone, which is why it needs no node.

Modelled: the universal, type, class, id and attribute selectors, each without a namespace and, for an attribute, without a case flag; :root, :empty, :first-child, :last-child, :only-child; the descendant, child and sibling combinators; and :is(), :where(), :not() and selector lists over those - a list is only as modelled as its least modelled branch. Everything else, every stateful pseudo-class and every pseudo-element among it, is not.

Sourceval layer_order : Stylesheet.t -> string list

layer_order sheet is the cascade layer order sheet declares, weakest first, as one dotted path per layer: a.b is the sublayer b of a, however it was written (@layer a.b or @layer a { @layer b }). Layers come in order of first appearance with each sublayer inside its parent's run (css-cascade-5 sec. 6.4.2), and an @layer a, b; statement declares its names there just as a block does. Every anonymous @layer { ... } block is a layer of its own, keyed by a path holding a U+0000 that no author can write - a caller that prints these paths has to spell those out itself. Layers declared inside a conditional group are not counted, as Make.resolve does not consider such groups either.

This is the ~layer_order that Stylesheet.cascade_layer_precedence_rank expects.

Sourcemodule Make (N : NODE) : sig ... end