Giter VIP home page Giter VIP logo

node-html-pdf's Introduction

node-html-pdf

HTML to PDF converter that uses phantomjs

image
Example Business Card
-> and its Source file

Example Receipt

Changelog

Have a look at the releases page: https://github.com/marcbachmann/node-html-pdf/releases

Installation

Install the html-pdf utility via npm:

$ npm install -g html-pdf

Command-line example

$ html-pdf test/businesscard.html businesscard.pdf

Code example

var fs = require('fs');
var pdf = require('html-pdf');
var html = fs.readFileSync('./test/businesscard.html', 'utf8');
var options = { format: 'Letter' };

pdf.create(html, options).toFile('./businesscard.pdf', function(err, res) {
  if (err) return console.log(err);
  console.log(res); // { filename: '/app/businesscard.pdf' }
});

API

var pdf = require('html-pdf');
pdf.create(html).toFile([filepath, ]function(err, res){
  console.log(res.filename);
});

pdf.create(html).toStream(function(err, stream){
  stream.pipe(fs.createWriteStream('./foo.pdf'));
});

pdf.create(html).toBuffer(function(err, buffer){
  console.log('This is a buffer:', Buffer.isBuffer(buffer));
});


// for backwards compatibility
// alias to pdf.create(html[, options]).toBuffer(callback)
pdf.create(html [, options], function(err, buffer){});

Footers and Headers

html-pdf can read the header or footer either out of the footer and header config object or out of the html source. You can either set a default header & footer or overwrite that by appending a page number (1 based index) to the id="pageHeader" attribute of a html tag.

You can use any combination of those tags. The library tries to find any element, that contains the pageHeader or pageFooter id prefix.

<div id="pageHeader">Default header</div>
<div id="pageHeader-first">Header on first page</div>
<div id="pageHeader-2">Header on second page</div>
<div id="pageHeader-3">Header on third page</div>
<div id="pageHeader-last">Header on last page</div>
...
<div id="pageFooter">Default footer</div>
<div id="pageFooter-first">Footer on first page</div>
<div id="pageFooter-2">Footer on second page</div>
<div id="pageFooter-last">Footer on last page</div>

Options

config = {

  // Export options
  "directory": "/tmp",       // The directory the file gets written into if not using .toFile(filename, callback). default: '/tmp'

  // Papersize Options: http://phantomjs.org/api/webpage/property/paper-size.html
  "height": "10.5in",        // allowed units: mm, cm, in, px
  "width": "8in",            // allowed units: mm, cm, in, px
  - or -
  "format": "Letter",        // allowed units: A3, A4, A5, Legal, Letter, Tabloid
  "orientation": "portrait", // portrait or landscape

  // Page options
  "border": "0",             // default is 0, units: mm, cm, in, px
  - or -
  "border": {
    "top": "2in",            // default is 0, units: mm, cm, in, px
    "right": "1in",
    "bottom": "2in",
    "left": "1.5in"
  },

  paginationOffset: 1,       // Override the initial pagination number
  "header": {
    "height": "45mm",
    "contents": '<div style="text-align: center;">Author: Marc Bachmann</div>'
  },
  "footer": {
    "height": "28mm",
    "contents": {
      first: 'Cover page',
      2: 'Second page', // Any page number is working. 1-based index
      default: '<span style="color: #444;">{{page}}</span>/<span>{{pages}}</span>', // fallback value
      last: 'Last Page'
    }
  },


  // Rendering options
  "base": "file:///home/www/your-asset-path/", // Base path that's used to load files (images, css, js) when they aren't referenced using a host

  // Zooming option, can be used to scale images if `options.type` is not pdf
  "zoomFactor": "1", // default is 1

  // File options
  "type": "pdf",           // allowed file types: png, jpeg, pdf
  "quality": "75",         // only used for types png & jpeg

  // Script options
  "phantomPath": "./node_modules/phantomjs/bin/phantomjs", // PhantomJS binary which should get downloaded automatically
  "phantomArgs": [], // array of strings used as phantomjs args e.g. ["--ignore-ssl-errors=yes"]
  "localUrlAccess": false, // Prevent local file:// access by passing '--local-url-access=false' to phantomjs
                           // For security reasons you should keep the default value if you render arbritary html/js.
  "script": '/url',        // Absolute path to a custom phantomjs script, use the file in lib/scripts as example
  "timeout": 30000,        // Timeout that will cancel phantomjs, in milliseconds

  // Time we should wait after window load
  // accepted values are 'manual', some delay in milliseconds or undefined to wait for a render event
  "renderDelay": 1000,

  // HTTP Headers that are used for requests
  "httpHeaders": {
    // e.g.
    "Authorization": "Bearer ACEFAD8C-4B4D-4042-AB30-6C735F5BAC8B"
  },

  // To run Node application as Windows service
  "childProcessOptions": {
    "detached": true
  }

  // HTTP Cookies that are used for requests
  "httpCookies": [
    // e.g.
    {
      "name": "Valid-Cookie-Name", // required
      "value": "Valid-Cookie-Value", // required
      "domain": "localhost",
      "path": "/foo", // required
      "httponly": true,
      "secure": false,
      "expires": (new Date()).getTime() + (1000 * 60 * 60) // e.g. expires in 1 hour
    }
  ]

}

