html2canvas-pro 2.3.1 → 2.3.2
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 +34 -64
- package/dist/html2canvas-pro.cjs.map +1 -1
- package/dist/html2canvas-pro.esm.js +34 -64
- package/dist/html2canvas-pro.esm.js.map +1 -1
- package/dist/html2canvas-pro.js +34 -64
- 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 -4
- package/dist/lib/render/canvas/content-renderer.js +5 -3
- package/dist/lib/render/canvas/font-utils.js +29 -0
- package/dist/lib/render/canvas/text-renderer.js +7 -6
- package/dist/types/render/canvas/canvas-renderer.d.ts +0 -1
- package/dist/types/render/canvas/content-renderer.d.ts +1 -2
- package/dist/types/render/canvas/font-utils.d.ts +19 -0
- package/dist/types/render/canvas/text-renderer.d.ts +0 -3
- 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.2 <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
|
*/
|
|
@@ -8950,60 +8950,6 @@
|
|
|
8950
8950
|
}
|
|
8951
8951
|
};
|
|
8952
8952
|
//#endregion
|
|
8953
|
-
//#region src/core/util.ts
|
|
8954
|
-
const SMALL_IMAGE = "data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7";
|
|
8955
|
-
//#endregion
|
|
8956
|
-
//#region src/render/font-metrics.ts
|
|
8957
|
-
const SAMPLE_TEXT = "Hidden Text";
|
|
8958
|
-
var FontMetrics = class {
|
|
8959
|
-
constructor(document) {
|
|
8960
|
-
this._data = {};
|
|
8961
|
-
this._document = document;
|
|
8962
|
-
}
|
|
8963
|
-
parseMetrics(fontFamily, fontSize) {
|
|
8964
|
-
const container = this._document.createElement("div");
|
|
8965
|
-
const img = this._document.createElement("img");
|
|
8966
|
-
const span = this._document.createElement("span");
|
|
8967
|
-
const body = this._document.body;
|
|
8968
|
-
container.style.visibility = "hidden";
|
|
8969
|
-
container.style.fontFamily = fontFamily;
|
|
8970
|
-
container.style.fontSize = fontSize;
|
|
8971
|
-
container.style.margin = "0";
|
|
8972
|
-
container.style.padding = "0";
|
|
8973
|
-
container.style.whiteSpace = "nowrap";
|
|
8974
|
-
body.appendChild(container);
|
|
8975
|
-
img.src = SMALL_IMAGE;
|
|
8976
|
-
img.width = 1;
|
|
8977
|
-
img.height = 1;
|
|
8978
|
-
img.style.margin = "0";
|
|
8979
|
-
img.style.padding = "0";
|
|
8980
|
-
img.style.verticalAlign = "baseline";
|
|
8981
|
-
span.style.fontFamily = fontFamily;
|
|
8982
|
-
span.style.fontSize = fontSize;
|
|
8983
|
-
span.style.margin = "0";
|
|
8984
|
-
span.style.padding = "0";
|
|
8985
|
-
span.appendChild(this._document.createTextNode(SAMPLE_TEXT));
|
|
8986
|
-
container.appendChild(span);
|
|
8987
|
-
container.appendChild(img);
|
|
8988
|
-
const baseline = img.offsetTop - span.offsetTop + 2;
|
|
8989
|
-
container.removeChild(span);
|
|
8990
|
-
container.appendChild(this._document.createTextNode(SAMPLE_TEXT));
|
|
8991
|
-
container.style.lineHeight = "normal";
|
|
8992
|
-
img.style.verticalAlign = "super";
|
|
8993
|
-
const middle = img.offsetTop - container.offsetTop + 2;
|
|
8994
|
-
body.removeChild(container);
|
|
8995
|
-
return {
|
|
8996
|
-
baseline,
|
|
8997
|
-
middle
|
|
8998
|
-
};
|
|
8999
|
-
}
|
|
9000
|
-
getMetrics(fontFamily, fontSize) {
|
|
9001
|
-
const key = `${fontFamily} ${fontSize}`;
|
|
9002
|
-
if (typeof this._data[key] === "undefined") this._data[key] = this.parseMetrics(fontFamily, fontSize);
|
|
9003
|
-
return this._data[key];
|
|
9004
|
-
}
|
|
9005
|
-
};
|
|
9006
|
-
//#endregion
|
|
9007
8953
|
//#region src/render/canvas/text/text-decoration-renderer.ts
|
|
9008
8954
|
var TextDecorationRenderer = class {
|
|
9009
8955
|
constructor(ctx) {
|
|
@@ -9092,6 +9038,33 @@
|
|
|
9092
9038
|
}
|
|
9093
9039
|
};
|
|
9094
9040
|
//#endregion
|
|
9041
|
+
//#region src/render/canvas/font-utils.ts
|
|
9042
|
+
/**
|
|
9043
|
+
* Font measurement utility
|
|
9044
|
+
*
|
|
9045
|
+
* Provides Canvas API-based baseline measurement that works correctly with
|
|
9046
|
+
* webfonts (which may not be loaded in the original document) and system fonts.
|
|
9047
|
+
*
|
|
9048
|
+
* Fallback chain:
|
|
9049
|
+
* 1. fontBoundingBoxAscent — font-level metric (Chrome 99+, FF 116+, Safari 17.4+)
|
|
9050
|
+
* 2. actualBoundingBoxAscent — glyph-level metric (widely supported)
|
|
9051
|
+
* 3. fallback value — coarse CSS fallback
|
|
9052
|
+
*/
|
|
9053
|
+
const SAMPLE_TEXT = "Mg";
|
|
9054
|
+
/**
|
|
9055
|
+
* Measure the baseline ascent for the currently set font.
|
|
9056
|
+
*
|
|
9057
|
+
* @param ctx - Canvas 2D rendering context with ctx.font already set
|
|
9058
|
+
* @param fallback - Fallback value when no metrics are available (e.g. fontSize.number)
|
|
9059
|
+
* @returns The distance from the text baseline to the top of the bounding box
|
|
9060
|
+
*/
|
|
9061
|
+
const measureBaseline = (ctx, fallback) => {
|
|
9062
|
+
const tm = ctx.measureText(SAMPLE_TEXT);
|
|
9063
|
+
const fmAscent = tm.fontBoundingBoxAscent;
|
|
9064
|
+
const ascent = fmAscent !== void 0 && !Number.isNaN(fmAscent) ? fmAscent : tm.actualBoundingBoxAscent;
|
|
9065
|
+
return ascent !== void 0 && !Number.isNaN(ascent) ? ascent : fallback;
|
|
9066
|
+
};
|
|
9067
|
+
//#endregion
|
|
9095
9068
|
//#region src/render/canvas/text-renderer.ts
|
|
9096
9069
|
const iOSBrokenFonts = ["-apple-system", "system-ui"];
|
|
9097
9070
|
/**
|
|
@@ -9144,7 +9117,6 @@
|
|
|
9144
9117
|
constructor(deps) {
|
|
9145
9118
|
this.glyphWidthCache = null;
|
|
9146
9119
|
this.ctx = deps.ctx;
|
|
9147
|
-
this.fontMetrics = deps.fontMetrics;
|
|
9148
9120
|
this.options = deps.options;
|
|
9149
9121
|
this.decorationRenderer = new TextDecorationRenderer(deps.ctx);
|
|
9150
9122
|
}
|
|
@@ -9405,13 +9377,13 @@
|
|
|
9405
9377
|
}
|
|
9406
9378
|
async renderTextNode(text, styles, containerBounds) {
|
|
9407
9379
|
this.glyphWidthCache = null;
|
|
9408
|
-
const [fontString
|
|
9380
|
+
const [fontString] = this.createFontStyle(styles);
|
|
9409
9381
|
this.ctx.font = fontString;
|
|
9410
9382
|
this.ctx.direction = styles.direction === 1 ? "rtl" : "ltr";
|
|
9411
9383
|
this.ctx.textAlign = "left";
|
|
9412
9384
|
this.ctx.textBaseline = "alphabetic";
|
|
9413
9385
|
const paintOrder = styles.paintOrder;
|
|
9414
|
-
const
|
|
9386
|
+
const baseline = measureBaseline(this.ctx, styles.fontSize.number);
|
|
9415
9387
|
if (styles.webkitLineClamp > 0 && (styles.display & 2) !== 0 && styles.overflowY === 1 && text.textBounds.length > 0) {
|
|
9416
9388
|
if (this.renderLineClampedText(text, styles, paintOrder, baseline, containerBounds)) return;
|
|
9417
9389
|
}
|
|
@@ -10307,7 +10279,7 @@
|
|
|
10307
10279
|
/**
|
|
10308
10280
|
* Render form element content: checkbox, radio, text input.
|
|
10309
10281
|
*/
|
|
10310
|
-
function renderFormElements(ctx,
|
|
10282
|
+
function renderFormElements(ctx, textRenderer, pathFn, container, styles) {
|
|
10311
10283
|
if (container instanceof InputElementContainer) {
|
|
10312
10284
|
const size = Math.min(container.bounds.width, container.bounds.height);
|
|
10313
10285
|
if (container.type === "checkbox" && container.checked) {
|
|
@@ -10334,9 +10306,9 @@
|
|
|
10334
10306
|
}
|
|
10335
10307
|
}
|
|
10336
10308
|
if (isTextInputElement(container) && container.value.length) {
|
|
10337
|
-
const [font
|
|
10338
|
-
const { baseline } = fontMetrics.getMetrics(fontFamily, fontSize);
|
|
10309
|
+
const [font] = textRenderer.createFontStyle(styles);
|
|
10339
10310
|
ctx.font = font;
|
|
10311
|
+
const baseline = measureBaseline(ctx, getAbsoluteValue(styles.fontSize, 0));
|
|
10340
10312
|
ctx.fillStyle = container instanceof InputElementContainer && container.isPlaceholder ? asString(PLACEHOLDER_COLOR) : asString(styles.color);
|
|
10341
10313
|
ctx.textBaseline = "alphabetic";
|
|
10342
10314
|
ctx.textAlign = canvasTextAlign(container.styles.textAlign);
|
|
@@ -10434,7 +10406,6 @@
|
|
|
10434
10406
|
this.canvas.style.width = `${options.width}px`;
|
|
10435
10407
|
this.canvas.style.height = `${options.height}px`;
|
|
10436
10408
|
}
|
|
10437
|
-
this.fontMetrics = new FontMetrics(document);
|
|
10438
10409
|
this.ctx.scale(this.options.scale, this.options.scale);
|
|
10439
10410
|
this.ctx.translate(-options.x, -options.y);
|
|
10440
10411
|
this.ctx.textBaseline = "bottom";
|
|
@@ -10458,7 +10429,6 @@
|
|
|
10458
10429
|
this.effectsRenderer = new EffectsRenderer({ ctx: this.ctx }, { path: (paths) => this.path(paths) });
|
|
10459
10430
|
this.textRenderer = new TextRenderer({
|
|
10460
10431
|
ctx: this.ctx,
|
|
10461
|
-
fontMetrics: this.fontMetrics,
|
|
10462
10432
|
options: { scale: options.scale }
|
|
10463
10433
|
});
|
|
10464
10434
|
this.context.logger.debug(`Canvas renderer initialized (${options.width}x${options.height}) with scale ${options.scale}`);
|
|
@@ -10506,7 +10476,7 @@
|
|
|
10506
10476
|
width: this.options.width,
|
|
10507
10477
|
height: this.options.height
|
|
10508
10478
|
}, (ctx, opts) => new CanvasRenderer(ctx, opts), container, curves, styles, (c, cv, img) => this.renderReplacedElement(c, cv, img));
|
|
10509
|
-
renderFormElements(this.ctx, this.
|
|
10479
|
+
renderFormElements(this.ctx, this.textRenderer, this.path.bind(this), container, styles);
|
|
10510
10480
|
await renderListMarker(this.ctx, this.context, this.textRenderer, paint, container, styles);
|
|
10511
10481
|
}
|
|
10512
10482
|
async renderStackContent(stack) {
|