diff --git a/Gruntfile.js b/Gruntfile.js index 536fe8d..53e15ab 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -17,6 +17,16 @@ module.exports = function (grunt) { all: { src: ['test/*.js'] } }, + jsdoc : { + dist : { + src: ['src/**/*.js'], + options: { + private: true, + destination: 'doc' + } + } + }, + clean: ['test/sandbox'], yuidoc: { @@ -47,13 +57,14 @@ module.exports = function (grunt) { grunt.loadNpmTasks('grunt-simple-mocha'); grunt.loadNpmTasks('grunt-contrib-yuidoc'); + grunt.loadNpmTasks('grunt-jsdoc'); grunt.loadNpmTasks('grunt-contrib-jshint'); grunt.loadNpmTasks('grunt-contrib-clean'); grunt.registerTask('test', 'Test the HackMyResume library.', - function( config ) { grunt.task.run( ['clean','jshint','simplemocha:all'] ); }); + function( config ) { grunt.task.run(['clean','jshint','simplemocha:all']); }); grunt.registerTask('document', 'Generate HackMyResume library documentation.', - function( config ) { grunt.task.run( ['yuidoc'] ); }); - grunt.registerTask('default', [ 'test', 'yuidoc' ]); + function( config ) { grunt.task.run( ['jsdoc'] ); }); + grunt.registerTask('default', [ 'test', 'jsdoc' ]); }; diff --git a/package.json b/package.json index 942f69e..480fe76 100644 --- a/package.json +++ b/package.json @@ -52,7 +52,7 @@ "commander": "^2.9.0", "copy": "^0.1.3", "fresca": "~0.4.0", - "fresh-jrs-converter": "^0.1.1", + "fresh-jrs-converter": "^0.2.0", "fresh-resume-starter": "^0.2.0", "fresh-themes": "~0.13.0-beta", "fs-extra": "^0.24.0", @@ -87,6 +87,7 @@ "grunt-contrib-clean": "^0.7.0", "grunt-contrib-jshint": "^0.11.3", "grunt-contrib-yuidoc": "^0.10.0", + "grunt-jsdoc": "^1.1.0", "grunt-simple-mocha": "*", "jsonresume-theme-boilerplate": "^0.1.2", "jsonresume-theme-classy": "^1.0.9", diff --git a/src/cli/error.js b/src/cli/error.js index 68bb810..fb6b13a 100644 --- a/src/cli/error.js +++ b/src/cli/error.js @@ -156,16 +156,17 @@ Error-handling routines for HackMyResume. ex.data.forEach(function(d){ msg += printf( M2C( this.msgs.invalidFormat.msg, 'bold' ), ex.theme.name.toUpperCase(), d.format.toUpperCase()); - }); + }, this); break; case HACKMYSTATUS.notOnPath: - msg = printf( M2C(this.msgs.notOnPath, 'bold'), ex.engine); + msg = printf( M2C(this.msgs.notOnPath.msg, 'bold'), ex.engine); quit = false; warn = false; break; case HACKMYSTATUS.readError: + console.error( printf( M2C(this.msgs.readError.msg, 'red'), ex.file ) ); msg = ex.inner.toString(); warn = false; break; diff --git a/src/cli/main.js b/src/cli/main.js index bcc0e03..b6aecd3 100644 --- a/src/cli/main.js +++ b/src/cli/main.js @@ -1,6 +1,6 @@ /** Definition of the `main` function. -@module main.js +@module cli/main @license MIT. See LICENSE.md for details. */ @@ -32,9 +32,11 @@ Definition of the `main` function. /** - Main function for HackMyResume - @license MIT. See LICENSE.md for details. - @module main.js + A callable implementation of the HackMyResume CLI. Encapsulates the command + line interface as a single method accepting a parameter array. + @alias module:cli/main.main + @param rawArgs {Array} An array of command-line parameters. Will either be + process.argv (in production) or custom parameters (in test). */ var main = module.exports = function( rawArgs ) { @@ -126,22 +128,23 @@ Definition of the `main` function. - /** - Massage command-line args and setup Commander.js. - */ + /** Massage command-line args and setup Commander.js. */ function initialize( ar ) { logMsg( _title ); var o = initOptions( ar ); + + // Emit debug prelude if --debug was specified if( o.debug ) { _out.log(chalk.cyan('The -d or --debug switch was specified. DEBUG mode engaged.')); _out.log(''); - _out.log(chalk.cyan(PAD(' Platform:',20, null, PAD.RIGHT)) + chalk.cyan.bold( process.platform )); - _out.log(chalk.cyan(PAD(' Node.js:',20, null, PAD.RIGHT)) + chalk.cyan.bold( process.version )); - _out.log(chalk.cyan(PAD(' HackMyResume:',20, null, PAD.RIGHT)) + chalk.cyan.bold('v' + PKG.version )); - _out.log(chalk.cyan(PAD(' FRESCA:',20, null, PAD.RIGHT)) + chalk.cyan.bold( PKG.dependencies.fresca )); - _out.log(chalk.cyan(PAD(' fresh-themes:',20, null, PAD.RIGHT)) + chalk.cyan.bold( PKG.dependencies['fresh-themes'] )); + _out.log(chalk.cyan(PAD(' Platform:',25, null, PAD.RIGHT)) + chalk.cyan.bold( process.platform === 'win32' ? 'windows' : process.platform )); + _out.log(chalk.cyan(PAD(' Node.js:',25, null, PAD.RIGHT)) + chalk.cyan.bold( process.version )); + _out.log(chalk.cyan(PAD(' HackMyResume:',25, null, PAD.RIGHT)) + chalk.cyan.bold('v' + PKG.version )); + _out.log(chalk.cyan(PAD(' FRESCA:',25, null, PAD.RIGHT)) + chalk.cyan.bold( PKG.dependencies.fresca )); + _out.log(chalk.cyan(PAD(' fresh-themes:',25, null, PAD.RIGHT)) + chalk.cyan.bold( PKG.dependencies['fresh-themes'] )); + _out.log(chalk.cyan(PAD(' fresh-jrs-converter:',25, null, PAD.RIGHT)) + chalk.cyan.bold( PKG.dependencies['fresh-jrs-converter'] )); _out.log(''); } @@ -172,14 +175,12 @@ Definition of the `main` function. - /** - Init options prior to setting up command infrastructure. - */ + /** Init options prior to setting up command infrastructure. */ function initOptions( ar ) { var oVerb, verb = '', args = ar.slice(), cleanArgs = args.slice(2), oJSON; if( cleanArgs.length ) { - // Support case-insensitive sub-commands (build, generate, validate, etc.).. + // Support case-insensitive sub-commands (build, generate, validate, etc) var vidx = _.findIndex( cleanArgs, function(v){ return v[0] !== '-'; }); if( vidx !== -1 ) { oVerb = cleanArgs[ vidx ]; @@ -223,9 +224,7 @@ Definition of the `main` function. - /** - Invoke a HackMyResume verb. - */ + /** Invoke a HackMyResume verb. */ function execute( src, dst, opts, log ) { loadOptions.call( this, opts, this.parent.jsonArgs ); @@ -271,7 +270,8 @@ Definition of the `main` function. if( o.debug ) { logMsg(chalk.cyan('OPTIONS:') + '\n'); _.each(o, function(val, key) { - logMsg(chalk.cyan(' %s') + chalk.cyan.bold(' %s'), PAD(key,17,null,PAD.RIGHT), val); + logMsg(chalk.cyan(' %s') + chalk.cyan.bold(' %s'), + PAD(key,17,null,PAD.RIGHT), val); }); logMsg(''); } @@ -282,9 +282,7 @@ Definition of the `main` function. - /** - Split multiple command-line filenames by the 'TO' keyword - */ + /** Split multiple command-line filenames by the 'TO' keyword */ function splitSrcDest() { var params = this.parent.args.filter(function(j) { return String.is(j); }); @@ -314,9 +312,7 @@ Definition of the `main` function. - /** - Simple logging placeholder. - */ + /** Simple logging placeholder. */ function logMsg() { _opts.silent || console.log.apply( console.log, arguments ); } diff --git a/src/cli/msg.yml b/src/cli/msg.yml index 70e87ee..95ca13d 100644 --- a/src/cli/msg.yml +++ b/src/cli/msg.yml @@ -1,10 +1,12 @@ events: + begin: + msg: Invoking **%s** command. beforeCreate: msg: Creating new **%s** resume: **%s** - beforeRead: - msg: Reading resume: **%s** + afterRead: + msg: Reading **%s** resume: **%s** beforeTheme: - msg: Verifying theme: **%s** + msg: Verifying **%s** theme. afterTheme: msg: Verifying outputs: ??? beforeMerge: @@ -72,5 +74,7 @@ errors: msg: The **%s** theme doesn't support the **%s** format. notOnPath: msg: %s wasn't found on your system path or is inaccessible. PDF not generated. + readError: + msg: Reading **???** resume: **%s** parseError: msg: Invalid or corrupt JSON on line %s column %s. diff --git a/src/cli/out.js b/src/cli/out.js index 129d5a3..4d16a7f 100644 --- a/src/cli/out.js +++ b/src/cli/out.js @@ -22,7 +22,8 @@ Output routines for HackMyResume. , HANDLEBARS = require('handlebars') , YAML = require('yamljs') , printf = require('printf') - , pad = require('string-padding'); + , pad = require('string-padding') + , dbgStyle = 'cyan'; @@ -58,8 +59,12 @@ Output routines for HackMyResume. switch( evt.sub ) { + case HME.begin: + this.opts.debug && + L( M2C( this.msgs.begin.msg, dbgStyle), evt.cmd.toUpperCase() ); + break; + case HME.error: - //L('ERROR occured'); break; case HME.beforeCreate: @@ -67,9 +72,6 @@ Output routines for HackMyResume. break; case HME.beforeRead: - L( - M2C( this.msgs.beforeRead.msg, 'cyan' ), evt.file - ); break; case HME.afterRead: @@ -77,12 +79,16 @@ Output routines for HackMyResume. case HME.beforeTheme: this.opts.debug && - L( M2C( this.msgs.beforeTheme.msg, 'cyan'), evt.theme.toUpperCase() ); + L( M2C( this.msgs.beforeTheme.msg, dbgStyle), evt.theme.toUpperCase() ); + break; + + case HME.afterParse: + L( M2C( this.msgs.afterRead.msg, 'green' ), evt.fmt.toUpperCase(), evt.file ); break; case HME.afterTheme: this.theme = evt.theme; - this.opts.debug && L( M2C(this.msgs.beforeTheme.msg, 'cyan'), evt.theme ); + // this.opts.debug && L( M2C(this.msgs.beforeTheme.msg, 'green'), evt.theme ); break; case HME.beforeMerge: @@ -99,7 +105,7 @@ Output routines for HackMyResume. case HME.afterMerge: var numFormats = Object.keys( this.theme.formats ).length; - L( M2C(this.msgs.afterMerge.msg, 'yellow'), + L( M2C(this.msgs.afterMerge.msg, 'green'), this.theme.name.toUpperCase(), numFormats, ( numFormats === 1 ? '' : 's') ); break; @@ -180,7 +186,6 @@ Output routines for HackMyResume. err.message) ); }, this); } - break; case HME.beforePeek: diff --git a/src/core/fresh-resume.js b/src/core/fresh-resume.js index 5dc00c1..6977e34 100644 --- a/src/core/fresh-resume.js +++ b/src/core/fresh-resume.js @@ -27,7 +27,7 @@ Definition of the FRESHResume class. /** A FRESH resume or CV. FRESH resumes are backed by JSON, and each FreshResume object is an instantiation of that JSON decorated with utility methods. - @class FreshResume + @constructor */ function FreshResume() { @@ -61,8 +61,8 @@ Definition of the FRESHResume class. Open and parse the specified FRESH resume. Merge the JSON object model onto this Sheet instance with extend() and convert sheet dates to a safe & consistent format. Then sort each section by startDate descending. - @param rep The raw JSON representation. - @param opts Resume loading and parsing options. + @param rep {Object} The raw JSON representation. + @param opts {Object} Resume loading and parsing options. { date: Perform safe date conversion. sort: Sort resume items by date. diff --git a/src/core/resume-factory.js b/src/core/resume-factory.js index 14924f1..fd77341 100644 --- a/src/core/resume-factory.js +++ b/src/core/resume-factory.js @@ -32,8 +32,8 @@ Definition of the ResumeFactory class. /** Load one or more resumes from disk. - @param opts An options object with settings for the factory as well as - passthrough settings for FRESHResume or JRSResume. Structure: + @param {Object} opts An options object with settings for the factory as well + as passthrough settings for FRESHResume or JRSResume. Structure: { format: 'FRESH', // Format to open as. ('FRESH', 'JRS', null) @@ -107,12 +107,15 @@ Definition of the ResumeFactory class. // Read the file eve && eve.stat( HME.beforeRead, { file: fileName }); rawData = FS.readFileSync( fileName, 'utf8' ); - eve && eve.stat( HME.afterRead, { data: rawData }); + eve && eve.stat( HME.afterRead, { file: fileName, data: rawData }); // Parse the file eve && eve.stat( HME.beforeParse, { data: rawData }); var ret = { json: JSON.parse( rawData ) }; - eve && eve.stat( HME.afterParse, { data: ret.json } ); + var orgFormat = ( ret.json.meta && ret.json.meta.format && + ret.json.meta.format.startsWith('FRESH@') ) ? + 'fresh' : 'jrs'; + eve && eve.stat( HME.afterParse, { file: fileName, data: ret.json, fmt: orgFormat } ); return ret; } diff --git a/src/generators/template-generator.js b/src/generators/template-generator.js index 4dd3580..b5c962f 100644 --- a/src/generators/template-generator.js +++ b/src/generators/template-generator.js @@ -78,8 +78,8 @@ Definition of the TemplateGenerator class. TODO: Refactor @method invoke @param rez A FreshResume object. @param opts Generator options. - @returns An array of objects representing the generated output files. Each - object has this format: + @returns {Array} An array of objects representing the generated output + files. Each object has this format: { files: [ { info: { }, data: [ ] }, { ... } ], diff --git a/src/inspectors/gap-inspector.js b/src/inspectors/gap-inspector.js index bf67ef5..5ce611b 100644 --- a/src/inspectors/gap-inspector.js +++ b/src/inspectors/gap-inspector.js @@ -1,7 +1,7 @@ /** Employment gap analysis for HackMyResume. @license MIT. See LICENSE.md for details. -@module gap-inspector.js +@module inspectors/gap-inspector */ @@ -19,7 +19,6 @@ Employment gap analysis for HackMyResume. /** Identify gaps in the candidate's employment history. - @class gapInspector */ var gapInspector = module.exports = { @@ -32,8 +31,9 @@ Employment gap analysis for HackMyResume. /** Run the Gap Analyzer on a resume. @method run - @return An array of object representing gaps in the candidate's employment - history. Each object provides the start, end, and duration of the gap: + @return {Array} An array of object representing gaps in the candidate's + employment history. Each object provides the start, end, and duration of the + gap: { <-- gap start: // A Moment.js date end: // A Moment.js date diff --git a/src/verbs/analyze.js b/src/verbs/analyze.js index 34ac4ff..5fbb294 100644 --- a/src/verbs/analyze.js +++ b/src/verbs/analyze.js @@ -1,6 +1,6 @@ /** Implementation of the 'analyze' verb for HackMyResume. -@module create.js +@module verbs/analyze @license MIT. See LICENSE.md for details. */ diff --git a/src/verbs/build.js b/src/verbs/build.js index c7df84d..074665c 100644 --- a/src/verbs/build.js +++ b/src/verbs/build.js @@ -1,6 +1,6 @@ /** Implementation of the 'build' verb for HackMyResume. -@module generate.js +@module verbs/build @license MIT. See LICENSE.md for details. */ @@ -33,17 +33,19 @@ Implementation of the 'build' verb for HackMyResume. - /** - An invokable resume generation command. - */ + /** An invokable resume generation command. */ var BuildVerb = module.exports = Verb.extend({ + /** Create a new build verb. */ init: function() { this._super('build'); }, + /** Invoke the Build command. */ invoke: function() { + this.stat( HME.begin, { cmd: 'build' } ); build.apply( this, arguments ); + this.stat( HME.end ); } }); @@ -60,10 +62,18 @@ Implementation of the 'build' verb for HackMyResume. */ function build( src, dst, opts ) { - this.stat( HME.begin ); + + if( !src || !src.length ) { this.err( HACKMYSTATUS.resumeNotFound ); } prep( src, dst, opts ); + // Load input resumes... + var sheets = ResumeFactory.load(src, { + format: null, objectify: true, throw: true, inner: { sort: _opts.sort } + }, this).map( function(sh) { + return sh.rez; + }); + // Load the theme...we do this first because the theme choice (FRESH or // JSON Resume) determines what format we'll convert the resume to. this.stat( HME.beforeTheme, { theme: _opts.theme }); @@ -77,13 +87,6 @@ Implementation of the 'build' verb for HackMyResume. this.err( HACKMYSTATUS.invalidFormat, { data: inv, theme: theme } ); } - // Load input resumes... - if( !src || !src.length ) { this.err( HACKMYSTATUS.resumeNotFound ); } - var sheets = ResumeFactory.load(src, { - format: theme.render ? 'JRS' : 'FRESH', - objectify: true, throw: true, inner: { sort: _opts.sort } - }, this).map( function(sh){ return sh.rez; }); - // Merge input resumes... (sheets.length > 1) && this.stat( HME.beforeMerge, { f: _.clone(sheets) }); rez = _.reduceRight( sheets, function( a, b, idx ) { @@ -100,8 +103,6 @@ Implementation of the 'build' verb for HackMyResume. t.final = single.call( this, t, theme, targets ); }, this); - this.stat( HME.end ); - // Don't send the client back empty-handed return { sheet: rez, targets: targets, processed: targets }; } diff --git a/src/verbs/convert.js b/src/verbs/convert.js index afacf35..dbb42c9 100644 --- a/src/verbs/convert.js +++ b/src/verbs/convert.js @@ -1,6 +1,6 @@ /** Implementation of the 'convert' verb for HackMyResume. -@module convert.js +@module verbs/convert @license MIT. See LICENSE.md for details. */ diff --git a/src/verbs/create.js b/src/verbs/create.js index af55e10..d50b229 100644 --- a/src/verbs/create.js +++ b/src/verbs/create.js @@ -1,6 +1,6 @@ /** Implementation of the 'create' verb for HackMyResume. -@module create.js +@module verbs/create @license MIT. See LICENSE.md for details. */ diff --git a/src/verbs/peek.js b/src/verbs/peek.js index 8c1da37..715d8f8 100644 --- a/src/verbs/peek.js +++ b/src/verbs/peek.js @@ -1,6 +1,6 @@ /** Implementation of the 'peek' verb for HackMyResume. -@module peek.js +@module verbs/peek @license MIT. See LICENSE.md for details. */ diff --git a/src/verbs/validate.js b/src/verbs/validate.js index 0408a6f..36346b4 100644 --- a/src/verbs/validate.js +++ b/src/verbs/validate.js @@ -1,6 +1,6 @@ /** Implementation of the 'validate' verb for HackMyResume. -@module validate.js +@module verbs/validate @license MIT. See LICENSE.md for details. */ diff --git a/src/verbs/verb.js b/src/verbs/verb.js index 8d84136..cbe3af9 100644 --- a/src/verbs/verb.js +++ b/src/verbs/verb.js @@ -1,6 +1,6 @@ /** Definition of the Verb class. -@module verb.js +@module verbs/verb @license MIT. See LICENSE.md for details. */