use cssparser::Parser;
use super::parse::border::{
BorderSide, parse_border_shorthand, parse_border_side_shorthand,
parse_border_style_shorthand_values, parse_color_shorthand_values,
};
use super::parse::box_model::parse_box_shorthand_values;
use super::parse::font::{
parse_font_family, parse_font_size, parse_font_weight, parse_line_height,
};
use super::parse::keywords::{
parse_border_collapse, parse_border_style_value, parse_box_sizing, parse_break_inside,
parse_break_value, parse_clear, parse_decoration_style, parse_display, parse_float,
parse_font_style, parse_font_variant, parse_hyphens, parse_list_style_position,
parse_list_style_shorthand, parse_list_style_type, parse_overflow_wrap, parse_text_align,
parse_text_transform, parse_vertical_align, parse_visibility, parse_white_space,
parse_word_break,
};
use super::parse::values::{
parse_background_shorthand, parse_color, parse_integer, parse_length, parse_text_decoration,
};
use super::properties::*;
#[derive(Debug, Clone)]
pub enum Declaration {
Color(Color),
BackgroundColor(Color),
FontFamily(String),
FontSize(Length),
FontWeight(FontWeight),
FontStyle(FontStyle),
FontVariant(FontVariant),
TextAlign(TextAlign),
TextIndent(Length),
LineHeight(Length),
LetterSpacing(Length),
WordSpacing(Length),
TextTransform(TextTransform),
Hyphens(Hyphens),
WhiteSpace(WhiteSpace),
VerticalAlign(VerticalAlign),
TextDecoration(super::parse::TextDecorationValue),
TextDecorationStyle(DecorationStyle),
TextDecorationColor(Color),
Margin(Length),
MarginTop(Length),
MarginRight(Length),
MarginBottom(Length),
MarginLeft(Length),
Padding(Length),
PaddingTop(Length),
PaddingRight(Length),
PaddingBottom(Length),
PaddingLeft(Length),
Width(Length),
Height(Length),
MaxWidth(Length),
MaxHeight(Length),
MinWidth(Length),
MinHeight(Length),
Display(Display),
Float(Float),
Clear(Clear),
Visibility(Visibility),
BoxSizing(BoxSizing),
Orphans(u32),
Widows(u32),
WordBreak(WordBreak),
OverflowWrap(OverflowWrap),
BreakBefore(BreakValue),
BreakAfter(BreakValue),
BreakInside(BreakValue),
BorderStyle(BorderStyle),
BorderTopStyle(BorderStyle),
BorderRightStyle(BorderStyle),
BorderBottomStyle(BorderStyle),
BorderLeftStyle(BorderStyle),
BorderWidth(Length),
BorderTopWidth(Length),
BorderRightWidth(Length),
BorderBottomWidth(Length),
BorderLeftWidth(Length),
BorderColor(Color),
BorderTopColor(Color),
BorderRightColor(Color),
BorderBottomColor(Color),
BorderLeftColor(Color),
BorderRadius(Length),
BorderTopLeftRadius(Length),
BorderTopRightRadius(Length),
BorderBottomLeftRadius(Length),
BorderBottomRightRadius(Length),
ListStyleType(ListStyleType),
ListStylePosition(ListStylePosition),
BorderCollapse(BorderCollapse),
BorderSpacing(Length),
}
impl Declaration {
pub fn parse(name: &str, input: &mut Parser<'_, '_>) -> Vec<Self> {
if let Some(decls) = Self::parse_shorthand(name, input) {
return decls;
}
Self::parse_single(name, input).into_iter().collect()
}
fn parse_shorthand(name: &str, input: &mut Parser<'_, '_>) -> Option<Vec<Self>> {
Some(match name {
"margin" => Self::parse_length_rect(input, |t, r, b, l| {
[
Self::MarginTop(t),
Self::MarginRight(r),
Self::MarginBottom(b),
Self::MarginLeft(l),
]
}),
"padding" => Self::parse_length_rect(input, |t, r, b, l| {
[
Self::PaddingTop(t),
Self::PaddingRight(r),
Self::PaddingBottom(b),
Self::PaddingLeft(l),
]
}),
"border-width" => Self::parse_length_rect(input, |t, r, b, l| {
[
Self::BorderTopWidth(t),
Self::BorderRightWidth(r),
Self::BorderBottomWidth(b),
Self::BorderLeftWidth(l),
]
}),
"border-style" => parse_border_style_shorthand_values(input)
.map(|(t, r, b, l)| {
vec![
Self::BorderTopStyle(t),
Self::BorderRightStyle(r),
Self::BorderBottomStyle(b),
Self::BorderLeftStyle(l),
]
})
.unwrap_or_default(),
"border-color" => parse_color_shorthand_values(input)
.map(|(t, r, b, l)| {
vec![
Self::BorderTopColor(t),
Self::BorderRightColor(r),
Self::BorderBottomColor(b),
Self::BorderLeftColor(l),
]
})
.unwrap_or_default(),
"border" => parse_border_shorthand(input),
"border-top" => parse_border_side_shorthand(input, BorderSide::Top),
"border-right" => parse_border_side_shorthand(input, BorderSide::Right),
"border-bottom" => parse_border_side_shorthand(input, BorderSide::Bottom),
"border-left" => parse_border_side_shorthand(input, BorderSide::Left),
"list-style" => parse_list_style_shorthand(input),
_ => return None,
})
}
fn parse_length_rect<F>(input: &mut Parser<'_, '_>, make_decls: F) -> Vec<Self>
where
F: FnOnce(Length, Length, Length, Length) -> [Self; 4],
{
parse_box_shorthand_values(input)
.map(|(t, r, b, l)| make_decls(t, r, b, l).into())
.unwrap_or_default()
}
fn parse_single(name: &str, input: &mut Parser<'_, '_>) -> Option<Self> {
match name {
"color" => parse_color(input).map(Self::Color),
"background-color" => parse_color(input).map(Self::BackgroundColor),
"background" => parse_background_shorthand(input).map(Self::BackgroundColor),
"font-family" => parse_font_family(input).map(Self::FontFamily),
"font-size" => parse_font_size(input).map(Self::FontSize),
"font-weight" => parse_font_weight(input).map(Self::FontWeight),
"font-style" => parse_font_style(input).map(Self::FontStyle),
"font-variant" | "font-variant-caps" => {
parse_font_variant(input).map(Self::FontVariant)
}
"text-align" => parse_text_align(input).map(Self::TextAlign),
"text-indent" => parse_length(input).map(Self::TextIndent),
"line-height" => parse_line_height(input).map(Self::LineHeight),
"letter-spacing" => parse_length(input).map(Self::LetterSpacing),
"word-spacing" => parse_length(input).map(Self::WordSpacing),
"text-transform" => parse_text_transform(input).map(Self::TextTransform),
"hyphens" => parse_hyphens(input).map(Self::Hyphens),
"white-space" => parse_white_space(input).map(Self::WhiteSpace),
"vertical-align" => parse_vertical_align(input).map(Self::VerticalAlign),
"text-decoration" | "text-decoration-line" => {
parse_text_decoration(input).map(Self::TextDecoration)
}
"text-decoration-style" => parse_decoration_style(input).map(Self::TextDecorationStyle),
"text-decoration-color" => parse_color(input).map(Self::TextDecorationColor),
"margin-top" => parse_length(input).map(Self::MarginTop),
"margin-right" => parse_length(input).map(Self::MarginRight),
"margin-bottom" => parse_length(input).map(Self::MarginBottom),
"margin-left" => parse_length(input).map(Self::MarginLeft),
"padding-top" => parse_length(input).map(Self::PaddingTop),
"padding-right" => parse_length(input).map(Self::PaddingRight),
"padding-bottom" => parse_length(input).map(Self::PaddingBottom),
"padding-left" => parse_length(input).map(Self::PaddingLeft),
"width" => parse_length(input).map(Self::Width),
"height" => parse_length(input).map(Self::Height),
"max-width" => parse_length(input).map(Self::MaxWidth),
"max-height" => parse_length(input).map(Self::MaxHeight),
"min-width" => parse_length(input).map(Self::MinWidth),
"min-height" => parse_length(input).map(Self::MinHeight),
"display" => parse_display(input).map(Self::Display),
"float" => parse_float(input).map(Self::Float),
"clear" => parse_clear(input).map(Self::Clear),
"visibility" => parse_visibility(input).map(Self::Visibility),
"box-sizing" => parse_box_sizing(input).map(Self::BoxSizing),
"orphans" => parse_integer(input).map(Self::Orphans),
"widows" => parse_integer(input).map(Self::Widows),
"word-break" => parse_word_break(input).map(Self::WordBreak),
"overflow-wrap" => parse_overflow_wrap(input).map(Self::OverflowWrap),
"break-before" | "page-break-before" => parse_break_value(input).map(Self::BreakBefore),
"break-after" | "page-break-after" => parse_break_value(input).map(Self::BreakAfter),
"break-inside" | "page-break-inside" => {
parse_break_inside(input).map(Self::BreakInside)
}
"border-top-style" => parse_border_style_value(input).map(Self::BorderTopStyle),
"border-right-style" => parse_border_style_value(input).map(Self::BorderRightStyle),
"border-bottom-style" => parse_border_style_value(input).map(Self::BorderBottomStyle),
"border-left-style" => parse_border_style_value(input).map(Self::BorderLeftStyle),
"border-top-width" => parse_length(input).map(Self::BorderTopWidth),
"border-right-width" => parse_length(input).map(Self::BorderRightWidth),
"border-bottom-width" => parse_length(input).map(Self::BorderBottomWidth),
"border-left-width" => parse_length(input).map(Self::BorderLeftWidth),
"border-top-color" => parse_color(input).map(Self::BorderTopColor),
"border-right-color" => parse_color(input).map(Self::BorderRightColor),
"border-bottom-color" => parse_color(input).map(Self::BorderBottomColor),
"border-left-color" => parse_color(input).map(Self::BorderLeftColor),
"border-radius" => parse_length(input).map(Self::BorderRadius),
"border-top-left-radius" => parse_length(input).map(Self::BorderTopLeftRadius),
"border-top-right-radius" => parse_length(input).map(Self::BorderTopRightRadius),
"border-bottom-left-radius" => parse_length(input).map(Self::BorderBottomLeftRadius),
"border-bottom-right-radius" => parse_length(input).map(Self::BorderBottomRightRadius),
"list-style-type" => parse_list_style_type(input).map(Self::ListStyleType),
"list-style-position" => parse_list_style_position(input).map(Self::ListStylePosition),
"border-collapse" => parse_border_collapse(input).map(Self::BorderCollapse),
"border-spacing" => parse_length(input).map(Self::BorderSpacing),
_ => {
while input.next().is_ok() {}
None
}
}
}
}