hauchiwa 0.0.1

Static site generator library
Documentation
use std::{collections::HashSet, rc::Rc};

use camino::{Utf8Path, Utf8PathBuf};

use crate::tree::{Output, PipelineItem, Sack, Virtual};
use crate::{BuildContext, Mode};

#[derive(Debug)]
pub struct Website {
	sources: Vec<Source>,
	special: Vec<Rc<Output>>,
}

impl Website {
	pub fn new() -> WebsiteBuilder {
		WebsiteBuilder::default()
	}

	pub fn build(&self) {
		let ctx = BuildContext {
			mode: Mode::Build,
			..Default::default()
		};
		let _ = crate::build::build(&ctx, &self.sources, &self.special.clone());
	}

	pub fn watch(&self) {
		let ctx = BuildContext {
			mode: Mode::Watch,
			..Default::default()
		};
		let state = crate::build::build(&ctx, &self.sources, &self.special.clone());
		crate::watch::watch(&ctx, &self.sources, state).unwrap()
	}
}

#[derive(Debug, Default)]
pub struct WebsiteBuilder {
	sources: Vec<Source>,
	special: Vec<Rc<Output>>,
}

impl WebsiteBuilder {
	pub fn add_source(
		mut self,
		path: &'static str,
		exts: HashSet<&'static str>,
		func: fn(PipelineItem) -> PipelineItem,
	) -> Self {
		self.sources.push(Source { path, exts, func });
		self
	}

	pub fn add_virtual(
		mut self,
		func: fn(&Sack) -> String,
		path: Utf8PathBuf,
	) -> Self {
		self.special.push(Output {
			kind: Virtual::new(func).into(),
			path,
			link: None,
		}.into());
		self
	}

	pub fn finish(self) -> Website {
		Website {
			sources: self.sources,
			special: self.special,
		}
	}
}

#[derive(Debug)]
pub(crate) struct Source {
	pub path: &'static str,
	pub exts: HashSet<&'static str>,
	pub func: fn(PipelineItem) -> PipelineItem,
}

impl Source {
	pub(crate) fn get(&self) -> Vec<PipelineItem> {
		crate::tree::gather(self.path, &self.exts)
			.into_iter()
			.map(self.func)
			.collect()
	}

	pub(crate) fn get_maybe(&self, path: &Utf8Path) -> Option<PipelineItem> {
		let pattern = glob::Pattern::new(self.path).expect("Bad pattern");
		if !pattern.matches_path(path.as_std_path()) {
			return None;
		};

		let item = match path.is_file() {
			true => Some(crate::tree::to_source(path.to_owned(), &self.exts)),
			false => None,
		};

		item.map(Into::into).map(self.func)
	}
}