Page meta from frontmatter
This commit is contained in:
@@ -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))
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user