Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Contributing And Reviewing

Start with the user documentation for behavior and examples, and architecture for runtime contracts. Repository instructions shared by coding agents are in AGENTS.md.

Requirements

  • Python 3.11+ and python3 -m pip install -r requirements-dev.txt.
  • Typst 0.15.0 or 0.15.1; verify with typst --version.
  • Poppler (pdftotext, pdftoppm) for painted text, bounds and visual inspection.
  • DejaVu Serif, DejaVu Sans and DejaVu Sans Mono for the manual (for example, Debian/Ubuntu package fonts-dejavu-core).
  • Node.js for the local highlight.js integration test (otherwise skipped).
  • Typst package dependencies from the local cache or registry. With an empty cache, run mkdir -p target && typst compile --root . scripts/fetch-packages.typ target/fetch.pdf once first: download progress on stderr would otherwise fail the warning-free checks. CI records exact compiler versions in its matrix.

CI runs the full matrix when a v* tag is pushed, or on demand from the Actions tab; ordinary pushes do not trigger it, so run the checks below locally.

Common Checks

python3 -m unittest discover -s tests -p 'test_*.py'
python3 tests/docs.py
python3 tests/run.py --filter 'tests/integration/*footnote*.typ'
python3 tests/page_numbering.py
python3 tests/run.py --manual

The full runner covers fixtures, expected diagnostics, examples and installed consumers. A filtered run keeps that source’s behavioral variants; an empty selection fails. Run the two compiler versions serially, selecting each with --typst /path/to/typst, and preserve target/tests/results.json between runs. The runner installs its own copied package under target/tests/package-data; a global install is unnecessary. Serialize all runner invocations in one checkout and save each compiler run’s log and results separately. Reject every Typst warning, especially non-convergence; inspect real PDF/SVG output for layout and navigation changes.

Within one invocation, sources are checked concurrently (--jobs N, default half the CPUs); the full suite takes a few minutes. While iterating, filter to the area you changed, for example --filter 'tests/integration/*margin*.typ', and run the full suite on both compilers before committing.

For ordinary CLI/editor development, use python3 scripts/install.py --namespace preview --link --reinstall. This overrides the published @preview/deixis:0.2.0 with your checkout. Omit --link for a copied install; omit --namespace to use local. For an isolated copy, pass --data-dir target/my-document/data and compile with --package-path target/my-document/data/typst/packages. Rerun after manifest version changes; restart the editor language server if it retains an old import error.

Independent Routing Audits

Run with each supported compiler on PATH:

python3 tests/scene_avoidance.py
python3 tests/scene_ports.py
python3 tests/scene_sliding.py
python3 tests/route_group.py
python3 tests/route_group_ports.py
python3 tests/route_group_sockets.py
python3 tests/relay_repair.py
python3 tests/route_group_invariants.py
python3 tests/route_group_margin.py
python3 tests/route_group_index.py

These compare search and planning against independent references. Preserve each compiler’s logs/results separately and include the compiler version in reports.

Documentation And Packaging

python3 scripts/render-manual-examples.py
python3 scripts/render-manual-examples.py --check
python3 scripts/render-guide-examples.py
python3 scripts/render-guide-examples.py --check
python3 scripts/render-guide-examples.py --verify --typst target/tools/typst-0.15.0/typst --work-dir target/guide-examples-0150
python3 scripts/render-manual.py
python3 scripts/render-manual.py --update-pdf

Preview refreshes are needed after runtime or worked-example changes. Guide previews use an immediate JSON directive before a plain Typst fence:

<!-- deixis-example: {"id":"short-note","height":"160pt"} -->
```typst
Text#deixis-footnote[An explanation.]
```

