html2canvas-pro 2.3.6 → 2.3.8

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.
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * html2canvas-pro 2.3.6 <https://yorickshan.github.io/html2canvas-pro/>
2
+ * html2canvas-pro 2.3.8 <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
  */
@@ -5160,6 +5160,23 @@ const wordBreak = {
5160
5160
  }
5161
5161
  };
5162
5162
  //#endregion
5163
+ //#region src/css/property-descriptors/white-space.ts
5164
+ const whiteSpace = {
5165
+ name: "white-space",
5166
+ initialValue: "normal",
5167
+ prefix: false,
5168
+ type: 2,
5169
+ parse: (_context, value) => {
5170
+ switch (value) {
5171
+ case "pre": return "pre";
5172
+ case "nowrap": return "nowrap";
5173
+ case "pre-wrap": return "pre-wrap";
5174
+ case "pre-line": return "pre-line";
5175
+ default: return "normal";
5176
+ }
5177
+ }
5178
+ };
5179
+ //#endregion
5163
5180
  //#region src/css/property-descriptors/writing-mode.ts
5164
5181
  const isVerticalWritingMode = (writingMode) => writingMode !== 0;
5165
5182
  const isSidewaysWritingMode = (writingMode) => writingMode === 3 || writingMode === 4;
@@ -6600,6 +6617,11 @@ var CSSParsedDeclaration = class CSSParsedDeclaration {
6600
6617
  wordBreak,
6601
6618
  "wordBreak"
6602
6619
  ],
6620
+ [
6621
+ "whiteSpace",
6622
+ whiteSpace,
6623
+ "whiteSpace"
6624
+ ],
6603
6625
  [
6604
6626
  "writingMode",
6605
6627
  writingMode,
@@ -7445,7 +7467,12 @@ var ElementContainer = class {
7445
7467
  this.bounds = parseBounds(this.context, element);
7446
7468
  if (element.tagName === "FIELDSET") {
7447
7469
  const legend = element.querySelector(":scope > legend");
7448
- if (legend) this.legendBounds = parseBounds(this.context, legend);
7470
+ if (legend) {
7471
+ const legendBounds = parseBounds(this.context, legend);
7472
+ this.legendBounds = legendBounds;
7473
+ const borderBoxTop = legendBounds.top + legendBounds.height / 2 - this.styles.borderTopWidth / 2;
7474
+ this.bounds = new Bounds(this.bounds.left, borderBoxTop, this.bounds.width, this.bounds.height - (borderBoxTop - this.bounds.top));
7475
+ }
7449
7476
  }
7450
7477
  if (isDebugging(element, 4)) this.debugRender = true;
7451
7478
  }
@@ -10353,13 +10380,57 @@ function renderFormElements(ctx, textRenderer, pathFn, container, styles) {
10353
10380
  new Vector(bounds.left, bounds.top + bounds.height)
10354
10381
  ]);
10355
10382
  ctx.clip();
10356
- textRenderer.renderTextWithLetterSpacing(new TextBounds(container.value, textBounds), styles.letterSpacing, baseline, styles.writingMode);
10383
+ const lines = wrapTextToWidth(ctx, container.value, bounds.width, styles.whiteSpace === "pre" || styles.whiteSpace === "nowrap");
10384
+ const fontSizeValue = getAbsoluteValue(styles.fontSize, 0);
10385
+ const lineHeight = computeLineHeight(styles.lineHeight, fontSizeValue);
10386
+ lines.forEach((line, index) => {
10387
+ let lineX = textBounds.left;
10388
+ const lineWidth = ctx.measureText(line).width;
10389
+ switch (styles.textAlign) {
10390
+ case 1:
10391
+ lineX += (bounds.width - lineWidth) / 2;
10392
+ break;
10393
+ case 2:
10394
+ lineX += bounds.width - lineWidth;
10395
+ break;
10396
+ }
10397
+ const lineBounds = new Bounds(lineX, textBounds.top + index * lineHeight, 0, 0);
10398
+ textRenderer.renderTextWithLetterSpacing(new TextBounds(line, lineBounds), styles.letterSpacing, baseline, styles.writingMode);
10399
+ });
10357
10400
  ctx.restore();
10358
10401
  ctx.textBaseline = "alphabetic";
10359
10402
  ctx.textAlign = "left";
10360
10403
  }
10361
10404
  }
10362
10405
  /**
10406
+ * Split text into lines that fit the given pixel width, preserving hard line
10407
+ * breaks and (when wrapping is enabled) breaking at word boundaries — mirroring
10408
+ * how a <textarea> lays out its value.
10409
+ * @internal exported for testing
10410
+ */
10411
+ const wrapTextToWidth = (ctx, text, maxWidth, noWrap) => {
10412
+ const lines = [];
10413
+ const paragraphs = text.split("\n");
10414
+ for (const paragraph of paragraphs) {
10415
+ if (noWrap) {
10416
+ lines.push(paragraph);
10417
+ continue;
10418
+ }
10419
+ const words = paragraph.split(/(\s+)/);
10420
+ let line = "";
10421
+ for (const word of words) {
10422
+ const candidate = line + word;
10423
+ if (ctx.measureText(candidate).width <= maxWidth || line === "") line = candidate;
10424
+ else {
10425
+ lines.push(line);
10426
+ line = word;
10427
+ }
10428
+ }
10429
+ lines.push(line);
10430
+ }
10431
+ return lines;
10432
+ };
10433
+ /**
10363
10434
  * Render list-item marker (image or text).
10364
10435
  */
10365
10436
  async function renderListMarker(ctx, context, textRenderer, paint, container, styles) {
@@ -10957,7 +11028,8 @@ var Cache = class {
10957
11028
  const originChecker = this.context.originChecker;
10958
11029
  const defaultIsSameOrigin = (src) => originChecker.isSameOrigin(src);
10959
11030
  const isSameOrigin = typeof this._options.customIsSameOrigin === "function" ? await this._options.customIsSameOrigin(key, defaultIsSameOrigin) : defaultIsSameOrigin(key);
10960
- const useCORS = !isInlineImage(key) && this._options.useCORS === true && FEATURES.SUPPORT_CORS_IMAGES && !isSameOrigin;
11031
+ const canAttemptCors = !isSameOrigin && this._options.allowTaint === false && !isInlineImage(key) && !isBlobImage(key) && typeof this._options.proxy !== "string";
11032
+ const useCORS = !isInlineImage(key) && (this._options.useCORS === true || canAttemptCors) && FEATURES.SUPPORT_CORS_IMAGES && !isSameOrigin;
10961
11033
  const useProxy = !isInlineImage(key) && !isSameOrigin && !isBlobImage(key) && typeof this._options.proxy === "string" && FEATURES.SUPPORT_CORS_XHR && !useCORS;
10962
11034
  if (!isSameOrigin && this._options.allowTaint === false && !isInlineImage(key) && !isBlobImage(key) && !useProxy && !useCORS) return;
10963
11035
  let src = key;