Skip to content

Commit 1022662

Browse files
refactor(markdown-parser): promote blank lines between list items to MdNewline nodes (#9313)
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
1 parent 1e82da1 commit 1022662

File tree

13 files changed

+968
-63
lines changed

13 files changed

+968
-63
lines changed

crates/biome_markdown_factory/src/generated/node_factory.rs

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/biome_markdown_factory/src/generated/syntax_factory.rs

Lines changed: 3 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/biome_markdown_formatter/src/generated.rs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1679,6 +1679,31 @@ impl IntoFormat<MarkdownFormatContext> for biome_markdown_syntax::AnyMdBlock {
16791679
)
16801680
}
16811681
}
1682+
impl AsFormat<MarkdownFormatContext> for biome_markdown_syntax::AnyMdBulletListMember {
1683+
type Format<'a> = FormatRefWithRule<
1684+
'a,
1685+
biome_markdown_syntax::AnyMdBulletListMember,
1686+
crate::markdown::any::bullet_list_member::FormatAnyMdBulletListMember,
1687+
>;
1688+
fn format(&self) -> Self::Format<'_> {
1689+
FormatRefWithRule::new(
1690+
self,
1691+
crate::markdown::any::bullet_list_member::FormatAnyMdBulletListMember::default(),
1692+
)
1693+
}
1694+
}
1695+
impl IntoFormat<MarkdownFormatContext> for biome_markdown_syntax::AnyMdBulletListMember {
1696+
type Format = FormatOwnedWithRule<
1697+
biome_markdown_syntax::AnyMdBulletListMember,
1698+
crate::markdown::any::bullet_list_member::FormatAnyMdBulletListMember,
1699+
>;
1700+
fn into_format(self) -> Self::Format {
1701+
FormatOwnedWithRule::new(
1702+
self,
1703+
crate::markdown::any::bullet_list_member::FormatAnyMdBulletListMember::default(),
1704+
)
1705+
}
1706+
}
16821707
impl AsFormat<MarkdownFormatContext> for biome_markdown_syntax::AnyMdCodeBlock {
16831708
type Format<'a> = FormatRefWithRule<
16841709
'a,
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
//! This is a generated file. Don't modify it by hand! Run 'cargo codegen formatter' to re-generate the file.
2+
3+
use crate::prelude::*;
4+
use biome_markdown_syntax::AnyMdBulletListMember;
5+
#[derive(Debug, Clone, Default)]
6+
pub(crate) struct FormatAnyMdBulletListMember;
7+
impl FormatRule<AnyMdBulletListMember> for FormatAnyMdBulletListMember {
8+
type Context = MarkdownFormatContext;
9+
fn fmt(&self, node: &AnyMdBulletListMember, f: &mut MarkdownFormatter) -> FormatResult<()> {
10+
match node {
11+
AnyMdBulletListMember::MdBullet(node) => node.format().fmt(f),
12+
AnyMdBulletListMember::MdNewline(node) => node.format().fmt(f),
13+
}
14+
}
15+
}

crates/biome_markdown_formatter/src/markdown/any/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
//! This is a generated file. Don't modify it by hand! Run 'cargo codegen formatter' to re-generate the file.
22
33
pub(crate) mod block;
4+
pub(crate) mod bullet_list_member;
45
pub(crate) mod code_block;
56
pub(crate) mod container_block;
67
pub(crate) mod inline;

crates/biome_markdown_parser/src/syntax/list.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -331,8 +331,10 @@ fn skip_blank_lines_between_items(
331331
// Blank lines between items make the list loose
332332
*is_tight = false;
333333
*last_item_ends_with_blank = true;
334-
// Skip the blank line as trivia (no tree node created)
335-
p.parse_as_skipped_trivia_tokens(|p| p.bump(NEWLINE));
334+
// Emit blank line as an explicit MdNewline CST node
335+
let newline_m = p.start();
336+
p.bump(NEWLINE);
337+
newline_m.complete(p, MD_NEWLINE);
336338
}
337339
}
338340

