Markdown parser fork with extended syntax for personal use.
at hack 115 lines 3.2 kB view raw
1//! Paragraph occurs in the [content][] content type. 2//! 3//! ## Grammar 4//! 5//! Paragraph forms with the following BNF 6//! (<small>see [construct][crate::construct] for character groups</small>): 7//! 8//! ```bnf 9//! ; Restriction: lines cannot start other flow constructs. 10//! ; Restriction: lines cannot be blank. 11//! paragraph ::= 1*line *(eol 1*line) 12//! ``` 13//! 14//! This construct must be followed by an eol (line ending) or eof (end of 15//! file), like flow constructs. 16//! 17//! Paragraphs can contain line endings and whitespace, but they are not 18//! allowed to contain blank lines, or to be blank themselves. 19//! 20//! The paragraph is interpreted as the [text][] content type. 21//! That means that [autolinks][autolink], [code (text)][raw_text], etc are 22//! allowed. 23//! 24//! ## HTML 25//! 26//! Paragraphs in markdown relate to the `<p>` element in HTML. 27//! See [*§ 4.4.1 The `p` element* in the HTML spec][html] for more info. 28//! 29//! ## Tokens 30//! 31//! * [`Paragraph`][Name::Paragraph] 32//! 33//! ## References 34//! 35//! * [`content.js` in `micromark`](https://github.com/micromark/micromark/blob/main/packages/micromark-core-commonmark/dev/lib/content.js) 36//! * [*§ 4.8 Paragraphs* in `CommonMark`](https://spec.commonmark.org/0.31/#paragraphs) 37//! 38//! [content]: crate::construct::content 39//! [text]: crate::construct::text 40//! [autolink]: crate::construct::autolink 41//! [raw_text]: crate::construct::raw_text 42//! [html]: https://html.spec.whatwg.org/multipage/grouping-content.html#the-p-element 43 44use crate::event::{Content, Link, Name}; 45use crate::state::{Name as StateName, State}; 46use crate::subtokenize::link; 47use crate::tokenizer::Tokenizer; 48 49/// Paragraph start. 50/// 51/// ```markdown 52/// > | abc 53/// ^ 54/// | def 55/// ``` 56pub fn start(tokenizer: &mut Tokenizer) -> State { 57 debug_assert!(tokenizer.current.is_some()); 58 tokenizer.enter(Name::Paragraph); 59 State::Retry(StateName::ParagraphLineStart) 60} 61 62/// Start of a line in a paragraph. 63/// 64/// ```markdown 65/// > | abc 66/// ^ 67/// > | def 68/// ^ 69/// ``` 70pub fn line_start(tokenizer: &mut Tokenizer) -> State { 71 debug_assert!(tokenizer.current.is_some()); 72 tokenizer.enter_link( 73 Name::Data, 74 Link { 75 previous: None, 76 next: None, 77 content: Content::Text, 78 }, 79 ); 80 81 if tokenizer.tokenize_state.connect { 82 let index = tokenizer.events.len() - 1; 83 link(&mut tokenizer.events, index); 84 } else { 85 tokenizer.tokenize_state.connect = true; 86 } 87 88 State::Retry(StateName::ParagraphInside) 89} 90 91/// In paragraph. 92/// 93/// ```markdown 94/// > | abc 95/// ^^^ 96/// ``` 97pub fn inside(tokenizer: &mut Tokenizer) -> State { 98 match tokenizer.current { 99 None => { 100 tokenizer.tokenize_state.connect = false; 101 tokenizer.exit(Name::Data); 102 tokenizer.exit(Name::Paragraph); 103 State::Ok 104 } 105 Some(b'\n') => { 106 tokenizer.consume(); 107 tokenizer.exit(Name::Data); 108 State::Next(StateName::ParagraphLineStart) 109 } 110 _ => { 111 tokenizer.consume(); 112 State::Next(StateName::ParagraphInside) 113 } 114 } 115}