html2canvas-pro 2.3.0 → 2.3.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.
- package/dist/html2canvas-pro.cjs +25 -22
- package/dist/html2canvas-pro.cjs.map +1 -1
- package/dist/html2canvas-pro.esm.js +25 -22
- package/dist/html2canvas-pro.esm.js.map +1 -1
- package/dist/html2canvas-pro.js +25 -22
- package/dist/html2canvas-pro.js.map +1 -1
- package/dist/html2canvas-pro.min.js +2 -2
- package/dist/lib/render/canvas/canvas-renderer.js +1 -1
- package/dist/lib/render/canvas/text-renderer.js +26 -20
- package/dist/types/render/canvas/text-renderer.d.ts +3 -2
- package/package.json +1 -1
package/dist/html2canvas-pro.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* html2canvas-pro 2.3.
|
|
2
|
+
* html2canvas-pro 2.3.1 <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
|
*/
|
|
@@ -9144,6 +9144,7 @@
|
|
|
9144
9144
|
constructor(deps) {
|
|
9145
9145
|
this.glyphWidthCache = null;
|
|
9146
9146
|
this.ctx = deps.ctx;
|
|
9147
|
+
this.fontMetrics = deps.fontMetrics;
|
|
9147
9148
|
this.options = deps.options;
|
|
9148
9149
|
this.decorationRenderer = new TextDecorationRenderer(deps.ctx);
|
|
9149
9150
|
}
|
|
@@ -9258,19 +9259,19 @@
|
|
|
9258
9259
|
this.ctx.strokeText(letter, x, y);
|
|
9259
9260
|
});
|
|
9260
9261
|
}
|
|
9261
|
-
renderTextStrokeWithStyle(text, styles) {
|
|
9262
|
+
renderTextStrokeWithStyle(text, styles, baseline) {
|
|
9262
9263
|
if (!styles.webkitTextStrokeWidth || !text.text.trim().length) return;
|
|
9263
9264
|
this.ctx.strokeStyle = asString(styles.webkitTextStrokeColor);
|
|
9264
9265
|
this.ctx.lineWidth = styles.webkitTextStrokeWidth;
|
|
9265
9266
|
this.ctx.lineJoin = getTextStrokeLineJoin();
|
|
9266
|
-
this.renderStrokeText(text, styles.letterSpacing,
|
|
9267
|
+
this.renderStrokeText(text, styles.letterSpacing, baseline, styles.writingMode);
|
|
9267
9268
|
this.ctx.strokeStyle = "";
|
|
9268
9269
|
this.ctx.lineWidth = 0;
|
|
9269
9270
|
this.ctx.lineJoin = "miter";
|
|
9270
9271
|
}
|
|
9271
|
-
renderTextFillWithShadows(text, styles) {
|
|
9272
|
+
renderTextFillWithShadows(text, styles, baseline) {
|
|
9272
9273
|
this.ctx.fillStyle = asString(styles.color);
|
|
9273
|
-
this.renderTextWithLetterSpacing(text, styles.letterSpacing,
|
|
9274
|
+
this.renderTextWithLetterSpacing(text, styles.letterSpacing, baseline, styles.writingMode);
|
|
9274
9275
|
const textShadows = styles.textShadow;
|
|
9275
9276
|
if (textShadows.length && text.text.trim().length) {
|
|
9276
9277
|
textShadows.slice(0).reverse().forEach((textShadow) => {
|
|
@@ -9278,7 +9279,7 @@
|
|
|
9278
9279
|
this.ctx.shadowOffsetX = textShadow.offsetX.number * this.options.scale;
|
|
9279
9280
|
this.ctx.shadowOffsetY = textShadow.offsetY.number * this.options.scale;
|
|
9280
9281
|
this.ctx.shadowBlur = textShadow.blur.number;
|
|
9281
|
-
this.renderTextWithLetterSpacing(text, styles.letterSpacing,
|
|
9282
|
+
this.renderTextWithLetterSpacing(text, styles.letterSpacing, baseline, styles.writingMode);
|
|
9282
9283
|
});
|
|
9283
9284
|
this.ctx.shadowColor = "";
|
|
9284
9285
|
this.ctx.shadowOffsetX = 0;
|
|
@@ -9290,15 +9291,15 @@
|
|
|
9290
9291
|
* Helper method to render text with paint order support
|
|
9291
9292
|
* Reduces code duplication in line-clamp and normal rendering
|
|
9292
9293
|
*/
|
|
9293
|
-
renderTextBoundWithPaintOrder(textBound, styles, paintOrderLayers) {
|
|
9294
|
+
renderTextBoundWithPaintOrder(textBound, styles, paintOrderLayers, baseline) {
|
|
9294
9295
|
paintOrderLayers.forEach((paintOrderLayer) => {
|
|
9295
9296
|
switch (paintOrderLayer) {
|
|
9296
9297
|
case 0:
|
|
9297
9298
|
this.ctx.fillStyle = asString(styles.color);
|
|
9298
|
-
this.renderTextWithLetterSpacing(textBound, styles.letterSpacing,
|
|
9299
|
+
this.renderTextWithLetterSpacing(textBound, styles.letterSpacing, baseline, styles.writingMode);
|
|
9299
9300
|
break;
|
|
9300
9301
|
case 1:
|
|
9301
|
-
this.renderTextStrokeWithStyle(textBound, styles);
|
|
9302
|
+
this.renderTextStrokeWithStyle(textBound, styles, baseline);
|
|
9302
9303
|
break;
|
|
9303
9304
|
}
|
|
9304
9305
|
});
|
|
@@ -9358,7 +9359,7 @@
|
|
|
9358
9359
|
* Groups text bounds by their Y position into visual lines, then renders
|
|
9359
9360
|
* only the first N-1 complete lines followed by an ellipsis on the Nth line.
|
|
9360
9361
|
*/
|
|
9361
|
-
renderLineClampedText(text, styles, paintOrder, containerBounds) {
|
|
9362
|
+
renderLineClampedText(text, styles, paintOrder, baseline, containerBounds) {
|
|
9362
9363
|
const lineHeight = styles.fontSize.number * 1.5;
|
|
9363
9364
|
const lines = [];
|
|
9364
9365
|
let currentLine = [];
|
|
@@ -9373,7 +9374,7 @@
|
|
|
9373
9374
|
if (currentLine.length > 0) lines.push(currentLine);
|
|
9374
9375
|
const maxLines = styles.webkitLineClamp;
|
|
9375
9376
|
if (lines.length <= maxLines) return false;
|
|
9376
|
-
for (let i = 0; i < maxLines - 1; i++) lines[i].forEach((tb) => this.renderTextBoundWithPaintOrder(tb, styles, paintOrder));
|
|
9377
|
+
for (let i = 0; i < maxLines - 1; i++) lines[i].forEach((tb) => this.renderTextBoundWithPaintOrder(tb, styles, paintOrder, baseline));
|
|
9377
9378
|
const lastLine = lines[maxLines - 1];
|
|
9378
9379
|
if (lastLine?.length && containerBounds) {
|
|
9379
9380
|
const textStr = lastLine.map((tb) => tb.text).join("");
|
|
@@ -9382,8 +9383,8 @@
|
|
|
9382
9383
|
const bounds = new TextBounds(this.truncateTextWithEllipsis(textStr, avail, styles.letterSpacing), first.bounds);
|
|
9383
9384
|
for (const layer of paintOrder) if (layer === 0) {
|
|
9384
9385
|
this.ctx.fillStyle = asString(styles.color);
|
|
9385
|
-
this.renderTextWithLetterSpacing(bounds, styles.letterSpacing,
|
|
9386
|
-
} else if (layer === 1) this.renderTextStrokeWithStyle(bounds, styles);
|
|
9386
|
+
this.renderTextWithLetterSpacing(bounds, styles.letterSpacing, baseline, styles.writingMode);
|
|
9387
|
+
} else if (layer === 1) this.renderTextStrokeWithStyle(bounds, styles, baseline);
|
|
9387
9388
|
}
|
|
9388
9389
|
return true;
|
|
9389
9390
|
}
|
|
@@ -9391,34 +9392,36 @@
|
|
|
9391
9392
|
* Render single-line text with text-overflow: ellipsis.
|
|
9392
9393
|
* Returns true if ellipsis was applied (caller should skip normal rendering).
|
|
9393
9394
|
*/
|
|
9394
|
-
renderEllipsisText(text, styles, paintOrder, containerBounds) {
|
|
9395
|
+
renderEllipsisText(text, styles, paintOrder, baseline, containerBounds) {
|
|
9395
9396
|
const lineHeight = styles.fontSize.number * 1.5;
|
|
9396
9397
|
const firstTop = text.textBounds[0].bounds.top;
|
|
9397
9398
|
if (!text.textBounds.every((tb) => Math.abs(tb.bounds.top - firstTop) < lineHeight * .5)) return false;
|
|
9398
9399
|
let fullText = text.textBounds.map((tb) => tb.text).join("").replace(/\s+/g, " ").trim();
|
|
9399
9400
|
if (this.ctx.measureText(fullText).width <= containerBounds.width) return false;
|
|
9400
9401
|
const bounds = new TextBounds(this.truncateTextWithEllipsis(fullText, containerBounds.width, styles.letterSpacing), text.textBounds[0].bounds);
|
|
9401
|
-
for (const layer of paintOrder) if (layer === 0) this.renderTextFillWithShadows(bounds, styles);
|
|
9402
|
-
else if (layer === 1) this.renderTextStrokeWithStyle(bounds, styles);
|
|
9402
|
+
for (const layer of paintOrder) if (layer === 0) this.renderTextFillWithShadows(bounds, styles, baseline);
|
|
9403
|
+
else if (layer === 1) this.renderTextStrokeWithStyle(bounds, styles, baseline);
|
|
9403
9404
|
return true;
|
|
9404
9405
|
}
|
|
9405
9406
|
async renderTextNode(text, styles, containerBounds) {
|
|
9406
9407
|
this.glyphWidthCache = null;
|
|
9407
|
-
|
|
9408
|
+
const [fontString, fontFamily, fontSize] = this.createFontStyle(styles);
|
|
9409
|
+
this.ctx.font = fontString;
|
|
9408
9410
|
this.ctx.direction = styles.direction === 1 ? "rtl" : "ltr";
|
|
9409
9411
|
this.ctx.textAlign = "left";
|
|
9410
9412
|
this.ctx.textBaseline = "alphabetic";
|
|
9411
9413
|
const paintOrder = styles.paintOrder;
|
|
9414
|
+
const { baseline } = this.fontMetrics.getMetrics(fontFamily, fontSize);
|
|
9412
9415
|
if (styles.webkitLineClamp > 0 && (styles.display & 2) !== 0 && styles.overflowY === 1 && text.textBounds.length > 0) {
|
|
9413
|
-
if (this.renderLineClampedText(text, styles, paintOrder, containerBounds)) return;
|
|
9416
|
+
if (this.renderLineClampedText(text, styles, paintOrder, baseline, containerBounds)) return;
|
|
9414
9417
|
}
|
|
9415
|
-
if (styles.textOverflow === 1 && containerBounds && styles.overflowX === 1 && text.textBounds.length > 0 && this.renderEllipsisText(text, styles, paintOrder, containerBounds)) return;
|
|
9418
|
+
if (styles.textOverflow === 1 && containerBounds && styles.overflowX === 1 && text.textBounds.length > 0 && this.renderEllipsisText(text, styles, paintOrder, baseline, containerBounds)) return;
|
|
9416
9419
|
text.textBounds.forEach((tb) => {
|
|
9417
9420
|
paintOrder.forEach((layer) => {
|
|
9418
9421
|
if (layer === 0) {
|
|
9419
|
-
this.renderTextFillWithShadows(tb, styles);
|
|
9422
|
+
this.renderTextFillWithShadows(tb, styles, baseline);
|
|
9420
9423
|
if (styles.textDecorationLine.length) this.renderTextDecoration(tb.bounds, styles);
|
|
9421
|
-
} else if (layer === 1) this.renderTextStrokeWithStyle(tb, styles);
|
|
9424
|
+
} else if (layer === 1) this.renderTextStrokeWithStyle(tb, styles, baseline);
|
|
9422
9425
|
});
|
|
9423
9426
|
});
|
|
9424
9427
|
}
|
|
@@ -10455,7 +10458,7 @@
|
|
|
10455
10458
|
this.effectsRenderer = new EffectsRenderer({ ctx: this.ctx }, { path: (paths) => this.path(paths) });
|
|
10456
10459
|
this.textRenderer = new TextRenderer({
|
|
10457
10460
|
ctx: this.ctx,
|
|
10458
|
-
|
|
10461
|
+
fontMetrics: this.fontMetrics,
|
|
10459
10462
|
options: { scale: options.scale }
|
|
10460
10463
|
});
|
|
10461
10464
|
this.context.logger.debug(`Canvas renderer initialized (${options.width}x${options.height}) with scale ${options.scale}`);
|