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,