minify-html/cli/src/main.rs

97 lines
3.2 KiB
Rust
Raw Normal View History

2019-12-25 04:44:51 -05:00
use std::fs::File;
2021-08-07 05:10:47 -04:00
use std::io::{stdin, stdout, Read, Write};
2019-12-25 07:29:18 -05:00
2019-12-25 04:44:51 -05:00
use structopt::StructOpt;
2021-08-07 05:10:47 -04:00
use minify_html::{minify, Cfg};
2019-12-25 04:44:51 -05:00
#[derive(StructOpt)]
2021-08-07 05:10:47 -04:00
#[structopt(
name = "minify-html",
about = "Extremely fast and smart HTML + JS + CSS minifier"
)]
// WARNING: Keep descriptions in sync with Cfg.
2019-12-25 04:44:51 -05:00
struct Cli {
2021-01-07 09:58:31 -05:00
/// File to minify; omit for stdin.
2019-12-25 04:44:51 -05:00
#[structopt(short, long, parse(from_os_str))]
src: Option<std::path::PathBuf>,
2021-01-07 09:58:31 -05:00
/// Output destination; omit for stdout.
2019-12-25 04:44:51 -05:00
#[structopt(short, long, parse(from_os_str))]
out: Option<std::path::PathBuf>,
2021-08-07 05:10:47 -04:00
/// Minify JS in `<script>` tags that have a valid or no `type` attribute value.
#[structopt(long)]
2021-08-07 05:10:47 -04:00
minify_js: bool,
/// Minify CSS in `<style>` tags and `style` attributes.
2021-01-07 08:26:02 -05:00
#[structopt(long)]
2021-08-07 05:10:47 -04:00
minify_css: bool,
/// Ensure all unquoted attribute values in the output do not contain any characters prohibited by the WHATWG specification.
2021-08-07 12:31:32 -04:00
#[structopt(long)]
2021-08-07 12:22:29 -04:00
ensure_spec_compliant_unquoted_attribute_values: bool,
2021-08-07 05:10:47 -04:00
/// Do not omit closing tags when possible.
#[structopt(long)]
keep_closing_tags: bool,
/// Do not omit `<html>` and `<head>` opening tags when they don't have attributes.
#[structopt(long)]
keep_html_and_head_opening_tags: bool,
/// Keep spaces between attributes when possible to conform to HTML standards.
#[structopt(long)]
keep_spaces_between_attributes: bool,
/// Keep all comments.
#[structopt(long)]
keep_comments: bool,
/// Remove all bangs.
#[structopt(long)]
remove_bangs: bool,
/// Remove all processing_instructions.
#[structopt(long)]
remove_processing_instructions: bool,
}
macro_rules! io_expect {
($expr:expr, $msg:literal) => {
match $expr {
Ok(r) => r,
Err(e) => {
eprintln!("Error: {}", $msg);
eprintln!("{}", e);
return;
}
}
};
2019-12-25 04:44:51 -05:00
}
fn main() {
let args = Cli::from_args();
2021-08-07 05:10:47 -04:00
let mut src_code = Vec::<u8>::new();
let mut src_file: Box<dyn Read> = match args.src {
Some(p) => Box::new(io_expect!(File::open(p), "could not open source file")),
None => Box::new(stdin()),
};
2021-08-07 05:10:47 -04:00
io_expect!(
src_file.read_to_end(&mut src_code),
"could not load source code"
);
let out_code = minify(
&src_code,
&Cfg {
ensure_spec_compliant_unquoted_attribute_values: args.ensure_spec_compliant_unquoted_attribute_values,
2021-08-07 05:10:47 -04:00
keep_closing_tags: args.keep_closing_tags,
keep_comments: args.keep_comments,
keep_html_and_head_opening_tags: args.keep_html_and_head_opening_tags,
keep_spaces_between_attributes: args.keep_spaces_between_attributes,
minify_css: args.minify_css,
minify_js: args.minify_js,
remove_bangs: args.remove_bangs,
remove_processing_instructions: args.remove_processing_instructions,
},
);
let mut out_file: Box<dyn Write> = match args.out {
Some(p) => Box::new(io_expect!(File::create(p), "could not open output file")),
None => Box::new(stdout()),
2019-12-25 07:29:18 -05:00
};
2021-08-07 05:10:47 -04:00
io_expect!(
out_file.write_all(&out_code),
"could not save minified code"
);
2019-12-25 04:44:51 -05:00
}