html2canvas-pro 2.1.0 → 2.2.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 (266) hide show
  1. package/dist/html2canvas-pro.esm.js +10226 -10526
  2. package/dist/html2canvas-pro.esm.js.map +1 -1
  3. package/dist/html2canvas-pro.js +10869 -11171
  4. package/dist/html2canvas-pro.js.map +1 -1
  5. package/dist/html2canvas-pro.min.js +8 -8
  6. package/dist/lib/config.js +0 -22
  7. package/dist/lib/core/cache-storage.js +3 -40
  8. package/dist/lib/core/constants.js +25 -0
  9. package/dist/lib/core/context.js +1 -0
  10. package/dist/lib/core/features.js +3 -2
  11. package/dist/lib/core/validator.js +3 -3
  12. package/dist/lib/css/grouped/background-styles.js +36 -0
  13. package/dist/lib/css/grouped/border-styles.js +75 -0
  14. package/dist/lib/css/grouped/font-styles.js +93 -0
  15. package/dist/lib/css/grouped/layout-styles.js +127 -0
  16. package/dist/lib/css/index.js +74 -46
  17. package/dist/lib/css/layout/text.js +7 -6
  18. package/dist/lib/css/property-descriptors/background-blend-mode.js +41 -0
  19. package/dist/lib/css/property-descriptors/border-image-repeat.js +42 -0
  20. package/dist/lib/css/property-descriptors/border-image-slice.js +45 -0
  21. package/dist/lib/css/property-descriptors/border-image-source.js +21 -0
  22. package/dist/lib/css/property-descriptors/border-radius.js +1 -1
  23. package/dist/lib/css/property-descriptors/box-decoration-break.js +18 -0
  24. package/dist/lib/css/property-descriptors/counter-increment.js +17 -12
  25. package/dist/lib/css/property-descriptors/counter-reset.js +4 -12
  26. package/dist/lib/css/property-descriptors/filter.js +76 -0
  27. package/dist/lib/css/property-descriptors/font-variant-ligatures.js +34 -0
  28. package/dist/lib/css/property-descriptors/object-fit.js +1 -1
  29. package/dist/lib/css/property-descriptors/object-position.js +42 -0
  30. package/dist/lib/css/property-descriptors/visibility.js +1 -1
  31. package/dist/lib/css/property-descriptors/zoom.js +18 -0
  32. package/dist/lib/css/syntax/parser.js +0 -1
  33. package/dist/lib/css/types/color.js +5 -1
  34. package/dist/lib/css/types/functions/repeating-linear-gradient.js +9 -0
  35. package/dist/lib/css/types/image.js +12 -2
  36. package/dist/lib/css/types/length-percentage.js +6 -2
  37. package/dist/lib/css/types/safe-eval.js +80 -0
  38. package/dist/lib/dom/document-cloner.js +23 -163
  39. package/dist/lib/dom/slot-cloner.js +176 -0
  40. package/dist/lib/index.js +1 -17
  41. package/dist/lib/render/canvas/background-renderer.js +169 -30
  42. package/dist/lib/render/canvas/border-image-renderer.js +153 -0
  43. package/dist/lib/render/canvas/canvas-renderer.js +39 -190
  44. package/dist/lib/render/canvas/content-renderer.js +202 -0
  45. package/dist/lib/render/canvas/effects-renderer.js +3 -0
  46. package/dist/lib/render/canvas/foreignobject-renderer.js +5 -1
  47. package/dist/lib/render/canvas/text/text-decoration-renderer.js +99 -0
  48. package/dist/lib/render/canvas/text-renderer.js +100 -224
  49. package/dist/lib/render/effects.js +38 -3
  50. package/dist/lib/render/object-fit.js +19 -15
  51. package/dist/lib/render/stacking-context.js +11 -0
  52. package/dist/types/config.d.ts +0 -10
  53. package/dist/types/core/cache-storage.d.ts +0 -24
  54. package/dist/types/core/constants.d.ts +22 -0
  55. package/dist/types/core/context.d.ts +3 -0
  56. package/dist/types/core/performance-monitor.d.ts +4 -4
  57. package/dist/types/core/validator.d.ts +6 -8
  58. package/dist/types/css/grouped/background-styles.d.ts +16 -0
  59. package/dist/types/css/grouped/border-styles.d.ts +31 -0
  60. package/dist/types/css/grouped/font-styles.d.ts +35 -0
  61. package/dist/types/css/grouped/layout-styles.d.ts +46 -0
  62. package/dist/types/css/index.d.ts +30 -0
  63. package/dist/types/css/property-descriptors/background-blend-mode.d.ts +23 -0
  64. package/dist/types/css/property-descriptors/border-image-repeat.d.ts +12 -0
  65. package/dist/types/css/property-descriptors/border-image-slice.d.ts +10 -0
  66. package/dist/types/css/property-descriptors/border-image-source.d.ts +4 -0
  67. package/dist/types/css/property-descriptors/box-decoration-break.d.ts +6 -0
  68. package/dist/types/css/property-descriptors/counter-increment.d.ts +3 -0
  69. package/dist/types/css/property-descriptors/filter.d.ts +3 -0
  70. package/dist/types/css/property-descriptors/font-variant-ligatures.d.ts +14 -0
  71. package/dist/types/css/property-descriptors/object-position.d.ts +4 -0
  72. package/dist/types/css/property-descriptors/zoom.d.ts +3 -0
  73. package/dist/types/css/types/functions/repeating-linear-gradient.d.ts +4 -0
  74. package/dist/types/css/types/image.d.ts +4 -2
  75. package/dist/types/css/types/safe-eval.d.ts +8 -0
  76. package/dist/types/dom/document-cloner.d.ts +3 -44
  77. package/dist/types/dom/slot-cloner.d.ts +66 -0
  78. package/dist/types/index.d.ts +3 -7
  79. package/dist/types/options.d.ts +11 -0
  80. package/dist/types/render/canvas/background-renderer.d.ts +23 -0
  81. package/dist/types/render/canvas/border-image-renderer.d.ts +18 -0
  82. package/dist/types/render/canvas/canvas-renderer.d.ts +1 -0
  83. package/dist/types/render/canvas/content-renderer.d.ts +44 -0
  84. package/dist/types/render/canvas/text/text-decoration-renderer.d.ts +18 -0
  85. package/dist/types/render/canvas/text-renderer.d.ts +12 -1
  86. package/dist/types/render/effects.d.ts +12 -2
  87. package/dist/types/render/object-fit.d.ts +2 -1
  88. package/dist/types/render/renderer-interface.d.ts +11 -9
  89. package/package.json +7 -20
  90. package/dist/lib/dom/replaced-elements/pseudo-elements.js +0 -0
  91. package/dist/lib/invariant.js +0 -9
  92. package/dist/types/dom/replaced-elements/pseudo-elements.d.ts +0 -0
  93. package/dist/types/invariant.d.ts +0 -1
  94. package/src/__tests__/index.ts +0 -99
  95. package/src/config.ts +0 -107
  96. package/src/core/__mocks__/cache-storage.ts +0 -1
  97. package/src/core/__mocks__/context.ts +0 -19
  98. package/src/core/__mocks__/features.ts +0 -8
  99. package/src/core/__mocks__/logger.ts +0 -17
  100. package/src/core/__tests__/cache-storage.test.ts +0 -205
  101. package/src/core/__tests__/cache-storage.ts +0 -278
  102. package/src/core/__tests__/logger.ts +0 -29
  103. package/src/core/__tests__/validator.ts +0 -359
  104. package/src/core/bitwise.ts +0 -1
  105. package/src/core/cache-storage.ts +0 -315
  106. package/src/core/context.ts +0 -31
  107. package/src/core/debugger.ts +0 -32
  108. package/src/core/features.ts +0 -222
  109. package/src/core/logger.ts +0 -64
  110. package/src/core/origin-checker.ts +0 -57
  111. package/src/core/performance-monitor.ts +0 -241
  112. package/src/core/render-element.ts +0 -272
  113. package/src/core/util.ts +0 -1
  114. package/src/core/validator.ts +0 -593
  115. package/src/css/index.ts +0 -427
  116. package/src/css/layout/__mocks__/bounds.ts +0 -6
  117. package/src/css/layout/bounds.ts +0 -79
  118. package/src/css/layout/text.ts +0 -161
  119. package/src/css/property-descriptor.ts +0 -49
  120. package/src/css/property-descriptors/__tests__/background-tests.ts +0 -65
  121. package/src/css/property-descriptors/__tests__/clip-path.test.ts +0 -280
  122. package/src/css/property-descriptors/__tests__/font-family.ts +0 -25
  123. package/src/css/property-descriptors/__tests__/image-rendering-integration.test.ts +0 -153
  124. package/src/css/property-descriptors/__tests__/image-rendering-performance.test.ts +0 -175
  125. package/src/css/property-descriptors/__tests__/image-rendering.test.ts +0 -72
  126. package/src/css/property-descriptors/__tests__/paint-order.ts +0 -87
  127. package/src/css/property-descriptors/__tests__/text-shadow.ts +0 -94
  128. package/src/css/property-descriptors/__tests__/transform-tests.ts +0 -18
  129. package/src/css/property-descriptors/background-clip.ts +0 -30
  130. package/src/css/property-descriptors/background-color.ts +0 -9
  131. package/src/css/property-descriptors/background-image.ts +0 -27
  132. package/src/css/property-descriptors/background-origin.ts +0 -31
  133. package/src/css/property-descriptors/background-position.ts +0 -38
  134. package/src/css/property-descriptors/background-repeat.ts +0 -44
  135. package/src/css/property-descriptors/background-size.ts +0 -27
  136. package/src/css/property-descriptors/border-color.ts +0 -13
  137. package/src/css/property-descriptors/border-radius.ts +0 -19
  138. package/src/css/property-descriptors/border-style.ts +0 -34
  139. package/src/css/property-descriptors/border-width.ts +0 -20
  140. package/src/css/property-descriptors/box-shadow.ts +0 -60
  141. package/src/css/property-descriptors/clip-path.ts +0 -271
  142. package/src/css/property-descriptors/color.ts +0 -9
  143. package/src/css/property-descriptors/content.ts +0 -26
  144. package/src/css/property-descriptors/counter-increment.ts +0 -43
  145. package/src/css/property-descriptors/counter-reset.ts +0 -36
  146. package/src/css/property-descriptors/direction.ts +0 -23
  147. package/src/css/property-descriptors/display.ts +0 -117
  148. package/src/css/property-descriptors/duration.ts +0 -14
  149. package/src/css/property-descriptors/float.ts +0 -29
  150. package/src/css/property-descriptors/font-family.ts +0 -38
  151. package/src/css/property-descriptors/font-size.ts +0 -9
  152. package/src/css/property-descriptors/font-style.ts +0 -25
  153. package/src/css/property-descriptors/font-variant.ts +0 -12
  154. package/src/css/property-descriptors/font-weight.ts +0 -26
  155. package/src/css/property-descriptors/image-rendering.ts +0 -33
  156. package/src/css/property-descriptors/letter-spacing.ts +0 -25
  157. package/src/css/property-descriptors/line-break.ts +0 -22
  158. package/src/css/property-descriptors/line-height.ts +0 -22
  159. package/src/css/property-descriptors/list-style-image.ts +0 -19
  160. package/src/css/property-descriptors/list-style-position.ts +0 -22
  161. package/src/css/property-descriptors/list-style-type.ts +0 -179
  162. package/src/css/property-descriptors/margin.ts +0 -13
  163. package/src/css/property-descriptors/mix-blend-mode.ts +0 -35
  164. package/src/css/property-descriptors/object-fit.ts +0 -39
  165. package/src/css/property-descriptors/opacity.ts +0 -15
  166. package/src/css/property-descriptors/overflow-wrap.ts +0 -22
  167. package/src/css/property-descriptors/overflow.ts +0 -34
  168. package/src/css/property-descriptors/padding.ts +0 -14
  169. package/src/css/property-descriptors/paint-order.ts +0 -42
  170. package/src/css/property-descriptors/position.ts +0 -30
  171. package/src/css/property-descriptors/quotes.ts +0 -57
  172. package/src/css/property-descriptors/rotate.ts +0 -34
  173. package/src/css/property-descriptors/text-align.ts +0 -26
  174. package/src/css/property-descriptors/text-decoration-color.ts +0 -9
  175. package/src/css/property-descriptors/text-decoration-line.ts +0 -38
  176. package/src/css/property-descriptors/text-decoration-style.ts +0 -32
  177. package/src/css/property-descriptors/text-decoration-thickness.ts +0 -30
  178. package/src/css/property-descriptors/text-overflow.ts +0 -23
  179. package/src/css/property-descriptors/text-shadow.ts +0 -52
  180. package/src/css/property-descriptors/text-transform.ts +0 -27
  181. package/src/css/property-descriptors/text-underline-offset.ts +0 -27
  182. package/src/css/property-descriptors/transform-origin.ts +0 -29
  183. package/src/css/property-descriptors/transform.ts +0 -74
  184. package/src/css/property-descriptors/visibility.ts +0 -25
  185. package/src/css/property-descriptors/webkit-line-clamp.ts +0 -30
  186. package/src/css/property-descriptors/webkit-text-stroke-color.ts +0 -8
  187. package/src/css/property-descriptors/webkit-text-stroke-width.ts +0 -15
  188. package/src/css/property-descriptors/word-break.ts +0 -25
  189. package/src/css/property-descriptors/writing-mode.ts +0 -37
  190. package/src/css/property-descriptors/z-index.ts +0 -27
  191. package/src/css/syntax/__tests__/tokernizer-tests.ts +0 -29
  192. package/src/css/syntax/parser.ts +0 -188
  193. package/src/css/syntax/tokenizer.ts +0 -822
  194. package/src/css/type-descriptor.ts +0 -7
  195. package/src/css/types/__tests__/color-tests.ts +0 -147
  196. package/src/css/types/__tests__/image-tests.ts +0 -239
  197. package/src/css/types/angle.ts +0 -86
  198. package/src/css/types/color-math.ts +0 -22
  199. package/src/css/types/color-spaces/a98.ts +0 -86
  200. package/src/css/types/color-spaces/p3.ts +0 -92
  201. package/src/css/types/color-spaces/pro-photo.ts +0 -87
  202. package/src/css/types/color-spaces/rec2020.ts +0 -90
  203. package/src/css/types/color-spaces/srgb.ts +0 -87
  204. package/src/css/types/color-utilities.ts +0 -452
  205. package/src/css/types/color.ts +0 -485
  206. package/src/css/types/functions/-prefix-linear-gradient.ts +0 -35
  207. package/src/css/types/functions/-prefix-radial-gradient.ts +0 -106
  208. package/src/css/types/functions/-webkit-gradient.ts +0 -69
  209. package/src/css/types/functions/__tests__/radial-gradient.ts +0 -69
  210. package/src/css/types/functions/counter.ts +0 -511
  211. package/src/css/types/functions/gradient.ts +0 -206
  212. package/src/css/types/functions/linear-gradient.ts +0 -28
  213. package/src/css/types/functions/radial-gradient.ts +0 -101
  214. package/src/css/types/image.ts +0 -120
  215. package/src/css/types/index.ts +0 -1
  216. package/src/css/types/length-percentage.ts +0 -137
  217. package/src/css/types/length.ts +0 -7
  218. package/src/css/types/time.ts +0 -20
  219. package/src/dom/__mocks__/document-cloner.ts +0 -22
  220. package/src/dom/__tests__/dom-normalizer.test.ts +0 -133
  221. package/src/dom/__tests__/element-container.test.ts +0 -129
  222. package/src/dom/document-cloner.ts +0 -929
  223. package/src/dom/dom-normalizer.ts +0 -133
  224. package/src/dom/element-container.ts +0 -75
  225. package/src/dom/elements/li-element-container.ts +0 -10
  226. package/src/dom/elements/ol-element-container.ts +0 -12
  227. package/src/dom/elements/select-element-container.ts +0 -10
  228. package/src/dom/elements/textarea-element-container.ts +0 -9
  229. package/src/dom/node-parser.ts +0 -177
  230. package/src/dom/node-type-guards.ts +0 -70
  231. package/src/dom/replaced-elements/canvas-element-container.ts +0 -15
  232. package/src/dom/replaced-elements/iframe-element-container.ts +0 -55
  233. package/src/dom/replaced-elements/image-element-container.ts +0 -16
  234. package/src/dom/replaced-elements/index.ts +0 -5
  235. package/src/dom/replaced-elements/input-element-container.ts +0 -105
  236. package/src/dom/replaced-elements/pseudo-elements.ts +0 -0
  237. package/src/dom/replaced-elements/svg-element-container.ts +0 -23
  238. package/src/dom/text-container.ts +0 -42
  239. package/src/global.d.ts +0 -19
  240. package/src/index.ts +0 -82
  241. package/src/invariant.ts +0 -5
  242. package/src/options.ts +0 -55
  243. package/src/render/__tests__/object-fit.test.ts +0 -85
  244. package/src/render/background.ts +0 -298
  245. package/src/render/bezier-curve.ts +0 -47
  246. package/src/render/border.ts +0 -165
  247. package/src/render/bound-curves.ts +0 -388
  248. package/src/render/box-sizing.ts +0 -31
  249. package/src/render/canvas/__tests__/background-renderer.test.ts +0 -72
  250. package/src/render/canvas/__tests__/border-renderer.test.ts +0 -24
  251. package/src/render/canvas/__tests__/effects-renderer.test.ts +0 -32
  252. package/src/render/canvas/__tests__/text-renderer.test.ts +0 -471
  253. package/src/render/canvas/background-renderer.ts +0 -271
  254. package/src/render/canvas/border-renderer.ts +0 -224
  255. package/src/render/canvas/canvas-path.ts +0 -31
  256. package/src/render/canvas/canvas-renderer.ts +0 -641
  257. package/src/render/canvas/effects-renderer.ts +0 -130
  258. package/src/render/canvas/foreignobject-renderer.ts +0 -53
  259. package/src/render/canvas/text-renderer.ts +0 -700
  260. package/src/render/effects.ts +0 -75
  261. package/src/render/font-metrics.ts +0 -72
  262. package/src/render/object-fit.ts +0 -100
  263. package/src/render/path.ts +0 -37
  264. package/src/render/renderer-interface.ts +0 -28
  265. package/src/render/stacking-context.ts +0 -386
  266. package/src/render/vector.ts +0 -19
