RSS Git Download  Clone
Raw Blame History
const utils = require('corifeus-utils');
const path = require('path');
const fs = require('mz/fs');
const fsExtra = require('fs-extra');
const template = require('lodash/template');
const cleanDeep = require('lodash/cloneDeep');
const cheerio = require('cheerio')
const startCase = require('lodash/startCase');

const os = require('os');
const isWin = os.platform() === 'win32';
const binPathAddon = isWin ? '' : 'wkhtmltox/';

let binpath = path.resolve(`${__dirname}/../release/${binPathAddon}bin/wkhtmltopdf`);
// if we are in arm64, change the binpath
if (os.arch() === 'arm64') {
    binpath = `${__dirname}/../release/wkhtmltopdf-arm64`
}

const generate = async (options) => {
    const {settings, saveFile, base, debug, title} = options;
    let {javascriptDelay} = options;

    //console.log('options', options)

    const isFixed = () => {
        return settings.template.fixedWidth > 0 && settings.template.fixedHeight
    }

    const save = settings.hasOwnProperty('save') && settings.save === true;

//    const consoleDebugOriginal = console.debug;
    if (debug) {
        console.debug = console.info;
    } else {
        console.debug = () => {
        };
    }

    let tmpHtmlPath;
    let tmpPdfPath;
    let tmpHtmlPathFooter;
    let tmpHtmlPathHeader;
    try {
        const baseHtml = (await fs.readFile(`${__dirname}/base.html`)).toString();
        const baseHtmlFooterHeader = (await fs.readFile(`${__dirname}/header-footer.html`)).toString();

        options.base = options.base || 'file://' + process.cwd();
        options.css = options.css || (await fs.readFile(`${__dirname}/html-template.css`)).toString();
        options.jquery = options.jquery || (await fs.readFile(`${__dirname}/jquery-1.12.4.min.js`)).toString();

        let html = template(baseHtml)(options)

        let $ = cheerio.load(html);

        const $id = $('[id]');

        let header = {}
        let footer = {};

        const defaultHeightMargin = '10mm';
        let marginTop = defaultHeightMargin;
        let marginBottom = defaultHeightMargin;
        $id.each((index, element) => {
            const $element = $(element)
            //const $parent = $element.parent();
//            console.debug($parent.html());
            const id = $element.attr('id');
            if (id.startsWith('p3x-header')) {
                header[id] = `<div>${$element.html()}</div>`;
                marginTop = $element.data('height') || defaultHeightMargin;
                $element.remove();
            } else if (id.startsWith('p3x-footer')) {
                footer[id] = `<div>${$element.html()}</div>`;
                marginBottom = $element.data('height') || defaultHeightMargin;
                $element.remove();
            }
        })


//        console.debug('marginTop', marginTop);
//        console.debug('marginBottom', marginBottom);

        /*
         page: <span class="page"></span>
         frompage: <span class="frompage"></span>
         topage: <span class="topage"></span> = pages
         webpage: <span class="webpage"></span>
         section: <span class="section"></span>
         subsection: <span class="subsection"></span>
         date: <span class="date"></span>
         isodate: <span class="isodate"></span>
         time: <span class="time"></span>
         title: <span class="title"></span>
         doctitle: <span class="doctitle"></span>
         sitepage: <span class="sitepage"></span>
         sitepages: <span class="sitepages"></span>
         */


        $('.p3x-header').remove();
        $('.p3x-footer').remove();
        //$('ng-core-pdf-template-include').remove()
        //$('ng-html-template-include').remove()
        html = $.html();

        html = html.replace(/\${qr}/g, options.settings.qr)

        const headerOrFooter = (data, type) => {

            const lodashTemplateHack = `
        item = item.replace(/\\$\{page}/g, vars.page);
        item = item.replace(/\\$\{pages}/g, vars.pages);
        item = item.replace(/\\$\{frompage}/g, vars.frompage);
        item = item.replace(/\\$\{topage}/g, vars.topage);
        item = item.replace(/\\$\{webpage}/g, vars.webpage);
        item = item.replace(/\\$\{section}/g, vars.section);
        item = item.replace(/\\$\{subsection}/g, vars.subsection);
        item = item.replace(/\\$\{date}/g, vars.date);
        item = item.replace(/\\$\{isodate}/g, vars.isodate);
        item = item.replace(/\\$\{time}/g, vars.time);
        item = item.replace(/\\$\{title}/g, vars.title);
        item = item.replace(/\\$\{doctitle}/g, vars.doctitle);
        item = item.replace(/\\$\{sitepage}/g, vars.sitepage);
        item = item.replace(/\\$\{sitepages}/g, vars.sitepages);
        item = item.replace(/\\$\{qr}/g, qr);

`;

            const mainsSettings = cleanDeep(options)
            mainsSettings.settings.html = JSON.stringify(data, null, 4);

            data = template(baseHtmlFooterHeader)(mainsSettings)
            data = data.replace('// headerOrFooter //', `var headerOrFooter = ${type};`)
            data = data.replace('// lodash-template-hack //', lodashTemplateHack)

            data = data.replace('// qr-hack //', `
var qr = ${JSON.stringify(mainsSettings.settings.qr)};
`)

            return {
                mainSettings: mainsSettings,
                data: data
            }
        }

        const headResult = headerOrFooter(header, 1)
//        const headerSettings = headResult.mainSettings;
        header = headResult.data;
        const footResult = headerOrFooter(footer, 2)
//        const footerSettings = footResult.mainSettings;
        footer = footResult.data;

//        console.debug('headerSettings', headerSettings)
//        console.debug('footerSettings', footerSettings)

//        console.debug('html', html)
//        console.debug('header', header)

        if (save) {
            tmpPdfPath = saveFile;
            tmpHtmlPath = `${saveFile}.html`;
            await utils.fs.ensureFile(tmpHtmlPath, html);
        } else {
            tmpHtmlPath = await utils.fs.ensureTempFile(html, 'html')
            tmpPdfPath = await utils.fs.tempFileName('pdf');
        }

        tmpHtmlPathHeader = await utils.fs.ensureTempFile(header, 'html')
        tmpHtmlPathFooter = await utils.fs.ensureTempFile(footer, 'html')

        //console.debug('header', footer)
        //console.debug('footer', footer)
        //console.debug('html', footer)
       // console.debug('tmpHtmlPath', tmpHtmlPath);
       // console.debug('tmpPdfPath', tmpPdfPath);

// --header-html ${tmpHtmlPath}  --footer-html ${tmpHtmlPath}
        /*
         -B, --margin-bottom <unitreal>      Set the page bottom margin
         -L, --margin-left <unitreal>        Set the page left margin (default 10mm)
         -R, --margin-right <unitreal>       Set the page right margin (default 10mm)
         -T, --margin-top <unitreal>         Set the page top margin
         */

//
//
        if (javascriptDelay === undefined) {
            javascriptDelay = 1000;
        }

        let addOn = '';
        if (isFixed()) {
            marginTop = '0mm';
            marginBottom = '0mm';
            addOn += ` --margin-left 0mm --margin-right 0mm --disable-smart-shrinking`
        } else {
            if (settings.template.marginLeft !== null && settings.template.marginLeft !== undefined) {
                addOn += ` --margin-left ${settings.template.marginLeft}mm `
            }
            if (settings.template.marginRight != null && settings.template.marginLeft !== undefined) {
                addOn += ` --margin-right ${settings.template.marginRight}mm `
            }
        }
        const pageSize = isFixed() ? `--page-width ${settings.template.fixedWidth + 1}mm --page-height ${settings.template.fixedHeight + 1}mm` : `--page-size ${settings.template.format}`;
        const generatePdfCommand = `${binpath} --javascript-delay ${javascriptDelay} --copies ${settings.template.copies} --margin-bottom ${marginBottom} --margin-top ${marginTop}  ${addOn}  ${debug ? '--debug-javascript' : ''} --title ${JSON.stringify(title + ' ' + new Date().toLocaleString())} --orientation ${startCase(settings.template.orientation)} ${pageSize} ${tmpHtmlPath} --header-html ${tmpHtmlPathHeader} --footer-html ${tmpHtmlPathFooter} ${tmpPdfPath}`;

        console.debug('generatePdfCommand', generatePdfCommand);

        await utils.childProcess.exec(generatePdfCommand, debug);

        if (!save) {
            return await fs.readFile(tmpPdfPath);
        }
    } finally {
        if (tmpHtmlPath !== undefined) {
            await fsExtra.remove(tmpHtmlPath);
        }
        if (tmpHtmlPathFooter !== undefined) {
            await fsExtra.remove(tmpHtmlPathFooter);
        }
        if (tmpHtmlPathHeader !== undefined) {
            await fsExtra.remove(tmpHtmlPathHeader);
        }
        if (!save && tmpPdfPath !== undefined) {
            await fsExtra.remove(tmpPdfPath);
        }
//        console.debug = consoleDebugOriginal;
    }
}
module.exports.generate = generate;