diff options
| author | Laurenz <laurmaedje@gmail.com> | 2025-07-09 10:16:36 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-07-09 08:16:36 +0000 |
| commit | e5e1dcd9c01341d2cd3473ac94a70223d5966086 (patch) | |
| tree | d648efad9463cb10270d55ba35210eeb1e91ee22 /crates/typst-library/src/model/table.rs | |
| parent | 0a3c6939dd274f40672484695d909c2cc0d0d755 (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.rs | 133 |
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( |
