diff --git a/src/core/fresh-resume.js b/src/core/fresh-resume.js index ff5eb24..3a30ff2 100644 --- a/src/core/fresh-resume.js +++ b/src/core/fresh-resume.js @@ -42,17 +42,40 @@ Definition of the FRESHResume class. }; /** - Convert this object to a JSON string, sanitizing meta-properties along the - way. Don't override .toString(). + Save the sheet to disk in a specific format, either FRESH or JSON Resume. */ - FreshResume.prototype.stringify = function() { + FreshResume.prototype.saveAs = function( filename, format ) { + this.meta.fileName = filename || this.meta.fileName; + if( format !== 'JRS' ) { + FS.writeFileSync( this.meta.fileName, this.stringify(), 'utf8' ); + } + else { + var newRep = CONVERTER.toJRS( this ); + FS.writeFileSync( this.meta.fileName, FreshResume.stringify( newRep ), 'utf8' ); + } + return this; + } + + /** + Convert the supplied object to a JSON string, sanitizing meta-properties along + the way. + */ + FreshResume.stringify = function( obj ) { function replacer( key,value ) { // Exclude these keys from stringification return _.some(['meta', 'warnings', 'computed', 'filt', 'ctrl', 'index', 'safe', 'result', 'isModified', 'htmlPreview', 'display_progress_bar'], function( val ) { return key.trim() === val; } ) ? undefined : value; } - return JSON.stringify( this, replacer, 2 ); + return JSON.stringify( obj, replacer, 2 ); + }, + + /** + Convert this object to a JSON string, sanitizing meta-properties along the + way. Don't override .toString(). + */ + FreshResume.prototype.stringify = function() { + return FreshResume.stringify( this ); }; /** @@ -66,7 +89,7 @@ Definition of the FRESHResume class. var rep = JSON.parse( stringData ); // Convert JSON Resume to FRESH if necessary - rep.basics && (rep = CONVERTER.toFRESH( rep )); + rep.basics && ( rep = CONVERTER.toFRESH( rep ) ); // Now apply the resume representation onto this object extend( true, this, rep ); diff --git a/src/fluentcmd.js b/src/fluentcmd.js index 6de5ab8..b25b3ac 100644 --- a/src/fluentcmd.js +++ b/src/fluentcmd.js @@ -149,6 +149,16 @@ module.exports = function () { }); } + /** + Convert between FRESH and JRS formats. + */ + function convert( src, dst, opts, logger ) { + _log = logger || console.log; + if( !src || src.length !== 1 ) { throw { fluenterror: 3 }; } + var sheet = (new FLUENT.FRESHResume()).open( src[ 0 ] ); + sheet.saveAs( dst[0], sheet.meta.orgFormat === 'JRS' ? 'FRESH' : 'JRS' ); + } + /** Supported resume formats. */ @@ -181,7 +191,8 @@ module.exports = function () { return { verbs: { generate: gen, - validate: validate + validate: validate, + convert: convert }, lib: require('./fluentlib'), options: _opts, diff --git a/tests/jrs-exemplar/richard-hendriks.json b/tests/jrs-exemplar/richard-hendriks.json new file mode 100644 index 0000000..17fddad --- /dev/null +++ b/tests/jrs-exemplar/richard-hendriks.json @@ -0,0 +1,130 @@ +{ + "basics": { + "name": "Richard Hendriks", + "label": "Programmer", + "picture": "", + "email": "richard.hendriks@gmail.com", + "phone": "(912) 555-4321", + "website": "http://richardhendricks.com", + "summary": "Richard hails from Tulsa. He has earned degrees from the University of Oklahoma and Stanford. (Go Sooners and Cardinals!) Before starting Pied Piper, he worked for Hooli as a part time software developer. While his work focuses on applied information theory, mostly optimizing lossless compression schema of both the length-limited and adaptive variants, his non-work interests range widely, everything from quantum computing to chaos theory. He could tell you about it, but THAT would NOT be a “length-limited” conversation!", + "location": { + "address": "2712 Broadway St", + "postalCode": "CA 94115", + "city": "San Francisco", + "countryCode": "US", + "region": "California" + }, + "profiles": [ + { + "network": "Twitter", + "username": "neutralthoughts", + "url": "" + }, + { + "network": "SoundCloud", + "username": "dandymusicnl", + "url": "https://soundcloud.com/dandymusicnl" + } + ] + }, + "work": [ + { + "company": "Pied Piper", + "position": "CEO/President", + "website": "http://piedpiper.com", + "startDate": "2013-12-01", + "endDate": "2014-12-01", + "summary": "Pied Piper is a multi-platform technology based on a proprietary universal compression algorithm that has consistently fielded high Weisman Scores™ that are not merely competitive, but approach the theoretical limit of lossless compression.", + "highlights": [ + "Build an algorithm for artist to detect if their music was violating copy right infringement laws", + "Successfully won Techcrunch Disrupt", + "Optimized an algorithm that holds the current world record for Weisman Scores" + ] + } + ], + "volunteer": [ + { + "organization": "CoderDojo", + "position": "Teacher", + "website": "http://coderdojo.com/", + "startDate": "2012-01-01", + "endDate": "2013-01-01", + "summary": "Global movement of free coding clubs for young people.", + "highlights": [ + "Awarded 'Teacher of the Month'" + ] + } + ], + "education": [ + { + "institution": "University of Oklahoma", + "area": "Information Technology", + "studyType": "Bachelor", + "startDate": "2011-06-01", + "endDate": "2014-01-01", + "gpa": "4.0", + "courses": [ + "DB1101 - Basic SQL", + "CS2011 - Java Introduction" + ] + } + ], + "awards": [ + { + "title": "Digital Compression Pioneer Award", + "date": "2014-11-01", + "awarder": "Techcrunch", + "summary": "There is no spoon." + } + ], + "publications": [ + { + "name": "Video compression for 3d media", + "publisher": "Hooli", + "releaseDate": "2014-10-01", + "website": "http://en.wikipedia.org/wiki/Silicon_Valley_(TV_series)", + "summary": "Innovative middle-out compression algorithm that changes the way we store data." + } + ], + "skills": [ + { + "name": "Web Development", + "level": "Master", + "keywords": [ + "HTML", + "CSS", + "Javascript" + ] + }, + { + "name": "Compression", + "level": "Master", + "keywords": [ + "Mpeg", + "MP4", + "GIF" + ] + } + ], + "languages": [ + { + "language": "English", + "fluency": "Native speaker" + } + ], + "interests": [ + { + "name": "Wildlife", + "keywords": [ + "Ferrets", + "Unicorns" + ] + } + ], + "references": [ + { + "name": "Erlich Bachman", + "reference": "It is my pleasure to recommend Richard, his performance working as a consultant for Main St. Company proved that he will be a valuable addition to any company." + } + ] +} diff --git a/tests/test-converter.js b/tests/test-converter.js new file mode 100644 index 0000000..ac778e2 --- /dev/null +++ b/tests/test-converter.js @@ -0,0 +1,36 @@ + +var chai = require('chai') + , expect = chai.expect + , should = chai.should() + , path = require('path') + , _ = require('underscore') + , FRESHResume = require('../src/core/fresh-resume') + , CONVERTER = require('../src/core/convert') + , FS = require('fs') + , _ = require('underscore'); + +chai.config.includeStack = false; + +describe('FRESH/JRS converter', function () { + + var _sheet; + + it('should round-trip from JRS to FRESH to JRS without modifying or losing data', function () { + + var fileA = path.join( __dirname, 'jrs-exemplar/richard-hendriks.json' ); + var fileB = path.join( __dirname, 'sandbox/richard-hendriks.json' ); + + _sheet = new FRESHResume().open( fileA ); + _sheet.saveAs( fileB, 'JRS' ); + + var rawA = FS.readFileSync( fileA, 'utf8' ); + var rawB = FS.readFileSync( fileB, 'utf8' ); + + var objA = JSON.parse( rawA ); + var objB = JSON.parse( rawB ); + + _.isEqual(objA, objB).should.equal(true); + + }); + +});