18819 Commits

Author SHA1 Message Date
claude 974a9c4fb3 fix(typst): restore HeadingMark+HeadingTitle with character-level bleed guard
Build and Deploy Verso / deploy (push) Successful in 10m0s
The single-HeadingLine token approach caused everything after the first
heading to be unparsed. Reverting to the two-token structure but adding a
backward character scan in headingTitleTokenizer: after canShift(), walk
backward past whitespace and require '=' immediately before the current
position. Body-text positions in LALR-merged states will have a letter or
closing bracket there instead, so the tokenizer returns without accepting.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-08 18:17:17 +00:00
claude 34025dc084 fix(typst): use HeadingLine single token to fix inline element highlighting
Build and Deploy Verso / deploy (push) Successful in 9m35s
The two-token approach (HeadingMark + HeadingTitle) caused LALR state
merging: the parser state waiting for HeadingTitle after HeadingMark was
merged into body-text item* states. In those merged states the
headingTitleTokenizer fired for every paragraph line, swallowing bold,
italic, math and inline function tokens — leaving body text black.

Fix: collapse the heading into a single HeadingLine external token that
covers the entire heading line (= prefix + title). A single-token Heading
rule leaves no post-token parser state waiting for a second token, so no
LALR merging can occur. The ViewPlugin and all HeadingMark/HeadingTitle
infrastructure are removed.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-08 16:55:09 +00:00
claude 0099672015 fix(typst): restore HeadingTitle token to fix broken syntax highlighting
Build and Deploy Verso / deploy (push) Successful in 10m12s
Removing HeadingTitle from the grammar left HeadingTitle? undeclared,
causing the Lezer grammar compiler to fail and producing no parser
output — hence everything rendered as unstyled black text.

Dual approach to prevent heading style bleed:
- HeadingTitle exists in grammar with contextual: true + canShift guard
  (prevents it from matching in body-text LALR states)
- HeadingTitle is intentionally absent from styleTags so even spurious
  matches cannot apply heading colour to body text
- ViewPlugin styles heading titles by finding HeadingMark nodes and
  extending tok-heading decoration to end-of-line

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-08 15:38:38 +00:00
claude a5ca432396 Fix heading bleeding and smooth_pdf_transition translation
Build and Deploy Verso / deploy (push) Successful in 13m35s
Two fixes:

1. Heading style bleeding (Typst): the HeadingTitle external token approach
   was unreliable — even with contextual:true and canShift(), body text was
   being styled as headings. Remove HeadingTitle from the grammar entirely.
   Instead, a ViewPlugin (headingLinePlugin in languages/typst/index.ts)
   walks the syntax tree, finds HeadingMark nodes, and decorates the rest of
   the line with tok-heading class + bold. This is unconditionally correct
   because it is based on the syntax tree rather than the LR tokenizer state.

2. smooth_pdf_transition raw key shown in all locales: the key was in the
   JSON locale files but missing from extracted-translations.json, which is
   the allowlist the webpack translation loader uses to decide what to bundle.
   Add it there so all locales (including fr, es, de already added) resolve
   to their translated strings.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-08 14:22:16 +00:00
claude f1abcaa4ce Hide LaTeX-only compile options for Typst/Quarto projects; add smooth_pdf_transition translations
Build and Deploy Verso / deploy (push) Successful in 9m35s
Draft compile mode and stop-on-first-error are LaTeX-only features not
supported by TypstRunner or QuartoRunner. Hide both sections from the
recompile dropdown for non-LaTeX projects. Also detect Quarto root files
(.qmd/.md/.Rmd) alongside Typst (.typ) to correctly set isLatexProject.

Add missing smooth_pdf_transition translations for French, Spanish, and
German (the English key already existed).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-08 13:45:02 +00:00
claude 1c323351a2 fix: parse Quarto schema YAML errors and stop heading style bleeding
Build and Deploy Verso / deploy (push) Successful in 9m46s
Two unrelated fixes:

1. quarto-log-parser: handle the two-line Quarto schema-validation
   error format:
     ERROR: In file main.qmd
     (line 6, columns 24--27) Field "section-numbering" has value …
   Previously neither the file name nor the line number were extracted,
   so the error appeared without a red highlight. Now the first line
   stores the filename in pendingLocation and the second line creates
   the log entry with the correct file and line so the editor can jump
   to and highlight it.

