docx-make-pdf 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.MD +133 -0
- package/build-vfs.js +24 -0
- package/index.d.ts +34 -0
- package/index.js +1 -0
- package/package.json +25 -0
- package/vfs_fonts.js +3 -0
package/README.MD
ADDED
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
# docx-make-pdf
|
|
2
|
+
|
|
3
|
+
在后端(nodeJs环境)将docx文档转换为pdf。搭配docx-template可以实现生成订单。
|
|
4
|
+
|
|
5
|
+
**步骤原理:**
|
|
6
|
+
|
|
7
|
+
1. 通过[docx-preview](https://github.com/VolodymyrBaydalka/docxjs)的node修改版[docx-preview-node](https://github.com/ifeda/docx-preview-node)先转换为html
|
|
8
|
+
|
|
9
|
+
2. 再通过[html-to-pdfmake](https://github.com/Aymkdn/html-to-pdfmake)(基于源码修改)转换为pdfmake的docDefinition
|
|
10
|
+
|
|
11
|
+
3. 然后通过[pdfmake](https://www.npmjs.com/package/pdfmake)输出为pdf文件
|
|
12
|
+
|
|
13
|
+
**优点:**
|
|
14
|
+
|
|
15
|
+
1. 不需要操作系统安装依赖,纯js代码
|
|
16
|
+
|
|
17
|
+
2. 支持输出buffer方便后续通过Node-SignPDF等模块加数字签名
|
|
18
|
+
|
|
19
|
+
3. 支持多页输出,支持识别word分页符
|
|
20
|
+
|
|
21
|
+
4. 异步模式Promise
|
|
22
|
+
|
|
23
|
+
5. Typescript友好
|
|
24
|
+
|
|
25
|
+
**缺点:**
|
|
26
|
+
|
|
27
|
+
1. 不支持word文件既包含纵向页面也包含横向页面
|
|
28
|
+
|
|
29
|
+
2. 不支持word文本框、图表
|
|
30
|
+
|
|
31
|
+
3. 宽度(如表格)适应不是很精确,无法精确地水平居中(所以尽量不要使用带边框的表格)
|
|
32
|
+
|
|
33
|
+
4. 不能使用系统自带字体,必须自己加工vfs字体文件
|
|
34
|
+
|
|
35
|
+
5. 集成了思源宋体,所以包比较大
|
|
36
|
+
|
|
37
|
+
## 安装
|
|
38
|
+
|
|
39
|
+
`npm install -S docx-make-pdf`
|
|
40
|
+
|
|
41
|
+
## 使用
|
|
42
|
+
|
|
43
|
+
```typescript
|
|
44
|
+
import docx2pdf from "docx-make-pdf"
|
|
45
|
+
docx2pdf({
|
|
46
|
+
docxFile:string, //docx文件路径,绝对路径
|
|
47
|
+
docxBuffer:Buffer, //docx文件内容
|
|
48
|
+
},{
|
|
49
|
+
pageSize?: PageSize | undefined; //页面大小,默认A4
|
|
50
|
+
pageOrientation?: "portrait" | "landscape"; // 页面方向,默认纵向 portrait
|
|
51
|
+
pageMargin?: pageMargin | undefined; // 页边距,默认1.27厘米(36pt)
|
|
52
|
+
version?: PDFVersion | undefined; // pdf版本,默认1.7
|
|
53
|
+
watermark?: string | Watermark | undefined; // 页面水印
|
|
54
|
+
language?: string | undefined; //页面语言,默认zh-cn
|
|
55
|
+
vfs?: { [filename: string]: string }; // 自定义字体数据(如果设置要自己require加载哦),注意这里的filename是fonts中normal、bold、italics、bolditalics对应的filename
|
|
56
|
+
fonts?: TFontDictionary; //自定义字体定义,参考build-vfs.js
|
|
57
|
+
defaultFont?: string; // 默认字体名称,默认SourceHanSerifCN (思源宋体)
|
|
58
|
+
}):{
|
|
59
|
+
toFile: (filename: string) => Promise<string>; //写入文件名
|
|
60
|
+
toBuffer: () => Promise<Buffer>; // Buffer 生成的pdf文件内容数据
|
|
61
|
+
toStream: () => Promise<NodeJS.ReadableStream>; // 可以自定义pipe输出
|
|
62
|
+
}
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
## 字体的制作
|
|
66
|
+
|
|
67
|
+
因为字体面临版权问题,所以pdfmake没有内置字体,也没有读取计算机/服务器上已经安装的字体,所以需要您自己制作已经获取版权的字体数据并加载。
|
|
68
|
+
|
|
69
|
+
docx-make-pdf内置了开源免费商用的思源宋体,如果您要添加字体,必须先加工vfs,然后定义字体名称和文件名对应关系。因为pdfmake说明较少,很多人容易糊涂,所以这里详细说明一下:
|
|
70
|
+
|
|
71
|
+
1. **加工vfs**
|
|
72
|
+
|
|
73
|
+
生成pdfmake所能识别的字体源数据,原理是将ttf字体通过base64编码加工成vfs;建议最好用ttf字体,otf字体和ttc字体我试验没成功;java压缩过的字体也有些问题,会出现无法识别的字符(似乎是空格);
|
|
74
|
+
|
|
75
|
+
`node build-vfs.js <path> [filename]`
|
|
76
|
+
|
|
77
|
+
参数说明:
|
|
78
|
+
|
|
79
|
+
- path: 字体所在目录,必须放在一个目录中,不支持子目录
|
|
80
|
+
|
|
81
|
+
- filename: 存储vfs数据的文件,默认是build/vfs_fonts.js
|
|
82
|
+
|
|
83
|
+
docx-make-pdf的package.json中内置了script可以参考下: `node build-vfs.js ./fonts ./src/vfs_fonts.js`
|
|
84
|
+
|
|
85
|
+
**加载使用:**
|
|
86
|
+
|
|
87
|
+
```javascript
|
|
88
|
+
const vfs_fonts = require("./vfs_fonts.js")
|
|
89
|
+
docx2pdf({docxBuffer},{vfs:vfs_fonts})
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
2. **定义字体名称和文件名对应关系**
|
|
93
|
+
|
|
94
|
+
要使用vfs还必须按照如下格式定义字体:
|
|
95
|
+
|
|
96
|
+
```typescript
|
|
97
|
+
fontFaceName:string {
|
|
98
|
+
"normal": filename:string,
|
|
99
|
+
"bold": filename:string,
|
|
100
|
+
"italics": filename:string,
|
|
101
|
+
"bolditalics": filename:string
|
|
102
|
+
}
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
注意:必须定义 normal、bold、italics、bolditalics 四种样式,否则pdfmake会报错;如果字体没有这些样式,可以引用其他样式字体文件名,例如:
|
|
106
|
+
|
|
107
|
+
```javascript
|
|
108
|
+
"SourceHanSerifCN": {
|
|
109
|
+
"normal": "SourceHanSerifCN-Regular.ttf",
|
|
110
|
+
"bold": "SourceHanSerifCN-Regular.ttf",
|
|
111
|
+
"italics": "SourceHanSerifCN-Regular.ttf",
|
|
112
|
+
"bolditalics": "SourceHanSerifCN-Regular.ttf"
|
|
113
|
+
}
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
SourceHanSerifCN 就是字体名称,比如:"宋体" "simsun"
|
|
117
|
+
|
|
118
|
+
SourceHanSerifCN-Regular.ttf 这就是字体文件名(不需要带路径),必须和第一步加工vfs时一致(大小写敏感)
|
|
119
|
+
|
|
120
|
+
**加载使用:**
|
|
121
|
+
|
|
122
|
+
```typescript
|
|
123
|
+
docx2pdf({docxBuffer},{fonts:{
|
|
124
|
+
fontFaceName:string {
|
|
125
|
+
"normal": filename:string,
|
|
126
|
+
"bold": filename:string,
|
|
127
|
+
"italics": filename:string,
|
|
128
|
+
"bolditalics": filename:string
|
|
129
|
+
}
|
|
130
|
+
}})
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
提示:即时自定义了vfs和fonts也不会覆盖docx2pdf内置的“SourceHanSerifCN"和pdfmake内置的"Roboto"(没有Roboto会报错)
|
package/build-vfs.js
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 因为字体面临版权问题,所以pdfmake没有内置字体,也没有读取计算机/服务器上已经安装的字体,所以需要您自己制作已经获取版权的字体数据并加载
|
|
3
|
+
* docx2pdf内置了开源免费商用的思源宋体,如果您要添加字体,必须先加工vfs,然后定义字体名称和文件名对应关系
|
|
4
|
+
*
|
|
5
|
+
* 1、加工vfs:
|
|
6
|
+
* 生成pdfmake所能识别的字体源数据,原理是将ttf字体通过base64编码加工成vfs;最好用ttf字体,otf字体和ttc字体我试验没成功;java压缩过的字体也有些问题,会出现无法识别的字符(似乎是空格);
|
|
7
|
+
* `node build-vfs.js <path> [filename]`
|
|
8
|
+
* 参数:
|
|
9
|
+
* path: 字体所在目录,必须放在一个目录中,不支持子目录
|
|
10
|
+
* filename: 存储vfs数据的文件,默认是build/vfs_fonts.js
|
|
11
|
+
*
|
|
12
|
+
* 2、定义字体名称和文件名对应关系
|
|
13
|
+
* 要使用vfs还必须按照如下格式定义字体
|
|
14
|
+
* "simsun": {
|
|
15
|
+
"normal": "SourceHanSerifCN-Regular.ttf",
|
|
16
|
+
"bold": "SourceHanSerifCN-Regular.ttf",
|
|
17
|
+
"italics": "SourceHanSerifCN-Regular.ttf",
|
|
18
|
+
"bolditalics": "SourceHanSerifCN-Regular.ttf"
|
|
19
|
+
}
|
|
20
|
+
* SourceHanSerifCN 就是字体名称,比如:"宋体" "simsun"
|
|
21
|
+
还必须定义 normal、bold、italics、bolditalics 四种样式,如果字体没有这些样式,可以引用其他样式字体文件名
|
|
22
|
+
SourceHanSerifCN-Regular.ttf 这就是字体文件名(不需要带路径),必须和第一步加工vfs时一致(大小写敏感)
|
|
23
|
+
*/
|
|
24
|
+
require("pdfmake/build-vfs.js")
|
package/index.d.ts
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { PageSize, PDFVersion, Watermark, TFontDictionary } from 'pdfmake/interfaces';
|
|
2
|
+
|
|
3
|
+
type pageMargin = {
|
|
4
|
+
top: `${number}${"px" | "cm" | "mm"}`;
|
|
5
|
+
right: `${number}${"px" | "cm" | "mm"}`;
|
|
6
|
+
bottom: `${number}${"px" | "cm" | "mm"}`;
|
|
7
|
+
left: `${number}${"px" | "cm" | "mm"}`;
|
|
8
|
+
};
|
|
9
|
+
type Input = {
|
|
10
|
+
docxFile?: string;
|
|
11
|
+
docxBuffer?: Buffer;
|
|
12
|
+
};
|
|
13
|
+
type InputOptions = {
|
|
14
|
+
pageSize?: PageSize | undefined;
|
|
15
|
+
pageOrientation?: "portrait" | "landscape";
|
|
16
|
+
pageMargin?: pageMargin | undefined;
|
|
17
|
+
version?: PDFVersion | undefined;
|
|
18
|
+
watermark?: string | Watermark | undefined;
|
|
19
|
+
language?: string | undefined;
|
|
20
|
+
vfs?: {
|
|
21
|
+
[filename: string]: string;
|
|
22
|
+
};
|
|
23
|
+
fonts?: TFontDictionary;
|
|
24
|
+
defaultFont?: string;
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
type Result = {
|
|
28
|
+
toFile: (filename: string) => Promise<string>;
|
|
29
|
+
toBuffer: () => Promise<Buffer>;
|
|
30
|
+
toStream: () => Promise<NodeJS.ReadableStream>;
|
|
31
|
+
};
|
|
32
|
+
declare function docx2pdf({ docxFile, docxBuffer }: Input, options?: InputOptions): Promise<Result>;
|
|
33
|
+
|
|
34
|
+
export { docx2pdf as default };
|
package/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";var e=require("docx-preview-node"),t=require("jsdom"),a=require("pdfmake/build/pdfmake"),r=require("pdfmake/build/vfs_fonts");function i(e){return e&&e.__esModule?e:{default:e}}var o=i(a),s=i(r),n=Object.defineProperty,l=(e,t)=>n(e,"name",{value:t,configurable:!0}),c=(e=>"undefined"!=typeof require?require:"undefined"!=typeof Proxy?new Proxy(e,{get:(e,t)=>("undefined"!=typeof require?require:e)[t]}):e)(function(e){if("undefined"!=typeof require)return require.apply(this,arguments);throw Error('Dynamic require of "'+e+'" is not supported')}),h={Roboto:{normal:"Roboto-Regular.ttf",bold:"Roboto-Medium.ttf",italics:"Roboto-Italic.ttf",bolditalics:"Roboto-MediumItalic.ttf"},SourceHanSerifCN:{normal:"SourceHanSerifCN-Regular.ttf",bold:"SourceHanSerifCN-Regular.ttf",italics:"SourceHanSerifCN-Regular.ttf",bolditalics:"SourceHanSerifCN-Regular.ttf"}},d={"4A0":[4767.87,6740.79],"2A0":[3370.39,4767.87],A0:[2383.94,3370.39],A1:[1683.78,2383.94],A2:[1190.55,1683.78],A3:[841.89,1190.55],A4:[595.28,841.89],A5:[419.53,595.28],A6:[297.64,419.53],A7:[209.76,297.64],A8:[147.4,209.76],A9:[104.88,147.4],A10:[73.7,104.88],B0:[2834.65,4008.19],B1:[2004.09,2834.65],B2:[1417.32,2004.09],B3:[1000.63,1417.32],B4:[708.66,1000.63],B5:[498.9,708.66],B6:[354.33,498.9],B7:[249.45,354.33],B8:[175.75,249.45],B9:[124.72,175.75],B10:[87.87,124.72],C0:[2599.37,3676.54],C1:[1836.85,2599.37],C2:[1298.27,1836.85],C3:[918.43,1298.27],C4:[649.13,918.43],C5:[459.21,649.13],C6:[323.15,459.21],C7:[229.61,323.15],C8:[161.57,229.61],C9:[113.39,161.57],C10:[79.37,113.39],RA0:[2437.8,3458.27],RA1:[1729.13,2437.8],RA2:[1218.9,1729.13],RA3:[864.57,1218.9],RA4:[609.45,864.57],SRA0:[2551.18,3628.35],SRA1:[1814.17,2551.18],SRA2:[1275.59,1814.17],SRA3:[907.09,1275.59],SRA4:[637.8,907.09],EXECUTIVE:[521.86,756],FOLIO:[612,936],LEGAL:[612,1008],LETTER:[612,792],TABLOID:[792,1224]},p=class e{static{l(this,"HtmlToPdfMake")}static convertToUnit(e){if(!isNaN(e)&&isFinite(parseFloat(e)))return parseFloat(e);var t=(e+"").trim().match(/^(-?\d*(\.\d+)?)(pt|px|r?em|cm|in)$/);if(!t)return!1;switch(e=t[1],t[3]){case"px":return.01*Math.round(.75292857248934*parseFloat(e)*100);case"em":case"rem":return 12*parseFloat(e);case"cm":return.01*Math.round(28.34646*parseFloat(e)*100);case"in":return 72*parseFloat(e);default:return parseFloat(e)}}static toCamelCase(e){return e.replace(/-([a-z])/g,function(e){return e[1].toUpperCase()})}static topRightBottomLeftToObject(e){var t=e.match(/#[0-9a-fA-F]{3,6}|\b(?:rgba?|hsla?)\([^)]*\)|\b[a-zA-Z]+\b/g)||[],a=t[0],r=t[1],i=t[2],o=t[3];switch(t.length){case 1:r=i=o=a;break;case 2:i=a,o=r;break;case 3:o=r}return{top:a,right:r,bottom:i,left:o}}static{this.hsl2rgb=l(function(e,t,a){var r=t*Math.min(a,1-a),i=l(function(t){var i=(t+e/30)%12;return Math.min(Math.floor(256*(a-r*Math.max(Math.min(i-3,9-i,1),-1))),255)},"f");return"rgb("+i(0)+","+i(8)+","+i(4)+")"},"hsl2rgb")}static parseColor(e){var t,a,r,i=1,o=new RegExp("^#([0-9a-f]{3}|[0-9a-f]{6})$","i"),s=/^rgba?\(\s*(\d+(\.\d+)?%?),\s*(\d+(\.\d+)?%?),\s*(\d+(\.\d+)?%?)(,\s*\d+(\.\d+)?)?\)$/,n=new RegExp("^hsl\\((\\d+(\\.\\d+)?%?),\\s*(\\d+(\\.\\d+)?%?),\\s*(\\d+(\\.\\d+)?%?)\\)$"),l=new RegExp("^[a-z]+$","i"),c=[];return o.test(e)?{color:e,opacity:i}:(n.test(e)&&(t=n.exec(e)?.slice(1),t&&(a=t[0].endsWith("%")?360*parseInt(t[0].slice(0,-1))/100:parseInt(t[0]),c.push(a),c.push(parseInt(t[2].slice(0,-1))/100),c.push(parseInt(t[4].slice(0,-1))/100),e=this.hsl2rgb(c[0],c[1],c[2]),c=[])),s.test(e)?(t=s.exec(e)?.slice(1),t&&t.filter(function(e,t){return t%2==0&&void 0!==e}).forEach(function(e,t){3===t?i=parseInt(e.slice(1)):((a=e.endsWith("%")?Math.round(255*parseInt(e.slice(0,-1))/100):parseInt(e))>255&&(a=255),r=(r="0"+a.toString(16)).slice(-2),c.push(r))}),{color:"#"+c.join(""),opacity:i}):(l.test(e)||console.error('Could not parse color "'+e+'"'),{color:e,opacity:i}))}static searchForStack(e){if(Array.isArray(e.text))for(var t=0;t<e.text.length;t++){if(e.text[t].stack||["SECTION","ARTICLE","DIV","P","SPAN","TABLE","SVG","UL","OL","IMG","H1","H2","H3","H4","H5","H6"].includes(e.text[t].nodeName))return!0;if(!0===this.searchForStack(e.text[t]))return!0}return!1}constructor(t){if("object"==typeof t.pageSize)this.pageSize=t.pageSize;else{var a=d[t?.pageSize||"A4"];this.pageSize={width:"portrait"==t?.pageOrientation?a[0]:a[1],height:"portrait"==t?.pageOrientation?a[1]:a[0]}}this.pageMargin=t?.pageMargin?{left:e.convertToUnit(t.pageMargin.left)||36,top:e.convertToUnit(t.pageMargin.top)||36,right:e.convertToUnit(t.pageMargin.right)||36,bottom:e.convertToUnit(t.pageMargin.bottom)||36}:{left:36,top:36,right:36,bottom:36},this.maxWidth=Math.round(this.pageSize.width-this.pageMargin.left-this.pageMargin.right-2),this.tableAutoSize=!t||"boolean"!=typeof t.tableAutoSize||t.tableAutoSize,this.imagesByReference=!(!t||"boolean"!=typeof t.imagesByReference)&&t.imagesByReference,this.removeExtraBlanks=!(!t||"boolean"!=typeof t.removeExtraBlanks)&&t.removeExtraBlanks,this.showHidden=!(!t||"boolean"!=typeof t.showHidden)&&t.showHidden,this.removeTagClasses=!(!t||"boolean"!=typeof t.removeTagClasses)&&t.removeTagClasses,this.ignoreStyles=t&&Array.isArray(t.ignoreStyles)?t.ignoreStyles:[],this.imagesByReferenceSuffix=Math.random().toString(36).slice(2,8),this.fontSizes=t&&Array.isArray(t.fontSizes)?t.fontSizes:[10,14,16,18,20,24,28],this.defaultStyles={b:{bold:!0},strong:{bold:!0},u:{decoration:"underline"},del:{decoration:"lineThrough"},s:{decoration:"lineThrough"},em:{italics:!0},i:{italics:!0},h1:{fontSize:24,bold:!0,marginBottom:5},h2:{fontSize:22,bold:!0,marginBottom:5},h3:{fontSize:20,bold:!0,marginBottom:5},h4:{fontSize:18,bold:!0,marginBottom:5},h5:{fontSize:16,bold:!0,marginBottom:5},h6:{fontSize:14,bold:!0,marginBottom:5},a:{color:"blue",decoration:"underline"},strike:{decoration:"lineThrough"},p:{margin:[0,5,0,5]},ul:{marginBottom:5,marginLeft:5},table:{marginBottom:5},th:{bold:!0,fillColor:"#EEEEEE"}},t.customTag&&(this.customTag=t.customTag),t.replaceText&&(this.replaceText=t.replaceText),t&&t.defaultStyles&&this.changeDefaultStyles(t.defaultStyles),this.imagesRef=[]}changeDefaultStyles(e){for(var t in e)if(this.defaultStyles.hasOwnProperty(t))if(e.hasOwnProperty(t)&&!e[t])delete this.defaultStyles[t];else for(var a in e[t])""===e[t][a]?delete this.defaultStyles[t][a]:this.defaultStyles[t][a]=e[t][a];else for(var r in this.defaultStyles[t]={},e[t])this.defaultStyles[t][r]=e[t][r]}getParentWidth(t){const a=t.parentNode;return a?a.style?.width||a.width?Math.min(e.convertToUnit(a.style?.width||a.width)||this.maxWidth,this.maxWidth):this.getParentWidth(a):this.maxWidth}convert(e){return"string"==typeof e?this._parserHTML(e):this._parserBody(e)}_parserHTML(e){this.removeExtraBlanks&&(e=e.replace(/(<\/?(div|p|h1|h2|h3|h4|h5|h6|ol|ul|li)([^>]+)?>)\s+(<\/?(div|p|h1|h2|h3|h4|h5|h6|ol|ul|li))/gi,"$1$4").replace(/(<\/?(div|p|h1|h2|h3|h4|h5|h6|ol|ul|li)([^>]+)?>)\s+(<\/?(div|p|h1|h2|h3|h4|h5|h6|ol|ul|li))/gi,"$1$4").replace(/(<td([^>]+)?>)\s+(<table)/gi,"$1$3").replace(/(<\/table>)\s+(<\/td>)/gi,"$1$2"));const a=new t.JSDOM("<html><body></body></html>").window.document;return a.body.innerHTML=e,this._parserBody(a.body)}_parserBody(e){var t=this.parseElement(e,[]);let a=t.stack||t.text;return"string"==typeof a&&(a={text:a}),this.imagesByReference&&(a={content:a,images:{}},this.imagesRef.forEach((e,t)=>{a.images["img_ref_"+this.imagesByReferenceSuffix+t]=e.startsWith("{")?JSON.parse(e):e})),a}parseElement(t,a){var r,i,o,s,n=t.nodeName.toUpperCase(),c=n.toLowerCase(),h={text:[]},d=this;if(["STYLE","SCRIPT","META","COLGROUP","COL"].indexOf(n)>-1)return"";switch(t.nodeType){case 3:if(t.textContent){r=t.textContent;var p=this.parseStyle(a[a.length-1],!0),u=a.findIndex(function(e){return"PRE"===e.nodeName})>-1;for(o=0;o<p.length;o++)if("preserveLeadingSpaces"===p[o].key){u=p[o].value;break}if(u||(r=r.replace(/\s*\n\s*/g," ")),"function"==typeof this.replaceText&&(r=this.replaceText(r,a)),["TABLE","THEAD","TBODY","TFOOT","TR","UL","OL"].indexOf(a[a.length-1].nodeName)>-1&&(r=r.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,"")),r)return h={text:r},h=this.applyStyle({ret:h,parents:a})}return"";case 1:if(!this.showHidden&&t.style.display&&"none"===t.style.display||t.style.visibility&&"hidden"===t.style.visibility)return;switch(null!==t.getAttribute("page")&&"1"!==t.getAttribute("page")&&(h.pageBreak="before"),h.nodeName=n,t.id&&(h.id=t.id),a.push(t),t.childNodes&&t.childNodes.length>0&&([].forEach.call(t.childNodes,e=>{var t=d.parseElement(e,a);t&&(Array.isArray(t.text)&&0===t.text.length&&(t.text=" "),h.text.push(t))}),e.searchForStack(h)?(h.stack=h.text.slice(0),delete h.text,h=this.applyStyle({ret:h,parents:[t]})):h=this.applyStyle({ret:h,parents:a})),a.pop(),n){case"DIV":"p"==t.parentNode.nodeName&&(h=this.applyStyle({ret:h,parents:a}));break;case"TABLE":var f;h.table={body:[]};var g=h.stack||h.text;if(Array.isArray(g)){f=0;var y=!1;if(g.forEach(function(e){var t=e.stack||e.text;Array.isArray(t)&&t.forEach(function(e){var t=e.stack||e.text;Array.isArray(t)&&(h.table.body[f]=[],t.forEach(function(e){if(h.table.body[f].push(e),e.colSpan>1)for(o=e.colSpan;--o>0;)h.table.body[f].push({text:" "});e.rowSpan>1&&(y=!0)}),f++)})}),y){var m=h.table.body[0];if(Array.isArray(m))for(var b=m.length,v=h.table.body.length,k=0;k<b;k++)for(var x=0;x<v;x++){var S=h.table.body[x];if(Array.isArray(S)){var A=S[k];if(A.rowSpan>1){for(var T,w=A.rowSpan,C=A.colSpan?A.colSpan:1,O=1;O<=w-1;O++)if(T=C,h.table.body[x+O])for(;T--;)h.table.body[x+O].splice(k,0,{text:""});else A.rowSpan--;x+=w-1}}}}}if(delete h.stack,delete h.text,h=this.applyStyle({ret:h,parents:a.concat([t])}),this.tableAutoSize){var E=[],B=[],R=[],L=[],M=t.getAttribute("width")||t.style.width,N=M.endsWith("%");N?(M=Math.round(this.getParentWidth(t)*parseFloat(M.replace(/[^\d\.]/g,""))*.01),console.log(this.maxWidth,M)):isNaN(M)&&(M=e.convertToUnit(M));for(var z=!1,F=-1,U=0;U<t.children.length;U++){z||F++,"COLGROUP"===t.children[U].nodeName.toUpperCase()&&(z=!0)}if(h.table.body.forEach(function(e,t){E.push([]),B.push([]),e.forEach(function(e,a){var r=void 0!==e.width?e.width:"auto";"*"===r&&(r="auto");var i=void 0!==e.height?e.height:"auto";"*"===i&&(i="auto"),"auto"!==r&&e.colSpan>1&&(isNaN(r)?r="auto":r/=e.colSpan),"auto"!==i&&e.rowSpan>1&&(isNaN(i)?i="auto":i/=e.rowSpan),E[t].push(r),B[t].push(i)})}),z){var H=t.children[F];[].forEach.call(H.childNodes,(a,r)=>{var i=a.getAttribute("width")||a.style.width;i.endsWith("%")?R[r]=.01*parseFloat(i.replace(/[^\d\.]/g,""))*this.getParentWidth(t):R[r]=e.convertToUnit(i)})}E.forEach(function(e){e.forEach(function(t,a){var r=typeof R[a];("undefined"===r||"auto"!==t&&"number"===r&&t>R[a]||"auto"!==t&&"auto"===R[a])&&(N&&(t="auto"===t?M/e.length:.01*t.toString().replace("%","")*M),R[a]=t)})}),B.forEach(function(e,t){e.forEach(function(e){var a=typeof L[t];("undefined"===a||"auto"!==e&&"number"===a&&e>L[t]||"auto"!==e&&"auto"===L[t])&&(L[t]=e)})}),R.length>0&&(h.table.widths=R.map(e=>.01*Math.round(100*(e-2*R.length)))),L.length>0&&(h.table.heights=L)}if(t.dataset&&t.dataset.pdfmake){i=t.dataset.pdfmake.replace(/'/g,'"');try{for(s in i=JSON.parse(i))"layout"===s?h.layout=i[s]:h.table[s]=i[s]}catch(e){console.error(e)}}else h.layout="html-table";break;case"TH":case"TD":t.getAttribute("rowspan")&&(h.rowSpan=1*t.getAttribute("rowspan")),t.getAttribute("colspan")&&(h.colSpan=1*t.getAttribute("colspan"));break;case"SVG":h={svg:t.outerHTML.replace(/\n(\s+)?/g,""),nodeName:"SVG"},this.removeTagClasses||(h.style=["html-svg"]);break;case"BR":h.text=[{text:"\n"}];break;case"SUB":case"SUP":h[n.toLowerCase()]={offset:"30%",fontSize:8};break;case"HR":var P={width:514,type:"line",margin:[0,12,0,12],thickness:.5,color:"#000000",left:0};if(t.dataset&&t.dataset.pdfmake){i=t.dataset.pdfmake.replace(/'/g,'"');try{for(s in i=JSON.parse(i))P[s]=i[s]}catch(e){console.error(e)}}h.margin=P.margin,h.canvas=[{type:P.type,x1:P.left,y1:0,x2:P.width,y2:0,lineWidth:P.thickness,lineColor:P.color}],delete h.text;break;case"OL":case"UL":switch(h[c]=(h.stack||h.text).slice(0),delete h.stack,delete h.text,h=this.applyStyle({ret:h,parents:a.concat([t])}),t.getAttribute("start")&&(h.start=1*t.getAttribute("start")),t.getAttribute("type")){case"A":h.type="upper-alpha";break;case"a":h.type="lower-alpha";break;case"I":h.type="upper-roman";break;case"i":h.type="lower-roman"}(h.listStyle||h.listStyleType)&&(h.type=h.listStyle||h.listStyleType);break;case"LI":h.stack&&!h.stack[h.stack.length-1].text&&(r=h.stack.slice(0,-1),h=[{text:r},h.stack[h.stack.length-1]]),Array.isArray(h)&&(h={stack:h});break;case"PRE":h.preserveLeadingSpaces=!0;break;case"IMG":if(h=this.applyStyle({ret:h,parents:a.concat([t])}),this.imagesByReference){var I=t.getAttribute("data-src")||t.getAttribute("src"),W=this.imagesRef.indexOf(I);W>-1?h.image="img_ref_"+this.imagesByReferenceSuffix+W:(h.image="img_ref_"+this.imagesByReferenceSuffix+this.imagesRef.length,this.imagesRef.push(I))}else h.image=t.getAttribute("src");delete h.stack,delete h.text;break;case"A":var $=l(function(e,t){return e=e||{text:""},Array.isArray(e.text)?(e.text=e.text.map(function(e){return $(e,t)}),e):Array.isArray(e.stack)?(e.stack=e.stack.map(function(e){return $(e,t)}),e):(0===t.indexOf("#")?e.linkToDestination=t.slice(1):e.link=t,e)},"setLink");t.getAttribute("href")&&(h=$(h,t.getAttribute("href")),Array.isArray(h.text)&&1===h.text.length&&(h=h.text[0]),h.nodeName="A");break;default:"DIV"===n&&t.dataset&&"columns"===t.dataset.pdfmakeType?h.stack&&(h.columns=h.stack,delete h.stack):"function"==typeof this.customTag&&(h=this.customTag.call(this,{element:t,parents:a,ret:h}))}if(Array.isArray(h.text)&&1===h.text.length&&h.text[0].text&&!h.text[0].nodeName&&(h.text=h.text[0].text),-1===["HR","TABLE"].indexOf(n)&&t.dataset&&t.dataset.pdfmake){i=t.dataset.pdfmake.replace(/'/g,'"');try{for(s in i=JSON.parse(i))h[s]=i[s]}catch(e){console.error(e)}}return h}}applyStyle(e){var t=[],a=e.parents.length-1,r=this;return e.parents.forEach(function(i,o){var s,n=i.nodeName.toLowerCase();if(!r.removeTagClasses){var l="html-"+n;"html-body"!==l&&-1===t.indexOf(l)&&t.unshift(l)}(i.getAttribute("class")||"").split(" ").forEach(function(e){e&&t.push(e)});var c=o!==a;if(r.defaultStyles[n])for(s in r.defaultStyles[n])r.defaultStyles[n].hasOwnProperty(s)&&(!c||c&&-1===s.indexOf("margin")&&-1===s.indexOf("border"))&&("decoration"===s?(Array.isArray(e.ret[s])||(e.ret[s]=[]),r.defaultStyles[n][s]&&-1===e.ret[s].indexOf(r.defaultStyles[n][s])&&e.ret[s].push(r.defaultStyles[n][s])):e.ret[s]=JSON.parse(JSON.stringify(r.defaultStyles[n][s])));"tr"===n&&(c=!1),(s=r.parseStyle(i,c)).forEach(function(t){if("decoration"===t.key)Array.isArray(e.ret[t.key])||(e.ret[t.key]=[]),e.ret[t.key].push(t.value);else if(["ul","ol"].includes(n)&&"alignment"===t.key);else if(e.ret.margin&&0===t.key.indexOf("margin"))switch(t.key){case"marginLeft":e.ret.margin[0]=t.value;break;case"marginTop":e.ret.margin[1]=t.value;break;case"marginRight":e.ret.margin[2]=t.value;break;case"marginBottom":e.ret.margin[3]=t.value}else["minHeight"].includes(t.key)||(e.ret[t.key]=t.value)})}),t.length>0&&(e.ret.style=t),e.ret}borderValueRearrange(e){try{var t=e.split(" ");if(3!==t.length)return e;var a="0px",r="none",i="transparent",o=["dotted","dashed","solid","double","groove","ridge","inset","outset","none","hidden","mix"];return t.forEach(function(e){e.match(/^\d/)?a=e:o.indexOf(e)>-1?r=e:i=e}),a+" "+r+" "+i}catch(t){return e}}parseStyle(t,a){var r=t.getAttribute("style")||"",i=[];r=r.replace(/!important/g,"").split(";");var o=t.getAttribute("width")||t.style.width,s=t.getAttribute("height")||t.style.height;o&&(o.endsWith("%")?o=this.getParentWidth(t)*parseFloat(o.replace(/[^\d\.]/g,""))*.01:isNaN(o)&&(o=e.convertToUnit(o)),r.unshift("width:"+o)),s&&r.unshift("height:"+e.convertToUnit(s+(isNaN(s)?"":"px")));var n=t.getAttribute("color");n&&i.push({key:"color",value:e.parseColor(n).color});var l=t.getAttribute("size");null!==l&&(l=Math.min(Math.max(1,parseInt(l)),7),i.push({key:"fontSize",value:Math.max(this.fontSizes[0],this.fontSizes[l-1])}));var c=r.map(function(e){return e.toLowerCase().split(":")}),h=[],d=t.nodeName.toUpperCase(),p=this;if(c.forEach(function(t){if(2===t.length){var r,o=t[0].trim().toLowerCase(),s=t[1].trim();if(-1===p.ignoreStyles.indexOf(o))switch(o){case"margin":{if(a)break;let t=s.split(" ");1===t.length?t=[t[0],t[0],t[0],t[0]]:2===t.length?t=[t[1],t[0]]:3===t.length?t=[t[1],t[0],t[1],t[2]]:4===t.length&&(t=[t[3],t[0],t[1],t[2]]),t.forEach(function(a,r){t[r]="auto"===a?"":e.convertToUnit(a)}),-1===t.indexOf(!1)&&i.push({key:o,value:s});break}case"line-height":s="string"==typeof s&&"%"===s.slice(-1)?parseFloat(s.slice(0,-1))/100:e.convertToUnit(s),i.push({key:"lineHeight",value:s});break;case"text-align":i.push({key:"alignment",value:s});break;case"font-weight":"bold"===s&&i.push({key:"bold",value:!0});break;case"text-decoration":s=e.toCamelCase(s),["underline","lineThrough","overline"].includes(s)&&i.push({key:"decoration",value:s});break;case"font-style":"italic"===s&&i.push({key:"italics",value:!0});break;case"font-family":i.push({key:"font",value:s.split(",")[0].replace(/"|^'|^\s*|\s*$|'$/g,"").replace(/^([a-z])/g,function(e){return e[0].toUpperCase()}).replace(/ ([a-z])/g,function(e){return e[1].toUpperCase()})});break;case"color":r=e.parseColor(s),i.push({key:"color",value:r.color}),r.opacity<1&&i.push({key:"opacity",value:r.opacity});break;case"background-color":r=e.parseColor(s),i.push({key:"TD"===d||"TH"===d?"fillColor":"background",value:r.color}),r.opacity<1&&i.push({key:"TD"===d||"TH"===d?"fillOpacity":"opacity",value:r.opacity});break;case"text-indent":i.push({key:"leadingIndent",value:e.convertToUnit(s)});break;case"white-space":"nowrap"===s?i.push({key:"noWrap",value:!0}):i.push({key:"preserveLeadingSpaces",value:"break-spaces"===s||"pre"===s.slice(0,3)});break;default:if(0===o.indexOf("border"))a||h.push({key:o,value:s});else{if(a||0===o.indexOf("margin-")||"width"===o||"height"===o)break;if("IMG"===d&&("width"===o||"height"===o)){i.push({key:o,value:e.convertToUnit(s)});break}if(0===o.indexOf("padding"))break;if(o.indexOf("-")>-1&&(o=e.toCamelCase(o)),s){var n=e.convertToUnit(s);if("fontSize"===o&&!1===n){if(!["xx-small","x-small","small","medium","large","x-large","xx-large","xxx-large"].includes(s))break;switch(s){case"xx-small":s=7.2;break;case"x-small":s=9;break;case"small":s=10.7;break;case"medium":s=12;break;case"large":s=14.4;break;case"x-large":s=18;break;case"xx-large":s=24;break;case"xxx-large":s=36}}if(0===o.indexOf("margin")&&"auto"===s)break;i.push({key:o,value:!1===n?s:n})}}}}}),h.length>0){var u=[],f=[];h.forEach(function(t){var a,r=-1;t.key.indexOf("-left")>-1?r=0:t.key.indexOf("-top")>-1?r=1:t.key.indexOf("-right")>-1?r=2:t.key.indexOf("-bottom")>-1&&(r=3);var i,o,s=t.key.split("-");if(1===s.length||2===s.length&&r>=0){if(t.value=p.borderValueRearrange(t.value),o=(i=t.value.split(" "))[0].replace(/(\d*)(\.\d+)?([^\d]+)/g,"$1$2 ").trim(),r>-1)u[r]=o>0;else for(a=0;a<4;a++)u[a]=o>0;if(i.length>2){var n=i.slice(2).join(" ");if(r>-1)f[r]=e.parseColor(n).color;else for(a=0;a<4;a++)f[a]=e.parseColor(n).color}}else r>=0&&"color"===s[2]?f[r]=e.parseColor(t.value).color:r>=0&&"width"===s[2]?u[r]=!/^0[a-z%]*$/.test(String(t.value)):"border-color"===t.key?(i=e.topRightBottomLeftToObject(t.value),f=[e.parseColor(i.left).color,e.parseColor(i.top).color,e.parseColor(i.right).color,e.parseColor(i.bottom).color]):"border-width"===t.key&&(i=e.topRightBottomLeftToObject(t.value),u=[!/^0[a-z%]*$/.test(i.left),!/^0[a-z%]*$/.test(i.top),!/^0[a-z%]*$/.test(i.right),!/^0[a-z%]*$/.test(i.bottom)])});for(var g=0;g<4;g++)u.length>0&&void 0===u[g]&&(u[g]=!0),f.length>0&&void 0===f[g]&&(f[g]="#000000");u.length>0&&i.push({key:"border",value:u}),f.length>0&&i.push({key:"borderColor",value:f})}return i}},u=c("path"),f=c("fs");async function g({docxFile:a,docxBuffer:r},i){if(!a||!f.existsSync(a))return Promise.reject(`Not found docx file:${a}`);if(r=f.readFileSync(a)){const a=new t.JSDOM("<!DOCTYPE html><html><body></body></html>",{pretendToBeVisual:!0}).window.document.body;await e.renderAsync(r,a,void 0,{inWrapper:!1,ignoreWidth:!0,ignoreHeight:!0,ignoreLastRenderedPageBreak:!0,renderHeaders:!1,renderFooters:!1,useBase64URL:!0,ignoreFonts:!0,renderFootnotes:!1,renderEndnotes:!1,renderComments:!1,renderAltChunks:!1,hideWrapperOnPrint:!0,breakPages:!0});const n=a.innerHTML.replace(/<\/?span[^>]*>/g,""),d=new p({pageSize:i?.pageSize,pageOrientation:i?.pageOrientation||"portrait",pageMargin:i?.pageMargin}).convert(n),g={version:i?.version||"1.7",language:i?.language||"zh-CN",pageSize:i?.pageSize||"A4",pageOrientation:i?.pageOrientation||"portrait",defaultStyle:{font:i?.defaultFont||"SourceHanSerifCN"},pageMargins:i?.pageMargin?[p.convertToUnit(i.pageMargin.left)||36,p.convertToUnit(i.pageMargin.top)||36,p.convertToUnit(i.pageMargin.right)||36,p.convertToUnit(i.pageMargin.bottom)||36]:[36,36,36,36],watermark:i?.watermark,content:d},y=i?.vfs||c("./vfs_fonts.js");o.default.vfs={...s.default,...y},o.default.fonts=i?.fonts||h;const m=o.default.createPdf(g),b={tableLayouts:{"html-table":{hLineWidth:l(()=>.5,"hLineWidth"),vLineWidth:l(()=>.5,"vLineWidth")}}};return{toBuffer:l(()=>new Promise((e,t)=>{try{m.getBuffer(t=>{e(t)},b)}catch(e){t(e)}}),"toBuffer"),toFile:l(e=>new Promise((t,a)=>{try{m.getBuffer(a=>{f.writeFileSync(u.resolve(e),a),t(u.resolve(e))},b)}catch(e){a(e)}}),"toFile"),toStream:l(()=>new Promise((e,t)=>{try{e(m.getStream(b))}catch(e){t(e)}}),"toStream")}}return Promise.reject("Either docx file path<docxFile> or buffer object<docxBuffer> must be provided.")}l(g,"docx2pdf");var y=g;module.exports=y;
|
package/package.json
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "docx-make-pdf",
|
|
3
|
+
"version": "0.0.2",
|
|
4
|
+
"description": "convert docx file to html then to pdf with pdfmake",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"docx",
|
|
7
|
+
"pdf",
|
|
8
|
+
"pdfmake"
|
|
9
|
+
],
|
|
10
|
+
"license": "Apache-2.0",
|
|
11
|
+
"author": "bleek@xjtime.com",
|
|
12
|
+
"repository": {
|
|
13
|
+
"type": "git",
|
|
14
|
+
"url": "git+https://github.com/ifeda/docxmakepdf.git"
|
|
15
|
+
},
|
|
16
|
+
"main": "index.js",
|
|
17
|
+
"dependencies": {
|
|
18
|
+
"docx-preview-node": "^0.3.6",
|
|
19
|
+
"jsdom": "^26.1.0",
|
|
20
|
+
"pdfmake": "^0.2.20"
|
|
21
|
+
},
|
|
22
|
+
"files": [
|
|
23
|
+
"*"
|
|
24
|
+
]
|
|
25
|
+
}
|