@@ -9,7 +9,7 @@ const list_style_type_1 = require("../css/property-descriptors/list-style-type")
9
9
  const index_1 = require("../css/index");
10
10
  const quotes_1 = require("../css/property-descriptors/quotes");
11
11
  const debugger_1 = require("../core/debugger");
12
- const IGNORE_ATTRIBUTE = 'data-html2canvas-ignore';
12
+ const slot_cloner_1 = require("./slot-cloner");
13
13
  /**
14
14
  * Find the parent ShadowRoot of an element, if any
15
15
  * @param element - The element to check
@@ -39,6 +39,7 @@ class DocumentCloner {
39
39
  this.referenceElement = element;
40
40
  this.counters = new counter_1.CounterState();
41
41
  this.quoteDepth = 0;
42
+ this.slotCloner = new slot_cloner_1.SlotCloner((node, copyStyles) => this.cloneNode(node, copyStyles), { ignoreElements: options.ignoreElements, copyStyles: options.copyStyles ?? true }, context);
42
43
  if (!element.ownerDocument) {
43
44
  throw new Error('Cloned element does not have an owner document');
44
45
  }
@@ -98,26 +99,26 @@ class DocumentCloner {
98
99
  */
99
100
  const baseUri = ownerDocument.baseURI;
100
101
  documentClone.open();
