diff --git a/server-ce/nginx/clsi-nginx.conf b/server-ce/nginx/clsi-nginx.conf index 5ce22a3f56..b907ecfcce 100644 --- a/server-ce/nginx/clsi-nginx.conf +++ b/server-ce/nginx/clsi-nginx.conf @@ -25,8 +25,19 @@ server { gzip_types text/plain; gzip_proxied any; types { - text/plain log blg aux stdout stderr; - application/pdf pdf; + text/html html htm; + text/css css; + application/javascript js; + application/json json; + image/svg+xml svg svgz; + image/png png; + image/jpeg jpeg jpg; + image/gif gif; + image/webp webp; + font/woff woff; + font/woff2 woff2; + application/pdf pdf; + text/plain log blg aux stdout stderr txt; } # handle output files for specific users location ~ ^/project/([0-9a-f]+)/user/([0-9a-f]+)/build/([0-9a-f-]+)/output/(.+)$ { diff --git a/services/clsi/app/js/CompileController.js b/services/clsi/app/js/CompileController.js index 53925c1291..9545d900a2 100644 --- a/services/clsi/app/js/CompileController.js +++ b/services/clsi/app/js/CompileController.js @@ -90,7 +90,10 @@ function compile(req, res, next) { } else { if ( outputFiles.some( - file => file.path === 'output.pdf' && file.size > 0 + file => + (file.path === 'output.pdf' || + file.path === 'output.html') && + file.size > 0 ) ) { status = 'success' diff --git a/services/clsi/app/js/QuartoRunner.js b/services/clsi/app/js/QuartoRunner.js index c548861b20..f54048f0cd 100644 --- a/services/clsi/app/js/QuartoRunner.js +++ b/services/clsi/app/js/QuartoRunner.js @@ -50,11 +50,21 @@ function runQuarto(compileName, options, callback) { function _buildQuartoCommand(mainFile) { // Run through a POSIX shell so stderr is merged into stdout (2>&1). - // Quarto writes all progress and error messages to stderr; without this - // the log panel would be empty on failure. // LocalCommandRunner replaces $COMPILE_DIR before the shell sees it. + // + // We do NOT pass --to or --output: let the YAML frontmatter decide the + // output format (typst → output.pdf, revealjs → output.html, etc.). + // --embed-resources makes HTML output self-contained (ignored for typst). + // After render we rename the produced file to the canonical output name + // expected by the rest of the pipeline. const inputPath = `$COMPILE_DIR/${mainFile}` - const cmd = `quarto render ${inputPath} --to typst --output output.pdf 2>&1` + const baseName = mainFile.replace(/\.[^/.]+$/, '') // strip extension + const pdfOut = `$COMPILE_DIR/${baseName}.pdf` + const htmlOut = `$COMPILE_DIR/${baseName}.html` + const cmd = + `quarto render ${inputPath} --embed-resources 2>&1 && ` + + `(mv ${pdfOut} $COMPILE_DIR/output.pdf 2>/dev/null || ` + + `mv ${htmlOut} $COMPILE_DIR/output.html 2>/dev/null)` return ['/bin/sh', '-c', cmd] } diff --git a/services/web/frontend/js/features/pdf-preview/components/pdf-viewer.tsx b/services/web/frontend/js/features/pdf-preview/components/pdf-viewer.tsx index c4d79243b4..657ad95cbb 100644 --- a/services/web/frontend/js/features/pdf-preview/components/pdf-viewer.tsx +++ b/services/web/frontend/js/features/pdf-preview/components/pdf-viewer.tsx @@ -12,6 +12,19 @@ function PdfViewer() { return null } + // HTML outputs (RevealJS, etc.) must always use the native iframe; + // PDF.js cannot render HTML. + if (pdfUrl.includes('output.html')) { + return ( +