Copy static files
This commit is contained in:
parent
494f2ad367
commit
f5c7c14d2e
@ -3,6 +3,7 @@ mod css;
|
|||||||
mod home;
|
mod home;
|
||||||
mod markdown;
|
mod markdown;
|
||||||
mod posts;
|
mod posts;
|
||||||
|
mod static_files;
|
||||||
mod tags;
|
mod tags;
|
||||||
mod templates;
|
mod templates;
|
||||||
mod util;
|
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 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);
|
builder.set_existing_output(output);
|
||||||
Ok(builder.build()?)
|
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