chisel-scripts 1.0.0 → 2.0.0-alpha.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.
Files changed (41) hide show
  1. package/CHANGELOG.md +17 -0
  2. package/README.md +0 -23
  3. package/bin/chisel-scripts.js +5 -23
  4. package/composer.phar +0 -0
  5. package/fetch-packages.js +30 -0
  6. package/index.js +60 -0
  7. package/lib/PluginAPI.js +4 -44
  8. package/lib/Service.js +25 -181
  9. package/lib/commands/add-page.js +92 -0
  10. package/lib/commands/composer.js +22 -0
  11. package/lib/commands/create-block/index.js +45 -0
  12. package/lib/commands/create-block/templates/README.md +5 -0
  13. package/lib/commands/create-block/templates/acf/block/edit.js.mustache +38 -0
  14. package/lib/commands/create-block/templates/acf/block/editor.scss.mustache +9 -0
  15. package/lib/commands/create-block/templates/acf/block/index.js.mustache +45 -0
  16. package/lib/commands/create-block/templates/acf/block/render.php.mustache +10 -0
  17. package/lib/commands/create-block/templates/acf/block/save.js.mustache +26 -0
  18. package/lib/commands/create-block/templates/acf/block/style.scss.mustache +12 -0
  19. package/lib/commands/create-block/templates/acf/block/view.js.mustache +25 -0
  20. package/lib/commands/create-block/templates/acf/index.js +3 -0
  21. package/lib/commands/wp-config.js +116 -0
  22. package/lib/commands/wp-scripts.mjs +70 -0
  23. package/lib/commands/wp.js +22 -0
  24. package/lib/extensions/stylesheets.mjs +51 -0
  25. package/lib/template/dev-vhost.chisel-tpl.conf +8 -0
  26. package/lib/template/wp-config-local.chisel-tpl.php +56 -0
  27. package/package.json +11 -37
  28. package/wp-cli.phar +0 -0
  29. package/lib/chisel.config.base.js +0 -31
  30. package/lib/commands/build/formatStats.js +0 -79
  31. package/lib/commands/build/index.js +0 -125
  32. package/lib/commands/inspect.js +0 -14
  33. package/lib/config/base.js +0 -201
  34. package/lib/config/css.js +0 -91
  35. package/lib/config/js.js +0 -52
  36. package/lib/generate-and-serialize-config.js +0 -9
  37. package/lib/webpack-loaders/sass-glob-loader.js +0 -41
  38. package/lib/webpack-plugins/DynamicPublicPath.js +0 -24
  39. package/lib/webpack-plugins/OptimizeCssnanoPlugin.js +0 -125
  40. package/webpack.config-sync.js +0 -16
  41. package/webpack.config.js +0 -9
