diff --git a/src/core/fresh-resume.js b/src/core/fresh-resume.js index 1ab8833..a568991 100644 --- a/src/core/fresh-resume.js +++ b/src/core/fresh-resume.js @@ -221,8 +221,14 @@ Definition of the FRESHResume class. */ FreshResume.prototype.keywords = function() { var flatSkills = []; - this.skills && this.skills.length && - (flatSkills = this.skills.map(function(sk) { return sk.name; })); + if( this.skills ) { + if( this.skills.sets ) { + flatSkills = flatSkills.concat( this.skills.sets.map(function(sk) { return sk.name; }) ); + } + else if( this.skills.list ) { + flatSkills = flatSkills.concat( this.skills.list.map(function(sk) { return sk.name; }) ); + } + } return flatSkills; }, diff --git a/src/inspectors/keyword-inspector.js b/src/inspectors/keyword-inspector.js new file mode 100644 index 0000000..d698c09 --- /dev/null +++ b/src/inspectors/keyword-inspector.js @@ -0,0 +1,70 @@ +/** +Keyword analysis for HackMyResume. +@license MIT. See LICENSE.md for details. +@module keyword-inspector.js +*/ + + + +(function() { + + + + var _ = require('underscore'); + var FluentDate = require('../core/fluent-date'); + + + + /** + Analyze the resume's use of keywords. + @class keywordInspector + */ + var keywordInspector = module.exports = { + + + + /** + A unique name for this inspector. + */ + moniker: 'keyword-inspector', + + + + /** + Run the Keyword Inspector on a resume. + @method run + @return An collection of statistical keyword data. + */ + run: function( rez ) { + + // http://stackoverflow.com/a/2593661/4942583 + function regex_quote(str) { + return (str + '').replace(/[.?*+^$[\]\\(){}|-]/ig, "\\$&"); + }; + + var searchable = ''; + rez.transformStrings( [], function trxString( key, val ) { + searchable += val; + }); + + return rez.keywords().map(function(kw) { + var regex = new RegExp( regex_quote( kw ), 'ig'); + var myArray, count = 0; + while ((myArray = regex.exec( searchable )) !== null) { + count++; + } + return { + name: kw, + count: count + }; + + }); + } + + + + }; + + + +}()); diff --git a/src/verbs/analyze.js b/src/verbs/analyze.js index 8954743..2f1cc5b 100644 --- a/src/verbs/analyze.js +++ b/src/verbs/analyze.js @@ -47,26 +47,40 @@ Implementation of the 'analyze' verb for HackMyResume. var safeFormat = (rez.meta && rez.meta.format && rez.meta.format.startsWith('FRESH')) ? 'FRESH' : 'JRS'; + + var padding = 20; log(chalk.cyan('Analyzing ') + chalk.cyan.bold(safeFormat) + chalk.cyan(' resume: ') + chalk.cyan.bold(resumeObject.file)); var info = _.mapObject( nlzrs, function(val, key) { return val.run( resumeObject.rez ); }); - log(chalk.cyan('\nTotals: ')); + log(chalk.cyan('\nSECTIONS (') + chalk.cyan.bold(_.keys(info.totals).length) + chalk.cyan('):\n')); var pad = require('string-padding'); _.each( info.totals, function(tot, key) { - log(chalk.cyan(pad(key + ': ',17)) + chalk.cyan.bold(pad(tot.toString(),4))); + log(chalk.cyan(pad(key + ': ',20)) + chalk.cyan.bold(pad(tot.toString(),4))); }); log(); - log(chalk.cyan('Gaps: ') + chalk.cyan.bold(info.gaps.length) + - chalk.cyan(' [') + info.gaps.map(function(g) { + log(chalk.cyan('GAPS (') + chalk.cyan.bold(info.gaps.length) + chalk.cyan('):\n')); + log(chalk.cyan(pad('Lengths: ', padding + 3)) + info.gaps.map(function(g) { var clr = 'green'; if( g.duration > 35 ) clr = 'yellow'; if( g.duration > 90 ) clr = 'red'; - return chalk[clr].bold(g.duration); - }).join(', ') + chalk.cyan(']') ); + return chalk[clr].bold( g.duration) ; + }).join(', ') ); + + + var tot = 0; + log(); + log( chalk.cyan('KEYWORDS (') + chalk.cyan.bold( info.keywords.length ) + + chalk.cyan('):\n\n') + + info.keywords.map(function(g) { + tot += g.count; + return chalk.cyan( pad(g.name + ': ', padding) ) + chalk.cyan.bold( pad( g.count.toString(), 4 )) + chalk.cyan(' mentions'); + }).join('\n')); + + console.log(chalk.cyan( pad('TOTAL: ', padding) ) + chalk.white.bold( pad( tot.toString(), 4 )) + chalk.cyan(' mentions')); } @@ -77,7 +91,8 @@ Implementation of the 'analyze' verb for HackMyResume. function _loadInspectors() { return { totals: require('../inspectors/totals-inspector'), - gaps: require('../inspectors/gap-inspector') + gaps: require('../inspectors/gap-inspector'), + keywords: require('../inspectors/keyword-inspector') }; }