Skip to documentation
SLOP

tiny.css.scan

Reference tiny.css scan

Defined in tiny.css.

Byte level CSS scanning shared by the sheet parser and the media reader.

API (16)

Actions

Public operations.

Types and contracts

Public types and contracts.

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

Source

Called byCallsNo direct callsprivate sourcelib.css.src.mediaevaluateMediaFeaturescanconsumePrefixIgnoreCase
Static calls · unresolved targets: 0 · external targets: 0.
Called byCallsprivate sourcelib.css.src.mediaevaluateMediaConditionSequenceprivate sourcelib.css.src.mediaevaluateMediaQueryscanreadIdentscanskipCssSpacescanconsumeWord
Static calls · unresolved targets: 0 · external targets: 0.
Called byCallsprivate sourcelib.css.src.mediaevaluateMediaConditionSequencescanidentBytescanreadIdentscanskipStringscancontainsTopLevelLogical
Static calls · unresolved targets: 0 · external targets: 0.
Called byCallsprivate sourcelib.css.src.sheetparseAtRulescanskipStringscanfindAtRuleBoundary
Static calls · unresolved targets: 0 · external targets: 0.
Called byCallsprivate sourcelib.css.src.sheetparseAtRuleprivate sourcelib.css.src.sheetparseRulesscanskipStringscanfindBlockEnd
Static calls · unresolved targets: 0 · external targets: 0.
Called byCallsprivate sourcelib.css.src.sheetscanDeclarationsscanfindTopLevelBytescanfindDeclarationEnd
Static calls · unresolved targets: 0 · external targets: 0.
Called byCallsprivate sourcelib.css.src.mediaevaluateMediaConditionSequencescanskipStringscanfindParenEnd
Static calls · unresolved targets: 0 · external targets: 0.
Called byCallsprivate sourcelib.css.src.mediaevaluateMediaFeaturescanfindDeclarationEndprivate sourcelib.css.src.sheetparseRulesprivate sourcelib.css.src.sheetscanDeclarationsscanskipStringscanfindTopLevelByte
Static calls · unresolved targets: 0 · external targets: 0.
Called byCallsNo direct callsscancontainsTopLevelLogicalscanreadIdentscanidentByte
Static calls · unresolved targets: 0 · external targets: 0.
Called byCallsprivate sourcelib.css.src.mediaevaluateMediaQuerymediamediaAppliesscanconsumeWordscancontainsTopLevelLogicalprivate sourcelib.css.src.sheetdescriptorAtRulescanidentBytescanreadIdent
Static calls · unresolved targets: 0 · external targets: 0.
Called byCallsNo direct callsprivate sourcelib.css.src.mediaevaluateMediaConditionprivate sourcelib.css.src.mediaevaluateMediaConditionSequenceprivate sourcelib.css.src.mediaevaluateMediaQuerymediamediaAppliesmediamediaListAppliesscanconsumeWordscanskipCssSpace
Static calls · unresolved targets: 0 · external targets: 0.
Called byCallsNo direct callsprivate sourcelib.css.src.sheetparseRulesscanskipSpaceAndComments
Static calls · unresolved targets: 0 · external targets: 0.
Called byCallsNo direct callsprivate sourcelib.css.src.mediafindMediaQueryEndscancontainsTopLevelLogicalscanfindAtRuleBoundaryscanfindBlockEndscanfindParenEndscanfindTopLevelBytescanskipString
Static calls · unresolved targets: 0 · external targets: 0.

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

zig
pub const scan = @import("scan.zig");

Source: lib/css/src/scan.zig

