use super::super::{PResult, Span};
use super::opt_spacelike;
use super::strings::custom_value;
use super::{comment, import2, strings, values};
use crate::css::parser::selector_set;
use crate::css::{BodyItem, CustomProperty, Property, Rule};
use nom::branch::alt;
use nom::bytes::complete::tag;
use nom::character::complete::one_of;
use nom::combinator::{into, map, opt};
use nom::multi::many_till;
use nom::sequence::{delimited, pair, preceded, terminated};
use nom::Parser as _;
pub fn rule(input: Span) -> PResult<Rule> {
map(
pair(
terminated(selector_set, terminated(tag("{"), opt_spacelike)),
many_till(terminated(body_item, opt_spacelike), tag("}")),
),
|(selectors, (body, _))| Rule { selectors, body },
)
.parse(input)
}
fn body_item(input: Span) -> PResult<BodyItem> {
alt((
into(comment),
into(preceded(tag("@import"), import2)),
property,
))
.parse(input)
}
pub fn property(input: Span) -> PResult<BodyItem> {
let (rest, name) = terminated(property_name, tag(":")).parse(input)?;
if name.starts_with("--") {
let (rest, value) =
terminated(custom_value, opt(tag(";"))).parse(rest)?;
Ok((rest, CustomProperty::new(name, value).into()))
} else {
let (rest, value) =
delimited(opt_spacelike, values::any, opt(tag(";")))
.parse(rest)?;
Ok((rest, Property::new(name, value).into()))
}
}
fn property_name(input: Span) -> PResult<String> {
map(
pair(opt(one_of("*:.")), strings::css_string),
|(pre, mut main)| {
if let Some(pre) = pre {
main.insert(0, pre);
}
main
},
)
.parse(input)
}