diff --git a/crates/idx-core/src/api/ipot/parse.rs b/crates/idx-core/src/api/ipot/parse.rs index 1b97ef1..516d4ae 100644 --- a/crates/idx-core/src/api/ipot/parse.rs +++ b/crates/idx-core/src/api/ipot/parse.rs @@ -131,6 +131,25 @@ fn broker_kind(class: Option<&str>) -> Option { } } +/// Whether `body` (lowercased) holds only `tr`, `td` and `span` tags, each +/// closed before the next `<`: no comments, other elements, or markup +/// inside attributes that the row checks could miscount. +fn plain_markup(body: &str) -> bool { + body.match_indices('<').all(|(at, _)| { + let tag = &body[at + 1..]; + let Some(end) = tag.find('>') else { + return false; + }; + let inner = &tag[..end]; + let name: String = inner + .trim_start_matches('/') + .chars() + .take_while(char::is_ascii_alphanumeric) + .collect(); + !inner.contains('<') && matches!(name.as_str(), "tr" | "td" | "span") + }) +} + /// The `MM/DD/YYYY` value of the input with this id. fn input_date(html: &str, id: &str) -> Option { let at = html.find(&format!("id=\"{id}\""))?; @@ -159,9 +178,12 @@ pub fn parse_broker_summary(html: &str) -> Result { .find("") .map(|len| (start + "".len(), start + len)) }); - let Some((body_start, body_end)) = body.filter(|_| lower.matches("", "") .replace("