dompdf.js 1.0.0

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.
Files changed (141) hide show
  1. package/CHANGELOG.md +566 -0
  2. package/LICENSE +22 -0
  3. package/README.md +155 -0
  4. package/README_CN.md +305 -0
  5. package/dist/__tests__/index.d.ts +1 -0
  6. package/dist/core/__mocks__/cache-storage.d.ts +2 -0
  7. package/dist/core/__mocks__/context.d.ts +9 -0
  8. package/dist/core/__mocks__/features.d.ts +8 -0
  9. package/dist/core/__mocks__/logger.d.ts +9 -0
  10. package/dist/core/__tests__/cache-storage.d.ts +1 -0
  11. package/dist/core/__tests__/logger.d.ts +1 -0
  12. package/dist/core/bitwise.d.ts +1 -0
  13. package/dist/core/cache-storage.d.ts +26 -0
  14. package/dist/core/context.d.ts +15 -0
  15. package/dist/core/debugger.d.ts +8 -0
  16. package/dist/core/features.d.ts +12 -0
  17. package/dist/core/logger.d.ts +18 -0
  18. package/dist/core/util.d.ts +1 -0
  19. package/dist/css/IPropertyDescriptor.d.ts +36 -0
  20. package/dist/css/ITypeDescriptor.d.ts +6 -0
  21. package/dist/css/index.d.ts +132 -0
  22. package/dist/css/layout/__mocks__/bounds.d.ts +2 -0
  23. package/dist/css/layout/bounds.d.ts +14 -0
  24. package/dist/css/layout/text.d.ts +10 -0
  25. package/dist/css/property-descriptors/__tests__/background-tests.d.ts +1 -0
  26. package/dist/css/property-descriptors/__tests__/font-family.d.ts +1 -0
  27. package/dist/css/property-descriptors/__tests__/paint-order.d.ts +1 -0
  28. package/dist/css/property-descriptors/__tests__/text-shadow.d.ts +1 -0
  29. package/dist/css/property-descriptors/__tests__/transform-tests.d.ts +1 -0
  30. package/dist/css/property-descriptors/background-clip.d.ts +8 -0
  31. package/dist/css/property-descriptors/background-color.d.ts +2 -0
  32. package/dist/css/property-descriptors/background-image.d.ts +3 -0
  33. package/dist/css/property-descriptors/background-origin.d.ts +8 -0
  34. package/dist/css/property-descriptors/background-position.d.ts +5 -0
  35. package/dist/css/property-descriptors/background-repeat.d.ts +9 -0
  36. package/dist/css/property-descriptors/background-size.d.ts +11 -0
  37. package/dist/css/property-descriptors/border-color.d.ts +5 -0
  38. package/dist/css/property-descriptors/border-radius.d.ts +7 -0
  39. package/dist/css/property-descriptors/border-style.d.ts +12 -0
  40. package/dist/css/property-descriptors/border-width.d.ts +5 -0
  41. package/dist/css/property-descriptors/box-shadow.d.ts +14 -0
  42. package/dist/css/property-descriptors/color.d.ts +2 -0
  43. package/dist/css/property-descriptors/content.d.ts +4 -0
  44. package/dist/css/property-descriptors/counter-increment.d.ts +7 -0
  45. package/dist/css/property-descriptors/counter-reset.d.ts +7 -0
  46. package/dist/css/property-descriptors/direction.d.ts +6 -0
  47. package/dist/css/property-descriptors/display.d.ts +35 -0
  48. package/dist/css/property-descriptors/duration.d.ts +2 -0
  49. package/dist/css/property-descriptors/float.d.ts +9 -0
  50. package/dist/css/property-descriptors/font-family.d.ts +4 -0
  51. package/dist/css/property-descriptors/font-size.d.ts +2 -0
  52. package/dist/css/property-descriptors/font-style.d.ts +7 -0
  53. package/dist/css/property-descriptors/font-variant.d.ts +2 -0
  54. package/dist/css/property-descriptors/font-weight.d.ts +2 -0
  55. package/dist/css/property-descriptors/letter-spacing.d.ts +2 -0
  56. package/dist/css/property-descriptors/line-break.d.ts +6 -0
  57. package/dist/css/property-descriptors/line-height.d.ts +4 -0
  58. package/dist/css/property-descriptors/list-style-image.d.ts +3 -0
  59. package/dist/css/property-descriptors/list-style-position.d.ts +6 -0
  60. package/dist/css/property-descriptors/list-style-type.d.ts +58 -0
  61. package/dist/css/property-descriptors/margin.d.ts +5 -0
  62. package/dist/css/property-descriptors/opacity.d.ts +2 -0
  63. package/dist/css/property-descriptors/overflow-wrap.d.ts +6 -0
  64. package/dist/css/property-descriptors/overflow.d.ts +9 -0
  65. package/dist/css/property-descriptors/padding.d.ts +5 -0
  66. package/dist/css/property-descriptors/paint-order.d.ts +8 -0
  67. package/dist/css/property-descriptors/position.d.ts +9 -0
  68. package/dist/css/property-descriptors/quotes.d.ts +8 -0
  69. package/dist/css/property-descriptors/text-align.d.ts +7 -0
  70. package/dist/css/property-descriptors/text-decoration-color.d.ts +2 -0
  71. package/dist/css/property-descriptors/text-decoration-line.d.ts +10 -0
  72. package/dist/css/property-descriptors/text-shadow.d.ts +12 -0
  73. package/dist/css/property-descriptors/text-transform.d.ts +8 -0
  74. package/dist/css/property-descriptors/transform-origin.d.ts +4 -0
  75. package/dist/css/property-descriptors/transform.d.ts +4 -0
  76. package/dist/css/property-descriptors/visibility.d.ts +7 -0
  77. package/dist/css/property-descriptors/webkit-text-stroke-color.d.ts +2 -0
  78. package/dist/css/property-descriptors/webkit-text-stroke-width.d.ts +2 -0
  79. package/dist/css/property-descriptors/word-break.d.ts +7 -0
  80. package/dist/css/property-descriptors/z-index.d.ts +7 -0
  81. package/dist/css/syntax/__tests__/tokernizer-tests.d.ts +1 -0
  82. package/dist/css/syntax/parser.d.ts +34 -0
  83. package/dist/css/syntax/tokenizer.d.ts +94 -0
  84. package/dist/css/types/__tests__/color-tests.d.ts +1 -0
  85. package/dist/css/types/__tests__/image-tests.d.ts +1 -0
  86. package/dist/css/types/angle.d.ts +7 -0
  87. package/dist/css/types/color.d.ts +11 -0
  88. package/dist/css/types/functions/-prefix-linear-gradient.d.ts +4 -0
  89. package/dist/css/types/functions/-prefix-radial-gradient.d.ts +4 -0
  90. package/dist/css/types/functions/-webkit-gradient.d.ts +4 -0
  91. package/dist/css/types/functions/__tests__/radial-gradient.d.ts +1 -0
  92. package/dist/css/types/functions/counter.d.ts +10 -0
  93. package/dist/css/types/functions/gradient.d.ts +7 -0
  94. package/dist/css/types/functions/linear-gradient.d.ts +4 -0
  95. package/dist/css/types/functions/radial-gradient.d.ts +12 -0
  96. package/dist/css/types/image.d.ts +54 -0
  97. package/dist/css/types/index.d.ts +1 -0
  98. package/dist/css/types/length-percentage.d.ts +11 -0
  99. package/dist/css/types/length.d.ts +4 -0
  100. package/dist/css/types/time.d.ts +2 -0
  101. package/dist/dom/__mocks__/document-cloner.d.ts +6 -0
  102. package/dist/dom/document-cloner.d.ts +45 -0
  103. package/dist/dom/element-container.d.ts +21 -0
  104. package/dist/dom/elements/li-element-container.d.ts +6 -0
  105. package/dist/dom/elements/ol-element-container.d.ts +7 -0
  106. package/dist/dom/elements/select-element-container.d.ts +6 -0
  107. package/dist/dom/elements/textarea-element-container.d.ts +6 -0
  108. package/dist/dom/node-parser.d.ts +23 -0
  109. package/dist/dom/replaced-elements/canvas-element-container.d.ts +8 -0
  110. package/dist/dom/replaced-elements/iframe-element-container.d.ts +11 -0
  111. package/dist/dom/replaced-elements/image-element-container.d.ts +8 -0
  112. package/dist/dom/replaced-elements/index.d.ts +4 -0
  113. package/dist/dom/replaced-elements/input-element-container.d.ts +12 -0
  114. package/dist/dom/replaced-elements/svg-element-container.d.ts +8 -0
  115. package/dist/dom/text-container.d.ts +8 -0
  116. package/dist/dompdf.esm.js +33182 -0
  117. package/dist/dompdf.esm.js.map +1 -0
  118. package/dist/dompdf.js +33190 -0
  119. package/dist/dompdf.js.map +1 -0
  120. package/dist/index.d.ts +18 -0
  121. package/dist/invariant.d.ts +1 -0
  122. package/dist/render/background.d.ts +16 -0
  123. package/dist/render/bezier-curve.d.ts +14 -0
  124. package/dist/render/border.d.ts +6 -0
  125. package/dist/render/bound-curves.d.ts +32 -0
  126. package/dist/render/box-sizing.d.ts +4 -0
  127. package/dist/render/canvas/canvas-renderer2.d.ts +81 -0
  128. package/dist/render/canvas/foreignobject-renderer.d.ts +11 -0
  129. package/dist/render/canvas/pdf-renderer.d.ts +82 -0
  130. package/dist/render/effects.d.ts +38 -0
  131. package/dist/render/font-metrics.d.ts +11 -0
  132. package/dist/render/path.d.ts +13 -0
  133. package/dist/render/renderer.d.ts +7 -0
  134. package/dist/render/stacking-context.d.ts +24 -0
  135. package/dist/render/vector.d.ts +9 -0
  136. package/html2pdf-userscript.js +936 -0
  137. package/package.json +134 -0
  138. package/tsconfig.json +23 -0
  139. package/userscript.js +372 -0
  140. package/webpack.base.js +31 -0
  141. package/webpack.dev.js +21 -0
