Markdown parser fork with extended syntax for personal use.
1//! Blank lines occur in the [flow][] content type.
2//!
3//! ## Grammar
4//!
5//! Blank lines form with the following BNF
6//! (<small>see [construct][crate::construct] for character groups</small>):
7//!
8//! ```bnf
9//! blank_line ::= *space_or_tab
10//! ```
11//!
12//! As this construct occurs in flow, like all flow constructs, it must be
13//! followed by an eol (line ending) or eof (end of file).
14//!
15//! Blank lines are sometimes needed, such as to differentiate a [paragraph][]
16//! from a definition.
17//! In several cases, blank lines are not needed between flow constructs,
18//! such as between two [heading (atx)][heading_atx]s.
19//! Sometimes, whether blank lines are present, changes the behavior of how
20//! HTML is rendered, such as whether blank lines are present inside or between
21//! [list items][list_item].
22//! More than one blank line is never needed in `CommonMark`.
23//!
24//! Because blank lines can be empty (line endings are not considered part of
25//! it), and events cannot be empty, blank lines are not present as an event.
26//!
27//! ## HTML
28//!
29//! Blank lines do not relate to an element in HTML, except for the role they
30//! play when inside or between [list items][list_item].
31//!
32//! ## Recommendation
33//!
34//! It is recommended to always use a blank line between every flow construct,
35//! to use blank lines (consistently) between list items as desired, and to
36//! never use more than one blank line.
37//!
38//! ## Tokens
39//!
40//! * [`SpaceOrTab`][crate::event::Name::SpaceOrTab]
41//!
42//! ## References
43//!
44//! * [`blank-line.js` in `micromark`](https://github.com/micromark/micromark/blob/main/packages/micromark-core-commonmark/dev/lib/blank-line.js)
45//! * [*§ 4.9 Blank lines* in `CommonMark`](https://spec.commonmark.org/0.31/#blank-lines)
46//!
47//! [heading_atx]: crate::construct::heading_atx
48//! [list_item]: crate::construct::list_item
49//! [paragraph]: crate::construct::paragraph
50//! [flow]: crate::construct::flow
51
52use crate::construct::partial_space_or_tab::space_or_tab;
53use crate::state::{Name as StateName, State};
54use crate::tokenizer::Tokenizer;
55
56/// Start of blank line.
57///
58/// > 👉 **Note**: `␠` represents a space character.
59///
60/// ```markdown
61/// > | ␠␠␊
62/// ^
63/// > | ␊
64/// ^
65/// ```
66pub fn start(tokenizer: &mut Tokenizer) -> State {
67 if matches!(tokenizer.current, Some(b'\t' | b' ')) {
68 tokenizer.attempt(State::Next(StateName::BlankLineAfter), State::Nok);
69 State::Retry(space_or_tab(tokenizer))
70 } else {
71 State::Retry(StateName::BlankLineAfter)
72 }
73}
74
75/// At eof/eol, after optional whitespace.
76///
77/// ```markdown
78/// > | ␠␠␊
79/// ^
80/// > | ␊
81/// ^
82/// ```
83pub fn after(tokenizer: &mut Tokenizer) -> State {
84 match tokenizer.current {
85 None | Some(b'\n') => State::Ok,
86 _ => State::Nok,
87 }
88}