1273 Commits

Author SHA1 Message Date
claude 8fc71d677c Fix thumbnail quality and mobile vertical split layout
Build and Deploy Verso / deploy (push) Successful in 10m23s
Thumbnails: update the actual thumbnail endpoint (ConversionController.js
thumbnailFromBuild) to quality=90 and width=794. The previous fix targeted
ConversionManager.js which handles preview mode, not the thumbnail route
called by ThumbnailManager.mjs.

Mobile layout: move the isMobile guard before the stored-preference check
in getInitialLayout(). The autoSave race fix (build 274) stopped future
bad writes, but a stale 'flat' in localStorage was still being read on
every load, blocking the mobile check. Mobile now always starts in
verticalSplit regardless of any stored value.

CI: add node --check on all server-side .mjs files in the Dockerfile,
after source copy and before webpack compile, so syntax errors like the
escaped-backtick incident fail the build immediately.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-18 13:48:44 +00:00
claude f629f6a50c Mobile polish: max thumbnail quality, tab-bar filter chips, fix vertical split default
Build and Deploy Verso / deploy (push) Successful in 10m12s
- CLSI thumbnails: bump to 794px/q90 (matches preview quality) for
  crisp display on 2x/3x phone screens
- Lumière filter chips → underline tab bar: single scrollable row with
  teal active indicator, no more wrapping alignment issues; zoom buttons
  separated by a vertical divider on the right
- Fix editor vertical split default on mobile: disable react-resizable-panels
  autoSaveId on mobile to prevent a stale collapsed PDF pane from firing
  onCollapse → changeLayout('flat') and overriding the verticalSplit
  default set by getInitialLayout()

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-18 12:19:10 +00:00
claude c79ac23a15 Improve thumbnail quality and fix mobile editor default layout
Build and Deploy Verso / deploy (push) Successful in 10m18s
Thumbnails: increase CLSI thumbnail from 190px/q50 to 400px/q80.
At 190px/50% JPEG quality, images are noticeably blurry on 2x phone
screens (source needs 380px device pixels but source is only 190px).

Editor mobile layout: getInitialLayout() was returning sideBySide for
any stored 'split' preference (set from a desktop session), even on
mobile. sideBySide on mobile renders vertically via the isMobile check
in main-layout, but the stated default was still wrong. Now on mobile,
any stored value other than 'flat' maps to verticalSplit so the
top-bottom split is always the default; flat is preserved so a user
who explicitly chose editor-only keeps that preference.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-18 11:44:34 +00:00
claude 2d2a85f06f Fix typst export 500, add export-as-latex for typst projects
Build and Deploy Verso / deploy (push) Successful in 10m4s
- clsi-nginx: allow hyphens in project-id regex — conversion IDs are UUIDs
  which nginx was rejecting, causing 500 on file download after conversion
- CLSI ConversionController/Manager: add 'latex' export type (typst→latex via pandoc)
- Web: add 'latex' to SUPPORTED_CONVERSION_TYPES
- Frontend: add Export as LaTeX button (visible only for typst projects)
- Fix visibility logic: export-as-latex shows for typst, export-as-typst shows for latex
- Add export_as_latex translation key (en + fr)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-17 11:55:41 +00:00
claude b545d08939 Fix four reported bugs: typst export 500, export shown for all project types, Lumiere tile button layout, i18n
Build and Deploy Verso / deploy (push) Successful in 15m7s
- ConversionController.js: add typst to CONVERSION_CONFIGS (missing entry caused 400→500 chain)
- export-project-with-conversion-button: hide button for non-LaTeX projects (typst/quarto) via compiler check
- project-list-lumiere.tsx + scss: revert lumiere-card-actions back inside .lumiere-card (put them back like they were)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-17 11:12:50 +00:00
claude 9d11683920 feat: Typst → LaTeX import, and fix export button visibility
Build and Deploy Verso / deploy (push) Successful in 1m14s
Typst → LaTeX import:
- CLSI ConversionManager: add 'typst' to CONVERSION_CONFIGS
  (pandoc input.typ --from typst --to latex --standalone → zip archive)
- Web controller: allow 'typst' as a valid importDocument conversion type
- Frontend modal: add .typ file config to ImportDocumentModal
- New project button modal: add 'import_typst' variant + switch case
- New project button: show "Import Typst file" when enablePandocConversions
  is true (no split test gate — Verso has no SaaS split test infra)
- Locales: add choose_typst_file and import_typst_file keys (18 locales)

Export button fix:
- Remove featureFlag="export-typst" from ExportProjectWithConversionButton
  so the button shows whenever enablePandocConversions is true, without
  needing an unconfigured split test to return 'enabled'

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-17 08:54:54 +00:00
claude 32aec14c41 feat: export LaTeX project as Typst (.typ) via pandoc
Build and Deploy Verso / deploy (push) Successful in 9m58s
Adds a new "Export as Typst" option in the project title dropdown and
File menu, mirroring the existing docx/markdown/html export pipeline.

