latex-html
v0.1.0
Published
Bounded LaTeX math subset to HTML (no MathJax)
Maintainers
Readme
LaTeX subset → HTML
TypeScript project that turns a small, documented subset of LaTeX math into HTML and CSS. There is no MathJax and no other third-party math libraries—only the tooling you explicitly add (TypeScript, Webpack, ESLint, Prettier).
Allowed npm dependencies
Runtime logic uses no production dependencies. devDependencies are limited to:
typescriptwebpack,webpack-cli,ts-loader,html-webpack-plugineslint,@eslint/js,typescript-eslint,eslint-config-prettierprettier@types/node(for the CLI)
Supported LaTeX (v1)
Article mode (when \documentclass appears)
A minimal article pipeline runs: strips % line comments, reads \title, \author, \date from the preamble, takes the body between \begin{document} … \end{document}, and renders:
\maketitle(from the extracted metadata;\date{\today}expands to the current locale date)\section{…},\subsection{…}(optional star after command name is skipped)\LaTeX→ small “LᵃTₑX”-style logo\todayin running text- Preamble-only commands that appear in the body (
\usepackage,\documentclass, …) are skipped with their arguments - Plain paragraphs split on blank lines
- List environments:
\begin{itemize} … \item … \end{itemize},enumerate, anddescription(with optional\item[label]); nested lists of the same type are supported
Anything else is not a full LaTeX engine (no hyperref, babel, custom packages, full amsmath, etc.). A few amsmath-like constructs are supported in math mode (aligned, align, bmatrix, cases); see the Math mode section.
Math mode (default when there is no \documentclass)
- Letters / digits: runs of Latin letters form one symbol; runs of digits form one number token; other characters are single symbols (e.g.
+,(,)). - Whitespace: spaces are optional between atoms; rendered as a small gap where explicit space tokens appear.
- Grouping:
{…}. - Delimiters:
\[ … \]for display-style math (centered block);\( … \)groups the inner math like{…}without changing layout. - Aligned equations:
\begin{aligned} … \end{aligned}and\begin{align} … \end{align}with&between columns and\\between rows (e.g.a &= b && \text{note}for extra columns before a comment). - Matrices:
\begin{bmatrix} … \end{bmatrix}with&between columns and\\between rows (same cell rules asaligned). - Piecewise (
cases):\begin{cases} … \end{cases}with&separating the value and condition on each row,\\between rows; left brace is drawn to match the block height. - Delimiters:
\left…\rightwith a following delimiter (( ) [ ] \{ \} | . < >); the body grows with content (e.g. tall fractions). Use\left.or\right.for an empty side. - Scripts:
^and_with a braced or atomic operand (no double sub/sup on the same base without grouping). - Fractions:
\frac{numerator}{denominator}. - Roots:
\sqrt{x},\sqrt[n]{x}. - Vectors:
\vec{…}(arrow above the body). - Text:
\mathrm{…},\rm{…},\text{…}(balanced braces inside;\starts a command name that is copied literally into the text). - Symbol commands: a large set of backslash commands map to Unicode (Greek, Hebrew, binary operators, relations, negated relations, arrows, big operators, dots, logic, etc.). See
src/core/commands.ts. Coverage is aligned with common “symbols.pdf”-style tables (e.g. Rice CMOR LaTeX symbols PDF). Unknown\foois rendered as a literal\foosymbol.
Not supported: \usepackage, custom macros, most environments beyond aligned / align / bmatrix / cases, \not overlay, stretchable delimiters, many font packages (e.g. full \mathbb), and accents like \hat{ } beyond what maps to a single Unicode glyph. Tab & is only allowed inside aligned, align, matrix, and cases environments.
Commands
| Script | Description |
| ----------------------- | ------------------------------------------------------ |
| npm run build | Compile CLI (dist/) and browser bundle (dist-web/) |
| npm run build:cli | TypeScript compile for Node CLI only |
| npm run build:browser | Webpack production build for the demo |
| npm test | Build CLI then run Node’s test runner on test/*.test.mjs |
| npm run lint | ESLint |
| npm run format | Prettier (write) |
| npm run format:check | Prettier (check only) |
npm package
Requires Node.js 18+. The published tarball includes compiled dist/cli and dist/core (with .d.ts for TypeScript).
Install
npm install latex-htmlIf the package name is unavailable on the public registry, use a scoped name instead (e.g. @your-org/latex-html) and adjust package.json before publishing.
CLI (after install, node_modules/.bin is on PATH for npm scripts, or use npx):
npx latex-html examples/sample.tex -o out.htmlProgrammatic API (ESM):
import {
latexToHtmlDocument,
latexToMathHtml,
MATH_STYLES,
} from 'latex-html';MATH_STYLES is the CSS string embedded in full documents by latexToHtmlDocument; use it when you emit --fragment-style HTML and need styles on the page.
Publish (maintainers): ensure npm run build:cli succeeds, bump version, then npm publish (the prepare script builds dist/ before pack). Scoped public packages need npm publish --access public.
CLI
From a git checkout, run the compiled file directly:
node dist/cli/index.js [options] [file]When installed from npm, use the latex-html command (same options).
- With no file, input is read from stdin.
-o/--output <path>— write HTML to a file instead of stdout.--fragment— emit only the math<span class="mj-math">…</span>(no full document; not for articles).--math— treat input as math only, even if it contains\documentclass.-h/--help— usage.
Example (local build):
npm run build
node dist/cli/index.js examples/sample.tex -o out.htmlBrowser demo
After npm run build, open dist-web/index.html in a browser (or serve dist-web/ with any static server). The bundle live-renders the textarea using the same core as the CLI.
Layout
test/— Nodenode:testsuites against the compiled CLI core (dist/).src/core/— lexer, parser, AST, HTML emitter, sharedmathStyles.ts(CSS string used in CLI documents and injected in the demo).src/cli/— Node entrypoint.src/browser/— Webpack entry + HTML template.
The CLI is compiled with tsc (tsconfig.cli.json). The demo is bundled with Webpack (webpack.config.cjs, tsconfig.webpack.json). Imports use .js extensions in sources for Node ESM; Webpack resolves them to .ts via resolve.extensionAlias.
Expectations
This is not a replacement for MathJax’s feature set. It is a small, testable renderer for the subset above, with a clear place to extend the grammar.
