@docen/docx 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +156 -0
- package/dist/converters/docx.d.mts +110 -0
- package/dist/converters/docx.mjs +624 -0
- package/dist/converters/html.d.mts +14 -0
- package/dist/converters/html.mjs +18 -0
- package/dist/converters/markdown.d.mts +13 -0
- package/dist/converters/markdown.mjs +18 -0
- package/dist/converters/patch.d.mts +53 -0
- package/dist/converters/patch.mjs +37 -0
- package/dist/converters/prepare.d.mts +51 -0
- package/dist/converters/prepare.mjs +76 -0
- package/dist/core-CFIQVRfx.mjs +88 -0
- package/dist/core-omBKMRtl.d.mts +34 -0
- package/dist/core.d.mts +2 -0
- package/dist/core.mjs +2 -0
- package/dist/editor.d.mts +21 -0
- package/dist/editor.mjs +20 -0
- package/dist/extensions/extensions.d.mts +12 -0
- package/dist/extensions/extensions.mjs +12 -0
- package/dist/extensions/heading.d.mts +2 -0
- package/dist/extensions/heading.mjs +145 -0
- package/dist/extensions/image.d.mts +2 -0
- package/dist/extensions/image.mjs +201 -0
- package/dist/extensions/index.d.mts +2 -0
- package/dist/extensions/index.mjs +2 -0
- package/dist/extensions/paragraph.d.mts +2 -0
- package/dist/extensions/paragraph.mjs +116 -0
- package/dist/extensions/strike.d.mts +2 -0
- package/dist/extensions/strike.mjs +50 -0
- package/dist/extensions/table-cell.d.mts +2 -0
- package/dist/extensions/table-cell.mjs +112 -0
- package/dist/extensions/table-header.d.mts +2 -0
- package/dist/extensions/table-header.mjs +112 -0
- package/dist/extensions/table-row.d.mts +2 -0
- package/dist/extensions/table-row.mjs +84 -0
- package/dist/extensions/table.d.mts +2 -0
- package/dist/extensions/table.mjs +134 -0
- package/dist/extensions/text-style.d.mts +2 -0
- package/dist/extensions/text-style.mjs +134 -0
- package/dist/extensions/tiptap.d.mts +2 -0
- package/dist/extensions/tiptap.mjs +33 -0
- package/dist/extensions/types.d.mts +30 -0
- package/dist/extensions/utils.d.mts +49 -0
- package/dist/extensions/utils.mjs +289 -0
- package/dist/heading-BvqBD2zX.d.mts +8 -0
- package/dist/image-Ge1y6uam.d.mts +47 -0
- package/dist/index.d.mts +213 -0
- package/dist/index.mjs +8 -0
- package/dist/paragraph-fhEXtAN2.d.mts +16 -0
- package/dist/strike-BgWGvjKr.d.mts +33 -0
- package/dist/table-BFkfeRp9.d.mts +9 -0
- package/dist/table-cell-D_FV4D2h.d.mts +8 -0
- package/dist/table-header-KGQ2aEkP.d.mts +8 -0
- package/dist/table-row-kgzYkZlW.d.mts +9 -0
- package/dist/text-style-BHdtXkMb.d.mts +8 -0
- package/dist/tiptap-TErPjuNJ.d.mts +33 -0
- package/package.json +106 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Demo Macro
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
# @docen/docx
|
|
2
|
+
|
|
3
|
+

|
|
4
|
+

|
|
5
|
+

