Fix rendering of markdown tables (#18315)

- Closes: https://github.com/zed-industries/zed/issues/11024

## Release Notes:

- Improved Markdown Preview rendering of tables

## Before:


![image](https://github.com/user-attachments/assets/25f05604-38a9-4bde-901c-6d53a5d9d94d)

<img width="2035" alt="Screenshot 2024-09-25 at 05 47 19"
src="https://github.com/user-attachments/assets/a30c56f5-4793-44c2-8527-294189f9e724">

## Now:


![image](https://github.com/user-attachments/assets/ce06f045-d0db-4b8c-a1fc-2811d35f2683)


<img width="2040" alt="Screenshot 2024-09-25 at 05 47 48"
src="https://github.com/user-attachments/assets/76e5d217-9110-4c5d-9fad-dc63ae0b75f4">

## Note:

I'm not a Rust programmer and this is my first PR in Zed (because i just
want to fix this, so i can view my notes in Markdown in Zed, not slow
Visual Studio Code) - so there may be errors. I'm open for critic a
This commit is contained in:
Andrey Arutiunian 2024-10-01 01:50:30 +03:00 committed by GitHub
parent 3010dfe038
commit eb9fd62a90
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -6,8 +6,8 @@ use crate::markdown_elements::{
}; };
use gpui::{ use gpui::{
div, px, rems, AbsoluteLength, AnyElement, DefiniteLength, Div, Element, ElementId, div, px, rems, AbsoluteLength, AnyElement, DefiniteLength, Div, Element, ElementId,
HighlightStyle, Hsla, InteractiveText, IntoElement, Keystroke, Modifiers, ParentElement, HighlightStyle, Hsla, InteractiveText, IntoElement, Keystroke, Length, Modifiers,
SharedString, Styled, StyledText, TextStyle, WeakView, WindowContext, ParentElement, SharedString, Styled, StyledText, TextStyle, WeakView, WindowContext,
}; };
use settings::Settings; use settings::Settings;
use std::{ use std::{
@ -16,7 +16,7 @@ use std::{
}; };
use theme::{ActiveTheme, SyntaxTheme, ThemeSettings}; use theme::{ActiveTheme, SyntaxTheme, ThemeSettings};
use ui::{ use ui::{
h_flex, v_flex, Checkbox, FluentBuilder, InteractiveElement, LinkPreview, Selection, h_flex, relative, v_flex, Checkbox, FluentBuilder, InteractiveElement, LinkPreview, Selection,
StatefulInteractiveElement, Tooltip, StatefulInteractiveElement, Tooltip,
}; };
use workspace::Workspace; use workspace::Workspace;
@ -231,12 +231,48 @@ fn render_markdown_list_item(
} }
fn render_markdown_table(parsed: &ParsedMarkdownTable, cx: &mut RenderContext) -> AnyElement { fn render_markdown_table(parsed: &ParsedMarkdownTable, cx: &mut RenderContext) -> AnyElement {
let header = render_markdown_table_row(&parsed.header, &parsed.column_alignments, true, cx); let mut max_lengths: Vec<usize> = vec![0; parsed.header.children.len()];
for (index, cell) in parsed.header.children.iter().enumerate() {
let length = cell.contents.len();
max_lengths[index] = length;
}
for row in &parsed.body {
for (index, cell) in row.children.iter().enumerate() {
let length = cell.contents.len();
if length > max_lengths[index] {
max_lengths[index] = length;
}
}
}
let total_max_length: usize = max_lengths.iter().sum();
let max_column_widths: Vec<f32> = max_lengths
.iter()
.map(|&length| length as f32 / total_max_length as f32)
.collect();
let header = render_markdown_table_row(
&parsed.header,
&parsed.column_alignments,
&max_column_widths,
true,
cx,
);
let body: Vec<AnyElement> = parsed let body: Vec<AnyElement> = parsed
.body .body
.iter() .iter()
.map(|row| render_markdown_table_row(row, &parsed.column_alignments, false, cx)) .map(|row| {
render_markdown_table_row(
row,
&parsed.column_alignments,
&max_column_widths,
false,
cx,
)
})
.collect(); .collect();
cx.with_common_p(v_flex()) cx.with_common_p(v_flex())
@ -249,14 +285,15 @@ fn render_markdown_table(parsed: &ParsedMarkdownTable, cx: &mut RenderContext) -
fn render_markdown_table_row( fn render_markdown_table_row(
parsed: &ParsedMarkdownTableRow, parsed: &ParsedMarkdownTableRow,
alignments: &Vec<ParsedMarkdownTableAlignment>, alignments: &Vec<ParsedMarkdownTableAlignment>,
max_column_widths: &Vec<f32>,
is_header: bool, is_header: bool,
cx: &mut RenderContext, cx: &mut RenderContext,
) -> AnyElement { ) -> AnyElement {
let mut items = vec![]; let mut items = vec![];
for cell in &parsed.children { for (index, cell) in parsed.children.iter().enumerate() {
let alignment = alignments let alignment = alignments
.get(items.len()) .get(index)
.copied() .copied()
.unwrap_or(ParsedMarkdownTableAlignment::None); .unwrap_or(ParsedMarkdownTableAlignment::None);
@ -268,8 +305,11 @@ fn render_markdown_table_row(
ParsedMarkdownTableAlignment::Right => v_flex().items_end(), ParsedMarkdownTableAlignment::Right => v_flex().items_end(),
}; };
let max_width = max_column_widths.get(index).unwrap_or(&0.0);
let mut cell = container let mut cell = container
.w_full() .w(Length::Definite(relative(*max_width)))
.h_full()
.child(contents) .child(contents)
.px_2() .px_2()
.py_1() .py_1()