var fs = require('fs');
var mustache = require('mustache');
var locale = require('./locale.js');
var inlineCss = require('inline-css');
var path = require('path');
module.exports = {
/**
* Get template.
* @param {String} template - Template name
* @param {Object} countryCode - Language code
* @param {Object} params - Params
* @param {Object} cb - Callback
*/
get: function(template, params, cb) {
var templatePath = path.join(__dirname, 'template', `${template}`, `index.html`);
var classPath = path.join(__dirname, 'template', `${template}`, `${template}.js`);
var stylePath = path.join(__dirname, 'template', `${template}`, 'style.css');
fs.stat(templatePath, (error, stat) => {
if (error)
return cb(new Error('Template ' + template + ' not found'));
let TemplateClass = require(classPath);
let instance = new TemplateClass();
let getRenderedStyles = (error, body) => {
if (error)
return cb(error);
this.renderStyles(stylePath, body, (error, body) => {
if (error)
return cb(error);
// Check if has a subject param
params.subject = params.subject || instance.subject;
if (params.subject == undefined) {
// Try to find a subject from Html source
let title = body.match(new RegExp('
(.*?)', 'i'));
if (title)
params.subject = title[1];
}
this.renderImages(template, body, params.isPreview, (error, body) => {
if (error)
return cb(error);
cb(null, {body: body});
});
});
};
let getDataCb = () => {
this.render(templatePath, params, instance, (error, result) => getRenderedStyles(error, result));
};
instance.getData(params, (error, result) => {
if (error)
return cb(error);
locale.load(template, instance.countryCode, (error, result) => {
if (error)
return cb(error);
instance._ = result.locale;
instance.isPreview = params.isPreview;
getDataCb(null, result);
});
});
});
},
/**
* Render template
* @param {String} path - Template path
* @param {Object} data - Params
* @param {Object} cb - Callback
*/
render: function(path, params, data, cb) {
fs.readFile(path, 'utf8', (error, body) => {
// Find matching sub-templates
let regexp = new RegExp(/\{\{\$\.(.*?)\}\}/, 'ig');
let subTpl = body.match(regexp);
if (!subTpl) {
mustache.parse(body);
return cb(null, mustache.render(body, data));
}
let parentBody = body;
this.renderSub(parentBody, subTpl, data, regexp, (error, body) => {
if (error)
return cb(error);
mustache.parse(body);
cb(null, mustache.render(body, data));
});
});
},
renderSub: function(body, subTpl, params, regexp, cb) {
let index = 1;
subTpl.forEach(keyName => {
subTplName = keyName.replace(regexp, '$1');
this.get(subTplName, params, (error, result) => {
if (error)
return cb(error);
let subTplBody = result.body;
body = body.replace(keyName, subTplBody);
if (index === subTpl.length)
cb(null, body);
index++;
});
});
},
/**
* Render template style.
* @param {String} path - Stylesheet path
* @param {String} body - Rendered html
* @param {Object} cb - Callback
*/
renderStyles: function(stylePath, html, cb) {
// Common components
let comPath = path.join(__dirname, '../', 'static', 'css', 'common.css');
fs.readFile(comPath, 'utf8', (error, comCss) => {
fs.stat(stylePath, error => {
if (error)
return cb(new Error('Template stylesheet not found'));
fs.readFile(stylePath, 'utf8', (error, css) => {
let style = '';
let body = style + html;
let options = {url: ' '};
inlineCss(body, options)
.then(function(body) {
cb(null, body);
});
});
});
});
},
/**
* Render template images
* @param {String} template - Template name
* @param {String} body - template body
* @param {Object} cb - Callback
*/
renderImages: function(template, body, isPreview, cb) {
let tplImages = body.match(new RegExp('src="cid:(.*?)"', 'ig'));
if (!tplImages)
tplImages = {};
// Template default attachments
for (var i = 0; i < tplImages.length; i++) {
let src = tplImages[i].replace('src="cid:', '').replace('"', '').split('/');
let attachmentTpl = src[0];
let attachment = src[1];
if (isPreview) {
let imagePath = `/print/static/${attachmentTpl}/${attachment}`;
body = body.replace(tplImages[i], `src="${imagePath}"`);
} else {
let imagePath = path.join(__dirname, 'template', attachmentTpl, 'image', attachment);
body = body.replace(tplImages[i], `src="file:///${imagePath}"`);
}
}
cb(null, body);
},
/**
* Get template attachments
* @param {String} template - Template name
* @param {String} body - template body
* @param {Object} cb - Callback
*/
getAttachments: function(template, body, isPreview, cb) {
let attachments = [];
let tplAttachments = body.match(new RegExp('src="cid:(.*?)"', 'ig'));
if (!tplAttachments)
tplAttachments = {};
// Template default attachments
for (var i = 0; i < tplAttachments.length; i++) {
let src = tplAttachments[i].replace('src="cid:', '').replace('"', '').split('/');
let attachmentTpl = src[0];
let attachment = src[1];
if (isPreview) {
let attachmentPath = `/mailer/static/${attachmentTpl}/${attachment}`;
body = body.replace(tplAttachments[i], `src="${attachmentPath}"`);
} else {
let attachmentPath = path.join(__dirname, 'template', `${attachmentTpl}`, 'image', attachment);
let attachmentName = attachmentTpl + '/' + attachment;
attachments.push({filename: attachmentName, path: attachmentPath, cid: attachmentName});
}
}
if (isPreview)
return cb(null, {body: body, attachments: attachments});
// Template attachment files
let attachmentsPath = path.join(__dirname, 'template', `${template}`, 'attachment.json');
fs.stat(attachmentsPath, (error, stats) => {
if (error)
return cb(null, {body: body, attachments: attachments});
let attachObj = require(attachmentsPath);
for (var i = 0; i < attachObj.length; i++) {
let filename = attachObj[i];
let attachmentPath = path.join(__dirname, 'template', `${template}`, 'attachment', filename);
attachments.push({filename: filename, path: attachmentPath, cid: filename});
}
this.checkAttachments(attachments, error => {
if (error)
return cb(error);
cb(null, {body: body, attachments: attachments});
});
});
},
/**
* Check all template attachments
* @param {Object} attachments - Attachments object
* @param {Object} cb - Callback
*/
checkAttachments: function(attachments, cb) {
for (var i = 0; i < attachments.length; i++) {
var attachment = attachments[i];
fs.stat(attachment.path, error => {
if (error)
return cb(new Error(`Could not load attachment file ${attachment.path}`));
});
}
cb();
}
};