yamlresume 0.4.0 → 0.4.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.js CHANGED
@@ -1,10 +1,10 @@
1
1
  #!/usr/bin/env node
2
- import {Command}from'commander';import A from'node:child_process';import l from'node:fs';import b from'node:path';import a,{consola}from'consola';import I from'which';import D from'yaml';import {YAMLResumeError,joinNonEmptyString,toCodeBlock,LocaleLanguageOption,getLocaleLanguageOptionDetail,TemplateOption,getTemplateOptionDetail,MarkdownParser,getResumeRenderer}from'@yamlresume/core';import {fileURLToPath}from'node:url';import {markdownTable}from'markdown-table';var h={version:"0.4.0"};function L(e){let t=b.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 x(e){try{return !!I.sync(e)}catch{return false}}function M(){if(x("xelatex"))return "xelatex";if(x("tectonic"))return "tectonic";throw new YAMLResumeError("LATEX_NOT_FOUND",{})}function X(e){let t=M(),r=L(e);switch(t){case "xelatex":return `xelatex -halt-on-error ${r}`;case "tectonic":return `tectonic ${r}`}}function j(e){let t=L(e),r;try{r=l.readFileSync(e,"utf8");}catch{throw new YAMLResumeError("FILE_READ_ERROR",{path:e})}let o;try{o=D.parse(r);}catch(i){throw new YAMLResumeError("INVALID_YAML",{error:i.message})}let E=new MarkdownParser,T=getResumeRenderer(o,E).render();try{l.writeFileSync(t,T);}catch{throw new YAMLResumeError("FILE_WRITE_ERROR",{path:t})}}function P(e,t={pdf:true}){if(j(e),!t.pdf){consola.success("Generated resume TeX file successfully.");return}let r=X(e);consola.start(`Generating resume PDF with command: \`${r}\`...`);try{let o=A.execSync(r,{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 u(){return new Command().name("build").description("build a resume to LaTeX and PDF").argument("<source>","the source resume file").option("--no-pdf","only generate TeX file without PDF").action(async(e,t)=>{try{P(e,t);}catch(r){consola.error(r.message),process.exit(r.errno);}})}function V(e){if(l.existsSync(e))throw new YAMLResumeError("FILE_CONFLICT",{path:e});let t=b.join(b.dirname(fileURLToPath(import.meta.url)),import.meta.url.includes("dist")?"../resources/resume.yml":"../../resources/resume.yml"),r;try{r=l.readFileSync(t,"utf8");}catch(o){throw a.debug(joinNonEmptyString(["Error reading template: ",toCodeBlock(o.stack)])),new YAMLResumeError("FILE_READ_ERROR",{path:t})}try{l.writeFileSync(e,r),a.success(`Created ${e} successfully.`);}catch(o){throw a.debug(joinNonEmptyString(["Error creating resume: ",toCodeBlock(o.stack)])),new YAMLResumeError("FILE_WRITE_ERROR",{path:e})}}function _(){return new Command().name("new").description("create a new resume").argument("[filename]","output filename","resume.yml").action(e=>{try{V(e);}catch(t){a.error(t.message),process.exit(t.errno);}})}function U(){return markdownTable([["layout.locale.language","Language Name"],...Object.values(LocaleLanguageOption).map(e=>[e,getLocaleLanguageOptionDetail(e).name])])}function f(){let e=new Command().name("languages").description("i18n and l10n support");return e.command("list").description("list all supported languages").action(()=>{a.log(U());}),e}function Z(){return markdownTable([["layout.template","Template Name","Description"],...Object.values(TemplateOption).map(e=>{let t=getTemplateOptionDetail(e);return [e,t.name,t.description]})])}function g(){let e=new Command().name("templates").description("manage resume templates");return e.command("list").description("list all supported templates").action(()=>{a.log(Z());}),e}function y(e){a.level=e?4:3;}var m=new Command,re=`
2
+ import {Command}from'commander';import A from'node:child_process';import l from'node:fs';import b from'node:path';import a,{consola}from'consola';import I from'which';import N from'yaml';import {YAMLResumeError,joinNonEmptyString,toCodeBlock,LOCALE_LANGUAGE_OPTIONS,getLocaleLanguageOptionDetail,TEMPLATE_OPTIONS,getTemplateOptionDetail,getResumeRenderer}from'@yamlresume/core';import {fileURLToPath}from'node:url';import {markdownTable}from'markdown-table';var y={version:"0.4.2"};function x(e){let t=b.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 L(e){try{return !!I.sync(e)}catch{return false}}function D(){if(L("xelatex"))return "xelatex";if(L("tectonic"))return "tectonic";throw new YAMLResumeError("LATEX_NOT_FOUND",{})}function M(e){let t=D(),r=x(e);switch(t){case "xelatex":return `xelatex -halt-on-error ${r}`;case "tectonic":return `tectonic ${r}`}}function k(e){let t=x(e),r;try{r=l.readFileSync(e,"utf8");}catch{throw new YAMLResumeError("FILE_READ_ERROR",{path:e})}let o;try{o=N.parse(r);}catch(i){throw new YAMLResumeError("INVALID_YAML",{error:i.message})}let R=getResumeRenderer(o).render();try{l.writeFileSync(t,R);}catch{throw new YAMLResumeError("FILE_WRITE_ERROR",{path:t})}}function S(e,t={pdf:true}){if(k(e),!t.pdf){consola.success("Generated resume TeX file successfully.");return}let r=M(e);consola.start(`Generating resume PDF file with command: \`${r}\`...`);try{let o=A.execSync(r,{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 u(){return new Command().name("build").description("build a resume to LaTeX and PDF").argument("<source>","the source resume file").option("--no-pdf","only generate TeX file without PDF").action(async(e,t)=>{try{S(e,t);}catch(r){consola.error(r.message),process.exit(r.errno);}})}function Y(e){if(l.existsSync(e))throw new YAMLResumeError("FILE_CONFLICT",{path:e});let t=b.join(b.dirname(fileURLToPath(import.meta.url)),import.meta.url.includes("dist")?"../resources/resume.yml":"../../resources/resume.yml"),r;try{r=l.readFileSync(t,"utf8");}catch(o){throw a.debug(joinNonEmptyString(["Error reading template: ",toCodeBlock(o.stack)])),new YAMLResumeError("FILE_READ_ERROR",{path:t})}try{l.writeFileSync(e,r),a.success(`Created ${e} successfully.`);}catch(o){throw a.debug(joinNonEmptyString(["Error creating resume: ",toCodeBlock(o.stack)])),new YAMLResumeError("FILE_WRITE_ERROR",{path:e})}}function _(){return new Command().name("new").description("create a new resume").argument("[filename]","output filename","resume.yml").action(e=>{try{Y(e);}catch(t){a.error(t.message),process.exit(t.errno);}})}function $(){return markdownTable([["layout.locale.language","Language Name"],...LOCALE_LANGUAGE_OPTIONS.map(e=>[e,getLocaleLanguageOptionDetail(e).name])])}function f(){let e=new Command().name("languages").description("i18n and l10n support");return e.command("list").description("list all supported languages").action(()=>{a.log($());}),e}function K(){return markdownTable([["layout.template","Template Name","Description"],...TEMPLATE_OPTIONS.map(e=>{let t=getTemplateOptionDetail(e);return [e,t.name,t.description]})])}function g(){let e=new Command().name("templates").description("manage resume templates");return e.command("list").description("list all supported templates").action(()=>{a.log(K());}),e}function h(e){a.level=e?4:3;}var m=new Command,ee=`
3
3
  __ __ _ __ __ _ ____
4
4
  \\ \\ / // \\ | \\/ | | | _ \\ ___ ___ _ _ ___ ___ ___
5
5
  \\ V // _ \\ | |\\/| | | | |_) / _ \\/ __| | | / _ \\/ _ \\ / _ \\
6
6
  | |/ ___ \\| | | | |___| _ < __/\\__ \\ |_| | | | | | | __/
7
7
  |_/_/ \\_\\_| |_|_____|_| \\_\\___||___/\\____|_| |_| |_|\\___|
8
- `;m.name("yamlresume").description(["YAMLResume \u2014 Resume as Code in YAML",re].join(`
9
- `)).version(h.version).option("-v, --verbose","verbose output").hook("preAction",e=>{y(e.opts().verbose);});m.addCommand(_());m.addCommand(u());m.addCommand(f());m.addCommand(g());m.parse();//# sourceMappingURL=cli.js.map
8
+ `;m.name("yamlresume").description(["YAMLResume \u2014 Resume as Code in YAML",ee].join(`
9
+ `)).version(y.version).option("-v, --verbose","verbose output").hook("preAction",e=>{h(e.opts().verbose);});m.addCommand(_());m.addCommand(u());m.addCommand(f());m.addCommand(g());m.parse();//# sourceMappingURL=cli.js.map
10
10
  //# sourceMappingURL=cli.js.map
package/dist/cli.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../package.json","../src/commands/build.ts","../src/commands/new.ts","../src/commands/languages.ts","../src/commands/templates.ts","../src/utils/consola.ts","../src/program.ts","../src/cli.ts"],"names":["package_default","inferOutput","source","extname","path","YAMLResumeError","isCommandAvailable","command","which","inferLaTeXEnvironment","inferLaTeXCommand","environment","destination","generateTeX","texFile","resumeContent","fs","resume","yaml","error","summaryParser","MarkdownParser","tex","getResumeRenderer","buildResume","options","consola","stdout","child_process","joinNonEmptyString","toCodeBlock","createBuildCommand","Command","newResume","filename","templatePath","fileURLToPath","templateContent","createNewCommand","listLanguages","markdownTable","LocaleLanguageOption","value","getLocaleLanguageOptionDetail","createLanguagesCommand","cmd","listTemplates","TemplateOption","details","getTemplateOptionDetail","createTemplatesCommand","setVerboseLog","verbose","program","banner","thisCommand"],"mappings":"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","file":"cli.js","sourcesContent":["{\n \"name\": \"yamlresume\",\n \"version\": \"0.4.0\",\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 \"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 },\n \"dependencies\": {\n \"@yamlresume/core\": \"workspace:*\",\n \"commander\": \"^11.0.0\",\n \"consola\": \"^3.4.2\",\n \"extensionless\": \"^1.9.9\",\n \"lodash-es\": \"^4.17.21\",\n \"markdown-table\": \"^3.0.4\",\n \"tslib\": \"^2.8.1\",\n \"which\": \"^5.0.0\",\n \"yaml\": \"^2.7.1\"\n },\n \"devDependencies\": {\n \"@types/commander\": \"^2.12.5\",\n \"@types/lodash-es\": \"^4.17.12\",\n \"@types/which\": \"^3.0.4\",\n \"tsx\": \"^4.19.3\"\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://github.com/yamlresume/yamlresume/tree/main/packages/cli#readme\",\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 child_process from 'node:child_process'\nimport fs from 'node:fs'\nimport path from 'node:path'\nimport { Command } from 'commander'\nimport { consola } from 'consola'\nimport which from 'which'\nimport yaml from 'yaml'\n\nimport {\n MarkdownParser,\n type Resume,\n YAMLResumeError,\n getResumeRenderer,\n joinNonEmptyString,\n toCodeBlock,\n} from '@yamlresume/core'\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 source - The source resume file\n * @returns The output file name\n * @throws {Error} If the source file has an unsupported extension.\n */\nexport function inferOutput(source: string): string {\n const extname = path.extname(source)\n\n if (\n source.endsWith('.yaml') ||\n source.endsWith('.yml') ||\n source.endsWith('.json')\n ) {\n return source.replace(/\\.yaml|\\.yml|\\.json$/, '.tex')\n }\n\n throw new YAMLResumeError('INVALID_EXTNAME', { extname })\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 source - The source resume file\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(source: string): string {\n const environment = inferLaTeXEnvironment()\n const destination = inferOutput(source)\n\n switch (environment) {\n case 'xelatex':\n return `xelatex -halt-on-error ${destination}`\n case 'tectonic':\n return `tectonic ${destination}`\n }\n}\n\n/**\n * Compiles the resume source file to a LaTeX file.\n *\n * @param source - The source resume file path (YAML, YML, or JSON).\n * @remarks This function performs file I/O: reads the source file and writes a\n * .tex file.\n * @throws {Error} Can throw if file reading, parsing, rendering, or writing\n * fails, or if the source file extension is unsupported.\n */\nexport function generateTeX(source: string) {\n // make sure the file has an valid extension, i.e, '.json', '.yml' or '.yaml'\n const texFile = inferOutput(source)\n\n let resumeContent: string\n\n try {\n resumeContent = fs.readFileSync(source, 'utf8')\n } catch (error) {\n throw new YAMLResumeError('FILE_READ_ERROR', { path: source })\n }\n\n let resume: Resume\n\n try {\n resume = yaml.parse(resumeContent) as Resume\n } catch (error) {\n throw new YAMLResumeError('INVALID_YAML', { error: error.message })\n }\n\n const summaryParser = new MarkdownParser()\n const renderer = getResumeRenderer(resume, summaryParser)\n const tex = renderer.render()\n\n try {\n fs.writeFileSync(texFile, tex)\n } catch (error) {\n throw new YAMLResumeError('FILE_WRITE_ERROR', { path: texFile })\n }\n}\n\n/**\n * Build a YAML resume to LaTeX & PDF\n *\n * It first generates the .tex file (using `generateTeX`) and then runs the\n * inferred LaTeX command (e.g., xelatex or tectonic) to produce the PDF.\n *\n * Steps:\n * 1. read the resume from the source file\n * 2. infer the LaTeX command to use\n * 2.1. infer the LaTeX environment to use\n * 2.2. infer the output destination\n * 3. [TODO] check the resume format and make sure it aligns with YAMLResume\n * schema\n * 4. build the resume to LaTeX and PDF at the same time\n *\n * @param source - The source resume file path (YAML, YML, or JSON).\n * @remarks This function performs file I/O (via `generateTeX`) and executes an\n * external process (LaTeX compiler).\n * @throws {Error} Can throw if .tex generation, LaTeX command inference, or the\n * LaTeX compilation process fails.\n * @todo Check the resume format against YAMLResume schema before compilation.\n */\nexport function buildResume(\n source: string,\n options: { pdf?: boolean } = { pdf: true }\n) {\n generateTeX(source)\n\n if (!options.pdf) {\n consola.success('Generated resume TeX file successfully.')\n return\n }\n\n const command = inferLaTeXCommand(source)\n consola.start(`Generating resume PDF with command: \\`${command}\\`...`)\n\n try {\n const stdout = child_process.execSync(command, { encoding: 'utf8' })\n consola.success('Generated resume PDF file successfully.')\n consola.debug(joinNonEmptyString(['stdout: ', toCodeBlock(stdout)]))\n } catch (error) {\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 * 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 and PDF')\n .argument('<source>', 'the source resume file')\n .option('--no-pdf', 'only generate TeX file without PDF')\n .action(async (source: string, options: { pdf: boolean }) => {\n try {\n buildResume(source, options)\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 { fileURLToPath } from 'node:url'\nimport { Command } from 'commander'\nimport consola from 'consola'\n\nimport {\n YAMLResumeError,\n joinNonEmptyString,\n toCodeBlock,\n} from '@yamlresume/core'\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 LocaleLanguageOption,\n getLocaleLanguageOptionDetail,\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 (enum key) and the language\n * name (enum value).\n *\n * @returns A string containing the formatted markdown table.\n */\nexport function listLanguages() {\n return markdownTable([\n ['layout.locale.language', 'Language Name'],\n ...Object.values(LocaleLanguageOption).map((value) => [\n value,\n getLocaleLanguageOptionDetail(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 { TemplateOption, getTemplateOptionDetail } 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 return markdownTable([\n ['layout.template', 'Template Name', 'Description'],\n ...Object.values(TemplateOption).map((value) => {\n const details = getTemplateOptionDetail(value)\n return [value, details.name, details.description]\n }),\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 * 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 createLanguagesCommand,\n createNewCommand,\n createTemplatesCommand,\n} from './commands'\nimport { setVerboseLog } from './utils'\n\nexport const program = new Command()\n\nconst banner = `\n __ __ _ __ __ _ ____\n \\\\ \\\\ / // \\\\ | \\\\/ | | | _ \\\\ ___ ___ _ _ ___ ___ ___\n \\\\ V // _ \\\\ | |\\\\/| | | | |_) / _ \\\\/ __| | | / _ \\\\/ _ \\\\ / _ \\\\\n | |/ ___ \\\\| | | | |___| _ < __/\\\\__ \\\\ |_| | | | | | | __/\n |_/_/ \\\\_\\\\_| |_|_____|_| \\\\_\\\\___||___/\\\\____|_| |_| |_|\\\\___|\n`\n\nprogram\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\nprogram.addCommand(createNewCommand())\nprogram.addCommand(createBuildCommand())\nprogram.addCommand(createLanguagesCommand())\nprogram.addCommand(createTemplatesCommand())\n","#!/usr/bin/env node\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 { program } from './program'\n\nprogram.parse()\n"]}
1
+ {"version":3,"sources":["../package.json","../src/commands/build.ts","../src/commands/new.ts","../src/commands/languages.ts","../src/commands/templates.ts","../src/utils/consola.ts","../src/program.ts","../src/cli.ts"],"names":["package_default","inferOutput","source","extname","path","YAMLResumeError","isCommandAvailable","command","which","inferLaTeXEnvironment","inferLaTeXCommand","environment","destination","generateTeX","texFile","resumeContent","fs","resume","yaml","error","tex","getResumeRenderer","buildResume","options","consola","stdout","child_process","joinNonEmptyString","toCodeBlock","createBuildCommand","Command","newResume","filename","templatePath","fileURLToPath","templateContent","createNewCommand","listLanguages","markdownTable","LOCALE_LANGUAGE_OPTIONS","value","getLocaleLanguageOptionDetail","createLanguagesCommand","cmd","listTemplates","TEMPLATE_OPTIONS","details","getTemplateOptionDetail","createTemplatesCommand","setVerboseLog","verbose","program","banner","thisCommand"],"mappings":"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","file":"cli.js","sourcesContent":["{\n \"name\": \"yamlresume\",\n \"version\": \"0.4.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 \"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 },\n \"dependencies\": {\n \"@yamlresume/core\": \"workspace:*\",\n \"commander\": \"^11.0.0\",\n \"consola\": \"^3.4.2\",\n \"extensionless\": \"^1.9.9\",\n \"lodash-es\": \"^4.17.21\",\n \"markdown-table\": \"^3.0.4\",\n \"tslib\": \"^2.8.1\",\n \"which\": \"^5.0.0\",\n \"yaml\": \"^2.7.1\"\n },\n \"devDependencies\": {\n \"@types/commander\": \"^2.12.5\",\n \"@types/lodash-es\": \"^4.17.12\",\n \"@types/which\": \"^3.0.4\",\n \"tsx\": \"^4.19.3\"\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://github.com/yamlresume/yamlresume/tree/main/packages/cli#readme\",\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 child_process from 'node:child_process'\nimport fs from 'node:fs'\nimport path from 'node:path'\nimport { Command } from 'commander'\nimport { consola } from 'consola'\nimport which from 'which'\nimport yaml from 'yaml'\n\nimport {\n type Resume,\n YAMLResumeError,\n getResumeRenderer,\n joinNonEmptyString,\n toCodeBlock,\n} from '@yamlresume/core'\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 source - The source resume file\n * @returns The output file name\n * @throws {Error} If the source file has an unsupported extension.\n */\nexport function inferOutput(source: string): string {\n const extname = path.extname(source)\n\n if (\n source.endsWith('.yaml') ||\n source.endsWith('.yml') ||\n source.endsWith('.json')\n ) {\n return source.replace(/\\.yaml|\\.yml|\\.json$/, '.tex')\n }\n\n throw new YAMLResumeError('INVALID_EXTNAME', { extname })\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 source - The source resume file\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(source: string): string {\n const environment = inferLaTeXEnvironment()\n const destination = inferOutput(source)\n\n switch (environment) {\n case 'xelatex':\n return `xelatex -halt-on-error ${destination}`\n case 'tectonic':\n return `tectonic ${destination}`\n }\n}\n\n/**\n * Compiles the resume source file to a LaTeX file.\n *\n * @param source - The source resume file path (YAML, YML, or JSON).\n * @remarks This function performs file I/O: reads the source file and writes a\n * .tex file.\n * @throws {Error} Can throw if file reading, parsing, rendering, or writing\n * fails, or if the source file extension is unsupported.\n */\nexport function generateTeX(source: string) {\n // make sure the file has an valid extension, i.e, '.json', '.yml' or '.yaml'\n const texFile = inferOutput(source)\n\n let resumeContent: string\n\n try {\n resumeContent = fs.readFileSync(source, 'utf8')\n } catch (error) {\n throw new YAMLResumeError('FILE_READ_ERROR', { path: source })\n }\n\n let resume: Resume\n\n try {\n resume = yaml.parse(resumeContent) as Resume\n } catch (error) {\n throw new YAMLResumeError('INVALID_YAML', { error: error.message })\n }\n\n const renderer = getResumeRenderer(resume)\n const tex = renderer.render()\n\n try {\n fs.writeFileSync(texFile, tex)\n } catch (error) {\n throw new YAMLResumeError('FILE_WRITE_ERROR', { path: texFile })\n }\n}\n\n/**\n * Build a YAML resume to LaTeX & PDF\n *\n * It first generates the .tex file (using `generateTeX`) and then runs the\n * inferred LaTeX command (e.g., xelatex or tectonic) to produce the PDF.\n *\n * Steps:\n * 1. read the resume from the source file\n * 2. infer the LaTeX command to use\n * 2.1. infer the LaTeX environment to use\n * 2.2. infer the output destination\n * 3. [TODO] check the resume format and make sure it aligns with YAMLResume\n * schema\n * 4. build the resume to LaTeX and PDF at the same time\n *\n * @param source - The source resume file path (YAML, YML, or JSON).\n * @remarks This function performs file I/O (via `generateTeX`) and executes an\n * external process (LaTeX compiler).\n * @throws {Error} Can throw if .tex generation, LaTeX command inference, or the\n * LaTeX compilation process fails.\n * @todo Check the resume format against YAMLResume schema before compilation.\n */\nexport function buildResume(\n source: string,\n options: { pdf?: boolean } = { pdf: true }\n) {\n generateTeX(source)\n\n if (!options.pdf) {\n consola.success('Generated resume TeX file successfully.')\n return\n }\n\n const command = inferLaTeXCommand(source)\n consola.start(`Generating resume PDF file with command: \\`${command}\\`...`)\n\n try {\n const stdout = child_process.execSync(command, { encoding: 'utf8' })\n consola.success('Generated resume PDF file successfully.')\n consola.debug(joinNonEmptyString(['stdout: ', toCodeBlock(stdout)]))\n } catch (error) {\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 * 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 and PDF')\n .argument('<source>', 'the source resume file')\n .option('--no-pdf', 'only generate TeX file without PDF')\n .action(async (source: string, options: { pdf: boolean }) => {\n try {\n buildResume(source, options)\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 { fileURLToPath } from 'node:url'\nimport { Command } from 'commander'\nimport consola from 'consola'\n\nimport {\n YAMLResumeError,\n joinNonEmptyString,\n toCodeBlock,\n} from '@yamlresume/core'\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 LOCALE_LANGUAGE_OPTIONS,\n getLocaleLanguageOptionDetail,\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 ['layout.locale.language', 'Language Name'],\n ...LOCALE_LANGUAGE_OPTIONS.map((value) => [\n value,\n getLocaleLanguageOptionDetail(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 { TEMPLATE_OPTIONS, getTemplateOptionDetail } 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 return markdownTable([\n ['layout.template', 'Template Name', 'Description'],\n ...TEMPLATE_OPTIONS.map((value) => {\n const details = getTemplateOptionDetail(value)\n return [value, details.name, details.description]\n }),\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 * 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 createLanguagesCommand,\n createNewCommand,\n createTemplatesCommand,\n} from './commands'\nimport { setVerboseLog } from './utils'\n\nexport const program = new Command()\n\nconst banner = `\n __ __ _ __ __ _ ____\n \\\\ \\\\ / // \\\\ | \\\\/ | | | _ \\\\ ___ ___ _ _ ___ ___ ___\n \\\\ V // _ \\\\ | |\\\\/| | | | |_) / _ \\\\/ __| | | / _ \\\\/ _ \\\\ / _ \\\\\n | |/ ___ \\\\| | | | |___| _ < __/\\\\__ \\\\ |_| | | | | | | __/\n |_/_/ \\\\_\\\\_| |_|_____|_| \\\\_\\\\___||___/\\\\____|_| |_| |_|\\\\___|\n`\n\nprogram\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\nprogram.addCommand(createNewCommand())\nprogram.addCommand(createBuildCommand())\nprogram.addCommand(createLanguagesCommand())\nprogram.addCommand(createTemplatesCommand())\n","#!/usr/bin/env node\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 { program } from './program'\n\nprogram.parse()\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "yamlresume",
3
- "version": "0.4.0",
3
+ "version": "0.4.2",
4
4
  "description": "The CLI interface for YAMLResume's engine",
5
5
  "license": "MIT",
6
6
  "author": {
@@ -37,7 +37,7 @@
37
37
  "tslib": "^2.8.1",
38
38
  "which": "^5.0.0",
39
39
  "yaml": "^2.7.1",
40
- "@yamlresume/core": "0.4.0"
40
+ "@yamlresume/core": "0.4.2"
41
41
  },
42
42
  "devDependencies": {
43
43
  "@types/commander": "^2.12.5",