dom-to-vector-pdf 0.0.1 → 0.0.3

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 CHANGED
@@ -1,14 +1,79 @@
1
1
  # dom-to-vector-pdf
2
2
 
3
- DOM 转矢量 PDF
4
-
5
- 1. 克隆元素时对原页面的影响
6
- - 内联控制(current)
7
- - 样式优先级
8
- - Shadow DOM
9
- - iframe
10
- 2. iconfont 大小问题:目前是默认 16px 字体大小来做的缩放
11
- 3. 原来的 DOM 中本身存在的 SVG 用的内联样式来决定样式
12
- - 目前只支持内联中属性名和元素属性名一致的情况
13
- 4. 页面整体转换出来的文字对比背景要偏下一点
14
- - 目前是暂时所有文字整体上移 3 个像素单位
3
+ A tool for converting DOM elements to vector PDFs using jsPDF, dom-to-svg and svg2pdf.js.
4
+
5
+ ## Basic Usage
6
+
7
+ ```javascript
8
+ import vectorInstance from "dom-to-vector-pdf";
9
+
10
+ export const ExportToPDF = (id, title) => {
11
+ vectorInstance.registerFont([
12
+ {
13
+ font: PingFangRegular,
14
+ fontId: "PingFang",
15
+ fontWeight: "400",
16
+ fontStyle: "normal",
17
+ },
18
+ {
19
+ font: PingFangHeavy,
20
+ fontId: "PingFang",
21
+ fontWeight: "700",
22
+ fontStyle: "normal",
23
+ },
24
+ ]);
25
+ vectorInstance.export({
26
+ id,
27
+ filename: title,
28
+ });
29
+ };
30
+ ```
31
+
32
+ ## Features
33
+
34
+ - Converts DOM elements to vector PDFs
35
+ - Preserves vector graphics and text
36
+ - Supports SVG elements
37
+ - Maintains font styles and weights
38
+ - Handles complex layouts
39
+
40
+ ## Todo List
41
+
42
+ ### DOM Cloning
43
+ - [ ] Inline style handling
44
+ - [ ] Style priority management
45
+ - [ ] Shadow DOM support
46
+ - [ ] iframe support
47
+
48
+ ### Icon Fonts
49
+ - [ ] Current implementation uses 16px as base font size for scaling
50
+ - [ ] Need to improve icon font size handling
51
+
52
+ ### SVG Support
53
+ - [ ] Currently only supports inline styles where property names match element attributes
54
+ - [ ] Need to enhance SVG style handling
55
+
56
+ ### Text Alignment
57
+ - [ ] Text appears slightly lower than background
58
+ - Current workaround: Shift all text up by 3 pixels
59
+
60
+ ### Unsupported Features
61
+ - [ ] Image background export
62
+ - [ ] Canvas export
63
+
64
+ ### Font Support
65
+ - [ ] Currently limited to single font family
66
+ - Font ID must be consistent during registration
67
+ - [ ] Need to add support for multiple fonts
68
+ - [ ] Consider WOFF2 format compatibility
69
+
70
+ ### Image Export
71
+ - [ ] Image export quality needs improvement
72
+
73
+ ## Contributing
74
+
75
+ Contributions are welcome! Please feel free to submit a Pull Request.
76
+
77
+ ## License
78
+
79
+ MIT
@@ -0,0 +1,79 @@
1
+ # dom-to-vector-pdf
2
+
3
+ 一个使用 jsPDF、dom-to-svg 和 svg2pdf.js 将 DOM 元素转换为矢量 PDF 的工具。
4
+
5
+ ## 基础使用
6
+
7
+ ```javascript
8
+ import vectorInstance from "dom-to-vector-pdf";
9
+
10
+ export const ExportToPDF = (id, title) => {
11
+ vectorInstance.registerFont([
12
+ {
13
+ font: PingFangRegular,
14
+ fontId: "PingFang",
15
+ fontWeight: "400",
16
+ fontStyle: "normal",
17
+ },
18
+ {
19
+ font: PingFangHeavy,
20
+ fontId: "PingFang",
21
+ fontWeight: "700",
22
+ fontStyle: "normal",
23
+ },
24
+ ]);
25
+ vectorInstance.export({
26
+ id,
27
+ filename: title,
28
+ });
29
+ };
30
+ ```
31
+
32
+ ## 功能特点
33
+
34
+ - 将 DOM 元素转换为矢量 PDF
35
+ - 保持矢量图形和文本质量
36
+ - 支持 SVG 元素
37
+ - 保持字体样式和字重
38
+ - 处理复杂布局
39
+
40
+ ## 待办事项
41
+
42
+ ### DOM 克隆
43
+ - [ ] 内联样式处理
44
+ - [ ] 样式优先级管理
45
+ - [ ] Shadow DOM 支持
46
+ - [ ] iframe 支持
47
+
48
+ ### 图标字体
49
+ - [ ] 当前实现使用 16px 作为基础字体大小进行缩放
50
+ - [ ] 需要改进图标字体大小处理
51
+
52
+ ### SVG 支持
53
+ - [ ] 目前仅支持属性名与元素属性名一致的内联样式
54
+ - [ ] 需要增强 SVG 样式处理
55
+
56
+ ### 文本对齐
57
+ - [ ] 文字相对背景略微偏下
58
+ - 当前解决方案:所有文字整体上移 3 个像素单位
59
+
60
+ ### 不支持的功能
61
+ - [ ] 图片背景导出
62
+ - [ ] Canvas 导出
63
+
64
+ ### 字体支持
65
+ - [ ] 目前仅支持单一字体系列
66
+ - 注册字体时 fontId 必须一致
67
+ - [ ] 需要添加多字体支持
68
+ - [ ] 考虑兼容 WOFF2 格式
69
+
70
+ ### 图片导出
71
+ - [ ] 图片导出效果需要改进
72
+
73
+ ## 贡献
74
+
75
+ 欢迎贡献代码!请随时提交 Pull Request。
76
+
77
+ ## 许可证
78
+
79
+ MIT
@@ -1,28 +1,28 @@
1
1
  import type { ExportPdfOptions, LifecycleHooks } from './types';
