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 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
- | test | Schema validation test your `resume.json` |
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 test`
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.
@@ -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
- import renderHTML from './render-html';
2
- import { promisify } from 'util';
3
- import fs from 'fs';
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
- { resume: resumeJson, fileName, theme, format },
12
- callback,
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, (error) => {
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, (error) => {
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 = (fileName) => {
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 = (theme) => {
67
+ const getThemePkg = theme => {
52
68
  if (theme[0] === '.') {
53
- theme = path.join(process.cwd(), theme, 'index.js');
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 renderHTML({ resume: resumeJson, themePath });
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
- const stream = fs.createWriteStream(pathToStream);
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 renderHTML(resumeJson, theme);
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;
@@ -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, (err) => {
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.2",
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
- "index.js",
11
- "lib/*"
10
+ "build/*",
11
+ "!test-utils",
12
+ "!*.test.js"
12
13
  ],
13
14
  "scripts": {
14
15
  "dev": "babel-node lib/main.js",
15
- "format": "prettier --write .",
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": "^4.2.3",
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.9",
58
+ "@babel/core": "7.12.10",
60
59
  "@babel/eslint-parser": "7.12.1",
61
- "@babel/node": "7.12.6",
60
+ "@babel/node": "7.12.10",
62
61
  "@babel/plugin-proposal-optional-chaining": "7.12.7",
63
- "@babel/preset-env": "7.12.10",
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.14.0",
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",