pdf-composer 1.0.1 → 1.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 +199 -203
- package/dist/index.d.ts +15 -0
- package/dist/index.esm.js +72 -4
- package/dist/index.js +72 -4
- package/dist/index.js.map +1 -1
- package/dist/index.umd.js +72 -4
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,203 +1,199 @@
|
|
|
1
|
-
#
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
##
|
|
6
|
-
|
|
7
|
-
-
|
|
8
|
-
-
|
|
9
|
-
-
|
|
10
|
-
-
|
|
11
|
-
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
}
|
|
61
|
-
```
|
|
62
|
-
|
|
63
|
-
###
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
#
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
## 许可证
|
|
202
|
-
|
|
203
|
-
MIT
|
|
1
|
+
# PDF Composer
|
|
2
|
+
|
|
3
|
+
一个基于 JavaScript 的 PDF 生成工具,支持将 Markdown 文本、SVG 图表和多种类型的图片转换为 PDF 文档。
|
|
4
|
+
|
|
5
|
+
## 功能特性
|
|
6
|
+
|
|
7
|
+
- ✅ Markdown 文本转 PDF
|
|
8
|
+
- ✅ SVG 图表支持(通过容器 ID 获取)
|
|
9
|
+
- ✅ 多种图片类型支持(远程图片、Base64、Canvas、Image)
|
|
10
|
+
- ✅ 多页 PDF 自动分页
|
|
11
|
+
- ✅ 自定义页面格式和方向
|
|
12
|
+
|
|
13
|
+
## 安装
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
npm install pdf-composer
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## 使用方法
|
|
20
|
+
|
|
21
|
+
### 基础用法
|
|
22
|
+
|
|
23
|
+
```typescript
|
|
24
|
+
import { generationPDFWithOptions } from 'pdf-composer';
|
|
25
|
+
|
|
26
|
+
const result = await generationPDFWithOptions({
|
|
27
|
+
markdownText: '# Hello World\n\n这是一个简单的 PDF 文档。',
|
|
28
|
+
fileName: 'output.pdf'
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
if (result.success) {
|
|
32
|
+
console.log(`PDF 生成成功,共 ${result.pageCount} 页`);
|
|
33
|
+
}
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
### SVG 图表支持
|
|
37
|
+
|
|
38
|
+
通过容器 ID 获取页面中的 SVG 元素:
|
|
39
|
+
|
|
40
|
+
```typescript
|
|
41
|
+
interface SvgOptions {
|
|
42
|
+
domId: string; // 页面中 SVG 所在容器的 ID
|
|
43
|
+
maxWidth?: number; // 最大宽度(默认 1000px)
|
|
44
|
+
margin?: number; // 外边距(默认 25px)
|
|
45
|
+
textAlign?: 'left' | 'center' | 'right'; // 对齐方式(默认 center)
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// HTML 中定义 SVG 容器
|
|
49
|
+
// <div id="chart1">
|
|
50
|
+
// <svg>...</svg>
|
|
51
|
+
// </div>
|
|
52
|
+
|
|
53
|
+
const result = await generationPDFWithOptions({
|
|
54
|
+
markdownText: '# 报告\n\n以下是数据图表:',
|
|
55
|
+
fileName: 'report.pdf',
|
|
56
|
+
svgOptions: [
|
|
57
|
+
{ domId: 'chart1', maxWidth: 800, margin: 30, textAlign: 'center' },
|
|
58
|
+
{ domId: 'chart2', maxWidth: 600, margin: 20, textAlign: 'left' }
|
|
59
|
+
]
|
|
60
|
+
});
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
### 图片支持(兼容多种类型)
|
|
64
|
+
|
|
65
|
+
支持远程图片、Base64、Canvas 和 HTMLImageElement:
|
|
66
|
+
|
|
67
|
+
```typescript
|
|
68
|
+
interface ImageOptions {
|
|
69
|
+
source: string | HTMLCanvasElement | HTMLImageElement;
|
|
70
|
+
width?: number;
|
|
71
|
+
height?: number;
|
|
72
|
+
margin?: number;
|
|
73
|
+
textAlign?: 'left' | 'center' | 'right';
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// 远程图片
|
|
77
|
+
const remoteImage = {
|
|
78
|
+
source: 'https://example.com/image.jpg',
|
|
79
|
+
width: 600,
|
|
80
|
+
margin: 25,
|
|
81
|
+
textAlign: 'center'
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
// Base64 图片
|
|
85
|
+
const base64Image = {
|
|
86
|
+
source: 'data:image/png;base64,iVBORw0KGgo...',
|
|
87
|
+
width: 200
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
// Canvas 生成的图片
|
|
91
|
+
const canvas = document.createElement('canvas');
|
|
92
|
+
canvas.width = 400;
|
|
93
|
+
canvas.height = 200;
|
|
94
|
+
const ctx = canvas.getContext('2d');
|
|
95
|
+
ctx.fillStyle = '#667eea';
|
|
96
|
+
ctx.fillRect(0, 0, 400, 200);
|
|
97
|
+
|
|
98
|
+
const canvasImage = {
|
|
99
|
+
source: canvas,
|
|
100
|
+
margin: 25
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
const result = await generationPDFWithOptions({
|
|
104
|
+
markdownText: '# 图片报告\n\n包含多种类型的图片:',
|
|
105
|
+
fileName: 'images.pdf',
|
|
106
|
+
imageOptions: [remoteImage, base64Image, canvasImage]
|
|
107
|
+
});
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
## API 接口
|
|
111
|
+
|
|
112
|
+
```typescript
|
|
113
|
+
interface GenerationPdfOptions {
|
|
114
|
+
markdownText: string; // 必需:Markdown 文本
|
|
115
|
+
fileName?: string; // 输出文件名(默认:output.pdf)
|
|
116
|
+
containerWidth?: number; // 渲染容器宽度(默认:1200px)
|
|
117
|
+
scale?: number; // 缩放比例(默认:2)
|
|
118
|
+
pageFormat?: 'a3' | 'a4' | 'letter' | 'legal'; // 页面格式(默认:a4)
|
|
119
|
+
orientation?: 'p' | 'l'; // 方向:纵向/横向(默认:p)
|
|
120
|
+
padding?: number; // 页面边距(默认:10mm)
|
|
121
|
+
|
|
122
|
+
svgOptions?: SvgOptions[]; // SVG 选项
|
|
123
|
+
imageOptions?: ImageOptions[]; // 图片选项
|
|
124
|
+
}
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
## 综合示例
|
|
128
|
+
|
|
129
|
+
```typescript
|
|
130
|
+
import { generationPDFWithOptions } from 'pdf-composer';
|
|
131
|
+
|
|
132
|
+
// 创建 Canvas 图片
|
|
133
|
+
const canvas = document.createElement('canvas');
|
|
134
|
+
canvas.width = 400;
|
|
135
|
+
canvas.height = 200;
|
|
136
|
+
const ctx = canvas.getContext('2d');
|
|
137
|
+
ctx.fillStyle = '#4facfe';
|
|
138
|
+
ctx.fillRect(0, 0, 400, 200);
|
|
139
|
+
ctx.fillStyle = 'white';
|
|
140
|
+
ctx.font = '24px Arial';
|
|
141
|
+
ctx.textAlign = 'center';
|
|
142
|
+
ctx.fillText('动态生成的图表', 200, 110);
|
|
143
|
+
|
|
144
|
+
// 生成综合 PDF
|
|
145
|
+
const result = await generationPDFWithOptions({
|
|
146
|
+
markdownText: `# 综合报告
|
|
147
|
+
|
|
148
|
+
这是一个包含多种内容类型的综合报告。
|
|
149
|
+
|
|
150
|
+
## 数据图表
|
|
151
|
+
|
|
152
|
+
下面是从页面获取的 SVG 图表:
|
|
153
|
+
|
|
154
|
+
## 动态内容
|
|
155
|
+
|
|
156
|
+
以及通过代码生成的图片:`,
|
|
157
|
+
fileName: 'comprehensive-report.pdf',
|
|
158
|
+
pageFormat: 'a4',
|
|
159
|
+
orientation: 'p',
|
|
160
|
+
svgOptions: [
|
|
161
|
+
{ domId: 'sales-chart', maxWidth: 800, margin: 30, textAlign: 'center' },
|
|
162
|
+
{ domId: 'pie-chart', maxWidth: 600, margin: 30, textAlign: 'center' }
|
|
163
|
+
],
|
|
164
|
+
imageOptions: [
|
|
165
|
+
{ source: 'https://example.com/logo.png', width: 300, margin: 20 },
|
|
166
|
+
{ source: canvas, margin: 25 },
|
|
167
|
+
{ source: 'data:image/png;base64,iVBORw0KGgo...', width: 200 }
|
|
168
|
+
]
|
|
169
|
+
});
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
## 测试页面
|
|
173
|
+
|
|
174
|
+
项目提供了完整的测试页面:
|
|
175
|
+
|
|
176
|
+
- [demo.html](example/demo.html) - 包含基础测试、SVG 测试、图片测试和综合测试
|
|
177
|
+
|
|
178
|
+
## 依赖
|
|
179
|
+
|
|
180
|
+
- **marked**:Markdown 解析
|
|
181
|
+
- **html2canvas**:HTML 转 Canvas
|
|
182
|
+
- **jsPDF**:PDF 生成
|
|
183
|
+
|
|
184
|
+
## 开发
|
|
185
|
+
|
|
186
|
+
```bash
|
|
187
|
+
# 安装依赖
|
|
188
|
+
npm install
|
|
189
|
+
|
|
190
|
+
# 构建
|
|
191
|
+
npm run build
|
|
192
|
+
|
|
193
|
+
# 启动开发服务器
|
|
194
|
+
npx http-server -p 8081
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
## 许可证
|
|
198
|
+
|
|
199
|
+
MIT
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,21 @@
|
|
|
1
|
+
export interface SvgOptions {
|
|
2
|
+
domId: string;
|
|
3
|
+
maxWidth?: number;
|
|
4
|
+
margin?: number;
|
|
5
|
+
textAlign?: 'left' | 'center' | 'right';
|
|
6
|
+
}
|
|
7
|
+
export interface ImageOptions {
|
|
8
|
+
source: string | HTMLCanvasElement | HTMLImageElement;
|
|
9
|
+
width?: number;
|
|
10
|
+
height?: number;
|
|
11
|
+
margin?: number;
|
|
12
|
+
textAlign?: 'left' | 'center' | 'right';
|
|
13
|
+
}
|
|
1
14
|
export interface GenerationPdfOptions {
|
|
2
15
|
markdownText: string;
|
|
3
16
|
mermaidDomId?: string;
|
|
17
|
+
svgOptions?: SvgOptions[];
|
|
18
|
+
imageOptions?: ImageOptions[];
|
|
4
19
|
fileName?: string;
|
|
5
20
|
containerWidth?: number;
|
|
6
21
|
containerPadding?: number;
|
package/dist/index.esm.js
CHANGED
|
@@ -28,6 +28,68 @@ const PAGE_SIZES = {
|
|
|
28
28
|
letter: { width: 215.9, height: 279.4 },
|
|
29
29
|
legal: { width: 215.9, height: 355.6 }
|
|
30
30
|
};
|
|
31
|
+
function processSvgOptions(svgOptions, container) {
|
|
32
|
+
for (const option of svgOptions) {
|
|
33
|
+
const el = document.getElementById(option.domId);
|
|
34
|
+
if (!el)
|
|
35
|
+
continue;
|
|
36
|
+
const svg = el.querySelector('svg');
|
|
37
|
+
if (!svg)
|
|
38
|
+
continue;
|
|
39
|
+
const wrapper = document.createElement('div');
|
|
40
|
+
const margin = option.margin ?? 25;
|
|
41
|
+
wrapper.style.cssText = `margin: ${margin}px 0; text-align: ${option.textAlign ?? 'center'};`;
|
|
42
|
+
const clone = svg.cloneNode(true);
|
|
43
|
+
clone.style.cssText = `max-width: ${option.maxWidth ?? 1000}px; width: 100%; height: auto;`;
|
|
44
|
+
wrapper.appendChild(clone);
|
|
45
|
+
container.appendChild(wrapper);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
async function processImageOptions(imageOptions, container) {
|
|
49
|
+
for (const option of imageOptions) {
|
|
50
|
+
const wrapper = document.createElement('div');
|
|
51
|
+
const margin = option.margin ?? 25;
|
|
52
|
+
wrapper.style.cssText = `margin: ${margin}px 0; text-align: ${option.textAlign ?? 'center'};`;
|
|
53
|
+
let imgEl = null;
|
|
54
|
+
if (typeof option.source === 'string') {
|
|
55
|
+
imgEl = document.createElement('img');
|
|
56
|
+
imgEl.src = option.source;
|
|
57
|
+
imgEl.style.maxWidth = '100%';
|
|
58
|
+
imgEl.style.height = 'auto';
|
|
59
|
+
if (option.width)
|
|
60
|
+
imgEl.style.width = `${option.width}px`;
|
|
61
|
+
if (option.height)
|
|
62
|
+
imgEl.style.height = `${option.height}px`;
|
|
63
|
+
await new Promise((resolve) => {
|
|
64
|
+
imgEl.onload = resolve;
|
|
65
|
+
imgEl.onerror = resolve;
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
else if (option.source instanceof HTMLCanvasElement) {
|
|
69
|
+
imgEl = document.createElement('img');
|
|
70
|
+
imgEl.src = option.source.toDataURL('image/png');
|
|
71
|
+
imgEl.style.maxWidth = '100%';
|
|
72
|
+
imgEl.style.height = 'auto';
|
|
73
|
+
if (option.width)
|
|
74
|
+
imgEl.style.width = `${option.width}px`;
|
|
75
|
+
if (option.height)
|
|
76
|
+
imgEl.style.height = `${option.height}px`;
|
|
77
|
+
}
|
|
78
|
+
else if (option.source instanceof HTMLImageElement) {
|
|
79
|
+
imgEl = option.source.cloneNode(true);
|
|
80
|
+
imgEl.style.maxWidth = '100%';
|
|
81
|
+
imgEl.style.height = 'auto';
|
|
82
|
+
if (option.width)
|
|
83
|
+
imgEl.style.width = `${option.width}px`;
|
|
84
|
+
if (option.height)
|
|
85
|
+
imgEl.style.height = `${option.height}px`;
|
|
86
|
+
}
|
|
87
|
+
if (imgEl) {
|
|
88
|
+
wrapper.appendChild(imgEl);
|
|
89
|
+
container.appendChild(wrapper);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
31
93
|
export async function generationPDF(markdownText, mermaidDomId, fileName = 'output.pdf') {
|
|
32
94
|
return generationPDFWithOptions({
|
|
33
95
|
markdownText,
|
|
@@ -36,7 +98,7 @@ export async function generationPDF(markdownText, mermaidDomId, fileName = 'outp
|
|
|
36
98
|
});
|
|
37
99
|
}
|
|
38
100
|
export async function generationPDFWithOptions(options) {
|
|
39
|
-
const { markdownText, mermaidDomId, fileName = 'output.pdf', containerWidth = 1200, containerPadding = 40, scale = 2, pageFormat = 'a4', orientation = 'p', padding = 10 } = options;
|
|
101
|
+
const { markdownText, mermaidDomId, svgOptions, imageOptions, fileName = 'output.pdf', containerWidth = 1200, containerPadding = 40, scale = 2, pageFormat = 'a4', orientation = 'p', padding = 10 } = options;
|
|
40
102
|
try {
|
|
41
103
|
const markdownHtml = parse(markdownText);
|
|
42
104
|
const exportContainer = document.createElement('div');
|
|
@@ -72,8 +134,14 @@ export async function generationPDFWithOptions(options) {
|
|
|
72
134
|
}
|
|
73
135
|
}
|
|
74
136
|
}
|
|
137
|
+
if (svgOptions && svgOptions.length > 0) {
|
|
138
|
+
processSvgOptions(svgOptions, exportContainer);
|
|
139
|
+
}
|
|
140
|
+
if (imageOptions && imageOptions.length > 0) {
|
|
141
|
+
await processImageOptions(imageOptions, exportContainer);
|
|
142
|
+
}
|
|
75
143
|
document.body.appendChild(exportContainer);
|
|
76
|
-
await new Promise(resolve => setTimeout(resolve,
|
|
144
|
+
await new Promise(resolve => setTimeout(resolve, 500));
|
|
77
145
|
const containerHeight = exportContainer.scrollHeight;
|
|
78
146
|
const pageSize = PAGE_SIZES[pageFormat] || PAGE_SIZES.a4;
|
|
79
147
|
const pageWidth = orientation === 'l' ? pageSize.height : pageSize.width;
|
|
@@ -112,9 +180,9 @@ export async function generationPDFWithOptions(options) {
|
|
|
112
180
|
ctx.fillRect(0, 0, pageCanvas.width, pageCanvas.height);
|
|
113
181
|
ctx.drawImage(canvas, 0, startY, canvas.width, pageCanvasHeight, 0, 0, pageCanvas.width, pageCanvasHeight);
|
|
114
182
|
}
|
|
115
|
-
const pageImgData = pageCanvas.toDataURL('image/
|
|
183
|
+
const pageImgData = pageCanvas.toDataURL('image/png');
|
|
116
184
|
const pageImgHeight = (pageCanvasHeight / canvas.height) * imgHeight;
|
|
117
|
-
pdf.addImage(pageImgData, '
|
|
185
|
+
pdf.addImage(pageImgData, 'PNG', padding, padding, imgWidth, pageImgHeight);
|
|
118
186
|
}
|
|
119
187
|
pdf.save(fileName);
|
|
120
188
|
document.body.removeChild(exportContainer);
|
package/dist/index.js
CHANGED
|
@@ -35,6 +35,68 @@ const PAGE_SIZES = {
|
|
|
35
35
|
letter: { width: 215.9, height: 279.4 },
|
|
36
36
|
legal: { width: 215.9, height: 355.6 }
|
|
37
37
|
};
|
|
38
|
+
function processSvgOptions(svgOptions, container) {
|
|
39
|
+
for (const option of svgOptions) {
|
|
40
|
+
const el = document.getElementById(option.domId);
|
|
41
|
+
if (!el)
|
|
42
|
+
continue;
|
|
43
|
+
const svg = el.querySelector('svg');
|
|
44
|
+
if (!svg)
|
|
45
|
+
continue;
|
|
46
|
+
const wrapper = document.createElement('div');
|
|
47
|
+
const margin = option.margin ?? 25;
|
|
48
|
+
wrapper.style.cssText = `margin: ${margin}px 0; text-align: ${option.textAlign ?? 'center'};`;
|
|
49
|
+
const clone = svg.cloneNode(true);
|
|
50
|
+
clone.style.cssText = `max-width: ${option.maxWidth ?? 1000}px; width: 100%; height: auto;`;
|
|
51
|
+
wrapper.appendChild(clone);
|
|
52
|
+
container.appendChild(wrapper);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
async function processImageOptions(imageOptions, container) {
|
|
56
|
+
for (const option of imageOptions) {
|
|
57
|
+
const wrapper = document.createElement('div');
|
|
58
|
+
const margin = option.margin ?? 25;
|
|
59
|
+
wrapper.style.cssText = `margin: ${margin}px 0; text-align: ${option.textAlign ?? 'center'};`;
|
|
60
|
+
let imgEl = null;
|
|
61
|
+
if (typeof option.source === 'string') {
|
|
62
|
+
imgEl = document.createElement('img');
|
|
63
|
+
imgEl.src = option.source;
|
|
64
|
+
imgEl.style.maxWidth = '100%';
|
|
65
|
+
imgEl.style.height = 'auto';
|
|
66
|
+
if (option.width)
|
|
67
|
+
imgEl.style.width = `${option.width}px`;
|
|
68
|
+
if (option.height)
|
|
69
|
+
imgEl.style.height = `${option.height}px`;
|
|
70
|
+
await new Promise((resolve) => {
|
|
71
|
+
imgEl.onload = resolve;
|
|
72
|
+
imgEl.onerror = resolve;
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
else if (option.source instanceof HTMLCanvasElement) {
|
|
76
|
+
imgEl = document.createElement('img');
|
|
77
|
+
imgEl.src = option.source.toDataURL('image/png');
|
|
78
|
+
imgEl.style.maxWidth = '100%';
|
|
79
|
+
imgEl.style.height = 'auto';
|
|
80
|
+
if (option.width)
|
|
81
|
+
imgEl.style.width = `${option.width}px`;
|
|
82
|
+
if (option.height)
|
|
83
|
+
imgEl.style.height = `${option.height}px`;
|
|
84
|
+
}
|
|
85
|
+
else if (option.source instanceof HTMLImageElement) {
|
|
86
|
+
imgEl = option.source.cloneNode(true);
|
|
87
|
+
imgEl.style.maxWidth = '100%';
|
|
88
|
+
imgEl.style.height = 'auto';
|
|
89
|
+
if (option.width)
|
|
90
|
+
imgEl.style.width = `${option.width}px`;
|
|
91
|
+
if (option.height)
|
|
92
|
+
imgEl.style.height = `${option.height}px`;
|
|
93
|
+
}
|
|
94
|
+
if (imgEl) {
|
|
95
|
+
wrapper.appendChild(imgEl);
|
|
96
|
+
container.appendChild(wrapper);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}
|
|
38
100
|
async function generationPDF(markdownText, mermaidDomId, fileName = 'output.pdf') {
|
|
39
101
|
return generationPDFWithOptions({
|
|
40
102
|
markdownText,
|
|
@@ -43,7 +105,7 @@ async function generationPDF(markdownText, mermaidDomId, fileName = 'output.pdf'
|
|
|
43
105
|
});
|
|
44
106
|
}
|
|
45
107
|
async function generationPDFWithOptions(options) {
|
|
46
|
-
const { markdownText, mermaidDomId, fileName = 'output.pdf', containerWidth = 1200, containerPadding = 40, scale = 2, pageFormat = 'a4', orientation = 'p', padding = 10 } = options;
|
|
108
|
+
const { markdownText, mermaidDomId, svgOptions, imageOptions, fileName = 'output.pdf', containerWidth = 1200, containerPadding = 40, scale = 2, pageFormat = 'a4', orientation = 'p', padding = 10 } = options;
|
|
47
109
|
try {
|
|
48
110
|
const markdownHtml = (0, marked_1.parse)(markdownText);
|
|
49
111
|
const exportContainer = document.createElement('div');
|
|
@@ -79,8 +141,14 @@ async function generationPDFWithOptions(options) {
|
|
|
79
141
|
}
|
|
80
142
|
}
|
|
81
143
|
}
|
|
144
|
+
if (svgOptions && svgOptions.length > 0) {
|
|
145
|
+
processSvgOptions(svgOptions, exportContainer);
|
|
146
|
+
}
|
|
147
|
+
if (imageOptions && imageOptions.length > 0) {
|
|
148
|
+
await processImageOptions(imageOptions, exportContainer);
|
|
149
|
+
}
|
|
82
150
|
document.body.appendChild(exportContainer);
|
|
83
|
-
await new Promise(resolve => setTimeout(resolve,
|
|
151
|
+
await new Promise(resolve => setTimeout(resolve, 500));
|
|
84
152
|
const containerHeight = exportContainer.scrollHeight;
|
|
85
153
|
const pageSize = PAGE_SIZES[pageFormat] || PAGE_SIZES.a4;
|
|
86
154
|
const pageWidth = orientation === 'l' ? pageSize.height : pageSize.width;
|
|
@@ -119,9 +187,9 @@ async function generationPDFWithOptions(options) {
|
|
|
119
187
|
ctx.fillRect(0, 0, pageCanvas.width, pageCanvas.height);
|
|
120
188
|
ctx.drawImage(canvas, 0, startY, canvas.width, pageCanvasHeight, 0, 0, pageCanvas.width, pageCanvasHeight);
|
|
121
189
|
}
|
|
122
|
-
const pageImgData = pageCanvas.toDataURL('image/
|
|
190
|
+
const pageImgData = pageCanvas.toDataURL('image/png');
|
|
123
191
|
const pageImgHeight = (pageCanvasHeight / canvas.height) * imgHeight;
|
|
124
|
-
pdf.addImage(pageImgData, '
|
|
192
|
+
pdf.addImage(pageImgData, 'PNG', padding, padding, imgWidth, pageImgHeight);
|
|
125
193
|
}
|
|
126
194
|
pdf.save(fileName);
|
|
127
195
|
document.body.removeChild(exportContainer);
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/index.umd.js
CHANGED
|
@@ -29,6 +29,68 @@ const PAGE_SIZES = {
|
|
|
29
29
|
letter: { width: 215.9, height: 279.4 },
|
|
30
30
|
legal: { width: 215.9, height: 355.6 }
|
|
31
31
|
};
|
|
32
|
+
function processSvgOptions(svgOptions, container) {
|
|
33
|
+
for (const option of svgOptions) {
|
|
34
|
+
const el = document.getElementById(option.domId);
|
|
35
|
+
if (!el)
|
|
36
|
+
continue;
|
|
37
|
+
const svg = el.querySelector('svg');
|
|
38
|
+
if (!svg)
|
|
39
|
+
continue;
|
|
40
|
+
const wrapper = document.createElement('div');
|
|
41
|
+
const margin = option.margin ?? 25;
|
|
42
|
+
wrapper.style.cssText = `margin: ${margin}px 0; text-align: ${option.textAlign ?? 'center'};`;
|
|
43
|
+
const clone = svg.cloneNode(true);
|
|
44
|
+
clone.style.cssText = `max-width: ${option.maxWidth ?? 1000}px; width: 100%; height: auto;`;
|
|
45
|
+
wrapper.appendChild(clone);
|
|
46
|
+
container.appendChild(wrapper);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
async function processImageOptions(imageOptions, container) {
|
|
50
|
+
for (const option of imageOptions) {
|
|
51
|
+
const wrapper = document.createElement('div');
|
|
52
|
+
const margin = option.margin ?? 25;
|
|
53
|
+
wrapper.style.cssText = `margin: ${margin}px 0; text-align: ${option.textAlign ?? 'center'};`;
|
|
54
|
+
let imgEl = null;
|
|
55
|
+
if (typeof option.source === 'string') {
|
|
56
|
+
imgEl = document.createElement('img');
|
|
57
|
+
imgEl.src = option.source;
|
|
58
|
+
imgEl.style.maxWidth = '100%';
|
|
59
|
+
imgEl.style.height = 'auto';
|
|
60
|
+
if (option.width)
|
|
61
|
+
imgEl.style.width = `${option.width}px`;
|
|
62
|
+
if (option.height)
|
|
63
|
+
imgEl.style.height = `${option.height}px`;
|
|
64
|
+
await new Promise((resolve) => {
|
|
65
|
+
imgEl.onload = resolve;
|
|
66
|
+
imgEl.onerror = resolve;
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
else if (option.source instanceof HTMLCanvasElement) {
|
|
70
|
+
imgEl = document.createElement('img');
|
|
71
|
+
imgEl.src = option.source.toDataURL('image/png');
|
|
72
|
+
imgEl.style.maxWidth = '100%';
|
|
73
|
+
imgEl.style.height = 'auto';
|
|
74
|
+
if (option.width)
|
|
75
|
+
imgEl.style.width = `${option.width}px`;
|
|
76
|
+
if (option.height)
|
|
77
|
+
imgEl.style.height = `${option.height}px`;
|
|
78
|
+
}
|
|
79
|
+
else if (option.source instanceof HTMLImageElement) {
|
|
80
|
+
imgEl = option.source.cloneNode(true);
|
|
81
|
+
imgEl.style.maxWidth = '100%';
|
|
82
|
+
imgEl.style.height = 'auto';
|
|
83
|
+
if (option.width)
|
|
84
|
+
imgEl.style.width = `${option.width}px`;
|
|
85
|
+
if (option.height)
|
|
86
|
+
imgEl.style.height = `${option.height}px`;
|
|
87
|
+
}
|
|
88
|
+
if (imgEl) {
|
|
89
|
+
wrapper.appendChild(imgEl);
|
|
90
|
+
container.appendChild(wrapper);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
32
94
|
async function generationPDF(markdownText, mermaidDomId, fileName = 'output.pdf') {
|
|
33
95
|
return generationPDFWithOptions({
|
|
34
96
|
markdownText,
|
|
@@ -37,7 +99,7 @@ async function generationPDF(markdownText, mermaidDomId, fileName = 'output.pdf'
|
|
|
37
99
|
});
|
|
38
100
|
}
|
|
39
101
|
async function generationPDFWithOptions(options) {
|
|
40
|
-
const { markdownText, mermaidDomId, fileName = 'output.pdf', containerWidth = 1200, containerPadding = 40, scale = 2, pageFormat = 'a4', orientation = 'p', padding = 10 } = options;
|
|
102
|
+
const { markdownText, mermaidDomId, svgOptions, imageOptions, fileName = 'output.pdf', containerWidth = 1200, containerPadding = 40, scale = 2, pageFormat = 'a4', orientation = 'p', padding = 10 } = options;
|
|
41
103
|
try {
|
|
42
104
|
const markdownHtml = marked.parse(markdownText);
|
|
43
105
|
const exportContainer = document.createElement('div');
|
|
@@ -73,8 +135,14 @@ async function generationPDFWithOptions(options) {
|
|
|
73
135
|
}
|
|
74
136
|
}
|
|
75
137
|
}
|
|
138
|
+
if (svgOptions && svgOptions.length > 0) {
|
|
139
|
+
processSvgOptions(svgOptions, exportContainer);
|
|
140
|
+
}
|
|
141
|
+
if (imageOptions && imageOptions.length > 0) {
|
|
142
|
+
await processImageOptions(imageOptions, exportContainer);
|
|
143
|
+
}
|
|
76
144
|
document.body.appendChild(exportContainer);
|
|
77
|
-
await new Promise(resolve => setTimeout(resolve,
|
|
145
|
+
await new Promise(resolve => setTimeout(resolve, 500));
|
|
78
146
|
const containerHeight = exportContainer.scrollHeight;
|
|
79
147
|
const pageSize = PAGE_SIZES[pageFormat] || PAGE_SIZES.a4;
|
|
80
148
|
const pageWidth = orientation === 'l' ? pageSize.height : pageSize.width;
|
|
@@ -113,9 +181,9 @@ async function generationPDFWithOptions(options) {
|
|
|
113
181
|
ctx.fillRect(0, 0, pageCanvas.width, pageCanvas.height);
|
|
114
182
|
ctx.drawImage(canvas, 0, startY, canvas.width, pageCanvasHeight, 0, 0, pageCanvas.width, pageCanvasHeight);
|
|
115
183
|
}
|
|
116
|
-
const pageImgData = pageCanvas.toDataURL('image/
|
|
184
|
+
const pageImgData = pageCanvas.toDataURL('image/png');
|
|
117
185
|
const pageImgHeight = (pageCanvasHeight / canvas.height) * imgHeight;
|
|
118
|
-
pdf.addImage(pageImgData, '
|
|
186
|
+
pdf.addImage(pageImgData, 'PNG', padding, padding, imgWidth, pageImgHeight);
|
|
119
187
|
}
|
|
120
188
|
pdf.save(fileName);
|
|
121
189
|
document.body.removeChild(exportContainer);
|