From 5a716dff164da7d2b56f37a1ad264d1bff9a6186 Mon Sep 17 00:00:00 2001 From: devlinjd Date: Mon, 7 Dec 2015 16:39:59 -0500 Subject: [PATCH] Add basic multiplexing support. --- src/core/theme.js | 114 +++++++++++++++++++++++--------- src/eng/underscore-generator.js | 28 +++++--- src/fluentcmd.js | 16 ++--- src/gen/latex-generator.js | 2 +- 4 files changed, 112 insertions(+), 48 deletions(-) diff --git a/src/core/theme.js b/src/core/theme.js index 6657c61..57565b3 100644 --- a/src/core/theme.js +++ b/src/core/theme.js @@ -27,26 +27,62 @@ Abstract theme representation. */ Theme.prototype.open = function( themeFolder ) { - function friendlyName( val ) { - val = val.trim().toLowerCase(); - var friendly = { yml: 'yaml', md: 'markdown', txt: 'text' }; - return friendly[val] || val; - } - // Open the [theme-name].json file; should have the same name as folder this.folder = themeFolder; var pathInfo = PATH.parse( themeFolder ); var themeFile = PATH.join( themeFolder, pathInfo.base + '.json' ); var themeInfo = JSON.parse( FS.readFileSync( themeFile, 'utf8' ) ); + var that = this; // Move properties from the theme JSON file to the theme object EXTEND( true, this, themeInfo ); + // Set up a formats has for the theme + var formatsHash = { }; + + // Check for an explicit "formats" entry in the theme JSON. If it has one, + // then this theme declares its files explicitly. + if( !!this.formats ) { + formatsHash = loadExplicit.call( this ); + } + else { + formatsHash = loadImplicit.call( this ); + } + + // Add freebie formats every theme gets + formatsHash[ 'json' ] = { title: 'json', outFormat: 'json', pre: 'json', ext: 'json', path: null, data: null }; + formatsHash[ 'yml' ] = { title: 'yaml', outFormat: 'yml', pre: 'yml', ext: 'yml', path: null, data: null }; + + // Cache + this.formats = formatsHash; + + // Set the official theme name + this.name = PATH.parse( this.folder ).name; + + return this; + }; + + /** + Determine if the theme supports the specified output format. + */ + Theme.prototype.hasFormat = function( fmt ) { + return _.has( this.formats, fmt ); + }; + + /** + Determine if the theme supports the specified output format. + */ + Theme.prototype.getFormat = function( fmt ) { + return this.formats[ fmt ]; + }; + + function loadImplicit() { + // Set up a hash of formats supported by this theme. var formatsHash = { }; // Establish the base theme folder - var tplFolder = PATH.join( themeFolder, 'src' ); + var tplFolder = PATH.join( this.folder, 'src' ); // Iterate over all files in the theme folder, producing an array, fmts, // containing info for each file. While we're doing that, also build up @@ -73,7 +109,8 @@ Abstract theme representation. } // We should have a valid output format now. - formatsHash[ outFmt ] = formatsHash[outFmt] || { outFormat: outFmt, files: [] }; + formatsHash[ outFmt ] = + formatsHash[outFmt] || { outFormat: outFmt, files: [] }; // Create the file representation object. var obj = { @@ -91,10 +128,6 @@ Abstract theme representation. return obj; }); - // Add freebie formats every theme gets - formatsHash[ 'json' ] = { title: 'json', outFormat: 'json', pre: 'json', ext: 'json', path: null, data: null }; - formatsHash[ 'yml' ] = { title: 'yaml', outFormat: 'yml', pre: 'yml', ext: 'yml', path: null, data: null }; - // Now, get all the CSS files... (this.cssFiles = fmts.filter(function( fmt ){ return fmt.ext === 'css'; })) .forEach(function( cssf ) { @@ -111,28 +144,49 @@ Abstract theme representation. return fmt.ext !== 'css'; }); - // Cache the formats hash - this.formats = formatsHash; + return formatsHash; + } - // Set the official theme name - this.name = PATH.parse( themeFolder ).name; + function loadExplicit() { - return this; - }; + var formatsHash = { }; + var that = this; - /** - Determine if the theme supports the specified output format. - */ - Theme.prototype.hasFormat = function( fmt ) { - return _.has( this.formats, fmt ); - }; + // Establish the base theme folder + var tplFolder = this.folder;//PATH.join( this.folder, 'src' ); - /** - Determine if the theme supports the specified output format. - */ - Theme.prototype.getFormat = function( fmt ) { - return this.formats[ fmt ]; - }; + // Iterate over all keys in the "formats" section of the theme JSON file. + // Each key will be a format (html, latex, pdf, etc) with some data. + Object.keys( this.formats ).forEach( function( k ) { + + formatsHash[ k ] = { + outFormat: k, + files: that.formats[ k ].files.map(function(fi){ + + var absPath = PATH.join( tplFolder, fi ); + var pathInfo = PATH.parse( absPath ); + + + return { + path: absPath, + ext: pathInfo.ext.slice(1), + title: friendlyName( k ), + pre: k, + outFormat: k, + data: FS.readFileSync( absPath, 'utf8' ), + css: null + }; + }) + }; + }); + return formatsHash; + } + + function friendlyName( val ) { + val = val.trim().toLowerCase(); + var friendly = { yml: 'yaml', md: 'markdown', txt: 'text' }; + return friendly[val] || val; + } module.exports = Theme; diff --git a/src/eng/underscore-generator.js b/src/eng/underscore-generator.js index f744153..a8102db 100644 --- a/src/eng/underscore-generator.js +++ b/src/eng/underscore-generator.js @@ -10,27 +10,37 @@ Underscore template generate for FluentCV. module.exports = function( json, jst, format, cssInfo, opts ) { // Tweak underscore's default template delimeters - _.templateSettings = opts.template; + var delims = opts.themeObj.delimeters || opts.template; + if( opts.themeObj.delimeters ) { + delims = _.mapObject( delims, function(val,key) { + return new RegExp( val, "ig") + }); + } + _.templateSettings = delims; // Convert {{ someVar }} to {% print(filt.out(someVar) %} // Convert {{ someVar|someFilter }} to {% print(filt.someFilter(someVar) %} - jst = jst.replace( _.templateSettings.interpolate, function replace(m, p1) { + jst = jst.replace( delims.interpolate, function replace(m, p1) { if( p1.indexOf('|') > -1 ) { var terms = p1.split('|'); - return '{% print( filt.' + terms[1] + '( ' + terms[0] + ' )) %}'; + return '[~ print( filt.' + terms[1] + '( ' + terms[0] + ' )) ]]'; } else { - return '{% print( filt.out(' + p1 + ') ) %}'; + return '[~ print( filt.out(' + p1 + ') ) ]]'; } }); // Strip {# comments #} - jst = jst.replace( _.templateSettings.comment, ''); - + jst = jst.replace( delims.comment, ''); // Compile and run the template. TODO: avoid unnecessary recompiles. - jst = _.template(jst)({ r: json, filt: opts.filters, cssInfo: cssInfo, headFragment: opts.headFragment || '' }); - - return jst; + var compiled = _.template(jst); + var ret = compiled({ + r: json, + filt: opts.filters, + cssInfo: cssInfo, + headFragment: opts.headFragment || '' + }); + return ret; }; diff --git a/src/fluentcmd.js b/src/fluentcmd.js index 0c03a63..5063911 100644 --- a/src/fluentcmd.js +++ b/src/fluentcmd.js @@ -93,21 +93,21 @@ module.exports = function () { @param f Full path to the destination resume to generate, for example, "/foo/bar/resume.pdf" or "c:\foo\bar\resume.txt". */ - function single( fi, theme ) { + function single( targetInfo, theme ) { try { - var f = fi.file, fType = fi.fmt.outFormat, fName = path.basename(f,'.'+fType); + var f = targetInfo.file, fType = targetInfo.fmt.outFormat, fName = path.basename(f,'.'+fType); - if( fi.fmt.files && fi.fmt.files.length ) { - fi.fmt.files.forEach( function( form ) { + if( targetInfo.fmt.files && targetInfo.fmt.files.length ) { + targetInfo.fmt.files.forEach( function( form ) { if( form.ext === 'css' ) return; - _log( 'Generating '.useful + form.title.toUpperCase().useful.bold + ' resume: '.useful + + _log( 'Generating '.useful + targetInfo.fmt.outFormat.toUpperCase().useful.bold + ' resume: '.useful + path.relative(process.cwd(), f ).useful.bold ); var theFormat = _fmts.filter( - function( fmt ) { return fmt.name === form.pre; })[0]; + function( fmt ) { return fmt.name === targetInfo.fmt.outFormat; })[0]; MKDIRP.sync( path.dirname( f ) ); // Ensure dest folder exists; theFormat.gen.generate( rez, f, _opts ); @@ -115,11 +115,11 @@ module.exports = function () { }); } else { - _log( 'Generating '.useful + fi.fmt.outFormat.toUpperCase().useful.bold + ' resume: '.useful + + _log( 'Generating '.useful + targetInfo.fmt.outFormat.toUpperCase().useful.bold + ' resume: '.useful + path.relative(process.cwd(), f ).useful.bold ); var theFormat = _fmts.filter( - function( fmt ) { return fmt.name === fi.fmt.outFormat; })[0]; + function( fmt ) { return fmt.name === targetInfo.fmt.outFormat; })[0]; MKDIRP.sync( path.dirname( f ) ); // Ensure dest folder exists; theFormat.gen.generate( rez, f, _opts ); } diff --git a/src/gen/latex-generator.js b/src/gen/latex-generator.js index 43b6b67..1e32315 100644 --- a/src/gen/latex-generator.js +++ b/src/gen/latex-generator.js @@ -11,7 +11,7 @@ LaTeXGenerator generates a LaTeX resume via TemplateGenerator. var LaTeXGenerator = module.exports = TemplateGenerator.extend({ init: function(){ - this._super( 'tex', 'tex' ); + this._super( 'latex', 'tex' ); } });