Skip to content

Commit

Permalink
Add main function
Browse files Browse the repository at this point in the history
  • Loading branch information
snics committed May 26, 2018
1 parent f4d0038 commit e515af2
Show file tree
Hide file tree
Showing 28 changed files with 1,390 additions and 38 deletions.
207 changes: 207 additions & 0 deletions lib/__tests__/effe.test.js
@@ -0,0 +1,207 @@
const Email = require('email-templates');
const path = require('path');
const cheerio = require('cheerio');
const _ = require('lodash');

const engine = require('../index');

const email = new Email({
views: {
root: path.join(__dirname, 'fixtures/effe'),
options: {
extension: 'hbs',
engineSource: engine({
layouts: path.join(__dirname, 'fixtures/handlebars/layouts'),
partials: path.join(__dirname, 'fixtures/handlebars/partials'),
helpers: path.join(__dirname, 'fixtures/handlebars/helpers')
})
}
}
});

describe('Effe', () => {
it('should be render a single file', () => {
expect(
email.render('hbs', { name: 'John' }).then(html => {
const $ = cheerio.load(html, { xmlMode: true });
return $('html').length;
})
).resolves.toEqual(0);

return expect(
email.render('hbs', { name: 'John' }).then(html => {
return _.trim(html);
})
).resolves.toEqual('Hello John!');
});

it('should be render all', () => {
const _renderAll = email.renderAll('all', { name: 'John' });

expect(_renderAll.then(o => _.isObject(o))).resolves.toBe(true);
expect(_renderAll.then(o => Object.keys(o))).resolves.toEqual(
expect.arrayContaining(['subject', 'html', 'text'])
);
expect(_renderAll.then(o => _.trim(o.subject))).resolves.toBe('Hello John!');
expect(
_renderAll.then(o => {
const $ = cheerio.load(o.html, { xmlMode: true });
return $('html').length;
})
).resolves.toBe(1);
expect(
_renderAll.then(o => {
const $ = cheerio.load(o.html, { xmlMode: true });
return $('body p').html();
})
).resolves.toBe('Hello John!');
return expect(_renderAll.then(o => _.trim(o.text))).resolves.toBe('Hello John!');
});

it('should be render with Inky html tag', () => {
const _renderAll = email.renderAll('inky', { name: 'John' });

expect(_renderAll.then(o => _.isObject(o))).resolves.toBe(true);
expect(_renderAll.then(o => Object.keys(o))).resolves.toEqual(
expect.arrayContaining(['subject', 'html', 'text'])
);
expect(_renderAll.then(o => _.trim(o.subject))).resolves.toBe('Hello John!');
expect(
_renderAll.then(o => {
const $ = cheerio.load(o.html, { xmlMode: true });
return $('body table.wrapper').length;
})
).resolves.toBe(1);
expect(
_renderAll.then(o => {
const $ = cheerio.load(o.html, { xmlMode: true });
return $('table.button').text();
})
).resolves.toBe('Click Me!');
return expect(_renderAll.then(o => _.trim(o.text))).resolves.toBe('Hello John!');
});

it('should be render with header data options', () => {
const _renderAll = email.renderAll('withHeaderData', { name: 'John' });

expect(_renderAll.then(o => _.isObject(o))).resolves.toBe(true);
expect(_renderAll.then(o => Object.keys(o))).resolves.toEqual(
expect.arrayContaining(['subject', 'html', 'text'])
);
expect(_renderAll.then(o => _.trim(o.subject))).resolves.toBe('Hello John!');
expect(
_renderAll.then(o => {
const $ = cheerio.load(o.html, { xmlMode: true });
return $('body table.wrapper').length;
})
).resolves.toBe(1);
expect(
_renderAll.then(o => {
const $ = cheerio.load(o.html, { xmlMode: true });
return $('body table.wrapper p').text();
})
).resolves.toBe('Hello Tim!');
return expect(_renderAll.then(o => _.trim(o.text))).resolves.toBe('Hello John!');
});

it('should be render with helper', () => {
const _renderAll = email.renderAll('withHelpers', { name: 'John' });

expect(_renderAll.then(o => _.isObject(o))).resolves.toBe(true);
expect(_renderAll.then(o => Object.keys(o))).resolves.toEqual(
expect.arrayContaining(['subject', 'html', 'text'])
);
expect(_renderAll.then(o => _.trim(o.subject))).resolves.toBe('Hello John!');
expect(
_renderAll.then(o => {
const $ = cheerio.load(o.html, { xmlMode: true });
return $('body').length;
})
).resolves.toBe(1);
expect(
_renderAll.then(o => {
const $ = cheerio.load(o.html, { xmlMode: true });
return $('body p').html();
})
).resolves.toBe('Hello JOHN!');
return expect(_renderAll.then(o => _.trim(o.text))).resolves.toBe('Hello John!');
});

it('should be render with other layout', () => {
const _renderAll = email.renderAll('withOtherLayout', {
layout: 'test',
name: 'John'
});

expect(_renderAll.then(o => _.isObject(o))).resolves.toBe(true);
expect(_renderAll.then(o => Object.keys(o))).resolves.toEqual(
expect.arrayContaining(['subject', 'html', 'text'])
);
expect(_renderAll.then(o => _.trim(o.subject))).resolves.toBe('Hello John!');
expect(
_renderAll.then(o => {
const $ = cheerio.load(o.html, { xmlMode: true });
return $('body').length;
})
).resolves.toBe(0);
expect(
_renderAll.then(o => {
const $ = cheerio.load(o.html, { xmlMode: true });
return $('div h1').html();
})
).resolves.toBe('This is a other layout');
expect(
_renderAll.then(o => {
const $ = cheerio.load(o.html, { xmlMode: true });
return $('div p').html();
})
).resolves.toBe('Hello John!');
return expect(_renderAll.then(o => _.trim(o.text))).resolves.toBe('Hello John!');
});

it('should be render with other partial', () => {
const _renderAll = email.renderAll('withPartials', { name: 'John' });

expect(_renderAll.then(o => _.isObject(o))).resolves.toBe(true);
expect(_renderAll.then(o => Object.keys(o))).resolves.toEqual(
expect.arrayContaining(['subject', 'html', 'text'])
);
expect(_renderAll.then(o => _.trim(o.subject))).resolves.toBe('Hello John!');
expect(
_renderAll.then(o => {
const $ = cheerio.load(o.html, { xmlMode: true });
return $('body').length;
})
).resolves.toBe(1);
expect(
_renderAll.then(o => {
const $ = cheerio.load(o.html, { xmlMode: true });
return $('p').html();
})
).resolves.toBe('This is a hbs partial');
return expect(_renderAll.then(o => _.trim(o.text))).resolves.toBe('Hello John!');
});

it('should be have no engine options', function() {
const email = new Email({
views: {
root: path.join(__dirname, 'fixtures/effe'),
options: {
extension: 'hbs',
engineSource: engine()
}
}
});

expect(
email.render('hbs', { name: 'John' }).then(html => {
const $ = cheerio.load(html, { xmlMode: true });
return $('html').length;
})
).resolves.toEqual(0);

return expect(
email.render('hbs', { name: 'John' }).then(html => _.trim(html))
).resolves.toEqual('Hello John!');
});
});
1 change: 1 addition & 0 deletions lib/__tests__/fixtures/effe/all/html.hbs
@@ -0,0 +1 @@
<p>Hello {{name}}!</p>
1 change: 1 addition & 0 deletions lib/__tests__/fixtures/effe/all/subject.hbs
@@ -0,0 +1 @@
Hello {{name}}!
1 change: 1 addition & 0 deletions lib/__tests__/fixtures/effe/all/text.hbs
@@ -0,0 +1 @@
Hello {{name}}!
1 change: 1 addition & 0 deletions lib/__tests__/fixtures/effe/hbs/index.hbs
@@ -0,0 +1 @@
Hello {{name}}!
4 changes: 4 additions & 0 deletions lib/__tests__/fixtures/effe/inky/html.hbs
@@ -0,0 +1,4 @@
<wrapper>
<p>Hello {{name}}!</p>
<button href="#">Click Me!</button>
</wrapper>
1 change: 1 addition & 0 deletions lib/__tests__/fixtures/effe/inky/subject.hbs
@@ -0,0 +1 @@
Hello {{name}}!
1 change: 1 addition & 0 deletions lib/__tests__/fixtures/effe/inky/text.hbs
@@ -0,0 +1 @@
Hello {{name}}!
7 changes: 7 additions & 0 deletions lib/__tests__/fixtures/effe/withHeaderData/html.hbs
@@ -0,0 +1,7 @@
---
name: Tim
---

