peacock-crest 0.1.0

A CSS library for parsing and applying styles to in-memory DOM structures
Documentation

/// BEGIN SELECTOR GRAMMAR SPEC
// each rule is defined in accordance to their corresponding rule at:
// https://www.w3.org/TR/selectors/#grammar

SELECTOR_LIST = { WS* ~ SELECTOR_COMPLEX_LIST }
SELECTOR_COMPLEX_LIST = { SELECTOR_COMPLEX ~ WS* ~ ("," ~ WS* ~ SELECTOR_COMPLEX ~ WS*)* }
SELECTOR_COMPOUND_LIST = { SELECTOR_COMPOUND ~ WS* ~ ("," ~ WS* ~ SELECTOR_COMPOUND ~ WS*)* }
SELECTOR_SIMPLE_LIST = { SELECTOR_SIMPLE ~ WS* ~ ("," ~ WS* ~ SELECTOR_SIMPLE ~ WS*)* }
SELECTOR_RELATIVE_LIST = { SELECTOR_RELATIVE ~ WS* ~ ("," ~ WS* ~ SELECTOR_RELATIVE ~ WS*)* }

SELECTOR_COMPLEX = { SELECTOR_COMPOUND ~ ((SELECTOR_COMBINATOR ~ SELECTOR_COMPOUND) | (SELECTOR_COMBINATOR__NAMESPACE))* }
SELECTOR_RELATIVE = { SELECTOR_COMBINATOR? ~ SELECTOR_COMPLEX }
SELECTOR_COMPOUND = {
    (
          (SELECTOR_TYPE ~ (SELECTOR_SUBCLASS*) ~ (SELECTOR_PSEUDOELEMENT_TAIL*))
        | ((SELECTOR_SUBCLASS+) ~ (SELECTOR_PSEUDOELEMENT_TAIL*))
        | SELECTOR_PSEUDOELEMENT_TAIL
    )+
}
SELECTOR_PSEUDOELEMENT_TAIL = { SELECTOR_PSEUDOELEMENT ~ SELECTOR_PSEUDOCLASS* }

SELECTOR_SIMPLE = { SELECTOR_SUBCLASS | SELECTOR_TYPE }

SELECTOR_COMBINATOR = {
      SELECTOR_COMBINATOR__NEXT_SIBLING
    | SELECTOR_COMBINATOR__CHILD
    | SELECTOR_COMBINATOR__COLUMN
    | SELECTOR_COMBINATOR__SUBSEQUENT_SIBLING
    | SELECTOR_COMBINATOR__DESCENDENT
}
SELECTOR_TYPE = { WQ_NAME | (PREFIX_NAMESPACE? ~ "*") }
PREFIX_NAMESPACE = { (IDENT | "*")? ~ "|" }
WQ_NAME = { PREFIX_NAMESPACE? ~ IDENT }
SELECTOR_SUBCLASS = { SELECTOR_ID | SELECTOR_CLASS | SELECTOR_ATTRIBUTE | SELECTOR_PSEUDOCLASS }

SELECTOR_ID = { HASH }
SELECTOR_CLASS = { "." ~ IDENT }
SELECTOR_ATTRIBUTE = {
      ("[" ~ WS* ~ IDENT ~ WS* ~ "]")
    | ("[" ~ WS* ~ IDENT ~ WS* ~ ATTR_MATCHER ~ WS* ~ (ATTR_MODIFIER ~ WS*)? ~ "]")
}
ATTR_MATCHER = {
    (
          ATTR_MATCHER__EXACT_MATCH
        | ATTR_MATCHER__LIST_CONTAINS
        | ATTR_MATCHER__STARTS_WITH
        | ATTR_MATCHER__STARTS_WITH_DASHED
        | ATTR_MATCHER__ENDS_WITH
        | ATTR_MATCHER__CONTAINS
    ) ~ WS* ~ (STRING | IDENT)
}
ATTR_MODIFIER = { "i" | "I" | "s" | "S" }
SELECTOR_PSEUDOCLASS = { ":" ~ (IDENT | FUNCTION_BLOCK) }
SELECTOR_PSEUDOELEMENT = { ":" ~ SELECTOR_PSEUDOCLASS }

ATTR_MATCHER__EXACT_MATCH = { "=" }
ATTR_MATCHER__LIST_CONTAINS = { "~=" }
ATTR_MATCHER__STARTS_WITH = { "^=" }
ATTR_MATCHER__STARTS_WITH_DASHED = { "|=" }
ATTR_MATCHER__ENDS_WITH = { "$=" }
ATTR_MATCHER__CONTAINS = { "*=" }

// CONVENIENCE TOKENS