102
+ // rawHTML is always a static, internally-generated string:
103
+ // serializeDoctype(document.doctype) + '<html></html>'
104
+ // No user-controlled input — safe for document.write in the sandbox iframe.
101
105
  const rawHTML = serializeDoctype(document.doctype) + '<html></html>';
102
106
  try {
103
- // Fixing "This document requires 'TrustedHTML' assignment. The action has been blocked." error.
104
- // Reuse existing policy when present (e.g. second html2canvas call) to avoid createPolicy duplicate-name throw.
105
107
  const ownerWindow = this.referenceElement.ownerDocument?.defaultView;
106
108
  const trustedTypesFactory = ownerWindow && ownerWindow.trustedTypes;
107
109
  let policy = trustedTypesFactory?.getPolicy?.('html2canvas-pro');
108
110
  if (!policy && trustedTypesFactory) {
109
111
  policy = trustedTypesFactory.createPolicy('html2canvas-pro', {
110
- createHTML: (string) => string
112
+ createHTML: (s) => s
111
113
  });
112
114
  }
113
- if (policy) {
114
- documentClone.write(policy.createHTML(rawHTML));
115
- }
116
- else {
117
- documentClone.write(rawHTML);
118
- }
115
+ // Prefer Trusted Types when available; fallback is the same static HTML.
116
+ const html = policy ? policy.createHTML(rawHTML) : rawHTML;
117
+ // CodeQL:no - rawHTML is a static internal string, never user-controlled
118
+ documentClone.write(html);
119
119
  }
