@schalkneethling/miyagi-core 4.4.2 → 4.4.3

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 (115) hide show
  1. package/README.md +7 -2
  2. package/api/app.js +16 -16
  3. package/api/index.js +263 -262
  4. package/bin/miyagi.js +1 -1
  5. package/dist/css/iframe.css +6 -30
  6. package/frontend/assets/css/iframe/accordion-tabs.css +39 -39
  7. package/frontend/assets/css/iframe/jsontree.js.css +149 -149
  8. package/frontend/assets/css/iframe/prism.css +45 -45
  9. package/frontend/assets/css/iframe/styleguide/colors.css +27 -27
  10. package/frontend/assets/css/iframe/styleguide/fonts.css +23 -23
  11. package/frontend/assets/css/iframe/styleguide/index.css +58 -58
  12. package/frontend/assets/css/iframe/styleguide/spacings.css +10 -10
  13. package/frontend/assets/css/iframe.css +191 -191
  14. package/frontend/assets/css/main/menu/config-switcher.css +21 -21
  15. package/frontend/assets/css/main/menu/config-switchers.css +34 -34
  16. package/frontend/assets/css/main/menu/goto.css +16 -16
  17. package/frontend/assets/css/main/menu/nav.css +49 -49
  18. package/frontend/assets/css/main/menu/search.css +34 -34
  19. package/frontend/assets/css/main/menu/title.css +18 -18
  20. package/frontend/assets/css/main/menu.css +89 -89
  21. package/frontend/assets/css/main/reset.css +47 -47
  22. package/frontend/assets/css/main.css +41 -41
  23. package/frontend/assets/css/shared.css +16 -16
  24. package/frontend/assets/css/tokens.css +108 -107
  25. package/frontend/assets/js/_accordion-tabs.js +392 -392
  26. package/frontend/assets/js/_goto.js +59 -59
  27. package/frontend/assets/js/_iframe-links.js +14 -14
  28. package/frontend/assets/js/_is-triggered.js +3 -3
  29. package/frontend/assets/js/_main.js +369 -369
  30. package/frontend/assets/js/_mock-data.js +8 -8
  31. package/frontend/assets/js/_prism.js +1082 -1081
  32. package/frontend/assets/js/_search.js +186 -186
  33. package/frontend/assets/js/_socket.js +44 -44
  34. package/frontend/assets/js/config-switcher/development-mode.js +38 -38
  35. package/frontend/assets/js/config-switcher/index.js +55 -55
  36. package/frontend/assets/js/config-switcher/text-direction.js +22 -22
  37. package/frontend/assets/js/config-switcher/theme.js +68 -68
  38. package/frontend/assets/js/iframe.build.js +25 -25
  39. package/frontend/assets/js/iframe.js +38 -38
  40. package/frontend/assets/js/jsontree.js +979 -976
  41. package/frontend/assets/js/main.build.js +29 -29
  42. package/frontend/assets/js/main.js +31 -31
  43. package/frontend/assets/js/styleguide/color-converter.js +652 -652
  44. package/frontend/assets/js/styleguide/index.js +100 -100
  45. package/lib/build/index.js +1014 -1020
  46. package/lib/cli/app.js +16 -16
  47. package/lib/cli/component.js +50 -50
  48. package/lib/cli/doctor.js +130 -121
  49. package/lib/cli/drupal-assets.js +163 -157
  50. package/lib/cli/lint.js +196 -196
  51. package/lib/cli/run.js +150 -146
  52. package/lib/config.js +86 -86
  53. package/lib/constants/lint-log-levels.js +6 -6
  54. package/lib/drupal/load-assets-config.js +59 -60
  55. package/lib/drupal/resolve-library-assets.js +132 -141
  56. package/lib/errors.js +20 -20
  57. package/lib/generator/component.js +124 -124
  58. package/lib/generator/mocks.js +156 -156
  59. package/lib/helpers.js +68 -68
  60. package/lib/i18n/en.js +93 -93
  61. package/lib/i18n/index.js +8 -8
  62. package/lib/index.js +13 -13
  63. package/lib/init/args.js +153 -153
  64. package/lib/init/config.js +452 -438
  65. package/lib/init/engines.js +41 -41
  66. package/lib/init/index.js +83 -83
  67. package/lib/init/rendering.js +3 -3
  68. package/lib/init/static.js +90 -90
  69. package/lib/init/twing/cache.js +27 -27
  70. package/lib/init/twing/functions.js +37 -37
  71. package/lib/init/views.js +5 -5
  72. package/lib/logger.js +72 -72
  73. package/lib/mocks/get.js +88 -88
  74. package/lib/mocks/index.js +2 -2
  75. package/lib/mocks/resolve/ref.js +447 -447
  76. package/lib/mocks/resolve/tpl.js +218 -218
  77. package/lib/mocks/resolve.js +154 -154
  78. package/lib/render/helpers/resolve-assets.js +29 -39
  79. package/lib/render/helpers.js +27 -27
  80. package/lib/render/index.js +18 -18
  81. package/lib/render/views/iframe/component.docs.js +50 -50
  82. package/lib/render/views/iframe/component.js +249 -248
  83. package/lib/render/views/iframe/design-tokens/colors.js +38 -38
  84. package/lib/render/views/iframe/design-tokens/index.js +3 -3
  85. package/lib/render/views/iframe/design-tokens/sizes.js +35 -35
  86. package/lib/render/views/iframe/design-tokens/typography.js +37 -37
  87. package/lib/render/views/iframe/docs.js +42 -42
  88. package/lib/render/views/iframe/index.js +28 -28
  89. package/lib/render/views/iframe/variation.js +89 -89
  90. package/lib/render/views/iframe/variation.standalone.js +69 -68
  91. package/lib/render/views/main/component.docs.js +38 -38
  92. package/lib/render/views/main/component.js +55 -55
  93. package/lib/render/views/main/design-tokens.js +38 -38
  94. package/lib/render/views/main/docs.js +33 -33
  95. package/lib/render/views/main/index.js +33 -33
  96. package/lib/state/components.js +99 -99
  97. package/lib/state/css.js +33 -33
  98. package/lib/state/docs.js +72 -72
  99. package/lib/state/file-contents.js +154 -154
  100. package/lib/state/helpers.js +53 -53
  101. package/lib/state/index.js +39 -39
  102. package/lib/state/menu/index.js +202 -202
  103. package/lib/state/menu/structure.js +84 -84
  104. package/lib/state/partials.js +12 -12
  105. package/lib/state/source-tree.js +51 -51
  106. package/lib/styleguide/color-names.js +148 -148
  107. package/lib/styleguide/colors.js +113 -113
  108. package/lib/styleguide/helpers.js +33 -33
  109. package/lib/styleguide/index.js +4 -4
  110. package/lib/styleguide/media-queries.js +18 -18
  111. package/lib/styleguide/spacings.js +22 -22
  112. package/lib/styleguide/typography.js +46 -46
  113. package/lib/validator/mocks.js +110 -83
  114. package/lib/validator/schemas.js +236 -227
  115. package/package.json +118 -117
