Skip to content

Commit

Permalink
HTML helpers refactor - issue TryGhost#246 items 2 and 5.
Browse files Browse the repository at this point in the history
- moved template logic out of individual helpers and into Ghost
- simplified template-driven helpers into closures which maintain the context of handlebars
- with handlebars context we have access to data, so don't need to pass data in
- check data to test that it is a simple object and not a function
- moved helpers back into index.js
- provided tests for both template functions in ghost and the nav helper so we are back to where we were
  • Loading branch information
ErisDS committed Jul 11, 2013
1 parent 017c17c commit a263624
Show file tree
Hide file tree
Showing 8 changed files with 162 additions and 169 deletions.
42 changes: 37 additions & 5 deletions core/frontend/helpers/index.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
var _ = require('underscore'),
moment = require('moment'),
when = require('when'),
pagination = require('./paginate'),
navHelper = require('./navigation'),
hbs = require('express-hbs'),
errors = require('../../shared/errorHandling'),
coreHelpers;

coreHelpers = function (ghost) {
var navHelper,
paginationHelper;

/**
* [ description]
* @todo ghost core helpers + a way for themes to register them
Expand Down Expand Up @@ -119,10 +121,40 @@ coreHelpers = function (ghost) {
}
return ret;
});
// Just one async helper for now, but could be more in the future

// ## Template driven helpers
// Template driven helpers require that their template is loaded before they can be registered.

// ###Nav Helper
// `{{nav}}`
// Outputs a navigation menu built from items in config.js
navHelper = ghost.loadTemplate('nav').then(function (templateFn) {
ghost.registerThemeHelper('nav', function (options) {
if (!_.isObject(this.navItems) || _.isFunction(this.navItems)) {
errors.logAndThrowError('navItems data is not an object or is a function');
return;
}
return new hbs.handlebars.SafeString(templateFn({links: this.navItems}));
});
});

// ### Pagination Helper
// `{{paginate}}`
// Outputs previous and next buttons, along with info about the current page
paginationHelper = ghost.loadTemplate('pagination').then(function (templateFn) {
ghost.registerThemeHelper('paginate', function (options) {
if (!_.isObject(this.pagination) || _.isFunction(this.pagination)) {
errors.logAndThrowError('pagination data is not an object or is a function');
return;
}
return new hbs.handlebars.SafeString(templateFn(this.pagination));
});
});

// Return once the template-driven helpers have loaded
return when.join(
navHelper.registerWithGhost(ghost),
pagination.registerWithGhost(ghost)
navHelper,
paginationHelper
);
};

Expand Down
46 changes: 0 additions & 46 deletions core/frontend/helpers/navigation.js

This file was deleted.

45 changes: 0 additions & 45 deletions core/frontend/helpers/paginate.js

This file was deleted.

17 changes: 17 additions & 0 deletions core/ghost.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,10 @@ var config = require('./../config'),
when = require('when'),
express = require('express'),
errors = require('../core/shared/errorHandling'),
fs = require('fs'),
path = require('path'),
hbs = require('express-hbs'),
nodefn = require('when/node/function'),
_ = require('underscore'),
Polyglot = require('node-polyglot'),

Expand Down Expand Up @@ -167,6 +169,21 @@ Ghost.prototype.updateSettingsCache = function (settings) {
}
};

// ## Template utils

Ghost.prototype.compileTemplate = function (templatePath) {
return nodefn.call(fs.readFile, templatePath).then(function (templateContents) {
return hbs.handlebars.compile(templateContents.toString());
}, errors.logAndThrowError);
};

Ghost.prototype.loadTemplate = function (name) {
// TODO: allow themes to override these templates
var templatePath = path.join(this.paths().frontendViews, name + '.hbs');

return this.compileTemplate(templatePath);
};

/**
* @param {string} name
* @param {Function} fn
Expand Down
1 change: 1 addition & 0 deletions core/test/ghost/fixtures/test.hbs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<h1>HelloWorld</h1>
55 changes: 55 additions & 0 deletions core/test/ghost/frontend_helpers_index_spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/*globals describe, beforeEach, it*/
var should = require('should'),
sinon = require('sinon'),
when = require('when'),
_ = require('underscore'),
handlebars = require('express-hbs').handlebars,
path = require('path'),
helpers = require('../../frontend/helpers'),
Ghost = require('../../ghost');

describe('Core Helpers', function () {

var ghost;

beforeEach(function () {
ghost = new Ghost();
});


describe('Navigation Helper', function () {

it('can render nav items', function (done) {
var templateSpy = sinon.spy(function (data) { return "rendered " + data.links.length; }),
compileSpy = sinon.stub(ghost, 'compileTemplate').returns(when.resolve(templateSpy)),
fakeNavItems = [{
title: 'test1',
url: '/test1'
}, {
title: 'test2',
url: '/test2'
}],
rendered;

helpers.loadCoreHelpers(ghost).then(function () {

should.exist(handlebars.helpers.nav);

rendered = handlebars.helpers.nav.call({navItems: fakeNavItems});

// Returns a string returned from navTemplateFunc
should.exist(rendered);
rendered.string.should.equal("rendered 2");

compileSpy.called.should.equal(true);
templateSpy.called.should.equal(true);
templateSpy.calledWith({ links: fakeNavItems }).should.equal(true);


compileSpy.restore();

done();
}, done);
});
});
});
65 changes: 0 additions & 65 deletions core/test/ghost/frontend_helpers_navigation_spec.js

This file was deleted.

Loading

0 comments on commit a263624

Please sign in to comment.