Skip to main content

morph_parser/
lib.rs

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
12/// Parse an .mx file (which is TSX) and return a structured representation.
13pub 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
22/// Parse .mx source text into structured representation.
23pub 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
59/// Parse external CSS text into style rules + `@keyframes`.
60pub fn parse_css(source: &str) -> Result<ast_types::CssData> {
61    css_parser::parse_css(source)
62}