Skip to content

Context aware Filters and Helpers

Hannah Wolfe edited this page Apr 8, 2014 · 44 revisions

NOTE: Everything you read in here is a lie. No really, this is merely a draft summary of some open discussions in #2249, #2567 and #2113 do not rely on it.

What does context awareness mean?

Helpers in themes are applied and sometimes only available in certain contexts. The {{has}} helper currently only works in the context of a single post and lets the theme developer ask for a set of tags. Context-aware helpers allow the theme developer to ask for the context in which the current template is being rendered in.

Example: post.hbs and index.hbs can use a _single.hbs partial to render each individual post. Inside the partial it might be necessary to change the output depending on whether the partial is rendered inside index.hbs or post.hbs.

Context in helpers

The {{#is}} block helper provides a means to ask for the current context.

  • {{#is "home"}} -> true if we’re on the homepage, false on any other page
  • {{#is "single"}} -> true if we're on a post or static page
  • {{#is "tag"}} -> true if we’re on a tag page

Lists:

  • {{#is "home-list"}} -> true if we’re on the normal post listing (homepage + paged)
  • {{#is "tag-list"}} -> true if we’re on a tag page (tag + paged)

Special:

  • {{#is "paged"}} -> true if we’re on page 2, 3, etc of the home or tag listings
  • {{#is "list"}} -> true if we’re on any home, tag, or paginated listing page

Context in filters

An app can use filters by providing a callback function. A filter can modify data that is passed to it. In addition to the data, filters also get a second parameter that provides contextual information. The names key contains the list of currently active contexts.

Example 1: Change feed title on paged feed

this.ghost.filters.register('rss.feed', function (data, context) {
    if (_.contains(context.name, 'paged')) {
        // Changes feed title based on context
        data.title = data.title + " archive";
    }

    return data;
});
filters.doFilter('rss.feed', feed, {
    names: ['rss', 'paged'] // Context names
});

Example 2: Add <audio> player when rendering post on frontend

this.ghost.filters.register('post.render', function (html, context) {
    if (_.contains(context.name, 'home-list')) {
        // Fetch app_fields for post.id
        audioFile = appFields.fetch(post.id, 'audioFile');
        html = "<audio>" + audioFile + "</audio>" + html;
    }

    return html;
});
filters.doFilter('post.render', html, {
    names: ['home', 'home-list'],
    post: post
});

Context Table

/ /single-post /page/2 /tag/ghost /tag/ghost/page/2
home x x
single x
tag x x
paged x x
list x x
home-list x x
tag-list x x

Alternative Context Table

| name | url (default) | single | paged | template | body classes (current) | body classes (proposed) [WIP]| context | data | |:---:|:---:|:---:|:---:|:---:|:---:|:---:|:---:|:---:|:---:| | index (home) | / | F | F | index.hbs | home-template | home-template | [index, home] | [{posts}], {pagination} | | index paged| /page/2 | F | T | index.hbs | archive-template | paged | [index, paged] | [{posts}], {pagination} | | single post | /my-post | T | F | post.hbs | post-template, tag-* | post-template, tag-* | [post] | {post} | single page | /my-page | T | F | page-{{slug}}.hbs or page.hbs or post.hbs | post-template, page, tag-* | page-template, tag-* | [post] | {post} | tag | /tag/my-tag/ | F | F | tag.hbs or index.hbs | tag-template, tag-* | tag-template, tag-* | [tag] | [{posts}], {pagination}, {tag} | | tag paged| /tag/my-tag/page/2/ | F | T | tag.hbs or index.hbs | archive-template, tag-template, tag-* | tag-template, tag-*, paged | [tag, paged] | [{posts}], {pagination}, {tag} | | rss | /rss/ | F | F | n/a | n/a | n/a | [rss] | rss feed XML | rss paged| /rss/2/ | F | T | n/a | n/a | n/a | [rss, paged] | rss feed XML | coming in 0.6 | (maybe) | - | - | - | - | - | - | | user | /user/my-user/ | F | F | user.hbs or index.hbs | n/a | user-template, user-* | [user] | [{posts}], {pagination}, {user} | | user paged | /user/my-user/page/2 | F | T | user.hbs or index.hbs | n/a | user-template, user-*, paged | [user, paged] | [{posts}], {pagination}, {user} | | coming in ?? | (maybe) | - | - | - | - | - | - | | users | /users/ | F | F | users.hbs | n/a | | [users] | [{users}], {pagination} | | users paged| /users/page/2/ | F | T | users.hbs | n/a | | [users, paged] | [{users}], {pagination} | | tags | /tags/ | F | F | tags.hbs | n/a | | [tags] | [{tags}], {pagination} | | tags | /tags/page/2 | F | F | tags.hbs | n/a | | [tags, paged] | [{tags}], {pagination} | | archive | /archive/ | F | F | archive.hbs or index.hbs | n/a | | [archive] | [{posts}], {pagination} | | archive paged| /archive/page/2/ | F | F | archive.hbs or index.hbs | n/a | | [archive, paged] | [{posts}], {pagination} |

? - The concept of 'single' vs 'list' breaks down for tag pages as they represent a single tag, but a list of posts... or are