scoped_css 0.0.1

A crate for the css! macro
Documentation
use crate::parser_types::*;

use crate::{
  core::{
    parse_any,
    parse_ident,
    parse_punct,
  },
  types::{
    PropertyBlock,
    Rule,
    RuleOrProperty,
    RuleSet,
  },
  util::{
    alt,
    many_0,
    many_0_joint,
    take_until_and_match,
  },
};

use proc_macro2::Delimiter;

use std::collections::HashMap;

use nom::combinator::map;

fn parse_property(input: TokenStream) -> TokenStreamIResult<(String, String)> {
  let (rest, property_name) = map(
    many_0_joint(alt(
      map(parse_ident, |ident| ident.to_string()),
      map(
        |input| parse_punct(input, None, Some('-')),
        |punct| punct.to_string(),
      ),
    )),
    |vec| vec.join(""),
  )(input)?;

  let (rest, _colon) = parse_punct(rest, None, Some(':'))?;
  let (rest, (property_values, _semicolon)) =
    take_until_and_match(|input| parse_punct(input, None, Some(';')))(rest)?;

  let (_rest, grouped_property_values) = many_0(many_0_joint(parse_any))(property_values)?;

  let property_values_string = grouped_property_values
    .into_iter()
    .map(|vec| {
      vec
        .into_iter()
        .map(|g| g.to_string())
        .collect::<Vec<_>>()
        .join("")
    })
    .collect::<Vec<_>>()
    .join(" ");

  Ok((rest, (property_name, property_values_string)))
}

fn parse_rule_or_property(input: TokenStream) -> TokenStreamIResult<RuleOrProperty> {
  alt(
    map(parse_property, |property| {
      RuleOrProperty::Property(property)
    }),
    map(parse_rule, |rule| RuleOrProperty::Rule(rule)),
  )(input)
}

fn parse_rule(input: TokenStream) -> TokenStreamIResult<Rule> {
  let (rest, nested_selector_list) = crate::selector::parse_nested_selector_list(input)?;
  let (rest, group_contents) =
    crate::core::parse_group_with_delimiter(rest, Some(Delimiter::Brace))?;

  let (inner_rest, (properties, nested_rules)) = map(
    crate::util::many_0(parse_rule_or_property),
    |rule_or_property_vec| {
      rule_or_property_vec.into_iter().fold(
        (HashMap::new(), vec![]),
        |(mut properties, mut nested_rules), rule_or_property| {
          match rule_or_property {
            RuleOrProperty::Rule(r) => {
              nested_rules.push(r);
            },
            RuleOrProperty::Property((key, val)) => {
              properties.insert(key, val);
            },
          };
          (properties, nested_rules)
        },
      )
    },
  )(group_contents)?;
  crate::util::ensure_consumed(inner_rest)?;
  Ok((
    rest,
    Rule {
      nested_selector_list,
      property_block: PropertyBlock {
        properties,
        nested_rules,
      },
    },
  ))
}

pub fn parse_rule_set(input: TokenStream) -> TokenStreamIResult<RuleSet> {
  let (rest, rules) = crate::util::many_0(parse_rule)(input)?;
  Ok((rest, RuleSet(rules)))
}