@reportforge/playwright-pdf 0.14.1 → 0.14.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -3,6 +3,23 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  Format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
5
5
 
6
+ ## [0.14.3] - 2026-07-06
7
+
8
+ ### Fixed
9
+
10
+ - **Watermark now shows on every page instead of only one.** Chromium's print-to-PDF doesn't repeat `position: fixed` elements per page (only paged-media renderers like Prince/WeasyPrint do), so a single watermark div only ever printed once for the whole document. An inline script now measures the rendered page height and stamps one `position: absolute` copy per page. Also changed from `z-index: -1` to painting above content — at 4% opacity it doesn't affect legibility, and the negative z-index made it invisible on any page dense enough to have no background gaps.
11
+ - **Executive report now leads with the pass-rate/suite-results charts, trend chart second.** Previously the trend chart was promoted above the doughnut/bar row; both now render in the same order as the other templates, landing on the same page as the summary stats.
12
+
13
+ ---
14
+
15
+ ## [0.14.2] - 2026-07-06
16
+
17
+ ### Fixed
18
+
19
+ - **Pass-rate doughnut and suite-results bar charts no longer render flush-left inside their card.** `canvas` computes to `display: block` in Chromium, so `.chart-card`'s `text-align: center` (which only centers inline-level boxes) never centered it — most visible on the executive template's wide secondary chart row. `.chart-card canvas` now centers with explicit `margin: 0 auto`.
20
+
21
+ ---
22
+
6
23
  ## [0.14.1] - 2026-07-06
7
24
 
8
25
  ### Fixed
package/dist/cli/index.js CHANGED
@@ -6590,7 +6590,7 @@ function deriveOptions(s) {
6590
6590
  showFullFailures: s.fullFailures
6591
6591
  };
6592
6592
  }
