Something went wrong. Try again.
Markdown parser fork with extended syntax for personal use.
Something went wrong. Try again.
7.5 kB · 281 lines
Rust
at main
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282//! The flow content type.//!//! **Flow** represents the sections, such as headings and code, which are//! parsed per line.//! An example is HTML, which has a certain starting condition (such as//! `<script>` on its own line), then continues for a while, until an end//! condition is found (such as `</style>`).//! If that line with an end condition is never found, that flow goes until//! the end.//!//! The constructs found in flow are://!//! * [Blank line][crate::construct::blank_line]//! * [Code (indented)][crate::construct::code_indented]//! * [Heading (atx)][crate::construct::heading_atx]//! * [Heading (setext)][crate::construct::heading_setext]//! * [HTML (flow)][crate::construct::html_flow]//! * [MDX esm][crate::construct::mdx_esm]//! * [MDX expression (flow)][crate::construct::mdx_expression_flow]//! * [MDX JSX (flow)][crate::construct::mdx_jsx_flow]//! * [Raw (flow)][crate::construct::raw_flow] (code (fenced), math (flow))//! * [Thematic break][crate::construct::thematic_break]
use crate::event::Name;use crate::state::{Name as StateName, State};use crate::tokenizer::Tokenizer;
/// Start of flow.///// ```markdown/// > | ## alpha/// ^/// > | bravo/// ^/// > | ***/// ^/// ```pub fn start(tokenizer: &mut Tokenizer) -> State { match tokenizer.current { Some(b'#') => { tokenizer.attempt( State::Next(StateName::FlowAfter), State::Next(StateName::FlowBeforeContent), ); State::Retry(StateName::HeadingAtxStart) } Some(b'$' | b'`' | b'~') => { tokenizer.attempt( State::Next(StateName::FlowAfter), State::Next(StateName::FlowBeforeContent), ); State::Retry(StateName::RawFlowStart) } // Note: `-` is also used in setext heading underline so it’s not // included here. Some(b'*' | b'_') => { tokenizer.attempt( State::Next(StateName::FlowAfter), State::Next(StateName::FlowBeforeContent), ); State::Retry(StateName::ThematicBreakStart) } Some(b'<') => { tokenizer.attempt( State::Next(StateName::FlowAfter), State::Next(StateName::FlowBeforeMdxJsx), ); State::Retry(StateName::HtmlFlowStart) } Some(b'e' | b'i') => { tokenizer.attempt( State::Next(StateName::FlowAfter), State::Next(StateName::FlowBeforeContent), ); State::Retry(StateName::MdxEsmStart) } Some(b'{') => { tokenizer.attempt( State::Next(StateName::FlowAfter), State::Next(StateName::FlowBeforeContent), ); State::Retry(StateName::MdxExpressionFlowStart) } // Actual parsing: blank line? Indented code? Indented anything? // Tables, setext heading underlines, definitions, and Contents are // particularly weird. _ => State::Retry(StateName::FlowBlankLineBefore), }}
/// At blank line.////// ```markdown/// > | ␠␠␊/// ^/// ```pub fn blank_line_before(tokenizer: &mut Tokenizer) -> State { tokenizer.attempt( State::Next(StateName::FlowBlankLineAfter), State::Next(StateName::FlowBeforeCodeIndented), ); State::Retry(StateName::BlankLineStart)}
/// At code (indented).////// ```markdown/// > | ␠␠␠␠a/// ^/// ```pub fn before_code_indented(tokenizer: &mut Tokenizer) -> State { tokenizer.attempt( State::Next(StateName::FlowAfter), State::Next(StateName::FlowBeforeRaw), ); State::Retry(StateName::CodeIndentedStart)}
/// At raw.////// ````markdown/// > | ```/// ^/// ````pub fn before_raw(tokenizer: &mut Tokenizer) -> State { tokenizer.attempt( State::Next(StateName::FlowAfter), State::Next(StateName::FlowBeforeHtml), ); State::Retry(StateName::RawFlowStart)}
/// At html (flow).////// ```markdown/// > | <a>/// ^/// ```pub fn before_html(tokenizer: &mut Tokenizer) -> State { tokenizer.attempt( State::Next(StateName::FlowAfter), State::Next(StateName::FlowBeforeMdxJsx), ); State::Retry(StateName::HtmlFlowStart)}
/// At mdx jsx (flow).////// ```markdown/// > | <A />/// ^/// ```pub fn before_mdx_jsx(tokenizer: &mut Tokenizer) -> State { tokenizer.attempt( State::Next(StateName::FlowAfter), State::Next(StateName::FlowBeforeHeadingAtx), ); State::Retry(StateName::MdxJsxFlowStart)}
/// At heading (atx).////// ```markdown/// > | # a/// ^/// ```pub fn before_heading_atx(tokenizer: &mut Tokenizer) -> State { tokenizer.attempt( State::Next(StateName::FlowAfter), State::Next(StateName::FlowBeforeHeadingSetext), ); State::Retry(StateName::HeadingAtxStart)}
/// At heading (setext).////// ```markdown/// | a/// > | =/// ^/// ```pub fn before_heading_setext(tokenizer: &mut Tokenizer) -> State { tokenizer.attempt( State::Next(StateName::FlowAfter), State::Next(StateName::FlowBeforeThematicBreak), ); State::Retry(StateName::HeadingSetextStart)}
/// At thematic break.////// ```markdown/// > | ***/// ^/// ```pub fn before_thematic_break(tokenizer: &mut Tokenizer) -> State { tokenizer.attempt( State::Next(StateName::FlowAfter), State::Next(StateName::FlowBeforeMdxExpression), ); State::Retry(StateName::ThematicBreakStart)}
/// At MDX expression (flow).////// ```markdown/// > | {Math.PI}/// ^/// ```pub fn before_mdx_expression(tokenizer: &mut Tokenizer) -> State { tokenizer.attempt( State::Next(StateName::FlowAfter), State::Next(StateName::FlowBeforeGfmTable), ); State::Retry(StateName::MdxExpressionFlowStart)}
/// At GFM table.////// ```markdown/// > | | a |/// ^/// ```pub fn before_gfm_table(tokenizer: &mut Tokenizer) -> State { tokenizer.attempt( State::Next(StateName::FlowAfter), State::Next(StateName::FlowBeforeContent), ); State::Retry(StateName::GfmTableStart)}
/// At content.////// ```markdown/// > | a/// ^/// ```pub fn before_content(tokenizer: &mut Tokenizer) -> State { tokenizer.attempt(State::Next(StateName::FlowAfter), State::Nok); State::Retry(StateName::ContentChunkStart)}
/// After blank line.////// ```markdown/// > | ␠␠␊/// ^/// ```pub fn blank_line_after(tokenizer: &mut Tokenizer) -> State { match tokenizer.current { None => State::Ok, Some(b'\n') => { tokenizer.enter(Name::BlankLineEnding); tokenizer.consume(); tokenizer.exit(Name::BlankLineEnding); // Feel free to interrupt. tokenizer.interrupt = false; State::Next(StateName::FlowStart) } _ => unreachable!("expected eol/eof"), }}
/// After flow.////// ```markdown/// > | # a␊/// ^/// ```pub fn after(tokenizer: &mut Tokenizer) -> State { match tokenizer.current { None => State::Ok, Some(b'\n') => { tokenizer.enter(Name::LineEnding); tokenizer.consume(); tokenizer.exit(Name::LineEnding); State::Next(StateName::FlowStart) } _ => unreachable!("expected eol/eof"), }}