62 lines
1.8 KiB
Rust
62 lines
1.8 KiB
Rust
use crate::generator::posts::parse::{parse_post, prepare_post, PostContent, PostMetadata};
|
|
use crate::generator::{content_path, HtmlContent, Post};
|
|
use compute_graph::rule::{Input, InputVisitable, Rule};
|
|
use std::fs;
|
|
use std::path::PathBuf;
|
|
|
|
pub fn list_post_files() -> anyhow::Result<Vec<PathBuf>> {
|
|
let posts_path = content_path("posts/");
|
|
let mut paths = vec![];
|
|
for ent in fs::read_dir(posts_path)? {
|
|
let Ok(ent) = ent else {
|
|
continue;
|
|
};
|
|
let Ok(ty) = ent.file_type() else {
|
|
continue;
|
|
};
|
|
if ty.is_dir() {
|
|
paths.push(find_index(ent.path()).expect("folder posts must have index file"));
|
|
} else {
|
|
paths.push(ent.path());
|
|
}
|
|
}
|
|
Ok(paths)
|
|
}
|
|
|
|
fn find_index(path: PathBuf) -> Option<PathBuf> {
|
|
let dir = fs::read_dir(path).ok()?;
|
|
dir.flatten()
|
|
.find(|e| e.path().file_stem().unwrap().eq_ignore_ascii_case("index"))
|
|
.map(|e| e.path())
|
|
}
|
|
|
|
#[derive(InputVisitable)]
|
|
pub struct ParsePost(pub PathBuf);
|
|
|
|
impl Rule for ParsePost {
|
|
type Output = Post<HtmlContent>;
|
|
fn evaluate(&mut self) -> Self::Output {
|
|
match parse_post(self.0.clone()) {
|
|
Ok(post) => prepare_post(post),
|
|
Err(e) => {
|
|
let path = self.0.to_string_lossy();
|
|
panic!("Failed to parse post {path}: {e}")
|
|
}
|
|
}
|
|
}
|
|
|
|
fn node_label(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
|
write!(f, "{}", self.0.file_stem().unwrap().to_string_lossy())
|
|
}
|
|
}
|
|
|
|
#[derive(InputVisitable)]
|
|
pub struct ExtractMetadata<C: PostContent>(pub Input<Post<C>>);
|
|
|
|
impl<C: PostContent + 'static> Rule for ExtractMetadata<C> {
|
|
type Output = PostMetadata;
|
|
fn evaluate(&mut self) -> Self::Output {
|
|
self.input_0().metadata.clone()
|
|
}
|
|
}
|