2
2
  /**
3
- * DOMPDF转换器
3
+ * DOM to PDF Converter
4
4
  */
5
5
  export declare class DomToPdfConverter {
6
6
  private fontManager;
7
7
  constructor();
8
8
  /**
9
- * 导出PDF
9
+ * Export PDF
10
10
  */
11
11
  exportPdf(options: ExportPdfOptions, hooks?: LifecycleHooks): Promise<void>;
12
12
  /**
13
- * 准备DOM元素
13
+ * Prepare DOM element
14
14
  */
15
15
  private prepareDomElement;
16
16
  /**
17
- * 准备SVG元素
17
+ * Prepare SVG element
18
18
  */
19
19
  private prepareSvgElement;
20
20
  /**
21
- * 创建PDF文档
21
+ * Create PDF document
22
22
  */
23
23
  private createPdfDocument;
24
24
  /**
25
- * 渲染SVGPDF
25
+ * Render SVG to PDF
26
26
  */
27
27
  private renderSvgToPdf;
28
28
  }
@@ -1,32 +1,37 @@
1
1
  import { jsPDF } from 'jspdf';
2
2
  import type { FontRegisterOptions } from './types';
3
3
  /**
4
- * 字体管理器
4
+ * Font manager
5
5
  */
6
6
  export declare class FontManager {
7
7
  private static instance;
8
8
  private registeredFonts;
9
9
  private pdfInstance?;
10
10
  private callbackList;
11
+ private fontId;
11
12
  private constructor();
12
13
  /**
13
- * 获取字体管理器单例
14
+ * Get font ID
15
+ */
16
+ getFontId(): string;
17
+ /**
18
+ * Get font manager singleton
14
19
  */
15
20
  static getInstance(): FontManager;
16
21
  /**
17
- * 设置PDF实例
22
+ * Set PDF instance
18
23
  */
19
- setPdfInstance(pdf: jsPDF): void;
24
+ setPdfInstance(pdf: jsPDF | null): void;
20
25
  /**
21
- * 注册字体
26
+ * Register font
22
27
  */
23
28
  registerFont(options: FontRegisterOptions): void;
24
29
  /**
25
- * 批量注册字体
30
+ * Batch register fonts
26
31
  */
27
32
  registerFonts(options: FontRegisterOptions[]): void;
28
33
  /**
29
- * 添加字体到PDF实例
34
+ * Add font to PDF instance
30
35
  */
31
36
  private addFontToPdf;
32
37
  }