6593
- var import_handlebars, import_fs, import_path, SLOW_MEDIAN_FACTOR, TemplateEngine;
6593
+ var import_handlebars, import_fs, import_path, A4_HEIGHT_MM, PAGE_MARGIN_Y_MM, PX_PER_MM, PAGE_CONTENT_HEIGHT_PX, SLOW_MEDIAN_FACTOR, TemplateEngine;
6594
6594
  var init_engine = __esm({
6595
6595
  "src/templates/engine.ts"() {
6596
6596
  "use strict";
@@ -6602,6 +6602,10 @@ var init_engine = __esm({
6602
6602
  init_duration();
6603
6603
  init_SummaryWriter();
6604
6604
  init_sections();
6605
+ A4_HEIGHT_MM = 297;
6606
+ PAGE_MARGIN_Y_MM = 16;
6607
+ PX_PER_MM = 96 / 25.4;
6608
+ PAGE_CONTENT_HEIGHT_PX = (A4_HEIGHT_MM - 2 * PAGE_MARGIN_Y_MM) * PX_PER_MM;
6605
6609
  SLOW_MEDIAN_FACTOR = 2;
6606
6610
  TemplateEngine = class {
6607
6611
  constructor() {
@@ -6661,7 +6665,8 @@ var init_engine = __esm({
6661
6665
  slowTests: slow.ranked,
6662
6666
  baseCSS: this.fontsBundleCss + "\n" + this.readStyle("base.css"),
6663
6667
  templateCSS: "",
6664
- chartjsScript: this.buildChartjsScript()
6668
+ chartjsScript: this.buildChartjsScript(),
6669
+ watermarkPageHeightPx: PAGE_CONTENT_HEIGHT_PX
6665
6670
  };
6666
6671
  }
6667
6672
  buildContext(data, template, userSections, slowTestThreshold) {
@@ -6684,7 +6689,8 @@ var init_engine = __esm({
6684
6689
  slowTests: slow.ranked,
6685
6690
  baseCSS,
6686
6691
  templateCSS,
6687
- chartjsScript: this.buildChartjsScript()
6692
+ chartjsScript: this.buildChartjsScript(),
6693
+ watermarkPageHeightPx: PAGE_CONTENT_HEIGHT_PX
6688
6694
  };
6689
6695
  }
6690
6696
  buildChartjsScript() {
package/dist/index.js CHANGED
@@ -12365,6 +12365,10 @@ function formatDuration(ms) {
12365
12365
  function jsonForInlineScript(value) {
12366
12366
  return JSON.stringify(value).replace(/<\//g, "<\\/");
12367
12367
  }
12368
+ var A4_HEIGHT_MM = 297;
12369
+ var PAGE_MARGIN_Y_MM = 16;
12370
+ var PX_PER_MM = 96 / 25.4;
12371
+ var PAGE_CONTENT_HEIGHT_PX = (A4_HEIGHT_MM - 2 * PAGE_MARGIN_Y_MM) * PX_PER_MM;
12368
12372
  function isUnknownValue(v) {
12369
12373
  return !v || v === "unknown";
12370
12374
  }
@@ -12438,7 +12442,8 @@ var TemplateEngine = class {
12438
12442
  slowTests: slow.ranked,
12439
12443
  baseCSS: this.fontsBundleCss + "\n" + this.readStyle("base.css"),
12440
12444
  templateCSS: "",
12441
- chartjsScript: this.buildChartjsScript()
12445
+ chartjsScript: this.buildChartjsScript(),
12446
+ watermarkPageHeightPx: PAGE_CONTENT_HEIGHT_PX
12442
12447
  };
12443
12448
  }
12444
12449
  buildContext(data, template, userSections, slowTestThreshold) {
@@ -12461,7 +12466,8 @@ var TemplateEngine = class {
12461
12466
  slowTests: slow.ranked,
12462
12467
  baseCSS,
12463
12468
  templateCSS,
12464
- chartjsScript: this.buildChartjsScript()
12469
+ chartjsScript: this.buildChartjsScript(),
12470
+ watermarkPageHeightPx: PAGE_CONTENT_HEIGHT_PX
12465
12471
  };
12466
12472
  }
12467
12473
  buildChartjsScript() {
@@ -14056,7 +14062,7 @@ var PdfReporter = class {
14056
14062
  this.liveConsole = false;
14057
14063
  this.options = parseOptions(rawOptions);
14058
14064
  this.dataCollector = new DataCollector(this.options.capture);
14059
- const version = true ? "0.14.1" : "0.x";
14065
+ const version = true ? "0.14.3" : "0.x";
14060
14066
  logger.info(`@reportforge/playwright-pdf v${version} initialised`);
14061
14067
  this.licenseClient = new LicenseClient({
14062
14068
  licenseKey: this.options.licenseKey,
package/dist/index.mjs CHANGED
@@ -12366,6 +12366,10 @@ function formatDuration(ms) {
12366
12366
  function jsonForInlineScript(value) {
12367
12367
  return JSON.stringify(value).replace(/<\//g, "<\\/");
12368
12368
  }
12369
+ var A4_HEIGHT_MM = 297;
12370
+ var PAGE_MARGIN_Y_MM = 16;
12371
+ var PX_PER_MM = 96 / 25.4;
12372
+ var PAGE_CONTENT_HEIGHT_PX = (A4_HEIGHT_MM - 2 * PAGE_MARGIN_Y_MM) * PX_PER_MM;
12369
12373
  function isUnknownValue(v) {
12370
12374
  return !v || v === "unknown";
12371
12375
  }
@@ -12439,7 +12443,8 @@ var TemplateEngine = class {
12439
12443
  slowTests: slow.ranked,
12440
12444
  baseCSS: this.fontsBundleCss + "\n" + this.readStyle("base.css"),
12441
12445
  templateCSS: "",
12442
- chartjsScript: this.buildChartjsScript()
12446
+ chartjsScript: this.buildChartjsScript(),
12447
+ watermarkPageHeightPx: PAGE_CONTENT_HEIGHT_PX
12443
12448
  };
12444
12449
  }
12445
12450
  buildContext(data, template, userSections, slowTestThreshold) {
@@ -12462,7 +12467,8 @@ var TemplateEngine = class {
12462
12467
  slowTests: slow.ranked,
12463
12468
  baseCSS,
12464
12469
  templateCSS,
12465
- chartjsScript: this.buildChartjsScript()
12470
+ chartjsScript: this.buildChartjsScript(),
12471
+ watermarkPageHeightPx: PAGE_CONTENT_HEIGHT_PX
12466
12472
  };
12467
12473
  }
12468
12474
  buildChartjsScript() {
@@ -14057,7 +14063,7 @@ var PdfReporter = class {
14057
14063
  this.liveConsole = false;
14058
14064
  this.options = parseOptions(rawOptions);
14059
14065
  this.dataCollector = new DataCollector(this.options.capture);
14060
- const version = true ? "0.14.1" : "0.x";
14066
+ const version = true ? "0.14.3" : "0.x";
14061
14067
  logger.info(`@reportforge/playwright-pdf v${version} initialised`);
14062
14068
  this.licenseClient = new LicenseClient({
14063
14069
  licenseKey: this.options.licenseKey,
@@ -1,7 +1,7 @@
1
1
  {{#if options.showCharts}}
2
2
  {{#if options.heroTrend}}
3
- {{> chart-trend-card options=options}}
4
3
  {{> chart-summary-grid options=options}}
4
+ {{> chart-trend-card options=options}}
5
5
  {{else}}
6
6
  {{> chart-summary-grid options=options}}
7
7
  {{> chart-trend-card options=options}}
@@ -1,3 +1,24 @@
1
1
  {{#if meta.branding.watermark}}
2
- <div class="watermark" aria-hidden="true">{{meta.branding.watermark}}</div>
2
+ <script>
3
+ document.addEventListener('DOMContentLoaded', function() {
4
+ // Chromium's print-to-PDF doesn't repeat position:fixed elements per page, so a
5
+ // single watermark div only ever prints on one page. Instead, measure the fully
6
+ // parsed document (this listener fires after all content above is in the DOM)
7
+ // and stamp one absolutely-positioned copy per page slot.
8
+ var text = {{{safeJsonData meta.branding.watermark}}};
9
+ var pageHeightPx = {{watermarkPageHeightPx}};
10
+ // +1: print pagination avoids breaking cards/rows mid-way, so each physical
11
+ // page is often a little under pageHeightPx of raw content — that nudges the
12
+ // real page count above what scrollHeight / pageHeightPx alone predicts.
13
+ var pageCount = Math.min(500, Math.max(1, Math.ceil(document.body.scrollHeight / pageHeightPx) + 1));
14
+ for (var i = 0; i < pageCount; i++) {
15
+ var el = document.createElement('div');
16
+ el.className = 'watermark';
17
+ el.setAttribute('aria-hidden', 'true');
18
+ el.style.top = (i * pageHeightPx + pageHeightPx / 2) + 'px';
19
+ el.textContent = text;
20
+ document.body.appendChild(el);
21
+ }
22
+ });
23
+ </script>
3
24
  {{/if}}
@@ -43,8 +43,8 @@ html, body {
43
43
  color: var(--text-1);
44
44
  background: var(--bg);
45
45
  }
46
- /* Establish a stacking context on the body so the fixed watermark (z-index:-1)
47
- paints behind all content instead of on top of cards, charts and screenshots. */
46
+ /* Positioned so it's the containing block for the watermark's `position: absolute`
47
+ copies (see below) without this they'd position relative to the document root. */
48
48
  body { position: relative; z-index: 0; }
49
49
 
50
50
  /* ── Typography ─────────────────────────────────────────────────────────── */
@@ -142,11 +142,17 @@ tr:last-child td { border-bottom: none; }
142
142
  .severity--low { color: var(--text-3); }
143
143
 
144
144
  /* ── Watermark ──────────────────────────────────────────────────────────── */
145
+ /* `top` is set inline per copy (see watermark.hbs) — Chromium's print-to-PDF
146
+ doesn't repeat `position: fixed` elements per page, so one copy is stamped
147
+ at each page's vertical centre in document-flow coordinates instead.
148
+ z-index is high (not negative) so it paints over cards/badges too — at
149
+ 4% opacity it doesn't hurt legibility, and a negative z-index made it
150
+ invisible on any page dense enough to have no gaps in the content. */
145
151
  .watermark {
146
- position: fixed; top: 50%; left: 50%;
152
+ position: absolute; left: 50%;
147
153
  transform: translate(-50%, -50%) rotate(-30deg);
148
154
  font-family: 'Source Serif Pro', Georgia, serif; font-size: 60px; font-weight: 700;
149
- color: rgba(31,31,28,0.04); pointer-events: none; z-index: -1;
155
+ color: rgba(31,31,28,0.04); pointer-events: none; z-index: 999;
150
156
  white-space: nowrap; letter-spacing: 8px; text-transform: uppercase;
151
157
  user-select: none;
152
158
  }
@@ -667,6 +673,9 @@ code {
667
673
  border: 1px solid var(--border-2);
668
674
  border-radius: 6px; padding: 16px 14px; text-align: center;
669
675
  }
676
+ /* canvas computes to display:block in Chromium, so text-align:center above
677
+ never centers it (that only affects inline-level boxes) — margin:auto does. */
678
+ .chart-card canvas { display: block; margin: 0 auto; }
670
679
  .chart-card h3 {
671
680
  margin: 0 0 12px;
672
681
  font-family: 'Inter', system-ui, sans-serif; font-size: 9px;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@reportforge/playwright-pdf",
3
- "version": "0.14.1",
3
+ "version": "0.14.3",
4
4
  "description": "Playwright Test reporter that generates designed PDF reports: minimal, detailed, and executive templates with CI/CD integrations",
5
5
  "license": "MIT",
6
6
  "author": "ReportForge",