Copy static files
This commit is contained in:
parent
494f2ad367
commit
f5c7c14d2e
@ -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()?)
|
||||
}
|
||||
|
120
src/generator/static_files.rs
Normal file
120
src/generator/static_files.rs
Normal 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,
|
||||
})
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user