use std::{env, path::PathBuf};
use crate::{assets::RouteAssetsOptions, is_dev, sitemap::SitemapOptions};
fn default_cache_dir() -> PathBuf {
let binary_name = env::current_exe()
.ok()
.and_then(|p| p.file_stem().map(|s| s.to_string_lossy().into_owned()))
.unwrap_or_else(|| "unknown".to_string());
let target_dir = env::var("CARGO_TARGET_DIR")
.map(PathBuf::from)
.unwrap_or_else(|_| find_project_root().join("target"));
target_dir.join("maudit").join(binary_name)
}
fn find_project_root() -> PathBuf {
let Ok(mut current) = env::current_dir() else {
return PathBuf::from(".");
};
for _ in 0..5 {
if current.join("Cargo.lock").exists() {
return current;
}
if !current.pop() {
break;
}
}
PathBuf::from(".")
}
pub struct BuildOptions {
pub base_url: Option<String>,
pub output_dir: PathBuf,
pub static_dir: PathBuf,
pub clean_output_dir: bool,
pub assets: AssetsOptions,
pub prefetch: PrefetchOptions,
pub sitemap: SitemapOptions,
pub incremental: bool,
pub cache_dir: PathBuf,
}
#[derive(Clone, Copy, PartialEq, Eq)]
pub enum PrefetchStrategy {
None,
Hover,
Tap,
Viewport,
}
#[derive(Clone, Copy, PartialEq, Eq)]
pub enum PrerenderEagerness {
Immediate,
Eager,
Moderate,
Conservative,
}
#[derive(Clone)]
pub struct PrefetchOptions {
pub strategy: PrefetchStrategy,
pub prerender: bool,
pub eagerness: PrerenderEagerness,
}
impl Default for PrefetchOptions {
fn default() -> Self {
Self {
strategy: PrefetchStrategy::Tap,
prerender: false,
eagerness: PrerenderEagerness::Immediate,
}
}
}
impl BuildOptions {
pub(crate) fn options_hash(&self) -> String {
use rapidhash::fast::RapidHasher;
use std::hash::{Hash, Hasher};
let mut hasher = RapidHasher::default();
self.base_url.hash(&mut hasher);
self.output_dir.hash(&mut hasher);
std::mem::discriminant(&self.prefetch.strategy).hash(&mut hasher);
self.prefetch.prerender.hash(&mut hasher);
std::mem::discriminant(&self.prefetch.eagerness).hash(&mut hasher);
std::mem::discriminant(&self.assets.hashing_strategy).hash(&mut hasher);
self.assets.assets_dir.hash(&mut hasher);
format!("{:016x}", hasher.finish())
}
pub fn route_assets_options(&self) -> RouteAssetsOptions {
RouteAssetsOptions {
assets_dir: self.assets.assets_dir.clone(),
output_assets_dir: self.output_dir.join(&self.assets.assets_dir),
hashing_strategy: self.assets.hashing_strategy,
}
}
}
#[derive(Clone)]
pub struct AssetsOptions {
pub tailwind_binary_path: PathBuf,
pub assets_dir: PathBuf,
pub hashing_strategy: AssetHashingStrategy,
}
#[derive(PartialEq, Eq, Clone, Copy)]
pub enum AssetHashingStrategy {
Precise,
FastImprecise,
}
impl Default for AssetsOptions {
fn default() -> Self {
Self {
tailwind_binary_path: "tailwindcss".into(),
assets_dir: "_maudit".into(),
hashing_strategy: if is_dev() {
AssetHashingStrategy::FastImprecise
} else {
AssetHashingStrategy::Precise
},
}
}
}
impl Default for BuildOptions {
fn default() -> Self {
Self {
base_url: None,
output_dir: "dist".into(),
static_dir: "static".into(),
clean_output_dir: true,
prefetch: PrefetchOptions::default(),
assets: AssetsOptions::default(),
sitemap: SitemapOptions::default(),
incremental: true,
cache_dir: default_cache_dir(),
}
}
}