2016-01-25 15:34:57 +00:00
( function ( ) {
2018-02-12 05:05:29 +00:00
/ * *
Definition of the ` main ` function .
@ module cli / main
@ license MIT . See LICENSE . md for details .
* /
/* Invoke a HackMyResume verb. */
/* Success handler for verb invocations. Calls process.exit by default */
/* Init options prior to setting up command infrastructure. */
/* Massage command-line args and setup Commander.js. */
/ *
Initialize HackMyResume options .
TODO : Options loading is a little hacky , for two reasons :
- Commander . js idiosyncracies
- Need to accept JSON inputs from the command line .
* /
/* Simple logging placeholder. */
/* Split multiple command-line filenames by the 'TO' keyword */
2018-02-12 09:01:00 +00:00
var Command , EXTEND , FS , HMR , HMSTATUS , M2C , OUTPUT , PAD , PATH , PKG , _ , _err , _exitCallback , _opts , _out , _title , chalk , execute , executeFail , executeSuccess , initOptions , initialize , loadOptions , logMsg , printf , safeLoadJSON , splitSrcDest ;
2016-01-25 15:34:57 +00:00
2016-01-29 20:23:57 +00:00
HMR = require ( '../index' ) ;
2016-01-25 15:34:57 +00:00
PKG = require ( '../../package.json' ) ;
FS = require ( 'fs' ) ;
EXTEND = require ( 'extend' ) ;
chalk = require ( 'chalk' ) ;
PATH = require ( 'path' ) ;
2016-01-29 20:23:57 +00:00
HMSTATUS = require ( '../core/status-codes' ) ;
2016-01-25 15:34:57 +00:00
2016-01-29 20:23:57 +00:00
safeLoadJSON = require ( '../utils/safe-json-loader' ) ;
2016-01-25 15:34:57 +00:00
2018-02-12 09:01:00 +00:00
//StringUtils = require '../utils/string.js'
2016-01-25 15:34:57 +00:00
_ = require ( 'underscore' ) ;
OUTPUT = require ( './out' ) ;
PAD = require ( 'string-padding' ) ;
Command = require ( 'commander' ) . Command ;
2016-02-03 00:02:56 +00:00
M2C = require ( '../utils/md2chalk' ) ;
printf = require ( 'printf' ) ;
2016-01-25 15:34:57 +00:00
_opts = { } ;
_title = chalk . white . bold ( '\n*** HackMyResume v' + PKG . version + ' ***' ) ;
_out = new OUTPUT ( _opts ) ;
2016-02-02 02:14:36 +00:00
_err = require ( './error' ) ;
_exitCallback = null ;
2018-02-12 09:01:00 +00:00
/ *
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 ) .
* /
module . exports = function ( rawArgs , exitCallback ) {
2016-01-25 15:34:57 +00:00
var args , initInfo , program ;
2016-02-02 02:14:36 +00:00
initInfo = initialize ( rawArgs , exitCallback ) ;
2018-01-29 07:04:00 +00:00
if ( initInfo === null ) {
return ;
}
2016-01-25 15:34:57 +00:00
args = initInfo . args ;
2018-02-12 05:05:29 +00:00
// Create the top-level (application) command...
2016-01-25 15:34:57 +00:00
program = new Command ( 'hackmyresume' ) . version ( PKG . version ) . description ( chalk . yellow . bold ( '*** HackMyResume ***' ) ) . option ( '-s --silent' , 'Run in silent mode' ) . option ( '--no-color' , 'Disable colors' ) . option ( '--color' , 'Enable colors' ) . option ( '-d --debug' , 'Enable diagnostics' , false ) . option ( '-a --assert' , 'Treat warnings as errors' , false ) . option ( '-v --version' , 'Show the version' ) . allowUnknownOption ( ) ;
program . jsonArgs = initInfo . options ;
2018-02-12 05:05:29 +00:00
// Create the NEW command
program . command ( 'new' ) . arguments ( '<sources...>' ) . option ( '-f --format <fmt>' , 'FRESH or JRS format' , 'FRESH' ) . alias ( 'create' ) . description ( 'Create resume(s) in FRESH or JSON RESUME format.' ) . action ( ( function ( sources ) {
2016-01-25 15:34:57 +00:00
execute . call ( this , sources , [ ] , this . opts ( ) , logMsg ) ;
} ) ) ;
2018-02-12 05:05:29 +00:00
// Create the VALIDATE command
program . command ( 'validate' ) . arguments ( '<sources...>' ) . description ( 'Validate a resume in FRESH or JSON RESUME format.' ) . action ( function ( sources ) {
2016-01-25 15:34:57 +00:00
execute . call ( this , sources , [ ] , this . opts ( ) , logMsg ) ;
} ) ;
2018-02-12 05:05:29 +00:00
// Create the CONVERT command
2018-02-10 02:34:24 +00:00
program . command ( 'convert' ) . description ( 'Convert a resume to/from FRESH or JSON RESUME format.' ) . option ( '-f --format <fmt>' , 'FRESH or JRS format and optional version' , void 0 ) . action ( function ( ) {
2016-01-25 15:34:57 +00:00
var x ;
x = splitSrcDest . call ( this ) ;
execute . call ( this , x . src , x . dst , this . opts ( ) , logMsg ) ;
} ) ;
2018-02-12 05:05:29 +00:00
// Create the ANALYZE command
program . command ( 'analyze' ) . arguments ( '<sources...>' ) . option ( '--private' , 'Include resume fields marked as private' , false ) . description ( 'Analyze one or more resumes.' ) . action ( function ( sources ) {
2016-01-25 15:34:57 +00:00
execute . call ( this , sources , [ ] , this . opts ( ) , logMsg ) ;
} ) ;
2018-02-12 05:05:29 +00:00
// Create the PEEK command
2018-02-12 09:01:00 +00:00
//.action(( sources, sectionOrField ) ->
program . command ( 'peek' ) . arguments ( '<sources...>' ) . description ( 'Peek at a resume field or section' ) . action ( function ( sources ) {
2016-01-25 15:34:57 +00:00
var dst ;
2018-02-12 05:05:29 +00:00
dst = ( sources && sources . length > 1 ) ? [ sources . pop ( ) ] : [ ] ;
2016-01-25 15:34:57 +00:00
execute . call ( this , sources , dst , this . opts ( ) , logMsg ) ;
} ) ;
2018-02-12 05:05:29 +00:00
// Create the BUILD command
2018-02-12 09:01:00 +00:00
//.action(( sources, targets, options ) ->
program . command ( 'build' ) . alias ( 'generate' ) . option ( '-t --theme <theme>' , 'Theme name or path' ) . option ( '-n --no-prettify' , 'Disable HTML prettification' , true ) . option ( '-c --css <option>' , 'CSS linking / embedding' ) . option ( '-p --pdf <engine>' , 'PDF generation engine' ) . option ( '--no-sort' , 'Sort resume sections by date' , false ) . option ( '--tips' , 'Display theme tips and warnings.' , false ) . option ( '--private' , 'Include resume fields marked as private' , false ) . option ( '--no-escape' , 'Turn off encoding in Handlebars themes.' , false ) . description ( 'Generate resume to multiple formats' ) . action ( function ( ) {
2016-01-25 15:34:57 +00:00
var x ;
x = splitSrcDest . call ( this ) ;
execute . call ( this , x . src , x . dst , this . opts ( ) , logMsg ) ;
} ) ;
2018-02-12 05:05:29 +00:00
// Create the HELP command
program . command ( 'help' ) . arguments ( '[command]' ) . description ( 'Get help on a HackMyResume command' ) . action ( function ( cmd ) {
2018-02-10 18:28:42 +00:00
var manPage ;
cmd = cmd || 'use' ;
manPage = FS . readFileSync ( PATH . join ( _ _dirname , 'help/' + cmd + '.txt' ) , 'utf8' ) ;
_out . log ( M2C ( manPage , 'white' , 'yellow.bold' ) ) ;
2018-02-10 18:03:52 +00:00
} ) ;
2016-01-25 15:34:57 +00:00
program . parse ( args ) ;
if ( ! program . args . length ) {
throw {
fluenterror : 4
} ;
}
} ;
2016-02-02 02:14:36 +00:00
initialize = function ( ar , exitCallback ) {
2016-01-25 15:34:57 +00:00
var o ;
2016-02-02 02:14:36 +00:00
_exitCallback = exitCallback || process . exit ;
2016-01-25 15:34:57 +00:00
o = initOptions ( ar ) ;
2018-01-29 07:04:00 +00:00
if ( o . ex ) {
_err . init ( false , true , false ) ;
if ( o . ex . op === 'parse' ) {
_err . err ( {
fluenterror : o . ex . op === 'parse' ? HMSTATUS . invalidOptionsFile : HMSTATUS . optionsFileNotFound ,
inner : o . ex . inner ,
quit : true
} ) ;
} else {
_err . err ( {
fluenterror : HMSTATUS . optionsFileNotFound ,
inner : o . ex . inner ,
quit : true
} ) ;
}
return null ;
}
2016-01-25 15:34:57 +00:00
o . silent || logMsg ( _title ) ;
2018-02-12 05:05:29 +00:00
// Emit debug prelude if --debug was specified
2016-01-25 15:34:57 +00:00
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:' , 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 ) ) ;
2018-02-12 05:05:29 +00:00
//_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'] ))
2016-01-25 15:34:57 +00:00
_out . log ( '' ) ;
}
2016-02-02 02:14:36 +00:00
_err . init ( o . debug , o . assert , o . silent ) ;
2018-02-12 05:05:29 +00:00
// Handle invalid verbs here (a bit easier here than in commander.js)...
2018-02-10 18:03:52 +00:00
if ( o . verb && ! HMR . verbs [ o . verb ] && ! HMR . alias [ o . verb ] && o . verb !== 'help' ) {
2016-02-02 02:14:36 +00:00
_err . err ( {
2016-01-25 15:34:57 +00:00
fluenterror : HMSTATUS . invalidCommand ,
quit : true ,
attempted : o . orgVerb
2016-02-02 02:14:36 +00:00
} , true ) ;
2016-01-25 15:34:57 +00:00
}
2018-02-12 05:05:29 +00:00
// Override the .missingArgument behavior
2018-02-12 09:01:00 +00:00
Command . prototype . missingArgument = function ( /* unused */ ) {
2018-02-10 18:03:52 +00:00
if ( this . name ( ) !== 'help' ) {
_err . err ( {
2018-02-11 13:13:13 +00:00
verb : this . name ( ) ,
fluenterror : HMSTATUS . resumeNotFound
2018-02-10 18:03:52 +00:00
} , true ) ;
}
2016-01-25 15:34:57 +00:00
} ;
2018-02-12 05:05:29 +00:00
// Override the .helpInformation behavior
2016-01-25 15:34:57 +00:00
Command . prototype . helpInformation = function ( ) {
var manPage ;
2018-02-10 18:28:42 +00:00
manPage = FS . readFileSync ( PATH . join ( _ _dirname , 'help/use.txt' ) , 'utf8' ) ;
2018-02-10 18:03:52 +00:00
return M2C ( manPage , 'white' , 'yellow' ) ;
2016-01-25 15:34:57 +00:00
} ;
return {
args : o . args ,
options : o . json
} ;
} ;
initOptions = function ( ar ) {
oVerb ;
2018-02-12 05:05:29 +00:00
/* jshint ignore:end */
2018-01-29 10:21:46 +00:00
var args , cleanArgs , inf , isAssert , isDebug , isMono , isNoEscape , isSilent , oJSON , oVerb , optStr , optsIdx , verb , vidx ;
2016-01-25 15:34:57 +00:00
verb = '' ;
args = ar . slice ( ) ;
cleanArgs = args . slice ( 2 ) ;
oJSON ;
if ( cleanArgs . length ) {
2018-02-12 05:05:29 +00:00
// Support case-insensitive sub-commands (build, generate, validate, etc)
2016-01-25 15:34:57 +00:00
vidx = _ . findIndex ( cleanArgs , function ( v ) {
return v [ 0 ] !== '-' ;
} ) ;
if ( vidx !== - 1 ) {
oVerb = cleanArgs [ vidx ] ;
verb = args [ vidx + 2 ] = oVerb . trim ( ) . toLowerCase ( ) ;
}
2018-02-12 05:05:29 +00:00
// Remove --options --opts -o and process separately
2016-01-25 15:34:57 +00:00
optsIdx = _ . findIndex ( cleanArgs , function ( v ) {
return v === '-o' || v === '--options' || v === '--opts' ;
} ) ;
if ( optsIdx !== - 1 ) {
optStr = cleanArgs [ optsIdx + 1 ] ;
args . splice ( optsIdx + 2 , 2 ) ;
if ( optStr && ( optStr = optStr . trim ( ) ) ) {
2018-02-12 05:05:29 +00:00
//var myJSON = JSON.parse(optStr);
2016-01-25 15:34:57 +00:00
if ( optStr [ 0 ] === '{' ) {
2018-02-12 05:05:29 +00:00
// TODO: remove use of evil(). - hacksalot
2016-01-25 15:34:57 +00:00
/* jshint ignore:start */
2018-02-12 05:05:29 +00:00
oJSON = eval ( '(' + optStr + ')' ) ; // jshint ignore:line <-- no worky
2016-01-25 15:34:57 +00:00
} else {
inf = safeLoadJSON ( optStr ) ;
if ( ! inf . ex ) {
oJSON = inf . json ;
2018-01-29 07:04:00 +00:00
} else {
return inf ;
2016-01-25 15:34:57 +00:00
}
}
}
}
}
2018-02-12 05:05:29 +00:00
// Grab the --debug flag, --silent, --assert and --no-color flags
2016-01-25 15:34:57 +00:00
isDebug = _ . some ( args , function ( v ) {
return v === '-d' || v === '--debug' ;
} ) ;
isSilent = _ . some ( args , function ( v ) {
return v === '-s' || v === '--silent' ;
} ) ;
2016-02-02 02:14:36 +00:00
isAssert = _ . some ( args , function ( v ) {
return v === '-a' || v === '--assert' ;
} ) ;
2016-01-26 15:58:10 +00:00
isMono = _ . some ( args , function ( v ) {
return v === '--no-color' ;
} ) ;
2018-01-29 10:21:46 +00:00
isNoEscape = _ . some ( args , function ( v ) {
return v === '--no-escape' ;
} ) ;
2016-01-25 15:34:57 +00:00
return {
2016-01-26 15:58:10 +00:00
color : ! isMono ,
2016-01-25 15:34:57 +00:00
debug : isDebug ,
silent : isSilent ,
2016-02-02 02:14:36 +00:00
assert : isAssert ,
2018-01-29 10:21:46 +00:00
noescape : isNoEscape ,
2016-01-25 15:34:57 +00:00
orgVerb : oVerb ,
verb : verb ,
json : oJSON ,
args : args
} ;
} ;
execute = function ( src , dst , opts , log ) {
2016-02-03 00:02:56 +00:00
var prom , v ;
2018-02-12 05:05:29 +00:00
// Create the verb
2016-01-25 15:34:57 +00:00
v = new HMR . verbs [ this . name ( ) ] ( ) ;
2018-02-12 05:05:29 +00:00
// Initialize command-specific options
2016-02-02 02:14:36 +00:00
loadOptions . call ( this , opts , this . parent . jsonArgs ) ;
2018-02-12 05:05:29 +00:00
// Set up error/output handling
2016-01-25 15:34:57 +00:00
_opts . errHandler = v ;
_out . init ( _opts ) ;
2018-02-12 05:05:29 +00:00
// Hook up event notifications
2016-01-25 15:34:57 +00:00
v . on ( 'hmr:status' , function ( ) {
2018-02-12 05:05:29 +00:00
return _out . do . apply ( _out , arguments ) ;
2016-01-25 15:34:57 +00:00
} ) ;
v . on ( 'hmr:error' , function ( ) {
2016-02-02 02:14:36 +00:00
return _err . err . apply ( _err , arguments ) ;
2016-01-25 15:34:57 +00:00
} ) ;
2018-02-12 05:05:29 +00:00
// Invoke the verb using promise syntax
2016-02-02 02:14:36 +00:00
prom = v . invoke . call ( v , src , dst , _opts , log ) ;
2016-02-03 00:02:56 +00:00
prom . then ( executeSuccess , executeFail ) ;
} ;
2018-02-12 09:01:00 +00:00
executeSuccess = function ( /*obj*/ ) { } ;
2016-02-03 00:02:56 +00:00
2018-02-12 05:05:29 +00:00
// Can't call _exitCallback here (process.exit) when PDF is running in BK
//_exitCallback 0; return
2016-02-03 00:02:56 +00:00
/* Failure handler for verb invocations. Calls process.exit by default */
executeFail = function ( err ) {
var finalErrorCode , msgs ;
2018-02-12 05:05:29 +00:00
//console.dir err
2016-02-03 00:02:56 +00:00
finalErrorCode = - 1 ;
if ( err ) {
2018-01-30 07:34:58 +00:00
if ( err . fluenterror ) {
finalErrorCode = err . fluenterror ;
} else if ( err . length ) {
finalErrorCode = err [ 0 ] . fluenterror ;
} else {
finalErrorCode = err ;
}
2016-02-03 00:02:56 +00:00
}
if ( _opts . debug ) {
msgs = require ( './msg' ) . errors ;
logMsg ( printf ( M2C ( msgs . exiting . msg , 'cyan' ) , finalErrorCode ) ) ;
2016-02-13 04:47:08 +00:00
if ( err . stack ) {
logMsg ( err . stack ) ;
}
2016-02-03 00:02:56 +00:00
}
_exitCallback ( finalErrorCode ) ;
2016-01-25 15:34:57 +00:00
} ;
loadOptions = function ( o , cmdO ) {
2018-02-12 05:05:29 +00:00
// o and this.opts() seem to be the same (command-specific options)
// Load the specified options file (if any) and apply options
2016-01-25 15:34:57 +00:00
if ( cmdO ) {
o = EXTEND ( true , o , cmdO ) ;
}
2018-02-12 05:05:29 +00:00
// Merge in command-line options
2016-01-25 15:34:57 +00:00
o = EXTEND ( true , o , this . opts ( ) ) ;
2018-02-12 05:05:29 +00:00
// Kludge parent-level options until piping issue is resolved
2016-01-25 15:34:57 +00:00
if ( this . parent . silent !== void 0 && this . parent . silent !== null ) {
o . silent = this . parent . silent ;
}
if ( this . parent . debug !== void 0 && this . parent . debug !== null ) {
o . debug = this . parent . debug ;
}
if ( this . parent . assert !== void 0 && this . parent . assert !== null ) {
o . assert = this . parent . assert ;
}
if ( o . debug ) {
logMsg ( chalk . cyan ( 'OPTIONS:' ) + '\n' ) ;
_ . each ( o , function ( val , key ) {
return logMsg ( chalk . cyan ( ' %s' ) + chalk . cyan . bold ( ' %s' ) , PAD ( key , 22 , null , PAD . RIGHT ) , val ) ;
} ) ;
logMsg ( '' ) ;
}
EXTEND ( true , _opts , o ) ;
} ;
splitSrcDest = function ( ) {
var params , splitAt ;
params = this . parent . args . filter ( function ( j ) {
return String . is ( j ) ;
} ) ;
if ( params . length === 0 ) {
throw {
2018-02-12 05:05:29 +00:00
//tmpName = @name()
2016-01-25 15:34:57 +00:00
fluenterror : HMSTATUS . resumeNotFound ,
2018-02-11 13:13:13 +00:00
verb : this . name ( ) ,
2016-01-25 15:34:57 +00:00
quit : true
} ;
}
2018-02-12 05:05:29 +00:00
// Find the TO keyword, if any
2016-01-25 15:34:57 +00:00
splitAt = _ . findIndex ( params , function ( p ) {
return p . toLowerCase ( ) === 'to' ;
} ) ;
2018-02-12 05:05:29 +00:00
// TO can't be the last keyword
2016-01-25 15:34:57 +00:00
if ( splitAt === params . length - 1 && splitAt !== - 1 ) {
logMsg ( chalk . yellow ( 'Please ' ) + chalk . yellow . bold ( 'specify an output file' ) + chalk . yellow ( ' for this operation or ' ) + chalk . yellow . bold ( 'omit the TO keyword' ) + chalk . yellow ( '.' ) ) ;
return ;
}
return {
src : params . slice ( 0 , splitAt === - 1 ? void 0 : splitAt ) ,
dst : splitAt === - 1 ? [ ] : params . slice ( splitAt + 1 )
} ;
} ;
logMsg = function ( ) {
2018-02-12 09:01:00 +00:00
// eslint-disable-next-line no-console
2016-01-25 15:34:57 +00:00
return _opts . silent || console . log . apply ( console . log , arguments ) ;
} ;
} ) . call ( this ) ;
2016-02-02 02:14:36 +00:00
//# sourceMappingURL=main.js.map