Changes:
- CLSI ConversionManager: add 'typst' to LATEX_EXPORT_CONFIGS
  (compressOutput: false, pandoc --from latex --to typst)
- Web controller: register 'typst' → 'typ' in SUPPORTED_CONVERSION_TYPES
- Frontend: extend conversionType union and add ExportProjectWithConversionButton
- File menu: add 'export-as-typst' to the download group command structure
- Locales: add export_as_typst key to all 18 locale files

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-17 08:24:54 +00:00
claude c5883e5954 feat: generate first-slide thumbnail for Quarto RevealJS presentations
Build and Deploy Verso / deploy (push) Successful in 14m10s
thumbnailFromBuild() now tries output.pdf → output-slides.pdf → decktape
on output.html (slide 1 only). The web service's ThumbnailManager already
calls this endpoint fire-and-forget on every successful compile, so RevealJS
project cards will show the first slide thumbnail automatically.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-13 16:02:54 +00:00
claude 0bbc07e0b9 fix: improve thumbnail quality and show gradient border around preview
Build and Deploy Verso / deploy (push) Successful in 15m20s
Increase pdftocairo output from 190px/q50 to 380px/q82 — 2× resolution
for crisp rendering on retina displays, higher quality to eliminate
visible compression artefacts.

Inset the thumbnail image 6px from the tile edges (inset: 6px) with a
4px border-radius so the card's colour gradient is visible as a frame
around the document preview.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-12 10:10:24 +00:00
claude 7da02d9e3a fix: use pdftocairo directly for thumbnails, no Docker image needed
Build and Deploy Verso / deploy (push) Successful in 15m11s
The previous implementation delegated to ConversionManager which uses
the Docker-based CommandRunner and is gated behind enablePdfConversions
(ENABLE_PDF_CONVERSIONS env var). Neither is configured in the Verso
deployment, so every thumbnail request 404'd before doing any work.

poppler-utils (which provides pdftocairo) is already installed directly
in the CLSI base image via install_deps.sh. Rewrite thumbnailFromBuild
to call pdftocairo via execFile instead — no feature flag, no Docker
image, no ConversionManager indirection.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-12 09:42:35 +00:00
claude b70c8ddd0e feat: show compiled PDF thumbnail in Lumière project cards
Build and Deploy Verso / deploy (push) Successful in 14m47s
After a successful compile, web service calls a new CLSI endpoint
(GET /project/:id/user/:uid/build/:bid/thumbnail) which runs pdftocairo
page-1 to a 190px-wide JPEG using the existing thumbnail preset. The
JPEG is stored in Redis (90-day TTL, overwritten on next compile) by
the new ThumbnailManager.

GET /project/:Project_id/thumbnail serves the cached JPEG to authenticated
users, returning 404 when no thumbnail exists. Project cards in the
Lumière grid show the image overlaying the coloured gradient tile; if
the image 404s (project never compiled or cache expired) the onerror
handler hides it and the gradient + initial letter shows through.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-12 09:20:48 +00:00
claude d8ce7f9dc1 feat: support svg package — install Inkscape and enable shell-escape
Build and Deploy Verso / deploy (push) Has been cancelled
The LaTeX svg package converts .svg files to PDF at compile time by
shelling out to Inkscape (requires --shell-escape). Without Inkscape in
the image and the flag enabled, compilation fails with "Did you run the
export with Inkscape?".

- Dockerfile-base: add inkscape to the apt install block
- settings.js: expose OVERLEAF_LATEX_SHELL_ESCAPE env var → clsi.latexShellEscape
- LatexRunner.js: pass -shell-escape to latexmk when the setting is on
- deploy-verso-prod.yml: set OVERLEAF_LATEX_SHELL_ESCAPE=true (trusted-user instance)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-10 10:57:56 +00:00
claude b8543c8bb9 fix: capture typst diagnostics emitted after the status line
Build and Deploy Verso / deploy (push) Has been cancelled
typst watch outputs the "[HH:MM:SS] compiled with errors" status line
FIRST, then the full diagnostic output (file:line:col, source snippets,
hints) AFTERWARDS. The previous code resolved the pending compile
promise as soon as COMPILE_DONE_RE fired, discarding all post-status
diagnostic lines. Those lines then got cleared by the next cycle's
COMPILE_START_RE, so output.log only ever contained the bare status
line — explaining the "zero verbosity" symptom.

Fix: introduce a two-phase buffering model. When COMPILE_DONE_RE fires,
enter "post-done" phase (storing doneResult) and keep accumulating into
currentLines. _finalizeCompile() is called either when the next
COMPILE_START_RE arrives (zero added latency) or after FLUSH_DELAY_MS
(150 ms fallback for the last compile). It concatenates pre-done and
post-done lines before resolving, so output.log now contains the full
diagnostic output.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-08 12:25:43 +00:00
claude 7e6c8c30cc fix: cache typst compile result to eliminate race-condition failures
Build and Deploy Verso / deploy (push) Successful in 14m6s
When typst watch detects a file change and compiles before the CLSI
resolver is registered (ResourceWriter writes files → typst compiles →
runTypst is called), _resolveAllPending was discarding the result
because pendingResolvers was empty. This caused two symptoms:

