use std::env;
use std::fs;
use std::path::Path;
use xhtml_minimizer::*;
use xml_tokens::Tokenizer;
fn main() {
let clargs = CLArgs::new();
if clargs.verbose {
println!("XHTML Minimizer\n");
clargs.print();
}
if clargs.help {
clargs.print_usage();
std::process::exit(0);
}
let input_path = Path::new(&clargs.input_filename);
let output_path = Path::new(&clargs.output_filename);
match fs::read_to_string(input_path) {
Ok(input) => {
let mut tok = Tokenizer::new(input);
let szr = XHTMLSerializer::new(false, false, false, false);
if tok.tokenize_document() {
match fs::write(output_path, szr.serialize(&tok.tokens)) {
Ok(_result) => {
if clargs.verbose {
print_statistics(
fs::metadata(clargs.input_filename).unwrap().len(),
fs::metadata(clargs.output_filename).unwrap().len(),
);
}
}
Err(_error) => println!("Failed to save output."),
}
} else {
println!("{:?}", tok.error_messages);
}
}
Err(_error) => panic!("Error reading input path into string."),
}
}
fn print_statistics(input_size: u64, output_size: u64) {
println!("Input file size: {} bytes", input_size);
println!("Output file size: {} bytes", output_size);
println!(
"Absolute size reduction: {} bytes",
input_size - output_size
);
println!(
"Percentage size reduction: {:.0}%",
100.0 * (1.0 - (output_size as f64 / input_size as f64))
);
}
struct CLArgs {
help: bool,
input_filename: String,
keep_comments: bool,
keep_references: bool,
keep_whitespace: bool,
keep_xml_declaration: bool,
output_filename: String,
verbose: bool,
}
impl CLArgs {
pub fn new() -> CLArgs {
let mut help = false;
let mut input_filename = String::from("index.xhtml");
let mut keep_comments = false;
let mut keep_references = false;
let mut keep_whitespace = false;
let mut keep_xml_declaration = false;
let mut output_filename = String::from("output.xhtml");
let mut verbose = false;
let mut args: Vec<String> = env::args().collect();
let mut i = 0;
while i < args.len() {
match args[i].as_ref() {
"--help" | "-h" => {
help = true;
}
"--keep-comments" | "-c" => {
keep_comments = true;
}
"--keep-references" | "-r" => {
keep_references = true;
}
"--keep-whitespace" | "-w" => {
keep_whitespace = true;
}
"--keep-xml-declaration" | "-x" => {
keep_xml_declaration = true;
}
"--output" | "-o" => {
if i + 1 < args.len() {
output_filename = args.remove(i + 1);
} else {
panic!("Syntax error. Expected output filename.")
}
}
"--verbose" | "-v" => {
verbose = true;
}
_ => {
if i == args.len() - 1 {
input_filename = args.remove(i);
}
}
}
i += 1;
}
CLArgs {
help,
input_filename,
keep_comments,
keep_references,
keep_whitespace,
keep_xml_declaration,
output_filename,
verbose,
}
}
fn print(&self) {
println!("Help: {}", self.help);
println!("Input filename: {}", self.input_filename);
println!("Keep comments: {}", self.keep_comments);
println!("Keep references: {}", self.keep_references);
println!("Keep whitespace: {}", self.keep_whitespace);
println!("Keep XML declaration: {}", self.keep_xml_declaration);
println!("Output filename: {}", self.output_filename);
println!("Verbose: {}", self.verbose);
println!("");
}
fn print_usage(&self) {
println!("Usage: xhtml-minimizer [OPTIONS] INPUT_XHTML_FILE");
println!("Options:");
println!(" -h, --help\t\t\tshow this message and exit");
println!(" -c, --keep-comments\t\tdo not omit XHTML comments");
println!(" -r, --keep-references\t\tdo not replace entity and character references");
println!(" -w, --keep-whitespace\t\tkeep all whitespace");
println!(" -x, --keep-xml-declaration\tkeep any XML declaration");
println!(" -o FILE, --output FILE\t\toutput to FILE");
println!(" -v, --verbose\t\t\tprint messages");
println!("\nFor more information see <https://gitlab.com/danieljrmay/xhtml_minimizer>")
}
}