
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.3"
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
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: currently does not add real Mermaid rendering; fencedmermaidblocks remain visible as explicit unsupported fallbacks.math: currently does not add real math layout; fencedmathblocks remain visible as explicit unsupported fallbacks.
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
- math fences
- unsupported raw HTML beyond basic
<img>extraction
These paths render deterministic fallback labels with the original content preserved in the output when possible.
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