@docen/export-docx 0.0.11 → 0.0.13
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/README.md +271 -271
- package/dist/index.d.mts +261 -30
- package/dist/index.mjs +101 -64
- package/package.json +4 -4
package/README.md
CHANGED
|
@@ -1,271 +1,271 @@
|
|
|
1
|
-
# @docen/export-docx
|
|
2
|
-
|
|
3
|
-

|
|
4
|
-

|
|
5
|
-

|
|
6
|
-
|
|
7
|
-
> Export TipTap/ProseMirror editor content to Microsoft Word DOCX format.
|
|
8
|
-
|
|
9
|
-
## Features
|
|
10
|
-
|
|
11
|
-
- 📝 **Rich Text Support** - Full support for headings, paragraphs, and blockquotes with proper formatting
|
|
12
|
-
- 🖼️ **Image Handling** - Automatic image sizing, positioning, and metadata extraction
|
|
13
|
-
- 📊 **Table Support** - Complete table structure with headers, cells, colspan, and rowspan
|
|
14
|
-
- ✅ **Lists & Tasks** - Bullet lists, numbered lists with custom start numbers, and task lists with checkboxes
|
|
15
|
-
- 🎨 **Text Formatting** - Bold, italic, underline, strikethrough, subscript, and superscript
|
|
16
|
-
- 🎯 **Text Styles** - Comprehensive style support including colors, backgrounds, fonts, sizes, and line heights
|
|
17
|
-
- 🔗 **Links** - Hyperlink support with href preservation
|
|
18
|
-
- 💻 **Code Blocks** - Syntax highlighted code blocks with language attribute support
|
|
19
|
-
- 📁 **Collapsible Content** - Details/summary sections for expandable content
|
|
20
|
-
- 😀 **Emoji Support** - Native emoji rendering in documents
|
|
21
|
-
- 🧮 **Mathematical Content** - LaTeX-style formula support
|
|
22
|
-
- ⚙️ **Configurable Options** - Customizable export options for documents, tables, styles, and horizontal rules
|
|
23
|
-
|
|
24
|
-
## Installation
|
|
25
|
-
|
|
26
|
-
```bash
|
|
27
|
-
# Install with npm
|
|
28
|
-
$ npm install @docen/export-docx
|
|
29
|
-
|
|
30
|
-
# Install with yarn
|
|
31
|
-
$ yarn add @docen/export-docx
|
|
32
|
-
|
|
33
|
-
# Install with pnpm
|
|
34
|
-
$ pnpm add @docen/export-docx
|
|
35
|
-
```
|
|
36
|
-
|
|
37
|
-
## Quick Start
|
|
38
|
-
|
|
39
|
-
```typescript
|
|
40
|
-
import { generateDOCX } from "@docen/export-docx";
|
|
41
|
-
import { writeFileSync } from "node:fs";
|
|
42
|
-
|
|
43
|
-
// Your TipTap/ProseMirror editor content
|
|
44
|
-
const content = {
|
|
45
|
-
type: "doc",
|
|
46
|
-
content: [
|
|
47
|
-
{
|
|
48
|
-
type: "paragraph",
|
|
49
|
-
content: [
|
|
50
|
-
{
|
|
51
|
-
type: "text",
|
|
52
|
-
marks: [{ type: "bold" }, { type: "italic" }],
|
|
53
|
-
text: "Hello, world!",
|
|
54
|
-
},
|
|
55
|
-
],
|
|
56
|
-
},
|
|
57
|
-
],
|
|
58
|
-
};
|
|
59
|
-
|
|
60
|
-
// Convert to DOCX and save to file
|
|
61
|
-
const docx = await generateDOCX(content, { outputType: "nodebuffer" });
|
|
62
|
-
writeFileSync("document.docx", docx);
|
|
63
|
-
```
|
|
64
|
-
|
|
65
|
-
## API Reference
|
|
66
|
-
|
|
67
|
-
### `generateDOCX(content, options)`
|
|
68
|
-
|
|
69
|
-
Converts TipTap/ProseMirror content to DOCX format.
|
|
70
|
-
|
|
71
|
-
**Parameters:**
|
|
72
|
-
|
|
73
|
-
- `content: JSONContent` - TipTap/ProseMirror editor content
|
|
74
|
-
- `options: DocxExportOptions` - Export configuration options
|
|
75
|
-
|
|
76
|
-
**Returns:** `Promise<OutputByType[T]>` - DOCX file data with type matching the specified outputType
|
|
77
|
-
|
|
78
|
-
**Available Output Types:**
|
|
79
|
-
|
|
80
|
-
- `"base64"` - Base64 encoded string
|
|
81
|
-
- `"string"` - Text string
|
|
82
|
-
- `"text"` - Plain text
|
|
83
|
-
- `"binarystring"` - Binary string
|
|
84
|
-
- `"array"` - Array of numbers
|
|
85
|
-
- `"uint8array"` - Uint8Array
|
|
86
|
-
- `"arraybuffer"` - ArrayBuffer
|
|
87
|
-
- `"blob"` - Blob object
|
|
88
|
-
- `"nodebuffer"` - Node.js Buffer
|
|
89
|
-
|
|
90
|
-
**Configuration Options:**
|
|
91
|
-
|
|
92
|
-
- `title` - Document title
|
|
93
|
-
- `creator` - Document author
|
|
94
|
-
- `description` - Document description
|
|
95
|
-
- `outputType` - Output format (required)
|
|
96
|
-
- `table` - Table styling defaults (alignment, spacing, borders)
|
|
97
|
-
- `image` - Image handling options
|
|
98
|
-
- `styles` - Document default styles (font, line height, spacing)
|
|
99
|
-
- `horizontalRule` - Horizontal rule style
|
|
100
|
-
|
|
101
|
-
## Supported Content Types
|
|
102
|
-
|
|
103
|
-
### Text Formatting
|
|
104
|
-
|
|
105
|
-
- **Bold**, _Italic_, <u>Underline</u>, ~~Strikethrough~~
|
|
106
|
-
- ^Superscript^ and ~Subscript~
|
|
107
|
-
- Text colors and background colors
|
|
108
|
-
- Font families and sizes
|
|
109
|
-
- Line heights
|
|
110
|
-
|
|
111
|
-
### Block Elements
|
|
112
|
-
|
|
113
|
-
- **Headings** (H1-H6) with level attribute
|
|
114
|
-
- **Paragraphs** with text alignment (left, right, center, justify)
|
|
115
|
-
- **Blockquotes** (Note: Exported as indented paragraphs with left border due to DOCX format)
|
|
116
|
-
- **Horizontal Rules** (Exported as page breaks by default)
|
|
117
|
-
- **Code Blocks** with language support
|
|
118
|
-
|
|
119
|
-
### Lists
|
|
120
|
-
|
|
121
|
-
- **Bullet Lists** - Standard unordered lists
|
|
122
|
-
- **Numbered Lists** - Ordered lists with custom start number
|
|
123
|
-
- **Task Lists** - Checkbox lists with checked/unchecked states
|
|
124
|
-
|
|
125
|
-
### Tables
|
|
126
|
-
|
|
127
|
-
- Complete table structure with rows and cells
|
|
128
|
-
- **Table Headers** with colspan/rowspan support
|
|
129
|
-
- **Table Cells** with colspan/rowspan support
|
|
130
|
-
- Cell alignment and formatting options
|
|
131
|
-
|
|
132
|
-
### Media & Embeds
|
|
133
|
-
|
|
134
|
-
- **Images** with automatic sizing and positioning
|
|
135
|
-
- **Links** (hyperlinks) with href attribute
|
|
136
|
-
- **Emoji** rendering
|
|
137
|
-
- **Mathematics** formulas (LaTeX-style)
|
|
138
|
-
- **Details/Summary** collapsible sections
|
|
139
|
-
|
|
140
|
-
## Examples
|
|
141
|
-
|
|
142
|
-
### Document with Tables and Colspan/Rowspan
|
|
143
|
-
|
|
144
|
-
```typescript
|
|
145
|
-
const content = {
|
|
146
|
-
type: "doc",
|
|
147
|
-
content: [
|
|
148
|
-
{
|
|
149
|
-
type: "table",
|
|
150
|
-
content: [
|
|
151
|
-
{
|
|
152
|
-
type: "tableRow",
|
|
153
|
-
content: [
|
|
154
|
-
{
|
|
155
|
-
type: "tableHeader",
|
|
156
|
-
attrs: { colspan: 2, rowspan: 1 },
|
|
157
|
-
content: [
|
|
158
|
-
{
|
|
159
|
-
type: "paragraph",
|
|
160
|
-
content: [{ type: "text", text: "Spanning Header" }],
|
|
161
|
-
},
|
|
162
|
-
],
|
|
163
|
-
},
|
|
164
|
-
{
|
|
165
|
-
type: "tableCell",
|
|
166
|
-
content: [
|
|
167
|
-
{
|
|
168
|
-
type: "paragraph",
|
|
169
|
-
content: [{ type: "text", text: "Regular Cell" }],
|
|
170
|
-
},
|
|
171
|
-
],
|
|
172
|
-
},
|
|
173
|
-
],
|
|
174
|
-
},
|
|
175
|
-
],
|
|
176
|
-
},
|
|
177
|
-
],
|
|
178
|
-
};
|
|
179
|
-
```
|
|
180
|
-
|
|
181
|
-
### Document with Text Styles
|
|
182
|
-
|
|
183
|
-
```typescript
|
|
184
|
-
const content = {
|
|
185
|
-
type: "doc",
|
|
186
|
-
content: [
|
|
187
|
-
{
|
|
188
|
-
type: "paragraph",
|
|
189
|
-
content: [
|
|
190
|
-
{
|
|
191
|
-
type: "text",
|
|
192
|
-
marks: [
|
|
193
|
-
{
|
|
194
|
-
type: "textStyle",
|
|
195
|
-
attrs: {
|
|
196
|
-
color: "#FF0000",
|
|
197
|
-
fontSize: "18px",
|
|
198
|
-
fontFamily: "Arial",
|
|
199
|
-
backgroundColor: "#FFFF00",
|
|
200
|
-
},
|
|
201
|
-
},
|
|
202
|
-
],
|
|
203
|
-
text: "Red, 18px, Arial text on yellow background",
|
|
204
|
-
},
|
|
205
|
-
],
|
|
206
|
-
},
|
|
207
|
-
],
|
|
208
|
-
};
|
|
209
|
-
```
|
|
210
|
-
|
|
211
|
-
### Document with Lists
|
|
212
|
-
|
|
213
|
-
```typescript
|
|
214
|
-
const content = {
|
|
215
|
-
type: "doc",
|
|
216
|
-
content: [
|
|
217
|
-
{
|
|
218
|
-
type: "bulletList",
|
|
219
|
-
content: [
|
|
220
|
-
{
|
|
221
|
-
type: "listItem",
|
|
222
|
-
content: [
|
|
223
|
-
{
|
|
224
|
-
type: "paragraph",
|
|
225
|
-
content: [{ type: "text", text: "First item" }],
|
|
226
|
-
},
|
|
227
|
-
],
|
|
228
|
-
},
|
|
229
|
-
{
|
|
230
|
-
type: "listItem",
|
|
231
|
-
content: [
|
|
232
|
-
{
|
|
233
|
-
type: "paragraph",
|
|
234
|
-
content: [{ type: "text", text: "Second item" }],
|
|
235
|
-
},
|
|
236
|
-
],
|
|
237
|
-
},
|
|
238
|
-
],
|
|
239
|
-
},
|
|
240
|
-
],
|
|
241
|
-
};
|
|
242
|
-
```
|
|
243
|
-
|
|
244
|
-
## Known Limitations
|
|
245
|
-
|
|
246
|
-
### Blockquote Structure
|
|
247
|
-
|
|
248
|
-
DOCX does not have a semantic blockquote structure. Blockquotes are exported as:
|
|
249
|
-
|
|
250
|
-
- Indented paragraphs (720 twips / 0.5 inch left indentation)
|
|
251
|
-
- Left border (single line)
|
|
252
|
-
|
|
253
|
-
This is a DOCX format limitation, not a bug.
|
|
254
|
-
|
|
255
|
-
### Code Marks
|
|
256
|
-
|
|
257
|
-
The `code` mark is exported as monospace font (Consolas). When re-importing, it will be recognized as `textStyle` with `fontFamily: "Consolas"`, not as a `code` mark.
|
|
258
|
-
|
|
259
|
-
This is intentional - we do not detect code marks from fonts during import to avoid false positives.
|
|
260
|
-
|
|
261
|
-
### Color Name Conversion
|
|
262
|
-
|
|
263
|
-
Color names (like `"red"`, `"green"`, `"blue"`) are automatically converted to hex values (`"#FF0000"`, `"#008000"`, `"#0000FF"`) for DOCX compatibility.
|
|
264
|
-
|
|
265
|
-
## Contributing
|
|
266
|
-
|
|
267
|
-
Contributions are welcome! Please read our [Contributor Covenant](https://www.contributor-covenant.org/version/2/1/code_of_conduct/) and submit pull requests to the [main repository](https://github.com/DemoMacro/docen).
|
|
268
|
-
|
|
269
|
-
## License
|
|
270
|
-
|
|
271
|
-
- [MIT](LICENSE) © [Demo Macro](https://imst.xyz/)
|
|
1
|
+
# @docen/export-docx
|
|
2
|
+
|
|
3
|
+

|
|
4
|
+

|
|
5
|
+

|
|
6
|
+
|
|
7
|
+
> Export TipTap/ProseMirror editor content to Microsoft Word DOCX format.
|
|
8
|
+
|
|
9
|
+
## Features
|
|
10
|
+
|
|
11
|
+
- 📝 **Rich Text Support** - Full support for headings, paragraphs, and blockquotes with proper formatting
|
|
12
|
+
- 🖼️ **Image Handling** - Automatic image sizing, positioning, and metadata extraction
|
|
13
|
+
- 📊 **Table Support** - Complete table structure with headers, cells, colspan, and rowspan
|
|
14
|
+
- ✅ **Lists & Tasks** - Bullet lists, numbered lists with custom start numbers, and task lists with checkboxes
|
|
15
|
+
- 🎨 **Text Formatting** - Bold, italic, underline, strikethrough, subscript, and superscript
|
|
16
|
+
- 🎯 **Text Styles** - Comprehensive style support including colors, backgrounds, fonts, sizes, and line heights
|
|
17
|
+
- 🔗 **Links** - Hyperlink support with href preservation
|
|
18
|
+
- 💻 **Code Blocks** - Syntax highlighted code blocks with language attribute support
|
|
19
|
+
- 📁 **Collapsible Content** - Details/summary sections for expandable content
|
|
20
|
+
- 😀 **Emoji Support** - Native emoji rendering in documents
|
|
21
|
+
- 🧮 **Mathematical Content** - LaTeX-style formula support
|
|
22
|
+
- ⚙️ **Configurable Options** - Customizable export options for documents, tables, styles, and horizontal rules
|
|
23
|
+
|
|
24
|
+
## Installation
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
# Install with npm
|
|
28
|
+
$ npm install @docen/export-docx
|
|
29
|
+
|
|
30
|
+
# Install with yarn
|
|
31
|
+
$ yarn add @docen/export-docx
|
|
32
|
+
|
|
33
|
+
# Install with pnpm
|
|
34
|
+
$ pnpm add @docen/export-docx
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## Quick Start
|
|
38
|
+
|
|
39
|
+
```typescript
|
|
40
|
+
import { generateDOCX } from "@docen/export-docx";
|
|
41
|
+
import { writeFileSync } from "node:fs";
|
|
42
|
+
|
|
43
|
+
// Your TipTap/ProseMirror editor content
|
|
44
|
+
const content = {
|
|
45
|
+
type: "doc",
|
|
46
|
+
content: [
|
|
47
|
+
{
|
|
48
|
+
type: "paragraph",
|
|
49
|
+
content: [
|
|
50
|
+
{
|
|
51
|
+
type: "text",
|
|
52
|
+
marks: [{ type: "bold" }, { type: "italic" }],
|
|
53
|
+
text: "Hello, world!",
|
|
54
|
+
},
|
|
55
|
+
],
|
|
56
|
+
},
|
|
57
|
+
],
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
// Convert to DOCX and save to file
|
|
61
|
+
const docx = await generateDOCX(content, { outputType: "nodebuffer" });
|
|
62
|
+
writeFileSync("document.docx", docx);
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
## API Reference
|
|
66
|
+
|
|
67
|
+
### `generateDOCX(content, options)`
|
|
68
|
+
|
|
69
|
+
Converts TipTap/ProseMirror content to DOCX format.
|
|
70
|
+
|
|
71
|
+
**Parameters:**
|
|
72
|
+
|
|
73
|
+
- `content: JSONContent` - TipTap/ProseMirror editor content
|
|
74
|
+
- `options: DocxExportOptions` - Export configuration options
|
|
75
|
+
|
|
76
|
+
**Returns:** `Promise<OutputByType[T]>` - DOCX file data with type matching the specified outputType
|
|
77
|
+
|
|
78
|
+
**Available Output Types:**
|
|
79
|
+
|
|
80
|
+
- `"base64"` - Base64 encoded string
|
|
81
|
+
- `"string"` - Text string
|
|
82
|
+
- `"text"` - Plain text
|
|
83
|
+
- `"binarystring"` - Binary string
|
|
84
|
+
- `"array"` - Array of numbers
|
|
85
|
+
- `"uint8array"` - Uint8Array
|
|
86
|
+
- `"arraybuffer"` - ArrayBuffer
|
|
87
|
+
- `"blob"` - Blob object
|
|
88
|
+
- `"nodebuffer"` - Node.js Buffer
|
|
89
|
+
|
|
90
|
+
**Configuration Options:**
|
|
91
|
+
|
|
92
|
+
- `title` - Document title
|
|
93
|
+
- `creator` - Document author
|
|
94
|
+
- `description` - Document description
|
|
95
|
+
- `outputType` - Output format (required)
|
|
96
|
+
- `table` - Table styling defaults (alignment, spacing, borders)
|
|
97
|
+
- `image` - Image handling options
|
|
98
|
+
- `styles` - Document default styles (font, line height, spacing)
|
|
99
|
+
- `horizontalRule` - Horizontal rule style
|
|
100
|
+
|
|
101
|
+
## Supported Content Types
|
|
102
|
+
|
|
103
|
+
### Text Formatting
|
|
104
|
+
|
|
105
|
+
- **Bold**, _Italic_, <u>Underline</u>, ~~Strikethrough~~
|
|
106
|
+
- ^Superscript^ and ~Subscript~
|
|
107
|
+
- Text colors and background colors
|
|
108
|
+
- Font families and sizes
|
|
109
|
+
- Line heights
|
|
110
|
+
|
|
111
|
+
### Block Elements
|
|
112
|
+
|
|
113
|
+
- **Headings** (H1-H6) with level attribute
|
|
114
|
+
- **Paragraphs** with text alignment (left, right, center, justify)
|
|
115
|
+
- **Blockquotes** (Note: Exported as indented paragraphs with left border due to DOCX format)
|
|
116
|
+
- **Horizontal Rules** (Exported as page breaks by default)
|
|
117
|
+
- **Code Blocks** with language support
|
|
118
|
+
|
|
119
|
+
### Lists
|
|
120
|
+
|
|
121
|
+
- **Bullet Lists** - Standard unordered lists
|
|
122
|
+
- **Numbered Lists** - Ordered lists with custom start number
|
|
123
|
+
- **Task Lists** - Checkbox lists with checked/unchecked states
|
|
124
|
+
|
|
125
|
+
### Tables
|
|
126
|
+
|
|
127
|
+
- Complete table structure with rows and cells
|
|
128
|
+
- **Table Headers** with colspan/rowspan support
|
|
129
|
+
- **Table Cells** with colspan/rowspan support
|
|
130
|
+
- Cell alignment and formatting options
|
|
131
|
+
|
|
132
|
+
### Media & Embeds
|
|
133
|
+
|
|
134
|
+
- **Images** with automatic sizing and positioning
|
|
135
|
+
- **Links** (hyperlinks) with href attribute
|
|
136
|
+
- **Emoji** rendering
|
|
137
|
+
- **Mathematics** formulas (LaTeX-style)
|
|
138
|
+
- **Details/Summary** collapsible sections
|
|
139
|
+
|
|
140
|
+
## Examples
|
|
141
|
+
|
|
142
|
+
### Document with Tables and Colspan/Rowspan
|
|
143
|
+
|
|
144
|
+
```typescript
|
|
145
|
+
const content = {
|
|
146
|
+
type: "doc",
|
|
147
|
+
content: [
|
|
148
|
+
{
|
|
149
|
+
type: "table",
|
|
150
|
+
content: [
|
|
151
|
+
{
|
|
152
|
+
type: "tableRow",
|
|
153
|
+
content: [
|
|
154
|
+
{
|
|
155
|
+
type: "tableHeader",
|
|
156
|
+
attrs: { colspan: 2, rowspan: 1 },
|
|
157
|
+
content: [
|
|
158
|
+
{
|
|
159
|
+
type: "paragraph",
|
|
160
|
+
content: [{ type: "text", text: "Spanning Header" }],
|
|
161
|
+
},
|
|
162
|
+
],
|
|
163
|
+
},
|
|
164
|
+
{
|
|
165
|
+
type: "tableCell",
|
|
166
|
+
content: [
|
|
167
|
+
{
|
|
168
|
+
type: "paragraph",
|
|
169
|
+
content: [{ type: "text", text: "Regular Cell" }],
|
|
170
|
+
},
|
|
171
|
+
],
|
|
172
|
+
},
|
|
173
|
+
],
|
|
174
|
+
},
|
|
175
|
+
],
|
|
176
|
+
},
|
|
177
|
+
],
|
|
178
|
+
};
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
### Document with Text Styles
|
|
182
|
+
|
|
183
|
+
```typescript
|
|
184
|
+
const content = {
|
|
185
|
+
type: "doc",
|
|
186
|
+
content: [
|
|
187
|
+
{
|
|
188
|
+
type: "paragraph",
|
|
189
|
+
content: [
|
|
190
|
+
{
|
|
191
|
+
type: "text",
|
|
192
|
+
marks: [
|
|
193
|
+
{
|
|
194
|
+
type: "textStyle",
|
|
195
|
+
attrs: {
|
|
196
|
+
color: "#FF0000",
|
|
197
|
+
fontSize: "18px",
|
|
198
|
+
fontFamily: "Arial",
|
|
199
|
+
backgroundColor: "#FFFF00",
|
|
200
|
+
},
|
|
201
|
+
},
|
|
202
|
+
],
|
|
203
|
+
text: "Red, 18px, Arial text on yellow background",
|
|
204
|
+
},
|
|
205
|
+
],
|
|
206
|
+
},
|
|
207
|
+
],
|
|
208
|
+
};
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
### Document with Lists
|
|
212
|
+
|
|
213
|
+
```typescript
|
|
214
|
+
const content = {
|
|
215
|
+
type: "doc",
|
|
216
|
+
content: [
|
|
217
|
+
{
|
|
218
|
+
type: "bulletList",
|
|
219
|
+
content: [
|
|
220
|
+
{
|
|
221
|
+
type: "listItem",
|
|
222
|
+
content: [
|
|
223
|
+
{
|
|
224
|
+
type: "paragraph",
|
|
225
|
+
content: [{ type: "text", text: "First item" }],
|
|
226
|
+
},
|
|
227
|
+
],
|
|
228
|
+
},
|
|
229
|
+
{
|
|
230
|
+
type: "listItem",
|
|
231
|
+
content: [
|
|
232
|
+
{
|
|
233
|
+
type: "paragraph",
|
|
234
|
+
content: [{ type: "text", text: "Second item" }],
|
|
235
|
+
},
|
|
236
|
+
],
|
|
237
|
+
},
|
|
238
|
+
],
|
|
239
|
+
},
|
|
240
|
+
],
|
|
241
|
+
};
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
## Known Limitations
|
|
245
|
+
|
|
246
|
+
### Blockquote Structure
|
|
247
|
+
|
|
248
|
+
DOCX does not have a semantic blockquote structure. Blockquotes are exported as:
|
|
249
|
+
|
|
250
|
+
- Indented paragraphs (720 twips / 0.5 inch left indentation)
|
|
251
|
+
- Left border (single line)
|
|
252
|
+
|
|
253
|
+
This is a DOCX format limitation, not a bug.
|
|
254
|
+
|
|
255
|
+
### Code Marks
|
|
256
|
+
|
|
257
|
+
The `code` mark is exported as monospace font (Consolas). When re-importing, it will be recognized as `textStyle` with `fontFamily: "Consolas"`, not as a `code` mark.
|
|
258
|
+
|
|
259
|
+
This is intentional - we do not detect code marks from fonts during import to avoid false positives.
|
|
260
|
+
|
|
261
|
+
### Color Name Conversion
|
|
262
|
+
|
|
263
|
+
Color names (like `"red"`, `"green"`, `"blue"`) are automatically converted to hex values (`"#FF0000"`, `"#008000"`, `"#0000FF"`) for DOCX compatibility.
|
|
264
|
+
|
|
265
|
+
## Contributing
|
|
266
|
+
|
|
267
|
+
Contributions are welcome! Please read our [Contributor Covenant](https://www.contributor-covenant.org/version/2/1/code_of_conduct/) and submit pull requests to the [main repository](https://github.com/DemoMacro/docen).
|
|
268
|
+
|
|
269
|
+
## License
|
|
270
|
+
|
|
271
|
+
- [MIT](LICENSE) © [Demo Macro](https://imst.xyz/)
|
package/dist/index.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ExternalHyperlink, FileChild,
|
|
1
|
+
import { ExternalHyperlink, FileChild, IImageOptions, IParagraphOptions, IParagraphStyleOptions, IPropertiesOptions, ISectionOptions, ITableCellOptions, ITableOfContentsOptions, ITableOptions, ITableRowOptions, ImageRun, OutputByType, OutputType, PositiveUniversalMeasure as PositiveUniversalMeasure$1, Table, TableCell, TableRow, TextRun } from "docx";
|
|
2
2
|
import { ImageMeta } from "image-meta";
|
|
3
3
|
|
|
4
4
|
//#region ../../node_modules/.pnpm/orderedmap@2.1.1/node_modules/orderedmap/dist/index.d.ts
|
|
@@ -3672,7 +3672,7 @@ point into textblock nodes. It can be empty (a regular cursor
|
|
|
3672
3672
|
position).
|
|
3673
3673
|
*/
|
|
3674
3674
|
//#endregion
|
|
3675
|
-
//#region ../../node_modules/.pnpm/@tiptap+core@3.20.
|
|
3675
|
+
//#region ../../node_modules/.pnpm/@tiptap+core@3.20.0_@tiptap+pm@3.20.0/node_modules/@tiptap/core/dist/index.d.ts
|
|
3676
3676
|
type StringKeyOf<T> = Extract<keyof T, string>;
|
|
3677
3677
|
type CallbackType<T extends Record<string, any>, EventName extends StringKeyOf<T>> = T[EventName] extends any[] ? T[EventName] : [T[EventName]];
|
|
3678
3678
|
type CallbackFunction<T extends Record<string, any>, EventName extends StringKeyOf<T>> = (...props: CallbackType<T, EventName>) => any;
|
|
@@ -6630,10 +6630,14 @@ declare function createFloatingOptions(): {
|
|
|
6630
6630
|
};
|
|
6631
6631
|
/**
|
|
6632
6632
|
* Get image width with priority: node attrs > image meta > calculated > default
|
|
6633
|
+
*
|
|
6634
|
+
* Note: maxWidth constraint only applies to inline (non-floating) images.
|
|
6635
|
+
* Floating images maintain their original dimensions.
|
|
6633
6636
|
*/
|
|
6634
6637
|
declare function getImageWidth(node: {
|
|
6635
6638
|
attrs?: {
|
|
6636
6639
|
width?: number | null;
|
|
6640
|
+
floating?: any;
|
|
6637
6641
|
};
|
|
6638
6642
|
}, imageMeta?: {
|
|
6639
6643
|
width?: number;
|
|
@@ -6641,10 +6645,15 @@ declare function getImageWidth(node: {
|
|
|
6641
6645
|
}, maxWidth?: number | PositiveUniversalMeasure$1): number;
|
|
6642
6646
|
/**
|
|
6643
6647
|
* Get image height with priority: node attrs > image meta > calculated > default
|
|
6648
|
+
*
|
|
6649
|
+
* Note: maxWidth constraint only applies to inline (non-floating) images.
|
|
6650
|
+
* Floating images maintain their original dimensions and aspect ratio.
|
|
6644
6651
|
*/
|
|
6645
6652
|
declare function getImageHeight(node: {
|
|
6646
6653
|
attrs?: {
|
|
6647
6654
|
height?: number | null;
|
|
6655
|
+
width?: number | null;
|
|
6656
|
+
floating?: any;
|
|
6648
6657
|
};
|
|
6649
6658
|
}, width: number, imageMeta?: {
|
|
6650
6659
|
width?: number;
|
|
@@ -6754,12 +6763,225 @@ declare function convertDocument(node: JSONContent, params: {
|
|
|
6754
6763
|
declare function convertNode(node: JSONContent, options: DocxExportOptions, effectiveContentWidth: number): Promise<FileChild | FileChild[] | null>;
|
|
6755
6764
|
//#endregion
|
|
6756
6765
|
//#region ../extensions/dist/types.d.mts
|
|
6766
|
+
//#region ../../node_modules/.pnpm/docx@9.6.1/node_modules/docx/dist/index.d.ts
|
|
6767
|
+
declare const CompoundLine: {
|
|
6768
|
+
readonly SINGLE: "sng";
|
|
6769
|
+
readonly DOUBLE: "dbl";
|
|
6770
|
+
readonly THICK_THIN: "thickThin";
|
|
6771
|
+
readonly THIN_THICK: "thinThick";
|
|
6772
|
+
readonly TRI: "tri";
|
|
6773
|
+
};
|
|
6774
|
+
declare type CoreImageOptions = {
|
|
6775
|
+
readonly transformation: IMediaTransformation;
|
|
6776
|
+
readonly floating?: IFloating;
|
|
6777
|
+
readonly altText?: DocPropertiesOptions;
|
|
6778
|
+
readonly outline?: OutlineOptions;
|
|
6779
|
+
readonly solidFill?: SolidFillOptions;
|
|
6780
|
+
};
|
|
6781
|
+
declare type DocPropertiesOptions = {
|
|
6782
|
+
readonly name: string;
|
|
6783
|
+
readonly description?: string;
|
|
6784
|
+
readonly title?: string;
|
|
6785
|
+
readonly id?: string;
|
|
6786
|
+
};
|
|
6787
|
+
declare const HorizontalPositionAlign: {
|
|
6788
|
+
readonly CENTER: "center";
|
|
6789
|
+
readonly INSIDE: "inside";
|
|
6790
|
+
readonly LEFT: "left";
|
|
6791
|
+
readonly OUTSIDE: "outside";
|
|
6792
|
+
readonly RIGHT: "right";
|
|
6793
|
+
};
|
|
6794
|
+
declare const HorizontalPositionRelativeFrom: {
|
|
6795
|
+
readonly CHARACTER: "character";
|
|
6796
|
+
readonly COLUMN: "column";
|
|
6797
|
+
readonly INSIDE_MARGIN: "insideMargin";
|
|
6798
|
+
readonly LEFT_MARGIN: "leftMargin";
|
|
6799
|
+
readonly MARGIN: "margin";
|
|
6800
|
+
readonly OUTSIDE_MARGIN: "outsideMargin";
|
|
6801
|
+
readonly PAGE: "page";
|
|
6802
|
+
readonly RIGHT_MARGIN: "rightMargin";
|
|
6803
|
+
};
|
|
6804
|
+
declare type IDistance = {
|
|
6805
|
+
readonly distT?: number;
|
|
6806
|
+
readonly distB?: number;
|
|
6807
|
+
readonly distL?: number;
|
|
6808
|
+
readonly distR?: number;
|
|
6809
|
+
};
|
|
6810
|
+
declare type IFloating = {
|
|
6811
|
+
readonly horizontalPosition: IHorizontalPositionOptions;
|
|
6812
|
+
readonly verticalPosition: IVerticalPositionOptions;
|
|
6813
|
+
readonly allowOverlap?: boolean;
|
|
6814
|
+
readonly lockAnchor?: boolean;
|
|
6815
|
+
readonly behindDocument?: boolean;
|
|
6816
|
+
readonly layoutInCell?: boolean;
|
|
6817
|
+
readonly margins?: IMargins;
|
|
6818
|
+
readonly wrap?: ITextWrapping;
|
|
6819
|
+
readonly zIndex?: number;
|
|
6820
|
+
};
|
|
6821
|
+
declare type IHorizontalPositionOptions = {
|
|
6822
|
+
readonly relative?: (typeof HorizontalPositionRelativeFrom)[keyof typeof HorizontalPositionRelativeFrom];
|
|
6823
|
+
readonly align?: (typeof HorizontalPositionAlign)[keyof typeof HorizontalPositionAlign];
|
|
6824
|
+
readonly offset?: number;
|
|
6825
|
+
};
|
|
6826
|
+
declare type IImageOptions$1 = (RegularImageOptions | SvgMediaOptions) & CoreImageOptions;
|
|
6827
|
+
declare type IMargins = {
|
|
6828
|
+
readonly left?: number;
|
|
6829
|
+
readonly bottom?: number;
|
|
6830
|
+
readonly top?: number;
|
|
6831
|
+
readonly right?: number;
|
|
6832
|
+
};
|
|
6833
|
+
declare type IMediaTransformation = {
|
|
6834
|
+
readonly offset?: {
|
|
6835
|
+
readonly top?: number;
|
|
6836
|
+
readonly left?: number;
|
|
6837
|
+
};
|
|
6838
|
+
readonly width: number;
|
|
6839
|
+
readonly height: number;
|
|
6840
|
+
readonly flip?: {
|
|
6841
|
+
readonly vertical?: boolean;
|
|
6842
|
+
readonly horizontal?: boolean;
|
|
6843
|
+
};
|
|
6844
|
+
readonly rotation?: number;
|
|
6845
|
+
};
|
|
6846
|
+
declare type ITextWrapping = {
|
|
6847
|
+
readonly type: (typeof TextWrappingType)[keyof typeof TextWrappingType];
|
|
6848
|
+
readonly side?: (typeof TextWrappingSide)[keyof typeof TextWrappingSide];
|
|
6849
|
+
readonly margins?: IDistance;
|
|
6850
|
+
};
|
|
6851
|
+
declare type IVerticalPositionOptions = {
|
|
6852
|
+
readonly relative?: (typeof VerticalPositionRelativeFrom)[keyof typeof VerticalPositionRelativeFrom];
|
|
6853
|
+
readonly align?: (typeof VerticalPositionAlign)[keyof typeof VerticalPositionAlign];
|
|
6854
|
+
readonly offset?: number;
|
|
6855
|
+
};
|
|
6856
|
+
declare const LineCap: {
|
|
6857
|
+
readonly ROUND: "rnd";
|
|
6858
|
+
readonly SQUARE: "sq";
|
|
6859
|
+
readonly FLAT: "flat";
|
|
6860
|
+
};
|
|
6861
|
+
declare type OutlineAttributes = {
|
|
6862
|
+
readonly width?: number;
|
|
6863
|
+
readonly cap?: keyof typeof LineCap;
|
|
6864
|
+
readonly compoundLine?: keyof typeof CompoundLine;
|
|
6865
|
+
readonly align?: keyof typeof PenAlignment;
|
|
6866
|
+
};
|
|
6867
|
+
declare type OutlineFillProperties = OutlineNoFill | OutlineSolidFill;
|
|
6868
|
+
declare type OutlineNoFill = {
|
|
6869
|
+
readonly type: "noFill";
|
|
6870
|
+
};
|
|
6871
|
+
declare type OutlineOptions = OutlineAttributes & OutlineFillProperties;
|
|
6872
|
+
declare type OutlineRgbSolidFill = {
|
|
6873
|
+
readonly type: "solidFill";
|
|
6874
|
+
readonly solidFillType: "rgb";
|
|
6875
|
+
readonly value: string;
|
|
6876
|
+
};
|
|
6877
|
+
declare type OutlineSchemeSolidFill = {
|
|
6878
|
+
readonly type: "solidFill";
|
|
6879
|
+
readonly solidFillType: "scheme";
|
|
6880
|
+
readonly value: (typeof SchemeColor)[keyof typeof SchemeColor];
|
|
6881
|
+
};
|
|
6882
|
+
declare type OutlineSolidFill = OutlineRgbSolidFill | OutlineSchemeSolidFill;
|
|
6883
|
+
declare const PenAlignment: {
|
|
6884
|
+
readonly CENTER: "ctr";
|
|
6885
|
+
readonly INSET: "in";
|
|
6886
|
+
};
|
|
6887
|
+
declare type RegularImageOptions = {
|
|
6888
|
+
readonly type: "jpg" | "png" | "gif" | "bmp";
|
|
6889
|
+
readonly data: Buffer | string | Uint8Array | ArrayBuffer;
|
|
6890
|
+
};
|
|
6891
|
+
declare type RgbColorOptions = {
|
|
6892
|
+
readonly type: "rgb";
|
|
6893
|
+
readonly value: string;
|
|
6894
|
+
};
|
|
6895
|
+
declare const SchemeColor: {
|
|
6896
|
+
readonly BG1: "bg1";
|
|
6897
|
+
readonly TX1: "tx1";
|
|
6898
|
+
readonly BG2: "bg2";
|
|
6899
|
+
readonly TX2: "tx2";
|
|
6900
|
+
readonly ACCENT1: "accent1";
|
|
6901
|
+
readonly ACCENT2: "accent2";
|
|
6902
|
+
readonly ACCENT3: "accent3";
|
|
6903
|
+
readonly ACCENT4: "accent4";
|
|
6904
|
+
readonly ACCENT5: "accent5";
|
|
6905
|
+
readonly ACCENT6: "accent6";
|
|
6906
|
+
readonly HLINK: "hlink";
|
|
6907
|
+
readonly FOLHLINK: "folHlink";
|
|
6908
|
+
readonly DK1: "dk1";
|
|
6909
|
+
readonly LT1: "lt1";
|
|
6910
|
+
readonly DK2: "dk2";
|
|
6911
|
+
readonly LT2: "lt2";
|
|
6912
|
+
readonly PHCLR: "phClr";
|
|
6913
|
+
};
|
|
6914
|
+
declare type SchemeColorOptions = {
|
|
6915
|
+
readonly type: "scheme";
|
|
6916
|
+
readonly value: (typeof SchemeColor)[keyof typeof SchemeColor];
|
|
6917
|
+
};
|
|
6918
|
+
declare type SolidFillOptions = RgbColorOptions | SchemeColorOptions;
|
|
6919
|
+
declare type SvgMediaOptions = {
|
|
6920
|
+
readonly type: "svg";
|
|
6921
|
+
readonly data: Buffer | string | Uint8Array | ArrayBuffer;
|
|
6922
|
+
readonly fallback: RegularImageOptions;
|
|
6923
|
+
};
|
|
6924
|
+
declare const TextWrappingSide: {
|
|
6925
|
+
readonly BOTH_SIDES: "bothSides";
|
|
6926
|
+
readonly LEFT: "left";
|
|
6927
|
+
readonly RIGHT: "right";
|
|
6928
|
+
readonly LARGEST: "largest";
|
|
6929
|
+
};
|
|
6930
|
+
declare const TextWrappingType: {
|
|
6931
|
+
readonly NONE: 0;
|
|
6932
|
+
readonly SQUARE: 1;
|
|
6933
|
+
readonly TIGHT: 2;
|
|
6934
|
+
readonly TOP_AND_BOTTOM: 3;
|
|
6935
|
+
};
|
|
6936
|
+
declare const VerticalPositionAlign: {
|
|
6937
|
+
readonly BOTTOM: "bottom";
|
|
6938
|
+
readonly CENTER: "center";
|
|
6939
|
+
readonly INSIDE: "inside";
|
|
6940
|
+
readonly OUTSIDE: "outside";
|
|
6941
|
+
readonly TOP: "top";
|
|
6942
|
+
};
|
|
6943
|
+
declare const VerticalPositionRelativeFrom: {
|
|
6944
|
+
readonly BOTTOM_MARGIN: "bottomMargin";
|
|
6945
|
+
readonly INSIDE_MARGIN: "insideMargin";
|
|
6946
|
+
readonly LINE: "line";
|
|
6947
|
+
readonly MARGIN: "margin";
|
|
6948
|
+
readonly OUTSIDE_MARGIN: "outsideMargin";
|
|
6949
|
+
readonly PAGE: "page";
|
|
6950
|
+
readonly PARAGRAPH: "paragraph";
|
|
6951
|
+
readonly TOP_MARGIN: "topMargin";
|
|
6952
|
+
}; //#endregion
|
|
6757
6953
|
//#region src/types.d.ts
|
|
6954
|
+
/**
|
|
6955
|
+
* Border definition (compatible with docx.js BorderOptions)
|
|
6956
|
+
* Used by paragraphs, table cells, and blockquotes
|
|
6957
|
+
*/
|
|
6958
|
+
interface Border {
|
|
6959
|
+
/** Border color (hex without #, e.g., "FF0000" or "auto") */
|
|
6960
|
+
color?: string;
|
|
6961
|
+
/** Border size (eighth-points, 1/8 pt) */
|
|
6962
|
+
size?: number;
|
|
6963
|
+
/** Border style */
|
|
6964
|
+
style?: "single" | "dashed" | "dotted" | "double" | "dotDash" | "dotDotDash" | "none";
|
|
6965
|
+
/** Space between border and content (points) */
|
|
6966
|
+
space?: number;
|
|
6967
|
+
}
|
|
6968
|
+
/**
|
|
6969
|
+
* Shading definition (compatible with docx.js ShadingOptions)
|
|
6970
|
+
* Used for paragraph and table cell background colors
|
|
6971
|
+
*/
|
|
6972
|
+
interface Shading {
|
|
6973
|
+
/** Fill color (hex without #, e.g., "FF0000") */
|
|
6974
|
+
fill?: string;
|
|
6975
|
+
/** Pattern color (hex without #) */
|
|
6976
|
+
color?: string;
|
|
6977
|
+
/** Shading pattern type (e.g., "clear", "percent-10") */
|
|
6978
|
+
type?: string;
|
|
6979
|
+
}
|
|
6758
6980
|
type ImageFloatingOptions = {
|
|
6759
6981
|
horizontalPosition: IHorizontalPositionOptions;
|
|
6760
6982
|
verticalPosition: IVerticalPositionOptions;
|
|
6761
6983
|
} & Partial<Omit<IFloating, "horizontalPosition" | "verticalPosition">>;
|
|
6762
|
-
type ImageOutlineOptions = IImageOptions["outline"];
|
|
6984
|
+
type ImageOutlineOptions = IImageOptions$1["outline"];
|
|
6763
6985
|
interface TextNode {
|
|
6764
6986
|
type: "text";
|
|
6765
6987
|
text: string;
|
|
@@ -6797,6 +7019,11 @@ interface ParagraphNode extends JSONContent {
|
|
|
6797
7019
|
indentFirstLine?: string;
|
|
6798
7020
|
spacingBefore?: string;
|
|
6799
7021
|
spacingAfter?: string;
|
|
7022
|
+
shading?: Shading;
|
|
7023
|
+
borderTop?: Border;
|
|
7024
|
+
borderBottom?: Border;
|
|
7025
|
+
borderLeft?: Border;
|
|
7026
|
+
borderRight?: Border;
|
|
6800
7027
|
};
|
|
6801
7028
|
content?: Array<TextNode | HardBreakNode | ImageNode>;
|
|
6802
7029
|
}
|
|
@@ -6810,6 +7037,11 @@ interface HeadingNode extends JSONContent {
|
|
|
6810
7037
|
spacingBefore?: string;
|
|
6811
7038
|
spacingAfter?: string;
|
|
6812
7039
|
textAlign?: "left" | "right" | "center" | "justify";
|
|
7040
|
+
shading?: Shading;
|
|
7041
|
+
borderTop?: Border;
|
|
7042
|
+
borderBottom?: Border;
|
|
7043
|
+
borderLeft?: Border;
|
|
7044
|
+
borderRight?: Border;
|
|
6813
7045
|
};
|
|
6814
7046
|
content?: Array<TextNode | HardBreakNode>;
|
|
6815
7047
|
}
|
|
@@ -6855,11 +7087,6 @@ interface TaskItemNode extends JSONContent {
|
|
|
6855
7087
|
};
|
|
6856
7088
|
content?: Array<ParagraphNode>;
|
|
6857
7089
|
}
|
|
6858
|
-
interface TableCellBorder {
|
|
6859
|
-
color?: string;
|
|
6860
|
-
width?: number;
|
|
6861
|
-
style?: "solid" | "dashed" | "dotted" | "double" | "none";
|
|
6862
|
-
}
|
|
6863
7090
|
interface TableNode extends JSONContent {
|
|
6864
7091
|
type: "table";
|
|
6865
7092
|
attrs?: {
|
|
@@ -6885,10 +7112,10 @@ interface TableCellNode extends JSONContent {
|
|
|
6885
7112
|
colwidth?: number[] | null;
|
|
6886
7113
|
backgroundColor?: string | null;
|
|
6887
7114
|
verticalAlign?: "top" | "middle" | "bottom" | null;
|
|
6888
|
-
borderTop?:
|
|
6889
|
-
borderBottom?:
|
|
6890
|
-
borderLeft?:
|
|
6891
|
-
borderRight?:
|
|
7115
|
+
borderTop?: Border;
|
|
7116
|
+
borderBottom?: Border;
|
|
7117
|
+
borderLeft?: Border;
|
|
7118
|
+
borderRight?: Border;
|
|
6892
7119
|
};
|
|
6893
7120
|
content?: Array<ParagraphNode>;
|
|
6894
7121
|
}
|
|
@@ -6900,10 +7127,10 @@ interface TableHeaderNode extends JSONContent {
|
|
|
6900
7127
|
colwidth?: number[] | null;
|
|
6901
7128
|
backgroundColor?: string | null;
|
|
6902
7129
|
verticalAlign?: "top" | "middle" | "bottom" | null;
|
|
6903
|
-
borderTop?:
|
|
6904
|
-
borderBottom?:
|
|
6905
|
-
borderLeft?:
|
|
6906
|
-
borderRight?:
|
|
7130
|
+
borderTop?: Border;
|
|
7131
|
+
borderBottom?: Border;
|
|
7132
|
+
borderLeft?: Border;
|
|
7133
|
+
borderRight?: Border;
|
|
6907
7134
|
};
|
|
6908
7135
|
content?: Array<ParagraphNode>;
|
|
6909
7136
|
}
|
|
@@ -7623,26 +7850,30 @@ declare function createStringValidator<T extends string>(validValues: readonly T
|
|
|
7623
7850
|
* Calculate effective content width from document options
|
|
7624
7851
|
*/
|
|
7625
7852
|
declare function calculateEffectiveContentWidth(options?: DocxExportOptions): number;
|
|
7626
|
-
//#endregion
|
|
7627
|
-
//#region src/utils/paragraph.d.ts
|
|
7628
7853
|
/**
|
|
7629
|
-
*
|
|
7854
|
+
* Convert Border to docx.js format
|
|
7630
7855
|
*/
|
|
7631
|
-
declare
|
|
7632
|
-
|
|
7633
|
-
|
|
7856
|
+
declare function convertBorder(border?: Border): {
|
|
7857
|
+
color?: string;
|
|
7858
|
+
size?: number;
|
|
7859
|
+
style?: string;
|
|
7860
|
+
space?: number;
|
|
7861
|
+
} | undefined;
|
|
7634
7862
|
/**
|
|
7635
|
-
* Convert
|
|
7636
|
-
*
|
|
7637
|
-
* @param border - TipTap table cell border definition
|
|
7638
|
-
* @returns DOCX border options or undefined if no border
|
|
7863
|
+
* Convert Shading to docx.js format
|
|
7639
7864
|
*/
|
|
7640
|
-
declare function
|
|
7865
|
+
declare function convertShading(shading?: Shading): {
|
|
7866
|
+
fill?: string;
|
|
7641
7867
|
color?: string;
|
|
7642
|
-
|
|
7643
|
-
style: "single" | "dashed" | "dotted" | "double" | "none";
|
|
7868
|
+
val?: string;
|
|
7644
7869
|
} | undefined;
|
|
7645
7870
|
//#endregion
|
|
7871
|
+
//#region src/utils/paragraph.d.ts
|
|
7872
|
+
/**
|
|
7873
|
+
* Apply paragraph style attributes to options
|
|
7874
|
+
*/
|
|
7875
|
+
declare const applyParagraphStyleAttributes: <T extends Record<string, unknown>>(options: T, attrs?: ParagraphNode["attrs"]) => T;
|
|
7876
|
+
//#endregion
|
|
7646
7877
|
//#region src/converters/image.d.ts
|
|
7647
7878
|
/**
|
|
7648
7879
|
* Convert TipTap image node to DOCX ImageRun
|
|
@@ -7816,4 +8047,4 @@ declare function convertDetailsSummary(node: DetailsSummaryNode, params: {
|
|
|
7816
8047
|
/** Export options for details styling */options?: DocxExportOptions["details"];
|
|
7817
8048
|
}): IParagraphOptions;
|
|
7818
8049
|
//#endregion
|
|
7819
|
-
export { BlockNode, BlockquoteNode, BulletListNode, CHECKBOX_SYMBOLS, COLOR_NAME_TO_HEX, CodeBlockNode, DEFAULT_CODE_FONT, DOCX_DPI, DOCX_STYLE_NAMES, DetailsContentNode, DetailsNode, DetailsSummaryNode, DocumentNode, DocxExportOptions, DocxImageExportHandler, EMUS_PER_INCH, HALF_POINTS_PER_PIXEL, HardBreakNode, HeadingNode, HorizontalRuleNode, ImageFloatingOptions, ImageNode, ImageOutlineOptions, type JSONContent, ListItemNode, ListOptions, Mark, OrderedListNode, PAGE_DIMENSIONS, PIXELS_PER_HALF_POINT, ParagraphNode, PositiveUniversalMeasure, TEXT_ALIGN_MAP, TWIPS_PER_INCH,
|
|
8050
|
+
export { BlockNode, BlockquoteNode, Border, BulletListNode, CHECKBOX_SYMBOLS, COLOR_NAME_TO_HEX, CodeBlockNode, DEFAULT_CODE_FONT, DOCX_DPI, DOCX_STYLE_NAMES, DetailsContentNode, DetailsNode, DetailsSummaryNode, DocumentNode, DocxExportOptions, DocxImageExportHandler, EMUS_PER_INCH, HALF_POINTS_PER_PIXEL, HardBreakNode, HeadingNode, HorizontalRuleNode, ImageFloatingOptions, ImageNode, ImageOutlineOptions, type JSONContent, ListItemNode, ListOptions, Mark, OrderedListNode, PAGE_DIMENSIONS, PIXELS_PER_HALF_POINT, ParagraphNode, PositiveUniversalMeasure, Shading, TEXT_ALIGN_MAP, TWIPS_PER_INCH, TableCellNode, TableHeaderNode, TableNode, TableRowNode, TaskItemNode, TaskListNode, TextContent, TextNode, applyParagraphStyleAttributes, applyTableMargins, calculateEffectiveContentWidth, convertBlockquote, convertBorder, convertBulletList, convertCodeBlock, convertColorToHex, convertCssLengthToPixels, convertDetailsSummary, convertDocument, convertEmuStringToPixels, convertEmuToPixels, convertHardBreak, convertHeading, convertHorizontalRule, convertImage, convertList, convertListItem, convertMeasureToInches, convertMeasureToPixels, convertNode, convertOrderedList, convertParagraph, convertPixelsToEmu, convertPixelsToTwip, convertShading, convertTable, convertTableCell, convertTableHeader, convertTableRow, convertTaskItem, convertTaskList, convertText, convertTextNodes, convertToDocxImageType, convertTwipToCssString, convertTwipToPixels, createFloatingOptions, createStringValidator, findChild, findDeepChild, findDeepChildren, generateDOCX, getImageDataAndMeta, getImageHeight, getImageTypeFromSrc, getImageWidth, normalizeHexColor, parseTwipAttr };
|
package/dist/index.mjs
CHANGED
|
@@ -438,6 +438,29 @@ function calculateEffectiveContentWidth(options) {
|
|
|
438
438
|
const effectiveWidth = pageWidth - marginLeft - marginRight;
|
|
439
439
|
return Math.max(convertTwipToPixels(effectiveWidth), 96);
|
|
440
440
|
}
|
|
441
|
+
/**
|
|
442
|
+
* Convert Border to docx.js format
|
|
443
|
+
*/
|
|
444
|
+
function convertBorder(border) {
|
|
445
|
+
if (!border) return void 0;
|
|
446
|
+
const docxBorder = {};
|
|
447
|
+
if (border.color) docxBorder.color = border.color.replace("#", "");
|
|
448
|
+
if (border.size !== void 0) docxBorder.size = border.size;
|
|
449
|
+
if (border.style) docxBorder.style = border.style;
|
|
450
|
+
if (border.space !== void 0) docxBorder.space = border.space;
|
|
451
|
+
return Object.keys(docxBorder).length > 0 ? docxBorder : void 0;
|
|
452
|
+
}
|
|
453
|
+
/**
|
|
454
|
+
* Convert Shading to docx.js format
|
|
455
|
+
*/
|
|
456
|
+
function convertShading(shading) {
|
|
457
|
+
if (!shading || !shading.fill) return void 0;
|
|
458
|
+
const docxShading = {};
|
|
459
|
+
if (shading.fill) docxShading.fill = shading.fill.replace("#", "");
|
|
460
|
+
if (shading.color) docxShading.color = shading.color.replace("#", "");
|
|
461
|
+
docxShading.val = shading.type || "clear";
|
|
462
|
+
return docxShading;
|
|
463
|
+
}
|
|
441
464
|
//#endregion
|
|
442
465
|
//#region src/utils/image.ts
|
|
443
466
|
const DEFAULT_MAX_IMAGE_WIDTH_PIXELS = 6.5 * 96;
|
|
@@ -525,18 +548,42 @@ function createFloatingOptions() {
|
|
|
525
548
|
}
|
|
526
549
|
/**
|
|
527
550
|
* Get image width with priority: node attrs > image meta > calculated > default
|
|
551
|
+
*
|
|
552
|
+
* Note: maxWidth constraint only applies to inline (non-floating) images.
|
|
553
|
+
* Floating images maintain their original dimensions.
|
|
528
554
|
*/
|
|
529
555
|
function getImageWidth(node, imageMeta, maxWidth) {
|
|
530
|
-
if (node.attrs?.width !== void 0 && node.attrs?.width !== null)
|
|
556
|
+
if (node.attrs?.width !== void 0 && node.attrs?.width !== null) {
|
|
557
|
+
const requestedWidth = node.attrs.width;
|
|
558
|
+
if (!node.attrs.floating && maxWidth) {
|
|
559
|
+
const maxWidthPixels = maxWidth !== void 0 ? convertMeasureToPixels(maxWidth) : void 0;
|
|
560
|
+
if (maxWidthPixels && requestedWidth > maxWidthPixels) return maxWidthPixels;
|
|
561
|
+
}
|
|
562
|
+
return requestedWidth;
|
|
563
|
+
}
|
|
531
564
|
const maxWidthPixels = maxWidth !== void 0 ? convertMeasureToPixels(maxWidth) : void 0;
|
|
532
565
|
if (imageMeta?.width && imageMeta?.height) return calculateDisplaySize(imageMeta, maxWidthPixels).width;
|
|
533
566
|
return maxWidthPixels || DEFAULT_MAX_IMAGE_WIDTH_PIXELS;
|
|
534
567
|
}
|
|
535
568
|
/**
|
|
536
569
|
* Get image height with priority: node attrs > image meta > calculated > default
|
|
570
|
+
*
|
|
571
|
+
* Note: maxWidth constraint only applies to inline (non-floating) images.
|
|
572
|
+
* Floating images maintain their original dimensions and aspect ratio.
|
|
537
573
|
*/
|
|
538
574
|
function getImageHeight(node, width, imageMeta, maxWidth) {
|
|
539
|
-
if (node.attrs?.height !== void 0 && node.attrs?.height !== null)
|
|
575
|
+
if (node.attrs?.height !== void 0 && node.attrs?.height !== null) {
|
|
576
|
+
const requestedHeight = node.attrs.height;
|
|
577
|
+
if (!node.attrs.floating && maxWidth && node.attrs?.width) {
|
|
578
|
+
const maxWidthPixels = maxWidth !== void 0 ? convertMeasureToPixels(maxWidth) : void 0;
|
|
579
|
+
const requestedWidth = node.attrs.width;
|
|
580
|
+
if (maxWidthPixels && requestedWidth > maxWidthPixels) {
|
|
581
|
+
const scaleFactor = maxWidthPixels / requestedWidth;
|
|
582
|
+
return Math.round(requestedHeight * scaleFactor);
|
|
583
|
+
}
|
|
584
|
+
}
|
|
585
|
+
return requestedHeight;
|
|
586
|
+
}
|
|
540
587
|
const maxWidthPixels = maxWidth !== void 0 ? convertMeasureToPixels(maxWidth) : void 0;
|
|
541
588
|
if (imageMeta?.width && imageMeta?.height) return calculateDisplaySize(imageMeta, maxWidthPixels).height;
|
|
542
589
|
return Math.round(width * .75);
|
|
@@ -576,52 +623,27 @@ async function getImageDataAndMeta(url) {
|
|
|
576
623
|
*/
|
|
577
624
|
const applyParagraphStyleAttributes = (options, attrs) => {
|
|
578
625
|
if (!attrs) return options;
|
|
579
|
-
|
|
580
|
-
if (attrs.indentLeft || attrs.indentRight || attrs.indentFirstLine) result = {
|
|
581
|
-
...
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
...attrs.indentRight && { right: convertPixelsToTwip(convertCssLengthToPixels(attrs.indentRight)) },
|
|
585
|
-
...attrs.indentFirstLine && { firstLine: convertPixelsToTwip(convertCssLengthToPixels(attrs.indentFirstLine)) }
|
|
586
|
-
}
|
|
626
|
+
const result = { ...options };
|
|
627
|
+
if (attrs.indentLeft || attrs.indentRight || attrs.indentFirstLine) result.indent = {
|
|
628
|
+
...attrs.indentLeft && { left: convertPixelsToTwip(convertCssLengthToPixels(attrs.indentLeft)) },
|
|
629
|
+
...attrs.indentRight && { right: convertPixelsToTwip(convertCssLengthToPixels(attrs.indentRight)) },
|
|
630
|
+
...attrs.indentFirstLine && { firstLine: convertPixelsToTwip(convertCssLengthToPixels(attrs.indentFirstLine)) }
|
|
587
631
|
};
|
|
588
|
-
if (attrs.spacingBefore || attrs.spacingAfter) result = {
|
|
589
|
-
...
|
|
590
|
-
|
|
591
|
-
...attrs.spacingBefore && { before: convertPixelsToTwip(convertCssLengthToPixels(attrs.spacingBefore)) },
|
|
592
|
-
...attrs.spacingAfter && { after: convertPixelsToTwip(convertCssLengthToPixels(attrs.spacingAfter)) }
|
|
593
|
-
}
|
|
632
|
+
if (attrs.spacingBefore || attrs.spacingAfter) result.spacing = {
|
|
633
|
+
...attrs.spacingBefore && { before: convertPixelsToTwip(convertCssLengthToPixels(attrs.spacingBefore)) },
|
|
634
|
+
...attrs.spacingAfter && { after: convertPixelsToTwip(convertCssLengthToPixels(attrs.spacingAfter)) }
|
|
594
635
|
};
|
|
595
|
-
if (attrs.textAlign) result =
|
|
596
|
-
|
|
597
|
-
|
|
636
|
+
if (attrs.textAlign) result.alignment = TEXT_ALIGN_MAP.tiptapToDocx[attrs.textAlign];
|
|
637
|
+
if (attrs.shading) result.shading = convertShading(attrs.shading);
|
|
638
|
+
if (attrs.borderTop || attrs.borderBottom || attrs.borderLeft || attrs.borderRight) result.border = {
|
|
639
|
+
...attrs.borderTop && { top: convertBorder(attrs.borderTop) },
|
|
640
|
+
...attrs.borderBottom && { bottom: convertBorder(attrs.borderBottom) },
|
|
641
|
+
...attrs.borderLeft && { left: convertBorder(attrs.borderLeft) },
|
|
642
|
+
...attrs.borderRight && { right: convertBorder(attrs.borderRight) }
|
|
598
643
|
};
|
|
599
644
|
return result;
|
|
600
645
|
};
|
|
601
646
|
//#endregion
|
|
602
|
-
//#region src/utils/table.ts
|
|
603
|
-
/**
|
|
604
|
-
* Convert TipTap border to DOCX border format
|
|
605
|
-
*
|
|
606
|
-
* @param border - TipTap table cell border definition
|
|
607
|
-
* @returns DOCX border options or undefined if no border
|
|
608
|
-
*/
|
|
609
|
-
function convertBorder(border) {
|
|
610
|
-
if (!border) return void 0;
|
|
611
|
-
const docxStyle = border.style ? {
|
|
612
|
-
solid: "single",
|
|
613
|
-
dashed: "dashed",
|
|
614
|
-
dotted: "dotted",
|
|
615
|
-
double: "double",
|
|
616
|
-
none: "none"
|
|
617
|
-
}[border.style] || "single" : "single";
|
|
618
|
-
return {
|
|
619
|
-
color: border.color?.replace("#", "") || "auto",
|
|
620
|
-
size: border.width ? border.width * 6 : 4,
|
|
621
|
-
style: docxStyle
|
|
622
|
-
};
|
|
623
|
-
}
|
|
624
|
-
//#endregion
|
|
625
647
|
//#region src/converters/text.ts
|
|
626
648
|
/**
|
|
627
649
|
* Convert TipTap text node to DOCX TextRun or ExternalHyperlink
|
|
@@ -909,13 +931,16 @@ async function convertTableCell(node, params) {
|
|
|
909
931
|
}
|
|
910
932
|
if (node.attrs?.backgroundColor) cellOptions.shading = { fill: node.attrs.backgroundColor.replace("#", "") };
|
|
911
933
|
if (node.attrs?.verticalAlign) cellOptions.verticalAlign = node.attrs.verticalAlign === "middle" ? "center" : node.attrs.verticalAlign;
|
|
912
|
-
const borders = {
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
if (
|
|
934
|
+
const borders = {};
|
|
935
|
+
const top = convertBorder(node.attrs?.borderTop);
|
|
936
|
+
if (top) borders.top = top;
|
|
937
|
+
const bottom = convertBorder(node.attrs?.borderBottom);
|
|
938
|
+
if (bottom) borders.bottom = bottom;
|
|
939
|
+
const left = convertBorder(node.attrs?.borderLeft);
|
|
940
|
+
if (left) borders.left = left;
|
|
941
|
+
const right = convertBorder(node.attrs?.borderRight);
|
|
942
|
+
if (right) borders.right = right;
|
|
943
|
+
if (Object.keys(borders).length > 0) cellOptions.borders = borders;
|
|
919
944
|
return new TableCell(cellOptions);
|
|
920
945
|
}
|
|
921
946
|
//#endregion
|
|
@@ -949,13 +974,16 @@ async function convertTableHeader(node, params) {
|
|
|
949
974
|
}
|
|
950
975
|
if (node.attrs?.backgroundColor) headerCellOptions.shading = { fill: node.attrs.backgroundColor.replace("#", "") };
|
|
951
976
|
if (node.attrs?.verticalAlign) headerCellOptions.verticalAlign = node.attrs.verticalAlign === "middle" ? "center" : node.attrs.verticalAlign;
|
|
952
|
-
const borders = {
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
if (
|
|
977
|
+
const borders = {};
|
|
978
|
+
const top = convertBorder(node.attrs?.borderTop);
|
|
979
|
+
if (top) borders.top = top;
|
|
980
|
+
const bottom = convertBorder(node.attrs?.borderBottom);
|
|
981
|
+
if (bottom) borders.bottom = bottom;
|
|
982
|
+
const left = convertBorder(node.attrs?.borderLeft);
|
|
983
|
+
if (left) borders.left = left;
|
|
984
|
+
const right = convertBorder(node.attrs?.borderRight);
|
|
985
|
+
if (right) borders.right = right;
|
|
986
|
+
if (Object.keys(borders).length > 0) headerCellOptions.borders = borders;
|
|
959
987
|
return new TableCell(headerCellOptions);
|
|
960
988
|
}
|
|
961
989
|
//#endregion
|
|
@@ -1016,6 +1044,7 @@ async function convertTable(node, params) {
|
|
|
1016
1044
|
const { options } = params;
|
|
1017
1045
|
let tableOptions = {
|
|
1018
1046
|
rows: await Promise.all((node.content || []).map((row) => convertTableRow(row, params))),
|
|
1047
|
+
...options?.style?.id && { style: options.style.id },
|
|
1019
1048
|
...options?.run
|
|
1020
1049
|
};
|
|
1021
1050
|
tableOptions = applyTableMargins(tableOptions, node);
|
|
@@ -1239,11 +1268,13 @@ async function generateDOCX(docJson, options) {
|
|
|
1239
1268
|
* Convert document content to DOCX elements
|
|
1240
1269
|
*/
|
|
1241
1270
|
async function convertDocument(node, params) {
|
|
1242
|
-
|
|
1243
|
-
if (!node || !Array.isArray(node.content)) return elements;
|
|
1271
|
+
if (!node || !Array.isArray(node.content)) return [];
|
|
1244
1272
|
const effectiveContentWidth = calculateEffectiveContentWidth(params.options);
|
|
1245
|
-
|
|
1246
|
-
|
|
1273
|
+
const convertedElements = await Promise.all(node.content.map((childNode) => convertNode(childNode, params.options, effectiveContentWidth)));
|
|
1274
|
+
const elements = [];
|
|
1275
|
+
for (let i = 0; i < convertedElements.length; i++) {
|
|
1276
|
+
const element = convertedElements[i];
|
|
1277
|
+
const childNode = node.content[i];
|
|
1247
1278
|
if (Array.isArray(element)) elements.push(...element);
|
|
1248
1279
|
else if (element) {
|
|
1249
1280
|
elements.push(element);
|
|
@@ -1267,10 +1298,16 @@ async function convertNode(node, options, effectiveContentWidth) {
|
|
|
1267
1298
|
if (Array.isArray(dataResult)) {
|
|
1268
1299
|
const styleId = getStyleIdByNodeType(node.type, options);
|
|
1269
1300
|
return dataResult.map((paragraphOptions) => {
|
|
1301
|
+
if (!styleId) return new Paragraph(paragraphOptions);
|
|
1270
1302
|
return new Paragraph(applyStyleReference(paragraphOptions, styleId));
|
|
1271
1303
|
});
|
|
1272
1304
|
}
|
|
1273
|
-
|
|
1305
|
+
let styleId = getStyleIdByNodeType(node.type, options);
|
|
1306
|
+
if (!styleId && node.type === "paragraph" && node.content) {
|
|
1307
|
+
if (node.content.length > 0 && node.content.every((child) => child.type === "image")) styleId = options.image?.style?.id;
|
|
1308
|
+
}
|
|
1309
|
+
if (!styleId) return createDOCXObject(dataResult);
|
|
1310
|
+
return createDOCXObject(applyStyleReference(dataResult, styleId));
|
|
1274
1311
|
}
|
|
1275
1312
|
/**
|
|
1276
1313
|
* Layer 1: Data Transformation
|
|
@@ -1289,11 +1326,11 @@ async function convertNodeData(node, options, effectiveContentWidth) {
|
|
|
1289
1326
|
case "heading": return convertHeading(node);
|
|
1290
1327
|
case "blockquote": return convertBlockquote(node);
|
|
1291
1328
|
case "codeBlock": return convertCodeBlock(node);
|
|
1292
|
-
case "image": return { children: [await convertImage(node, {
|
|
1329
|
+
case "image": return applyStyleReference({ children: [await convertImage(node, {
|
|
1293
1330
|
maxWidth: effectiveContentWidth,
|
|
1294
1331
|
options: options.image?.run,
|
|
1295
1332
|
handler: options.image?.handler
|
|
1296
|
-
})] };
|
|
1333
|
+
})] }, getStyleIdByNodeType("image", options));
|
|
1297
1334
|
case "table": return await convertTable(node, { options: options.table });
|
|
1298
1335
|
case "bulletList": return await convertList(node, { listType: "bullet" });
|
|
1299
1336
|
case "orderedList": return await convertList(node, { listType: "ordered" });
|
|
@@ -1414,4 +1451,4 @@ function createDOCXObject(options) {
|
|
|
1414
1451
|
return new Paragraph(options);
|
|
1415
1452
|
}
|
|
1416
1453
|
//#endregion
|
|
1417
|
-
export { CHECKBOX_SYMBOLS, COLOR_NAME_TO_HEX, DEFAULT_CODE_FONT, DOCX_DPI, DOCX_STYLE_NAMES, EMUS_PER_INCH, HALF_POINTS_PER_PIXEL, PAGE_DIMENSIONS, PIXELS_PER_HALF_POINT, TEXT_ALIGN_MAP, TWIPS_PER_INCH, applyParagraphStyleAttributes, applyTableMargins, calculateEffectiveContentWidth, convertBlockquote, convertBorder, convertBulletList, convertCodeBlock, convertColorToHex, convertCssLengthToPixels, convertDetailsSummary, convertDocument, convertEmuStringToPixels, convertEmuToPixels, convertHardBreak, convertHeading, convertHorizontalRule, convertImage, convertList, convertListItem, convertMeasureToInches, convertMeasureToPixels, convertNode, convertOrderedList, convertParagraph, convertPixelsToEmu, convertPixelsToTwip, convertTable, convertTableCell, convertTableHeader, convertTableRow, convertTaskItem, convertTaskList, convertText, convertTextNodes, convertToDocxImageType, convertTwipToCssString, convertTwipToPixels, createFloatingOptions, createStringValidator, findChild, findDeepChild, findDeepChildren, generateDOCX, getImageDataAndMeta, getImageHeight, getImageTypeFromSrc, getImageWidth, normalizeHexColor, parseTwipAttr };
|
|
1454
|
+
export { CHECKBOX_SYMBOLS, COLOR_NAME_TO_HEX, DEFAULT_CODE_FONT, DOCX_DPI, DOCX_STYLE_NAMES, EMUS_PER_INCH, HALF_POINTS_PER_PIXEL, PAGE_DIMENSIONS, PIXELS_PER_HALF_POINT, TEXT_ALIGN_MAP, TWIPS_PER_INCH, applyParagraphStyleAttributes, applyTableMargins, calculateEffectiveContentWidth, convertBlockquote, convertBorder, convertBulletList, convertCodeBlock, convertColorToHex, convertCssLengthToPixels, convertDetailsSummary, convertDocument, convertEmuStringToPixels, convertEmuToPixels, convertHardBreak, convertHeading, convertHorizontalRule, convertImage, convertList, convertListItem, convertMeasureToInches, convertMeasureToPixels, convertNode, convertOrderedList, convertParagraph, convertPixelsToEmu, convertPixelsToTwip, convertShading, convertTable, convertTableCell, convertTableHeader, convertTableRow, convertTaskItem, convertTaskList, convertText, convertTextNodes, convertToDocxImageType, convertTwipToCssString, convertTwipToPixels, createFloatingOptions, createStringValidator, findChild, findDeepChild, findDeepChildren, generateDOCX, getImageDataAndMeta, getImageHeight, getImageTypeFromSrc, getImageWidth, normalizeHexColor, parseTwipAttr };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@docen/export-docx",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.13",
|
|
4
4
|
"description": "A powerful TipTap/ProseMirror extension that converts editor content to Microsoft Word DOCX format",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"converter",
|
|
@@ -54,9 +54,9 @@
|
|
|
54
54
|
"ofetch": "1.5.1"
|
|
55
55
|
},
|
|
56
56
|
"devDependencies": {
|
|
57
|
-
"@tiptap/core": "3.20.
|
|
58
|
-
"@docen/
|
|
59
|
-
"@docen/
|
|
57
|
+
"@tiptap/core": "3.20.0",
|
|
58
|
+
"@docen/extensions": "0.0.13",
|
|
59
|
+
"@docen/utils": "0.0.13"
|
|
60
60
|
},
|
|
61
61
|
"scripts": {
|
|
62
62
|
"dev": "basis build --stub",
|