@honzuvduch/typst_tools
v0.7.1
Published
NextTeX high-performance WebAssembly compilation suite and CLI for Typst
Readme
@honzuvduch/typst_tools
High-performance WebAssembly Typst compilation, introspection, rasterization, and bidirectional SyncTeX navigation engine for NextTeX.
📖 Overview
typst_tools is a Rust-powered WebAssembly compilation suite designed specifically for NextTeX. It provides a complete, self-contained implementation of the Typst compiler ecosystem without reliance on external renderer sessions or heavy multi-package runtimes.
Key Capabilities
- In-Memory Virtual File System (VFS): Complete shadow filesystem with multi-file
#includesupport, path normalization, chapter aliases, and transparent $1\times 1$ transparent PNG fallback for missing image paths. - Embedded & Dynamic Font Engine: Standard academic fonts (Linux Libertine, New Computer Modern Math, DejaVu Sans Mono) embedded directly into the WASM bundle, supplemented by on-demand web font loading.
- Multi-Format Document Export:
- Vector PDF: High-fidelity PDF generation via
typst-pdf. - Vector SVG: Full-document and page-by-page vector SVG generation via
typst-svg. - Native RGBA Rasterization: Direct pixel-perfect raster rendering via
typst-renderandtiny-skiainto raw byte buffers for zero-overhead HTML5<canvas>painting.
- Vector PDF: High-fidelity PDF generation via
- Bidirectional SyncTeX Navigation:
- Forward Jump (
jump_from_source): Resolves Monaco editor line and column to exact sub-pixel point coordinates $(x, y)$ on the rendered page. - Reverse Jump (
jump_from_click): Sub-pixel spatial hit-testing over document page frames resolves preview click coordinates back to source file, line, and column.
- Forward Jump (
- Instant Fast Syntax Checking (
check_syntax_fast): Validates Typst code in $< 0.5\text{ ms}$ on detached syntax trees without layout overhead, providing instant typing feedback. - Lossless AST Structural Inspection (
inspect_syntax_ast): Extracts headings, equations, tables, labels, and references directly from the Typst concrete syntax tree foreasyTagsvisual widgets and document outlines. - Typst Introspection & Symbol Catalog (
WasmTypstLibrary): Introspects global functions, parameters, documentation, and mathematical symbols for auto-completion palettes.
🏛️ Architecture
typst_tools/
├── src/
│ ├── lib.rs # WebAssembly exports (WasmTypstCompiler, WasmTypstLibrary)
│ ├── world.rs # typst::World implementation with comemo memoization
│ ├── fonts.rs # FontBook & Font storage combining bundled & dynamic fonts
│ ├── compiler/ # Compilation pipeline & structured diagnostic mapping
│ │ ├── mod.rs
│ │ ├── pipeline.rs # Compiler execution, world orchestration & timings
│ │ ├── compiler_diagnostic.rs # Structured diagnostic DTO
│ │ ├── diagnostic_range.rs # Source range DTO
│ │ └── compilation_result.rs # Compilation result DTO
│ ├── syntax/ # Instant CST syntax checking & lossless AST inspection
│ │ ├── mod.rs
│ │ ├── parser.rs # Fast syntax validator & AST walker
│ │ ├── visual_document.rs # Aggregated document visual model DTO
│ │ ├── visual_tag.rs # easyTags visual tag DTO
│ │ ├── visual_heading.rs # Document heading DTO
│ │ ├── visual_equation.rs # Math equation DTO
│ │ ├── visual_label.rs # Label definition DTO
│ │ ├── visual_reference.rs # Reference citation DTO
│ │ ├── visual_ignored_range.rs # Ignored syntax range DTO
│ │ ├── ast_summary.rs # AST outline summary DTO
│ │ ├── heading_item.rs # Outline heading item DTO
│ │ ├── syntax_error.rs # CST syntax error DTO
│ │ └── position_mapper.rs # Byte offset to line/column position mapper
│ ├── navigation/ # Bidirectional SyncTeX navigation & sub-pixel frame hit-testing
│ │ ├── mod.rs
│ │ ├── engine.rs # Navigation resolver & frame spatial search
│ │ ├── source_to_doc.rs # Source line/col to canvas point DTO
│ │ └── doc_to_source.rs # Canvas point to source line/col DTO
│ ├── vfs/ # In-memory virtual filesystem with path normalization & fallback
│ │ ├── mod.rs
│ │ ├── manager.rs # VFS storage, package mapping & fallback handlers
│ │ ├── entry.rs # Virtual file entry enum (Text, Binary)
│ │ └── batch_item.rs # Batch file mapping DTO
│ ├── dto/ # WebAssembly library & introspection DTOs
│ │ ├── mod.rs
│ │ ├── wasm_symbol.rs # Math & text symbol DTO
│ │ ├── lib_element.rs # Typst library element DTO
│ │ ├── lib_param.rs # Library function parameter DTO
│ │ ├── wasm_compile_status.rs # Compiler status DTO
│ │ └── page_info.rs # Rendered page dimension DTO
│ └── export/ # Document export coordinator
│ ├── mod.rs # Export coordinator
│ ├── pdf.rs # typst-pdf integration
│ ├── svg.rs # typst-svg integration (page-level & merged)
│ └── raster.rs # tiny-skia RGBA rasterizer (renderPage)
├── tests/
│ └── compiler_tests.rs # Native Rust integration test suite
└── Cargo.toml # Dependencies and wasm-opt build profile🚀 WebAssembly API Reference
WasmTypstCompiler
Main compiler instance managing document compilation, VFS, and SyncTeX navigation.
export class WasmTypstCompiler {
/**
* Creates a new compiler instance with a designated entrypoint file.
* @param mainPath Root document path (e.g. "/main.typ")
*/
constructor(mainPath?: string);
/**
* Adds or updates a text source file in the VFS.
* Skips re-parsing if text is unchanged, maintaining memoization.
*/
addSource(path: string, text: string): boolean;
/**
* Maps binary data (images, bibliographies) in the shadow VFS.
* Skips re-allocation if byte slice is identical.
*/
mapShadow(path: string, bytes: Uint8Array): boolean;
/**
* Maps multiple files in a single batch call, amortizing lock acquisition and WASM overhead.
*/
mapBatch(items: Array<{
path: string;
is_text: boolean;
text?: string;
binary?: Uint8Array;
}>): boolean;
/**
* Maps a @preview package source file into the VFS.
*/
mapPackageSource(
namespace: string,
name: string,
version: string,
path: string,
content: string
): boolean;
/**
* Maps a @preview package binary file into the VFS.
*/
mapPackageBinary(
namespace: string,
name: string,
version: string,
path: string,
data: Uint8Array
): boolean;
/**
* Checks whether a file exists in the VFS.
*/
hasFile(path: string): boolean;
/**
* Returns the byte size of a file in the VFS, or undefined if not found.
*/
getFileSize(path: string): number | undefined;
/**
* Retrieves the raw source text of a file in the VFS.
*/
getSourceText(path: string): string | undefined;
/**
* Returns all file paths currently mapped in the VFS.
*/
getAllFilePaths(): string[];
/**
* Returns the total count of files currently mapped in the VFS.
*/
getFileCount(): number;
/**
* Unmaps a file from the shadow VFS.
*/
unmapShadow(path: string): boolean;
/**
* Clears all files from the shadow VFS.
*/
resetShadow(): void;
/**
* Sets the default main entrypoint path.
*/
setMainPath(path: string): void;
/**
* Adds dynamic font bytes (TTF/OTF) into the compiler's font book.
* @returns Number of fonts successfully loaded
*/
addFont(bytes: Uint8Array): number;
/**
* Compiles the root document and returns compilation status, page count, and structured diagnostics.
*/
compile(): {
has_errors: boolean;
diagnostics: Array<{
message: string;
severity: "error" | "warning" | "info";
hints: string[];
file: string | null;
range?: {
start_line: number;
start_column: number;
end_line: number;
end_column: number;
start_byte: number;
end_byte: number;
};
line?: number;
column?: number;
raw: string;
}>;
page_count: number;
};
/**
* Exports the entire document to PDF bytes.
*/
compilePdf(mainPath?: string): Uint8Array | undefined;
/**
* Exports the document to a single merged SVG string.
*/
compileSvg(mainPath?: string): string | undefined;
/**
* Exports a specific page to an SVG string.
* @param pageIndex 0-indexed page number
*/
compileSvgPage(pageIndex: number): string | undefined;
/**
* Renders a page directly to raw RGBA pixmap via tiny-skia.
* @param pageIndex 0-indexed page number
* @param pixelPerPt Raster scale (e.g. 2.0 for high-DPI display)
*/
renderPage(pageIndex: number, pixelPerPt: number): {
width: number;
height: number;
pixel_per_pt: number;
rgba: Uint8Array;
} | undefined;
/**
* Resolves source line and column to page coordinates (Forward SyncTeX).
*/
jumpToPreview(filePath: string, line: number, column: number): {
page: number; // 1-indexed
x: number; // Points from left
y: number; // Points from top
width: number;
height: number;
} | undefined;
/**
* Resolves preview click coordinates to source code (Reverse SyncTeX).
*/
jumpToSource(pageIndex: number, xPt: number, yPt: number): {
file: string;
line: number; // 1-indexed
column: number; // 1-indexed
start_byte: number;
end_byte: number;
} | undefined;
/**
* Checks Typst syntax in < 0.5ms without layout overhead.
*/
checkSyntax(text: string): Array<{
message: string;
hints: string[];
line: number;
column: number;
end_line: number;
end_column: number;
start_byte: number;
end_byte: number;
}>;
/**
* Extracts headings, labels, and references from the syntax tree.
*/
inspectAst(text: string): {
has_errors: boolean;
errors: Array<...>;
headings: Array<{ level: number; title: string; line: number; column: number }>;
labels: string[];
references: string[];
};
}WasmTypstLibrary
Exposes Typst's standard library functions, parameter metadata, and symbol tables for visual UI affordances and autocomplete palettes.
export class WasmTypstLibrary {
constructor();
/**
* Returns all mathematical symbols and emoji variants from the Typst standard scope.
*/
getAllSymbols(): Array<{
name: string;
character: string;
module: string;
}>;
/**
* Retrieves documentation and parameter definitions for a function (e.g. "global.rect", "math.frac").
*/
getLibraryElement(name: string): {
name: string;
docs: string;
parameters: Array<{
name: string;
required: boolean;
named: boolean;
positional: boolean;
settable: boolean;
expected_types: string[];
docs: string;
}>;
};
/**
* Fast syntax checking on raw Typst text without compilation overhead.
*/
checkSyntax(text: string): Array<{
message: string;
hints: string[];
line: number;
column: number;
end_line: number;
end_column: number;
start_byte: number;
end_byte: number;
}>;
/**
* Parses the document directly into visual models (schema_version >= 2) with
* tags (including id, parent_id, args, is_complete), markup, headings, equations,
* labels, references, imports, and syntax errors.
*/
parseVisualDocumentFast(text: string): {
schema_version: number;
tags: Array<any>;
headings: Array<any>;
equations: Array<any>;
labels: Array<any>;
references: Array<any>;
ignored_ranges: Array<any>;
markup: Array<any>;
imports: Array<any>;
syntax_errors: Array<any>;
};
}
💻 Native Desktop CLI (typst-tools)
typst_tools includes a native CLI binary for offline desktop compilation, syntax verification, and template testing without launching the NextTeX web frontend.
Installation
# Build and install to ~/.cargo/bin
cargo install --path . --bin typst-toolsCLI Commands & Options
# Compile Typst document to PDF (default)
typst-tools compile main.typ -o output.pdf
# Compile to vector SVG
typst-tools compile template.typ --format svg -o preview.svg
# Fast sub-millisecond syntax check
typst-tools check chapters/01_introduction.typ
# Structural AST inspection (headings, labels, cross-references)
typst-tools inspect main.typ
typst-tools inspect main.typ --json| Option | Description |
| :--- | :--- |
| -o, --output <PATH> | Output destination file path |
| -f, --format <pdf\|svg> | Output format (pdf or svg) |
| -r, --root <DIR> | Project root for resolving #include and assets |
| --font-path <DIR> | Directory containing additional TTF/OTF fonts |
| --system-fonts | Scans /usr/share/fonts and ~/.local/share/fonts |
🛠️ Building and Testing
Prerequisites
- Rust toolchain (stable) with
wasm32-unknown-unknowntarget:rustup target add wasm32-unknown-unknown wasm-pack($>= 0.12$):cargo install wasm-pack
Build WebAssembly Bundle (Dual-Target)
NextTeX requires both bundler target (for Vite's vite-plugin-wasm) and web target (for worker standalone initialization):
# Automated dual-target build & NextTex node_modules sync
./build.shRun Native Tests
cargo testRun Full System Tests (from NextTex workspace)
# Compiler parity and performance comparison
./node_modules/.bin/vite-node tests/typst-compiler-comparison.test.ts
# Full NextTex test suite
./node_modules/.bin/vite-node tests/run-all.ts📄 License
MIT / Apache 2.0 (Dual-licensed).
