Own the document model
DOCX parses into a typed, editable model instead of being flattened into browser markup.
- Semantic import and export
- Byte-identical save of unedited packages
- Unsupported data retained or reported
Open-source DOCX infrastructure
OpenDoc is a deterministic, loss-aware document engine written in Rust. Import,
edit, lay out, render, and write .docx across browser, desktop, and
headless environments — with one authoritative model.
The document itself is the source of truth. The canvas is a rendering surface; UI, storage, authentication, and network policy stay yours.
DOCX parses into a typed, editable model instead of being flattened into browser markup.
One Rust pipeline shapes, paginates, hit-tests, and renders across every host.
Every edit routes through a closed command set with undo. Everything around it is yours.
Document semantics live inside OpenDoc. Product policy lives inside your host. That line is the whole design, so it is drawn rather than described.
What is supported, how it was measured, and where the gaps still are — including the ones we have not closed.
corpus documents matching LibreOffice's page count exactly; worst delta +2. A manual measurement, not yet a CI gate.
“Preserved or reported — never silently dropped.”
Content the engine does not understand is carried through untouched or named in a compatibility report. Of 27 graded families, 21 round-trip in full.
No account, no hosted backend. Every pull request runs the same gates you can run locally.
Putting the editor in your own page has its own guide: Embed the editor.
$ git clone https://github.com/CasualOffice/opendoc.git
$ cd opendoc
$ cargo test --workspace --all-features --locked
# run the browser editor locally
$ ./webapp/build.sh
$ ./webapp/serve.py
import init, { open } from "./pkg/casual_doc_wasm.js";
await init();
const doc = open(new Uint8Array(await file.arrayBuffer()));
// a page-local point (twips, page 1) → a model anchor
const at = doc.hitTest(1, 1440, 1440);
doc.insertText(at.node, at.offset, "Hello from OpenDoc");
const rgba = doc.renderPage(0, 96); // RGBA8888, page 0 at 96 dpi
const docx = doc.exportDocx(); // bytes, ready to save
Shipped, active, and planned are kept separate, so a pre-release reads as a status rather than a promise.
Semantic import and export, and byte-identical save of unedited packages.
Paragraphs, tables, sections and columns, floats with text wrap, and math.
Comments, tracked changes, and every editing surface held to the Word and Docs standard.
Operational transformation over the same transactions, with snapshot and replay versioning.
Not yet: hyphenation · vertical and rotated text · floating tables. Full roadmap
No account required for the demo. No opaque hosted backend.