Skip to documentation
SLOP

tiny.css.selector

Reference tiny.css selector

Defined in tiny.css.

The selector grammar: compounds, combinators, specificity, and bucket keys.

API (18)

Actions

Public operations.

Types and contracts

Public types and contracts.

Namespaces

Public namespaces.

Values and defaults

Public values and defaults.

No direct callersNo direct callstiny.cssselector
Static calls · unresolved targets: unknown · external targets: unknown.

Source

Source: lib/css/src/selector/grammar.zig:127

zig
/// The strongest key of a selector's rightmost compound. The rule bucket index/// groups selectors by this key so a node visits few candidates.pub const BucketKey = union(enum(u8)) {    universal,    id: u32,    class: u32,    role: u16,    kind: u16,};

Source: lib/css/src/selector/grammar.zig:159

zig
/// Builds compiled selectors into placement arrays, or counts them when the/// arrays are absent. One builder serves both passes so the inspection and/// emission walks cannot drift.pub const Builder = struct {    source: []const u8,    atoms: ?*atom.Table = null,    classes: ?[]u32 = null,    compounds: ?[]Compound = null,    combinators: ?[]Combinator = null,    nths: ?[]nth.Nth = null,    selectors: ?[]Selector = null,    diagnostics: ?[][]const u8 = null,    class_used: u32 = 0,    compound_used: u32 = 0,    combinator_used: u32 = 0,    nth_used: u32 = 0,    selector_used: u32 = 0,    atom_used: u32 = 0,    atom_bytes: u32 = 0,    dependency_used: u32 = 0,    diagnostic_used: u32 = 0,    /// Interns one identifier, folding it when the position is case    /// insensitive. Returns `atom.none` when the identifier cannot be held.    pub fn intern(self: *Builder, text: []const u8, folded: bool) error{CapacityOverflow}!u32 {        if (text.len == 0 or text.len > atom.max_text_bytes) return atom.none;        var buffer: [atom.max_text_bytes]u8 = undefined;        var body = text;        var copy = false;        if (token.hasEscape(body)) {            body = token.unescape(body, &buffer) orelse return atom.none;            copy = true;        }        if (folded and needsFold(body)) {            if (!copy) @memcpy(buffer[0..body.len], body);            for (buffer[0..body.len]) |*byte| byte.* = std.ascii.toLower(byte.*);            body = buffer[0..body.len];            copy = true;        }        if (body.len == 0) return atom.none;        if (self.atoms) |table| return table.intern(body, copy);        self.atom_used = try grow(self.atom_used, 1);        if (copy) self.atom_bytes = try grow(self.atom_bytes, @intCast(body.len));        return self.atom_used;    }    fn pushClass(self: *Builder, id: u32) error{CapacityOverflow}!void {        if (self.classes) |slice| {            std.debug.assert(self.class_used < slice.len);            slice[self.class_used] = id;        }        self.class_used = try grow(self.class_used, 1);    }    fn pushCompound(self: *Builder, compound: Compound) error{CapacityOverflow}!void {        if (self.compounds) |slice| {            std.debug.assert(self.compound_used < slice.len);            slice[self.compound_used] = compound;        }        self.compound_used = try grow(self.compound_used, 1);    }    fn pushCombinator(self: *Builder, joint: Combinator) error{CapacityOverflow}!void {        if (self.combinators) |slice| {            std.debug.assert(self.combinator_used < slice.len);            slice[self.combinator_used] = joint;        }        self.combinator_used = try grow(self.combinator_used, 1);    }    fn pushNth(self: *Builder, out: *Compound, record: nth.Nth) error{CapacityOverflow}!void {        const id = try grow(self.nth_used, 1);        if (self.nths) |slice| {            std.debug.assert(self.nth_used < slice.len);            slice[self.nth_used] = record;        }        self.nth_used = id;        if (out.nth == 0) {            out.nth = id;            return;        }        const slice = self.nths orelse return;        var walk = out.nth;        var guard: usize = 0;        while (slice[walk - 1].next != 0 and guard <= slice.len) : (guard += 1) {            walk = slice[walk - 1].next;        }        slice[walk - 1].next = id;    }    /// Records one diagnostic against the shared diagnostic cursor.    pub fn note(self: *Builder, text: []const u8) error{CapacityOverflow}!void {        if (self.diagnostics) |slice| {            std.debug.assert(self.diagnostic_used < slice.len);            slice[self.diagnostic_used] = text;        }        self.diagnostic_used = try grow(self.diagnostic_used, 1);    }    fn flagLast(self: *Builder) void {        const slice = self.compounds orelse return;        if (self.compound_used == 0) return;        slice[self.compound_used - 1].flags |= unmatchable;    }};

