resume-cli 3.0.2 → 3.0.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +7 -2
- package/build/builder.js +61 -0
- package/{lib → build}/export-resume.js +57 -37
- package/build/get-resume.js +66 -0
- package/build/get-schema.js +28 -0
- package/build/init.js +67 -0
- package/build/render-html.js +58 -0
- package/{lib → build}/serve.js +10 -5
- package/build/validate.js +36 -0
- package/package.json +12 -11
- package/lib/builder.js +0 -66
- package/lib/get-resume.js +0 -38
- package/lib/get-resume.test.js +0 -73
- package/lib/get-schema.js +0 -16
- package/lib/init.js +0 -56
- package/lib/main.js +0 -136
- package/lib/main.test.js +0 -155
- package/lib/render-html.js +0 -35
- package/lib/render-html.test.js +0 -47
- package/lib/test-utils/cli-test-entry.js +0 -12
- package/lib/test-utils/mocked-volume-builder.js +0 -45
- package/lib/validate.js +0 -15
- package/lib/validate.test.js +0 -33
package/README.md
CHANGED
|
@@ -10,6 +10,11 @@ This is the command line tool for [JSON Resume](https://jsonresume.org), the ope
|
|
|
10
10
|
|
|
11
11
|
[Read more...](https://jsonresume.org/schema/)
|
|
12
12
|
|
|
13
|
+
|
|
14
|
+
Alternatives: The Resume CLI tool works as it is so there isn't a huge amount of active development on it, try these alternatives if it doesn't work for you;
|
|
15
|
+
- [Resumed](https://github.com/rbardini/resumed)
|
|
16
|
+
|
|
17
|
+
|
|
13
18
|
# Getting Started
|
|
14
19
|
|
|
15
20
|
Install the command-line tool:
|
|
@@ -23,7 +28,7 @@ npm install -g resume-cli
|
|
|
23
28
|
| command | description |
|
|
24
29
|
| ---------------------- | ----------------------------------------- |
|
|
25
30
|
| init | Initialize a `resume.json` file |
|
|
26
|
-
|
|
|
31
|
+
| validate | Schema validation test your `resume.json` |
|
|
27
32
|
| export [fileName.html] | Export locally to `.html` |
|
|
28
33
|
| serve | Serve resume at `http://localhost:4000/` |
|
|
29
34
|
|
|
@@ -40,7 +45,7 @@ Creates a new `resume.json` file in your current working directory.
|
|
|
40
45
|
Complete the `resume.json` with your text editor. Be sure to follow the schema
|
|
41
46
|
(available at http://jsonresume.org).
|
|
42
47
|
|
|
43
|
-
## `resume
|
|
48
|
+
## `resume validate`
|
|
44
49
|
|
|
45
50
|
Validates your `resume.json` against our schema tests to ensure it complies with
|
|
46
51
|
the standard. Tries to identify where any errors may be occurring.
|
package/build/builder.js
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
const themeServer = process.env.THEME_SERVER || 'https://themes.jsonresume.org/theme/';
|
|
4
|
+
|
|
5
|
+
const fs = require('fs');
|
|
6
|
+
|
|
7
|
+
const request = require('superagent');
|
|
8
|
+
|
|
9
|
+
const chalk = require('chalk');
|
|
10
|
+
|
|
11
|
+
const renderHtml = require('./render-html').default;
|
|
12
|
+
|
|
13
|
+
const denormalizeTheme = value => {
|
|
14
|
+
return value.match(/jsonresume-theme-(.*)/)[1];
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
const sendExportHTML = (resumeJson, theme, callback) => {
|
|
18
|
+
console.log(resumeJson, theme);
|
|
19
|
+
console.log('Requesting theme from server...');
|
|
20
|
+
request.post(themeServer + denormalizeTheme(theme)).send({
|
|
21
|
+
resume: resumeJson
|
|
22
|
+
}).set('Accept', 'application/json').end((err, response) => {
|
|
23
|
+
if (err) {
|
|
24
|
+
callback('There was an error downloading your generated html resume from our server: ' + err);
|
|
25
|
+
} else if (response.text) {
|
|
26
|
+
callback(null, response.text);
|
|
27
|
+
} else {
|
|
28
|
+
callback('There was an error downloading your generated html resume from our server.');
|
|
29
|
+
}
|
|
30
|
+
});
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
module.exports = function resumeBuilder(theme, dir, resumeFilename, cb) {
|
|
34
|
+
fs.readFile(resumeFilename, async (err, resumeJson) => {
|
|
35
|
+
if (err) {
|
|
36
|
+
console.log(chalk.yellow('Could not find:'), resumeFilename);
|
|
37
|
+
console.log(chalk.cyan('Using example resume.json from resume-schema instead...'));
|
|
38
|
+
resumeJson = require('resume-schema').resumeJson;
|
|
39
|
+
} else {
|
|
40
|
+
try {
|
|
41
|
+
// todo: test resume schema
|
|
42
|
+
resumeJson = JSON.parse(resumeJson);
|
|
43
|
+
} catch (e) {
|
|
44
|
+
err = 'Parse error: ' + resumeFilename;
|
|
45
|
+
return cb(err);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
try {
|
|
50
|
+
const html = await renderHtml({
|
|
51
|
+
resume: resumeJson,
|
|
52
|
+
themePath: theme
|
|
53
|
+
});
|
|
54
|
+
cb(null, html);
|
|
55
|
+
} catch (err) {
|
|
56
|
+
console.log(err);
|
|
57
|
+
console.log(chalk.yellow('Could not run the render function from local theme.'));
|
|
58
|
+
sendExportHTML(resumeJson, theme, cb);
|
|
59
|
+
}
|
|
60
|
+
});
|
|
61
|
+
};
|
|
@@ -1,16 +1,27 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
var _renderHtml = _interopRequireDefault(require("./render-html"));
|
|
4
|
+
|
|
5
|
+
var _util = require("util");
|
|
6
|
+
|
|
7
|
+
var _fs = _interopRequireDefault(require("fs"));
|
|
8
|
+
|
|
9
|
+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
10
|
+
|
|
11
|
+
const writeFile = (0, _util.promisify)(_fs.default.writeFile);
|
|
4
12
|
|
|
5
|
-
const writeFile = promisify(fs.writeFile);
|
|
6
13
|
const path = require('path');
|
|
14
|
+
|
|
7
15
|
const puppeteer = require('puppeteer');
|
|
16
|
+
|
|
8
17
|
const btoa = require('btoa');
|
|
9
18
|
|
|
10
|
-
module.exports = (
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
19
|
+
module.exports = ({
|
|
20
|
+
resume: resumeJson,
|
|
21
|
+
fileName,
|
|
22
|
+
theme,
|
|
23
|
+
format
|
|
24
|
+
}, callback) => {
|
|
14
25
|
if (!fileName) {
|
|
15
26
|
console.error('Please enter a export destination.');
|
|
16
27
|
process.exit(1);
|
|
@@ -20,18 +31,21 @@ module.exports = (
|
|
|
20
31
|
fileName = fileNameAndFormat.fileName;
|
|
21
32
|
const fileFormatToUse = fileNameAndFormat.fileFormatToUse;
|
|
22
33
|
const formatToUse = '.' + fileFormatToUse;
|
|
34
|
+
|
|
23
35
|
if (formatToUse === '.html') {
|
|
24
|
-
createHtml(resumeJson, fileName, theme, formatToUse,
|
|
36
|
+
createHtml(resumeJson, fileName, theme, formatToUse, error => {
|
|
25
37
|
if (error) {
|
|
26
38
|
console.error(error, '`createHtml` errored out');
|
|
27
39
|
}
|
|
40
|
+
|
|
28
41
|
callback(error, fileName, formatToUse);
|
|
29
42
|
});
|
|
30
43
|
} else if (formatToUse === '.pdf') {
|
|
31
|
-
createPdf(resumeJson, fileName, theme, formatToUse,
|
|
44
|
+
createPdf(resumeJson, fileName, theme, formatToUse, error => {
|
|
32
45
|
if (error) {
|
|
33
46
|
console.error(error, '`createPdf` errored out');
|
|
34
47
|
}
|
|
48
|
+
|
|
35
49
|
callback(error, fileName, formatToUse);
|
|
36
50
|
});
|
|
37
51
|
} else {
|
|
@@ -40,41 +54,49 @@ module.exports = (
|
|
|
40
54
|
}
|
|
41
55
|
};
|
|
42
56
|
|
|
43
|
-
const extractFileFormat =
|
|
57
|
+
const extractFileFormat = fileName => {
|
|
44
58
|
const dotPos = fileName.lastIndexOf('.');
|
|
59
|
+
|
|
45
60
|
if (dotPos === -1) {
|
|
46
61
|
return null;
|
|
47
62
|
}
|
|
63
|
+
|
|
48
64
|
return fileName.substring(dotPos + 1).toLowerCase();
|
|
49
65
|
};
|
|
50
66
|
|
|
51
|
-
const getThemePkg =
|
|
67
|
+
const getThemePkg = theme => {
|
|
52
68
|
if (theme[0] === '.') {
|
|
53
|
-
theme = path.join(process.cwd(),
|
|
69
|
+
theme = path.join(process.cwd(), 'index.js');
|
|
70
|
+
} else {
|
|
71
|
+
theme = path.join(process.cwd(), 'node_modules', theme, 'index.js');
|
|
54
72
|
}
|
|
73
|
+
|
|
55
74
|
try {
|
|
56
75
|
const themePkg = require(theme);
|
|
76
|
+
|
|
57
77
|
return themePkg;
|
|
58
78
|
} catch (err) {
|
|
59
79
|
// Theme not installed
|
|
60
|
-
console.log(
|
|
61
|
-
'You have to install this theme relative to the folder to use it e.g. `npm install ' +
|
|
62
|
-
theme +
|
|
63
|
-
'`',
|
|
64
|
-
);
|
|
80
|
+
console.log('You have to install this theme relative to the folder to use it e.g. `npm install ' + theme + '`');
|
|
65
81
|
process.exit();
|
|
66
82
|
}
|
|
67
83
|
};
|
|
68
84
|
|
|
69
85
|
async function createHtml(resumeJson, fileName, themePath, format, callback) {
|
|
70
|
-
const html = await
|
|
86
|
+
const html = await (0, _renderHtml.default)({
|
|
87
|
+
resume: resumeJson,
|
|
88
|
+
themePath
|
|
89
|
+
});
|
|
71
90
|
const pathToStream = path.resolve(process.cwd(), fileName + format);
|
|
72
91
|
await writeFile(pathToStream, ''); // workaround for https://github.com/streamich/unionfs/issues/428
|
|
73
|
-
|
|
92
|
+
|
|
93
|
+
const stream = _fs.default.createWriteStream(pathToStream);
|
|
94
|
+
|
|
74
95
|
stream.write(html, () => {
|
|
75
96
|
stream.close(callback);
|
|
76
97
|
});
|
|
77
98
|
}
|
|
99
|
+
|
|
78
100
|
const createPdf = (resumeJson, fileName, theme, format, callback) => {
|
|
79
101
|
(async () => {
|
|
80
102
|
const themePkg = getThemePkg(theme);
|
|
@@ -84,39 +106,37 @@ const createPdf = (resumeJson, fileName, theme, format, callback) => {
|
|
|
84
106
|
puppeteerLaunchArgs.push('--no-sandbox');
|
|
85
107
|
}
|
|
86
108
|
|
|
87
|
-
const html = await
|
|
109
|
+
const html = await (0, _renderHtml.default)({
|
|
110
|
+
resume: resumeJson,
|
|
111
|
+
themePath: theme
|
|
112
|
+
});
|
|
88
113
|
const browser = await puppeteer.launch({
|
|
89
|
-
args: puppeteerLaunchArgs
|
|
114
|
+
args: puppeteerLaunchArgs
|
|
90
115
|
});
|
|
91
116
|
const page = await browser.newPage();
|
|
117
|
+
await page.emulateMediaType(themePkg.pdfRenderOptions && themePkg.pdfRenderOptions.mediaType || 'screen');
|
|
118
|
+
await page.goto(`data:text/html;base64,${btoa(unescape(encodeURIComponent(html)))}`, {
|
|
119
|
+
waitUntil: 'networkidle0'
|
|
120
|
+
});
|
|
92
121
|
|
|
93
|
-
await page.emulateMediaType(
|
|
94
|
-
(themePkg.pdfRenderOptions && themePkg.pdfRenderOptions.mediaType) ||
|
|
95
|
-
'screen',
|
|
96
|
-
);
|
|
97
|
-
await page.goto(
|
|
98
|
-
`data:text/html;base64,${btoa(unescape(encodeURIComponent(html)))}`,
|
|
99
|
-
{ waitUntil: 'networkidle0' },
|
|
100
|
-
);
|
|
101
122
|
if (themePkg.pdfViewport) {
|
|
102
123
|
await page.setViewport(themePkg.pdfViewport);
|
|
103
124
|
}
|
|
125
|
+
|
|
104
126
|
await page.pdf({
|
|
105
127
|
path: fileName + format,
|
|
106
128
|
format: 'Letter',
|
|
107
129
|
printBackground: true,
|
|
108
|
-
...themePkg.pdfRenderOptions
|
|
130
|
+
...themePkg.pdfRenderOptions
|
|
109
131
|
});
|
|
110
|
-
|
|
111
132
|
await browser.close();
|
|
112
|
-
})()
|
|
113
|
-
.then(callback)
|
|
114
|
-
.catch(callback);
|
|
133
|
+
})().then(callback).catch(callback);
|
|
115
134
|
};
|
|
116
135
|
|
|
117
136
|
const getFileNameAndFormat = (fileName, format) => {
|
|
118
137
|
const fileFormatFound = extractFileFormat(fileName);
|
|
119
138
|
let fileFormatToUse = format;
|
|
139
|
+
|
|
120
140
|
if (format && fileFormatFound && format === fileFormatFound) {
|
|
121
141
|
fileName = fileName.substring(0, fileName.lastIndexOf('.'));
|
|
122
142
|
} else if (fileFormatFound) {
|
|
@@ -126,6 +146,6 @@ const getFileNameAndFormat = (fileName, format) => {
|
|
|
126
146
|
|
|
127
147
|
return {
|
|
128
148
|
fileName: fileName,
|
|
129
|
-
fileFormatToUse: fileFormatToUse
|
|
149
|
+
fileFormatToUse: fileFormatToUse
|
|
130
150
|
};
|
|
131
|
-
};
|
|
151
|
+
};
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.default = void 0;
|
|
7
|
+
|
|
8
|
+
var _fs = _interopRequireDefault(require("fs"));
|
|
9
|
+
|
|
10
|
+
var _mimeTypes = require("mime-types");
|
|
11
|
+
|
|
12
|
+
var _path = require("path");
|
|
13
|
+
|
|
14
|
+
var _quaff = _interopRequireDefault(require("quaff"));
|
|
15
|
+
|
|
16
|
+
var _streamToString = _interopRequireDefault(require("stream-to-string"));
|
|
17
|
+
|
|
18
|
+
var _yamlJs = _interopRequireDefault(require("yaml-js"));
|
|
19
|
+
|
|
20
|
+
var _util = require("util");
|
|
21
|
+
|
|
22
|
+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
23
|
+
|
|
24
|
+
const {
|
|
25
|
+
createReadStream
|
|
26
|
+
} = _fs.default;
|
|
27
|
+
const stat = (0, _util.promisify)(_fs.default.stat);
|
|
28
|
+
const parsers = {
|
|
29
|
+
'text/yaml': string => _yamlJs.default.load(string),
|
|
30
|
+
'application/json': string => JSON.parse(string)
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
var _default = async ({
|
|
34
|
+
path,
|
|
35
|
+
mime: inputMime
|
|
36
|
+
}) => {
|
|
37
|
+
let input;
|
|
38
|
+
let mime;
|
|
39
|
+
|
|
40
|
+
if ('-' === path) {
|
|
41
|
+
mime = inputMime || (0, _mimeTypes.lookup)('.json');
|
|
42
|
+
input = process.stdin;
|
|
43
|
+
} else if (path && (await stat(path)).isDirectory()) {
|
|
44
|
+
return (0, _quaff.default)(path);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
if (!input) {
|
|
48
|
+
mime = inputMime || (0, _mimeTypes.lookup)(path);
|
|
49
|
+
input = createReadStream((0, _path.resolve)(process.cwd(), path));
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
if (!input) {
|
|
53
|
+
throw new Error('resume could not be gotten from path or stdin');
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const resumeString = await (0, _streamToString.default)(input);
|
|
57
|
+
const parser = parsers[mime];
|
|
58
|
+
|
|
59
|
+
if (!parser) {
|
|
60
|
+
throw new Error(`no parser available for detected mime type ${mime}`);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
return parser(resumeString);
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
exports.default = _default;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.default = void 0;
|
|
7
|
+
|
|
8
|
+
var _fs = require("fs");
|
|
9
|
+
|
|
10
|
+
var _util = require("util");
|
|
11
|
+
|
|
12
|
+
const readFile = (0, _util.promisify)(_fs.readFile);
|
|
13
|
+
|
|
14
|
+
var _default = async ({
|
|
15
|
+
path: pathArg
|
|
16
|
+
} = {}) => {
|
|
17
|
+
let path = pathArg;
|
|
18
|
+
|
|
19
|
+
if (!path) {
|
|
20
|
+
path = require.resolve('resume-schema/schema.json');
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
return JSON.parse(await readFile(path, {
|
|
24
|
+
encoding: 'utf-8'
|
|
25
|
+
}));
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
exports.default = _default;
|
package/build/init.js
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.default = void 0;
|
|
7
|
+
|
|
8
|
+
var _util = require("util");
|
|
9
|
+
|
|
10
|
+
var _fs = _interopRequireDefault(require("fs"));
|
|
11
|
+
|
|
12
|
+
var _chalk = _interopRequireDefault(require("chalk"));
|
|
13
|
+
|
|
14
|
+
var _yesno = _interopRequireDefault(require("yesno"));
|
|
15
|
+
|
|
16
|
+
var _objectPathImmutable = require("object-path-immutable");
|
|
17
|
+
|
|
18
|
+
var _fileExists = _interopRequireDefault(require("file-exists"));
|
|
19
|
+
|
|
20
|
+
var _read = _interopRequireDefault(require("read"));
|
|
21
|
+
|
|
22
|
+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
23
|
+
|
|
24
|
+
const writeFile = (0, _util.promisify)(_fs.default.writeFile);
|
|
25
|
+
const read = (0, _util.promisify)(_read.default);
|
|
26
|
+
|
|
27
|
+
const resume = require('resume-schema/sample.resume.json');
|
|
28
|
+
|
|
29
|
+
var _default = async ({
|
|
30
|
+
resumePath
|
|
31
|
+
}) => {
|
|
32
|
+
if (await (0, _fileExists.default)(resumePath)) {
|
|
33
|
+
console.log(_chalk.default.yellow('There is already a resume.json file in this directory.'));
|
|
34
|
+
|
|
35
|
+
if (!(await (0, _yesno.default)({
|
|
36
|
+
question: 'Do you want to override?'
|
|
37
|
+
}))) {
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
console.log(`This utility will generate a file at ${resumePath}.`);
|
|
43
|
+
console.log('Fill out your name and email to get started, or leave the fields blank.');
|
|
44
|
+
console.log('All fields are optional.\n');
|
|
45
|
+
console.log('Press ^C at any time to quit.');
|
|
46
|
+
const name = await read({
|
|
47
|
+
prompt: 'name: '
|
|
48
|
+
});
|
|
49
|
+
const email = await read({
|
|
50
|
+
prompt: 'email: '
|
|
51
|
+
});
|
|
52
|
+
const personalizedResume = Object.entries({
|
|
53
|
+
name,
|
|
54
|
+
email
|
|
55
|
+
}).reduce((acc, [key, value]) => (0, _objectPathImmutable.set)(acc, `basics.${key}`, value), resume);
|
|
56
|
+
await writeFile(resumePath, JSON.stringify(personalizedResume, undefined, 2));
|
|
57
|
+
console.log(`Your resume has been created at ${resumePath}`);
|
|
58
|
+
console.log('');
|
|
59
|
+
console.log('To generate a formatted .html .md .txt or .pdf resume from your resume');
|
|
60
|
+
console.log('type: `resume export [someFileName]` including file extension eg: `resume export myresume.html`');
|
|
61
|
+
console.log('\nYou can optionally specify an available theme for html and pdf resumes using the --theme flag.');
|
|
62
|
+
console.log('Example: `resume export myresume.pdf --theme even`');
|
|
63
|
+
console.log('Or simply type: `resume export` and follow the prompts.');
|
|
64
|
+
console.log('');
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
exports.default = _default;
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.default = void 0;
|
|
7
|
+
|
|
8
|
+
const tryResolve = (...args) => {
|
|
9
|
+
try {
|
|
10
|
+
return require.resolve(...args);
|
|
11
|
+
} catch (err) {
|
|
12
|
+
return false;
|
|
13
|
+
}
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
var _default = async ({
|
|
17
|
+
resume,
|
|
18
|
+
themePath
|
|
19
|
+
}) => {
|
|
20
|
+
const cwd = process.cwd();
|
|
21
|
+
let path;
|
|
22
|
+
|
|
23
|
+
if (themePath[0] === '.') {
|
|
24
|
+
path = tryResolve(require('path').join(cwd, themePath), {
|
|
25
|
+
paths: [cwd]
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
if (!path) {
|
|
29
|
+
throw new Error(`Theme ${themePath} could not be resolved relative to ${cwd}`);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
if (!path) {
|
|
34
|
+
path = tryResolve(themePath, {
|
|
35
|
+
paths: [cwd]
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
if (!path && /^[a-z0-9]/i.test(path)) {
|
|
40
|
+
path = tryResolve(`jsonresume-theme-${themePath}`, {
|
|
41
|
+
paths: [cwd]
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
if (!path) {
|
|
46
|
+
throw new Error(`theme path ${themePath} could not be resolved from current working directory`);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const theme = require(path);
|
|
50
|
+
|
|
51
|
+
if (typeof (theme === null || theme === void 0 ? void 0 : theme.render) !== 'function') {
|
|
52
|
+
throw new Error('theme.render is not a function');
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
return theme.render(resume);
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
exports.default = _default;
|
package/{lib → build}/serve.js
RENAMED
|
@@ -1,6 +1,11 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
1
3
|
const fs = require('fs');
|
|
4
|
+
|
|
2
5
|
const path = require('path');
|
|
6
|
+
|
|
3
7
|
const readline = require('readline');
|
|
8
|
+
|
|
4
9
|
const bs = require('browser-sync').create();
|
|
5
10
|
|
|
6
11
|
const builder = require('./builder');
|
|
@@ -13,10 +18,11 @@ const reBuildResume = (theme, dir, resumeFilename, cb) => {
|
|
|
13
18
|
html = err;
|
|
14
19
|
}
|
|
15
20
|
|
|
16
|
-
fs.writeFile(path.join(process.cwd(), dir, 'index.html'), html,
|
|
21
|
+
fs.writeFile(path.join(process.cwd(), dir, 'index.html'), html, err => {
|
|
17
22
|
if (err) {
|
|
18
23
|
console.log(err);
|
|
19
24
|
}
|
|
25
|
+
|
|
20
26
|
cb();
|
|
21
27
|
});
|
|
22
28
|
});
|
|
@@ -27,7 +33,7 @@ module.exports = function ({
|
|
|
27
33
|
theme,
|
|
28
34
|
silent,
|
|
29
35
|
dir,
|
|
30
|
-
resumeFilename
|
|
36
|
+
resumeFilename
|
|
31
37
|
}) {
|
|
32
38
|
if (!fs.existsSync(dir)) {
|
|
33
39
|
fs.mkdirSync(dir);
|
|
@@ -43,13 +49,12 @@ module.exports = function ({
|
|
|
43
49
|
server: dir,
|
|
44
50
|
port: port,
|
|
45
51
|
open: !silent && 'local',
|
|
46
|
-
ui: false
|
|
52
|
+
ui: false
|
|
47
53
|
});
|
|
48
54
|
});
|
|
49
|
-
|
|
50
55
|
console.log('');
|
|
51
56
|
const previewUrl = 'http://localhost:' + port;
|
|
52
57
|
console.log('Preview: ' + previewUrl);
|
|
53
58
|
console.log('Press ctrl-c to stop');
|
|
54
59
|
console.log('');
|
|
55
|
-
};
|
|
60
|
+
};
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.default = void 0;
|
|
7
|
+
|
|
8
|
+
var _util = require("util");
|
|
9
|
+
|
|
10
|
+
var _zSchema = _interopRequireDefault(require("z-schema"));
|
|
11
|
+
|
|
12
|
+
var _zSchemaErrors = _interopRequireDefault(require("z-schema-errors"));
|
|
13
|
+
|
|
14
|
+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
15
|
+
|
|
16
|
+
const reporter = _zSchemaErrors.default.init();
|
|
17
|
+
|
|
18
|
+
const validator = new _zSchema.default();
|
|
19
|
+
const validate = (0, _util.promisify)((...args) => validator.validate(...args)); // maintains context
|
|
20
|
+
|
|
21
|
+
var _default = async ({
|
|
22
|
+
resume,
|
|
23
|
+
schema
|
|
24
|
+
}) => {
|
|
25
|
+
try {
|
|
26
|
+
return await validate(resume, schema);
|
|
27
|
+
} catch (errors) {
|
|
28
|
+
throw new Error(reporter.extractMessage({
|
|
29
|
+
report: {
|
|
30
|
+
errors
|
|
31
|
+
}
|
|
32
|
+
}));
|
|
33
|
+
}
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
exports.default = _default;
|
package/package.json
CHANGED
|
@@ -1,20 +1,19 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "resume-cli",
|
|
3
|
-
"version": "3.0.
|
|
3
|
+
"version": "3.0.6",
|
|
4
4
|
"description": "The JSON Resume command line interface",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"engines": {
|
|
7
7
|
"node": ">=10.18.1"
|
|
8
8
|
},
|
|
9
9
|
"files": [
|
|
10
|
-
"
|
|
11
|
-
"
|
|
10
|
+
"build/*",
|
|
11
|
+
"!test-utils",
|
|
12
|
+
"!*.test.js"
|
|
12
13
|
],
|
|
13
14
|
"scripts": {
|
|
14
15
|
"dev": "babel-node lib/main.js",
|
|
15
|
-
"
|
|
16
|
-
"format:check": "prettier --check .",
|
|
17
|
-
"lint": "eslint --ignore-path .gitignore lib",
|
|
16
|
+
"lint": "eslint --ignore-path .gitignore .",
|
|
18
17
|
"_postinstall": "husky install",
|
|
19
18
|
"prepublishOnly": "pinst --disable",
|
|
20
19
|
"postpublish": "pinst --enable",
|
|
@@ -51,21 +50,23 @@
|
|
|
51
50
|
"util.promisify": "^1.0.1",
|
|
52
51
|
"yaml-js": "^0.2.3",
|
|
53
52
|
"yesno": "^0.3.1",
|
|
54
|
-
"z-schema": "^
|
|
53
|
+
"z-schema": "^5.0.0",
|
|
55
54
|
"z-schema-errors": "^0.2.1"
|
|
56
55
|
},
|
|
57
56
|
"devDependencies": {
|
|
58
57
|
"@babel/cli": "7.12.10",
|
|
59
|
-
"@babel/core": "7.12.
|
|
58
|
+
"@babel/core": "7.12.10",
|
|
60
59
|
"@babel/eslint-parser": "7.12.1",
|
|
61
|
-
"@babel/node": "7.12.
|
|
60
|
+
"@babel/node": "7.12.10",
|
|
62
61
|
"@babel/plugin-proposal-optional-chaining": "7.12.7",
|
|
63
|
-
"@babel/preset-env": "7.12.
|
|
62
|
+
"@babel/preset-env": "7.12.11",
|
|
64
63
|
"babel-eslint": "10.1.0",
|
|
65
64
|
"babel-jest": "^26.6.3",
|
|
66
65
|
"dedent": "0.7.0",
|
|
67
|
-
"eslint": "7.
|
|
66
|
+
"eslint": "7.15.0",
|
|
67
|
+
"eslint-config-prettier": "7.0.0",
|
|
68
68
|
"eslint-plugin-jest": "24.1.3",
|
|
69
|
+
"eslint-plugin-prettier": "3.2.0",
|
|
69
70
|
"flat": "5.0.2",
|
|
70
71
|
"fs-monkey": "1.0.1",
|
|
71
72
|
"husky": "5.0.6",
|