diff --git a/crates/crw-renderer/src/lib.rs b/crates/crw-renderer/src/lib.rs
index 762a279d..f16ff0d6 100644
--- a/crates/crw-renderer/src/lib.rs
+++ b/crates/crw-renderer/src/lib.rs
@@ -4475,6 +4475,60 @@ impl FallbackRenderer {
}
}
+/// Byte offset of the document's real `
Option {
+ const SKIPPED: [&str; 4] = ["script", "style", "template", "textarea"];
+ let b = html.as_bytes();
+ // `name` at `b[at..]`, case-insensitive, followed by a tag-name boundary.
+ let tag_at = |at: usize, name: &str| {
+ b.get(at..at + name.len())
+ .is_some_and(|w| w.eq_ignore_ascii_case(name.as_bytes()))
+ && matches!(
+ b.get(at + name.len()),
+ None | Some(b'>' | b'/' | b' ' | b'\t' | b'\n' | b'\r' | b'\x0c')
+ )
+ };
+ let find_from = |from: usize, needle: &[u8]| {
+ b[from..]
+ .windows(needle.len())
+ .position(|w| w.eq_ignore_ascii_case(needle))
+ .map(|i| from + i)
+ };
+ let mut i = 0;
+ while let Some(off) = b[i..].iter().position(|&c| c == b'<') {
+ let at = i + off;
+ if b[at..].starts_with(b"` and `` close too.
+ i = find_from(at + 2, b"-->")? + 3;
+ } else if tag_at(at + 1, "body") {
+ return Some(at);
+ } else if let Some(name) = SKIPPED.iter().find(|n| tag_at(at + 1, n)) {
+ // An unterminated raw-text element swallows the rest of the document.
+ i = find_from(at + 1 + name.len(), format!("{name}").as_bytes())? + 2;
+ } else if b.get(at + 1).is_some_and(u8::is_ascii_alphabetic) {
+ // Step over the whole tag: a `` into an iframe
+ // made the real body measure 0 characters, so a fully loaded page was
+ // classified as a thin render and escalated to the next tier.
+ //
+ // When the scan finds nothing (an unterminated comment or raw-text element
+ // swallowed the rest of the document) it falls back to the plain find, which
+ // is what this function did before.
+ let body = if let Some(start) = find_body_open(html).or_else(|| html.find("').map(|i| start + i + 1).unwrap_or(0);
let end = html[start..]
.find("")
@@ -4552,6 +4617,71 @@ mod tests {
assert!(html_body_text_len(html) > 0);
}
+ #[test]
+ fn body_text_len_ignores_a_body_tag_inside_a_head_script() {
+ // An iframe-writing loader in carries a literal `...`
+ // pair. Locating the opening tag with a plain find measured the 0
+ // characters between that pair instead of the real body.
+ let html = concat!(
+ "",
+ "real content here
"
+ );
+ assert_eq!(html_body_text_len(html), 17);
+ }
+
+ #[test]
+ fn find_body_open_skips_raw_text_and_comments() {
+ let real = "x
";
+ for skipped in [
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ ] {
+ let html = format!("{skipped}{real}");
+ assert_eq!(find_body_open(&html), html.find(""));
+ }
+
+ #[test]
+ fn find_body_open_gives_up_on_an_unterminated_raw_text_element() {
+ // Nothing after an unclosed "
+ );
+ assert_eq!(find_body_open(html), html.find("", ""] {
+ let html = format!("{empty}x");
+ assert_eq!(find_body_open(&html), html.find("