less-rs 0.0.0

A Rust implementation of the Less CSS preprocessor.
Documentation
use std::{fmt, marker::PhantomData};

use cssparser::ToCss;
use selectors::parser::Selector;

use crate::{
  error::ParserError,
  rules::variable::VariableCurly,
  values::{ident::CssIdent, namespace::Namespace, string::CssString},
};

mod private {
  #[derive(Clone, Debug)]
  pub struct SelectorImpl;
}

use private::SelectorImpl;

impl<'i> selectors::SelectorImpl<'i> for SelectorImpl {
  type ExtraMatchingData = ();

  type AttrValue = CssString<'i>;

  type Identifier = CssIdent<'i>;

  type LocalName = CssIdent<'i>;

  type NamespaceUrl = Namespace<'i>;

  type NamespacePrefix = CssIdent<'i>;

  type BorrowedNamespaceUrl = Namespace<'i>;

  type BorrowedLocalName = CssIdent<'i>;

  type NonTSPseudoClass = NonTSPseudoClass<'i>;

  type VendorPrefix = VendorPrefix;

  type PseudoElement = PseudoElement<'i>;

  type VariableCurly = VariableCurly<'i>;
}

// TODO: Less does not care about this
#[derive(Clone, PartialEq, Eq, Hash)]
pub struct VendorPrefix;

impl cssparser::ToCss for VendorPrefix {
  fn to_css<W>(&self, dest: &mut W) -> std::fmt::Result
  where
    W: std::fmt::Write,
  {
    todo!()
  }
}

#[derive(Clone, PartialEq, Eq, Hash)]
pub enum NonTSPseudoClass<'i> {
  Before,
  After,
  TODO(PhantomData<&'i ()>),
}

impl<'i> selectors::parser::NonTSPseudoClass<'i> for NonTSPseudoClass<'i> {
  type Impl = SelectorImpl;

  fn is_active_or_hover(&self) -> bool {
    todo!()
  }

  fn is_user_action_state(&self) -> bool {
    todo!()
  }
}

impl<'i> ToCss for NonTSPseudoClass<'i> {
  fn to_css<W>(&self, dest: &mut W) -> std::fmt::Result
  where
    W: std::fmt::Write,
  {
    todo!()
  }
}

#[derive(Clone, PartialEq, Eq, Hash)]
pub enum PseudoElement<'i> {
  Before,
  After,
  TODO(PhantomData<&'i ()>),
}

impl<'i> selectors::parser::PseudoElement<'i> for PseudoElement<'i> {
  type Impl = SelectorImpl;
}

impl<'i> ToCss for PseudoElement<'i> {
  fn to_css<W>(&self, dest: &mut W) -> std::fmt::Result
  where
    W: std::fmt::Write,
  {
    todo!()
  }
}

pub type SelectorList<'i> = selectors::SelectorList<'i, SelectorImpl>;

pub struct SelectorParser {}

impl<'i> selectors::Parser<'i> for SelectorParser {
  type Impl = SelectorImpl;

  type Error = ParserError<'i>;

  fn parse_slotted(&self) -> bool {
    false
  }

  fn parse_part(&self) -> bool {
    false
  }

  fn parse_is_and_where(&self) -> bool {
    false
  }

  fn is_and_where_error_recovery(&self) -> selectors::parser::ParseErrorRecovery {
    selectors::parser::ParseErrorRecovery::IgnoreInvalidSelector
  }

  fn parse_any_prefix(
    &self,
    _name: &str,
  ) -> Option<<Self::Impl as selectors::SelectorImpl<'i>>::VendorPrefix> {
    None
  }

  fn parse_host(&self) -> bool {
    false
  }

  fn parse_non_ts_pseudo_class(
    &self,
    location: cssparser::SourceLocation,
    name: cssparser::CowRcStr<'i>,
  ) -> Result<
    <Self::Impl as selectors::SelectorImpl<'i>>::NonTSPseudoClass,
    cssparser::ParseError<'i, Self::Error>,
  > {
    Err(
      location
        .new_custom_error(selectors::parser::SelectorParseErrorKind::UnsupportedPseudoClass(name)),
    )
  }

  fn parse_non_ts_functional_pseudo_class<'t>(
    &self,
    name: cssparser::CowRcStr<'i>,
    arguments: &mut cssparser::Parser<'i, 't>,
  ) -> Result<
    <Self::Impl as selectors::SelectorImpl<'i>>::NonTSPseudoClass,
    cssparser::ParseError<'i, Self::Error>,
  > {
    Err(
      arguments
        .new_custom_error(selectors::parser::SelectorParseErrorKind::UnsupportedPseudoClass(name)),
    )
  }

  fn parse_pseudo_element(
    &self,
    location: cssparser::SourceLocation,
    name: cssparser::CowRcStr<'i>,
  ) -> Result<
    <Self::Impl as selectors::SelectorImpl<'i>>::PseudoElement,
    cssparser::ParseError<'i, Self::Error>,
  > {
    Err(
      location.new_custom_error(
        selectors::parser::SelectorParseErrorKind::UnsupportedPseudoElement(name),
      ),
    )
  }

  fn parse_functional_pseudo_element<'t>(
    &self,
    name: cssparser::CowRcStr<'i>,
    arguments: &mut cssparser::Parser<'i, 't>,
  ) -> Result<
    <Self::Impl as selectors::SelectorImpl<'i>>::PseudoElement,
    cssparser::ParseError<'i, Self::Error>,
  > {
    Err(
      arguments.new_custom_error(
        selectors::parser::SelectorParseErrorKind::UnsupportedPseudoElement(name),
      ),
    )
  }

  fn default_namespace(&self) -> Option<<Self::Impl as selectors::SelectorImpl<'i>>::NamespaceUrl> {
    None
  }

  fn namespace_for_prefix(
    &self,
    _prefix: &<Self::Impl as selectors::SelectorImpl<'i>>::NamespacePrefix,
  ) -> Option<<Self::Impl as selectors::SelectorImpl<'i>>::NamespaceUrl> {
    None
  }

  fn is_nesting_allowed(&self) -> bool {
    false
  }

  fn deep_combinator_enabled(&self) -> bool {
    false
  }
}

fn serialize_selector_list<'a, 'i: 'a, Impl, I, W>(iter: I, dest: &mut W) -> fmt::Result
where
  Impl: selectors::SelectorImpl<'i>,
  I: Iterator<Item = &'a Selector<'i, Impl>>,
  W: fmt::Write,
{
  let mut first = true;
  for selector in iter {
    if !first {
      dest.write_str(", ")?;
    }
    first = false;
    selector.to_css(dest)?;
  }
  Ok(())
}