
GlyphWeaveForge
GlyphWeaveForge converts Markdown into PDF through a small Rust pipeline with explicit boundaries:
api -> pipeline -> core -> adapters
The crate ships a lightweight built-in renderer by default and can optionally use Typst without changing the public builder API.
What the crate provides today
- A fluent
Forgebuilder for Markdown-to-PDF conversion. - Three input modes: UTF-8 text, UTF-8 bytes, and filesystem paths (
fsfeature). - Three output modes: in-memory bytes, explicit file path, and output directory (
fsfeature). - Built-in page sizes (
A4,Letter,Legal, custom millimeter sizes). - Built-in layout modes (
Paged,SinglePage). - Built-in themes with optional JSON overrides.
- Resource resolution through filesystem lookup (
fs) or caller-provided resolvers. - Renderer extension points through public
RenderBackendandResourceResolvertraits. - Two backend selections behind a stable builder API:
Minimalby default andTypstwhen the feature is enabled.
Installation
[]
= "0.1.5"
Enable optional features when you need them:
[]
= { = "0.1.3", = ["renderer-typst"] }
Main builder flow
use Forge;
let pdf = new
.from_text
.to_memory
.convert
.expect;
let bytes = pdf.bytes.expect;
assert!;
Forge::new() starts with these defaults:
- source: not set
- output: not set
- backend:
RenderBackendSelection::Minimal - page size:
PageSize::A4 - layout mode:
LayoutMode::Paged - theme:
BuiltInTheme::Professional
Supported inputs and outputs
Always available:
from_textfrom_bytesto_memory- injected resource resolvers through
with_resource_resolverorwith_resource_adapter - explicit backend selection through
with_backend - custom renderer injection through
with_renderer - full option replacement through
with_options
Available with the default fs feature:
from_pathto_fileto_directorywith_output_file_namefor directory outputs- filesystem-based resource lookup for local assets relative to the markdown file
Output behavior
to_memory()returnsPdfOutput { bytes: Some(...), written_path: None }.to_file(...)writes the PDF and returnsPdfOutput { bytes: None, written_path: Some(...) }.to_directory(...)creates the directory if needed and derives the file name from the source name unlesswith_output_file_name(...)overrides it.
When deriving a directory output name, the crate appends .pdf if it is missing.
Page sizes, layout modes, and themes
Page sizes
PageSize::A4PageSize::LetterPageSize::LegalPageSize::Custom { width_mm, height_mm }
Custom page sizes must be strictly positive.
Layout modes
LayoutMode::Paged: paginates rendered lines across pages.LayoutMode::SinglePage: keeps the rendered content in a single page payload.
Built-in themes
BuiltInTheme::InvoiceBuiltInTheme::ScientificArticleBuiltInTheme::Professional(default)BuiltInTheme::EngineeringBuiltInTheme::Informational
with_theme(...) selects a built-in preset. with_theme_config(...) lets you combine an optional built-in theme with JSON overrides such as:
namebody_font_size_ptcode_font_size_ptheading_scalemargin_mm
The Typst backend applies the full theme profile, including fonts, colors, margins, body/code sizes, and heading scale. The default minimal backend is a fallback PDF writer; it applies layout-affecting values such as margins and font sizes, while color and font-family overrides are represented only in the resolved theme profile.
Current theme profiles do not yet expose explicit controls for line height, paragraph alignment/indentation, multi-column layout, or page background color. Built-in presets therefore approximate those style guides through currently supported properties (fonts, sizes, heading scale, margins, and palette).
Example:
use ;
use json;
let pdf = new
.from_text
.to_memory
.with_page_size
.with_layout_mode
.with_theme_config
.convert
.expect;
assert!;
Backend selection
The default build uses the minimal built-in renderer. To opt into the Typst backend, enable renderer-typst and select it explicitly:
#
#
Backends exposed by the public API:
RenderBackendSelection::Minimal: always available in the default feature set.RenderBackendSelection::Typst: available whenrenderer-typstis enabled.
The typst Cargo feature is a compatibility alias for renderer-typst.
If you need complete control, with_renderer(...) accepts any type implementing the public RenderBackend trait and overrides the built-in backend selection.
Feature matrix
fs(default): enables path-based source/output helpers and filesystem resource loading.renderer-minimal(default): keeps the built-in lightweight renderer enabled and addressable in tests/documentation.renderer-typst: enables the Typst-backed renderer.typst: compatibility alias forrenderer-typst.mermaid: enables a Rust-native Mermaid subset renderer for the Typst backend (no Node/npm/network required). Unsupported Mermaid syntax remains visible through explicit fallback notices.- Mermaid fenced-block rendering is available through this Rust-native subset renderer.
math: enables GFM math parsing ($...$,$$...$$) and TeX-subset conversion for real Typst math rendering. The minimal renderer remains a readable text fallback.
Current Markdown behavior
Supported today:
- headings
- paragraphs
- emphasis/strong text
- inline code
- links
- unordered and ordered lists
- block quotes
- thematic breaks
- fenced code blocks
- images, including injected resolvers and memory-backed assets
- basic HTML
<img>tags withsrc/alt - tables
Resource handling behavior:
- For path-based markdown sources with the
fsfeature, local assets are resolved relative to the markdown file directory. - For text/bytes sources, you can inject assets with
with_resource_resolver(...)orwith_resource_adapter(...). - Missing assets remain visible in the output as explicit fallback text.
Unsupported advanced Markdown stays visible instead of silently disappearing. Examples include:
- footnotes
- Mermaid diagrams (Rust-native rendering on Typst for supported subset types when
mermaid+renderer-typstare enabled; unsupported syntax remains explicit fallback) - unsupported TeX environments/commands are surfaced as visible conversion notices in Typst output
- unsupported raw HTML beyond basic
<img>extraction
These paths render deterministic fallback labels with the original content preserved in the output when possible.
Math support details
- Inline math uses
$...$and display math uses$$...$$in Markdown. - The Typst backend renders real math with Typst delimiters after converting a practical TeX subset.
- Supported subset includes
\frac,\sqrt, grouped superscripts/subscripts,\sum,\prod,\int,\lim, common Greek letters (\alpha,\beta,\gamma,\delta,\lambda,\pi,\sigma,\Omega,\Delta), symbols (\pm,\infty,\approx,\neq,\leq,\geq,\le,\ge,\to,\cdot,\times), spacing/wrappers (\,,\qquad,\left,\right), and common functions (\sin,\cos,\exp,\partial). - Unsupported environments (
\begin{...}/\end{...}) and unknown commands produce explicit, visible error notices in Typst output instead of silent data loss. - Fenced code blocks like ```math are still treated as code fences (honest fallback), not as math AST nodes.
Extending the crate
Custom resource resolver
use io;
use Forge;
let pdf = new
.from_text
.to_memory
.with_resource_resolver
.convert
.expect;
assert!;
Custom renderer
use ;
;
let pdf = new
.from_text
.to_memory
.with_renderer
.convert
.expect;
assert_eq!;
The public extension traits are:
RenderBackendResourceResolver
The rendering request/asset helper types exposed for adapters are:
RenderRequestResolvedAssetResourceStatus
Limitations
- This crate does not claim real Mermaid diagram rendering.
- This crate does not claim real TeX/LaTeX or advanced math typesetting.
- Footnotes are exposed through visible fallback text rather than full layout support.
- General raw HTML is not a full rendering target; basic
<img>extraction is supported, but broader HTML layout is not. - The minimal renderer writes a compact PDF text stream; it is designed for deterministic output and testability rather than rich page design.
renderer-typstis optional; docs.rs for the default documentation build does not require Typst support to use the crate.
Public error and result types
Result<T>is an alias forstd::result::Result<T, ForgeError>.ForgeError::MissingSourceandForgeError::MissingOutputprotect incomplete builder usage.ForgeError::InputReadandForgeError::InvalidUtf8cover source loading.ForgeError::Resourcecovers resolver failures.ForgeError::InvalidConfigurationcovers invalid runtime options such as non-positive custom page sizes.ForgeError::Render,ForgeError::TypstCompile,ForgeError::TypstExport, andForgeError::TypstAssetcover backend/rendering failures.ForgeError::OutputWrite,ForgeError::OutputDirectory, andForgeError::InvalidOutputFileNamecover output persistence.
Architecture note
Release work should preserve the internal boundary:
api -> pipeline -> core -> adapters