@@ -18,25 +18,25 @@ const { defaultUserConfig } = appConfig;
18
18
  * @returns {string} the given path sanitized
19
19
  */
20
20
  function sanitizePath(path) {
21
- if (path === null) return path;
21
+ if (path === null) return path;
22
22
 
23
- let sanitizedPath = path;
23
+ let sanitizedPath = path;
24
24
 
25
- if (sanitizedPath.startsWith("./")) {
26
- sanitizedPath = sanitizedPath.slice(2);
27
- } else if (sanitizedPath.startsWith("/")) {
28
- sanitizedPath = sanitizedPath.slice(1);
29
- }
25
+ if (sanitizedPath.startsWith("./")) {
26
+ sanitizedPath = sanitizedPath.slice(2);
27
+ } else if (sanitizedPath.startsWith("/")) {
28
+ sanitizedPath = sanitizedPath.slice(1);
29
+ }
30
30
 
31
- if (sanitizedPath === "." || sanitizedPath === "/") {
32
- sanitizedPath = "";
33
- }
31
+ if (sanitizedPath === "." || sanitizedPath === "/") {
32
+ sanitizedPath = "";
33
+ }
34
34
 
35
- if (sanitizedPath.endsWith("/")) {
36
- sanitizedPath = sanitizedPath.slice(0, -1);
37
- }
35
+ if (sanitizedPath.endsWith("/")) {
36
+ sanitizedPath = sanitizedPath.slice(0, -1);
37
+ }
38
38
 
39
- return sanitizedPath;
39
+ return sanitizedPath;
40
40
  }
41
41
 
42
42
  /**
@@ -46,21 +46,21 @@ function sanitizePath(path) {
46
46
  * @returns {string}
47
47
  */
48
48
  function sanitizeWatchPath(watchPath) {
49
- if (typeof watchPath !== "string") {
50
- return watchPath;
51
- }
49
+ if (typeof watchPath !== "string") {
50
+ return watchPath;
51
+ }
52
52
 
53
- let sanitizedPath = watchPath;
53
+ let sanitizedPath = watchPath;
54
54
 
55
- if (sanitizedPath.startsWith("./")) {
56
- sanitizedPath = sanitizedPath.slice(2);
57
- }
55
+ if (sanitizedPath.startsWith("./")) {
56
+ sanitizedPath = sanitizedPath.slice(2);
57
+ }
58
58
 
59
- if (sanitizedPath.endsWith("/")) {
60
- sanitizedPath = sanitizedPath.slice(0, -1);
61
- }
59
+ if (sanitizedPath.endsWith("/")) {
60
+ sanitizedPath = sanitizedPath.slice(0, -1);
61
+ }
62
62
 
63
- return sanitizedPath;
63
+ return sanitizedPath;
64
64
  }
65
65
 
66
66
  /**
@@ -68,7 +68,7 @@ function sanitizeWatchPath(watchPath) {
68
68
  * @returns {Array} the given file path in an array or simply the given array
69
69
  */
70
70
  function arrayfy(strOrArr) {
71
- return Array.isArray(strOrArr) ? strOrArr : [strOrArr];
71
+ return Array.isArray(strOrArr) ? strOrArr : [strOrArr];
72
72
  }
73
73
 
74
74
  /**
@@ -76,94 +76,104 @@ function arrayfy(strOrArr) {
76
76
  * @returns {object[]}
77
77
  */
