mirror of
https://github.com/typst/typst
synced 2025-05-14 04:56:26 +08:00
initial html target support
This commit is contained in:
parent
1e3e6167af
commit
07a060a9da
@ -292,18 +292,61 @@ fn show_cellgrid_html(grid: CellGrid, styles: StyleChain) -> Content {
|
||||
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))))
|
||||
});
|
||||
// TODO: Headers and footers in arbitrary positions
|
||||
// Right now, only those at either end are accepted
|
||||
let header = grid.headers.first().filter(|h| h.start == 0).map(|hd| {
|
||||
let rows = rows.drain(..hd.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)));
|
||||
// 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.start == consecutive_header_end;
|
||||
consecutive_header_end = hd.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().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.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);
|
||||
}
|
||||
|
69
tests/ref/html/multi-header-inside-table.html
Normal file
69
tests/ref/html/multi-header-inside-table.html
Normal file
@ -0,0 +1,69 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
</head>
|
||||
<body>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>First</th>
|
||||
<th>Header</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Second</th>
|
||||
<th>Header</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Level 2</th>
|
||||
<th>Header</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Level 3</th>
|
||||
<th>Header</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>Body</td>
|
||||
<td>Cells</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Yet</td>
|
||||
<td>More</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Level 2</th>
|
||||
<th>Header Inside</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Level 3</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Even</td>
|
||||
<td>More</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Body</td>
|
||||
<td>Cells</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>One Last Header</th>
|
||||
<th>For Good Measure</th>
|
||||
</tr>
|
||||
</tbody>
|
||||
<tfoot>
|
||||
<tr>
|
||||
<td>Footer</td>
|
||||
<td>Row</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Ending</td>
|
||||
<td>Table</td>
|
||||
</tr>
|
||||
</tfoot>
|
||||
</table>
|
||||
</body>
|
||||
</html>
|
49
tests/ref/html/multi-header-table.html
Normal file
49
tests/ref/html/multi-header-table.html
Normal file
@ -0,0 +1,49 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
</head>
|
||||
<body>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>First</th>
|
||||
<th>Header</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Second</th>
|
||||
<th>Header</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Level 2</th>
|
||||
<th>Header</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Level 3</th>
|
||||
<th>Header</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>Body</td>
|
||||
<td>Cells</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Yet</td>
|
||||
<td>More</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
<tfoot>
|
||||
<tr>
|
||||
<td>Footer</td>
|
||||
<td>Row</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Ending</td>
|
||||
<td>Table</td>
|
||||
</tr>
|
||||
</tfoot>
|
||||
</table>
|
||||
</body>
|
||||
</html>
|
@ -57,3 +57,78 @@
|
||||
[d], [e], [f],
|
||||
[g], [h], [i]
|
||||
)
|
||||
|
||||
--- multi-header-table html ---
|
||||
#table(
|
||||
columns: 2,
|
||||
|
||||
table.header(
|
||||
[First], [Header]
|
||||
),
|
||||
table.header(
|
||||
[Second], [Header]
|
||||
),
|
||||
table.header(
|
||||
[Level 2], [Header],
|
||||
level: 2,
|
||||
),
|
||||
table.header(
|
||||
[Level 3], [Header],
|
||||
level: 3,
|
||||
),
|
||||
|
||||
[Body], [Cells],
|
||||
[Yet], [More],
|
||||
|
||||
table.footer(
|
||||
[Footer], [Row],
|
||||
[Ending], [Table],
|
||||
),
|
||||
)
|
||||
|
||||
--- multi-header-inside-table html ---
|
||||
#table(
|
||||
columns: 2,
|
||||
|
||||
table.header(
|
||||
[First], [Header]
|
||||
),
|
||||
table.header(
|
||||
[Second], [Header]
|
||||
),
|
||||
table.header(
|
||||
[Level 2], [Header],
|
||||
level: 2,
|
||||
),
|
||||
table.header(
|
||||
[Level 3], [Header],
|
||||
level: 3,
|
||||
),
|
||||
|
||||
[Body], [Cells],
|
||||
[Yet], [More],
|
||||
|
||||
table.header(
|
||||
[Level 2], [Header Inside],
|
||||
level: 2,
|
||||
),
|
||||
table.header(
|
||||
[Level 3],
|
||||
level: 3,
|
||||
),
|
||||
|
||||
[Even], [More],
|
||||
[Body], [Cells],
|
||||
|
||||
table.header(
|
||||
[One Last Header],
|
||||
[For Good Measure],
|
||||
repeat: false,
|
||||
level: 4,
|
||||
),
|
||||
|
||||
table.footer(
|
||||
[Footer], [Row],
|
||||
[Ending], [Table],
|
||||
),
|
||||
)
|
||||
|
Loading…
x
Reference in New Issue
Block a user