less-rs 0.0.0

A Rust implementation of the Less CSS preprocessor.
Documentation
use std::{
  fmt::Write,
  ops::{Deref, DerefMut},
};

use less_allocator::{Box, Vec};
use variable::Variable;

use crate::{
  parser::DeclarationList,
  printer::{Printer, PrinterError},
  selector::SelectorList,
  traits::ToCss,
};

pub mod variable;

#[derive(Debug)]
pub struct CssRuleList<'i>(pub(crate) Vec<'i, CssRule<'i>>);

impl<'i> ToCss<'i> for CssRuleList<'i> {
  fn to_css<W: std::fmt::Write>(
    &self,
    dest: &mut Printer<'_, 'i, W>,
  ) -> Result<(), PrinterError<'i>> {
    let variables = Vec::from_iter_in(
      self.0.iter().filter_map(|rule| {
        if let CssRule::LessVariable(variable) = rule {
          Some(&*variable.0)
        } else {
          None
        }
      }),
      dest.allocator,
    );

    dest.with_context(variables, |dest| {
      self.0.iter().try_for_each(|rule| rule.to_css(dest))
    })?;

    Ok(())
  }
}

#[derive(Debug)]
pub struct StyleRule<'i> {
  pub selector: SelectorList<'i>,
  pub declarations: DeclarationList<'i>,
  pub rules: CssRuleList<'i>,
}

impl<'i> ToCss<'i> for StyleRule<'i> {
  fn to_css<W: std::fmt::Write>(
    &self,
    dest: &mut Printer<'_, 'i, W>,
  ) -> Result<(), PrinterError<'i>> {
    // TODO: remove this as both `CssRules` and `StyleRule` have their own variables,
    // which is basically the same.
    let variables = Vec::from_iter_in(
      self.rules.iter().filter_map(|rule| {
        if let CssRule::LessVariable(variable) = rule {
          Some(&*variable.0)
        } else {
          None
        }
      }),
      dest.allocator,
    );

    dest.write_str(".class {")?;
    dest.write_newline()?;
    dest.with_context(variables, |dest| self.declarations.to_css(dest))?;
    self.rules.to_css(dest)?;
    dest.write_char('}')?;
    Ok(())
  }
}

#[derive(Debug)]
pub enum CssRule<'i> {
  /// A Style rule
  /// https://drafts.csswg.org/cssom-1/#the-cssstylerule-interface
  Style(Box<'i, StyleRule<'i>>),
  LessVariable(Box<'i, Variable<'i>>),
}

impl<'i> ToCss<'i> for CssRule<'i> {
  fn to_css<W: std::fmt::Write>(
    &self,
    dest: &mut Printer<'_, 'i, W>,
  ) -> Result<(), PrinterError<'i>> {
    match self {
      CssRule::Style(rule) => {
        rule.to_css(dest)?;
      }
      CssRule::LessVariable(_) => {}
    }
    Ok(())
  }
}

impl<'i> Deref for CssRuleList<'i> {
  type Target = Vec<'i, CssRule<'i>>;

  fn deref(&self) -> &Self::Target {
    &self.0
  }
}

impl DerefMut for CssRuleList<'_> {
  fn deref_mut(&mut self) -> &mut Self::Target {
    &mut self.0
  }
}