Render HTML with variable data and convert to PDF - node.js

I have a html template page that I want to fill in data with via EJS, after which I want to pass this completed page to a PDF creator; the end result being a nice PDF version of my page filled with my data.
For the PDF creator, I'm using the NPM html-pdf do the conversion. Problem is, I don't know of any way I can render the page with my data, save it automatically, then pass the finished page to the PDF creator, since the PDF creator only accepts server paths to saved webpages.
Maybe I'm approaching this the wrong way, but below is what I currently have which admittedly isn't a lot. Any help in the right direction would be appreciated.
var renderPDF = function() {
var pdf = require('html-pdf');
// pulls html page
var html = fs.readFileSync('views/assets/html/render.ejs', 'utf8');
var options = {};
// creates views/test.pdf
pdf.create(html, options).toFile('views/test.pdf', function(err, res) {
if (err) return console.log(err);
console.log(res);
});
};
// this is how I usually render ejs files with data
response.render('assets/html/render.ejs', {myDataOject});
// start the conversion
renderPDF();

Here is the solution.
We read EJS's template file then compile it to PDF format.
index.js
var fs = require('fs');
var ejs = require('ejs');
var pdf = require('html-pdf')
var compiled = ejs.compile(fs.readFileSync(__dirname + '/template.html', 'utf8'));
var html = compiled({ title : 'EJS', text : 'Hello, World!' });
pdf.create(html).toFile('./result.pdf',() => {
console.log('pdf done')
})
template.html
<html>
<head>
<title><%= title %></title>
</head>
<body>
<p><%= text %></p>
</body>

Related

Is it possible to share some code between several pages in Node.js like with PHP without using pug or ejs?

I want to include a header, a menu and a footer in my web app for most of the pages but I don't want to write the same code in every pages. I know this is possible with PHP, but I'm using Node.js and I can't use jade/pug or EJS. How can I do that ?
To do this, you would create your files that contain your content like the following two file here:
header.js
module.exports = `<nav>
<ul>
<li>Item 1</li>
<li>Item 2</li>
</ul>
</nav>`
footer.js
module.exports = `<footer>
<!-- Your footer code -->
</footer>`
Next within your app, you would listen for a request and then just require the files, and concatenate the data to generate a new string header + body + footer, then you would write that out to the response. I am not sure how you will be getting your body, but here is an example:
main.js
const http = require('http');
const header = require('./header.js');
const footer = require('./footer.js');
const server = http.createServer((req, res) => {
// Get the body somehow
// We will just use a switch here and test `req.url`
let bodyFile = './home.js';
switch(req.url) {
case '/about': bodyFile = './about.js'; break;
case '/contact': bodyFile = './contact.js'; break;
}
const body = require(bodyFile);
res.write(header + body + footer);
res.end();
});
server.listen(8000);

Nodejs append backend data to html