The full options object gets converted to JSON and will get passed to the phantomjs script as third argument.
There are more options concerning the paperSize, header & footer options inside the phantomjs script.

node-html-pdf's People

Contributors

alexbor avatar atinux avatar chipta avatar chris-kobrzak avatar chriskinsman avatar denysvitali avatar fakelag avatar ggirou avatar ivantodorovich avatar jason-cooke avatar jdeniau avatar manishbhatt94 avatar marcbachmann avatar mdelorimier avatar micahbule avatar seyfert avatar sorgel avatar tymekg avatar westy92 avatar zmedgyes avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

node-html-pdf's Issues

Html page cut off

When I convert my html page to pdf, the page doesn't fit the pdf width, and the right side get cut off.
The simple html is just using width="100%"

Global Executable

It would be nice to have a script that allows to run it as command:

$ html-pdf input.html output.pdf

...or so.

border

if i use border on my body , i get seperate borders around my #pageHeader, # pageContent en #pageFooter.

how do i set border-color in options ?

Images in header and footer getting removed

I am trying to add header and footer containing images/logo, but when the pdf is getting generated, it is removing the images from the header and footer.
The image src is base 64 encoded string and shows up when I put that in the main content.
Only it is getting removed from header and footer.

Thanks.

License

Hi,
can you please add a license agreement for your project?

Cheers,
Andreas

Flexbox layouts don't work

I am using Stylus to generate the CSS for my web page. When I enable flexbox layout (flexbox=true), nothing is rendered by node-html-pdf, but Chrome displays the page fine. When I disable flexbox layout, node-html-pdf and Chrome render the same output.

Chinese characters shows up as boxes in the generated pdf

Hi,

I am using this module to transform html to pdf on the fly in my website. What i observed is whenever there are Chinese characters in my html, it transforms to boxes in pdf. Is this you are aware of?

Here is the snippet

var options = {format: 'Letter'};
options.border = {
  "top": "30px",
  "right": "30px",
  "bottom": "30px",
  "left": "30px"
};

pdf.create(html, options).toStream(function (err, stream) {
          //TODO:Handle err
          res.setHeader('Content-Type', 'application/pdf');
          res.setHeader('Content-disposition', 'attachment; filename="'+ 'Document - '+result.docId + '.pdf"');
          stream.pipe(res);
});

'html-pdf: PDF generation timeout. Phantom.js script did not exit.' on Debian Wheezy

I have this issue on Debian Wheezy when running this code:

pdf.create(html, {
    width: '297mm',
    height: '400mm',
    directory: '/tmp/ramdisk',
    timeout: '60000'
    }, function(err, buffer) {});

After taking some time to check, and play around with html-pdf, here is what I did:

  • I change the timeout to 10 minutes on my machine, still the same issue.
  • I change the destination repository to be /tmp/ramdisk, as I had some issues before (in Python) with some IO work taking a really long time. I thought it might be related so I used some ramdisk instead, same issue.
  • I tried to run the unit tests, only the first 5 are passing. It stucks on 'task watch..'
    I don't really know what to do now to make any progress.

Table headers get copied

Reproduction

  1. Create a PDF from HTML containing a table that overflows onto the next page

Current behaviour

The table headers gets rendered twice, overlapping the table body.

Expected behaviour

The header only gets rendered once.

Files and screenshots

Here you can find the actual PDF, but the following screenshot shows the problem as well:

screen shot 2015-06-07 at 23 53 25

Links not working after generating to PDF

