diff --git a/src/cli/error.js b/src/cli/error.js index e76cb08..e592c42 100644 --- a/src/cli/error.js +++ b/src/cli/error.js @@ -198,7 +198,7 @@ Error-handling routines for HackMyResume. case HMSTATUS.invalidHelperUse: msg = printf( M2C( this.msgs.invalidHelperUse.msg ), ex.helper ); quit = false; - etype = 'error'; + etype = 'warning'; break; case HMSTATUS.notOnPath: @@ -226,10 +226,18 @@ Error-handling routines for HackMyResume. break; case HMSTATUS.compileTemplate: - //msg = printf( M2C( this.msgs.compileTemplate.msg ), ex.inner); etype = 'error'; break; + case HMSTATUS.themeLoad: + msg = M2C( printf( this.msgs.themeLoad.msg, ex.attempted.toUpperCase() ), 'red'); + if( ex.inner && ex.inner.fluenterror ) { + msg += M2C('\nError: ', 'red') + assembleError.call( this, ex.inner ).msg; + } + quit = true; + etype = 'custom'; + break; + case HMSTATUS.parseError: if( SyntaxErrorEx.is( ex.inner )) { console.error( printf( M2C(this.msgs.readError.msg, 'red'), ex.file ) ); diff --git a/src/cli/main.js b/src/cli/main.js index 5db46a3..0e4f1c0 100644 --- a/src/cli/main.js +++ b/src/cli/main.js @@ -238,6 +238,7 @@ Definition of the `main` function. var hand = require( './error' ); hand.init( _opts.debug, _opts.assert, _opts.silent ); var v = new HMR.verbs[ this.name() ](); + _opts.errHandler = v; _out.init( _opts ); v.on( 'hmr:status', function() { _out.do.apply( _out, arguments ); }); v.on( 'hmr:error', function() { diff --git a/src/cli/msg.yml b/src/cli/msg.yml index e55e808..029b668 100644 --- a/src/cli/msg.yml +++ b/src/cli/msg.yml @@ -81,7 +81,7 @@ errors: parseError: msg: Invalid or corrupt JSON on line %s column %s. invalidHelperUse: - msg: Invalid use of the **%s** theme helper. + msg: Warning: Invalid use of the **%s** theme helper. fileSaveError: msg: An error occurred while writing %s to disk: %s. mixedMerge: @@ -90,3 +90,5 @@ errors: msg: "An error occurred during template invocation." compileTemplate: msg: "An error occurred during template compilation." + themeLoad: + msg: "Applying **%s** theme (? formats)" diff --git a/src/cli/out.js b/src/cli/out.js index 58ff0c5..797463e 100644 --- a/src/cli/out.js +++ b/src/cli/out.js @@ -107,7 +107,7 @@ Output routines for HackMyResume. case HME.applyTheme: this.theme = evt.theme; var numFormats = Object.keys( evt.theme.formats ).length; - L( M2C(this.msgs.applyTheme.msg, 'green'), + L( M2C(this.msgs.applyTheme.msg, evt.status === 'error' ? 'red' : 'green'), evt.theme.name.toUpperCase(), numFormats, ( numFormats === 1 ? '' : 's') ); break; diff --git a/src/core/fresh-theme.js b/src/core/fresh-theme.js index 68b300c..994cae2 100644 --- a/src/core/fresh-theme.js +++ b/src/core/fresh-theme.js @@ -15,7 +15,9 @@ Definition of the FRESHTheme class. , parsePath = require('parse-filepath') , pathExists = require('path-exists').sync , EXTEND = require('extend') + , HMSTATUS = require('./status-codes') , moment = require('moment') + , loadSafeJson = require('../utils/safe-json-loader') , READFILES = require('recursive-readdir-sync'); @@ -46,11 +48,17 @@ Definition of the FRESHTheme class. // Load the theme var themeFile = PATH.join( themeFolder, 'theme.json' ); - var themeInfo = JSON.parse( FS.readFileSync( themeFile, 'utf8' ) ); + var themeInfo = loadSafeJson( themeFile ); + if( themeInfo.ex ) throw { + fluenterror: themeInfo.ex.operation === 'parse' ? + HMSTATUS.parseError : HMSTATUS.readError, + inner: themeInfo.ex.inner + }; + var that = this; // Move properties from the theme JSON file to the theme object - EXTEND( true, this, themeInfo ); + EXTEND( true, this, themeInfo.json ); // Check for an "inherits" entry in the theme JSON. if( this.inherits ) { diff --git a/src/core/status-codes.js b/src/core/status-codes.js index 302d1d3..f398dcb 100644 --- a/src/core/status-codes.js +++ b/src/core/status-codes.js @@ -28,7 +28,8 @@ Status codes for HackMyResume. invalidHelperUse: 18, mixedMerge: 19, invokeTemplate: 20, - compileTemplate: 21 + compileTemplate: 21, + themeLoad: 22 }; }()); diff --git a/src/verbs/build.js b/src/verbs/build.js index 677c3ca..4c4dd2b 100644 --- a/src/verbs/build.js +++ b/src/verbs/build.js @@ -74,12 +74,30 @@ Implementation of the 'build' verb for HackMyResume. format: null, objectify: false, quit: true, inner: { sort: _opts.sort } }, this); + // Explicit check for any resume loading errors... + if( !sheetObjects || + _.some( sheetObjects, function(so) { return so.fluenterror; } ) ) { + return null; + } + var sheets = sheetObjects.map(function(r) { return r.json; }); // Load the theme... + var theme; this.stat( HMEVENT.beforeTheme, { theme: _opts.theme }); - var tFolder = verifyTheme.call( this, _opts.theme ); - var theme = _opts.themeObj = loadTheme( tFolder ); + try { + var tFolder = verifyTheme.call( this, _opts.theme ); + theme = _opts.themeObj = loadTheme( tFolder ); + } + catch( ex ) { + var newEx = { + fluenterror: HMSTATUS.themeLoad, + inner: ex, + attempted: _opts.theme + }; + this.err( HMSTATUS.themeLoad, newEx ); + return null; + } this.stat( HMEVENT.afterTheme, { theme: theme }); // Check for invalid outputs... @@ -149,6 +167,7 @@ Implementation of the 'build' verb for HackMyResume. _opts.wrap = opts.wrap || 60; _opts.stitles = opts.sectionTitles; _opts.tips = opts.tips; + _opts.errHandler = opts.errHandler; _opts.noTips = opts.noTips; _opts.debug = opts.debug; _opts.sort = opts.sort;