1#![allow(clippy::literal_string_with_formatting_args, clippy::needless_pass_by_ref_mut)]
4
5mod compressor;
6mod ctx;
7mod keep_var;
8mod options;
9mod peephole;
10mod state;
11mod symbol_value;
12
13#[cfg(test)]
14mod tester;
15
16use oxc_allocator::Allocator;
17use oxc_ast::ast::Program;
18use oxc_mangler::Mangler;
19use oxc_semantic::{Scoping, SemanticBuilder};
20
21pub use oxc_mangler::{MangleOptions, MangleOptionsKeepNames};
22
23pub use crate::{compressor::Compressor, options::*};
24
25#[derive(Debug, Clone)]
26pub struct MinifierOptions {
27 pub mangle: Option<MangleOptions>,
28 pub compress: Option<CompressOptions>,
29}
30
31impl Default for MinifierOptions {
32 fn default() -> Self {
33 Self { mangle: Some(MangleOptions::default()), compress: Some(CompressOptions::default()) }
34 }
35}
36
37pub struct MinifierReturn {
38 pub scoping: Option<Scoping>,
39
40 pub iterations: u8,
42}
43
44pub struct Minifier {
45 options: MinifierOptions,
46}
47
48impl Minifier {
49 pub fn new(options: MinifierOptions) -> Self {
50 Self { options }
51 }
52
53 pub fn build<'a>(self, allocator: &'a Allocator, program: &mut Program<'a>) -> MinifierReturn {
54 let (stats, iterations) = self
55 .options
56 .compress
57 .map(|options| {
58 let semantic = SemanticBuilder::new().build(program).semantic;
59 let stats = semantic.stats();
60 let scoping = semantic.into_scoping();
61 let iterations =
62 Compressor::new(allocator).build_with_scoping(program, scoping, options);
63 (stats, iterations)
64 })
65 .unwrap_or_default();
66 let scoping = self.options.mangle.map(|options| {
67 let mut semantic = SemanticBuilder::new()
68 .with_stats(stats)
69 .with_scope_tree_child_ids(true)
70 .build(program)
71 .semantic;
72 Mangler::default().with_options(options).build_with_semantic(&mut semantic, program);
73 semantic.into_scoping()
74 });
75 MinifierReturn { scoping, iterations }
76 }
77}