html2canvas-pro 2.4.5 → 2.5.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 (228) hide show
  1. package/README.md +115 -13
  2. package/dist/html2canvas-pro.cjs +3058 -1607
  3. package/dist/html2canvas-pro.cjs.map +1 -1
  4. package/dist/html2canvas-pro.esm.js +3058 -1607
  5. package/dist/html2canvas-pro.esm.js.map +1 -1
  6. package/dist/html2canvas-pro.js +3055 -1604
  7. package/dist/html2canvas-pro.js.map +1 -1
  8. package/dist/html2canvas-pro.min.js +5 -5
  9. package/dist/types/core/cache-storage.d.ts +4 -1
  10. package/dist/types/core/context.d.ts +10 -1
  11. package/dist/types/core/render-element.d.ts +11 -0
  12. package/dist/types/core/util.d.ts +6 -0
  13. package/dist/types/css/index.d.ts +77 -46
  14. package/dist/types/css/parse.d.ts +15 -0
  15. package/dist/types/css/property-descriptors/accent-color.d.ts +5 -0
  16. package/dist/types/css/property-descriptors/backdrop-filter.d.ts +9 -0
  17. package/dist/types/css/property-descriptors/background-blend-mode.d.ts +16 -16
  18. package/dist/types/css/property-descriptors/border-image-width.d.ts +36 -0
  19. package/dist/types/css/property-descriptors/clip-path.d.ts +16 -2
  20. package/dist/types/css/property-descriptors/isolation.d.ts +6 -0
  21. package/dist/types/css/property-descriptors/mask.d.ts +25 -0
  22. package/dist/types/css/property-descriptors/mix-blend-mode.d.ts +16 -16
  23. package/dist/types/css/property-descriptors/outline.d.ts +15 -0
  24. package/dist/types/css/property-descriptors/text-emphasis.d.ts +22 -0
  25. package/dist/types/css/property-descriptors/text-shadow.d.ts +1 -1
  26. package/dist/types/css/property-descriptors/webkit-box-reflect.d.ts +19 -0
  27. package/dist/types/css/property-descriptors/webkit-text-fill-color.d.ts +9 -0
  28. package/dist/types/css/syntax/token-constants.d.ts +1 -1
  29. package/dist/types/css/types/color-math.d.ts +7 -1
  30. package/dist/types/css/types/color-spaces/a98.d.ts +2 -1
  31. package/dist/types/css/types/color-spaces/p3.d.ts +5 -4
  32. package/dist/types/css/types/color-spaces/pro-photo.d.ts +5 -4
  33. package/dist/types/css/types/color-spaces/rec2020.d.ts +5 -4
  34. package/dist/types/css/types/color-spaces/srgb.d.ts +5 -4
  35. package/dist/types/css/types/color-utilities.d.ts +11 -11
  36. package/dist/types/css/types/color.d.ts +1 -0
  37. package/dist/types/css/types/functions/conic-gradient.d.ts +11 -0
  38. package/dist/types/css/types/functions/image-set.d.ts +11 -0
  39. package/dist/types/css/types/functions/repeating-radial-gradient.d.ts +8 -0
  40. package/dist/types/css/types/image.d.ts +15 -2
  41. package/dist/types/css/types/safe-eval.d.ts +0 -6
  42. package/dist/types/dom/copy-css-styles.d.ts +8 -0
  43. package/dist/types/dom/document-cloner.d.ts +3 -13
  44. package/dist/types/dom/iframe-mount.d.ts +37 -0
  45. package/dist/types/dom/pseudo-content.d.ts +33 -0
  46. package/dist/types/dom/replaced-elements/iframe-element-container.d.ts +2 -2
  47. package/dist/types/options.d.ts +8 -2
  48. package/dist/types/render/canvas/background-renderer.d.ts +19 -0
  49. package/dist/types/render/canvas/border-image-renderer.d.ts +50 -1
  50. package/dist/types/render/canvas/canvas-renderer.d.ts +21 -15
  51. package/dist/types/render/canvas/mask-renderer.d.ts +36 -0
  52. package/dist/types/render/canvas/text-clip-renderer.d.ts +36 -0
  53. package/dist/types/render/canvas/text-renderer.d.ts +22 -0
  54. package/dist/types/render/stacking-context.d.ts +4 -1
  55. package/package.json +39 -40
  56. package/dist/lib/config.js +0 -49
  57. package/dist/lib/core/abort-helper.js +0 -20
  58. package/dist/lib/core/background-parser.js +0 -41
  59. package/dist/lib/core/bitwise.js +0 -5
  60. package/dist/lib/core/cache-storage.js +0 -283
  61. package/dist/lib/core/config-assembler.js +0 -88
  62. package/dist/lib/core/constants.js +0 -25
  63. package/dist/lib/core/context.js +0 -19
  64. package/dist/lib/core/debugger.js +0 -27
  65. package/dist/lib/core/features.js +0 -190
  66. package/dist/lib/core/logger.js +0 -56
  67. package/dist/lib/core/lru-map.js +0 -66
  68. package/dist/lib/core/origin-checker.js +0 -53
  69. package/dist/lib/core/performance-monitor.js +0 -185
  70. package/dist/lib/core/render-element.js +0 -131
  71. package/dist/lib/core/util.js +0 -4
  72. package/dist/lib/core/validator.js +0 -500
  73. package/dist/lib/css/grouped/background-styles.js +0 -36
  74. package/dist/lib/css/grouped/border-styles.js +0 -75
  75. package/dist/lib/css/grouped/font-styles.js +0 -93
  76. package/dist/lib/css/grouped/layout-styles.js +0 -127
  77. package/dist/lib/css/index.js +0 -339
  78. package/dist/lib/css/layout/bounds.js +0 -52
  79. package/dist/lib/css/layout/text.js +0 -133
  80. package/dist/lib/css/property-descriptor.js +0 -2
  81. package/dist/lib/css/property-descriptors/background-blend-mode.js +0 -41
  82. package/dist/lib/css/property-descriptors/background-clip.js +0 -25
  83. package/dist/lib/css/property-descriptors/background-color.js +0 -10
  84. package/dist/lib/css/property-descriptors/background-image.js +0 -24
  85. package/dist/lib/css/property-descriptors/background-origin.js +0 -23
  86. package/dist/lib/css/property-descriptors/background-position.js +0 -19
  87. package/dist/lib/css/property-descriptors/background-repeat.js +0 -33
  88. package/dist/lib/css/property-descriptors/background-size.js +0 -23
  89. package/dist/lib/css/property-descriptors/border-color.js +0 -14
  90. package/dist/lib/css/property-descriptors/border-image-repeat.js +0 -42
  91. package/dist/lib/css/property-descriptors/border-image-slice.js +0 -45
  92. package/dist/lib/css/property-descriptors/border-image-source.js +0 -22
  93. package/dist/lib/css/property-descriptors/border-radius.js +0 -15
  94. package/dist/lib/css/property-descriptors/border-style.js +0 -26
  95. package/dist/lib/css/property-descriptors/border-width.js +0 -20
  96. package/dist/lib/css/property-descriptors/box-decoration-break.js +0 -18
  97. package/dist/lib/css/property-descriptors/box-shadow.js +0 -54
  98. package/dist/lib/css/property-descriptors/clip-path.js +0 -189
  99. package/dist/lib/css/property-descriptors/color.js +0 -10
  100. package/dist/lib/css/property-descriptors/content.js +0 -19
  101. package/dist/lib/css/property-descriptors/counter-increment.js +0 -35
  102. package/dist/lib/css/property-descriptors/counter-reset.js +0 -18
  103. package/dist/lib/css/property-descriptors/direction.js +0 -18
  104. package/dist/lib/css/property-descriptors/display.js +0 -81
  105. package/dist/lib/css/property-descriptors/duration.js +0 -14
  106. package/dist/lib/css/property-descriptors/filter.js +0 -86
  107. package/dist/lib/css/property-descriptors/float.js +0 -22
  108. package/dist/lib/css/property-descriptors/font-family.js +0 -47
  109. package/dist/lib/css/property-descriptors/font-size.js +0 -10
  110. package/dist/lib/css/property-descriptors/font-style.js +0 -20
  111. package/dist/lib/css/property-descriptors/font-variant-ligatures.js +0 -34
  112. package/dist/lib/css/property-descriptors/font-variant.js +0 -13
  113. package/dist/lib/css/property-descriptors/font-weight.js +0 -25
  114. package/dist/lib/css/property-descriptors/image-rendering.js +0 -33
  115. package/dist/lib/css/property-descriptors/letter-spacing.js +0 -21
  116. package/dist/lib/css/property-descriptors/line-break.js +0 -23
  117. package/dist/lib/css/property-descriptors/line-height.js +0 -24
  118. package/dist/lib/css/property-descriptors/list-style-image.js +0 -17
  119. package/dist/lib/css/property-descriptors/list-style-position.js +0 -18
  120. package/dist/lib/css/property-descriptors/list-style-type.js +0 -122
  121. package/dist/lib/css/property-descriptors/margin.js +0 -13
  122. package/dist/lib/css/property-descriptors/mix-blend-mode.js +0 -31
  123. package/dist/lib/css/property-descriptors/object-fit.js +0 -28
  124. package/dist/lib/css/property-descriptors/object-position.js +0 -42
  125. package/dist/lib/css/property-descriptors/opacity.js +0 -16
  126. package/dist/lib/css/property-descriptors/overflow-wrap.js +0 -18
  127. package/dist/lib/css/property-descriptors/overflow.js +0 -27
  128. package/dist/lib/css/property-descriptors/padding.js +0 -14
  129. package/dist/lib/css/property-descriptors/paint-order.js +0 -33
  130. package/dist/lib/css/property-descriptors/position.js +0 -22
  131. package/dist/lib/css/property-descriptors/quotes.js +0 -41
  132. package/dist/lib/css/property-descriptors/rotate.js +0 -27
  133. package/dist/lib/css/property-descriptors/text-align.js +0 -21
  134. package/dist/lib/css/property-descriptors/text-decoration-color.js +0 -10
  135. package/dist/lib/css/property-descriptors/text-decoration-line.js +0 -28
  136. package/dist/lib/css/property-descriptors/text-decoration-style.js +0 -24
  137. package/dist/lib/css/property-descriptors/text-decoration-thickness.js +0 -26
  138. package/dist/lib/css/property-descriptors/text-overflow.js +0 -18
  139. package/dist/lib/css/property-descriptors/text-shadow.js +0 -46
  140. package/dist/lib/css/property-descriptors/text-transform.js +0 -20
  141. package/dist/lib/css/property-descriptors/text-underline-offset.js +0 -23
  142. package/dist/lib/css/property-descriptors/transform-origin.js +0 -24
  143. package/dist/lib/css/property-descriptors/transform.js +0 -57
  144. package/dist/lib/css/property-descriptors/visibility.js +0 -20
  145. package/dist/lib/css/property-descriptors/webkit-line-clamp.js +0 -26
  146. package/dist/lib/css/property-descriptors/webkit-text-stroke-color.js +0 -10
  147. package/dist/lib/css/property-descriptors/webkit-text-stroke-width.js +0 -16
  148. package/dist/lib/css/property-descriptors/white-space.js +0 -32
  149. package/dist/lib/css/property-descriptors/word-break.js +0 -26
  150. package/dist/lib/css/property-descriptors/writing-mode.js +0 -28
  151. package/dist/lib/css/property-descriptors/z-index.js +0 -19
  152. package/dist/lib/css/property-descriptors/zoom.js +0 -18
  153. package/dist/lib/css/syntax/parser.js +0 -141
  154. package/dist/lib/css/syntax/token-constants.js +0 -214
  155. package/dist/lib/css/syntax/token-singletons.js +0 -36
  156. package/dist/lib/css/syntax/token-types.js +0 -10
  157. package/dist/lib/css/syntax/tokenizer.js +0 -502
  158. package/dist/lib/css/type-descriptor.js +0 -2
  159. package/dist/lib/css/types/angle.js +0 -80
  160. package/dist/lib/css/types/color-math.js +0 -25
  161. package/dist/lib/css/types/color-spaces/a98.js +0 -78
  162. package/dist/lib/css/types/color-spaces/p3.js +0 -86
  163. package/dist/lib/css/types/color-spaces/pro-photo.js +0 -83
  164. package/dist/lib/css/types/color-spaces/rec2020.js +0 -85
  165. package/dist/lib/css/types/color-spaces/srgb.js +0 -79
  166. package/dist/lib/css/types/color-utilities.js +0 -342
  167. package/dist/lib/css/types/color.js +0 -400
  168. package/dist/lib/css/types/functions/-prefix-linear-gradient.js +0 -32
  169. package/dist/lib/css/types/functions/-prefix-radial-gradient.js +0 -83
  170. package/dist/lib/css/types/functions/-webkit-gradient.js +0 -59
  171. package/dist/lib/css/types/functions/counter.js +0 -367
  172. package/dist/lib/css/types/functions/gradient.js +0 -163
  173. package/dist/lib/css/types/functions/linear-gradient.js +0 -27
  174. package/dist/lib/css/types/functions/radial-gradient.js +0 -90
  175. package/dist/lib/css/types/functions/repeating-linear-gradient.js +0 -9
  176. package/dist/lib/css/types/image.js +0 -62
  177. package/dist/lib/css/types/index.js +0 -2
  178. package/dist/lib/css/types/length-percentage.js +0 -197
  179. package/dist/lib/css/types/length.js +0 -5
  180. package/dist/lib/css/types/safe-eval.js +0 -80
  181. package/dist/lib/css/types/time.js +0 -17
  182. package/dist/lib/dom/document-cloner.js +0 -618
  183. package/dist/lib/dom/dom-normalizer.js +0 -115
  184. package/dist/lib/dom/element-container.js +0 -71
  185. package/dist/lib/dom/elements/li-element-container.js +0 -11
  186. package/dist/lib/dom/elements/ol-element-container.js +0 -12
  187. package/dist/lib/dom/elements/select-element-container.js +0 -12
  188. package/dist/lib/dom/elements/textarea-element-container.js +0 -11
  189. package/dist/lib/dom/node-parser.js +0 -125
  190. package/dist/lib/dom/node-type-guards.js +0 -81
  191. package/dist/lib/dom/replaced-elements/canvas-element-container.js +0 -13
  192. package/dist/lib/dom/replaced-elements/iframe-element-container.js +0 -38
  193. package/dist/lib/dom/replaced-elements/image-element-container.js +0 -14
  194. package/dist/lib/dom/replaced-elements/index.js +0 -2
  195. package/dist/lib/dom/replaced-elements/input-element-container.js +0 -89
  196. package/dist/lib/dom/replaced-elements/svg-element-container.js +0 -57
  197. package/dist/lib/dom/slot-cloner.js +0 -176
  198. package/dist/lib/dom/text-container.js +0 -35
  199. package/dist/lib/index.js +0 -49
  200. package/dist/lib/options.js +0 -2
  201. package/dist/lib/render/background.js +0 -188
  202. package/dist/lib/render/bezier-curve.js +0 -34
  203. package/dist/lib/render/border.js +0 -104
  204. package/dist/lib/render/bound-curves.js +0 -188
  205. package/dist/lib/render/box-sizing.js +0 -20
  206. package/dist/lib/render/canvas/background-renderer.js +0 -338
  207. package/dist/lib/render/canvas/border-image-renderer.js +0 -153
  208. package/dist/lib/render/canvas/border-renderer.js +0 -184
  209. package/dist/lib/render/canvas/box-shadow-geometry.js +0 -52
  210. package/dist/lib/render/canvas/box-shadow-painter.js +0 -194
  211. package/dist/lib/render/canvas/box-shadow-transform.js +0 -42
  212. package/dist/lib/render/canvas/canvas-path.js +0 -25
  213. package/dist/lib/render/canvas/canvas-renderer.js +0 -610
  214. package/dist/lib/render/canvas/content-renderer.js +0 -270
  215. package/dist/lib/render/canvas/effects-renderer.js +0 -171
  216. package/dist/lib/render/canvas/filter-surface.js +0 -270
  217. package/dist/lib/render/canvas/font-utils.js +0 -46
  218. package/dist/lib/render/canvas/foreignobject-renderer.js +0 -38
  219. package/dist/lib/render/canvas/surface-bounds.js +0 -64
  220. package/dist/lib/render/canvas/text/text-decoration-renderer.js +0 -99
  221. package/dist/lib/render/canvas/text-renderer.js +0 -486
  222. package/dist/lib/render/effects.js +0 -231
  223. package/dist/lib/render/font-metrics.js +0 -53
  224. package/dist/lib/render/object-fit.js +0 -91
  225. package/dist/lib/render/path.js +0 -26
  226. package/dist/lib/render/renderer-interface.js +0 -2
  227. package/dist/lib/render/stacking-context.js +0 -341
  228. package/dist/lib/render/vector.js +0 -16
