1mod latex;
2use crate::latex::latex_render_mathml;
3
4use markdown_it::{
5 MarkdownIt, Node, NodeValue, Renderer,
6 parser::inline::{ InlineRule, InlineState }
7};
8
9#[derive(Debug)]
10pub struct LaTeXNode {
11 latex: String,
12 inline: bool
13}
14
15impl NodeValue for LaTeXNode {
16 fn render(&self, _node: &Node, fmt: &mut dyn Renderer) {
17 let mathml = latex_render_mathml(&self.latex, self.inline);
18 fmt.text_raw(&mathml);
19 }
20}
21
22struct LaTeXScan;
23
24impl InlineRule for LaTeXScan {
25 const MARKER: char = '$';
26 fn run(state: &mut InlineState) -> Option<(Node, usize)> {
27 let input = &state.src[state.pos..];
28 if !input.starts_with("$") { return None; }
29
30 let latex_enter_count = if input.starts_with("$$") { 2 } else { 1 };
31
32 let start_pos = state.pos + latex_enter_count;
33 let mut last_posi = state.pos + latex_enter_count;
34 let mut next_posi = state.pos + latex_enter_count;
35
36 while next_posi < state.pos_max {
37 let current_input = &state.src[next_posi..];
38 if !current_input.starts_with(&"$".repeat(latex_enter_count)) {
39 next_posi += 1;
40 continue;
41 }
42
43 last_posi = next_posi;
44 break;
45 }
46 let latex_text = &state.src[start_pos..last_posi];
47 Some((
48 Node::new(LaTeXNode {
49 latex: latex_text.to_string(),
50 inline: latex_enter_count == 1
51 }),
52 last_posi + latex_enter_count - (state.pos)
53 ))
54 }
55}
56
57pub fn add(md: &mut MarkdownIt) {
58 md.inline.add_rule::<LaTeXScan>();
59}