I am using Foxit Reader to open the PDF files. I opened the PDF file that was generated by Prince and the links work well. However, but the links in PDF generated by node-html-pdf do not.

Crashes on mutli-node.js system

Running the following on a single Node.js server is fine.

console.log('create PDF');
pdf.create(html).toBuffer(function(err, buffer){
//console.log('This is a buffer:', Buffer.isBuffer(buffer));
console.log('create PDF async call returned');
try{
posterBuffer = buffer;
callback();
}
catch (err){
callback( err );
}
});

But if you have two servers behind an HAPROXY load balancer both servers crash with (no state):

* START ERROR***
Un-Caught exception (reported from app.js):
{ [Error: write EPIPE] code: 'EPIPE', errno: 'EPIPE', syscall: 'write' }
Error: write EPIPE
at exports._errnoException (util.js:746:11)
at WriteWrap.afterWrite (net.js:775:14)
****************** END ERROR ********************

I read a post about a double callback failure with phantom but now I cannot find it again.

Server OS Ubuntu 14.0.4
Node 12.5

Bootstrap columns problem

Hi, I am trying to generate my PDF layout using bootstrap columns classes, but it doesn't work. Each row takes a full line. I was simply wondering if anyone ran into this before and how they solved the issue.

Here is my code:
image

image

Thanks.

thead and tbody get mixed starting from second page

I'm creating a pdf from a html with thead and tbody tags, I have already removed all style I had and I'm still with the same problem.

Starting from second page the tbody overwrite thead, like on image bellow:

screen shot 2015-07-17 at 11 24 02

It is very strange because it works on the first page (image below) and I don't have any style on this page.

screen shot 2015-07-17 at 11 26 10

It seems to happened too with the guy who opened this issue: #36. But he didn't want to have table headers on all pages, I want to.

Do you ever experienced this problem? Is there a way to solve it?

Failed to convert for big file.

I tried to convert html to pdf with this module, and html file size is over 3MB.
But it failed to convert. Converted pdf file size is variable for each case, and it's about 70~90MB.
What's a reason for this? How can I solve this issue?

External CSS file in header and footer

I am trying to use en external CSS file in my header and my footer, but it doesn't seems to works. Even bootstrap style that works in the body doesn't work in footer and header. However, the inline CSS works, but I would prefer to have cleaner code and to split the CSS from the HTML.

Thanks.

CSS overflow:hidden not supported?

Hello,

is there any secret in using overflow:hidden or is it just not supported?
When positioning two divs absolute in a relative container and using overflow:hidden, the image beneath the other one is shown out of bounds.

Is it my fault or does your module don't support overflow:hidden property?

Greetings

When executing code through this error ?

My code 👍

var fs = require('fs');
    var pdf = require('html-pdf');
    var html = fs.readFileSync('./test/businesscard.html', 'utf8')
    var options = { filename: './businesscard.pdf', format: 'Letter', width: '210mm', height: '297mm', border: '10mm', timeout: 30000 };
    pdf.create(html, options, function(err, buffer) {
      if (err) return console.log(err);
      console.log("Converted successfully. Output in " + outputPath);
    });
[Error: html-pdf: PDF generation timeout. Phantom.js script did not exit.]

Cannot execute binary file

Using AWS Lambda (works locally on OSX)

[Error: /var/task/node_modules/html-pdf/node_modules/phantomjs/lib/phantom/bin/phantomjs: /var/task/node_modules/html-pdf/node_modules/phantomjs/lib/phantom/bin/phantomjs: cannot execute binary file

One thing to note is the npm install is done on OSX before zipping up and uploading to Lambda (amazon linux). Is that what cause this issue?

links not working

simply

<a href="http://google.com">This is a link</a>

doesn't seem to work. The link is text is blue, but the cursor doesn't change when hovered, and it's not possible to click it. What could be the problem?

Font-face not working properly

Hi, I am trying to used personalized fonts with the @font-face CSS tag. When I use it in my HTML page inside a <style></style> in the header, I get some strange results.

The only custom font-family referenced in my HTML and CSS is Helvetica Neue Light Italic. However, for reasons I don't know, the document also has Helvetica Neue (named 'Regular') and Helvetica Neue Light (named 'Light') applied on other sections. Even more bizarre, if in the CSS I specify 'Regular' as font-family for the section weirdly having 'Regular' as font-family, it sets it to some basic HTML font.

Here are some screenshots.
Html (Part 1)
image

Html (Part 2)
image

CSS
image

Even if I use ejs to generate my HTML template, I verified and the links to the files are correct. Here are the 2 states I talked about:

-CSS only refers to 'Light' (as shown in the previous screenshot)
The title 'Basic Report' should not be in Helvetiva, but it is.
image

-CSS now sets .reportTitle to 'Regular'
image

Now this is the result:
image

You can see that the title clearly doesn't have Helvetica as font-family:
image

I also got some other weird side effets during my testing.

I found that post about PhantomJS.
ariya/phantomjs#12132

I reverted to version 1.9.1 but it didn't correct the problem.

Question: How html to pdf works?

Hi @marcbachmann,

I couldn't understand how you get the data from phantom and transform it in pdf binary. You create something like an image? Because the content is not selectable or links can't be clicked.

Can you explain if you have some time?

Thanks anyways =)

