mdpreview/build.rs
2026-07-20 10:00:57 +03:00

116 lines
3.5 KiB
Rust

use minify_html::{Cfg, minify};
use std::env;
use std::fs;
use std::io;
use std::path::Path;
const HIGHLIGHT_STYLE_URL_TEMPLATE: &str =
"https://cdnjs.cloudflare.com/ajax/libs/highlight.js/{VERSION}/styles/atom-one-dark.min.css";
const HIGHLIGHT_SCRIPT_URL_TEMPLATE: &str =
"https://cdnjs.cloudflare.com/ajax/libs/highlight.js/{VERSION}/highlight.min.js";
const MERMAID_SCRIPT_URL_TEMPLATE: &str =
"https://cdn.jsdelivr.net/npm/mermaid@{VERSION}/dist/mermaid.min.js";
fn main() {
println!("cargo:rerun-if-changed=build.rs");
println!("cargo:rerun-if-changed=assets/");
println!("cargo:rerun-if-env-changed=FORCE_DEPS_DOWNLOAD");
println!("cargo:rerun-if-changed=templates/");
minify_template_file("templates/base.html", "templates/.base.min.html").unwrap();
minify_template_file("templates/dir.html", "templates/.dir.min.html").unwrap();
minify_template_file("templates/file.html", "templates/.file.min.html").unwrap();
let out_dir = env::var("CARGO_MANIFEST_DIR").unwrap();
let assets_path = Path::new(&out_dir).join("assets");
fs::create_dir_all(&assets_path).expect("Fail to create directory");
let highlight_version = match env::var("HIGHLIGHT_VERSION") {
Ok(var) => var,
Err(_) => "11.9.0".to_string(),
};
let mermaid_version = match env::var("MERMAID_VERSION") {
Ok(var) => var,
Err(_) => "10".to_string(),
};
download(
HIGHLIGHT_STYLE_URL_TEMPLATE,
&highlight_version,
&assets_path.join("highlight.css"),
);
download(
HIGHLIGHT_SCRIPT_URL_TEMPLATE,
&highlight_version,
&assets_path.join("highlight.js"),
);
download(
MERMAID_SCRIPT_URL_TEMPLATE,
&mermaid_version,
&assets_path.join("mermaid.js"),
);
}
fn download(url: &str, version: &str, dest_path: &Path) {
if !should_download(dest_path) {
println!(
"cargo:warning=✅ {} actual, skip downloading",
dest_path.to_string_lossy()
);
return;
}
println!(
"cargo:warning=📥 Downloading {}...",
dest_path.to_string_lossy()
);
let response = reqwest::blocking::get(url.replace("{VERSION}", version))
.expect("Fail to download sources")
.error_for_status()
.expect("Fail to download sources: non-2xx status code");
let content = response.text().expect("Fail to read answer");
fs::write(dest_path, &content).expect("Fail to write file");
}
fn should_download(path: &Path) -> bool {
if env::var("FORCE_DEPS_DOWNLOAD").is_ok() {
return true;
}
if path.exists() {
return false;
}
true
}
fn minify_template_file<P: AsRef<str>>(input_path: P, output_path: P) -> io::Result<()> {
let html_content = fs::read_to_string(input_path.as_ref())?;
let minified = minify_template_content(&html_content)
.map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?;
fs::write(output_path.as_ref(), minified)?;
Ok(())
}
#[allow(clippy::missing_errors_doc)]
pub fn minify_template_content(template: &str) -> Result<String, String> {
let mut cfg = Cfg::new();
cfg.allow_removing_spaces_between_attributes = true;
cfg.keep_comments = false;
cfg.minify_css = true;
cfg.minify_js = true;
cfg.keep_html_and_head_opening_tags = true;
cfg.keep_closing_tags = true;
cfg.remove_processing_instructions = true;
let minified_bytes = minify(template.as_bytes(), &cfg);
String::from_utf8(minified_bytes).map_err(|e| format!("Invalid UTF-8 in output: {e}"))
}