@docen/import-docx 0.0.9 → 0.0.10
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.cjs +1 -1
- package/dist/index.d.cts +17 -41
- package/dist/index.d.mts +17 -41
- package/dist/index.d.ts +17 -41
- package/dist/index.mjs +1 -1
- package/package.json +5 -5
package/dist/index.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";const xastUtilFromXml=require("xast-util-from-xml"),fflate=require("fflate"),undio=require("undio"),imageMeta=require("image-meta");function a(n){return Math.round(n*96/1440)}function s$1(n){return Math.round(n/(914400/96))}function m$2(n){const t=parseInt(n,10);if(!isNaN(t))return s$1(t)}function B$1(n,t){if(!n.children)return null;for(const e of n.children)if(e.type==="element"&&e.name===t)return e;return null}function l$1(n,t){if(!n.children)return null;for(const e of n.children)if(e.type==="element"){if(e.name===t)return e;const r=l$1(e,t);if(r)return r}return null}function F(n,t){const e=[];if(!n.children)return e;for(const r of n.children)r.type==="element"&&(r.name===t&&e.push(r),e.push(...F(r,t)));return e}function D$1(n,t){const e=n[t];if(!e)return;const r=parseInt(e,10);if(!isNaN(r))return e}const s="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";function uint8ArrayToBase64(n){const t=n.length,e=Math.ceil(t/3)*4,r=Array.from({length:e});let i=0;for(let c=0;c<t;c+=3){const f=n[c],g=c+1<t?n[c+1]:0,v=c+2<t?n[c+2]:0,I=f>>2,C=(f&3)<<4|g>>4,T=(g&15)<<2|v>>6,k=v&63;r[i++]=s[I],r[i++]=s[C],r[i++]=c+1<t?s[T]:"=",r[i++]=c+2<t?s[k]:"="}return r.join("")}function base64ToUint8Array(n){const t=atob(n),e=new Uint8Array(t.length);for(let r=0;r<t.length;r++)e[r]=t.charCodeAt(r);return e}const isNode=globalThis.process?.release?.name==="node",isBrowser=typeof window<"u";async function h(n){const t=await n;return t.default||t}let o,u$1=class{#t=!1;constructor({enableHWA:t=!1}={}){this.#t=t}create(t,e){const r=this._createCanvas(t,e);return{canvas:r,context:r.getContext("2d",{willReadFrequently:!this.#t})}}reset({canvas:t},e,r){if(!t)throw new Error("Canvas is not specified");t.width=e,t.height=r}destroy(t){if(!t.canvas)throw new Error("Canvas is not specified");t.canvas.width=0,t.canvas.height=0,t.canvas=void 0,t.context=void 0}_createCanvas(t,e){throw new Error("Not implemented")}};class DOMCanvasFactory extends u$1{_document;constructor({ownerDocument:t=globalThis.document,enableHWA:e=!1}={}){super({enableHWA:e}),this._document=t}_createCanvas(t,e){const r=this._document.createElement("canvas");return r.width=t,r.height=e,r}}class NodeCanvasFactory extends u$1{constructor({enableHWA:t=!1}={}){super({enableHWA:t})}_createCanvas(t,e){if(!o)throw new Error("@napi-rs/canvas module is not resolved");return o.createCanvas(t,e)}}async function resolveCanvasModule(n){o??=await h(n())}async function createCanvasFactory(n){if(isBrowser)return DOMCanvasFactory;if(isNode){if(!n)throw new Error("In Node.js environment, @napi-rs/canvas is required for image cropping. Please provide canvasImport parameter or install it: pnpm add @napi-rs/canvas");return await resolveCanvasModule(n),NodeCanvasFactory}throw new Error("Unsupported environment for canvas operations")}async function cropImageIfNeeded(n,t,e={}){if(!t||!t.left&&!t.top&&!t.right&&!t.bottom||e.enabled===!1)return n;try{const r=await createCanvasFactory(e.canvasImport),i=await w$2(n,r),c=(t.left||0)/1e5*i.width,f=(t.top||0)/1e5*i.height,g=(t.right||0)/1e5*i.width,v=(t.bottom||0)/1e5*i.height,I=Math.round(i.width-c-g),C=Math.round(i.height-f-v);if(I<=0||C<=0)return console.warn("Invalid crop dimensions, returning original image"),n;const T=new r().create(I,C);if(!T.context)throw new Error("Failed to get 2D context from canvas");T.context.drawImage(i,c,f,I,C,0,0,I,C);const k=T.canvas.toDataURL(),M=await(await fetch(k)).arrayBuffer();return new Uint8Array(M)}catch(r){return console.warn("Image cropping failed, returning original image:",r),n}}async function w$2(n,t){if(isBrowser){const e=new Blob([n.buffer]),r=URL.createObjectURL(e);try{const i=new Image;return new Promise((c,f)=>{i.onload=()=>{URL.revokeObjectURL(r),c(i)},i.onerror=()=>{URL.revokeObjectURL(r),f(new Error("Failed to load image"))},i.src=r})}catch(i){throw URL.revokeObjectURL(r),i}}else{if(!o)throw new Error("@napi-rs/canvas module is not resolved");return await o.loadImage(Buffer.from(n))}}const X$1="http://schemas.openxmlformats.org/officeDocument/2006/relationships/image";function _(n){const t=n.attributes.l,e=n.attributes.t,r=n.attributes.r,i=n.attributes.b;if(!(!t&&!e&&!r&&!i))return{left:t?parseInt(t,10):void 0,top:e?parseInt(e,10):void 0,right:r?parseInt(r,10):void 0,bottom:i?parseInt(i,10):void 0}}function N(n){const t=B$1(n,"wp:align"),e=B$1(n,"wp:posOffset"),r=t?.children[0]?.type==="text"?t.children[0].value:void 0,i=e?.children[0]?.type==="text"?parseInt(e.children[0].value,10):void 0;if(!(!r&&i===void 0))return{...r&&{align:r},...i!==void 0&&{offset:i}}}function findDrawingElement(n){let t=B$1(n,"w:drawing");if(t)return t;const e=B$1(n,"mc:AlternateContent"),r=e&&B$1(e,"mc:Choice");return r?B$1(r,"w:drawing"):null}function R$1(n,t,e,r){const i=e/r,c=n/t;return Math.abs(i-c)>.1?i>c?{width:n,height:Math.round(n/i)}:{width:Math.round(t*i),height:t}:{width:n,height:t}}function extractImages(n){const t=new Map,e=n["word/_rels/document.xml.rels"];if(!e)return t;const r=xastUtilFromXml.fromXml(new TextDecoder().decode(e)),i=B$1(r,"Relationships");if(!i)return t;const c=F(i,"Relationship");for(const f of c)if(f.attributes.Type===X$1&&f.attributes.Id&&f.attributes.Target){const g="word/"+f.attributes.Target,v=n[g];if(!v)continue;let I,C,T="png";try{const P=imageMeta.imageMeta(v);I=P.width,C=P.height,P.type&&(T=P.type)}catch{}const k=uint8ArrayToBase64(v),M=`data:image/${T};base64,${k}`;t.set(f.attributes.Id,{src:M,width:I,height:C})}return t}async function extractImageFromDrawing(n,t){const{context:e}=t,r=l$1(n,"a:blip");if(!r?.attributes["r:embed"])return null;const i=r.attributes["r:embed"],c=e.images.get(i);if(!c)return null;let f=c.src;const g=l$1(n,"a:srcRect");if(g){const $=_(g);if($&&f.startsWith("data:")){const[S,H]=f.split(",");if(H){const V=base64ToUint8Array(H);try{const q=await cropImageIfNeeded(V,$,{canvasImport:e.canvasImport,enabled:e.enableImageCrop}),G=uint8ArrayToBase64(q);f=`${S},${G}`}catch(q){console.warn("Image cropping failed, using original image:",q)}}}}const v=l$1(n,"wp:extent");let I,C;if(v){const $=v.attributes.cx,S=v.attributes.cy;typeof $=="string"&&(I=m$2($)),typeof S=="string"&&(C=m$2(S))}const T=l$1(n,"a:xfrm");let k;if(T?.attributes.rot){const $=parseInt(T.attributes.rot,10);isNaN($)||(k=$/6e4)}const M=l$1(n,"wp:docPr")?.attributes.title,P=l$1(n,"wp:positionH"),W=l$1(n,"wp:positionV");let O;if(P||W){const $=P?N(P):void 0,S=W?N(W):void 0;O={horizontalPosition:{relative:P?.attributes.relativeFrom||"page",...$?.align&&{align:$.align},...$?.offset!==void 0&&{offset:$.offset}},verticalPosition:{relative:W?.attributes.relativeFrom||"page",...S?.align&&{align:S.align},...S?.offset!==void 0&&{offset:S.offset}}}}const E=l$1(n,"pic:spPr");let U;if(E){const $=l$1(E,"a:ln"),S=$&&l$1($,"a:solidFill"),H=S&&l$1(S,"a:srgbClr");H?.attributes.val&&(U={type:"solidFill",solidFillType:"rgb",value:H.attributes.val})}return{type:"image",attrs:{src:f,alt:"",...I!==void 0&&{width:I},...C!==void 0&&{height:C},...k!==void 0&&{rotation:k},...M&&{title:M},...O&&{floating:O},...U&&{outline:U}}}}function j(n,t,e){if(t&&e&&n.width&&n.height){const r=R$1(t,e,n.width,n.height);return{type:"image",attrs:{src:n.src,alt:"",width:r.width,height:r.height}}}return{type:"image",attrs:{src:n.src,alt:"",...t!==void 0&&{width:t},...e!==void 0&&{height:e}}}}async function extractImagesFromDrawing(n,t){const e=[],r=B$1(n,"wp:inline")||B$1(n,"wp:anchor");if(!r)return e;const i=B$1(r,"wp:extent");let c,f;if(i){const C=i.attributes.cx,T=i.attributes.cy;typeof C=="string"&&(c=m$2(C)),typeof T=="string"&&(f=m$2(T))}const g=B$1(r,"a:graphic");if(!g)return e;const v=B$1(g,"a:graphicData");if(!v)return e;const I=B$1(v,"wpg:wgp");if(I){const C=B$1(I,"wpg:grpSp"),T=C?[...F(C,"pic:pic"),...F(C,"pic")]:[...F(I,"pic:pic"),...F(I,"pic")];for(const k of T){const M=B$1(k,"a:graphic");if(!M){const E=B$1(k,"pic:blipFill")||l$1(k,"a:blipFill");if(!E)continue;const U=B$1(E,"a:blip")||l$1(E,"a:blip");if(!U?.attributes["r:embed"])continue;const $=U.attributes["r:embed"],S=t.context.images.get($);if(!S)continue;e.push(j(S,c,f));continue}const P={children:[M]},W=await extractImageFromDrawing(P,t);if(!W)continue;const O=P.children[0]?.type==="element"?l$1(P.children[0],"a:blip")?.attributes["r:embed"]:void 0;if(c&&f&&O){const E=t.context.images.get(O);if(E?.width&&E?.height){const U=R$1(c,f,E.width,E.height);W.attrs.width=U.width,W.attrs.height=U.height}else W.attrs.width=c,W.attrs.height=f}e.push(W)}}else{const C=await extractImageFromDrawing(n,t);C&&e.push(C)}return e}const p="http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink";function extractHyperlinks(n){const t=new Map,e=n["word/_rels/document.xml.rels"];if(!e)return t;const r=xastUtilFromXml.fromXml(new TextDecoder().decode(e)),i=B$1(r,"Relationships");if(!i)return t;const c=F(i,"Relationship");for(const f of c)f.attributes.Type===p&&f.attributes.Id&&f.attributes.Target&&t.set(f.attributes.Id,f.attributes.Target);return t}function parseNumberingXml(n){const t=new Map,e=new Map,r=n["word/numbering.xml"];if(!r)return t;const i=xastUtilFromXml.fromXml(new TextDecoder().decode(r)),c=new Map,f=B$1(i,"w:numbering");if(!f)return t;const g=F(f,"w:abstractNum");for(const I of g){const C=I.attributes["w:abstractNumId"],T=B$1(I,"w:lvl");if(!T)continue;const k=B$1(T,"w:numFmt");k?.attributes["w:val"]&&c.set(C,k.attributes["w:val"]);const M=B$1(T,"w:start");M?.attributes["w:val"]&&e.set(C,parseInt(M.attributes["w:val"],10))}const v=F(f,"w:num");for(const I of v){const C=I.attributes["w:numId"],T=B$1(I,"w:abstractNumId");if(!T?.attributes["w:val"])continue;const k=T.attributes["w:val"],M=c.get(k);if(!M)continue;const P=e.get(k);M==="bullet"?t.set(C,{type:"bullet"}):t.set(C,{type:"ordered",...P!==void 0&&{start:P}})}return t}function parseStylesXml(n){const t=new Map,e=n["word/styles.xml"];if(!e)return t;const r=xastUtilFromXml.fromXml(new TextDecoder().decode(e)),i=B$1(r,"w:styles");if(!i)return t;const c=F(i,"w:style").filter(f=>f.attributes["w:type"]==="paragraph");for(const f of c){const g=f.attributes["w:styleId"];if(!g)continue;const v={styleId:g},I=B$1(f,"w:name");I?.attributes["w:val"]&&(v.name=I.attributes["w:val"]);const C=B$1(f,"w:pPr");if(C){const k=B$1(C,"w:outlineLvl");k?.attributes["w:val"]!==void 0&&(v.outlineLvl=parseInt(k.attributes["w:val"],10))}const T=B$1(f,"w:rPr");if(T){const k={},M=B$1(T,"w:color");if(M?.attributes["w:val"]&&M.attributes["w:val"]!=="auto"){const O=M.attributes["w:val"];k.color=O.startsWith("#")?O:`#${O}`}B$1(T,"w:b")&&(k.bold=!0),B$1(T,"w:i")&&(k.italic=!0),B$1(T,"w:u")&&(k.underline=!0),B$1(T,"w:strike")&&(k.strike=!0);const P=B$1(T,"w:sz");if(P?.attributes["w:val"]){const O=P.attributes["w:val"],E=parseInt(O,10);isNaN(E)||(k.fontSize=E)}const W=B$1(T,"w:rFonts");W?.attributes["w:ascii"]&&(k.fontFamily=W.attributes["w:ascii"]),Object.keys(k).length>0&&(v.charFormat=k)}t.set(g,v)}return t}function w$1(n,t){const e=B$1(n,"w:t");if(!e)return null;const r=e.children.find(c=>c.type==="text");if(!r?.value)return null;const i=extractMarks(n,t);return{type:"text",text:r.value,...i.length&&{marks:i}}}async function extractRuns(n,t){const{context:e,styleInfo:r}=t,i=[];for(const c of n.children)if(c.type==="element"){if(c.name==="w:hyperlink"){const f=c,g=f.attributes["r:id"],v=e.hyperlinks.get(g);if(!v)continue;for(const I of f.children){if(I.type!=="element"||I.name!=="w:r")continue;const C=I,T=findDrawingElement(C);if(T){const M=await extractImageFromDrawing(T,{context:e});if(M){i.push(M);continue}const P=await extractImagesFromDrawing(T,{context:e});if(P.length){i.push(...P);continue}}const k=w$1(C,r);k&&(k.marks=k.marks||[],k.marks.push({type:"link",attrs:{href:v}}),i.push(k))}}else if(c.name==="w:r"){const f=c,g=findDrawingElement(f);if(g){const I=await extractImagesFromDrawing(g,{context:e});if(I.length){i.push(...I);continue}}if(B$1(f,"w:br")){const I=extractMarks(f,r);i.push({type:"hardBreak",...I.length&&{marks:I}})}const v=w$1(f,r);v&&i.push(v)}}return i}function extractMarks(n,t){const e=[],r=B$1(n,"w:rPr");let i={};if(t?.charFormat&&(i={...t.charFormat}),r){const c=B$1(r,"w:b");c&&(c.attributes["w:val"]==="false"?i.bold=!1:i.bold=!0);const f=B$1(r,"w:i");f&&(f.attributes["w:val"]==="false"?i.italic=!1:i.italic=!0),B$1(r,"w:u")&&(i.underline=!0),B$1(r,"w:strike")&&(i.strike=!0);const g=B$1(r,"w:color");if(g?.attributes["w:val"]&&g.attributes["w:val"]!=="auto"){const k=g.attributes["w:val"];i.color=k.startsWith("#")?k:`#${k}`}const v=B$1(r,"w:sz");if(v?.attributes["w:val"]){const k=v.attributes["w:val"],M=parseInt(k,10);isNaN(M)||(i.fontSize=M)}const I=B$1(r,"w:rFonts");I?.attributes["w:ascii"]&&(i.fontFamily=I.attributes["w:ascii"]);const C=B$1(r,"w:shd");if(C?.attributes["w:fill"]&&C.attributes["w:fill"]!=="auto"){const k=C.attributes["w:fill"];i.backgroundColor=k.startsWith("#")?k:`#${k}`}B$1(r,"w:highlight")&&e.push({type:"highlight"});const T=B$1(r,"w:vertAlign");if(T){const k=T.attributes["w:val"];k==="subscript"?e.push({type:"subscript"}):k==="superscript"&&e.push({type:"superscript"})}}if(i.bold&&e.push({type:"bold"}),i.italic&&e.push({type:"italic"}),i.underline&&e.push({type:"underline"}),i.strike&&e.push({type:"strike"}),i.color||i.backgroundColor||i.fontSize||i.fontFamily){const c={color:i.color||"",backgroundColor:i.backgroundColor||"",fontSize:"",fontFamily:"",lineHeight:""};if(i.fontSize){const f=Math.round(i.fontSize/1.5*10)/10;c.fontSize=`${f}px`}i.fontFamily&&(c.fontFamily=i.fontFamily),e.push({type:"textStyle",attrs:c})}return e}function extractAlignment(n){const t=B$1(n,"w:pPr");if(!t)return;const e=B$1(t,"w:jc");if(!e?.attributes["w:val"])return;const r=e.attributes["w:val"],i={left:"left",right:"right",center:"center",both:"justify"}[r];return i?{textAlign:i}:void 0}function m$1(n){const t=B$1(n,"w:pPr");if(!t)return null;const e={},r=B$1(t,"w:ind");if(r){const c=D$1(r.attributes,"w:left");c&&(e.indentLeft=c);const f=D$1(r.attributes,"w:right");f&&(e.indentRight=f);const g=D$1(r.attributes,"w:firstLine");if(g)e.indentFirstLine=g;else{const v=D$1(r.attributes,"w:hanging");v&&(e.indentFirstLine=`-${v}`)}}const i=B$1(t,"w:spacing");if(i){const c=D$1(i.attributes,"w:before");c&&(e.spacingBefore=c);const f=D$1(i.attributes,"w:after");f&&(e.spacingAfter=f)}return Object.keys(e).length?e:null}async function convertParagraph(n,t){const{context:e,styleInfo:r}=t,i=B$1(n,"w:pPr"),c=(i&&B$1(i,"w:pStyle"))?.attributes["w:val"];if(c&&e.styleMap){const I=e.styleMap.get(c);if(I?.outlineLvl!==void 0&&I.outlineLvl>=0&&I.outlineLvl<=5){const T=I.outlineLvl+1;return d(n,t,I,T)}const C=c.match(/^Heading(\d+)$/);if(C){const T=parseInt(C[1],10);return d(n,t,I,T)}}const f=c&&e.styleMap?e.styleMap.get(c):void 0,g=await extractRuns(n,{context:e,styleInfo:r||f}),v={...extractAlignment(n),...m$1(n)};if(w(n)){const I=g.filter(C=>C.type!=="hardBreak");return[{type:"paragraph",...Object.keys(v).length&&{attrs:v},content:I.length?I:void 0},{type:"horizontalRule"}]}if(g.length===1&&g[0].type==="hardBreak"){const I=B$1(n,"w:r");if((I&&B$1(I,"w:br"))?.attributes["w:type"]==="page")return{type:"horizontalRule"}}return g.length===1&&g[0].type==="image"?g[0]:{type:"paragraph",...Object.keys(v).length&&{attrs:v},content:g}}function w(n){const t=[],e=r=>{if(r.name==="w:r")t.push(r);else for(const i of r.children)i.type==="element"&&e(i)};return e(n),t.some(r=>B$1(r,"w:br")?.attributes["w:type"]==="page")}async function d(n,t,e,r){return{type:"heading",attrs:{level:r,...m$1(n)},content:await extractRuns(n,{context:t.context,styleInfo:e})}}function parseBorder(n){if(!n)return null;const t=n.attributes["w:val"],e=n.attributes["w:sz"],r=n.attributes["w:color"],i={single:"solid",dashed:"dashed",dotted:"dotted",double:"double",none:"none",nil:"none"},c={};if(r&&r!=="auto"&&(c.color=`#${r}`),e){const f=parseInt(e);isNaN(f)||(c.width=Math.round(f/6))}return t&&i[t]&&(c.style=i[t]),Object.keys(c).length>0?c:null}function parseTableProperties(n){const t={marginTop:void 0,marginBottom:void 0,marginLeft:void 0,marginRight:void 0},e=B$1(n,"w:tblPr");if(!e)return null;const r=B$1(e,"w:tblCellMar");if(!r)return null;const i=B$1(r,"w:top");if(i?.attributes["w:w"]){const v=parseInt(i.attributes["w:w"]);isNaN(v)||(t.marginTop=v)}const c=B$1(r,"w:bottom");if(c?.attributes["w:w"]){const v=parseInt(c.attributes["w:w"]);isNaN(v)||(t.marginBottom=v)}const f=B$1(r,"w:left");if(f?.attributes["w:w"]){const v=parseInt(f.attributes["w:w"]);isNaN(v)||(t.marginLeft=v)}const g=B$1(r,"w:right");if(g?.attributes["w:w"]){const v=parseInt(g.attributes["w:w"]);isNaN(v)||(t.marginRight=v)}return t.marginTop===void 0&&t.marginBottom===void 0&&t.marginLeft===void 0&&t.marginRight===void 0?null:t}function parseRowProperties(n){const t={rowHeight:null},e=B$1(n,"w:trPr");if(!e)return t;const r=B$1(e,"w:trHeight");if(r?.attributes["w:val"]){const i=parseInt(r.attributes["w:val"]),c=a(i);t.rowHeight=`${c}px`}return t}function parseCellProperties(n){const t={colspan:1,rowspan:1,colwidth:null},e=B$1(n,"w:tcPr");if(!e)return t;const r=B$1(e,"w:gridSpan");r?.attributes["w:val"]&&(t.colspan=parseInt(r.attributes["w:val"])),B$1(e,"w:vMerge")?.attributes["w:val"]==="continue"&&(t.rowspan=0);const i=B$1(e,"w:tcW");if(i?.attributes["w:w"]){const v=parseInt(i.attributes["w:w"]),I=a(v);t.colwidth=[I]}const c=B$1(e,"w:shd");c?.attributes["w:fill"]&&(t.backgroundColor=`#${c.attributes["w:fill"]}`);const f=B$1(e,"w:vAlign");f?.attributes["w:val"]&&(t.verticalAlign=f.attributes["w:val"]);const g=B$1(e,"w:tcBorders");if(g){const v=parseBorder(B$1(g,"w:top"));v&&(t.borderTop=v);const I=parseBorder(B$1(g,"w:bottom"));I&&(t.borderBottom=I);const C=parseBorder(B$1(g,"w:left"));C&&(t.borderLeft=C);const T=parseBorder(B$1(g,"w:right"));T&&(t.borderRight=T)}return t}function isTable(n){return n.name==="w:tbl"}async function convertTable(n,t){const e=[];for(const f of n.children)f.type==="element"&&f.name==="w:tr"&&e.push(f);const r=new Map,i=await Promise.all(e.map((f,g)=>u(f,{context:t.context,activeRowspans:r,rows:e,rowIndex:g}))),c=parseTableProperties(n);return{type:"table",...c&&{attrs:c},content:i}}async function u(n,t){const e=[];let r=0;const i=parseRowProperties(n);for(const c of n.children){if(c.type!=="element"||c.name!=="w:tc")continue;const f=t.activeRowspans.get(r);if(f&&f>0){t.activeRowspans.set(r,f-1),r++;continue}let g=parseCellProperties(c);if(g?.rowspan===1){const I=x$1({rows:t.rows,rowIndex:t.rowIndex,colIndex:r});I>1&&(g={...g,rowspan:I})}if(g?.rowspan&&g.rowspan>1&&t.activeRowspans.set(r,g.rowspan-1),g?.rowspan===0){r++;continue}const v=await b(c,t);e.push({type:"tableCell",...g&&{attrs:g},content:v}),r+=g?.colspan||1}return{type:"tableRow",...i&&{attrs:i},content:e}}function x$1(n){let t=1,e=n.colIndex;for(let r=n.rowIndex+1;r<n.rows.length;r++){const i=n.rows[r];let c=!1;for(const f of i.children){if(f.type!=="element"||f.name!=="w:tc")continue;const g=parseCellProperties(f),v=g?.colspan||1;if(e>=0&&e<v){if(g?.rowspan===0)t++,c=!0;else return t;break}e-=v}if(!c)break}return t}async function b(n,t){const e=[];for(const r of n.children)if(r.type==="element"&&r.name==="w:p"){const i=await convertParagraph(r,t);Array.isArray(i)?e.push(...i):e.push(i)}return e.length?e:[{type:"paragraph",content:[]}]}const m="\u2610",l="\u2611";function x(n){const t=B$1(n,"w:r");if(!t)return null;const e=B$1(t,"w:t");if(!e)return null;const r=e.children.find(i=>i.type==="text");return r?.value&&r||null}function isTaskItem(n){const t=x(n);if(!t)return!1;const e=t.value;return e.startsWith(m)||e.startsWith(l)}function getTaskItemChecked(n){return x(n)?.value.startsWith(l)||!1}async function convertTaskItem(n,t){return{type:"taskItem",attrs:{checked:getTaskItemChecked(n)},content:[await y(n,t)]}}async function convertTaskList(n,t){const{siblings:e,index:r,processedIndices:i}=t,c=[];let f=r;for(;f<e.length;){const g=e[f];if(g.name!=="w:p"||!isTaskItem(g))break;i.add(f);const v=await convertTaskItem(g,{context:t.context,styleInfo:t.styleInfo});c.push(v),f++}return{type:"taskList",content:c}}async function y(n,t){const{context:e,styleInfo:r}=t,i=await extractRuns(n,{context:e,styleInfo:r});if(i.length>0&&i[0].type==="text"){const f=i[0],g=f.text;if(g.startsWith(m)||g.startsWith(l)){const v=g.substring(2).trimStart();v?f.text=v:i.shift()}}const c=extractAlignment(n);return{type:"paragraph",...c&&{attrs:c},content:i.length?i:void 0}}function isCodeBlock(n){const t=B$1(n,"w:pPr"),e=(t&&B$1(t,"w:pStyle"))?.attributes["w:val"];return e==="CodeBlock"||e?.startsWith("Code")||!1}function getCodeBlockLanguage(n){const t=B$1(n,"w:pPr"),e=(t&&B$1(t,"w:pStyle"))?.attributes["w:val"];return e?.startsWith("CodeBlock")&&e.replace("CodeBlock","").toLowerCase()||void 0}function isListItem(n){const t=B$1(n,"w:pPr");return!!t&&B$1(t,"w:numPr")!==void 0}function getListInfo(n){const t=B$1(n,"w:pPr"),e=t&&B$1(t,"w:numPr");if(!e)return null;const r=B$1(e,"w:ilvl"),i=B$1(e,"w:numId");return!r||!i?null:{numId:i.attributes["w:val"],level:parseInt(r.attributes["w:val"]||"0",10)}}function isHorizontalRule(n){const t=B$1(n,"w:r");if(!t)return!1;let e=!1,r=!1;for(const i of t.children)i.type==="element"&&(i.name==="w:br"&&i.attributes["w:type"]==="page"?e=!0:i.name==="w:t"?i.children.find(c=>c.type==="text")?.value?.trim().length&&(r=!0):i.name!=="w:rPr"&&(r=!0));return e&&!r}async function parseDOCX(n,t={}){const e=await undio.toUint8Array(n),r=fflate.unzipSync(e),i=extractHyperlinks(r),c=extractImages(r),f=r["word/document.xml"];if(!f)throw new Error("Invalid DOCX file: missing word/document.xml");const g=xastUtilFromXml.fromXml(new TextDecoder().decode(f)),v=parseNumberingXml(r),I=parseStylesXml(r),C={enableImageCrop:!1,ignoreEmptyParagraphs:!1,...t,hyperlinks:i,images:c,listTypeMap:v,styleMap:I};return await D(g,{context:C})}async function D(n,t){if(n.type!=="root")return{type:"doc",content:[]};const e=B$1(n,"w:document");if(!e)return{type:"doc",content:[]};const r=B$1(e,"w:body");return r?{type:"doc",content:await A(r.children.filter(i=>i.type==="element"),t)}:{type:"doc",content:[]}}async function A(n,t){const e=[],r=new Set;for(let i=0;i<n.length;i++){if(r.has(i))continue;const c=n[i];if(t.context.ignoreEmptyParagraphs&&c.name==="w:p"&&z(c))continue;const f=await L(c,n,i,t,r);Array.isArray(f)?e.push(...f):f&&e.push(f)}return e}async function L(n,t,e,r,i){switch(n.name){case"w:tbl":return await convertTable(n,r);case"w:p":return isCodeBlock(n)?await X(n):isTaskItem(n)?await convertTaskList(n,{...r,siblings:t,index:e,processedIndices:i}):isListItem(n)?await B(n,t,e,r,i):isHorizontalRule(n)?{type:"horizontalRule"}:await convertParagraph(n,r);default:return null}}async function X(n){const t=getCodeBlockLanguage(n),e=R(n);return{type:"codeBlock",...t&&{attrs:{language:t}},content:e}}async function B(n,t,e,r,i){const c=getListInfo(n);if(!c)return await convertParagraph(n,r);const f=r.context.listTypeMap.get(c.numId),g=f?.type||"bullet",v=[];let I=e;for(;I<t.length;){const T=t[I];if(T.name!=="w:p"||!isListItem(T))break;const k=getListInfo(T);if(!k||k.numId!==c.numId)break;i.add(I);const M=await convertParagraph(T,r),P=Array.isArray(M)?M[0]:M;v.push({type:"listItem",content:[P]}),I++}const C={type:g==="bullet"?"bulletList":"orderedList",content:v};return g==="ordered"&&(C.attrs={type:null,...f?.start!==void 0&&{start:f.start}}),C}function R(n){const t=[],e=F(n,"w:r");for(const r of e){const i=B$1(r,"w:t");if(!i)continue;const c=i.children.find(f=>f.type==="text");c&&"value"in c&&c.value&&t.push({type:"text",text:c.value})}return t}function z(n){const t=F(n,"w:r");for(const e of t){const r=B$1(e,"w:t");if(r){const c=r.children.find(f=>f.type==="text");if(c&&"value"in c&&c.value&&c.value.trim().length>0)return!1}if(B$1(e,"w:drawing")||B$1(e,"mc:AlternateContent")||B$1(e,"w:pict"))return!1;const i=B$1(e,"w:br");if(i&&i.attributes["w:type"]==="page")return!1}return!0}exports.convertParagraph=convertParagraph,exports.convertTable=convertTable,exports.convertTaskItem=convertTaskItem,exports.convertTaskList=convertTaskList,exports.extractAlignment=extractAlignment,exports.extractMarks=extractMarks,exports.extractRuns=extractRuns,exports.getCodeBlockLanguage=getCodeBlockLanguage,exports.getListInfo=getListInfo,exports.getTaskItemChecked=getTaskItemChecked,exports.isCodeBlock=isCodeBlock,exports.isHorizontalRule=isHorizontalRule,exports.isListItem=isListItem,exports.isTable=isTable,exports.isTaskItem=isTaskItem,exports.parseDOCX=parseDOCX;
|
|
1
|
+
"use strict";const xastUtilFromXml=require("xast-util-from-xml"),fflate=require("fflate"),undio=require("undio"),imageMeta=require("image-meta"),C=.6666666666666666,g={CODE_BLOCK:"CodeBlock",CODE_PREFIX:"Code"},_$1={docxToTipTap:{left:"left",right:"right",center:"center",both:"justify"}},o$1=96;function s$1(n){return Math.round(n*o$1/1440)}function A$1(n){return`${s$1(n)}px`}function c(n){return Math.round(n/(914400/o$1))}function I(n){const t=parseInt(n,10);if(!isNaN(t))return c(t)}function S$1(n,t){if(!n.children)return null;for(const e of n.children)if(e.type==="element"&&e.name===t)return e;return null}function F(n,t){if(!n.children)return null;for(const e of n.children)if(e.type==="element"){if(e.name===t)return e;const r=F(e,t);if(r)return r}return null}function f(n,t){const e=[];if(!n.children)return e;for(const r of n.children)r.type==="element"&&(r.name===t&&e.push(r),e.push(...f(r,t)));return e}function H$1(n,t){const e=n[t];if(!e)return;const r=parseInt(e,10);if(!isNaN(r))return e}function b$2(n){return t=>n.includes(t)}const s="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";function uint8ArrayToBase64(n){const t=n.length,e=Math.ceil(t/3)*4,r=Array.from({length:e});let i=0;for(let a=0;a<t;a+=3){const v=n[a],k=a+1<t?n[a+1]:0,T=a+2<t?n[a+2]:0,M=v>>2,O=(v&3)<<4|k>>4,E=(k&15)<<2|T>>6,$=T&63;r[i++]=s[M],r[i++]=s[O],r[i++]=a+1<t?s[E]:"=",r[i++]=a+2<t?s[$]:"="}return r.join("")}function base64ToUint8Array(n){const t=atob(n),e=new Uint8Array(t.length);for(let r=0;r<t.length;r++)e[r]=t.charCodeAt(r);return e}const isNode=globalThis.process?.release?.name==="node",isBrowser=typeof window<"u";async function h(n){const t=await n;return t.default||t}let o,u$1=class{#t=!1;constructor({enableHWA:t=!1}={}){this.#t=t}create(t,e){const r=this._createCanvas(t,e);return{canvas:r,context:r.getContext("2d",{willReadFrequently:!this.#t})}}reset({canvas:t},e,r){if(!t)throw new Error("Canvas is not specified");t.width=e,t.height=r}destroy(t){if(!t.canvas)throw new Error("Canvas is not specified");t.canvas.width=0,t.canvas.height=0,t.canvas=void 0,t.context=void 0}_createCanvas(t,e){throw new Error("Not implemented")}};class DOMCanvasFactory extends u$1{_document;constructor({ownerDocument:t=globalThis.document,enableHWA:e=!1}={}){super({enableHWA:e}),this._document=t}_createCanvas(t,e){const r=this._document.createElement("canvas");return r.width=t,r.height=e,r}}class NodeCanvasFactory extends u$1{constructor({enableHWA:t=!1}={}){super({enableHWA:t})}_createCanvas(t,e){if(!o)throw new Error("@napi-rs/canvas module is not resolved");return o.createCanvas(t,e)}}async function resolveCanvasModule(n){o??=await h(n())}async function createCanvasFactory(n){if(isBrowser)return DOMCanvasFactory;if(isNode){if(!n)throw new Error("In Node.js environment, @napi-rs/canvas is required for image cropping. Please provide canvasImport parameter or install it: pnpm add @napi-rs/canvas");return await resolveCanvasModule(n),NodeCanvasFactory}throw new Error("Unsupported environment for canvas operations")}async function cropImageIfNeeded(n,t,e={}){if(!t||!t.left&&!t.top&&!t.right&&!t.bottom||e.enabled===!1)return n;try{const r=await createCanvasFactory(e.canvasImport),i=await w$1(n,r),a=(t.left||0)/1e5*i.width,v=(t.top||0)/1e5*i.height,k=(t.right||0)/1e5*i.width,T=(t.bottom||0)/1e5*i.height,M=Math.round(i.width-a-k),O=Math.round(i.height-v-T);if(M<=0||O<=0)return console.warn("Invalid crop dimensions, returning original image"),n;const E=new r().create(M,O);if(!E.context)throw new Error("Failed to get 2D context from canvas");E.context.drawImage(i,a,v,M,O,0,0,M,O);const $=E.canvas.toDataURL(),W=await(await fetch($)).arrayBuffer();return new Uint8Array(W)}catch(r){return console.warn("Image cropping failed, returning original image:",r),n}}async function w$1(n,t){if(isBrowser){const e=new Blob([n.buffer]),r=URL.createObjectURL(e);try{const i=new Image;return new Promise((a,v)=>{i.onload=()=>{URL.revokeObjectURL(r),a(i)},i.onerror=()=>{URL.revokeObjectURL(r),v(new Error("Failed to load image"))},i.src=r})}catch(i){throw URL.revokeObjectURL(r),i}}else{if(!o)throw new Error("@napi-rs/canvas module is not resolved");return await o.loadImage(Buffer.from(n))}}const G="http://schemas.openxmlformats.org/officeDocument/2006/relationships/image",S=b$2(["left","right","center","inside","outside"]),X$1=b$2(["top","bottom","center","inside","outside"]),_=b$2(["page","character","column","margin","leftMargin","rightMargin","insideMargin","outsideMargin"]),j=b$2(["page","paragraph","margin","topMargin","bottomMargin","insideMargin","outsideMargin","line"]);function B$1(n){const t=n.attributes.l,e=n.attributes.t,r=n.attributes.r,i=n.attributes.b;if(!(!t&&!e&&!r&&!i))return{left:t?parseInt(t,10):void 0,top:e?parseInt(e,10):void 0,right:r?parseInt(r,10):void 0,bottom:i?parseInt(i,10):void 0}}function U(n){const t=S$1(n,"wp:align"),e=S$1(n,"wp:posOffset");let r;if(t?.children[0]?.type==="text"){const a=t.children[0].value;S(a)&&(r=a)}const i=e?.children[0]?.type==="text"?parseInt(e.children[0].value,10):void 0;if(!(!r&&i===void 0))return{...r&&{align:r},...i!==void 0&&{offset:i}}}function H(n){const t=S$1(n,"wp:align"),e=S$1(n,"wp:posOffset");let r;if(t?.children[0]?.type==="text"){const a=t.children[0].value;X$1(a)&&(r=a)}const i=e?.children[0]?.type==="text"?parseInt(e.children[0].value,10):void 0;if(!(!r&&i===void 0))return{...r&&{align:r},...i!==void 0&&{offset:i}}}function findDrawingElement(n){let t=S$1(n,"w:drawing");if(t)return t;const e=S$1(n,"mc:AlternateContent"),r=e&&S$1(e,"mc:Choice");return r?S$1(r,"w:drawing"):null}function N(n,t,e,r){const i=e/r,a=n/t;return Math.abs(i-a)>.1?i>a?{width:n,height:Math.round(n/i)}:{width:Math.round(t*i),height:t}:{width:n,height:t}}async function extractImages(n,t){const e=new Map,r=n["word/_rels/document.xml.rels"];if(!r)return e;const i=xastUtilFromXml.fromXml(new TextDecoder().decode(r)),a=S$1(i,"Relationships");if(!a)return e;const v=f(a,"Relationship");for(const k of v)if(k.attributes.Type===G&&k.attributes.Id&&k.attributes.Target){const T="word/"+k.attributes.Target,M=n[T];if(!M)continue;let O,E,$="png";try{const q=imageMeta.imageMeta(M);O=q.width,E=q.height,q.type&&($=q.type)}catch{}let W;if(t)W=(await t({id:k.attributes.Id,contentType:`image/${$}`,data:M})).src;else{const q=uint8ArrayToBase64(M);W=`data:image/${$};base64,${q}`}e.set(k.attributes.Id,{src:W,width:O,height:E})}return e}async function extractImageFromDrawing(n,t){const{context:e}=t,r=F(n,"a:blip");if(!r?.attributes["r:embed"])return null;const i=r.attributes["r:embed"],a=e.images.get(i);if(!a)return null;let v=a.src;const k=F(n,"a:srcRect");if(k){const K=B$1(k);if(K&&v.startsWith("data:")){const[V,tt]=v.split(",");if(tt){const et=base64ToUint8Array(tt);try{const nt=await cropImageIfNeeded(et,K,{canvasImport:e.image?.canvasImport,enabled:e.image?.enableImageCrop??!1}),rt=uint8ArrayToBase64(nt);v=`${V},${rt}`}catch(nt){console.warn("Image cropping failed, using original image:",nt)}}}}const T=F(n,"wp:extent");let M,O;if(T){const K=T.attributes.cx,V=T.attributes.cy;typeof K=="string"&&(M=I(K)),typeof V=="string"&&(O=I(V))}const E=F(n,"a:xfrm");let $;if(E?.attributes.rot){const K=parseInt(E.attributes.rot,10);isNaN(K)||($=K/6e4)}const W=F(n,"wp:docPr")?.attributes.title,q=F(n,"wp:positionH"),J=F(n,"wp:positionV");let Y;if(q||J){const K=q?U(q):void 0,V=J?H(J):void 0,tt=q?.attributes.relativeFrom,et=J?.attributes.relativeFrom,nt=typeof tt=="string"&&_(tt)?tt:"page",rt=typeof et=="string"&&j(et)?et:"page";Y={horizontalPosition:{relative:nt,...K?.align&&{align:K.align},...K?.offset!==void 0&&{offset:K.offset}},verticalPosition:{relative:rt,...V?.align&&{align:V.align},...V?.offset!==void 0&&{offset:V.offset}}}}const Q=F(n,"pic:spPr");let Z;if(Q){const K=F(Q,"a:ln"),V=K&&F(K,"a:solidFill"),tt=V&&F(V,"a:srgbClr");tt?.attributes.val&&(Z={type:"solidFill",solidFillType:"rgb",value:tt.attributes.val})}return{type:"image",attrs:{src:v,alt:"",...M!==void 0&&{width:M},...O!==void 0&&{height:O},...$!==void 0&&{rotation:$},...W&&{title:W},...Y&&{floating:Y},...Z&&{outline:Z}}}}function L$1(n,t,e){if(t&&e&&n.width&&n.height){const r=N(t,e,n.width,n.height);return{type:"image",attrs:{src:n.src,alt:"",width:r.width,height:r.height}}}return{type:"image",attrs:{src:n.src,alt:"",...t!==void 0&&{width:t},...e!==void 0&&{height:e}}}}async function extractImagesFromDrawing(n,t){const e=[],r=S$1(n,"wp:inline")||S$1(n,"wp:anchor");if(!r)return e;const i=S$1(r,"wp:extent");let a,v;if(i){const O=i.attributes.cx,E=i.attributes.cy;typeof O=="string"&&(a=I(O)),typeof E=="string"&&(v=I(E))}const k=S$1(r,"a:graphic");if(!k)return e;const T=S$1(k,"a:graphicData");if(!T)return e;const M=S$1(T,"wpg:wgp");if(M){const O=S$1(M,"wpg:grpSp"),E=O?[...f(O,"pic:pic"),...f(O,"pic")]:[...f(M,"pic:pic"),...f(M,"pic")];for(const $ of E){const W=S$1($,"a:graphic");if(!W){const Q=S$1($,"pic:blipFill")||F($,"a:blipFill");if(!Q)continue;const Z=S$1(Q,"a:blip")||F(Q,"a:blip");if(!Z?.attributes["r:embed"])continue;const K=Z.attributes["r:embed"],V=t.context.images.get(K);if(!V)continue;e.push(L$1(V,a,v));continue}const q={children:[W]},J=await extractImageFromDrawing(q,t);if(!J)continue;const Y=q.children[0]?.type==="element"?F(q.children[0],"a:blip")?.attributes["r:embed"]:void 0;if(a&&v&&Y){const Q=t.context.images.get(Y);if(Q?.width&&Q?.height){const Z=N(a,v,Q.width,Q.height);J.attrs.width=Z.width,J.attrs.height=Z.height}else J.attrs.width=a,J.attrs.height=v}e.push(J)}}else{const O=await extractImageFromDrawing(n,t);O&&e.push(O)}return e}const p="http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink";function extractHyperlinks(n){const t=new Map,e=n["word/_rels/document.xml.rels"];if(!e)return t;const r=xastUtilFromXml.fromXml(new TextDecoder().decode(e)),i=S$1(r,"Relationships");if(!i)return t;const a=f(i,"Relationship");for(const v of a)v.attributes.Type===p&&v.attributes.Id&&v.attributes.Target&&t.set(v.attributes.Id,v.attributes.Target);return t}function parseNumberingXml(n){const t=new Map,e=new Map,r=n["word/numbering.xml"];if(!r)return t;const i=xastUtilFromXml.fromXml(new TextDecoder().decode(r)),a=new Map,v=S$1(i,"w:numbering");if(!v)return t;const k=f(v,"w:abstractNum");for(const M of k){const O=M.attributes["w:abstractNumId"],E=S$1(M,"w:lvl");if(!E)continue;const $=S$1(E,"w:numFmt");$?.attributes["w:val"]&&a.set(O,$.attributes["w:val"]);const W=S$1(E,"w:start");W?.attributes["w:val"]&&e.set(O,parseInt(W.attributes["w:val"],10))}const T=f(v,"w:num");for(const M of T){const O=M.attributes["w:numId"],E=S$1(M,"w:abstractNumId");if(!E?.attributes["w:val"])continue;const $=E.attributes["w:val"],W=a.get($);if(!W)continue;const q=e.get($);W==="bullet"?t.set(O,{type:"bullet"}):t.set(O,{type:"ordered",...q!==void 0&&{start:q}})}return t}function parseStylesXml(n){const t=new Map,e=n["word/styles.xml"];if(!e)return t;const r=xastUtilFromXml.fromXml(new TextDecoder().decode(e)),i=S$1(r,"w:styles");if(!i)return t;const a=f(i,"w:style").filter(v=>v.attributes["w:type"]==="paragraph");for(const v of a){const k=v.attributes["w:styleId"];if(!k)continue;const T={styleId:k},M=S$1(v,"w:name");M?.attributes["w:val"]&&(T.name=M.attributes["w:val"]);const O=S$1(v,"w:pPr");if(O){const $=S$1(O,"w:outlineLvl");$?.attributes["w:val"]!==void 0&&(T.outlineLvl=parseInt($.attributes["w:val"],10))}const E=S$1(v,"w:rPr");if(E){const $={},W=S$1(E,"w:color");if(W?.attributes["w:val"]&&W.attributes["w:val"]!=="auto"){const Y=W.attributes["w:val"];$.color=Y.startsWith("#")?Y:`#${Y}`}S$1(E,"w:b")&&($.bold=!0),S$1(E,"w:i")&&($.italic=!0),S$1(E,"w:u")&&($.underline=!0),S$1(E,"w:strike")&&($.strike=!0);const q=S$1(E,"w:sz");if(q?.attributes["w:val"]){const Y=q.attributes["w:val"],Q=parseInt(Y,10);isNaN(Q)||($.fontSize=Q)}const J=S$1(E,"w:rFonts");J?.attributes["w:ascii"]&&($.fontFamily=J.attributes["w:ascii"]),Object.keys($).length>0&&(T.charFormat=$)}t.set(k,T)}return t}function w(n,t){const e=S$1(n,"w:t");if(!e)return null;const r=e.children.find(a=>a.type==="text");if(!r?.value)return null;const i=extractMarks(n,t);return{type:"text",text:r.value,...i.length&&{marks:i}}}async function extractRuns(n,t){const{context:e,styleInfo:r}=t,i=[];for(const a of n.children)if(a.type==="element"){if(a.name==="w:hyperlink"){const v=a,k=v.attributes["r:id"],T=e.hyperlinks.get(k);if(!T)continue;for(const M of v.children){if(M.type!=="element"||M.name!=="w:r")continue;const O=M,E=findDrawingElement(O);if(E){const W=await extractImageFromDrawing(E,{context:e});if(W){i.push(W);continue}const q=await extractImagesFromDrawing(E,{context:e});if(q.length){i.push(...q);continue}}const $=w(O,r);$&&($.marks=$.marks||[],$.marks.push({type:"link",attrs:{href:T}}),i.push($))}}else if(a.name==="w:r"){const v=a,k=findDrawingElement(v);if(k){const M=await extractImagesFromDrawing(k,{context:e});if(M.length){i.push(...M);continue}}if(S$1(v,"w:br")){const M=extractMarks(v,r);i.push({type:"hardBreak",...M.length&&{marks:M}})}const T=w(v,r);T&&i.push(T)}}return i}function extractMarks(n,t){const e=[],r=S$1(n,"w:rPr");let i={};if(t?.charFormat&&(i={...t.charFormat}),r){const a=S$1(r,"w:b");a&&(a.attributes["w:val"]==="false"?i.bold=!1:i.bold=!0);const v=S$1(r,"w:i");v&&(v.attributes["w:val"]==="false"?i.italic=!1:i.italic=!0),S$1(r,"w:u")&&(i.underline=!0),S$1(r,"w:strike")&&(i.strike=!0);const k=S$1(r,"w:color");if(k?.attributes["w:val"]&&k.attributes["w:val"]!=="auto"){const $=k.attributes["w:val"];i.color=$.startsWith("#")?$:`#${$}`}const T=S$1(r,"w:sz");if(T?.attributes["w:val"]){const $=T.attributes["w:val"],W=parseInt($,10);isNaN(W)||(i.fontSize=W)}const M=S$1(r,"w:rFonts");M?.attributes["w:ascii"]&&(i.fontFamily=M.attributes["w:ascii"]);const O=S$1(r,"w:shd");if(O?.attributes["w:fill"]&&O.attributes["w:fill"]!=="auto"){const $=O.attributes["w:fill"];i.backgroundColor=$.startsWith("#")?$:`#${$}`}S$1(r,"w:highlight")&&e.push({type:"highlight"});const E=S$1(r,"w:vertAlign");if(E){const $=E.attributes["w:val"];$==="subscript"?e.push({type:"subscript"}):$==="superscript"&&e.push({type:"superscript"})}}if(i.bold&&e.push({type:"bold"}),i.italic&&e.push({type:"italic"}),i.underline&&e.push({type:"underline"}),i.strike&&e.push({type:"strike"}),i.color||i.backgroundColor||i.fontSize||i.fontFamily){const a={color:i.color||"",backgroundColor:i.backgroundColor||"",fontSize:"",fontFamily:"",lineHeight:""};if(i.fontSize){const v=Math.round(i.fontSize*C*10)/10;a.fontSize=`${v}px`}i.fontFamily&&(a.fontFamily=i.fontFamily),e.push({type:"textStyle",attrs:a})}return e}function extractAlignment(n){const t=S$1(n,"w:pPr");if(!t)return;const e=S$1(t,"w:jc");if(!e?.attributes["w:val"])return;const r=e.attributes["w:val"],i=_$1.docxToTipTap[r];return i?{textAlign:i}:void 0}function d(n){const t=S$1(n,"w:pPr");if(!t)return null;const e={},r=S$1(t,"w:ind");if(r){const a=H$1(r.attributes,"w:left");if(a){const T=parseInt(a,10);e.indentLeft=A$1(T)}const v=H$1(r.attributes,"w:right");if(v){const T=parseInt(v,10);e.indentRight=A$1(T)}const k=H$1(r.attributes,"w:firstLine");if(k){const T=parseInt(k,10);e.indentFirstLine=A$1(T)}else{const T=H$1(r.attributes,"w:hanging");if(T){const M=a?parseInt(a,10):0,O=parseInt(T,10),E=M-O;e.indentFirstLine=A$1(E)}}}const i=S$1(t,"w:spacing");if(i){const a=H$1(i.attributes,"w:before");if(a){const k=parseInt(a,10);e.spacingBefore=A$1(k)}const v=H$1(i.attributes,"w:after");if(v){const k=parseInt(v,10);e.spacingAfter=A$1(k)}}return Object.keys(e).length?e:null}async function convertParagraph(n,t){const{context:e,styleInfo:r}=t,i=S$1(n,"w:pPr"),a=(i&&S$1(i,"w:pStyle"))?.attributes["w:val"];if(a&&e.styleMap){const M=e.styleMap.get(a);if(M?.outlineLvl!==void 0&&M.outlineLvl>=0&&M.outlineLvl<=5){const E=M.outlineLvl+1;return b$1(n,t,M,E)}const O=a.match(/^Heading(\d+)$/);if(O){const E=parseInt(O[1],10);return b$1(n,t,M,E)}}const v=a&&e.styleMap?e.styleMap.get(a):void 0,k=await extractRuns(n,{context:e,styleInfo:r||v}),T={...extractAlignment(n),...d(n)};if(P(n)){const M=k.filter(O=>O.type!=="hardBreak");return[{type:"paragraph",...Object.keys(T).length&&{attrs:T},content:M.length?M:void 0},{type:"horizontalRule"}]}if(k.length===1&&k[0].type==="hardBreak"){const M=S$1(n,"w:r");if((M&&S$1(M,"w:br"))?.attributes["w:type"]==="page")return{type:"horizontalRule"}}if(k.length===1&&k[0].type==="image"){const M=k[0];return{type:"paragraph",...Object.keys(T).length&&{attrs:T},content:[M]}}return{type:"paragraph",...Object.keys(T).length&&{attrs:T},content:k}}function P(n){const t=[],e=r=>{if(r.name==="w:r")t.push(r);else for(const i of r.children)i.type==="element"&&e(i)};return e(n),t.some(r=>S$1(r,"w:br")?.attributes["w:type"]==="page")}async function b$1(n,t,e,r){return{type:"heading",attrs:{level:r,...d(n)},content:await extractRuns(n,{context:t.context,styleInfo:e})}}function parseBorder(n){if(!n)return null;const t=n.attributes["w:val"],e=n.attributes["w:sz"],r=n.attributes["w:color"],i={single:"solid",dashed:"dashed",dotted:"dotted",double:"double",none:"none",nil:"none"},a={};if(r&&r!=="auto"&&(a.color=`#${r}`),e){const v=parseInt(e);isNaN(v)||(a.width=Math.round(v/6))}return t&&i[t]&&(a.style=i[t]),Object.keys(a).length>0?a:null}function parseTableProperties(n){const t={marginTop:void 0,marginBottom:void 0,marginLeft:void 0,marginRight:void 0},e=S$1(n,"w:tblPr");if(!e)return null;const r=S$1(e,"w:tblCellMar");if(!r)return null;const i=S$1(r,"w:top");if(i?.attributes["w:w"]){const T=parseInt(i.attributes["w:w"]);isNaN(T)||(t.marginTop=T)}const a=S$1(r,"w:bottom");if(a?.attributes["w:w"]){const T=parseInt(a.attributes["w:w"]);isNaN(T)||(t.marginBottom=T)}const v=S$1(r,"w:left");if(v?.attributes["w:w"]){const T=parseInt(v.attributes["w:w"]);isNaN(T)||(t.marginLeft=T)}const k=S$1(r,"w:right");if(k?.attributes["w:w"]){const T=parseInt(k.attributes["w:w"]);isNaN(T)||(t.marginRight=T)}return t.marginTop===void 0&&t.marginBottom===void 0&&t.marginLeft===void 0&&t.marginRight===void 0?null:t}function parseRowProperties(n){const t={rowHeight:null},e=S$1(n,"w:trPr");if(!e)return t;const r=S$1(e,"w:trHeight");if(r?.attributes["w:val"]){const i=parseInt(r.attributes["w:val"]),a=s$1(i);t.rowHeight=`${a}px`}return t}function parseCellProperties(n){const t={colspan:1,rowspan:1,colwidth:null},e=S$1(n,"w:tcPr");if(!e)return t;const r=S$1(e,"w:gridSpan");r?.attributes["w:val"]&&(t.colspan=parseInt(r.attributes["w:val"])),S$1(e,"w:vMerge")?.attributes["w:val"]==="continue"&&(t.rowspan=0);const i=S$1(e,"w:tcW");if(i?.attributes["w:w"]){const T=parseInt(i.attributes["w:w"]),M=s$1(T);t.colwidth=[M]}const a=S$1(e,"w:shd");a?.attributes["w:fill"]&&(t.backgroundColor=`#${a.attributes["w:fill"]}`);const v=S$1(e,"w:vAlign");v?.attributes["w:val"]&&(t.verticalAlign=v.attributes["w:val"]);const k=S$1(e,"w:tcBorders");if(k){const T=parseBorder(S$1(k,"w:top"));T&&(t.borderTop=T);const M=parseBorder(S$1(k,"w:bottom"));M&&(t.borderBottom=M);const O=parseBorder(S$1(k,"w:left"));O&&(t.borderLeft=O);const E=parseBorder(S$1(k,"w:right"));E&&(t.borderRight=E)}return t}function isTable(n){return n.name==="w:tbl"}async function convertTable(n,t){const e=[];for(const v of n.children)v.type==="element"&&v.name==="w:tr"&&e.push(v);const r=new Map,i=await Promise.all(e.map((v,k)=>u(v,{context:t.context,activeRowspans:r,rows:e,rowIndex:k}))),a=parseTableProperties(n);return{type:"table",...a&&{attrs:a},content:i}}async function u(n,t){const e=[];let r=0;const i=parseRowProperties(n);for(const a of n.children){if(a.type!=="element"||a.name!=="w:tc")continue;const v=t.activeRowspans.get(r);if(v&&v>0){t.activeRowspans.set(r,v-1),r++;continue}let k=parseCellProperties(a);if(k?.rowspan===1){const M=x$1({rows:t.rows,rowIndex:t.rowIndex,colIndex:r});M>1&&(k={...k,rowspan:M})}if(k?.rowspan&&k.rowspan>1&&t.activeRowspans.set(r,k.rowspan-1),k?.rowspan===0){r++;continue}const T=await b(a,t);e.push({type:"tableCell",...k&&{attrs:k},content:T}),r+=k?.colspan||1}return{type:"tableRow",...i&&{attrs:i},content:e}}function x$1(n){let t=1,e=n.colIndex;for(let r=n.rowIndex+1;r<n.rows.length;r++){const i=n.rows[r];let a=!1;for(const v of i.children){if(v.type!=="element"||v.name!=="w:tc")continue;const k=parseCellProperties(v),T=k?.colspan||1;if(e>=0&&e<T){if(k?.rowspan===0)t++,a=!0;else return t;break}e-=T}if(!a)break}return t}async function b(n,t){const e=[];for(const r of n.children)if(r.type==="element"&&r.name==="w:p"){const i=await convertParagraph(r,t);Array.isArray(i)?e.push(...i):e.push(i)}return e.length?e:[{type:"paragraph",content:[]}]}const m="\u2610",l="\u2611";function x(n){const t=S$1(n,"w:r");if(!t)return null;const e=S$1(t,"w:t");if(!e)return null;const r=e.children.find(i=>i.type==="text");return r?.value&&r||null}function isTaskItem(n){const t=x(n);if(!t)return!1;const e=t.value;return e.startsWith(m)||e.startsWith(l)}function getTaskItemChecked(n){return x(n)?.value.startsWith(l)||!1}async function convertTaskItem(n,t){return{type:"taskItem",attrs:{checked:getTaskItemChecked(n)},content:[await y(n,t)]}}async function convertTaskList(n,t){const{siblings:e,index:r,processedIndices:i}=t,a=[];let v=r;for(;v<e.length;){const k=e[v];if(k.name!=="w:p"||!isTaskItem(k))break;i.add(v);const T=await convertTaskItem(k,{context:t.context,styleInfo:t.styleInfo});a.push(T),v++}return{type:"taskList",content:a}}async function y(n,t){const{context:e,styleInfo:r}=t,i=await extractRuns(n,{context:e,styleInfo:r});if(i.length>0&&i[0].type==="text"){const v=i[0],k=v.text;if(k.startsWith(m)||k.startsWith(l)){const T=k.substring(2).trimStart();T?v.text=T:i.shift()}}const a=extractAlignment(n);return{type:"paragraph",...a&&{attrs:a},content:i.length?i:void 0}}function isCodeBlock(n){const t=S$1(n,"w:pPr"),e=(t&&S$1(t,"w:pStyle"))?.attributes["w:val"];return e===g.CODE_BLOCK||e?.startsWith(g.CODE_PREFIX)||!1}function getCodeBlockLanguage(n){const t=S$1(n,"w:pPr"),e=(t&&S$1(t,"w:pStyle"))?.attributes["w:val"];return e?.startsWith(g.CODE_BLOCK)&&e.replace(g.CODE_BLOCK,"").toLowerCase()||void 0}function isListItem(n){const t=S$1(n,"w:pPr");return!!t&&S$1(t,"w:numPr")!==void 0}function getListInfo(n){const t=S$1(n,"w:pPr"),e=t&&S$1(t,"w:numPr");if(!e)return null;const r=S$1(e,"w:ilvl"),i=S$1(e,"w:numId");return!r||!i?null:{numId:i.attributes["w:val"],level:parseInt(r.attributes["w:val"]||"0",10)}}function isHorizontalRule(n){const t=S$1(n,"w:r");if(!t)return!1;let e=!1,r=!1;for(const i of t.children)i.type==="element"&&(i.name==="w:br"&&i.attributes["w:type"]==="page"?e=!0:i.name==="w:t"?i.children.find(a=>a.type==="text")?.value?.trim().length&&(r=!0):i.name!=="w:rPr"&&(r=!0));return e&&!r}async function parseDOCX(n,t={}){const e=await undio.toUint8Array(n),r=fflate.unzipSync(e),i=extractHyperlinks(r),a=await extractImages(r,t.image?.handler),v=r["word/document.xml"];if(!v)throw new Error("Invalid DOCX file: missing word/document.xml");const k=xastUtilFromXml.fromXml(new TextDecoder().decode(v)),T=parseNumberingXml(r),M=parseStylesXml(r),O={...t,hyperlinks:i,images:a,listTypeMap:T,styleMap:M};return await D(k,{context:O})}async function D(n,t){if(n.type!=="root")return{type:"doc",content:[]};const e=S$1(n,"w:document");if(!e)return{type:"doc",content:[]};const r=S$1(e,"w:body");return r?{type:"doc",content:await A(r.children.filter(i=>i.type==="element"),t)}:{type:"doc",content:[]}}async function A(n,t){const e=[],r=new Set;for(let i=0;i<n.length;i++){if(r.has(i))continue;const a=n[i];if(t.context.ignoreEmptyParagraphs&&a.name==="w:p"&&z(a))continue;const v=await L(a,n,i,t,r);Array.isArray(v)?e.push(...v):v&&e.push(v)}return e}async function L(n,t,e,r,i){switch(n.name){case"w:tbl":return await convertTable(n,r);case"w:p":return isCodeBlock(n)?await X(n):isTaskItem(n)?await convertTaskList(n,{...r,siblings:t,index:e,processedIndices:i}):isListItem(n)?await B(n,t,e,r,i):isHorizontalRule(n)?{type:"horizontalRule"}:await convertParagraph(n,r);default:return null}}async function X(n){const t=getCodeBlockLanguage(n),e=R(n);return{type:"codeBlock",...t&&{attrs:{language:t}},content:e}}async function B(n,t,e,r,i){const a=getListInfo(n);if(!a)return await convertParagraph(n,r);const v=r.context.listTypeMap.get(a.numId),k=v?.type||"bullet",T=[];let M=e;for(;M<t.length;){const E=t[M];if(E.name!=="w:p"||!isListItem(E))break;const $=getListInfo(E);if(!$||$.numId!==a.numId)break;i.add(M);const W=await convertParagraph(E,r),q=Array.isArray(W)?W[0]:W;T.push({type:"listItem",content:[q]}),M++}const O={type:k==="bullet"?"bulletList":"orderedList",content:T};return k==="ordered"&&(O.attrs={type:null,...v?.start!==void 0&&{start:v.start}}),O}function R(n){const t=[],e=f(n,"w:r");for(const r of e){const i=S$1(r,"w:t");if(!i)continue;const a=i.children.find(v=>v.type==="text");a&&"value"in a&&a.value&&t.push({type:"text",text:a.value})}return t}function z(n){const t=f(n,"w:r");for(const e of t){const r=S$1(e,"w:t");if(r){const a=r.children.find(v=>v.type==="text");if(a&&"value"in a&&a.value&&a.value.trim().length>0)return!1}if(S$1(e,"w:drawing")||S$1(e,"mc:AlternateContent")||S$1(e,"w:pict"))return!1;const i=S$1(e,"w:br");if(i&&i.attributes["w:type"]==="page")return!1}return!0}exports.convertParagraph=convertParagraph,exports.convertTable=convertTable,exports.convertTaskItem=convertTaskItem,exports.convertTaskList=convertTaskList,exports.extractAlignment=extractAlignment,exports.extractMarks=extractMarks,exports.extractRuns=extractRuns,exports.getCodeBlockLanguage=getCodeBlockLanguage,exports.getListInfo=getListInfo,exports.getTaskItemChecked=getTaskItemChecked,exports.isCodeBlock=isCodeBlock,exports.isHorizontalRule=isHorizontalRule,exports.isListItem=isListItem,exports.isTable=isTable,exports.isTaskItem=isTaskItem,exports.parseDOCX=parseDOCX;
|
package/dist/index.d.cts
CHANGED
|
@@ -2029,6 +2029,16 @@ declare class Transform {
|
|
|
2029
2029
|
*/
|
|
2030
2030
|
get docChanged(): boolean;
|
|
2031
2031
|
/**
|
|
2032
|
+
Return a single range, in post-transform document positions,
|
|
2033
|
+
that covers all content changed by this transform. Returns null
|
|
2034
|
+
if no replacements are made. Note that this will ignore changes
|
|
2035
|
+
that add/remove marks without replacing the underlying content.
|
|
2036
|
+
*/
|
|
2037
|
+
changedRange(): {
|
|
2038
|
+
from: number;
|
|
2039
|
+
to: number;
|
|
2040
|
+
} | null;
|
|
2041
|
+
/**
|
|
2032
2042
|
Replace the part of the document between `from` and `to` with the
|
|
2033
2043
|
given `slice`.
|
|
2034
2044
|
*/
|
|
@@ -6567,30 +6577,16 @@ interface Commands<ReturnType = any> {
|
|
|
6567
6577
|
interface Storage {
|
|
6568
6578
|
}
|
|
6569
6579
|
|
|
6570
|
-
/**
|
|
6571
|
-
* DOCX image information for custom converter
|
|
6572
|
-
*/
|
|
6573
6580
|
interface DocxImageInfo {
|
|
6574
|
-
/** Image ID (relationship ID in DOCX) */
|
|
6575
6581
|
id: string;
|
|
6576
|
-
/** Content type (e.g., "image/png", "image/jpeg") */
|
|
6577
6582
|
contentType: string;
|
|
6578
|
-
/** Raw image data */
|
|
6579
6583
|
data: Uint8Array;
|
|
6580
6584
|
}
|
|
6581
|
-
/**
|
|
6582
|
-
* Result of image conversion
|
|
6583
|
-
*/
|
|
6584
6585
|
interface DocxImageResult {
|
|
6585
|
-
/** Image src attribute value (URL or data URL) */
|
|
6586
6586
|
src: string;
|
|
6587
|
-
/** Optional alt text */
|
|
6588
6587
|
alt?: string;
|
|
6589
6588
|
}
|
|
6590
|
-
|
|
6591
|
-
* Custom image converter function type
|
|
6592
|
-
*/
|
|
6593
|
-
type DocxImageConverter = (image: DocxImageInfo) => Promise<DocxImageResult>;
|
|
6589
|
+
type DocxImageImportHandler = (info: DocxImageInfo) => Promise<DocxImageResult>;
|
|
6594
6590
|
/**
|
|
6595
6591
|
* List information extracted from numbering.xml
|
|
6596
6592
|
*/
|
|
@@ -6611,33 +6607,13 @@ interface ImageInfo {
|
|
|
6611
6607
|
height?: number;
|
|
6612
6608
|
}
|
|
6613
6609
|
|
|
6614
|
-
/**
|
|
6615
|
-
* Options for importing DOCX files to TipTap content
|
|
6616
|
-
*/
|
|
6617
6610
|
interface DocxImportOptions {
|
|
6618
|
-
|
|
6619
|
-
|
|
6620
|
-
|
|
6611
|
+
image?: {
|
|
6612
|
+
handler?: DocxImageImportHandler;
|
|
6613
|
+
canvasImport?: () => Promise<typeof _napi_rs_canvas>;
|
|
6614
|
+
enableImageCrop?: boolean;
|
|
6615
|
+
};
|
|
6621
6616
|
ignoreEmptyParagraphs?: boolean;
|
|
6622
|
-
/**
|
|
6623
|
-
* Dynamic import function for @napi-rs/canvas
|
|
6624
|
-
* Required for image cropping in Node.js environment, ignored in browser
|
|
6625
|
-
*
|
|
6626
|
-
* @example
|
|
6627
|
-
* import { parseDOCX } from '@docen/import-docx';
|
|
6628
|
-
* const content = await parseDOCX(buffer, {
|
|
6629
|
-
* canvasImport: () => import('@napi-rs/canvas')
|
|
6630
|
-
* });
|
|
6631
|
-
*/
|
|
6632
|
-
canvasImport?: () => Promise<typeof _napi_rs_canvas>;
|
|
6633
|
-
/**
|
|
6634
|
-
* Enable or disable image cropping during import
|
|
6635
|
-
* When true, images with crop information in DOCX will be cropped
|
|
6636
|
-
* When false (default), crop information is ignored and full image is used
|
|
6637
|
-
*
|
|
6638
|
-
* @default false
|
|
6639
|
-
*/
|
|
6640
|
-
enableImageCrop?: boolean;
|
|
6641
6617
|
}
|
|
6642
6618
|
|
|
6643
6619
|
/**
|
|
@@ -6778,4 +6754,4 @@ declare function convertTaskList(_node: Element$1, params: {
|
|
|
6778
6754
|
declare function isHorizontalRule(node: Element$1): boolean;
|
|
6779
6755
|
|
|
6780
6756
|
export { convertParagraph, convertTable, convertTaskItem, convertTaskList, extractAlignment, extractMarks, extractRuns, getCodeBlockLanguage, getListInfo, getTaskItemChecked, isCodeBlock, isHorizontalRule, isListItem, isTable, isTaskItem, parseDOCX };
|
|
6781
|
-
export type {
|
|
6757
|
+
export type { DocxImageImportHandler, DocxImageInfo, DocxImageResult, DocxImportOptions, ImageInfo, ListInfo, ListTypeMap, ParseContext };
|
package/dist/index.d.mts
CHANGED
|
@@ -2029,6 +2029,16 @@ declare class Transform {
|
|
|
2029
2029
|
*/
|
|
2030
2030
|
get docChanged(): boolean;
|
|
2031
2031
|
/**
|
|
2032
|
+
Return a single range, in post-transform document positions,
|
|
2033
|
+
that covers all content changed by this transform. Returns null
|
|
2034
|
+
if no replacements are made. Note that this will ignore changes
|
|
2035
|
+
that add/remove marks without replacing the underlying content.
|
|
2036
|
+
*/
|
|
2037
|
+
changedRange(): {
|
|
2038
|
+
from: number;
|
|
2039
|
+
to: number;
|
|
2040
|
+
} | null;
|
|
2041
|
+
/**
|
|
2032
2042
|
Replace the part of the document between `from` and `to` with the
|
|
2033
2043
|
given `slice`.
|
|
2034
2044
|
*/
|
|
@@ -6567,30 +6577,16 @@ interface Commands<ReturnType = any> {
|
|
|
6567
6577
|
interface Storage {
|
|
6568
6578
|
}
|
|
6569
6579
|
|
|
6570
|
-
/**
|
|
6571
|
-
* DOCX image information for custom converter
|
|
6572
|
-
*/
|
|
6573
6580
|
interface DocxImageInfo {
|
|
6574
|
-
/** Image ID (relationship ID in DOCX) */
|
|
6575
6581
|
id: string;
|
|
6576
|
-
/** Content type (e.g., "image/png", "image/jpeg") */
|
|
6577
6582
|
contentType: string;
|
|
6578
|
-
/** Raw image data */
|
|
6579
6583
|
data: Uint8Array;
|
|
6580
6584
|
}
|
|
6581
|
-
/**
|
|
6582
|
-
* Result of image conversion
|
|
6583
|
-
*/
|
|
6584
6585
|
interface DocxImageResult {
|
|
6585
|
-
/** Image src attribute value (URL or data URL) */
|
|
6586
6586
|
src: string;
|
|
6587
|
-
/** Optional alt text */
|
|
6588
6587
|
alt?: string;
|
|
6589
6588
|
}
|
|
6590
|
-
|
|
6591
|
-
* Custom image converter function type
|
|
6592
|
-
*/
|
|
6593
|
-
type DocxImageConverter = (image: DocxImageInfo) => Promise<DocxImageResult>;
|
|
6589
|
+
type DocxImageImportHandler = (info: DocxImageInfo) => Promise<DocxImageResult>;
|
|
6594
6590
|
/**
|
|
6595
6591
|
* List information extracted from numbering.xml
|
|
6596
6592
|
*/
|
|
@@ -6611,33 +6607,13 @@ interface ImageInfo {
|
|
|
6611
6607
|
height?: number;
|
|
6612
6608
|
}
|
|
6613
6609
|
|
|
6614
|
-
/**
|
|
6615
|
-
* Options for importing DOCX files to TipTap content
|
|
6616
|
-
*/
|
|
6617
6610
|
interface DocxImportOptions {
|
|
6618
|
-
|
|
6619
|
-
|
|
6620
|
-
|
|
6611
|
+
image?: {
|
|
6612
|
+
handler?: DocxImageImportHandler;
|
|
6613
|
+
canvasImport?: () => Promise<typeof _napi_rs_canvas>;
|
|
6614
|
+
enableImageCrop?: boolean;
|
|
6615
|
+
};
|
|
6621
6616
|
ignoreEmptyParagraphs?: boolean;
|
|
6622
|
-
/**
|
|
6623
|
-
* Dynamic import function for @napi-rs/canvas
|
|
6624
|
-
* Required for image cropping in Node.js environment, ignored in browser
|
|
6625
|
-
*
|
|
6626
|
-
* @example
|
|
6627
|
-
* import { parseDOCX } from '@docen/import-docx';
|
|
6628
|
-
* const content = await parseDOCX(buffer, {
|
|
6629
|
-
* canvasImport: () => import('@napi-rs/canvas')
|
|
6630
|
-
* });
|
|
6631
|
-
*/
|
|
6632
|
-
canvasImport?: () => Promise<typeof _napi_rs_canvas>;
|
|
6633
|
-
/**
|
|
6634
|
-
* Enable or disable image cropping during import
|
|
6635
|
-
* When true, images with crop information in DOCX will be cropped
|
|
6636
|
-
* When false (default), crop information is ignored and full image is used
|
|
6637
|
-
*
|
|
6638
|
-
* @default false
|
|
6639
|
-
*/
|
|
6640
|
-
enableImageCrop?: boolean;
|
|
6641
6617
|
}
|
|
6642
6618
|
|
|
6643
6619
|
/**
|
|
@@ -6778,4 +6754,4 @@ declare function convertTaskList(_node: Element$1, params: {
|
|
|
6778
6754
|
declare function isHorizontalRule(node: Element$1): boolean;
|
|
6779
6755
|
|
|
6780
6756
|
export { convertParagraph, convertTable, convertTaskItem, convertTaskList, extractAlignment, extractMarks, extractRuns, getCodeBlockLanguage, getListInfo, getTaskItemChecked, isCodeBlock, isHorizontalRule, isListItem, isTable, isTaskItem, parseDOCX };
|
|
6781
|
-
export type {
|
|
6757
|
+
export type { DocxImageImportHandler, DocxImageInfo, DocxImageResult, DocxImportOptions, ImageInfo, ListInfo, ListTypeMap, ParseContext };
|
package/dist/index.d.ts
CHANGED
|
@@ -2029,6 +2029,16 @@ declare class Transform {
|
|
|
2029
2029
|
*/
|
|
2030
2030
|
get docChanged(): boolean;
|
|
2031
2031
|
/**
|
|
2032
|
+
Return a single range, in post-transform document positions,
|
|
2033
|
+
that covers all content changed by this transform. Returns null
|
|
2034
|
+
if no replacements are made. Note that this will ignore changes
|
|
2035
|
+
that add/remove marks without replacing the underlying content.
|
|
2036
|
+
*/
|
|
2037
|
+
changedRange(): {
|
|
2038
|
+
from: number;
|
|
2039
|
+
to: number;
|
|
2040
|
+
} | null;
|
|
2041
|
+
/**
|
|
2032
2042
|
Replace the part of the document between `from` and `to` with the
|
|
2033
2043
|
given `slice`.
|
|
2034
2044
|
*/
|
|
@@ -6567,30 +6577,16 @@ interface Commands<ReturnType = any> {
|
|
|
6567
6577
|
interface Storage {
|
|
6568
6578
|
}
|
|
6569
6579
|
|
|
6570
|
-
/**
|
|
6571
|
-
* DOCX image information for custom converter
|
|
6572
|
-
*/
|
|
6573
6580
|
interface DocxImageInfo {
|
|
6574
|
-
/** Image ID (relationship ID in DOCX) */
|
|
6575
6581
|
id: string;
|
|
6576
|
-
/** Content type (e.g., "image/png", "image/jpeg") */
|
|
6577
6582
|
contentType: string;
|
|
6578
|
-
/** Raw image data */
|
|
6579
6583
|
data: Uint8Array;
|
|
6580
6584
|
}
|
|
6581
|
-
/**
|
|
6582
|
-
* Result of image conversion
|
|
6583
|
-
*/
|
|
6584
6585
|
interface DocxImageResult {
|
|
6585
|
-
/** Image src attribute value (URL or data URL) */
|
|
6586
6586
|
src: string;
|
|
6587
|
-
/** Optional alt text */
|
|
6588
6587
|
alt?: string;
|
|
6589
6588
|
}
|
|
6590
|
-
|
|
6591
|
-
* Custom image converter function type
|
|
6592
|
-
*/
|
|
6593
|
-
type DocxImageConverter = (image: DocxImageInfo) => Promise<DocxImageResult>;
|
|
6589
|
+
type DocxImageImportHandler = (info: DocxImageInfo) => Promise<DocxImageResult>;
|
|
6594
6590
|
/**
|
|
6595
6591
|
* List information extracted from numbering.xml
|
|
6596
6592
|
*/
|
|
@@ -6611,33 +6607,13 @@ interface ImageInfo {
|
|
|
6611
6607
|
height?: number;
|
|
6612
6608
|
}
|
|
6613
6609
|
|
|
6614
|
-
/**
|
|
6615
|
-
* Options for importing DOCX files to TipTap content
|
|
6616
|
-
*/
|
|
6617
6610
|
interface DocxImportOptions {
|
|
6618
|
-
|
|
6619
|
-
|
|
6620
|
-
|
|
6611
|
+
image?: {
|
|
6612
|
+
handler?: DocxImageImportHandler;
|
|
6613
|
+
canvasImport?: () => Promise<typeof _napi_rs_canvas>;
|
|
6614
|
+
enableImageCrop?: boolean;
|
|
6615
|
+
};
|
|
6621
6616
|
ignoreEmptyParagraphs?: boolean;
|
|
6622
|
-
/**
|
|
6623
|
-
* Dynamic import function for @napi-rs/canvas
|
|
6624
|
-
* Required for image cropping in Node.js environment, ignored in browser
|
|
6625
|
-
*
|
|
6626
|
-
* @example
|
|
6627
|
-
* import { parseDOCX } from '@docen/import-docx';
|
|
6628
|
-
* const content = await parseDOCX(buffer, {
|
|
6629
|
-
* canvasImport: () => import('@napi-rs/canvas')
|
|
6630
|
-
* });
|
|
6631
|
-
*/
|
|
6632
|
-
canvasImport?: () => Promise<typeof _napi_rs_canvas>;
|
|
6633
|
-
/**
|
|
6634
|
-
* Enable or disable image cropping during import
|
|
6635
|
-
* When true, images with crop information in DOCX will be cropped
|
|
6636
|
-
* When false (default), crop information is ignored and full image is used
|
|
6637
|
-
*
|
|
6638
|
-
* @default false
|
|
6639
|
-
*/
|
|
6640
|
-
enableImageCrop?: boolean;
|
|
6641
6617
|
}
|
|
6642
6618
|
|
|
6643
6619
|
/**
|
|
@@ -6778,4 +6754,4 @@ declare function convertTaskList(_node: Element$1, params: {
|
|
|
6778
6754
|
declare function isHorizontalRule(node: Element$1): boolean;
|
|
6779
6755
|
|
|
6780
6756
|
export { convertParagraph, convertTable, convertTaskItem, convertTaskList, extractAlignment, extractMarks, extractRuns, getCodeBlockLanguage, getListInfo, getTaskItemChecked, isCodeBlock, isHorizontalRule, isListItem, isTable, isTaskItem, parseDOCX };
|
|
6781
|
-
export type {
|
|
6757
|
+
export type { DocxImageImportHandler, DocxImageInfo, DocxImageResult, DocxImportOptions, ImageInfo, ListInfo, ListTypeMap, ParseContext };
|
package/dist/index.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{fromXml as R}from"xast-util-from-xml";import{unzipSync as ut}from"fflate";import{toUint8Array as ft}from"undio";import{imageMeta as wt}from"image-meta";function O(n){return Math.round(n*96/1440)}function pt(n){return Math.round(n/(914400/96))}function P(n){const t=parseInt(n,10);if(!isNaN(t))return pt(t)}function a(n,t){if(!n.children)return null;for(const e of n.children)if(e.type==="element"&&e.name===t)return e;return null}function m(n,t){if(!n.children)return null;for(const e of n.children)if(e.type==="element"){if(e.name===t)return e;const r=m(e,t);if(r)return r}return null}function I(n,t){const e=[];if(!n.children)return e;for(const r of n.children)r.type==="element"&&(r.name===t&&e.push(r),e.push(...I(r,t)));return e}function C(n,t){const e=n[t];if(!e)return;const r=parseInt(e,10);if(!isNaN(r))return e}const N="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";function U(n){const t=n.length,e=Math.ceil(t/3)*4,r=Array.from({length:e});let i=0;for(let o=0;o<t;o+=3){const s=n[o],c=o+1<t?n[o+1]:0,l=o+2<t?n[o+2]:0,u=s>>2,w=(s&3)<<4|c>>4,p=(c&15)<<2|l>>6,f=l&63;r[i++]=N[u],r[i++]=N[w],r[i++]=o+1<t?N[p]:"=",r[i++]=o+2<t?N[f]:"="}return r.join("")}function dt(n){const t=atob(n),e=new Uint8Array(t.length);for(let r=0;r<t.length;r++)e[r]=t.charCodeAt(r);return e}const ht=globalThis.process?.release?.name==="node",H=typeof window<"u";async function gt(n){const t=await n;return t.default||t}let L,_=class{#t=!1;constructor({enableHWA:t=!1}={}){this.#t=t}create(t,e){const r=this._createCanvas(t,e);return{canvas:r,context:r.getContext("2d",{willReadFrequently:!this.#t})}}reset({canvas:t},e,r){if(!t)throw new Error("Canvas is not specified");t.width=e,t.height=r}destroy(t){if(!t.canvas)throw new Error("Canvas is not specified");t.canvas.width=0,t.canvas.height=0,t.canvas=void 0,t.context=void 0}_createCanvas(t,e){throw new Error("Not implemented")}};class bt extends _{_document;constructor({ownerDocument:t=globalThis.document,enableHWA:e=!1}={}){super({enableHWA:e}),this._document=t}_createCanvas(t,e){const r=this._document.createElement("canvas");return r.width=t,r.height=e,r}}class mt extends _{constructor({enableHWA:t=!1}={}){super({enableHWA:t})}_createCanvas(t,e){if(!L)throw new Error("@napi-rs/canvas module is not resolved");return L.createCanvas(t,e)}}async function yt(n){L??=await gt(n())}async function vt(n){if(H)return bt;if(ht){if(!n)throw new Error("In Node.js environment, @napi-rs/canvas is required for image cropping. Please provide canvasImport parameter or install it: pnpm add @napi-rs/canvas");return await yt(n),mt}throw new Error("Unsupported environment for canvas operations")}async function xt(n,t,e={}){if(!t||!t.left&&!t.top&&!t.right&&!t.bottom||e.enabled===!1)return n;try{const r=await vt(e.canvasImport),i=await It(n,r),o=(t.left||0)/1e5*i.width,s=(t.top||0)/1e5*i.height,c=(t.right||0)/1e5*i.width,l=(t.bottom||0)/1e5*i.height,u=Math.round(i.width-o-c),w=Math.round(i.height-s-l);if(u<=0||w<=0)return console.warn("Invalid crop dimensions, returning original image"),n;const p=new r().create(u,w);if(!p.context)throw new Error("Failed to get 2D context from canvas");p.context.drawImage(i,o,s,u,w,0,0,u,w);const f=p.canvas.toDataURL(),d=await(await fetch(f)).arrayBuffer();return new Uint8Array(d)}catch(r){return console.warn("Image cropping failed, returning original image:",r),n}}async function It(n,t){if(H){const e=new Blob([n.buffer]),r=URL.createObjectURL(e);try{const i=new Image;return new Promise((o,s)=>{i.onload=()=>{URL.revokeObjectURL(r),o(i)},i.onerror=()=>{URL.revokeObjectURL(r),s(new Error("Failed to load image"))},i.src=r})}catch(i){throw URL.revokeObjectURL(r),i}}else{if(!L)throw new Error("@napi-rs/canvas module is not resolved");return await L.loadImage(Buffer.from(n))}}const kt="http://schemas.openxmlformats.org/officeDocument/2006/relationships/image";function Ct(n){const t=n.attributes.l,e=n.attributes.t,r=n.attributes.r,i=n.attributes.b;if(!(!t&&!e&&!r&&!i))return{left:t?parseInt(t,10):void 0,top:e?parseInt(e,10):void 0,right:r?parseInt(r,10):void 0,bottom:i?parseInt(i,10):void 0}}function X(n){const t=a(n,"wp:align"),e=a(n,"wp:posOffset"),r=t?.children[0]?.type==="text"?t.children[0].value:void 0,i=e?.children[0]?.type==="text"?parseInt(e.children[0].value,10):void 0;if(!(!r&&i===void 0))return{...r&&{align:r},...i!==void 0&&{offset:i}}}function q(n){let t=a(n,"w:drawing");if(t)return t;const e=a(n,"mc:AlternateContent"),r=e&&a(e,"mc:Choice");return r?a(r,"w:drawing"):null}function V(n,t,e,r){const i=e/r,o=n/t;return Math.abs(i-o)>.1?i>o?{width:n,height:Math.round(n/i)}:{width:Math.round(t*i),height:t}:{width:n,height:t}}function Ft(n){const t=new Map,e=n["word/_rels/document.xml.rels"];if(!e)return t;const r=R(new TextDecoder().decode(e)),i=a(r,"Relationships");if(!i)return t;const o=I(i,"Relationship");for(const s of o)if(s.attributes.Type===kt&&s.attributes.Id&&s.attributes.Target){const c="word/"+s.attributes.Target,l=n[c];if(!l)continue;let u,w,p="png";try{const h=wt(l);u=h.width,w=h.height,h.type&&(p=h.type)}catch{}const f=U(l),d=`data:image/${p};base64,${f}`;t.set(s.attributes.Id,{src:d,width:u,height:w})}return t}async function B(n,t){const{context:e}=t,r=m(n,"a:blip");if(!r?.attributes["r:embed"])return null;const i=r.attributes["r:embed"],o=e.images.get(i);if(!o)return null;let s=o.src;const c=m(n,"a:srcRect");if(c){const g=Ct(c);if(g&&s.startsWith("data:")){const[b,F]=s.split(",");if(F){const ct=dt(F);try{const $=await xt(ct,g,{canvasImport:e.canvasImport,enabled:e.enableImageCrop}),lt=U($);s=`${b},${lt}`}catch($){console.warn("Image cropping failed, using original image:",$)}}}}const l=m(n,"wp:extent");let u,w;if(l){const g=l.attributes.cx,b=l.attributes.cy;typeof g=="string"&&(u=P(g)),typeof b=="string"&&(w=P(b))}const p=m(n,"a:xfrm");let f;if(p?.attributes.rot){const g=parseInt(p.attributes.rot,10);isNaN(g)||(f=g/6e4)}const d=m(n,"wp:docPr")?.attributes.title,h=m(n,"wp:positionH"),y=m(n,"wp:positionV");let x;if(h||y){const g=h?X(h):void 0,b=y?X(y):void 0;x={horizontalPosition:{relative:h?.attributes.relativeFrom||"page",...g?.align&&{align:g.align},...g?.offset!==void 0&&{offset:g.offset}},verticalPosition:{relative:y?.attributes.relativeFrom||"page",...b?.align&&{align:b.align},...b?.offset!==void 0&&{offset:b.offset}}}}const v=m(n,"pic:spPr");let k;if(v){const g=m(v,"a:ln"),b=g&&m(g,"a:solidFill"),F=b&&m(b,"a:srgbClr");F?.attributes.val&&(k={type:"solidFill",solidFillType:"rgb",value:F.attributes.val})}return{type:"image",attrs:{src:s,alt:"",...u!==void 0&&{width:u},...w!==void 0&&{height:w},...f!==void 0&&{rotation:f},...d&&{title:d},...x&&{floating:x},...k&&{outline:k}}}}function Rt(n,t,e){if(t&&e&&n.width&&n.height){const r=V(t,e,n.width,n.height);return{type:"image",attrs:{src:n.src,alt:"",width:r.width,height:r.height}}}return{type:"image",attrs:{src:n.src,alt:"",...t!==void 0&&{width:t},...e!==void 0&&{height:e}}}}async function G(n,t){const e=[],r=a(n,"wp:inline")||a(n,"wp:anchor");if(!r)return e;const i=a(r,"wp:extent");let o,s;if(i){const w=i.attributes.cx,p=i.attributes.cy;typeof w=="string"&&(o=P(w)),typeof p=="string"&&(s=P(p))}const c=a(r,"a:graphic");if(!c)return e;const l=a(c,"a:graphicData");if(!l)return e;const u=a(l,"wpg:wgp");if(u){const w=a(u,"wpg:grpSp"),p=w?[...I(w,"pic:pic"),...I(w,"pic")]:[...I(u,"pic:pic"),...I(u,"pic")];for(const f of p){const d=a(f,"a:graphic");if(!d){const v=a(f,"pic:blipFill")||m(f,"a:blipFill");if(!v)continue;const k=a(v,"a:blip")||m(v,"a:blip");if(!k?.attributes["r:embed"])continue;const g=k.attributes["r:embed"],b=t.context.images.get(g);if(!b)continue;e.push(Rt(b,o,s));continue}const h={children:[d]},y=await B(h,t);if(!y)continue;const x=h.children[0]?.type==="element"?m(h.children[0],"a:blip")?.attributes["r:embed"]:void 0;if(o&&s&&x){const v=t.context.images.get(x);if(v?.width&&v?.height){const k=V(o,s,v.width,v.height);y.attrs.width=k.width,y.attrs.height=k.height}else y.attrs.width=o,y.attrs.height=s}e.push(y)}}else{const w=await B(n,t);w&&e.push(w)}return e}const Lt="http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink";function Mt(n){const t=new Map,e=n["word/_rels/document.xml.rels"];if(!e)return t;const r=R(new TextDecoder().decode(e)),i=a(r,"Relationships");if(!i)return t;const o=I(i,"Relationship");for(const s of o)s.attributes.Type===Lt&&s.attributes.Id&&s.attributes.Target&&t.set(s.attributes.Id,s.attributes.Target);return t}function Pt(n){const t=new Map,e=new Map,r=n["word/numbering.xml"];if(!r)return t;const i=R(new TextDecoder().decode(r)),o=new Map,s=a(i,"w:numbering");if(!s)return t;const c=I(s,"w:abstractNum");for(const u of c){const w=u.attributes["w:abstractNumId"],p=a(u,"w:lvl");if(!p)continue;const f=a(p,"w:numFmt");f?.attributes["w:val"]&&o.set(w,f.attributes["w:val"]);const d=a(p,"w:start");d?.attributes["w:val"]&&e.set(w,parseInt(d.attributes["w:val"],10))}const l=I(s,"w:num");for(const u of l){const w=u.attributes["w:numId"],p=a(u,"w:abstractNumId");if(!p?.attributes["w:val"])continue;const f=p.attributes["w:val"],d=o.get(f);if(!d)continue;const h=e.get(f);d==="bullet"?t.set(w,{type:"bullet"}):t.set(w,{type:"ordered",...h!==void 0&&{start:h}})}return t}function Nt(n){const t=new Map,e=n["word/styles.xml"];if(!e)return t;const r=R(new TextDecoder().decode(e)),i=a(r,"w:styles");if(!i)return t;const o=I(i,"w:style").filter(s=>s.attributes["w:type"]==="paragraph");for(const s of o){const c=s.attributes["w:styleId"];if(!c)continue;const l={styleId:c},u=a(s,"w:name");u?.attributes["w:val"]&&(l.name=u.attributes["w:val"]);const w=a(s,"w:pPr");if(w){const f=a(w,"w:outlineLvl");f?.attributes["w:val"]!==void 0&&(l.outlineLvl=parseInt(f.attributes["w:val"],10))}const p=a(s,"w:rPr");if(p){const f={},d=a(p,"w:color");if(d?.attributes["w:val"]&&d.attributes["w:val"]!=="auto"){const x=d.attributes["w:val"];f.color=x.startsWith("#")?x:`#${x}`}a(p,"w:b")&&(f.bold=!0),a(p,"w:i")&&(f.italic=!0),a(p,"w:u")&&(f.underline=!0),a(p,"w:strike")&&(f.strike=!0);const h=a(p,"w:sz");if(h?.attributes["w:val"]){const x=h.attributes["w:val"],v=parseInt(x,10);isNaN(v)||(f.fontSize=v)}const y=a(p,"w:rFonts");y?.attributes["w:ascii"]&&(f.fontFamily=y.attributes["w:ascii"]),Object.keys(f).length>0&&(l.charFormat=f)}t.set(c,l)}return t}function J(n,t){const e=a(n,"w:t");if(!e)return null;const r=e.children.find(o=>o.type==="text");if(!r?.value)return null;const i=D(n,t);return{type:"text",text:r.value,...i.length&&{marks:i}}}async function T(n,t){const{context:e,styleInfo:r}=t,i=[];for(const o of n.children)if(o.type==="element"){if(o.name==="w:hyperlink"){const s=o,c=s.attributes["r:id"],l=e.hyperlinks.get(c);if(!l)continue;for(const u of s.children){if(u.type!=="element"||u.name!=="w:r")continue;const w=u,p=q(w);if(p){const d=await B(p,{context:e});if(d){i.push(d);continue}const h=await G(p,{context:e});if(h.length){i.push(...h);continue}}const f=J(w,r);f&&(f.marks=f.marks||[],f.marks.push({type:"link",attrs:{href:l}}),i.push(f))}}else if(o.name==="w:r"){const s=o,c=q(s);if(c){const u=await G(c,{context:e});if(u.length){i.push(...u);continue}}if(a(s,"w:br")){const u=D(s,r);i.push({type:"hardBreak",...u.length&&{marks:u}})}const l=J(s,r);l&&i.push(l)}}return i}function D(n,t){const e=[],r=a(n,"w:rPr");let i={};if(t?.charFormat&&(i={...t.charFormat}),r){const o=a(r,"w:b");o&&(o.attributes["w:val"]==="false"?i.bold=!1:i.bold=!0);const s=a(r,"w:i");s&&(s.attributes["w:val"]==="false"?i.italic=!1:i.italic=!0),a(r,"w:u")&&(i.underline=!0),a(r,"w:strike")&&(i.strike=!0);const c=a(r,"w:color");if(c?.attributes["w:val"]&&c.attributes["w:val"]!=="auto"){const f=c.attributes["w:val"];i.color=f.startsWith("#")?f:`#${f}`}const l=a(r,"w:sz");if(l?.attributes["w:val"]){const f=l.attributes["w:val"],d=parseInt(f,10);isNaN(d)||(i.fontSize=d)}const u=a(r,"w:rFonts");u?.attributes["w:ascii"]&&(i.fontFamily=u.attributes["w:ascii"]);const w=a(r,"w:shd");if(w?.attributes["w:fill"]&&w.attributes["w:fill"]!=="auto"){const f=w.attributes["w:fill"];i.backgroundColor=f.startsWith("#")?f:`#${f}`}a(r,"w:highlight")&&e.push({type:"highlight"});const p=a(r,"w:vertAlign");if(p){const f=p.attributes["w:val"];f==="subscript"?e.push({type:"subscript"}):f==="superscript"&&e.push({type:"superscript"})}}if(i.bold&&e.push({type:"bold"}),i.italic&&e.push({type:"italic"}),i.underline&&e.push({type:"underline"}),i.strike&&e.push({type:"strike"}),i.color||i.backgroundColor||i.fontSize||i.fontFamily){const o={color:i.color||"",backgroundColor:i.backgroundColor||"",fontSize:"",fontFamily:"",lineHeight:""};if(i.fontSize){const s=Math.round(i.fontSize/1.5*10)/10;o.fontSize=`${s}px`}i.fontFamily&&(o.fontFamily=i.fontFamily),e.push({type:"textStyle",attrs:o})}return e}function z(n){const t=a(n,"w:pPr");if(!t)return;const e=a(t,"w:jc");if(!e?.attributes["w:val"])return;const r=e.attributes["w:val"],i={left:"left",right:"right",center:"center",both:"justify"}[r];return i?{textAlign:i}:void 0}function K(n){const t=a(n,"w:pPr");if(!t)return null;const e={},r=a(t,"w:ind");if(r){const o=C(r.attributes,"w:left");o&&(e.indentLeft=o);const s=C(r.attributes,"w:right");s&&(e.indentRight=s);const c=C(r.attributes,"w:firstLine");if(c)e.indentFirstLine=c;else{const l=C(r.attributes,"w:hanging");l&&(e.indentFirstLine=`-${l}`)}}const i=a(t,"w:spacing");if(i){const o=C(i.attributes,"w:before");o&&(e.spacingBefore=o);const s=C(i.attributes,"w:after");s&&(e.spacingAfter=s)}return Object.keys(e).length?e:null}async function M(n,t){const{context:e,styleInfo:r}=t,i=a(n,"w:pPr"),o=(i&&a(i,"w:pStyle"))?.attributes["w:val"];if(o&&e.styleMap){const u=e.styleMap.get(o);if(u?.outlineLvl!==void 0&&u.outlineLvl>=0&&u.outlineLvl<=5){const p=u.outlineLvl+1;return Q(n,t,u,p)}const w=o.match(/^Heading(\d+)$/);if(w){const p=parseInt(w[1],10);return Q(n,t,u,p)}}const s=o&&e.styleMap?e.styleMap.get(o):void 0,c=await T(n,{context:e,styleInfo:r||s}),l={...z(n),...K(n)};if(Tt(n)){const u=c.filter(w=>w.type!=="hardBreak");return[{type:"paragraph",...Object.keys(l).length&&{attrs:l},content:u.length?u:void 0},{type:"horizontalRule"}]}if(c.length===1&&c[0].type==="hardBreak"){const u=a(n,"w:r");if((u&&a(u,"w:br"))?.attributes["w:type"]==="page")return{type:"horizontalRule"}}return c.length===1&&c[0].type==="image"?c[0]:{type:"paragraph",...Object.keys(l).length&&{attrs:l},content:c}}function Tt(n){const t=[],e=r=>{if(r.name==="w:r")t.push(r);else for(const i of r.children)i.type==="element"&&e(i)};return e(n),t.some(r=>a(r,"w:br")?.attributes["w:type"]==="page")}async function Q(n,t,e,r){return{type:"heading",attrs:{level:r,...K(n)},content:await T(n,{context:t.context,styleInfo:e})}}function A(n){if(!n)return null;const t=n.attributes["w:val"],e=n.attributes["w:sz"],r=n.attributes["w:color"],i={single:"solid",dashed:"dashed",dotted:"dotted",double:"double",none:"none",nil:"none"},o={};if(r&&r!=="auto"&&(o.color=`#${r}`),e){const s=parseInt(e);isNaN(s)||(o.width=Math.round(s/6))}return t&&i[t]&&(o.style=i[t]),Object.keys(o).length>0?o:null}function At(n){const t={marginTop:void 0,marginBottom:void 0,marginLeft:void 0,marginRight:void 0},e=a(n,"w:tblPr");if(!e)return null;const r=a(e,"w:tblCellMar");if(!r)return null;const i=a(r,"w:top");if(i?.attributes["w:w"]){const l=parseInt(i.attributes["w:w"]);isNaN(l)||(t.marginTop=l)}const o=a(r,"w:bottom");if(o?.attributes["w:w"]){const l=parseInt(o.attributes["w:w"]);isNaN(l)||(t.marginBottom=l)}const s=a(r,"w:left");if(s?.attributes["w:w"]){const l=parseInt(s.attributes["w:w"]);isNaN(l)||(t.marginLeft=l)}const c=a(r,"w:right");if(c?.attributes["w:w"]){const l=parseInt(c.attributes["w:w"]);isNaN(l)||(t.marginRight=l)}return t.marginTop===void 0&&t.marginBottom===void 0&&t.marginLeft===void 0&&t.marginRight===void 0?null:t}function $t(n){const t={rowHeight:null},e=a(n,"w:trPr");if(!e)return t;const r=a(e,"w:trHeight");if(r?.attributes["w:val"]){const i=parseInt(r.attributes["w:val"]),o=O(i);t.rowHeight=`${o}px`}return t}function Y(n){const t={colspan:1,rowspan:1,colwidth:null},e=a(n,"w:tcPr");if(!e)return t;const r=a(e,"w:gridSpan");r?.attributes["w:val"]&&(t.colspan=parseInt(r.attributes["w:val"])),a(e,"w:vMerge")?.attributes["w:val"]==="continue"&&(t.rowspan=0);const i=a(e,"w:tcW");if(i?.attributes["w:w"]){const l=parseInt(i.attributes["w:w"]),u=O(l);t.colwidth=[u]}const o=a(e,"w:shd");o?.attributes["w:fill"]&&(t.backgroundColor=`#${o.attributes["w:fill"]}`);const s=a(e,"w:vAlign");s?.attributes["w:val"]&&(t.verticalAlign=s.attributes["w:val"]);const c=a(e,"w:tcBorders");if(c){const l=A(a(c,"w:top"));l&&(t.borderTop=l);const u=A(a(c,"w:bottom"));u&&(t.borderBottom=u);const w=A(a(c,"w:left"));w&&(t.borderLeft=w);const p=A(a(c,"w:right"));p&&(t.borderRight=p)}return t}function Bt(n){return n.name==="w:tbl"}async function Z(n,t){const e=[];for(const s of n.children)s.type==="element"&&s.name==="w:tr"&&e.push(s);const r=new Map,i=await Promise.all(e.map((s,c)=>Dt(s,{context:t.context,activeRowspans:r,rows:e,rowIndex:c}))),o=At(n);return{type:"table",...o&&{attrs:o},content:i}}async function Dt(n,t){const e=[];let r=0;const i=$t(n);for(const o of n.children){if(o.type!=="element"||o.name!=="w:tc")continue;const s=t.activeRowspans.get(r);if(s&&s>0){t.activeRowspans.set(r,s-1),r++;continue}let c=Y(o);if(c?.rowspan===1){const u=zt({rows:t.rows,rowIndex:t.rowIndex,colIndex:r});u>1&&(c={...c,rowspan:u})}if(c?.rowspan&&c.rowspan>1&&t.activeRowspans.set(r,c.rowspan-1),c?.rowspan===0){r++;continue}const l=await St(o,t);e.push({type:"tableCell",...c&&{attrs:c},content:l}),r+=c?.colspan||1}return{type:"tableRow",...i&&{attrs:i},content:e}}function zt(n){let t=1,e=n.colIndex;for(let r=n.rowIndex+1;r<n.rows.length;r++){const i=n.rows[r];let o=!1;for(const s of i.children){if(s.type!=="element"||s.name!=="w:tc")continue;const c=Y(s),l=c?.colspan||1;if(e>=0&&e<l){if(c?.rowspan===0)t++,o=!0;else return t;break}e-=l}if(!o)break}return t}async function St(n,t){const e=[];for(const r of n.children)if(r.type==="element"&&r.name==="w:p"){const i=await M(r,t);Array.isArray(i)?e.push(...i):e.push(i)}return e.length?e:[{type:"paragraph",content:[]}]}const tt="\u2610",S="\u2611";function et(n){const t=a(n,"w:r");if(!t)return null;const e=a(t,"w:t");if(!e)return null;const r=e.children.find(i=>i.type==="text");return r?.value&&r||null}function W(n){const t=et(n);if(!t)return!1;const e=t.value;return e.startsWith(tt)||e.startsWith(S)}function nt(n){return et(n)?.value.startsWith(S)||!1}async function rt(n,t){return{type:"taskItem",attrs:{checked:nt(n)},content:[await Wt(n,t)]}}async function it(n,t){const{siblings:e,index:r,processedIndices:i}=t,o=[];let s=r;for(;s<e.length;){const c=e[s];if(c.name!=="w:p"||!W(c))break;i.add(s);const l=await rt(c,{context:t.context,styleInfo:t.styleInfo});o.push(l),s++}return{type:"taskList",content:o}}async function Wt(n,t){const{context:e,styleInfo:r}=t,i=await T(n,{context:e,styleInfo:r});if(i.length>0&&i[0].type==="text"){const s=i[0],c=s.text;if(c.startsWith(tt)||c.startsWith(S)){const l=c.substring(2).trimStart();l?s.text=l:i.shift()}}const o=z(n);return{type:"paragraph",...o&&{attrs:o},content:i.length?i:void 0}}function ot(n){const t=a(n,"w:pPr"),e=(t&&a(t,"w:pStyle"))?.attributes["w:val"];return e==="CodeBlock"||e?.startsWith("Code")||!1}function st(n){const t=a(n,"w:pPr"),e=(t&&a(t,"w:pStyle"))?.attributes["w:val"];return e?.startsWith("CodeBlock")&&e.replace("CodeBlock","").toLowerCase()||void 0}function E(n){const t=a(n,"w:pPr");return!!t&&a(t,"w:numPr")!==void 0}function j(n){const t=a(n,"w:pPr"),e=t&&a(t,"w:numPr");if(!e)return null;const r=a(e,"w:ilvl"),i=a(e,"w:numId");return!r||!i?null:{numId:i.attributes["w:val"],level:parseInt(r.attributes["w:val"]||"0",10)}}function at(n){const t=a(n,"w:r");if(!t)return!1;let e=!1,r=!1;for(const i of t.children)i.type==="element"&&(i.name==="w:br"&&i.attributes["w:type"]==="page"?e=!0:i.name==="w:t"?i.children.find(o=>o.type==="text")?.value?.trim().length&&(r=!0):i.name!=="w:rPr"&&(r=!0));return e&&!r}async function Et(n,t={}){const e=await ft(n),r=ut(e),i=Mt(r),o=Ft(r),s=r["word/document.xml"];if(!s)throw new Error("Invalid DOCX file: missing word/document.xml");const c=R(new TextDecoder().decode(s)),l=Pt(r),u=Nt(r),w={enableImageCrop:!1,ignoreEmptyParagraphs:!1,...t,hyperlinks:i,images:o,listTypeMap:l,styleMap:u};return await jt(c,{context:w})}async function jt(n,t){if(n.type!=="root")return{type:"doc",content:[]};const e=a(n,"w:document");if(!e)return{type:"doc",content:[]};const r=a(e,"w:body");return r?{type:"doc",content:await Ot(r.children.filter(i=>i.type==="element"),t)}:{type:"doc",content:[]}}async function Ot(n,t){const e=[],r=new Set;for(let i=0;i<n.length;i++){if(r.has(i))continue;const o=n[i];if(t.context.ignoreEmptyParagraphs&&o.name==="w:p"&&qt(o))continue;const s=await Ut(o,n,i,t,r);Array.isArray(s)?e.push(...s):s&&e.push(s)}return e}async function Ut(n,t,e,r,i){switch(n.name){case"w:tbl":return await Z(n,r);case"w:p":return ot(n)?await Ht(n):W(n)?await it(n,{...r,siblings:t,index:e,processedIndices:i}):E(n)?await _t(n,t,e,r,i):at(n)?{type:"horizontalRule"}:await M(n,r);default:return null}}async function Ht(n){const t=st(n),e=Xt(n);return{type:"codeBlock",...t&&{attrs:{language:t}},content:e}}async function _t(n,t,e,r,i){const o=j(n);if(!o)return await M(n,r);const s=r.context.listTypeMap.get(o.numId),c=s?.type||"bullet",l=[];let u=e;for(;u<t.length;){const p=t[u];if(p.name!=="w:p"||!E(p))break;const f=j(p);if(!f||f.numId!==o.numId)break;i.add(u);const d=await M(p,r),h=Array.isArray(d)?d[0]:d;l.push({type:"listItem",content:[h]}),u++}const w={type:c==="bullet"?"bulletList":"orderedList",content:l};return c==="ordered"&&(w.attrs={type:null,...s?.start!==void 0&&{start:s.start}}),w}function Xt(n){const t=[],e=I(n,"w:r");for(const r of e){const i=a(r,"w:t");if(!i)continue;const o=i.children.find(s=>s.type==="text");o&&"value"in o&&o.value&&t.push({type:"text",text:o.value})}return t}function qt(n){const t=I(n,"w:r");for(const e of t){const r=a(e,"w:t");if(r){const o=r.children.find(s=>s.type==="text");if(o&&"value"in o&&o.value&&o.value.trim().length>0)return!1}if(a(e,"w:drawing")||a(e,"mc:AlternateContent")||a(e,"w:pict"))return!1;const i=a(e,"w:br");if(i&&i.attributes["w:type"]==="page")return!1}return!0}export{M as convertParagraph,Z as convertTable,rt as convertTaskItem,it as convertTaskList,z as extractAlignment,D as extractMarks,T as extractRuns,st as getCodeBlockLanguage,j as getListInfo,nt as getTaskItemChecked,ot as isCodeBlock,at as isHorizontalRule,E as isListItem,Bt as isTable,W as isTaskItem,Et as parseDOCX};
|
|
1
|
+
import{fromXml as F}from"xast-util-from-xml";import{unzipSync as wt}from"fflate";import{toUint8Array as dt}from"undio";import{imageMeta as ht}from"image-meta";const gt=.6666666666666666,N={CODE_BLOCK:"CodeBlock",CODE_PREFIX:"Code"},mt={docxToTipTap:{left:"left",right:"right",center:"center",both:"justify"}},q=96;function z(n){return Math.round(n*q/1440)}function M(n){return`${z(n)}px`}function bt(n){return Math.round(n/(914400/q))}function A(n){const t=parseInt(n,10);if(!isNaN(t))return bt(t)}function a(n,t){if(!n.children)return null;for(const e of n.children)if(e.type==="element"&&e.name===t)return e;return null}function b(n,t){if(!n.children)return null;for(const e of n.children)if(e.type==="element"){if(e.name===t)return e;const r=b(e,t);if(r)return r}return null}function x(n,t){const e=[];if(!n.children)return e;for(const r of n.children)r.type==="element"&&(r.name===t&&e.push(r),e.push(...x(r,t)));return e}function T(n,t){const e=n[t];if(!e)return;const r=parseInt(e,10);if(!isNaN(r))return e}function B(n){return t=>n.includes(t)}const O="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";function G(n){const t=n.length,e=Math.ceil(t/3)*4,r=Array.from({length:e});let i=0;for(let o=0;o<t;o+=3){const s=n[o],c=o+1<t?n[o+1]:0,l=o+2<t?n[o+2]:0,u=s>>2,p=(s&3)<<4|c>>4,w=(c&15)<<2|l>>6,f=l&63;r[i++]=O[u],r[i++]=O[p],r[i++]=o+1<t?O[w]:"=",r[i++]=o+2<t?O[f]:"="}return r.join("")}function yt(n){const t=atob(n),e=new Uint8Array(t.length);for(let r=0;r<t.length;r++)e[r]=t.charCodeAt(r);return e}const vt=globalThis.process?.release?.name==="node",V=typeof window<"u";async function It(n){const t=await n;return t.default||t}let P,J=class{#t=!1;constructor({enableHWA:t=!1}={}){this.#t=t}create(t,e){const r=this._createCanvas(t,e);return{canvas:r,context:r.getContext("2d",{willReadFrequently:!this.#t})}}reset({canvas:t},e,r){if(!t)throw new Error("Canvas is not specified");t.width=e,t.height=r}destroy(t){if(!t.canvas)throw new Error("Canvas is not specified");t.canvas.width=0,t.canvas.height=0,t.canvas=void 0,t.context=void 0}_createCanvas(t,e){throw new Error("Not implemented")}};class xt extends J{_document;constructor({ownerDocument:t=globalThis.document,enableHWA:e=!1}={}){super({enableHWA:e}),this._document=t}_createCanvas(t,e){const r=this._document.createElement("canvas");return r.width=t,r.height=e,r}}class kt extends J{constructor({enableHWA:t=!1}={}){super({enableHWA:t})}_createCanvas(t,e){if(!P)throw new Error("@napi-rs/canvas module is not resolved");return P.createCanvas(t,e)}}async function Ct(n){P??=await It(n())}async function Mt(n){if(V)return xt;if(vt){if(!n)throw new Error("In Node.js environment, @napi-rs/canvas is required for image cropping. Please provide canvasImport parameter or install it: pnpm add @napi-rs/canvas");return await Ct(n),kt}throw new Error("Unsupported environment for canvas operations")}async function Tt(n,t,e={}){if(!t||!t.left&&!t.top&&!t.right&&!t.bottom||e.enabled===!1)return n;try{const r=await Mt(e.canvasImport),i=await Lt(n,r),o=(t.left||0)/1e5*i.width,s=(t.top||0)/1e5*i.height,c=(t.right||0)/1e5*i.width,l=(t.bottom||0)/1e5*i.height,u=Math.round(i.width-o-c),p=Math.round(i.height-s-l);if(u<=0||p<=0)return console.warn("Invalid crop dimensions, returning original image"),n;const w=new r().create(u,p);if(!w.context)throw new Error("Failed to get 2D context from canvas");w.context.drawImage(i,o,s,u,p,0,0,u,p);const f=w.canvas.toDataURL(),d=await(await fetch(f)).arrayBuffer();return new Uint8Array(d)}catch(r){return console.warn("Image cropping failed, returning original image:",r),n}}async function Lt(n,t){if(V){const e=new Blob([n.buffer]),r=URL.createObjectURL(e);try{const i=new Image;return new Promise((o,s)=>{i.onload=()=>{URL.revokeObjectURL(r),o(i)},i.onerror=()=>{URL.revokeObjectURL(r),s(new Error("Failed to load image"))},i.src=r})}catch(i){throw URL.revokeObjectURL(r),i}}else{if(!P)throw new Error("@napi-rs/canvas module is not resolved");return await P.loadImage(Buffer.from(n))}}const Rt="http://schemas.openxmlformats.org/officeDocument/2006/relationships/image",Ft=B(["left","right","center","inside","outside"]),Pt=B(["top","bottom","center","inside","outside"]),$t=B(["page","character","column","margin","leftMargin","rightMargin","insideMargin","outsideMargin"]),Nt=B(["page","paragraph","margin","topMargin","bottomMargin","insideMargin","outsideMargin","line"]);function At(n){const t=n.attributes.l,e=n.attributes.t,r=n.attributes.r,i=n.attributes.b;if(!(!t&&!e&&!r&&!i))return{left:t?parseInt(t,10):void 0,top:e?parseInt(e,10):void 0,right:r?parseInt(r,10):void 0,bottom:i?parseInt(i,10):void 0}}function Bt(n){const t=a(n,"wp:align"),e=a(n,"wp:posOffset");let r;if(t?.children[0]?.type==="text"){const o=t.children[0].value;Ft(o)&&(r=o)}const i=e?.children[0]?.type==="text"?parseInt(e.children[0].value,10):void 0;if(!(!r&&i===void 0))return{...r&&{align:r},...i!==void 0&&{offset:i}}}function Ot(n){const t=a(n,"wp:align"),e=a(n,"wp:posOffset");let r;if(t?.children[0]?.type==="text"){const o=t.children[0].value;Pt(o)&&(r=o)}const i=e?.children[0]?.type==="text"?parseInt(e.children[0].value,10):void 0;if(!(!r&&i===void 0))return{...r&&{align:r},...i!==void 0&&{offset:i}}}function Q(n){let t=a(n,"w:drawing");if(t)return t;const e=a(n,"mc:AlternateContent"),r=e&&a(e,"mc:Choice");return r?a(r,"w:drawing"):null}function Y(n,t,e,r){const i=e/r,o=n/t;return Math.abs(i-o)>.1?i>o?{width:n,height:Math.round(n/i)}:{width:Math.round(t*i),height:t}:{width:n,height:t}}async function Dt(n,t){const e=new Map,r=n["word/_rels/document.xml.rels"];if(!r)return e;const i=F(new TextDecoder().decode(r)),o=a(i,"Relationships");if(!o)return e;const s=x(o,"Relationship");for(const c of s)if(c.attributes.Type===Rt&&c.attributes.Id&&c.attributes.Target){const l="word/"+c.attributes.Target,u=n[l];if(!u)continue;let p,w,f="png";try{const h=ht(u);p=h.width,w=h.height,h.type&&(f=h.type)}catch{}let d;if(t)d=(await t({id:c.attributes.Id,contentType:`image/${f}`,data:u})).src;else{const h=G(u);d=`data:image/${f};base64,${h}`}e.set(c.attributes.Id,{src:d,width:p,height:w})}return e}async function W(n,t){const{context:e}=t,r=b(n,"a:blip");if(!r?.attributes["r:embed"])return null;const i=r.attributes["r:embed"],o=e.images.get(i);if(!o)return null;let s=o.src;const c=b(n,"a:srcRect");if(c){const g=At(c);if(g&&s.startsWith("data:")){const[m,C]=s.split(",");if(C){const L=yt(C);try{const R=await Tt(L,g,{canvasImport:e.image?.canvasImport,enabled:e.image?.enableImageCrop??!1}),S=G(R);s=`${m},${S}`}catch(R){console.warn("Image cropping failed, using original image:",R)}}}}const l=b(n,"wp:extent");let u,p;if(l){const g=l.attributes.cx,m=l.attributes.cy;typeof g=="string"&&(u=A(g)),typeof m=="string"&&(p=A(m))}const w=b(n,"a:xfrm");let f;if(w?.attributes.rot){const g=parseInt(w.attributes.rot,10);isNaN(g)||(f=g/6e4)}const d=b(n,"wp:docPr")?.attributes.title,h=b(n,"wp:positionH"),y=b(n,"wp:positionV");let I;if(h||y){const g=h?Bt(h):void 0,m=y?Ot(y):void 0,C=h?.attributes.relativeFrom,L=y?.attributes.relativeFrom,R=typeof C=="string"&&$t(C)?C:"page",S=typeof L=="string"&&Nt(L)?L:"page";I={horizontalPosition:{relative:R,...g?.align&&{align:g.align},...g?.offset!==void 0&&{offset:g.offset}},verticalPosition:{relative:S,...m?.align&&{align:m.align},...m?.offset!==void 0&&{offset:m.offset}}}}const v=b(n,"pic:spPr");let k;if(v){const g=b(v,"a:ln"),m=g&&b(g,"a:solidFill"),C=m&&b(m,"a:srgbClr");C?.attributes.val&&(k={type:"solidFill",solidFillType:"rgb",value:C.attributes.val})}return{type:"image",attrs:{src:s,alt:"",...u!==void 0&&{width:u},...p!==void 0&&{height:p},...f!==void 0&&{rotation:f},...d&&{title:d},...I&&{floating:I},...k&&{outline:k}}}}function Et(n,t,e){if(t&&e&&n.width&&n.height){const r=Y(t,e,n.width,n.height);return{type:"image",attrs:{src:n.src,alt:"",width:r.width,height:r.height}}}return{type:"image",attrs:{src:n.src,alt:"",...t!==void 0&&{width:t},...e!==void 0&&{height:e}}}}async function Z(n,t){const e=[],r=a(n,"wp:inline")||a(n,"wp:anchor");if(!r)return e;const i=a(r,"wp:extent");let o,s;if(i){const p=i.attributes.cx,w=i.attributes.cy;typeof p=="string"&&(o=A(p)),typeof w=="string"&&(s=A(w))}const c=a(r,"a:graphic");if(!c)return e;const l=a(c,"a:graphicData");if(!l)return e;const u=a(l,"wpg:wgp");if(u){const p=a(u,"wpg:grpSp"),w=p?[...x(p,"pic:pic"),...x(p,"pic")]:[...x(u,"pic:pic"),...x(u,"pic")];for(const f of w){const d=a(f,"a:graphic");if(!d){const v=a(f,"pic:blipFill")||b(f,"a:blipFill");if(!v)continue;const k=a(v,"a:blip")||b(v,"a:blip");if(!k?.attributes["r:embed"])continue;const g=k.attributes["r:embed"],m=t.context.images.get(g);if(!m)continue;e.push(Et(m,o,s));continue}const h={children:[d]},y=await W(h,t);if(!y)continue;const I=h.children[0]?.type==="element"?b(h.children[0],"a:blip")?.attributes["r:embed"]:void 0;if(o&&s&&I){const v=t.context.images.get(I);if(v?.width&&v?.height){const k=Y(o,s,v.width,v.height);y.attrs.width=k.width,y.attrs.height=k.height}else y.attrs.width=o,y.attrs.height=s}e.push(y)}}else{const p=await W(n,t);p&&e.push(p)}return e}const St="http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink";function zt(n){const t=new Map,e=n["word/_rels/document.xml.rels"];if(!e)return t;const r=F(new TextDecoder().decode(e)),i=a(r,"Relationships");if(!i)return t;const o=x(i,"Relationship");for(const s of o)s.attributes.Type===St&&s.attributes.Id&&s.attributes.Target&&t.set(s.attributes.Id,s.attributes.Target);return t}function Wt(n){const t=new Map,e=new Map,r=n["word/numbering.xml"];if(!r)return t;const i=F(new TextDecoder().decode(r)),o=new Map,s=a(i,"w:numbering");if(!s)return t;const c=x(s,"w:abstractNum");for(const u of c){const p=u.attributes["w:abstractNumId"],w=a(u,"w:lvl");if(!w)continue;const f=a(w,"w:numFmt");f?.attributes["w:val"]&&o.set(p,f.attributes["w:val"]);const d=a(w,"w:start");d?.attributes["w:val"]&&e.set(p,parseInt(d.attributes["w:val"],10))}const l=x(s,"w:num");for(const u of l){const p=u.attributes["w:numId"],w=a(u,"w:abstractNumId");if(!w?.attributes["w:val"])continue;const f=w.attributes["w:val"],d=o.get(f);if(!d)continue;const h=e.get(f);d==="bullet"?t.set(p,{type:"bullet"}):t.set(p,{type:"ordered",...h!==void 0&&{start:h}})}return t}function _t(n){const t=new Map,e=n["word/styles.xml"];if(!e)return t;const r=F(new TextDecoder().decode(e)),i=a(r,"w:styles");if(!i)return t;const o=x(i,"w:style").filter(s=>s.attributes["w:type"]==="paragraph");for(const s of o){const c=s.attributes["w:styleId"];if(!c)continue;const l={styleId:c},u=a(s,"w:name");u?.attributes["w:val"]&&(l.name=u.attributes["w:val"]);const p=a(s,"w:pPr");if(p){const f=a(p,"w:outlineLvl");f?.attributes["w:val"]!==void 0&&(l.outlineLvl=parseInt(f.attributes["w:val"],10))}const w=a(s,"w:rPr");if(w){const f={},d=a(w,"w:color");if(d?.attributes["w:val"]&&d.attributes["w:val"]!=="auto"){const I=d.attributes["w:val"];f.color=I.startsWith("#")?I:`#${I}`}a(w,"w:b")&&(f.bold=!0),a(w,"w:i")&&(f.italic=!0),a(w,"w:u")&&(f.underline=!0),a(w,"w:strike")&&(f.strike=!0);const h=a(w,"w:sz");if(h?.attributes["w:val"]){const I=h.attributes["w:val"],v=parseInt(I,10);isNaN(v)||(f.fontSize=v)}const y=a(w,"w:rFonts");y?.attributes["w:ascii"]&&(f.fontFamily=y.attributes["w:ascii"]),Object.keys(f).length>0&&(l.charFormat=f)}t.set(c,l)}return t}function tt(n,t){const e=a(n,"w:t");if(!e)return null;const r=e.children.find(o=>o.type==="text");if(!r?.value)return null;const i=_(n,t);return{type:"text",text:r.value,...i.length&&{marks:i}}}async function D(n,t){const{context:e,styleInfo:r}=t,i=[];for(const o of n.children)if(o.type==="element"){if(o.name==="w:hyperlink"){const s=o,c=s.attributes["r:id"],l=e.hyperlinks.get(c);if(!l)continue;for(const u of s.children){if(u.type!=="element"||u.name!=="w:r")continue;const p=u,w=Q(p);if(w){const d=await W(w,{context:e});if(d){i.push(d);continue}const h=await Z(w,{context:e});if(h.length){i.push(...h);continue}}const f=tt(p,r);f&&(f.marks=f.marks||[],f.marks.push({type:"link",attrs:{href:l}}),i.push(f))}}else if(o.name==="w:r"){const s=o,c=Q(s);if(c){const u=await Z(c,{context:e});if(u.length){i.push(...u);continue}}if(a(s,"w:br")){const u=_(s,r);i.push({type:"hardBreak",...u.length&&{marks:u}})}const l=tt(s,r);l&&i.push(l)}}return i}function _(n,t){const e=[],r=a(n,"w:rPr");let i={};if(t?.charFormat&&(i={...t.charFormat}),r){const o=a(r,"w:b");o&&(o.attributes["w:val"]==="false"?i.bold=!1:i.bold=!0);const s=a(r,"w:i");s&&(s.attributes["w:val"]==="false"?i.italic=!1:i.italic=!0),a(r,"w:u")&&(i.underline=!0),a(r,"w:strike")&&(i.strike=!0);const c=a(r,"w:color");if(c?.attributes["w:val"]&&c.attributes["w:val"]!=="auto"){const f=c.attributes["w:val"];i.color=f.startsWith("#")?f:`#${f}`}const l=a(r,"w:sz");if(l?.attributes["w:val"]){const f=l.attributes["w:val"],d=parseInt(f,10);isNaN(d)||(i.fontSize=d)}const u=a(r,"w:rFonts");u?.attributes["w:ascii"]&&(i.fontFamily=u.attributes["w:ascii"]);const p=a(r,"w:shd");if(p?.attributes["w:fill"]&&p.attributes["w:fill"]!=="auto"){const f=p.attributes["w:fill"];i.backgroundColor=f.startsWith("#")?f:`#${f}`}a(r,"w:highlight")&&e.push({type:"highlight"});const w=a(r,"w:vertAlign");if(w){const f=w.attributes["w:val"];f==="subscript"?e.push({type:"subscript"}):f==="superscript"&&e.push({type:"superscript"})}}if(i.bold&&e.push({type:"bold"}),i.italic&&e.push({type:"italic"}),i.underline&&e.push({type:"underline"}),i.strike&&e.push({type:"strike"}),i.color||i.backgroundColor||i.fontSize||i.fontFamily){const o={color:i.color||"",backgroundColor:i.backgroundColor||"",fontSize:"",fontFamily:"",lineHeight:""};if(i.fontSize){const s=Math.round(i.fontSize*gt*10)/10;o.fontSize=`${s}px`}i.fontFamily&&(o.fontFamily=i.fontFamily),e.push({type:"textStyle",attrs:o})}return e}function j(n){const t=a(n,"w:pPr");if(!t)return;const e=a(t,"w:jc");if(!e?.attributes["w:val"])return;const r=e.attributes["w:val"],i=mt.docxToTipTap[r];return i?{textAlign:i}:void 0}function et(n){const t=a(n,"w:pPr");if(!t)return null;const e={},r=a(t,"w:ind");if(r){const o=T(r.attributes,"w:left");if(o){const l=parseInt(o,10);e.indentLeft=M(l)}const s=T(r.attributes,"w:right");if(s){const l=parseInt(s,10);e.indentRight=M(l)}const c=T(r.attributes,"w:firstLine");if(c){const l=parseInt(c,10);e.indentFirstLine=M(l)}else{const l=T(r.attributes,"w:hanging");if(l){const u=o?parseInt(o,10):0,p=parseInt(l,10),w=u-p;e.indentFirstLine=M(w)}}}const i=a(t,"w:spacing");if(i){const o=T(i.attributes,"w:before");if(o){const c=parseInt(o,10);e.spacingBefore=M(c)}const s=T(i.attributes,"w:after");if(s){const c=parseInt(s,10);e.spacingAfter=M(c)}}return Object.keys(e).length?e:null}async function $(n,t){const{context:e,styleInfo:r}=t,i=a(n,"w:pPr"),o=(i&&a(i,"w:pStyle"))?.attributes["w:val"];if(o&&e.styleMap){const u=e.styleMap.get(o);if(u?.outlineLvl!==void 0&&u.outlineLvl>=0&&u.outlineLvl<=5){const w=u.outlineLvl+1;return nt(n,t,u,w)}const p=o.match(/^Heading(\d+)$/);if(p){const w=parseInt(p[1],10);return nt(n,t,u,w)}}const s=o&&e.styleMap?e.styleMap.get(o):void 0,c=await D(n,{context:e,styleInfo:r||s}),l={...j(n),...et(n)};if(jt(n)){const u=c.filter(p=>p.type!=="hardBreak");return[{type:"paragraph",...Object.keys(l).length&&{attrs:l},content:u.length?u:void 0},{type:"horizontalRule"}]}if(c.length===1&&c[0].type==="hardBreak"){const u=a(n,"w:r");if((u&&a(u,"w:br"))?.attributes["w:type"]==="page")return{type:"horizontalRule"}}if(c.length===1&&c[0].type==="image"){const u=c[0];return{type:"paragraph",...Object.keys(l).length&&{attrs:l},content:[u]}}return{type:"paragraph",...Object.keys(l).length&&{attrs:l},content:c}}function jt(n){const t=[],e=r=>{if(r.name==="w:r")t.push(r);else for(const i of r.children)i.type==="element"&&e(i)};return e(n),t.some(r=>a(r,"w:br")?.attributes["w:type"]==="page")}async function nt(n,t,e,r){return{type:"heading",attrs:{level:r,...et(n)},content:await D(n,{context:t.context,styleInfo:e})}}function E(n){if(!n)return null;const t=n.attributes["w:val"],e=n.attributes["w:sz"],r=n.attributes["w:color"],i={single:"solid",dashed:"dashed",dotted:"dotted",double:"double",none:"none",nil:"none"},o={};if(r&&r!=="auto"&&(o.color=`#${r}`),e){const s=parseInt(e);isNaN(s)||(o.width=Math.round(s/6))}return t&&i[t]&&(o.style=i[t]),Object.keys(o).length>0?o:null}function Ht(n){const t={marginTop:void 0,marginBottom:void 0,marginLeft:void 0,marginRight:void 0},e=a(n,"w:tblPr");if(!e)return null;const r=a(e,"w:tblCellMar");if(!r)return null;const i=a(r,"w:top");if(i?.attributes["w:w"]){const l=parseInt(i.attributes["w:w"]);isNaN(l)||(t.marginTop=l)}const o=a(r,"w:bottom");if(o?.attributes["w:w"]){const l=parseInt(o.attributes["w:w"]);isNaN(l)||(t.marginBottom=l)}const s=a(r,"w:left");if(s?.attributes["w:w"]){const l=parseInt(s.attributes["w:w"]);isNaN(l)||(t.marginLeft=l)}const c=a(r,"w:right");if(c?.attributes["w:w"]){const l=parseInt(c.attributes["w:w"]);isNaN(l)||(t.marginRight=l)}return t.marginTop===void 0&&t.marginBottom===void 0&&t.marginLeft===void 0&&t.marginRight===void 0?null:t}function Ut(n){const t={rowHeight:null},e=a(n,"w:trPr");if(!e)return t;const r=a(e,"w:trHeight");if(r?.attributes["w:val"]){const i=parseInt(r.attributes["w:val"]),o=z(i);t.rowHeight=`${o}px`}return t}function rt(n){const t={colspan:1,rowspan:1,colwidth:null},e=a(n,"w:tcPr");if(!e)return t;const r=a(e,"w:gridSpan");r?.attributes["w:val"]&&(t.colspan=parseInt(r.attributes["w:val"])),a(e,"w:vMerge")?.attributes["w:val"]==="continue"&&(t.rowspan=0);const i=a(e,"w:tcW");if(i?.attributes["w:w"]){const l=parseInt(i.attributes["w:w"]),u=z(l);t.colwidth=[u]}const o=a(e,"w:shd");o?.attributes["w:fill"]&&(t.backgroundColor=`#${o.attributes["w:fill"]}`);const s=a(e,"w:vAlign");s?.attributes["w:val"]&&(t.verticalAlign=s.attributes["w:val"]);const c=a(e,"w:tcBorders");if(c){const l=E(a(c,"w:top"));l&&(t.borderTop=l);const u=E(a(c,"w:bottom"));u&&(t.borderBottom=u);const p=E(a(c,"w:left"));p&&(t.borderLeft=p);const w=E(a(c,"w:right"));w&&(t.borderRight=w)}return t}function Xt(n){return n.name==="w:tbl"}async function it(n,t){const e=[];for(const s of n.children)s.type==="element"&&s.name==="w:tr"&&e.push(s);const r=new Map,i=await Promise.all(e.map((s,c)=>Kt(s,{context:t.context,activeRowspans:r,rows:e,rowIndex:c}))),o=Ht(n);return{type:"table",...o&&{attrs:o},content:i}}async function Kt(n,t){const e=[];let r=0;const i=Ut(n);for(const o of n.children){if(o.type!=="element"||o.name!=="w:tc")continue;const s=t.activeRowspans.get(r);if(s&&s>0){t.activeRowspans.set(r,s-1),r++;continue}let c=rt(o);if(c?.rowspan===1){const u=qt({rows:t.rows,rowIndex:t.rowIndex,colIndex:r});u>1&&(c={...c,rowspan:u})}if(c?.rowspan&&c.rowspan>1&&t.activeRowspans.set(r,c.rowspan-1),c?.rowspan===0){r++;continue}const l=await Gt(o,t);e.push({type:"tableCell",...c&&{attrs:c},content:l}),r+=c?.colspan||1}return{type:"tableRow",...i&&{attrs:i},content:e}}function qt(n){let t=1,e=n.colIndex;for(let r=n.rowIndex+1;r<n.rows.length;r++){const i=n.rows[r];let o=!1;for(const s of i.children){if(s.type!=="element"||s.name!=="w:tc")continue;const c=rt(s),l=c?.colspan||1;if(e>=0&&e<l){if(c?.rowspan===0)t++,o=!0;else return t;break}e-=l}if(!o)break}return t}async function Gt(n,t){const e=[];for(const r of n.children)if(r.type==="element"&&r.name==="w:p"){const i=await $(r,t);Array.isArray(i)?e.push(...i):e.push(i)}return e.length?e:[{type:"paragraph",content:[]}]}const ot="\u2610",H="\u2611";function st(n){const t=a(n,"w:r");if(!t)return null;const e=a(t,"w:t");if(!e)return null;const r=e.children.find(i=>i.type==="text");return r?.value&&r||null}function U(n){const t=st(n);if(!t)return!1;const e=t.value;return e.startsWith(ot)||e.startsWith(H)}function at(n){return st(n)?.value.startsWith(H)||!1}async function ct(n,t){return{type:"taskItem",attrs:{checked:at(n)},content:[await Vt(n,t)]}}async function lt(n,t){const{siblings:e,index:r,processedIndices:i}=t,o=[];let s=r;for(;s<e.length;){const c=e[s];if(c.name!=="w:p"||!U(c))break;i.add(s);const l=await ct(c,{context:t.context,styleInfo:t.styleInfo});o.push(l),s++}return{type:"taskList",content:o}}async function Vt(n,t){const{context:e,styleInfo:r}=t,i=await D(n,{context:e,styleInfo:r});if(i.length>0&&i[0].type==="text"){const s=i[0],c=s.text;if(c.startsWith(ot)||c.startsWith(H)){const l=c.substring(2).trimStart();l?s.text=l:i.shift()}}const o=j(n);return{type:"paragraph",...o&&{attrs:o},content:i.length?i:void 0}}function ut(n){const t=a(n,"w:pPr"),e=(t&&a(t,"w:pStyle"))?.attributes["w:val"];return e===N.CODE_BLOCK||e?.startsWith(N.CODE_PREFIX)||!1}function ft(n){const t=a(n,"w:pPr"),e=(t&&a(t,"w:pStyle"))?.attributes["w:val"];return e?.startsWith(N.CODE_BLOCK)&&e.replace(N.CODE_BLOCK,"").toLowerCase()||void 0}function X(n){const t=a(n,"w:pPr");return!!t&&a(t,"w:numPr")!==void 0}function K(n){const t=a(n,"w:pPr"),e=t&&a(t,"w:numPr");if(!e)return null;const r=a(e,"w:ilvl"),i=a(e,"w:numId");return!r||!i?null:{numId:i.attributes["w:val"],level:parseInt(r.attributes["w:val"]||"0",10)}}function pt(n){const t=a(n,"w:r");if(!t)return!1;let e=!1,r=!1;for(const i of t.children)i.type==="element"&&(i.name==="w:br"&&i.attributes["w:type"]==="page"?e=!0:i.name==="w:t"?i.children.find(o=>o.type==="text")?.value?.trim().length&&(r=!0):i.name!=="w:rPr"&&(r=!0));return e&&!r}async function Jt(n,t={}){const e=await dt(n),r=wt(e),i=zt(r),o=await Dt(r,t.image?.handler),s=r["word/document.xml"];if(!s)throw new Error("Invalid DOCX file: missing word/document.xml");const c=F(new TextDecoder().decode(s)),l=Wt(r),u=_t(r),p={...t,hyperlinks:i,images:o,listTypeMap:l,styleMap:u};return await Qt(c,{context:p})}async function Qt(n,t){if(n.type!=="root")return{type:"doc",content:[]};const e=a(n,"w:document");if(!e)return{type:"doc",content:[]};const r=a(e,"w:body");return r?{type:"doc",content:await Yt(r.children.filter(i=>i.type==="element"),t)}:{type:"doc",content:[]}}async function Yt(n,t){const e=[],r=new Set;for(let i=0;i<n.length;i++){if(r.has(i))continue;const o=n[i];if(t.context.ignoreEmptyParagraphs&&o.name==="w:p"&&re(o))continue;const s=await Zt(o,n,i,t,r);Array.isArray(s)?e.push(...s):s&&e.push(s)}return e}async function Zt(n,t,e,r,i){switch(n.name){case"w:tbl":return await it(n,r);case"w:p":return ut(n)?await te(n):U(n)?await lt(n,{...r,siblings:t,index:e,processedIndices:i}):X(n)?await ee(n,t,e,r,i):pt(n)?{type:"horizontalRule"}:await $(n,r);default:return null}}async function te(n){const t=ft(n),e=ne(n);return{type:"codeBlock",...t&&{attrs:{language:t}},content:e}}async function ee(n,t,e,r,i){const o=K(n);if(!o)return await $(n,r);const s=r.context.listTypeMap.get(o.numId),c=s?.type||"bullet",l=[];let u=e;for(;u<t.length;){const w=t[u];if(w.name!=="w:p"||!X(w))break;const f=K(w);if(!f||f.numId!==o.numId)break;i.add(u);const d=await $(w,r),h=Array.isArray(d)?d[0]:d;l.push({type:"listItem",content:[h]}),u++}const p={type:c==="bullet"?"bulletList":"orderedList",content:l};return c==="ordered"&&(p.attrs={type:null,...s?.start!==void 0&&{start:s.start}}),p}function ne(n){const t=[],e=x(n,"w:r");for(const r of e){const i=a(r,"w:t");if(!i)continue;const o=i.children.find(s=>s.type==="text");o&&"value"in o&&o.value&&t.push({type:"text",text:o.value})}return t}function re(n){const t=x(n,"w:r");for(const e of t){const r=a(e,"w:t");if(r){const o=r.children.find(s=>s.type==="text");if(o&&"value"in o&&o.value&&o.value.trim().length>0)return!1}if(a(e,"w:drawing")||a(e,"mc:AlternateContent")||a(e,"w:pict"))return!1;const i=a(e,"w:br");if(i&&i.attributes["w:type"]==="page")return!1}return!0}export{$ as convertParagraph,it as convertTable,ct as convertTaskItem,lt as convertTaskList,j as extractAlignment,_ as extractMarks,D as extractRuns,ft as getCodeBlockLanguage,K as getListInfo,at as getTaskItemChecked,ut as isCodeBlock,pt as isHorizontalRule,X as isListItem,Xt as isTable,U as isTaskItem,Jt as parseDOCX};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@docen/import-docx",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.10",
|
|
4
4
|
"description": "A powerful TipTap/ProseMirror extension that imports Microsoft Word DOCX files to editor content",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"converter",
|
|
@@ -50,10 +50,10 @@
|
|
|
50
50
|
"xast-util-from-xml": "4.0.0"
|
|
51
51
|
},
|
|
52
52
|
"devDependencies": {
|
|
53
|
-
"@tiptap/core": "3.
|
|
53
|
+
"@tiptap/core": "3.19.0",
|
|
54
54
|
"@types/xast": "2.0.4",
|
|
55
|
-
"@docen/extensions": "0.0.
|
|
56
|
-
"@docen/utils": "0.0.
|
|
55
|
+
"@docen/extensions": "0.0.10",
|
|
56
|
+
"@docen/utils": "0.0.10"
|
|
57
57
|
},
|
|
58
58
|
"peerDependencies": {
|
|
59
59
|
"@napi-rs/canvas": "^0.1.88"
|
|
@@ -64,7 +64,7 @@
|
|
|
64
64
|
}
|
|
65
65
|
},
|
|
66
66
|
"optionalDependencies": {
|
|
67
|
-
"@napi-rs/canvas": "^0.1.
|
|
67
|
+
"@napi-rs/canvas": "^0.1.91"
|
|
68
68
|
},
|
|
69
69
|
"scripts": {
|
|
70
70
|
"dev": "unbuild --stub",
|