html2canvas-pro 2.1.0 → 2.1.1

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 (186) hide show
  1. package/dist/html2canvas-pro.esm.js +21 -7
  2. package/dist/html2canvas-pro.esm.js.map +1 -1
  3. package/dist/html2canvas-pro.js +21 -7
  4. package/dist/html2canvas-pro.js.map +1 -1
  5. package/dist/html2canvas-pro.min.js +3 -3
  6. package/dist/lib/core/cache-storage.js +2 -2
  7. package/dist/lib/core/features.js +2 -2
  8. package/dist/lib/render/canvas/background-renderer.js +6 -0
  9. package/dist/lib/render/canvas/canvas-renderer.js +5 -1
  10. package/dist/lib/render/canvas/foreignobject-renderer.js +5 -1
  11. package/package.json +3 -11
  12. package/dist/lib/invariant.js +0 -9
  13. package/dist/types/invariant.d.ts +0 -1
  14. package/src/__tests__/index.ts +0 -99
  15. package/src/config.ts +0 -107
  16. package/src/core/__mocks__/cache-storage.ts +0 -1
  17. package/src/core/__mocks__/context.ts +0 -19
  18. package/src/core/__mocks__/features.ts +0 -8
  19. package/src/core/__mocks__/logger.ts +0 -17
  20. package/src/core/__tests__/cache-storage.test.ts +0 -205
  21. package/src/core/__tests__/cache-storage.ts +0 -278
  22. package/src/core/__tests__/logger.ts +0 -29
  23. package/src/core/__tests__/validator.ts +0 -359
  24. package/src/core/bitwise.ts +0 -1
  25. package/src/core/cache-storage.ts +0 -315
  26. package/src/core/context.ts +0 -31
  27. package/src/core/debugger.ts +0 -32
  28. package/src/core/features.ts +0 -222
  29. package/src/core/logger.ts +0 -64
  30. package/src/core/origin-checker.ts +0 -57
  31. package/src/core/performance-monitor.ts +0 -241
  32. package/src/core/render-element.ts +0 -272
  33. package/src/core/util.ts +0 -1
  34. package/src/core/validator.ts +0 -593
  35. package/src/css/index.ts +0 -427
  36. package/src/css/layout/__mocks__/bounds.ts +0 -6
  37. package/src/css/layout/bounds.ts +0 -79
  38. package/src/css/layout/text.ts +0 -161
  39. package/src/css/property-descriptor.ts +0 -49
  40. package/src/css/property-descriptors/__tests__/background-tests.ts +0 -65
  41. package/src/css/property-descriptors/__tests__/clip-path.test.ts +0 -280
  42. package/src/css/property-descriptors/__tests__/font-family.ts +0 -25
  43. package/src/css/property-descriptors/__tests__/image-rendering-integration.test.ts +0 -153
  44. package/src/css/property-descriptors/__tests__/image-rendering-performance.test.ts +0 -175
  45. package/src/css/property-descriptors/__tests__/image-rendering.test.ts +0 -72
  46. package/src/css/property-descriptors/__tests__/paint-order.ts +0 -87
  47. package/src/css/property-descriptors/__tests__/text-shadow.ts +0 -94
  48. package/src/css/property-descriptors/__tests__/transform-tests.ts +0 -18
  49. package/src/css/property-descriptors/background-clip.ts +0 -30
  50. package/src/css/property-descriptors/background-color.ts +0 -9
  51. package/src/css/property-descriptors/background-image.ts +0 -27
  52. package/src/css/property-descriptors/background-origin.ts +0 -31
  53. package/src/css/property-descriptors/background-position.ts +0 -38
  54. package/src/css/property-descriptors/background-repeat.ts +0 -44
  55. package/src/css/property-descriptors/background-size.ts +0 -27
  56. package/src/css/property-descriptors/border-color.ts +0 -13
  57. package/src/css/property-descriptors/border-radius.ts +0 -19
  58. package/src/css/property-descriptors/border-style.ts +0 -34
  59. package/src/css/property-descriptors/border-width.ts +0 -20
  60. package/src/css/property-descriptors/box-shadow.ts +0 -60
  61. package/src/css/property-descriptors/clip-path.ts +0 -271
  62. package/src/css/property-descriptors/color.ts +0 -9
  63. package/src/css/property-descriptors/content.ts +0 -26
  64. package/src/css/property-descriptors/counter-increment.ts +0 -43
  65. package/src/css/property-descriptors/counter-reset.ts +0 -36
  66. package/src/css/property-descriptors/direction.ts +0 -23
  67. package/src/css/property-descriptors/display.ts +0 -117
  68. package/src/css/property-descriptors/duration.ts +0 -14
  69. package/src/css/property-descriptors/float.ts +0 -29
  70. package/src/css/property-descriptors/font-family.ts +0 -38
  71. package/src/css/property-descriptors/font-size.ts +0 -9
  72. package/src/css/property-descriptors/font-style.ts +0 -25
  73. package/src/css/property-descriptors/font-variant.ts +0 -12
  74. package/src/css/property-descriptors/font-weight.ts +0 -26
  75. package/src/css/property-descriptors/image-rendering.ts +0 -33
  76. package/src/css/property-descriptors/letter-spacing.ts +0 -25
  77. package/src/css/property-descriptors/line-break.ts +0 -22
  78. package/src/css/property-descriptors/line-height.ts +0 -22
  79. package/src/css/property-descriptors/list-style-image.ts +0 -19
  80. package/src/css/property-descriptors/list-style-position.ts +0 -22
  81. package/src/css/property-descriptors/list-style-type.ts +0 -179
  82. package/src/css/property-descriptors/margin.ts +0 -13
  83. package/src/css/property-descriptors/mix-blend-mode.ts +0 -35
  84. package/src/css/property-descriptors/object-fit.ts +0 -39
  85. package/src/css/property-descriptors/opacity.ts +0 -15
  86. package/src/css/property-descriptors/overflow-wrap.ts +0 -22
  87. package/src/css/property-descriptors/overflow.ts +0 -34
  88. package/src/css/property-descriptors/padding.ts +0 -14
  89. package/src/css/property-descriptors/paint-order.ts +0 -42
  90. package/src/css/property-descriptors/position.ts +0 -30
  91. package/src/css/property-descriptors/quotes.ts +0 -57
  92. package/src/css/property-descriptors/rotate.ts +0 -34
  93. package/src/css/property-descriptors/text-align.ts +0 -26
  94. package/src/css/property-descriptors/text-decoration-color.ts +0 -9
  95. package/src/css/property-descriptors/text-decoration-line.ts +0 -38
  96. package/src/css/property-descriptors/text-decoration-style.ts +0 -32
  97. package/src/css/property-descriptors/text-decoration-thickness.ts +0 -30
  98. package/src/css/property-descriptors/text-overflow.ts +0 -23
  99. package/src/css/property-descriptors/text-shadow.ts +0 -52
  100. package/src/css/property-descriptors/text-transform.ts +0 -27
  101. package/src/css/property-descriptors/text-underline-offset.ts +0 -27
  102. package/src/css/property-descriptors/transform-origin.ts +0 -29
  103. package/src/css/property-descriptors/transform.ts +0 -74
  104. package/src/css/property-descriptors/visibility.ts +0 -25
  105. package/src/css/property-descriptors/webkit-line-clamp.ts +0 -30
  106. package/src/css/property-descriptors/webkit-text-stroke-color.ts +0 -8
  107. package/src/css/property-descriptors/webkit-text-stroke-width.ts +0 -15
  108. package/src/css/property-descriptors/word-break.ts +0 -25
  109. package/src/css/property-descriptors/writing-mode.ts +0 -37
  110. package/src/css/property-descriptors/z-index.ts +0 -27
  111. package/src/css/syntax/__tests__/tokernizer-tests.ts +0 -29
  112. package/src/css/syntax/parser.ts +0 -188
  113. package/src/css/syntax/tokenizer.ts +0 -822
  114. package/src/css/type-descriptor.ts +0 -7
  115. package/src/css/types/__tests__/color-tests.ts +0 -147
  116. package/src/css/types/__tests__/image-tests.ts +0 -239
  117. package/src/css/types/angle.ts +0 -86
  118. package/src/css/types/color-math.ts +0 -22
  119. package/src/css/types/color-spaces/a98.ts +0 -86
  120. package/src/css/types/color-spaces/p3.ts +0 -92
  121. package/src/css/types/color-spaces/pro-photo.ts +0 -87
  122. package/src/css/types/color-spaces/rec2020.ts +0 -90
  123. package/src/css/types/color-spaces/srgb.ts +0 -87
  124. package/src/css/types/color-utilities.ts +0 -452
  125. package/src/css/types/color.ts +0 -485
  126. package/src/css/types/functions/-prefix-linear-gradient.ts +0 -35
  127. package/src/css/types/functions/-prefix-radial-gradient.ts +0 -106
  128. package/src/css/types/functions/-webkit-gradient.ts +0 -69
  129. package/src/css/types/functions/__tests__/radial-gradient.ts +0 -69
  130. package/src/css/types/functions/counter.ts +0 -511
  131. package/src/css/types/functions/gradient.ts +0 -206
  132. package/src/css/types/functions/linear-gradient.ts +0 -28
  133. package/src/css/types/functions/radial-gradient.ts +0 -101
  134. package/src/css/types/image.ts +0 -120
  135. package/src/css/types/index.ts +0 -1
  136. package/src/css/types/length-percentage.ts +0 -137
  137. package/src/css/types/length.ts +0 -7
  138. package/src/css/types/time.ts +0 -20
  139. package/src/dom/__mocks__/document-cloner.ts +0 -22
  140. package/src/dom/__tests__/dom-normalizer.test.ts +0 -133
  141. package/src/dom/__tests__/element-container.test.ts +0 -129
  142. package/src/dom/document-cloner.ts +0 -929
  143. package/src/dom/dom-normalizer.ts +0 -133
  144. package/src/dom/element-container.ts +0 -75
  145. package/src/dom/elements/li-element-container.ts +0 -10
  146. package/src/dom/elements/ol-element-container.ts +0 -12
  147. package/src/dom/elements/select-element-container.ts +0 -10
  148. package/src/dom/elements/textarea-element-container.ts +0 -9
  149. package/src/dom/node-parser.ts +0 -177
  150. package/src/dom/node-type-guards.ts +0 -70
  151. package/src/dom/replaced-elements/canvas-element-container.ts +0 -15
  152. package/src/dom/replaced-elements/iframe-element-container.ts +0 -55
  153. package/src/dom/replaced-elements/image-element-container.ts +0 -16
  154. package/src/dom/replaced-elements/index.ts +0 -5
  155. package/src/dom/replaced-elements/input-element-container.ts +0 -105
  156. package/src/dom/replaced-elements/pseudo-elements.ts +0 -0
  157. package/src/dom/replaced-elements/svg-element-container.ts +0 -23
  158. package/src/dom/text-container.ts +0 -42
  159. package/src/global.d.ts +0 -19
  160. package/src/index.ts +0 -82
  161. package/src/invariant.ts +0 -5
  162. package/src/options.ts +0 -55
  163. package/src/render/__tests__/object-fit.test.ts +0 -85
  164. package/src/render/background.ts +0 -298
  165. package/src/render/bezier-curve.ts +0 -47
  166. package/src/render/border.ts +0 -165
  167. package/src/render/bound-curves.ts +0 -388
  168. package/src/render/box-sizing.ts +0 -31
  169. package/src/render/canvas/__tests__/background-renderer.test.ts +0 -72
  170. package/src/render/canvas/__tests__/border-renderer.test.ts +0 -24
  171. package/src/render/canvas/__tests__/effects-renderer.test.ts +0 -32
  172. package/src/render/canvas/__tests__/text-renderer.test.ts +0 -471
  173. package/src/render/canvas/background-renderer.ts +0 -271
  174. package/src/render/canvas/border-renderer.ts +0 -224
  175. package/src/render/canvas/canvas-path.ts +0 -31
  176. package/src/render/canvas/canvas-renderer.ts +0 -641
  177. package/src/render/canvas/effects-renderer.ts +0 -130
  178. package/src/render/canvas/foreignobject-renderer.ts +0 -53
  179. package/src/render/canvas/text-renderer.ts +0 -700
  180. package/src/render/effects.ts +0 -75
  181. package/src/render/font-metrics.ts +0 -72
  182. package/src/render/object-fit.ts +0 -100
  183. package/src/render/path.ts +0 -37
  184. package/src/render/renderer-interface.ts +0 -28
  185. package/src/render/stacking-context.ts +0 -386
  186. package/src/render/vector.ts +0 -19
