Typst. The format that compiles without a toolchain.
Here to keep :mod:math_spec.typesetting.format honest: a seam with one
implementation behind it is a shape, not an abstraction. Typst's syntax differs
from LaTeX's in every respect that matters — sum_(…), cal(T),
function-call grouping instead of brace groups, a term list instead of a
description environment — so if the walk needed changing to accommodate it,
the split was in the wrong place.
Practically: the compiler is one self-contained binary (a pip wheel, so the
suite compiles every example without apt), and multi-letter identifiers in math
are upright by default, which is why names go through italic("…").
See :class:math_spec.typesetting.format.Format.
The cyclic operators spell with .o, Typst's circled modifier;
minus.circle does not compile.
f(x) in Typst math is a call on f.
With an upright("bus") head that is exactly the notation wanted,
and it needs no thin space.
Source code in src/math_spec/typesetting/typst.py
| def apply(self, function: str, argument: str) -> str:
"""``f(x)`` in Typst math is a call on ``f``.
With an ``upright("bus")`` head that is exactly the notation wanted,
and it needs no thin space.
"""
return f'{function}({argument})'
|
Source code in src/math_spec/typesetting/typst.py
| def cardinality(self, inner: str) -> str:
return f'abs({inner})'
|
Join the blocks; standalone only decides whether page setup is emitted.
Typst has no preamble/body split — a bare fragment is already a document.
Source code in src/math_spec/typesetting/typst.py
| def document(self, blocks: list[str], *, standalone: bool) -> str:
"""Join the blocks; ``standalone`` only decides whether page setup is emitted.
Typst has no preamble/body split — a bare fragment is already a document.
"""
body = '\n\n'.join(blocks) + '\n'
return f'{_PREAMBLE}\n{body}' if standalone else body
|
A block equation, aligned on &.
Typst aligns on & inside a block equation exactly as amsmath
does, so the :class:Line split carries over unchanged — which is
the point.
Source code in src/math_spec/typesetting/typst.py
| def equations(self, lines: list[Line], *, numbered: bool) -> str:
"""A block equation, aligned on ``&``.
Typst aligns on ``&`` inside a block equation exactly as amsmath
does, so the :class:`Line` split carries over unchanged — which is
the point.
"""
rows = [
f'{self.prose(line.label) if line.label else ""} & {line.left} & {line.right} & {line.condition}'.rstrip(
' &'
)
for line in lines
]
body = ' \\\n '.join(rows)
numbering = '#set math.equation(numbering: "(1)")\n' if numbered else ''
return f'{numbering}$ {body} $'
|
Source code in src/math_spec/typesetting/typst.py
| def escape(self, prose: str) -> str:
return _escape(prose)
|
Source code in src/math_spec/typesetting/typst.py
| def fraction(self, numerator: str, denominator: str) -> str:
return f'frac({numerator}, {denominator})'
|
Source code in src/math_spec/typesetting/typst.py
| def glossary(self, title: str, entries: list[Entry]) -> str:
rows = '\n'.join(f'/ {self.math(e.symbol)}: {e.meaning(self.dash)}' for e in entries)
return f'== {title}\n{rows}'
|
Source code in src/math_spec/typesetting/typst.py
| def greek(self, name: str) -> str:
return name
|
Source code in src/math_spec/typesetting/typst.py
| def italic(self, name: str) -> str:
return f'italic({_quote(name)})'
|
Source code in src/math_spec/typesetting/typst.py
| def joined(self, parts: list[str], operator: str) -> str:
return f' {operator} '.join(parts) if operator else ', '.join(parts)
|
Source code in src/math_spec/typesetting/typst.py
| def math(self, expression: str) -> str:
return f'${expression}$'
|
Source code in src/math_spec/typesetting/typst.py
| def mono(self, text: str) -> str:
return _raw(text)
|
Source code in src/math_spec/typesetting/typst.py
| def note(self, text: str) -> str:
return text
|
Source code in src/math_spec/typesetting/typst.py
| def parenthesise(self, inner: str) -> str:
return f'({inner})'
|
Source code in src/math_spec/typesetting/typst.py
| def prose(self, text: str) -> str:
return f'upright({_quote(text)})'
|
Source code in src/math_spec/typesetting/typst.py
| def script(self, letter: str) -> str:
return f'cal({letter})'
|
Source code in src/math_spec/typesetting/typst.py
| def section(self, title: str, body: str) -> str:
return f'== {title}\n{body}'
|
Source code in src/math_spec/typesetting/typst.py
| def subscript(self, base: str, indices: list[str]) -> str:
return f'{base}_({",".join(indices)})' if indices else base
|
Source code in src/math_spec/typesetting/typst.py
| def summation(self, domain: str, body: str) -> str:
return f'sum_({domain}) {body}'
|
Source code in src/math_spec/typesetting/typst.py
| def superscript(self, base: str, tail: str) -> str:
return f'{base}^({tail})'
|
Source code in src/math_spec/typesetting/typst.py
| def upright(self, name: str) -> str:
return f'upright({_quote(name)})'
|