80 lines
2.6 KiB
Rust
80 lines
2.6 KiB
Rust
use std::{
|
|
env, fs,
|
|
path::{Path, PathBuf},
|
|
};
|
|
|
|
fn fnv1a64(parts: &[&[u8]]) -> u64 {
|
|
let mut hash = 0xcbf29ce484222325u64;
|
|
for part in parts {
|
|
for byte in *part {
|
|
hash ^= u64::from(*byte);
|
|
hash = hash.wrapping_mul(0x100000001b3);
|
|
}
|
|
}
|
|
hash
|
|
}
|
|
|
|
fn bundle_manifest(root: &Path, directory: &Path, manifest: &Path, extension: &str) -> String {
|
|
println!("cargo:rerun-if-changed={}", manifest.display());
|
|
let manifest_text = fs::read_to_string(manifest)
|
|
.unwrap_or_else(|error| panic!("{}: {error}", manifest.display()));
|
|
let mut bundle = String::new();
|
|
|
|
for raw in manifest_text.lines() {
|
|
let name = raw.trim();
|
|
if name.is_empty() || name.starts_with('#') {
|
|
continue;
|
|
}
|
|
assert!(
|
|
name.ends_with(extension)
|
|
&& !name.contains('/')
|
|
&& !name.contains('\\')
|
|
&& !name.contains(".."),
|
|
"invalid {extension} manifest entry: {name}"
|
|
);
|
|
let path = directory.join(name);
|
|
assert!(
|
|
path.starts_with(root),
|
|
"asset path escaped project root: {}",
|
|
path.display()
|
|
);
|
|
println!("cargo:rerun-if-changed={}", path.display());
|
|
let source =
|
|
fs::read_to_string(&path).unwrap_or_else(|error| panic!("{}: {error}", path.display()));
|
|
if !bundle.is_empty() {
|
|
bundle.push('\n');
|
|
}
|
|
bundle.push_str(&source);
|
|
if !source.ends_with('\n') {
|
|
bundle.push('\n');
|
|
}
|
|
}
|
|
|
|
bundle
|
|
}
|
|
|
|
fn main() {
|
|
let root = PathBuf::from(env::var_os("CARGO_MANIFEST_DIR").expect("CARGO_MANIFEST_DIR"));
|
|
let out = PathBuf::from(env::var_os("OUT_DIR").expect("OUT_DIR"));
|
|
let css_dir = root.join("src/web/css");
|
|
let js_dir = root.join("src/web/js");
|
|
|
|
for path in [
|
|
root.join("src/web/index.html"),
|
|
root.join("src/web/icons.svg"),
|
|
root.join("src/web/i18n/en.json"),
|
|
root.join("src/web/i18n/pl.json"),
|
|
] {
|
|
println!("cargo:rerun-if-changed={}", path.display());
|
|
}
|
|
|
|
let css_bundle = bundle_manifest(&root, &css_dir, &css_dir.join("manifest.txt"), ".css");
|
|
let js_bundle = bundle_manifest(&root, &js_dir, &js_dir.join("manifest.txt"), ".js");
|
|
|
|
let asset_id = fnv1a64(&[css_bundle.as_bytes(), js_bundle.as_bytes()]);
|
|
println!("cargo:rustc-env=RUSTBOX_ASSET_ID={asset_id:016x}");
|
|
|
|
fs::write(out.join("rustbox-ui.css"), css_bundle).expect("write RustBox CSS bundle");
|
|
fs::write(out.join("rustbox-ui.js"), js_bundle).expect("write RustBox JavaScript bundle");
|
|
}
|