docen
v0.5.3
Published
Universal document toolkit — one package for headless Markdown/HTML/DOCX conversion AND the full docen web-component editor. Re-exports @docen/docx (converters + engine) and @docen/editor (<docen-document>).
Maintainers
Readme
docen
Universal document toolkit — one package for headless Markdown/HTML/DOCX conversion AND the full
<docen-document>web-component editor (via thedocen/editorsubpath).
Features
- 🔄 Universal Format Support - Seamless conversion between Markdown, HTML, and DOCX
- 🎯 Unified API - Consistent, intuitive interface across all format conversions
- 📦 All-in-One Package - Single dependency for both headless conversion AND the full
<docen-document>editor (viadocen/editor) - 🔧 Built on TipTap - Powered by the robust TipTap/ProseMirror ecosystem
- 💪 TypeScript-First - Full type safety with comprehensive TypeScript support
- ⚡ Zero Configuration - Works out of the box with smart defaults
- 🌳 Extensible - Customize conversions with TipTap extensions and advanced options
- 🔄 Bidirectional - Convert in both directions (parse ↔ generate) for each format
Installation
# Install with npm
$ npm install docen
# Install with yarn
$ yarn add docen
# Install with pnpm
$ pnpm add docenQuick Start
HTML ↔ TipTap JSON
import { parseHTML, generateHTML } from "docen";
// Parse HTML to TipTap JSON
const doc = parseHTML("<h1>Hello World</h1><p>This is <strong>bold</strong> text.</p>");
// Generate HTML from TipTap JSON
const html = generateHTML(doc);Markdown ↔ TipTap JSON
import { parseMarkdown, generateMarkdown } from "docen";
// Parse Markdown to TipTap JSON
const doc = parseMarkdown("# Hello World\n\nThis is **bold** text.");
// Generate Markdown from TipTap JSON
const markdown = generateMarkdown(doc);DOCX ↔ TipTap JSON
import { parseDOCX, generateDOCX } from "docen";
// Parse DOCX to TipTap JSON
const doc = parseDOCX(buffer);
// Generate DOCX from TipTap JSON
const docxBuffer = await generateDOCX(doc); // defaults to a Node.js BufferCross-Format Conversion
Convert between any formats by using TipTap JSON as the intermediate format:
import { parseHTML, generateDOCX } from "docen";
// HTML → DOCX
const html = "<h1>Title</h1><p>Content...</p>";
const doc = parseHTML(html);
const docx = await generateDOCX(doc, { packer: { type: "blob" } });
// Markdown → HTML
import { parseMarkdown, generateHTML } from "docen";
const md = "# Title\n\nContent...";
const doc2 = parseMarkdown(md);
const htmlContent = generateHTML(doc2);Full Editor (via docen/editor)
The same docen package also re-exports the turnkey web-component editor. Import from the docen/editor subpath to register <docen-document> and apply a theme:
<docen-document id="doc" filename="Welcome.docx"></docen-document>
<script type="module">
import { registerComponents, applyTheme } from "docen/editor";
registerComponents();
applyTheme("light");
</script>The editor lives on a subpath so that pure-converter imports (
import { parseDOCX } from "docen") stay tree-shakable and never pull in the Fluent UI shell.
API Reference
HTML Functions
parseHTML(html, extensions?, options?)
Parses an HTML string into TipTap JSON content.
Parameters:
html: string- HTML string to parseextensions?: Extensions- Optional TipTap extensions (defaults to @docen/docx's docxExtensions)options?: ParseOptions- Optional ProseMirror parse options
Returns: JSONContent - TipTap document object
const doc = parseHTML("<p>Hello World</p>");generateHTML(doc, extensions?)
Generates an HTML string from TipTap JSON content.
Parameters:
doc: JSONContent- TipTap document objectextensions?: Extensions- Optional TipTap extensions
Returns: string - HTML string
const html = generateHTML({ type: 'doc', content: [...] });Markdown Functions
parseMarkdown(markdown)
Parses a Markdown string into TipTap JSON content.
Parameters:
markdown: string- Markdown string to parse
Returns: JSONContent - TipTap document object
const doc = parseMarkdown("# Hello\n\nWorld");generateMarkdown(doc)
Generates a Markdown string from TipTap JSON content.
Parameters:
doc: JSONContent- TipTap document object
Returns: string - Markdown string
const markdown = generateMarkdown({ type: 'doc', content: [...] });DOCX Functions
parseDOCX(input)
Parses a DOCX file into TipTap JSON content.
Parameters:
input: Buffer | ArrayBuffer | Uint8Array | string- DOCX file data or path
Returns: JSONContent - TipTap document object
import { readFileSync } from "node:fs";
const buffer = readFileSync("document.docx");
const doc = parseDOCX(buffer);generateDOCX(docJson, options?)
Generates a DOCX file from TipTap JSON asynchronously. Styling is derived from the TipTap attrs. By default runs prepareDocument first — fetching http image URLs and embedding them as data URLs (required: http images are otherwise dropped).
Parameters:
docJson: JSONContent- TipTap document objectoptions?: DocxGenerateOptions-{ prepare?, packer? }:prepare(defaulttrue):trueruns the default image pre-fetch;falseskips it; aPrepareStep[]runs custom steps.packer:PackerOptions;typecontrols the output format ("nodebuffer"default → Buffer,"blob","arraybuffer", …).
Returns: Promise<Buffer | Blob | ArrayBuffer | Uint8Array | string> - DOCX data in the requested format
// Default: prepare images, Node.js Buffer
const buffer = await generateDOCX(doc);
// Skip preparation, Browser Blob
const blob = await generateDOCX(doc, { prepare: false, packer: { type: "blob" } });generateDOCXSync(docJson, packerOptions?)
Synchronous variant — fastest throughput, blocks the event loop. Does not run prepareDocument (it is async); call await prepareDocument(doc) first when http images need embedding.
Returns: Buffer | Blob | ArrayBuffer | Uint8Array | string - DOCX data in the requested format
const buffer = generateDOCXSync(doc);generateDOCXStream(docJson, options?)
Streams the DOCX as a ReadableStream<Uint8Array> — for large documents or HTTP responses. Runs prepareDocument by default (async).
Returns: Promise<ReadableStream<Uint8Array>>
const stream = await generateDOCXStream(doc);
return new Response(stream);Advanced Usage
Custom Extensions
Use custom TipTap extensions for HTML/Markdown conversions:
import { CustomExtension } from "./custom-extension";
import { parseHTML, generateHTML } from "docen";
const doc = parseHTML(html, [CustomExtension]);
const htmlContent = generateHTML(doc, [CustomExtension]);DOCX Template Patching
Replace {{placeholders}} in a DOCX template with TipTap-JSON content:
import { patchDOCX, parseHTML, parseMarkdown } from "docen";
const result = await patchDOCX({
template: templateBuffer,
patches: {
title: { content: parseHTML("<h1>Report</h1>") },
body: { content: parseMarkdown("## Section\n\nHello **world**.") },
},
outputType: "nodebuffer",
});Each patch's content is compiled to DOCX (styling derived from attrs) and the first section's children replace the placeholder. keepOriginalStyles, recursive, and placeholderDelimiters mirror the underlying @office-open/docx patchDocument.
Format Conversion Matrix
| From \ To | HTML | Markdown | DOCX | | ------------ | -------- | -------- | -------- | | HTML | - | via JSON | via JSON | | Markdown | via JSON | - | via JSON | | DOCX | via JSON | via JSON | - |
All conversions go through TipTap JSON as the intermediate format, ensuring consistency and enabling cross-format transformations.
Supported Content Types
Text Formatting
- Bold, Italic, Underline, Strikethrough
- Superscript, Subscript
- Text highlights, colors, backgrounds
- Font families, sizes, line heights
Block Elements
- Headings (H1-H6)
- Paragraphs with alignment
- Blockquotes
- Horizontal rules
- Code blocks with syntax highlighting
Lists & Tables
- Bullet lists, ordered lists
- Task lists with checkboxes
- Tables with colspan/rowspan
Media & Links
- Images with embedded base64
- Hyperlinks
Use Cases
- Content Management Systems - Import/export documents in multiple formats
- Documentation Tools - Convert between Markdown and Word
- Note-taking Apps - Support various import/export formats
- Report Generation - Generate DOCX reports from HTML/Markdown templates
- Content Migration - Migrate content between different formats
- Collaborative Editing - Use TipTap editor with format support
Under the Hood
docen ships three entry points: the root re-exports the high-level converters; docen/docx exposes the full engine (createDocxEditor, docxExtensions, resolve/compile/prepare, styles); docen/editor exposes the <docen-document> web component. It builds on:
- @docen/docx - DOCX / HTML / Markdown converters built on the DocxManager architecture (full surface via
docen/docx) - @docen/editor - Fluent UI shell + docx engine →
<docen-document>(exposed via thedocen/editorsubpath) - @office-open/docx - Native OOXML parse/generate (
parseDocument,generateDocument,patchDocument) - @tiptap/html / @tiptap/markdown - HTML and Markdown serialization (via @docen/docx)
Comparison with Alternatives
| Feature | docen | markdown-docx | mammoth | turndown | | ----------- | ----- | ------------- | ------- | -------- | | MD → DOCX | ✅ | ✅ | ❌ | ❌ | | DOCX → MD | ✅ | ❌ | ❌ | ❌ | | HTML ↔ MD | ✅ | ❌ | ❌ | ✅ | | DOCX ↔ HTML | ✅ | ❌ | ✅ | ❌ | | TypeScript | ✅ | ✅ | ✅ | ✅ | | Unified API | ✅ | ❌ | ❌ | ❌ | | Extensible | ✅ | ❌ | ❌ | ✅ |
License
MIT © Demo Macro
