diff --git a/src/html.rs b/src/html.rs index d67e943..6b58ced 100644 --- a/src/html.rs +++ b/src/html.rs @@ -1,9 +1,6 @@ -//! An HTML renderer that takes an iterator of [`Event`]s and emits HTML. - use std::collections::HashMap; use anyhow::anyhow; -use anyhow::bail; use chrono::DateTime; use chrono::TimeZone; use jotdown::Alignment; @@ -15,6 +12,7 @@ use jotdown::OrderedListNumbering::*; use jotdown::SpanLinkType; use crate::metadata::PageMetadata; +use crate::metadata::PageRoute; use crate::template; use crate::template::TemplateRenderer; @@ -185,7 +183,9 @@ impl<'s> Writer<'s> { Container::Table => out.write_str("<table")?, Container::TableRow { .. } => out.write_str("<tr")?, Container::Section { id } => match self.metadata { - Some(meta) if &meta.title.id == id => { + Some(meta) + if &meta.title.id == id && matches!(meta.route, PageRoute::Post(_)) => + { let renderer = template!("templates/post.html", &mut out)?; assert_eq!(renderer.current(), Some("attrs")); self.states.push(State::Article(renderer)); @@ -432,9 +432,12 @@ impl<'s> Writer<'s> { Container::Table => out.write_str("</table>")?, Container::TableRow { .. } => out.write_str("</tr>")?, Container::Section { id, .. } => match self.metadata { - Some(meta) if &meta.title.id == id => { + Some(meta) + if &meta.title.id == id + && matches!(self.states.last(), Some(State::Article(_))) => + { let Some(State::Article(renderer)) = self.states.pop() else { - bail!("Arrived at the end of the main <section> element without being in the `Article` state.") + unreachable!() }; renderer.finish(&mut out)?; @@ -471,7 +474,7 @@ impl<'s> Writer<'s> { write!(&mut out, "Posted on ")?; write_datetime(&d, &mut out)?; } else { - write!(&mut out, "Still being conjured ")?; + write!(&mut out, "Being conjured by ")?; } } else if label == "updated_on" { write_datetime(&meta.last_modified, &mut out)?; diff --git a/src/metadata.rs b/src/metadata.rs index 0c7e1de..37d212a 100644 --- a/src/metadata.rs +++ b/src/metadata.rs @@ -1,5 +1,7 @@ -#![allow(dead_code)] -use std::{fmt::Write, path::PathBuf, process::Command}; +use std::ffi::OsStr; +use std::fmt::Write; +use std::path::{Component, Path, PathBuf}; +use std::process::Command; use anyhow::{anyhow, bail, Context}; use chrono::{DateTime, FixedOffset}; @@ -31,14 +33,53 @@ impl PageConfig { } } +#[derive(Debug)] +pub enum PageRoute { + Home, + Posts, + #[allow(dead_code)] + Post(String), +} + +impl PageRoute { + fn from_path(path: &Path) -> anyhow::Result<Self> { + let Some(Component::Normal(first)) = path.components().nth(1) else { + bail!("Path is too short"); + }; + + let result = if first == OsStr::new("index.dj") { + Self::Home + } else if first == OsStr::new("posts") { + if let Some(Component::Normal(second)) = path.components().nth(2) { + let mut slice = second.to_str().unwrap(); + if slice.ends_with(".dj") { + slice = slice.strip_suffix(".dj").unwrap(); + } + + Self::Post(slice.to_owned()) + } else { + Self::Posts + } + } else { + bail!("Cannot convert path '{:?}' to page route", path); + }; + + Ok(result) + } +} + #[derive(Debug)] pub struct PageMetadata { pub title: Heading, pub config: PageConfig, - pub toc: Vec<Heading>, pub word_count: usize, - pub path: PathBuf, pub last_modified: DateTime<FixedOffset>, + pub route: PageRoute, + + #[allow(dead_code)] + pub toc: Vec<Heading>, + #[allow(dead_code)] + pub path: PathBuf, } impl PageMetadata { @@ -72,17 +113,19 @@ impl PageMetadata { Ok(Self { title: title.to_owned(), + route: PageRoute::from_path(&path)?, config: w.config, toc: w.toc, word_count: w.word_count, - path, last_modified, + path, }) } } #[derive(Debug, Clone)] pub struct Heading { + #[allow(dead_code)] pub level: u8, pub id: String, pub text: String,