1
0
mirror of https://github.com/JuanCanham/HackMyResume.git synced 2025-05-10 07:47:07 +01:00

Introduce FluentLib sources.

This commit is contained in:
devlinjd
2015-10-26 12:30:00 -04:00
parent 21d9db2d99
commit 0aaa9ffff8
24 changed files with 1576 additions and 6 deletions

43
src/gen/base-generator.js Normal file
View File

@ -0,0 +1,43 @@
/**
Base resume generator for FluentCV.
@license Copyright (c) 2015 | James M. Devlin
*/
(function() {
// Use J. Resig's nifty class implementation
var Class = require( '../utils/class' );
/**
The BaseGenerator class is the root of the generator hierarchy. Functionality
common to ALL generators lives here.
*/
var BaseGenerator = module.exports = Class.extend({
/**
Base-class initialize.
*/
init: function( outputFormat ) {
this.format = outputFormat;
},
/**
Status codes.
*/
codes: {
success: 0,
themeNotFound: 1,
copyCss: 2,
resumeNotFound: 3
},
/**
Generator options.
*/
opts: {
}
});
}());

32
src/gen/html-generator.js Normal file
View File

@ -0,0 +1,32 @@
/**
HTML resume generator for FluentCV.
@license Copyright (c) 2015 by James M. Devlin. All rights reserved.
*/
var TemplateGenerator = require('./template-generator');
var FS = require('fs-extra');
var HTML = require( 'html' );
var HtmlGenerator = module.exports = TemplateGenerator.extend({
init: function() {
this._super( 'html' );
},
/**
Generate an HTML resume with optional pretty printing.
*/
onBeforeSave: function( mk, theme, outputFile ) {
var themeFile = theme.getFormat('html').path;
var cssSrc = themeFile.replace( /.html$/g, '.css' );
var cssDst = outputFile.replace( /.html$/g, '.css' );
var that = this;
FS.copySync( cssSrc, cssDst, { clobber: true }, function( e ) {
throw { fluenterror: that.codes.copyCss, data: [cssSrc,cssDst] };
});
return this.opts.prettify ?
HTML.prettyPrint( mk, this.opts.prettify ) : mk;
}
});

View File

@ -0,0 +1,74 @@
/**
HTML-based PDF resume generator for FluentCV.
@license Copyright (c) 2015 by James M. Devlin. All rights reserved.
*/
var TemplateGenerator = require('./template-generator');
var FS = require('fs-extra');
var HTML = require( 'html' );
var HtmlPdfGenerator = module.exports = TemplateGenerator.extend({
init: function() {
this._super( 'pdf', 'html' );
},
/**
Generate an HTML resume with optional pretty printing.
TODO: Avoid copying the CSS file to dest if we don't need to.
*/
onBeforeSave: function( mk, themeFile, outputFile ) {
// var cssSrc = themeFile.replace( /pdf\.html$/gi, 'html.css' );
// var cssDst = outputFile.replace( /\.pdf$/gi, '.css' );
// var that = this;
// FS.copySync( cssSrc, cssDst, { clobber: true }, function( e ) {
// if( e ) that.err( "Couldn't copy CSS file to destination: " + e);
// });
// return true ?
// HTML.prettyPrint( mk, { indent_size: 2 } ) : mk;
pdf(mk, outputFile);
return mk;
}
});
/**
Generate a PDF from HTML.
*/
function pdf( markup, fOut ) {
var pdfCount = 0;
if( false ) { //( _opts.pdf === 'phantom' || _opts.pdf == 'all' ) {
pdfCount++;
require('phantom').create( function( ph ) {
ph.createPage( function( page ) {
page.setContent( markup );
page.set('paperSize', {
format: 'A4',
orientation: 'portrait',
margin: '1cm'
});
page.set("viewportSize", {
width: 1024, // TODO: option-ify
height: 768 // TODO: Use "A" sizes
});
page.set('onLoadFinished', function(success) {
page.render( fOut );
pdfCount++;
ph.exit();
});
},
{ dnodeOpts: { weak: false } } );
});
}
if( true ) { // _opts.pdf === 'wkhtmltopdf' || _opts.pdf == 'all' ) {
var fOut2 = fOut;
if( pdfCount == 1 ) {
fOut2 = fOut2.replace(/\.pdf$/g, '.b.pdf');
}
require('wkhtmltopdf')( markup, { pageSize: 'letter' } )
.pipe( FS.createWriteStream( fOut2 ) );
pdfCount++;
}
}

35
src/gen/json-generator.js Normal file
View File

