Commit Graph

28380 Commits

Author SHA1 Message Date
claude a004f21688 Fix mobile ergonomics on Lumière project list page
Build and Deploy Verso / deploy (push) Successful in 14m58s
Compact row (xs): wrap format/owner/date in a lumiere-compact-meta div
that uses display:contents on desktop (preserving the 6-column grid) and
switches to a 2-row grid layout on mobile — row 1: checkbox/name/actions,
row 2: format·owner·date. Actions are always visible on touch devices.

Filter access: add a horizontal scrollable filter-pill bar (d-md-none)
to the Lumière header so users can switch between All/Yours/Shared/Archived/
Trashed on phone without needing the desktop sidebar.

Also: hide zoom control on mobile (d-md-none), auto-force compact view on
mobile via useIsMobile hook, fix search form min-width overflow on xs.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-18 08:22:27 +00:00
claude 065534819c Fix file tree refresh after convert and compiler sync on set-as-main
Build and Deploy Verso / deploy (push) Successful in 14m4s
- Convert: backend now returns parentFolderId+isNew; frontend calls
  dispatchCreateDoc directly so the new file appears without a page refresh
- Set as main: infer compiler from file extension and POST both rootDocId
  and compiler together; updateProject propagates the change to the
  editor settings dropdown and project list immediately

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-18 07:50:02 +00:00
claude b0b389dc4c feat: set-as-main for .typ/.qmd; fix compiler filter; fix ZIP import compiler
Build and Deploy Verso / deploy (push) Successful in 14m56s
Set as main document (context menu):
- canSetRootDocId used selectedEntityIds so .typ/.qmd files couldn't be
  set as main via right-click on an unselected file.
  Now computed locally from contextMenuEntityId (same pattern as convert)
  using isValidTeXFile which already covers .typ, .qmd, .tex etc.

Compiler filter (editor settings):
- docs?.find(id) could return undefined due to ID format mismatch,
  causing all engines to show as available for non-LaTeX projects.
  Added findInTree fallback so the root doc name is always resolved.

ZIP import compiler:
- Projects created from ZIP always got defaultLatexCompiler ('quarto')
  regardless of content.
- findRootDocFileFromDirectory now also searches for .typ and .qmd root
  files after finding no .tex file.
- ProjectUploadManager now infers the compiler from the root doc
  extension and sets it on the project after import.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-17 21:56:39 +00:00
claude bc131f6440 fix: convert items show for unselected files; add success toast
Build and Deploy Verso / deploy (push) Successful in 15m23s
canRename required selectedEntityIds.size === 1, so right-clicking an
unselected file hid the convert items even though contextMenuEntityId
was correctly set. Replace canRename with !fileTreeReadOnly for the
convert-specific gate, which is the actual write-access check needed.

Also add showExportDocumentSuccess so the user sees the warning toast
on successful conversion instead of silent nothing.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-17 21:18:24 +00:00
claude ff7de70a61 fix: per-file convert — DuplicateNameError + first-click no-op
Build and Deploy Verso / deploy (push) Successful in 21m44s
Two bugs:
1. Converting when output already exists threw DuplicateNameError (400).
   Now overwrites existing doc via setDocument instead of failing.

2. Right-clicking an unselected file left contextMenuEntityId null,
   so the first click on Convert silently did nothing. Added
   contextMenuEntityId to FileTreeMainContext, set it on right-click
   and on the … button click; FileTreeItemMenuItems now uses it for
   the convert hooks rather than relying on selectedEntityIds.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-17 20:35:50 +00:00
claude dbb7899ca3 docs: clean up Alpha 3 section, add Known Issues
Build and Deploy Verso / deploy (push) Successful in 15m23s
Remove RevealJS thumbnails (redundant with Features section) and Upload
reliability (still unresolved). Add Known Issues section documenting
the large file upload timeout.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-17 19:58:52 +00:00
claude 7eeabc93aa fix: send empty JSON body on convert to avoid body-parser 400
postJSON without options sends Content-Type: application/json with no
body; body-parser's BodyParserWrapper intercepts the resulting
SyntaxError and returns 400 before the route handler runs.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-17 19:58:48 +00:00
claude ac2315bc8e feat: per-file Convert in explorer menu + fix export success toast
Build and Deploy Verso / deploy (push) Successful in 9m50s
- Add "Convert to Typst (.typ)" in the file tree context menu for .tex
  docs, and "Convert to LaTeX (.tex)" for .typ docs. Clicking runs pandoc
  on the file content and creates the converted file in the same folder.
