Socket
Book a DemoInstallSign in
Socket

grunt-email-builder

Package Overview
Dependencies
Maintainers
2
Versions
31
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

grunt-email-builder - npm Package Compare versions

Comparing version

to
2.0.10

2

package.json
{
"name": "grunt-email-builder",
"description": "Combine Html and Css into an email",
"version": "2.0.8",
"version": "2.0.10",
"homepage": "https://github.com/yargalot/Email-Builder",

@@ -6,0 +6,0 @@ "author": {

@@ -12,14 +12,13 @@ /* jshint -W030,-W117 */

// Required modules
var path = require('path'),
os = require('os');
cheerio = require('cheerio'),
mailer = require('nodemailer'),
encode = require('./entityEncode'),
Litmus = require('./litmus'),
Promise = require('bluebird'),
juice = Promise.promisifyAll(require('juice2'));
var path = require('path');
var os = require('os');
var cheerio = require('cheerio');
var mailer = require('nodemailer');
var encode = require('./entityEncode');
var Litmus = require('./litmus');
var Promise = require('bluebird');
var juice = Promise.promisifyAll(require('juice2'));
function EmailBuilder(task) {
this.task = task;

@@ -33,6 +32,40 @@ this.options = task.options(EmailBuilder.Defaults);

EmailBuilder.taskDescription = 'Compile Files';
EmailBuilder.Defaults = {};
EmailBuilder.Defaults = {
removeStyleTags: true,
removeLinkTags: true
};
/**
* Remove all style and link tags by default
*
* @param {String} html
*
* @returns {String} html that has style and link tags removed
*/
EmailBuilder.prototype.removeStyles = function(html) {
var $ = cheerio.load(html);
var linkTags = $('link');
var styleTags = $('style');
var stylesExist = (styleTags.length || linkTags.length);
// Remove links and style tags after they've been inlined
if(stylesExist){
if(this.options.removeStyleTags) {
html = html.replace(/<\bstyle\b[\s\S]+<\/\bstyle\b>/g, '');
}
if(this.options.removeLinkTags){
html = html.replace(/<link.*stylesheet[^>]+>/g,'');
}
}
return html;
};
/**
* Pull all styles from link/style tags within conditional comments and put them

@@ -46,31 +79,24 @@ * in a style tag

EmailBuilder.prototype.handleConditionals = function(html){
EmailBuilder.prototype.addStylesToConditionals = function(html){
var reConditional = /(<!--\[\s*if[^>]+>(?:<![^>]+>)?)([\s\S]+?)(<![^>]+>)/gi;
var _self = this;
var $, linkTags, styleTags, stylesExist, styles;
html = html.replace(reConditional, function(match, p1, p2, p3, offset, string){
var $ = cheerio.load(p2),
linkTags = $('link'),
styleTags = $('style'),
stylesExist = (styleTags.length || linkTags.length),
styles = stylesExist ? '\n<style type="text/css">\n' : '';
$ = cheerio.load(p2);
linkTags = $('link');
styleTags = $('style');
stylesExist = (styleTags.length || linkTags.length);
styles = stylesExist ? '\n<style type="text/css">\n' : '';
styleTags.each(function(){
var $this = $(this);
styles += $this.text() + '\n';
$this.remove();
});
styles += _self.getStyleTagContent(p2).conditionalStyles;
styles += _self.getLinkTagContent(p2).conditionalStyles;
p2 = _self.removeStyles(p2);
linkTags.each(function(){
var $this = $(this);
var href = $this.attr('href');
styles += _self.grunt.file.read(href) + '\n';
$this.remove();
});
styles += stylesExist ? '\n</style>\n' : '';
return p1 + styles + $.html() + p3;
return p1 + styles + p2 + p3;

@@ -84,49 +110,142 @@ });

/**
* Prepare html to be inlined by extracting and removing any data-ignore styles
* Get styles from style tag
*
* @param {String} file - src file to read
* @param {String} html
*
* @returns {Object} ignoreStyles - styles from style tags/links that have data-ignore attribute
* @returns {Object} html - the new html with any style tags/links
* @returns {String} an object whose properties contain styles from data-ignore being set
* or styles within conditional comments
*/
EmailBuilder.prototype.prepareHtml = function(file) {
EmailBuilder.prototype.getStyleTagContent = function(html) {
var $ = cheerio.load(html);
var styleTags = $('style');
var ignoreStyles = '';
var conditionalStyles = '';
var $this;
var html = this.grunt.file.read(file),
$ = cheerio.load(html),
styleTags = $('style'),
linkTags = $('link'),
ignoreStyles = '',
conditionals = '',
_self = this;
// Grab styles from style tags with data-ignore attr
styleTags.each(function(){
var $this = $(this);
$this = $(this);
if($this.attr('data-ignore')){
ignoreStyles += $this.text();
$this.remove();
} else {
conditionalStyles += $this.text();
}
});
});
// Reset base to file path
this.grunt.file.setBase(path.dirname(file));
return {
ignoreStyles: ignoreStyles,
conditionalStyles: conditionalStyles
};
};
/**
* Get styles from link tag path
*
* @param {String} html
*
* @returns {String} an object whose properties contain styles from data-ignore being set
* or styles within conditional comments
*/
EmailBuilder.prototype.getLinkTagContent = function(html) {
var $ = cheerio.load(html);
var linkTags = $('link');
var _self = this;
var ignoreStyles = '';
var conditionalStyles = '';
var $this, href, pathExists;
// Grab styles from links with data-ignore attr
linkTags.each(function(){
var $this = $(this);
$this = $(this);
href = $this.attr('href');
pathExists = _self.grunt.file.exists(path.resolve(process.cwd(), href));
if(pathExists){
if($this.attr('data-ignore')){
ignoreStyles += _self.grunt.file.read(href);
} else {
conditionalStyles += _self.grunt.file.read(href);
}
}
if($this.attr('data-ignore')){
var href = $this.attr('href');
ignoreStyles += _self.grunt.file.read(href);
$this.remove();
}
});
return {
ignoreStyles: ignoreStyles,
conditionalStyles: conditionalStyles
};
};
/**
* Remove any link tags whose href path does not exist
*
* @param {String} html
*
* @returns {String} new html
*/
EmailBuilder.prototype.removeNonLinks = function(html) {
var $ = cheerio.load(html);
var linkTags = $('link');
var _self = this;
var linkTag;
linkTags.each(function(){
$this = $(this);
href = $this.attr('href');
pathExists = _self.grunt.file.exists(path.resolve(process.cwd(), href));
if(!pathExists){
linkTag = new RegExp('<link.*'+ href +'[^>]+>', 'g');
html = html.replace(linkTag, '');
}
});
html = this.handleConditionals($.html());
return html;
};
/**
* Transform html to be inlined by extracting and removing any data-ignore styles
*
* @param {String} file - src file to read
*
* @returns {Object} ignoreStyles - styles from style tags/links that have data-ignore attribute
* @returns {Object} html - the new html with any style tags/links
*/
EmailBuilder.prototype.transformHtml = function(file) {
var html = this.grunt.file.read(file);
var $ = cheerio.load(html);
var ignoreStyles = '';
var _self = this;
// Reset base to file path
this.grunt.file.setBase(path.dirname(file));
ignoreStyles += this.getStyleTagContent(html).ignoreStyles;
ignoreStyles += this.getLinkTagContent(html).ignoreStyles;
html = this.addStylesToConditionals($.html());
// If we don't remove links whose paths do not exist then the css
// will not get inlined due to a bug in juice
html = this.removeNonLinks(html);
// Reset base to default
this.grunt.file.setBase(this.basepath);
return {

@@ -155,13 +274,14 @@ ignoreStyles: ignoreStyles,

var slashes = os.platform() === 'win32' ? '\\\\' : '//',
url = "file:" + slashes + path.join(this.basepath, src),
prepHtml = this.prepareHtml(src);
var slashes = os.platform() === 'win32' ? '\\\\' : '//';
var url = "file:" + slashes + path.join(this.basepath, src);
var transformHtml = this.transformHtml(src);
this.options.url = url;
return juice.juiceContentAsync(prepHtml.html, this.options)
return juice.juiceContentAsync(transformHtml.html, this.options)
.bind(this)
.then(function(html){
html = html.replace(/(<\/head>)/gi, '<style type="text/css">' + prepHtml.ignoreStyles + '</style>$1');
html = html.replace(/(<\/head>)/gi, '<style type="text/css">' + transformHtml.ignoreStyles + '</style>$1');
if(this.options.encodeSpecialChars) { html = encode.htmlEncode(html); }

@@ -178,2 +298,3 @@

/**

@@ -200,2 +321,3 @@ * Write final html output to file

/**

@@ -213,9 +335,9 @@ * Send tests to Litmus App

if(this.options.litmus){
var litmus = new Litmus(this.options.litmus),
date = this.task.grunt.template.today('yyyy-mm-dd'),
subject = this.options.litmus.subject,
$ = cheerio.load(html),
$title = $('title').text().trim(),
files = this.task.filesSrc,
titleDups = {};
var litmus = new Litmus(this.options.litmus);
var date = this.task.grunt.template.today('yyyy-mm-dd');
var subject = this.options.litmus.subject;
var $ = cheerio.load(html);
var $title = $('title').text().trim();
var files = this.task.filesSrc;
var titleDups = {};

@@ -269,7 +391,6 @@ if( (subject === undefined) || (subject.trim().length === 0) ){

var emailTest = this.options.emailTest,
transportType = emailTest.transport ? emailTest.transport.type : false,
transportOpts = emailTest.transport ? emailTest.transport.options : false,
transport = mailer.createTransport(transportType, transportOpts);
var emailTest = this.options.emailTest;
var transportType = emailTest.transport ? emailTest.transport.type : false;
var transportOpts = emailTest.transport ? emailTest.transport.options : false;
var transport = mailer.createTransport(transportType, transportOpts);
var mailOptions = {

@@ -352,11 +473,10 @@ from: emailTest.email,

grunt.registerMultiTask(EmailBuilder.taskName, EmailBuilder.taskDescription, function() {
this.grunt = grunt;
var done = this.async();
var task = new EmailBuilder(this);
var done = this.async();
var task = new EmailBuilder(this);
task.run()
.done(done);
});

@@ -363,0 +483,0 @@ };

@@ -206,13 +206,10 @@ var mailer = require('nodemailer'),

Litmus.prototype.getBuiltXml = function(html, title) {
var xmlApplications = builder.create('applications').att('type', 'array');
var xml = builder.create('test_set').ele('applications').att('type', 'array');
_.each(this.options.applications, function(app) {
var item = xmlApplications.ele('application');
item.ele('code', app);
xml = xml.ele('application').ele('code', app).up().up();
});
//Build Xml to send off, Join with Application XMl
var xml = builder.create('test_set')
.importXMLBuilder(xmlApplications)
xml = xml.up()
.ele('save_defaults', 'false').up()

@@ -219,0 +216,0 @@ .ele('use_defaults', 'false').up()

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

About

Packages

Stay in touch

Get open source security insights delivered straight into your inbox.

  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc

U.S. Patent No. 12,346,443 & 12,314,394. Other pending.