120
120
  catch (_e) {
121
+ // CodeQL:no - rawHTML is a static internal string, never user-controlled
121
122
  documentClone.write(rawHTML);
122
123
  }
123
124
  // Chrome scrolls the parent document for some reason after the write to the cloned window???
@@ -284,162 +285,14 @@ class DocumentCloner {
284
285
  return blankCanvas;
285
286
  }
286
287
  appendChildNode(clone, child, copyStyles) {
287
- this.safeAppendClonedChild(clone, child, copyStyles);
288
- }
289
- /**
290
- * Check if a child node should be cloned based on filtering rules
291
- * Filters out: scripts, ignored elements, and optionally styles
292
- */
293
- shouldCloneChild(child) {
294
- return (!(0, node_parser_1.isElementNode)(child) ||
295
- (!(0, node_parser_1.isScriptElement)(child) &&
296
- !child.hasAttribute(IGNORE_ATTRIBUTE) &&
297
- (typeof this.options.ignoreElements !== 'function' || !this.options.ignoreElements(child))));
298
- }
299
- /**
300
- * Check if a style element should be cloned based on copyStyles option
301
- */
302
- shouldCloneStyleElement(child) {
303
- return !this.options.copyStyles || !(0, node_parser_1.isElementNode)(child) || !(0, node_parser_1.isStyleElement)(child);
304
- }
305
- /**
306
- * Safely append a cloned child to a target, applying all filtering rules
307
- */
308
- safeAppendClonedChild(target, child, copyStyles) {
309
- if (this.shouldCloneChild(child) && this.shouldCloneStyleElement(child)) {
310
- target.appendChild(this.cloneNode(child, copyStyles));
311
- }
312
- }
313
- /**
314
- * Clone assigned nodes from a slot element to the target
315
- */
316
- cloneAssignedNodes(assignedNodes, target, copyStyles) {
317
- assignedNodes.forEach((node) => {
318
- this.safeAppendClonedChild(target, node, copyStyles);
319
- });
320
- }
321
- /**
322
- * Clone fallback content from a slot element when no nodes are assigned
323
- */
324
- cloneSlotFallbackContent(slot, target, copyStyles) {
325
- for (let child = slot.firstChild; child; child = child.nextSibling) {
326
- this.safeAppendClonedChild(target, child, copyStyles);
327
- }
328
- }
329
- /**
330
- * Handle cloning of a slot element, including assigned nodes or fallback content
331
- */
332
- cloneSlotElement(slot, targetShadowRoot, copyStyles) {
333
- if (!(0, node_parser_1.isSlotElement)(slot)) {
334
- return;
335
- }
336
- const slotElement = slot;
337
- // Defensive check: ensure assignedNodes method exists
338
- if (typeof slotElement.assignedNodes !== 'function') {
339
- this.context.logger.warn('HTMLSlotElement.assignedNodes is not available', slot);
340
- this.cloneSlotFallbackContent(slot, targetShadowRoot, copyStyles);
341
- return;
342
- }
343
- const assignedNodes = slotElement.assignedNodes();
344
- // Defensive check: ensure assignedNodes returns an array
345
- if (!assignedNodes || !Array.isArray(assignedNodes)) {
346
- this.context.logger.warn('assignedNodes() did not return a valid array', slot);
347
- this.cloneSlotFallbackContent(slot, targetShadowRoot, copyStyles);
348
- return;
349
- }
350
- if (assignedNodes.length > 0) {
351
- // Clone assigned nodes
352
- this.cloneAssignedNodes(assignedNodes, targetShadowRoot, copyStyles);
353
- }
354
- else {
355
- // Clone fallback content
356
- this.cloneSlotFallbackContent(slot, targetShadowRoot, copyStyles);
357
- }
358
- }
359
- /**
360
- * Clone shadow DOM children to the target shadow root
361
- */
362
- cloneShadowDOMChildren(shadowRoot, targetShadowRoot, copyStyles) {
363
- for (let child = shadowRoot.firstChild; child; child = child.nextSibling) {
364
- if ((0, node_parser_1.isElementNode)(child) && (0, node_parser_1.isSlotElement)(child)) {
365
- // Handle slot elements specially
366
- this.cloneSlotElement(child, targetShadowRoot, copyStyles);
367
- }
368
- else {
369
- // Clone regular elements
370
- this.safeAppendClonedChild(targetShadowRoot, child, copyStyles);
371
- }
372
- }
373
- }
374
- /**
375
- * Clone light DOM children to the target element
376
- */
377
- cloneLightDOMChildren(node, clone, copyStyles) {
378
- for (let child = node.firstChild; child; child = child.nextSibling) {
379
- this.appendChildNode(clone, child, copyStyles);
380
- }
288
+ this.slotCloner.appendChildNode(clone, child, copyStyles);
381
289
  }
