diff --git a/lib/__tests__/fixtures/render/data-header.html b/lib/__tests__/fixtures/render/data-header.html new file mode 100644 index 0000000..cb3cf85 --- /dev/null +++ b/lib/__tests__/fixtures/render/data-header.html @@ -0,0 +1,4 @@ +--- +name: John doe +--- +

Hallo {{name}}

diff --git a/lib/__tests__/fixtures/render/layouts/default.html b/lib/__tests__/fixtures/render/layouts/default.html new file mode 100644 index 0000000..4d711ca --- /dev/null +++ b/lib/__tests__/fixtures/render/layouts/default.html @@ -0,0 +1,10 @@ + + + + + {{title}} + + +{{> body}} + + diff --git a/lib/__tests__/render.test.js b/lib/__tests__/render.test.js index 48be786..31a397c 100644 --- a/lib/__tests__/render.test.js +++ b/lib/__tests__/render.test.js @@ -1,8 +1,21 @@ const _ = require('lodash'); +const handlebars = require('handlebars'); +const cheerio = require('cheerio'); +const path = require('path'); +const fs = require('fs'); + const render = require('../render'); +const loadLayouts = require('../loadLayouts'); + +function Engine() { + this.layouts = {}; + this.Handlebars = handlebars; +} + +Engine.prototype.render = render.render; describe('render', () => { - describe('loadFiles', () => { + describe('_renderInky', () => { it('should display an empty array by not found files', () => { const content = '

Hello Wold

'; const buildContent = render._renderInky(content); @@ -21,4 +34,113 @@ describe('render', () => { return expect(buildContent).resolves.toEqual(_.trim(output)); }); }); + + describe('render', () => { + it('should render with out of data', () => { + const engine = new Engine(); + const input = '

Hallo!

'; + + const _render = engine.render(input); + + return expect( + _render.then(html => { + const $ = cheerio.load(html); + return $('h1').html(); + }) + ).resolves.toEqual('Hallo!'); + }); + + it('should render with hbs data', () => { + const engine = new Engine(); + const input = '

Hallo {{name}}

'; + const data = { name: 'John' }; + + const _render = engine.render(input, data); + + return expect( + _render.then(html => { + const $ = cheerio.load(html); + return $('h1').html(); + }) + ).resolves.toEqual('Hallo John'); + }); + + it('should render with data from file header', () => { + const engine = new Engine(); + const input = fs.readFileSync( + path.join(__dirname, 'fixtures/render/data-header.html') + ); + const data = { name: 'John' }; + + const _render = engine.render(input, data); + + return expect( + _render.then(html => { + const $ = cheerio.load(html); + return $('h1').html(); + }) + ).resolves.toEqual('Hallo John doe'); + }); + + it('should render with Inky html tag', () => { + const engine = new Engine(); + const input = ''; + const data = { name: 'John' }; + + const _render = engine.render(input, data); + + return expect( + _render.then(html => { + console.log(html); + const $ = cheerio.load(html); + return $('a').html(); + }) + ).resolves.toEqual('Click Me'); + }); + + it('should render with default', () => { + function Engine() { + this.layouts = {}; + this.Handlebars = handlebars; + + this.loadLayouts(path.join(__dirname, 'fixtures/render/layouts')); + } + + Engine.prototype.render = render.render; + Engine.prototype.loadLayouts = loadLayouts; + + const engine = new Engine(); + const input = '

Hallo {{name}}

'; + const data = { + name: 'John', + title: 'This is a page title', + layout: 'default' + }; + + const _render = engine.render(input, data); + + expect( + _render.then(html => { + const $ = cheerio.load(html); + console.log(); + return $('title').html(); + }) + ).resolves.toEqual('This is a page title'); + + expect( + _render.then(html => { + const $ = cheerio.load(html); + console.log(); + return $('html').length; + }) + ).resolves.toEqual(1); + + return expect( + _render.then(html => { + const $ = cheerio.load(html); + return $('body h1').html(); + }) + ).resolves.toEqual('Hallo John'); + }); + }); }); diff --git a/lib/render.js b/lib/render.js index 1399a30..856447a 100644 --- a/lib/render.js +++ b/lib/render.js @@ -3,9 +3,17 @@ const Promise = require('bluebird'); const Inky = require('inky').Inky; const cheerio = require('cheerio'); +const _ = require('lodash'); +const stripBom = require('strip-bom'); +const fm = require('front-matter'); const utils = require('./utils'); +/** + * Render all Inky HTML tags + * @param {string} htmlContent + * @private + */ const _renderInky = function(htmlContent) { return new Promise(resolve => { if (!utils.hasInkyCode(htmlContent)) return resolve(htmlContent); @@ -17,6 +25,32 @@ const _renderInky = function(htmlContent) { }); }; +/** + * A final render function and combined Handlebars and Inky rendering + * @param {string} html + * @param {object} options + * @return {PromiseLike} + */ +const render = function(html, options = {}) { + const engine = this.Handlebars; + const page = fm(stripBom(_.toString(html))); + const layout = page.attributes.layout || 'default'; + const layoutTemplate = this.layouts[layout]; + const date = _.merge(options, page.attributes); + + return Promise.resolve() + .then(() => _renderInky(page.body)) + .then(content => { + const pageTemplate = engine.compile(content + '\n'); + if (!_.isUndefined(layoutTemplate)) { + engine.registerPartial('body', pageTemplate); + return layoutTemplate(date); + } + return pageTemplate(date); + }); +}; + module.exports = { - _renderInky + _renderInky, + render }; diff --git a/package-lock.json b/package-lock.json index fff4b2d..404178e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -480,7 +480,6 @@ "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dev": true, "requires": { "sprintf-js": "~1.0.2" } @@ -2022,8 +2021,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.0.tgz", "integrity": - "sha512-oftTcaMu/EGrEIu904mWteKIv8vMuOgGYo7EhVJJN00R/EED9DCua/xxHRdYnKtcECzVg7xOWhflvJMnqcFZjw==", - "dev": true + "sha512-oftTcaMu/EGrEIu904mWteKIv8vMuOgGYo7EhVJJN00R/EED9DCua/xxHRdYnKtcECzVg7xOWhflvJMnqcFZjw==" }, "esquery": { "version": "1.0.1", @@ -2354,6 +2352,14 @@ "map-cache": "^0.2.2" } }, + "front-matter": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/front-matter/-/front-matter-2.3.0.tgz", + "integrity": "sha1-cgOviWzjV+4E4qpFFp6pHtf2dQQ=", + "requires": { + "js-yaml": "^3.10.0" + } + }, "fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", @@ -4434,7 +4440,6 @@ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.11.0.tgz", "integrity": "sha512-saJstZWv7oNeOyBh3+Dx1qWzhW0+e6/8eDzo7p5rDFqxntSztloLtuKu+Ejhtq82jsilwOIZYsCz+lIjthg1Hw==", - "dev": true, "requires": { "argparse": "^1.0.7", "esprima": "^4.0.0" @@ -7231,8 +7236,7 @@ "sprintf-js": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", - "dev": true + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=" }, "sshpk": { "version": "1.14.1", diff --git a/package.json b/package.json index 953778c..b1118cf 100644 --- a/package.json +++ b/package.json @@ -28,6 +28,7 @@ "dependencies": { "bluebird": "^3.5.1", "cheerio": "^1.0.0-rc.2", + "front-matter": "^2.3.0", "glob": "^7.1.2", "handlebars": "^4.0.11", "inky": "^1.3.7", @@ -48,7 +49,7 @@ "prettier": "^1.11.1" }, "engines": { - "npm": ">= 6.0.0" + "node": ">= 6.0.0" }, "license": "MIT" }