mod assets;
#[cfg(feature = "asyncrt")]
mod asyncrt;
mod content;
mod glob;
#[cfg(feature = "images")]
mod images;
mod script;
#[cfg(feature = "styles")]
mod styles;
mod svelte;
pub use assets::glob_assets;
#[cfg(feature = "asyncrt")]
pub use asyncrt::async_asset;
pub use content::{Content, glob_content};
use gray_matter::engine::YAML;
#[cfg(feature = "images")]
pub use images::Image;
pub use script::JS;
#[cfg(feature = "styles")]
pub use styles::CSS;
pub use svelte::Svelte;
use crate::{
Hash32,
error::{BuildError, HauchiwaError},
};
use ::glob::Pattern;
use camino::{Utf8Path, Utf8PathBuf};
use std::{collections::HashMap, fs};
#[derive(Debug)]
pub struct Registry<T> {
map: HashMap<camino::Utf8PathBuf, T>,
}
impl<T: Clone> Registry<T> {
pub fn get(&self, path: impl AsRef<Utf8Path>) -> Result<&T, HauchiwaError> {
self.map
.get(path.as_ref())
.ok_or(HauchiwaError::AssetNotFound(
path.as_ref().to_string().into(),
))
}
pub fn values(&self) -> std::collections::hash_map::Values<'_, Utf8PathBuf, T> {
self.map.values()
}
pub fn glob(&self, pattern: &str) -> Result<Vec<(&Utf8PathBuf, &T)>, HauchiwaError> {
let matcher = Pattern::new(pattern)?;
let matches: Vec<_> = self
.map
.iter()
.filter(|(path, _)| matcher.matches(path.as_str()))
.collect();
Ok(matches)
}
}
pub struct File<T> {
pub path: Utf8PathBuf,
pub metadata: T,
}
#[derive(Clone)]
pub struct Runtime;
impl Runtime {
pub fn store(&self, data: &[u8], ext: &str) -> Result<Utf8PathBuf, BuildError> {
let hash = Hash32::hash(data);
let hash = hash.to_hex();
let path_temp = Utf8Path::new(".cache/hash").join(&hash);
let path_dist = Utf8Path::new("dist/hash").join(&hash).with_extension(ext);
let path_root = Utf8Path::new("/hash/").join(&hash).with_extension(ext);
if !path_temp.exists() {
fs::create_dir_all(".cache/hash")?;
fs::write(&path_temp, data)?;
}
let dir = path_dist.parent().unwrap_or(&path_dist);
fs::create_dir_all(dir)?;
fs::copy(&path_temp, &path_dist)?;
Ok(path_root)
}
}
macro_rules! matter_parser {
($name:ident, $engine:path) => {
#[doc = concat!(
"This function can be used to extract metadata from a document with `D` as the frontmatter shape.\n",
"Configured to use [`", stringify!($engine), "`] as the engine of the parser."
)]
fn $name<D>(content: &str) -> Result<(D, String), anyhow::Error>
where
D: for<'de> serde::Deserialize<'de> + Send + Sync + 'static,
{
use gray_matter::{Matter, Pod};
static PARSER: std::sync::LazyLock<Matter<$engine>> = std::sync::LazyLock::new(Matter::<$engine>::new);
let entity = PARSER.parse(content)?;
let object = entity
.data
.unwrap_or_else(Pod::new_hash)
.deserialize::<D>()
.map_err(|e| anyhow::anyhow!("Malformed frontmatter:\n{e}"))?;
Ok((
object,
entity.content,
))
}
};
}
matter_parser!(parse_yaml, YAML);