pagespeed-quest 0.6.0 → 0.7.0

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/build/adhoc.js CHANGED
@@ -27,5 +27,5 @@ export async function playback() {
27
27
  await execLighthouse({ url: proxy.entryUrl, proxyPort: proxy.port, headless: false, timeout: 60000 }, dependency);
28
28
  });
29
29
  }
30
- playback();
31
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYWRob2MuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvYWRob2MudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxHQUFHLE1BQU0sYUFBYSxDQUFBO0FBRTdCLE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQTtBQUM1QyxPQUFPLEVBQUUsbUJBQW1CLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQTtBQUNwRCxPQUFPLEVBQUUsY0FBYyxFQUFFLE1BQU0saUJBQWlCLENBQUE7QUFDaEQsT0FBTyxFQUFFLGlCQUFpQixFQUFFLE1BQU0sZUFBZSxDQUFBO0FBQ2pELE9BQU8sRUFBRSxrQkFBa0IsRUFBRSxNQUFNLGdCQUFnQixDQUFBO0FBRW5ELE1BQU0sVUFBVSxHQUFHLElBQUksVUFBVSxFQUFFLENBQUE7QUFFbkMsTUFBTSxDQUFDLEtBQUssVUFBVSxTQUFTO0lBQzdCLE1BQU0sU0FBUyxHQUFHLCtCQUErQixDQUFBO0lBQ2pELGlEQUFpRDtJQUVqRCxNQUFNLEdBQUcsQ0FBQyxLQUFLLENBQUMsT0FBTyxFQUFFLEVBQUUsU0FBUyxFQUFFLElBQUksRUFBRSxDQUFDLENBQUE7SUFDN0MsTUFBTSxtQkFBbUIsR0FBRyxJQUFJLG1CQUFtQixDQUFDLE9BQU8sRUFBRSxVQUFVLENBQUMsQ0FBQTtJQUN4RSxNQUFNLGtCQUFrQixDQUN0QjtRQUNFLG1CQUFtQjtLQUNwQixFQUNELFVBQVUsRUFDVixLQUFLLEVBQUUsS0FBSyxFQUFFLEVBQUU7UUFDZCxLQUFLLENBQUMsUUFBUSxHQUFHLFNBQVMsQ0FBQTtRQUMxQixNQUFNLGNBQWMsQ0FBQyxFQUFFLEdBQUcsRUFBRSxTQUFTLEVBQUUsU0FBUyxFQUFFLEtBQUssQ0FBQyxJQUFJLEVBQUUsUUFBUSxFQUFFLEtBQUssRUFBRSxPQUFPLEVBQUUsS0FBSyxFQUFFLEVBQUUsVUFBVSxDQUFDLENBQUE7SUFDOUcsQ0FBQyxDQUNGLENBQUE7QUFDSCxDQUFDO0FBRUQsTUFBTSxDQUFDLEtBQUssVUFBVSxRQUFRO0lBQzVCLE1BQU0sbUJBQW1CLEdBQUcsSUFBSSxtQkFBbUIsQ0FBQyxPQUFPLEVBQUUsVUFBVSxDQUFDLENBQUE7SUFDeEUsTUFBTSxpQkFBaUIsQ0FDckI7UUFDRSxtQkFBbUI7S0FDcEIsRUFDRCxVQUFVLEVBQ1YsS0FBSyxFQUFFLEtBQUssRUFBRSxFQUFFO1FBQ2QsSUFBSSxDQUFDLEtBQUssQ0FBQyxRQUFRO1lBQUUsTUFBTSxJQUFJLEtBQUssQ0FBQyx5QkFBeUIsQ0FBQyxDQUFBO1FBQy9ELE1BQU0sY0FBYyxDQUFDLEVBQUUsR0FBRyxFQUFFLEtBQUssQ0FBQyxRQUFRLEVBQUUsU0FBUyxFQUFFLEtBQUssQ0FBQyxJQUFJLEVBQUUsUUFBUSxFQUFFLEtBQUssRUFBRSxPQUFPLEVBQUUsS0FBSyxFQUFFLEVBQUUsVUFBVSxDQUFDLENBQUE7SUFDbkgsQ0FBQyxDQUNGLENBQUE7QUFDSCxDQUFDO0FBRUQsUUFBUSxFQUFFLENBQUEifQ==
30
+ recording().then(playback);
31
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYWRob2MuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvYWRob2MudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxHQUFHLE1BQU0sYUFBYSxDQUFBO0FBRTdCLE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQTtBQUM1QyxPQUFPLEVBQUUsbUJBQW1CLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQTtBQUNwRCxPQUFPLEVBQUUsY0FBYyxFQUFFLE1BQU0saUJBQWlCLENBQUE7QUFDaEQsT0FBTyxFQUFFLGlCQUFpQixFQUFFLE1BQU0sZUFBZSxDQUFBO0FBQ2pELE9BQU8sRUFBRSxrQkFBa0IsRUFBRSxNQUFNLGdCQUFnQixDQUFBO0FBRW5ELE1BQU0sVUFBVSxHQUFHLElBQUksVUFBVSxFQUFFLENBQUE7QUFFbkMsTUFBTSxDQUFDLEtBQUssVUFBVSxTQUFTO0lBQzdCLE1BQU0sU0FBUyxHQUFHLCtCQUErQixDQUFBO0lBQ2pELGlEQUFpRDtJQUVqRCxNQUFNLEdBQUcsQ0FBQyxLQUFLLENBQUMsT0FBTyxFQUFFLEVBQUUsU0FBUyxFQUFFLElBQUksRUFBRSxDQUFDLENBQUE7SUFDN0MsTUFBTSxtQkFBbUIsR0FBRyxJQUFJLG1CQUFtQixDQUFDLE9BQU8sRUFBRSxVQUFVLENBQUMsQ0FBQTtJQUN4RSxNQUFNLGtCQUFrQixDQUN0QjtRQUNFLG1CQUFtQjtLQUNwQixFQUNELFVBQVUsRUFDVixLQUFLLEVBQUUsS0FBSyxFQUFFLEVBQUU7UUFDZCxLQUFLLENBQUMsUUFBUSxHQUFHLFNBQVMsQ0FBQTtRQUMxQixNQUFNLGNBQWMsQ0FBQyxFQUFFLEdBQUcsRUFBRSxTQUFTLEVBQUUsU0FBUyxFQUFFLEtBQUssQ0FBQyxJQUFJLEVBQUUsUUFBUSxFQUFFLEtBQUssRUFBRSxPQUFPLEVBQUUsS0FBSyxFQUFFLEVBQUUsVUFBVSxDQUFDLENBQUE7SUFDOUcsQ0FBQyxDQUNGLENBQUE7QUFDSCxDQUFDO0FBRUQsTUFBTSxDQUFDLEtBQUssVUFBVSxRQUFRO0lBQzVCLE1BQU0sbUJBQW1CLEdBQUcsSUFBSSxtQkFBbUIsQ0FBQyxPQUFPLEVBQUUsVUFBVSxDQUFDLENBQUE7SUFDeEUsTUFBTSxpQkFBaUIsQ0FDckI7UUFDRSxtQkFBbUI7S0FDcEIsRUFDRCxVQUFVLEVBQ1YsS0FBSyxFQUFFLEtBQUssRUFBRSxFQUFFO1FBQ2QsSUFBSSxDQUFDLEtBQUssQ0FBQyxRQUFRO1lBQUUsTUFBTSxJQUFJLEtBQUssQ0FBQyx5QkFBeUIsQ0FBQyxDQUFBO1FBQy9ELE1BQU0sY0FBYyxDQUFDLEVBQUUsR0FBRyxFQUFFLEtBQUssQ0FBQyxRQUFRLEVBQUUsU0FBUyxFQUFFLEtBQUssQ0FBQyxJQUFJLEVBQUUsUUFBUSxFQUFFLEtBQUssRUFBRSxPQUFPLEVBQUUsS0FBSyxFQUFFLEVBQUUsVUFBVSxDQUFDLENBQUE7SUFDbkgsQ0FBQyxDQUNGLENBQUE7QUFDSCxDQUFDO0FBRUQsU0FBUyxFQUFFLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxDQUFBIn0=
@@ -24,8 +24,9 @@ export class Dependency {
24
24
  await execa(lighthousePath, args, { stdout: 'inherit', stderr: 'inherit' });
25
25
  }
