mirror of
https://github.com/JuanCanham/HackMyResume.git
synced 2024-11-05 09:56:22 +00:00
commit
786b3fd3b2
@ -17,6 +17,8 @@ module.exports = function (grunt) {
|
|||||||
all: { src: ['tests/*.js'] }
|
all: { src: ['tests/*.js'] }
|
||||||
},
|
},
|
||||||
|
|
||||||
|
clean: ['tests/sandbox'],
|
||||||
|
|
||||||
yuidoc: {
|
yuidoc: {
|
||||||
compile: {
|
compile: {
|
||||||
name: '<%= pkg.name %>',
|
name: '<%= pkg.name %>',
|
||||||
@ -46,9 +48,10 @@ module.exports = function (grunt) {
|
|||||||
grunt.loadNpmTasks('grunt-simple-mocha');
|
grunt.loadNpmTasks('grunt-simple-mocha');
|
||||||
grunt.loadNpmTasks('grunt-contrib-yuidoc');
|
grunt.loadNpmTasks('grunt-contrib-yuidoc');
|
||||||
grunt.loadNpmTasks('grunt-contrib-jshint');
|
grunt.loadNpmTasks('grunt-contrib-jshint');
|
||||||
|
grunt.loadNpmTasks('grunt-contrib-clean');
|
||||||
|
|
||||||
grunt.registerTask('test', 'Test the FluentCV library.',
|
grunt.registerTask('test', 'Test the FluentCV library.',
|
||||||
function( config ) { grunt.task.run( ['simplemocha:all'] ); });
|
function( config ) { grunt.task.run( ['clean','simplemocha:all'] ); });
|
||||||
grunt.registerTask('document', 'Generate FluentCV library documentation.',
|
grunt.registerTask('document', 'Generate FluentCV library documentation.',
|
||||||
function( config ) { grunt.task.run( ['yuidoc'] ); });
|
function( config ) { grunt.task.run( ['yuidoc'] ); });
|
||||||
grunt.registerTask('default', [ 'jshint', 'test', 'yuidoc' ]);
|
grunt.registerTask('default', [ 'jshint', 'test', 'yuidoc' ]);
|
||||||
|
16
README.md
16
README.md
@ -1,12 +1,13 @@
|
|||||||
fluentCV
|
fluentCV
|
||||||
========
|
========
|
||||||
*Create polished technical résumés and CVs in multiple formats from your command
|
*Create polished résumés and CVs in multiple formats from your command line or
|
||||||
line or shell. See [FluentCV Desktop][7] for the desktop version. OS X ~ Windows
|
shell. Author in clean Markdown and JSON, export to Word, HTML, PDF, LaTeX,
|
||||||
~ Linux.*
|
plain text, and other arbitrary formats.*
|
||||||
|
|
||||||
![](assets/fluentcv_cli_ubuntu.png)
|
![](assets/resume-bouqet.png)
|
||||||
|
|
||||||
FluentCV is a dev-friendly Swiss Army knife for resumes and CVs. Use it to:
|
FluentCV is a dev-friendly, local-only Swiss Army knife for resumes and CVs. Use
|
||||||
|
it to:
|
||||||
|
|
||||||
1. **Generate** HTML, Markdown, LaTeX, MS Word, PDF, plain text, JSON, XML,
|
1. **Generate** HTML, Markdown, LaTeX, MS Word, PDF, plain text, JSON, XML,
|
||||||
YAML, print, smoke signal, carrier pigeon, and other arbitrary-format resumes
|
YAML, print, smoke signal, carrier pigeon, and other arbitrary-format resumes
|
||||||
@ -14,7 +15,10 @@ and CVs, from a single source of truth—without violating DRY.
|
|||||||
2. **Convert** resumes between [FRESH][fresca] and [JSON Resume][6] formats.
|
2. **Convert** resumes between [FRESH][fresca] and [JSON Resume][6] formats.
|
||||||
3. **Validate** resumes against either format.
|
3. **Validate** resumes against either format.
|
||||||
|
|
||||||
FluentCV supports both the [FRESH][fresca] and [JSON Resume][6] source formats.
|
FluentCV is built with Node.js and runs on recent versions of OS X, Linux, or
|
||||||
|
Windows.
|
||||||
|
|
||||||
|
![](assets/fluentcv_cli_ubuntu.png)
|
||||||
|
|
||||||
## Features
|
## Features
|
||||||
|
|
||||||
|
BIN
assets/resume-bouqet.png
Normal file
BIN
assets/resume-bouqet.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 162 KiB |
11
package.json
11
package.json
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "fluentcv",
|
"name": "fluentcv",
|
||||||
"version": "0.10.3",
|
"version": "0.11.0",
|
||||||
"description": "Generate polished résumés and CVs in HTML, Markdown, LaTeX, MS Word, PDF, plain text, JSON, XML, YAML, smoke signal, and carrier pigeon.",
|
"description": "Generate polished résumés and CVs in HTML, Markdown, LaTeX, MS Word, PDF, plain text, JSON, XML, YAML, smoke signal, and carrier pigeon.",
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
@ -20,7 +20,7 @@
|
|||||||
"HTML",
|
"HTML",
|
||||||
"CLI"
|
"CLI"
|
||||||
],
|
],
|
||||||
"author": "James M. Devlin",
|
"author": "hacksalot <hacksalot@fluentdesk.com> (https://github.com/hacksalot)",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"preferGlobal": "true",
|
"preferGlobal": "true",
|
||||||
"bugs": {
|
"bugs": {
|
||||||
@ -33,8 +33,8 @@
|
|||||||
"homepage": "https://github.com/fluentdesk/fluentcv",
|
"homepage": "https://github.com/fluentdesk/fluentcv",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"colors": "^1.1.2",
|
"colors": "^1.1.2",
|
||||||
"fluent-themes": "~0.6.3-beta",
|
"fluent-themes": "~0.7.0-beta",
|
||||||
"fresca": "~0.2.1",
|
"fresca": "~0.2.2",
|
||||||
"fs-extra": "^0.24.0",
|
"fs-extra": "^0.24.0",
|
||||||
"handlebars": "^4.0.5",
|
"handlebars": "^4.0.5",
|
||||||
"html": "0.0.10",
|
"html": "0.0.10",
|
||||||
@ -54,10 +54,11 @@
|
|||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"chai": "*",
|
"chai": "*",
|
||||||
"grunt": "*",
|
"grunt": "*",
|
||||||
|
"grunt-contrib-clean": "^0.7.0",
|
||||||
"grunt-contrib-jshint": "^0.11.3",
|
"grunt-contrib-jshint": "^0.11.3",
|
||||||
"grunt-contrib-yuidoc": "^0.10.0",
|
"grunt-contrib-yuidoc": "^0.10.0",
|
||||||
"grunt-simple-mocha": "*",
|
"grunt-simple-mocha": "*",
|
||||||
"is-my-json-valid": "^2.12.2",
|
"jane-q-fullstacker": "fluentdesk/jane-q-fullstacker",
|
||||||
"mocha": "*",
|
"mocha": "*",
|
||||||
"resample": "fluentdesk/resample"
|
"resample": "fluentdesk/resample"
|
||||||
}
|
}
|
||||||
|
@ -100,6 +100,7 @@ Definition of the Theme class.
|
|||||||
var outFmt = '', isMajor = false;
|
var outFmt = '', isMajor = false;
|
||||||
var portion = pathInfo.dir.replace(tplFolder,'');
|
var portion = pathInfo.dir.replace(tplFolder,'');
|
||||||
if( portion && portion.trim() ) {
|
if( portion && portion.trim() ) {
|
||||||
|
if( portion[1] === '_' ) return;
|
||||||
var reg = /^(?:\/|\\)(html|latex|doc|pdf|partials)(?:\/|\\)?/ig;
|
var reg = /^(?:\/|\\)(html|latex|doc|pdf|partials)(?:\/|\\)?/ig;
|
||||||
var res = reg.exec( portion );
|
var res = reg.exec( portion );
|
||||||
if( res ) {
|
if( res ) {
|
||||||
@ -152,7 +153,7 @@ Definition of the Theme class.
|
|||||||
.forEach(function( cssf ) {
|
.forEach(function( cssf ) {
|
||||||
// For each CSS file, get its corresponding HTML file
|
// For each CSS file, get its corresponding HTML file
|
||||||
var idx = _.findIndex(fmts, function( fmt ) {
|
var idx = _.findIndex(fmts, function( fmt ) {
|
||||||
return fmt.pre === cssf.pre && fmt.ext === 'html';
|
return fmt && fmt.pre === cssf.pre && fmt.ext === 'html';
|
||||||
});
|
});
|
||||||
cssf.action = null;
|
cssf.action = null;
|
||||||
fmts[ idx ].css = cssf.data;
|
fmts[ idx ].css = cssf.data;
|
||||||
|
@ -11,93 +11,40 @@ Definition of the HandlebarsGenerator class.
|
|||||||
var _ = require('underscore')
|
var _ = require('underscore')
|
||||||
, HANDLEBARS = require('handlebars')
|
, HANDLEBARS = require('handlebars')
|
||||||
, FS = require('fs')
|
, FS = require('fs')
|
||||||
, moment = require('moment')
|
, registerHelpers = require('./handlebars-helpers');
|
||||||
, MD = require('marked')
|
|
||||||
, H2W = require('../utils/html-to-wpml');
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Perform template-based resume generation using Handlebars.js.
|
Perform template-based resume generation using Handlebars.js.
|
||||||
@method generate
|
@class HandlebarsGenerator
|
||||||
*/
|
*/
|
||||||
module.exports = function( json, jst, format, cssInfo, opts, theme ) {
|
var HandlebarsGenerator = module.exports = {
|
||||||
|
|
||||||
// Pre-compile any partials present in the theme.
|
generate: function( json, jst, format, cssInfo, opts, theme ) {
|
||||||
_.each( theme.partials, function( el ) {
|
|
||||||
var tplData = FS.readFileSync( el.path, 'utf8' );
|
|
||||||
var compiledTemplate = HANDLEBARS.compile( tplData );
|
|
||||||
HANDLEBARS.registerPartial( el.name, compiledTemplate );
|
|
||||||
});
|
|
||||||
|
|
||||||
// Register necessary helpers.
|
// Pre-compile any partials present in the theme.
|
||||||
registerHelpers();
|
_.each( theme.partials, function( el ) {
|
||||||
|
var tplData = FS.readFileSync( el.path, 'utf8' );
|
||||||
|
var compiledTemplate = HANDLEBARS.compile( tplData );
|
||||||
|
HANDLEBARS.registerPartial( el.name, compiledTemplate );
|
||||||
|
});
|
||||||
|
|
||||||
// Compile and run the Handlebars template.
|
// Register necessary helpers.
|
||||||
var template = HANDLEBARS.compile(jst);
|
registerHelpers();
|
||||||
return template({
|
|
||||||
r: json,
|
// Compile and run the Handlebars template.
|
||||||
filt: opts.filters,
|
var template = HANDLEBARS.compile(jst);
|
||||||
cssInfo: cssInfo,
|
return template({
|
||||||
headFragment: opts.headFragment || ''
|
r: format === 'html' || format === 'pdf' ? json.markdownify() : json,
|
||||||
});
|
RAW: json,
|
||||||
|
filt: opts.filters,
|
||||||
|
cssInfo: cssInfo,
|
||||||
|
headFragment: opts.headFragment || ''
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
Register useful Handlebars helpers.
|
|
||||||
@method registerHelpers
|
|
||||||
*/
|
|
||||||
function registerHelpers() {
|
|
||||||
|
|
||||||
// Set up a date formatting helper so we can do:
|
|
||||||
// {{#formatDate val 'YYYY-MM'}}
|
|
||||||
HANDLEBARS.registerHelper("formatDate", function(datetime, format) {
|
|
||||||
if( moment ) {
|
|
||||||
return moment( datetime ).format( format );
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return datetime;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Set up a Markdown-to-WordProcessingML helper so we can do:
|
|
||||||
// {{#wmpl val [true|false]}}
|
|
||||||
HANDLEBARS.registerHelper("wpml", function( txt, inline ) {
|
|
||||||
inline = (inline && !inline.hash) || false;
|
|
||||||
txt = inline ?
|
|
||||||
MD(txt.trim()).replace(/^\s*<p>|<\/p>\s*$/gi, '') :
|
|
||||||
MD(txt.trim());
|
|
||||||
txt = H2W( txt.trim() );
|
|
||||||
return txt;
|
|
||||||
});
|
|
||||||
|
|
||||||
// Set up a generic conditional helper so we can do:
|
|
||||||
// {{#compare val otherVal operator="<"}}
|
|
||||||
// http://doginthehat.com.au/2012/02/comparison-block-helper-for-handlebars-templates/
|
|
||||||
HANDLEBARS.registerHelper('compare', function(lvalue, rvalue, options) {
|
|
||||||
if (arguments.length < 3)
|
|
||||||
throw new Error("Handlerbars Helper 'compare' needs 2 parameters");
|
|
||||||
var operator = options.hash.operator || "==";
|
|
||||||
var operators = {
|
|
||||||
'==': function(l,r) { return l == r; },
|
|
||||||
'===': function(l,r) { return l === r; },
|
|
||||||
'!=': function(l,r) { return l != r; },
|
|
||||||
'<': function(l,r) { return l < r; },
|
|
||||||
'>': function(l,r) { return l > r; },
|
|
||||||
'<=': function(l,r) { return l <= r; },
|
|
||||||
'>=': function(l,r) { return l >= r; },
|
|
||||||
'typeof': function(l,r) { return typeof l == r; }
|
|
||||||
};
|
|
||||||
if (!operators[operator])
|
|
||||||
throw new Error("Handlerbars Helper 'compare' doesn't know the operator "+operator);
|
|
||||||
var result = operators[operator](lvalue,rvalue);
|
|
||||||
return result ? options.fn(this) : options.inverse(this);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}());
|
}());
|
||||||
|
124
src/eng/handlebars-helpers.js
Normal file
124
src/eng/handlebars-helpers.js
Normal file
@ -0,0 +1,124 @@
|
|||||||
|
/**
|
||||||
|
Template helper definitions for Handlebars.
|
||||||
|
@license MIT. Copyright (c) 2015 James Devlin / FluentDesk.
|
||||||
|
@module handlebars-helpers.js
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
(function() {
|
||||||
|
|
||||||
|
var HANDLEBARS = require('handlebars')
|
||||||
|
, MD = require('marked')
|
||||||
|
, H2W = require('../utils/html-to-wpml')
|
||||||
|
, moment = require('moment')
|
||||||
|
, _ = require('underscore');
|
||||||
|
|
||||||
|
/**
|
||||||
|
Register useful Handlebars helpers.
|
||||||
|
@method registerHelpers
|
||||||
|
*/
|
||||||
|
module.exports = function() {
|
||||||
|
|
||||||
|
// Set up a date formatting helper so we can do:
|
||||||
|
// {{formatDate val 'YYYY-MM'}}
|
||||||
|
HANDLEBARS.registerHelper("formatDate", function(datetime, format) {
|
||||||
|
return moment ? moment( datetime ).format( format ) : datetime;
|
||||||
|
});
|
||||||
|
|
||||||
|
// Set up a Markdown-to-WordProcessingML helper so we can do:
|
||||||
|
// {{wmpl val [true|false]}}
|
||||||
|
HANDLEBARS.registerHelper("wpml", function( txt, inline ) {
|
||||||
|
if(!txt) return '';
|
||||||
|
inline = (inline && !inline.hash) || false;
|
||||||
|
txt = inline ?
|
||||||
|
MD(txt.trim()).replace(/^\s*<p>|<\/p>\s*$/gi, '') :
|
||||||
|
MD(txt.trim());
|
||||||
|
txt = H2W( txt.trim() );
|
||||||
|
return txt;
|
||||||
|
});
|
||||||
|
|
||||||
|
// Set up a last-word helper so we can do:
|
||||||
|
// {{lastWord val [true|false]}}
|
||||||
|
HANDLEBARS.registerHelper("link", function( text, url ) {
|
||||||
|
return url && url.trim() ?
|
||||||
|
('<a href="' + url + '">' + text + '</a>') : text;
|
||||||
|
});
|
||||||
|
|
||||||
|
// Set up a last-word helper so we can do:
|
||||||
|
// {{lastWord val [true|false]}}
|
||||||
|
HANDLEBARS.registerHelper("lastWord", function( txt ) {
|
||||||
|
return txt && txt.trim() ? _.last( txt.split(' ') ) : '';
|
||||||
|
});
|
||||||
|
|
||||||
|
// Set up a skill colorizing helper:
|
||||||
|
// {{skillColor val}}
|
||||||
|
HANDLEBARS.registerHelper("skillColor", function( lvl ) {
|
||||||
|
switch(lvl) {
|
||||||
|
case 'beginner': return '#5CB85C';
|
||||||
|
case 'intermediate': return '#F1C40F';
|
||||||
|
case 'advanced': return '#428BCA';
|
||||||
|
case 'master': return '#C00000';
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Set up a skill colorizing helper:
|
||||||
|
// {{skillColor val}}
|
||||||
|
HANDLEBARS.registerHelper("skillHeight", function( lvl ) {
|
||||||
|
switch(lvl) {
|
||||||
|
case 'beginner': return '30';
|
||||||
|
case 'intermediate': return '16';
|
||||||
|
case 'advanced': return '8';
|
||||||
|
case 'master': return '0';
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Set up a Markdown-to-WordProcessingML helper so we can do:
|
||||||
|
// {{initialWords val [true|false]}}
|
||||||
|
HANDLEBARS.registerHelper("initialWords", function( txt ) {
|
||||||
|
return txt && txt.trim() ? _.initial( txt.split(' ') ).join(' ') : '';
|
||||||
|
});
|
||||||
|
|
||||||
|
// Set up a URL-trimming helper to drop the protocol so we can do:
|
||||||
|
// {{trimURL url}}
|
||||||
|
HANDLEBARS.registerHelper("trimURL", function( url ) {
|
||||||
|
return url && url.trim() ? url.trim().replace(/^https?:\/\//i, '') : '';
|
||||||
|
});
|
||||||
|
|
||||||
|
// Set up a URL-trimming helper to drop the protocol so we can do:
|
||||||
|
// {{trimURL url}}
|
||||||
|
HANDLEBARS.registerHelper("toLower", function( txt ) {
|
||||||
|
return txt && txt.trim() ? txt.toLowerCase() : '';
|
||||||
|
});
|
||||||
|
|
||||||
|
// Set up a Markdown-to-WordProcessingML helper so we can do:
|
||||||
|
// {{either A B}}
|
||||||
|
HANDLEBARS.registerHelper("either", function( lhs, rhs, options ) {
|
||||||
|
if (lhs || rhs) return options.fn(this);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Set up a generic conditional helper so we can do:
|
||||||
|
// {{compare val otherVal operator="<"}}
|
||||||
|
// http://doginthehat.com.au/2012/02/comparison-block-helper-for-handlebars-templates/
|
||||||
|
HANDLEBARS.registerHelper('compare', function(lvalue, rvalue, options) {
|
||||||
|
if (arguments.length < 3)
|
||||||
|
throw new Error("Handlerbars Helper 'compare' needs 2 parameters");
|
||||||
|
var operator = options.hash.operator || "==";
|
||||||
|
var operators = {
|
||||||
|
'==': function(l,r) { return l == r; },
|
||||||
|
'===': function(l,r) { return l === r; },
|
||||||
|
'!=': function(l,r) { return l != r; },
|
||||||
|
'<': function(l,r) { return l < r; },
|
||||||
|
'>': function(l,r) { return l > r; },
|
||||||
|
'<=': function(l,r) { return l <= r; },
|
||||||
|
'>=': function(l,r) { return l >= r; },
|
||||||
|
'typeof': function(l,r) { return typeof l == r; }
|
||||||
|
};
|
||||||
|
if (!operators[operator])
|
||||||
|
throw new Error("Handlerbars Helper 'compare' doesn't know the operator "+operator);
|
||||||
|
var result = operators[operator](lvalue,rvalue);
|
||||||
|
return result ? options.fn(this) : options.inverse(this);
|
||||||
|
});
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
}());
|
@ -1,37 +1,52 @@
|
|||||||
/**
|
/**
|
||||||
Definition of the UnderscoreGenerator class.
|
Definition of the UnderscoreGenerator class.
|
||||||
@license MIT. Copyright (c) 2015 James Devlin / FluentDesk.
|
@license MIT. Copyright (c) 2015 James Devlin / FluentDesk.
|
||||||
|
@module underscore-generator.js
|
||||||
*/
|
*/
|
||||||
|
|
||||||
(function() {
|
(function() {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
var _ = require('underscore');
|
var _ = require('underscore');
|
||||||
|
|
||||||
module.exports = function( json, jst, format, cssInfo, opts, theme ) {
|
|
||||||
|
|
||||||
// Tweak underscore's default template delimeters
|
|
||||||
var delims = (opts.themeObj && opts.themeObj.delimeters) || opts.template;
|
/**
|
||||||
if( opts.themeObj && opts.themeObj.delimeters ) {
|
Perform template-based resume generation using Underscore.js.
|
||||||
delims = _.mapObject( delims, function(val,key) {
|
@class UnderscoreGenerator
|
||||||
return new RegExp( val, "ig");
|
*/
|
||||||
|
var UnderscoreGenerator = module.exports = {
|
||||||
|
|
||||||
|
generate: function( json, jst, format, cssInfo, opts, theme ) {
|
||||||
|
|
||||||
|
// Tweak underscore's default template delimeters
|
||||||
|
var delims = (opts.themeObj && opts.themeObj.delimeters) || opts.template;
|
||||||
|
if( opts.themeObj && opts.themeObj.delimeters ) {
|
||||||
|
delims = _.mapObject( delims, function(val,key) {
|
||||||
|
return new RegExp( val, "ig");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
_.templateSettings = delims;
|
||||||
|
|
||||||
|
// Strip {# comments #}
|
||||||
|
jst = jst.replace( delims.comment, '');
|
||||||
|
|
||||||
|
// Compile and run the template. TODO: avoid unnecessary recompiles.
|
||||||
|
var compiled = _.template(jst);
|
||||||
|
var ret = compiled({
|
||||||
|
r: format === 'html' || format === 'pdf' ? json.markdownify() : json,
|
||||||
|
filt: opts.filters,
|
||||||
|
XML: require('xml-escape'),
|
||||||
|
RAW: json,
|
||||||
|
cssInfo: cssInfo,
|
||||||
|
headFragment: opts.headFragment || ''
|
||||||
});
|
});
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
_.templateSettings = delims;
|
|
||||||
|
|
||||||
// Strip {# comments #}
|
|
||||||
jst = jst.replace( delims.comment, '');
|
|
||||||
// Compile and run the template. TODO: avoid unnecessary recompiles.
|
|
||||||
var compiled = _.template(jst);
|
|
||||||
var ret = compiled({
|
|
||||||
r: format === 'html' || format === 'pdf' ? json.markdownify() : json,
|
|
||||||
filt: opts.filters,
|
|
||||||
XML: require('xml-escape'),
|
|
||||||
RAW: json,
|
|
||||||
cssInfo: cssInfo,
|
|
||||||
headFragment: opts.headFragment || ''
|
|
||||||
});
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}());
|
}());
|
||||||
|
@ -142,9 +142,8 @@ Definition of the TemplateGenerator class.
|
|||||||
*/
|
*/
|
||||||
single: function( json, jst, format, cssInfo, opts, theme ) {
|
single: function( json, jst, format, cssInfo, opts, theme ) {
|
||||||
this.opts.freezeBreaks && ( jst = freeze(jst) );
|
this.opts.freezeBreaks && ( jst = freeze(jst) );
|
||||||
var eng = require( '../eng/' + ((opts.themeObj && opts.themeObj.engine) ||
|
var eng = require( '../eng/' + theme.engine + '-generator' );
|
||||||
opts.engine) + '-generator' );
|
var result = eng.generate( json, jst, format, cssInfo, opts, theme );
|
||||||
var result = eng( json, jst, format, cssInfo, opts, theme );
|
|
||||||
this.opts.freezeBreaks && ( result = unfreeze(result) );
|
this.opts.freezeBreaks && ( result = unfreeze(result) );
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -1,14 +1,14 @@
|
|||||||
{
|
{
|
||||||
"basics": {
|
"basics": {
|
||||||
"name": "Jane Doe",
|
"name": "Jane Q. Fullstacker",
|
||||||
"label": "Senior Developer / Code Ninja",
|
"label": "Senior Developer",
|
||||||
"summary": "**Full-stack software developer with 6+ years industry experience** specializing in scalable cloud architectures for this, that, and the other. A native of southern CA, Jane enjoys hiking, mystery novels, and the company of Rufus, her two-year-old beagle.",
|
"summary": "**Full-stack software developer with 6+ years industry experience** specializing in scalable cloud architectures for this, that, and the other. A native of southern CA, Jane enjoys hiking, mystery novels, and the company of Rufus, her two-year-old beagle.",
|
||||||
"website": "http://jane-doe.me",
|
"website": "http://janef.me/blog",
|
||||||
"phone": "1-650-999-7777",
|
"phone": "1-650-999-7777",
|
||||||
"email": "jdoe@onecoolstartup.io",
|
"email": "jdoe@onecoolstartup.io",
|
||||||
"picture": "jane_doe.png",
|
"picture": "jane_doe.png",
|
||||||
"location": {
|
"location": {
|
||||||
"address": "Jane Doe\n123 Somewhere Rd.\nMountain View, CA 94035",
|
"address": "Jane Fullstacker\n123 Somewhere Rd.\nMountain View, CA 94035",
|
||||||
"postalCode": "94035",
|
"postalCode": "94035",
|
||||||
"city": "Mountain View",
|
"city": "Mountain View",
|
||||||
"countryCode": "US",
|
"countryCode": "US",
|
||||||
@ -17,13 +17,13 @@
|
|||||||
"profiles": [
|
"profiles": [
|
||||||
{
|
{
|
||||||
"network": "GitHub",
|
"network": "GitHub",
|
||||||
"username": "jane-doe-was-here",
|
"username": "janef-was-here",
|
||||||
"url": "https://github.com/jane-doe-was-here"
|
"url": "https://github.com/janef-was-here"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"network": "Twitter",
|
"network": "Twitter",
|
||||||
"username": "jane-doe-was-here",
|
"username": "janef-was-here",
|
||||||
"url": "https://twitter.com/jane-doe-was-here"
|
"url": "https://twitter.com/janef-was-here"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
@ -104,17 +104,55 @@
|
|||||||
],
|
],
|
||||||
"skills": [
|
"skills": [
|
||||||
{
|
{
|
||||||
"name": "Programming",
|
"name": "Web Dev",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"C++",
|
"JavaScript",
|
||||||
"Ruby",
|
"HTML 5",
|
||||||
"Xcode"
|
"CSS",
|
||||||
|
"LAMP",
|
||||||
|
"MVC",
|
||||||
|
"REST"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Project Management",
|
"name": "JavaScript",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"Agile"
|
"Node.js",
|
||||||
|
"Angular.js",
|
||||||
|
"jQuery",
|
||||||
|
"Bootstrap",
|
||||||
|
"React.js",
|
||||||
|
"Backbone.js"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Database",
|
||||||
|
"keywords": [
|
||||||
|
"MySQL",
|
||||||
|
"PostgreSQL",
|
||||||
|
"NoSQL",
|
||||||
|
"ORM",
|
||||||
|
"Hibernate"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Cloud",
|
||||||
|
"keywords": [
|
||||||
|
"AWS",
|
||||||
|
"EC2",
|
||||||
|
"RDS",
|
||||||
|
"S3",
|
||||||
|
"Azure",
|
||||||
|
"Dropbox"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Project",
|
||||||
|
"keywords": [
|
||||||
|
"Agile",
|
||||||
|
"TFS",
|
||||||
|
"Unified Process",
|
||||||
|
"MS Project"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
@ -166,10 +204,10 @@
|
|||||||
"website": "http://codeproject.com/build-ui-electron-atom.aspx"
|
"website": "http://codeproject.com/build-ui-electron-atom.aspx"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Jane Doe Unplugged",
|
"name": "Jane Fullstacker's Blog",
|
||||||
"publisher": "self",
|
"publisher": "self",
|
||||||
"releaseDate": "2011",
|
"releaseDate": "2011",
|
||||||
"website": "http://jane-doe.me"
|
"website": "http://janef.me"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Teach Yourself GORFF in 21 Days",
|
"name": "Teach Yourself GORFF in 21 Days",
|
||||||
@ -218,7 +256,8 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"language": "Spanish",
|
"language": "Spanish",
|
||||||
"level": "Moderate"
|
"level": "Moderate",
|
||||||
|
"years": 10
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
@ -7,6 +7,7 @@ var chai = require('chai')
|
|||||||
, FRESHResume = require('../src/core/fresh-resume')
|
, FRESHResume = require('../src/core/fresh-resume')
|
||||||
, CONVERTER = require('../src/core/convert')
|
, CONVERTER = require('../src/core/convert')
|
||||||
, FS = require('fs')
|
, FS = require('fs')
|
||||||
|
, MKDIRP = require('mkdirp')
|
||||||
, _ = require('underscore');
|
, _ = require('underscore');
|
||||||
|
|
||||||
chai.config.includeStack = false;
|
chai.config.includeStack = false;
|
||||||
@ -21,6 +22,7 @@ describe('FRESH/JRS converter', function () {
|
|||||||
var fileB = path.join( __dirname, 'sandbox/richard-hendriks.json' );
|
var fileB = path.join( __dirname, 'sandbox/richard-hendriks.json' );
|
||||||
|
|
||||||
_sheet = new FRESHResume().open( fileA );
|
_sheet = new FRESHResume().open( fileA );
|
||||||
|
MKDIRP.sync( path.parse(fileB).dir );
|
||||||
_sheet.saveAs( fileB, 'JRS' );
|
_sheet.saveAs( fileB, 'JRS' );
|
||||||
|
|
||||||
var rawA = FS.readFileSync( fileA, 'utf8' );
|
var rawA = FS.readFileSync( fileA, 'utf8' );
|
||||||
|
@ -16,7 +16,7 @@ describe('jane-doe.json (FRESH)', function () {
|
|||||||
it('should open without throwing an exception', function () {
|
it('should open without throwing an exception', function () {
|
||||||
function tryOpen() {
|
function tryOpen() {
|
||||||
_sheet = new FRESHResume().open(
|
_sheet = new FRESHResume().open(
|
||||||
'node_modules/FRESCA/exemplar/jane-doe.json' );
|
'node_modules/jane-q-fullstacker/resume/jane-resume.json' );
|
||||||
}
|
}
|
||||||
tryOpen.should.not.Throw();
|
tryOpen.should.not.Throw();
|
||||||
});
|
});
|
||||||
@ -43,13 +43,13 @@ describe('jane-doe.json (FRESH)', function () {
|
|||||||
|
|
||||||
it('should save without throwing an exception', function(){
|
it('should save without throwing an exception', function(){
|
||||||
function trySave() {
|
function trySave() {
|
||||||
_sheet.save( 'tests/sandbox/jane-doe.json' );
|
_sheet.save( 'tests/sandbox/jane-q-fullstacker.json' );
|
||||||
}
|
}
|
||||||
trySave.should.not.Throw();
|
trySave.should.not.Throw();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should not be modified after saving', function() {
|
it('should not be modified after saving', function() {
|
||||||
var savedSheet = new FRESHResume().open('tests/sandbox/jane-doe.json');
|
var savedSheet = new FRESHResume().open('tests/sandbox/jane-q-fullstacker.json');
|
||||||
_sheet.stringify().should.equal( savedSheet.stringify() )
|
_sheet.stringify().should.equal( savedSheet.stringify() )
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -16,7 +16,7 @@ describe('jane-doe.json (JRS)', function () {
|
|||||||
it('should open without throwing an exception', function () {
|
it('should open without throwing an exception', function () {
|
||||||
function tryOpen() {
|
function tryOpen() {
|
||||||
_sheet = new JRSResume().open(
|
_sheet = new JRSResume().open(
|
||||||
path.join( __dirname, 'resumes/jrs/jane-doe.json' ) );
|
path.join( __dirname, 'resumes/jrs/jane-q-fullstacker.json' ) );
|
||||||
}
|
}
|
||||||
tryOpen.should.not.Throw();
|
tryOpen.should.not.Throw();
|
||||||
});
|
});
|
||||||
@ -39,13 +39,13 @@ describe('jane-doe.json (JRS)', function () {
|
|||||||
|
|
||||||
it('should save without throwing an exception', function(){
|
it('should save without throwing an exception', function(){
|
||||||
function trySave() {
|
function trySave() {
|
||||||
_sheet.save( 'tests/sandbox/jane-doe.json' );
|
_sheet.save( 'tests/sandbox/jane-q-fullstacker.json' );
|
||||||
}
|
}
|
||||||
trySave.should.not.Throw();
|
trySave.should.not.Throw();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should not be modified after saving', function() {
|
it('should not be modified after saving', function() {
|
||||||
var savedSheet = new JRSResume().open( 'tests/sandbox/jane-doe.json' );
|
var savedSheet = new JRSResume().open( 'tests/sandbox/jane-q-fullstacker.json' );
|
||||||
_sheet.stringify().should.equal( savedSheet.stringify() )
|
_sheet.stringify().should.equal( savedSheet.stringify() )
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -29,8 +29,8 @@ describe('Testing themes', function () {
|
|||||||
function genTheme( themeName ) {
|
function genTheme( themeName ) {
|
||||||
it( themeName.toUpperCase() + ' theme should generate without throwing an exception', function () {
|
it( themeName.toUpperCase() + ' theme should generate without throwing an exception', function () {
|
||||||
function tryOpen() {
|
function tryOpen() {
|
||||||
var src = ['node_modules/FRESCA/exemplar/jane-doe.json'];
|
var src = ['node_modules/jane-q-fullstacker/resume/jane-resume.json'];
|
||||||
var dst = ['tests/sandbox/hello-world/resume.all'];
|
var dst = ['tests/sandbox/' + themeName + '/resume.all'];
|
||||||
var opts = {
|
var opts = {
|
||||||
theme: themeName,
|
theme: themeName,
|
||||||
format: 'FRESH',
|
format: 'FRESH',
|
||||||
@ -48,5 +48,6 @@ describe('Testing themes', function () {
|
|||||||
genTheme('modern');
|
genTheme('modern');
|
||||||
genTheme('minimist');
|
genTheme('minimist');
|
||||||
genTheme('awesome');
|
genTheme('awesome');
|
||||||
|
genTheme('positive');
|
||||||
|
|
||||||
});
|
});
|
||||||
|
Loading…
Reference in New Issue
Block a user