Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Scripts are not evalutated in header and footer HTML templates for PDFs. #2167

Open
chrisjpatty opened this issue Mar 8, 2018 · 27 comments
Open
Labels
chromium Issues with Puppeteer-Chromium confirmed feature upstream

Comments

@chrisjpatty
Copy link
Contributor

Steps to reproduce

  • Puppeteer version: 1.1.1
  • Platform / OS version: Windows 10, version 1709, build 16299.248
  • Node.js version: v7.9.0

What steps will reproduce the problem?

First, I setup a basic test page like this:

const browser = await puppeteer.launch({ignoreHTTPSErrors: true})
const page = await browser.newPage()
await page.setContent(`
<html>
  <head>
    <title>Test Page</title>
    <style>
      body{
        background: yellow;
        min-height: 6000px;
      }
    </style>
  </head>
  <body>
    I'm an HTML page.
  </body>
</html>
`)
const pdf = await page.pdf({
  format: 'Letter',
  printBackground: true,
  headerTemplate: headerTemplate,
  displayHeaderFooter: true,
  margin: {
    top: '1in',
    right: '0in',
    bottom: '1in',
    left: '0in'
  }
})
await browser.close()

The headerTemplate looks like this:

const headerTemplate = `
<div style="font-size: 10px; display: flex; flex-direction: row; justify-content: space-between; width: 100%" id='template'>
  <div class='pageNumber' id='num' style="font-size: 10px;">Page number</div>
  <div class='date' style="font-size: 10px;"></div>
  <div class='title' style="font-size: 10px;"></div>
  <div class='url' style="font-size: 10px;"></div>
  <div class='totalPages' style="font-size: 10px;"></div>
  <script>
    var pageNum = document.getElementById("num");
    pageNum.remove()
    var template = document.getElementById("template")
    template.style.background = 'red';
  </script>
</div>`

What is the expected result?
The docs don't mention whether or not script tags are supported in the header and footer templates. I would expect then that the code above would render a header with a red background and remove the page number node. (The code above was just for testing purposes).

What happens instead?
The script appears not to evaluate. Instead the resulting PDF has no background, and a page number div.

If evaluating scripts in these templates is not supported, might I suggest updating the PDF section of the docs to state as much. Thanks for all the hard work the Puppeteer team has put into this project!

@jmas
Copy link

jmas commented Mar 21, 2018

I also need this feature, because I do not see a normal way to make different headers for different pages. For example on first page (intro page) is one header and on the internal pages is different.
If not possible run scripts in header/footer templates I have another proposal that can be solved via CSS:

<div class="header" id="page1">Intro header</div>
<div class="header">Internal header</div>
#page1 {
  display: none;
}
#page1:target {
  display: block;
}
#page1:target + .header {
  display: none;
}

:target selector is valid when we have anchor #page1 in URL.

@cakebake
Copy link

Maybe it helps, or is an drive for your own thoughts: #1853 (comment)

@skymon4
Copy link

skymon4 commented Jun 1, 2018

