html2canvas-pro 2.6.0 → 2.6.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.
@@ -1,9 +1,9 @@
1
1
  /*!
2
- * html2canvas-pro 2.6.0 <https://yorickshan.github.io/html2canvas-pro/>
2
+ * html2canvas-pro 2.6.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
  */
6
- //#region src/config.ts
6
+ // src/config.ts
7
7
  /**
8
8
  * Html2Canvas Configuration
9
9
  *
@@ -46,8 +46,7 @@ var Html2CanvasConfig = class Html2CanvasConfig {
46
46
  });
47
47
  }
48
48
  };
49
- //#endregion
50
- //#region src/core/validator.ts
49
+ // src/core/validator.ts
51
50
  /**
52
51
  * Input Validator
53
52
  *
@@ -435,8 +434,7 @@ function createDefaultValidator(config = {}) {
435
434
  ...config
436
435
  });
437
436
  }
438
- //#endregion
439
- //#region src/core/performance-monitor.ts
437
+ // src/core/performance-monitor.ts
440
438
  /**
441
439
  * Performance Monitor
442
440
  *
@@ -445,7 +443,8 @@ function createDefaultValidator(config = {}) {
445
443
  *
446
444
  * Usage:
447
445
  * ```typescript
448
- * const monitor = new PerformanceMonitor(context);
446
+ * // Standalone (logs disabled) or with the render pipeline's context.
447
+ * const monitor = new PerformanceMonitor(null);
449
448
  *
450
449
  * monitor.start('clone');
451
450
  * await cloneDocument();
@@ -455,13 +454,13 @@ function createDefaultValidator(config = {}) {
455
454
  * ```
456
455
  */
457
456
  var PerformanceMonitor = class {
458
- context;
457
+ logger;
459
458
  activeMetrics = /* @__PURE__ */ new Map();
460
459
  completedMetrics = [];
461
460
  enabled;
462
461
  getTime;
463
- constructor(context, enabled = true) {
464
- this.context = context;
462
+ constructor(logger, enabled = true) {
463
+ this.logger = logger;
465
464
  this.enabled = enabled;
466
465
  this.getTime = typeof performance !== "undefined" && typeof performance.now === "function" ? () => performance.now() : () => Date.now();
467
466
  }
@@ -473,7 +472,7 @@ var PerformanceMonitor = class {
473
472
  */
474
473
  start(name, metadata) {
475
474
  if (!this.enabled) return;
476
- if (this.activeMetrics.has(name)) this.context?.logger.warn(`Performance metric '${name}' already started. Overwriting.`);
475
+ if (this.activeMetrics.has(name)) this.logger?.warn(`Performance metric '${name}' already started. Overwriting.`);
477
476
  this.activeMetrics.set(name, {
478
477
  name,
479
478
  startTime: this.getTime(),
@@ -490,14 +489,14 @@ var PerformanceMonitor = class {
490
489
  if (!this.enabled) return;
491
490
  const metric = this.activeMetrics.get(name);
492
491
  if (!metric) {
493
- this.context?.logger.warn(`Performance metric '${name}' not found. Was start() called?`);
492
+ this.logger?.warn(`Performance metric '${name}' not found. Was start() called?`);
494
493
  return;
495
494
  }
496
495
  metric.endTime = this.getTime();
497
496
  metric.duration = metric.endTime - metric.startTime;
498
497
  this.completedMetrics.push(metric);
499
498
  this.activeMetrics.delete(name);
500
- this.context?.logger.debug(`⏱️ ${name}: ${metric.duration.toFixed(2)}ms`, metric.metadata);
499
+ this.logger?.debug(`⏱️ ${name}: ${metric.duration.toFixed(2)}ms`, metric.metadata);
501
500
  return metric;
502
501
  }
503
502
  /**
@@ -577,11 +576,12 @@ var PerformanceMonitor = class {
577
576
  * Log performance summary to console
578
577
  */
579
578
  logSummary() {
580
- if (!this.enabled || this.completedMetrics.length === 0 || !this.context) return;
579
+ if (!this.enabled || this.completedMetrics.length === 0 || !this.logger) return;
580
+ const logger = this.logger;
581
581
  const summary = this.getSummary();
582
- this.context.logger.info(`\n📊 Performance Summary (Total: ${summary.totalDuration.toFixed(2)}ms):`);
582
+ logger.info(`\n📊 Performance Summary (Total: ${summary.totalDuration.toFixed(2)}ms):`);
583
583
  summary.breakdown.sort((a, b) => b.duration - a.duration).forEach((item) => {
584
- this.context.logger.info(` ${item.name.padEnd(20)} ${item.duration.toFixed(2).padStart(8)}ms ${item.percentage.padStart(6)}`);
584
+ logger.info(` ${item.name.padEnd(20)} ${item.duration.toFixed(2).padStart(8)}ms ${item.percentage.padStart(6)}`);
585
585
  });
586
586
  }
587
587
  /**
@@ -605,8 +605,7 @@ var PerformanceMonitor = class {
605
605
  return Array.from(this.activeMetrics.keys());
606
606
  }
607
607
  };
608
- //#endregion
609
- //#region src/css/layout/bounds.ts
608
+ // src/css/layout/bounds.ts
610
609
  var Bounds = class Bounds {
611
610
  left;
612
611
  top;
@@ -642,8 +641,7 @@ const parseDocumentSize = (document) => {
642
641
  if (!body || !documentElement) throw new Error(`Unable to get document size`);
643
642
  return new Bounds(0, 0, Math.max(Math.max(body.scrollWidth, documentElement.scrollWidth), Math.max(body.offsetWidth, documentElement.offsetWidth), Math.max(body.clientWidth, documentElement.clientWidth)), Math.max(Math.max(body.scrollHeight, documentElement.scrollHeight), Math.max(body.offsetHeight, documentElement.offsetHeight), Math.max(body.clientHeight, documentElement.clientHeight)));
644
643
  };
645
- //#endregion
646
- //#region src/core/util.ts
644
+ // src/core/util.ts
647
645
  /**
648
646
  * Indexed access where the shape/arity is guaranteed by construction (the CSS
649
647
  * grammar or a preceding length check). Throws on the impossible case instead
@@ -721,8 +719,7 @@ const stringToNumber = (codePoints) => {
721
719
  const exp = exponent.length ? parseInt(String.fromCodePoint(...exponent), 10) : 0;
722
720
  return sign * (int + frac * Math.pow(10, -fracd)) * Math.pow(10, expsign * exp);
723
721
  };
724
- //#endregion
725
- //#region src/css/syntax/token-singletons.ts
722
+ // src/css/syntax/token-singletons.ts
726
723
  const LEFT_PARENTHESIS_TOKEN = { type: 2 };
727
724
  const RIGHT_PARENTHESIS_TOKEN = { type: 3 };
728
725
  const COMMA_TOKEN = { type: 4 };
@@ -744,8 +741,7 @@ const LEFT_SQUARE_BRACKET_TOKEN = { type: 28 };
744
741
  const RIGHT_SQUARE_BRACKET_TOKEN = { type: 29 };
745
742
  const WHITESPACE_TOKEN = { type: 31 };
746
743
  const EOF_TOKEN = { type: 32 };
747
- //#endregion
748
- //#region src/css/syntax/tokenizer.ts
744
+ // src/css/syntax/tokenizer.ts
749
745
  var Tokenizer = class Tokenizer {
750
746
  static _pool = [];
751
747
  static MAX_POOL_SIZE = 40;
@@ -1201,8 +1197,7 @@ var Tokenizer = class Tokenizer {
1201
1197
  }
1202
1198
  }
1203
1199
  };
1204
- //#endregion
1205
- //#region src/css/syntax/parser.ts
1200
+ // src/css/syntax/parser.ts
1206
1201
  var Parser = class Parser {
1207
1202
  _tokens;
1208
1203
  constructor(tokens) {
@@ -1311,8 +1306,7 @@ const isEndingTokenFor = (token, type) => {
1311
1306
  if (type === 28 && token.type === 29) return true;
1312
1307
  return type === 2 && token.type === 3;
1313
1308
  };
1314
- //#endregion
1315
- //#region src/css/types/safe-eval.ts
1309
+ // src/css/types/safe-eval.ts
1316
1310
  /**
1317
1311
  * Safe arithmetic expression evaluator — replaces `new Function()`.
1318
1312
  *
@@ -1370,8 +1364,7 @@ const safeEvalArithmetic = (expr) => {
1370
1364
  }
1371
1365
  return stack.length === 1 ? stack[0] ?? NaN : NaN;
1372
1366
  };
1373
- //#endregion
1374
- //#region src/css/types/color-math.ts
1367
+ // src/css/types/color-math.ts
1375
1368
  /**
1376
1369
  * Color mathematics utilities
1377
1370
  * Extracted to break circular dependency between srgb.ts and color-utilities.ts
@@ -1392,8 +1385,7 @@ const multiplyMatrices = (A, B) => {
1392
1385
  A[6] * B[0] + A[7] * B[1] + A[8] * B[2]
1393
1386
  ];
1394
1387
  };
1395
- //#endregion
1396
- //#region src/css/types/color-spaces/srgb.ts
1388
+ // src/css/types/color-spaces/srgb.ts
1397
1389
  /**
1398
1390
  * SRGB related functions
1399
1391
  */
@@ -1502,11 +1494,9 @@ const srgbLinearFromXYZ = (args) => {
1502
1494
  args[3]
1503
1495
  ];
1504
1496
  };
1505
- //#endregion
1506
- //#region src/css/types/length.ts
1497
+ // src/css/types/length.ts
1507
1498
  const isLength = (token) => token.type === 17 || token.type === 15;
1508
- //#endregion
1509
- //#region src/css/types/length-percentage.ts
1499
+ // src/css/types/length-percentage.ts
1510
1500
  const isLengthPercentage = (token) => token.type === 16 || isLength(token) || isCalcWithPercentage(token);
1511
1501
  /**
1512
1502
  * Check if a token is a CalcWithPercentage deferred token.
@@ -1630,8 +1620,7 @@ const getAbsoluteValue = (token, parent) => {
1630
1620
  }
1631
1621
  return token.number;
1632
1622
  };
1633
- //#endregion
1634
- //#region src/css/types/angle.ts
1623
+ // src/css/types/angle.ts
1635
1624
  const DEG = "deg";
1636
1625
  const GRAD = "grad";
1637
1626
  const RAD = "rad";
@@ -1684,8 +1673,7 @@ const parseNamedSide = (tokens) => {
1684
1673
  return 0;
1685
1674
  };
1686
1675
  const deg = (deg) => Math.PI * deg / 180;
1687
- //#endregion
1688
- //#region src/css/types/color-utilities.ts
1676
+ // src/css/types/color-utilities.ts
1689
1677
  const isTransparent = (color) => (255 & color) === 0;
1690
1678
  const asString = (color) => {
1691
1679
  const alpha = 255 & color;
@@ -2140,8 +2128,7 @@ const convertXyz50 = (args) => {
2140
2128
  args[3]
2141
2129
  ]);
2142
2130
  };
2143
- //#endregion
2144
- //#region src/css/types/color-spaces/p3.ts
2131
+ // src/css/types/color-spaces/p3.ts
2145
2132
  /**
2146
2133
  * Display-P3 related functions
2147
2134
  */
@@ -2259,8 +2246,7 @@ const convertP3 = (args) => {
2259
2246
  args[3]
2260
2247
  ]);
2261
2248
  };
2262
- //#endregion
2263
- //#region src/css/types/color-spaces/a98.ts
2249
+ // src/css/types/color-spaces/a98.ts
2264
2250
  /**
2265
2251
  * A98-RGB related functions
2266
2252
  */
@@ -2366,8 +2352,7 @@ const convertA98rgb = (args) => {
2366
2352
  args[3]
2367
2353
  ]);
2368
2354
  };
2369
- //#endregion
2370
- //#region src/css/types/color-spaces/pro-photo.ts
2355
+ // src/css/types/color-spaces/pro-photo.ts
2371
2356
  /**
2372
2357
  * Pro Photo related functions
2373
2358
  */
@@ -2492,8 +2477,7 @@ const convertProPhoto = (args) => {
2492
2477
  args[3]
2493
2478
  ]);
2494
2479
  };
2495
- //#endregion
2496
- //#region src/css/types/color-spaces/rec2020.ts
2480
+ // src/css/types/color-spaces/rec2020.ts
2497
2481
  /**
2498
2482
  * REC2020 related functions
2499
2483
  */
@@ -2614,8 +2598,7 @@ const convertRec2020 = (args) => {
2614
2598
  args[3]
2615
2599
  ]);
2616
2600
  };
2617
- //#endregion
2618
- //#region src/css/types/functions/color-mix.ts
2601
+ // src/css/types/functions/color-mix.ts
2619
2602
  const HUE_DEG_INDEX = {
2620
2603
  lch: 2,
2621
2604
  oklch: 2,
@@ -3001,8 +2984,7 @@ const colorMix = (context, args) => {
3001
2984
  return 0;
3002
2985
  }
3003
2986
  };
3004
- //#endregion
3005
- //#region src/css/types/color.ts
2987
+ // src/css/types/color.ts
3006
2988
  const color$1 = {
3007
2989
  name: "color",
3008
2990
  parse: (context, value) => {
@@ -3406,8 +3388,7 @@ const COLORS = {
3406
3388
  YELLOW: 4294902015,
3407
3389
  YELLOWGREEN: 2597139199
3408
3390
  };
3409
- //#endregion
3410
- //#region src/dom/node-type-guards.ts
3391
+ // src/dom/node-type-guards.ts
3411
3392
  /**
3412
3393
  * DOM Node Type Guards
3413
3394
  *
@@ -3463,8 +3444,7 @@ const VOID_OR_REPLACED_TAGS = /* @__PURE__ */ new Set([
3463
3444
  * SVG elements also do not support pseudo-elements.
3464
3445
  */
3465
3446
  const canHavePseudoElements = (element) => !isSVGElementNode(element) && !VOID_OR_REPLACED_TAGS.has(element.tagName);
3466
- //#endregion
3467
- //#region src/css/property-descriptors/list-style-type.ts
3447
+ // src/css/property-descriptors/list-style-type.ts
3468
3448
  const listStyleType = {
3469
3449
  name: "list-style-type",
3470
3450
  initialValue: "none",
@@ -3529,11 +3509,9 @@ const listStyleType = {
3529
3509
  }
3530
3510
  }
3531
3511
  };
3532
- //#endregion
3533
- //#region src/core/bitwise.ts
3512
+ // src/core/bitwise.ts
3534
3513
  const contains = (bit, value) => (bit & value) !== 0;
3535
- //#endregion
3536
- //#region src/css/types/functions/counter.ts
3514
+ // src/css/types/functions/counter.ts
3537
3515
  var CounterState = class {
3538
3516
  counters = {};
3539
3517
  getCounterValue(name) {
@@ -3949,8 +3927,7 @@ const createCounterText = (value, type, appendSuffix) => {
3949
3927
  default: return createCounterStyleFromRange(value, 48, 57, true, defaultSuffix);
3950
3928
  }
3951
3929
  };
3952
- //#endregion
3953
- //#region src/css/property-descriptors/display.ts
3930
+ // src/css/property-descriptors/display.ts
3954
3931
  const display = {
3955
3932
  name: "display",
3956
3933
  initialValue: "inline-block",
@@ -3999,8 +3976,7 @@ const parseDisplayValue$1 = (display) => {
3999
3976
  }
4000
3977
  return 0;
4001
3978
  };
4002
- //#endregion
4003
- //#region src/css/property-descriptors/float.ts
3979
+ // src/css/property-descriptors/float.ts
4004
3980
  const float = {
4005
3981
  name: "float",
4006
3982
  initialValue: "none",
@@ -4016,8 +3992,7 @@ const float = {
4016
3992
  return 0;
4017
3993
  }
4018
3994
  };
4019
- //#endregion
4020
- //#region src/css/property-descriptors/overflow.ts
3995
+ // src/css/property-descriptors/overflow.ts
4021
3996
  const overflow = {
4022
3997
  name: "overflow",
4023
3998
  initialValue: "visible",
@@ -4035,8 +4010,7 @@ const overflow = {
4035
4010
  });
4036
4011
  }
4037
4012
  };
4038
- //#endregion
4039
- //#region src/css/property-descriptors/text-decoration-color.ts
4013
+ // src/css/property-descriptors/text-decoration-color.ts
4040
4014
  const textDecorationColor = {
4041
4015
  name: `text-decoration-color`,
4042
4016
  initialValue: "transparent",
@@ -4044,8 +4018,7 @@ const textDecorationColor = {
4044
4018
  type: 3,
4045
4019
  format: "color"
4046
4020
  };
4047
- //#endregion
4048
- //#region src/css/property-descriptors/text-decoration-line.ts
4021
+ // src/css/property-descriptors/text-decoration-line.ts
4049
4022
  const textDecorationLine = {
4050
4023
  name: "text-decoration-line",
4051
4024
  initialValue: "none",
@@ -4063,8 +4036,7 @@ const textDecorationLine = {
4063
4036
  }).filter((line) => line !== 0);
4064
4037
  }
4065
4038
  };
4066
- //#endregion
4067
- //#region src/css/property-descriptors/content.ts
4039
+ // src/css/property-descriptors/content.ts
4068
4040
  const content = {
4069
4041
  name: "content",
4070
4042
  initialValue: "none",
@@ -4077,8 +4049,7 @@ const content = {
4077
4049
  return tokens;
4078
4050
  }
4079
4051
  };
4080
- //#endregion
4081
- //#region src/css/property-descriptors/quotes.ts
4052
+ // src/css/property-descriptors/quotes.ts
4082
4053
  const quotes = {
4083
4054
  name: "quotes",
4084
4055
  initialValue: "none",
@@ -4108,8 +4079,7 @@ const getQuote = (quotes, depth, open) => {
4108
4079
  if (!quote) return "";
4109
4080
  return open ? quote.open : quote.close;
4110
4081
  };
4111
- //#endregion
4112
- //#region src/css/property-descriptors/counter-increment.ts
4082
+ // src/css/property-descriptors/counter-increment.ts
4113
4083
  /** Shared counter-ID parsing: returns next number or a fallback default. */
4114
4084
  const parseCounterValue = (tokens, defaultNumber) => {
4115
4085
  const entries = [];
@@ -4139,8 +4109,7 @@ const counterIncrement = {
4139
4109
  }));
4140
4110
  }
