use super::{
selectors::Opt, AtRule, Comment, CssString, Import, SelectorSet, Value,
};
use crate::output::CssBuf;
use std::io;
#[derive(Clone, Debug)]
pub struct Rule {
pub(crate) selectors: SelectorSet,
pub(crate) body: Vec<BodyItem>,
}
impl Rule {
pub fn new(selectors: SelectorSet) -> Self {
Self {
selectors,
body: Vec::new(),
}
}
pub fn push(&mut self, item: BodyItem) {
self.body.push(item);
}
pub(crate) fn write(&self, buf: &mut CssBuf) -> io::Result<()> {
if !self.body.is_empty() {
let s = self.selectors.no_placeholder();
if matches!(s, Opt::None) {
return Ok(());
}
buf.do_indent_no_nl();
let p = buf.len();
if let Opt::Some(s) = s {
s.write_to(buf);
}
if buf.len() == p {
buf.add_str("*");
}
buf.start_block();
for item in &self.body {
item.write(buf)?;
}
buf.end_block();
}
Ok(())
}
}
#[derive(Clone, Debug)]
pub enum BodyItem {
Import(Import),
Property(Property),
CustomProperty(CustomProperty),
Comment(Comment),
ARule(AtRule),
}
impl BodyItem {
pub(crate) fn write(&self, buf: &mut CssBuf) -> io::Result<()> {
match self {
Self::Comment(c) => c.write(buf),
Self::Import(import) => import.write(buf)?,
Self::Property(property) => property.write(buf),
Self::CustomProperty(property) => property.write(buf),
Self::ARule(rule) => rule.write(buf)?,
}
Ok(())
}
}
impl From<Comment> for BodyItem {
fn from(comment: Comment) -> Self {
Self::Comment(comment)
}
}
impl From<Import> for BodyItem {
fn from(import: Import) -> Self {
Self::Import(import)
}
}
impl From<Property> for BodyItem {
fn from(property: Property) -> Self {
Self::Property(property)
}
}
impl From<CustomProperty> for BodyItem {
fn from(property: CustomProperty) -> Self {
Self::CustomProperty(property)
}
}
impl TryFrom<AtRule> for BodyItem {
type Error = AtRule;
fn try_from(value: AtRule) -> Result<Self, Self::Error> {
if value.no_body() {
Ok(Self::ARule(value))
} else {
Err(value)
}
}
}
#[derive(Clone, Debug)]
pub struct Property {
name: String,
value: Value,
}
impl Property {
pub fn new(name: String, value: Value) -> Self {
Self { name, value }
}
pub(crate) fn write(&self, buf: &mut CssBuf) {
buf.do_indent_no_nl();
buf.add_str(&self.name);
buf.add_one(": ", ":");
buf.add_str(&self.value.to_string(buf.format()).replace('\n', " "));
buf.add_one(";\n", ";");
}
}
#[derive(Clone, Debug)]
pub struct CustomProperty {
name: String,
value: CssString,
}
impl CustomProperty {
pub fn new(name: String, value: CssString) -> Self {
Self { name, value }
}
pub(crate) fn write(&self, buf: &mut CssBuf) {
buf.do_indent_no_nl();
buf.add_str(&self.name);
buf.add_str(":");
if !(self.value.quotes().is_none() || buf.format().is_compressed()) {
buf.add_str(" ");
}
buf.add_str(&self.value.to_string());
buf.add_one(";\n", ";");
}
}