I also met this problem,but I dont know how to slove this problem.my code doesn't seem to be a bit of a problem;
await page.pdf({ path:${path}/${title}.pdf, scale:0.7, margin: {top: 75, bottom: 75}, format: 'letter', headerTemplate: '<p style="font-size:40px;" class="title"></p>', // footerTemplate: '<div class="footer" style="font-size: 10px;color: #000; margin: 10px auto;"><span class="pageNumber"></span></div>', footerTemplate:'<div class="footer" style="height:75px;position: absolute;background- color:red;top:auto;left:0px;right:0px;bottom:0px;"><span class="title"></span></div>', displayHeaderFooter: true, });

@benmehlman
Copy link

benmehlman commented Aug 3, 2018

I am stuck on this too.. I am trying to replace wkhtmltopdf, which allows scripts in the header/footer. They also have [section] and [subsection] which render as the contents of the most recent <h1> and <h2>, respectively. Currently, chrome has no equivalent functionality.

If, when the header/footer was rendered, there was some information available via javascript that allowed locating elements relative to the boundaries of the page, to serve this same purpose, that would allow the same type of behavior, eg printing the name of a section that started on a previous page in the header or footer of the current page.

Thanks to all for your great work.

@raffaelmeier
Copy link

I would also appreciate some development concerning these issues. Javascripts in headers and footers or a header footer function was absolutely useful. Also have external css loaded in headers work would be a great reduction of pain ;-)

@skymon4
Copy link

skymon4 commented Sep 27, 2018 via email

@raffaelmeier
Copy link

Hi skymon4. please descibe your solution. What do you mean by "The reason is that I have been packaged by others." - i do not understand this sentence.

@cakebake
Copy link

@yale8848
Copy link

this is chromium source code print_header_footer_template_page.html

https://cs.chromium.org/chromium/src/components/printing/resources/print_header_footer_template_page.html

function setup(options) {
  const body = document.querySelector('body');
  const header = document.querySelector('#header');
  const footer = document.querySelector('#footer');

  body.style.width = `${options.width}px`;
  body.style.height = `${options.height}px`;
  header.style.height = `${options.topMargin}px`;
  footer.style.height = `${options.bottomMargin}px`;

  header.innerHTML = options['headerTemplate'] || `
    <div class='date text left'></div>
    <div class='title text center'></div>`;
  footer.innerHTML = options['footerTemplate'] || `
    <div class='url text left grow'></div>
    <div class='text right'>
      <span class='pageNumber'></span>/<span class='totalPages'></span>
    </div>`;

  options.date = new Date(options.date).toLocaleDateString();
  for (const cssClass of ['date', 'title', 'url', 'pageNumber', 'totalPages']) {
    for (const element of document.querySelectorAll(`.${cssClass}`))
      element.textContent = options[cssClass];
  }
}

headerTemplate and footerTemplate content was used innerHTML method to render , so it can't execute JavaScript, but we can use other method to execute javascript, we can use under code:

    <div style="font-size: 10px;">
      <div id="test">header test</div>
      <img src='http://www.chromium.org/_/rsrc/1438879449147/config/customLogo.gif?revision=3' onload='document.getElementById("test").style.color = "green";this.parentNode.removeChild(this);'/>
    </div>

the result is js modify test color to green.

header

@user9179380
Copy link

@yale8848 I've run your snipplet, but I've got a black 'header test' text and I cannot reproduce your result. I've tested on a Chrome 69.0 in headless mode, in Win10 environment, with Node.js v8.11.3.
Could you please detail your setup? OS? Chrome version? Etc?

I've also tested without the onload attribute, and the image has not loaded. If I set a base64 data img, then the image is displayed, but with the onload attribute, the JS does not run in this case neither. I'm not able to run JS at all in the templates.

My goal is to modify the counter in the pageNumber span, to count from a given number, instead of one.

Any ideas are welcome. Thank you for your answer.

@yale8848
Copy link

@user9179380 I test in url-to-pdf-api project docker container, https://github.com/yale8848/url-to-pdf-api-docker

os: Debian GNU/Linux 8 (jessie)
node:8.12.0
chrome:571375

I try to modify 'header test' color in js code is ok , but try to get 'pageNumber' value in js code , it get empty.
I will try to find other method in next time.

@user9179380
Copy link

user9179380 commented Oct 10, 2018

@yale8848 Thank you for you answer. I will check the linked docker container. Do you use any specific Chrome flag? The list of flags are available here:
https://peter.sh/experiments/chromium-command-line-switches/

How did you try to get access to pageNumber? By using innerHTML? Please try to run the following snipplet for me, maybe you can modify the pageNumber this way:

<img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" alt="tmpimg" 
onload="var x = document.getElementById('pn').innerHTML; var y = 10; document.getElementById('pn').innerHTML = parseInt(x) + y; this.parentNode.removeChild(this);"/>
<span id="pn" class="pageNumber"></span>

If it doesn't work, please also try an external image source. Theoretically, the code modify pageNumber by adding 10 to it. Does it work for you?

I've posted a question about the issue on StackOverflow:
https://stackoverflow.com/q/52729615

Thank you for your contribution.

@luxueyan
Copy link

I hate so many trick hacks!I need the headerrTemplate/ footerTemplate can support function setting.

@skymon4
Copy link

skymon4 commented Aug 22, 2019

yeah,as some reason,this way is some diffcult.but if we do use truth way, we can solve this question

@sjjhsjjh
Copy link

sjjhsjjh commented Oct 1, 2019

Something that might be quick to deliver is to allow this resource file to be replaced at run time:
https://cs.chromium.org/chromium/src/components/printing/resources/print_header_footer_template_page.html

Then I would be able to write my own custom setupHeaderFooterTemplate function. I could then do a bit more than replace the pageNumber text, such as adding a conditional class based on the page number.

@luckydrq
Copy link

I have similar needs but simpler. I want to have a "Back to top" link in footer which can navigate to page 1 when clicked. Tried <a href="#page=1">Back to top</a> or <a href="#top">Back to top</a> in footerTemplate option and didn't work.

PS: i place a <a name="top"></a> after the starting <body>.

@lesfauches
Copy link

@luckydrq did you find how to manage that ?

I have the exact same needs and even if links for table of contents works well, as soon as the link is in the footer, it's ignored.

@luckydrq
Copy link

@luckydrq did you find how to manage that ?

I have the exact same needs and even if links for table of contents works well, as soon as the link is in the footer, it's ignored.

Not yet, seems that links not supported in footer.

@richardwooding
Copy link

I have been trying to do the same (run code in header/footer) but haven't been successful. Ultimately I would like to have number page 1 from the second page. And remove headers from 1st page.

@buzzie-bee
Copy link

buzzie-bee commented Mar 8, 2022

@yale8848

I've been playing with running an onload script like you had in your comment and thought it might work as your example was producing numbered pages. However it seems this is achieved via the class name rather than the script execution.

Simply using the class="pageNumber" prints the page numbers for me.

<span class="pageNumber"></span>

I would very much like to be able to only show our footer on the last page of the pdf and haven't figured out a good way to make that happen yet unfortunately.

@yale8848
Copy link

@buzzie-bee
Yes, you are right, class="pageNumber" can show page number OK. I just try to find other more flexible way to modify header and footer, so i find onload script. It was just a trick :)

