diff --git a/.eslintrc.js b/.eslintrc.js index f097e8068bb..eed2db928ff 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -9,7 +9,7 @@ module.exports = { '@wordpress/valid-sprintf': 'warn', 'jsdoc/check-tag-names': [ 'error', - { definedTags: [ 'jest-environment' ] }, + { definedTags: [ 'jest-environment', 'hook' ] }, ], 'import/no-extraneous-dependencies': 'warn', 'import/no-unresolved': 'warn', diff --git a/bin/hook-reference/data.js b/bin/hook-reference/data.js new file mode 100644 index 00000000000..a74ab934650 --- /dev/null +++ b/bin/hook-reference/data.js @@ -0,0 +1,73 @@ +const { readFile } = require( 'fs' ).promises; +const exec = require( 'await-exec' ); +const { parse } = require( 'comment-parser/lib' ); +const { relative, resolve } = require( 'path' ); +const chalk = require( 'chalk' ); + +const getHooks = ( parsedData ) => + parsedData.filter( ( docBlock ) => + docBlock.tags.some( ( tag ) => tag.tag === 'hook' ) + ); + +const getSourceFile = ( file, commit, { source } ) => { + const first = source[ 0 ].number + 1; + const last = source[ source.length - 1 ].number + 1; + + return `https://github.com/woocommerce/woocommerce-admin/blob/${ commit }/${ file }#L${ first }-L${ last }`; +}; + +const logProgress = ( fileName, { tags } ) => { + const hook = tags.find( ( tag ) => tag.tag === 'hook' ); + console.log( + chalk.cyan( `${ hook.name } ` ) + + chalk.yellow( 'generated in ' ) + + chalk.yellow.underline( fileName ) + ); +}; + +const addSourceFiles = async ( hooks, fileName ) => { + const { stdout } = await exec( 'git log --pretty="format:%H" -1' ); + const commit = stdout.trim(); + + return hooks.map( ( hook ) => { + logProgress( fileName, hook ); + hook.sourceFile = getSourceFile( fileName, commit, hook ); + return hook; + } ); +}; + +const prepareHooks = async ( path ) => { + const data = await readFile( path, 'utf-8' ).catch( ( err ) => + console.error( 'Failed to read file', err ) + ); + const fileName = relative( resolve( __dirname, '../../' ), path ); + + const parsedData = parse( data ); + const rawHooks = getHooks( parsedData ); + return await addSourceFiles( rawHooks, fileName ); +}; + +const makeDocObjects = async ( path ) => { + const hooks = await prepareHooks( path ); + return hooks.map( ( { description, tags, sourceFile } ) => { + const example = tags.find( ( tag ) => tag.tag === 'example' ); + const hook = tags.find( ( tag ) => tag.tag === 'hook' ); + return { + description, + sourceFile, + name: hook ? hook.name : '', + example: example ? example.description : '', + }; + } ); +}; + +const createData = async ( paths ) => { + const data = await Promise.all( + paths.map( async ( path ) => { + return await makeDocObjects( path ); + } ) + ); + return data.flat(); +}; + +module.exports = createData; diff --git a/bin/hook-reference/data.json b/bin/hook-reference/data.json new file mode 100644 index 00000000000..39c9262789a --- /dev/null +++ b/bin/hook-reference/data.json @@ -0,0 +1,8 @@ +[ + { + "description": "List of homepage stats enabled by default", + "sourceFile": "https://github.com/woocommerce/woocommerce-admin/blob/ff1a3cb2f3857cfa759fb3c93cedfe630dbd5510/client/homescreen/stats-overview/defaults.js#L5-L16", + "name": "woocommerce_admin_homepage_default_stats", + "example": "addFilter( 'woocommerce_admin_homepage_default_stats', 'plugin-domain', ( defaultStats ) => defaultStats.filter( ( stat ) => stat !== 'jetpack/stats/views' ) );" + } +] diff --git a/bin/hook-reference/index.js b/bin/hook-reference/index.js new file mode 100644 index 00000000000..861c59e46cd --- /dev/null +++ b/bin/hook-reference/index.js @@ -0,0 +1,39 @@ +const fs = require( 'fs' ); +const { stat, readdir, writeFile } = require( 'fs' ).promises; +const { resolve } = require( 'path' ); +const createData = require( './data' ); +const chalk = require( 'chalk' ); + +async function getFilePaths( dir ) { + const subdirs = await readdir( dir ); + const files = await Promise.all( + subdirs.map( async ( subdir ) => { + const res = resolve( dir, subdir ); + return ( await stat( res ) ).isDirectory() + ? getFilePaths( res ) + : res; + } ) + ); + return files.reduce( ( a, f ) => a.concat( f ), [] ); +} + +const writeJSONFile = async ( data ) => { + const fileName = 'bin/hook-reference/data.json'; + const stringifiedData = JSON.stringify( data, null, 4 ); + await writeFile( fileName, stringifiedData + '\n' ); + + console.log( '\n' ); + console.log( + chalk.greenBright( + 'A new Hook Reference data source has been created. See `/bin/hook-reference/data.json` and be sure to commit changes.' + ) + ); +}; + +console.log( chalk.green( 'Preparing Hook Reference data file' ) ); +console.log( '\n' ); + +getFilePaths( 'client' ) + .then( ( paths ) => createData( paths ) ) + .then( ( data ) => writeJSONFile( data ) ) + .catch( ( e ) => console.error( e ) ); diff --git a/client/homescreen/stats-overview/defaults.js b/client/homescreen/stats-overview/defaults.js index 957e9c7a786..994f1a4c76e 100644 --- a/client/homescreen/stats-overview/defaults.js +++ b/client/homescreen/stats-overview/defaults.js @@ -2,7 +2,18 @@ * External dependencies */ import { applyFilters } from '@wordpress/hooks'; - +/** + * List of homepage stats enabled by default + * + * @hook woocommerce_admin_homepage_default_stats + * @example + * addFilter( + * 'woocommerce_admin_homepage_default_stats', + * 'plugin-domain', + * ( defaultStats ) => + * defaultStats.filter( ( stat ) => stat !== 'jetpack/stats/views' ) + *); + */ export const DEFAULT_STATS = applyFilters( 'woocommerce_admin_homepage_default_stats', [ diff --git a/package-lock.json b/package-lock.json index 15c642c4a6d..3c36bd8991d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8800,16 +8800,6 @@ "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-20.2.0.tgz", "integrity": "sha512-37RSHht+gzzgYeobbG+KWryeAW8J33Nhr69cjTqSYymXVZEN9NbRYWoYlRtDhHKPVT1FyNKwaTPC1NynKZpzRA==" }, - "@types/yauzl": { - "version": "2.9.1", - "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.9.1.tgz", - "integrity": "sha512-A1b8SU4D10uoPjwb0lnHmmu8wZhR9d+9o2PKBQT2jU5YPTKsxac6M2qGAdY7VcL+dHHhARVUDmeg0rOrcd9EjA==", - "dev": true, - "optional": true, - "requires": { - "@types/node": "*" - } - }, "@typescript-eslint/eslint-plugin": { "version": "4.15.2", "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.15.2.tgz", @@ -10805,13 +10795,14 @@ "version": "file:packages/experimental", "dev": true, "requires": { + "@babel/runtime": "7.13.10", "@wordpress/components": "10.2.0" }, "dependencies": { "@babel/runtime": { - "version": "7.12.5", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.12.5.tgz", - "integrity": "sha512-plcc+hbExy3McchJCEQG3knOsuh3HH+Prx1P6cLIkET/0dLuQDEnrT+s27Axgc9bqfsmNUNHfscgMUdBpC9xfg==", + "version": "7.13.10", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.13.10.tgz", + "integrity": "sha512-4QPkjJq6Ns3V/RgpEahRk+AGfL0eO6RHHtTWoNNr5mO49G6B5+X6d6THgWEAvTrznU5xYpbAlVKRYcsCgh/Akw==", "dev": true, "requires": { "regenerator-runtime": "^0.13.4" @@ -12775,6 +12766,12 @@ "fill-range": "^7.0.1" } }, + "chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", + "dev": true + }, "color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", @@ -12983,6 +12980,18 @@ "debug": "^4.1.1", "get-stream": "^5.1.0", "yauzl": "^2.10.0" + }, + "dependencies": { + "@types/yauzl": { + "version": "2.9.1", + "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.9.1.tgz", + "integrity": "sha512-A1b8SU4D10uoPjwb0lnHmmu8wZhR9d+9o2PKBQT2jU5YPTKsxac6M2qGAdY7VcL+dHHhARVUDmeg0rOrcd9EjA==", + "dev": true, + "optional": true, + "requires": { + "@types/node": "*" + } + } } }, "fast-glob": { @@ -13628,6 +13637,30 @@ "tar-fs": "^2.0.0", "unbzip2-stream": "^1.3.3", "ws": "^7.2.3" + }, + "dependencies": { + "tar-fs": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz", + "integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==", + "dev": true, + "requires": { + "chownr": "^1.1.1", + "mkdirp-classic": "^0.5.2", + "pump": "^3.0.0", + "tar-stream": "^2.1.4" + } + }, + "unbzip2-stream": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/unbzip2-stream/-/unbzip2-stream-1.4.3.tgz", + "integrity": "sha512-mlExGW4w71ebDJviH16lQLtZS32VKqsSfk80GCfUlwT/4/hNRFsoscrF/c++9xinkMzECL1uL9DDwXqFWkruPg==", + "dev": true, + "requires": { + "buffer": "^5.2.1", + "through": "^2.3.8" + } + } } }, "read-pkg": { @@ -14771,6 +14804,12 @@ } } }, + "await-exec": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/await-exec/-/await-exec-0.1.2.tgz", + "integrity": "sha512-BQUiyBLScS0+YPnnCZZGjb78mZ8sQ8aKgxarDPNw05rpbaCS7VIQSLy2tgjZKct9Dn1xLbKMXOpA98OWei90zA==", + "dev": true + }, "aws-sign2": { "version": "0.7.0", "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", @@ -17334,9 +17373,9 @@ "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==" }, "comment-parser": { - "version": "0.7.6", - "resolved": "https://registry.npmjs.org/comment-parser/-/comment-parser-0.7.6.tgz", - "integrity": "sha512-GKNxVA7/iuTnAqGADlTWX4tkhzxZKXp5fLJqKTlQLHkE65XDUKutZ3BHaJC5IGcper2tT3QRD1xr4o3jNpgXXg==", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/comment-parser/-/comment-parser-1.1.2.tgz", + "integrity": "sha512-AOdq0i8ghZudnYv8RUnHrhTgafUGs61Rdz9jemU5x2lnZwAWyOq7vySo626K59e1fVKH1xSRorJwPVRLSWOoAQ==", "dev": true }, "commondir": { @@ -20866,6 +20905,12 @@ "spdx-expression-parse": "^3.0.1" }, "dependencies": { + "comment-parser": { + "version": "0.7.6", + "resolved": "https://registry.npmjs.org/comment-parser/-/comment-parser-0.7.6.tgz", + "integrity": "sha512-GKNxVA7/iuTnAqGADlTWX4tkhzxZKXp5fLJqKTlQLHkE65XDUKutZ3BHaJC5IGcper2tT3QRD1xr4o3jNpgXXg==", + "dev": true + }, "semver": { "version": "7.3.4", "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.4.tgz", @@ -37924,26 +37969,6 @@ } } }, - "tar-fs": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz", - "integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==", - "dev": true, - "requires": { - "chownr": "^1.1.1", - "mkdirp-classic": "^0.5.2", - "pump": "^3.0.0", - "tar-stream": "^2.1.4" - }, - "dependencies": { - "chownr": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", - "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", - "dev": true - } - } - }, "tar-stream": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", @@ -38746,16 +38771,6 @@ "integrity": "sha1-8pzr8B31F5ErtY/5xOUP3o4zMg0=", "dev": true }, - "unbzip2-stream": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/unbzip2-stream/-/unbzip2-stream-1.4.3.tgz", - "integrity": "sha512-mlExGW4w71ebDJviH16lQLtZS32VKqsSfk80GCfUlwT/4/hNRFsoscrF/c++9xinkMzECL1uL9DDwXqFWkruPg==", - "dev": true, - "requires": { - "buffer": "^5.2.1", - "through": "^2.3.8" - } - }, "unc-path-regex": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/unc-path-regex/-/unc-path-regex-0.1.2.tgz", diff --git a/package.json b/package.json index 942b8290a0c..3de9cfc1ef1 100644 --- a/package.json +++ b/package.json @@ -77,7 +77,8 @@ "build-storybook": "build-storybook -c ./storybook", "changelog": "node ./bin/changelog --changelogSrcType='ZENHUB_RELEASE'", "bump-version": "npm run -s install-if-deps-outdated && php ./bin/update-version.php", - "wp-env-mysql-port": "node ./docker/wc-admin-wp-env/mysql-port.js" + "wp-env-mysql-port": "node ./docker/wc-admin-wp-env/mysql-port.js", + "create-hook-reference": "node ./bin/hook-reference/index.js" }, "changelog": { "labelPrefix": "[Type]", @@ -176,11 +177,13 @@ "@wordpress/scripts": "12.6.1", "ast-types": "0.14.2", "autoprefixer": "10.2.4", + "await-exec": "^0.1.2", "babel-jest": "26.6.3", "babel-loader": "8.2.2", "babel-plugin-transform-class-properties": "6.24.1", "babel-plugin-transform-es2015-template-literals": "6.22.0", "chalk": "4.1.0", + "comment-parser": "^1.1.2", "concurrently": "5.3.0", "config": "3.3.6", "copy-webpack-plugin": "5.1.1", diff --git a/readme.txt b/readme.txt index c4363d40064..5d80f63b19a 100644 --- a/readme.txt +++ b/readme.txt @@ -122,6 +122,7 @@ Release and roadmap notes are available on the [WooCommerce Developers Blog](htt - Add: CES survey for importing products #6419 - Add: CES survey for adding product categories, tags, and attributes #6418 - Add: Include tracking for mail poet installs in the selective bundle install #6603 +- Dev: Add script automation for gathering hooks and filters. #6454 == 2.1.3 3/14/2021 ==