tecgonic

package module
v0.0.0-...-6b60686 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Feb 10, 2026 License: MIT Imports: 13 Imported by: 0

README

tecgonic

A Go library that compiles LaTeX documents to PDF using the Tectonic engine compiled to WebAssembly. No native TeX installation required.

Features

  • Pure Go — the Tectonic engine runs as WASM via wazero (no CGo)
  • Self-contained bundle download — fetches the TeX Live bundle on first use
  • Concurrent compilation — each Compile call gets its own isolated WASM instance
  • WASM compilation cache — optional on-disk cache cuts startup from ~1.4 s to ~50 ms

Quick start

package main

import (
	"context"
	"os"

	"github.com/mgilbir/tecgonic"
)

func main() {
	ctx := context.Background()
	bundleDir := os.Getenv("HOME") + "/.cache/tecgonic/bundle"
	cacheDir := os.Getenv("HOME") + "/.cache/tecgonic/wasm-cache"

	// Download the TeX bundle (~800 MB, one-time).
	tecgonic.PrepareBundle(ctx, bundleDir, "", false, tecgonic.WithProgress(os.Stderr))

	// Create compiler and generate format file (one-time).
	compiler, _ := tecgonic.New(ctx,
		tecgonic.WithDefaultBundleDir(bundleDir),
		tecgonic.WithCompilationCache(cacheDir),
	)
	defer compiler.Close(ctx)
	compiler.GenerateFormat(ctx, bundleDir)

	// Compile LaTeX to PDF.
	pdf, _ := compiler.Compile(ctx, []byte(`\documentclass{article}
\begin{document}
Hello, World!
\end{document}
`))
	os.WriteFile("output.pdf", pdf, 0o644)
}

See examples/simple for a complete runnable example.

WASM compilation cache

Creating a Compiler with New() involves compiling the Tectonic WASM module, which takes ~1.4 s. Pass WithCompilationCache(dir) to cache the compiled module on disk. Subsequent calls load the cached result in ~50 ms — a ~26x speedup.

compiler, err := tecgonic.New(ctx,
	tecgonic.WithDefaultBundleDir(bundleDir),
	tecgonic.WithCompilationCache("/path/to/cache"),
)

Benchmark results (AMD Ryzen 9 6900HX):

BenchmarkNew/NoCache       1   1360 ms/op   79 MB/op   117k allocs/op
BenchmarkNew/WithCache    22     51 ms/op  6.8 MB/op    31k allocs/op

The cache directory can be shared across processes. The first invocation populates the cache; all later invocations (including from different processes) read from it.

Building the WASM module

The pre-built WASM artifact is included under wasm/. To rebuild it from the Tectonic source:

make wasm

This uses Docker to cross-compile Tectonic to wasm32-wasip1. See the Dockerfile for details.

Thanks

This project would not be possible without:

  • Tectonic — a modernized, complete, self-contained TeX/LaTeX engine. Tectonic does all the heavy lifting of turning LaTeX into PDF; tecgonic simply makes it callable from Go.
  • wazero — a zero-dependency WebAssembly runtime for Go. wazero makes it practical to embed the Tectonic WASM binary in a pure-Go library with no CGo and no external dependencies.

Documentation

Index

Constants

View Source
const DefaultBundleURL = "https://relay.fullyjustified.net/default_bundle_v33.tar"

Variables

This section is empty.

Functions

func PrepareBundle

func PrepareBundle(ctx context.Context, destDir, bundleURL string, force bool, opts ...PrepareBundleOption) error

PrepareBundle downloads and extracts a Tectonic TeX Live bundle to destDir.

The bundle is an "itar" format: a tar archive where most entries are individually gzip-compressed. Metadata entries (like SVNREV) may not be compressed. Files are extracted to a flat directory structure.

If destDir already contains SHA256SUM and force is false, the download is skipped. After extraction, call Compiler.GenerateFormat to generate the latex.fmt format file.

Types

type CompileError

type CompileError struct {
	ExitCode int32  // 1=TeX error, 2=panic/trap
	Logs     string // stderr output captured from tectonic
	WasmErr  error  // underlying wazero error (for traps), nil for normal TeX errors
}

