html2canvas-pro 2.5.4 → 2.6.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.
- package/dist/html2canvas-pro.cjs +46 -11
- package/dist/html2canvas-pro.cjs.map +1 -1
- package/dist/html2canvas-pro.esm.js +46 -11
- package/dist/html2canvas-pro.esm.js.map +1 -1
- package/dist/html2canvas-pro.js +46 -11
- package/dist/html2canvas-pro.js.map +1 -1
- package/dist/html2canvas-pro.min.js +6 -6
- package/dist/types/core/validator.d.ts +9 -1
- package/dist/types/dom/iframe-mount.d.ts +1 -1
- package/package.json +5 -4
package/dist/html2canvas-pro.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* html2canvas-pro 2.
|
|
2
|
+
* html2canvas-pro 2.6.0 <https://yorickshan.github.io/html2canvas-pro/>
|
|
3
3
|
* Copyright (c) 2024-present yorickshan and html2canvas-pro contributors
|
|
4
4
|
* Released under MIT License
|
|
5
5
|
*/
|
|
@@ -249,6 +249,30 @@
|
|
|
249
249
|
};
|
|
250
250
|
}
|
|
251
251
|
/**
|
|
252
|
+
* Validate the backgroundColor option
|
|
253
|
+
*
|
|
254
|
+
* @param backgroundColor - CSS color string or null (transparent)
|
|
255
|
+
* @returns Validation result
|
|
256
|
+
*/
|
|
257
|
+
validateBackgroundColor(backgroundColor) {
|
|
258
|
+
if (backgroundColor === null) return {
|
|
259
|
+
valid: true,
|
|
260
|
+
sanitized: null
|
|
261
|
+
};
|
|
262
|
+
if (typeof backgroundColor !== "string" || backgroundColor.length === 0) return {
|
|
263
|
+
valid: false,
|
|
264
|
+
error: "backgroundColor must be a CSS color string or null"
|
|
265
|
+
};
|
|
266
|
+
if (/[^a-zA-Z0-9%(),.#\s/-]/.test(backgroundColor)) return {
|
|
267
|
+
valid: false,
|
|
268
|
+
error: `backgroundColor contains characters that cannot appear in a CSS color: ${backgroundColor}`
|
|
269
|
+
};
|
|
270
|
+
return {
|
|
271
|
+
valid: true,
|
|
272
|
+
sanitized: backgroundColor
|
|
273
|
+
};
|
|
274
|
+
}
|
|
275
|
+
/**
|
|
252
276
|
* Validate image timeout
|
|
253
277
|
*
|
|
254
278
|
* @param timeout - Timeout in milliseconds
|
|
@@ -393,6 +417,10 @@
|
|
|
393
417
|
const nonceResult = this.validateCspNonce(options.cspNonce);
|
|
394
418
|
if (!nonceResult.valid) errors.push(`CSP nonce: ${nonceResult.error}`);
|
|
395
419
|
}
|
|
420
|
+
if (options.backgroundColor !== void 0) {
|
|
421
|
+
const colorResult = this.validateBackgroundColor(options.backgroundColor);
|
|
422
|
+
if (!colorResult.valid) errors.push(`backgroundColor: ${colorResult.error}`);
|
|
423
|
+
}
|
|
396
424
|
if (this.config.customValidator) {
|
|
397
425
|
const customResult = this.config.customValidator(options, "options");
|
|
398
426
|
if (!customResult.valid) errors.push(`Custom validation: ${customResult.error}`);
|
|
@@ -8069,9 +8097,9 @@
|
|
|
8069
8097
|
if (!rules) return true;
|
|
8070
8098
|
for (let i = 0; i < rules.length; i++) {
|
|
8071
8099
|
const rule = rules[i];
|
|
8072
|
-
if (rule
|
|
8073
|
-
|
|
8074
|
-
|
|
8100
|
+
if (!rule || !("styleSheet" in rule)) continue;
|
|
8101
|
+
const inner = rule.styleSheet;
|
|
8102
|
+
if (!inner || !isSheetFullyApplied(inner, depth + 1)) return false;
|
|
8075
8103
|
}
|
|
8076
8104
|
return true;
|
|
8077
8105
|
};
|
|
@@ -8113,7 +8141,7 @@
|
|
|
8113
8141
|
* remain as the settle path for plain <link> fetches.
|
|
8114
8142
|
* @internal – exported for testing only.
|
|
8115
8143
|
*/
|
|
8116
|
-
const stylesheetsReady = (documentClone, logger, signal) => {
|
|
8144
|
+
const stylesheetsReady = (documentClone, logger, signal, timeoutMs = STYLESHEET_READY_TIMEOUT_MS) => {
|
|
8117
8145
|
if (signal?.aborted) return Promise.resolve();
|
|
8118
8146
|
const pending = [];
|
|
8119
8147
|
const links = [];
|
|
@@ -8143,8 +8171,8 @@
|
|
|
8143
8171
|
const timer = setInterval(() => {
|
|
8144
8172
|
elapsed += 50;
|
|
8145
8173
|
if (link.sheet) settle();
|
|
8146
|
-
else if (elapsed >=
|
|
8147
|
-
logger?.warn(`Stylesheet ${href} did not finish loading within ${
|
|
8174
|
+
else if (elapsed >= timeoutMs) {
|
|
8175
|
+
logger?.warn(`Stylesheet ${href} did not finish loading within ${timeoutMs / 1e3}s; continuing with a possibly unstyled clone`);
|
|
8148
8176
|
settle();
|
|
8149
8177
|
}
|
|
8150
8178
|
}, 50);
|
|
@@ -8161,8 +8189,8 @@
|
|
|
8161
8189
|
const timer = setInterval(() => {
|
|
8162
8190
|
elapsed += 50;
|
|
8163
8191
|
const currentSheet = style.sheet;
|
|
8164
|
-
if (currentSheet && isSheetFullyApplied(currentSheet) || elapsed >=
|
|
8165
|
-
if (elapsed >=
|
|
8192
|
+
if (currentSheet && isSheetFullyApplied(currentSheet) || elapsed >= timeoutMs) {
|
|
8193
|
+
if (elapsed >= timeoutMs && !isSheetFullyApplied(currentSheet ?? null)) logger?.warn(`@import chain in an inline <style> did not finish loading within ${timeoutMs / 1e3}s; continuing with a possibly unstyled clone`);
|
|
8166
8194
|
clearInterval(timer);
|
|
8167
8195
|
resolve();
|
|
8168
8196
|
}
|
|
@@ -9850,7 +9878,7 @@
|
|
|
9850
9878
|
if (treatAsRealStackingContext || createsStackingContext) {
|
|
9851
9879
|
const parentStack = treatAsRealStackingContext || child.styles.isPositioned() ? realStackingContext : stackingContext;
|
|
9852
9880
|
const stack = new StackingContext(paintContainer);
|
|
9853
|
-
if (child.styles.isPositioned() || child.styles.opacity < 1 || child.styles.isTransformed()) {
|
|
9881
|
+
if (treatAsRealStackingContext || child.styles.isPositioned() || child.styles.opacity < 1 || child.styles.isTransformed()) {
|
|
9854
9882
|
const order = child.styles.zIndex.order;
|
|
9855
9883
|
if (order < 0) {
|
|
9856
9884
|
let index = 0;
|
|
@@ -12148,6 +12176,7 @@
|
|
|
12148
12176
|
ctx.fillStyle = rasterized.lastColor;
|
|
12149
12177
|
ctx.fillRect(area.left, area.top, area.width, area.height);
|
|
12150
12178
|
ctx.drawImage(rasterized.canvas, area.left + cx - rx, area.top + cy - ry, rx * 2, ry * 2);
|
|
12179
|
+
releaseSurface(rasterized.canvas);
|
|
12151
12180
|
};
|
|
12152
12181
|
/** Draw one gradient layer filling the whole mask area. */
|
|
12153
12182
|
const paintGradientLayer = (ctx, layer, area) => {
|
|
@@ -13061,7 +13090,10 @@
|
|
|
13061
13090
|
maskCanvas.width = surface.width;
|
|
13062
13091
|
maskCanvas.height = surface.height;
|
|
13063
13092
|
const maskCtx = maskCanvas.getContext("2d");
|
|
13064
|
-
if (!maskCtx)
|
|
13093
|
+
if (!maskCtx) {
|
|
13094
|
+
releaseSurface(maskCanvas);
|
|
13095
|
+
return;
|
|
13096
|
+
}
|
|
13065
13097
|
maskCtx.scale(this.options.scale, this.options.scale);
|
|
13066
13098
|
maskCtx.translate(-bounds.left, -bounds.top);
|
|
13067
13099
|
try {
|
|
@@ -13073,6 +13105,7 @@
|
|
|
13073
13105
|
}, async (url) => await this.context.cache.match(url));
|
|
13074
13106
|
} catch (error) {
|
|
13075
13107
|
this.context.logger.error(`Error rendering mask-image: ${error instanceof Error ? error.message : error}`);
|
|
13108
|
+
releaseSurface(maskCanvas);
|
|
13076
13109
|
return;
|
|
13077
13110
|
}
|
|
13078
13111
|
ctx.save();
|
|
@@ -13082,6 +13115,7 @@
|
|
|
13082
13115
|
ctx.drawImage(maskCanvas, 0, 0);
|
|
13083
13116
|
} finally {
|
|
13084
13117
|
ctx.restore();
|
|
13118
|
+
releaseSurface(maskCanvas);
|
|
13085
13119
|
}
|
|
13086
13120
|
}
|
|
13087
13121
|
/**
|
|
@@ -13486,6 +13520,7 @@
|
|
|
13486
13520
|
ctx.fillStyle = rasterized.lastColor;
|
|
13487
13521
|
ctx.fillRect(0, 0, width, height);
|
|
13488
13522
|
ctx.drawImage(rasterized.canvas, cx - rx, cy - ry, rx * 2, ry * 2);
|
|
13523
|
+
releaseSurface(rasterized.canvas);
|
|
13489
13524
|
return canvas;
|
|
13490
13525
|
}
|
|
13491
13526
|
if (source.type === 5 || source.type === 6) {
|