UNPKG

2.62 kBJavaScriptView Raw
1const errorPage = require('../serve/error_page');
2const fs = require('fs');
3const path = require('path');
4const chokidar = require('chokidar');
5const sharedOptions = require('./shared_options');
6const Server = require('../serve/server');
7const _ = require('lodash');
8const getPort = require('get-port');
9const documentation = require('../');
10
11module.exports.command = 'serve [input..]';
12module.exports.description = 'generate, update, and display HTML documentation';
13/**
14 * Add yargs parsing for the serve command
15 * @param {Object} yargs module instance
16 * @returns {Object} yargs with options
17 * @private
18 */
19module.exports.builder = Object.assign(
20 {},
21 sharedOptions.sharedOutputOptions,
22 sharedOptions.sharedInputOptions,
23 {
24 port: {
25 describe: 'preferred port for the local server',
26 type: 'number',
27 default: 4001
28 }
29 }
30);
31
32/**
33 * Wrap the documentation build command along with a server, making it possible
34 * to preview changes live
35 * @private
36 * @param {Object} argv cli input
37 * @returns {undefined} has side effects
38 */
39module.exports.handler = function serve(argv) {
40 argv._handled = true;
41
42 if (!argv.input.length) {
43 try {
44 argv.input = [
45 JSON.parse(fs.readFileSync(path.resolve('package.json'), 'utf8'))
46 .main || 'index.js'
47 ];
48 } catch (e) {
49 throw new Error(
50 'documentation was given no files and was not run in a module directory'
51 );
52 }
53 }
54
55 getPort({ port: argv.port }).then(port => {
56 const server = new Server(port);
57 let watcher;
58
59 server.on('listening', function() {
60 process.stdout.write(`documentation.js serving on port ${port}\n`);
61 });
62
63 function updateWatcher() {
64 if (!watcher) {
65 watcher = chokidar.watch(argv.input);
66 watcher.on('all', _.debounce(updateServer, 300));
67 }
68
69 documentation
70 .expandInputs(argv.input, argv)
71 .then(files => {
72 watcher.add(
73 files.map(data => (typeof data === 'string' ? data : data.file))
74 );
75 })
76 .catch(err => {
77 /* eslint no-console: 0 */
78 return server.setFiles([errorPage(err)]).start();
79 });
80 }
81
82 function updateServer() {
83 documentation
84 .build(argv.input, argv)
85 .then(comments => documentation.formats.html(comments, argv))
86 .then(files => {
87 if (argv.watch) {
88 updateWatcher();
89 }
90 server.setFiles(files).start();
91 })
92 .catch(err => {
93 return server.setFiles([errorPage(err)]).start();
94 });
95 }
96
97 updateServer();
98 });
99};