1- #!/usr/bin/env -S deno run --allow-read --allow-write
1+ #!/usr/bin/env -S deno run --allow-read --allow-write --allow-run
22
3- import { pngImagesDiffer } from "./compare_images.mts" ;
4- import { ScreenshotContext } from "./presets.ts" ;
3+ import { walk } from "jsr:@std/fs/walk" ;
4+ import { pngImagesDiffer } from "./compare-images.mts" ;
5+ import { ScreenshotEvent } from "./e2e-test-run-logger.ts" ;
56
67const runLogDir = Deno . args [ 0 ] ;
78const helpRepo = Deno . args [ 1 ] ;
9+ const copyFilesEvenIfIdentical = true ;
810
911if ( runLogDir == null || helpRepo == null ) {
1012 console . error ( "Usage: ./copy-help-site-screenshots.mts <run_log_dir> <help_repo>" ) ;
@@ -17,58 +19,75 @@ if (!(await Deno.stat(helpRepo)).isDirectory) {
1719 Deno . exit ( 1 ) ;
1820}
1921
20- const pageNameToFileName = {
21- localized_page_sign_up : "1786056439.png" ,
22- localized_auth0_sign_up_with_pt : "1624359167.png" ,
23- localized_pt_registry_login : "448045579.png" ,
24- localized_my_projects : "1783795116.png" ,
25- localized_sync : "1990846672.png" ,
26- sign_up_for_drafting : "Draft-Generation/sign_up_for_drafting.png" ,
27- configure_sources_button : "Draft-Generation/configure_sources_button.png" ,
28- configure_sources_draft_source : "Draft-Generation/configure_sources_draft_source.png" ,
29- configure_sources_draft_reference : "Draft-Generation/configure_sources_draft_reference.png" ,
30- configure_sources_confirm_languages : "Draft-Generation/configure_sources_confirm_languages.png" ,
31- generate_draft_button : "Draft-Generation/generate_draft_button.png" ,
32- generate_draft_confirm_sources : "Draft-Generation/generate_draft_confirm_sources.png" ,
33- generate_draft_select_books_to_draft : "Draft-Generation/generate_draft_select_books_to_draft.png" ,
34- generate_draft_select_books_to_train : "Draft-Generation/generate_draft_select_books_to_train.png" ,
35- generate_draft_summary : "Draft-Generation/generate_draft_summary.png"
36- } ;
37-
38- const screenshotsWithNoDestination = new Set ( ) ;
22+ const screenshotEvents : ScreenshotEvent [ ] = runLog . screenshotEvents ;
3923
4024function getDirForLocale ( localeCode : string ) : string {
4125 return localeCode === "en"
4226 ? `${ helpRepo } /docs`
4327 : `${ helpRepo } /i18n/${ localeCode } /docusaurus-plugin-content-docs/current` ;
4428}
4529
46- for ( const screenshot of runLog . screenshotEvents ) {
47- const context : ScreenshotContext = screenshot . context ;
48- const pageName = context . pageName ;
49- const localeCode = context . locale ;
50- if ( pageName == null || localeCode == null ) {
51- console . error ( "Screenshot context is missing pageName or locale:" , JSON . stringify ( context ) ) ;
52- continue ;
53- }
30+ function getScreenshotByFileNameAndLocale ( fileName : string , localeCode : string ) : any | undefined {
31+ const pageName = fileName . replace ( / \. p n g $ / , "" ) ;
32+ return screenshotEvents . find ( event => event . context . pageName === pageName && event . context . locale === localeCode ) ;
33+ }
5434
55- if ( pageName in pageNameToFileName ) {
56- const currentFile = `${ runLogDir } /${ screenshot . fileName } ` ;
57- const newFile = `${ getDirForLocale ( localeCode ) } /${ pageNameToFileName [ pageName as keyof typeof pageNameToFileName ] } ` ;
35+ function localeCodesInRunLog ( ) : string [ ] {
36+ return [ ...new Set ( screenshotEvents . map ( event => event . context . locale ) ) ] as string [ ] ;
37+ }
38+
39+ const markdownImageRegex = / ! \[ .* ?\] \( .\/ ( [ \w ] + \. p n g ) \) / gm;
5840
59- const imageDiffers = pngImagesDiffer ( currentFile , newFile ) ;
60- if ( imageDiffers ) {
61- console . log ( `Moving ${ currentFile } to ${ newFile } ` ) ;
62- await Deno . copyFile ( currentFile , newFile ) ;
63- } else {
64- console . log ( `Skipping ${ currentFile } as it is identical to ${ newFile } ` ) ;
41+ async function imagesInMarkdownFile ( filePath : string ) : Promise < string [ ] > {
42+ const content = await Deno . readTextFile ( filePath ) ;
43+ const matches = Array . from ( content . matchAll ( markdownImageRegex ) ) ;
44+ return matches . map ( match => match [ 1 ] ) ;
45+ }
46+
47+ for ( const locale of localeCodesInRunLog ( ) ) {
48+ const localeDir = getDirForLocale ( locale ) ;
49+ try {
50+ console . log ( `Walking directory: ${ localeDir } ` ) ;
51+ for await ( const entry of walk ( localeDir ) ) {
52+ if ( entry . isFile && entry . name . endsWith ( ".md" ) ) {
53+ for ( const imageFileName of await imagesInMarkdownFile ( entry . path ) ) {
54+ const screenshot = getScreenshotByFileNameAndLocale ( imageFileName , locale ) ;
55+ if ( screenshot ) {
56+ console . log ( `Found screenshot for image ${ imageFileName } in locale ${ locale } :` , screenshot . fileName ) ;
57+ const markdownFileDir = entry . path . substring ( 0 , entry . path . lastIndexOf ( "/" ) ) ;
58+ const source = `${ runLogDir } /${ screenshot . fileName } ` ;
59+ const destination = `${ markdownFileDir } /${ imageFileName } ` ;
60+ await copyScreenshotIfDiffers ( source , destination ) ;
61+ } else {
62+ console . warn ( `No screenshot found for image ${ imageFileName } in locale ${ locale } ` ) ;
63+ }
64+ }
65+ }
6566 }
66- } else {
67- screenshotsWithNoDestination . add ( pageName ) ;
67+ } catch ( error ) {
68+ console . error ( `Error reading directory ${ localeDir } :` , error ) ;
6869 }
6970}
7071
71- if ( screenshotsWithNoDestination . size > 0 ) {
72- console . error ( "Screenshots with no destination:" , Array . from ( screenshotsWithNoDestination ) . join ( ", " ) ) ;
73- console . error ( "Please update the script to handle these screenshots." ) ;
72+ /**
73+ * Copies a file from point A to point B if the files differ, or if there is no file at point B, or if
74+ * copyFilesEvenIfIdentical is set to true.
75+ * Uses zopflipng to optimize the PNG file.
76+ * @param source The source file path.
77+ * @param destination The destination file path.
78+ * @returns A promise that resolves when the copy is complete.
79+ * @throws If the source file does not exist or if the copy fails.
80+ */
81+ async function copyScreenshotIfDiffers ( source : string , destination : string ) : Promise < void > {
82+ const imageDiffers = pngImagesDiffer ( source , destination ) ;
83+ if ( imageDiffers || copyFilesEvenIfIdentical ) {
84+ console . log ( `Copying ${ source } to ${ destination } using zopflipng...` ) ;
85+ const zopflipng = new Deno . Command ( "zopflipng" , { args : [ "-y" , source , destination ] , stdout : "inherit" } ) ;
86+ const status = await zopflipng . output ( ) ;
87+ if ( status . code !== 0 ) {
88+ throw new Error ( `Failed to copy ${ source } to ${ destination } using zopflipng:` , status ) ;
89+ }
90+ } else {
91+ console . log ( `Skipping ${ source } as it is identical to ${ destination } ` ) ;
92+ }
7493}
0 commit comments