sevenmark_parser/parser/markdown/
markdown_header.rs1use crate::ast::{Element, HeaderElement, Span};
2use crate::parser::ParserInput;
3use crate::parser::element::element_parser;
4use crate::parser::utils::with_depth;
5use winnow::Result;
6use winnow::ascii::line_ending;
7use winnow::combinator::eof;
8use winnow::combinator::{alt, opt, terminated};
9use winnow::prelude::*;
10use winnow::stream::Location as StreamLocation;
11use winnow::token::{literal, take_while};
12
13pub fn markdown_header_parser(parser_input: &mut ParserInput) -> Result<Element> {
15 if parser_input.state.current_depth() > 0 {
16 return Err(winnow::error::ContextError::new());
17 }
18
19 let current_pos = parser_input.current_token_start();
21 if !parser_input.state.is_at_line_start(current_pos) {
22 return Err(winnow::error::ContextError::new());
23 }
24
25 let start = parser_input.current_token_start();
31 let (header_marks, is_folded, _, parsed_content) = (
32 take_while(1..=6, '#'),
33 opt(literal('!')),
34 opt(literal(' ')),
35 terminated(
36 |input: &mut ParserInput| {
37 input.state.set_header_context();
38 let result = with_depth(input, element_parser);
39 input.state.unset_header_context();
40 result
41 },
42 alt((line_ending, eof)),
43 ),
44 )
45 .parse_next(parser_input)?;
46
47 let end = parser_input.previous_token_end();
48 let header_level = header_marks.len();
49 let is_folded = is_folded.is_some();
50 let section_index = parser_input.state.next_section_index();
51
52 Ok(Element::Header(HeaderElement {
53 span: Span { start, end },
54 level: header_level,
55 is_folded,
56 section_index,
57 children: parsed_content,
58 }))
59}