@emulsify/core 2.5.1 → 2.6.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.
@@ -7,6 +7,9 @@ const optimizers = require('./optimizers');
7
7
  const emulsifyConfig = require('../../../../../project.emulsify.json');
8
8
  const fs = require('fs-extra');
9
9
 
10
+ // Utility to sanitize file paths (to prevent unwanted characters).
11
+ const sanitizePath = (inputPath) => inputPath.replace(/[^a-zA-Z0-9/_-]/g, '');
12
+
10
13
  // Get directories for file contexts.
11
14
  const webpackDir = path.resolve(__dirname);
12
15
  const projectDir = path.resolve(__dirname, '../../../../..');
@@ -27,7 +30,13 @@ const ComponentLibraryScssPattern = path.resolve(
27
30
  );
28
31
 
29
32
  // Glob pattern for JS files.
30
- const jsPattern = fs.existsSync(path.resolve(projectDir, 'src'))
33
+ const BaseJsPattern = fs.existsSync(path.resolve(projectDir, 'src'))
34
+ ? path.resolve(
35
+ srcDir,
36
+ '!(components|util)/**/!(*.stories|*.component|*.min|*.test).js',
37
+ )
38
+ : '';
39
+ const ComponentJsPattern = fs.existsSync(path.resolve(projectDir, 'src'))
31
40
  ? path.resolve(
32
41
  srcDir,
33
42
  'components/**/!(*.stories|*.component|*.min|*.test).js',
@@ -59,36 +68,79 @@ function replaceLastSlash(str, replacement) {
59
68
  /**
60
69
  * Return all scss/js/svg files that Webpack needs to compile.
61
70
  * @constructor
71
+ * @param {string} BaseJsMatcher - Glob pattern.
72
+ * @param {string} jsMatcher - Glob pattern.
62
73
  * @param {string} BaseScssMatcher - Glob pattern.
63
74
  * @param {string} ComponentScssMatcher - Glob pattern.
64
75
  * @param {string} ComponentLibraryScssMatcher - Glob pattern.
65
- * @param {string} jsMatcher - Glob pattern.
66
76
  * @param {string} spriteMatcher - Glob pattern.
67
77
  */
68
78
  function getEntries(
79
+ BaseJsMatcher,
80
+ jsMatcher,
69
81
  BaseScssMatcher,
70
82
  ComponentScssMatcher,
71
83
  ComponentLibraryScssMatcher,
72
- jsMatcher,
73
84
  spriteMatcher,
74
85
  ) {
75
86
  const entries = {};
76
87
 
88
+ const addEntry = (key, file) => {
89
+ const sanitizedKey = sanitizePath(key);
90
+ if (
91
+ sanitizedKey &&
92
+ !Object.prototype.hasOwnProperty.call(entries, sanitizedKey)
93
+ ) {
94
+ entries[sanitizedKey] = file;
95
+ }
96
+ };
97
+
98
+ // Non-component or global JS entries.
99
+ glob.sync(BaseJsMatcher).forEach((file) => {
100
+ const filePath = file.split(`${srcDir}/`)[1];
101
+ const pathParts = filePath.split('/');
102
+ // Construct the output path by joining all path parts except the last, with "/js/" prefix.
103
+ const filePathDist = `${pathParts.slice(0, -1).join('/')}/js/${pathParts.at(-1).replace('.js', '')}`;
104
+ // Determine if the src directory exists and construct the appropriate path.
105
+ const newFilePath = fs.existsSync(path.resolve(projectDir, 'src'))
106
+ ? `dist/global/${filePathDist}`
107
+ : `dist/js/${filePathDist}`;
108
+ // Add the file to the entries.
109
+ addEntry(newFilePath, file);
110
+ });
111
+
112
+ // Component JS entries.
113
+ glob.sync(jsMatcher).forEach((file) => {
114
+ if (!file.includes('dist/')) {
115
+ const filePath = file.split('components/')[1];
116
+ const filePathDist = replaceLastSlash(filePath, '/js/');
117
+ const distStructure = fs.existsSync(path.resolve(projectDir, 'src'))
118
+ ? 'components'
119
+ : 'js';
120
+ const newFilePath =
121
+ emulsifyConfig.project.platform === 'drupal' &&
122
+ fs.existsSync(path.resolve(projectDir, 'src'))
123
+ ? `components/${filePathDist.replace('.js', '')}`
124
+ : `dist/${distStructure}/${filePathDist.replace('.js', '')}`;
125
+ addEntry(newFilePath, file);
126
+ }
127
+ });
128
+
77
129
  // Non-component or global SCSS entries.
78
130
  glob.sync(BaseScssMatcher).forEach((file) => {
79
131
  const filePath = file.split(`${srcDir}/`)[1];
80
- // Support multi-level folder structures.
81
- let filePathDist = filePath.split('/')[0];
82
- if (filePath.split('/')[1] && !filePath.split('/')[1].endsWith('.scss')) {
83
- filePathDist = filePath.split('/')[1];
84
- }
85
- if (filePath.split('/')[2]) {
86
- filePathDist = `${filePath.split('/')[1]}/${filePath.split('/')[2]}`;
87
- }
88
- const newfilePath = fs.existsSync(path.resolve(projectDir, 'src'))
89
- ? `dist/global/${filePathDist.replace('.scss', '')}`
90
- : `dist/css/${filePathDist.replace('.scss', '')}`;
91
- entries[newfilePath] = file;
132
+ const pathParts = filePath.split('/');
133
+
134
+ // Construct the output path by joining all path parts except the last, with "/css/" prefix.
135
+ const filePathDist = `${pathParts.slice(0, -1).join('/')}/css/${pathParts.at(-1).replace('.scss', '')}`;
136
+
137
+ // Determine if the src directory exists and construct the appropriate path.
138
+ const newFilePath = fs.existsSync(path.resolve(projectDir, 'src'))
139
+ ? `dist/global/${filePathDist}`
140
+ : `dist/css/${filePathDist}`;
141
+
142
+ // Add the file to the entries.
143
+ addEntry(newFilePath, file);
92
144
  });
93
145
 
94
146
  // Component SCSS entries.-
@@ -98,42 +150,25 @@ function getEntries(
98
150
  const distStructure = fs.existsSync(path.resolve(projectDir, 'src'))
99
151
  ? 'components'
100
152
  : 'css';
101
- const newfilePath =
153
+ const newFilePath =
102
154
  emulsifyConfig.project.platform === 'drupal' &&
103
155
  fs.existsSync(path.resolve(projectDir, 'src'))
104
156
  ? `components/${filePathDist.replace('.scss', '')}`
105
157
  : `dist/${distStructure}/${filePathDist.replace('.scss', '')}`;
106
- entries[newfilePath] = file;
158
+ addEntry(newFilePath, file);
107
159
  });
108
160
 
109
161
  // Component Library SCSS entries.
110
162
  glob.sync(ComponentLibraryScssMatcher).forEach((file) => {
111
163
  const filePath = file.split(`${srcDir}/`)[1];
112
- const newfilePath = `dist/storybook/${filePath.replace('.scss', '')}`;
113
- entries[newfilePath] = file;
114
- });
115
-
116
- // JS entries.
117
- glob.sync(jsMatcher).forEach((file) => {
118
- if (!file.includes('dist/')) {
119
- const filePath = file.split('components/')[1];
120
- const filePathDist = replaceLastSlash(filePath, '/js/');
121
- const distStructure = fs.existsSync(path.resolve(projectDir, 'src'))
122
- ? 'components'
123
- : 'js';
124
- const newfilePath =
125
- emulsifyConfig.project.platform === 'drupal' &&
126
- fs.existsSync(path.resolve(projectDir, 'src'))
127
- ? `components/${filePathDist.replace('.js', '')}`
128
- : `dist/${distStructure}/${filePathDist.replace('.js', '')}`;
129
- entries[newfilePath] = file;
130
- }
164
+ const newFilePath = `dist/storybook/${filePath.replace('.scss', '')}`;
165
+ addEntry(newFilePath, file);
131
166
  });
132
167
 
133
168
  glob.sync(spriteMatcher).forEach((file) => {
134
169
  const filePath = file.split('/webpack/')[1];
135
- const newfilePath = `dist/${filePath.replace('.js', '')}`;
136
- entries[newfilePath] = file;
170
+ const newFilePath = `dist/${filePath.replace('.js', '')}`;
171
+ addEntry(newFilePath, file);
137
172
  });
138
173
 
139
174
  return entries;
@@ -144,10 +179,11 @@ module.exports = {
144
179
  errorDetails: true,
145
180
  },
146
181
  entry: getEntries(
182
+ BaseJsPattern,
183
+ ComponentJsPattern,
147
184
  BaseScssPattern,
148
185
  ComponentScssPattern,
149
186
  ComponentLibraryScssPattern,
150
- jsPattern,
151
187
  spritePattern,
152
188
  ),
153
189
  module: {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@emulsify/core",
3
- "version": "2.5.1",
3
+ "version": "2.6.0",
4
4
  "description": "Bundled tooling for Storybook development + Webpack Build",
5
5
  "keywords": [
6
6
  "component library",
@@ -47,45 +47,45 @@
47
47
  },
48
48
  "dependencies": {
49
49
  "@babel/core": "^7.25.9",
50
- "@babel/eslint-parser": "^7.25.9",
50
+ "@babel/eslint-parser": "^7.26.5",
51
51
  "@babel/preset-env": "^7.25.9",
52
52
  "@emulsify/cli": "^1.11.4",
53
- "@storybook/addon-a11y": "^8.4.7",
54
- "@storybook/addon-actions": "^8.4.7",
55
- "@storybook/addon-essentials": "^8.4.7",
56
- "@storybook/addon-links": "^8.4.7",
53
+ "@storybook/addon-a11y": "^8.5.0",
54
+ "@storybook/addon-actions": "^8.5.0",
55
+ "@storybook/addon-essentials": "^8.5.0",
56
+ "@storybook/addon-links": "^8.5.0",
57
57
  "@storybook/addon-styling-webpack": "^1.0.1",
58
- "@storybook/addon-themes": "^8.4.7",
59
- "@storybook/html": "^8.4.5",
60
- "@storybook/html-webpack5": "^8.4.7",
61
- "@storybook/manager-api": "^8.4.7",
62
- "@storybook/preview-api": "^8.4.7",
63
- "@storybook/theming": "^8.4.7",
58
+ "@storybook/addon-themes": "^8.5.0",
59
+ "@storybook/html": "^8.5.0",
60
+ "@storybook/html-webpack5": "^8.5.0",
61
+ "@storybook/manager-api": "^8.5.0",
62
+ "@storybook/preview-api": "^8.5.0",
63
+ "@storybook/theming": "^8.5.0",
64
64
  "add-attributes-twig-extension": "^0.1.0",
65
65
  "autoprefixer": "^10.4.20",
66
66
  "babel-loader": "^9.2.1",
67
67
  "babel-preset-minify": "^0.5.2",
68
68
  "bem-twig-extension": "^0.1.1",
69
69
  "breakpoint-sass": "^3.0.0",
70
- "chalk": "^5.2.0",
70
+ "chalk": "^5.4.1",
71
71
  "clean-webpack-plugin": "^4.0.0",
72
- "concurrently": "^9.1.0",
72
+ "concurrently": "^9.1.2",
73
73
  "copy-webpack-plugin": "^12.0.2",
74
74
  "css-loader": "^7.1.1",
75
75
  "eslint": "^8.57.0",
76
76
  "eslint-config-prettier": "^9.1.0",
77
77
  "eslint-plugin-import": "^2.31.0",
78
- "eslint-plugin-jest": "^28.9.0",
79
- "eslint-plugin-prettier": "^5.1.3",
78
+ "eslint-plugin-jest": "^28.11.0",
79
+ "eslint-plugin-prettier": "^5.2.3",
80
80
  "eslint-plugin-security": "^3.0.1",
81
- "eslint-plugin-storybook": "^0.11.1",
81
+ "eslint-plugin-storybook": "^0.11.2",
82
82
  "eslint-webpack-plugin": "^4.1.0",
83
83
  "file-loader": "^6.2.0",
84
- "fs-extra": "^11.2.0",
85
- "glob": "^11.0.0",
84
+ "fs-extra": "^11.3.0",
85
+ "glob": "^11.0.1",
86
86
  "graceful-fs": "^4.2.11",
87
87
  "html-webpack-plugin": "^5.6.3",
88
- "image-minimizer-webpack-plugin": "^4.1.1",
88
+ "image-minimizer-webpack-plugin": "^4.1.3",
89
89
  "imagemin": "^9.0.0",
90
90
  "imagemin-gifsicle": "^7.0.0",
91
91
  "imagemin-jpegtran": "^8.0.0",
@@ -99,18 +99,18 @@
99
99
  "normalize.css": "^8.0.1",
100
100
  "open-cli": "^8.0.0",
101
101
  "pa11y": "^8.0.0",
102
- "postcss": "^8.4.49",
102
+ "postcss": "^8.5.1",
103
103
  "postcss-loader": "^8.1.1",
104
104
  "postcss-scss": "^4.0.9",
105
105
  "ramda": "^0.30.1",
106
106
  "react": "^19.0.0",
107
107
  "react-dom": "^19.0.0",
108
108
  "regenerator-runtime": "^0.14.1",
109
- "sass": "^1.83.0",
109
+ "sass": "^1.83.4",
110
110
  "sass-loader": "^16.0.4",
111
111
  "storybook": "^8.4.7",
112
- "style-dictionary": "^4.3.0",
113
- "stylelint": "^16.11.0",
112
+ "style-dictionary": "^4.3.2",
113
+ "stylelint": "^16.13.2",
114
114
  "stylelint-config-standard-scss": "^14.0.0",
115
115
  "stylelint-prettier": "^5.0.0",
116
116
  "stylelint-selector-bem-pattern": "^4.0.1",
@@ -121,21 +121,21 @@
121
121
  "twig-testing-library": "^1.2.0",
122
122
  "twigjs-loader": "^1.0.3",
123
123
  "webpack": "^5.97.1",
124
- "webpack-cli": "^5.1.4",
124
+ "webpack-cli": "^6.0.1",
125
125
  "webpack-merge": "^6.0.1",
126
- "yaml": "^2.6.1"
126
+ "yaml": "^2.7.0"
127
127
  },
128
128
  "devDependencies": {
129
- "@commitlint/cli": "^19.6.0",
129
+ "@commitlint/cli": "^19.6.1",
130
130
  "@commitlint/config-conventional": "^19.6.0",
131
131
  "@semantic-release/changelog": "^6.0.2",
132
- "@semantic-release/commit-analyzer": "^13.0.0",
132
+ "@semantic-release/commit-analyzer": "^13.0.1",
133
133
  "@semantic-release/git": "^10.0.1",
134
134
  "@semantic-release/github": "^11.0.1",
135
- "@semantic-release/release-notes-generator": "^14.0.0",
135
+ "@semantic-release/release-notes-generator": "^14.0.3",
136
136
  "husky": "^9.1.7",
137
- "lint-staged": "^15.2.11",
138
- "semantic-release": "^24.2.0"
137
+ "lint-staged": "^15.4.1",
138
+ "semantic-release": "^24.2.1"
139
139
  },
140
140
  "overrides": {
141
141
  "graceful-fs": "^4.2.11"