@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/dist/index.mjs ADDED
@@ -0,0 +1 @@
1
+ import{ExternalHyperlink as At,TextRun as b,ImageRun as J,Paragraph as p,HeadingLevel as v,TableCell as K,TableRow as Tt,Table as Q,PageBreak as Ft,TableOfContents as St,Document as Ct,Packer as Lt,convertInchesToTwip as k,AlignmentType as D,LevelFormat as j}from"docx";import{imageMeta as V}from"image-meta";import{ofetch as It}from"ofetch";const Mt=96,Bt=/^([\d.]+)(px|pt|em|rem|%|)?$/,Wt=/^([\d.]+)(in|mm|cm|pt|pc|pi)$/,Ht={px:1,pt:1.333,em:16,rem:16,"%":.16},Pt={in:1,mm:1/25.4,cm:1/2.54,pt:1/72,pc:1/6,pi:1/6},B=t=>Math.round(t*96/1440),g=t=>{if(!t)return 0;t=t.trim();const e=t.match(Bt);if(!e)return 0;const r=parseFloat(e[1]);if(isNaN(r))return 0;const a=e[2]||"px",n=Ht[a]??1;return Math.round(r*n)},f=t=>Math.round(t*15),F=t=>{if(typeof t=="number")return t;const e=t.match(Wt);if(e){const a=parseFloat(e[1]),n=e[2],o=Pt[n];return o!==void 0?a*o:a}const r=parseFloat(t);return isNaN(r)?6.5:r},E=t=>{if(typeof t=="number")return t;const e=F(t);return Math.round(e*96)},R=t=>{if(!t?.sections?.length)return B(11906-1440*2);const e=t.sections[0];if(!e.properties?.page)return B(11906-1440*2);const r=e.properties.page;let a=11906;if(r.size?.width){const u=r.size.width;a=typeof u=="number"?u:Math.round(F(u)*1440)}const n=r.margin,o=n?.left?typeof n.left=="number"?n.left:Math.round(F(n.left)*1440):1440,i=n?.right?typeof n.right=="number"?n.right:Math.round(F(n.right)*1440):1440,c=a-o-i;return Math.max(B(c),96)},Dt={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"},N=t=>{if(t)return t.startsWith("#")?t:Dt[t.toLowerCase()]||t},Y=6.5*96,jt={jpg:"jpeg",jpeg:"jpeg",png:"png",gif:"gif",bmp:"bmp",tiff:"tiff"},Et={jpg:"jpeg",jpeg:"jpeg",png:"png",gif:"gif",bmp:"bmp",tiff:"tiff"},z=t=>{if(t.startsWith("data:")){const e=t.match(/data:image\/(\w+);/);if(e){const r=e[1].toLowerCase();return jt[r]||"png"}}else{const e=t.split(".").pop()?.toLowerCase();if(e)return Et[e]||"png"}return"png"},tt=(t,e=Y)=>{if(!t.width||!t.height)return{width:e,height:Math.round(e*.75)};if(t.width<=e)return{width:t.width,height:t.height};const r=e/t.width;return{width:e,height:Math.round(t.height*r)}},Rt=()=>({horizontalPosition:{relative:"page",align:"center"},verticalPosition:{relative:"page",align:"top"},lockAnchor:!0,behindDocument:!1,inFrontOfText:!1}),et=(t,e,r)=>{if(t.attrs?.width!==void 0&&t.attrs?.width!==null)return t.attrs.width;const a=r!==void 0?E(r):void 0;return e?.width&&e?.height?tt(e,a).width:a||Y},rt=(t,e,r,a)=>{if(t.attrs?.height!==void 0&&t.attrs?.height!==null)return t.attrs.height;const n=a!==void 0?E(a):void 0;return r?.width&&r?.height?tt(r,n).height:Math.round(e*.75)},nt=async t=>{try{const e=await(await It(t,{responseType:"blob"})).bytes();let r;try{r=V(e)}catch(a){console.warn("Failed to extract image metadata:",a),r={width:void 0,height:void 0,type:z(t)||"png",orientation:void 0}}return{data:e,meta:r}}catch(e){throw console.warn(`Failed to fetch image from ${t}:`,e),e}},O=(t,e)=>{if(!e)return t;let r={...t};return(e.indentLeft||e.indentRight||e.indentFirstLine)&&(r={...r,indent:{...e.indentLeft&&{left:f(g(e.indentLeft))},...e.indentRight&&{right:f(g(e.indentRight))},...e.indentFirstLine&&{firstLine:f(g(e.indentFirstLine))}}}),(e.spacingBefore||e.spacingAfter)&&(r={...r,spacing:{...e.spacingBefore&&{before:f(g(e.spacingBefore))},...e.spacingAfter&&{after:f(g(e.spacingAfter))}}}),e.textAlign&&(r={...r,alignment:{left:"left",right:"right",center:"center",justify:"both"}[e.textAlign]}),r};function S(t){const e=t.marks?.some(s=>s.type==="bold"),r=t.marks?.some(s=>s.type==="italic"),a=t.marks?.some(s=>s.type==="underline"),n=t.marks?.some(s=>s.type==="strike"),o=t.marks?.some(s=>s.type==="code"),i=t.marks?.some(s=>s.type==="subscript"),c=t.marks?.some(s=>s.type==="superscript"),u=t.marks?.find(s=>s.type==="link"),l=t.marks?.find(s=>s.type==="textStyle"),d=t.marks?.some(s=>s.type==="highlight"),m=N(l?.attrs?.color),h=N(l?.attrs?.backgroundColor);let A;if(l?.attrs?.fontSize){const s=l.attrs.fontSize;if(s.endsWith("px")){const T=parseFloat(s);isNaN(T)||(A=Math.round(T*1.5))}}let y;o?y="Consolas":l?.attrs?.fontFamily&&(y=l.attrs.fontFamily);const w={text:t.text||"",bold:e||void 0,italics:r||void 0,underline:a?{}:void 0,strike:n||void 0,font:y,size:A,subScript:i||void 0,superScript:c||void 0,color:m,shading:h?{fill:h}:void 0,highlight:d?"yellow":void 0};return u?.attrs?.href?new At({children:[new b({...w,style:"Hyperlink"})],link:u.attrs.href}):new b(w)}function x(t){const e={text:"",break:1};if(t)for(const r of t)switch(r.type){case"bold":e.bold=!0;break;case"italic":e.italics=!0;break;case"underline":e.underline={};break;case"strike":e.strike=!0;break;case"textStyle":r.attrs?.color&&(e.color=r.attrs.color);break}return new b(e)}const $=(t=[])=>t.flatMap(e=>e.type==="text"?[S(e)]:e.type==="hardBreak"?[x(e.marks)]:[]);async function _(t,e){const r=l=>{switch(l){case"jpeg":case"jpg":return"jpg";case"png":return"png";case"gif":return"gif";case"bmp":return"bmp"}switch(z(t.attrs?.src||"")){case"jpeg":return"jpg";case"png":return"png";case"gif":return"gif";case"bmp":return"bmp";default:return"png"}};let a,n;try{const l=t.attrs?.src||"";if(l.startsWith("http")){const d=await nt(l);a=d.data,n=d.meta}else if(l.startsWith("data:")){const d=l.split(",")[1];if(!d)throw new Error("Invalid data URL: missing base64 data");const m=atob(d);a=Uint8Array.from(m,h=>h.charCodeAt(0));try{n=V(a)}catch{n={type:"png",width:void 0,height:void 0,orientation:void 0}}}else throw new Error(`Unsupported image source format: ${l.substring(0,20)}...`)}catch(l){return console.warn("Failed to process image:",l),new J({type:"png",data:new Uint8Array(0),transformation:{width:100,height:100},altText:{name:t.attrs?.alt||"Failed to load image"}})}const o=et(t,n,e?.maxWidth),i=rt(t,o,n,e?.maxWidth),c={width:o,height:i};t.attrs?.rotation!==void 0&&(c.rotation=t.attrs.rotation);const u={type:r(n.type),data:a,transformation:c,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 J(u)}async function C(t,e){const{options:r,image:a}=e||{},n=[];for(const i of t.content||[])if(i.type==="text")n.push(S(i));else if(i.type==="hardBreak")n.push(x(i.marks));else if(i.type==="image"){const c=await _(i,{maxWidth:a?.maxWidth});n.push(c)}let o={children:n};return r&&(o={...o,...r}),t.attrs&&(o=O(o,t.attrs)),new p(o)}function ot(t){const e=t?.attrs?.level,r=$(t.content).filter(o=>o!==void 0),a={1:v.HEADING_1,2:v.HEADING_2,3:v.HEADING_3,4:v.HEADING_4,5:v.HEADING_5,6:v.HEADING_6};let n={children:r,heading:a[e]};return t.attrs&&(n=O(n,t.attrs)),new p(n)}function at(t){return t.content?t.content.map(e=>{if(e.type==="paragraph"){const r=e.content?.flatMap(a=>a.type==="text"?S(a):a.type==="hardBreak"?x(a.marks):[])||[];return new p({children:r,indent:{left:720},border:{left:{style:"single"}}})}return new p({})}):[]}function W(t){if(!t)return;const e={solid:"single",dashed:"dashed",dotted:"dotted",double:"double",none:"none"},r=t.style&&e[t.style]||"single",a=t.color?.replace("#","")||"auto",n=t.width?t.width*6:4;return{color:a,size:n,style:r}}async function it(t,e){const{options:r}=e;let a=r?.cell?.paragraph??r?.row?.paragraph??{};r?.style&&(a={...a,style:r.style.id});const n={children:await Promise.all((t.content||[]).map(i=>C(i,{options:a}))),...r?.cell?.run};if(t.attrs?.colSpan&&t.attrs.colSpan>1&&(n.columnSpan=t.attrs.colSpan),t.attrs?.rowSpan&&t.attrs.rowSpan>1&&(n.rowSpan=t.attrs.rowSpan),t.attrs?.colWidth!==null&&t.attrs?.colWidth!==void 0){const i=Array.isArray(t.attrs.colWidth)?t.attrs.colWidth[0]:t.attrs.colWidth;if(i&&i>0){const c=Math.round(i*15);n.width={size:c,type:"dxa"}}}if(t.attrs?.backgroundColor){const i=t.attrs.backgroundColor.replace("#","");n.shading={fill:i}}if(t.attrs?.verticalAlign){const i=t.attrs.verticalAlign==="middle"?"center":t.attrs.verticalAlign;n.verticalAlign=i}const o={top:W(t.attrs?.borderTop),bottom:W(t.attrs?.borderBottom),left:W(t.attrs?.borderLeft),right:W(t.attrs?.borderRight)};return(o.top||o.bottom||o.left||o.right)&&(n.borders=o),new K(n)}function H(t){if(!t)return;const e={solid:"single",dashed:"dashed",dotted:"dotted",double:"double",none:"none"},r=t.style&&e[t.style]||"single",a=t.color?.replace("#","")||"auto",n=t.width?t.width*6:4;return{color:a,size:n,style:r}}async function st(t,e){const{options:r}=e;let a=r?.header?.paragraph??r?.cell?.paragraph??r?.row?.paragraph??{};r?.style&&(a={...a,style:r.style.id});const n={children:await Promise.all((t.content||[]).map(i=>C(i,{options:a}))),...r?.header?.run};if(t.attrs?.colSpan&&t.attrs.colSpan>1&&(n.columnSpan=t.attrs.colSpan),t.attrs?.rowSpan&&t.attrs.rowSpan>1&&(n.rowSpan=t.attrs.rowSpan),t.attrs?.colWidth!==null&&t.attrs?.colWidth!==void 0){const i=Array.isArray(t.attrs.colWidth)?t.attrs.colWidth[0]:t.attrs.colWidth;if(i&&i>0){const c=Math.round(i*15);n.width={size:c,type:"dxa"}}}if(t.attrs?.backgroundColor){const i=t.attrs.backgroundColor.replace("#","");n.shading={fill:i}}if(t.attrs?.verticalAlign){const i=t.attrs.verticalAlign==="middle"?"center":t.attrs.verticalAlign;n.verticalAlign=i}const o={top:H(t.attrs?.borderTop),bottom:H(t.attrs?.borderBottom),left:H(t.attrs?.borderLeft),right:H(t.attrs?.borderRight)};return(o.top||o.bottom||o.left||o.right)&&(n.borders=o),new K(n)}async function ct(t,e){const{options:r}=e,a=r?.row,n={children:(await Promise.all((t.content||[]).map(async o=>o.type==="tableCell"?await it(o,e):o.type==="tableHeader"?await st(o,e):null))).filter(o=>o!==void 0),...a};if(t.attrs?.rowHeight){const o=g(t.attrs.rowHeight),i=f(o);i>0&&(n.height={rule:"atLeast",value:i})}return new Tt(n)}const Nt=(t,e)=>{const r={top:e.attrs?.marginTop??void 0,bottom:e.attrs?.marginBottom??void 0,left:e.attrs?.marginLeft??void 0,right:e.attrs?.marginRight??void 0};return r.top||r.bottom||r.left||r.right?{...t,margins:r}:t};async function lt(t,e){const{options:r}=e;let a={rows:await Promise.all((t.content||[]).map(n=>ct(n,e))),...r?.run};return a=Nt(a,t),new Q(a)}function pt(t){const e=t.content?.map(r=>r.text||"").join("")||"";return new p({children:[new b({text:e,font:"Consolas"})]})}async function G(t,e){if(!t.content||t.content.length===0)return new p({});const r=t.content[0];return r.type==="paragraph"?await C(r,{options:e.options}):new p({})}function dt(){return{numbering:{reference:"bullet-list",level:0}}}function ut(t){const e=t.attrs?.start||1;return{numbering:{reference:"ordered-list",level:0},start:e}}async function U(t,e){const{listType:r}=e;if(!t.content)return[];const a=[],n=r==="bullet"?dt():ut(t);let o=n.numbering.reference;r==="ordered"&&n.start&&n.start!==1&&(o=`ordered-list-start-${n.start}`);for(const i of t.content)if(i.type==="listItem"){const c=await G(i,{options:{numbering:{reference:o,level:0}}});a.push(c)}return a}function q(t){if(!t.content||t.content.length===0)return new p({});const e=t.content[0];if(e.type==="paragraph"){const r=t.attrs?.checked?"\u2611 ":"\u2610 ",a=e.content?.flatMap(o=>o.type==="text"?S(o):o.type==="hardBreak"?x(o.marks):[])||[],n=new b({text:r});return new p({children:[n,...a]})}return new p({})}function ht(t){return!t.content||t.content.length===0?[]:t.content.filter(e=>e.type==="taskItem").map(e=>q(e))}function gt(t,e){const r={children:[new Ft]};return new p({...r,...e.options?.paragraph})}async function ft(t,e){if(!t.content)return[];const r=[];let a,n;for(const o of t.content)o.type==="detailsSummary"?a=o:o.type==="detailsContent"&&(n=o);if(a?.content){const o=$(a.content).filter(c=>c!==void 0),i=new p({children:o,...e.options?.summary?.paragraph});r.push(i)}if(n?.content){const o=R(e.exportOptions);for(const i of n.content){const c=await X(i,e.exportOptions,o);Array.isArray(c)?r.push(...c):c&&r.push(c)}}return r}async function zt(t,e){const{title:r,subject:a,creator:n,keywords:o,description:i,lastModifiedBy:c,revision:u,styles:l,tableOfContents:d,sections:m,fonts:h,hyphenation:A,compatibility:y,customProperties:w,evenAndOddHeaderAndFooters:s,defaultTabStop:T,outputType:yt}=e,P=await mt(t,e),L=d?new St(d.title,{...d.run}):null,wt=Ot(t),I=[];e.image?.style&&I.push(e.image.style),e.table?.style&&I.push(e.table.style);const bt=l?{...l,...I.length>0&&{paragraphStyles:[...l.paragraphStyles||[],...I]}}:{},vt={sections:m?m.map((xt,Z)=>{const M=[];return Z===0&&L&&M.push(L),Z===0&&M.push(...P),{...xt,...M.length>0?{children:M}:{}}}):[{children:L?[L,...P]:P}],title:r||"Document",subject:a||"",creator:n||"",keywords:o||"",description:i||"",lastModifiedBy:c||"",revision:u||1,styles:bt,numbering:wt,...h&&h.length>0&&{fonts:h},...A&&{hyphenation:A},...y&&{compatibility:y},...w&&w.length>0&&{customProperties:w},...s!==void 0&&{evenAndOddHeaderAndFooters:s},...T!==void 0&&{defaultTabStop:T}},kt=new Ct(vt);return Lt.pack(kt,yt||"arraybuffer")}async function mt(t,e){const r=[];if(!t||!Array.isArray(t.content))return r;const a=R(e);for(const n of t.content){const o=await X(n,e,a);Array.isArray(o)?r.push(...o):o&&(r.push(o),n.type==="table"&&r.length>=2&&r[r.length-2]instanceof Q&&r.push(new p({})))}return r}async function X(t,e,r){if(!t||!t.type)return null;switch(t.type){case"paragraph":return await C(t,{image:{maxWidth:r}});case"heading":return ot(t);case"blockquote":return at(t);case"codeBlock":return pt(t);case"image":const a=await _(t,{maxWidth:r}),n=e.image?.style?{children:[a],style:e.image.style.id}:{children:[a]};return new p(n);case"table":return await lt(t,{options:e.table});case"bulletList":return await U(t,{listType:"bullet"});case"orderedList":return await U(t,{listType:"ordered"});case"taskList":return ht(t);case"listItem":return G(t,{options:void 0});case"taskItem":return q(t);case"hardBreak":return new p({children:[x()]});case"horizontalRule":return gt(t,{options:e.horizontalRule});case"details":return await ft(t,{options:e.details,exportOptions:e});default:return new p({children:[new b({text:`[Unsupported: ${t.type}]`})]})}}function Ot(t){const e=new Set;function r(o){if(o.type==="orderedList"&&o.attrs?.start&&e.add(o.attrs.start),o.content)for(const i of o.content)r(i)}r(t);const a=[{level:0,format:j.BULLET,text:"\u2022",alignment:D.START,style:{paragraph:{indent:{left:k(.5),hanging:k(.25)}}}},{level:0,format:j.DECIMAL,text:"%1.",alignment:D.START,style:{paragraph:{indent:{left:k(.5),hanging:k(.25)}}}}],n=[{reference:"bullet-list",levels:[a[0]]},{reference:"ordered-list",levels:[a[1]]}];for(const o of e)o!==1&&n.push({reference:`ordered-list-start-${o}`,levels:[{level:0,format:j.DECIMAL,text:"%1.",alignment:D.START,start:o,style:{paragraph:{indent:{left:k(.5),hanging:k(.25)}}}}]});return{config:n}}export{Mt as DOCX_DPI,O as applyParagraphStyleAttributes,R as calculateEffectiveContentWidth,at as convertBlockquote,dt as convertBulletList,pt as convertCodeBlock,N as convertColorToHex,g as convertCssLengthToPixels,ft as convertDetails,mt as convertDocumentContent,x as convertHardBreak,ot as convertHeading,gt as convertHorizontalRule,_ as convertImage,U as convertList,G as convertListItem,F as convertMeasureToInches,E as convertMeasureToPixels,X as convertNode,ut as convertOrderedList,C as convertParagraph,f as convertPixelsToTwip,lt as convertTable,it as convertTableCell,st as convertTableHeader,ct as convertTableRow,q as convertTaskItem,ht as convertTaskList,S as convertText,$ as convertTextNodes,B as convertTwipToPixels,Rt as createFloatingOptions,zt as generateDOCX,nt as getImageDataAndMeta,rt as getImageHeight,z as getImageTypeFromSrc,et as getImageWidth};
package/package.json ADDED
@@ -0,0 +1,64 @@
1
+ {
2
+ "name": "@docen/export-docx",
3
+ "version": "0.0.8",
4
+ "description": "A powerful TipTap/ProseMirror extension that converts editor content to Microsoft Word DOCX format",
5
+ "keywords": [
6
+ "converter",
7
+ "docen",
8
+ "document",
9
+ "docx",
10
+ "editor",
11
+ "export",
12
+ "microsoft-word",
13
+ "office",
14
+ "prosemirror",
15
+ "rich-text",
16
+ "tiptap",
17
+ "typescript",
18
+ "word",
19
+ "wysiwyg"
20
+ ],
21
+ "homepage": "https://github.com/DemoMacro/docen#readme",
22
+ "bugs": {
23
+ "url": "https://github.com/DemoMacro/docen/issues"
24
+ },
25
+ "license": "MIT",
26
+ "author": {
27
+ "name": "Demo Macro",
28
+ "email": "abc@imst.xyz",
29
+ "url": "https://imst.xyz/"
30
+ },
31
+ "repository": {
32
+ "type": "git",
33
+ "url": "git+https://github.com/DemoMacro/docen.git"
34
+ },
35
+ "files": [
36
+ "dist"
37
+ ],
38
+ "main": "dist/index.mjs",
39
+ "types": "dist/index.d.ts",
40
+ "exports": {
41
+ ".": {
42
+ "import": "./dist/index.mjs",
43
+ "require": "./dist/index.cjs"
44
+ },
45
+ "./docx": {
46
+ "types": "./dist/docx.d.ts",
47
+ "import": "./dist/docx.mjs",
48
+ "require": "./dist/docx.cjs"
49
+ }
50
+ },
51
+ "dependencies": {
52
+ "docx": "9.5.1",
53
+ "image-meta": "0.2.2",
54
+ "ofetch": "1.5.1"
55
+ },
56
+ "devDependencies": {
57
+ "@tiptap/core": "3.15.3",
58
+ "@docen/extensions": "0.0.8"
59
+ },
60
+ "scripts": {
61
+ "dev": "unbuild --stub",
62
+ "build": "unbuild"
63
+ }
64
+ }