Skip to content
| Marketplace
Sign in
Visual Studio Code>Other>LaTeX Real-Time PreviewNew to Visual Studio Code? Get it now.
LaTeX Real-Time Preview

LaTeX Real-Time Preview

Weijie Zhong

|
125 installs
| (1) | Free
Fast, approximate real-time LaTeX preview — no TeX installation required
Installation
Launch VS Code Quick Open (Ctrl+P), paste the following command, and press enter.
Copied to clipboard
More Info

LaTeX Real-Time Preview

A VS Code extension that provides fast, approximate real-time preview of LaTeX documents without requiring a TeX installation. It treats LaTeX as structured markup (like Markdown) rather than a full typesetting language, delivering instant visual feedback as you type.

Motivation

Existing LaTeX previewers (e.g., LaTeX Workshop) require a full TeX distribution, take seconds to compile, and break entirely on syntax errors. This extension trades exact layout fidelity for speed, error tolerance, and immediate feedback -- you get a live, readable rendering of your document the moment you start typing.

Features

  • Real-time preview -- side panel updates as you type, with sub-100 ms latency for prose
  • No TeX installation required -- JS-based parser plus KaTeX for math
  • Error tolerant -- continues rendering even when your LaTeX has syntax errors
  • Incremental block rendering -- only the edited block is re-parsed and re-rendered; the rest of the preview is untouched, so a 10 000-line document stays snappy
  • Math-aware typing -- when the cursor is inside $...$, $$...$$, \(...\), \[...\], or a math environment, re-render is debounced longer (default 5 s) and flushes the moment the cursor leaves the math, so a single render covers an entire equation instead of one per keystroke
  • Refresh-mode toggle -- switch between "on type" and "on save" from the toolbar; saving the file always triggers a refresh regardless of mode
  • Refresh-now button -- forces a full re-render on demand
  • Viewport-aware math -- KaTeX renders math when it scrolls into view; cached by source so re-typing the same expression is free
  • Bidirectional scroll sync -- scroll in the editor or the preview, the other follows; preview snaps to top while the editor is in the preamble
  • Double-click to jump -- double-click any element in the preview to jump to its source line (works across files)
  • Theming -- light, dark, and sepia backgrounds; configurable font family and size
  • Multi-file projects -- \input and \include are resolved and inlined recursively, with file watching for live updates
  • Bibliography support -- parses .bib files and resolves \cite, \citet, \citep to author-year format
  • Cross-references -- \label, \ref, \eqref, \autoref, \cref resolved to numbered links
  • Custom macros -- \newcommand, \renewcommand, \def, \DeclareMathOperator are expanded
  • TikZ diagrams -- rendered asynchronously; uses local TeX if available, falls back to a built-in WASM renderer (node-tikzjax)
  • Rich LaTeX support -- sections, math environments, lists, theorems, tables, figures, footnotes, verbatim blocks, and more

Usage

  1. Open a .tex file in VS Code
  2. Press Ctrl+K V (or Cmd+K V on macOS), or click the preview icon in the editor title bar
  3. A preview panel opens to the right and updates in real-time

The toolbar at the top of the preview panel lets you:

  • switch background theme (Light / Dark / Sepia)
  • adjust font size and family
  • toggle refresh mode (On Type / On Save)
  • force a full re-render (Refresh Now)
  • open the compiled PDF

Settings

Setting Type Default Description
latexPreview.debounceMs number 100 Delay (ms) before re-parsing after a non-math edit
latexPreview.mathDebounceMs number 5000 Delay (ms) before re-rendering when the cursor is inside math. Render also fires on save and when the cursor leaves the math span
latexPreview.refreshMode string "onType" "onType" re-renders on every keystroke (after debounce); "onSave" re-renders only on save. Save always triggers a refresh in either mode
latexPreview.scrollSync boolean true Enable bidirectional scroll sync
latexPreview.mathRenderer string "katex" Math rendering engine (currently only KaTeX)
latexPreview.tikzRenderer string "auto" TikZ backend: "auto" uses local TeX if available, falls back to WASM; "local" requires a TeX install; "wasm" uses the built-in renderer only
latexPreview.tikzTimeout number 30000 Timeout (ms) per TikZ diagram

Architecture

 User edits .tex file
       |
       v
 [VS Code Extension Host]
   onDidChangeTextDocument
       |  (debounce: debounceMs, or mathDebounceMs if cursor in math)
       v
 [Block Cache]
   splitIntoBlocks --> content-stable block IDs (djb2 + ordinal)
   diffBlocks      --> insert / update / move / delete patches
       |
       v
 [Webview Panel]
   Receives full HTML (initial) or patches (incremental) via postMessage
   Patch handler applies DOM ops, then KaTeX renders math via IntersectionObserver
   IntersectionObserver also drives reverse scroll sync
   Double-click handler jumps back to source

Incremental rendering pipeline

  1. Split the source into blocks at paragraph breaks, sectioning commands, and \begin{...} / \end{...} boundaries. Long prose environments (proof, theorem, lemma, proposition, corollary, definition, example, remark, abstract) are further split on blank lines into sub-blocks so editing one paragraph of a long proof doesn't re-render the whole proof.
  2. ID each block with djb2(source) + ordinal, so identical content keeps the same ID across edits. Insertion in the middle of the document doesn't renumber later blocks.
  3. Diff the new block list against the cached one. Output is a sequence of insert, update, move, and delete patches. A move is detected via a max-old-position walk so blocks moved to the end are still recognised.
  4. Render each updated/inserted block to HTML once, then ship the patch list to the webview in 50-block batches with a generation counter so stale patches are dropped.
  5. Math is rendered lazily: each <span class="math"> is observed; KaTeX runs when the span scrolls into view, with an LRU cache keyed by source so re-typing the same $...$ is free.

