@oroinc/oro-webpack-config-builder 0.0.3 → 4.2.1-dev4
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 +1 -1
- package/modules-config/layout-modules-config-loader.js +4 -4
- package/modules-config/modules-config-loader.js +9 -12
- package/oro-webpack-config.js +22 -7
- package/package.json +18 -17
- package/style/layout-style-loader.js +37 -12
- package/theme-config-factory.js +1 -1
- package/writer/scss-entry-point-file-writer.js +8 -2
package/README.md
CHANGED
|
@@ -2,4 +2,4 @@
|
|
|
2
2
|
|
|
3
3
|
An integration of OroPlatform based applications with the Webpack.
|
|
4
4
|
|
|
5
|
-
For more details see [the documentation](https://doc.oroinc.com/
|
|
5
|
+
For more details see [the documentation](https://doc.oroinc.com/bundles/platform/AssetBundle/).
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
const path = require('path');
|
|
2
2
|
const merge = require('deepmerge');
|
|
3
|
-
const
|
|
3
|
+
const ModulesConfigLoader = require('./modules-config-loader');
|
|
4
4
|
|
|
5
|
-
class LayoutModulesConfigLoader extends
|
|
5
|
+
class LayoutModulesConfigLoader extends ModulesConfigLoader {
|
|
6
6
|
/**
|
|
7
|
-
*
|
|
7
|
+
* @inheritdoc
|
|
8
8
|
*/
|
|
9
9
|
loadConfig(theme, filePath) {
|
|
10
10
|
let themeConfig = super.loadConfig(theme, path.join('/Resources/views/layouts/', theme, filePath));
|
|
11
11
|
// recursive process parent theme
|
|
12
|
-
const parentTheme = this.themes[theme];
|
|
12
|
+
const {parent: parentTheme} = this.themes[theme];
|
|
13
13
|
if (typeof parentTheme === 'string') {
|
|
14
14
|
const parentThemeConfig = this.loadConfig(parentTheme, filePath);
|
|
15
15
|
themeConfig = merge(parentThemeConfig, themeConfig);
|
|
@@ -3,6 +3,9 @@ const fs = require('fs');
|
|
|
3
3
|
const merge = require('deepmerge');
|
|
4
4
|
const yaml = require('js-yaml');
|
|
5
5
|
|
|
6
|
+
// merge only unique items
|
|
7
|
+
const arrayMerge = (target, source) => target.concat(source.filter(item => !target.includes(item)));
|
|
8
|
+
|
|
6
9
|
class ModulesConfigLoader {
|
|
7
10
|
/**
|
|
8
11
|
* @returns {Array}
|
|
@@ -43,21 +46,15 @@ class ModulesConfigLoader {
|
|
|
43
46
|
if (!fs.existsSync(source)) return;
|
|
44
47
|
|
|
45
48
|
fs.readdirSync(source).forEach(name => {
|
|
46
|
-
const
|
|
47
|
-
if (!fs.lstatSync(
|
|
49
|
+
const themePath = path.resolve(source, name);
|
|
50
|
+
if (!fs.lstatSync(themePath).isDirectory()) {
|
|
48
51
|
return;
|
|
49
52
|
}
|
|
50
|
-
const themeFile = path.resolve(
|
|
53
|
+
const themeFile = path.resolve(themePath, themeInfoFileName);
|
|
51
54
|
if (!fs.existsSync(themeFile)) return;
|
|
52
55
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
}
|
|
56
|
-
const themeInfo = yaml.safeLoad(fs.readFileSync(themeFile, 'utf8'));
|
|
57
|
-
|
|
58
|
-
if ('parent' in themeInfo) {
|
|
59
|
-
themes[name] = themeInfo.parent;
|
|
60
|
-
}
|
|
56
|
+
const theme = yaml.load(fs.readFileSync(themeFile, 'utf8'));
|
|
57
|
+
themes[name] = merge(themes[name] || {}, theme, {arrayMerge});
|
|
61
58
|
});
|
|
62
59
|
});
|
|
63
60
|
|
|
@@ -75,7 +72,7 @@ class ModulesConfigLoader {
|
|
|
75
72
|
const absolutePath = bundle + filePath;
|
|
76
73
|
if (!fs.existsSync(absolutePath)) return;
|
|
77
74
|
|
|
78
|
-
const doc = yaml.
|
|
75
|
+
const doc = yaml.load(fs.readFileSync(absolutePath, 'utf8'));
|
|
79
76
|
configs = merge(configs, doc);
|
|
80
77
|
});
|
|
81
78
|
return configs;
|
package/oro-webpack-config.js
CHANGED
|
@@ -19,8 +19,9 @@ const ThemeConfigFactory = require('./theme-config-factory');
|
|
|
19
19
|
const path = require('path');
|
|
20
20
|
const prepareModulesMap = require('./plugin/map/prepare-modules-map');
|
|
21
21
|
const resolve = require('enhanced-resolve');
|
|
22
|
-
const webpackMerge = require('webpack-merge');
|
|
22
|
+
const {merge: webpackMerge} = require('webpack-merge');
|
|
23
23
|
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
|
|
24
|
+
const WebpackRTLPlugin = require('webpack-rtl-plugin');
|
|
24
25
|
|
|
25
26
|
class ConfigBuilder {
|
|
26
27
|
constructor() {
|
|
@@ -145,7 +146,7 @@ class ConfigBuilder {
|
|
|
145
146
|
if (this._defaultLayoutThemes) {
|
|
146
147
|
themes = [...themes, ...this._defaultLayoutThemes];
|
|
147
148
|
} else {
|
|
148
|
-
themes = [...themes, ...
|
|
149
|
+
themes = [...themes, ...this._appConfig['themes']];
|
|
149
150
|
}
|
|
150
151
|
} else if (this._layoutThemes.indexOf(selectedTheme) !== -1) {
|
|
151
152
|
// build single layout theme
|
|
@@ -337,11 +338,11 @@ class ConfigBuilder {
|
|
|
337
338
|
|
|
338
339
|
plugins: [
|
|
339
340
|
new OptimizeCssAssetsPlugin({
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
341
|
+
cssProcessorPluginOptions: {
|
|
342
|
+
preset: ['default', {
|
|
343
|
+
// preserve comments for WebpackRTLPlugin, comments will be removed anyway later
|
|
344
|
+
discardComments: false,
|
|
345
|
+
}],
|
|
345
346
|
}
|
|
346
347
|
})
|
|
347
348
|
]
|
|
@@ -351,17 +352,21 @@ class ConfigBuilder {
|
|
|
351
352
|
const webpackConfigs = [];
|
|
352
353
|
|
|
353
354
|
themes.forEach(theme => {
|
|
355
|
+
let themeDefinition;
|
|
354
356
|
let themeConfig;
|
|
355
357
|
let buildPublicPath;
|
|
356
358
|
if (this._isAdminTheme(theme)) {
|
|
359
|
+
themeDefinition = this._modulesConfigLoader.themes[theme.split('.')[1]];
|
|
357
360
|
buildPublicPath = '/build/admin/';
|
|
358
361
|
themeConfig = this._themeConfigFactory
|
|
359
362
|
.create(theme, buildPublicPath, '/Resources/config/jsmodules.yml');
|
|
360
363
|
} else {
|
|
364
|
+
themeDefinition = this._layoutModulesConfigLoader.themes[theme];
|
|
361
365
|
buildPublicPath = `/build/${theme}/`;
|
|
362
366
|
themeConfig = this._layoutThemeConfigFactory
|
|
363
367
|
.create(theme, buildPublicPath, '/config/jsmodules.yml');
|
|
364
368
|
}
|
|
369
|
+
const {rtl_support: rtlSupport = false} = themeDefinition;
|
|
365
370
|
const resolvedBuildPath = path.join(resolvedPublicPath, buildPublicPath);
|
|
366
371
|
|
|
367
372
|
const resolverConfig = {
|
|
@@ -379,6 +384,15 @@ class ConfigBuilder {
|
|
|
379
384
|
return moduleName => resolver({}, '', moduleName, {});
|
|
380
385
|
})(resolve.create.sync({...resolverConfig}));
|
|
381
386
|
|
|
387
|
+
const plugins = [];
|
|
388
|
+
if (rtlSupport && !env.skipCSS && !env.skipRTL) {
|
|
389
|
+
plugins.push(new WebpackRTLPlugin({
|
|
390
|
+
filename: '[name].rtl.css',
|
|
391
|
+
// RTL all chunks, except those that already support RTL
|
|
392
|
+
test: '(?<!(-rtl-ready))\\.css'
|
|
393
|
+
}));
|
|
394
|
+
}
|
|
395
|
+
|
|
382
396
|
const cssEntryPoints = !env.skipCSS ? this._getCssEntryPoints(theme, buildPublicPath) : {};
|
|
383
397
|
const jsEntryPoints = !env.skipJS ? themeConfig.entry : {};
|
|
384
398
|
|
|
@@ -400,6 +414,7 @@ class ConfigBuilder {
|
|
|
400
414
|
new MapModulesPlugin(prepareModulesMap(resolver, themeConfig.map))
|
|
401
415
|
]
|
|
402
416
|
},
|
|
417
|
+
plugins,
|
|
403
418
|
module: {
|
|
404
419
|
rules: [
|
|
405
420
|
{
|
package/package.json
CHANGED
|
@@ -1,45 +1,46 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@oroinc/oro-webpack-config-builder",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "4.2.1-dev4",
|
|
4
4
|
"author": "Oro, Inc (https://www.oroinc.com)",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"description": "An integration of OroPlatform based applications with the Webpack.",
|
|
7
7
|
"main": "oro-webpack-config.js",
|
|
8
8
|
"dependencies": {
|
|
9
|
-
"@babel/core": "^7.
|
|
10
|
-
"@babel/plugin-transform-runtime": "^7.
|
|
11
|
-
"@babel/preset-env": "^7.
|
|
12
|
-
"autoprefixer": "9.
|
|
13
|
-
"babel-loader": "^8.
|
|
9
|
+
"@babel/core": "^7.16.0",
|
|
10
|
+
"@babel/plugin-transform-runtime": "^7.16.4",
|
|
11
|
+
"@babel/preset-env": "^7.16.4",
|
|
12
|
+
"autoprefixer": "^9.8.8",
|
|
13
|
+
"babel-loader": "^8.2.3",
|
|
14
14
|
"css-loader": "^3.6.0",
|
|
15
|
-
"deepmerge": "
|
|
15
|
+
"deepmerge": "4.2.2",
|
|
16
16
|
"exports-loader": "^0.7.0",
|
|
17
17
|
"expose-loader": "^0.7.5",
|
|
18
18
|
"extract-loader": "3.1.0",
|
|
19
19
|
"file-loader": "^4.3.0",
|
|
20
20
|
"font-awesome": "4.7.0",
|
|
21
21
|
"happypack": "^5.0.1",
|
|
22
|
-
"html-webpack-plugin": "^3.2.0",
|
|
23
22
|
"imports-loader": "^0.8.0",
|
|
24
23
|
"inject-loader": "^4.0.1",
|
|
25
|
-
"js-yaml": "
|
|
24
|
+
"js-yaml": "4.1.0",
|
|
26
25
|
"mini-css-extract-plugin": "0.7.0",
|
|
27
26
|
"minimist": "^1.2.3",
|
|
28
|
-
"node-sass": "^
|
|
27
|
+
"node-sass": "^6.0.1",
|
|
29
28
|
"optimize-css-assets-webpack-plugin": "5.0.3",
|
|
30
29
|
"path": "0.12.7",
|
|
31
30
|
"postcss-loader": "3.0.0",
|
|
32
|
-
"printf": "^0.6.
|
|
31
|
+
"printf": "^0.6.1",
|
|
33
32
|
"sass-loader": "7.1.0",
|
|
34
33
|
"style-loader": "^0.23.1",
|
|
35
34
|
"terser": "4.1.2",
|
|
36
35
|
"text-loader": "0.0.1",
|
|
37
|
-
"underscore": "
|
|
36
|
+
"underscore": "1.13.*",
|
|
38
37
|
"url-loader": "2.0.1",
|
|
39
|
-
"webpack": "^4.
|
|
40
|
-
"webpack-bundle-analyzer": "^
|
|
41
|
-
"webpack-cli": "^
|
|
42
|
-
"webpack-dev-server": "^
|
|
43
|
-
"webpack-merge": "
|
|
38
|
+
"webpack": "^4.46.0",
|
|
39
|
+
"webpack-bundle-analyzer": "^4.5.0",
|
|
40
|
+
"webpack-cli": "^4.9.1",
|
|
41
|
+
"webpack-dev-server": "^4.5.0",
|
|
42
|
+
"webpack-merge": "5.8.0",
|
|
43
|
+
"webpack-rtl-plugin": "^2.0.0",
|
|
44
|
+
"wildcard": "^2.0.0"
|
|
44
45
|
}
|
|
45
46
|
}
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
const path = require('path');
|
|
2
|
+
const wildcard = require('wildcard');
|
|
3
|
+
const _ = require('underscore')
|
|
2
4
|
|
|
3
5
|
class LayoutStyleLoader {
|
|
4
6
|
/**
|
|
@@ -17,21 +19,25 @@ class LayoutStyleLoader {
|
|
|
17
19
|
*/
|
|
18
20
|
getThemeEntryPoints(theme, buildPath) {
|
|
19
21
|
const entryPoints = {};
|
|
20
|
-
|
|
22
|
+
const {rtl_support: rtlSupport = false} = this._configLoader.themes[theme];
|
|
21
23
|
const themeConfig = this._configLoader.loadConfig(theme, '/config/assets.yml');
|
|
24
|
+
const writingOptions = {};
|
|
22
25
|
|
|
23
|
-
for (const key
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
const filePath = path.join(buildPath, config.output);
|
|
33
|
-
entryPoints[entryPointName] = this._entryPointFileWriter.write('./../../../', inputs, filePath);
|
|
26
|
+
for (const [key, config] of Object.entries(themeConfig)) {
|
|
27
|
+
let {inputs, output, auto_rtl_inputs: rtlMasks = []} = config;
|
|
28
|
+
if (config.output === undefined) {
|
|
29
|
+
throw new Error('"output" for "' + key + '" group in theme "' + theme + '" is not defined');
|
|
30
|
+
}
|
|
31
|
+
inputs = this._overrideInputs(inputs);
|
|
32
|
+
inputs = this._sortInputs(inputs);
|
|
33
|
+
if (rtlSupport) {
|
|
34
|
+
writingOptions.ignoreRTLInputs = _.difference(inputs, this._matchInputs(rtlMasks, inputs));
|
|
34
35
|
}
|
|
36
|
+
|
|
37
|
+
const entryPointName = output.replace(/\.[^/.]+$/, '');
|
|
38
|
+
const filePath = path.join(buildPath, output);
|
|
39
|
+
entryPoints[entryPointName] =
|
|
40
|
+
this._entryPointFileWriter.write('./../../../', inputs, filePath, writingOptions);
|
|
35
41
|
}
|
|
36
42
|
return entryPoints;
|
|
37
43
|
}
|
|
@@ -86,6 +92,25 @@ class LayoutStyleLoader {
|
|
|
86
92
|
});
|
|
87
93
|
return [...settingsInputs, ...variablesInputs, ...restInputs];
|
|
88
94
|
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Filter inputs that matches any mask from the list
|
|
98
|
+
*
|
|
99
|
+
* @param {[string]} masks list of wildcard masks
|
|
100
|
+
* @param {[string]} inputs
|
|
101
|
+
* @return {[string]} matched inputs
|
|
102
|
+
* @private
|
|
103
|
+
*/
|
|
104
|
+
_matchInputs(masks, inputs) {
|
|
105
|
+
masks = masks.map(mask => wildcard(mask));
|
|
106
|
+
|
|
107
|
+
const whiteListedInputs = masks.reduce((include, mask) => {
|
|
108
|
+
include.push(...mask.match(inputs));
|
|
109
|
+
return include;
|
|
110
|
+
}, []);
|
|
111
|
+
|
|
112
|
+
return _.unique(whiteListedInputs);
|
|
113
|
+
}
|
|
89
114
|
}
|
|
90
115
|
|
|
91
116
|
module.exports = LayoutStyleLoader;
|
package/theme-config-factory.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
class ThemeConfigFactory {
|
|
2
2
|
/**
|
|
3
|
-
* @param {
|
|
3
|
+
* @param {ModulesConfigLoader} configLoader
|
|
4
4
|
* @param {DynamicImportsFileWriter} dynamicImportsFileWriter
|
|
5
5
|
* @param {AppModulesFileWriter} appModulesFileWriter
|
|
6
6
|
* @param {ConfigsFileWriter} configsFileWriter
|
|
@@ -15,16 +15,22 @@ class SCSSEntryPointFileWriter {
|
|
|
15
15
|
* @param {string} baseInputPath base path for input files
|
|
16
16
|
* @param {Array} inputs List of inputs
|
|
17
17
|
* @param {string} output Output file path
|
|
18
|
+
* @param {Object} options writing options
|
|
18
19
|
* @returns {string} JS file path of an output file
|
|
19
20
|
*/
|
|
20
|
-
write(baseInputPath, inputs, output) {
|
|
21
|
+
write(baseInputPath, inputs, output, {ignoreRTLInputs = []}) {
|
|
21
22
|
let content = '';
|
|
22
23
|
inputs.forEach(input => {
|
|
24
|
+
const ignoreRTL = ignoreRTLInputs.indexOf(input) !== -1;
|
|
23
25
|
input = input.replace(/\.[^/.]+$/, '');
|
|
24
26
|
// don't add the base path to global node modules,
|
|
25
27
|
// e.g. '~bootstrap/scss/bootstrap'
|
|
26
28
|
const basePath = input.startsWith('~') ? '': baseInputPath;
|
|
27
|
-
|
|
29
|
+
let importModule = `@import "${basePath}${input}";\n`;
|
|
30
|
+
if (ignoreRTL) {
|
|
31
|
+
importModule = `/*rtl:begin:ignore*/\n${importModule}/*rtl:end:ignore*/\n`;
|
|
32
|
+
}
|
|
33
|
+
content += importModule;
|
|
28
34
|
});
|
|
29
35
|
const scssFilepath = path.resolve(this._publicPath + output + '.scss');
|
|
30
36
|
fs.mkdirSync(path.dirname(scssFilepath), {recursive: true});
|