diff --git a/crates/benilla-ui/src/script/simplehtml/mod.rs b/crates/benilla-ui/src/script/simplehtml/mod.rs
index 1a6513cf..1e3772d0 100644
--- a/crates/benilla-ui/src/script/simplehtml/mod.rs
+++ b/crates/benilla-ui/src/script/simplehtml/mod.rs
@@ -288,6 +288,11 @@ fn build(model: &mut Model, fh: FrameHandle, blocks: &[Block]) {
let anchors = point
.map(|p| vec![anchor_for(prev_block, frame_id, p, next_y)])
.unwrap_or_default();
+ // `src=""` names no file, as `""` does on every texture setter (`0x770200`).
+ // Kept, it was the one path left in the UI that could put an empty string where a
+ // texture path goes, and the renderer then searched the patch chain for a nameless
+ // file and warned about a miss it could name neither the file nor the asker of.
+ let src = src.clone().filter(|p| !p.is_empty());
model.region_data.insert(
rh,
RegionData {
diff --git a/crates/benilla-ui/src/script/tests/simplehtml.rs b/crates/benilla-ui/src/script/tests/simplehtml.rs
index 0da4387e..ed8f49b4 100644
--- a/crates/benilla-ui/src/script/tests/simplehtml.rs
+++ b/crates/benilla-ui/src/script/tests/simplehtml.rs
@@ -552,6 +552,54 @@ fn the_books_unsized_crest_is_its_arts_texel_square_not_the_whole_page() {
);
}
+/// `
` names no file. `""` clears on every texture setter here, as the reference's path
+/// arm treats it like nil (`0x770200`), but the SimpleHTML image path stored the empty string: the
+/// region then carried `texture: Some("")`, the resolve asked the size probe for a nameless file,
+/// and the renderer searched the patch chain and logged `texture miss: ''` — a defect-shaped
+/// warning naming neither a file nor an asker. It was the last unguarded route in the UI.
+#[test]
+fn an_img_with_an_empty_src_names_no_file() {
+ use std::cell::RefCell;
+ use std::rc::Rc;
+
+ let asked: Rc>> = Rc::new(RefCell::new(Vec::new()));
+ let seen = Rc::clone(&asked);
+ let mut s = script();
+ s.set_texture_size_probe(Box::new(move |path| {
+ seen.borrow_mut().push(path.to_string());
+ Some((64, 48))
+ }));
+ page(&s);
+ s.run(
+ r#"Page:SetText("a
" ..
+ "
" ..
+ "b
")"#,
+ )
+ .unwrap();
+
+ let b = blocks(&s, "Page");
+ assert_eq!(
+ b.len(),
+ 3,
+ "the image block is still made, art or none: {b:?}"
+ );
+ assert!(
+ b.iter().all(|x| x.texture.as_deref() != Some("")),
+ "a nameless file was stored as this image's texture: {b:?}"
+ );
+ assert!(
+ !asked.borrow().iter().any(|p| p.is_empty()),
+ "the patch chain was searched for a nameless file: {:?}",
+ asked.borrow()
+ );
+ // And nothing is reserved in the flow for art that does not exist.
+ assert_eq!(
+ b[2].anchor.unwrap(),
+ (Point::TopLeft, Point::BottomLeft, 0.0, 0.0, Rel::Block(0)),
+ "an image with no art reserved height anyway"
+ );
+}
+
/// An unfloated image reserves `GetHeight()` in the flow (`0x78ad07`), its art's texel height when
/// it has no `height=`; a floated one reserves nothing, so text runs over it in the reference too.
#[test]