@@ -1 +1 @@
1
- {"version":3,"file":"font-manager.d.ts","sourceRoot":"","sources":["../src/font-manager.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,OAAO,CAAC;AAC9B,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,SAAS,CAAC;AAGnD;;GAEG;AACH,qBAAa,WAAW;IACtB,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAc;IACrC,OAAO,CAAC,eAAe,CAAuC;IAC9D,OAAO,CAAC,WAAW,CAAC,CAAe;IACnC,OAAO,CAAC,YAAY,CAAsB;IAE1C,OAAO;IAEP;;OAEG;WACW,WAAW,IAAI,WAAW;IAOxC;;OAEG;IACI,cAAc,CAAC,GAAG,EAAE,KAAK,GAAG,IAAI;IAMvC;;OAEG;IACI,YAAY,CAAC,OAAO,EAAE,mBAAmB,GAAG,IAAI;IAIvD;;OAEG;IACI,aAAa,CAAC,OAAO,EAAE,mBAAmB,EAAE,GAAG,IAAI;IAI1D;;OAEG;IACH,OAAO,CAAC,YAAY;CAYrB"}
1
+ {"version":3,"file":"font-manager.d.ts","sourceRoot":"","sources":["../src/font-manager.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,OAAO,CAAC;AAC9B,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,SAAS,CAAC;AAGnD;;GAEG;AACH,qBAAa,WAAW;IACtB,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAc;IACrC,OAAO,CAAC,eAAe,CAAuC;IAC9D,OAAO,CAAC,WAAW,CAAC,CAAe;IACnC,OAAO,CAAC,YAAY,CAAsB;IAC1C,OAAO,CAAC,MAAM,CAAsB;IAEpC,OAAO;IAEP;;OAEG;IACI,SAAS,IAAI,MAAM;IAI1B;;OAEG;WACW,WAAW,IAAI,WAAW;IAOxC;;OAEG;IACI,cAAc,CAAC,GAAG,EAAE,KAAK,GAAG,IAAI,GAAG,IAAI;IAM9C;;OAEG;IACI,YAAY,CAAC,OAAO,EAAE,mBAAmB,GAAG,IAAI;IAKvD;;OAEG;IACI,aAAa,CAAC,OAAO,EAAE,mBAAmB,EAAE,GAAG,IAAI;IAI1D;;OAEG;IACH,OAAO,CAAC,YAAY;CAYrB"}
package/dist/index.d.ts CHANGED
@@ -1,23 +1,23 @@
1
1
  import type { ExportPdfOptions, FontRegisterOptions, LifecycleHooks } from './types';
2
2
  /**
3
- * DOMPDF工具实例
3
+ * DOM to PDF tool instance
4
4
  */
5
- declare class DomToPdf {
5
+ declare class DOMToPDF {
6
6
  private converter;
7
7
  private fontManager;
8
8
  constructor();
9
9
  /**
10
- * 导出PDF
11
- * @param options 导出配置
12
- * @param hooks 生命周期钩子
10
+ * Export PDF
11
+ * @param options Export configuration
12
+ * @param hooks Lifecycle hooks
13
13
  */
14
- export(options: ExportPdfOptions, hooks?: LifecycleHooks): Promise<void>;
14
+ exportPDF(options: ExportPdfOptions, hooks?: LifecycleHooks): Promise<void>;
15
15
  /**
16
- * 注册字体
17
- * @param options 字体注册选项
16
+ * Register font
17
+ * @param options Font registration options
18
18
  */
19
19
  registerFont(options: FontRegisterOptions | FontRegisterOptions[]): void;
20
20
  }
21
- export declare const instance: DomToPdf;
21
+ export declare const instance: DOMToPDF;
22
22
  export default instance;
23
23
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAErF;;GAEG;AACH,cAAM,QAAQ;IACZ,OAAO,CAAC,SAAS,CAAoB;IACrC,OAAO,CAAC,WAAW,CAAc;;IAOjC;;;;OAIG;IACU,MAAM,CAAC,OAAO,EAAE,gBAAgB,EAAE,KAAK,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC;IAIrF;;;OAGG;IACI,YAAY,CAAC,OAAO,EAAE,mBAAmB,GAAG,mBAAmB,EAAE,GAAG,IAAI;CAOhF;AAGD,eAAO,MAAM,QAAQ,UAAiB,CAAC;AACvC,eAAe,QAAQ,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAErF;;GAEG;AACH,cAAM,QAAQ;IACZ,OAAO,CAAC,SAAS,CAAoB;IACrC,OAAO,CAAC,WAAW,CAAc;;IAOjC;;;;OAIG;IACU,SAAS,CAAC,OAAO,EAAE,gBAAgB,EAAE,KAAK,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC;IAIxF;;;OAGG;IACI,YAAY,CAAC,OAAO,EAAE,mBAAmB,GAAG,mBAAmB,EAAE,GAAG,IAAI;CAOhF;AAGD,eAAO,MAAM,QAAQ,UAAiB,CAAC;AACvC,eAAe,QAAQ,CAAC"}
package/dist/index.esm.js CHANGED
@@ -3,9 +3,9 @@ import { elementToSVG } from 'dom-to-svg';
3
3
  import { svg2pdf } from 'svg2pdf.js';
4
4
 
5
5
  /**
6
- * 转换字体字重
7
- * @param weight 字体粗细
8
- * @returns 标准化后的字重
6
+ * Convert font weight
7
+ * @param weight Font weight
8
+ * @returns Normalized font weight
9
9
  */
10
10
  function normalizeFontWeight(weight) {
11
11
  const weightMap = {
@@ -15,7 +15,7 @@ function normalizeFontWeight(weight) {
15
15
  return weightMap[weight?.toString() || 'normal'] || weight?.toString() || '400';
16
16
  }
17
17
  /**
18
- * 计算SVG symbol的缩放比例
18
+ * Calculate SVG symbol scale ratio
19
19
  */
20
20
  function calculateSymbolScale(symbol) {
21
21
  const viewBox = symbol.getAttribute('viewBox');
@@ -28,7 +28,7 @@ function calculateSymbolScale(symbol) {
28
28
  return expectedSize / width;
29
29
  }
30
30
  /**
31
- * 内联SVG中的symbol元素
31
+ * Symbol element in inline SVG
32
32
  */
33
33
  function inlineSvgSymbols(element) {
34
34
  const uses = element.querySelectorAll('use');
@@ -41,34 +41,34 @@ function inlineSvgSymbols(element) {
41
41
  if (!symbol) {
42
42
  return;
43
43
  }
44
- // 创建 <g> 容器保留所有属性
44
+ // Create <g> container preserving all attributes
45
45
  const g = document.createElementNS('http://www.w3.org/2000/svg', 'g');
46
- // 复制除href外的所有属性
46
+ // Copy all attributes except href
47
47
  Array.from(use.attributes).forEach((attr) => {
48
48
  if (attr.name !== 'xlink:href' && attr.name !== 'href') {
49
49
  g.setAttribute(attr.name, attr.value);
50
50
  }
51
51
  });
52
- // 插入缩放后的路径
52
+ // Insert scaled path
53
53
  g.innerHTML = `
54
54
  <g transform="scale(${calculateSymbolScale(symbol)})">
55
55
  ${symbol.innerHTML}
56
56
  </g>
57
57
  `;
58
- // 替换并保留父SVG尺寸
58
+ // Replace and preserve parent SVG dimensions
59
59
  use.replaceWith(g);
60
60
  });
61
61
  }
62
62
  /**
63
- * 递归处理SVG元素的字体属性
63
+ * Recursively process SVG element font attributes
64
64
  */
65
- function processSvgFonts(element) {
65
+ function processSvgFonts(element, fontManager) {
66
66
  if (element.classList.contains('no-print')) {
67
67
  element.remove();
68
68
  return;
69
69
  }
70
70
  if (element.tagName === 'text' || element.tagName === 'tspan') {
71
- // 解析style字符串
71
+ // Parse style string
72
72
  const style = element.getAttribute('style');
73
73
  if (style) {
74
74
  style.split(';').forEach((css) => {
@@ -83,29 +83,36 @@ function processSvgFonts(element) {
83
83
  const fontWeight = element.getAttribute('font-weight');
84
84
  // TODO
85
85
  if (fontFamily) {
86
- element.setAttribute('font-family', 'PingFang');
86
+ element.setAttribute('font-family', fontManager.getFontId());
87
87
  element.setAttribute('font-weight', normalizeFontWeight(fontWeight));
88
88
  }
89
- // 调整y坐标
89
+ // Adjust y coordinate
90
90
  const y = element.getAttribute('y');
91
91
  if (y) {
92
92
  element.setAttribute('y', String(Number(y) - 3));
93
93
  }
94
94
  }
95
- // 递归处理子元素
96
- Array.from(element.children).forEach((child) => processSvgFonts(child));
95
+ // Recursively process child elements
96
+ Array.from(element.children).forEach((child) => processSvgFonts(child, fontManager));
97
97
  }
98
98
 
99
99
  /**
100
- * 字体管理器
100
+ * Font manager
101
101
  */
102
102
  class FontManager {
103
103
  constructor() {
104
104
  this.registeredFonts = new Map();
105
105
  this.callbackList = [];
106
+ this.fontId = 'PingFang';
106
107
  }
107
108
  /**
108
- * 获取字体管理器单例
109
+ * Get font ID
110
+ */
111
+ getFontId() {
112
+ return this.fontId;
113
+ }
114
+ /**
115
+ * Get font manager singleton
109
116
  */
110
117
  static getInstance() {
111
118
  if (!FontManager.instance) {
@@ -114,7 +121,7 @@ class FontManager {
114
121
  return FontManager.instance;
115
122
  }
116
123
  /**
117
- * 设置PDF实例
124
+ * Set PDF instance
118
125
  */
119
126
  setPdfInstance(pdf) {
120
127
  this.pdfInstance = pdf;
@@ -122,19 +129,20 @@ class FontManager {
122
129
  this.callbackList = [];
123
130
  }
124
131
  /**
125
- * 注册字体
132
+ * Register font
126
133
  */
127
134
  registerFont(options) {
135
+ this.fontId = options.fontId;
128
136
  this.addFontToPdf(options);
129
137
  }
130
138
  /**
131
- * 批量注册字体
139
+ * Batch register fonts
132
140
  */
133
141
  registerFonts(options) {
134
142
  options.map((font) => this.registerFont(font));
135
143
  }
136
144
  /**
137
- * 添加字体到PDF实例
145
+ * Add font to PDF instance
138
146
  */
139
147
  addFontToPdf(options) {
140
148
  if (!this.pdfInstance) {
@@ -146,44 +154,44 @@ class FontManager {
146
154
  }
147
155
 
148
156
  /**
149
- * DOMPDF转换器
157
+ * DOM to PDF Converter
150
158
  */
151
159
  class DomToPdfConverter {
152
160
  constructor() {
153
161
  this.fontManager = FontManager.getInstance();
154
162
  }
155
163
  /**
156
- * 导出PDF
164
+ * Export PDF
157
165
  */
158
166
  async exportPdf(options, hooks) {
159
167
  try {
160
- // 1. 获取并克隆DOM元素
168
+ // 1. Get and clone DOM element
161
169
  const { element, parentElement } = this.prepareDomElement(options.id);
162
- // 调用生命周期钩子
170
+ // Call lifecycle hook
163
171
  hooks?.afterDomClone?.(element);
164
- // 2. 处理SVG符号
172
+ // 2. Process SVG symbols
165
173
  inlineSvgSymbols(element);
166
- // 3. 转换为SVG
174
+ // 3. Convert to SVG
167
175
  const svgDocument = elementToSVG(element);
168
176
  parentElement?.removeChild(element);
169
177
  const svgElement = svgDocument.documentElement;
170
178
  document.body.appendChild(svgElement);
171
179
  this.prepareSvgElement(svgElement);
172
- // 4. 处理SVG字体
173
- processSvgFonts(svgElement);
174
- // 调用生命周期钩子
180
+ // 4. Process SVG fonts
181
+ processSvgFonts(svgElement, this.fontManager);
182
+ // Call lifecycle hook
175
183
  hooks?.beforeSvgConvert?.(svgElement);
176
- // 5. 创建PDF文档
184
+ // 5. Create PDF document
177
185
  const pdf = this.createPdfDocument(svgElement);
178
186
  this.fontManager.setPdfInstance(pdf);
179
- // 6. 绘制SVG内容到PDF
187
+ // 6. Draw SVG content to PDF
180
188
  await this.renderSvgToPdf(svgElement, pdf);
181
- // 调用生命周期钩子
189
+ // Call lifecycle hook
182
190
  hooks?.beforePdfGenerate?.(pdf);
183
191
  hooks?.beforePdfSave?.(pdf);
184
- // 7. 保存PDF
192
+ // 7. Save PDF
185
193
  pdf.save(`${options.filename}.pdf`);
186
- // 8. 清理临时元素
194
+ // 8. Clean up temporary elements
187
195
  svgElement.remove();
188
196
  this.fontManager.setPdfInstance(null);
189
197
  }
@@ -193,7 +201,7 @@ class DomToPdfConverter {
193
201
  }
194
202
  }
195
203
  /**
196
- * 准备DOM元素
204
+ * Prepare DOM element
197
205
  */
198
206
  prepareDomElement(id) {
199
207
  const originElement = document.querySelector(id);
@@ -202,7 +210,7 @@ class DomToPdfConverter {
202
210
  }
203
211
  const parentElement = originElement.parentElement;
204
212
  const element = originElement.cloneNode(true);
205
- // 设置克隆元素的样式
213
+ // Set cloned element styles
206
214
  element.style.cssText = `
207
215
  z-index: -999999;
208
216
  position: absolute;
@@ -214,7 +222,7 @@ class DomToPdfConverter {
214
222
  return { element, parentElement };
215
223
  }
216
224
  /**
217
- * 准备SVG元素
225
+ * Prepare SVG element
218
226
  */
219
227
  prepareSvgElement(svgElement) {
220
228
  svgElement.style.cssText = `
@@ -225,12 +233,12 @@ class DomToPdfConverter {
225
233
  left: 0;
226
234
  z-index: -999999;
227
235
  `;
228
- // 添加XML声明
236
+ // Add XML declaration
229
237
  const utf8Declaration = document.createTextNode('<?xml version="1.0" encoding="utf-8"?>');
230
238
  svgElement.insertBefore(utf8Declaration, svgElement.firstChild);
231
239
  }
232
240
  /**
233
- * 创建PDF文档
241
+ * Create PDF document
234
242
  */
235
243
  createPdfDocument(svgElement) {
236
244
  const { width, height } = svgElement.getBoundingClientRect();
@@ -241,7 +249,7 @@ class DomToPdfConverter {
241
249
  });
242
250
  }
243
251
  /**
244
- * 渲染SVGPDF
252
+ * Render SVG to PDF
245
253
  */
246
254
  async renderSvgToPdf(svgElement, pdf) {
247
255
  await svg2pdf(svgElement, pdf, {
@@ -254,24 +262,24 @@ class DomToPdfConverter {
254
262
  }
255
263
 
256
264
  /**
257
- * DOMPDF工具实例
265
+ * DOM to PDF tool instance
258
266
  */
259
- class DomToPdf {
267
+ class DOMToPDF {
260
268
  constructor() {
261
269
  this.converter = new DomToPdfConverter();
262
270
  this.fontManager = FontManager.getInstance();
263
271
  }
264
272
  /**
265
- * 导出PDF
266
- * @param options 导出配置
267
- * @param hooks 生命周期钩子
273
+ * Export PDF
274
+ * @param options Export configuration
275
+ * @param hooks Lifecycle hooks
268
276
  */
269
- async export(options, hooks) {
277
+ async exportPDF(options, hooks) {
270
278
  await this.converter.exportPdf(options, hooks);
271
279
  }
272
280
  /**
273
- * 注册字体
274
- * @param options 字体注册选项
281
+ * Register font
282
+ * @param options Font registration options
275
283
  */
276
284
  registerFont(options) {
277
285
  if (Array.isArray(options)) {
@@ -282,7 +290,7 @@ class DomToPdf {
282
290
  }
283
291
  }
284
292
  }
285
- // 导出单例实例
286
- const instance = new DomToPdf();
293
+ // Export singleton instance
294
+ const instance = new DOMToPDF();
287
295
 
288
296
  export { instance as default, instance };
package/dist/index.js CHANGED
@@ -1,13 +1,13 @@
1
1
  (function (global, factory) {
2
2
  typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('jspdf'), require('dom-to-svg'), require('svg2pdf.js')) :
3
3
  typeof define === 'function' && define.amd ? define(['exports', 'jspdf', 'dom-to-svg', 'svg2pdf.js'], factory) :
4
- (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.DomToPdf = {}, global.jspdf, global.domToSvg, global.svg2pdf_js));
4
+ (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.DOMToPDF = {}, global.jspdf, global.domToSvg, global.svg2pdf_js));
5
5
  })(this, (function (exports, jspdf, domToSvg, svg2pdf_js) { 'use strict';
6
6
 
7
7
  /**
8
- * 转换字体字重
9
- * @param weight 字体粗细
10
- * @returns 标准化后的字重
8
+ * Convert font weight
9
+ * @param weight Font weight
10
+ * @returns Normalized font weight
11
11
  */
12
12
  function normalizeFontWeight(weight) {
13
13
  const weightMap = {
@@ -17,7 +17,7 @@
17
17
  return weightMap[weight?.toString() || 'normal'] || weight?.toString() || '400';
18
18
  }
19
19
  /**
20
- * 计算SVG symbol的缩放比例
20
+ * Calculate SVG symbol scale ratio
21
21
  */
22
22
  function calculateSymbolScale(symbol) {
23
23
  const viewBox = symbol.getAttribute('viewBox');
@@ -30,7 +30,7 @@
30
30
  return expectedSize / width;
31
31
  }
32
32
  /**
33
- * 内联SVG中的symbol元素
33
+ * Symbol element in inline SVG
34
34
  */
35
35
  function inlineSvgSymbols(element) {
36
36
  const uses = element.querySelectorAll('use');
@@ -43,34 +43,34 @@
43
43
  if (!symbol) {
44
44
  return;
45
45
  }
46
- // 创建 <g> 容器保留所有属性
46
+ // Create <g> container preserving all attributes
47
47
  const g = document.createElementNS('http://www.w3.org/2000/svg', 'g');
48
- // 复制除href外的所有属性
48
+ // Copy all attributes except href
49
49
  Array.from(use.attributes).forEach((attr) => {
50
50
  if (attr.name !== 'xlink:href' && attr.name !== 'href') {
51
51
  g.setAttribute(attr.name, attr.value);
52
52
  }
53
53
  });
54
- // 插入缩放后的路径
54
+ // Insert scaled path
55
55
  g.innerHTML = `
56
56
  <g transform="scale(${calculateSymbolScale(symbol)})">
57
57
  ${symbol.innerHTML}
58
58
  </g>
59
59
  `;
60
- // 替换并保留父SVG尺寸
60
+ // Replace and preserve parent SVG dimensions
61
61
  use.replaceWith(g);
62
62
  });
63
63
  }
64
64
  /**
65
- * 递归处理SVG元素的字体属性
65
+ * Recursively process SVG element font attributes
66
66
  */
67
- function processSvgFonts(element) {
67
+ function processSvgFonts(element, fontManager) {
68
68
  if (element.classList.contains('no-print')) {
69
69
  element.remove();
70
70
  return;
71
71
  }
72
72
  if (element.tagName === 'text' || element.tagName === 'tspan') {
73
- // 解析style字符串
73
+ // Parse style string
74
74
  const style = element.getAttribute('style');
75
75
  if (style) {
76
76
  style.split(';').forEach((css) => {
@@ -85,29 +85,36 @@
85
85
  const fontWeight = element.getAttribute('font-weight');
86
86
  // TODO
87
87
  if (fontFamily) {
88
- element.setAttribute('font-family', 'PingFang');
88
+ element.setAttribute('font-family', fontManager.getFontId());
89
89
  element.setAttribute('font-weight', normalizeFontWeight(fontWeight));
90
90
  }
91
- // 调整y坐标
91
+ // Adjust y coordinate
92
92
  const y = element.getAttribute('y');
93
93
  if (y) {
94
94
  element.setAttribute('y', String(Number(y) - 3));
95
95
  }
96
96
  }
97
- // 递归处理子元素
98
- Array.from(element.children).forEach((child) => processSvgFonts(child));
97
+ // Recursively process child elements
98
+ Array.from(element.children).forEach((child) => processSvgFonts(child, fontManager));
99
99
  }
100
100
 
101
101
  /**
102
- * 字体管理器
102
+ * Font manager
103
103
  */
104
104
  class FontManager {
105
105
  constructor() {
106
106
  this.registeredFonts = new Map();
107
107
  this.callbackList = [];
108
+ this.fontId = 'PingFang';
108
109
  }
109
110
  /**
110
- * 获取字体管理器单例
111
+ * Get font ID
112
+ */
113
+ getFontId() {
114
+ return this.fontId;
115
+ }
116
+ /**
117
+ * Get font manager singleton
111
118
  */
112
119
  static getInstance() {
113
120
  if (!FontManager.instance) {
@@ -116,7 +123,7 @@
116
123
  return FontManager.instance;
117
124
  }
118
125
  /**
119
- * 设置PDF实例
126
+ * Set PDF instance
120
127
  */
121
128
  setPdfInstance(pdf) {
122
129
  this.pdfInstance = pdf;
@@ -124,19 +131,20 @@
124
131
  this.callbackList = [];
125
132
  }
126
133
  /**
127
- * 注册字体
134
+ * Register font
128
135
  */
129
136
  registerFont(options) {
137
+ this.fontId = options.fontId;
130
138
  this.addFontToPdf(options);
131
139
  }
132
140
  /**
133
- * 批量注册字体
141
+ * Batch register fonts
134
142
  */
135
143
  registerFonts(options) {
136
144
  options.map((font) => this.registerFont(font));
137
145
  }
138
146
  /**
139
- * 添加字体到PDF实例
147
+ * Add font to PDF instance
140
148
  */
141
149
  addFontToPdf(options) {
142
150
  if (!this.pdfInstance) {
@@ -148,44 +156,44 @@
148
156
  }
149
157
 
150
158
  /**
151
- * DOMPDF转换器
159
+ * DOM to PDF Converter
152
160
  */
153
161
  class DomToPdfConverter {
154
162
  constructor() {
155
163
  this.fontManager = FontManager.getInstance();
156
164
  }
157
165
  /**
158
- * 导出PDF
166
+ * Export PDF
159
167
  */
160
168
  async exportPdf(options, hooks) {
161
169
  try {
162
- // 1. 获取并克隆DOM元素
170
+ // 1. Get and clone DOM element
163
171
  const { element, parentElement } = this.prepareDomElement(options.id);
164
- // 调用生命周期钩子
172
+ // Call lifecycle hook
165
173
  hooks?.afterDomClone?.(element);
166
- // 2. 处理SVG符号
174
+ // 2. Process SVG symbols
167
175
  inlineSvgSymbols(element);
168
- // 3. 转换为SVG
176
+ // 3. Convert to SVG
169
177
  const svgDocument = domToSvg.elementToSVG(element);
170
178
  parentElement?.removeChild(element);
171
179
  const svgElement = svgDocument.documentElement;
172
180
  document.body.appendChild(svgElement);
173
181
  this.prepareSvgElement(svgElement);
174
- // 4. 处理SVG字体
175
- processSvgFonts(svgElement);
176
- // 调用生命周期钩子
182
+ // 4. Process SVG fonts
183
+ processSvgFonts(svgElement, this.fontManager);
184
+ // Call lifecycle hook
177
185
  hooks?.beforeSvgConvert?.(svgElement);
178
- // 5. 创建PDF文档
186
+ // 5. Create PDF document
179
187
  const pdf = this.createPdfDocument(svgElement);
180
188
  this.fontManager.setPdfInstance(pdf);
181
- // 6. 绘制SVG内容到PDF
189
+ // 6. Draw SVG content to PDF
182
190
  await this.renderSvgToPdf(svgElement, pdf);
183
- // 调用生命周期钩子
191
+ // Call lifecycle hook
184
192
  hooks?.beforePdfGenerate?.(pdf);
185
193
  hooks?.beforePdfSave?.(pdf);
186
- // 7. 保存PDF
194
+ // 7. Save PDF
187
195
  pdf.save(`${options.filename}.pdf`);
188
- // 8. 清理临时元素
196
+ // 8. Clean up temporary elements
189
197
  svgElement.remove();
190
198
  this.fontManager.setPdfInstance(null);
191
199
  }
@@ -195,7 +203,7 @@
195
203
  }
196
204
  }
197
205
  /**
198
- * 准备DOM元素
206
+ * Prepare DOM element
199
207
  */
200
208
  prepareDomElement(id) {
201
209
  const originElement = document.querySelector(id);
@@ -204,7 +212,7 @@
204
212
  }
205
213
  const parentElement = originElement.parentElement;
206
214
  const element = originElement.cloneNode(true);
207
- // 设置克隆元素的样式
215
+ // Set cloned element styles
208
216
  element.style.cssText = `
209
217
  z-index: -999999;
210
218
  position: absolute;
@@ -216,7 +224,7 @@
216
224
  return { element, parentElement };
217
225
  }
218
226
  /**
219
- * 准备SVG元素
227
+ * Prepare SVG element
220
228
  */
221
229
  prepareSvgElement(svgElement) {
222
230
  svgElement.style.cssText = `
@@ -227,12 +235,12 @@
227
235
  left: 0;
228
236
  z-index: -999999;
229
237
  `;
230
- // 添加XML声明
238
+ // Add XML declaration
231
239
  const utf8Declaration = document.createTextNode('<?xml version="1.0" encoding="utf-8"?>');
232
240
  svgElement.insertBefore(utf8Declaration, svgElement.firstChild);
233
241
  }
234
242
  /**
235
- * 创建PDF文档
243
+ * Create PDF document
236
244
  */
237
245
  createPdfDocument(svgElement) {
238
246
  const { width, height } = svgElement.getBoundingClientRect();
@@ -243,7 +251,7 @@
243
251
  });
244
252
  }
245
253
  /**
246
- * 渲染SVGPDF
254
+ * Render SVG to PDF
247
255
  */
248
256
  async renderSvgToPdf(svgElement, pdf) {
249
257
  await svg2pdf_js.svg2pdf(svgElement, pdf, {
@@ -256,24 +264,24 @@
256
264
  }
257
265
 
258
266
  /**
259
- * DOMPDF工具实例
267
+ * DOM to PDF tool instance
260
268
  */
261
- class DomToPdf {
269
+ class DOMToPDF {
262
270
  constructor() {
263
271
  this.converter = new DomToPdfConverter();
264
272
  this.fontManager = FontManager.getInstance();
265
273
  }
266
274
  /**
267
- * 导出PDF
268
- * @param options 导出配置
269
- * @param hooks 生命周期钩子
275
+ * Export PDF
276
+ * @param options Export configuration
277
+ * @param hooks Lifecycle hooks
270
278
  */
271
- async export(options, hooks) {
279
+ async exportPDF(options, hooks) {
272
280
  await this.converter.exportPdf(options, hooks);
273
281
  }
274
282
  /**
275
- * 注册字体
276
- * @param options 字体注册选项
283
+ * Register font
284
+ * @param options Font registration options
277
285
  */
278
286
  registerFont(options) {
279
287
  if (Array.isArray(options)) {
@@ -284,8 +292,8 @@
284
292
  }
285
293
  }
286
294
  }
287
- // 导出单例实例
288
- const instance = new DomToPdf();
295
+ // Export singleton instance
296
+ const instance = new DOMToPDF();
289
297
 
290
298
  exports["default"] = instance;
291
299
  exports.instance = instance;
package/dist/types.d.ts CHANGED
@@ -1,45 +1,45 @@
1
1
  import { jsPDF } from 'jspdf';
2
2
  /**
3
- * 导出PDF配置项
3
+ * Export PDF配置项
4
4
  */
5
5
  export interface ExportPdfOptions {
6
- /** 要导出的DOM元素ID */
6
+ /** DOM element ID to export */
7
7
  id: string;
8
- /** 导出的PDF文件名 */
8
+ /** Exported PDF file name */
9
9
  filename: string;
10
- /** PDF方向,默认为 portrait */
10
+ /** PDF orientation, default is portrait */
11
11
  orientation?: 'portrait' | 'landscape';
12
- /** 单位,默认为 px */
12
+ /** Unit, default is px */
13
13
  unit?: 'pt' | 'px' | 'in' | 'mm' | 'cm' | 'ex' | 'em' | 'pc';
14
- /** 自定义处理SVG元素的钩子 */
14
+ /** Custom hook for processing SVG elements */
15
15
  beforeSvgConvert?: (svgElement: SVGElement) => void;
16
- /** 自定义处理PDF文档的钩子 */
16
+ /** Custom hook for processing PDF document */
17
17
  beforePdfSave?: (pdf: jsPDF) => void;
18
18
  }
19
19
  /**
20
- * 字体注册选项
20
+ * Font registration options
21
21
  */
22
22
  export interface FontRegisterOptions {
23
- /** 字体文件路径或URL */
23
+ /** Font file path or URL */
24
24
  font: string;
25
- /** 字体ID,用于标识字体 */
25
+ /** Font ID for identifying the font */
26
26
  fontId: string;
27
27
  /** 字体样式 (normal/italic) */
28
28
  fontStyle?: 'normal' | 'italic';
29
- /** 字体粗细 (100-900) */
29
+ /** Font weight (100-900) */
30
30
  fontWeight?: string | number;
31
31
  }
32
32
  /**
33
- * 生命周期钩子
33
+ * Lifecycle hooks
34
34
  */
35
35
  export interface LifecycleHooks {
36
- /** DOM克隆后触发 */
36
+ /** Triggered after DOM clone */
37
37
  afterDomClone?: (clonedElement: HTMLElement) => void;
38
- /** SVG转换前触发 */
38
+ /** Triggered before SVG conversion */
39
39
  beforeSvgConvert?: (svgElement: SVGElement) => void;
40
- /** PDF生成前触发 */
40
+ /** Triggered before PDF generation */
41
41
  beforePdfGenerate?: (pdf: jsPDF) => void;
42
- /** PDF保存前触发 */
42
+ /** Triggered before PDF save */
43
43
  beforePdfSave?: (pdf: jsPDF) => void;
44
44
  }
45
45
  //# sourceMappingURL=types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,OAAO,CAAC;AAE9B;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,kBAAkB;IAClB,EAAE,EAAE,MAAM,CAAC;IACX,gBAAgB;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,yBAAyB;IACzB,WAAW,CAAC,EAAE,UAAU,GAAG,WAAW,CAAC;IACvC,gBAAgB;IAChB,IAAI,CAAC,EAAE,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;IAC7D,oBAAoB;IACpB,gBAAgB,CAAC,EAAE,CAAC,UAAU,EAAE,UAAU,KAAK,IAAI,CAAC;IACpD,oBAAoB;IACpB,aAAa,CAAC,EAAE,CAAC,GAAG,EAAE,KAAK,KAAK,IAAI,CAAC;CACtC;AAED;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC,iBAAiB;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,kBAAkB;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,2BAA2B;IAC3B,SAAS,CAAC,EAAE,QAAQ,GAAG,QAAQ,CAAC;IAChC,qBAAqB;IACrB,UAAU,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;CAC9B;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,eAAe;IACf,aAAa,CAAC,EAAE,CAAC,aAAa,EAAE,WAAW,KAAK,IAAI,CAAC;IACrD,eAAe;IACf,gBAAgB,CAAC,EAAE,CAAC,UAAU,EAAE,UAAU,KAAK,IAAI,CAAC;IACpD,eAAe;IACf,iBAAiB,CAAC,EAAE,CAAC,GAAG,EAAE,KAAK,KAAK,IAAI,CAAC;IACzC,eAAe;IACf,aAAa,CAAC,EAAE,CAAC,GAAG,EAAE,KAAK,KAAK,IAAI,CAAC;CACtC"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,OAAO,CAAC;AAE9B;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,+BAA+B;IAC/B,EAAE,EAAE,MAAM,CAAC;IACX,6BAA6B;IAC7B,QAAQ,EAAE,MAAM,CAAC;IACjB,2CAA2C;IAC3C,WAAW,CAAC,EAAE,UAAU,GAAG,WAAW,CAAC;IACvC,0BAA0B;IAC1B,IAAI,CAAC,EAAE,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;IAC7D,8CAA8C;IAC9C,gBAAgB,CAAC,EAAE,CAAC,UAAU,EAAE,UAAU,KAAK,IAAI,CAAC;IACpD,8CAA8C;IAC9C,aAAa,CAAC,EAAE,CAAC,GAAG,EAAE,KAAK,KAAK,IAAI,CAAC;CACtC;AAED;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC,4BAA4B;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,uCAAuC;IACvC,MAAM,EAAE,MAAM,CAAC;IACf,2BAA2B;IAC3B,SAAS,CAAC,EAAE,QAAQ,GAAG,QAAQ,CAAC;IAChC,4BAA4B;IAC5B,UAAU,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;CAC9B;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,gCAAgC;IAChC,aAAa,CAAC,EAAE,CAAC,aAAa,EAAE,WAAW,KAAK,IAAI,CAAC;IACrD,sCAAsC;IACtC,gBAAgB,CAAC,EAAE,CAAC,UAAU,EAAE,UAAU,KAAK,IAAI,CAAC;IACpD,sCAAsC;IACtC,iBAAiB,CAAC,EAAE,CAAC,GAAG,EAAE,KAAK,KAAK,IAAI,CAAC;IACzC,gCAAgC;IAChC,aAAa,CAAC,EAAE,CAAC,GAAG,EAAE,KAAK,KAAK,IAAI,CAAC;CACtC"}
package/dist/utils.d.ts CHANGED
@@ -1,19 +1,20 @@
1
+ import type { FontManager } from './font-manager';
1
2
  /**
2
- * 转换字体字重
3
- * @param weight 字体粗细
4
- * @returns 标准化后的字重
3
+ * Convert font weight
4
+ * @param weight Font weight
5
+ * @returns Normalized font weight
5
6
  */
6
- export declare function normalizeFontWeight(weight?: string | number): string;
7
+ export declare function normalizeFontWeight(weight?: string | number | null): string;
7
8
  /**
8
- * 计算SVG symbol的缩放比例
9
+ * Calculate SVG symbol scale ratio
9
10
  */
10
11
  export declare function calculateSymbolScale(symbol: SVGElement): number;
11
12
  /**
12
- * 内联SVG中的symbol元素
13
+ * Symbol element in inline SVG
13
14
  */
14
15
  export declare function inlineSvgSymbols(element: HTMLElement | SVGElement): void;
15
16
  /**
16
- * 递归处理SVG元素的字体属性
17
+ * Recursively process SVG element font attributes
17
18
  */
18
- export declare function processSvgFonts(element: Element): void;
19
+ export declare function processSvgFonts(element: Element, fontManager: FontManager): void;
19
20
  //# sourceMappingURL=utils.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,CAMpE;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,UAAU,GAAG,MAAM,CAU/D;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,WAAW,GAAG,UAAU,GAAG,IAAI,CAkCxE;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAqCtD"}
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAElD;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,GAAG,MAAM,CAM3E;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,UAAU,GAAG,MAAM,CAU/D;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,WAAW,GAAG,UAAU,GAAG,IAAI,CAkCxE;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,OAAO,EAAE,WAAW,EAAE,WAAW,GAAG,IAAI,CAqChF"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dom-to-vector-pdf",
3
- "version": "0.0.1",
3
+ "version": "0.0.3",
4
4
  "author": {
5
5
  "name": "xzboss"
6
6
  },
@@ -29,7 +29,9 @@
29
29
  "dev": "rollup -c -w",
30
30
  "test": "jest",
31
31
  "prepublishOnly": "npm run build",
32
- "release": "standard-version",
32
+ "release": "standard-version --release-as patch",
33
+ "release:minor": "standard-version --release-as minor",
34
+ "release:major": "standard-version --release-as major",
33
35
  "release:alpha": "standard-version --prerelease alpha",
34
36
  "release:beta": "standard-version --prerelease beta",
35
37
  "release:rc": "standard-version --prerelease rc",