51 lines
1.6 KiB
Rust
51 lines
1.6 KiB
Rust
use std::sync::LazyLock;
|
|
|
|
use askama::Template;
|
|
use askama_web::WebTemplate;
|
|
use pulldown_cmark::{Event, Options, Parser, Tag, html};
|
|
|
|
static README_HTML: LazyLock<String> = LazyLock::new(|| {
|
|
let events: Vec<_> = Parser::new_ext(
|
|
include_str!("../../README.md"),
|
|
Options::ENABLE_TABLES | Options::ENABLE_STRIKETHROUGH | Options::ENABLE_TASKLISTS,
|
|
)
|
|
.collect();
|
|
let anchored = events.iter().enumerate().map(|(index, event)| {
|
|
if let Event::Start(Tag::Heading(level, None, _)) = event {
|
|
let title: String = events[index + 1..]
|
|
.iter()
|
|
.take_while(|event| !matches!(event, Event::End(Tag::Heading(..))))
|
|
.filter_map(|event| match event {
|
|
Event::Text(text) | Event::Code(text) => Some(text.as_ref()),
|
|
_ => None,
|
|
})
|
|
.collect();
|
|
let slug: String = title
|
|
.to_lowercase()
|
|
.chars()
|
|
.filter(|character| {
|
|
character.is_alphanumeric() || *character == '-' || character.is_whitespace()
|
|
})
|
|
.collect();
|
|
let slug = slug.split_whitespace().collect::<Vec<_>>().join("-");
|
|
return Event::Html(format!("<{level} id=\"{slug}\">").into());
|
|
}
|
|
event.clone()
|
|
});
|
|
let mut rendered = String::new();
|
|
html::push_html(&mut rendered, anchored);
|
|
rendered
|
|
});
|
|
|
|
#[derive(Template, WebTemplate)]
|
|
#[template(path = "home.html")]
|
|
pub struct HomePage {
|
|
readme: &'static str,
|
|
}
|
|
|
|
pub async fn home_page() -> HomePage {
|
|
HomePage {
|
|
readme: &README_HTML,
|
|
}
|
|
}
|