1. output.log only contained "compiled with errors" (no diagnostics)
   because the result carrying the full stdout was thrown away.

2. Every other manual compile failed with "compilation already gone"
   because the missed result caused a timeout, which killed the watcher
   and triggered a watcher restart cycle (success → miss → timeout →
   kill → restart → success → miss → ...).

Fix: when _resolveAllPending fires with no pending resolvers, store the
result in entry.pendingResult. _waitForNextCompile checks this field
first and resolves immediately if a cached result is present.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-08 11:48:46 +00:00
claude e0c717c131 fix: suppress interim compile errors while typing, show Typst error logs, dark-mode footer
Build and Deploy Verso / deploy (push) Successful in 1m43s
- local-compile-context: suppress failure/exited error state when
  changedAt > 0 (another compile is already queued), preventing the UI
  from flashing an error banner mid-typing that resolves moments later

- TypstRunner + CompileController: detect "compiled with errors" from
  typst watch and non-zero exit from typst compile, and signal
  status:'failure' to the frontend so the log panel opens automatically
  with the parsed error details (previously always returned 'success')

- footer.scss: add dark-mode overrides for footer.site-footer so the
  thin footer on project/marketing pages uses bg-dark-primary and
  content-primary-dark text in dark theme instead of hardcoded light bg

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-08 10:19:36 +00:00
claude 0b8897540d Fix Quarto RevealJS media missing on second compile
Build and Deploy Verso / deploy (push) Successful in 11m49s
When output.html exists, findOutputFiles includes project media files
(images, videos) in outputFiles via the MEDIA_REGEX exception so they
get served from the cache.  _removeExtraneousFiles then treated them
as extraneous and deleted them.  On the next incremental compile,
unchanged binary files are not re-synced, so the files were gone when
Quarto ran and when _appendMissingResourceWarnings checked for them.

Fix: skip deletion for any file that is a project input resource.
Those files appear in outputFiles to be served, not cleaned up.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-07 15:30:08 +00:00
claude 2ead377ebc Fix stale error lines bleeding into next Typst compile log
Build and Deploy Verso / deploy (push) Failing after 36m24s
When typst watch doesn't emit "compiled with errors" after a failed
compile, currentLines accumulates indefinitely. The next successful
compile then flushes the buffer including the stale error from the
prior cycle. Reset currentLines at the start of each compile cycle
("[HH:MM:SS] compiling ...") so each log only contains output from
one compile.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-07 15:10:59 +00:00
claude 7eaeaedcd8 Implement persistent typst watch for incremental compilation
Build and Deploy Verso / deploy (push) Successful in 59m27s
Instead of cold-starting 'typst compile' on every request, TypstRunner
now maintains a long-lived 'typst watch' process per project. Subsequent
compiles reuse the warm process, which caches fonts, packages, and the
compiled AST via Typst's comemo framework — dramatically faster.

Architecture:
- WatchTable: maps compileName → live watcher process + state
- _startWatcher: spawns 'typst watch input.typ output.pdf', registers
  stdout/close handlers, then immediately awaits the first compile result.
  The resolver is pushed to pendingResolvers synchronously inside the
  Promise constructor before any I/O event can fire — eliminating the
  race between file-write detection and resolver registration.
- _onWatcherData: parses stdout line-by-line, resolves pending callers
  on "compiled successfully/with warnings/with errors" (the three terminal
  lines typst watch emits at the end of each compile cycle).
- Graceful restart: watcher is restarted after MAX_COMPILES_BEFORE_RESTART
  (1000) cycles to stay clear of Typst's ~65k FileId limit, or immediately
  if the "ran out of file ids" message is detected in stdout.
- killTypst: tears down both the watcher and any cold-start fallback job;
  called by stopCompile (user-initiated) and clearProject/clearProjectWithListing
  (before compile-dir deletion).
- Docker fallback: Settings.clsi.dockerRunner=true falls back to the
  original cold-start 'typst compile' path unchanged.
- process.on('exit') kills all watcher process groups on CLSI shutdown.