@ -0,0 +1,35 @@
/**
Definition of the JsonGenerator class.
@license Copyright (c) 2015 | James M. Devlin
*/
var BaseGenerator = require('./base-generator');
var FS = require('fs');
var _ = require('underscore');
/**
The JsonGenerator generates a JSON resume directly.
*/
var JsonGenerator = module.exports = BaseGenerator.extend({
init: function(){
this._super( 'json' );
},
invoke: function( rez ) {
// TODO: merge with FCVD
function replacer( key,value ) { // Exclude these keys from stringification
return _.some(['meta', 'warnings', 'computed', 'filt', 'ctrl', 'index',
'safeStartDate', 'safeEndDate', 'safeDate', 'safeReleaseDate', 'result',
'isModified', 'htmlPreview'],
function( val ) { return key.trim() === val; }
) ? undefined : value;
}
return JSON.stringify( rez, replacer, 2 );
},
generate: function( rez, f ) {
FS.writeFileSync( f, this.invoke(rez), 'utf8' );
}
});

View File

@ -0,0 +1,37 @@
/**
A JSON-driven YAML resume generator for FluentLib.
@module json-yaml-generator.js
@license MIT. Copyright (c) 2015 James Devlin / FluentDesk
*/
(function() {
var BaseGenerator = require('./base-generator');
var FS = require('fs');
var YAML = require('yamljs');
/**
JsonYamlGenerator takes a JSON resume object and translates it directly to
JSON without a template, producing an equivalent YAML-formatted resume. See
also YamlGenerator (yaml-generator.js).
*/
var JsonYamlGenerator = module.exports = BaseGenerator.extend({
init: function(){
this._super( 'yml' );
},
invoke: function( rez, themeMarkup, cssInfo, opts ) {
return YAML.stringify( JSON.parse( rez.stringify() ), Infinity, 2 );
},
generate: function( rez, f, opts ) {
var data = YAML.stringify( JSON.parse( rez.stringify() ), Infinity, 2 );
FS.writeFileSync( f, data, 'utf8' );
}
});
}());

View File

@ -0,0 +1,17 @@
/**
Markdown resume generator for FluentCV.
@license Copyright (c) 2015 by James M. Devlin. All rights reserved.
*/
var TemplateGenerator = require('./template-generator');
/**
MarkdownGenerator generates a Markdown-formatted resume via TemplateGenerator.
*/
var MarkdownGenerator = module.exports = TemplateGenerator.extend({
init: function(){
this._super( 'md', 'txt' );
}
});

View File

