const puppeteer = require('puppeteer'); const fs = require('fs'); const path = require('path'); const http = require('http'); const config = require('../config'); const devPort = process.env.PORT || config.dev.port; const { interval } = require('rxjs'); const { filter, first, mergeMap } = require('rxjs/operators'); const fetchResponse = () => { return new Promise((res, rej) => { try { const req = http.request(`http://localhost:${devPort}/#/`, response => res(response.statusCode)); req.on('error', (err) => rej(err)); req.end(); } catch (err) { rej(err); } }); }; const waitForServerReachable = () => { return interval(1000).pipe( mergeMap(async () => { try { const statusCode = await fetchResponse(); if (statusCode === 200) return true; } catch (err) {} return false; }), filter(ok => !!ok) ); }; /* const timedOut = timeout => { return new Promise(res => { setTimeout(res, timeout); }); }; */ const convert = async () => { await waitForServerReachable().pipe( first() ).toPromise(); console.log('Connected to server ...'); console.log('Exporting ...'); try { const fullDirectoryPath = path.join(__dirname, '../pdf/'); let directories = getResumesFromDirectories(); const resumeFilterRaw = (process.env.EXPORT_RESUME || process.argv[2] || '').trim(); const resumeFilter = resumeFilterRaw.replace(/\.vue$/i, '').toLowerCase(); if (resumeFilter) { directories = directories.filter(d => d.name.toLowerCase() === resumeFilter); if (directories.length === 0) { console.error( `No resume template "${resumeFilterRaw}". Expected a name like "green" (see src/resumes/*.vue).` ); process.exit(1); } console.log('Resume filter: ' + directories.map(d => d.name).join(', ')); } for (const dir of directories) { const browser = await puppeteer.launch({ headless: true, args: ['--no-sandbox', '--font-render-hinting=none'] }); const page = await browser.newPage(); await page.goto(`http://localhost:${devPort}/#/resume/` + dir.name, { waitUntil: 'load', timeout: 120000 }); try { await page.evaluate(() => document.fonts.ready); } catch (_err) { /* ignore if fonts API missing */ } await new Promise((r) => setTimeout(r, 300)); if ( !fs.existsSync(fullDirectoryPath) ) { fs.mkdirSync(fullDirectoryPath); } await page.pdf({ path: fullDirectoryPath + dir.name + '.pdf', format: 'A4', printBackground: true }); await browser.close(); } } catch (err) { throw new Error(err); } console.log('Finished exports.'); }; const getResumesFromDirectories = () => { const directories = getDirectories(); return directories .map(dir => { const fileName = dir.replace('.vue', ''); return { path: fileName, name: fileName }; }); }; const getDirectories = () => { const srcpath = path.join(__dirname, '../src/resumes'); return fs.readdirSync(srcpath) .filter(file => file !== 'resumes.js' && file !== 'template.vue' && file !== 'options.js'); }; convert();