Why Folio
Folio is a paginated document engine for the web. It lays out rich documents (headings, lists, tables, code, math, media, Arabic and mixed-direction text) into pages the way a word processor does, and it does so without the DOM: the same layout runs in the browser, in a Web Worker and in Node.
That one layout powers everything downstream:
FolioDocument ──► formatter (rules → hints) ──► layout (theme + measurer) ──► DocumentLayout
(@nextgensoftwares/folio-model) (@nextgensoftwares/folio-formatter) (@nextgensoftwares/folio-layout) │
┌────────────────┼────────────────┐
▼ ▼ ▼
@nextgensoftwares/folio-editor @nextgensoftwares/folio-export-pdf DOCX export
(paint pages) (draw the pages) (maps the model)What you see while editing is, by construction, what prints.
The problem
Browsers are built for scrolling, not pages. Paginated editors on the web usually take one of two routes, and both hurt:
- Let the browser lay out, then cut it into pages. Measure DOM nodes, move them between page containers, repeat after each edit. Pagination becomes a function of the browser's text engine, the zoom level, installed fonts and timing, so the PDF never quite matches the screen, and big documents crawl.
- Render to a canvas from a private layout engine. Accurate, but the big office suites that do this are AGPL, and the result fights accessibility, selection and IME.
Folio's answer
- A deterministic, DOM-free layout engine.
@nextgensoftwares/folio-layouttakes a document, a theme and an injectedTextMeasurer, and returns positioned fragments per page. NogetBoundingClientRect, nomeasureText. In production the measurer is HarfBuzz over the actual font files (@nextgensoftwares/folio-fonts), so line breaks are reproducible anywhere. - Word-like pagination as data. Every block measures into a Flow: fragments at relative positions plus the places a page may end, each with a penalty. Widows/orphans, keep-with-next, keep-lines-together, forced breaks and repeated table headers are all breaks. The paginator is one linear pass.
- ProseMirror's proven editing core, without its view.
@nextgensoftwares/folio-editoruses ProseMirror's headless packages (model, state, transform, commands, history, keymap, tables, collab) for the document, selection, undo and collaboration. There is nocontenteditable: Folio lays out, maps positions to fragments and the host draws pages, caret and selection. - Book-scale by design. An edit does work proportional to what it changed: identity-cached block measurement, page-object reuse, incremental pagination that stops when it converges with the old page breaks, a lazy per-page position index. See Performance.
- Hosts extend, never fork. Custom blocks, themes, formatter rule packs, painters and UI are registered by the host app or shipped as plugins.
What's in the box
| Package | What it does | Status |
|---|---|---|
@nextgensoftwares/folio-model | ProseMirror-shaped JSON model, schema, validate / normalize | working |
@nextgensoftwares/folio-layout | Line breaking (UAX #14), bidi (UAX #9), justification, pagination, headers/footers, incremental layout | working |
@nextgensoftwares/folio-fonts | HarfBuzz TextMeasurer: CSS face matching, per-grapheme fallback, variable weights | working |
@nextgensoftwares/folio-formatter | Rules that read the document and emit layout hints | 2 rules |
@nextgensoftwares/folio-editor | Headless paginated editor: input, commands, caret, hit-testing, selection, plugins, collab | working |
@nextgensoftwares/folio-sync | Chunked progressive loading, step-based saving, IndexedDB outbox, server-verified checksums | working |
@nextgensoftwares/folio-react | FolioView, toolbar, menus, rulers, page setup, theme editor | in progress |
@nextgensoftwares/folio-plugin-media | Images, video, audio, file attachments, uploads | working |
@nextgensoftwares/folio-plugin-toc | Outline, table of contents with live page numbers, navigator | in progress |
@nextgensoftwares/folio-plugin-collab | Realtime transport, presence, history | in progress |
@nextgensoftwares/folio-export-pdf | PDF drawn from the layout with embedded, subset fonts | in progress |
@nextgensoftwares/folio-export-docx | DOCX export | in progress |
Fidelity
Against headless Chrome 143 on every textblock of a real chapter corpus plus an Arabic/mixed/justified stress set, 205 of 206 blocks break lines identically and heights match to 0.01 px. The one miss is a line ending within 0.5 px of the margin, where Chrome's text stack rounds advances to 1/64 px. Once the editor and the PDF both draw Folio's own glyph positions this stops mattering.
The long-term oracle is Word: a corpus of .docx fixtures with Word-rendered PDFs, compared page by page. "1:1" is promised only for the declared subset of fonts, styles and block types.
Known gaps
Folio is pre-1.0. Today the layout does not yet do: floats with text wrap (floated media is laid out as an aligned block), automatic table column sizing (unknown columns share space equally), kashida justification, hyphenation, footnotes, or per-section page setup. Oversized table rows can straddle lines at the cut. The roadmap lists what comes next.
Prior art
Folio studied SuperDoc, OnlyOffice and LibreOffice for ideas, and the ECMA-376 (OOXML), ISO 32000 (PDF), UAX #14 and UAX #9 specifications. It never copies code from AGPL/GPL projects; see Contributing.