4141
4111
  };
4142
- //#endregion
4143
- //#region src/css/property-descriptors/counter-reset.ts
4112
+ // src/css/property-descriptors/counter-reset.ts
4144
4113
  const counterReset = {
4145
4114
  name: "counter-reset",
4146
4115
  initialValue: "none",
@@ -4154,8 +4123,7 @@ const counterReset = {
4154
4123
  }));
4155
4124
  }
4156
4125
  };
4157
- //#endregion
4158
- //#region src/css/property-descriptors/background-clip.ts
4126
+ // src/css/property-descriptors/background-clip.ts
4159
4127
  const backgroundClip = {
4160
4128
  name: "background-clip",
4161
4129
  initialValue: "border-box",
@@ -4172,8 +4140,7 @@ const backgroundClip = {
4172
4140
  });
4173
4141
  }
4174
4142
  };
4175
- //#endregion
4176
- //#region src/css/property-descriptors/background-color.ts
4143
+ // src/css/property-descriptors/background-color.ts
4177
4144
  const backgroundColor = {
4178
4145
  name: `background-color`,
4179
4146
  initialValue: "transparent",
@@ -4181,8 +4148,7 @@ const backgroundColor = {
4181
4148
  type: 3,
4182
4149
  format: "color"
4183
4150
  };
4184
- //#endregion
4185
- //#region src/css/types/functions/gradient.ts
4151
+ // src/css/types/functions/gradient.ts
4186
4152
  const parseColorStop = (context, args) => {
4187
4153
  const color = color$1.parse(context, at(args, 0));
4188
4154
  const stop = args[1];
@@ -4318,8 +4284,7 @@ const calculateRadius = (gradient, x, y, width, height) => {
4318
4284
  }
4319
4285
  return [rx, ry];
4320
4286
  };
4321
- //#endregion
4322
- //#region src/css/types/functions/linear-gradient.ts
4287
+ // src/css/types/functions/linear-gradient.ts
4323
4288
  const linearGradient = (context, tokens) => {
4324
4289
  let angle$2 = deg(180);
4325
4290
  const stops = [];
@@ -4343,8 +4308,7 @@ const linearGradient = (context, tokens) => {
4343
4308
  type: 1
4344
4309
  };
4345
4310
  };
4346
- //#endregion
4347
- //#region src/css/types/functions/-prefix-linear-gradient.ts
4311
+ // src/css/types/functions/-prefix-linear-gradient.ts
4348
4312
  const prefixLinearGradient = (context, tokens) => {
4349
4313
  let angle$1 = deg(180);
4350
4314
  const stops = [];
@@ -4373,8 +4337,7 @@ const prefixLinearGradient = (context, tokens) => {
4373
4337
  type: 1
4374
4338
  };
4375
4339
  };
4376
- //#endregion
4377
- //#region src/css/types/functions/-webkit-gradient.ts
4340
+ // src/css/types/functions/-webkit-gradient.ts
4378
4341
  const webkitGradient = (context, tokens) => {
4379
4342
  const angle = deg(180);
4380
4343
  const stops = [];
@@ -4436,8 +4399,7 @@ const webkitGradient = (context, tokens) => {
4436
4399
  type
4437
4400
  };
4438
4401
  };
4439
- //#endregion
4440
- //#region src/css/types/functions/radial-gradient.ts
4402
+ // src/css/types/functions/radial-gradient.ts
4441
4403
  const CLOSEST_SIDE = "closest-side";
4442
4404
  const FARTHEST_SIDE = "farthest-side";
4443
4405
  const CLOSEST_CORNER = "closest-corner";
@@ -4517,8 +4479,7 @@ const radialGradient = (context, tokens) => {
4517
4479
  type: 2
4518
4480
  };
4519
4481
  };
4520
- //#endregion
4521
- //#region src/css/types/functions/-prefix-radial-gradient.ts
4482
+ // src/css/types/functions/-prefix-radial-gradient.ts
4522
4483
  const prefixRadialGradient = (context, tokens) => {
4523
4484
  let shape = 1;
4524
4485
  let size = 3;
@@ -4589,16 +4550,14 @@ const prefixRadialGradient = (context, tokens) => {
4589
4550
  type: 2
4590
4551
  };
4591
4552
  };
4592
- //#endregion
4593
- //#region src/css/types/functions/repeating-linear-gradient.ts
4553
+ // src/css/types/functions/repeating-linear-gradient.ts
4594
4554
  const repeatingLinearGradient = (context, tokens) => {
4595
4555
  return {
4596
4556
  ...linearGradient(context, tokens),
4597
4557
  type: 3
4598
4558
  };
4599
4559
  };
