pub struct MinifyOutcome {
pub content: String,
pub had_error: bool,
}
pub fn minify(content: String) -> MinifyOutcome {
minify_impl(content)
}
#[cfg(all(feature = "minify", not(target_family = "wasm")))]
fn minify_impl(content: String) -> MinifyOutcome {
match try_minify(&content) {
Some(minified) => MinifyOutcome {
content: minified,
had_error: false,
},
None => MinifyOutcome {
content,
had_error: true,
},
}
}
#[cfg(not(all(feature = "minify", not(target_family = "wasm"))))]
fn minify_impl(content: String) -> MinifyOutcome {
MinifyOutcome {
content,
had_error: false,
}
}
#[cfg(all(feature = "minify", not(target_family = "wasm")))]
fn try_minify(source: &str) -> Option<String> {
std::thread::scope(|scope| {
std::thread::Builder::new()
.stack_size(16 * 1024 * 1024)
.spawn_scoped(scope, || minify_with_oxc(source))
.ok()
.and_then(|handle| handle.join().ok())
.flatten()
})
}
#[cfg(all(feature = "minify", not(target_family = "wasm")))]
fn minify_with_oxc(source: &str) -> Option<String> {
use oxc::allocator::Allocator;
use oxc::codegen::{Codegen, CodegenOptions};
use oxc::minifier::{Minifier, MinifierOptions};
use oxc::parser::Parser;
use oxc::span::SourceType;
let allocator = Allocator::default();
let source_type = SourceType::cjs();
let parsed = Parser::new(&allocator, source, source_type).parse();
if parsed.panicked || !parsed.diagnostics.is_empty() {
return None;
}
let mut program = parsed.program;
let minified = Minifier::new(MinifierOptions::default()).minify(&allocator, &mut program);
let printed = Codegen::new()
.with_options(CodegenOptions {
minify: true,
..CodegenOptions::default()
})
.with_scoping(minified.scoping)
.build(&program);
Some(printed.code)
}
#[cfg(test)]
mod tests {
use super::*;
#[cfg(all(feature = "minify", not(target_family = "wasm")))]
#[test]
fn minify_compacts_valid_javascript() {
let content = "function add ( a , b ) {\n return a + b ;\n}\n".to_owned();
let outcome = minify(content.clone());
assert!(!outcome.had_error, "valid input minifies without error");
assert!(
outcome.content.len() < content.len(),
"minified output is smaller: {:?}",
outcome.content
);
assert!(
!outcome.content.contains(" "),
"insignificant whitespace is removed: {:?}",
outcome.content
);
}
#[cfg(all(feature = "minify", not(target_family = "wasm")))]
#[test]
fn minify_falls_back_on_invalid_javascript() {
let content = "function ( {{ this is not valid ".to_owned();
let outcome = minify(content.clone());
assert!(outcome.had_error, "invalid input is flagged");
assert_eq!(outcome.content, content, "the original content is kept");
}
#[cfg(not(all(feature = "minify", not(target_family = "wasm"))))]
#[test]
fn minify_returns_content_unchanged_without_the_feature() {
let content = "var x = 1 ;".to_owned();
let outcome = minify(content.clone());
assert!(!outcome.had_error);
assert_eq!(outcome.content, content);
}
}