Skip to content

Feature Request MVP: Add Typst as a PDF Generator Option in Print Format#450

Open
agatho-daemon wants to merge 23 commits into
frappe:developfrom
agatho-daemon:develop
Open

Feature Request MVP: Add Typst as a PDF Generator Option in Print Format#450
agatho-daemon wants to merge 23 commits into
frappe:developfrom
agatho-daemon:develop

Conversation

@agatho-daemon
Copy link
Copy Markdown

Description

This MVP serves as a proof-of-concept implementation of Typst as a PDF generator within Print Designer. It is intended to demonstrate the feasibility and potential advantages of supporting declarative typesetting engines alongside existing HTML-based renderers. Feedback and discussion are welcome.

This PR introduces a Minimum Viable Product (MVP) for integrating Typst as a PDF rendering engine in Frappe's Print Designer. It serves as a proof of concept, demonstrating the feasibility and advantages of supporting declarative typesetting engines like Typst alongside existing HTML-based renderers. Feedback and discussion are welcome.

MVP Scope

  • Adds "typst" to the pdf_generator field options in Print Format
  • Supports WASM-based Typst rendering with optional fallback logic
  • Implements global page settings (e.g. paper size, orientation)
  • Adds initial support for staticText, dynamicText, and image block styles
  • Introduces core architectural classes: TypstDocumentBuilder, TypstEngine, and layout scaffolding

⚠️ Limitations

This MVP is tightly coupled to the current Print Designer JSON schema, which brings the following constraints:

  • Relies on precise and accurate hard-coded positioning (x/y/width/height) in provided JSON code
  • Header and footer conversion not implemented
  • Only supports staticText, image, and limited dynamic fields
  • No table rendering or layout grid logic
  • No direct support for Jinja or dynamic variables
  • Assumes Print Format JSON is well-structured
  • Due to deprecated parameter usage in the Typst WebAssembly initialization, the first print attempt may fail silently. Users currently need to click the print button twice until initialization is properly refactored.

Changes Included

  • Added add_pdf_generator_option() and set_pdf_generator_option() in install.py
  • Dynamically injects "typst" (and "chrome") into the pdf_generator options via make_property_setter
  • Ensures idempotent logic to avoid duplication
  • Establishes the groundwork for Typst-based print rendering in Frappe

Why Typst?

Frappe has historically relied on wkhtmltopdf, which is deprecated and being replaced by WeasyPrint. Meanwhile, Print Designer currently uses Chromium (chrome) to convert HTML to PDF—an approach that lacks the precision, consistency, and elegance of a typesetting system.

Typst offers a clean and modern alternative—a declarative, typesetting-first approach that prioritizes consistency and developer ergonomics.

🌟 Typst Benefits

  • Platform-independent output — High fedility identical rendering across all systems
  • Fast and lightweight — compiled to WebAssembly, runs directly in-browser or headless
  • Declarative syntax — programmatically generated layouts are clean and readable
  • Advanced typography — fine-grained control over alignment, spacing, and typesetting
  • Multi-format output — supports both PDF and SVG natively
  • Better maintainability — eliminates browser rendering inconsistencies
  • Possible theme-based PDF generation — enables reusable templates across formats
  • Integrates with Frappe workflows — complements current DocTypes and Print Formats
  • Open-source and community-driven — growing ecosystem of libraries, templates, and tooling
  • Foundation for long-term architecture — aligns with future-proof, plugin-based document pipelines (e.g. legal documents, reports, academic layouts)

For architectural context and diagrams, check: typst-arch.md

⚠️ Integration Notes

The current implementation of Typst rendering relies solely on the structure and semantics of the JSON output generated by Print Designer. While this provides a useful baseline for rendering, it introduces some rigidity and complexity when mapping document elements to Typst’s typesetting constructs.

This MVP was coded within the existing format to ensure compatibility without requiring upstream changes. However, improvements to the JSON schema or a shared interface specification between the builder and renderers (e.g., Typst, Chrome, WeasyPrint) could open the door for more flexible and expressive layouts in the future.

This is not a blocker for Typst integration, but rather a potential area for shared improvement.

Future