@ -0,0 +1,173 @@
/**
Template-based resume generator base for FluentCV.
@license Copyright (c) 2015 | James M. Devlin
*/
var FS = require( 'fs' )
, _ = require( 'underscore' )
, MD = require( 'marked' )
, XML = require( 'xml-escape' )
, PATH = require('path')
, BaseGenerator = require( './base-generator' )
, EXTEND = require('../utils/extend')
, Theme = require('../core/theme');
// Default options.
var _defaultOpts = {
themeRelative: '../../node_modules/watermark/themes',
keepBreaks: true,
freezeBreaks: true,
nSym: '&newl;', // newline entity
rSym: '&retn;', // return entity
template: {
interpolate: /\{\{(.+?)\}\}/g,
escape: /\{\{\=(.+?)\}\}/g,
evaluate: /\{\%(.+?)\%\}/g,
comment: /\{\#(.+?)\#\}/g
},
filters: {
out: function( txt ) { return txt; },
raw: function( txt ) { return txt; },
xml: function( txt ) { return XML(txt); },
md: function( txt ) { return MD(txt); },
mdin: function( txt ) { return MD(txt).replace(/^\s*\<p\>|\<\/p\>\s*$/gi, ''); },
lower: function( txt ) { return txt.toLowerCase(); }
},
prettify: { // ← See https://github.com/beautify-web/js-beautify#options
indent_size: 2,
unformatted: ['em','strong'],
max_char: 80, // ← See lib/html.js in above-linked repo
//wrap_line_length: 120, <-- Don't use this
}
};
/**
TemplateGenerator performs resume generation via Underscore-style template
expansion and is appropriate for text-based formats like HTML, plain text,
and XML versions of Microsoft Word, Excel, and OpenOffice.
*/
var TemplateGenerator = module.exports = BaseGenerator.extend({
/** outputFormat: html, txt, pdf, doc
templateFormat: html or txt
**/
init: function( outputFormat, templateFormat, cssFile ){
this._super( outputFormat );
this.tplFormat = templateFormat || outputFormat;
},
/** Default generation method for template-based generators. */
invoke: function( rez, themeMarkup, cssInfo, opts ) {
// Compile and invoke the template!
this.opts = EXTEND( true, {}, _defaultOpts, opts );
mk = this.single( rez, themeMarkup, this.format, cssInfo, { } );
this.onBeforeSave && (mk = this.onBeforeSave( mk, themeFile, f ));
return mk;
},
/** Default generation method for template-based generators. */
generate: function( rez, f, opts ) {
// Carry over options
this.opts = EXTEND( true, { }, _defaultOpts, opts );
// Verify the specified theme name/path
var tFolder = PATH.resolve( __dirname, this.opts.themeRelative, this.opts.theme );
var exists = require('../utils/file-exists');
if (!exists( tFolder )) {
tFolder = PATH.resolve( this.opts.theme );
if (!exists( tFolder )) {
throw { fluenterror: this.codes.themeNotFound, data: this.opts.theme };
}
}
// Load the theme
var theme = opts.themeObj || new Theme().open( tFolder );
// Load theme and CSS data
var tplFolder = PATH.join( tFolder, 'templates' );
var curFmt = theme.getFormat( this.format );
var ctx = { file: curFmt.css ? curFmt.cssPath : null, data: curFmt.css || null };
// Compile and invoke the template!
var mk = this.single( rez, curFmt.data, this.format, ctx, opts );
this.onBeforeSave && (mk = this.onBeforeSave( mk, theme, f ));
FS.writeFileSync( f, mk, { encoding: 'utf8', flags: 'w' } );
},
/**
Perform a single resume JSON-to-DEST resume transformation. Exists as a
separate function in order to expose string-based transformations to clients
who don't have access to filesystem resources (in-browser, etc.).
*/
single: function( json, jst, format, cssInfo, opts ) {
// Freeze whitespace in the template.
this.opts.freezeBreaks && ( jst = freeze(jst) );
// Tweak underscore's default template delimeters
_.templateSettings = this.opts.template;
// Convert {{ someVar }} to {% print(filt.out(someVar) %}
// Convert {{ someVar|someFilter }} to {% print(filt.someFilter(someVar) %}
jst = jst.replace( _.templateSettings.interpolate, function replace(m, p1) {
if( p1.indexOf('|') > -1 ) {
var terms = p1.split('|');
return '{% print( filt.' + terms[1] + '( ' + terms[0] + ' )) %}';
}
else {
return '{% print( filt.out(' + p1 + ') ) %}';
}
});
// Strip {# comments #}
jst = jst.replace( _.templateSettings.comment, '');
json.display_progress_bar = true;
// Compile and run the template. TODO: avoid unnecessary recompiles.
jst = _.template(jst)({ r: json, filt: this.opts.filters, cssInfo: cssInfo, headFragment: this.opts.headFragment || '' });
// Unfreeze whitespace
this.opts.freezeBreaks && ( jst = unfreeze(jst) );
return jst;
}
});
/**
Export the TemplateGenerator function/ctor.
*/
module.exports = TemplateGenerator;
/**
Freeze newlines for protection against errant JST parsers.
*/
function freeze( markup ) {
return markup
.replace( _reg.regN, _defaultOpts.nSym )
.replace( _reg.regR, _defaultOpts.rSym );
}
/**
Unfreeze newlines when the coast is clear.
*/
function unfreeze( markup ) {
return markup
.replace( _reg.regSymR, '\r' )
.replace( _reg.regSymN, '\n' );
}
/**
Regexes for linebreak preservation.
*/
var _reg = {
regN: new RegExp( '\n', 'g' ),
regR: new RegExp( '\r', 'g' ),
regSymN: new RegExp( _defaultOpts.nSym, 'g' ),
regSymR: new RegExp( _defaultOpts.rSym, 'g' )
};

19
src/gen/text-generator.js Normal file
View File

@ -0,0 +1,19 @@
/**
Plain text resume generator for FluentCV.
@license Copyright (c) 2015 by James M. Devlin. All rights reserved.
*/
var TemplateGenerator = require('./template-generator');
/**
The TextGenerator generates a plain-text resume via the TemplateGenerator.
*/
var TextGenerator = TemplateGenerator.extend({
init: function(){
this._super( 'txt' );
},
});
module.exports = TextGenerator;

13
src/gen/word-generator.js Normal file
View File

@ -0,0 +1,13 @@
/**
MS Word resume generator for FluentCV.
@license Copyright (c) 2015 by James M. Devlin. All rights reserved.
*/
var TemplateGenerator = require('./template-generator');
var WordGenerator = module.exports = TemplateGenerator.extend({
init: function(){
this._super( 'doc', 'xml' );
},
});

17
src/gen/xml-generator.js Normal file
View File

@ -0,0 +1,17 @@
/**
XML resume generator for FluentCV.
@license Copyright (c) 2015 | James M. Devlin
*/
var BaseGenerator = require('./base-generator');
/**
The XmlGenerator generates an XML resume via the TemplateGenerator.
*/
var XmlGenerator = module.exports = BaseGenerator.extend({
init: function(){
this._super( 'xml' );
},
});

24
src/gen/yaml-generator.js Normal file
View File

@ -0,0 +1,24 @@
/**
A YAML resume generator for FluentLib.
@module yaml-generator.js
@license MIT. Copyright (c) 2015 James Devlin / FluentDesk
*/
(function() {
var TemplateGenerator = require('./template-generator');
/**
YamlGenerator generates a YAML-formatted resume via TemplateGenerator.
*/
var YamlGenerator = module.exports = TemplateGenerator.extend({
init: function(){
this._super( 'yml', 'yml' );
}
});
}());