Interactive Demo
Try out LaTeX compilation below. Select an engine, configure options, and compile your LaTeX code.
Fonts must be referenced by filename rather than by font name, e.g. \setmainfont{FiraSans-Regular.otf} instead of \setmainfont{Fira Sans}.
Shell escape in this demo runs entirely in the browser through registered JavaScript handlers. It does not execute arbitrary native system commands. The syntax highlighting example uses a browser-side handler powered by PrismJS to emulate a small external command safely inside the WebAssembly workflow.
Features requiring unavailable native external tools, such as SVG/EPS conversion or bibliography processing with biber, are not supported unless a compatible browser-side handler is provided.
Input
PDF Preview
Compilation Log
Features
- XeLaTeX: Compile with XeTeX engine + bibtex8 + dvipdfmx
- PdfLaTeX: Compile with PdfTeX engine + bibtex8
- LuaLaTeX: Compile with LuaHBTeX engine + bibtex8
- Multi-file Support: Handle complex projects with multiple .tex and .bib files
- SyncTeX: Generate SyncTeX files for editor synchronization
- Browser Shell Escape: Register JavaScript handlers for controlled in-browser command emulation, such as the PrismJS syntax-highlighting example
- On-Demand Packages: Optional TeX Live remote endpoint fetches additional packages at compile time, beyond those bundled in
texlive-extra - All compilation runs entirely in the browser with no server required (aside from optional on-demand package fetching)
Installation
npm install texlyre-busytex
npx texlyre-busytex download-assetsUsage
import { BusyTexRunner, XeLatex, PdfLatex, LuaLatex } from 'texlyre-busytex';
// Combined mode (single WASM with all engines, default)
const runner = new BusyTexRunner({
busytexBasePath: '/core/busytex'
});
await runner.initialize();
const xelatex = new XeLatex(runner);
const result = await xelatex.compile({
input: '\\documentclass{article}\\begin{document}Hello\\end{document}',
bibtex: true,
makeindex: true,
rerun: true,
});
if (result.success && result.pdf) {
const blob = new Blob([result.pdf], { type: 'application/pdf' });
window.open(URL.createObjectURL(blob));
}
// Browser shell escape with a registered JavaScript handler
const shellEscapeResult = await xelatex.compile({
input: '\\documentclass{article}\\usepackage{xcolor}\\begin{document}\\input{highlighted-output.tex}\\end{document}',
shellEscape: true,
shellHandlerScripts: [
'/shell-handlers/highlight-handler.js'
],
additionalFiles: [
{
path: 'snippet-javascript.txt',
content: 'const message = "Hello from BusyTeX";\\nconsole.log(message);'
}
]
});
// Split mode (per-engine WASM, smaller downloads)
const pdftexRunner = new BusyTexRunner({
busytexBasePath: '/core/busytex',
engineMode: 'pdftex'
});
await pdftexRunner.initialize();
const pdflatex = new PdfLatex(pdftexRunner);
const pdfResult = await pdflatex.compile({
input: '\\documentclass{article}\\begin{document}Hello\\end{document}'
});
// Switch engines with split builds
const xetexRunner = new BusyTexRunner({
busytexBasePath: '/core/busytex',
engineMode: 'xetex'
});
await xetexRunner.initialize();
const xelatexSplit = new XeLatex(xetexRunner);
const xeResult = await xelatexSplit.compile({
input: '\\documentclass{article}\\begin{document}Hello\\end{document}'
});