chisel-scripts 2.0.0-alpha.4 → 2.0.0-alpha.6

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/CHANGELOG.md CHANGED
@@ -2,6 +2,23 @@
2
2
 
3
3
  <!-- INSERT-NEW-ENTRIES-HERE -->
4
4
 
5
+ ## 2.0.0-alpha.6 (2025-02-04)
6
+
7
+ - blocks, scripts, images optimize, mega menu settings ([d8a8b3c](https://github.com/xfiveco/generator-chisel/commit/d8a8b3c))
8
+
9
+ ## 2.0.0-alpha.5 (2024-12-06)
10
+
11
+ - refactor: icons.mjs - updated preview generation ([16f7792](https://github.com/xfiveco/generator-chisel/commit/16f7792))
12
+ - refactor: modified icons.mjs ([6c61b40](https://github.com/xfiveco/generator-chisel/commit/6c61b40))
13
+ - refactor: removed uneeded comments from icons.mjs ([ab62eb5](https://github.com/xfiveco/generator-chisel/commit/ab62eb5))
14
+ - composer, wp-config, plugins list updates ([642f983](https://github.com/xfiveco/generator-chisel/commit/642f983))
15
+ - modified icons.mjs ([eff3391](https://github.com/xfiveco/generator-chisel/commit/eff3391))
16
+ - Publish ([3209b73](https://github.com/xfiveco/generator-chisel/commit/3209b73))
17
+ - feature: added svg icons generation bundle ([8cda54a](https://github.com/xfiveco/generator-chisel/commit/8cda54a))
18
+ - feature: testing new approach to icons generating ([35b3064](https://github.com/xfiveco/generator-chisel/commit/35b3064))
19
+ - chore: renamed name of the function ([68c4deb](https://github.com/xfiveco/generator-chisel/commit/68c4deb))
20
+ - V2: Add Devcontainers (#538) ([b878421](https://github.com/xfiveco/generator-chisel/commit/b878421)), closes [#538](https://github.com/xfiveco/generator-chisel/issues/538)
21
+
5
22
  ## 2.0.0-alpha.4 (2024-11-12)
6
23
 
7
24
  - V2: Add Devcontainers (#538) ([b878421](https://github.com/xfiveco/generator-chisel/commit/b878421)), closes [#538](https://github.com/xfiveco/generator-chisel/issues/538)
package/composer.phar CHANGED
Binary file
@@ -0,0 +1,440 @@
1
+ import fs from 'fs/promises';
2
+ import fastGlob from 'fast-glob';
3
+ import path from 'path';
4
+ import svgo from 'svgo';
5
+ import { chalk } from 'chisel-shared-utils';
6
+
7
+ const { convertPathToPattern } = fastGlob;
8
+
9
+ const printLog = (...args) => console.log(chalk.dim('[icons]::'), ...args);
10
+
11
+ const icons = (api) => {
12
+ const svgSourceFilesDirectory = api.resolve('assets/icons-source');
13
+ const svgSourceFilesDirectoryMono = svgSourceFilesDirectory + '/';
14
+ const svgSourceFilesDirectoryColor = svgSourceFilesDirectory + '/color/';
15
+
16
+ const iconsDestinationFolder = api.resolve('assets/icons');
17
+ const iconsJsonFileDestinationFile = iconsDestinationFolder + '/icons.json';
18
+ const iconsFileDestinationFile = iconsDestinationFolder + '/icons.svg';
19
+
20
+ const iconsScssSettingsFileDestinationFolder = api.resolve('src/design/settings');
21
+ const iconsScssSettingsFileDestinationFile =
22
+ iconsScssSettingsFileDestinationFolder + '/_icon-settings.scss';
23
+
24
+ function optimizeSVG(svgContent, idPrefix, colorfulIcons) {
25
+ const configMono = [
26
+ {
27
+ name: 'removeAttrs',
28
+ params: {
29
+ attrs: ['path:(fill|stroke)', 'fill'],
30
+ },
31
+ },
32
+ ];
33
+
34
+ const configColor = [];
35
+ const config = colorfulIcons ? configColor : configMono;
36
+
37
+ const result = svgo.optimize(svgContent, {
38
+ removeViewBox: false,
39
+ removeDimensions: false,
40
+ plugins: [
41
+ 'preset-default',
42
+ 'removeDimensions',
43
+ {
44
+ name: 'prefixIds',
45
+ params: {
46
+ delim: '',
47
+ prefixIds: true,
48
+ prefixClassNames: true,
49
+ prefix: (data) => {
50
+ const prefix =
51
+ data.type === 'element' &&
52
+ data.name === 'use' &&
53
+ data.attributes?.href?.startsWith('#icon-')
54
+ ? ''
55
+ : `${idPrefix}__`;
56
+ return prefix;
57
+ },
58
+ },
59
+ },
60
+ ...config,
61
+ ],
62
+ });
63
+ return result.data;
64
+ }
65
+
66
+ async function parseSVGFileData(iconSourceFilePath, iconColorful) {
67
+ const iconName = path.basename(iconSourceFilePath, '.svg').replace(/[_|\s]/gm, '-');
68
+ const iconId = iconColorful ? `icon-color-${iconName}` : `icon-${iconName}`;
69
+ const iconViewId = `${iconId}-view`;
70
+ const svgContent = await fs.readFile(iconSourceFilePath, 'utf-8');
71
+ const optimizedSvgContent = optimizeSVG(svgContent, iconId, iconColorful);
72
+ const viewBoxMatch = optimizedSvgContent.match(/viewBox=["']([^'|^"]+)["']/);
73
+ const svgViewBox = viewBoxMatch ? viewBoxMatch[1] : null;
74
+ const defsRegex = /<defs>([\s\S]*?)<\/defs>/gm;
75
+ const defsMatches = optimizedSvgContent.matchAll(defsRegex);
76
+ const svgDefsContent = Array.from(defsMatches)
77
+ .map((data) => data[1].trim())
78
+ .join('\n');
79
+
80
+ if (!svgViewBox) {
81
+ throw Error(`SVG viewBox not found in file ${iconSourceFilePath}.`);
82
+ }
83
+
84
+ const svgWidth = parseInt(svgViewBox.split(' ')[2], 10);
85
+ const svgHeight = parseInt(svgViewBox.split(' ')[3], 10);
86
+ const svgRectangle = svgWidth !== svgHeight;
87
+ const svgIconDataFull = optimizedSvgContent.replace(/<svg[^>]*>|<\/svg>/gi, '').trim();
88
+ const svgIconDataNoDefs = svgIconDataFull.replace(defsRegex, '');
89
+
90
+ return {
91
+ iconSourceFilePath,
92
+ iconName,
93
+ iconColorful,
94
+ iconId,
95
+ iconViewId,
96
+ svgViewBox,
97
+ svgWidth,
98
+ svgHeight,
99
+ svgIconDataFull,
100
+ svgIconDataNoDefs,
101
+ svgDefsContent,
102
+ svgRectangle,
103
+ };
104
+ }
105
+
106
+ async function readSVGFilesDataOptimized(sourceDir = svgSourceFilesDirectory, iconsColorful) {
107
+ const sourceDirExists = await fs.access(sourceDir).then(() => true).catch(() => false);
108
+ if (!sourceDirExists) {
109
+ printLog(chalk.yellow(`Path to source SVG files not found!!!`), chalk.italic.underline(sourceDir));
110
+ return [];
111
+ }
112
+
113
+ const svgFiles = await fs.readdir(sourceDir);
114
+ const svgFilesDataPromises = svgFiles
115
+ .filter((file) => file.endsWith('.svg'))
116
+ .map((file) => parseSVGFileData(path.join(sourceDir, file), iconsColorful));
117
+
118
+ const svgIconsData = await Promise.all(svgFilesDataPromises);
119
+ return svgIconsData;
120
+ }
121
+
122
+ async function createDestinationDir() {
123
+ const dirCreation = await fs.mkdir(iconsDestinationFolder, { recursive: true });
124
+ dirCreation && printLog(`Destination directory created:`, chalk.italic.underline(dirCreation));
125
+ }
126
+
127
+
128
+ async function generateFileContentDataOfSvgIcons(svgIconsData, viewBoxYStartAt = 0) {
129
+ const iconsViewGap = 10;
130
+ const viewBoxMaxWidth = svgIconsData
131
+ .map((data) => data.svgWidth)
132
+ .reduce((max, width) => (width > max ? width : max), 0);
133
+
134
+ const contentData = {
135
+ views: ``,
136
+ groups: ``,
137
+ defs: ``,
138
+ viewBoxTotalHeight: 0,
139
+ viewBoxMaxWidth,
140
+ };
141
+
142
+ let viewBoxY = viewBoxYStartAt;
143
+
144
+ svgIconsData.forEach((data) => {
145
+ const tmpViewBoxElementPositionY = viewBoxY;
146
+ const tmpViewBoxForView = `0 ${tmpViewBoxElementPositionY} ${data.svgWidth} ${data.svgHeight}`;
147
+
148
+ viewBoxY += data.svgHeight + iconsViewGap;
149
+ contentData.viewBoxTotalHeight += data.svgHeight + iconsViewGap;
150
+ contentData.defs += data.svgDefsContent ? `\t\t${data.svgDefsContent}\n` : '';
151
+ contentData.views += `\t<view id="${data.iconId}-view" viewBox="${tmpViewBoxForView}" />\n`;
152
+
153
+ contentData.groups += `
154
+ <svg y="${tmpViewBoxElementPositionY}">
155
+ <g id="${data.iconId}">
156
+ ${data.svgIconDataNoDefs}
157
+ </g>
158
+ </svg>`;
159
+ });
160
+
161
+ return {contentData, viewBoxY};
162
+ }
163
+
164
+ async function generateIconsFile(svgIconsDataMono, svgIconsDataColor) {
165
+ const {contentData: contentDataMono, viewBoxY} = await generateFileContentDataOfSvgIcons(svgIconsDataMono);
166
+ const {contentData: contentDataColor} = await generateFileContentDataOfSvgIcons(svgIconsDataColor, viewBoxY);
167
+
168
+ const iconsSVG =
169
+ `
170
+ <!-- This file is auto generated. Do not edit directly. -->
171
+
172
+ <svg version="1.1" viewBox="0 0 ${contentDataColor.viewBoxMaxWidth} ${contentDataColor.viewBoxTotalHeight}" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
173
+ <defs>
174
+ ${contentDataColor.defs.trim()}
175
+ </defs>
176
+
177
+ <!-- Monochromatic icons -->
178
+ ${contentDataMono.views.trim()}
179
+
180
+ ${contentDataMono.groups.trim()}
181
+
182
+ <!-- Colored icons -->
183
+ ${contentDataColor.views.trim()}
184
+
185
+ ${contentDataColor.groups.trim()}
186
+ </svg>`.trim() + '\n';
187
+
188
+ try {
189
+ await fs.writeFile(iconsFileDestinationFile, iconsSVG, 'utf-8');
190
+ printLog(`Generated SVG icons file: ${chalk.italic.underline(iconsFileDestinationFile)}`);
191
+ } catch (error) {
192
+ throw new Error(`Error generating ${iconsFileDestinationFile}: ${error.message}`);
193
+ }
194
+ }
195
+
196
+ async function generateScssSettingsFile(svgIconsData) {
197
+ const scssVariables = svgIconsData
198
+ .filter((data) => data.svgWidth / data.svgHeight !== 1)
199
+ .map((data) => {
200
+ return `
201
+ ${data.iconId}: math.div(${data.svgWidth}, ${data.svgHeight}),`;
202
+ })
203
+ .join('')
204
+ .trim();
205
+
206
+ const scssSettingsFileContent =
207
+ `@use 'sass:math';
208
+
209
+ /* This file is auto generated. Do not edit directly. */
210
+
211
+ $o-icon-icons: (
212
+ ${scssVariables}
213
+ );`.trim() + '\n';
214
+
215
+ try {
216
+ await fs.writeFile(iconsScssSettingsFileDestinationFile, scssSettingsFileContent, 'utf-8');
217
+ printLog(`Generated SCSS file: ${chalk.italic.underline(iconsScssSettingsFileDestinationFile)}`);
218
+ } catch (error) {
219
+ throw new Error(`Error generating ${iconsScssSettingsFileDestinationFile}: ${error.message}`);
220
+ }
221
+ }
222
+
223
+ async function generateIconsJsonFile(svgIconsData) {
224
+ try {
225
+ const jsonContent = JSON.stringify(svgIconsData, null, 2).trim() + '\n';
226
+ await fs.writeFile(iconsJsonFileDestinationFile, jsonContent, 'utf-8');
227
+ printLog(`Generated JSON icons data file: ${chalk.italic.underline(iconsJsonFileDestinationFile)}`);
228
+ } catch (error) {
229
+ throw new Error(`Error generating ${iconsJsonFileDestinationFile}: ${error.message}`);
230
+ }
231
+ }
232
+
233
+ async function generateIconsHTMLPreview(svgIconsDataMono = [], svgIconsDataColor = []) {
234
+ const allIconsData = [...svgIconsDataColor, ...svgIconsDataMono];
235
+
236
+ const iconsColorHTML = svgIconsDataColor
237
+ .map((data) => {
238
+ return `
239
+ <div class="element">
240
+ <!-- Alternative HTML usage example
241
+ <div class="o-icon o-icon--${data.iconId}">
242
+ 1: <img class="o-icon__icon" src="./icons.svg#${data.iconId}-view" alt="${data.iconId}">
243
+ 2: <iframe class="o-icon__icon" src="./icons.svg#${data.iconId}-view"></iframe>
244
+ </div>
245
+ -->
246
+ <i class="o-icon o-icon--color o-icon--${data.iconId}" style="background-image: url(./icons.svg#${data.iconViewId});"></i>
247
+
248
+ <p class="element__name" title="Usage name">${data.iconId.replace('icon-', '')}</p>
249
+ <!-- <p class="element__id">ID: ${data.iconId}</p> -->
250
+ <p class="element__id">View ID: ${data.iconViewId}</p>
251
+ </div>`;
252
+ })
253
+ .join('\n').trim();
254
+
255
+ const iconsMonoHTML = svgIconsDataMono
256
+ .map((data) => {
257
+ return `
258
+ <div class="element">
259
+ <i class="o-icon o-icon--mono o-icon--${data.iconId}" style="mask-image: url(./icons.svg#${data.iconViewId});"></i>
260
+
261
+ <p class="element__name" title="Usage name">${data.iconId.replace('icon-', '')}</p>
262
+ <!-- <p class="element__id">ID: ${data.iconId}</p> -->
263
+ <p class="element__id">View ID: ${data.iconViewId}</p>
264
+ </div>`;
265
+ })
266
+ .join('\n').trim();
267
+
268
+ const cssClasses = allIconsData
269
+ .filter((data) => data.svgWidth / data.svgHeight !== 1)
270
+ .map((data) => {
271
+ return `\t.o-icon--${data.iconId}{ width: calc(${data.svgWidth / data.svgHeight} * 1em); }\n`;
272
+ })
273
+ .join('')
274
+ .trim();
275
+
276
+ const htmlContent = `
277
+ <!DOCTYPE html>
278
+ <html lang="en">
279
+ <head>
280
+ <meta charset="UTF-8">
281
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
282
+ <title>Icons Preview</title>
283
+ <style>
284
+ :root {
285
+ font-size: 62.5%;
286
+ }
287
+ body {
288
+ font-size: 3.6rem;
289
+ background: #f4f4f4;
290
+ }
291
+
292
+ h2 {
293
+ display: block;
294
+ margin: 1rem 0;
295
+ width: 100%;
296
+ font-size: 3rem;
297
+ }
298
+
299
+ section {
300
+ display: flex;
301
+ gap: 2rem;
302
+ flex-wrap: wrap;
303
+ align-items: center;
304
+ padding: 20px;
305
+ }
306
+
307
+ .info {
308
+ font-size: 1.6rem;
309
+ color: #333;
310
+ background: #fff7e3;
311
+ padding: 1rem;
312
+ border: 1px solid #f7d990;
313
+ border-radius: 1rem;
314
+ text-align: center;
315
+ }
316
+
317
+ .element {
318
+ display: flex;
319
+ flex-direction: column;
320
+ align-items: center;
321
+ justify-content: center;
322
+ padding: 1rem;
323
+ border: 1px solid #ccc;
324
+ border-radius: 1rem;
325
+ background: #fff;
326
+ color: #333;
327
+ }
328
+
329
+ .element:hover {
330
+ color: #0073aa;
331
+ }
332
+
333
+ .element__name {
334
+ font-family: monospace;
335
+ font-size: 1.4rem;
336
+ color: currentcolor;
337
+ margin: 1.5rem 0 0.5rem;
338
+ }
339
+
340
+ .element__id {
341
+ font-family: monospace;
342
+ font-size: 0.9rem;
343
+ color: #999;
344
+ margin: 0.5rem 0 0;
345
+ }
346
+
347
+ .o-icon {
348
+ display: flex;
349
+ align-items: center;
350
+ justify-content: center;
351
+ height: 1em;
352
+ line-height: 1em;;
353
+ width: 1em;
354
+ font-size: var(--o-icon-size, 1em);
355
+ }
356
+
357
+ .o-icon--color {
358
+ background-repeat: no-repeat;
359
+ background-size: contain;
360
+ }
361
+
362
+ .o-icon--mono {
363
+ mask-repeat: no-repeat;
364
+ mask-size: contain;
365
+ background-color: var(--o-icon-color, currentcolor);
366
+ }
367
+
368
+ ${cssClasses}
369
+ </style>
370
+ </head>
371
+ <body>
372
+ <!-- Potential issues: https://betravis.github.io/icon-methods/svg-sprite-sheets.html -->
373
+ <p class="info">To properly display this file, it shouldn't be opened directly in the browser, but it should be served.</p>
374
+ <section>
375
+ <h2>Colorful Icons</h2>
376
+ ${iconsColorHTML}
377
+ </section>
378
+ <section>
379
+ <h2>Monochromatic Icons</h2>
380
+ ${iconsMonoHTML}
381
+ </section>
382
+ </body>
383
+ </html>
384
+ `.trim();
385
+
386
+ const previewDestinationFolder = `${iconsDestinationFolder}/icons-preview.html`;
387
+ try {
388
+ await fs.writeFile(previewDestinationFolder, htmlContent, 'utf-8');
389
+ printLog(`Generated HTML preview file: ${chalk.italic.underline(previewDestinationFolder)}`);
390
+ } catch (error) {
391
+ throw new Error(`Error generating icons-preview.html: ${error.message}`);
392
+ }
393
+ }
394
+
395
+ return async function generateIcons() {
396
+ printLog(chalk.cyanBright('Starting icons files generation'));
397
+ printLog('Path to source SVG files:', chalk.italic.underline(svgSourceFilesDirectory));
398
+
399
+ const svgIconsDataMono = await readSVGFilesDataOptimized(svgSourceFilesDirectoryMono, false);
400
+ const svgIconsDataColor = await readSVGFilesDataOptimized(svgSourceFilesDirectoryColor, true);
401
+ const allIconsData = [...svgIconsDataMono, ...svgIconsDataColor];
402
+
403
+ if (allIconsData.length === 0) {
404
+ printLog(chalk.yellow('No icons found!!!'));
405
+ printLog(chalk.yellow('Warning: Skipping icons files generation!'));
406
+ return;
407
+ }
408
+
409
+ await createDestinationDir();
410
+ await Promise.all([
411
+ generateIconsFile(svgIconsDataMono, svgIconsDataColor),
412
+ generateScssSettingsFile(allIconsData),
413
+ generateIconsJsonFile(allIconsData),
414
+ generateIconsHTMLPreview(svgIconsDataMono, svgIconsDataColor),
415
+ ]);
416
+
417
+ printLog(chalk.green('Icons files generated successfully'));
418
+ }
419
+ }
420
+
421
+ export const build = async (api) => {
422
+ await icons(api)();
423
+ };
424
+
425
+ export const start = async (api) => {
426
+ const { default: chokidar } = await import('chokidar');
427
+
428
+ const sourceIconsDir = api.resolve('assets/icons-source');
429
+ const pattern = convertPathToPattern(sourceIconsDir) + '/**/*.svg';
430
+
431
+ const watcher = chokidar.watch(pattern, {
432
+ persistent: true,
433
+ ignoreInitial: true,
434
+ awaitWriteFinish: true,
435
+ });
436
+
437
+ watcher.on('add', () => icons(api)());
438
+ watcher.on('change', () => icons(api)());
439
+ watcher.on('unlink', () => icons(api)());
440
+ };
@@ -50,7 +50,7 @@ $table_prefix = '<%= tablePrefix %>';
50
50
  */
51
51
  define( 'WP_DEBUG', true );
52
52
  define( 'WP_DEBUG_LOG', true );
53
- define( 'WP_DEBUG_DISPLAY', true );
53
+ define( 'WP_DEBUG_DISPLAY', false );
54
54
 
55
55
  // Required for the theme fast refresh mode.
56
56
  define( 'SCRIPT_DEBUG', true );
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "chisel-scripts",
3
- "version": "2.0.0-alpha.4",
3
+ "version": "2.0.0-alpha.6",
4
4
  "description": "TODO",
5
5
  "bin": {
6
6
  "chisel-scripts": "bin/chisel-scripts.js"
@@ -33,10 +33,11 @@
33
33
  "globby": "^11.0.1",
34
34
  "inquirer": "^7.1.0",
35
35
  "json2php": "^0.0.9",
36
- "lodash": "^4.17.15"
36
+ "lodash": "^4.17.15",
37
+ "svgo": "^3.3.2"
37
38
  },
38
39
  "peerDependencies": {
39
40
  "@wordpress/scripts": "^27.9.0"
40
41
  },
41
- "gitHead": "3209b735b8259ad3296f477cfe13ad3a14d130a9"
42
+ "gitHead": "21320eb0f55ecd1f1df445265608df0778101c8e"
42
43
  }