sdc-build-wp 4.1.3 → 4.2.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.
- package/.phpcs.xml +0 -1
- package/index.js +82 -198
- package/lib/components/base.js +36 -0
- package/lib/components/blocks.js +98 -0
- package/lib/components/fonts.js +36 -0
- package/lib/components/images.js +47 -0
- package/lib/components/index.js +7 -0
- package/lib/components/php.js +91 -0
- package/lib/components/scripts.js +77 -0
- package/lib/components/server.js +62 -0
- package/lib/components/style.js +189 -0
- package/lib/project.js +34 -2
- package/lib/utils.js +38 -0
- package/package.json +1 -1
- package/lib/blocks.js +0 -63
- package/lib/browsersync.js +0 -55
- package/lib/fonts.js +0 -19
- package/lib/images.js +0 -22
- package/lib/php.js +0 -71
- package/lib/scripts.js +0 -49
- package/lib/style.js +0 -155
package/.phpcs.xml
CHANGED
package/index.js
CHANGED
|
@@ -1,48 +1,22 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import path from 'path';
|
|
3
|
-
import project from './lib/project.js';
|
|
4
3
|
import parseArgs from 'minimist';
|
|
5
4
|
const argv = parseArgs(process.argv.slice(2));
|
|
6
|
-
import
|
|
7
|
-
import {
|
|
8
|
-
import { existsSync } from 'node:fs';
|
|
5
|
+
import { glob } from 'node:fs/promises';
|
|
6
|
+
import { promises as fs } from 'fs';
|
|
9
7
|
import { Tail } from 'tail';
|
|
10
|
-
|
|
8
|
+
import project from './lib/project.js';
|
|
9
|
+
import * as utils from './lib/utils.js';
|
|
11
10
|
import log from './lib/logging.js';
|
|
12
|
-
import
|
|
13
|
-
import buildJS from './lib/scripts.js';
|
|
14
|
-
import { default as buildPHP, shouldPHPLint } from './lib/php.js';
|
|
15
|
-
import buildBlock from './lib/blocks.js';
|
|
16
|
-
import buildImages from './lib/images.js';
|
|
17
|
-
import buildFonts from './lib/fonts.js';
|
|
18
|
-
import buildBrowserSync from './lib/browsersync.js';
|
|
19
|
-
|
|
20
|
-
let paths = {
|
|
21
|
-
theme: {
|
|
22
|
-
json: `${project.path}/theme.json`,
|
|
23
|
-
scss: `${project.path}/_src/style/partials/_theme.scss`
|
|
24
|
-
},
|
|
25
|
-
nodeModules: `${project.path}/node_modules`,
|
|
26
|
-
composer: {
|
|
27
|
-
vendor: `${project.path}/vendor`
|
|
28
|
-
},
|
|
29
|
-
images: project.package?.sdc?.imagesPath || `${project.path}/_src/images`,
|
|
30
|
-
errorLog: process.env.ERROR_LOG_PATH || project.package.sdc?.error_log_path || '../../../../../logs/php/error.log'
|
|
31
|
-
};
|
|
11
|
+
import * as Components from './lib/components/index.js';
|
|
32
12
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
};
|
|
41
|
-
|
|
42
|
-
let globs = {};
|
|
43
|
-
let entries = {};
|
|
44
|
-
let filesSass = [];
|
|
45
|
-
let filesJS = [];
|
|
13
|
+
const styleComponent = new Components.style();
|
|
14
|
+
const scriptsComponent = new Components.scripts();
|
|
15
|
+
const blocksComponent = new Components.blocks();
|
|
16
|
+
const imagesComponent = new Components.images();
|
|
17
|
+
const fontsComponent = new Components.fonts();
|
|
18
|
+
const phpComponent = new Components.php();
|
|
19
|
+
const serverComponent = new Components.server();
|
|
46
20
|
|
|
47
21
|
let builds = argv.builds ? argv.builds.split(',') : [
|
|
48
22
|
'sass',
|
|
@@ -53,224 +27,134 @@ let builds = argv.builds ? argv.builds.split(',') : [
|
|
|
53
27
|
'php'
|
|
54
28
|
];
|
|
55
29
|
|
|
30
|
+
for (const [name, files] of Object.entries(project.package.sdc.entries)) {
|
|
31
|
+
project.entries[name] = [];
|
|
32
|
+
files.forEach(function(file) {
|
|
33
|
+
project.entries[name].push(project.path + file);
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
for (const [name, files] of Object.entries(project.entries)) {
|
|
38
|
+
files.forEach(function(file) {
|
|
39
|
+
switch (path.parse(file).ext) {
|
|
40
|
+
case '.scss':
|
|
41
|
+
if (builds.includes('sass')) {
|
|
42
|
+
project.files.sass.push({
|
|
43
|
+
'name': name,
|
|
44
|
+
'file': file
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
break;
|
|
48
|
+
case '.js':
|
|
49
|
+
if (builds.includes('js')) {
|
|
50
|
+
project.files.js.push({
|
|
51
|
+
'name': name,
|
|
52
|
+
'file': file
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
break;
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
|
|
56
60
|
(async() => {
|
|
57
61
|
|
|
58
62
|
let initialBuildTimerStart = Date.now();
|
|
59
63
|
log('info', `Starting initial build`);
|
|
60
64
|
|
|
61
65
|
if (builds.includes('sass')) {
|
|
62
|
-
globs.sass = await Array.fromAsync(
|
|
66
|
+
project.globs.sass = await Array.fromAsync(
|
|
63
67
|
glob(project.package?.sdc?.sassGlobPath ||
|
|
64
68
|
`${project.path}{/_src/style,/blocks}/**/*.scss`)
|
|
65
69
|
);
|
|
70
|
+
await styleComponent.process();
|
|
66
71
|
}
|
|
72
|
+
|
|
67
73
|
if (builds.includes('js')) {
|
|
68
|
-
globs.js = await Array.fromAsync(
|
|
74
|
+
project.globs.js = await Array.fromAsync(
|
|
69
75
|
glob(project.package?.sdc?.jsGlobPath ||
|
|
70
76
|
`${project.path}/_src/scripts/**/*.js`)
|
|
71
77
|
);
|
|
78
|
+
await scriptsComponent.process();
|
|
72
79
|
}
|
|
80
|
+
|
|
73
81
|
if (builds.includes('blocks')) {
|
|
74
|
-
globs.blocks = await Array.fromAsync(
|
|
82
|
+
project.globs.blocks = await Array.fromAsync(
|
|
75
83
|
glob(`${project.path}/blocks/*`)
|
|
76
84
|
);
|
|
77
|
-
globs.blocksSass = await Array.fromAsync(
|
|
85
|
+
project.globs.blocksSass = await Array.fromAsync(
|
|
78
86
|
glob(`${project.path}/blocks/*/src/*.scss`)
|
|
79
87
|
);
|
|
80
|
-
// for (var filename of globs.blocksSass) {
|
|
81
|
-
// entries[`blocks/${path.basename(path.dirname(filename))}/style`] = [ filename ];
|
|
88
|
+
// for (var filename of project.globs.blocksSass) {
|
|
89
|
+
// project.entries[`blocks/${path.basename(path.dirname(filename))}/style`] = [ filename ];
|
|
82
90
|
// }
|
|
91
|
+
await blocksComponent.process();
|
|
83
92
|
}
|
|
93
|
+
|
|
84
94
|
if (builds.includes('images')) {
|
|
85
|
-
globs.images = await Array.fromAsync(
|
|
95
|
+
project.globs.images = await Array.fromAsync(
|
|
86
96
|
glob(project.package?.sdc?.imagesPath ||
|
|
87
|
-
`${paths.images}/**/*`)
|
|
97
|
+
`${project.paths.images}/**/*`)
|
|
88
98
|
);
|
|
89
|
-
globs.imageDirectories = [
|
|
90
|
-
paths.images,
|
|
91
|
-
...await getAllSubdirectories(paths.images)
|
|
99
|
+
project.globs.imageDirectories = [
|
|
100
|
+
project.paths.images,
|
|
101
|
+
...await utils.getAllSubdirectories(project.paths.images)
|
|
92
102
|
];
|
|
103
|
+
await imagesComponent.process();
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
if (builds.includes('fonts')) {
|
|
107
|
+
await fontsComponent.process();
|
|
93
108
|
}
|
|
109
|
+
|
|
94
110
|
if (builds.includes('php')) {
|
|
95
|
-
globs.php = await Array.fromAsync(
|
|
111
|
+
project.globs.php = await Array.fromAsync(
|
|
96
112
|
glob(project.package?.sdc?.jsGlobPath ||
|
|
97
113
|
`${project.path}/**/*.php`)
|
|
98
114
|
);
|
|
99
|
-
globs.blocksPHP = await Array.fromAsync(
|
|
115
|
+
project.globs.blocksPHP = await Array.fromAsync(
|
|
100
116
|
glob(`${project.path}/blocks/*/build/*.php`)
|
|
101
117
|
);
|
|
102
|
-
chokidarOpts.ignored
|
|
103
|
-
|
|
104
|
-
...globs.blocksPHP
|
|
105
|
-
];
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
for (const [name, files] of Object.entries(project.package.sdc.entries)) {
|
|
109
|
-
entries[name] = [];
|
|
110
|
-
files.forEach(function(file) {
|
|
111
|
-
entries[name].push(project.path + file);
|
|
112
|
-
});
|
|
118
|
+
project.chokidarOpts.ignored.concat(project.globs.blocksPHP);
|
|
119
|
+
// await phpComponent.process(null, { lintType: 'warn' }); // this errors "Fatal error: Allowed memory size"
|
|
113
120
|
}
|
|
114
121
|
|
|
115
|
-
for (const [name, files] of Object.entries(entries)) {
|
|
116
|
-
files.forEach(function(file) {
|
|
117
|
-
switch (path.parse(file).ext) {
|
|
118
|
-
case '.scss':
|
|
119
|
-
if (builds.includes('sass')) {
|
|
120
|
-
filesSass.push({
|
|
121
|
-
'name': name,
|
|
122
|
-
'file': file
|
|
123
|
-
});
|
|
124
|
-
}
|
|
125
|
-
break;
|
|
126
|
-
case '.js':
|
|
127
|
-
if (builds.includes('js')) {
|
|
128
|
-
filesJS.push({
|
|
129
|
-
'name': name,
|
|
130
|
-
'file': file
|
|
131
|
-
});
|
|
132
|
-
}
|
|
133
|
-
break;
|
|
134
|
-
}
|
|
135
|
-
});
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
if (builds.includes('sass')) {
|
|
139
|
-
await runSass(null, true);
|
|
140
|
-
}
|
|
141
|
-
if (builds.includes('js')) {
|
|
142
|
-
await runJS();
|
|
143
|
-
}
|
|
144
|
-
if (builds.includes('blocks')) {
|
|
145
|
-
await runBlocks();
|
|
146
|
-
}
|
|
147
|
-
if (builds.includes('images')) {
|
|
148
|
-
await frontrunImages();
|
|
149
|
-
}
|
|
150
|
-
if (builds.includes('fonts')) {
|
|
151
|
-
await buildFonts(project.path + '/_src/fonts');
|
|
152
|
-
}
|
|
153
|
-
// if (builds.includes('php') && shouldPHPLint) {
|
|
154
|
-
// await runPHP(null, 'warn'); // this errors "Fatal error: Allowed memory size"
|
|
155
|
-
// }
|
|
156
|
-
|
|
157
122
|
log('info', `Finished initial build in ${Math.round((Date.now() - initialBuildTimerStart) / 1000)} seconds`);
|
|
158
123
|
|
|
159
124
|
if (argv.watch) {
|
|
160
125
|
|
|
161
|
-
|
|
126
|
+
serverComponent.start();
|
|
162
127
|
|
|
163
128
|
if (builds.includes('sass')) {
|
|
164
|
-
|
|
165
|
-
...[paths.theme.json],
|
|
166
|
-
globs.sass
|
|
167
|
-
], {
|
|
168
|
-
...chokidarOpts
|
|
169
|
-
}).on('all', (event, path) => {
|
|
170
|
-
let hasRanSingle = false;
|
|
171
|
-
for (var block of filesSass) {
|
|
172
|
-
if (path == block.file || getImportedFilesSass(block.file).includes(path)) {
|
|
173
|
-
runSass(block.file, path == paths.theme.json);
|
|
174
|
-
hasRanSingle = true;
|
|
175
|
-
}
|
|
176
|
-
}
|
|
177
|
-
if (!hasRanSingle) {
|
|
178
|
-
runSass(null, path == paths.theme.json);
|
|
179
|
-
}
|
|
180
|
-
});
|
|
129
|
+
styleComponent.watch();
|
|
181
130
|
}
|
|
182
131
|
|
|
183
132
|
if (builds.includes('js')) {
|
|
184
|
-
|
|
185
|
-
...chokidarOpts
|
|
186
|
-
}).on('all', (event, path) => {
|
|
187
|
-
runJS();
|
|
188
|
-
});
|
|
133
|
+
scriptsComponent.watch();
|
|
189
134
|
}
|
|
190
135
|
|
|
191
136
|
if (builds.includes('blocks')) {
|
|
192
|
-
|
|
193
|
-
chokidar.watch(`${block}/src`, {
|
|
194
|
-
...chokidarOpts
|
|
195
|
-
}).on('all', (event, path) => {
|
|
196
|
-
runBlocks(block);
|
|
197
|
-
});
|
|
198
|
-
}
|
|
137
|
+
blocksComponent.watch();
|
|
199
138
|
}
|
|
200
139
|
|
|
201
140
|
if (builds.includes('images')) {
|
|
202
|
-
|
|
203
|
-
frontrunImages();
|
|
204
|
-
});
|
|
141
|
+
imagesComponent.watch();
|
|
205
142
|
}
|
|
206
143
|
|
|
207
|
-
if (builds.includes('php') && shouldPHPLint) {
|
|
208
|
-
|
|
209
|
-
...chokidarOpts
|
|
210
|
-
}).on('all', (event, path) => {
|
|
211
|
-
runPHP(path);
|
|
212
|
-
});
|
|
144
|
+
if (builds.includes('php') && project.shouldPHPLint) {
|
|
145
|
+
phpComponent.watch();
|
|
213
146
|
}
|
|
214
147
|
|
|
215
|
-
|
|
216
|
-
|
|
148
|
+
try {
|
|
149
|
+
await fs.access(project.paths.errorLog);
|
|
150
|
+
let errorLogTail = new Tail(project.paths.errorLog);
|
|
217
151
|
errorLogTail.on('line', function(data) {
|
|
218
152
|
log('php', data);
|
|
219
153
|
});
|
|
220
|
-
}
|
|
221
|
-
log('info', `Cannot find error log @ ${paths.errorLog}. Skipping watching php error logs`);
|
|
154
|
+
} catch (error) {
|
|
155
|
+
log('info', `Cannot find error log @ ${project.paths.errorLog}. Skipping watching php error logs`);
|
|
222
156
|
}
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
})();
|
|
226
|
-
|
|
227
|
-
async function frontrunImages() {
|
|
228
|
-
const promisesImages = globs.imageDirectories.map(directory => buildImages(directory));
|
|
229
|
-
await Promise.all(promisesImages);
|
|
230
|
-
}
|
|
231
157
|
|
|
232
|
-
async function runBlocks(singleBlock) {
|
|
233
|
-
if (singleBlock) {
|
|
234
|
-
await buildBlock(singleBlock);
|
|
235
|
-
} else {
|
|
236
|
-
const promisesBlocks = globs.blocks.map(block => buildBlock(block));
|
|
237
|
-
await Promise.all(promisesBlocks);
|
|
238
158
|
}
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
async function runSass(singleEntry, buildTheme = true) {
|
|
242
|
-
if (buildTheme) {
|
|
243
|
-
await buildSassTheme();
|
|
244
|
-
}
|
|
245
|
-
for (var block of filesSass) {
|
|
246
|
-
if (!singleEntry || singleEntry == block.file) {
|
|
247
|
-
await buildSass(block.file, block.name, globs.sass);
|
|
248
|
-
if (singleEntry == block.file) {
|
|
249
|
-
break;
|
|
250
|
-
}
|
|
251
|
-
}
|
|
252
|
-
}
|
|
253
|
-
}
|
|
254
159
|
|
|
255
|
-
|
|
256
|
-
const promisesJS = filesJS.map(block => buildJS(block.file, block.name, globs.js));
|
|
257
|
-
await Promise.all(promisesJS);
|
|
258
|
-
}
|
|
259
|
-
|
|
260
|
-
async function runPHP(file, method) {
|
|
261
|
-
await buildPHP(file, method);
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
async function getAllSubdirectories(dir) {
|
|
265
|
-
let subdirectories = [];
|
|
266
|
-
const subdirectoriesEntries = await readdir(dir, { withFileTypes: true });
|
|
267
|
-
for (const subdirectoriesEntry of subdirectoriesEntries) {
|
|
268
|
-
if (subdirectoriesEntry.isDirectory()) {
|
|
269
|
-
const subdirPath = path.join(dir, subdirectoriesEntry.name);
|
|
270
|
-
subdirectories.push(subdirPath);
|
|
271
|
-
const nestedSubdirs = await getAllSubdirectories(subdirPath);
|
|
272
|
-
subdirectories = subdirectories.concat(nestedSubdirs);
|
|
273
|
-
}
|
|
274
|
-
}
|
|
275
|
-
return subdirectories;
|
|
276
|
-
}
|
|
160
|
+
})();
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import path from 'path';
|
|
2
|
+
import project from '../project.js';
|
|
3
|
+
import log from '../logging.js';
|
|
4
|
+
import chokidar from 'chokidar';
|
|
5
|
+
|
|
6
|
+
class BaseComponent {
|
|
7
|
+
|
|
8
|
+
constructor() {
|
|
9
|
+
this.timer = null;
|
|
10
|
+
this.path = path;
|
|
11
|
+
this.project = project;
|
|
12
|
+
this.log = log;
|
|
13
|
+
this.chokidar = chokidar;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
start() {
|
|
17
|
+
this.timer = Date.now();
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
end(options) {
|
|
21
|
+
options = Object.assign({}, {
|
|
22
|
+
verb: 'Built',
|
|
23
|
+
itemLabel: null,
|
|
24
|
+
timerStart: this.timer,
|
|
25
|
+
timerEnd: Date.now()
|
|
26
|
+
}, options);
|
|
27
|
+
this.log('success', `${options.verb}${options.itemLabel ? ` ${options.itemLabel}` : ''} in ${options.timerEnd - options.timerStart}ms`);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
entryBasename(entry) {
|
|
31
|
+
return this.path.parse(entry).base;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export { BaseComponent as default }
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import BaseComponent from './base.js';
|
|
2
|
+
import { stat } from 'fs/promises';
|
|
3
|
+
import { spawn } from 'child_process';
|
|
4
|
+
import process from 'process';
|
|
5
|
+
|
|
6
|
+
class BlocksComponent extends BaseComponent {
|
|
7
|
+
|
|
8
|
+
constructor() {
|
|
9
|
+
super();
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
async build(entry, options) {
|
|
13
|
+
options = Object.assign({}, {}, options);
|
|
14
|
+
let entryLabel = entry.replace(this.project.path, '');
|
|
15
|
+
|
|
16
|
+
let timerStart = Date.now();
|
|
17
|
+
|
|
18
|
+
this.start();
|
|
19
|
+
|
|
20
|
+
let workingBlockJson = null;
|
|
21
|
+
let potentialBlockJsonLocations = [
|
|
22
|
+
`${entry}/src/block.json`,
|
|
23
|
+
// `${entry}/block.json`
|
|
24
|
+
];
|
|
25
|
+
for (var location of potentialBlockJsonLocations) {
|
|
26
|
+
try {
|
|
27
|
+
await stat(location);
|
|
28
|
+
workingBlockJson = location
|
|
29
|
+
break;
|
|
30
|
+
} catch (error) {
|
|
31
|
+
//
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
if (workingBlockJson === null) {
|
|
35
|
+
this.log('error', `Failed building ${entry} blocks - no block.json found.`);
|
|
36
|
+
return false;
|
|
37
|
+
}
|
|
38
|
+
let cmds = [
|
|
39
|
+
`${this.project.path}/node_modules/@wordpress/scripts/bin/wp-scripts.js`,
|
|
40
|
+
`build`,
|
|
41
|
+
`--source-path=.${entry.replace(this.project.path, '')}/src`,
|
|
42
|
+
`--output-path=.${entry.replace(this.project.path, '')}/build`,
|
|
43
|
+
`--webpack-copy-php`
|
|
44
|
+
];
|
|
45
|
+
await cmd(cmds, { entryLabel: entryLabel });
|
|
46
|
+
|
|
47
|
+
this.end({
|
|
48
|
+
itemLabel: entryLabel,
|
|
49
|
+
timerStart: timerStart,
|
|
50
|
+
timerEnd: Date.now()
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
async process(entry) {
|
|
55
|
+
if (entry) {
|
|
56
|
+
await this.build(entry);
|
|
57
|
+
} else {
|
|
58
|
+
const promisesBlocks = this.project.globs.blocks.map(block => this.build(block));
|
|
59
|
+
await Promise.all(promisesBlocks);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
watch() {
|
|
64
|
+
for (let block of this.project.globs.blocks) {
|
|
65
|
+
this.chokidar.watch(`${block}/src`, {
|
|
66
|
+
...this.project.chokidarOpts
|
|
67
|
+
}).on('all', (event, path) => {
|
|
68
|
+
this.process(block);
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
function cmd(commands) {
|
|
76
|
+
let p = spawn(commands[0], commands.slice(1), {
|
|
77
|
+
shell: true
|
|
78
|
+
});
|
|
79
|
+
return new Promise((resolveFunc) => {
|
|
80
|
+
p.stdout.on('data', (x) => {
|
|
81
|
+
if (x.toString().includes('Error:')) {
|
|
82
|
+
process.stdout.write(x.toString());
|
|
83
|
+
log('error', `Failed building ${entryLabel} block - See above error.`);
|
|
84
|
+
}
|
|
85
|
+
});
|
|
86
|
+
p.stderr.on('data', (x) => {
|
|
87
|
+
if (x.toString().includes('Error:')) {
|
|
88
|
+
process.stderr.write(x.toString());
|
|
89
|
+
log('error', `Failed building ${entryLabel} block - See above error.`);
|
|
90
|
+
}
|
|
91
|
+
});
|
|
92
|
+
p.on('exit', (code) => {
|
|
93
|
+
resolveFunc(code);
|
|
94
|
+
});
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
export { BlocksComponent as default }
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import BaseComponent from './base.js';
|
|
2
|
+
import { readdir } from 'fs/promises';
|
|
3
|
+
import fs from 'fs-extra';
|
|
4
|
+
|
|
5
|
+
class FontsComponent extends BaseComponent {
|
|
6
|
+
|
|
7
|
+
constructor() {
|
|
8
|
+
super();
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
async build(entry) {
|
|
12
|
+
let entryLabel = `/dist/fonts`;
|
|
13
|
+
|
|
14
|
+
this.start();
|
|
15
|
+
|
|
16
|
+
try {
|
|
17
|
+
const fontsDir = await readdir(entry);
|
|
18
|
+
if (fontsDir.length == 0) { throw new Error('No files present'); }
|
|
19
|
+
await fs.copy(entry, `${this.project.path}${entryLabel}`);
|
|
20
|
+
} catch(error) {
|
|
21
|
+
this.log('info', `${error} at ${entry.replace(this.project.path, '')}/. Skipping font copy`);
|
|
22
|
+
return false;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
this.end({
|
|
26
|
+
itemLabel: entryLabel
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
async process() {
|
|
31
|
+
await this.build(`${this.project.path}/_src/fonts`);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export { FontsComponent as default }
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import BaseComponent from './base.js';
|
|
2
|
+
import imagemin from 'imagemin';
|
|
3
|
+
import imageminJpegtran from 'imagemin-jpegtran';
|
|
4
|
+
import imageminPngquant from 'imagemin-pngquant';
|
|
5
|
+
import imageminSvgo from 'imagemin-svgo';
|
|
6
|
+
|
|
7
|
+
class ImagesComponent extends BaseComponent {
|
|
8
|
+
|
|
9
|
+
constructor() {
|
|
10
|
+
super();
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
async build(entry, options) {
|
|
14
|
+
let timerStart = Date.now();
|
|
15
|
+
let dest = entry.replace('_src/images', 'dist/images');
|
|
16
|
+
const files = await imagemin([entry + '/*'], {
|
|
17
|
+
destination: dest,
|
|
18
|
+
plugins: [
|
|
19
|
+
imageminJpegtran(),
|
|
20
|
+
imageminPngquant(),
|
|
21
|
+
imageminSvgo()
|
|
22
|
+
]
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
this.end({
|
|
26
|
+
itemLabel: `${dest.replace(this.project.path, '')} (${files.length} image${files.length == 1 ? '' : 's'})`,
|
|
27
|
+
timerStart: timerStart,
|
|
28
|
+
timerEnd: Date.now()
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
async process() {
|
|
33
|
+
const promisesImages = this.project.globs.imageDirectories.map(directory => this.build(directory));
|
|
34
|
+
await Promise.all(promisesImages);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
watch() {
|
|
38
|
+
this.chokidar.watch(this.project.paths.images, {
|
|
39
|
+
...this.project.chokidarOpts
|
|
40
|
+
}).on('all', (event, path) => {
|
|
41
|
+
this.process();
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export { ImagesComponent as default }
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export { default as style } from './style.js';
|
|
2
|
+
export { default as scripts } from './scripts.js';
|
|
3
|
+
export { default as blocks } from './blocks.js';
|
|
4
|
+
export { default as images } from './images.js';
|
|
5
|
+
export { default as fonts } from './fonts.js';
|
|
6
|
+
export { default as php } from './php.js';
|
|
7
|
+
export { default as server } from './server.js';
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import BaseComponent from './base.js';
|
|
2
|
+
import { fileURLToPath } from 'url';
|
|
3
|
+
import { exec } from 'child_process';
|
|
4
|
+
import { promisify } from 'util';
|
|
5
|
+
|
|
6
|
+
class PHPComponent extends BaseComponent {
|
|
7
|
+
|
|
8
|
+
constructor() {
|
|
9
|
+
super();
|
|
10
|
+
this.execPromise = promisify(exec);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
async build(entry, options) {
|
|
14
|
+
options = Object.assign({}, {
|
|
15
|
+
lintType: 'fix'
|
|
16
|
+
}, options);
|
|
17
|
+
let entryLabel = `all PHP files`;
|
|
18
|
+
|
|
19
|
+
this.start();
|
|
20
|
+
let workingLintBin = 'phpcbf';
|
|
21
|
+
if (options.lintType == 'warn') {
|
|
22
|
+
workingLintBin = 'phpcs';
|
|
23
|
+
}
|
|
24
|
+
let phpFiles = '.';
|
|
25
|
+
let additionalFlags = '';
|
|
26
|
+
if (entry) {
|
|
27
|
+
phpFiles = entry;
|
|
28
|
+
entryLabel = entry.replace(this.project.path, '');
|
|
29
|
+
} else {
|
|
30
|
+
additionalFlags += ' -d memory_limit=2G'; // FIXME: this doesn't solve error issue "Fatal error: Allowed memory size"
|
|
31
|
+
}
|
|
32
|
+
try {
|
|
33
|
+
const cmds = [
|
|
34
|
+
`vendor/bin/${workingLintBin}`,
|
|
35
|
+
`--parallel=5`,
|
|
36
|
+
`--error-severity=1`,
|
|
37
|
+
`--warning-severity=1`,
|
|
38
|
+
`--colors`,
|
|
39
|
+
`--basepath=${this.project.path}`,
|
|
40
|
+
phpFiles,
|
|
41
|
+
additionalFlags
|
|
42
|
+
];
|
|
43
|
+
|
|
44
|
+
const { stdout, stderr } = await this.execPromise(cmds.join(' '), {
|
|
45
|
+
cwd: this.path.resolve(this.path.dirname(fileURLToPath(import.meta.url)), '../../')
|
|
46
|
+
}); // returns an error if any violations are found, so we can't rely on the try/catch as usual
|
|
47
|
+
} catch (error) {
|
|
48
|
+
if (
|
|
49
|
+
error.stderr?.length ||
|
|
50
|
+
(
|
|
51
|
+
error.stdout?.length &&
|
|
52
|
+
(
|
|
53
|
+
error.stdout.startsWith('ERROR:') ||
|
|
54
|
+
error.stdout.includes('FAILED TO FIX')
|
|
55
|
+
)
|
|
56
|
+
)
|
|
57
|
+
) {
|
|
58
|
+
console.error(error.stderr?.length ? error.stderr : error.stdout);
|
|
59
|
+
this.log('error', `Failed linting ${entryLabel.replace(this.project.path, '')} - See above error.`);
|
|
60
|
+
return false;
|
|
61
|
+
} else {
|
|
62
|
+
if (error.stdout?.length) {
|
|
63
|
+
console.log(error.stdout);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
if (this.project.server) {
|
|
68
|
+
this.project.server.reload();
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
this.end({
|
|
72
|
+
itemLabel: entryLabel,
|
|
73
|
+
verb: `Linted (${options.lintType})`
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
async process(entry, options) {
|
|
78
|
+
await this.build(entry, options);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
watch() {
|
|
82
|
+
this.chokidar.watch(this.project.globs.php, {
|
|
83
|
+
...this.project.chokidarOpts
|
|
84
|
+
}).on('all', (event, path) => {
|
|
85
|
+
this.process(path);
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
export { PHPComponent as default }
|