mirror of
https://github.com/JuanCanham/HackMyResume.git
synced 2024-12-23 13:47:22 +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')
|
||||
, _ = require('underscore')
|
||||
, PATH = require('path')
|
||||
, moment = require('moment');
|
||||
, moment = require('moment')
|
||||
, CONVERTER = require('./convert');
|
||||
|
||||
/**
|
||||
A FRESH-style resume in JSON or YAML.
|
||||
@ -66,7 +67,7 @@ FRESH character/resume sheet representation.
|
||||
var rep = JSON.parse( stringData );
|
||||
|
||||
// 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
|
||||
extend( true, this, rep );
|
||||
@ -87,106 +88,6 @@ FRESH character/resume sheet representation.
|
||||
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.
|
||||
*/
|
||||
@ -266,12 +167,17 @@ FRESH character/resume sheet representation.
|
||||
/**
|
||||
Validate the sheet against the FRESH Resume schema.
|
||||
*/
|
||||
FreshSheet.prototype.isValid = function( ) { // TODO: ↓ fix this path ↓
|
||||
var schema = FS.readFileSync( PATH.join( __dirname, 'resume.json' ), 'utf8' );
|
||||
var schemaObj = JSON.parse( schema );
|
||||
FreshSheet.prototype.isValid = function( info ) {
|
||||
var schemaObj = require('FRESCA');
|
||||
//var schemaObj = JSON.parse( schema );
|
||||
var validator = require('is-my-json-valid')
|
||||
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' )
|
||||
, extend = require( './utils/extend' )
|
||||
, unused = require('./utils/string')
|
||||
, fs = require('fs')
|
||||
, FS = require('fs')
|
||||
, _ = require('underscore')
|
||||
, FLUENT = require('./fluentlib')
|
||||
, PATH = require('path')
|
||||
@ -109,6 +109,46 @@ module.exports = function () {
|
||||
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.
|
||||
*/
|
||||
@ -139,10 +179,17 @@ module.exports = function () {
|
||||
Internal module interface. Used by FCV Desktop and HMR.
|
||||
*/
|
||||
return {
|
||||
generate: gen,
|
||||
verbs: {
|
||||
generate: gen,
|
||||
validate: validate,
|
||||
convert: convert
|
||||
},
|
||||
lib: require('./fluentlib'),
|
||||
options: _opts,
|
||||
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 = {
|
||||
Sheet: require('./core/sheet'),
|
||||
Sheet: require('./core/fresh-sheet'),
|
||||
Theme: require('./core/theme'),
|
||||
FluentDate: require('./core/fluent-date'),
|
||||
HtmlGenerator: require('./gen/html-generator'),
|
||||
|
@ -29,7 +29,9 @@ Base resume generator for FluentCV.
|
||||
success: 0,
|
||||
themeNotFound: 1,
|
||||
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() {
|
||||
|
||||
// Setup.
|
||||
// Setup
|
||||
var title = '*** FluentCV v' + PKG.version + ' ***';
|
||||
if( process.argv.length <= 2 ) { logMsg(title); throw { fluenterror: 3 }; }
|
||||
var args = ARGS( process.argv.slice(2) );
|
||||
opts = getOpts( args );
|
||||
if( process.argv.length <= 2 ) { logMsg(title); throw { fluenterror: 4 }; }
|
||||
var a = ARGS( process.argv.slice(2) );
|
||||
opts = getOpts( a );
|
||||
logMsg( title );
|
||||
|
||||
// Convert arguments to source files, target files, options
|
||||
var src = args._ || [];
|
||||
var dst = (args.o && ((typeof args.o === 'string' && [ args.o ]) || args.o)) || [];
|
||||
dst = (dst === true) ? [] : dst; // Handle -o with missing output file
|
||||
// Get the action to be performed
|
||||
var verb = a._[0].toLowerCase().trim();
|
||||
if( !FCMD.verbs[ verb ] ) {
|
||||
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 ) {
|
||||
@ -60,6 +67,7 @@ function handleError( ex ) {
|
||||
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 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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user