@10up/wp-vite-plugins 1.0.0-alpha.2 → 1.0.0-alpha.3
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/README.md +53 -3
- package/dist/build.d.ts +2 -2
- package/dist/build.js +18 -1
- package/dist/build.js.map +1 -1
- package/dist/cli.js +85 -7
- package/dist/cli.js.map +1 -1
- package/dist/dev.d.ts +35 -0
- package/dist/dev.js +384 -0
- package/dist/dev.js.map +1 -0
- package/dist/index.d.ts +153 -2
- package/dist/index.js +1561 -120
- package/dist/index.js.map +1 -1
- package/dist/{runner-WUYCS-nx.d.ts → runner-jUVlAHlZ.d.ts} +8 -3
- package/dist/watch.d.ts +2 -2
- package/dist/watch.js +18 -1
- package/dist/watch.js.map +1 -1
- package/package.json +6 -1
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { resolve, join, relative, dirname, extname } from 'path';
|
|
2
|
-
import { readdirSync, existsSync, readFileSync, realpathSync } from 'fs';
|
|
1
|
+
import { resolve, join, relative, dirname, extname, isAbsolute } from 'path';
|
|
2
|
+
import { readdirSync, existsSync, readFileSync, rmSync, mkdirSync, writeFileSync, realpathSync } from 'fs';
|
|
3
3
|
import crypto, { createHash } from 'crypto';
|
|
4
4
|
import fg from 'fast-glob';
|
|
5
5
|
import { init, parse } from 'es-module-lexer';
|
|
@@ -874,6 +874,599 @@ function ${prefix}_register_page_routes( $page_routes, $register_function_name )
|
|
|
874
874
|
${pageFunctions}
|
|
875
875
|
`;
|
|
876
876
|
}
|
|
877
|
+
function renderDevServerPhp(ctx) {
|
|
878
|
+
const prefixUnderscore = toUnderscore(ctx.prefix);
|
|
879
|
+
const fn = `${prefixUnderscore}_wp_vite_dev`;
|
|
880
|
+
const client = `${ctx.prefix}-vite-client`;
|
|
881
|
+
const checkConstant = `${prefixUnderscore.toUpperCase()}_WP_VITE_CHECK_DEV_SERVER`;
|
|
882
|
+
const checkFilter = `${prefixUnderscore}_wp_vite_check_dev_server`;
|
|
883
|
+
return `<?php
|
|
884
|
+
/**
|
|
885
|
+
* Vite dev-server bridge.
|
|
886
|
+
* Auto-generated by build process. Do not edit this file manually.
|
|
887
|
+
*
|
|
888
|
+
* Require it once, unconditionally, next to the rest of your dist requires:
|
|
889
|
+
*
|
|
890
|
+
* $wp_vite_dev = __DIR__ . '/dist/dev-server.php';
|
|
891
|
+
* if ( file_exists( $wp_vite_dev ) ) {
|
|
892
|
+
* require_once $wp_vite_dev;
|
|
893
|
+
* }
|
|
894
|
+
*
|
|
895
|
+
* With no dev server running it costs a single \`file_exists()\` and returns.
|
|
896
|
+
* When ${ctx.hotFile} is sitting next to it, it repoints every script,
|
|
897
|
+
* stylesheet and Script Module WordPress would have loaded out of this
|
|
898
|
+
* directory at the running Vite server instead.
|
|
899
|
+
*
|
|
900
|
+
* @package ${ctx.prefix}
|
|
901
|
+
*/
|
|
902
|
+
|
|
903
|
+
/*
|
|
904
|
+
* Two loaders, a theme that also boots its own mu-plugin: requiring this file
|
|
905
|
+
* twice must not redeclare anything or stack a second set of filters.
|
|
906
|
+
*
|
|
907
|
+
* The guard has to *wrap* the declarations rather than \`return\` above them.
|
|
908
|
+
* PHP binds an unconditionally-declared top-level function when it compiles the
|
|
909
|
+
* file \u2014 before a single statement in it runs \u2014 so an early return would fatal
|
|
910
|
+
* on the second require anyway. Conditional declarations are bound at run time,
|
|
911
|
+
* which is what makes the check mean something.
|
|
912
|
+
*/
|
|
913
|
+
if ( ! function_exists( '${fn}_hot' ) ) :
|
|
914
|
+
|
|
915
|
+
/**
|
|
916
|
+
* Whether ${fn}_hot() should verify the dev server is actually reachable
|
|
917
|
+
* before trusting the hot file's mere presence.
|
|
918
|
+
*
|
|
919
|
+
* Off by default. Every other check in this bridge is a single
|
|
920
|
+
* \`file_exists()\` because a running dev server keeps that contract
|
|
921
|
+
* deliberately \u2014 write on 'listening', delete on exit, exit handlers bound
|
|
922
|
+
* once. The one hole is a \`kill -9\`'d process, which leaves the file behind
|
|
923
|
+
* pointing at a socket nothing is listening on any more. Closing that hole
|
|
924
|
+
* costs a real HTTP request \u2014 timed short, but still a round trip \u2014 on every
|
|
925
|
+
* single request this bridge participates in, so it stays opt-in rather than
|
|
926
|
+
* something every site pays for.
|
|
927
|
+
*
|
|
928
|
+
* Enable it with the \`${checkConstant}\` constant, or the
|
|
929
|
+
* \`${checkFilter}\` filter for anything more dynamic (e.g. only inside a
|
|
930
|
+
* container where \`kill -9\`ing the dev server is routine).
|
|
931
|
+
*
|
|
932
|
+
* @return bool
|
|
933
|
+
*/
|
|
934
|
+
function ${fn}_should_verify_dev_server() {
|
|
935
|
+
$default = defined( '${checkConstant}' ) && constant( '${checkConstant}' );
|
|
936
|
+
|
|
937
|
+
/**
|
|
938
|
+
* Filters whether the dev-server bridge verifies the running server is
|
|
939
|
+
* reachable before trusting the hot file.
|
|
940
|
+
*
|
|
941
|
+
* @param bool $verify Whether to probe. Default from the
|
|
942
|
+
* ${checkConstant} constant, else false.
|
|
943
|
+
*/
|
|
944
|
+
return (bool) apply_filters( '${checkFilter}', $default );
|
|
945
|
+
}
|
|
946
|
+
|
|
947
|
+
/**
|
|
948
|
+
* The decoded hot file, or null when no dev server is running.
|
|
949
|
+
*
|
|
950
|
+
* The presence of the file is the entire protocol \u2014 a running server writes it
|
|
951
|
+
* on 'listening' and deletes it on exit. Cached in a static because this is on
|
|
952
|
+
* the request path for every enqueued asset.
|
|
953
|
+
*
|
|
954
|
+
* @return array|null Array with 'origin', 'base' and 'plugins' keys, or null.
|
|
955
|
+
*/
|
|
956
|
+
function ${fn}_hot() {
|
|
957
|
+
static $hot = false;
|
|
958
|
+
|
|
959
|
+
if ( false !== $hot ) {
|
|
960
|
+
return $hot;
|
|
961
|
+
}
|
|
962
|
+
|
|
963
|
+
$hot = null;
|
|
964
|
+
$hot_file = __DIR__ . '/${ctx.hotFile}';
|
|
965
|
+
|
|
966
|
+
if ( ! file_exists( $hot_file ) ) {
|
|
967
|
+
return $hot;
|
|
968
|
+
}
|
|
969
|
+
|
|
970
|
+
// phpcs:ignore WordPress.WP.AlternativeFunctions.file_get_contents_file_get_contents
|
|
971
|
+
$contents = file_get_contents( $hot_file );
|
|
972
|
+
$decoded = is_string( $contents ) ? json_decode( $contents, true ) : null;
|
|
973
|
+
|
|
974
|
+
if ( ! is_array( $decoded ) || empty( $decoded['origin'] ) || ! is_string( $decoded['origin'] ) ) {
|
|
975
|
+
return $hot;
|
|
976
|
+
}
|
|
977
|
+
|
|
978
|
+
$base = isset( $decoded['base'] ) && is_string( $decoded['base'] ) ? $decoded['base'] : '/';
|
|
979
|
+
$base = '/' . ltrim( $base, '/' );
|
|
980
|
+
if ( '/' !== substr( $base, -1 ) ) {
|
|
981
|
+
$base .= '/';
|
|
982
|
+
}
|
|
983
|
+
|
|
984
|
+
$hot = array(
|
|
985
|
+
'origin' => rtrim( $decoded['origin'], '/' ),
|
|
986
|
+
'base' => $base,
|
|
987
|
+
'plugins' => isset( $decoded['plugins'] ) && is_array( $decoded['plugins'] ) ? $decoded['plugins'] : array(),
|
|
988
|
+
);
|
|
989
|
+
|
|
990
|
+
// Stale hot file: the file is there, but nothing answers for it (a
|
|
991
|
+
// \`kill -9\`'d dev server). See ${fn}_should_verify_dev_server() above \u2014
|
|
992
|
+
// off by default, so this whole block is skipped on the common path.
|
|
993
|
+
if ( ${fn}_should_verify_dev_server() && function_exists( 'wp_remote_head' ) ) {
|
|
994
|
+
$response = wp_remote_head(
|
|
995
|
+
$hot['origin'] . $hot['base'] . '@vite/client',
|
|
996
|
+
array( 'timeout' => 0.2, 'blocking' => true )
|
|
997
|
+
);
|
|
998
|
+
|
|
999
|
+
$status_code = is_wp_error( $response ) ? 0 : (int) wp_remote_retrieve_response_code( $response );
|
|
1000
|
+
|
|
1001
|
+
if ( $status_code < 200 || $status_code >= 400 ) {
|
|
1002
|
+
$hot = null;
|
|
1003
|
+
}
|
|
1004
|
+
}
|
|
1005
|
+
|
|
1006
|
+
return $hot;
|
|
1007
|
+
}
|
|
1008
|
+
|
|
1009
|
+
/**
|
|
1010
|
+
* Turn a project-relative source path into the URL the dev server serves it at.
|
|
1011
|
+
*
|
|
1012
|
+
* @param string $source Project-relative path from an .asset.php 'source' key.
|
|
1013
|
+
* @return string Absolute URL, or '' when no dev server is running.
|
|
1014
|
+
*/
|
|
1015
|
+
function ${fn}_url( $source ) {
|
|
1016
|
+
$hot = ${fn}_hot();
|
|
1017
|
+
|
|
1018
|
+
if ( null === $hot ) {
|
|
1019
|
+
return '';
|
|
1020
|
+
}
|
|
1021
|
+
|
|
1022
|
+
return $hot['origin'] . $hot['base'] . ltrim( (string) $source, '/' );
|
|
1023
|
+
}
|
|
1024
|
+
|
|
1025
|
+
/**
|
|
1026
|
+
* URL of the directory this file lives in.
|
|
1027
|
+
*
|
|
1028
|
+
* Derived from __DIR__ rather than configured, so the same generated file works
|
|
1029
|
+
* whether it was built into a theme, a plugin or an mu-plugin. The candidates
|
|
1030
|
+
* are tried most-specific first: content_url() is the general answer, but a
|
|
1031
|
+
* theme under a custom theme root \u2014 or anything reached through a symlink \u2014 is
|
|
1032
|
+
* only spelled correctly by its own helper.
|
|
1033
|
+
*
|
|
1034
|
+
* @return string Trailing-slashed URL, or '' when this directory is outside
|
|
1035
|
+
* every location WordPress can build a URL for.
|
|
1036
|
+
*/
|
|
1037
|
+
function ${fn}_dist_url() {
|
|
1038
|
+
static $dist_url = false;
|
|
1039
|
+
|
|
1040
|
+
if ( false !== $dist_url ) {
|
|
1041
|
+
return $dist_url;
|
|
1042
|
+
}
|
|
1043
|
+
|
|
1044
|
+
$dist_url = '';
|
|
1045
|
+
$dir = rtrim( str_replace( '\\\\', '/', __DIR__ ), '/' );
|
|
1046
|
+
$roots = array();
|
|
1047
|
+
|
|
1048
|
+
if ( function_exists( 'get_stylesheet_directory' ) && function_exists( 'get_stylesheet_directory_uri' ) ) {
|
|
1049
|
+
$roots[] = array( get_stylesheet_directory(), get_stylesheet_directory_uri() );
|
|
1050
|
+
}
|
|
1051
|
+
if ( function_exists( 'get_template_directory' ) && function_exists( 'get_template_directory_uri' ) ) {
|
|
1052
|
+
$roots[] = array( get_template_directory(), get_template_directory_uri() );
|
|
1053
|
+
}
|
|
1054
|
+
if ( defined( 'WPMU_PLUGIN_DIR' ) && defined( 'WPMU_PLUGIN_URL' ) ) {
|
|
1055
|
+
$roots[] = array( WPMU_PLUGIN_DIR, WPMU_PLUGIN_URL );
|
|
1056
|
+
}
|
|
1057
|
+
if ( defined( 'WP_PLUGIN_DIR' ) && defined( 'WP_PLUGIN_URL' ) ) {
|
|
1058
|
+
$roots[] = array( WP_PLUGIN_DIR, WP_PLUGIN_URL );
|
|
1059
|
+
}
|
|
1060
|
+
if ( defined( 'WP_CONTENT_DIR' ) && function_exists( 'content_url' ) ) {
|
|
1061
|
+
$roots[] = array( WP_CONTENT_DIR, content_url() );
|
|
1062
|
+
}
|
|
1063
|
+
|
|
1064
|
+
foreach ( $roots as $root ) {
|
|
1065
|
+
list( $root_dir, $root_url ) = $root;
|
|
1066
|
+
|
|
1067
|
+
if ( ! is_string( $root_dir ) || ! is_string( $root_url ) || '' === $root_dir || '' === $root_url ) {
|
|
1068
|
+
continue;
|
|
1069
|
+
}
|
|
1070
|
+
|
|
1071
|
+
$root_dir = rtrim( str_replace( '\\\\', '/', $root_dir ), '/' );
|
|
1072
|
+
|
|
1073
|
+
if ( '' === $root_dir || 0 !== strpos( $dir . '/', $root_dir . '/' ) ) {
|
|
1074
|
+
continue;
|
|
1075
|
+
}
|
|
1076
|
+
|
|
1077
|
+
$dist_url = rtrim( $root_url, '/' ) . substr( $dir, strlen( $root_dir ) ) . '/';
|
|
1078
|
+
break;
|
|
1079
|
+
}
|
|
1080
|
+
|
|
1081
|
+
return $dist_url;
|
|
1082
|
+
}
|
|
1083
|
+
|
|
1084
|
+
/**
|
|
1085
|
+
* Map an asset URL pointing into this directory back to the file the dev
|
|
1086
|
+
* server serves it from.
|
|
1087
|
+
*
|
|
1088
|
+
* The lookup is the .asset.php sidecar next to where the built file would have
|
|
1089
|
+
* been: dist-relative URL, extension stripped, '.asset.php' appended. Its
|
|
1090
|
+
* 'source' key \u2014 written by both a build and a running dev server \u2014 is the
|
|
1091
|
+
* project-relative path of the file Vite compiles on demand.
|
|
1092
|
+
*
|
|
1093
|
+
* @param string $url Asset URL as WordPress is about to print it, '?ver=' and all.
|
|
1094
|
+
* @return string|null Project-relative source path, or null when this URL is
|
|
1095
|
+
* not ours or has no sidecar.
|
|
1096
|
+
*/
|
|
1097
|
+
function ${fn}_source( $url ) {
|
|
1098
|
+
static $cache = array();
|
|
1099
|
+
|
|
1100
|
+
if ( ! is_string( $url ) || '' === $url ) {
|
|
1101
|
+
return null;
|
|
1102
|
+
}
|
|
1103
|
+
|
|
1104
|
+
$dist_url = ${fn}_dist_url();
|
|
1105
|
+
|
|
1106
|
+
if ( '' === $dist_url ) {
|
|
1107
|
+
return null;
|
|
1108
|
+
}
|
|
1109
|
+
|
|
1110
|
+
// The filters hand us the versioned URL; the sidecar lives at the
|
|
1111
|
+
// unversioned path.
|
|
1112
|
+
$query = strpos( $url, '?' );
|
|
1113
|
+
if ( false !== $query ) {
|
|
1114
|
+
$url = substr( $url, 0, $query );
|
|
1115
|
+
}
|
|
1116
|
+
|
|
1117
|
+
if ( array_key_exists( $url, $cache ) ) {
|
|
1118
|
+
return $cache[ $url ];
|
|
1119
|
+
}
|
|
1120
|
+
|
|
1121
|
+
$cache[ $url ] = null;
|
|
1122
|
+
$relative = null;
|
|
1123
|
+
|
|
1124
|
+
// A protocol-relative src, and an http/https mismatch between the enqueued
|
|
1125
|
+
// URL and content_url(), are both routine; neither should stop a match. The
|
|
1126
|
+
// path-only form additionally catches root-relative and CDN-fronted srcs.
|
|
1127
|
+
$path_only = preg_replace( '#^([a-z][a-z0-9+.-]*:)?//[^/]*#i', '', $dist_url );
|
|
1128
|
+
foreach ( array( $dist_url, is_string( $path_only ) ? $path_only : '' ) as $prefix ) {
|
|
1129
|
+
if ( '' === $prefix ) {
|
|
1130
|
+
continue;
|
|
1131
|
+
}
|
|
1132
|
+
|
|
1133
|
+
$bare_prefix = preg_replace( '#^[a-z][a-z0-9+.-]*:#i', '', $prefix );
|
|
1134
|
+
$bare_url = preg_replace( '#^[a-z][a-z0-9+.-]*:#i', '', $url );
|
|
1135
|
+
|
|
1136
|
+
if ( 0 !== strpos( $bare_url, $bare_prefix ) ) {
|
|
1137
|
+
continue;
|
|
1138
|
+
}
|
|
1139
|
+
|
|
1140
|
+
$relative = substr( $bare_url, strlen( $bare_prefix ) );
|
|
1141
|
+
break;
|
|
1142
|
+
}
|
|
1143
|
+
|
|
1144
|
+
// The relative path reaches a require(), and it came out of a URL. Nothing
|
|
1145
|
+
// but the shape a build actually emits gets through.
|
|
1146
|
+
if ( null === $relative || ! preg_match( '#^[A-Za-z0-9_][A-Za-z0-9_./-]*$#', $relative ) || false !== strpos( $relative, '..' ) ) {
|
|
1147
|
+
return null;
|
|
1148
|
+
}
|
|
1149
|
+
|
|
1150
|
+
$asset_file = __DIR__ . '/' . preg_replace( '/\\.(js|mjs|css)$/', '', $relative ) . '.asset.php';
|
|
1151
|
+
|
|
1152
|
+
if ( ! file_exists( $asset_file ) ) {
|
|
1153
|
+
return null;
|
|
1154
|
+
}
|
|
1155
|
+
|
|
1156
|
+
$asset = require $asset_file;
|
|
1157
|
+
|
|
1158
|
+
if ( ! is_array( $asset ) || empty( $asset['source'] ) || ! is_string( $asset['source'] ) ) {
|
|
1159
|
+
return null;
|
|
1160
|
+
}
|
|
1161
|
+
|
|
1162
|
+
$cache[ $url ] = $asset['source'];
|
|
1163
|
+
|
|
1164
|
+
return $cache[ $url ];
|
|
1165
|
+
}
|
|
1166
|
+
|
|
1167
|
+
/**
|
|
1168
|
+
* Registry of handles whose <script> tag has to be stamped type="module".
|
|
1169
|
+
*
|
|
1170
|
+
* Everything the dev server serves is ESM \u2014 that is the point of dev mode \u2014 so
|
|
1171
|
+
* every handle this file repoints joins the set.
|
|
1172
|
+
*
|
|
1173
|
+
* @param string $handle Script handle.
|
|
1174
|
+
* @param bool $mark Add the handle to the registry.
|
|
1175
|
+
* @return bool Whether the handle prints as a module.
|
|
1176
|
+
*/
|
|
1177
|
+
function ${fn}_is_module( $handle, $mark = false ) {
|
|
1178
|
+
static $handles = array();
|
|
1179
|
+
|
|
1180
|
+
if ( $mark ) {
|
|
1181
|
+
$handles[ $handle ] = true;
|
|
1182
|
+
}
|
|
1183
|
+
|
|
1184
|
+
return isset( $handles[ $handle ] );
|
|
1185
|
+
}
|
|
1186
|
+
|
|
1187
|
+
// Nothing below this line matters when no dev server is running.
|
|
1188
|
+
if ( null === ${fn}_hot() ) {
|
|
1189
|
+
return;
|
|
1190
|
+
}
|
|
1191
|
+
|
|
1192
|
+
/**
|
|
1193
|
+
* Register and enqueue Vite's HMR client, early.
|
|
1194
|
+
*
|
|
1195
|
+
* It opens the websocket, applies hot updates, and renders the error overlay.
|
|
1196
|
+
* Every handle this file repoints gets it as a dependency, so it is always the
|
|
1197
|
+
* first module in the document.
|
|
1198
|
+
*/
|
|
1199
|
+
function ${fn}_enqueue_client() {
|
|
1200
|
+
$src = ${fn}_url( '@vite/client' );
|
|
1201
|
+
|
|
1202
|
+
if ( '' === $src ) {
|
|
1203
|
+
return;
|
|
1204
|
+
}
|
|
1205
|
+
|
|
1206
|
+
wp_register_script( '${client}', $src, array(), null, false );
|
|
1207
|
+
wp_enqueue_script( '${client}' );
|
|
1208
|
+
${fn}_is_module( '${client}', true );
|
|
1209
|
+
|
|
1210
|
+
${fn}_enqueue_react_refresh_preamble();
|
|
1211
|
+
}
|
|
1212
|
+
add_action( 'wp_enqueue_scripts', '${fn}_enqueue_client', -1000 );
|
|
1213
|
+
add_action( 'admin_enqueue_scripts', '${fn}_enqueue_client', -1000 );
|
|
1214
|
+
|
|
1215
|
+
/**
|
|
1216
|
+
* Attach the React Fast Refresh preamble to the vite-client handle, when the
|
|
1217
|
+
* running dev server reports \`vite:react-refresh\` in the hot file's plugin
|
|
1218
|
+
* list.
|
|
1219
|
+
*
|
|
1220
|
+
* The preamble has to run before any React component module evaluates \u2014
|
|
1221
|
+
* @vitejs/plugin-react's transform assumes \`window.$RefreshReg$\` already
|
|
1222
|
+
* exists, and every transformed component module throws otherwise. Attaching
|
|
1223
|
+
* it to the vite-client handle rather than to each rewritten script gets that
|
|
1224
|
+
* ordering for free, two different ways depending on how the component reaches
|
|
1225
|
+
* the page:
|
|
1226
|
+
*
|
|
1227
|
+
* - **Classic scripts.** ${fn}_prepare() (below) makes the client a
|
|
1228
|
+
* dependency of every classic handle this bridge repoints, so WordPress's
|
|
1229
|
+
* own dependency graph orders the client \u2014 and the inline block
|
|
1230
|
+
* \`wp_add_inline_script( \u2026, 'after' )\` attaches to it \u2014 before them.
|
|
1231
|
+
* - **Script Modules.** There is no cross-system dependency a classic handle
|
|
1232
|
+
* can declare on a Script Module, so this relies on where WordPress prints
|
|
1233
|
+
* each group instead: the client is a classic-registered handle (its
|
|
1234
|
+
* \`type="module"\` is only a printed attribute, stamped by
|
|
1235
|
+
* ${fn}_script_tag() below), and every generated page in this package
|
|
1236
|
+
* prints classic scripts \u2014 the client included \u2014 before it prints Script
|
|
1237
|
+
* Modules. Same-document module scripts without \`async\` execute in that
|
|
1238
|
+
* print order, so the preamble still runs first.
|
|
1239
|
+
*
|
|
1240
|
+
* Same mechanics vite-for-wp uses for the classic-script half.
|
|
1241
|
+
*
|
|
1242
|
+
* Guarded by a static so a request that somehow fires both enqueue hooks
|
|
1243
|
+
* cannot attach the preamble, and its type="module" filter, twice.
|
|
1244
|
+
*/
|
|
1245
|
+
function ${fn}_enqueue_react_refresh_preamble() {
|
|
1246
|
+
static $attached = false;
|
|
1247
|
+
|
|
1248
|
+
if ( $attached ) {
|
|
1249
|
+
return;
|
|
1250
|
+
}
|
|
1251
|
+
|
|
1252
|
+
$hot = ${fn}_hot();
|
|
1253
|
+
|
|
1254
|
+
if ( null === $hot || ! in_array( 'vite:react-refresh', $hot['plugins'], true ) ) {
|
|
1255
|
+
return;
|
|
1256
|
+
}
|
|
1257
|
+
|
|
1258
|
+
$attached = true;
|
|
1259
|
+
|
|
1260
|
+
$preamble = sprintf(
|
|
1261
|
+
'import RefreshRuntime from "%1$s"
|
|
1262
|
+
RefreshRuntime.injectIntoGlobalHook(window)
|
|
1263
|
+
window.$RefreshReg$ = () => {}
|
|
1264
|
+
window.$RefreshSig$ = () => (type) => type
|
|
1265
|
+
window.__vite_plugin_react_preamble_installed__ = true',
|
|
1266
|
+
esc_js( ${fn}_url( '@react-refresh' ) )
|
|
1267
|
+
);
|
|
1268
|
+
|
|
1269
|
+
wp_add_inline_script( '${client}', $preamble, 'after' );
|
|
1270
|
+
add_filter( 'wp_inline_script_attributes', '${fn}_react_refresh_inline_attributes' );
|
|
1271
|
+
}
|
|
1272
|
+
|
|
1273
|
+
/**
|
|
1274
|
+
* Stamp type="module" on exactly the inline block ${fn}_enqueue_react_refresh_preamble()
|
|
1275
|
+
* attached \u2014 the preamble is a top-level \`import\`, so it must not print as a
|
|
1276
|
+
* classic inline script the way an 'after' block otherwise would.
|
|
1277
|
+
*
|
|
1278
|
+
* WordPress assigns an inline block printed at the 'after' position the id
|
|
1279
|
+
* \`<handle>-js-after\`; matching on it (rather than the handle alone) is what
|
|
1280
|
+
* keeps this from touching some other inline script attached to the same
|
|
1281
|
+
* vite-client handle by unrelated code.
|
|
1282
|
+
*
|
|
1283
|
+
* @param array $attributes Attributes about to be printed on the inline <script> tag.
|
|
1284
|
+
* @return array
|
|
1285
|
+
*/
|
|
1286
|
+
function ${fn}_react_refresh_inline_attributes( $attributes ) {
|
|
1287
|
+
if ( is_array( $attributes ) && isset( $attributes['id'] ) && '${client}-js-after' === $attributes['id'] ) {
|
|
1288
|
+
$attributes['type'] = 'module';
|
|
1289
|
+
}
|
|
1290
|
+
|
|
1291
|
+
return $attributes;
|
|
1292
|
+
}
|
|
1293
|
+
|
|
1294
|
+
/**
|
|
1295
|
+
* The one pass that has to happen while the queues are still mutable: wire the
|
|
1296
|
+
* HMR client into everything about to be repointed, and swap this directory's
|
|
1297
|
+
* stylesheets for the JS modules Vite serves them as.
|
|
1298
|
+
*
|
|
1299
|
+
* Runs last on the enqueue hooks \u2014 the URL rewriting itself happens later, in
|
|
1300
|
+
* script_loader_src, which also catches handles registered after this point.
|
|
1301
|
+
*/
|
|
1302
|
+
function ${fn}_prepare() {
|
|
1303
|
+
$claimed = array();
|
|
1304
|
+
|
|
1305
|
+
if ( function_exists( 'wp_scripts' ) && function_exists( 'wp_script_is' ) ) {
|
|
1306
|
+
$has_client = wp_script_is( '${client}', 'registered' );
|
|
1307
|
+
|
|
1308
|
+
foreach ( wp_scripts()->registered as $handle => $script ) {
|
|
1309
|
+
if ( '${client}' === $handle || empty( $script->src ) ) {
|
|
1310
|
+
continue;
|
|
1311
|
+
}
|
|
1312
|
+
|
|
1313
|
+
$source = ${fn}_source( $script->src );
|
|
1314
|
+
|
|
1315
|
+
if ( null === $source ) {
|
|
1316
|
+
continue;
|
|
1317
|
+
}
|
|
1318
|
+
|
|
1319
|
+
$claimed[ $source ] = true;
|
|
1320
|
+
|
|
1321
|
+
// Ordering only. A missing client handle would make WordPress drop
|
|
1322
|
+
// the script entirely, so never depend on one that isn't there.
|
|
1323
|
+
if ( $has_client && is_array( $script->deps ) && ! in_array( '${client}', $script->deps, true ) ) {
|
|
1324
|
+
$script->deps[] = '${client}';
|
|
1325
|
+
}
|
|
1326
|
+
}
|
|
1327
|
+
}
|
|
1328
|
+
|
|
1329
|
+
if ( ! function_exists( 'wp_styles' ) ) {
|
|
1330
|
+
return;
|
|
1331
|
+
}
|
|
1332
|
+
|
|
1333
|
+
$styles = wp_styles();
|
|
1334
|
+
|
|
1335
|
+
foreach ( $styles->queue as $handle ) {
|
|
1336
|
+
if ( ! isset( $styles->registered[ $handle ] ) || empty( $styles->registered[ $handle ]->src ) ) {
|
|
1337
|
+
continue;
|
|
1338
|
+
}
|
|
1339
|
+
|
|
1340
|
+
$source = ${fn}_source( $styles->registered[ $handle ]->src );
|
|
1341
|
+
|
|
1342
|
+
if ( null === $source ) {
|
|
1343
|
+
continue;
|
|
1344
|
+
}
|
|
1345
|
+
|
|
1346
|
+
wp_dequeue_style( $handle );
|
|
1347
|
+
|
|
1348
|
+
// A stylesheet whose source is already served by a repointed script is
|
|
1349
|
+
// covered: in dev the entry imports its own CSS.
|
|
1350
|
+
if ( isset( $claimed[ $source ] ) ) {
|
|
1351
|
+
continue;
|
|
1352
|
+
}
|
|
1353
|
+
|
|
1354
|
+
$claimed[ $source ] = true;
|
|
1355
|
+
$shim = $handle . '-vite-dev';
|
|
1356
|
+
|
|
1357
|
+
wp_register_script(
|
|
1358
|
+
$shim,
|
|
1359
|
+
${fn}_url( $source ),
|
|
1360
|
+
wp_script_is( '${client}', 'registered' ) ? array( '${client}' ) : array(),
|
|
1361
|
+
null,
|
|
1362
|
+
false
|
|
1363
|
+
);
|
|
1364
|
+
wp_enqueue_script( $shim );
|
|
1365
|
+
${fn}_is_module( $shim, true );
|
|
1366
|
+
}
|
|
1367
|
+
}
|
|
1368
|
+
add_action( 'wp_enqueue_scripts', '${fn}_prepare', PHP_INT_MAX );
|
|
1369
|
+
add_action( 'admin_enqueue_scripts', '${fn}_prepare', PHP_INT_MAX );
|
|
1370
|
+
|
|
1371
|
+
/**
|
|
1372
|
+
* Repoint a classic script at the dev server.
|
|
1373
|
+
*
|
|
1374
|
+
* @param string $src Script URL.
|
|
1375
|
+
* @param string $handle Script handle.
|
|
1376
|
+
* @return string Rewritten URL, or the original.
|
|
1377
|
+
*/
|
|
1378
|
+
function ${fn}_script_src( $src, $handle ) {
|
|
1379
|
+
$source = ${fn}_source( $src );
|
|
1380
|
+
|
|
1381
|
+
if ( null === $source ) {
|
|
1382
|
+
return $src;
|
|
1383
|
+
}
|
|
1384
|
+
|
|
1385
|
+
// script_loader_src always runs before script_loader_tag for the same
|
|
1386
|
+
// handle (both live in WP_Scripts::do_item()), so marking here is enough.
|
|
1387
|
+
${fn}_is_module( $handle, true );
|
|
1388
|
+
|
|
1389
|
+
return ${fn}_url( $source );
|
|
1390
|
+
}
|
|
1391
|
+
add_filter( 'script_loader_src', '${fn}_script_src', 10, 2 );
|
|
1392
|
+
|
|
1393
|
+
/**
|
|
1394
|
+
* Stamp type="module" on the handles this file repointed.
|
|
1395
|
+
*
|
|
1396
|
+
* @param string $tag Script tag HTML.
|
|
1397
|
+
* @param string $handle Script handle.
|
|
1398
|
+
* @return string Rewritten tag.
|
|
1399
|
+
*/
|
|
1400
|
+
function ${fn}_script_tag( $tag, $handle ) {
|
|
1401
|
+
if ( ! is_string( $tag ) || ! ${fn}_is_module( $handle ) ) {
|
|
1402
|
+
return $tag;
|
|
1403
|
+
}
|
|
1404
|
+
|
|
1405
|
+
// WP 6.2+. Without it, the crude rewrite is still better than letting an
|
|
1406
|
+
// ESM file load as a classic script and throw on its first import.
|
|
1407
|
+
if ( ! class_exists( 'WP_HTML_Tag_Processor' ) ) {
|
|
1408
|
+
return false === strpos( $tag, 'type="module"' )
|
|
1409
|
+
? str_replace( '<script ', '<script type="module" ', $tag )
|
|
1410
|
+
: $tag;
|
|
1411
|
+
}
|
|
1412
|
+
|
|
1413
|
+
$processor = new WP_HTML_Tag_Processor( $tag );
|
|
1414
|
+
|
|
1415
|
+
while ( $processor->next_tag( 'script' ) ) {
|
|
1416
|
+
// Inline blocks attached to the same handle stay classic; only the
|
|
1417
|
+
// src'd tag is the module.
|
|
1418
|
+
if ( null === $processor->get_attribute( 'src' ) ) {
|
|
1419
|
+
continue;
|
|
1420
|
+
}
|
|
1421
|
+
|
|
1422
|
+
$processor->set_attribute( 'type', 'module' );
|
|
1423
|
+
}
|
|
1424
|
+
|
|
1425
|
+
return $processor->get_updated_html();
|
|
1426
|
+
}
|
|
1427
|
+
add_filter( 'script_loader_tag', '${fn}_script_tag', 10, 2 );
|
|
1428
|
+
|
|
1429
|
+
/**
|
|
1430
|
+
* Repoint a Script Module at the dev server.
|
|
1431
|
+
*
|
|
1432
|
+
* script_module_loader_src (WP 6.5+) is the single choke point inside
|
|
1433
|
+
* WP_Script_Modules::get_src() for all three Script Module outputs \u2014 the
|
|
1434
|
+
* <script type="module"> tag, its <link rel="modulepreload">, and the import
|
|
1435
|
+
* map \u2014 so one filter keeps all three consistent and no consumer registration
|
|
1436
|
+
* has to change.
|
|
1437
|
+
*
|
|
1438
|
+
* @param string $src Script Module URL.
|
|
1439
|
+
* @param string $id Script Module identifier.
|
|
1440
|
+
* @return string Rewritten URL, or the original.
|
|
1441
|
+
*/
|
|
1442
|
+
function ${fn}_script_module_src( $src, $id ) {
|
|
1443
|
+
$source = ${fn}_source( $src );
|
|
1444
|
+
|
|
1445
|
+
return null === $source ? $src : ${fn}_url( $source );
|
|
1446
|
+
}
|
|
1447
|
+
add_filter( 'script_module_loader_src', '${fn}_script_module_src', 10, 2 );
|
|
1448
|
+
|
|
1449
|
+
/**
|
|
1450
|
+
* Last resort for a stylesheet ${fn}_prepare() never saw \u2014 one registered
|
|
1451
|
+
* after the enqueue hooks, or pulled in as another stylesheet's dependency.
|
|
1452
|
+
*
|
|
1453
|
+
* Vite's '?direct' serves the compiled CSS with a text/css content type instead
|
|
1454
|
+
* of the JS module a bare .css request returns. Correct styles, no hot reload.
|
|
1455
|
+
*
|
|
1456
|
+
* @param string $src Stylesheet URL.
|
|
1457
|
+
* @param string $handle Stylesheet handle.
|
|
1458
|
+
* @return string Rewritten URL, or the original.
|
|
1459
|
+
*/
|
|
1460
|
+
function ${fn}_style_src( $src, $handle ) {
|
|
1461
|
+
$source = ${fn}_source( $src );
|
|
1462
|
+
|
|
1463
|
+
return null === $source ? $src : ${fn}_url( $source ) . '?direct';
|
|
1464
|
+
}
|
|
1465
|
+
add_filter( 'style_loader_src', '${fn}_style_src', 10, 2 );
|
|
1466
|
+
|
|
1467
|
+
endif;
|
|
1468
|
+
`;
|
|
1469
|
+
}
|
|
877
1470
|
function generatePhpFiles(ctx, pages) {
|
|
878
1471
|
const files = [
|
|
879
1472
|
{ fileName: "build.php", source: renderBuildPhp(ctx) },
|
|
@@ -1815,37 +2408,135 @@ function isBarePackageName(name) {
|
|
|
1815
2408
|
}
|
|
1816
2409
|
return name.length > 0 && !name.includes("/") && !name.startsWith(".");
|
|
1817
2410
|
}
|
|
2411
|
+
function entrySourcePath(facadeModuleId, root) {
|
|
2412
|
+
if (!facadeModuleId) return null;
|
|
2413
|
+
const relativePath = relative(root, facadeModuleId).replace(/\\/g, "/");
|
|
2414
|
+
if (relativePath === "" || relativePath === ".." || relativePath.startsWith("../")) {
|
|
2415
|
+
return null;
|
|
2416
|
+
}
|
|
2417
|
+
if (isAbsolute(relativePath)) return null;
|
|
2418
|
+
return relativePath;
|
|
2419
|
+
}
|
|
2420
|
+
function phpSingleQuoteEscape(value) {
|
|
2421
|
+
return value.replace(/\\/g, "\\\\").replace(/'/g, "\\'");
|
|
2422
|
+
}
|
|
1818
2423
|
var DEFAULT_VENDOR = {
|
|
1819
2424
|
react: { global: "React", handle: "react" },
|
|
1820
2425
|
"react-dom": { global: "ReactDOM", handle: "react-dom" },
|
|
1821
2426
|
"react-dom/client": { global: "ReactDOM", handle: "react-dom" },
|
|
1822
|
-
"react/jsx-runtime": {
|
|
1823
|
-
|
|
2427
|
+
"react/jsx-runtime": {
|
|
2428
|
+
global: "ReactJSXRuntime",
|
|
2429
|
+
handle: "react-jsx-runtime"
|
|
2430
|
+
},
|
|
2431
|
+
"react/jsx-dev-runtime": {
|
|
2432
|
+
global: "ReactJSXRuntime",
|
|
2433
|
+
handle: "react-jsx-runtime"
|
|
2434
|
+
},
|
|
1824
2435
|
moment: { global: "moment", handle: "moment" },
|
|
1825
2436
|
jquery: { global: "jQuery", handle: "jquery" },
|
|
1826
2437
|
lodash: { global: "lodash", handle: "lodash" },
|
|
1827
2438
|
"lodash-es": { global: "lodash", handle: "lodash" }
|
|
1828
2439
|
};
|
|
1829
2440
|
var CJS_GLOBAL_SHIM_PREFIX = "\0wp-external-global:";
|
|
2441
|
+
function matchesScriptModuleNamespace(packageName, scriptModuleNamespaces) {
|
|
2442
|
+
if (!packageName.startsWith("@")) return false;
|
|
2443
|
+
const slashIndex = packageName.indexOf("/");
|
|
2444
|
+
if (slashIndex < 0) return false;
|
|
2445
|
+
const namespace = packageName.slice(1, slashIndex);
|
|
2446
|
+
for (const pattern of scriptModuleNamespaces) {
|
|
2447
|
+
if (pattern.endsWith("*")) {
|
|
2448
|
+
if (namespace.startsWith(pattern.slice(0, -1))) return true;
|
|
2449
|
+
} else if (namespace === pattern) {
|
|
2450
|
+
return true;
|
|
2451
|
+
}
|
|
2452
|
+
}
|
|
2453
|
+
return false;
|
|
2454
|
+
}
|
|
2455
|
+
function resolveExternal(specifier, options) {
|
|
2456
|
+
const projectRoot = options.projectRoot;
|
|
2457
|
+
const vendorExternals = options.vendorExternals ?? DEFAULT_VENDOR;
|
|
2458
|
+
const externalNamespaces = options.externalNamespaces ?? {};
|
|
2459
|
+
const scriptModuleNamespaces = options.scriptModuleNamespaces ?? [];
|
|
2460
|
+
const bundledPackages = options.bundledPackages instanceof Set ? options.bundledPackages : new Set(options.bundledPackages ?? []);
|
|
2461
|
+
if (bundledPackages.has(splitImport(specifier).name)) return null;
|
|
2462
|
+
if (vendorExternals[specifier]) {
|
|
2463
|
+
const vendor = vendorExternals[specifier];
|
|
2464
|
+
return {
|
|
2465
|
+
global: vendor.global,
|
|
2466
|
+
handle: vendor.handle,
|
|
2467
|
+
specifier,
|
|
2468
|
+
moduleEligible: false,
|
|
2469
|
+
scriptEligible: true
|
|
2470
|
+
};
|
|
2471
|
+
}
|
|
2472
|
+
const { name, subpath } = splitImport(specifier);
|
|
2473
|
+
if (name.startsWith("@wordpress/")) {
|
|
2474
|
+
const meta = readPackageMetadata(name, projectRoot);
|
|
2475
|
+
if (!meta) {
|
|
2476
|
+
return null;
|
|
2477
|
+
}
|
|
2478
|
+
const shortName = name.slice("@wordpress/".length);
|
|
2479
|
+
const moduleEligible = isScriptModule(meta, subpath);
|
|
2480
|
+
const scriptEligible = !!meta.wpScript;
|
|
2481
|
+
if (!moduleEligible && !scriptEligible) {
|
|
2482
|
+
return null;
|
|
2483
|
+
}
|
|
2484
|
+
return {
|
|
2485
|
+
global: scriptEligible ? `wp.${camelize(shortName)}` : null,
|
|
2486
|
+
handle: scriptEligible ? `wp-${shortName}` : null,
|
|
2487
|
+
specifier,
|
|
2488
|
+
moduleEligible,
|
|
2489
|
+
scriptEligible
|
|
2490
|
+
};
|
|
2491
|
+
}
|
|
2492
|
+
for (const [namespace, config] of Object.entries(externalNamespaces)) {
|
|
2493
|
+
if (name.startsWith(`@${namespace}/`)) {
|
|
2494
|
+
const shortName = name.slice(`@${namespace}/`.length);
|
|
2495
|
+
return {
|
|
2496
|
+
global: `${config.global}.${camelize(shortName)}`,
|
|
2497
|
+
handle: `${config.handlePrefix}-${shortName}`,
|
|
2498
|
+
specifier,
|
|
2499
|
+
moduleEligible: false,
|
|
2500
|
+
scriptEligible: true
|
|
2501
|
+
};
|
|
2502
|
+
}
|
|
2503
|
+
}
|
|
2504
|
+
if (matchesScriptModuleNamespace(name, scriptModuleNamespaces)) {
|
|
2505
|
+
return {
|
|
2506
|
+
global: null,
|
|
2507
|
+
handle: null,
|
|
2508
|
+
specifier,
|
|
2509
|
+
moduleEligible: true,
|
|
2510
|
+
scriptEligible: false
|
|
2511
|
+
};
|
|
2512
|
+
}
|
|
2513
|
+
return null;
|
|
2514
|
+
}
|
|
1830
2515
|
var JS_IDENTIFIER = "[A-Za-z_$][\\w$]*";
|
|
2516
|
+
var SIDE_EFFECT_IMPORT = /^\s*import\s*['"][^'"]+['"]\s*;?\s*$/;
|
|
1831
2517
|
function rewriteImport(importStatement, globalAccess) {
|
|
1832
|
-
|
|
1833
|
-
|
|
2518
|
+
if (SIDE_EFFECT_IMPORT.test(importStatement)) return "";
|
|
2519
|
+
const match = importStatement.match(/^\s*import\s*(.*?)\s*from\s*['"][^'"]+['"]\s*;?\s*$/s);
|
|
2520
|
+
if (!match || !match[1]) return null;
|
|
1834
2521
|
const bindings = match[1].trim();
|
|
1835
|
-
const namespaceImport = bindings.match(new RegExp(`^\\*\\s
|
|
2522
|
+
const namespaceImport = bindings.match(new RegExp(`^\\*\\s*as\\s+(${JS_IDENTIFIER})$`));
|
|
1836
2523
|
if (namespaceImport) return `const ${namespaceImport[1]} = ${globalAccess};`;
|
|
1837
2524
|
const defaultWithNamed = bindings.match(
|
|
1838
2525
|
new RegExp(`^(${JS_IDENTIFIER})\\s*,\\s*\\{(.+)\\}$`, "s")
|
|
1839
2526
|
);
|
|
1840
2527
|
if (defaultWithNamed) {
|
|
2528
|
+
const destructured = namedImportsToDestructuring(defaultWithNamed[2].trim());
|
|
2529
|
+
if (destructured === null) return null;
|
|
1841
2530
|
return [
|
|
1842
2531
|
`const ${defaultWithNamed[1]} = (${globalAccess} && ${globalAccess}.default) || ${globalAccess};`,
|
|
1843
|
-
`const { ${
|
|
2532
|
+
`const { ${destructured} } = ${globalAccess};`
|
|
1844
2533
|
].join(" ");
|
|
1845
2534
|
}
|
|
1846
2535
|
if (bindings.startsWith("{")) {
|
|
1847
2536
|
const namedImports = bindings.replace(/^\{|\}$/g, "").trim();
|
|
1848
|
-
|
|
2537
|
+
const destructured = namedImportsToDestructuring(namedImports);
|
|
2538
|
+
if (destructured === null) return null;
|
|
2539
|
+
return `const { ${destructured} } = ${globalAccess};`;
|
|
1849
2540
|
}
|
|
1850
2541
|
if (new RegExp(`^${JS_IDENTIFIER}$`).test(bindings)) {
|
|
1851
2542
|
return `const ${bindings} = (${globalAccess} && ${globalAccess}.default) || ${globalAccess};`;
|
|
@@ -1854,10 +2545,23 @@ function rewriteImport(importStatement, globalAccess) {
|
|
|
1854
2545
|
}
|
|
1855
2546
|
function namedImportsToDestructuring(namedImports) {
|
|
1856
2547
|
const aliasPattern = new RegExp(`^(${JS_IDENTIFIER})\\s+as\\s+(${JS_IDENTIFIER})$`);
|
|
1857
|
-
|
|
2548
|
+
const plainPattern = new RegExp(`^${JS_IDENTIFIER}$`);
|
|
2549
|
+
const bindings = [];
|
|
2550
|
+
for (const raw of namedImports.split(",")) {
|
|
2551
|
+
const binding = raw.trim();
|
|
2552
|
+
if (!binding) continue;
|
|
1858
2553
|
const aliased = binding.match(aliasPattern);
|
|
1859
|
-
|
|
1860
|
-
|
|
2554
|
+
if (aliased) {
|
|
2555
|
+
bindings.push(`${aliased[1]}: ${aliased[2]}`);
|
|
2556
|
+
continue;
|
|
2557
|
+
}
|
|
2558
|
+
if (plainPattern.test(binding)) {
|
|
2559
|
+
bindings.push(binding);
|
|
2560
|
+
continue;
|
|
2561
|
+
}
|
|
2562
|
+
return null;
|
|
2563
|
+
}
|
|
2564
|
+
return bindings.join(", ");
|
|
1861
2565
|
}
|
|
1862
2566
|
function wpExternals(options = {}) {
|
|
1863
2567
|
const projectRoot = options.projectRoot ?? process.cwd();
|
|
@@ -1867,6 +2571,7 @@ function wpExternals(options = {}) {
|
|
|
1867
2571
|
const moduleEntryMatchers = options.moduleEntryMatchers ?? [];
|
|
1868
2572
|
const wpBuildAssetMatchers = options.wpBuildAssetMatchers ?? [];
|
|
1869
2573
|
const scriptModuleNamespaces = options.scriptModuleNamespaces ?? [];
|
|
2574
|
+
const globalsSink = options.globalsSink;
|
|
1870
2575
|
for (const name of options.bundle ?? []) {
|
|
1871
2576
|
if (isBarePackageName(name)) continue;
|
|
1872
2577
|
const { name: rootName, subpath } = splitImport(name);
|
|
@@ -1875,24 +2580,22 @@ function wpExternals(options = {}) {
|
|
|
1875
2580
|
);
|
|
1876
2581
|
}
|
|
1877
2582
|
const bundledPackages = /* @__PURE__ */ new Set([...DEFAULT_BUNDLED_PACKAGES, ...options.bundle ?? []]);
|
|
1878
|
-
|
|
1879
|
-
|
|
1880
|
-
|
|
1881
|
-
|
|
1882
|
-
|
|
1883
|
-
|
|
1884
|
-
|
|
1885
|
-
|
|
1886
|
-
|
|
1887
|
-
|
|
1888
|
-
|
|
1889
|
-
}
|
|
1890
|
-
return false;
|
|
2583
|
+
const resolveExternalOptions = {
|
|
2584
|
+
projectRoot,
|
|
2585
|
+
vendorExternals,
|
|
2586
|
+
externalNamespaces,
|
|
2587
|
+
scriptModuleNamespaces,
|
|
2588
|
+
bundledPackages
|
|
2589
|
+
};
|
|
2590
|
+
function resolveExternalForThisPlugin(specifier) {
|
|
2591
|
+
const external = resolveExternal(specifier, resolveExternalOptions);
|
|
2592
|
+
if (external?.global) globalsSink?.set(external.specifier, external.global);
|
|
2593
|
+
return external;
|
|
1891
2594
|
}
|
|
1892
2595
|
function buildModeForFile(moduleId) {
|
|
1893
|
-
const filePath = moduleId.split("?")[0] ?? moduleId;
|
|
2596
|
+
const filePath = (moduleId.split("?")[0] ?? moduleId).replace(/\\/g, "/");
|
|
1894
2597
|
for (const pattern of moduleEntryMatchers) {
|
|
1895
|
-
if (filePath.includes(pattern)) return "module";
|
|
2598
|
+
if (filePath.includes(pattern.replace(/\\/g, "/"))) return "module";
|
|
1896
2599
|
}
|
|
1897
2600
|
return buildType;
|
|
1898
2601
|
}
|
|
@@ -1904,61 +2607,6 @@ function wpExternals(options = {}) {
|
|
|
1904
2607
|
}
|
|
1905
2608
|
return false;
|
|
1906
2609
|
}
|
|
1907
|
-
function resolveExternal(specifier) {
|
|
1908
|
-
if (bundledPackages.has(splitImport(specifier).name)) return null;
|
|
1909
|
-
if (vendorExternals[specifier]) {
|
|
1910
|
-
const vendor = vendorExternals[specifier];
|
|
1911
|
-
return {
|
|
1912
|
-
global: vendor.global,
|
|
1913
|
-
handle: vendor.handle,
|
|
1914
|
-
specifier,
|
|
1915
|
-
moduleEligible: false,
|
|
1916
|
-
scriptEligible: true
|
|
1917
|
-
};
|
|
1918
|
-
}
|
|
1919
|
-
const { name, subpath } = splitImport(specifier);
|
|
1920
|
-
if (name.startsWith("@wordpress/")) {
|
|
1921
|
-
const meta = readPackageMetadata(name, projectRoot);
|
|
1922
|
-
if (!meta) {
|
|
1923
|
-
return null;
|
|
1924
|
-
}
|
|
1925
|
-
const shortName = name.slice("@wordpress/".length);
|
|
1926
|
-
const moduleEligible = isScriptModule(meta, subpath);
|
|
1927
|
-
const scriptEligible = !!meta.wpScript;
|
|
1928
|
-
if (!moduleEligible && !scriptEligible) {
|
|
1929
|
-
return null;
|
|
1930
|
-
}
|
|
1931
|
-
return {
|
|
1932
|
-
global: scriptEligible ? `wp.${camelize(shortName)}` : null,
|
|
1933
|
-
handle: scriptEligible ? `wp-${shortName}` : null,
|
|
1934
|
-
specifier,
|
|
1935
|
-
moduleEligible,
|
|
1936
|
-
scriptEligible
|
|
1937
|
-
};
|
|
1938
|
-
}
|
|
1939
|
-
for (const [namespace, config] of Object.entries(externalNamespaces)) {
|
|
1940
|
-
if (name.startsWith(`@${namespace}/`)) {
|
|
1941
|
-
const shortName = name.slice(`@${namespace}/`.length);
|
|
1942
|
-
return {
|
|
1943
|
-
global: `${config.global}.${camelize(shortName)}`,
|
|
1944
|
-
handle: `${config.handlePrefix}-${shortName}`,
|
|
1945
|
-
specifier,
|
|
1946
|
-
moduleEligible: false,
|
|
1947
|
-
scriptEligible: true
|
|
1948
|
-
};
|
|
1949
|
-
}
|
|
1950
|
-
}
|
|
1951
|
-
if (matchesScriptModuleNamespace(name)) {
|
|
1952
|
-
return {
|
|
1953
|
-
global: null,
|
|
1954
|
-
handle: null,
|
|
1955
|
-
specifier,
|
|
1956
|
-
moduleEligible: true,
|
|
1957
|
-
scriptEligible: false
|
|
1958
|
-
};
|
|
1959
|
-
}
|
|
1960
|
-
return null;
|
|
1961
|
-
}
|
|
1962
2610
|
function moduleImportKind(specifier, isDynamic) {
|
|
1963
2611
|
if (specifier === "@wordpress/interactivity") return "static";
|
|
1964
2612
|
return isDynamic ? "dynamic" : "static";
|
|
@@ -1979,7 +2627,7 @@ function wpExternals(options = {}) {
|
|
|
1979
2627
|
enforce: "pre",
|
|
1980
2628
|
resolveId(source, _importer, options2) {
|
|
1981
2629
|
const isRequireCall = options2?.kind === "require-call";
|
|
1982
|
-
const external =
|
|
2630
|
+
const external = resolveExternalForThisPlugin(source);
|
|
1983
2631
|
if (external) {
|
|
1984
2632
|
if (isRequireCall) {
|
|
1985
2633
|
if (external.global) {
|
|
@@ -1994,7 +2642,7 @@ function wpExternals(options = {}) {
|
|
|
1994
2642
|
return { id: source, external: true };
|
|
1995
2643
|
}
|
|
1996
2644
|
const commonjsMatch = source.match(/^\0([^?]+)\?commonjs-external$/);
|
|
1997
|
-
if (commonjsMatch && commonjsMatch[1] &&
|
|
2645
|
+
if (commonjsMatch && commonjsMatch[1] && resolveExternalForThisPlugin(commonjsMatch[1])) {
|
|
1998
2646
|
return source;
|
|
1999
2647
|
}
|
|
2000
2648
|
return null;
|
|
@@ -2002,7 +2650,7 @@ function wpExternals(options = {}) {
|
|
|
2002
2650
|
load(id) {
|
|
2003
2651
|
if (id.startsWith(CJS_GLOBAL_SHIM_PREFIX)) {
|
|
2004
2652
|
const specifier = id.slice(CJS_GLOBAL_SHIM_PREFIX.length);
|
|
2005
|
-
const external2 =
|
|
2653
|
+
const external2 = resolveExternalForThisPlugin(specifier);
|
|
2006
2654
|
if (!external2 || !external2.global) return null;
|
|
2007
2655
|
if (external2.handle) recordDeps(handleDepsByModule, id, [external2.handle]);
|
|
2008
2656
|
return `module.exports = (typeof window !== "undefined" ? window.${external2.global} : {});
|
|
@@ -2010,7 +2658,7 @@ function wpExternals(options = {}) {
|
|
|
2010
2658
|
}
|
|
2011
2659
|
const commonjsMatch = id.match(/^\0([^?]+)\?commonjs-external$/);
|
|
2012
2660
|
if (!commonjsMatch || !commonjsMatch[1]) return null;
|
|
2013
|
-
const external =
|
|
2661
|
+
const external = resolveExternalForThisPlugin(commonjsMatch[1]);
|
|
2014
2662
|
if (!external) return null;
|
|
2015
2663
|
if (buildModeForFile(id) === "module" && external.moduleEligible) {
|
|
2016
2664
|
return `export default {};`;
|
|
@@ -2022,9 +2670,13 @@ function wpExternals(options = {}) {
|
|
|
2022
2670
|
return `const __wpExternal = (typeof window !== "undefined" ? window.${external.global} : {}); export default __wpExternal;`;
|
|
2023
2671
|
}
|
|
2024
2672
|
};
|
|
2673
|
+
let resolvedRoot = projectRoot;
|
|
2025
2674
|
const transformPlugin = {
|
|
2026
2675
|
name: `wp-externals(${buildType})`,
|
|
2027
2676
|
enforce: "post",
|
|
2677
|
+
configResolved(config) {
|
|
2678
|
+
resolvedRoot = config.root;
|
|
2679
|
+
},
|
|
2028
2680
|
async transform(code, id) {
|
|
2029
2681
|
if (!code.includes("@wordpress/") && !Object.keys(vendorExternals).some((packageName) => code.includes(packageName)) && !Object.keys(externalNamespaces).some(
|
|
2030
2682
|
(namespace) => code.includes(`@${namespace}/`)
|
|
@@ -2064,7 +2716,7 @@ Most likely cause: JSX in a file that isn't .jsx/.tsx. JSX must live in .jsx/.ts
|
|
|
2064
2716
|
for (const importRecord of imports) {
|
|
2065
2717
|
const importedSpecifier = importRecord.n;
|
|
2066
2718
|
if (importedSpecifier === void 0) continue;
|
|
2067
|
-
const external =
|
|
2719
|
+
const external = resolveExternalForThisPlugin(importedSpecifier);
|
|
2068
2720
|
if (!external) continue;
|
|
2069
2721
|
const isDynamic = importRecord.d > -1;
|
|
2070
2722
|
if (fileMode === "script") {
|
|
@@ -2198,6 +2850,10 @@ Most likely cause: JSX in a file that isn't .jsx/.tsx. JSX must live in .jsx/.ts
|
|
|
2198
2850
|
}
|
|
2199
2851
|
fields.push(`'version' => '${version}'`);
|
|
2200
2852
|
if (entryMode === "module") fields.push(`'type' => 'module'`);
|
|
2853
|
+
const sourcePath = entrySourcePath(output.facadeModuleId, resolvedRoot);
|
|
2854
|
+
if (sourcePath) {
|
|
2855
|
+
fields.push(`'source' => '${phpSingleQuoteEscape(sourcePath)}'`);
|
|
2856
|
+
}
|
|
2201
2857
|
this.emitFile({
|
|
2202
2858
|
type: "asset",
|
|
2203
2859
|
fileName: fileName.replace(/\.m?js$/, ".asset.php"),
|
|
@@ -2558,7 +3214,14 @@ var CLASSIC_SCRIPT_DEFINE = {
|
|
|
2558
3214
|
"import.meta.resolve": "undefined"
|
|
2559
3215
|
};
|
|
2560
3216
|
var LIVE_MODULE_STATEMENT = /^[ \t]*(?:import\s*(?:[{*"']|[A-Za-z_$][\w$]*\s*(?:,|from\b))|export\s*(?:[{*]|(?:default|const|let|var|function|class|async)\b))[^\n]*/m;
|
|
2561
|
-
|
|
3217
|
+
var ROLLDOWN_REQUIRE_SHIM = /typeof\s+require\s*(?:<|!==?|===?)/;
|
|
3218
|
+
var REQUIRE_CALL = /(?:^|[^.\w$])require\s*\(/;
|
|
3219
|
+
function buildRequireShim(globals) {
|
|
3220
|
+
const cases = [...globals.entries()].map(([specifier, global]) => `case ${JSON.stringify(specifier)}:return window.${global};`).join("");
|
|
3221
|
+
return `const require=(id)=>{switch(id){${cases}}throw new Error('require("'+id+'") is not mapped to a global in this classic script.');};`;
|
|
3222
|
+
}
|
|
3223
|
+
function wpScriptIife(options = {}) {
|
|
3224
|
+
const globals = options.globals ?? /* @__PURE__ */ new Map();
|
|
2562
3225
|
return {
|
|
2563
3226
|
name: "wp-script-iife",
|
|
2564
3227
|
// Build-only. Vite filters plugins by `apply` before it runs `config`,
|
|
@@ -2574,34 +3237,68 @@ function wpScriptIife() {
|
|
|
2574
3237
|
}
|
|
2575
3238
|
return Object.keys(define).length > 0 ? { define } : null;
|
|
2576
3239
|
},
|
|
2577
|
-
async writeBundle(
|
|
3240
|
+
async writeBundle(options2, bundle) {
|
|
2578
3241
|
const { readFile, writeFile } = await import('fs/promises');
|
|
2579
|
-
const { join:
|
|
2580
|
-
const outDir =
|
|
3242
|
+
const { join: join6 } = await import('path');
|
|
3243
|
+
const outDir = options2.dir ?? ".";
|
|
3244
|
+
const pending = [];
|
|
3245
|
+
const failures = [];
|
|
2581
3246
|
for (const [fileName, output] of Object.entries(bundle)) {
|
|
2582
3247
|
if (output.type !== "chunk") continue;
|
|
2583
3248
|
if (!fileName.endsWith(".js") && !fileName.endsWith(".mjs")) continue;
|
|
2584
3249
|
if (!output.isEntry && !output.isDynamicEntry) continue;
|
|
2585
|
-
const filePath =
|
|
3250
|
+
const filePath = join6(outDir, fileName);
|
|
2586
3251
|
let chunkSource = await readFile(filePath, "utf8");
|
|
2587
|
-
const sideEffectImport = /^\s*import\s
|
|
3252
|
+
const sideEffectImport = /^\s*import\s*["'][^"']+["'];?\s*\n?/;
|
|
2588
3253
|
while (sideEffectImport.test(chunkSource)) {
|
|
2589
3254
|
chunkSource = chunkSource.replace(sideEffectImport, "");
|
|
2590
3255
|
}
|
|
2591
|
-
|
|
2592
|
-
|
|
3256
|
+
const failure = classicScriptFailure(
|
|
3257
|
+
fileName,
|
|
3258
|
+
chunkSource,
|
|
3259
|
+
output.isEntry !== true
|
|
3260
|
+
);
|
|
3261
|
+
if (failure) {
|
|
3262
|
+
failures.push(failure);
|
|
3263
|
+
continue;
|
|
3264
|
+
}
|
|
3265
|
+
if (ROLLDOWN_REQUIRE_SHIM.test(chunkSource)) {
|
|
3266
|
+
pending.push({
|
|
3267
|
+
filePath,
|
|
3268
|
+
body: `${buildRequireShim(globals)}(()=>{
|
|
2593
3269
|
${chunkSource}
|
|
3270
|
+
})();`
|
|
3271
|
+
});
|
|
3272
|
+
continue;
|
|
3273
|
+
}
|
|
3274
|
+
if (globals.size > 0 && REQUIRE_CALL.test(chunkSource)) {
|
|
3275
|
+
this.warn(
|
|
3276
|
+
`${fileName} calls \`require()\` but carries none of Rolldown's runtime require shim, so no global mapping was injected. If this is a CJS dependency reaching for an external, it will throw at runtime \u2014 please report it, as the shim's shape may have changed.`
|
|
3277
|
+
);
|
|
3278
|
+
}
|
|
3279
|
+
pending.push({ filePath, body: chunkSource });
|
|
3280
|
+
}
|
|
3281
|
+
if (failures.length > 0) {
|
|
3282
|
+
throw new Error(
|
|
3283
|
+
`wp-script-iife: ${failures.length} chunk(s) are not valid as classic scripts, so nothing was wrapped:
|
|
3284
|
+
|
|
3285
|
+
${failures.join("\n\n")}`
|
|
3286
|
+
);
|
|
3287
|
+
}
|
|
3288
|
+
for (const { filePath, body } of pending) {
|
|
3289
|
+
await writeFile(filePath, `(()=>{
|
|
3290
|
+
${body}
|
|
2594
3291
|
})();
|
|
2595
3292
|
`);
|
|
2596
3293
|
}
|
|
2597
3294
|
}
|
|
2598
3295
|
};
|
|
2599
3296
|
}
|
|
2600
|
-
function
|
|
3297
|
+
function classicScriptFailure(fileName, code, isDynamicOnly = false) {
|
|
2601
3298
|
let parseError;
|
|
2602
3299
|
try {
|
|
2603
3300
|
new Function(code);
|
|
2604
|
-
return;
|
|
3301
|
+
return null;
|
|
2605
3302
|
} catch (error) {
|
|
2606
3303
|
if (!(error instanceof SyntaxError)) throw error;
|
|
2607
3304
|
parseError = error;
|
|
@@ -2609,24 +3306,19 @@ function assertClassicScript(fileName, code, isDynamicOnly = false) {
|
|
|
2609
3306
|
const liveStatement = code.match(LIVE_MODULE_STATEMENT);
|
|
2610
3307
|
if (liveStatement) {
|
|
2611
3308
|
const specifiers = [...code.matchAll(/^[ \t]*(?:import|export)\b[^\n]*?["']([^"']+)["']/gm)].map((match) => match[1]).filter((specifier, index, all) => all.indexOf(specifier) === index);
|
|
2612
|
-
|
|
2613
|
-
`wp-script-iife: ${fileName} still contains a top-level module statement, which is a SyntaxError once WordPress enqueues it as a classic script:
|
|
3309
|
+
return `wp-script-iife: ${fileName} still contains a top-level module statement, which is a SyntaxError once WordPress enqueues it as a classic script:
|
|
2614
3310
|
${liveStatement[0].trim()}
|
|
2615
3311
|
` + (specifiers.length > 0 ? ` Imported chunk(s): ${specifiers.join(", ")}
|
|
2616
|
-
` : "") + (isDynamicOnly ? ` This file is a dynamic-import chunk, so it needs its \`export\`s and cannot be an IIFE. A script-mode entry can't lazily load one either (WP has no module context to resolve it in) \u2014 drop the dynamic \`import()\`, or build this entry in module mode.` : ` This is almost always a shared chunk: a module two or more script-mode entries import gets hoisted into its own chunk instead of being duplicated into each entry. Add the wpScriptDedupe() plugin (auto-included by wp() in script mode \u2014 check you haven't set \`scriptDedupe: false\`), or build this entry in module mode
|
|
2617
|
-
|
|
3312
|
+
` : "") + (isDynamicOnly ? ` This file is a dynamic-import chunk, so it needs its \`export\`s and cannot be an IIFE. A script-mode entry can't lazily load one either (WP has no module context to resolve it in) \u2014 drop the dynamic \`import()\`, or build this entry in module mode.` : ` This is almost always a shared chunk: a module two or more script-mode entries import gets hoisted into its own chunk instead of being duplicated into each entry. Add the wpScriptDedupe() plugin (auto-included by wp() in script mode \u2014 check you haven't set \`scriptDedupe: false\`), or build this entry in module mode.
|
|
3313
|
+
If the specifier above is a bare \`@wordpress/*\` package rather than a relative chunk path, this is instead a module-only package (no \`wpScript\` in its package.json) imported into a script-mode entry \u2014 wpExternals warns about it by name earlier in the build. Move that import to a viewScriptModule entry, or build this entry in module mode.`);
|
|
2618
3314
|
}
|
|
2619
3315
|
if (/\bimport\.meta\b/.test(code)) {
|
|
2620
|
-
|
|
2621
|
-
|
|
2622
|
-
Vite injects its module-preload helper (which reads \`import.meta.url\`) whenever the bundled graph contains a dynamic \`import()\` \u2014 \`build.modulePreload: false\` does not remove it. This plugin's \`config()\` hook defines \`import.meta.url\`/\`import.meta.resolve\` away; a surviving reference means either that define was overridden, or the code touches another \`import.meta\` member. Extend \`define\` in your Vite config, or move this entry to module mode.`
|
|
2623
|
-
);
|
|
3316
|
+
return `wp-script-iife: ${fileName} references \`import.meta\`, which is a SyntaxError once WordPress enqueues it as a classic script.
|
|
3317
|
+
Vite injects its module-preload helper (which reads \`import.meta.url\`) whenever the bundled graph contains a dynamic \`import()\` \u2014 \`build.modulePreload: false\` does not remove it. This plugin's \`config()\` hook defines \`import.meta.url\`/\`import.meta.resolve\` away; a surviving reference means either that define was overridden, or the code touches another \`import.meta\` member. Extend \`define\` in your Vite config, or move this entry to module mode.`;
|
|
2624
3318
|
}
|
|
2625
|
-
|
|
2626
|
-
`wp-script-iife: ${fileName} does not parse as a classic script, so WordPress could not load it:
|
|
3319
|
+
return `wp-script-iife: ${fileName} does not parse as a classic script, so WordPress could not load it:
|
|
2627
3320
|
${parseError.message}
|
|
2628
|
-
Nothing in this plugin's usual suspects (a shared chunk's \`import\`, an \`import.meta\` reference) explains it \u2014 inspect the written file, and report it upstream if the source is valid
|
|
2629
|
-
);
|
|
3321
|
+
Nothing in this plugin's usual suspects (a shared chunk's \`import\`, an \`import.meta\` reference) explains it \u2014 inspect the written file, and report it upstream if the source is valid.`;
|
|
2630
3322
|
}
|
|
2631
3323
|
|
|
2632
3324
|
// src/wp-clean-css-chunks.ts
|
|
@@ -2645,17 +3337,37 @@ function wpCleanCssChunks() {
|
|
|
2645
3337
|
};
|
|
2646
3338
|
}
|
|
2647
3339
|
var STYLESHEET_EXTENSION = /\.(css|scss|sass)$/i;
|
|
3340
|
+
function tryRealpath(path) {
|
|
3341
|
+
try {
|
|
3342
|
+
return realpathSync(path);
|
|
3343
|
+
} catch {
|
|
3344
|
+
return path;
|
|
3345
|
+
}
|
|
3346
|
+
}
|
|
3347
|
+
function entrySourcePath2(sourcePath, root) {
|
|
3348
|
+
const relativePath = relative(tryRealpath(root), tryRealpath(sourcePath)).replace(/\\/g, "/");
|
|
3349
|
+
if (relativePath === "" || relativePath === ".." || relativePath.startsWith("../")) {
|
|
3350
|
+
return null;
|
|
3351
|
+
}
|
|
3352
|
+
if (isAbsolute(relativePath)) return null;
|
|
3353
|
+
return relativePath;
|
|
3354
|
+
}
|
|
3355
|
+
function phpSingleQuoteEscape2(value) {
|
|
3356
|
+
return value.replace(/\\/g, "\\\\").replace(/'/g, "\\'");
|
|
3357
|
+
}
|
|
2648
3358
|
function wpCssAssetInfo() {
|
|
2649
3359
|
const cssEntries = /* @__PURE__ */ new Map();
|
|
3360
|
+
let resolvedRoot = process.cwd();
|
|
2650
3361
|
return {
|
|
2651
3362
|
name: "wp-css-asset-info",
|
|
2652
3363
|
configResolved(config) {
|
|
2653
3364
|
cssEntries.clear();
|
|
3365
|
+
resolvedRoot = config.root;
|
|
2654
3366
|
const input = config.build?.rollupOptions?.input;
|
|
2655
3367
|
if (!input || typeof input !== "object" || Array.isArray(input)) return;
|
|
2656
3368
|
for (const [entryName, source] of Object.entries(input)) {
|
|
2657
3369
|
if (typeof source === "string" && STYLESHEET_EXTENSION.test(source)) {
|
|
2658
|
-
cssEntries.set(entryName, source);
|
|
3370
|
+
cssEntries.set(entryName, resolve(config.root, source));
|
|
2659
3371
|
}
|
|
2660
3372
|
}
|
|
2661
3373
|
},
|
|
@@ -2672,10 +3384,13 @@ function wpCssAssetInfo() {
|
|
|
2672
3384
|
const assetPhpFileName = cssAsset.fileName.replace(/\.css$/i, ".asset.php");
|
|
2673
3385
|
if (bundle[assetPhpFileName]) continue;
|
|
2674
3386
|
const version = crypto.createHash("md5").update(cssAsset.source).digest("hex");
|
|
3387
|
+
const fields = [`'dependencies' => array()`, `'version' => '${version}'`];
|
|
3388
|
+
const source = entrySourcePath2(sourcePath, resolvedRoot);
|
|
3389
|
+
if (source) fields.push(`'source' => '${phpSingleQuoteEscape2(source)}'`);
|
|
2675
3390
|
this.emitFile({
|
|
2676
3391
|
type: "asset",
|
|
2677
3392
|
fileName: assetPhpFileName,
|
|
2678
|
-
source: `<?php return array(
|
|
3393
|
+
source: `<?php return array( ${fields.join(", ")} );
|
|
2679
3394
|
`
|
|
2680
3395
|
});
|
|
2681
3396
|
}
|
|
@@ -2693,6 +3408,681 @@ function findCssAsset(bundle, expectedFileName, sourcePath) {
|
|
|
2693
3408
|
}
|
|
2694
3409
|
return void 0;
|
|
2695
3410
|
}
|
|
3411
|
+
var HOT_FILE_NAME = ".wp-vite-dev.json";
|
|
3412
|
+
var DEV_SERVER_PHP_NAME = "dev-server.php";
|
|
3413
|
+
var DEFAULT_PHP_PREFIX = "wp-vite";
|
|
3414
|
+
var REPORTED_PLUGINS = ["vite:react-refresh"];
|
|
3415
|
+
var SCAN_EXTENSIONS = [".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs"];
|
|
3416
|
+
var STYLESHEET_EXTENSION2 = /\.(css|scss|sass)$/i;
|
|
3417
|
+
var JSX_SOURCE_EXTENSION = /\.[jt]sx$/i;
|
|
3418
|
+
var JSX_RUNTIME_SPECIFIER = "react/jsx-runtime";
|
|
3419
|
+
var DEFAULT_MAX_SCAN_DEPTH = 24;
|
|
3420
|
+
var REDISCOVER_DEBOUNCE_MS = 50;
|
|
3421
|
+
function wpDevServer(options = {}) {
|
|
3422
|
+
const projectRoot = options.projectRoot ?? process.cwd();
|
|
3423
|
+
const emitManifest = options.emitManifest ?? true;
|
|
3424
|
+
const buildType = options.buildType ?? "script";
|
|
3425
|
+
const skip = new Set(options.skip ?? []);
|
|
3426
|
+
const maxScanDepth = options.maxScanDepth ?? DEFAULT_MAX_SCAN_DEPTH;
|
|
3427
|
+
const moduleEntryMatchers = options.moduleEntryMatchers;
|
|
3428
|
+
const wpBuildAssetMatchers = (options.wpBuildAssetMatchers ?? []).map(toPosix);
|
|
3429
|
+
const resolveExternalOptions = {
|
|
3430
|
+
projectRoot,
|
|
3431
|
+
...options.additionalExternals ? { vendorExternals: options.additionalExternals } : {},
|
|
3432
|
+
...options.externalNamespaces ? { externalNamespaces: options.externalNamespaces } : {},
|
|
3433
|
+
...options.scriptModuleNamespaces ? { scriptModuleNamespaces: options.scriptModuleNamespaces } : {},
|
|
3434
|
+
...options.bundledPackages ? { bundledPackages: options.bundledPackages } : {}
|
|
3435
|
+
};
|
|
3436
|
+
const blocksDirAbs = options.blocksDir ? resolve(process.cwd(), options.blocksDir) : null;
|
|
3437
|
+
const blockStylesDirAbs = options.blocksStylesDir ? resolve(process.cwd(), options.blocksStylesDir) : null;
|
|
3438
|
+
const adminPagesDirAbs = options.adminPagesDir ? resolve(process.cwd(), options.adminPagesDir) : null;
|
|
3439
|
+
let config;
|
|
3440
|
+
let outDirAbs = "";
|
|
3441
|
+
let entries = [];
|
|
3442
|
+
let configuredEntries = {};
|
|
3443
|
+
let entriesByFile = /* @__PURE__ */ new Map();
|
|
3444
|
+
let writtenSidecars = /* @__PURE__ */ new Set();
|
|
3445
|
+
let writtenBlockFiles = /* @__PURE__ */ new Set();
|
|
3446
|
+
const collectEntries = () => discoverDevEntries({
|
|
3447
|
+
blocksDirAbs,
|
|
3448
|
+
blockStylesDirAbs,
|
|
3449
|
+
adminPagesDirAbs,
|
|
3450
|
+
skip,
|
|
3451
|
+
configuredEntries,
|
|
3452
|
+
buildType
|
|
3453
|
+
});
|
|
3454
|
+
const syncModuleEntryMatchers = () => {
|
|
3455
|
+
if (!moduleEntryMatchers) return;
|
|
3456
|
+
for (const entry of entries) {
|
|
3457
|
+
if (entry.mode !== "module" || entry.kind !== "js") continue;
|
|
3458
|
+
const matcher = toPosix(entry.file);
|
|
3459
|
+
if (!moduleEntryMatchers.includes(matcher)) moduleEntryMatchers.push(matcher);
|
|
3460
|
+
}
|
|
3461
|
+
};
|
|
3462
|
+
return {
|
|
3463
|
+
name: "wp-dev-server",
|
|
3464
|
+
// Build is untouched: every write below exists only because there is no
|
|
3465
|
+
// bundle to emit into.
|
|
3466
|
+
apply: "serve",
|
|
3467
|
+
/**
|
|
3468
|
+
* WordPress ships the *production* JSX runtime and nothing else. Core's
|
|
3469
|
+
* `react-jsx-runtime` handle is built from `react/jsx-runtime`, so
|
|
3470
|
+
* `window.ReactJSXRuntime` carries `jsx`, `jsxs` and `Fragment` — there
|
|
3471
|
+
* is no `jsxDEV` on it, in `SCRIPT_DEBUG` or out of it.
|
|
3472
|
+
*
|
|
3473
|
+
* Vite's serve default is the opposite: JSX compiles against the dev
|
|
3474
|
+
* runtime, `react/jsx-dev-runtime`. `wpExternals` then does exactly what
|
|
3475
|
+
* it is supposed to and rewrites that import to the global WordPress
|
|
3476
|
+
* registers for it, so every block editor script with JSX in it comes
|
|
3477
|
+
* out as `const { jsxDEV: _jsxDEV } = (window.ReactJSXRuntime)` —
|
|
3478
|
+
* `undefined`, and a `_jsxDEV is not a function` the moment anything
|
|
3479
|
+
* renders. Builds never see it (`development` is off there), which makes
|
|
3480
|
+
* it a dev-only cliff that a passing build tells you nothing about.
|
|
3481
|
+
*
|
|
3482
|
+
* Filled in only where the user has no opinion, the same rule
|
|
3483
|
+
* `wpScriptIife`'s `define` injection and `wpModuleEntrySignatures`
|
|
3484
|
+
* follow. The cost is the `__source`/`__self` debug props; the benefit is
|
|
3485
|
+
* that the editor script runs at all.
|
|
3486
|
+
*/
|
|
3487
|
+
config(userConfig) {
|
|
3488
|
+
const oxc = userConfig.oxc;
|
|
3489
|
+
if (oxc === false) return null;
|
|
3490
|
+
const jsx = oxc?.jsx;
|
|
3491
|
+
if (jsx === "preserve") return null;
|
|
3492
|
+
if (jsx && typeof jsx === "object" && jsx.development !== void 0) return null;
|
|
3493
|
+
return { oxc: { jsx: { development: false } } };
|
|
3494
|
+
},
|
|
3495
|
+
configResolved(resolvedConfig) {
|
|
3496
|
+
config = resolvedConfig;
|
|
3497
|
+
outDirAbs = resolve(resolvedConfig.root, resolvedConfig.build.outDir);
|
|
3498
|
+
configuredEntries = readConfiguredEntries(resolvedConfig);
|
|
3499
|
+
entries = collectEntries();
|
|
3500
|
+
syncModuleEntryMatchers();
|
|
3501
|
+
},
|
|
3502
|
+
/**
|
|
3503
|
+
* Answer for the bare specifiers the escape above hands back to the
|
|
3504
|
+
* browser.
|
|
3505
|
+
*
|
|
3506
|
+
* `installBareSpecifierEscape` rewrites the served code *after*
|
|
3507
|
+
* import-analysis, which means Vite's module graph still holds the
|
|
3508
|
+
* `/@id/@wordpress/interactivity` form it produced — and Vite eagerly
|
|
3509
|
+
* pre-transforms every import it recorded. That request resolves to a
|
|
3510
|
+
* bare specifier nothing on disk backs, and the console gets a red
|
|
3511
|
+
* `Pre-transform error: Failed to load url @wordpress/interactivity` for
|
|
3512
|
+
* every Script Module entry, on a server that is working perfectly.
|
|
3513
|
+
*
|
|
3514
|
+
* An empty module makes the warm-up succeed and changes nothing else:
|
|
3515
|
+
* the URL is not in the code any browser receives, so it is never
|
|
3516
|
+
* fetched — WordPress's import map resolves the specifier instead.
|
|
3517
|
+
* Narrow by construction: only ids `resolveExternal()` recognizes (i.e.
|
|
3518
|
+
* an installed package whose own metadata says it is externalizable),
|
|
3519
|
+
* and never a path, so a genuinely missing module still fails loudly.
|
|
3520
|
+
*/
|
|
3521
|
+
load(id) {
|
|
3522
|
+
if (id.startsWith(".") || id.startsWith("/") || id.startsWith("\0")) return null;
|
|
3523
|
+
if (isAbsolute(id) || !resolveExternal(id, resolveExternalOptions)) return null;
|
|
3524
|
+
return "export {};\n";
|
|
3525
|
+
},
|
|
3526
|
+
async configureServer(server) {
|
|
3527
|
+
installBareSpecifierEscape(server, config, resolveExternalOptions);
|
|
3528
|
+
const refreshAll = async () => {
|
|
3529
|
+
const { index, written } = await writeAllSidecars({
|
|
3530
|
+
entries,
|
|
3531
|
+
outDirAbs,
|
|
3532
|
+
root: config.root,
|
|
3533
|
+
resolveExternalOptions,
|
|
3534
|
+
wpBuildAssetMatchers,
|
|
3535
|
+
maxScanDepth
|
|
3536
|
+
});
|
|
3537
|
+
entriesByFile = index;
|
|
3538
|
+
pruneStale(writtenSidecars, written);
|
|
3539
|
+
writtenSidecars = written;
|
|
3540
|
+
};
|
|
3541
|
+
const refreshFor = async (file) => {
|
|
3542
|
+
const affected = entriesByFile.get(toPosix(file));
|
|
3543
|
+
if (!affected || affected.size === 0) return;
|
|
3544
|
+
const subset = entries.filter((entry) => affected.has(entry.name));
|
|
3545
|
+
const { index: rescanned } = await writeAllSidecars({
|
|
3546
|
+
entries: subset,
|
|
3547
|
+
outDirAbs,
|
|
3548
|
+
root: config.root,
|
|
3549
|
+
resolveExternalOptions,
|
|
3550
|
+
wpBuildAssetMatchers,
|
|
3551
|
+
maxScanDepth
|
|
3552
|
+
});
|
|
3553
|
+
for (const [scannedFile, names] of rescanned) {
|
|
3554
|
+
const existing = entriesByFile.get(scannedFile);
|
|
3555
|
+
if (existing) for (const name of names) existing.add(name);
|
|
3556
|
+
else entriesByFile.set(scannedFile, new Set(names));
|
|
3557
|
+
}
|
|
3558
|
+
};
|
|
3559
|
+
const refreshBlocksTree = () => {
|
|
3560
|
+
const written = writeBlocksTree({ blocksDirAbs, outDirAbs, emitManifest, skip });
|
|
3561
|
+
pruneStale(writtenBlockFiles, written);
|
|
3562
|
+
writtenBlockFiles = written;
|
|
3563
|
+
};
|
|
3564
|
+
const addWatchDirs = () => {
|
|
3565
|
+
for (const dir of [blocksDirAbs, blockStylesDirAbs, adminPagesDirAbs]) {
|
|
3566
|
+
if (dir && existsSync(dir)) server.watcher.add(dir);
|
|
3567
|
+
}
|
|
3568
|
+
};
|
|
3569
|
+
const rediscover = () => {
|
|
3570
|
+
addWatchDirs();
|
|
3571
|
+
refreshBlocksTree();
|
|
3572
|
+
configuredEntries = readConfiguredEntries(config);
|
|
3573
|
+
entries = collectEntries();
|
|
3574
|
+
syncModuleEntryMatchers();
|
|
3575
|
+
return refreshAll();
|
|
3576
|
+
};
|
|
3577
|
+
refreshBlocksTree();
|
|
3578
|
+
writeFileTree(
|
|
3579
|
+
join(outDirAbs, DEV_SERVER_PHP_NAME),
|
|
3580
|
+
renderDevServerPhp({
|
|
3581
|
+
prefix: resolvePhpPrefix(options.phpPrefix, config.root),
|
|
3582
|
+
hotFile: HOT_FILE_NAME
|
|
3583
|
+
})
|
|
3584
|
+
);
|
|
3585
|
+
await refreshAll();
|
|
3586
|
+
addWatchDirs();
|
|
3587
|
+
watchSources({
|
|
3588
|
+
server,
|
|
3589
|
+
sourceDirs: [blocksDirAbs, blockStylesDirAbs, adminPagesDirAbs],
|
|
3590
|
+
blocksDirAbs,
|
|
3591
|
+
onRediscover: rediscover,
|
|
3592
|
+
onFileChange: (file) => refreshFor(file)
|
|
3593
|
+
});
|
|
3594
|
+
const hotFilePath = join(outDirAbs, HOT_FILE_NAME);
|
|
3595
|
+
const httpServer = server.httpServer;
|
|
3596
|
+
if (httpServer) {
|
|
3597
|
+
httpServer.once("listening", () => {
|
|
3598
|
+
const hotFile = buildHotFile(config, httpServer.address());
|
|
3599
|
+
writeFileTree(hotFilePath, `${JSON.stringify(hotFile, null, " ")}
|
|
3600
|
+
`);
|
|
3601
|
+
registerHotFileCleanup(hotFilePath);
|
|
3602
|
+
});
|
|
3603
|
+
}
|
|
3604
|
+
},
|
|
3605
|
+
/**
|
|
3606
|
+
* Vite closes the plugin container on `server.close()`, which is what
|
|
3607
|
+
* makes this fire for a programmatically-created server (tests, a
|
|
3608
|
+
* wrapper process). The `process` handlers registered above cover the
|
|
3609
|
+
* interactive case, where nothing calls `close()` at all.
|
|
3610
|
+
*/
|
|
3611
|
+
closeBundle() {
|
|
3612
|
+
removeHotFile(join(outDirAbs, HOT_FILE_NAME));
|
|
3613
|
+
}
|
|
3614
|
+
};
|
|
3615
|
+
}
|
|
3616
|
+
function wpDevServerPhp(options = {}) {
|
|
3617
|
+
let projectRoot = options.projectRoot ?? process.cwd();
|
|
3618
|
+
return {
|
|
3619
|
+
name: "wp-dev-server-php",
|
|
3620
|
+
apply: "build",
|
|
3621
|
+
configResolved(resolvedConfig) {
|
|
3622
|
+
projectRoot = options.projectRoot ?? resolvedConfig.root;
|
|
3623
|
+
},
|
|
3624
|
+
generateBundle() {
|
|
3625
|
+
this.emitFile({
|
|
3626
|
+
type: "asset",
|
|
3627
|
+
fileName: DEV_SERVER_PHP_NAME,
|
|
3628
|
+
source: renderDevServerPhp({
|
|
3629
|
+
prefix: resolvePhpPrefix(options.phpPrefix, projectRoot),
|
|
3630
|
+
hotFile: HOT_FILE_NAME
|
|
3631
|
+
})
|
|
3632
|
+
});
|
|
3633
|
+
}
|
|
3634
|
+
};
|
|
3635
|
+
}
|
|
3636
|
+
function resolvePhpPrefix(explicit, projectRoot) {
|
|
3637
|
+
const fromOption = sanitizePhpPrefix(explicit);
|
|
3638
|
+
if (fromOption) return fromOption;
|
|
3639
|
+
let packageJson = {};
|
|
3640
|
+
try {
|
|
3641
|
+
packageJson = JSON.parse(readFileSync(join(projectRoot, "package.json"), "utf8"));
|
|
3642
|
+
} catch {
|
|
3643
|
+
}
|
|
3644
|
+
return sanitizePhpPrefix(packageJson.wpPlugin?.name) ?? sanitizePhpPrefix(packageJson.name?.replace(/^@[^/]+\//, "")) ?? DEFAULT_PHP_PREFIX;
|
|
3645
|
+
}
|
|
3646
|
+
function sanitizePhpPrefix(value) {
|
|
3647
|
+
if (!value) return null;
|
|
3648
|
+
const cleaned = value.replace(/[^A-Za-z0-9_-]/g, "-").replace(/^-+|-+$/g, "");
|
|
3649
|
+
return cleaned !== "" && isValidPhpIdentifier(cleaned) ? cleaned : null;
|
|
3650
|
+
}
|
|
3651
|
+
function buildHotFile(config, address) {
|
|
3652
|
+
return {
|
|
3653
|
+
origin: resolveDevOrigin(config, address),
|
|
3654
|
+
base: config.base,
|
|
3655
|
+
plugins: REPORTED_PLUGINS.filter(
|
|
3656
|
+
(name) => config.plugins.some((plugin) => plugin.name === name)
|
|
3657
|
+
)
|
|
3658
|
+
};
|
|
3659
|
+
}
|
|
3660
|
+
var UNPUBLISHABLE_ADDRESSES = /* @__PURE__ */ new Set([
|
|
3661
|
+
"0.0.0.0",
|
|
3662
|
+
"::",
|
|
3663
|
+
"::0",
|
|
3664
|
+
"0000:0000:0000:0000:0000:0000:0000:0000",
|
|
3665
|
+
"127.0.0.1",
|
|
3666
|
+
"::1",
|
|
3667
|
+
"0000:0000:0000:0000:0000:0000:0000:0001"
|
|
3668
|
+
]);
|
|
3669
|
+
function resolveDevOrigin(config, address) {
|
|
3670
|
+
const explicitOrigin = config.server?.origin;
|
|
3671
|
+
if (typeof explicitOrigin === "string" && explicitOrigin.length > 0) {
|
|
3672
|
+
return explicitOrigin.replace(/\/+$/, "");
|
|
3673
|
+
}
|
|
3674
|
+
const hmr = typeof config.server?.hmr === "object" ? config.server.hmr : null;
|
|
3675
|
+
const hmrProtocol = hmr && "protocol" in hmr ? hmr.protocol : void 0;
|
|
3676
|
+
const protocol = hmrProtocol ? hmrProtocol === "wss" ? "https" : "http" : config.server?.https ? "https" : "http";
|
|
3677
|
+
const hmrHost = hmr && "host" in hmr && typeof hmr.host === "string" ? hmr.host : void 0;
|
|
3678
|
+
const configHost = typeof config.server?.host === "string" ? config.server.host : void 0;
|
|
3679
|
+
const boundHost = address && typeof address === "object" ? address.address : void 0;
|
|
3680
|
+
const host = hmrHost ?? configHost ?? (boundHost ? normalizeBoundHost(boundHost) : "localhost");
|
|
3681
|
+
const hmrClientPort = hmr && "clientPort" in hmr && typeof hmr.clientPort === "number" ? hmr.clientPort : void 0;
|
|
3682
|
+
const boundPort = address && typeof address === "object" ? address.port : void 0;
|
|
3683
|
+
const port = hmrClientPort ?? boundPort;
|
|
3684
|
+
return port === void 0 ? `${protocol}://${host}` : `${protocol}://${host}:${port}`;
|
|
3685
|
+
}
|
|
3686
|
+
function normalizeBoundHost(host) {
|
|
3687
|
+
if (UNPUBLISHABLE_ADDRESSES.has(host)) return "localhost";
|
|
3688
|
+
if (host.includes(":") && !host.startsWith("[")) return `[${host}]`;
|
|
3689
|
+
return host;
|
|
3690
|
+
}
|
|
3691
|
+
var pendingHotFiles = /* @__PURE__ */ new Set();
|
|
3692
|
+
var hotFileHandlersBound = false;
|
|
3693
|
+
function registerHotFileCleanup(hotFilePath) {
|
|
3694
|
+
pendingHotFiles.add(hotFilePath);
|
|
3695
|
+
if (hotFileHandlersBound) return;
|
|
3696
|
+
hotFileHandlersBound = true;
|
|
3697
|
+
const cleanAll = () => {
|
|
3698
|
+
for (const filePath of pendingHotFiles) removeHotFile(filePath);
|
|
3699
|
+
pendingHotFiles.clear();
|
|
3700
|
+
};
|
|
3701
|
+
process.on("exit", cleanAll);
|
|
3702
|
+
for (const signal of ["SIGINT", "SIGTERM", "SIGHUP"]) {
|
|
3703
|
+
process.on(signal, () => {
|
|
3704
|
+
cleanAll();
|
|
3705
|
+
process.exit();
|
|
3706
|
+
});
|
|
3707
|
+
}
|
|
3708
|
+
}
|
|
3709
|
+
function removeHotFile(hotFilePath) {
|
|
3710
|
+
pendingHotFiles.delete(hotFilePath);
|
|
3711
|
+
try {
|
|
3712
|
+
rmSync(hotFilePath, { force: true });
|
|
3713
|
+
} catch {
|
|
3714
|
+
}
|
|
3715
|
+
}
|
|
3716
|
+
var decoratedEnvironments = /* @__PURE__ */ new WeakSet();
|
|
3717
|
+
function installBareSpecifierEscape(server, config, resolveExternalOptions) {
|
|
3718
|
+
const base = config.base ?? "/";
|
|
3719
|
+
const wrappedPrefix = `${base.replace(/\/+$/, "")}/@id/`;
|
|
3720
|
+
const pattern = new RegExp(`(["'])${escapeRegExp2(wrappedPrefix)}([^"'\\s]+)\\1`, "g");
|
|
3721
|
+
const unwrap = (code) => code.replace(
|
|
3722
|
+
pattern,
|
|
3723
|
+
(match, quote, specifier) => resolveExternal(specifier, resolveExternalOptions) ? `${quote}${specifier}${quote}` : match
|
|
3724
|
+
);
|
|
3725
|
+
for (const environment of Object.values(server.environments)) {
|
|
3726
|
+
if (decoratedEnvironments.has(environment)) continue;
|
|
3727
|
+
decoratedEnvironments.add(environment);
|
|
3728
|
+
const original = environment.transformRequest.bind(environment);
|
|
3729
|
+
environment.transformRequest = async (url) => {
|
|
3730
|
+
const result = await original(url);
|
|
3731
|
+
if (!result || typeof result.code !== "string") return result;
|
|
3732
|
+
if (!result.code.includes(wrappedPrefix)) return result;
|
|
3733
|
+
const code = unwrap(result.code);
|
|
3734
|
+
return code === result.code ? result : { ...result, code };
|
|
3735
|
+
};
|
|
3736
|
+
}
|
|
3737
|
+
}
|
|
3738
|
+
function escapeRegExp2(value) {
|
|
3739
|
+
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
3740
|
+
}
|
|
3741
|
+
function discoverDevEntries(options) {
|
|
3742
|
+
const { blocksDirAbs, blockStylesDirAbs, adminPagesDirAbs, skip } = options;
|
|
3743
|
+
const byName = /* @__PURE__ */ new Map();
|
|
3744
|
+
const add = (entry) => {
|
|
3745
|
+
if (!byName.has(entry.name)) byName.set(entry.name, entry);
|
|
3746
|
+
};
|
|
3747
|
+
if (blocksDirAbs && existsSync(blocksDirAbs)) {
|
|
3748
|
+
for (const [name, file] of Object.entries(discoverEntries(blocksDirAbs, "module", skip))) {
|
|
3749
|
+
add({ name, file, mode: "module", kind: entryKind(file) });
|
|
3750
|
+
}
|
|
3751
|
+
for (const [name, file] of Object.entries(discoverEntries(blocksDirAbs, "script", skip))) {
|
|
3752
|
+
add({ name, file, mode: "script", kind: entryKind(file) });
|
|
3753
|
+
}
|
|
3754
|
+
}
|
|
3755
|
+
if (blockStylesDirAbs && existsSync(blockStylesDirAbs)) {
|
|
3756
|
+
const stylesheets = fg.sync(`${toPosix(blockStylesDirAbs)}/**/*.{css,scss,sass}`, {
|
|
3757
|
+
absolute: true
|
|
3758
|
+
});
|
|
3759
|
+
for (const file of stylesheets) {
|
|
3760
|
+
const blockName = relative(blockStylesDirAbs, file).replace(extname(file), "").replace(/\\/g, "/");
|
|
3761
|
+
add({ name: `autoenqueue/${blockName}`, file, mode: "script", kind: "css" });
|
|
3762
|
+
}
|
|
3763
|
+
}
|
|
3764
|
+
if (adminPagesDirAbs && existsSync(adminPagesDirAbs)) {
|
|
3765
|
+
for (const page of discoverPages(adminPagesDirAbs)) {
|
|
3766
|
+
add({
|
|
3767
|
+
name: `modules/${page.dirName}/content`,
|
|
3768
|
+
file: page.content,
|
|
3769
|
+
mode: "module",
|
|
3770
|
+
kind: "js"
|
|
3771
|
+
});
|
|
3772
|
+
if (page.route) {
|
|
3773
|
+
add({
|
|
3774
|
+
name: `modules/${page.dirName}/route`,
|
|
3775
|
+
file: page.route,
|
|
3776
|
+
mode: "module",
|
|
3777
|
+
kind: "js"
|
|
3778
|
+
});
|
|
3779
|
+
}
|
|
3780
|
+
for (const subRoute of page.subRoutes) {
|
|
3781
|
+
const base = `modules/${page.dirName}/routes/${subRoute.name}`;
|
|
3782
|
+
if (subRoute.content) {
|
|
3783
|
+
add({
|
|
3784
|
+
name: `${base}/content`,
|
|
3785
|
+
file: subRoute.content,
|
|
3786
|
+
mode: "module",
|
|
3787
|
+
kind: "js"
|
|
3788
|
+
});
|
|
3789
|
+
}
|
|
3790
|
+
if (subRoute.route) {
|
|
3791
|
+
add({
|
|
3792
|
+
name: `${base}/route`,
|
|
3793
|
+
file: subRoute.route,
|
|
3794
|
+
mode: "module",
|
|
3795
|
+
kind: "js"
|
|
3796
|
+
});
|
|
3797
|
+
}
|
|
3798
|
+
}
|
|
3799
|
+
}
|
|
3800
|
+
}
|
|
3801
|
+
for (const [name, file] of Object.entries(options.configuredEntries ?? {})) {
|
|
3802
|
+
add({ name, file, mode: options.buildType ?? "script", kind: entryKind(file) });
|
|
3803
|
+
}
|
|
3804
|
+
return [...byName.values()].sort((a, b) => a.name < b.name ? -1 : a.name > b.name ? 1 : 0);
|
|
3805
|
+
}
|
|
3806
|
+
function readConfiguredEntries(config) {
|
|
3807
|
+
const input = config.build?.rollupOptions?.input;
|
|
3808
|
+
if (!input || typeof input !== "object" || Array.isArray(input)) return {};
|
|
3809
|
+
const entries = {};
|
|
3810
|
+
for (const [name, source] of Object.entries(input)) {
|
|
3811
|
+
if (typeof source !== "string") continue;
|
|
3812
|
+
const file = resolve(config.root, source);
|
|
3813
|
+
if (existsSync(file)) entries[name] = file;
|
|
3814
|
+
}
|
|
3815
|
+
return entries;
|
|
3816
|
+
}
|
|
3817
|
+
function entryKind(file) {
|
|
3818
|
+
return STYLESHEET_EXTENSION2.test(file) ? "css" : "js";
|
|
3819
|
+
}
|
|
3820
|
+
async function scanEntryDependencies(entryFile, options) {
|
|
3821
|
+
const maxDepth = options.maxDepth ?? DEFAULT_MAX_SCAN_DEPTH;
|
|
3822
|
+
const moduleIds = /* @__PURE__ */ new Set();
|
|
3823
|
+
const dynamicModuleIds = /* @__PURE__ */ new Set();
|
|
3824
|
+
const handles = /* @__PURE__ */ new Set();
|
|
3825
|
+
const visited = /* @__PURE__ */ new Set();
|
|
3826
|
+
const files = [];
|
|
3827
|
+
let hasJsxSource = false;
|
|
3828
|
+
await init;
|
|
3829
|
+
const queue = [{ file: entryFile, depth: 0 }];
|
|
3830
|
+
while (queue.length > 0) {
|
|
3831
|
+
const { file, depth } = queue.shift();
|
|
3832
|
+
const key = toPosix(file);
|
|
3833
|
+
if (visited.has(key)) continue;
|
|
3834
|
+
visited.add(key);
|
|
3835
|
+
files.push(key);
|
|
3836
|
+
if (JSX_SOURCE_EXTENSION.test(key)) hasJsxSource = true;
|
|
3837
|
+
if (depth >= maxDepth) continue;
|
|
3838
|
+
if (STYLESHEET_EXTENSION2.test(file)) continue;
|
|
3839
|
+
let code;
|
|
3840
|
+
try {
|
|
3841
|
+
code = readFileSync(file, "utf8");
|
|
3842
|
+
} catch {
|
|
3843
|
+
continue;
|
|
3844
|
+
}
|
|
3845
|
+
for (const { specifier, isDynamic } of lexImports(code, file)) {
|
|
3846
|
+
if (specifier.startsWith(".") || isAbsolute(specifier)) {
|
|
3847
|
+
const resolved = resolveLocalImport(specifier, file);
|
|
3848
|
+
if (resolved) queue.push({ file: resolved, depth: depth + 1 });
|
|
3849
|
+
continue;
|
|
3850
|
+
}
|
|
3851
|
+
const external = resolveExternal(specifier, options.resolveExternalOptions);
|
|
3852
|
+
if (!external) continue;
|
|
3853
|
+
if (options.mode === "module" && external.moduleEligible) {
|
|
3854
|
+
if (isDynamic && specifier !== "@wordpress/interactivity") {
|
|
3855
|
+
dynamicModuleIds.add(external.specifier);
|
|
3856
|
+
} else {
|
|
3857
|
+
moduleIds.add(external.specifier);
|
|
3858
|
+
}
|
|
3859
|
+
continue;
|
|
3860
|
+
}
|
|
3861
|
+
if (external.handle) handles.add(external.handle);
|
|
3862
|
+
}
|
|
3863
|
+
}
|
|
3864
|
+
if (hasJsxSource) {
|
|
3865
|
+
const jsxRuntime = resolveExternal(JSX_RUNTIME_SPECIFIER, options.resolveExternalOptions);
|
|
3866
|
+
if (jsxRuntime?.handle) handles.add(jsxRuntime.handle);
|
|
3867
|
+
}
|
|
3868
|
+
for (const id of moduleIds) dynamicModuleIds.delete(id);
|
|
3869
|
+
return {
|
|
3870
|
+
moduleIds: [...moduleIds].sort(),
|
|
3871
|
+
dynamicModuleIds: [...dynamicModuleIds].sort(),
|
|
3872
|
+
handles: [...handles].sort(),
|
|
3873
|
+
files
|
|
3874
|
+
};
|
|
3875
|
+
}
|
|
3876
|
+
function lexImports(code, file) {
|
|
3877
|
+
try {
|
|
3878
|
+
const [imports] = parse(code, file);
|
|
3879
|
+
const found = [];
|
|
3880
|
+
for (const importRecord of imports) {
|
|
3881
|
+
if (importRecord.n === void 0) continue;
|
|
3882
|
+
found.push({ specifier: importRecord.n, isDynamic: importRecord.d > -1 });
|
|
3883
|
+
}
|
|
3884
|
+
return found;
|
|
3885
|
+
} catch {
|
|
3886
|
+
return regexImports(code);
|
|
3887
|
+
}
|
|
3888
|
+
}
|
|
3889
|
+
function stripComments(code) {
|
|
3890
|
+
return code.replace(/\/\*[\s\S]*?\*\//g, "").replace(/(^|[^:"'`\\])\/\/[^\n]*/g, "$1");
|
|
3891
|
+
}
|
|
3892
|
+
var DYNAMIC_IMPORT_RE = /\bimport\s*\(\s*(['"])([^'"]+)\1\s*\)/g;
|
|
3893
|
+
var STATIC_FROM_RE = /(?:^|[\s;}(])(?:import|export)\b[^;]*?\bfrom\s*(['"])([^'"]+)\1/g;
|
|
3894
|
+
var BARE_IMPORT_RE = /(?:^|[\s;}])import\s*(['"])([^'"]+)\1/g;
|
|
3895
|
+
function regexImports(code) {
|
|
3896
|
+
const source = stripComments(code);
|
|
3897
|
+
const found = /* @__PURE__ */ new Map();
|
|
3898
|
+
const record = (specifier, isDynamic) => {
|
|
3899
|
+
const existing = found.get(specifier);
|
|
3900
|
+
if (existing && !existing.isDynamic) return;
|
|
3901
|
+
found.set(specifier, { specifier, isDynamic });
|
|
3902
|
+
};
|
|
3903
|
+
for (const match of source.matchAll(DYNAMIC_IMPORT_RE)) record(match[2], true);
|
|
3904
|
+
for (const match of source.matchAll(STATIC_FROM_RE)) record(match[2], false);
|
|
3905
|
+
for (const match of source.matchAll(BARE_IMPORT_RE)) record(match[2], false);
|
|
3906
|
+
return [...found.values()];
|
|
3907
|
+
}
|
|
3908
|
+
function resolveLocalImport(specifier, importerFile) {
|
|
3909
|
+
const withoutQuery = specifier.split("?")[0] ?? specifier;
|
|
3910
|
+
const target = isAbsolute(withoutQuery) ? withoutQuery : join(dirname(importerFile), withoutQuery);
|
|
3911
|
+
if (existsSync(target) && !isDirectory(target)) return target;
|
|
3912
|
+
const candidates = [];
|
|
3913
|
+
const withoutJsExtension = target.replace(/\.[mc]?js$/, "");
|
|
3914
|
+
for (const extension of SCAN_EXTENSIONS) {
|
|
3915
|
+
candidates.push(`${target}${extension}`);
|
|
3916
|
+
if (withoutJsExtension !== target) candidates.push(`${withoutJsExtension}${extension}`);
|
|
3917
|
+
}
|
|
3918
|
+
for (const extension of SCAN_EXTENSIONS) candidates.push(join(target, `index${extension}`));
|
|
3919
|
+
return candidates.find((candidate) => existsSync(candidate)) ?? null;
|
|
3920
|
+
}
|
|
3921
|
+
function isDirectory(filePath) {
|
|
3922
|
+
try {
|
|
3923
|
+
return existsSync(filePath) && extname(filePath) === "";
|
|
3924
|
+
} catch {
|
|
3925
|
+
return false;
|
|
3926
|
+
}
|
|
3927
|
+
}
|
|
3928
|
+
function renderDevAssetPhp(input) {
|
|
3929
|
+
const { scan, mode, kind, source } = input;
|
|
3930
|
+
const phpList = (items) => items.length > 0 ? ` ${items.join(", ")} ` : "";
|
|
3931
|
+
const quoted = (items) => items.map((item) => `'${phpSingleQuoteEscape3(item)}'`);
|
|
3932
|
+
const fields = [];
|
|
3933
|
+
if (kind === "css") {
|
|
3934
|
+
fields.push(`'dependencies' => array()`);
|
|
3935
|
+
} else if (input.wpBuildShape) {
|
|
3936
|
+
fields.push(`'dependencies' => array(${phpList(quoted(scan.handles))})`);
|
|
3937
|
+
const moduleDependencies = [
|
|
3938
|
+
...scan.moduleIds.map(
|
|
3939
|
+
(id) => `array( 'id' => '${phpSingleQuoteEscape3(id)}', 'import' => 'static' )`
|
|
3940
|
+
),
|
|
3941
|
+
...scan.dynamicModuleIds.map(
|
|
3942
|
+
(id) => `array( 'id' => '${phpSingleQuoteEscape3(id)}', 'import' => 'dynamic' )`
|
|
3943
|
+
)
|
|
3944
|
+
];
|
|
3945
|
+
if (moduleDependencies.length > 0) {
|
|
3946
|
+
fields.push(`'module_dependencies' => array(${phpList(moduleDependencies)})`);
|
|
3947
|
+
}
|
|
3948
|
+
} else if (mode === "module") {
|
|
3949
|
+
const moduleDependencies = [
|
|
3950
|
+
...quoted(scan.moduleIds),
|
|
3951
|
+
...scan.dynamicModuleIds.map(
|
|
3952
|
+
(id) => `array( 'id' => '${phpSingleQuoteEscape3(id)}', 'import' => 'dynamic' )`
|
|
3953
|
+
)
|
|
3954
|
+
];
|
|
3955
|
+
fields.push(`'dependencies' => array(${phpList(moduleDependencies)})`);
|
|
3956
|
+
if (scan.handles.length > 0) {
|
|
3957
|
+
fields.push(`'script_dependencies' => array(${phpList(quoted(scan.handles))})`);
|
|
3958
|
+
}
|
|
3959
|
+
} else {
|
|
3960
|
+
fields.push(`'dependencies' => array(${phpList(quoted(scan.handles))})`);
|
|
3961
|
+
}
|
|
3962
|
+
fields.push(`'version' => null`);
|
|
3963
|
+
if (kind === "js" && mode === "module") fields.push(`'type' => 'module'`);
|
|
3964
|
+
if (source) fields.push(`'source' => '${phpSingleQuoteEscape3(source)}'`);
|
|
3965
|
+
fields.push(`'dev' => true`);
|
|
3966
|
+
return `<?php return array( ${fields.join(", ")} );
|
|
3967
|
+
`;
|
|
3968
|
+
}
|
|
3969
|
+
async function writeAllSidecars(options) {
|
|
3970
|
+
const index = /* @__PURE__ */ new Map();
|
|
3971
|
+
const written = /* @__PURE__ */ new Set();
|
|
3972
|
+
for (const entry of options.entries) {
|
|
3973
|
+
const scan = entry.kind === "css" ? { moduleIds: [], dynamicModuleIds: [], handles: [], files: [toPosix(entry.file)] } : await scanEntryDependencies(entry.file, {
|
|
3974
|
+
mode: entry.mode,
|
|
3975
|
+
resolveExternalOptions: options.resolveExternalOptions,
|
|
3976
|
+
maxDepth: options.maxScanDepth
|
|
3977
|
+
});
|
|
3978
|
+
const php = renderDevAssetPhp({
|
|
3979
|
+
scan,
|
|
3980
|
+
mode: entry.mode,
|
|
3981
|
+
kind: entry.kind,
|
|
3982
|
+
source: projectRelativeSource(entry.file, options.root),
|
|
3983
|
+
wpBuildShape: options.wpBuildAssetMatchers.some(
|
|
3984
|
+
(matcher) => toPosix(entry.file).includes(matcher)
|
|
3985
|
+
)
|
|
3986
|
+
});
|
|
3987
|
+
const sidecarPath = join(options.outDirAbs, `${entry.name}.asset.php`);
|
|
3988
|
+
writeFileTree(sidecarPath, php);
|
|
3989
|
+
written.add(sidecarPath);
|
|
3990
|
+
for (const file of scan.files) {
|
|
3991
|
+
let names = index.get(file);
|
|
3992
|
+
if (!names) index.set(file, names = /* @__PURE__ */ new Set());
|
|
3993
|
+
names.add(entry.name);
|
|
3994
|
+
}
|
|
3995
|
+
}
|
|
3996
|
+
return { index, written };
|
|
3997
|
+
}
|
|
3998
|
+
function pruneStale(previous, current) {
|
|
3999
|
+
for (const filePath of previous) {
|
|
4000
|
+
if (current.has(filePath)) continue;
|
|
4001
|
+
try {
|
|
4002
|
+
rmSync(filePath, { force: true });
|
|
4003
|
+
} catch {
|
|
4004
|
+
}
|
|
4005
|
+
}
|
|
4006
|
+
}
|
|
4007
|
+
function projectRelativeSource(file, root) {
|
|
4008
|
+
const relativePath = relative(root, file).replace(/\\/g, "/");
|
|
4009
|
+
if (relativePath === "" || relativePath === ".." || relativePath.startsWith("../")) return null;
|
|
4010
|
+
if (isAbsolute(relativePath)) return null;
|
|
4011
|
+
return relativePath;
|
|
4012
|
+
}
|
|
4013
|
+
function phpSingleQuoteEscape3(value) {
|
|
4014
|
+
return value.replace(/\\/g, "\\\\").replace(/'/g, "\\'");
|
|
4015
|
+
}
|
|
4016
|
+
function writeBlocksTree(options) {
|
|
4017
|
+
const { blocksDirAbs, outDirAbs, emitManifest, skip } = options;
|
|
4018
|
+
const written = /* @__PURE__ */ new Set();
|
|
4019
|
+
if (!blocksDirAbs || !existsSync(blocksDirAbs)) return written;
|
|
4020
|
+
const files = fg.sync(
|
|
4021
|
+
[`${toPosix(blocksDirAbs)}/**/block.json`, `${toPosix(blocksDirAbs)}/**/*.php`],
|
|
4022
|
+
{ absolute: true }
|
|
4023
|
+
);
|
|
4024
|
+
for (const file of files) {
|
|
4025
|
+
const relativePath = relative(blocksDirAbs, file).replace(/\\/g, "/");
|
|
4026
|
+
const blockDirName = relativePath.replace(/\/?[^/]+$/, "");
|
|
4027
|
+
if (blockDirName && skip.has(blockDirName)) continue;
|
|
4028
|
+
const source = relativePath.endsWith("block.json") ? transformBlockJson(readFileSync(file, "utf8"), file) : readFileSync(file);
|
|
4029
|
+
const target = join(outDirAbs, "blocks", relativePath);
|
|
4030
|
+
writeFileTree(target, source);
|
|
4031
|
+
written.add(target);
|
|
4032
|
+
}
|
|
4033
|
+
if (!emitManifest) return written;
|
|
4034
|
+
const manifest = buildBlocksManifest(blocksDirAbs, skip);
|
|
4035
|
+
if (manifest) {
|
|
4036
|
+
const target = join(outDirAbs, "blocks-manifest.php");
|
|
4037
|
+
writeFileTree(target, manifest);
|
|
4038
|
+
written.add(target);
|
|
4039
|
+
}
|
|
4040
|
+
return written;
|
|
4041
|
+
}
|
|
4042
|
+
function watchSources(options) {
|
|
4043
|
+
const { server, blocksDirAbs } = options;
|
|
4044
|
+
const sourceDirs = options.sourceDirs.filter((dir) => !!dir).map((dir) => `${toPosix(dir)}/`);
|
|
4045
|
+
const isUnderSourceDir = (posixFile) => sourceDirs.some((dir) => posixFile.startsWith(dir));
|
|
4046
|
+
const isBlocksMetadata = (posixFile) => {
|
|
4047
|
+
if (!blocksDirAbs) return false;
|
|
4048
|
+
if (!posixFile.startsWith(`${toPosix(blocksDirAbs)}/`)) return false;
|
|
4049
|
+
return posixFile.endsWith("/block.json") || posixFile.endsWith(".php");
|
|
4050
|
+
};
|
|
4051
|
+
const run = (work, file) => {
|
|
4052
|
+
void Promise.resolve(work).catch((error) => {
|
|
4053
|
+
server.config.logger.error(
|
|
4054
|
+
`[wp-dev-server] failed to refresh after ${file}: ${error instanceof Error ? error.message : String(error)}`
|
|
4055
|
+
);
|
|
4056
|
+
});
|
|
4057
|
+
};
|
|
4058
|
+
let pending = null;
|
|
4059
|
+
const scheduleRediscover = (file) => {
|
|
4060
|
+
if (pending) clearTimeout(pending);
|
|
4061
|
+
pending = setTimeout(() => {
|
|
4062
|
+
pending = null;
|
|
4063
|
+
run(options.onRediscover(), file);
|
|
4064
|
+
}, REDISCOVER_DEBOUNCE_MS);
|
|
4065
|
+
pending.unref?.();
|
|
4066
|
+
};
|
|
4067
|
+
const handle = (event, file) => {
|
|
4068
|
+
const posixFile = toPosix(file);
|
|
4069
|
+
if (isBlocksMetadata(posixFile) || event !== "change" && isUnderSourceDir(posixFile)) {
|
|
4070
|
+
scheduleRediscover(file);
|
|
4071
|
+
return;
|
|
4072
|
+
}
|
|
4073
|
+
run(options.onFileChange(file), file);
|
|
4074
|
+
};
|
|
4075
|
+
for (const event of ["add", "change", "unlink"]) {
|
|
4076
|
+
server.watcher.on(event, (file) => handle(event, file));
|
|
4077
|
+
}
|
|
4078
|
+
}
|
|
4079
|
+
function writeFileTree(filePath, contents) {
|
|
4080
|
+
mkdirSync(dirname(filePath), { recursive: true });
|
|
4081
|
+
writeFileSync(filePath, contents);
|
|
4082
|
+
}
|
|
4083
|
+
function toPosix(filePath) {
|
|
4084
|
+
return filePath.replace(/\\/g, "/");
|
|
4085
|
+
}
|
|
2696
4086
|
|
|
2697
4087
|
// src/wp.ts
|
|
2698
4088
|
function wpModuleEntrySignatures() {
|
|
@@ -2700,17 +4090,27 @@ function wpModuleEntrySignatures() {
|
|
|
2700
4090
|
name: "wp-module-entry-signatures",
|
|
2701
4091
|
config(userConfig) {
|
|
2702
4092
|
if (userConfig.build?.rollupOptions?.preserveEntrySignatures !== void 0) return null;
|
|
2703
|
-
return {
|
|
4093
|
+
return {
|
|
4094
|
+
build: { rollupOptions: { preserveEntrySignatures: "exports-only" } }
|
|
4095
|
+
};
|
|
2704
4096
|
}
|
|
2705
4097
|
};
|
|
2706
4098
|
}
|
|
2707
4099
|
function wp(options = {}) {
|
|
2708
4100
|
const buildType = options.buildType ?? "script";
|
|
2709
4101
|
const plugins = [];
|
|
4102
|
+
const globalsSink = /* @__PURE__ */ new Map();
|
|
4103
|
+
let activeBlocksDir;
|
|
4104
|
+
let activeBlocksSkip;
|
|
4105
|
+
let activeEmitManifest;
|
|
4106
|
+
let activeBlockStylesDir;
|
|
2710
4107
|
if (options.blocks !== false) {
|
|
2711
4108
|
const blocksOptions = typeof options.blocks === "object" ? options.blocks : void 0;
|
|
2712
4109
|
const blocksDir = blocksOptions?.blocksDir ?? options.blocksDir;
|
|
2713
4110
|
if (blocksDir) {
|
|
4111
|
+
activeBlocksDir = blocksDir;
|
|
4112
|
+
activeBlocksSkip = blocksOptions?.skip;
|
|
4113
|
+
activeEmitManifest = blocksOptions?.emitManifest;
|
|
2714
4114
|
plugins.push(
|
|
2715
4115
|
wpBlocks({
|
|
2716
4116
|
blocksDir,
|
|
@@ -2724,6 +4124,7 @@ function wp(options = {}) {
|
|
|
2724
4124
|
const blockStylesOptions = typeof options.blockStyles === "object" ? options.blockStyles : void 0;
|
|
2725
4125
|
const blocksStylesDir = blockStylesOptions?.blocksStylesDir ?? options.blocksStylesDir;
|
|
2726
4126
|
if (blocksStylesDir) {
|
|
4127
|
+
activeBlockStylesDir = blocksStylesDir;
|
|
2727
4128
|
plugins.push(
|
|
2728
4129
|
wpBlockStyles({
|
|
2729
4130
|
blocksStylesDir,
|
|
@@ -2760,26 +4161,66 @@ function wp(options = {}) {
|
|
|
2760
4161
|
);
|
|
2761
4162
|
}
|
|
2762
4163
|
}
|
|
4164
|
+
const externalsOptions = typeof options.externals === "object" ? options.externals : void 0;
|
|
4165
|
+
const wpBuildAssetMatchers = [...externalsOptions?.wpBuildAssetMatchers ?? []];
|
|
4166
|
+
if (activeAdminPagesDir) {
|
|
4167
|
+
const matcher = resolve(process.cwd(), activeAdminPagesDir).replace(/\\/g, "/");
|
|
4168
|
+
if (!wpBuildAssetMatchers.includes(matcher)) wpBuildAssetMatchers.push(matcher);
|
|
4169
|
+
}
|
|
4170
|
+
const moduleEntryMatchers = [...externalsOptions?.moduleEntryMatchers ?? []];
|
|
2763
4171
|
if (options.externals !== false) {
|
|
2764
|
-
const externalsOptions = typeof options.externals === "object" ? options.externals : void 0;
|
|
2765
|
-
const wpBuildAssetMatchers = [...externalsOptions?.wpBuildAssetMatchers ?? []];
|
|
2766
|
-
if (activeAdminPagesDir) {
|
|
2767
|
-
const matcher = resolve(process.cwd(), activeAdminPagesDir).replace(/\\/g, "/");
|
|
2768
|
-
if (!wpBuildAssetMatchers.includes(matcher)) wpBuildAssetMatchers.push(matcher);
|
|
2769
|
-
}
|
|
2770
4172
|
plugins.push(
|
|
2771
4173
|
...wpExternals({
|
|
2772
4174
|
buildType,
|
|
2773
4175
|
...externalsOptions,
|
|
4176
|
+
moduleEntryMatchers,
|
|
4177
|
+
// After the spread, deliberately: `globalsSink` is an internal
|
|
4178
|
+
// out-param, not user config. A consumer passing their own Map
|
|
4179
|
+
// through `externals: { globalsSink }` would otherwise sever the
|
|
4180
|
+
// wiring — wpExternals would fill their map, wpScriptIife would
|
|
4181
|
+
// read an empty one, and every shimmed `require()` would throw
|
|
4182
|
+
// at runtime with nothing said at build time.
|
|
4183
|
+
globalsSink,
|
|
2774
4184
|
...wpBuildAssetMatchers.length > 0 ? { wpBuildAssetMatchers } : {}
|
|
2775
4185
|
})
|
|
2776
4186
|
);
|
|
2777
4187
|
}
|
|
4188
|
+
if (options.devServer !== false) {
|
|
4189
|
+
const devServerOptions = typeof options.devServer === "object" ? options.devServer : void 0;
|
|
4190
|
+
plugins.push(
|
|
4191
|
+
wpDevServer({
|
|
4192
|
+
// The mode the *declared* entries (`build.rollupOptions.input`)
|
|
4193
|
+
// are served in. Block and admin-page entries carry their own
|
|
4194
|
+
// verdict from discovery, so this only decides the project's own.
|
|
4195
|
+
buildType,
|
|
4196
|
+
...activeBlocksDir ? { blocksDir: activeBlocksDir } : {},
|
|
4197
|
+
...activeBlockStylesDir ? { blocksStylesDir: activeBlockStylesDir } : {},
|
|
4198
|
+
...activeAdminPagesDir ? { adminPagesDir: activeAdminPagesDir } : {},
|
|
4199
|
+
...activeBlocksSkip ? { skip: activeBlocksSkip } : {},
|
|
4200
|
+
...activeEmitManifest !== void 0 ? { emitManifest: activeEmitManifest } : {},
|
|
4201
|
+
// The dev dependency scan has to reach the same externalization
|
|
4202
|
+
// verdicts `wpExternals` does, so it gets the same inputs.
|
|
4203
|
+
...externalsOptions?.projectRoot ? { projectRoot: externalsOptions.projectRoot } : {},
|
|
4204
|
+
...externalsOptions?.externalNamespaces ? { externalNamespaces: externalsOptions.externalNamespaces } : {},
|
|
4205
|
+
...externalsOptions?.additionalExternals ? { additionalExternals: externalsOptions.additionalExternals } : {},
|
|
4206
|
+
...externalsOptions?.scriptModuleNamespaces ? { scriptModuleNamespaces: externalsOptions.scriptModuleNamespaces } : {},
|
|
4207
|
+
...externalsOptions?.bundle ? { bundledPackages: [...DEFAULT_BUNDLED_PACKAGES, ...externalsOptions.bundle] } : {},
|
|
4208
|
+
moduleEntryMatchers,
|
|
4209
|
+
...wpBuildAssetMatchers.length > 0 ? { wpBuildAssetMatchers } : {},
|
|
4210
|
+
...devServerOptions
|
|
4211
|
+
})
|
|
4212
|
+
);
|
|
4213
|
+
plugins.push(
|
|
4214
|
+
wpDevServerPhp(
|
|
4215
|
+
devServerOptions?.phpPrefix ? { phpPrefix: devServerOptions.phpPrefix } : {}
|
|
4216
|
+
)
|
|
4217
|
+
);
|
|
4218
|
+
}
|
|
2778
4219
|
if (buildType === "script" && options.scriptDedupe !== false) {
|
|
2779
4220
|
plugins.push(wpScriptDedupe());
|
|
2780
4221
|
}
|
|
2781
4222
|
if (buildType === "script" && options.iife !== false) {
|
|
2782
|
-
plugins.push(wpScriptIife());
|
|
4223
|
+
plugins.push(wpScriptIife({ globals: globalsSink }));
|
|
2783
4224
|
}
|
|
2784
4225
|
if (options.cleanCssChunks !== false) {
|
|
2785
4226
|
plugins.push(wpCleanCssChunks());
|
|
@@ -2793,6 +4234,6 @@ function wp(options = {}) {
|
|
|
2793
4234
|
return plugins;
|
|
2794
4235
|
}
|
|
2795
4236
|
|
|
2796
|
-
export { DEFAULT_BUNDLED_PACKAGES, wp, wpAdminPages, wpBlockStyles, wpBlocks, wpCleanCssChunks, wpCopyAssets, wpCssAssetInfo, wpExternals, wpScriptDedupe, wpScriptIife };
|
|
4237
|
+
export { DEFAULT_BUNDLED_PACKAGES, DEV_SERVER_PHP_NAME, HOT_FILE_NAME, wp, wpAdminPages, wpBlockStyles, wpBlocks, wpCleanCssChunks, wpCopyAssets, wpCssAssetInfo, wpDevServer, wpDevServerPhp, wpExternals, wpScriptDedupe, wpScriptIife };
|
|
2797
4238
|
//# sourceMappingURL=index.js.map
|
|
2798
4239
|
//# sourceMappingURL=index.js.map
|