1
0
mirror of https://github.com/JuanCanham/HackMyResume.git synced 2024-11-22 16:30:11 +00:00

Start integrating JRS and FRESH rendering paths.

This commit is contained in:
hacksalot 2016-01-08 08:40:19 -05:00
parent 4a2a47f551
commit d6280e6d89
6 changed files with 143 additions and 74 deletions

View File

@ -29,7 +29,7 @@ Error-handling routines for HackMyResume.
err: function( ex, shouldExit ) { err: function( ex, shouldExit ) {
var msg = '', exitCode, log = console.log, showStack = false; var msg = '', exitCode, log = console.log, showStack = ex.showStack;
// If the exception has been handled elsewhere and shouldExit is true, // If the exception has been handled elsewhere and shouldExit is true,
// let's get out of here, otherwise silently return. // let's get out of here, otherwise silently return.

View File

@ -16,8 +16,7 @@ Definition of the JRSTheme class.
/** /**
The JRSTheme class is a representation of a JSON Resume The JRSTheme class is a representation of a JSON Resume theme asset.
theme asset. See also: FRESHTheme.
@class JRSTheme @class JRSTheme
*/ */
function JRSTheme() { function JRSTheme() {
@ -41,12 +40,31 @@ Definition of the JRSTheme class.
// Open and parse the theme's package.json file. // Open and parse the theme's package.json file.
var pkgJsonPath = PATH.join( thFolder, 'package.json' ); var pkgJsonPath = PATH.join( thFolder, 'package.json' );
if( pathExists( pkgJsonPath )) { if( pathExists( pkgJsonPath )) {
var thApi = require( thFolder ) var thApi = require( thFolder )
, thPkg = require( pkgJsonPath ); , thPkg = require( pkgJsonPath );
this.name = thPkg.name; this.name = thPkg.name;
this.render = (thApi && thApi.render) || undefined; this.render = (thApi && thApi.render) || undefined;
this.engine = 'jrs';
// Create theme formats (HTML and PDF)
this.formats = { this.formats = {
html: { title:'html', outFormat:'html', ext:'html' } html: { outFormat: 'html', files: [
{
action: 'transform',
render: this.render,
//path: absPath,
major: true,
//orgPath: PATH.relative(thFolder, absPath),
ext: pathInfo.extname.slice(1),
//title: friendlyName( outFmt ),
//pre: outFmt,
// outFormat: outFmt || pathInfo.name,
//data: FS.readFileSync( absPath, 'utf8' ),
css: null
}
]}
}; };
} }
else { else {

76
src/eng/jrs-generator.js Normal file
View File

@ -0,0 +1,76 @@
/**
Definition of the JRSGenerator class.
@license MIT. See LICENSE.md for details.
@module jrs-generator.js
*/
(function() {
var _ = require('underscore')
, HANDLEBARS = require('handlebars')
, FS = require('fs')
, registerHelpers = require('./handlebars-helpers')
, PATH = require('path')
, parsePath = require('parse-filepath')
, READFILES = require('recursive-readdir-sync')
, SLASH = require('slash')
, MD = require('marked');
/**
Perform template-based resume generation for JSON Resume themes.
@class JRSGenerator
*/
var JRSGenerator = module.exports = {
generate: function( json, jst, format, cssInfo, opts, theme ) {
// JSON Resume themes don't have a specific structure, so the safest thing
// to do is copy all files from source to dest.
// var COPY = require('copy');
// var globs = [ '*.css', '*.js', '*.png', '*.jpg', '*.gif', '*.bmp' ];
// COPY.sync( globs , outFolder, {
// cwd: theme.folder, nodir: true,
// ignore: ['node_modules/','node_modules/**']
// // rewrite: function(p1, p2) {
// // return PATH.join(p2, p1);
// // }
// });
// Disable JRS theme chatter (console.log, console.error, etc.)
var off = ['log', 'error', 'dir'], org = off.map(function(c){
var ret = console[c]; console[c] = function(){}; return ret;
});
// Freeze and render
var rezHtml = theme.render( json.harden() );
// Turn logging back on
off.forEach(function(c, idx){ console[c] = org[idx]; });
// Unfreeze and apply Markdown
rezHtml = rezHtml.replace( /@@@@~.*?~@@@@/gm, function(val){
return MDIN( val.replace( /~@@@@/gm,'' ).replace( /@@@@~/gm,'' ) );
});
return rezHtml;
}
};
function MDIN(txt) { // TODO: Move this
return MD(txt || '' ).replace(/^\s*<p>|<\/p>\s*$/gi, '');
}
}());

View File

@ -20,7 +20,8 @@ Definition of the HtmlPdfCLIGenerator class.
/** /**
An HTML-driven PDF resume generator for HackMyResume. Talks to Phantom, An HTML-driven PDF resume generator for HackMyResume. Talks to Phantom,
wkhtmltopdf, and other PDF libraries over a CLI. wkhtmltopdf, and other PDF engines over a CLI (command-line interface).
If an engine isn't installed for a particular platform, error out gracefully.
*/ */
var HtmlPdfCLIGenerator = module.exports = TemplateGenerator.extend({ var HtmlPdfCLIGenerator = module.exports = TemplateGenerator.extend({
@ -36,6 +37,7 @@ Definition of the HtmlPdfCLIGenerator class.
Generate the binary PDF. Generate the binary PDF.
*/ */
onBeforeSave: function( info ) { onBeforeSave: function( info ) {
console.log('Called');
try { try {
var safe_eng = info.opts.pdf || 'wkhtmltopdf'; var safe_eng = info.opts.pdf || 'wkhtmltopdf';
engines[ safe_eng ].call( this, info.mk, info.outputFile ); engines[ safe_eng ].call( this, info.mk, info.outputFile );
@ -50,16 +52,23 @@ Definition of the HtmlPdfCLIGenerator class.
} }
} }
}); });
// TODO: Move each engine to a separate module
var engines = { var engines = {
/** /**
Generate a PDF from HTML using wkhtmltopdf. Generate a PDF from HTML using wkhtmltopdf's CLI interface.
Spawns a child process with `wkhtmltopdf <source> <target>`. wkhtmltopdf
must be installed and path-accessible.
TODO: If HTML generation has run, reuse that output
TODO: Local web server to ease wkhtmltopdf rendering
*/ */
wkhtmltopdf: function(markup, fOut) { wkhtmltopdf: function(markup, fOut) {
@ -89,8 +98,11 @@ Definition of the HtmlPdfCLIGenerator class.
/** /**
Generate a PDF from HTML using Phantom. Generate a PDF from HTML using Phantom's CLI interface.
See: https://github.com/ariya/phantomjs/blob/master/examples/rasterize.js Spawns a child process with `phantomjs <script> <source> <target>`. Phantom
must be installed and path-accessible.
TODO: If HTML generation has run, reuse that output
TODO: Local web server to ease Phantom rendering
*/ */
phantom: function( markup, fOut ) { phantom: function( markup, fOut ) {
@ -104,7 +116,7 @@ Definition of the HtmlPdfCLIGenerator class.
var destPath = SLASH( PATH.relative( process.cwd(), fOut) ); var destPath = SLASH( PATH.relative( process.cwd(), fOut) );
var spawn = require('child_process').spawnSync; var spawn = require('child_process').spawnSync;
var info = spawn('1phantomjs', [ scriptPath, sourcePath, destPath ]); var info = spawn('phantomjs', [ scriptPath, sourcePath, destPath ]);
if( info.error ) { if( info.error ) {
throw { throw {
cmd: 'phantomjs', cmd: 'phantomjs',

View File

@ -1,5 +1,5 @@
/** /**
Definition of the TemplateGenerator class. Definition of the TemplateGenerator class. TODO: Refactor
@license MIT. See LICENSE.md for details. @license MIT. See LICENSE.md for details.
@module template-generator.js @module template-generator.js
*/ */
@ -145,6 +145,10 @@ Definition of the TemplateGenerator class.
var thisFilePath; var thisFilePath;
if( theme.engine === 'jrs' ) {
file.info.orgPath = '';
}
if( file.info.action === 'transform' ) { if( file.info.action === 'transform' ) {
thisFilePath = PATH.join( outFolder, file.info.orgPath ); thisFilePath = PATH.join( outFolder, file.info.orgPath );
try { try {
@ -175,7 +179,8 @@ Definition of the TemplateGenerator class.
FS.copySync( file.info.path, thisFilePath ); FS.copySync( file.info.path, thisFilePath );
} }
catch(ex) { catch(ex) {
console.log(ex); ex.showStack = true;
require('../core/error-handler').err( ex );
} }
} }
}); });
@ -274,8 +279,8 @@ Definition of the TemplateGenerator class.
theme ); theme );
} }
catch(ex) { catch(ex) {
console.log(ex); ex.showStack = true;
throw ex; require('../core/error-handler').err( ex );
} }
} }

View File

@ -50,7 +50,7 @@ Implementation of the 'generate' verb for HackMyResume.
// Check for invalid outputs // Check for invalid outputs
var inv = verifyOutputs( dst, theme ); var inv = verifyOutputs( dst, theme );
if( inv && inv.length ) { if( inv && inv.length ) {
throw { fluenterror: HACKMYSTATUS.invalidTarget, data: inv, theme: theme }; throw {fluenterror: HACKMYSTATUS.invalidTarget, data: inv, theme: theme};
} }
// Load input resumes... // Load input resumes...
@ -184,6 +184,7 @@ Implementation of the 'generate' verb for HackMyResume.
// If targInfo.fmt.files exists, this format is backed by a document. // If targInfo.fmt.files exists, this format is backed by a document.
// Fluent/FRESH themes are handled here. // Fluent/FRESH themes are handled here.
// TODO: Make FRESH and JRS themes render on the same path
if( targInfo.fmt.files && targInfo.fmt.files.length ) { if( targInfo.fmt.files && targInfo.fmt.files.length ) {
theFormat = _fmts.filter( theFormat = _fmts.filter(
function(fmt) { return fmt.name === targInfo.fmt.outFormat; })[0]; function(fmt) { return fmt.name === targInfo.fmt.outFormat; })[0];
@ -194,23 +195,23 @@ Implementation of the 'generate' verb for HackMyResume.
// Otherwise this is either a) a JSON Resume theme or b) an ad-hoc format // Otherwise this is either a) a JSON Resume theme or b) an ad-hoc format
// (JSON, YML, or PNG) that every theme gets "for free". // (JSON, YML, or PNG) that every theme gets "for free".
else { // else {
//
theFormat = _fmts.filter( function(fmt) { // theFormat = _fmts.filter( function(fmt) {
return fmt.name === targInfo.fmt.outFormat; // return fmt.name === targInfo.fmt.outFormat;
})[0]; // })[0];
//
var outFolder = PATH.dirname( f ); // var outFolder = PATH.dirname( f );
MKDIRP.sync( outFolder ); // Ensure dest folder exists; // MKDIRP.sync( outFolder ); // Ensure dest folder exists;
//
// JSON Resume themes have a 'render' method that needs to be called // // JSON Resume themes have a 'render' method that needs to be called
if( theme.render ) { // if( theme.render ) {
return renderJRSTheme( f, outFolder, theme ); // return renderJRSTheme( f, outFolder, theme );
} // }
else { // else {
return theFormat.gen.generate( rez, f, _opts ); // return theFormat.gen.generate( rez, f, _opts );
} // }
} // }
} }
catch( ex ) { catch( ex ) {
_err( ex ); _err( ex );
@ -219,49 +220,6 @@ Implementation of the 'generate' verb for HackMyResume.
/**
Render a JSON Resume theme. JSON Resume themes have an index.js that needs
to be called to perform the render. Additionally, we need to flow Markdown
styles to the JSON Resume (to the extent possible).
TODO: Refactor
*/
function renderJRSTheme( f, outFolder, theme ) {
var COPY = require('copy');
var globs = [ '*.css', '*.js', '*.png', '*.jpg', '*.gif', '*.bmp' ];
COPY.sync( globs , outFolder, {
cwd: theme.folder, nodir: true,
ignore: ['node_modules/','node_modules/**']
// rewrite: function(p1, p2) {
// return PATH.join(p2, p1);
// }
});
// Disable JRS theme chatter (console.log, console.error, etc.)
var off = ['log', 'error', 'dir'], org = off.map(function(c){
var ret = console[c]; console[c] = function(){}; return ret;
});
// Freeze and render
var rezHtml = theme.render( rez.harden() );
// Turn logging back on
off.forEach(function(c, idx){ console[c] = org[idx]; });
// Unfreeze and apply Markdown
rezHtml = rezHtml.replace( /@@@@~.*?~@@@@/gm, function(val){
return MDIN( val.replace( /~@@@@/gm,'' ).replace( /@@@@~/gm,'' ) );
});
// Save the file
FS.writeFileSync( f, rezHtml );
// Return markup to the client
return rezHtml;
}
/** /**
Ensure that user-specified outputs/targets are valid. Ensure that user-specified outputs/targets are valid.
*/ */