yamlresume 0.12.2 → 0.12.3
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.
|
@@ -11,12 +11,12 @@ import C from'node:fs';import {joinNonEmptyString,YAMLResumeError,DEFAULT_RESUME
|
|
|
11
11
|
`);}}async function ve(){w.info("Checking Tectonic...");try{let{stdout:e}=await execa("tectonic",["--version"]);console.log(` Tectonic: ${e.split(`
|
|
12
12
|
`)[0]}
|
|
13
13
|
`);}catch{console.log(` Tectonic: Not Found
|
|
14
|
-
`);}}async function Ee(){w.info("Checking Fonts...");let e=await getFonts({disableQuoting:true}),t=["Linux Libertine O","Linux Libertine","Noto Serif CJK SC","Noto Sans CJK SC"];for(let n of t){let r=e.some(s=>s.toLowerCase().includes(n.toLowerCase()))?"Installed":"Not Installed";console.log(` ${n}: ${r}`);}}function N(){return new Command().name("doctor").description("check environment for YAMLResume dependencies").action(async()=>{await Ce(),await Te(),await ve(),await Ee();})}function Se(){return markdownTable([["locale.language","Language Name"],...LOCALE_LANGUAGE_OPTIONS.map(e=>[e,getLocaleLanguageDetail(e).name])])}function I(){let e=new Command().name("languages").description("i18n and l10n support");return e.command("list").description("list all supported languages").action(()=>{w.log(Se());}),e}function Xe(e){if(C.existsSync(e))throw new YAMLResumeError("FILE_CONFLICT",{path:e});let t=c.join(c.dirname(fileURLToPath(import.meta.url)),import.meta.url.includes("dist")?"../resources/resume.yml":"../../resources/resume.yml"),n;try{n=C.readFileSync(t,"utf8");}catch(o){throw w.debug(joinNonEmptyString(["Error reading template: ",toCodeBlock(o.stack)])),new YAMLResumeError("FILE_READ_ERROR",{path:t})}try{C.writeFileSync(e,n),w.success(`Created ${e} successfully.`);}catch(o){throw w.debug(joinNonEmptyString(["Error creating resume: ",toCodeBlock(o.stack)])),new YAMLResumeError("FILE_WRITE_ERROR",{path:e})}}function O(){return new Command().name("new").description("create a new resume").argument("[filename]","output filename","resume.yml").action(e=>{try{Xe(e);}catch(t){w.error(t.message),process.exit(t.errno);}})}function We(){let e=[...LATEX_TEMPLATE_OPTIONS.map(t=>{let n=getLatexTemplateDetail(t);return [t,n.engine,n.name,n.description]}),...HTML_TEMPLATE_OPTIONS.map(t=>{let n=getHtmlTemplateDetail(t);return [t,n.engine,n.name,n.description]})];return markdownTable([["layouts.[].template","Engine","Template Name","Description"],...e])}function X(){let e=new Command().name("templates").description("manage resume templates");return e.command("list").description("list all supported templates").action(()=>{w.log(We());}),e}var W={version:"0.12.
|
|
14
|
+
`);}}async function Ee(){w.info("Checking Fonts...");let e=await getFonts({disableQuoting:true}),t=["Linux Libertine O","Linux Libertine","Noto Serif CJK SC","Noto Sans CJK SC"];for(let n of t){let r=e.some(s=>s.toLowerCase().includes(n.toLowerCase()))?"Installed":"Not Installed";console.log(` ${n}: ${r}`);}}function N(){return new Command().name("doctor").description("check environment for YAMLResume dependencies").action(async()=>{await Ce(),await Te(),await ve(),await Ee();})}function Se(){return markdownTable([["locale.language","Language Name"],...LOCALE_LANGUAGE_OPTIONS.map(e=>[e,getLocaleLanguageDetail(e).name])])}function I(){let e=new Command().name("languages").description("i18n and l10n support");return e.command("list").description("list all supported languages").action(()=>{w.log(Se());}),e}function Xe(e){if(C.existsSync(e))throw new YAMLResumeError("FILE_CONFLICT",{path:e});let t=c.join(c.dirname(fileURLToPath(import.meta.url)),import.meta.url.includes("dist")?"../resources/resume.yml":"../../resources/resume.yml"),n;try{n=C.readFileSync(t,"utf8");}catch(o){throw w.debug(joinNonEmptyString(["Error reading template: ",toCodeBlock(o.stack)])),new YAMLResumeError("FILE_READ_ERROR",{path:t})}try{C.writeFileSync(e,n),w.success(`Created ${e} successfully.`);}catch(o){throw w.debug(joinNonEmptyString(["Error creating resume: ",toCodeBlock(o.stack)])),new YAMLResumeError("FILE_WRITE_ERROR",{path:e})}}function O(){return new Command().name("new").description("create a new resume").argument("[filename]","output filename","resume.yml").action(e=>{try{Xe(e);}catch(t){w.error(t.message),process.exit(t.errno);}})}function We(){let e=[...LATEX_TEMPLATE_OPTIONS.map(t=>{let n=getLatexTemplateDetail(t);return [t,n.engine,n.name,n.description]}),...HTML_TEMPLATE_OPTIONS.map(t=>{let n=getHtmlTemplateDetail(t);return [t,n.engine,n.name,n.description]})];return markdownTable([["layouts.[].template","Engine","Template Name","Description"],...e])}function X(){let e=new Command().name("templates").description("manage resume templates");return e.command("list").description("list all supported templates").action(()=>{w.log(We());}),e}var W={version:"0.12.3"};function M(e){w.level=e?4:3;}function tn(){let e=new Command;return e.name("yamlresume").description(["YAMLResume \u2014 Resume as Code in YAML",`
|
|
15
15
|
__ __ _ __ __ _ ____
|
|
16
16
|
\\ \\ / // \\ | \\/ | | | _ \\ ___ ___ _ _ ___ ___ ___
|
|
17
17
|
\\ V // _ \\ | |\\/| | | | |_) / _ \\/ __| | | / _ \\/ _ \\ / _ \\
|
|
18
18
|
| |/ ___ \\| | | | |___| _ < __/\\__ \\ |_| | | | | | | __/
|
|
19
19
|
|_/_/ \\_\\_| |_|_____|_| \\_\\___||___/\\____|_| |_| |_|\\___|
|
|
20
20
|
`].join(`
|
|
21
|
-
`)).version(W.version).option("-v, --verbose","verbose output").hook("preAction",n=>{M(n.opts().verbose);}),e.addCommand(O()),e.addCommand(R()),e.addCommand(k()),e.addCommand(N()),e.addCommand(I()),e.addCommand(X()),e.addCommand(L()),e}export{L as a,R as b,k as c,N as d,I as e,O as f,X as g,tn as h};//# sourceMappingURL=chunk-
|
|
22
|
-
//# sourceMappingURL=chunk-
|
|
21
|
+
`)).version(W.version).option("-v, --verbose","verbose output").hook("preAction",n=>{M(n.opts().verbose);}),e.addCommand(O()),e.addCommand(R()),e.addCommand(k()),e.addCommand(N()),e.addCommand(I()),e.addCommand(X()),e.addCommand(L()),e}export{L as a,R as b,k as c,N as d,I as e,O as f,X as g,tn as h};//# sourceMappingURL=chunk-FTS5HDX6.js.map
|
|
22
|
+
//# sourceMappingURL=chunk-FTS5HDX6.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/commands/validate.ts","../src/commands/build.ts","../src/commands/dev.ts","../src/commands/doctor.ts","../src/commands/languages.ts","../src/commands/new.ts","../src/commands/templates.ts","../package.json","../src/utils/consola.ts","../src/program.ts"],"names":["prettifySchemaValidationError","error","resumePath","resumeStr","lineContent","pointer","filePath","chalk","errorType","message","codeLine","pointerLine","prettifyYamlParseError","errorMessage","lineMatch","joinNonEmptyString","line","column","validateResume","yamlStr","schema","lineCounter","LineCounter","resumeCST","parseDocument","validationResult","issues","issue","path","node","isNode","startOffset","pos","a","b","readResume","resuemPath","validate","fs","YAMLResumeError","resume","yaml","formattedError","errors","ResumeSchema","createValidateCommand","Command","validated","consola","inferOutput","outputDir","extname","baseName","getOutputPath","extension","index","total","fileName","getPdfPath","texPath","isCommandAvailable","command","which","inferLaTeXEnvironment","inferLaTeXCommand","resumePathOrTexFile","environment","texFile","args","cwd","normalizeExtension","generateOutput","layoutIndex","outputFile","dir","content","getResumeRenderer","LATEX_COMPILE_TIMEOUT_MS","compileLaTeX","timeout","execaTimeout","result","execa","toCodeBlock","parseTimeout","value","num","buildResume","options","allLayouts","DEFAULT_RESUME_LAYOUTS","totals","l","indices","createBuildCommand","watchResume","pdf","output","exclusiveBuild","coalesce","watcher","chokidar","createDevCommand","checkSystem","info","envinfo","checkXeTeX","stdout","checkTectonic","checkFonts","installedFonts","getFonts","fonts","font","status","f","createDoctorCommand","listLanguages","markdownTable","LOCALE_LANGUAGE_OPTIONS","getLocaleLanguageDetail","createLanguagesCommand","cmd","newResume","filename","templatePath","fileURLToPath","templateContent","createNewCommand","listTemplates","templates","LATEX_TEMPLATE_OPTIONS","details","getLatexTemplateDetail","HTML_TEMPLATE_OPTIONS","getHtmlTemplateDetail","createTemplatesCommand","package_default","setVerboseLog","verbose","createProgram","program","thisCommand"],"mappings":"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","file":"chunk-6AURNMNJ.js","sourcesContent":["/**\n * MIT License\n *\n * Copyright (c) 2023–Present PPResume (https://ppresume.com)\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport fs from 'node:fs'\nimport {\n joinNonEmptyString,\n type Resume,\n ResumeSchema,\n YAMLResumeError,\n} from '@yamlresume/core'\nimport chalk from 'chalk'\nimport { Command } from 'commander'\nimport consola from 'consola'\nimport yaml, { isNode, LineCounter, parseDocument } from 'yaml'\n\n/**\n * A positional error with line number, column number, and path.\n *\n * @param message The error message.\n * @param line The line number.\n * @param column The column number.\n * @param path The path to the error.\n */\nexport interface PositionalError {\n message: string\n line: number\n column: number\n path: (string | number | symbol)[]\n}\n\n/**\n * Formats an error in clang-style with line number, column pointer, and message\n *\n * @param error The positional error to format\n * @param resumePath The source file path\n * @param resumeStr The content of the source file for line display\n * @returns Formatted error string in clang style\n */\nexport function prettifySchemaValidationError(\n error: PositionalError,\n resumePath: string,\n resumeStr: string\n): string {\n // Normalize CRLF to LF for cross-platform consistency\n const lines = resumeStr.replace(/\\r\\n/g, '\\n').split('\\n')\n const lineContent = lines[error.line - 1] || ''\n\n // Create the pointer line with spaces and caret\n const pointer = `${' '.repeat(error.column - 1)}^`\n\n // Color scheme similar to clang with enhanced visibility\n const filePath = chalk.white.bold(\n `${resumePath}:${error.line}:${error.column}`\n )\n const errorType = chalk.red.bold('warning')\n const message = chalk.white(error.message)\n const codeLine = chalk.white(lineContent)\n const pointerLine = chalk.green.bold(pointer)\n\n return [\n `${filePath}: ${errorType}: ${message}`,\n `${codeLine}`,\n `${pointerLine}`,\n ].join('\\n')\n}\n\n/**\n * Parses YAML parsing error messages and extracts line/column information\n *\n * @param errorMessage The error message from `yaml.parse`\n * @param resumePath The source file path\n * @param resumeStr The content of the source file for line display\n * @returns Formatted error string in clang style\n */\nexport function prettifyYamlParseError(\n errorMessage: string,\n resumePath: string,\n resumeStr: string\n): string {\n // parse the error message to extract line and column\n // example:\n // \"Nested mappings are not allowed in compact mappings at line 6, column 10\"\n const lineMatch = errorMessage.match(/at line (\\d+), column (\\d+)/)\n\n if (!lineMatch) {\n // if we can't parse the error, return a simple formatted message\n return joinNonEmptyString(\n [\n chalk.white.bold(resumePath),\n chalk.red.bold('error'),\n `${chalk.white(errorMessage)}.`,\n ],\n ': '\n )\n }\n\n const line = Number.parseInt(lineMatch[1], 10)\n const column = Number.parseInt(lineMatch[2], 10)\n // Normalize CRLF to LF for cross-platform consistency\n const lines = resumeStr.replace(/\\r\\n/g, '\\n').split('\\n')\n const lineContent = lines[line - 1] || ''\n\n // create the pointer line with spaces and caret\n const pointer = `${' '.repeat(column - 1)}^`\n\n // color scheme similar to clang with enhanced visibility\n const filePath = chalk.white.bold(`${resumePath}:${line}:${column}`)\n const errorType = chalk.red.bold('error')\n const message = chalk.white(\n errorMessage\n .split('\\n')[0]\n .replace(/ at line \\d+, column \\d+:?/, '.')\n .trim()\n )\n const codeLine = chalk.white(lineContent)\n const pointerLine = chalk.green.bold(pointer)\n\n return [\n `${filePath}: ${errorType}: ${message}`,\n `${codeLine}`,\n `${pointerLine}`,\n ].join('\\n')\n}\n\n/**\n * Validates a YAML string against a Zod schema and returns errors.\n *\n * @param yamlStr The YAML string to validate.\n * @param schema The Zod schema to validate against.\n * @returns A list of positional errors, or an empty array if validation is\n * successful.\n */\nexport function validateResume(\n yamlStr: string,\n schema: typeof ResumeSchema\n): PositionalError[] {\n const lineCounter = new LineCounter()\n\n // CST: Concrete Syntax Tree\n const resumeCST = parseDocument(yamlStr, {\n lineCounter,\n keepSourceTokens: true,\n })\n\n const validationResult = schema.safeParse(resumeCST.toJS())\n\n if (validationResult.success) {\n return []\n }\n\n const {\n error: { issues },\n } = validationResult\n\n return issues\n .map((issue) => {\n const path = issue.path\n const node = resumeCST.getIn(path, true)\n\n let line = 1\n let column = 1\n\n if (isNode(node) && node.range) {\n const startOffset = node.range[0]\n const pos = lineCounter.linePos(startOffset)\n line = pos.line\n column = pos.col\n }\n\n return {\n message: issue.message,\n line,\n column,\n path,\n }\n })\n .sort((a, b) => a.line - b.line)\n}\n\n/**\n * Read the resume from the source file and validate it on request.\n *\n * Steps:\n *\n * 1. read the resume from the source file\n * 2. validate the resume with `yaml.parse`\n * 3. if `validate` is true, validate the resume with `ResumeSchema`\n *\n * @param resuemPath - The source resume file path (YAML, YML, or JSON).\n * @returns The resume object.\n * @throws {Error} If the source file cannot be read or is invalid.\n */\nexport function readResume(\n resuemPath: string,\n validate = true\n): { resume: Resume; validated: 'success' | 'failed' | 'unknown' } {\n let resumeStr: string\n\n try {\n resumeStr = fs.readFileSync(resuemPath, 'utf8')\n } catch (_error) {\n throw new YAMLResumeError('FILE_READ_ERROR', { path: resuemPath })\n }\n\n let resume: Resume\n\n try {\n resume = yaml.parse(resumeStr) as Resume\n } catch (error) {\n // Format YAML parsing errors in clang style\n //\n // Actually you can use `parseDocument` to get a list of errors, here we\n // only use `yaml.parse` to get the first error, which should be enough for\n // users to know that there is something wrong with the yaml file.\n const formattedError = prettifyYamlParseError(\n error.message,\n resuemPath,\n resumeStr\n )\n\n console.log(formattedError)\n throw new YAMLResumeError('INVALID_YAML', {\n error: `Failed to parse ${resuemPath}.`,\n })\n }\n\n if (validate) {\n const errors = validateResume(resumeStr, ResumeSchema)\n\n if (errors.length > 0) {\n for (const error of errors) {\n console.log(prettifySchemaValidationError(error, resuemPath, resumeStr))\n }\n\n return { resume, validated: 'failed' }\n }\n\n return { resume, validated: 'success' }\n }\n\n return { resume, validated: 'unknown' }\n}\n\n/**\n * Create a command instance to validate a YAML resume\n */\nexport function createValidateCommand() {\n return new Command()\n .name('validate')\n .description('validate a resume against the YAMLResume schema')\n .argument('<resume-path>', 'the resume file path')\n .action(async (resumePath: string) => {\n try {\n const { validated } = readResume(resumePath, true)\n\n if (validated === 'success') {\n consola.success('Resume validation passed.')\n }\n if (validated === 'failed') {\n consola.fail('Resume validation failed.')\n }\n } catch (error) {\n consola.error(error.message)\n process.exit(error.errno)\n }\n })\n}\n","/**\n * MIT License\n *\n * Copyright (c) 2023–Present PPResume (https://ppresume.com)\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport fs from 'node:fs'\nimport path from 'node:path'\nimport {\n DEFAULT_RESUME_LAYOUTS,\n getResumeRenderer,\n joinNonEmptyString,\n type Resume,\n toCodeBlock,\n YAMLResumeError,\n} from '@yamlresume/core'\nimport { Command } from 'commander'\nimport { consola } from 'consola'\nimport { execa } from 'execa'\nimport which from 'which'\n\nimport { readResume } from './validate'\n\n/**\n * Infer the output file name from the source file name\n *\n * For now we support yaml, yml and json file extensions, and the output file\n * will have a `.tex` extension.\n *\n * @param resumePath - The source resume file\n * @param outputDir - Optional output directory to place the file in\n * @returns The output file name\n * @throws {Error} If the source file has an unsupported extension.\n */\nexport function inferOutput(resumePath: string, outputDir?: string): string {\n const extname = path.extname(resumePath)\n\n if (\n resumePath.endsWith('.yaml') ||\n resumePath.endsWith('.yml') ||\n resumePath.endsWith('.json')\n ) {\n const baseName = path.basename(\n resumePath.replace(/\\.yaml|\\.yml|\\.json$/, '.tex')\n )\n if (outputDir) {\n return path.join(outputDir, baseName)\n }\n return resumePath.replace(/\\.yaml|\\.yml|\\.json$/, '.tex')\n }\n\n throw new YAMLResumeError('INVALID_EXTNAME', { extname })\n}\n\n/**\n * Get the output file path with support for multiple outputs and custom extension\n *\n * @param resumePath - The source resume file path\n * @param extension - The target file extension (e.g., '.tex', '.md')\n * @param index - The index of the current layout\n * @param total - The total number of layouts for this engine\n * @param outputDir - Optional output directory\n * @returns The determined output file path\n */\nfunction getOutputPath(\n resumePath: string,\n extension: string,\n index: number,\n total: number,\n outputDir?: string\n): string {\n const baseName = path.basename(resumePath.replace(/\\.yaml|\\.yml|\\.json$/, ''))\n\n // If there are multiple layouts, append the index to the filename\n // e.g., resume.0.tex, resume.1.tex\n // Otherwise, use the base filename\n // e.g., resume.tex\n const fileName =\n total > 1 ? `${baseName}.${index}${extension}` : `${baseName}${extension}`\n\n if (outputDir) {\n return path.join(outputDir, fileName)\n }\n return path.join(path.dirname(resumePath), fileName)\n}\n\n/**\n * Get the PDF output path from a tex file path\n *\n * @param texPath - The tex file path\n * @returns The PDF file path\n */\nexport function getPdfPath(texPath: string): string {\n return texPath.replace(/\\.tex$/, '.pdf')\n}\n\ntype LaTeXEnvironment = 'xelatex' | 'tectonic'\n\n/**\n * Check if a command is available\n *\n * @param command - The command to check\n * @returns True if the command is available, false otherwise\n */\nexport function isCommandAvailable(command: string): boolean {\n try {\n return !!which.sync(command)\n } catch {\n return false\n }\n}\n\n/**\n * Infer the LaTeX environment to use\n *\n * We support xelatex and tectonic, if both are installed we will prioritize\n * xelatex.\n *\n * @returns The LaTeX environment PATH.\n * @throws {Error} If neither 'xelatex' nor 'tectonic' is found in system PATH.\n */\nexport function inferLaTeXEnvironment(): LaTeXEnvironment {\n if (isCommandAvailable('xelatex')) {\n return 'xelatex'\n }\n\n if (isCommandAvailable('tectonic')) {\n return 'tectonic'\n }\n\n throw new YAMLResumeError('LATEX_NOT_FOUND', {})\n}\n\n/**\n * Infer the LaTeX command to use based on the LaTeX environment\n *\n * @param resumePathOrTexFile - The source resume file OR the target .tex file\n * @param outputDir - Optional output directory\n * @returns The LaTeX command\n * @throws {Error} If the LaTeX environment cannot be inferred or the source\n * file extension is unsupported.\n */\nexport function inferLaTeXCommand(\n resumePathOrTexFile: string,\n outputDir?: string\n): { command: string; args: string[]; cwd: string } {\n const environment = inferLaTeXEnvironment()\n\n // If the input is already a .tex file, use it directly; otherwise infer from .yaml/.json\n const texFile = resumePathOrTexFile.endsWith('.tex')\n ? resumePathOrTexFile\n : inferOutput(resumePathOrTexFile, outputDir)\n\n let command = ''\n let args: string[] = []\n\n switch (environment) {\n case 'xelatex':\n command = 'xelatex'\n args = ['-halt-on-error', path.basename(texFile)]\n break\n case 'tectonic':\n command = 'tectonic'\n args = [path.basename(texFile)]\n break\n }\n\n const cwd = outputDir\n ? path.resolve(outputDir)\n : path.dirname(path.resolve(texFile))\n\n return { command, args, cwd }\n}\n\n/**\n * Normalize the file extension that can be used in the output file name\n *\n * @param extension - file extension\n * @returns\n */\nexport function normalizeExtension(extension: string): string {\n switch (extension) {\n case '.tex':\n return 'tex'\n case '.md':\n return 'markdown'\n case '.html':\n return 'html'\n default:\n return extension.replace('.', '')\n }\n}\n\n/**\n * Shared helper to generate output file from a layout\n */\nfunction generateOutput(\n resumePath: string,\n resume: Resume,\n index: number,\n total: number,\n outputDir: string | undefined,\n extension: string,\n layoutIndex: number\n): string {\n const outputFile = getOutputPath(\n resumePath,\n extension,\n index,\n total,\n outputDir\n )\n\n const dir = path.dirname(outputFile)\n if (!fs.existsSync(dir)) {\n fs.mkdirSync(dir, { recursive: true })\n }\n\n const renderer = getResumeRenderer(resume, layoutIndex)\n const content = renderer.render()\n\n try {\n fs.writeFileSync(outputFile, content)\n consola.success(\n joinNonEmptyString(\n [\n `Generated resume ${normalizeExtension(extension)} file successfully:`,\n outputFile,\n ],\n ' '\n )\n )\n } catch (_error) {\n throw new YAMLResumeError('FILE_WRITE_ERROR', { path: outputFile })\n }\n\n return outputFile\n}\n\n/**\n * Default timeout for LaTeX compilation in milliseconds (30 seconds)\n */\nexport const LATEX_COMPILE_TIMEOUT_MS = 30000\n\n/**\n * Compile a TeX file to PDF\n *\n * @param texFile - The TeX file to compile.\n * @param outputDir - Optional output directory.\n * @param timeout - Timeout in milliseconds. 0 means no timeout.\n */\nasync function compileLaTeX(\n texFile: string,\n outputDir?: string,\n timeout: number = LATEX_COMPILE_TIMEOUT_MS\n) {\n const { command, args, cwd } = inferLaTeXCommand(texFile, outputDir)\n\n consola.start(\n `Generating resume pdf file with command: \\`${command} ${args.join(' ')}\\`...`\n )\n\n // When timeout is 0, disable timeout by setting it to undefined\n const execaTimeout = timeout === 0 ? undefined : timeout\n\n try {\n const result = await execa(command, args, {\n cwd,\n encoding: 'utf8',\n timeout: execaTimeout,\n })\n consola.success(\n `Generated resume pdf file successfully: ${getPdfPath(texFile)}`\n )\n consola.debug(joinNonEmptyString(['stdout: ', toCodeBlock(result.stdout)]))\n } catch (error) {\n // Check if it's a timeout error\n if (error.timedOut) {\n // Show raw logs to help users diagnose the issue\n if (error.stdout) {\n consola.info('LaTeX output before timeout:')\n consola.log(error.stdout)\n }\n if (error.stderr) {\n consola.info('LaTeX error output:')\n consola.log(error.stderr)\n }\n throw new YAMLResumeError('LATEX_COMPILE_TIMEOUT', {\n timeout: String(timeout / 1000),\n })\n }\n\n consola.debug(joinNonEmptyString(['stdout: ', toCodeBlock(error.stdout)]))\n consola.debug(joinNonEmptyString(['stderr: ', toCodeBlock(error.stderr)]))\n throw new YAMLResumeError('LATEX_COMPILE_ERROR', { error: error.message })\n }\n}\n\n/**\n * Parse and validate the timeout option.\n *\n * If the value is invalid, logs a warning and returns the default timeout.\n *\n * @param value - The timeout value in seconds as a string.\n * @returns The parsed timeout in milliseconds.\n */\nexport function parseTimeout(value: string): number {\n const num = Number(value)\n\n if (Number.isNaN(num) || num < 0) {\n consola.warn(\n joinNonEmptyString(\n [\n `Invalid timeout value: \"${value}\".`,\n `Using default timeout: ${LATEX_COMPILE_TIMEOUT_MS / 1000}s.`,\n 'Timeout must be a non-negative number in seconds (0 to disable).',\n ],\n ' '\n )\n )\n return LATEX_COMPILE_TIMEOUT_MS\n }\n\n // Convert seconds to milliseconds (supports fractional seconds like curl)\n return num * 1000\n}\n\n/**\n * Build a YAML resume to LaTeX & PDF and/or Markdown\n *\n * It first validates the resume against the schema (unless `--no-validate` flag\n * is used), then iterates through configured layouts to generate outputs.\n *\n * @param resumePath - The source resume file path (YAML, YML, or JSON).\n * @param options - Build options including validation, PDF generation flags,\n * output directory, and LaTeX compilation timeout.\n */\nexport async function buildResume(\n resumePath: string,\n options: {\n pdf?: boolean\n validate?: boolean\n output?: string\n timeout?: number\n } = {\n pdf: true,\n validate: true,\n timeout: LATEX_COMPILE_TIMEOUT_MS,\n }\n) {\n const { resume } = readResume(resumePath, options.validate)\n\n // Fallback to default layout if none provided\n const allLayouts = resume.layouts ?? DEFAULT_RESUME_LAYOUTS\n // Ensure resume has layouts for the renderer to use\n if (!resume.layouts) {\n resume.layouts = allLayouts\n }\n\n // Count totals for each engine to determine file naming strategy\n // (e.g. resume.0.tex vs resume.tex)\n const totals = {\n latex: allLayouts.filter((l) => l.engine === 'latex').length,\n markdown: allLayouts.filter((l) => l.engine === 'markdown').length,\n html: allLayouts.filter((l) => l.engine === 'html').length,\n }\n\n // Track current index for each engine\n const indices = {\n latex: 0,\n markdown: 0,\n html: 0,\n }\n\n for (let layoutIndex = 0; layoutIndex < allLayouts.length; layoutIndex++) {\n const layout = allLayouts[layoutIndex]\n\n switch (layout.engine) {\n case 'latex': {\n const texFile = generateOutput(\n resumePath,\n resume,\n indices.latex++,\n totals.latex,\n options.output,\n '.tex',\n layoutIndex\n )\n\n if (options.pdf === true) {\n await compileLaTeX(texFile, options.output, options.timeout)\n }\n break\n }\n case 'markdown': {\n generateOutput(\n resumePath,\n resume,\n indices.markdown++,\n totals.markdown,\n options.output,\n '.md',\n layoutIndex\n )\n break\n }\n case 'html': {\n generateOutput(\n resumePath,\n resume,\n indices.html++,\n totals.html,\n options.output,\n '.html',\n layoutIndex\n )\n break\n }\n }\n }\n}\n\n/**\n * Create a command instance to build a YAML resume to LaTeX and PDF\n */\nexport function createBuildCommand() {\n return new Command()\n .name('build')\n .description('build a resume to LaTeX, PDF, Markdown, or HTML')\n .argument('<resume-path>', 'the resume file path')\n .option(\n '--no-pdf',\n 'only generate TeX file without PDF (for LaTeX layouts)'\n )\n .option('--no-validate', 'skip resume schema validation')\n .option('-o, --output <dir>', 'output directory for generated files')\n .option(\n '-t, --timeout <seconds>',\n joinNonEmptyString(\n [\n 'timeout for LaTeX compilation in seconds',\n `(default: ${LATEX_COMPILE_TIMEOUT_MS / 1000}, 0 to disable)`,\n ],\n ' '\n ),\n (value) => parseTimeout(value)\n )\n .action(\n async (\n resumePath: string,\n options: {\n pdf: boolean\n validate: boolean\n output?: string\n timeout: number\n }\n ) => {\n try {\n await buildResume(resumePath, options)\n } catch (error) {\n consola.error(error.message)\n process.exit(error.errno)\n }\n }\n )\n}\n","/**\n * MIT License\n *\n * Copyright (c) 2023–Present PPResume (https://ppresume.com)\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport chokidar from 'chokidar'\n\nimport { coalesce } from 'coalescifn'\nimport { Command } from 'commander'\nimport { consola } from 'consola'\n\nimport { buildResume } from './build'\n\n/**\n * Options for the watchResume function\n *\n * @param pdf - Whether to generate PDF\n * @param validate - Whether to validate the resume\n */\ntype WatchOptions = {\n pdf?: boolean\n validate?: boolean\n output?: string\n}\n\n/**\n * Watch a resume source file and rebuild on changes.\n *\n * - Only one build runs at a time.\n * - If multiple events arrive during a build, run exactly one more build after\n * it finishes (coalesce bursts).\n * - Uses chokidar for robust file watching that handles editor operations.\n *\n * @param resumePath - The resume file to watch\n * @param options - Build and watch options\n * @returns Chokidar watcher instance\n */\nexport function watchResume(\n resumePath: string,\n options: WatchOptions = { pdf: true, validate: true }\n) {\n const { pdf, validate, output } = options\n\n // there should be only one build running at a time\n const exclusiveBuild = coalesce(() =>\n buildResume(resumePath, { pdf, validate, output })\n )\n\n // initial build\n exclusiveBuild()\n\n consola.start(`Watching file changes: ${resumePath}...`)\n\n // use chokidar for robust file watching that handles vim and other editors\n // properly.\n //\n // vim will save the file in a single atomic operation, that being said, it\n // will first create a temporary file (the '.swp' file), then rename it to the\n // final file.\n //\n // Node.js `fs.watch` has trouble with this, so we use chokidar instead.\n const watcher = chokidar.watch(resumePath, {\n awaitWriteFinish: {\n stabilityThreshold: 200, // wait 200ms after file stops changing\n pollInterval: 200, // check every 200ms\n },\n ignoreInitial: true, // don't trigger on initial file discovery\n })\n\n // handle file changes - chokidar's awaitWriteFinish already handles\n // debouncing\n watcher.on('change', () => exclusiveBuild())\n\n // handle file additions (in case file gets recreated)\n watcher.on('add', () => exclusiveBuild())\n\n return watcher\n}\n\n/**\n * Create a command instance to run in watch mode\n */\nexport function createDevCommand() {\n return new Command()\n .name('dev')\n .description('build a resume on file changes (watch mode)')\n .argument('<resume-path>', 'the resume file path')\n .option('--no-pdf', 'only generate TeX file without PDF')\n .option('--no-validate', 'skip resume schema validation')\n .option('-o, --output <dir>', 'output directory for generated files')\n .action(\n (\n resumePath: string,\n options: { pdf: boolean; validate: boolean; output?: string }\n ) => {\n watchResume(resumePath, options)\n }\n )\n}\n","/**\n * MIT License\n *\n * Copyright (c) 2023–Present PPResume (https://ppresume.com)\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport { Command } from 'commander'\nimport consola from 'consola'\nimport envinfo from 'envinfo'\nimport { execa } from 'execa'\nimport { getFonts } from 'font-list'\n\n/**\n * Check system information\n */\nexport async function checkSystem() {\n const info = await envinfo.run(\n {\n System: ['OS', 'CPU'],\n Binaries: ['Node', 'Yarn', 'npm', 'pnpm', 'Bun'],\n },\n { json: false, showNotFound: true }\n )\n console.log(info)\n}\n\n/**\n * Check if XeTeX is installed\n */\nexport async function checkXeTeX() {\n consola.info('Checking XeTeX...')\n try {\n const { stdout } = await execa('xelatex', ['--version'])\n console.log(` XeTeX: ${stdout.split('\\n')[0]}\\n`)\n } catch {\n console.log(' XeTeX: Not Found\\n')\n }\n}\n\n/**\n * Check if Tectonic is installed\n */\nexport async function checkTectonic() {\n consola.info('Checking Tectonic...')\n try {\n const { stdout } = await execa('tectonic', ['--version'])\n console.log(` Tectonic: ${stdout.split('\\n')[0]}\\n`)\n } catch {\n console.log(' Tectonic: Not Found\\n')\n }\n}\n\n/**\n * Check if required fonts are installed\n */\nexport async function checkFonts() {\n consola.info('Checking Fonts...')\n const installedFonts = await getFonts({ disableQuoting: true })\n const fonts = [\n 'Linux Libertine O',\n 'Linux Libertine',\n 'Noto Serif CJK SC',\n 'Noto Sans CJK SC',\n ]\n\n for (const font of fonts) {\n // font-list returns fonts like \"Arial\" or \"Times New Roman\" in an array\n // We check if the required font is included in the list\n // The checking is case-insensitive\n const isInstalled = installedFonts.some((f) =>\n f.toLowerCase().includes(font.toLowerCase())\n )\n const status = isInstalled ? 'Installed' : 'Not Installed'\n console.log(` ${font}: ${status}`)\n }\n}\n\n/**\n * Create a command instance to check the environment\n */\nexport function createDoctorCommand() {\n return new Command()\n .name('doctor')\n .description('check environment for YAMLResume dependencies')\n .action(async () => {\n await checkSystem()\n await checkXeTeX()\n await checkTectonic()\n await checkFonts()\n })\n}\n","/**\n * MIT License\n *\n * Copyright (c) 2023–Present PPResume (https://ppresume.com)\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport {\n getLocaleLanguageDetail,\n LOCALE_LANGUAGE_OPTIONS,\n} from '@yamlresume/core'\nimport { Command } from 'commander'\nimport consola from 'consola'\nimport { markdownTable } from 'markdown-table'\n\n/**\n * Generates a markdown table listing all supported locale languages.\n *\n * The table includes columns for the language code and the language name.\n *\n * @returns A string containing the formatted markdown table.\n */\nexport function listLanguages() {\n return markdownTable([\n ['locale.language', 'Language Name'],\n ...LOCALE_LANGUAGE_OPTIONS.map((value) => [\n value,\n getLocaleLanguageDetail(value).name,\n ]),\n ])\n}\n\n/**\n * Create a command instance to list supported languages\n */\n\nexport function createLanguagesCommand() {\n const cmd = new Command()\n .name('languages')\n .description('i18n and l10n support')\n\n cmd\n .command('list')\n .description('list all supported languages')\n .action(() => {\n consola.log(listLanguages())\n })\n\n return cmd\n}\n","/**\n * MIT License\n *\n * Copyright (c) 2023–Present PPResume (https://ppresume.com)\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport fs from 'node:fs'\nimport path from 'node:path'\nimport { fileURLToPath } from 'node:url'\nimport {\n joinNonEmptyString,\n toCodeBlock,\n YAMLResumeError,\n} from '@yamlresume/core'\nimport { Command } from 'commander'\nimport consola from 'consola'\n\n/**\n * Creates a new resume file with the given filename\n *\n * @param filename - The name of the resume file to create\n * @throws {YAMLResumeError} When there are file-related errors:\n * - FILE_CONFLICT: When the file already exists\n * - FILE_READ_ERROR: When there's an error reading the template\n * - FILE_WRITE_ERROR: When there's an error writing the file\n */\nexport function newResume(filename: string) {\n if (fs.existsSync(filename)) {\n throw new YAMLResumeError('FILE_CONFLICT', { path: filename })\n }\n\n const templatePath = path.join(\n path.dirname(fileURLToPath(import.meta.url)),\n /* v8 ignore start */\n // I din't find a way to mock `import.meta.url` in tests so we have to\n // ignore the following lines for coverage calculation\n import.meta.url.includes('dist')\n ? '../resources/resume.yml'\n : '../../resources/resume.yml'\n /* v8 ignore stop */\n )\n\n let templateContent: string\n\n try {\n templateContent = fs.readFileSync(templatePath, 'utf8')\n } catch (error) {\n consola.debug(\n joinNonEmptyString(['Error reading template: ', toCodeBlock(error.stack)])\n )\n throw new YAMLResumeError('FILE_READ_ERROR', { path: templatePath })\n }\n\n try {\n fs.writeFileSync(filename, templateContent)\n consola.success(`Created ${filename} successfully.`)\n } catch (error) {\n consola.debug(\n joinNonEmptyString(['Error creating resume: ', toCodeBlock(error.stack)])\n )\n throw new YAMLResumeError('FILE_WRITE_ERROR', { path: filename })\n }\n}\n\n/**\n * Create a command instance to create a new YAML resume\n */\nexport function createNewCommand() {\n return new Command()\n .name('new')\n .description('create a new resume')\n .argument('[filename]', 'output filename', 'resume.yml')\n .action((filename) => {\n try {\n newResume(filename)\n } catch (error) {\n consola.error(error.message)\n process.exit(error.errno)\n }\n })\n}\n","/**\n * MIT License\n *\n * Copyright (c) 2023–Present PPResume (https://ppresume.com)\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport {\n getHtmlTemplateDetail,\n getLatexTemplateDetail,\n HTML_TEMPLATE_OPTIONS,\n LATEX_TEMPLATE_OPTIONS,\n} from '@yamlresume/core'\nimport { Command } from 'commander'\nimport consola from 'consola'\nimport { markdownTable } from 'markdown-table'\n\n/**\n * Generates a markdown table listing all supported templates.\n *\n * The table includes columns for the template id, name and description.\n *\n * @returns A string containing the formatted markdown table.\n */\nexport function listTemplates() {\n const templates = [\n ...LATEX_TEMPLATE_OPTIONS.map((value) => {\n const details = getLatexTemplateDetail(value)\n return [value, details.engine, details.name, details.description]\n }),\n ...HTML_TEMPLATE_OPTIONS.map((value) => {\n const details = getHtmlTemplateDetail(value)\n return [value, details.engine, details.name, details.description]\n }),\n ]\n\n return markdownTable([\n ['layouts.[].template', 'Engine', 'Template Name', 'Description'],\n ...templates,\n ])\n}\n\n/**\n * Create a command instance to list supported templates\n */\nexport function createTemplatesCommand() {\n const cmd = new Command()\n .name('templates')\n .description('manage resume templates')\n\n cmd\n .command('list')\n .description('list all supported templates')\n .action(() => {\n consola.log(listTemplates())\n })\n\n return cmd\n}\n","{\n \"name\": \"yamlresume\",\n \"version\": \"0.12.2\",\n \"description\": \"The CLI interface for YAMLResume's engine\",\n \"license\": \"MIT\",\n \"author\": {\n \"name\": \"YAMLResume\",\n \"email\": \"support@yamlresume.com\",\n \"url\": \"https://yamlresume.dev\"\n },\n \"keywords\": [\n \"YAMLResume\",\n \"CV\",\n \"Resume\",\n \"LaTeX\",\n \"Typesetting\",\n \"PDF\",\n \"YAML\",\n \"JSON\"\n ],\n \"type\": \"module\",\n \"main\": \"./dist/index.js\",\n \"types\": \"./dist/index.d.ts\",\n \"exports\": {\n \".\": {\n \"types\": \"./dist/index.d.ts\",\n \"default\": \"./dist/index.js\"\n }\n },\n \"bin\": {\n \"yamlresume\": \"./dist/cli.js\"\n },\n \"files\": [\n \"dist\",\n \"README.md\",\n \"LICENSE\",\n \"resources/resume.yml\"\n ],\n \"scripts\": {\n \"build\": \"tsup\",\n \"build:watch\": \"tsup --watch\",\n \"build:clean\": \"rm -rf dist\",\n \"build:prod\": \"tsup --dts --minify --sourcemap\",\n \"prepublishOnly\": \"pnpm test\",\n \"dev\": \"tsx src/cli.ts\",\n \"test\": \"vitest --run\",\n \"test:cov\": \"vitest --coverage --run\",\n \"test:watch\": \"vitest\",\n \"typedoc\": \"typedoc\"\n },\n \"dependencies\": {\n \"@yamlresume/core\": \"workspace:*\",\n \"chalk\": \"^5.6.2\",\n \"chokidar\": \"^4.0.3\",\n \"coalescifn\": \"^0.1.1\",\n \"commander\": \"^14.0.1\",\n \"consola\": \"^3.4.2\",\n \"envinfo\": \"^7.21.0\",\n \"execa\": \"^9.6.1\",\n \"extensionless\": \"^2.0.6\",\n \"font-list\": \"^2.0.2\",\n \"lodash-es\": \"^4.17.23\",\n \"markdown-table\": \"^3.0.4\",\n \"tslib\": \"^2.8.1\",\n \"which\": \"^6.0.1\",\n \"yaml\": \"^2.8.2\"\n },\n \"devDependencies\": {\n \"@types/envinfo\": \"^7.8.4\",\n \"@types/which\": \"^3.0.4\"\n },\n \"publishConfig\": {\n \"access\": \"public\"\n },\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"https://github.com/yamlresume/yamlresume.git\",\n \"directory\": \"packages/cli\"\n },\n \"bugs\": {\n \"url\": \"https://github.com/yamlresume/yamlresume/issues\"\n },\n \"homepage\": \"https://yamlresume.dev/docs/cli\",\n \"engines\": {\n \"node\": \">=20.0.0\"\n }\n}\n","/**\n * MIT License\n *\n * Copyright (c) 2023–Present PPResume (https://ppresume.com)\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport consola from 'consola'\n\n/**\n * Set the verbose mode for consola\n *\n * @param verbose - Whether to enable verbose mode\n * @see https://github.com/unjs/consola?tab=readme-ov-file#log-level\n */\nexport function setVerboseLog(verbose: boolean) {\n consola.level = verbose ? 4 : 3\n}\n","/**\n * MIT License\n *\n * Copyright (c) 2023–Present PPResume (https://ppresume.com)\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport { Command } from 'commander'\n\nimport packageJson from '../package.json' with { type: 'json' }\nimport {\n createBuildCommand,\n createDevCommand,\n createDoctorCommand,\n createLanguagesCommand,\n createNewCommand,\n createTemplatesCommand,\n createValidateCommand,\n} from './commands'\nimport { setVerboseLog } from './utils'\n\n/**\n * Create the CLI program.\n *\n * @returns The CLI program.\n */\nexport function createProgram(): Command {\n const program = new Command()\n\n const banner = `\n __ __ _ __ __ _ ____\n \\\\ \\\\ / // \\\\ | \\\\/ | | | _ \\\\ ___ ___ _ _ ___ ___ ___\n \\\\ V // _ \\\\ | |\\\\/| | | | |_) / _ \\\\/ __| | | / _ \\\\/ _ \\\\ / _ \\\\\n | |/ ___ \\\\| | | | |___| _ < __/\\\\__ \\\\ |_| | | | | | | __/\n |_/_/ \\\\_\\\\_| |_|_____|_| \\\\_\\\\___||___/\\\\____|_| |_| |_|\\\\___|\n`\n\n program\n .name('yamlresume')\n .description(['YAMLResume — Resume as Code in YAML', banner].join('\\n'))\n .version(packageJson.version)\n .option('-v, --verbose', 'verbose output')\n .hook('preAction', (thisCommand) => {\n setVerboseLog(thisCommand.opts().verbose)\n })\n\n program.addCommand(createNewCommand())\n program.addCommand(createBuildCommand())\n program.addCommand(createDevCommand())\n program.addCommand(createDoctorCommand())\n program.addCommand(createLanguagesCommand())\n program.addCommand(createTemplatesCommand())\n program.addCommand(createValidateCommand())\n\n return program\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/commands/validate.ts","../src/commands/build.ts","../src/commands/dev.ts","../src/commands/doctor.ts","../src/commands/languages.ts","../src/commands/new.ts","../src/commands/templates.ts","../package.json","../src/utils/consola.ts","../src/program.ts"],"names":["prettifySchemaValidationError","error","resumePath","resumeStr","lineContent","pointer","filePath","chalk","errorType","message","codeLine","pointerLine","prettifyYamlParseError","errorMessage","lineMatch","joinNonEmptyString","line","column","validateResume","yamlStr","schema","lineCounter","LineCounter","resumeCST","parseDocument","validationResult","issues","issue","path","node","isNode","startOffset","pos","a","b","readResume","resuemPath","validate","fs","YAMLResumeError","resume","yaml","formattedError","errors","ResumeSchema","createValidateCommand","Command","validated","consola","inferOutput","outputDir","extname","baseName","getOutputPath","extension","index","total","fileName","getPdfPath","texPath","isCommandAvailable","command","which","inferLaTeXEnvironment","inferLaTeXCommand","resumePathOrTexFile","environment","texFile","args","cwd","normalizeExtension","generateOutput","layoutIndex","outputFile","dir","content","getResumeRenderer","LATEX_COMPILE_TIMEOUT_MS","compileLaTeX","timeout","execaTimeout","result","execa","toCodeBlock","parseTimeout","value","num","buildResume","options","allLayouts","DEFAULT_RESUME_LAYOUTS","totals","l","indices","createBuildCommand","watchResume","pdf","output","exclusiveBuild","coalesce","watcher","chokidar","createDevCommand","checkSystem","info","envinfo","checkXeTeX","stdout","checkTectonic","checkFonts","installedFonts","getFonts","fonts","font","status","f","createDoctorCommand","listLanguages","markdownTable","LOCALE_LANGUAGE_OPTIONS","getLocaleLanguageDetail","createLanguagesCommand","cmd","newResume","filename","templatePath","fileURLToPath","templateContent","createNewCommand","listTemplates","templates","LATEX_TEMPLATE_OPTIONS","details","getLatexTemplateDetail","HTML_TEMPLATE_OPTIONS","getHtmlTemplateDetail","createTemplatesCommand","package_default","setVerboseLog","verbose","createProgram","program","thisCommand"],"mappings":"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","file":"chunk-FTS5HDX6.js","sourcesContent":["/**\n * MIT License\n *\n * Copyright (c) 2023–Present PPResume (https://ppresume.com)\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport fs from 'node:fs'\nimport {\n joinNonEmptyString,\n type Resume,\n ResumeSchema,\n YAMLResumeError,\n} from '@yamlresume/core'\nimport chalk from 'chalk'\nimport { Command } from 'commander'\nimport consola from 'consola'\nimport yaml, { isNode, LineCounter, parseDocument } from 'yaml'\n\n/**\n * A positional error with line number, column number, and path.\n *\n * @param message The error message.\n * @param line The line number.\n * @param column The column number.\n * @param path The path to the error.\n */\nexport interface PositionalError {\n message: string\n line: number\n column: number\n path: (string | number | symbol)[]\n}\n\n/**\n * Formats an error in clang-style with line number, column pointer, and message\n *\n * @param error The positional error to format\n * @param resumePath The source file path\n * @param resumeStr The content of the source file for line display\n * @returns Formatted error string in clang style\n */\nexport function prettifySchemaValidationError(\n error: PositionalError,\n resumePath: string,\n resumeStr: string\n): string {\n // Normalize CRLF to LF for cross-platform consistency\n const lines = resumeStr.replace(/\\r\\n/g, '\\n').split('\\n')\n const lineContent = lines[error.line - 1] || ''\n\n // Create the pointer line with spaces and caret\n const pointer = `${' '.repeat(error.column - 1)}^`\n\n // Color scheme similar to clang with enhanced visibility\n const filePath = chalk.white.bold(\n `${resumePath}:${error.line}:${error.column}`\n )\n const errorType = chalk.red.bold('warning')\n const message = chalk.white(error.message)\n const codeLine = chalk.white(lineContent)\n const pointerLine = chalk.green.bold(pointer)\n\n return [\n `${filePath}: ${errorType}: ${message}`,\n `${codeLine}`,\n `${pointerLine}`,\n ].join('\\n')\n}\n\n/**\n * Parses YAML parsing error messages and extracts line/column information\n *\n * @param errorMessage The error message from `yaml.parse`\n * @param resumePath The source file path\n * @param resumeStr The content of the source file for line display\n * @returns Formatted error string in clang style\n */\nexport function prettifyYamlParseError(\n errorMessage: string,\n resumePath: string,\n resumeStr: string\n): string {\n // parse the error message to extract line and column\n // example:\n // \"Nested mappings are not allowed in compact mappings at line 6, column 10\"\n const lineMatch = errorMessage.match(/at line (\\d+), column (\\d+)/)\n\n if (!lineMatch) {\n // if we can't parse the error, return a simple formatted message\n return joinNonEmptyString(\n [\n chalk.white.bold(resumePath),\n chalk.red.bold('error'),\n `${chalk.white(errorMessage)}.`,\n ],\n ': '\n )\n }\n\n const line = Number.parseInt(lineMatch[1], 10)\n const column = Number.parseInt(lineMatch[2], 10)\n // Normalize CRLF to LF for cross-platform consistency\n const lines = resumeStr.replace(/\\r\\n/g, '\\n').split('\\n')\n const lineContent = lines[line - 1] || ''\n\n // create the pointer line with spaces and caret\n const pointer = `${' '.repeat(column - 1)}^`\n\n // color scheme similar to clang with enhanced visibility\n const filePath = chalk.white.bold(`${resumePath}:${line}:${column}`)\n const errorType = chalk.red.bold('error')\n const message = chalk.white(\n errorMessage\n .split('\\n')[0]\n .replace(/ at line \\d+, column \\d+:?/, '.')\n .trim()\n )\n const codeLine = chalk.white(lineContent)\n const pointerLine = chalk.green.bold(pointer)\n\n return [\n `${filePath}: ${errorType}: ${message}`,\n `${codeLine}`,\n `${pointerLine}`,\n ].join('\\n')\n}\n\n/**\n * Validates a YAML string against a Zod schema and returns errors.\n *\n * @param yamlStr The YAML string to validate.\n * @param schema The Zod schema to validate against.\n * @returns A list of positional errors, or an empty array if validation is\n * successful.\n */\nexport function validateResume(\n yamlStr: string,\n schema: typeof ResumeSchema\n): PositionalError[] {\n const lineCounter = new LineCounter()\n\n // CST: Concrete Syntax Tree\n const resumeCST = parseDocument(yamlStr, {\n lineCounter,\n keepSourceTokens: true,\n })\n\n const validationResult = schema.safeParse(resumeCST.toJS())\n\n if (validationResult.success) {\n return []\n }\n\n const {\n error: { issues },\n } = validationResult\n\n return issues\n .map((issue) => {\n const path = issue.path\n const node = resumeCST.getIn(path, true)\n\n let line = 1\n let column = 1\n\n if (isNode(node) && node.range) {\n const startOffset = node.range[0]\n const pos = lineCounter.linePos(startOffset)\n line = pos.line\n column = pos.col\n }\n\n return {\n message: issue.message,\n line,\n column,\n path,\n }\n })\n .sort((a, b) => a.line - b.line)\n}\n\n/**\n * Read the resume from the source file and validate it on request.\n *\n * Steps:\n *\n * 1. read the resume from the source file\n * 2. validate the resume with `yaml.parse`\n * 3. if `validate` is true, validate the resume with `ResumeSchema`\n *\n * @param resuemPath - The source resume file path (YAML, YML, or JSON).\n * @returns The resume object.\n * @throws {Error} If the source file cannot be read or is invalid.\n */\nexport function readResume(\n resuemPath: string,\n validate = true\n): { resume: Resume; validated: 'success' | 'failed' | 'unknown' } {\n let resumeStr: string\n\n try {\n resumeStr = fs.readFileSync(resuemPath, 'utf8')\n } catch (_error) {\n throw new YAMLResumeError('FILE_READ_ERROR', { path: resuemPath })\n }\n\n let resume: Resume\n\n try {\n resume = yaml.parse(resumeStr) as Resume\n } catch (error) {\n // Format YAML parsing errors in clang style\n //\n // Actually you can use `parseDocument` to get a list of errors, here we\n // only use `yaml.parse` to get the first error, which should be enough for\n // users to know that there is something wrong with the yaml file.\n const formattedError = prettifyYamlParseError(\n error.message,\n resuemPath,\n resumeStr\n )\n\n console.log(formattedError)\n throw new YAMLResumeError('INVALID_YAML', {\n error: `Failed to parse ${resuemPath}.`,\n })\n }\n\n if (validate) {\n const errors = validateResume(resumeStr, ResumeSchema)\n\n if (errors.length > 0) {\n for (const error of errors) {\n console.log(prettifySchemaValidationError(error, resuemPath, resumeStr))\n }\n\n return { resume, validated: 'failed' }\n }\n\n return { resume, validated: 'success' }\n }\n\n return { resume, validated: 'unknown' }\n}\n\n/**\n * Create a command instance to validate a YAML resume\n */\nexport function createValidateCommand() {\n return new Command()\n .name('validate')\n .description('validate a resume against the YAMLResume schema')\n .argument('<resume-path>', 'the resume file path')\n .action(async (resumePath: string) => {\n try {\n const { validated } = readResume(resumePath, true)\n\n if (validated === 'success') {\n consola.success('Resume validation passed.')\n }\n if (validated === 'failed') {\n consola.fail('Resume validation failed.')\n }\n } catch (error) {\n consola.error(error.message)\n process.exit(error.errno)\n }\n })\n}\n","/**\n * MIT License\n *\n * Copyright (c) 2023–Present PPResume (https://ppresume.com)\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport fs from 'node:fs'\nimport path from 'node:path'\nimport {\n DEFAULT_RESUME_LAYOUTS,\n getResumeRenderer,\n joinNonEmptyString,\n type Resume,\n toCodeBlock,\n YAMLResumeError,\n} from '@yamlresume/core'\nimport { Command } from 'commander'\nimport { consola } from 'consola'\nimport { execa } from 'execa'\nimport which from 'which'\n\nimport { readResume } from './validate'\n\n/**\n * Infer the output file name from the source file name\n *\n * For now we support yaml, yml and json file extensions, and the output file\n * will have a `.tex` extension.\n *\n * @param resumePath - The source resume file\n * @param outputDir - Optional output directory to place the file in\n * @returns The output file name\n * @throws {Error} If the source file has an unsupported extension.\n */\nexport function inferOutput(resumePath: string, outputDir?: string): string {\n const extname = path.extname(resumePath)\n\n if (\n resumePath.endsWith('.yaml') ||\n resumePath.endsWith('.yml') ||\n resumePath.endsWith('.json')\n ) {\n const baseName = path.basename(\n resumePath.replace(/\\.yaml|\\.yml|\\.json$/, '.tex')\n )\n if (outputDir) {\n return path.join(outputDir, baseName)\n }\n return resumePath.replace(/\\.yaml|\\.yml|\\.json$/, '.tex')\n }\n\n throw new YAMLResumeError('INVALID_EXTNAME', { extname })\n}\n\n/**\n * Get the output file path with support for multiple outputs and custom extension\n *\n * @param resumePath - The source resume file path\n * @param extension - The target file extension (e.g., '.tex', '.md')\n * @param index - The index of the current layout\n * @param total - The total number of layouts for this engine\n * @param outputDir - Optional output directory\n * @returns The determined output file path\n */\nfunction getOutputPath(\n resumePath: string,\n extension: string,\n index: number,\n total: number,\n outputDir?: string\n): string {\n const baseName = path.basename(resumePath.replace(/\\.yaml|\\.yml|\\.json$/, ''))\n\n // If there are multiple layouts, append the index to the filename\n // e.g., resume.0.tex, resume.1.tex\n // Otherwise, use the base filename\n // e.g., resume.tex\n const fileName =\n total > 1 ? `${baseName}.${index}${extension}` : `${baseName}${extension}`\n\n if (outputDir) {\n return path.join(outputDir, fileName)\n }\n return path.join(path.dirname(resumePath), fileName)\n}\n\n/**\n * Get the PDF output path from a tex file path\n *\n * @param texPath - The tex file path\n * @returns The PDF file path\n */\nexport function getPdfPath(texPath: string): string {\n return texPath.replace(/\\.tex$/, '.pdf')\n}\n\ntype LaTeXEnvironment = 'xelatex' | 'tectonic'\n\n/**\n * Check if a command is available\n *\n * @param command - The command to check\n * @returns True if the command is available, false otherwise\n */\nexport function isCommandAvailable(command: string): boolean {\n try {\n return !!which.sync(command)\n } catch {\n return false\n }\n}\n\n/**\n * Infer the LaTeX environment to use\n *\n * We support xelatex and tectonic, if both are installed we will prioritize\n * xelatex.\n *\n * @returns The LaTeX environment PATH.\n * @throws {Error} If neither 'xelatex' nor 'tectonic' is found in system PATH.\n */\nexport function inferLaTeXEnvironment(): LaTeXEnvironment {\n if (isCommandAvailable('xelatex')) {\n return 'xelatex'\n }\n\n if (isCommandAvailable('tectonic')) {\n return 'tectonic'\n }\n\n throw new YAMLResumeError('LATEX_NOT_FOUND', {})\n}\n\n/**\n * Infer the LaTeX command to use based on the LaTeX environment\n *\n * @param resumePathOrTexFile - The source resume file OR the target .tex file\n * @param outputDir - Optional output directory\n * @returns The LaTeX command\n * @throws {Error} If the LaTeX environment cannot be inferred or the source\n * file extension is unsupported.\n */\nexport function inferLaTeXCommand(\n resumePathOrTexFile: string,\n outputDir?: string\n): { command: string; args: string[]; cwd: string } {\n const environment = inferLaTeXEnvironment()\n\n // If the input is already a .tex file, use it directly; otherwise infer from .yaml/.json\n const texFile = resumePathOrTexFile.endsWith('.tex')\n ? resumePathOrTexFile\n : inferOutput(resumePathOrTexFile, outputDir)\n\n let command = ''\n let args: string[] = []\n\n switch (environment) {\n case 'xelatex':\n command = 'xelatex'\n args = ['-halt-on-error', path.basename(texFile)]\n break\n case 'tectonic':\n command = 'tectonic'\n args = [path.basename(texFile)]\n break\n }\n\n const cwd = outputDir\n ? path.resolve(outputDir)\n : path.dirname(path.resolve(texFile))\n\n return { command, args, cwd }\n}\n\n/**\n * Normalize the file extension that can be used in the output file name\n *\n * @param extension - file extension\n * @returns\n */\nexport function normalizeExtension(extension: string): string {\n switch (extension) {\n case '.tex':\n return 'tex'\n case '.md':\n return 'markdown'\n case '.html':\n return 'html'\n default:\n return extension.replace('.', '')\n }\n}\n\n/**\n * Shared helper to generate output file from a layout\n */\nfunction generateOutput(\n resumePath: string,\n resume: Resume,\n index: number,\n total: number,\n outputDir: string | undefined,\n extension: string,\n layoutIndex: number\n): string {\n const outputFile = getOutputPath(\n resumePath,\n extension,\n index,\n total,\n outputDir\n )\n\n const dir = path.dirname(outputFile)\n if (!fs.existsSync(dir)) {\n fs.mkdirSync(dir, { recursive: true })\n }\n\n const renderer = getResumeRenderer(resume, layoutIndex)\n const content = renderer.render()\n\n try {\n fs.writeFileSync(outputFile, content)\n consola.success(\n joinNonEmptyString(\n [\n `Generated resume ${normalizeExtension(extension)} file successfully:`,\n outputFile,\n ],\n ' '\n )\n )\n } catch (_error) {\n throw new YAMLResumeError('FILE_WRITE_ERROR', { path: outputFile })\n }\n\n return outputFile\n}\n\n/**\n * Default timeout for LaTeX compilation in milliseconds (30 seconds)\n */\nexport const LATEX_COMPILE_TIMEOUT_MS = 30000\n\n/**\n * Compile a TeX file to PDF\n *\n * @param texFile - The TeX file to compile.\n * @param outputDir - Optional output directory.\n * @param timeout - Timeout in milliseconds. 0 means no timeout.\n */\nasync function compileLaTeX(\n texFile: string,\n outputDir?: string,\n timeout: number = LATEX_COMPILE_TIMEOUT_MS\n) {\n const { command, args, cwd } = inferLaTeXCommand(texFile, outputDir)\n\n consola.start(\n `Generating resume pdf file with command: \\`${command} ${args.join(' ')}\\`...`\n )\n\n // When timeout is 0, disable timeout by setting it to undefined\n const execaTimeout = timeout === 0 ? undefined : timeout\n\n try {\n const result = await execa(command, args, {\n cwd,\n encoding: 'utf8',\n timeout: execaTimeout,\n })\n consola.success(\n `Generated resume pdf file successfully: ${getPdfPath(texFile)}`\n )\n consola.debug(joinNonEmptyString(['stdout: ', toCodeBlock(result.stdout)]))\n } catch (error) {\n // Check if it's a timeout error\n if (error.timedOut) {\n // Show raw logs to help users diagnose the issue\n if (error.stdout) {\n consola.info('LaTeX output before timeout:')\n consola.log(error.stdout)\n }\n if (error.stderr) {\n consola.info('LaTeX error output:')\n consola.log(error.stderr)\n }\n throw new YAMLResumeError('LATEX_COMPILE_TIMEOUT', {\n timeout: String(timeout / 1000),\n })\n }\n\n consola.debug(joinNonEmptyString(['stdout: ', toCodeBlock(error.stdout)]))\n consola.debug(joinNonEmptyString(['stderr: ', toCodeBlock(error.stderr)]))\n throw new YAMLResumeError('LATEX_COMPILE_ERROR', { error: error.message })\n }\n}\n\n/**\n * Parse and validate the timeout option.\n *\n * If the value is invalid, logs a warning and returns the default timeout.\n *\n * @param value - The timeout value in seconds as a string.\n * @returns The parsed timeout in milliseconds.\n */\nexport function parseTimeout(value: string): number {\n const num = Number(value)\n\n if (Number.isNaN(num) || num < 0) {\n consola.warn(\n joinNonEmptyString(\n [\n `Invalid timeout value: \"${value}\".`,\n `Using default timeout: ${LATEX_COMPILE_TIMEOUT_MS / 1000}s.`,\n 'Timeout must be a non-negative number in seconds (0 to disable).',\n ],\n ' '\n )\n )\n return LATEX_COMPILE_TIMEOUT_MS\n }\n\n // Convert seconds to milliseconds (supports fractional seconds like curl)\n return num * 1000\n}\n\n/**\n * Build a YAML resume to LaTeX & PDF and/or Markdown\n *\n * It first validates the resume against the schema (unless `--no-validate` flag\n * is used), then iterates through configured layouts to generate outputs.\n *\n * @param resumePath - The source resume file path (YAML, YML, or JSON).\n * @param options - Build options including validation, PDF generation flags,\n * output directory, and LaTeX compilation timeout.\n */\nexport async function buildResume(\n resumePath: string,\n options: {\n pdf?: boolean\n validate?: boolean\n output?: string\n timeout?: number\n } = {\n pdf: true,\n validate: true,\n timeout: LATEX_COMPILE_TIMEOUT_MS,\n }\n) {\n const { resume } = readResume(resumePath, options.validate)\n\n // Fallback to default layout if none provided\n const allLayouts = resume.layouts ?? DEFAULT_RESUME_LAYOUTS\n // Ensure resume has layouts for the renderer to use\n if (!resume.layouts) {\n resume.layouts = allLayouts\n }\n\n // Count totals for each engine to determine file naming strategy\n // (e.g. resume.0.tex vs resume.tex)\n const totals = {\n latex: allLayouts.filter((l) => l.engine === 'latex').length,\n markdown: allLayouts.filter((l) => l.engine === 'markdown').length,\n html: allLayouts.filter((l) => l.engine === 'html').length,\n }\n\n // Track current index for each engine\n const indices = {\n latex: 0,\n markdown: 0,\n html: 0,\n }\n\n for (let layoutIndex = 0; layoutIndex < allLayouts.length; layoutIndex++) {\n const layout = allLayouts[layoutIndex]\n\n switch (layout.engine) {\n case 'latex': {\n const texFile = generateOutput(\n resumePath,\n resume,\n indices.latex++,\n totals.latex,\n options.output,\n '.tex',\n layoutIndex\n )\n\n if (options.pdf === true) {\n await compileLaTeX(texFile, options.output, options.timeout)\n }\n break\n }\n case 'markdown': {\n generateOutput(\n resumePath,\n resume,\n indices.markdown++,\n totals.markdown,\n options.output,\n '.md',\n layoutIndex\n )\n break\n }\n case 'html': {\n generateOutput(\n resumePath,\n resume,\n indices.html++,\n totals.html,\n options.output,\n '.html',\n layoutIndex\n )\n break\n }\n }\n }\n}\n\n/**\n * Create a command instance to build a YAML resume to LaTeX and PDF\n */\nexport function createBuildCommand() {\n return new Command()\n .name('build')\n .description('build a resume to LaTeX, PDF, Markdown, or HTML')\n .argument('<resume-path>', 'the resume file path')\n .option(\n '--no-pdf',\n 'only generate TeX file without PDF (for LaTeX layouts)'\n )\n .option('--no-validate', 'skip resume schema validation')\n .option('-o, --output <dir>', 'output directory for generated files')\n .option(\n '-t, --timeout <seconds>',\n joinNonEmptyString(\n [\n 'timeout for LaTeX compilation in seconds',\n `(default: ${LATEX_COMPILE_TIMEOUT_MS / 1000}, 0 to disable)`,\n ],\n ' '\n ),\n (value) => parseTimeout(value)\n )\n .action(\n async (\n resumePath: string,\n options: {\n pdf: boolean\n validate: boolean\n output?: string\n timeout: number\n }\n ) => {\n try {\n await buildResume(resumePath, options)\n } catch (error) {\n consola.error(error.message)\n process.exit(error.errno)\n }\n }\n )\n}\n","/**\n * MIT License\n *\n * Copyright (c) 2023–Present PPResume (https://ppresume.com)\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport chokidar from 'chokidar'\n\nimport { coalesce } from 'coalescifn'\nimport { Command } from 'commander'\nimport { consola } from 'consola'\n\nimport { buildResume } from './build'\n\n/**\n * Options for the watchResume function\n *\n * @param pdf - Whether to generate PDF\n * @param validate - Whether to validate the resume\n */\ntype WatchOptions = {\n pdf?: boolean\n validate?: boolean\n output?: string\n}\n\n/**\n * Watch a resume source file and rebuild on changes.\n *\n * - Only one build runs at a time.\n * - If multiple events arrive during a build, run exactly one more build after\n * it finishes (coalesce bursts).\n * - Uses chokidar for robust file watching that handles editor operations.\n *\n * @param resumePath - The resume file to watch\n * @param options - Build and watch options\n * @returns Chokidar watcher instance\n */\nexport function watchResume(\n resumePath: string,\n options: WatchOptions = { pdf: true, validate: true }\n) {\n const { pdf, validate, output } = options\n\n // there should be only one build running at a time\n const exclusiveBuild = coalesce(() =>\n buildResume(resumePath, { pdf, validate, output })\n )\n\n // initial build\n exclusiveBuild()\n\n consola.start(`Watching file changes: ${resumePath}...`)\n\n // use chokidar for robust file watching that handles vim and other editors\n // properly.\n //\n // vim will save the file in a single atomic operation, that being said, it\n // will first create a temporary file (the '.swp' file), then rename it to the\n // final file.\n //\n // Node.js `fs.watch` has trouble with this, so we use chokidar instead.\n const watcher = chokidar.watch(resumePath, {\n awaitWriteFinish: {\n stabilityThreshold: 200, // wait 200ms after file stops changing\n pollInterval: 200, // check every 200ms\n },\n ignoreInitial: true, // don't trigger on initial file discovery\n })\n\n // handle file changes - chokidar's awaitWriteFinish already handles\n // debouncing\n watcher.on('change', () => exclusiveBuild())\n\n // handle file additions (in case file gets recreated)\n watcher.on('add', () => exclusiveBuild())\n\n return watcher\n}\n\n/**\n * Create a command instance to run in watch mode\n */\nexport function createDevCommand() {\n return new Command()\n .name('dev')\n .description('build a resume on file changes (watch mode)')\n .argument('<resume-path>', 'the resume file path')\n .option('--no-pdf', 'only generate TeX file without PDF')\n .option('--no-validate', 'skip resume schema validation')\n .option('-o, --output <dir>', 'output directory for generated files')\n .action(\n (\n resumePath: string,\n options: { pdf: boolean; validate: boolean; output?: string }\n ) => {\n watchResume(resumePath, options)\n }\n )\n}\n","/**\n * MIT License\n *\n * Copyright (c) 2023–Present PPResume (https://ppresume.com)\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport { Command } from 'commander'\nimport consola from 'consola'\nimport envinfo from 'envinfo'\nimport { execa } from 'execa'\nimport { getFonts } from 'font-list'\n\n/**\n * Check system information\n */\nexport async function checkSystem() {\n const info = await envinfo.run(\n {\n System: ['OS', 'CPU'],\n Binaries: ['Node', 'Yarn', 'npm', 'pnpm', 'Bun'],\n },\n { json: false, showNotFound: true }\n )\n console.log(info)\n}\n\n/**\n * Check if XeTeX is installed\n */\nexport async function checkXeTeX() {\n consola.info('Checking XeTeX...')\n try {\n const { stdout } = await execa('xelatex', ['--version'])\n console.log(` XeTeX: ${stdout.split('\\n')[0]}\\n`)\n } catch {\n console.log(' XeTeX: Not Found\\n')\n }\n}\n\n/**\n * Check if Tectonic is installed\n */\nexport async function checkTectonic() {\n consola.info('Checking Tectonic...')\n try {\n const { stdout } = await execa('tectonic', ['--version'])\n console.log(` Tectonic: ${stdout.split('\\n')[0]}\\n`)\n } catch {\n console.log(' Tectonic: Not Found\\n')\n }\n}\n\n/**\n * Check if required fonts are installed\n */\nexport async function checkFonts() {\n consola.info('Checking Fonts...')\n const installedFonts = await getFonts({ disableQuoting: true })\n const fonts = [\n 'Linux Libertine O',\n 'Linux Libertine',\n 'Noto Serif CJK SC',\n 'Noto Sans CJK SC',\n ]\n\n for (const font of fonts) {\n // font-list returns fonts like \"Arial\" or \"Times New Roman\" in an array\n // We check if the required font is included in the list\n // The checking is case-insensitive\n const isInstalled = installedFonts.some((f) =>\n f.toLowerCase().includes(font.toLowerCase())\n )\n const status = isInstalled ? 'Installed' : 'Not Installed'\n console.log(` ${font}: ${status}`)\n }\n}\n\n/**\n * Create a command instance to check the environment\n */\nexport function createDoctorCommand() {\n return new Command()\n .name('doctor')\n .description('check environment for YAMLResume dependencies')\n .action(async () => {\n await checkSystem()\n await checkXeTeX()\n await checkTectonic()\n await checkFonts()\n })\n}\n","/**\n * MIT License\n *\n * Copyright (c) 2023–Present PPResume (https://ppresume.com)\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport {\n getLocaleLanguageDetail,\n LOCALE_LANGUAGE_OPTIONS,\n} from '@yamlresume/core'\nimport { Command } from 'commander'\nimport consola from 'consola'\nimport { markdownTable } from 'markdown-table'\n\n/**\n * Generates a markdown table listing all supported locale languages.\n *\n * The table includes columns for the language code and the language name.\n *\n * @returns A string containing the formatted markdown table.\n */\nexport function listLanguages() {\n return markdownTable([\n ['locale.language', 'Language Name'],\n ...LOCALE_LANGUAGE_OPTIONS.map((value) => [\n value,\n getLocaleLanguageDetail(value).name,\n ]),\n ])\n}\n\n/**\n * Create a command instance to list supported languages\n */\n\nexport function createLanguagesCommand() {\n const cmd = new Command()\n .name('languages')\n .description('i18n and l10n support')\n\n cmd\n .command('list')\n .description('list all supported languages')\n .action(() => {\n consola.log(listLanguages())\n })\n\n return cmd\n}\n","/**\n * MIT License\n *\n * Copyright (c) 2023–Present PPResume (https://ppresume.com)\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport fs from 'node:fs'\nimport path from 'node:path'\nimport { fileURLToPath } from 'node:url'\nimport {\n joinNonEmptyString,\n toCodeBlock,\n YAMLResumeError,\n} from '@yamlresume/core'\nimport { Command } from 'commander'\nimport consola from 'consola'\n\n/**\n * Creates a new resume file with the given filename\n *\n * @param filename - The name of the resume file to create\n * @throws {YAMLResumeError} When there are file-related errors:\n * - FILE_CONFLICT: When the file already exists\n * - FILE_READ_ERROR: When there's an error reading the template\n * - FILE_WRITE_ERROR: When there's an error writing the file\n */\nexport function newResume(filename: string) {\n if (fs.existsSync(filename)) {\n throw new YAMLResumeError('FILE_CONFLICT', { path: filename })\n }\n\n const templatePath = path.join(\n path.dirname(fileURLToPath(import.meta.url)),\n /* v8 ignore start */\n // I din't find a way to mock `import.meta.url` in tests so we have to\n // ignore the following lines for coverage calculation\n import.meta.url.includes('dist')\n ? '../resources/resume.yml'\n : '../../resources/resume.yml'\n /* v8 ignore stop */\n )\n\n let templateContent: string\n\n try {\n templateContent = fs.readFileSync(templatePath, 'utf8')\n } catch (error) {\n consola.debug(\n joinNonEmptyString(['Error reading template: ', toCodeBlock(error.stack)])\n )\n throw new YAMLResumeError('FILE_READ_ERROR', { path: templatePath })\n }\n\n try {\n fs.writeFileSync(filename, templateContent)\n consola.success(`Created ${filename} successfully.`)\n } catch (error) {\n consola.debug(\n joinNonEmptyString(['Error creating resume: ', toCodeBlock(error.stack)])\n )\n throw new YAMLResumeError('FILE_WRITE_ERROR', { path: filename })\n }\n}\n\n/**\n * Create a command instance to create a new YAML resume\n */\nexport function createNewCommand() {\n return new Command()\n .name('new')\n .description('create a new resume')\n .argument('[filename]', 'output filename', 'resume.yml')\n .action((filename) => {\n try {\n newResume(filename)\n } catch (error) {\n consola.error(error.message)\n process.exit(error.errno)\n }\n })\n}\n","/**\n * MIT License\n *\n * Copyright (c) 2023–Present PPResume (https://ppresume.com)\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport {\n getHtmlTemplateDetail,\n getLatexTemplateDetail,\n HTML_TEMPLATE_OPTIONS,\n LATEX_TEMPLATE_OPTIONS,\n} from '@yamlresume/core'\nimport { Command } from 'commander'\nimport consola from 'consola'\nimport { markdownTable } from 'markdown-table'\n\n/**\n * Generates a markdown table listing all supported templates.\n *\n * The table includes columns for the template id, name and description.\n *\n * @returns A string containing the formatted markdown table.\n */\nexport function listTemplates() {\n const templates = [\n ...LATEX_TEMPLATE_OPTIONS.map((value) => {\n const details = getLatexTemplateDetail(value)\n return [value, details.engine, details.name, details.description]\n }),\n ...HTML_TEMPLATE_OPTIONS.map((value) => {\n const details = getHtmlTemplateDetail(value)\n return [value, details.engine, details.name, details.description]\n }),\n ]\n\n return markdownTable([\n ['layouts.[].template', 'Engine', 'Template Name', 'Description'],\n ...templates,\n ])\n}\n\n/**\n * Create a command instance to list supported templates\n */\nexport function createTemplatesCommand() {\n const cmd = new Command()\n .name('templates')\n .description('manage resume templates')\n\n cmd\n .command('list')\n .description('list all supported templates')\n .action(() => {\n consola.log(listTemplates())\n })\n\n return cmd\n}\n","{\n \"name\": \"yamlresume\",\n \"version\": \"0.12.3\",\n \"description\": \"The CLI interface for YAMLResume's engine\",\n \"license\": \"MIT\",\n \"author\": {\n \"name\": \"YAMLResume\",\n \"email\": \"support@yamlresume.com\",\n \"url\": \"https://yamlresume.dev\"\n },\n \"keywords\": [\n \"YAMLResume\",\n \"CV\",\n \"Resume\",\n \"LaTeX\",\n \"Typesetting\",\n \"PDF\",\n \"YAML\",\n \"JSON\"\n ],\n \"type\": \"module\",\n \"main\": \"./dist/index.js\",\n \"types\": \"./dist/index.d.ts\",\n \"exports\": {\n \".\": {\n \"types\": \"./dist/index.d.ts\",\n \"default\": \"./dist/index.js\"\n }\n },\n \"bin\": {\n \"yamlresume\": \"./dist/cli.js\"\n },\n \"files\": [\n \"dist\",\n \"README.md\",\n \"LICENSE\",\n \"resources/resume.yml\"\n ],\n \"scripts\": {\n \"build\": \"tsup\",\n \"build:watch\": \"tsup --watch\",\n \"build:clean\": \"rm -rf dist\",\n \"build:prod\": \"tsup --dts --minify --sourcemap\",\n \"prepublishOnly\": \"pnpm test\",\n \"dev\": \"tsx src/cli.ts\",\n \"test\": \"vitest --run\",\n \"test:cov\": \"vitest --coverage --run\",\n \"test:watch\": \"vitest\",\n \"typedoc\": \"typedoc\"\n },\n \"dependencies\": {\n \"@yamlresume/core\": \"workspace:*\",\n \"chalk\": \"^5.6.2\",\n \"chokidar\": \"^5.0.0\",\n \"coalescifn\": \"^0.1.1\",\n \"commander\": \"^14.0.3\",\n \"consola\": \"^3.4.2\",\n \"envinfo\": \"^7.21.0\",\n \"execa\": \"^9.6.1\",\n \"extensionless\": \"^2.0.6\",\n \"font-list\": \"^2.0.2\",\n \"lodash-es\": \"^4.18.1\",\n \"markdown-table\": \"^3.0.4\",\n \"tslib\": \"^2.8.1\",\n \"which\": \"^6.0.1\",\n \"yaml\": \"^2.8.3\"\n },\n \"devDependencies\": {\n \"@types/envinfo\": \"^7.8.4\",\n \"@types/which\": \"^3.0.4\"\n },\n \"publishConfig\": {\n \"access\": \"public\"\n },\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"https://github.com/yamlresume/yamlresume.git\",\n \"directory\": \"packages/cli\"\n },\n \"bugs\": {\n \"url\": \"https://github.com/yamlresume/yamlresume/issues\"\n },\n \"homepage\": \"https://yamlresume.dev/docs/cli\",\n \"engines\": {\n \"node\": \">=20.0.0\"\n }\n}\n","/**\n * MIT License\n *\n * Copyright (c) 2023–Present PPResume (https://ppresume.com)\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport consola from 'consola'\n\n/**\n * Set the verbose mode for consola\n *\n * @param verbose - Whether to enable verbose mode\n * @see https://github.com/unjs/consola?tab=readme-ov-file#log-level\n */\nexport function setVerboseLog(verbose: boolean) {\n consola.level = verbose ? 4 : 3\n}\n","/**\n * MIT License\n *\n * Copyright (c) 2023–Present PPResume (https://ppresume.com)\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport { Command } from 'commander'\n\nimport packageJson from '../package.json' with { type: 'json' }\nimport {\n createBuildCommand,\n createDevCommand,\n createDoctorCommand,\n createLanguagesCommand,\n createNewCommand,\n createTemplatesCommand,\n createValidateCommand,\n} from './commands'\nimport { setVerboseLog } from './utils'\n\n/**\n * Create the CLI program.\n *\n * @returns The CLI program.\n */\nexport function createProgram(): Command {\n const program = new Command()\n\n const banner = `\n __ __ _ __ __ _ ____\n \\\\ \\\\ / // \\\\ | \\\\/ | | | _ \\\\ ___ ___ _ _ ___ ___ ___\n \\\\ V // _ \\\\ | |\\\\/| | | | |_) / _ \\\\/ __| | | / _ \\\\/ _ \\\\ / _ \\\\\n | |/ ___ \\\\| | | | |___| _ < __/\\\\__ \\\\ |_| | | | | | | __/\n |_/_/ \\\\_\\\\_| |_|_____|_| \\\\_\\\\___||___/\\\\____|_| |_| |_|\\\\___|\n`\n\n program\n .name('yamlresume')\n .description(['YAMLResume — Resume as Code in YAML', banner].join('\\n'))\n .version(packageJson.version)\n .option('-v, --verbose', 'verbose output')\n .hook('preAction', (thisCommand) => {\n setVerboseLog(thisCommand.opts().verbose)\n })\n\n program.addCommand(createNewCommand())\n program.addCommand(createBuildCommand())\n program.addCommand(createDevCommand())\n program.addCommand(createDoctorCommand())\n program.addCommand(createLanguagesCommand())\n program.addCommand(createTemplatesCommand())\n program.addCommand(createValidateCommand())\n\n return program\n}\n"]}
|
package/dist/cli.js
CHANGED
package/dist/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export{b as createBuildCommand,c as createDevCommand,d as createDoctorCommand,e as createLanguagesCommand,f as createNewCommand,h as createProgram,g as createTemplatesCommand,a as createValidateCommand}from'./chunk-
|
|
1
|
+
export{b as createBuildCommand,c as createDevCommand,d as createDoctorCommand,e as createLanguagesCommand,f as createNewCommand,h as createProgram,g as createTemplatesCommand,a as createValidateCommand}from'./chunk-FTS5HDX6.js';//# sourceMappingURL=index.js.map
|
|
2
2
|
//# sourceMappingURL=index.js.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "yamlresume",
|
|
3
|
-
"version": "0.12.
|
|
3
|
+
"version": "0.12.3",
|
|
4
4
|
"description": "The CLI interface for YAMLResume's engine",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": {
|
|
@@ -38,20 +38,20 @@
|
|
|
38
38
|
],
|
|
39
39
|
"dependencies": {
|
|
40
40
|
"chalk": "^5.6.2",
|
|
41
|
-
"chokidar": "^
|
|
41
|
+
"chokidar": "^5.0.0",
|
|
42
42
|
"coalescifn": "^0.1.1",
|
|
43
|
-
"commander": "^14.0.
|
|
43
|
+
"commander": "^14.0.3",
|
|
44
44
|
"consola": "^3.4.2",
|
|
45
45
|
"envinfo": "^7.21.0",
|
|
46
46
|
"execa": "^9.6.1",
|
|
47
47
|
"extensionless": "^2.0.6",
|
|
48
48
|
"font-list": "^2.0.2",
|
|
49
|
-
"lodash-es": "^4.
|
|
49
|
+
"lodash-es": "^4.18.1",
|
|
50
50
|
"markdown-table": "^3.0.4",
|
|
51
51
|
"tslib": "^2.8.1",
|
|
52
52
|
"which": "^6.0.1",
|
|
53
|
-
"yaml": "^2.8.
|
|
54
|
-
"@yamlresume/core": "0.12.
|
|
53
|
+
"yaml": "^2.8.3",
|
|
54
|
+
"@yamlresume/core": "0.12.3"
|
|
55
55
|
},
|
|
56
56
|
"devDependencies": {
|
|
57
57
|
"@types/envinfo": "^7.8.4",
|