- New backend endpoint POST /project/:id/doc/:id/convert/:type that reads
  the doc from document-updater, runs pandoc directly, and creates the
  result via ProjectEntityUpdateHandler (file tree updates via socket).
- Rewrite the export success toast for typst and latex conversions: no
  more link to /contact, replaced with a plain warning that errors are
  expected (pandoc does not support all constructs).
- Add i18n keys: convert_to_typst, convert_to_latex,
  typst_export_feedback_message, latex_export_feedback_message (EN + FR)
  and all four to extracted-translations.json.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-17 15:18:31 +00:00
claude de22dcf87f docs: add mobile layout to Alpha 3 release notes
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-17 14:58:28 +00:00
claude e82f5fbead docs: update Alpha 3 release notes and fix Overleaf description
Add top/bottom split view and bidirectional format export (LaTeX↔Typst,
LaTeX→DOCX/Markdown/HTML) to the Alpha 3 feature list. Fix the security
section which incorrectly referred to Overleaf as a LaTeX/Typst editor —
Overleaf only supports LaTeX.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-17 14:56:45 +00:00
claude d64365aa56 Add missing i18n keys to extracted-translations.json
Build and Deploy Verso / deploy (push) Successful in 14m28s
top_bottom_split_view, export_as_typst, and export_as_latex were absent
from the whitelist, so translations-loader.js stripped them from the
locale bundles at build time — causing raw keys to show in the UI.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-17 14:46:31 +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 15ffaefb87 fix: install pandoc and enable pandoc conversions
Build and Deploy Verso / deploy (push) Failing after 1h2m54s
Pandoc was not installed in the base image, so the export buttons
(docx, markdown, html, typst) were hidden because ENABLE_PANDOC_CONVERSIONS
defaulted to false.

- Dockerfile-base: add pandoc via apt (Ubuntu Noble ships 3.1.3, which
  supports --to typst added in pandoc 3.0)
- env.sh: set ENABLE_PANDOC_CONVERSIONS=true so both the web and CLSI
  services expose and serve the export endpoints

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-17 08:46:09 +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 f7d0369213 fix: translate hardcoded 'Editor settings' header in View menu
Build and Deploy Verso / deploy (push) Successful in 9m45s
The DropdownHeader in the View > Layout menu was using a raw English
string instead of t('editor_settings'). Added the key to all 18 locale
files with appropriate translations.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-17 08:04:56 +00:00
claude 57e34aa104 fix: dropdown positioned at top-left on first click
Build and Deploy Verso / deploy (push) Successful in 15m17s
Popper lazy-initializes on first open, causing it to place the menu at
[0,0] before it has computed the toggle's position. renderOnMount forces
Popper to initialize while the component is first mounted, so the
position is ready before the user's first click.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-16 22:05:01 +00:00
claude 48d5e15f7f fix: Lumiere card dropdown clipped by card's backdrop-filter and transform
Build and Deploy Verso / deploy (push) Successful in 14m35s
.lumiere-card has both backdrop-filter and a hover transform, both of
which create a new containing block for position:fixed descendants,
trapping Popper dropdowns inside the card's overflow:hidden bounds.

Fix: move .lumiere-card-actions outside .lumiere-card (sibling inside
.lumiere-card-wrapper, which has position:relative but no filter or
transform). The actions strip is now absolutely positioned at the card
bottom with its own solid background and bottom border-radius.
No backdrop-filter on the strip to avoid re-introducing the same trap.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-16 21:35:52 +00:00
claude b78845a926 fix: show presentation export dropdown on Lumiere tiles for Quarto projects
Build and Deploy Verso / deploy (push) Successful in 14m25s
ProjectCard in the Lumiere tile view always showed CompileAndDownloadProjectPDFButtonTooltip,
ignoring the project compiler. Quarto presentation projects need the
DownloadPresentationButtonTooltip (HTML/PDF dropdown) instead, matching
the logic already in actions-cell.tsx and actions-dropdown.tsx.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-16 21:08:43 +00:00
claude c10a13f605 fix: PC layout regression and silent PDF download failure
Build and Deploy Verso / deploy (push) Successful in 13m21s
layout-context: getInitialLayout() was returning verticalSplit for
any stored 'vertical' preference, including on desktop. Now checks
isMobile first so stored mobile preference doesn't bleed into PC.

