Skip to content

Commit

Permalink
Implements is-helper
Browse files Browse the repository at this point in the history
closes #2249
- Added context to res.locals
- Added context aware is helper
- Added unit tests
  • Loading branch information
halfdan committed Sep 23, 2014
1 parent 438444d commit aa5cf6e
Show file tree
Hide file tree
Showing 4 changed files with 179 additions and 9 deletions.
41 changes: 39 additions & 2 deletions core/server/controllers/frontend.js
Expand Up @@ -88,6 +88,35 @@ function handleError(next) {
};
}

function setResponseContext(req, res, data) {
var contexts = [],
pageParam = req.params.page !== undefined ? parseInt(req.params.page, 10) : 1;

// paged context
if (!isNaN(pageParam) && pageParam > 1) {
contexts.push('paged');
}

if (req.route.path === '/page/:page/') {
contexts.push('index');
} else if (req.route.path === '/') {
contexts.push('home');
contexts.push('index');
} else if (/\/rss\/(:page\/)?$/.test(req.route.path)) {
contexts.push('rss');
} else if (/^\/tag\//.test(req.route.path)) {
contexts.push('tag');
} else if (/^\/author\//.test(req.route.path)) {
contexts.push('author');
} else if (data && data.post && data.post.page) {
contexts.push('page');
} else {
contexts.push('post');
}

res.locals.context = contexts;
}

// Add Request context parameter to the data object
// to be passed down to the templates
function setReqCtx(req, data) {
Expand Down Expand Up @@ -146,6 +175,7 @@ frontendControllers = {
view = 'index';
}

setResponseContext(req, res);
res.render(view, formatPageResponse(posts, page));
});
});
Expand Down Expand Up @@ -200,6 +230,7 @@ frontendControllers = {
if (!result.tag) {
return next();
}
setResponseContext(req, res);
res.render(view, result);
});
});
Expand Down Expand Up @@ -254,6 +285,8 @@ frontendControllers = {
if (!result.author) {
return next();
}

setResponseContext(req, res);
res.render(view, result);
});
});
Expand Down Expand Up @@ -325,9 +358,12 @@ frontendControllers = {

filters.doFilter('prePostsRender', post).then(function (post) {
getActiveThemePaths().then(function (paths) {
var view = template.getThemeViewForPost(paths, post);
var view = template.getThemeViewForPost(paths, post),
response = formatResponse(post);

setResponseContext(req, res, response);

res.render(view, formatResponse(post));
res.render(view, response);
});
});
}
Expand Down Expand Up @@ -470,6 +506,7 @@ frontendControllers = {
}

setReqCtx(req, page.posts);
setResponseContext(req, res);

