| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465 | 
							- /* eslint-disable indent, no-process-exit */
 
- /**
 
-  * Helper methods for running JSDoc on the command line.
 
-  *
 
-  * A few critical notes for anyone who works on this module:
 
-  *
 
-  * + The module should really export an instance of `cli`, and `props` should be properties of a
 
-  * `cli` instance.
 
-  *
 
-  * @private
 
-  */
 
- module.exports = (() => {
 
-     const app = require('jsdoc/app');
 
-     const env = require('jsdoc/env');
 
-     const logger = require('jsdoc/util/logger');
 
-     const stripBom = require('jsdoc/util/stripbom');
 
-     const stripJsonComments = require('strip-json-comments');
 
-     const Promise = require('bluebird');
 
-     const props = {
 
-         docs: [],
 
-         packageJson: null,
 
-         shouldExitWithError: false,
 
-         tmpdir: null
 
-     };
 
-     const FATAL_ERROR_MESSAGE = 'Exiting JSDoc because an error occurred. See the previous log ' +
 
-         'messages for details.';
 
-     const cli = {};
 
-     // TODO: docs
 
-     cli.setVersionInfo = () => {
 
-         const fs = require('fs');
 
-         const path = require('path');
 
-         // allow this to throw--something is really wrong if we can't read our own package file
 
-         const info = JSON.parse( stripBom.strip(fs.readFileSync(path.join(env.dirname, 'package.json'),
 
-             'utf8')) );
 
-         env.version = {
 
-             number: info.version,
 
-             revision: new Date( parseInt(info.revision, 10) ).toUTCString()
 
-         };
 
-         return cli;
 
-     };
 
-     // TODO: docs
 
-     cli.loadConfig = () => {
 
-         const _ = require('underscore');
 
-         const args = require('jsdoc/opts/args');
 
-         const Config = require('jsdoc/config');
 
-         let config;
 
-         const fs = require('jsdoc/fs');
 
-         const path = require('jsdoc/path');
 
-         let confPath;
 
-         let isFile;
 
-         const defaultOpts = {
 
-             destination: './out/',
 
-             encoding: 'utf8'
 
-         };
 
-         try {
 
-             env.opts = args.parse(env.args);
 
-         }
 
-         catch (e) {
 
-             console.error(`${e.message}\n`);
 
-             cli.printHelp().then(() => {
 
-                 cli.exit(1);
 
-             });
 
-         }
 
-         confPath = env.opts.configure || path.join(env.dirname, 'conf.json');
 
-         try {
 
-             isFile = fs.statSync(confPath).isFile();
 
-         }
 
-         catch (e) {
 
-             isFile = false;
 
-         }
 
-         if ( !isFile && !env.opts.configure ) {
 
-             confPath = path.join(env.dirname, 'conf.json.EXAMPLE');
 
-         }
 
-         try {
 
-             switch ( path.extname(confPath) ) {
 
-                 case '.js':
 
-                     config = require( path.resolve(confPath) ) || {};
 
-                     break;
 
-                 case '.json':
 
-                 case '.EXAMPLE':
 
-                 default:
 
-                     config = fs.readFileSync(confPath, 'utf8');
 
-                     break;
 
-             }
 
-             env.conf = new Config(config).get();
 
-         }
 
-         catch (e) {
 
-             cli.exit(1, `Cannot parse the config file ${confPath}: ${e}\n${FATAL_ERROR_MESSAGE}`);
 
-         }
 
-         // look for options on the command line, in the config file, and in the defaults, in that order
 
-         env.opts = _.defaults(env.opts, env.conf.opts, defaultOpts);
 
-         return cli;
 
-     };
 
-     // TODO: docs
 
-     cli.configureLogger = () => {
 
-         function recoverableError() {
 
-             props.shouldExitWithError = true;
 
-         }
 
-         function fatalError() {
 
-             cli.exit(1);
 
-         }
 
-         if (env.opts.debug) {
 
-             logger.setLevel(logger.LEVELS.DEBUG);
 
-         }
 
-         else if (env.opts.verbose) {
 
-             logger.setLevel(logger.LEVELS.INFO);
 
-         }
 
-         if (env.opts.pedantic) {
 
-             logger.once('logger:warn', recoverableError);
 
-             logger.once('logger:error', fatalError);
 
-         }
 
-         else {
 
-             logger.once('logger:error', recoverableError);
 
-         }
 
-         logger.once('logger:fatal', fatalError);
 
-         return cli;
 
-     };
 
-     // TODO: docs
 
-     cli.logStart = () => {
 
-         logger.debug( cli.getVersion() );
 
-         logger.debug('Environment info: %j', {
 
-             env: {
 
-                 conf: env.conf,
 
-                 opts: env.opts
 
-             }
 
-         });
 
-     };
 
-     // TODO: docs
 
-     cli.logFinish = () => {
 
-         let delta;
 
-         let deltaSeconds;
 
-         if (env.run.finish && env.run.start) {
 
-             delta = env.run.finish.getTime() - env.run.start.getTime();
 
-         }
 
-         if (delta !== undefined) {
 
-             deltaSeconds = (delta / 1000).toFixed(2);
 
-             logger.info('Finished running in %s seconds.', deltaSeconds);
 
-         }
 
-     };
 
-     // TODO: docs
 
-     cli.runCommand = cb => {
 
-         let cmd;
 
-         const opts = env.opts;
 
-         if (opts.help) {
 
-             cmd = cli.printHelp;
 
-         }
 
-         else if (opts.test) {
 
-             cmd = cli.runTests;
 
-         }
 
-         else if (opts.version) {
 
-             cmd = cli.printVersion;
 
-         }
 
-         else {
 
-             cmd = cli.main;
 
-         }
 
-         cmd().then(errorCode => {
 
-             if (!errorCode && props.shouldExitWithError) {
 
-                 errorCode = 1;
 
-             }
 
-             cb(errorCode);
 
-         });
 
-     };
 
-     // TODO: docs
 
-     cli.printHelp = () => {
 
-         cli.printVersion();
 
-         console.log( `\n${require('jsdoc/opts/args').help()}\n` );
 
-         console.log('Visit https://jsdoc.app/ for more information.');
 
-         return Promise.resolve(0);
 
-     };
 
-     // TODO: docs
 
-     cli.runTests = () => {
 
-         const path = require('jsdoc/path');
 
-         const runner = Promise.promisify(require( path.join(env.dirname, 'test/runner') ));
 
-         console.log('Running tests...');
 
-         return runner();
 
-     };
 
-     // TODO: docs
 
-     cli.getVersion = () => `JSDoc ${env.version.number} (${env.version.revision})`;
 
-     // TODO: docs
 
-     cli.printVersion = () => {
 
-         console.log( cli.getVersion() );
 
-         return Promise.resolve(0);
 
-     };
 
-     // TODO: docs
 
-     cli.main = () => {
 
-         cli.scanFiles();
 
-         if (env.sourceFiles.length === 0) {
 
-             console.log('There are no input files to process.');
 
-             return Promise.resolve(0);
 
-         } else {
 
-             return cli.createParser()
 
-                 .parseFiles()
 
-                 .processParseResults()
 
-                 .then(() => {
 
-                     env.run.finish = new Date();
 
-                     return 0;
 
-                 });
 
-         }
 
-     };
 
-     function readPackageJson(filepath) {
 
-         const fs = require('jsdoc/fs');
 
-         try {
 
-             return stripJsonComments( fs.readFileSync(filepath, 'utf8') );
 
-         }
 
-         catch (e) {
 
-             logger.error('Unable to read the package file "%s"', filepath);
 
-             return null;
 
-         }
 
-     }
 
-     function buildSourceList() {
 
-         const Readme = require('jsdoc/readme');
 
-         let packageJson;
 
-         let readmeHtml;
 
-         let sourceFile;
 
-         let sourceFiles = env.opts._ ? env.opts._.slice(0) : [];
 
-         if (env.conf.source && env.conf.source.include) {
 
-             sourceFiles = sourceFiles.concat(env.conf.source.include);
 
-         }
 
-         // load the user-specified package/README files, if any
 
-         if (env.opts.package) {
 
-             packageJson = readPackageJson(env.opts.package);
 
-         }
 
-         if (env.opts.readme) {
 
-             readmeHtml = new Readme(env.opts.readme).html;
 
-         }
 
-         // source files named `package.json` or `README.md` get special treatment, unless the user
 
-         // explicitly specified a package and/or README file
 
-         for (let i = 0, l = sourceFiles.length; i < l; i++) {
 
-             sourceFile = sourceFiles[i];
 
-             if ( !env.opts.package && /\bpackage\.json$/i.test(sourceFile) ) {
 
-                 packageJson = readPackageJson(sourceFile);
 
-                 sourceFiles.splice(i--, 1);
 
-             }
 
-             if ( !env.opts.readme && /(\bREADME|\.md)$/i.test(sourceFile) ) {
 
-                 readmeHtml = new Readme(sourceFile).html;
 
-                 sourceFiles.splice(i--, 1);
 
-             }
 
-         }
 
-         props.packageJson = packageJson;
 
-         env.opts.readme = readmeHtml;
 
-         return sourceFiles;
 
-     }
 
-     // TODO: docs
 
-     cli.scanFiles = () => {
 
-         const Filter = require('jsdoc/src/filter').Filter;
 
-         let filter;
 
-         env.opts._ = buildSourceList();
 
-         // are there any files to scan and parse?
 
-         if (env.conf.source && env.opts._.length) {
 
-             filter = new Filter(env.conf.source);
 
-             env.sourceFiles = app.jsdoc.scanner.scan(env.opts._,
 
-                 (env.opts.recurse ? env.conf.recurseDepth : undefined), filter);
 
-         }
 
-         return cli;
 
-     };
 
-     function resolvePluginPaths(paths) {
 
-         const path = require('jsdoc/path');
 
-         const pluginPaths = [];
 
-         paths.forEach(plugin => {
 
-             const basename = path.basename(plugin);
 
-             const dirname = path.dirname(plugin);
 
-             const pluginPath = path.getResourcePath(dirname, basename);
 
-             if (!pluginPath) {
 
-                 logger.error('Unable to find the plugin "%s"', plugin);
 
-                 return;
 
-             }
 
-             pluginPaths.push( pluginPath );
 
-         });
 
-         return pluginPaths;
 
-     }
 
-     cli.createParser = () => {
 
-         const handlers = require('jsdoc/src/handlers');
 
-         const parser = require('jsdoc/src/parser');
 
-         const plugins = require('jsdoc/plugins');
 
-         app.jsdoc.parser = parser.createParser(env.conf.parser);
 
-         if (env.conf.plugins) {
 
-             env.conf.plugins = resolvePluginPaths(env.conf.plugins);
 
-             plugins.installPlugins(env.conf.plugins, app.jsdoc.parser);
 
-         }
 
-         handlers.attachTo(app.jsdoc.parser);
 
-         return cli;
 
-     };
 
-     cli.parseFiles = () => {
 
-         const augment = require('jsdoc/augment');
 
-         const borrow = require('jsdoc/borrow');
 
-         const Package = require('jsdoc/package').Package;
 
-         let docs;
 
-         let packageDocs;
 
-         props.docs = docs = app.jsdoc.parser.parse(env.sourceFiles, env.opts.encoding);
 
-         // If there is no package.json, just create an empty package
 
-         packageDocs = new Package(props.packageJson);
 
-         packageDocs.files = env.sourceFiles || [];
 
-         docs.push(packageDocs);
 
-         logger.debug('Adding inherited symbols, mixins, and interface implementations...');
 
-         augment.augmentAll(docs);
 
-         logger.debug('Adding borrowed doclets...');
 
-         borrow.resolveBorrows(docs);
 
-         logger.debug('Post-processing complete.');
 
-         app.jsdoc.parser.fireProcessingComplete(docs);
 
-         return cli;
 
-     };
 
-     cli.processParseResults = () => {
 
-         if (env.opts.explain) {
 
-             cli.dumpParseResults();
 
-             return Promise.resolve();
 
-         }
 
-         else {
 
-             cli.resolveTutorials();
 
-             return cli.generateDocs();
 
-         }
 
-     };
 
-     cli.dumpParseResults = () => {
 
-         console.log(require('jsdoc/util/dumper').dump(props.docs));
 
-         return cli;
 
-     };
 
-     cli.resolveTutorials = () => {
 
-         const resolver = require('jsdoc/tutorial/resolver');
 
-         if (env.opts.tutorials) {
 
-             resolver.load(env.opts.tutorials);
 
-             resolver.resolve();
 
-         }
 
-         return cli;
 
-     };
 
-     cli.generateDocs = () => {
 
-         const path = require('jsdoc/path');
 
-         const resolver = require('jsdoc/tutorial/resolver');
 
-         const { taffy } = require('@jsdoc/salty');
 
-         let template;
 
-         env.opts.template = (() => {
 
-             const publish = env.opts.template || 'templates/default';
 
-             const templatePath = path.getResourcePath(publish);
 
-             // if we didn't find the template, keep the user-specified value so the error message is
 
-             // useful
 
-             return templatePath || env.opts.template;
 
-         })();
 
-         try {
 
-             template = require(`${env.opts.template}/publish`);
 
-         }
 
-         catch (e) {
 
-             logger.fatal(`Unable to load template: ${e.message}` || e);
 
-         }
 
-         // templates should include a publish.js file that exports a "publish" function
 
-         if (template.publish && typeof template.publish === 'function') {
 
-             let publishPromise;
 
-             logger.info('Generating output files...');
 
-             publishPromise = template.publish(
 
-                 taffy(props.docs),
 
-                 env.opts,
 
-                 resolver.root
 
-             );
 
-             return Promise.resolve(publishPromise);
 
-         }
 
-         else {
 
-             logger.fatal(`${env.opts.template} does not export a "publish" function. Global "publish" functions are no longer supported.`);
 
-         }
 
-         return Promise.resolve();
 
-     };
 
-     // TODO: docs
 
-     cli.exit = (exitCode, message) => {
 
-         if (exitCode > 0 && message) {
 
-             console.error(message);
 
-         }
 
-         process.on('exit', () => { process.exit(exitCode); });
 
-     };
 
-     return cli;
 
- })();
 
 
  |