Source: lib/css/src/selector/grammar.zig:9

zig
/// How two compounds are joined. The list runs left to right, so/// `combinators[i]` joins `compounds[i]` to `compounds[i + 1]`.pub const Combinator = enum(u8) {    descendant,    child,    next_sibling,    subsequent_sibling,};

Source: lib/css/src/selector/grammar.zig:114

zig
/// One compound selector. Every identifier is an interned atom, so matching a/// compound is a run of integer compares.pub const Compound = extern struct {    kind: u16 = 0,    role: u16 = 0,    id: u32 = 0,    class_first: u32 = 0,    class_count: u16 = 0,    flags: u16 = 0,    pseudo: u32 = 0,    nth: u32 = 0,};

Source: lib/css/src/selector/grammar.zig:19

zig
/// The interaction and node state pseudo-classes, one bit each. An element/// interface reports them as one word, so `:hover` and `[state~=selected]` are/// the same test on the same bit.pub const PseudoClass = enum(u5) {    hover = 0,    focus = 1,    focus_visible = 2,    focus_within = 3,    active = 4,    target = 5,    root = 6,    empty = 7,    enabled = 8,    disabled = 9,    checked = 10,    indeterminate = 11,    selected = 12,    expanded = 13,    pressed = 14,    busy = 15,    invalid = 16,    required = 17,    current = 18,    mixed = 19,    link = 20,    visited = 21,    read_only = 22,    read_write = 23,    placeholder_shown = 24,    optional = 25,    default = 26,    open = 27,    modal = 28,    defined = 29,};

Source: lib/css/src/selector/grammar.zig:151

zig
/// The span of selectors one selector list contributed.pub const Range = struct {    first: u32,    count: u32,};
Called byCallsNo direct callersprivate sourcelib.css.src.selector.grammargrowprivate sourcelib.css.src.selector.grammarneedsFoldselector.Builderintern
Static calls · unresolved targets: 0 · external targets: 3.
Called byCallsNo direct callersprivate sourcelib.css.src.selector.grammargrowselector.Buildernote
Static calls · unresolved targets: 0 · external targets: 0.

Source: lib/css/src/selector/grammar.zig:53

zig
/// The bit `class` occupies in an element's pseudo-class word.pub fn bit(class: PseudoClass) u32 {    return @as(u32, 1) << @backingInt(class);}
Called byCallsNo direct callsprivate sourcelib.css.src.selector.grammarapplyAttributeprivate sourcelib.css.src.selector.grammarparsePseudotest sourcelib.css.src.selector.grammartest: state attributes and pseudo cla...selectorbit
Static calls · unresolved targets: 0 · external targets: 0.

Source: lib/css/src/selector/grammar.zig:276

zig
/// Parses a comma separated selector list over `source[start..end]` and/// returns the span of selectors it produced.pub fn parseList(builder: *Builder, start: u32, end: u32) error{CapacityOverflow}!Range {    std.debug.assert(start <= end);    std.debug.assert(end <= builder.source.len);    const first = builder.selector_used;    var cursor = start;    var guard: usize = 0;    while (cursor <= end and guard <= builder.source.len + 1) : (guard += 1) {        const comma = topLevelComma(builder.source, cursor, end) orelse end;        try parseSelector(builder, cursor, comma);        if (comma >= end) break;        cursor = comma + 1;    }    return .{ .first = first, .count = builder.selector_used - first };}
Called byCallsprivate sourcelib.css.src.selector.grammar.Fixtureparsetest sourcelib.css.src.selector.grammartest: counting and filling produce id...private sourcelib.css.src.selector.grammarparseSelectorprivate sourcelib.css.src.selector.grammartopLevelCommaselectorparseList
Static calls · unresolved targets: 0 · external targets: 0.

