Expand description
Renders Excalidraw scenes to SVG, PNG and PDF, matching Excalidraw 0.18.1’s exporter as closely as possible.
It is pure Rust with every font bundled: rendering needs no browser, Node.js, network access or installed fonts. Export a whole scene or each frame on its own. Every render also returns a compatibility report that lists what the renderer substituted, omitted or approximated, so differences from Excalidraw are reported rather than silent.
This release reproduces Excalidraw 0.18.1. In 0.x, any release may change output and diagnostics; pin the renderer version and dependency lockfile for reproducible output. Linux x86-64 GNU is release-qualified; browser WASM is experimental.
Throughout this documentation, reference means Excalidraw’s own exporter
at the pinned release, v0.18.1: “reference frame-export semantics” and
“reference dark-mode colors” describe what Excalidraw itself produces. An
admitted scene is one SceneDocument::parse accepted.
§Quick start
Admit the scene once with SceneDocument::parse, describe one output
with a RenderRequest, and render it with a Renderer. A successful
render returns the complete Artifact together with a
CompatibilityReport listing every repair, substitution or omission the
renderer made to keep the artifact meaningful; an empty report means none
were needed.
use excalidraw_render::{
FrameRenderRequest, OutputFormat, RenderRequest, Renderer, SceneDocument, Sizing,
};
// The contents of an `.excalidraw` file.
let bytes = br##"{
"type": "excalidraw",
"version": 2,
"elements": [
{"id": "overview", "type": "frame", "name": "Overview",
"x": 0, "y": 0, "width": 200, "height": 140},
{"id": "box", "type": "rectangle", "frameId": "overview",
"x": 40, "y": 30, "width": 120, "height": 80}
],
"appState": {"viewBackgroundColor": "#ffffff"},
"files": {}
}"##;
let scene = SceneDocument::parse(bytes)?;
let renderer = Renderer::new();
// Export the whole scene as SVG with the reference export defaults.
let request = RenderRequest::builder(OutputFormat::Svg).build()?;
let outcome = renderer.render(&scene, &request)?;
for diagnostic in outcome.report().diagnostics() {
eprintln!(
"{} {} at {}: {}",
diagnostic.severity(),
diagnostic.code(),
diagnostic.json_pointer(),
diagnostic.message()
);
}
let svg = outcome.artifact().bytes();
assert!(svg.starts_with(b"<svg"));
// Export every frame as a PNG no larger than 1024 pixels on either side.
let request = FrameRenderRequest::builder(OutputFormat::Png)
.sizing(Sizing::MaxDimension(1024.0))
.build()?;
for frame in scene.frames() {
let outcome = renderer.render_frame(frame, &request)?;
let png = outcome.artifact().bytes();
println!("{}: {} bytes", frame.name().unwrap_or("unnamed"), png.len());
assert!(png.starts_with(b"\x89PNG"));
}Each failure type (SceneParseError, RequestError, RenderError,
FrameBatchError) carries a stable ErrorCode, and descriptor() gives
its serializable form; the first three also carry typed details.
Renderer::render_frames renders a frame batch that shares scene
preparation across frames.
§Serving untrusted input
The renderer is built to render scene documents from untrusted sources, but a service still has to decide how much CPU time and memory one request may take.
-
Share and move freely.
RendererandSceneDocumentare immutable,Clone,SendandSync; one renderer can serve every request concurrently, and an admitted scene can be rendered to several formats from different threads. -
Rendering is synchronous and CPU-bound. In an async server, run it on a blocking pool (for example
tokio::task::spawn_blocking) rather than on the executor’s worker threads. -
There is no deadline or cancellation. Every render terminates, because all work is bounded by
ResourceLimits, but a render cannot be interrupted once started. When you need a hard wall-clock deadline, render in a separate process you can kill. -
Bound raster sizes from the request. For PNG and PDF, prefer
Sizing::MaxDimensionover a caller-chosenSizing::Scaleso a large scene cannot request an enormous PNG or page; then lowermax_raster_dimensionandmax_raster_surface_pixelsto what you are willing to allocate. SVG ignoresMaxDimensionand keeps the scene’s logical size, whichmax_svg_dimensionbounds instead. -
max_working_bytesis not a memory cap. It budgets the renderer’s deterministic, logical working set so that the same input fails the same way on every machine; it does not measure or limit allocator usage. Actual peak memory is higher, dominated by raster surfaces: PNG rasterizes a 4× supersampled canvas, about 65 bytes per output pixel, so the defaultmax_raster_surface_pixels(33,554,432) admits renders that need over 2 GiB. A ceiling of 4,194,304 pixels (2048 × 2048) keeps one render near 300 MB. Size worker memory (or a container limit) for your raster ceilings and concurrency. -
Parsing has its own ceilings.
SceneDocument::parseaccepts up to 64 MiB of JSON whatevermax_scene_bytessays; that limit is checked when rendering. Bound request bodies before parsing for a lower ceiling. -
Limits apply per render.
Renderer::render_framesrenders every selected frame within its own limits, so bound the frame count of an untrusted batch. -
Build with optimizations. Unoptimized builds are roughly 50 times slower, which turns ordinary scenes into multi-second renders and makes resource limits much easier to exhaust in wall-clock terms. Most of the time goes to dependencies (rasterization, compression, font decoding), so in a debug build of your service optimize every dependency:
[profile.dev.package."*"] opt-level = 2
§Cargo features
All three features are on by default. The API is the same with any combination of them, so Cargo’s feature unification can never change what compiles; a feature only decides which requests a build can serve, and turning one off never changes the bytes of the output that remains.
pngrendersOutputFormat::Png. It brings theresvgrasterizer andtiny-skia.pdfrendersOutputFormat::Pdf. It brings the Krilla PDF writer, and the rasterizer for the isolated raster fallbacks of embedded SVG effects.cjkbundles Xiaolai, Excalifont’s Chinese, Japanese and Korean fallback font (about 12 MiB). Without it, a render whose text needs Xiaolai fails withErrorCode::RENDER_FONT_UNAVAILABLE(render.font-unavailable, aRenderErrorCategory::Capabilityfailure) rather than substituting another font. Every other font, including Noto Emoji, is always bundled.
SVG output is always available. Without png or pdf, building a
RenderRequest or FrameRenderRequest for that format fails with
ErrorCode::REQUEST_FORMAT_UNAVAILABLE (request.format-unavailable),
whose message names the feature to enable. An SVG-only build, for example
for WebAssembly, depends on the renderer like this:
[dependencies]
excalidraw-render = { version = "0.1", default-features = false, features = ["cjk"] }Structs§
- Artifact
- One complete renderer-owned static export.
- Asset
Chain Entry - One entry in a nested asset occurrence chain.
- Compatibility
Diagnostic - Stable serializable view of one compatibility diagnostic occurrence.
- Compatibility
Report - Complete ordered compatibility diagnostics for one render transaction.
- Diagnostic
Code - String-backed stable compatibility diagnostic code.
- Error
Code - String-backed stable error code.
- Error
Descriptor - Stable serializable view of a typed renderer failure.
- Finite
Value - Finite schema-1 number with canonical JSON serialization.
- Frame
Batch Error - Failure to construct a lazy multi-frame render operation.
- Frame
Options - Whole-scene frame rendering controls.
- Frame
Ref - Borrowed identity and display metadata for one live frame occurrence.
- Frame
Refs - Iterator over live ordinary and magic frame occurrences.
- Frame
Render Cursor - Lazy source-ordered rendering of selected frames from one scene document.
- Frame
Render Entry - One target result yielded by a lazy multi-frame render operation.
- Frame
Render Request - A validated one-format frame render request.
- Frame
Render Request Builder - Builder for a validated one-format frame render request.
- Logical
Bounds - Finite logical bounds of a PDF raster fallback closure.
- Metadata
Options - Optional artifact metadata controls.
- Nested
Path - Canonical identity path within one nested source.
- Nested
Path Segment - One segment of a canonical nested-source path.
- PdfOptions
- PDF-specific request controls.
- Render
Error - Fatal render failure with the complete report accumulated before failure.
- Render
Outcome - Successful result of one complete render transaction.
- Render
Request - A validated one-format render request.
- Render
Request Builder - Builder for a validated one-format render request.
- Renderer
- Immutable renderer for this release’s compatibility revision.
- Request
Error - Indicates that a render request could not be validated.
- Resource
Limits - Validated semantic resource ceilings for one render.
- Resource
Limits Builder - Builder for validated semantic resource ceilings.
- Scene
Document - An admitted Excalidraw scene document.
- Scene
Parse Error - Indicates that scene-document bytes could not be admitted.
- Supplemental
Asset - One owned caller-supplied asset.
- Supplemental
Assets - Owned caller-supplied assets keyed by scene file ID.
- Supplemental
Assets Builder - Builder for an owned deterministic supplemental-asset mapping.
Enums§
- Color
Mode - Color mode used to interpret scene colors.
- Diagnostic
Details - Typed details attached to an
ErrorDescriptoror aCompatibilityDiagnostic. - Diagnostic
Effect - Observable effect class of a compatibility diagnostic.
- Diagnostic
Severity - Severity of one compatibility diagnostic occurrence.
- Error
Family - Stable family of a typed renderer failure.
- Frame
Batch Error Kind - Stable category of a lazy frame-batch construction failure.
- Frame
Kind - Kind of live frame occurrence discovered in a scene document.
- Measurement
- Stable attempted or lower-bound measurement.
- Metadata
Component - Optional artifact metadata component.
- Metadata
Operation - Operation performed on an optional metadata component.
- Nested
Segment Kind - Kind of one canonical nested-source path segment.
- Output
Format - The single artifact format produced by a render request.
- PdfRaster
Fallback - Policy for PDF-only isolated raster fallback.
- Recovery
- Stable recovery applied after diagnosed compatibility loss.
- Render
Error Category - Stable category of a fatal render failure.
- Resource
Value - Nonnegative integer or finite number used by semantic resource details.
- Sizing
- Output sizing selected for one render.
- SvgFont
Subset Stage - Stable stage vocabulary for a direct-SVG font subset failure.
- Value
Kind - Unit used by a stable limit measurement.
Functions§
- license_
bundle - Returns the complete package-wide license and attribution bundle.
Type Aliases§
- Resource
Measurement - Stable measurement form for integer, dimension, or coordinate resources.