⚠️ Warning: This project is not yet stable and may undergo significant changes before reaching version 1.0.0. We strongly advise against using it in production environments.
Docen is a high-fidelity, high-performance Office document editor for the modern web. Canvas typesetting brings the typesetting, layout, and editing experience of Microsoft Office / WPS Office to the browser, and gigabyte-scale documents open fluently — no server required. Presentation slides and spreadsheet editing are on the roadmap.
Built on TipTap/ProseMirror and LeaferJS, with headless Markdown ⇄ DOCX conversion through a unified Tiptap JSON model. Fully typed.
Live Demo · Discussions · Report Issues
⭐ If Docen is useful to you, a star helps other developers find it.
- True-to-Word fidelity — a pagination engine that follows Word's stacking rules (document grid, table page breaks with repeated headers, text wrapping around floats) and a canvas painter that draws the result faithfully, page by page.
- Gigabyte-scale documents, smooth — incremental layout slices pages as you read, media loads lazily, and repaints stay incremental, so even 1 GB+ documents open and scroll without freezing.
- Modern web, zero server — standards-based web components with a typed Vue 3 adapter; everything runs client-side, in any modern browser.
- Headless conversion included — Markdown ⇄ DOCX through one unified Tiptap JSON model, usable with or without the editor.
| Package | Version | Description |
|---|---|---|
| docen | All-in-one — headless Markdown/DOCX conversion + the full <docen-document> editor |
|
| @docen/vue | Vue 3 adapter — <DocenDocument> component (v-model + v-slot editor) |
|
| @docen/editor | Assembly layer — Fluent UI host + docx engine into <docen-document> |
|
| @docen/docx | DOCX engine — Tiptap schema + converters + layout projection, powered by @office-open/docx | |
| @docen/layout | Pagination engine — measurement → paginated LayoutDoc, Word's stacking rules | |
| @docen/markdown | Markdown syntax layer — neutral IR + renderer, format mappers bind their own model | |
| @docen/pretext | Vendored fork of @chenglou/pretext — CJK measure correction + Word/CJK layout fixes | |
| @docen/core | Scene painter — LayoutDoc → LeaferJS tree for the canvas editors | |
| leafer-x-metafile | Zero-dependency WMF/EMF+ metafile replay → neutral drawing members | |
| @docen/deduplicate | Document comparison (SimHash + Winnowing) for the compare feature |
For seamless conversion between Markdown, plain text, and DOCX through a single unified API:
# Install with pnpm
$ pnpm add docen
import { parseMarkdown, generateDOCX, parseDOCX, generateMarkdown } from "docen";
// Markdown → DOCX
const doc = parseMarkdown("# Title\n\nHello World");
const docx = await generateDOCX(doc);
// DOCX → Markdown
const json = await parseDOCX(buffer);
const markdown = generateMarkdown(json);
Styled HTML from the clipboard is supported as paste input in the editor — the extensions' parseHTML rules turn it into document JSON. There is no HTML generation anywhere.
💡 The
docenpackage also bundles the full engine and editor —import { createDocxEditor } from "docen/docx"orimport { DocenDocument } from "docen/editor"— so one dependency covers headless conversion, the engine, and the web component.
The DOCX engine — Tiptap schema, converters, and the layout projection — with near-lossless round-trip conversion:
$ pnpm add @docen/docx
import { docxExtensions, parseDOCX, generateDOCX } from "@docen/docx";
import { Editor } from "@docen/docx/core";
// Viewless: the editor is the editing model — rendering belongs to the host.
const editor = new Editor({
element: null,
extensions: docxExtensions,
content: await parseDOCX(buffer),
});
const output = await generateDOCX(editor.getJSON());
A turnkey web-component editor (<docen-document>) bundling the Fluent UI host, the @docen/docx engine, and the LeaferJS canvas stage:
$ pnpm add @docen/editor
<docen-document id="doc" filename="Welcome.docx"></docen-document>
<script type="module">
import { registerComponents, applyTheme } from "@docen/editor";
registerComponents();
applyTheme("light");
</script>
A typed <DocenDocument> component — v-model for content, a v-slot="{ editor }" scope, and a template-ref expose — for Vue 3:
$ pnpm add @docen/vue
<script setup lang="ts">
import { ref } from "vue";
import type { JSONContent } from "@docen/docx";
import { DocenDocument } from "@docen/vue";
import { parseDOCX } from "@docen/docx";
// v-model carries Tiptap JSON; the template ref exposes the Tiptap editor
// plus a getJSON/setJSON pair.
const content = ref<JSONContent>({ type: "doc", content: [{ type: "paragraph" }] });
const editorRef = ref();
async function open(file: File) {
const json = await parseDOCX(await file.arrayBuffer());
editorRef.value?.setJSON(json); // preserves doc.attrs.styles
}
</script>
<template>
<DocenDocument ref="editorRef" v-model="content" filename="Welcome.docx" editable />
</template>
- Node.js 18.x or higher
- pnpm 9.x or higher (recommended package manager)
- Git for version control
-
Clone the repository:
git clone https://github.com/DemoMacro/docen.git cd docen -
Install dependencies:
pnpm install
-
Build all packages:
pnpm build
pnpm build # Build all packages
cd packages/<pkg> && pnpm build # Build one package
vp check # Lint & format
This project follows Semantic Versioning. While the major version is 0 (pre-1.0), breaking API changes are released as minor version bumps (0.x.0) rather than patch releases — the public API is expected to keep evolving until the 1.0.0 stabilization release. Pin exact versions in downstream projects if you require stability between minor updates.
We welcome contributions! See CONTRIBUTING.md for the full contribution workflow, coding standards, and PR checklist.
- 📫 Report Issues
- 💬 Discussions — questions, ideas, and show-and-tell
If Docen is useful to you, a ⭐ star helps other developers find it.
- 📚 docen Documentation
- 📚 @docen/vue Documentation
- 📚 @docen/editor Documentation
- 📚 @docen/docx Documentation
- 📚 @docen/layout Documentation
- 📚 @docen/core Documentation
- 📚 leafer-x-metafile Documentation
This project is licensed under the MIT License - see the LICENSE file for details.
Built with ❤️ by Demo Macro