compile-and-download-pdf: when compile succeeds but output.pdf is
absent from outputFiles, the code crashed silently at outputFile.build
leaving the user with no feedback. Now shows the error modal instead.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-16 20:42:22 +00:00
claude 762d3e75cf fix: footer translation, mobile search bar and table row layout
Build and Deploy Verso / deploy (push) Successful in 13m32s
- Footer: use translate('built_on') key instead of hardcoded 'Built on';
  update fr.json 'built_on' → 'Basé sur Overleaf'
- Mobile project list: move search bar + button outside the bordered
  TableContainer so its width is viewport-constrained, not affected by
  the table's fixed layout
- Mobile table rows: use width:100% (not auto) on cells so they fill the
  full tr width regardless of the higher-specificity column percentage
  rules; add explicit width:100% on tr to anchor flex-column sizing;
  keep width:auto on absolutely-positioned actions cell

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-16 15:31:09 +00:00
claude db5b2b1f82 fix: show presentation download dropdown for all Quarto projects
quartoFlavor is set only after a project is compiled with the current
build. Existing Quarto projects that haven't been recompiled have
quartoFlavor=undefined, so the old check (quartoFlavor === 'revealjs')
fell through to the regular PDF compile button with no dropdown.

Drop the quartoFlavor guard — compiler === 'quarto' is sufficient since
all Quarto projects in Verso are RevealJS presentations. Changes applied
to ActionsCell (desktop icon), DownloadPresentationButtonTooltip guard,
and ActionsDropdown (mobile three-dot menu).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-16 14:53:33 +00:00
claude 685a7ffca1 fix: language picker links, dropdown position, and editor layout defaults
Build and Deploy Verso / deploy (push) Successful in 14m34s
Language picker:
- Add fallback href in Pug so language links navigate even if JS fails
- Anchor dropdown to right edge (right:0) so it stays on-screen when
  the picker is near the right side of the footer on mobile

Editor layout:
- Read stored pdfLayout from localStorage on init so the last-used
  layout is remembered across sessions
- Default to verticalSplit (top/bottom) on mobile when no preference
  is stored, so the editor opens in a sensible layout on phones

Translations:
- Add top_bottom_split_view key to all 16 locales that were missing it

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-16 14:40:02 +00:00
claude 84d1efc271 fix: use <details>/<summary> for Pug language picker to get native toggle
Build and Deploy Verso / deploy (push) Successful in 14m10s
The manual JS click-handler approach (tried with stopPropagation,
containment check, and mousedown variants) never worked reliably on
login/password/settings pages. The browser's native <details>/<summary>
toggle behaviour requires no JavaScript and is immune to Bootstrap JS or
React event delegation interference.

The inline script now only builds the return_to hrefs and handles
outside-click-to-close (setting details.open=false). The CSS gains a
.language-picker-details rule that sets position:relative so the
absolutely-positioned dropdown-menu is positioned correctly, and
details[open] .dropdown-menu { display: block } to show the menu.

The #language-picker-toggle id remains on the <summary> so the existing
CSS (cursor, text-decoration, material-symbols alignment) continues to
apply. The React LanguagePicker is unaffected.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-16 12:55:39 +00:00
claude b461343b23 fix: project list phone layout and language picker
Build and Deploy Verso / deploy (push) Successful in 14m3s
- Search bar overflow: min-width:0 on form prevents input min-content
  from overflowing flex container on narrow screens
- Remove duplicate New Project button from header row (tableTopArea
  already provides it for mobile)
- Simplify tableTopArea: single button+search layout regardless of
  isLibraryEnabled flag
- 2-line project rows on mobile: merge dash-cell-date-owner +
  dash-cell-tag into a single dash-cell-meta so date/owner/tags flow
  inline on line 2 below the project name
- Footer mobile: hide language-picker-text on mobile (icon only) to
  prevent 3rd line in 2-row footer
- Language picker: use mousedown instead of click for outside-close
  handler — click bubbling is unreliable on iOS for non-interactive
  elements; mousedown fires for all taps

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-16 11:47:32 +00:00
claude be353d53bd Center footer items on mobile for harmonious two-line layout
Build and Deploy Verso / deploy (push) Successful in 9m44s
Both ul.site-footer-items rows are now justify-content: center on small
screens, so the copyright/language row and the licence/source row are
symmetrically aligned instead of left-justified.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-16 11:05:22 +00:00
claude 0a5bd4e47d Fix mobile layout key, language picker close handler, and presentation download
Build and Deploy Verso / deploy (push) Has been cancelled
- Mobile vertical layout: add key= based on direction so react-resizable-panels
  remounts cleanly when switching between horizontal and vertical; also use
  isVertical (not just pdfLayout) for the autoSaveId to avoid restoring a
  mismatched layout from localStorage