filters.doFilter('prePostsRender', page.posts).then(function (posts) {
posts.forEach(function (post) {
Expand Down
30 changes: 30 additions & 0 deletions core/server/helpers/index.js
Expand Up @@ -677,6 +677,34 @@ coreHelpers.foreach = function (context, options) {
return ret;
};

// ### Is Helper
// `{{#is "paged"}}`
// `{{#is "index, paged"}}`
// Checks whether we're in a given context.
coreHelpers.is = function (context, options) {
options = options || {};

var currentContext = options.data.root.context;

if (!_.isString(context)) {
errors.logWarn('Invalid or no attribute given to is helper');
return;
}

function evaluateContext(expr) {
return expr.split(',').map(function (v) {
return v.trim();
}).reduce(function (p, c) {
return p || _.contains(currentContext, c);
}, false);
}

if (evaluateContext(context)) {
return options.fn(this);
}
return options.inverse(this);
};

// ### Has Helper
// `{{#has tag="video, music"}}`
// `{{#has author="sam, pat"}}`
Expand Down Expand Up @@ -855,6 +883,8 @@ registerHelpers = function (adminHbs, assetHash) {

registerThemeHelper('foreach', coreHelpers.foreach);

registerThemeHelper('is', coreHelpers.is);

registerThemeHelper('has', coreHelpers.has);

registerThemeHelper('page_url', coreHelpers.page_url);
Expand Down
68 changes: 61 additions & 7 deletions core/test/unit/frontend_spec.js
Expand Up @@ -202,6 +202,7 @@ describe('Frontend Controller', function () {
route: {}
},
res = {
locals: {},
render: function (view) {
assert.equal(view, 'home');
done();
Expand All @@ -220,6 +221,7 @@ describe('Frontend Controller', function () {
route: {}
},
res = {
locals: {},
render: function (view) {
assert.equal(view, 'index');
done();
Expand Down Expand Up @@ -251,6 +253,7 @@ describe('Frontend Controller', function () {
route: {}
},
res = {
locals: {},
render: function (view) {
assert.equal(view, 'index');
done();
Expand Down Expand Up @@ -360,9 +363,13 @@ describe('Frontend Controller', function () {
it('it will render custom tag template if it exists', function (done) {
var req = {
path: '/tag/' + mockTags[0].slug,
params: {}
params: {},
route: {
path: '/tag/:slug'
}
},
res = {
locals: {},
render: function (view, context) {
assert.equal(view, 'tag');
assert.equal(context.tag, mockTags[0]);
Expand Down Expand Up @@ -576,9 +583,14 @@ describe('Frontend Controller', function () {

it('it will render custom page template if it exists', function (done) {
var req = {
path: '/' + mockPosts[2].posts[0].slug
path: '/' + mockPosts[2].posts[0].slug,
route: {
path: '*'
},
params: {}
},
res = {
locals: {},
render: function (view, context) {
assert.equal(view, 'page-' + mockPosts[2].posts[0].slug);
assert.equal(context.post, mockPosts[2].posts[0]);
Expand All @@ -601,9 +613,14 @@ describe('Frontend Controller', function () {

it('will render static page via /:slug', function (done) {
var req = {
path: '/' + mockPosts[0].posts[0].slug
path: '/' + mockPosts[0].posts[0].slug,
route: {
path: '*'
},
params: {}
},
res = {
locals: {},
render: function (view, context) {
assert.equal(view, 'page');
assert.equal(context.post, mockPosts[0].posts[0]);
Expand All @@ -620,6 +637,7 @@ describe('Frontend Controller', function () {
path: '/' + ['2012/12/30', mockPosts[0].posts[0].slug].join('/')
},
res = {
locals: {},
render: sinon.spy()
};

Expand All @@ -634,6 +652,7 @@ describe('Frontend Controller', function () {
path: '/' + [mockPosts[0].posts[0].slug, 'edit'].join('/')
},
res = {
locals: {},
render: sinon.spy(),
redirect: function (arg) {
res.render.called.should.be.false;
Expand All @@ -650,6 +669,7 @@ describe('Frontend Controller', function () {
path: '/' + ['2012/12/30', mockPosts[0].posts[0].slug, 'edit'].join('/')
},
res = {
locals: {},
render: sinon.spy(),
redirect: sinon.spy()
};
Expand All @@ -673,9 +693,14 @@ describe('Frontend Controller', function () {

it('will render static page via /:slug', function (done) {
var req = {
path: '/' + mockPosts[0].posts[0].slug
path: '/' + mockPosts[0].posts[0].slug,
route: {
path: '*'
},
params: {}
},
res = {
locals: {},
render: function (view, context) {
assert.equal(view, 'page');
assert.equal(context.post, mockPosts[0].posts[0]);
Expand Down Expand Up @@ -705,6 +730,7 @@ describe('Frontend Controller', function () {
path: '/' + [mockPosts[0].posts[0].slug, 'edit'].join('/')
},
res = {
locals: {},
render: sinon.spy(),
redirect: function (arg) {
res.render.called.should.be.false;
Expand All @@ -721,6 +747,7 @@ describe('Frontend Controller', function () {
path: '/' + ['2012/12/30', mockPosts[0].posts[0].slug, 'edit'].join('/')
},
res = {
locals: {},
render: sinon.spy(),
redirect: sinon.spy()
};
Expand All @@ -746,9 +773,14 @@ describe('Frontend Controller', function () {

it('will render post via /:slug', function (done) {
var req = {
path: '/' + mockPosts[1].posts[0].slug
path: '/' + mockPosts[1].posts[0].slug,
route: {
path: '*'
},
params: {}
},
res = {
locals: {},
render: function (view, context) {
assert.equal(view, 'post');
assert(context.post, 'Context object has post attribute');
Expand All @@ -766,6 +798,7 @@ describe('Frontend Controller', function () {
path: '/' + ['2012/12/30', mockPosts[1].posts[0].slug].join('/')
},
res = {
locals: {},
render: sinon.spy()
};

Expand All @@ -781,6 +814,7 @@ describe('Frontend Controller', function () {
path: '/' + [mockPosts[1].posts[0].slug, 'edit'].join('/')
},
res = {
locals: {},
render: sinon.spy(),
redirect: function (arg) {
res.render.called.should.be.false;
Expand All @@ -797,6 +831,7 @@ describe('Frontend Controller', function () {
path: '/' + ['2012/12/30', mockPosts[1].posts[0].slug, 'edit'].join('/')
},
res = {
locals: {},
render: sinon.spy(),
redirect: sinon.spy()
};
Expand All @@ -821,9 +856,14 @@ describe('Frontend Controller', function () {
it('will render post via /YYYY/MM/DD/:slug', function (done) {
var date = moment(mockPosts[1].posts[0].published_at).format('YYYY/MM/DD'),
req = {
path: '/' + [date, mockPosts[1].posts[0].slug].join('/')
path: '/' + [date, mockPosts[1].posts[0].slug].join('/'),
route: {
path: '*'
},
params: {}
},
res = {
locals: {},
render: function (view, context) {
assert.equal(view, 'post');
assert(context.post, 'Context object has post attribute');
Expand All @@ -842,6 +882,7 @@ describe('Frontend Controller', function () {
path: '/' + [date, mockPosts[1].posts[0].slug].join('/')
},
res = {
locals: {},
render: sinon.spy()
};

Expand All @@ -856,6 +897,7 @@ describe('Frontend Controller', function () {
path: '/' + mockPosts[1].posts[0].slug
},
res = {
locals: {},
render: sinon.spy()
};

Expand All @@ -872,6 +914,7 @@ describe('Frontend Controller', function () {
path: '/' + [dateFormat, mockPosts[1].posts[0].slug, 'edit'].join('/')
},
res = {
locals: {},
render: sinon.spy(),
redirect: function (arg) {
res.render.called.should.be.false;
Expand All @@ -888,6 +931,7 @@ describe('Frontend Controller', function () {
path: '/' + [mockPosts[1].posts[0].slug, 'edit'].join('/')
},
res = {
locals: {},
render: sinon.spy(),
redirect: sinon.spy()
};
Expand All @@ -912,9 +956,14 @@ describe('Frontend Controller', function () {
it('will render post via /:year/:slug', function (done) {
var date = moment(mockPosts[1].posts[0].published_at).format('YYYY'),
req = {
path: '/' + [date, mockPosts[1].posts[0].slug].join('/')
path: '/' + [date, mockPosts[1].posts[0].slug].join('/'),
route: {
path: '*'
},
params: {}
},
res = {
locals: {},
render: function (view, context) {
assert.equal(view, 'post');
assert(context.post, 'Context object has post attribute');
Expand All @@ -933,6 +982,7 @@ describe('Frontend Controller', function () {
path: '/' + [date, mockPosts[1].posts[0].slug].join('/')
},
res = {
locals: {},
render: sinon.spy()
};

Expand All @@ -948,6 +998,7 @@ describe('Frontend Controller', function () {
path: '/' + [date, mockPosts[1].posts[0].slug].join('/')
},
res = {
locals: {},
render: sinon.spy()
};

Expand All @@ -962,6 +1013,7 @@ describe('Frontend Controller', function () {
path: '/' + mockPosts[1].posts[0].slug
},
res = {
locals: {},
render: sinon.spy()
};

Expand All @@ -978,6 +1030,7 @@ describe('Frontend Controller', function () {
path: '/' + [date, mockPosts[1].posts[0].slug, 'edit'].join('/')
},
res = {
locals: {},
render: sinon.spy(),
redirect: function (arg) {
res.render.called.should.be.false;
Expand All @@ -994,6 +1047,7 @@ describe('Frontend Controller', function () {
path: '/' + [mockPosts[1].posts[0].slug, 'edit'].join('/')
},
res = {
locals: {},
render: sinon.spy(),
redirect: sinon.spy()
};
Expand Down

0 comments on commit aa5cf6e

Please sign in to comment.