markdown_that/plugins/html/
html_inline.rs

1//! HTML inline syntax from CommonMark
2//!
3//! <https://spec.commonmark.org/0.30/#raw-html>
4use super::utils::regexps::*;
5use crate::parser::inline::{InlineRule, InlineState};
6use crate::{MarkdownThat, Node, NodeValue, Renderer};
7
8#[derive(Debug)]
9pub struct HtmlInline {
10    pub content: String,
11}
12
13impl NodeValue for HtmlInline {
14    fn render(&self, _: &Node, fmt: &mut dyn Renderer) {
15        fmt.text_raw(&self.content);
16    }
17}
18
19pub fn add(md: &mut MarkdownThat) {
20    md.inline.add_rule::<HtmlInlineScanner>();
21}
22
23#[doc(hidden)]
24pub struct HtmlInlineScanner;
25impl InlineRule for HtmlInlineScanner {
26    const MARKER: char = '<';
27
28    fn run(state: &mut InlineState) -> Option<(Node, usize)> {
29        // Check start
30        let mut chars = state.src[state.pos..state.pos_max].chars();
31        if chars.next().unwrap() != '<' {
32            return None;
33        }
34
35        // Quick fail on second char
36        let Some('!' | '?' | '/' | 'A'..='Z' | 'a'..='z') = chars.next() else {
37            return None;
38        };
39
40        let capture = HTML_TAG_RE
41            .captures(&state.src[state.pos..state.pos_max])?
42            .get(0)
43            .unwrap()
44            .as_str();
45        let capture_len = capture.len();
46
47        let content = capture.to_owned();
48
49        if HTML_LINK_OPEN.is_match(&content) {
50            state.link_level += 1;
51        } else if HTML_LINK_CLOSE.is_match(&content) {
52            state.link_level -= 1;
53        }
54
55        let node = Node::new(HtmlInline { content });
56        Some((node, capture_len))
57    }
58}