<wrapper>
<p>Hello {{name}}!</p>
</wrapper>
1 change: 1 addition & 0 deletions lib/__tests__/fixtures/effe/withHeaderData/subject.hbs
@@ -0,0 +1 @@
Hello {{name}}!
1 change: 1 addition & 0 deletions lib/__tests__/fixtures/effe/withHeaderData/text.hbs
@@ -0,0 +1 @@
Hello {{name}}!
1 change: 1 addition & 0 deletions lib/__tests__/fixtures/effe/withHelpers/html.hbs
@@ -0,0 +1 @@
<p>Hello {{upcase name}}!</p>
1 change: 1 addition & 0 deletions lib/__tests__/fixtures/effe/withHelpers/subject.hbs
@@ -0,0 +1 @@
Hello {{name}}!
1 change: 1 addition & 0 deletions lib/__tests__/fixtures/effe/withHelpers/text.hbs
@@ -0,0 +1 @@
Hello {{name}}!
1 change: 1 addition & 0 deletions lib/__tests__/fixtures/effe/withOtherLayout/html.hbs
@@ -0,0 +1 @@
<p>Hello {{name}}!</p>
1 change: 1 addition & 0 deletions lib/__tests__/fixtures/effe/withOtherLayout/subject.hbs
@@ -0,0 +1 @@
Hello {{name}}!
1 change: 1 addition & 0 deletions lib/__tests__/fixtures/effe/withOtherLayout/text.hbs
@@ -0,0 +1 @@
Hello {{name}}!
3 changes: 3 additions & 0 deletions lib/__tests__/fixtures/effe/withPartials/html.hbs
@@ -0,0 +1,3 @@
<wrapper>
{{> test}}
</wrapper>
1 change: 1 addition & 0 deletions lib/__tests__/fixtures/effe/withPartials/subject.hbs
@@ -0,0 +1 @@
Hello {{name}}!
1 change: 1 addition & 0 deletions lib/__tests__/fixtures/effe/withPartials/text.hbs
@@ -0,0 +1 @@
Hello {{name}}!
14 changes: 14 additions & 0 deletions lib/__tests__/fixtures/handlebars/helpers/upcase.js
@@ -0,0 +1,14 @@
const _ = require('lodash');
const helpers = module.exports;

