11import { spawn , spawnSync } from 'node:child_process'
2- import { copyFileSync , cpSync } from 'node:fs'
2+ import { copyFileSync , cpSync , existsSync } from 'node:fs'
33
44import { cleanDir , write , totalBytesWritten } from "./export_util.js"
55import DefinitionSet from '#src/definitions/definition_set.js'
2020 definitions = await DefinitionSet . load ( ) ,
2121
2222 exporters = {
23+ // Build the Blockly application itself
2324 "app" : async ( destination = "export" ) => {
2425
2526 // clear the export directory
@@ -34,13 +35,13 @@ const
3435 } )
3536 } ,
3637
38+ // Build the documentation for the Blockly application
3739 "docs" : async ( ) => {
38- // allow option to skip image generation
39- const skipImages = taskArgs . includes ( "skipImages" )
40- if ( ! skipImages ) {
41- await exporters . blockImages ( )
42- cleanDir ( "docs/block_images" )
43- cpSync ( "tmp/block_images/images" , "docs/block_images" , { recursive : true } )
40+ // TODO: check and warn if block images haven't been generated
41+ if ( ! existsSync ( "docs/block_images/action_root.png" ) ) {
42+ console . log ( "Block images missing from docs/block_images!" )
43+ console . log ( "Run: `npm run export:block-images` before exporting the docs" )
44+ process . exit ( 1 )
4445 }
4546
4647 await exporters . app ( "docs/blockly" )
@@ -54,67 +55,70 @@ const
5455 } )
5556 } ,
5657
58+ // Build the documentation but only touch files that have changed
59+ // This is good to pair with a process that watches files for changes
5760 "docs-incremental" : async ( ) => {
58- // allow option to skip image generation
59- // const skipImages = taskArgs.includes("skipImages")
60- // if(!skipImages) {
61- // await exporters.blockImages()
62- // cleanDir("docs/block_images")
63- // cpSync("tmp/block_images/images", "docs/block_images", { recursive: true })
64- // }
65-
66- // await exporters.app("docs/blockly")
67- // cleanDir("docs/blocks")
68-
6961 await exportTo ( "docs" , definitions , exportItem => {
7062 exportItem . blockIndex ( "blocks/index.md" )
7163 exportItem . blockPages ( )
7264 exportItem . sidebar ( "blocks/_blocks_sidebar.json" )
7365 } )
7466 } ,
7567
76- "blockImages" : async ( ) => {
77- const destination = "tmp/block_images"
78- cleanDir ( destination )
79- cleanDir ( `${ destination } /images` )
68+ // Create png images of all blocks by:
69+ // - creating a temporary app with no toolbox and all blocks on the workspace
70+ // - serving that application
71+ // - driving a browser to it with Cypress
72+ // - right clicking on each block and clicking "download image"
73+ "blockImages" : async ( imageDestination = "docs/block_images" ) => {
74+ const tmpAppDestination = "tmp/block_images_app"
75+ cleanDir ( tmpAppDestination )
8076
8177 // export a special app with no toolbox, all blocks on workspace
82- await exportTo ( destination , definitions , exportItem => {
78+ await exportTo ( tmpAppDestination , definitions , exportItem => {
8379 exportItem . workspaceAllBlocks ( "workspace.json" )
84- write ( `${ destination } /toolbox.json` , "null" )
80+ write ( `${ tmpAppDestination } /toolbox.json` , "null" )
8581 exportItem . blocks ( "blocks.json" )
8682 exportItem . script ( "blockly_app.js" )
8783 // TODO: make a DocumentExporter for generating html wrappers
88- copyFileSync ( "src/exporters/document_templates/blockly_workspace.template.html" , `${ destination } /index.html` )
84+ copyFileSync ( "src/exporters/document_templates/blockly_workspace.template.html" , `${ tmpAppDestination } /index.html` )
8985 } )
9086
91- // serve it
87+ // serve the screenshot app
9288 console . log ( 'Serving workspace for screenshots...' )
93- const viteProcess = spawn ( "npx" , [ "vite" , "serve" , destination ] )
89+ const viteProcess = spawn ( "npx" , [ "vite" , "serve" , tmpAppDestination ] )
90+
91+ // prepare the image location
92+ cleanDir ( imageDestination )
9493
9594 // extract the screenshots
9695 console . log ( 'Generating screenshots...' )
97- spawnSync ( "npx" , [ "cypress" , "run" ,
98- "--config" , `downloadsFolder=${ destination } /images ` ,
96+ await spawnSync ( "npx" , [ "cypress" , "run" ,
97+ "--config" , `downloadsFolder=${ imageDestination } ` ,
9998 "--config-file" , `cypress/cypress.config.js` ,
100- ] )
99+ "--browser" , "chromium" ,
100+ "--spec" , "cypress/e2e/block_images.cy.js" ,
101+ ] , { stdio : 'inherit' } )
101102 console . log ( 'Generation complete.' )
102103
103104 // kill the server
104105 if ( ! viteProcess . kill ( ) ) {
105106 console . log ( "Vite failed to exit gracefully" )
106107 process . exit ( 1 )
107108 }
109+
108110 console . log ( 'Server closed.' )
109111 }
110112 } ,
111113 exporterNames = Object . keys ( exporters )
112114
115+ // Look up the requested exporter
113116if ( ! exporterNames . includes ( toExport ) ) {
114117 console . error ( `Export Error: No exporter found for: "${ toExport } "\nValid exporters: "${ exporterNames . join ( '", "' ) } "` )
115118 process . exit ( 1 )
116119}
117120
121+ // Execute the export
118122const startTime = Date . now ( )
119123console . log ( `\nStarting Export: ${ toExport } ` )
120124console . log ( "=======================" )
@@ -124,7 +128,8 @@ await exporter()
124128
125129const elapsed = Date . now ( ) - startTime
126130console . log ( "=======================" )
127- console . log ( `🏁 Done. Wrote ${ totalBytesWritten . toFixed ( 3 ) } k in ${ elapsed } ms 🏁` )
131+ console . log ( `🏁 Done ( ${ elapsed } ms) 🏁` )
128132
129133
134+ // Bye!
130135process . exit ( 0 )
0 commit comments