Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
100 changes: 79 additions & 21 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,10 @@ different connection and sync options.

`zn` is a single static binary with no runtime dependencies. Pick one:

> One optional feature is the exception: drawing LaTeX math as pictures
> (`math = "latex"`) runs TeX installed on your own computer, and zn does not
> include it. See [LaTeX math needs TeX on your computer](#latex-math-needs-tex-on-your-computer).

**Homebrew (macOS and Linux).** Install from the same tap as the desktop app:

```bash
Expand Down Expand Up @@ -624,31 +628,85 @@ sheet of your own, or `zen` for the built-in renderer).
- **`![[Note]]`** renders the note inline.
- **Mermaid** blocks draw as text through a pure-Go renderer, or as
pictures when `mmdc` is installed.
- **`[terminal] math`** picks the engine for display math. `typst`, the
default, renders `$$` blocks when `typst` is installed. `latex` also renders
`\[ \]`, `tikzpicture` and the amsmath display environments (`equation`,
`align`, `gather`, `multline` and the rest, starred or not), and ` ```tikz `
fences the way the desktop app draws them (`\usepackage` and
`\usetikzlibrary` lines above the picture are kept). It needs `pdftex` and
`pdftocairo` (poppler) on PATH; `zn doctor` names a missing one. A basic TeX
Live is enough: add the packages zn uses with
`tlmgr install standalone varwidth preview xcolor amsmath amsfonts mhchem pgf`
(or your distribution's TeX packages), and others later as your preamble
needs them. Packages come from `preamble.tex` next to `config.toml`, written
on the first render with `amsmath`, `amssymb`, `mhchem` and `tikz` with the
TikZ libraries the desktop loads (`arrows.meta`, `calc`, `positioning`,
`shapes`, `decorations.pathreplacing`, `intersections`, `patterns`); zn
never rewrites it. The desktop also loads `pgfplots` and `circuitikz` when a
fence uses them; for those, install them and add them to `preamble.tex`.
Pictures are cached in the user cache directory under `zn/tex`; zn deletes
the pictures and formats there that it has not used for 30 days. TeX can
read files by absolute path, so under `latex` a note can show in the preview
the contents of any file you can read. Leave latex off for vaults you do not
trust.
- **`[terminal] math`** picks the engine for display math: `typst`, the
default, renders `$$` blocks when `typst` is installed; `latex` uses TeX on
your computer (next section).
- **`render_timeout`** (seconds, default 10) bounds one diagram or math
render; **`render_concurrency`** (default 2) caps how many run at once and
takes effect after a restart.

### LaTeX math needs TeX on your computer

**zn does not include TeX.** `math = "latex"` runs two programs you install
yourself: `pdftex`, from a TeX distribution (TeX Live, MacTeX, MiKTeX), and
`pdftocairo`, from poppler. Until both are on your PATH, LaTeX blocks show
their source and the preview says which one is missing. `zn doctor` checks for
them and prints the install commands for your system.

macOS, with Homebrew:

```bash
brew install --cask basictex
brew install poppler
eval "$(/usr/libexec/path_helper)" # or open a new terminal
sudo tlmgr update --self
sudo tlmgr install standalone varwidth preview xcolor amsmath amsfonts mhchem pgf
```

Debian and Ubuntu:

```bash
sudo apt install texlive-latex-extra texlive-science texlive-pictures poppler-utils
```

Fedora:

```bash
sudo dnf install texlive-scheme-basic texlive-standalone texlive-varwidth texlive-preview texlive-xcolor texlive-amsmath texlive-amsfonts texlive-mhchem texlive-pgf poppler-utils
```

Arch:

```bash
sudo pacman -S texlive-basic texlive-latex texlive-latexextra texlive-science texlive-pictures poppler
```

Windows: install [MiKTeX](https://miktex.org), which fetches missing LaTeX
packages on first use, and poppler for `pdftocairo`, for example with
`scoop install poppler`.

Then turn it on in `config.toml` (or under `:settings`) and check:

```toml
[terminal]
math = "latex"
```

```bash
zn doctor
```

Pictures need a terminal that shows images (Kitty, Ghostty); others show the
source.

What it draws: `$$` and `\[ \]` blocks, `tikzpicture` blocks, the amsmath
display environments (`equation`, `align`, `gather`, `multline` and the rest,
starred or not), and ` ```tikz ` fences the way the desktop app draws them
(`\usepackage` and `\usetikzlibrary` lines above the picture are kept).
Packages come from `preamble.tex` next to `config.toml`, written on the first
render with `amsmath`, `amssymb`, `mhchem` and `tikz` with the TikZ libraries
the desktop loads (`arrows.meta`, `calc`, `positioning`, `shapes`,
`decorations.pathreplacing`, `intersections`, `patterns`); zn never rewrites
it, so add your own packages there (and install them with your TeX
distribution). The desktop also loads `pgfplots` and `circuitikz` when a fence
uses them; for those, install them and add them to `preamble.tex`.

Pictures are cached in the user cache directory under `zn/tex`; zn deletes
the pictures and formats there that it has not used for 30 days. TeX can read
files by absolute path, so under `latex` a note can show in the preview the
contents of any file you can read. Leave latex off for vaults you do not
trust.

### Vaults and servers inside the app

`:vault` (or `Space v`) lists every saved vault and server, with entries to
Expand Down
66 changes: 66 additions & 0 deletions docs/embedded-latex-coverage/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
# Embedded LaTeX: coverage audit (2026-10-27, parked)

Question: could zn render `math = "latex"` without the user installing TeX,
and would users lose anything? Decision: **not now**. zn keeps using the
user's own `pdftex` and `pdftocairo`; this folder keeps the evidence for a
later look.

## Method

`harness/corpus.py` writes `harness/corpus.json`: 90 math and 34 TikZ cases
covering every display form zn detects, amsmath, amssymb, mhchem, macros
defined in a block, colour, TikZ with each default preamble library, and
fences that add their own `\usetikzlibrary` or `\usepackage`. Each case ran
through:

- zn 0.12.0's own latex path (`latexPNG`, TeX Live 2026 basic plus the
README's `tlmgr` list, in Docker): the baseline, 120 of 124 render.
- `github.com/d2lang/mathjax-go` v0.1.0 (math only).
- node-tikzjax 1.0.5, the desktop's TikZ engine (e-TeX in WebAssembly),
configured as `apps/desktop/src/main/tikz.ts` calls it; math wrapped in a
TikZ node.

Results per case are in `results/`. Every case was also compared visually
against the TeX picture (pages built from the outputs; regenerate them by
rerunning the harness).

## Results (of what the TeX path renders)

| | Math (86) | TikZ (34) |
|---|---|---|
| mathjax-go | 68 | none |
| tikzjax | 75 | 33 |
| either | 83 | 33 |

- **mathjax-go** misses `\newcommand`/`\renewcommand`/`\def`, `eqnarray`,
`subequations`, `\intertext`, `\hline` in arrays, `\pmb`, `\pod`,
`\mathstrut`, `\leftroot`, `\overleftrightarrow`, mhchem `<=>>` and `&`
inside `\ce`. Silent differences: no automatic equation numbers, wrong
`alignat` spacing, literal `$` inside `\colorbox`. About 0.16 ms a block.
oksvg rendered none of its SVG.
- **tikzjax** misses mhchem (not in its bundle), crashes on `\pmb` and
`\boldsymbol` (missing font `cmmib5`; the throw escapes its promise and
kills the Node process, which matters for the desktop too), and breaks on
`\substack`. Silent differences: `patterns` render empty, `matrix of nodes`
loses node borders. About 0.36 s a block including Node start-up.
- Nothing embedded covers packages a user adds to `preamble.tex`.

## If this is reopened

The strongest route was one embedded engine (tikzjax's wasm under wazero)
with mhchem and the bold-math fonts added, a Go DVI-to-PNG renderer, and the
installed `pdftex` as automatic fallback for custom preambles. Open
questions: wazero speed, renderer effort, and dvi2html's unclear licence.

## Rerunning

- TeX: build `harness/Dockerfile.texlive` as `zn-texlive-readme`, put
`harness/pdftex-docker-wrapper.sh` on PATH as `pdftex`, and use
`harness/pdftex_coverage_test.go.txt`.
- mathjax-go: copy `harness/mathjax-run.go.txt` to `main.go` with
`mathjax-go.mod`/`.sum` as `go.mod`/`go.sum` in an empty folder;
`go run . corpus.json <outdir>`. (The `.txt` names keep these files out of
zn's own module.)
- tikzjax: `node harness/tikzjax-run.cjs corpus.json <outdir> [id]` (needs
the desktop repo's `node_modules`; run one id per process, a missing font
kills the process).
2 changes: 2 additions & 0 deletions docs/embedded-latex-coverage/harness/Dockerfile.texlive
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
FROM texlive/texlive:latest-basic
RUN tlmgr install standalone varwidth preview xcolor amsmath amsfonts mhchem pgf
Loading
Loading