Markdown images in descriptions, gated and framed

Images already flowed through render_inline_markdown ungated; they
now take the same scheme gate as links (https or same-origin only -
no data:, no plain http) and render as full-width framed figures in
alternative, feature, and item-card descriptions. Carries whole-site
imagery for content-driven instances (westra).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Y42TyF8Zu7NGRR2893vNcZ
This commit is contained in:
Bendik Aagaard Lynghaug
2026-09-01 16:46:56 +02:00
co-authored by Claude Fable 5
parent 756818cacd
commit 7f10ba20d3
2 changed files with 33 additions and 0 deletions
+21
View File
@@ -199,6 +199,18 @@ pub fn render_inline_markdown(text: &str) -> String {
in_link -= 1;
None
}
// Images take the same gate as links: https or same-origin
// only - no data:, no plain http.
Event::Start(Tag::Image { dest_url, .. })
if !(dest_url.starts_with("https://") || dest_url.starts_with('/')) =>
{
in_link += 1;
None
}
Event::End(TagEnd::Image) if in_link > 0 => {
in_link -= 1;
None
}
other => Some(other),
});
let mut out = String::new();
@@ -2026,6 +2038,15 @@ alternatives:
fn markdown_drops_html_and_unsafe_links() {
assert_eq!(render_inline_markdown("x <script>y</script> z"), "x y z");
assert_eq!(render_inline_markdown("[bad](javascript:alert(1))"), "bad");
assert_eq!(
render_inline_markdown("![site](https://x.no/a.jpg)"),
"<img src=\"https://x.no/a.jpg\" alt=\"site\" />"
);
assert_eq!(render_inline_markdown("![x](data:image/png;base64,AA)"), "");
assert_eq!(
render_inline_markdown("![local](/images/a.jpg)"),
"<img src=\"/images/a.jpg\" alt=\"local\" />"
);
assert_eq!(render_inline_markdown("[ok](/shape)"), "<a href=\"/shape\">ok</a>");
assert_eq!(render_inline_markdown("[mail](mailto:bl@uhhm.no)"), "<a href=\"mailto:bl@uhhm.no\">mail</a>");
}