diff --git a/crates/markdown_preview/src/markdown_elements.rs b/crates/markdown_preview/src/markdown_elements.rs index 8d2175ab98621fed7e989bbb121cade3afcdf894..17dec6c2194747cfcd397395903a6b4bb5c309d0 100644 --- a/crates/markdown_preview/src/markdown_elements.rs +++ b/crates/markdown_preview/src/markdown_elements.rs @@ -108,6 +108,7 @@ pub struct ParsedMarkdownTable { pub source_range: Range, pub header: Vec, pub body: Vec, + pub caption: Option, } #[derive(Debug, Clone, Copy, Default)] diff --git a/crates/markdown_preview/src/markdown_parser.rs b/crates/markdown_preview/src/markdown_parser.rs index 8f2203c25b9a7193759668a35016c2d3203310b6..b2e68b4e1495515d2b37ca310ff3ec9b3502c2cc 100644 --- a/crates/markdown_preview/src/markdown_parser.rs +++ b/crates/markdown_preview/src/markdown_parser.rs @@ -533,6 +533,7 @@ impl<'a> MarkdownParser<'a> { source_range, header, body, + caption: None, } } @@ -1232,11 +1233,17 @@ impl<'a> MarkdownParser<'a> { ) -> Option { let mut header_rows = Vec::new(); let mut body_rows = Vec::new(); + let mut caption = None; - // node should be a thead or tbody element + // node should be a thead, tbody or caption element for node in node.children.borrow().iter() { match &node.data { markup5ever_rcdom::NodeData::Element { name, .. } => { + if local_name!("caption") == name.local { + let mut paragraph = MarkdownParagraph::new(); + self.parse_paragraph(source_range.clone(), node, &mut paragraph); + caption = Some(paragraph); + } if local_name!("thead") == name.local { // node should be a tr element for node in node.children.borrow().iter() { @@ -1262,6 +1269,7 @@ impl<'a> MarkdownParser<'a> { source_range, body: body_rows, header: header_rows, + caption, }) } else { None @@ -1919,6 +1927,7 @@ mod tests { ParsedMarkdown { children: vec![ParsedMarkdownElement::Table(table( 0..366, + None, vec![row(vec![ column( 1, @@ -1975,6 +1984,77 @@ mod tests { ); } + #[gpui::test] + async fn test_html_table_with_caption() { + let parsed = parse( + " + + + + + + + + + + + +
My Table
1Chris
2Dennis
", + ) + .await; + + assert_eq!( + ParsedMarkdown { + children: vec![ParsedMarkdownElement::Table(table( + 0..280, + Some(vec![MarkdownParagraphChunk::Text(ParsedMarkdownText { + source_range: 0..280, + contents: "My Table".into(), + highlights: Default::default(), + region_ranges: Default::default(), + regions: Default::default() + })]), + vec![], + vec![ + row(vec![ + column( + 1, + 1, + false, + text("1", 0..280), + ParsedMarkdownTableAlignment::None + ), + column( + 1, + 1, + false, + text("Chris", 0..280), + ParsedMarkdownTableAlignment::None + ) + ]), + row(vec![ + column( + 1, + 1, + false, + text("2", 0..280), + ParsedMarkdownTableAlignment::None + ), + column( + 1, + 1, + false, + text("Dennis", 0..280), + ParsedMarkdownTableAlignment::None + ) + ]), + ], + ))], + }, + parsed + ); + } + #[gpui::test] async fn test_html_table_without_headings() { let parsed = parse( @@ -1997,6 +2077,7 @@ mod tests { ParsedMarkdown { children: vec![ParsedMarkdownElement::Table(table( 0..240, + None, vec![], vec![ row(vec![ @@ -2056,6 +2137,7 @@ mod tests { ParsedMarkdown { children: vec![ParsedMarkdownElement::Table(table( 0..150, + None, vec![row(vec![ column( 1, @@ -2253,6 +2335,7 @@ Some other content let expected_table = table( 0..48, + None, vec![row(vec![ column( 1, @@ -2288,6 +2371,7 @@ Some other content let expected_table = table( 0..95, + None, vec![row(vec![ column( 1, @@ -2809,6 +2893,7 @@ fn main() { fn table( source_range: Range, + caption: Option, header: Vec, body: Vec, ) -> ParsedMarkdownTable { @@ -2816,6 +2901,7 @@ fn main() { source_range, header, body, + caption, } } diff --git a/crates/markdown_preview/src/markdown_renderer.rs b/crates/markdown_preview/src/markdown_renderer.rs index 38b38466394cf8073b26b1ca5728eecc8230d9c1..4a8c69e997f3db8881c0d47cb2e62d8edbeda526 100644 --- a/crates/markdown_preview/src/markdown_renderer.rs +++ b/crates/markdown_preview/src/markdown_renderer.rs @@ -561,12 +561,17 @@ fn render_markdown_table(parsed: &ParsedMarkdownTable, cx: &mut RenderContext) - } cx.with_common_p(div()) - .grid() - .size_full() - .grid_cols(max_column_count as u16) - .border_1() - .border_color(cx.border_color) - .children(cells) + .when_some(parsed.caption.as_ref(), |this, caption| { + this.children(render_markdown_text(caption, cx)) + }) + .child( + div() + .grid() + .grid_cols(max_column_count as u16) + .border_1() + .border_color(cx.border_color) + .children(cells), + ) .into_any() }