26
26
  async executeLoadshow(args) {
27
- const loadshowPath = process.env.LOADSHOW_PATH || './node_modules/.bin/loadshow';
27
+ const binaryName = process.platform === 'win32' ? 'loadshow.exe' : 'loadshow';
28
+ const loadshowPath = process.env.LOADSHOW_PATH || `./bin/${binaryName}`;
28
29
  await execa(loadshowPath, args, { stdout: 'inherit', stderr: 'inherit' });
29
30
  }
30
31
  }
31
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGVwZW5kZW5jeS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy9kZXBlbmRlbmN5LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sR0FBRyxNQUFNLGFBQWEsQ0FBQTtBQUU3QixPQUFPLEVBQUUsS0FBSyxFQUFFLE1BQU0sT0FBTyxDQUFBO0FBQzdCLE9BQU8sSUFBSSxNQUFNLE1BQU0sQ0FBQTtBQUl2QixNQUFNLE9BQU8sVUFBVTtJQUNyQixNQUFNLENBQWM7SUFFcEI7UUFDRSxJQUFJLENBQUMsTUFBTSxHQUFHLElBQUksQ0FBQztZQUNqQixLQUFLLEVBQUUsT0FBTyxDQUFDLEdBQUcsQ0FBQyxTQUFTLElBQUksTUFBTTtZQUN0QyxTQUFTLEVBQUU7Z0JBQ1QsTUFBTSxFQUFFLGFBQWE7Z0JBQ3JCLE9BQU8sRUFBRTtvQkFDUCxRQUFRLEVBQUUsSUFBSTtvQkFDZCxNQUFNLEVBQUUsY0FBYztvQkFDdEIsVUFBVSxFQUFFLENBQUMsQ0FBQyxFQUFFLEVBQUUsR0FBRyxFQUFFLE9BQU8sRUFBRSxJQUFJLENBQUMsQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxXQUFXLEVBQUUsV0FBVyxFQUFFLENBQUM7aUJBQ3ZGO2FBQ0Y7U0FDRixDQUFDLENBQUE7SUFDSixDQUFDO0lBRUQsS0FBSyxDQUFDLE1BQU0sQ0FBQyxPQUFlO1FBQzFCLE1BQU0sR0FBRyxDQUFDLEtBQUssQ0FBQyxPQUFPLEVBQUUsRUFBRSxTQUFTLEVBQUUsSUFBSSxFQUFFLENBQUMsQ0FBQTtJQUMvQyxDQUFDO0lBRUQsS0FBSyxDQUFDLGlCQUFpQixDQUFDLElBQWM7UUFDcEMsTUFBTSxjQUFjLEdBQUcsT0FBTyxDQUFDLEdBQUcsQ0FBQyxlQUFlLElBQUksZ0NBQWdDLENBQUE7UUFDdEYsTUFBTSxLQUFLLENBQUMsY0FBYyxFQUFFLElBQUksRUFBRSxFQUFFLE1BQU0sRUFBRSxTQUFTLEVBQUUsTUFBTSxFQUFFLFNBQVMsRUFBRSxDQUFDLENBQUE7SUFDN0UsQ0FBQztJQUVELEtBQUssQ0FBQyxlQUFlLENBQUMsSUFBYztRQUNsQyxNQUFNLFlBQVksR0FBRyxPQUFPLENBQUMsR0FBRyxDQUFDLGFBQWEsSUFBSSw4QkFBOEIsQ0FBQTtRQUNoRixNQUFNLEtBQUssQ0FBQyxZQUFZLEVBQUUsSUFBSSxFQUFFLEVBQUUsTUFBTSxFQUFFLFNBQVMsRUFBRSxNQUFNLEVBQUUsU0FBUyxFQUFFLENBQUMsQ0FBQTtJQUMzRSxDQUFDO0NBQ0YifQ==
32
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGVwZW5kZW5jeS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy9kZXBlbmRlbmN5LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sR0FBRyxNQUFNLGFBQWEsQ0FBQTtBQUU3QixPQUFPLEVBQUUsS0FBSyxFQUFFLE1BQU0sT0FBTyxDQUFBO0FBQzdCLE9BQU8sSUFBSSxNQUFNLE1BQU0sQ0FBQTtBQUl2QixNQUFNLE9BQU8sVUFBVTtJQUNyQixNQUFNLENBQWM7SUFFcEI7UUFDRSxJQUFJLENBQUMsTUFBTSxHQUFHLElBQUksQ0FBQztZQUNqQixLQUFLLEVBQUUsT0FBTyxDQUFDLEdBQUcsQ0FBQyxTQUFTLElBQUksTUFBTTtZQUN0QyxTQUFTLEVBQUU7Z0JBQ1QsTUFBTSxFQUFFLGFBQWE7Z0JBQ3JCLE9BQU8sRUFBRTtvQkFDUCxRQUFRLEVBQUUsSUFBSTtvQkFDZCxNQUFNLEVBQUUsY0FBYztvQkFDdEIsVUFBVSxFQUFFLENBQUMsQ0FBQyxFQUFFLEVBQUUsR0FBRyxFQUFFLE9BQU8sRUFBRSxJQUFJLENBQUMsQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxXQUFXLEVBQUUsV0FBVyxFQUFFLENBQUM7aUJBQ3ZGO2FBQ0Y7U0FDRixDQUFDLENBQUE7SUFDSixDQUFDO0lBRUQsS0FBSyxDQUFDLE1BQU0sQ0FBQyxPQUFlO1FBQzFCLE1BQU0sR0FBRyxDQUFDLEtBQUssQ0FBQyxPQUFPLEVBQUUsRUFBRSxTQUFTLEVBQUUsSUFBSSxFQUFFLENBQUMsQ0FBQTtJQUMvQyxDQUFDO0lBRUQsS0FBSyxDQUFDLGlCQUFpQixDQUFDLElBQWM7UUFDcEMsTUFBTSxjQUFjLEdBQUcsT0FBTyxDQUFDLEdBQUcsQ0FBQyxlQUFlLElBQUksZ0NBQWdDLENBQUE7UUFDdEYsTUFBTSxLQUFLLENBQUMsY0FBYyxFQUFFLElBQUksRUFBRSxFQUFFLE1BQU0sRUFBRSxTQUFTLEVBQUUsTUFBTSxFQUFFLFNBQVMsRUFBRSxDQUFDLENBQUE7SUFDN0UsQ0FBQztJQUVELEtBQUssQ0FBQyxlQUFlLENBQUMsSUFBYztRQUNsQyxNQUFNLFVBQVUsR0FBRyxPQUFPLENBQUMsUUFBUSxLQUFLLE9BQU8sQ0FBQyxDQUFDLENBQUMsY0FBYyxDQUFDLENBQUMsQ0FBQyxVQUFVLENBQUE7UUFDN0UsTUFBTSxZQUFZLEdBQUcsT0FBTyxDQUFDLEdBQUcsQ0FBQyxhQUFhLElBQUksU0FBUyxVQUFVLEVBQUUsQ0FBQTtRQUN2RSxNQUFNLEtBQUssQ0FBQyxZQUFZLEVBQUUsSUFBSSxFQUFFLEVBQUUsTUFBTSxFQUFFLFNBQVMsRUFBRSxNQUFNLEVBQUUsU0FBUyxFQUFFLENBQUMsQ0FBQTtJQUMzRSxDQUFDO0NBQ0YifQ==
package/build/index.d.ts CHANGED
@@ -7,4 +7,5 @@ export * from './playback.js';
7
7
  export * from './recording.js';
