From b2b2593832cc17282f3e41fa54dcb2923cbf7354 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Michael=20F=C3=A4rber?= <01mf02@gmail.com>
Date: Tue, 21 Jan 2025 11:07:52 +0100
Subject: [PATCH] Print cells in table header as `
` as opposed to ` | `.
---
crates/typst-library/src/model/table.rs | 90 ++++++++++++++-----------
1 file changed, 52 insertions(+), 38 deletions(-)
diff --git a/crates/typst-library/src/model/table.rs b/crates/typst-library/src/model/table.rs
index bdcdf68e7..ba7924422 100644
--- a/crates/typst-library/src/model/table.rs
+++ b/crates/typst-library/src/model/table.rs
@@ -9,9 +9,9 @@ use crate::foundations::{
cast, elem, scope, Content, NativeElement, Packed, Show, Smart, StyleChain,
TargetElem,
};
-use crate::html::{tag, HtmlAttr, HtmlAttrs, HtmlElem};
+use crate::html::{tag, HtmlAttr, HtmlAttrs, HtmlElem, HtmlTag};
use crate::introspection::Locator;
-use crate::layout::grid::resolve::table_to_cellgrid;
+use crate::layout::grid::resolve::{table_to_cellgrid, Cell, CellGrid, Entry};
use crate::layout::{
show_grid_cell, Abs, Alignment, BlockElem, Celled, GridCell, GridFooter, GridHLine,
GridHeader, GridVLine, Length, OuterHAlignment, OuterVAlignment, Rel, Sides,
@@ -262,34 +262,61 @@ impl TableElem {
type TableFooter;
}
+fn show_cell_html(tag: HtmlTag, cell: &Cell, styles: StyleChain) -> Content {
+ let cell = cell.body.clone();
+ let Some(cell) = cell.to_packed::() else { return cell };
+ let mut attrs = HtmlAttrs::default();
+ let span = |n: NonZeroUsize| (n != NonZeroUsize::MIN).then(|| n.to_string());
+ if let Some(colspan) = span(cell.colspan(styles)) {
+ attrs.push(HtmlAttr::constant("colspan"), colspan);
+ }
+ if let Some(rowspan) = span(cell.rowspan(styles)) {
+ attrs.push(HtmlAttr::constant("rowspan"), rowspan);
+ }
+ HtmlElem::new(tag)
+ .with_body(Some(cell.body.clone()))
+ .with_attrs(attrs)
+ .pack()
+ .spanned(cell.span())
+}
+
+fn show_cellgrid_html(grid: CellGrid, styles: StyleChain) -> Content {
+ let elem = |tag, body| HtmlElem::new(tag).with_body(Some(body)).pack();
+ let mut rows: Vec<_> = grid.entries.chunks(grid.cols.len()).collect();
+
+ let tr = |tag, row: &[Entry]| {
+ let row = row
+ .iter()
+ .flat_map(|entry| entry.as_cell())
+ .map(|cell| show_cell_html(tag, cell, styles));
+ elem(tag::tr, Content::sequence(row))
+ };
+
+ let footer = grid.footer.map(|ft| {
+ let rows = rows.drain(ft.unwrap().start..);
+ elem(tag::tfoot, Content::sequence(rows.map(|row| tr(tag::td, row))))
+ });
+ let header = grid.header.map(|hd| {
+ let rows = rows.drain(..hd.unwrap().end);
+ elem(tag::thead, Content::sequence(rows.map(|row| tr(tag::th, row))))
+ });
+
+ let mut body = Content::sequence(rows.into_iter().map(|row| tr(tag::td, row)));
+ if header.is_some() || footer.is_some() {
+ body = elem(tag::tbody, body);
+ }
+
+ let content = header.into_iter().chain(core::iter::once(body)).chain(footer);
+ elem(tag::table, Content::sequence(content))
+}
+
impl Show for Packed {
fn show(&self, engine: &mut Engine, styles: StyleChain) -> SourceResult {
Ok(if TargetElem::target_in(styles).is_html() {
// 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| entry.as_cell());
- elem(tag::tr, Content::sequence(row.map(|cell| cell.body.clone())))
- });
- let mut rows: Vec<_> = rows.collect();
-
- let footer = grid.footer.map(|ft| {
- elem(tag::tfoot, Content::sequence(rows.drain(ft.unwrap().start..)))
- });
- let header = grid.header.map(|hd| {
- elem(tag::thead, Content::sequence(rows.drain(..hd.unwrap().end)))
- });
-
- let mut body = Content::sequence(rows);
- if header.is_some() || footer.is_some() {
- body = elem(tag::tbody, body);
- }
-
- let content = header.into_iter().chain(core::iter::once(body)).chain(footer);
- elem(tag::table, Content::sequence(content))
+ show_cellgrid_html(table_to_cellgrid(self, engine, locator, styles)?, styles)
} else {
BlockElem::multi_layouter(self.clone(), engine.routines.layout_table).pack()
}
@@ -737,20 +764,7 @@ cast! {
impl Show for Packed {
fn show(&self, _engine: &mut Engine, styles: StyleChain) -> SourceResult {
- if TargetElem::target_in(styles).is_html() {
- let mut attrs = HtmlAttrs::default();
- let span = |n: NonZeroUsize| (n != NonZeroUsize::MIN).then(|| n.to_string());
- if let Some(colspan) = span(self.colspan(styles)) {
- attrs.push(HtmlAttr::constant("colspan"), colspan);
- }
- if let Some(rowspan) = span(self.rowspan(styles)) {
- attrs.push(HtmlAttr::constant("rowspan"), rowspan);
- }
- let body = Some(self.body.clone());
- Ok(HtmlElem::new(tag::td).with_body(body).with_attrs(attrs).pack())
- } else {
- show_grid_cell(self.body.clone(), self.inset(styles), self.align(styles))
- }
+ show_grid_cell(self.body.clone(), self.inset(styles), self.align(styles))
}
}
|