diff --git a/crates/typst-library/src/model/table.rs b/crates/typst-library/src/model/table.rs index c619f294b..715a09655 100644 --- a/crates/typst-library/src/model/table.rs +++ b/crates/typst-library/src/model/table.rs @@ -268,14 +268,37 @@ impl Show for Packed { // TODO: This is a hack, it is not clear whether the locator is actually used by HTML. // How can we find out whether locator is actually used? let locator = Locator::root(); + let elem = |tag, body| HtmlElem::new(tag).with_body(Some(body)).pack(); let grid = table_to_cellgrid(self, engine, locator, styles)?; let rows = grid.entries.chunks(grid.cols.len()).map(|row| { - let row = - row.iter().flat_map(|entry| Some(entry.as_cell()?.body.clone())); - HtmlElem::new(tag::tr).with_body(Some(Content::sequence(row))).pack() + let row = row.iter().flat_map(|entry| entry.as_cell()); + elem(tag::tr, Content::sequence(row.map(|cell| cell.body.clone()))) }); - let content = Content::sequence(rows); - HtmlElem::new(tag::table).with_body(Some(content)).pack() + let mut rows: Vec<_> = rows.collect(); + + let footer_start = + grid.footer.map_or(rows.len(), |footer| footer.unwrap().start); + let header_end = grid.header.map_or(0, |footer| footer.unwrap().end); + let footer: Vec<_> = rows.drain(footer_start..).collect(); + let body: Vec<_> = rows.drain(header_end..).collect(); + let header = rows; + + let mut content = Vec::new(); + + let only_body = header.is_empty() && footer.is_empty(); + if !header.is_empty() { + content.push(elem(tag::thead, Content::sequence(header))); + } + if only_body { + content = body; + } else { + content.push(elem(tag::tbody, Content::sequence(body))); + } + if !footer.is_empty() { + content.push(elem(tag::tfoot, Content::sequence(footer))); + } + + elem(tag::table, Content::sequence(content)) } else { BlockElem::multi_layouter(self.clone(), engine.routines.layout_table).pack() } diff --git a/tests/ref/html/basic-table.html b/tests/ref/html/basic-table.html index b1a18b648..5ceffa976 100644 --- a/tests/ref/html/basic-table.html +++ b/tests/ref/html/basic-table.html @@ -5,6 +5,6 @@ -
Thefirstrow
FooBazBar
12
34
+
Thefirstand
thesecondrow
FooBazBar
12
34
Thelastrow
diff --git a/tests/suite/layout/grid/html.typ b/tests/suite/layout/grid/html.typ index 04835533c..2a7dfc2ce 100644 --- a/tests/suite/layout/grid/html.typ +++ b/tests/suite/layout/grid/html.typ @@ -4,10 +4,13 @@ rows: 3, table.header( - [The], - [first], - [row], - table.hline(stroke: red) + [The], + [first], + [and], + [the], + [second], + [row], + table.hline(stroke: red) ), table.cell(x: 1, rowspan: 2)[Baz], @@ -20,4 +23,10 @@ table.cell(colspan: 2)[3], [4], + + table.footer( + [The], + [last], + [row], + ), )