Skip to main content

rushdown/parser/
strikethrough.rs

1extern crate alloc;
2
3use crate::{
4    as_kind_data,
5    ast::{Arena, NodeRef, Strikethrough},
6    parser::{self, parse_delimiter, Delimiter, DelimiterProcessor, InlineParser},
7    text::{self, Reader},
8};
9
10/// [`InlineParser`] for strikethrough text.
11#[derive(Debug)]
12pub struct StrikethroughParser {
13    processor: DelimiterProcessor,
14}
15
16fn is_delimiter(c: u8) -> bool {
17    c == b'~'
18}
19
20fn can_open_closer(opener: &Delimiter, closer: &Delimiter) -> bool {
21    opener.char() == closer.char()
22}
23
24fn on_match(arena: &mut Arena, _consumes: usize) -> NodeRef {
25    arena.new_node(Strikethrough::new())
26}
27
28impl Default for StrikethroughParser {
29    fn default() -> Self {
30        let processor = DelimiterProcessor::new(is_delimiter, can_open_closer, on_match);
31        Self { processor }
32    }
33}
34
35impl StrikethroughParser {
36    /// Returns a new [`StrikethroughParser`].
37    pub fn new() -> Self {
38        Self::default()
39    }
40}
41
42impl InlineParser for StrikethroughParser {
43    fn trigger(&self) -> &[u8] {
44        b"~"
45    }
46
47    fn parse(
48        &self,
49        arena: &mut Arena,
50        parent_ref: NodeRef,
51        reader: &mut text::BlockReader,
52        ctx: &mut parser::Context,
53    ) -> Option<NodeRef> {
54        let precending = reader.precending_charater();
55        let text = parse_delimiter(arena, parent_ref, reader, 1, &self.processor, ctx)?;
56        let index = as_kind_data!(arena, text, Text).index()?;
57        if index.len() > 2 || precending == '~' {
58            return None;
59        }
60        Some(text)
61    }
62}