PejmanNik / puppeteer-report

Convert HTML to PDF by Puppeteer with support of adding a custom header, footer, and page number
MIT License
148 stars 28 forks source link

Different header on pages with pageRanges? #52

Open 7iomka opened 1 year ago

7iomka commented 1 year ago

Hi. With clean puppeteer we can able to use something like this:


const puppeteer = require('puppeteer');
const { writeFile } = require('fs');
const { PDFDocument } = require('pdf-lib');

(async () => {
  const browser = await puppeteer.launch({
    headless: 'new',
    ignoreHTTPSErrors: true,
    args: ['--lang=en-US'],
  });
  const browserPage = await browser.newPage();

  await browserPage.goto('http://localhost:5555/templates/payment-invoice/', {
    waitUntil: ['load', 'networkidle2'],
  });

  // header for the 1st page (not needed)
  const firstPageHeader = `<div class="header-first"></div>`;

  // header for the all next pages
  const otherPagesHeader = `<div class="header-other">some header content</div>`;

  const printedPdf = await browserPage.pdf({
    printBackground: true,
    format: 'A4',
    displayHeaderFooter: true,
    headerTemplate: firstPageHeader,
    footerTemplate: ``, 
    margin: { bottom: '0px' },
    scale: 1,
    pageRanges: '1', // apply firstPageHeader only for first page
  });

  const printedOtherPagesPdf = await browserPage.pdf({
    printBackground: true,
    format: 'A4',
    displayHeaderFooter: true,
    headerTemplate: otherPagesHeader,
    footerTemplate: ``, 
    margin: { bottom: '0px' },
    scale: 1,
    pageRanges: '2-', // apply otherPagesHeader for other pages
  });

  await browser.close();

  // Safe both PDF in the temp files
  writeFile('./output/first_page.pdf', printedPdf, {}, (err) => {
    if (err) {
      return console.error('Error saving first page PDF');
    }
    console.log('First page PDF saved successfully!');
  });

  writeFile('./output/other_pages.pdf', printedOtherPagesPdf, {}, (err) => {
    if (err) {
      return console.error('Error saving other pages PDF');
    }
    console.log('Other pages PDF saved successfully!');
  });

  // Combine them into resulted one
  const firstPagePdfBytes = await readFile('./output/first_page.pdf');
  const otherPagesPdfBytes = await readFile('./output/other_pages.pdf');

  const pdfDoc = await PDFDocument.create();

  const [firstPage, ...otherPages] = await pdfDoc.copyPages(
    firstPagePdfBytes,
    otherPagesPdfBytes
  );

 pdfDoc.addPage(firstPage);

  for (const page of otherPages) {
    pdfDoc.addPage(page);
  }

  const mergedPdfBytes = await pdfDoc.save();

  // Save combined PDF
  writeFile('./output/merged.pdf', mergedPdfBytes, {}, (err) => {
    if (err) {
      return console.error('Error saving merged PDF');
    }
    console.log('Merged PDF saved successfully!');
  });
})();

How to do the same with your library? Since you have use id for header and footer, I don't have any idea how to do that conditionally

PejmanNik commented 1 year ago

Hi, you should be able to do the same within this lib, only you need to inject the header (manipulate the dom) before making the pdf file through the browser to the current location in the file (under the correct ID)

await browserPage.evaluate(() => {
    let dom = document.querySelector('#header');
    dom.innerHTML = "change to something"
 });