tcss_wasm/
lib.rs

1//! TCSS WebAssembly Bindings
2//!
3//! This module provides WebAssembly bindings for the TCSS compiler,
4//! allowing it to be used in web browsers and Node.js environments.
5//!
6//! # Example (JavaScript)
7//!
8//! ```javascript
9//! import init, { compile_tcss } from './tcss_wasm.js';
10//!
11//! await init();
12//!
13//! const tcss = `
14//! @var primary: #3498db
15//! .button:
16//!     background: primary
17//!     padding: 16px
18//! `;
19//!
20//! const css = compile_tcss(tcss);
21//! console.log(css);
22//! ```
23
24use wasm_bindgen::prelude::*;
25use tcss_core::{Lexer, Parser, Generator, GeneratorOptions};
26
27/// Initialize the WASM module
28///
29/// This sets up panic hooks for better error messages in the browser console.
30#[wasm_bindgen(start)]
31pub fn init() {
32    #[cfg(feature = "console_error_panic_hook")]
33    console_error_panic_hook::set_once();
34}
35
36/// Compile TCSS source code to CSS
37///
38/// # Arguments
39///
40/// * `input` - The TCSS source code as a string
41///
42/// # Returns
43///
44/// Returns the compiled CSS as a string, or throws a JavaScript error if compilation fails.
45///
46/// # Example (JavaScript)
47///
48/// ```javascript
49/// const css = compile_tcss('.button:\n    padding: 16px');
50/// console.log(css); // ".button {\n  padding: 16px;\n}\n"
51/// ```
52#[wasm_bindgen]
53pub fn compile_tcss(input: &str) -> Result<String, JsValue> {
54    compile_tcss_with_options(input, false)
55}
56
57/// Compile TCSS source code to minified CSS
58///
59/// # Arguments
60///
61/// * `input` - The TCSS source code as a string
62///
63/// # Returns
64///
65/// Returns the compiled and minified CSS as a string, or throws a JavaScript error if compilation fails.
66///
67/// # Example (JavaScript)
68///
69/// ```javascript
70/// const css = compile_tcss_minified('.button:\n    padding: 16px');
71/// console.log(css); // ".button{padding:16px;}"
72/// ```
73#[wasm_bindgen]
74pub fn compile_tcss_minified(input: &str) -> Result<String, JsValue> {
75    compile_tcss_with_options(input, true)
76}
77
78/// Compile TCSS source code to CSS with custom options
79///
80/// # Arguments
81///
82/// * `input` - The TCSS source code as a string
83/// * `minify` - Whether to minify the output CSS
84///
85/// # Returns
86///
87/// Returns the compiled CSS as a string, or throws a JavaScript error if compilation fails.
88#[wasm_bindgen]
89pub fn compile_tcss_with_options(input: &str, minify: bool) -> Result<String, JsValue> {
90    // Tokenize
91    let mut lexer = Lexer::new(input);
92    let tokens = lexer
93        .tokenize()
94        .map_err(|e| JsValue::from_str(&format!("Lexer error: {}", e)))?;
95
96    // Parse
97    let mut parser = Parser::new(tokens);
98    let program = parser
99        .parse()
100        .map_err(|e| JsValue::from_str(&format!("Parser error: {}", e)))?;
101
102    // Generate CSS
103    let mut generator = Generator::with_options(GeneratorOptions {
104        minify,
105        indent: "  ".to_string(),
106        trailing_newline: true,
107    });
108
109    let css = generator
110        .generate(&program)
111        .map_err(|e| JsValue::from_str(&format!("Generator error: {}", e)))?;
112
113    Ok(css)
114}
115
116/// Parse TCSS source code and return the AST as JSON
117///
118/// This is useful for debugging and tooling purposes.
119///
120/// # Arguments
121///
122/// * `input` - The TCSS source code as a string
123///
124/// # Returns
125///
126/// Returns the AST as a JSON string, or throws a JavaScript error if parsing fails.
127#[wasm_bindgen]
128pub fn parse_tcss(input: &str) -> Result<JsValue, JsValue> {
129    // Tokenize
130    let mut lexer = Lexer::new(input);
131    let tokens = lexer
132        .tokenize()
133        .map_err(|e| JsValue::from_str(&format!("Lexer error: {}", e)))?;
134
135    // Parse
136    let mut parser = Parser::new(tokens);
137    let program = parser
138        .parse()
139        .map_err(|e| JsValue::from_str(&format!("Parser error: {}", e)))?;
140
141    // Convert to JsValue using serde
142    serde_wasm_bindgen::to_value(&program)
143        .map_err(|e| JsValue::from_str(&format!("Serialization error: {}", e)))
144}
145
146/// Validate TCSS source code without generating CSS
147///
148/// # Arguments
149///
150/// * `input` - The TCSS source code as a string
151///
152/// # Returns
153///
154/// Returns `true` if the TCSS is valid, or throws a JavaScript error with details if invalid.
155#[wasm_bindgen]
156pub fn validate_tcss(input: &str) -> Result<bool, JsValue> {
157    // Tokenize
158    let mut lexer = Lexer::new(input);
159    let tokens = lexer
160        .tokenize()
161        .map_err(|e| JsValue::from_str(&format!("Lexer error: {}", e)))?;
162
163    // Parse
164    let mut parser = Parser::new(tokens);
165    parser
166        .parse()
167        .map_err(|e| JsValue::from_str(&format!("Parser error: {}", e)))?;
168
169    Ok(true)
170}
171