From cfdd8d27443f467c7b0dd1606911e95247f666cb Mon Sep 17 00:00:00 2001 From: Davide Scaini Date: Thu, 16 Apr 2026 10:19:32 +0200 Subject: [PATCH] fix: image refs in description and broken gallery URLs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - EditDrawer: stop auto-inserting ![filename](...) into description on upload — images are tracked via custom.images; the refs only cluttered the textarea. Strip any pre-existing refs on load so old sidecars are also cleaned up when the drawer is opened. - ActivityDetail: imageBase now treats detail_url that starts with '/' as already-absolute (same fix pattern as track_url / detail_url); was prepending ${base}data/ on top of /data/... → double path. --- site/src/components/ActivityDetail.svelte | 5 +++-- site/src/components/EditDrawer.svelte | 9 ++------- 2 files changed, 5 insertions(+), 9 deletions(-) diff --git a/site/src/components/ActivityDetail.svelte b/site/src/components/ActivityDetail.svelte index c9bf3ed..a0bb7a6 100644 --- a/site/src/components/ActivityDetail.svelte +++ b/site/src/components/ActivityDetail.svelte @@ -82,10 +82,11 @@ })(); // Derive image dir from detail_url so multi-user paths resolve correctly. - // "dave/_merged/activities/foo.json" → "/data/dave/_merged/activities/images/{id}/" + // Relative: "dave/_merged/activities/foo.json" → "/data/dave/_merged/activities/images/{id}/" + // Absolute: "/data/dave/_merged/activities/foo.json" → "/data/dave/_merged/activities/images/{id}/" $: imageBase = (() => { const du = activity.detail_url ?? ''; - const dir = du.startsWith('http') + const dir = du.startsWith('http') || du.startsWith('/') ? du.substring(0, du.lastIndexOf('/') + 1) : du.includes('/') ? `${base}data/${du.substring(0, du.lastIndexOf('/') + 1)}` diff --git a/site/src/components/EditDrawer.svelte b/site/src/components/EditDrawer.svelte index 47b18fc..5246953 100644 --- a/site/src/components/EditDrawer.svelte +++ b/site/src/components/EditDrawer.svelte @@ -51,7 +51,8 @@ title = d.title ?? ''; sport = d.sport ?? 'cycling'; gear = d.gear ?? ''; - description = d.description ?? ''; + // Strip any auto-inserted image markdown refs — images are tracked via custom.images + description = (d.description ?? '').replace(/!\[[^\]]*\]\([^)]+\)\n?/g, '').trim(); highlight = d.highlight ?? false; isPrivate = d.private ?? false; hideStats = d.hide_stats ?? []; @@ -95,9 +96,6 @@ if (res.ok) { const d = await res.json(); if (!images.includes(d.filename)) images = [...images, d.filename]; - // Insert markdown reference at cursor or end - const ref = `\n![${d.filename.replace(/\.[^.]+$/, '')}](${d.filename})`; - description = description.trimEnd() + ref; } } } catch (e: any) { @@ -111,9 +109,6 @@ async function deleteImage(filename: string) { await fetch(`${api}/images/${encodeURIComponent(filename)}`, { method: 'DELETE' }); images = images.filter(f => f !== filename); - // Remove the markdown reference — escape filename before using in regex - const escaped = filename.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); - description = description.replace(new RegExp(`!\\[[^\\]]*\\]\\(${escaped}\\)`, 'g'), '').trim(); } function toggleStat(key: string) {