@elementor/generate-wordpress-asset-file-webpack-plugin 0.2.1 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +11 -0
- package/dist/index.d.mts +10 -36
- package/dist/index.d.ts +10 -36
- package/dist/index.js +66 -144
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +65 -145
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -2
- package/src/__tests__/__snapshots__/index.test.ts.snap +12 -44
- package/src/__tests__/index.test.ts +12 -17
- package/src/index.ts +1 -263
- package/src/plugin.ts +86 -0
- package/src/types.ts +4 -0
- package/src/utils.ts +48 -0
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,17 @@
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
|
5
5
|
|
|
6
|
+
# [0.3.0](https://github.com/elementor/elementor-packages/compare/@elementor/generate-wordpress-asset-file-webpack-plugin@0.2.1...@elementor/generate-wordpress-asset-file-webpack-plugin@0.3.0) (2023-07-11)
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
### Features
|
|
10
|
+
|
|
11
|
+
* **webpack-plugins:** simplify logic ([#78](https://github.com/elementor/elementor-packages/issues/78)) ([e4cadc0](https://github.com/elementor/elementor-packages/commit/e4cadc06be61450437274610e65b9d92eb245844))
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
|
|
6
17
|
## 0.2.1 (2023-07-02)
|
|
7
18
|
|
|
8
19
|
**Note:** Version bump only for package @elementor/generate-wordpress-asset-file-webpack-plugin
|
package/dist/index.d.mts
CHANGED
|
@@ -1,47 +1,21 @@
|
|
|
1
1
|
import { Compiler, Compilation, Chunk } from 'webpack';
|
|
2
2
|
|
|
3
|
-
type
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
}
|
|
3
|
+
type RequestToHandleMap = Array<{
|
|
4
|
+
request: string | RegExp;
|
|
5
|
+
handle: string;
|
|
6
|
+
}>;
|
|
7
|
+
|
|
7
8
|
type Options = {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
apps?: string[];
|
|
11
|
-
extensions?: string[];
|
|
12
|
-
i18n?: {
|
|
13
|
-
domain: string;
|
|
14
|
-
replaceRequestedFile?: boolean;
|
|
15
|
-
};
|
|
16
|
-
};
|
|
17
|
-
type NormalizedOptions = {
|
|
18
|
-
handlePrefix: string;
|
|
19
|
-
handlesMap: HandlesMap;
|
|
20
|
-
apps: string[];
|
|
21
|
-
extensions: string[];
|
|
22
|
-
i18n: {
|
|
23
|
-
domain: string | null;
|
|
24
|
-
replaceRequestedFile: boolean;
|
|
25
|
-
};
|
|
9
|
+
handle: (entryName: string) => string;
|
|
10
|
+
map: RequestToHandleMap;
|
|
26
11
|
};
|
|
27
12
|
declare class GenerateWordPressAssetFileWebpackPlugin {
|
|
28
|
-
options:
|
|
13
|
+
options: Options;
|
|
29
14
|
constructor(options: Options);
|
|
30
15
|
apply(compiler: Compiler): void;
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
deps: Set<string>;
|
|
34
|
-
i18n: NormalizedOptions['i18n'];
|
|
35
|
-
entryName: string;
|
|
36
|
-
}): string;
|
|
37
|
-
getLoaderFileContent(entriesData: Record<string, string>): string;
|
|
38
|
-
getEntryType(entryName: string): "extension" | "app" | "util";
|
|
16
|
+
addAssetFileToEntrypoint(compilation: Compilation, entryName: string, chunk: Chunk): void;
|
|
17
|
+
getDepsHandlesFromChunk(compilation: Compilation, chunk: Chunk): string[];
|
|
39
18
|
getFileFromChunk(chunk: Chunk): string | undefined;
|
|
40
|
-
isExternalDep(request: string): boolean | "";
|
|
41
|
-
getHandleFromDep(dep: string): string;
|
|
42
|
-
generateHandleName(name: string): string;
|
|
43
|
-
generateAssetsFileName(filename: string): string;
|
|
44
|
-
normalizeOptions(options: Options): NormalizedOptions;
|
|
45
19
|
}
|
|
46
20
|
|
|
47
21
|
export { GenerateWordPressAssetFileWebpackPlugin };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,47 +1,21 @@
|
|
|
1
1
|
import { Compiler, Compilation, Chunk } from 'webpack';
|
|
2
2
|
|
|
3
|
-
type
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
}
|
|
3
|
+
type RequestToHandleMap = Array<{
|
|
4
|
+
request: string | RegExp;
|
|
5
|
+
handle: string;
|
|
6
|
+
}>;
|
|
7
|
+
|
|
7
8
|
type Options = {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
apps?: string[];
|
|
11
|
-
extensions?: string[];
|
|
12
|
-
i18n?: {
|
|
13
|
-
domain: string;
|
|
14
|
-
replaceRequestedFile?: boolean;
|
|
15
|
-
};
|
|
16
|
-
};
|
|
17
|
-
type NormalizedOptions = {
|
|
18
|
-
handlePrefix: string;
|
|
19
|
-
handlesMap: HandlesMap;
|
|
20
|
-
apps: string[];
|
|
21
|
-
extensions: string[];
|
|
22
|
-
i18n: {
|
|
23
|
-
domain: string | null;
|
|
24
|
-
replaceRequestedFile: boolean;
|
|
25
|
-
};
|
|
9
|
+
handle: (entryName: string) => string;
|
|
10
|
+
map: RequestToHandleMap;
|
|
26
11
|
};
|
|
27
12
|
declare class GenerateWordPressAssetFileWebpackPlugin {
|
|
28
|
-
options:
|
|
13
|
+
options: Options;
|
|
29
14
|
constructor(options: Options);
|
|
30
15
|
apply(compiler: Compiler): void;
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
deps: Set<string>;
|
|
34
|
-
i18n: NormalizedOptions['i18n'];
|
|
35
|
-
entryName: string;
|
|
36
|
-
}): string;
|
|
37
|
-
getLoaderFileContent(entriesData: Record<string, string>): string;
|
|
38
|
-
getEntryType(entryName: string): "extension" | "app" | "util";
|
|
16
|
+
addAssetFileToEntrypoint(compilation: Compilation, entryName: string, chunk: Chunk): void;
|
|
17
|
+
getDepsHandlesFromChunk(compilation: Compilation, chunk: Chunk): string[];
|
|
39
18
|
getFileFromChunk(chunk: Chunk): string | undefined;
|
|
40
|
-
isExternalDep(request: string): boolean | "";
|
|
41
|
-
getHandleFromDep(dep: string): string;
|
|
42
|
-
generateHandleName(name: string): string;
|
|
43
|
-
generateAssetsFileName(filename: string): string;
|
|
44
|
-
normalizeOptions(options: Options): NormalizedOptions;
|
|
45
19
|
}
|
|
46
20
|
|
|
47
21
|
export { GenerateWordPressAssetFileWebpackPlugin };
|
package/dist/index.js
CHANGED
|
@@ -23,176 +23,98 @@ __export(src_exports, {
|
|
|
23
23
|
GenerateWordPressAssetFileWebpackPlugin: () => GenerateWordPressAssetFileWebpackPlugin
|
|
24
24
|
});
|
|
25
25
|
module.exports = __toCommonJS(src_exports);
|
|
26
|
+
|
|
27
|
+
// src/plugin.ts
|
|
26
28
|
var import_webpack = require("webpack");
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
29
|
+
|
|
30
|
+
// src/utils.ts
|
|
31
|
+
function getAssetFileContent(entryHandle, depsHandles) {
|
|
32
|
+
const depsAsString = depsHandles.filter((dep) => dep !== entryHandle).sort().map((dep) => `'${dep}',`).join("\n ");
|
|
33
|
+
return `<?php
|
|
34
|
+
if ( ! defined( 'ABSPATH' ) ) {
|
|
35
|
+
exit;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* This file is generated by Webpack, do not edit it directly.
|
|
39
|
+
*/
|
|
40
|
+
return [
|
|
41
|
+
'handle' => '${entryHandle}',
|
|
42
|
+
'deps' => [
|
|
43
|
+
${depsAsString}
|
|
44
|
+
],
|
|
45
|
+
];
|
|
46
|
+
`;
|
|
47
|
+
}
|
|
48
|
+
function transformRequestToHandle(request, map) {
|
|
49
|
+
if (!request) {
|
|
50
|
+
return request;
|
|
35
51
|
}
|
|
36
|
-
|
|
52
|
+
for (const item of map) {
|
|
53
|
+
let { request: requestRegex, handle } = item;
|
|
54
|
+
if (!(requestRegex instanceof RegExp)) {
|
|
55
|
+
requestRegex = new RegExp(`^${requestRegex}$`);
|
|
56
|
+
}
|
|
57
|
+
const matches = request.match(requestRegex);
|
|
58
|
+
if (matches) {
|
|
59
|
+
return request.replace(requestRegex, handle);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
function createAssetFilePath(path, suffix = ".asset.php") {
|
|
64
|
+
return path.replace(/(\.min)?\.js$/i, suffix);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// src/plugin.ts
|
|
37
68
|
var GenerateWordPressAssetFileWebpackPlugin = class {
|
|
38
69
|
options;
|
|
39
70
|
constructor(options) {
|
|
40
|
-
this.options =
|
|
71
|
+
this.options = options;
|
|
41
72
|
}
|
|
42
73
|
apply(compiler) {
|
|
43
74
|
compiler.hooks.thisCompilation.tap(this.constructor.name, (compilation) => {
|
|
44
|
-
let handlesAssetsMap;
|
|
45
75
|
compilation.hooks.processAssets.tap({ name: this.constructor.name }, () => {
|
|
46
|
-
|
|
76
|
+
[...compilation.entrypoints].forEach(([entryName, entrypoint]) => {
|
|
47
77
|
const chunk = entrypoint.chunks.find(({ name }) => name === entryName);
|
|
48
78
|
if (!chunk) {
|
|
49
|
-
return
|
|
50
|
-
}
|
|
51
|
-
const chunkJSFile = this.getFileFromChunk(chunk);
|
|
52
|
-
if (!chunkJSFile) {
|
|
53
|
-
return map;
|
|
79
|
+
return;
|
|
54
80
|
}
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
compilation.getPath("[file]", { filename: chunkJSFile })
|
|
58
|
-
);
|
|
59
|
-
const handle = this.generateHandleName(entryName);
|
|
60
|
-
const content = this.createAssetsFileContent({
|
|
61
|
-
deps,
|
|
62
|
-
entryName,
|
|
63
|
-
i18n: this.options.i18n
|
|
64
|
-
});
|
|
65
|
-
compilation.assets[assetFilename] = new import_webpack.sources.RawSource(content);
|
|
66
|
-
chunk.files.add(assetFilename);
|
|
67
|
-
map[handle] = assetFilename;
|
|
68
|
-
return map;
|
|
69
|
-
}, {});
|
|
70
|
-
});
|
|
71
|
-
compilation.hooks.afterProcessAssets.tap({ name: this.constructor.name }, () => {
|
|
72
|
-
const loaderFileContent = this.getLoaderFileContent(handlesAssetsMap);
|
|
73
|
-
compilation.assets["loader.php"] = new import_webpack.sources.RawSource(loaderFileContent);
|
|
81
|
+
this.addAssetFileToEntrypoint(compilation, entryName, chunk);
|
|
82
|
+
});
|
|
74
83
|
});
|
|
75
84
|
});
|
|
76
85
|
}
|
|
77
|
-
|
|
86
|
+
addAssetFileToEntrypoint(compilation, entryName, chunk) {
|
|
87
|
+
const chunkJSFile = this.getFileFromChunk(chunk);
|
|
88
|
+
if (!chunkJSFile) {
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
const transformEntryNameToHandle = this.options.handle;
|
|
92
|
+
const entryHandle = transformEntryNameToHandle(entryName);
|
|
93
|
+
const depsHandles = this.getDepsHandlesFromChunk(compilation, chunk);
|
|
94
|
+
const assetFilePath = createAssetFilePath(
|
|
95
|
+
compilation.getPath("[file]", { filename: chunkJSFile })
|
|
96
|
+
);
|
|
97
|
+
compilation.assets[assetFilePath] = new import_webpack.sources.RawSource(
|
|
98
|
+
getAssetFileContent(entryHandle, depsHandles)
|
|
99
|
+
);
|
|
100
|
+
chunk.files.add(assetFilePath);
|
|
101
|
+
}
|
|
102
|
+
getDepsHandlesFromChunk(compilation, chunk) {
|
|
78
103
|
const depsSet = /* @__PURE__ */ new Set();
|
|
79
104
|
compilation.chunkGraph.getChunkModules(chunk).forEach((module2) => {
|
|
80
105
|
const theModule = module2;
|
|
81
106
|
[...theModule.modules || [], theModule].forEach((subModule) => {
|
|
82
|
-
|
|
83
|
-
|
|
107
|
+
const depHandle = transformRequestToHandle(subModule.userRequest, this.options.map);
|
|
108
|
+
if (depHandle) {
|
|
109
|
+
depsSet.add(depHandle);
|
|
84
110
|
}
|
|
85
111
|
});
|
|
86
112
|
});
|
|
87
|
-
return depsSet;
|
|
88
|
-
}
|
|
89
|
-
createAssetsFileContent({
|
|
90
|
-
deps,
|
|
91
|
-
i18n,
|
|
92
|
-
entryName
|
|
93
|
-
}) {
|
|
94
|
-
const handleName = this.generateHandleName(entryName);
|
|
95
|
-
const type = this.getEntryType(entryName);
|
|
96
|
-
const depsAsString = [...deps].map((dep) => this.getHandleFromDep(dep)).filter((dep) => dep !== handleName).sort().map((dep) => `'${dep}',`).join("\n ");
|
|
97
|
-
const i18nContent = i18n.domain ? `[
|
|
98
|
-
'domain' => '${i18n.domain}',
|
|
99
|
-
'replace_requested_file' => ${(i18n.replaceRequestedFile ?? false).toString()},
|
|
100
|
-
]` : "[]";
|
|
101
|
-
const content = `<?php
|
|
102
|
-
if ( ! defined( 'ABSPATH' ) ) {
|
|
103
|
-
exit;
|
|
104
|
-
}
|
|
105
|
-
/**
|
|
106
|
-
* This file is generated by Webpack, do not edit it directly.
|
|
107
|
-
*/
|
|
108
|
-
return [
|
|
109
|
-
'handle' => '${handleName}',
|
|
110
|
-
'src' => plugins_url( '/', __FILE__ ) . '${entryName}{{MIN_SUFFIX}}.js',
|
|
111
|
-
'i18n' => ${i18nContent},
|
|
112
|
-
'type' => '${type}',
|
|
113
|
-
'deps' => [
|
|
114
|
-
${depsAsString}
|
|
115
|
-
],
|
|
116
|
-
];
|
|
117
|
-
`;
|
|
118
|
-
return content;
|
|
119
|
-
}
|
|
120
|
-
getLoaderFileContent(entriesData) {
|
|
121
|
-
const entriesContent = Object.entries(entriesData).map(([handle, assetFileName]) => {
|
|
122
|
-
return `
|
|
123
|
-
$data['${handle}'] = require __DIR__ . '/${assetFileName}';`;
|
|
124
|
-
});
|
|
125
|
-
return `<?php
|
|
126
|
-
if ( ! defined( 'ABSPATH' ) ) {
|
|
127
|
-
exit;
|
|
128
|
-
}
|
|
129
|
-
/**
|
|
130
|
-
* This file is generated by Webpack, do not edit it directly.
|
|
131
|
-
*/
|
|
132
|
-
add_filter( 'elementor/editor-v2/packages/config', function( $data ) {
|
|
133
|
-
${entriesContent.join("\n")}
|
|
134
|
-
return $data;
|
|
135
|
-
} );
|
|
136
|
-
`;
|
|
137
|
-
}
|
|
138
|
-
getEntryType(entryName) {
|
|
139
|
-
if (this.options.extensions.includes(entryName)) {
|
|
140
|
-
return "extension";
|
|
141
|
-
}
|
|
142
|
-
if (this.options.apps.includes(entryName)) {
|
|
143
|
-
return "app";
|
|
144
|
-
}
|
|
145
|
-
return "util";
|
|
113
|
+
return [...depsSet];
|
|
146
114
|
}
|
|
147
115
|
getFileFromChunk(chunk) {
|
|
148
116
|
return [...chunk.files].find((f) => /\.js$/i.test(f));
|
|
149
117
|
}
|
|
150
|
-
isExternalDep(request) {
|
|
151
|
-
const { startsWith, exact } = this.options.handlesMap;
|
|
152
|
-
return request && (Object.keys(exact).includes(request) || Object.keys(startsWith).some((dep) => request.startsWith(dep)));
|
|
153
|
-
}
|
|
154
|
-
getHandleFromDep(dep) {
|
|
155
|
-
const { startsWith, exact } = this.options.handlesMap;
|
|
156
|
-
if (Object.keys(exact).includes(dep)) {
|
|
157
|
-
return exact[dep];
|
|
158
|
-
}
|
|
159
|
-
for (const [key, value] of Object.entries(startsWith)) {
|
|
160
|
-
if (dep.startsWith(key)) {
|
|
161
|
-
return dep.replace(key, value);
|
|
162
|
-
}
|
|
163
|
-
}
|
|
164
|
-
return dep;
|
|
165
|
-
}
|
|
166
|
-
generateHandleName(name) {
|
|
167
|
-
if (this.options.handlePrefix) {
|
|
168
|
-
return `${this.options.handlePrefix}${name}`;
|
|
169
|
-
}
|
|
170
|
-
return name;
|
|
171
|
-
}
|
|
172
|
-
generateAssetsFileName(filename) {
|
|
173
|
-
return filename.replace(/(\.min)?\.js$/i, ".asset.php");
|
|
174
|
-
}
|
|
175
|
-
normalizeOptions(options) {
|
|
176
|
-
return {
|
|
177
|
-
...options,
|
|
178
|
-
handlesMap: {
|
|
179
|
-
exact: {
|
|
180
|
-
...baseHandlesMap.exact,
|
|
181
|
-
...options?.handlesMap?.exact || {}
|
|
182
|
-
},
|
|
183
|
-
startsWith: {
|
|
184
|
-
...baseHandlesMap.startsWith,
|
|
185
|
-
...options?.handlesMap?.startsWith || {}
|
|
186
|
-
}
|
|
187
|
-
},
|
|
188
|
-
apps: options?.apps || [],
|
|
189
|
-
extensions: options?.extensions || [],
|
|
190
|
-
i18n: {
|
|
191
|
-
domain: options?.i18n?.domain || null,
|
|
192
|
-
replaceRequestedFile: options?.i18n?.replaceRequestedFile ?? false
|
|
193
|
-
}
|
|
194
|
-
};
|
|
195
|
-
}
|
|
196
118
|
};
|
|
197
119
|
// Annotate the CommonJS export names for ESM import in node:
|
|
198
120
|
0 && (module.exports = {
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["// Inspired by \"Dependency Extraction Webpack Plugin\" by @wordpress team.\n// Link: https://github.com/WordPress/gutenberg/tree/trunk/packages/dependency-extraction-webpack-plugin\nimport { sources, Compilation, Compiler, Chunk } from 'webpack';\n\ntype HandlesMap = {\n\texact: Record<string, string>;\n\tstartsWith: Record<string, string>;\n}\n\ntype Options = {\n\thandlePrefix: string;\n\thandlesMap?: Partial<HandlesMap>\n\tapps?: string[];\n\textensions?: string[];\n\ti18n?: {\n\t\tdomain: string;\n\t\treplaceRequestedFile?: boolean;\n\t}\n}\n\ntype NormalizedOptions = {\n\thandlePrefix: string;\n\thandlesMap: HandlesMap;\n\tapps: string[];\n\textensions: string[];\n\ti18n: {\n\t\tdomain: string | null;\n\t\treplaceRequestedFile: boolean;\n\t}\n}\n\ntype Module = {\n\tuserRequest?: string;\n\tmodules?: Module[];\n}\n\nconst baseHandlesMap: HandlesMap = {\n\texact: {\n\t\treact: 'react',\n\t\t'react-dom': 'react-dom',\n\t},\n\tstartsWith: {\n\t\t'@elementor/': 'elementor-packages-',\n\t\t'@wordpress/': 'wp-',\n\t},\n};\n\nexport class GenerateWordPressAssetFileWebpackPlugin {\n\toptions: NormalizedOptions;\n\n\tconstructor( options: Options ) {\n\t\tthis.options = this.normalizeOptions( options );\n\t}\n\n\tapply( compiler: Compiler ) {\n\t\tcompiler.hooks.thisCompilation.tap( this.constructor.name, ( compilation ) => {\n\t\t\tlet handlesAssetsMap: Record<string, string>;\n\n\t\t\tcompilation.hooks.processAssets.tap( { name: this.constructor.name }, () => {\n\t\t\t\thandlesAssetsMap = [ ...compilation.entrypoints ].reduce<Record<string, string>>( ( map, [ entryName, entrypoint ] ) => {\n\t\t\t\t\tconst chunk = entrypoint.chunks.find( ( { name } ) => name === entryName );\n\n\t\t\t\t\tif ( ! chunk ) {\n\t\t\t\t\t\treturn map;\n\t\t\t\t\t}\n\n\t\t\t\t\tconst chunkJSFile = this.getFileFromChunk( chunk );\n\n\t\t\t\t\tif ( ! chunkJSFile ) {\n\t\t\t\t\t\treturn map;\n\t\t\t\t\t}\n\n\t\t\t\t\tconst deps = this.getDepsFromChunk( compilation, chunk );\n\n\t\t\t\t\tconst assetFilename = this.generateAssetsFileName(\n\t\t\t\t\t\tcompilation.getPath( '[file]', { filename: chunkJSFile } )\n\t\t\t\t\t);\n\n\t\t\t\t\tconst handle = this.generateHandleName( entryName );\n\n\t\t\t\t\tconst content = this.createAssetsFileContent( {\n\t\t\t\t\t\tdeps,\n\t\t\t\t\t\tentryName,\n\t\t\t\t\t\ti18n: this.options.i18n,\n\t\t\t\t\t} );\n\n\t\t\t\t\t// Add source and file into compilation for webpack to output.\n\t\t\t\t\tcompilation.assets[ assetFilename ] = new sources.RawSource( content );\n\n\t\t\t\t\tchunk.files.add( assetFilename );\n\n\t\t\t\t\tmap[ handle ] = assetFilename;\n\n\t\t\t\t\treturn map;\n\t\t\t\t}, {} );\n\t\t\t} );\n\n\t\t\tcompilation.hooks.afterProcessAssets.tap( { name: this.constructor.name }, () => {\n\t\t\t\tconst loaderFileContent = this.getLoaderFileContent( handlesAssetsMap );\n\n\t\t\t\tcompilation.assets[ 'loader.php' ] = new sources.RawSource( loaderFileContent );\n\t\t\t} );\n\t\t} );\n\t}\n\n\tgetDepsFromChunk( compilation: Compilation, chunk: Chunk ) {\n\t\tconst depsSet = new Set<string>();\n\n\t\tcompilation.chunkGraph.getChunkModules( chunk ).forEach( ( module ) => {\n\t\t\t// There are some issues with types in webpack, so we need to cast it.\n\t\t\tconst theModule = module as Module;\n\n\t\t\t[ ...( theModule.modules || [] ), theModule ].forEach( ( subModule ) => {\n\t\t\t\tif ( subModule.userRequest && this.isExternalDep( subModule.userRequest ) ) {\n\t\t\t\t\tdepsSet.add( subModule.userRequest );\n\t\t\t\t}\n\t\t\t} );\n\t\t} );\n\n\t\treturn depsSet;\n\t}\n\n\tcreateAssetsFileContent( {\n\t\tdeps,\n\t\ti18n,\n\t\tentryName,\n\t}: {\n\t\tdeps: Set<string>;\n\t\ti18n: NormalizedOptions[ 'i18n' ];\n\t\tentryName: string;\n\t} ) {\n\t\tconst handleName = this.generateHandleName( entryName );\n\t\tconst type = this.getEntryType( entryName );\n\n\t\tconst depsAsString = [ ...deps ]\n\t\t\t.map( ( dep ) => this.getHandleFromDep( dep ) )\n\t\t\t.filter( ( dep ) => dep !== handleName )\n\t\t\t.sort()\n\t\t\t.map( ( dep ) => `'${ dep }',` )\n\t\t\t.join( '\\n\\t\\t' );\n\n\t\tconst i18nContent = i18n.domain ? `[\n\t\t'domain' => '${ i18n.domain }',\n\t\t'replace_requested_file' => ${ ( i18n.replaceRequestedFile ?? false ).toString() },\n\t]` : '[]';\n\n\t\tconst content =\n\t\t\t`<?php\nif ( ! defined( 'ABSPATH' ) ) {\n\texit;\n}\n/**\n * This file is generated by Webpack, do not edit it directly.\n */\nreturn [\n\t'handle' => '${ handleName }',\n\t'src' => plugins_url( '/', __FILE__ ) . '${ entryName }{{MIN_SUFFIX}}.js',\n\t'i18n' => ${ i18nContent },\n\t'type' => '${ type }',\n\t'deps' => [\n\t\t${ depsAsString }\n\t],\n];\n`;\n\n\t\treturn content;\n\t}\n\n\tgetLoaderFileContent( entriesData: Record<string, string> ) {\n\t\tconst entriesContent = Object.entries( entriesData ).map( ( [ handle, assetFileName ] ) => {\n\t\t\treturn `\n\t$data['${ handle }'] = require __DIR__ . '/${ assetFileName }';`;\n\t\t} );\n\n\t\treturn `<?php\nif ( ! defined( 'ABSPATH' ) ) {\n\texit;\n}\n/**\n * This file is generated by Webpack, do not edit it directly.\n */\nadd_filter( 'elementor/editor-v2/packages/config', function( $data ) {\n${ entriesContent.join( '\\n' ) }\n\treturn $data;\n} );\n`;\n\t}\n\n\tgetEntryType( entryName: string ) {\n\t\tif ( this.options.extensions.includes( entryName ) ) {\n\t\t\treturn 'extension';\n\t\t}\n\n\t\tif ( this.options.apps.includes( entryName ) ) {\n\t\t\treturn 'app';\n\t\t}\n\n\t\treturn 'util';\n\t}\n\n\tgetFileFromChunk( chunk: Chunk ) {\n\t\treturn [ ...chunk.files ].find( ( f ) => /\\.js$/i.test( f ) );\n\t}\n\n\tisExternalDep( request: string ) {\n\t\tconst { startsWith, exact } = this.options.handlesMap;\n\n\t\treturn request && (\n\t\t\tObject.keys( exact ).includes( request ) ||\n\t\t\tObject.keys( startsWith ).some( ( dep ) => request.startsWith( dep ) )\n\t\t);\n\t}\n\n\tgetHandleFromDep( dep: string ) {\n\t\tconst { startsWith, exact } = this.options.handlesMap;\n\n\t\tif ( Object.keys( exact ).includes( dep ) ) {\n\t\t\treturn exact[ dep ];\n\t\t}\n\n\t\tfor ( const [ key, value ] of Object.entries( startsWith ) ) {\n\t\t\tif ( dep.startsWith( key ) ) {\n\t\t\t\treturn dep.replace( key, value );\n\t\t\t}\n\t\t}\n\n\t\treturn dep;\n\t}\n\n\tgenerateHandleName( name: string ) {\n\t\tif ( this.options.handlePrefix ) {\n\t\t\treturn `${ this.options.handlePrefix }${ name }`;\n\t\t}\n\n\t\treturn name;\n\t}\n\n\tgenerateAssetsFileName( filename: string ) {\n\t\treturn filename.replace( /(\\.min)?\\.js$/i, '.asset.php' );\n\t}\n\n\tnormalizeOptions( options: Options ): NormalizedOptions {\n\t\treturn {\n\t\t\t...options,\n\t\t\thandlesMap: {\n\t\t\t\texact: {\n\t\t\t\t\t...baseHandlesMap.exact,\n\t\t\t\t\t...( options?.handlesMap?.exact || {} ),\n\t\t\t\t},\n\t\t\t\tstartsWith: {\n\t\t\t\t\t...baseHandlesMap.startsWith,\n\t\t\t\t\t...( options?.handlesMap?.startsWith || {} ),\n\t\t\t\t},\n\t\t\t},\n\t\t\tapps: options?.apps || [],\n\t\t\textensions: options?.extensions || [],\n\t\t\ti18n: {\n\t\t\t\tdomain: options?.i18n?.domain || null,\n\t\t\t\treplaceRequestedFile: options?.i18n?.replaceRequestedFile ?? false,\n\t\t\t},\n\t\t};\n\t}\n}\n"],"mappings":"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","names":["module"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/plugin.ts","../src/utils.ts"],"sourcesContent":["export { default as GenerateWordPressAssetFileWebpackPlugin } from './plugin';\n","// Inspired by \"Dependency Extraction Webpack Plugin\" by @wordpress team.\n// Link: https://github.com/WordPress/gutenberg/tree/trunk/packages/dependency-extraction-webpack-plugin\nimport { sources, Compilation, Compiler, Chunk } from 'webpack';\nimport { createAssetFilePath, getAssetFileContent, transformRequestToHandle } from './utils';\nimport { RequestToHandleMap } from './types';\n\ntype Options = {\n\thandle: ( entryName: string ) => string;\n\tmap: RequestToHandleMap\n}\n\ntype Module = {\n\tuserRequest?: string;\n\tmodules?: Module[];\n}\n\nexport default class GenerateWordPressAssetFileWebpackPlugin {\n\toptions: Options;\n\n\tconstructor( options: Options ) {\n\t\tthis.options = options;\n\t}\n\n\tapply( compiler: Compiler ) {\n\t\tcompiler.hooks.thisCompilation.tap( this.constructor.name, ( compilation ) => {\n\t\t\tcompilation.hooks.processAssets.tap( { name: this.constructor.name }, () => {\n\t\t\t\t[ ...compilation.entrypoints ].forEach( ( [ entryName, entrypoint ] ) => {\n\t\t\t\t\tconst chunk = entrypoint.chunks.find( ( { name } ) => name === entryName );\n\n\t\t\t\t\tif ( ! chunk ) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\tthis.addAssetFileToEntrypoint( compilation, entryName, chunk );\n\t\t\t\t} );\n\t\t\t} );\n\t\t} );\n\t}\n\n\taddAssetFileToEntrypoint( compilation: Compilation, entryName: string, chunk: Chunk ) {\n\t\tconst chunkJSFile = this.getFileFromChunk( chunk );\n\n\t\tif ( ! chunkJSFile ) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst transformEntryNameToHandle = this.options.handle;\n\n\t\tconst entryHandle = transformEntryNameToHandle( entryName );\n\t\tconst depsHandles = this.getDepsHandlesFromChunk( compilation, chunk );\n\n\t\tconst assetFilePath = createAssetFilePath(\n\t\t\tcompilation.getPath( '[file]', { filename: chunkJSFile } )\n\t\t);\n\n\t\t// Add source and file into compilation for webpack to output.\n\t\tcompilation.assets[ assetFilePath ] = new sources.RawSource(\n\t\t\tgetAssetFileContent( entryHandle, depsHandles )\n\t\t);\n\n\t\tchunk.files.add( assetFilePath );\n\t}\n\n\tgetDepsHandlesFromChunk( compilation: Compilation, chunk: Chunk ) {\n\t\tconst depsSet = new Set<string>();\n\n\t\tcompilation.chunkGraph.getChunkModules( chunk ).forEach( ( module ) => {\n\t\t\t// There are some issues with types in webpack, so we need to cast it.\n\t\t\tconst theModule = module as Module;\n\n\t\t\t[ ...( theModule.modules || [] ), theModule ].forEach( ( subModule ) => {\n\t\t\t\tconst depHandle = transformRequestToHandle( subModule.userRequest, this.options.map );\n\n\t\t\t\tif ( depHandle ) {\n\t\t\t\t\tdepsSet.add( depHandle );\n\t\t\t\t}\n\t\t\t} );\n\t\t} );\n\n\t\treturn [ ...depsSet ];\n\t}\n\n\tgetFileFromChunk( chunk: Chunk ) {\n\t\treturn [ ...chunk.files ].find( ( f ) => /\\.js$/i.test( f ) );\n\t}\n}\n","import { RequestToHandleMap } from './types';\n\nexport function getAssetFileContent( entryHandle: string, depsHandles: string[] ) {\n\tconst depsAsString = depsHandles\n\t\t.filter( ( dep ) => dep !== entryHandle )\n\t\t.sort()\n\t\t.map( ( dep ) => `'${ dep }',` )\n\t\t.join( '\\n\\t\\t' );\n\n\treturn `<?php\nif ( ! defined( 'ABSPATH' ) ) {\n\texit;\n}\n/**\n * This file is generated by Webpack, do not edit it directly.\n */\nreturn [\n\t'handle' => '${ entryHandle }',\n\t'deps' => [\n\t\t${ depsAsString }\n\t],\n];\n`;\n}\n\nexport function transformRequestToHandle( request: string | undefined, map: RequestToHandleMap ) {\n\tif ( ! request ) {\n\t\treturn request;\n\t}\n\n\tfor ( const item of map ) {\n\t\tlet { request: requestRegex, handle } = item;\n\n\t\tif ( ! ( requestRegex instanceof RegExp ) ) {\n\t\t\trequestRegex = new RegExp( `^${ requestRegex }$` );\n\t\t}\n\n\t\tconst matches = request.match( requestRegex );\n\n\t\tif ( matches ) {\n\t\t\treturn request.replace( requestRegex, handle );\n\t\t}\n\t}\n}\n\nexport function createAssetFilePath( path: string, suffix = '.asset.php' ) {\n\treturn path.replace( /(\\.min)?\\.js$/i, suffix );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACEA,qBAAsD;;;ACA/C,SAAS,oBAAqB,aAAqB,aAAwB;AACjF,QAAM,eAAe,YACnB,OAAQ,CAAE,QAAS,QAAQ,WAAY,EACvC,KAAK,EACL,IAAK,CAAE,QAAS,IAAK,GAAI,IAAK,EAC9B,KAAM,MAAS;AAEjB,SAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,gBAQS,WAAY;AAAA;AAAA,IAExB,YAAa;AAAA;AAAA;AAAA;AAIlB;AAEO,SAAS,yBAA0B,SAA6B,KAA0B;AAChG,MAAK,CAAE,SAAU;AAChB,WAAO;AAAA,EACR;AAEA,aAAY,QAAQ,KAAM;AACzB,QAAI,EAAE,SAAS,cAAc,OAAO,IAAI;AAExC,QAAK,EAAI,wBAAwB,SAAW;AAC3C,qBAAe,IAAI,OAAQ,IAAK,YAAa,GAAI;AAAA,IAClD;AAEA,UAAM,UAAU,QAAQ,MAAO,YAAa;AAE5C,QAAK,SAAU;AACd,aAAO,QAAQ,QAAS,cAAc,MAAO;AAAA,IAC9C;AAAA,EACD;AACD;AAEO,SAAS,oBAAqB,MAAc,SAAS,cAAe;AAC1E,SAAO,KAAK,QAAS,kBAAkB,MAAO;AAC/C;;;AD/BA,IAAqB,0CAArB,MAA6D;AAAA,EAC5D;AAAA,EAEA,YAAa,SAAmB;AAC/B,SAAK,UAAU;AAAA,EAChB;AAAA,EAEA,MAAO,UAAqB;AAC3B,aAAS,MAAM,gBAAgB,IAAK,KAAK,YAAY,MAAM,CAAE,gBAAiB;AAC7E,kBAAY,MAAM,cAAc,IAAK,EAAE,MAAM,KAAK,YAAY,KAAK,GAAG,MAAM;AAC3E,SAAE,GAAG,YAAY,WAAY,EAAE,QAAS,CAAE,CAAE,WAAW,UAAW,MAAO;AACxE,gBAAM,QAAQ,WAAW,OAAO,KAAM,CAAE,EAAE,KAAK,MAAO,SAAS,SAAU;AAEzE,cAAK,CAAE,OAAQ;AACd;AAAA,UACD;AAEA,eAAK,yBAA0B,aAAa,WAAW,KAAM;AAAA,QAC9D,CAAE;AAAA,MACH,CAAE;AAAA,IACH,CAAE;AAAA,EACH;AAAA,EAEA,yBAA0B,aAA0B,WAAmB,OAAe;AACrF,UAAM,cAAc,KAAK,iBAAkB,KAAM;AAEjD,QAAK,CAAE,aAAc;AACpB;AAAA,IACD;AAEA,UAAM,6BAA6B,KAAK,QAAQ;AAEhD,UAAM,cAAc,2BAA4B,SAAU;AAC1D,UAAM,cAAc,KAAK,wBAAyB,aAAa,KAAM;AAErE,UAAM,gBAAgB;AAAA,MACrB,YAAY,QAAS,UAAU,EAAE,UAAU,YAAY,CAAE;AAAA,IAC1D;AAGA,gBAAY,OAAQ,aAAc,IAAI,IAAI,uBAAQ;AAAA,MACjD,oBAAqB,aAAa,WAAY;AAAA,IAC/C;AAEA,UAAM,MAAM,IAAK,aAAc;AAAA,EAChC;AAAA,EAEA,wBAAyB,aAA0B,OAAe;AACjE,UAAM,UAAU,oBAAI,IAAY;AAEhC,gBAAY,WAAW,gBAAiB,KAAM,EAAE,QAAS,CAAEA,YAAY;AAEtE,YAAM,YAAYA;AAElB,OAAE,GAAK,UAAU,WAAW,CAAC,GAAK,SAAU,EAAE,QAAS,CAAE,cAAe;AACvE,cAAM,YAAY,yBAA0B,UAAU,aAAa,KAAK,QAAQ,GAAI;AAEpF,YAAK,WAAY;AAChB,kBAAQ,IAAK,SAAU;AAAA,QACxB;AAAA,MACD,CAAE;AAAA,IACH,CAAE;AAEF,WAAO,CAAE,GAAG,OAAQ;AAAA,EACrB;AAAA,EAEA,iBAAkB,OAAe;AAChC,WAAO,CAAE,GAAG,MAAM,KAAM,EAAE,KAAM,CAAE,MAAO,SAAS,KAAM,CAAE,CAAE;AAAA,EAC7D;AACD;","names":["module"]}
|
package/dist/index.mjs
CHANGED
|
@@ -1,174 +1,94 @@
|
|
|
1
|
-
// src/
|
|
1
|
+
// src/plugin.ts
|
|
2
2
|
import { sources } from "webpack";
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
3
|
+
|
|
4
|
+
// src/utils.ts
|
|
5
|
+
function getAssetFileContent(entryHandle, depsHandles) {
|
|
6
|
+
const depsAsString = depsHandles.filter((dep) => dep !== entryHandle).sort().map((dep) => `'${dep}',`).join("\n ");
|
|
7
|
+
return `<?php
|
|
8
|
+
if ( ! defined( 'ABSPATH' ) ) {
|
|
9
|
+
exit;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* This file is generated by Webpack, do not edit it directly.
|
|
13
|
+
*/
|
|
14
|
+
return [
|
|
15
|
+
'handle' => '${entryHandle}',
|
|
16
|
+
'deps' => [
|
|
17
|
+
${depsAsString}
|
|
18
|
+
],
|
|
19
|
+
];
|
|
20
|
+
`;
|
|
21
|
+
}
|
|
22
|
+
function transformRequestToHandle(request, map) {
|
|
23
|
+
if (!request) {
|
|
24
|
+
return request;
|
|
11
25
|
}
|
|
12
|
-
|
|
26
|
+
for (const item of map) {
|
|
27
|
+
let { request: requestRegex, handle } = item;
|
|
28
|
+
if (!(requestRegex instanceof RegExp)) {
|
|
29
|
+
requestRegex = new RegExp(`^${requestRegex}$`);
|
|
30
|
+
}
|
|
31
|
+
const matches = request.match(requestRegex);
|
|
32
|
+
if (matches) {
|
|
33
|
+
return request.replace(requestRegex, handle);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
function createAssetFilePath(path, suffix = ".asset.php") {
|
|
38
|
+
return path.replace(/(\.min)?\.js$/i, suffix);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// src/plugin.ts
|
|
13
42
|
var GenerateWordPressAssetFileWebpackPlugin = class {
|
|
14
43
|
options;
|
|
15
44
|
constructor(options) {
|
|
16
|
-
this.options =
|
|
45
|
+
this.options = options;
|
|
17
46
|
}
|
|
18
47
|
apply(compiler) {
|
|
19
48
|
compiler.hooks.thisCompilation.tap(this.constructor.name, (compilation) => {
|
|
20
|
-
let handlesAssetsMap;
|
|
21
49
|
compilation.hooks.processAssets.tap({ name: this.constructor.name }, () => {
|
|
22
|
-
|
|
50
|
+
[...compilation.entrypoints].forEach(([entryName, entrypoint]) => {
|
|
23
51
|
const chunk = entrypoint.chunks.find(({ name }) => name === entryName);
|
|
24
52
|
if (!chunk) {
|
|
25
|
-
return
|
|
53
|
+
return;
|
|
26
54
|
}
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
return map;
|
|
30
|
-
}
|
|
31
|
-
const deps = this.getDepsFromChunk(compilation, chunk);
|
|
32
|
-
const assetFilename = this.generateAssetsFileName(
|
|
33
|
-
compilation.getPath("[file]", { filename: chunkJSFile })
|
|
34
|
-
);
|
|
35
|
-
const handle = this.generateHandleName(entryName);
|
|
36
|
-
const content = this.createAssetsFileContent({
|
|
37
|
-
deps,
|
|
38
|
-
entryName,
|
|
39
|
-
i18n: this.options.i18n
|
|
40
|
-
});
|
|
41
|
-
compilation.assets[assetFilename] = new sources.RawSource(content);
|
|
42
|
-
chunk.files.add(assetFilename);
|
|
43
|
-
map[handle] = assetFilename;
|
|
44
|
-
return map;
|
|
45
|
-
}, {});
|
|
46
|
-
});
|
|
47
|
-
compilation.hooks.afterProcessAssets.tap({ name: this.constructor.name }, () => {
|
|
48
|
-
const loaderFileContent = this.getLoaderFileContent(handlesAssetsMap);
|
|
49
|
-
compilation.assets["loader.php"] = new sources.RawSource(loaderFileContent);
|
|
55
|
+
this.addAssetFileToEntrypoint(compilation, entryName, chunk);
|
|
56
|
+
});
|
|
50
57
|
});
|
|
51
58
|
});
|
|
52
59
|
}
|
|
53
|
-
|
|
60
|
+
addAssetFileToEntrypoint(compilation, entryName, chunk) {
|
|
61
|
+
const chunkJSFile = this.getFileFromChunk(chunk);
|
|
62
|
+
if (!chunkJSFile) {
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
const transformEntryNameToHandle = this.options.handle;
|
|
66
|
+
const entryHandle = transformEntryNameToHandle(entryName);
|
|
67
|
+
const depsHandles = this.getDepsHandlesFromChunk(compilation, chunk);
|
|
68
|
+
const assetFilePath = createAssetFilePath(
|
|
69
|
+
compilation.getPath("[file]", { filename: chunkJSFile })
|
|
70
|
+
);
|
|
71
|
+
compilation.assets[assetFilePath] = new sources.RawSource(
|
|
72
|
+
getAssetFileContent(entryHandle, depsHandles)
|
|
73
|
+
);
|
|
74
|
+
chunk.files.add(assetFilePath);
|
|
75
|
+
}
|
|
76
|
+
getDepsHandlesFromChunk(compilation, chunk) {
|
|
54
77
|
const depsSet = /* @__PURE__ */ new Set();
|
|
55
78
|
compilation.chunkGraph.getChunkModules(chunk).forEach((module) => {
|
|
56
79
|
const theModule = module;
|
|
57
80
|
[...theModule.modules || [], theModule].forEach((subModule) => {
|
|
58
|
-
|
|
59
|
-
|
|
81
|
+
const depHandle = transformRequestToHandle(subModule.userRequest, this.options.map);
|
|
82
|
+
if (depHandle) {
|
|
83
|
+
depsSet.add(depHandle);
|
|
60
84
|
}
|
|
61
85
|
});
|
|
62
86
|
});
|
|
63
|
-
return depsSet;
|
|
64
|
-
}
|
|
65
|
-
createAssetsFileContent({
|
|
66
|
-
deps,
|
|
67
|
-
i18n,
|
|
68
|
-
entryName
|
|
69
|
-
}) {
|
|
70
|
-
const handleName = this.generateHandleName(entryName);
|
|
71
|
-
const type = this.getEntryType(entryName);
|
|
72
|
-
const depsAsString = [...deps].map((dep) => this.getHandleFromDep(dep)).filter((dep) => dep !== handleName).sort().map((dep) => `'${dep}',`).join("\n ");
|
|
73
|
-
const i18nContent = i18n.domain ? `[
|
|
74
|
-
'domain' => '${i18n.domain}',
|
|
75
|
-
'replace_requested_file' => ${(i18n.replaceRequestedFile ?? false).toString()},
|
|
76
|
-
]` : "[]";
|
|
77
|
-
const content = `<?php
|
|
78
|
-
if ( ! defined( 'ABSPATH' ) ) {
|
|
79
|
-
exit;
|
|
80
|
-
}
|
|
81
|
-
/**
|
|
82
|
-
* This file is generated by Webpack, do not edit it directly.
|
|
83
|
-
*/
|
|
84
|
-
return [
|
|
85
|
-
'handle' => '${handleName}',
|
|
86
|
-
'src' => plugins_url( '/', __FILE__ ) . '${entryName}{{MIN_SUFFIX}}.js',
|
|
87
|
-
'i18n' => ${i18nContent},
|
|
88
|
-
'type' => '${type}',
|
|
89
|
-
'deps' => [
|
|
90
|
-
${depsAsString}
|
|
91
|
-
],
|
|
92
|
-
];
|
|
93
|
-
`;
|
|
94
|
-
return content;
|
|
95
|
-
}
|
|
96
|
-
getLoaderFileContent(entriesData) {
|
|
97
|
-
const entriesContent = Object.entries(entriesData).map(([handle, assetFileName]) => {
|
|
98
|
-
return `
|
|
99
|
-
$data['${handle}'] = require __DIR__ . '/${assetFileName}';`;
|
|
100
|
-
});
|
|
101
|
-
return `<?php
|
|
102
|
-
if ( ! defined( 'ABSPATH' ) ) {
|
|
103
|
-
exit;
|
|
104
|
-
}
|
|
105
|
-
/**
|
|
106
|
-
* This file is generated by Webpack, do not edit it directly.
|
|
107
|
-
*/
|
|
108
|
-
add_filter( 'elementor/editor-v2/packages/config', function( $data ) {
|
|
109
|
-
${entriesContent.join("\n")}
|
|
110
|
-
return $data;
|
|
111
|
-
} );
|
|
112
|
-
`;
|
|
113
|
-
}
|
|
114
|
-
getEntryType(entryName) {
|
|
115
|
-
if (this.options.extensions.includes(entryName)) {
|
|
116
|
-
return "extension";
|
|
117
|
-
}
|
|
118
|
-
if (this.options.apps.includes(entryName)) {
|
|
119
|
-
return "app";
|
|
120
|
-
}
|
|
121
|
-
return "util";
|
|
87
|
+
return [...depsSet];
|
|
122
88
|
}
|
|
123
89
|
getFileFromChunk(chunk) {
|
|
124
90
|
return [...chunk.files].find((f) => /\.js$/i.test(f));
|
|
125
91
|
}
|
|
126
|
-
isExternalDep(request) {
|
|
127
|
-
const { startsWith, exact } = this.options.handlesMap;
|
|
128
|
-
return request && (Object.keys(exact).includes(request) || Object.keys(startsWith).some((dep) => request.startsWith(dep)));
|
|
129
|
-
}
|
|
130
|
-
getHandleFromDep(dep) {
|
|
131
|
-
const { startsWith, exact } = this.options.handlesMap;
|
|
132
|
-
if (Object.keys(exact).includes(dep)) {
|
|
133
|
-
return exact[dep];
|
|
134
|
-
}
|
|
135
|
-
for (const [key, value] of Object.entries(startsWith)) {
|
|
136
|
-
if (dep.startsWith(key)) {
|
|
137
|
-
return dep.replace(key, value);
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
return dep;
|
|
141
|
-
}
|
|
142
|
-
generateHandleName(name) {
|
|
143
|
-
if (this.options.handlePrefix) {
|
|
144
|
-
return `${this.options.handlePrefix}${name}`;
|
|
145
|
-
}
|
|
146
|
-
return name;
|
|
147
|
-
}
|
|
148
|
-
generateAssetsFileName(filename) {
|
|
149
|
-
return filename.replace(/(\.min)?\.js$/i, ".asset.php");
|
|
150
|
-
}
|
|
151
|
-
normalizeOptions(options) {
|
|
152
|
-
return {
|
|
153
|
-
...options,
|
|
154
|
-
handlesMap: {
|
|
155
|
-
exact: {
|
|
156
|
-
...baseHandlesMap.exact,
|
|
157
|
-
...options?.handlesMap?.exact || {}
|
|
158
|
-
},
|
|
159
|
-
startsWith: {
|
|
160
|
-
...baseHandlesMap.startsWith,
|
|
161
|
-
...options?.handlesMap?.startsWith || {}
|
|
162
|
-
}
|
|
163
|
-
},
|
|
164
|
-
apps: options?.apps || [],
|
|
165
|
-
extensions: options?.extensions || [],
|
|
166
|
-
i18n: {
|
|
167
|
-
domain: options?.i18n?.domain || null,
|
|
168
|
-
replaceRequestedFile: options?.i18n?.replaceRequestedFile ?? false
|
|
169
|
-
}
|
|
170
|
-
};
|
|
171
|
-
}
|
|
172
92
|
};
|
|
173
93
|
export {
|
|
174
94
|
GenerateWordPressAssetFileWebpackPlugin
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["// Inspired by \"Dependency Extraction Webpack Plugin\" by @wordpress team.\n// Link: https://github.com/WordPress/gutenberg/tree/trunk/packages/dependency-extraction-webpack-plugin\nimport { sources, Compilation, Compiler, Chunk } from 'webpack';\n\ntype HandlesMap = {\n\texact: Record<string, string>;\n\tstartsWith: Record<string, string>;\n}\n\ntype Options = {\n\thandlePrefix: string;\n\thandlesMap?: Partial<HandlesMap>\n\tapps?: string[];\n\textensions?: string[];\n\ti18n?: {\n\t\tdomain: string;\n\t\treplaceRequestedFile?: boolean;\n\t}\n}\n\ntype NormalizedOptions = {\n\thandlePrefix: string;\n\thandlesMap: HandlesMap;\n\tapps: string[];\n\textensions: string[];\n\ti18n: {\n\t\tdomain: string | null;\n\t\treplaceRequestedFile: boolean;\n\t}\n}\n\ntype Module = {\n\tuserRequest?: string;\n\tmodules?: Module[];\n}\n\nconst baseHandlesMap: HandlesMap = {\n\texact: {\n\t\treact: 'react',\n\t\t'react-dom': 'react-dom',\n\t},\n\tstartsWith: {\n\t\t'@elementor/': 'elementor-packages-',\n\t\t'@wordpress/': 'wp-',\n\t},\n};\n\nexport class GenerateWordPressAssetFileWebpackPlugin {\n\toptions: NormalizedOptions;\n\n\tconstructor( options: Options ) {\n\t\tthis.options = this.normalizeOptions( options );\n\t}\n\n\tapply( compiler: Compiler ) {\n\t\tcompiler.hooks.thisCompilation.tap( this.constructor.name, ( compilation ) => {\n\t\t\tlet handlesAssetsMap: Record<string, string>;\n\n\t\t\tcompilation.hooks.processAssets.tap( { name: this.constructor.name }, () => {\n\t\t\t\thandlesAssetsMap = [ ...compilation.entrypoints ].reduce<Record<string, string>>( ( map, [ entryName, entrypoint ] ) => {\n\t\t\t\t\tconst chunk = entrypoint.chunks.find( ( { name } ) => name === entryName );\n\n\t\t\t\t\tif ( ! chunk ) {\n\t\t\t\t\t\treturn map;\n\t\t\t\t\t}\n\n\t\t\t\t\tconst chunkJSFile = this.getFileFromChunk( chunk );\n\n\t\t\t\t\tif ( ! chunkJSFile ) {\n\t\t\t\t\t\treturn map;\n\t\t\t\t\t}\n\n\t\t\t\t\tconst deps = this.getDepsFromChunk( compilation, chunk );\n\n\t\t\t\t\tconst assetFilename = this.generateAssetsFileName(\n\t\t\t\t\t\tcompilation.getPath( '[file]', { filename: chunkJSFile } )\n\t\t\t\t\t);\n\n\t\t\t\t\tconst handle = this.generateHandleName( entryName );\n\n\t\t\t\t\tconst content = this.createAssetsFileContent( {\n\t\t\t\t\t\tdeps,\n\t\t\t\t\t\tentryName,\n\t\t\t\t\t\ti18n: this.options.i18n,\n\t\t\t\t\t} );\n\n\t\t\t\t\t// Add source and file into compilation for webpack to output.\n\t\t\t\t\tcompilation.assets[ assetFilename ] = new sources.RawSource( content );\n\n\t\t\t\t\tchunk.files.add( assetFilename );\n\n\t\t\t\t\tmap[ handle ] = assetFilename;\n\n\t\t\t\t\treturn map;\n\t\t\t\t}, {} );\n\t\t\t} );\n\n\t\t\tcompilation.hooks.afterProcessAssets.tap( { name: this.constructor.name }, () => {\n\t\t\t\tconst loaderFileContent = this.getLoaderFileContent( handlesAssetsMap );\n\n\t\t\t\tcompilation.assets[ 'loader.php' ] = new sources.RawSource( loaderFileContent );\n\t\t\t} );\n\t\t} );\n\t}\n\n\tgetDepsFromChunk( compilation: Compilation, chunk: Chunk ) {\n\t\tconst depsSet = new Set<string>();\n\n\t\tcompilation.chunkGraph.getChunkModules( chunk ).forEach( ( module ) => {\n\t\t\t// There are some issues with types in webpack, so we need to cast it.\n\t\t\tconst theModule = module as Module;\n\n\t\t\t[ ...( theModule.modules || [] ), theModule ].forEach( ( subModule ) => {\n\t\t\t\tif ( subModule.userRequest && this.isExternalDep( subModule.userRequest ) ) {\n\t\t\t\t\tdepsSet.add( subModule.userRequest );\n\t\t\t\t}\n\t\t\t} );\n\t\t} );\n\n\t\treturn depsSet;\n\t}\n\n\tcreateAssetsFileContent( {\n\t\tdeps,\n\t\ti18n,\n\t\tentryName,\n\t}: {\n\t\tdeps: Set<string>;\n\t\ti18n: NormalizedOptions[ 'i18n' ];\n\t\tentryName: string;\n\t} ) {\n\t\tconst handleName = this.generateHandleName( entryName );\n\t\tconst type = this.getEntryType( entryName );\n\n\t\tconst depsAsString = [ ...deps ]\n\t\t\t.map( ( dep ) => this.getHandleFromDep( dep ) )\n\t\t\t.filter( ( dep ) => dep !== handleName )\n\t\t\t.sort()\n\t\t\t.map( ( dep ) => `'${ dep }',` )\n\t\t\t.join( '\\n\\t\\t' );\n\n\t\tconst i18nContent = i18n.domain ? `[\n\t\t'domain' => '${ i18n.domain }',\n\t\t'replace_requested_file' => ${ ( i18n.replaceRequestedFile ?? false ).toString() },\n\t]` : '[]';\n\n\t\tconst content =\n\t\t\t`<?php\nif ( ! defined( 'ABSPATH' ) ) {\n\texit;\n}\n/**\n * This file is generated by Webpack, do not edit it directly.\n */\nreturn [\n\t'handle' => '${ handleName }',\n\t'src' => plugins_url( '/', __FILE__ ) . '${ entryName }{{MIN_SUFFIX}}.js',\n\t'i18n' => ${ i18nContent },\n\t'type' => '${ type }',\n\t'deps' => [\n\t\t${ depsAsString }\n\t],\n];\n`;\n\n\t\treturn content;\n\t}\n\n\tgetLoaderFileContent( entriesData: Record<string, string> ) {\n\t\tconst entriesContent = Object.entries( entriesData ).map( ( [ handle, assetFileName ] ) => {\n\t\t\treturn `\n\t$data['${ handle }'] = require __DIR__ . '/${ assetFileName }';`;\n\t\t} );\n\n\t\treturn `<?php\nif ( ! defined( 'ABSPATH' ) ) {\n\texit;\n}\n/**\n * This file is generated by Webpack, do not edit it directly.\n */\nadd_filter( 'elementor/editor-v2/packages/config', function( $data ) {\n${ entriesContent.join( '\\n' ) }\n\treturn $data;\n} );\n`;\n\t}\n\n\tgetEntryType( entryName: string ) {\n\t\tif ( this.options.extensions.includes( entryName ) ) {\n\t\t\treturn 'extension';\n\t\t}\n\n\t\tif ( this.options.apps.includes( entryName ) ) {\n\t\t\treturn 'app';\n\t\t}\n\n\t\treturn 'util';\n\t}\n\n\tgetFileFromChunk( chunk: Chunk ) {\n\t\treturn [ ...chunk.files ].find( ( f ) => /\\.js$/i.test( f ) );\n\t}\n\n\tisExternalDep( request: string ) {\n\t\tconst { startsWith, exact } = this.options.handlesMap;\n\n\t\treturn request && (\n\t\t\tObject.keys( exact ).includes( request ) ||\n\t\t\tObject.keys( startsWith ).some( ( dep ) => request.startsWith( dep ) )\n\t\t);\n\t}\n\n\tgetHandleFromDep( dep: string ) {\n\t\tconst { startsWith, exact } = this.options.handlesMap;\n\n\t\tif ( Object.keys( exact ).includes( dep ) ) {\n\t\t\treturn exact[ dep ];\n\t\t}\n\n\t\tfor ( const [ key, value ] of Object.entries( startsWith ) ) {\n\t\t\tif ( dep.startsWith( key ) ) {\n\t\t\t\treturn dep.replace( key, value );\n\t\t\t}\n\t\t}\n\n\t\treturn dep;\n\t}\n\n\tgenerateHandleName( name: string ) {\n\t\tif ( this.options.handlePrefix ) {\n\t\t\treturn `${ this.options.handlePrefix }${ name }`;\n\t\t}\n\n\t\treturn name;\n\t}\n\n\tgenerateAssetsFileName( filename: string ) {\n\t\treturn filename.replace( /(\\.min)?\\.js$/i, '.asset.php' );\n\t}\n\n\tnormalizeOptions( options: Options ): NormalizedOptions {\n\t\treturn {\n\t\t\t...options,\n\t\t\thandlesMap: {\n\t\t\t\texact: {\n\t\t\t\t\t...baseHandlesMap.exact,\n\t\t\t\t\t...( options?.handlesMap?.exact || {} ),\n\t\t\t\t},\n\t\t\t\tstartsWith: {\n\t\t\t\t\t...baseHandlesMap.startsWith,\n\t\t\t\t\t...( options?.handlesMap?.startsWith || {} ),\n\t\t\t\t},\n\t\t\t},\n\t\t\tapps: options?.apps || [],\n\t\t\textensions: options?.extensions || [],\n\t\t\ti18n: {\n\t\t\t\tdomain: options?.i18n?.domain || null,\n\t\t\t\treplaceRequestedFile: options?.i18n?.replaceRequestedFile ?? false,\n\t\t\t},\n\t\t};\n\t}\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/plugin.ts","../src/utils.ts"],"sourcesContent":["// Inspired by \"Dependency Extraction Webpack Plugin\" by @wordpress team.\n// Link: https://github.com/WordPress/gutenberg/tree/trunk/packages/dependency-extraction-webpack-plugin\nimport { sources, Compilation, Compiler, Chunk } from 'webpack';\nimport { createAssetFilePath, getAssetFileContent, transformRequestToHandle } from './utils';\nimport { RequestToHandleMap } from './types';\n\ntype Options = {\n\thandle: ( entryName: string ) => string;\n\tmap: RequestToHandleMap\n}\n\ntype Module = {\n\tuserRequest?: string;\n\tmodules?: Module[];\n}\n\nexport default class GenerateWordPressAssetFileWebpackPlugin {\n\toptions: Options;\n\n\tconstructor( options: Options ) {\n\t\tthis.options = options;\n\t}\n\n\tapply( compiler: Compiler ) {\n\t\tcompiler.hooks.thisCompilation.tap( this.constructor.name, ( compilation ) => {\n\t\t\tcompilation.hooks.processAssets.tap( { name: this.constructor.name }, () => {\n\t\t\t\t[ ...compilation.entrypoints ].forEach( ( [ entryName, entrypoint ] ) => {\n\t\t\t\t\tconst chunk = entrypoint.chunks.find( ( { name } ) => name === entryName );\n\n\t\t\t\t\tif ( ! chunk ) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\tthis.addAssetFileToEntrypoint( compilation, entryName, chunk );\n\t\t\t\t} );\n\t\t\t} );\n\t\t} );\n\t}\n\n\taddAssetFileToEntrypoint( compilation: Compilation, entryName: string, chunk: Chunk ) {\n\t\tconst chunkJSFile = this.getFileFromChunk( chunk );\n\n\t\tif ( ! chunkJSFile ) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst transformEntryNameToHandle = this.options.handle;\n\n\t\tconst entryHandle = transformEntryNameToHandle( entryName );\n\t\tconst depsHandles = this.getDepsHandlesFromChunk( compilation, chunk );\n\n\t\tconst assetFilePath = createAssetFilePath(\n\t\t\tcompilation.getPath( '[file]', { filename: chunkJSFile } )\n\t\t);\n\n\t\t// Add source and file into compilation for webpack to output.\n\t\tcompilation.assets[ assetFilePath ] = new sources.RawSource(\n\t\t\tgetAssetFileContent( entryHandle, depsHandles )\n\t\t);\n\n\t\tchunk.files.add( assetFilePath );\n\t}\n\n\tgetDepsHandlesFromChunk( compilation: Compilation, chunk: Chunk ) {\n\t\tconst depsSet = new Set<string>();\n\n\t\tcompilation.chunkGraph.getChunkModules( chunk ).forEach( ( module ) => {\n\t\t\t// There are some issues with types in webpack, so we need to cast it.\n\t\t\tconst theModule = module as Module;\n\n\t\t\t[ ...( theModule.modules || [] ), theModule ].forEach( ( subModule ) => {\n\t\t\t\tconst depHandle = transformRequestToHandle( subModule.userRequest, this.options.map );\n\n\t\t\t\tif ( depHandle ) {\n\t\t\t\t\tdepsSet.add( depHandle );\n\t\t\t\t}\n\t\t\t} );\n\t\t} );\n\n\t\treturn [ ...depsSet ];\n\t}\n\n\tgetFileFromChunk( chunk: Chunk ) {\n\t\treturn [ ...chunk.files ].find( ( f ) => /\\.js$/i.test( f ) );\n\t}\n}\n","import { RequestToHandleMap } from './types';\n\nexport function getAssetFileContent( entryHandle: string, depsHandles: string[] ) {\n\tconst depsAsString = depsHandles\n\t\t.filter( ( dep ) => dep !== entryHandle )\n\t\t.sort()\n\t\t.map( ( dep ) => `'${ dep }',` )\n\t\t.join( '\\n\\t\\t' );\n\n\treturn `<?php\nif ( ! defined( 'ABSPATH' ) ) {\n\texit;\n}\n/**\n * This file is generated by Webpack, do not edit it directly.\n */\nreturn [\n\t'handle' => '${ entryHandle }',\n\t'deps' => [\n\t\t${ depsAsString }\n\t],\n];\n`;\n}\n\nexport function transformRequestToHandle( request: string | undefined, map: RequestToHandleMap ) {\n\tif ( ! request ) {\n\t\treturn request;\n\t}\n\n\tfor ( const item of map ) {\n\t\tlet { request: requestRegex, handle } = item;\n\n\t\tif ( ! ( requestRegex instanceof RegExp ) ) {\n\t\t\trequestRegex = new RegExp( `^${ requestRegex }$` );\n\t\t}\n\n\t\tconst matches = request.match( requestRegex );\n\n\t\tif ( matches ) {\n\t\t\treturn request.replace( requestRegex, handle );\n\t\t}\n\t}\n}\n\nexport function createAssetFilePath( path: string, suffix = '.asset.php' ) {\n\treturn path.replace( /(\\.min)?\\.js$/i, suffix );\n}\n"],"mappings":";AAEA,SAAS,eAA6C;;;ACA/C,SAAS,oBAAqB,aAAqB,aAAwB;AACjF,QAAM,eAAe,YACnB,OAAQ,CAAE,QAAS,QAAQ,WAAY,EACvC,KAAK,EACL,IAAK,CAAE,QAAS,IAAK,GAAI,IAAK,EAC9B,KAAM,MAAS;AAEjB,SAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,gBAQS,WAAY;AAAA;AAAA,IAExB,YAAa;AAAA;AAAA;AAAA;AAIlB;AAEO,SAAS,yBAA0B,SAA6B,KAA0B;AAChG,MAAK,CAAE,SAAU;AAChB,WAAO;AAAA,EACR;AAEA,aAAY,QAAQ,KAAM;AACzB,QAAI,EAAE,SAAS,cAAc,OAAO,IAAI;AAExC,QAAK,EAAI,wBAAwB,SAAW;AAC3C,qBAAe,IAAI,OAAQ,IAAK,YAAa,GAAI;AAAA,IAClD;AAEA,UAAM,UAAU,QAAQ,MAAO,YAAa;AAE5C,QAAK,SAAU;AACd,aAAO,QAAQ,QAAS,cAAc,MAAO;AAAA,IAC9C;AAAA,EACD;AACD;AAEO,SAAS,oBAAqB,MAAc,SAAS,cAAe;AAC1E,SAAO,KAAK,QAAS,kBAAkB,MAAO;AAC/C;;;AD/BA,IAAqB,0CAArB,MAA6D;AAAA,EAC5D;AAAA,EAEA,YAAa,SAAmB;AAC/B,SAAK,UAAU;AAAA,EAChB;AAAA,EAEA,MAAO,UAAqB;AAC3B,aAAS,MAAM,gBAAgB,IAAK,KAAK,YAAY,MAAM,CAAE,gBAAiB;AAC7E,kBAAY,MAAM,cAAc,IAAK,EAAE,MAAM,KAAK,YAAY,KAAK,GAAG,MAAM;AAC3E,SAAE,GAAG,YAAY,WAAY,EAAE,QAAS,CAAE,CAAE,WAAW,UAAW,MAAO;AACxE,gBAAM,QAAQ,WAAW,OAAO,KAAM,CAAE,EAAE,KAAK,MAAO,SAAS,SAAU;AAEzE,cAAK,CAAE,OAAQ;AACd;AAAA,UACD;AAEA,eAAK,yBAA0B,aAAa,WAAW,KAAM;AAAA,QAC9D,CAAE;AAAA,MACH,CAAE;AAAA,IACH,CAAE;AAAA,EACH;AAAA,EAEA,yBAA0B,aAA0B,WAAmB,OAAe;AACrF,UAAM,cAAc,KAAK,iBAAkB,KAAM;AAEjD,QAAK,CAAE,aAAc;AACpB;AAAA,IACD;AAEA,UAAM,6BAA6B,KAAK,QAAQ;AAEhD,UAAM,cAAc,2BAA4B,SAAU;AAC1D,UAAM,cAAc,KAAK,wBAAyB,aAAa,KAAM;AAErE,UAAM,gBAAgB;AAAA,MACrB,YAAY,QAAS,UAAU,EAAE,UAAU,YAAY,CAAE;AAAA,IAC1D;AAGA,gBAAY,OAAQ,aAAc,IAAI,IAAI,QAAQ;AAAA,MACjD,oBAAqB,aAAa,WAAY;AAAA,IAC/C;AAEA,UAAM,MAAM,IAAK,aAAc;AAAA,EAChC;AAAA,EAEA,wBAAyB,aAA0B,OAAe;AACjE,UAAM,UAAU,oBAAI,IAAY;AAEhC,gBAAY,WAAW,gBAAiB,KAAM,EAAE,QAAS,CAAE,WAAY;AAEtE,YAAM,YAAY;AAElB,OAAE,GAAK,UAAU,WAAW,CAAC,GAAK,SAAU,EAAE,QAAS,CAAE,cAAe;AACvE,cAAM,YAAY,yBAA0B,UAAU,aAAa,KAAK,QAAQ,GAAI;AAEpF,YAAK,WAAY;AAChB,kBAAQ,IAAK,SAAU;AAAA,QACxB;AAAA,MACD,CAAE;AAAA,IACH,CAAE;AAEF,WAAO,CAAE,GAAG,OAAQ;AAAA,EACrB;AAAA,EAEA,iBAAkB,OAAe;AAChC,WAAO,CAAE,GAAG,MAAM,KAAM,EAAE,KAAM,CAAE,MAAO,SAAS,KAAM,CAAE,CAAE;AAAA,EAC7D;AACD;","names":[]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@elementor/generate-wordpress-asset-file-webpack-plugin",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"author": "Elementor Team",
|
|
6
6
|
"homepage": "https://elementor.com/",
|
|
@@ -34,5 +34,5 @@
|
|
|
34
34
|
"peerDependencies": {
|
|
35
35
|
"webpack": "5.x"
|
|
36
36
|
},
|
|
37
|
-
"gitHead": "
|
|
37
|
+
"gitHead": "7fd9a516887f8bdb3479c54a48dafcb12bb41db7"
|
|
38
38
|
}
|
|
@@ -9,15 +9,11 @@ if ( ! defined( 'ABSPATH' ) ) {
|
|
|
9
9
|
* This file is generated by Webpack, do not edit it directly.
|
|
10
10
|
*/
|
|
11
11
|
return [
|
|
12
|
-
'handle' => 'elementor-
|
|
13
|
-
'src' => plugins_url( '/', __FILE__ ) . 'app{{MIN_SUFFIX}}.js',
|
|
14
|
-
'i18n' => [
|
|
15
|
-
'domain' => 'elementor-test',
|
|
16
|
-
'replace_requested_file' => true,
|
|
17
|
-
],
|
|
18
|
-
'type' => 'app',
|
|
12
|
+
'handle' => 'elementor-packages-app',
|
|
19
13
|
'deps' => [
|
|
20
|
-
'elementor-editor',
|
|
14
|
+
'elementor-packages-editor',
|
|
15
|
+
'react',
|
|
16
|
+
'react-dom',
|
|
21
17
|
'wp-element',
|
|
22
18
|
],
|
|
23
19
|
];
|
|
@@ -33,41 +29,17 @@ if ( ! defined( 'ABSPATH' ) ) {
|
|
|
33
29
|
* This file is generated by Webpack, do not edit it directly.
|
|
34
30
|
*/
|
|
35
31
|
return [
|
|
36
|
-
'handle' => 'elementor-
|
|
37
|
-
'src' => plugins_url( '/', __FILE__ ) . 'extension{{MIN_SUFFIX}}.js',
|
|
38
|
-
'i18n' => [
|
|
39
|
-
'domain' => 'elementor-test',
|
|
40
|
-
'replace_requested_file' => true,
|
|
41
|
-
],
|
|
42
|
-
'type' => 'extension',
|
|
32
|
+
'handle' => 'elementor-packages-extension',
|
|
43
33
|
'deps' => [
|
|
44
|
-
'elementor-editor',
|
|
34
|
+
'elementor-packages-editor',
|
|
35
|
+
'react',
|
|
36
|
+
'react-dom',
|
|
45
37
|
'wp-element',
|
|
46
38
|
],
|
|
47
39
|
];
|
|
48
40
|
"
|
|
49
41
|
`;
|
|
50
42
|
|
|
51
|
-
exports[`@elementor/generate-wordpress-asset-file-webpack-plugin should generate assets files: loader.php 1`] = `
|
|
52
|
-
"<?php
|
|
53
|
-
if ( ! defined( 'ABSPATH' ) ) {
|
|
54
|
-
exit;
|
|
55
|
-
}
|
|
56
|
-
/**
|
|
57
|
-
* This file is generated by Webpack, do not edit it directly.
|
|
58
|
-
*/
|
|
59
|
-
add_filter( 'elementor/editor-v2/packages/config', function( $data ) {
|
|
60
|
-
|
|
61
|
-
$data['elementor-test-app'] = require __DIR__ . '/app.asset.php';
|
|
62
|
-
|
|
63
|
-
$data['elementor-test-extension'] = require __DIR__ . '/extension.asset.php';
|
|
64
|
-
|
|
65
|
-
$data['elementor-test-util'] = require __DIR__ . '/util.asset.php';
|
|
66
|
-
return $data;
|
|
67
|
-
} );
|
|
68
|
-
"
|
|
69
|
-
`;
|
|
70
|
-
|
|
71
43
|
exports[`@elementor/generate-wordpress-asset-file-webpack-plugin should generate assets files: util.asset.php 1`] = `
|
|
72
44
|
"<?php
|
|
73
45
|
if ( ! defined( 'ABSPATH' ) ) {
|
|
@@ -77,15 +49,11 @@ if ( ! defined( 'ABSPATH' ) ) {
|
|
|
77
49
|
* This file is generated by Webpack, do not edit it directly.
|
|
78
50
|
*/
|
|
79
51
|
return [
|
|
80
|
-
'handle' => 'elementor-
|
|
81
|
-
'src' => plugins_url( '/', __FILE__ ) . 'util{{MIN_SUFFIX}}.js',
|
|
82
|
-
'i18n' => [
|
|
83
|
-
'domain' => 'elementor-test',
|
|
84
|
-
'replace_requested_file' => true,
|
|
85
|
-
],
|
|
86
|
-
'type' => 'util',
|
|
52
|
+
'handle' => 'elementor-packages-util',
|
|
87
53
|
'deps' => [
|
|
88
|
-
'elementor-editor',
|
|
54
|
+
'elementor-packages-editor',
|
|
55
|
+
'react',
|
|
56
|
+
'react-dom',
|
|
89
57
|
'wp-element',
|
|
90
58
|
],
|
|
91
59
|
];
|
|
@@ -16,6 +16,8 @@ describe( '@elementor/generate-wordpress-asset-file-webpack-plugin', () => {
|
|
|
16
16
|
import elementor from '@elementor/editor';
|
|
17
17
|
import wp from '@wordpress/element';
|
|
18
18
|
import other from '@other/package';
|
|
19
|
+
import react from 'react';
|
|
20
|
+
import ReactDOM from 'react-dom';
|
|
19
21
|
|
|
20
22
|
elementor();
|
|
21
23
|
wp();
|
|
@@ -49,30 +51,24 @@ describe( '@elementor/generate-wordpress-asset-file-webpack-plugin', () => {
|
|
|
49
51
|
'@elementor/editor': 'editor',
|
|
50
52
|
'@wordpress/element': 'wp',
|
|
51
53
|
'@other/package': 'other',
|
|
54
|
+
react: 'react',
|
|
55
|
+
'react-dom': 'reactDOM',
|
|
52
56
|
},
|
|
53
57
|
plugins: [
|
|
54
58
|
new GenerateWordPressAssetFileWebpackPlugin( {
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
startsWith: {
|
|
63
|
-
'@wordpress/': 'wp-',
|
|
64
|
-
},
|
|
65
|
-
},
|
|
66
|
-
i18n: {
|
|
67
|
-
domain: 'elementor-test',
|
|
68
|
-
replaceRequestedFile: true,
|
|
69
|
-
},
|
|
59
|
+
handle: ( entryName ) => `elementor-packages-${ entryName }`,
|
|
60
|
+
map: [
|
|
61
|
+
{ request: 'react', handle: 'react' },
|
|
62
|
+
{ request: 'react-dom', handle: 'react-dom' },
|
|
63
|
+
{ request: /^@elementor\/(.+)$/, handle: 'elementor-packages-$1' },
|
|
64
|
+
{ request: /^@wordpress\/(.+)$/, handle: 'wp-$1' },
|
|
65
|
+
],
|
|
70
66
|
} ),
|
|
71
67
|
],
|
|
72
68
|
} );
|
|
73
69
|
|
|
74
70
|
// Expect.
|
|
75
|
-
expect.assertions(
|
|
71
|
+
expect.assertions( 6 );
|
|
76
72
|
|
|
77
73
|
// Act.
|
|
78
74
|
compiler.run( ( err, stats ) => {
|
|
@@ -85,7 +81,6 @@ describe( '@elementor/generate-wordpress-asset-file-webpack-plugin', () => {
|
|
|
85
81
|
'app.asset.php',
|
|
86
82
|
'extension.asset.php',
|
|
87
83
|
'util.asset.php',
|
|
88
|
-
'loader.php',
|
|
89
84
|
];
|
|
90
85
|
|
|
91
86
|
files.forEach( ( fileName ) => {
|
package/src/index.ts
CHANGED
|
@@ -1,263 +1 @@
|
|
|
1
|
-
|
|
2
|
-
// Link: https://github.com/WordPress/gutenberg/tree/trunk/packages/dependency-extraction-webpack-plugin
|
|
3
|
-
import { sources, Compilation, Compiler, Chunk } from 'webpack';
|
|
4
|
-
|
|
5
|
-
type HandlesMap = {
|
|
6
|
-
exact: Record<string, string>;
|
|
7
|
-
startsWith: Record<string, string>;
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
type Options = {
|
|
11
|
-
handlePrefix: string;
|
|
12
|
-
handlesMap?: Partial<HandlesMap>
|
|
13
|
-
apps?: string[];
|
|
14
|
-
extensions?: string[];
|
|
15
|
-
i18n?: {
|
|
16
|
-
domain: string;
|
|
17
|
-
replaceRequestedFile?: boolean;
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
type NormalizedOptions = {
|
|
22
|
-
handlePrefix: string;
|
|
23
|
-
handlesMap: HandlesMap;
|
|
24
|
-
apps: string[];
|
|
25
|
-
extensions: string[];
|
|
26
|
-
i18n: {
|
|
27
|
-
domain: string | null;
|
|
28
|
-
replaceRequestedFile: boolean;
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
type Module = {
|
|
33
|
-
userRequest?: string;
|
|
34
|
-
modules?: Module[];
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
const baseHandlesMap: HandlesMap = {
|
|
38
|
-
exact: {
|
|
39
|
-
react: 'react',
|
|
40
|
-
'react-dom': 'react-dom',
|
|
41
|
-
},
|
|
42
|
-
startsWith: {
|
|
43
|
-
'@elementor/': 'elementor-packages-',
|
|
44
|
-
'@wordpress/': 'wp-',
|
|
45
|
-
},
|
|
46
|
-
};
|
|
47
|
-
|
|
48
|
-
export class GenerateWordPressAssetFileWebpackPlugin {
|
|
49
|
-
options: NormalizedOptions;
|
|
50
|
-
|
|
51
|
-
constructor( options: Options ) {
|
|
52
|
-
this.options = this.normalizeOptions( options );
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
apply( compiler: Compiler ) {
|
|
56
|
-
compiler.hooks.thisCompilation.tap( this.constructor.name, ( compilation ) => {
|
|
57
|
-
let handlesAssetsMap: Record<string, string>;
|
|
58
|
-
|
|
59
|
-
compilation.hooks.processAssets.tap( { name: this.constructor.name }, () => {
|
|
60
|
-
handlesAssetsMap = [ ...compilation.entrypoints ].reduce<Record<string, string>>( ( map, [ entryName, entrypoint ] ) => {
|
|
61
|
-
const chunk = entrypoint.chunks.find( ( { name } ) => name === entryName );
|
|
62
|
-
|
|
63
|
-
if ( ! chunk ) {
|
|
64
|
-
return map;
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
const chunkJSFile = this.getFileFromChunk( chunk );
|
|
68
|
-
|
|
69
|
-
if ( ! chunkJSFile ) {
|
|
70
|
-
return map;
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
const deps = this.getDepsFromChunk( compilation, chunk );
|
|
74
|
-
|
|
75
|
-
const assetFilename = this.generateAssetsFileName(
|
|
76
|
-
compilation.getPath( '[file]', { filename: chunkJSFile } )
|
|
77
|
-
);
|
|
78
|
-
|
|
79
|
-
const handle = this.generateHandleName( entryName );
|
|
80
|
-
|
|
81
|
-
const content = this.createAssetsFileContent( {
|
|
82
|
-
deps,
|
|
83
|
-
entryName,
|
|
84
|
-
i18n: this.options.i18n,
|
|
85
|
-
} );
|
|
86
|
-
|
|
87
|
-
// Add source and file into compilation for webpack to output.
|
|
88
|
-
compilation.assets[ assetFilename ] = new sources.RawSource( content );
|
|
89
|
-
|
|
90
|
-
chunk.files.add( assetFilename );
|
|
91
|
-
|
|
92
|
-
map[ handle ] = assetFilename;
|
|
93
|
-
|
|
94
|
-
return map;
|
|
95
|
-
}, {} );
|
|
96
|
-
} );
|
|
97
|
-
|
|
98
|
-
compilation.hooks.afterProcessAssets.tap( { name: this.constructor.name }, () => {
|
|
99
|
-
const loaderFileContent = this.getLoaderFileContent( handlesAssetsMap );
|
|
100
|
-
|
|
101
|
-
compilation.assets[ 'loader.php' ] = new sources.RawSource( loaderFileContent );
|
|
102
|
-
} );
|
|
103
|
-
} );
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
getDepsFromChunk( compilation: Compilation, chunk: Chunk ) {
|
|
107
|
-
const depsSet = new Set<string>();
|
|
108
|
-
|
|
109
|
-
compilation.chunkGraph.getChunkModules( chunk ).forEach( ( module ) => {
|
|
110
|
-
// There are some issues with types in webpack, so we need to cast it.
|
|
111
|
-
const theModule = module as Module;
|
|
112
|
-
|
|
113
|
-
[ ...( theModule.modules || [] ), theModule ].forEach( ( subModule ) => {
|
|
114
|
-
if ( subModule.userRequest && this.isExternalDep( subModule.userRequest ) ) {
|
|
115
|
-
depsSet.add( subModule.userRequest );
|
|
116
|
-
}
|
|
117
|
-
} );
|
|
118
|
-
} );
|
|
119
|
-
|
|
120
|
-
return depsSet;
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
createAssetsFileContent( {
|
|
124
|
-
deps,
|
|
125
|
-
i18n,
|
|
126
|
-
entryName,
|
|
127
|
-
}: {
|
|
128
|
-
deps: Set<string>;
|
|
129
|
-
i18n: NormalizedOptions[ 'i18n' ];
|
|
130
|
-
entryName: string;
|
|
131
|
-
} ) {
|
|
132
|
-
const handleName = this.generateHandleName( entryName );
|
|
133
|
-
const type = this.getEntryType( entryName );
|
|
134
|
-
|
|
135
|
-
const depsAsString = [ ...deps ]
|
|
136
|
-
.map( ( dep ) => this.getHandleFromDep( dep ) )
|
|
137
|
-
.filter( ( dep ) => dep !== handleName )
|
|
138
|
-
.sort()
|
|
139
|
-
.map( ( dep ) => `'${ dep }',` )
|
|
140
|
-
.join( '\n\t\t' );
|
|
141
|
-
|
|
142
|
-
const i18nContent = i18n.domain ? `[
|
|
143
|
-
'domain' => '${ i18n.domain }',
|
|
144
|
-
'replace_requested_file' => ${ ( i18n.replaceRequestedFile ?? false ).toString() },
|
|
145
|
-
]` : '[]';
|
|
146
|
-
|
|
147
|
-
const content =
|
|
148
|
-
`<?php
|
|
149
|
-
if ( ! defined( 'ABSPATH' ) ) {
|
|
150
|
-
exit;
|
|
151
|
-
}
|
|
152
|
-
/**
|
|
153
|
-
* This file is generated by Webpack, do not edit it directly.
|
|
154
|
-
*/
|
|
155
|
-
return [
|
|
156
|
-
'handle' => '${ handleName }',
|
|
157
|
-
'src' => plugins_url( '/', __FILE__ ) . '${ entryName }{{MIN_SUFFIX}}.js',
|
|
158
|
-
'i18n' => ${ i18nContent },
|
|
159
|
-
'type' => '${ type }',
|
|
160
|
-
'deps' => [
|
|
161
|
-
${ depsAsString }
|
|
162
|
-
],
|
|
163
|
-
];
|
|
164
|
-
`;
|
|
165
|
-
|
|
166
|
-
return content;
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
getLoaderFileContent( entriesData: Record<string, string> ) {
|
|
170
|
-
const entriesContent = Object.entries( entriesData ).map( ( [ handle, assetFileName ] ) => {
|
|
171
|
-
return `
|
|
172
|
-
$data['${ handle }'] = require __DIR__ . '/${ assetFileName }';`;
|
|
173
|
-
} );
|
|
174
|
-
|
|
175
|
-
return `<?php
|
|
176
|
-
if ( ! defined( 'ABSPATH' ) ) {
|
|
177
|
-
exit;
|
|
178
|
-
}
|
|
179
|
-
/**
|
|
180
|
-
* This file is generated by Webpack, do not edit it directly.
|
|
181
|
-
*/
|
|
182
|
-
add_filter( 'elementor/editor-v2/packages/config', function( $data ) {
|
|
183
|
-
${ entriesContent.join( '\n' ) }
|
|
184
|
-
return $data;
|
|
185
|
-
} );
|
|
186
|
-
`;
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
getEntryType( entryName: string ) {
|
|
190
|
-
if ( this.options.extensions.includes( entryName ) ) {
|
|
191
|
-
return 'extension';
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
if ( this.options.apps.includes( entryName ) ) {
|
|
195
|
-
return 'app';
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
return 'util';
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
getFileFromChunk( chunk: Chunk ) {
|
|
202
|
-
return [ ...chunk.files ].find( ( f ) => /\.js$/i.test( f ) );
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
isExternalDep( request: string ) {
|
|
206
|
-
const { startsWith, exact } = this.options.handlesMap;
|
|
207
|
-
|
|
208
|
-
return request && (
|
|
209
|
-
Object.keys( exact ).includes( request ) ||
|
|
210
|
-
Object.keys( startsWith ).some( ( dep ) => request.startsWith( dep ) )
|
|
211
|
-
);
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
getHandleFromDep( dep: string ) {
|
|
215
|
-
const { startsWith, exact } = this.options.handlesMap;
|
|
216
|
-
|
|
217
|
-
if ( Object.keys( exact ).includes( dep ) ) {
|
|
218
|
-
return exact[ dep ];
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
for ( const [ key, value ] of Object.entries( startsWith ) ) {
|
|
222
|
-
if ( dep.startsWith( key ) ) {
|
|
223
|
-
return dep.replace( key, value );
|
|
224
|
-
}
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
return dep;
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
generateHandleName( name: string ) {
|
|
231
|
-
if ( this.options.handlePrefix ) {
|
|
232
|
-
return `${ this.options.handlePrefix }${ name }`;
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
return name;
|
|
236
|
-
}
|
|
237
|
-
|
|
238
|
-
generateAssetsFileName( filename: string ) {
|
|
239
|
-
return filename.replace( /(\.min)?\.js$/i, '.asset.php' );
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
normalizeOptions( options: Options ): NormalizedOptions {
|
|
243
|
-
return {
|
|
244
|
-
...options,
|
|
245
|
-
handlesMap: {
|
|
246
|
-
exact: {
|
|
247
|
-
...baseHandlesMap.exact,
|
|
248
|
-
...( options?.handlesMap?.exact || {} ),
|
|
249
|
-
},
|
|
250
|
-
startsWith: {
|
|
251
|
-
...baseHandlesMap.startsWith,
|
|
252
|
-
...( options?.handlesMap?.startsWith || {} ),
|
|
253
|
-
},
|
|
254
|
-
},
|
|
255
|
-
apps: options?.apps || [],
|
|
256
|
-
extensions: options?.extensions || [],
|
|
257
|
-
i18n: {
|
|
258
|
-
domain: options?.i18n?.domain || null,
|
|
259
|
-
replaceRequestedFile: options?.i18n?.replaceRequestedFile ?? false,
|
|
260
|
-
},
|
|
261
|
-
};
|
|
262
|
-
}
|
|
263
|
-
}
|
|
1
|
+
export { default as GenerateWordPressAssetFileWebpackPlugin } from './plugin';
|
package/src/plugin.ts
ADDED
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
// Inspired by "Dependency Extraction Webpack Plugin" by @wordpress team.
|
|
2
|
+
// Link: https://github.com/WordPress/gutenberg/tree/trunk/packages/dependency-extraction-webpack-plugin
|
|
3
|
+
import { sources, Compilation, Compiler, Chunk } from 'webpack';
|
|
4
|
+
import { createAssetFilePath, getAssetFileContent, transformRequestToHandle } from './utils';
|
|
5
|
+
import { RequestToHandleMap } from './types';
|
|
6
|
+
|
|
7
|
+
type Options = {
|
|
8
|
+
handle: ( entryName: string ) => string;
|
|
9
|
+
map: RequestToHandleMap
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
type Module = {
|
|
13
|
+
userRequest?: string;
|
|
14
|
+
modules?: Module[];
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export default class GenerateWordPressAssetFileWebpackPlugin {
|
|
18
|
+
options: Options;
|
|
19
|
+
|
|
20
|
+
constructor( options: Options ) {
|
|
21
|
+
this.options = options;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
apply( compiler: Compiler ) {
|
|
25
|
+
compiler.hooks.thisCompilation.tap( this.constructor.name, ( compilation ) => {
|
|
26
|
+
compilation.hooks.processAssets.tap( { name: this.constructor.name }, () => {
|
|
27
|
+
[ ...compilation.entrypoints ].forEach( ( [ entryName, entrypoint ] ) => {
|
|
28
|
+
const chunk = entrypoint.chunks.find( ( { name } ) => name === entryName );
|
|
29
|
+
|
|
30
|
+
if ( ! chunk ) {
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
this.addAssetFileToEntrypoint( compilation, entryName, chunk );
|
|
35
|
+
} );
|
|
36
|
+
} );
|
|
37
|
+
} );
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
addAssetFileToEntrypoint( compilation: Compilation, entryName: string, chunk: Chunk ) {
|
|
41
|
+
const chunkJSFile = this.getFileFromChunk( chunk );
|
|
42
|
+
|
|
43
|
+
if ( ! chunkJSFile ) {
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const transformEntryNameToHandle = this.options.handle;
|
|
48
|
+
|
|
49
|
+
const entryHandle = transformEntryNameToHandle( entryName );
|
|
50
|
+
const depsHandles = this.getDepsHandlesFromChunk( compilation, chunk );
|
|
51
|
+
|
|
52
|
+
const assetFilePath = createAssetFilePath(
|
|
53
|
+
compilation.getPath( '[file]', { filename: chunkJSFile } )
|
|
54
|
+
);
|
|
55
|
+
|
|
56
|
+
// Add source and file into compilation for webpack to output.
|
|
57
|
+
compilation.assets[ assetFilePath ] = new sources.RawSource(
|
|
58
|
+
getAssetFileContent( entryHandle, depsHandles )
|
|
59
|
+
);
|
|
60
|
+
|
|
61
|
+
chunk.files.add( assetFilePath );
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
getDepsHandlesFromChunk( compilation: Compilation, chunk: Chunk ) {
|
|
65
|
+
const depsSet = new Set<string>();
|
|
66
|
+
|
|
67
|
+
compilation.chunkGraph.getChunkModules( chunk ).forEach( ( module ) => {
|
|
68
|
+
// There are some issues with types in webpack, so we need to cast it.
|
|
69
|
+
const theModule = module as Module;
|
|
70
|
+
|
|
71
|
+
[ ...( theModule.modules || [] ), theModule ].forEach( ( subModule ) => {
|
|
72
|
+
const depHandle = transformRequestToHandle( subModule.userRequest, this.options.map );
|
|
73
|
+
|
|
74
|
+
if ( depHandle ) {
|
|
75
|
+
depsSet.add( depHandle );
|
|
76
|
+
}
|
|
77
|
+
} );
|
|
78
|
+
} );
|
|
79
|
+
|
|
80
|
+
return [ ...depsSet ];
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
getFileFromChunk( chunk: Chunk ) {
|
|
84
|
+
return [ ...chunk.files ].find( ( f ) => /\.js$/i.test( f ) );
|
|
85
|
+
}
|
|
86
|
+
}
|
package/src/types.ts
ADDED
package/src/utils.ts
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { RequestToHandleMap } from './types';
|
|
2
|
+
|
|
3
|
+
export function getAssetFileContent( entryHandle: string, depsHandles: string[] ) {
|
|
4
|
+
const depsAsString = depsHandles
|
|
5
|
+
.filter( ( dep ) => dep !== entryHandle )
|
|
6
|
+
.sort()
|
|
7
|
+
.map( ( dep ) => `'${ dep }',` )
|
|
8
|
+
.join( '\n\t\t' );
|
|
9
|
+
|
|
10
|
+
return `<?php
|
|
11
|
+
if ( ! defined( 'ABSPATH' ) ) {
|
|
12
|
+
exit;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* This file is generated by Webpack, do not edit it directly.
|
|
16
|
+
*/
|
|
17
|
+
return [
|
|
18
|
+
'handle' => '${ entryHandle }',
|
|
19
|
+
'deps' => [
|
|
20
|
+
${ depsAsString }
|
|
21
|
+
],
|
|
22
|
+
];
|
|
23
|
+
`;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export function transformRequestToHandle( request: string | undefined, map: RequestToHandleMap ) {
|
|
27
|
+
if ( ! request ) {
|
|
28
|
+
return request;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
for ( const item of map ) {
|
|
32
|
+
let { request: requestRegex, handle } = item;
|
|
33
|
+
|
|
34
|
+
if ( ! ( requestRegex instanceof RegExp ) ) {
|
|
35
|
+
requestRegex = new RegExp( `^${ requestRegex }$` );
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const matches = request.match( requestRegex );
|
|
39
|
+
|
|
40
|
+
if ( matches ) {
|
|
41
|
+
return request.replace( requestRegex, handle );
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export function createAssetFilePath( path: string, suffix = '.asset.php' ) {
|
|
47
|
+
return path.replace( /(\.min)?\.js$/i, suffix );
|
|
48
|
+
}
|