summaryrefslogtreecommitdiff
path: root/crates/typst-library/src/model/table.rs
diff options
context:
space:
mode:
authorLaurenz <laurmaedje@gmail.com>2025-07-09 10:16:36 +0200
committerGitHub <noreply@github.com>2025-07-09 08:16:36 +0000
commite5e1dcd9c01341d2cd3473ac94a70223d5966086 (patch)
treed648efad9463cb10270d55ba35210eeb1e91ee22 /crates/typst-library/src/model/table.rs
parent0a3c6939dd274f40672484695d909c2cc0d0d755 (diff)
Target-specific native show rules (#6569)
Diffstat (limited to 'crates/typst-library/src/model/table.rs')
-rw-r--r--crates/typst-library/src/model/table.rs133
1 files changed, 6 insertions, 127 deletions
diff --git a/crates/typst-library/src/model/table.rs b/crates/typst-library/src/model/table.rs
index 72c5acc5..e46efc81 100644
--- a/crates/typst-library/src/model/table.rs
+++ b/crates/typst-library/src/model/table.rs
@@ -3,19 +3,11 @@ use std::sync::Arc;
use typst_utils::NonZeroExt;
-use crate::diag::{bail, HintedStrResult, HintedString, SourceResult};
-use crate::engine::Engine;
-use crate::foundations::{
- cast, elem, scope, Content, NativeElement, Packed, Show, Smart, StyleChain,
- TargetElem,
-};
-use crate::html::{attr, tag, HtmlAttrs, HtmlElem, HtmlTag};
-use crate::introspection::Locator;
-use crate::layout::grid::resolve::{table_to_cellgrid, Cell, CellGrid, Entry};
+use crate::diag::{bail, HintedStrResult, HintedString};
+use crate::foundations::{cast, elem, scope, Content, Packed, Smart};
use crate::layout::{
- show_grid_cell, Abs, Alignment, BlockElem, Celled, GridCell, GridFooter, GridHLine,
- GridHeader, GridVLine, Length, OuterHAlignment, OuterVAlignment, Rel, Sides,
- TrackSizings,
+ Abs, Alignment, Celled, GridCell, GridFooter, GridHLine, GridHeader, GridVLine,
+ Length, OuterHAlignment, OuterVAlignment, Rel, Sides, TrackSizings,
};
use crate::model::Figurable;
use crate::text::LocalName;
@@ -121,7 +113,7 @@ use crate::visualize::{Paint, Stroke};
/// [Robert], b, a, b,
/// )
/// ```
-#[elem(scope, Show, LocalName, Figurable)]
+#[elem(scope, LocalName, Figurable)]
pub struct TableElem {
/// The column sizes. See the [grid documentation]($grid) for more
/// information on track sizing.
@@ -255,113 +247,6 @@ 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::<TableCell>() 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.get(styles)) {
- attrs.push(attr::colspan, colspan);
- }
- if let Some(rowspan) = span(cell.rowspan.get(styles)) {
- attrs.push(attr::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.non_gutter_column_count()).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))
- };
-
- // TODO(subfooters): similarly to headers, take consecutive footers from
- // the end for 'tfoot'.
- let footer = grid.footer.map(|ft| {
- let rows = rows.drain(ft.start..);
- elem(tag::tfoot, Content::sequence(rows.map(|row| tr(tag::td, row))))
- });
-
- // Store all consecutive headers at the start in 'thead'. All remaining
- // headers are just 'th' rows across the table body.
- let mut consecutive_header_end = 0;
- let first_mid_table_header = grid
- .headers
- .iter()
- .take_while(|hd| {
- let is_consecutive = hd.range.start == consecutive_header_end;
- consecutive_header_end = hd.range.end;
-
- is_consecutive
- })
- .count();
-
- let (y_offset, header) = if first_mid_table_header > 0 {
- let removed_header_rows =
- grid.headers.get(first_mid_table_header - 1).unwrap().range.end;
- let rows = rows.drain(..removed_header_rows);
-
- (
- removed_header_rows,
- Some(elem(tag::thead, Content::sequence(rows.map(|row| tr(tag::th, row))))),
- )
- } else {
- (0, None)
- };
-
- // TODO: Consider improving accessibility properties of multi-level headers
- // inside tables in the future, e.g. indicating which columns they are
- // relative to and so on. See also:
- // https://www.w3.org/WAI/tutorials/tables/multi-level/
- let mut next_header = first_mid_table_header;
- let mut body =
- Content::sequence(rows.into_iter().enumerate().map(|(relative_y, row)| {
- let y = relative_y + y_offset;
- if let Some(current_header) =
- grid.headers.get(next_header).filter(|h| h.range.contains(&y))
- {
- if y + 1 == current_header.range.end {
- next_header += 1;
- }
-
- tr(tag::th, row)
- } else {
- 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<TableElem> {
- fn show(&self, engine: &mut Engine, styles: StyleChain) -> SourceResult<Content> {
- Ok(if styles.get(TargetElem::target).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();
- show_cellgrid_html(table_to_cellgrid(self, engine, locator, styles)?, styles)
- } else {
- BlockElem::multi_layouter(self.clone(), engine.routines.layout_table).pack()
- }
- .spanned(self.span()))
- }
-}
-
impl LocalName for Packed<TableElem> {
const KEY: &'static str = "table";
}
@@ -761,7 +646,7 @@ pub struct TableVLine {
/// [Vikram], [49], [Perseverance],
/// )
/// ```
-#[elem(name = "cell", title = "Table Cell", Show)]
+#[elem(name = "cell", title = "Table Cell")]
pub struct TableCell {
/// The cell's body.
#[required]
@@ -808,12 +693,6 @@ cast! {
v: Content => v.into(),
}
-impl Show for Packed<TableCell> {
- fn show(&self, _engine: &mut Engine, styles: StyleChain) -> SourceResult<Content> {
- show_grid_cell(self.body.clone(), self.inset.get(styles), self.align.get(styles))
- }
-}
-
impl Default for Packed<TableCell> {
fn default() -> Self {
Packed::new(