IDs are stable and unique within each guide. Optional width, height and margin are Typst page values; prelude and postlude are supporting Typst source strings, and setup: false disables the default setup show rule. The renderer imports the isolated installed package, uses DejaVu Serif at 10pt on a 360pt-wide page with 18pt margins, and rejects all compiler diagnostics. Choose a fixed height and adequate margins for overlays; inspect actual SVGs for clipping. The site pairs each fence with SVG pages on white paper and offers the complete source including setup. Mark configuration/signatures/partial excerpts with typst fragment; these stay code-only with a visible Fragment label. Every Typst guide fence must choose a directive or the fragment info string.

The renderer publishes docs/assets/guides/ only after every snippet succeeds. Its digest index covers complete generated source, runtime, renderer and assets; --check checks freshness without compiling. --verify compiles into target without replacing committed SVGs; use separate --work-dir paths for compiler logs and minimum-version results. The website build and tests/docs.py run the freshness check, including both CI workflows. Guide changes do not affect the PDF manual.

The manual builder validates the PDF before replacing the checked-in copy; inspect its rendered pages too. User guides and examples describe supported behavior. Update source docstrings, guides and minimal examples when a public contract changes. Use Camel Case With Spaces for example headings; keep useful source/output pairs.

Use develop/ for disposable probes, tests/ for maintained checks, docs/ for documentation, and target/ for generated output. Include a minimal reproducer, compiler version, expected/actual behavior and relevant output in bug reports. Review findings should name a concrete trigger, consequence, source location and reproduction; distinguish defects from documented native limitations.

Tagging, publication and release uploads are separate actions. Follow the release checklist when preparing a release.

Local Website And Agent Skill

mdbook --version  # Tested with mdBook 0.5.4
python3 scripts/build-docs.py
python3 -m http.server 8765 --bind 127.0.0.1 --directory target/site
python3 scripts/export-api.py --skill
python3 tests/skill.py

The website build runs a local link/search-coverage check and writes target/site/; it does not deploy. The Docs workflow publishes the same build to GitHub Pages (https://inspiros.github.io/typst-deixis/) when a v* tag is pushed, or on demand from the Actions tab; it sets the project URL prefix that the published 404 page needs. Open http://127.0.0.1:8765/ after starting the server and stop it when finished. Use the build script so generated navigation and API pages are present. book.toml configures the site; theme/search assets are bundled locally. Review desktop and phone layouts after presentation changes. The agent skill targets Deixis 0.2.0; its check compiles every Typst snippet against an isolated package copy and rejects warnings. Both commands accept --typst for the minimum-version check. Regenerate the API cheat sheet after public API changes.

README Artwork

python3 scripts/render-readme.py
python3 scripts/render-readme.py --update-assets
python3 scripts/render-readme.py --check
python3 tests/readme.py

The first command writes previews to target/readme/. Inspect the hero, equation, individual transparent fragments and draft/final PNGs there before updating assets/readme/. The illustrations are actual Deixis output; the hero/comparison sources in scripts/artwork/ use bundled SVGs for immediate IDE preview. The eight hero fragments are independently compiled from hero-fragments.typ with --input kind=text|equation|shared|diagram|editorial|footnote|outline|local. The generator uses standard-library Python, Typst and the DejaVu Sans/Libertinus Serif fonts. It accepts --typst and rejects compiler warnings or extra specimen pages. The complete batch must succeed before bundled artwork is replaced. Preview refreshes and manual/website regeneration remain separate commands. Logo variants live only in assets/logos/; artwork is excluded from the runtime package.

Local Performance Measurements

python3 scripts/benchmark.py --output target/benchmarks/before
# After changing the runtime:
python3 scripts/benchmark.py --output target/benchmarks/after \
  --baseline target/benchmarks/before/results.json --compare-rendering

The fixed fixture covers 100/200/400 footnotes, margin notes and named references. Each sample runs in a fresh process, serially with one compiler thread by default; stop other test sweeps while measuring. Output includes copied input sources, raw timings, compiler/runtime/workload identities and median speedup ratios. --compare-rendering checks every page’s pixels and internal PDF links using Poppler/pypdf. --trace adds separate unmeasured compiler traces. Compare results with the same compiler and workload; do not cache executable note bodies.