OpenDoc · pre-release · successor to Casual Docs

The document engine, not the dependency.

OpenDoc is a deterministic, embeddable Word-document engine written in Rust. It reads and writes .docx, holds the document in a normalized editable model, and lays it out and renders it to pixels — for native, WebAssembly, and headless hosts that need real DOCX fidelity without a browser, a server, or a UI framework. It is the ground-up successor to Casual Docs, which treats the DOM as its canvas; OpenDoc owns the layout itself.

Apache-2.0. Pre-release — OpenDoc will take semantic versioning when its public package line begins. Rust 1.96 pinned, 1.88 MSRV; every pull request runs build, test, lint, docs and WASM gates.

opendoc.casualoffice.org/editor.html

Type with formatting, apply styles, fonts, sizes and colours, build lists and tables, then save back to .docx. Nothing is uploaded — everything runs client-side. To start from your own file instead, open the blank editor.

Status
pre-release
Targets
Rust · WASM · headless
Rendering
own layout + raster
License
Apache-2.0
Why OpenDoc

Most ways to work with .docx
force a trade-off. This one doesn’t.

The usual options are a full office suite you cannot embed, a converter that silently drops what it does not understand, or a browser editor that treats the DOM as the source of truth. OpenDoc is built the other way around.

Loss-aware by design

Content the semantic model does not yet represent is preserved and reproduced verbatim, or reported — never silently discarded.

Deterministic

The same input, fonts, and engine version produce the same model, layout, and bytes, every time — which is what makes rendering regression-testable at all.

Embeddable and host-agnostic

No mandatory DOM, server, React, or collaboration provider. The core targets Rust hosts, wasm32-unknown-unknown, desktop, and headless services alike.

Safe with untrusted files

Packages are parsed under explicit entry, path, size, expansion, and resource limits — a hostile .docx is an input, not an exploit.

What it does

Import, edit, lay out, render, export.

DOCX import

Into a normalized, editable model: paragraphs and runs with the full property tail, styles (basedOn chains) and theme, numbering, sections and page geometry, tables (merged cells, nested tables, borders, shading, cell margins), images and drawings, hyperlinks, fields, text boxes, footnotes and endnotes, headers and footers, comments, tracked changes, bookmarks, and content controls.

DOCX export, two ways

Byte-identical reconstruction of an unedited package, or a semantic writer that re-emits an edited model as a valid .docx that opens cleanly in LibreOffice.

Editing primitives

Grapheme-aware inserts and deletes, paragraph split/join, atomic transactions with semantic inverses, position mapping, revision-checked undo/redo, directed caret and range selection, and bounded ordered events.

Layout and rendering

Text shaping and line breaking via parley, an effective-property style cascade, pagination with break control, a backend-neutral display list, and a CPU raster backend that renders real pages and tables to PNG via tiny-skia with glyph outlines from skrifa.

In-browser editor (WASM)

The engine compiled to wasm32-unknown-unknown drives a live editor: hit-testing, an engine-drawn caret and selection, incremental per-page repaint (sub-10 ms on a large document), run and paragraph formatting with type-in-format, lists, tables, pictures, drawings, comments and tracked changes — all through a closed operation set with group undo/redo.

Every surface takes every operation

The page body, headers, footers, footnote and endnote bodies, text boxes, and objects nested inside a shape group each accept typing, selection, formatting, clipboard, find and replace, comments, and tracked changes — held to that by an operation × surface matrix in CI, not by spot-checks.

Build it

It builds from source, and renders a page in one command.

Clone and test
git clone https://github.com/CasualOffice/opendoc.git
cd opendoc
cargo test --workspace --all-features --locked

The repository pins Rust 1.96.0 through rust-toolchain.toml and supports 1.88.0 as its MSRV, checked separately on every pull request.

Render a page to PNG
# import → paginate → compose → raster, in one command
cargo run -p casual-doc-render \
  --example render_docx_page -- page.png

On native, the render crate resolves installed OS faces by default — useful for CJK, symbol, and complex-script text the bundled Latin faces do not cover — so no feature flag is needed.

Honest status

Pre-release, developed in the open.

Working today

Import, export, the editing model, layout, raster rendering, and the WebAssembly editor above all run. The engine is the document core for Casual Docs and an SDK others can embed.

Not yet

There is no published package line yet, so there is no stable version to pin — semantic versioning starts when one does. Build from source in the meantime.

Relationship to Casual Docs

Casual Docs is the shipping ProseMirror web editor and is what docs.casualoffice.org runs today. OpenDoc is its successor and is not yet a drop-in replacement — it is where the document engine work now happens.

Open a document in it. The editor above loads a bundled .docx; the blank editor takes one of your own. Everything runs client-side, so nothing you open leaves the browser.