diff --git a/crates/biome_markdown_factory/src/generated/node_factory.rs b/crates/biome_markdown_factory/src/generated/node_factory.rs index 64e8684eecc6..a9e24e1b6c8d 100644 --- a/crates/biome_markdown_factory/src/generated/node_factory.rs +++ b/crates/biome_markdown_factory/src/generated/node_factory.rs @@ -641,7 +641,7 @@ where } pub fn md_bullet_list(items: I) -> MdBulletList where - I: IntoIterator, + I: IntoIterator, I::IntoIter: ExactSizeIterator, { MdBulletList::unwrap_cast(SyntaxNode::new_detached( diff --git a/crates/biome_markdown_factory/src/generated/syntax_factory.rs b/crates/biome_markdown_factory/src/generated/syntax_factory.rs index 5241566fe7ab..1dba1842e0ea 100644 --- a/crates/biome_markdown_factory/src/generated/syntax_factory.rs +++ b/crates/biome_markdown_factory/src/generated/syntax_factory.rs @@ -1106,7 +1106,9 @@ impl SyntaxFactory for MarkdownSyntaxFactory { slots.into_node(MD_THEMATIC_BREAK_BLOCK, children) } MD_BLOCK_LIST => Self::make_node_list_syntax(kind, children, AnyMdBlock::can_cast), - MD_BULLET_LIST => Self::make_node_list_syntax(kind, children, MdBullet::can_cast), + MD_BULLET_LIST => { + Self::make_node_list_syntax(kind, children, AnyMdBulletListMember::can_cast) + } MD_CODE_NAME_LIST => Self::make_node_list_syntax(kind, children, MdTextual::can_cast), MD_HASH_LIST => Self::make_node_list_syntax(kind, children, MdHash::can_cast), MD_INDENT_TOKEN_LIST => { diff --git a/crates/biome_markdown_formatter/src/generated.rs b/crates/biome_markdown_formatter/src/generated.rs index 7bbc5019e64a..7a6cd3d02b67 100644 --- a/crates/biome_markdown_formatter/src/generated.rs +++ b/crates/biome_markdown_formatter/src/generated.rs @@ -1679,6 +1679,31 @@ impl IntoFormat for biome_markdown_syntax::AnyMdBlock { ) } } +impl AsFormat for biome_markdown_syntax::AnyMdBulletListMember { + type Format<'a> = FormatRefWithRule< + 'a, + biome_markdown_syntax::AnyMdBulletListMember, + crate::markdown::any::bullet_list_member::FormatAnyMdBulletListMember, + >; + fn format(&self) -> Self::Format<'_> { + FormatRefWithRule::new( + self, + crate::markdown::any::bullet_list_member::FormatAnyMdBulletListMember::default(), + ) + } +} +impl IntoFormat for biome_markdown_syntax::AnyMdBulletListMember { + type Format = FormatOwnedWithRule< + biome_markdown_syntax::AnyMdBulletListMember, + crate::markdown::any::bullet_list_member::FormatAnyMdBulletListMember, + >; + fn into_format(self) -> Self::Format { + FormatOwnedWithRule::new( + self, + crate::markdown::any::bullet_list_member::FormatAnyMdBulletListMember::default(), + ) + } +} impl AsFormat for biome_markdown_syntax::AnyMdCodeBlock { type Format<'a> = FormatRefWithRule< 'a, diff --git a/crates/biome_markdown_formatter/src/markdown/any/bullet_list_member.rs b/crates/biome_markdown_formatter/src/markdown/any/bullet_list_member.rs new file mode 100644 index 000000000000..a28a4c8c2493 --- /dev/null +++ b/crates/biome_markdown_formatter/src/markdown/any/bullet_list_member.rs @@ -0,0 +1,15 @@ +//! This is a generated file. Don't modify it by hand! Run 'cargo codegen formatter' to re-generate the file. + +use crate::prelude::*; +use biome_markdown_syntax::AnyMdBulletListMember; +#[derive(Debug, Clone, Default)] +pub(crate) struct FormatAnyMdBulletListMember; +impl FormatRule for FormatAnyMdBulletListMember { + type Context = MarkdownFormatContext; + fn fmt(&self, node: &AnyMdBulletListMember, f: &mut MarkdownFormatter) -> FormatResult<()> { + match node { + AnyMdBulletListMember::MdBullet(node) => node.format().fmt(f), + AnyMdBulletListMember::MdNewline(node) => node.format().fmt(f), + } + } +} diff --git a/crates/biome_markdown_formatter/src/markdown/any/mod.rs b/crates/biome_markdown_formatter/src/markdown/any/mod.rs index 5a24b1a08ff7..9cd99d0060d0 100644 --- a/crates/biome_markdown_formatter/src/markdown/any/mod.rs +++ b/crates/biome_markdown_formatter/src/markdown/any/mod.rs @@ -1,6 +1,7 @@ //! This is a generated file. Don't modify it by hand! Run 'cargo codegen formatter' to re-generate the file. pub(crate) mod block; +pub(crate) mod bullet_list_member; pub(crate) mod code_block; pub(crate) mod container_block; pub(crate) mod inline; diff --git a/crates/biome_markdown_parser/src/syntax/list.rs b/crates/biome_markdown_parser/src/syntax/list.rs index a8cd03674d2f..1b836697a654 100644 --- a/crates/biome_markdown_parser/src/syntax/list.rs +++ b/crates/biome_markdown_parser/src/syntax/list.rs @@ -331,8 +331,10 @@ fn skip_blank_lines_between_items( // Blank lines between items make the list loose *is_tight = false; *last_item_ends_with_blank = true; - // Skip the blank line as trivia (no tree node created) - p.parse_as_skipped_trivia_tokens(|p| p.bump(NEWLINE)); + // Emit blank line as an explicit MdNewline CST node + let newline_m = p.start(); + p.bump(NEWLINE); + newline_m.complete(p, MD_NEWLINE); } } diff --git a/crates/biome_markdown_parser/src/syntax/mod.rs b/crates/biome_markdown_parser/src/syntax/mod.rs index ecf8a1487aa9..251f159a1de0 100644 --- a/crates/biome_markdown_parser/src/syntax/mod.rs +++ b/crates/biome_markdown_parser/src/syntax/mod.rs @@ -1161,6 +1161,7 @@ fn set_inline_emphasis_context(p: &mut MarkdownParser) -> Option usize { p.lookahead(|p| { let mut len = 0usize; + let mut has_content = false; loop { if p.at(T![EOF]) { @@ -1186,11 +1187,19 @@ fn inline_list_source_len(p: &mut MarkdownParser) -> usize { consume_quote_prefix_without_virtual(p, quote_depth); } + if has_content && p.at(MD_SETEXT_UNDERLINE_LITERAL) && allow_setext_heading(p) { + break; + } + + if has_content && p.at(MD_THEMATIC_BREAK_LITERAL) && is_dash_only_thematic_break(p) + { + break; + } if quote_depth > 0 && p.at(R_ANGLE) && !has_quote_prefix(p, quote_depth) { consume_partial_quote_prefix_lookahead(p, quote_depth, &mut len); } - if at_paragraph_break(p, true) { + if at_paragraph_break(p, has_content) { break; } @@ -1228,9 +1237,10 @@ fn inline_list_source_len(p: &mut MarkdownParser) -> usize { // We intentionally skip the heavier post-indent block-interrupt // check here; the following non-NEWLINE pass still catches // interrupts for emphasis-context length calculation. - if p.at(MD_SETEXT_UNDERLINE_LITERAL) - || (p.at(MD_THEMATIC_BREAK_LITERAL) - && is_dash_only_thematic_break_text(p.cur_text())) + if has_content + && (p.at(MD_SETEXT_UNDERLINE_LITERAL) + || (p.at(MD_THEMATIC_BREAK_LITERAL) + && is_dash_only_thematic_break_text(p.cur_text()))) { break; } @@ -1239,11 +1249,11 @@ fn inline_list_source_len(p: &mut MarkdownParser) -> usize { continue; } - if p.at(MD_SETEXT_UNDERLINE_LITERAL) && allow_setext_heading(p) { + if has_content && p.at(MD_SETEXT_UNDERLINE_LITERAL) && allow_setext_heading(p) { break; } - if p.at(MD_THEMATIC_BREAK_LITERAL) && is_dash_only_thematic_break(p) { + if has_content && p.at(MD_THEMATIC_BREAK_LITERAL) && is_dash_only_thematic_break(p) { break; } @@ -1251,6 +1261,10 @@ fn inline_list_source_len(p: &mut MarkdownParser) -> usize { break; } + if !p.cur_text().chars().all(|c| c == ' ' || c == '\t') { + has_content = true; + } + len += p.cur_text().len(); p.bump(p.cur()); } diff --git a/crates/biome_markdown_parser/src/to_html.rs b/crates/biome_markdown_parser/src/to_html.rs index 322c81279edf..981cc0c3e5e4 100644 --- a/crates/biome_markdown_parser/src/to_html.rs +++ b/crates/biome_markdown_parser/src/to_html.rs @@ -43,13 +43,13 @@ //! be decided with full context. use biome_markdown_syntax::{ - AnyMdBlock, AnyMdCodeBlock, AnyMdInline, AnyMdLeafBlock, MarkdownLanguage, MdAutolink, - MdBlockList, MdBullet, MdBulletListItem, MdDocument, MdEntityReference, MdFencedCodeBlock, - MdHardLine, MdHeader, MdHtmlBlock, MdIndentCodeBlock, MdInlineCode, MdInlineEmphasis, - MdInlineHtml, MdInlineImage, MdInlineItalic, MdInlineItemList, MdInlineLink, MdLinkBlock, - MdLinkDestination, MdLinkLabel, MdLinkReferenceDefinition, MdLinkTitle, MdOrderedListItem, - MdParagraph, MdQuote, MdReferenceImage, MdReferenceLink, MdReferenceLinkLabel, MdSetextHeader, - MdSoftBreak, MdTextual, MdThematicBreakBlock, + AnyMdBlock, AnyMdBulletListMember, AnyMdCodeBlock, AnyMdInline, AnyMdLeafBlock, + MarkdownLanguage, MdAutolink, MdBlockList, MdBullet, MdBulletListItem, MdDocument, + MdEntityReference, MdFencedCodeBlock, MdHardLine, MdHeader, MdHtmlBlock, MdIndentCodeBlock, + MdInlineCode, MdInlineEmphasis, MdInlineHtml, MdInlineImage, MdInlineItalic, MdInlineItemList, + MdInlineLink, MdLinkBlock, MdLinkDestination, MdLinkLabel, MdLinkReferenceDefinition, + MdLinkTitle, MdOrderedListItem, MdParagraph, MdQuote, MdReferenceImage, MdReferenceLink, + MdReferenceLinkLabel, MdSetextHeader, MdSoftBreak, MdTextual, MdThematicBreakBlock, }; use biome_rowan::{AstNode, AstNodeList, Direction, SyntaxNode, TextRange, WalkEvent}; use percent_encoding::{AsciiSet, CONTROLS, utf8_percent_encode}; @@ -565,7 +565,11 @@ impl<'a> HtmlRenderer<'a> { let start = list .md_bullet_list() - .first() + .iter() + .find_map(|member| match member { + AnyMdBulletListMember::MdBullet(bullet) => Some(bullet), + _ => None, + }) .and_then(|bullet| bullet.prefix().ok()) .and_then(|prefix| prefix.marker().ok()) .map_or(1, |marker| { diff --git a/crates/biome_markdown_parser/tests/md_test_suite/ok/list_blank_lines_between_items.md b/crates/biome_markdown_parser/tests/md_test_suite/ok/list_blank_lines_between_items.md new file mode 100644 index 000000000000..017d6469aac4 --- /dev/null +++ b/crates/biome_markdown_parser/tests/md_test_suite/ok/list_blank_lines_between_items.md @@ -0,0 +1,29 @@ +# Blank lines between bullet items + +- foo + +- bar + +- baz + +# Blank lines between ordered items + +1. first + +2. second + +3. third + +# Multiple blank lines between items + +- alpha + + +- beta + +# Mixed: some items separated, some not + +- one +- two + +- three diff --git a/crates/biome_markdown_parser/tests/md_test_suite/ok/list_blank_lines_between_items.md.snap b/crates/biome_markdown_parser/tests/md_test_suite/ok/list_blank_lines_between_items.md.snap new file mode 100644 index 000000000000..ffae40651a3c --- /dev/null +++ b/crates/biome_markdown_parser/tests/md_test_suite/ok/list_blank_lines_between_items.md.snap @@ -0,0 +1,664 @@ +--- +source: crates/biome_markdown_parser/tests/spec_test.rs +expression: snapshot +--- + +## Input + +``` +# Blank lines between bullet items + +- foo + +- bar + +- baz + +# Blank lines between ordered items + +1. first + +2. second + +3. third + +# Multiple blank lines between items + +- alpha + + +- beta + +# Mixed: some items separated, some not + +- one +- two + +- three + +``` + + +## AST + +``` +MdDocument { + bom_token: missing (optional), + value: MdBlockList [ + MdHeader { + before: MdHashList [ + MdHash { + hash_token: HASH@0..1 "#" [] [], + }, + ], + content: MdParagraph { + list: MdInlineItemList [ + MdTextual { + value_token: MD_TEXTUAL_LITERAL@1..34 " Blank lines between bullet items" [] [], + }, + ], + hard_line: missing (optional), + }, + after: MdHashList [], + }, + MdNewline { + value_token: NEWLINE@34..35 "\n" [] [], + }, + MdNewline { + value_token: NEWLINE@35..36 "\n" [] [], + }, + MdBulletListItem { + md_bullet_list: MdBulletList [ + MdBullet { + prefix: MdListMarkerPrefix { + pre_marker_indent: MdIndentTokenList [], + marker: MINUS@36..37 "-" [] [], + post_marker_space_token: missing (optional), + content_indent: MdIndentTokenList [], + }, + content: MdBlockList [ + MdParagraph { + list: MdInlineItemList [ + MdTextual { + value_token: MD_TEXTUAL_LITERAL@37..41 " foo" [] [], + }, + MdTextual { + value_token: MD_TEXTUAL_LITERAL@41..42 "\n" [] [], + }, + ], + hard_line: missing (optional), + }, + MdNewline { + value_token: NEWLINE@42..43 "\n" [] [], + }, + ], + }, + MdBullet { + prefix: MdListMarkerPrefix { + pre_marker_indent: MdIndentTokenList [], + marker: MINUS@43..44 "-" [] [], + post_marker_space_token: missing (optional), + content_indent: MdIndentTokenList [], + }, + content: MdBlockList [ + MdParagraph { + list: MdInlineItemList [ + MdTextual { + value_token: MD_TEXTUAL_LITERAL@44..48 " bar" [] [], + }, + MdTextual { + value_token: MD_TEXTUAL_LITERAL@48..49 "\n" [] [], + }, + ], + hard_line: missing (optional), + }, + MdNewline { + value_token: NEWLINE@49..50 "\n" [] [], + }, + ], + }, + MdBullet { + prefix: MdListMarkerPrefix { + pre_marker_indent: MdIndentTokenList [], + marker: MINUS@50..51 "-" [] [], + post_marker_space_token: missing (optional), + content_indent: MdIndentTokenList [], + }, + content: MdBlockList [ + MdParagraph { + list: MdInlineItemList [ + MdTextual { + value_token: MD_TEXTUAL_LITERAL@51..55 " baz" [] [], + }, + MdTextual { + value_token: MD_TEXTUAL_LITERAL@55..56 "\n" [] [], + }, + ], + hard_line: missing (optional), + }, + ], + }, + ], + }, + MdNewline { + value_token: NEWLINE@56..57 "\n" [] [], + }, + MdHeader { + before: MdHashList [ + MdHash { + hash_token: HASH@57..58 "#" [] [], + }, + ], + content: MdParagraph { + list: MdInlineItemList [ + MdTextual { + value_token: MD_TEXTUAL_LITERAL@58..92 " Blank lines between ordered items" [] [], + }, + ], + hard_line: missing (optional), + }, + after: MdHashList [], + }, + MdNewline { + value_token: NEWLINE@92..93 "\n" [] [], + }, + MdNewline { + value_token: NEWLINE@93..94 "\n" [] [], + }, + MdOrderedListItem { + md_bullet_list: MdBulletList [ + MdBullet { + prefix: MdListMarkerPrefix { + pre_marker_indent: MdIndentTokenList [], + marker: MD_ORDERED_LIST_MARKER@94..96 "1." [] [], + post_marker_space_token: missing (optional), + content_indent: MdIndentTokenList [], + }, + content: MdBlockList [ + MdParagraph { + list: MdInlineItemList [ + MdTextual { + value_token: MD_TEXTUAL_LITERAL@96..102 " first" [] [], + }, + MdTextual { + value_token: MD_TEXTUAL_LITERAL@102..103 "\n" [] [], + }, + ], + hard_line: missing (optional), + }, + MdNewline { + value_token: NEWLINE@103..104 "\n" [] [], + }, + ], + }, + MdBullet { + prefix: MdListMarkerPrefix { + pre_marker_indent: MdIndentTokenList [], + marker: MD_ORDERED_LIST_MARKER@104..106 "2." [] [], + post_marker_space_token: missing (optional), + content_indent: MdIndentTokenList [], + }, + content: MdBlockList [ + MdParagraph { + list: MdInlineItemList [ + MdTextual { + value_token: MD_TEXTUAL_LITERAL@106..113 " second" [] [], + }, + MdTextual { + value_token: MD_TEXTUAL_LITERAL@113..114 "\n" [] [], + }, + ], + hard_line: missing (optional), + }, + MdNewline { + value_token: NEWLINE@114..115 "\n" [] [], + }, + ], + }, + MdBullet { + prefix: MdListMarkerPrefix { + pre_marker_indent: MdIndentTokenList [], + marker: MD_ORDERED_LIST_MARKER@115..117 "3." [] [], + post_marker_space_token: missing (optional), + content_indent: MdIndentTokenList [], + }, + content: MdBlockList [ + MdParagraph { + list: MdInlineItemList [ + MdTextual { + value_token: MD_TEXTUAL_LITERAL@117..123 " third" [] [], + }, + MdTextual { + value_token: MD_TEXTUAL_LITERAL@123..124 "\n" [] [], + }, + ], + hard_line: missing (optional), + }, + ], + }, + ], + }, + MdNewline { + value_token: NEWLINE@124..125 "\n" [] [], + }, + MdHeader { + before: MdHashList [ + MdHash { + hash_token: HASH@125..126 "#" [] [], + }, + ], + content: MdParagraph { + list: MdInlineItemList [ + MdTextual { + value_token: MD_TEXTUAL_LITERAL@126..161 " Multiple blank lines between items" [] [], + }, + ], + hard_line: missing (optional), + }, + after: MdHashList [], + }, + MdNewline { + value_token: NEWLINE@161..162 "\n" [] [], + }, + MdNewline { + value_token: NEWLINE@162..163 "\n" [] [], + }, + MdBulletListItem { + md_bullet_list: MdBulletList [ + MdBullet { + prefix: MdListMarkerPrefix { + pre_marker_indent: MdIndentTokenList [], + marker: MINUS@163..164 "-" [] [], + post_marker_space_token: missing (optional), + content_indent: MdIndentTokenList [], + }, + content: MdBlockList [ + MdParagraph { + list: MdInlineItemList [ + MdTextual { + value_token: MD_TEXTUAL_LITERAL@164..170 " alpha" [] [], + }, + MdTextual { + value_token: MD_TEXTUAL_LITERAL@170..171 "\n" [] [], + }, + ], + hard_line: missing (optional), + }, + MdNewline { + value_token: NEWLINE@171..172 "\n" [] [], + }, + ], + }, + MdNewline { + value_token: NEWLINE@172..173 "\n" [] [], + }, + MdBullet { + prefix: MdListMarkerPrefix { + pre_marker_indent: MdIndentTokenList [], + marker: MINUS@173..174 "-" [] [], + post_marker_space_token: missing (optional), + content_indent: MdIndentTokenList [], + }, + content: MdBlockList [ + MdParagraph { + list: MdInlineItemList [ + MdTextual { + value_token: MD_TEXTUAL_LITERAL@174..179 " beta" [] [], + }, + MdTextual { + value_token: MD_TEXTUAL_LITERAL@179..180 "\n" [] [], + }, + ], + hard_line: missing (optional), + }, + ], + }, + ], + }, + MdNewline { + value_token: NEWLINE@180..181 "\n" [] [], + }, + MdHeader { + before: MdHashList [ + MdHash { + hash_token: HASH@181..182 "#" [] [], + }, + ], + content: MdParagraph { + list: MdInlineItemList [ + MdTextual { + value_token: MD_TEXTUAL_LITERAL@182..220 " Mixed: some items separated, some not" [] [], + }, + ], + hard_line: missing (optional), + }, + after: MdHashList [], + }, + MdNewline { + value_token: NEWLINE@220..221 "\n" [] [], + }, + MdNewline { + value_token: NEWLINE@221..222 "\n" [] [], + }, + MdBulletListItem { + md_bullet_list: MdBulletList [ + MdBullet { + prefix: MdListMarkerPrefix { + pre_marker_indent: MdIndentTokenList [], + marker: MINUS@222..223 "-" [] [], + post_marker_space_token: missing (optional), + content_indent: MdIndentTokenList [], + }, + content: MdBlockList [ + MdParagraph { + list: MdInlineItemList [ + MdTextual { + value_token: MD_TEXTUAL_LITERAL@223..227 " one" [] [], + }, + MdTextual { + value_token: MD_TEXTUAL_LITERAL@227..228 "\n" [] [], + }, + ], + hard_line: missing (optional), + }, + ], + }, + MdBullet { + prefix: MdListMarkerPrefix { + pre_marker_indent: MdIndentTokenList [], + marker: MINUS@228..229 "-" [] [], + post_marker_space_token: missing (optional), + content_indent: MdIndentTokenList [], + }, + content: MdBlockList [ + MdParagraph { + list: MdInlineItemList [ + MdTextual { + value_token: MD_TEXTUAL_LITERAL@229..233 " two" [] [], + }, + MdTextual { + value_token: MD_TEXTUAL_LITERAL@233..234 "\n" [] [], + }, + ], + hard_line: missing (optional), + }, + MdNewline { + value_token: NEWLINE@234..235 "\n" [] [], + }, + ], + }, + MdBullet { + prefix: MdListMarkerPrefix { + pre_marker_indent: MdIndentTokenList [], + marker: MINUS@235..236 "-" [] [], + post_marker_space_token: missing (optional), + content_indent: MdIndentTokenList [], + }, + content: MdBlockList [ + MdParagraph { + list: MdInlineItemList [ + MdTextual { + value_token: MD_TEXTUAL_LITERAL@236..242 " three" [] [], + }, + MdTextual { + value_token: MD_TEXTUAL_LITERAL@242..243 "\n" [] [], + }, + ], + hard_line: missing (optional), + }, + ], + }, + ], + }, + ], + eof_token: EOF@243..243 "" [] [], +} +``` + +## CST + +``` +0: MD_DOCUMENT@0..243 + 0: (empty) + 1: MD_BLOCK_LIST@0..243 + 0: MD_HEADER@0..34 + 0: MD_HASH_LIST@0..1 + 0: MD_HASH@0..1 + 0: HASH@0..1 "#" [] [] + 1: MD_PARAGRAPH@1..34 + 0: MD_INLINE_ITEM_LIST@1..34 + 0: MD_TEXTUAL@1..34 + 0: MD_TEXTUAL_LITERAL@1..34 " Blank lines between bullet items" [] [] + 1: (empty) + 2: MD_HASH_LIST@34..34 + 1: MD_NEWLINE@34..35 + 0: NEWLINE@34..35 "\n" [] [] + 2: MD_NEWLINE@35..36 + 0: NEWLINE@35..36 "\n" [] [] + 3: MD_BULLET_LIST_ITEM@36..56 + 0: MD_BULLET_LIST@36..56 + 0: MD_BULLET@36..43 + 0: MD_LIST_MARKER_PREFIX@36..37 + 0: MD_INDENT_TOKEN_LIST@36..36 + 1: MINUS@36..37 "-" [] [] + 2: (empty) + 3: MD_INDENT_TOKEN_LIST@37..37 + 1: MD_BLOCK_LIST@37..43 + 0: MD_PARAGRAPH@37..42 + 0: MD_INLINE_ITEM_LIST@37..42 + 0: MD_TEXTUAL@37..41 + 0: MD_TEXTUAL_LITERAL@37..41 " foo" [] [] + 1: MD_TEXTUAL@41..42 + 0: MD_TEXTUAL_LITERAL@41..42 "\n" [] [] + 1: (empty) + 1: MD_NEWLINE@42..43 + 0: NEWLINE@42..43 "\n" [] [] + 1: MD_BULLET@43..50 + 0: MD_LIST_MARKER_PREFIX@43..44 + 0: MD_INDENT_TOKEN_LIST@43..43 + 1: MINUS@43..44 "-" [] [] + 2: (empty) + 3: MD_INDENT_TOKEN_LIST@44..44 + 1: MD_BLOCK_LIST@44..50 + 0: MD_PARAGRAPH@44..49 + 0: MD_INLINE_ITEM_LIST@44..49 + 0: MD_TEXTUAL@44..48 + 0: MD_TEXTUAL_LITERAL@44..48 " bar" [] [] + 1: MD_TEXTUAL@48..49 + 0: MD_TEXTUAL_LITERAL@48..49 "\n" [] [] + 1: (empty) + 1: MD_NEWLINE@49..50 + 0: NEWLINE@49..50 "\n" [] [] + 2: MD_BULLET@50..56 + 0: MD_LIST_MARKER_PREFIX@50..51 + 0: MD_INDENT_TOKEN_LIST@50..50 + 1: MINUS@50..51 "-" [] [] + 2: (empty) + 3: MD_INDENT_TOKEN_LIST@51..51 + 1: MD_BLOCK_LIST@51..56 + 0: MD_PARAGRAPH@51..56 + 0: MD_INLINE_ITEM_LIST@51..56 + 0: MD_TEXTUAL@51..55 + 0: MD_TEXTUAL_LITERAL@51..55 " baz" [] [] + 1: MD_TEXTUAL@55..56 + 0: MD_TEXTUAL_LITERAL@55..56 "\n" [] [] + 1: (empty) + 4: MD_NEWLINE@56..57 + 0: NEWLINE@56..57 "\n" [] [] + 5: MD_HEADER@57..92 + 0: MD_HASH_LIST@57..58 + 0: MD_HASH@57..58 + 0: HASH@57..58 "#" [] [] + 1: MD_PARAGRAPH@58..92 + 0: MD_INLINE_ITEM_LIST@58..92 + 0: MD_TEXTUAL@58..92 + 0: MD_TEXTUAL_LITERAL@58..92 " Blank lines between ordered items" [] [] + 1: (empty) + 2: MD_HASH_LIST@92..92 + 6: MD_NEWLINE@92..93 + 0: NEWLINE@92..93 "\n" [] [] + 7: MD_NEWLINE@93..94 + 0: NEWLINE@93..94 "\n" [] [] + 8: MD_ORDERED_LIST_ITEM@94..124 + 0: MD_BULLET_LIST@94..124 + 0: MD_BULLET@94..104 + 0: MD_LIST_MARKER_PREFIX@94..96 + 0: MD_INDENT_TOKEN_LIST@94..94 + 1: MD_ORDERED_LIST_MARKER@94..96 "1." [] [] + 2: (empty) + 3: MD_INDENT_TOKEN_LIST@96..96 + 1: MD_BLOCK_LIST@96..104 + 0: MD_PARAGRAPH@96..103 + 0: MD_INLINE_ITEM_LIST@96..103 + 0: MD_TEXTUAL@96..102 + 0: MD_TEXTUAL_LITERAL@96..102 " first" [] [] + 1: MD_TEXTUAL@102..103 + 0: MD_TEXTUAL_LITERAL@102..103 "\n" [] [] + 1: (empty) + 1: MD_NEWLINE@103..104 + 0: NEWLINE@103..104 "\n" [] [] + 1: MD_BULLET@104..115 + 0: MD_LIST_MARKER_PREFIX@104..106 + 0: MD_INDENT_TOKEN_LIST@104..104 + 1: MD_ORDERED_LIST_MARKER@104..106 "2." [] [] + 2: (empty) + 3: MD_INDENT_TOKEN_LIST@106..106 + 1: MD_BLOCK_LIST@106..115 + 0: MD_PARAGRAPH@106..114 + 0: MD_INLINE_ITEM_LIST@106..114 + 0: MD_TEXTUAL@106..113 + 0: MD_TEXTUAL_LITERAL@106..113 " second" [] [] + 1: MD_TEXTUAL@113..114 + 0: MD_TEXTUAL_LITERAL@113..114 "\n" [] [] + 1: (empty) + 1: MD_NEWLINE@114..115 + 0: NEWLINE@114..115 "\n" [] [] + 2: MD_BULLET@115..124 + 0: MD_LIST_MARKER_PREFIX@115..117 + 0: MD_INDENT_TOKEN_LIST@115..115 + 1: MD_ORDERED_LIST_MARKER@115..117 "3." [] [] + 2: (empty) + 3: MD_INDENT_TOKEN_LIST@117..117 + 1: MD_BLOCK_LIST@117..124 + 0: MD_PARAGRAPH@117..124 + 0: MD_INLINE_ITEM_LIST@117..124 + 0: MD_TEXTUAL@117..123 + 0: MD_TEXTUAL_LITERAL@117..123 " third" [] [] + 1: MD_TEXTUAL@123..124 + 0: MD_TEXTUAL_LITERAL@123..124 "\n" [] [] + 1: (empty) + 9: MD_NEWLINE@124..125 + 0: NEWLINE@124..125 "\n" [] [] + 10: MD_HEADER@125..161 + 0: MD_HASH_LIST@125..126 + 0: MD_HASH@125..126 + 0: HASH@125..126 "#" [] [] + 1: MD_PARAGRAPH@126..161 + 0: MD_INLINE_ITEM_LIST@126..161 + 0: MD_TEXTUAL@126..161 + 0: MD_TEXTUAL_LITERAL@126..161 " Multiple blank lines between items" [] [] + 1: (empty) + 2: MD_HASH_LIST@161..161 + 11: MD_NEWLINE@161..162 + 0: NEWLINE@161..162 "\n" [] [] + 12: MD_NEWLINE@162..163 + 0: NEWLINE@162..163 "\n" [] [] + 13: MD_BULLET_LIST_ITEM@163..180 + 0: MD_BULLET_LIST@163..180 + 0: MD_BULLET@163..172 + 0: MD_LIST_MARKER_PREFIX@163..164 + 0: MD_INDENT_TOKEN_LIST@163..163 + 1: MINUS@163..164 "-" [] [] + 2: (empty) + 3: MD_INDENT_TOKEN_LIST@164..164 + 1: MD_BLOCK_LIST@164..172 + 0: MD_PARAGRAPH@164..171 + 0: MD_INLINE_ITEM_LIST@164..171 + 0: MD_TEXTUAL@164..170 + 0: MD_TEXTUAL_LITERAL@164..170 " alpha" [] [] + 1: MD_TEXTUAL@170..171 + 0: MD_TEXTUAL_LITERAL@170..171 "\n" [] [] + 1: (empty) + 1: MD_NEWLINE@171..172 + 0: NEWLINE@171..172 "\n" [] [] + 1: MD_NEWLINE@172..173 + 0: NEWLINE@172..173 "\n" [] [] + 2: MD_BULLET@173..180 + 0: MD_LIST_MARKER_PREFIX@173..174 + 0: MD_INDENT_TOKEN_LIST@173..173 + 1: MINUS@173..174 "-" [] [] + 2: (empty) + 3: MD_INDENT_TOKEN_LIST@174..174 + 1: MD_BLOCK_LIST@174..180 + 0: MD_PARAGRAPH@174..180 + 0: MD_INLINE_ITEM_LIST@174..180 + 0: MD_TEXTUAL@174..179 + 0: MD_TEXTUAL_LITERAL@174..179 " beta" [] [] + 1: MD_TEXTUAL@179..180 + 0: MD_TEXTUAL_LITERAL@179..180 "\n" [] [] + 1: (empty) + 14: MD_NEWLINE@180..181 + 0: NEWLINE@180..181 "\n" [] [] + 15: MD_HEADER@181..220 + 0: MD_HASH_LIST@181..182 + 0: MD_HASH@181..182 + 0: HASH@181..182 "#" [] [] + 1: MD_PARAGRAPH@182..220 + 0: MD_INLINE_ITEM_LIST@182..220 + 0: MD_TEXTUAL@182..220 + 0: MD_TEXTUAL_LITERAL@182..220 " Mixed: some items separated, some not" [] [] + 1: (empty) + 2: MD_HASH_LIST@220..220 + 16: MD_NEWLINE@220..221 + 0: NEWLINE@220..221 "\n" [] [] + 17: MD_NEWLINE@221..222 + 0: NEWLINE@221..222 "\n" [] [] + 18: MD_BULLET_LIST_ITEM@222..243 + 0: MD_BULLET_LIST@222..243 + 0: MD_BULLET@222..228 + 0: MD_LIST_MARKER_PREFIX@222..223 + 0: MD_INDENT_TOKEN_LIST@222..222 + 1: MINUS@222..223 "-" [] [] + 2: (empty) + 3: MD_INDENT_TOKEN_LIST@223..223 + 1: MD_BLOCK_LIST@223..228 + 0: MD_PARAGRAPH@223..228 + 0: MD_INLINE_ITEM_LIST@223..228 + 0: MD_TEXTUAL@223..227 + 0: MD_TEXTUAL_LITERAL@223..227 " one" [] [] + 1: MD_TEXTUAL@227..228 + 0: MD_TEXTUAL_LITERAL@227..228 "\n" [] [] + 1: (empty) + 1: MD_BULLET@228..235 + 0: MD_LIST_MARKER_PREFIX@228..229 + 0: MD_INDENT_TOKEN_LIST@228..228 + 1: MINUS@228..229 "-" [] [] + 2: (empty) + 3: MD_INDENT_TOKEN_LIST@229..229 + 1: MD_BLOCK_LIST@229..235 + 0: MD_PARAGRAPH@229..234 + 0: MD_INLINE_ITEM_LIST@229..234 + 0: MD_TEXTUAL@229..233 + 0: MD_TEXTUAL_LITERAL@229..233 " two" [] [] + 1: MD_TEXTUAL@233..234 + 0: MD_TEXTUAL_LITERAL@233..234 "\n" [] [] + 1: (empty) + 1: MD_NEWLINE@234..235 + 0: NEWLINE@234..235 "\n" [] [] + 2: MD_BULLET@235..243 + 0: MD_LIST_MARKER_PREFIX@235..236 + 0: MD_INDENT_TOKEN_LIST@235..235 + 1: MINUS@235..236 "-" [] [] + 2: (empty) + 3: MD_INDENT_TOKEN_LIST@236..236 + 1: MD_BLOCK_LIST@236..243 + 0: MD_PARAGRAPH@236..243 + 0: MD_INLINE_ITEM_LIST@236..243 + 0: MD_TEXTUAL@236..242 + 0: MD_TEXTUAL_LITERAL@236..242 " three" [] [] + 1: MD_TEXTUAL@242..243 + 0: MD_TEXTUAL_LITERAL@242..243 "\n" [] [] + 1: (empty) + 2: EOF@243..243 "" [] [] + +``` diff --git a/crates/biome_markdown_parser/tests/md_test_suite/ok/quote_textual_marker_parity.md.snap b/crates/biome_markdown_parser/tests/md_test_suite/ok/quote_textual_marker_parity.md.snap index 2fea026b5b26..14011ab191af 100644 --- a/crates/biome_markdown_parser/tests/md_test_suite/ok/quote_textual_marker_parity.md.snap +++ b/crates/biome_markdown_parser/tests/md_test_suite/ok/quote_textual_marker_parity.md.snap @@ -1,6 +1,5 @@ --- source: crates/biome_markdown_parser/tests/spec_test.rs -assertion_line: 131 expression: snapshot --- @@ -26,12 +25,16 @@ MdDocument { bom_token: missing (optional), value: MdBlockList [ MdQuote { - marker_token: R_ANGLE@0..1 ">" [] [], + prefix: MdQuotePrefix { + pre_marker_indent: MdQuoteIndentList [], + marker_token: R_ANGLE@0..1 ">" [] [], + post_marker_space_token: MD_QUOTE_POST_MARKER_SPACE@1..2 " " [] [], + }, content: MdBlockList [ MdParagraph { list: MdInlineItemList [ MdTextual { - value_token: MD_TEXTUAL_LITERAL@1..16 "paragraph line" [Skipped(" ")] [], + value_token: MD_TEXTUAL_LITERAL@2..16 "paragraph line" [] [], }, MdTextual { value_token: MD_TEXTUAL_LITERAL@16..17 "\n" [] [], @@ -39,10 +42,20 @@ MdDocument { ], hard_line: missing (optional), }, + MdQuotePrefix { + pre_marker_indent: MdQuoteIndentList [], + marker_token: R_ANGLE@17..18 ">" [] [], + post_marker_space_token: MD_QUOTE_POST_MARKER_SPACE@18..19 " " [] [], + }, MdBulletListItem { md_bullet_list: MdBulletList [ MdBullet { - bullet: MINUS@17..20 "-" [Skipped(">"), Skipped(" ")] [], + prefix: MdListMarkerPrefix { + pre_marker_indent: MdIndentTokenList [], + marker: MINUS@19..20 "-" [] [], + post_marker_space_token: missing (optional), + content_indent: MdIndentTokenList [], + }, content: MdBlockList [ MdParagraph { list: MdInlineItemList [ @@ -65,12 +78,16 @@ MdDocument { value_token: NEWLINE@35..36 "\n" [] [], }, MdQuote { - marker_token: R_ANGLE@36..37 ">" [] [], + prefix: MdQuotePrefix { + pre_marker_indent: MdQuoteIndentList [], + marker_token: R_ANGLE@36..37 ">" [] [], + post_marker_space_token: MD_QUOTE_POST_MARKER_SPACE@37..38 " " [] [], + }, content: MdBlockList [ MdParagraph { list: MdInlineItemList [ MdTextual { - value_token: MD_TEXTUAL_LITERAL@37..52 "paragraph line" [Skipped(" ")] [], + value_token: MD_TEXTUAL_LITERAL@38..52 "paragraph line" [] [], }, MdTextual { value_token: MD_TEXTUAL_LITERAL@52..53 "\n" [] [], @@ -78,10 +95,20 @@ MdDocument { ], hard_line: missing (optional), }, + MdQuotePrefix { + pre_marker_indent: MdQuoteIndentList [], + marker_token: R_ANGLE@53..54 ">" [] [], + post_marker_space_token: MD_QUOTE_POST_MARKER_SPACE@54..55 " " [] [], + }, MdOrderedListItem { md_bullet_list: MdBulletList [ MdBullet { - bullet: MD_ORDERED_LIST_MARKER@53..57 "1." [Skipped(">"), Skipped(" ")] [], + prefix: MdListMarkerPrefix { + pre_marker_indent: MdIndentTokenList [], + marker: MD_ORDERED_LIST_MARKER@55..57 "1." [] [], + post_marker_space_token: missing (optional), + content_indent: MdIndentTokenList [], + }, content: MdBlockList [ MdParagraph { list: MdInlineItemList [ @@ -104,18 +131,27 @@ MdDocument { value_token: NEWLINE@73..74 "\n" [] [], }, MdQuote { - marker_token: R_ANGLE@74..75 ">" [] [], + prefix: MdQuotePrefix { + pre_marker_indent: MdQuoteIndentList [], + marker_token: R_ANGLE@74..75 ">" [] [], + post_marker_space_token: MD_QUOTE_POST_MARKER_SPACE@75..76 " " [] [], + }, content: MdBlockList [ MdParagraph { list: MdInlineItemList [ MdTextual { - value_token: MD_TEXTUAL_LITERAL@75..90 "paragraph line" [Skipped(" ")] [], + value_token: MD_TEXTUAL_LITERAL@76..90 "paragraph line" [] [], }, MdTextual { value_token: MD_TEXTUAL_LITERAL@90..91 "\n" [] [], }, + MdQuotePrefix { + pre_marker_indent: MdQuoteIndentList [], + marker_token: R_ANGLE@91..92 ">" [] [], + post_marker_space_token: MD_QUOTE_POST_MARKER_SPACE@92..93 " " [] [], + }, MdTextual { - value_token: MD_TEXTUAL_LITERAL@91..108 "still paragraph" [Skipped(">"), Skipped(" ")] [], + value_token: MD_TEXTUAL_LITERAL@93..108 "still paragraph" [] [], }, MdTextual { value_token: MD_TEXTUAL_LITERAL@108..109 "\n" [] [], @@ -137,19 +173,30 @@ MdDocument { 0: (empty) 1: MD_BLOCK_LIST@0..109 0: MD_QUOTE@0..35 - 0: R_ANGLE@0..1 ">" [] [] - 1: MD_BLOCK_LIST@1..35 - 0: MD_PARAGRAPH@1..17 - 0: MD_INLINE_ITEM_LIST@1..17 - 0: MD_TEXTUAL@1..16 - 0: MD_TEXTUAL_LITERAL@1..16 "paragraph line" [Skipped(" ")] [] + 0: MD_QUOTE_PREFIX@0..2 + 0: MD_QUOTE_INDENT_LIST@0..0 + 1: R_ANGLE@0..1 ">" [] [] + 2: MD_QUOTE_POST_MARKER_SPACE@1..2 " " [] [] + 1: MD_BLOCK_LIST@2..35 + 0: MD_PARAGRAPH@2..17 + 0: MD_INLINE_ITEM_LIST@2..17 + 0: MD_TEXTUAL@2..16 + 0: MD_TEXTUAL_LITERAL@2..16 "paragraph line" [] [] 1: MD_TEXTUAL@16..17 0: MD_TEXTUAL_LITERAL@16..17 "\n" [] [] 1: (empty) - 1: MD_BULLET_LIST_ITEM@17..35 - 0: MD_BULLET_LIST@17..35 - 0: MD_BULLET@17..35 - 0: MINUS@17..20 "-" [Skipped(">"), Skipped(" ")] [] + 1: MD_QUOTE_PREFIX@17..19 + 0: MD_QUOTE_INDENT_LIST@17..17 + 1: R_ANGLE@17..18 ">" [] [] + 2: MD_QUOTE_POST_MARKER_SPACE@18..19 " " [] [] + 2: MD_BULLET_LIST_ITEM@19..35 + 0: MD_BULLET_LIST@19..35 + 0: MD_BULLET@19..35 + 0: MD_LIST_MARKER_PREFIX@19..20 + 0: MD_INDENT_TOKEN_LIST@19..19 + 1: MINUS@19..20 "-" [] [] + 2: (empty) + 3: MD_INDENT_TOKEN_LIST@20..20 1: MD_BLOCK_LIST@20..35 0: MD_PARAGRAPH@20..35 0: MD_INLINE_ITEM_LIST@20..35 @@ -161,19 +208,30 @@ MdDocument { 1: MD_NEWLINE@35..36 0: NEWLINE@35..36 "\n" [] [] 2: MD_QUOTE@36..73 - 0: R_ANGLE@36..37 ">" [] [] - 1: MD_BLOCK_LIST@37..73 - 0: MD_PARAGRAPH@37..53 - 0: MD_INLINE_ITEM_LIST@37..53 - 0: MD_TEXTUAL@37..52 - 0: MD_TEXTUAL_LITERAL@37..52 "paragraph line" [Skipped(" ")] [] + 0: MD_QUOTE_PREFIX@36..38 + 0: MD_QUOTE_INDENT_LIST@36..36 + 1: R_ANGLE@36..37 ">" [] [] + 2: MD_QUOTE_POST_MARKER_SPACE@37..38 " " [] [] + 1: MD_BLOCK_LIST@38..73 + 0: MD_PARAGRAPH@38..53 + 0: MD_INLINE_ITEM_LIST@38..53 + 0: MD_TEXTUAL@38..52 + 0: MD_TEXTUAL_LITERAL@38..52 "paragraph line" [] [] 1: MD_TEXTUAL@52..53 0: MD_TEXTUAL_LITERAL@52..53 "\n" [] [] 1: (empty) - 1: MD_ORDERED_LIST_ITEM@53..73 - 0: MD_BULLET_LIST@53..73 - 0: MD_BULLET@53..73 - 0: MD_ORDERED_LIST_MARKER@53..57 "1." [Skipped(">"), Skipped(" ")] [] + 1: MD_QUOTE_PREFIX@53..55 + 0: MD_QUOTE_INDENT_LIST@53..53 + 1: R_ANGLE@53..54 ">" [] [] + 2: MD_QUOTE_POST_MARKER_SPACE@54..55 " " [] [] + 2: MD_ORDERED_LIST_ITEM@55..73 + 0: MD_BULLET_LIST@55..73 + 0: MD_BULLET@55..73 + 0: MD_LIST_MARKER_PREFIX@55..57 + 0: MD_INDENT_TOKEN_LIST@55..55 + 1: MD_ORDERED_LIST_MARKER@55..57 "1." [] [] + 2: (empty) + 3: MD_INDENT_TOKEN_LIST@57..57 1: MD_BLOCK_LIST@57..73 0: MD_PARAGRAPH@57..73 0: MD_INLINE_ITEM_LIST@57..73 @@ -185,17 +243,24 @@ MdDocument { 3: MD_NEWLINE@73..74 0: NEWLINE@73..74 "\n" [] [] 4: MD_QUOTE@74..109 - 0: R_ANGLE@74..75 ">" [] [] - 1: MD_BLOCK_LIST@75..109 - 0: MD_PARAGRAPH@75..109 - 0: MD_INLINE_ITEM_LIST@75..109 - 0: MD_TEXTUAL@75..90 - 0: MD_TEXTUAL_LITERAL@75..90 "paragraph line" [Skipped(" ")] [] + 0: MD_QUOTE_PREFIX@74..76 + 0: MD_QUOTE_INDENT_LIST@74..74 + 1: R_ANGLE@74..75 ">" [] [] + 2: MD_QUOTE_POST_MARKER_SPACE@75..76 " " [] [] + 1: MD_BLOCK_LIST@76..109 + 0: MD_PARAGRAPH@76..109 + 0: MD_INLINE_ITEM_LIST@76..109 + 0: MD_TEXTUAL@76..90 + 0: MD_TEXTUAL_LITERAL@76..90 "paragraph line" [] [] 1: MD_TEXTUAL@90..91 0: MD_TEXTUAL_LITERAL@90..91 "\n" [] [] - 2: MD_TEXTUAL@91..108 - 0: MD_TEXTUAL_LITERAL@91..108 "still paragraph" [Skipped(">"), Skipped(" ")] [] - 3: MD_TEXTUAL@108..109 + 2: MD_QUOTE_PREFIX@91..93 + 0: MD_QUOTE_INDENT_LIST@91..91 + 1: R_ANGLE@91..92 ">" [] [] + 2: MD_QUOTE_POST_MARKER_SPACE@92..93 " " [] [] + 3: MD_TEXTUAL@93..108 + 0: MD_TEXTUAL_LITERAL@93..108 "still paragraph" [] [] + 4: MD_TEXTUAL@108..109 0: MD_TEXTUAL_LITERAL@108..109 "\n" [] [] 1: (empty) 2: EOF@109..109 "" [] [] diff --git a/crates/biome_markdown_syntax/src/generated/nodes.rs b/crates/biome_markdown_syntax/src/generated/nodes.rs index 98a97be7768a..65255547e295 100644 --- a/crates/biome_markdown_syntax/src/generated/nodes.rs +++ b/crates/biome_markdown_syntax/src/generated/nodes.rs @@ -1642,6 +1642,25 @@ impl AnyMdBlock { } } #[derive(Clone, PartialEq, Eq, Hash, Serialize)] +pub enum AnyMdBulletListMember { + MdBullet(MdBullet), + MdNewline(MdNewline), +} +impl AnyMdBulletListMember { + pub fn as_md_bullet(&self) -> Option<&MdBullet> { + match &self { + Self::MdBullet(item) => Some(item), + _ => None, + } + } + pub fn as_md_newline(&self) -> Option<&MdNewline> { + match &self { + Self::MdNewline(item) => Some(item), + _ => None, + } + } +} +#[derive(Clone, PartialEq, Eq, Hash, Serialize)] pub enum AnyMdCodeBlock { MdFencedCodeBlock(MdFencedCodeBlock), MdIndentCodeBlock(MdIndentCodeBlock), @@ -3889,6 +3908,65 @@ impl From for SyntaxElement { node.into() } } +impl From for AnyMdBulletListMember { + fn from(node: MdBullet) -> Self { + Self::MdBullet(node) + } +} +impl From for AnyMdBulletListMember { + fn from(node: MdNewline) -> Self { + Self::MdNewline(node) + } +} +impl AstNode for AnyMdBulletListMember { + type Language = Language; + const KIND_SET: SyntaxKindSet = MdBullet::KIND_SET.union(MdNewline::KIND_SET); + fn can_cast(kind: SyntaxKind) -> bool { + matches!(kind, MD_BULLET | MD_NEWLINE) + } + fn cast(syntax: SyntaxNode) -> Option { + let res = match syntax.kind() { + MD_BULLET => Self::MdBullet(MdBullet { syntax }), + MD_NEWLINE => Self::MdNewline(MdNewline { syntax }), + _ => return None, + }; + Some(res) + } + fn syntax(&self) -> &SyntaxNode { + match self { + Self::MdBullet(it) => it.syntax(), + Self::MdNewline(it) => it.syntax(), + } + } + fn into_syntax(self) -> SyntaxNode { + match self { + Self::MdBullet(it) => it.into_syntax(), + Self::MdNewline(it) => it.into_syntax(), + } + } +} +impl std::fmt::Debug for AnyMdBulletListMember { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + Self::MdBullet(it) => std::fmt::Debug::fmt(it, f), + Self::MdNewline(it) => std::fmt::Debug::fmt(it, f), + } + } +} +impl From for SyntaxNode { + fn from(n: AnyMdBulletListMember) -> Self { + match n { + AnyMdBulletListMember::MdBullet(it) => it.into_syntax(), + AnyMdBulletListMember::MdNewline(it) => it.into_syntax(), + } + } +} +impl From for SyntaxElement { + fn from(n: AnyMdBulletListMember) -> Self { + let node: SyntaxNode = n.into(); + node.into() + } +} impl From for AnyMdCodeBlock { fn from(node: MdFencedCodeBlock) -> Self { Self::MdFencedCodeBlock(node) @@ -4394,6 +4472,11 @@ impl std::fmt::Display for AnyMdBlock { std::fmt::Display::fmt(self.syntax(), f) } } +impl std::fmt::Display for AnyMdBulletListMember { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self.syntax(), f) + } +} impl std::fmt::Display for AnyMdCodeBlock { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { std::fmt::Display::fmt(self.syntax(), f) @@ -4797,7 +4880,7 @@ impl Serialize for MdBulletList { } impl AstNodeList for MdBulletList { type Language = Language; - type Node = MdBullet; + type Node = AnyMdBulletListMember; fn syntax_list(&self) -> &SyntaxList { &self.syntax_list } @@ -4812,15 +4895,15 @@ impl Debug for MdBulletList { } } impl IntoIterator for &MdBulletList { - type Item = MdBullet; - type IntoIter = AstNodeListIterator; + type Item = AnyMdBulletListMember; + type IntoIter = AstNodeListIterator; fn into_iter(self) -> Self::IntoIter { self.iter() } } impl IntoIterator for MdBulletList { - type Item = MdBullet; - type IntoIter = AstNodeListIterator; + type Item = AnyMdBulletListMember; + type IntoIter = AstNodeListIterator; fn into_iter(self) -> Self::IntoIter { self.iter() } diff --git a/xtask/codegen/markdown.ungram b/xtask/codegen/markdown.ungram index 90c835c70eab..0101c8ac1288 100644 --- a/xtask/codegen/markdown.ungram +++ b/xtask/codegen/markdown.ungram @@ -187,7 +187,8 @@ MdBulletListItem = MdBulletList MdOrderedListItem = MdBulletList -MdBulletList = MdBullet* +AnyMdBulletListMember = MdBullet | MdNewline +MdBulletList = AnyMdBulletListMember* // - Hey! // ^^^^^^ // 1. Hey!