@@ -35,6 +35,13 @@ export declare class TextRenderer {
35
35
  private readonly ctx;
36
36
  private readonly options;
37
37
  private readonly decorationRenderer;
38
+ /**
39
+ * Baseline ascent per font string. Consecutive text nodes overwhelmingly
40
+ * share a font, and each measureBaseline call issues a canvas measureText,
41
+ * so repeated fonts are memoised (bounded; cleared if the working set
42
+ * exceeds the cap).
43
+ */
44
+ private readonly baselineCache;
38
45
  /**
39
46
  * Per-render glyph width cache. Keyed by glyph + font string,
40
47
  * avoids redundant `measureText` calls when letter-spacing is non-zero.
@@ -90,6 +97,13 @@ export declare class TextRenderer {
90
97
  * Public method used by list rendering
91
98
  */
92
99
  createFontStyle(styles: CSSParsedDeclaration): string[];
100
+ /**
101
+ * -webkit-text-fill-color overrides the fill colour while leaving
102
+ * decorations and strokes on `color` (e.g. the classic transparent-fill
103
+ * gradient text). Falls back to `color` when the computed value could not
104
+ * be resolved (currentcolor).
105
+ */
106
+ private resolveFillColor;
93
107
  /**
94
108
  * Render text with -webkit-line-clamp truncation.
95
109
  * Groups text bounds by their Y position into visual lines, then renders
@@ -101,5 +115,13 @@ export declare class TextRenderer {
101
115
  * Returns true if ellipsis was applied (caller should skip normal rendering).
102
116
  */
103
117
  private renderEllipsisText;
118
+ private measureBaselineCached;
104
119
  renderTextNode(text: TextContainer, styles: CSSParsedDeclaration, containerBounds?: Bounds): Promise<void>;
120
+ /**
121
+ * Draw text-emphasis marks over (or under) each grapheme cluster.
122
+ *
123
+ * Vertical writing modes are skipped in the current scope: marks would
124
+ * need to sit beside vertical glyph runs rather than above them.
125
+ */
126
+ private renderTextEmphasis;
105
127
  }
