factor out simple templates into a separate SimpleTemplateDir

there's no need to bloat TreehouseDir with that logic
This commit is contained in:
りき萌 2025-07-10 16:50:41 +02:00
parent b792688776
commit 550c062327
7 changed files with 211 additions and 156 deletions

View file

@ -4,7 +4,7 @@ mod include_static_helper;
mod simple_template;
mod tree;
use std::{collections::HashMap, fmt, ops::ControlFlow, sync::Arc};
use std::{ops::ControlFlow, sync::Arc};
use atom::FeedDir;
use dir_helper::DirHelper;
@ -17,10 +17,14 @@ use crate::{
config::Config,
dirs::Dirs,
fun::seasons::Season,
generate::{
simple_template::SimpleTemplateDir,
tree::{DirIndex, TreehouseDir},
},
sources::Sources,
vfs::{
self, AnchoredAtExt, Cd, Content, ContentCache, Dir, DynDir, Entries, HtmlCanonicalize,
MemDir, Overlay, ToDynDir, VPath, VPathBuf,
self, layered_dir, AnchoredAtExt, Cd, Content, ContentCache, Dir, DynDir, Entries,
HtmlCanonicalize, MemDir, Overlay, ToDynDir, VPath, VPathBuf,
},
};
@ -76,134 +80,6 @@ fn load_templates(handlebars: &mut Handlebars, dir: &dyn Dir) {
});
}
struct TreehouseDir {
dirs: Arc<Dirs>,
sources: Arc<Sources>,
handlebars: Arc<Handlebars<'static>>,
dir_index: DirIndex,
}
impl TreehouseDir {
fn new(
dirs: Arc<Dirs>,
sources: Arc<Sources>,
handlebars: Arc<Handlebars<'static>>,
dir_index: DirIndex,
) -> Self {
Self {
dirs,
sources,
handlebars,
dir_index,
}
}
#[instrument("TreehouseDir::dir", skip(self))]
fn dir(&self, path: &VPath) -> Vec<VPathBuf> {
// NOTE: This does not include simple templates, because that's not really needed right now.
let mut index = &self.dir_index;
for component in path.segments() {
if let Some(child) = index.children.get(component) {
index = child;
} else {
// There cannot possibly be any entries under an invalid path.
// Bail early.
return vec![];
}
}
index
.children
.values()
.map(|child| child.full_path.clone())
.collect()
}
#[instrument("TreehouseDir::content", skip(self))]
fn content(&self, path: &VPath) -> Option<Content> {
let path = if path.is_root() {
VPath::new_const("index")
} else {
path
};
self.sources
.treehouse
.files_by_tree_path
.get(path)
.map(|&file_id| {
Content::new(
"text/html",
tree::generate_or_error(&self.sources, &self.dirs, &self.handlebars, file_id)
.into(),
)
})
.or_else(|| {
if path.file_name().is_some_and(|s| !s.starts_with('_')) {
let template_name = path.with_extension("hbs");
if self.handlebars.has_template(template_name.as_str()) {
return Some(Content::new(
"text/html",
simple_template::generate_or_error(
&self.sources,
&self.handlebars,
template_name.as_str(),
)
.into(),
));
}
}
None
})
}
}
impl Dir for TreehouseDir {
fn query(&self, path: &VPath, query: &mut vfs::Query) {
query.provide(|| Entries(self.dir(path)));
query.try_provide(|| self.content(path));
}
}
impl fmt::Debug for TreehouseDir {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str("TreehouseDir")
}
}
/// Acceleration structure for `dir` operations on [`TreehouseDir`]s.
#[derive(Debug, Default)]
struct DirIndex {
full_path: VPathBuf,
children: HashMap<VPathBuf, DirIndex>,
}
impl DirIndex {
#[instrument(name = "DirIndex::new", skip(paths))]
pub fn new<'a>(paths: impl Iterator<Item = &'a VPath>) -> Self {
let mut root = DirIndex::default();
for path in paths {
let mut parent = &mut root;
let mut full_path = VPath::ROOT.to_owned();
for segment in path.segments() {
full_path.push(segment);
let child = parent
.children
.entry(segment.to_owned())
.or_insert_with(|| DirIndex {
full_path: full_path.clone(),
children: HashMap::new(),
});
parent = child;
}
}
root
}
}
pub fn target(dirs: Arc<Dirs>, sources: Arc<Sources>) -> DynDir {
let mut handlebars = create_handlebars(&sources.config.site, dirs.static_.clone());
load_templates(&mut handlebars, &dirs.template);
@ -226,13 +102,16 @@ pub fn target(dirs: Arc<Dirs>, sources: Arc<Sources>) -> DynDir {
);
let dir_index = DirIndex::new(sources.treehouse.files_by_tree_path.keys().map(|x| &**x));
let tree_view = TreehouseDir::new(dirs, sources, handlebars, dir_index);
let treehouse_dir = layered_dir(&[
TreehouseDir::new(dirs, sources.clone(), handlebars.clone(), dir_index).to_dyn(),
SimpleTemplateDir::new(sources.clone(), handlebars.clone()).to_dyn(),
]);
let tree_view = ContentCache::new(tree_view);
let tree_view = ContentCache::new(treehouse_dir);
tree_view.warm_up();
let tree_view = HtmlCanonicalize::new(tree_view);
Overlay::new(tree_view.to_dyn(), root.to_dyn())
layered_dir(&[tree_view.to_dyn(), root.to_dyn()])
.anchored_at(VPath::ROOT.to_owned())
.to_dyn()
}