106 lines
5.0 KiB
Diff
106 lines
5.0 KiB
Diff
diff --git a/node_modules/html2canvas-pro/dist/html2canvas-pro.esm.js b/node_modules/html2canvas-pro/dist/html2canvas-pro.esm.js
|
|
index d49f1bd..cb90b52 100644
|
|
--- a/node_modules/html2canvas-pro/dist/html2canvas-pro.esm.js
|
|
+++ b/node_modules/html2canvas-pro/dist/html2canvas-pro.esm.js
|
|
@@ -5875,6 +5875,8 @@ class SVGElementContainer extends ElementContainer {
|
|
constructor(context, img) {
|
|
super(context, img);
|
|
const s = new XMLSerializer();
|
|
+ // Remove transform to prevent double-application (transform is already accounted for in bounds/positioning)
|
|
+ img.style.transform = "none";
|
|
const bounds = parseBounds(context, img);
|
|
img.setAttribute('width', `${bounds.width}px`);
|
|
img.setAttribute('height', `${bounds.height}px`);
|
|
@@ -7144,14 +7146,55 @@ const ignoredStyleProperties = [
|
|
'd', // #2483
|
|
'content' // Safari shows pseudoelements if content is set
|
|
];
|
|
+const svgTextFontProperties = [
|
|
+ 'font-family',
|
|
+ 'font-size',
|
|
+ 'font-weight',
|
|
+ 'font-style',
|
|
+ 'font-variant',
|
|
+ 'font-stretch',
|
|
+ 'font-size-adjust',
|
|
+ 'letter-spacing',
|
|
+ 'word-spacing',
|
|
+ 'line-height',
|
|
+];
|
|
+const isSVGTextNode = (node) => {
|
|
+ const tagName = node.tagName;
|
|
+ return tagName === 'text' || tagName === 'tspan' || tagName === 'textPath';
|
|
+};
|
|
const copyCSSStyles = (style, target) => {
|
|
- // Edge does not provide value for cssText
|
|
- for (let i = style.length - 1; i >= 0; i--) {
|
|
- const property = style.item(i);
|
|
- // fix: Chrome_138 ignore custom properties
|
|
- if (ignoredStyleProperties.indexOf(property) === -1 && !property.startsWith('--')) {
|
|
- target.style.setProperty(property, style.getPropertyValue(property));
|
|
- }
|
|
+ // Use cssText for a single native call instead of iterating 300+ properties
|
|
+ // individually via style.item(i), which is extremely slow in Firefox due to
|
|
+ // Stylo's per-call indexmap lookups in the custom properties map.
|
|
+ target.style.cssText = style.cssText;
|
|
+ // Remove properties that should be ignored
|
|
+ for (let i = ignoredStyleProperties.length - 1; i >= 0; i--) {
|
|
+ target.style.removeProperty(ignoredStyleProperties[i]);
|
|
+ }
|
|
+ // For SVG text elements, explicitly re-apply font properties from the
|
|
+ // computed style since cssText may not reliably serialize them.
|
|
+ if (isSVGTextNode(target)) {
|
|
+ for (let i = 0; i < svgTextFontProperties.length; i++) {
|
|
+ const value = style.getPropertyValue(svgTextFontProperties[i]);
|
|
+ if (value) {
|
|
+ target.style.setProperty(svgTextFontProperties[i], value);
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ // cssText is empty for computed styles in Chrome, which drops the SVG's transform and
|
|
+ // offsets its serialized bounds, re-breaking #68751. Re-apply transform props explicitly.
|
|
+ const transform = style.getPropertyValue('transform');
|
|
+ if (transform && transform !== 'none') {
|
|
+ target.style.setProperty('transform', transform);
|
|
+ target.style.setProperty('transform-origin', style.getPropertyValue('transform-origin'));
|
|
+ target.style.setProperty('transform-box', style.getPropertyValue('transform-box'));
|
|
+ }
|
|
+ // Same empty-cssText Chrome quirk drops the resolved `color`, so SVGs painting
|
|
+ // with fill="currentColor" lose their inherited color when serialized standalone
|
|
+ // (rendered black). Re-apply it so currentColor resolves. (metabase#77001)
|
|
+ const color = style.getPropertyValue('color');
|
|
+ if (color) {
|
|
+ target.style.setProperty('color', color);
|
|
}
|
|
return target;
|
|
};
|
|
@@ -7534,7 +7577,8 @@ class ElementPaint {
|
|
const rotateMatrix = [cos, sin, -sin, cos, 0, 0];
|
|
this.effects.push(new TransformEffect(offsetX, offsetY, rotateMatrix));
|
|
}
|
|
- if (this.container.styles.transform !== null) {
|
|
+ // Skip TransformEffect for SVG elements - their transform is already baked into bounds
|
|
+ if (this.container.styles.transform !== null && !(this.container instanceof SVGElementContainer)) {
|
|
const origin = this.container.styles.transformOrigin;
|
|
const offsetX = this.container.bounds.left + getAbsoluteValue(origin[0], this.container.bounds.width);
|
|
const offsetY = this.container.bounds.top + getAbsoluteValue(origin[1], this.container.bounds.height);
|
|
@@ -10373,12 +10417,12 @@ class Validator {
|
|
}
|
|
// Basic format validation - nonce should be base64-like
|
|
// Typical format: base64 string, often 32+ characters
|
|
- if (nonce.length < 16) {
|
|
- return {
|
|
- valid: false,
|
|
- error: 'CSP nonce is too short (minimum 16 characters recommended)'
|
|
- };
|
|
- }
|
|
+ // if (nonce.length < 16) {
|
|
+ // return {
|
|
+ // valid: false,
|
|
+ // error: 'CSP nonce is too short (minimum 16 characters recommended)'
|
|
+ // };
|
|
+ // }
|
|
// Check for suspicious characters
|
|
if (!/^[A-Za-z0-9+/=_-]+$/.test(nonce)) {
|
|
return {
|