Math-aware debounce

mathCursorDetect.ts walks the document text up to the cursor offset, tracking line comments, backslash escapes, an env stack, and the four math delimiter pairs. If the cursor is inside math, edits use mathDebounceMs (default 5 s) instead of debounceMs (default 100 ms). The pending render flushes immediately on:

  • save (always, even in onSave mode)
  • the cursor moving out of the math span
  • pressing the Refresh Now button

Key components

File Purpose
src/extension.ts Entry point. Registers the preview command.
src/preview/previewPanel.ts Webview lifecycle. Listens to document changes, picks the right debounce, ships full or patch updates, manages TikZ rendering and include-file watchers.
src/preview/scrollSync.ts Bidirectional scroll sync with feedback-loop suppression.
src/preview/mathCursorDetect.ts Forward-scanning detector that decides whether a given cursor offset is inside a math context.
src/parser/latexParser.ts Thin wrapper around @unified-latex/unified-latex-util-parse.
src/parser/astToHtml.ts AST-to-HTML transformation. Emits data-source-line for scroll sync. Handles 100+ LaTeX constructs, including the prose sub-block wrappers.
src/parser/blockSplitter.ts Splits source into blocks; sub-splits prose environments on blank lines; assigns content-stable IDs.
src/parser/blockDiffer.ts Diffs old vs. new block lists into insert/update/move/delete patches.
src/parser/blockCache.ts Owns the block list across edits. Routes to fast-path (patches) or slow-path (full re-render) and exposes the KaTeX macro table.
src/parser/macroExpander.ts Expands \newcommand, \renewcommand, \def, \DeclareMathOperator with argument substitution and recursion-depth limiting.
src/parser/labelResolver.ts Tracks section/equation/figure/table/theorem numbering; resolves \ref/\eqref/etc. to numbered links.
src/parser/bibParser.ts Regex-based BibTeX parser. Resolves \bibliography and \addbibresource.
src/parser/fileResolver.ts Resolves \input/\include paths with cycle detection and caching.
src/parser/tikzRenderManager.ts Routes TikZ rendering between local TeX and the WASM backend, with timeout and queuing.
src/parser/tikzRenderer.ts WASM TikZ-to-SVG via node-tikzjax. Caches by content hash.
src/webview/preview.js Browser-side: patch handler, viewport-aware KaTeX with source cache, scroll sync, toolbar controls, double-click-to-jump.
src/webview/preview.css Theming and styling for all rendered LaTeX elements.

LaTeX-to-HTML mapping

LaTeX HTML
\section{...} <h2>
\textbf{...} <strong>
\emph{...} <em>
$...$ <span class="math"> rendered by KaTeX on demand
\begin{itemize} <ul> with <li>
\begin{enumerate} <ol> with <li>
\begin{theorem} <div class="env-theorem"> with label (split into sub-blocks per paragraph)
\begin{align} Display math block for KaTeX
\begin{tabular} <table> with rows/cells
\begin{figure} <figure> with <figcaption>
\includegraphics{...} <img> (resolved to webview URI)
\footnote{...} Superscript number + text at block bottom
\href{url}{text} <a href="url">
\maketitle Renders collected title/author/date block
\begin{tikzpicture} Async-rendered SVG
Unknown macros Content rendered, command name shown in dim gray

Scroll sync

  • Editor to preview: listens to onDidChangeTextEditorVisibleRanges, sends the top visible line to the webview, which finds the closest element with data-source-line <= line and scrolls to it. If no such element exists (editor is in the preamble), the preview snaps to the top.
  • Preview to editor: an IntersectionObserver in the webview tracks which elements are visible and reports the topmost line back; the extension calls editor.revealRange().
  • Both directions suppress the reverse direction for 150 ms after acting to prevent oscillation. Content updates suppress reverse sync for 500 ms so an incoming patch doesn't make the editor jump.

Tech Stack

  • Language: TypeScript (extension), JavaScript (webview)
  • LaTeX Parsing: unified-latex -- PEG-based parser producing an AST
  • Math Rendering: KaTeX -- fast client-side math rendering, viewport-driven
  • TikZ Rendering: local TeX if available, otherwise node-tikzjax -- WASM-based minimal TeX for TikZ-to-SVG
  • Bundler: esbuild
  • Testing: Jest + ts-jest

Building from Source

cd latex-realtime-preview
npm install
npm run build       # compile and bundle
npm run watch       # watch mode for development
npm run test        # run tests

To package as a .vsix:

npx @vscode/vsce package

Limitations

  • No exact layout: page breaks, margins, column layouts, and float positioning are not replicated
  • Approximate math: KaTeX covers most LaTeX math but not all packages
  • TikZ: only packages supported by your TeX install (or by node-tikzjax in WASM mode) will render; complex diagrams may fail or hit the timeout
  • No PDF output: this is a preview tool, not a compiler (the PDF button opens an existing PDF or runs pdflatex)
  • Contact us
  • Jobs
  • Privacy
  • Manage cookies
  • Terms of use
  • Trademarks
© 2026 Microsoft