yamlresume 0.2.2 → 0.2.4

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,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import {Command}from'commander';import y from'node:child_process';import a from'node:fs';import {LocaleLanguageOption,getLocaleLanguageOptionDetail,TemplateOption,getTemplateOptionDetail,MarkdownParser,getResumeRenderer}from'@yamlresume/core';import b from'which';import C from'yaml';import d from'node:path';import {fileURLToPath}from'node:url';import {markdownTable}from'markdown-table';var l={version:"0.2.2"};function u(e){if(e.endsWith(".yaml")||e.endsWith(".yml")||e.endsWith(".json"))return e.replace(/\.yaml|\.yml|\.json$/,".tex");throw new Error(`Unsupported file extension: ${e}`)}function c(e){try{return !!b.sync(e)}catch{return false}}function L(){if(c("xelatex"))return "xelatex";if(c("tectonic"))return "tectonic";throw new Error("neither xelatex nor tectonic is installed")}function v(e){let t=L(),m=u(e);return `${t} -halt-on-error ${m}`}function T(e){let t=u(e),m=a.readFileSync(e,"utf8"),_=new MarkdownParser,g=getResumeRenderer(C.parse(m),_).render();a.writeFileSync(t,g);}function R(e){T(e);let t=v(e);console.log(`-> generating resume PDF with command: \`${t}\`...`),y.execSync(t),console.log("-> resume PDF generated successfully.");}function E(e){R(e);}var s=new Command().name("build").description("build a resume to LaTeX and PDF").argument("<source>","the source resume file").action(e=>{E(e);});var i=new Command().name("new").description("create a new resume").argument("[filename]","output filename","resume.yml").action(e=>{try{if(a.existsSync(e))throw new Error([`File "${e}" already exists.`,"Please choose a different name or remove the existing file."].join(" "));let t=d.join(d.dirname(fileURLToPath(import.meta.url)),import.meta.url.includes("dist")?"../resources/software-engineer.yml":"../../resources/software-engineer.yml");a.writeFileSync(e,a.readFileSync(t,"utf8")),console.log(`-> Successfully created ${e}.`);}catch(t){console.error("Error creating resume template:",t),process.exit(1);}});function O(){return markdownTable([["`layout.locale.language`","Language Name"],...Object.values(LocaleLanguageOption).map(e=>[e,getLocaleLanguageOptionDetail(e).name])])}var n=new Command().name("languages").description("i18n and l10n support");n.command("list").description("list all supported languages").action(()=>{console.log(O());});function Y(){return markdownTable([["`layout.template`","Template Name","Description"],...Object.values(TemplateOption).map(e=>{let t=getTemplateOptionDetail(e);return [e,t.name,t.description]})])}var o=new Command().name("templates").description("manage resume templates");o.command("list").description("list all supported templates").action(()=>{console.log(Y());});var r=new Command,I=`
2
+ import {Command}from'commander';import y from'node:child_process';import a from'node:fs';import {LocaleLanguageOption,getLocaleLanguageOptionDetail,TemplateOption,getTemplateOptionDetail,MarkdownParser,getResumeRenderer}from'@yamlresume/core';import b from'which';import C from'yaml';import d from'node:path';import {fileURLToPath}from'node:url';import {markdownTable}from'markdown-table';var l={version:"0.2.4"};function u(e){if(e.endsWith(".yaml")||e.endsWith(".yml")||e.endsWith(".json"))return e.replace(/\.yaml|\.yml|\.json$/,".tex");throw new Error(`Unsupported file extension: ${e}`)}function c(e){try{return !!b.sync(e)}catch{return false}}function L(){if(c("xelatex"))return "xelatex";if(c("tectonic"))return "tectonic";throw new Error("neither xelatex nor tectonic is installed")}function v(e){let t=L(),m=u(e);return `${t} -halt-on-error ${m}`}function T(e){let t=u(e),m=a.readFileSync(e,"utf8"),_=new MarkdownParser,g=getResumeRenderer(C.parse(m),_).render();a.writeFileSync(t,g);}function R(e){T(e);let t=v(e);console.log(`-> generating resume PDF with command: \`${t}\`...`),y.execSync(t),console.log("-> resume PDF generated successfully.");}function E(e){R(e);}var s=new Command().name("build").description("build a resume to LaTeX and PDF").argument("<source>","the source resume file").action(e=>{E(e);});var i=new Command().name("new").description("create a new resume").argument("[filename]","output filename","resume.yml").action(e=>{try{if(a.existsSync(e))throw new Error([`File "${e}" already exists.`,"Please choose a different name or remove the existing file."].join(" "));let t=d.join(d.dirname(fileURLToPath(import.meta.url)),import.meta.url.includes("dist")?"../resources/resume.yml":"../../resources/resume.yml");a.writeFileSync(e,a.readFileSync(t,"utf8")),console.log(`-> Successfully created ${e}.`);}catch(t){console.error("Error creating resume template:",t),process.exit(1);}});function O(){return markdownTable([["`layout.locale.language`","Language Name"],...Object.values(LocaleLanguageOption).map(e=>[e,getLocaleLanguageOptionDetail(e).name])])}var n=new Command().name("languages").description("i18n and l10n support");n.command("list").description("list all supported languages").action(()=>{console.log(O());});function Y(){return markdownTable([["`layout.template`","Template Name","Description"],...Object.values(TemplateOption).map(e=>{let t=getTemplateOptionDetail(e);return [e,t.name,t.description]})])}var o=new Command().name("templates").description("manage resume templates");o.command("list").description("list all supported templates").action(()=>{console.log(Y());});var r=new Command,I=`
3
3
  __ __ _ __ __ _ ____
4
4
  \\ \\ / // \\ | \\/ | | | _ \\ ___ ___ _ _ ___ ___ ___
5
5
  \\ V // _ \\ | |\\/| | | | |_) / _ \\/ __| | | / _ \\/ _ \\ / _ \\
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/program.ts","../src/cli.ts"],"names":["package_default","inferOutput","source","isCommandAvailable","command","which","inferLaTeXEnvironment","inferLaTeXCommand","environment","destination","generateTeX","texFile","resume","fs","summaryParser","MarkdownParser","tex","getResumeRenderer","yaml","generatePDF","child_process","buildResume","buildCommand","Command","newCommand","filename","templatePath","path","fileURLToPath","error","listLanguages","markdownTable","LocaleLanguageOption","value","getLocaleLanguageOptionDetail","languagesCommand","listTemplates","TemplateOption","details","getTemplateOptionDetail","templatesCommand","program","banner"],"mappings":"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","file":"cli.js","sourcesContent":["{\n \"name\": \"yamlresume\",\n \"version\": \"0.2.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 \"coverage\": \"vitest --coverage --run\",\n \"dev\": \"tsx src/cli.ts\",\n \"test\": \"vitest --run\",\n \"test:watch\": \"vitest\"\n },\n \"dependencies\": {\n \"@yamlresume/core\": \"workspace:*\",\n \"commander\": \"^11.0.0\",\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 {\n MarkdownParser,\n type Resume,\n getResumeRenderer,\n} from '@yamlresume/core'\nimport { Command } from 'commander'\nimport which from 'which'\nimport yaml from 'yaml'\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 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 Error(`Unsupported file extension: ${source}`)\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 Error('neither xelatex nor tectonic is installed')\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 return `${environment} -halt-on-error ${destination}`\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 const resume = fs.readFileSync(source, 'utf8')\n const summaryParser = new MarkdownParser()\n\n const renderer = getResumeRenderer(\n yaml.parse(resume) as Resume,\n summaryParser\n )\n const tex = renderer.render()\n\n fs.writeFileSync(texFile, tex)\n}\n\n/**\n * Compiles the resume source file to a PDF file.\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 * @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 */\nexport function generatePDF(source: string) {\n generateTeX(source)\n\n const command = inferLaTeXCommand(source)\n console.log(`-> generating resume PDF with command: \\`${command}\\`...`)\n\n child_process.execSync(command)\n console.log('-> resume PDF generated successfully.')\n}\n\n/**\n * Build a resume to LaTeX & PDF\n *\n * This function will read a resume from a file in yaml or json format, and then\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 * This function will throw an exception if any error\n *\n * @param source - The source resume file\n * @throws {Error} If any part of the PDF generation process fails (forwarded\n * from `generatePDF`).\n * @todo Check the resume format against YAMLResume schema before compilation.\n */\nexport function buildResume(source: string) {\n generatePDF(source)\n}\n\n/**\n * Commander command instance to build a YAML resume to LaTeX and PDF\n *\n * @param source - The source resume file\n * @throws {Error} If any part of the PDF generation process fails (forwarded\n * from `generatePDF`).\n */\nexport const buildCommand = new Command()\n .name('build')\n .description('build a resume to LaTeX and PDF')\n .argument('<source>', 'the source resume file')\n .action((source: string) => {\n buildResume(source)\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'\n\n/**\n * Commander command instance to create a new YAML resume\n *\n * @param filename - The output filename for the new resume\n * @throws {Error} If file creation fails\n */\nexport const newCommand = new Command()\n .name('new')\n .description('create a new resume')\n .argument('[filename]', 'output filename', 'resume.yml')\n .action((filename) => {\n try {\n if (fs.existsSync(filename)) {\n throw new Error(\n [\n `File \"${filename}\" already exists.`,\n 'Please choose a different name or remove the existing file.',\n ].join(' ')\n )\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/software-engineer.yml'\n : '../../resources/software-engineer.yml'\n /* v8 ignore stop */\n )\n\n fs.writeFileSync(filename, fs.readFileSync(templatePath, 'utf8'))\n console.log(`-> Successfully created ${filename}.`)\n } catch (error) {\n console.error('Error creating resume template:', error)\n process.exit(1)\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 { 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 * Commander command instance to list supported languages\n *\n * Provides subcommands like 'list' to interact with language settings or\n * information.\n */\nexport const languagesCommand = new Command()\n .name('languages')\n .description('i18n and l10n support')\n\nlanguagesCommand\n .command('list')\n .description('list all supported languages')\n .action(() => {\n console.log(listLanguages())\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 { 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 * Commander command instance to list supported templates\n *\n * Provides subcommands like 'list' to interact with template information.\n */\nexport const templatesCommand = new Command()\n .name('templates')\n .description('manage resume templates')\n\ntemplatesCommand\n .command('list')\n .description('list all supported templates')\n .action(() => {\n console.log(listTemplates())\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 buildCommand,\n languagesCommand,\n newCommand,\n templatesCommand,\n} from './commands'\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\nprogram.addCommand(newCommand)\nprogram.addCommand(buildCommand)\nprogram.addCommand(languagesCommand)\nprogram.addCommand(templatesCommand)\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/program.ts","../src/cli.ts"],"names":["package_default","inferOutput","source","isCommandAvailable","command","which","inferLaTeXEnvironment","inferLaTeXCommand","environment","destination","generateTeX","texFile","resume","fs","summaryParser","MarkdownParser","tex","getResumeRenderer","yaml","generatePDF","child_process","buildResume","buildCommand","Command","newCommand","filename","templatePath","path","fileURLToPath","error","listLanguages","markdownTable","LocaleLanguageOption","value","getLocaleLanguageOptionDetail","languagesCommand","listTemplates","TemplateOption","details","getTemplateOptionDetail","templatesCommand","program","banner"],"mappings":"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","file":"cli.js","sourcesContent":["{\n \"name\": \"yamlresume\",\n \"version\": \"0.2.4\",\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 \"coverage\": \"vitest --coverage --run\",\n \"dev\": \"tsx src/cli.ts\",\n \"test\": \"vitest --run\",\n \"test:watch\": \"vitest\"\n },\n \"dependencies\": {\n \"@yamlresume/core\": \"workspace:*\",\n \"commander\": \"^11.0.0\",\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 {\n MarkdownParser,\n type Resume,\n getResumeRenderer,\n} from '@yamlresume/core'\nimport { Command } from 'commander'\nimport which from 'which'\nimport yaml from 'yaml'\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 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 Error(`Unsupported file extension: ${source}`)\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 Error('neither xelatex nor tectonic is installed')\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 return `${environment} -halt-on-error ${destination}`\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 const resume = fs.readFileSync(source, 'utf8')\n const summaryParser = new MarkdownParser()\n\n const renderer = getResumeRenderer(\n yaml.parse(resume) as Resume,\n summaryParser\n )\n const tex = renderer.render()\n\n fs.writeFileSync(texFile, tex)\n}\n\n/**\n * Compiles the resume source file to a PDF file.\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 * @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 */\nexport function generatePDF(source: string) {\n generateTeX(source)\n\n const command = inferLaTeXCommand(source)\n console.log(`-> generating resume PDF with command: \\`${command}\\`...`)\n\n child_process.execSync(command)\n console.log('-> resume PDF generated successfully.')\n}\n\n/**\n * Build a resume to LaTeX & PDF\n *\n * This function will read a resume from a file in yaml or json format, and then\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 * This function will throw an exception if any error\n *\n * @param source - The source resume file\n * @throws {Error} If any part of the PDF generation process fails (forwarded\n * from `generatePDF`).\n * @todo Check the resume format against YAMLResume schema before compilation.\n */\nexport function buildResume(source: string) {\n generatePDF(source)\n}\n\n/**\n * Commander command instance to build a YAML resume to LaTeX and PDF\n *\n * @param source - The source resume file\n * @throws {Error} If any part of the PDF generation process fails (forwarded\n * from `generatePDF`).\n */\nexport const buildCommand = new Command()\n .name('build')\n .description('build a resume to LaTeX and PDF')\n .argument('<source>', 'the source resume file')\n .action((source: string) => {\n buildResume(source)\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'\n\n/**\n * Commander command instance to create a new YAML resume\n *\n * @param filename - The output filename for the new resume\n * @throws {Error} If file creation fails\n */\nexport const newCommand = new Command()\n .name('new')\n .description('create a new resume')\n .argument('[filename]', 'output filename', 'resume.yml')\n .action((filename) => {\n try {\n if (fs.existsSync(filename)) {\n throw new Error(\n [\n `File \"${filename}\" already exists.`,\n 'Please choose a different name or remove the existing file.',\n ].join(' ')\n )\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 fs.writeFileSync(filename, fs.readFileSync(templatePath, 'utf8'))\n console.log(`-> Successfully created ${filename}.`)\n } catch (error) {\n console.error('Error creating resume template:', error)\n process.exit(1)\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 { 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 * Commander command instance to list supported languages\n *\n * Provides subcommands like 'list' to interact with language settings or\n * information.\n */\nexport const languagesCommand = new Command()\n .name('languages')\n .description('i18n and l10n support')\n\nlanguagesCommand\n .command('list')\n .description('list all supported languages')\n .action(() => {\n console.log(listLanguages())\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 { 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 * Commander command instance to list supported templates\n *\n * Provides subcommands like 'list' to interact with template information.\n */\nexport const templatesCommand = new Command()\n .name('templates')\n .description('manage resume templates')\n\ntemplatesCommand\n .command('list')\n .description('list all supported templates')\n .action(() => {\n console.log(listTemplates())\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 buildCommand,\n languagesCommand,\n newCommand,\n templatesCommand,\n} from './commands'\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\nprogram.addCommand(newCommand)\nprogram.addCommand(buildCommand)\nprogram.addCommand(languagesCommand)\nprogram.addCommand(templatesCommand)\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.2.2",
3
+ "version": "0.2.4",
4
4
  "description": "The CLI interface for YAMLResume's engine",
5
5
  "license": "MIT",
6
6
  "author": {
@@ -36,7 +36,7 @@
36
36
  "tslib": "^2.8.1",
37
37
  "which": "^5.0.0",
38
38
  "yaml": "^2.7.1",
39
- "@yamlresume/core": "0.2.2"
39
+ "@yamlresume/core": "0.2.4"
40
40
  },
41
41
  "devDependencies": {
42
42
  "@types/commander": "^2.12.5",