UNPKG

@reason.co/docugen

Version:

`npm i docugen` (private npm install for now)

129 lines (108 loc) 3.69 kB
#!/usr/bin/env node const fs = require('fs-extra'); const path = require('path'); const os = require('os'); const mdToPdf = require('md-to-pdf'); const marked = require('marked'); const yaml = require('js-yaml'); const singleHeadingRegex = /^(#+)\s+(.*)$/; const allHeadingsRegex = new RegExp(singleHeadingRegex, 'gm'); const renderToc = (headings, maxDepth = 3) => { const markdown = headings .slice(1) // ignore h1 .map((heading) => { try { const [hashes, title] = heading.match(singleHeadingRegex); const headingLevel = hashes.length - 1; if (headingLevel <= maxDepth) { return `${' '.repeat(headingLevel - 1)}1. ${title}`; } } catch(e){ console.log('Bad heading',heading,e); } }) .filter(Boolean) .join('\n'); return `<div class="toc">${marked(markdown)}</div>`; }; async function renderFile( srcFile, outDir, tmpDir, version, projectname, helperHtml, config ) { let markdownSource = includeFile(srcFile); const filename = path.basename(srcFile); const headings = []; /* const markdownWithHeadings = markdownSource.replace( allHeadingsRegex, (headingLine) => { headings.push(headingLine); return headingLine; } ); */ const markdownCombined = [helperHtml, markdownSource] .join('\r\n\r\n') .replace(/\[\[\s*TOC\s*]]/i, renderToc(headings)) .replace(/{fileName}/g, filename) .replace(/{projectname}/g, projectname) .replace(/{runDate}/g, new Date().toLocaleString()) .replace(/{version}/g, version); await fs.writeFile(`${tmpDir}/${filename}`, markdownCombined); const dest = `${outDir}/${path.basename(filename, '.md')}.pdf`; const mergedPdf = await mdToPdf(`${tmpDir}/${filename}`, { ...config, dest }); return mergedPdf.filename.replace(process.cwd(), ''); } function includeFile(srcFile) { return fs .readFileSync(srcFile, 'utf8') .replace(/\[\[\s*include\s+(['"])(.+)\1\s*]]/g, (_1, _2, relativePath) => includeFile(path.resolve(path.dirname(srcFile), relativePath)) ); } async function renderFolder(args) { let {sourcedir, destdir, version, projectname} = args.opts; //const pkg = require('../../../package.json'); //const [majorVersion, minorVersion] = pkg.version.split('.'); const filenames = fs.readdirSync(sourcedir).filter((elm) => elm.match(/\.md$/i)); const tmpDir = fs.mkdtempSync(`${os.tmpdir()}/docgen`); await fs.copy(sourcedir, tmpDir); await fs.copy(`${__dirname}/fonts`, `${tmpDir}/fonts`); await fs.ensureDir(destdir); const [configYaml, helperHtml, pageHeader, pageFooter] = [ 'config.yml', 'helpers.html', 'header.html', 'footer.html', ].map((file) => fs.readFileSync(`${__dirname}/templates/${file}`, 'utf8')); const pageFooterWithVersion = pageFooter .replace(/{versionNumber}/g, version) .replace(/{projectname}/g, projectname) .replace(/{runDate}/g, new Date().toLocaleString()); const config = yaml.safeLoad(configYaml); // stylesheet paths are relative to CWD by default so make them absolute config.stylesheet = config.stylesheet.map((file) => `${__dirname}/${file}`); config.pdf_options.headerTemplate = pageHeader; config.pdf_options.footerTemplate = pageFooterWithVersion; const generatedFiles = await Promise.all( filenames.map((filename) => renderFile( `${sourcedir}/${filename}`, destdir, tmpDir, version, projectname, helperHtml, config, ) ) ); console.info('Created PDF docs:'); console.info(generatedFiles.map((name) => `- ${name}`).join('\n')); } module.exports = renderFolder;