- Language picker: replace stopPropagation pattern with a containment check on
  the document click handler — more robust on React pages where Bootstrap JS or
  React's event delegation can interfere with stopPropagation
- Presentation download dropdown: use popperConfig strategy:'fixed' so the menu
  escapes overflow:hidden table cells; remove forced drop='up' and let Popper
  choose; defer URL.revokeObjectURL by 10 s to give the browser time to start
  the download before the blob URL is released

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-16 11:01:15 +00:00
claude 11227d59e3 Editor mobile ergonomics: vertical split layout on phones and as desktop option
Build and Deploy Verso / deploy (push) Successful in 14m3s
On mobile (< 768 px) the existing side-by-side layout automatically switches
to a vertical stack (editor on top, PDF/presentation on bottom) without
changing the stored layout preference.

A new "Top / bottom split" option is added to the layout menu so desktop
users can choose the same vertical split explicitly.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-16 09:25:15 +00:00
claude 0f585ea5bb Fix: use picture_as_pdf icon for presentation download toggle
Using the generic 'download' icon duplicated the ZIP button icon,
giving two identical icons side by side. Switch to picture_as_pdf to
match the previous compile-and-download button's appearance.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-16 08:51:29 +00:00
claude a6ea291ea8 Add PDF/HTML download dropdown for Quarto Slides in project list
Quarto Slides (RevealJS) projects compile to output.html, not output.pdf,
so the existing "Download PDF" button was meaningless for them. Replace it
with a two-option dropdown matching the editor's PdfHybridDownloadButton:

- Desktop (ActionsCell): icon button opens a dropup with
  "Download standalone HTML" and "Download PDF slides"
- Mobile (ActionsDropdown): two separate dropdown items with the same
  choices and per-format spinner while the export is in progress

Both use the same /project/:id/presentation-export/:format endpoint and
show a loading modal (with error reporting) during the server-side render,
exactly as the editor toolbar does.

Non-RevealJS projects continue to show the compile-and-download-PDF button
unchanged.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-16 08:48:03 +00:00
claude 703f4d6ee2 Replace native <select> language picker with styled dropdown
Build and Deploy Verso / deploy (push) Successful in 13m43s
The native <select> looked like a form control ("cheap"). Replace it with
the same HTML+CSS pattern as the React LanguagePicker: btn-inline-link
toggle with a translate icon, Bootstrap dropdown-menu for the list, active
item highlighted in green.

A tiny self-contained inline script handles the toggle since Bootstrap JS
is not loaded on React-layout pages. It builds the return_to URL from
window.location.pathname at click time (same as the old select approach).

Added top: auto / bottom: 100% to .language-picker .dropdown-menu so the
list always opens upward regardless of whether Popper.js is present.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-16 08:29:10 +00:00
claude 86a902c197 Improve mobile ergonomics for footer and project list
Footer (both React and Pug):
- Below md: switch to flex-wrap so items wrap naturally instead of
  overflowing; reset line-height from the fixed 49px to normal; add
  row-gap so wrapped rows aren't crammed together
- Add footer-sep class to pipe separator <li>s so they can be hidden
  on small screens (wrapping mid-separator looks wrong)
- Change col-lg-3 text-end → text-lg-end so the right column (licence,
  source code) aligns left when it stacks full-width below lg

Project list:
- Show NewProjectButton on mobile in the header row (the sidebar that
  holds the button is already hidden below md via d-none d-md-flex,
  leaving users with no way to create projects on their phone)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-16 08:22:57 +00:00