CompileError represents a failure during LaTeX compilation.

func (*CompileError) Error

func (e *CompileError) Error() string

func (*CompileError) IsPanic

func (e *CompileError) IsPanic() bool

IsPanic returns true if the error is a WASM engine trap (exit code 2).

func (*CompileError) IsTexError

func (e *CompileError) IsTexError() bool

IsTexError returns true if the error is a TeX compilation error (exit code 1).

func (*CompileError) Unwrap

func (e *CompileError) Unwrap() error

Unwrap returns the underlying wazero error for errors.Is/errors.As chaining.

type CompileOption

type CompileOption func(*compileConfig)

CompileOption configures a single Compile() call.

func WithBundleDir

func WithBundleDir(dir string) CompileOption

WithBundleDir overrides the bundle directory for this compilation.

func WithFontsDir

func WithFontsDir(dir string) CompileOption

WithFontsDir overrides the fonts directory for this compilation.

func WithOutput

func WithOutput(w io.Writer) CompileOption

WithOutput streams the compiled PDF to the given writer instead of returning it as a byte slice. When set, Compile returns (nil, nil) on success.

func WithStderr

func WithStderr(w io.Writer) CompileOption

WithStderr tees tectonic's diagnostic output to the given writer.

type Compiler

type Compiler struct {
	// contains filtered or unexported fields
}

Compiler compiles LaTeX documents to PDF using the Tectonic engine via WASM. It is safe for concurrent use; each Compile call gets its own WASM instance.

func New

func New(ctx context.Context, opts ...CompilerOption) (*Compiler, error)

New creates a new Compiler, initializing the WASM runtime and pre-compiling the Tectonic module. This is a one-time cost.

func (*Compiler) Close

func (c *Compiler) Close(ctx context.Context) error

Close releases the WASM runtime and all associated resources.

func (*Compiler) Compile

func (c *Compiler) Compile(ctx context.Context, texSource []byte, opts ...CompileOption) ([]byte, error)

Compile compiles the given LaTeX source to PDF. Each call creates an isolated WASM instance with its own filesystem.

func (*Compiler) GenerateFormat

func (c *Compiler) GenerateFormat(ctx context.Context, bundleDir string, opts ...GenerateFormatOption) error

GenerateFormat generates the LaTeX format file (latex.fmt) in the bundle directory. This must be called once after extracting a bundle before compilations can succeed. If latex.fmt already exists in bundleDir, this is a no-op.

type CompilerOption

type CompilerOption func(*compilerConfig)

CompilerOption configures a Compiler at creation time.

func WithCompilationCache

func WithCompilationCache(dir string) CompilerOption

WithCompilationCache enables caching of the compiled WASM module on disk. Subsequent New() calls with the same directory will skip WASM compilation.

func WithDefaultBundleDir

func WithDefaultBundleDir(dir string) CompilerOption

WithDefaultBundleDir sets the default bundle directory for all compilations.

func WithDefaultFontsDir

func WithDefaultFontsDir(dir string) CompilerOption

WithDefaultFontsDir sets the default fonts directory for all compilations.

type GenerateFormatOption

type GenerateFormatOption func(*generateFormatConfig)

GenerateFormatOption configures a single GenerateFormat() call.

func WithGenerateFormatStderr

func WithGenerateFormatStderr(w io.Writer) GenerateFormatOption

WithGenerateFormatStderr tees tectonic's diagnostic output to the given writer during format generation.

type PrepareBundleOption

type PrepareBundleOption func(*prepareBundleConfig)

PrepareBundleOption configures a PrepareBundle call.

func WithProgress

func WithProgress(w io.Writer) PrepareBundleOption

WithProgress enables progress reporting to the given writer. Download progress (bytes/percentage) and extraction progress (file count) are reported.

Directories

Path Synopsis
examples
simple command
Command simple demonstrates the full tecgonic workflow: download a TeX bundle, generate the format file, and compile LaTeX to PDF.
Command simple demonstrates the full tecgonic workflow: download a TeX bundle, generate the format file, and compile LaTeX to PDF.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL