docs; rendering docs from .dj to .html
still no in-app link to these docs though
This commit is contained in:
parent
8aa38ae4c4
commit
879d17d904
13 changed files with 1298 additions and 294 deletions
|
@ -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]
|
||||
|
|
|
@ -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 },
|
||||
}
|
||||
|
|
|
@ -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());
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue