mirror of
https://github.com/TryGhost/Ghost.git
synced 2025-01-20 22:42:53 -05:00
Implements is-helper
closes #2249 - Added context to res.locals - Added context aware is helper - Added unit tests
This commit is contained in:
parent
438444df3d
commit
aa5cf6ed3b
4 changed files with 179 additions and 9 deletions
|
@ -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) {
|
||||
|
@ -146,6 +175,7 @@ frontendControllers = {
|
|||
view = 'index';
|
||||
}
|
||||
|
||||
setResponseContext(req, res);
|
||||
res.render(view, formatPageResponse(posts, page));
|
||||
});
|
||||
});
|
||||
|
@ -200,6 +230,7 @@ frontendControllers = {
|
|||
if (!result.tag) {
|
||||
return next();
|
||||
}
|
||||
setResponseContext(req, res);
|
||||
res.render(view, result);
|
||||
});
|
||||
});
|
||||
|
@ -254,6 +285,8 @@ frontendControllers = {
|
|||
if (!result.author) {
|
||||
return next();
|
||||
}
|
||||
|
||||
setResponseContext(req, res);
|
||||
res.render(view, result);
|
||||
});
|
||||
});
|
||||
|
@ -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);
|
||||
|
||||
res.render(view, formatResponse(post));
|
||||
setResponseContext(req, res, response);
|
||||
|
||||
res.render(view, response);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
@ -470,6 +506,7 @@ frontendControllers = {
|
|||
}
|
||||
|
||||
setReqCtx(req, page.posts);
|
||||
setResponseContext(req, res);
|
||||
|
||||
filters.doFilter('prePostsRender', page.posts).then(function (posts) {
|
||||
posts.forEach(function (post) {
|
||||
|
|
|
@ -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"}}`
|
||||
|
@ -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);
|
||||
|
|
|
@ -202,6 +202,7 @@ describe('Frontend Controller', function () {
|
|||
route: {}
|
||||
},
|
||||
res = {
|
||||
locals: {},
|
||||
render: function (view) {
|
||||
assert.equal(view, 'home');
|
||||
done();
|
||||
|
@ -220,6 +221,7 @@ describe('Frontend Controller', function () {
|
|||
route: {}
|
||||
},
|
||||
res = {
|
||||
locals: {},
|
||||
render: function (view) {
|
||||
assert.equal(view, 'index');
|
||||
done();
|
||||
|
@ -251,6 +253,7 @@ describe('Frontend Controller', function () {
|
|||
route: {}
|
||||
},
|
||||
res = {
|
||||
locals: {},
|
||||
render: function (view) {
|
||||
assert.equal(view, 'index');
|
||||
done();
|
||||
|
@ -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]);
|
||||
|
@ -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]);
|
||||
|
@ -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]);
|
||||
|
@ -620,6 +637,7 @@ describe('Frontend Controller', function () {
|
|||
path: '/' + ['2012/12/30', mockPosts[0].posts[0].slug].join('/')
|
||||
},
|
||||
res = {
|
||||
locals: {},
|
||||
render: sinon.spy()
|
||||
};
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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()
|
||||
};
|
||||
|
@ -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]);
|
||||
|
@ -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;
|
||||
|
@ -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()
|
||||
};
|
||||
|
@ -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');
|
||||
|
@ -766,6 +798,7 @@ describe('Frontend Controller', function () {
|
|||
path: '/' + ['2012/12/30', mockPosts[1].posts[0].slug].join('/')
|
||||
},
|
||||
res = {
|
||||
locals: {},
|
||||
render: sinon.spy()
|
||||
};
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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()
|
||||
};
|
||||
|
@ -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');
|
||||
|
@ -842,6 +882,7 @@ describe('Frontend Controller', function () {
|
|||
path: '/' + [date, mockPosts[1].posts[0].slug].join('/')
|
||||
},
|
||||
res = {
|
||||
locals: {},
|
||||
render: sinon.spy()
|
||||
};
|
||||
|
||||
|
@ -856,6 +897,7 @@ describe('Frontend Controller', function () {
|
|||
path: '/' + mockPosts[1].posts[0].slug
|
||||
},
|
||||
res = {
|
||||
locals: {},
|
||||
render: sinon.spy()
|
||||
};
|
||||
|
||||
|
@ -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;
|
||||
|
@ -888,6 +931,7 @@ describe('Frontend Controller', function () {
|
|||
path: '/' + [mockPosts[1].posts[0].slug, 'edit'].join('/')
|
||||
},
|
||||
res = {
|
||||
locals: {},
|
||||
render: sinon.spy(),
|
||||
redirect: sinon.spy()
|
||||
};
|
||||
|
@ -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');
|
||||
|
@ -933,6 +982,7 @@ describe('Frontend Controller', function () {
|
|||
path: '/' + [date, mockPosts[1].posts[0].slug].join('/')
|
||||
},
|
||||
res = {
|
||||
locals: {},
|
||||
render: sinon.spy()
|
||||
};
|
||||
|
||||
|
@ -948,6 +998,7 @@ describe('Frontend Controller', function () {
|
|||
path: '/' + [date, mockPosts[1].posts[0].slug].join('/')
|
||||
},
|
||||
res = {
|
||||
locals: {},
|
||||
render: sinon.spy()
|
||||
};
|
||||
|
||||
|
@ -962,6 +1013,7 @@ describe('Frontend Controller', function () {
|
|||
path: '/' + mockPosts[1].posts[0].slug
|
||||
},
|
||||
res = {
|
||||
locals: {},
|
||||
render: sinon.spy()
|
||||
};
|
||||
|
||||
|
@ -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;
|
||||
|
@ -994,6 +1047,7 @@ describe('Frontend Controller', function () {
|
|||
path: '/' + [mockPosts[1].posts[0].slug, 'edit'].join('/')
|
||||
},
|
||||
res = {
|
||||
locals: {},
|
||||
render: sinon.spy(),
|
||||
redirect: sinon.spy()
|
||||
};
|
||||
|
|
|
@ -669,6 +669,55 @@ describe('Core Helpers', function () {
|
|||
});
|
||||
});
|
||||
|
||||
describe('is Block Helper', function () {
|
||||
it('has loaded is block helper', function () {
|
||||
should.exist(handlebars.helpers.is);
|
||||
});
|
||||
|
||||
// All positive tests
|
||||
it('should match single context "index"', function () {
|
||||
var fn = sinon.spy(),
|
||||
inverse = sinon.spy();
|
||||
|
||||
helpers.is.call(
|
||||
{},
|
||||
'index',
|
||||
{fn: fn, inverse: inverse, data: {root: {context: ['home', 'index']}}}
|
||||
);
|
||||
|
||||
fn.called.should.be.true;
|
||||
inverse.called.should.be.false;
|
||||
});
|
||||
|
||||
it('should match OR context "index, paged"', function () {
|
||||
var fn = sinon.spy(),
|
||||
inverse = sinon.spy();
|
||||
|
||||
helpers.is.call(
|
||||
{},
|
||||
'index, paged',
|
||||
{fn: fn, inverse: inverse, data: {root: {context: ['tag', 'paged']}}}
|
||||
);
|
||||
|
||||
fn.called.should.be.true;
|
||||
inverse.called.should.be.false;
|
||||
});
|
||||
|
||||
it('should not match "paged"', function () {
|
||||
var fn = sinon.spy(),
|
||||
inverse = sinon.spy();
|
||||
|
||||
helpers.is.call(
|
||||
{},
|
||||
'paged',
|
||||
{fn: fn, inverse: inverse, data: {root: {context: ['index', 'home']}}}
|
||||
);
|
||||
|
||||
fn.called.should.be.false;
|
||||
inverse.called.should.be.true;
|
||||
});
|
||||
});
|
||||
|
||||
describe('has Block Helper', function () {
|
||||
it('has loaded has block helper', function () {
|
||||
should.exist(handlebars.helpers.has);
|
||||
|
|
Loading…
Add table
Reference in a new issue