diff --git a/Gruntfile.js b/Gruntfile.js
index 815ccce3af535..82c346bec7443 100644
--- a/Gruntfile.js
+++ b/Gruntfile.js
@@ -47,7 +47,7 @@ module.exports = function(grunt) {
'wp-includes/js/',
],
- // All files copied from the Gutenberg repository excluded from version control.
+ // Unversioned files copied from the Gutenberg repository.
gutenbergFiles = [
'wp-includes/js/dist',
'wp-includes/css/dist',
@@ -55,6 +55,14 @@ module.exports = function(grunt) {
'wp-includes/icons',
],
+ // Files copied from Gutenberg subject to version control.
+ gutenbergVersionedFiles = [
+ 'wp-includes/images/icon-library',
+ 'wp-includes/build',
+ 'wp-includes/blocks/*',
+ '!wp-includes/blocks/index.php',
+ ],
+
// All files built by Webpack, in /src or /build.
// Webpack only builds Core-specific media files and development scripts.
// Blocks, packages, script modules, and vendors come from the Gutenberg build.
@@ -245,6 +253,37 @@ module.exports = function(grunt) {
gutenberg: gutenbergFiles.map( function( file ) {
return setFilePath( WORKING_DIR, file );
}),
+
+ /*
+ * Delete directories and files subjet to version control where the contents come from Gutenberg.
+ *
+ * This handles instances where a file remains present even after being deleted upstream.
+ *
+ * This task is intentionally skipped unless the current task will re-copy the corresponding files.
+ */
+ 'gutenberg-versioned': {
+ filter: function() {
+ var allowedTasks = [
+ 'build',
+ 'build:gutenberg',
+ 'build:gutenberg:versioned',
+ 'clean:gutenberg-versioned',
+ /*
+ * These tasks chain `build` internally, but grunt.cli.tasks only reflects the current task,
+ * which does not include expanded tasks.
+ */
+ 'default',
+ 'qunit:compiled',
+ 'test',
+ ];
+ return allowedTasks.some( function( task ) {
+ return grunt.cli.tasks.indexOf( task ) !== -1;
+ } );
+ },
+ src: gutenbergVersionedFiles.map( function( file ) {
+ return setFilePath( SOURCE_DIR, file );
+ } ),
+ },
dynamic: {
dot: true,
expand: true,
@@ -290,6 +329,10 @@ module.exports = function(grunt) {
cwd: SOURCE_DIR,
src: buildFiles.concat( [
'!wp-includes/assets/**', // Assets is extracted into separate copy tasks.
+ // Gutenberg-sourced files in src/wp-includes/assets/ that must propagate to build/.
+ 'wp-includes/assets/icon-library-manifest.php',
+ 'wp-includes/assets/script-loader-packages.php',
+ 'wp-includes/assets/script-modules-packages.php',
'!js/**', // JavaScript is extracted into separate copy tasks.
'!.{svn,git}', // Exclude version control folders.
'!wp-includes/version.php', // Exclude version.php.
@@ -666,7 +709,7 @@ module.exports = function(grunt) {
'constants.php',
'pages/**/*.php',
],
- dest: WORKING_DIR + 'wp-includes/build/',
+ dest: SOURCE_DIR + 'wp-includes/build/',
} ],
},
/*
@@ -683,7 +726,7 @@ module.exports = function(grunt) {
expand: true,
cwd: 'gutenberg/build',
src: [],
- dest: WORKING_DIR + 'wp-includes/build/',
+ dest: SOURCE_DIR + 'wp-includes/build/',
},
'gutenberg-js': {
files: [ {
@@ -692,7 +735,7 @@ module.exports = function(grunt) {
src: [
'pages/**/*.js',
],
- dest: WORKING_DIR + 'wp-includes/build/',
+ dest: SOURCE_DIR + 'wp-includes/build/',
} ],
},
'gutenberg-modules': {
@@ -738,11 +781,11 @@ module.exports = function(grunt) {
files: [
{
src: 'gutenberg/lib/theme.json',
- dest: WORKING_DIR + 'wp-includes/theme.json',
+ dest: SOURCE_DIR + 'wp-includes/theme.json',
},
{
src: 'gutenberg/lib/theme-i18n.json',
- dest: WORKING_DIR + 'wp-includes/theme-i18n.json',
+ dest: SOURCE_DIR + 'wp-includes/theme-i18n.json',
},
],
},
@@ -751,7 +794,7 @@ module.exports = function(grunt) {
expand: true,
cwd: 'gutenberg/packages/icons/src/library',
src: '*.svg',
- dest: WORKING_DIR + 'wp-includes/images/icon-library',
+ dest: SOURCE_DIR + 'wp-includes/images/icon-library',
} ],
},
'icon-library-manifest': {
@@ -773,7 +816,7 @@ module.exports = function(grunt) {
},
files: [ {
src: 'gutenberg/packages/icons/src/manifest.php',
- dest: WORKING_DIR + 'wp-includes/assets/icon-library-manifest.php',
+ dest: SOURCE_DIR + 'wp-includes/assets/icon-library-manifest.php',
} ],
},
},
@@ -1675,12 +1718,20 @@ module.exports = function(grunt) {
} );
} );
+ // Underlying runner. Accepts colon-suffixed scope (`:versioned`, `:unversioned`)
+ // to drive the corresponding subset of tools/gutenberg/copy.js. With no scope
+ // (`gutenberg:copy`), the script runs in `all` mode.
grunt.registerTask( 'gutenberg:copy', 'Copies Gutenberg JS packages and block assets to WordPress Core.', function() {
const done = this.async();
- const buildDir = grunt.option( 'dev' ) ? 'src' : 'build';
+ const scope = this.args[ 0 ] || 'all';
+ const args = [ 'tools/gutenberg/copy.js', `--scope=${ scope }` ];
+ // Unversioned JS packages need to know WORKING_DIR semantics; versioned files always land in src/.
+ if ( scope !== 'versioned' ) {
+ args.push( `--build-dir=${ grunt.option( 'dev' ) ? 'src' : 'build' }` );
+ }
grunt.util.spawn( {
cmd: 'node',
- args: [ 'tools/gutenberg/copy.js', `--build-dir=${ buildDir }` ],
+ args: args,
opts: { stdio: 'inherit' }
}, function( error ) {
done( ! error );
@@ -2156,40 +2207,72 @@ module.exports = function(grunt) {
) );
} );
- grunt.registerTask( 'build:gutenberg', [
+ /*
+ * Versioned half: paths under version control. Always written to src/.
+ *
+ * Called early in prod builds so the fresh content propagates from src/ to
+ * build/ via the subsequent build:files ā copy:files step.
+ */
+ grunt.registerTask( 'build:gutenberg:versioned', [
+ 'gutenberg:verify',
+ 'clean:gutenberg-versioned',
'copy:gutenberg-php',
'routes:setup',
'copy:routes',
'copy:gutenberg-js',
- 'gutenberg:copy',
- 'copy:gutenberg-modules',
- 'copy:gutenberg-styles',
'copy:gutenberg-theme-json',
'copy:icon-library-images',
'copy:icon-library-manifest',
+ 'gutenberg:copy:versioned',
+ ] );
+
+ /*
+ * Unversioned half: gitignored dist artifacts. Written to WORKING_DIR
+ * (src/ in dev, build/ in prod).
+ *
+ * Called late in the build chain so the freshly-built dist content is not
+ * wiped by clean:files / clean:js. Intentionally does NOT call clean:gutenberg
+ * because that would wipe vendor files placed earlier by copy:vendor-js.
+ */
+ grunt.registerTask( 'build:gutenberg:unversioned', [
+ 'copy:gutenberg-modules',
+ 'copy:gutenberg-styles',
+ 'gutenberg:copy:unversioned',
+ ] );
+
+ // Combined target for callers that don't need to interleave with the rest of the build.
+ grunt.registerTask( 'build:gutenberg', [
+ 'build:gutenberg:versioned',
+ 'build:gutenberg:unversioned',
] );
grunt.registerTask( 'build', function() {
if ( grunt.option( 'dev' ) ) {
grunt.task.run( [
- 'gutenberg:verify',
+ // Refresh versioned src/ paths first.
+ 'build:gutenberg:versioned',
'build:js',
'build:css',
'build:codemirror',
- 'build:gutenberg',
- 'build:certificates'
+ // Populate dist artifacts LAST so clean:js doesn't wipe them.
+ 'build:gutenberg:unversioned',
+ 'build:certificates',
] );
} else {
grunt.task.run( [
- 'gutenberg:verify',
- 'build:certificates',
+ // Refresh versioned src/ paths first so copy:files (inside build:files)
+ // propagates the new Gutenberg state into build/.
+ 'build:gutenberg:versioned',
'build:files',
'build:js',
'build:css',
'build:codemirror',
- 'build:gutenberg',
+ // Populate dist artifacts in build/ last so clean:files/clean:js
+ // can't wipe them.
+ 'build:gutenberg:unversioned',
+ 'build:certificates',
'replace:source-maps',
- 'verify:build'
+ 'verify:build',
] );
}
} );
diff --git a/src/wp-includes/images/icon-library/tabs-menu-item.svg b/src/wp-includes/images/icon-library/tabs-menu-item.svg
deleted file mode 100644
index 2e8102d5d7f9b..0000000000000
--- a/src/wp-includes/images/icon-library/tabs-menu-item.svg
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git a/src/wp-includes/images/icon-library/tabs-menu.svg b/src/wp-includes/images/icon-library/tabs-menu.svg
deleted file mode 100644
index d42453416b532..0000000000000
--- a/src/wp-includes/images/icon-library/tabs-menu.svg
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git a/src/wp-includes/images/icon-library/time-to-read.svg b/src/wp-includes/images/icon-library/time-to-read.svg
deleted file mode 100644
index fd368c5e4fc80..0000000000000
--- a/src/wp-includes/images/icon-library/time-to-read.svg
+++ /dev/null
@@ -1,3 +0,0 @@
-
diff --git a/tools/gutenberg/copy.js b/tools/gutenberg/copy.js
index 8589c9581bed1..ce3df4602cb78 100644
--- a/tools/gutenberg/copy.js
+++ b/tools/gutenberg/copy.js
@@ -20,20 +20,30 @@ const gutenbergDir = path.join( rootDir, 'gutenberg' );
const gutenbergBuildDir = path.join( gutenbergDir, 'build' );
/*
- * Determine build target from command line argument (--dev or --build-dir).
- * Default to 'src' for development.
+ * Scope selects which subset of files to copy.
+ * - `versioned` : blocks/, generated PHP under assets/ (script-loader, script-modules), blocks-json,
+ * require-{dynamic,static}-blocks. Always written under src/.
+ * - `unversioned`: top-level @wordpress JS packages under wp-includes/js/dist/. Written to the
+ * directory chosen by --build-dir / --dev (src/ in dev builds, build/ in prod builds).
+ * - `all` (default): both, with the same target-dir rules as above.
*/
const args = process.argv.slice( 2 );
+const scopeArg = args.find( ( arg ) => arg.startsWith( '--scope=' ) );
+const scope = scopeArg ? scopeArg.split( '=' )[ 1 ] : 'all';
+
const buildDirArg = args.find( ( arg ) => arg.startsWith( '--build-dir=' ) );
-const buildTarget = buildDirArg
+const buildDir = buildDirArg
? buildDirArg.split( '=' )[ 1 ]
: args.includes( '--dev' )
? 'src'
: 'build';
-const wpIncludesDir = path.join( rootDir, buildTarget, 'wp-includes' );
+// Versioned outputs always go to src/.
+const wpIncludesDir = path.join( rootDir, 'src', 'wp-includes' );
+// Unversioned JS packages follow WORKING_DIR (--build-dir / --dev).
+const unversionedWpIncludesDir = path.join( rootDir, buildDir, 'wp-includes' );
-/**
+/*
* Copy configuration.
* Defines what to copy from Gutenberg build and where it goes in Core.
*/
@@ -508,7 +518,7 @@ function generateBlocksJson() {
* Main execution function.
*/
async function main() {
- console.log( `š¦ Copying Gutenberg build to ${ buildTarget }/...` );
+ console.log( `š¦ Copying Gutenberg build (scope: ${ scope })...` );
if ( ! fs.existsSync( gutenbergBuildDir ) ) {
console.error( 'ā Gutenberg build directory not found' );
@@ -516,11 +526,12 @@ async function main() {
process.exit( 1 );
}
- // 1. Copy JavaScript packages.
+ // 1. Copy JavaScript packages (unversioned ā WORKING_DIR).
+ if ( scope === 'unversioned' || scope === 'all' ) {
console.log( '\nš¦ Copying JavaScript packages...' );
const scriptsConfig = COPY_CONFIG.scripts;
const scriptsSrc = path.join( gutenbergBuildDir, scriptsConfig.source );
- const scriptsDest = path.join( wpIncludesDir, scriptsConfig.destination );
+ const scriptsDest = path.join( unversionedWpIncludesDir, scriptsConfig.destination );
if ( fs.existsSync( scriptsSrc ) ) {
const entries = fs.readdirSync( scriptsSrc, { withFileTypes: true } );
@@ -601,26 +612,29 @@ async function main() {
console.log( ' ā
JavaScript packages copied' );
}
+ }
- // 2. Copy blocks (unified: scripts, styles, PHP, JSON).
- console.log( '\nš¦ Copying blocks...' );
- copyBlockAssets( COPY_CONFIG.blocks );
+ if ( scope === 'versioned' || scope === 'all' ) {
+ // 2. Copy blocks (unified: scripts, styles, PHP, JSON).
+ console.log( '\nš¦ Copying blocks...' );
+ copyBlockAssets( COPY_CONFIG.blocks );
- // 3. Generate script-modules-packages.php from individual asset files.
- console.log( '\nš¦ Generating script-modules-packages.php...' );
- generateScriptModulesPackages();
+ // 3. Generate script-modules-packages.php from individual asset files.
+ console.log( '\nš¦ Generating script-modules-packages.php...' );
+ generateScriptModulesPackages();
- // 4. Generate script-loader-packages.php.
- console.log( '\nš¦ Generating script-loader-packages.php...' );
- generateScriptLoaderPackages();
+ // 4. Generate script-loader-packages.php.
+ console.log( '\nš¦ Generating script-loader-packages.php...' );
+ generateScriptLoaderPackages();
- // 5. Generate require-dynamic-blocks.php and require-static-blocks.php.
- console.log( '\nš¦ Generating block registration files...' );
- generateBlockRegistrationFiles();
+ // 5. Generate require-dynamic-blocks.php and require-static-blocks.php.
+ console.log( '\nš¦ Generating block registration files...' );
+ generateBlockRegistrationFiles();
- // 6. Generate blocks-json.php from block.json files.
- console.log( '\nš¦ Generating blocks-json.php...' );
- generateBlocksJson();
+ // 6. Generate blocks-json.php from block.json files.
+ console.log( '\nš¦ Generating blocks-json.php...' );
+ generateBlocksJson();
+ }
console.log( '\nā
Copy complete!' );
}