feat: builder pattern

This commit is contained in:
Maciej Jur 2024-07-12 00:04:19 +02:00
parent 0974abc81d
commit 142ea69ff7
Signed by: kamov
GPG key ID: 191CBFF5F72ECAFD
3 changed files with 79 additions and 37 deletions

View file

@ -5,10 +5,12 @@ mod text;
mod ts;
mod utils;
mod watch;
mod website;
use std::collections::{HashMap, HashSet};
use std::fs;
use std::process::Command;
use std::rc::Rc;
use build::Hashed;
use camino::{Utf8Path, Utf8PathBuf};
@ -19,6 +21,7 @@ use gray_matter::Matter;
use hypertext::{Raw, Renderable};
use pipeline::{Asset, AssetKind, Content, FileItemKind, Output, OutputKind, PipelineItem};
use serde::Deserialize;
use website::WebsiteDesigner;
use crate::pipeline::Virtual;
@ -83,41 +86,38 @@ fn main() {
.into(),
};
let sources = &[
Source {
let website = WebsiteDesigner::default()
.add_source(Source {
path: "content/about.md",
exts: ["md"].into(),
func: process_content::<crate::html::Post>,
},
Source {
})
.add_source(Source {
path: "content/posts/**/*",
exts: ["md", "mdx"].into(),
func: process_content::<crate::html::Post>,
},
Source {
})
.add_source(Source {
path: "content/slides/**/*",
exts: ["md", "lhs"].into(),
func: process_content::<crate::html::Slideshow>,
},
Source {
})
.add_source(Source {
path: "content/wiki/**/*",
exts: ["md"].into(),
func: process_content::<crate::html::Wiki>,
},
];
let special = vec![
Output {
})
.add_output(Output {
kind: Virtual::new(|sack| crate::html::map(sack).render().to_owned().into()).into(),
path: "map/index.html".into(),
link: None,
},
Output {
})
.add_output(Output {
kind: Virtual::new(|sack| crate::html::search(sack).render().to_owned().into()).into(),
path: "search/index.html".into(),
link: None,
},
Output {
})
.add_output(Output {
kind: Asset {
kind: pipeline::AssetKind::html(|sack| {
let data = std::fs::read_to_string("content/index.md").unwrap();
@ -135,16 +135,16 @@ fn main() {
.into(),
path: "index.html".into(),
link: None,
},
Output {
})
.add_output(Output {
kind: Virtual::new(|sack| {
crate::html::to_list(sack, sack.get_links("posts/**/*.html"), "Posts".into())
})
.into(),
path: "posts/index.html".into(),
link: None,
},
Output {
})
.add_output(Output {
kind: Virtual::new(|sack| {
crate::html::to_list(
sack,
@ -155,17 +155,12 @@ fn main() {
.into(),
path: "slides/index.html".into(),
link: None,
},
];
})
.finish();
match args.mode {
Mode::Build => {
let _ = build(&ctx, sources, special);
}
Mode::Watch => {
let state = build(&ctx, sources, special);
watch::watch(&ctx, sources, state).unwrap()
}
Mode::Build => website.build(&ctx),
Mode::Watch => website.watch(&ctx),
}
}
@ -199,7 +194,7 @@ impl Source {
}
}
fn build(ctx: &BuildContext, sources: &[Source], special: Vec<Output>) -> Vec<Output> {
fn build(ctx: &BuildContext, sources: &[Source], special: &[Rc<Output>]) -> Vec<Rc<Output>> {
crate::build::clean_dist();
let content: Vec<Output> = sources
@ -218,9 +213,9 @@ fn build(ctx: &BuildContext, sources: &[Source], special: Vec<Output>) -> Vec<Ou
.collect();
let hashes = crate::build::store_hash_all(&images);
let hashes = HashMap::from_iter(hashes.into_iter().map(|Hashed { file, hash } | (file, hash)));
let hashes = HashMap::from_iter(hashes.into_iter().map(|Hashed { file, hash }| (file, hash)));
let assets: Vec<_> = content.iter().chain(special.iter()).collect();
let assets: Vec<_> = content.iter().chain(special.iter().map(AsRef::as_ref)).collect();
crate::build::build_content(ctx, &assets, &assets, Some(hashes));
crate::build::build_static();
@ -228,7 +223,7 @@ fn build(ctx: &BuildContext, sources: &[Source], special: Vec<Output>) -> Vec<Ou
crate::build::build_pagefind();
crate::build::build_js();
content.into_iter().chain(special).collect()
content.into_iter().map(Rc::new).chain(special.iter().map(ToOwned::to_owned)).collect()
}
pub fn parse_frontmatter<D>(raw: &str) -> (D, String)

View file

@ -71,7 +71,7 @@ fn new_thread_ws_reload(
(tx, thread)
}
pub fn watch(ctx: &BuildContext, sources: &[Source], state: Vec<Output>) -> Result<()> {
pub fn watch(ctx: &BuildContext, sources: &[Source], mut state: Vec<Rc<Output>>) -> Result<()> {
let root = env::current_dir().unwrap();
let server = TcpListener::bind("127.0.0.1:1337")?;
let client = Arc::new(Mutex::new(vec![]));
@ -92,8 +92,6 @@ pub fn watch(ctx: &BuildContext, sources: &[Source], state: Vec<Output>) -> Resu
let thread_i = new_thread_ws_incoming(server, client.clone());
let (tx_reload, thread_o) = new_thread_ws_reload(client.clone());
let mut state: Vec<Rc<Output>> = state.into_iter().map(Rc::new).collect();
while let Ok(events) = rx.recv().unwrap() {
let paths: Vec<Utf8PathBuf> = events
.into_iter()

49
src/website.rs Normal file
View file

@ -0,0 +1,49 @@
use std::rc::Rc;
use crate::{build, pipeline::Output, watch, BuildContext, Source};
#[derive(Debug)]
pub(crate) struct Website {
sources: Vec<Source>,
special: Vec<Rc<Output>>,
}
impl Website {
pub(crate) fn designer() -> WebsiteDesigner {
WebsiteDesigner::default()
}
pub(crate) fn build(&self, ctx: &BuildContext) {
let _ = build(ctx, &self.sources, &self.special.clone());
}
pub(crate) fn watch(&self, ctx: &BuildContext) {
let state = build(&ctx, &self.sources, &self.special.clone());
watch::watch(&ctx, &self.sources, state).unwrap()
}
}
#[derive(Debug, Default)]
pub(crate) struct WebsiteDesigner {
sources: Vec<Source>,
special: Vec<Rc<Output>>,
}
impl WebsiteDesigner {
pub(crate) fn add_source(mut self, source: Source) -> WebsiteDesigner {
self.sources.push(source);
self
}
pub(crate) fn add_output(mut self, output: Output) -> WebsiteDesigner {
self.special.push(Rc::new(output));
self
}
pub(crate) fn finish(self) -> Website {
Website {
sources: self.sources,
special: self.special,
}
}
}