/* This Source Code Form is subject to the terms of the Mozilla Public *License,v.2.0.IfacopyoftheMPLwasnotdistributedwiththis
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
/// <https://drafts.csswg.org/css-counter-styles/#typedef-counter-style> /// /// Note that 'none' is not a valid name, but we include this (along with String) for space /// efficiency when storing list-style-type. #[derive(
Clone, Debug, Eq, MallocSizeOf, PartialEq, ToComputedValue, ToCss, ToResolvedValue, ToShmem,
)] #[repr(u8)] pubenum CounterStyle { /// The 'none' value.
None, /// `<counter-style-name>`
Name(CustomIdent), /// `symbols()` #[css(function)]
Symbols { /// The <symbols-type>, or symbolic if not specified. #[css(skip_if = "is_symbolic")]
ty: SymbolsType, /// The actual symbols.
symbols: Symbols,
}, /// A single string value, useful for `<list-style-type>`.
String(AtomString),
}
/// decimal value pubfn decimal() -> Self {
CounterStyle::Name(CustomIdent(atom!("decimal")))
}
/// Is this a bullet? (i.e. `list-style-type: disc|circle|square|disclosure-closed|disclosure-open`) #[inline] pubfn is_bullet(&self) -> bool { matchself {
CounterStyle::Name(CustomIdent(ref name)) => {
name == &atom!("disc") ||
name == &atom!("circle") ||
name == &atom!("square") ||
name == &atom!("disclosure-closed") ||
name == &atom!("disclosure-open")
},
_ => false,
}
}
}
bitflags! { #[derive(Clone, Copy)] /// Flags to control parsing of counter styles. pubstruct CounterStyleParsingFlags: u8 { /// Whether `none` is allowed. const ALLOW_NONE = 1 << 0; /// Whether a bare string is allowed. const ALLOW_STRING = 1 << 1;
}
}
impl CounterStyle { /// Parse a counter style, and optionally none|string (for list-style-type). pubfn parse<'i, 't>(
context: &ParserContext,
input: &mut Parser<'i, 't>,
flags: CounterStyleParsingFlags,
) -> Result<Self, ParseError<'i>> { useself::CounterStyleParsingFlags as Flags; let location = input.current_source_location(); match input.next()? {
Token::QuotedString(ref string) if flags.intersects(Flags::ALLOW_STRING) => {
Ok(Self::String(AtomString::from(string.as_ref())))
},
Token::Ident(ref ident) => { if flags.intersects(Flags::ALLOW_NONE) && ident.eq_ignore_ascii_case("none") { return Ok(Self::None);
}
Ok(Self::Name(counter_style_name_from_ident(ident, location)?))
},
Token::Function(ref name) if name.eq_ignore_ascii_case("symbols") => {
input.parse_nested_block(|input| { let symbols_type = input
.try_parse(SymbolsType::parse)
.unwrap_or(SymbolsType::Symbolic); let symbols = Symbols::parse(context, input)?; // There must be at least two symbols for alphabetic or // numeric system. if (symbols_type == SymbolsType::Alphabetic ||
symbols_type == SymbolsType::Numeric) &&
symbols.0.len() < 2
{ return Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError));
} // Identifier is not allowed in symbols() function. if symbols.0.iter().any(|sym| !sym.is_allowed_in_symbols()) { return Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError));
}
Ok(Self::Symbols {
ty: symbols_type,
symbols,
})
})
},
t => Err(location.new_unexpected_token_error(t.clone())),
}
}
}
impl SpecifiedValueInfo for CounterStyle { fn collect_completion_keywords(f: KeywordsCollectFn) { // XXX The best approach for implementing this is probably // having a CounterStyleName type wrapping CustomIdent, and // put the predefined list for that type in counter_style mod. // But that's a non-trivial change itself, so we use a simpler // approach here.
macro_rules! predefined {
($($name:expr,)+) => {
f(&["symbols", "none", $($name,)+])
}
}
include!("predefined.rs");
}
}
fn parse_counter_style_name<'i>(input: &mut Parser<'i, '_>) -> Result<CustomIdent, ParseError<'i>> { let location = input.current_source_location(); let ident = input.expect_ident()?;
counter_style_name_from_ident(ident, location)
}
/// Default methods reject all at rules. impl<'a, 'b, 'i> AtRuleParser<'i> for CounterStyleRuleParser<'a, 'b> { type Prelude = (); type AtRule = (); type Error = StyleParseErrorKind<'i>;
}
impl<'a, 'b, 'i> QualifiedRuleParser<'i> for CounterStyleRuleParser<'a, 'b> { type Prelude = (); type QualifiedRule = (); type Error = StyleParseErrorKind<'i>;
}
impl<'a, 'b, 'i> DeclarationParser<'i> for CounterStyleRuleParser<'a, 'b> { type Declaration = (); type Error = StyleParseErrorKind<'i>;
fn parse_value<'t>(
&mutself,
name: CowRcStr<'i>,
input: &mut Parser<'i, 't>,
) -> Result<(), ParseError<'i>> {
match_ignore_ascii_case! { &*name,
$(
$name => { // DeclarationParser also calls parse_entirely so we’d normally not // need to, but in this case we do because we set the value as a side // effect rather than returning it. let value = input.parse_entirely(|i| Parse::parse(self.context, i))?; self.rule.$ident = Some(value)
},
)*
_ => return Err(input.new_custom_error(SelectorParseErrorKind::UnexpectedIdent(name.clone()))),
}
Ok(())
}
}
// Implements the special checkers for some setters. // See <https://drafts.csswg.org/css-counter-styles/#the-csscounterstylerule-interface> impl CounterStyleRuleData { /// Check that the system is effectively not changed. Only params /// of system descriptor is changeable. fn check_system(&self, value: &System) -> bool {
mem::discriminant(self.resolved_system()) == mem::discriminant(value)
}
fn check_symbols(&self, value: &Symbols) -> bool { match *self.resolved_system() { // These two systems require at least two symbols.
System::Numeric | System::Alphabetic => value.0.len() >= 2, // No symbols should be set for extends system.
System::Extends(_) => false,
_ => true,
}
}
fn check_additive_symbols(&self, _value: &AdditiveSymbols) -> bool { match *self.resolved_system() { // No additive symbols should be set for extends system.
System::Extends(_) => false,
_ => true,
}
}
}
impl CounterStyleRuleData { /// Get the name of the counter style rule. pubfn name(&self) -> &CustomIdent {
&self.name
}
/// Set the name of the counter style rule. Caller must ensure that /// the name is valid. pubfn set_name(&mutself, name: CustomIdent) {
debug_assert!(is_valid_name_definition(&name)); self.name = name;
}
/// Get the current generation of the counter style rule. pubfn generation(&self) -> u32 { self.generation.0
}
/// Get the system of this counter style rule, default to /// `symbolic` if not specified. pubfn resolved_system(&self) -> &System { matchself.system {
Some(ref system) => system,
None => &System::Symbolic,
}
}
}
impl Parse for Symbol { fn parse<'i, 't>(
_context: &ParserContext,
input: &mut Parser<'i, 't>,
) -> Result<Self, ParseError<'i>> { let location = input.current_source_location(); match *input.next()? {
Token::QuotedString(ref s) => Ok(Symbol::String(s.as_ref().to_owned().into())),
Token::Ident(ref s) => Ok(Symbol::Ident(CustomIdent::from_ident(location, s, &[])?)), ref t => Err(location.new_unexpected_token_error(t.clone())),
}
}
}
impl Symbol { /// Returns whether this symbol is allowed in symbols() function. pubfn is_allowed_in_symbols(&self) -> bool { matchself { // Identifier is not allowed.
&Symbol::Ident(_) => false,
_ => true,
}
}
}
/// A bound found in `CounterRanges`. #[derive(Clone, Copy, Debug, ToCss, ToShmem)] pubenum CounterBound { /// An integer bound.
Integer(Integer), /// The infinite bound.
Infinite,
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.