78
78
  function getDefaultWatchSources(merged) {
79
- const sources = [];
80
- const sourceByPath = new Set();
81
-
82
- const addSource = (source) => {
83
- if (!source || typeof source.path !== "string" || source.path.length === 0) {
84
- return;
85
- }
86
-
87
- const key = `${source.type}:${source.path}`;
88
- // Deduplicate watch targets; While calling add on Set will dedup,
89
- // we need a conditional to avoid adding duplicates to the `sources` array.
90
- if (sourceByPath.has(key)) {
91
- return;
92
- }
93
-
94
- sourceByPath.add(key);
95
- sources.push(source);
96
- };
97
-
98
- if (merged.components.folder) {
99
- addSource({
100
- id: "components",
101
- type: "dir",
102
- path: sanitizeWatchPath(merged.components.folder),
103
- recursive: true,
104
- });
105
- }
106
-
107
- if (merged.docs?.folder) {
108
- addSource({
109
- id: "docs",
110
- type: "dir",
111
- path: sanitizeWatchPath(merged.docs.folder),
112
- recursive: true,
113
- optional: true,
114
- });
115
- }
116
-
117
- for (const folder of merged.assets.folder || []) {
118
- addSource({
119
- id: `assets-folder-${folder}`,
120
- type: "dir",
121
- path: sanitizeWatchPath(path.join(merged.assets.root, folder)),
122
- recursive: true,
123
- optional: true,
124
- });
125
- }
126
-
127
- const localCssFiles = [...(merged.assets.css || []), ...(merged.assets.shared?.css || [])]
128
- .filter((filePath) => !filePath.startsWith("http://"))
129
- .filter((filePath) => !filePath.startsWith("https://"))
130
- .filter((filePath) => !filePath.startsWith("://"));
131
-
132
- for (const cssFile of localCssFiles) {
133
- addSource({
134
- id: `assets-css-${cssFile}`,
135
- type: "file",
136
- path: sanitizeWatchPath(path.join(merged.assets.root, cssFile)),
137
- optional: true,
138
- });
139
- }
140
-
141
- const localJsFiles = [...(merged.assets.js || []), ...(merged.assets.shared?.js || [])]
142
- .map((entry) => entry.src || entry)
143
- .filter((filePath) => typeof filePath === "string")
144
- .filter((filePath) => !filePath.startsWith("http://"))
145
- .filter((filePath) => !filePath.startsWith("https://"))
146
- .filter((filePath) => !filePath.startsWith("://"));
147
-
148
- for (const jsFile of localJsFiles) {
149
- addSource({
150
- id: `assets-js-${jsFile}`,
151
- type: "file",
152
- path: sanitizeWatchPath(path.join(merged.assets.root, jsFile)),
153
- optional: true,
154
- });
155
- }
156
-
157
- if (merged.userFileName && merged.watch?.configFile?.enabled) {
158
- addSource({
159
- id: "config-file",
160
- type: "file",
161
- path: sanitizeWatchPath(merged.userFileName),
162
- optional: true,
163
- });
164
- }
165
-
166
- return sources;
79
+ const sources = [];
80
+ const sourceByPath = new Set();
81
+
82
+ const addSource = (source) => {
83
+ if (
84
+ !source ||
85
+ typeof source.path !== "string" ||
86
+ source.path.length === 0
87
+ ) {
88
+ return;
89
+ }
90
+
91
+ const key = `${source.type}:${source.path}`;
92
+ // Deduplicate watch targets; While calling add on Set will dedup,
93
+ // we need a conditional to avoid adding duplicates to the `sources` array.
94
+ if (sourceByPath.has(key)) {
95
+ return;
96
+ }
97
+
98
+ sourceByPath.add(key);
99
+ sources.push(source);
100
+ };
101
+
102
+ if (merged.components.folder) {
103
+ addSource({
104
+ id: "components",
105
+ type: "dir",
106
+ path: sanitizeWatchPath(merged.components.folder),
107
+ recursive: true,
108
+ });
109
+ }
110
+
111
+ if (merged.docs?.folder) {
112
+ addSource({
113
+ id: "docs",
114
+ type: "dir",
115
+ path: sanitizeWatchPath(merged.docs.folder),
116
+ recursive: true,
117
+ optional: true,
118
+ });
119
+ }
120
+
121
+ for (const folder of merged.assets.folder || []) {
122
+ addSource({
123
+ id: `assets-folder-${folder}`,
124
+ type: "dir",
125
+ path: sanitizeWatchPath(path.join(merged.assets.root, folder)),
126
+ recursive: true,
127
+ optional: true,
128
+ });
129
+ }
130
+
131
+ const localCssFiles = [
132
+ ...(merged.assets.css || []),
133
+ ...(merged.assets.shared?.css || []),
134
+ ]
135
+ .filter((filePath) => !filePath.startsWith("http://"))
136
+ .filter((filePath) => !filePath.startsWith("https://"))
137
+ .filter((filePath) => !filePath.startsWith("://"));
138
+
139
+ for (const cssFile of localCssFiles) {
140
+ addSource({
141
+ id: `assets-css-${cssFile}`,
142
+ type: "file",
143
+ path: sanitizeWatchPath(path.join(merged.assets.root, cssFile)),
144
+ optional: true,
145
+ });
146
+ }
147
+
148
+ const localJsFiles = [
149
+ ...(merged.assets.js || []),
150
+ ...(merged.assets.shared?.js || []),
151
+ ]
152
+ .map((entry) => entry.src || entry)
153
+ .filter((filePath) => typeof filePath === "string")
154
+ .filter((filePath) => !filePath.startsWith("http://"))
155
+ .filter((filePath) => !filePath.startsWith("https://"))
156
+ .filter((filePath) => !filePath.startsWith("://"));
157
+
158
+ for (const jsFile of localJsFiles) {
159
+ addSource({
160
+ id: `assets-js-${jsFile}`,
161
+ type: "file",
162
+ path: sanitizeWatchPath(path.join(merged.assets.root, jsFile)),
163
+ optional: true,
164
+ });
165
+ }
166
+
167
+ if (merged.userFileName && merged.watch?.configFile?.enabled) {
168
+ addSource({
169
+ id: "config-file",
170
+ type: "file",
171
+ path: sanitizeWatchPath(merged.userFileName),
172
+ optional: true,
173
+ });
174
+ }
175
+
176
+ return sources;
167
177
  }
