Page meta from frontmatter

This commit is contained in:
2025-11-04 14:15:00 -08:00
parent 4504a88f4b
commit dc4a1def5f
13 changed files with 518 additions and 163 deletions

View File

@@ -1,33 +1,51 @@
use lazy_static::lazy_static;
use markdown_it::parser::block::{BlockRule, BlockState};
use markdown_it::parser::core::Root;
use markdown_it::parser::inline::{InlineRule, InlineState};
use markdown_it::{Node, NodeValue, Renderer};
use markdown_it::{MarkdownIt, Node, NodeValue, Renderer};
use maud::{Markup, PreEscaped, Render};
use std::str::FromStr;
use crate::components::fa::FAIcon;
use crate::components::mangle::{MangledBetaEmail, MangledGoogleEmail};
lazy_static! {
static ref MdParser: MarkdownIt = {
let mut md = markdown_it::MarkdownIt::new();
markdown_it::plugins::cmark::add(&mut md);
markdown_it::plugins::html::add(&mut md);
md.inline.add_rule::<InlineEmote>();
md.inline.add_rule::<InlineEmote>();
md.inline.add_rule::<InlineMdx>();
md.block.add_rule::<FrontMatter>().before_all();
md
};
}
pub struct Markdown<'a>(pub &'a str);
impl Render for Markdown<'_> {
fn render(&self) -> Markup {
// TODO: init once
let md = &mut markdown_it::MarkdownIt::new();
markdown_it::plugins::cmark::add(md);
markdown_it::plugins::html::add(md);
md.inline.add_rule::<InlineEmote>();
md.inline.add_rule::<InlineMdx>();
let md = md.parse(self.0);
let md = Self::parse(self.0);
let html = md.render();
return PreEscaped(html);
}
}
impl Markdown<'_> {
pub fn parse(md_str: &str) -> Node {
MdParser.parse(md_str)
}
}
//
// MARK: extensions
//
//
// MARK: emote
//
#[derive(Debug)]
pub struct InlineEmote(String);
@@ -66,6 +84,10 @@ impl InlineRule for InlineEmote {
}
}
//
// MARK: mdx
//
#[derive(Debug)]
pub struct InlineMdx(String);
@@ -245,3 +267,58 @@ fn mdx_include(mdx: &str, _node: &Node, fmt: &mut dyn Renderer) -> bool {
return true;
}
//
// MARK: frontmatter
//
#[derive(Debug)]
/// AST node for front-matter
pub struct FrontMatter {
pub content: String,
}
impl NodeValue for FrontMatter {
fn render(&self, _node: &Node, _fmt: &mut dyn Renderer) {}
}
impl BlockRule for FrontMatter {
fn run(state: &mut BlockState<'_, '_>) -> Option<(Node, usize)> {
// check the parent is the document Root
if !state.node.is::<Root>() {
return None;
}
// check we are on the first line of the document
if state.line != 0 {
return None;
}
// check line starts with opening dashes
let opening = state
.get_line(state.line)
.chars()
.take_while(|c| *c == '-')
.collect::<String>();
if !opening.starts_with("---") {
return None;
}
// Search for the end of the block
let mut next_line = state.line;
loop {
next_line += 1;
if next_line >= state.line_max {
return None;
}
let line = state.get_line(next_line);
if line.starts_with(&opening) {
break;
}
}
let (content, _) = state.get_lines(state.line + 1, next_line, 0, true);
Some((Node::new(FrontMatter { content }), next_line + 1))
}
}