post parsing with different comrak

This commit is contained in:
2024-03-02 13:12:55 +01:00
parent 4fd4373ed0
commit 49b92088b7
8 changed files with 188 additions and 130 deletions

View File

@ -26,7 +26,9 @@ async fn main() {
.init();
// build our application with a single route
let app = router::get_router().nest_service("/styles", ServeDir::new("styles"));
let app = router::get_router()
.nest_service("/styles", ServeDir::new("styles"))
.nest_service("/images", ServeDir::new("../static/images"));
#[cfg(debug_assertions)]
let app = app.layer(LiveReloadLayer::new());

View File

@ -1,3 +1,4 @@
use crate::filters;
use askama::Template;
use axum::{extract::Path, http::StatusCode};
use chrono::{DateTime, Utc};
@ -28,6 +29,7 @@ pub struct PostMetadata {
pub struct PostTemplate {
pub title: String,
pub body: String,
pub date: DateTime<Utc>,
pub site_footer: SiteFooter,
pub header_props: HeaderProps,
}
@ -42,6 +44,7 @@ pub async fn render_post(Path(post_id): Path<String>) -> Result<PostTemplate, St
.map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?;
Ok(PostTemplate {
title: parsed.metadata.title,
date: parsed.metadata.date,
body: parsed.body,
site_footer,
header_props: HeaderProps::default(),

View File

@ -2,8 +2,12 @@ use std::path::Path;
use axum::http::StatusCode;
use chrono::{DateTime, Utc};
use comrak::{
format_html,
nodes::{AstNode, NodeValue},
parse_document, Arena, Options,
};
use gray_matter::{engine::YAML, Matter};
use markdown::{to_html_with_options, CompileOptions, Constructs, Options, ParseOptions};
use serde::{de::DeserializeOwned, Deserialize, Deserializer};
use tokio::fs;
@ -35,26 +39,6 @@ pub async fn parse_post<'de, Metadata: DeserializeOwned>(
// TODO Proper reasoning for an error
.map_err(|_| StatusCode::NOT_FOUND)?;
let markdown_options = Options {
parse: ParseOptions {
constructs: Constructs {
frontmatter: true,
..Default::default()
},
..Default::default()
},
compile: CompileOptions {
allow_dangerous_html: true,
..Default::default()
},
..Default::default()
};
let body = to_html_with_options(&file_contents, &markdown_options).map_err(|reason| {
tracing::error!(reason);
return StatusCode::INTERNAL_SERVER_ERROR;
})?;
let matter = Matter::<YAML>::new();
let metadata = matter
.parse_with_struct::<Metadata>(&file_contents)
@ -63,6 +47,8 @@ pub async fn parse_post<'de, Metadata: DeserializeOwned>(
return StatusCode::INTERNAL_SERVER_ERROR;
})?;
let body = parse_html(&metadata.content);
let filename = Path::new(path)
.file_stem()
.ok_or(StatusCode::INTERNAL_SERVER_ERROR)?
@ -76,3 +62,51 @@ pub async fn parse_post<'de, Metadata: DeserializeOwned>(
slug: filename,
});
}
fn parse_html(markdown: &str) -> String {
let mut options = Options::default();
options.parse.smart = true;
options.parse.relaxed_autolinks = true;
options.extension.strikethrough = true;
// options.extension.tagfilter = true;
options.extension.table = true;
options.extension.autolink = true;
options.extension.tasklist = true;
options.extension.superscript = true;
options.extension.header_ids = Some("".to_string());
options.extension.footnotes = false;
options.extension.description_lists = false;
options.extension.multiline_block_quotes = false;
options.extension.shortcodes = true;
options.render.hardbreaks = true;
options.render.github_pre_lang = true;
options.render.full_info_string = true;
options.render.unsafe_ = true;
// The returned nodes are created in the supplied Arena, and are bound by its lifetime.
let arena = Arena::new();
let root = parse_document(&arena, markdown, &options);
fn iter_nodes<'a, F>(node: &'a AstNode<'a>, f: &F)
where
F: Fn(&'a AstNode<'a>),
{
f(node);
for c in node.children() {
iter_nodes(c, f);
}
}
iter_nodes(root, &|node| match &mut node.data.borrow_mut().value {
&mut NodeValue::Text(ref mut _text) => {
// let orig = std::mem::replace(text, String::new());
// *text = orig.replace("my", "your");
}
_ => (),
});
let mut html = vec![];
format_html(root, &options, &mut html).unwrap();
return String::from_utf8(html).unwrap();
}