I am using the html as content and sending the mail, but one more requirement is need to get the data from backend and need to append to the html.I am getting error of syntax at the path can anyone help me
client.query(query, function(err, result1) {
var renderTemplate = function('/index2.html', result1.rows) {
fs.readFile('/index2.html', 'utf8', function(err, file){
return ejs.render('/index2.html', result1.rows); }} });
UPDATE: I realize that ejs v1 may not be as popular, so this was edited to work with v2.
This example uses ejs, be sure to install ejs for this example to work.
I didn't write any error handling, be sure to write the error handling if this is for production.
Rendering a template with inserted data:
var fs = require('fs');
var ejs = require('ejs');
var renderTemplate = function(pathToHtmlTemplate, dataToBeInserted) {
// reads your template file to be used in the callback
fs.readFile(pathToHtmlTemplate, 'utf8', function(err, file) {
// returns a rendered html with data to driver code
return ejs.render(pathToHtmlTemplate, dataToBeInserted);
}
}
Your html template should use something like <%= data.name %> :
<ul>
<li><%=data.name%></li>
<li><%=data.email%></li>
</ul>
Further information about the library: https://github.com/mde/ejs
If your HTML file is prepared to have data appended to it then you can use fs.append like this:
fs.appendFile(pathToFile, dataToAppend, function(err) {
if (err) // Handle error
transporter.sendMail({
from : xxxx#gmail.com,
to : xxxx#gmail.com,
subject : 'Invitation',
html : pathToFile
})
})
But if you have closing tags that may cause issues...
You can use some library like nunjucks(https://mozilla.github.io/nunjucks/api.html#renderstring)
var res = nunjucks.render('foo.html', { username: 'James' });
Should give you the html you want.
I didn't try but it should work.

Retrieving HTML from CouchBase into Node.js / Express 4 leaves it unrendered

I'm having a small issue with rendering HTML, stored in CouchBase, fetched by Node.js
In CouchBase I have several small HTML-snippets. They contain text, tags such as <br /> and html entities such as <. They are of course stored as an escaped string in JSON.
So far, so good. However when I pull it out and display on the page, it is rendered "as-is", without being interpreted as HTML.
For example:
[ some content ...]
<p>Lorem is > ipsum<br />And another line</p>
[rest of content ...]
From the controller in Express 4:
var express = require('express');
var router = express.Router();
var couchbase = require('couchbase');
var cluster = new couchbase.Cluster('couchbase://myserver');
var bucket = cluster.openBucket('someBucket', 'somePassword');
var Entities = require('html-entities').XmlEntities;
entities = new Entities();
var utf8 = require('utf8');
/* GET home page. */
router.get('/', function(req, res) {
bucket.get('my:thingie:44', function(err, result) {
if(err) throw err
console.log(result);
var html = utf8.decode(entities.decode(result.value.thingie.html));
// var html = utf8.encode(result.value.thingie.html);
// var html = utf8.decode(result.value.thingie.html);
res.render('index', { title: 'PageTitle', content: html });
});
});
It is then passed to the template (using hogan.js) for rendering.
When looking into this I found that it might have something to do with the encoding of the <'s and <'s that prevent it from being parsed. You can see my converting attempts in the code, where none of the options gave the desired result, i.e. rendering the contents as HTML.
When using utf8.decode(), no difference.
Using utf8.encode(), no difference.
Using entities.decode() it convert < into < as predicted, but it's not rendered even if <div;&gt becomes <div>.
Any ideas?
I found the solution over here: Partials with Node.js + Express + Hogan.js
When putting HTML in a Hogan template, you have to use {{{var}}} instead of {{var}}.
And thus it renders beautifully, as intended :)
Wasn't encoding issues at all ;)

Is there a way to get the HTML of a JADE Template before sending it via response

What I usually do is:
res.render('myJadeTemplate');
but I want to add another transformation to the html before attaching it to the response.
How can I get the rendered HTML then modify it and send it over via res.send()
If you are using Express3. There is an additional (and optional) parameter to res.render() that is a callback that will give you the rendered HTML rather than sending it directly to the client.
res.render('myJadeTemplate', function (err, html) {
// html => rendered HTML from jade template
});
Ok I found a solution:
var jade = require('jade');
var fs = require('fs');
var jadetemplate = jade.compile(fs.readFileSync('code.jade', 'utf8'));
var html = jadetemplate({
params:"{Some parames}"
});
console.log(html);
Thanks for this thread
Node says Jade has no method "renderFile", why?

How to compile jade template file to get string?

I have a view logic in my jade template file. How can I pass model in to jade and get html for further sending by email ?
You can try the following:
var jade = require('jade'),
fs = require('fs');
fs.readFile('template.jade', 'utf8', function (err, data) {
if (err) throw err;
console.log(data);
var fn = jade.compile(data);
var html = fn({name:'Oleg'});
console.log(html);
});
Where template.jade is the path to your template. And it look like this:
!!!
html
head
title= 'Hello world'
body
p Hello #{name}!
So you pass your model as input of the fn() function, and the output of it will be the html.
<!DOCTYPE html><html><head><title>Hello world</title></head><body><p>Hello Oleg!</p></body></html>
Also you can catch the string from render callback (express example)
exports.test1 = function(req, res){
res.render('test1', { title: 'test1' }, function(err, body) {
console.log(body);
});
res.send('wooo');
};
test1.jade
div
= title
p hello world!
Opening the template with fs.readFile() is no longer necessary. The Jade API includes the compileFile() method that compiles directly from a file.
var jade = require("jade");
var locals = {name: "Linus"},
render = jade.compileFile('template.jade'),
html = render(locals);
The Jade API also includes the renderFile() method that directly returns an html string from a given file, making it even simpler.
var jade = require("jade");
var locals = {name: "Linus"},
html = jade.renderFile('template.jade', locals);
The answers all work for loading the jade template and compiling it to HTML using locals. However if you are sending HTML emails you need to be aware that most clients strip out all CSS classes. Use Juice (or something like it) to apply all of the CSS classes inline.

Resources