TeXSmith
TeXSmith is a Python package and CLI tool to convert Markdown or HTML documents into LaTeX or Typst. It is designed to be extensible via templates and integrates with MkDocs for generating printable documents from documentation sites.
TL;DR
pip install texsmith
texsmith input.md input.bib -o build/ --build
Check the installed version with texsmith --version or in Python with texsmith.get_version().
Key features
- TMark Markdown – The TMark parser reads every Markdown source, so callouts, containers, data tables, counters and cross-references mean the same thing in the editor, on the site and in the PDF.
- Typed IR with multiple backends – Documents are parsed into a typed intermediate representation, run through TeXSmith's IR passes, resolved, and emitted as LaTeX (default) or Typst (experimental) via
--format. - Template-first runtime – Bundle multiple fragments into slots, merge front matter metadata, and emit LaTeX projects ready for Tectonic or latexmk with Docker-friendly manifests.
- CLI and Python parity – The Typer-powered CLI wraps the same ConversionService you can consume as a library, making CI/CD and notebooks behave like local runs.
- Actionable diagnostics – Every finding, from the Rust parser or from TeXSmith, prints in one shape with a stable code.
--strictrefuses to build a PDF from a document that has one,--diagnostics-jsonhands the lot to an editor or CI, and--deprecatedkeeps 0.6 spellings from failing a strict run while you migrate. - Extensible converters – Add IR passes, redefine a construct's contract macro in a fragment or template, or ship diagram transformers (Mermaid, Draw.io, Svgbob) that plug directly into the pipeline.
Installation
# uv (recommended for isolated CLI installs)
uv tool install texsmith
# pip / pipx
pip install texsmith
pipx install texsmith
TeXSmith targets Python 3.10+ and expects a LaTeX distribution (TeX Live, MiKTeX, or MacTeX) when you pass --build with the default LaTeX backend. Optional converters such as Mermaid try a Playwright exporter first, then a local CLI, then Docker (minlag/mermaid-cli); --diagrams-backend pins one, and you can register your own with texsmith.adapters.transformers.register_converter.
To build with the Typst backend (--format typst), install the embedded compiler as an extra:
pip install "texsmith[typst]"
# or with uv
uv tool install "texsmith[typst]"
This bundles the typst PyPI package, so no system binary is required. A system typst on PATH (Homebrew, cargo install typst-cli, or a GitHub release) is detected automatically as a fallback. See the Output backends guide for details.
Platform notes
- Linux – Install TeX Live (full) via your package manager or
install-tl. When running inside CI containers, cache~/.texliveYYso repeated latexmk runs stay fast—or use the default Tectonic engine to minimise setup. - macOS – Use MacTeX or
BasicTeXplus the tlmgr packages reported bytexsmith --template <name> --template-info. Homebrew’smactexcask works well when paired withuv. - Windows – TeXSmith runs via native Python or WSL. For PDF builds we recommend MiKTeX + PowerShell, or WSL2 with TeX Live and Docker Desktop (needed for Mermaid).
- Docker workflows – Run
texsmith --buildinside a TeX Live container, mounting your project plus the template directory. Copy tlmgr prerequisites from--template-infoso images compile without network access.
See the Getting Started guide for a step-by-step walkthrough, verification commands, and Python API examples.
Documentation
Browse the full documentation at yves-chevallier.github.io/texsmith for:
- Getting Started: installation, prerequisites, and API snippets.
- CLI Reference: every flag, including the template inspector.
- Syntax: the TMark dialect, construct by construct.
- Migrating to TMark: what changed since 0.6 and what
tmark lint --fixrewrites. - API Reference: ConversionService, TemplateSession, IR passes, and plugins.
- Template Cookbook: practical recipes for slots, contract macros, packaging, and testing.
- Diagnostics: the finding format,
--strict,--deprecated,--diagnostics-json. - Release Notes: TeXSmith feature history plus template/TeX Live requirements.
Template catalog
Inspect templates by name or path to understand their slots, metadata attributes, TeX Live requirements, and declared assets:
texsmith --list-templates # discovery order: built-ins, packages, local, home
texsmith --template article --template-info # one template's slots, attributes, tlmgr packages
texsmith --template ./templates/nature --template-info # or a local path
texsmith --template article --template-scaffold ./templates/mine # copy one to edit
Use this command before wiring slots or when you need to confirm which tlmgr packages to preinstall in CI.
Examples
The examples/ directory includes reproducible demos:
examples/paper– end-to-end render with bibliographies and latexmk (or Tectonic with--engine tectonic).examples/diagrams– Mermaid and Draw.io conversions.examples/tmark– the TMark syntax construct by construct, with diagram/front-matter overrides.
Each example ships build instructions inside docs/examples/index.md.
Project layout
src/texsmith/
├── readers/ tmark.parse — the one reader
├── ir/ the generated Python mirror of tmark's IR schema, plus walkers
├── passes/ the IR passes (include, glossary, var, title, snippet, assets,
│ doi, emoji, scripts | slots, headings, highlight)
├── writers/ what stays Python-side of the writers: escaping, asset naming,
│ the Typst document wrapper
├── diagnostics/ the one diagnostic shape, its codes, the sink and file table
├── templates/ the built-in templates (article, book, letter, snippet)
├── fragments/ the ts-* fragments that define the contract macros
├── core/ conversion orchestration, documents, bibliography, templates
├── adapters/ LaTeX engines, diagram transformers, Docker, MkDocs plugins
└── ui/cli/ the Typer CLI
The MkDocs companion is a separate workspace package, packages/mkdocs_texsmith.
Core architecture highlights
ConversionServiceis the single orchestrator behind both the CLI and the library. Provide aConversionRequest, get aConversionResponsecarrying either aConversionBundleor aTemplateRenderResult.- A construct is rendered by a contract macro a
ts-*fragment provides, not by a template-side partial. The writer names the fragment it needs inRequires.fragments, so activation is by construction; redefining the macro is how a template restyles the construct. TemplateRendererowns slot aggregation and LaTeX assembly.TemplateSessionfocuses on session state, template options, and bibliography tracking.- Slot directives from front matter, CLI flags, and programmatic overrides converge on one data model, so every entry point behaves the same.
- Every finding — from tmark or from TeXSmith — is one
Diagnosticin one shape, gated by--strictand dumped by--diagnostics-json.DiagnosticEmitterdecides where they are shown (CLI usesCliEmitter; libraries can plug in their own). - Fragments use a
BaseFragment+ config dataclass model (fragment = YourFragment()export referenced byfragment.tomlentrypoints). No legacy factories remain.
Programmatic conversions with ConversionService
from pathlib import Path
from texsmith import ConversionRequest, ConversionService
service = ConversionService()
request = ConversionRequest(
documents=[Path("docs/index.html")],
bibliography_files=[Path("references.bib")],
template="article",
render_dir=Path("build"),
)
prepared = service.prepare_documents(request)
response = service.execute(request, prepared=prepared)
print("Main TeX:", response.render_result.main_tex_path)
for record in response.documents[0].diagnostics:
print(record.severity, record.code, record.message)
If you only need a quick conversion, the high-level helpers (texsmith.Document, texsmith.convert_documents, texsmith.TemplateSession) continue to work, but they now reuse the same ConversionService plumbing as the CLI.
Upgrading from 0.6? Migrating to TMark lists every changed spelling and what
tmark lint --fixrewrites;CHANGELOG.mdhas the release history.
Render pipeline
TeXSmith parses every document into a typed intermediate representation (IR) and then emits a backend from that IR:
tmark.parse → IR → TeXSmith passes → tmark.resolve → tmark.write → LaTeX | Typst
- Readers produce the IR:
tmark.parsefor a Markdown source, and the one reader; an input is a Markdown source. - IR (
texsmith.ir.model) is a typed, backend-neutral node tree generated from tmark's committed schema. Semantic hints travel asSpan/Divattributes rather than backend strings. - Passes (
texsmith.passes) are pureDocument → Documentfunctions doing the work a writer cannot: includes, assets and diagrams, DOI lookups, moustaches, snippets, slots, headings, font scripts, glossary entries. - Writers are tmark's. Each construct is emitted as a fixed macro or
environment, and the fragment named in
Requires.fragmentsdefines it — redefining that macro is how a template overrides a construct's look.
Resolution happens once, over the whole document, so numbering and
cross-references are consistent across slots. --numbering tmark moves the
numbers of figures, tables, listings, equations and sections into that single
resolve, making the .tex and the .typ print identical numbers.
Select the backend with --format {latex,typst}. See the
Output backends guide, the
pipeline walkthrough and the
IR passes & fragment contracts reference.
Metadata
Release files for texsmith 0.9.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| texsmith-0.9.0.tar.gz | 7.9 MB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| texsmith-0.9.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 8.6 MB
Release files / texsmith-0.9.0.tar.gz
| Download URL | texsmith-0.9.0.tar.gz |
|---|---|
| Size | 7.9 MB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
66ce5179dae05fc22bb9cd0d567333fe395df741549b60a9a2a0003a4e23618a
|
|
BLAKE2b-256 checksum How to use checksums |
69525570f6e84238bb0878ac4a977c04ebfdf29246a190afd27d27834dae7cc5
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 17, 2026.
Transparency logRelease files / texsmith-0.9.0-py3-none-any.whl
| Download URL | texsmith-0.9.0-py3-none-any.whl |
|---|---|
| Size | 661.1 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
4a5b918aad6789422f623da61233b6bdab474c1a78a670ca4e99c94032adb900
|
|
BLAKE2b-256 checksum How to use checksums |
08b3a31658fdd25294ee25b94b5030476aaedcc55ac133460cab652ad5d1878a
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 17, 2026.
Transparency log