|
|
6
|
+
|
|
7
|
+
> DOCX editor and converter powered by @office-open/docx with Tiptap editing layer, supporting bidirectional conversion between DOCX, HTML, and Markdown.
|
|
8
|
+
|
|
9
|
+
## Features
|
|
10
|
+
|
|
11
|
+
- 📝 **Tiptap Editor** — Full-featured WYSIWYG editor with DOCX-aware extensions
|
|
12
|
+
- 🔄 **DOCX Round-trip** — Near-lossless DOCX ↔ Editor conversion via @office-open/docx
|
|
13
|
+
- 🌐 **HTML Conversion** — Bidirectional Tiptap JSON ↔ HTML (editor path + standalone)
|
|
14
|
+
- 📄 **Markdown Support** — Tiptap JSON ↔ Markdown conversion
|
|
15
|
+
- 🎨 **DOCX Properties** — Custom Tiptap extensions carry shading, borders, indent, spacing, floating, crop
|
|
16
|
+
- 🔗 **Template Patching** — Replace `{{placeholders}}` in DOCX templates with Tiptap-JSON content
|
|
17
|
+
|
|
18
|
+
## Installation
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
# Install with pnpm
|
|
22
|
+
$ pnpm add @docen/docx
|
|
23
|
+
|
|
24
|
+
# Install with npm
|
|
25
|
+
$ npm install @docen/docx
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## Quick Start
|
|
29
|
+
|
|
30
|
+
```typescript
|
|
31
|
+
import { createDocxEditor, docxExtensions, parseDOCX, generateDOCX } from "@docen/docx";
|
|
32
|
+
|
|
33
|
+
// Create editor
|
|
34
|
+
const editor = createDocxEditor({
|
|
35
|
+
element: document.querySelector("#editor"),
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
// Load a DOCX file
|
|
39
|
+
editor.commands.setContent(parseDOCX(buffer));
|
|
40
|
+
|
|
41
|
+
// Save back to DOCX
|
|
42
|
+
const output = await generateDOCX(editor.getJSON());
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## API
|
|
46
|
+
|
|
47
|
+
### Standalone Functions (Core)
|
|
48
|
+
|
|
49
|
+
These work without an editor instance — for headless/server/batch use.
|
|
50
|
+
|
|
51
|
+
```typescript
|
|
52
|
+
import {
|
|
53
|
+
parseDOCX,
|
|
54
|
+
generateDOCX,
|
|
55
|
+
generateDOCXSync,
|
|
56
|
+
generateDOCXStream,
|
|
57
|
+
parseHTML,
|
|
58
|
+
generateHTML,
|
|
59
|
+
parseMarkdown,
|
|
60
|
+
generateMarkdown,
|
|
61
|
+
} from "@docen/docx";
|
|
62
|
+
|
|
63
|
+
// DOCX pipeline: DOCX binary ↔ Tiptap JSON
|
|
64
|
+
const json = parseDOCX(buffer); // → JSONContent
|
|
65
|
+
const buffer = await generateDOCX(json); // → Buffer (pre-fetches http images by default)
|
|
66
|
+
const blob = await generateDOCX(json, { packer: { type: "blob" } }); // → Blob
|
|
67
|
+
const sync = generateDOCXSync(json); // → Buffer (skips prepare)
|
|
68
|
+
const stream = await generateDOCXStream(json); // → ReadableStream<Uint8Array>
|
|
69
|
+
|
|
70
|
+
// HTML pipeline: HTML string ↔ Tiptap JSON
|
|
71
|
+
const json = parseHTML("<p>Hello</p>"); // → JSONContent
|
|
72
|
+
const html = generateHTML(json); // → string
|
|
73
|
+
|
|
74
|
+
// Markdown pipeline: Markdown string ↔ Tiptap JSON
|
|
75
|
+
const json = parseMarkdown("# Hello"); // → JSONContent
|
|
76
|
+
const md = generateMarkdown(json); // → string
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
### Editor
|
|
80
|
+
|
|
81
|
+
```typescript
|
|
82
|
+
import { createDocxEditor, docxExtensions } from "@docen/docx";
|
|
83
|
+
|
|
84
|
+
const editor = createDocxEditor({
|
|
85
|
+
element: document.querySelector("#editor"),
|
|
86
|
+
extensions: docxExtensions,
|
|
87
|
+
spellcheck: true,
|
|
88
|
+
editable: true,
|
|
89
|
+
});
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
### Extension Commands (Thin Wrappers)
|
|
93
|
+
|
|
94
|
+
Convenience commands that call standalone functions internally.
|
|
95
|
+
|
|
96
|
+
```typescript
|
|
97
|
+
// Load DOCX into editor (calls parseDOCX → setContent)
|
|
98
|
+
editor.commands.importDocx(buffer);
|
|
99
|
+
|
|
100
|
+
// Export editor content as DOCX (calls getJSON → generateDOCX)
|
|
101
|
+
const buffer = await editor.commands.exportDocx();
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
### Template Patching
|
|
105
|
+
|
|
106
|
+
Replace `{{placeholders}}` in a DOCX template with Tiptap-JSON content. Each
|
|
107
|
+
patch's `content` is prepared (default: fetch http images) then compiled to DOCX.
|
|
108
|
+
|
|
109
|
+
```typescript
|
|
110
|
+
import { patchDOCX, parseHTML } from "@docen/docx";
|
|
111
|
+
|
|
112
|
+
const result = await patchDOCX({
|
|
113
|
+
template: templateBuffer,
|
|
114
|
+
patches: {
|
|
115
|
+
title: { content: parseHTML("<h1>Report</h1>") },
|
|
116
|
+
},
|
|
117
|
+
outputType: "nodebuffer",
|
|
118
|
+
});
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
### Advanced: Model Bridge
|
|
122
|
+
|
|
123
|
+
`generateDOCX` runs `prepareDocument → compileDocument → generateDocument`
|
|
124
|
+
internally. You rarely need these directly — reach for them only when working
|
|
125
|
+
with the intermediate `DocumentOptions` (the OOXML persistence model):
|
|
126
|
+
|
|
127
|
+
```typescript
|
|
128
|
+
import { resolveDocument, compileDocument, prepareDocument } from "@docen/docx";
|
|
129
|
+
|
|
130
|
+
const json = resolveDocument(docOpts); // DocumentOptions → JSONContent
|
|
131
|
+
const docOpts = compileDocument(json); // JSONContent → DocumentOptions
|
|
132
|
+
await prepareDocument(json); // in place: http image URLs → data URLs
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
## Architecture
|
|
136
|
+
|
|
137
|
+
```
|
|
138
|
+
Standalone Functions (core)
|
|
139
|
+
parseDOCX / generateDOCX / generateDOCXSync / generateDOCXStream / patchDOCX
|
|
140
|
+
parseHTML / generateHTML / parseMarkdown / generateMarkdown
|
|
141
|
+
resolveDocument / compileDocument / prepareDocument (model bridge, advanced)
|
|
142
|
+
↕ used by
|
|
143
|
+
Tiptap Extension Commands (thin wrappers)
|
|
144
|
+
editor.commands.importDocx() / exportDocx()
|
|
145
|
+
↕ used by
|
|
146
|
+
@docen/ui (Fluent UI Web Components)
|
|
147
|
+
<docx-editor> toolbar / ribbon / menus
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
- **Runtime model**: Tiptap JSON with DOCX-rich attributes via custom extensions
|
|
151
|
+
- **Persistence model**: DocumentOptions (complete OOXML expressiveness)
|
|
152
|
+
- **Standalone functions are core** — extension commands are thin wrappers
|
|
153
|
+
|
|
154
|
+
## License
|
|
155
|
+
|
|
156
|
+
- [MIT](LICENSE) © [Demo Macro](https://www.demomacro.com/)
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import { a as JSONContent } from "../core-omBKMRtl.mjs";
|
|
2
|
+
import { PrepareStep } from "./prepare.mjs";
|
|
3
|
+
import { DocumentOptions, OutputByType, OutputType, PackerOptions, parseDocument } from "@office-open/docx";
|
|
4
|
+
|
|
5
|
+
//#region src/converters/docx.d.ts
|
|
6
|
+
/**
|
|
7
|
+
* Manages DOCX serialization (Tiptap JSON ↔ DocumentOptions).
|
|
8
|
+
*
|
|
9
|
+
* Each extension provides renderDocx/parseDocx for its own attrs mapping.
|
|
10
|
+
* DocxManager handles tree walking, child assembly, and dispatching.
|
|
11
|
+
*/
|
|
12
|
+
declare class DocxManager {
|
|
13
|
+
compile(json: JSONContent): DocumentOptions;
|
|
14
|
+
resolve(docOpts: DocumentOptions): JSONContent;
|
|
15
|
+
private compileSectionChild;
|
|
16
|
+
private compileParagraphNode;
|
|
17
|
+
private compileHeadingNode;
|
|
18
|
+
private compileCodeBlock;
|
|
19
|
+
/** Simple text optimization: merge plain runs into text field */
|
|
20
|
+
private simplifyParagraph;
|
|
21
|
+
private compileTableNode;
|
|
22
|
+
/** Count grid columns from the first table row (summing colspan). */
|
|
23
|
+
private getTableColumnCount;
|
|
24
|
+
/**
|
|
25
|
+
* Compute tblGrid column widths (twips) from first-row cell colwidth attrs.
|
|
26
|
+
* Returns columnWidths array and the appropriate tableWidth.
|
|
27
|
+
*/
|
|
28
|
+
private computeColumnWidths;
|
|
29
|
+
private compileTableCellNode;
|
|
30
|
+
private compileListFromNode;
|
|
31
|
+
private compileInlineContent;
|
|
32
|
+
private compileTextNode;
|
|
33
|
+
private resolveSectionChild;
|
|
34
|
+
private resolveParagraph;
|
|
35
|
+
private resolveListItem;
|
|
36
|
+
private resolveTable;
|
|
37
|
+
/**
|
|
38
|
+
* Resolve a paragraph's inline content. @office-open collapses a plain-text
|
|
39
|
+
* paragraph (a single run with no properties) to a bare string or a `{ text }`
|
|
40
|
+
* object with no `children` — recover that text here so it round-trips back to
|
|
41
|
+
* a text node instead of being dropped.
|
|
42
|
+
*/
|
|
43
|
+
private resolveInlineContent;
|
|
44
|
+
private resolveParagraphChildren;
|
|
45
|
+
private resolveParagraphChild;
|
|
46
|
+
private resolveRun;
|
|
47
|
+
private resolveMarks;
|
|
48
|
+
private resolveImage;
|
|
49
|
+
private resolveHyperlink;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Parse a DOCX file into Tiptap JSON (runtime model).
|
|
53
|
+
*
|
|
54
|
+
* Combines @office-open/docx's `parseDocument` (DOCX binary → DocumentOptions)
|
|
55
|
+
* with `DocxManager.resolve` (DocumentOptions → Tiptap JSON).
|
|
56
|
+
*/
|
|
57
|
+
declare function parseDOCX(data: Parameters<typeof parseDocument>[0]): JSONContent;
|
|
58
|
+
/**
|
|
59
|
+
* Options for {@link generateDOCX} / {@link generateDOCXStream}.
|
|
60
|
+
*/
|
|
61
|
+
interface DocxGenerateOptions<T extends OutputType = "nodebuffer"> {
|
|
62
|
+
/**
|
|
63
|
+
* Pre-compilation steps run on the JSON in place (default: `prepareImages()`).
|
|
64
|
+
* - `true` / `undefined`: default image pre-fetch (http(s) → embedded data URL)
|
|
65
|
+
* - `false`: skip preparation
|
|
66
|
+
* - `PrepareStep[]`: custom steps
|
|
67
|
+
*
|
|
68
|
+
* Required for http image URLs — image `renderDocx` drops images without
|
|
69
|
+
* embedded data (see extensions/image.ts). Mutates the JSON, like `prepareDocument`.
|
|
70
|
+
*/
|
|
71
|
+
prepare?: boolean | PrepareStep[];
|
|
72
|
+
/** Packer options; `type` controls the output format (default `"nodebuffer"` → Buffer). */
|
|
73
|
+
packer?: PackerOptions<T>;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Generate a DOCX file from Tiptap JSON (runtime model), asynchronously.
|
|
77
|
+
*
|
|
78
|
+
* Pipeline: `prepareDocument` (default: fetch http images, in place) →
|
|
79
|
+
* `DocxManager.compile` → @office-open/docx's `generateDocument`. `packer.type`
|
|
80
|
+
* controls the output format (default: `"nodebuffer"` → Buffer). Non-blocking
|
|
81
|
+
* (fflate Web Workers). With the default `prepare`, the input `json` is mutated
|
|
82
|
+
* in place (http image URLs become embedded data URLs).
|
|
83
|
+
*/
|
|
84
|
+
declare function generateDOCX<T extends OutputType = "nodebuffer">(json: JSONContent, options?: DocxGenerateOptions<T>): Promise<OutputByType[T]>;
|
|
85
|
+
/**
|
|
86
|
+
* Generate a DOCX file synchronously — fastest throughput, blocks the event loop.
|
|
87
|
+
*
|
|
88
|
+
* Pipeline: `DocxManager.compile` → `generateDocumentSync`. Does **not** run
|
|
89
|
+
* `prepareDocument` (it is async); call `await prepareDocument(json)` first
|
|
90
|
+
* when http images need embedding.
|
|
91
|
+
*/
|
|
92
|
+
declare function generateDOCXSync<T extends OutputType = "nodebuffer">(json: JSONContent, packerOptions?: PackerOptions<T>): OutputByType[T];
|
|
93
|
+
/**
|
|
94
|
+
* Generate a DOCX file as a `ReadableStream<Uint8Array>` — for large documents
|
|
95
|
+
* or streaming HTTP responses.
|
|
96
|
+
*
|
|
97
|
+
* Pipeline: `prepareDocument` (default: fetch http images, in place) →
|
|
98
|
+
* `DocxManager.compile` → `generateDocumentStream`. Async due to preparation.
|
|
99
|
+
*/
|
|
100
|
+
declare function generateDOCXStream(json: JSONContent, options?: DocxGenerateOptions): Promise<ReadableStream<Uint8Array>>;
|
|
101
|
+
/**
|
|
102
|
+
* Convert DocumentOptions (persistence model) to Tiptap JSON (runtime model).
|
|
103
|
+
*/
|
|
104
|
+
declare function resolveDocument(docOpts: DocumentOptions): JSONContent;
|
|
105
|
+
/**
|
|
106
|
+
* Convert Tiptap JSON (runtime model) to DocumentOptions (persistence model).
|
|
107
|
+
*/
|
|
108
|
+
declare function compileDocument(json: JSONContent): DocumentOptions;
|
|
109
|
+
//#endregion
|
|
110
|
+
export { type DocumentOptions, DocxGenerateOptions, DocxManager, compileDocument, generateDOCX, generateDOCXStream, generateDOCXSync, parseDOCX, resolveDocument };
|