8
8
  export * from './types.js';
9
9
  export * from './lighthouse.js';
10
+ export * from './lighthouse-digest.js';
10
11
  export * from './loadshow.js';
package/build/index.js CHANGED
@@ -7,5 +7,6 @@ export * from './playback.js';
7
7
  export * from './recording.js';
8
8
  export * from './types.js';
9
9
  export * from './lighthouse.js';
10
+ export * from './lighthouse-digest.js';
10
11
  export * from './loadshow.js';
11
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsY0FBYyxpQkFBaUIsQ0FBQTtBQUMvQixjQUFjLGVBQWUsQ0FBQTtBQUM3QixjQUFjLGlCQUFpQixDQUFBO0FBQy9CLGNBQWMsV0FBVyxDQUFBO0FBQ3pCLGNBQWMsZ0JBQWdCLENBQUE7QUFDOUIsY0FBYyxlQUFlLENBQUE7QUFDN0IsY0FBYyxnQkFBZ0IsQ0FBQTtBQUM5QixjQUFjLFlBQVksQ0FBQTtBQUMxQixjQUFjLGlCQUFpQixDQUFBO0FBQy9CLGNBQWMsZUFBZSxDQUFBIn0=
12
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsY0FBYyxpQkFBaUIsQ0FBQTtBQUMvQixjQUFjLGVBQWUsQ0FBQTtBQUM3QixjQUFjLGlCQUFpQixDQUFBO0FBQy9CLGNBQWMsV0FBVyxDQUFBO0FBQ3pCLGNBQWMsZ0JBQWdCLENBQUE7QUFDOUIsY0FBYyxlQUFlLENBQUE7QUFDN0IsY0FBYyxnQkFBZ0IsQ0FBQTtBQUM5QixjQUFjLFlBQVksQ0FBQTtBQUMxQixjQUFjLGlCQUFpQixDQUFBO0FBQy9CLGNBQWMsd0JBQXdCLENBQUE7QUFDdEMsY0FBYyxlQUFlLENBQUEifQ==
@@ -0,0 +1,12 @@
1
+ import { DependencyInterface } from './types.js';
2
+ export interface CaptureLighthouseDigestInput {
3
+ htmlPath: string;
4
+ outputPath: string;
5
+ }
6
+ /**
7
+ * Captures a digest screenshot of the Lighthouse report.
8
+ * This function captures two specific sections:
9
+ * 1. The final screenshot header (lh-category-header__finalscreenshot)
10
+ * 2. The metrics audit group (lh-audit-group--metrics)
11
+ */
12
+ export declare function captureLighthouseDigest(opts: CaptureLighthouseDigestInput, dependency: Pick<DependencyInterface, 'logger' | 'mkdirp'>): Promise<void>;
@@ -0,0 +1,69 @@
1
+ import Path from 'path';
2
+ import puppeteer from 'puppeteer';
3
+ /**
4
+ * Captures a digest screenshot of the Lighthouse report.
5
+ * This function captures two specific sections:
6
+ * 1. The final screenshot header (lh-category-header__finalscreenshot)
7
+ * 2. The metrics audit group (lh-audit-group--metrics)
8
+ */
9
+ export async function captureLighthouseDigest(opts, dependency) {
10
+ const browser = await puppeteer.launch({
11
+ headless: true,
12
+ args: ['--no-sandbox', '--disable-setuid-sandbox'],
13
+ });
14
+ try {
15
+ const page = await browser.newPage();
16
+ // Load the HTML file
17
+ const fileUrl = `file://${Path.resolve(opts.htmlPath)}`;
18
+ await page.goto(fileUrl, { waitUntil: 'networkidle0' });
19
+ // Check if the required elements exist
20
+ const elementsExist = await page.evaluate(() => {
21
+ const finalScreenshot = document.querySelector('.lh-category-header__finalscreenshot');
22
+ const metrics = document.querySelector('.lh-audit-group--metrics');
23
+ return finalScreenshot !== null && metrics !== null;
24
+ });
25
+ if (!elementsExist) {
26
+ throw new Error('Required elements not found in the Lighthouse report');
27
+ }
28
+ // Get the bounding boxes of both elements
29
+ const finalScreenshotElement = await page.$('.lh-category-header__finalscreenshot');
30
+ const metricsElement = await page.$('.lh-audit-group--metrics');
31
+ if (!finalScreenshotElement || !metricsElement) {
32
+ throw new Error('Required elements not found in the Lighthouse report');
33
+ }
34
+ const finalScreenshotBox = await finalScreenshotElement.boundingBox();
35
+ const metricsBox = await metricsElement.boundingBox();
36
+ if (!finalScreenshotBox || !metricsBox) {
37
+ throw new Error('Could not get bounding box of required elements');
38
+ }
39
+ // Calculate the bounding box that encompasses both elements
40
+ const minX = Math.min(finalScreenshotBox.x, metricsBox.x);
41
+ const minY = Math.min(finalScreenshotBox.y, metricsBox.y);
42
+ const maxX = Math.max(finalScreenshotBox.x + finalScreenshotBox.width, metricsBox.x + metricsBox.width);
43
+ const maxY = Math.max(finalScreenshotBox.y + finalScreenshotBox.height, metricsBox.y + metricsBox.height);
44
+ const boundingBox = {
45
+ x: minX,
46
+ y: minY,
47
+ width: maxX - minX,
48
+ height: maxY - minY,
49
+ };
50
+ // Ensure output directory exists
51
+ const outputDir = Path.dirname(opts.outputPath);
52
+ await dependency.mkdirp(outputDir);
53
+ // Capture the screenshot
54
+ await page.screenshot({
55
+ path: opts.outputPath,
56
+ clip: {
57
+ x: boundingBox.x,
58
+ y: boundingBox.y,
59
+ width: boundingBox.width,
60
+ height: boundingBox.height,
61
+ },
62
+ });
63
+ dependency.logger?.info(`Lighthouse digest screenshot saved to ${opts.outputPath}`);
64
+ }
65
+ finally {
66
+ await browser.close();
67
+ }
68
+ }
69
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibGlnaHRob3VzZS1kaWdlc3QuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvbGlnaHRob3VzZS1kaWdlc3QudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxJQUFJLE1BQU0sTUFBTSxDQUFBO0FBRXZCLE9BQU8sU0FBUyxNQUFNLFdBQVcsQ0FBQTtBQVNqQzs7Ozs7R0FLRztBQUNILE1BQU0sQ0FBQyxLQUFLLFVBQVUsdUJBQXVCLENBQzNDLElBQWtDLEVBQ2xDLFVBQTBEO0lBRTFELE1BQU0sT0FBTyxHQUFHLE1BQU0sU0FBUyxDQUFDLE1BQU0sQ0FBQztRQUNyQyxRQUFRLEVBQUUsSUFBSTtRQUNkLElBQUksRUFBRSxDQUFDLGNBQWMsRUFBRSwwQkFBMEIsQ0FBQztLQUNuRCxDQUFDLENBQUE7SUFFRixJQUFJO1FBQ0YsTUFBTSxJQUFJLEdBQUcsTUFBTSxPQUFPLENBQUMsT0FBTyxFQUFFLENBQUE7UUFFcEMscUJBQXFCO1FBQ3JCLE1BQU0sT0FBTyxHQUFHLFVBQVUsSUFBSSxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLEVBQUUsQ0FBQTtRQUN2RCxNQUFNLElBQUksQ0FBQyxJQUFJLENBQUMsT0FBTyxFQUFFLEVBQUUsU0FBUyxFQUFFLGNBQWMsRUFBRSxDQUFDLENBQUE7UUFFdkQsdUNBQXVDO1FBQ3ZDLE1BQU0sYUFBYSxHQUFHLE1BQU0sSUFBSSxDQUFDLFFBQVEsQ0FBQyxHQUFHLEVBQUU7WUFDN0MsTUFBTSxlQUFlLEdBQUcsUUFBUSxDQUFDLGFBQWEsQ0FBQyxzQ0FBc0MsQ0FBQyxDQUFBO1lBQ3RGLE1BQU0sT0FBTyxHQUFHLFFBQVEsQ0FBQyxhQUFhLENBQUMsMEJBQTBCLENBQUMsQ0FBQTtZQUNsRSxPQUFPLGVBQWUsS0FBSyxJQUFJLElBQUksT0FBTyxLQUFLLElBQUksQ0FBQTtRQUNyRCxDQUFDLENBQUMsQ0FBQTtRQUVGLElBQUksQ0FBQyxhQUFhLEVBQUU7WUFDbEIsTUFBTSxJ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
@@ -0,0 +1,32 @@
1
+ import { DependencyInterface } from './types.js';
2
+ /**
3
+ * Lighthouse audit result structure
4
+ */
5
+ export interface LighthouseAudit {
6
+ id: string;
7
+ title: string;
8
+ score: number | null;
9
+ numericValue?: number;
10
+ displayValue?: string;
11
+ }
12
+ /**
13
+ * Lighthouse JSON report structure (partial)
14
+ */
15
+ export interface LighthouseReport {
16
+ categories: {
17
+ performance: {
18
+ id: string;
19
+ title: string;
20
+ score: number | null;
21
+ };
22
+ };
23
+ audits: Record<string, LighthouseAudit>;
24
+ }
25
+ export interface GenerateLighthouseSummaryInput {
26
+ jsonPath: string;
27
+ outputPath: string;
28
+ }
29
+ /**
30
+ * Generates a Markdown summary from a Lighthouse JSON report
31
+ */
32
+ export declare function generateLighthouseSummary(opts: GenerateLighthouseSummaryInput, dependency: Pick<DependencyInterface, 'logger' | 'mkdirp'>): Promise<void>;
@@ -0,0 +1,80 @@
1
+ import fs from 'fs/promises';
2
+ import Path from 'path';
3
+ /**
4
+ * Performance metrics to extract from Lighthouse report
5
+ * Weights are based on Lighthouse v10+ scoring
6
+ */
7
+ const PERFORMANCE_METRICS = [
8
+ { id: 'first-contentful-paint', abbr: 'FCP', unit: 'ms', weight: 0.1 },
9
+ { id: 'largest-contentful-paint', abbr: 'LCP', unit: 'ms', weight: 0.25 },
10
+ { id: 'total-blocking-time', abbr: 'TBT', unit: 'ms', weight: 0.3 },
11
+ { id: 'cumulative-layout-shift', abbr: 'CLS', unit: '', weight: 0.25 },
12
+ { id: 'speed-index', abbr: 'SI', unit: 'ms', weight: 0.1 },
13
+ ];
14
+ /**
15
+ * Formats a score as a percentage integer
16
+ */
17
+ function formatScore(score) {
18
+ if (score === null)
19
+ return 'N/A';
20
+ return `${Math.round(score * 100)}`;
21
+ }
22
+ /**
23
+ * Formats a numeric value in milliseconds (rounded to integer)
24
+ * For CLS, returns the raw value with 3 decimal places
25
+ */
26
+ function formatValue(numericValue, unit) {
27
+ if (numericValue === undefined)
28
+ return 'N/A';
29
+ if (unit === '') {
30
+ // CLS - no unit, show decimal value
31
+ return numericValue.toFixed(3);
32
+ }
33
+ // Time-based metrics - round to integer ms
34
+ return `${Math.round(numericValue)} ${unit}`;
35
+ }
36
+ /**
37
+ * Generates a Markdown summary from a Lighthouse JSON report
38
+ */
39
+ export async function generateLighthouseSummary(opts, dependency) {
40
+ // Read and parse the Lighthouse JSON report
41
+ const jsonContent = await fs.readFile(opts.jsonPath, 'utf-8');
42
+ const report = JSON.parse(jsonContent);
43
+ // Extract overall performance score
44
+ const overallScore = report.categories?.performance?.score;
45
+ // Build the Markdown content
46
+ const lines = [];
47
+ lines.push('# Lighthouse Performance Summary');
48
+ lines.push('');
49
+ // Section 1: Metric Values
50
+ lines.push('## Metrics');
51
+ lines.push('');
52
+ for (const metric of PERFORMANCE_METRICS) {
53
+ const audit = report.audits[metric.id];
54
+ if (audit) {
55
+ const value = formatValue(audit.numericValue, metric.unit);
56
+ lines.push(`- ${metric.abbr} ${value}`);
57
+ }
58
+ }
59
+ lines.push('');
60
+ // Section 2: Scores
61
+ lines.push('## Scores');
62
+ lines.push('');
63
+ lines.push(`- Overall ${formatScore(overallScore)}`);
64
+ for (const metric of PERFORMANCE_METRICS) {
65
+ const audit = report.audits[metric.id];
66
+ if (audit) {
67
+ const score = formatScore(audit.score);
68
+ const weight = `x${metric.weight.toFixed(2)}`;
69
+ lines.push(`- ${metric.abbr} ${score} ${weight}`);
70
+ }
71
+ }
72
+ lines.push('');
73
+ // Ensure output directory exists
74
+ const outputDir = Path.dirname(opts.outputPath);
75
+ await dependency.mkdirp(outputDir);
76
+ // Write the summary file
77
+ await fs.writeFile(opts.outputPath, lines.join('\n'), 'utf-8');
78
+ dependency.logger?.info(`Lighthouse summary saved to ${opts.outputPath}`);
79
+ }
80
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibGlnaHRob3VzZS1zdW1tYXJ5LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vc3JjL2xpZ2h0aG91c2Utc3VtbWFyeS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsTUFBTSxhQUFhLENBQUE7QUFDNUIsT0FBTyxJQUFJLE1BQU0sTUFBTSxDQUFBO0FBNkJ2Qjs7O0dBR0c7QUFDSCxNQUFNLG1CQUFtQixHQUFHO0lBQzFCLEVBQUUsRUFBRSxFQUFFLHdCQUF3QixFQUFFLElBQUksRUFBRSxLQUFLLEVBQUUsSUFBSSxFQUFFLElBQUksRUFBRSxNQUFNLEVBQUUsR0FBRyxFQUFFO0lBQ3RFLEVBQUUsRUFBRSxFQUFFLDBCQUEwQixFQUFFLElBQUksRUFBRSxLQUFLLEVBQUUsSUFBSSxFQUFFLElBQUksRUFBRSxNQUFNLEVBQUUsSUFBSSxFQUFFO0lBQ3pFLEVBQUUsRUFBRSxFQUFFLHFCQUFxQixFQUFFLElBQUksRUFBRSxLQUFLLEVBQUUsSUFBSSxFQUFFLElBQUksRUFBRSxNQUFNLEVBQUUsR0FBRyxFQUFFO0lBQ25FLEVBQUUsRUFBRSxFQUFFLHlCQUF5QixFQUFFLElBQUksRUFBRSxLQUFLLEVBQUUsSUFBSSxFQUFFLEVBQUUsRUFBRSxNQUFNLEVBQUUsSUFBSSxFQUFFO0lBQ3RFLEVBQUUsRUFBRSxFQUFFLGFBQWEsRUFBRSxJQUFJLEVBQUUsSUFBSSxFQUFFLElBQUksRUFBRSxJQUFJLEVBQUUsTUFBTSxFQUFFLEdBQUcsRUFBRTtDQUMzRCxDQUFBO0FBT0Q7O0dBRUc7QUFDSCxTQUFTLFdBQVcsQ0FBQyxLQUFvQjtJQUN2QyxJQUFJLEtBQUssS0FBSyxJQUFJO1FBQUUsT0FBTyxLQUFLLENBQUE7SUFDaEMsT0FBTyxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsS0FBSyxHQUFHLEdBQUcsQ0FBQyxFQUFFLENBQUE7QUFDckMsQ0FBQztBQUVEOzs7R0FHRztBQUNILFNBQVMsV0FBVyxDQUFDLFlBQWdDLEVBQUUs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
@@ -7,5 +7,6 @@ export interface ExecLighthouseInput {
7
7
  artifactsDir?: string;
8
8
  headless: boolean;
9
9
  timeout: number;
10
+ captureScoreAndMetrics?: boolean;
10
11
  }