168
178
 
169
179
  /**
@@ -171,27 +181,31 @@ function getDefaultWatchSources(merged) {
171
181
  * @returns {object[]}
172
182
  */
173
183
  function normalizeWatchSources(watchConfig) {
174
- if (!Array.isArray(watchConfig.sources) || watchConfig.sources.length === 0) {
175
- return [];
176
- }
177
-
178
- return watchConfig.sources
179
- .map((source, index) => {
180
- if (!source || typeof source.path !== "string" || source.path.length === 0) {
181
- return null;
182
- }
183
-
184
- const type = source.type === "file" ? "file" : "dir";
185
-
186
- return {
187
- id: source.id || `source-${index + 1}`,
188
- type,
189
- path: sanitizeWatchPath(source.path),
190
- recursive: source.recursive !== false,
191
- optional: source.optional === true,
192
- };
193
- })
194
- .filter(Boolean);
184
+ if (!Array.isArray(watchConfig.sources) || watchConfig.sources.length === 0) {
185
+ return [];
186
+ }
187
+
188
+ return watchConfig.sources
189
+ .map((source, index) => {
190
+ if (
191
+ !source ||
192
+ typeof source.path !== "string" ||
193
+ source.path.length === 0
194
+ ) {
195
+ return null;
196
+ }
197
+
198
+ const type = source.type === "file" ? "file" : "dir";
199
+
200
+ return {
201
+ id: source.id || `source-${index + 1}`,
202
+ type,
203
+ path: sanitizeWatchPath(source.path),
204
+ recursive: source.recursive !== false,
205
+ optional: source.optional === true,
206
+ };
207
+ })
208
+ .filter(Boolean);
195
209
  }
196
210
 
197
211
  /**
@@ -201,45 +215,45 @@ function normalizeWatchSources(watchConfig) {
201
215
  * @param {object} userConfig
202
216
  */
203
217
  function applyLegacyWatchCompatibility(merged, userConfig) {
204
- merged.watch.configFile = merged.watch.configFile || { enabled: true };
205
- merged.watch.configFile.enabled =
206
- typeof merged.watch.configFile.enabled === "boolean"
207
- ? merged.watch.configFile.enabled
208
- : merged.ui.watchConfigFile;
209
-
210
- merged.watch.reload = merged.watch.reload || {};
211
- merged.watch.reload.enabled =
212
- typeof merged.watch.reload.enabled === "boolean"
213
- ? merged.watch.reload.enabled
214
- : merged.ui.reload;
215
-
216
- const userReloadRules = userConfig.watch?.reload?.rules || {};
217
- merged.watch.reload.rules = {
218
- ...defaultUserConfig.watch.reload.rules,
219
- ...(merged.watch.reload.rules || {}),
220
- componentAsset:
221
- userReloadRules.componentAsset ??
222
- (merged.ui.reloadAfterChanges.componentAssets
223
- ? "iframe"
224
- : defaultUserConfig.watch.reload.rules.componentAsset),
225
- globalCss:
226
- userReloadRules.globalCss ??
227
- (merged.ui.reloadAfterChanges.componentAssets
228
- ? "iframe"
229
- : defaultUserConfig.watch.reload.rules.globalCss),
230
- globalJs:
231
- userReloadRules.globalJs ??
232
- (merged.ui.reloadAfterChanges.componentAssets
233
- ? "iframe"
234
- : defaultUserConfig.watch.reload.rules.globalJs),
235
- };
236
-
237
- merged.watch.ignore = merged.watch.ignore || {};
238
- merged.watch.ignore.patterns = [
239
- ...(merged.watch.ignore.patterns || []),
240
- ...(merged.components.ignores || []),
241
- ].filter((entry) => typeof entry === "string");
242
- merged.watch.ignore.patterns = [...new Set(merged.watch.ignore.patterns)];
218
+ merged.watch.configFile = merged.watch.configFile || { enabled: true };
219
+ merged.watch.configFile.enabled =
220
+ typeof merged.watch.configFile.enabled === "boolean"
221
+ ? merged.watch.configFile.enabled
222
+ : merged.ui.watchConfigFile;
223
+
224
+ merged.watch.reload = merged.watch.reload || {};
225
+ merged.watch.reload.enabled =
226
+ typeof merged.watch.reload.enabled === "boolean"
227
+ ? merged.watch.reload.enabled
228
+ : merged.ui.reload;
229
+
230
+ const userReloadRules = userConfig.watch?.reload?.rules || {};
231
+ merged.watch.reload.rules = {
232
+ ...defaultUserConfig.watch.reload.rules,
233
+ ...(merged.watch.reload.rules || {}),
234
+ componentAsset:
235
+ userReloadRules.componentAsset ??
236
+ (merged.ui.reloadAfterChanges.componentAssets
237
+ ? "iframe"
238
+ : defaultUserConfig.watch.reload.rules.componentAsset),
239
+ globalCss:
240
+ userReloadRules.globalCss ??
241
+ (merged.ui.reloadAfterChanges.componentAssets
242
+ ? "iframe"
243
+ : defaultUserConfig.watch.reload.rules.globalCss),
244
+ globalJs:
245
+ userReloadRules.globalJs ??
246
+ (merged.ui.reloadAfterChanges.componentAssets
247
+ ? "iframe"
248
+ : defaultUserConfig.watch.reload.rules.globalJs),
249
+ };
250
+
251
+ merged.watch.ignore = merged.watch.ignore || {};
252
+ merged.watch.ignore.patterns = [
253
+ ...(merged.watch.ignore.patterns || []),
254
+ ...(merged.components.ignores || []),
255
+ ].filter((entry) => typeof entry === "string");
256
+ merged.watch.ignore.patterns = [...new Set(merged.watch.ignore.patterns)];
243
257
  }
