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

Detect bad option files supplied via --options.

This commit is contained in:
hacksalot 2018-01-29 02:04:00 -05:00
parent 12a14dadeb
commit 17259cedbf
19 changed files with 149 additions and 13 deletions

24
dist/cli/error.js vendored
View File

@ -234,6 +234,30 @@ Error-handling routines for HackMyResume.
case HMSTATUS.validateError: case HMSTATUS.validateError:
msg = printf(M2C(this.msgs.validateError.msg), ex.inner.toString()); msg = printf(M2C(this.msgs.validateError.msg), ex.inner.toString());
etype = 'error'; etype = 'error';
break;
case HMSTATUS.invalidOptionsFile:
msg = M2C(this.msgs.invalidOptionsFile.msg[0]);
if (SyntaxErrorEx.is(ex.inner)) {
console.error(printf(M2C(this.msgs.readError.msg, 'red'), ex.file));
se = new SyntaxErrorEx(ex, ex.raw);
if ((se.line != null) && (se.col != null)) {
msg += printf(M2C(this.msgs.parseError.msg[0], 'red'), se.line, se.col);
} else if (se.line != null) {
msg += printf(M2C(this.msgs.parseError.msg[1], 'red'), se.line);
} else {
msg += M2C(this.msgs.parseError.msg[2], 'red');
}
} else if (ex.inner && (ex.inner.line != null) && (ex.inner.col != null)) {
msg += printf(M2C(this.msgs.parseError.msg[0], 'red'), ex.inner.line, ex.inner.col);
} else {
msg += ex;
}
msg += this.msgs.invalidOptionsFile.msg[1];
etype = 'error';
break;
case HMSTATUS.optionsFileNotFound:
msg = M2C(this.msgs.optionsFileNotFound.msg);
etype = 'error';
} }
return { return {
msg: msg, msg: msg,

22
dist/cli/main.js vendored
View File

@ -62,6 +62,9 @@ Definition of the `main` function.
main = module.exports = function(rawArgs, exitCallback) { main = module.exports = function(rawArgs, exitCallback) {
var args, initInfo, program; var args, initInfo, program;
initInfo = initialize(rawArgs, exitCallback); initInfo = initialize(rawArgs, exitCallback);
if (initInfo === null) {
return;
}
args = initInfo.args; args = initInfo.args;
program = new Command('hackmyresume').version(PKG.version).description(chalk.yellow.bold('*** HackMyResume ***')).option('-s --silent', 'Run in silent mode').option('--no-color', 'Disable colors').option('--color', 'Enable colors').option('-d --debug', 'Enable diagnostics', false).option('-a --assert', 'Treat warnings as errors', false).option('-v --version', 'Show the version').allowUnknownOption(); program = new Command('hackmyresume').version(PKG.version).description(chalk.yellow.bold('*** HackMyResume ***')).option('-s --silent', 'Run in silent mode').option('--no-color', 'Disable colors').option('--color', 'Enable colors').option('-d --debug', 'Enable diagnostics', false).option('-a --assert', 'Treat warnings as errors', false).option('-v --version', 'Show the version').allowUnknownOption();
program.jsonArgs = initInfo.options; program.jsonArgs = initInfo.options;
@ -104,6 +107,23 @@ Definition of the `main` function.
var o; var o;
_exitCallback = exitCallback || process.exit; _exitCallback = exitCallback || process.exit;
o = initOptions(ar); o = initOptions(ar);
if (o.ex) {
_err.init(false, true, false);
if (o.ex.op === 'parse') {
_err.err({
fluenterror: o.ex.op === 'parse' ? HMSTATUS.invalidOptionsFile : HMSTATUS.optionsFileNotFound,
inner: o.ex.inner,
quit: true
});
} else {
_err.err({
fluenterror: HMSTATUS.optionsFileNotFound,
inner: o.ex.inner,
quit: true
});
}
return null;
}
o.silent || logMsg(_title); o.silent || logMsg(_title);
if (o.debug) { if (o.debug) {
_out.log(chalk.cyan('The -d or --debug switch was specified. DEBUG mode engaged.')); _out.log(chalk.cyan('The -d or --debug switch was specified. DEBUG mode engaged.'));
@ -173,6 +193,8 @@ Definition of the `main` function.
inf = safeLoadJSON(optStr); inf = safeLoadJSON(optStr);
if (!inf.ex) { if (!inf.ex) {
oJSON = inf.json; oJSON = inf.json;
} else {
return inf;
} }
} }
} }

6
dist/cli/msg.yml vendored
View File

@ -109,3 +109,9 @@ errors:
msg: Exiting with status code **%s**. msg: Exiting with status code **%s**.
validateError: validateError:
msg: "An error occurred during validation:\n%s" msg: "An error occurred during validation:\n%s"
invalidOptionsFile:
msg:
- "The specified options file is invalid:\n"
- "\nMake sure the options file contains valid JSON."
optionsFileNotFound:
msg: "The specified options file is missing or inaccessible."

View File

@ -50,7 +50,7 @@ Definition of the FRESHTheme class.
themeInfo = loadSafeJson(themeFile); themeInfo = loadSafeJson(themeFile);
if (themeInfo.ex) { if (themeInfo.ex) {
throw { throw {
fluenterror: themeInfo.ex.operation === 'parse' ? HMSTATUS.parseError : HMSTATUS.readError, fluenterror: themeInfo.ex.op === 'parse' ? HMSTATUS.parseError : HMSTATUS.readError,
inner: themeInfo.ex.inner inner: themeInfo.ex.inner
}; };
} }

View File

@ -33,7 +33,9 @@ Status codes for HackMyResume.
invalidParamCount: 23, invalidParamCount: 23,
missingParam: 24, missingParam: 24,
createError: 25, createError: 25,
validateError: 26 validateError: 26,
invalidOptionsFile: 27,
optionsFileNotFound: 28
}; };
}).call(this); }).call(this);