helpers.uppercase = function(str) {
if (_.isObject(str) && str.fn) {
return str.fn(this).toUpperCase();
}
if (!_.isString(str)) return '';
return str.toUpperCase();
};

helpers.upcase = function() {
return helpers.uppercase.apply(this, arguments);
};
5 changes: 5 additions & 0 deletions lib/__tests__/fixtures/handlebars/layouts/test.hbs
@@ -0,0 +1,5 @@
<div>
<h1>This is a other layout</h1>

{{> body}}
</div>
1 change: 1 addition & 0 deletions lib/__tests__/fixtures/handlebars/partials/test.hbs
@@ -0,0 +1 @@
<p>This is a hbs partial</p>
29 changes: 29 additions & 0 deletions lib/hbs/layouts/default.html
@@ -0,0 +1,29 @@
{{!-- This is the base layout for your project, and will be used on every page. --}}

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head>
<link rel="stylesheet" type="text/css" href="{{root}}css/app.css">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta name="viewport" content="width=device-width">
<title>{{subject}}</title>
<!-- <style> -->
</head>
<body>
<span class="preheader">{{description}}</span>
<table class="body">
<tr>
<td class="center" align="center" valign="top">
<center>
{{!-- Pages you create in the src/pages/ folder are inserted here when the flattened emails are created. --}}
{{> body}}
</center>
</td>
</tr>
</table>
<!-- prevent Gmail on iOS font size manipulation -->
<div style="display:none; white-space:nowrap; font:15px courier; line-height:0;"> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </div>
</body>
</html>
53 changes: 52 additions & 1 deletion lib/index.js
@@ -1,3 +1,54 @@
'use strict';

module.exports = {};
const path = require('path');
const _ = require('lodash');
const fs = require('fs');

/**
* Initializes an instance of Effe.
* @constructor
* @param {object} options - Configuration options to use.
*/
function Effe(options = {}) {
this.options = options;
this.Handlebars = require('handlebars');
this.layouts = {};

if (this.options.layouts) {
this._loadLayouts([path.join(__dirname, 'hbs/layouts'), this.options.layouts]);
} else {
this._loadLayouts(path.join(__dirname, 'hbs/layouts'));
}
if (this.options.partials) this._loadPartials(this.options.partials);
if (this.options.helpers) this._loadHelpers(this.options.helpers);
}

Effe.prototype._loadLayouts = require('./loadLayouts');
Effe.prototype._loadPartials = require('./loadPartials');
Effe.prototype._loadHelpers = require('./loadHelpers');
Effe.prototype._render = require('./render').render;

/**
* Make the object with the engines
* @param {Object} effe
* @return {Function}
*/
function makeRenderer(effe) {
return function(path, options, cb) {
options.filename = path;
exports.handlebars = {};

fs.readFile(path, function() {
exports.handlebars.render = effe
._render(_.toString(arguments[1]), options)
.then(html => cb(null, html));
});
};
}

module.exports = function(options) {
const effe = new Effe(options);
const handlebars = makeRenderer(effe);

return { handlebars };
};

0 comments on commit e515af2

Please sign in to comment.