mirror of
				https://github.com/JuanCanham/HackMyResume.git
				synced 2025-10-30 20:57:26 +00:00 
			
		
		
		
	Capture.
This commit is contained in:
		| @@ -52,6 +52,10 @@ Output routines for HackMyResume. | ||||
|             chalk.green(' resume: ') + chalk.green.bold(evt.file)); | ||||
|           break; | ||||
|  | ||||
|         case HME.beforeRead: | ||||
|           this.log( chalk.cyan('Reading resume: ' + chalk.bold( evt.file ))); | ||||
|           break; | ||||
|  | ||||
|         case HME.afterTheme: | ||||
|           this.theme = evt.theme; | ||||
|           break; | ||||
| @@ -148,6 +152,23 @@ Output routines for HackMyResume. | ||||
|             chalk.green(' (' + evt.srcFmt + ') to ') + chalk.green.bold(evt.dstFile) + | ||||
|             chalk.green(' (' + evt.dstFmt + ').')); | ||||
|           break; | ||||
|  | ||||
|         case HME.afterValidate: | ||||
|           var style = evt.isValid ? 'green' : 'yellow'; | ||||
|           this.log( chalk.white('Validating ') + chalk.white.bold(evt.file) + chalk.white(' against ') + | ||||
|             chalk.white.bold( evt.fmt ).toUpperCase() + | ||||
|             chalk.white(' schema: ') + chalk[style].bold(evt.isValid ? 'VALID!' : 'INVALID')); | ||||
|  | ||||
|           if( evt.errors ) { | ||||
|             _.each(evt.errors, function(err,idx) { | ||||
|               this.log( chalk.yellow.bold('--> ') + | ||||
|                 chalk.yellow(err.field.replace('data.','resume.').toUpperCase() + ' ' + | ||||
|                 err.message) ); | ||||
|             }, this); | ||||
|           } | ||||
|  | ||||
|           break; | ||||
|  | ||||
|       } | ||||
|     } | ||||
|  | ||||
|   | ||||
| @@ -2,26 +2,63 @@ Usage: | ||||
|  | ||||
|     hackmyresume <COMMAND> <SOURCES> [TO <TARGETS>] [-t <THEME>] [-f <FORMAT>] | ||||
|  | ||||
| <COMMAND> should be BUILD, NEW, CONVERT, VALIDATE, ANALYZE or HELP. <SOURCES> | ||||
| should be the path to one or more FRESH or JSON Resume format resumes. <TARGETS> | ||||
| should be the name of the destination resume to be created, if any. The <THEME> | ||||
| <COMMAND> should be BUILD, ANALYZE, NEW, CONVERT, or VALIDATE. <SOURCES> should | ||||
| be the path to one or more FRESH or JSON Resume format resumes. <TARGETS> should | ||||
| be the name of the destination resume to be created, if any. The <THEME> | ||||
| parameter should be the name of a predefined theme (for example: COMPACT, | ||||
| MINIMIST, MODERN, or HELLO-WORLD) or the relative path to a custom theme. | ||||
| <FORMAT> should be either FRESH (for a FRESH-format resume) or JRS (for a JSON | ||||
| Resume-format resume). | ||||
|  | ||||
|     hackmyresume BUILD resume.json TO out/resume.all | ||||
|     hackmyresume NEW resume.json | ||||
|     hackmyresume CONVERT resume.json TO resume-jrs.json | ||||
|     hackmyresume ANALYZE resume.json | ||||
|     hackmyresume VALIDATE resume.json | ||||
|    hackmyresume BUILD resume.json TO out/resume.all | ||||
|    hackmyresume ANALYZE resume.json | ||||
|    hackmyresume NEW resume.json | ||||
|    hackmyresume CONVERT resume.json TO resume-jrs.json | ||||
|    hackmyresume VALIDATE resume.json | ||||
|  | ||||
| Both SOURCES and TARGETS can accept multiple files: | ||||
|  | ||||
|     hackmyresume BUILD r1.json r2.json TO out/resume.all out2/resume.html | ||||
|     hackmyresume NEW r1.json r2.json r3.json | ||||
|     hackmyresume ANALYZE r1.json r2.json r3.json | ||||
|     hackmyresume VALIDATE resume.json resume2.json resume3.json | ||||
|    hackmyresume BUILD r1.json r2.json TO out/resume.all out2/resume.html | ||||
|    hackmyresume ANALYZE r1.json r2.json r3.json | ||||
|    hackmyresume NEW r1.json r2.json r3.json | ||||
|    hackmyresume CONVERT r1.json r2.json TO o1.json o2.json | ||||
|    hackmyresume VALIDATE r1.json r2.json r3.json | ||||
|  | ||||
| Available options: | ||||
|  | ||||
|    --theme <theme>    Specify a theme for the BUILD command. Can be the path | ||||
|    -t <theme>         to any FRESH or JSON Resume theme, or the name of one | ||||
|                       of HackMyResume's predefined themes. | ||||
|  | ||||
|  | ||||
|    --pdf <engine>     Specify a PDF rendering engine. Can be "wkhtmltopdf", | ||||
|    -p <engine>        "phantom", or "none". Requires that the corresponding | ||||
|                       engine be installed and path-accessible. | ||||
|  | ||||
|  | ||||
|    --opts <path>      Load HackMyResume options via an external file. | ||||
|    -o <path> | ||||
|  | ||||
|  | ||||
|    --color            Enable/disable terminal colors. | ||||
|    --no-color | ||||
|  | ||||
|  | ||||
|    --tips             Enable/disable theme tips and messages. | ||||
|    --no-tips | ||||
|  | ||||
|  | ||||
|    --debug            Emit debug info. | ||||
|    -d | ||||
|  | ||||
|  | ||||
|    --help             Display help documentation. | ||||
|    -h | ||||
|  | ||||
|  | ||||
|    --version          Display the current HackMyResume version. | ||||
|    -v | ||||
|  | ||||
|  | ||||
| See https://github.com/hacksalot/hackmyresume/blob/master/README.md for more | ||||
| information. | ||||
|   | ||||
| @@ -156,6 +156,21 @@ Error-handling routines for HackMyResume. | ||||
|           " is inaccessible. PDF not generated." ); | ||||
|         break; | ||||
|  | ||||
|       case HACKMYSTATUS.readError: | ||||
|         msg = formatError( ex.inner.toString() ); | ||||
|         break; | ||||
|  | ||||
|       case HACKMYSTATUS.parseError: | ||||
|         if( SyntaxErrorEx.is( ex.inner )) { | ||||
|           var se = new SyntaxErrorEx( ex, ex.raw ); | ||||
|           msg = formatError( 'Invalid or corrupt JSON on line ' + se.line + | ||||
|             ' column ' + se.col ); | ||||
|         } | ||||
|         else { | ||||
|           msg = formatError( ex.inner.toString() ); | ||||
|         } | ||||
|         break; | ||||
|  | ||||
|     } | ||||
|     return { | ||||
|       msg: msg, | ||||
|   | ||||
| @@ -40,7 +40,12 @@ Event code definitions. | ||||
|     afterAnalyze: 14, | ||||
|  | ||||
|     beforeConvert: 15, | ||||
|     afterConvert: 16 | ||||
|     afterConvert: 16, | ||||
|  | ||||
|     verifyOutputs: 17, | ||||
|  | ||||
|     beforeParse: 18, | ||||
|     afterParse: 19 | ||||
|  | ||||
|   }; | ||||
|  | ||||
|   | ||||
| @@ -10,11 +10,14 @@ Definition of the ResumeFactory class. | ||||
|  | ||||
|  | ||||
|  | ||||
|   require('string.prototype.startswith'); | ||||
|   var FS = require('fs'); | ||||
|   var ResumeConverter = require('./convert'); | ||||
|   var chalk = require('chalk'); | ||||
|   var SyntaxErrorEx = require('../utils/syntax-error-ex'); | ||||
|   var FS          = require('fs'), | ||||
|   HACKMYSTATUS    = require('./status-codes'), | ||||
|   HME             = require('./event-codes'), | ||||
|   ResumeConverter = require('./convert'), | ||||
|   chalk           = require('chalk'), | ||||
|   SyntaxErrorEx   = require('../utils/syntax-error-ex'), | ||||
|   _               = require('underscore'); | ||||
|                     require('string.prototype.startswith'); | ||||
|  | ||||
|  | ||||
|  | ||||
| @@ -29,14 +32,11 @@ Definition of the ResumeFactory class. | ||||
|     /** | ||||
|     Load one or more resumes from disk. | ||||
|     */ | ||||
|     load: function ( sources, opts ) { | ||||
|     load: function ( sources, opts, emitter ) { | ||||
|  | ||||
|       // Loop over all inputs, parsing each to JSON and then to a FRESHResume | ||||
|       // or JRSResume object. | ||||
|       var that = this; | ||||
|       return sources.map( function( src ) { | ||||
|         return that.loadOne( src, opts ); | ||||
|       }); | ||||
|         return this.loadOne( src, opts, emitter ); | ||||
|       }, this); | ||||
|  | ||||
|     }, | ||||
|  | ||||
| @@ -45,9 +45,8 @@ Definition of the ResumeFactory class. | ||||
|     /** | ||||
|     Load a single resume from disk. | ||||
|     */ | ||||
|     loadOne: function( src, opts ) { | ||||
|     loadOne: function( src, opts, emitter ) { | ||||
|  | ||||
|       var log = opts.log; | ||||
|       var toFormat = opts.format; | ||||
|       var objectify = opts.objectify; | ||||
|  | ||||
| @@ -55,7 +54,7 @@ Definition of the ResumeFactory class. | ||||
|       toFormat && (toFormat = toFormat.toLowerCase().trim()); | ||||
|  | ||||
|       // Load and parse the resume JSON | ||||
|       var info = _parse( src, opts ); | ||||
|       var info = _parse( src, opts, emitter ); | ||||
|       if( info.error ) return info; | ||||
|  | ||||
|       // Determine the resume format: FRESH or JRS | ||||
| @@ -88,44 +87,28 @@ Definition of the ResumeFactory class. | ||||
|  | ||||
|  | ||||
|  | ||||
|   function _parse( fileName, opts ) { | ||||
|   function _parse( fileName, opts, eve ) { | ||||
|  | ||||
|     var rawData; | ||||
|     try { | ||||
|  | ||||
|       // TODO: Core should not log | ||||
|       opts.log( chalk.cyan('Reading resume: ') + chalk.cyan.bold(fileName) ); | ||||
|  | ||||
|       // Read the file | ||||
|       eve && eve.stat( HME.beforeRead, { file: fileName }); | ||||
|       rawData = FS.readFileSync( fileName, 'utf8' ); | ||||
|  | ||||
|       // Parse it to JSON | ||||
|       return { | ||||
|       eve && eve.stat( HME.afterRead, { data: rawData }); | ||||
|       eve && eve.stat( HME.beforeParse, { data: rawData }); | ||||
|       var ret = { | ||||
|         json: JSON.parse( rawData ) | ||||
|       }; | ||||
|  | ||||
|       eve && eve.stat( HME.afterParse, { data: ret.json } ); | ||||
|       return ret; | ||||
|     } | ||||
|     catch( ex ) { | ||||
|  | ||||
|       // JSON.parse failed due to invalid JSON | ||||
|       if ( !opts.muffle && ex instanceof SyntaxError) { | ||||
|         var info = new SyntaxErrorEx( ex, rawData ); | ||||
|         opts.log( chalk.red.bold(fileName.toUpperCase() + ' contains invalid JSON on line ' + | ||||
|           info.line + ' column ' + info.col + '.' + | ||||
|           chalk.red(' Unable to validate.'))); | ||||
|         opts.log( chalk.red.bold('INTERNAL: ' + ex) ); | ||||
|         ex.handled = true; | ||||
|       } | ||||
|  | ||||
|       // FS.readFileSync failed | ||||
|       if( !rawData || opts.throw ) throw ex; | ||||
|  | ||||
|       return { | ||||
|         error: ex, | ||||
|         raw: rawData, | ||||
|         file: fileName | ||||
|       throw { | ||||
|         fluenterror: rawData ? HACKMYSTATUS.parseError : HACKMYSTATUS.readError, | ||||
|         inner: ex, raw: rawData, file: fileName, shouldExit: false | ||||
|       }; | ||||
|  | ||||
|     } | ||||
|  | ||||
|   } | ||||
|  | ||||
|  | ||||
|   | ||||
| @@ -20,7 +20,9 @@ Status codes for HackMyResume. | ||||
|     missingPackageJSON: 10, | ||||
|     invalid: 11, | ||||
|     invalidFormat: 12, | ||||
|     notOnPath: 13 | ||||
|     notOnPath: 13, | ||||
|     readError: 14, | ||||
|     parseError: 15 | ||||
|   }; | ||||
|  | ||||
| }()); | ||||
|   | ||||
| @@ -31,6 +31,7 @@ Implementation of the 'generate' verb for HackMyResume. | ||||
|     , _err, _log, rez; | ||||
|  | ||||
|  | ||||
|  | ||||
|   var BuildVerb = module.exports = Verb.extend({ | ||||
|  | ||||
|     init: function() { | ||||
| @@ -64,7 +65,7 @@ Implementation of the 'generate' verb for HackMyResume. | ||||
|     this.stat( HME.afterTheme, { theme: theme }); | ||||
|  | ||||
|     // Check for invalid outputs | ||||
|     var inv = verifyOutputs( dst, theme ); | ||||
|     var inv = verifyOutputs.call( this, dst, theme ); | ||||
|     if( inv && inv.length ) { | ||||
|       throw {fluenterror: HACKMYSTATUS.invalidFormat, data: inv, theme: theme}; | ||||
|     } | ||||
| @@ -181,6 +182,8 @@ Implementation of the 'generate' verb for HackMyResume. | ||||
|   */ | ||||
|   function verifyOutputs( targets, theme ) { | ||||
|  | ||||
|     this.stat(HME.verifyOutputs, { targets: targets, theme: theme }); | ||||
|  | ||||
|     return _.reject( | ||||
|       targets.map( function( t ) { | ||||
|         var pathInfo = parsePath( t ); | ||||
|   | ||||
| @@ -12,6 +12,8 @@ Implementation of the 'validate' verb for HackMyResume. | ||||
|   var chalk = require('chalk'); | ||||
|   var Verb = require('../core/verb'); | ||||
|   var HACKMYSTATUS = require('../core/status-codes'); | ||||
|   var HME = require('../core/event-codes'); | ||||
|   var _ = require('underscore'); | ||||
|  | ||||
|  | ||||
|  | ||||
| @@ -45,74 +47,51 @@ Implementation of the 'validate' verb for HackMyResume. | ||||
|  | ||||
|     var resumes = ResumeFactory.load( sources, { | ||||
|       format: null, | ||||
|       objectify: false, | ||||
|       throw: false, | ||||
|       muffle: true | ||||
|     }); | ||||
|       objectify: false | ||||
|     }, this ); | ||||
|  | ||||
|     // Load input resumes... | ||||
|     resumes.forEach(function( src ) { | ||||
|     // Validate input resumes. Return a { file: <f>, isValid: <v>} object for | ||||
|     // each resume (valid, invalid, or broken). | ||||
|     return resumes.map( function( src ) { | ||||
|  | ||||
|       var ret =  { file: src, isValid: false }; | ||||
|  | ||||
|       // If there was an error reading the resume | ||||
|       if( src.error ) { | ||||
|         // TODO: Core should not log | ||||
|         _log( chalk.white('Validating ') + chalk.gray.bold(src.file) + | ||||
|         chalk.white(' against ') + chalk.gray.bold('AUTO') + | ||||
|         chalk.white(' schema:') + chalk.red.bold(' BROKEN') ); | ||||
|  | ||||
|         var ex = src.error; // alias | ||||
|         if ( ex instanceof SyntaxError) { | ||||
|           var info = new SyntaxErrorEx( ex, src.raw ); | ||||
|           _log( chalk.red.bold('--> ' + src.file.toUpperCase() + ' contains invalid JSON on line ' + | ||||
|             info.line + ' column ' + info.col + '.' + | ||||
|             chalk.red(' Unable to validate.') ) ); | ||||
|           _log( chalk.red.bold('    INTERNAL: ' + ex) ); | ||||
|         } | ||||
|         else { | ||||
|           _log(chalk.red.bold('ERROR: ' + ex.toString())); | ||||
|         } | ||||
|         if( opts.assert ) throw { fluenterror: HACKMYSTATUS.invalid }; | ||||
|         return; | ||||
|         return ret; | ||||
|       } | ||||
|  | ||||
|       var json = src.json; | ||||
|       var isValid = false; | ||||
|       var style = 'green'; | ||||
|       var errors = []; | ||||
|       var fmt = json.basics ? 'jrs' : 'fresh'; | ||||
|  | ||||
|       // Successfully read the resume. Now parse it as JSON. | ||||
|       var json = src.json, fmt = json.basics ? 'jrs' : 'fresh', errors = []; | ||||
|       try { | ||||
|         var validate = validator( schemas[ fmt ], { // Note [1] | ||||
|           formats: { | ||||
|             date: /^\d{4}(?:-(?:0[0-9]{1}|1[0-2]{1})(?:-[0-9]{2})?)?$/ | ||||
|              date: /^\d{4}(?:-(?:0[0-9]{1}|1[0-2]{1})(?:-[0-9]{2})?)?$/ | ||||
|           } | ||||
|         }); | ||||
|  | ||||
|         isValid = validate( json ); | ||||
|         if( !isValid ) { | ||||
|           style = 'yellow'; | ||||
|         ret.isValid = validate( json ); | ||||
|         if( !ret.isValid ) { | ||||
|           errors = validate.errors; | ||||
|         } | ||||
|  | ||||
|       } | ||||
|       catch(exc) { | ||||
|         return; | ||||
|         return ret; | ||||
|       } | ||||
|  | ||||
|       _log( chalk.white('Validating ') + chalk.white.bold(src.file) + chalk.white(' against ') + | ||||
|         chalk.white.bold(fmt.replace('jars','JSON Resume').toUpperCase()) + | ||||
|         chalk.white(' schema: ') + chalk[style].bold(isValid ? 'VALID!' : 'INVALID') ); | ||||
|  | ||||
|       errors.forEach(function(err,idx) { | ||||
|         _log( chalk.yellow.bold('--> ') + | ||||
|           chalk.yellow(err.field.replace('data.','resume.').toUpperCase() + ' ' + | ||||
|           err.message) ); | ||||
|       }); | ||||
|       this.stat(HME.afterValidate, { file: src.file, isValid: isValid, | ||||
|         fmt: fmt.replace('jars', 'JSON Resume'), errors: errors }); | ||||
|  | ||||
|       if( opts.assert && !isValid ) { | ||||
|         throw { fluenterror: HACKMYSTATUS.invalid, shouldExit: true }; | ||||
|       } | ||||
|  | ||||
|     }); | ||||
|       return ret; | ||||
|  | ||||
|     }, this); | ||||
|  | ||||
|   } | ||||
|  | ||||
| }()); | ||||
|   | ||||
		Reference in New Issue
	
	Block a user