claude 36f5e9fb06 Remove rounded top-left corner from project list content area
The content panel had border-top-left-radius: var(--border-radius-large)
at md+ breakpoint, left over from the old Overleaf theme. Everything else
is square now so this corner stood out. Removing it makes the edge flush.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-16 07:58:33 +00:00
claude 2b9ebe5522 Replace Overleaf O with Verso icon mark in editor state favicons
Build and Deploy Verso / deploy (push) Successful in 10m0s
favicon-compiled.svg, favicon-compiling.svg, favicon-error.svg all used
the Overleaf O logo as the base. Replace with the Verso icon mark (dark
background, four colored circles, white V polygon, clipped to a circle)
while keeping the existing status badge icons (✓ / ↻ / ✗) unchanged.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-16 07:54:33 +00:00
claude e4f1eead25 Branding polish: Verso favicons, OG image, and meta tag fixes
Build and Deploy Verso / deploy (push) Successful in 10m24s
Replace Overleaf favicons with Verso icon mark across all sizes (16x16,
32x32, 180x180 apple-touch, 192x192/512x512 android-chrome, ICO). Add
OG social preview image (1200x630) for Discord/Twitter link cards.

- New favicon.svg: Verso icon mark with four overlapping circles and V
- mask-favicon.svg: monochrome V polygon (was Overleaf chevron)
- og-image.png: 1200x630 social card with icon mark and "Verso" wordmark
- web.sitemanifest.json: rename "Overleaf" → "Verso", theme_color updated
- _metadata.pug: add og:url tag, fix og:type missing content= attribute,
  point CE default OG/twitter images to og-image.png instead of apple-touch-icon.png

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-15 20:19:01 +00:00
claude 323d74cc66 fix: replace Pug language picker dropdown with native select
Build and Deploy Verso / deploy (push) Successful in 14m31s
The old dropdown relied on data-bs-toggle and AngularJS directives,
neither of which are loaded on React-layout pages (layout-react.pug
intentionally excludes Bootstrap JS). The toggle button was inert on
pages like /user/settings.

Replace with a plain <select> that navigates via window.location.href
onchange — works without any framework on all page types.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-15 18:46:03 +00:00
claude 81c1fc92d1 fix: remove data-bs-toggle from LanguagePicker dropdown toggle
Build and Deploy Verso / deploy (push) Successful in 10m8s
Bootstrap vanilla JS and react-bootstrap were both handling the dropdown,
causing the toggle to be unresponsive. react-bootstrap manages its own
state and does not need this attribute.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-15 14:15:36 +00:00
claude 319ccc32ee feat: add language picker to logged-in footer and editor settings
Build and Deploy Verso / deploy (push) Successful in 18m46s
- Rewrites LanguagePicker to use availableLanguages from ol-footer meta
  instead of subdomainLang (which is always empty in single-domain setup)
- Passes availableLanguages through layout-react.pug → ol-footer meta so
  React footer picks it up
- Adds InterfaceLanguageSetting component to the editor settings modal
  ("Spelling and language" tab) for use when no footer is present
- Adds interface_language key to all five locale files (en/fr/de/es/it)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-15 12:22:55 +00:00
claude 1a0197812d feat: cookie+DB language preference, eliminating subdomain requirement
Build and Deploy Verso / deploy (push) Successful in 14m53s
Users can now select their UI language directly without relying on
subdomain routing (fr.verso.alocoq.fr etc.).

Resolution order: (1) verso-lang cookie, (2) subdomain host header,
(3) OVERLEAF_SITE_LANGUAGE default — fully backward compatible.

Changes:
- Translations.mjs: read verso-lang cookie in middleware; include all
  bundled locale files in availableLanguageCodes regardless of subdomain
  config so every loaded locale appears in the picker
- User.mjs: add languageCode field to persist preference per user
- UserController.mjs: setLanguage handler — sets cookie (1 year) and
  writes languageCode to DB when called by a logged-in user
- AuthenticationController.mjs: on login, sync DB languageCode to cookie
  so preference follows the user to any new browser/device after login
- ExpressLocals.mjs: expose availableLanguages to all Pug templates
- router.mjs: GET /set-language?lng=<code> (anonymous + logged-in),
  POST /user/language (logged-in, REST-style)
- language-picker.pug: replace subdomain href links with /set-language
  redirect links; iterate availableLanguages instead of subdomainLang
- thin-footer.pug: show picker whenever availableLanguages.length > 1,
  not only when multiple subdomains are configured

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-15 11:44:56 +00:00
claude 589c60a325 i18n(de/es/it): correct machine-translation errors in German, Spanish, Italian
Build and Deploy Verso / deploy (push) Successful in 14m22s
German (43 fixes): table→Tabelle (was Tisch/furniture), figure→Abbildung (was Figur),
no_borders→Keine Rahmen (was Grenzen/national borders), run→Ausführen (was Lauf),
right→Rechts (was Richtig/correct), unpausing was "Ununterbrochen" (uninterrupted),
unlink_provider said "verknüpfen" (link) instead of "trennen" (unlink),
unpause_subscription said "pausieren" (pause) instead of "fortsetzen",
zotero_reference_loading_error mentioned Mendeley, light_themes→Helle Themen,
review_panel→Überprüfungsbereich (was Gremium/committee), x_price_per_month untranslated,
Writefull/Papers/booktabs/Labs product names preserved

