From a78f6ee3bddeb6b4ae56fe1d57cddb01920101be Mon Sep 17 00:00:00 2001 From: Davide Scaini Date: Thu, 16 Apr 2026 10:29:13 +0200 Subject: [PATCH] fix: strip local image refs with spaces/parens in filenames before markdown render --- site/src/components/ActivityDetail.svelte | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/site/src/components/ActivityDetail.svelte b/site/src/components/ActivityDetail.svelte index a0bb7a6..38c98b8 100644 --- a/site/src/components/ActivityDetail.svelte +++ b/site/src/components/ActivityDetail.svelte @@ -70,15 +70,23 @@ $: rawDescription = localDescription || detail?.description || ''; $: descriptionHtml = (() => { if (!rawDescription) return ''; + // Strip local image refs before marked sees them. marked only parses ![alt](url) as an + // image when the URL has no spaces — filenames like "WhatsApp Image 2026.jpg" are left + // as literal text instead. The lazy .*? anchored to the image extension handles filenames + // with spaces and nested parens (e.g. "file(2).jpg") correctly. + const stripped = rawDescription + .replace(/!\[[^\]]*\]\((?!https?:\/\/|\/|data:).*?\.(?:jpe?g|png|gif|webp|bmp|avif|heic)\)/gi, '') + .trim(); + if (!stripped) return ''; const renderer = new marked.Renderer(); - // Local relative images are always shown in the gallery — suppress inline rendering + // Any remaining remote images render inline; local ones (shouldn't exist after strip) are suppressed renderer.image = ({ href, title, text }) => { const isLocal = href && !href.startsWith('http') && !href.startsWith('/') && !href.startsWith('data:'); if (isLocal) return ''; const titleAttr = title ? ` title="${title}"` : ''; return `${text}`; }; - return DOMPurify.sanitize(marked(rawDescription, { renderer }) as string); + return DOMPurify.sanitize(marked(stripped, { renderer }) as string); })(); // Derive image dir from detail_url so multi-user paths resolve correctly.