Skip to content

Commit

Permalink
Merge pull request #172 from jugglerchris/bugfix_171
Browse files Browse the repository at this point in the history
Fix #171
  • Loading branch information
jugglerchris authored Sep 22, 2024
2 parents 5b91835 + e1baf67 commit b902f6b
Show file tree
Hide file tree
Showing 3 changed files with 108 additions and 18 deletions.
48 changes: 47 additions & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ use markup5ever_rcdom::{
};
use std::cell::Cell;
use std::cmp::{max, min};
use std::collections::{BTreeSet, HashMap};
use unicode_width::UnicodeWidthStr;

use std::io;
Expand Down Expand Up @@ -268,7 +269,52 @@ struct RenderTable {

impl RenderTable {
/// Create a new RenderTable with the given rows
fn new(rows: Vec<RenderTableRow>) -> RenderTable {
fn new(mut rows: Vec<RenderTableRow>) -> RenderTable {
// We later on want to allocate a vector sized by the column count,
// but occasionally we see something like colspan="1000000000". We
// handle this by remapping the column ids to the smallest values
// possible.
//
// Tables with no explicit colspan will be unchanged, but if there
// are multiple columns each covered by a single <td> on every row,
// they will be collapsed into a single column. For example:
//
// <td><td colspan=1000><td>
// <td colspan=1000><td><td>
//
// becomes the equivalent:
// <td><td colspan=2><td>
// <td colspan=2><td><td>

// This will include 0 and the index after the last colspan.
let mut col_positions = BTreeSet::new();
col_positions.insert(0);
for row in &rows {
let mut col = 0;
for cell in row.cells() {
col += cell.colspan;
col_positions.insert(col);
}
}

let colmap: HashMap<_, _> = col_positions
.into_iter()
.enumerate()
.map(|(i, pos)| (pos, i))
.collect();

for row in &mut rows {
let mut pos = 0;
let mut mapped_pos = 0;
for cell in row.cells_mut() {
let nextpos = pos + cell.colspan.max(1);
let next_mapped_pos = *colmap.get(&nextpos).unwrap();
cell.colspan = next_mapped_pos - mapped_pos;
pos = nextpos;
mapped_pos = next_mapped_pos;
}
}

let num_columns = rows.iter().map(|r| r.num_cells()).max().unwrap_or(0);
RenderTable {
rows,
Expand Down
5 changes: 3 additions & 2 deletions src/render/text_renderer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -903,14 +903,15 @@ pub(crate) struct SubRenderer<D: TextDecorator> {
pre_depth: usize,
}

impl<D: TextDecorator + Debug> std::fmt::Debug for SubRenderer<D> {
impl<D: TextDecorator> std::fmt::Debug for SubRenderer<D> {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
f.debug_struct("SubRenderer")
.field("width", &self.width)
.field("lines", &self.lines)
.field("decorator", &self.decorator)
//.field("decorator", &self.decorator)
.field("ann_stack", &self.ann_stack)
.field("pre_depth", &self.pre_depth)
.field("wrapping", &self.wrapping)
.finish()
}
}
Expand Down
73 changes: 58 additions & 15 deletions src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -332,21 +332,46 @@ fn test_colspan_large() {
</tr>
</table>
"##,
r#"────────────
1
////////////
2
////////////
3
────────────
12
////////////
3
────────────
1
////////////
23
────────────
// FIXME: The extra long line blow is not ideal
r#"─┬─┬─
1│2│3
─┴─┼─
12 │3
─┬─┴─
1│23
─┴────
"#,
12,
);
}

#[test]
fn test_colspan_larger() {
test_html(
br##"
<table>
<tr>
<td colspan="50">1</td>
<td colspan="50">2</td>
<td colspan="50">3</td>
</tr>
<tr>
<td colspan="100">12</td>
<td colspan="50">3</td>
</tr>
<tr>
<td colspan="50">1</td>
<td colspan="100">23</td>
</tr>
</table>
"##,
r#"─┬─┬─
1│2│3
─┴─┼─
12 │3
─┬─┴─
1│23
─┴───
"#,
12,
);
Expand Down Expand Up @@ -2020,6 +2045,24 @@ fn test_empty_table_in_list() {
);
}

#[test]
fn test_silly_colspan() {
test_html(
br#"
<table>
<tr>
<td colspan="9007199254740991">foo</td.
</tr>
</table>
"#,
r#"───
foo
───
"#,
80,
);
}

#[cfg(feature = "css")]
mod css_tests {
use super::{test_html_coloured, test_html_css, test_html_style};
Expand Down

0 comments on commit b902f6b

Please sign in to comment.