diff --git a/crates/engine/src/clip_html.rs b/crates/engine/src/clip_html.rs
index ca7667694..d208155df 100644
--- a/crates/engine/src/clip_html.rs
+++ b/crates/engine/src/clip_html.rs
@@ -11,6 +11,11 @@
const MAX_HTML: usize = 16 * 1024 * 1024;
/// Widest `colspan` honoured (the sheet's column count).
const MAX_SPAN: usize = gridcraft_core::MAX_COLS as usize;
+/// Tallest `rowspan` honoured (the sheet's row count).
+const MAX_ROW_SPAN: usize = gridcraft_core::MAX_ROWS as usize;
+/// Most cells, span placeholders included, one paste reads from the HTML. Past it the rest of the
+/// table is ignored: the HTML only refines cells of the tab-separated text, which stays the source.
+const MAX_HTML_CELLS: usize = 1_000_000;
/// One table cell: its visible text and the number the source recorded for it, if any.
#[derive(Clone, Debug, Default, PartialEq)]
@@ -19,25 +24,28 @@ pub(crate) struct HtmlCell {
pub num: Option,
}
-/// The cells of the first table in `html`, row by row; a cell spanning columns is followed by
-/// empty cells so positions line up with the tab-separated text. Empty when there is no table.
-pub(crate) fn table_cells(html: &str) -> Vec> {
- let mut rows: Vec> = Vec::new();
+/// The cells of the first table in `html`, row by row, read no further than `max_rows` rows of
+/// `max_cols` cells (the pasted text's shape, itself clamped to the sheet) and [`MAX_HTML_CELLS`]
+/// in all. A cell spanning columns is followed by empty cells, and a column covered by a `rowspan`
+/// from above holds an empty cell, so positions line up with the tab-separated text. Empty when
+/// there is no table.
+pub(crate) fn table_cells(html: &str, max_rows: usize, max_cols: usize) -> Vec> {
+ let mut grid = Grid::new(max_rows, max_cols);
if html.len() > MAX_HTML {
- return rows;
+ return grid.rows;
}
- let mut cell: Option<(HtmlCell, usize)> = None;
+ let mut cell: Option = None;
let mut in_table = false;
let mut rest = html;
- while !rest.is_empty() {
+ while !rest.is_empty() && !grid.full {
let Some(lt) = rest.find('<') else {
- if let Some((c, _)) = cell.as_mut() {
- c.text.push_str(rest);
+ if let Some(c) = cell.as_mut() {
+ c.cell.text.push_str(rest);
}
break;
};
- if let Some((c, _)) = cell.as_mut() {
- c.text.push_str(rest.get(..lt).unwrap_or_default());
+ if let Some(c) = cell.as_mut() {
+ c.cell.text.push_str(rest.get(..lt).unwrap_or_default());
}
rest = rest.get(lt..).unwrap_or_default();
if let Some(after) = rest.strip_prefix("| Rp10,000.00 | Name |
| 2.50 & up | x |