diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index c6d9694eae9b6..d1dc33c9b08ed 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -31,7 +31,7 @@ # Tooling /bin @ntwb @nerrad @ajitbohra -/bin/update-readmes.js @ntwb @nerrad @ajitbohra @nosolosw +/bin/api-docs @ntwb @nerrad @ajitbohra @nosolosw /docs/tool @youknowriad @chrisvanpatten @ajitbohra @nosolosw /packages/babel-plugin-import-jsx-pragma @gziolo @ntwb @nerrad @ajitbohra /packages/babel-plugin-makepot @ntwb @nerrad @ajitbohra diff --git a/bin/api-docs/are-readmes-unstaged.js b/bin/api-docs/are-readmes-unstaged.js new file mode 100644 index 0000000000000..19c7eeba8d162 --- /dev/null +++ b/bin/api-docs/are-readmes-unstaged.js @@ -0,0 +1,28 @@ +#!/usr/bin/env node + +/** + * Node dependencies. + */ +const { join } = require( 'path' ); +const chalk = require( 'chalk' ); +const execSync = require( 'child_process' ).execSync; + +/** + * Local dependencies. + */ +const getPackages = require( './packages' ); + +const getUnstagedFiles = () => execSync( 'git diff --name-only', { encoding: 'utf8' } ).split( '\n' ).filter( ( element ) => '' !== element ); +const readmeFiles = getPackages().map( ( [ packageName ] ) => join( 'packages', packageName, 'README.md' ) ); +const unstagedReadmes = getUnstagedFiles().filter( ( element ) => readmeFiles.includes( element ) ); + +if ( unstagedReadmes.length > 0 ) { + process.exitCode = 1; + process.stdout.write( chalk.red( + '\n', + 'Some API docs may be out of date:', + unstagedReadmes.toString(), + 'Either stage them or continue with --no-verify.', + '\n' + ) ); +} diff --git a/bin/api-docs/packages.js b/bin/api-docs/packages.js new file mode 100644 index 0000000000000..0fcc19400bf11 --- /dev/null +++ b/bin/api-docs/packages.js @@ -0,0 +1,44 @@ +const packages = [ + 'a11y', + 'autop', + 'blob', + 'block-editor', + 'block-library', + 'block-serialization-default-parser', + 'blocks', + 'compose', + [ 'core-data', { + 'Autogenerated actions': 'src/actions.js', + 'Autogenerated selectors': 'src/selectors.js', + } ], + 'data', + 'data-controls', + 'date', + 'deprecated', + 'dom', + 'dom-ready', + 'e2e-test-utils', + 'edit-post', + 'element', + 'escape-html', + 'html-entities', + 'i18n', + 'keycodes', + 'plugins', + 'priority-queue', + 'redux-routine', + 'rich-text', + 'shortcode', + 'url', + 'viewport', + 'wordcount', +]; + +module.exports = function() { + return packages.map( ( entry ) => { + if ( ! Array.isArray( entry ) ) { + entry = [ entry, { 'Autogenerated API docs': 'src/index.js' } ]; + } + return entry; + } ); +}; diff --git a/bin/api-docs/update-readmes.js b/bin/api-docs/update-readmes.js new file mode 100755 index 0000000000000..fd66e6cbf39d0 --- /dev/null +++ b/bin/api-docs/update-readmes.js @@ -0,0 +1,35 @@ +/** + * Node dependencies. + */ +const { join } = require( 'path' ); +const spawnSync = require( 'child_process' ).spawnSync; + +/** + * Local dependencies. + */ +const getPackages = require( './packages' ); + +getPackages().forEach( ( entry ) => { + const [ packageName, targetFiles ] = entry; + + Object.entries( targetFiles ).forEach( ( [ token, path ] ) => { + // Each target operates over the same file, so it needs to be processed synchronously, + // as to make sure the processes don't overwrite each other. + const { status, stderr } = spawnSync( + join( __dirname, '..', '..', 'node_modules', '.bin', 'docgen' ).replace( / /g, '\\ ' ), + [ + join( 'packages', packageName, path ), + `--output packages/${ packageName }/README.md`, + '--to-token', + `--use-token "${ token }"`, + '--ignore "/unstable|experimental/i"', + ], + { shell: true }, + ); + + if ( status !== 0 ) { + process.stderr.write( `${ packageName } ${ stderr.toString() }\n` ); + process.exit( 1 ); + } + } ); +} ); diff --git a/bin/update-readmes.js b/bin/update-readmes.js deleted file mode 100755 index 4fb85e423b556..0000000000000 --- a/bin/update-readmes.js +++ /dev/null @@ -1,70 +0,0 @@ -/** - * Node dependencies. - */ -const { join } = require( 'path' ); -const spawnSync = require( 'child_process' ).spawnSync; - -const packages = [ - 'a11y', - 'autop', - 'blob', - 'block-editor', - 'block-library', - 'block-serialization-default-parser', - 'blocks', - 'compose', - [ 'core-data', { - 'Autogenerated actions': 'src/actions.js', - 'Autogenerated selectors': 'src/selectors.js', - } ], - 'data', - 'data-controls', - 'date', - 'deprecated', - 'dom', - 'dom-ready', - 'e2e-test-utils', - 'edit-post', - 'element', - 'escape-html', - 'html-entities', - 'i18n', - 'keycodes', - 'plugins', - 'priority-queue', - 'redux-routine', - 'rich-text', - 'shortcode', - 'url', - 'viewport', - 'wordcount', -]; - -packages.forEach( ( entry ) => { - if ( ! Array.isArray( entry ) ) { - entry = [ entry, { 'Autogenerated API docs': 'src/index.js' } ]; - } - - const [ packageName, targets ] = entry; - - Object.entries( targets ).forEach( ( [ token, path ] ) => { - // Each target operates over the same file, so it needs to be processed synchronously, - // as to make sure the processes don't overwrite each other. - const { status, stderr } = spawnSync( - join( __dirname, '..', 'node_modules', '.bin', 'docgen' ).replace( / /g, '\\ ' ), - [ - join( 'packages', packageName, path ), - `--output packages/${ packageName }/README.md`, - '--to-token', - `--use-token "${ token }"`, - '--ignore "/unstable|experimental/i"', - ], - { shell: true }, - ); - - if ( status !== 0 ) { - process.stderr.write( `${ packageName } ${ stderr.toString() }\n` ); - process.exit( 1 ); - } - } ); -} ); diff --git a/docs/tool/are-data-files-unstaged.js b/docs/tool/are-data-files-unstaged.js new file mode 100644 index 0000000000000..5591de0ae6d62 --- /dev/null +++ b/docs/tool/are-data-files-unstaged.js @@ -0,0 +1,27 @@ +#!/usr/bin/env node + +/** + * Node dependencies. + */ +const chalk = require( 'chalk' ); +const execSync = require( 'child_process' ).execSync; + +/** + * Local dependencies. + */ +const getPackages = require( './packages' ); + +const getUnstagedFiles = () => execSync( 'git diff --name-only', { encoding: 'utf8' } ).split( '\n' ).filter( ( element ) => '' !== element ); +const readmeFiles = getPackages().map( ( [ packageName ] ) => `docs/designers-developers/developers/data/data-${ packageName.replace( '/', '-' ) }.md` ); +const unstagedReadmes = getUnstagedFiles().filter( ( element ) => readmeFiles.includes( element ) ); + +if ( unstagedReadmes.length > 0 ) { + process.exitCode = 1; + process.stdout.write( chalk.red( + '\n', + 'Some API docs may be out of date:', + unstagedReadmes.toString(), + 'Either stage them or continue with --no-verify.', + '\n' + ) ); +} diff --git a/docs/tool/packages.js b/docs/tool/packages.js new file mode 100644 index 0000000000000..5caf4d258e156 --- /dev/null +++ b/docs/tool/packages.js @@ -0,0 +1,26 @@ +const packages = [ + [ 'core', { + 'Autogenerated actions': 'packages/core-data/src/actions.js', + 'Autogenerated selectors': 'packages/core-data/src/selectors.js', + } ], + 'core/annotations', + 'core/blocks', + 'core/block-editor', + 'core/editor', + 'core/edit-post', + 'core/notices', + 'core/nux', + 'core/viewport', +]; + +module.exports = function() { + return packages.map( ( entry ) => { + if ( ! Array.isArray( entry ) ) { + entry = [ entry, { + 'Autogenerated actions': `packages/${ entry.replace( 'core/', '' ) }/src/store/actions.js`, + 'Autogenerated selectors': `packages/${ entry.replace( 'core/', '' ) }/src/store/selectors.js`, + } ]; + } + return entry; + } ); +}; diff --git a/docs/tool/update-data.js b/docs/tool/update-data.js index 46263e788dfe0..4a5d231e3c601 100644 --- a/docs/tool/update-data.js +++ b/docs/tool/update-data.js @@ -4,31 +4,15 @@ const { join } = require( 'path' ); const spawnSync = require( 'child_process' ).spawnSync; -const modules = [ - [ 'core', { - 'Autogenerated actions': 'packages/core-data/src/actions.js', - 'Autogenerated selectors': 'packages/core-data/src/selectors.js', - } ], - 'core/annotations', - 'core/blocks', - 'core/block-editor', - 'core/editor', - 'core/edit-post', - 'core/notices', - 'core/nux', - 'core/viewport', -]; +/** + * Local dependencies. + */ +const getPackages = require( './packages' ); -modules.forEach( ( entry ) => { - if ( ! Array.isArray( entry ) ) { - entry = [ entry, { - 'Autogenerated actions': `packages/${ entry.replace( 'core/', '' ) }/src/store/actions.js`, - 'Autogenerated selectors': `packages/${ entry.replace( 'core/', '' ) }/src/store/selectors.js`, - } ]; - } - const [ namespace, targets ] = entry; +getPackages().forEach( ( entry ) => { + const [ packageName, targetFiles ] = entry; - Object.entries( targets ).forEach( ( [ token, target ] ) => { + Object.entries( targetFiles ).forEach( ( [ token, target ] ) => { // Note that this needs to be a sync process for each output file that is updated: // until docgen provides a way to update many tokens at once, we need to make sure // the output file is updated before starting the second pass for the next token. @@ -36,7 +20,7 @@ modules.forEach( ( entry ) => { join( __dirname, '..', '..', 'node_modules', '.bin', 'docgen' ).replace( / /g, '\\ ' ), [ target, - `--output docs/designers-developers/developers/data/data-${ namespace.replace( '/', '-' ) }.md`, + `--output docs/designers-developers/developers/data/data-${ packageName.replace( '/', '-' ) }.md`, '--to-token', `--use-token "${ token }"`, '--ignore "/unstable|experimental/i"', @@ -45,7 +29,8 @@ modules.forEach( ( entry ) => { ); if ( status !== 0 ) { - throw stderr.toString(); + process.stderr.write( `${ packageName } ${ stderr.toString() }\n` ); + process.exit( 1 ); } } ); } ); diff --git a/package.json b/package.json index 74ba34bb8877f..f6605e2e2b965 100644 --- a/package.json +++ b/package.json @@ -171,7 +171,7 @@ "predev": "npm run check-engines", "dev": "npm run build:packages && concurrently \"wp-scripts start\" \"npm run dev:packages\"", "dev:packages": "node ./bin/packages/watch.js", - "docs:build": "node ./docs/tool/index.js && node ./bin/update-readmes.js", + "docs:build": "node ./docs/tool/index.js && node ./bin/api-docs/update-readmes.js", "fixtures:clean": "rimraf \"packages/e2e-tests/fixtures/blocks/*.+(json|serialized.html)\"", "fixtures:server-registered": "wp-scripts env docker-run php ./bin/get-server-blocks.php > test/integration/full-content/server-registered.json", "fixtures:generate": "npm run fixtures:server-registered && cross-env GENERATE_MISSING_FIXTURES=y npm run test-unit", @@ -228,10 +228,12 @@ "wp-scripts lint-js" ], "{docs/{toc.json,tool/*.js},packages/{*/README.md,*/src/{actions,selectors}.js,components/src/*/**/README.md}}": [ - "node ./docs/tool/index.js" + "node ./docs/tool/index.js", + "node ./docs/tool/are-data-files-unstaged.js" ], "packages/**/*.js": [ - "node ./bin/update-readmes.js" + "node ./bin/api-docs/update-readmes.js", + "node ./bin/api-docs/are-readmes-unstaged.js" ] }, "wp-env": {