Copy static files

This commit is contained in:
Shadowfacts 2025-01-11 17:22:25 -05:00
parent 494f2ad367
commit f5c7c14d2e
2 changed files with 131 additions and 1 deletions

View File

@ -3,6 +3,7 @@ mod css;
mod home;
mod markdown;
mod posts;
mod static_files;
mod tags;
mod templates;
mod util;
@ -57,7 +58,16 @@ fn make_graph(watcher: Rc<RefCell<FileWatcher>>) -> anyhow::Result<AsyncGraph<()
let css = css::make_graph(&mut builder, Rc::clone(&watcher));
let output = Combine::make(&mut builder, &[void_outputs, archive, tags, home, css]);
let statics = static_files::make_graph(&mut builder, Rc::clone(&watcher));
let output = Combine::make(&mut builder, &[
void_outputs,
archive,
tags,
home,
css,
statics,
]);
builder.set_existing_output(output);
Ok(builder.build()?)
}

View File

@ -0,0 +1,120 @@
use std::{cell::RefCell, fs::ReadDir, path::PathBuf, rc::Rc};
use compute_graph::{
builder::GraphBuilder,
input::{Input, InputVisitable},
rule::{DynamicNodeFactory, DynamicRule, DynamicRuleContext, Rule},
synchronicity::Asynchronous,
};
use crate::generator::{
FileWatcher,
util::{MapDynamicToVoid, content_path, output_path},
};
pub fn make_graph(
builder: &mut GraphBuilder<(), Asynchronous>,
watcher: Rc<RefCell<FileWatcher>>,
) -> Input<()> {
let (read_statics, invalidate) =
builder.add_invalidatable_dynamic_rule(ReadStatics::new(Rc::clone(&watcher)));
watcher
.borrow_mut()
.watch(content_path("static"), move || invalidate.invalidate());
builder.add_rule(MapDynamicToVoid(read_statics))
}
#[derive(InputVisitable)]
struct ReadStatics {
#[skip_visit]
watcher: Rc<RefCell<FileWatcher>>,
factory: DynamicNodeFactory<PathBuf, ()>,
}
impl ReadStatics {
fn new(watcher: Rc<RefCell<FileWatcher>>) -> Self {
Self {
watcher,
factory: DynamicNodeFactory::new(),
}
}
}
impl DynamicRule for ReadStatics {
type ChildOutput = ();
fn evaluate(&mut self, ctx: &mut impl DynamicRuleContext) -> Vec<Input<Self::ChildOutput>> {
let files = read_files_recursive(content_path("static")).expect("reading static directory");
for ent in files {
if let Ok(ent) = ent {
assert!(ent.file_type().unwrap().is_file());
self.factory.add_node(ctx, ent.path(), |ctx| {
let (node, invalidate) =
ctx.add_invalidatable_rule(CopyStatic { path: ent.path() });
self.watcher
.borrow_mut()
.watch(ent.path(), move || invalidate.invalidate());
node
});
}
}
self.factory.all_nodes(ctx)
}
}
#[derive(InputVisitable)]
struct CopyStatic {
#[skip_visit]
path: PathBuf,
}
impl Rule for CopyStatic {
type Output = ();
fn evaluate(&mut self) -> Self::Output {
let relative_path = self
.path
.strip_prefix(content_path("static"))
.expect("CopyStatic path should be relative to static directory");
let output_path = output_path(relative_path);
std::fs::copy(&self.path, output_path).expect("copying static");
}
}
#[derive(Debug)]
struct ReadFilesRecursive {
read_dir: ReadDir,
recurse: Option<Box<ReadFilesRecursive>>,
}
impl Iterator for ReadFilesRecursive {
type Item = <ReadDir as Iterator>::Item;
fn next(&mut self) -> Option<Self::Item> {
if let Some(ref mut recursive) = self.recurse {
match recursive.next() {
Some(item) => Some(item),
None => {
self.recurse = None;
self.next()
}
}
} else {
match self.read_dir.next() {
Some(Ok(ent)) => {
if let Ok(ft) = ent.file_type()
&& ft.is_dir()
&& let Ok(recurse) = read_files_recursive(ent.path())
{
self.recurse = Some(Box::new(recurse));
self.next()
} else {
Some(Ok(ent))
}
}
result => result,
}
}
}
}
fn read_files_recursive(path: PathBuf) -> std::io::Result<ReadFilesRecursive> {
std::fs::read_dir(path).map(|read_dir| ReadFilesRecursive {
read_dir,
recurse: None,
})
}