244
258
 
245
259
  /**
@@ -247,17 +261,17 @@ function applyLegacyWatchCompatibility(merged, userConfig) {
247
261
  * @param {object} merged
248
262
  */
249
263
  function normalizeAndValidateWatchConfig(merged) {
250
- if (merged.watch?.backend === "node-watch") {
251
- throw new Error(
252
- '`watch.backend="node-watch"` is no longer supported. Please use `watch.backend="chokidar"`. See https://docs.miyagi.dev/configuration/options/ for migration details.',
253
- );
254
- }
255
-
256
- merged.watch.backend = "chokidar";
257
- merged.watch.sources = normalizeWatchSources(merged.watch);
258
- if (merged.watch.sources.length === 0) {
259
- merged.watch.sources = getDefaultWatchSources(merged);
260
- }
264
+ if (merged.watch?.backend === "node-watch") {
265
+ throw new Error(
266
+ '`watch.backend="node-watch"` is no longer supported. Please use `watch.backend="chokidar"`. See https://docs.miyagi.dev/configuration/options/ for migration details.',
267
+ );
268
+ }
269
+
270
+ merged.watch.backend = "chokidar";
271
+ merged.watch.sources = normalizeWatchSources(merged.watch);
272
+ if (merged.watch.sources.length === 0) {
273
+ merged.watch.sources = getDefaultWatchSources(merged);
274
+ }
261
275
  }
262
276
 
263
277
  /**
@@ -271,13 +285,13 @@ function normalizeAndValidateWatchConfig(merged) {
271
285
  * @returns {object}
272
286
  */
273
287
  function getJsFileObject({ src, defer, async, type, position = "head" }) {
274
- return {
275
- src,
276
- defer,
277
- async,
278
- type,
279
- position,
280
- };
288
+ return {
289
+ src,
290
+ defer,
291
+ async,
292
+ type,
293
+ position,
294
+ };
281
295
  }
282
296
 
283
297
  /**
@@ -289,36 +303,36 @@ function getJsFileObject({ src, defer, async, type, position = "head" }) {
289
303
  * @returns {string[]} converts the given object to an array of asset file path strings
290
304
  */
291
305
  function getJsFilesArray(strOrArrOrObj, manifest, root) {
292
- if (!Array.isArray(strOrArrOrObj)) {
293
- log("warn", "config.assets.js is not an array.");
294
- return [];
295
- }
296
-
297
- let files = strOrArrOrObj.map((entry) =>
298
- typeof entry === "string" ? getJsFileObject({ src: entry }) : entry,
299
- );
300
-
301
- if (files.length > 0 && manifest.file && manifest.content) {
302
- files = files.map((file) => {
303
- const manifestEntry = getPathFromManifest(file.src, manifest, root);
304
-
305
- if (manifestEntry) {
306
- return {
307
- ...file,
308
- src: path.join(path.dirname(manifest.file), manifestEntry),
309
- };
310
- } else {
311
- return file;
312
- }
313
- });
314
- }
315
-
316
- return files
317
- .filter((file) => typeof file.src === "string")
318
- .map((file) => ({
319
- ...file,
320
- src: sanitizePath(file.src),
321
- }));
306
+ if (!Array.isArray(strOrArrOrObj)) {
307
+ log("warn", "config.assets.js is not an array.");
308
+ return [];
309
+ }
310
+
311
+ let files = strOrArrOrObj.map((entry) =>
312
+ typeof entry === "string" ? getJsFileObject({ src: entry }) : entry,
313
+ );
314
+
315
+ if (files.length > 0 && manifest.file && manifest.content) {
316
+ files = files.map((file) => {
317
+ const manifestEntry = getPathFromManifest(file.src, manifest, root);
318
+
319
+ if (manifestEntry) {
320
+ return {
321
+ ...file,
322
+ src: path.join(path.dirname(manifest.file), manifestEntry),
323
+ };
324
+ } else {
325
+ return file;
326
+ }
327
+ });
328
+ }
329
+
330
+ return files
331
+ .filter((file) => typeof file.src === "string")
332
+ .map((file) => ({
333
+ ...file,
334
+ src: sanitizePath(file.src),
335
+ }));
322
336
  }
