resuml 1.20.1 → 2.0.0
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/DOCS.md +314 -0
- package/README.md +7 -2
- package/dist/{chunk-KRJMZ2RQ.js → chunk-GRIYYG45.js} +242 -2
- package/dist/chunk-GRIYYG45.js.map +1 -0
- package/dist/index.d.ts +422 -3
- package/dist/index.js +119 -54
- package/dist/index.js.map +1 -1
- package/dist/mcp/server.js +4 -8
- package/dist/mcp/server.js.map +1 -1
- package/package.json +26 -52
- package/dist/api.d.ts +0 -9
- package/dist/api.js +0 -20
- package/dist/api.js.map +0 -1
- package/dist/chunk-4ZOTZUAW.js +0 -6666
- package/dist/chunk-4ZOTZUAW.js.map +0 -1
- package/dist/chunk-JP7UCR3P.js +0 -182
- package/dist/chunk-JP7UCR3P.js.map +0 -1
- package/dist/chunk-KRJMZ2RQ.js.map +0 -1
- package/dist/chunk-ZLA7NFYP.js +0 -90
- package/dist/chunk-ZLA7NFYP.js.map +0 -1
- package/dist/index-yHdKpxms.d.ts +0 -422
- package/dist/themeLoader-ZGWEGYXG.js +0 -7
- package/dist/themeLoader-ZGWEGYXG.js.map +0 -1
- package/scripts/build-builder.js +0 -25
- package/scripts/build-skills-db.js +0 -314
- package/scripts/bundle-themes.js +0 -1104
- package/scripts/dev-server.js +0 -392
- package/scripts/enrich-themes-manifest.mjs +0 -156
- package/scripts/generate-types.cjs +0 -55
- package/scripts/mcp-call.mjs +0 -99
- package/scripts/quick-bundle.cjs +0 -129
- package/scripts/render-theme-thumbs.mjs +0 -117
- package/scripts/test-mcp.mjs +0 -583
package/dist/index.js
CHANGED
|
@@ -1,30 +1,95 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
3
|
-
loadResumeFiles
|
|
4
|
-
} from "./chunk-4ZOTZUAW.js";
|
|
5
2
|
import {
|
|
6
3
|
KNOWN_THEMES,
|
|
4
|
+
__export,
|
|
5
|
+
analyzeAts,
|
|
7
6
|
generateResumeYaml,
|
|
8
7
|
getInstalledVersion,
|
|
9
|
-
isThemeInstalled
|
|
10
|
-
|
|
11
|
-
import {
|
|
12
|
-
analyzeAts,
|
|
8
|
+
isThemeInstalled,
|
|
9
|
+
loadTheme,
|
|
13
10
|
processResumeData
|
|
14
|
-
} from "./chunk-
|
|
15
|
-
import {
|
|
16
|
-
__export,
|
|
17
|
-
loadTheme
|
|
18
|
-
} from "./chunk-ZLA7NFYP.js";
|
|
11
|
+
} from "./chunk-GRIYYG45.js";
|
|
19
12
|
|
|
20
13
|
// src/index.ts
|
|
21
14
|
import { Command } from "commander";
|
|
22
|
-
import
|
|
23
|
-
import
|
|
15
|
+
import path6 from "path";
|
|
16
|
+
import fs9 from "fs";
|
|
24
17
|
import { fileURLToPath } from "url";
|
|
25
18
|
|
|
26
19
|
// src/commands/validate.ts
|
|
27
|
-
import
|
|
20
|
+
import fs3 from "fs";
|
|
21
|
+
|
|
22
|
+
// src/utils/loadResume.ts
|
|
23
|
+
import fs2 from "fs/promises";
|
|
24
|
+
import YAML from "yaml";
|
|
25
|
+
|
|
26
|
+
// src/utils/fileUtils.ts
|
|
27
|
+
import fs from "fs/promises";
|
|
28
|
+
import path from "path";
|
|
29
|
+
import { glob } from "glob";
|
|
30
|
+
async function findInputFiles(inputPath) {
|
|
31
|
+
if (!inputPath) {
|
|
32
|
+
return [];
|
|
33
|
+
}
|
|
34
|
+
if (inputPath.includes("*")) {
|
|
35
|
+
try {
|
|
36
|
+
const matchedFiles = await glob(inputPath);
|
|
37
|
+
if (matchedFiles.length === 0) {
|
|
38
|
+
throw new Error(`No files found matching pattern: ${inputPath}`);
|
|
39
|
+
}
|
|
40
|
+
return matchedFiles;
|
|
41
|
+
} catch (err) {
|
|
42
|
+
throw new Error(`Error matching files: ${err instanceof Error ? err.message : String(err)}`);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
try {
|
|
46
|
+
const stat = await fs.stat(inputPath);
|
|
47
|
+
if (stat.isFile()) {
|
|
48
|
+
return [inputPath];
|
|
49
|
+
} else if (stat.isDirectory()) {
|
|
50
|
+
const pattern = path.join(inputPath, "*.{yaml,yml}");
|
|
51
|
+
try {
|
|
52
|
+
const yamlFiles = await glob(pattern);
|
|
53
|
+
if (yamlFiles.length === 0) {
|
|
54
|
+
throw new Error(`No YAML files found in directory: ${inputPath}`);
|
|
55
|
+
}
|
|
56
|
+
return yamlFiles;
|
|
57
|
+
} catch (_) {
|
|
58
|
+
throw new Error(`No YAML files found in directory: ${inputPath}`);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
} catch (e) {
|
|
62
|
+
if (e instanceof Error && e.message.includes("ENOENT")) {
|
|
63
|
+
throw new Error("Input path not found");
|
|
64
|
+
}
|
|
65
|
+
throw e;
|
|
66
|
+
}
|
|
67
|
+
return [];
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// src/utils/loadResume.ts
|
|
71
|
+
async function loadResumeFiles(inputPath) {
|
|
72
|
+
const files = await findInputFiles(inputPath);
|
|
73
|
+
if (files.length === 0) {
|
|
74
|
+
throw new Error("No resume files found");
|
|
75
|
+
}
|
|
76
|
+
const yamlContents = [];
|
|
77
|
+
for (const file of files) {
|
|
78
|
+
try {
|
|
79
|
+
const content = await fs2.readFile(file, "utf-8");
|
|
80
|
+
const parsed = YAML.parse(content);
|
|
81
|
+
if (parsed && typeof parsed === "object") {
|
|
82
|
+
yamlContents.push(content);
|
|
83
|
+
}
|
|
84
|
+
} catch (error) {
|
|
85
|
+
throw new Error(`Failed to parse ${file}: ${error.message}`);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
if (yamlContents.length === 0) {
|
|
89
|
+
throw new Error("No valid data found in any of the input files");
|
|
90
|
+
}
|
|
91
|
+
return { files, yamlContents };
|
|
92
|
+
}
|
|
28
93
|
|
|
29
94
|
// src/utils/errorHandler.ts
|
|
30
95
|
function handleCommandError(error, command, debug = false) {
|
|
@@ -36,8 +101,8 @@ function handleCommandError(error, command, debug = false) {
|
|
|
36
101
|
if (debug) {
|
|
37
102
|
console.error("\nValidation failed with the following errors:");
|
|
38
103
|
errors.forEach((err, index) => {
|
|
39
|
-
const
|
|
40
|
-
console.error(`${index + 1}. Path: ${
|
|
104
|
+
const path7 = err.instancePath || "root";
|
|
105
|
+
console.error(`${index + 1}. Path: ${path7}`);
|
|
41
106
|
console.error(` Error: ${err.message || "Unknown validation error"}`);
|
|
42
107
|
if (err.params) {
|
|
43
108
|
console.error(` Params: ${JSON.stringify(err.params)}`);
|
|
@@ -47,8 +112,8 @@ function handleCommandError(error, command, debug = false) {
|
|
|
47
112
|
console.error("\nSome validation errors were found:");
|
|
48
113
|
const maxErrors = 5;
|
|
49
114
|
errors.slice(0, maxErrors).forEach((err, index) => {
|
|
50
|
-
const
|
|
51
|
-
console.error(`${index + 1}. Field: ${
|
|
115
|
+
const path7 = err.instancePath || "root";
|
|
116
|
+
console.error(`${index + 1}. Field: ${path7}`);
|
|
52
117
|
console.error(` Error: ${err.message || "Unknown validation error"}`);
|
|
53
118
|
});
|
|
54
119
|
if (errors.length > maxErrors) {
|
|
@@ -137,7 +202,7 @@ async function validateAction(options) {
|
|
|
137
202
|
let jobDescription;
|
|
138
203
|
if (options.jd) {
|
|
139
204
|
try {
|
|
140
|
-
jobDescription =
|
|
205
|
+
jobDescription = fs3.readFileSync(options.jd, "utf8");
|
|
141
206
|
} catch {
|
|
142
207
|
console.error(chalk6.red(`Failed to read job description file: ${options.jd}`));
|
|
143
208
|
return;
|
|
@@ -165,7 +230,7 @@ ATS score ${result.score} is below threshold ${threshold}.`));
|
|
|
165
230
|
}
|
|
166
231
|
|
|
167
232
|
// src/commands/tojson.ts
|
|
168
|
-
import
|
|
233
|
+
import fs4 from "fs";
|
|
169
234
|
async function toJsonAction(options) {
|
|
170
235
|
const chalk6 = (await import("chalk")).default;
|
|
171
236
|
console.log(chalk6.blue("Starting resuml tojson..."));
|
|
@@ -176,7 +241,7 @@ async function toJsonAction(options) {
|
|
|
176
241
|
const resumeData = await processResumeData(yamlContents);
|
|
177
242
|
console.log(chalk6.green("Processing and validation successful!"));
|
|
178
243
|
const jsonOutput = JSON.stringify(resumeData, null, 2);
|
|
179
|
-
|
|
244
|
+
fs4.writeFileSync(options.output, jsonOutput, "utf8");
|
|
180
245
|
console.log(chalk6.green(`Successfully wrote output to ${options.output}`));
|
|
181
246
|
} catch (error) {
|
|
182
247
|
handleCommandError(error, "tojson", options.debug);
|
|
@@ -184,8 +249,8 @@ async function toJsonAction(options) {
|
|
|
184
249
|
}
|
|
185
250
|
|
|
186
251
|
// src/commands/render.ts
|
|
187
|
-
import
|
|
188
|
-
import
|
|
252
|
+
import fs5 from "fs";
|
|
253
|
+
import path2 from "path";
|
|
189
254
|
import chalk from "chalk";
|
|
190
255
|
async function renderAction(options) {
|
|
191
256
|
if (!options.theme) {
|
|
@@ -225,12 +290,12 @@ async function renderAction(options) {
|
|
|
225
290
|
}
|
|
226
291
|
});
|
|
227
292
|
await browser.close();
|
|
228
|
-
|
|
293
|
+
fs5.writeFileSync(outputPath, pdfBuffer);
|
|
229
294
|
console.log(chalk.green(`Successfully wrote PDF output to ${outputPath}`));
|
|
230
295
|
} else {
|
|
231
296
|
console.log(chalk.blue(`Writing HTML output to ${outputPath}...`));
|
|
232
|
-
|
|
233
|
-
|
|
297
|
+
fs5.mkdirSync(path2.dirname(outputPath), { recursive: true });
|
|
298
|
+
fs5.writeFileSync(outputPath, htmlOutput, "utf8");
|
|
234
299
|
console.log(chalk.green(`Successfully wrote HTML output to ${outputPath}`));
|
|
235
300
|
}
|
|
236
301
|
} catch (error) {
|
|
@@ -239,8 +304,8 @@ async function renderAction(options) {
|
|
|
239
304
|
}
|
|
240
305
|
|
|
241
306
|
// src/commands/dev.ts
|
|
242
|
-
import
|
|
243
|
-
import
|
|
307
|
+
import fs6 from "fs";
|
|
308
|
+
import path3 from "path";
|
|
244
309
|
import chalk2 from "chalk";
|
|
245
310
|
async function devAction(options) {
|
|
246
311
|
if (!options.theme) {
|
|
@@ -258,11 +323,11 @@ async function devAction(options) {
|
|
|
258
323
|
await renderResume(options);
|
|
259
324
|
console.log(chalk2.green(`\u{1F680} Development server running at http://localhost:${port}`));
|
|
260
325
|
console.log(chalk2.blue("Watching for file changes..."));
|
|
261
|
-
if (
|
|
326
|
+
if (fs6.existsSync(inputPath) && fs6.statSync(inputPath).isDirectory()) {
|
|
262
327
|
watchDirectory(inputPath, () => {
|
|
263
328
|
void renderResume(options);
|
|
264
329
|
});
|
|
265
|
-
} else if (
|
|
330
|
+
} else if (fs6.existsSync(inputPath)) {
|
|
266
331
|
watchFile(inputPath, () => {
|
|
267
332
|
void renderResume(options);
|
|
268
333
|
});
|
|
@@ -285,16 +350,16 @@ async function renderResume(options) {
|
|
|
285
350
|
const htmlOutput = await theme.render(resumeData, {
|
|
286
351
|
locale: options.language
|
|
287
352
|
});
|
|
288
|
-
const outputPath =
|
|
289
|
-
|
|
290
|
-
|
|
353
|
+
const outputPath = path3.join(process.cwd(), ".resuml-dev", "index.html");
|
|
354
|
+
fs6.mkdirSync(path3.dirname(outputPath), { recursive: true });
|
|
355
|
+
fs6.writeFileSync(outputPath, htmlOutput, "utf8");
|
|
291
356
|
console.log(chalk2.green("\u2705 Resume updated!"));
|
|
292
357
|
} catch (error) {
|
|
293
358
|
console.error(chalk2.red("\u274C Error rendering resume:"), error.message);
|
|
294
359
|
}
|
|
295
360
|
}
|
|
296
361
|
function watchDirectory(dirPath, callback) {
|
|
297
|
-
|
|
362
|
+
fs6.watch(dirPath, { recursive: true }, (_eventType, filename) => {
|
|
298
363
|
if (filename && (filename.endsWith(".yaml") || filename.endsWith(".yml"))) {
|
|
299
364
|
console.log(chalk2.blue(`\u{1F4C1} File changed: ${filename}`));
|
|
300
365
|
callback();
|
|
@@ -302,9 +367,9 @@ function watchDirectory(dirPath, callback) {
|
|
|
302
367
|
});
|
|
303
368
|
}
|
|
304
369
|
function watchFile(filePath, callback) {
|
|
305
|
-
|
|
370
|
+
fs6.watch(filePath, (eventType) => {
|
|
306
371
|
if (eventType === "change") {
|
|
307
|
-
console.log(chalk2.blue(`\u{1F4C4} File changed: ${
|
|
372
|
+
console.log(chalk2.blue(`\u{1F4C4} File changed: ${path3.basename(filePath)}`));
|
|
308
373
|
callback();
|
|
309
374
|
}
|
|
310
375
|
});
|
|
@@ -316,9 +381,9 @@ async function startDevServer(port) {
|
|
|
316
381
|
const parsedUrl = url.parse(req.url || "", true);
|
|
317
382
|
const pathname = parsedUrl.pathname || "/";
|
|
318
383
|
if (pathname === "/" || pathname === "/index.html") {
|
|
319
|
-
const htmlPath =
|
|
320
|
-
if (
|
|
321
|
-
const html =
|
|
384
|
+
const htmlPath = path3.join(process.cwd(), ".resuml-dev", "index.html");
|
|
385
|
+
if (fs6.existsSync(htmlPath)) {
|
|
386
|
+
const html = fs6.readFileSync(htmlPath, "utf8");
|
|
322
387
|
const liveReloadScript = `
|
|
323
388
|
<script>
|
|
324
389
|
setInterval(() => {
|
|
@@ -351,8 +416,8 @@ async function startDevServer(port) {
|
|
|
351
416
|
}
|
|
352
417
|
|
|
353
418
|
// src/commands/init.ts
|
|
354
|
-
import
|
|
355
|
-
import
|
|
419
|
+
import fs7 from "fs";
|
|
420
|
+
import path4 from "path";
|
|
356
421
|
import readline from "readline";
|
|
357
422
|
import chalk3 from "chalk";
|
|
358
423
|
function createReadlineInterface() {
|
|
@@ -371,10 +436,10 @@ function ask(rl, question, defaultValue) {
|
|
|
371
436
|
}
|
|
372
437
|
async function initAction(options) {
|
|
373
438
|
const outputPath = options.output || "resume.yaml";
|
|
374
|
-
const fullPath =
|
|
439
|
+
const fullPath = path4.resolve(outputPath);
|
|
375
440
|
const rl = createReadlineInterface();
|
|
376
441
|
try {
|
|
377
|
-
if (
|
|
442
|
+
if (fs7.existsSync(fullPath)) {
|
|
378
443
|
const overwrite = await ask(
|
|
379
444
|
rl,
|
|
380
445
|
`${chalk3.yellow("\u26A0")} ${outputPath} already exists. Overwrite? (y/N)`,
|
|
@@ -390,8 +455,8 @@ async function initAction(options) {
|
|
|
390
455
|
const email = await ask(rl, "Email address", "john@example.com");
|
|
391
456
|
const label = await ask(rl, "Professional title/label", "Software Engineer");
|
|
392
457
|
const yaml = generateResumeYaml(name, email, label);
|
|
393
|
-
|
|
394
|
-
|
|
458
|
+
fs7.mkdirSync(path4.dirname(fullPath), { recursive: true });
|
|
459
|
+
fs7.writeFileSync(fullPath, yaml, "utf8");
|
|
395
460
|
console.log(chalk3.green(`
|
|
396
461
|
\u2705 Created ${outputPath}`));
|
|
397
462
|
console.log(chalk3.blue("\nNext steps:"));
|
|
@@ -404,8 +469,8 @@ async function initAction(options) {
|
|
|
404
469
|
}
|
|
405
470
|
|
|
406
471
|
// src/commands/pdf.ts
|
|
407
|
-
import
|
|
408
|
-
import
|
|
472
|
+
import fs8 from "fs";
|
|
473
|
+
import path5 from "path";
|
|
409
474
|
import chalk4 from "chalk";
|
|
410
475
|
async function loadPlaywright() {
|
|
411
476
|
try {
|
|
@@ -466,8 +531,8 @@ async function pdfAction(options) {
|
|
|
466
531
|
printBackground: true,
|
|
467
532
|
preferCSSPageSize: true
|
|
468
533
|
});
|
|
469
|
-
|
|
470
|
-
|
|
534
|
+
fs8.mkdirSync(path5.dirname(path5.resolve(outputPath)), { recursive: true });
|
|
535
|
+
fs8.writeFileSync(outputPath, pdfBuffer);
|
|
471
536
|
console.log(chalk4.green(`\u2705 Successfully generated ${outputPath}`));
|
|
472
537
|
} finally {
|
|
473
538
|
await browser.close();
|
|
@@ -591,12 +656,12 @@ function injectCss(html, css) {
|
|
|
591
656
|
}
|
|
592
657
|
|
|
593
658
|
// src/index.ts
|
|
594
|
-
var currentDir =
|
|
659
|
+
var currentDir = path6.dirname(fileURLToPath(import.meta.url));
|
|
595
660
|
function getCliVersion() {
|
|
596
|
-
const packageJsonPath =
|
|
597
|
-
if (
|
|
661
|
+
const packageJsonPath = path6.resolve(currentDir, "../package.json");
|
|
662
|
+
if (fs9.existsSync(packageJsonPath)) {
|
|
598
663
|
try {
|
|
599
|
-
const packageJson = JSON.parse(
|
|
664
|
+
const packageJson = JSON.parse(fs9.readFileSync(packageJsonPath, "utf8"));
|
|
600
665
|
return packageJson.version ?? "0.0.0";
|
|
601
666
|
} catch {
|
|
602
667
|
return "0.0.0";
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/commands/validate.ts","../src/utils/errorHandler.ts","../src/commands/tojson.ts","../src/commands/render.ts","../src/commands/dev.ts","../src/commands/init.ts","../src/commands/pdf.ts","../src/commands/themes.ts","../src/commands/mcp.ts","../src/utils/themeRender.ts"],"sourcesContent":["#!/usr/bin/env node\n\nimport { Command } from 'commander';\nimport path from 'path';\nimport fs from 'fs';\nimport { fileURLToPath } from 'url';\nimport { validateAction } from './commands/validate';\nimport { toJsonAction } from './commands/tojson';\nimport { renderAction } from './commands/render';\nimport { devAction } from './commands/dev';\nimport { initAction } from './commands/init';\nimport { pdfAction } from './commands/pdf';\nimport { themesAction } from './commands/themes';\nimport { mcpAction } from './commands/mcp';\n\n// Get the directory name equivalent to __dirname in CommonJS\nconst currentDir = path.dirname(fileURLToPath(import.meta.url));\n\nfunction getCliVersion(): string {\n const packageJsonPath = path.resolve(currentDir, '../package.json');\n if (fs.existsSync(packageJsonPath)) {\n try {\n const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8')) as { version?: string };\n return packageJson.version ?? '0.0.0';\n } catch {\n return '0.0.0';\n }\n }\n return '0.0.0';\n}\n\nexport const program = new Command();\n\nprogram\n .name('resuml')\n .description('CLI tool for managing resuml resume files.')\n .version(getCliVersion());\n\n// Validate Command\nprogram\n .command('validate')\n .description('Validates resume data against the schema.')\n .option('-r, --resume <path>', 'Input YAML file, directory, or glob pattern.')\n .option('--debug', 'Show detailed validation errors.')\n .option('--ats', 'Run ATS (Applicant Tracking System) compatibility analysis.')\n .option('--jd <path>', 'Path to a job description file for keyword matching (requires --ats).')\n .option('--ats-threshold <score>', 'Minimum ATS score (0-100). Exit with code 1 if below threshold.')\n .option('--format <type>', 'Output format for ATS results (text or json).', 'text')\n .action(validateAction);\n\n// ToJSON Command\nprogram\n .command('tojson')\n .description('Converts YAML resume data to JSON format.')\n .option('-r, --resume <path>', 'Input YAML file, directory, or glob pattern.')\n .option('-o, --output <file>', 'Output JSON file path.', 'resume.json')\n .option('--debug', 'Show detailed validation and processing information.')\n .action(toJsonAction);\n\n// Render Command\nprogram\n .command('render')\n .description('Renders the resume data using a specified theme.')\n .option('-r, --resume <path>', 'Input YAML file, directory, or glob pattern.')\n .option('-t, --theme <name>', 'Theme name (e.g., stackoverflow, react).')\n .option('-o, --output <file>', 'Output file path.')\n .option('--format <type>', 'Output format (html or pdf).', 'html')\n .option('--language <code>', 'Language code for localization.', 'en')\n .option('--debug', 'Show detailed validation and processing information.')\n .action(renderAction);\n\n// Dev Command\nprogram\n .command('dev')\n .description('Start development server with hot-reload.')\n .option('-r, --resume <path>', 'Input YAML file, directory, or glob pattern.')\n .option('-t, --theme <name>', 'Theme name (e.g., stackoverflow, react).')\n .option('--port <number>', 'Port for development server.', '3000')\n .option('--language <code>', 'Language code for localization.', 'en')\n .option('--debug', 'Show detailed validation and processing information.')\n .action(devAction);\n\n// Init Command\nprogram\n .command('init')\n .description('Scaffold a starter resume.yaml file with all sections.')\n .option('-o, --output <file>', 'Output YAML file path.', 'resume.yaml')\n .action(initAction);\n\n// PDF Command\nprogram\n .command('pdf')\n .description('Export resume as PDF using Playwright.')\n .option('-r, --resume <path>', 'Input YAML file, directory, or glob pattern.')\n .option('-t, --theme <name>', 'Theme name (e.g., stackoverflow, react).')\n .option('-o, --output <file>', 'Output PDF file path.', 'resume.pdf')\n .option('--language <code>', 'Language code for localization.', 'en')\n .option('--format <size>', 'Page format: A4 or Letter.', 'A4')\n .option('--margin <values>', 'Page margins (e.g., \"10mm\" or \"10mm,15mm,10mm,15mm\").')\n .option('--debug', 'Show detailed validation and processing information.')\n .action(pdfAction);\n\n// Themes Command\nprogram\n .command('themes')\n .description('List available JSON Resume themes and install them.')\n .option('--install <name>', 'Install a theme by name (e.g., stackoverflow, elegant).')\n .action(themesAction);\n\n// MCP Server Command\nprogram\n .command('mcp')\n .description('Start MCP server for AI agent integration (stdio transport).')\n .action(mcpAction);\n\n// Parse Arguments - only execute when not in test environment\nif (process.env['NODE_ENV'] !== 'test') {\n void (async () => {\n try {\n await program.parseAsync(process.argv);\n } catch (e: unknown) {\n console.error('Command line error:', (e as Error).message);\n process.exit(1);\n }\n })();\n}\n\nexport { processResumeData } from './core';\nexport { loadResumeFiles } from './utils/loadResume';\nexport { loadTheme } from './utils/themeLoader';\nexport * as themeRender from './utils/themeRender';\nexport { analyzeAts } from './ats/index';\nexport type { AtsResult, AtsOptions } from './ats/index';\n","import fs from 'fs';\nimport { processResumeData } from '../core';\nimport { loadResumeFiles } from '../utils/loadResume';\nimport { handleCommandError } from '../utils/errorHandler';\nimport { analyzeAts } from '../ats/index';\nimport type { AtsResult, AtsCheck } from '../ats/index';\n\ninterface ValidateCommandOptions {\n resume?: string;\n debug?: boolean;\n ats?: boolean;\n jd?: string;\n atsThreshold?: string;\n format?: string;\n}\n\nfunction formatAtsReport(result: AtsResult, debug: boolean, chalk: typeof import('chalk').default): void {\n const scoreColor = result.score >= 75 ? chalk.green : result.score >= 60 ? chalk.yellow : chalk.red;\n console.log('');\n console.log(chalk.bold('═══ ATS Analysis Report ═══'));\n console.log('');\n console.log(` Score: ${scoreColor(chalk.bold(`${result.score}/100`))} (${result.rating.replace('-', ' ')})`);\n console.log(` ${result.summary}`);\n console.log('');\n\n // Group checks by category\n const categories: Record<string, AtsCheck[]> = {};\n for (const check of result.checks) {\n const list = categories[check.category];\n if (!list) {\n categories[check.category] = [check];\n } else {\n list.push(check);\n }\n }\n\n const categoryLabels: Record<string, string> = {\n contact: 'Contact Information',\n content: 'Content Quality',\n structure: 'Resume Structure',\n keywords: 'Keywords',\n };\n\n for (const [cat, checks] of Object.entries(categories)) {\n const label = categoryLabels[cat] || cat;\n console.log(chalk.bold(` ${label}`));\n\n for (const check of checks) {\n if (!debug && check.passed) continue; // In normal mode, only show failures\n const icon = check.passed ? chalk.green('✓') : chalk.red('✗');\n const scoreText = chalk.dim(`[${check.score}]`);\n console.log(` ${icon} ${check.message} ${scoreText}`);\n if (!check.passed && check.suggestion) {\n console.log(chalk.dim(` → ${check.suggestion}`));\n }\n }\n console.log('');\n }\n\n // JD keyword section\n if (result.keywords) {\n console.log(chalk.bold(' Job Description Match'));\n const kw = result.keywords;\n const matchColor = kw.matchPercentage >= 70 ? chalk.green : kw.matchPercentage >= 50 ? chalk.yellow : chalk.red;\n console.log(` Match: ${matchColor(`${kw.matchPercentage}%`)} (${kw.matched.length}/${kw.matched.length + kw.missing.length} keywords)`);\n if (kw.matched.length > 0) {\n console.log(chalk.green(` ✓ Matched: ${kw.matched.join(', ')}`));\n }\n if (kw.missing.length > 0) {\n console.log(chalk.red(` ✗ Missing: ${kw.missing.join(', ')}`));\n console.log(chalk.dim(' → Consider incorporating these keywords into your resume where relevant.'));\n }\n console.log('');\n }\n\n console.log(chalk.dim('═══════════════════════════'));\n}\n\nexport async function validateAction(options: ValidateCommandOptions): Promise<void> {\n const chalk = (await import('chalk')).default;\n console.log(chalk.blue('Starting resuml validate...'));\n\n try {\n const inputPath = options.resume;\n const { yamlContents } = await loadResumeFiles(inputPath);\n\n console.log(chalk.blue('Validating resume data...'));\n\n let resumeData;\n try {\n resumeData = await processResumeData(yamlContents);\n console.log(chalk.green('✓ Resume data is valid against the schema!'));\n } catch (error: unknown) {\n handleCommandError(error, 'validate', options.debug);\n return;\n }\n\n // Run ATS analysis if requested\n if (options.ats) {\n console.log(chalk.blue('Running ATS analysis...'));\n\n let jobDescription: string | undefined;\n if (options.jd) {\n try {\n jobDescription = fs.readFileSync(options.jd, 'utf8');\n } catch {\n console.error(chalk.red(`Failed to read job description file: ${options.jd}`));\n return;\n }\n }\n\n const result = analyzeAts(resumeData, {\n language: 'en',\n jobDescription,\n });\n\n if (options.format === 'json') {\n console.log(JSON.stringify(result, null, 2));\n } else {\n formatAtsReport(result, !!options.debug, chalk);\n }\n\n // Check threshold\n const threshold = options.atsThreshold ? parseInt(options.atsThreshold, 10) : undefined;\n if (threshold !== undefined && result.score < threshold) {\n console.error(chalk.red(`\\nATS score ${result.score} is below threshold ${threshold}.`));\n process.exit(1);\n }\n }\n } catch (error: unknown) {\n handleCommandError(error, 'validate', options.debug);\n }\n}\n","interface ValidationErrorDetail {\n instancePath?: string;\n message?: string;\n params?: Record<string, unknown>;\n // Add other properties from Ajv error objects if needed\n}\n\ninterface SchemaValidationError extends Error {\n errors?: ValidationErrorDetail[];\n}\n\n/**\n * Handle command errors, displaying useful information to the user\n */\nexport function handleCommandError(error: unknown, command: string, debug: boolean = false): void {\n const errorMessage = error instanceof Error ? error.message : String(error);\n console.error(`❌ Error during ${command} command: ${errorMessage}`);\n\n // Handle validation errors from core\n const potentialValidationError = error as SchemaValidationError;\n if (\n potentialValidationError instanceof Error &&\n potentialValidationError.name === 'SchemaValidationError' &&\n Array.isArray(potentialValidationError.errors)\n ) {\n const errors: ValidationErrorDetail[] = potentialValidationError.errors;\n\n if (debug) {\n // Show detailed errors with all information in debug mode\n console.error('\\nValidation failed with the following errors:');\n errors.forEach((err: ValidationErrorDetail, index: number) => {\n const path = err.instancePath || 'root';\n console.error(`${index + 1}. Path: ${path}`);\n console.error(` Error: ${err.message || 'Unknown validation error'}`);\n if (err.params) {\n console.error(` Params: ${JSON.stringify(err.params)}`);\n }\n });\n } else {\n // Show a more concise error message in normal mode\n console.error('\\nSome validation errors were found:');\n // Show a limited number of errors to avoid overwhelming output\n const maxErrors = 5;\n errors.slice(0, maxErrors).forEach((err: ValidationErrorDetail, index: number) => {\n const path = err.instancePath || 'root';\n console.error(`${index + 1}. Field: ${path}`);\n console.error(` Error: ${err.message || 'Unknown validation error'}`);\n });\n\n if (errors.length > maxErrors) {\n console.error(`\\n...and ${errors.length - maxErrors} more errors.`);\n console.error('Use the --debug flag for complete error details.');\n }\n }\n }\n\n // Only exit if not in a test environment where exit might disrupt the test runner\n if (process.env['NODE_ENV'] !== 'test') {\n process.exit(1);\n }\n}\n","import fs from 'fs';\nimport { processResumeData } from '../core';\nimport { loadResumeFiles } from '../utils/loadResume';\nimport { handleCommandError } from '../utils/errorHandler';\n\ninterface ToJsonOptions {\n resume?: string;\n output: string;\n debug?: boolean;\n}\n\nexport async function toJsonAction(options: ToJsonOptions): Promise<void> {\n const chalk = (await import('chalk')).default;\n console.log(chalk.blue('Starting resuml tojson...'));\n\n try {\n const inputPath = options.resume;\n const { yamlContents } = await loadResumeFiles(inputPath);\n\n console.log(chalk.blue('Processing and validating data...'));\n const resumeData = await processResumeData(yamlContents);\n console.log(chalk.green('Processing and validation successful!'));\n\n // Generate JSON output\n const jsonOutput = JSON.stringify(resumeData, null, 2);\n fs.writeFileSync(options.output, jsonOutput, 'utf8');\n console.log(chalk.green(`Successfully wrote output to ${options.output}`));\n } catch (error: unknown) {\n handleCommandError(error, 'tojson', options.debug);\n }\n}\n","import fs from 'fs';\nimport path from 'node:path';\nimport { processResumeData } from '../core';\nimport { loadResumeFiles } from '../utils/loadResume';\nimport { loadTheme } from '../utils/themeLoader';\nimport { handleCommandError } from '../utils/errorHandler';\nimport chalk from 'chalk';\n\ninterface RenderCommandOptions {\n resume?: string;\n theme?: string;\n output?: string;\n format: 'html' | 'pdf';\n language: string;\n debug?: boolean;\n}\n\nexport async function renderAction(options: RenderCommandOptions): Promise<void> {\n if (!options.theme) {\n throw new Error(\n '--theme option is required. Please specify a theme name (e.g., stackoverflow, react).'\n );\n }\n\n console.log(chalk.blue('Starting resuml render...'));\n\n try {\n const inputPath = options.resume;\n const { yamlContents } = await loadResumeFiles(inputPath);\n\n console.log(chalk.blue('Processing and validating resume data...'));\n const resumeData = await processResumeData(yamlContents);\n console.log(chalk.green('Resume data processing and validation successful!'));\n\n const theme = loadTheme(options.theme);\n\n const htmlOutput = await theme.render(resumeData, {\n locale: options.language,\n });\n\n const defaultExtension = options.format;\n const defaultFilename = `resume.${defaultExtension}`;\n const outputPath = options.output || defaultFilename;\n\n if (options.format === 'pdf') { // eslint-disable-line @typescript-eslint/no-unnecessary-condition\n console.log(chalk.blue(`Generating PDF output at ${outputPath}...`));\n const { chromium } = await import('playwright');\n const browser = await chromium.launch();\n const page = await browser.newPage();\n await page.setContent(htmlOutput, { waitUntil: 'networkidle' });\n const pdfBuffer = await page.pdf({\n path: outputPath,\n format: 'A4',\n printBackground: true,\n margin: {\n top: '1cm',\n right: '1cm',\n bottom: '1cm',\n left: '1cm',\n },\n });\n await browser.close();\n fs.writeFileSync(outputPath, pdfBuffer);\n console.log(chalk.green(`Successfully wrote PDF output to ${outputPath}`));\n } else {\n console.log(chalk.blue(`Writing HTML output to ${outputPath}...`));\n fs.mkdirSync(path.dirname(outputPath), { recursive: true });\n fs.writeFileSync(outputPath, htmlOutput, 'utf8');\n console.log(chalk.green(`Successfully wrote HTML output to ${outputPath}`));\n }\n } catch (error: unknown) {\n handleCommandError(error, 'render', options.debug);\n }\n}\n","import fs from 'fs';\nimport path from 'node:path';\nimport { processResumeData } from '../core';\nimport { loadResumeFiles } from '../utils/loadResume';\nimport { loadTheme } from '../utils/themeLoader';\nimport { handleCommandError } from '../utils/errorHandler';\nimport chalk from 'chalk';\n\ninterface DevCommandOptions {\n resume?: string;\n theme?: string;\n port?: number;\n language: string;\n debug?: boolean;\n}\n\nexport async function devAction(options: DevCommandOptions): Promise<void> {\n if (!options.theme) {\n throw new Error(\n '--theme option is required. Please specify a theme name (e.g., stackoverflow, react).'\n );\n }\n\n console.log(chalk.blue('Starting resuml development server...'));\n\n const port = options.port || 3000;\n const inputPath = options.resume;\n\n if (!inputPath) {\n throw new Error('Resume path is required. Use -r or --resume option.');\n }\n\n try {\n // Initial render\n await renderResume(options);\n\n console.log(chalk.green(`🚀 Development server running at http://localhost:${port}`));\n console.log(chalk.blue('Watching for file changes...'));\n\n // Watch for file changes if inputPath is a directory\n if (fs.existsSync(inputPath) && fs.statSync(inputPath).isDirectory()) {\n watchDirectory(inputPath, () => { void renderResume(options); });\n } else if (fs.existsSync(inputPath)) {\n watchFile(inputPath, () => { void renderResume(options); });\n }\n\n // Simple HTTP server\n await startDevServer(port);\n } catch (error: unknown) {\n handleCommandError(error, 'dev', options.debug);\n }\n}\n\nasync function renderResume(options: DevCommandOptions): Promise<void> {\n try {\n const inputPath = options.resume;\n if (!inputPath) {\n throw new Error('Resume path is required');\n }\n\n const { yamlContents } = await loadResumeFiles(inputPath);\n\n console.log(chalk.blue('🔄 Processing resume data...'));\n const resumeData = await processResumeData(yamlContents);\n\n const theme = loadTheme(options.theme ?? 'stackoverflow');\n\n const htmlOutput = await theme.render(resumeData, {\n locale: options.language,\n });\n\n // Write to a temp directory for the dev server\n const outputPath = path.join(process.cwd(), '.resuml-dev', 'index.html');\n fs.mkdirSync(path.dirname(outputPath), { recursive: true });\n fs.writeFileSync(outputPath, htmlOutput, 'utf8');\n\n console.log(chalk.green('✅ Resume updated!'));\n } catch (error: unknown) {\n console.error(chalk.red('❌ Error rendering resume:'), (error as Error).message);\n }\n}\n\nfunction watchDirectory(dirPath: string, callback: () => void): void {\n fs.watch(dirPath, { recursive: true }, (_eventType, filename) => {\n if (filename && (filename.endsWith('.yaml') || filename.endsWith('.yml'))) {\n console.log(chalk.blue(`📁 File changed: ${filename}`));\n callback();\n }\n });\n}\n\nfunction watchFile(filePath: string, callback: () => void): void {\n fs.watch(filePath, (eventType) => {\n if (eventType === 'change') {\n console.log(chalk.blue(`📄 File changed: ${path.basename(filePath)}`));\n callback();\n }\n });\n}\n\nasync function startDevServer(port: number): Promise<void> {\n // Simple HTTP server implementation\n const http = await import('http');\n const url = await import('url');\n\n const server = http.createServer((req, res) => {\n const parsedUrl = url.parse(req.url || '', true);\n const pathname = parsedUrl.pathname || '/';\n\n if (pathname === '/' || pathname === '/index.html') {\n const htmlPath = path.join(process.cwd(), '.resuml-dev', 'index.html');\n\n if (fs.existsSync(htmlPath)) {\n const html = fs.readFileSync(htmlPath, 'utf8');\n\n // Inject live reload script\n const liveReloadScript = `\n <script>\n setInterval(() => {\n fetch('/health').then(() => {\n location.reload();\n }).catch(() => {\n // Server might be restarting\n });\n }, 1000);\n </script>\n `;\n\n const modifiedHtml = html.replace('</body>', `${liveReloadScript}</body>`);\n\n res.writeHead(200, { 'Content-Type': 'text/html' });\n res.end(modifiedHtml);\n } else {\n res.writeHead(404, { 'Content-Type': 'text/plain' });\n res.end('Resume not found. Make sure to provide a valid resume path.');\n }\n } else if (pathname === '/health') {\n res.writeHead(200, { 'Content-Type': 'application/json' });\n res.end('{\"status\":\"ok\"}');\n } else {\n res.writeHead(404, { 'Content-Type': 'text/plain' });\n res.end('Not found');\n }\n });\n\n server.listen(port, () => {\n console.log(chalk.green(`🌐 Server listening on port ${port}`));\n });\n}\n","import fs from 'fs';\nimport path from 'path';\nimport readline from 'readline';\nimport chalk from 'chalk';\nimport { generateResumeYaml } from '../utils/resumeTemplate';\n\ninterface InitCommandOptions {\n output?: string;\n}\n\nfunction createReadlineInterface(): readline.Interface {\n return readline.createInterface({\n input: process.stdin,\n output: process.stdout,\n });\n}\n\nfunction ask(rl: readline.Interface, question: string, defaultValue?: string): Promise<string> {\n const prompt = defaultValue ? `${question} (${defaultValue}): ` : `${question}: `;\n return new Promise((resolve) => {\n rl.question(prompt, (answer) => {\n resolve(answer.trim() || defaultValue || '');\n });\n });\n}\n\nexport async function initAction(options: InitCommandOptions): Promise<void> {\n const outputPath = options.output || 'resume.yaml';\n const fullPath = path.resolve(outputPath);\n\n const rl = createReadlineInterface();\n\n try {\n // Check if file already exists\n if (fs.existsSync(fullPath)) {\n const overwrite = await ask(\n rl,\n `${chalk.yellow('⚠')} ${outputPath} already exists. Overwrite? (y/N)`,\n 'N'\n );\n if (overwrite.toLowerCase() !== 'y') {\n console.log(chalk.blue('Aborted. No files were changed.'));\n return;\n }\n }\n\n console.log(chalk.blue('\\n📝 Let\\'s set up your resume!\\n'));\n\n const name = await ask(rl, 'Your full name', 'John Doe');\n const email = await ask(rl, 'Email address', 'john@example.com');\n const label = await ask(rl, 'Professional title/label', 'Software Engineer');\n\n const yaml = generateResumeYaml(name, email, label);\n\n fs.mkdirSync(path.dirname(fullPath), { recursive: true });\n fs.writeFileSync(fullPath, yaml, 'utf8');\n\n console.log(chalk.green(`\\n✅ Created ${outputPath}`));\n console.log(chalk.blue('\\nNext steps:'));\n console.log(` 1. Edit ${outputPath} to fill in your details`);\n console.log(' 2. Run ' + chalk.cyan('resuml validate --resume ' + outputPath));\n console.log(' 3. Run ' + chalk.cyan('resuml render --resume ' + outputPath + ' --theme stackoverflow'));\n } finally {\n rl.close();\n }\n}\n","import fs from 'fs';\nimport path from 'node:path';\nimport { processResumeData } from '../core';\nimport { loadResumeFiles } from '../utils/loadResume';\nimport { loadTheme } from '../utils/themeLoader';\nimport { handleCommandError } from '../utils/errorHandler';\nimport chalk from 'chalk';\n\ninterface PdfCommandOptions {\n resume?: string;\n theme?: string;\n output?: string;\n language: string;\n format: string;\n margin?: string;\n debug?: boolean;\n}\n\ninterface PlaywrightBrowser {\n newPage(): Promise<PlaywrightPage>;\n close(): Promise<void>;\n}\n\ninterface PlaywrightPage {\n setContent(html: string, options?: { waitUntil?: string }): Promise<void>;\n pdf(options?: Record<string, unknown>): Promise<Buffer>;\n}\n\ninterface PlaywrightBrowserType {\n launch(options?: Record<string, unknown>): Promise<PlaywrightBrowser>;\n}\n\nasync function loadPlaywright(): Promise<PlaywrightBrowserType> {\n try {\n const { chromium } = await import('playwright');\n return chromium;\n } catch {\n throw new Error(\n `Playwright is required for PDF export but is not installed.\\n` +\n `Install it with: ${chalk.cyan('npm install playwright')}`\n );\n }\n}\n\nfunction parseMargin(margin?: string): Record<string, string> {\n const defaultMargin = { top: '10mm', right: '10mm', bottom: '10mm', left: '10mm' };\n if (!margin) return defaultMargin;\n\n const parts = margin.split(',').map((s) => s.trim());\n if (parts.length === 1 && parts[0]) {\n return { top: parts[0], right: parts[0], bottom: parts[0], left: parts[0] };\n }\n if (parts.length === 2 && parts[0] && parts[1]) {\n return { top: parts[0], right: parts[1], bottom: parts[0], left: parts[1] };\n }\n if (parts.length === 4 && parts[0] && parts[1] && parts[2] && parts[3]) {\n return { top: parts[0], right: parts[1], bottom: parts[2], left: parts[3] };\n }\n return defaultMargin;\n}\n\nexport async function pdfAction(options: PdfCommandOptions): Promise<void> {\n if (!options.theme) {\n throw new Error(\n '--theme option is required. Please specify a theme name (e.g., stackoverflow, react).'\n );\n }\n\n console.log(chalk.blue('Starting resuml PDF export...'));\n\n try {\n // Load and process resume data\n const inputPath = options.resume;\n const { yamlContents } = await loadResumeFiles(inputPath);\n\n console.log(chalk.blue('Processing and validating resume data...'));\n const resumeData = await processResumeData(yamlContents);\n console.log(chalk.green('Resume data processing and validation successful!'));\n\n // Render HTML using theme\n const theme = loadTheme(options.theme);\n const htmlOutput = await theme.render(resumeData, {\n locale: options.language,\n });\n\n // Load playwright\n console.log(chalk.blue('Loading Playwright...'));\n const chromium = await loadPlaywright();\n\n // Convert HTML to PDF\n const outputPath = options.output || 'resume.pdf';\n const format = options.format === 'Letter' ? 'Letter' : 'A4';\n const margin = parseMargin(options.margin);\n\n console.log(chalk.blue(`Generating PDF (${format} format)...`));\n\n const browser = await chromium.launch({ headless: true });\n try {\n const page = await browser.newPage();\n await page.setContent(htmlOutput, { waitUntil: 'networkidle' });\n\n const pdfBuffer = await page.pdf({\n format,\n margin,\n printBackground: true,\n preferCSSPageSize: true,\n });\n\n fs.mkdirSync(path.dirname(path.resolve(outputPath)), { recursive: true });\n fs.writeFileSync(outputPath, pdfBuffer);\n\n console.log(chalk.green(`✅ Successfully generated ${outputPath}`));\n } finally {\n await browser.close();\n }\n } catch (error: unknown) {\n handleCommandError(error, 'pdf', options.debug);\n }\n}\n","import chalk from 'chalk';\nimport { execSync } from 'child_process';\nimport { KNOWN_THEMES, isThemeInstalled, getInstalledVersion } from '../utils/themeInfo';\n\ninterface ThemesCommandOptions {\n install?: string;\n}\n\nfunction listThemes(): void {\n console.log(chalk.blue('\\n📦 Compatible JSON Resume Themes\\n'));\n\n const nameWidth = 16;\n const pkgWidth = 38;\n\n // Header\n console.log(\n ` ${'Status'.padEnd(10)}${'Name'.padEnd(nameWidth)}${'Package'.padEnd(pkgWidth)}Description`\n );\n console.log(` ${'─'.repeat(10)}${'─'.repeat(nameWidth)}${'─'.repeat(pkgWidth)}${'─'.repeat(30)}`);\n\n for (const theme of KNOWN_THEMES) {\n const installed = isThemeInstalled(theme.pkg);\n const version = installed ? getInstalledVersion(theme.pkg) : null;\n const status = installed\n ? chalk.green(`✓ ${version || 'yes'}`.padEnd(10))\n : chalk.yellow('not installed'.substring(0, 10).padEnd(10));\n\n console.log(\n ` ${status}${theme.name.padEnd(nameWidth)}${chalk.blue(theme.pkg.padEnd(pkgWidth))}${theme.description}`\n );\n }\n\n console.log(chalk.blue('\\nInstall a theme:'));\n console.log(` ${chalk.cyan('resuml themes --install <name>')}`);\n console.log(` ${chalk.cyan('resuml themes --install stackoverflow')}\\n`);\n console.log(\n chalk.blue('Browse all themes: ') +\n 'https://www.npmjs.com/search?q=jsonresume-theme\\n'\n );\n}\n\nfunction installTheme(name: string): void {\n // Check if it's a known short name\n const known = KNOWN_THEMES.find((t) => t.name === name);\n const pkg = known ? known.pkg : name.startsWith('jsonresume-theme-') ? name : `jsonresume-theme-${name}`;\n\n console.log(chalk.blue(`\\n📦 Installing ${pkg}...\\n`));\n\n try {\n execSync(`npm install ${pkg}`, { stdio: 'inherit' });\n console.log(chalk.green(`\\n✅ Successfully installed ${pkg}`));\n console.log(chalk.blue(`\\nUse it with: ${chalk.cyan(`resuml render --theme ${known?.name || name}`)}\\n`));\n } catch {\n console.error(chalk.red(`\\n❌ Failed to install ${pkg}`));\n console.error(chalk.yellow(`Make sure the package exists: https://www.npmjs.com/package/${pkg}\\n`));\n }\n}\n\nexport function themesAction(options: ThemesCommandOptions): void {\n if (options.install) {\n installTheme(options.install);\n } else {\n listThemes();\n }\n}\n","export async function mcpAction(): Promise<void> {\n const { startMcpServer } = await import('../mcp/server');\n await startMcpServer();\n}\n","import type { Resume } from '../core';\n\ninterface ThemeConfig {\n sections?: {\n order?: string[];\n exclude?: string[];\n };\n layout?: {\n style?: string;\n };\n styling?: Record<string, string | number>;\n labels?: Record<string, string>;\n}\n\n/**\n * Render a resume using the specified theme\n * @param themeName Name of the theme to use\n * @param resumeData Resume data to render\n * @param themeConfig Theme configuration\n * @param inlineCss Optional CSS to include in the HTML\n * @param language Language code for localization\n * @returns Object containing the rendered HTML\n */\nexport async function renderTheme(\n themeName: string,\n resumeData: Resume,\n themeConfig: ThemeConfig = {},\n inlineCss?: string,\n language: string = 'en'\n): Promise<{ htmlOutput: string }> {\n try {\n if (themeName.startsWith('jsonresume-')) {\n return await renderJsonResumeTheme(themeName, resumeData, inlineCss);\n } else {\n return await renderRyamlTheme(themeName, resumeData, themeConfig, inlineCss, language);\n }\n } catch (error) {\n if (error instanceof Error) {\n throw new Error(`Error rendering theme: ${error.message}`);\n }\n throw new Error('Unknown error rendering theme');\n }\n}\n\n/**\n * Renders a JSON Resume theme\n */\nasync function renderJsonResumeTheme(\n themeName: string,\n resumeData: Resume,\n inlineCss?: string\n): Promise<{ htmlOutput: string }> {\n // Handle both formats: with and without 'jsonresume-' prefix\n let themePackageName;\n if (themeName.startsWith('jsonresume-theme-')) {\n // User provided full name (jsonresume-theme-stackoverflow)\n themePackageName = themeName;\n } else if (themeName.startsWith('jsonresume-')) {\n // User provided short name (jsonresume-stackoverflow)\n themePackageName = `jsonresume-theme-${themeName.replace('jsonresume-', '')}`;\n } else {\n // User provided just the name (stackoverflow)\n themePackageName = `jsonresume-theme-${themeName}`;\n }\n\n // Convert resuml data to jsonresume format if needed\n const jsonResumeData = resumeData; // In real implementation, convert if necessary\n\n // Dynamically import the theme\n const themePackage = await import(themePackageName) as { default: { render: (d: unknown) => string } };\n const renderedHTML = themePackage.default.render(jsonResumeData);\n\n return {\n htmlOutput: injectCss(renderedHTML, inlineCss),\n };\n}\n\n/**\n * Renders a resuml theme\n */\nasync function renderRyamlTheme(\n themeName: string,\n resumeData: Resume,\n themeConfig: ThemeConfig,\n inlineCss?: string,\n language: string = 'en'\n): Promise<{ htmlOutput: string }> {\n if (themeName === 'default') {\n throw new Error('No default theme available. Please specify a specific theme name.');\n }\n\n const themePackageName = `@resuml/theme-${themeName}`;\n\n // Dynamically import the theme (better than require)\n const themePackage = await import(themePackageName) as { default: { render: (d: unknown, c: unknown, l: string) => string } };\n const renderedHTML = themePackage.default.render(resumeData, themeConfig, language);\n\n return {\n htmlOutput: injectCss(renderedHTML, inlineCss),\n };\n}\n\n/**\n * Injects CSS into HTML content\n * @param html HTML content\n * @param css CSS to inject\n * @returns HTML with injected CSS\n */\nexport function injectCss(html: string, css?: string): string {\n if (!css) return html;\n return html.replace('</head>', `<style>${css}</style></head>`);\n}\n"],"mappings":"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","names":["path","fs","path","chalk","fs","chalk","fs","fs","fs","fs","path","chalk","fs","path","fs","path","chalk","path","fs","chalk","fs","path","chalk","fs","path","chalk","chalk","path","fs"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/commands/validate.ts","../src/utils/loadResume.ts","../src/utils/fileUtils.ts","../src/utils/errorHandler.ts","../src/commands/tojson.ts","../src/commands/render.ts","../src/commands/dev.ts","../src/commands/init.ts","../src/commands/pdf.ts","../src/commands/themes.ts","../src/commands/mcp.ts","../src/utils/themeRender.ts"],"sourcesContent":["#!/usr/bin/env node\n\nimport { Command } from 'commander';\nimport path from 'path';\nimport fs from 'fs';\nimport { fileURLToPath } from 'url';\nimport { validateAction } from './commands/validate';\nimport { toJsonAction } from './commands/tojson';\nimport { renderAction } from './commands/render';\nimport { devAction } from './commands/dev';\nimport { initAction } from './commands/init';\nimport { pdfAction } from './commands/pdf';\nimport { themesAction } from './commands/themes';\nimport { mcpAction } from './commands/mcp';\n\n// Get the directory name equivalent to __dirname in CommonJS\nconst currentDir = path.dirname(fileURLToPath(import.meta.url));\n\nfunction getCliVersion(): string {\n const packageJsonPath = path.resolve(currentDir, '../package.json');\n if (fs.existsSync(packageJsonPath)) {\n try {\n const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8')) as { version?: string };\n return packageJson.version ?? '0.0.0';\n } catch {\n return '0.0.0';\n }\n }\n return '0.0.0';\n}\n\nexport const program = new Command();\n\nprogram\n .name('resuml')\n .description('CLI tool for managing resuml resume files.')\n .version(getCliVersion());\n\n// Validate Command\nprogram\n .command('validate')\n .description('Validates resume data against the schema.')\n .option('-r, --resume <path>', 'Input YAML file, directory, or glob pattern.')\n .option('--debug', 'Show detailed validation errors.')\n .option('--ats', 'Run ATS (Applicant Tracking System) compatibility analysis.')\n .option('--jd <path>', 'Path to a job description file for keyword matching (requires --ats).')\n .option('--ats-threshold <score>', 'Minimum ATS score (0-100). Exit with code 1 if below threshold.')\n .option('--format <type>', 'Output format for ATS results (text or json).', 'text')\n .action(validateAction);\n\n// ToJSON Command\nprogram\n .command('tojson')\n .description('Converts YAML resume data to JSON format.')\n .option('-r, --resume <path>', 'Input YAML file, directory, or glob pattern.')\n .option('-o, --output <file>', 'Output JSON file path.', 'resume.json')\n .option('--debug', 'Show detailed validation and processing information.')\n .action(toJsonAction);\n\n// Render Command\nprogram\n .command('render')\n .description('Renders the resume data using a specified theme.')\n .option('-r, --resume <path>', 'Input YAML file, directory, or glob pattern.')\n .option('-t, --theme <name>', 'Theme name (e.g., stackoverflow, react).')\n .option('-o, --output <file>', 'Output file path.')\n .option('--format <type>', 'Output format (html or pdf).', 'html')\n .option('--language <code>', 'Language code for localization.', 'en')\n .option('--debug', 'Show detailed validation and processing information.')\n .action(renderAction);\n\n// Dev Command\nprogram\n .command('dev')\n .description('Start development server with hot-reload.')\n .option('-r, --resume <path>', 'Input YAML file, directory, or glob pattern.')\n .option('-t, --theme <name>', 'Theme name (e.g., stackoverflow, react).')\n .option('--port <number>', 'Port for development server.', '3000')\n .option('--language <code>', 'Language code for localization.', 'en')\n .option('--debug', 'Show detailed validation and processing information.')\n .action(devAction);\n\n// Init Command\nprogram\n .command('init')\n .description('Scaffold a starter resume.yaml file with all sections.')\n .option('-o, --output <file>', 'Output YAML file path.', 'resume.yaml')\n .action(initAction);\n\n// PDF Command\nprogram\n .command('pdf')\n .description('Export resume as PDF using Playwright.')\n .option('-r, --resume <path>', 'Input YAML file, directory, or glob pattern.')\n .option('-t, --theme <name>', 'Theme name (e.g., stackoverflow, react).')\n .option('-o, --output <file>', 'Output PDF file path.', 'resume.pdf')\n .option('--language <code>', 'Language code for localization.', 'en')\n .option('--format <size>', 'Page format: A4 or Letter.', 'A4')\n .option('--margin <values>', 'Page margins (e.g., \"10mm\" or \"10mm,15mm,10mm,15mm\").')\n .option('--debug', 'Show detailed validation and processing information.')\n .action(pdfAction);\n\n// Themes Command\nprogram\n .command('themes')\n .description('List available JSON Resume themes and install them.')\n .option('--install <name>', 'Install a theme by name (e.g., stackoverflow, elegant).')\n .action(themesAction);\n\n// MCP Server Command\nprogram\n .command('mcp')\n .description('Start MCP server for AI agent integration (stdio transport).')\n .action(mcpAction);\n\n// Parse Arguments - only execute when not in test environment\nif (process.env['NODE_ENV'] !== 'test') {\n void (async () => {\n try {\n await program.parseAsync(process.argv);\n } catch (e: unknown) {\n console.error('Command line error:', (e as Error).message);\n process.exit(1);\n }\n })();\n}\n\nexport { processResumeData } from './core';\nexport { loadResumeFiles } from './utils/loadResume';\nexport { loadTheme } from './utils/themeLoader';\nexport * as themeRender from './utils/themeRender';\nexport { analyzeAts } from './ats/index';\nexport type { AtsResult, AtsOptions } from './ats/index';\n","import fs from 'fs';\nimport { processResumeData } from '../core';\nimport { loadResumeFiles } from '../utils/loadResume';\nimport { handleCommandError } from '../utils/errorHandler';\nimport { analyzeAts } from '../ats/index';\nimport type { AtsResult, AtsCheck } from '../ats/index';\n\ninterface ValidateCommandOptions {\n resume?: string;\n debug?: boolean;\n ats?: boolean;\n jd?: string;\n atsThreshold?: string;\n format?: string;\n}\n\nfunction formatAtsReport(result: AtsResult, debug: boolean, chalk: typeof import('chalk').default): void {\n const scoreColor = result.score >= 75 ? chalk.green : result.score >= 60 ? chalk.yellow : chalk.red;\n console.log('');\n console.log(chalk.bold('═══ ATS Analysis Report ═══'));\n console.log('');\n console.log(` Score: ${scoreColor(chalk.bold(`${result.score}/100`))} (${result.rating.replace('-', ' ')})`);\n console.log(` ${result.summary}`);\n console.log('');\n\n // Group checks by category\n const categories: Record<string, AtsCheck[]> = {};\n for (const check of result.checks) {\n const list = categories[check.category];\n if (!list) {\n categories[check.category] = [check];\n } else {\n list.push(check);\n }\n }\n\n const categoryLabels: Record<string, string> = {\n contact: 'Contact Information',\n content: 'Content Quality',\n structure: 'Resume Structure',\n keywords: 'Keywords',\n };\n\n for (const [cat, checks] of Object.entries(categories)) {\n const label = categoryLabels[cat] || cat;\n console.log(chalk.bold(` ${label}`));\n\n for (const check of checks) {\n if (!debug && check.passed) continue; // In normal mode, only show failures\n const icon = check.passed ? chalk.green('✓') : chalk.red('✗');\n const scoreText = chalk.dim(`[${check.score}]`);\n console.log(` ${icon} ${check.message} ${scoreText}`);\n if (!check.passed && check.suggestion) {\n console.log(chalk.dim(` → ${check.suggestion}`));\n }\n }\n console.log('');\n }\n\n // JD keyword section\n if (result.keywords) {\n console.log(chalk.bold(' Job Description Match'));\n const kw = result.keywords;\n const matchColor = kw.matchPercentage >= 70 ? chalk.green : kw.matchPercentage >= 50 ? chalk.yellow : chalk.red;\n console.log(` Match: ${matchColor(`${kw.matchPercentage}%`)} (${kw.matched.length}/${kw.matched.length + kw.missing.length} keywords)`);\n if (kw.matched.length > 0) {\n console.log(chalk.green(` ✓ Matched: ${kw.matched.join(', ')}`));\n }\n if (kw.missing.length > 0) {\n console.log(chalk.red(` ✗ Missing: ${kw.missing.join(', ')}`));\n console.log(chalk.dim(' → Consider incorporating these keywords into your resume where relevant.'));\n }\n console.log('');\n }\n\n console.log(chalk.dim('═══════════════════════════'));\n}\n\nexport async function validateAction(options: ValidateCommandOptions): Promise<void> {\n const chalk = (await import('chalk')).default;\n console.log(chalk.blue('Starting resuml validate...'));\n\n try {\n const inputPath = options.resume;\n const { yamlContents } = await loadResumeFiles(inputPath);\n\n console.log(chalk.blue('Validating resume data...'));\n\n let resumeData;\n try {\n resumeData = await processResumeData(yamlContents);\n console.log(chalk.green('✓ Resume data is valid against the schema!'));\n } catch (error: unknown) {\n handleCommandError(error, 'validate', options.debug);\n return;\n }\n\n // Run ATS analysis if requested\n if (options.ats) {\n console.log(chalk.blue('Running ATS analysis...'));\n\n let jobDescription: string | undefined;\n if (options.jd) {\n try {\n jobDescription = fs.readFileSync(options.jd, 'utf8');\n } catch {\n console.error(chalk.red(`Failed to read job description file: ${options.jd}`));\n return;\n }\n }\n\n const result = analyzeAts(resumeData, {\n language: 'en',\n jobDescription,\n });\n\n if (options.format === 'json') {\n console.log(JSON.stringify(result, null, 2));\n } else {\n formatAtsReport(result, !!options.debug, chalk);\n }\n\n // Check threshold\n const threshold = options.atsThreshold ? parseInt(options.atsThreshold, 10) : undefined;\n if (threshold !== undefined && result.score < threshold) {\n console.error(chalk.red(`\\nATS score ${result.score} is below threshold ${threshold}.`));\n process.exit(1);\n }\n }\n } catch (error: unknown) {\n handleCommandError(error, 'validate', options.debug);\n }\n}\n","import fs from 'fs/promises';\nimport YAML from 'yaml';\nimport { findInputFiles } from './fileUtils';\n\n/**\n * Load and parse resume files\n */\nexport async function loadResumeFiles(\n inputPath?: string\n): Promise<{ files: string[]; yamlContents: string[] }> {\n const files = await findInputFiles(inputPath);\n if (files.length === 0) {\n throw new Error('No resume files found');\n }\n\n const yamlContents: string[] = [];\n\n for (const file of files) {\n try {\n const content = await fs.readFile(file, 'utf-8');\n const parsed: unknown = YAML.parse(content);\n if (parsed && typeof parsed === 'object') {\n yamlContents.push(content);\n }\n } catch (error) {\n throw new Error(`Failed to parse ${file}: ${(error as Error).message}`);\n }\n }\n\n if (yamlContents.length === 0) {\n throw new Error('No valid data found in any of the input files');\n }\n\n return { files, yamlContents };\n}\n","import fs from 'fs/promises';\nimport path from 'path';\nimport { glob } from 'glob';\n\n/**\n * Find input files based on provided path\n * @param inputPath File, directory, or glob pattern\n * @returns Array of matched file paths\n */\nexport async function findInputFiles(inputPath?: string): Promise<string[]> {\n if (!inputPath) {\n return [];\n }\n\n if (inputPath.includes('*')) {\n try {\n const matchedFiles = await glob(inputPath);\n if (matchedFiles.length === 0) {\n throw new Error(`No files found matching pattern: ${inputPath}`);\n }\n return matchedFiles;\n } catch (err) {\n throw new Error(`Error matching files: ${err instanceof Error ? err.message : String(err)}`);\n }\n }\n\n try {\n const stat = await fs.stat(inputPath);\n if (stat.isFile()) {\n return [inputPath];\n } else if (stat.isDirectory()) {\n const pattern = path.join(inputPath, '*.{yaml,yml}');\n try {\n const yamlFiles = await glob(pattern);\n if (yamlFiles.length === 0) {\n throw new Error(`No YAML files found in directory: ${inputPath}`);\n }\n return yamlFiles;\n } catch (_) {\n throw new Error(`No YAML files found in directory: ${inputPath}`);\n }\n }\n } catch (e) {\n if (e instanceof Error && e.message.includes('ENOENT')) {\n throw new Error('Input path not found');\n }\n throw e;\n }\n\n return [];\n}\n","interface ValidationErrorDetail {\n instancePath?: string;\n message?: string;\n params?: Record<string, unknown>;\n // Add other properties from Ajv error objects if needed\n}\n\ninterface SchemaValidationError extends Error {\n errors?: ValidationErrorDetail[];\n}\n\n/**\n * Handle command errors, displaying useful information to the user\n */\nexport function handleCommandError(error: unknown, command: string, debug: boolean = false): void {\n const errorMessage = error instanceof Error ? error.message : String(error);\n console.error(`❌ Error during ${command} command: ${errorMessage}`);\n\n // Handle validation errors from core\n const potentialValidationError = error as SchemaValidationError;\n if (\n potentialValidationError instanceof Error &&\n potentialValidationError.name === 'SchemaValidationError' &&\n Array.isArray(potentialValidationError.errors)\n ) {\n const errors: ValidationErrorDetail[] = potentialValidationError.errors;\n\n if (debug) {\n // Show detailed errors with all information in debug mode\n console.error('\\nValidation failed with the following errors:');\n errors.forEach((err: ValidationErrorDetail, index: number) => {\n const path = err.instancePath || 'root';\n console.error(`${index + 1}. Path: ${path}`);\n console.error(` Error: ${err.message || 'Unknown validation error'}`);\n if (err.params) {\n console.error(` Params: ${JSON.stringify(err.params)}`);\n }\n });\n } else {\n // Show a more concise error message in normal mode\n console.error('\\nSome validation errors were found:');\n // Show a limited number of errors to avoid overwhelming output\n const maxErrors = 5;\n errors.slice(0, maxErrors).forEach((err: ValidationErrorDetail, index: number) => {\n const path = err.instancePath || 'root';\n console.error(`${index + 1}. Field: ${path}`);\n console.error(` Error: ${err.message || 'Unknown validation error'}`);\n });\n\n if (errors.length > maxErrors) {\n console.error(`\\n...and ${errors.length - maxErrors} more errors.`);\n console.error('Use the --debug flag for complete error details.');\n }\n }\n }\n\n // Only exit if not in a test environment where exit might disrupt the test runner\n if (process.env['NODE_ENV'] !== 'test') {\n process.exit(1);\n }\n}\n","import fs from 'fs';\nimport { processResumeData } from '../core';\nimport { loadResumeFiles } from '../utils/loadResume';\nimport { handleCommandError } from '../utils/errorHandler';\n\ninterface ToJsonOptions {\n resume?: string;\n output: string;\n debug?: boolean;\n}\n\nexport async function toJsonAction(options: ToJsonOptions): Promise<void> {\n const chalk = (await import('chalk')).default;\n console.log(chalk.blue('Starting resuml tojson...'));\n\n try {\n const inputPath = options.resume;\n const { yamlContents } = await loadResumeFiles(inputPath);\n\n console.log(chalk.blue('Processing and validating data...'));\n const resumeData = await processResumeData(yamlContents);\n console.log(chalk.green('Processing and validation successful!'));\n\n // Generate JSON output\n const jsonOutput = JSON.stringify(resumeData, null, 2);\n fs.writeFileSync(options.output, jsonOutput, 'utf8');\n console.log(chalk.green(`Successfully wrote output to ${options.output}`));\n } catch (error: unknown) {\n handleCommandError(error, 'tojson', options.debug);\n }\n}\n","import fs from 'fs';\nimport path from 'node:path';\nimport { processResumeData } from '../core';\nimport { loadResumeFiles } from '../utils/loadResume';\nimport { loadTheme } from '../utils/themeLoader';\nimport { handleCommandError } from '../utils/errorHandler';\nimport chalk from 'chalk';\n\ninterface RenderCommandOptions {\n resume?: string;\n theme?: string;\n output?: string;\n format: 'html' | 'pdf';\n language: string;\n debug?: boolean;\n}\n\nexport async function renderAction(options: RenderCommandOptions): Promise<void> {\n if (!options.theme) {\n throw new Error(\n '--theme option is required. Please specify a theme name (e.g., stackoverflow, react).'\n );\n }\n\n console.log(chalk.blue('Starting resuml render...'));\n\n try {\n const inputPath = options.resume;\n const { yamlContents } = await loadResumeFiles(inputPath);\n\n console.log(chalk.blue('Processing and validating resume data...'));\n const resumeData = await processResumeData(yamlContents);\n console.log(chalk.green('Resume data processing and validation successful!'));\n\n const theme = loadTheme(options.theme);\n\n const htmlOutput = await theme.render(resumeData, {\n locale: options.language,\n });\n\n const defaultExtension = options.format;\n const defaultFilename = `resume.${defaultExtension}`;\n const outputPath = options.output || defaultFilename;\n\n if (options.format === 'pdf') { // eslint-disable-line @typescript-eslint/no-unnecessary-condition\n console.log(chalk.blue(`Generating PDF output at ${outputPath}...`));\n const { chromium } = await import('playwright');\n const browser = await chromium.launch();\n const page = await browser.newPage();\n await page.setContent(htmlOutput, { waitUntil: 'networkidle' });\n const pdfBuffer = await page.pdf({\n path: outputPath,\n format: 'A4',\n printBackground: true,\n margin: {\n top: '1cm',\n right: '1cm',\n bottom: '1cm',\n left: '1cm',\n },\n });\n await browser.close();\n fs.writeFileSync(outputPath, pdfBuffer);\n console.log(chalk.green(`Successfully wrote PDF output to ${outputPath}`));\n } else {\n console.log(chalk.blue(`Writing HTML output to ${outputPath}...`));\n fs.mkdirSync(path.dirname(outputPath), { recursive: true });\n fs.writeFileSync(outputPath, htmlOutput, 'utf8');\n console.log(chalk.green(`Successfully wrote HTML output to ${outputPath}`));\n }\n } catch (error: unknown) {\n handleCommandError(error, 'render', options.debug);\n }\n}\n","import fs from 'fs';\nimport path from 'node:path';\nimport { processResumeData } from '../core';\nimport { loadResumeFiles } from '../utils/loadResume';\nimport { loadTheme } from '../utils/themeLoader';\nimport { handleCommandError } from '../utils/errorHandler';\nimport chalk from 'chalk';\n\ninterface DevCommandOptions {\n resume?: string;\n theme?: string;\n port?: number;\n language: string;\n debug?: boolean;\n}\n\nexport async function devAction(options: DevCommandOptions): Promise<void> {\n if (!options.theme) {\n throw new Error(\n '--theme option is required. Please specify a theme name (e.g., stackoverflow, react).'\n );\n }\n\n console.log(chalk.blue('Starting resuml development server...'));\n\n const port = options.port || 3000;\n const inputPath = options.resume;\n\n if (!inputPath) {\n throw new Error('Resume path is required. Use -r or --resume option.');\n }\n\n try {\n // Initial render\n await renderResume(options);\n\n console.log(chalk.green(`🚀 Development server running at http://localhost:${port}`));\n console.log(chalk.blue('Watching for file changes...'));\n\n // Watch for file changes if inputPath is a directory\n if (fs.existsSync(inputPath) && fs.statSync(inputPath).isDirectory()) {\n watchDirectory(inputPath, () => { void renderResume(options); });\n } else if (fs.existsSync(inputPath)) {\n watchFile(inputPath, () => { void renderResume(options); });\n }\n\n // Simple HTTP server\n await startDevServer(port);\n } catch (error: unknown) {\n handleCommandError(error, 'dev', options.debug);\n }\n}\n\nasync function renderResume(options: DevCommandOptions): Promise<void> {\n try {\n const inputPath = options.resume;\n if (!inputPath) {\n throw new Error('Resume path is required');\n }\n\n const { yamlContents } = await loadResumeFiles(inputPath);\n\n console.log(chalk.blue('🔄 Processing resume data...'));\n const resumeData = await processResumeData(yamlContents);\n\n const theme = loadTheme(options.theme ?? 'stackoverflow');\n\n const htmlOutput = await theme.render(resumeData, {\n locale: options.language,\n });\n\n // Write to a temp directory for the dev server\n const outputPath = path.join(process.cwd(), '.resuml-dev', 'index.html');\n fs.mkdirSync(path.dirname(outputPath), { recursive: true });\n fs.writeFileSync(outputPath, htmlOutput, 'utf8');\n\n console.log(chalk.green('✅ Resume updated!'));\n } catch (error: unknown) {\n console.error(chalk.red('❌ Error rendering resume:'), (error as Error).message);\n }\n}\n\nfunction watchDirectory(dirPath: string, callback: () => void): void {\n fs.watch(dirPath, { recursive: true }, (_eventType, filename) => {\n if (filename && (filename.endsWith('.yaml') || filename.endsWith('.yml'))) {\n console.log(chalk.blue(`📁 File changed: ${filename}`));\n callback();\n }\n });\n}\n\nfunction watchFile(filePath: string, callback: () => void): void {\n fs.watch(filePath, (eventType) => {\n if (eventType === 'change') {\n console.log(chalk.blue(`📄 File changed: ${path.basename(filePath)}`));\n callback();\n }\n });\n}\n\nasync function startDevServer(port: number): Promise<void> {\n // Simple HTTP server implementation\n const http = await import('http');\n const url = await import('url');\n\n const server = http.createServer((req, res) => {\n const parsedUrl = url.parse(req.url || '', true);\n const pathname = parsedUrl.pathname || '/';\n\n if (pathname === '/' || pathname === '/index.html') {\n const htmlPath = path.join(process.cwd(), '.resuml-dev', 'index.html');\n\n if (fs.existsSync(htmlPath)) {\n const html = fs.readFileSync(htmlPath, 'utf8');\n\n // Inject live reload script\n const liveReloadScript = `\n <script>\n setInterval(() => {\n fetch('/health').then(() => {\n location.reload();\n }).catch(() => {\n // Server might be restarting\n });\n }, 1000);\n </script>\n `;\n\n const modifiedHtml = html.replace('</body>', `${liveReloadScript}</body>`);\n\n res.writeHead(200, { 'Content-Type': 'text/html' });\n res.end(modifiedHtml);\n } else {\n res.writeHead(404, { 'Content-Type': 'text/plain' });\n res.end('Resume not found. Make sure to provide a valid resume path.');\n }\n } else if (pathname === '/health') {\n res.writeHead(200, { 'Content-Type': 'application/json' });\n res.end('{\"status\":\"ok\"}');\n } else {\n res.writeHead(404, { 'Content-Type': 'text/plain' });\n res.end('Not found');\n }\n });\n\n server.listen(port, () => {\n console.log(chalk.green(`🌐 Server listening on port ${port}`));\n });\n}\n","import fs from 'fs';\nimport path from 'path';\nimport readline from 'readline';\nimport chalk from 'chalk';\nimport { generateResumeYaml } from '../utils/resumeTemplate';\n\ninterface InitCommandOptions {\n output?: string;\n}\n\nfunction createReadlineInterface(): readline.Interface {\n return readline.createInterface({\n input: process.stdin,\n output: process.stdout,\n });\n}\n\nfunction ask(rl: readline.Interface, question: string, defaultValue?: string): Promise<string> {\n const prompt = defaultValue ? `${question} (${defaultValue}): ` : `${question}: `;\n return new Promise((resolve) => {\n rl.question(prompt, (answer) => {\n resolve(answer.trim() || defaultValue || '');\n });\n });\n}\n\nexport async function initAction(options: InitCommandOptions): Promise<void> {\n const outputPath = options.output || 'resume.yaml';\n const fullPath = path.resolve(outputPath);\n\n const rl = createReadlineInterface();\n\n try {\n // Check if file already exists\n if (fs.existsSync(fullPath)) {\n const overwrite = await ask(\n rl,\n `${chalk.yellow('⚠')} ${outputPath} already exists. Overwrite? (y/N)`,\n 'N'\n );\n if (overwrite.toLowerCase() !== 'y') {\n console.log(chalk.blue('Aborted. No files were changed.'));\n return;\n }\n }\n\n console.log(chalk.blue('\\n📝 Let\\'s set up your resume!\\n'));\n\n const name = await ask(rl, 'Your full name', 'John Doe');\n const email = await ask(rl, 'Email address', 'john@example.com');\n const label = await ask(rl, 'Professional title/label', 'Software Engineer');\n\n const yaml = generateResumeYaml(name, email, label);\n\n fs.mkdirSync(path.dirname(fullPath), { recursive: true });\n fs.writeFileSync(fullPath, yaml, 'utf8');\n\n console.log(chalk.green(`\\n✅ Created ${outputPath}`));\n console.log(chalk.blue('\\nNext steps:'));\n console.log(` 1. Edit ${outputPath} to fill in your details`);\n console.log(' 2. Run ' + chalk.cyan('resuml validate --resume ' + outputPath));\n console.log(' 3. Run ' + chalk.cyan('resuml render --resume ' + outputPath + ' --theme stackoverflow'));\n } finally {\n rl.close();\n }\n}\n","import fs from 'fs';\nimport path from 'node:path';\nimport { processResumeData } from '../core';\nimport { loadResumeFiles } from '../utils/loadResume';\nimport { loadTheme } from '../utils/themeLoader';\nimport { handleCommandError } from '../utils/errorHandler';\nimport chalk from 'chalk';\n\ninterface PdfCommandOptions {\n resume?: string;\n theme?: string;\n output?: string;\n language: string;\n format: string;\n margin?: string;\n debug?: boolean;\n}\n\ninterface PlaywrightBrowser {\n newPage(): Promise<PlaywrightPage>;\n close(): Promise<void>;\n}\n\ninterface PlaywrightPage {\n setContent(html: string, options?: { waitUntil?: string }): Promise<void>;\n pdf(options?: Record<string, unknown>): Promise<Buffer>;\n}\n\ninterface PlaywrightBrowserType {\n launch(options?: Record<string, unknown>): Promise<PlaywrightBrowser>;\n}\n\nasync function loadPlaywright(): Promise<PlaywrightBrowserType> {\n try {\n const { chromium } = await import('playwright');\n return chromium;\n } catch {\n throw new Error(\n `Playwright is required for PDF export but is not installed.\\n` +\n `Install it with: ${chalk.cyan('npm install playwright')}`\n );\n }\n}\n\nfunction parseMargin(margin?: string): Record<string, string> {\n const defaultMargin = { top: '10mm', right: '10mm', bottom: '10mm', left: '10mm' };\n if (!margin) return defaultMargin;\n\n const parts = margin.split(',').map((s) => s.trim());\n if (parts.length === 1 && parts[0]) {\n return { top: parts[0], right: parts[0], bottom: parts[0], left: parts[0] };\n }\n if (parts.length === 2 && parts[0] && parts[1]) {\n return { top: parts[0], right: parts[1], bottom: parts[0], left: parts[1] };\n }\n if (parts.length === 4 && parts[0] && parts[1] && parts[2] && parts[3]) {\n return { top: parts[0], right: parts[1], bottom: parts[2], left: parts[3] };\n }\n return defaultMargin;\n}\n\nexport async function pdfAction(options: PdfCommandOptions): Promise<void> {\n if (!options.theme) {\n throw new Error(\n '--theme option is required. Please specify a theme name (e.g., stackoverflow, react).'\n );\n }\n\n console.log(chalk.blue('Starting resuml PDF export...'));\n\n try {\n // Load and process resume data\n const inputPath = options.resume;\n const { yamlContents } = await loadResumeFiles(inputPath);\n\n console.log(chalk.blue('Processing and validating resume data...'));\n const resumeData = await processResumeData(yamlContents);\n console.log(chalk.green('Resume data processing and validation successful!'));\n\n // Render HTML using theme\n const theme = loadTheme(options.theme);\n const htmlOutput = await theme.render(resumeData, {\n locale: options.language,\n });\n\n // Load playwright\n console.log(chalk.blue('Loading Playwright...'));\n const chromium = await loadPlaywright();\n\n // Convert HTML to PDF\n const outputPath = options.output || 'resume.pdf';\n const format = options.format === 'Letter' ? 'Letter' : 'A4';\n const margin = parseMargin(options.margin);\n\n console.log(chalk.blue(`Generating PDF (${format} format)...`));\n\n const browser = await chromium.launch({ headless: true });\n try {\n const page = await browser.newPage();\n await page.setContent(htmlOutput, { waitUntil: 'networkidle' });\n\n const pdfBuffer = await page.pdf({\n format,\n margin,\n printBackground: true,\n preferCSSPageSize: true,\n });\n\n fs.mkdirSync(path.dirname(path.resolve(outputPath)), { recursive: true });\n fs.writeFileSync(outputPath, pdfBuffer);\n\n console.log(chalk.green(`✅ Successfully generated ${outputPath}`));\n } finally {\n await browser.close();\n }\n } catch (error: unknown) {\n handleCommandError(error, 'pdf', options.debug);\n }\n}\n","import chalk from 'chalk';\nimport { execSync } from 'child_process';\nimport { KNOWN_THEMES, isThemeInstalled, getInstalledVersion } from '../utils/themeInfo';\n\ninterface ThemesCommandOptions {\n install?: string;\n}\n\nfunction listThemes(): void {\n console.log(chalk.blue('\\n📦 Compatible JSON Resume Themes\\n'));\n\n const nameWidth = 16;\n const pkgWidth = 38;\n\n // Header\n console.log(\n ` ${'Status'.padEnd(10)}${'Name'.padEnd(nameWidth)}${'Package'.padEnd(pkgWidth)}Description`\n );\n console.log(` ${'─'.repeat(10)}${'─'.repeat(nameWidth)}${'─'.repeat(pkgWidth)}${'─'.repeat(30)}`);\n\n for (const theme of KNOWN_THEMES) {\n const installed = isThemeInstalled(theme.pkg);\n const version = installed ? getInstalledVersion(theme.pkg) : null;\n const status = installed\n ? chalk.green(`✓ ${version || 'yes'}`.padEnd(10))\n : chalk.yellow('not installed'.substring(0, 10).padEnd(10));\n\n console.log(\n ` ${status}${theme.name.padEnd(nameWidth)}${chalk.blue(theme.pkg.padEnd(pkgWidth))}${theme.description}`\n );\n }\n\n console.log(chalk.blue('\\nInstall a theme:'));\n console.log(` ${chalk.cyan('resuml themes --install <name>')}`);\n console.log(` ${chalk.cyan('resuml themes --install stackoverflow')}\\n`);\n console.log(\n chalk.blue('Browse all themes: ') +\n 'https://www.npmjs.com/search?q=jsonresume-theme\\n'\n );\n}\n\nfunction installTheme(name: string): void {\n // Check if it's a known short name\n const known = KNOWN_THEMES.find((t) => t.name === name);\n const pkg = known ? known.pkg : name.startsWith('jsonresume-theme-') ? name : `jsonresume-theme-${name}`;\n\n console.log(chalk.blue(`\\n📦 Installing ${pkg}...\\n`));\n\n try {\n execSync(`npm install ${pkg}`, { stdio: 'inherit' });\n console.log(chalk.green(`\\n✅ Successfully installed ${pkg}`));\n console.log(chalk.blue(`\\nUse it with: ${chalk.cyan(`resuml render --theme ${known?.name || name}`)}\\n`));\n } catch {\n console.error(chalk.red(`\\n❌ Failed to install ${pkg}`));\n console.error(chalk.yellow(`Make sure the package exists: https://www.npmjs.com/package/${pkg}\\n`));\n }\n}\n\nexport function themesAction(options: ThemesCommandOptions): void {\n if (options.install) {\n installTheme(options.install);\n } else {\n listThemes();\n }\n}\n","export async function mcpAction(): Promise<void> {\n const { startMcpServer } = await import('../mcp/server');\n await startMcpServer();\n}\n","import type { Resume } from '../core';\n\ninterface ThemeConfig {\n sections?: {\n order?: string[];\n exclude?: string[];\n };\n layout?: {\n style?: string;\n };\n styling?: Record<string, string | number>;\n labels?: Record<string, string>;\n}\n\n/**\n * Render a resume using the specified theme\n * @param themeName Name of the theme to use\n * @param resumeData Resume data to render\n * @param themeConfig Theme configuration\n * @param inlineCss Optional CSS to include in the HTML\n * @param language Language code for localization\n * @returns Object containing the rendered HTML\n */\nexport async function renderTheme(\n themeName: string,\n resumeData: Resume,\n themeConfig: ThemeConfig = {},\n inlineCss?: string,\n language: string = 'en'\n): Promise<{ htmlOutput: string }> {\n try {\n if (themeName.startsWith('jsonresume-')) {\n return await renderJsonResumeTheme(themeName, resumeData, inlineCss);\n } else {\n return await renderRyamlTheme(themeName, resumeData, themeConfig, inlineCss, language);\n }\n } catch (error) {\n if (error instanceof Error) {\n throw new Error(`Error rendering theme: ${error.message}`);\n }\n throw new Error('Unknown error rendering theme');\n }\n}\n\n/**\n * Renders a JSON Resume theme\n */\nasync function renderJsonResumeTheme(\n themeName: string,\n resumeData: Resume,\n inlineCss?: string\n): Promise<{ htmlOutput: string }> {\n // Handle both formats: with and without 'jsonresume-' prefix\n let themePackageName;\n if (themeName.startsWith('jsonresume-theme-')) {\n // User provided full name (jsonresume-theme-stackoverflow)\n themePackageName = themeName;\n } else if (themeName.startsWith('jsonresume-')) {\n // User provided short name (jsonresume-stackoverflow)\n themePackageName = `jsonresume-theme-${themeName.replace('jsonresume-', '')}`;\n } else {\n // User provided just the name (stackoverflow)\n themePackageName = `jsonresume-theme-${themeName}`;\n }\n\n // Convert resuml data to jsonresume format if needed\n const jsonResumeData = resumeData; // In real implementation, convert if necessary\n\n // Dynamically import the theme\n const themePackage = await import(themePackageName) as { default: { render: (d: unknown) => string } };\n const renderedHTML = themePackage.default.render(jsonResumeData);\n\n return {\n htmlOutput: injectCss(renderedHTML, inlineCss),\n };\n}\n\n/**\n * Renders a resuml theme\n */\nasync function renderRyamlTheme(\n themeName: string,\n resumeData: Resume,\n themeConfig: ThemeConfig,\n inlineCss?: string,\n language: string = 'en'\n): Promise<{ htmlOutput: string }> {\n if (themeName === 'default') {\n throw new Error('No default theme available. Please specify a specific theme name.');\n }\n\n const themePackageName = `@resuml/theme-${themeName}`;\n\n // Dynamically import the theme (better than require)\n const themePackage = await import(themePackageName) as { default: { render: (d: unknown, c: unknown, l: string) => string } };\n const renderedHTML = themePackage.default.render(resumeData, themeConfig, language);\n\n return {\n htmlOutput: injectCss(renderedHTML, inlineCss),\n };\n}\n\n/**\n * Injects CSS into HTML content\n * @param html HTML content\n * @param css CSS to inject\n * @returns HTML with injected CSS\n */\nexport function injectCss(html: string, css?: string): string {\n if (!css) return html;\n return html.replace('</head>', `<style>${css}</style></head>`);\n}\n"],"mappings":"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","names":["path","fs","fs","fs","fs","path","chalk","fs","fs","chalk","fs","fs","path","fs","path","fs","path","chalk","fs","path","fs","path","chalk","path","fs","chalk","fs","path","chalk","fs","path","chalk","chalk","path","fs"]}
|
package/dist/mcp/server.js
CHANGED
|
@@ -1,16 +1,12 @@
|
|
|
1
1
|
import {
|
|
2
2
|
KNOWN_THEMES,
|
|
3
|
+
analyzeAts,
|
|
3
4
|
generateResumeYaml,
|
|
4
5
|
getInstalledVersion,
|
|
5
|
-
isThemeInstalled
|
|
6
|
-
|
|
7
|
-
import {
|
|
8
|
-
analyzeAts,
|
|
6
|
+
isThemeInstalled,
|
|
7
|
+
loadTheme,
|
|
9
8
|
processResumeData
|
|
10
|
-
} from "../chunk-
|
|
11
|
-
import {
|
|
12
|
-
loadTheme
|
|
13
|
-
} from "../chunk-ZLA7NFYP.js";
|
|
9
|
+
} from "../chunk-GRIYYG45.js";
|
|
14
10
|
|
|
15
11
|
// src/mcp/server.ts
|
|
16
12
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|