use axum::{ extract::{Path, State}, http::{header, StatusCode}, response::{Html, IntoResponse}, routing::get, Router, }; use clap::Parser; use markdown::ParseOptions; use std::{collections::HashMap, path::PathBuf, sync::Arc}; use syntect::{ highlighting::{Theme, ThemeSet}, html::highlighted_html_for_string, parsing::{SyntaxSet, SyntaxSetBuilder}, }; use two_face::theme::EmbeddedLazyThemeSet; // #[derive(Debug)] struct BlogState { templates: HashMap>, posts: HashMap>, ps: SyntaxSet, ts: EmbeddedLazyThemeSet, config: Config, } type AppState = State>; #[derive(Debug)] struct Cached { data: S, path: PathBuf, // TODO // last_read: NaiveDateTime, } impl> Cached { fn data(&self) -> std::io::Result { let contents = std::fs::read_to_string(&self.path)?; Ok(S::from(contents)) // TODO //if self.last_read + Duration::minutes(30) > now { // let contents = std::fs::read_to_string(&self.path)?; // // self.last_read = now; // self.data = S::from(contents); // // Ok(&self.data) //} else { // Ok(&self.data) //} } fn from_file_path(path: PathBuf) -> std::io::Result { let contents = std::fs::read_to_string(&path)?; Ok(Self { data: S::from(contents), path, // last_read: Utc::now().naive_utc(), }) } } #[derive(Debug)] struct Template { index: usize, content: String, } impl From for Template { fn from(value: String) -> Self { let index = value.find("%%%").unwrap_or_default(); Self { index, content: value, } } } #[derive(Debug)] struct Post { content: String, embed_template_name: Option, } trait ToHtml { fn is_directive(&self) -> bool; fn to_html(&self, ps: &SyntaxSet, theme: &Theme) -> String; fn template(&self) -> Option; } impl ToHtml for markdown::mdast::Node { fn to_html(&self, ps: &SyntaxSet, theme: &Theme) -> String { let mut s = String::new(); if self.is_directive() { return s; } match self { markdown::mdast::Node::Root(root) => { for child in &root.children { s += &child.to_html(ps, theme); } } markdown::mdast::Node::Blockquote(block_quote) => { s += "
"; for child in &block_quote.children { s += &child.to_html(ps, theme); } s += "
"; } markdown::mdast::Node::FootnoteDefinition(_) => {} markdown::mdast::Node::MdxJsxFlowElement(_) => {} markdown::mdast::Node::List(list) => { s += "
    "; for child in &list.children { s += &child.to_html(ps, theme); } s += "
"; } markdown::mdast::Node::MdxjsEsm(_) => {} markdown::mdast::Node::Toml(_) => {} markdown::mdast::Node::Yaml(_) => {} markdown::mdast::Node::Break(_) => {} markdown::mdast::Node::InlineCode(inline_code) => { s += &format!( "{}", &ansi_to_html::convert(&inline_code.value).unwrap() ); } markdown::mdast::Node::InlineMath(_) => {} markdown::mdast::Node::Delete(_) => {} markdown::mdast::Node::Emphasis(emphasis) => { s += ""; for child in &emphasis.children { s += &child.to_html(ps, theme); } s += ""; } markdown::mdast::Node::MdxTextExpression(_) => {} markdown::mdast::Node::FootnoteReference(_) => {} markdown::mdast::Node::Html(_) => {} markdown::mdast::Node::Image(image) => { if image.url.ends_with(".mp4") { s += &format!("