A paged-media layout engine for book-shaped documents, in Rust.
Documentation · Demos · API
fleuron takes markdown and CSS and gives back a typeset book. It shapes the text, breaks and hyphenates the lines, fragments the result into pages, and emits a display structure for preview and a PDF for export. The same source compiles to native and to WebAssembly.
A fleuron is the printer's flower ❦, the ornament set into a page to mark a pause.
fleuron repaginates a full-length manuscript while the writer waits, and gives them a preview that matches the export.
It owns the whole pipeline: harfrust shaping, Unicode line breaking and segmentation, Knuth-Plass justification, and CSS Fragmentation over a box tree it builds itself. Break decisions come out of the layout pass, so a 333-page novel reaches PDF bytes in 287 ms. The preview and the PDF are painted from the same display structure, so they cannot come out different. The engine does no I/O and links no platform library, so it builds for any target Rust does.
fleuron handles book-shaped documents: flowing prose with headings, block quotes, scene breaks, drop caps, images, lists, tables, code blocks, running heads, multi-column pages, and page furniture like recto and verso, page counters and named pages.
It is not a browser engine. There is no float layout, no grid or flexbox, no transforms. CSS the engine does not support is reported with the line and column it was written at, and the book lays out anyway.
markdown ─► content tree ──┐
├─► style tree ─► box tree ─► line layout ─► fragmentation ─► pages
CSS ───────────────────────┘ │
├─► display structure (preview)
└─► PDF (export)
The pipeline runs one way. Nothing downstream reaches back upstream.
| crate | |
|---|---|
fleuron |
The engine: style compilation, box construction, inline layout, fragmentation, page assembly. No I/O. |
fleuron-markdown |
Markdown in, sections out. The mapping is in docs/reference/markdown.mdx. |
fleuron-epub |
The content tree and the stylesheets in, a reflowable EPUB out. It lays nothing out, because the reading system makes the pages. See docs/library/epub.md. |
fleuron-cli |
The fleuron binary. Markdown in, PDF or EPUB out. |
fleuron-wasm |
WASM bindings, plus a worker, a display-structure reader and an SVG painter in TypeScript. Ships to npm as fleuron. |
fleuron-react wraps the preview as a component and contains no
engine logic.
Most callers write markdown. The content tree stays public for a host that already has structured content, such as a CMS or a docx converter.
- Styling enters as CSS. A built-in user-agent stylesheet supplies
the defaults and author CSS cascades over it. Everything downstream
reads the resolved style tree.
docs/css-subset.mdxlists what the engine supports. - The engine never touches the DOM. Bytes in, bytes out. SVG, canvas and PDF are interchangeable painters over the display structure.
- Layout never decodes images. A header probe gives intrinsic size, orientation and DPI. Painters decode the pixels themselves.
Two public-domain novels, laid out from markdown and checked against fixed budgets.
| pages | parse | style | line layout | fragment | end to end | layout peak | ||
|---|---|---|---|---|---|---|---|---|
| Pride and Prejudice | 333 | 1 ms | 1 ms | 128 ms | 5 ms | 150 ms | 287 ms | 12 MiB |
| The Count of Monte Cristo | 1254 | 5 ms | 6 ms | 505 ms | 20 ms | 563 ms | 1.10 s | 47 MiB |
Four times the book costs about four times the time and four times the memory.
A session keeps the same pipeline open and re-runs only the stages an edit invalidates. Restyling Pride and Prejudice with a sheet that moves the page box costs 6 ms, against the 128 ms of line breaking it skips.
Apple M-series, release build, best of three. The demos run the same two books in your browser and name the machine they ran on.
The budgets: a book-scale manuscript reaches PDF bytes in under a second natively, lays out in under half a second in a WebAssembly worker, stays under 32 MiB doing it, and re-renders a style change in under 20 ms from a session capped at 64 MiB. CI checks them natively and under wasm on every pull request.
cargo run --release -p fleuron-fixtures --bin perf-gate
cargo bench -p fleuron
Pre-alpha. fleuron is the pagination backend for Orca, the Obsidian novel-writing suite, extracted into its own project. The build order is in the issue tracker.
Dual-licensed under either of Apache-2.0 or MIT at your option.