Skip to content

Render via Typst literals#91

Merged
istathar merged 41 commits intomainfrom
render-via-literal
Mar 11, 2026
Merged

Render via Typst literals#91
istathar merged 41 commits intomainfrom
render-via-literal

Conversation

@istathar
Copy link
Copy Markdown
Member

@istathar istathar commented Mar 11, 2026

Redesign the rendering pipeline so that presentation logic lives in Typst template files rather than compiled Rust code, thus enabling user-defined templates written in Typst.

This continues and supersedes #88. Adapters are refactored to emit a Typst literal, and templates are reinterpreted to mean a Typst file which supplies a render() function which, when given an appropriate domain-specific literal, is renders out the appropriate layout.

Every domain has an Adapter which projects from the parser's internal AST to a set of types that are domain-specific. These are denormalized and suitable for being used by a template. These domain-specific objects are then serialized out as a Typst literal.

This literal can then be used by a Template. Each domain has a default built in, but the --template command-line option allows the user to specify their own Typst file to handle the rendering.

@istathar istathar self-assigned this Mar 11, 2026
@istathar istathar merged commit 9d051fd into main Mar 11, 2026
1 check passed
istathar added a commit that referenced this pull request Mar 14, 2026
Redesign the rendering pipeline so that Rust walks the domain model and
emits calls to thin, individually overridable Typst functions. This
replaces the previous code which produced a single large Typst literal
and then required the user's template code to process that data
structure into markup.

This involved making a change to where the tree-walk of that structure
happened. While we were able to do so in Typst (#91) the result was that
iterating on the default template was difficult and providing for user
overrides of style elements necessitated the user to clone the default
template containing machinery that really should have been internal.

Instead we further strengthen the idea of domain to include both the
domain model created by the Adapter and the Renderer able to walk such a
domain model on the Rust side. Rather than emitting a data dictionary
literal, or finished Typst markup, we instead emit a stream of function
calls: `#render-description("Hello")#render-structure(":")` and so on,
with the function names matching the entities the domain's object model.

The functions are initially defined in a built-in template that is
copied to _.domain.typ_ in the directory containing the document to be
rendered. If a custom user-defined template is provided via `--template`
then an `#include *` directive for it is added to the top of the
generated document, allowing that template to selectively override any
of the individual render functions without having to reimplement the
entire rendering pipeline.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

1 participant