@oroinc/oro-webpack-config-builder 6.1.0-lts05 → 6.1.0-lts06

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/error-handler.js CHANGED
@@ -1,15 +1,7 @@
1
1
  const BaseError = require('./validation/errors/base-error');
2
- const {isVerboseMode} = require('./utils');
2
+ const {isVerboseMode, multiline} = require('./utils');
3
3
  const {red, yellow, green, bgRed} = require('colorette');
4
4
 
5
- const emptyLine = length => new Array(length).fill(' ').join('');
6
- const multiline = (color, msg) => {
7
- msg = ` ${msg}`;
8
- msg = msg + emptyLine(120 - msg.length);
9
-
10
- return `\n${color(emptyLine(msg.length))}\n${color(msg)}\n${color(emptyLine(msg.length))}`;
11
- };
12
-
13
5
  class ErrorHandler {
14
6
  constructor() {
15
7
  this.failedThemes = [];
@@ -19,6 +19,7 @@ const ThemeConfigFactory = require('./theme-config-factory');
19
19
  const path = require('path');
20
20
  const fs = require('fs');
21
21
  const prepareModulesMap = require('./plugin/map/prepare-modules-map');
22
+ const CssToJsonPlugin = require('./plugin/css-to-json');
22
23
  const resolve = require('enhanced-resolve');
23
24
  const {merge: webpackMerge} = require('webpack-merge');
24
25
  const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
@@ -30,7 +31,6 @@ const SVGSprite = require('./svg-sprite');
30
31
  const TerserPlugin = require('terser-webpack-plugin');
31
32
  require('resolve-url-loader');
32
33
  require('lezer-loader');
33
-
34
34
  class ConfigBuilder {
35
35
  constructor() {
36
36
  this._projectPath = '';
@@ -534,6 +534,10 @@ class ConfigBuilder {
534
534
  }));
535
535
  }
536
536
 
537
+ if (!skipCSS) {
538
+ plugins.push(new CssToJsonPlugin());
539
+ }
540
+
537
541
  const cssEntryPoints = !skipCSS ? this._getCssEntryPoints(buildName, buildPublicPath) : {};
538
542
  const jsEntryPoints = !skipJS ? jsBuildConfig.entry : {};
539
543
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@oroinc/oro-webpack-config-builder",
3
- "version": "6.1.0-lts05",
3
+ "version": "6.1.0-lts06",
4
4
  "author": "Oro, Inc. (https://oroinc.com)",
5
5
  "license": "MIT",
6
6
  "description": "An integration of OroPlatform based applications with the Webpack.",
@@ -16,7 +16,6 @@
16
16
  "css-loader": "^6.8.1",
17
17
  "css-minimizer-webpack-plugin": "~5.0.0",
18
18
  "deepmerge": "~4.3.1",
19
- "esbuild": "^0.25.2",
20
19
  "esbuild-loader": "^4.3.0",
21
20
  "exports-loader": "~4.0.0",
22
21
  "expose-loader": "~4.1.0",
@@ -31,6 +30,7 @@
31
30
  "path": "0.12.7",
32
31
  "postcss": "<8.4.33",
33
32
  "postcss-loader": "~7.3.4",
33
+ "postcss-safe-parser": "^7.0.1",
34
34
  "printf": "~0.6.0",
35
35
  "resolve-url-loader": "^5.0.0",
36
36
  "rtlcss-webpack-plugin": "~4.0.6",
@@ -0,0 +1,66 @@
1
+ const path = require('path');
2
+ const webpack = require('webpack');
3
+ const jsonTransform = require('./json-transformer');
4
+ const {multiline} = require('./../../utils');
5
+ const {bgRed} = require('colorette');
6
+
7
+ const isExportCssFile = filename => {
8
+ return path.extname(filename) === '.css' && /_json(\.rtl)?$/.test(path.basename(filename, '.css'));
9
+ };
10
+
11
+ class CssToJsonPlugin {
12
+ constructor(options) {}
13
+
14
+ processAssets = (compilation, callback) => {
15
+ const chunks = Array.from(compilation.chunks);
16
+
17
+ chunks.forEach(chunk => {
18
+ const files = Array.from(chunk.files);
19
+
20
+ files.filter(isExportCssFile).forEach(filename => {
21
+ const src = compilation.assets[filename].source();
22
+ const json = jsonTransform(src);
23
+
24
+ try {
25
+ JSON.parse(json);
26
+ } catch (e) {
27
+ console.error(
28
+ multiline(bgRed, `[ERROR] The JSON generated from the CSS file "${filename}" is invalid.`)
29
+ );
30
+ console.error(e.message);
31
+ return;
32
+ }
33
+
34
+ let jsonFileName = '[name].json';
35
+
36
+ if (filename.includes('rtl')) {
37
+ jsonFileName = '[name].rtl.json';
38
+ }
39
+
40
+ const dstFileName = compilation.getPath(jsonFileName, {
41
+ chunk,
42
+ cssFileName: filename
43
+ });
44
+
45
+ compilation.assets[dstFileName] = new webpack.sources.RawSource(json);
46
+ chunk.files.add(dstFileName);
47
+ });
48
+ });
49
+
50
+ callback();
51
+ };
52
+
53
+ apply(compiler) {
54
+ compiler.hooks.compilation.tap('CssToJsonPlugin', compilation => {
55
+ compilation.hooks.processAssets.tapAsync(
56
+ {
57
+ name: 'CssToJsonPlugin',
58
+ stage: compilation.PROCESS_ASSETS_STAGE_OPTIMIZE
59
+ },
60
+ (chunks, callback) => this.processAssets(compilation, callback)
61
+ );
62
+ });
63
+ }
64
+ }
65
+
66
+ module.exports = CssToJsonPlugin;
@@ -0,0 +1,42 @@
1
+ const postcss = require('postcss');
2
+ const safeParser = require('postcss-safe-parser');
3
+
4
+ const normalizeSelector = selector => {
5
+ return selector
6
+ .replace(/^\./g, '')
7
+ .replace(/:(\w+)/, (matched, group) => {
8
+ return group.charAt(0).toUpperCase() + group.slice(1);
9
+ })
10
+ /*
11
+ * #main > .item => _main__item
12
+ * input[type="text"] => input_type_text
13
+ * .button + .icon => button__icon
14
+ * .p:has(.btn) => p_has__btn_
15
+ */
16
+ .replace(/[:\.\[\]\(\)#\s>+~]/g, '_');
17
+ };
18
+
19
+ const transform = src => {
20
+ const classMap = {};
21
+ const root = postcss.parse(src, {parser: safeParser});
22
+ root.walkRules(rule => {
23
+ const selector = rule.selector;
24
+
25
+ if (!selector.startsWith('.')) {
26
+ return;
27
+ }
28
+
29
+ const normalizedKey = normalizeSelector(selector);
30
+ const props = [];
31
+ rule.walkDecls(decl => {
32
+ const important = decl.important ? ' !important' : '';
33
+ props.push(`${decl.prop}: ${decl.value}${important}`);
34
+ });
35
+
36
+ classMap[normalizedKey] = props.join('; ') + (props.length ? ';' : '');
37
+ });
38
+
39
+ return JSON.stringify(classMap, null, 2);
40
+ };
41
+
42
+ module.exports = transform;
package/utils.js CHANGED
@@ -1,7 +1,7 @@
1
1
  let prodMode;
2
2
  let verboseMode;
3
3
 
4
- module.exports = {
4
+ const utils = {
5
5
  isVerboseMode() {
6
6
  if (verboseMode === void 0) {
7
7
  verboseMode = process.argv.filter(arg => {
@@ -13,6 +13,7 @@ module.exports = {
13
13
 
14
14
  return verboseMode;
15
15
  },
16
+
16
17
  isProdMode() {
17
18
  if (prodMode !== void 0) {
18
19
  return prodMode;
@@ -26,5 +27,18 @@ module.exports = {
26
27
  });
27
28
 
28
29
  return prodMode;
30
+ },
31
+
32
+ emptyLine(length) {
33
+ return new Array(length).fill(' ').join('');
34
+ },
35
+
36
+ multiline(color, msg) {
37
+ msg = ` ${msg}`;
38
+ msg = msg + utils.emptyLine(120 - msg.length);
39
+
40
+ return `\n${color(utils.emptyLine(msg.length))}\n${color(msg)}\n${color(utils.emptyLine(msg.length))}`;
29
41
  }
30
42
  };
43
+
44
+ module.exports = utils;