Phantomjs node set header,footer - node.js

How can I set page header and footer using phantomjs with node, basically I'm generating pdf from html and I'm willing to add my header and footer from node, I have tries with following but pdf is not showing any data, and I'm reading empty page and willing to add header and footer, here is my Code:
// Load ejs template
fs.readFile(__dirname + '/../pdf' + pdfpath, 'utf8', function (err, data) {
// Render the page to variable.
var html = ejs.render(data, pdfJSON);
// Set this html as the content for the pdf file.
page.set('content', html);
page.set('generatePDF', function (pageNum, numPages) {
if (pageNum == 1) {
return "";
}
return "<h1>Header <span style='float:right'>" + pageNum + " / " + numPages + "</span></h1>";
});
page.set('paperSize', {
width: 1200,
height: 1500,
header: {
height: "1cm",
contents: phantom.generatePDF
}
});
console.log(phantom.generatePDF);//return undifned
page.set('paperSize', {
width: 1200,
height: 1500
});
// Generate the pdf.
var fileName = __dirname + '/pdfdata/' + f.formType + f.formId + '.pdf';
page.render(fileName, cb);
});
How I can resolve this?

Take a look to these example:
https://github.com/ariya/phantomjs/blob/master/examples/printheaderfooter.js
Edit: Sorry, didn't noticed you asked for Node, you can find some solutions and answers here also:
Footer's contents don't seem to work

Related

NodeJS + Express + PDFKit + node-qrcode: Not able to add QR code to PDF

