first commit

This commit is contained in:
Mateusz Gruszczyński committed 2026-10-28 09:16:54 +01:00
commit 32a7ba8e8f
168 files changed
+123856

No files matched your search

+103
View File
@@ -0,0 +1,103 @@
use std::{
env, fs,
path::{Path, PathBuf},
};
fn content_hash(content: &str) -> String {
let value = content.bytes().fold(0xcbf29ce484222325_u64, |hash, byte| {
(hash ^ u64::from(byte)).wrapping_mul(0x100000001b3)
});
format!("{value:016x}")
}
fn write_asset(output: &Path, stem: &str, extension: &str, content: &str) -> String {
let file_name = format!("{stem}.{}.{extension}", content_hash(content));
fs::write(output.join(&file_name), content)
.unwrap_or_else(|error| panic!("write {file_name}: {error}"));
file_name
}
fn cargo_asset_env(name: &str, file_name: &str) {
println!("cargo:rustc-env={name}_FILE={file_name}");
println!("cargo:rustc-env={name}_ROUTE=/assets/{file_name}");
}
fn main() {
let output = PathBuf::from(env::var_os("OUT_DIR").expect("OUT_DIR"));
println!("cargo:rerun-if-changed=build.rs");
println!("cargo:rerun-if-changed=web");
println!("cargo:rerun-if-changed=docs/api-ui");
println!("cargo:rerun-if-changed=vendor/swagger-ui/swagger-ui-bundle.js");
println!("cargo:rerun-if-changed=vendor/swagger-ui/swagger-ui.css");
if let Ok(entries) = fs::read_dir(&output) {
for entry in entries.flatten() {
let name = entry.file_name();
let name = name.to_string_lossy();
let generated_asset = (name.starts_with("app.") || name.starts_with("docs."))
&& (name.ends_with(".js") || name.ends_with(".css"));
if generated_asset {
let _ = fs::remove_file(entry.path());
}
}
}
let manifest = fs::read_to_string("web/assets.list").expect("web/assets.list is required");
let mut js =
String::from("/* MikroTik Backup System 0.0.1; generated from web/assets.list */\n");
let mut css = String::new();
for entry in manifest
.lines()
.map(str::trim)
.filter(|value| !value.is_empty() && !value.starts_with('#'))
{
let source = fs::read_to_string(PathBuf::from("web").join(entry))
.unwrap_or_else(|error| panic!("{entry}: {error}"));
if entry.ends_with(".js") {
js.push_str(&source);
js.push_str("\n;\n");
} else if entry.ends_with(".css") {
css.push_str(&source);
css.push('\n');
} else {
panic!("Unsupported bundle input: {entry}");
}
}
let app_js_file = write_asset(&output, "app", "js", &js);
let app_css_file = write_asset(&output, "app", "css", &css);
cargo_asset_env("APP_JS", &app_js_file);
cargo_asset_env("APP_CSS", &app_css_file);
let html = fs::read_to_string("web/index.html")
.expect("web/index.html is required")
.replace("/assets/app.js", &format!("/assets/{app_js_file}"))
.replace("/assets/app.css", &format!("/assets/{app_css_file}"));
fs::write(output.join("index.html"), html).expect("write HTML shell");
let mut docs_js = fs::read_to_string("vendor/swagger-ui/swagger-ui-bundle.js")
.expect("Swagger UI JavaScript is required")
.lines()
.filter(|line| !line.starts_with("//# sourceMappingURL="))
.collect::<Vec<_>>()
.join("\n");
docs_js.push_str("\n;\n");
docs_js.push_str(&fs::read_to_string("docs/api-ui/init.js").expect("docs API initializer"));
let mut docs_css = fs::read_to_string("vendor/swagger-ui/swagger-ui.css")
.expect("Swagger UI stylesheet is required")
.replace("/*# sourceMappingURL=swagger-ui.css.map*/", "");
docs_css.push('\n');
docs_css.push_str(&fs::read_to_string("docs/api-ui/style.css").expect("docs API stylesheet"));
let docs_js_file = write_asset(&output, "docs", "js", &docs_js);
let docs_css_file = write_asset(&output, "docs", "css", &docs_css);
cargo_asset_env("DOCS_JS", &docs_js_file);
cargo_asset_env("DOCS_CSS", &docs_css_file);
let docs_html = fs::read_to_string("docs/api-ui/index.html")
.expect("docs API HTML is required")
.replace("/assets/docs.js", &format!("/assets/{docs_js_file}"))
.replace("/assets/docs.css", &format!("/assets/{docs_css_file}"));
fs::write(output.join("docs.html"), docs_html).expect("write API documentation HTML");
}