use crate::args::CLIArgs; use crate::args::GenHTMLCommandArgs; use crate::types::File; use crate::utils::formats::get_format_handler; use crate::utils::scan_for_music; use std::cmp::Ordering; use std::io::Write; use html_escape::encode_text; fn table_for_files(files: Vec<File>, includes_path: bool) -> String { let mut html_content = String::new(); let mut path_head = String::new(); if includes_path { path_head.push_str("<th>Path</th>") } html_content.push_str( format!( " <table class=\"pure-table pure-table-horizontal\"> <thead> <tr> {} <th>Title</th> <th>Artist</th> <th>Format</th> </tr> </thead> <tbody> ", path_head ) .as_str(), ); let mut is_odd = true; for file in files.iter() { let td_class = match is_odd { true => "pure-table-odd", false => "pure-table-even", }; let data_title = encode_text(&file.info.tags.title); let data_artist = encode_text(&file.info.tags.artist); let data_extension = encode_text(&file.extension); let mut path_data = String::new(); if includes_path { let file_directory = file.path_from_source.to_string_lossy().to_string(); path_data.push_str(format!("<td>{}</td>", encode_text(&file_directory)).as_str()); } html_content.push_str( format!( " <tr class=\"{}\"> {} <td>{}</td> <td>{}</td> <td>{}</td> </tr> ", td_class, path_data, data_title, data_artist, data_extension ) .as_str(), ); is_odd = !is_odd; } html_content.push_str( " </tbody> </table> ", ); html_content } pub fn genhtml_command( _args: &CLIArgs, genhtml_args: &GenHTMLCommandArgs, ) -> Result<(), Box<dyn std::error::Error>> { println!("Scanning For Music"); let mut files = scan_for_music(&genhtml_args.source)?; println!("Analysing Files"); for file in files.iter_mut() { println!("Analysing: {:?}", file.join_path_from_source()); let handler = get_format_handler(file)?; file.info = handler.get_audio_file_info(false)?; } files.sort_by(|a, b| -> Ordering { if a.path_from_source != b.path_from_source { return a.path_from_source.cmp(&b.path_from_source); } let a_tags = &a.info.tags; let b_tags = &b.info.tags; if a_tags.title != b_tags.title { return a_tags.title.cmp(&b_tags.title); } a_tags.artist.cmp(&b_tags.artist) }); let mut html_content = String::new(); html_content.push_str( format!( " <!DOCTYPE HTML> <html> <head> <meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\"> <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\"> <link rel=\"stylesheet\" href=\"https://unpkg.com/purecss@2.0.6/build/pure-min.css\"> <title>{}</title> <meta property=\"og:title\" content=\"{}\" /> <meta property=\"og:description\" content=\"{}\" /> </head> <body> ", encode_text(&genhtml_args.title), encode_text(&genhtml_args.title), encode_text(&genhtml_args.description) ) .as_str(), ); html_content.push_str(&table_for_files(files, true)); html_content.push_str("</body></html>"); let file_path = std::path::PathBuf::from(genhtml_args.dest.as_str()).join("index.html"); let html_index_file = std::fs::File::create(file_path); match html_index_file { Ok(mut file) => match file.write_all(html_content.as_bytes()) { Ok(_) => {} Err(e) => { panic!("Could not write html file: {}", e); } }, Err(e) => { panic!("Could not create HTML file: {}", e); } } Ok(()) }