4600
- //#endregion
4601
- //#region src/css/types/functions/repeating-radial-gradient.ts
4560
+ // src/css/types/functions/repeating-radial-gradient.ts
4602
4561
  /**
4603
4562
  * repeating-radial-gradient shares the radial-gradient grammar exactly; only
4604
4563
  * the image type differs, which switches the renderer to periodic stops.
@@ -4609,8 +4568,7 @@ const repeatingRadialGradient = (context, tokens) => {
4609
4568
  type: 4
4610
4569
  };
4611
4570
  };
4612
- //#endregion
4613
- //#region src/css/types/functions/conic-gradient.ts
4571
+ // src/css/types/functions/conic-gradient.ts
4614
4572
  /**
4615
4573
  * conic-gradient( [ from <angle> ]? [ at <position> ]?, <color-stop-list> )
4616
4574
  *
@@ -4680,8 +4638,7 @@ const repeatingConicGradient = (context, tokens) => {
4680
4638
  type: 6
4681
4639
  };
4682
4640
  };
4683
- //#endregion
4684
- //#region src/css/types/functions/image-set.ts
4641
+ // src/css/types/functions/image-set.ts
4685
4642
  const parseResolution = (token) => {
4686
4643
  if (!token) return 1;
4687
4644
  if (isDimensionToken(token)) {
@@ -4715,8 +4672,7 @@ const imageSet = (context, tokens) => {
4715
4672
  const chosen = at(satisfying.length > 0 ? satisfying : candidates.slice().sort((a, b) => b.resolution - a.resolution), 0);
4716
4673
  return image.parse(context, chosen.imageToken);
4717
4674
  };
4718
- //#endregion
4719
- //#region src/css/types/image.ts
4675
+ // src/css/types/image.ts
4720
4676
  const isLinearGradient = (background) => {
4721
4677
  return background.type === 1;
4722
4678
  };
@@ -4786,8 +4742,7 @@ const SUPPORTED_IMAGE_FUNCTIONS = {
4786
4742
  "image-set": imageSet,
4787
4743
  "-webkit-image-set": imageSet
4788
4744
  };
4789
- //#endregion
4790
- //#region src/css/property-descriptors/background-image.ts
4745
+ // src/css/property-descriptors/background-image.ts
4791
4746
  const backgroundImage = {
4792
4747
  name: "background-image",
4793
4748
  initialValue: "none",
@@ -4801,8 +4756,7 @@ const backgroundImage = {
4801
4756
  return tokens.filter((value) => nonFunctionArgSeparator(value) && isSupportedImage(value)).map((value) => image.parse(context, value));
4802
4757
  }
4803
4758
  };
4804
- //#endregion
4805
- //#region src/css/property-descriptors/background-origin.ts
4759
+ // src/css/property-descriptors/background-origin.ts
4806
4760
  const backgroundOrigin = {
4807
4761
  name: "background-origin",
4808
4762
  initialValue: "border-box",
@@ -4818,8 +4772,7 @@ const backgroundOrigin = {
4818
4772
  });
4819
4773
  }
4820
4774
  };
4821
- //#endregion
4822
- //#region src/css/property-descriptors/background-position.ts
4775
+ // src/css/property-descriptors/background-position.ts
4823
4776
  const backgroundPosition = {
4824
4777
  name: "background-position",
4825
4778
  initialValue: "0% 0%",
@@ -4831,8 +4784,7 @@ const backgroundPosition = {
4831
4784
  }).map(parseLengthPercentageTuple);
4832
4785
  }
4833
4786
  };
4834
- //#endregion
4835
- //#region src/css/property-descriptors/background-repeat.ts
4787
+ // src/css/property-descriptors/background-repeat.ts
4836
4788
  const backgroundRepeat = {
4837
4789
  name: "background-repeat",
4838
4790
  initialValue: "repeat",
@@ -4852,8 +4804,7 @@ const parseBackgroundRepeat = (value) => {
4852
4804
  default: return 0;
4853
4805
  }
4854
4806
  };
4855
- //#endregion
4856
- //#region src/css/property-descriptors/background-size.ts
4807
+ // src/css/property-descriptors/background-size.ts
4857
4808
  const backgroundSize = {
4858
4809
  name: "background-size",
4859
4810
  initialValue: "0",
@@ -4864,8 +4815,7 @@ const backgroundSize = {
4864
4815
  }
4865
4816
  };
4866
4817
  const isBackgroundSizeInfoToken = (value) => isIdentToken(value) || isLengthPercentage(value);
4867
- //#endregion
4868
- //#region src/css/property-descriptors/border-color.ts
4818
+ // src/css/property-descriptors/border-color.ts
4869
4819
  const borderColorForSide = (side) => ({
4870
4820
  name: `border-${side}-color`,
4871
4821
  initialValue: "transparent",
@@ -4877,8 +4827,7 @@ const borderTopColor = borderColorForSide("top");
4877
4827
  const borderRightColor = borderColorForSide("right");
4878
4828
  const borderBottomColor = borderColorForSide("bottom");
4879
4829
  const borderLeftColor = borderColorForSide("left");
4880
- //#endregion
4881
- //#region src/css/property-descriptors/border-radius.ts
4830
+ // src/css/property-descriptors/border-radius.ts
4882
4831
  const borderRadiusForSide = (side) => ({
4883
4832
  name: `border-${side}-radius`,
4884
4833
  initialValue: "0 0",
@@ -4890,8 +4839,7 @@ const borderTopLeftRadius = borderRadiusForSide("top-left");
4890
4839
  const borderTopRightRadius = borderRadiusForSide("top-right");
4891
4840
  const borderBottomRightRadius = borderRadiusForSide("bottom-right");
4892
4841
  const borderBottomLeftRadius = borderRadiusForSide("bottom-left");
4893
- //#endregion
4894
- //#region src/css/property-descriptors/border-style.ts
4842
+ // src/css/property-descriptors/border-style.ts
4895
4843
  const borderStyleForSide = (side) => ({
4896
4844
  name: `border-${side}-style`,
4897
4845
  initialValue: "solid",
@@ -4911,8 +4859,7 @@ const borderTopStyle = borderStyleForSide("top");
4911
4859
  const borderRightStyle = borderStyleForSide("right");
4912
4860
  const borderBottomStyle = borderStyleForSide("bottom");
4913
4861
  const borderLeftStyle = borderStyleForSide("left");
4914
- //#endregion
4915
- //#region src/css/property-descriptors/border-width.ts
4862
+ // src/css/property-descriptors/border-width.ts
4916
4863
  const borderWidthForSide = (side) => ({
4917
4864
  name: `border-${side}-width`,
4918
4865
  initialValue: "0",
@@ -4927,8 +4874,7 @@ const borderTopWidth = borderWidthForSide("top");
4927
4874
  const borderRightWidth = borderWidthForSide("right");
4928
4875
  const borderBottomWidth = borderWidthForSide("bottom");
4929
4876
  const borderLeftWidth = borderWidthForSide("left");
4930
- //#endregion
4931
- //#region src/css/property-descriptors/clip-path.ts
4877
+ // src/css/property-descriptors/clip-path.ts
4932
4878
  const NONE = { type: 0 };
4933
4879
  /**
4934
4880
  * Parse a shape-radius token: <length-percentage> | closest-side | farthest-side.
@@ -5149,8 +5095,7 @@ const clipPath = {
5149
5095
  return NONE;
5150
5096
  }
5151
5097
  };
5152
- //#endregion
5153
- //#region src/css/property-descriptors/color.ts
5098
+ // src/css/property-descriptors/color.ts
5154
5099
  const color = {
5155
5100
  name: `color`,
5156
5101
  initialValue: "transparent",
@@ -5158,8 +5103,7 @@ const color = {
5158
5103
  type: 3,
5159
5104
  format: "color"
5160
5105
  };
5161
- //#endregion
5162
- //#region src/css/property-descriptors/direction.ts
5106
+ // src/css/property-descriptors/direction.ts
5163
5107
  const direction = {
5164
5108
  name: "direction",
5165
5109
  initialValue: "ltr",
@@ -5172,8 +5116,7 @@ const direction = {
5172
5116
  }
5173
5117
  }
5174
5118
  };
5175
- //#endregion
5176
- //#region src/css/property-descriptors/font-family.ts
5119
+ // src/css/property-descriptors/font-family.ts
5177
5120
  const fontFamily = {
5178
5121
  name: `font-family`,
5179
5122
  initialValue: "",
@@ -5210,8 +5153,7 @@ const fontFamily = {
5210
5153
  return results.map((result, index) => quoted[index] || result.indexOf(" ") !== -1 ? `'${result.replace(/\\/g, "\\\\").replace(/'/g, "\\'").replace(/\n/g, "\\a ").replace(/\r/g, "\\d ").replace(/\f/g, "\\c ")}'` : result);
5211
5154
  }
5212
5155
  };
5213
- //#endregion
5214
- //#region src/css/property-descriptors/font-size.ts
5156
+ // src/css/property-descriptors/font-size.ts
5215
5157
  const fontSize = {
5216
5158
  name: `font-size`,
5217
5159
  initialValue: "0",
@@ -5219,8 +5161,7 @@ const fontSize = {
5219
5161
  type: 3,
5220
5162
  format: "length"
5221
5163
  };
5222
- //#endregion
5223
- //#region src/css/property-descriptors/letter-spacing.ts
5164
+ // src/css/property-descriptors/letter-spacing.ts
5224
5165
  const letterSpacing = {
5225
5166
  name: "letter-spacing",
5226
5167
  initialValue: "0",
@@ -5233,8 +5174,7 @@ const letterSpacing = {
5233
5174
  return 0;
5234
5175
  }
5235
5176
  };
5236
- //#endregion
5237
- //#region src/css/property-descriptors/line-break.ts
5177
+ // src/css/property-descriptors/line-break.ts
5238
5178
  const lineBreak = {
5239
5179
  name: "line-break",
5240
5180
  initialValue: "normal",
@@ -5247,8 +5187,7 @@ const lineBreak = {
5247
5187
  }
5248
5188
  }
5249
5189
  };
5250
- //#endregion
5251
- //#region src/css/property-descriptors/line-height.ts
5190
+ // src/css/property-descriptors/line-height.ts
5252
5191
  const lineHeight = {
5253
5192
  name: "line-height",
5254
5193
  initialValue: "normal",
@@ -5261,8 +5200,7 @@ const computeLineHeight = (token, fontSize) => {
5261
5200
  else if (isLengthPercentage(token)) return getAbsoluteValue(token, fontSize);
5262
5201
  return fontSize;
5263
5202
  };
5264
- //#endregion
5265
- //#region src/css/property-descriptors/list-style-image.ts
5203
+ // src/css/property-descriptors/list-style-image.ts
5266
5204
  const listStyleImage = {
5267
5205
  name: "list-style-image",
5268
5206
  initialValue: "none",
@@ -5275,8 +5213,7 @@ const listStyleImage = {
5275
5213
  return image.parse(context, token);
5276
5214
  }
5277
5215
  };
5278
- //#endregion
5279
- //#region src/css/property-descriptors/list-style-position.ts
5216
+ // src/css/property-descriptors/list-style-position.ts
5280
5217
  const listStylePosition = {
5281
5218
  name: "list-style-position",
5282
5219
  initialValue: "outside",
@@ -5289,8 +5226,7 @@ const listStylePosition = {
5289
5226
  }
5290
5227
  }
5291
5228
  };
5292
- //#endregion
5293
- //#region src/css/property-descriptors/margin.ts
5229
+ // src/css/property-descriptors/margin.ts
5294
5230
  const marginForSide = (side) => ({
5295
5231
  name: `margin-${side}`,
5296
5232
  initialValue: "0",
@@ -5301,8 +5237,7 @@ const marginTop = marginForSide("top");
5301
5237
  const marginRight = marginForSide("right");
5302
5238
  const marginBottom = marginForSide("bottom");
5303
5239
  const marginLeft = marginForSide("left");
5304
- //#endregion
5305
- //#region src/css/property-descriptors/overflow-wrap.ts
5240
+ // src/css/property-descriptors/overflow-wrap.ts
5306
5241
  const overflowWrap = {
5307
5242
  name: "overflow-wrap",
5308
5243
  initialValue: "normal",
@@ -5315,8 +5250,7 @@ const overflowWrap = {
5315
5250
  }
5316
5251
  }
5317
5252
  };
5318
- //#endregion
5319
- //#region src/css/property-descriptors/padding.ts
5253
+ // src/css/property-descriptors/padding.ts
5320
5254
  const paddingForSide = (side) => ({
5321
5255
  name: `padding-${side}`,
5322
5256
  initialValue: "0",
@@ -5328,8 +5262,7 @@ const paddingTop = paddingForSide("top");
5328
5262
  const paddingRight = paddingForSide("right");
5329
5263
  const paddingBottom = paddingForSide("bottom");
5330
5264
  const paddingLeft = paddingForSide("left");
5331
- //#endregion
5332
- //#region src/css/property-descriptors/text-align.ts
5265
+ // src/css/property-descriptors/text-align.ts
5333
5266
  const textAlign = {
5334
5267
  name: "text-align",
5335
5268
  initialValue: "left",
@@ -5344,8 +5277,7 @@ const textAlign = {
5344
5277
  }
5345
5278
  }
5346
5279
  };
5347
- //#endregion
5348
- //#region src/css/property-descriptors/position.ts
5280
+ // src/css/property-descriptors/position.ts
5349
5281
  const position = {
5350
5282
  name: "position",
5351
5283
  initialValue: "static",
@@ -5361,8 +5293,7 @@ const position = {
5361
5293
  return 0;
5362
5294
  }
5363
5295
  };
5364
- //#endregion
5365
- //#region src/css/property-descriptors/text-shadow.ts
5296
+ // src/css/property-descriptors/text-shadow.ts
5366
5297
  const textShadow = {
5367
5298
  name: "text-shadow",
5368
5299
  initialValue: "none",
@@ -5392,8 +5323,7 @@ const textShadow = {
5392
5323
  });
5393
5324
  }
5394
5325
  };
5395
- //#endregion
5396
- //#region src/css/property-descriptors/text-transform.ts
5326
+ // src/css/property-descriptors/text-transform.ts
5397
5327
  const textTransform = {
5398
5328
  name: "text-transform",
5399
5329
  initialValue: "none",
@@ -5408,8 +5338,7 @@ const textTransform = {
5408
5338
  return 0;
5409
5339
  }
5410
5340
  };
5411
- //#endregion
5412
- //#region src/css/property-descriptors/transform.ts
5341
+ // src/css/property-descriptors/transform.ts
5413
5342
  const transform$1 = {
5414
5343
  name: "transform",
5415
5344
  initialValue: "none",
@@ -5464,8 +5393,7 @@ const SUPPORTED_TRANSFORM_FUNCTIONS = {
5464
5393
  matrix3d,
5465
5394
  rotate: rotate$1
5466
5395
  };
5467
- //#endregion
5468
- //#region src/css/property-descriptors/transform-origin.ts
5396
+ // src/css/property-descriptors/transform-origin.ts
5469
5397
  const DEFAULT_VALUE = {
5470
5398
  type: 16,
5471
5399
  number: 50,
@@ -5483,8 +5411,7 @@ const transformOrigin = {
5483
5411
  return [at(origins, 0), at(origins, 1)];
5484
5412
  }
5485
5413
  };
5486
- //#endregion
5487
- //#region src/css/property-descriptors/rotate.ts
5414
+ // src/css/property-descriptors/rotate.ts
5488
5415
  const rotate = {
5489
5416
  name: "rotate",
5490
5417
  initialValue: "none",
@@ -5499,8 +5426,7 @@ const rotate = {
5499
5426
  return null;
5500
5427
  }
5501
5428
  };
5502
- //#endregion
5503
- //#region src/css/property-descriptors/visibility.ts
5429
+ // src/css/property-descriptors/visibility.ts
5504
5430
  const visibility = {
5505
5431
  name: "visibility",
5506
5432
  initialValue: "none",
@@ -5514,8 +5440,7 @@ const visibility = {
5514
5440
  }
5515
5441
  }
5516
5442
  };
5517
- //#endregion
5518
- //#region src/css/property-descriptors/word-break.ts
5443
+ // src/css/property-descriptors/word-break.ts
5519
5444
  const wordBreak = {
5520
5445
  name: "word-break",
5521
5446
  initialValue: "normal",
@@ -5529,8 +5454,7 @@ const wordBreak = {
5529
5454
  }
5530
5455
  }
5531
5456
  };
5532
- //#endregion
5533
- //#region src/css/property-descriptors/white-space.ts
5457
+ // src/css/property-descriptors/white-space.ts
5534
5458
  const whiteSpace = {
5535
5459
  name: "white-space",
5536
5460
  initialValue: "normal",
@@ -5546,8 +5470,7 @@ const whiteSpace = {
5546
5470
  }
5547
5471
  }
5548
5472
  };
5549
- //#endregion
5550
- //#region src/css/property-descriptors/writing-mode.ts
5473
+ // src/css/property-descriptors/writing-mode.ts
5551
5474
  const isVerticalWritingMode = (writingMode) => writingMode !== 0;
5552
5475
  const isSidewaysWritingMode = (writingMode) => writingMode === 3 || writingMode === 4;
5553
5476
  const writingMode = {
@@ -5565,8 +5488,7 @@ const writingMode = {
5565
5488
  }
5566
5489
  }
5567
5490
  };
5568
- //#endregion
5569
- //#region src/css/property-descriptors/z-index.ts
5491
+ // src/css/property-descriptors/z-index.ts
5570
5492
  const zIndex = {
5571
5493
  name: "z-index",
5572
5494
  initialValue: "auto",
@@ -5584,8 +5506,7 @@ const zIndex = {
5584
5506
  throw new Error(`Invalid z-index number parsed`);
5585
5507
  }
5586
5508
  };
5587
- //#endregion
5588
- //#region src/css/types/time.ts
5509
+ // src/css/types/time.ts
5589
5510
  const time = {
5590
5511
  name: "time",
5591
5512
  parse: (_context, value) => {
@@ -5596,8 +5517,7 @@ const time = {
5596
5517
  throw new Error(`Unsupported time type`);
5597
5518
  }
5598
5519
  };
5599
- //#endregion
5600
- //#region src/css/property-descriptors/opacity.ts
5520
+ // src/css/property-descriptors/opacity.ts
5601
5521
  const opacity = {
5602
5522
  name: "opacity",
5603
5523
  initialValue: "1",
@@ -5608,8 +5528,7 @@ const opacity = {
5608
5528
  return 1;
5609
5529
  }
5610
5530
  };
5611
- //#endregion
5612
- //#region src/css/property-descriptors/text-decoration-style.ts
5531
+ // src/css/property-descriptors/text-decoration-style.ts
5613
5532
  const textDecorationStyle = {
5614
5533
  name: "text-decoration-style",
5615
5534
  initialValue: "solid",
@@ -5625,8 +5544,7 @@ const textDecorationStyle = {
5625
5544
  }
5626
5545
  }
5627
5546
  };
5628
- //#endregion
5629
- //#region src/css/property-descriptors/text-decoration-thickness.ts
5547
+ // src/css/property-descriptors/text-decoration-thickness.ts
5630
5548
  const textDecorationThickness = {
5631
5549
  name: "text-decoration-thickness",
5632
5550
  initialValue: "auto",
@@ -5641,8 +5559,7 @@ const textDecorationThickness = {
5641
5559
  return "auto";
5642
5560
  }
5643
5561
  };
5644
- //#endregion
5645
- //#region src/css/property-descriptors/text-underline-offset.ts
5562
+ // src/css/property-descriptors/text-underline-offset.ts
5646
5563
  const textUnderlineOffset = {
5647
5564
  name: "text-underline-offset",
5648
5565
  initialValue: "auto",
@@ -5656,8 +5573,7 @@ const textUnderlineOffset = {
5656
5573
  return "auto";
5657
5574
  }
5658
5575
  };
5659
- //#endregion
5660
- //#region src/css/property-descriptors/font-weight.ts
5576
+ // src/css/property-descriptors/font-weight.ts
5661
5577
  const fontWeight = {
5662
5578
  name: "font-weight",
5663
5579
  initialValue: "normal",
@@ -5672,8 +5588,7 @@ const fontWeight = {
5672
5588
  return 400;
5673
5589
  }
5674
5590
  };
5675
- //#endregion
5676
- //#region src/css/property-descriptors/font-variant.ts
5591
+ // src/css/property-descriptors/font-variant.ts
5677
5592
  const fontVariant = {
5678
5593
  name: "font-variant",
5679
5594
  initialValue: "none",
@@ -5683,8 +5598,7 @@ const fontVariant = {
5683
5598
  return tokens.filter(isIdentToken).map((token) => token.value);
5684
5599
  }
5685
5600
  };
5686
- //#endregion
5687
- //#region src/css/property-descriptors/font-style.ts
5601
+ // src/css/property-descriptors/font-style.ts
5688
5602
  const fontStyle = {
5689
5603
  name: "font-style",
5690
5604
  initialValue: "normal",
@@ -5698,8 +5612,7 @@ const fontStyle = {
5698
5612
  }
5699
5613
  }
5700
5614
  };
5701
- //#endregion
5702
- //#region src/css/property-descriptors/duration.ts
5615
+ // src/css/property-descriptors/duration.ts
5703
5616
  const duration = {
5704
5617
  name: "duration",
5705
5618
  initialValue: "0s",
@@ -5709,8 +5622,7 @@ const duration = {
5709
5622
  return tokens.filter(isDimensionToken).map((token) => time.parse(context, token));
5710
5623
  }
5711
5624
  };
5712
- //#endregion
5713
- //#region src/css/property-descriptors/box-shadow.ts
5625
+ // src/css/property-descriptors/box-shadow.ts
5714
5626
  const boxShadow = {
5715
5627
  name: "box-shadow",
5716
5628
  initialValue: "none",
@@ -5744,8 +5656,7 @@ const boxShadow = {
5744
5656
  });
5745
5657
  }
5746
5658
  };
5747
- //#endregion
5748
- //#region src/css/property-descriptors/paint-order.ts
5659
+ // src/css/property-descriptors/paint-order.ts
5749
5660
  const paintOrder = {
5750
5661
  name: "paint-order",
5751
5662
  initialValue: "normal",
@@ -5775,8 +5686,7 @@ const paintOrder = {
5775
5686
  return layers;
5776
5687
  }
5777
5688
  };
5778
- //#endregion
5779
- //#region src/css/property-descriptors/webkit-text-stroke-color.ts
5689
+ // src/css/property-descriptors/webkit-text-stroke-color.ts
5780
5690
  const webkitTextStrokeColor = {
5781
5691
  name: `-webkit-text-stroke-color`,
5782
5692
  initialValue: "currentcolor",
@@ -5784,8 +5694,7 @@ const webkitTextStrokeColor = {
5784
5694
  type: 3,
5785
5695
  format: "color"
5786
5696
  };
5787
- //#endregion
5788
- //#region src/css/property-descriptors/webkit-text-stroke-width.ts
5697
+ // src/css/property-descriptors/webkit-text-stroke-width.ts
5789
5698
  const webkitTextStrokeWidth = {
5790
5699
  name: `-webkit-text-stroke-width`,
5791
5700
  initialValue: "0",
@@ -5796,8 +5705,7 @@ const webkitTextStrokeWidth = {
5796
5705
  return 0;
5797
5706
  }
5798
5707
  };
5799
- //#endregion
5800
- //#region src/css/property-descriptors/webkit-line-clamp.ts
5708
+ // src/css/property-descriptors/webkit-line-clamp.ts
5801
5709
  /**
5802
5710
  * -webkit-line-clamp property descriptor
5803
5711
  * Used with display: -webkit-box and -webkit-box-orient: vertical
@@ -5814,8 +5722,7 @@ const webkitLineClamp = {
5814
5722
  return 0;
5815
5723
  }
5816
5724
  };
5817
- //#endregion
5818
- //#region src/css/property-descriptors/object-fit.ts
5725
+ // src/css/property-descriptors/object-fit.ts
5819
5726
  const objectFit = {
5820
5727
  name: "object-fit",
5821
5728
  initialValue: "fill",
@@ -5836,8 +5743,7 @@ const parseDisplayValue = (display) => {
5836
5743
  }
5837
5744
  return 0;
5838
5745
  };
5839
- //#endregion
5840
- //#region src/css/property-descriptors/text-overflow.ts
5746
+ // src/css/property-descriptors/text-overflow.ts
5841
5747
  const textOverflow = {
5842
5748
  name: "text-overflow",
5843
5749
  initialValue: "clip",
@@ -5850,8 +5756,7 @@ const textOverflow = {
5850
5756
  }
5851
5757
  }
5852
5758
  };
5853
- //#endregion
5854
- //#region src/css/property-descriptors/image-rendering.ts
5759
+ // src/css/property-descriptors/image-rendering.ts
5855
5760
  const imageRendering = {
5856
5761
  name: "image-rendering",
5857
5762
  initialValue: "auto",
@@ -5870,8 +5775,7 @@ const imageRendering = {
5870
5775
  }
5871
5776
  }
5872
5777
  };
5873
- //#endregion
5874
- //#region src/css/property-descriptors/mix-blend-mode.ts
5778
+ // src/css/property-descriptors/mix-blend-mode.ts
5875
5779
  const MIX_BLEND_MODE$1 = {
5876
5780
  NORMAL: "normal",
5877
5781
  MULTIPLY: "multiply",
@@ -5900,8 +5804,7 @@ const mixBlendMode = {
5900
5804
  return VALID_VALUES$1.has(token) ? token : MIX_BLEND_MODE$1.NORMAL;
5901
5805
  }
5902
5806
  };
5903
- //#endregion
5904
- //#region src/css/property-descriptors/filter.ts
5807
+ // src/css/property-descriptors/filter.ts
5905
5808
  const filter = {
5906
5809
  name: "filter",
5907
5810
  initialValue: "none",
@@ -5971,8 +5874,7 @@ const renderFilterArgs = (values) => {
5971
5874
  }
5972
5875
  return parts.join("").trim();
5973
5876
  };
5974
- //#endregion
5975
- //#region src/css/property-descriptors/font-variant-ligatures.ts
5877
+ // src/css/property-descriptors/font-variant-ligatures.ts
5976
5878
  const fontVariantLigatures = {
5977
5879
  name: "font-variant-ligatures",
5978
5880
  initialValue: "normal",
@@ -5993,8 +5895,7 @@ const fontVariantLigatures = {
5993
5895
  }
5994
5896
  }
5995
5897
  };
5996
- //#endregion
5997
- //#region src/css/property-descriptors/zoom.ts
5898
+ // src/css/property-descriptors/zoom.ts
5998
5899
  const zoom = {
5999
5900
  name: "zoom",
6000
5901
  initialValue: "1",
@@ -6006,8 +5907,7 @@ const zoom = {
6006
5907
  return 1;
6007
5908
  }
6008
5909
  };
6009
- //#endregion
6010
- //#region src/css/property-descriptors/object-position.ts
5910
+ // src/css/property-descriptors/object-position.ts
6011
5911
  const objectPosition = {
6012
5912
  name: "object-position",
6013
5913
  initialValue: "50% 50%",
@@ -6069,8 +5969,7 @@ const backgroundBlendMode = {
6069
5969
  return modes.length > 0 ? modes : ["normal"];
6070
5970
  }
6071
5971
  };
6072
- //#endregion
6073
- //#region src/css/property-descriptors/border-image-source.ts
5972
+ // src/css/property-descriptors/border-image-source.ts
6074
5973
  const borderImageSource = {
6075
5974
  name: "border-image-source",
6076
5975
  initialValue: "none",
@@ -6084,8 +5983,7 @@ const borderImageSource = {
6084
5983
  return image.parse(context, at(filtered, 0));
6085
5984
  }
6086
5985
  };
6087
- //#endregion
6088
- //#region src/css/property-descriptors/border-image-slice.ts
5986
+ // src/css/property-descriptors/border-image-slice.ts
6089
5987
  const fillSides$1 = (sides) => {
6090
5988
  const result = [...sides];
6091
5989
  if (result.length === 1) {
@@ -6134,8 +6032,7 @@ const borderImageSlice = {
6134
6032
  };
6135
6033
  }
6136
6034
  };
6137
- //#endregion
6138
- //#region src/css/property-descriptors/border-image-repeat.ts
6035
+ // src/css/property-descriptors/border-image-repeat.ts
6139
6036
  const parseRepeatValue = (value) => {
6140
6037
  switch (value) {
6141
6038
  case "repeat": return 1;
@@ -6160,8 +6057,7 @@ const borderImageRepeat = {
6160
6057
  };
6161
6058
  }
6162
6059
  };
6163
- //#endregion
6164
- //#region src/css/property-descriptors/box-decoration-break.ts
6060
+ // src/css/property-descriptors/box-decoration-break.ts
6165
6061
  const boxDecorationBreak = {
6166
6062
  name: "box-decoration-break",
6167
6063
  initialValue: "slice",
@@ -6174,8 +6070,7 @@ const boxDecorationBreak = {
6174
6070
  }
6175
6071
  }
6176
6072
  };
6177
- //#endregion
6178
- //#region src/css/property-descriptors/accent-color.ts
6073
+ // src/css/property-descriptors/accent-color.ts
6179
6074
  const accentColor = {
6180
6075
  name: "accent-color",
6181
6076
  initialValue: "auto",
@@ -6186,8 +6081,7 @@ const accentColor = {
6186
6081
  return color$1.parse(context, token);
6187
6082
  }
6188
6083
  };
6189
- //#endregion
6190
- //#region src/css/property-descriptors/webkit-text-fill-color.ts
6084
+ // src/css/property-descriptors/webkit-text-fill-color.ts
6191
6085
  const webkitTextFillColor = {
6192
6086
  name: "-webkit-text-fill-color",
6193
6087
  initialValue: "currentcolor",
@@ -6198,8 +6092,7 @@ const webkitTextFillColor = {
6198
6092
  return color$1.parse(context, token);
6199
6093
  }
6200
6094
  };
6201
- //#endregion
6202
- //#region src/css/property-descriptors/isolation.ts
6095
+ // src/css/property-descriptors/isolation.ts
6203
6096
  const isolation = {
6204
6097
  name: "isolation",
6205
6098
  initialValue: "auto",
@@ -6209,8 +6102,52 @@ const isolation = {
6209
6102
  return value === "isolate" ? 1 : 0;
6210
6103
  }
6211
6104
  };
6212
- //#endregion
6213
- //#region src/css/property-descriptors/outline.ts
6105
+ // src/css/property-descriptors/will-change.ts
6106
+ const STACKING_HINTS = /* @__PURE__ */ new Set([
6107
+ "transform",
6108
+ "translate",
6109
+ "rotate",
6110
+ "scale",
6111
+ "opacity",
6112
+ "filter",
6113
+ "backdrop-filter",
6114
+ "mix-blend-mode",
6115
+ "isolation",
6116
+ "clip-path",
6117
+ "mask",
6118
+ "mask-image",
6119
+ "mask-border",
6120
+ "perspective",
6121
+ "contain",
6122
+ "offset-path",
6123
+ "offset-distance",
6124
+ "offset-rotate",
6125
+ "top",
6126
+ "left",
6127
+ "bottom",
6128
+ "right",
6129
+ "z-index"
6130
+ ]);
6131
+ const willChange = {
6132
+ name: "will-change",
6133
+ initialValue: "auto",
6134
+ prefix: false,
6135
+ type: 1,
6136
+ parse: (_context, tokens) => {
6137
+ return tokens.some((token) => isIdentToken(token) && STACKING_HINTS.has(token.value)) ? 1 : 0;
6138
+ }
6139
+ };
6140
+ // src/css/property-descriptors/contain.ts
6141
+ const contain = {
6142
+ name: "contain",
6143
+ initialValue: "none",
6144
+ prefix: false,
6145
+ type: 2,
6146
+ parse: (_context, value) => {
6147
+ return /\b(paint|strict|content)\b/.test(value) ? 1 : 0;
6148
+ }
6149
+ };
6150
+ // src/css/property-descriptors/outline.ts
6214
6151
  const outlineStyle = {
6215
6152
  name: "outline-style",
6216
6153
  initialValue: "none",
@@ -6253,8 +6190,7 @@ const outlineOffset = {
6253
6190
  return isDimensionToken(token) || isNumberToken(token) ? token.number : 0;
6254
6191
  }
6255
6192
  };
