use std::collections::HashSet;
use oxc_allocator::Allocator;
use oxc_ast::ast::{StringLiteral, TemplateLiteral};
use oxc_parser::Parser;
use oxc_span::SourceType;
use crate::rwe::class_notation::extract_tailwind_tokens_from_class_value;
use super::compiler::token_css_rule;
struct StringLiteralCollector {
candidates: Vec<String>,
}
impl<'a> oxc_ast_visit::Visit<'a> for StringLiteralCollector {
fn visit_string_literal(&mut self, lit: &StringLiteral<'a>) {
self.candidates.push(lit.value.to_string());
}
fn visit_template_literal(&mut self, lit: &TemplateLiteral<'a>) {
for quasi in &lit.quasis {
let s = quasi.value.raw.as_str();
if !s.trim().is_empty() {
self.candidates.push(s.to_string());
}
}
oxc_ast_visit::walk::walk_template_literal(self, lit);
}
}
pub fn collect_source_tokens(js_source: &str) -> HashSet<String> {
let alloc = Allocator::default();
let source_type = SourceType::default()
.with_module(true)
.with_jsx(true)
.with_typescript(true);
let parsed = Parser::new(&alloc, js_source, source_type).parse();
if parsed.panicked {
return HashSet::new();
}
let mut collector = StringLiteralCollector {
candidates: Vec::new(),
};
oxc_ast_visit::walk::walk_program(&mut collector, &parsed.program);
let mut tokens = HashSet::new();
for candidate in collector.candidates {
for token in extract_tailwind_tokens_from_class_value(&candidate) {
if token_css_rule(&token).is_some() {
tokens.insert(token);
}
}
}
tokens
}