mirror of
https://github.com/JuanCanham/HackMyResume.git
synced 2025-05-02 12:27:08 +01:00
Finish HackMyCore reshaping.
Reintroduce HackMyCore, dropping the interim submodule, and reorganize and improve tests.
This commit is contained in:
102
dist/verbs/analyze.js
vendored
Normal file
102
dist/verbs/analyze.js
vendored
Normal file
@ -0,0 +1,102 @@
|
||||
|
||||
/**
|
||||
Implementation of the 'analyze' verb for HackMyResume.
|
||||
@module verbs/analyze
|
||||
@license MIT. See LICENSE.md for details.
|
||||
*/
|
||||
|
||||
(function() {
|
||||
var AnalyzeVerb, HMEVENT, HMSTATUS, MKDIRP, PATH, ResumeFactory, Verb, _, _analyze, _loadInspectors, analyze, chalk;
|
||||
|
||||
MKDIRP = require('mkdirp');
|
||||
|
||||
PATH = require('path');
|
||||
|
||||
HMEVENT = require('../core/event-codes');
|
||||
|
||||
HMSTATUS = require('../core/status-codes');
|
||||
|
||||
_ = require('underscore');
|
||||
|
||||
ResumeFactory = require('../core/resume-factory');
|
||||
|
||||
Verb = require('../verbs/verb');
|
||||
|
||||
chalk = require('chalk');
|
||||
|
||||
AnalyzeVerb = module.exports = Verb.extend({
|
||||
init: function() {
|
||||
return this._super('analyze');
|
||||
},
|
||||
invoke: function() {
|
||||
this.stat(HMEVENT.begin, {
|
||||
cmd: 'analyze'
|
||||
});
|
||||
analyze.apply(this, arguments);
|
||||
return this.stat(HMEVENT.end);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
Run the 'analyze' command.
|
||||
*/
|
||||
|
||||
analyze = function(sources, dst, opts) {
|
||||
var nlzrs;
|
||||
if (!sources || !sources.length) {
|
||||
throw {
|
||||
fluenterror: HMSTATUS.resumeNotFound,
|
||||
quit: true
|
||||
};
|
||||
}
|
||||
nlzrs = _loadInspectors();
|
||||
return _.each(sources, function(src) {
|
||||
var result;
|
||||
result = ResumeFactory.loadOne(src, {
|
||||
format: 'FRESH',
|
||||
objectify: true
|
||||
}, this);
|
||||
if (result.fluenterror) {
|
||||
return this.setError(result.fluenterror, result);
|
||||
} else {
|
||||
return _analyze.call(this, result, nlzrs, opts);
|
||||
}
|
||||
}, this);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
Analyze a single resume.
|
||||
*/
|
||||
|
||||
_analyze = function(resumeObject, nlzrs, opts) {
|
||||
var info, rez, safeFormat;
|
||||
rez = resumeObject.rez;
|
||||
safeFormat = rez.meta && rez.meta.format && rez.meta.format.startsWith('FRESH') ? 'FRESH' : 'JRS';
|
||||
this.stat(HMEVENT.beforeAnalyze, {
|
||||
fmt: safeFormat,
|
||||
file: resumeObject.file
|
||||
});
|
||||
info = _.mapObject(nlzrs, function(val, key) {
|
||||
return val.run(rez);
|
||||
});
|
||||
return this.stat(HMEVENT.afterAnalyze, {
|
||||
info: info
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
Load inspectors.
|
||||
*/
|
||||
|
||||
_loadInspectors = function() {
|
||||
return {
|
||||
totals: require('../inspectors/totals-inspector'),
|
||||
coverage: require('../inspectors/gap-inspector'),
|
||||
keywords: require('../inspectors/keyword-inspector')
|
||||
};
|
||||
};
|
||||
|
||||
}).call(this);
|
416
dist/verbs/build.js
vendored
Normal file
416
dist/verbs/build.js
vendored
Normal file
@ -0,0 +1,416 @@
|
||||
|
||||
/**
|
||||
Implementation of the 'build' verb for HackMyResume.
|
||||
@module verbs/build
|
||||
@license MIT. See LICENSE.md for details.
|
||||
*/
|
||||
|
||||
(function() {
|
||||
var BuildVerb, FRESHTheme, FS, HMEVENT, HMSTATUS, JRSTheme, MD, MKDIRP, PATH, RConverter, RTYPES, ResumeFactory, Verb, _, _err, _fmts, _log, _opts, _rezObj, addFreebieFormats, build, expand, extend, loadTheme, parsePath, prep, single, verifyOutputs, verifyTheme;
|
||||
|
||||
_ = require('underscore');
|
||||
|
||||
PATH = require('path');
|
||||
|
||||
FS = require('fs');
|
||||
|
||||
MD = require('marked');
|
||||
|
||||
MKDIRP = require('mkdirp');
|
||||
|
||||
extend = require('extend');
|
||||
|
||||
parsePath = require('parse-filepath');
|
||||
|
||||
RConverter = require('fresh-jrs-converter');
|
||||
|
||||
HMSTATUS = require('../core/status-codes');
|
||||
|
||||
HMEVENT = require('../core/event-codes');
|
||||
|
||||
RTYPES = {
|
||||
FRESH: require('../core/fresh-resume'),
|
||||
JRS: require('../core/jrs-resume')
|
||||
};
|
||||
|
||||
_opts = require('../core/default-options');
|
||||
|
||||
FRESHTheme = require('../core/fresh-theme');
|
||||
|
||||
JRSTheme = require('../core/jrs-theme');
|
||||
|
||||
ResumeFactory = require('../core/resume-factory');
|
||||
|
||||
_fmts = require('../core/default-formats');
|
||||
|
||||
Verb = require('../verbs/verb');
|
||||
|
||||
_err = null;
|
||||
|
||||
_log = null;
|
||||
|
||||
_rezObj = null;
|
||||
|
||||
build = null;
|
||||
|
||||
prep = null;
|
||||
|
||||
single = null;
|
||||
|
||||
verifyOutputs = null;
|
||||
|
||||
addFreebieFormats = null;
|
||||
|
||||
expand = null;
|
||||
|
||||
verifyTheme = null;
|
||||
|
||||
loadTheme = null;
|
||||
|
||||
|
||||
/** An invokable resume generation command. */
|
||||
|
||||
BuildVerb = module.exports = Verb.extend({
|
||||
|
||||
/** Create a new build verb. */
|
||||
init: function() {
|
||||
return this._super('build');
|
||||
},
|
||||
|
||||
/** Invoke the Build command. */
|
||||
invoke: function() {
|
||||
var ret;
|
||||
this.stat(HMEVENT.begin, {
|
||||
cmd: 'build'
|
||||
});
|
||||
ret = build.apply(this, arguments);
|
||||
this.stat(HMEVENT.end);
|
||||
return ret;
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
Given a source resume in FRESH or JRS format, a destination resume path, and a
|
||||
theme file, generate 0..N resumes in the desired formats.
|
||||
@param src Path to the source JSON resume file: "rez/resume.json".
|
||||
@param dst An array of paths to the target resume file(s).
|
||||
@param theme Friendly name of the resume theme. Defaults to "modern".
|
||||
@param logger Optional logging override.
|
||||
*/
|
||||
|
||||
build = function(src, dst, opts) {
|
||||
var ex, inv, isFRESH, mixed, newEx, orgFormat, rez, sheetObjects, sheets, tFolder, targets, theme, toFormat;
|
||||
if (!src || !src.length) {
|
||||
this.err(HMSTATUS.resumeNotFound, {
|
||||
quit: true
|
||||
});
|
||||
}
|
||||
prep(src, dst, opts);
|
||||
sheetObjects = ResumeFactory.load(src, {
|
||||
format: null,
|
||||
objectify: false,
|
||||
quit: true,
|
||||
inner: {
|
||||
sort: _opts.sort
|
||||
}
|
||||
}, this);
|
||||
if (!sheetObjects || _.some(sheetObjects, function(so) {
|
||||
return so.fluenterror;
|
||||
})) {
|
||||
return null;
|
||||
}
|
||||
sheets = sheetObjects.map(function(r) {
|
||||
return r.json;
|
||||
});
|
||||
theme = null;
|
||||
this.stat(HMEVENT.beforeTheme, {
|
||||
theme: _opts.theme
|
||||
});
|
||||
try {
|
||||
tFolder = verifyTheme.call(this, _opts.theme);
|
||||
theme = _opts.themeObj = loadTheme(tFolder);
|
||||
} catch (_error) {
|
||||
ex = _error;
|
||||
newEx = {
|
||||
fluenterror: HMSTATUS.themeLoad,
|
||||
inner: ex,
|
||||
attempted: _opts.theme
|
||||
};
|
||||
this.err(HMSTATUS.themeLoad, newEx);
|
||||
return null;
|
||||
}
|
||||
this.stat(HMEVENT.afterTheme, {
|
||||
theme: theme
|
||||
});
|
||||
inv = verifyOutputs.call(this, dst, theme);
|
||||
if (inv && inv.length) {
|
||||
this.err(HMSTATUS.invalidFormat, {
|
||||
data: inv,
|
||||
theme: theme
|
||||
});
|
||||
}
|
||||
rez = null;
|
||||
if (sheets.length > 1) {
|
||||
isFRESH = !sheets[0].basics;
|
||||
mixed = _.any(sheets, function(s) {
|
||||
if (isFRESH) {
|
||||
return s.basics;
|
||||
} else {
|
||||
return !s.basics;
|
||||
}
|
||||
});
|
||||
this.stat(HMEVENT.beforeMerge, {
|
||||
f: _.clone(sheetObjects),
|
||||
mixed: mixed
|
||||
});
|
||||
if (mixed) {
|
||||
this.err(HMSTATUS.mixedMerge);
|
||||
}
|
||||
rez = _.reduceRight(sheets, function(a, b, idx) {
|
||||
return extend(true, b, a);
|
||||
});
|
||||
this.stat(HMEVENT.afterMerge, {
|
||||
r: rez
|
||||
});
|
||||
} else {
|
||||
rez = sheets[0];
|
||||
}
|
||||
orgFormat = rez.basics ? 'JRS' : 'FRESH';
|
||||
toFormat = theme.render ? 'JRS' : 'FRESH';
|
||||
if (toFormat !== orgFormat) {
|
||||
this.stat(HMEVENT.beforeInlineConvert);
|
||||
rez = RConverter['to' + toFormat](rez);
|
||||
this.stat(HMEVENT.afterInlineConvert, {
|
||||
file: sheetObjects[0].file,
|
||||
fmt: toFormat
|
||||
});
|
||||
}
|
||||
addFreebieFormats(theme);
|
||||
this.stat(HMEVENT.applyTheme, {
|
||||
r: rez,
|
||||
theme: theme
|
||||
});
|
||||
_rezObj = new RTYPES[toFormat]().parseJSON(rez);
|
||||
targets = expand(dst, theme);
|
||||
_.each(targets, function(t) {
|
||||
return t.final = single.call(this, t, theme, targets);
|
||||
}, this);
|
||||
return {
|
||||
sheet: _rezObj,
|
||||
targets: targets,
|
||||
processed: targets
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
Prepare for a BUILD run.
|
||||
*/
|
||||
|
||||
prep = function(src, dst, opts) {
|
||||
_opts.theme = (opts.theme && opts.theme.toLowerCase().trim()) || 'modern';
|
||||
_opts.prettify = opts.prettify === true;
|
||||
_opts.css = opts.css;
|
||||
_opts.pdf = opts.pdf;
|
||||
_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;
|
||||
(src.length > 1 && (!dst || !dst.length)) && dst.push(src.pop());
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
Generate a single target resume such as "out/rez.html" or "out/rez.doc".
|
||||
TODO: Refactor.
|
||||
@param targInfo Information for the target resume.
|
||||
@param theme A FRESHTheme or JRSTheme object.
|
||||
*/
|
||||
|
||||
single = function(targInfo, theme, finished) {
|
||||
var e, ex, f, fName, fType, outFolder, ret, theFormat;
|
||||
ret = null;
|
||||
ex = null;
|
||||
f = targInfo.file;
|
||||
try {
|
||||
if (!targInfo.fmt) {
|
||||
return;
|
||||
}
|
||||
fType = targInfo.fmt.outFormat;
|
||||
fName = PATH.basename(f, '.' + fType);
|
||||
theFormat = null;
|
||||
this.stat(HMEVENT.beforeGenerate, {
|
||||
fmt: targInfo.fmt.outFormat,
|
||||
file: PATH.relative(process.cwd(), f)
|
||||
});
|
||||
if (targInfo.fmt.files && targInfo.fmt.files.length) {
|
||||
theFormat = _fmts.filter(function(fmt) {
|
||||
return fmt.name === targInfo.fmt.outFormat;
|
||||
})[0];
|
||||
MKDIRP.sync(PATH.dirname(f));
|
||||
_opts.targets = finished;
|
||||
ret = theFormat.gen.generate(_rezObj, f, _opts);
|
||||
} else {
|
||||
theFormat = _fmts.filter(function(fmt) {
|
||||
return fmt.name === targInfo.fmt.outFormat;
|
||||
})[0];
|
||||
outFolder = PATH.dirname(f);
|
||||
MKDIRP.sync(outFolder);
|
||||
ret = theFormat.gen.generate(_rezObj, f, _opts);
|
||||
}
|
||||
} catch (_error) {
|
||||
e = _error;
|
||||
ex = e;
|
||||
}
|
||||
this.stat(HMEVENT.afterGenerate, {
|
||||
fmt: targInfo.fmt.outFormat,
|
||||
file: PATH.relative(process.cwd(), f),
|
||||
error: ex
|
||||
});
|
||||
if (ex) {
|
||||
if (ex.fluenterror) {
|
||||
this.err(ex.fluenterror, ex);
|
||||
} else {
|
||||
this.err(HMSTATUS.generateError, {
|
||||
inner: ex
|
||||
});
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
Ensure that user-specified outputs/targets are valid.
|
||||
*/
|
||||
|
||||
verifyOutputs = function(targets, theme) {
|
||||
this.stat(HMEVENT.verifyOutputs, {
|
||||
targets: targets,
|
||||
theme: theme
|
||||
});
|
||||
return _.reject(targets.map(function(t) {
|
||||
var pathInfo;
|
||||
pathInfo = parsePath(t);
|
||||
return {
|
||||
format: pathInfo.extname.substr(1)
|
||||
};
|
||||
}), function(t) {
|
||||
return t.format === 'all' || theme.hasFormat(t.format);
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
Reinforce the chosen theme with "freebie" formats provided by HackMyResume.
|
||||
A "freebie" format is an output format such as JSON, YML, or PNG that can be
|
||||
generated directly from the resume model or from one of the theme's declared
|
||||
output formats. For example, the PNG format can be generated for any theme
|
||||
that declares an HTML format; the theme doesn't have to provide an explicit
|
||||
PNG template.
|
||||
@param theTheme A FRESHTheme or JRSTheme object.
|
||||
*/
|
||||
|
||||
addFreebieFormats = function(theTheme) {
|
||||
theTheme.formats.json = theTheme.formats.json || {
|
||||
freebie: true,
|
||||
title: 'json',
|
||||
outFormat: 'json',
|
||||
pre: 'json',
|
||||
ext: 'json',
|
||||
path: null,
|
||||
data: null
|
||||
};
|
||||
theTheme.formats.yml = theTheme.formats.yml || {
|
||||
freebie: true,
|
||||
title: 'yaml',
|
||||
outFormat: 'yml',
|
||||
pre: 'yml',
|
||||
ext: 'yml',
|
||||
path: null,
|
||||
data: null
|
||||
};
|
||||
if (theTheme.formats.html && !theTheme.formats.png) {
|
||||
theTheme.formats.png = {
|
||||
freebie: true,
|
||||
title: 'png',
|
||||
outFormat: 'png',
|
||||
ext: 'yml',
|
||||
path: null,
|
||||
data: null
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
Expand output files. For example, "foo.all" should be expanded to
|
||||
["foo.html", "foo.doc", "foo.pdf", "etc"].
|
||||
@param dst An array of output files as specified by the user.
|
||||
@param theTheme A FRESHTheme or JRSTheme object.
|
||||
*/
|
||||
|
||||
expand = function(dst, theTheme) {
|
||||
var destColl, targets;
|
||||
destColl = (dst && dst.length && dst) || [PATH.normalize('out/resume.all')];
|
||||
targets = [];
|
||||
destColl.forEach(function(t) {
|
||||
var fmat, pa, to;
|
||||
to = PATH.resolve(t);
|
||||
pa = parsePath(to);
|
||||
fmat = pa.extname || '.all';
|
||||
return targets.push.apply(targets, fmat === '.all' ? Object.keys(theTheme.formats).map(function(k) {
|
||||
var z;
|
||||
z = theTheme.formats[k];
|
||||
return {
|
||||
file: to.replace(/all$/g, z.outFormat),
|
||||
fmt: z
|
||||
};
|
||||
}) : [
|
||||
{
|
||||
file: to,
|
||||
fmt: theTheme.getFormat(fmat.slice(1))
|
||||
}
|
||||
]);
|
||||
});
|
||||
return targets;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
Verify the specified theme name/path.
|
||||
*/
|
||||
|
||||
verifyTheme = function(themeNameOrPath) {
|
||||
var exists, tFolder;
|
||||
tFolder = PATH.join(parsePath(require.resolve('fresh-themes')).dirname, '/themes/', themeNameOrPath);
|
||||
exists = require('path-exists').sync;
|
||||
if (!exists(tFolder)) {
|
||||
tFolder = PATH.resolve(themeNameOrPath);
|
||||
if (!exists(tFolder)) {
|
||||
this.err(HMSTATUS.themeNotFound, {
|
||||
data: _opts.theme
|
||||
});
|
||||
}
|
||||
}
|
||||
return tFolder;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
Load the specified theme, which could be either a FRESH theme or a JSON Resume
|
||||
theme.
|
||||
*/
|
||||
|
||||
loadTheme = function(tFolder) {
|
||||
var theTheme;
|
||||
theTheme = _opts.theme.indexOf('jsonresume-theme-') > -1 ? new JRSTheme().open(tFolder) : new FRESHTheme().open(tFolder);
|
||||
_opts.themeObj = theTheme;
|
||||
return theTheme;
|
||||
};
|
||||
|
||||
}).call(this);
|
95
dist/verbs/convert.js
vendored
Normal file
95
dist/verbs/convert.js
vendored
Normal file
@ -0,0 +1,95 @@
|
||||
|
||||
/**
|
||||
Implementation of the 'convert' verb for HackMyResume.
|
||||
@module verbs/convert
|
||||
@license MIT. See LICENSE.md for details.
|
||||
*/
|
||||
|
||||
(function() {
|
||||
var ConvertVerb, HMEVENT, HMSTATUS, ResumeFactory, Verb, _, chalk, convert;
|
||||
|
||||
ResumeFactory = require('../core/resume-factory');
|
||||
|
||||
chalk = require('chalk');
|
||||
|
||||
Verb = require('../verbs/verb');
|
||||
|
||||
HMSTATUS = require('../core/status-codes');
|
||||
|
||||
_ = require('underscore');
|
||||
|
||||
HMEVENT = require('../core/event-codes');
|
||||
|
||||
ConvertVerb = module.exports = Verb.extend({
|
||||
init: function() {
|
||||
return this._super('convert');
|
||||
},
|
||||
invoke: function() {
|
||||
this.stat(HMEVENT.begin, {
|
||||
cmd: 'convert'
|
||||
});
|
||||
convert.apply(this, arguments);
|
||||
return this.stat(HMEVENT.end);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
Convert between FRESH and JRS formats.
|
||||
*/
|
||||
|
||||
convert = function(srcs, dst, opts) {
|
||||
if (!srcs || !srcs.length) {
|
||||
throw {
|
||||
fluenterror: 6,
|
||||
quit: true
|
||||
};
|
||||
}
|
||||
if (!dst || !dst.length) {
|
||||
if (srcs.length === 1) {
|
||||
throw {
|
||||
fluenterror: HMSTATUS.inputOutputParity,
|
||||
quit: true
|
||||
};
|
||||
} else if (srcs.length === 2) {
|
||||
dst = dst || [];
|
||||
dst.push(srcs.pop());
|
||||
} else {
|
||||
throw {
|
||||
fluenterror: HMSTATUS.inputOutputParity,
|
||||
quit: true
|
||||
};
|
||||
}
|
||||
}
|
||||
if (srcs && dst && srcs.length && dst.length && srcs.length !== dst.length) {
|
||||
throw {
|
||||
fluenterror: HMSTATUS.inputOutputParity({
|
||||
quit: true
|
||||
})
|
||||
};
|
||||
}
|
||||
_.each(srcs, function(src, idx) {
|
||||
var rinfo, s, srcFmt, targetFormat;
|
||||
rinfo = ResumeFactory.loadOne(src, {
|
||||
format: null,
|
||||
objectify: true,
|
||||
"throw": false
|
||||
});
|
||||
if (rinfo.fluenterror) {
|
||||
this.err(rinfo.fluenterror, rinfo);
|
||||
return;
|
||||
}
|
||||
s = rinfo.rez;
|
||||
srcFmt = ((s.basics && s.basics.imp) || s.imp).orgFormat === 'JRS' ? 'JRS' : 'FRESH';
|
||||
targetFormat = srcFmt === 'JRS' ? 'FRESH' : 'JRS';
|
||||
this.stat(HMEVENT.beforeConvert, {
|
||||
srcFile: rinfo.file,
|
||||
srcFmt: srcFmt,
|
||||
dstFile: dst[idx],
|
||||
dstFmt: targetFormat
|
||||
});
|
||||
s.saveAs(dst[idx], targetFormat);
|
||||
}, this);
|
||||
};
|
||||
|
||||
}).call(this);
|
69
dist/verbs/create.js
vendored
Normal file
69
dist/verbs/create.js
vendored
Normal file
@ -0,0 +1,69 @@
|
||||
|
||||
/**
|
||||
Implementation of the 'create' verb for HackMyResume.
|
||||
@module verbs/create
|
||||
@license MIT. See LICENSE.md for details.
|
||||
*/
|
||||
|
||||
(function() {
|
||||
var CreateVerb, HMEVENT, HMSTATUS, MKDIRP, PATH, Verb, _, chalk, create;
|
||||
|
||||
MKDIRP = require('mkdirp');
|
||||
|
||||
PATH = require('path');
|
||||
|
||||
chalk = require('chalk');
|
||||
|
||||
Verb = require('../verbs/verb');
|
||||
|
||||
_ = require('underscore');
|
||||
|
||||
HMSTATUS = require('../core/status-codes');
|
||||
|
||||
HMEVENT = require('../core/event-codes');
|
||||
|
||||
CreateVerb = module.exports = Verb.extend({
|
||||
init: function() {
|
||||
return this._super('new');
|
||||
},
|
||||
invoke: function() {
|
||||
this.stat(HMEVENT.begin, {
|
||||
cmd: 'create'
|
||||
});
|
||||
create.apply(this, arguments);
|
||||
this.stat(HMEVENT.begin, {
|
||||
cmd: 'convert'
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
Create a new empty resume in either FRESH or JRS format.
|
||||
*/
|
||||
|
||||
create = function(src, dst, opts) {
|
||||
if (!src || !src.length) {
|
||||
throw {
|
||||
fluenterror: HMSTATUS.createNameMissing,
|
||||
quit: true
|
||||
};
|
||||
}
|
||||
_.each(src, function(t) {
|
||||
var RezClass, safeFmt;
|
||||
safeFmt = opts.format.toUpperCase();
|
||||
this.stat(HMEVENT.beforeCreate, {
|
||||
fmt: safeFmt,
|
||||
file: t
|
||||
});
|
||||
MKDIRP.sync(PATH.dirname(t));
|
||||
RezClass = require('../core/' + safeFmt.toLowerCase() + '-resume');
|
||||
RezClass["default"]().save(t);
|
||||
return this.stat(HMEVENT.afterCreate, {
|
||||
fmt: safeFmt,
|
||||
file: t
|
||||
});
|
||||
}, this);
|
||||
};
|
||||
|
||||
}).call(this);
|
77
dist/verbs/peek.js
vendored
Normal file
77
dist/verbs/peek.js
vendored
Normal file
@ -0,0 +1,77 @@
|
||||
|
||||
/**
|
||||
Implementation of the 'peek' verb for HackMyResume.
|
||||
@module verbs/peek
|
||||
@license MIT. See LICENSE.md for details.
|
||||
*/
|
||||
|
||||
(function() {
|
||||
var HMEVENT, HMSTATUS, PeekVerb, Verb, _, __, peek, safeLoadJSON;
|
||||
|
||||
Verb = require('../verbs/verb');
|
||||
|
||||
_ = require('underscore');
|
||||
|
||||
__ = require('lodash');
|
||||
|
||||
safeLoadJSON = require('../utils/safe-json-loader');
|
||||
|
||||
HMSTATUS = require('../core/status-codes');
|
||||
|
||||
HMEVENT = require('../core/event-codes');
|
||||
|
||||
PeekVerb = module.exports = Verb.extend({
|
||||
init: function() {
|
||||
return this._super('peek');
|
||||
},
|
||||
invoke: function() {
|
||||
this.stat(HMEVENT.begin, {
|
||||
cmd: 'peek'
|
||||
});
|
||||
peek.apply(this, arguments);
|
||||
return this.stat(HMEVENT.end);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
/** Peek at a resume, resume section, or resume field. */
|
||||
|
||||
peek = function(src, dst, opts) {
|
||||
var objPath;
|
||||
if (!src || !src.length) {
|
||||
({
|
||||
"throw": {
|
||||
fluenterror: HMSTATUS.resumeNotFound
|
||||
}
|
||||
});
|
||||
}
|
||||
objPath = (dst && dst[0]) || '';
|
||||
_.each(src, function(t) {
|
||||
var errCode, obj, tgt;
|
||||
this.stat(HMEVENT.beforePeek, {
|
||||
file: t,
|
||||
target: objPath
|
||||
});
|
||||
obj = safeLoadJSON(t);
|
||||
tgt = null;
|
||||
if (!obj.ex) {
|
||||
tgt = objPath ? __.get(obj.json, objPath) : obj.json;
|
||||
}
|
||||
this.stat(HMEVENT.afterPeek, {
|
||||
file: t,
|
||||
requested: objPath,
|
||||
target: tgt,
|
||||
error: obj.ex
|
||||
});
|
||||
if (obj.ex) {
|
||||
errCode = obj.ex.operation === 'parse' ? HMSTATUS.parseError : HMSTATUS.readError;
|
||||
if (errCode === HMSTATUS.readError) {
|
||||
obj.ex.quiet = true;
|
||||
}
|
||||
this.setError(errCode, obj.ex);
|
||||
return this.err(errCode, obj.ex);
|
||||
}
|
||||
}, this);
|
||||
};
|
||||
|
||||
}).call(this);
|
112
dist/verbs/validate.js
vendored
Normal file
112
dist/verbs/validate.js
vendored
Normal file
@ -0,0 +1,112 @@
|
||||
|
||||
/**
|
||||
Implementation of the 'validate' verb for HackMyResume.
|
||||
@module verbs/validate
|
||||
@license MIT. See LICENSE.md for details.
|
||||
*/
|
||||
|
||||
(function() {
|
||||
var FS, HMEVENT, HMSTATUS, ResumeFactory, SyntaxErrorEx, ValidateVerb, Verb, _, chalk, safeLoadJSON, validate;
|
||||
|
||||
FS = require('fs');
|
||||
|
||||
ResumeFactory = require('../core/resume-factory');
|
||||
|
||||
SyntaxErrorEx = require('../utils/syntax-error-ex');
|
||||
|
||||
chalk = require('chalk');
|
||||
|
||||
Verb = require('../verbs/verb');
|
||||
|
||||
HMSTATUS = require('../core/status-codes');
|
||||
|
||||
HMEVENT = require('../core/event-codes');
|
||||
|
||||
_ = require('underscore');
|
||||
|
||||
safeLoadJSON = require('../utils/safe-json-loader');
|
||||
|
||||
|
||||
/** An invokable resume validation command. */
|
||||
|
||||
ValidateVerb = module.exports = Verb.extend({
|
||||
init: function() {
|
||||
return this._super('validate');
|
||||
},
|
||||
invoke: function() {
|
||||
var ret;
|
||||
this.stat(HMEVENT.begin, {
|
||||
cmd: 'validate'
|
||||
});
|
||||
ret = validate.apply(this, arguments);
|
||||
this.stat(HMEVENT.end);
|
||||
return ret;
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
/** Validate 1 to N resumes in FRESH or JSON Resume format. */
|
||||
|
||||
validate = function(sources, unused, opts) {
|
||||
var schemas, validator;
|
||||
if (!sources || !sources.length) {
|
||||
throw {
|
||||
fluenterror: HMSTATUS.resumeNotFoundAlt,
|
||||
quit: true
|
||||
};
|
||||
}
|
||||
validator = require('is-my-json-valid');
|
||||
schemas = {
|
||||
fresh: require('fresca'),
|
||||
jars: require('../core/resume.json')
|
||||
};
|
||||
return _.map(sources, function(t) {
|
||||
var errCode, errors, fmt, json, obj, ret;
|
||||
ret = {
|
||||
file: t,
|
||||
isValid: false
|
||||
};
|
||||
obj = safeLoadJSON(t);
|
||||
if (!obj.ex) {
|
||||
json = obj.json;
|
||||
fmt = json.basics ? 'jrs' : 'fresh';
|
||||
errors = [];
|
||||
try {
|
||||
validate = validator(schemas[fmt], {
|
||||
formats: {
|
||||
date: /^\d{4}(?:-(?:0[0-9]{1}|1[0-2]{1})(?:-[0-9]{2})?)?$/
|
||||
}
|
||||
});
|
||||
ret.isValid = validate(json);
|
||||
if (!ret.isValid) {
|
||||
errors = validate.errors;
|
||||
}
|
||||
} catch (_error) {
|
||||
ret.ex = _error;
|
||||
}
|
||||
} else {
|
||||
errCode = obj.ex.operation === 'parse' ? HMSTATUS.parseError : HMSTATUS.readError;
|
||||
if (errCode === HMSTATUS.readError) {
|
||||
obj.ex.quiet = true;
|
||||
}
|
||||
this.setError(errCode, obj.ex);
|
||||
this.err(errCode, obj.ex);
|
||||
}
|
||||
this.stat(HMEVENT.afterValidate, {
|
||||
file: t,
|
||||
isValid: ret.isValid,
|
||||
fmt: fmt != null ? fmt.replace('jars', 'JSON Resume') : void 0,
|
||||
errors: errors
|
||||
});
|
||||
if (opts.assert && !ret.isValid) {
|
||||
throw {
|
||||
fluenterror: HMSTATUS.invalid,
|
||||
shouldExit: true
|
||||
};
|
||||
}
|
||||
console.log('1111');
|
||||
return ret;
|
||||
}, this);
|
||||
};
|
||||
|
||||
}).call(this);
|
69
dist/verbs/verb.js
vendored
Normal file
69
dist/verbs/verb.js
vendored
Normal file
@ -0,0 +1,69 @@
|
||||
|
||||
/**
|
||||
Definition of the Verb class.
|
||||
@module verbs/verb
|
||||
@license MIT. See LICENSE.md for details.
|
||||
*/
|
||||
|
||||
(function() {
|
||||
var Class, EVENTS, Verb;
|
||||
|
||||
Class = require('../utils/class');
|
||||
|
||||
EVENTS = require('events');
|
||||
|
||||
|
||||
/**
|
||||
An instantiation of a HackMyResume command.
|
||||
@class Verb
|
||||
*/
|
||||
|
||||
Verb = module.exports = Class.extend({
|
||||
|
||||
/** Constructor. Automatically called at creation. */
|
||||
init: function(moniker) {
|
||||
this.moniker = moniker;
|
||||
this.emitter = new EVENTS.EventEmitter();
|
||||
},
|
||||
|
||||
/** Forward subscriptions to the event emitter. */
|
||||
on: function() {
|
||||
return this.emitter.on.apply(this.emitter, arguments);
|
||||
},
|
||||
|
||||
/** Fire an arbitrary event, scoped to "hmr:". */
|
||||
fire: function(evtName, payload) {
|
||||
payload = payload || {};
|
||||
payload.cmd = this.moniker;
|
||||
this.emitter.emit('hmr:' + evtName, payload);
|
||||
return true;
|
||||
},
|
||||
|
||||
/** Handle an error condition. */
|
||||
err: function(errorCode, payload, hot) {
|
||||
payload = payload || {};
|
||||
payload.sub = payload.fluenterror = errorCode;
|
||||
payload["throw"] = hot;
|
||||
this.fire('error', payload);
|
||||
if (hot) {
|
||||
throw payload;
|
||||
}
|
||||
return true;
|
||||
},
|
||||
|
||||
/** Fire the 'hmr:status' error event. */
|
||||
stat: function(subEvent, payload) {
|
||||
payload = payload || {};
|
||||
payload.sub = subEvent;
|
||||
this.fire('status', payload);
|
||||
return true;
|
||||
},
|
||||
|
||||
/** Associate error info with the invocation. */
|
||||
setError: function(code, obj) {
|
||||
this.errorCode = code;
|
||||
this.errorObj = obj;
|
||||
}
|
||||
});
|
||||
|
||||
}).call(this);
|
Reference in New Issue
Block a user