6256
- //#endregion
6257
- //#region src/css/property-descriptors/backdrop-filter.ts
6193
+ // src/css/property-descriptors/backdrop-filter.ts
6258
6194
  const backdropFilter = {
6259
6195
  name: "backdrop-filter",
6260
6196
  initialValue: "none",
@@ -6262,8 +6198,7 @@ const backdropFilter = {
6262
6198
  type: 1,
6263
6199
  parse: (context, tokens) => filter.parse(context, tokens)
6264
6200
  };
6265
- //#endregion
6266
- //#region src/css/property-descriptors/mask.ts
6201
+ // src/css/property-descriptors/mask.ts
6267
6202
  const maskImage = {
6268
6203
  name: "mask-image",
6269
6204
  initialValue: "none",
@@ -6293,8 +6228,7 @@ const maskSize = {
6293
6228
  type: 1,
6294
6229
  parse: backgroundSize.parse
6295
6230
  };
6296
- //#endregion
6297
- //#region src/css/property-descriptors/text-emphasis.ts
6231
+ // src/css/property-descriptors/text-emphasis.ts
6298
6232
  const SHAPES = [
6299
6233
  "dot",
6300
6234
  "circle",
@@ -6369,8 +6303,7 @@ const textEmphasisPosition = {
6369
6303
  };
6370
6304
  }
6371
6305
  };
6372
- //#endregion
6373
- //#region src/css/property-descriptors/border-image-width.ts
6306
+ // src/css/property-descriptors/border-image-width.ts
6374
6307
  const fillSides = (sides) => {
6375
6308
  const result = [...sides];
6376
6309
  if (result.length === 1) {
@@ -6467,8 +6400,7 @@ const borderImageOutset = {
6467
6400
  };
6468
6401
  }
6469
6402
  };
6470
- //#endregion
6471
- //#region src/css/property-descriptors/webkit-box-reflect.ts
6403
+ // src/css/property-descriptors/webkit-box-reflect.ts
6472
6404
  /**
6473
6405
  * -webkit-box-reflect: <direction> <offset>? <mask-image>?
6474
6406
  *
@@ -6512,8 +6444,7 @@ const webkitBoxReflect = {
6512
6444
  };
6513
6445
  }
6514
6446
  };
6515
- //#endregion
6516
- //#region src/css/property-descriptors/translate.ts
6447
+ // src/css/property-descriptors/translate.ts
6517
6448
  const translate = {
6518
6449
  name: "translate",
6519
6450
  initialValue: "none",
@@ -6526,8 +6457,7 @@ const translate = {
6526
6457
  return [at(values, 0), values.length > 1 ? at(values, 1) : ZERO_LENGTH];
6527
6458
  }
6528
6459
  };
6529
- //#endregion
6530
- //#region src/css/property-descriptors/scale.ts
6460
+ // src/css/property-descriptors/scale.ts
6531
6461
  const scale = {
6532
6462
  name: "scale",
6533
6463
  initialValue: "none",
@@ -6562,8 +6492,7 @@ const STYLESHEET_READY_TIMEOUT_MS = 1e4;
6562
6492
  * never fires, the mount is rejected instead of hanging forever.
6563
6493
  */
6564
6494
  const IFRAME_LOAD_WATCHDOG_MS = 6e4;
6565
- //#endregion
6566
- //#region src/css/parse.ts
6495
+ // src/css/parse.ts
6567
6496
  const STANDARD_PROPERTIES = [
6568
6497
  [
6569
6498
  "animationDuration",
@@ -7000,6 +6929,16 @@ const STANDARD_PROPERTIES = [
7000
6929
  isolation,
7001
6930
  "isolation"
7002
6931
  ],
6932
+ [
6933
+ "willChange",
6934
+ willChange,
6935
+ "will-change"
6936
+ ],
6937
+ [
6938
+ "contain",
6939
+ contain,
6940
+ "contain"
6941
+ ],
7003
6942
  [
7004
6943
  "outlineColor",
7005
6944
  outlineColor,
@@ -7131,8 +7070,7 @@ const parse = (context, descriptor, style) => {
7131
7070
  }
7132
7071
  return result;
7133
7072
  };
7134
- //#endregion
7135
- //#region src/css/grouped/border-styles.ts
7073
+ // src/css/grouped/border-styles.ts
7136
7074
  /**
7137
7075
  * Read-only grouped accessor for border-related CSS properties.
7138
7076
  *
@@ -7209,8 +7147,7 @@ var BorderStyles = class {
7209
7147
  return this.styles.boxShadow;
7210
7148
  }
7211
7149
  };
7212
- //#endregion
7213
- //#region src/css/grouped/background-styles.ts
7150
+ // src/css/grouped/background-styles.ts
7214
7151
  /**
7215
7152
  * Read-only grouped accessor for background-related CSS properties.
7216
7153
  *
@@ -7248,8 +7185,7 @@ var BackgroundStyles = class {
7248
7185
  return this.styles.backgroundBlendMode;
7249
7186
  }
7250
7187
  };
7251
- //#endregion
7252
- //#region src/css/grouped/font-styles.ts
7188
+ // src/css/grouped/font-styles.ts
7253
7189
  /**
7254
7190
  * Read-only grouped accessor for font/text-related CSS properties.
7255
7191
  *
@@ -7344,8 +7280,7 @@ var FontStyles = class {
7344
7280
  return this.styles.paintOrder;
7345
7281
  }
7346
7282
  };
7347
- //#endregion
7348
- //#region src/css/grouped/layout-styles.ts
7283
+ // src/css/grouped/layout-styles.ts
7349
7284
  /**
7350
7285
  * Read-only grouped accessor for layout/display/positioning CSS properties.
7351
7286
  *
@@ -7473,8 +7408,7 @@ var LayoutStyles = class {
7473
7408
  return this.styles.isInlineLevel();
7474
7409
  }
7475
7410
  };
7476
- //#endregion
7477
- //#region src/css/index.ts
7411
+ // src/css/index.ts
7478
7412
  var CSSParsedDeclaration = class {
7479
7413
  animationDuration;
7480
7414
  backgroundClip;
@@ -7568,6 +7502,8 @@ var CSSParsedDeclaration = class {
7568
7502
  accentColor;
7569
7503
  webkitTextFillColor;
7570
7504
  isolation;
7505
+ willChange;
7506
+ contain;
7571
7507
  outlineColor;
7572
7508
  outlineStyle;
7573
7509
  outlineWidth;
@@ -7666,8 +7602,7 @@ var CSSParsedCounterDeclaration = class {
7666
7602
  this.counterReset = parse(context, counterReset, declaration.counterReset);
7667
7603
  }
7668
7604
  };
7669
- //#endregion
7670
- //#region src/core/debugger.ts
7605
+ // src/core/debugger.ts
7671
7606
  const elementDebuggerAttribute = "data-html2canvas-debug";
7672
7607
  const getElementDebugType = (element) => {
7673
7608
  if (typeof element.getAttribute !== "function") return 0;
@@ -7683,8 +7618,7 @@ const isDebugging = (element, type) => {
7683
7618
  const elementType = getElementDebugType(element);
7684
7619
  return elementType === 1 || type === elementType;
7685
7620
  };
7686
- //#endregion
7687
- //#region src/dom/adopted-styles.ts
7621
+ // src/dom/adopted-styles.ts
7688
7622
  /**
7689
7623
  * Constructable stylesheet cloning (adoptedStyleSheets).
7690
7624
  *
@@ -7725,8 +7659,7 @@ const createAdoptedStylesElement = (styleDocument, sheets, nonce) => {
7725
7659
  if (nonce) style.nonce = nonce;
7726
7660
  return style;
7727
7661
  };
7728
- //#endregion
7729
- //#region src/dom/slot-cloner.ts
7662
+ // src/dom/slot-cloner.ts
7730
7663
  /** Exported for reuse in document-cloner.ts */
7731
7664
  const IGNORE_ATTRIBUTE = "data-html2canvas-ignore";
7732
7665
  /**
@@ -7863,8 +7796,7 @@ var SlotCloner = class {
7863
7796
  if (style) target.appendChild(style);
7864
7797
  }
7865
7798
  };
7866
- //#endregion
7867
- //#region src/dom/copy-css-styles.ts
7799
+ // src/dom/copy-css-styles.ts
7868
7800
  /**
7869
7801
  * Computed-style copying for cloned elements.
7870
7802
  *
@@ -7892,8 +7824,7 @@ const copyCSSStyles = (style, target) => {
7892
7824
  if (parts.length > 0) target.style.cssText = parts.join(";") + ";";
7893
7825
  return target;
7894
7826
  };
7895
- //#endregion
7896
- //#region src/dom/pseudo-content.ts
7827
+ // src/dom/pseudo-content.ts
7897
7828
  /**
7898
7829
  * Pseudo-element (::before / ::after) content resolution.
7899
7830
  *
@@ -7913,19 +7844,19 @@ const PSEUDO_HIDE_ELEMENT_STYLE = `{
7913
7844
  }`;
7914
7845
  /**
7915
7846
  * Inject the stylesheet that hides pseudo-element surrogate containers.
7916
- * Called on the cloned <body> so the surrogates themselves never render.
7847
+ * Added to the cloned <head> so the surrogates themselves never render.
7917
7848
  */
7918
- const createPseudoHideStyles = (body, cspNonce) => {
7919
- createStyles(body, `.${PSEUDO_HIDE_ELEMENT_CLASS_BEFORE}${PSEUDO_BEFORE}${PSEUDO_HIDE_ELEMENT_STYLE}
7849
+ const createPseudoHideStyles = (parent, cspNonce) => {
7850
+ createStyles(parent, `.${PSEUDO_HIDE_ELEMENT_CLASS_BEFORE}${PSEUDO_BEFORE}${PSEUDO_HIDE_ELEMENT_STYLE}
7920
7851
  .${PSEUDO_HIDE_ELEMENT_CLASS_AFTER}${PSEUDO_AFTER}${PSEUDO_HIDE_ELEMENT_STYLE}`, cspNonce);
7921
7852
  };
7922
- const createStyles = (body, styles, cspNonce) => {
7923
- const document = body.ownerDocument;
7853
+ const createStyles = (parent, styles, cspNonce) => {
7854
+ const document = parent.ownerDocument;
7924
7855
  if (document) {
7925
7856
  const style = document.createElement("style");
7926
7857
  style.textContent = styles;
7927
7858
  if (cspNonce) style.nonce = cspNonce;
7928
- body.appendChild(style);
7859
+ parent.appendChild(style);
7929
7860
  }
7930
7861
  };
7931
7862
  /**
@@ -7999,8 +7930,7 @@ var PseudoContentResolver = class {
7999
7930
  return anonymousReplacedElement;
8000
7931
  }
8001
7932
  };
8002
- //#endregion
8003
- //#region src/core/abort-helper.ts
7933
+ // src/core/abort-helper.ts
8004
7934
  /**
8005
7935
  * AbortSignal helper utilities.
8006
7936
  */
@@ -8015,8 +7945,7 @@ var PseudoContentResolver = class {
8015
7945
  const throwIfAborted = (signal) => {
8016
7946
  if (signal?.aborted) throw new DOMException("The operation was aborted.", "AbortError");
8017
7947
  };
8018
- //#endregion
8019
- //#region src/dom/iframe-mount.ts
7948
+ // src/dom/iframe-mount.ts
8020
7949
  const trustedTypePolicies = /* @__PURE__ */ new WeakMap();
8021
7950
  /**
8022
7951
  * Resolve the Trusted Types policy used for writing the clone document.
@@ -8045,9 +7974,20 @@ const createIFrameContainer = (ownerDocument, bounds, customContainer) => {
8045
7974
  cloneIframeContainer.style.position = "fixed";
8046
7975
  cloneIframeContainer.style.left = "-10000px";
8047
7976
  cloneIframeContainer.style.top = "0px";
8048
- cloneIframeContainer.style.border = "0";
8049
7977
  cloneIframeContainer.width = bounds.width.toString();
8050
7978
  cloneIframeContainer.height = bounds.height.toString();
7979
+ const contentBox = [
7980
+ ["width", `${bounds.width}px`],
7981
+ ["height", `${bounds.height}px`],
7982
+ ["min-width", "0px"],
7983
+ ["max-width", "none"],
7984
+ ["min-height", "0px"],
7985
+ ["max-height", "none"],
7986
+ ["box-sizing", "content-box"],
7987
+ ["padding", "0px"],
7988
+ ["border", "0"]
7989
+ ];
7990
+ for (const [property, value] of contentBox) cloneIframeContainer.style.setProperty(property, value, "important");
8051
7991
  cloneIframeContainer.scrolling = "no";
8052
7992
  cloneIframeContainer.setAttribute(IGNORE_ATTRIBUTE, "true");
8053
7993
  (customContainer || ownerDocument.body).appendChild(cloneIframeContainer);
@@ -8180,6 +8120,11 @@ const stylesheetsReady = (documentClone, logger, signal, timeoutMs = STYLESHEET_
8180
8120
  pending.push(new Promise((resolve) => {
8181
8121
  let elapsed = 0;
8182
8122
  const timer = setInterval(() => {
8123
+ if (signal?.aborted) {
8124
+ clearInterval(timer);
8125
+ resolve();
8126
+ return;
8127
+ }
8183
8128
  elapsed += 50;
8184
8129
  const currentSheet = style.sheet;
8185
8130
  if (currentSheet && isSheetFullyApplied(currentSheet) || elapsed >= timeoutMs) {
@@ -8350,8 +8295,7 @@ const mountCloneInIFrame = (context, ownerDocument, windowSize, mount) => {
8350
8295
  throw error;
8351
8296
  });
8352
8297
  };
8353
- //#endregion
8354
- //#region src/dom/document-cloner.ts
8298
+ // src/dom/document-cloner.ts
8355
8299
  /**
8356
8300
  * Find the parent ShadowRoot of an element, if any
8357
8301
  * @param element - The element to check
@@ -8396,6 +8340,7 @@ var DocumentCloner = class {
8396
8340
  }
8397
8341
  this.documentElement = this.cloneNode(element.ownerDocument.documentElement, false);
8398
8342
  this.appendDocumentAdoptedStyles(element.ownerDocument);
8343
+ this.appendPseudoHideStyles();
8399
8344
  }
8400
8345
  /**
8401
8346
  * Re-materialise the source document's constructable stylesheets
@@ -8415,6 +8360,16 @@ var DocumentCloner = class {
8415
8360
  const style = createAdoptedStylesElement(this.documentElement.ownerDocument ?? ownerDocument, sheets, this.options.cspNonce);
8416
8361
  if (style) head.appendChild(style);
8417
8362
  }
8363
+ /**
8364
+ * Add the rules that hide the source ::before / ::after (the clone draws
8365
+ * them as surrogate elements) to the clone's <head>. Inside <body> the
8366
+ * <style> would be one of its children, and `body > :first-child`,
8367
+ * `:nth-child()` and sibling selectors would match the wrong elements.
8368
+ */
8369
+ appendPseudoHideStyles() {
8370
+ const head = this.documentElement.getElementsByTagName("head").item(0);
8371
+ createPseudoHideStyles(head ?? this.documentElement, this.options.cspNonce);
8372
+ }
8418
8373
  toIFrame(ownerDocument, windowSize) {
8419
8374
  return mountCloneInIFrame(this.context, ownerDocument, windowSize, {
8420
8375
  documentElement: this.documentElement,
@@ -8550,7 +8505,6 @@ var DocumentCloner = class {
8550
8505
  const style = window.getComputedStyle(node);
8551
8506
  const checkPseudoElements = canHavePseudoElements(node);
8552
8507
  if (this.referenceElement === node && isHTMLElementNode(clone)) this.clonedReferenceElement = clone;
8553
- if (isBodyElement(clone)) createPseudoHideStyles(clone, this.options.cspNonce);
8554
8508
  const counters = this.counters.parse(new CSSParsedCounterDeclaration(this.context, style));
8555
8509
  if (checkPseudoElements) {
8556
8510
  const styleBefore = window.getComputedStyle(node, ":before");
@@ -8584,8 +8538,7 @@ var DocumentCloner = class {
8584
8538
  return false;
8585
8539
  }
8586
8540
  };
8587
- //#endregion
8588
- //#region src/dom/dom-normalizer.ts
8541
+ // src/dom/dom-normalizer.ts
8589
8542
  /**
8590
8543
  * Normalize element styles for accurate rendering
8591
8544
  * This includes disabling animations and neutralizing transforms.
@@ -8673,8 +8626,115 @@ var DOMNormalizer = class {
8673
8626
  if (originalStyles.scale !== void 0) element.style.scale = originalStyles.scale;
8674
8627
  }
8675
8628
  };
8676
- //#endregion
8677
- //#region src/dom/element-container.ts
8629
+ // src/dom/filter-reference.ts
8630
+ const SVG_NS$1 = "http://www.w3.org/2000/svg";
8631
+ const XLINK_NS = "http://www.w3.org/1999/xlink";
8632
+ const REGION_DEFAULTS = {
8633
+ x: "-10%",
8634
+ y: "-10%",
8635
+ width: "120%",
8636
+ height: "120%"
8637
+ };
8638
+ const PRESENTATION_PROPERTIES = [
8639
+ "color-interpolation-filters",
8640
+ "flood-color",
8641
+ "flood-opacity",
8642
+ "lighting-color"
8643
+ ];
8644
+ const REFERENCE_RE = /^(["']?)(#[^"'\s()]+)\1$/;
8645
+ const URL_RE = /url\(\s*([^)]*?)\s*\)/g;
8646
+ /** The `#id` of a same-document url() body (`"#id"`, `'#id'` or `#id`), or null. */
8647
+ const parseFilterReference = (body) => {
8648
+ const match = REFERENCE_RE.exec(body.trim());
8649
+ return match ? match[2] : null;
8650
+ };
8651
+ /**
8652
+ * Resolve every same-document url() reference of a computed filter value.
8653
+ * References that cannot be expressed in the serialized SVG are left out, so
8654
+ * the compositor rejects the chain and the subtree keeps the legacy renderer.
8655
+ */
8656
+ function resolveFilterReferences(element, filter, box) {
8657
+ if (!filter || filter.indexOf("url(") === -1) return void 0;
8658
+ const references = /* @__PURE__ */ new Map();
8659
+ const seen = /* @__PURE__ */ new Set();
8660
+ for (const match of filter.matchAll(URL_RE)) {
8661
+ const ref = parseFilterReference(match[1]);
8662
+ if (!ref || seen.has(ref)) continue;
8663
+ seen.add(ref);
8664
+ const reference = resolveFilterReference(element.ownerDocument, ref, box);
8665
+ if (reference) references.set(ref, reference);
8666
+ }
8667
+ return references;
8668
+ }
8669
+ function resolveFilterReference(document, ref, box) {
8670
+ const source = document.getElementById(ref.slice(1));
8671
+ if (!source || source.namespaceURI !== SVG_NS$1 || source.localName !== "filter") return null;
8672
+ if (!isSelfContained(source)) return null;
8673
+ const region = filterRegion(source, box);
8674
+ if (!region) return null;
8675
+ const copy = source.cloneNode(true);
8676
+ inlinePresentation(source, copy);
8677
+ copy.removeAttribute("id");
8678
+ copy.setAttribute("filterUnits", "userSpaceOnUse");
8679
+ Object.keys(region).forEach((name) => copy.setAttribute(name, String(region[name])));
8680
+ const outset = Math.max(0, -region.x, -region.y, region.x + region.width - box.width, region.y + region.height - box.height);
8681
+ return {
8682
+ element: copy,
8683
+ region,
8684
+ outset: Math.ceil(outset)
8685
+ };
8686
+ }
8687
+ const hasHref = (node) => node.hasAttribute("href") || node.hasAttributeNS(XLINK_NS, "href");
8688
+ function isSelfContained(source) {
8689
+ if (source.getAttribute("primitiveUnits") === "objectBoundingBox" || hasHref(source)) return false;
8690
+ for (const primitive of Array.from(source.querySelectorAll("*"))) {
8691
+ if (primitive.localName === "feImage" || hasHref(primitive)) return false;
8692
+ for (const name of [
8693
+ "x",
8694
+ "y",
8695
+ "width",
8696
+ "height"
8697
+ ]) if ((primitive.getAttribute(name) ?? "").indexOf("%") !== -1) return false;
8698
+ }
8699
+ return true;
8700
+ }
8701
+ function filterRegion(source, box) {
8702
+ const boundingBox = source.getAttribute("filterUnits") !== "userSpaceOnUse";
8703
+ const read = (name, size) => {
8704
+ const raw = (source.getAttribute(name) ?? (boundingBox ? REGION_DEFAULTS[name] : "")).trim();
8705
+ if (raw === "") return null;
8706
+ const percentage = raw.endsWith("%");
8707
+ const value = Number(percentage ? raw.slice(0, -1) : raw.replace(/px$/, ""));
8708
+ if (!Number.isFinite(value)) return null;
8709
+ if (boundingBox) return (percentage ? value / 100 : value) * size;
8710
+ return percentage ? null : value;
8711
+ };
8712
+ const x = read("x", box.width);
8713
+ const y = read("y", box.height);
8714
+ const width = read("width", box.width);
8715
+ const height = read("height", box.height);
8716
+ if (x === null || y === null || width === null || height === null || width <= 0 || height <= 0) return null;
8717
+ return {
8718
+ x,
8719
+ y,
8720
+ width,
8721
+ height
8722
+ };
8723
+ }
8724
+ function inlinePresentation(source, copy) {
8725
+ const view = source.ownerDocument.defaultView;
8726
+ if (!view) return;
8727
+ const sources = [source, ...Array.from(source.querySelectorAll("*"))];
8728
+ const copies = [copy, ...Array.from(copy.querySelectorAll("*"))];
8729
+ sources.forEach((node, index) => {
8730
+ const style = view.getComputedStyle(node);
8731
+ for (const property of PRESENTATION_PROPERTIES) {
8732
+ const value = style.getPropertyValue(property);
8733
+ if (value) copies[index]?.setAttribute(property, value);
8734
+ }
8735
+ });
8736
+ }
8737
+ // src/dom/element-container.ts
8678
8738
  var ElementContainer = class {
8679
8739
  context;
8680
8740
  styles;
@@ -8687,6 +8747,11 @@ var ElementContainer = class {
8687
8747
  * bounds to leave a matching gap (issue #227).
8688
8748
  */
8689
8749
  legendBounds;
8750
+ /**
8751
+ * Same-document `filter: url(#id)` references, resolved while the cloned
8752
+ * DOM is available. The surface compositor renders them in an SVG pass.
8753
+ */
8754
+ filterReferences;
8690
8755
  createsStackingContext = false;
8691
8756
  createsRealStackingContext = false;
8692
8757
  isListOwner = false;
@@ -8711,6 +8776,7 @@ var ElementContainer = class {
8711
8776
  this.bounds = new Bounds(this.bounds.left, borderBoxTop, this.bounds.width, this.bounds.height - (borderBoxTop - this.bounds.top));
8712
8777
  }
8713
8778
  }
8779
+ this.filterReferences = resolveFilterReferences(element, this.styles.filter, this.bounds);
8714
8780
  if (isDebugging(element, 4)) this.debugRender = true;
8715
8781
  }
8716
8782
  /**
@@ -8733,8 +8799,7 @@ var ElementContainer = class {
8733
8799
  for (const child of this.elements) child.restoreTree();
8734
8800
  }
8735
8801
  };
8736
- //#endregion
8737
- //#region src/core/features.ts
8802
+ // src/core/features.ts
8738
8803
  /**
8739
8804
  * Runtime feature detection.
8740
8805
  *
@@ -8820,8 +8885,7 @@ const FEATURES = {
8820
8885
  return value;
8821
8886
  }
8822
8887
  };
8823
- //#endregion
8824
- //#region src/css/layout/text.ts
8888
+ // src/css/layout/text.ts
8825
8889
  var TextBounds = class {
8826
8890
  text;
8827
8891
  bounds;
@@ -8896,8 +8960,7 @@ const breakText = (value, styles) => {
8896
8960
  if (isVerticalWritingMode(styles.writingMode)) return segmentGraphemes(value);
8897
8961
  return styles.letterSpacing !== 0 ? segmentGraphemes(value) : segmentWords(value);
8898
8962
  };
8899
- //#endregion
8900
- //#region src/dom/text-container.ts
8963
+ // src/dom/text-container.ts
8901
8964
  var TextContainer = class {
8902
8965
  text;
8903
8966
  textBounds;
@@ -8920,8 +8983,7 @@ const capitalize = (m, p1, p2) => {
8920
8983
  if (m.length > 0) return p1 + p2.toUpperCase();
8921
8984
  return m;
8922
8985
  };
8923
- //#endregion
8924
- //#region src/dom/replaced-elements/image-element-container.ts
8986
+ // src/dom/replaced-elements/image-element-container.ts
8925
8987
  var ImageElementContainer = class extends ElementContainer {
8926
8988
  src;
8927
8989
  intrinsicWidth;
@@ -8934,8 +8996,7 @@ var ImageElementContainer = class extends ElementContainer {
8934
8996
  this.context.cache.addImage(this.src);
8935
8997
  }
8936
8998
  };
8937
- //#endregion
8938
- //#region src/dom/replaced-elements/canvas-element-container.ts
8999
+ // src/dom/replaced-elements/canvas-element-container.ts
8939
9000
  var CanvasElementContainer = class extends ElementContainer {
8940
9001
  canvas;
8941
9002
  intrinsicWidth;
@@ -8947,8 +9008,7 @@ var CanvasElementContainer = class extends ElementContainer {
8947
9008
  this.intrinsicHeight = canvas.height;
8948
9009
  }
8949
9010
  };
8950
- //#endregion
8951
- //#region src/dom/replaced-elements/svg-element-container.ts
9011
+ // src/dom/replaced-elements/svg-element-container.ts
8952
9012
  const BOX_OFFSET_PROPERTIES = [
8953
9013
  "position",
8954
9014
  "inset",
@@ -8998,8 +9058,7 @@ var SVGElementContainer = class extends ElementContainer {
8998
9058
  this.context.cache.addImage(this.svg);
8999
9059
  }
9000
9060
  };
9001
- //#endregion
9002
- //#region src/dom/elements/li-element-container.ts
9061
+ // src/dom/elements/li-element-container.ts
9003
9062
  var LIElementContainer = class extends ElementContainer {
9004
9063
  value;
9005
9064
  constructor(context, element, options = {}) {
@@ -9007,8 +9066,7 @@ var LIElementContainer = class extends ElementContainer {
9007
9066
  this.value = element.value;
9008
9067
  }
9009
9068
  };
9010
- //#endregion
9011
- //#region src/dom/elements/ol-element-container.ts
9069
+ // src/dom/elements/ol-element-container.ts
9012
9070
  var OLElementContainer = class extends ElementContainer {
9013
9071
  start;
9014
9072
  reversed;
@@ -9018,8 +9076,7 @@ var OLElementContainer = class extends ElementContainer {
9018
9076
  this.reversed = typeof element.reversed === "boolean" && element.reversed === true;
9019
9077
  }
9020
9078
  };
9021
- //#endregion
9022
- //#region src/dom/replaced-elements/input-element-container.ts
9079
+ // src/dom/replaced-elements/input-element-container.ts
9023
9080
  const CHECKBOX_BORDER_RADIUS = [{
9024
9081
  type: 15,
9025
9082
  flags: 0,
@@ -9074,8 +9131,7 @@ var InputElementContainer = class extends ElementContainer {
9074
9131
  }
9075
9132
  }
9076
9133
  };
9077
- //#endregion
9078
- //#region src/dom/elements/select-element-container.ts
9134
+ // src/dom/elements/select-element-container.ts
9079
9135
  var SelectElementContainer = class extends ElementContainer {
9080
9136
  value;
9081
9137
  constructor(context, element, options = {}) {
@@ -9084,8 +9140,7 @@ var SelectElementContainer = class extends ElementContainer {
9084
9140
  this.value = option ? option.text || "" : "";
9085
9141
  }
9086
9142
  };
9087
- //#endregion
9088
- //#region src/dom/elements/textarea-element-container.ts
9143
+ // src/dom/elements/textarea-element-container.ts
9089
9144
  var TextareaElementContainer = class extends ElementContainer {
9090
9145
  value;
9091
9146
  constructor(context, element, options = {}) {
@@ -9093,8 +9148,7 @@ var TextareaElementContainer = class extends ElementContainer {
9093
9148
  this.value = element.value;
9094
9149
  }
9095
9150
  };
9096
- //#endregion
9097
- //#region src/dom/replaced-elements/iframe-element-container.ts
9151
+ // src/dom/replaced-elements/iframe-element-container.ts
9098
9152
  var IFrameElementContainer = class extends ElementContainer {
9099
9153
  src;
9100
9154
  width;
@@ -9125,8 +9179,7 @@ var IFrameElementContainer = class extends ElementContainer {
9125
9179
  }
9126
9180
  }
9127
9181
  };
9128
- //#endregion
9129
- //#region src/dom/node-parser.ts
9182
+ // src/dom/node-parser.ts
9130
9183
  const LIST_OWNERS = [
9131
9184
  "OL",
9132
9185
  "UL",
@@ -9192,15 +9245,14 @@ const parseTree = (context, element, options = {}) => {
9192
9245
  return container;
9193
9246
  };
9194
9247
  const createsRealStackingContext = (node, container, root) => {
9195
- return container.styles.isPositionedWithZIndex() || container.styles.opacity < 1 || Boolean(container.styles.filter) || Boolean(container.styles.backdropFilter) || container.styles.maskImage.length > 0 || Boolean(container.styles.webkitBoxReflect) || container.styles.isolation === 1 || container.styles.isTransformed() || isBodyElement(node) && root.styles.isTransparent();
9248
+ return container.styles.isPositionedWithZIndex() || container.styles.opacity < 1 || Boolean(container.styles.filter) || Boolean(container.styles.backdropFilter) || container.styles.maskImage.length > 0 || Boolean(container.styles.webkitBoxReflect) || container.styles.isolation === 1 || container.styles.willChange === 1 || container.styles.contain === 1 || container.styles.isTransformed() || isBodyElement(node) && root.styles.isTransparent();
9196
9249
  };
9197
9250
  const createsStackingContext = (styles) => {
9198
9251
  if (styles.isPositioned() || styles.isFloating()) return true;
9199
9252
  if (styles.mixBlendMode !== MIX_BLEND_MODE$1.NORMAL) return true;
9200
9253
  return contains(styles.display, 268435456) || contains(styles.display, 33554432) || contains(styles.display, 536870912) || contains(styles.display, 134217728);
9201
9254
  };
9202
- //#endregion
9203
- //#region src/render/path.ts
9255
+ // src/render/path.ts
9204
9256
  const equalPath = (a, b) => {
9205
9257
  if (a.length === b.length) return a.some((v, i) => v === b[i]);
9206
9258
  return false;
@@ -9216,8 +9268,7 @@ const transformPath = (path, deltaX, deltaY, deltaW, deltaH) => {
9216
9268
  return point;
9217
9269
  });
9218
9270
  };
9219
- //#endregion
9220
- //#region src/render/vector.ts
9271
+ // src/render/vector.ts
9221
9272
  var Vector = class Vector {
9222
9273
  type;
9223
9274
  x;
@@ -9231,8 +9282,7 @@ var Vector = class Vector {
9231
9282
  return new Vector(this.x + deltaX, this.y + deltaY);
9232
9283
  }
9233
9284
  };
9234
- //#endregion
9235
- //#region src/render/bezier-curve.ts
9285
+ // src/render/bezier-curve.ts
9236
9286
  const lerp = (a, b, t) => {
9237
9287
  return new Vector(a.x + (b.x - a.x) * t, a.y + (b.y - a.y) * t);
9238
9288
  };
@@ -9266,8 +9316,7 @@ var BezierCurve = class BezierCurve {
9266
9316
  }
9267
9317
  };
9268
9318
  const isBezierCurve = (path) => path.type === 1;
9269
- //#endregion
9270
- //#region src/render/bound-curves.ts
9319
+ // src/render/bound-curves.ts
9271
9320
  var BoundCurves = class {
9272
9321
  topLeftBorderDoubleOuterBox;
9273
9322
  topRightBorderDoubleOuterBox;
@@ -9391,8 +9440,7 @@ const calculatePaddingBoxPath = (curves) => {
9391
9440
  curves.bottomLeftPaddingBox
9392
9441
  ];
9393
9442
  };
9394
- //#endregion
9395
- //#region src/render/effects.ts
9443
+ // src/render/effects.ts
9396
9444
  var TransformEffect = class {
9397
9445
  offsetX;
9398
9446
  offsetY;
@@ -9599,8 +9647,7 @@ const isOpacityEffect = (effect) => effect.type === 2;
9599
9647
  const isClipPathEffect = (effect) => effect.type === 3;
9600
9648
  const isBlendEffect = (effect) => effect.type === 4;
9601
9649
  const isFilterEffect = (effect) => effect.type === 5;
9602
- //#endregion
9603
- //#region src/render/stacking-context.ts
9650
+ // src/render/stacking-context.ts
9604
9651
  var StackingContext = class {
9605
9652
  element;
9606
9653
  negativeZIndex;
@@ -9923,8 +9970,7 @@ const parseStackingContexts = (container) => {
9923
9970
  processListItems(paintContainer.container, listItems);
9924
9971
  return root;
9925
9972
  };
9926
- //#endregion
9927
- //#region src/render/canvas/gradient-rasterizer.ts
9973
+ // src/render/canvas/gradient-rasterizer.ts
9928
9974
  const clampStop = (stop) => Math.min(1, Math.max(0, stop));
9929
9975
  /**
9930
9976
  * Stack the one-cycle stop list periodically across [0, 1]. Returns null for
@@ -10003,8 +10049,7 @@ const rasterizeRadialGradient = (ownerDocument, rx, ry, stops, repeating = false
10003
10049
  ry
10004
10050
  };
10005
10051
  };
10006
- //#endregion
10007
- //#region src/render/box-sizing.ts
10052
+ // src/render/box-sizing.ts
10008
10053
  const paddingBox = (element) => {
10009
10054
  const bounds = element.bounds;
10010
10055
  const styles = element.styles;
@@ -10019,8 +10064,7 @@ const contentBox = (element) => {
10019
10064
  const paddingBottom = getAbsoluteValue(styles.paddingBottom, bounds.width);
10020
10065
  return bounds.add(paddingLeft + styles.borderLeftWidth, paddingTop + styles.borderTopWidth, -(styles.borderRightWidth + styles.borderLeftWidth + paddingLeft + paddingRight), -(styles.borderTopWidth + styles.borderBottomWidth + paddingTop + paddingBottom));
10021
10066
  };
10022
- //#endregion
10023
- //#region src/render/background.ts
10067
+ // src/render/background.ts
10024
10068
  const calculateBackgroundPositioningArea = (backgroundOrigin, element) => {
10025
10069
  if (backgroundOrigin === 0) return element.bounds;
10026
10070
  if (backgroundOrigin === 2) return contentBox(element);
@@ -10121,8 +10165,7 @@ const calculateBackgroundRepeatPath = (repeat, [x, y], [width, height], backgrou
10121
10165
  ];
10122
10166
  }
10123
10167
  };
10124
- //#endregion
10125
- //#region src/render/canvas/filter-surface.ts
10168
+ // src/render/canvas/filter-surface.ts
10126
10169
  var FilterSurfaceError = class extends Error {};
10127
10170
  const releaseSurface = (canvas) => {
10128
10171
  canvas.width = canvas.height = 0;
@@ -10226,6 +10269,13 @@ const parseFilterFunction = (name, body) => {
10226
10269
  value: Number.parseFloat(numeric) * (percentage ? 1 / 100 : 1)
10227
10270
  };
10228
10271
  }
10272
+ if (name === "url") {
10273
+ const ref = parseFilterReference(body);
10274
+ return ref ? {
10275
+ kind: "url",
10276
+ ref
10277
+ } : null;
10278
+ }
10229
10279
  return null;
10230
10280
  };
10231
10281
  /** Split on whitespace outside parentheses so rgba(...) colours stay one token. */
@@ -10281,22 +10331,25 @@ const nativeFilterString = (filter, scale) => filter.functions.map((fn) => {
10281
10331
  case "blur": return `blur(${fn.value * scale}px)`;
10282
10332
  case "drop-shadow": return `drop-shadow(${fn.x * scale}px ${fn.y * scale}px ${fn.blur * scale}px ${fn.color})`;
10283
10333
  case "unitless": return fn.name === "hue-rotate" ? `hue-rotate(${fn.value}deg)` : `${fn.name}(${fn.value})`;
10334
+ case "url": return `url("${fn.ref}")`;
10284
10335
  }
10285
10336
  }).join(" ");
10286
10337
  /**
10287
10338
  * Outset (in CSS pixels) a surface must grow so blur/shadow spillover is not
10288
10339
  * cropped. Unitless functions never spread beyond the bounds. Consecutive
10289
- * blurs compound, so their radii sum.
10340
+ * blurs compound, so their radii sum. A url() reference can paint up to its
10341
+ * filter region, which may extend beyond the border box.
10290
10342
  */
10291
- function filterOutset(filter) {
10343
+ function filterOutset(filter, references) {
10292
10344
  let blurSum = 0;
10293
10345
  let maxShadowOffset = 0;
10346
+ let referenceOutset = 0;
10294
10347
  for (const fn of filter.functions) if (fn.kind === "blur") blurSum += fn.value;
10295
10348
  else if (fn.kind === "drop-shadow") {
10296
10349
  blurSum += fn.blur;
10297
10350
  maxShadowOffset = Math.max(maxShadowOffset, Math.abs(fn.x), Math.abs(fn.y));
10298
- }
10299
- return Math.ceil(3 * blurSum + maxShadowOffset);
10351
+ } else if (fn.kind === "url") referenceOutset += references?.get(fn.ref)?.outset ?? 0;
10352
+ return Math.ceil(3 * blurSum + maxShadowOffset + referenceOutset);
10300
10353
  }
10301
10354
  function canvasLike(source) {
10302
10355
  const canvas = (source.ownerDocument ?? document).createElement("canvas");
@@ -10392,8 +10445,9 @@ const isSvgExpressible = (filter) => {
10392
10445
  if (blurs > 0 && shadows > 0) return filter.functions.findIndex((fn) => fn.kind === "blur") < filter.functions.findIndex((fn) => fn.kind === "drop-shadow");
10393
10446
  return true;
10394
10447
  };
10395
- async function renderFilterSurface(source, filter, opacity, scale, signal) {
10448
+ async function renderFilterSurface(source, filter, opacity, scale, signal, references) {
10396
10449
  throwIfAborted(signal);
10450
+ if (filter.functions.some((fn) => fn.kind === "url")) return renderReferencedFilterSurface(source, filter, opacity, scale, signal, references);
10397
10451
  if (filter.functions.length > 0 && supportsNativeFilters(source.ownerDocument ?? document)) {
10398
10452
  const output = tryNativeFilterSurface(source, filter, opacity, scale, signal);
10399
10453
  if (output) return output;
@@ -10401,6 +10455,136 @@ async function renderFilterSurface(source, filter, opacity, scale, signal) {
10401
10455
  if (!isSvgExpressible(filter)) throw new FilterSurfaceError("Filter chain requires native canvas filters");
10402
10456
  return renderSvgFilterSurface(source, filter, opacity, scale, signal);
10403
10457
  }
10458
+ /**
10459
+ * Split a chain at its url() references: each reference is one SVG pass, and
10460
+ * the standard functions between them run through the usual backends. Every
10461
+ * step filters the previous step's complete output at alpha 1, then CSS
10462
+ * opacity is applied once, as for any other chain.
10463
+ */
10464
+ async function renderReferencedFilterSurface(source, filter, opacity, scale, signal, context) {
10465
+ const steps = [];
10466
+ for (const fn of filter.functions) {
10467
+ if (fn.kind === "url") {
10468
+ const reference = context?.references?.get(fn.ref);
10469
+ if (!reference) throw new FilterSurfaceError(`Filter reference ${fn.ref} cannot be resolved`);
10470
+ steps.push(reference);
10471
+ continue;
10472
+ }
10473
+ const last = steps[steps.length - 1];
10474
+ if (Array.isArray(last)) last.push(fn);
10475
+ else steps.push([fn]);
10476
+ }
10477
+ const origin = context?.origin ?? {
10478
+ x: 0,
10479
+ y: 0
10480
+ };
10481
+ const last = steps[steps.length - 1];
10482
+ const opacityApplied = Array.isArray(last);
10483
+ let current = source;
10484
+ try {
10485
+ for (const step of steps) {
10486
+ const next = Array.isArray(step) ? await renderFilterSurface(current, { functions: step }, step === last ? opacity : 1, scale, signal) : await renderReferenceSurface(current, step, origin, scale, signal);
10487
+ if (current !== source) releaseSurface(current);
10488
+ current = next;
10489
+ }
10490
+ if (opacityApplied || opacity === 1) {
10491
+ const output = current;
10492
+ current = source;
10493
+ return output;
10494
+ }
10495
+ return drawWithOpacity(current, opacity);
10496
+ } finally {
10497
+ if (current !== source) releaseSurface(current);
10498
+ }
10499
+ }
10500
+ function drawWithOpacity(source, opacity) {
10501
+ const output = canvasLike(source);
10502
+ const context = output.getContext("2d");
10503
+ if (!context) {
10504
+ releaseSurface(output);
10505
+ throw new FilterSurfaceError("Filter surface canvas is unavailable");
10506
+ }
10507
+ context.globalAlpha = opacity;
10508
+ try {
10509
+ context.drawImage(source, 0, 0);
10510
+ return output;
10511
+ } catch {
10512
+ releaseSurface(output);
10513
+ throw new FilterSurfaceError("Filter surface image cannot be drawn");
10514
+ }
10515
+ }
10516
+ const SVG_NS = "http://www.w3.org/2000/svg";
10517
+ function createSvgElement(owner, tag, attributes = {}) {
10518
+ const node = owner.createElementNS(SVG_NS, tag);
10519
+ Object.entries(attributes).forEach(([key, value]) => node.setAttribute(key, String(value)));
10520
+ return node;
10521
+ }
10522
+ function serializeSurface(source) {
10523
+ try {
10524
+ const url = source.toDataURL("image/png");
10525
+ if (url === "data:,") throw new Error("Canvas size is unsupported");
10526
+ return url;
10527
+ } catch {
10528
+ throw new FilterSurfaceError("Filter surface pixels cannot be serialized");
10529
+ }
10530
+ }
10531
+ /** Decode a filtered SVG image and draw it onto a surface-sized canvas. */
10532
+ async function drawSvgSurface(svg, source, opacity, signal) {
10533
+ const imageWindow = (source.ownerDocument ?? document).defaultView;
10534
+ const image = imageWindow?.Image ? new imageWindow.Image() : new Image();
10535
+ let output;
10536
+ try {
10537
+ image.src = `data:image/svg+xml,${encodeURIComponent(new XMLSerializer().serializeToString(svg))}`;
10538
+ await decodeSurface(image, signal);
10539
+ throwIfAborted(signal);
10540
+ output = canvasLike(source);
10541
+ const context = output.getContext("2d");
10542
+ if (!context) throw new FilterSurfaceError("Filter surface canvas is unavailable");
10543
+ context.globalAlpha = opacity;
10544
+ context.drawImage(image, 0, 0);
10545
+ return output;
10546
+ } catch (error) {
10547
+ if (output) releaseSurface(output);
10548
+ if (signal?.aborted) throwIfAborted(signal);
10549
+ throw error instanceof FilterSurfaceError ? error : new FilterSurfaceError("Filter surface image cannot be drawn");
10550
+ } finally {
10551
+ image.removeAttribute("src");
10552
+ }
10553
+ }
10554
+ /**
10555
+ * Apply a referenced SVG filter to the complete surface. The viewBox is in CSS
10556
+ * pixels, so the filter's user units scale with the capture, and the image is
10557
+ * placed so user space starts at the element's border box, as it does for the
10558
+ * live element. Canvas filters cannot express either: their lengths are in
10559
+ * device pixels and their bounding box is the whole canvas.
10560
+ */
10561
+ async function renderReferenceSurface(source, reference, origin, scale, signal) {
10562
+ throwIfAborted(signal);
10563
+ const owner = source.ownerDocument ?? document;
10564
+ const width = source.width / scale;
10565
+ const height = source.height / scale;
10566
+ const svg = createSvgElement(owner, "svg", {
10567
+ width: source.width,
10568
+ height: source.height,
10569
+ viewBox: `0 0 ${width} ${height}`
10570
+ });
10571
+ const defs = createSvgElement(owner, "defs");
10572
+ const filterElement = owner.importNode(reference.element, true);
10573
+ filterElement.setAttribute("id", "composited-reference");
10574
+ defs.appendChild(filterElement);
10575
+ svg.appendChild(defs);
10576
+ const group = createSvgElement(owner, "g", { transform: `translate(${origin.x} ${origin.y})` });
10577
+ group.appendChild(createSvgElement(owner, "image", {
10578
+ x: -origin.x,
10579
+ y: -origin.y,
10580
+ width,
10581
+ height,
10582
+ href: serializeSurface(source),
10583
+ filter: "url(#composited-reference)"
10584
+ }));
10585
+ svg.appendChild(group);
10586
+ return drawSvgSurface(svg, source, 1, signal);
10587
+ }
10404
10588
  async function renderSvgFilterSurface(source, filter, opacity, scale, signal) {
10405
10589
  throwIfAborted(signal);
10406
10590
  const blur = filter.functions.find((fn) => fn.kind === "blur");
@@ -10412,29 +10596,9 @@ async function renderSvgFilterSurface(source, filter, opacity, scale, signal) {
10412
10596
  blur: shadow.blur,
10413
10597
  color: shadow.color
10414
10598
  } : void 0;
10415
- if (!blurValue && !shadowValue) {
10416
- const output = canvasLike(source);
10417
- const context = output.getContext("2d");
10418
- if (!context) {
10419
- releaseSurface(output);
10420
- throw new FilterSurfaceError("Filter surface canvas is unavailable");
10421
- }
10422
- context.globalAlpha = opacity;
10423
- try {
10424
- context.drawImage(source, 0, 0);
10425
- return output;
10426
- } catch {
10427
- releaseSurface(output);
10428
- throw new FilterSurfaceError("Filter surface image cannot be drawn");
10429
- }
10430
- }
10431
- const namespace = "http://www.w3.org/2000/svg";
10599
+ if (!blurValue && !shadowValue) return drawWithOpacity(source, opacity);
10432
10600
  const svgDocument = source.ownerDocument ?? document;
10433
- const element = (tag, attributes = {}) => {
10434
- const node = svgDocument.createElementNS(namespace, tag);
10435
- Object.entries(attributes).forEach(([key, value]) => node.setAttribute(key, String(value)));
10436
- return node;
10437
- };
10601
+ const element = (tag, attributes = {}) => createSvgElement(svgDocument, tag, attributes);
10438
10602
  const svg = element("svg", {
10439
10603
  width: source.width,
10440
10604
  height: source.height,
@@ -10476,39 +10640,13 @@ async function renderSvgFilterSurface(source, filter, opacity, scale, signal) {
10476
10640
  }
10477
10641
  defs.appendChild(filterElement);
10478
10642
  svg.appendChild(defs);
10479
- let sourceUrl;
10480
- try {
10481
- sourceUrl = source.toDataURL("image/png");
10482
- if (sourceUrl === "data:,") throw new Error("Canvas size is unsupported");
10483
- } catch {
10484
- throw new FilterSurfaceError("Filter surface pixels cannot be serialized");
10485
- }
10486
10643
  svg.appendChild(element("image", {
10487
10644
  width: source.width,
10488
10645
  height: source.height,
10489
- href: sourceUrl,
10646
+ href: serializeSurface(source),
10490
10647
  filter: "url(#composited-filter)"
10491
10648
  }));
10492
- const imageWindow = svgDocument.defaultView;
10493
- const image = imageWindow?.Image ? new imageWindow.Image() : new Image();
10494
- let output;
10495
- try {
10496
- image.src = `data:image/svg+xml,${encodeURIComponent(new XMLSerializer().serializeToString(svg))}`;
10497
- await decodeSurface(image, signal);
10498
- throwIfAborted(signal);
10499
- output = canvasLike(source);
10500
- const context = output.getContext("2d");
10501
- if (!context) throw new FilterSurfaceError("Filter surface canvas is unavailable");
10502
- context.globalAlpha = opacity;
10503
- context.drawImage(image, 0, 0);
10504
- return output;
10505
- } catch (error) {
10506
- if (output) releaseSurface(output);
10507
- if (signal?.aborted) throwIfAborted(signal);
10508
- throw error instanceof FilterSurfaceError ? error : new FilterSurfaceError("Filter surface image cannot be drawn");
10509
- } finally {
10510
- image.removeAttribute("src");
10511
- }
10649
+ return drawSvgSurface(svg, source, opacity, signal);
10512
10650
  }
10513
10651
  function reserveSurface(budget, width, height) {
10514
10652
  const pixels = width * height * 4;
@@ -10532,7 +10670,7 @@ function surfaceBounds(container) {
10532
10670
  }
10533
10671
  for (const child of container.elements) if (child.styles.isVisible()) bounds = union(bounds, surfaceBounds(child));
10534
10672
  const filter = parseFilterChain(styles.filter);
10535
- return expand(bounds, filter ? filterOutset(filter) : 0);
10673
+ return expand(bounds, filter ? filterOutset(filter, container.filterReferences) : 0);
10536
10674
  }
10537
10675
  function cropSurface(bounds, viewport, margin, scale) {
10538
10676
  const area = expand(viewport, margin);
@@ -10542,8 +10680,91 @@ function cropSurface(bounds, viewport, margin, scale) {
10542
10680
  const bottom = Math.ceil(Math.min(bounds.top + bounds.height, area.top + area.height) * scale) / scale;
10543
10681
  return new Bounds(left, top, Math.max(0, right - left), Math.max(0, bottom - top));
10544
10682
  }
10545
- //#endregion
10546
- //#region src/render/canvas/text/text-decoration-renderer.ts
10683
+ // src/render/matrix.ts
10684
+ /**
10685
+ * 2D affine matrix utilities for the composited-surface render path.
10686
+ *
10687
+ * Matrices use the canvas `transform(a, b, c, d, e, f)` column-vector
10688
+ * convention:
10689
+ *
10690
+ * | a c e | | x' | | a·x + c·y + e |
10691
+ * | b d f | × | y' | = | b·x + d·y + f |
10692
+ * | 0 0 1 | | 1 | | 1 |
10693
+ *
10694
+ * `TransformEffect` carries the same tuple order, so effects and bounds can
10695
+ * share these helpers. Composition follows the canvas post-multiply rule:
10696
+ * `multiplyMatrix(ancestor, own)` equals `ancestor` followed by `own`.
10697
+ */
10698
+ const IDENTITY_MATRIX = [
10699
+ 1,
10700
+ 0,
10701
+ 0,
10702
+ 1,
10703
+ 0,
10704
+ 0
10705
+ ];
10706
+ const isIdentityMatrix = (m) => m[0] === 1 && m[1] === 0 && m[2] === 0 && m[3] === 1 && m[4] === 0 && m[5] === 0;
10707
+ /**
10708
+ * Compose two transforms: the result applies `a` first, then `b`
10709
+ * (canvas post-multiply, matching successive `ctx.transform` calls).
10710
+ */
10711
+ const multiplyMatrix = (a, b) => [
10712
+ a[0] * b[0] + a[2] * b[1],
10713
+ a[1] * b[0] + a[3] * b[1],
10714
+ a[0] * b[2] + a[2] * b[3],
10715
+ a[1] * b[2] + a[3] * b[3],
10716
+ a[0] * b[4] + a[2] * b[5] + a[4],
10717
+ a[1] * b[4] + a[3] * b[5] + a[5]
10718
+ ];
10719
+ /** Apply a matrix to a point, returning the mapped [x, y]. */
10720
+ const applyMatrixToPoint = (m, x, y) => [m[0] * x + m[2] * y + m[4], m[1] * x + m[3] * y + m[5]];
10721
+ /**
10722
+ * Map a layout-space Bounds through the matrix and return the axis-aligned
10723
+ * bounding box of the four transformed corners. Non-uniform scales and
10724
+ * rotations grow the box; this is intentionally conservative.
10725
+ */
10726
+ const transformBoundsToAabb = (m, bounds) => {
10727
+ const corners = [
10728
+ applyMatrixToPoint(m, bounds.left, bounds.top),
10729
+ applyMatrixToPoint(m, bounds.left + bounds.width, bounds.top),
10730
+ applyMatrixToPoint(m, bounds.left, bounds.top + bounds.height),
10731
+ applyMatrixToPoint(m, bounds.left + bounds.width, bounds.top + bounds.height)
10732
+ ];
10733
+ const left = Math.min(...corners.map((p) => p[0]));
10734
+ const right = Math.max(...corners.map((p) => p[0]));
10735
+ const top = Math.min(...corners.map((p) => p[1]));
10736
+ const bottom = Math.max(...corners.map((p) => p[1]));
10737
+ return new Bounds(left, top, right - left, bottom - top);
10738
+ };
10739
+ /**
10740
+ * Invert an affine matrix. Returns null for singular matrices
10741
+ * (zero-scale transforms have no meaningful inverse).
10742
+ */
10743
+ const invertMatrix = (m) => {
10744
+ const det = m[0] * m[3] - m[1] * m[2];
10745
+ if (!Number.isFinite(det) || det === 0) return null;
10746
+ const invDet = 1 / det;
10747
+ return [
10748
+ m[3] * invDet,
10749
+ -m[1] * invDet,
10750
+ -m[2] * invDet,
10751
+ m[0] * invDet,
10752
+ (m[2] * m[5] - m[3] * m[4]) * invDet,
10753
+ (m[1] * m[4] - m[0] * m[5]) * invDet
10754
+ ];
10755
+ };
10756
+ /**
10757
+ * Map a visual-space viewport back into the layout space of `m`'s inputs.
10758
+ * Used where a crop window (visual coordinates) must select content measured
10759
+ * in layout coordinates: the conservative answer is the AABB of the inverse
10760
+ * viewport corners.
10761
+ */
10762
+ const inverseTransformBoundsToAabb = (m, bounds) => {
10763
+ const inverse = invertMatrix(m);
10764
+ if (!inverse) return null;
10765
+ return transformBoundsToAabb(inverse, bounds);
10766
+ };
10767
+ // src/render/canvas/text/text-decoration-renderer.ts
10547
10768
  var TextDecorationRenderer = class {
10548
10769
  ctx;
10549
10770
  constructor(ctx) {
@@ -10631,8 +10852,7 @@ var TextDecorationRenderer = class {
10631
10852
  this.ctx.restore();
10632
10853
  }
10633
10854
  };
10634
- //#endregion
10635
- //#region src/render/canvas/font-utils.ts
10855
+ // src/render/canvas/font-utils.ts
10636
10856
  /**
10637
10857
  * Font measurement utility
10638
10858
  *
@@ -10667,8 +10887,7 @@ const measureFontMetrics = (ctx, fallback) => {
10667
10887
  const measureBaseline = (ctx, fallback) => {
10668
10888
  return measureFontMetrics(ctx, fallback).baseline;
10669
10889
  };
10670
- //#endregion
10671
- //#region src/render/canvas/text-renderer.ts
10890
+ // src/render/canvas/text-renderer.ts
10672
10891
  const TEXT_OVERFLOW_EPSILON = 1;
10673
10892
  /**
10674
10893
  * Detect CJK (Chinese, Japanese, Korean) characters in a string.
@@ -11094,8 +11313,7 @@ var TextRenderer = class {
11094
11313
  }
11095
11314
  }
11096
11315
  };
11097
- //#endregion
11098
- //#region src/render/canvas/canvas-path.ts
11316
+ // src/render/canvas/canvas-path.ts
11099
11317
  const formatCanvasPath = (ctx, paths) => {
11100
11318
  paths.forEach((point, index) => {
11101
11319
  const start = isBezierCurve(point) ? point.start : point;
@@ -11109,8 +11327,7 @@ const createCanvasPath = (ctx, paths) => {
11109
11327
  formatCanvasPath(ctx, paths);
11110
11328
  ctx.closePath();
11111
11329
  };
11112
- //#endregion
11113
- //#region src/core/lru-map.ts
11330
+ // src/core/lru-map.ts
11114
11331
  /**
11115
11332
  * Generic LRU (Least-Recently-Used) wrapper over a native `Map`.
11116
11333
  *
@@ -11168,8 +11385,7 @@ var LRUMap = class {
11168
11385
  this._map.clear();
11169
11386
  }
11170
11387
  };
11171
- //#endregion
11172
- //#region src/render/canvas/background-renderer.ts
11388
+ // src/render/canvas/background-renderer.ts
11173
11389
  /**
11174
11390
  * Background Renderer
11175
11391
  *
@@ -11532,8 +11748,7 @@ var BackgroundRenderer = class {
11532
11748
  createCanvasPath(this.ctx, paths);
11533
11749
  }
11534
11750
  };
11535
- //#endregion
11536
- //#region src/render/border.ts
11751
+ // src/render/border.ts
11537
11752
  const parsePathForBorder = (curves, borderSide) => {
11538
11753
  switch (borderSide) {
11539
11754
  case 0: return createPathFromCurves(curves.topLeftBorderBox, curves.topLeftPaddingBox, curves.topRightBorderBox, curves.topRightPaddingBox);
@@ -11586,8 +11801,7 @@ const createPathFromCurves = (outer1, inner1, outer2, inner2) => {
11586
11801
  else path.push(inner1);
11587
11802
  return path;
11588
11803
  };
11589
- //#endregion
11590
- //#region src/render/canvas/border-renderer.ts
11804
+ // src/render/canvas/border-renderer.ts
11591
11805
  /**
11592
11806
  * Border Renderer
11593
11807
  *
@@ -11721,8 +11935,7 @@ var BorderRenderer = class {
11721
11935
  this.ctx.restore();
11722
11936
  }
11723
11937
  };
11724
- //#endregion
11725
- //#region src/render/canvas/border-image-renderer.ts
11938
+ // src/render/canvas/border-image-renderer.ts
11726
11939
  /**
11727
11940
  * Resolve border-image-width to per-side pixel widths. `auto` uses the
11728
11941
  * corresponding border width, numbers multiply it, lengths are absolute and
@@ -11930,8 +12143,7 @@ var BorderImageRenderer = class {
11930
12143
  this.ctx.restore();
11931
12144
  }
11932
12145
  };
11933
- //#endregion
11934
- //#region src/render/canvas/effects-renderer.ts
12146
+ // src/render/canvas/effects-renderer.ts
11935
12147
  /**
11936
12148
  * Effects Renderer
11937
12149
  *
@@ -12079,8 +12291,7 @@ var EffectsRenderer = class {
12079
12291
  return this.activeEffects.length > 0;
12080
12292
  }
12081
12293
  };
12082
- //#endregion
12083
- //#region src/render/canvas/mask-renderer.ts
12294
+ // src/render/canvas/mask-renderer.ts
12084
12295
  /**
12085
12296
  * Mask Renderer
12086
12297
  *
@@ -12227,8 +12438,7 @@ const paintMaskLayers = async (ctx, layers, styles, area, matchImage) => {
12227
12438
  } else paintGradientLayer(ctx, layer, area);
12228
12439
  }
12229
12440
  };
12230
- //#endregion
12231
- //#region src/render/object-fit.ts
12441
+ // src/render/object-fit.ts
12232
12442
  const calculateObjectFitRendering = (intrinsicWidth, intrinsicHeight, box, objectFit, objectPosition) => {
12233
12443
  let sx = 0;
12234
12444
  let sy = 0;
@@ -12314,8 +12524,7 @@ const calculateObjectFitRendering = (intrinsicWidth, intrinsicHeight, box, objec
12314
12524
  dh
12315
12525
  };
12316
12526
  };
12317
- //#endregion
12318
- //#region src/render/canvas/content-renderer.ts
12527
+ // src/render/canvas/content-renderer.ts
12319
12528
  /**
12320
12529
  * Render replaced elements: Image, Canvas, SVG, IFrame.
12321
12530
  */
@@ -12536,8 +12745,7 @@ const canvasTextAlign = (textAlign) => {
12536
12745
  default: return "left";
12537
12746
  }
12538
12747
  };
12539
- //#endregion
12540
- //#region src/render/canvas/box-shadow-geometry.ts
12748
+ // src/render/canvas/box-shadow-geometry.ts
12541
12749
  const shadowRadius = (radius, spread) => {
12542
12750
  const delta = spread > radius ? spread * (1 + Math.pow(radius / spread - 1, 3)) : spread;
12543
12751
  return Math.max(0, radius + delta);
@@ -12581,8 +12789,7 @@ const spreadShadowPath = (paths, spread) => {
12581
12789
  return new BezierCurve(resize(point.start), resize(point.startControl), resize(point.endControl), resize(point.end));
12582
12790
  });
12583
12791
  };
12584
- //#endregion
12585
- //#region src/render/canvas/box-shadow-transform.ts
12792
+ // src/render/canvas/box-shadow-transform.ts
12586
12793
  const shadowSpace = (matrix, width, height) => {
12587
12794
  const { a, b, c, d, e, f } = matrix;
12588
12795
  if (![
@@ -12625,8 +12832,7 @@ const shadowSpace = (matrix, width, height) => {
12625
12832
  uniform: Math.abs(xx - yy) <= tolerance && Math.abs(xy) <= tolerance
12626
12833
  };
12627
12834
  };
12628
- //#endregion
12629
- //#region src/render/canvas/box-shadow-painter.ts
12835
+ // src/render/canvas/box-shadow-painter.ts
12630
12836
  const complement = (ctx, rect, hole) => {
12631
12837
  ctx.beginPath();
12632
12838
  ctx.rect(rect.left, rect.top, rect.width, rect.height);
@@ -12754,8 +12960,7 @@ const paintBoxShadow = async (ctx, paint, shadow, options, budget) => {
12754
12960
  ctx.restore();
12755
12961
  }
12756
12962
  };
12757
- //#endregion
12758
- //#region src/render/canvas/text-clip-renderer.ts
12963
+ // src/render/canvas/text-clip-renderer.ts
12759
12964
  var TextClipRenderer = class {
12760
12965
  ctx;
12761
12966
  context;
@@ -12915,8 +13120,7 @@ var TextClipRenderer = class {
12915
13120
  return canvases.length ? canvases : null;
12916
13121
  }
12917
13122
  };
12918
- //#endregion
12919
- //#region src/render/canvas/canvas-renderer.ts
13123
+ // src/render/canvas/canvas-renderer.ts
12920
13124
  var CanvasRenderer = class CanvasRenderer {
12921
13125
  surfaceRoot;
12922
13126
  surfaceBudget;
@@ -12994,7 +13198,9 @@ var CanvasRenderer = class CanvasRenderer {
12994
13198
  const hasMask = styles.maskImage.length > 0;
12995
13199
  const reflect = styles.webkitBoxReflect;
12996
13200
  const hasBlend = styles.mixBlendMode !== MIX_BLEND_MODE$1.NORMAL;
12997
- if (stack.element !== this.surfaceRoot && !this.legacySubtree && (hasMask || reflect || hasBlend || filter !== null && (hasFilter || styles.opacity < 1)) && this.canComposite(stack.element)) {
13201
+ const reflectTransformed = reflect && !isIdentityMatrix(this.ancestorTransform(stack.element));
13202
+ if (reflectTransformed) this.context.logger.warn("-webkit-box-reflect under an ancestor transform is not supported; the reflection is skipped for this subtree");
13203
+ if (stack.element !== this.surfaceRoot && !this.legacySubtree && !reflectTransformed && (hasMask || reflect || hasBlend || filter !== null && (hasFilter || styles.opacity < 1)) && this.canComposite(stack.element)) {
12998
13204
  if (!await this.renderCompositedStack(stack, filter, hasMask, reflect, hasBlend)) {
12999
13205
  this.legacySubtree = true;
13000
13206
  try {
@@ -13011,7 +13217,7 @@ var CanvasRenderer = class CanvasRenderer {
13011
13217
  canComposite(paint) {
13012
13218
  const supported = (container) => {
13013
13219
  const styles = container.styles;
13014
- return !styles.isTransformed() && styles.zoom === 1 && styles.clipPath.type === 0 && !contains(styles.display, 2048) && parseFilterChain(styles.filter) !== null;
13220
+ return styles.clipPath.type === 0 && !contains(styles.display, 2048) && parseFilterChain(styles.filter) !== null;
13015
13221
  };
13016
13222
  const subtree = (container) => supported(container) && container.elements.every(subtree);
13017
13223
  let ancestor = paint.parent;
@@ -13021,24 +13227,82 @@ var CanvasRenderer = class CanvasRenderer {
13021
13227
  }
13022
13228
  return subtree(paint.container);
13023
13229
  }
13230
+ /**
13231
+ * Root-to-element transform accumulated from the ancestor chain's
13232
+ * TransformEffects (including zoom), stopping at the surface root. The
13233
+ * element's own TransformEffect is intentionally excluded: inside the
13234
+ * offscreen surface it is still applied by the normal effects pass, and
13235
+ * at composition time it is filtered from the recomposed effect list.
13236
+ */
13237
+ ancestorTransform(paint) {
13238
+ const chain = [];
13239
+ let node = paint;
13240
+ while (node && node !== this.surfaceRoot) {
13241
+ for (const effect of node.effects) if (isTransformEffect(effect)) chain.push(effect);
13242
+ node = node.parent;
13243
+ }
13244
+ if (chain.length === 0) return IDENTITY_MATRIX;
13245
+ let matrix = IDENTITY_MATRIX;
13246
+ for (let i = chain.length - 1; i >= 0; i--) {
13247
+ const effect = at(chain, i);
13248
+ const anchored = multiplyMatrix(multiplyMatrix([
13249
+ 1,
13250
+ 0,
13251
+ 0,
13252
+ 1,
13253
+ effect.offsetX,
13254
+ effect.offsetY
13255
+ ], effect.matrix), [
13256
+ 1,
13257
+ 0,
13258
+ 0,
13259
+ 1,
13260
+ -effect.offsetX,
13261
+ -effect.offsetY
13262
+ ]);
13263
+ matrix = multiplyMatrix(matrix, anchored);
13264
+ }
13265
+ return matrix;
13266
+ }
13024
13267
  async renderCompositedStack(stack, filter, hasMask, reflect, hasBlend = false) {
13025
13268
  const signal = this.options.signal;
13026
13269
  if (signal?.aborted) throw new DOMException("The operation was aborted.", "AbortError");
13027
- const bounds = cropSurface(surfaceBounds(stack.element.container), new Bounds(this.options.x, this.options.y, this.options.width, this.options.height), filter ? filterOutset(filter) : 0, this.options.scale);
13270
+ const container = stack.element.container;
13271
+ const ancestorMatrix = this.ancestorTransform(stack.element);
13272
+ const ownTransforms = stack.element.effects.filter(isTransformEffect);
13273
+ let chainMatrix = ancestorMatrix;
13274
+ for (const effect of ownTransforms) chainMatrix = multiplyMatrix(chainMatrix, multiplyMatrix(multiplyMatrix([
13275
+ 1,
13276
+ 0,
13277
+ 0,
13278
+ 1,
13279
+ effect.offsetX,
13280
+ effect.offsetY
13281
+ ], effect.matrix), [
13282
+ 1,
13283
+ 0,
13284
+ 0,
13285
+ 1,
13286
+ -effect.offsetX,
13287
+ -effect.offsetY
13288
+ ]));
13289
+ const layoutBounds = surfaceBounds(container);
13290
+ const bounds = cropSurface(isIdentityMatrix(chainMatrix) ? layoutBounds : transformBoundsToAabb(chainMatrix, layoutBounds), new Bounds(this.options.x, this.options.y, this.options.width, this.options.height), filter ? filterOutset(filter, container.filterReferences) : 0, this.options.scale);
13028
13291
  if (!bounds.width || !bounds.height) return true;
13029
13292
  const reserved = reserveSurface(this.surfaceBudget, Math.ceil(bounds.width * this.options.scale), Math.ceil(bounds.height * this.options.scale));
13030
13293
  if (!reserved) {
13031
- this.context.logger.info("Filter surface budget exceeded; using the existing renderer");
13294
+ this.context.logger.warn("Filter surface budget exceeded; mask/filter/blend effects are dropped for this subtree");
13032
13295
  return false;
13033
13296
  }
13297
+ const surfaceWindow = isIdentityMatrix(ancestorMatrix) || !hasMask ? bounds : inverseTransformBoundsToAabb(ancestorMatrix, bounds) ?? bounds;
13034
13298
  const options = {
13035
13299
  ...this.options,
13036
13300
  canvas: void 0,
13037
13301
  backgroundColor: null,
13038
- x: bounds.left,
13039
- y: bounds.top,
13040
- width: bounds.width,
13041
- height: bounds.height
13302
+ x: surfaceWindow.left,
13303
+ y: surfaceWindow.top,
13304
+ width: surfaceWindow.width,
13305
+ height: surfaceWindow.height
13042
13306
  };
13043
13307
  let source;
13044
13308
  let filtered;
@@ -13046,12 +13310,18 @@ var CanvasRenderer = class CanvasRenderer {
13046
13310
  source = new CanvasRenderer(this.context, options, stack.element, this.surfaceBudget);
13047
13311
  await source.renderStackContent(stack);
13048
13312
  source.effectsRenderer.applyEffects([]);
13049
- if (filter) filtered = await renderFilterSurface(source.canvas, filter, stack.element.container.styles.opacity, options.scale, signal);
13313
+ if (filter) filtered = await renderFilterSurface(source.canvas, filter, container.styles.opacity, options.scale, signal, {
13314
+ references: container.filterReferences,
13315
+ origin: {
13316
+ x: container.bounds.left - surfaceWindow.left,
13317
+ y: container.bounds.top - surfaceWindow.top
13318
+ }
13319
+ });
13050
13320
  const composited = filtered ?? source.canvas;
13051
- if (hasMask) await this.applyMask(composited, stack.element.container.styles, bounds);
13321
+ if (hasMask) await this.applyMask(composited, stack.element.container.styles, surfaceWindow, container.bounds, ownTransforms);
13052
13322
  if (signal?.aborted) throw new DOMException("The operation was aborted.", "AbortError");
13053
13323
  const own = stack.element.effects;
13054
- const effects = stack.element.getEffects(4, this.surfaceRoot).filter((effect) => !own.includes(effect) || !isFilterEffect(effect) && !isOpacityEffect(effect) && !isBlendEffect(effect) && !isClipEffect(effect));
13324
+ const effects = stack.element.getEffects(4, this.surfaceRoot).filter((effect) => !own.includes(effect) || !isFilterEffect(effect) && !isOpacityEffect(effect) && !isBlendEffect(effect) && !isClipEffect(effect) && !isTransformEffect(effect));
13055
13325
  this.effectsRenderer.applyEffects(effects);
13056
13326
  if (hasBlend) {
13057
13327
  this.ctx.save();
@@ -13075,8 +13345,15 @@ var CanvasRenderer = class CanvasRenderer {
13075
13345
  * Composite an alpha mask onto a finished element surface: all mask
13076
13346
  * layers are painted additively into a mask surface, then kept pixels are
13077
13347
  * selected with destination-in.
13348
+ *
13349
+ * Coordinate spaces: the source surface paints in LAYOUT space (the
13350
+ * ancestor TransformEffects stay active on the main canvas and transform
13351
+ * the draw-back), so the mask must be painted in layout space too —
13352
+ * anchored to the element's border box (containerBounds) — riding ONLY
13353
+ * the element's own transform effects, which apply inside the surface
13354
+ * rather than at draw-back.
13078
13355
  */
13079
- async applyMask(surface, styles, bounds) {
13356
+ async applyMask(surface, styles, surfaceWindow, containerBounds, ownTransforms) {
13080
13357
  const ctx = surface.getContext("2d");
13081
13358
  if (!ctx) return;
13082
13359
  const maskCanvas = this.context.resourceDocument.createElement("canvas");
@@ -13088,14 +13365,21 @@ var CanvasRenderer = class CanvasRenderer {
13088
13365
  return;
13089
13366
  }
13090
13367
  maskCtx.scale(this.options.scale, this.options.scale);
13091
- maskCtx.translate(-bounds.left, -bounds.top);
13368
+ maskCtx.translate(-surfaceWindow.left, -surfaceWindow.top);
13369
+ for (let i = ownTransforms.length - 1; i >= 0; i--) {
13370
+ const effect = at(ownTransforms, i);
13371
+ maskCtx.translate(effect.offsetX, effect.offsetY);
13372
+ maskCtx.transform(...effect.matrix);
13373
+ maskCtx.translate(-effect.offsetX, -effect.offsetY);
13374
+ }
13375
+ const layoutArea = {
13376
+ left: containerBounds.left,
13377
+ top: containerBounds.top,
13378
+ width: containerBounds.width,
13379
+ height: containerBounds.height
13380
+ };
13092
13381
  try {
13093
- await paintMaskLayers(maskCtx, styles.maskImage, styles, {
13094
- left: bounds.left,
13095
- top: bounds.top,
13096
- width: bounds.width,
13097
- height: bounds.height
13098
- }, async (url) => await this.context.cache.match(url));
13382
+ await paintMaskLayers(maskCtx, styles.maskImage, styles, layoutArea, async (url) => await this.context.cache.match(url));
13099
13383
  } catch (error) {
13100
13384
  this.context.logger.error(`Error rendering mask-image: ${error instanceof Error ? error.message : error}`);
13101
13385
  releaseSurface(maskCanvas);
@@ -13239,7 +13523,7 @@ var CanvasRenderer = class CanvasRenderer {
13239
13523
  y: this.options.y,
13240
13524
  width: this.options.width,
13241
13525
  height: this.options.height
13242
- }, (ctx, opts) => new CanvasRenderer(ctx, opts), container, curves, styles, (c, cv, img) => this.renderReplacedElement(c, cv, img));
13526
+ }, (ctx, opts) => new CanvasRenderer(ctx, opts, void 0, this.surfaceBudget), container, curves, styles, (c, cv, img) => this.renderReplacedElement(c, cv, img));
13243
13527
  renderFormElements(this.ctx, this.textRenderer, this.path.bind(this), container, styles);
13244
13528
  await renderListMarker(this.ctx, this.context, this.textRenderer, paint, container, styles);
13245
13529
  }
@@ -13635,8 +13919,7 @@ const calculateBackgroundCurvedPaintingArea = (clip, curves) => {
13635
13919
  const hasTextBackgroundClip = (styles) => {
13636
13920
  return styles.backgroundClip.some((clip) => clip === 3);
13637
13921
  };
13638
- //#endregion
13639
- //#region src/render/canvas/foreignobject-renderer.ts
13922
+ // src/render/canvas/foreignobject-renderer.ts
13640
13923
  var ForeignObjectRenderer = class {
13641
13924
  canvas;
13642
13925
  ctx;
@@ -13701,8 +13984,7 @@ const stripRootOffsets = (element) => {
13701
13984
  for (const [property, value] of previous) style[property] = value;
13702
13985
  };
13703
13986
  };
13704
- //#endregion
13705
- //#region src/core/logger.ts
13987
+ // src/core/logger.ts
13706
13988
  var Logger = class {
13707
13989
  id;
13708
13990
  enabled;
@@ -13739,8 +14021,7 @@ var Logger = class {
13739
14021
  }
13740
14022
  }
13741
14023
  };
13742
- //#endregion
13743
- //#region src/core/cache-storage.ts
14024
+ // src/core/cache-storage.ts
13744
14025
  var Cache = class {
13745
14026
  context;
13746
14027
  _options;
@@ -13985,8 +14266,7 @@ const isInlineImage = (src) => INLINE_IMG.test(src);
13985
14266
  const isInlineBase64Image = (src) => INLINE_BASE64.test(src);
13986
14267
  const isBlobImage = (src) => src.substring(0, 4) === "blob";
13987
14268
  const isSVG = (src) => src.slice(-3).toLowerCase() === "svg" || INLINE_SVG.test(src);
13988
- //#endregion
13989
- //#region src/core/origin-checker.ts
14269
+ // src/core/origin-checker.ts
13990
14270
  /**
13991
14271
  * Origin Checker
13992
14272
  *
@@ -14038,8 +14318,7 @@ var OriginChecker = class {
14038
14318
  return this.origin;
14039
14319
  }
14040
14320
  };
14041
- //#endregion
14042
- //#region src/core/context.ts
14321
+ // src/core/context.ts
14043
14322
  var Context = class Context {
14044
14323
  static instanceCount = 1;
14045
14324
  instanceName = `#${Context.instanceCount++}`;
@@ -14086,8 +14365,7 @@ var Context = class Context {
14086
14365
  this._windowBounds = this._windowBounds.add(left, top, 0, 0);
14087
14366
  }
14088
14367
  };
14089
- //#endregion
14090
- //#region src/core/config-assembler.ts
14368
+ // src/core/config-assembler.ts
14091
14369
  /**
14092
14370
  * Coerce known numeric options from string (or other) values to actual numbers.
14093
14371
  * Mutates the opts object in place — this is intentionally a normalisation
@@ -14164,8 +14442,7 @@ const assembleRenderOptions = (opts, backgroundColor, left, top, width, height,
14164
14442
  imageSmoothing: opts.imageSmoothing,
14165
14443
  imageSmoothingQuality: opts.imageSmoothingQuality
14166
14444
  });
14167
- //#endregion
14168
- //#region src/core/background-parser.ts
14445
+ // src/core/background-parser.ts
14169
14446
  /**
14170
14447
  * Resolve the background colour for the rendered canvas, following CSS
14171
14448
  * background propagation rules:
@@ -14186,8 +14463,7 @@ const parseBackgroundColor = (context, element, backgroundColorOverride) => {
14186
14463
  const defaultBackgroundColor = typeof backgroundColorOverride === "string" ? parseColor(context, backgroundColorOverride) : backgroundColorOverride === null ? 0 : 4294967295;
14187
14464
  return element === ownerDocument.documentElement ? isTransparent(documentBackgroundColor) ? isTransparent(bodyBackgroundColor) ? defaultBackgroundColor : bodyBackgroundColor : documentBackgroundColor : defaultBackgroundColor;
14188
14465
  };
14189
- //#endregion
14190
- //#region src/core/render-element.ts
14466
+ // src/core/render-element.ts
14191
14467
  const emitProgress = (onProgress, context, phase, progress) => {
14192
14468
  if (!onProgress) return;
14193
14469
  try {
@@ -14216,7 +14492,7 @@ const renderElement = async (element, opts, config) => {
14216
14492
  const windowBounds = new Bounds(windowOptions.scrollX, windowOptions.scrollY, windowOptions.windowWidth, windowOptions.windowHeight);
14217
14493
  const context = new Context(contextOptions, windowBounds, config);
14218
14494
  const performanceMonitoring = opts.enablePerformanceMonitoring ?? opts.logging ?? false;
14219
- const perfMonitor = new PerformanceMonitor(context, performanceMonitoring);
14495
+ const perfMonitor = new PerformanceMonitor(context.logger, performanceMonitoring);
14220
14496
  perfMonitor.start("total", {
14221
14497
  width: windowOptions.windowWidth,
14222
14498
  height: windowOptions.windowHeight
@@ -14285,8 +14561,7 @@ const renderElement = async (element, opts, config) => {
14285
14561
  emitProgress(opts.onProgress, context, "render", 100);
14286
14562
  return canvas;
14287
14563
  };
14288
- //#endregion
14289
- //#region src/index.ts
14564
+ // src/index.ts
14290
14565
  /**
14291
14566
  * Renders an HTML element to a `<canvas>` element.
14292
14567
  *
@@ -14322,7 +14597,6 @@ const html2canvas = (element, options = {}, config) => {
14322
14597
  });
14323
14598
  return renderElement(element, options, finalConfig);
14324
14599
  };
14325
- //#endregion
14326
14600
  export { Html2CanvasConfig, PerformanceMonitor, Validator, createDefaultValidator, html2canvas as default, html2canvas };
14327
14601
 
14328
14602
  //# sourceMappingURL=html2canvas-pro.esm.js.map