not-tailwind 0.2.0

A tool for shortening css classes
Documentation
use crate::visit_selectors::ClassVisitor;

use swc_core::{
    common::{sync::Lrc, FileName, SourceMap},
    ecma::{
        codegen::{text_writer::JsWriter, Emitter},
        parser::{lexer::Lexer, Parser, StringInput},
        visit::{Fold, VisitMut, VisitMutWith},
    },
};

pub fn check_js(
    old_content: &String,
    class_visitor: &ClassVisitor,
) -> Option<Vec<u8>> {
    let mut map_visitor = MapVisitor::new(class_visitor);
    let cm: Lrc<SourceMap> = Default::default();
    let fm = cm.new_source_file(
        Lrc::new(FileName::Custom("test.js".into())),
        old_content.into(),
    );
    let lexer = Lexer::new(
        swc_core::ecma::parser::Syntax::Es(Default::default()),
        Default::default(),
        StringInput::from(&*fm),
        None,
    );
    let mut parser = Parser::new_from(lexer);
    let s = parser.parse_module();
    let mut code = vec![];
    let mut srcmap = vec![];
    match s {
        Ok(mut module) => {
            module.visit_mut_with(&mut map_visitor);

            {
                let mut emitter = Emitter {
                    cfg: Default::default(),
                    cm: cm.clone(),
                    comments: None,
                    wr: JsWriter::new(
                        cm.clone(),
                        "\n",
                        &mut code,
                        Some(&mut srcmap),
                    ),
                };
                if emitter.emit_module(&module).is_ok() {
                    return Some(code);
                }
                None
            }
        }
        Err(e) => {
            dbg!(e);
            None
        }
    }
}

pub struct MapVisitor<'a> {
    pub is_set: bool,
    pub first_string: Option<String>,
    pub class_visitor: &'a ClassVisitor,
}

impl<'a> MapVisitor<'a> {
    fn new(class_visitor: &'a ClassVisitor) -> Self {
        Self {
            is_set: false,
            first_string: None,
            class_visitor,
        }
    }
}

impl<'a> Fold for MapVisitor<'a> {}

impl<'a> VisitMut for MapVisitor<'a> {
    fn visit_mut_ident_name(&mut self, n: &mut swc_core::ecma::ast::IdentName) {
        let s = n.to_string();
        if s.starts_with("set") {
            self.is_set = true;
        } else {
            self.is_set = false;
            self.first_string = None;
        }
    }

    fn visit_mut_str(&mut self, n: &mut swc_core::ecma::ast::Str) {
        if self.is_set {
            match &self.first_string {
                Some(s) => {
                    let mut custom_variable = "";
                    let new_str = &self.class_visitor.get(s).or_else(|| {
                        custom_variable = "--";
                        self.class_visitor.get_custom_property(s)
                    });
                    if let Some(new_str) = new_str {
                        let new_str =
                            format!("'{}{}'", custom_variable, new_str);
                        n.raw = Some(new_str.into());
                    }
                    self.is_set = false;
                    self.first_string = None;
                }
                None => {
                    self.is_set = true;
                    self.first_string = Some(n.value.to_string());
                }
            }
        }
    }
}