Skip to content

Commit

Permalink
Build: Include Core blocks' render and variations files (#63311)
Browse files Browse the repository at this point in the history
If a Core block's `block.json` contains a `render` and/or `variations` field that points to a PHP file name, copy those files to the build directory.

Co-authored-by: ockham <bernhard-reiter@git.wordpress.org>
Co-authored-by: gziolo <gziolo@git.wordpress.org>
  • Loading branch information
3 people committed Sep 10, 2024
1 parent aca9273 commit cc133bf
Show file tree
Hide file tree
Showing 5 changed files with 103 additions and 60 deletions.
51 changes: 5 additions & 46 deletions packages/scripts/config/webpack.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ const RtlCssPlugin = require( 'rtlcss-webpack-plugin' );
const TerserPlugin = require( 'terser-webpack-plugin' );
const { realpathSync } = require( 'fs' );
const { sync: glob } = require( 'fast-glob' );
const { validate } = require( 'schema-utils' );

/**
* WordPress dependencies
Expand All @@ -32,11 +31,11 @@ const {
hasPostCSSConfig,
getWordPressSrcDirectory,
getWebpackEntryPoints,
getPhpFilePaths,
getAsBooleanFromENV,
getBlockJsonModuleFields,
getBlockJsonScriptFields,
fromProjectRoot,
PhpFilePathsPlugin,
} = require( '../utils' );

const isProduction = process.env.NODE_ENV === 'production';
Expand All @@ -50,49 +49,6 @@ const hasExperimentalModulesFlag = getAsBooleanFromENV(
'WP_EXPERIMENTAL_MODULES'
);

const phpFilePathsPluginSchema = {
type: 'object',
properties: {
props: {
type: 'array',
items: {
type: 'string',
},
},
},
};

/**
* The plugin recomputes PHP file paths once on each compilation. It is necessary to avoid repeating processing
* when filtering every discovered PHP file in the source folder. This is the most performant way to ensure that
* changes in `block.json` files are picked up in watch mode.
*/
class PhpFilePathsPlugin {
/**
* PHP file paths from `render` and `variations` props found in `block.json` files.
*
* @type {string[]}
*/
static paths;

constructor( options = {} ) {
validate( phpFilePathsPluginSchema, options, {
name: 'PHP File Paths Plugin',
baseDataPath: 'options',
} );

this.options = options;
}

apply( compiler ) {
const pluginName = this.constructor.name;

compiler.hooks.thisCompilation.tap( pluginName, () => {
this.constructor.paths = getPhpFilePaths( this.options.props );
} );
}
}