SELECTOR_COMBINATOR__NEXT_SIBLING = { WS* ~ "+" ~ WS* }
SELECTOR_COMBINATOR__CHILD = { WS* ~ ">" ~ WS* }
SELECTOR_COMBINATOR__COLUMN = { WS* ~ "||" ~ WS* }
SELECTOR_COMBINATOR__SUBSEQUENT_SIBLING = { WS* ~ "~" ~ WS* }
SELECTOR_COMBINATOR__DESCENDENT = { " "+ }

SELECTOR_COMBINATOR__NAMESPACE = { WS* ~ "|" ~ WS* ~ IDENT }

// BEGIN CSS GRAMMAR TOKENS SPEC

// https://drafts.csswg.org/css-syntax/#string-token-diagram
// COMPLIANT
STRING = {
    ("'" ~ (
          (!"'" ~ !NEWLINE ~ !"\\" ~ ANY)
        | ESCAPE
        | ("\\" ~ NEWLINE)
    )*
    ~ "'")
    |
    ("\"" ~ (
        (!"\"" ~ !NEWLINE ~ !"\\" ~ ANY)
      | ESCAPE
      | ("\\" ~ NEWLINE)
  )*
  ~ "\"")
}

// https://drafts.csswg.org/css-syntax/#hash-token-diagram
// COMPLIANT
HASH = {
    "#" ~ (
          ('0'..'9' | 'a'..'z' | 'A'..'Z' | "_" | "-" | NON_ASCII)
        | ESCAPE
    )+
}

FUNCTION_BLOCK = { (FUNCTION ~ FUNCTION__CONTENTS ~ ")") }

// https://drafts.csswg.org/css-syntax/#function-token-diagram
// COMPLIANT
FUNCTION = { IDENT ~ "(" }

FUNCTION__CONTENTS = { FUNCTION__PARAMS ~ (((WS+) | (WS* ~ "," ~ WS*)) ~ FUNCTION__PARAMS)* }
FUNCTION__PARAMS = { IDENT | STRING | NUMBER | HASH }

// https://drafts.csswg.org/css-syntax/#number-token-diagram
// COMPLIANT
NUMBER = { ("+" | "-")? ~ ((ASCII_DIGIT+ ~ "." ~ ASCII_DIGIT+) | ASCII_DIGIT+ | ("." ~ ASCII_DIGIT+)) ~ (("e" | "E") ~ ("+" | "-")? ~ ASCII_DIGIT+)? }

// https://drafts.csswg.org/css-syntax/#ident-token-diagram
// COMPLIANT
IDENT = { (
    "--" | (
        "-"? ~ (
            ('a'..'z' | 'A'..'Z' | "_" | NON_ASCII)
            | ESCAPE
        )
    ))
    ~ (
        ('0'..'9' | 'a'..'z' | 'A'..'Z' | "_" | "-" | NON_ASCII)
        | ESCAPE
    )*
}

// https://drafts.csswg.org/css-syntax/#comment-diagram
// https://drafts.csswg.org/css-syntax/#whitespace-diagram
// https://drafts.csswg.org/css-syntax/#ws*-diagram
// DEVIATION: PEDANTIC
// REASON: simplifies multiple token types into a single definition.
//         doesn't repeat so usage mirrors "ws*" syntax used in spec
WS = _{ (" " | "\t" | NEWLINE) | ("/*" ~ (!"*/" ~ ANY)* ~ "*/") }

// https://drafts.csswg.org/css-syntax/#non-printable-code-point
// COMPLIANT
NON_PRINTABLE = _{ '\u{0000}'..'\u{0008}' | "\u{000B}" | '\u{000E}'..'\u{001F}' | "\u{007F}" }

// https://drafts.csswg.org/css-syntax/#non-ascii-ident-code-point
// COMPLIANT
NON_ASCII = _{
      "\u{00B7}"
    | '\u{00C0}'..'\u{00D6}' | '\u{00F8}'..'\u{037D}' | '\u{037F}'..'\u{1FFF}'
    | "\u{200C}" | "\u{200D}" | "\u{203F}" | "\u{2040}"
    | '\u{2070}'..'\u{218F}' | '\u{2C00}'..'\u{2FEF}' | '\u{3001}'..'\u{D7FF}'
    | '\u{F900}'..'\u{FDCF}' | '\u{FDF0}'..'\u{FFFD}' | '\u{10000}'..'\u{10FFFF}'
}

// https://drafts.csswg.org/css-syntax/#escape-diagram
// COMPLIANT
ESCAPE = _{
    "\\" ~ (
          (!NEWLINE ~ !HEX_DIGIT)
        | (HEX_DIGIT{1, 6} ~ WS?)
    )
}

// https://drafts.csswg.org/css-syntax/#hex-digit-diagram
// COMPLIANT
HEX_DIGIT = _{ '0'..'9' | 'a'..'f' | 'A'..'F' }

// https://drafts.csswg.org/css-syntax/#newline-diagram
// COMPLIANT
NEWLINE = _{ "\n" | "\r" | "\r\n" | "\u{000C}" }