[Error: PDF creation timeout. PDF generation script did not end.]

On Windows 7 when trying to convert a .html to .pdf I get this message: [Error: PDF creation timeout. PDF generation script did not end.]. and no .pdf.

Script

var fs = require('fs');
var pdf = require('html-pdf');
var html = fs.readFileSync('LICENSE.md.html', 'utf8')
pdf.create(html, { width: '50mm', height: '90mm'}, function(err, buffer) {
  if (err) return console.log(err);
  fs.writeFile('LICENSE.md.html.pdf', buffer);
});

LICENSE.md.html

<p>Copyright (c) 2014 GitHub Inc.</p>

Note: Originally discovered the issue in the markdown-pdf module for Atom.

execute node filename programatically is a problem

var fs = require('fs');
var pdf = require('html-pdf'); 
var options = { filename: 'businesscard.pdf', format: 'Letter' }; 
  console.log("sadfasdf")
console.log(html="<body><div style='background-color: #000088' >dfasdf</div><table></table><td>fsdafsdf</table></body>")
pdf.create(html, options).toFile(function(err, res) {
    if (err) return console.log(err);
    console.log(res); // { filename: '/tmp/html-pdf-8ymPV.pdf' }
}); 

if my code has more content oh the same line new line automatically not getting inserted.

Use with browserify?

I wonder if this module can run in browser via browserify

I'm trying with your example code and replacing the line
var fs = require('fs');
with
var fs = require('browserify-fs');
or with
var fs = require('brfs');

but I always gey the same error
TypeError: fs.readFileSync is not a function

Error: write EPIPE

I'm using nunjucks to render a template into a string, i then try to convert that html to a pdf file however everytime i get this error:

Error: write EPIPE
    at errnoException (net.js:905:11)
    at Object.afterWrite (net.js:721:19)

Here is the code i use to create the pdf file:

                        nunjucks.render(path.join(__dirname, '../views/mail/receipt.html'), {
                                __: res.__,
                                query: req.query,
                                payment: payment
                            }, function(err, html) {
                                if (err) {
                                    next(err);
                                }
                                htmlPdf.create(html, {
                                    type: 'pdf'
                                }).toBuffer(function(erro, fileBuffer) {
                                    // Code never gets this far, errors out before it happens and the error object is still null.
                                    if (erro) {
                                        next(erro);
                                    }

                                    var transporter = nodemailer.createTransport({
                                        host: config.email.host,
                                        port: config.email.port,
                                        secure: config.email.secure
                                    });

                                    transporter.sendMail({
                                        from: config.email.from,
                                        to: payment.receipt_email,
                                        subject: res.__({
                                            phrase: 'Receipt_Email_Subject',
                                            locale: payment.lang
                                        }),
                                        attachments: [{
                                            filename: 'receipt.pdf',
                                            content: fileBuffer,
                                            contentType: 'application/pdf'
                                        }],
                                        text: 'test'
                                    }, function(error, info) {
                                        if (error) {
                                            next(error);
                                        }

                                        res.json(info);
                                    });
                                });
                            });

Here is the HTML string that is generated by nunjucks, not the most readable i know but figured i should post it like it is instead of trying to make it prettier