Source: lib/css/src/selector/grammar.zig:293

zig
/// Publishes one selector that never matches an element. An at-rule/// descriptor block keeps its prelude text this way without joining matching.pub fn parseOpaque(builder: *Builder, start: u32, end: u32) error{CapacityOverflow}!Range {    std.debug.assert(start <= end);    std.debug.assert(end <= builder.source.len);    const first = builder.selector_used;    const compound_first = builder.compound_used;    const combinator_first = builder.combinator_used;    try builder.pushCompound(.{ .flags = unmatchable });    try publish(builder, .{        .compound_first = compound_first,        .combinator_first = combinator_first,        .count = 1,        .start = start,        .end = end,        .specificity = .{},    });    return .{ .first = first, .count = builder.selector_used - first };}
Called byCallsNo direct callersprivate sourcelib.css.src.selector.grammarpublishselectorparseOpaque
Static calls · unresolved targets: 0 · external targets: 1.

Source: lib/css/src/selector/grammar.zig:58

zig
/// Resolves a pseudo-class written with a colon, ASCII case insensitively.pub fn pseudoByName(name: []const u8) ?PseudoClass {    return byName(name);}
Called byCallsprivate sourcelib.css.src.selector.grammarparsePseudoprivate sourcelib.css.src.selector.grammarbyNameselectorpseudoByName
Static calls · unresolved targets: 0 · external targets: 0.

Source: lib/css/src/selector/grammar.zig:63

zig
/// Resolves one of the ten published node states, written `[state~=name]`.pub fn stateByName(name: []const u8) ?PseudoClass {    const found = byName(name) orelse return null;    for (states) |candidate| {        if (candidate == found) return found;    }    return null;}
Called byCallsprivate sourcelib.css.src.selector.grammarapplyAttributeprivate sourcelib.css.src.selector.grammarbyNameselectorstateByName
Static calls · unresolved targets: 0 · external targets: 0.

Source: lib/css/src/selector/grammar.zig:72

zig
/// The node states the published node record carries in its `state` word.pub const states = [_]PseudoClass{    .selected, .disabled, .expanded, .checked,  .mixed,    .pressed,  .busy,     .invalid,  .required, .current,};

Source: lib/css/src/selector/grammar.zig:110

zig
/// Set on a compound whose grammar named something the node model cannot/// carry. Such a compound never matches, which is what CSS requires of a/// selector over an attribute no element has.pub const unmatchable: u16 = 1;

Source: lib/css/src/root.zig:42

zig
pub const selector = @import("selector/root.zig");

Source: lib/css/src/selector/root.zig

zig
//! The selector grammar: compounds, combinators, specificity, and bucket keys.//!//! A compound holds interned atoms rather than byte slices, so matching is a//! run of integer compares and a rule bucket is an integer key. Interaction//! pseudo-classes and the published node states share one bit word, which is//! why `:disabled` and `[state~=disabled]` are the same test.//!//! Attribute selectors cover the four keys the node model carries: `id`,//! `class`, `role`, and `state`. A selector over any other attribute parses,//! reports a diagnostic, and is marked unmatchable, which is the CSS result for//! an attribute no element in the model can hold.//!//! `Builder` runs both passes. With its placement arrays absent it counts, with//! them present it fills, so the inspection and emission walks cannot drift.const grammar = @import("grammar.zig");const nth_expression = @import("nth.zig");pub const nth = nth_expression;pub const BucketKey = grammar.BucketKey;pub const Builder = grammar.Builder;pub const Combinator = grammar.Combinator;pub const Compound = grammar.Compound;pub const PseudoClass = grammar.PseudoClass;pub const Range = grammar.Range;pub const Selector = grammar.Selector;pub const Specificity = grammar.Specificity;pub const bit = grammar.bit;pub const parseList = grammar.parseList;pub const parseOpaque = grammar.parseOpaque;pub const pseudoByName = grammar.pseudoByName;pub const stateByName = grammar.stateByName;pub const states = grammar.states;pub const unmatchable = grammar.unmatchable;

Audit

Definitions16
Public names16
Members66
Version26.7.0
Revisiondaab053ee433