crates/biome_markdown_parser/src/syntax/mod.rs

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1161,6 +1161,7 @@ fn set_inline_emphasis_context(p: &mut MarkdownParser) -> Option<EmphasisContext
11611161
fn inline_list_source_len(p: &mut MarkdownParser) -> usize {
11621162
p.lookahead(|p| {
11631163
let mut len = 0usize;
1164+
let mut has_content = false;
11641165

11651166
loop {
11661167
if p.at(T![EOF]) {
@@ -1186,11 +1187,19 @@ fn inline_list_source_len(p: &mut MarkdownParser) -> usize {
11861187
consume_quote_prefix_without_virtual(p, quote_depth);
11871188
}
11881189

1190+
if has_content && p.at(MD_SETEXT_UNDERLINE_LITERAL) && allow_setext_heading(p) {
1191+
break;
1192+
}
1193+
1194+
if has_content && p.at(MD_THEMATIC_BREAK_LITERAL) && is_dash_only_thematic_break(p)
1195+
{
1196+
break;
1197+
}
11891198
if quote_depth > 0 && p.at(R_ANGLE) && !has_quote_prefix(p, quote_depth) {
11901199
consume_partial_quote_prefix_lookahead(p, quote_depth, &mut len);
11911200
}
11921201

1193-
if at_paragraph_break(p, true) {
1202+
if at_paragraph_break(p, has_content) {
11941203
break;
11951204
}
11961205

@@ -1228,9 +1237,10 @@ fn inline_list_source_len(p: &mut MarkdownParser) -> usize {
12281237
// We intentionally skip the heavier post-indent block-interrupt
12291238
// check here; the following non-NEWLINE pass still catches
12301239
// interrupts for emphasis-context length calculation.
1231-
if p.at(MD_SETEXT_UNDERLINE_LITERAL)
1232-
|| (p.at(MD_THEMATIC_BREAK_LITERAL)
1233-
&& is_dash_only_thematic_break_text(p.cur_text()))
1240+
if has_content
1241+
&& (p.at(MD_SETEXT_UNDERLINE_LITERAL)
1242+
|| (p.at(MD_THEMATIC_BREAK_LITERAL)
1243+
&& is_dash_only_thematic_break_text(p.cur_text())))
12341244
{
12351245
break;
12361246
}
@@ -1239,18 +1249,22 @@ fn inline_list_source_len(p: &mut MarkdownParser) -> usize {
12391249
continue;
12401250
}
12411251

1242-
if p.at(MD_SETEXT_UNDERLINE_LITERAL) && allow_setext_heading(p) {
1252+
if has_content && p.at(MD_SETEXT_UNDERLINE_LITERAL) && allow_setext_heading(p) {
12431253
break;
12441254
}
12451255

1246-
if p.at(MD_THEMATIC_BREAK_LITERAL) && is_dash_only_thematic_break(p) {
1256+
if has_content && p.at(MD_THEMATIC_BREAK_LITERAL) && is_dash_only_thematic_break(p) {
12471257
break;
12481258
}
12491259

12501260
if p.has_preceding_line_break() && at_block_interrupt(p) {
12511261
break;
12521262
}
12531263

1264+
if !p.cur_text().chars().all(|c| c == ' ' || c == '\t') {
1265+
has_content = true;
1266+
}
1267+
12541268
len += p.cur_text().len();
12551269
p.bump(p.cur());
12561270
}

crates/biome_markdown_parser/src/to_html.rs

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -43,13 +43,13 @@
4343
//! be decided with full context.
4444
4545
use biome_markdown_syntax::{
46-
AnyMdBlock, AnyMdCodeBlock, AnyMdInline, AnyMdLeafBlock, MarkdownLanguage, MdAutolink,
47-
MdBlockList, MdBullet, MdBulletListItem, MdDocument, MdEntityReference, MdFencedCodeBlock,
48-
MdHardLine, MdHeader, MdHtmlBlock, MdIndentCodeBlock, MdInlineCode, MdInlineEmphasis,
49-
MdInlineHtml, MdInlineImage, MdInlineItalic, MdInlineItemList, MdInlineLink, MdLinkBlock,
50-
MdLinkDestination, MdLinkLabel, MdLinkReferenceDefinition, MdLinkTitle, MdOrderedListItem,
51-
MdParagraph, MdQuote, MdReferenceImage, MdReferenceLink, MdReferenceLinkLabel, MdSetextHeader,
52-
MdSoftBreak, MdTextual, MdThematicBreakBlock,
46+
AnyMdBlock, AnyMdBulletListMember, AnyMdCodeBlock, AnyMdInline, AnyMdLeafBlock,
47+
MarkdownLanguage, MdAutolink, MdBlockList, MdBullet, MdBulletListItem, MdDocument,
48+
MdEntityReference, MdFencedCodeBlock, MdHardLine, MdHeader, MdHtmlBlock, MdIndentCodeBlock,
49+
MdInlineCode, MdInlineEmphasis, MdInlineHtml, MdInlineImage, MdInlineItalic, MdInlineItemList,
50+
MdInlineLink, MdLinkBlock, MdLinkDestination, MdLinkLabel, MdLinkReferenceDefinition,
51+
MdLinkTitle, MdOrderedListItem, MdParagraph, MdQuote, MdReferenceImage, MdReferenceLink,
52+
MdReferenceLinkLabel, MdSetextHeader, MdSoftBreak, MdTextual, MdThematicBreakBlock,
5353
};
5454
use biome_rowan::{AstNode, AstNodeList, Direction, SyntaxNode, TextRange, WalkEvent};
5555
use percent_encoding::{AsciiSet, CONTROLS, utf8_percent_encode};
@@ -565,7 +565,11 @@ impl<'a> HtmlRenderer<'a> {
565565

566566
let start = list
567567
.md_bullet_list()
568-
.first()
568+
.iter()
569+
.find_map(|member| match member {
570+
AnyMdBulletListMember::MdBullet(bullet) => Some(bullet),
571+
_ => None,
572+
})
569573
.and_then(|bullet| bullet.prefix().ok())
570574
.and_then(|prefix| prefix.marker().ok())
571575
.map_or(1, |marker| {
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
# Blank lines between bullet items
2+
3+
- foo
4+
5+
- bar
6+
7+
- baz
8+
9+
# Blank lines between ordered items
10+
11+
1. first
12+
13+
2. second
14+
15+
3. third
16+
17+
# Multiple blank lines between items
18+
19+
- alpha
20+
21+
22+
- beta
23+
24+
# Mixed: some items separated, some not
25+
26+
- one
27+
- two
28+
29+
- three

0 commit comments

Comments
 (0)