khguide/src/main.rs

144 lines
3.2 KiB
Rust
Raw Normal View History

#![allow(dead_code)]
use std::{collections::HashMap, fs, path::PathBuf, sync::LazyLock};
use askama::Template;
use blake3::{Hash, Hasher};
use tracing_subscriber::EnvFilter;
mod common;
#[cfg(feature = "bbs")]
mod bbs;
#[cfg(feature = "ddd")]
mod ddd;
#[cfg(feature = "kh1")]
mod kh1;
2025-02-08 13:35:55 +02:00
#[cfg(feature = "kh2")]
mod kh2;
#[cfg(feature = "kh3")]
mod kh3;
pub const VERSION: &str = env!("CARGO_PKG_VERSION");
pub const ASSETS_FOLDER_PATH: &str = "./public/assets";
pub const SCRIPTS_FOLDER_PATH: &str = "./public/scripts";
pub const STYLES_FOLDER_PATH: &str = "./public/styles";
static FILE_HASHES: LazyLock<HashMap<String, Hash>> = LazyLock::new(|| {
let mut map = HashMap::new();
fn parse_path(path: PathBuf, map: &mut HashMap<String, Hash>) {
if let Ok(paths) = fs::read_dir(path) {
for path in paths.flatten() {
let path = path.path();
if path.metadata().is_ok_and(|p| p.is_dir()) {
parse_path(path, map);
continue;
}
let dir = path.parent().unwrap().to_str().unwrap();
let path = path.to_str().unwrap();
let is_module = path.contains("/common");
let mut hasher = Hasher::new();
hash_file(path.to_string().into(), &mut hasher);
if !is_module {
hash_files_in_dir(format!("{dir}/common").into(), &mut hasher);
}
let hash = hasher.finalize();
map.insert(path.to_string(), hash);
}
}
}
parse_path(SCRIPTS_FOLDER_PATH.into(), &mut map);
parse_path(STYLES_FOLDER_PATH.into(), &mut map);
map
});
pub trait RuntimeModule {
fn start_module();
}
#[derive(Template)]
#[template(path = "pages/index.html")]
struct IndexTemplate {}
fn main() {
// Initialize tracing
tracing_subscriber::fmt()
.with_env_filter(EnvFilter::from_default_env())
.event_format(tracing_subscriber::fmt::format().with_source_location(true))
.init();
tracing::info!("Generating the main menu template");
let template = IndexTemplate {};
std::fs::write("./out/index.html", template.render().unwrap()).unwrap();
2025-02-10 00:47:36 +02:00
std::process::Command::new("cp")
.args(["-r", "./assets", "./out"])
.output()
.unwrap();
#[cfg(feature = "bbs")]
start_module::<bbs::Module>();
#[cfg(feature = "ddd")]
start_module::<ddd::Module>();
#[cfg(feature = "kh1")]
start_module::<kh1::Module>();
2025-02-08 13:35:55 +02:00
#[cfg(feature = "kh2")]
start_module::<kh2::Module>();
2025-02-08 13:35:55 +02:00
#[cfg(feature = "kh3")]
start_module::<kh3::Module>();
}
fn start_module<M: RuntimeModule>() {
M::start_module();
}
fn find_hash(file: &str) -> String {
let map = &*FILE_HASHES;
let hash = map.get(&format!(".{file}"));
if let Some(hash) = hash {
return format!("{file}?hash={hash}");
}
file.to_string()
}
fn hash_files_in_dir(path: PathBuf, hasher: &mut Hasher) {
if let Ok(paths) = fs::read_dir(path) {
for path in paths.flatten() {
let path = path.path();
if path.metadata().is_ok_and(|p| p.is_dir()) {
hash_files_in_dir(path, hasher);
continue;
}
hash_file(path, hasher);
}
}
}
fn hash_file(path: PathBuf, hasher: &mut Hasher) {
if let Ok(file) = fs::read(path) {
hasher.update(&file);
}
}
2025-06-29 14:03:58 +03:00
fn create_file(dir: &str, file: &str, buf: impl Template) -> std::io::Result<()> {
std::fs::create_dir_all(dir)?;
2025-06-29 14:03:58 +03:00
std::fs::write(format!("{}/{}.html", dir, file), buf.render().unwrap())?;
Ok(())
}