View File

@ -21,7 +21,7 @@ Definition of the SafeJsonLoader class.
} catch (_error) { } catch (_error) {
retRaw = ret.raw && ret.raw.trim(); retRaw = ret.raw && ret.raw.trim();
ret.ex = { ret.ex = {
operation: retRaw ? 'parse' : 'read', op: retRaw ? 'parse' : 'read',
inner: SyntaxErrorEx.is(_error) ? new SyntaxErrorEx(_error, retRaw) : _error, inner: SyntaxErrorEx.is(_error) ? new SyntaxErrorEx(_error, retRaw) : _error,
file: file file: file
}; };

2
dist/verbs/peek.js vendored
View File

@ -80,7 +80,7 @@ Implementation of the 'peek' verb for HackMyResume.
} }
pkgError = null; pkgError = null;
if (obj.ex) { if (obj.ex) {
errCode = obj.ex.operation === 'parse' ? HMSTATUS.parseError : HMSTATUS.readError; errCode = obj.ex.op === 'parse' ? HMSTATUS.parseError : HMSTATUS.readError;
if (errCode === HMSTATUS.readError) { if (errCode === HMSTATUS.readError) {
obj.ex.quiet = true; obj.ex.quiet = true;
} }

View File

@ -111,7 +111,7 @@ Implementation of the 'validate' verb for HackMyResume.
ret.violations = validate.errors; ret.violations = validate.errors;
} }
} else { } else {
if (obj.ex.operation === 'parse') { if (obj.ex.op === 'parse') {
errCode = HMSTATUS.parseError; errCode = HMSTATUS.parseError;
ret.status = 'broken'; ret.status = 'broken';
} else { } else {

View File

@ -226,6 +226,28 @@ assembleError = ( ex ) ->
msg = printf M2C( @msgs.validateError.msg ), ex.inner.toString() msg = printf M2C( @msgs.validateError.msg ), ex.inner.toString()
etype = 'error' etype = 'error'
when HMSTATUS.invalidOptionsFile
msg = M2C @msgs.invalidOptionsFile.msg[0]
if SyntaxErrorEx.is ex.inner
console.error printf( M2C(this.msgs.readError.msg, 'red'), ex.file )
se = new SyntaxErrorEx ex, ex.raw
if se.line? and se.col?
msg += printf M2C( this.msgs.parseError.msg[0], 'red' ), se.line, se.col
else if se.line?
msg += printf M2C( this.msgs.parseError.msg[1], 'red' ), se.line
else
msg += M2C @msgs.parseError.msg[2], 'red'
else if ex.inner && ex.inner.line? && ex.inner.col?
msg += printf( M2C( this.msgs.parseError.msg[0], 'red' ), ex.inner.line, ex.inner.col)
else
msg += ex
msg += @msgs.invalidOptionsFile.msg[1]
etype = 'error'
when HMSTATUS.optionsFileNotFound
msg = M2C( @msgs.optionsFileNotFound.msg )
etype = 'error'
msg: msg # The error message to display msg: msg # The error message to display
withStack: withStack # Whether to include the stack withStack: withStack # Whether to include the stack
quit: quit quit: quit

View File

@ -40,6 +40,9 @@ process.argv (in production) or custom parameters (in test).
main = module.exports = ( rawArgs, exitCallback ) -> main = module.exports = ( rawArgs, exitCallback ) ->
initInfo = initialize( rawArgs, exitCallback ) initInfo = initialize( rawArgs, exitCallback )
if initInfo is null
return
args = initInfo.args args = initInfo.args
# Create the top-level (application) command... # Create the top-level (application) command...
@ -139,6 +142,16 @@ initialize = ( ar, exitCallback ) ->
_exitCallback = exitCallback || process.exit _exitCallback = exitCallback || process.exit
o = initOptions ar o = initOptions ar
if o.ex
_err.init false, true, false
if( o.ex.op == 'parse' )
_err.err
fluenterror: if o.ex.op == 'parse' then HMSTATUS.invalidOptionsFile else HMSTATUS.optionsFileNotFound,
inner: o.ex.inner,
quit: true
else
_err.err fluenterror: HMSTATUS.optionsFileNotFound, inner: o.ex.inner, quit: true
return null
o.silent || logMsg( _title ) o.silent || logMsg( _title )
# Emit debug prelude if --debug was specified # Emit debug prelude if --debug was specified
@ -169,7 +182,6 @@ initialize = ( ar, exitCallback ) ->
, true , true
return return
# Override the .helpInformation behavior # Override the .helpInformation behavior
Command.prototype.helpInformation = -> Command.prototype.helpInformation = ->
manPage = FS.readFileSync( manPage = FS.readFileSync(
@ -210,6 +222,7 @@ initOptions = ( ar ) ->
if optStr && (optStr = optStr.trim()) if optStr && (optStr = optStr.trim())
#var myJSON = JSON.parse(optStr); #var myJSON = JSON.parse(optStr);
if( optStr[0] == '{') if( optStr[0] == '{')
# TODO: remove use of evil(). - hacksalot
### jshint ignore:start ### ### jshint ignore:start ###
oJSON = eval('(' + optStr + ')') # jshint ignore:line <-- no worky oJSON = eval('(' + optStr + ')') # jshint ignore:line <-- no worky
### jshint ignore:end ### ### jshint ignore:end ###
@ -217,7 +230,8 @@ initOptions = ( ar ) ->
inf = safeLoadJSON( optStr ) inf = safeLoadJSON( optStr )
if( !inf.ex ) if( !inf.ex )
oJSON = inf.json oJSON = inf.json
# TODO: Error handling else
return inf
# Grab the --debug flag, --silent, --assert and --no-color flags # Grab the --debug flag, --silent, --assert and --no-color flags
isDebug = _.some args, (v) -> v == '-d' || v == '--debug' isDebug = _.some args, (v) -> v == '-d' || v == '--debug'

View File

@ -109,3 +109,9 @@ errors:
msg: Exiting with status code **%s**. msg: Exiting with status code **%s**.
validateError: validateError:
msg: "An error occurred during validation:\n%s" msg: "An error occurred during validation:\n%s"
invalidOptionsFile:
msg:
- "The specified options file is invalid:\n"
- "\nMake sure the options file contains valid JSON."
optionsFileNotFound:
msg: "The specified options file is missing or inaccessible."

View File

@ -43,7 +43,7 @@ class FRESHTheme
if themeInfo.ex if themeInfo.ex
throw throw
fluenterror: fluenterror:
if themeInfo.ex.operation == 'parse' if themeInfo.ex.op == 'parse'
then HMSTATUS.parseError then HMSTATUS.parseError
else HMSTATUS.readError else HMSTATUS.readError
inner: themeInfo.ex.inner inner: themeInfo.ex.inner

View File

@ -33,3 +33,5 @@ module.exports =
missingParam: 24 missingParam: 24
createError: 25 createError: 25
validateError: 26 validateError: 26
invalidOptionsFile: 27
optionsFileNotFound: 28

View File

@ -17,7 +17,7 @@ module.exports = ( file ) ->
# We'll return HMSTATUS.readError or HMSTATUS.parseError. # We'll return HMSTATUS.readError or HMSTATUS.parseError.
retRaw = ret.raw && ret.raw.trim() retRaw = ret.raw && ret.raw.trim()
ret.ex = ret.ex =
operation: if retRaw then 'parse' else 'read' op: if retRaw then 'parse' else 'read'
inner: inner:
if SyntaxErrorEx.is( _error ) if SyntaxErrorEx.is( _error )
then (new SyntaxErrorEx( _error, retRaw )) then (new SyntaxErrorEx( _error, retRaw ))

View File

@ -30,6 +30,7 @@ class SyntaxErrorEx
@line = (/on line (\d+)/.exec _error)[1] @line = (/on line (\d+)/.exec _error)[1]
# Return true if the supplied parameter is a JavaScript SyntaxError
SyntaxErrorEx.is = ( ex ) -> ex instanceof SyntaxError SyntaxErrorEx.is = ( ex ) -> ex instanceof SyntaxError
module.exports = SyntaxErrorEx; module.exports = SyntaxErrorEx;

View File

@ -66,7 +66,7 @@ _peekOne = ( t, objPath ) ->
## safeLoadJSON can only return a READ error or a PARSE error ## safeLoadJSON can only return a READ error or a PARSE error
pkgError = null pkgError = null
if obj.ex if obj.ex
errCode = if obj.ex.operation == 'parse' then HMSTATUS.parseError else HMSTATUS.readError errCode = if obj.ex.op == 'parse' then HMSTATUS.parseError else HMSTATUS.readError
if errCode == HMSTATUS.readError if errCode == HMSTATUS.readError
obj.ex.quiet = true obj.ex.quiet = true
pkgError = fluenterror: errCode, inner: obj.ex pkgError = fluenterror: errCode, inner: obj.ex

View File

@ -83,7 +83,7 @@ _validateOne = (t, validator, schemas, opts) ->
# If failure, package JSON read/parse errors # If failure, package JSON read/parse errors
else else
if obj.ex.operation == 'parse' if obj.ex.op == 'parse'
errCode = HMSTATUS.parseError errCode = HMSTATUS.parseError
ret.status = 'broken' ret.status = 'broken'
else else

View File

@ -0,0 +1,10 @@
{
// Set the default theme to "compact"
//"theme": "node_modules/jsonresume-theme-elegant",
//"theme": "jsonresume-theme-elegant",
"theme": "elegant",
// Change the "employment" section title text to "Work"
"sectionTitles": {
"employment": "Work"
}
}

View File

@ -143,9 +143,36 @@ describe('Testing Ouput interface', function () {
'to', 'to',
'test/sandbox/temp/janeq-3.all', 'test/sandbox/temp/janeq-3.all',
'--options', '--options',
"test/hmr-options.json", "test/scripts/hmr-options.json",
"-t", "-t",
"modern" "modern"
], ],
[ 'Applying MODERN theme'] ); [ 'Applying MODERN theme'] );
run('HMR should detect a missing or inaccessible options file',
[
'build',
'doesntmatter.json',
'to',
'dontcare.all',
'--options',
"test/scripts/hmr-options-nonexistent.json",
"-t",
"modern"
],
[ 'The specified options file is missing or inaccessible'] );
run('HMR should detect an invalid or malformed options file',
[
'build',
'doesntmatter.json',
'to',
'dontcare.all',
'--options',
"test/scripts/hmr-options-broken.json",
"-t",
"modern"
],
[ 'The specified options file is invalid'] );
}); });