@@ -1,79 +0,0 @@
1
- // https://github.com/vuejs/vue-cli/blob/dcfb0bdbc948d73371f70d650f0f808f81c51cc1/packages/%40vue/cli-service/lib/commands/build/formatStats.js#L1
2
-
3
- module.exports = function formatStats(stats, dir, assetsDir, api) {
4
- const fs = require('fs');
5
- const path = require('path');
6
- const zlib = require('zlib');
7
- const ui = require('cliui')({ width: 80 });
8
- const { chalk } = require('chisel-shared-utils');
9
-
10
- const json = stats.toJson({
11
- hash: false,
12
- modules: false,
13
- chunks: false,
14
- });
15
-
16
- let assets = json.assets
17
- ? json.assets
18
- : json.children.reduce((acc, child) => acc.concat(child.assets), []);
19
-
20
- const seenNames = new Map();
21
- const isJS = (val) => /\.js$/.test(val);
22
- const isCSS = (val) => /\.css$/.test(val);
23
- const isMinJS = (val) => /\.min\.js$/.test(val);
24
- assets = assets
25
- .map((a) => {
26
- [a.name] = a.name.split('?');
27
- return a;
28
- })
29
- .filter((a) => {
30
- if (seenNames.has(a.name)) {
31
- return false;
32
- }
33
- seenNames.set(a.name, true);
34
- return (isJS(a.name) || isCSS(a.name)) && !a.name.startsWith(assetsDir);
35
- })
36
- .sort((a, b) => {
37
- if (isJS(a.name) && isCSS(b.name)) return -1;
38
- if (isCSS(a.name) && isJS(b.name)) return 1;
39
- if (isMinJS(a.name) && !isMinJS(b.name)) return -1;
40
- if (!isMinJS(a.name) && isMinJS(b.name)) return 1;
41
- return b.size - a.size;
42
- });
43
-
44
- function formatSize(size) {
45
- return `${(size / 1024).toFixed(2)} KiB`;
46
- }
47
-
48
- function getGzippedSize(asset) {
49
- const filepath = api.resolve(path.join(dir, asset.name));
50
- const buffer = fs.readFileSync(filepath);
51
- return formatSize(zlib.gzipSync(buffer).length);
52
- }
53
-
54
- function makeRow(a, b, c) {
55
- return ` ${a}\t ${b}\t ${c}`;
56
- }
57
-
58
- ui.div(
59
- `${makeRow(
60
- chalk.cyan.bold(`File`),
61
- chalk.cyan.bold(`Size`),
62
- chalk.cyan.bold(`Gzipped`),
63
- )}\n\n${assets
64
- .map((asset) =>
65
- makeRow(
66
- /js$/.test(asset.name)
67
- ? chalk.green(asset.name)
68
- : chalk.blue(asset.name),
69
- formatSize(asset.size),
70
- getGzippedSize(asset),
71
- ),
72
- )
73
- .join(`\n`)}`,
74
- );
75
-
76
- return `${ui.toString()}\n\n ${chalk.gray(
77
- `Images and other types of assets omitted.`,
78
- )}\n`;
79
- };
@@ -1,125 +0,0 @@
1
- // TODO: no minify?
2
- // TODO: report
3
-
4
- module.exports = (api, options) => {
5
- api.registerCommand(
6
- 'build',
7
- (command) =>
8
- command
9
- .description('build for production')
10
- .option(
11
- '--no-clean',
12
- 'do not remove the dist directory before building the project',
13
- )
14
- .option('--watch', 'watch for changes')
15
- .option('--report', 'generate report to help analyze bundles content'),
16
- async (cmd) => {
17
- const path = require('path');
18
- const webpack = require('webpack');
19
- const { chalk } = require('chisel-shared-utils');
20
- const fs = require('fs-extra');
21
- const formatStats = require('./formatStats');
22
-
23
- process.env.NODE_ENV = 'production';
24
-
25
- if (cmd.clean) {
26
- await fs.remove(api.resolve(options.output.base));
27
- }
28
-
29
- const REPORT_ANALYZER_FILE_NAME = 'report-analyzer.html';
30
- api.chainWebpack((webpackConfig) => {
31
- if (cmd.report) {
32
- webpackConfig
33
- .plugin('webpack-bundle-analyzer')
34
- .use(require('webpack-bundle-analyzer').BundleAnalyzerPlugin, [
35
- {
36
- analyzerMode: 'static',
37
- reportFilename: REPORT_ANALYZER_FILE_NAME,
38
- openAnalyzer: false,
39
- },
40
- ]);
41
- }
42
- });
43
-
44
- const config = await api.service.resolveWebpackConfig();
45
-
46
- await new Promise((resolve, reject) => {
47
- const targetDir = api.resolve(options.output.base);
48
- config.watch = Boolean(cmd.watch);
49
-
50
- webpack(config, (err, stats) => {
51
- if (err) {
52
- reject(err);
53
- return;
54
- }
55
-
56
- const info = stats.toJson();
57
-
58
- if (stats.hasErrors()) {
59
- console.log(stats.toString({ colors: chalk.supportsColor }));
60
- reject(new Error('Build failed with errors.'));
61
- return;
62
- }
63
-
64
- if (stats.hasWarnings()) {
65
- console.warn(info.warnings);
66
- }
67
-
68
- const targetDirShort = path.relative(api.service.context, targetDir);
69
- const assetsDir = `${options.output.assets}/`;
70
- console.log();
71
- console.log(formatStats(stats, targetDirShort, assetsDir, api));
72
-
73
- resolve();
74
- });
75
- });
76
-
77
- if (cmd.report) {
78
- const slash = (str) => str.replace(/\\/g, '/');
79
- const { explore } = require('source-map-explorer');
80
- const open = require('open');
81
-
82
- const outAnalyzer = api.resolve(
83
- options.output.base,
84
- REPORT_ANALYZER_FILE_NAME,
85
- );
86
- const outSmScripts = api.resolve(
87
- options.output.base,
88
- 'report-source-map-scripts.html',
89
- );
90
- const outSmStyles = api.resolve(
91
- options.output.base,
92
- 'report-source-map-styles.html',
93
- );
94
-
95
- await Promise.all([
96
- explore(
97
- slash(
98
- api.resolve(options.output.base, options.output.scripts, '*.js'),
99
- ),
100
- { output: { format: 'html', filename: outSmScripts } },
101
- ),
102
- explore(
103
- slash(
104
- api.resolve(options.output.base, options.output.styles, '*.css'),
105
- ),
106
- { output: { format: 'html', filename: outSmStyles } },
107
- ),
108
- ]).then(() => {});
109
-
110
- console.log();
111
- console.log(chalk.greenBright.bold(`Reports generated:`));
112
- console.log(`${chalk.bold(`Webpack Bundle Analyzer:`)} ${outAnalyzer}`);
113
- console.log(
114
- `${chalk.bold(`Source map for script(s):`)} ${outSmScripts}`,
115
- );
116
- console.log(`${chalk.bold(`Source map for style(s):`)} ${outSmStyles}`);
117
- console.log();
118
-
119
- open(outAnalyzer);
120
- open(outSmScripts);
121
- open(outSmStyles);
122
- }
123
- },
124
- );
125
- };
@@ -1,14 +0,0 @@
1
- module.exports = (api) => {
2
- api.registerCommand(
3
- 'inspect',
4
- (command) => command.description('inspect internal webpack config'),
5
- async () => {
6
- const { toString } = require('webpack-chain');
7
- const { highlight } = require('cli-highlight');
8
-
9
- const config = await api.service.resolveWebpackConfig();
10
-
11
- console.log(highlight(toString(config), { language: 'js' }));
12
- },
13
- );
14
- };
@@ -1,201 +0,0 @@
1
- module.exports = (api, options) => {
2
- api.chainWebpack(async (webpackConfig) => {
3
- const globby = require('globby');
4
- const path = require('path');
5
-
6
- const isProd = process.env.NODE_ENV === 'production';
7
- const {
8
- productionSourceMap = true,
9
- productionMinimize = true,
10
- react,
11
- } = options;
12
-
13
- if (isProd) {
14
- webpackConfig
15
- .mode('production')
16
- .devtool(productionSourceMap ? 'source-map' : false);
17
-
18
- if (!productionMinimize) {
19
- webpackConfig.optimization.minimize(false);
20
- }
21
- } else {
22
- // webpackConfig.mode('development').devtool('cheap-module-eval-source-map');
23
- webpackConfig.mode('development').devtool(false);
24
-
25
- // Use separate source maps for styles due to
26
- // https://github.com/webpack-contrib/mini-css-extract-plugin/issues/529
27
-
28
- const devToolShared = {
29
- module: true,
30
- columns: false,
31
- noSources: false,
32
- };
33
-
34
- // * is mini-css-extract-plugin
35
-
36
- webpackConfig
37
- .plugin('devtool-default')
38
- .use(require('webpack/lib/EvalSourceMapDevToolPlugin'), [
39
- {
40
- ...devToolShared,
41
- test: /(?!(?:^\*|\.s?css)$)/,
42
- },
43
- ]);
44
-
45
- webpackConfig
46
- .plugin('devtool-styles')
47
- .use(require('webpack/lib/SourceMapDevToolPlugin'), [
48
- {
49
- ...devToolShared,
50
- test: /(?=(?:^\*|\.s?css)$)/,
51
- },
52
- ]);
53
- }
54
-
55
- const baseDir = api.resolve(options.source.base);
56
-
57
- webpackConfig.context(api.service.context);
58
-
59
- (
60
- await globby([
61
- path.join(baseDir, options.source.scripts, '*.js').replace(/\\/g, '/'),
62
- path.join(baseDir, options.source.styles, '*.scss').replace(/\\/g, '/'),
63
- ])
64
- )
65
- .map((p) => path.relative(api.service.context, p))
66
- .sort()
67
- .forEach((p) => {
68
- const ext = path.extname(p);
69
- const base = path.basename(p, ext);
70
- const isScript = ext !== '.scss';
71
- const outDir = options.output[!isScript ? 'styles' : 'scripts'];
72
- const name = `${outDir}/${base}`;
73
- const entry = webpackConfig.entry(name).add(`./${p}`);
74
-
75
- if (isScript) {
76
- if (react) {
77
- entry.prepend('react-hot-loader/patch');
78
- }
79
- }
80
- });
81
-
82
- const outScriptsDir = options.output.scripts;
83
- webpackConfig.output
84
- .path(api.resolve(options.output.base))
85
- .filename(`[name]${isProd ? '.[contenthash:8]' : ''}.js`)
86
- .chunkFilename(`${outScriptsDir}/[id].js`);
87
-
88
- // prettier-ignore
89
- webpackConfig.resolve
90
- .modules
91
- .add('node_modules')
92
- .add(api.resolve('node_modules'))
93
- .end()
94
- .alias
95
- .set('@@', api.resolve(options.source.base))
96
- .set('~~', api.resolve(options.source.base))
97
- .set('@', api.resolve(options.source.base, options.source.scripts))
98
- .set('~', api.resolve(options.source.base, options.source.scripts))
99
- .set('assets', api.resolve(options.source.base, options.source.assets))
100
- .set('~assets', api.resolve(options.source.base, options.source.assets));
101
-
102
- if (react) {
103
- if (!isProd) {
104
- webpackConfig.resolve.alias.set('react-dom', '@hot-loader/react-dom');
105
- }
106
- }
107
-
108
- const fileLoaderOptions = {
109
- name(p) {
110
- const relative = path.relative(
111
- path.join(baseDir, options.source.assets),
112
- path.dirname(p),
113
- );
114
-
115
- if (!relative) {
116
- return `${options.output.assets}/[name].[hash:8].[ext]`;
117
- }
118
-
119
- return `${options.output.assets}/[folder]/[name].[hash:8].[ext]`;
120
- },
121
- };
122
-
123
- const urlLoaderOptions = {
124
- generator(content, mimetype, encoding, resourcePath) {
125
- if (resourcePath.endsWith('.svg')) {
126
- return require('mini-svg-data-uri')(content.toString());
127
- }
128
-
129
- return `data:${mimetype}${
130
- encoding ? `;${encoding}` : ''
131
- },${content.toString(encoding || undefined)}`;
132
- },
133
- };
134
-
135
- // prettier-ignore
136
- webpackConfig.module
137
- .rule('assets')
138
- .include
139
- .add(api.resolve(path.join(baseDir, options.source.assets)))
140
- .end()
141
- .oneOf('inline')
142
- .resourceQuery(/inline/)
143
- .use('url')
144
- .loader('url-loader')
145
- .options(urlLoaderOptions)
146
- .end()
147
- .end()
148
- .oneOf('external')
149
- .use('file-loader')
150
- .loader(require.resolve('file-loader'))
151
- .options(fileLoaderOptions)
152
-
153
- // prettier-ignore
154
- webpackConfig.resolveLoader
155
- .modules
156
- .add('node_modules')
157
- .add(api.resolve('node_modules'))
158
-
159
- webpackConfig
160
- .plugin('case-sensitive-paths')
161
- .use(require('case-sensitive-paths-webpack-plugin'));
162
-
163
- webpackConfig
164
- .plugin('chisel-dynamic-public-path')
165
- .use(require('../webpack-plugins/DynamicPublicPath'));
166
-
167
- webpackConfig.plugin('webpackbar').use(require('webpackbar'));
168
-
169
- if (isProd) {
170
- // keep chunk ids stable so async chunks have consistent hash (#1916)
171
- webpackConfig
172
- .plugin('named-chunks')
173
- .use(require('webpack/lib/NamedChunksPlugin'), [
174
- (chunk) => {
175
- if (chunk.name) {
176
- return chunk.name;
177
- }
178
-
179
- const hash = require('hash-sum');
180
- const joinedHash = hash(
181
- Array.from(chunk.modulesIterable, (m) => m.id).join('_'),
182
- );
183
- return `chunk-${joinedHash}`;
184
- },
185
- ]);
186
-
187
- // keep module.id stable when vendor modules does not change
188
- webpackConfig
189
- .plugin('hash-module-ids')
190
- .use(require('webpack/lib/HashedModuleIdsPlugin'), [
191
- { hashDigest: 'hex' },
192
- ]);
193
-
194
- if (productionMinimize) {
195
- webpackConfig
196
- .plugin('unminified-webpack-plugin')
197
- .use(require('unminified-webpack-plugin'), [{ postfix: 'full' }]);
198
- }
199
- }
200
- });
201
- };
package/lib/config/css.js DELETED
@@ -1,91 +0,0 @@
1
- module.exports = (api, options) => {
2
- api.chainWebpack((webpackConfig) => {
3
- const path = require('path');
4
-
5
- const isProd = process.env.NODE_ENV === 'production';
6
- const sourceMap = true;
7
-
8
- const sassLoaderOptions = {
9
- sourceMap,
10
- sassOptions: {
11
- indentedSyntax: false,
12
- includePaths: [api.resolve('node_modules')], // TODO: don't use?
13
- outputStyle: 'expanded',
14
- },
15
- };
16
-
17
- const postCssLoaderOptions = {
18
- sourceMap,
19
- };
20
-
21
- const cssLoaderOptions = {
22
- sourceMap,
23
- import: false,
24
- };
25
-
26
- const extractCssLoaderOptions = {
27
- hmr: !isProd,
28
- publicPath: path.relative(
29
- api.resolve(path.join(options.source.base, options.source.styles)),
30
- api.resolve(options.source.base),
31
- ),
32
- };
33
-
34
- const assetsDir = api.resolve(
35
- path.join(options.source.base, options.source.assets),
36
- );
37
-
38
- // Note: thread loader cannot be used right now
39
- // https://github.com/webpack-contrib/thread-loader/issues/79
40
-
41
- const createCssLoader = (rule, test) => {
42
- // prettier-ignore
43
- return webpackConfig.module.rule(rule).test(test)
44
- .exclude
45
- .add(assetsDir)
46
- .end()
47
- .use('extract-css-loader')
48
- .loader(require('mini-css-extract-plugin').loader)
49
- .options(extractCssLoaderOptions)
50
- .end()
51
- .use('css-loader')
52
- .loader(require.resolve('css-loader'))
53
- .options(cssLoaderOptions)
54
- .end()
55
- .use('postcss-loader')
56
- .loader(require.resolve('postcss-loader'))
57
- .options(postCssLoaderOptions)
58
- .end()
59
- };
60
-
61
- createCssLoader('css', /\.css$/);
62
-
63
- // prettier-ignore
64
- createCssLoader('scss', /\.scss$/)
65
- .use('sass-loader')
66
- .loader(require.resolve('sass-loader'))
67
- .options(sassLoaderOptions)
68
- .end()
69
- .use('sass-glob-loader')
70
- .loader(require.resolve('../webpack-loaders/sass-glob-loader.js'))
71
- .end();
72
-
73
- webpackConfig
74
- .plugin('extract-css')
75
- .use(require('mini-css-extract-plugin'), [
76
- { filename: `[name]${isProd ? '.[contenthash:8]' : ''}.css` },
77
- ]);
78
-
79
- webpackConfig.optimization
80
- .minimizer('css')
81
- .use(require.resolve('../webpack-plugins/OptimizeCssnanoPlugin'), [
82
- { sourceMap: true },
83
- ]);
84
-
85
- if (isProd) {
86
- webpackConfig
87
- .plugin('style-only-entries')
88
- .use(require('webpack-fix-style-only-entries'), [{ silent: true }]);
89
- }
90
- });
91
- };
package/lib/config/js.js DELETED
@@ -1,52 +0,0 @@
1
- // TODO: allow easy inclusion of selected node modules
2
- // cache loader?
3
-
4
- const path = require('path');
5
-
6
- const isWindows = process.platform === 'win32';
7
- // https://github.com/vuejs/vue-cli/blob/544e0547054947c471fe9d71a2b967e57f5f3111/packages/%40vue/cli-plugin-babel/index.js
8
- function genTranspileDepRegex(transpileDependencies) {
9
- const deps = transpileDependencies.map((dep) => {
10
- if (typeof dep === 'string') {
11
- const depPath = path.join('node_modules', dep, '/');
12
- return isWindows
13
- ? depPath.replace(/\\/g, '\\\\') // double escape for windows style path
14
- : depPath;
15
- }
16
- if (dep instanceof RegExp) {
17
- return dep.source;
18
- }
19
- return undefined;
20
- });
21
- return deps.length ? new RegExp(deps.join('|')) : null;
22
- }
23
-
24
- module.exports = (api, options) => {
25
- api.chainWebpack((webpackConfig) => {
26
- const transpileDepRegex = genTranspileDepRegex(
27
- options.transpileDependencies || [],
28
- );
29
-
30
- const excludeFunction = (filepath) => {
31
- if (transpileDepRegex && transpileDepRegex.test(filepath)) {
32
- return false;
33
- }
34
- // Don't transpile node_modules
35
- return /node_modules/.test(filepath);
36
- };
37
-
38
- // prettier-ignore
39
- webpackConfig.module.rule('js')
40
- .test(/\.m?jsx?$/)
41
- .exclude
42
- .add(excludeFunction)
43
- .add(api.resolve(options.source.base, options.source.assets))
44
- .end()
45
- .use('babel-loader')
46
- .loader(require.resolve('babel-loader'))
47
-
48
- webpackConfig.optimization
49
- .minimizer('js')
50
- .use(require.resolve('terser-webpack-plugin'));
51
- });
52
- };
@@ -1,9 +0,0 @@
1
- console.log = console.error.bind(console);
2
-
3
- const { toString } = require('webpack-chain');
4
- const config = require('../webpack.config');
5
-
6
- config.then((cfg) => {
7
- cfg.plugins = []; // problems with serialization
8
- process.stdout.write(toString(cfg, { verbose: true }));
9
- });
@@ -1,41 +0,0 @@
1
- // Based on https://github.com/mikevercoelen/gulp-sass-glob/blob/255ee047789e69c82d5e3fc87452360ef8c56f41/src/index.js
2
-
3
- // we initially used custom dart-sass importer instead of this but there
4
- // is noticeable performance difference
5
-
6
- const path = require('path');
7
- const globby = require('globby');
8
-
9
- const IMPORT_RE = /^([ \t]*(?:\/\*.*)?)@import\s+["']([^"']+(?:\.scss|\.sass)?)["'];?([ \t]*(?:\/[/*].*)?)$/gm;
10
-
11
- module.exports = async function sassGlobLoader(content) {
12
- // console.log(`Sass glob loader for ${this.resourcePath}`);
13
-
14
- const file = this.resourcePath;
15
- const base = path.dirname(file);
16
-
17
- const newContent = content.replace(
18
- IMPORT_RE,
19
- (importRule, startComment, globPattern, endComment) => {
20
- if (globby.hasMagic(globPattern)) {
21
- const files = globby.sync(globPattern, { cwd: base }).sort();
22
-
23
- const filesString = files.map((f) => `@import '${f}';`).join('\n');
24
-
25
- // Inlining sources here makes sass build even faster
26
- // but breaks source maps
27
- // const filesString = files
28
- // .map((f) => fs.readFileSync(path.join(base, f), 'utf8'))
29
- // .join('\n');
30
-
31
- return startComment + filesString + endComment;
32
- }
33
-
34
- return importRule;
35
- },
36
- );
37
-
38
- // console.log(newContent);
39
-
40
- return newContent;
41
- };
@@ -1,24 +0,0 @@
1
- class DynamicPublicPath {
2
- constructor(options = {}) {
3
- this.options = options;
4
- }
5
-
6
- // eslint-disable-next-line class-methods-use-this
7
- apply(compiler) {
8
- compiler.hooks.compilation.tap('DynamicPublicPath', (compilation) => {
9
- compilation.mainTemplate.hooks.requireExtensions.tap(
10
- 'DynamicPublicPath',
11
- (source) => {
12
- // Inspired by https://github.com/webpack/webpack/blob/9fe42e7c4027d0a74addaa3352973f6bb6d20689/lib/MainTemplate.js#L237
13
- source +=
14
- '\n\n// Chisel: Allow public path to be modified during runtime\n' +
15
- '__webpack_require__.p = (typeof document !== "undefined" && document.documentElement.dataset.webpackPublicPath) || __webpack_require__.p;';
16
-
17
- return source;
18
- },
19
- );
20
- });
21
- }
22
- }
23
-
24
- module.exports = DynamicPublicPath;