382
290
  /**
383
- * Clone slot element as light DOM when shadow root creation failed
384
- */
385
- cloneSlotElementAsLightDOM(slot, clone, copyStyles) {
386
- if (!(0, node_parser_1.isSlotElement)(slot)) {
387
- return;
388
- }
389
- const slotElement = slot;
390
- if (typeof slotElement.assignedNodes !== 'function') {
391
- // Fallback: clone slot's children
392
- for (let child = slot.firstChild; child; child = child.nextSibling) {
393
- this.appendChildNode(clone, child, copyStyles);
394
- }
395
- return;
396
- }
397
- const assignedNodes = slotElement.assignedNodes();
398
- if (assignedNodes && Array.isArray(assignedNodes) && assignedNodes.length > 0) {
399
- // Clone assigned nodes as light DOM
400
- assignedNodes.forEach((node) => this.appendChildNode(clone, node, copyStyles));
401
- }
402
- else {
403
- // Clone fallback content as light DOM
404
- for (let child = slot.firstChild; child; child = child.nextSibling) {
405
- this.appendChildNode(clone, child, copyStyles);
406
- }
407
- }
408
- }
409
- /**
410
- * Clone shadow DOM content as light DOM when shadow root creation failed
411
- * This is a fallback mechanism to ensure content is not lost
412
- */
413
- cloneShadowDOMAsLightDOM(shadowRoot, clone, copyStyles) {
414
- for (let child = shadowRoot.firstChild; child; child = child.nextSibling) {
415
- if ((0, node_parser_1.isElementNode)(child) && (0, node_parser_1.isSlotElement)(child)) {
416
- this.cloneSlotElementAsLightDOM(child, clone, copyStyles);
417
- }
418
- else {
419
- this.appendChildNode(clone, child, copyStyles);
420
- }
421
- }
422
- }
423
- /**
424
- * Clone child nodes from source element to clone element
425
- * Handles shadow DOM, slots, and light DOM appropriately
291
+ * Clone child nodes from source element to clone element.
292
+ * Delegates to SlotCloner which handles shadow DOM, slots, and light DOM.
426
293
  */
