1use anyhow::{bail, Result};
2use std::path::Path;
3
4pub(crate) mod ast_types;
5pub(crate) mod js_walker;
6mod css_parser;
7pub mod linter;
8
9pub use ast_types::*;
10pub use linter::{check as lint_check, lint};
11
12pub fn parse_mx_file(path: &Path) -> Result<MxSource> {
14 let source = std::fs::read_to_string(path)?;
15 let filename = path
16 .file_name()
17 .map(|f| f.to_string_lossy().to_string())
18 .unwrap_or_default();
19 parse_mx_str(&source, &filename)
20}
21
22pub fn parse_mx_str(source: &str, filename: &str) -> Result<MxSource> {
24 let allocator = oxc_allocator::Allocator::default();
25 let source_type = oxc_span::SourceType::from_path("file.tsx").unwrap();
26
27 let ret = oxc_parser::Parser::new(&allocator, source, source_type).parse();
28
29 if ret.panicked {
30 bail!("Parser panicked on {filename}");
31 }
32 if !ret.diagnostics.is_empty() {
33 let msgs: Vec<String> = ret.diagnostics.iter().map(|d| d.to_string()).collect();
34 bail!("Parse errors in {filename}: {}", msgs.join("; "));
35 }
36
37 let mut walker = js_walker::MxWalker::new(source);
38 {
39 use oxc_ast_visit::Visit;
40 walker.visit_program(&ret.program);
41 }
42
43 Ok(MxSource {
44 filename: filename.to_string(),
45 imports: walker.imports,
46 window_config: walker.window_config,
47 components: walker.components,
48 state_vars: walker.state_vars,
49 effects: walker.effects,
50 inner_functions: walker.inner_functions,
51 function_declarations: walker.function_declarations,
52 global_vars: walker.global_vars,
53 console_logs: walker.console_logs,
54 extra_headers: walker.extra_headers,
55 cpp_imports: walker.cpp_imports,
56 })
57}
58
59pub fn parse_css(source: &str) -> Result<ast_types::CssData> {
61 css_parser::parse_css(source)
62}