@@ -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| [ ] |";