2. headingTitleTokenizer: change contextual: false → contextual: true
   and guard with stack.canShift(HeadingTitle). With contextual: false
   Lezer calls the tokenizer speculatively at positions beyond the strict
   post-HeadingMark state; in some LALR-merged states the resulting token
   was accepted for body-text lines, making them render as bold-blue
   heading text. The contextual guard ensures the tokenizer only fires
   in the one state where HeadingTitle is legitimately valid.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-08 13:31:26 +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 7a5218d472 typst: fix CodeIdent vs "_" token overlap after #keyword CallExpr?
Build and Deploy Verso / deploy (push) Failing after 8m41s
KeywordExpr { CodeKeyword CallExpr? } merges the post-keyword LR state
with document-level markup states, where "_" opens Emphasis.  CodeIdent
starts with identHead which includes "_", so the two tokens overlap.

Adding "_" after CodeIdent in @precedence resolves the conflict: CodeIdent
wins in the merged state (correct for '#set _name(...)'), and in pure markup
states CodeIdent is not in the valid set so "_" still opens Emphasis.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-08 09:16:35 +00:00
claude b16b096744 projection: visit overlay/mounted subtrees during tree iteration
Build and Deploy Verso / deploy (push) Successful in 22m39s
yamlFrontmatter() embeds the Markdown content as an overlay on the top-level
YAML-frontmatter tree.  The previous mode (IgnoreMounts | IgnoreOverlays)
skipped that overlay entirely, so ATXHeading nodes were never visited and the
Quarto (.qmd) file outline was always empty.

Dropping the mode flag lets the iterator descend into overlay and mounted
subtrees.  This is safe because every enterNode function already filters by
node name — visiting extra nodes from foreign-language mounts is a no-op.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-08 09:03:43 +00:00
claude e9cc63a261 typst: highlight function name after #set / #show keywords
Build and Deploy Verso / deploy (push) Has been cancelled
KeywordExpr now optionally includes a CallExpr, so '#set text(size: 12pt)'
parses 'text' as a CallExpr/CodeIdent and gets the function-name highlight
colour.  The optional CallExpr only shifts when the lookahead is CodeIdent,
so there is no shift/reduce conflict with other items.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-08 08:40:28 +00:00
claude 07c72cf7e5 typst: stop heading title at // or /* comment markers
Build and Deploy Verso / deploy (push) Successful in 9m24s
headingTitleTokenizer now stops reading when it encounters '//' or '/*',
so '= Heading // note' correctly produces a HeadingTitle token for 'Heading'
and a LineComment for the rest of the line.  Without this, the comment was
consumed into HeadingTitle, getting heading highlight and appearing verbatim
in the file outline.