@@ -1,57 +0,0 @@
1
- /**
2
- * Origin Checker
3
- *
4
- * Provides origin checking functionality without global static state.
5
- * Each instance maintains its own anchor element and origin reference.
6
- *
7
- * Replaces the static methods in CacheStorage with instance-based approach.
8
- */
9
- export class OriginChecker {
10
- private readonly link: HTMLAnchorElement;
11
- private readonly origin: string;
12
-
13
- constructor(window: Window) {
14
- if (!window || !window.document) {
15
- throw new Error('Valid window object required for OriginChecker');
16
- }
17
-
18
- if (!window.location || !window.location.href) {
19
- throw new Error('Window object must have valid location');
20
- }
21
-
22
- this.link = window.document.createElement('a');
23
- this.origin = this.getOrigin(window.location.href);
24
- }
25
-
26
- /**
27
- * Get the origin (protocol + hostname + port) of a URL
28
- *
29
- * @param url - URL to parse
30
- * @returns Origin string (e.g., "https://example.com:8080")
31
- */
32
- getOrigin(url: string): string {
33
- this.link.href = url;
34
- // IE9 hack: accessing href twice to ensure it's properly parsed
35
- this.link.href = this.link.href;
36
- return this.link.protocol + this.link.hostname + this.link.port;
37
- }
38
-
39
- /**
40
- * Check if a URL is from the same origin as the context
41
- *
42
- * @param src - URL to check
43
- * @returns true if same origin, false otherwise
44
- */
45
- isSameOrigin(src: string): boolean {
46
- return this.getOrigin(src) === this.origin;
47
- }
48
-
49
- /**
50
- * Get the current context origin
51
- *
52
- * @returns The origin of the context window
53
- */
54
- getContextOrigin(): string {
55
- return this.origin;
56
- }
57
- }
@@ -1,241 +0,0 @@
1
- import { Context } from './context';
2
-
3
- /**
4
- * Performance Metric
5
- *
6
- * Represents a single performance measurement
7
- */
8
- export interface PerformanceMetric {
9
- name: string;
10
- startTime: number;
11
- endTime?: number;
12
- duration?: number;
13
- metadata?: Record<string, any>;
14
- }
15
-
16
- /**
17
- * Performance Summary
18
- *
19
- * Aggregated performance data
20
- */
21
- export interface PerformanceSummary {
22
- totalDuration: number;
23
- metrics: PerformanceMetric[];
24
- breakdown: Array<{
25
- name: string;
26
- duration: number;
27
- percentage: string;
28
- }>;
29
- }
30
-
31
- /**
32
- * Performance Monitor
33
- *
34
- * Tracks performance metrics throughout the rendering pipeline.
35
- * Provides insights into where time is spent during rendering.
36
- *
37
- * Usage:
38
- * ```typescript
39
- * const monitor = new PerformanceMonitor(context);
40
- *
41
- * monitor.start('clone');
42
- * await cloneDocument();
43
- * monitor.end('clone');
44
- *
45
- * const summary = monitor.getSummary();
46
- * ```
47
- */
48
- export class PerformanceMonitor {
49
- private readonly activeMetrics: Map<string, PerformanceMetric> = new Map();
50
- private readonly completedMetrics: PerformanceMetric[] = [];
51
- private readonly enabled: boolean;
52
- private readonly getTime: () => number;
53
-
54
- constructor(
55
- private readonly context: Context | null,
56
- enabled: boolean = true
57
- ) {
58
- this.enabled = enabled;
59
-
60
- // Fallback for environments without performance.now()
61
- this.getTime =
62
- typeof performance !== 'undefined' && typeof performance.now === 'function'
63
- ? () => performance.now()
64
- : () => Date.now();
65
- }
66
-
67
- /**
68
- * Start measuring a performance metric
69
- *
70
- * @param name - Unique name for this metric
71
- * @param metadata - Optional metadata to attach
72
- */
73
- start(name: string, metadata?: Record<string, any>): void {
74
- if (!this.enabled) {
75
- return;
76
- }
77
-
78
- if (this.activeMetrics.has(name)) {
79
- this.context?.logger.warn(`Performance metric '${name}' already started. Overwriting.`);
80
- }
81
-
82
- this.activeMetrics.set(name, {
83
- name,
84
- startTime: this.getTime(),
85
- metadata
86
- });
87
- }
88
-
89
- /**
90
- * End measuring a performance metric
91
- *
92
- * @param name - Name of the metric to end
93
- * @returns The completed metric, or undefined if not found
94
- */
95
- end(name: string): PerformanceMetric | undefined {
96
- if (!this.enabled) {
97
- return undefined;
98
- }
99
-
100
- const metric = this.activeMetrics.get(name);
101
-
102
- if (!metric) {
103
- this.context?.logger.warn(`Performance metric '${name}' not found. Was start() called?`);
104
- return undefined;
105
- }
106
-
107
- metric.endTime = this.getTime();
108
- metric.duration = metric.endTime - metric.startTime;
109
-
110
- this.completedMetrics.push(metric);
111
- this.activeMetrics.delete(name);
112
-
113
- this.context?.logger.debug(`⏱️ ${name}: ${metric.duration.toFixed(2)}ms`, metric.metadata);
114
-
115
- return metric;
116
- }
117
-
118
- /**
119
- * Measure a synchronous function
120
- *
121
- * @param name - Name for this measurement
122
- * @param fn - Function to measure
123
- * @param metadata - Optional metadata
124
- * @returns The function's return value
125
- */
126
- measure<T>(name: string, fn: () => T, metadata?: Record<string, any>): T {
127
- this.start(name, metadata);
128
- try {
129
- const result = fn();
130
- this.end(name);
131
- return result;
132
- } catch (error) {
133
- this.end(name);
134
- throw error;
135
- }
136
- }
137
-
138
- /**
139
- * Measure an asynchronous function
140
- *
141
- * @param name - Name for this measurement
142
- * @param fn - Async function to measure
143
- * @param metadata - Optional metadata
144
- * @returns Promise resolving to the function's return value
145
- */
146
- async measureAsync<T>(name: string, fn: () => Promise<T>, metadata?: Record<string, any>): Promise<T> {
147
- this.start(name, metadata);
148
- try {
149
- const result = await fn();
150
- this.end(name);
151
- return result;
152
- } catch (error) {
153
- this.end(name);
154
- throw error;
155
- }
156
- }
157
-
158
- /**
159
- * Get all completed metrics
160
- *
161
- * @returns Array of completed performance metrics
162
- */
163
- getMetrics(): PerformanceMetric[] {
164
- return [...this.completedMetrics];
165
- }
166
-
167
- /**
168
- * Get a specific metric by name
169
- *
170
- * @param name - Metric name
171
- * @returns The metric, or undefined if not found
172
- */
173
- getMetric(name: string): PerformanceMetric | undefined {
174
- return this.completedMetrics.find((m) => m.name === name);
175
- }
176
-
177
- /**
178
- * Get performance summary
179
- *
180
- * @returns Aggregated performance data
181
- */
182
- getSummary(): PerformanceSummary {
183
- const totalDuration = this.completedMetrics.reduce((sum, metric) => sum + (metric.duration || 0), 0);
184
-
185
- const breakdown = this.completedMetrics.map((metric) => ({
186
- name: metric.name,
187
- duration: metric.duration || 0,
188
- percentage: totalDuration > 0 ? (((metric.duration || 0) / totalDuration) * 100).toFixed(1) + '%' : '0%'
189
- }));
190
-
191
- return {
192
- totalDuration,
193
- metrics: this.getMetrics(),
194
- breakdown
195
- };
196
- }
197
-
198
- /**
199
- * Log performance summary to console
200
- */
201
- logSummary(): void {
202
- if (!this.enabled || this.completedMetrics.length === 0 || !this.context) {
203
- return;
204
- }
205
-
206
- const summary = this.getSummary();
207
-
208
- this.context.logger.info(`\n📊 Performance Summary (Total: ${summary.totalDuration.toFixed(2)}ms):`);
209
-
210
- summary.breakdown
211
- .sort((a, b) => b.duration - a.duration)
212
- .forEach((item) => {
213
- this.context!.logger.info(
214
- ` ${item.name.padEnd(20)} ${item.duration.toFixed(2).padStart(8)}ms ${item.percentage.padStart(6)}`
215
- );
216
- });
217
- }
218
-
219
- /**
220
- * Clear all metrics
221
- */
222
- clear(): void {
223
- this.activeMetrics.clear();
224
- this.completedMetrics.splice(0);
225
- }
226
-
227
- /**
228
- * Check if monitoring is enabled
229
- */
230
- isEnabled(): boolean {
231
- return this.enabled;
232
- }
233
-
234
- /**
235
- * Get active (uncompleted) metrics
236
- * Useful for debugging leaked measurements
237
- */
238
- getActiveMetrics(): string[] {
239
- return Array.from(this.activeMetrics.keys());
240
- }
241
- }
@@ -1,272 +0,0 @@
1
- import { Bounds, parseBounds, parseDocumentSize } from '../css/layout/bounds';
2
- import { COLORS, parseColor } from '../css/types/color';
3
- import { isTransparent } from '../css/types/color-utilities';
4
- import { CloneConfigurations, DocumentCloner } from '../dom/document-cloner';
5
- import { isBodyElement, isHTMLElement, parseTree } from '../dom/node-parser';
6
- import { ElementContainer } from '../dom/element-container';
7
- import { CanvasRenderer, RenderConfigurations } from '../render/canvas/canvas-renderer';
8
- import { ForeignObjectRenderer } from '../render/canvas/foreignobject-renderer';
9
- import { Context } from './context';
10
- import { Html2CanvasConfig } from '../config';
11
- import { createDefaultValidator } from './validator';
12
- import { PerformanceMonitor } from './performance-monitor';
13
- import type { Options } from '../options';
14
-
15
- const coerceNumberOptions = (opts: Partial<Options>): void => {
16
- const numKeys: (keyof Options)[] = [
17
- 'scale',
18
- 'width',
19
- 'height',
20
- 'imageTimeout',
21
- 'x',
22
- 'y',
23
- 'windowWidth',
24
- 'windowHeight',
25
- 'scrollX',
26
- 'scrollY'
27
- ];
28
- numKeys.forEach((key) => {
29
- const v = opts[key];
30
- if (v !== undefined && v !== null && typeof v !== 'number') {
31
- const n = Number(v);
32
- if (!Number.isNaN(n)) {
33
- (opts as Record<string, unknown>)[key] = n;
34
- }
35
- }
36
- });
37
- };
38
-
39
- export const renderElement = async (
40
- element: HTMLElement,
41
- opts: Partial<Options>,
42
- config: Html2CanvasConfig
43
- ): Promise<HTMLCanvasElement> => {
44
- coerceNumberOptions(opts);
45
-
46
- // Input validation (unless explicitly skipped)
47
- if (!opts.skipValidation) {
48
- const validator = opts.validator || createDefaultValidator();
49
-
50
- const elementValidation = validator.validateElement(element);
51
- if (!elementValidation.valid) {
52
- throw new Error(elementValidation.error);
53
- }
54
-
55
- const optionsValidation = validator.validateOptions(opts);
56
- if (!optionsValidation.valid) {
57
- throw new Error(`Invalid options: ${optionsValidation.error}`);
58
- }
59
- }
60
-
61
- if (!element || typeof element !== 'object') {
62
- throw new Error('Invalid element provided as first argument');
63
- }
64
- const ownerDocument = element.ownerDocument;
65
-
66
- if (!ownerDocument) {
67
- throw new Error(`Element is not attached to a Document`);
68
- }
69
-
70
- const defaultView = ownerDocument.defaultView;
71
-
72
- if (!defaultView) {
73
- throw new Error(`Document is not attached to a Window`);
74
- }
75
-
76
- const resourceOptions = {
77
- allowTaint: opts.allowTaint ?? false,
78
- imageTimeout: opts.imageTimeout ?? 15000,
79
- proxy: opts.proxy,
80
- useCORS: opts.useCORS ?? false,
81
- customIsSameOrigin: opts.customIsSameOrigin
82
- };
83
-
84
- const contextOptions = {
85
- logging: opts.logging ?? true,
86
- cache: opts.cache ?? config.cache,
87
- ...resourceOptions
88
- };
89
-
90
- const DEFAULT_WINDOW_WIDTH = 800;
91
- const DEFAULT_WINDOW_HEIGHT = 600;
92
- const DEFAULT_SCROLL = 0;
93
- const win = defaultView as Window & {
94
- innerWidth?: number;
95
- innerHeight?: number;
96
- pageXOffset?: number;
97
- pageYOffset?: number;
98
- };
99
- const windowOptions = {
100
- windowWidth: opts.windowWidth ?? win.innerWidth ?? DEFAULT_WINDOW_WIDTH,
101
- windowHeight: opts.windowHeight ?? win.innerHeight ?? DEFAULT_WINDOW_HEIGHT,
102
- scrollX: opts.scrollX ?? win.pageXOffset ?? DEFAULT_SCROLL,
103
- scrollY: opts.scrollY ?? win.pageYOffset ?? DEFAULT_SCROLL
104
- };
105
-
106
- const windowBounds = new Bounds(
107
- windowOptions.scrollX,
108
- windowOptions.scrollY,
109
- windowOptions.windowWidth,
110
- windowOptions.windowHeight
111
- );
112
-
113
- const context = new Context(contextOptions, windowBounds, config);
114
-
115
- const performanceMonitoring = opts.enablePerformanceMonitoring ?? opts.logging ?? false;
116
- const perfMonitor = new PerformanceMonitor(context, performanceMonitoring);
117
-
118
- perfMonitor.start('total', {
119
- width: windowOptions.windowWidth,
120
- height: windowOptions.windowHeight
121
- });
122
-
123
- const signal = opts.signal;
124
-
125
- if (signal?.aborted) {
126
- throw new DOMException('The operation was aborted.', 'AbortError');
127
- }
128
-
129
- const foreignObjectRendering = opts.foreignObjectRendering ?? false;
130
-
131
- const cloneOptions: CloneConfigurations = {
132
- allowTaint: opts.allowTaint ?? false,
133
- onclone: opts.onclone,
134
- ignoreElements: opts.ignoreElements,
135
- iframeContainer: opts.iframeContainer,
136
- inlineImages: foreignObjectRendering,
137
- copyStyles: foreignObjectRendering,
138
- cspNonce: opts.cspNonce ?? config.cspNonce
139
- };
140
-
141
- context.logger.debug(
142
- `Starting document clone with size ${windowBounds.width}x${
143
- windowBounds.height
144
- } scrolled to ${-windowBounds.left},${-windowBounds.top}`
145
- );
146
-
147
- perfMonitor.start('clone');
148
- const documentCloner = new DocumentCloner(context, element, cloneOptions);
149
- const clonedElement = documentCloner.clonedReferenceElement;
150
- if (!clonedElement) {
151
- throw new Error('Unable to find element in cloned iframe');
152
- }
153
-
154
- const container = await documentCloner.toIFrame(ownerDocument, windowBounds);
155
- perfMonitor.end('clone');
156
-
157
- if (signal?.aborted) {
158
- if (opts.removeContainer ?? true) {
159
- DocumentCloner.destroy(container);
160
- }
161
- throw new DOMException('The operation was aborted.', 'AbortError');
162
- }
163
-
164
- const { width, height, left, top } =
165
- isBodyElement(clonedElement) || isHTMLElement(clonedElement)
166
- ? parseDocumentSize(clonedElement.ownerDocument)
167
- : parseBounds(context, clonedElement);
168
-
169
- const backgroundColor = parseBackgroundColor(context, clonedElement, opts.backgroundColor);
170
-
171
- const renderOptions: RenderConfigurations = {
172
- canvas: opts.canvas,
173
- backgroundColor,
174
- signal,
175
- scale: opts.scale ?? defaultView.devicePixelRatio ?? 1,
176
- x: (opts.x ?? 0) + left,
177
- y: (opts.y ?? 0) + top,
178
- width: opts.width ?? Math.ceil(width),
179
- height: opts.height ?? Math.ceil(height),
180
- imageSmoothing: opts.imageSmoothing,
181
- imageSmoothingQuality: opts.imageSmoothingQuality
182
- };
183
-
184
- let canvas;
185
-
186
- let root: ElementContainer | undefined;
187
-
188
- try {
189
- if (foreignObjectRendering) {
190
- context.logger.debug(`Document cloned, using foreign object rendering`);
191
- perfMonitor.start('render-foreignobject');
192
- const renderer = new ForeignObjectRenderer(context, renderOptions);
193
- canvas = await renderer.render(clonedElement);
194
- perfMonitor.end('render-foreignobject');
195
- } else {
196
- context.logger.debug(
197
- `Document cloned, element located at ${left},${top} with size ${width}x${height} using computed rendering`
198
- );
199
-
200
- context.logger.debug(`Starting DOM parsing`);
201
- perfMonitor.start('parse');
202
- if (signal?.aborted) {
203
- throw new DOMException('The operation was aborted.', 'AbortError');
204
- }
205
- root = parseTree(context, clonedElement);
206
- perfMonitor.end('parse');
207
-
208
- if (backgroundColor === root.styles.backgroundColor) {
209
- root.styles.backgroundColor = COLORS.TRANSPARENT;
210
- }
211
-
212
- context.logger.debug(
213
- `Starting renderer for element at ${renderOptions.x},${renderOptions.y} with size ${renderOptions.width}x${renderOptions.height}`
214
- );
215
-
216
- perfMonitor.start('render');
217
- if (signal?.aborted) {
218
- throw new DOMException('The operation was aborted.', 'AbortError');
219
- }
220
- const renderer = new CanvasRenderer(context, renderOptions);
221
- canvas = await renderer.render(root);
222
- perfMonitor.end('render');
223
- }
224
-
225
- perfMonitor.start('cleanup');
226
- if (opts.removeContainer ?? true) {
227
- if (!DocumentCloner.destroy(container)) {
228
- context.logger.error(`Cannot detach cloned iframe as it is not in the DOM anymore`);
229
- }
230
- }
231
- perfMonitor.end('cleanup');
232
-
233
- perfMonitor.end('total');
234
- context.logger.debug(`Finished rendering`);
235
-
236
- if (performanceMonitoring) {
237
- perfMonitor.logSummary();
238
- }
239
-
240
- return canvas;
241
- } finally {
242
- if (root) {
243
- root.restoreTree();
244
- }
245
- }
246
- };
247
-
248
- const parseBackgroundColor = (context: Context, element: HTMLElement, backgroundColorOverride?: string | null) => {
249
- const ownerDocument = element.ownerDocument;
250
- // http://www.w3.org/TR/css3-background/#special-backgrounds
251
- const documentBackgroundColor = ownerDocument.documentElement
252
- ? parseColor(context, getComputedStyle(ownerDocument.documentElement).backgroundColor as string)
253
- : COLORS.TRANSPARENT;
254
- const bodyBackgroundColor = ownerDocument.body
255
- ? parseColor(context, getComputedStyle(ownerDocument.body).backgroundColor as string)
256
- : COLORS.TRANSPARENT;
257
-
258
- const defaultBackgroundColor =
259
- typeof backgroundColorOverride === 'string'
260
- ? parseColor(context, backgroundColorOverride)
261
- : backgroundColorOverride === null
262
- ? COLORS.TRANSPARENT
263
- : 0xffffffff;
264
-
265
- return element === ownerDocument.documentElement
266
- ? isTransparent(documentBackgroundColor)
267
- ? isTransparent(bodyBackgroundColor)
268
- ? defaultBackgroundColor
269
- : bodyBackgroundColor
270
- : documentBackgroundColor
271
- : defaultBackgroundColor;
272
- };
package/src/core/util.ts DELETED
@@ -1 +0,0 @@
1
- export const SMALL_IMAGE = 'data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7';