mirror of
https://github.com/zed-industries/zed.git
synced 2026-06-01 03:14:56 +07:00
markdown: Fix table header alignment and apply alignment to cell content (#56179)
Follow up: https://github.com/zed-industries/zed/pull/53465 For Markdown tables, headers are now always centered (ignoring column alignment), matching standard Markdown rendering behavior. For HTML tables, headers default to center but respect explicit `align` attributes. This also propagates alignment to paragraphs and headings inside table cells, not just the cell container itself. Release Notes: - N/A
This commit is contained in:
parent
b8c3167a9d
commit
6151889ddf
2 changed files with 114 additions and 9 deletions
|
|
@ -867,6 +867,51 @@ mod tests {
|
|||
assert_eq!(table.body[1].columns.len(), 2);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parses_html_table_th_defaults_to_center() {
|
||||
let html = "<table><thead><tr><th>H1</th><th>H2</th></tr></thead><tbody><tr><td>a</td><td>b</td></tr></tbody></table>";
|
||||
let parsed = parse_html_block(html, 0..html.len()).unwrap();
|
||||
|
||||
let ParsedHtmlElement::Table(table) = &parsed.children[0] else {
|
||||
panic!("expected table");
|
||||
};
|
||||
|
||||
assert_eq!(table.header.len(), 1);
|
||||
for column in &table.header[0].columns {
|
||||
assert!(column.is_header);
|
||||
assert_eq!(column.alignment, Alignment::Center);
|
||||
}
|
||||
|
||||
for column in &table.body[0].columns {
|
||||
assert!(!column.is_header);
|
||||
assert_eq!(column.alignment, Alignment::None);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parses_html_table_explicit_align_attribute_preserved() {
|
||||
let html = "<table>\
|
||||
<thead><tr>\
|
||||
<th align=\"right\">H1</th>\
|
||||
<th align=\"left\">H2</th>\
|
||||
</tr></thead>\
|
||||
<tbody><tr>\
|
||||
<td align=\"center\">a</td>\
|
||||
<td align=\"right\">b</td>\
|
||||
</tr></tbody>\
|
||||
</table>";
|
||||
let parsed = parse_html_block(html, 0..html.len()).unwrap();
|
||||
|
||||
let ParsedHtmlElement::Table(table) = &parsed.children[0] else {
|
||||
panic!("expected table");
|
||||
};
|
||||
|
||||
assert_eq!(table.header[0].columns[0].alignment, Alignment::Right);
|
||||
assert_eq!(table.header[0].columns[1].alignment, Alignment::Left);
|
||||
assert_eq!(table.body[0].columns[0].alignment, Alignment::Center);
|
||||
assert_eq!(table.body[0].columns[1].alignment, Alignment::Right);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parses_html_list_as_explicit_list_node() {
|
||||
let parsed = parse_html_block(
|
||||
|
|
|
|||
|
|
@ -1730,15 +1730,28 @@ impl Element for MarkdownElement {
|
|||
}
|
||||
}
|
||||
MarkdownTag::Paragraph => {
|
||||
self.push_markdown_paragraph(&mut builder, range, markdown_end, None);
|
||||
let text_align_override = builder
|
||||
.table
|
||||
.current_cell_alignment()
|
||||
.and_then(alignment_to_text_align);
|
||||
self.push_markdown_paragraph(
|
||||
&mut builder,
|
||||
range,
|
||||
markdown_end,
|
||||
text_align_override,
|
||||
);
|
||||
}
|
||||
MarkdownTag::Heading { level, .. } => {
|
||||
let text_align_override = builder
|
||||
.table
|
||||
.current_cell_alignment()
|
||||
.and_then(alignment_to_text_align);
|
||||
self.push_markdown_heading(
|
||||
&mut builder,
|
||||
*level,
|
||||
range,
|
||||
markdown_end,
|
||||
None,
|
||||
text_align_override,
|
||||
);
|
||||
}
|
||||
MarkdownTag::BlockQuote(kind) => {
|
||||
|
|
@ -2000,13 +2013,10 @@ impl Element for MarkdownElement {
|
|||
let is_header = builder.table.in_head;
|
||||
let row_index = builder.table.row_index;
|
||||
let col_index = builder.table.col_index;
|
||||
let alignment = builder.table.alignments.get(col_index).copied();
|
||||
let text_align = match alignment {
|
||||
Some(Alignment::Left) => TextAlign::Left,
|
||||
Some(Alignment::Center) => TextAlign::Center,
|
||||
Some(Alignment::Right) => TextAlign::Right,
|
||||
_ => self.style.base_text_style.text_align,
|
||||
};
|
||||
let alignment = builder.table.current_cell_alignment();
|
||||
let text_align = alignment
|
||||
.and_then(alignment_to_text_align)
|
||||
.unwrap_or(self.style.base_text_style.text_align);
|
||||
|
||||
let mut cell_div = div()
|
||||
.flex()
|
||||
|
|
@ -2445,6 +2455,25 @@ impl TableState {
|
|||
fn end_cell(&mut self) {
|
||||
self.col_index += 1;
|
||||
}
|
||||
|
||||
fn current_cell_alignment(&self) -> Option<Alignment> {
|
||||
if self.alignments.is_empty() {
|
||||
return None;
|
||||
}
|
||||
if self.in_head {
|
||||
return Some(Alignment::Center);
|
||||
}
|
||||
self.alignments.get(self.col_index).copied()
|
||||
}
|
||||
}
|
||||
|
||||
fn alignment_to_text_align(alignment: Alignment) -> Option<TextAlign> {
|
||||
match alignment {
|
||||
Alignment::Left => Some(TextAlign::Left),
|
||||
Alignment::Center => Some(TextAlign::Center),
|
||||
Alignment::Right => Some(TextAlign::Right),
|
||||
Alignment::None => None,
|
||||
}
|
||||
}
|
||||
|
||||
struct MarkdownElementBuilder {
|
||||
|
|
@ -3474,6 +3503,37 @@ mod tests {
|
|||
assert_eq!(second_word, "b");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_table_state_current_cell_alignment_centers_headers() {
|
||||
let mut table = TableState::default();
|
||||
table.start(vec![Alignment::Left, Alignment::Right, Alignment::None]);
|
||||
|
||||
table.start_head();
|
||||
for _ in 0..3 {
|
||||
assert_eq!(table.current_cell_alignment(), Some(Alignment::Center));
|
||||
table.end_cell();
|
||||
}
|
||||
|
||||
table.end_head();
|
||||
table.start_row();
|
||||
assert_eq!(table.current_cell_alignment(), Some(Alignment::Left));
|
||||
table.end_cell();
|
||||
assert_eq!(table.current_cell_alignment(), Some(Alignment::Right));
|
||||
table.end_cell();
|
||||
assert_eq!(table.current_cell_alignment(), Some(Alignment::None));
|
||||
table.end_cell();
|
||||
table.end_row();
|
||||
|
||||
table.end();
|
||||
assert_eq!(table.current_cell_alignment(), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_table_state_current_cell_alignment_outside_table() {
|
||||
let table = TableState::default();
|
||||
assert_eq!(table.current_cell_alignment(), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_table_checkbox_detection() {
|
||||
let md = "| Done |\n|------|\n| [x] |\n| [ ] |";
|
||||
|
|
|
|||
Loading…
Reference in a new issue