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 args = require('jsdoc/opts/args');
var Config = require('jsdoc/config');
var config;
var fs = require('jsdoc/fs');
var path = require('jsdoc/path');
@ -88,8 +89,19 @@ cli.loadConfig = function() {
}
try {
env.conf = new Config( stripJsonComments(fs.readFileSync(confPath, 'utf8')) )
.get();
switch ( path.extname(confPath) ) {
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) {
cli.exit(1, 'Cannot parse the config file ' + confPath + ': ' + e + '\n' +

View File

@ -10,6 +10,7 @@
'use strict';
var stripBom = require('jsdoc/util/stripbom');
var stripJsonComments = require('strip-json-comments');
function mergeRecurse(target, source) {
Object.keys(source).forEach(function(p) {
@ -47,11 +48,23 @@ var defaults = {
/**
@class
@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) {
json = JSON.parse( (stripBom.strip(json) || '{}') );
this._config = mergeRecurse(defaults, json);
function Config(jsonOrObject) {
if (typeof jsonOrObject === 'undefined') {
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;

View File

@ -34,6 +34,13 @@ describe('jsdoc/config', function() {
expect( Array.isArray(config.plugins) ).toBe(true);
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() {
@ -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() {
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();
@ -54,6 +71,14 @@ describe('jsdoc/config', function() {
expect(config.plugins.length).toBe(1);
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() {
@ -62,5 +87,11 @@ describe('jsdoc/config', function() {
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');
});
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']);
var r = args.get();
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']);
var r = args.get();
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() {
args.parse(['-e', 'ascii']);
var r = args.get();