mirror of
https://github.com/JuanCanham/HackMyResume.git
synced 2024-11-24 17:30:10 +00:00
Scrub sheet.js.
This commit is contained in:
parent
7df7a3f894
commit
1715a66514
86
src/sheet.js
86
src/sheet.js
@ -12,22 +12,27 @@ Abstract character/resume sheet representation.
|
|||||||
, moment = require('moment');
|
, moment = require('moment');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Initialize a new Sheet instance.
|
The Sheet class represent a specific JSON character sheet. When Sheet.open
|
||||||
|
is called, we merge the loaded JSON sheet properties onto the Sheet instance
|
||||||
|
via extend(), so a full-grown sheet object will have all of the methods here,
|
||||||
|
plus a complement of JSON properties from the backing JSON file. That allows
|
||||||
|
us to treat Sheet objects interchangeably with the loaded JSON model.
|
||||||
|
@class Sheet
|
||||||
*/
|
*/
|
||||||
function Sheet() {
|
function Sheet() {
|
||||||
this.id = null;
|
this.meta = { };
|
||||||
this.title = "New";
|
|
||||||
this.fileName = null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Open and parse the specified JSON resume sheet.
|
Open and parse the specified JSON resume sheet. Validate any dates present in
|
||||||
|
the sheet and convert them to a safe/consistent format. Then sort each section
|
||||||
|
on the sheet by startDate descending.
|
||||||
*/
|
*/
|
||||||
Sheet.prototype.open = function( file, title ) {
|
Sheet.prototype.open = function( file, title ) {
|
||||||
var rep = JSON.parse( FS.readFileSync( file, 'utf8' ) );
|
var rep = JSON.parse( FS.readFileSync( file, 'utf8' ) );
|
||||||
extend( true, this, rep );
|
extend( true, this, rep );
|
||||||
this.fileName = file;
|
this.meta.fileName = file;
|
||||||
this.title = title || this.basics.name;
|
this.meta.title = title || this.basics.name;
|
||||||
_parseDates.call( this );
|
_parseDates.call( this );
|
||||||
this.sort();
|
this.sort();
|
||||||
this.computed = this.computed || { };
|
this.computed = this.computed || { };
|
||||||
@ -40,8 +45,8 @@ Abstract character/resume sheet representation.
|
|||||||
*/
|
*/
|
||||||
Sheet.prototype.hasProfile = function( socialNetwork ) {
|
Sheet.prototype.hasProfile = function( socialNetwork ) {
|
||||||
socialNetwork = socialNetwork.trim().toLowerCase();
|
socialNetwork = socialNetwork.trim().toLowerCase();
|
||||||
return this.basics.profiles && _.some( this.basics.profiles, function(prof) {
|
return this.basics.profiles && _.some( this.basics.profiles, function(p) {
|
||||||
return prof.network.trim().toLowerCase() === socialNetwork;
|
return p.network.trim().toLowerCase() === socialNetwork;
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -58,10 +63,11 @@ Abstract character/resume sheet representation.
|
|||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Validate the sheet against a specific JSON schema.
|
Validate the sheet against the JSON Resume schema.
|
||||||
*/
|
*/
|
||||||
Sheet.prototype.isValid = function( ) {
|
Sheet.prototype.isValid = function( ) {
|
||||||
var schemaObj = JSON.parse( FS.readFileSync( __dirname + '/resume-schema.json', 'utf8' ) );
|
var schema = FS.readFileSync( __dirname + '/resume-schema.json', 'utf8' );
|
||||||
|
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 );
|
return validate( this );
|
||||||
@ -69,37 +75,53 @@ Abstract character/resume sheet representation.
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
Calculate the total duration of the sheet. Assumes this.work has been sorted
|
Calculate the total duration of the sheet. Assumes this.work has been sorted
|
||||||
by start date descending.
|
by start date descending, perhaps via a call to Sheet.sort().
|
||||||
|
@returns The total duration of the sheet's work history, that is, the number
|
||||||
|
of years between the start date of the earliest job on the resume and the
|
||||||
|
*latest end date of all jobs in the work history*. This last condition is for
|
||||||
|
sheets that have overlapping jobs.
|
||||||
*/
|
*/
|
||||||
Sheet.prototype.duration = function() {
|
Sheet.prototype.duration = function() {
|
||||||
var careerStart = this.work[ this.work.length - 1].safeStartDate;
|
var careerStart = this.work[ this.work.length - 1].safeStartDate;
|
||||||
var careerLast = _.max( this.work, function( w ) { return w.safeEndDate.unix(); }).safeEndDate;
|
var careerLast = _.max( this.work, function( w ) {
|
||||||
|
return w.safeEndDate.unix();
|
||||||
|
}).safeEndDate;
|
||||||
return careerLast.diff( careerStart, 'years' );
|
return careerLast.diff( careerStart, 'years' );
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Sort dated things by start date descending.
|
Sort dated things on the sheet by start date descending.
|
||||||
*/
|
*/
|
||||||
Sheet.prototype.sort = function( ) {
|
Sheet.prototype.sort = function( ) {
|
||||||
this.work && this.work.length > 1 && this.work.sort( function(a, b) {
|
|
||||||
return( a.safeStartDate.isBefore(b.safeStartDate) ) ? 1 : ( a.safeStartDate.isAfter(b.safeStartDate) && -1 ) || 0;
|
this.work && this.work.sort( byDateDesc );
|
||||||
|
this.education && this.education.sort( byDateDesc );
|
||||||
|
this.volunteer && this.volunteer.sort( byDateDesc );
|
||||||
|
|
||||||
|
this.awards && this.awards.sort( function(a, b) {
|
||||||
|
return( a.safeDate.isBefore(b.safeDate) ) ? 1
|
||||||
|
: ( a.safeDate.isAfter(b.safeDate) && -1 ) || 0;
|
||||||
});
|
});
|
||||||
this.education && this.education.length > 1 && this.education.sort( function(a, b) {
|
this.publications && this.publications.sort( function(a, b) {
|
||||||
return( a.safeStartDate.isBefore(b.safeStartDate) ) ? 1 : ( a.safeStartDate.isAfter(b.safeStartDate) && -1 ) || 0;
|
return( a.safeReleaseDate.isBefore(b.safeReleaseDate) ) ? 1
|
||||||
});
|
: ( a.safeReleaseDate.isAfter(b.safeReleaseDate) && -1 ) || 0;
|
||||||
this.volunteer && this.volunteer.length > 1 && this.volunteer.sort( function(a, b) {
|
|
||||||
return( a.safeStartDate.isBefore(b.safeStartDate) ) ? 1 : ( a.safeStartDate.isAfter(b.safeStartDate) && -1 ) || 0;
|
|
||||||
});
|
|
||||||
this.awards && this.awards.length > 1 && this.awards.sort( function(a, b) {
|
|
||||||
return( a.safeDate.isBefore(b.safeDate) ) ? 1 : ( a.safeDate.isAfter(b.safeDate) && -1 ) || 0;
|
|
||||||
});
|
|
||||||
this.publications && this.publications.length > 1 && this.publications.sort( function(a, b) {
|
|
||||||
return( a.safeReleaseDate.isBefore(b.safeReleaseDate) ) ? 1 : ( a.safeReleaseDate.isAfter(b.safeReleaseDate) && -1 ) || 0;
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
function byDateDesc(a,b) {
|
||||||
|
return( a.safeStartDate.isBefore(b.safeStartDate) ) ? 1
|
||||||
|
: ( a.safeStartDate.isAfter(b.safeStartDate) && -1 ) || 0;
|
||||||
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Format a human-friendly FluentCV date to a Moment.js-compatible date.
|
Format a human-friendly FluentCV date to a Moment.js-compatible date. There
|
||||||
|
are a few date formats to be aware of here.
|
||||||
|
- The words "Present" and "Now", referring to the current date.
|
||||||
|
- The default "YYYY-MM-DD" format used in JSON Resume ("2015-02-10").
|
||||||
|
- The friendly FluentCV "mmm YYYY" format ("Mar 2015" or "Dec 2008").
|
||||||
|
- Year-only "YYYY" ("2015").
|
||||||
|
- Any other date format that Moment.js can parse from.
|
||||||
*/
|
*/
|
||||||
function _fmt( dt ) {
|
function _fmt( dt ) {
|
||||||
dt = dt.toLowerCase().trim();
|
dt = dt.toLowerCase().trim();
|
||||||
@ -108,7 +130,8 @@ Abstract character/resume sheet representation.
|
|||||||
}
|
}
|
||||||
else if( /^\D+/.test(dt) ) { // "Mar 2015"
|
else if( /^\D+/.test(dt) ) { // "Mar 2015"
|
||||||
var parts = dt.split(' ');
|
var parts = dt.split(' ');
|
||||||
return moment( parts[1] + '-' + (months[ parts[0] ] || abbr[ parts[0] ] || ( parts[0] === 'sept' && '09' )) + '-' + '01', 'YYYY-MM-DD' );
|
var dt = parts[1] + '-' + (months[parts[0]] || abbr[parts[0]]) + '-01';
|
||||||
|
return moment( dt, 'YYYY-MM-DD' );
|
||||||
}
|
}
|
||||||
else if( /^\d+$/.test(dt) ) { // "2015"
|
else if( /^\d+$/.test(dt) ) { // "2015"
|
||||||
return moment( dt, 'YYYY' );
|
return moment( dt, 'YYYY' );
|
||||||
@ -123,6 +146,10 @@ Abstract character/resume sheet representation.
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
Convert human-friendly dates into formal Moment.js dates for all collections.
|
Convert human-friendly dates into formal Moment.js dates for all collections.
|
||||||
|
We don't want to lose the raw textual date as entered by the user, so we store
|
||||||
|
the Moment-ified date as a separate property with a prefix of .safe. For ex:
|
||||||
|
job.startDate is the date as entered by the user. job.safeStartDate is the
|
||||||
|
parsed Moment.js date that we actually use in processing.
|
||||||
*/
|
*/
|
||||||
function _parseDates() {
|
function _parseDates() {
|
||||||
this.work.forEach( function(job) {
|
this.work.forEach( function(job) {
|
||||||
@ -148,6 +175,7 @@ Abstract character/resume sheet representation.
|
|||||||
var months = {}, abbr = {};
|
var months = {}, abbr = {};
|
||||||
moment.months().forEach(function(m,idx){months[m.toLowerCase()]=idx+1;});
|
moment.months().forEach(function(m,idx){months[m.toLowerCase()]=idx+1;});
|
||||||
moment.monthsShort().forEach(function(m,idx){abbr[m.toLowerCase()]=idx+1;});
|
moment.monthsShort().forEach(function(m,idx){abbr[m.toLowerCase()]=idx+1;});
|
||||||
|
abbr.sept = 9;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Export the Sheet function/ctor.
|
Export the Sheet function/ctor.
|
||||||
|
Loading…
Reference in New Issue
Block a user