html2canvas-pro 2.3.7 → 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.7 <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
  */
@@ -5167,6 +5167,23 @@
5167
5167
  }
5168
5168
  };
5169
5169
  //#endregion
5170
+ //#region src/css/property-descriptors/white-space.ts
5171
+ const whiteSpace = {
5172
+ name: "white-space",
5173
+ initialValue: "normal",
5174
+ prefix: false,
5175
+ type: 2,
5176
+ parse: (_context, value) => {
5177
+ switch (value) {
5178
+ case "pre": return "pre";
5179
+ case "nowrap": return "nowrap";
5180
+ case "pre-wrap": return "pre-wrap";
5181
+ case "pre-line": return "pre-line";
5182
+ default: return "normal";
5183
+ }
5184
+ }
5185
+ };
5186
+ //#endregion
5170
5187
  //#region src/css/property-descriptors/writing-mode.ts
5171
5188
  const isVerticalWritingMode = (writingMode) => writingMode !== 0;
5172
5189
  const isSidewaysWritingMode = (writingMode) => writingMode === 3 || writingMode === 4;
@@ -6607,6 +6624,11 @@
6607
6624
  wordBreak,
6608
6625
  "wordBreak"
6609
6626
  ],
6627
+ [
6628
+ "whiteSpace",
6629
+ whiteSpace,
6630
+ "whiteSpace"
6631
+ ],
6610
6632
  [
6611
6633
  "writingMode",
6612
6634
  writingMode,
@@ -10365,13 +10387,57 @@
10365
10387
  new Vector(bounds.left, bounds.top + bounds.height)
10366
10388
  ]);
10367
10389
  ctx.clip();
10368
- textRenderer.renderTextWithLetterSpacing(new TextBounds(container.value, textBounds), styles.letterSpacing, baseline, styles.writingMode);
10390
+ const lines = wrapTextToWidth(ctx, container.value, bounds.width, styles.whiteSpace === "pre" || styles.whiteSpace === "nowrap");
10391
+ const fontSizeValue = getAbsoluteValue(styles.fontSize, 0);
10392
+ const lineHeight = computeLineHeight(styles.lineHeight, fontSizeValue);
10393
+ lines.forEach((line, index) => {
10394
+ let lineX = textBounds.left;
10395
+ const lineWidth = ctx.measureText(line).width;
10396
+ switch (styles.textAlign) {
10397
+ case 1:
10398
+ lineX += (bounds.width - lineWidth) / 2;
10399
+ break;
10400
+ case 2:
10401
+ lineX += bounds.width - lineWidth;
10402
+ break;
10403
+ }
10404
+ const lineBounds = new Bounds(lineX, textBounds.top + index * lineHeight, 0, 0);
10405
+ textRenderer.renderTextWithLetterSpacing(new TextBounds(line, lineBounds), styles.letterSpacing, baseline, styles.writingMode);
10406
+ });
10369
10407
  ctx.restore();
10370
10408
  ctx.textBaseline = "alphabetic";
10371
10409
  ctx.textAlign = "left";
10372
10410
  }
10373
10411
  }
10374
10412
  /**
10413
+ * Split text into lines that fit the given pixel width, preserving hard line
10414
+ * breaks and (when wrapping is enabled) breaking at word boundaries — mirroring
10415
+ * how a <textarea> lays out its value.
10416
+ * @internal exported for testing
10417
+ */
10418
+ const wrapTextToWidth = (ctx, text, maxWidth, noWrap) => {
10419
+ const lines = [];
10420
+ const paragraphs = text.split("\n");
10421
+ for (const paragraph of paragraphs) {
10422
+ if (noWrap) {
10423
+ lines.push(paragraph);
10424
+ continue;
10425
+ }
10426
+ const words = paragraph.split(/(\s+)/);
10427
+ let line = "";
10428
+ for (const word of words) {
10429
+ const candidate = line + word;
10430
+ if (ctx.measureText(candidate).width <= maxWidth || line === "") line = candidate;
10431
+ else {
10432
+ lines.push(line);
10433
+ line = word;
10434
+ }
10435
+ }
10436
+ lines.push(line);
10437
+ }
10438
+ return lines;
10439
+ };
10440
+ /**
10375
10441
  * Render list-item marker (image or text).
10376
10442
  */
10377
10443
  async function renderListMarker(ctx, context, textRenderer, paint, container, styles) {
@@ -10969,7 +11035,8 @@
10969
11035
  const originChecker = this.context.originChecker;
10970
11036
  const defaultIsSameOrigin = (src) => originChecker.isSameOrigin(src);
10971
11037
  const isSameOrigin = typeof this._options.customIsSameOrigin === "function" ? await this._options.customIsSameOrigin(key, defaultIsSameOrigin) : defaultIsSameOrigin(key);
10972
- const useCORS = !isInlineImage(key) && this._options.useCORS === true && FEATURES.SUPPORT_CORS_IMAGES && !isSameOrigin;
11038
+ const canAttemptCors = !isSameOrigin && this._options.allowTaint === false && !isInlineImage(key) && !isBlobImage(key) && typeof this._options.proxy !== "string";
11039
+ const useCORS = !isInlineImage(key) && (this._options.useCORS === true || canAttemptCors) && FEATURES.SUPPORT_CORS_IMAGES && !isSameOrigin;
10973
11040
  const useProxy = !isInlineImage(key) && !isSameOrigin && !isBlobImage(key) && typeof this._options.proxy === "string" && FEATURES.SUPPORT_CORS_XHR && !useCORS;
10974
11041
  if (!isSameOrigin && this._options.allowTaint === false && !isInlineImage(key) && !isBlobImage(key) && !useProxy && !useCORS) return;
10975
11042
  let src = key;