Skip to content

Commit 51bfaba

Browse files
committed
Fixes an edge case encountered by a certain combination of settings and a lack of an initial tmp file.
1 parent 8c25d5a commit 51bfaba

File tree

1 file changed

+70
-72
lines changed

1 file changed

+70
-72
lines changed

index.js

+70-72
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
*/
55
const webpack = require('webpack');
66
const path = require('path');
7-
const spawn = require('child_process').spawn;
7+
const spawn = require('child_process').spawnSync;
88
const fse = require('fs-extra');
99
const chalk = require('chalk');
1010
const validateOptions = require('schema-utils');
@@ -60,7 +60,7 @@ module.exports = class Plugin {
6060
// If the user has chosen to show output, output information about the finalized
6161
// options the plugin will use.
6262
if (this.options.showOutput) {
63-
console.log(chalk.yellow(`${pluginName}:`), 'Initializing with Options:', this.options);
63+
console.log(chalk.yellow(`${this.pluginName}:`), 'Initializing with Options:', this.options);
6464
}
6565
}
6666
/**
@@ -192,55 +192,64 @@ module.exports = class Plugin {
192192
* @param {string} tmpFile - The full path to the tmpFile. Used for checking whether it exists or not.
193193
* @return {Promise} The Promise returned by the function.
194194
*/
195-
promiseEsdoc(cmd, esdocArgs, esdocConfigDir, tmpFile) {
195+
Esdoc(cmd, esdocArgs, esdocConfigDir, tmpFile) {
196196
let esdocErrors = [];
197-
return new Promise((resolve, reject) => {
198-
const esdoc = spawn(cmd, esdocArgs, {
199-
cwd: esdocConfigDir,
200-
});
201-
// If showOutput is true, collect the socket output from esdoc, turning
202-
// the buffer into something readable.
203-
if (this.options.showOutput) {
204-
let received = '';
197+
const esdoc = spawn(cmd, esdocArgs, {
198+
cwd: esdocConfigDir,
199+
});
205200

206-
// Tell the user it's about to start.
207-
console.log(chalk.yellow(`${pluginName}:`), 'Beginning output.');
201+
// If showOutput is true, collect the socket output from esdoc, turning
202+
// the buffer into something readable.
203+
if (this.options.showOutput) {
208204

209-
// Upon receiving data:
210-
esdoc.stdout.on('data', (data) => {
211-
received += data;
212-
const messages = received.split('\n');
213-
if (messages.length > 1) {
214-
let printed = '';
215-
for (let message of messages) {
216-
if (message !== '') {
217-
let split = (message.toString().split(':'));
218-
console.log(`${chalk.blue(split[0])}: ${chalk.green(split[1])}`);
219-
received = '';
220-
}
221-
}
222-
}
223-
});
224-
}
225-
// Upon an error:
226-
esdoc.stderr.on('data', (data) => esdocErrors.push(data.toString()));
205+
let received = '';
227206

228-
// Upon socket close:
229-
esdoc.on('close', (closeCode) => {
230-
// Remove that tmp file, if one exists, and the user has chosen not to preserve it.
231-
if (tmpFile && !this.options.preserveTmpFile) {
232-
console.log(chalk.yellow(`${this.pluginName}:`), 'Removing temporary esdoc config file...');
233-
fse.unlinkSync(tmpFile);
207+
// Tell the user it's about to start.
208+
console.log(chalk.yellow(`${this.pluginName}:`), 'Beginning output.');
209+
210+
// Show the data.
211+
const esdocOutput = esdoc.stdout;
212+
received += esdocOutput;
213+
const messages = received.split('\n');
214+
// Try to make the buffer data look nicer by coloring parts.
215+
const setOutputPrefixColor = (str) => {
216+
let prefixes = {resolve: 'cyan', output: 'blue', parse: 'green'};
217+
let prefix = str;
218+
for (const key in prefixes) {
219+
if (str === key) {
220+
prefix = chalk[prefixes[key]](str);
221+
break;
222+
}
234223
}
235-
if (esdocErrors.length > 0) {
236-
esdocErrors.forEach((value) => console.error(value));
237-
reject(new Error(chalk.yellow(`${this.pluginName}:`), 'Exited with code ' + code));
238-
} else {
239-
console.log(chalk.yellow(`${this.pluginName}:`), 'Emitted files to output directory.');
240-
resolve(true);
224+
return prefix;
225+
}
226+
if (messages.length > 1) {
227+
let printed = '';
228+
for (let message of messages) {
229+
if (message !== '') {
230+
let split = (message.toString().split(':'));
231+
console.log(`${setOutputPrefixColor(split[0])}: ${chalk.dim(split[1])}`);
232+
received = '';
233+
}
241234
}
242-
});
243-
});
235+
}
236+
}
237+
238+
// Remove that tmp file, if one exists, and the user has chosen not to preserve it.
239+
if (tmpFile && !this.options.preserveTmpFile) {
240+
console.log(chalk.yellow(`${this.pluginName}:`), 'Removing temporary esdoc config file...');
241+
if (fse.existsSync(tmpFile)) {
242+
fse.unlinkSync(tmpFile);
243+
}
244+
}
245+
if ( esdoc.stderr.length > 0) {
246+
console.error('ERR toString', esdoc.stderr.toString());
247+
// esdocErrors.forEach((value) => console.error(value));
248+
return new Error(chalk.yellow(`${this.pluginName}:`), 'Exited with code ' + esdoc.status);
249+
} else {
250+
console.log(chalk.yellow(`${this.pluginName}:`), 'Emitted files to output directory.');
251+
return true;
252+
}
244253
}
245254
/**
246255
* The apply method Webpack plugins must declare.
@@ -271,22 +280,17 @@ module.exports = class Plugin {
271280
tmpFilepath;
272281

273282
/**
274-
* Hooks into watchRun using tapAsync().
283+
* Hooks into emit using tap().
275284
*
276-
* @external {compiler.hooks.watchRun.tapAsync} https://webpack.js.org/api/compiler-hooks/#watchrun
285+
* @external {compiler.hooks.shouldEmit} https://webpack.js.org/api/compiler-hooks/#shouldEmit
286+
* @todo This would probably be better using the emit hook, but no matter
287+
* do it seems like it always forces two runs when watch mode is
288+
* started. Running ESDoc on the compile hook works, but eventually
289+
* it would be good to do this the webpack way with compilation
290+
* modules and chunks and stuff.
291+
* Everything works, but watch is annoying on startup.
277292
*/
278-
compiler.hooks.watchRun.tapAsync(pluginName, (compiler, callback) => {
279-
// During the Webpack watchRun event, notify the user that the plugin is watching for changes.
280-
console.log(chalk.yellow(`${pluginName}`), chalk.magenta('Watching for changes...'));
281-
callback();
282-
});
283-
284-
/**
285-
* Hooks into emit using tapAsync().
286-
*
287-
* @external {compiler.hooks.emit.tapAsync} https://webpack.js.org/api/compiler-hooks/#emit
288-
*/
289-
compiler.hooks.emit.tapAsync(pluginName, (compilation, callback) => {
293+
compiler.hooks.compilation.tap(pluginName, (compilation) => {
290294
// Let the user know ESDocPlugin is running.
291295
console.log(chalk.yellow(`${pluginName}:`), 'Compiling...');
292296

@@ -366,7 +370,11 @@ module.exports = class Plugin {
366370
esdocArgs = ['-c', esdocConfig];
367371

368372
// End the emit hook.
369-
callback();
373+
try {
374+
this.Esdoc(cmd, esdocArgs, esdocConfigDir, tmpFile, obj)
375+
} catch (err) {
376+
return new Error(pluginName, 'There was a problem running ESDoc.');
377+
}
370378
});
371379

372380
/**
@@ -375,18 +383,8 @@ module.exports = class Plugin {
375383
* @external {compiler.hooks.done.tapAsync} https://webpack.js.org/api/compiler-hooks/#done
376384
*/
377385
compiler.hooks.done.tap(pluginName, (stats) => {
378-
// @TODO: Really this run of ESDoc as a child process should probably happen in the emit hook,
379-
// but if it's there, watching makes emit trigger twice on startup. I'm guessing the
380-
// reason this happens is that emit finishes before the subprocess has totally exited,
381-
// so when it finally does end, the ESDoc process creates/modifies files in the plugin
382-
// output directory get created and compilation starts all over again.
383-
// I need a way to ignore the output files or directory for this plugin during watch, it
384-
// doesn't matter if something happens there.
385-
this.promiseEsdoc(cmd, esdocArgs, esdocConfigDir, tmpFile, obj)
386-
.then(response => {
387-
console.log(chalk.yellow(`${pluginName}:`), 'Finished compiling.');
388-
console.log(chalk.yellow(`${pluginName}:`), 'Total run time ', chalk.green(self.millisToMinutesAndSeconds(stats.endTime - stats.startTime)));
389-
})
386+
console.log(chalk.yellow(`${pluginName}:`), 'Finished.');
387+
console.log(chalk.yellow(`${pluginName}:`), 'Total run time ', chalk.green(self.millisToMinutesAndSeconds(stats.endTime - stats.startTime)));
390388
});
391389

392390
}

0 commit comments

Comments
 (0)