It is very imperative to note that the progress of implementation is tightly coupled to a structured JSON taking into account Typst markup structural precision for elements positioning on page.

How to Test

  1. Run:
    bench --site [your-site] install-app print_designer
  2. Open a Print Format (e.g., Sales Invoice PD Format v2)
  3. Set the PDF Generator field to typst
  4. Navigate to a Sales Invoice, open it, and click the Print icon
  5. You should receive a Typst-rendered PDF via the WASM engine in a new tab

📎 Sample Output

A complete sample of a rendered sales invoice using Typst is included in this repository to demonstrate layout accuracy, styled label/value blocks, and use of a letterhead background image.

Included files:

  • print_designer/pdf_generator/samples/sales_invoice_sample.typ
  • print_designer/pdf_generator/samples/sales_invoice_sample.png
  • print_designer/pdf_generator/samples/letterhead.svg

These serve as a practical reference for how Typst can express precise business document layouts typically rendered in HTML/CSS.

- Installed Vitest, configured tsconfig and vite.config.ts
- Verified module resolution using @typst aliases
- Fixed issues with sanitizeFontFamily test logic
- Removed old references to #box from page tests
- Confirmed successful UI testing with --ui flag
Hijack the default 'chrome' PDF generator in Print Designer to use Typst instead,
by checking for the presence of the Typst engine directory. This avoids the need
for modifying core Frappe validation or requiring a new pdf_generator literal.

- Added `generate_typst_pdf` with sample Typst output
- Modified `get_pdf` to route Chrome-based PDF generation to Typst if engine is present
- Cleaned up all prior patching, JS overrides, and unnecessary hooks
- Preserves fallback to Chromium-based rendering for other formats
This commit enhances the Print Designer by injecting "typst" (and "chrome")
into the `pdf_generator` field options of the "Print Format" DocType. The
addition is performed programmatically during installation using
`make_property_setter`.

Changes:
- Introduced `add_pdf_generator_option()` to add custom generators
- Created `set_pdf_generator_option(action, generators)` to handle addition/removal
- Ensured the new generator is only added if not already present
- Applied changes to the DocType definition without requiring manual intervention

This ensures Typst can be selected via the UI as an alternative to Chrome
for generating PDF outputs.

Note:
- Compatible with Frappe v15+
- Safe for repeated installs due to idempotent logic
Removed hijacking backend print_doc() to render using Typst CLI call.
Adds a sample Typst source file (invoice_sample.typ), its rendered output
(invoice_sample.png), and a sample letterhead background (letterhead.png)
to demonstrate the visual and layout capabilities of Typst PDF generation.

This example serves as a visual supplement to the Typst MVP PR and
provides a reference implementation of styled, positioned text
and image-based layouts.

Location: print_designer/pdf_generator/samples/
@maharshivpatel
Copy link
Copy Markdown
Collaborator

maharshivpatel commented Aug 7, 2025

@agatho-daemon would love to discuss and understand before reviewing +14,272 change. if you are open to google meet call please let me know. if you prefer we can also do discussion via comments.

Also, Thank you for your contribution.

@agatho-daemon
Copy link
Copy Markdown
Author

@maharshivpatel
Thanks for the review.
Regarding the code changes I have intentionally confined all within print_designer/public/js/typst. This is due to the fact that backend setup for typst would require changes upstream in frappe code so I avoided this and used only frontend in the MVP.

The other changes are samples, and the arch readme file print_designer/pdf_generator/typst-arch.md.

As I have titled the request, this is only a minimal MVP and typst-arch.md would display the benefit of moving the PDF generation and printing to Typst in as far as:

  1. performance
  2. reproducibility
  3. speed
  4. memory requirements
  5. there is a node based compiler and previewer.

Why I choose Typst:

  1. simplicity of Typst markup (it gets even more simple if vanilla frappe/erpnext formats are used)
  2. Possibility of future expansion to include all types of document printing and templating with fancy designers.

Kindly note that this PR is not for submission. It is an MVP attempt to present the benefits of using typst as PDF generating engine. To generate the full document from the JSON code, it would require much more understanding of the JSON structure.

So, please don't be tempted to accept the PR.

We can discuss using both google meet and here depending on my proximity to a google meet enabled device.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants