yamlresume
Version:
The CLI interface for YAMLResume's engine
15 lines • 6.38 kB
JavaScript
import {Command}from'commander';import H from'node:child_process';import C from'node:fs';import F from'node:path';import _,{consola}from'consola';import ee from'which';import {YAMLResumeError,joinNonEmptyString,toCodeBlock,LOCALE_LANGUAGE_OPTIONS,getLocaleLanguageDetail,TEMPLATE_OPTIONS,getTemplateDetail,getResumeRenderer,ResumeSchema}from'@yamlresume/core';import j,{LineCounter,parseDocument,isNode}from'yaml';import s from'chalk';import {fileURLToPath}from'node:url';import {markdownTable}from'markdown-table';var N={version:"0.6.0"};function U(e,t,r){let o=r.split(`
`)[e.line-1]||"",a=`${" ".repeat(e.column-1)}^`,c=s.white.bold(`${t}:${e.line}:${e.column}`),i=s.red.bold("warning"),l=s.white(e.message),p=s.white(o),d=s.green.bold(a);return [`${c}: ${i}: ${l}`,`${p}`,`${d}`].join(`
`)}function z(e,t,r){let n=e.match(/at line (\d+), column (\d+)/);if(!n)return joinNonEmptyString([s.white.bold(t),s.red.bold("error"),`${s.white(e)}.`],": ");let o=Number.parseInt(n[1],10),a=Number.parseInt(n[2],10),i=r.split(`
`)[o-1]||"",l=`${" ".repeat(a-1)}^`,p=s.white.bold(`${t}:${o}:${a}`),d=s.red.bold("error"),h=s.white(e.split(`
`)[0].replace(/ at line \d+, column \d+:?/,".").trim()),f=s.white(i),M=s.green.bold(l);return [`${p}: ${d}: ${h}`,`${f}`,`${M}`].join(`
`)}function q(e,t){let r=new LineCounter,n=parseDocument(e,{lineCounter:r,keepSourceTokens:true}),o=t.safeParse(n.toJS());if(o.success)return [];let{error:{issues:a}}=o;return a.map(c=>{let i=c.path,l=n.getIn(i,true),p=1,d=1;if(isNode(l)&&l.range){let h=l.range[0],f=r.linePos(h);p=f.line,d=f.col;}return {message:c.message,line:p,column:d,path:i}}).sort((c,i)=>c.line-i.line)}function w(e,t=true){let r;try{r=C.readFileSync(e,"utf8");}catch{throw new YAMLResumeError("FILE_READ_ERROR",{path:e})}let n;try{n=j.parse(r);}catch(o){let a=z(o.message,e,r);throw console.log(a),new YAMLResumeError("INVALID_YAML",{error:`Failed to parse ${e}.`})}if(t){let o=q(r,ResumeSchema);if(o.length>0){for(let a of o)console.log(U(a,e,r));return {resume:n,validated:"failed"}}return {resume:n,validated:"success"}}return {resume:n,validated:"unknown"}}function b(){return new Command().name("validate").description("validate a resume against the YAMLResume schema").argument("<resume-path>","the resume file path").action(async e=>{try{let{validated:t}=w(e,!0);t==="success"&&_.success("Resume validation passed."),t==="failed"&&_.fail("Resume validation failed.");}catch(t){_.error(t.message),process.exit(t.errno);}})}function S(e){let t=F.extname(e);if(e.endsWith(".yaml")||e.endsWith(".yml")||e.endsWith(".json"))return e.replace(/\.yaml|\.yml|\.json$/,".tex");throw new YAMLResumeError("INVALID_EXTNAME",{extname:t})}function I(e){try{return !!ee.sync(e)}catch{return false}}function re(){if(I("xelatex"))return "xelatex";if(I("tectonic"))return "tectonic";throw new YAMLResumeError("LATEX_NOT_FOUND",{})}function oe(e){let t=re(),r=S(e);switch(t){case "xelatex":return `xelatex -halt-on-error ${r}`;case "tectonic":return `tectonic ${r}`}}function ne(e,t){let r=S(e),o=getResumeRenderer(t).render();try{C.writeFileSync(r,o);}catch{throw new YAMLResumeError("FILE_WRITE_ERROR",{path:r})}}function se(e,t={pdf:true,validate:true}){let{resume:r}=w(e,t.validate);if(ne(e,r),!t.pdf){consola.success("Generated resume TeX file successfully.");return}let n=oe(e);consola.start(`Generating resume PDF file with command: \`${n}\`...`);try{let o=H.execSync(n,{encoding:"utf8"});consola.success("Generated resume PDF file successfully."),consola.debug(joinNonEmptyString(["stdout: ",toCodeBlock(o)]));}catch(o){throw consola.debug(joinNonEmptyString(["stdout: ",toCodeBlock(o.stdout)])),consola.debug(joinNonEmptyString(["stderr: ",toCodeBlock(o.stderr)])),new YAMLResumeError("LATEX_COMPILE_ERROR",{error:o.message})}}function R(){return new Command().name("build").description("build a resume to LaTeX and PDF").argument("<resume-path>","the resume file path").option("--no-pdf","only generate TeX file without PDF").option("--no-validate","skip resume schema validation").action(async(e,t)=>{try{se(e,t);}catch(r){consola.error(r.message),process.exit(r.errno);}})}function me(e){if(C.existsSync(e))throw new YAMLResumeError("FILE_CONFLICT",{path:e});let t=F.join(F.dirname(fileURLToPath(import.meta.url)),import.meta.url.includes("dist")?"../resources/resume.yml":"../../resources/resume.yml"),r;try{r=C.readFileSync(t,"utf8");}catch(n){throw _.debug(joinNonEmptyString(["Error reading template: ",toCodeBlock(n.stack)])),new YAMLResumeError("FILE_READ_ERROR",{path:t})}try{C.writeFileSync(e,r),_.success(`Created ${e} successfully.`);}catch(n){throw _.debug(joinNonEmptyString(["Error creating resume: ",toCodeBlock(n.stack)])),new YAMLResumeError("FILE_WRITE_ERROR",{path:e})}}function v(){return new Command().name("new").description("create a new resume").argument("[filename]","output filename","resume.yml").action(e=>{try{me(e);}catch(t){_.error(t.message),process.exit(t.errno);}})}function fe(){return markdownTable([["layout.locale.language","Language Name"],...LOCALE_LANGUAGE_OPTIONS.map(e=>[e,getLocaleLanguageDetail(e).name])])}function T(){let e=new Command().name("languages").description("i18n and l10n support");return e.command("list").description("list all supported languages").action(()=>{_.log(fe());}),e}function be(){return markdownTable([["layout.template","Template Name","Description"],...TEMPLATE_OPTIONS.map(e=>{let t=getTemplateDetail(e);return [e,t.name,t.description]})])}function A(){let e=new Command().name("templates").description("manage resume templates");return e.command("list").description("list all supported templates").action(()=>{_.log(be());}),e}function $(e){_.level=e?4:3;}var m=new Command,Re=`
__ __ _ __ __ _ ____
\\ \\ / // \\ | \\/ | | | _ \\ ___ ___ _ _ ___ ___ ___
\\ V // _ \\ | |\\/| | | | |_) / _ \\/ __| | | / _ \\/ _ \\ / _ \\
| |/ ___ \\| | | | |___| _ < __/\\__ \\ |_| | | | | | | __/
|_/_/ \\_\\_| |_|_____|_| \\_\\___||___/\\____|_| |_| |_|\\___|
`;m.name("yamlresume").description(["YAMLResume \u2014 Resume as Code in YAML",Re].join(`
`)).version(N.version).option("-v, --verbose","verbose output").hook("preAction",e=>{$(e.opts().verbose);});m.addCommand(v());m.addCommand(R());m.addCommand(T());m.addCommand(A());m.addCommand(b());m.parse();//# sourceMappingURL=cli.js.map
//# sourceMappingURL=cli.js.map