html2canvas-pro 2.3.4 → 2.3.6
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 +72 -23
- package/dist/html2canvas-pro.cjs.map +1 -1
- package/dist/html2canvas-pro.esm.js +72 -23
- package/dist/html2canvas-pro.esm.js.map +1 -1
- package/dist/html2canvas-pro.js +72 -23
- package/dist/html2canvas-pro.js.map +1 -1
- package/dist/html2canvas-pro.min.js +3 -3
- package/dist/lib/dom/document-cloner.js +25 -6
- package/dist/lib/dom/element-container.js +6 -0
- package/dist/lib/dom/node-parser.js +42 -30
- package/dist/lib/render/canvas/canvas-renderer.js +42 -9
- package/dist/lib/render/canvas/text-renderer.js +8 -1
- package/dist/types/dom/document-cloner.d.ts +1 -1
- package/dist/types/dom/element-container.d.ts +6 -0
- package/package.json +1 -1
package/dist/html2canvas-pro.cjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* html2canvas-pro 2.3.
|
|
2
|
+
* html2canvas-pro 2.3.6 <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
|
*/
|
|
@@ -7034,14 +7034,19 @@ var DocumentCloner = class {
|
|
|
7034
7034
|
}
|
|
7035
7035
|
if (clone.loading === "lazy") clone.loading = "eager";
|
|
7036
7036
|
}
|
|
7037
|
-
if (isCustomElement(clone) && !isSVGElementNode(clone)) return this.createCustomElementClone(clone);
|
|
7037
|
+
if (isCustomElement(clone) && !isSVGElementNode(clone)) return this.createCustomElementClone(node, clone);
|
|
7038
7038
|
return clone;
|
|
7039
7039
|
}
|
|
7040
|
-
createCustomElementClone(
|
|
7040
|
+
createCustomElementClone(originalNode, clonedNode) {
|
|
7041
7041
|
const clone = document.createElement("div");
|
|
7042
|
-
clone.className =
|
|
7043
|
-
copyCSSStyles(
|
|
7044
|
-
|
|
7042
|
+
clone.className = clonedNode.className;
|
|
7043
|
+
copyCSSStyles(clonedNode.style, clone);
|
|
7044
|
+
const attributes = clonedNode.attributes;
|
|
7045
|
+
for (let i = 0; i < attributes.length; i++) {
|
|
7046
|
+
const attr = attributes[i];
|
|
7047
|
+
if (attr.name !== "class" && attr.name !== "style") clone.setAttribute(attr.name, attr.value);
|
|
7048
|
+
}
|
|
7049
|
+
if (originalNode.shadowRoot) try {
|
|
7045
7050
|
clone.attachShadow({ mode: "open" });
|
|
7046
7051
|
} catch (e) {
|
|
7047
7052
|
this.context.logger.error("Failed to attach shadow root to custom element clone:", e);
|
|
@@ -7442,6 +7447,10 @@ var ElementContainer = class {
|
|
|
7442
7447
|
this.originalElement = element;
|
|
7443
7448
|
}
|
|
7444
7449
|
this.bounds = parseBounds(this.context, element);
|
|
7450
|
+
if (element.tagName === "FIELDSET") {
|
|
7451
|
+
const legend = element.querySelector(":scope > legend");
|
|
7452
|
+
if (legend) this.legendBounds = parseBounds(this.context, legend);
|
|
7453
|
+
}
|
|
7445
7454
|
if (isDebugging(element, 4)) this.debugRender = true;
|
|
7446
7455
|
}
|
|
7447
7456
|
/**
|
|
@@ -8183,18 +8192,29 @@ const LIST_OWNERS = [
|
|
|
8183
8192
|
const parseNodeTree = (context, node, parent, root) => {
|
|
8184
8193
|
for (let childNode = node.firstChild, nextNode; childNode; childNode = nextNode) {
|
|
8185
8194
|
nextNode = childNode.nextSibling;
|
|
8186
|
-
|
|
8187
|
-
|
|
8188
|
-
|
|
8189
|
-
|
|
8190
|
-
|
|
8191
|
-
|
|
8192
|
-
|
|
8193
|
-
|
|
8194
|
-
|
|
8195
|
-
|
|
8196
|
-
|
|
8197
|
-
|
|
8195
|
+
parseChildNode(context, childNode, parent, root);
|
|
8196
|
+
}
|
|
8197
|
+
};
|
|
8198
|
+
/**
|
|
8199
|
+
* Parse a single node as a child of `parent`.
|
|
8200
|
+
*
|
|
8201
|
+
* Separated from the tree walk so that nodes assigned to a `<slot>` (including
|
|
8202
|
+
* bare text nodes, which have no child nodes) can be parsed directly. Without
|
|
8203
|
+
* this, slotted shadow-DOM content such as web component labels was silently
|
|
8204
|
+
* dropped because `parseNodeTree` only iterates `node.firstChild` (issue #226).
|
|
8205
|
+
*/
|
|
8206
|
+
const parseChildNode = (context, childNode, parent, root) => {
|
|
8207
|
+
if (isTextNode(childNode) && childNode.data.length > 0) parent.textNodes.push(new TextContainer(context, childNode, parent.styles));
|
|
8208
|
+
else if (isElementNode(childNode)) if (isSlotElement(childNode) && childNode.assignedNodes) childNode.assignedNodes().forEach((assignedNode) => parseChildNode(context, assignedNode, parent, root));
|
|
8209
|
+
else {
|
|
8210
|
+
const container = createContainer(context, childNode);
|
|
8211
|
+
if (container.styles.isVisible()) {
|
|
8212
|
+
if (createsRealStackingContext(childNode, container, root)) container.createsRealStackingContext = true;
|
|
8213
|
+
else if (createsStackingContext(container.styles)) container.createsStackingContext = true;
|
|
8214
|
+
if (LIST_OWNERS.indexOf(childNode.tagName) !== -1) container.isListOwner = true;
|
|
8215
|
+
parent.elements.push(container);
|
|
8216
|
+
if (childNode.shadowRoot) parseNodeTree(context, childNode.shadowRoot, container, root);
|
|
8217
|
+
else if (!isTextareaElement(childNode) && !isSVGElement(childNode) && !isSelectElement(childNode)) parseNodeTree(context, childNode, container, root);
|
|
8198
8218
|
}
|
|
8199
8219
|
}
|
|
8200
8220
|
};
|
|
@@ -9067,6 +9087,7 @@ const measureBaseline = (ctx, fallback) => {
|
|
|
9067
9087
|
//#endregion
|
|
9068
9088
|
//#region src/render/canvas/text-renderer.ts
|
|
9069
9089
|
const iOSBrokenFonts = ["-apple-system", "system-ui"];
|
|
9090
|
+
const TEXT_OVERFLOW_EPSILON = 1;
|
|
9070
9091
|
/**
|
|
9071
9092
|
* Detect CJK (Chinese, Japanese, Korean) characters in a string.
|
|
9072
9093
|
* CJK characters use the ideographic baseline in browsers, which differs
|
|
@@ -9369,7 +9390,7 @@ var TextRenderer = class {
|
|
|
9369
9390
|
const firstTop = text.textBounds[0].bounds.top;
|
|
9370
9391
|
if (!text.textBounds.every((tb) => Math.abs(tb.bounds.top - firstTop) < lineHeight * .5)) return false;
|
|
9371
9392
|
let fullText = text.textBounds.map((tb) => tb.text).join("").replace(/\s+/g, " ").trim();
|
|
9372
|
-
if (this.ctx.measureText(fullText).width <= containerBounds.width) return false;
|
|
9393
|
+
if (this.ctx.measureText(fullText).width <= containerBounds.width + TEXT_OVERFLOW_EPSILON) return false;
|
|
9373
9394
|
const bounds = new TextBounds(this.truncateTextWithEllipsis(fullText, containerBounds.width, styles.letterSpacing), text.textBounds[0].bounds);
|
|
9374
9395
|
for (const layer of paintOrder) if (layer === 0) this.renderTextFillWithShadows(bounds, styles, baseline);
|
|
9375
9396
|
else if (layer === 1) this.renderTextStrokeWithStyle(bounds, styles, baseline);
|
|
@@ -10607,10 +10628,38 @@ var CanvasRenderer = class CanvasRenderer {
|
|
|
10607
10628
|
}
|
|
10608
10629
|
let side = 0;
|
|
10609
10630
|
for (const border of borders) {
|
|
10610
|
-
if (border.style !== 0 && !isTransparent(border.color) && border.width > 0)
|
|
10611
|
-
|
|
10612
|
-
|
|
10613
|
-
|
|
10631
|
+
if (border.style !== 0 && !isTransparent(border.color) && border.width > 0) {
|
|
10632
|
+
const renderBorderSide = async () => {
|
|
10633
|
+
if (border.style === 2) await this.borderRenderer.renderDashedDottedBorder(border.color, border.width, side, paint.curves, 2);
|
|
10634
|
+
else if (border.style === 3) await this.borderRenderer.renderDashedDottedBorder(border.color, border.width, side, paint.curves, 3);
|
|
10635
|
+
else if (border.style === 4) await this.borderRenderer.renderDoubleBorder(border.color, border.width, side, paint.curves);
|
|
10636
|
+
else await this.borderRenderer.renderSolidBorder(border.color, side, paint.curves);
|
|
10637
|
+
};
|
|
10638
|
+
const legend = paint.container.legendBounds;
|
|
10639
|
+
if (side === 0 && legend) {
|
|
10640
|
+
const bounds = paint.container.bounds;
|
|
10641
|
+
const legendLeft = legend.left - bounds.left;
|
|
10642
|
+
const legendRight = legend.left + legend.width - bounds.left;
|
|
10643
|
+
if (legendLeft > 0) {
|
|
10644
|
+
this.ctx.save();
|
|
10645
|
+
this.ctx.beginPath();
|
|
10646
|
+
this.ctx.rect(bounds.left, bounds.top, legendLeft, bounds.height);
|
|
10647
|
+
this.ctx.clip();
|
|
10648
|
+
await renderBorderSide();
|
|
10649
|
+
this.ctx.restore();
|
|
10650
|
+
}
|
|
10651
|
+
const rightStart = bounds.left + legendRight;
|
|
10652
|
+
const rightWidth = bounds.width - legendRight;
|
|
10653
|
+
if (rightWidth > 0) {
|
|
10654
|
+
this.ctx.save();
|
|
10655
|
+
this.ctx.beginPath();
|
|
10656
|
+
this.ctx.rect(rightStart, bounds.top, rightWidth, bounds.height);
|
|
10657
|
+
this.ctx.clip();
|
|
10658
|
+
await renderBorderSide();
|
|
10659
|
+
this.ctx.restore();
|
|
10660
|
+
}
|
|
10661
|
+
} else await renderBorderSide();
|
|
10662
|
+
}
|
|
10614
10663
|
side++;
|
|
10615
10664
|
}
|
|
10616
10665
|
}
|