11
- export declare function execLighthouse(opts: ExecLighthouseInput, dependency: Pick<DependencyInterface, 'mkdirp' | 'executeLighthouse'>): Promise<void>;
12
+ export declare function execLighthouse(opts: ExecLighthouseInput, dependency: Pick<DependencyInterface, 'mkdirp' | 'executeLighthouse' | 'logger'>): Promise<void>;
@@ -1,4 +1,6 @@
1
1
  import Path from 'path';
2
+ import { captureLighthouseDigest } from './lighthouse-digest.js';
3
+ import { generateLighthouseSummary } from './lighthouse-summary.js';
2
4
  export async function execLighthouse(opts, dependency) {
3
5
  const artifactsDir = opts.artifactsDir || './artifacts';
4
6
  await dependency.mkdirp(artifactsDir);
@@ -28,5 +30,33 @@ export async function execLighthouse(opts, dependency) {
28
30
  if (opts.view)
29
31
  args.push('--view');
30
32
  await dependency.executeLighthouse(args);
33
+ // Capture score and metrics screenshot if requested
34
+ if (opts.captureScoreAndMetrics !== false) {
35
+ const htmlPath = `${outputPath}.report.html`;
36
+ const digestPath = Path.join(artifactsDir, 'lighthouse.digest.png');
37
+ try {
38
+ await captureLighthouseDigest({
39
+ htmlPath,
40
+ outputPath: digestPath,
41
+ }, dependency);
42
+ }
43
+ catch (error) {
44
+ dependency.logger?.warn(`Failed to capture Lighthouse score and metrics: ${error}`);
45
+ }
46
+ }
47
+ // Generate summary markdown
48
+ if (opts.artifactsDir) {
49
+ const jsonPath = `${outputPath}.report.json`;
50
+ const summaryPath = Path.join(artifactsDir, 'summary.md');
51
+ try {
52
+ await generateLighthouseSummary({
53
+ jsonPath,
54
+ outputPath: summaryPath,
55
+ }, dependency);
56
+ }
57
+ catch (error) {
58
+ dependency.logger?.warn(`Failed to generate Lighthouse summary: ${error}`);
59
+ }
60
+ }
31
61
  }
32
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibGlnaHRob3VzZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy9saWdodGhvdXNlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sSUFBSSxNQUFNLE1BQU0sQ0FBQTtBQWN2QixNQUFNLENBQUMsS0FBSyxVQUFVLGNBQWMsQ0FDbEMsSUFBeUIsRUFDekIsVUFBcUU7SUFFckUsTUFBTSxZQUFZLEdBQUcsSUFBSSxDQUFDLFlBQVksSUFBSSxhQUFhLENBQUE7SUFDdkQsTUFBTSxVQUFVLENBQUMsTUFBTSxDQUFDLFlBQVksQ0FBQyxDQUFBO0lBRXJDLE1BQU0sVUFBVSxHQUFHLElBQUksQ0FBQyxVQUFVLElBQUksUUFBUSxDQUFBO0lBQzlDLE1BQU0sVUFBVSxHQUFHLElBQUksQ0FBQyxJQUFJLENBQUMsWUFBWSxFQUFFLFlBQVksQ0FBQyxDQUFBO0lBQ3hELE1BQU0sSUFBSSxHQUFhO1FBQ3JCLElBQUksQ0FBQyxHQUFHO1FBQ1IsZUFBZTtRQUNmLG9CQUFvQjtRQUNwQixpQkFBaUIsVUFBVSxFQUFFO1FBQzdCLCtCQUErQjtRQUMvQixpQkFBaUIsVUFBVSxFQUFFO1FBQzdCLDRDQUE0QztRQUM1Qyw0QkFBNEIsVUFBVSxLQUFLLFFBQVEsQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxPQUFPLEVBQUU7UUFDeEUsNkRBQTZEO1FBQzdELHNCQUFzQjtRQUN0QiwrQkFBK0I7UUFDL0IsdUNBQXVDO1FBQ3ZDLHFDQUFxQztRQUNyQyxzQ0FBc0M7S0FDdkMsQ0FBQTtJQUVELElBQUksQ0FBQyxJQUFJLENBQUMsdUJBQXVCLElBQUksQ0FBQyxPQUFPLEVBQUUsQ0FBQyxDQUFBO0lBRWhELE1BQU0sV0FBVyxHQUFhLENBQUMsNkJBQTZCLEVBQUUsbUNBQW1DLElBQUksQ0FBQyxTQUFTLEVBQUUsQ0FBQyxDQUFBO0lBQ2xILElBQUksSUFBSSxDQUFDLFFBQVE7UUFBRSxXQUFXLENBQUMsSUFBSSxDQUFDLFlBQVksQ0FBQyxDQUFBO0lBQ2pELElBQUksQ0FBQyxJQUFJLENBQUMsbUJBQW1CLFdBQVcsQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxDQUFBO0lBRXRELElBQUksSUFBSSxDQUFDLElBQUk7UUFBRSxJQUFJLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxDQUFBO0lBRWxDLE1BQU0sVUFBVSxDQUFDLGlCQUFpQixDQUFDLElBQUksQ0FBQyxDQUFBO0FBQzFDLENBQUMifQ==
62
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibGlnaHRob3VzZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy9saWdodGhvdXNlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sSUFBSSxNQUFNLE1BQU0sQ0FBQTtBQUV2QixPQUFPLEVBQUUsdUJBQXVCLEVBQUUsTUFBTSx3QkFBd0IsQ0FBQTtBQUNoRSxPQUFPLEVBQUUseUJBQXlCLEVBQUUsTUFBTSx5QkFBeUIsQ0FBQTtBQWNuRSxNQUFNLENBQUMsS0FBSyxVQUFVLGNBQWMsQ0FDbEMsSUFBeUIsRUFDekIsVUFBZ0Y7SUFFaEYsTUFBTSxZQUFZLEdBQUcsSUFBSSxDQUFDLFlBQVksSUFBSSxhQUFhLENBQUE7SUFDdkQsTUFBTSxVQUFVLENBQUMsTUFBTSxDQUFDLFlBQVksQ0FBQyxDQUFBO0lBRXJDLE1BQU0sVUFBVSxHQUFHLElBQUksQ0FBQyxVQUFVLElBQUksUUFBUSxDQUFBO0lBQzlDLE1BQU0sVUFBVSxHQUFHLElBQUksQ0FBQyxJQUFJLENBQUMsWUFBWSxFQUFFLFlBQVksQ0FBQyxDQUFBO0lBQ3hELE1BQU0sSUFBSSxHQUFhO1FBQ3JCLElBQUksQ0FBQyxHQUFHO1FBQ1IsZUFBZTtRQUNmLG9CQUFvQjtRQUNwQixpQkFBaUIsVUFBVSxFQUFFO1FBQzdCLCtCQUErQjtRQUMvQixpQkFBaUIsVUFBVSxFQUFFO1FBQzdCLDRDQUE0QztRQUM1Qyw0QkFBNEIsVUFBVSxLQUFLLFFBQVEsQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxPQUFPLEVBQUU7UUFDeEUsNkRBQTZEO1FBQzdELHNCQUFzQjtRQUN0QiwrQkFBK0I7UUFDL0IsdUNBQXVDO1FBQ3ZDLHFDQUFxQztRQUNyQyxzQ0FBc0M7S0FDdkMsQ0FBQTtJQUVELElBQUksQ0FBQyxJQUFJLENBQUMsdUJBQXVCLElBQUksQ0FBQyxPQUFPLEVBQUUsQ0FBQyxDQUFBO0lBRWhELE1BQU0sV0FBVyxHQUFhLENBQUMsNkJBQTZCLEVBQUUsbUNBQW1DLElBQUksQ0FBQyxTQUFTLEVBQUUsQ0FBQyxDQUFBO0lBQ2xILElBQUksSUFBSSxDQUFDLFFBQVE7UUFBRSxXQUFXLENBQUMsSUFBSSxDQUFDLFlBQVksQ0FBQyxDQUFBO0lBQ2pELElBQUksQ0FBQyxJQUFJLENBQUMsbUJBQW1CLFdBQVcsQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxDQUFBO0lBRXRELElBQUksSUFBSSxDQUFDLElBQUk7UUFBRSxJQUFJLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxDQUFBO0lBRWxDLE1BQU0sVUFBVSxDQUFDLGlCQUFpQixDQUFDLElBQUksQ0FBQyxDQUFBO0lBRXhDLG9EQUFvRDtJQUNwRCxJQUFJLElBQUksQ0FBQyxzQkFBc0IsS0FBSyxLQUFLLEVBQUU7UUFDekMsTUFBTSxRQUFRLEdBQUcsR0FBRyxVQUFVLGNBQWMsQ0FBQTtRQUM1QyxNQUFNLFVBQVUsR0FBRyxJQUFJLENBQUMsSUFBSSxDQUFDLFlBQVksRUFBRSx1QkFBdUIsQ0FBQyxDQUFBO1FBRW5FLElBQUk7WUFDRixNQUFNLHVCQUF1QixDQUMzQjtnQkFDRSxRQUFRO2dCQUNSLFVBQVUsRUFBRSxVQUFVO2FBQ3ZCLEVBQ0QsVUFBVSxDQUNYLENBQUE7U0FDRjtRQUFDLE9BQU8sS0FBSyxFQUFFO1lBQ2QsVUFBVSxDQUFDLE1BQU0sRUFBRSxJQUFJLENBQUMsbURBQW1ELEtBQUssRUFBRSxDQUFDLENBQUE7U0FDcEY7S0FDRjtJQUVELDRCQUE0QjtJQUM1QixJQUFJLElBQUksQ0FBQyxZQUFZLEVBQUU7UUFDckIsTUFBTSxRQUFRLEdBQUcsR0FBRyxVQUFVLGNBQWMsQ0FBQTtRQUM1QyxNQUFNLFdBQVcsR0FBRyxJQUFJLENBQUMsSUFBSSxDQUFDLFlBQVksRUFBRSxZQUFZLENBQUMsQ0FBQTtRQUV6RCxJQUFJO1lBQ0YsTUFBTSx5QkFBeUIsQ0FDN0I7Z0JBQ0UsUUFBUTtnQkFDUixVQUFVLEVBQUUsV0FBVzthQUN4QixFQUNELFVBQVUsQ0FDWCxDQUFBO1NBQ0Y7UUFBQyxPQUFPLEtBQUssRUFBRTtZQUNkLFVBQVUsQ0FBQyxNQUFNLEVBQUUsSUFBSSxDQUFDLDBDQUEwQyxLQUFLLEVBQUUsQ0FBQyxDQUFBO1NBQzNFO0tBQ0Y7QUFDSCxDQUFDIn0=
@@ -8,12 +8,14 @@ export interface ExecLoadshowInput {
8
8
  credit?: string;
9
9
  }
10
10
  export interface ExecLoadshowSpec {
11
+ preset?: 'desktop' | 'mobile';
11
12
  viewportWidth?: number;
12
13
  columns?: number;
13
14
  cpuThrottling?: number;
14
- timeoutMs?: number;
15
- userAgent?: string;
15
+ timeoutSec?: number;
16
16
  proxyPort?: number;
17
17
  credit?: string;
18
+ debugDir?: string;
19
+ outputSummary?: string;
18
20
  }
19
21
  export declare function execLoadshow(input: ExecLoadshowInput, dependency: Pick<DependencyInterface, 'mkdirp' | 'executeLoadshow'>): Promise<void>;
package/build/loadshow.js CHANGED
@@ -1,54 +1,62 @@
1
1
  import Path from 'path';
2
- import { defaultConfig, desktopConfig } from 'lighthouse';
3
2
  function execSpecToCommandArgs(spec) {
4
3
  const args = [];
4
+ // preset
5
+ if (spec.preset !== undefined)
6
+ args.push('--preset', spec.preset);
5
7
  // layout
6
8
  if (spec.columns !== undefined)
7
- args.push('-u', `layout.columns=${spec.columns}`);
8
- // recording
9
+ args.push('--columns', String(spec.columns));
10
+ // browser settings
9
11
  if (spec.viewportWidth !== undefined)
10
- args.push('-u', `recording.viewportWidth=${spec.viewportWidth}`);
12
+ args.push('--viewport-width', String(spec.viewportWidth));
11
13
  if (spec.cpuThrottling !== undefined)
12
- args.push('-u', `recording.cpuThrottling=${spec.cpuThrottling}`);
13
- if (spec.timeoutMs !== undefined)
14
- args.push('-u', `recording.timeoutMs=${spec.timeoutMs}`);
15
- if (spec.userAgent !== undefined)
16
- args.push('-u', `recording.headers.User-Agent=${spec.userAgent}`);
17
- // recording.puppeteer
18
- const chromeArgs = ['--ignore-certificate-errors'];
14
+ args.push('--cpu-throttling', String(spec.cpuThrottling));
15
+ // timeout
16
+ if (spec.timeoutSec !== undefined)
17
+ args.push('--timeout-sec', String(spec.timeoutSec));
18
+ // proxy settings
19
19
  if (spec.proxyPort !== undefined) {
20
- chromeArgs.push(`--proxy-server=http://localhost:${spec.proxyPort}`);
20
+ args.push('--proxy-server', `http://localhost:${spec.proxyPort}`);
21
+ args.push('--ignore-https-errors');
21
22
  }
22
- args.push('-u', 'recording.puppeteer.args=' + chromeArgs.join(','));
23
23
  // credit
24
24
  if (spec.credit)
25
- args.push('-u', `banner.vars.credit=${spec.credit}`);
25
+ args.push('--credit', spec.credit);
26
+ // debug directory
27
+ if (spec.debugDir)
28
+ args.push('--debug-dir', spec.debugDir);
29
+ // output summary
30
+ if (spec.outputSummary)
31
+ args.push('--output-summary', spec.outputSummary);
26
32
  return args;
27
33
  }
28
34
  export async function execLoadshow(input, dependency) {
29
35
  const artifactsDir = input.artifactsDir || './artifacts';
30
36
  const loadshowDir = Path.join(artifactsDir, 'loadshow');
31
37
  const outputPath = Path.join(artifactsDir, 'loadshow.mp4');
38
+ const summaryPath = Path.join(loadshowDir, 'summary.md');
32
39
  await dependency.mkdirp(loadshowDir);
33
40
  // By form factor
34
- const lighthouseByDevice = input.deviceType === 'desktop' ? desktopConfig : defaultConfig;
41
+ const preset = input.deviceType === 'desktop' ? 'desktop' : 'mobile';
35
42
  const customByDevice = input.deviceType === 'desktop' ? { columns: 2 } : { columns: 3 };
43
+ // Convert timeout from milliseconds to seconds
44
+ const timeoutSec = Math.ceil(input.timeout / 1000);
36
45
  // Basic spec
37
- const userAgent = lighthouseByDevice.settings?.emulatedUserAgent;
38
46
  const spec = {
47
+ preset,
39
48
  proxyPort: input.proxyPort,
40
49
  columns: customByDevice.columns,
41
- viewportWidth: lighthouseByDevice.settings?.screenEmulation?.width,
42
- cpuThrottling: lighthouseByDevice.settings?.throttling?.cpuSlowdownMultiplier,
43
- userAgent: typeof userAgent === 'string' ? userAgent : undefined,
44
- timeoutMs: input.timeout,
50
+ timeoutSec,
45
51
  credit: input.credit,
52
+ debugDir: loadshowDir,
53
+ outputSummary: summaryPath,
46
54
  };
47
55
  const args = [];
48
56
  args.push('record');
49
- args.push('-a', loadshowDir);
50
57
  args.push(...execSpecToCommandArgs(spec));
51
- args.push(input.url, outputPath);
58
+ args.push('--output', outputPath);
59
+ args.push(input.url);
52
60
  await dependency.executeLoadshow(args);
53
61
  }
54
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibG9hZHNob3cuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvbG9hZHNob3cudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxJQUFJLE1BQU0sTUFBTSxDQUFBO0FBRXZCLE9BQU8sRUFBRSxhQUFhLEVBQUUsYUFBYSxFQUFFLE1BQU0sWUFBWSxDQUFBO0FBdUJ6RCxTQUFTLHFCQUFxQixDQUFDLElBQXNCO0lBQ25ELE1BQU0sSUFBSSxHQUFhLEVBQUUsQ0FBQTtJQUV6QixTQUFTO0lBQ1QsSUFBSSxJQUFJLENBQUMsT0FBTyxLQUFLLFNBQVM7UUFBRSxJQUFJLENBQUMsSUFBSSxDQUFDLElBQUksRUFBRSxrQkFBa0IsSUFBSSxDQUFDLE9BQU8sRUFBRSxDQUFDLENBQUE7SUFFakYsWUFBWTtJQUNaLElBQUksSUFBSSxDQUFDLGFBQWEsS0FBSyxTQUFTO1FBQUUsSUFBSSxDQUFDLElBQUksQ0FBQyxJQUFJLEVBQUUsMkJBQTJCLElBQUksQ0FBQyxhQUFhLEVBQUUsQ0FBQyxDQUFBO0lBQ3RHLElBQUksSUFBSSxDQUFDLGFBQWEsS0FBSyxTQUFTO1FBQUUsSUFBSSxDQUFDLElBQUksQ0FBQyxJQUFJLEVBQUUsMkJBQTJCLElBQUksQ0FBQyxhQUFhLEVBQUUsQ0FBQyxDQUFBO0lBQ3RHLElBQUksSUFBSSxDQUFDLFNBQVMsS0FBSyxTQUFTO1FBQUUsSUFBSSxDQUFDLElBQUksQ0FBQyxJQUFJLEVBQUUsdUJBQXVCLElBQUksQ0FBQyxTQUFTLEVBQUUsQ0FBQyxDQUFBO0lBQzFGLElBQUksSUFBSSxDQUFDLFNBQVMsS0FBSyxTQUFTO1FBQUUsSUFBSSxDQUFDLElBQUksQ0FBQyxJQUFJLEVBQUUsZ0NBQWdDLElBQUksQ0FBQyxTQUFTLEVBQUUsQ0FBQyxDQUFBO0lBRW5HLHNCQUFzQjtJQUN0QixNQUFNLFVBQVUsR0FBYSxDQUFDLDZCQUE2QixDQUFDLENBQUE7SUFDNUQsSUFBSSxJQUFJLENBQUMsU0FBUyxLQUFLLFNBQVMs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
62
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibG9hZHNob3cuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvbG9hZHNob3cudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxJQUFJLE1BQU0sTUFBTSxDQUFBO0FBeUJ2QixTQUFTLHFCQUFxQixDQUFDLElBQXNCO0lBQ25ELE1BQU0sSUFBSSxHQUFhLEVBQUUsQ0FBQTtJQUV6QixTQUFTO0lBQ1QsSUFBSSxJQUFJLENBQUMsTUFBTSxLQUFLLFNBQVM7UUFBRSxJQUFJLENBQUMsSUFBSSxDQUFDLFVBQVUsRUFBRSxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUE7SUFFakUsU0FBUztJQUNULElBQUksSUFBSSxDQUFDLE9BQU8sS0FBSyxTQUFTO1FBQUUsSUFBSSxDQUFDLElBQUksQ0FBQyxXQUFXLEVBQUUsTUFBTSxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFBO0lBRTVFLG1CQUFtQjtJQUNuQixJQUFJLElBQUksQ0FBQyxhQUFhLEtBQUssU0FBUztRQUFFLElBQUksQ0FBQyxJQUFJLENBQUMsa0JBQWtCLEVBQUUsTUFBTSxDQUFDLElBQUksQ0FBQyxhQUFhLENBQUMsQ0FBQyxDQUFBO0lBQy9GLElBQUksSUFBSSxDQUFDLGFBQWEsS0FBSyxTQUFTO1FBQUUsSUFBSSxDQUFDLElBQUksQ0FBQyxrQkFBa0IsRUFBRSxNQUFNLENBQUMsSUFBSSxDQUFDLGFBQWEsQ0FBQyxDQUFDLENBQUE7SUFFL0YsVUFBVTtJQUNWLElBQUksSUFBSSxDQUFDLFVBQVUsS0FBSyxTQUFTO1FBQUUsSUFBSSxDQUFDLElBQUksQ0FBQyxlQUFlLEVBQUUsTUFBTSxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsQ0FBQyxDQUFBO0lBRXRGLGlCQUFpQjtJQUNqQixJQUFJLElBQUksQ0FBQyxTQUFTLEtBQUssU0FBUyxFQUFFO1FBQ2hDLElBQUksQ0FBQyxJQUFJLENBQUMsZ0JBQWdCLEVBQUUsb0JBQW9CLElBQUksQ0FBQyxTQUFTLEVB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
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pagespeed-quest",
3
- "version": "0.6.0",
3
+ "version": "0.7.0",
4
4
  "type": "module",
5
5
  "description": "A framework for efficient web front-end speed improvement",
6
6
  "main": "build/index.js",
@@ -46,7 +46,8 @@
46
46
  "prepare-release": "run-s reset-hard test cov:check doc:html version doc:publish",
47
47
  "adhoc": "yarn build && node build/adhoc.js",
48
48
  "command": "yarn build && node build/command.js",
49
- "prepublishOnly": "yarn build"
49
+ "prepublishOnly": "yarn build",
50
+ "postinstall": "node scripts/postinstall.js"
50
51
  },