@@ -20,11 +20,14 @@ export declare class ElementPaint {
20
20
  readonly effects: IElementEffect[];
21
21
  readonly curves: BoundCurves;
22
22
  listValue?: string;
23
+ /** Memoised getEffects results for the plain (surfaceRoot-less) render path. */
24
+ private plainEffectsCache;
23
25
  constructor(container: ElementContainer, parent: ElementPaint | null);
24
26
  getEffects(target: EffectTarget, surfaceRoot?: ElementPaint): IElementEffect[];
27
+ private computeEffects;
25
28
  }
26
29
  /** @internal – exported for testing only. */
27
- export declare const hasOverflowClip: (styles: ElementContainer["styles"]) => boolean;
30
+ export declare const hasOverflowClip: (styles: ElementContainer['styles']) => boolean;
28
31
  /**
29
32
  * Resolve a `closest-side` or `farthest-side` shape-radius keyword to pixels
30
33
  * for a single axis. Used by both `circle()` (per-axis) and `ellipse()`.
package/package.json CHANGED
@@ -19,7 +19,7 @@
19
19
  "default": "./dist/html2canvas-pro.esm.js"
20
20
  }
21
21
  },
22
- "version": "2.4.5",
22
+ "version": "2.5.0",
23
23
  "author": {
24
24
  "name": "yorickshan",
25
25
  "email": "yorickshan@gmail.com",
@@ -39,66 +39,65 @@
39
39
  "url": "https://github.com/yorickshan/html2canvas-pro"
40
40
  },
41
41
  "devDependencies": {
42
- "@commitlint/cli": "^20.3.0",
43
- "@commitlint/config-conventional": "^20.2.0",
42
+ "@commitlint/cli": "^21.2.3",
43
+ "@commitlint/config-conventional": "^21.2.3",
44
44
  "@types/chai": "^5.2.3",
45
45
  "@types/express": "^5.0.6",
46
- "@types/karma": "^6.3.0",
47
- "@types/mocha": "^10.0.7",
48
- "@types/node": "^25.0.3",
49
- "@types/platform": "^1.3.4",
46
+ "@types/karma": "^6.3.9",
47
+ "@types/mocha": "^10.0.10",
48
+ "@types/node": "^26.6.3",
49
+ "@types/platform": "^1.3.6",
50
50
  "@types/pngjs": "^6.0.5",
51
51
  "@types/serve-index": "^1.9.4",
52
- "@typescript-eslint/eslint-plugin": "^8.50.0",
53
- "@typescript-eslint/parser": "^8.50.0",
54
- "@vitest/coverage-v8": "^3.2.6",
55
- "appium-ios-simulator": "^8.0.9",
52
+ "@typescript-eslint/eslint-plugin": "^8.70.1",
53
+ "@typescript-eslint/parser": "^8.70.1",
54
+ "@typescript/native": "npm:typescript@^7.0.2",
55
+ "@vitest/coverage-v8": "^5.0.2",
56
+ "appium-ios-simulator": "^8.2.8",
56
57
  "base64-arraybuffer": "1.0.2",
57
- "body-parser": "^2.2.1",
58
+ "body-parser": "^2.3.0",
58
59
  "chai": "6.2.2",
59
60
  "change-case": "^5.4.4",
60
- "conventional-changelog": "^7.2.1",
61
- "conventional-changelog-conventionalcommits": "^9.3.1",
62
- "cors": "^2.8.5",
61
+ "conventional-changelog": "^8.1.3",
62
+ "conventional-changelog-conventionalcommits": "^10.4.0",
63
+ "cors": "^2.8.6",
63
64
  "cz-conventional-changelog": "^3.3.0",
64
- "eslint": "^9.13.0",
65
+ "eslint": "^10.11.0",
65
66
  "eslint-config-prettier": "^10.1.8",
66
- "eslint-plugin-prettier": "^5.5.4",
67
+ "eslint-plugin-prettier": "^5.5.6",
67
68
  "express": "^5.2.1",
68
69
  "filenamify-url": "4.0.0",
69
- "glob": "^13.0.0",
70
- "html2canvas-pro-baseline": "npm:html2canvas-pro@2.4.3",
70
+ "glob": "^13.0.6",
71
71
  "husky": "^9.1.7",
72
- "jsdom": "^29.1.1",
73
- "karma": "^6.3.2",
74
- "karma-chrome-launcher": "^3.1.0",
72
+ "jsdom": "^30.1.1",
73
+ "karma": "^6.4.4",
74
+ "karma-chrome-launcher": "^3.2.0",
75
75
  "karma-edge-launcher": "^0.4.2",
76
- "karma-firefox-launcher": "^2.1.0",
76
+ "karma-firefox-launcher": "^2.1.3",
77
77
  "karma-ie-launcher": "^1.0.0",
78
78
  "karma-junit-reporter": "^2.0.1",
79
79
  "karma-mocha": "^2.0.1",
80
80
  "karma-safarinative-launcher": "^1.1.0",
81
- "lint-staged": "^16.2.7",
82
- "mocha": "^11.7.5",
83
- "node-simctl": "^8.1.2",
81
+ "lint-staged": "^17.6.0",
82
+ "mocha": "^12.0.2",
83
+ "node-simctl": "^8.2.9",
84
84
  "pixelmatch": "^7.2.0",
85
85
  "platform": "^1.3.6",
86
- "playwright": "1.60.0",
86
+ "playwright": "1.63.0",
87
87
  "pngjs": "^7.0.0",
88
- "prettier": "^3.3.3",
89
- "puppeteer": "^24.34.0",
90
- "replace-in-file": "^8.4.0",
91
- "rimraf": "^6.0.1",
92
- "rolldown": "^1.2.0",
93
- "serve-index": "^1.9.1",
88
+ "prettier": "^3.9.9",
89
+ "puppeteer": "^25.12.0",
90
+ "rimraf": "^6.1.3",
91
+ "rolldown": "^1.2.11",
92
+ "serve-index": "^1.9.2",
94
93
  "slash": "5.1.0",
95
- "ts-node": "^10.9.2",
96
- "tsx": "^4.22.3",
97
- "typedoc": "^0.28.19",
98
- "typescript": "^5.5.4",
94
+ "tsx": "^4.23.15",
95
+ "typedoc": "^0.28.20",
96
+ "typescript": "npm:@typescript/typescript6@^6.0.2",
97
+ "vite": "^8.3.1",
99
98
  "vitepress": "^1.6.4",
100
- "vitest": "^3.2.6",
101
- "yargs": "^18.0.0"
99
+ "vitest": "^5.0.2",
100
+ "yargs": "^18.2.0"
102
101
  },
103
102
  "dependencies": {
104
103
  "css-line-break": "^2.1.0",
@@ -112,7 +111,7 @@
112
111
  },
113
112
  "scripts": {
114
113
  "prebuild": "rimraf dist/ && rimraf build/ && mkdir -p dist && mkdir -p build",
115
- "build": "tsc --module commonjs -p tsconfig.build.json && rolldown -c rolldown.config.ts && pnpm build:create-reftest-list && rolldown -c tests/rolldown.testrunner.config.ts && node scripts/copy-filter-baseline.mjs",
114
+ "build": "tsc -p tsconfig.build.json && rolldown -c rolldown.config.ts && pnpm build:create-reftest-list && rolldown -c tests/rolldown.testrunner.config.ts && node scripts/bundle-filter-surface.mjs",
116
115
  "build:testrunner": "rolldown -c tests/rolldown.testrunner.config.ts",
117
116
  "build:reftest-result-list": "tsx scripts/create-reftest-result-list.ts",
118
117
  "build:create-reftest-list": "tsx scripts/create-reftest-list.ts tests/reftests/ignore.txt build/reftests.js",
@@ -1,49 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.Html2CanvasConfig = void 0;
4
- /**
5
- * Html2Canvas Configuration
6
- *
7
- * Manages configuration state for html2canvas rendering.
8
- * Eliminates the need for global static variables.
9
- */
10
- class Html2CanvasConfig {
11
- constructor(options = {}) {
12
- const resolvedWindow = options.window || (typeof window !== 'undefined' ? window : undefined);
13
- if (!resolvedWindow) {
14
- throw new Error('Window object is required but not available');
15
- }
16
- this.window = resolvedWindow;
17
- this.cspNonce = options.cspNonce;
18
- this.cache = options.cache;
19
- }
20
- /**
21
- * Create configuration from an element
22
- * Extracts window from element's owner document
23
- */
24
- static fromElement(element, options = {}) {
25
- const ownerDocument = element.ownerDocument;
26
- if (!ownerDocument) {
27
- throw new Error('Element is not attached to a document');
28
- }
29
- const defaultView = ownerDocument.defaultView;
30
- if (!defaultView) {
31
- throw new Error('Document is not attached to a window');
32
- }
33
- return new Html2CanvasConfig({
34
- window: defaultView,
35
- ...options
36
- });
37
- }
38
- /**
39
- * Clone configuration with override options
40
- */
41
- clone(options = {}) {
42
- return new Html2CanvasConfig({
43
- window: options.window || this.window,
44
- cspNonce: options.cspNonce ?? this.cspNonce,
45
- cache: options.cache ?? this.cache
46
- });
47
- }
48
- }
49
- exports.Html2CanvasConfig = Html2CanvasConfig;
@@ -1,20 +0,0 @@
1
- "use strict";
2
- /**
3
- * AbortSignal helper utilities.
4
- */
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.throwIfAborted = void 0;
7
- /**
8
- * Throw a DOMException if the given AbortSignal is already aborted.
9
- * Used at checkpoints throughout the rendering pipeline to support
10
- * cancellable renders.
11
- *
12
- * @param signal - The AbortSignal to check. If undefined or not aborted, this is a no-op.
13
- * @throws {DOMException} With name 'AbortError' if the signal has been aborted.
14
- */
15
- const throwIfAborted = (signal) => {
16
- if (signal?.aborted) {
17
- throw new DOMException('The operation was aborted.', 'AbortError');
18
- }
19
- };
20
- exports.throwIfAborted = throwIfAborted;
@@ -1,41 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.parseBackgroundColor = void 0;
4
- const color_1 = require("../css/types/color");
5
- const color_utilities_1 = require("../css/types/color-utilities");
6
- /**
7
- * Resolve the background colour for the rendered canvas, following CSS
8
- * background propagation rules:
9
- *
10
- * 1. If the target element is `<html>`, inherit the first opaque ancestor
11
- * (doc → body → fallback).
12
- * 2. Otherwise use the user-supplied backgroundColor, or opaque white.
13
- *
14
- * @param context - Current rendering context.
15
- * @param element - The root element being rendered.
16
- * @param backgroundColorOverride - User-supplied override (string | null).
17
- * @returns A resolved colour value suitable for filling the canvas.
18
- */
19
- const parseBackgroundColor = (context, element, backgroundColorOverride) => {
20
- const ownerDocument = element.ownerDocument;
21
- // http://www.w3.org/TR/css3-background/#special-backgrounds
22
- const documentBackgroundColor = ownerDocument.documentElement
23
- ? (0, color_1.parseColor)(context, getComputedStyle(ownerDocument.documentElement).backgroundColor)
24
- : color_1.COLORS.TRANSPARENT;
25
- const bodyBackgroundColor = ownerDocument.body
26
- ? (0, color_1.parseColor)(context, getComputedStyle(ownerDocument.body).backgroundColor)
27
- : color_1.COLORS.TRANSPARENT;
28
- const defaultBackgroundColor = typeof backgroundColorOverride === 'string'
29
- ? (0, color_1.parseColor)(context, backgroundColorOverride)
30
- : backgroundColorOverride === null
31
- ? color_1.COLORS.TRANSPARENT
32
- : 0xffffffff;
33
- return element === ownerDocument.documentElement
34
- ? (0, color_utilities_1.isTransparent)(documentBackgroundColor)
35
- ? (0, color_utilities_1.isTransparent)(bodyBackgroundColor)
36
- ? defaultBackgroundColor
37
- : bodyBackgroundColor
38
- : documentBackgroundColor
39
- : defaultBackgroundColor;
40
- };
41
- exports.parseBackgroundColor = parseBackgroundColor;
@@ -1,5 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.contains = void 0;
4
- const contains = (bit, value) => (bit & value) !== 0;
5
- exports.contains = contains;
@@ -1,283 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.Cache = void 0;
4
- const features_1 = require("./features");
5
- class Cache {
6
- constructor(context, _options) {
7
- this.context = context;
8
- this._options = _options;
9
- this._cache = new Map();
10
- this._pendingOperations = new Map();
11
- /** When true, addImage() collects URLs without starting loads. */
12
- this._deferMode = false;
13
- /** URLs collected during defer mode, pending batch preload. */
14
- this._collectedUrls = new Set();
15
- // Default cache size: 100 items
16
- this.maxSize = _options.maxCacheSize ?? 100;
17
- if (this.maxSize < 1) {
18
- throw new Error('Cache maxSize must be at least 1');
19
- }
20
- if (this.maxSize > 10000) {
21
- this.context.logger.warn(`Cache maxSize ${this.maxSize} is very large and may cause memory issues. ` +
22
- `Consider using a smaller value (recommended: 100-1000).`);
23
- }
24
- }
25
- /**
26
- * Enter defer mode: subsequent addImage() calls only collect URLs.
27
- * Call preloadAll() to exit defer mode and batch-load all URLs.
28
- */
29
- startDefer() {
30
- this._deferMode = true;
31
- }
32
- /**
33
- * Exit defer mode and load all collected URLs in parallel, respecting
34
- * an optional concurrency cap to avoid overwhelming the browser's network
35
- * stack (default: 10 concurrent loads).
36
- * After this call returns, all images are either loaded (cache hit) or
37
- * failed (logged). Subsequent cache.match() calls return immediately.
38
- *
39
- * @param concurrency - Max concurrent image loads (1–100, default 10).
40
- */
41
- async preloadAll(concurrency = 10) {
42
- this._deferMode = false;
43
- const urls = Array.from(this._collectedUrls);
44
- this._collectedUrls.clear();
45
- if (urls.length === 0) {
46
- return;
47
- }
48
- const limit = Math.max(1, Math.min(concurrency, 100));
49
- this.context.logger.debug(`Preloading ${urls.length} image(s) with concurrency ${limit}`);
50
- // Load in batches to respect the concurrency cap while maximising
51
- // parallelism within each batch.
52
- for (let i = 0; i < urls.length; i += limit) {
53
- const batch = urls.slice(i, i + limit);
54
- const operations = batch.map((url) => this._addImageWithPending(url));
55
- await Promise.allSettled(operations);
56
- }
57
- }
58
- addImage(src) {
59
- // ── Defer mode: collect only ──────────────────────────────
60
- if (this._deferMode) {
61
- if (!this.has(src) && (isBlobImage(src) || isRenderable(src))) {
62
- this._collectedUrls.add(src);
63
- }
64
- return Promise.resolve();
65
- }
66
- // ── Normal mode: immediate load ───────────────────────────
67
- // Wait for any pending operations on this key
68
- const pending = this._pendingOperations.get(src);
69
- if (pending) {
70
- return pending;
71
- }
72
- if (this.has(src)) {
73
- // Move to end for LRU ordering
74
- const entry = this._cache.get(src);
75
- this._cache.delete(src);
76
- this._cache.set(src, entry);
77
- return Promise.resolve();
78
- }
79
- if (isBlobImage(src) || isRenderable(src)) {
80
- return this._addImageWithPending(src);
81
- }
82
- return Promise.resolve();
83
- }
84
- /**
85
- * Shared helper: enqueues loading for a single URL with pending-operation
86
- * deduplication and error swallowing. Used by both addImage() (normal mode)
87
- * and preloadAll() (batch mode).
88
- */
89
- _addImageWithPending(src) {
90
- const pending = this._pendingOperations.get(src);
91
- if (pending) {
92
- return pending;
93
- }
94
- const operation = this._addImageInternal(src);
95
- this._pendingOperations.set(src, operation);
96
- operation.finally(() => {
97
- this._pendingOperations.delete(src);
98
- });
99
- return operation;
100
- }
101
- async _addImageInternal(src) {
102
- const timeoutMs = this._options.imageTimeout ?? 15000;
103
- const imageWithTimeout = this.withTimeout(this.loadImage(src), timeoutMs, `Timed out (${timeoutMs}ms) loading image`);
104
- // Handle errors to prevent unhandled rejections
105
- imageWithTimeout.catch((error) => {
106
- this.context.logger.error(`Failed to load image ${src}: ${error instanceof Error ? error.message : 'Unknown error'}`);
107
- });
108
- // Store the promise with timeout in cache
109
- this.set(src, imageWithTimeout);
110
- }
111
- withTimeout(promise, timeoutMs, message) {
112
- if (timeoutMs <= 0) {
113
- return promise;
114
- }
115
- let timeoutId;
116
- const timeout = new Promise((_, reject) => {
117
- timeoutId = setTimeout(() => reject(new Error(message)), timeoutMs);
118
- });
119
- return Promise.race([promise, timeout]).finally(() => {
120
- if (timeoutId !== undefined) {
121
- clearTimeout(timeoutId);
122
- }
123
- });
124
- }
125
- match(src) {
126
- const entry = this._cache.get(src);
127
- if (entry) {
128
- // Move to end for LRU ordering (O(1))
129
- this._cache.delete(src);
130
- this._cache.set(src, entry);
131
- return entry.value;
132
- }
133
- return undefined;
134
- }
135
- /**
136
- * Set a value in cache with LRU eviction (O(1) via Map insertion order).
137
- * Map preserves insertion order; delete+set on access moves items to the end.
138
- * The first key in Map.keys() is always the least recently used.
139
- */
140
- set(key, value) {
141
- if (this._cache.has(key)) {
142
- // Update existing entry: move to end of Map
143
- this._cache.delete(key);
144
- }
145
- else if (this._cache.size >= this.maxSize) {
146
- // Evict LRU (first key = least recently used) — O(1)
147
- const lruKey = this._cache.keys().next().value;
148
- if (lruKey !== undefined) {
149
- this._cache.delete(lruKey);
150
- this.context.logger.debug(`Cache: Evicted LRU entry: ${lruKey}`);
151
- }
152
- }
153
- this._cache.set(key, { value });
154
- }
155
- /**
156
- * Get cache size
157
- */
158
- size() {
159
- return this._cache.size;
160
- }
161
- /**
162
- * Get max cache size
163
- */
164
- getMaxSize() {
165
- return this.maxSize;
166
- }
167
- /**
168
- * Clear all cache entries
169
- */
170
- clear() {
171
- this._cache.clear();
172
- }
173
- async loadImage(key) {
174
- const originChecker = this.context.originChecker;
175
- const defaultIsSameOrigin = (src) => originChecker.isSameOrigin(src);
176
- const isSameOrigin = typeof this._options.customIsSameOrigin === 'function'
177
- ? await this._options.customIsSameOrigin(key, defaultIsSameOrigin)
178
- : defaultIsSameOrigin(key);
179
- // With allowTaint disabled (the default), a cross-origin image is safe to
180
- // draw only when the server sends CORS headers. Instead of skipping such
181
- // images outright, still ATTEMPT a CORS load: it succeeds for CORS-enabled
182
- // hosts (CDNs, avatar services, picsum, ...) and fails cleanly for hosts
183
- // without CORS headers, where the image is skipped exactly as before
184
- // (issue #229). An explicit proxy takes precedence so existing setups
185
- // that rely on proxying keep working.
186
- const canAttemptCors = !isSameOrigin &&
187
- this._options.allowTaint === false &&
188
- !isInlineImage(key) &&
189
- !isBlobImage(key) &&
190
- typeof this._options.proxy !== 'string';
191
- const useCORS = !isInlineImage(key) &&
192
- (this._options.useCORS === true || canAttemptCors) &&
193
- features_1.FEATURES.SUPPORT_CORS_IMAGES &&
194
- !isSameOrigin;
195
- const useProxy = !isInlineImage(key) &&
196
- !isSameOrigin &&
197
- !isBlobImage(key) &&
198
- typeof this._options.proxy === 'string' &&
199
- features_1.FEATURES.SUPPORT_CORS_XHR &&
200
- !useCORS;
201
- if (!isSameOrigin &&
202
- this._options.allowTaint === false &&
203
- !isInlineImage(key) &&
204
- !isBlobImage(key) &&
205
- !useProxy &&
206
- !useCORS) {
207
- return;
208
- }
209
- let src = key;
210
- if (useProxy) {
211
- src = await this.proxy(src);
212
- }
213
- this.context.logger.debug(`Added image ${key.substring(0, 256)}`);
214
- return await new Promise((resolve, reject) => {
215
- const img = new Image();
216
- img.onload = () => resolve(img);
217
- img.onerror = reject;
218
- //ios safari 10.3 taints canvas with data urls unless crossOrigin is set to anonymous
219
- if (isInlineBase64Image(src) || useCORS) {
220
- img.crossOrigin = 'anonymous';
221
- }
222
- img.src = src;
223
- if (img.complete === true) {
224
- // Inline XML images may fail to parse, throwing an Error later on
225
- setTimeout(() => resolve(img), 500);
226
- }
227
- });
228
- }
229
- has(key) {
230
- return this._cache.has(key);
231
- }
232
- keys() {
233
- return Promise.resolve(Array.from(this._cache.keys()));
234
- }
235
- proxy(src) {
236
- const proxy = this._options.proxy;
237
- if (!proxy) {
238
- throw new Error('No proxy defined');
239
- }
240
- const key = src.substring(0, 256);
241
- return new Promise((resolve, reject) => {
242
- const responseType = features_1.FEATURES.SUPPORT_RESPONSE_TYPE ? 'blob' : 'text';
243
- const xhr = new XMLHttpRequest();
244
- xhr.onload = () => {
245
- if (xhr.status === 200) {
246
- if (responseType === 'text') {
247
- resolve(xhr.response);
248
- }
249
- else {
250
- const reader = new FileReader();
251
- reader.addEventListener('load', () => resolve(reader.result), false);
252
- reader.addEventListener('error', (e) => reject(e), false);
253
- reader.readAsDataURL(xhr.response);
254
- }
255
- }
256
- else {
257
- reject(`Failed to proxy resource ${key} with status code ${xhr.status}`);
258
- }
259
- };
260
- xhr.onerror = reject;
261
- const queryString = proxy.indexOf('?') > -1 ? '&' : '?';
262
- xhr.open('GET', `${proxy}${queryString}url=${encodeURIComponent(src)}&responseType=${responseType}`);
263
- if (responseType !== 'text' && xhr instanceof XMLHttpRequest) {
264
- xhr.responseType = responseType;
265
- }
266
- if (this._options.imageTimeout) {
267
- const timeout = this._options.imageTimeout;
268
- xhr.timeout = timeout;
269
- xhr.ontimeout = () => reject(`Timed out (${timeout}ms) proxying ${key}`);
270
- }
271
- xhr.send();
272
- });
273
- }
274
- }
275
- exports.Cache = Cache;
276
- const INLINE_SVG = /^data:image\/svg\+xml/i;
277
- const INLINE_BASE64 = /^data:image\/.*;base64,/i;
278
- const INLINE_IMG = /^data:image\/.*/i;
279
- const isRenderable = (src) => features_1.FEATURES.SUPPORT_SVG_DRAWING || !isSVG(src);
280
- const isInlineImage = (src) => INLINE_IMG.test(src);
281
- const isInlineBase64Image = (src) => INLINE_BASE64.test(src);
282
- const isBlobImage = (src) => src.substring(0, 4) === 'blob';
283
- const isSVG = (src) => src.slice(-3).toLowerCase() === 'svg' || INLINE_SVG.test(src);
@@ -1,88 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.assembleRenderOptions = exports.assembleCloneOptions = exports.assembleWindowOptions = exports.assembleContextOptions = exports.assembleResourceOptions = exports.coerceNumberOptions = void 0;
4
- const constants_1 = require("./constants");
5
- /**
6
- * Coerce known numeric options from string (or other) values to actual numbers.
7
- * Mutates the opts object in place — this is intentionally a normalisation
8
- * (not pure) step that runs once at the beginning of renderElement.
9
- */
10
- const coerceNumberOptions = (opts) => {
11
- const numKeys = [
12
- 'scale',
13
- 'width',
14
- 'height',
15
- 'imageTimeout',
16
- 'x',
17
- 'y',
18
- 'windowWidth',
19
- 'windowHeight',
20
- 'scrollX',
21
- 'scrollY'
22
- ];
23
- numKeys.forEach((key) => {
24
- const v = opts[key];
25
- if (v !== undefined && v !== null && typeof v !== 'number') {
26
- const n = Number(v);
27
- if (!Number.isNaN(n)) {
28
- opts[key] = n;
29
- }
30
- }
31
- });
32
- };
33
- exports.coerceNumberOptions = coerceNumberOptions;
34
- /** Assemble resource loading options from user-provided Options. */
35
- const assembleResourceOptions = (opts) => ({
36
- allowTaint: opts.allowTaint ?? false,
37
- imageTimeout: opts.imageTimeout ?? constants_1.DEFAULT_IMAGE_TIMEOUT_MS,
38
- proxy: opts.proxy,
39
- useCORS: opts.useCORS ?? false,
40
- customIsSameOrigin: opts.customIsSameOrigin,
41
- maxCacheSize: opts.maxCacheSize
42
- });
43
- exports.assembleResourceOptions = assembleResourceOptions;
44
- /** Assemble context (logging + cache) options, extending resource options. */
45
- const assembleContextOptions = (opts, config, resourceOptions) => ({
46
- logging: opts.logging ?? true,
47
- cache: opts.cache ?? config.cache,
48
- ...resourceOptions
49
- });
50
- exports.assembleContextOptions = assembleContextOptions;
51
- const DEFAULT_WINDOW_WIDTH = 800;
52
- const DEFAULT_WINDOW_HEIGHT = 600;
53
- const DEFAULT_SCROLL = 0;
54
- const assembleWindowOptions = (opts, defaultView) => {
55
- const win = defaultView;
56
- return {
57
- windowWidth: opts.windowWidth ?? win.innerWidth ?? DEFAULT_WINDOW_WIDTH,
58
- windowHeight: opts.windowHeight ?? win.innerHeight ?? DEFAULT_WINDOW_HEIGHT,
59
- scrollX: opts.scrollX ?? win.pageXOffset ?? DEFAULT_SCROLL,
60
- scrollY: opts.scrollY ?? win.pageYOffset ?? DEFAULT_SCROLL
61
- };
62
- };
63
- exports.assembleWindowOptions = assembleWindowOptions;
64
- /** Assemble DOM cloning options. */
65
- const assembleCloneOptions = (opts, config, foreignObjectRendering) => ({
66
- allowTaint: opts.allowTaint ?? false,
67
- onclone: opts.onclone,
68
- ignoreElements: opts.ignoreElements,
69
- iframeContainer: opts.iframeContainer,
70
- inlineImages: foreignObjectRendering,
71
- copyStyles: foreignObjectRendering,
72
- cspNonce: opts.cspNonce ?? config.cspNonce
73
- });
74
- exports.assembleCloneOptions = assembleCloneOptions;
75
- /** Assemble canvas rendering options. */
76
- const assembleRenderOptions = (opts, backgroundColor, left, top, width, height, devicePixelRatio) => ({
77
- canvas: opts.canvas,
78
- backgroundColor,
79
- signal: opts.signal,
80
- scale: opts.scale ?? devicePixelRatio ?? 1,
81
- x: (opts.x ?? 0) + left,
82
- y: (opts.y ?? 0) + top,
83
- width: opts.width ?? Math.ceil(width),
84
- height: opts.height ?? Math.ceil(height),
85
- imageSmoothing: opts.imageSmoothing,
86
- imageSmoothingQuality: opts.imageSmoothingQuality
87
- });
88
- exports.assembleRenderOptions = assembleRenderOptions;