Also strip trailing line comments from heading titles in the regex-based
document outline scanner, which reads raw text independently of the tree.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-08 08:27:02 +00:00
claude 4f98abbc5d classHighlighter: map function(variableName) to tok-function
Build and Deploy Verso / deploy (push) Has been cancelled
All cm6 themes define .tok-function but the classHighlighter had no entry
for tags.function(tags.variableName), so function-name tokens fell back to
tok-variableName (which themes leave unstyled).  This affected Typst function
calls (#func(...)) and would affect any future language that tags function
names with t.function(t.variableName).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-08 08:21:16 +00:00
claude 1dcd6e24f4 lezer-typst: convert LineCommentContent and MathContent to external tokenizers
Build and Deploy Verso / deploy (push) Successful in 10m10s
Both tokens are "read until delimiter" catchalls that match almost every
non-newline character, causing buildTokenGroups conflicts with every other
literal token in LALR-merged states.  Moving them to ExternalTokenizer (the
same pattern already used for HeadingTitle, RawBlockBody, etc.) makes them
context-isolated: the LR state machine only calls them when those tokens are
actually valid, so they never participate in the static token-group overlap
check.

Also exclude '<' from StrongText/EmphText so Label ('<' LabelName '>') is
recognised inside strong/emphasis spans rather than being consumed as plain
text.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-08 07:56:20 +00:00
claude e21f7cc0d5 fix(typst): resolve all overlapping-token errors via @precedence
Build and Deploy Verso / deploy (push) Has been cancelled
Lezer's buildTokenGroups rejects grammars with ambiguous token sets.
Eight overlaps existed:

  EscapeChar vs spaces       — EscapeChar { _ } matches \t; after '\'
                               it must win over the @skip spaces token.
  "(" / "." vs text tokens   — in the LALR-merged state after #CodeIdent,
                               callSuffix delimiters must beat
                               MarkupContent / StrongText / EmphText.
  "]" vs LineCommentContent  — inside #[...], the ContentBlock closer
                               must win even if it follows "//".

One extended @precedence declaration resolves all eight.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-08 07:41:03 +00:00
claude e4f5385e35 fix(typst): fix zero-length token error for LineCommentContent
Build and Deploy Verso / deploy (push) Has been cancelled
LineCommentContent { ![\n]* } matches the empty string, which Lezer
rejects as a zero-length token (infinite-loop risk). Change to ![\n]+
and mark it optional in the LineComment rule so empty // comments parse.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-08 06:54:56 +00:00
claude 2f3e3e7363 fix(typst): make HeadingTitle an external token to end LALR conflicts
Build and Deploy Verso / deploy (push) Has been cancelled
Any item shared between headingTitleItem and document-level item causes
a shift/reduce conflict: the LALR automaton merges the two contexts and
makes the shared token ambiguous. The only structural fix is to make
HeadingTitle a terminal (external tokenizer) that reads greedily to EOL,
giving the LR state machine a context-isolated token that can never
collide with document-level item tokens.

Removes headingTitleItem sub-rule, HeadingText token, and updates
styleTags to match HeadingTitle directly.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-07 21:14:18 +00:00
claude 94e8ff3503 fix(typst): eliminate LALR(1) conflict on heading title items
Build and Deploy Verso / deploy (push) Failing after 3h10m10s
Removing Strong and Emphasis from headingTitleItem eliminates the
conflict: both appear in document-level item, causing the LR automaton
to merge heading-title states with document-item states and make "*"
ambiguous (Strong opener vs. end of heading).

HeadingText is widened to ![\n$#`<@\\]+ so "*" and "_" inside headings
are consumed as plain text rather than producing error nodes.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-07 20:58:05 +00:00
claude 26da1f6205 fix(editor): resolve HeadingTitle shift/reduce conflict in Typst grammar
Build and Deploy Verso / deploy (push) Has been cancelled
headingTitleItem* allowed an empty HeadingTitle, causing a shift/reduce
conflict: after HeadingMark, seeing "*" the LR parser couldn't decide
whether to shift it as a Strong inside the heading or reduce HeadingTitle
to empty and treat "*" as a document-level item.

Changing to headingTitleItem+ forces HeadingTitle to be non-empty, so
"*" after HeadingMark must be inside the heading. Empty headings are
handled by Lezer's error recovery.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-07 20:35:42 +00:00
claude 5287ea6f00 fix(editor): break Strong/Emphasis mutual recursion in Typst grammar
Build and Deploy Verso / deploy (push) Has been cancelled
Strong{strongItem{Emphasis}} and Emphasis{emphItem{Strong}} created a
mutual-recursion cycle that caused Lezer's LR automaton builder to
produce exponentially many states and crash.

Remove each construct from the other's item list. StrongText already
includes '_' and EmphText already includes '*', so nested delimiters
render as plain text inside the opposite construct rather than errors.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-07 20:14:33 +00:00
claude 045d458875 feat(editor): native Lezer grammar for Typst syntax highlighting
Build and Deploy Verso / deploy (push) Has been cancelled
Replace the StreamLanguage tokenizer with a full LR grammar compiled by
@lezer/generator, giving Typst the same parse-tree infrastructure that
LaTeX and BibTeX already use.

Grammar features:
- Headings (=, ==, …) via SOL-detecting external tokenizer
- Code expressions (#keyword, #func(args), #ident.method, #{…}, #[…])
- Named argument highlighting (key: value in function calls)
- Inline and display math ($…$)
- Strong (*…*) and emphasis (_…_) with bold/italic formatting
- Raw blocks (```lang…```) and inline raw (`…`)
- Nested block comments (/* /* */ */) via depth-tracking external tokenizer
- Labels (<name>) and references (@name)
- Backslash escapes

Infrastructure changes:
- lezer-typst/typst.grammar — new Lezer grammar
- lezer-typst/tokens.mjs — external tokenizers for context-sensitive lexing
- scripts/lezer-latex/generate.mjs — Typst added to grammars array so the
  existing lezer-latex:generate script (and Dockerfile step) compile it
- .gitignore — generated typst.mjs / typst.terms.mjs excluded from git

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-07 19:49:17 +00:00
claude 2c0f387cef feat(editor): use @codemirror/lang-yaml for Quarto YAML frontmatter
Build and Deploy Verso / deploy (push) Successful in 12m20s
Replace the custom regex-based ViewPlugin with the official
@codemirror/lang-yaml package. yamlFrontmatter({ content: mdLS })
wraps the Markdown language with a mixed parser: the leading ---/---
block is handed to the full Lezer YAML parser (proper key/value/scalar/
anchor/alias highlighting), while the document body continues to use
the Markdown parser. The manual Frontmatter extension import is also
removed since yamlFrontmatter handles frontmatter recognition itself.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-07 18:30:35 +00:00
claude f9788a1c69 feat(editor): improve syntax highlighting for Typst and Quarto documents
Build and Deploy Verso / deploy (push) Successful in 10m50s
Typst: heading tokenizer now colors the entire heading line (not just the
'=' prefix), and bold/italic markers (*/_) map to strong/emphasis tags
rather than the generic operator tag. A typstHighlightStyle applies
bold/italic formatting even when the active theme lacks .tok-heading.

Quarto: enable @lezer/markdown's Frontmatter extension so the YAML header
is no longer mis-parsed as Setext headings. A new ViewPlugin decorates
frontmatter lines with type-appropriate CSS classes: keys (tok-typeName),
string/bool/number values, comments, and the --- delimiter markers.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-07 17:42:51 +00:00
claude 489bdb01ec feat(pdf): dark mode for Quarto RevealJS HTML output
Build and Deploy Verso / deploy (push) Successful in 10m36s
Apply the same CSS inversion filter to the HTML iframe as is already
applied to pdfjs PDF pages, so Quarto RevealJS presentations respect
the dark mode toggle. Also show the theme button for HTML outputs and
relax the darkModePdf condition to activate for iframes regardless of
the pdfViewer setting.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-07 17:18:29 +00:00
claude 5a85e1b9d8 Add smooth PDF transition toggle to compile settings
Build and Deploy Verso / deploy (push) Successful in 11m53s
Per-project-type setting: Typst defaults to on, LaTeX defaults to off.
Toggle appears in the compile dropdown under "Smooth PDF transition".
The enableTransition flag is read via a ref so toggling does not
reload the current PDF.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-07 14:19:37 +00:00
claude 165219dcb1 fix(autocompile): prevent compile chaining — wait for previous compile before starting next
Build and Deploy Verso / deploy (push) Successful in 11m38s
The auto-compile effect was calling debouncedAutoCompile() on every changedAt
update (every keystroke), including while a compile was already running.  With
a 1000ms maxWait the debounce fired every second even mid-compile, chaining
compiles back-to-back and making the user wait for all of them to drain.

Fix: add `compiling` to the effect's dependency array.
- While compiling: the effect cancels the debounce immediately, preventing
  any new compile from being queued.
- When compile finishes (compiling → false): the effect re-runs; if changedAt
  is still > 0 (changes were made during the compile), it re-arms the debounce
  exactly once.  One follow-up compile, then idle.

Also remove the debouncedAutoCompile() re-queue from compiler.ts's
wasCompiling guard — the effect now owns that responsibility.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-07 13:38:43 +00:00
claude 71755e5cee fix(pdf): replace document.startViewTransition with non-blocking canvas fade
Build and Deploy Verso / deploy (push) Successful in 14m22s
document.startViewTransition with an async callback places a ::view-transition
overlay on top of the entire page, intercepting pointer events for the duration
of the callback (up to the 1s safety timeout + 250ms animation).  With rapid
auto-compiles this created interface freezes and overlapping transitions that
could leave the visual lock in a broken state, causing 'stuck on compiling'.

Replace with a canvas snapshot overlay + CSS opacity fade-out:
- pointer-events:none so the overlay never blocks input
- snapshot covers the canvas-clear from setDocument() (no white flash)
- on pagerendered: opacity transitions to 0 over 250ms, then overlay removed
- gives the same smooth visual crossfade, reliably, in all browsers

Chrome 126+ retains the element-level startViewTransition path which is
scoped to the PDF container and does not affect the rest of the page.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-07 13:09:18 +00:00
claude 453439e611 fix(pdf): suppress root view-transition animation to isolate fade to PDF pane only
Build and Deploy Verso / deploy (push) Successful in 11m47s
document.startViewTransition generates both a named pseudo-element for the PDF
container (ol-pdf-viewer) and a root-level pseudo-element that covers the entire
page, causing the editor to fade along with the PDF.

Inject a temporary <style> that sets animation:none on the root pseudo-elements
before starting the transition, then remove it in transition.finished.  Only the
named PDF container crossfades; the editor is unaffected.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-07 12:39:01 +00:00
claude d895e14e48 feat(pdf): restore smooth crossfade for Chrome 111+ using document.startViewTransition
Build and Deploy Verso / deploy (push) Successful in 11m24s
The original code used container.startViewTransition(setDocument) with a
synchronous callback, giving a 250ms CSS crossfade that looked smooth when
the PDF happened to re-render before the animation ended — but was a race.

Now there are three tiers:
- Chrome 126+: element-level startViewTransition, async, waits for pagerendered
- Chrome 111+ (Brave 138, Edge 111+): document-level startViewTransition with
  view-transition-name scoped to the PDF container, same async pattern
- Firefox / Safari / older Chromium: canvas snapshot overlay (no animation,
  but seamless — introduced in build #108)

The document-level path restores the smooth fade the user saw on Edge build
#93, now guaranteed to crossfade old→new rather than old→blank.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-07 12:22:46 +00:00
claude 4410a83146 fix: eliminate too-recently-compiled error and PDF flicker on fast Typst compiles
Build and Deploy Verso / deploy (push) Successful in 11m25s
Rate limit: auto-compile requests already have a client-side debounce; skip
the 1-second server-side recently-compiled gate for them to avoid spurious
'too-recently-compiled' rejections that were blocking ~1/3 of Typst compiles.

PDF flicker: add _snapshotCanvases() fallback for browsers without element-level
View Transitions (Chrome <126, Firefox, Safari).  Before setDocument() clears the
canvases it copies each rendered page to a positioned overlay; the overlay is
removed once the first page of the new document fires pagerendered, giving a
seamless old→new swap in all browsers.  Chrome 126+ continues to use the
startViewTransition async callback path.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-07 12:00:01 +00:00
claude db162e54af fix(typst): correct auto-compile default and debounce detection for Typst projects
Build and Deploy Verso / deploy (push) Successful in 11m37s
The previous implementation used useState() to detect the project type, but the
file tree is loaded asynchronously after the WebSocket joinProject event, so
pathInFolder() always returns null on the initial render.

Use useEffect() instead — it re-runs when getRootDocInfo's reference changes
(i.e. when the file tree populates), correctly detecting .typ root docs.
Also adds updateAutoCompileDebounce() to DocumentCompiler so the tight
debounce can be applied at that point.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-07 11:37:28 +00:00
claude 228ad00075 feat(typst): auto-compile on by default with fast debounce + smoother PDF transitions
Build and Deploy Verso / deploy (push) Successful in 14m23s
- Typst projects default autocompile to enabled (300ms debounce / 1s max-wait
  instead of 2.5s/5s), so the PDF refreshes nearly as the user types.
- Make startViewTransition wait for the first page to render before completing
  the crossfade, eliminating the old-PDF→blank flash on Chrome 126+.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-07 10:40:10 +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 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 170818e6fc fix(synctex): gate sync buttons to LaTeX-only projects
Build and Deploy Verso / deploy (push) Successful in 11m0s
Verso added 'qmd' and 'typ' to validRootDocExtensions, which caused
isValidTeXFile() to return true for Typst/Quarto files — enabling
SyncTeX UI controls for projects that never produce output.synctex.gz.

Replace the open-doc extension check in canSyncToPdf with a
LaTeX-only regex on the project root document path (tex|ltx|Rtex|Rnw),
and add the same guard in _syncToCode so PDF-click sync never fires
an API request for non-LaTeX projects.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-06 14:50:02 +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
roo hutton 757735b075 Merge pull request #34297 from overleaf/rh-prev-plan-type-cancel
Update previous_plan_type on subscription expiry

GitOrigin-RevId: 19381e5516fdbfd2650a9a5b94b61791e0da909f
2026-06-05 08:07:27 +00:00
Mathias Jakobsen fa36cd508b Merge pull request #34310 from overleaf/mj-handle-lazy-errors-for-search-and-share
[web] Handle errors while loading full project search and share modal

GitOrigin-RevId: 29d863324a54fa872022002f612498335f88f377
2026-06-05 08:07:10 +00:00
Mathias Jakobsen b7735d402d Merge pull request #34195 from overleaf/mj-command-palette-menu-labels
[web] Add menu labels to commands, and add more commands to command palette

GitOrigin-RevId: 21e17142bb3112b5fdcda85a472122b011979f49
2026-06-05 08:07:06 +00:00
Mathias Jakobsen cabe0046c5 Merge pull request #34102 from overleaf/mj-document-import-errors
[web] Expose pandoc errors in import

GitOrigin-RevId: 55f89b91a52099a99a5d955bc05f3657b87b2cdc
2026-06-05 08:07:02 +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 bfcf75855a [PnP migration] Convert .prettierrc to .prettierrc.cjs with require.resolve (#34237)
GitOrigin-RevId: ab57ca143bca8bfd2b44f03f9712a1aae70b2c1c
2026-06-05 08:06:42 +00:00
Antoine Clausse 3140e46e68 [web] Replace token-link email verification with 6-digit code on SSO registration (ORCID) (#33889)
* Replace token-link email with 6-digit code on SSO registration

Unverified SSO emails previously received a long-lived token link
(90-day TTL) via UserEmailsConfirmationHandler. This replaces that
flow with the same 6-digit code verification used for password
registration, redirecting through /registration/confirm-email.

- SSOManager.registerSSO now always confirms email (caller must
  verify first); removes sendConfirmationEmail / _finishRegistration
- SSOController._signUp sends confirmation code and stores
  pendingSSORegistration in session when IdP email_verified is false
- New SSOConfirmEmailHandler completes registration after code check
  via completeSSOEmailConfirmation module hook
- OnboardingController confirm-email handlers accept
  pendingSSORegistration alongside pendingUserRegistration

confirmEmailFromToken (POST /user/emails/confirm) removal is deferred
to a follow-up PR to avoid breaking in-flight 90-day tokens.

Closes #28607

* Fix unverified-email edge cases; Add ORCID e2e tests;

* Rename `confirmEmail` parameter to `emailVerifiedByIdP` in _signUp function

* Remove `sendConfirmationEmail`

* Mock getUserByAnyEmail in tests

* Extract _finishSSORegistration helper to deduplicate the register →
set session flags → allocate referral → finishSaasLogin → finishLogin
sequence shared by both the direct and deferred (code-confirmed) paths.

* Stop duplicating session data in pendingSSORegistration

analyticsId, splitTests, and referal_* are already in the session at
confirmation time — no need to copy them into pendingSSORegistration.
Re-fetch splitTests fresh on completion instead.

* Simplify the code

* Remove dead confirmEmail template

No callers remain after sendConfirmationEmail was deleted. The token-link
flow (confirmEmailFromToken) only validates tokens, never sends email.

* Remove dead reconfirmEmail template

* Address comments from Copilot

* Clear stale pending registration when starting a new flow

* Add unit tests for completeSSOEmailConfirmation

* Add `verificationMethod` param

* Fix camelcase issues

* Extract _createSSOUser and _registerAndFinish helpers to deduplicate registration logic

* Remove obscure "registration_error"

* Prevent FormTextIcon from shrinking

* Enable "email_already_registered_sso" error

* Misc. improvements to confirm-email-form.tsx

* Remove `UserEmailsConfirmationHandler` mock

Co-authored-by: Olzhas Askar <olzhas.askar@overleaf.com>

* Add info on sso_email.pug page

---------

Co-authored-by: Olzhas Askar <olzhas.askar@overleaf.com>
GitOrigin-RevId: d0196ebc6d81ff61bcd27726d0b899b743d08d64
2026-06-05 08:06:34 +00:00
Davinder Singh 6ce36a2606 adding web changes of Export HTML (#34117)
GitOrigin-RevId: 804c576faefebfc6683a0363b45372e66a43d8fc
2026-06-05 08:06:19 +00:00
Jakob Ackermann fc2abf5b24 [web] fix submit modal in Codespaces (#34137)
GitOrigin-RevId: dc057ed736e97265a901b1cf21995c1f391339a5
2026-06-05 08:06:15 +00:00
Malik Glossop b8fc478e1f Merge pull request #34185 from overleaf/worktree-mg-error-assist-paywall
Show paywall from gutter when user hits suggestion limit

GitOrigin-RevId: 36c09e3d93ac38e1e675aa8ffb419e928094d68e
2026-06-05 08:06:11 +00:00
Malik Glossop d25b032e16 Merge pull request #33450 from overleaf/worktree-mg-writefull-spelling-tab
Add writefull language suggestions section to Spelling and language tab

GitOrigin-RevId: 6195683ca175a4c3da25a7ab334a605c67db04b8
2026-06-05 08:06:07 +00:00
Olzhas Askar 8e36f20950 Merge pull request #34267 from overleaf/oa-move-upgrade
[web] Moving the upgrade button

GitOrigin-RevId: 33dcdcfa4e816e29177abe2c045e919edd7a4e08
2026-06-04 08:07:21 +00:00
roo hutton 06e99fe62a Merge pull request #34130 from overleaf/rh-enterprise-cio
Expose enterprise indicators and previous_plan_type for first subscriptions to customer.io

GitOrigin-RevId: 693db7f796609f00ecd31216a6d6be32c1f569c8
2026-06-04 08:07:09 +00:00
Maria Florencia Besteiro Gonzalez d112271b1c Merge pull request #34184 from overleaf/cs-icon-button-labs-library
feat(library): add Labs feedback badge to Library heading

GitOrigin-RevId: 6dacc588cc58300a09b8195ca800d042d40f4c89
2026-06-04 08:06:52 +00:00
Antoine Clausse 0658bd9a31 [web] Change plans order in Change Plan modal (#34096)
* [web] Order plans in Change Plan modal consistently

Reorder the plans returned by `buildPlansListForSubscriptionDash` so the
Subscription page "Change plan" modal lists them top-to-bottom as:

  1. Student annual
  2. Student monthly
  3. Standard monthly
  4. Standard annual
  5. Pro monthly
  6. Pro annual

Previously `buildPlansList` produced three per-period buckets which the
dash function concatenated, giving an order that flipped per family.
Replace that with an explicit `CHANGE_PLAN_MODAL_PLAN_CODES` list so the
order matches the Design QA spec at a glance. The now-unused
`studentAccounts`, `individualMonthlyPlans`, `individualAnnualPlans`,
`groupMonthlyPlans`, and `groupAnnualPlans` buckets are dropped from
`buildPlansList` (no other callers).

Closes #34024

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* [web] Update personal-plan acceptance test for new buildPlansList shape

The previous test asserted `buildPlansList().individualMonthlyPlans`,
which no longer exists after the change-plan modal reorder dropped the
per-period buckets. Move the assertion to
`buildPlansListForSubscriptionDash()`, which is where the personal-plan
exclusion is now enforced (via `CHANGE_PLAN_MODAL_PLAN_CODES`).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* [web] Drop now-dead client-side plan filter

`IndividualPlansTable` used to filter out `paid-personal`,
`paid-personal-annual` and `institutional_commons` defensively because
the old `buildPlansListForSubscriptionDash` returned every non-group
plan that wasn't `hideFromUsers`. The previous commit pins the modal to
an explicit six-plan list (`CHANGE_PLAN_MODAL_PLAN_CODES`), so none of
those plan codes ever reach the frontend and the filter is dead. Remove
it and the now-unused `useMemo` import.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* Revert "[web] Drop now-dead client-side plan filter"

This reverts commit 83e8448f2cfa2c68e44b749d5a2bc350a7443c6d.

We'll do that in a later cleanup

* Swap "Student monthly" and "Student annual" for consistency

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
GitOrigin-RevId: 046a235e14e7ad6622288f5a5a723f5a4f7f14da
2026-06-04 08:06:40 +00:00