Spanish (58 fixes): no_borders→Sin bordes (was fronteras/national borders),
invite_resent→Invitación reenviada (was "Invita a resentirse"),
trash→Papelera, trashed→En papelera (was "Destrozado"/destroyed),
plan→Plan (was Planificar/verb), premium→Premium (was prima/bonus),
disabled→Desactivado (was Discapacitado/handicapped), breadcrumbs navigation fixed,
cookie_banner→Banner de cookies, search_match_case fixed, Writefull/Papers/Dropbox/Git preserved

Italian (85 fixes): no_borders→Nessun bordo (was confini/national borders),
right→Destra (was Giusto/correct), run→Esegui (was Corri/run physically),
standard→Standard (was Norma), premium→Premium (was Premio/prize),
characters→Caratteri (was Personaggi), editor→Editor (was Editore/publisher) throughout,
light_themes→Temi chiari (was leggeri/lightweight), unpausing→Riattivazione,
back_to_x buttons fixed from "Torniamo" (we return) to imperative "Torna",
~20 infinitives corrected to imperatives for button labels,
booktabs/Writefull/Papers product names preserved, triple-r typo fixed

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-15 11:30:04 +00:00
claude 38144b1033 i18n(fr): correct 41 machine-translation errors in French locale
Fix a batch of severe mistranslations produced by automated translation:
- typographic terms: bold→Gras (was "Audacieux"), figure→Figure (was "Chiffre"),
  characters→Caractères (was "Personnages"), borders→bordures (was "frontières")
- UI action labels: apply→Appliquer (was "Postuler"/job application),
  run→Exécuter (was "Courir"/to run physically), chat→Chat (was "Discuter"/verb),
  code→Code (was "Coder"/verb), more_actions→Plus d'actions (was "propositions")
- subscription plan terms: plan→Forfait (was "Planifier"/verb),
  premium→Premium (was "Prime"), standard→Standard (was "Norme")
- role/position: role→Rôle, position→Poste (both were "Grade"/military rank)
- light mode: mode lumière→mode clair throughout
- upload direction: Télécharger→Téléverser (download vs upload)
- invite_resent: catastrophic mis-parse of "resent" as resentment
- search_match_case: "Étui de correspondance" (phone case)→"Respecter la casse"
- product names preserved: booktabs, Writefull, GPT (were translated literally)
- typo: "toruvé"→"trouvé", missing spaces: "viaGit"→"via Git", "SSOconfiguration"→"Configuration SSO"
- untranslated: x_price_per_month was left in English
- accent: "Suedois"→"Suédois", "Koréen"→"Coréen", "Turque"→"Turc"

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-15 11:17:32 +00:00
claude 00ccb9748e docs: red CAUTION block for security warning, fix hallucinated Overleaf/Typst claim
Use GitHub's > [!CAUTION] admonition (renders with red background) for the
trusted-environment security warning, matching the style used by Collabst.

Remove invented claim that Overleaf is working on Typst support — that was
a hallucination. Replace with a plain "Verso is built on Overleaf's infra"
statement. Add RevealJS as a separate ecosystem project worth supporting.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-14 09:31:35 +00:00
claude a16ad0b977 docs: no contributions/donations, add security model + Collabst + ecosystem support
Build and Deploy Verso / deploy (push) Successful in 15m37s
- Remove Contributing section (not accepting PRs/issues)
- Add Security model section: Verso is for trusted environments only;
  point untrusted-user use cases at Overleaf non-Community offerings
- Mention Collabst as a promising open-source Typst-only alternative
  in the Verso vs Typst.app comparison
- Add Supporting the ecosystem section redirecting to Overleaf (Typst +
  RevealJS work) and the Typst project instead of Verso donations

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-14 09:22:34 +00:00
claude c2a21da47c docs: rewrite README — positioning vs Overleaf/Quarto/Typst.app, add releases section
Build and Deploy Verso / deploy (push) Has been cancelled
Replace the "how to write a .qmd / .typ / .tex" tutorial content with a
clear positioning narrative: what Verso is vs Overleaf (same engine + more
languages), vs Quarto CLI (browser-based, collaborative, multi-language),
and vs Typst.app (self-hosted, AGPL, OT-backed, three languages).

