@@ -6,17 +6,64 @@ const usage = `Generate before/after screenshots for two URLs using Playwright.
66Usage:
77 node script/compare-screenshots.js [options] <before-url> <after-url>
88
9+ Arguments can be URLs or paths to git-scm.com worktrees. When a worktree
10+ path is given, Hugo is run to build the site and a local server is started.
11+
912Options:
1013 --dark Emulate dark mode (prefers-color-scheme: dark)
1114 --light Emulate light mode (default)
1215 --clip=<WxH+X+Y> Clip screenshots to specified region (e.g., --clip=1280x720+0+0)
1316
1417Examples:
1518 node script/compare-screenshots.js https://git-scm.com http://localhost:5000
19+ node script/compare-screenshots.js https://git-scm.com /path/to/worktree
1620 node script/compare-screenshots.js --dark https://git-scm.com http://localhost:5000
1721 node script/compare-screenshots.js --clip=1280x720+0+0 https://git-scm.com http://localhost:5000` ;
1822
1923const { chromium } = require ( '@playwright/test' ) ;
24+ const { spawn, execSync } = require ( 'child_process' ) ;
25+ const fs = require ( 'fs' ) ;
26+ const path = require ( 'path' ) ;
27+
28+ function isWorktree ( arg ) {
29+ if ( arg . startsWith ( 'http://' ) || arg . startsWith ( 'https://' ) ) return false ;
30+ try {
31+ return fs . statSync ( path . join ( arg , 'hugo.yml' ) ) . isFile ( ) ;
32+ } catch {
33+ return false ;
34+ }
35+ }
36+
37+ async function startServer ( worktreePath , port ) {
38+ // Build Hugo site
39+ console . error ( `Building Hugo site in ${ worktreePath } ...` ) ;
40+ execSync ( 'hugo' , { cwd : worktreePath , stdio : 'inherit' } ) ;
41+
42+ // Start serve-public.js
43+ const serverScript = path . join ( worktreePath , 'script' , 'serve-public.js' ) ;
44+ const server = spawn ( 'node' , [ serverScript ] , {
45+ cwd : worktreePath ,
46+ env : { ...process . env , PORT : String ( port ) } ,
47+ stdio : [ 'ignore' , 'pipe' , 'inherit' ] ,
48+ } ) ;
49+
50+ // Wait for server to be ready
51+ await new Promise ( ( resolve , reject ) => {
52+ const timeout = setTimeout ( ( ) => reject ( new Error ( 'Server startup timeout' ) ) , 30000 ) ;
53+ server . stdout . on ( 'data' , ( data ) => {
54+ if ( data . toString ( ) . includes ( 'Now listening' ) ) {
55+ clearTimeout ( timeout ) ;
56+ resolve ( ) ;
57+ }
58+ } ) ;
59+ server . on ( 'error' , ( err ) => {
60+ clearTimeout ( timeout ) ;
61+ reject ( err ) ;
62+ } ) ;
63+ } ) ;
64+
65+ return server ;
66+ }
2067
2168async function main ( ) {
2269 const args = process . argv . slice ( 2 ) ;
@@ -77,18 +124,32 @@ async function main() {
77124 console . error ( 'Using dark mode (prefers-color-scheme: dark)' ) ;
78125 }
79126
80- async function takeScreenshot ( url , outputPath ) {
81- console . error ( `Navigating to: ${ url } ` ) ;
82- await page . goto ( url , { waitUntil : 'networkidle' } ) ;
83- await page . screenshot ( { path : outputPath , clip, fullPage : ! clip } ) ;
84- const pageDims = await page . evaluate ( ( ) => ( {
85- width : document . documentElement . scrollWidth ,
86- height : document . documentElement . scrollHeight ,
87- } ) ) ;
88- const info = clip
89- ? `${ clip . width } x${ clip . height } +${ clip . x } +${ clip . y } of ${ pageDims . width } x${ pageDims . height } `
90- : `${ pageDims . width } x${ pageDims . height } ` ;
91- console . error ( `Saved: ${ outputPath } (${ info } )` ) ;
127+ async function takeScreenshot ( urlOrWorktree , outputPath ) {
128+ let server ;
129+ let url = urlOrWorktree ;
130+
131+ if ( isWorktree ( urlOrWorktree ) ) {
132+ server = await startServer ( urlOrWorktree , 5000 ) ;
133+ url = 'http://localhost:5000/' ;
134+ }
135+
136+ try {
137+ console . error ( `Navigating to: ${ url } ` ) ;
138+ await page . goto ( url , { waitUntil : 'networkidle' } ) ;
139+ await page . screenshot ( { path : outputPath , clip, fullPage : ! clip } ) ;
140+ const pageDims = await page . evaluate ( ( ) => ( {
141+ width : document . documentElement . scrollWidth ,
142+ height : document . documentElement . scrollHeight ,
143+ } ) ) ;
144+ const info = clip
145+ ? `${ clip . width } x${ clip . height } +${ clip . x } +${ clip . y } of ${ pageDims . width } x${ pageDims . height } `
146+ : `${ pageDims . width } x${ pageDims . height } ` ;
147+ console . error ( `Saved: ${ outputPath } (${ info } )` ) ;
148+ } finally {
149+ if ( server ) {
150+ server . kill ( ) ;
151+ }
152+ }
92153 }
93154
94155 await takeScreenshot ( beforeUrl , '.before.png' ) ;
0 commit comments