This extension is inspired by the work done by Physically Based Rendering: From Theory To Implementation by Matt Pharr, Wenzel Jakob, and Greg Humphreys.
Initial extension activation is read-only: it discovers the project without writing source or HTML. Saving inputs or running Literate: Process triggers generation. Markdown preview supplies an editor preview. A headless CLI uses the same generation engine, so VS Code is not required to regenerate or check a project. Invalid projects produce diagnostics without replacing generated files. Book publication is separate and always explicit.
Markdown previews receive Literate's document-scoped theme. The extension no
longer injects the legacy global style.css; the surrounding editor UI retains
its own theme.
Use the literate programming paradigm to write your programs. Documents that end
with the extension .literate will be processed.
Literate documents are written with regular Markdown. The CommonMark specification is followed through the use of the markdown-it library. The code fence has been extended to include fragment identifiers and their related settings.
If a root index.literate exists, it is processed first, followed by documents
linked from it in link order. Remaining .literate documents are processed in
sorted path order; the index controls ordering, not exclusion.
The index.literate can contain a fence with SETTINGS on its info line. This
fence will be hidden from HTML, but hosts settings for controlling some aspects
of processing. Key=value pairs are given each on their own line. The recognized
keys for source/HTML processing are template, authors, and theme.
LaTeX export additionally reads the publication font settings described below.
The template should point to an
existing file containing an HTML template. The string [CONTENT] will be
replaced with the rendered HTML from the literate document. The string
[AUTHORS] will be replaced with <meta /> tags for author information.
[THEME] inserts the selected theme's complete <style> element; put it in the
HTML template's head. Legacy templates without [THEME] receive the stylesheet
alongside [CONTENT], so their content remains themed.
Code fragments can be created by adding <<some identifying string>>= to the
info line of a code fence, separated by a colon : after the language identifier.
Adding to existing fragments is done through <<some identifying string>>=+.
A top-level code fragment has a .* at the end of the identifying string:
<<some identifying string.*>>=. The top-level fragment should include a file
name followed by whitespace and ending in a dollar sign:
<<some top level.*>>=./CodeFile.cs $.
The file name is relative to the workspace folder. It can contain subfolders, which will be automatically created during code generation .
After the file name you can specify extra settings, currently just
template=filename, where filename points to a file with a source template.
The string [CODE] in the source template will be replaced with the generated
source code.
Code fragments can reference other code fragments in code by using the code
fragment tag <<some identifying string>>. To emit literal delimiter text inside
a code fragment, escape the opening chevrons: \<<some identifying string>>.
The backslash is removed from the generated code and rendered code block.
If a fragment use is indented the indentation will be maintained for its realization. This makes it suitable for use with languages like Python that use indentation to denote scope.
The command Literate: Process (literate.process) processes all workspace
folders. Edits to referenced source/HTML templates also regenerate automatically;
external input create/change/delete events are debounced per workspace. Associate
*.literate files with Markdown to enable the editor providers.
Associate *.literate with Markdown, open a trusted local workspace, and
configure literate.languageServers in User settings. Hover over a code symbol
or type inside a named fragment: after a short pause, Literate automatically opens
suggestions when the server has matching results. Ctrl+Space remains available.
Fragment-name suggestions remain available inside unfinished << tags. Language
services also include signature help, snippets and completion details, code
navigation, and mapped diagnostics.
Automatic completion is scoped to mapped fragment code, including template-backed
outputs. Identifier typing and the server's advertised trigger characters (such
as TypeScript's .) are supported without enabling Markdown-wide quick suggestions.
Literate does not trigger language suggestions in prose, fence headers, fragment
reference markers or ordinary .md files. Cursor/editor changes and Escape cancel
pending suggestions. Only the latest typing position is retained while a server
starts or finishes another request.
To keep completion manual, set "literate.automaticCompletion": false in User or
workspace settings. No changes to [markdown].editor.quickSuggestions are needed.
Automatic triggering handles single-character insertions in a single empty
selection; undo/redo, replacements and multi-character/multiline paste do not
trigger it. VS Code reports a one-character paste like an insertion, so it can
trigger suggestions too.
Each entry is keyed by a canonical VS Code language ID and contains an absolute
server executable path, optional args, optional initializationOptions, and
optional configuration returned to server configuration requests. For example,
a TypeScript entry uses typescript and a Zig entry uses zig. Fence aliases
ts/js/tsx/jsx normalize to their corresponding language IDs. Configure each
language ID you want to request services for; a TypeScript-family session receives
all TypeScript/JavaScript-family output overlays for import resolution.
Executable settings are global-only; workspace overrides are ignored. Literate launches its own stdio LSP process per workspace/language on demand, without a shell. It does not attach to another extension's private server, install tools, or download servers. Installing a language extension alone is not sufficient: its server must be available as a standalone stdio LSP executable. Configured servers are trusted programs with normal access to the workspace, not sandboxed. Remote extension hosts and non-file workspaces are not supported.
Verified server configurations:
- TypeScript 7:
TypeScriptTeam.native-previewsupplies a server executable inside its installation. The tested build useslib/tscwith arguments["--lsp", "--stdio"].code --locate-extension TypeScriptTeam.native-previewreports the extension directory. This is not the older JavaScripttsccommand. - typescript-language-server: a standalone alternative available through Mason,
launched with
["--stdio"]. Hover/completion on the actual template-backedGrabbedStateListsource is verified. It can select the workspace TypeScript version: with TypeScript 4.9, our disk-absent alias/dependency fixture returnedanywhere TypeScript 7 resolved types. Keep generated dependencies on disk if needed. SetinitializationOptions.disableAutomaticTypingAcquisitiontotrueto prevent this server's automatic typings installer from downloading packages. - Zig: use the ZLS executable selected by
ziglang.vscode-zig, with no arguments. Its ZLS language server output channel identifies the path after activation. SetinitializationOptions.zig_exe_pathto the absolute Zig compiler path when necessary. Tested with ZLS/Zig 0.16.0; TypeScript was 7.0.2.
Server paths may change when an owning extension updates. Failed sessions remain
stopped rather than repeatedly launching; consult Literate Language Servers
in the Output panel and run Literate: Restart Language Servers after fixing
configuration. Changing literate.languageServers also resets sessions. The
channel reports successful startup, projection failures (including missing
templates and expansion limits), and categorized snapshot/server errors without
printing source contents or server protocol payloads.
The server sees assembled outputs at their intended file: URIs, populated from
current literate buffers. Requests neither save nor generate files; ordinary
edit-triggered generation remains unchanged. Same-language generated dependencies
are synchronized too, even if their output files do not exist. Physical imports
and project configuration are read by the server. Source templates are included,
with unsaved template buffers taking precedence over disk. Only the code inserted
at [CODE] has fragment mappings; wrapper text cannot be edited through a fragment.
Supported services (subject to the server's advertised capabilities):
- Signature help: parameter hints in mapped code, including server-advertised trigger/retrigger characters and parameter labels/documentation.
- Completion: plain text and snippets, incomplete lists with follow-up requests, and lazy completion resolution. Resolve copies documentation and detail only; it cannot change the accepted insertion, range or label.
- Navigation: definition, type definition, implementation and references.
Generated-output targets map back to literate sources; validated ordinary local
file:targets can open directly. Repeated results are deduplicated. - Diagnostics: server problems map into literate sources in the separate
literate-languagecollection, without replacing Literate's fragment/engine diagnostics. The resource-scopedliterate.languageDiagnosticssetting defaults totrue; set it tofalsefor a resource or workspace to disable language diagnostics without disabling the other services. Open/edit activity can start configured servers for background diagnostics. Pull diagnostics are preferred when advertised; otherwise push diagnostics are used. - Code actions: explicitly invoked edit-only quick fixes and refactorings whose complete edit set maps into the current, uniquely expanded fragment. VS Code presents the action for review and applies it only after the user selects it.
Boundaries:
- Only named fragments reachable from a valid output receive services. Invalid
fragment graphs, missing templates, and expansion-limit violations return no
results. A request in a repeatedly used fragment or repeated
[CODE]slot uses its first deterministic expansion. Mutating code actions are stricter and reject repeatedly expanded fragments because one source edit would affect every use. - Completion replacement ranges must be single-line and remain within the active source mapping. Commands and auxiliary edits/auto-imports are not applied, including during resolve. Snippets do not grant access to other source ranges.
- Hover, completion and signature Markdown is untrusted; unsafe mapped ranges are rejected. UTF-16 positions and document open/change/close synchronization are required from servers.
- Unmapped diagnostics (for example, template-wrapper-only ranges) are omitted,
not attached to an invented source location. Diagnostic
relatedInformationis omitted. Matching versions and captured input freshness reject known stale reports; unversioned push freshness is best effort, since a late report cannot reliably be correlated with the source version that produced it. - Code actions must be explicit, eager
WorkspaceEdit.changesreplies for one generated URI. Every non-overlapping edit must map into the current fragment. Commands, disabled or malformed actions, partial mappings, cross-file edits, file operations, annotations, snippets, repeated expansions and oversized edits are rejected as a whole. Onlyquickfixandrefactorkinds are accepted. - Interactive requests are serialized; overlapping requests can return no result. Cancelled or stale results are discarded. Language-server rename and formatting are not forwarded. Existing fragment-name completion, definition/reference navigation, rename and fragment code actions are unchanged.
- General server filesystem-watch registration is not forwarded. Restart servers if external dependency or project-configuration changes are not picked up.
Preview and generated HTML retain ordinary fragment-navigation links and add separate disclosure buttons for local fragment uses. Opening a disclosure shows the family's contributions without eagerly expanding the whole reference graph. Nested references can be explored in turn; cycles and depth limits stop locally. Without JavaScript, ordinary links remain usable.
Exploration is bounded: a 1 MiB serialized payload, eight nested layers, 256 KiB of conservatively accounted panel content per document, 200 open panels, and at most 200 unique contributions and 4096 segments per requested panel. Oversized views are rejected before their DOM is allocated, rather than silently truncated. Links from payloads accept only matching anchors, validated relative HTML paths, or narrowly shaped Literate editor capabilities. HTTPS destinations are reused only from an existing same-target baseline link. The extension independently validates editor capabilities; payloads cannot supply arbitrary commands.
All 70 HErmonica built-in palettes are available locally, with their original
case-sensitive names. Set the project theme in the root index.literate:
```SETTINGS
theme=rosepine-dawn
```rosepine-dawn is the default when omitted. Other choices include rosepine,
hermonica, catppuccin, gruvbox, gruvbox_light, nord, github_light,
tokyonight, and vscode_dark. See the theme catalogue
for the full set. Hyphens and underscores are significant.
The selection applies project-wide to prose, code fragments, syntax highlighting, tables, and Mermaid diagrams in both preview and default generated HTML. It is independent of VS Code's light/dark selection. Preview prefers unsaved root settings; CLI generation reads disk. Standalone Markdown previews use the default. Unknown or empty theme names produce a diagnostic and prevent output writes; preview falls back to the default while the setting is invalid. Chapter-local SETTINGS do not override the root theme. Saved input changes outside VS Code refresh the cached project state through filesystem watchers; Literate: Process remains available for an explicit refresh.
Generated pages embed their CSS, so nested chapters no longer depend on a relative
style.css path. Custom templates control their own Mermaid initialization; the
[THEME] placeholder supplies document CSS, not scripts. Palette provenance and
MIT attribution are preserved in THIRD_PARTY_NOTICES.md.
This version requires VS Code 1.96 or newer for the bundled renderer's modern browser APIs. Literate bundles Mermaid 12.0.0 locally. No Mermaid extension, account, or CDN is required to preview ordinary Mermaid fences:
```mermaid
flowchart TD
A[Write literate source] --> B[Preview the diagram]
```Associate *.literate with Markdown, then use Markdown: Open Preview to the Side.
Diagrams update with the document and follow the project's selected palette. Syntax
errors appear beside the original diagram source without stopping other diagrams.
Named literate fragments with the Mermaid language remain code, not diagrams.
The preview uses strict rendering, disables callbacks, and limits diagrams to 50,000 characters and 500 edges. Mermaid directives and YAML frontmatter are currently rejected to keep rendering configuration controlled by Literate. Literate handles its own diagram containers; other Mermaid extensions are optional.
This support is for the VS Code preview. Generated HTML still uses the existing browser/CDN rendering path; offline, embedded-SVG HTML export is not implemented.
From a checkout, use Node.js 22 LTS (>=22.12) and the pinned Yarn version through Corepack:
yarn install --immutable
yarn literate generate
yarn literate check
yarn testgenerate updates source and HTML; check reports missing or stale outputs without
writing. An optional final argument selects another project root. The CLI reads
saved files, whereas the extension uses open buffers; do not run both generators
concurrently against the same project.
After yarn build:cli, the direct executable is node out/cli-entry.js
(for example, node out/cli-entry.js check). out/cli.js is a library module,
not the executable entry point.
See CONTRIBUTING.md and the development chapter for the self-hosting workflow. Edit the literate chapters rather than their generated TypeScript.
Use the Command Palette's Literate: Export LaTeX (literate.exportLatex) or
Literate: Export PDF (literate.exportPdf). M5 integrates the explicit M1–M4
publication pipeline; saves and ordinary generation still never export a book.
Publication requires a trusted, local desktop workspace with file: folders
on POSIX. Remote extension hosts/workspaces, web, virtual filesystems and Windows
are rejected. Node, Pandoc, TeX, Chromium and the project must be on the same host.
This is trusted-input processing, not a TeX/Lua sandbox.
Configure these machine-scoped settings in User settings, not workspace settings:
literate.publication.nodePath: required explicit absolute path to external Node.js >=22.12. Electron (including VS Code's runtime) is not supported; there is no PATH-based Node discovery. Workspace executable overrides are ignored.literate.publication.browserPath: optional explicit absolute path to an installed sandbox-capable Chromium. Required for Mermaid publication; omit for books without diagrams. No browser discovery or downloader is provided.literate.publication.fontManifest: optional safe root-relative JSON path, such asfonts.json, resolved inside the selected workspace folder. See portable fonts for its format and licensing obligations.
Pandoc must be on PATH; PDF also requires the local TeX tools and packages listed
under M4. Installed packages need no checkout,
node_modules, or build tools: publication ships three self-contained runtime
files (publication-helper.cjs, publication-mermaid-worker.mjs, and
publication-mermaid-browser.js). External tools and fonts are not bundled or
installed automatically.
- The active editor's workspace folder is selected when available; otherwise choose a workspace folder in the picker.
- Pick the page size:
a4,a5,letter, orlegal. - Enter margins in top,right,bottom,left order, in millimetres, for example
18,16,22,20. Each must be 5–50 mm and leave at least an 80 × 100 mm text area. - Choose a
.texor.pdfsave path inside the selected root. The Save dialog selects the output, not a request to save your input documents. Unsafe paths, symlinks and protected input aliases are rejected.
Only successful choices are remembered, separately per workspace root and export
kind. Defaults are A4, 20,20,20,20, and publication.tex or publication.pdf.
Prompt cancellation starts no helper and writes nothing.
After the prompts and on entering the shared queue, publication captures a fresh
snapshot of the selected project's .literate documents. Open file-backed buffers
supply their current text, including unsaved edits, new files not yet on disk and
empty documents. It never calls saveAll; untitled/virtual documents are not
project inputs. Later edits do not change that captured export. Binary assets and
font files are read from disk only, not from editor buffers.
Publication and source/HTML generation use one serialized extension queue; a second publication is rejected while one is in progress. Initial activation is read-only—no source/HTML output until a save or explicit processing. Invalid source/HTML generation templates do not disable publication. This queue does not coordinate separate CLI processes or other VS Code instances: do not run those writers concurrently.
The notification provides cancellable progress. Cancellation or revocation before commit aborts publication and rolls back staged changes, preserving existing outputs. A cancellation arriving after commit does not undo the output: committed success is reported truthfully. Removing the selected folder or disposing the extension cancels active work and suppresses subsequent remember/open actions; any already committed output remains published.
The helper has a 10-minute execution deadline, after which the extension sends
SIGTERM for graceful transaction cleanup. Cancellation uses the same cooperative
path. If cleanup has not acknowledged cancellation after 30 seconds, progress and
the output channel report that publication remains locked. The queue is retained
until the helper exits—there is no force kill or hard termination guarantee.
The Literate Publication output channel records results, errors and compiler warnings. Success offers Open Output, which opens the exported file. Success with warnings is not a clean-typography guarantee; inspect the channel and PDF. See M5 acceptance for the headless, real-host and isolated-package evidence and its limits.
M6 is complete with the approved explicit author syntax. It works through the
existing latex/pdf CLI and VS Code publication commands, generated HTML and
Markdown preview; there is no separate annotation export command. M7 is not
claimed complete. See M6 acceptance
for recorded tests, real PDFs and native-host evidence.
```TERM transaction "Output transaction"
A transaction publishes related outputs together, or preserves the previous set.
```
See the [transaction contract](term:transaction).
```NOTE
This explanation belongs to this point in the prose.
- **Important:** publication is explicit.
- Use `check` before generating; see the [contract](term:transaction).
```Fence headers are case-sensitive: TERM key "Display title" or NOTE without
arguments. A key matches ASCII [A-Za-z][A-Za-z0-9_.:-]{0,99} (1–100 characters).
The required title is a JSON-quoted string, at most 200 Unicode code points;
an empty title is accepted. Trailing header whitespace is ignored. Markdown-it
controls fence boundaries. Both bodies allow paragraphs, ordered/unordered lists,
emphasis, strong emphasis, inline code, links and line breaks. Raw HTML, images,
headings, blockquotes, tables, strikethrough, indented/fenced code and nested
TERM/NOTE/Mermaid fences are rejected. Inline code is allowed; code blocks are not.
Raw author TeX is not an escape hatch into the rail.
Only explicit [label](term:key) links are term uses. Keys are exact and
case-sensitive; destinations are percent-decoded once. There is no heuristic
matching of words, labels or display titles. Different keys may share a title.
Malformed headers/bodies report annotation-header / annotation-body;
duplicate definitions report annotation-duplicate, and unresolved uses report
annotation-missing or annotation-ambiguous, with source locations. These
errors block publication. Tolerant preview leaves unresolved links inert rather
than guessing. Term links in headings intentionally fail export with
annotation-heading: moving headings into contents/running matter would replay
rail markers. Put the link in prose below the heading instead.
These are four distinct things:
- A TERM definition remains in the prose with its title and definition body.
- The Term index links to definitions; it does not relocate their bodies.
- A page-local term lookup in the PDF rail contains the title and final definition page, not the definition body. Repeated uses of one key on the same physical page share one entry; a use on another page gets another entry. Prose link labels retain their explicit wording and linked definition-page suffix.
- A NOTE is a numbered explanation in source encounter order, with a marker in print prose and its controlled body in the rail. It is not a term definition or a term lookup. Links inside annotation bodies still resolve, but do not recursively create rail markers.
Annotated projects get both Term index and Fragment index. Print indexes
link to term definitions and fragment contribution pages. HTML/preview indexes
also link to definitions, additions and reference sites, and appear only at the
root (index.literate, or the first document if absent), not on every chapter.
Screen TERM sections and numbered NOTE asides remain in document flow; screens
have no physical-page rail. Preview uses the existing semantic navigation route,
including current unsaved canonical documents. Projects without TERM/NOTE
annotations retain their previous output and geometry: no new indexes or rail.
Annotated books reserve a 25 mm right-hand rail plus a 5 mm gap, always on the right in one-sided layout. The requested outer page margins are preserved: the body's right edge moves left by 30 mm (internally its right margin increases by 30 mm). The reduced body must still be at least 80 × 100 mm.
- A5 with default 20 mm margins leaves
148 - 20 - 20 - 30 = 78 mm: rejected. - A5 with top/right/bottom/left 18/16/22/20 mm leaves an 82 × 170 mm body: valid geometry. Use the asymmetric example under PDF/LaTeX export below.
- Unannotated books do not reserve the extra 30 mm.
Placement uses actual shipped page positions, not estimated source positions.
PDF publication requires both reference convergence and a stable book.litrail
placement certificate. Entries stay on their reference page without overlap;
there is no split, shrink, spill-to-another-page or other fallback. Stable vertical
or horizontal rail overflow fails publication, as does non-convergence, preserving
the previous PDF. A valid page size alone does not guarantee that its notes fit.
Export allows at most 1,000 terms and 1,000 notes. Each source annotation body and each controlled rail text value is limited to 131,072 UTF-16 code units; aggregate source/declaration and rendered declaration budgets are 2,097,152 code units. These are the implementation's nominal “128 KiB” / “2 MiB” limits, measured by JavaScript string length, not UTF-8 byte limits. Encoded identifiers also consume declaration budgets. The rail additionally bounds use markers at 10,000; exceeding a limit fails rather than truncating content.
M4 is finished: compile a supported, trusted literate project explicitly with the CLI (omit the root to use the current directory):
yarn literate pdf path/to/project --output books/book.pdf --paper a4 --margin 20mm --jsonThe .pdf destination is relative to the selected project root, not the working
directory; absolute paths and paths outside the root are rejected. pdf shares
latex options: --paper a4|a5|letter|legal, --margin, --margin-top,
--margin-right, --margin-bottom, --margin-left, --font-manifest,
--browser, and --json. Geometry defaults and bounds are described below.
Arguments take separate values. --keep-build is PDF-only. For example:
yarn literate pdf path/to/project --output books/book.pdf --paper a5 \
--margin 20mm --margin-top 18mm --margin-right 16mm --margin-bottom 22mm \
--font-manifest fonts.json --browser /usr/bin/chromium-browser --keep-build --jsonOmit --browser for books without Mermaid; diagrams require an explicitly
selected installed, sandbox-capable Chromium as described under M3. Portable
fonts are opt-in; otherwise the configured families must be installed.
Prerequisites: Pandoc, latexmk, LuaLaTeX (lualatex), and kpsewhich on PATH,
plus KOMA-Script (scrbook.cls) and the TeX packages fontspec, geometry,
fvextra, needspace, xcolor, microtype, amssymb, amsmath, graphicx,
ulem, and hyperref. Nothing downloads or installs tools, browsers, fonts, or
packages. The default compiler is POSIX-only because process-tree termination
uses POSIX process groups; .tex export remains available without this compiler.
Font availability is checked by fontspec at the start of compilation, not by the
package preflight.
Compilation uses a private temporary stage and private TeX caches, with a fixed
book.tex entry regardless of the requested PDF name. Both the latexmk version
preflight and build use -norc, so latexmk rc files are ignored. Shell escape is
disabled, but this is not a TeX/Lua sandbox: trusted inputs only. Each preflight
process has a 15-second timeout; the build has a 180-second deadline and
max_repeat = 5. Process output and the compiler log are bounded at 4 MiB; the
PDF is bounded at 64 MiB. Publication requires reference convergence: genuine
final-log undefined-reference/citation or rerun warnings and exhausted passes
fail the build, rather than matching similar words in ordinary document text.
Only the requested PDF is published—no TeX, logs, auxiliary files, font/image
companions, tangled source, or HTML. Precommit failures or cancellation preserve
the original PDF. SIGINT, SIGTERM, and SIGHUP are handled throughout the
compiler and PDF CLI lifetime, with transaction cancellation checkpoints through
commit. A signal after commit does not undo successful publication or interrupt
its cleanup. Do not run concurrent writers.
Normally the private build is removed on success or failure. --keep-build
retains it on success or compilation failure and reports its path in
publication.buildDirectory (no directory exists for errors before staging).
The caller owns cleanup: retained TeX, logs, caches, fonts and assets may contain
sensitive material and licensed files. publication.warnings is an array of
deduplicated final compiler warnings, including missing glyphs and overfull boxes;
JSON mode reports them there, while human mode prints warnings and any retained
build path to stderr. Successful compilation does not imply clean typography.
SOURCE_DATE_EPOCH is honored via the inherited build environment, but PDF byte
determinism is not promised. The latex ... --output books/book.tex command is
unchanged and never compiles the book. Ordinary generation, activation and saves
do not compile PDFs; M5 adds the explicit extension commands described above.
See M4 acceptance for real CLI evidence and
yarn test:pdf.
The CLI can export a supported literate project as a typeset book source:
yarn literate latex path/to/project --output books/book.tex --paper a4 --margin 20mmOmit path/to/project to use the current directory. The .tex destination is
relative to the selected project root; absolute paths and paths outside it are
rejected. Paper choices are a4, a5, letter, and legal; defaults are A4 and
20 mm uniform margins. Override individual sides with --margin-top,
--margin-right, --margin-bottom, and --margin-left; unspecified sides use
--margin. Values accept decimal millimetres only, each from 5 to 50 mm, leaving
at least an 80 × 100 mm text area. For example:
yarn literate latex path/to/project --output books/book.tex --paper a5 \
--margin 20mm --margin-top 18mm --margin-right 16mm --margin-bottom 22mmRun
yarn literate latex --help for bounds, or add --json for machine-readable
results. Arguments use separate values rather than --option=value.
Export requires Pandoc on PATH (tested with 3.7.0.2), but never runs a TeX
engine. Mermaid additionally requires the explicit system browser described below;
exports without diagrams need no browser. It writes the requested LaTeX file,
local image/diagram companions and, only with --font-manifest, font/license
companions—not tangled source, HTML, or a compiled book PDF. Export is always
explicit: ordinary generation, extension activation and saves never launch the
publication browser. M5 supplies explicit extension export actions, not automatic
PDF compilation. Source, template, font and image inputs are protected
(including existing hard-link aliases), and all writes use the
same transaction/recovery mechanism as generation. Re-exporting identical content
leaves the output unchanged. Do not run concurrent writers.
The existing root SETTINGS theme selects from all 70 palettes; the default is
rosepine-dawn. Fonts default to Latin Modern Roman for prose, Monofur Nerd Font
for headings/references, and Lilex Nerd Font for code. Ligatures
remain enabled; copying code from PDF may change operators, so use original or
tangled source for executable code.
Select publication font roles in the root index.literate SETTINGS fence:
```SETTINGS
theme=rosepine-dawn
font-body=Latin Modern Roman
font-heading=Monofur Nerd Font
font-code=Lilex Nerd Font
font-fragment=Monofur Nerd Font
font-note=Latin Modern Roman
font-code-ligatures=on
```These are the defaults. font-fragment covers both declarations and references;
font-note covers running matter, navigation, and reference page numbers. If
font-note is omitted it inherits the selected font-body. Font roles currently
apply to LaTeX only—not HTML or VS Code preview. Chapter-local settings cannot
change them. Use font-code-ligatures=off to disable contextual substitutions
(calt); font families may implement other ligatures through different features.
Lilex has native regular, bold, italic and bold-italic faces, so default code
comments use real italics rather than synthetic slant.
Family names accept 1–100 ASCII letters, digits, spaces, dots, or hyphens,
starting with a letter or digit. Paths and TeX options are not accepted. Repeated
settings keep the last valid value, but any invalid occurrence blocks export.
Without --font-manifest, LaTeX export does not install a selected family or
verify that it is available; PDF compilation checks availability through fontspec.
Lilex and ordinary family overrides use native style lookup.
Only the exact legacy D2CodingLigature Nerd Font Propo code family retains its
automatic slant declaration. To keep that former default, explicitly set
font-code=D2CodingLigature Nerd Font Propo.
Add --font-manifest publication-fonts.json to latex. The manifest filename,
font paths, and license paths are all relative to the project root, not the
manifest directory. No Fonts directory or installed-font discovery occurs.
For example, a manifest entry looks like:
{"version": 1, "families": {"Example Serif": {
"regular": "fonts/serif-regular.otf", "bold": "fonts/serif-bold.otf",
"italic": "fonts/serif-italic.otf", "boldItalic": "fonts/serif-bolditalic.otf",
"licenses": ["fonts/OFL.txt"]
}}}Map every distinct family selected by the root settings (including defaults and
inherited note fonts). Keys match family names exactly. Each entry requires all
four faces and one or more license paths; unknown fields, missing faces, unsafe
paths, missing/non-regular files, and symlink components are errors. Only .ttf
and .otf containers are supported. There is no automatic synthesis or fallback;
string mappings always use the supplied files without FakeSlant/FakeBold.
Mapping several string faces to one file does not synthesize styles.
For Lilex, map LilexNerdFont-Regular.ttf, LilexNerdFont-Bold.ttf,
LilexNerdFont-Italic.ttf, and LilexNerdFont-BoldItalic.ttf as plain strings under
Lilex Nerd Font; no synthesis is needed.
For families without italic faces, italic and boldItalic may instead explicitly
request slant. If you explicitly select D2 instead of Lilex, its family entry can use:
"D2CodingLigature Nerd Font Propo": {
"regular": "fonts/D2-Regular.ttf", "bold": "fonts/D2-Bold.ttf",
"italic": {"file": "fonts/D2-Regular.ttf", "slant": 0.2},
"boldItalic": {"file": "fonts/D2-Bold.ttf", "slant": 0.2},
"licenses": ["fonts/D2-LICENSE.txt"]
}Place that entry in the version-1 manifest's families object, alongside explicit
Latin Modern and Monofur mappings for the other default roles. Synthesis objects
require exactly file and slant; the latter must be a finite JSON number from
0.01 through 0.3, inclusive. Regular and bold remain string-only mappings.
The exporter copies each explicit file and emits ItalicFeatures={FakeSlant=0.2}
and/or BoldItalicFeatures={FakeSlant=0.2} only for opted-in faces. This preserves
italic D2 code comments without an automatic fallback. Bold-italic slant should
normally use the actual bold file: synthetic weight and arbitrary fontspec features
are not supported. The renderer revalidates paths and slants for API callers too.
All entries are validated and all declared paths are protected from output
collisions, including unselected entries; only selected families are copied.
Font and license bytes are preserved exactly. Companions receive deterministic
ASCII names under a lit-fonts-<hash> directory beside the .tex; raw input paths
never enter TeX. The book, fonts, and licenses use one recoverable transaction.
Re-export preserves unchanged files' mtimes. Old companions from previous selections
are not pruned: use a fresh export directory for a minimal distribution.
Move the .tex and its companion directory together. Compile from the .tex
directory (or use latexmk -cd as below). Providing licenses is an explicit author
responsibility: export does not check redistribution rights, parse font binaries,
verify family/face metadata, or guarantee glyph coverage. Font/package installation,
font collections, variable-font axes, and synthesis other than explicit italic-face
slant are outside this portable-font slice. M4 adds explicit PDF compilation above.
As with the existing filesystem transaction, concurrent changes to inputs are not
sandboxed; use a trusted,
quiescent project.
To compile later, install the named fonts (or export companions) and LuaLaTeX packages fontspec,
geometry, fvextra, needspace, xcolor, microtype, amsmath, amssymb,
ulem, hyperref, graphicx, and KOMA-Script (scrbook), then explicitly run, for example:
latexmk -cd -lualatex -interaction=nonstopmode -halt-on-error -no-shell-escape books/book.texCompile trusted projects only: disabling shell escape is not a complete TeX sandbox. No fonts or packages are downloaded by the export command.
Put a PNG, JPEG or single-page PDF image in its own Markdown paragraph:

> Paths are relative to the source chapter, unlike font-manifest paths. Parent steps are allowed only within the project root. Remote URLs, absolute paths, queries/fragments, malformed URI escaping, symlink components and non-regular files are rejected. Inline images, formatted alt text, raw SVG and other formats are explicitly unsupported. PDF inclusion uses page one; supply a single-page figure. Extensions must match binary signatures, but export is not a full image validator or a sanitizer: compile trusted assets only.
Identical bytes share a companion under lit-assets-<hash> beside the .tex.
Original names never enter TeX. All source aliases remain protected inputs.
The limits are 1024 image occurrences, 32 MiB per image, 128 MiB unique bytes and
4096 caption characters. Missing/invalid inputs and converter failures prevent
publication; text, font/license and image companions use one rollback transaction.
Old orphan companions are not automatically removed.
Move the whole export directory and compile there. The graphic fits both the current list/quote width and the page text height minus a measured caption and spacing budget, preserving aspect ratio. Every paper size and all four margins participate through LaTeX geometry: A5 with top/right/bottom/left 18/16/22/20 mm has a 112 × 170 mm body. A tall figure may move to a new page, leaving a preceding heading behind. Captions leaving less than 24 pt for the graphic fail compilation. Long unbreakable caption words can still cause TeX warnings, and extremely dense figures may become unreadable when reduced; inspect compiler logs and the PDF. No clipping or rasterization is added by the fitting code. An input PDF's own CropBox still determines its visible content.
Ordinary Mermaid fences can become local SVG+PDF companions; LaTeX includes the PDF using the same width/height fitting as local illustrations. For example:
yarn literate latex path/to/project --output books/book.tex \
--browser /usr/bin/chromium-browserSupply an absolute path to an installed, sandbox-capable system Chromium.
The verified path is /usr/bin/chromium-browser; puppeteer-core neither downloads
nor discovers a browser. Install the checkout's development dependencies and use
Node >=22.12 on POSIX; Windows is rejected because worker/browser process-tree
cleanup relies on POSIX process groups. Without --browser, Mermaid export fails
explicitly; pre-rendered local PNG/JPEG/PDF figures remain a browser-free option.
The publication bundle includes the full pinned Mermaid 12.0.0 families,
registering ZenUML 1.0.1 and tidy-tree 1.0.1, with no family allowlist.
Rendering uses the selected palette and system sans-serif fonts, separate from
book font roles and --font-manifest. Browser/font differences can affect layout;
not every theme/family configuration has been exhaustively verified.
Remote assets, image/icon resources, directives/frontmatter, authored HTML/CSS,
and interactions are blocked. Double-quote labels containing command words such
as style, classDef, linkStyle, click, link or links (for example,
A["click to continue"]): quoted text and comments are masked for the keyword
scan, not exempted from the other safety checks. Limits are 64 unique diagrams,
50,000 source characters each, Mermaid's 500-edge cap, 16,384 px per side and
16 million pixels of geometry; artifacts are capped at 4 MiB SVG, 16 MiB PDF and
32 MiB combined per batch. The worker has a 120-second batch deadline, 15-second
browser-operation timeouts and a 64 KiB log cap.
Generated SVG+PDF companions join the same rollback transaction as TeX, local images and optional fonts/licenses. Move the whole export directory to compile; raw local SVG input remains unsupported. See M3 acceptance for fixture and security evidence, including full-book compilation with remaining typography issues.
Publication supports [local](#heading), [chapter](chapter.literate#heading)
and the existing [HTML alias](chapter.html#heading) convention. Whole-document
links still work. Paths resolve relative to the source document, must stay inside
the project, and must name an included document. Percent-encoded paths/fragments
are decoded once; local queries, empty fragments, malformed escapes and unsafe
URL forms are rejected. HTTP/HTTPS/mailto links retain their external semantics.
Heading slugs use visible parsed inline text (including code spans and link labels), not formatting delimiters or link destinations:
- Normalize Unicode to NFC and lowercase without locale-specific rules.
- Keep Unicode letters, marks, numbers, whitespace, hyphens and underscores;
remove other punctuation/symbols. Trim and collapse whitespace to
-. - Normalize the final slug to NFC again before duplicate grouping and ID encoding: lowercasing or removing punctuation can create new composable sequences.
- Use
sectionif the result is empty. Thus# *Café* and \x_y`becomescafé-and-x_y`; fragments are case-sensitive but NFC-normalized. - Reserve all natural slugs in a document. A unique heading keeps its slug.
Duplicate groups assign every occurrence numbered slugs (
foo-1,foo-2, …), skipping reserved/allocated names. With twoFooheadings and a literalFoo-1, use#foo-2and#foo-3for the duplicates,#foo-1for the literal. An unnumbered#foois ambiguous and reports the available alternatives.
Opaque Pandoc heading IDs encode the canonical document path and allocated slug in a separate collision-safe namespace. Line offsets, chapter order and unrelated headings do not change them. Renaming paths/headings or adding colliding titles can change IDs; duplicate ordinals follow source order, not edit-stable author IDs. Forward links, setext headings and headings inside lists/quotes are supported without flattening containers. Titles and labels stay escaped Pandoc data.
Compatibility: generated HTML currently emits plain Markdown-it headings
without IDs. The extension leaves heading IDs to VS Code's preview parser and
has no local slug implementation. Publication uses familiar lowercase/hyphen
slugs where practical, but does not promise exact host-preview punctuation or
duplicate behavior. In particular it rejects ambiguous duplicate links instead
of silently selecting the first. This slice does not change HTML/preview output
or add explicit {#id} syntax.
Missing documents (missing-publication-document), missing headings
(missing-publication-heading), ambiguous headings
(ambiguous-publication-heading) and unsupported URL forms
(unsupported-publication-link) report source locations before conversion.
Current limits: inline/unsupported images, tables and raw author tokens produce diagnostics rather than disappearing. Missing fragments and cycles also block export. Missing tools, browser/conversion failures and publication diagnostics leave existing output untouched. Full-book compilation is not a clean-typography guarantee; inspect compiler logs and the resulting PDF.
Historically, M1 provided explicit CLI export of the supported prose/fragment subset to a portable LaTeX book, with optional licensed font companions. Its sign-off excluded whole-repository Mermaid export (now covered separately by M3) and compilation on a machine without the documented fonts/packages. See the criterion-by-criterion acceptance review for evidence and remaining limitations.
Fragment families have collision-safe f- targets; individual accepted definitions
and additions have distinct c- targets. IDs encode exact names as fixed-width
UTF-16 hex, with canonical document path and a one-based per-family/document
ordinal for contributions. Prose shifts and unrelated insertions preserve them;
renames, moves and insertions into the same family can change contribution IDs.
These are logical identities, not user-editable slugs. LaTeX destination names
encode the logical target again with a lit- prefix.
HTML and preview now render definitions and uses from the same publication model
as LaTeX. Definition labels and genuine uses link to the family's base; Previous,
Base, and Next controls navigate individual contributions when available.
Links are native, keyboard-focusable anchors with descriptive accessible names.
Generated HTML uses chapter-relative .html#target URLs and needs no navigation
JavaScript. Escaped \<<literal>> examples remain literal, never links.
Associate *.literate with Markdown. Same-document links use native logical-ID
anchors and stay in the preview. Cross-document fragment links open the source
editor at the current declaration through Literate's registered URI handler,
independently of markdown.preview.openMarkdownLinks. Ordinary Markdown links
retain the host's behavior; Literate does not change editor preferences.
Cross-document URLs are opaque session capabilities, resolved as complete
vscode://jesterking.literate/navigate/<session>/<token> URIs through
env.asExternalUri (using the host's URI scheme). Returned routing data is kept
unchanged. No command URLs, custom click script, socket or browser bridge is used.
Only accepted semantic targets in a trusted, currently open workspace get a
capability. The handler rediscovers current sources, overlays unsaved buffers,
validates the target and safe existing path, and calls showTextDocument on the
canonical document with an explicit selection. Navigation retains a clean disk
snapshot and rebuilds the current-buffer overlay after opening, so discarding
another input cannot leave its old unsaved text in the final model. It never falls
back to #L links, which can produce divergent buffers in VS Code 1.138.0.
Pending or failed URL resolution renders plain text; successful resolution requests a preview refresh. Capabilities expire on extension disposal or workspace removal; re-adding the same workspace can mint fresh links but never revives old tokens. Missing/renamed targets and unsafe paths fail closed. Restricted Mode disables cross-document fragment navigation, not local anchors. The cache retains at most 4,096 workspace/target entries, with at most 16 URL resolutions in flight; additional targets remain text while that limit is reached.
External URLs can become invalid without notification. Successful URLs are cached
for at most 60 seconds; one expiry timer requests a refresh, and targets still
rendered renew through asExternalUri without changing their capability tokens.
Unused targets do not keep renewing. Failures remain text and may retry on a later
render after a 60-second cooldown (refresh the preview to request that retry).
Removal/disposal cancels expiry work, and late results cannot revive removed entries.
This bounds recovery but cannot guarantee a URL stays valid during its cache lifetime.
data-literate-target preserves logical identity independently of the opaque URL.
A third-party fence renderer that ignores Markdown-it's highlight option may
suppress code-use links.
Preview rendering is synchronous and read-only. It overlays the current rendered source and other open, unsaved buffers on the owning workspace's last discovered snapshot. Empty buffers remove definitions immediately. Missing references remain unlinked; unmatched stale tokens (including changed declaration settings) never borrow old semantic ranges. Raw invalid source is checked before host text normalization. Rendered root settings and semantics use the same source overlay, and snapshot refresh notifications follow installation of the new destinations. Closed-file changes become available after the existing filesystem refresh completes; Literate: Process explicitly refreshes the snapshot after a read failure. The save/output transaction workflow is unchanged.
Whole-block syntax highlighting preserves context across references. Both
js: <<name>>= and js : <<name>>= delegate normalized js. Preview also preserves
host aliases such as jsonc/json5, tsx/typescriptreact, and py3. The syntax
merge advances monotonically, and snapshot indexes avoid per-use model scans.
All 70 palettes,
ordinary fences, source-token maps and Mermaid handling remain in place.
Screen comments retain the existing hiding policy, but genuine references inside
comments remain visible and navigable. M2 deferred the fragment index; M6 now
adds it for annotated projects only. Heading-ID parity remains deferred; M2 did
not redesign the website or add Mermaid export assets.
Automated tests use the real engine and activated preview plugin, including independent destination/label assertions, cached tokens, unsaved buffers, remote snapshots, all palettes, linear merge work and real Pandoc target parity. A bounded VS Code 1.138.0 acceptance test dispatched real browser Tab/Enter input, checked native focus/outline and ARIA names, and verified local scrolling before and after an unsaved source shift. On the unmodified installed host, cross-file navigation, an unsaved destination edit and navigation again reused the same canonical dirty TextDocument, selected the actual moved declaration, and retained exactly one document identity. Real pointer input also passed. Screen-reader behavior, physical-keyboard interaction, minimum-version host acceptance and complete editor scroll synchronization remain unverified. See the M2 acceptance and manual checklist.
Development validation: LITERATE_TEST_PANDOC=1 yarn test enables real Pandoc
integration tests. Add LITERATE_TEST_PANDOC_LIFECYCLE=1 to exercise both
30-second converter deadlines on POSIX; ordinary tests skip these slow cases.
For opt-in real A4/A5 portable PDF acceptance, use yarn test:publication --font-manifest /path/to/font-project/fonts.json; see
the acceptance workflow and its limits.
It checks relocated, unmodified CLI exports and requires caller-supplied licensed
fonts, LuaLaTeX/latexmk and Poppler. It is not part of the normal test suite.
CLI and editor generation stage the entire changed batch before replacing output
files. Originals remain in private .literate-txn-* directories until installation
finishes. If staging or installation fails, the writer restores originals and
removes newly installed files and empty directories it created. Unchanged files
are not rewritten; local permission bits are preserved for existing files.
If rollback itself fails, the error lists affected paths and recovery directories.
Keep those directories: their numbered .backup files may contain your
originals. Inspect them before manual recovery. A committed, cleanup failed error
means new outputs are installed but some temporary material could not be removed;
it is not an unsuccessful commit. CLI written statuses follow that distinction.
This is a rollback-capable batch, not a crash-durable database transaction. Readers can observe intermediate renames, and power loss or process termination does not trigger automatic recovery. Do not run concurrent writers. Remote-provider rename semantics and metadata guarantees vary; see the transaction chapter for the contract.
The HTML documentation generated from this repository .literate files can be
found here : https://jesterking.github.io/literate/ . Here creation of code fragments
is explained in more detail.
Extension author: Nathan jesterKing Letwory