@@ -0,0 +1,936 @@
1
+ // ==UserScript==
2
+ // @name HTML2PDF 网页元素转PDF
3
+ // @namespace http://tampermonkey.net/
4
+ // @version 1.0
5
+ // @description 在任意网站添加按钮,选择页面元素并生成PDF
6
+ // @author You
7
+ // @match *://*/*
8
+ // @grant none
9
+ // @require file:///D:/project-code/html2pdf/dist/html2pdf.js
10
+ // @require file:///D:/project-code/html2pdf/examples/SourceHanSansSC-Normal-Min-normal.js
11
+ // ==/UserScript==
12
+
13
+ (function () {
14
+ 'use strict';
15
+
16
+ // 全局变量
17
+ let isSelecting = false;
18
+ let selectedElement = null;
19
+ let overlay = null;
20
+ let controlPanel = null;
21
+
22
+ // 创建控制面板
23
+ function createControlPanel() {
24
+ const panel = document.createElement('div');
25
+ panel.id = 'html2pdf-control-panel';
26
+ panel.style.cssText = `
27
+ position: fixed;
28
+ top: 20px;
29
+ right: 20px;
30
+ z-index: 10000;
31
+ font-family: 'Arial', sans-serif;
32
+ transition: all 0.3s ease;
33
+ display: flex;
34
+ flex-direction: column;
35
+ align-items: flex-end;
36
+ `;
37
+
38
+ // 创建主面板内容(默认隐藏)
39
+ const panelContent = document.createElement('div');
40
+ panelContent.id = 'html2pdf-panel-content';
41
+ panelContent.style.cssText = `
42
+ background: linear-gradient(145deg, #0F1C2E, #1E2A45);
43
+ border: 1px solid #3A86FF;
44
+ border-radius: 10px;
45
+ padding: 15px;
46
+ box-shadow: 0 4px 20px rgba(0,0,0,0.4), 0 0 15px rgba(58, 134, 255, 0.4);
47
+ color: #e1e1e1;
48
+ min-width: 220px;
49
+ display: none;
50
+ backdrop-filter: blur(5px);
51
+ margin-top: 10px;
52
+ `;
53
+
54
+ panelContent.innerHTML = `
55
+ <div style="
56
+ margin-bottom: 15px;
57
+ font-weight: bold;
58
+ color: #5EEAD4;
59
+ font-size: 16px;
60
+ display: flex;
61
+ align-items: center;
62
+ justify-content: space-between;
63
+ ">
64
+ <span>HTML2PDF 工具</span>
65
+ <div style="
66
+ width: 40px;
67
+ height: 4px;
68
+ background: linear-gradient(90deg, #5EEAD4, #3A86FF);
69
+ border-radius: 2px;
70
+ box-shadow: 0 0 8px rgba(94, 234, 212, 0.6);
71
+ "></div>
72
+ </div>
73
+ <button id="select-element-btn" style="
74
+ width: 100%;
75
+ padding: 8px 12px;
76
+ margin-bottom: 10px;
77
+ background: linear-gradient(90deg, #3A86FF, #5E60CE);
78
+ color: white;
79
+ border: none;
80
+ border-radius: 6px;
81
+ cursor: pointer;
82
+ font-size: 14px;
83
+ box-shadow: 0 2px 10px rgba(58, 134, 255, 0.4);
84
+ transition: all 0.2s ease;
85
+ ">选择元素</button>
86
+ <button id="generate-pdf-btn" style="
87
+ width: 100%;
88
+ padding: 8px 12px;
89
+ margin-bottom: 10px;
90
+ background: linear-gradient(90deg, #5EEAD4, #38BDF8);
91
+ color: white;
92
+ border: none;
93
+ border-radius: 6px;
94
+ cursor: pointer;
95
+ font-size: 14px;
96
+ box-shadow: 0 2px 10px rgba(94, 234, 212, 0.4);
97
+ opacity: 0.5;
98
+ transition: all 0.2s ease;
99
+ margin-left:0;
100
+ text-shadow: 0 1px 2px rgba(0,0,0,0.3);
101
+ " disabled>生成PDF</button>
102
+ <button id="close-panel-btn" style="
103
+ width: 100%;
104
+ padding: 6px 12px;
105
+ background: linear-gradient(90deg, #F72585, #7209B7);
106
+ color: white;
107
+ border: none;
108
+ border-radius: 6px;
109
+ cursor: pointer;
110
+ font-size: 12px;
111
+ box-shadow: 0 2px 10px rgba(247, 37, 133, 0.4);
112
+ transition: all 0.2s ease;
113
+ margin-left: 0;
114
+ text-shadow: 0 1px 2px rgba(0,0,0,0.3);
115
+ ">关闭</button>
116
+ <div id="selected-info" style="
117
+ margin-top: 10px;
118
+ padding: 10px;
119
+ background: rgba(14, 23, 38, 0.6);
120
+ border-radius: 6px;
121
+ font-size: 12px;
122
+ color: #e1e1e1;
123
+ display: none;
124
+ border-left: 3px solid #5EEAD4;
125
+ box-shadow: 0 2px 8px rgba(0,0,0,0.2) inset;
126
+ "></div>
127
+ `;
128
+
129
+ // 创建触发按钮(默认显示)
130
+ const triggerButton = document.createElement('div');
131
+ triggerButton.id = 'html2pdf-trigger-button';
132
+ triggerButton.style.cssText = `
133
+ width: 50px;
134
+ height: 50px;
135
+ border-radius: 50%;
136
+ background: linear-gradient(145deg, #3A86FF, #5E60CE);
137
+ box-shadow: 0 4px 15px rgba(58, 134, 255, 0.5), 0 0 20px rgba(58, 134, 255, 0.3);
138
+ cursor: pointer;
139
+ display: flex;
140
+ align-items: center;
141
+ justify-content: center;
142
+ transition: all 0.3s ease;
143
+ position: relative;
144
+ overflow: hidden;
145
+ `;
146
+
147
+ // 添加PDF图标
148
+ triggerButton.innerHTML = `
149
+ <div style="
150
+ color: white;
151
+ font-size: 20px;
152
+ font-weight: bold;
153
+ text-shadow: 0 1px 2px rgba(0,0,0,0.3);
154
+ ">PDF</div>
155
+ <div style="
156
+ position: absolute;
157
+ width: 100%;
158
+ height: 100%;
159
+ border-radius: 50%;
160
+ border: 2px solid rgba(94, 234, 212, 0.4);
161
+ animation: pulse 2s infinite;
162
+ "></div>
163
+ `;
164
+
165
+ // 添加脉冲动画样式
166
+ const style = document.createElement('style');
167
+ style.textContent = `
168
+ @keyframes pulse {
169
+ 0% {
170
+ transform: scale(1);
171
+ opacity: 0.8;
172
+ }
173
+ 70% {
174
+ transform: scale(1.1);
175
+ opacity: 0;
176
+ }
177
+ 100% {
178
+ transform: scale(1);
179
+ opacity: 0;
180
+ }
181
+ }
182
+ #select-element-btn:hover, #generate-pdf-btn:not([disabled]):hover, #close-panel-btn:hover {
183
+ transform: translateY(-2px);
184
+ box-shadow: 0 4px 15px rgba(0,0,0,0.3);
185
+ filter: brightness(1.1);
186
+ }
187
+ #html2pdf-trigger-button:hover {
188
+ transform: scale(1.05);
189
+ box-shadow: 0 4px 20px rgba(58, 134, 255, 0.6), 0 0 30px rgba(58, 134, 255, 0.4);
190
+ }
191
+ .html2pdf-highlight {
192
+ outline: 3px solid #5EEAD4 !important;
193
+ outline-offset: 2px !important;
194
+ box-shadow: 0 0 15px rgba(94, 234, 212, 0.4) !important;
195
+ }
196
+ `;
197
+ document.head.appendChild(style);
198
+
199
+ // 将触发按钮和面板内容添加到主面板
200
+ panel.appendChild(triggerButton);
201
+ panel.appendChild(panelContent);
202
+ document.body.appendChild(panel);
203
+
204
+ // 添加触发按钮点击事件
205
+ triggerButton.addEventListener('click', () => {
206
+ const content = document.getElementById('html2pdf-panel-content');
207
+ if (content.style.display === 'none') {
208
+ content.style.display = 'block';
209
+ triggerButton.style.transform = 'scale(0.9)';
210
+ } else {
211
+ content.style.display = 'none';
212
+ triggerButton.style.transform = 'scale(1)';
213
+ }
214
+ });
215
+
216
+ return panel;
217
+ }
218
+
219
+ // 创建选择覆盖层
220
+ function createOverlay() {
221
+ const overlay = document.createElement('div');
222
+ overlay.id = 'html2pdf-overlay';
223
+ overlay.style.cssText = `
224
+ position: fixed;
225
+ top: 0;
226
+ left: 0;
227
+ width: 100%;
228
+ height: 100%;
229
+ background: rgba(0, 123, 186, 0.1);
230
+ z-index: 9999;
231
+ cursor: crosshair;
232
+ pointer-events: none;
233
+ `;
234
+ document.body.appendChild(overlay);
235
+ return overlay;
236
+ }
237
+
238
+ // 高亮元素
239
+ function highlightElement(element) {
240
+ // 移除之前的高亮
241
+ const prevHighlight = document.querySelector('.html2pdf-highlight');
242
+ if (prevHighlight) {
243
+ prevHighlight.classList.remove('html2pdf-highlight');
244
+ }
245
+
246
+ // 添加高亮样式
247
+ if (element && element !== document.body) {
248
+ element.classList.add('html2pdf-highlight');
249
+
250
+ // 添加高亮CSS
251
+ if (!document.querySelector('#html2pdf-highlight-style')) {
252
+ const style = document.createElement('style');
253
+ style.id = 'html2pdf-highlight-style';
254
+ // style.textContent = `
255
+ // .html2pdf-highlight {
256
+ // outline: 3px solid #007cba !important;
257
+ // outline-offset: 2px !important;
258
+ // }
259
+ // `;
260
+ document.head.appendChild(style);
261
+ }
262
+ }
263
+ }
264
+
265
+ // 高亮元素
266
+ function highlightElement(element) {
267
+ // 移除之前的高亮
268
+ const prevHighlight = document.querySelector('.html2pdf-highlight');
269
+ if (prevHighlight) {
270
+ prevHighlight.classList.remove('html2pdf-highlight');
271
+ }
272
+
273
+ // 添加高亮样式
274
+ if (element && element !== document.body) {
275
+ element.classList.add('html2pdf-highlight');
276
+
277
+ // 添加高亮CSS
278
+ if (!document.querySelector('#html2pdf-highlight-style')) {
279
+ const style = document.createElement('style');
280
+ style.id = 'html2pdf-highlight-style';
281
+ style.textContent = `
282
+ .html2pdf-highlight {
283
+ outline: 3px solid #007cba !important;
284
+ outline-offset: 2px !important;
285
+
286
+ }
287
+ `;
288
+ document.head.appendChild(style);
289
+ }
290
+ }
291
+ }
292
+
293
+ // 开始选择模式
294
+ function startSelection() {
295
+ isSelecting = true;
296
+ overlay = createOverlay();
297
+ document.body.style.cursor = 'crosshair';
298
+
299
+ // 更新按钮状态
300
+ const selectBtn = document.getElementById('select-element-btn');
301
+ selectBtn.textContent = '取消选择';
302
+ selectBtn.style.background = '#dc3545';
303
+
304
+ // 添加事件监听
305
+ document.addEventListener('mouseover', onMouseOver);
306
+ document.addEventListener('click', onElementClick);
307
+ document.addEventListener('keydown', onKeyDown);
308
+ }
309
+
310
+ // 停止选择模式
311
+ function stopSelection() {
312
+ isSelecting = false;
313
+ document.body.style.cursor = '';
314
+
315
+ if (overlay) {
316
+ overlay.remove();
317
+ overlay = null;
318
+ }
319
+
320
+ // 更新按钮状态
321
+ const selectBtn = document.getElementById('select-element-btn');
322
+ selectBtn.textContent = '选择元素';
323
+ selectBtn.style.background = 'linear-gradient(90deg, #4cc9f0, #4361ee)';
324
+
325
+ // 移除事件监听
326
+ document.removeEventListener('mouseover', onMouseOver);
327
+ document.removeEventListener('click', onElementClick);
328
+ document.removeEventListener('keydown', onKeyDown);
329
+ }
330
+
331
+ // 鼠标悬停事件
332
+ function onMouseOver(e) {
333
+ if (!isSelecting) return;
334
+ e.preventDefault();
335
+
336
+ const element = e.target;
337
+ if (element !== controlPanel && !controlPanel.contains(element)) {
338
+ highlightElement(element);
339
+ }
340
+ }
341
+
342
+ // 元素点击事件
343
+ function onElementClick(e) {
344
+ if (!isSelecting) return;
345
+ e.preventDefault();
346
+ e.stopPropagation();
347
+
348
+ const element = e.target;
349
+ if (element !== controlPanel && !controlPanel.contains(element)) {
350
+ selectedElement = element;
351
+ stopSelection();
352
+ updateSelectedInfo(element);
353
+ enablePdfGeneration();
354
+ }
355
+ }
356
+
357
+ // 键盘事件(ESC取消选择)
358
+ function onKeyDown(e) {
359
+ if (e.key === 'Escape' && isSelecting) {
360
+ stopSelection();
361
+ }
362
+ }
363
+
364
+ // 更新选中元素信息
365
+ function updateSelectedInfo(element) {
366
+ const info = document.getElementById('selected-info');
367
+ const tagName = element.tagName.toLowerCase();
368
+ const className = element.className ? `.${element.className.split(' ').join('.')}` : '';
369
+ const id = element.id ? `#${element.id}` : '';
370
+
371
+ // info.innerHTML = `
372
+ // <strong>已选择元素:</strong><br>
373
+ // 标签: ${tagName}${id}${className}<br>
374
+ // 尺寸: ${element.offsetWidth} × ${element.offsetHeight}px
375
+ // ${element.parentElement && element.parentElement !== document.body ?
376
+ // `<button id="select-parent-btn" style="
377
+ // margin-top: 8px;
378
+ // padding: 4px 8px;
379
+ // background: linear-gradient(90deg, #5E60CE, #7209B7);
380
+ // color: white;
381
+ // border: none;
382
+ // border-radius: 4px;
383
+ // cursor: pointer;
384
+ // font-size: 12px;
385
+ // box-shadow: 0 2px 6px rgba(94, 96, 206, 0.4);
386
+ // transition: all 0.2s ease;
387
+ // display: block;
388
+ // width: 100%;
389
+ // ">选择父元素</button>` :
390
+ // ''
391
+ // }
392
+ // `;
393
+ info.style.display = 'block';
394
+
395
+ // 如果有父元素且不是body,添加选择父元素按钮事件
396
+ // if (element.parentElement && element.parentElement !== document.body) {
397
+ // document.getElementById('select-parent-btn').addEventListener('click', () => {
398
+ // selectParentElement(element);
399
+ // });
400
+ // }
401
+ }
402
+
403
+ // 选择父元素
404
+ // function selectParentElement(element) {
405
+ // if (element && element.parentElement && element.parentElement !== document.body) {
406
+ // // 更新选中元素为父元素
407
+ // selectedElement = element.parentElement;
408
+
409
+ // // 高亮显示父元素
410
+ // highlightElement(selectedElement);
411
+
412
+ // // 更新选中信息
413
+ // updateSelectedInfo(selectedElement);
414
+ // }
415
+ // }
416
+
417
+ // 启用PDF生成按钮
418
+ function enablePdfGeneration() {
419
+ const pdfBtn = document.getElementById('generate-pdf-btn');
420
+ pdfBtn.disabled = false;
421
+ pdfBtn.style.opacity = '1';
422
+ }
423
+
424
+ // 生成PDF
425
+ async function generatePDF() {
426
+ if (!selectedElement) {
427
+ alert('请先选择要转换的元素');
428
+ return;
429
+ }
430
+
431
+ try {
432
+ // 显示加载状态
433
+ const pdfBtn = document.getElementById('generate-pdf-btn');
434
+ const originalText = pdfBtn.textContent;
435
+ pdfBtn.textContent = '生成中...';
436
+ pdfBtn.disabled = true;
437
+
438
+ // 使用html2canvas截图
439
+ html2pdf(selectedElement, {
440
+ useCORS: true,
441
+ scale: 1,
442
+ fontConfig: {
443
+ fontFamily: 'SourceHanSansCN-Medium',
444
+ fontBase64: window.fontBase64, //
445
+ fontUrl: '',
446
+ fontWeight: 400,
447
+ fontStyle: 'normal'
448
+ },
449
+ }).then(function (canvas) {
450
+ const link = document.createElement('a');
451
+ link.download = 'output.png';
452
+ link.href = canvas.toDataURL('image/png');
453
+ link.click();
454
+ // 恢复按钮状态
455
+ pdfBtn.textContent = originalText;
456
+ pdfBtn.disabled = false;
457
+
458
+ alert('PDF生成成功!');
459
+ }).catch(function (err) {
460
+ console.log('creacterr', err);
461
+
462
+ });;
463
+
464
+
465
+
466
+
467
+
468
+ } catch (error) {
469
+ console.error('PDF生成失败:', error);
470
+ alert('PDF生成失败,请检查控制台错误信息');
471
+
472
+ // 恢复按钮状态
473
+ const pdfBtn = document.getElementById('generate-pdf-btn');
474
+ pdfBtn.textContent = '生成PDF';
475
+ pdfBtn.disabled = false;
476
+ }
477
+ }
478
+
479
+
480
+ // 关闭面板
481
+ function closePanel() {
482
+ if (isSelecting) {
483
+ stopSelection();
484
+ }
485
+
486
+ // 移除高亮
487
+ const highlight = document.querySelector('.html2pdf-highlight');
488
+ if (highlight) {
489
+ highlight.classList.remove('html2pdf-highlight');
490
+ }
491
+
492
+ // 移除样式
493
+ const style = document.querySelector('#html2pdf-highlight-style');
494
+ if (style) {
495
+ style.remove();
496
+ }
497
+
498
+ // 移除面板
499
+ if (controlPanel) {
500
+ controlPanel.remove();
501
+ controlPanel = null;
502
+ }
503
+
504
+ selectedElement = null;
505
+ }
506
+
507
+ // 初始化
508
+ function init() {
509
+ // 等待页面加载完成
510
+ if (document.readyState === 'loading') {
511
+ document.addEventListener('DOMContentLoaded', init);
512
+ return;
513
+ }
514
+
515
+ // 创建控制面板
516
+ controlPanel = createControlPanel();
517
+
518
+ // 绑定事件
519
+ document.getElementById('select-element-btn').addEventListener('click', () => {
520
+ if (isSelecting) {
521
+ stopSelection();
522
+ } else {
523
+ startSelection();
524
+ }
525
+ });
526
+
527
+ document.getElementById('generate-pdf-btn').addEventListener('click', generatePDF);
528
+ document.getElementById('close-panel-btn').addEventListener('click', closePanel);
529
+
530
+ // 让面板可拖拽
531
+ let isDragging = false;
532
+ let dragOffset = {
533
+ x: 0,
534
+ y: 0
535
+ };
536
+
537
+ controlPanel.addEventListener('mousedown', (e) => {
538
+ if (e.target.tagName !== 'BUTTON') {
539
+ isDragging = true;
540
+ dragOffset.x = e.clientX - controlPanel.offsetLeft;
541
+ dragOffset.y = e.clientY - controlPanel.offsetTop;
542
+ controlPanel.style.cursor = 'move';
543
+ }
544
+ });
545
+
546
+ document.addEventListener('mousemove', (e) => {
547
+ if (isDragging) {
548
+ controlPanel.style.left = (e.clientX - dragOffset.x) + 'px';
549
+ controlPanel.style.top = (e.clientY - dragOffset.y) + 'px';
550
+ controlPanel.style.right = 'auto';
551
+ }
552
+ });
553
+
554
+ document.addEventListener('mouseup', () => {
555
+ isDragging = false;
556
+ controlPanel.style.cursor = '';
557
+ });
558
+
559
+ console.log('HTML2PDF 用户脚本已加载');
560
+ }
561
+
562
+ // 启动脚本
563
+ init();
564
+
565
+ })();
566
+
567
+
568
+
569
+ // (function () {
570
+ // 'use strict';
571
+
572
+ // // 全局变量
573
+ // let isSelecting = false;
574
+ // let selectedElement = null;
575
+ // let overlay = null;
576
+ // let controlPanel = null;
577
+
578
+ // // 创建控制面板
579
+ // function createControlPanel() {
580
+ // const panel = document.createElement('div');
581
+ // panel.id = 'dompdf-control-panel';
582
+ // panel.style.cssText = `
583
+ // position: fixed;
584
+ // top: 20px;
585
+ // right: 20px;
586
+ // z-index: 10000;
587
+ // background: #fff;
588
+ // border: 2px solid #007cba;
589
+ // border-radius: 8px;
590
+ // padding: 15px;
591
+ // box-shadow: 0 4px 12px rgba(0,0,0,0.15);
592
+ // font-family: Arial, sans-serif;
593
+ // min-width: 200px;
594
+ // `;
595
+
596
+ // panel.innerHTML = `
597
+ // <div style="margin-bottom: 10px; font-weight: bold; color: #333;">dompdf 工具</div>
598
+ // <button id="select-element-btn" style="
599
+ // width: 100%;
600
+ // padding: 8px 12px;
601
+ // margin-bottom: 8px;
602
+ // background: #007cba;
603
+ // color: white;
604
+ // border: none;
605
+ // border-radius: 4px;
606
+ // cursor: pointer;
607
+ // font-size: 14px;
608
+ // ">选择元素</button>
609
+ // <button id="generate-pdf-btn" style="
610
+ // width: 100%;
611
+ // padding: 8px 12px;
612
+ // margin-bottom: 8px;
613
+ // background: #28a745;
614
+ // color: white;
615
+ // border: none;
616
+ // border-radius: 4px;
617
+ // cursor: pointer;
618
+ // font-size: 14px;
619
+ // opacity: 0.5;
620
+ // margin-left:0
621
+ // " disabled>生成PDF</button>
622
+ // <button id="close-panel-btn" style="
623
+ // width: 100%;
624
+ // padding: 6px 12px;
625
+ // background: #dc3545;
626
+ // color: white;
627
+ // border: none;
628
+ // border-radius: 4px;
629
+ // cursor: pointer;
630
+ // font-size: 12px;
631
+ // margin - left: 0
632
+ // ">关闭</button>
633
+ // <div id="selected-info" style="
634
+ // margin-top: 10px;
635
+ // padding: 8px;
636
+ // background: #f8f9fa;
637
+ // border-radius: 4px;
638
+ // font-size: 12px;
639
+ // color: #666;
640
+ // display: none;
641
+ // "></div>
642
+ // `;
643
+
644
+ // document.body.appendChild(panel);
645
+ // return panel;
646
+ // }
647
+
648
+ // // 创建选择覆盖层
649
+ // function createOverlay() {
650
+ // const overlay = document.createElement('div');
651
+ // overlay.id = 'dompdf-overlay';
652
+ // overlay.style.cssText = `
653
+ // position: fixed;
654
+ // top: 0;
655
+ // left: 0;
656
+ // width: 100%;
657
+ // height: 100%;
658
+ // background: rgba(0, 123, 186, 0.1);
659
+ // z-index: 9999;
660
+ // cursor: crosshair;
661
+ // pointer-events: none;
662
+ // `;
663
+ // document.body.appendChild(overlay);
664
+ // return overlay;
665
+ // }
666
+
667
+ // // 高亮元素
668
+ // function highlightElement(element) {
669
+ // // 移除之前的高亮
670
+ // const prevHighlight = document.querySelector('.dompdf-highlight');
671
+ // if (prevHighlight) {
672
+ // prevHighlight.classList.remove('dompdf-highlight');
673
+ // }
674
+
675
+ // // 添加高亮样式
676
+ // if (element && element !== document.body) {
677
+ // element.classList.add('dompdf-highlight');
678
+
679
+ // // 添加高亮CSS
680
+ // if (!document.querySelector('#dompdf-highlight-style')) {
681
+ // const style = document.createElement('style');
682
+ // style.id = 'dompdf-highlight-style';
683
+ // style.textContent = `
684
+ // .dompdf-highlight {
685
+ // outline: 3px solid #007cba !important;
686
+ // outline-offset: 2px !important;
687
+
688
+ // }
689
+ // `;
690
+ // document.head.appendChild(style);
691
+ // }
692
+ // }
693
+ // }
694
+
695
+ // // 开始选择模式
696
+ // function startSelection() {
697
+ // isSelecting = true;
698
+ // overlay = createOverlay();
699
+ // document.body.style.cursor = 'crosshair';
700
+
701
+ // // 更新按钮状态
702
+ // const selectBtn = document.getElementById('select-element-btn');
703
+ // selectBtn.textContent = '取消选择';
704
+ // selectBtn.style.background = '#dc3545';
705
+
706
+ // // 添加事件监听
707
+ // document.addEventListener('mouseover', onMouseOver);
708
+ // document.addEventListener('click', onElementClick);
709
+ // document.addEventListener('keydown', onKeyDown);
710
+ // }
711
+
712
+ // // 停止选择模式
713
+ // function stopSelection() {
714
+ // isSelecting = false;
715
+ // document.body.style.cursor = '';
716
+
717
+ // if (overlay) {
718
+ // overlay.remove();
719
+ // overlay = null;
720
+ // }
721
+
722
+ // // 更新按钮状态
723
+ // const selectBtn = document.getElementById('select-element-btn');
724
+ // selectBtn.textContent = '选择元素';
725
+ // selectBtn.style.background = '#007cba';
726
+
727
+ // // 移除事件监听
728
+ // document.removeEventListener('mouseover', onMouseOver);
729
+ // document.removeEventListener('click', onElementClick);
730
+ // document.removeEventListener('keydown', onKeyDown);
731
+ // }
732
+
733
+ // // 鼠标悬停事件
734
+ // function onMouseOver(e) {
735
+ // if (!isSelecting) return;
736
+ // e.preventDefault();
737
+
738
+ // const element = e.target;
739
+ // if (element !== controlPanel && !controlPanel.contains(element)) {
740
+ // highlightElement(element);
741
+ // }
742
+ // }
743
+
744
+ // // 元素点击事件
745
+ // function onElementClick(e) {
746
+ // if (!isSelecting) return;
747
+ // e.preventDefault();
748
+ // e.stopPropagation();
749
+
750
+ // const element = e.target;
751
+ // if (element !== controlPanel && !controlPanel.contains(element)) {
752
+ // selectedElement = element;
753
+ // stopSelection();
754
+ // updateSelectedInfo(element);
755
+ // enablePdfGeneration();
756
+ // }
757
+ // }
758
+
759
+ // // 键盘事件(ESC取消选择)
760
+ // function onKeyDown(e) {
761
+ // if (e.key === 'Escape' && isSelecting) {
762
+ // stopSelection();
763
+ // }
764
+ // }
765
+
766
+ // // 更新选中元素信息
767
+ // function updateSelectedInfo(element) {
768
+ // const info = document.getElementById('selected-info');
769
+ // const tagName = element.tagName.toLowerCase();
770
+ // const className = element.className ? `.${element.className.split(' ').join('.')}` : '';
771
+ // const id = element.id ? `#${element.id}` : '';
772
+
773
+ // info.innerHTML = `
774
+ // <strong>已选择元素:</strong><br>
775
+ // 标签: ${tagName}${id}${className}<br>
776
+ // 尺寸: ${element.offsetWidth} × ${element.offsetHeight}px
777
+ // `;
778
+ // info.style.display = 'block';
779
+ // }
780
+
781
+ // // 启用PDF生成按钮
782
+ // function enablePdfGeneration() {
783
+ // const pdfBtn = document.getElementById('generate-pdf-btn');
784
+ // pdfBtn.disabled = false;
785
+ // pdfBtn.style.opacity = '1';
786
+ // }
787
+
788
+ // // 生成PDF
789
+ // async function generatePDF() {
790
+ // if (!selectedElement) {
791
+ // alert('请先选择要转换的元素');
792
+ // return;
793
+ // }
794
+
795
+ // try {
796
+ // // 显示加载状态
797
+ // const pdfBtn = document.getElementById('generate-pdf-btn');
798
+ // const originalText = pdfBtn.textContent;
799
+ // pdfBtn.textContent = '生成中...';
800
+ // pdfBtn.disabled = true;
801
+
802
+ // // 使用html2canvas截图
803
+ // dompdf(selectedElement, {
804
+ // useCORS: true,
805
+ // scale: 1,
806
+ // fontConfig: {
807
+ // fontFamily: 'SourceHanSansCN-Medium',
808
+ // fontBase64: window.fontBase64, //
809
+ // fontUrl: '',
810
+ // fontWeight: 400,
811
+ // fontStyle: 'normal'
812
+ // },
813
+ // }).then(function (blob) {
814
+ // const url = URL.createObjectURL(blob);
815
+ // const a = document.createElement('a');
816
+ // a.href = url;
817
+ // a.download = "example.pdf";
818
+ // document.body.appendChild(a);
819
+ // a.click();
820
+
821
+ // // 清理
822
+ // setTimeout(() => {
823
+ // document.body.removeChild(a);
824
+ // URL.revokeObjectURL(url);
825
+ // }, 100);
826
+ // // 恢复按钮状态
827
+ // pdfBtn.textContent = originalText;
828
+ // pdfBtn.disabled = false;
829
+
830
+ // alert('PDF生成成功!');
831
+ // }).catch(function (err) {
832
+ // console.log('creacterr', err);
833
+
834
+ // });;
835
+
836
+
837
+
838
+
839
+
840
+ // } catch (error) {
841
+ // console.error('PDF生成失败:', error);
842
+ // alert('PDF生成失败,请检查控制台错误信息');
843
+
844
+ // // 恢复按钮状态
845
+ // const pdfBtn = document.getElementById('generate-pdf-btn');
846
+ // pdfBtn.textContent = '生成PDF';
847
+ // pdfBtn.disabled = false;
848
+ // }
849
+ // }
850
+
851
+ // // 关闭面板
852
+ // function closePanel() {
853
+ // if (isSelecting) {
854
+ // stopSelection();
855
+ // }
856
+
857
+ // // 移除高亮
858
+ // const highlight = document.querySelector('.dompdf-highlight');
859
+ // if (highlight) {
860
+ // highlight.classList.remove('dompdf-highlight');
861
+ // }
862
+
863
+ // // 移除样式
864
+ // const style = document.querySelector('#dompdf-highlight-style');
865
+ // if (style) {
866
+ // style.remove();
867
+ // }
868
+
869
+ // // 移除面板
870
+ // if (controlPanel) {
871
+ // controlPanel.remove();
872
+ // controlPanel = null;
873
+ // }
874
+
875
+ // selectedElement = null;
876
+ // }
877
+
878
+ // // 初始化
879
+ // function init() {
880
+ // // 等待页面加载完成
881
+ // if (document.readyState === 'loading') {
882
+ // document.addEventListener('DOMContentLoaded', init);
883
+ // return;
884
+ // }
885
+
886
+ // // 创建控制面板
887
+ // controlPanel = createControlPanel();
888
+
889
+ // // 绑定事件
890
+ // document.getElementById('select-element-btn').addEventListener('click', () => {
891
+ // if (isSelecting) {
892
+ // stopSelection();
893
+ // } else {
894
+ // startSelection();
895
+ // }
896
+ // });
897
+
898
+ // document.getElementById('generate-pdf-btn').addEventListener('click', generatePDF);
899
+ // document.getElementById('close-panel-btn').addEventListener('click', closePanel);
900
+
901
+ // // 让面板可拖拽
902
+ // let isDragging = false;
903
+ // let dragOffset = {
904
+ // x: 0,
905
+ // y: 0
906
+ // };
907
+
908
+ // controlPanel.addEventListener('mousedown', (e) => {
909
+ // if (e.target.tagName !== 'BUTTON') {
910
+ // isDragging = true;
911
+ // dragOffset.x = e.clientX - controlPanel.offsetLeft;
912
+ // dragOffset.y = e.clientY - controlPanel.offsetTop;
913
+ // controlPanel.style.cursor = 'move';
914
+ // }
915
+ // });
916
+
917
+ // document.addEventListener('mousemove', (e) => {
918
+ // if (isDragging) {
919
+ // controlPanel.style.left = (e.clientX - dragOffset.x) + 'px';
920
+ // controlPanel.style.top = (e.clientY - dragOffset.y) + 'px';
921
+ // controlPanel.style.right = 'auto';
922
+ // }
923
+ // });
924
+
925
+ // document.addEventListener('mouseup', () => {
926
+ // isDragging = false;
927
+ // controlPanel.style.cursor = '';
928
+ // });
929
+
930
+ // console.log('dompdf 用户脚本已加载');
931
+ // }
932
+
933
+ // // 启动脚本
934
+ // init();
935
+
936
+ // })();