@docen/export-docx 0.0.8

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 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,271 @@
1
+ # @docen/export-docx
2
+
3
+ ![npm version](https://img.shields.io/npm/v/@docen/export-docx)
4
+ ![npm downloads](https://img.shields.io/npm/dw/@docen/export-docx)
5
+ ![npm license](https://img.shields.io/npm/l/@docen/export-docx)
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) &copy; [Demo Macro](https://imst.xyz/)
package/dist/docx.cjs ADDED
@@ -0,0 +1 @@
1
+ "use strict";const docx=require("docx");Object.prototype.hasOwnProperty.call(docx,"__proto__")&&!Object.prototype.hasOwnProperty.call(exports,"__proto__")&&Object.defineProperty(exports,"__proto__",{enumerable:!0,value:docx.__proto__}),Object.keys(docx).forEach(function(t){t!=="default"&&!Object.prototype.hasOwnProperty.call(exports,t)&&(exports[t]=docx[t])});
@@ -0,0 +1 @@
1
+ export * from 'docx';
@@ -0,0 +1 @@
1
+ export * from 'docx';
package/dist/docx.d.ts ADDED
@@ -0,0 +1 @@
1
+ export * from 'docx';
package/dist/docx.mjs ADDED
@@ -0,0 +1 @@
1
+ export*from"docx";
package/dist/index.cjs ADDED
@@ -0,0 +1 @@
1
+ "use strict";const docx=require("docx"),imageMeta=require("image-meta"),ofetch=require("ofetch"),DOCX_DPI=96,a$1=/^([\d.]+)(px|pt|em|rem|%|)?$/,T=/^([\d.]+)(in|mm|cm|pt|pc|pi)$/,_={px:1,pt:1.333,em:16,rem:16,"%":.16},f={in:1,mm:1/25.4,cm:1/2.54,pt:1/72,pc:1/6,pi:1/6},convertTwipToPixels=t=>Math.round(t*96/1440),convertCssLengthToPixels=t=>{if(!t)return 0;t=t.trim();const r=t.match(a$1);if(!r)return 0;const n=parseFloat(r[1]);if(isNaN(n))return 0;const c=r[2]||"px",o=_[c]??1;return Math.round(n*o)},convertPixelsToTwip=t=>Math.round(t*15),convertMeasureToInches=t=>{if(typeof t=="number")return t;const r=t.match(T);if(r){const c=parseFloat(r[1]),o=r[2],i=f[o];return i!==void 0?c*i:c}const n=parseFloat(t);return isNaN(n)?6.5:n},convertMeasureToPixels=t=>{if(typeof t=="number")return t;const r=convertMeasureToInches(t);return Math.round(r*96)},calculateEffectiveContentWidth=t=>{if(!t?.sections?.length)return convertTwipToPixels(11906-1440*2);const r=t.sections[0];if(!r.properties?.page)return convertTwipToPixels(11906-1440*2);const n=r.properties.page;let c=11906;if(n.size?.width){const w=n.size.width;c=typeof w=="number"?w:Math.round(convertMeasureToInches(w)*1440)}const o=n.margin,i=o?.left?typeof o.left=="number"?o.left:Math.round(convertMeasureToInches(o.left)*1440):1440,d=o?.right?typeof o.right=="number"?o.right:Math.round(convertMeasureToInches(o.right)*1440):1440,m=c-i-d;return Math.max(convertTwipToPixels(m),96)},e={red:"#FF0000",green:"#008000",blue:"#0000FF",yellow:"#FFFF00",orange:"#FFA500",purple:"#800080",pink:"#FFC0CB",brown:"#A52A2A",black:"#000000",white:"#FFFFFF",gray:"#808080",grey:"#808080",cyan:"#00FFFF",magenta:"#FF00FF",lime:"#00FF00",navy:"#000080",teal:"#008080",maroon:"#800000",olive:"#808000",silver:"#C0C0C0",gold:"#FFD700",indigo:"#4B0082",violet:"#EE82EE"},convertColorToHex=t=>{if(t)return t.startsWith("#")?t:e[t.toLowerCase()]||t},a=6.5*96,p={jpg:"jpeg",jpeg:"jpeg",png:"png",gif:"gif",bmp:"bmp",tiff:"tiff"},u={jpg:"jpeg",jpeg:"jpeg",png:"png",gif:"gif",bmp:"bmp",tiff:"tiff"},getImageTypeFromSrc=t=>{if(t.startsWith("data:")){const r=t.match(/data:image\/(\w+);/);if(r){const n=r[1].toLowerCase();return p[n]||"png"}}else{const r=t.split(".").pop()?.toLowerCase();if(r)return u[r]||"png"}return"png"},h=(t,r=a)=>{if(!t.width||!t.height)return{width:r,height:Math.round(r*.75)};if(t.width<=r)return{width:t.width,height:t.height};const n=r/t.width;return{width:r,height:Math.round(t.height*n)}},createFloatingOptions=()=>({horizontalPosition:{relative:"page",align:"center"},verticalPosition:{relative:"page",align:"top"},lockAnchor:!0,behindDocument:!1,inFrontOfText:!1}),getImageWidth=(t,r,n)=>{if(t.attrs?.width!==void 0&&t.attrs?.width!==null)return t.attrs.width;const c=n!==void 0?convertMeasureToPixels(n):void 0;return r?.width&&r?.height?h(r,c).width:c||a},getImageHeight=(t,r,n,c)=>{if(t.attrs?.height!==void 0&&t.attrs?.height!==null)return t.attrs.height;const o=c!==void 0?convertMeasureToPixels(c):void 0;return n?.width&&n?.height?h(n,o).height:Math.round(r*.75)},getImageDataAndMeta=async t=>{try{const r=await(await ofetch.ofetch(t,{responseType:"blob"})).bytes();let n;try{n=imageMeta.imageMeta(r)}catch(c){console.warn("Failed to extract image metadata:",c),n={width:void 0,height:void 0,type:getImageTypeFromSrc(t)||"png",orientation:void 0}}return{data:r,meta:n}}catch(r){throw console.warn(`Failed to fetch image from ${t}:`,r),r}},applyParagraphStyleAttributes=(t,r)=>{if(!r)return t;let n={...t};return(r.indentLeft||r.indentRight||r.indentFirstLine)&&(n={...n,indent:{...r.indentLeft&&{left:convertPixelsToTwip(convertCssLengthToPixels(r.indentLeft))},...r.indentRight&&{right:convertPixelsToTwip(convertCssLengthToPixels(r.indentRight))},...r.indentFirstLine&&{firstLine:convertPixelsToTwip(convertCssLengthToPixels(r.indentFirstLine))}}}),(r.spacingBefore||r.spacingAfter)&&(n={...n,spacing:{...r.spacingBefore&&{before:convertPixelsToTwip(convertCssLengthToPixels(r.spacingBefore))},...r.spacingAfter&&{after:convertPixelsToTwip(convertCssLengthToPixels(r.spacingAfter))}}}),r.textAlign&&(n={...n,alignment:{left:"left",right:"right",center:"center",justify:"both"}[r.textAlign]}),n};function convertText(t){const r=t.marks?.some(g=>g.type==="bold"),n=t.marks?.some(g=>g.type==="italic"),c=t.marks?.some(g=>g.type==="underline"),o=t.marks?.some(g=>g.type==="strike"),i=t.marks?.some(g=>g.type==="code"),d=t.marks?.some(g=>g.type==="subscript"),m=t.marks?.some(g=>g.type==="superscript"),w=t.marks?.find(g=>g.type==="link"),y=t.marks?.find(g=>g.type==="textStyle"),v=t.marks?.some(g=>g.type==="highlight"),x=convertColorToHex(y?.attrs?.color),b=convertColorToHex(y?.attrs?.backgroundColor);let F;if(y?.attrs?.fontSize){const g=y.attrs.fontSize;if(g.endsWith("px")){const L=parseFloat(g);isNaN(L)||(F=Math.round(L*1.5))}}let k;i?k="Consolas":y?.attrs?.fontFamily&&(k=y.attrs.fontFamily);const A={text:t.text||"",bold:r||void 0,italics:n||void 0,underline:c?{}:void 0,strike:o||void 0,font:k,size:F,subScript:d||void 0,superScript:m||void 0,color:x,shading:b?{fill:b}:void 0,highlight:v?"yellow":void 0};return w?.attrs?.href?new docx.ExternalHyperlink({children:[new docx.TextRun({...A,style:"Hyperlink"})],link:w.attrs.href}):new docx.TextRun(A)}function convertHardBreak(t){const r={text:"",break:1};if(t)for(const n of t)switch(n.type){case"bold":r.bold=!0;break;case"italic":r.italics=!0;break;case"underline":r.underline={};break;case"strike":r.strike=!0;break;case"textStyle":n.attrs?.color&&(r.color=n.attrs.color);break}return new docx.TextRun(r)}const convertTextNodes=(t=[])=>t.flatMap(r=>r.type==="text"?[convertText(r)]:r.type==="hardBreak"?[convertHardBreak(r.marks)]:[]);async function convertImage(t,r){const n=y=>{switch(y){case"jpeg":case"jpg":return"jpg";case"png":return"png";case"gif":return"gif";case"bmp":return"bmp"}switch(getImageTypeFromSrc(t.attrs?.src||"")){case"jpeg":return"jpg";case"png":return"png";case"gif":return"gif";case"bmp":return"bmp";default:return"png"}};let c,o;try{const y=t.attrs?.src||"";if(y.startsWith("http")){const v=await getImageDataAndMeta(y);c=v.data,o=v.meta}else if(y.startsWith("data:")){const v=y.split(",")[1];if(!v)throw new Error("Invalid data URL: missing base64 data");const x=atob(v);c=Uint8Array.from(x,b=>b.charCodeAt(0));try{o=imageMeta.imageMeta(c)}catch{o={type:"png",width:void 0,height:void 0,orientation:void 0}}}else throw new Error(`Unsupported image source format: ${y.substring(0,20)}...`)}catch(y){return console.warn("Failed to process image:",y),new docx.ImageRun({type:"png",data:new Uint8Array(0),transformation:{width:100,height:100},altText:{name:t.attrs?.alt||"Failed to load image"}})}const i=getImageWidth(t,o,r?.maxWidth),d=getImageHeight(t,i,o,r?.maxWidth),m={width:i,height:d};t.attrs?.rotation!==void 0&&(m.rotation=t.attrs.rotation);const w={type:n(o.type),data:c,transformation:m,altText:{name:t.attrs?.alt||"",description:void 0,title:t.attrs?.title||void 0},...t.attrs?.floating&&{floating:t.attrs.floating},...t.attrs?.outline&&{outline:t.attrs.outline}};return new docx.ImageRun(w)}async function convertParagraph(t,r){const{options:n,image:c}=r||{},o=[];for(const d of t.content||[])if(d.type==="text")o.push(convertText(d));else if(d.type==="hardBreak")o.push(convertHardBreak(d.marks));else if(d.type==="image"){const m=await convertImage(d,{maxWidth:c?.maxWidth});o.push(m)}let i={children:o};return n&&(i={...i,...n}),t.attrs&&(i=applyParagraphStyleAttributes(i,t.attrs)),new docx.Paragraph(i)}function convertHeading(t){const r=t?.attrs?.level,n=convertTextNodes(t.content).filter(i=>i!==void 0),c={1:docx.HeadingLevel.HEADING_1,2:docx.HeadingLevel.HEADING_2,3:docx.HeadingLevel.HEADING_3,4:docx.HeadingLevel.HEADING_4,5:docx.HeadingLevel.HEADING_5,6:docx.HeadingLevel.HEADING_6};let o={children:n,heading:c[r]};return t.attrs&&(o=applyParagraphStyleAttributes(o,t.attrs)),new docx.Paragraph(o)}function convertBlockquote(t){return t.content?t.content.map(r=>{if(r.type==="paragraph"){const n=r.content?.flatMap(c=>c.type==="text"?convertText(c):c.type==="hardBreak"?convertHardBreak(c.marks):[])||[];return new docx.Paragraph({children:n,indent:{left:720},border:{left:{style:"single"}}})}return new docx.Paragraph({})}):[]}function s$1(t){if(!t)return;const r={solid:"single",dashed:"dashed",dotted:"dotted",double:"double",none:"none"},n=t.style&&r[t.style]||"single",c=t.color?.replace("#","")||"auto",o=t.width?t.width*6:4;return{color:c,size:o,style:n}}async function convertTableCell(t,r){const{options:n}=r;let c=n?.cell?.paragraph??n?.row?.paragraph??{};n?.style&&(c={...c,style:n.style.id});const o={children:await Promise.all((t.content||[]).map(d=>convertParagraph(d,{options:c}))),...n?.cell?.run};if(t.attrs?.colSpan&&t.attrs.colSpan>1&&(o.columnSpan=t.attrs.colSpan),t.attrs?.rowSpan&&t.attrs.rowSpan>1&&(o.rowSpan=t.attrs.rowSpan),t.attrs?.colWidth!==null&&t.attrs?.colWidth!==void 0){const d=Array.isArray(t.attrs.colWidth)?t.attrs.colWidth[0]:t.attrs.colWidth;if(d&&d>0){const m=Math.round(d*15);o.width={size:m,type:"dxa"}}}if(t.attrs?.backgroundColor){const d=t.attrs.backgroundColor.replace("#","");o.shading={fill:d}}if(t.attrs?.verticalAlign){const d=t.attrs.verticalAlign==="middle"?"center":t.attrs.verticalAlign;o.verticalAlign=d}const i={top:s$1(t.attrs?.borderTop),bottom:s$1(t.attrs?.borderBottom),left:s$1(t.attrs?.borderLeft),right:s$1(t.attrs?.borderRight)};return(i.top||i.bottom||i.left||i.right)&&(o.borders=i),new docx.TableCell(o)}function l(t){if(!t)return;const r={solid:"single",dashed:"dashed",dotted:"dotted",double:"double",none:"none"},n=t.style&&r[t.style]||"single",c=t.color?.replace("#","")||"auto",o=t.width?t.width*6:4;return{color:c,size:o,style:n}}async function convertTableHeader(t,r){const{options:n}=r;let c=n?.header?.paragraph??n?.cell?.paragraph??n?.row?.paragraph??{};n?.style&&(c={...c,style:n.style.id});const o={children:await Promise.all((t.content||[]).map(d=>convertParagraph(d,{options:c}))),...n?.header?.run};if(t.attrs?.colSpan&&t.attrs.colSpan>1&&(o.columnSpan=t.attrs.colSpan),t.attrs?.rowSpan&&t.attrs.rowSpan>1&&(o.rowSpan=t.attrs.rowSpan),t.attrs?.colWidth!==null&&t.attrs?.colWidth!==void 0){const d=Array.isArray(t.attrs.colWidth)?t.attrs.colWidth[0]:t.attrs.colWidth;if(d&&d>0){const m=Math.round(d*15);o.width={size:m,type:"dxa"}}}if(t.attrs?.backgroundColor){const d=t.attrs.backgroundColor.replace("#","");o.shading={fill:d}}if(t.attrs?.verticalAlign){const d=t.attrs.verticalAlign==="middle"?"center":t.attrs.verticalAlign;o.verticalAlign=d}const i={top:l(t.attrs?.borderTop),bottom:l(t.attrs?.borderBottom),left:l(t.attrs?.borderLeft),right:l(t.attrs?.borderRight)};return(i.top||i.bottom||i.left||i.right)&&(o.borders=i),new docx.TableCell(o)}async function convertTableRow(t,r){const{options:n}=r,c=n?.row,o={children:(await Promise.all((t.content||[]).map(async i=>i.type==="tableCell"?await convertTableCell(i,r):i.type==="tableHeader"?await convertTableHeader(i,r):null))).filter(i=>i!==void 0),...c};if(t.attrs?.rowHeight){const i=convertCssLengthToPixels(t.attrs.rowHeight),d=convertPixelsToTwip(i);d>0&&(o.height={rule:"atLeast",value:d})}return new docx.TableRow(o)}const s=(t,r)=>{const n={top:r.attrs?.marginTop??void 0,bottom:r.attrs?.marginBottom??void 0,left:r.attrs?.marginLeft??void 0,right:r.attrs?.marginRight??void 0};return n.top||n.bottom||n.left||n.right?{...t,margins:n}:t};async function convertTable(t,r){const{options:n}=r;let c={rows:await Promise.all((t.content||[]).map(o=>convertTableRow(o,r))),...n?.run};return c=s(c,t),new docx.Table(c)}function convertCodeBlock(t){const r=t.content?.map(n=>n.text||"").join("")||"";return new docx.Paragraph({children:[new docx.TextRun({text:r,font:"Consolas"})]})}async function convertListItem(t,r){if(!t.content||t.content.length===0)return new docx.Paragraph({});const n=t.content[0];return n.type==="paragraph"?await convertParagraph(n,{options:r.options}):new docx.Paragraph({})}function convertBulletList(){return{numbering:{reference:"bullet-list",level:0}}}function convertOrderedList(t){const r=t.attrs?.start||1;return{numbering:{reference:"ordered-list",level:0},start:r}}async function convertList(t,r){const{listType:n}=r;if(!t.content)return[];const c=[],o=n==="bullet"?convertBulletList():convertOrderedList(t);let i=o.numbering.reference;n==="ordered"&&o.start&&o.start!==1&&(i=`ordered-list-start-${o.start}`);for(const d of t.content)if(d.type==="listItem"){const m=await convertListItem(d,{options:{numbering:{reference:i,level:0}}});c.push(m)}return c}function convertTaskItem(t){if(!t.content||t.content.length===0)return new docx.Paragraph({});const r=t.content[0];if(r.type==="paragraph"){const n=t.attrs?.checked?"\u2611 ":"\u2610 ",c=r.content?.flatMap(i=>i.type==="text"?convertText(i):i.type==="hardBreak"?convertHardBreak(i.marks):[])||[],o=new docx.TextRun({text:n});return new docx.Paragraph({children:[o,...c]})}return new docx.Paragraph({})}function convertTaskList(t){return!t.content||t.content.length===0?[]:t.content.filter(r=>r.type==="taskItem").map(r=>convertTaskItem(r))}function convertHorizontalRule(t,r){const n={children:[new docx.PageBreak]};return new docx.Paragraph({...n,...r.options?.paragraph})}async function convertDetails(t,r){if(!t.content)return[];const n=[];let c,o;for(const i of t.content)i.type==="detailsSummary"?c=i:i.type==="detailsContent"&&(o=i);if(c?.content){const i=convertTextNodes(c.content).filter(m=>m!==void 0),d=new docx.Paragraph({children:i,...r.options?.summary?.paragraph});n.push(d)}if(o?.content){const i=calculateEffectiveContentWidth(r.exportOptions);for(const d of o.content){const m=await convertNode(d,r.exportOptions,i);Array.isArray(m)?n.push(...m):m&&n.push(m)}}return n}async function generateDOCX(t,r){const{title:n,subject:c,creator:o,keywords:i,description:d,lastModifiedBy:m,revision:w,styles:y,tableOfContents:v,sections:x,fonts:b,hyphenation:F,compatibility:k,customProperties:A,evenAndOddHeaderAndFooters:g,defaultTabStop:L,outputType:M}=r,S=await convertDocumentContent(t,r),P=v?new docx.TableOfContents(v.title,{...v.run}):null,B=Z(t),C=[];r.image?.style&&C.push(r.image.style),r.table?.style&&C.push(r.table.style);const R=y?{...y,...C.length>0&&{paragraphStyles:[...y.paragraphStyles||[],...C]}}:{},W={sections:x?x.map((E,H)=>{const I=[];return H===0&&P&&I.push(P),H===0&&I.push(...S),{...E,...I.length>0?{children:I}:{}}}):[{children:P?[P,...S]:S}],title:n||"Document",subject:c||"",creator:o||"",keywords:i||"",description:d||"",lastModifiedBy:m||"",revision:w||1,styles:R,numbering:B,...b&&b.length>0&&{fonts:b},...F&&{hyphenation:F},...k&&{compatibility:k},...A&&A.length>0&&{customProperties:A},...g!==void 0&&{evenAndOddHeaderAndFooters:g},...L!==void 0&&{defaultTabStop:L}},D=new docx.Document(W);return docx.Packer.pack(D,M||"arraybuffer")}async function convertDocumentContent(t,r){const n=[];if(!t||!Array.isArray(t.content))return n;const c=calculateEffectiveContentWidth(r);for(const o of t.content){const i=await convertNode(o,r,c);Array.isArray(i)?n.push(...i):i&&(n.push(i),o.type==="table"&&n.length>=2&&n[n.length-2]instanceof docx.Table&&n.push(new docx.Paragraph({})))}return n}async function convertNode(t,r,n){if(!t||!t.type)return null;switch(t.type){case"paragraph":return await convertParagraph(t,{image:{maxWidth:n}});case"heading":return convertHeading(t);case"blockquote":return convertBlockquote(t);case"codeBlock":return convertCodeBlock(t);case"image":const c=await convertImage(t,{maxWidth:n}),o=r.image?.style?{children:[c],style:r.image.style.id}:{children:[c]};return new docx.Paragraph(o);case"table":return await convertTable(t,{options:r.table});case"bulletList":return await convertList(t,{listType:"bullet"});case"orderedList":return await convertList(t,{listType:"ordered"});case"taskList":return convertTaskList(t);case"listItem":return convertListItem(t,{options:void 0});case"taskItem":return convertTaskItem(t);case"hardBreak":return new docx.Paragraph({children:[convertHardBreak()]});case"horizontalRule":return convertHorizontalRule(t,{options:r.horizontalRule});case"details":return await convertDetails(t,{options:r.details,exportOptions:r});default:return new docx.Paragraph({children:[new docx.TextRun({text:`[Unsupported: ${t.type}]`})]})}}function Z(t){const r=new Set;function n(i){if(i.type==="orderedList"&&i.attrs?.start&&r.add(i.attrs.start),i.content)for(const d of i.content)n(d)}n(t);const c=[{level:0,format:docx.LevelFormat.BULLET,text:"\u2022",alignment:docx.AlignmentType.START,style:{paragraph:{indent:{left:docx.convertInchesToTwip(.5),hanging:docx.convertInchesToTwip(.25)}}}},{level:0,format:docx.LevelFormat.DECIMAL,text:"%1.",alignment:docx.AlignmentType.START,style:{paragraph:{indent:{left:docx.convertInchesToTwip(.5),hanging:docx.convertInchesToTwip(.25)}}}}],o=[{reference:"bullet-list",levels:[c[0]]},{reference:"ordered-list",levels:[c[1]]}];for(const i of r)i!==1&&o.push({reference:`ordered-list-start-${i}`,levels:[{level:0,format:docx.LevelFormat.DECIMAL,text:"%1.",alignment:docx.AlignmentType.START,start:i,style:{paragraph:{indent:{left:docx.convertInchesToTwip(.5),hanging:docx.convertInchesToTwip(.25)}}}}]});return{config:o}}exports.DOCX_DPI=DOCX_DPI,exports.applyParagraphStyleAttributes=applyParagraphStyleAttributes,exports.calculateEffectiveContentWidth=calculateEffectiveContentWidth,exports.convertBlockquote=convertBlockquote,exports.convertBulletList=convertBulletList,exports.convertCodeBlock=convertCodeBlock,exports.convertColorToHex=convertColorToHex,exports.convertCssLengthToPixels=convertCssLengthToPixels,exports.convertDetails=convertDetails,exports.convertDocumentContent=convertDocumentContent,exports.convertHardBreak=convertHardBreak,exports.convertHeading=convertHeading,exports.convertHorizontalRule=convertHorizontalRule,exports.convertImage=convertImage,exports.convertList=convertList,exports.convertListItem=convertListItem,exports.convertMeasureToInches=convertMeasureToInches,exports.convertMeasureToPixels=convertMeasureToPixels,exports.convertNode=convertNode,exports.convertOrderedList=convertOrderedList,exports.convertParagraph=convertParagraph,exports.convertPixelsToTwip=convertPixelsToTwip,exports.convertTable=convertTable,exports.convertTableCell=convertTableCell,exports.convertTableHeader=convertTableHeader,exports.convertTableRow=convertTableRow,exports.convertTaskItem=convertTaskItem,exports.convertTaskList=convertTaskList,exports.convertText=convertText,exports.convertTextNodes=convertTextNodes,exports.convertTwipToPixels=convertTwipToPixels,exports.createFloatingOptions=createFloatingOptions,exports.generateDOCX=generateDOCX,exports.getImageDataAndMeta=getImageDataAndMeta,exports.getImageHeight=getImageHeight,exports.getImageTypeFromSrc=getImageTypeFromSrc,exports.getImageWidth=getImageWidth;