# jsmeld
A wrapper around SWC for compiling and bundling JavaScript in Rust and Python.
## Rust usage
Both `compile` and `bundle` take a file path and a `JSMeldOptions` struct:
```rust
use jsmeld::{compile, bundle, JSMeldOptions};
// Compile a single file
let output = compile(
"./src/app.ts".to_string(),
JSMeldOptions {
target: "es2020".to_string(),
minify: true,
..Default::default()
},
)?;
// Bundle an entry point
let output = bundle(
"./src/index.js".to_string(),
JSMeldOptions {
target: "es2020".to_string(),
externals: vec!["react".to_string()],
..Default::default()
},
)?;
```
### `JSMeldOptions`
A single unified options struct used by both compilation and bundling.
| `target` | `String` | `"es6"` | both |
| `minify` | `bool` | `false` | both |
| `source_map` | `bool` | `true` | both |
| `typescript` | `bool` | `true` | compile |
| `module` | `String` | `"esm"` | compile |
| `strict` | `bool` | `true` | compile |
| `code_split` | `bool` | `false` | bundle |
| `externals` | `Vec<String>` | `[]` | bundle |
| `style_hooks` | `HashMap<String, Vec<StyleTransformHook>>` | `{}` | bundle |
### Style hooks
`JSMeldOptions` supports style transformation hooks keyed by file extension.
Hooks are executed in order when a matching style file is loaded during bundling.
Each key is a file extension (e.g. `"css"`, `"less"`) and each value is an ordered list of hook closures.
Hook type:
```rust
type StyleTransformHook = Arc<dyn Fn(&Path, &str) -> Result<String, String> + Send + Sync>;
```
#### Registering hooks in `JSMeldOptions`
```rust
use std::sync::Arc;
use std::collections::HashMap;
use jsmeld::{Bundler, JSMeldOptions};
let mut options = JSMeldOptions::default();
options.style_hooks.insert(
"less".to_string(),
vec![Arc::new(|_path, source| {
// transform LESS -> CSS here
Ok(source.to_string())
})],
);
options.style_hooks.entry("css".to_string()).or_default().push(
Arc::new(|_path, source| {
// post-process CSS here
Ok(source.to_string())
}),
);
let bundler = Bundler::new(options);
let output = bundler.bundle("./src/index.js")?;
```
#### Registering hooks via `Bundler`
If you initialize a `Bundler` with options, you can append hooks per extension:
```rust
use std::sync::Arc;
use jsmeld::{Bundler, JSMeldOptions};
let mut bundler = Bundler::new(JSMeldOptions::default());
`style_hooks` can be passed as a dictionary mapping file extensions to lists
of callables `(path: str, source: str) -> str`:
```python
def add_banner(path: str, source: str) -> str:
return f"/* bundled by jsmeld */\n{source}"
output = jsmeld.bundle("src/index.js", {
"style_hooks": {
"css": [add_banner],
},
})
```