323
337
 
324
338
  /**
@@ -330,26 +344,26 @@ function getJsFilesArray(strOrArrOrObj, manifest, root) {
330
344
  * @returns {string[]} converts the given object to an array of asset file path strings
331
345
  */
332
346
  function getCssFilesArray(strOrArrOrObj, manifest, root) {
333
- if (!Array.isArray(strOrArrOrObj)) {
334
- log("warn", "config.assets.css is not an array.");
335
- return [];
336
- }
337
-
338
- let files = strOrArrOrObj.filter((entry) => typeof entry === "string");
339
-
340
- if (files.length > 0 && manifest.content && manifest.file) {
341
- files = files.map((file) => {
342
- const manifestEntry = getPathFromManifest(file, manifest, root);
343
-
344
- if (manifestEntry) {
345
- return path.join(path.dirname(manifest.file), manifestEntry);
346
- } else {
347
- return file;
348
- }
349
- });
350
- }
351
-
352
- return files.map(sanitizePath);
347
+ if (!Array.isArray(strOrArrOrObj)) {
348
+ log("warn", "config.assets.css is not an array.");
349
+ return [];
350
+ }
351
+
352
+ let files = strOrArrOrObj.filter((entry) => typeof entry === "string");
353
+
354
+ if (files.length > 0 && manifest.content && manifest.file) {
355
+ files = files.map((file) => {
356
+ const manifestEntry = getPathFromManifest(file, manifest, root);
357
+
358
+ if (manifestEntry) {
359
+ return path.join(path.dirname(manifest.file), manifestEntry);
360
+ } else {
361
+ return file;
362
+ }
363
+ });
364
+ }
365
+
366
+ return files.map(sanitizePath);
353
367
  }
354
368
 
355
369
  /**
@@ -357,14 +371,14 @@ function getCssFilesArray(strOrArrOrObj, manifest, root) {
357
371
  * @returns {string[]} the given param converted to an array of asset file path strings
358
372
  */
359
373
  function getAssetFoldersArray(strOrArrOrObj) {
360
- if (!Array.isArray(strOrArrOrObj)) {
361
- log("warn", "config.assets.folder is not an array.");
362
- return [];
363
- }
364
-
365
- return strOrArrOrObj
366
- .filter((entry) => typeof entry === "string")
367
- .map(sanitizePath);
374
+ if (!Array.isArray(strOrArrOrObj)) {
375
+ log("warn", "config.assets.folder is not an array.");
376
+ return [];
377
+ }
378
+
379
+ return strOrArrOrObj
380
+ .filter((entry) => typeof entry === "string")
381
+ .map(sanitizePath);
368
382
  }
369
383
 
370
384
  /**
@@ -372,186 +386,186 @@ function getAssetFoldersArray(strOrArrOrObj) {
372
386
  * @returns {object} the user configuration merged with the default configuration
373
387
  */