zig
//! Byte level CSS scanning shared by the sheet parser and the media reader.//!//! These helpers respect strings, comments, and bracket nesting, which is what//! keeps a declaration delimiter inside a data URL or a comma inside a media//! query from ending the construct that holds it.const std = @import("std");pub fn findTopLevelByte(source: []const u8, start: usize, needle: u8) ?usize {    var index = start;    var square_depth: usize = 0;    var paren_depth: usize = 0;    while (index < source.len) : (index += 1) {        const byte = source[index];        if (byte == '"' or byte == '\'') {            index = skipString(source, index);            continue;        }        switch (byte) {            '[' => square_depth += 1,            ']' => {                if (square_depth > 0) square_depth -= 1;            },            '(' => paren_depth += 1,            ')' => {                if (paren_depth > 0) paren_depth -= 1;            },            else => {},        }        if (byte == needle and square_depth == 0 and paren_depth == 0) return index;    }    return null;}pub fn findBlockEnd(source: []const u8, open: usize) ?usize {    var index = open + 1;    var depth: usize = 1;    while (index < source.len) : (index += 1) {        const byte = source[index];        if (byte == '"' or byte == '\'') {            index = skipString(source, index);            continue;        }        if (byte == '/' and index + 1 < source.len and source[index + 1] == '*') {            const end = std.mem.indexOf(u8, source[index + 2 ..], "*/") orelse return null;            index += end + 3;            continue;        }        if (byte == '{') {            depth += 1;            continue;        }        if (byte == '}') {            depth -= 1;            if (depth == 0) return index;        }    }    return null;}pub fn skipString(source: []const u8, quote: usize) usize {    var index = quote + 1;    while (index < source.len) : (index += 1) {        if (source[index] == '\\') {            if (index + 1 < source.len) index += 1;            continue;        }        if (source[index] == source[quote]) return index;    }    return source.len;}pub fn findDeclarationEnd(source: []const u8, start: usize) usize {    return findTopLevelByte(source, start, ';') orelse source.len;}pub fn findParenEnd(source: []const u8, open: usize) ?usize {    var index = open + 1;    var depth: usize = 1;    while (index < source.len) : (index += 1) {        const byte = source[index];        if (byte == '"' or byte == '\'') {            index = skipString(source, index);            continue;        }        if (byte == '/' and index + 1 < source.len and source[index + 1] == '*') {            const end = std.mem.indexOf(u8, source[index + 2 ..], "*/") orelse return null;            index += end + 3;            continue;        }        if (byte == '(') {            depth += 1;            continue;        }        if (byte == ')') {            depth -= 1;            if (depth == 0) return index;        }    }    return null;}pub fn containsTopLevelLogical(source: []const u8) bool {    var index: usize = 0;    var paren_depth: usize = 0;    while (index < source.len) : (index += 1) {        const byte = source[index];        if (byte == '"' or byte == '\'') {            index = skipString(source, index);            continue;        }        switch (byte) {            '(' => paren_depth += 1,            ')' => {                if (paren_depth > 0) paren_depth -= 1;            },            else => {},        }        if (paren_depth == 0 and identByte(byte)) {            const end = readIdent(source, index);            const word = source[index..end];            if (std.ascii.eqlIgnoreCase(word, "and") or std.ascii.eqlIgnoreCase(word, "or")) return true;            index = end - 1;        }    }    return false;}pub fn consumePrefixIgnoreCase(source: []const u8, prefix: []const u8) ?[]const u8 {    if (source.len < prefix.len) return null;    if (!std.ascii.eqlIgnoreCase(source[0..prefix.len], prefix)) return null;    return source[prefix.len..];}pub fn endsWithIgnoreCase(source: []const u8, suffix: []const u8) bool {    if (source.len < suffix.len) return false;    return std.ascii.eqlIgnoreCase(source[source.len - suffix.len ..], suffix);}pub fn consumeWord(source: []const u8, index: *usize, word: []const u8) bool {    index.* = skipCssSpace(source, index.*);    const end = readIdent(source, index.*);    if (end == index.* or !std.ascii.eqlIgnoreCase(source[index.*..end], word)) return false;    index.* = end;    return true;}pub fn skipCssSpace(source: []const u8, start: usize) usize {    var index = start;    while (index < source.len and std.ascii.isWhitespace(source[index])) index += 1;    return index;}pub fn readIdent(source: []const u8, start: usize) usize {    var index = start;    while (index < source.len and identByte(source[index])) index += 1;    return index;}pub fn identByte(byte: u8) bool {    return std.ascii.isAlphanumeric(byte) or byte == '_' or byte == '-';}pub fn skipSpaceAndComments(source: []const u8, start: usize) usize {    var index = start;    while (index < source.len) {        while (index < source.len and std.ascii.isWhitespace(source[index])) index += 1;        if (index + 1 < source.len and source[index] == '/' and source[index + 1] == '*') {            const end = std.mem.indexOf(u8, source[index + 2 ..], "*/") orelse return source.len;            index += end + 4;            continue;        }        return index;    }    return index;}pub const AtRuleBoundaryKind = enum {    semicolon,    block,};pub const AtRuleBoundary = struct {    kind: AtRuleBoundaryKind,    index: usize,};pub fn findAtRuleBoundary(source: []const u8, start: usize) ?AtRuleBoundary {    var index = start;    var square_depth: usize = 0;    var paren_depth: usize = 0;    while (index < source.len) : (index += 1) {        const byte = source[index];        if (byte == '"' or byte == '\'') {            index = skipString(source, index);            continue;        }        switch (byte) {            '[' => square_depth += 1,            ']' => {                if (square_depth > 0) square_depth -= 1;            },            '(' => paren_depth += 1,            ')' => {                if (paren_depth > 0) paren_depth -= 1;            },            ';' => if (square_depth == 0 and paren_depth == 0) return .{ .kind = .semicolon, .index = index },            '{' => if (square_depth == 0 and paren_depth == 0) return .{ .kind = .block, .index = index },            else => {},        }    }    return null;}

Audit

Definitions17
Public names17
Members4
Version26.7.0
Revisiondaab053ee433