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