<!DOCTYPE html>\n<html lang="en">\n    <head>\n        <meta charset="utf-8">\n        <meta content="IE=edge" http-equiv="X-UA-Compatible">\n        <meta content="width=device-width, initial-scale=1" name="viewport">\n        <title>Snerpa WiFi Receipt</title>\n        <link href="//netdna.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css"\n            rel="stylesheet">\n    </head>\n    <body>\n        <div class="container">\n            <div class="row">\n                <div class="col-xs-6 col-sm-5 col-md-4 col-lg-3">\n                    <img src="http://wifi.snerpa.is/assets/images/wifi_logo.png" class="img-responsive" alt="WiFi Logo">\n                </div>\n            </div>\n            <div class="row">\n                <div class="col-xs-12">\n                    <div class="invoice-title">\n                        <h2>Invoice</h2>\n                        <h3 class="pull-right">Pöntun # 0575741</h3>\n                    </div>\n                    <hr>\n                        <div class="row">\n                            <div class="col-xs-6">\n                                <address>\n                                    <strong>Greiðslumáti:</strong><br>\n                                    VISA 999999******9999<br>\n                                    [email protected]\n                                </address>\n                            </div>\n                            <div class="col-xs-6 text-right">\n                                <address>\n                                    <strong>Dagsetning:</strong><br>\n                                    03.06.2015<br><br>\n                                </address>\n                            </div>\n                        </div>\n                    </div>\n                </div>\n                <div class="row">\n                    <div class="col-md-12">\n                        <div class="panel panel-default">\n                            <div class="panel-heading">\n                                <h3 class="panel-title"><strong>Samantekt</strong></h3>\n                            </div>\n                            <div class="panel-body">\n                                <div class="table-responsive">\n                                    <table class="table table-condensed">\n                                        <thead>\n                                            <tr>\n                                                <td><strong>Vara</strong></td>\n                                                <td class="text-center"><strong>Verð</strong></td>\n                                                <td class="text-center"><strong>Magn</strong></td>\n                                                <td class="text-right"><strong>Samtals</strong></td>\n                                            </tr>\n                                        </thead>\n                                        <tbody>\n                                            \n                                            <tr>\n                                                <td>Snerpa WiFi 1 Klst Aðgangur</td>\n                                                <td class="text-center">€1</td>\n                                                <td class="text-center">1</td>\n                                                <td class="text-right">€1</td>\n                                            </tr>\n                                            \n                                        </tbody>\n                                    </table>\n                                </div>\n                            </div>\n                        </div>\n                    </div>\n                </div>\n                <style>\n                    .invoice-title h2,\n                    .invoice-title h3 {\n                        display: inline-block;\n                    }\n\n                    .table> tbody> tr> .no-line {\n                        border-top: none;\n                    }\n\n                    .table> thead> tr> .no-line {\n                        border-bottom: none;\n                    }\n\n                    .table> tbody> tr> .thick-line {\n                        border-top: 2px solid;\n                    }\n                </style>\n            </body>\n        </html>\n

I've been stuck at this for hours and can't see that im doing anything wrong, any ideas?

Not rendering web fonts

Hi there,
I'm having no luck getting html-pdf to render webfonts that are included within the HTML itself. For example, the fonts are included within a <style> block on the HTML:-

@font-face {
                font-family: 'Raleway';
                src: url('/static/fonts/raleway/raleway-regular-webfont.eot');
                src: url('/static/fonts/raleway/raleway-regular-webfont.eot?#iefix') format('embedded-opentype'),
                     url('/static/fonts/raleway/raleway-regular-webfont.woff') format('woff'),
                     url('/static/fonts/raleway/raleway-regular-webfont.ttf') format('truetype'),
                     url('/static/fonts/raleway/raleway-regular-webfont.svg#ralewayregular') format('svg');
                font-weight: normal;
                font-style: normal;

            }
            body 
            {
                font-family: 'Raleway';
                font-size: 14px;
            }

The fonts are rendered when visiting the template HTML manually. But when html-pdf renders the page to PDF, it is output in Helvetica throughout. My assumption is this is a race condition, with html-pdf rendering before the fonts are called and rendered -- but I maybe simplifying it. Can you offer any steer as to how this can be achieved?

Many thanks

text color problem

when setting the color of text , it shows always black

example :

Text Goes Here

Base 64 image parse error

i try use a base64 image for background on my html and throws 'Parse error'

  .main{
    background-origin: content-box;
    background-image: url(data:image/png;base64,blablabalbalbaba);
    border: 26px solid #D5D5D5;
    box-sizing: border-box;
    display: inline-flex;
    height: 100%;
    width: 100%;
  }  

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.