docs; rendering docs from .dj to .html

still no in-app link to these docs though
This commit is contained in:
りき萌 2024-08-26 23:25:36 +02:00
parent 8aa38ae4c4
commit 879d17d904
13 changed files with 1298 additions and 294 deletions

View file

@ -14,7 +14,9 @@ dashmap = "6.0.1"
derive_more = { version = "1.0.0", features = ["try_from"] }
eyre = "0.6.12"
haku.workspace = true
handlebars = "6.0.0"
indexmap = "2.4.0"
jotdown = "0.5.0"
rand = "0.8.5"
rand_chacha = "0.3.1"
rayon = "1.10.0"
@ -27,6 +29,7 @@ tower-http = { version = "0.5.2", features = ["fs"] }
tracing = "0.1.40"
tracing-subscriber = { version = "0.3.18", features = ["fmt"] }
tracy-client = { version = "0.17.1", optional = true}
walkdir = "2.5.0"
webp = "0.3.0"
[features]

View file

@ -1,9 +1,31 @@
use std::{collections::HashMap, path::PathBuf};
use serde::{Deserialize, Serialize};
use crate::wall;
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct Config {
pub build: BuildConfig,
pub wall_broker: wall::broker::Settings,
pub haku: crate::haku::Limits,
}
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct BuildConfig {
pub render_templates: Vec<RenderTemplate>,
pub page_titles: HashMap<PathBuf, String>,
}
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct RenderTemplate {
pub template: String,
#[serde(flatten)]
pub files: RenderTemplateFiles,
}
#[derive(Debug, Clone, Deserialize, Serialize)]
#[serde(untagged)]
pub enum RenderTemplateFiles {
Directory { from_dir: PathBuf, to_dir: PathBuf },
}

View file

@ -1,4 +1,5 @@
use std::{
ffi::OsStr,
fs::{copy, create_dir_all, remove_dir_all},
net::Ipv4Addr,
path::Path,
@ -7,12 +8,15 @@ use std::{
use api::Api;
use axum::Router;
use config::Config;
use config::{BuildConfig, Config, RenderTemplateFiles};
use copy_dir::copy_dir;
use eyre::Context;
use handlebars::Handlebars;
use serde::Serialize;
use tokio::{fs, net::TcpListener};
use tower_http::services::{ServeDir, ServeFile};
use tracing::{info, info_span};
use tracing::{info, info_span, instrument};
use walkdir::WalkDir;
mod api;
mod config;
@ -20,7 +24,7 @@ mod haku;
mod id;
mod live_reload;
mod login;
pub mod schema;
mod schema;
mod serialization;
mod wall;
@ -35,8 +39,9 @@ struct Paths<'a> {
database_dir: &'a Path,
}
fn build(paths: &Paths<'_>) -> eyre::Result<()> {
let _span = info_span!("build").entered();
#[instrument(skip(paths, config))]
fn build(paths: &Paths<'_>, config: &BuildConfig) -> eyre::Result<()> {
info!("building static site");
_ = remove_dir_all(paths.target_dir);
create_dir_all(paths.target_dir).context("cannot create target directory")?;
@ -50,6 +55,64 @@ fn build(paths: &Paths<'_>) -> eyre::Result<()> {
)
.context("cannot copy haku.wasm file")?;
let mut handlebars = Handlebars::new();
for entry in WalkDir::new("template") {
let entry = entry?;
let path = entry.path();
let file_name = path
.file_name()
.unwrap_or_default()
.to_string_lossy()
.into_owned();
if file_name
.rsplit_once('.')
.is_some_and(|(left, _)| left.ends_with(".hbs"))
{
handlebars.register_template_file(&file_name, path)?;
info!(file_name, "registered template");
}
}
#[derive(Serialize)]
struct DjotData {
title: String,
content: String,
}
for render_template in &config.render_templates {
info!(?render_template);
match &render_template.files {
RenderTemplateFiles::Directory { from_dir, to_dir } => {
create_dir_all(paths.target_dir.join(to_dir))?;
for entry in WalkDir::new(from_dir) {
let entry = entry?;
let inner_path = entry.path().strip_prefix(from_dir)?;
if entry.path().extension() == Some(OsStr::new("dj")) {
let djot = std::fs::read_to_string(entry.path())?;
let events = jotdown::Parser::new(&djot);
let content = jotdown::html::render_to_string(events);
let title = config
.page_titles
.get(entry.path())
.cloned()
.unwrap_or_else(|| entry.path().to_string_lossy().into_owned());
let rendered = handlebars
.render(&render_template.template, &DjotData { title, content })?;
std::fs::write(
paths
.target_dir
.join(to_dir)
.join(inner_path.with_extension("html")),
rendered,
)?;
}
}
}
}
}
Ok(())
}
@ -89,7 +152,7 @@ async fn fallible_main() -> eyre::Result<()> {
)
.context("cannot deserialize config file")?;
build(&paths)?;
build(&paths, &config.build)?;
let dbs = Arc::new(database(&config, &paths)?);
let api = Arc::new(Api { config, dbs });
@ -99,6 +162,7 @@ async fn fallible_main() -> eyre::Result<()> {
ServeFile::new(paths.target_dir.join("static/index.html")),
)
.nest_service("/static", ServeDir::new(paths.target_dir.join("static")))
.nest_service("/docs", ServeDir::new(paths.target_dir.join("docs")))
.nest("/api", api::router(api));
let app = app.nest("/auto-reload", live_reload::router());