const cssLoaders = [
{
loader: MiniCSSExtractPlugin.loader,
Expand Down Expand Up @@ -345,7 +301,10 @@ const scriptConfig = {
cleanStaleWebpackAssets: false,
} ),

new PhpFilePathsPlugin( { props: [ 'render', 'variations' ] } ),
new PhpFilePathsPlugin( {
context: getWordPressSrcDirectory(),
props: [ 'render', 'variations' ],
} ),
new CopyWebpackPlugin( {
patterns: [
{
Expand Down
13 changes: 7 additions & 6 deletions packages/scripts/utils/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -351,22 +351,23 @@ function getWebpackEntryPoints( buildType ) {
/**
* Returns the list of PHP file paths found in `block.json` files for the given props.
*
* @param {string[]} props The props to search for in the `block.json` files.
* @param {string} context The path to search for `block.json` files.
* @param {string[]} props The props to search for in the `block.json` files.
* @return {string[]} The list of PHP file paths.
*/
function getPhpFilePaths( props ) {
function getPhpFilePaths( context, props ) {
// Continue only if the source directory exists.
if ( ! hasProjectFile( getWordPressSrcDirectory() ) ) {
if ( ! hasProjectFile( context ) ) {
return [];
}

// Checks whether any block metadata files can be detected in the defined source directory.
const blockMetadataFiles = glob( '**/block.json', {
absolute: true,
cwd: fromProjectRoot( getWordPressSrcDirectory() ),
cwd: fromProjectRoot( context ),
} );

const srcDirectory = fromProjectRoot( getWordPressSrcDirectory() + sep );
const srcDirectory = fromProjectRoot( context + sep );

return blockMetadataFiles.flatMap( ( blockMetadataFile ) => {
const blockJson = JSON.parse( readFileSync( blockMetadataFile ) );
Expand Down Expand Up @@ -396,7 +397,7 @@ function getPhpFilePaths( props ) {
) }" listed in "${ blockMetadataFile.replace(
fromProjectRoot( sep ),
''
) }". File is located outside of the "${ getWordPressSrcDirectory() }" directory.`
) }". File is located outside of the "${ context }" directory.`
)
);
continue;
Expand Down
2 changes: 2 additions & 0 deletions packages/scripts/utils/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ const {
getBlockJsonModuleFields,
getBlockJsonScriptFields,
} = require( './block-json' );
const { PhpFilePathsPlugin } = require( './php-file-paths-plugin' );

module.exports = {
fromProjectRoot,
Expand All @@ -55,5 +56,6 @@ module.exports = {
hasPostCSSConfig,
hasPrettierConfig,
hasProjectFile,
PhpFilePathsPlugin,
spawnScript,
};
60 changes: 60 additions & 0 deletions packages/scripts/utils/php-file-paths-plugin.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
/**
* External dependencies
*/
const { validate } = require( 'schema-utils' );

/**
* Internal dependencies
*/
const { getPhpFilePaths } = require( './config' );

const phpFilePathsPluginSchema = {
type: 'object',
properties: {
context: {
type: 'string',
},
props: {
type: 'array',
items: {
type: 'string',
},
},
},
};

/**
* The plugin recomputes PHP file paths once on each compilation. It is necessary to avoid repeating processing
* when filtering every discovered PHP file in the source folder. This is the most performant way to ensure that
* changes in `block.json` files are picked up in watch mode.
*/
class PhpFilePathsPlugin {
/**
* PHP file paths from `render` and `variations` props found in `block.json` files.
*
* @type {string[]}
*/
static paths;

constructor( options = {} ) {
validate( phpFilePathsPluginSchema, options, {
name: 'PHP File Paths Plugin',
baseDataPath: 'options',
} );

this.options = options;
}

apply( compiler ) {
const pluginName = this.constructor.name;

compiler.hooks.thisCompilation.tap( pluginName, () => {
this.constructor.paths = getPhpFilePaths(
this.options.context,
this.options.props
);
} );
}
}

module.exports = { PhpFilePathsPlugin };
37 changes: 29 additions & 8 deletions tools/webpack/blocks.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,13 @@
const CopyWebpackPlugin = require( 'copy-webpack-plugin' );
const { join, sep } = require( 'path' );
const fastGlob = require( 'fast-glob' );
const { realpathSync } = require( 'fs' );

/**
* WordPress dependencies
*/
const DependencyExtractionWebpackPlugin = require( '@wordpress/dependency-extraction-webpack-plugin' );
const { PhpFilePathsPlugin } = require( '@wordpress/scripts/utils' );

/**
* Internal dependencies
Expand Down Expand Up @@ -90,6 +92,10 @@ module.exports = [
plugins: [
...plugins,
new DependencyExtractionWebpackPlugin( { injectPolyfill: false } ),
new PhpFilePathsPlugin( {
context: './packages/block-library/src/',
props: [ 'render', 'variations' ],
} ),
new CopyWebpackPlugin( {
patterns: [].concat(
[
Expand Down Expand Up @@ -127,17 +133,32 @@ module.exports = [
'build/widgets/blocks/',
} ).flatMap( ( [ from, to ] ) => [
{
from: `${ from }/**/index.php`,
from: `${ from }/**/*.php`,
to( { absoluteFilename } ) {
const [ , dirname ] = absoluteFilename.match(
new RegExp(
`([\\w-]+)${ escapeRegExp(
sep
) }index\\.php$`
const [ , dirname, basename ] =
absoluteFilename.match(
new RegExp(
`([\\w-]+)${ escapeRegExp(
sep
) }([\\w-]+)\\.php$`
)
);

if ( basename === 'index' ) {
return join( to, `${ dirname }.php` );
}
return join( to, dirname, `${ basename }.php` );
},
filter: ( filepath ) => {
return (
filepath.endsWith( sep + 'index.php' ) ||
PhpFilePathsPlugin.paths.includes(
realpathSync( filepath ).replace(
/\\/g,
'/'
)
)
);

return join( to, `${ dirname }.php` );
},
transform: ( content ) => {
const prefix = 'gutenberg_';
Expand Down

0 comments on commit cc133bf

Please sign in to comment.