From 4152942a8efcdbf9be6d401be4fc852cbd7f3729 Mon Sep 17 00:00:00 2001 From: Remco Smits Date: Wed, 8 Oct 2025 11:33:42 +0200 Subject: [PATCH] markdown: Add support for `HTML` block quotes (#39755) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This PR adds support for HTML block quotes, that also allows you to have nested variant of it. Screenshot 2025-10-08 at 10 25 57 Code example used in screenshot: ```html

Words can be like X-rays, if you use them properly—they’ll go through anything. You read and you’re pierced.

lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed non risus. Suspendisse lectus tortor, dignissim sit amet, adipiscing nec, ultricies sed, dolor.

``` Release Notes: - Markdown: Added support for `HTML` block quotes --- .../markdown_preview/src/markdown_parser.rs | 77 +++++++++++++++++++ 1 file changed, 77 insertions(+) diff --git a/crates/markdown_preview/src/markdown_parser.rs b/crates/markdown_preview/src/markdown_parser.rs index 86bf7e94b4f8be6b7724b9e95b2583127861fff3..ba02a00932320e5ac5bb1ac1cd922e78e1f9c7e5 100644 --- a/crates/markdown_preview/src/markdown_parser.rs +++ b/crates/markdown_preview/src/markdown_parser.rs @@ -880,6 +880,10 @@ impl<'a> MarkdownParser<'a> { contents: paragraph, })); } + } else if local_name!("blockquote") == name.local { + if let Some(blockquote) = self.extract_html_blockquote(node, source_range) { + elements.push(ParsedMarkdownElement::BlockQuote(blockquote)); + } } else if local_name!("table") == name.local { if let Some(table) = self.extract_html_table(node, source_range) { elements.push(ParsedMarkdownElement::Table(table)); @@ -1002,6 +1006,24 @@ impl<'a> MarkdownParser<'a> { Some(image) } + fn extract_html_blockquote( + &self, + node: &Rc, + source_range: Range, + ) -> Option { + let mut children = Vec::new(); + self.consume_children(source_range.clone(), node, &mut children); + + if children.is_empty() { + None + } else { + Some(ParsedMarkdownBlockQuote { + children, + source_range, + }) + } + } + fn extract_html_table( &self, node: &Rc, @@ -1410,6 +1432,61 @@ mod tests { ); } + #[gpui::test] + async fn test_html_block_quote() { + let parsed = parse( + "
+

some description

+
", + ) + .await; + + assert_eq!( + ParsedMarkdown { + children: vec![block_quote( + vec![ParsedMarkdownElement::Paragraph(text( + "some description", + 0..76 + ))], + 0..76, + )] + }, + parsed + ); + } + + #[gpui::test] + async fn test_html_nested_block_quote() { + let parsed = parse( + "
+

some description

+
+

second description

+
+
", + ) + .await; + + assert_eq!( + ParsedMarkdown { + children: vec![block_quote( + vec![ + ParsedMarkdownElement::Paragraph(text("some description", 0..173)), + block_quote( + vec![ParsedMarkdownElement::Paragraph(text( + "second description", + 0..173 + ))], + 0..173, + ) + ], + 0..173, + )] + }, + parsed + ); + } + #[gpui::test] async fn test_html_table() { let parsed = parse(