@liuyiliuyi
Copy link

liuyiliuyi commented Mar 31, 2022

@user9179380 I test in url-to-pdf-api project docker container, https://github.com/yale8848/url-to-pdf-api-docker

os: Debian GNU/Linux 8 (jessie) node:8.12.0 chrome:571375

I try to modify 'header test' color in js code is ok , but try to get 'pageNumber' value in js code , it get empty. I will try to find other method in next time.

@yale8848
Hi, I run your docker container, but it doesn't work. Can you give me some advice or help, please?

  1. code
<div style="font-size: 10px;">
  <div id="test">header test</div>
  <img src='data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7' onerror='document.getElementById("test").style.color = "green";this.parentNode.removeChild(this);'/>
</div>
  1. result
    20220331114410

Waiting for your reply, thank you.

@yale8848
Copy link

yale8848 commented Mar 31, 2022

@user9179380 I test in url-to-pdf-api project docker container, https://github.com/yale8848/url-to-pdf-api-docker
os: Debian GNU/Linux 8 (jessie) node:8.12.0 chrome:571375
I try to modify 'header test' color in js code is ok , but try to get 'pageNumber' value in js code , it get empty. I will try to find other method in next time.

@yale8848 Hi, I run your docker container, but it doesn't work. Can you give me some advice or help, please?

  1. code
<div style="font-size: 10px;">
  <div id="test">header test</div>
  <img src='data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7' onerror='document.getElementById("test").style.color = "green";this.parentNode.removeChild(this);'/>
</div>
  1. result
    20220331114410

Waiting for your reply, thank you.

try to change onerror= to onload= . @liuyiliuyi

@liuyiliuyi
Copy link

@yale8848 I tested onerror/onload, but it still doesn't work properly.

@stale
Copy link

stale bot commented Jun 23, 2022

We're marking this issue as unconfirmed because it has not had recent activity and we weren't able to confirm it yet. It will be closed if no further activity occurs within the next 30 days.

@stale stale bot added the unconfirmed label Jun 23, 2022
@PAStheLoD
Copy link

🤷

@stale stale bot removed the unconfirmed label Jun 23, 2022
@stale
Copy link

stale bot commented Aug 30, 2022

We're marking this issue as unconfirmed because it has not had recent activity and we weren't able to confirm it yet. It will be closed if no further activity occurs within the next 30 days.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
chromium Issues with Puppeteer-Chromium confirmed feature upstream
Projects
None yet
Development

No branches or pull requests