Skip to content

Commit

Permalink
Merge pull request #92 from jugglerchris/issue_90
Browse files Browse the repository at this point in the history
Handle the colspan=0 case.
  • Loading branch information
jugglerchris authored Nov 5, 2023
2 parents 16dbb93 + baf903d commit cff1ab6
Show file tree
Hide file tree
Showing 2 changed files with 169 additions and 4 deletions.
39 changes: 35 additions & 4 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@ impl RenderTableRow {
/// Count the number of cells in the row.
/// Takes into account colspan.
pub fn num_cells(&self) -> usize {
self.cells.iter().map(|cell| cell.colspan).sum()
self.cells.iter().map(|cell| cell.colspan.max(1)).sum()
}
/// Return an iterator over (column, &cell)s, which
/// takes into account colspan.
Expand Down Expand Up @@ -644,7 +644,7 @@ fn tbody_to_render_tree<'a, 'b, T: Write>(
_err_out: &'b mut T,
) -> TreeMapResult<'a, (), Handle, RenderNode> {
pending(handle, |_, rowchildren| {
let rows = rowchildren
let mut rows = rowchildren
.into_iter()
.flat_map(|rownode| {
if let RenderNodeInfo::TableRow(row, _) = rownode.info {
Expand All @@ -654,7 +654,37 @@ fn tbody_to_render_tree<'a, 'b, T: Write>(
None
}
})
.collect();
.collect::<Vec<_>>();

// Handle colspan=0 by replacing it.
// Get a list of (has_zero_colspan, sum_colspan)
let num_columns =
rows.iter()
.map(|row| {
row.cells()
// Treat the column as having colspan 1 for initial counting.
.map(|cell| (cell.colspan == 0, cell.colspan.max(1)))
.fold((false, 0), |a, b| {
(a.0 || b.0, a.1 + b.1)
})
})
.collect::<Vec<_>>();

let max_columns = num_columns.iter().map(|(_, span)| span).max().unwrap_or(&1);

for (i, &(has_zero, num_cols)) in num_columns.iter().enumerate() {
// Note this won't be sensible if more than one column has colspan=0,
// but that's not very well defined anyway.
if has_zero {
for cell in rows[i].cells_mut() {
if cell.colspan == 0 {
// +1 because we said it had 1 to start with
cell.colspan = max_columns - num_cols + 1;
}
}
}
}

Some(RenderNode::new(RenderNodeInfo::TableBody(rows)))
})
}
Expand Down Expand Up @@ -1377,6 +1407,7 @@ fn render_table_tree<T: Write, D: TextDecorator>(
for cell in row.cells() {
// FIXME: get_size_estimate is still recursive.
let mut estimate = cell.get_size_estimate();

// If the cell has a colspan>1, then spread its size between the
// columns.
estimate.size /= cell.colspan;
Expand All @@ -1393,7 +1424,7 @@ fn render_table_tree<T: Write, D: TextDecorator>(
+ col_sizes.len().saturating_sub(1);
let width = renderer.width();

let vert_row = min_size > width;
let vert_row = min_size > width || width == 0;

let mut col_widths: Vec<usize> = if !vert_row {
col_sizes
Expand Down
134 changes: 134 additions & 0 deletions src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,78 @@ fn test_colspan() {
);
}

#[test]
fn test_colspan_zero() {
test_html(
br##"
<table>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
</tr>
<tr>
<td colspan="2">12</td>
<td>3</td>
</tr>
<tr>
<td>1</td>
<td colspan="0">23</td>
</tr>
</table>
"##,
r#"─┬─┬─
1│2│3
─┴─┼─
12 │3
─┬─┴─
1│23
─┴───
"#,
12,
);
}

#[test]
fn test_colspan_large() {
test_html(
br##"
<table>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
</tr>
<tr>
<td colspan="2">12</td>
<td>3</td>
</tr>
<tr>
<td>1</td>
<td colspan="99">23</td>
</tr>
</table>
"##,
r#"────────────
1
////////////
2
////////////
3
────────────
12
////////////
3
────────────
1
////////////
23
────────────
"#,
12,
);
}

#[test]
fn test_para() {
assert_eq_str!(from_read(&b"<p>Hello</p>"[..], 10), "Hello\n");
Expand Down Expand Up @@ -1262,6 +1334,68 @@ fn test_empty_cols() {
);
}

#[test]
fn test_empty_table() {
test_html(
br##"
<table></table>
"##,
r#"
"#,
12,
);
}

#[test]
fn test_table_empty_single_row() {
test_html(
br##"
<table><tr></tr></table>
"##,
r#"
"#,
12,
);
}

#[test]
fn test_table_empty_single_row_empty_cell() {
test_html(
br##"
<table><tr><td></td></tr></table>
"##,
r#"
"#,
12,
);
}

#[test]
fn test_renderer_zero_width() {
test_html(
br##"<ul><li><table><tr><td>x</td></tr></table></li></ul>
"##,
// Unfortunately the "x" ends up not being rendered as it doesn't fit.
r#"*
"#,
2,
);
}

#[test]
fn test_ul_tiny_table() {
test_html(
br##"<ul><li><table><tr><td>x</td></tr></table></li></ul>
"##,
r#"* ─
x
"#,
12,
);
}

#[test]
fn test_issue_54_oob() {
test_html(
Expand Down

0 comments on commit cff1ab6

Please sign in to comment.