CompileManager: call TypstRunner.promises.killTypst before deleting the
compile directory in both clearProject and clearProjectWithListing.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-07 09:09:33 +00:00
claude 54c510c818 Revert Typst SyncTeX attempt; clean up diagnostic logging
Build and Deploy Verso / deploy (push) Has been cancelled
Typst has no --synctex CLI option (open feature request #289 since 2023).
Revert the frontend guard back to LaTeX-only and remove --synctex from
the Typst compile command. Also remove the temporary logger.warn calls
added for diagnosing the LaTeX synctex issue (now resolved).

The official Typst binary installation in Dockerfile-base is kept as it
is cleaner than using Quarto's modified fork for .typ compilation.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-07 08:43:18 +00:00
claude 5796c0157c Install official Typst binary and use it for .typ compilation
Build and Deploy Verso / deploy (push) Has been cancelled
Quarto bundles a modified Typst fork that lacks --synctex, making
bidirectional sync impossible. Install the official Typst binary
(v0.13.1) from upstream and use it in TypstRunner instead.

This also means .typ projects now use the unmodified Typst compiler,
which is correct since TypstRunner handles plain .typ files (not .qmd).
QuartoRunner continues to use Quarto's bundled Typst internally.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-07 08:40:48 +00:00
claude 3f68c147a4 Call Typst binary directly for compile and SyncTeX support
Build and Deploy Verso / deploy (push) Successful in 13m8s
Instead of going through 'quarto typst compile' (which intercepts
--synctex before it reaches Typst), call the Typst binary bundled in
the Quarto .deb directly at /opt/quarto/bin/tools/x86_64/typst.

This allows passing --synctex output.synctex.gz to generate the SyncTeX
file for bidirectional editor↔PDF sync.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-07 08:24:20 +00:00
claude 0780963bc7 Fix --synctex argument order for Typst compile
Build and Deploy Verso / deploy (push) Successful in 11m33s
Typst's CLI requires options before positional arguments (INPUT OUTPUT).
Placing --synctex after output.pdf caused it to be treated as an extra
positional arg and rejected with 'unexpected argument'.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-07 08:09:52 +00:00
claude 43a622cd71 Add SyncTeX support for Typst projects
Build and Deploy Verso / deploy (push) Successful in 11m58s
- TypstRunner: add --synctex output.synctex.gz to quarto typst compile,
  generating a synctex file alongside the PDF (requires Typst 0.11+,
  bundled in Quarto 1.5+).
- use-synctex: extend the root-doc guard from LaTeX-only to also cover
  .typ files, enabling the Show in PDF / Show in code buttons for Typst.

The rest of the sync infrastructure (OutputCacheManager, synctex binary,
SynctexOutputParser, CLSI routes) is already format-agnostic.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-06 21:52:05 +00:00
claude e6add1e6f0 Add diagnostic logging to synctex to identify failure cause
Build and Deploy Verso / deploy (push) Successful in 9m42s
Logs: request params, directory used, whether output.synctex.gz
is found, and the actual synctex binary output or error.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-06 16:21:35 +00:00
claude 9ea904f78f Merge upstream Overleaf up to PR #34297 (68 commits)
Build and Deploy Verso / deploy (push) Successful in 11m30s
Conflicts resolved:
- fat-footer-website-redesign.pug: keep Verso footer (discard Overleaf marketing footer)
- MaterialSymbolsRoundedUnfilledPartialSlice.woff2: regenerated from merged
  unfilled-symbols.mjs (preserves Verso's deployed_code + adds upstream's spellcheck)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-06 13:39:32 +00:00
Anna Claire Fields 97247b8ea5 [PnP migration] Remove mock-fs dependency (#33835)
GitOrigin-RevId: ff8df32d85b2ecd2837c9eee6d6d2b3b95285239
2026-06-05 08:06:54 +00:00
Anna Claire Fields 44dee7592a use require.resolve for mocha reporter paths (#34235)
GitOrigin-RevId: af607dfdeac8f91f63db294a964ade7622225932
2026-06-05 08:06:46 +00:00
Anna Claire Fields bfcf75855a [PnP migration] Convert .prettierrc to .prettierrc.cjs with require.resolve (#34237)
GitOrigin-RevId: ab57ca143bca8bfd2b44f03f9712a1aae70b2c1c
2026-06-05 08:06:42 +00:00
Mathias Jakobsen fc31a88767 Merge pull request #34145 from overleaf/ds-download-html-using-pandoc-clsi-1
[CLSI] Download as HTML feature

GitOrigin-RevId: 374101c1f957a00eda423a6be0363c08b5de7a95
2026-06-05 08:06:03 +00:00
Jakob Ackermann df61bfc788 [clsi] initial version of /convert/pdf-to-jpeg (#33752)
* [monorepo] consolidate clsi-lb host/ip env-vars

Target env-var is CLSI_LB_HOST. Keep CLSI_LB_IP populated for a week.

* [clsi] initial version of /convert/pdf-to-jpeg

* [rails] use fake-secrets in CI and Codespaces

* [rails] adapt tests for using clsi to convert PDFs to image

* [rails] add rake task for comparing clsi conversion with transloadit

* [clsi] double check that output.jpg is a regular file

Co-authored-by: Brian Gough <brian.gough@overleaf.com>

* [clsi] fix composing basename

* [monorepo] fix clsi-lb host env-var post merge

* [monorepo] sort dev-environment.env hosts

* [rails] use local pdf file rather than downloading it again

Download from the old renderer code path still. It's dead code.

* [terraform] clsi: enable pdf to jpg conversion

---------

Co-authored-by: Brian Gough <brian.gough@overleaf.com>
GitOrigin-RevId: 5ecaa8559d299486340bb3961f06b29f7c4dfcca
2026-06-05 08:05:55 +00:00
Brian Gough f8c7e092fa upgrade to eslint v10 (#34054)
* upgrade from eslint version 8 to eslint version 10

* remove unsupported eslint-env directive

* include jsx files in latexqc linting

* use basePath and extends to maintain paths in writefull eslint

* fix yarn.lock

with ./bin/yarn install

* preserve existing glob patterns in web eslint config

* restore original comments

* fix worker path

* corrected comment about eslint-plugin-mocha

* remove unused imports

* remove unused import of includeIgnoreFile

* switch to individual eslit.config.mjs files

* fix lint errors on eslint.config.mjs in web

* update build scripts for eslint.config.mjs

* update volumes for RUN_LINTING_CI_MONOREPO in web Makefile

updated manually as this makefile is not autogenerated
the RUN_LINTING_CI_MONOREPO command is only used for prettier, not eslint, but updating for consistency.

* migrate from mocha/no-skipped-tests to mocha/no-pending-tests

see https://github.com/lo1tuma/eslint-plugin-mocha/pull/365
"rule no-skipped-tests has been removed, its functionality has been merged into the existing no-pending-tests rule"

GitOrigin-RevId: 2c8f25c8049a0dba374a51df1214286bb5093a51
2026-06-03 08:06:29 +00:00
claude c9727a26e4 Python deps: smart missing-package hint + switch to .vrf requirements file
Build and Deploy Verso / deploy (push) Successful in 9m46s
Option A: when a {python} cell fails with ModuleNotFoundError/ImportError, the
log now suggests the exact PyPI package to add (with a module->package map, e.g.
cv2 -> opencv-python, sklearn -> scikit-learn), names the Verso requirements
file, and notes it could instead be a local module — so the langmuirthermalstudy
case isn't mistaken for a PyPI package.

Switch the per-project requirements file from requirements.txt to a Verso-
specific requirements.vrf (so it won't be confused with arbitrary .txt files);
QuartoRunner now looks for requirements.vrf, and 'vrf' is registered as an
editable text extension. The dedicated in-UI editor (and hiding it from the
file tree) follows in a separate change.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-02 14:19:01 +00:00
claude 8530c5ebe0 Run Quarto Python kernel inside the project venv, not base python
Build and Deploy Verso / deploy (push) Successful in 9m33s
The global python3 kernelspec hardcodes /usr/bin/python3, so even with
QUARTO_PYTHON pointing at the project venv, Quarto launched the kernel in the
base interpreter — packages installed into the venv (e.g. openpyxl) were not
importable. Register a python3 kernelspec inside the venv via
'ipykernel install --sys-prefix' (kernel.json argv -> the venv's python); since
Quarto runs kernel discovery through QUARTO_PYTHON, the venv's kernelspec is
found ahead of the global one and the kernel runs in the venv.

Bump the completion marker (.verso-complete -> .verso-ready) so venvs built
before this change are rebuilt with the kernelspec.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-02 13:50:01 +00:00
claude 83b6b323c3 Add cv2/tqdm to base; implement per-project Python venvs (Design B, Phase 1)
Build and Deploy Verso / deploy (push) Successful in 17m0s
Base image: add opencv-python-headless (cv2) and tqdm to the bundled
scientific stack, and python3-venv (needed to build per-project venvs).

Per-project dependencies: a project's requirements.txt is now installed into a
venv cached by its sha256 (python3 -m venv --system-site-packages, so the
bundled stack stays visible and only extra packages are installed); QuartoRunner
points Quarto at it via QUARTO_PYTHON. A per-hash flock serialises concurrent
builds; pip output is merged into output.log; on failure the render falls back
to the base interpreter. Venvs live under PYTHON_VENVS_DIR
(default /var/lib/overleaf/data/python-venvs).

Gating: PythonVenvGate.userCanInstallPython restricts installs to the project
owner + invited collaborators (ignorePublicAccess excludes anonymous/link
users), threaded to CLSI as allowPythonInstall on the editor compile,
presentation export, and publish paths. Behind OVERLEAF_ENABLE_PROJECT_PYTHON_VENV
(enabled in the deployment). Design doc updated; Phase 2 (egress policy) and
Phase 3 (venv eviction) remain.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-02 13:14:47 +00:00
claude 7e1c2ce53a Fix standalone-HTML export: inject embed-resources into the deck frontmatter
Build and Deploy Verso / deploy (push) Has been cancelled
embed-resources cannot be enabled from the CLI: Quarto only honours it when
nested under the format, and a document's own format block fully overrides
project/CLI metadata (confirmed in Quarto docs). So --metadata embed-resources
was silently ignored and the 'standalone' HTML was the ordinary non-embedded
deck referencing a sibling _files/ dir — unstyled, no math, no images once
downloaded on its own.

For the html-standalone export, render a temporary copy of the root .qmd with
embed-resources/self-contained-math enabled and chalkboard disabled inside its
revealjs block (replacing an existing chalkboard key rather than duplicating
it), then clean the temp file up. Falls back to the original file if the deck
isn't an editable nested-revealjs document, so the export is never worse than
before.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-02 09:51:52 +00:00
claude 67b27c2684 Fix PDF export Chromium launch + HTML export caching
Build and Deploy Verso / deploy (push) Successful in 7m54s
The slide-PDF export failed because the CLSI runtime user has no writable
HOME, so Chromium's crashpad couldn't create its database and the browser
died on launch ('chrome_crashpad_handler: --database is required'). Give
decktape's Chromium a fresh writable temp dir via HOME/XDG_*/--user-data-dir
(plus --disable-gpu).

The standalone-HTML export kept returning the old non-embedded file partly
because the GET response had no cache headers, so the browser served its
cached copy; add Cache-Control: no-store to both export responses. Also
switch the embed-resources flags to the long '--metadata KEY:VALUE' form
(the documented Quarto syntax) to remove any ambiguity vs the '-M' alias.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-02 09:27:44 +00:00
claude 4d9adb2723 Fix presentation export: Quarto -M uses colon syntax, harden decktape
Build and Deploy Verso / deploy (push) Successful in 8m13s
The standalone-HTML export produced a non-self-contained file (no slide
CSS/JS, math or images when opened away from the server) because Quarto's
--metadata/-M flag uses KEY:VALUE (colon), not KEY=VALUE. '-M
embed-resources=true' silently registered a bogus key and left
embed-resources unset. Switch to colon syntax and also embed MathJax
(self-contained-math:true) so equations render offline.

For the slide PDF, add --disable-dev-shm-usage (the usual cause of
Chromium crashing inside a container with a small /dev/shm), and have the
export controller return the compile log as text/plain on failure so a
failed PDF export shows the real decktape/Chromium error instead of an
HTML page the browser saves as 'pdf.htm'.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-02 07:11:51 +00:00
claude c38e2b8b49 Presentation download menu: standalone HTML + faithful slide PDF (decktape)
Build and Deploy Verso / deploy (push) Failing after 24m2s
In RevealJS mode the download button becomes a 2-choice menu:

- Standalone HTML: a one-off compile with embed-resources (chalkboard and other
  runtime-only plugins are dropped, since they don't survive self-containment),
  yielding a single portable .html.
- Slide PDF: render the deck, then print it with decktape (headless Chromium)
  to a faithful one-slide-per-page PDF.

Implementation:
- Dockerfile-base: install decktape + headless Chromium (open-source; deps via
  playwright install-deps for Ubuntu-Noble correctness). Base-only change.
- QuartoRunner honours options.exportMode ('html-standalone' | 'pdf-slides');
  exportMode is threaded web ClsiManager -> CLSI RequestParser -> CompileManager
  -> runner.
- New GET /project/:id/presentation-export/:format compiles in the matching
  export mode and streams the result as a download (PresentationExportController,
  reusing ClsiManager.getOutputFileStream).
- pdf-hybrid-download-button shows the dropdown when the output is output.html;
  PDF/LaTeX projects keep the single download button.
- i18n: download_as_standalone_html / download_as_pdf_slides (en + fr +
  extracted-translations.json).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-01 21:00:50 +00:00
claude 9b01fab383 Serve referenced media for HTML/RevealJS output
Build and Deploy Verso / deploy (push) Successful in 7m39s
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 <noreply@anthropic.com>
2026-06-01 14:01:58 +00:00
claude 7c2b903e4d Warn about missing images/videos in Quarto HTML output
Build and Deploy Verso / deploy (push) Successful in 7m49s
Since we dropped --embed-resources (so RevealJS plugins like chalkboard work),
pandoc no longer tries to fetch referenced media for HTML output, so a missing
image or video produces no compile-time warning — it only renders broken in the
browser. PDF/Typst output is unaffected because Typst hard-errors on a missing
image.

After an HTML render, QuartoRunner now scans output.html for local media
references (img/video/audio/iframe src, poster, RevealJS data-background-*) and
appends a `[WARNING] Missing resource: …` line to output.log for any that don't
exist on disk. External URLs, data URIs, anchors and Quarto's own generated
<basename>_files assets are ignored. The [WARNING] prefix is recognised by the
Quarto/Typst log parser, so these show up in the Warnings tab.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-01 13:24:56 +00:00
claude 2d4ca6f13a Fix LaTeX projects failing to compile (HTTP 500, no logs)
Build and Deploy Verso / deploy (push) Successful in 7m44s
Project.compiler defaults to settings.defaultLatexCompiler ('quarto' in this
fork), so every .tex project carried compiler='quarto'. Since the CLSI runner
is chosen by file extension, a .tex root still goes to LatexRunner, whose
_buildLatexCommand threw `unknown compiler: quarto` — surfacing as an opaque
HTTP 500 with no compile log.

- LatexRunner: fall back to pdfLaTeX when the compiler isn't a known TeX engine
  instead of throwing. Universal safety net (covers existing projects, uploads
  and GitHub imports already saved with compiler='quarto').
- ProjectCreationHandler: store a sensible compiler per flavour at creation via
  a shared _flavourConfig helper — blank/example LaTeX → 'pdflatex',
  Typst → 'typst', Quarto → 'quarto' — so the compiler dropdown reflects the
  engine and LatexRunner receives a valid one directly.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-01 13:08:57 +00:00
claude d67bc77b0e Add a Typst compiler alongside Quarto and LaTeX
Build and Deploy Verso / deploy (push) Successful in 7m37s
A project whose root file is a .typ file now compiles straight to PDF with
Typst, as a third engine beside Quarto (.qmd) and latexmk (.tex). Dispatch
stays purely extension-based.

CLSI:
- New TypstRunner.js: runs `quarto typst compile <main>.typ output.pdf` (reuses
  the Typst bundled in Quarto, so no extra binary / Docker change). stderr is
  merged into output.log.
- CompileManager: _isTypstFile + a TypstRunner branch in _getRunner, and
  TypstRunner added to the isRunning check and stopCompile kill list.
- RequestParser: 'typst' added to VALID_COMPILERS.

web:
- settings.defaults: 'typ' added to validRootDocExtensions and the text
  extensions (so .typ opens in the editor); 'typst' added to safeCompilers.
- output-files: the Quarto/Typst log parser (which already understands Typst
  `error:`/`warning:` + `┌─ file:line:col` diagnostics) now also handles .typ
  compiles, so their errors/warnings populate the log tabs.

Polish:
- New-project menu: "Blank Typst project" + "Example Typst project" in both the
  main and welcome dropdowns, backed by createBasicProject/createExampleProject
  flavour 'typst', a new mainbasic.typ template and an example-project-typst
  presentation (math, an image, a table, lists).
- Compiler dropdown gains a "Typst" option (cosmetic; dispatch is by extension).

README updated: three compilers side by side, with a Writing-a-Typst-document
section.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-01 12:56:30 +00:00
claude e87bbfe5b0 HTML preview: drop embed-resources and clear stale deck on failure
Build and Deploy Verso / deploy (push) Successful in 12m5s
Two HTML/RevealJS preview fixes:

1. Stop passing --embed-resources to quarto render. A self-contained
   single-file HTML breaks reveal.js plugins that load/store resources at
   runtime (chalkboard, multiplex) and is slow to transfer. Quarto now
   emits the HTML plus a sibling "<basename>_files/" asset dir referenced
   by relative paths; both are served from the same .../output/ path
   (nginx output/(.+) and web :file(.*) both capture slashes), so the
   relative links resolve. The renamed output.html still points at the
   unchanged "<basename>_files" dir. This also fixes the slow-load issue,
   since assets now load on demand instead of one giant inlined file.

2. On a failed compile that follows a successful one, the previous deck
   stayed in the iframe, making the failure look like a success. We now
   clear pdfFile when a non-success status carries a stale output.html.
   The last-good-PDF-beside-the-error behaviour is preserved for PDF
   output (only output.html is dropped).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-01 08:40:18 +00:00
Gernot Schulz a0ca344065 Merge pull request #34127 from overleaf/gs-j-cd-hooks
Add deploy pipeline trigger hooks to Jenkinsfiles

GitOrigin-RevId: 80bb89615ae16b733009dca21a5fc41b5c30e993
2026-06-01 08:04:55 +00:00
claude 422ac30e6c Support LaTeX and Quarto compilation in parallel
Build and Deploy Verso / deploy (push) Has been cancelled
Verso now compiles both .tex (latexmk) and .qmd (Quarto) projects,
dispatching by the root file's extension rather than replacing one with
the other. LaTeX and Quarto projects can coexist on the same server.

CompileManager: re-import LatexRunner and add a _getRunner() dispatcher
  that returns a uniform {run, isRunning, kill} interface. .qmd/.md/.Rmd
  → QuartoRunner; everything else (.tex/.ltx/.Rtex/.Rnw) → LatexRunner.
  stopCompile now checks/kills both runners since it has no root path.

compiler-setting.tsx: restore the LaTeX engine choices (pdfLaTeX, LaTeX,
  XeLaTeX, LuaLaTeX) alongside Quarto. The dropdown still controls which
  TeX engine latexmk uses; actual engine dispatch is by file extension.

Dockerfile-base: reinstall TeX Live alongside Quarto (texlive-full minus
  -doc/-lang- packages, plus xetex/luatex/biber/latexmk/texcount/chktex/
  synctex). Restore TEXMFVAR for a writable LuaTeX cache. This brings back
  a large image, which is the accepted cost of full LaTeX+Quarto support.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-31 19:27:39 +00:00
claude a241e2c201 Pre-install popular Quarto extensions in the Docker image
Build and Deploy Verso / deploy (push) Successful in 11m22s
Dockerfile-base: after Quarto is installed, run 'quarto add --no-prompt'
  for a curated set of extensions into /opt/quarto-extensions/. Quarto
  writes _extensions/<author>/<name>/ in the working dir, giving us a
  clean shared store. Extensions included:
    - igorlima/charged-ieee      — IEEE paper format (Typst)
    - quarto-ext/fontawesome     — Font Awesome icons
    - quarto-ext/attribution     — attribution footer on RevealJS slides
    - quarto-ext/pointer         — laser pointer for presentations
    - quarto-ext/drop            — drop-down overlay for RevealJS
  Adding more: one extra '&& quarto add --no-prompt <author>/<repo>' line.

QuartoRunner: before quarto render, merge /opt/quarto-extensions/_extensions/
  into the compile dir's _extensions/ with 'cp -rn' (no-clobber). This
  makes all pre-installed extensions available to every project without
  any user action. Project-uploaded _extensions/ files take precedence
  since cp -n never overwrites existing files.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-31 16:54:56 +00:00
claude 24cd4bf13d Fix HTML compile success check: size is undefined for non-PDF outputs
Build and Deploy Verso / deploy (push) Has been cancelled
collectOutputPdfSize() only calls stat() and sets .size on output.pdf.
All other output files (including output.html) keep size: undefined.
The previous check required file.size > 0 for both PDF and HTML, so
undefined > 0 always evaluated false for output.html, making every
RevealJS compile report 'failure' even when the file was produced.

Fix: require size > 0 only for output.pdf; accept output.html
regardless of size (it is always non-empty if Quarto succeeded).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-31 16:27:02 +00:00
claude 090018c191 Fix QuartoRunner mv: use relative paths to avoid $COMPILE_DIR replacement bug
Build and Deploy Verso / deploy (push) Successful in 11m1s
LocalCommandRunner.replace() uses String.replace() which only substitutes
the FIRST occurrence of '$COMPILE_DIR' in the shell script string. The mv
commands had two more occurrences that stayed as literal '$COMPILE_DIR',
which the shell expanded to '', making 'mv /main.pdf /output.pdf' fail
silently. The file was produced (Quarto logged 'Output created: main.pdf')
but never renamed to output.pdf, so the pipeline reported failure.

Fix: mv uses relative filenames since the shell CWD is already the compile
directory (set by LocalCommandRunner via the spawnCwd option).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-31 15:51:01 +00:00
claude 48fd24a6b2 Add HTML/RevealJS preview alongside existing PDF preview
Build and Deploy Verso / deploy (push) Successful in 11m0s
clsi-nginx.conf: the types{} block was overriding all nginx defaults,
  leaving HTML/CSS/JS/fonts as application/octet-stream. Add the full
  set of web MIME types so RevealJS assets are served correctly. Also
  needed for X-Content-Type-Options: nosniff to pass.

CompileController.js: success was hardcoded to require output.pdf.
  Also accept output.html so a RevealJS compile is reported as
  'success' rather than 'failure'.

QuartoRunner.js: remove hardcoded --to typst --output output.pdf.
  Instead run `quarto render` without --to/--output so the YAML
  frontmatter decides the format (typst → PDF, revealjs → HTML, etc.).
  Pass --embed-resources so HTML output is self-contained (flag is
  silently ignored by the typst backend). After render, rename
  main.pdf → output.pdf or main.html → output.html so the pipeline
  finds the standard canonical filename.

output-files.ts: handleOutputFiles now falls back to output.html when
  output.pdf is absent. Download URL uses outputFile.path instead of
  the hardcoded 'output.pdf' string.

pdf-viewer.tsx: when pdfUrl contains output.html, bypass PDF.js
  entirely and render a sandboxed iframe (allow-scripts for RevealJS
  interactivity, allow-presentation for fullscreen).

Usage: set `format: revealjs` in the .qmd YAML frontmatter to get
  an HTML presentation preview; set `format: typst` for PDF.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-31 15:32:00 +00:00
claude ce0572e01e Revert QuartoRunner: restore --output output.pdf
Build and Deploy Verso / deploy (push) Successful in 11m9s
The previous compile logs confirm Quarto handles --to typst --output
output.pdf correctly: pandoc produces main.typ, typst compiles it to
main.pdf, then Quarto renames to output.pdf. The mv-based approach was
unnecessary and incorrect.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-31 14:11:03 +00:00