Skip to documentation
SLOP

tiny.css.selector.nth

Reference tiny.css selector nth

Defined in selector.

API (5)

Actions

Public operations.

Types and contracts

Public types and contracts.

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

Source

Called byCallsNo direct callsprivate sourcelib.css.src.match.enginematchNthtest sourcelib.css.src.selector.nthtest: a fixed index matches only its ...test sourcelib.css.src.selector.nthtest: a stepped expression matches it...selector.nthmatches
Static calls · unresolved targets: 0 · external targets: 0.
Called byCallsprivate sourcelib.css.src.selector.grammarparseFunctionalPseudotest sourcelib.css.src.selector.nthtest: an nth expression parses its ke...private sourcelib.css.src.selector.nthcoefficientprivate sourcelib.css.src.selector.nthintegerselector.nthparse
Static calls · unresolved targets: 0 · external targets: 0.

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

zig
const std = @import("std");/// Which sibling sequence a structural pseudo-class counts over.pub const Kind = enum(u8) {    child,    last_child,    of_type,    last_of_type,};/// One `An+B` test. `next` chains further structural tests on the same/// compound, one based, so that `Compound.nth` stays a single word.pub const Nth = struct {    a: i32,    b: i32,    kind: Kind,    next: u32 = 0,};/// The coefficients of an `An+B` expression.pub const Coefficients = struct {    a: i32,    b: i32,};/// Parses `odd`, `even`, `An+B`, `n`, or a bare integer.pub fn parse(text: []const u8) ?Coefficients {    const trimmed = std.mem.trim(u8, text, " \t\r\n\x0C");    if (trimmed.len == 0) return null;    if (std.ascii.eqlIgnoreCase(trimmed, "odd")) return .{ .a = 2, .b = 1 };    if (std.ascii.eqlIgnoreCase(trimmed, "even")) return .{ .a = 2, .b = 0 };    const split = std.mem.indexOfAny(u8, trimmed, "nN") orelse {        return .{ .a = 0, .b = integer(trimmed) orelse return null };    };    const head = std.mem.trim(u8, trimmed[0..split], " \t\r\n\x0C");    const tail = std.mem.trim(u8, trimmed[split + 1 ..], " \t\r\n\x0C");    const a = coefficient(head) orelse return null;    if (tail.len == 0) return .{ .a = a, .b = 0 };    const sign: i32 = switch (tail[0]) {        '+' => 1,        '-' => -1,        else => return null,    };    const rest = std.mem.trim(u8, tail[1..], " \t\r\n\x0C");    const magnitude = integer(rest) orelse return null;    if (magnitude < 0) return null;    return .{ .a = a, .b = sign * magnitude };}/// Whether a one based `index` out of `count` siblings satisfies `An+B`.pub fn matches(coefficients: Coefficients, index: u32, count: u32, kind: Kind) bool {    std.debug.assert(index >= 1);    if (count != 0) std.debug.assert(index <= count);    const last = kind == .last_child or kind == .last_of_type;    const position: i64 = if (last)        @as(i64, count) - @as(i64, index) + 1    else        @as(i64, index);    const b: i64 = coefficients.b;    if (coefficients.a == 0) return position == b;    const offset = position - b;    const a: i64 = coefficients.a;    if (@rem(offset, a) != 0) return false;    return @divTrunc(offset, a) >= 0;}fn coefficient(head: []const u8) ?i32 {    if (head.len == 0) return 1;    if (head.len == 1 and head[0] == '+') return 1;    if (head.len == 1 and head[0] == '-') return -1;    return integer(head);}fn integer(text: []const u8) ?i32 {    if (text.len == 0) return null;    var index: usize = 0;    var sign: i32 = 1;    if (text[0] == '+' or text[0] == '-') {        sign = if (text[0] == '-') -1 else 1;        index = 1;    }    if (index >= text.len) return null;    var magnitude: i32 = 0;    while (index < text.len) : (index += 1) {        if (!std.ascii.isDigit(text[index])) return null;        magnitude = std.math.mul(i32, magnitude, 10) catch return null;        magnitude = std.math.add(i32, magnitude, text[index] - '0') catch return null;    }    return sign * magnitude;}test "an nth expression parses its keywords, coefficients, and offsets" {    try std.testing.expectEqual(Coefficients{ .a = 2, .b = 1 }, parse("odd").?);    try std.testing.expectEqual(Coefficients{ .a = 2, .b = 0 }, parse("EVEN").?);    try std.testing.expectEqual(Coefficients{ .a = 0, .b = 3 }, parse("3").?);    try std.testing.expectEqual(Coefficients{ .a = 3, .b = 1 }, parse("3n + 1").?);    try std.testing.expectEqual(Coefficients{ .a = -1, .b = 3 }, parse("-n+3").?);    try std.testing.expectEqual(Coefficients{ .a = 1, .b = 0 }, parse("n").?);    try std.testing.expectEqual(Coefficients{ .a = 1, .b = -2 }, parse("+n-2").?);    try std.testing.expect(parse("") == null);    try std.testing.expect(parse("2x+1") == null);    try std.testing.expect(parse("2n*1") == null);}test "a fixed index matches only its own position" {    const first = Coefficients{ .a = 0, .b = 1 };    try std.testing.expect(matches(first, 1, 5, .child));    try std.testing.expect(!matches(first, 2, 5, .child));    try std.testing.expect(matches(first, 5, 5, .last_child));    try std.testing.expect(!matches(first, 4, 5, .last_child));}test "a stepped expression matches its arithmetic sequence forward only" {    const odd = Coefficients{ .a = 2, .b = 1 };    try std.testing.expect(matches(odd, 1, 6, .child));    try std.testing.expect(!matches(odd, 2, 6, .child));    try std.testing.expect(matches(odd, 5, 6, .child));    const leading = Coefficients{ .a = -1, .b = 3 };    try std.testing.expect(matches(leading, 1, 9, .child));    try std.testing.expect(matches(leading, 3, 9, .child));    try std.testing.expect(!matches(leading, 4, 9, .child));}

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

zig
pub const nth = nth_expression;

Audit

Definitions6
Public names6
Members10
Version26.7.0
Revisiondaab053ee433