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/lib/builder.js
DELETED
|
@@ -1,66 +0,0 @@
|
|
|
1
|
-
const themeServer =
|
|
2
|
-
process.env.THEME_SERVER || 'https://themes.jsonresume.org/theme/';
|
|
3
|
-
const fs = require('fs');
|
|
4
|
-
const request = require('superagent');
|
|
5
|
-
const chalk = require('chalk');
|
|
6
|
-
const renderHtml = require('./render-html');
|
|
7
|
-
|
|
8
|
-
const denormalizeTheme = (value) => {
|
|
9
|
-
return value.match(/jsonresume-theme-(.*)/)[1];
|
|
10
|
-
};
|
|
11
|
-
|
|
12
|
-
const sendExportHTML = (resumeJson, theme, callback) => {
|
|
13
|
-
console.log(resumeJson, theme);
|
|
14
|
-
console.log('Requesting theme from server...');
|
|
15
|
-
|
|
16
|
-
request
|
|
17
|
-
.post(themeServer + denormalizeTheme(theme))
|
|
18
|
-
.send({
|
|
19
|
-
resume: resumeJson,
|
|
20
|
-
})
|
|
21
|
-
.set('Accept', 'application/json')
|
|
22
|
-
.end((err, response) => {
|
|
23
|
-
if (err) {
|
|
24
|
-
callback(
|
|
25
|
-
'There was an error downloading your generated html resume from our server: ' +
|
|
26
|
-
err,
|
|
27
|
-
);
|
|
28
|
-
} else if (response.text) {
|
|
29
|
-
callback(null, response.text);
|
|
30
|
-
} else {
|
|
31
|
-
callback(
|
|
32
|
-
'There was an error downloading your generated html resume from our server.',
|
|
33
|
-
);
|
|
34
|
-
}
|
|
35
|
-
});
|
|
36
|
-
};
|
|
37
|
-
module.exports = function resumeBuilder(theme, dir, resumeFilename, cb) {
|
|
38
|
-
fs.readFile(resumeFilename, async (err, resumeJson) => {
|
|
39
|
-
if (err) {
|
|
40
|
-
console.log(chalk.yellow('Could not find:'), resumeFilename);
|
|
41
|
-
console.log(
|
|
42
|
-
chalk.cyan('Using example resume.json from resume-schema instead...'),
|
|
43
|
-
);
|
|
44
|
-
resumeJson = require('resume-schema').resumeJson;
|
|
45
|
-
} else {
|
|
46
|
-
try {
|
|
47
|
-
// todo: test resume schema
|
|
48
|
-
resumeJson = JSON.parse(resumeJson);
|
|
49
|
-
} catch (e) {
|
|
50
|
-
err = 'Parse error: ' + resumeFilename;
|
|
51
|
-
return cb(err);
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
try {
|
|
56
|
-
const html = await renderHtml({ resume: resumeJson, themePath: theme });
|
|
57
|
-
cb(null, html);
|
|
58
|
-
} catch (err) {
|
|
59
|
-
console.log(err);
|
|
60
|
-
console.log(
|
|
61
|
-
chalk.yellow('Could not run the render function from local theme.'),
|
|
62
|
-
);
|
|
63
|
-
sendExportHTML(resumeJson, theme, cb);
|
|
64
|
-
}
|
|
65
|
-
});
|
|
66
|
-
};
|
package/lib/get-resume.js
DELETED
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
import fs from 'fs';
|
|
2
|
-
import { lookup } from 'mime-types';
|
|
3
|
-
import { resolve as resolvePath } from 'path';
|
|
4
|
-
import quaff from 'quaff';
|
|
5
|
-
import toString from 'stream-to-string';
|
|
6
|
-
import yaml from 'yaml-js';
|
|
7
|
-
import { promisify } from 'util';
|
|
8
|
-
|
|
9
|
-
const { createReadStream } = fs;
|
|
10
|
-
const stat = promisify(fs.stat);
|
|
11
|
-
|
|
12
|
-
const parsers = {
|
|
13
|
-
'text/yaml': (string) => yaml.load(string),
|
|
14
|
-
'application/json': (string) => JSON.parse(string),
|
|
15
|
-
};
|
|
16
|
-
export default async ({ path, mime: inputMime }) => {
|
|
17
|
-
let input;
|
|
18
|
-
let mime;
|
|
19
|
-
if ('-' === path) {
|
|
20
|
-
mime = inputMime || lookup('.json');
|
|
21
|
-
input = process.stdin;
|
|
22
|
-
} else if (path && (await stat(path)).isDirectory()) {
|
|
23
|
-
return quaff(path);
|
|
24
|
-
}
|
|
25
|
-
if (!input) {
|
|
26
|
-
mime = inputMime || lookup(path);
|
|
27
|
-
input = createReadStream(resolvePath(process.cwd(), path));
|
|
28
|
-
}
|
|
29
|
-
if (!input) {
|
|
30
|
-
throw new Error('resume could not be gotten from path or stdin');
|
|
31
|
-
}
|
|
32
|
-
const resumeString = await toString(input);
|
|
33
|
-
const parser = parsers[mime];
|
|
34
|
-
if (!parser) {
|
|
35
|
-
throw new Error(`no parser available for detected mime type ${mime}`);
|
|
36
|
-
}
|
|
37
|
-
return parser(resumeString);
|
|
38
|
-
};
|
package/lib/get-resume.test.js
DELETED
|
@@ -1,73 +0,0 @@
|
|
|
1
|
-
import wait from 'waait';
|
|
2
|
-
import getResume from './get-resume';
|
|
3
|
-
import { stdin as mockStdin } from 'mock-stdin';
|
|
4
|
-
|
|
5
|
-
jest.mock('fs', () => {
|
|
6
|
-
const build = require('./test-utils/mocked-volume-builder');
|
|
7
|
-
const { createFsFromVolume } = require('memfs');
|
|
8
|
-
const vol = build();
|
|
9
|
-
return createFsFromVolume(vol);
|
|
10
|
-
});
|
|
11
|
-
|
|
12
|
-
describe('get-resume', () => {
|
|
13
|
-
it('should consume yaml', async () => {
|
|
14
|
-
expect(await getResume({ path: '/resume.yaml' })).toMatchInlineSnapshot(`
|
|
15
|
-
Object {
|
|
16
|
-
"basics": Object {
|
|
17
|
-
"email": "thomas@example.com",
|
|
18
|
-
"name": "thomas",
|
|
19
|
-
},
|
|
20
|
-
}
|
|
21
|
-
`);
|
|
22
|
-
});
|
|
23
|
-
it('should consume json', async () => {
|
|
24
|
-
expect(await getResume({ path: '/resume.json' })).toMatchInlineSnapshot(`
|
|
25
|
-
Object {
|
|
26
|
-
"basics": Object {
|
|
27
|
-
"email": "thomas@example.com",
|
|
28
|
-
"name": "thomas",
|
|
29
|
-
},
|
|
30
|
-
}
|
|
31
|
-
`);
|
|
32
|
-
});
|
|
33
|
-
it('should consume an entire directory as if it were a json object', async () => {
|
|
34
|
-
expect(await getResume({ path: '/quaff' })).toMatchInlineSnapshot(`
|
|
35
|
-
Object {
|
|
36
|
-
"basics": Object {
|
|
37
|
-
"email": "thomas@example.com",
|
|
38
|
-
"name": "thomas",
|
|
39
|
-
},
|
|
40
|
-
"work": Array [
|
|
41
|
-
Object {
|
|
42
|
-
"company": "Pied Piper",
|
|
43
|
-
"endDate": "2014-12-01",
|
|
44
|
-
"position": "CEO/President",
|
|
45
|
-
"startDate": "2013-12-01",
|
|
46
|
-
},
|
|
47
|
-
],
|
|
48
|
-
}
|
|
49
|
-
`);
|
|
50
|
-
});
|
|
51
|
-
it('should read from process.stdin when path is a dash', async () => {
|
|
52
|
-
const stdin = mockStdin();
|
|
53
|
-
const gotResume = getResume({ path: '-' });
|
|
54
|
-
await wait();
|
|
55
|
-
stdin.send(
|
|
56
|
-
JSON.stringify({
|
|
57
|
-
basics: {
|
|
58
|
-
name: 'thomas',
|
|
59
|
-
email: 'thomas@example.com',
|
|
60
|
-
},
|
|
61
|
-
}),
|
|
62
|
-
);
|
|
63
|
-
stdin.send(null);
|
|
64
|
-
expect(await gotResume).toMatchInlineSnapshot(`
|
|
65
|
-
Object {
|
|
66
|
-
"basics": Object {
|
|
67
|
-
"email": "thomas@example.com",
|
|
68
|
-
"name": "thomas",
|
|
69
|
-
},
|
|
70
|
-
}
|
|
71
|
-
`);
|
|
72
|
-
});
|
|
73
|
-
});
|
package/lib/get-schema.js
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import { readFile as readFileCB } from 'fs';
|
|
2
|
-
import { promisify } from 'util';
|
|
3
|
-
|
|
4
|
-
const readFile = promisify(readFileCB);
|
|
5
|
-
|
|
6
|
-
export default async ({ path: pathArg } = {}) => {
|
|
7
|
-
let path = pathArg;
|
|
8
|
-
if (!path) {
|
|
9
|
-
path = require.resolve('resume-schema/schema.json');
|
|
10
|
-
}
|
|
11
|
-
return JSON.parse(
|
|
12
|
-
await readFile(path, {
|
|
13
|
-
encoding: 'utf-8',
|
|
14
|
-
}),
|
|
15
|
-
);
|
|
16
|
-
};
|
package/lib/init.js
DELETED
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
import { promisify } from 'util';
|
|
2
|
-
import fs from 'fs';
|
|
3
|
-
import chalk from 'chalk';
|
|
4
|
-
import yesno from 'yesno';
|
|
5
|
-
import { set } from 'object-path-immutable';
|
|
6
|
-
import exists from 'file-exists';
|
|
7
|
-
import readCB from 'read';
|
|
8
|
-
|
|
9
|
-
const writeFile = promisify(fs.writeFile);
|
|
10
|
-
const read = promisify(readCB);
|
|
11
|
-
const resume = require('resume-schema/sample.resume.json');
|
|
12
|
-
|
|
13
|
-
export default async ({ resumePath }) => {
|
|
14
|
-
if (await exists(resumePath)) {
|
|
15
|
-
console.log(
|
|
16
|
-
chalk.yellow('There is already a resume.json file in this directory.'),
|
|
17
|
-
);
|
|
18
|
-
if (!(await yesno({ question: 'Do you want to override?' }))) {
|
|
19
|
-
return;
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
console.log(`This utility will generate a file at ${resumePath}.`);
|
|
23
|
-
console.log(
|
|
24
|
-
'Fill out your name and email to get started, or leave the fields blank.',
|
|
25
|
-
);
|
|
26
|
-
console.log('All fields are optional.\n');
|
|
27
|
-
console.log('Press ^C at any time to quit.');
|
|
28
|
-
|
|
29
|
-
const name = await read({
|
|
30
|
-
prompt: 'name: ',
|
|
31
|
-
});
|
|
32
|
-
const email = await read({
|
|
33
|
-
prompt: 'email: ',
|
|
34
|
-
});
|
|
35
|
-
|
|
36
|
-
const personalizedResume = Object.entries({
|
|
37
|
-
name,
|
|
38
|
-
email,
|
|
39
|
-
}).reduce((acc, [key, value]) => set(acc, `basics.${key}`, value), resume);
|
|
40
|
-
await writeFile(resumePath, JSON.stringify(personalizedResume, undefined, 2));
|
|
41
|
-
|
|
42
|
-
console.log(`Your resume has been created at ${resumePath}`);
|
|
43
|
-
console.log('');
|
|
44
|
-
console.log(
|
|
45
|
-
'To generate a formatted .html .md .txt or .pdf resume from your resume',
|
|
46
|
-
);
|
|
47
|
-
console.log(
|
|
48
|
-
'type: `resume export [someFileName]` including file extension eg: `resume export myresume.html`',
|
|
49
|
-
);
|
|
50
|
-
console.log(
|
|
51
|
-
'\nYou can optionally specify an available theme for html and pdf resumes using the --theme flag.',
|
|
52
|
-
);
|
|
53
|
-
console.log('Example: `resume export myresume.pdf --theme even`');
|
|
54
|
-
console.log('Or simply type: `resume export` and follow the prompts.');
|
|
55
|
-
console.log('');
|
|
56
|
-
};
|
package/lib/main.js
DELETED
|
@@ -1,136 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
import 'dotenv/config';
|
|
4
|
-
|
|
5
|
-
import init from './init';
|
|
6
|
-
import getResume from './get-resume';
|
|
7
|
-
import getSchema from './get-schema';
|
|
8
|
-
import validate from './validate';
|
|
9
|
-
|
|
10
|
-
const pkg = require('../package.json');
|
|
11
|
-
const exportResume = require('./export-resume');
|
|
12
|
-
const serve = require('./serve');
|
|
13
|
-
const program = require('commander');
|
|
14
|
-
const chalk = require('chalk');
|
|
15
|
-
const path = require('path');
|
|
16
|
-
|
|
17
|
-
const normalizeTheme = (value, defaultValue) => {
|
|
18
|
-
const theme = value || defaultValue;
|
|
19
|
-
// TODO - This is not great, but bypasses this function if it is a relative path
|
|
20
|
-
if (theme[0] === '.') {
|
|
21
|
-
return theme;
|
|
22
|
-
}
|
|
23
|
-
return theme.match('jsonresume-theme-.*')
|
|
24
|
-
? theme
|
|
25
|
-
: `jsonresume-theme-${theme}`;
|
|
26
|
-
};
|
|
27
|
-
|
|
28
|
-
(async () => {
|
|
29
|
-
program
|
|
30
|
-
.name('resume')
|
|
31
|
-
.usage('[command] [options]')
|
|
32
|
-
.version(pkg.version)
|
|
33
|
-
.option(
|
|
34
|
-
'-F, --force',
|
|
35
|
-
'Used by `publish` and `export` - bypasses schema testing.',
|
|
36
|
-
)
|
|
37
|
-
.option(
|
|
38
|
-
'-t, --theme <theme name>',
|
|
39
|
-
'Specify theme used by `export` and `serve` or specify a path starting with . (use . for current directory or ../some/other/dir)',
|
|
40
|
-
normalizeTheme,
|
|
41
|
-
'jsonresume-theme-even',
|
|
42
|
-
)
|
|
43
|
-
.option('-f, --format <file type extension>', 'Used by `export`.')
|
|
44
|
-
.option(
|
|
45
|
-
'-r, --resume <resume filename>',
|
|
46
|
-
"path to the resume in json format. Use '-' to read from stdin",
|
|
47
|
-
'resume.json',
|
|
48
|
-
)
|
|
49
|
-
.option('-p, --port <port>', 'Used by `serve` (default: 4000)', 4000)
|
|
50
|
-
.option(
|
|
51
|
-
'-s, --silent',
|
|
52
|
-
'Used by `serve` to tell it if open browser auto or not.',
|
|
53
|
-
false,
|
|
54
|
-
)
|
|
55
|
-
.option(
|
|
56
|
-
'-d, --dir <path>',
|
|
57
|
-
'Used by `serve` to indicate a public directory path.',
|
|
58
|
-
'public',
|
|
59
|
-
)
|
|
60
|
-
.option(
|
|
61
|
-
'--schema <relativePath>',
|
|
62
|
-
'Used by `validate` to validate against a custom schema.',
|
|
63
|
-
);
|
|
64
|
-
|
|
65
|
-
program
|
|
66
|
-
.command('init')
|
|
67
|
-
.description('Initialize a resume.json file')
|
|
68
|
-
.action(async () => {
|
|
69
|
-
await init({ resumePath: program.resume });
|
|
70
|
-
});
|
|
71
|
-
|
|
72
|
-
program
|
|
73
|
-
.command('validate')
|
|
74
|
-
.description("Validate your resume's schema")
|
|
75
|
-
.action(async () => {
|
|
76
|
-
const resume = await getResume({ path: program.resume });
|
|
77
|
-
const schema = await getSchema({ path: program.schema });
|
|
78
|
-
try {
|
|
79
|
-
await validate({
|
|
80
|
-
resume,
|
|
81
|
-
schema,
|
|
82
|
-
});
|
|
83
|
-
} catch (e) {
|
|
84
|
-
console.error(e.message);
|
|
85
|
-
process.exitCode = 1;
|
|
86
|
-
}
|
|
87
|
-
});
|
|
88
|
-
|
|
89
|
-
program
|
|
90
|
-
.command('export [fileName]')
|
|
91
|
-
.description(
|
|
92
|
-
'Export locally to .html or .pdf. Supply a --format <file format> flag and argument to specify export format.',
|
|
93
|
-
)
|
|
94
|
-
.action(async (fileName) => {
|
|
95
|
-
const resume = await getResume({ path: program.resume });
|
|
96
|
-
exportResume(
|
|
97
|
-
{ ...program, resume, fileName },
|
|
98
|
-
(err, fileName, format) => {
|
|
99
|
-
console.log(
|
|
100
|
-
chalk.green(
|
|
101
|
-
'\nDone! Find your new',
|
|
102
|
-
format,
|
|
103
|
-
'resume at:\n',
|
|
104
|
-
path.resolve(process.cwd(), fileName + format),
|
|
105
|
-
),
|
|
106
|
-
);
|
|
107
|
-
},
|
|
108
|
-
);
|
|
109
|
-
});
|
|
110
|
-
|
|
111
|
-
program
|
|
112
|
-
.command('serve')
|
|
113
|
-
.description('Serve resume at http://localhost:4000/')
|
|
114
|
-
.action(async () => {
|
|
115
|
-
serve({
|
|
116
|
-
...program,
|
|
117
|
-
resumeFilename: program.resume,
|
|
118
|
-
});
|
|
119
|
-
});
|
|
120
|
-
|
|
121
|
-
await program.parseAsync(process.argv);
|
|
122
|
-
|
|
123
|
-
const validCommands = program.commands.map((cmd) => {
|
|
124
|
-
return cmd._name;
|
|
125
|
-
});
|
|
126
|
-
|
|
127
|
-
// https://github.com/tj/commander.js/blob/master/CHANGELOG.md#testing-for-no-arguments
|
|
128
|
-
if (program.rawArgs.length < 3) {
|
|
129
|
-
console.log(chalk.cyan('resume-cli:'), 'https://jsonresume.org', '\n');
|
|
130
|
-
program.help();
|
|
131
|
-
} else if (validCommands.indexOf(process.argv[2]) === -1) {
|
|
132
|
-
console.log(chalk.red('Invalid argument:'), process.argv[2]);
|
|
133
|
-
console.log(chalk.cyan('resume-cli:'), 'https://jsonresume.org', '\n');
|
|
134
|
-
program.help();
|
|
135
|
-
}
|
|
136
|
-
})();
|
package/lib/main.test.js
DELETED
|
@@ -1,155 +0,0 @@
|
|
|
1
|
-
import { spawn, exec as execCB } from 'child_process';
|
|
2
|
-
import streamToString from 'stream-to-string';
|
|
3
|
-
import { promisify } from 'util';
|
|
4
|
-
import packageJson from '../package.json';
|
|
5
|
-
|
|
6
|
-
const exec = promisify(execCB);
|
|
7
|
-
|
|
8
|
-
const run = async (argv, { waitForVolumeExport = true, stdin = '' } = {}) => {
|
|
9
|
-
let volume;
|
|
10
|
-
let exitCode;
|
|
11
|
-
const child = spawn(
|
|
12
|
-
process.execPath,
|
|
13
|
-
['build/test-utils/cli-test-entry.js', ...argv],
|
|
14
|
-
{
|
|
15
|
-
stdio: ['pipe', 'pipe', 2, 'ipc'],
|
|
16
|
-
},
|
|
17
|
-
);
|
|
18
|
-
const allChecks = Promise.all([
|
|
19
|
-
waitForVolumeExport
|
|
20
|
-
? new Promise((volumeSet) => {
|
|
21
|
-
child.on('message', async (message) => {
|
|
22
|
-
if (message.type === 'volumeExport') {
|
|
23
|
-
volume = message.data;
|
|
24
|
-
volumeSet();
|
|
25
|
-
}
|
|
26
|
-
});
|
|
27
|
-
})
|
|
28
|
-
: true,
|
|
29
|
-
new Promise((processExited) => {
|
|
30
|
-
child.on('exit', (code) => {
|
|
31
|
-
exitCode = code;
|
|
32
|
-
processExited();
|
|
33
|
-
});
|
|
34
|
-
}),
|
|
35
|
-
]);
|
|
36
|
-
child.stdin.write(stdin);
|
|
37
|
-
child.stdin.end();
|
|
38
|
-
const stdout = await streamToString(child.stdout);
|
|
39
|
-
await allChecks;
|
|
40
|
-
return {
|
|
41
|
-
volume,
|
|
42
|
-
code: exitCode,
|
|
43
|
-
stdout,
|
|
44
|
-
};
|
|
45
|
-
};
|
|
46
|
-
|
|
47
|
-
describe('cli configuration', () => {
|
|
48
|
-
beforeAll(() => exec(packageJson.scripts.prepare));
|
|
49
|
-
it('should show help', async () => {
|
|
50
|
-
const { stdout } = await run(['help'], { waitForVolumeExport: false });
|
|
51
|
-
expect(stdout).toMatchInlineSnapshot(`
|
|
52
|
-
"Usage: resume [command] [options]
|
|
53
|
-
|
|
54
|
-
Options:
|
|
55
|
-
-V, --version output the version number
|
|
56
|
-
-F, --force Used by \`publish\` and \`export\` - bypasses
|
|
57
|
-
schema testing.
|
|
58
|
-
-t, --theme <theme name> Specify theme used by \`export\` and
|
|
59
|
-
\`serve\` or specify a path starting with .
|
|
60
|
-
(use . for current directory or
|
|
61
|
-
../some/other/dir) (default:
|
|
62
|
-
\\"jsonresume-theme-even\\")
|
|
63
|
-
-f, --format <file type extension> Used by \`export\`.
|
|
64
|
-
-r, --resume <resume filename> path to the resume in json format. Use
|
|
65
|
-
'-' to read from stdin (default:
|
|
66
|
-
\\"resume.json\\")
|
|
67
|
-
-p, --port <port> Used by \`serve\` (default: 4000) (default:
|
|
68
|
-
4000)
|
|
69
|
-
-s, --silent Used by \`serve\` to tell it if open
|
|
70
|
-
browser auto or not. (default: false)
|
|
71
|
-
-d, --dir <path> Used by \`serve\` to indicate a public
|
|
72
|
-
directory path. (default: \\"public\\")
|
|
73
|
-
--schema <relativePath> Used by \`validate\` to validate against a
|
|
74
|
-
custom schema.
|
|
75
|
-
-h, --help display help for command
|
|
76
|
-
|
|
77
|
-
Commands:
|
|
78
|
-
init Initialize a resume.json file
|
|
79
|
-
validate Validate your resume's schema
|
|
80
|
-
export [fileName] Export locally to .html or .pdf. Supply
|
|
81
|
-
a --format <file format> flag and
|
|
82
|
-
argument to specify export format.
|
|
83
|
-
serve Serve resume at http://localhost:4000/
|
|
84
|
-
help [command] display help for command
|
|
85
|
-
"
|
|
86
|
-
`);
|
|
87
|
-
});
|
|
88
|
-
describe('validate', () => {
|
|
89
|
-
it('should use the schema override arg', async () => {
|
|
90
|
-
const { stdout } = await run([
|
|
91
|
-
'validate',
|
|
92
|
-
'--schema',
|
|
93
|
-
'/test-resumes/only-number-schema.json',
|
|
94
|
-
'--resume',
|
|
95
|
-
'/test-resumes/only-number.json',
|
|
96
|
-
]);
|
|
97
|
-
expect(stdout).toMatchInlineSnapshot(`""`);
|
|
98
|
-
});
|
|
99
|
-
it('should fail when trying to validate an invalid resume specified by the --resume option', async () => {
|
|
100
|
-
expect(
|
|
101
|
-
(
|
|
102
|
-
await run([
|
|
103
|
-
'validate',
|
|
104
|
-
'--resume',
|
|
105
|
-
'/test-resumes/invalid-resume.json',
|
|
106
|
-
])
|
|
107
|
-
).code,
|
|
108
|
-
).toEqual(1);
|
|
109
|
-
});
|
|
110
|
-
it('should validate a resume specified by the --resume option', async () => {
|
|
111
|
-
const { stdout } = await run([
|
|
112
|
-
'validate',
|
|
113
|
-
'--resume',
|
|
114
|
-
'/test-resumes/resume.json',
|
|
115
|
-
]);
|
|
116
|
-
expect(stdout).toMatchInlineSnapshot(`""`);
|
|
117
|
-
});
|
|
118
|
-
});
|
|
119
|
-
describe('export', () => {
|
|
120
|
-
it('should read from stdin when path is a dash', async () => {
|
|
121
|
-
const { stdout, volume } = await run(
|
|
122
|
-
[
|
|
123
|
-
'export',
|
|
124
|
-
'/test-resumes/exported-resume-from-stdin.html',
|
|
125
|
-
'--resume',
|
|
126
|
-
'-', // this is the dash
|
|
127
|
-
],
|
|
128
|
-
{ stdin: JSON.stringify({ basics: { name: 'thomas-from-stdin' } }) },
|
|
129
|
-
);
|
|
130
|
-
expect(volume['/test-resumes/exported-resume-from-stdin.html']).toEqual(
|
|
131
|
-
expect.stringContaining('thomas-from-stdin'),
|
|
132
|
-
);
|
|
133
|
-
expect(stdout).toMatchInlineSnapshot(`
|
|
134
|
-
"
|
|
135
|
-
Done! Find your new .html resume at:
|
|
136
|
-
/test-resumes/exported-resume-from-stdin.html
|
|
137
|
-
"
|
|
138
|
-
`);
|
|
139
|
-
});
|
|
140
|
-
it('should export a resume from the path specified by --resume to the path specified immediately after the export command', async () => {
|
|
141
|
-
const { stdout } = await run([
|
|
142
|
-
'export',
|
|
143
|
-
'/test-resumes/exported-resume.html',
|
|
144
|
-
'--resume',
|
|
145
|
-
'/test-resumes/resume.json',
|
|
146
|
-
]);
|
|
147
|
-
expect(stdout).toMatchInlineSnapshot(`
|
|
148
|
-
"
|
|
149
|
-
Done! Find your new .html resume at:
|
|
150
|
-
/test-resumes/exported-resume.html
|
|
151
|
-
"
|
|
152
|
-
`);
|
|
153
|
-
});
|
|
154
|
-
});
|
|
155
|
-
});
|
package/lib/render-html.js
DELETED
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
const tryResolve = (...args) => {
|
|
2
|
-
try {
|
|
3
|
-
return require.resolve(...args);
|
|
4
|
-
} catch (err) {
|
|
5
|
-
return false;
|
|
6
|
-
}
|
|
7
|
-
};
|
|
8
|
-
|
|
9
|
-
export default async ({ resume, themePath }) => {
|
|
10
|
-
const cwd = process.cwd();
|
|
11
|
-
let path;
|
|
12
|
-
if (themePath[0] === '.') {
|
|
13
|
-
path = tryResolve(path.join(cwd, themePath), { paths: [cwd] });
|
|
14
|
-
throw new Error(
|
|
15
|
-
`Theme ${themePath} could not be resolved relative to ${cwd}`,
|
|
16
|
-
);
|
|
17
|
-
}
|
|
18
|
-
if (!path) {
|
|
19
|
-
path = tryResolve(themePath, { paths: [cwd] });
|
|
20
|
-
}
|
|
21
|
-
if (!path && /^[a-z0-9]/i.test(path)) {
|
|
22
|
-
path = tryResolve(`jsonresume-theme-${themePath}`, { paths: [cwd] });
|
|
23
|
-
}
|
|
24
|
-
if (!path) {
|
|
25
|
-
throw new Error(
|
|
26
|
-
`theme path ${themePath} could not be resolved from current working directory`,
|
|
27
|
-
);
|
|
28
|
-
}
|
|
29
|
-
const theme = require(path);
|
|
30
|
-
if (typeof theme?.render !== 'function') {
|
|
31
|
-
throw new Error('theme.render is not a function');
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
return theme.render(resume);
|
|
35
|
-
};
|
package/lib/render-html.test.js
DELETED
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
import renderHTML from './render-html';
|
|
2
|
-
|
|
3
|
-
describe('renderHTML', () => {
|
|
4
|
-
beforeAll(() => {
|
|
5
|
-
const originalRequireResolve = require.resolve;
|
|
6
|
-
const mockThemePath = 'mock/path/to/jsonresume-theme-even';
|
|
7
|
-
require.resolve = (...args) => {
|
|
8
|
-
if (args[0] === 'jsonresume-theme-even') {
|
|
9
|
-
return mockThemePath;
|
|
10
|
-
}
|
|
11
|
-
if (args[0] === 'jsonresume-theme-even') {
|
|
12
|
-
return mockThemePath;
|
|
13
|
-
}
|
|
14
|
-
return originalRequireResolve.apply(require, ...args);
|
|
15
|
-
};
|
|
16
|
-
require.cache[mockThemePath] = {
|
|
17
|
-
render: () => 'here-is-your-mocked-theme',
|
|
18
|
-
};
|
|
19
|
-
});
|
|
20
|
-
const resume = {
|
|
21
|
-
basics: {
|
|
22
|
-
name: 'test',
|
|
23
|
-
label: 'Programmer',
|
|
24
|
-
email: 'test4@test.com',
|
|
25
|
-
},
|
|
26
|
-
};
|
|
27
|
-
|
|
28
|
-
it('should reject when theme is not availlable', async () => {
|
|
29
|
-
await expect(
|
|
30
|
-
renderHTML({ resume, themePath: 'unknown' }),
|
|
31
|
-
).rejects.toBeTruthy();
|
|
32
|
-
});
|
|
33
|
-
|
|
34
|
-
describe('should render html when theme is availlable', () => {
|
|
35
|
-
it('with long theme name', async () => {
|
|
36
|
-
expect(
|
|
37
|
-
await renderHTML({ resume, themePath: 'jsonresume-theme-even' }),
|
|
38
|
-
).toStartWith('<!doctype html>');
|
|
39
|
-
});
|
|
40
|
-
|
|
41
|
-
it('with short theme name', async () => {
|
|
42
|
-
expect(await renderHTML({ resume, themePath: 'even' })).toStartWith(
|
|
43
|
-
'<!doctype html>',
|
|
44
|
-
);
|
|
45
|
-
});
|
|
46
|
-
});
|
|
47
|
-
});
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import build from './mocked-volume-builder';
|
|
2
|
-
import { patchFs } from 'fs-monkey';
|
|
3
|
-
import { ufs } from 'unionfs';
|
|
4
|
-
import * as fs from 'fs';
|
|
5
|
-
|
|
6
|
-
const mockVolume = build({ mount: '/test-resumes' });
|
|
7
|
-
const vol = ufs.use(mockVolume).use(fs);
|
|
8
|
-
patchFs(vol);
|
|
9
|
-
require('../main.js');
|
|
10
|
-
process.once('beforeExit', () => {
|
|
11
|
-
process.send({ data: mockVolume.toJSON(), type: 'volumeExport' });
|
|
12
|
-
});
|
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
module.exports = ({ mount = '/' } = {}) => {
|
|
2
|
-
const dedent = require('dedent');
|
|
3
|
-
const flat = require('flat');
|
|
4
|
-
const { Volume } = require('memfs');
|
|
5
|
-
return Volume.fromJSON(
|
|
6
|
-
flat(
|
|
7
|
-
{
|
|
8
|
-
'only-number-schema.json': JSON.stringify({ type: 'number' }),
|
|
9
|
-
'only-number.json': '123',
|
|
10
|
-
'invalid-resume.json': JSON.stringify({
|
|
11
|
-
notAValidKey: {
|
|
12
|
-
foo: 'bar',
|
|
13
|
-
},
|
|
14
|
-
}),
|
|
15
|
-
'resume.json': JSON.stringify({
|
|
16
|
-
basics: {
|
|
17
|
-
name: 'thomas',
|
|
18
|
-
email: 'thomas@example.com',
|
|
19
|
-
},
|
|
20
|
-
}),
|
|
21
|
-
'resume.yaml': dedent`
|
|
22
|
-
basics:
|
|
23
|
-
name: thomas
|
|
24
|
-
email: thomas@example.com
|
|
25
|
-
`,
|
|
26
|
-
quaff: {
|
|
27
|
-
'basics.yaml': dedent`
|
|
28
|
-
name: thomas
|
|
29
|
-
email: thomas@example.com
|
|
30
|
-
`,
|
|
31
|
-
'work.json': JSON.stringify([
|
|
32
|
-
{
|
|
33
|
-
company: 'Pied Piper',
|
|
34
|
-
endDate: '2014-12-01',
|
|
35
|
-
position: 'CEO/President',
|
|
36
|
-
startDate: '2013-12-01',
|
|
37
|
-
},
|
|
38
|
-
]),
|
|
39
|
-
},
|
|
40
|
-
},
|
|
41
|
-
{ delimiter: '/' },
|
|
42
|
-
),
|
|
43
|
-
mount,
|
|
44
|
-
);
|
|
45
|
-
};
|