not_tailwind/
visit_map.rs

1use crate::visit_selectors::ClassVisitor;
2
3use swc_core::{
4    common::{sync::Lrc, FileName, SourceMap},
5    ecma::{
6        codegen::{text_writer::JsWriter, Emitter},
7        parser::{lexer::Lexer, Parser, StringInput},
8        visit::{Fold, VisitMut, VisitMutWith},
9    },
10};
11
12pub fn check_js(
13    old_content: &String,
14    class_visitor: &ClassVisitor,
15) -> Option<Vec<u8>> {
16    let mut map_visitor = MapVisitor::new(class_visitor);
17    let cm: Lrc<SourceMap> = Default::default();
18    let fm = cm.new_source_file(
19        Lrc::new(FileName::Custom("test.js".into())),
20        old_content.into(),
21    );
22    let lexer = Lexer::new(
23        swc_core::ecma::parser::Syntax::Es(Default::default()),
24        Default::default(),
25        StringInput::from(&*fm),
26        None,
27    );
28    let mut parser = Parser::new_from(lexer);
29    let s = parser.parse_module();
30    let mut code = vec![];
31    let mut srcmap = vec![];
32    match s {
33        Ok(mut module) => {
34            module.visit_mut_with(&mut map_visitor);
35
36            {
37                let mut emitter = Emitter {
38                    cfg: Default::default(),
39                    cm: cm.clone(),
40                    comments: None,
41                    wr: JsWriter::new(
42                        cm.clone(),
43                        "\n",
44                        &mut code,
45                        Some(&mut srcmap),
46                    ),
47                };
48                if emitter.emit_module(&module).is_ok() {
49                    return Some(code);
50                }
51                None
52            }
53        }
54        Err(e) => {
55            dbg!(e);
56            None
57        }
58    }
59}
60
61pub struct MapVisitor<'a> {
62    pub is_set: bool,
63    pub first_string: Option<String>,
64    pub class_visitor: &'a ClassVisitor,
65}
66
67impl<'a> MapVisitor<'a> {
68    fn new(class_visitor: &'a ClassVisitor) -> Self {
69        Self {
70            is_set: false,
71            first_string: None,
72            class_visitor,
73        }
74    }
75}
76
77impl<'a> Fold for MapVisitor<'a> {}
78
79impl<'a> VisitMut for MapVisitor<'a> {
80    fn visit_mut_ident_name(&mut self, n: &mut swc_core::ecma::ast::IdentName) {
81        let s = n.to_string();
82        if s.starts_with("set") {
83            self.is_set = true;
84        } else {
85            self.is_set = false;
86            self.first_string = None;
87        }
88    }
89
90    fn visit_mut_str(&mut self, n: &mut swc_core::ecma::ast::Str) {
91        if self.is_set {
92            match &self.first_string {
93                Some(s) => {
94                    let mut custom_variable = "";
95                    let new_str = &self.class_visitor.get(s).or_else(|| {
96                        custom_variable = "--";
97                        self.class_visitor.get_custom_property(s)
98                    });
99                    if let Some(new_str) = new_str {
100                        let new_str =
101                            format!("'{}{}'", custom_variable, new_str);
102                        n.raw = Some(new_str.into());
103                    }
104                    self.is_set = false;
105                    self.first_string = None;
106                }
107                None => {
108                    self.is_set = true;
109                    self.first_string = Some(n.value.to_string());
110                }
111            }
112        }
113    }
114}