mirror of
https://github.com/JuanCanham/HackMyResume.git
synced 2024-11-22 08:20:11 +00:00
Implement "generate" and "validate" verbs.
Start moving to a more familiar verb-based interface with "generate" and "validate" commands. Use with "fluentcv generate" or "fluentcv validate".
This commit is contained in:
parent
9044dff504
commit
a410153253
@ -10,7 +10,8 @@ FRESH character/resume sheet representation.
|
|||||||
, validator = require('is-my-json-valid')
|
, validator = require('is-my-json-valid')
|
||||||
, _ = require('underscore')
|
, _ = require('underscore')
|
||||||
, PATH = require('path')
|
, PATH = require('path')
|
||||||
, moment = require('moment');
|
, moment = require('moment')
|
||||||
|
, CONVERTER = require('./convert');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
A FRESH-style resume in JSON or YAML.
|
A FRESH-style resume in JSON or YAML.
|
||||||
@ -66,7 +67,7 @@ FRESH character/resume sheet representation.
|
|||||||
var rep = JSON.parse( stringData );
|
var rep = JSON.parse( stringData );
|
||||||
|
|
||||||
// Convert JSON Resume to FRESH if necessary
|
// Convert JSON Resume to FRESH if necessary
|
||||||
rep.basics && (rep = FreshSheet.convert( rep ));
|
rep.basics && (rep = CONVERTER.toFRESH( rep ));
|
||||||
|
|
||||||
// Now apply the resume representation onto this object
|
// Now apply the resume representation onto this object
|
||||||
extend( true, this, rep );
|
extend( true, this, rep );
|
||||||
@ -87,106 +88,6 @@ FRESH character/resume sheet representation.
|
|||||||
return this;
|
return this;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
Convert from JSON Resume format
|
|
||||||
*/
|
|
||||||
FreshSheet.convert = function( jrs ) {
|
|
||||||
|
|
||||||
return {
|
|
||||||
|
|
||||||
name: jrs.basics.name,
|
|
||||||
label: jrs.basics.label,
|
|
||||||
class: jrs.basics.label,
|
|
||||||
summary: jrs.basics.summary,
|
|
||||||
|
|
||||||
contact: {
|
|
||||||
email: jrs.basics.email,
|
|
||||||
phone: jrs.basics.phone,
|
|
||||||
website: jrs.basics.website,
|
|
||||||
postal: {
|
|
||||||
city: jrs.basics.location.city,
|
|
||||||
region: jrs.basics.location.region,
|
|
||||||
country: jrs.basics.location.countryCode,
|
|
||||||
code: jrs.basics.location.postalCode,
|
|
||||||
address: [
|
|
||||||
jrs.basics.location.address,
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
employment: {
|
|
||||||
history: jrs.work.map( function( job ) {
|
|
||||||
return {
|
|
||||||
position: job.position,
|
|
||||||
employer: job.company,
|
|
||||||
summary: job.summary,
|
|
||||||
current: !job.endDate || !job.endDate.trim() || job.endDate.trim().toLowerCase() === 'current',
|
|
||||||
start: job.startDate,
|
|
||||||
end: job.endDate,
|
|
||||||
url: job.website,
|
|
||||||
keywords: "",
|
|
||||||
highlights: job.highlights
|
|
||||||
};
|
|
||||||
})
|
|
||||||
},
|
|
||||||
|
|
||||||
education: {
|
|
||||||
history: jrs.education.map(function(edu){
|
|
||||||
return {
|
|
||||||
institution: edu.institution,
|
|
||||||
start: edu.startDate,
|
|
||||||
end: edu.endDate,
|
|
||||||
grade: edu.gpa,
|
|
||||||
curriculum: edu.courses,
|
|
||||||
url: edu.website || edu.url || null,
|
|
||||||
summary: null,
|
|
||||||
// ???: edu.area, TODO
|
|
||||||
// ???: edu.studyType TODO
|
|
||||||
};
|
|
||||||
})
|
|
||||||
},
|
|
||||||
|
|
||||||
service: {
|
|
||||||
history: jrs.volunteer.map(function(vol) {
|
|
||||||
return {
|
|
||||||
type: 'volunteer',
|
|
||||||
position: vol.position,
|
|
||||||
organization: vol.organization,
|
|
||||||
start: vol.startDate,
|
|
||||||
end: vol.endDate,
|
|
||||||
url: vol.website,
|
|
||||||
summary: vol.summary,
|
|
||||||
highlights: vol.highlights
|
|
||||||
};
|
|
||||||
})
|
|
||||||
},
|
|
||||||
|
|
||||||
skills: jrs.skills.map(function(sk){
|
|
||||||
return {
|
|
||||||
name: sk.name,
|
|
||||||
summary: "",
|
|
||||||
level: sk.level,
|
|
||||||
summary: sk.keywords.join(', '),
|
|
||||||
years: null,
|
|
||||||
proof: null
|
|
||||||
};
|
|
||||||
}),
|
|
||||||
|
|
||||||
publications: jrs.publications.map(function(pub){
|
|
||||||
return {
|
|
||||||
title: pub.name,
|
|
||||||
publisher: pub.publisher,
|
|
||||||
link: [
|
|
||||||
{ 'url': pub.website }
|
|
||||||
],
|
|
||||||
year: pub.releaseDate
|
|
||||||
};
|
|
||||||
}),
|
|
||||||
|
|
||||||
interests: jrs.interests
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Return a unique list of all keywords across all skills.
|
Return a unique list of all keywords across all skills.
|
||||||
*/
|
*/
|
||||||
@ -266,12 +167,17 @@ FRESH character/resume sheet representation.
|
|||||||
/**
|
/**
|
||||||
Validate the sheet against the FRESH Resume schema.
|
Validate the sheet against the FRESH Resume schema.
|
||||||
*/
|
*/
|
||||||
FreshSheet.prototype.isValid = function( ) { // TODO: ↓ fix this path ↓
|
FreshSheet.prototype.isValid = function( info ) {
|
||||||
var schema = FS.readFileSync( PATH.join( __dirname, 'resume.json' ), 'utf8' );
|
var schemaObj = require('FRESCA');
|
||||||
var schemaObj = JSON.parse( schema );
|
//var schemaObj = JSON.parse( schema );
|
||||||
var validator = require('is-my-json-valid')
|
var validator = require('is-my-json-valid')
|
||||||
var validate = validator( schemaObj );
|
var validate = validator( schemaObj );
|
||||||
return validate( this );
|
var ret = validate( this );
|
||||||
|
if( !ret ) {
|
||||||
|
this.meta = this.meta || { };
|
||||||
|
this.meta.validationErrors = validate.errors;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -9,7 +9,7 @@ module.exports = function () {
|
|||||||
var path = require( 'path' )
|
var path = require( 'path' )
|
||||||
, extend = require( './utils/extend' )
|
, extend = require( './utils/extend' )
|
||||||
, unused = require('./utils/string')
|
, unused = require('./utils/string')
|
||||||
, fs = require('fs')
|
, FS = require('fs')
|
||||||
, _ = require('underscore')
|
, _ = require('underscore')
|
||||||
, FLUENT = require('./fluentlib')
|
, FLUENT = require('./fluentlib')
|
||||||
, PATH = require('path')
|
, PATH = require('path')
|
||||||
@ -109,6 +109,46 @@ module.exports = function () {
|
|||||||
throw ex;
|
throw ex;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Validate 1 to N resumes as vanilla JSON.
|
||||||
|
*/
|
||||||
|
// function validateAsJSON( src, logger ) {
|
||||||
|
// _log = logger || console.log;
|
||||||
|
// if( !src || !src.length ) { throw { fluenterror: 3 }; }
|
||||||
|
// var isValid = true;
|
||||||
|
// var sheets = src.map( function( res ) {
|
||||||
|
// try {
|
||||||
|
// var rawJson = FS.readFileSync( res, 'utf8' );
|
||||||
|
// var testObj = JSON.parse( rawJson );
|
||||||
|
// }
|
||||||
|
// catch(ex) {
|
||||||
|
// if (!(ex instanceof SyntaxError)) { throw ex; } // [1]
|
||||||
|
// isValid = false;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// _log( 'Validating JSON resume: ' + res + (isValid ? ' (VALID)' : ' (INVALID)'));
|
||||||
|
// return isValid;
|
||||||
|
// });
|
||||||
|
// }
|
||||||
|
|
||||||
|
/**
|
||||||
|
Validate 1 to N resumes in either FRESH or JSON Resume format.
|
||||||
|
*/
|
||||||
|
function validate( src, unused, opts, logger ) {
|
||||||
|
_log = logger || console.log;
|
||||||
|
if( !src || !src.length ) { throw { fluenterror: 3 }; }
|
||||||
|
var isValid = true;
|
||||||
|
var sheets = src.map( function( res ) {
|
||||||
|
var sheet = (new FLUENT.Sheet()).open( res );
|
||||||
|
var valid = sheet.isValid();
|
||||||
|
_log( 'Validating JSON resume: ' + res +
|
||||||
|
(valid ? ' (VALID)' : ' (INVALID)'));
|
||||||
|
if( !valid ) {
|
||||||
|
_log( sheet.meta.validationErrors );
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Supported resume formats.
|
Supported resume formats.
|
||||||
*/
|
*/
|
||||||
@ -139,10 +179,17 @@ module.exports = function () {
|
|||||||
Internal module interface. Used by FCV Desktop and HMR.
|
Internal module interface. Used by FCV Desktop and HMR.
|
||||||
*/
|
*/
|
||||||
return {
|
return {
|
||||||
|
verbs: {
|
||||||
generate: gen,
|
generate: gen,
|
||||||
|
validate: validate,
|
||||||
|
convert: convert
|
||||||
|
},
|
||||||
lib: require('./fluentlib'),
|
lib: require('./fluentlib'),
|
||||||
options: _opts,
|
options: _opts,
|
||||||
formats: _fmts
|
formats: _fmts
|
||||||
};
|
};
|
||||||
|
|
||||||
}();
|
}();
|
||||||
|
|
||||||
|
// [1]: JSON.parse throws SyntaxError on invalid JSON. See:
|
||||||
|
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/parse
|
||||||
|
@ -4,7 +4,7 @@ External API surface for FluentCV:CLI.
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
Sheet: require('./core/sheet'),
|
Sheet: require('./core/fresh-sheet'),
|
||||||
Theme: require('./core/theme'),
|
Theme: require('./core/theme'),
|
||||||
FluentDate: require('./core/fluent-date'),
|
FluentDate: require('./core/fluent-date'),
|
||||||
HtmlGenerator: require('./gen/html-generator'),
|
HtmlGenerator: require('./gen/html-generator'),
|
||||||
|
@ -29,7 +29,9 @@ Base resume generator for FluentCV.
|
|||||||
success: 0,
|
success: 0,
|
||||||
themeNotFound: 1,
|
themeNotFound: 1,
|
||||||
copyCss: 2,
|
copyCss: 2,
|
||||||
resumeNotFound: 3
|
resumeNotFound: 3,
|
||||||
|
missingCommand: 4,
|
||||||
|
invalidCommand: 5
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
28
src/index.js
28
src/index.js
@ -23,20 +23,27 @@ catch( ex ) {
|
|||||||
|
|
||||||
function main() {
|
function main() {
|
||||||
|
|
||||||
// Setup.
|
// Setup
|
||||||
var title = '*** FluentCV v' + PKG.version + ' ***';
|
var title = '*** FluentCV v' + PKG.version + ' ***';
|
||||||
if( process.argv.length <= 2 ) { logMsg(title); throw { fluenterror: 3 }; }
|
if( process.argv.length <= 2 ) { logMsg(title); throw { fluenterror: 4 }; }
|
||||||
var args = ARGS( process.argv.slice(2) );
|
var a = ARGS( process.argv.slice(2) );
|
||||||
opts = getOpts( args );
|
opts = getOpts( a );
|
||||||
logMsg( title );
|
logMsg( title );
|
||||||
|
|
||||||
// Convert arguments to source files, target files, options
|
// Get the action to be performed
|
||||||
var src = args._ || [];
|
var verb = a._[0].toLowerCase().trim();
|
||||||
var dst = (args.o && ((typeof args.o === 'string' && [ args.o ]) || args.o)) || [];
|
if( !FCMD.verbs[ verb ] ) {
|
||||||
dst = (dst === true) ? [] : dst; // Handle -o with missing output file
|
throw 'Invalid command: "' + verb + '"';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Preload our params array
|
||||||
|
var dst = (a.o && ((typeof a.o === 'string' && [ a.o ]) || a.o)) || [];
|
||||||
|
dst = (dst === true) ? [] : dst; // Handle -o with missing output file
|
||||||
|
var parms = [ a._.slice(1) || [], dst, opts, logMsg ];
|
||||||
|
|
||||||
|
// Invoke the action
|
||||||
|
FCMD.verbs[ verb ].apply( null, parms );
|
||||||
|
|
||||||
// Generate!
|
|
||||||
FCMD.generate( src, dst, opts, logMsg );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function logMsg( msg ) {
|
function logMsg( msg ) {
|
||||||
@ -60,6 +67,7 @@ function handleError( ex ) {
|
|||||||
case 1: msg = "The specified theme couldn't be found: " + ex.data; break;
|
case 1: msg = "The specified theme couldn't be found: " + ex.data; break;
|
||||||
case 2: msg = "Couldn't copy CSS file to destination folder"; break;
|
case 2: msg = "Couldn't copy CSS file to destination folder"; break;
|
||||||
case 3: msg = "Please specify a valid JSON resume file."; break;
|
case 3: msg = "Please specify a valid JSON resume file."; break;
|
||||||
|
case 4: msg = "Please specify a valid command (GENERATE, VALIDATE, or CONVERT)."
|
||||||
};
|
};
|
||||||
exitCode = ex.fluenterror;
|
exitCode = ex.fluenterror;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user