support a JS config file (#1351)

Thanks to @BrandonOCasey for implementing this feature.
This commit is contained in:
Jeff Williams 2017-07-03 17:00:19 -07:00
parent 4a187da562
commit 2aad297cdc
4 changed files with 78 additions and 8 deletions

16
cli.js
View File

@ -54,6 +54,7 @@ cli.loadConfig = function() {
var _ = require('underscore'); var _ = require('underscore');
var args = require('jsdoc/opts/args'); var args = require('jsdoc/opts/args');
var Config = require('jsdoc/config'); var Config = require('jsdoc/config');
var config;
var fs = require('jsdoc/fs'); var fs = require('jsdoc/fs');
var path = require('jsdoc/path'); var path = require('jsdoc/path');
@ -88,8 +89,19 @@ cli.loadConfig = function() {
} }
try { try {
env.conf = new Config( stripJsonComments(fs.readFileSync(confPath, 'utf8')) ) switch ( path.extname(confPath) ) {
.get(); case '.js':
config = require(confPath) || {};
break;
case '.json':
case '.EXAMPLE':
config = fs.readFileSync(confPath, 'utf8');
break;
default:
cli.exit(1, 'Cannot use config file ' + confPath + '. Only .js and .json files ' +
'are supported.\n' + FATAL_ERROR_MESSAGE);
}
env.conf = new Config(config).get();
} }
catch (e) { catch (e) {
cli.exit(1, 'Cannot parse the config file ' + confPath + ': ' + e + '\n' + cli.exit(1, 'Cannot parse the config file ' + confPath + ': ' + e + '\n' +

View File

@ -10,6 +10,7 @@
'use strict'; 'use strict';
var stripBom = require('jsdoc/util/stripbom'); var stripBom = require('jsdoc/util/stripbom');
var stripJsonComments = require('strip-json-comments');
function mergeRecurse(target, source) { function mergeRecurse(target, source) {
Object.keys(source).forEach(function(p) { Object.keys(source).forEach(function(p) {
@ -47,11 +48,23 @@ var defaults = {
/** /**
@class @class
@classdesc Represents a JSDoc application configuration. @classdesc Represents a JSDoc application configuration.
@param {string} [json] - The contents of config.json. @param {(string|object)} [jsonOrObject] - The contents of config.json, or a JavaScript object
exported from a .js config file.
*/ */
function Config(json) { function Config(jsonOrObject) {
json = JSON.parse( (stripBom.strip(json) || '{}') ); if (typeof jsonOrObject === 'undefined') {
this._config = mergeRecurse(defaults, json); jsonOrObject = {};
}
if (typeof jsonOrObject === 'string') {
jsonOrObject = JSON.parse( (stripJsonComments(stripBom.strip(jsonOrObject)) || '{}') );
}
if (typeof jsonOrObject !== 'object') {
jsonOrObject = {};
}
this._config = mergeRecurse(defaults, jsonOrObject);
} }
module.exports = Config; module.exports = Config;

View File

@ -34,6 +34,13 @@ describe('jsdoc/config', function() {
expect( Array.isArray(config.plugins) ).toBe(true); expect( Array.isArray(config.plugins) ).toBe(true);
expect(config.plugins.length).toBe(0); expect(config.plugins.length).toBe(0);
}); });
it('should be possible to construct a Config with an empty JavaScript object', function() {
var config = new Config({}).get();
expect( Array.isArray(config.plugins) ).toBe(true);
expect(config.plugins.length).toBe(0);
});
}); });
describe('constructor with leading BOM', function() { describe('constructor with leading BOM', function() {
@ -46,6 +53,16 @@ describe('jsdoc/config', function() {
}); });
}); });
describe('constructor with comments', function() {
it('should be possible to construct a Config with JSON that includes comments', function() {
function getConfig() {
return new Config('{\n// comment\n}').get();
}
expect(getConfig).not.toThrow();
});
});
describe('constructor with plugins value', function() { describe('constructor with plugins value', function() {
it('should be possible to construct a Config with JSON of an object literal that has a plugin value', function() { it('should be possible to construct a Config with JSON of an object literal that has a plugin value', function() {
var config = new Config('{"plugins":[42]}').get(); var config = new Config('{"plugins":[42]}').get();
@ -54,6 +71,14 @@ describe('jsdoc/config', function() {
expect(config.plugins.length).toBe(1); expect(config.plugins.length).toBe(1);
expect(config.plugins[0]).toBe(42); expect(config.plugins[0]).toBe(42);
}); });
it('should be possible to construct a Config with a JavaScript object that has a plugin value', function() {
var config = new Config({'plugins': [42]}).get();
expect( Array.isArray(config.plugins) ).toBe(true);
expect(config.plugins.length).toBe(1);
expect(config.plugins[0]).toBe(42);
});
}); });
describe('constructor with source value', function() { describe('constructor with source value', function() {
@ -62,5 +87,11 @@ describe('jsdoc/config', function() {
expect(config.source.includePattern).toBe('hello'); expect(config.source.includePattern).toBe('hello');
}); });
it('should be possible to construct a Config with a JavaScript object that has a source value', function() {
var config = new Config({'source': {'includePattern': 'hello'}}).get();
expect(config.source.includePattern).toBe('hello');
});
}); });
}); });

View File

@ -39,20 +39,34 @@ describe('jsdoc/opts/args', function() {
expect(r.template).toBe('mytemplate'); expect(r.template).toBe('mytemplate');
}); });
it('should accept a "-c" option and return an object with a "configure" property', function() { it('should accept a "-c" option with a JSON file and return an object with a "configure" property', function() {
args.parse(['-c', 'myconf.json']); args.parse(['-c', 'myconf.json']);
var r = args.get(); var r = args.get();
expect(r.configure).toBe('myconf.json'); expect(r.configure).toBe('myconf.json');
}); });
it('should accept a "--configure" option and return an object with a "configure" property', function() { it('should accept a "-c" option with a JS file and return an object with a "configure" property', function() {
args.parse(['-c', 'myconf.js']);
var r = args.get();
expect(r.configure).toBe('myconf.js');
});
it('should accept a "--configure" option with a JSON file and return an object with a "configure" property', function() {
args.parse(['--configure', 'myconf.json']); args.parse(['--configure', 'myconf.json']);
var r = args.get(); var r = args.get();
expect(r.configure).toBe('myconf.json'); expect(r.configure).toBe('myconf.json');
}); });
it('should accept a "--configure" option with a JS file and return an object with a "configure" property', function() {
args.parse(['--configure', 'myconf.js']);
var r = args.get();
expect(r.configure).toBe('myconf.js');
});
it('should accept an "-e" option and return an object with a "encoding" property', function() { it('should accept an "-e" option and return an object with a "encoding" property', function() {
args.parse(['-e', 'ascii']); args.parse(['-e', 'ascii']);
var r = args.get(); var r = args.get();