Add a Releases section covering Alpha 1 (core multi-compiler foundation),
Alpha 2 (Typst grammar overhaul, format sub-types, Python for collaborators),
and Alpha 3 in-progress (Lumière, i18n, visual editors, upload fix).

Keep Quick start, Architecture, Env vars, and License sections intact.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-14 09:11:02 +00:00
claude 94d3764c05 fix: stream HTTP 200 heartbeat before upload body to prevent proxy timeouts
Build and Deploy Verso / deploy (push) Has been cancelled
Uploads from slow connections consistently fail with 502 after ~60-120s
because an upstream proxy (Traefik or cloud load-balancer) has a
"first response byte" deadline that fires before the request body arrives.

Fix: add startStreamingResponse middleware (after auth, before multer)
that immediately writes HTTP 200 + Transfer-Encoding: chunked + '\n'.
With proxy_request_buffering off in Nginx, this reaches the proxy at T≈0,
so no timeout triggers. The upload body continues streaming; multer writes
to disk; the actual JSON result arrives as the final chunk. Periodic
heartbeat '\n' writes every 30s keep response-idle timeouts at bay too.

Client-side: override Uppy's getResponseData/validateStatus to trim
leading whitespace before JSON.parse so the extra '\n' bytes are ignored.
Server-side: sendUploadResponse() helper handles both streaming mode
(res.headersSent → res.end(json)) and normal mode (res.status(N).json()).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-14 08:59:02 +00:00
claude 8f372d13f8 fix: Lumière layout/navbar on settings+404, drop proxy_request_buffering
Build and Deploy Verso / deploy (push) Successful in 14m28s
- Move min-height:100vh from body to html:has(body[data-lumiere]) so the
  gradient fills the viewport on short pages without inflating document
  height or pushing the footer below the fold
- Remove min-height:60vh from .error-container (was causing scrollbar on
  404 when combined with thin footer)
- Replace Bootstrap 3 navbar selectors (.navbar-nav > li > a) with CSS
  custom property overrides (--navbar-link-color, --navbar-link-hover-*,
  --navbar-bg, etc.) consumed by navbar.scss — fixes header button colours
- Remove position:relative from .navbar-default override; base CSS already
  has position:absolute which provides the stacking context for ::before
- Drop proxy_request_buffering off from upload location: buffered mode +
  global client_body_timeout 15m (nginx.conf.template) is more compatible
  with multer's multipart stream handling on slow connections

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-13 20:38:00 +00:00
claude 211ca9c46d Fix Lumière theming + upload timeout via global middleware
Build and Deploy Verso / deploy (push) Successful in 14m26s
Theming: replace per-controller isLumiere lookups with a single
ExpressLocals middleware that sets res.locals.isLumiere for every
web request. Uses getOverallTheme() (now exported from
UserSettingsHelper) so the date-based default is handled correctly.
This covers 404, settings, setPassword, activate, and all future
server-rendered pages automatically.

Upload timeout: add client_body_timeout 15m to nginx.conf.template
at the http level (was defaulting to 60s globally). This is more
reliable than the location-specific override from build 229.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-13 19:33:53 +00:00
claude 2ec6ca827e Fix upload timeout + apply Lumière to settings/auth pages
Build and Deploy Verso / deploy (push) Successful in 15m0s
Nginx: add dedicated upload location with client_body_timeout 15m,
client_max_body_size 550m, and proxy_request_buffering off. Default
client_body_timeout of 60s was the actual culprit cutting slow uploads.
Node.js requestTimeout (build 228) remains as a backstop.

Lumière: pass isLumiere from UserPagesController (settings),
PasswordResetController (set-password), and UserActivateController
(first-time activation). auth.scss adds card styling for auth pages.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-13 17:47:03 +00:00
claude 41d38a70ed Increase upload timeout to 15 min for slow connections
Build and Deploy Verso / deploy (push) Successful in 15m39s
Frontend fetch gets AbortSignal.timeout(15 min) so hung connections
fail cleanly. Server requestTimeout raised from Node default (5 min)
to match, preventing large-file uploads from being cut off server-side.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-13 16:58:10 +00:00