#!/usr/bin/env node const fs = require("fs"); const path = require("path"); const yaml = require("yaml"); const { exec, execSync } = require("child_process"); const puppeteer = require("puppeteer"); const pug = require("pug"); function parseData(dataFilePath) { return yaml.parse(fs.readFileSync(dataFilePath, { encoding: "utf8" })); } function createHtml(pugFile, data, outputPath) { const rendered = pug.renderFile(pugFile, data); fs.writeFile(outputPath, rendered, (err) => { if (err) throw err; }); } async function printPDF(url) { const browser = await puppeteer.launch({ headless: "new" }); const page = await browser.newPage(); await page.goto(url, { waitUntil: "networkidle0" }); const pdf = await page.pdf({ format: "A4" }); await browser.close(); return pdf; } function exportToPdf(htmlFile, pdfPath) { url = `file://${path.resolve(htmlFile)}`; printPDF(url).then((pdf) => { fs.writeFile(pdfPath, pdf, (err) => { if (err) throw err; }); }); } function cleanString(string) { return string.replaceAll(" ", "_"); } function exportRenderToPdf(dataFilePath, templatePath, assetsPath, outputPath) { const data = parseData(dataFilePath); const outputBasename = `CV_${cleanString(data.basics.name)}_${cleanString(data.basics.label)}`; const revPath = path.join(outputPath, `${outputBasename}.revision.txt`); const htmlPath = path.join(outputPath, `${outputBasename}.html`); const pdfPath = path.join(outputPath, `${outputBasename}.pdf`); const newAssetsPath = path.join(outputPath, "assets"); fs.mkdirSync(outputPath, { recursive: true }); fs.mkdirSync(newAssetsPath, { recursive: true }); fs.cpSync(assetsPath, newAssetsPath, { recursive: true }); createHtml(templatePath, data, htmlPath); console.log(`Wrote HTML file to ${htmlPath}`); exportToPdf(htmlPath, pdfPath); console.log(`Wrote PDF file to ${pdfPath}`); writeGitRevisionFile(dataFilePath, templatePath, assetsPath, revPath); } function writeGitRevisionFile(dataFilePath, templatePath, assetsPath, revPath) { const allFiles = `${dataFilePath} ${templatePath} ${assetsPath}`; const dirty = areDirty(allFiles); const cmd = `git log --format="%H" ${allFiles} | head -1`; exec(cmd, (err, stdout, stderr) => { if (err) { return; } const newRev = dirty ? `#${stdout}` : stdout; fs.appendFile(revPath, newRev, (err) => { if (err) throw err; }); console.log(`Wrote ${dirty ? "dirty" : "clean"} revision data to ${revPath}`); }); } function areDirty(fileList) { const dirtyStatusCmd = `git diff --quiet ${fileList}`; try { execSync(dirtyStatusCmd); return false; } catch { return true; } } const [inputPath, variantName, outputPath] = process.argv.slice(2); if (!inputPath || !variantName || !outputPath) { console.error(`The script should be called like :\n${process.argv[1]} input_path variant_name output_dir`); process.exit(1); } const dataFilePath = path.join(inputPath, `${variantName}.yaml`); const templatePath = path.join(inputPath, `template.pug`); const assetsPath = path.join(inputPath, "assets"); exportRenderToPdf(dataFilePath, templatePath, assetsPath, outputPath);