From dcae9feac795bd338c30d11a29d20834ff4101cd Mon Sep 17 00:00:00 2001 From: eiiko6 Date: Wed, 7 Jan 2026 20:55:32 +0100 Subject: [PATCH] implemented automatic summary generation, and added timestamps in page list --- example/SUMMARY.md | 11 --- .../{02-coffee.md => coffee@1767815445.md} | 0 .../{01-ferris.md => ferris@1767468388.md} | 0 example/{03-space.md => space@1767813388.md} | 0 src/main.rs | 71 ++++++++++++++++--- templates/_base.html | 19 +++++ templates/home.html | 41 +++++++++++ templates/page.html | 20 ++---- 8 files changed, 125 insertions(+), 37 deletions(-) delete mode 100644 example/SUMMARY.md rename example/{02-coffee.md => coffee@1767815445.md} (100%) rename example/{01-ferris.md => ferris@1767468388.md} (100%) rename example/{03-space.md => space@1767813388.md} (100%) create mode 100644 templates/_base.html create mode 100644 templates/home.html diff --git a/example/SUMMARY.md b/example/SUMMARY.md deleted file mode 100644 index 8eebf7f..0000000 --- a/example/SUMMARY.md +++ /dev/null @@ -1,11 +0,0 @@ -# The Random Collection - -Welcome to this automatically generated book! This is the **Summary** page, acting as the entry point for our small website. - -### Table of Contents -1. [The Mascot: Ferris](./01-ferris.md) - A look at the Rust mascot. -2. [The Dark Elixir](./02-coffee.md) - A brief history of coffee. -3. [To the Stars](./03-space.md) - Facts about the Voyager 1 probe. - ---- -*Generated for the Axum Markdown Server test.* diff --git a/example/02-coffee.md b/example/coffee@1767815445.md similarity index 100% rename from example/02-coffee.md rename to example/coffee@1767815445.md diff --git a/example/01-ferris.md b/example/ferris@1767468388.md similarity index 100% rename from example/01-ferris.md rename to example/ferris@1767468388.md diff --git a/example/03-space.md b/example/space@1767813388.md similarity index 100% rename from example/03-space.md rename to example/space@1767813388.md diff --git a/src/main.rs b/src/main.rs index a4c3033..5c78149 100644 --- a/src/main.rs +++ b/src/main.rs @@ -8,10 +8,12 @@ use axum::{ use clap::{Parser, Subcommand}; use lazy_static::lazy_static; use pulldown_cmark::{Options, Parser as MarkdownParser, html}; +use serde::{Deserialize, Serialize}; use std::sync::Arc; use std::{io::Cursor, path::PathBuf}; use syntect::{highlighting::ThemeSet, parsing::SyntaxSet}; use tera::{Context, Tera}; +use tokio::io::{AsyncBufReadExt, BufReader}; mod codeblocks; use codeblocks::*; @@ -20,6 +22,8 @@ lazy_static! { pub static ref TEMPLATES: Tera = { let mut tera = Tera::default(); tera.add_raw_templates(vec![ + ("_base.html", include_str!("../templates/_base.html")), + ("home.html", include_str!("../templates/home.html")), ("page.html", include_str!("../templates/page.html")), ("style.css", include_str!("../templates/style.css")), ]) @@ -100,7 +104,54 @@ async fn main() -> anyhow::Result<()> { } async fn render_summary(State(state): State>) -> impl IntoResponse { - render_md_file("SUMMARY.md", state).await + let mut context = Context::new(); + context.insert("title", "Pages"); + + #[derive(Deserialize, Serialize)] + struct Page { + filename: String, + title: String, + datetime: String, + } + + let mut pages: Vec = Vec::new(); + if let Ok(mut entries) = tokio::fs::read_dir(&state.docs_dir).await { + while let Ok(Some(entry)) = entries.next_entry().await { + let path = entry.path(); + let filename = entry.file_name(); + let filename = filename.to_str().unwrap_or(""); + + let title = if let Ok(file) = tokio::fs::File::open(&path).await { + let mut reader = BufReader::new(file); + let mut line = String::new(); + match reader.read_line(&mut line).await { + Ok(_) => line.trim_start_matches('#').trim().to_string(), + Err(_) => filename.to_string(), + } + } else { + filename.to_string() + }; + + let datetime = filename + .split_once('@') + .and_then(|(_, ts_with_ext)| ts_with_ext.split('.').next()) + .map(|dt| dt.to_string()) + .unwrap_or_else(|| "Invalid Date".to_string()); + + pages.push(Page { + filename: filename.to_string(), + title, + datetime, + }); + } + } + + context.insert("files", &pages); + + match TEMPLATES.render("home.html", &context) { + Ok(rendered) => Html(rendered), + Err(e) => Html(format!("

Template Error

{}
", e)), + } } async fn render_page( @@ -112,7 +163,14 @@ async fn render_page( } else { format!("{}.md", page) }; - render_md_file(&filename, state).await + + let file_path = state.docs_dir.join(&filename); + + let content = match tokio::fs::read_to_string(&file_path).await { + Ok(c) => c, + Err(_) => return Html("

404

Page not found

".to_string()), + }; + render_md_file(&content, &filename, state).await } async fn serve_css() -> impl IntoResponse { @@ -125,14 +183,7 @@ async fn serve_css() -> impl IntoResponse { } } -async fn render_md_file(filename: &str, state: Arc) -> Html { - let file_path = state.docs_dir.join(filename); - - let content = match tokio::fs::read_to_string(&file_path).await { - Ok(c) => c, - Err(_) => return Html("

404

Page not found

".to_string()), - }; - +async fn render_md_file(content: &String, filename: &str, state: Arc) -> Html { let mut options = Options::empty(); options.insert(Options::ENABLE_TABLES); options.insert(Options::ENABLE_FOOTNOTES); diff --git a/templates/_base.html b/templates/_base.html new file mode 100644 index 0000000..abce6b4 --- /dev/null +++ b/templates/_base.html @@ -0,0 +1,19 @@ + + + + {% block head %} + + {{ title }} + + + {% endblock head %} + + + + + +
{% block content %}{% endblock content %}
+ + diff --git a/templates/home.html b/templates/home.html new file mode 100644 index 0000000..a71d3f8 --- /dev/null +++ b/templates/home.html @@ -0,0 +1,41 @@ +{% extends "_base.html" %} +{% block title %}{{ title }}{% endblock title %} +{% block content %} +

{{ title }}

+ +
    + {% for file in files %} +
  1. + {{ file.title }} - + + {{ file.datetime }} + +
  2. + {% endfor %} +
+ +
+ + +{% endblock content %} diff --git a/templates/page.html b/templates/page.html index 648b7f1..b66ea2c 100644 --- a/templates/page.html +++ b/templates/page.html @@ -1,21 +1,10 @@ - - - - - {{ title }} - - - - - +{% extends "_base.html" %} +{% block title %}{{ title }}{% endblock title %} +{% block content %}
{{ content | safe }}
- - - - +{% endblock content %}