427
294
  cloneChildNodes(node, clone, copyStyles) {
428
- if (node.shadowRoot && clone.shadowRoot) {
429
- // Both original and clone have shadow roots - clone shadow DOM content
430
- this.cloneShadowDOMChildren(node.shadowRoot, clone.shadowRoot, copyStyles);
431
- // Also clone light DOM (slot content sources)
432
- this.cloneLightDOMChildren(node, clone, copyStyles);
433
- }
434
- else if (node.shadowRoot && !clone.shadowRoot) {
435
- // Original has shadow root but clone doesn't (creation failed)
436
- // Fallback: clone shadow DOM content as light DOM to preserve content
437
- this.cloneShadowDOMAsLightDOM(node.shadowRoot, clone, copyStyles);
438
- }
439
- else {
440
- // No shadow DOM - just clone light DOM children
441
- this.cloneLightDOMChildren(node, clone, copyStyles);
442
- }
295
+ this.slotCloner.cloneChildNodes(node, clone, copyStyles);
443
296
  }
444
297
  cloneNode(node, copyStyles) {
445
298
  if ((0, node_parser_1.isTextNode)(node)) {
@@ -606,7 +459,7 @@ const createIFrameContainer = (ownerDocument, bounds, customContainer) => {
606
459
  cloneIframeContainer.width = bounds.width.toString();
607
460
  cloneIframeContainer.height = bounds.height.toString();
608
461
  cloneIframeContainer.scrolling = 'no'; // ios won't scroll without it
609
- cloneIframeContainer.setAttribute(IGNORE_ATTRIBUTE, 'true');
462
+ cloneIframeContainer.setAttribute(slot_cloner_1.IGNORE_ATTRIBUTE, 'true');
610
463
  // Use custom container if provided, otherwise use body
611
464
  const container = customContainer || ownerDocument.body;
612
465
  container.appendChild(cloneIframeContainer);
@@ -638,11 +491,18 @@ const iframeLoader = (iframe) => {
638
491
  const documentClone = cloneWindow.document;
639
492
  cloneWindow.onload = iframe.onload = () => {
640
493
  cloneWindow.onload = iframe.onload = null;
494
+ const MAX_POLL_ATTEMPTS = 600; // 30 seconds at 50ms intervals
495
+ let attempts = 0;
641
496
  const interval = setInterval(() => {
497
+ attempts++;
642
498
  if (documentClone.body.childNodes.length > 0 && documentClone.readyState === 'complete') {
643
499
  clearInterval(interval);
644
500
  resolve(iframe);
645
501
  }
502
+ else if (attempts >= MAX_POLL_ATTEMPTS) {
503
+ clearInterval(interval);
504
+ resolve(iframe); // resolve anyway to avoid hanging
505
+ }
646
506
  }, 50);
647
507
  };
648
508
  });
@@ -0,0 +1,176 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SlotCloner = exports.IGNORE_ATTRIBUTE = void 0;
4
+ const node_parser_1 = require("./node-parser");
5
+ /** Exported for reuse in document-cloner.ts */
6
+ exports.IGNORE_ATTRIBUTE = 'data-html2canvas-ignore';
7
+ /**
8
+ * Handles shadow DOM child cloning, slot assignment, and light DOM traversal.
9
+ * Extracted from DocumentCloner to reduce file size and improve separation of concerns.
10
+ */
11
+ class SlotCloner {
12
+ constructor(cloneNodeFn, options, context) {
13
+ this.cloneNodeFn = cloneNodeFn;
14
+ this.options = options;
15
+ this.context = context;
16
+ }
17
+ appendChildNode(clone, child, copyStyles) {
18
+ this.safeAppendClonedChild(clone, child, copyStyles);
19
+ }
20
+ /**
21
+ * Clone child nodes from source element to clone element.
22
+ * Handles shadow DOM, slots, and light DOM appropriately.
23
+ */
24
+ cloneChildNodes(node, clone, copyStyles) {
25
+ if (node.shadowRoot && clone.shadowRoot) {
26
+ // Both original and clone have shadow roots - clone shadow DOM content
27
+ this.cloneShadowDOMChildren(node.shadowRoot, clone.shadowRoot, copyStyles);
28
+ // Also clone light DOM (slot content sources)
29
+ this.cloneLightDOMChildren(node, clone, copyStyles);
30
+ }
31
+ else if (node.shadowRoot && !clone.shadowRoot) {
32
+ // Original has shadow root but clone doesn't (creation failed)
33
+ // Fallback: clone shadow DOM content as light DOM to preserve content
34
+ this.cloneShadowDOMAsLightDOM(node.shadowRoot, clone, copyStyles);
35
+ }
36
+ else {
37
+ // No shadow DOM - just clone light DOM children
38
+ this.cloneLightDOMChildren(node, clone, copyStyles);
39
+ }
40
+ }
41
+ /**
42
+ * Check if a child node should be cloned based on filtering rules.
43
+ * Filters out: scripts, ignored elements, and optionally styles.
44
+ */
45
+ shouldCloneChild(child) {
46
+ return (!(0, node_parser_1.isElementNode)(child) ||
47
+ (!(0, node_parser_1.isScriptElement)(child) &&
48
+ !child.hasAttribute(exports.IGNORE_ATTRIBUTE) &&
49
+ (typeof this.options.ignoreElements !== 'function' || !this.options.ignoreElements(child))));
50
+ }
51
+ /**
52
+ * Check if a style element should be cloned based on copyStyles option.
53
+ */
54
+ shouldCloneStyleElement(child) {
55
+ return !this.options.copyStyles || !(0, node_parser_1.isElementNode)(child) || !(0, node_parser_1.isStyleElement)(child);
56
+ }
57
+ /**
58
+ * Safely append a cloned child to a target, applying all filtering rules.
59
+ */
60
+ safeAppendClonedChild(target, child, copyStyles) {
61
+ if (this.shouldCloneChild(child) && this.shouldCloneStyleElement(child)) {
62
+ target.appendChild(this.cloneNodeFn(child, copyStyles));
63
+ }
64
+ }
65
+ /**
66
+ * Clone assigned nodes from a slot element to the target.
67
+ */
68
+ cloneAssignedNodes(assignedNodes, target, copyStyles) {
69
+ assignedNodes.forEach((node) => {
70
+ this.safeAppendClonedChild(target, node, copyStyles);
71
+ });
72
+ }
73
+ /**
74
+ * Clone fallback content from a slot element when no nodes are assigned.
75
+ */
76
+ cloneSlotFallbackContent(slot, target, copyStyles) {
77
+ for (let child = slot.firstChild; child; child = child.nextSibling) {
78
+ this.safeAppendClonedChild(target, child, copyStyles);
79
+ }
80
+ }
81
+ /**
82
+ * Handle cloning of a slot element, including assigned nodes or fallback content.
83
+ */
84
+ cloneSlotElement(slot, targetShadowRoot, copyStyles) {
85
+ if (!(0, node_parser_1.isSlotElement)(slot)) {
86
+ return;
87
+ }
88
+ const slotElement = slot;
89
+ // Defensive check: ensure assignedNodes method exists
90
+ if (typeof slotElement.assignedNodes !== 'function') {
91
+ this.context.logger.warn('HTMLSlotElement.assignedNodes is not available', slot);
92
+ this.cloneSlotFallbackContent(slot, targetShadowRoot, copyStyles);
93
+ return;
94
+ }
95
+ const assignedNodes = slotElement.assignedNodes();
96
+ // Defensive check: ensure assignedNodes returns an array
97
+ if (!assignedNodes || !Array.isArray(assignedNodes)) {
98
+ this.context.logger.warn('assignedNodes() did not return a valid array', slot);
99
+ this.cloneSlotFallbackContent(slot, targetShadowRoot, copyStyles);
100
+ return;
101
+ }
102
+ if (assignedNodes.length > 0) {
103
+ // Clone assigned nodes
104
+ this.cloneAssignedNodes(assignedNodes, targetShadowRoot, copyStyles);
105
+ }
106
+ else {
107
+ // Clone fallback content
108
+ this.cloneSlotFallbackContent(slot, targetShadowRoot, copyStyles);
109
+ }
110
+ }
111
+ /**
112
+ * Clone shadow DOM children to the target shadow root.
113
+ */
114
+ cloneShadowDOMChildren(shadowRoot, targetShadowRoot, copyStyles) {
115
+ for (let child = shadowRoot.firstChild; child; child = child.nextSibling) {
116
+ if ((0, node_parser_1.isElementNode)(child) && (0, node_parser_1.isSlotElement)(child)) {
117
+ // Handle slot elements specially
118
+ this.cloneSlotElement(child, targetShadowRoot, copyStyles);
119
+ }
120
+ else {
121
+ // Clone regular elements
122
+ this.safeAppendClonedChild(targetShadowRoot, child, copyStyles);
123
+ }
124
+ }
125
+ }
126
+ /**
127
+ * Clone light DOM children to the target element.
128
+ */
129
+ cloneLightDOMChildren(node, clone, copyStyles) {
130
+ for (let child = node.firstChild; child; child = child.nextSibling) {
131
+ this.appendChildNode(clone, child, copyStyles);
132
+ }
133
+ }
134
+ /**
135
+ * Clone slot element as light DOM when shadow root creation failed.
136
+ */
137
+ cloneSlotElementAsLightDOM(slot, clone, copyStyles) {
138
+ if (!(0, node_parser_1.isSlotElement)(slot)) {
139
+ return;
140
+ }
141
+ const slotElement = slot;
142
+ if (typeof slotElement.assignedNodes !== 'function') {
143
+ // Fallback: clone slot's children
144
+ for (let child = slot.firstChild; child; child = child.nextSibling) {
145
+ this.appendChildNode(clone, child, copyStyles);
146
+ }
147
+ return;
148
+ }
149
+ const assignedNodes = slotElement.assignedNodes();
150
+ if (assignedNodes && Array.isArray(assignedNodes) && assignedNodes.length > 0) {
151
+ // Clone assigned nodes as light DOM
152
+ assignedNodes.forEach((node) => this.appendChildNode(clone, node, copyStyles));
153
+ }
154
+ else {
155
+ // Clone fallback content as light DOM
156
+ for (let child = slot.firstChild; child; child = child.nextSibling) {
157
+ this.appendChildNode(clone, child, copyStyles);
158
+ }
159
+ }
160
+ }
161
+ /**
162
+ * Clone shadow DOM content as light DOM when shadow root creation failed.
163
+ * This is a fallback mechanism to ensure content is not lost.
164
+ */
165
+ cloneShadowDOMAsLightDOM(shadowRoot, clone, copyStyles) {
166
+ for (let child = shadowRoot.firstChild; child; child = child.nextSibling) {
167
+ if ((0, node_parser_1.isElementNode)(child) && (0, node_parser_1.isSlotElement)(child)) {
168
+ this.cloneSlotElementAsLightDOM(child, clone, copyStyles);
169
+ }
170
+ else {
171
+ this.appendChildNode(clone, child, copyStyles);
172
+ }
173
+ }
174
+ }
175
+ }
176
+ exports.SlotCloner = SlotCloner;
package/dist/lib/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.IMAGE_RENDERING = exports.PerformanceMonitor = exports.createDefaultValidator = exports.Validator = exports.Html2CanvasConfig = exports.html2canvas = void 0;
3
+ exports.PerformanceMonitor = exports.createDefaultValidator = exports.Validator = exports.Html2CanvasConfig = exports.html2canvas = void 0;
4
4
  const config_1 = require("./config");
5
5
  Object.defineProperty(exports, "Html2CanvasConfig", { enumerable: true, get: function () { return config_1.Html2CanvasConfig; } });
6
6
  const validator_1 = require("./core/validator");
@@ -46,20 +46,4 @@ const html2canvas = (element, options = {}, config) => {
46
46
  return (0, render_element_1.renderElement)(element, options, finalConfig);
47
47
  };
48
48
  exports.html2canvas = html2canvas;
49
- /**
50
- * Set CSP nonce for inline styles.
51
- *
52
- * @deprecated Since 2.0.0. Pass `cspNonce` in options instead:
53
- * `html2canvas(element, { cspNonce: '...' })`
54
- */
55
- const setCspNonce = (nonce) => {
56
- console.warn('[html2canvas-pro] setCspNonce is deprecated. ' +
57
- 'Pass cspNonce in options instead: html2canvas(element, { cspNonce: "..." })');
58
- if (typeof window !== 'undefined') {
59
- (0, config_1.setDefaultConfig)(new config_1.Html2CanvasConfig({ window, cspNonce: nonce }));
60
- }
61
- };
62
- html2canvas.setCspNonce = setCspNonce;
63
49
  exports.default = html2canvas;
64
- var image_rendering_1 = require("./css/property-descriptors/image-rendering");
65
- Object.defineProperty(exports, "IMAGE_RENDERING", { enumerable: true, get: function () { return image_rendering_1.IMAGE_RENDERING; } });