use {
super::System::{self, *},
crate::{
domain::{at_rules::counter_style::*, CounterStyleIdent},
parsers::{CounterStyleAtRuleParser, ParserContext},
CustomParseError,
},
cssparser::{DeclarationListParser, ParseError, Parser, ToCss},
std::{borrow::Cow, fmt},
};
#[derive(Clone, Debug)]
pub struct CounterStyleAtRule {
pub name: CounterStyleIdent,
pub system: Option<System>,
pub negative: Option<Negative>,
pub prefix: Option<Symbol>,
pub suffix: Option<Symbol>,
pub range: Option<Ranges>,
pub pad: Option<Pad>,
pub fallback: Option<Fallback>,
pub symbols: Option<Symbols>,
pub additive_symbols: Option<AdditiveSymbols>,
pub speak_as: Option<SpeakAs>,
}
impl ToCss for CounterStyleAtRule {
fn to_css<W: fmt::Write>(&self, dest: &mut W) -> fmt::Result {
#[inline(always)]
fn write<W: fmt::Write, T: ToCss>(
afterFirst: &mut bool,
dest: &mut W,
name: &str,
value: &Option<T>,
) -> fmt::Result {
if let &Some(ref value) = value {
if *afterFirst {
dest.write_char(';')?;
} else {
*afterFirst = true;
}
dest.write_str(name)?;
dest.write_char(':')?;
value.to_css(dest)
} else {
Ok(())
}
}
dest.write_str("@counter-style ")?;
self.name.to_css(dest)?;
dest.write_char('{')?;
let mut afterFirst = false;
write(&mut afterFirst, dest, "system", &self.system)?;
write(&mut afterFirst, dest, "negative", &self.negative)?;
write(&mut afterFirst, dest, "prefix", &self.prefix)?;
write(&mut afterFirst, dest, "suffix", &self.suffix)?;
write(&mut afterFirst, dest, "range", &self.range)?;
write(&mut afterFirst, dest, "pad", &self.pad)?;
write(&mut afterFirst, dest, "fallback", &self.fallback)?;
write(&mut afterFirst, dest, "symbols", &self.symbols)?;
write(
&mut afterFirst,
dest,
"additive-symbols",
&self.additive_symbols,
)?;
write(&mut afterFirst, dest, "speak-as", &self.speak_as)?;
dest.write_char('}')
}
}
impl CounterStyleAtRule {
#[inline(always)]
fn empty(name: CounterStyleIdent) -> Self {
Self {
name,
system: None,
negative: None,
prefix: None,
suffix: None,
range: None,
pad: None,
fallback: None,
symbols: None,
additive_symbols: None,
speak_as: None,
}
}
#[inline(always)]
pub fn name(&self) -> &CounterStyleIdent {
&self.name
}
#[inline(always)]
pub fn system(&self) -> Cow<System> {
if let Some(ref value) = self.system {
Cow::Borrowed(value)
} else {
Cow::Owned(System::Symbolic)
}
}
#[inline(always)]
pub fn negative(&self) -> Cow<Negative> {
if let Some(ref value) = self.negative {
Cow::Borrowed(value)
} else {
Cow::Owned(Negative(Symbol::String("-".to_owned()), None))
}
}
#[inline(always)]
pub fn prefix(&self) -> Cow<Symbol> {
if let Some(ref value) = self.prefix {
Cow::Borrowed(value)
} else {
Cow::Owned(Symbol::String("".to_owned()))
}
}
#[inline(always)]
pub fn suffix(&self) -> Cow<Symbol> {
if let Some(ref value) = self.suffix {
Cow::Borrowed(value)
} else {
Cow::Owned(Symbol::String(". ".to_owned()))
}
}
#[inline(always)]
pub fn range(&self) -> Cow<Ranges> {
if let Some(ref value) = self.range {
Cow::Borrowed(value)
} else {
Cow::Owned(Ranges::empty())
}
}
#[inline(always)]
pub fn pad(&self) -> Cow<Pad> {
if let Some(ref value) = self.pad {
Cow::Borrowed(value)
} else {
Cow::Owned(Pad(0, Symbol::String("".to_owned())))
}
}
#[inline(always)]
pub fn fallback(&self) -> Cow<Fallback> {
if let Some(ref value) = self.fallback {
Cow::Borrowed(value)
} else {
Cow::Owned(Fallback(CounterStyleIdent::decimal))
}
}
#[inline(always)]
pub fn symbols(&self) -> Option<&Symbols> {
self.symbols.as_ref()
}
#[inline(always)]
pub fn additive_symbols(&self) -> Option<&AdditiveSymbols> {
self.additive_symbols.as_ref()
}
#[inline(always)]
pub fn speak_as(&self) -> Cow<SpeakAs> {
if let Some(ref value) = self.speak_as {
Cow::Borrowed(value)
} else {
Cow::Owned(SpeakAs::Auto)
}
}
pub(crate) fn parse_body<'i, 't>(
name: CounterStyleIdent,
context: &ParserContext,
input: &mut Parser<'i, 't>,
) -> Result<CounterStyleAtRule, ParseError<'i, CustomParseError<'i>>> {
let mut rule = CounterStyleAtRule::empty(name);
{
let parser = CounterStyleAtRuleParser {
context,
rule: &mut rule,
};
let iterator = DeclarationListParser::new(input, parser);
for declaration in iterator {
if declaration.is_err() {
return Err(declaration.unwrap_err().0);
}
}
}
match *rule.system() {
ref system @ Cyclic
| ref system @ Fixed { .. }
| ref system @ Symbolic
| ref system @ Alphabetic
| ref system @ Numeric
if rule.symbols.is_none() =>
{
return Err(ParseError::from(
CustomParseError::InvalidCounterStyleWithoutSymbols(system.clone()),
))
}
ref system @ Alphabetic | ref system @ Numeric
if rule.symbols().unwrap().0.len() < 2 =>
{
return Err(ParseError::from(
CustomParseError::InvalidCounterStyleNotEnoughSymbols(system.clone()),
))
}
Additive if rule.additive_symbols.is_none() => {
return Err(ParseError::from(
CustomParseError::InvalidCounterStyleWithoutAdditiveSymbols,
))
}
Extends(_) if rule.symbols.is_some() => {
return Err(ParseError::from(
CustomParseError::InvalidCounterStyleExtendsWithSymbols,
))
}
Extends(_) if rule.additive_symbols.is_some() => {
return Err(ParseError::from(
CustomParseError::InvalidCounterStyleExtendsWithAdditiveSymbols,
))
}
_ => {}
};
Ok(rule)
}
}