I am trying to implement a QR code in a PDF document using PDFkit (https://github.com/foliojs/pdfkit) and node-qrcode (https://github.com/soldair/node-qrcode).
Implementing PDF document:
const doc = new PDFDocument({
margin: 0,
size: 'LETTER'
})
doc.pipe(fs.createWriteStream('/files/result.pdf'))
doc.pipe(res)
Creating QR code and adding it to the PDF:
var opts = {
errorCorrectionLevel: 'H',
type: 'image/png',
quality: 0.9,
margin: 1,
color: {
dark:"#000000",
light:"#FFFFFF"
}
}
QRCode.toDataURL('http://link.to.website', function (err, url) {
if (err) throw err
doc.image(url, 50, 45, { width: 50 })
console.log(url)
})
Close the PDF:
doc.end()
Console output of the url from QRCode is correctly formatted and no error messages from PDFKit:
data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAIQAAACECAYAAABRRIOnAAAAAklEQVR4AewaftIAAAOQSURBVO3BQY5jBxYDweSD7n/lHC+84OoDglTltocR8S/M/O2YKcdMOWbKMVOOmXLMlGOmHDPlmCnHTDlmyjFTjplyzJRjprz4UBJ+k8qTJHxC5R1JaCotCb9J5RPHTDlmyjFTXnyZyjcl4ZtUWhJaEppKS8InVL4pCd90zJRjphwz5cUPS8I7VN6RhG9S+U1JeIfKTzpmyjFTjpny4j9G5R0qLQnvUPkvOWbKMVOOmfLiPy4JTaUloam0JDSVloSm8m92zJRjphwz5cUPU/mTqbQkNJWWhG9S+ZMcM+WYKcdMefFlSfg3SUJTaUloKi0J70jCn+yYKcdMOWbKiw+p/EmS8CdR+Tc5ZsoxU46ZEv/CB5LQVFoSvknlSRKayjuS8AmVloRvUvlJx0w5ZsoxU158SKUloak8ScITlSdJaCotCU3lHSpPkvBEpSWhqbwjCU3lm46ZcsyUY6a8+GFJaCpPVFoSmsqTJLwjCU3lSRKaSktCU3lHEprKkyQ0lU8cM+WYKcdMefGhJDxRaUloKi0JTaUl4R0qLQnvSEJTaUloKk9UWhKayhOVloRvOmbKMVOOmfLihyWhqTxRaUloKt+k0pLwDpWWhCcq70jCbzpmyjFTjpny4h+WhCcqT5LwRKWptCQ0lZaEd6g8SUJTaUloKi0JTeWbjplyzJRjprz4MpWWhCcqT5LwiSQ0labyjiQ8UXmi8k1JaCqfOGbKMVOOmfLih6k8ScITlZaEpvIkCU+S0FSaypMktCQ0lZaET6i0JHzTMVOOmXLMlBf/MJWWhJaEptKS8E1JeKLyjiS8Q6Uloak0lW86ZsoxU46Z8uJDKt+k8ptU3pGEJyrvSEJLwj/pmCnHTDlmyosPJeE3qTSVloQnSXii0pLQVFoSniShqXwiCU9UPnHMlGOmHDPlxZepfFMSniThiUpLQlP5SSqfUPlNx0w5ZsoxU178sCS8Q+UTKt+k0pLwJAnflIR3qHzimCnHTDlmyov/MyotCU9Unqg8SUJTaUloKi0Jv+mYKcdMOWbKi/+YJDSVJyotCS0JTeUdKi0JTeUdKi0J33TMlGOmHDPlxQ9T+UkqT5LQVFoSnqg8ScITlSdJeKLym46ZcsyUY6a8+LIk/KYkNJVPqLQkNJWm8pOS8JuOmXLMlGOmxL8w87djphwz5Zgpx0w5ZsoxU46ZcsyUY6YcM+WYKcdMOWbKMVOOmfI/dLqWFdMR+T4AAAAASUVORK5CYII=
The problem is that no image is displayed in the produced PDF.
If I use any other functions (than doc.image), e.g. doc.text(), doc.circle() all elements works fine and added to the PDF.
Any idea how to solve this?
toDataURL() is a asynchronous method.
I didn't wait for it to complete.
Closed the PDF document after it completed, and that worked.

Text size changes when using html-pdf local vs online

I'm actually using node js and html-pdf lib to generate a pdf on the server which is return as a blob to the client. When I did it on my local machine everything is fine but when I upload it to the server and test it out. The text size increases when in production.
I've created a function that takes an object as a parameter:
async function generatePDF(object) {
let htmlContent = `
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<style>
body,
html {
font-family: arial, sans-serif;
color: rgb(46, 46, 46);
}
</style>
</head>
<body>
<br />
Date: ${object.todayDate}
<div style="margin-top: 60px">
<h3 style="border-top: 1px solid black">Dr. ${object.name} ${object.firstname}</h3>
</div>
</html>
`;
Down below is the code to generate PDF from the HTML file created:
let sideMargin = "1.5cm";
var options = {
format: "A5",
border: {
top: "1.5cm", // default is 0, units: mm, cm, in, px
right: sideMargin,
bottom: "3.0cm",
left: sideMargin,
},
};
console.log(options);
var path = require("path");
var appDir = path.dirname(require.main.filename);
let date = Date.now();
let newPDF = `${appDir}/files/${date}new.pdf`;
let newHTML = `${appDir}/files/${date}new.html`;
htmlData["fileName"] = newHTML;
console.log(`Generating new PDF '${newPDF}`);
await generatePDF(htmlData);
var html = fs.readFileSync(`${newHTML}`, "utf8");
pdf.create(html, options).toFile(`${newPDF}`, function (err, res) {
if (err) return console.log(err);
console.log(res);
r.sendFile(`${newPDF}`, (error) => {
if (!error) {
fs.unlinkSync(`${newPDF}`);
fs.unlinkSync(`${newHTML}`);
}
});
});
The problem is that locally on my machine everything is fine, but online the text size of the PDF is way bigger, and instead of returning one page it's returning back two pages (of course the content I've set here in the HTML is not the result I want, it is just an example).
Hey i've found what was the problem,
there is no solution to this problem yet. The work around is to add
html {
zoom: 0.55;
}
to the CSS file/code
There's actually an open issue for this.

Add hash of most recent git commit to footer of pdf via markdown-pdf

I am using markdown-pdf via gulp to convert .md files to .pdf. I want to get the sha of the latest git commit and add it to the footer. I can get the hash like so in my gulpfile.js (found the answer):
revision = require('child_process')
.execSync('git rev-parse HEAD')
.toString().trim();
But how can I get that into my footer?
Below is my code for markdown-pdf that I am using in my gulpfile.js:
function docsToPdf() {
return src(["Views/Documentation/Files/*.md", "!Views/Documentation/Files/_README.md"])
.pipe(markdownPdf({
preProcessMd: preProcessMd,
remarkable: {
html: true
},
paperBorder: "1cm",
runningsPath: "Content/Pdf/assets/js/runnings.js",
cssPath: "Content/Pdf/assets/css/pdf.min.css"
}))
.pipe(dest("Content/Pdf"))
}
And my runnings.js file:
module.exports = {
header: {
height: '2cm',
contents: function (pageNum) {
if (pageNum == 1) {
return '<header class="pdf-header" style="padding-bottom: 20px;"><h2 style="text-align:center;margin:0;">Documentation</h2></header>'
}
return ''
}
},
footer: {
height: '1.5cm',
contents: function (pageNum, numPages) {
return '<footer class="pdf-footer" style="padding-top:20px;"><p style="float:left;width:33.33%;margin:0;font-size:10px;">' + new Date().toDateString() + '</p><p style="float:left;width:33.33%;margin:0;font-size:10px;text-align:center;">© 2020</p><p style="float:right;width:33.33%;margin:0;font-size:10px;text-align:right;">Page ' + pageNum + ' of ' + numPages + '</p></footer>'
}
}
}
And my preProccessMd:
function preProcessMd() {
var splitter = split()
var docsUrl = "https://example.org/docs/";
var urlOne = /\[\[((?:(?!\[\[).)*?)\|(.*?)]]/g;
var urlImg = /(\()(images)/g;
var replacer = through(function (data, path) {
this.queue(
data
.replace(urlOne, (_, x, y) => `[${x}](${docsUrl}${y.replace(/(?!^)[A-Z]/g, '-$&').toLowerCase()})`)
.replace(urlImg, "$1$2".replace("$2", "content/images/docs"))
+ "\n"
)
})
splitter.pipe(replacer)
return duplexer(splitter, replacer)
}
The best way to do this would be to use the preProcessMd method to inject the SHA into the footer. You do seem to have the preprocessor defined in preProcessMd: preProcessMd,. Is that actually doing anything? If so, what is the definition?
EDIT, after update from OP: Quick and dirty solution would be to use an empty span where you want the SHA to go. Then look for that span and replace with the SHA in your preProcessMd. For e.g., <span class="git-hash"></span>. Then replace <span class="git-hash"> with <span>YOUR-SHA.
You might need to update your gulp task like so:
function docsToPdf() {
revision = require('child_process')
.execSync('git rev-parse HEAD')
.toString().trim();
return src(["Views/Documentation/Files/*.md", "!Views/Documentation/Files/_README.md"])
.pipe(markdownPdf({
preProcessMd: preProcessMd.bind(this, revision),
remarkable: {
html: true
},
paperBorder: "1cm",
runningsPath: "Content/Pdf/assets/js/runnings.js",
cssPath: "Content/Pdf/assets/css/pdf.min.css"
}))
.pipe(dest("Content/Pdf"))
}
And your function preProcessMd() { to function preProcessMd(revision) {
NOTE: I'm unsure if the preProcessMd.bind(this, ... is going to be problematic or not.

nodeJS how to use router to add icon tag into pug file?

Hello I think it's easier to show partial lines of my code.
What I'm trying to do is when I input a zipcode, the right icon will show.
I'm using https://erikflowers.github.io/weather-icons/ this git.
for example: if NY weather condition says clear
weather condition in weather.pug should be like i.wi.wi-night-sleet
is it possible to add class name in icon tag from topic.js? or
can I use equal statement in pug flie like - if text=='clear' i.wi.wi-night-sleet
topic.js
router.post('/weather', function(req,res){
let url = `http://api.openweathermap.org/data/2.5/weather?zip=${req.body.zipcode}&units=imperial&appid=${apiKey}`
request(url, function (err, response, body) {
if(err){
res.status(500).send('Internal Server Error');
console.log('error: ' ,err);
} else {
if(req.body.zipcode.length != 5) {
res.render('topic/weather', {text: "Zipcode does not exist"})
} else {
let weather = JSON.parse(body)
let temp = weather.main.temp
let location = weather.name;
let day_weather = weather.weather[0].main;
let message = `It's ${weather.main.temp} degrees in ${weather.name}!`;
//below this I want to call icon tag that has a class name
res.render('topic/weather', {text: location + " : " + day_weather, weatherCondition: `i.wi.wi-night-sleet`});
}
}
});
})
weather.pug
extends ./homepage
block navigate
div.container-fluid
div.row.row-centered
p= text
//- space 넣을떄
= " "
if text
= date
div.col-lg-6.col-centered
form.form-group(action='/weather', method='post')
p
input(type='text', class="form-control", id="zipcode",name='zipcode', placeholder='zipcode')
p
button(type='submit', class="btn btn-primary btn-lg" style='margin-right: 10px;') Login
In your route just pass the identifying part of the icon you need:
res.render('topic/weather', {text: location + " : " + day_weather, weatherCondition: "night-sleet"});
Then here's what your pug template needs to look like:
i.wi(class= 'wi-' + weatherCondition)
or
i(class= 'wi wi-' + weatherCondition)
Either of those lines of pug will produce the same html:
<i class="wi wi-night-sleet"></i>

Phantomjs:How to remove header footer only for the first page?

I'm using phantomjs to render pdf with header and footer. Adding header and footer is implemented in all pages. Is there any way to remove header/footer from 1st page alone?
header: {
height: "1cm",
contents: phantom.callback(function(pageNum, numPages) {
return "<h1>Header <span style='float:right'>" + pageNum + " / " + numPages + "</span></h1>";
})}, footer: {
height: "1cm",
contents: phantom.callback(function(pageNum, numPages) {
return "<h1>Footer <span style='float:right'>" + pageNum + " / " + numPages + "</span></h1>";
})}
While not perfect, I return and empty string instead of actual html content when pageNum is equal to 1 (or to numPages in my case). The height is still occupied but at least its empty.

Resources