51
52
  "engines": {
52
53
  "node": ">=18"
@@ -57,11 +58,12 @@
57
58
  "iconv-lite": "^0.6.3",
58
59
  "jschardet": "^3.0.0",
59
60
  "lighthouse": "^12.2.1",
60
- "loadshow": "1.2.0",
61
+ "node-html-to-image": "^5.0.0",
61
62
  "node-watch": "^0.7.4",
62
63
  "pino": "^9.4.0",
63
64
  "pino-pretty": "^11.2.2",
64
65
  "prettier": "^2.1.1",
66
+ "puppeteer": "^24.31.0",
65
67
  "rust-http-playback-proxy": "0.4.2",
66
68
  "tmp-promise": "^3.0.3"
67
69
  },
@@ -91,6 +93,7 @@
91
93
  },
92
94
  "files": [
93
95
  "build",
96
+ "scripts",
94
97
  "!**/*.spec.*",
95
98
  "!**/*.json",
96
99
  "CHANGELOG.md",
@@ -0,0 +1,99 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { createWriteStream, mkdirSync, chmodSync, existsSync, unlinkSync } from 'fs'
4
+ import { pipeline } from 'stream/promises'
5
+ import { createGunzip } from 'zlib'
6
+ import { extract } from 'tar'
7
+ import { fileURLToPath } from 'url'
8
+ import { dirname, join } from 'path'
9
+
10
+ const __filename = fileURLToPath(import.meta.url)
11
+ const __dirname = dirname(__filename)
12
+
13
+ const LOADSHOW_VERSION = 'v1.3.0'
14
+ const REPO = 'ideamans/go-loadshow'
15
+
16
+ function getPlatformInfo() {
17
+ const platform = process.platform
18
+ const arch = process.arch
19
+
20
+ if (platform === 'darwin' && arch === 'arm64') {
21
+ return { os: 'darwin', arch: 'arm64', ext: 'tar.gz' }
22
+ } else if (platform === 'darwin' && arch === 'x64') {
23
+ // macOS x64 is not available, fall back to arm64 (Rosetta 2)
24
+ return { os: 'darwin', arch: 'arm64', ext: 'tar.gz' }
25
+ } else if (platform === 'linux' && arch === 'x64') {
26
+ return { os: 'linux', arch: 'amd64', ext: 'tar.gz' }
27
+ } else if (platform === 'linux' && arch === 'arm64') {
28
+ return { os: 'linux', arch: 'arm64', ext: 'tar.gz' }
29
+ } else if (platform === 'win32' && arch === 'x64') {
30
+ return { os: 'windows', arch: 'amd64', ext: 'zip' }
31
+ } else {
32
+ throw new Error(`Unsupported platform: ${platform} ${arch}`)
33
+ }
34
+ }
35
+
36
+ async function downloadFile(url, destPath) {
37
+ const response = await fetch(url, { redirect: 'follow' })
38
+ if (!response.ok) {
39
+ throw new Error(`Failed to download: ${response.status} ${response.statusText}`)
40
+ }
41
+ const fileStream = createWriteStream(destPath)
42
+ await pipeline(response.body, fileStream)
43
+ }
44
+
45
+ async function extractTarGz(archivePath, destDir) {
46
+ const { execSync } = await import('child_process')
47
+ execSync(`tar -xzf "${archivePath}" -C "${destDir}"`, { stdio: 'inherit' })
48
+ }
49
+
50
+ async function extractZip(archivePath, destDir) {
51
+ const { execSync } = await import('child_process')
52
+ execSync(`unzip -o "${archivePath}" -d "${destDir}"`, { stdio: 'inherit' })
53
+ }
54
+
55
+ async function main() {
56
+ const binDir = join(__dirname, '..', 'bin')
57
+ const platformInfo = getPlatformInfo()
58
+
59
+ const assetName = `loadshow_${LOADSHOW_VERSION}_${platformInfo.os}_${platformInfo.arch}.${platformInfo.ext}`
60
+ const downloadUrl = `https://github.com/${REPO}/releases/download/${LOADSHOW_VERSION}/${assetName}`
61
+
62
+ console.log(`Downloading go-loadshow ${LOADSHOW_VERSION} for ${platformInfo.os}/${platformInfo.arch}...`)
63
+ console.log(`URL: ${downloadUrl}`)
64
+
65
+ // Create bin directory if not exists
66
+ if (!existsSync(binDir)) {
67
+ mkdirSync(binDir, { recursive: true })
68
+ }
69
+
70
+ const archivePath = join(binDir, assetName)
71
+ const binaryName = platformInfo.os === 'windows' ? 'loadshow.exe' : 'loadshow'
72
+ const binaryPath = join(binDir, binaryName)
73
+
74
+ // Download archive
75
+ await downloadFile(downloadUrl, archivePath)
76
+ console.log('Download complete. Extracting...')
77
+
78
+ // Extract archive
79
+ if (platformInfo.ext === 'tar.gz') {
80
+ await extractTarGz(archivePath, binDir)
81
+ } else {
82
+ await extractZip(archivePath, binDir)
83
+ }
84
+
85
+ // Make binary executable (Unix only)
86
+ if (platformInfo.os !== 'windows') {
87
+ chmodSync(binaryPath, 0o755)
88
+ }
89
+
90
+ // Clean up archive
91
+ unlinkSync(archivePath)
92
+
93
+ console.log(`go-loadshow installed successfully at ${binaryPath}`)
94
+ }
95
+
96
+ main().catch((err) => {
97
+ console.error('Failed to install go-loadshow:', err.message)
98
+ process.exit(1)
99
+ })