From 9b01fab383fa05027e2879079adf88d1b7a96ea0 Mon Sep 17 00:00:00 2001 From: claude Date: Mon, 1 Jun 2026 14:01:58 +0000 Subject: [PATCH] Serve referenced media for HTML/RevealJS output MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit OutputFileFinder excluded all incoming project resources from the output set, and OutputCacheManager only copies outputs into the served build dir. For PDF that's fine (media is embedded), but for HTML/RevealJS the browser fetches images/videos/fonts from the output path at runtime — so a deck's referenced image (a project input file) was never served and rendered broken in the preview. When the compile produced output.html, keep media inputs (img/video/audio/font extensions) in the output set so they're served alongside the deck. PDF/LaTeX compiles are unaffected. This also makes referenced media land in output.zip, which the upcoming presentation-publishing feature relies on. Co-Authored-By: Claude Opus 4.8 --- services/clsi/app/js/OutputFileFinder.js | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/services/clsi/app/js/OutputFileFinder.js b/services/clsi/app/js/OutputFileFinder.js index 5b581a9a7d..49cf4e2f05 100644 --- a/services/clsi/app/js/OutputFileFinder.js +++ b/services/clsi/app/js/OutputFileFinder.js @@ -20,16 +20,29 @@ async function walkFolder(compileDir, d, files, allEntries) { } } +// Media that an HTML/RevealJS deck references at runtime (img/video/audio). +// These are usually project *input* files, which would normally be excluded +// from the output set — but for HTML output the browser fetches them from the +// output path, so they must be served. (For PDF output they are embedded, so +// the exclusion still applies.) +const MEDIA_REGEX = + /\.(png|jpe?g|gif|svg|webp|avif|bmp|ico|mp4|webm|ogg|ogv|mov|m4v|mp3|wav|m4a|woff2?|ttf|otf)$/i + async function findOutputFiles(resources, directory) { const files = [] const allEntries = [] await walkFolder(directory, '', files, allEntries) const incomingResources = new Set(resources.map(resource => resource.path)) + // For HTML output (Quarto/RevealJS), referenced media must be served even + // though it is an input file; see MEDIA_REGEX above. + const hasHtmlOutput = files.includes('output.html') const outputFiles = [] for (const path of files) { - if (incomingResources.has(path)) continue + if (incomingResources.has(path)) { + if (!(hasHtmlOutput && MEDIA_REGEX.test(path))) continue + } if (path === '.project-sync-state') continue outputFiles.push({ path,