mirror of
https://github.com/JuanCanham/HackMyResume.git
synced 2024-11-22 00:10:15 +00:00
Improve CSS handling.
This commit is contained in:
parent
5b0ee89e34
commit
6b171e69db
@ -110,7 +110,7 @@ Definition of the `main` function.
|
|||||||
.alias('generate')
|
.alias('generate')
|
||||||
.option('-t --theme <theme>', 'Theme name or path')
|
.option('-t --theme <theme>', 'Theme name or path')
|
||||||
.option('-n --no-prettify', 'Disable HTML prettification', true)
|
.option('-n --no-prettify', 'Disable HTML prettification', true)
|
||||||
.option('-c --css <option>', 'CSS linking / embedding', 'embed')
|
.option('-c --css <option>', 'CSS linking / embedding')
|
||||||
.option('-p --pdf <engine>', 'PDF generation engine')
|
.option('-p --pdf <engine>', 'PDF generation engine')
|
||||||
.option('--no-sort', 'Sort resume sections by date', false)
|
.option('--no-sort', 'Sort resume sections by date', false)
|
||||||
.option('--no-tips', 'Disable theme tips and warnings.', false)
|
.option('--no-tips', 'Disable theme tips and warnings.', false)
|
||||||
|
@ -188,7 +188,7 @@ Definition of the FRESHTheme class.
|
|||||||
var idx = _.findIndex(fmts, function( fmt ) {
|
var idx = _.findIndex(fmts, function( fmt ) {
|
||||||
return fmt && fmt.pre === cssf.pre && fmt.ext === 'html';
|
return fmt && fmt.pre === cssf.pre && fmt.ext === 'html';
|
||||||
});
|
});
|
||||||
cssf.action = null;
|
cssf.major = false;
|
||||||
if( idx > -1) {
|
if( idx > -1) {
|
||||||
fmts[ idx ].css = cssf.data;
|
fmts[ idx ].css = cssf.data;
|
||||||
fmts[ idx ].cssPath = cssf.path;
|
fmts[ idx ].cssPath = cssf.path;
|
||||||
@ -202,11 +202,6 @@ Definition of the FRESHTheme class.
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Remove CSS files from the formats array
|
|
||||||
fmts = fmts.filter( function( fmt) {
|
|
||||||
return fmt && (fmt.ext !== 'css');
|
|
||||||
});
|
|
||||||
|
|
||||||
return formatsHash;
|
return formatsHash;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10,6 +10,7 @@ Definition of the HTMLGenerator class.
|
|||||||
, FS = require('fs-extra')
|
, FS = require('fs-extra')
|
||||||
, HTML = require( 'html' )
|
, HTML = require( 'html' )
|
||||||
, PATH = require('path');
|
, PATH = require('path');
|
||||||
|
require('string.prototype.endswith');
|
||||||
|
|
||||||
var HtmlGenerator = module.exports = TemplateGenerator.extend({
|
var HtmlGenerator = module.exports = TemplateGenerator.extend({
|
||||||
|
|
||||||
@ -22,6 +23,8 @@ Definition of the HTMLGenerator class.
|
|||||||
the HTML resume prior to saving.
|
the HTML resume prior to saving.
|
||||||
*/
|
*/
|
||||||
onBeforeSave: function( info ) {
|
onBeforeSave: function( info ) {
|
||||||
|
if( info.outputFile.endsWith('.css') )
|
||||||
|
return info.mk;
|
||||||
return this.opts.prettify ?
|
return this.opts.prettify ?
|
||||||
HTML.prettyPrint( info.mk, this.opts.prettify ) : info.mk;
|
HTML.prettyPrint( info.mk, this.opts.prettify ) : info.mk;
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,8 @@ Definition of the TemplateGenerator class. TODO: Refactor
|
|||||||
@module template-generator.js
|
@module template-generator.js
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
(function() {
|
(function() {
|
||||||
|
|
||||||
|
|
||||||
@ -22,7 +24,178 @@ Definition of the TemplateGenerator class. TODO: Refactor
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Default options.
|
/**
|
||||||
|
TemplateGenerator performs resume generation via local Handlebar or Underscore
|
||||||
|
style template expansion and is appropriate for text-based formats like HTML,
|
||||||
|
plain text, and XML versions of Microsoft Word, Excel, and OpenOffice.
|
||||||
|
@class TemplateGenerator
|
||||||
|
*/
|
||||||
|
var TemplateGenerator = module.exports = BaseGenerator.extend({
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/** Constructor. Set the output format and template format for this
|
||||||
|
generator. Will usually be called by a derived generator such as
|
||||||
|
HTMLGenerator or MarkdownGenerator. */
|
||||||
|
|
||||||
|
init: function( outputFormat, templateFormat, cssFile ){
|
||||||
|
this._super( outputFormat );
|
||||||
|
this.tplFormat = templateFormat || outputFormat;
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/** Generate a resume using string-based inputs and outputs without touching
|
||||||
|
the filesystem.
|
||||||
|
@method invoke
|
||||||
|
@param rez A FreshResume object.
|
||||||
|
@param opts Generator options.
|
||||||
|
@returns {Array} An array of objects representing the generated output
|
||||||
|
files. */
|
||||||
|
|
||||||
|
invoke: function( rez, opts ) {
|
||||||
|
|
||||||
|
opts = opts ?
|
||||||
|
(this.opts = EXTEND( true, { }, _defaultOpts, opts )) :
|
||||||
|
this.opts;
|
||||||
|
|
||||||
|
// Sort such that CSS files are processed before others
|
||||||
|
var curFmt = opts.themeObj.getFormat( this.format );
|
||||||
|
curFmt.files = _.sortBy( curFmt.files, function(fi) {
|
||||||
|
return fi.ext !== 'css';
|
||||||
|
});
|
||||||
|
|
||||||
|
// Run the transformation!
|
||||||
|
var results = curFmt.files.map( function( tplInfo, idx ) {
|
||||||
|
var trx = this.single( rez, tplInfo.data, this.format, opts, opts.themeObj, curFmt );
|
||||||
|
if( tplInfo.ext === 'css' ) { curFmt.files[idx].data = trx; }
|
||||||
|
else if( tplInfo.ext === 'html' ) {
|
||||||
|
//tplInfo.css contains the CSS data loaded by theme
|
||||||
|
//tplInfo.cssPath contains the absolute path to the source CSS File
|
||||||
|
}
|
||||||
|
return { info: tplInfo, data: trx };
|
||||||
|
}, this);
|
||||||
|
|
||||||
|
return {
|
||||||
|
files: results
|
||||||
|
};
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/** Generate a resume using file-based inputs and outputs. Requires access
|
||||||
|
to the local filesystem.
|
||||||
|
@method generate
|
||||||
|
@param rez A FreshResume object.
|
||||||
|
@param f Full path to the output resume file to generate.
|
||||||
|
@param opts Generator options. */
|
||||||
|
|
||||||
|
generate: function( rez, f, opts ) {
|
||||||
|
|
||||||
|
// Prepare
|
||||||
|
this.opts = EXTEND( true, { }, _defaultOpts, opts );
|
||||||
|
|
||||||
|
// Call the string-based generation method to perform the generation.
|
||||||
|
var genInfo = this.invoke( rez, null );
|
||||||
|
|
||||||
|
var outFolder = parsePath( f ).dirname;
|
||||||
|
var curFmt = opts.themeObj.getFormat( this.format );
|
||||||
|
|
||||||
|
// Process individual files within this format. For example, the HTML
|
||||||
|
// output format for a theme may have multiple HTML files, CSS files,
|
||||||
|
// etc. Process them here.
|
||||||
|
genInfo.files.forEach(function( file ){
|
||||||
|
|
||||||
|
// Pre-processing
|
||||||
|
var thisFilePath = PATH.join( outFolder, file.info.orgPath );
|
||||||
|
if( this.onBeforeSave ) {
|
||||||
|
file.data = this.onBeforeSave({
|
||||||
|
theme: opts.themeObj,
|
||||||
|
outputFile: (file.info.major ? f : thisFilePath),
|
||||||
|
mk: file.data,
|
||||||
|
opts: this.opts
|
||||||
|
});
|
||||||
|
if( !file.data ) return; // PDF etc
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write the file
|
||||||
|
var fileName = file.info.major ? f : thisFilePath;
|
||||||
|
MKDIRP.sync( PATH.dirname( fileName ) );
|
||||||
|
FS.writeFileSync( fileName, file.data,
|
||||||
|
{ encoding: 'utf8', flags: 'w' } );
|
||||||
|
|
||||||
|
// Post-processing
|
||||||
|
this.onAfterSave && this.onAfterSave(
|
||||||
|
{ outputFile: fileName, mk: file.data, opts: this.opts } );
|
||||||
|
|
||||||
|
}, this);
|
||||||
|
|
||||||
|
// Some themes require a symlink structure. If so, create it.
|
||||||
|
if( curFmt.symLinks ) {
|
||||||
|
Object.keys( curFmt.symLinks ).forEach( function(loc) {
|
||||||
|
var absLoc = PATH.join(outFolder, loc);
|
||||||
|
var absTarg = PATH.join(PATH.dirname(absLoc), curFmt.symLinks[loc]);
|
||||||
|
// 'file', 'dir', or 'junction' (Windows only)
|
||||||
|
var type = parsePath( absLoc ).extname ? 'file' : 'junction';
|
||||||
|
FS.symlinkSync( absTarg, absLoc, type);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return genInfo;
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/** Perform a single resume resume transformation using string-based inputs
|
||||||
|
and outputs without touching the local file system.
|
||||||
|
@param json A FRESH or JRS resume object.
|
||||||
|
@param jst The stringified template data
|
||||||
|
@param format The format name, such as "html" or "latex"
|
||||||
|
@param cssInfo Needs to be refactored.
|
||||||
|
@param opts Options and passthrough data. */
|
||||||
|
|
||||||
|
single: function( json, jst, format, opts, theme, curFmt ) {
|
||||||
|
this.opts.freezeBreaks && ( jst = freeze(jst) );
|
||||||
|
|
||||||
|
var eng = require( '../renderers/' + theme.engine + '-generator' );
|
||||||
|
var result = eng.generate( json, jst, format, curFmt, opts, theme );
|
||||||
|
|
||||||
|
this.opts.freezeBreaks && ( result = unfreeze(result) );
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/** 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' );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/** Default template generator options. */
|
||||||
var _defaultOpts = {
|
var _defaultOpts = {
|
||||||
engine: 'underscore',
|
engine: 'underscore',
|
||||||
keepBreaks: true,
|
keepBreaks: true,
|
||||||
@ -57,250 +230,7 @@ Definition of the TemplateGenerator class. TODO: Refactor
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/** Regexes for linebreak preservation. */
|
||||||
TemplateGenerator performs resume generation via local Handlebar or Underscore
|
|
||||||
style template expansion and is appropriate for text-based formats like HTML,
|
|
||||||
plain text, and XML versions of Microsoft Word, Excel, and OpenOffice.
|
|
||||||
@class TemplateGenerator
|
|
||||||
*/
|
|
||||||
var TemplateGenerator = module.exports = BaseGenerator.extend({
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
init: function( outputFormat, templateFormat, cssFile ){
|
|
||||||
this._super( outputFormat );
|
|
||||||
this.tplFormat = templateFormat || outputFormat;
|
|
||||||
},
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
String-based template generation method.
|
|
||||||
@method invoke
|
|
||||||
@param rez A FreshResume object.
|
|
||||||
@param opts Generator options.
|
|
||||||
@returns {Array} An array of objects representing the generated output
|
|
||||||
files. Each object has this format:
|
|
||||||
|
|
||||||
{
|
|
||||||
files: [ { info: { }, data: [ ] }, { ... } ],
|
|
||||||
themeInfo: { }
|
|
||||||
}
|
|
||||||
|
|
||||||
*/
|
|
||||||
invoke: function( rez, opts ) {
|
|
||||||
|
|
||||||
// Carry over options
|
|
||||||
this.opts = EXTEND( true, { }, _defaultOpts, opts );
|
|
||||||
|
|
||||||
// Load the theme
|
|
||||||
var themeInfo = themeFromMoniker.call( this );
|
|
||||||
var theme = themeInfo.theme;
|
|
||||||
var tFolder = themeInfo.folder;
|
|
||||||
var tplFolder = PATH.join( tFolder, 'src' );
|
|
||||||
var curFmt = theme.getFormat( this.format );
|
|
||||||
var that = this;
|
|
||||||
|
|
||||||
// "Generate": process individual files within the theme
|
|
||||||
// The transform() method catches exceptions internally
|
|
||||||
return {
|
|
||||||
files: curFmt.files.map( function( tplInfo ) {
|
|
||||||
return {
|
|
||||||
info: tplInfo,
|
|
||||||
data: tplInfo.action === 'transform' ?
|
|
||||||
transform.call( that, rez, tplInfo, theme, opts ) : undefined
|
|
||||||
};
|
|
||||||
}).filter(function(item){ return item !== null; }),
|
|
||||||
themeInfo: themeInfo
|
|
||||||
};
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
File-based template generation method.
|
|
||||||
@method generate
|
|
||||||
@param rez A FreshResume object.
|
|
||||||
@param f Full path to the output resume file to generate.
|
|
||||||
@param opts Generator options.
|
|
||||||
*/
|
|
||||||
generate: function( rez, f, opts ) {
|
|
||||||
|
|
||||||
// Call the generation method
|
|
||||||
var genInfo = this.invoke( rez, opts );
|
|
||||||
|
|
||||||
// Carry over options
|
|
||||||
this.opts = EXTEND( true, { }, _defaultOpts, opts );
|
|
||||||
|
|
||||||
// Load the theme
|
|
||||||
var themeInfo = genInfo.themeInfo;
|
|
||||||
var theme = themeInfo.theme;
|
|
||||||
var tFolder = themeInfo.folder;
|
|
||||||
var tplFolder = PATH.join( tFolder, 'src' );
|
|
||||||
var outFolder = parsePath(f).dirname;
|
|
||||||
var curFmt = theme.getFormat( this.format );
|
|
||||||
var that = this;
|
|
||||||
|
|
||||||
// "Generate": process individual files within the theme
|
|
||||||
// TODO: refactor
|
|
||||||
genInfo.files.forEach(function( file ){
|
|
||||||
|
|
||||||
var thisFilePath;
|
|
||||||
|
|
||||||
if( theme.engine === 'jrs' ) {
|
|
||||||
file.info.orgPath = '';
|
|
||||||
}
|
|
||||||
|
|
||||||
if( file.info.action === 'transform' ) {
|
|
||||||
thisFilePath = PATH.join( outFolder, file.info.orgPath );
|
|
||||||
if( that.onBeforeSave ) {
|
|
||||||
file.data = that.onBeforeSave({
|
|
||||||
theme: theme,
|
|
||||||
outputFile: (file.info.major ? f : thisFilePath),
|
|
||||||
mk: file.data,
|
|
||||||
opts: that.opts
|
|
||||||
});
|
|
||||||
if( !file.data ) return; // PDF etc
|
|
||||||
}
|
|
||||||
var fileName = file.info.major ? f : thisFilePath;
|
|
||||||
MKDIRP.sync( PATH.dirname( fileName ) );
|
|
||||||
FS.writeFileSync( fileName, file.data,
|
|
||||||
{ encoding: 'utf8', flags: 'w' } );
|
|
||||||
that.onAfterSave && that.onAfterSave(
|
|
||||||
{ outputFile: fileName, mk: file.data, opts: that.opts } );
|
|
||||||
}
|
|
||||||
else if( file.info.action === null/* && theme.explicit*/ ) {
|
|
||||||
thisFilePath = PATH.join( outFolder, file.info.orgPath );
|
|
||||||
MKDIRP.sync( PATH.dirname(thisFilePath) );
|
|
||||||
FS.copySync( file.info.path, thisFilePath );
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Some themes require a symlink structure. If so, create it.
|
|
||||||
if( curFmt.symLinks ) {
|
|
||||||
Object.keys( curFmt.symLinks ).forEach( function(loc) {
|
|
||||||
var absLoc = PATH.join(outFolder, loc);
|
|
||||||
var absTarg = PATH.join(PATH.dirname(absLoc), curFmt.symLinks[loc]);
|
|
||||||
// 'file', 'dir', or 'junction' (Windows only)
|
|
||||||
var type = parsePath( absLoc ).extname ? 'file' : 'junction';
|
|
||||||
FS.symlinkSync( absTarg, absLoc, type);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return genInfo;
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
Perform a single resume JSON-to-DEST resume transformation.
|
|
||||||
@param json A FRESH or JRS resume object.
|
|
||||||
@param jst The stringified template data
|
|
||||||
@param format The format name, such as "html" or "latex"
|
|
||||||
@param cssInfo Needs to be refactored.
|
|
||||||
@param opts Options and passthrough data.
|
|
||||||
*/
|
|
||||||
single: function( json, jst, format, cssInfo, opts, theme ) {
|
|
||||||
this.opts.freezeBreaks && ( jst = freeze(jst) );
|
|
||||||
|
|
||||||
var eng = require( '../renderers/' + theme.engine + '-generator' );
|
|
||||||
var result = eng.generate( json, jst, format, cssInfo, opts, theme );
|
|
||||||
|
|
||||||
this.opts.freezeBreaks && ( result = unfreeze(result) );
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
Export the TemplateGenerator function/ctor.
|
|
||||||
*/
|
|
||||||
module.exports = TemplateGenerator;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
Given a theme title, load the corresponding theme.
|
|
||||||
*/
|
|
||||||
function themeFromMoniker() {
|
|
||||||
|
|
||||||
// Verify the specified theme name/path
|
|
||||||
var tFolder = PATH.join(
|
|
||||||
parsePath( require.resolve('fresh-themes') ).dirname,
|
|
||||||
'/themes/',
|
|
||||||
this.opts.theme
|
|
||||||
);
|
|
||||||
|
|
||||||
var t;
|
|
||||||
if( this.opts.theme.startsWith('jsonresume-theme-') ) {
|
|
||||||
t = new JRSTheme().open( tFolder );
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
var exists = require('path-exists').sync;
|
|
||||||
if( !exists( tFolder ) ) {
|
|
||||||
tFolder = PATH.resolve( this.opts.theme );
|
|
||||||
if( !exists( tFolder ) ) {
|
|
||||||
throw { fluenterror: this.codes.themeNotFound, data: this.opts.theme};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
t = this.opts.themeObj || new FRESHTheme().open( tFolder );
|
|
||||||
}
|
|
||||||
|
|
||||||
// Load the theme and format
|
|
||||||
return {
|
|
||||||
theme: t,
|
|
||||||
folder: tFolder
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
function transform( rez, tplInfo, theme, opts ) {
|
|
||||||
try {
|
|
||||||
var cssInfo = {
|
|
||||||
file: tplInfo.css ? tplInfo.cssPath : null,
|
|
||||||
data: tplInfo.css || null
|
|
||||||
};
|
|
||||||
return this.single( rez, tplInfo.data, this.format, cssInfo, this.opts,
|
|
||||||
theme );
|
|
||||||
}
|
|
||||||
catch(ex) {
|
|
||||||
if( opts.errHandler ) opts.errHandler(ex);
|
|
||||||
else throw ex;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
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 = {
|
var _reg = {
|
||||||
regN: new RegExp( '\n', 'g' ),
|
regN: new RegExp( '\n', 'g' ),
|
||||||
regR: new RegExp( '\r', 'g' ),
|
regR: new RegExp( '\r', 'g' ),
|
||||||
|
@ -13,7 +13,10 @@ Generic template helper definitions for HackMyResume / FluentCV.
|
|||||||
, FluentDate = require('../core/fluent-date')
|
, FluentDate = require('../core/fluent-date')
|
||||||
, HMSTATUS = require('../core/status-codes')
|
, HMSTATUS = require('../core/status-codes')
|
||||||
, moment = require('moment')
|
, moment = require('moment')
|
||||||
|
, FS = require('fs')
|
||||||
, LO = require('lodash')
|
, LO = require('lodash')
|
||||||
|
, PATH = require('path')
|
||||||
|
, printf = require('printf')
|
||||||
, _ = require('underscore')
|
, _ = require('underscore')
|
||||||
, unused = require('../utils/string');
|
, unused = require('../utils/string');
|
||||||
|
|
||||||
@ -74,6 +77,21 @@ Generic template helper definitions for HackMyResume / FluentCV.
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
fontFace: function( styleName ) {
|
||||||
|
var ret = '';
|
||||||
|
var fontSpec = GenericHelpers.theme.fonts[ styleName ];
|
||||||
|
if( _.isArray( fontSpec ) ) {
|
||||||
|
fontSpec = fontSpec.map( function(ff) {
|
||||||
|
return "'" + ff + "'";
|
||||||
|
});
|
||||||
|
ret = fontSpec.join(', ');
|
||||||
|
}
|
||||||
|
else if( _.isString( fontSpec )) {
|
||||||
|
ret = fontSpec;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Capitalize the first letter of the word.
|
Capitalize the first letter of the word.
|
||||||
@method section
|
@method section
|
||||||
@ -218,21 +236,46 @@ Generic template helper definitions for HackMyResume / FluentCV.
|
|||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Conditional stylesheet link. Either display the link or embed the stylesheet
|
Conditional stylesheet link. Creates a link to the specified stylesheet with
|
||||||
via <style></style> tag.
|
<link> or embeds the styles inline with <style></style>, depending on the
|
||||||
|
theme author's and user's preferences.
|
||||||
|
@param url {String} The path to the CSS file.
|
||||||
|
@param linkage {String} The default link method. Can be either `embed` or
|
||||||
|
`link`. If omitted, defaults to `embed`. Can be overridden by the `--css`
|
||||||
|
command-line switch.
|
||||||
*/
|
*/
|
||||||
styleSheet: function( file, options ) {
|
|
||||||
var styles = ( this.opts.css === 'link') ?
|
styleSheet: function( url, linkage ) {
|
||||||
'<link href="' + file + '" rel="stylesheet" type="text/css">' :
|
|
||||||
'<style>' + this.cssInfo.data + '</style>';
|
// Establish the linkage style
|
||||||
|
linkage = this.opts.css || linkage || 'embed';
|
||||||
|
|
||||||
|
// Create the <link> or <style> tag
|
||||||
|
var ret = '';
|
||||||
|
if( linkage === 'link' ) {
|
||||||
|
ret = printf('<link href="%s" rel="stylesheet" type="text/css">', url);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
var rawCss = FS.readFileSync(
|
||||||
|
PATH.join( this.opts.themeObj.folder, '/src/', url ), 'utf8' );
|
||||||
|
var renderedCss = this.engine.generateSimple( this, rawCss );
|
||||||
|
ret = printf('<style>%s</style>', renderedCss );
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the currently-executing template is inherited, append styles
|
||||||
if( this.opts.themeObj.inherits &&
|
if( this.opts.themeObj.inherits &&
|
||||||
this.opts.themeObj.inherits.html &&
|
this.opts.themeObj.inherits.html &&
|
||||||
this.format === 'html' ) {
|
this.format === 'html' ) {
|
||||||
styles += (this.opts.css === 'link') ?
|
ret += (linkage === 'link') ?
|
||||||
'<link href="' + this.opts.themeObj.overrides.path + '" rel="stylesheet" type="text/css">' :
|
'<link href="' + this.opts.themeObj.overrides.path +
|
||||||
|
'" rel="stylesheet" type="text/css">' :
|
||||||
'<style>' + this.opts.themeObj.overrides.data + '</style>';
|
'<style>' + this.opts.themeObj.overrides.data + '</style>';
|
||||||
}
|
}
|
||||||
return styles;
|
|
||||||
|
// TODO: It would be nice to use Handlebar.SafeString here, but these
|
||||||
|
// are supposed to be generic helpers. Provide an equivalent, or expose
|
||||||
|
// it when Handlebars is the chosen engine, which is most of the time.
|
||||||
|
return ret;
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/**
|
/**
|
||||||
Definition of the HandlebarsGenerator class.
|
Definition of the HandlebarsGenerator class.
|
||||||
@license MIT. See LICENSE.md for details.
|
@license MIT. See LICENSE.md for details.
|
||||||
@module handlebars-generator.js
|
@module renderers/handlebars-generator
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
@ -30,29 +30,12 @@ Definition of the HandlebarsGenerator class.
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
generate: function( json, jst, format, cssInfo, opts, theme ) {
|
generateSimple: function( data, tpl ) {
|
||||||
|
|
||||||
registerPartials( format, theme );
|
|
||||||
registerHelpers( theme, opts );
|
|
||||||
|
|
||||||
// Preprocess text
|
|
||||||
var encData = json;
|
|
||||||
( format === 'html' || format === 'pdf' ) && (encData = json.markdownify());
|
|
||||||
( format === 'doc' ) && (encData = json.xmlify());
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Compile and run the Handlebars template.
|
// Compile and run the Handlebars template.
|
||||||
var template = HANDLEBARS.compile(jst, { strict: false, assumeObjects: false });
|
var template = HANDLEBARS.compile( tpl, { strict: false, assumeObjects: false } );
|
||||||
return template({ // TODO: Clean
|
return template( data );
|
||||||
r: encData,
|
|
||||||
RAW: json,
|
|
||||||
filt: opts.filters,
|
|
||||||
cssInfo: cssInfo,
|
|
||||||
format: format,
|
|
||||||
opts: opts,
|
|
||||||
headFragment: opts.headFragment || ''
|
|
||||||
});
|
|
||||||
|
|
||||||
}
|
}
|
||||||
catch( ex ) {
|
catch( ex ) {
|
||||||
throw {
|
throw {
|
||||||
@ -62,6 +45,35 @@ Definition of the HandlebarsGenerator class.
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
generate: function( json, jst, format, curFmt, opts, theme ) {
|
||||||
|
|
||||||
|
// Set up partials and helpers
|
||||||
|
registerPartials( format, theme );
|
||||||
|
registerHelpers( theme, opts );
|
||||||
|
|
||||||
|
// Preprocess text
|
||||||
|
var encData = json;
|
||||||
|
( format === 'html' || format === 'pdf' ) && (encData = json.markdownify());
|
||||||
|
( format === 'doc' ) && (encData = json.xmlify());
|
||||||
|
|
||||||
|
// Set up the context
|
||||||
|
var ctx = {
|
||||||
|
r: encData,
|
||||||
|
RAW: json,
|
||||||
|
filt: opts.filters,
|
||||||
|
format: format,
|
||||||
|
opts: opts,
|
||||||
|
engine: this,
|
||||||
|
results: curFmt.files,
|
||||||
|
headFragment: opts.headFragment || ''
|
||||||
|
};
|
||||||
|
|
||||||
|
// Render the template
|
||||||
|
return this.generateSimple( ctx, jst );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -79,7 +79,7 @@ Implementation of the 'build' verb for HackMyResume.
|
|||||||
// Load the theme...
|
// Load the theme...
|
||||||
this.stat( HMEVENT.beforeTheme, { theme: _opts.theme });
|
this.stat( HMEVENT.beforeTheme, { theme: _opts.theme });
|
||||||
var tFolder = verifyTheme.call( this, _opts.theme );
|
var tFolder = verifyTheme.call( this, _opts.theme );
|
||||||
var theme = loadTheme( tFolder );
|
var theme = _opts.themeObj = loadTheme( tFolder );
|
||||||
this.stat( HMEVENT.afterTheme, { theme: theme });
|
this.stat( HMEVENT.afterTheme, { theme: theme });
|
||||||
|
|
||||||
// Check for invalid outputs...
|
// Check for invalid outputs...
|
||||||
@ -144,7 +144,7 @@ Implementation of the 'build' verb for HackMyResume.
|
|||||||
// Cherry-pick options //_opts = extend( true, _opts, opts );
|
// Cherry-pick options //_opts = extend( true, _opts, opts );
|
||||||
_opts.theme = (opts.theme && opts.theme.toLowerCase().trim()) || 'modern';
|
_opts.theme = (opts.theme && opts.theme.toLowerCase().trim()) || 'modern';
|
||||||
_opts.prettify = opts.prettify === true;
|
_opts.prettify = opts.prettify === true;
|
||||||
_opts.css = opts.css || 'embed';
|
_opts.css = opts.css;
|
||||||
_opts.pdf = opts.pdf;
|
_opts.pdf = opts.pdf;
|
||||||
_opts.wrap = opts.wrap || 60;
|
_opts.wrap = opts.wrap || 60;
|
||||||
_opts.stitles = opts.sectionTitles;
|
_opts.stitles = opts.sectionTitles;
|
||||||
|
Loading…
Reference in New Issue
Block a user