diff --git a/crates/biome_markdown_parser/src/syntax/mod.rs b/crates/biome_markdown_parser/src/syntax/mod.rs
index c47543489e44..d778917c0d86 100644
--- a/crates/biome_markdown_parser/src/syntax/mod.rs
+++ b/crates/biome_markdown_parser/src/syntax/mod.rs
@@ -858,6 +858,12 @@ fn is_quote_blank_line_after_newline(p: &mut MarkdownParser, quote_depth: usize)
p.lookahead(|p| {
p.bump(NEWLINE);
+ is_quote_blank_line_from_current(p, quote_depth)
+ })
+}
+
+fn is_quote_blank_line_from_current(p: &mut MarkdownParser, quote_depth: usize) -> bool {
+ p.lookahead(|p| {
if is_quote_only_blank_line_from_source(p, quote_depth) {
return true;
}
@@ -1009,8 +1015,22 @@ fn handle_inline_newline(p: &mut MarkdownParser, has_content: bool) -> InlineNew
// Consume the NEWLINE as textual content (remap to MD_TEXTUAL_LITERAL)
emit_inline_newline_as_text(p);
- // If we're inside a block quote, only consume the quote prefix
- // when it doesn't start a new block (e.g., a nested quote).
+ handle_line_continuation(p, has_content, true)
+}
+
+/// Consume container continuation prefixes and check for block interrupts.
+///
+/// Called after a line boundary has been crossed — either a NEWLINE (via
+/// `handle_inline_newline`) or a hard line break (`MD_HARD_LINE_LITERAL`,
+/// which embeds its own newline). Handles quote prefixes, list indent,
+/// setext underlines, and other block-level constructs that can end or
+/// interrupt a paragraph.
+fn handle_line_continuation(
+ p: &mut MarkdownParser,
+ has_content: bool,
+ emit_indent_tokens: bool,
+) -> InlineNewlineAction {
+ let quote_depth = p.state().block_quote_depth;
if break_for_quote_prefix_after_inline_newline(p, quote_depth) {
return InlineNewlineAction::Break;
}
@@ -1024,12 +1044,6 @@ fn handle_inline_newline(p: &mut MarkdownParser, has_content: bool) -> InlineNew
return InlineNewlineAction::Break;
}
- // Inside a nested list item (depth >= 2), break the paragraph when the
- // continuation line's indent drops to or below the marker column.
- // Such lines belong to a parent item, not lazy continuation.
- // We only check nesting depth, not marker_indent alone, because a
- // top-level list with leading whitespace (e.g. ` 1. text`) still
- // allows lazy continuation at indent 0 per CommonMark §5.2.
if required_indent > 0 && p.state().list_nesting_depth >= 2 {
let marker_indent = p.state().list_item_marker_indent;
if marker_indent > 0 {
@@ -1040,9 +1054,6 @@ fn handle_inline_newline(p: &mut MarkdownParser, has_content: bool) -> InlineNew
}
}
- // Check for block-level constructs that can interrupt paragraphs.
- // Textual fence tokens (e.g. "```") may not be caught by line_starts_with_fence
- // because the lexer emits them as MD_TEXTUAL_LITERAL in inline context.
if p.at(MD_TEXTUAL_LITERAL) {
let text = p.cur_text();
if text.starts_with("```") || text.starts_with("~~~") {
@@ -1053,7 +1064,9 @@ fn handle_inline_newline(p: &mut MarkdownParser, has_content: bool) -> InlineNew
return InlineNewlineAction::Break;
}
- emit_inline_continuation_indent(p, required_indent);
+ if emit_indent_tokens {
+ emit_inline_continuation_indent(p, required_indent);
+ }
InlineNewlineAction::Continue
}
@@ -1145,8 +1158,21 @@ pub(crate) fn parse_inline_item_list(p: &mut MarkdownParser) {
after_hard_break = matches!(&parsed, Present(cm) if cm.kind(p) == MD_HARD_LINE);
// Per CommonMark §6.7: after a hard line break, leading spaces on the
- // next line are ignored. Consume as whitespace trivia (structural).
+ // next line are ignored. First, run container continuation handling so
+ // block quote/list prefixes remain part of the same paragraph.
if after_hard_break {
+ let quote_depth = p.state().block_quote_depth;
+ if p.at(NEWLINE) || is_quote_blank_line_from_current(p, quote_depth) {
+ break;
+ }
+
+ if matches!(
+ handle_line_continuation(p, has_content, false),
+ InlineNewlineAction::Break
+ ) {
+ break;
+ }
+
while p.at(MD_TEXTUAL_LITERAL) && p.cur_text().chars().all(|c| c == ' ' || c == '\t') {
p.consume_as_whitespace_trivia();
}
diff --git a/crates/biome_markdown_parser/src/to_html.rs b/crates/biome_markdown_parser/src/to_html.rs
index 613118d0b3ca..2e8d049343de 100644
--- a/crates/biome_markdown_parser/src/to_html.rs
+++ b/crates/biome_markdown_parser/src/to_html.rs
@@ -2007,6 +2007,36 @@ mod tests {
assert_eq!(html, "
foo\\
\n");
}
+ #[test]
+ fn test_hard_break_in_blockquote() {
+ let parsed = parse_markdown("> foo \n> bar \n>\n> baz");
+ let html = document_to_html(
+ &parsed.tree(),
+ parsed.list_tightness(),
+ parsed.list_item_indents(),
+ parsed.quote_indents(),
+ );
+ assert_eq!(
+ html,
+ "\nfoo
\nbar
\nbaz
\n
\n"
+ );
+ }
+
+ #[test]
+ fn test_hard_break_nested_quote_in_list() {
+ let parsed = parse_markdown("- > quoted \n > line \n >\n > next para\n\n- after\n");
+ let html = document_to_html(
+ &parsed.tree(),
+ parsed.list_tightness(),
+ parsed.list_item_indents(),
+ parsed.quote_indents(),
+ );
+ assert_eq!(
+ html,
+ "\n- \n
\nquoted
\nline
\nnext para
\n
\n \n- \n
after
\n \n
\n"
+ );
+ }
+
#[test]
fn test_tight_list_marker_split() {
// Two tight lists separated by blank line with different markers
diff --git a/crates/biome_markdown_parser/tests/md_test_suite/ok/hard_break_in_blockquote.md b/crates/biome_markdown_parser/tests/md_test_suite/ok/hard_break_in_blockquote.md
new file mode 100644
index 000000000000..ad78c37471ba
--- /dev/null
+++ b/crates/biome_markdown_parser/tests/md_test_suite/ok/hard_break_in_blockquote.md
@@ -0,0 +1,4 @@
+> foo
+> bar
+>
+> baz
\ No newline at end of file
diff --git a/crates/biome_markdown_parser/tests/md_test_suite/ok/hard_break_in_blockquote.md.snap b/crates/biome_markdown_parser/tests/md_test_suite/ok/hard_break_in_blockquote.md.snap
new file mode 100644
index 000000000000..d43f890f1ef7
--- /dev/null
+++ b/crates/biome_markdown_parser/tests/md_test_suite/ok/hard_break_in_blockquote.md.snap
@@ -0,0 +1,123 @@
+---
+source: crates/biome_markdown_parser/tests/spec_test.rs
+expression: snapshot
+---
+
+## Input
+
+```
+> foo
+> bar
+>
+> baz
+```
+
+
+## AST
+
+```
+MdDocument {
+ bom_token: missing (optional),
+ value: MdBlockList [
+ MdQuote {
+ 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@2..5 "foo" [] [],
+ },
+ MdHardLine {
+ value_token: MD_HARD_LINE_LITERAL@5..8 " \n" [] [],
+ },
+ MdQuotePrefix {
+ pre_marker_indent: MdQuoteIndentList [],
+ marker_token: R_ANGLE@8..9 ">" [] [],
+ post_marker_space_token: MD_QUOTE_POST_MARKER_SPACE@9..10 " " [] [],
+ },
+ MdTextual {
+ value_token: MD_TEXTUAL_LITERAL@10..13 "bar" [] [],
+ },
+ MdHardLine {
+ value_token: MD_HARD_LINE_LITERAL@13..16 " \n" [] [],
+ },
+ ],
+ hard_line: missing (optional),
+ },
+ MdQuotePrefix {
+ pre_marker_indent: MdQuoteIndentList [],
+ marker_token: R_ANGLE@16..17 ">" [] [],
+ post_marker_space_token: missing (optional),
+ },
+ MdNewline {
+ value_token: NEWLINE@17..18 "\n" [] [],
+ },
+ MdQuotePrefix {
+ pre_marker_indent: MdQuoteIndentList [],
+ marker_token: R_ANGLE@18..19 ">" [] [],
+ post_marker_space_token: MD_QUOTE_POST_MARKER_SPACE@19..20 " " [] [],
+ },
+ MdParagraph {
+ list: MdInlineItemList [
+ MdTextual {
+ value_token: MD_TEXTUAL_LITERAL@20..23 "baz" [] [],
+ },
+ ],
+ hard_line: missing (optional),
+ },
+ ],
+ },
+ ],
+ eof_token: EOF@23..23 "" [] [],
+}
+```
+
+## CST
+
+```
+0: MD_DOCUMENT@0..23
+ 0: (empty)
+ 1: MD_BLOCK_LIST@0..23
+ 0: MD_QUOTE@0..23
+ 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..23
+ 0: MD_PARAGRAPH@2..16
+ 0: MD_INLINE_ITEM_LIST@2..16
+ 0: MD_TEXTUAL@2..5
+ 0: MD_TEXTUAL_LITERAL@2..5 "foo" [] []
+ 1: MD_HARD_LINE@5..8
+ 0: MD_HARD_LINE_LITERAL@5..8 " \n" [] []
+ 2: MD_QUOTE_PREFIX@8..10
+ 0: MD_QUOTE_INDENT_LIST@8..8
+ 1: R_ANGLE@8..9 ">" [] []
+ 2: MD_QUOTE_POST_MARKER_SPACE@9..10 " " [] []
+ 3: MD_TEXTUAL@10..13
+ 0: MD_TEXTUAL_LITERAL@10..13 "bar" [] []
+ 4: MD_HARD_LINE@13..16
+ 0: MD_HARD_LINE_LITERAL@13..16 " \n" [] []
+ 1: (empty)
+ 1: MD_QUOTE_PREFIX@16..17
+ 0: MD_QUOTE_INDENT_LIST@16..16
+ 1: R_ANGLE@16..17 ">" [] []
+ 2: (empty)
+ 2: MD_NEWLINE@17..18
+ 0: NEWLINE@17..18 "\n" [] []
+ 3: MD_QUOTE_PREFIX@18..20
+ 0: MD_QUOTE_INDENT_LIST@18..18
+ 1: R_ANGLE@18..19 ">" [] []
+ 2: MD_QUOTE_POST_MARKER_SPACE@19..20 " " [] []
+ 4: MD_PARAGRAPH@20..23
+ 0: MD_INLINE_ITEM_LIST@20..23
+ 0: MD_TEXTUAL@20..23
+ 0: MD_TEXTUAL_LITERAL@20..23 "baz" [] []
+ 1: (empty)
+ 2: EOF@23..23 "" [] []
+
+```
diff --git a/crates/biome_markdown_parser/tests/md_test_suite/ok/hard_break_in_list_item.md b/crates/biome_markdown_parser/tests/md_test_suite/ok/hard_break_in_list_item.md
new file mode 100644
index 000000000000..716e805085f0
--- /dev/null
+++ b/crates/biome_markdown_parser/tests/md_test_suite/ok/hard_break_in_list_item.md
@@ -0,0 +1,6 @@
+- foo
+ bar
+
+ baz
+
+- simple
\ No newline at end of file
diff --git a/crates/biome_markdown_parser/tests/md_test_suite/ok/hard_break_in_list_item.md.snap b/crates/biome_markdown_parser/tests/md_test_suite/ok/hard_break_in_list_item.md.snap
new file mode 100644
index 000000000000..9cc37c11b4c5
--- /dev/null
+++ b/crates/biome_markdown_parser/tests/md_test_suite/ok/hard_break_in_list_item.md.snap
@@ -0,0 +1,162 @@
+---
+source: crates/biome_markdown_parser/tests/spec_test.rs
+expression: snapshot
+---
+
+## Input
+
+```
+- foo
+ bar
+
+ baz
+
+- simple
+```
+
+
+## AST
+
+```
+MdDocument {
+ bom_token: missing (optional),
+ value: MdBlockList [
+ MdBulletListItem {
+ md_bullet_list: MdBulletList [
+ MdBullet {
+ prefix: MdListMarkerPrefix {
+ pre_marker_indent: MdIndentTokenList [],
+ marker: MINUS@0..1 "-" [] [],
+ post_marker_space_token: missing (optional),
+ content_indent: MdIndentTokenList [],
+ },
+ content: MdBlockList [
+ MdParagraph {
+ list: MdInlineItemList [
+ MdTextual {
+ value_token: MD_TEXTUAL_LITERAL@1..5 " foo" [] [],
+ },
+ MdHardLine {
+ value_token: MD_HARD_LINE_LITERAL@5..8 " \n" [] [],
+ },
+ MdTextual {
+ value_token: MD_TEXTUAL_LITERAL@8..13 "bar" [Whitespace(" "), Whitespace(" ")] [],
+ },
+ MdHardLine {
+ value_token: MD_HARD_LINE_LITERAL@13..16 " \n" [] [],
+ },
+ ],
+ hard_line: missing (optional),
+ },
+ MdNewline {
+ value_token: NEWLINE@16..17 "\n" [] [],
+ },
+ MdContinuationIndent {
+ indent: MdIndentTokenList [
+ MdIndentToken {
+ md_indent_char_token: MD_INDENT_CHAR@17..18 " " [] [],
+ },
+ MdIndentToken {
+ md_indent_char_token: MD_INDENT_CHAR@18..19 " " [] [],
+ },
+ ],
+ },
+ MdParagraph {
+ list: MdInlineItemList [
+ MdTextual {
+ value_token: MD_TEXTUAL_LITERAL@19..22 "baz" [] [],
+ },
+ MdTextual {
+ value_token: MD_TEXTUAL_LITERAL@22..23 "\n" [] [],
+ },
+ ],
+ hard_line: missing (optional),
+ },
+ MdNewline {
+ value_token: NEWLINE@23..24 "\n" [] [],
+ },
+ ],
+ },
+ MdBullet {
+ prefix: MdListMarkerPrefix {
+ pre_marker_indent: MdIndentTokenList [],
+ marker: MINUS@24..25 "-" [] [],
+ post_marker_space_token: missing (optional),
+ content_indent: MdIndentTokenList [],
+ },
+ content: MdBlockList [
+ MdParagraph {
+ list: MdInlineItemList [
+ MdTextual {
+ value_token: MD_TEXTUAL_LITERAL@25..32 " simple" [] [],
+ },
+ ],
+ hard_line: missing (optional),
+ },
+ ],
+ },
+ ],
+ },
+ ],
+ eof_token: EOF@32..32 "" [] [],
+}
+```
+
+## CST
+
+```
+0: MD_DOCUMENT@0..32
+ 0: (empty)
+ 1: MD_BLOCK_LIST@0..32
+ 0: MD_BULLET_LIST_ITEM@0..32
+ 0: MD_BULLET_LIST@0..32
+ 0: MD_BULLET@0..24
+ 0: MD_LIST_MARKER_PREFIX@0..1
+ 0: MD_INDENT_TOKEN_LIST@0..0
+ 1: MINUS@0..1 "-" [] []
+ 2: (empty)
+ 3: MD_INDENT_TOKEN_LIST@1..1
+ 1: MD_BLOCK_LIST@1..24
+ 0: MD_PARAGRAPH@1..16
+ 0: MD_INLINE_ITEM_LIST@1..16
+ 0: MD_TEXTUAL@1..5
+ 0: MD_TEXTUAL_LITERAL@1..5 " foo" [] []
+ 1: MD_HARD_LINE@5..8
+ 0: MD_HARD_LINE_LITERAL@5..8 " \n" [] []
+ 2: MD_TEXTUAL@8..13
+ 0: MD_TEXTUAL_LITERAL@8..13 "bar" [Whitespace(" "), Whitespace(" ")] []
+ 3: MD_HARD_LINE@13..16
+ 0: MD_HARD_LINE_LITERAL@13..16 " \n" [] []
+ 1: (empty)
+ 1: MD_NEWLINE@16..17
+ 0: NEWLINE@16..17 "\n" [] []
+ 2: MD_CONTINUATION_INDENT@17..19
+ 0: MD_INDENT_TOKEN_LIST@17..19
+ 0: MD_INDENT_TOKEN@17..18
+ 0: MD_INDENT_CHAR@17..18 " " [] []
+ 1: MD_INDENT_TOKEN@18..19
+ 0: MD_INDENT_CHAR@18..19 " " [] []
+ 3: MD_PARAGRAPH@19..23
+ 0: MD_INLINE_ITEM_LIST@19..23
+ 0: MD_TEXTUAL@19..22
+ 0: MD_TEXTUAL_LITERAL@19..22 "baz" [] []
+ 1: MD_TEXTUAL@22..23
+ 0: MD_TEXTUAL_LITERAL@22..23 "\n" [] []
+ 1: (empty)
+ 4: MD_NEWLINE@23..24
+ 0: NEWLINE@23..24 "\n" [] []
+ 1: MD_BULLET@24..32
+ 0: MD_LIST_MARKER_PREFIX@24..25
+ 0: MD_INDENT_TOKEN_LIST@24..24
+ 1: MINUS@24..25 "-" [] []
+ 2: (empty)
+ 3: MD_INDENT_TOKEN_LIST@25..25
+ 1: MD_BLOCK_LIST@25..32
+ 0: MD_PARAGRAPH@25..32
+ 0: MD_INLINE_ITEM_LIST@25..32
+ 0: MD_TEXTUAL@25..32
+ 0: MD_TEXTUAL_LITERAL@25..32 " simple" [] []
+ 1: (empty)
+ 2: EOF@32..32 "" [] []
+
+```
diff --git a/crates/biome_markdown_parser/tests/md_test_suite/ok/hard_break_nested_quote_in_list.md b/crates/biome_markdown_parser/tests/md_test_suite/ok/hard_break_nested_quote_in_list.md
new file mode 100644
index 000000000000..782f41770033
--- /dev/null
+++ b/crates/biome_markdown_parser/tests/md_test_suite/ok/hard_break_nested_quote_in_list.md
@@ -0,0 +1,6 @@
+- > quoted
+ > line
+ >
+ > next para
+
+- after
diff --git a/crates/biome_markdown_parser/tests/md_test_suite/ok/hard_break_nested_quote_in_list.md.snap b/crates/biome_markdown_parser/tests/md_test_suite/ok/hard_break_nested_quote_in_list.md.snap
new file mode 100644
index 000000000000..9800ce3572fd
--- /dev/null
+++ b/crates/biome_markdown_parser/tests/md_test_suite/ok/hard_break_nested_quote_in_list.md.snap
@@ -0,0 +1,227 @@
+---
+source: crates/biome_markdown_parser/tests/spec_test.rs
+expression: snapshot
+---
+
+## Input
+
+```
+- > quoted
+ > line
+ >
+ > next para
+
+- after
+
+```
+
+
+## AST
+
+```
+MdDocument {
+ bom_token: missing (optional),
+ value: MdBlockList [
+ MdBulletListItem {
+ md_bullet_list: MdBulletList [
+ MdBullet {
+ prefix: MdListMarkerPrefix {
+ pre_marker_indent: MdIndentTokenList [],
+ marker: MINUS@0..1 "-" [] [],
+ post_marker_space_token: MD_LIST_POST_MARKER_SPACE@1..2 " " [] [],
+ content_indent: MdIndentTokenList [],
+ },
+ content: MdBlockList [
+ MdQuote {
+ prefix: MdQuotePrefix {
+ pre_marker_indent: MdQuoteIndentList [],
+ marker_token: R_ANGLE@2..3 ">" [] [],
+ post_marker_space_token: missing (optional),
+ },
+ content: MdBlockList [
+ MdParagraph {
+ list: MdInlineItemList [
+ MdTextual {
+ value_token: MD_TEXTUAL_LITERAL@3..10 " quoted" [] [],
+ },
+ MdHardLine {
+ value_token: MD_HARD_LINE_LITERAL@10..13 " \n" [] [],
+ },
+ MdQuotePrefix {
+ pre_marker_indent: MdQuoteIndentList [
+ MdQuoteIndent {
+ md_quote_pre_marker_indent_token: MD_QUOTE_PRE_MARKER_INDENT@13..14 " " [] [],
+ },
+ MdQuoteIndent {
+ md_quote_pre_marker_indent_token: MD_QUOTE_PRE_MARKER_INDENT@14..15 " " [] [],
+ },
+ ],
+ marker_token: R_ANGLE@15..16 ">" [] [],
+ post_marker_space_token: MD_QUOTE_POST_MARKER_SPACE@16..17 " " [] [],
+ },
+ MdTextual {
+ value_token: MD_TEXTUAL_LITERAL@17..21 "line" [] [],
+ },
+ MdHardLine {
+ value_token: MD_HARD_LINE_LITERAL@21..24 " \n" [] [],
+ },
+ ],
+ hard_line: missing (optional),
+ },
+ MdQuotePrefix {
+ pre_marker_indent: MdQuoteIndentList [
+ MdQuoteIndent {
+ md_quote_pre_marker_indent_token: MD_QUOTE_PRE_MARKER_INDENT@24..25 " " [] [],
+ },
+ MdQuoteIndent {
+ md_quote_pre_marker_indent_token: MD_QUOTE_PRE_MARKER_INDENT@25..26 " " [] [],
+ },
+ ],
+ marker_token: R_ANGLE@26..27 ">" [] [],
+ post_marker_space_token: missing (optional),
+ },
+ MdNewline {
+ value_token: NEWLINE@27..28 "\n" [] [],
+ },
+ MdQuotePrefix {
+ pre_marker_indent: MdQuoteIndentList [
+ MdQuoteIndent {
+ md_quote_pre_marker_indent_token: MD_QUOTE_PRE_MARKER_INDENT@28..29 " " [] [],
+ },
+ MdQuoteIndent {
+ md_quote_pre_marker_indent_token: MD_QUOTE_PRE_MARKER_INDENT@29..30 " " [] [],
+ },
+ ],
+ marker_token: R_ANGLE@30..31 ">" [] [],
+ post_marker_space_token: MD_QUOTE_POST_MARKER_SPACE@31..32 " " [] [],
+ },
+ MdParagraph {
+ list: MdInlineItemList [
+ MdTextual {
+ value_token: MD_TEXTUAL_LITERAL@32..41 "next para" [] [],
+ },
+ 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..50 " after" [] [],
+ },
+ MdTextual {
+ value_token: MD_TEXTUAL_LITERAL@50..51 "\n" [] [],
+ },
+ ],
+ hard_line: missing (optional),
+ },
+ ],
+ },
+ ],
+ },
+ ],
+ eof_token: EOF@51..51 "" [] [],
+}
+```
+
+## CST
+
+```
+0: MD_DOCUMENT@0..51
+ 0: (empty)
+ 1: MD_BLOCK_LIST@0..51
+ 0: MD_BULLET_LIST_ITEM@0..51
+ 0: MD_BULLET_LIST@0..51
+ 0: MD_BULLET@0..43
+ 0: MD_LIST_MARKER_PREFIX@0..2
+ 0: MD_INDENT_TOKEN_LIST@0..0
+ 1: MINUS@0..1 "-" [] []
+ 2: MD_LIST_POST_MARKER_SPACE@1..2 " " [] []
+ 3: MD_INDENT_TOKEN_LIST@2..2
+ 1: MD_BLOCK_LIST@2..43
+ 0: MD_QUOTE@2..42
+ 0: MD_QUOTE_PREFIX@2..3
+ 0: MD_QUOTE_INDENT_LIST@2..2
+ 1: R_ANGLE@2..3 ">" [] []
+ 2: (empty)
+ 1: MD_BLOCK_LIST@3..42
+ 0: MD_PARAGRAPH@3..24
+ 0: MD_INLINE_ITEM_LIST@3..24
+ 0: MD_TEXTUAL@3..10
+ 0: MD_TEXTUAL_LITERAL@3..10 " quoted" [] []
+ 1: MD_HARD_LINE@10..13
+ 0: MD_HARD_LINE_LITERAL@10..13 " \n" [] []
+ 2: MD_QUOTE_PREFIX@13..17
+ 0: MD_QUOTE_INDENT_LIST@13..15
+ 0: MD_QUOTE_INDENT@13..14
+ 0: MD_QUOTE_PRE_MARKER_INDENT@13..14 " " [] []
+ 1: MD_QUOTE_INDENT@14..15
+ 0: MD_QUOTE_PRE_MARKER_INDENT@14..15 " " [] []
+ 1: R_ANGLE@15..16 ">" [] []
+ 2: MD_QUOTE_POST_MARKER_SPACE@16..17 " " [] []
+ 3: MD_TEXTUAL@17..21
+ 0: MD_TEXTUAL_LITERAL@17..21 "line" [] []
+ 4: MD_HARD_LINE@21..24
+ 0: MD_HARD_LINE_LITERAL@21..24 " \n" [] []
+ 1: (empty)
+ 1: MD_QUOTE_PREFIX@24..27
+ 0: MD_QUOTE_INDENT_LIST@24..26
+ 0: MD_QUOTE_INDENT@24..25
+ 0: MD_QUOTE_PRE_MARKER_INDENT@24..25 " " [] []
+ 1: MD_QUOTE_INDENT@25..26
+ 0: MD_QUOTE_PRE_MARKER_INDENT@25..26 " " [] []
+ 1: R_ANGLE@26..27 ">" [] []
+ 2: (empty)
+ 2: MD_NEWLINE@27..28
+ 0: NEWLINE@27..28 "\n" [] []
+ 3: MD_QUOTE_PREFIX@28..32
+ 0: MD_QUOTE_INDENT_LIST@28..30
+ 0: MD_QUOTE_INDENT@28..29
+ 0: MD_QUOTE_PRE_MARKER_INDENT@28..29 " " [] []
+ 1: MD_QUOTE_INDENT@29..30
+ 0: MD_QUOTE_PRE_MARKER_INDENT@29..30 " " [] []
+ 1: R_ANGLE@30..31 ">" [] []
+ 2: MD_QUOTE_POST_MARKER_SPACE@31..32 " " [] []
+ 4: MD_PARAGRAPH@32..42
+ 0: MD_INLINE_ITEM_LIST@32..42
+ 0: MD_TEXTUAL@32..41
+ 0: MD_TEXTUAL_LITERAL@32..41 "next para" [] []
+ 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..51
+ 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..51
+ 0: MD_PARAGRAPH@44..51
+ 0: MD_INLINE_ITEM_LIST@44..51
+ 0: MD_TEXTUAL@44..50
+ 0: MD_TEXTUAL_LITERAL@44..50 " after" [] []
+ 1: MD_TEXTUAL@50..51
+ 0: MD_TEXTUAL_LITERAL@50..51 "\n" [] []
+ 1: (empty)
+ 2: EOF@51..51 "" [] []
+
+```
diff --git a/crates/biome_markdown_parser/tests/spec_test.rs b/crates/biome_markdown_parser/tests/spec_test.rs
index 233a48fc2d4b..d4c34ce710bf 100644
--- a/crates/biome_markdown_parser/tests/spec_test.rs
+++ b/crates/biome_markdown_parser/tests/spec_test.rs
@@ -269,6 +269,11 @@ pub fn quick_test() {
"> ```\n> hello\n> ```\n",
"\nhello\n
\n
\n",
);
+ test_example(
+ 99922,
+ "> foo \n> bar\n",
+ "\nfoo
\nbar
\n
\n",
+ );
// Quoted indented code must terminate before a quoted thematic break.
test_example(
99921,