html2canvas-pro 2.5.0 → 2.5.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.
@@ -5,6 +5,11 @@ export interface ResourceOptions {
5
5
  allowTaint: boolean;
6
6
  proxy?: string;
7
7
  customIsSameOrigin?: (this: void, src: string, oldFn: (src: string) => boolean) => boolean | Promise<boolean>;
8
+ /**
9
+ * LRU cap for normal-mode (immediate) loads. Default: 100.
10
+ * Suspended between startDefer() and preloadAll() so every image collected
11
+ * during a render stays available to the renderer, which never reloads.
12
+ */
8
13
  maxCacheSize?: number;
9
14
  }
10
15
  export declare class Cache {
@@ -17,6 +22,19 @@ export declare class Cache {
17
22
  private _deferMode;
18
23
  /** URLs collected during defer mode, pending batch preload. */
19
24
  private _collectedUrls;
25
+ /**
26
+ * Eviction is suspended between startDefer() and the end of preloadAll():
27
+ * the render pipeline loads every image it is going to paint inside that
28
+ * window, and match() never reloads, so an LRU eviction there would
29
+ * silently drop images from the output on pages with more unique images
30
+ * than maxSize.
31
+ *
32
+ * A counter (not a flag) keeps nested/overlapping defer windows — e.g.
33
+ * two renders sharing one cache via `config.cache` — suspended until the
34
+ * last one finishes preloading.
35
+ */
36
+ private _evictionSuspendCount;
37
+ private get _evictionEnabled();
20
38
  constructor(context: Context, _options: ResourceOptions);
21
39
  /**
22
40
  * Enter defer mode: subsequent addImage() calls only collect URLs.
@@ -3,9 +3,6 @@ export interface LoggerOptions {
3
3
  enabled: boolean;
4
4
  }
5
5
  export declare class Logger {
6
- static instances: {
7
- [key: string]: Logger;
8
- };
9
6
  private readonly id;
10
7
  private readonly enabled;
11
8
  private readonly start;
@@ -9,3 +9,9 @@ import { Context } from '../../../core/context';
9
9
  * may carry the from/at clauses; every following group is a color stop.
10
10
  */
11
11
  export declare const conicGradient: (context: Context, tokens: CSSValue[]) => CSSConicGradientImage;
12
+ /**
13
+ * repeating-conic-gradient shares the conic-gradient grammar exactly; only
14
+ * the image type differs, which switches the renderer to periodic stops
15
+ * stacked across the full sweep.
16
+ */
17
+ export declare const repeatingConicGradient: (context: Context, tokens: CSSValue[]) => CSSConicGradientImage;
@@ -8,13 +8,15 @@ export declare const enum CSSImageType {
8
8
  RADIAL_GRADIENT = 2,
9
9
  REPEATING_LINEAR_GRADIENT = 3,
10
10
  REPEATING_RADIAL_GRADIENT = 4,
11
- CONIC_GRADIENT = 5
11
+ CONIC_GRADIENT = 5,
12
+ REPEATING_CONIC_GRADIENT = 6
12
13
  }
13
14
  export declare const isLinearGradient: (background: ICSSImage) => background is CSSLinearGradientImage;
14
15
  export declare const isRadialGradient: (background: ICSSImage) => background is CSSRadialGradientImage;
15
16
  export declare const isRepeatingLinearGradient: (background: ICSSImage) => background is CSSLinearGradientImage;
16
17
  export declare const isRepeatingRadialGradient: (background: ICSSImage) => background is CSSRadialGradientImage;
17
18
  export declare const isConicGradient: (background: ICSSImage) => background is CSSConicGradientImage;
19
+ export declare const isRepeatingConicGradient: (background: ICSSImage) => background is CSSConicGradientImage;
18
20
  export interface UnprocessedGradientColorStop {
19
21
  color: Color;
20
22
  stop: LengthPercentage | null;
@@ -60,7 +62,7 @@ export interface CSSRadialGradientImage extends ICSSGradientImage {
60
62
  * `angle` is the `from` angle in radians, measured clockwise from 12 o'clock.
61
63
  */
62
64
  export interface CSSConicGradientImage extends ICSSGradientImage {
63
- type: CSSImageType.CONIC_GRADIENT;
65
+ type: CSSImageType.CONIC_GRADIENT | CSSImageType.REPEATING_CONIC_GRADIENT;
64
66
  angle: number;
65
67
  position: LengthPercentage[];
66
68
  }
@@ -3,7 +3,7 @@ import { Context } from '../../core/context';
3
3
  export declare const CHECKBOX = "checkbox";
4
4
  export declare const RADIO = "radio";
5
5
  export declare const PASSWORD = "password";
6
- export declare const INPUT_COLOR = 707406591;
6
+ export declare const INPUT_COLOR = 7733247;
7
7
  export declare const PLACEHOLDER_COLOR = 1970632191;
8
8
  export declare class InputElementContainer extends ElementContainer {
9
9
  readonly type: string;
@@ -85,6 +85,15 @@ export declare class BackgroundRenderer {
85
85
  * CSS `from <angle>`.
86
86
  */
87
87
  private renderConicGradient;
88
+ /**
89
+ * Render a repeating conic gradient background.
90
+ *
91
+ * Canvas conic gradient stops span the full 2π sweep as [0, 1], so the
92
+ * one-cycle stop list is stacked k·period + s for k = 0..cycles-1 over the
93
+ * whole sweep — the same periodic-stop stacking the repeating linear and
94
+ * radial renderers use along their gradient lines.
95
+ */
96
+ private renderRepeatingConicGradient;
88
97
  /**
89
98
  * Render a repeating pattern with offset
90
99
  *
@@ -81,6 +81,14 @@ export declare class CanvasRenderer {
81
81
  * offset outwards. Outlines paint atop content and do not affect layout.
82
82
  */
83
83
  private renderOutline;
84
+ /**
85
+ * Rasterise a gradient border-image-source across the border image area.
86
+ * CSS allows any <image> as the border-image source; gradients are painted
87
+ * over the whole border-image box and then sliced by the regular 9-slice
88
+ * pipeline, matching browser behaviour for `border-image: linear-gradient()`.
89
+ * Returns null when the gradient could not be painted.
90
+ */
91
+ private rasterizeGradientSource;
84
92
  /**
85
93
  * Filter the already-painted content beneath the element's border box and
86
94
  * paint the result back, approximating CSS backdrop-filter for the
@@ -16,6 +16,13 @@ import { Path } from '../path';
16
16
  */
17
17
  export interface EffectsRendererDependencies {
18
18
  ctx: CanvasRenderingContext2D;
19
+ /**
20
+ * Device-pixel ratio of the bound context. Canvas shadow metrics
21
+ * (offset/blur) live in device space, unaffected by the context
22
+ * transform, so drop-shadow() blur must be scaled like the offsets.
23
+ * Defaults to 1.
24
+ */
25
+ scale?: number;
19
26
  }
20
27
  /**
21
28
  * Path callback for clip effects
@@ -57,6 +64,7 @@ export interface EffectsPathCallback {
57
64
  export declare class EffectsRenderer {
58
65
  private readonly ctx;
59
66
  private readonly pathCallback;
67
+ private readonly scale;
60
68
  private readonly activeEffects;
61
69
  /** Whether a canvas state save was performed for the current batch. */
62
70
  private didSave;
@@ -9,8 +9,15 @@
9
9
  * Extracted from CanvasRenderer to keep paint orchestration separate from
10
10
  * this self-contained compositing algorithm.
11
11
  *
12
- * The offscreen canvas uses CSS-pixel dimensions (not device-pixel) because the
13
- * background renderer handles scaling internally via BackgroundRenderer options.
12
+ * The offscreen and mask canvases are backed at device-pixel resolution
13
+ * (bounds × scale) with their contexts scaled to CSS pixels, so the
14
+ * composite back onto the main canvas maps 1:1 onto the backing store and
15
+ * stays sharp at devicePixelRatio > 1.
16
+ *
17
+ * Matching browser paint order for clipped text:
18
+ * - text shadows render *beneath* the clipped background (silhouettes in
19
+ * the shadow colour), they are not part of the clip region;
20
+ * - -webkit-text-stroke is part of the clip region (fill ∪ stroke band).
14
21
  */
15
22
  import { ElementPaint } from '../stacking-context';
16
23
  import { CSSParsedDeclaration } from '../../css';
@@ -19,18 +26,31 @@ export interface TextClipRendererDependencies {
19
26
  /** Main canvas context the clipped background is composited onto. */
20
27
  ctx: CanvasRenderingContext2D;
21
28
  context: Context;
29
+ /** Device-pixel ratio shared with the main renderer. */
30
+ scale: number;
22
31
  /** Font builder shared with the text renderer so both use identical fonts. */
23
32
  createFontStyle: (styles: CSSParsedDeclaration) => string[];
24
33
  }
25
34
  export declare class TextClipRenderer {
26
35
  private readonly ctx;
27
36
  private readonly context;
37
+ private readonly scale;
28
38
  private readonly createFontStyle;
29
39
  constructor(deps: TextClipRendererDependencies);
30
40
  render(paint: ElementPaint): Promise<void>;
41
+ private createLayer;
42
+ private createGlyphLayer;
43
+ /**
44
+ * Draw one text bound onto a glyph layer, splitting into per-glyph draws
45
+ * when letter-spacing is in effect so the layout matches the main text
46
+ * renderer. Vertical writing modes fall back to a single draw call.
47
+ */
48
+ private drawGlyphs;
31
49
  /**
32
- * Render text glyphs one-by-one as a mask, applying letter-spacing between characters.
33
- * This ensures the mask matches how the text renderer lays out the characters.
50
+ * Paint the text-shadow silhouettes for every glyph, one canvas per
51
+ * shadow, returned front-to-back (the last shadow sits deepest). Returns
52
+ * null when the element has no text shadows.
34
53
  */
35
- private renderTextMaskWithLetterSpacing;
54
+ private renderShadowSilhouettes;
55
+ private getTextStrokeLineJoin;
36
56
  }
package/package.json CHANGED
@@ -19,7 +19,7 @@
19
19
  "default": "./dist/html2canvas-pro.esm.js"
20
20
  }
21
21
  },
22
- "version": "2.5.0",
22
+ "version": "2.5.1",
23
23
  "author": {
24
24
  "name": "yorickshan",
25
25
  "email": "yorickshan@gmail.com",
@@ -31,7 +31,7 @@
31
31
  "screenshot"
32
32
  ],
33
33
  "engines": {
34
- "node": ">=16.0.0"
34
+ "node": ">=24.0.0"
35
35
  },
36
36
  "homepage": "https://yorickshan.github.io/html2canvas-pro/",
37
37
  "repository": {
@@ -117,7 +117,7 @@
117
117
  "build:create-reftest-list": "tsx scripts/create-reftest-list.ts tests/reftests/ignore.txt build/reftests.js",
118
118
  "release": "sh scripts/version-upgrade.sh",
119
119
  "format": "prettier --write \"{src,tests,scripts}/**/*.ts\"",
120
- "lint": "eslint src/**/*.ts --max-warnings 0",
120
+ "lint": "eslint \"src/**/*.ts\" \"tests/**/*.ts\" \"scripts/**/*.ts\" \"scripts/**/*.mjs\" --max-warnings 0",
121
121
  "test": "pnpm lint && pnpm unittest && pnpm karma",
122
122
  "unittest": "vitest run",
123
123
  "unittest:coverage": "vitest run --coverage",