374
388
  export default (userConfig = {}) => {
375
- const config = { ...userConfig };
376
-
377
- if (config.build) {
378
- if (config.build.basePath) {
379
- if (!config.build.basePath.startsWith("/")) {
380
- config.build.basePath = `/${config.build.basePath}`;
381
- }
382
-
383
- if (!config.build.basePath.endsWith("/")) {
384
- config.build.basePath = `${config.build.basePath}/`;
385
- }
386
- }
387
- }
388
-
389
- if (config.assets) {
390
- let manifest = {};
391
-
392
- if (config.assets.manifest) {
393
- try {
394
- const manifestContent = fs.readFileSync(
395
- path.resolve(
396
- path.join(config.assets.root || "", config.assets.manifest),
397
- ),
398
- { encoding: "utf8" },
399
- );
400
-
401
- manifest.file = config.assets.manifest;
402
- manifest.content = JSON.parse(manifestContent);
403
-
404
- // eslint-disable-next-line no-unused-vars
405
- } catch (e) {
406
- log(
407
- "warn",
408
- t("manifestNotFound").replace("{{manifest}}", config.assets.manifest),
409
- );
410
- }
411
- }
412
-
413
- if (config.assets.folder) {
414
- config.assets.folder = getAssetFoldersArray(config.assets.folder);
415
- }
416
-
417
- if (config.assets.css) {
418
- config.assets.css = getCssFilesArray(
419
- config.assets.css,
420
- manifest,
421
- config.assets.root,
422
- );
423
- }
424
-
425
- if (config.assets.js) {
426
- config.assets.js = getJsFilesArray(
427
- config.assets.js,
428
- manifest,
429
- config.assets.root,
430
- );
431
- }
432
-
433
- if (config.assets.shared) {
434
- if (config.assets.shared.css) {
435
- config.assets.shared.css = getCssFilesArray(
436
- config.assets.shared.css,
437
- manifest,
438
- config.assets.root,
439
- );
440
- }
441
- if (config.assets.shared.js) {
442
- config.assets.shared.js = getJsFilesArray(
443
- config.assets.shared.js,
444
- manifest,
445
- config.assets.root,
446
- );
447
- }
448
- }
449
-
450
- if (!config.assets.customProperties) {
451
- config.assets.customProperties = {};
452
- }
453
-
454
- if (Array.isArray(config.assets.customProperties.files)) {
455
- config.assets.customProperties.files =
456
- config.assets.customProperties.files.filter(
457
- (entry) => typeof entry === "string",
458
- );
459
-
460
- if (manifest?.content) {
461
- config.assets.customProperties.files =
462
- config.assets.customProperties.files.map((file) => {
463
- const manifestEntry = getPathFromManifest(
464
- file,
465
- manifest,
466
- config.assets.root,
467
- );
468
-
469
- if (manifestEntry) {
470
- return path.join(path.dirname(manifest.file), manifestEntry);
471
- } else {
472
- return file;
473
- }
474
- });
475
- }
476
- } else {
477
- log("warn", "config.assets.customProperties.files is not an array.");
478
-
479
- config.assets.customProperties.files = [];
480
- }
481
- }
482
-
483
- if (config.components) {
484
- if (config.components.ignores) {
485
- config.components.ignores = arrayfy(config.components.ignores).map(
486
- sanitizePath,
487
- );
488
- }
489
- }
490
-
491
- if (!config.ui) config.ui = {};
492
- if (!config.ui.theme) config.ui.theme = {};
493
- if (!config.ui.theme.light) config.ui.theme.light = {};
494
- if (!config.ui.theme.dark) config.ui.theme.dark = {};
495
-
496
- if (config.ui.theme.logo) {
497
- if (typeof config.ui.theme.logo === "string") {
498
- const { logo } = config.ui.theme;
499
-
500
- config.ui.theme.logo = {
501
- light: logo,
502
- dark: logo,
503
- };
504
- } else {
505
- if (config.ui.theme.logo.light && !config.ui.theme.logo.dark) {
506
- config.ui.theme.logo.dark = config.ui.theme.logo.light;
507
- } else if (config.ui.theme.logo.dark && !config.ui.theme.logo.light) {
508
- config.ui.theme.logo.light = config.ui.theme.logo.dark;
509
- }
510
- }
511
-
512
- if (config.ui.theme.logo.light) {
513
- config.ui.theme.logo.light = sanitizePath(config.ui.theme.logo.light);
514
- }
515
- if (config.ui.theme.logo.dark) {
516
- config.ui.theme.logo.dark = sanitizePath(config.ui.theme.logo.dark);
517
- }
518
- }
519
-
520
- const merged = deepMerge(defaultUserConfig, config);
521
-
522
- merged.components.folder = sanitizePath(merged.components.folder);
523
-
524
- // do this later as otherwise the deepMerge would do concatenation which we do not want
525
- if (config.files) {
526
- if (config.files.mocks) {
527
- if (config.files.mocks.extension) {
528
- merged.files.mocks.extension = arrayfy(config.files.mocks.extension);
529
-
530
- if (merged.files.mocks.extension.length === 1) {
531
- merged.files.mocks.extension.push(
532
- defaultUserConfig.files.mocks.extension[1],
533
- );
534
- }
535
- }
536
- }
537
- }
538
-
539
- if (!langAvailable.includes(merged.ui.lang)) {
540
- merged.ui.lang = "en";
541
- }
542
-
543
- if (!Object.values(LINT_LOG_LEVELS).includes(merged.lint.logLevel)) {
544
- log(
545
- "warn",
546
- `Invalid config.lint.logLevel "${merged.lint.logLevel}". Falling back to "${defaultUserConfig.lint.logLevel}".`,
547
- );
548
- merged.lint.logLevel = defaultUserConfig.lint.logLevel;
549
- }
550
-
551
- applyLegacyWatchCompatibility(merged, config);
552
- normalizeAndValidateWatchConfig(merged);
553
-
554
- return merged;
389
+ const config = { ...userConfig };
390
+
391
+ if (config.build) {
392
+ if (config.build.basePath) {
393
+ if (!config.build.basePath.startsWith("/")) {
394
+ config.build.basePath = `/${config.build.basePath}`;
395
+ }
396
+
397
+ if (!config.build.basePath.endsWith("/")) {
398
+ config.build.basePath = `${config.build.basePath}/`;
399
+ }
400
+ }
401
+ }
402
+
403
+ if (config.assets) {
404
+ let manifest = {};
405
+
406
+ if (config.assets.manifest) {
407
+ try {
408
+ const manifestContent = fs.readFileSync(
409
+ path.resolve(
410
+ path.join(config.assets.root || "", config.assets.manifest),
411
+ ),
412
+ { encoding: "utf8" },
413
+ );
414
+
415
+ manifest.file = config.assets.manifest;
416
+ manifest.content = JSON.parse(manifestContent);
417
+
418
+ // eslint-disable-next-line no-unused-vars
419
+ } catch (e) {
420
+ log(
421
+ "warn",
422
+ t("manifestNotFound").replace("{{manifest}}", config.assets.manifest),
423
+ );
424
+ }
425
+ }
426
+
427
+ if (config.assets.folder) {
428
+ config.assets.folder = getAssetFoldersArray(config.assets.folder);
429
+ }
430
+
431
+ if (config.assets.css) {
432
+ config.assets.css = getCssFilesArray(
433
+ config.assets.css,
434
+ manifest,
435
+ config.assets.root,
436
+ );
437
+ }
438
+
439
+ if (config.assets.js) {
440
+ config.assets.js = getJsFilesArray(
441
+ config.assets.js,
442
+ manifest,
443
+ config.assets.root,
444
+ );
445
+ }
446
+
447
+ if (config.assets.shared) {
448
+ if (config.assets.shared.css) {
449
+ config.assets.shared.css = getCssFilesArray(
450
+ config.assets.shared.css,
451
+ manifest,
452
+ config.assets.root,
453
+ );
454
+ }
455
+ if (config.assets.shared.js) {
456
+ config.assets.shared.js = getJsFilesArray(
457
+ config.assets.shared.js,
458
+ manifest,
459
+ config.assets.root,
460
+ );
461
+ }
462
+ }
463
+
464
+ if (!config.assets.customProperties) {
465
+ config.assets.customProperties = {};
466
+ }
467
+
468
+ if (Array.isArray(config.assets.customProperties.files)) {
469
+ config.assets.customProperties.files =
470
+ config.assets.customProperties.files.filter(
471
+ (entry) => typeof entry === "string",
472
+ );
473
+
474
+ if (manifest?.content) {
475
+ config.assets.customProperties.files =
476
+ config.assets.customProperties.files.map((file) => {
477
+ const manifestEntry = getPathFromManifest(
478
+ file,
479
+ manifest,
480
+ config.assets.root,
481
+ );
482
+
483
+ if (manifestEntry) {
484
+ return path.join(path.dirname(manifest.file), manifestEntry);
485
+ } else {
486
+ return file;
487
+ }
488
+ });
489
+ }
490
+ } else {
491
+ log("warn", "config.assets.customProperties.files is not an array.");
492
+
493
+ config.assets.customProperties.files = [];
494
+ }
495
+ }
496
+
497
+ if (config.components) {
498
+ if (config.components.ignores) {
499
+ config.components.ignores = arrayfy(config.components.ignores).map(
500
+ sanitizePath,
501
+ );
502
+ }
503
+ }
504
+
505
+ if (!config.ui) config.ui = {};
506
+ if (!config.ui.theme) config.ui.theme = {};
507
+ if (!config.ui.theme.light) config.ui.theme.light = {};
508
+ if (!config.ui.theme.dark) config.ui.theme.dark = {};
509
+
510
+ if (config.ui.theme.logo) {
511
+ if (typeof config.ui.theme.logo === "string") {
512
+ const { logo } = config.ui.theme;
513
+
514
+ config.ui.theme.logo = {
515
+ light: logo,
516
+ dark: logo,
517
+ };
518
+ } else {
519
+ if (config.ui.theme.logo.light && !config.ui.theme.logo.dark) {
520
+ config.ui.theme.logo.dark = config.ui.theme.logo.light;
521
+ } else if (config.ui.theme.logo.dark && !config.ui.theme.logo.light) {
522
+ config.ui.theme.logo.light = config.ui.theme.logo.dark;
523
+ }
524
+ }
525
+
526
+ if (config.ui.theme.logo.light) {
527
+ config.ui.theme.logo.light = sanitizePath(config.ui.theme.logo.light);
528
+ }
529
+ if (config.ui.theme.logo.dark) {
530
+ config.ui.theme.logo.dark = sanitizePath(config.ui.theme.logo.dark);
531
+ }
532
+ }
533
+
534
+ const merged = deepMerge(defaultUserConfig, config);
535
+
536
+ merged.components.folder = sanitizePath(merged.components.folder);
537
+
538
+ // do this later as otherwise the deepMerge would do concatenation which we do not want
539
+ if (config.files) {
540
+ if (config.files.mocks) {
541
+ if (config.files.mocks.extension) {
542
+ merged.files.mocks.extension = arrayfy(config.files.mocks.extension);
543
+
544
+ if (merged.files.mocks.extension.length === 1) {
545
+ merged.files.mocks.extension.push(
546
+ defaultUserConfig.files.mocks.extension[1],
547
+ );
548
+ }
549
+ }
550
+ }
551
+ }
552
+
553
+ if (!langAvailable.includes(merged.ui.lang)) {
554
+ merged.ui.lang = "en";
555
+ }
556
+
557
+ if (!Object.values(LINT_LOG_LEVELS).includes(merged.lint.logLevel)) {
558
+ log(
559
+ "warn",
560
+ `Invalid config.lint.logLevel "${merged.lint.logLevel}". Falling back to "${defaultUserConfig.lint.logLevel}".`,
561
+ );
562
+ merged.lint.logLevel = defaultUserConfig.lint.logLevel;
563
+ }
564
+
565
+ applyLegacyWatchCompatibility(merged, config);
566
+ normalizeAndValidateWatchConfig(merged);
567
+
568
+ return merged;
555
569
  };
556
570
 
557
571
  /**
@@ -561,12 +575,12 @@ export default (userConfig = {}) => {
561
575
  * @returns {string|null}
562
576
  */
563
577
  function getPathFromManifest(file, manifest, root = "") {
564
- const entry = Object.entries(manifest.content).find(([key]) => {
565
- return (
566
- path.resolve(root, path.dirname(manifest.file), sanitizePath(key)) ===
567
- path.resolve(root, sanitizePath(file))
568
- );
569
- });
570
-
571
- return entry ? entry[1] : null;
578
+ const entry = Object.entries(manifest.content).find(([key]) => {
579
+ return (
580
+ path.resolve(root, path.dirname(manifest.file), sanitizePath(key)) ===
581
+ path.resolve(root, sanitizePath(file))
582
+ );
583
+ });
584
+
585
+ return entry ? entry[1] : null;
572
586
  }