@wordpress/build 0.5.0 → 0.5.1-next.06ee73755.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.cache/tsconfig.tsbuildinfo +1 -1
- package/CHANGELOG.md +0 -2
- package/LICENSE.md +1 -1
- package/README.md +47 -5
- package/{src → lib}/build.mjs +272 -137
- package/{src → lib}/dependency-graph.mjs +36 -110
- package/{src → lib}/package-utils.mjs +45 -10
- package/{src → lib}/php-generator.mjs +5 -6
- package/{src → lib}/route-utils.mjs +13 -4
- package/{src → lib}/wordpress-externals-plugin.mjs +77 -15
- package/package.json +11 -8
- package/templates/constants.php.template +14 -0
- package/templates/index.php.template +0 -6
- package/templates/module-registration.php.template +3 -1
- package/templates/page-wp-admin.php.template +68 -28
- package/templates/page.php.template +13 -4
- package/templates/routes-registration.php.template +4 -2
- package/templates/script-registration.php.template +4 -2
- package/templates/style-registration.php.template +6 -2
- package/tsconfig.json +1 -1
- package/templates/version.php.template +0 -11
package/{src → lib}/build.mjs
RENAMED
|
@@ -17,6 +17,7 @@ import rtlcss from 'rtlcss';
|
|
|
17
17
|
import cssnano from 'cssnano';
|
|
18
18
|
import babel from 'esbuild-plugin-babel';
|
|
19
19
|
import { camelCase } from 'change-case';
|
|
20
|
+
import { NodePackageImporter } from 'sass-embedded';
|
|
20
21
|
|
|
21
22
|
/**
|
|
22
23
|
* Internal dependencies
|
|
@@ -43,7 +44,7 @@ const ROOT_DIR = process.cwd();
|
|
|
43
44
|
const PACKAGES_DIR = path.join( ROOT_DIR, 'packages' );
|
|
44
45
|
const BUILD_DIR = path.join( ROOT_DIR, 'build' );
|
|
45
46
|
|
|
46
|
-
const SOURCE_EXTENSIONS = '{js,ts,tsx}';
|
|
47
|
+
const SOURCE_EXTENSIONS = '{js,mjs,ts,tsx}';
|
|
47
48
|
const ASSET_EXTENSIONS = 'json';
|
|
48
49
|
const IGNORE_PATTERNS = [
|
|
49
50
|
'**/benchmark/**',
|
|
@@ -107,26 +108,59 @@ const wordpressExternalsPlugin = createWordpressExternalsPlugin(
|
|
|
107
108
|
HANDLE_PREFIX
|
|
108
109
|
);
|
|
109
110
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
111
|
+
/**
|
|
112
|
+
* Get SASS options for the given working directory.
|
|
113
|
+
*
|
|
114
|
+
* Uses NodePackageImporter from sass-embedded for resolving package imports
|
|
115
|
+
* (like @wordpress/base-styles) which works with any package manager (npm, pnpm, yarn).
|
|
116
|
+
*
|
|
117
|
+
* @param {string} workingDir - The directory where we're working (for NodePackageImporter).
|
|
118
|
+
* @return {Object} SASS options object with importers and loadPaths.
|
|
119
|
+
*/
|
|
120
|
+
function getSassOptions( workingDir ) {
|
|
121
|
+
return {
|
|
122
|
+
importers: [ new NodePackageImporter( workingDir ) ],
|
|
123
|
+
// loadPaths for resolving @wordpress/base-styles imports and local base-styles imports
|
|
124
|
+
loadPaths: [
|
|
125
|
+
// Package's own node_modules (for pnpm isolated deps)
|
|
126
|
+
path.join( workingDir, 'node_modules' ),
|
|
127
|
+
// Root node_modules (for npm hoisted deps)
|
|
128
|
+
path.join( ROOT_DIR, 'node_modules' ),
|
|
129
|
+
// For local imports like @use "mixins"
|
|
130
|
+
path.join( PACKAGES_DIR, 'base-styles' ),
|
|
131
|
+
],
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* Create style bundling plugins with the given working directory.
|
|
137
|
+
*
|
|
138
|
+
* @param {string} workingDir - The directory where we're working (for NodePackageImporter).
|
|
139
|
+
* @return {object[]} Array of esbuild plugins for handling CSS/SCSS.
|
|
140
|
+
*/
|
|
141
|
+
function createStyleBundlingPlugins( workingDir ) {
|
|
142
|
+
const sassOptions = getSassOptions( workingDir );
|
|
143
|
+
return [
|
|
144
|
+
// Handle CSS modules (.module.css and .module.scss)
|
|
145
|
+
sassPlugin( {
|
|
146
|
+
embedded: true,
|
|
147
|
+
filter: /\.module\.(css|scss)$/,
|
|
148
|
+
transform: postcssModules( {
|
|
149
|
+
generateScopedName: '[name]__[local]__[hash:base64:5]',
|
|
150
|
+
} ),
|
|
151
|
+
type: 'style',
|
|
152
|
+
...sassOptions,
|
|
117
153
|
} ),
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
} ),
|
|
129
|
-
];
|
|
154
|
+
// Handle regular CSS/SCSS files
|
|
155
|
+
// Note: .module.css and .module.scss already handled by plugin above
|
|
156
|
+
sassPlugin( {
|
|
157
|
+
embedded: true,
|
|
158
|
+
filter: /\.(css|scss)$/,
|
|
159
|
+
type: 'style',
|
|
160
|
+
...sassOptions,
|
|
161
|
+
} ),
|
|
162
|
+
];
|
|
163
|
+
}
|
|
130
164
|
|
|
131
165
|
/**
|
|
132
166
|
* Normalize path separators for cross-platform compatibility.
|
|
@@ -199,16 +233,12 @@ function momentTimezoneAliasPlugin() {
|
|
|
199
233
|
|
|
200
234
|
// Cached paths - resolved lazily on first use
|
|
201
235
|
let preBuiltBundlePath;
|
|
202
|
-
let momentTimezoneUtilsPath;
|
|
203
236
|
const resolvePaths = () => {
|
|
204
237
|
if ( preBuiltBundlePath ) {
|
|
205
238
|
return;
|
|
206
239
|
}
|
|
207
240
|
preBuiltBundlePath = require.resolve(
|
|
208
|
-
'moment-timezone/builds/moment-timezone-with-data-1970-2030'
|
|
209
|
-
);
|
|
210
|
-
momentTimezoneUtilsPath = require.resolve(
|
|
211
|
-
'moment-timezone/moment-timezone-utils.js'
|
|
241
|
+
'moment-timezone/builds/moment-timezone-with-data-1970-2030.js'
|
|
212
242
|
);
|
|
213
243
|
};
|
|
214
244
|
|
|
@@ -221,17 +251,6 @@ function momentTimezoneAliasPlugin() {
|
|
|
221
251
|
}
|
|
222
252
|
);
|
|
223
253
|
|
|
224
|
-
// For utils, we need to load it but ensure it works with the pre-built bundle.
|
|
225
|
-
// The utils file tries to require('./') which would load index.js.
|
|
226
|
-
// We need to make sure it gets the pre-built bundle instead.
|
|
227
|
-
build.onResolve(
|
|
228
|
-
{ filter: /^moment-timezone\/moment-timezone-utils$/ },
|
|
229
|
-
() => {
|
|
230
|
-
resolvePaths();
|
|
231
|
-
return { path: momentTimezoneUtilsPath };
|
|
232
|
-
}
|
|
233
|
-
);
|
|
234
|
-
|
|
235
254
|
// Intercept the require('./') call inside moment-timezone-utils
|
|
236
255
|
// and redirect it to the pre-built bundle.
|
|
237
256
|
build.onResolve( { filter: /^\.\/$/ }, ( args ) => {
|
|
@@ -344,14 +363,7 @@ async function bundlePackage( packageName, options = {} ) {
|
|
|
344
363
|
};
|
|
345
364
|
}
|
|
346
365
|
|
|
347
|
-
const
|
|
348
|
-
momentTimezoneAliasPlugin(),
|
|
349
|
-
wordpressExternalsPlugin(
|
|
350
|
-
'index.min',
|
|
351
|
-
'iife',
|
|
352
|
-
packageJson.wpScriptExtraDependencies || []
|
|
353
|
-
),
|
|
354
|
-
];
|
|
366
|
+
const baseBundlePlugins = [ momentTimezoneAliasPlugin() ];
|
|
355
367
|
|
|
356
368
|
builds.push(
|
|
357
369
|
esbuild.build( {
|
|
@@ -359,14 +371,30 @@ async function bundlePackage( packageName, options = {} ) {
|
|
|
359
371
|
outfile: path.join( outputDir, 'index.min.js' ),
|
|
360
372
|
minify: true,
|
|
361
373
|
define: getDefine( false ),
|
|
362
|
-
plugins:
|
|
374
|
+
plugins: [
|
|
375
|
+
...baseBundlePlugins,
|
|
376
|
+
wordpressExternalsPlugin(
|
|
377
|
+
'index.min',
|
|
378
|
+
'iife',
|
|
379
|
+
packageJson.wpScriptExtraDependencies || [],
|
|
380
|
+
true // Generate asset file for minified build
|
|
381
|
+
),
|
|
382
|
+
],
|
|
363
383
|
} ),
|
|
364
384
|
esbuild.build( {
|
|
365
385
|
...baseConfig,
|
|
366
386
|
outfile: path.join( outputDir, 'index.js' ),
|
|
367
387
|
minify: false,
|
|
368
388
|
define: getDefine( true ),
|
|
369
|
-
plugins:
|
|
389
|
+
plugins: [
|
|
390
|
+
...baseBundlePlugins,
|
|
391
|
+
wordpressExternalsPlugin(
|
|
392
|
+
'index.min',
|
|
393
|
+
'iife',
|
|
394
|
+
packageJson.wpScriptExtraDependencies || [],
|
|
395
|
+
false // Skip asset file for non-minified build
|
|
396
|
+
),
|
|
397
|
+
],
|
|
370
398
|
} )
|
|
371
399
|
);
|
|
372
400
|
|
|
@@ -397,9 +425,6 @@ async function bundlePackage( packageName, options = {} ) {
|
|
|
397
425
|
: exportName.replace( /^\.\//, '' );
|
|
398
426
|
const entryPoint = path.join( packageDir, exportPath );
|
|
399
427
|
const baseFileName = path.basename( fileName );
|
|
400
|
-
const modulePlugins = [
|
|
401
|
-
wordpressExternalsPlugin( `${ baseFileName }.min`, 'esm' ),
|
|
402
|
-
];
|
|
403
428
|
|
|
404
429
|
builds.push(
|
|
405
430
|
esbuild.build( {
|
|
@@ -415,7 +440,14 @@ async function bundlePackage( packageName, options = {} ) {
|
|
|
415
440
|
platform: 'browser',
|
|
416
441
|
minify: true,
|
|
417
442
|
define: getDefine( false ),
|
|
418
|
-
plugins:
|
|
443
|
+
plugins: [
|
|
444
|
+
wordpressExternalsPlugin(
|
|
445
|
+
`${ baseFileName }.min`,
|
|
446
|
+
'esm',
|
|
447
|
+
[],
|
|
448
|
+
true // Generate asset file for minified build
|
|
449
|
+
),
|
|
450
|
+
],
|
|
419
451
|
} ),
|
|
420
452
|
esbuild.build( {
|
|
421
453
|
entryPoints: [ entryPoint ],
|
|
@@ -430,14 +462,21 @@ async function bundlePackage( packageName, options = {} ) {
|
|
|
430
462
|
platform: 'browser',
|
|
431
463
|
minify: false,
|
|
432
464
|
define: getDefine( true ),
|
|
433
|
-
plugins:
|
|
465
|
+
plugins: [
|
|
466
|
+
wordpressExternalsPlugin(
|
|
467
|
+
`${ baseFileName }.min`,
|
|
468
|
+
'esm',
|
|
469
|
+
[],
|
|
470
|
+
false // Skip asset file for non-minified build
|
|
471
|
+
),
|
|
472
|
+
],
|
|
434
473
|
} )
|
|
435
474
|
);
|
|
436
475
|
|
|
437
476
|
const scriptModuleId =
|
|
438
477
|
exportName === '.'
|
|
439
|
-
?
|
|
440
|
-
:
|
|
478
|
+
? `@${ packageNamespace }/${ packageName }`
|
|
479
|
+
: `@${ packageNamespace }/${ packageName }/${ fileName }`;
|
|
441
480
|
|
|
442
481
|
builtModules.push( {
|
|
443
482
|
id: scriptModuleId,
|
|
@@ -451,7 +490,6 @@ async function bundlePackage( packageName, options = {} ) {
|
|
|
451
490
|
if ( packageJson.wpScript ) {
|
|
452
491
|
const buildStyleDir = path.join( packageDir, 'build-style' );
|
|
453
492
|
const outputDir = path.join( BUILD_DIR, 'styles', packageName );
|
|
454
|
-
const isProduction = process.env.NODE_ENV === 'production';
|
|
455
493
|
|
|
456
494
|
const cssFiles = await glob(
|
|
457
495
|
normalizePath( path.join( buildStyleDir, '**/*.css' ) )
|
|
@@ -467,36 +505,39 @@ async function bundlePackage( packageName, options = {} ) {
|
|
|
467
505
|
hasMainStyle = true;
|
|
468
506
|
}
|
|
469
507
|
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
508
|
+
// Generate minified path: style.css -> style.min.css, style-rtl.css -> style-rtl.min.css
|
|
509
|
+
const minifiedPath = destPath.replace( /\.css$/, '.min.css' );
|
|
510
|
+
|
|
511
|
+
// Always produce both versions (like JavaScript does):
|
|
512
|
+
// 1. Non-minified version (for SCRIPT_DEBUG=true)
|
|
513
|
+
// 2. Minified version (for SCRIPT_DEBUG=false)
|
|
514
|
+
builds.push(
|
|
515
|
+
( async () => {
|
|
516
|
+
await mkdir( destDir, { recursive: true } );
|
|
517
|
+
const content = await readFile( cssFile, 'utf8' );
|
|
518
|
+
|
|
519
|
+
// Write non-minified version
|
|
520
|
+
await writeFile( destPath, content );
|
|
521
|
+
|
|
522
|
+
// Write minified version
|
|
523
|
+
const result = await postcss( [
|
|
524
|
+
cssnano( {
|
|
525
|
+
preset: [
|
|
526
|
+
'default',
|
|
527
|
+
{
|
|
528
|
+
discardComments: {
|
|
529
|
+
removeAll: true,
|
|
483
530
|
},
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
)
|
|
493
|
-
|
|
494
|
-
builds.push(
|
|
495
|
-
mkdir( destDir, { recursive: true } ).then( () =>
|
|
496
|
-
copyFile( cssFile, destPath )
|
|
497
|
-
)
|
|
498
|
-
);
|
|
499
|
-
}
|
|
531
|
+
},
|
|
532
|
+
],
|
|
533
|
+
} ),
|
|
534
|
+
] ).process( content, {
|
|
535
|
+
from: cssFile,
|
|
536
|
+
to: minifiedPath,
|
|
537
|
+
} );
|
|
538
|
+
await writeFile( minifiedPath, result.css );
|
|
539
|
+
} )()
|
|
540
|
+
);
|
|
500
541
|
}
|
|
501
542
|
}
|
|
502
543
|
|
|
@@ -603,7 +644,10 @@ async function bundlePackage( packageName, options = {} ) {
|
|
|
603
644
|
?.map( ( d ) => d.replace( /'/g, '' ) ) || [];
|
|
604
645
|
}
|
|
605
646
|
|
|
606
|
-
const styleDeps = await inferStyleDependencies(
|
|
647
|
+
const styleDeps = await inferStyleDependencies(
|
|
648
|
+
scriptDependencies,
|
|
649
|
+
packageName
|
|
650
|
+
);
|
|
607
651
|
|
|
608
652
|
builtStyles.push( {
|
|
609
653
|
handle: `${ handlePrefix }-${ packageName }`,
|
|
@@ -627,14 +671,17 @@ async function bundlePackage( packageName, options = {} ) {
|
|
|
627
671
|
* 3. Actually have a built style.css file
|
|
628
672
|
*
|
|
629
673
|
* @param {string[]} scriptDependencies Array of script handles from asset file.
|
|
674
|
+
* @param {string} packageName Package name (short name) being bundled, for context-aware resolution.
|
|
630
675
|
* @return {Promise<string[]>} Array of style handles to depend on.
|
|
631
676
|
*/
|
|
632
|
-
async function inferStyleDependencies( scriptDependencies ) {
|
|
677
|
+
async function inferStyleDependencies( scriptDependencies, packageName ) {
|
|
633
678
|
if ( ! scriptDependencies || scriptDependencies.length === 0 ) {
|
|
634
679
|
return [];
|
|
635
680
|
}
|
|
636
681
|
|
|
637
682
|
const styleDeps = [];
|
|
683
|
+
// Get the resolve directory for context-aware package resolution
|
|
684
|
+
const resolveDir = path.join( PACKAGES_DIR, packageName );
|
|
638
685
|
|
|
639
686
|
for ( const scriptHandle of scriptDependencies ) {
|
|
640
687
|
// Skip non-package dependencies (like 'react', 'lodash', etc.)
|
|
@@ -642,13 +689,13 @@ async function inferStyleDependencies( scriptDependencies ) {
|
|
|
642
689
|
continue;
|
|
643
690
|
}
|
|
644
691
|
|
|
645
|
-
// Convert handle to package name: 'wp-components' → 'components'
|
|
692
|
+
// Convert handle to package name: 'wp-components' → '@wordpress/components'
|
|
646
693
|
const shortName = scriptHandle.replace( 'wp-', '' );
|
|
647
694
|
const depPackageName = `@wordpress/${ shortName }`;
|
|
648
695
|
|
|
649
|
-
// Read the dependency's package.json
|
|
696
|
+
// Read the dependency's package.json with context-aware resolution
|
|
650
697
|
try {
|
|
651
|
-
const depPackageJson = getPackageInfo( depPackageName );
|
|
698
|
+
const depPackageJson = getPackageInfo( depPackageName, resolveDir );
|
|
652
699
|
|
|
653
700
|
if ( ! depPackageJson ) {
|
|
654
701
|
continue;
|
|
@@ -746,14 +793,14 @@ async function generateScriptRegistrationPhp( scripts, replacements ) {
|
|
|
746
793
|
}
|
|
747
794
|
|
|
748
795
|
/**
|
|
749
|
-
* Generate PHP file for version
|
|
796
|
+
* Generate PHP file for constants (version and build URL).
|
|
750
797
|
*
|
|
751
798
|
* @param {Record<string, string>} replacements PHP template replacements.
|
|
752
799
|
*/
|
|
753
|
-
async function
|
|
800
|
+
async function generateConstantsPhp( replacements ) {
|
|
754
801
|
await generatePhpFromTemplate(
|
|
755
|
-
'
|
|
756
|
-
path.join( BUILD_DIR, '
|
|
802
|
+
'constants.php.template',
|
|
803
|
+
path.join( BUILD_DIR, 'constants.php' ),
|
|
757
804
|
replacements
|
|
758
805
|
);
|
|
759
806
|
}
|
|
@@ -1002,7 +1049,12 @@ async function transpilePackage( packageName ) {
|
|
|
1002
1049
|
name: 'externalize-except-css',
|
|
1003
1050
|
setup( build ) {
|
|
1004
1051
|
// Externalize all non-CSS imports
|
|
1005
|
-
build.onResolve( { filter: /.*/ }, ( args ) => {
|
|
1052
|
+
build.onResolve( { filter: /.*/ }, async ( args ) => {
|
|
1053
|
+
// Skip recursive calls.
|
|
1054
|
+
if ( args.pluginData?.__fromExternalize ) {
|
|
1055
|
+
return null;
|
|
1056
|
+
}
|
|
1057
|
+
|
|
1006
1058
|
// Skip entry points
|
|
1007
1059
|
if ( args.kind === 'entry-point' ) {
|
|
1008
1060
|
return null;
|
|
@@ -1013,6 +1065,44 @@ async function transpilePackage( packageName ) {
|
|
|
1013
1065
|
return null;
|
|
1014
1066
|
}
|
|
1015
1067
|
|
|
1068
|
+
// Fully resolve local dependencies without file extension
|
|
1069
|
+
// and replace the extension with the target extension.
|
|
1070
|
+
if ( args.path.startsWith( '.' ) ) {
|
|
1071
|
+
const resolved = await build.resolve( args.path, {
|
|
1072
|
+
namespace: args.namespace,
|
|
1073
|
+
importer: args.importer,
|
|
1074
|
+
kind: args.kind,
|
|
1075
|
+
resolveDir: args.resolveDir,
|
|
1076
|
+
with: args.with,
|
|
1077
|
+
pluginData: {
|
|
1078
|
+
...args.pluginData,
|
|
1079
|
+
__fromExternalize: true,
|
|
1080
|
+
},
|
|
1081
|
+
} );
|
|
1082
|
+
|
|
1083
|
+
if ( resolved.errors.length > 0 ) {
|
|
1084
|
+
return resolved;
|
|
1085
|
+
}
|
|
1086
|
+
|
|
1087
|
+
// Relativize path: make it relative to resolveDir with leading ./
|
|
1088
|
+
let relativePath = normalizePath(
|
|
1089
|
+
path.relative( args.resolveDir, resolved.path )
|
|
1090
|
+
);
|
|
1091
|
+
if ( ! relativePath.startsWith( '.' ) ) {
|
|
1092
|
+
relativePath = './' + relativePath;
|
|
1093
|
+
}
|
|
1094
|
+
|
|
1095
|
+
// Replace extension: make sure that file extension is always `.mjs` or `.cjs`.
|
|
1096
|
+
const newExt =
|
|
1097
|
+
build.initialOptions.format === 'cjs' ? '.cjs' : '.mjs';
|
|
1098
|
+
relativePath = relativePath.replace( /\.[jt]sx?$/, newExt );
|
|
1099
|
+
|
|
1100
|
+
return {
|
|
1101
|
+
path: relativePath,
|
|
1102
|
+
external: true,
|
|
1103
|
+
};
|
|
1104
|
+
}
|
|
1105
|
+
|
|
1016
1106
|
// Externalize everything else (keep imports as-is)
|
|
1017
1107
|
return { path: args.path, external: true };
|
|
1018
1108
|
} );
|
|
@@ -1021,7 +1111,7 @@ async function transpilePackage( packageName ) {
|
|
|
1021
1111
|
const plugins = [
|
|
1022
1112
|
needsEmotionPlugin && emotionPlugin,
|
|
1023
1113
|
externalizeAllExceptCssPlugin,
|
|
1024
|
-
...
|
|
1114
|
+
...createStyleBundlingPlugins( packageDir ),
|
|
1025
1115
|
].filter( Boolean );
|
|
1026
1116
|
|
|
1027
1117
|
if ( packageJson.main ) {
|
|
@@ -1030,6 +1120,7 @@ async function transpilePackage( packageName ) {
|
|
|
1030
1120
|
entryPoints: srcFiles,
|
|
1031
1121
|
outdir: buildDir,
|
|
1032
1122
|
outbase: srcDir,
|
|
1123
|
+
outExtension: { '.js': '.cjs' },
|
|
1033
1124
|
bundle: true,
|
|
1034
1125
|
platform: 'node',
|
|
1035
1126
|
format: 'cjs',
|
|
@@ -1037,9 +1128,7 @@ async function transpilePackage( packageName ) {
|
|
|
1037
1128
|
target,
|
|
1038
1129
|
jsx: 'automatic',
|
|
1039
1130
|
jsxImportSource: 'react',
|
|
1040
|
-
loader: {
|
|
1041
|
-
'.js': 'jsx',
|
|
1042
|
-
},
|
|
1131
|
+
loader: { '.js': 'jsx' },
|
|
1043
1132
|
plugins,
|
|
1044
1133
|
} )
|
|
1045
1134
|
);
|
|
@@ -1062,6 +1151,7 @@ async function transpilePackage( packageName ) {
|
|
|
1062
1151
|
entryPoints: srcFiles,
|
|
1063
1152
|
outdir: buildModuleDir,
|
|
1064
1153
|
outbase: srcDir,
|
|
1154
|
+
outExtension: { '.js': '.mjs' },
|
|
1065
1155
|
bundle: true,
|
|
1066
1156
|
platform: 'neutral',
|
|
1067
1157
|
format: 'esm',
|
|
@@ -1069,9 +1159,7 @@ async function transpilePackage( packageName ) {
|
|
|
1069
1159
|
target,
|
|
1070
1160
|
jsx: 'automatic',
|
|
1071
1161
|
jsxImportSource: 'react',
|
|
1072
|
-
loader: {
|
|
1073
|
-
'.js': 'jsx',
|
|
1074
|
-
},
|
|
1162
|
+
loader: { '.js': 'jsx' },
|
|
1075
1163
|
plugins,
|
|
1076
1164
|
} )
|
|
1077
1165
|
);
|
|
@@ -1157,10 +1245,7 @@ async function compileStyles( packageName ) {
|
|
|
1157
1245
|
plugins: [
|
|
1158
1246
|
sassPlugin( {
|
|
1159
1247
|
embedded: true,
|
|
1160
|
-
|
|
1161
|
-
'node_modules',
|
|
1162
|
-
path.join( PACKAGES_DIR, 'base-styles' ),
|
|
1163
|
-
],
|
|
1248
|
+
...getSassOptions( packageDir ),
|
|
1164
1249
|
async transform( source ) {
|
|
1165
1250
|
// Process with autoprefixer for LTR version
|
|
1166
1251
|
const ltrResult = await postcss( [
|
|
@@ -1279,10 +1364,6 @@ async function buildRoute( routeName ) {
|
|
|
1279
1364
|
} );
|
|
1280
1365
|
|
|
1281
1366
|
if ( routeEntryPoints.length > 0 ) {
|
|
1282
|
-
const routePlugins = [
|
|
1283
|
-
wordpressExternalsPlugin( 'route.min', 'esm' ),
|
|
1284
|
-
];
|
|
1285
|
-
|
|
1286
1367
|
// Build both minified and non-minified versions in parallel
|
|
1287
1368
|
await Promise.all( [
|
|
1288
1369
|
esbuild.build( {
|
|
@@ -1293,7 +1374,14 @@ async function buildRoute( routeName ) {
|
|
|
1293
1374
|
target: browserslistToEsbuild(),
|
|
1294
1375
|
minify: true,
|
|
1295
1376
|
define: getDefine( false ),
|
|
1296
|
-
plugins:
|
|
1377
|
+
plugins: [
|
|
1378
|
+
wordpressExternalsPlugin(
|
|
1379
|
+
'route.min',
|
|
1380
|
+
'esm',
|
|
1381
|
+
[],
|
|
1382
|
+
true // Generate asset file for minified build
|
|
1383
|
+
),
|
|
1384
|
+
],
|
|
1297
1385
|
} ),
|
|
1298
1386
|
esbuild.build( {
|
|
1299
1387
|
entryPoints: routeEntryPoints,
|
|
@@ -1303,7 +1391,14 @@ async function buildRoute( routeName ) {
|
|
|
1303
1391
|
target: browserslistToEsbuild(),
|
|
1304
1392
|
minify: false,
|
|
1305
1393
|
define: getDefine( true ),
|
|
1306
|
-
plugins:
|
|
1394
|
+
plugins: [
|
|
1395
|
+
wordpressExternalsPlugin(
|
|
1396
|
+
'route.min',
|
|
1397
|
+
'esm',
|
|
1398
|
+
[],
|
|
1399
|
+
false // Skip asset file for non-minified build
|
|
1400
|
+
),
|
|
1401
|
+
],
|
|
1307
1402
|
} ),
|
|
1308
1403
|
] );
|
|
1309
1404
|
}
|
|
@@ -1318,11 +1413,6 @@ async function buildRoute( routeName ) {
|
|
|
1318
1413
|
// Write temporary entry file
|
|
1319
1414
|
await writeFile( tempEntryPath, syntheticEntry );
|
|
1320
1415
|
|
|
1321
|
-
const contentPlugins = [
|
|
1322
|
-
wordpressExternalsPlugin( 'content.min', 'esm' ),
|
|
1323
|
-
...styleBundlingPlugins,
|
|
1324
|
-
];
|
|
1325
|
-
|
|
1326
1416
|
// Build both minified and non-minified versions in parallel
|
|
1327
1417
|
await Promise.all( [
|
|
1328
1418
|
esbuild.build( {
|
|
@@ -1333,7 +1423,15 @@ async function buildRoute( routeName ) {
|
|
|
1333
1423
|
target: browserslistToEsbuild(),
|
|
1334
1424
|
minify: true,
|
|
1335
1425
|
define: getDefine( false ),
|
|
1336
|
-
plugins:
|
|
1426
|
+
plugins: [
|
|
1427
|
+
wordpressExternalsPlugin(
|
|
1428
|
+
'content.min',
|
|
1429
|
+
'esm',
|
|
1430
|
+
[],
|
|
1431
|
+
true // Generate asset file for minified build
|
|
1432
|
+
),
|
|
1433
|
+
...createStyleBundlingPlugins( routeDir ),
|
|
1434
|
+
],
|
|
1337
1435
|
} ),
|
|
1338
1436
|
esbuild.build( {
|
|
1339
1437
|
entryPoints: [ tempEntryPath ],
|
|
@@ -1343,7 +1441,15 @@ async function buildRoute( routeName ) {
|
|
|
1343
1441
|
target: browserslistToEsbuild(),
|
|
1344
1442
|
minify: false,
|
|
1345
1443
|
define: getDefine( true ),
|
|
1346
|
-
plugins:
|
|
1444
|
+
plugins: [
|
|
1445
|
+
wordpressExternalsPlugin(
|
|
1446
|
+
'content.min',
|
|
1447
|
+
'esm',
|
|
1448
|
+
[],
|
|
1449
|
+
false // Skip asset file for non-minified build
|
|
1450
|
+
),
|
|
1451
|
+
...createStyleBundlingPlugins( routeDir ),
|
|
1452
|
+
],
|
|
1347
1453
|
} ),
|
|
1348
1454
|
] );
|
|
1349
1455
|
|
|
@@ -1380,24 +1486,28 @@ async function buildAllRoutes() {
|
|
|
1380
1486
|
|
|
1381
1487
|
/**
|
|
1382
1488
|
* Main build function.
|
|
1489
|
+
*
|
|
1490
|
+
* @param {string?} baseUrlExpression
|
|
1383
1491
|
*/
|
|
1384
|
-
async function buildAll() {
|
|
1492
|
+
async function buildAll( baseUrlExpression ) {
|
|
1385
1493
|
console.log( '🔨 Building packages...\n' );
|
|
1386
1494
|
|
|
1387
1495
|
const startTime = Date.now();
|
|
1388
1496
|
|
|
1389
|
-
// Build maps: short name ↔ full name from package.json
|
|
1497
|
+
// Build maps: short name ↔ full name ↔ package.json from package.json files
|
|
1390
1498
|
const shortToFull = new Map();
|
|
1391
1499
|
const fullToShort = new Map();
|
|
1500
|
+
const fullToPackageJson = new Map();
|
|
1392
1501
|
for ( const pkg of PACKAGES ) {
|
|
1393
1502
|
const packageJson = getPackageInfoFromFile(
|
|
1394
1503
|
path.join( PACKAGES_DIR, pkg, 'package.json' )
|
|
1395
1504
|
);
|
|
1396
1505
|
shortToFull.set( pkg, packageJson.name );
|
|
1397
1506
|
fullToShort.set( packageJson.name, pkg );
|
|
1507
|
+
fullToPackageJson.set( packageJson.name, packageJson );
|
|
1398
1508
|
}
|
|
1399
1509
|
|
|
1400
|
-
const levels = groupByDepth(
|
|
1510
|
+
const levels = groupByDepth( fullToPackageJson );
|
|
1401
1511
|
|
|
1402
1512
|
console.log( '📝 Phase 1: Transpiling packages...\n' );
|
|
1403
1513
|
|
|
@@ -1444,26 +1554,40 @@ async function buildAll() {
|
|
|
1444
1554
|
await buildAllRoutes();
|
|
1445
1555
|
|
|
1446
1556
|
// Collect route and page data for PHP generation
|
|
1447
|
-
|
|
1557
|
+
// Use flatMap to expand routes with multiple pages into separate entries
|
|
1558
|
+
const routes = getAllRoutes( ROOT_DIR ).flatMap( ( routeName ) => {
|
|
1448
1559
|
const metadata = getRouteMetadata( ROOT_DIR, routeName );
|
|
1560
|
+
|
|
1561
|
+
// Skip routes without pages
|
|
1562
|
+
if ( ! metadata || ! metadata.pages || metadata.pages.length === 0 ) {
|
|
1563
|
+
return [];
|
|
1564
|
+
}
|
|
1449
1565
|
const routeFiles = getRouteFiles(
|
|
1450
1566
|
path.join( ROOT_DIR, 'routes', routeName )
|
|
1451
1567
|
);
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
|
|
1568
|
+
|
|
1569
|
+
// Create a route entry for each page
|
|
1570
|
+
return metadata.pages.map( ( page ) => {
|
|
1571
|
+
return {
|
|
1572
|
+
name: routeName,
|
|
1573
|
+
path: metadata.path,
|
|
1574
|
+
page,
|
|
1575
|
+
hasRoute: routeFiles.hasRoute,
|
|
1576
|
+
hasContent: routeFiles.hasStage || routeFiles.hasInspector,
|
|
1577
|
+
};
|
|
1578
|
+
} );
|
|
1459
1579
|
} );
|
|
1460
1580
|
|
|
1461
1581
|
// Normalize PAGES config to support both string and object formats
|
|
1462
1582
|
const normalizedPages = PAGES.map( ( page ) => {
|
|
1463
1583
|
if ( typeof page === 'string' ) {
|
|
1464
|
-
return { id: page, init: [] };
|
|
1584
|
+
return { id: page, init: [], title: undefined };
|
|
1465
1585
|
}
|
|
1466
|
-
return {
|
|
1586
|
+
return {
|
|
1587
|
+
id: page.id,
|
|
1588
|
+
init: page.init || [],
|
|
1589
|
+
title: page.title || undefined,
|
|
1590
|
+
};
|
|
1467
1591
|
} );
|
|
1468
1592
|
|
|
1469
1593
|
const pageData = normalizedPages.map( ( page ) => {
|
|
@@ -1472,6 +1596,7 @@ async function buildAll() {
|
|
|
1472
1596
|
slug: page.id,
|
|
1473
1597
|
routes: pageRoutes,
|
|
1474
1598
|
initModules: page.init,
|
|
1599
|
+
title: page.title,
|
|
1475
1600
|
};
|
|
1476
1601
|
} );
|
|
1477
1602
|
|
|
@@ -1521,13 +1646,16 @@ async function buildAll() {
|
|
|
1521
1646
|
}
|
|
1522
1647
|
|
|
1523
1648
|
console.log( '\n📄 Generating PHP registration files...\n' );
|
|
1524
|
-
const phpReplacements = await getPhpReplacements(
|
|
1649
|
+
const phpReplacements = await getPhpReplacements(
|
|
1650
|
+
ROOT_DIR,
|
|
1651
|
+
baseUrlExpression
|
|
1652
|
+
);
|
|
1525
1653
|
await Promise.all( [
|
|
1526
1654
|
generateMainIndexPhp( phpReplacements ),
|
|
1527
1655
|
generateModuleRegistrationPhp( modules, phpReplacements ),
|
|
1528
1656
|
generateScriptRegistrationPhp( scripts, phpReplacements ),
|
|
1529
1657
|
generateStyleRegistrationPhp( styles, phpReplacements ),
|
|
1530
|
-
|
|
1658
|
+
generateConstantsPhp( phpReplacements ),
|
|
1531
1659
|
generateRoutesRegistry( routes, phpReplacements ),
|
|
1532
1660
|
generateRoutesPhp( routes, phpReplacements ),
|
|
1533
1661
|
generatePagesPhp( pageData, phpReplacements ),
|
|
@@ -1566,17 +1694,18 @@ async function watchMode() {
|
|
|
1566
1694
|
let isRebuilding = false;
|
|
1567
1695
|
const needsRebuild = new Set();
|
|
1568
1696
|
|
|
1569
|
-
// Build maps: short name ↔ full name from package.json (once)
|
|
1697
|
+
// Build maps: short name ↔ full name ↔ package.json from package.json files (once)
|
|
1570
1698
|
const shortToFull = new Map();
|
|
1571
1699
|
const fullToShort = new Map();
|
|
1700
|
+
const fullToPackageJson = new Map();
|
|
1572
1701
|
for ( const pkg of PACKAGES ) {
|
|
1573
1702
|
const packageJson = getPackageInfoFromFile(
|
|
1574
1703
|
path.join( PACKAGES_DIR, pkg, 'package.json' )
|
|
1575
1704
|
);
|
|
1576
1705
|
shortToFull.set( pkg, packageJson.name );
|
|
1577
1706
|
fullToShort.set( packageJson.name, pkg );
|
|
1707
|
+
fullToPackageJson.set( packageJson.name, packageJson );
|
|
1578
1708
|
}
|
|
1579
|
-
const allFullNames = Array.from( shortToFull.values() );
|
|
1580
1709
|
|
|
1581
1710
|
// Get all routes for dependency tracking
|
|
1582
1711
|
const allRoutes = getAllRoutes( ROOT_DIR );
|
|
@@ -1599,7 +1728,7 @@ async function watchMode() {
|
|
|
1599
1728
|
const fullName = shortToFull.get( packageName );
|
|
1600
1729
|
const affectedScripts = findScriptsToRebundle(
|
|
1601
1730
|
fullName,
|
|
1602
|
-
|
|
1731
|
+
fullToPackageJson
|
|
1603
1732
|
);
|
|
1604
1733
|
|
|
1605
1734
|
for ( const fullScript of affectedScripts ) {
|
|
@@ -1622,7 +1751,7 @@ async function watchMode() {
|
|
|
1622
1751
|
// Find and rebuild affected routes
|
|
1623
1752
|
const affectedRoutes = findRoutesToRebuild(
|
|
1624
1753
|
fullName,
|
|
1625
|
-
|
|
1754
|
+
fullToPackageJson,
|
|
1626
1755
|
ROOT_DIR,
|
|
1627
1756
|
allRoutes
|
|
1628
1757
|
);
|
|
@@ -1815,10 +1944,16 @@ async function main() {
|
|
|
1815
1944
|
short: 'w',
|
|
1816
1945
|
default: false,
|
|
1817
1946
|
},
|
|
1947
|
+
'base-url': {
|
|
1948
|
+
type: 'string',
|
|
1949
|
+
default: 'plugin_dir_url( __FILE__ )',
|
|
1950
|
+
},
|
|
1818
1951
|
},
|
|
1819
1952
|
} );
|
|
1820
1953
|
|
|
1821
|
-
|
|
1954
|
+
const baseUrlExpression = values[ 'base-url' ];
|
|
1955
|
+
|
|
1956
|
+
await buildAll( baseUrlExpression );
|
|
1822
1957
|
|
|
1823
1958
|
if ( values.watch ) {
|
|
1824
1959
|
console.log( '\n👀 Watching for changes...\n' );
|